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

📄 sphelper.h

📁 TTS语音开发示例
💻 H
📖 第 1 页 / 共 5 页
字号:
        SPDBG_REPORT_ON_FAIL(hr);
    }

    return hr;
}

inline HRESULT SpCreatePhoneConverter(
    LANGID LangID,
    const WCHAR * pszReqAttribs,
    const WCHAR * pszOptAttribs,
    ISpPhoneConverter ** ppPhoneConverter)
{
    SPDBG_FUNC("SpCreatePhoneConverter");
    HRESULT hr;

    if (LangID == 0)
    {
        hr = E_INVALIDARG;
    }
    else
    {
        CSpDynamicString dstrReqAttribs;
        if (pszReqAttribs)
        {
            dstrReqAttribs = pszReqAttribs;
            dstrReqAttribs.Append(L";");
        }

        WCHAR szLang[MAX_PATH];

        SpHexFromUlong(szLang, LangID);

        WCHAR szLangCondition[MAX_PATH];
        wcscpy(szLangCondition, L"Language=");
        wcscat(szLangCondition, szLang);

        dstrReqAttribs.Append(szLangCondition);

        hr = SpCreateBestObject(SPCAT_PHONECONVERTERS, dstrReqAttribs, pszOptAttribs, ppPhoneConverter);
    }

    if (hr != SPERR_NOT_FOUND)
    {
        SPDBG_REPORT_ON_FAIL(hr);
    }

    return hr;
}

/****************************************************************************
* SpHrFromWin32 *
*---------------*
*   Description:
*       This inline function works around a basic problem with the macro
*   HRESULT_FROM_WIN32.  The macro forces the expresion in ( ) to be evaluated
*   two times.  By using this inline function, the expression will only be
*   evaluated once.
*
*   Returns:
*       HRESULT of converted Win32 error code
*
*****************************************************************************/

inline HRESULT SpHrFromWin32(DWORD dwErr)
{
    return HRESULT_FROM_WIN32(dwErr);
}


/****************************************************************************
* SpHrFromLastWin32Error *
*------------------------*
*   Description:
*       This simple inline function is used to return a converted HRESULT
*   from the Win32 function ::GetLastError.  Note that using HRESULT_FROM_WIN32
*   will evaluate the error code twice so we don't want to use:
*
*       HRESULT_FROM_WIN32(::GetLastError()) 
*
*   since that will call GetLastError twice.
*   On Win98 and WinMe ::GetLastError() returns 0 for some functions (see MSDN).
*   We therefore check for that and return E_FAIL. This function should only be
*   called in an error case since it will always return an error code!
*
*   Returns:
*       HRESULT for ::GetLastError()
*
*****************************************************************************/

inline HRESULT SpHrFromLastWin32Error()
{
    DWORD dw = ::GetLastError();
    return (dw == 0) ? E_FAIL : SpHrFromWin32(dw);
}


/****************************************************************************
* SpGetUserDefaultUILanguage *
*----------------------------*
*   Description:
*       Returns the default user interface language, using a method 
*       appropriate to the platform (Windows 9x, Windows NT, or Windows 2000)
*
*   Returns:
*       Default UI language
*
*****************************************************************************/

