gpt4 book ai didi

c++ - 基于 SAPI 的应用程序在枚举 token 时抛出内存访问冲突

转载 作者:太空宇宙 更新时间:2023-11-04 13:19:17 31 4
gpt4 key购买 nike

我最近刚刚下载了 Visual Studio 2015(社区),以便我可以使用 Microsoft SAPI TTS 开发应用程序。我已经安装了 5.1 SDK,随后安装了 5.4 SDK for Speech,并安装了 Runtime Languages for SAPI。

到目前为止,我可以通过使用我希望 SAPI 通过直接参数和读取 SSML .XML 文件来表达的短语来设法让应用程序正常工作。 SAPI 和 SSML 的所有功能都可以工作,除了与更改语音 token 有关的任何事情。 (例如,<voice xml:lang="pl-PL"> ... <voice required="Gender:Female"> ... 等)

我阅读了一些关于如何设置语言/语音 token 的论坛,并且我尝试了以下代码:

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

程序构建没有错误,但在最终返回语句中抛出错误 0xC0000005(内存访问冲突)。

我确实必须修改头文件 <sphelper.h>由于不推荐使用的方法::GetVersionExW() ...我设法使用此链接中的方法使其工作:http://www.codeproject.com/Articles/678606/Part-Overcoming-Windows-s-deprecation-of-GetVe .奇迹般地(并且对系统源代码进行了一些调整,这可能是个坏主意),它成功了。

我不知道为什么程序会在最后抛出错误,因为问题一定出在访问注册表 token 的程序中。我知道问题通常出在指针上,那么我需要做什么才能完成这项工作?

请注意,我正在尝试制作 cpVoice对象使用波兰语标记“Paulina”。有没有办法以某种方式手动将注册表 token 值分配给对象?

最佳答案

这就是您检查每个已安装声音的方式。 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++ - 基于 SAPI 的应用程序在枚举 token 时抛出内存访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35925377/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com