c++ - 如何获取Microsoft TTS语音的耗时?

标签 c++ windows text-to-speech sapi

我现在使用下面的函数来实现一个TTS服务。

int tts(LPCWSTR text){
    ::CoInitialize(NULL);         
    CLSID CLSID_SpVoice;
    CLSIDFromProgID(_T("SAPI.SpVoice"), &CLSID_SpVoice);
    ISpVoice *pSpVoice = NULL;
    IEnumSpObjectTokens *pSpEnumTokens = NULL;

    if (FAILED(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_INPROC_SERVER, IID_ISpVoice, (void**)&pSpVoice))){
        return -1;
    }

    if (SUCCEEDED(SpEnumTokens(SPCAT_VOICES, NULL, NULL, &pSpEnumTokens))){
        ISpObjectToken *pSpToken = NULL;
        SpFindBestToken(SPCAT_VOICES, L"Gender=Male", L"Name=Microsoft Simplified Chinese", &pSpToken);
        pSpVoice->SetVoice(pSpToken);
        pSpVoice->Speak(text, SPF_DEFAULT, NULL);
        pSpEnumTokens->Release();        
    }

    pSpVoice->Release();
    ::CoUninitialize();
    return 0;
}

我有可能得到每个被说出的字符的耗时吗?或者它是恒定的(如果设置了语速)?目的是想展示一些面部动画来配合演讲...

最佳答案

您不一定需要耗时;您可以使用 Viseme 事件来触发动画。

由于您使用的是 C++,因此请使用 ISpVoice::SetInterest描述您想要的事件集,以及 ISpNotifySource 之一方法(取决于您的外部代码在做什么)来将事件传递给您。

Microsoft 有一个详细的 workthrough以防此草图没有帮助。

请注意,视位的确切(以及视位映射到哪些值)取决于语言。对于美国英语,视位定义为 here .对于中文,从音位到语音位的映射没有公开定义。

另一方面,您可以将 viseme 事件用作触发器,而不必真正关心实际的 viseme

假设您的应用中某处有一个消息循环,您的代码将如下所示:

CLSID CLSID_SpVoice;
CLSIDFromProgID(_T("SAPI.SpVoice"), &CLSID_SpVoice);
ISpVoice *pSpVoice = NULL;
IEnumSpObjectTokens *pSpEnumTokens = NULL;
ULONGLONG  ullMyEvents = SPFEI(SPEI_VISEME);

if (FAILED(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_INPROC_SERVER, IID_ISpVoice, (void**)&pSpVoice))){
    return -1;
}

if (SUCCEEDED(SpEnumTokens(SPCAT_VOICES, NULL, NULL, &pSpEnumTokens))){
    ISpObjectToken *pSpToken = NULL;
    SpFindBestToken(SPCAT_VOICES, L"Gender=Male", L"Name=Microsoft Simplified Chinese", &pSpToken);
    pSpVoice->SetVoice(pSpToken);
    // Set type of events the client is interested in.
    pSpVoice->SetInterest(ullMyEvents, ullMyEvents);
    // deliver a WM_APP message when a SAPI event arrives.   
    // Use a different message ID for real code.
    pSpVoice->SetNotifyWindowMessage(hWnd, WM_APP, 0, 0);
    pSpVoice->Speak(text, SPF_DEFAULT, NULL);
    pSpEnumTokens->Release();        
}

pSpVoice->Release();

稍后,在您的消息循环中,您需要处理 SAPI 消息:

  case WM_APP:
     SPEVENT eventItem;
     memset( &eventItem;, 0,sizeof(SPEVENT));
     while( pVoice->GetEvents(1, &eventItem;, NULL ) == S_OK )
     {
       switch(eventItem.eEventId )
       {
          case SPEI_VISEME:
             .
             .
             .
             break;

          default:
             break;
       }

     SpClearEvent( eventItem );

关于c++ - 如何获取Microsoft TTS语音的耗时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30049895/

相关文章:

c++ - TYPE_ALIGNMENT() 失败的示例

c++ - Windows 上的堆栈 - 它在哪里?

java - 如何为运行最新操作系统 Sierra 的 iMac 安装和设置 Java 语音 (jsapi)?

android - 同时进行语音转文本和文本转语音

c++ - Windows - VC++ - 不能在静态构建中使用 "_ASSERTE"

c++ - 20 个问题游戏

c++ - 如何在没有冲突的情况下隐式链接到 dll 及其依赖项?

python - 在 Python 3 下工作的文本到语音 (TTS) 模块

c++ - 基于 SFINAE 的 ifdef

windows - 如何重新配置​​ RabbitMQ 在 Windows 上不使用 %appdata%?