inline LANGID SpGetUserDefaultUILanguage(void) 
{
    HRESULT hr = S_OK;
    LANGID wUILang = 0;

    OSVERSIONINFO Osv ;
    Osv.dwOSVersionInfoSize = sizeof(Osv) ;
    if(!GetVersionEx(&Osv)) 
    {
        hr = SpHrFromLastWin32Error();
    }
    // Get the UI language by one of three methods, depending on the system
    else if(Osv.dwPlatformId != VER_PLATFORM_WIN32_NT) 
    {
        // Case 1: Running on Windows 9x. Get the system UI language from registry:
        CHAR szData[32];
        DWORD dwSize = sizeof(szData) ;
        HKEY hKey;

        long lRet = RegOpenKeyEx(
                        HKEY_USERS, 
                        _T(".Default\\Control Panel\\desktop\\ResourceLocale"), 
                        0, 
                        KEY_READ, 
                        &hKey);

#ifdef _WIN32_WCE_BUG_10655
        if (lRet == ERROR_INVALID_PARAMETER)
        {
            lRet = ERROR_FILE_NOT_FOUND;
        }
#endif // _WIN32_WCE_BUG_10655

        hr = SpHrFromWin32(lRet);

        if (SUCCEEDED(hr))
        {
            lRet = RegQueryValueEx(  
                        hKey, 
                        _T(""), 
                        NULL, 
                        NULL, 
                        (BYTE *)szData, 
                        &dwSize);

#ifdef _WIN32_WCE_BUG_10655
            if(lRet == ERROR_INVALID_PARAMETER)
            {
                lRet = ERROR_FILE_NOT_FOUND;
            }
#endif //_WIN32_WCE_BUG_10655

            hr = SpHrFromWin32(lRet); 
            ::RegCloseKey(hKey) ;
        }
        if (SUCCEEDED(hr))
        {
            // Convert string to number
            wUILang = (LANGID) strtol(szData, NULL, 16) ;
        }
    }
    else if (Osv.dwMajorVersion >= 5.0) 
    {
    // Case 2: Running on Windows 2000 or later. Use GetUserDefaultUILanguage to find 
    // the user's prefered UI language


        HMODULE hMKernel32 = ::LoadLibraryW(L"kernel32.dll") ;
        if (hMKernel32 == NULL)
        {
            hr = SpHrFromLastWin32Error();
        }
        else
        {

            LANGID (WINAPI *pfnGetUserDefaultUILanguage) () = 
                (LANGID (WINAPI *)(void)) 
#ifdef _WIN32_WCE
                    GetProcAddress(hMKernel32, L"GetUserDefaultUILanguage") ;
#else
                    GetProcAddress(hMKernel32, "GetUserDefaultUILanguage") ;
#endif

            if(NULL != pfnGetUserDefaultUILanguage) 
            {
                wUILang = pfnGetUserDefaultUILanguage() ;
            }
            else
            {   // GetProcAddress failed
                hr = SpHrFromLastWin32Error();
            }
            ::FreeLibrary(hMKernel32);
        }
    }
    else {
    // Case 3: Running on Windows NT 4.0 or earlier. Get UI language
    // from locale of .default user in registry:
    // HKEY_USERS\.DEFAULT\Control Panel\International\Locale
        
        WCHAR szData[32]   ;
        DWORD dwSize = sizeof(szData) ;
        HKEY hKey          ;

        LONG lRet = RegOpenKeyEx(HKEY_USERS, 
                                    _T(".DEFAULT\\Control Panel\\International"), 
                                    0, 
                                    KEY_READ, 
                                    &hKey);
#ifdef _WIN32_WCE_BUG_10655
            if(lRet == ERROR_INVALID_PARAMETER)
            {
                lRet = ERROR_FILE_NOT_FOUND;
            }
#endif //_WIN32_WCE_BUG_10655

        hr = SpHrFromWin32(lRet);

        if (SUCCEEDED(hr))
        {
            lRet = RegQueryValueEx(  
                        hKey, 
                        _T("Locale"),
                        NULL, 
                        NULL, 
                        (BYTE *)szData, 
                        &dwSize);

#ifdef _WIN32_WCE_BUG_10655
            if(lRet == ERROR_INVALID_PARAMETER)
            {
                lRet = ERROR_FILE_NOT_FOUND;
            }
#endif //_WIN32_WCE_BUG_10655

        hr = SpHrFromWin32(lRet);
            ::RegCloseKey(hKey);
        }

        if (SUCCEEDED(hr))
        {
            // Convert string to number
            wUILang = (LANGID) wcstol(szData, NULL, 16) ;

            if(0x0401 == wUILang || // Arabic
               0x040d == wUILang || // Hebrew
               0x041e == wUILang    // Thai
               )
            {
                // Special case these to the English UI.
                // These versions of Windows NT 4.0 were enabled only, i.e., the
                // UI was English. However, the registry setting 
                // HKEY_USERS\.DEFAULT\Control Panel\International\Locale was set  
                // to the respective locale for application compatibility.
                wUILang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US) ;
            }
        }
    }

    return (wUILang ? wUILang : ::GetUserDefaultLangID());    // In failure case, try our best!
}


