⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sphelper.h

📁 TTS语音开发示例
💻 H
📖 第 1 页 / 共 5 页
字号:
                0xCC, 0x01, 0x30, 0xFF, 0x88, 0x01, 0x18, 0xFF
            };

            static const BYTE Extra44[32] =
            {
                0xF4, 0x07, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00,
                0x00, 0x02, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
                0xC0, 0x00, 0x40, 0x00, 0xF0, 0x00, 0x00, 0x00,
                0xCC, 0x01, 0x30, 0xFF, 0x88, 0x01, 0x18, 0xFF
            };

            static const BYTE* Extra[4] = { Extra811, Extra811, Extra22, Extra44 };
            memset( pwfex, 0, NumBytes );
            DWORD dwIndex  = eFormat - SPSF_ADPCM_8kHzMono;
            DWORD dwKHZ    = dwIndex / 2;
            BOOL bIsStereo = dwIndex & 0x1;
            pwfex->wFormatTag      = WAVE_FORMAT_ADPCM;
            pwfex->nChannels       = (WORD)(bIsStereo ? 2 : 1);
            pwfex->nSamplesPerSec  = adwKHZ[dwKHZ];
            pwfex->nAvgBytesPerSec = BytesPerSec[dwIndex];
            pwfex->nBlockAlign     = (WORD)(BlockAlign[dwKHZ] * pwfex->nChannels);
            pwfex->wBitsPerSample  = 4;
            pwfex->cbSize          = 32;
            BYTE* pExtra = ((BYTE*)pwfex) + sizeof( WAVEFORMATEX );
            memcpy( pExtra, Extra[dwKHZ], 32 );
            pFmtGuid = &SPDFID_WaveFormatEx;
        }
        else
        {
            hr = E_OUTOFMEMORY;
        }
    }
    else if( (eFormat >= SPSF_GSM610_8kHzMono    ) &&
             (eFormat <= SPSF_GSM610_44kHzMono ) )
    {
        int NumBytes = sizeof( WAVEFORMATEX ) + 2;
        WAVEFORMATEX * pwfex = (WAVEFORMATEX *)::CoTaskMemAlloc( NumBytes );
        *ppCoMemWaveFormatEx = pwfex;
        if( pwfex )
        {
            //--- Some of these values seem odd. We used what the codec told us.
            static const DWORD adwKHZ[] = { 8000, 11025, 22050, 44100 };
            static const DWORD BytesPerSec[] = { 1625, 2239, 4478, 8957 };
            memset( pwfex, 0, NumBytes );
            DWORD dwIndex          = eFormat - SPSF_GSM610_8kHzMono;
            pwfex->wFormatTag      = WAVE_FORMAT_GSM610;
            pwfex->nChannels       = 1;
            pwfex->nSamplesPerSec  = adwKHZ[dwIndex];
            pwfex->nAvgBytesPerSec = BytesPerSec[dwIndex];
            pwfex->nBlockAlign     = 65;
            pwfex->wBitsPerSample  = 0;
            pwfex->cbSize          = 2;
            BYTE* pExtra = ((BYTE*)pwfex) + sizeof( WAVEFORMATEX );
            pExtra[0] = 0x40;
            pExtra[1] = 0x01;
            pFmtGuid = &SPDFID_WaveFormatEx;
        }
        else
        {
            hr = E_OUTOFMEMORY;
        }
    }
    else
    {
        *ppCoMemWaveFormatEx = NULL;
        switch (eFormat)
        {
        case SPSF_NoAssignedFormat:
            break;
        case SPSF_Text:
            pFmtGuid = &SPDFID_Text;
            break;
        default:
            hr = E_INVALIDARG;
            break;
        }
    }
    *pFormatId = *pFmtGuid;
    return hr;
}

class CSpStreamFormat
{
public:
    GUID            m_guidFormatId;
    WAVEFORMATEX  * m_pCoMemWaveFormatEx; 


