2

誰か助けてもらえますか?SAPIを介してTTSの音声合成に関する情報を取得する方法の例を検索します(C#でアプリケーションをプログラミングしていますが、必要ありません。SAPIはC ++でも同じです)。必要な情報は次のとおりです。ユーザーはテキストボックスに書き込む:

「これはテキストです」 ..

tts.Speak( "これはテキストです"); //これはそれを「読み取り」ます。

わかりました、いいです...しかし、私も「タイミング」に関する情報を取得する必要があります。

例えば:

「Th」(「This」の最初の音(音素))は0.01msで「読み」ました。

「i」(「is」の最初の音)は0.5msで「読み取った」。

「e」(「テキスト」の2番目の音)は1.02msで「読み取られました」。

SAPIによって生成された.wavファイルを保存するとき、wavファイルの後続の「処理」のために.wavのタイミングに関する情報を取得する必要があります。

私の英語と私の問題の悪い説明について申し訳ありませんが、問題は私が非常に単純だと思い、すべてがそれを理解することです。そうでない場合は、問題についてもう一度説明します:) ^^ ..

4

1 に答える 1

4

私はC++とSAPI5.1を使用して音声を合成し、それに応じて仮想キャラクターに唇を動かさせました。これは、visemesで動作するいくつかのコードです。http://msdn.microsoft.com/en-us/library/ms720164(v=vs.85).aspxのドキュメントによると、音素は。に置き換える以外は同じように機能SPEI_VISEMESPEI_PHONEMEます。

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);
}
于 2012-05-08T17:50:59.870 に答える