inline HRESULT SpGetDescription(ISpObjectToken * pObjToken, WCHAR ** ppszDescription, LANGID Language = SpGetUserDefaultUILanguage())
{
    WCHAR szLangId[10];
    SpHexFromUlong(szLangId, Language);
    HRESULT hr = pObjToken->GetStringValue(szLangId, ppszDescription);
    if (hr == SPERR_NOT_FOUND)
    {
        hr = pObjToken->GetStringValue(NULL, ppszDescription);
    }
    return hr;
}


inline HRESULT SpSetDescription(ISpObjectToken * pObjToken, const WCHAR * pszDescription, LANGID Language = SpGetUserDefaultUILanguage(), BOOL fSetLangIndependentId = TRUE)
{
    WCHAR szLangId[10];
    SpHexFromUlong(szLangId, Language);
    HRESULT hr = pObjToken->SetStringValue(szLangId, pszDescription);
    if (SUCCEEDED(hr) && fSetLangIndependentId)
    {
        hr = pObjToken->SetStringValue(NULL, pszDescription);
    }
    return hr;
}

/****************************************************************************
* SpConvertStreamFormatEnum *
*---------------------------*
*   Description:
*       This method converts the specified stream format into a wave format
*   structure.
*
*****************************************************************************/
inline HRESULT SpConvertStreamFormatEnum(SPSTREAMFORMAT eFormat, GUID * pFormatId, WAVEFORMATEX ** ppCoMemWaveFormatEx)
{
    HRESULT hr = S_OK;

    if(pFormatId==NULL || ::IsBadWritePtr(pFormatId, sizeof(*pFormatId))
        || ppCoMemWaveFormatEx==NULL || ::IsBadWritePtr(ppCoMemWaveFormatEx, sizeof(*ppCoMemWaveFormatEx)))
    {
        return E_INVALIDARG;
    }

    const GUID * pFmtGuid = &GUID_NULL;     // Assume failure case
    if( eFormat >= SPSF_8kHz8BitMono && eFormat <= SPSF_48kHz16BitStereo )
    {
        WAVEFORMATEX * pwfex = (WAVEFORMATEX *)::CoTaskMemAlloc(sizeof(WAVEFORMATEX));
        *ppCoMemWaveFormatEx = pwfex;
        if (pwfex)
        {
            DWORD dwIndex = eFormat - SPSF_8kHz8BitMono;
            BOOL bIsStereo = dwIndex & 0x1;
            BOOL bIs16 = dwIndex & 0x2;
            DWORD dwKHZ = (dwIndex & 0x3c) >> 2;
            static const DWORD adwKHZ[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 };
            pwfex->wFormatTag = WAVE_FORMAT_PCM;
            pwfex->nChannels = pwfex->nBlockAlign = (WORD)(bIsStereo ? 2 : 1);
            pwfex->nSamplesPerSec = adwKHZ[dwKHZ];
            pwfex->wBitsPerSample = 8;
            if (bIs16)
            {
                pwfex->wBitsPerSample *= 2;
                pwfex->nBlockAlign *= 2;
            }
                pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nBlockAlign;
            pwfex->cbSize = 0;
            pFmtGuid = &SPDFID_WaveFormatEx;
        }
        else
        {
            hr = E_OUTOFMEMORY;
        }
    }
    else if( eFormat == SPSF_TrueSpeech_8kHz1BitMono )
    {
        int NumBytes = sizeof( WAVEFORMATEX ) + 32;
        WAVEFORMATEX * pwfex = (WAVEFORMATEX *)::CoTaskMemAlloc( NumBytes );
        *ppCoMemWaveFormatEx = pwfex;
        if( pwfex )
        {
            memset( pwfex, 0, NumBytes );
            pwfex->wFormatTag      = WAVE_FORMAT_DSPGROUP_TRUESPEECH;
            pwfex->nChannels       = 1;
            pwfex->nSamplesPerSec  = 8000;
            pwfex->nAvgBytesPerSec = 1067;
            pwfex->nBlockAlign     = 32;
            pwfex->wBitsPerSample  = 1;
            pwfex->cbSize          = 32;
            BYTE* pExtra = ((BYTE*)pwfex) + sizeof( WAVEFORMATEX );
            pExtra[0] = 1;
            pExtra[2] = 0xF0;
            pFmtGuid = &SPDFID_WaveFormatEx;
        }
        else
        {
            hr = E_OUTOFMEMORY;
        }
    }
    else if( (eFormat >= SPSF_CCITT_ALaw_8kHzMono    ) &&
             (eFormat <= SPSF_CCITT_ALaw_44kHzStereo ) )
    {
        WAVEFORMATEX * pwfex = (WAVEFORMATEX *)::CoTaskMemAlloc( sizeof(WAVEFORMATEX) );
        *ppCoMemWaveFormatEx = pwfex;
        if( pwfex )
        {
            memset( pwfex, 0, sizeof(WAVEFORMATEX) );
            DWORD dwIndex = eFormat - SPSF_CCITT_ALaw_8kHzMono;
            DWORD dwKHZ = dwIndex / 2;
            static const DWORD adwKHZ[] = { 8000, 11025, 22050, 44100 };
            BOOL bIsStereo    = dwIndex & 0x1;
            pwfex->wFormatTag = WAVE_FORMAT_ALAW;
            pwfex->nChannels  = pwfex->nBlockAlign = (WORD)(bIsStereo ? 2 : 1);
            pwfex->nSamplesPerSec  = adwKHZ[dwKHZ];
            pwfex->wBitsPerSample  = 8;
                pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nBlockAlign;
            pwfex->cbSize          = 0;
            pFmtGuid = &SPDFID_WaveFormatEx;
        }
        else
        {
            hr = E_OUTOFMEMORY;
        }
    }
    else if( (eFormat >= SPSF_CCITT_uLaw_8kHzMono    ) &&
             (eFormat <= SPSF_CCITT_uLaw_44kHzStereo ) )
    {
        WAVEFORMATEX * pwfex = (WAVEFORMATEX *)::CoTaskMemAlloc( sizeof(WAVEFORMATEX) );
        *ppCoMemWaveFormatEx = pwfex;
        if( pwfex )
        {
            memset( pwfex, 0, sizeof(WAVEFORMATEX) );
            DWORD dwIndex = eFormat - SPSF_CCITT_uLaw_8kHzMono;
            DWORD dwKHZ = dwIndex / 2;
            static const DWORD adwKHZ[] = { 8000, 11025, 22050, 44100 };
            BOOL bIsStereo    = dwIndex & 0x1;
            pwfex->wFormatTag = WAVE_FORMAT_MULAW;
            pwfex->nChannels  = pwfex->nBlockAlign = (WORD)(bIsStereo ? 2 : 1);
            pwfex->nSamplesPerSec  = adwKHZ[dwKHZ];
            pwfex->wBitsPerSample  = 8;
                pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nBlockAlign;
            pwfex->cbSize          = 0;
            pFmtGuid = &SPDFID_WaveFormatEx;
        }
        else
        {
            hr = E_OUTOFMEMORY;
        }
    }
    else if( (eFormat >= SPSF_ADPCM_8kHzMono    ) &&
             (eFormat <= SPSF_ADPCM_44kHzStereo ) )
    {
        int NumBytes = sizeof( WAVEFORMATEX ) + 32;
        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[] = { 4096, 8192, 5644, 11289, 11155, 22311, 22179, 44359 };
            static const DWORD BlockAlign[]  = { 256, 256, 512, 1024 };
            static const BYTE Extra811[32] =
            {
                0xF4, 0x01, 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 Extra22[32] =
            {
                0xF4, 0x03, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00,
                0x00, 0x02, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
                0xC0, 0x00, 0x40, 0x00, 0xF0, 0x00, 0x00, 0x00,

⌨️ 快捷键说明

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