    static int CoMemCopyWFEX(const WAVEFORMATEX * pSrc, WAVEFORMATEX ** ppCoMemWFEX)
    {
        ULONG cb = sizeof(WAVEFORMATEX) + pSrc->cbSize;
        *ppCoMemWFEX = (WAVEFORMATEX *)::CoTaskMemAlloc(cb);
        if (*ppCoMemWFEX)
        {
            memcpy(*ppCoMemWFEX, pSrc, cb);
            return S_OK;
        }
        else
        {
            return E_OUTOFMEMORY;
        }
    }


    CSpStreamFormat()
    {
        m_guidFormatId = GUID_NULL;
        m_pCoMemWaveFormatEx = NULL;
    }

    CSpStreamFormat(SPSTREAMFORMAT eFormat, HRESULT * phr)
    {
        *phr = SpConvertStreamFormatEnum(eFormat, &m_guidFormatId, &m_pCoMemWaveFormatEx);
    }

    CSpStreamFormat(const WAVEFORMATEX * pWaveFormatEx, HRESULT * phr)
    {
        SPDBG_ASSERT(pWaveFormatEx);
        *phr = CoMemCopyWFEX(pWaveFormatEx, &m_pCoMemWaveFormatEx);
        m_guidFormatId = SUCCEEDED(*phr) ? SPDFID_WaveFormatEx : GUID_NULL;
    }

    ~CSpStreamFormat()
    {
        ::CoTaskMemFree(m_pCoMemWaveFormatEx);
    }

    void Clear()
    {
        ::CoTaskMemFree(m_pCoMemWaveFormatEx);
        m_pCoMemWaveFormatEx = NULL;
        memset(&m_guidFormatId, 0, sizeof(m_guidFormatId));
    }

    const GUID & FormatId() const 
    {
        return m_guidFormatId;
    }

    const WAVEFORMATEX * WaveFormatExPtr() const
    {
        return m_pCoMemWaveFormatEx;
    }


    HRESULT AssignFormat(SPSTREAMFORMAT eFormat)
    {
        ::CoTaskMemFree(m_pCoMemWaveFormatEx);    
        return SpConvertStreamFormatEnum(eFormat, &m_guidFormatId, &m_pCoMemWaveFormatEx);
    }

    HRESULT AssignFormat(ISpStreamFormat * pStream)
    {
        ::CoTaskMemFree(m_pCoMemWaveFormatEx);
        m_pCoMemWaveFormatEx = NULL;
        return pStream->GetFormat(&m_guidFormatId, &m_pCoMemWaveFormatEx);
    }

    HRESULT AssignFormat(const WAVEFORMATEX * pWaveFormatEx)
    {
        ::CoTaskMemFree(m_pCoMemWaveFormatEx);
        HRESULT hr = CoMemCopyWFEX(pWaveFormatEx, &m_pCoMemWaveFormatEx);
        m_guidFormatId = SUCCEEDED(hr) ? SPDFID_WaveFormatEx : GUID_NULL;
        return hr;
    }

    HRESULT AssignFormat(REFGUID rguidFormatId, const WAVEFORMATEX * pWaveFormatEx)
    {
        HRESULT hr = S_OK;

        m_guidFormatId = rguidFormatId;
        ::CoTaskMemFree(m_pCoMemWaveFormatEx);
        m_pCoMemWaveFormatEx = NULL;

        if (rguidFormatId == SPDFID_WaveFormatEx)
        {
            if (::IsBadReadPtr(pWaveFormatEx, sizeof(*pWaveFormatEx)))
            {
                hr = E_INVALIDARG;
            }
            else 
            {
                hr = CoMemCopyWFEX(pWaveFormatEx, &m_pCoMemWaveFormatEx);
            }

            if (FAILED(hr))
            {
                m_guidFormatId = GUID_NULL;
            }
        }

        return hr;
    }


