发现问题/崩溃的关键,请参阅帖子的底部。
使用ISpVoice
创建CoCreateInstance
的实例时,似乎第一个实例在第一个发言后不能发言。也就是说,如果pVoice
先发言,pVoice2
将不会发言。如果pVoice2
先发言,pVoice
将不会发言。创建/分配的顺序似乎并不重要。
当我说“不会说话”时,我的意思是:调用ISpVoice::Speak
会立即返回结果S_OK
;没有合成声音。
更正:当未附加调试器时,上述情况发生在D版本中。附加Visual Studio调试程序时,vtjpnsapi50.dll!10004e65
处发生访问冲突。此外,无论是附加调试器还是生成调试信息,都会在C ++版本中发生访问冲突。
在Speak调用之间插入对sleep
的调用不会改变任何内容(当然,它会插入延迟)。
D中的再现(C ++等价物如下):
import std.c.windows.com;
import core.sys.windows.windows;
import speech.windows.sapi;
import std.stdio;
int main()
{
if (FAILED(CoInitialize(null)))
return 1;
scope(exit) CoUninitialize();
ISpVoice pVoice;
HRESULT hr = CoCreateInstance(&CLSID_SpVoice, null, CLSCTX_ALL, &IID_ISpVoice, cast(void**)&pVoice);
assert(hr == S_OK);
hr = pVoice.Speak("Hello world", 0, null); // This speaks fine
assert(hr == S_OK);
ISpVoice pVoice2;
hr = CoCreateInstance(&CLSID_SpVoice, null, CLSCTX_ALL, &IID_ISpVoice, cast(void**)&pVoice2);
assert(hr == S_OK);
hr = pVoice2.Speak("hello again", 0, null); // This returns immediately
assert(hr == S_OK); // Yet it still returns S_OK
hr = pVoice.Speak("first voice again", 0, null); // This speaks fine too, immediately after "hello world" finishes
assert(hr == S_OK);
// The two objects are indeed at different memory addresses
writefln("voice 1: %s, voice 2: %s", cast(void*)pVoice, cast(void*)pVoice2);
pVoice.Release();
pVoice = null;
pVoice2.Release();
pVoice2 = null;
return 0;
}
这是等效的C ++程序:
#include <sapi.h>
#include<Windows.h>
int main()
{
if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
return 1;
ISpVoice* pVoice;
HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&pVoice);
hr = pVoice->Speak(L"Hello world", 0, NULL); // This speaks fine
ISpVoice* pVoice2;
hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&pVoice2);
hr = pVoice2->Speak(L"hello again", 0, NULL); // This causes an access violation
hr = pVoice->Speak(L"first voice again", 0, NULL);
pVoice->Release();
pVoice = NULL;
pVoice2->Release();
pVoice2 = NULL;
CoUninitialize();
return 0;
}
在上面的例子中,两个声音都分配了相同的参数,并且第一个说话的声音正常工作。在没有附加调试器的D版本中,Speak
上pVoice
的第二次调用也可以。
如果有人知道可能导致这种情况的原因,或者知道任何使用多个语音对象的开源软件,请告诉我,谢谢!
修改 这只发生在NeoSpeech的声音中。它可以与微软和eSpeak的声音一起使用。我仍然想知道我能做些什么来解决这个问题(NeoSpeech有一些非常非常好的声音......)。