www.pudn.com > ruier_TTS_SR(vc6).rar > Text2Speech.cpp
// Text2Speech.cpp : 实现文件
//
#include "stdafx.h"
#include "TTS_SR.h"
#include "Text2Speech.h"
#include "TTDLG.h"
// CText2Speech
CText2Speech::CText2Speech()
{
m_IpVoice = NULL;
m_sError=_T("");
}
CText2Speech::~CText2Speech()
{
Destroy();
}
// CText2Speech 成员函数
CString CText2Speech::GetErrorString()
{
return m_sError;
}
//初始化函数Initialize首先初始化COM库,并调用CoCreateInstance方法初始化语音引擎。然后设置必须响应的引擎事件,并指定响应事件消息的窗口句柄。该窗口句柄是作为函数的参数传入的,此方法应在初始化窗口之后再调用
bool CText2Speech::Initialize(HWND hWnd,int nIDDlgItem)
{
if (FAILED(CoInitialize(NULL)))
{
m_sError=_T("Error intialization COM");
return false;
}
HRESULT hr;
hr = m_IpVoice.CoCreateInstance(CLSID_SpVoice);
if (FAILED(hr))
{
m_sError=_T("Error creating voice");
return false;
}
hr = m_IpVoice->SetInterest(SPFEI(SPEI_WORD_BOUNDARY), SPFEI(SPEI_WORD_BOUNDARY));
if (FAILED(hr))
{
m_sError=_T("Error creating interest");
return false;
}
if (::IsWindow(hWnd))
{
hr = m_IpVoice->SetNotifyWindowMessage(hWnd, WM_TTSEVENT, 0, 0);
if (FAILED(hr))
{
m_sError=_T("Error setting notification window");
return false;
}
hr =initVoiceList(hWnd,nIDDlgItem);
if (FAILED(hr))
{
m_sError=_T("Error init comboBox for window");
return false;
}
}
hw=hWnd;
return true;
}
//释放函数则释放语音引擎接口和COM库
void CText2Speech::Destroy()
{
if (m_IpVoice)
m_IpVoice.Release();
SpDestroyTokenComboBox(hw);
CoUninitialize();
}
//语音、语速、音量函数都是通过m_IpVoice成员直接调用ISpVoice接口的相关方法来实现的
HRESULT CText2Speech::Speak(const WCHAR *pwcs, DWORD dwFlags)
{
return m_IpVoice->Speak(pwcs, dwFlags, NULL);
}
HRESULT CText2Speech::Stop()
{
return m_IpVoice->Speak( NULL, SPF_PURGEBEFORESPEAK, 0);
}
HRESULT CText2Speech::Pause()
{
return m_IpVoice->Pause();
}
HRESULT CText2Speech::Resume()
{
return m_IpVoice->Resume();
}
// 设置播放速率
HRESULT CText2Speech::SetRate(long lRateAdjust)
{
return m_IpVoice->SetRate(lRateAdjust);
}
HRESULT CText2Speech::GetRate(long* plRateAdjust)
{
return m_IpVoice->GetRate(plRateAdjust);
}
//设置音量
HRESULT CText2Speech::SetVolume(USHORT usVolume)
{
return m_IpVoice->SetVolume(usVolume);
}
HRESULT CText2Speech::GetVolume(USHORT* pusVolume)
{
return m_IpVoice->GetVolume(pusVolume);
}
HRESULT CText2Speech::initVoiceList(HWND hWnd,int nIDDlgItem)
{
HRESULT hr = 0;
// Use the SAPI5 helper function in sphelper.h to initialize the Voice combo box.
if ( SUCCEEDED( hr ) )
{
hr = SpInitTokenComboBox(GetDlgItem(hWnd,nIDDlgItem),SPCAT_VOICES);
}
return hr;
}
ULONG CText2Speech::GetVoiceCount()
{
HRESULT hr = S_OK;
CComPtr cpVoiceToken;
CComPtr cpEnum;
ULONG ulCount = -1;
//枚举已有的发音者
hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
if(FAILED(hr))
{
m_sError = _T("Error to enumerate voices");
return -1;
}
//获得已有的发音者数
hr = cpEnum->GetCount(&ulCount);
if(FAILED(hr))
{
m_sError = _T("Error to get voice count");
return -1;
}
return ulCount;
}
HRESULT CText2Speech::SetVoice(HWND hWnd,int nIDDlgItem)
{
HRESULT hr = S_OK;
hr = m_IpVoice->SetVoice(SpGetCurSelComboBoxToken(GetDlgItem(hWnd,nIDDlgItem)));
if(FAILED(hr))
{
m_sError = _T("Error to set voice");
return hr;
}
return hr;
}
LRESULT CText2Speech::PrcEvent(WPARAM wParam, LPARAM lParam,CWnd* cw,int len)
{
WPARAM nStart;
LPARAM nEnd;
CSpEvent event;
while (event.GetFrom(m_IpVoice) == S_OK) {
switch (event.eEventId) {
case SPEI_WORD_BOUNDARY:
{
HRESULT hr = m_IpVoice->GetStatus( &Stat, NULL );
if( FAILED( hr ) )
{
m_sError=_T("Error getting Status");
}
nStart = (LPARAM)( Stat.ulInputWordPos / sizeof(char) );
nEnd = nStart + Stat.ulInputWordLen;
if(nEnd>=(len+1)) {((CTTDLG*)cw)->OnButtonStartTt() ;return 0;};
SendDlgItemMessage( cw->m_hWnd, IDC_EDIT_TT, EM_SETSEL, nStart, nEnd );
break;
}
case SPEI_END_INPUT_STREAM:
break;
}
}
return 0;
}