    BOOL IsEqual(REFGUID rguidFormatId, const WAVEFORMATEX * pwfex) const
    {
        if (rguidFormatId == m_guidFormatId)
        {
            if (m_pCoMemWaveFormatEx)
            {
                if (pwfex &&
                    pwfex->cbSize == m_pCoMemWaveFormatEx->cbSize &&
                    memcmp(m_pCoMemWaveFormatEx, pwfex, sizeof(WAVEFORMATEX) + pwfex->cbSize) == 0)
                {
                    return TRUE;
                }
            }
            else
            {
                return (pwfex == NULL);
            }
        }
        return FALSE;
    }



    HRESULT ParamValidateAssignFormat(REFGUID rguidFormatId, const WAVEFORMATEX * pWaveFormatEx, BOOL fRequireWaveFormat = FALSE)
    {
        if ((pWaveFormatEx && (::IsBadReadPtr(pWaveFormatEx, sizeof(*pWaveFormatEx)) || rguidFormatId != SPDFID_WaveFormatEx)) ||
            (fRequireWaveFormat && pWaveFormatEx == NULL))
        {
            return E_INVALIDARG;
        }
        return AssignFormat(rguidFormatId, pWaveFormatEx);
    }

    SPSTREAMFORMAT ComputeFormatEnum()
    {
        if (m_guidFormatId == GUID_NULL)
        {
            return SPSF_NoAssignedFormat;
        }
        if (m_guidFormatId == SPDFID_Text)
        {
            return SPSF_Text;
        }
        if (m_guidFormatId != SPDFID_WaveFormatEx)
        {
            return SPSF_NonStandardFormat;
        }
        //
        //  It is a WAVEFORMATEX.  Now determine which type it is and convert.
        //
        DWORD dwIndex = 0;
        switch (m_pCoMemWaveFormatEx->wFormatTag)
        {
          case WAVE_FORMAT_PCM:
          {
            switch (m_pCoMemWaveFormatEx->nChannels)
            {
              case 1:
                break;
              case 2:
                dwIndex |= 1;
                break;
              default:
                return SPSF_ExtendedAudioFormat;
            }

            switch (m_pCoMemWaveFormatEx->wBitsPerSample)
            {
              case 8:
                break;
              case 16:
                dwIndex |= 2;
                break;
              default:
                return SPSF_ExtendedAudioFormat;
            }

            switch (m_pCoMemWaveFormatEx->nSamplesPerSec)
            {
              case 48000:
                dwIndex += 4;   // Fall through
              case 44100:
                dwIndex += 4;   // Fall through
              case 32000:
                dwIndex += 4;   // Fall through
              case 24000:
                dwIndex += 4;   // Fall through
              case 22050:
                dwIndex += 4;   // Fall through
              case 16000:
                dwIndex += 4;   // Fall through
              case 12000:
                dwIndex += 4;   // Fall through
              case 11025:
                dwIndex += 4;   // Fall through
              case 8000:
                break;
              default:
                return SPSF_ExtendedAudioFormat;
            }

            return static_cast<SPSTREAMFORMAT>(SPSF_8kHz8BitMono + dwIndex);
          }

          case WAVE_FORMAT_DSPGROUP_TRUESPEECH:
          {
            return SPSF_TrueSpeech_8kHz1BitMono;
          }

          case WAVE_FORMAT_ALAW: // fall through
          case WAVE_FORMAT_MULAW:
          case WAVE_FORMAT_ADPCM:
          {
            switch (m_pCoMemWaveFormatEx->nChannels)
            {
              case 1:
                break;
              case 2:
                dwIndex |= 1;
                break;
              default:
                return SPSF_ExtendedAudioFormat;
            }

            if(m_pCoMemWaveFormatEx->wFormatTag == WAVE_FORMAT_ADPCM)
            {
                if(m_pCoMemWaveFormatEx->wBitsPerSample != 4)
                {
                    return SPSF_ExtendedAudioFormat;
                }
            }
            else if(m_pCoMemWaveFormatEx->wBitsPerSample != 8)
            {
                return SPSF_ExtendedAudioFormat;
            }

            switch (m_pCoMemWaveFormatEx->nSamplesPerSec)
            {
              case 44100:
                dwIndex += 2;   // Fall through
              case 22050:
                dwIndex += 2;   // Fall through
              case 11025:
                dwIndex += 2;   // Fall through
              case 8000:
                break;
              default:
                return SPSF_ExtendedAudioFormat;
            }

            switch( m_pCoMemWaveFormatEx->wFormatTag )
            {
              case WAVE_FORMAT_ALAW:
                return static_cast<SPSTREAMFORMAT>(SPSF_CCITT_ALaw_8kHzMono + dwIndex);
              case WAVE_FORMAT_MULAW:
                return static_cast<SPSTREAMFORMAT>(SPSF_CCITT_uLaw_8kHzMono + dwIndex);
              case WAVE_FORMAT_ADPCM:
                return static_cast<SPSTREAMFORMAT>(SPSF_ADPCM_8kHzMono + dwIndex);
            }
          }

          case WAVE_FORMAT_GSM610:
          {
            if( m_pCoMemWaveFormatEx->nChannels != 1 )
            {
                return SPSF_ExtendedAudioFormat;
            }

            switch (m_pCoMemWaveFormatEx->nSamplesPerSec)
            {
              case 44100:
                dwIndex = 3;
                break;
              case 22050:
                dwIndex = 2;
                break;
              case 11025:
                dwIndex = 1;
                break;
              case 8000:
                dwIndex = 0;
                break;
              default:
                return SPSF_ExtendedAudioFormat;
            }

            return static_cast<SPSTREAMFORMAT>(SPSF_GSM610_8kHzMono + dwIndex);
          }

          default:
            return SPSF_ExtendedAudioFormat;
            break;
        }
    }

