当前位置: 首页 > 工具软件 > SAPI++ > 使用案例 >

sapi 实现语音朗读

方季同
2023-12-01

头文件定义(CSpeechSpeekImpl.h):

#pragma once

#include "sphelper.h"
class CSpeechSpeekImpl
{
public:
    CSpeechSpeekImpl(void);
    ~CSpeechSpeekImpl(void);

    HRESULT SpeechVoice(LPCSTR lpszVoiceText, UINT bSyn=TRUE);
    HRESULT SetVolume(USHORT usVolume);
    HRESULT MakeWavFile(LPCTSTR lpszVoiceText, LPCTSTR lpszWaveFile);

private:
    ISpVoice* m_pVoice;
    BOOL Inited();
    void EnumVoicePackage();
};

源码实现(CSpeechSpeekImpl.cpp):

#include "StdAfx.h"
#include "SpeechSpeekImpl.h"

#include "sapi.h"
#pragma comment(lib,"sapi.lib")

CSpeechSpeekImpl::CSpeechSpeekImpl(void)
{
    m_pVoice = NULL;
    CoInitialize(NULL);
    Inited();
}


CSpeechSpeekImpl::~CSpeechSpeekImpl(void)
{
    if ( m_pVoice )
        m_pVoice->Release();
    CoUninitialize();
}

BOOL CSpeechSpeekImpl::Inited()
{
    //初始化COM 
    if ( m_pVoice == NULL )
    {
        //初始化SAPI 
        HRESULT hr = CoCreateInstance(CLSID_SpVoice, 
            NULL, 
            CLSCTX_ALL, 
            IID_ISpVoice, 
            (void **)&m_pVoice); 
        ISpObjectToken * pSpObjectToken = NULL; 
        if (SUCCEEDED(SpFindBestToken(SPCAT_VOICES, 
            L"language=804", 
            NULL, 
            &pSpObjectToken)))//804代表中文 
        { 
            m_pVoice->SetVoice(pSpObjectToken);//声音大小
            m_pVoice->SetRate(-8);//设置朗读速度(取值范围:-10到10)
            pSpObjectToken->Release(); 
        }
        else
        { 
            return FALSE; 
        } 
    }

    if ( m_pVoice == NULL )
        return FALSE;

    return TRUE;
}

HRESULT CSpeechSpeekImpl::SpeechVoice(LPCSTR lpszVoiceText, UINT bSyn/*=TRUE*/)
{
    if ( !Inited() )
        return E_FAIL;

    //朗读文字 
    CString strText = __T(lpszVoiceText);
    BSTR lpwszVoiceText = strText.AllocSysString();
    m_pVoice->SetRate(2);	//设置朗读速度(取值范围:-10到10)
    HRESULT hr = m_pVoice->Speak(lpwszVoiceText, SPF_ASYNC, NULL); 
    SysFreeString(lpwszVoiceText);

    return S_OK;
}


HRESULT CSpeechSpeekImpl::SetVolume(USHORT usVolume)
{
    if ( !Inited() )
        return E_FAIL;

    return m_pVoice->SetVolume(usVolume);// m_pVoice->SetVolume(usVolume);
}

//生成WAV文件
HRESULT CSpeechSpeekImpl::MakeWavFile(LPCTSTR lpszVoiceText, LPCTSTR lpszWaveFile)
{
    if ( !Inited() )
        return E_FAIL;

    CComPtr<ISpStream> cpISpStream;
    CComPtr<ISpStreamFormat> cpISpStreamFormat;
    CSpStreamFormat spStreamFormat;
    m_pVoice->GetOutputStream(&cpISpStreamFormat);
    spStreamFormat.AssignFormat(cpISpStreamFormat);
    HRESULT hResult = SPBindToFile(lpszWaveFile, 
        SPFM_CREATE_ALWAYS, 
        &cpISpStream, 
        &spStreamFormat.FormatId(), 
        spStreamFormat.WaveFormatExPtr());
    if(SUCCEEDED(hResult))
    {
        m_pVoice->SetOutput(cpISpStream, TRUE);
        CString strText = __T(lpszVoiceText);
        BSTR lpwszVoiceText = strText.AllocSysString();
        m_pVoice->SetRate(2);
        m_pVoice->Speak(lpwszVoiceText, SPF_DEFAULT, NULL);
        SysFreeString(lpwszVoiceText);
        return S_OK;
    }
    else
    {
        return E_FAIL;
    }
}


void CSpeechSpeekImpl::EnumVoicePackage()
{
    //初始化COM组件
    if (FAILED(::CoInitialize(NULL)))
        return;

    //枚举所有语音Token
    IEnumSpObjectTokens* pIEnumSpObjectTokens = NULL;
    if(SUCCEEDED(SpEnumTokens(SPCAT_VOICES, NULL, NULL, &pIEnumSpObjectTokens)))
    {
        //得到所有语音Token的个数
        ULONG ulTokensNumber = 0;
        pIEnumSpObjectTokens->GetCount(&ulTokensNumber);

        //检测该机器是否安装有语音包
        if (ulTokensNumber == 0)
            return;    

        //将语音包的名字加入组合框控件
        CString strVoicePackageName = _T("");
        CString strTokenPrefixText = _T("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\");
        for(ULONG i=0; i<ulTokensNumber; i++)
        {
            ISpObjectToken* pISpObjectToken = NULL;
            pIEnumSpObjectTokens->Item(i, &pISpObjectToken);
            WCHAR* pChar;
            pISpObjectToken->GetId(&pChar);
            strVoicePackageName = pChar;
            strVoicePackageName.Delete(0, strTokenPrefixText.GetLength());
        }

//设置语言
// 		ISpObjectToken *pISpObjectToken = NULL;
// 		pIEnumSpObjectTokens->Item(1, &pISpObjectToken);
// 		m_pVoice->SetVoice(pISpObjectToken);
// 		pISpObjectToken->Release();

        pIEnumSpObjectTokens->Release();
    }
}

 

 类似资料: