C # (C ++) SAPI - TTS - как получить время речи для читаемого текста - PullRequest
2 голосов
/ 14 января 2012

Пожалуйста, кто-нибудь может мне помочь?Я ищу пример того, как я могу получить информацию о речевом тексте в TTS через SAPI (я программирую свое приложение на C #, но это не нужно, SAPI такой же в C ++ и т. Д.) Информация, которая мне нужна, например:напишите в текстовом поле:

"Это текст" ..

tts.Speak ("Это текст"); // это "прочитает" это ..

хорошо, хорошо ... но мне тоже нужно получить информацию о "времени" ..

например:

«Th» (первый звук (фонема) «This») был «прочитан» в 0,01 мс ..

«i» (первый звук «is») был «прочитан»через 0,5 мс ..

«e» (второй звук «Текст») был «прочитан» в 1,02 мс ..

при сохранении файла .wav, созданного SAPIМне нужно получить информацию о времени в .wav для последующей «обработки» файла wav.

Извините за мой английский и извините за плохое описание моей проблемы, но проблема, я думаю, очень простаи все это поймут.Если нет, я попытаюсь описать проблему снова :) ^^ ..

1 Ответ

4 голосов
/ 08 мая 2012

Я использовал C ++ и SAPI 5.1 для синтеза речи и заставил виртуального персонажа соответственно двигать губами. Вот код, который работает с висемами. Согласно документации на http://msdn.microsoft.com/en-us/library/ms720164(v=vs.85).aspx, фонемы работают так же, за исключением замены SPEI_VISEME на SPEI_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);
}
...