基于 SAPI 的应用程序在枚举令牌时引发内存访问冲突
SAPI-Based application throwing memory access violation when enumerating tokens
我最近刚刚下载了Visual Studio 2015(社区),以便我可以使用Microsoft SAPI TTS开发应用程序。我已经安装了 5.1 SDK,然后安装了 5.4 SDK 语音,并安装了 SAP 运行时语言。
到目前为止,我可以通过使用我希望 SAPI 通过直接参数和读取 SSML .XML文件来说话的短语来设法让应用程序工作。SAPI和SSML的所有功能都可以工作,除了与更改语音令牌有关的任何功能。(例如,<voice xml:lang="pl-PL">
... <voice required="Gender:Female">
......等)
我阅读了一些关于如何设置语言/语音令牌的论坛,并尝试了以下代码:
if(FAILED(::CoInitialized(NULL))
return false;
HRESULT hr = S_OK;
CComPtr<ISpVoice> cpVoice;
CComPtr<ISpObjectTokenCategory> cpObjectCat;
CComPtr<ISpObjectToken> cpObjectToken;
CComPtr<IEnumSpObjectTokens> cpEnum;
hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&cpVoice);
if(SUCCEEDED(hr))
{
hr = SpGetDefaultTokenFromCategoryId(SPCAT_VOICES, &cpObjectToken);
}
if(SUCCEEDED(hr))
{
hr = SpGetCategoryFromId(SPCAT_VOICES, &cpObjectCat);
}
if(SUCCEEDED(hr))
{
hr = cpObjectCat->EnumTokens(NULL, NULL, &cpEnum);
}
if(SUCCEEDED(hr))
{
hr = cpEnum->Next(1, &cpObjectToken, NULL);
//Currently only concerned with making 1 token assign without
//throwing exception
}
if(SUCCEEDED(hr))
{
hr = cpVoice->SetVoice(cpObjectToken);
}
if(SUCCEEDED(hr))
{
hr = cpVoice->Speak(L"Hello There!", NULL, NULL);
}
//... lots of commented-out code here ...
cpVoice.Release();
::CoUninitialize();
return true; // <-- Throws Exception Here
程序构建时没有错误,但在最终的 return 语句中抛出错误0xC0000005(内存访问冲突)。
<sphelper.h>
由于已弃用的方法::GetVersionExW() ...我设法使用此链接中的方法使其工作:http://www.codeproject.com/Articles/678606/Part-Overcoming-Windows-s-deprecation-of-GetVe.奇迹般地(并且对系统源代码进行了一些调整,可能是一个坏主意),它奏效了。
我不知道为什么程序在最后抛出,因为问题一定出在访问注册表令牌的程序上。我知道通常问题出在指针上,那么我需要做什么才能完成这项工作呢?
请注意,我正在尝试使cpVoice
对象使用波兰语令牌"Paulina"。有没有办法以某种方式手动将注册表令牌值分配给对象?
这是您浏览每个已安装语音的方式。 pszCurTokenId 将是你得到的声音的描述。您可能会将其打印到控制台或其他内容,或者只查看调试器中的值。
您不必编辑 sphelper.h 即可正确选择语音。有时 SAPI 可能需要几秒钟才能改变声音,所以如果感觉它挂起来,我会耐心等待。我刚刚在 Windows 7 上运行了以下代码,并验证了它适用于该平台。
HRESULT hr = S_OK;
CComPtr<ISpObjectToken> cpVoiceToken;
CComPtr<ISpVoice> cpVoice;
::CoInitialize(NULL);
if(SUCCEEDED(hr))
hr = cpVoice.CoCreateInstance(CLSID_SpVoice);
ULONG ulCount = 0;
CComPtr<IEnumSpObjectTokens> cpEnum;
if(SUCCEEDED(hr))
hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
//Get the number of voices
if(SUCCEEDED(hr))
hr = cpEnum->GetCount(&ulCount);
for(ULONG i = 0; i < ulCount; ++i) {
CSpDynamicString* szDescription;
CComPtr<ISpObjectToken> cpTempVoiceToken;
cpEnum->Item(i, &cpTempVoiceToken);
WCHAR* pszCurTokenId = NULL;
SpGetDescription(cpTempVoiceToken, &pszCurTokenId);
cpVoice->SetVoice(cpTempVoiceToken);
cpVoice->Speak(L"This is a test phrase.", SPF_DEFAULT, NULL);
cpTempVoiceToken.Release();
}
cpVoice.Release();
cpEnum.Release();
::CoUninitialize();
- C++尝试深度复制唯一指针时出现内存访问冲突
- C++中的内存分配(引发异常:读取访问冲突)
- 使用加速进程间创建消息队列 - 内存访问冲突
- C 指针转换会导致内存访问冲突
- 为什么创建进程 API 调用会导致内存访问冲突?
- 使用 std::map 作为本地成员的内存访问冲突
- 编译哈希算法时出现内存访问冲突错误
- 使用内存访问冲突错误
- 堆栈引发内存访问冲突
- 使用 Boost::序列化时内存访问冲突
- 调用std::vector::empty()时内存访问冲突读取位置
- 基于 SAPI 的应用程序在枚举令牌时引发内存访问冲突
- 内存访问冲突
- 使用 VC++ 中的 Try 和 catch 块捕获内存访问冲突
- 对象向量中的内存访问冲突
- "detects_simple_anagram"中的致命错误:地址 0x00000000 处的内存访问冲突:故障地址处没有映射
- 内存访问冲突插入结构在树结构c++
- c++内存访问冲突
- MotorBee dll和c++,内存访问冲突
- 调用FindConnectionPoint时写入内存访问冲突