4

問題/クラッシュの鍵を発見しました。投稿の下部を参照してください。

ISpVoiceusingのインスタンスを作成するときCoCreateInstance、最初のインスタンスが発話するとすぐに、最初のインスタンスの後のインスタンスが発話できないようです。つまり、pVoice最初に話すと、話しpVoice2ません。pVoice2最初に話す場合は、話しpVoiceません。作成/割り当ての順序は問題ではないようです。

私が「話さない」と言うのは、次のことを意味ISpVoice::SpeakS_OKます。音声は合成されませんでした。

訂正:デバッガがアタッチされていない場合、上記は D バージョンで発生します。Visual Studio デバッガーをアタッチすると、 でアクセス違反が発生しvtjpnsapi50.dll!10004e65ます。また、C++版では、デバッガのアタッチやデバッグ情報生成の有無に関わらず、アクセス違反が発生します。

sleepSpeak への呼び出しの間にへの呼び出しを挿入しても、何も変わりません (もちろん、遅延が挿入されることを除いて)。

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 バージョンでは、Speakonの 2 回目の呼び出しpVoiceも機能します。

誰かがこれを引き起こす原因を知っている場合、または複数の音声オブジェクトが使用されているオープン ソース ソフトウェアについて知っている場合は、お知らせください。

編集 これは、NeoSpeech の音声でのみ発生します。Microsoft と eSpeak の音声で問題なく動作します。問題を解決するために何かできることがあれば、まだ知りたいです (NeoSpeech には本当に本当に良い声がいくつかあります...)。

4

0 に答える 0