C#(C++)SAPI-TTS-如何获得正在读取的文本的语音计时

本文关键字:读取 文本 语音 C++ SAPI-TTS- 何获得 | 更新日期: 2023-09-27 18:20:28

有人能帮我吗?我搜索了一些例子,如何通过SAPI获得TTS中拼写文本的信息(我正在用C#编程我的应用程序,但这不是必需的,SAPI在C++中是一样的,等等)我需要的信息例如:用户将在文本框中写入:

";这是一个文本"。。

tts.Speak("This is a text")//这将";读取";它..

好的,很好。。。但我也需要得到关于";定时";。。

例如:

"Th";(第一个声音(音素)";这")是";读取";在0.01ms内。

"i〃;("is"的第一个音)是"is";读取";在0.5ms内。

"e";("文本"的第二个声音)是"文本";读取";在1.02ms内。

当我保存SAPI生成的.wav文件时,我需要在.wav中获得有关后续";处理";wav文件的。

很抱歉我的英语,也很抱歉我对问题的描述不好,但问题很简单,大家都会理解的。如果不是,我会再次描述这个问题:)^^。。

C#(C++)SAPI-TTS-如何获得正在读取的文本的语音计时

我使用C++和SAPI 5.1来合成语音,并让虚拟角色相应地移动嘴唇。以下是一些适用于visemes的代码。根据上的文件http://msdn.microsoft.com/en-us/library/ms720164(v=vs.85).aspx,除了用SPEI_PHONEME替换SPEI_VISEME之外,音素的工作原理相同。

DWORD WINAPI Character::sayMessage(LPVOID lpParam){
    HRESULT hres;
    try{
        ::CoInitialize(NULL);
        ThreadParam * param = (ThreadParam *)lpParam;
        wstring s = param->message;
        //first check the string for null
        if (s == L"") return false;
        //http://msdn.microsoft.com/en-us/library/ms720163(VS.85,classic).asp is my source for this
        //set up text to speech
        //get the voice associated with the character
        ISpVoice * pVoice;
        pVoice = param->sceneObject->characterVoice;
        if (pVoice != NULL){
            pVoice->Speak( NULL, SPF_PURGEBEFORESPEAK, 0 );
            SPEVENT event;
            ULONG ul;
            pVoice->SetInterest(SPFEI(SPEI_VISEME)|SPFEI(SPEI_END_INPUT_STREAM),SPFEI(SPEI_VISEME)|SPFEI(SPEI_END_INPUT_STREAM));
            pVoice->SetNotifyCallbackFunction(&eventFunction,0,0);
            pVoice->WaitForNotifyEvent(INFINITE);
            if (param->sceneObject->age == CHILD){
                s = L"<pitch middle='"+10'">" + s + L"</pitch>";
            }
            hres = pVoice->Speak(s.c_str(),SPF_ASYNC,NULL);
            bool isDone = false;
            while(!isDone && pVoice != NULL && !FAILED(hres)){                  
                if(pVoice->GetEvents(1,&event, &ul) == S_OK){
                    if(event.eEventId==SPEI_VISEME){
                        //get the viseme
                        int vis = LOWORD(event.lParam);  //handle it however you'd like after this

                    }
                    else if(event.eEventId== SPEI_END_INPUT_STREAM){
                        isDone = true;
                        s = L"";
                        return true;
                    }
                }                   
            }
        }
    }
    catch(...){
        return false;
    }       
    return !FAILED(hres);
}