语言函数的实现比较复杂。由于IspVoice接口提供的语言函数,都只与抽象的语音语言接口ISpObjectToken相关,而我们能看到的却是语音语言的描述,比如,通过控制面板的语音程序所能见到的就是语音语言的描述。因此,笔者设计了直接对语音语言进行操作的语言函数,包括获取系统中已安装的语音语言数目,设置指定的语音语言,获取指定的语音语言描述(包括当前设定的语音语言)。它们的代码如下:
ULONG CText2Speech::GetVoiceCount()
{
HRESULT hr = S_OK;
CComPtr<ISpObjectToken> cpVoiceToken;
CComPtr<IEnumSpObjectTokens> cpEnum;
ULONG ulCount = -1;
//Enumerate the available voices
hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
if(FAILED(hr))
{
m_sError = _T("Error to enumerate voices");
return -1;
}
//Get the number of voices
hr = cpEnum->GetCount(&ulCount);
if(FAILED(hr))
{
m_sError = _T("Error to get voice count");
return -1;
}
return ulCount;
}
HRESULT CText2Speech::GetVoice(WCHAR **ppszDescription, ULONG lIndex)
{
HRESULT hr = S_OK;
CComPtr<ISpObjectToken> cpVoiceToken;
CComPtr<IEnumSpObjectTokens> cpEnum;
ULONG ulCount = 0;
if (lIndex == -1)
{
// current voice
//
hr = m_IpVoice->GetVoice(&cpVoiceToken);
if(FAILED(hr))
{
m_sError = _T("Error to get current voice");
return hr;
}
SpGetDescription(cpVoiceToken, ppszDescription);
if(FAILED(hr))
{
m_sError = _T("Error to get current voice description");
return hr;
}
}
else
{
// else other voices, we should enumerate the voice list first
//Enumerate the available voices
hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
if(FAILED(hr))
{
m_sError = _T("Error to enumerate voices");
return hr;
}
//Get the number of voices
hr = cpEnum->GetCount(&ulCount);
if(FAILED(hr))
{
m_sError = _T("Error to voice count");
return hr;
}
// range control
ASSERT(lIndex >= 0);
ASSERT(lIndex < ulCount);
// Obtain specified voice id
ULONG l = 0;
while (SUCCEEDED(hr))
{
cpVoiceToken.Release();
hr = cpEnum->Next( 1, &cpVoiceToken, NULL );
if(FAILED(hr))
{
m_sError = _T("Error to get voice token");
return hr;
}
if (l == lIndex)
{
hr = SpGetDescription(cpVoiceToken, ppszDescription);
if(FAILED(hr))
{
m_sError = _T("Error to get voice description");
return hr;
}
break;
}
l++;
}
}
return hr;
}
HRESULT CText2Speech::SetVoice(WCHAR **ppszDescription)
{
HRESULT hr = S_OK;
CComPtr<ISpObjectToken> cpVoiceToken;
CComPtr<IEnumSpObjectTokens> cpEnum;
ULONG ulCount = 0;
//Enumerate the available voices
hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
if(FAILED(hr))
{
m_sError = _T("Error to enumerate voices");
return hr;
}
//Get the number of voices
hr = cpEnum->GetCount(&ulCount);
if(FAILED(hr))
{
m_sError = _T("Error to voice count");
return hr;
}
// Obtain specified voice id
while (SUCCEEDED(hr) && ulCount--)
{
cpVoiceToken.Release();
hr = cpEnum->Next( 1, &cpVoiceToken, NULL );
if(FAILED(hr))
{
m_sError = _T("Error to voice token");
return hr;
}
WCHAR *pszDescription1;
hr = SpGetDescription(cpVoiceToken, &pszDescription1);
if(FAILED(hr))
{
m_sError = _T("Error to get voice description");
return hr;
}
if (! wcsicmp(pszDescription1, *ppszDescription))
{
hr = m_IpVoice->SetVoice(cpVoiceToken);
if(FAILED(hr))
{
m_sError = _T("Error to set voice");
return hr;
}
break;
}
}
return hr;
}