問題/クラッシュの鍵を発見しました。投稿の下部を参照してください。
ISpVoice
usingのインスタンスを作成するときCoCreateInstance
、最初のインスタンスが発話するとすぐに、最初のインスタンスの後のインスタンスが発話できないようです。つまり、pVoice
最初に話すと、話しpVoice2
ません。pVoice2
最初に話す場合は、話しpVoice
ません。作成/割り当ての順序は問題ではないようです。
私が「話さない」と言うのは、次のことを意味ISpVoice::Speak
しS_OK
ます。音声は合成されませんでした。
訂正:デバッガがアタッチされていない場合、上記は D バージョンで発生します。Visual Studio デバッガーをアタッチすると、 でアクセス違反が発生しvtjpnsapi50.dll!10004e65
ます。また、C++版では、デバッガのアタッチやデバッグ情報生成の有無に関わらず、アクセス違反が発生します。
sleep
Speak への呼び出しの間にへの呼び出しを挿入しても、何も変わりません (もちろん、遅延が挿入されることを除いて)。
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
onの 2 回目の呼び出しpVoice
も機能します。
誰かがこれを引き起こす原因を知っている場合、または複数の音声オブジェクトが使用されているオープン ソース ソフトウェアについて知っている場合は、お知らせください。
編集 これは、NeoSpeech の音声でのみ発生します。Microsoft と eSpeak の音声で問題なく動作します。問題を解決するために何かできることがあれば、まだ知りたいです (NeoSpeech には本当に本当に良い声がいくつかあります...)。