后续SpVoice实例是静默的

时间:2012-10-04 05:17:16

标签: c++ com d sapi text-to-speech

发现问题/崩溃的关键,请参阅帖子的底部。

使用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版本中,SpeakpVoice的第二次调用也可以。

如果有人知道可能导致这种情况的原因,或者知道任何使用多个语音对象的开源软件,请告诉我,谢谢!

修改 这只发生在NeoSpeech的声音中。它可以与微软和eSpeak的声音一起使用。我仍然想知道我能做些什么来解决这个问题(NeoSpeech有一些非常非常好的声音......)。

0 个答案:

没有答案