    void DetachTo(CSpStreamFormat & Other)
    {
        ::CoTaskMemFree(Other.m_pCoMemWaveFormatEx);
        Other.m_guidFormatId = m_guidFormatId;
        Other.m_pCoMemWaveFormatEx = m_pCoMemWaveFormatEx;
        m_pCoMemWaveFormatEx = NULL;
        memset(&m_guidFormatId, 0, sizeof(m_guidFormatId));
    }

    void DetachTo(GUID * pFormatId, WAVEFORMATEX ** ppCoMemWaveFormatEx)
    {
        *pFormatId = m_guidFormatId;
        *ppCoMemWaveFormatEx = m_pCoMemWaveFormatEx;
        m_pCoMemWaveFormatEx = NULL;
        memset(&m_guidFormatId, 0, sizeof(m_guidFormatId));
    }

    HRESULT CopyTo(GUID * pFormatId, WAVEFORMATEX ** ppCoMemWFEX) const
    {
        HRESULT hr = S_OK;
        *pFormatId = m_guidFormatId;
        if (m_pCoMemWaveFormatEx)
        {
            hr = CoMemCopyWFEX(m_pCoMemWaveFormatEx, ppCoMemWFEX);
            if (FAILED(hr))
            {
                memset(pFormatId, 0, sizeof(*pFormatId));
            }
        }
        else
        {
            *ppCoMemWFEX = NULL;
        }
        return hr;
    }

    HRESULT CopyTo(CSpStreamFormat & Other) const
    {
        ::CoTaskMemFree(Other.m_pCoMemWaveFormatEx);
        return CopyTo(&Other.m_guidFormatId, &Other.m_pCoMemWaveFormatEx);
    }
    
    HRESULT AssignFormat(const CSpStreamFormat & Src)
    {
        return Src.CopyTo(*this);
    }


    HRESULT ParamValidateCopyTo(GUID * pFormatId, WAVEFORMATEX ** ppCoMemWFEX) const
    {
        if (::IsBadWritePtr(pFormatId, sizeof(*pFormatId)) ||
            ::IsBadWritePtr(ppCoMemWFEX, sizeof(*ppCoMemWFEX)))
        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -