Что является правильным способом для «синхронизации» фонемы в SAPI TTS (c #) ??(SpVoice.Phoneme () -> streamPosition) - PullRequest
0 голосов
/ 29 января 2012

У меня есть следующая «проблема» в моем приложении, я пишу приложение, где кто-то напишет текст, SAPI TTS переведет его в речь, а затем я буду работать с выходным WAV. Что мне нужно, так это информация о фонемах (где в выходном WAV есть какая-то фонема, как долго голос говорит и т.д.) .. Хорошо, я использовал SpVoice.Phoneme () и добавил обработчик для фонем. Хорошо, теперь я могу получить продолжительность и т. Д., Но в SpVoice.Phoneme () это атрибут StreamPosition, но я не знаю, что это значит ..

от MSDN:

StreamPosition
Положение символа в выходном потоке, с которого начинается фонема.

Я не понимаю, имеют ли они в виду "байтовую" позицию в выходном WAV (на котором байт является фонемой) .. или миллисекундное время в выходном WAV .. или что это значит ??

Например, для текста:

Это высоко. Это низко. Это быстро. Это медленно.

Я получаю значения StreamPositions:

Позиция: 0
Позиция: 120
Позиция: 2562
....
Позиция: 143798
Позиция: 147874
Должность: 151950

Выходной WAV-файл имеет 5,377098 секунд, а последний фонем "оу" сообщается примерно в 4,734 с. Выходной файл WAV имеет 237 568 байт. Таким образом, значение атрибута StreamPosition "147874", вероятно, не является байтом, с которого начинается фонема. То же самое для «синхронизации» (в мс, потому что у WAV есть 5.3 с, но 151950 мс - 151 950 с .. так что это закрыто ..).

Так что такое StreamPosition? (что означает значение в StreamPosition?)

Мне действительно нужно поймать точное время, когда начнется фонема. Я попробовал это с DateTime.Now.Ticks / 10000. Когда пользователь нажимает кнопку для начала перевода TTS, я сохраняю это значение даты и времени, а когда какой-то обработчик перехватывает какую-то фонему, я снова ловлю это значение. И тогда я получу значение с currTime-startTime. Но этот «метод» не так точен. Всегда есть некоторые расхождения. Есть ли у SpVoice.Phoneme () какой-нибудь «метод» или что-то, чтобы получить точную информацию о времени начала фонемы? Если нет, есть ли лучший способ получить точное время в мс?

прошу прощения за мой английский и действительно спасибо за все ответы и советы ..

Ответы [ 2 ]

1 голос
/ 30 января 2012

хорошо, я отвечу сам .. Мой профессор бакалавров прислал мне какой-то код на C ++, который он написал .. Я прочитал его последние 2 дня, и теперь я вижу, насколько я глуп.

так я отвечу ..

атрибут StreamPosition действительно «кусает» позицию в выходном потоке (вероятно, WAV).

Если вы хотите узнать позицию миллисекунды в потоке вывода, вам нужно написать что-то вроде:

(интермедиат) StreamPosition / (двойной) wavFileFormat_samplesPerSec / ((двойной) wavFileFormat_BitsPerSample / 8)

поэтому вам нужно найти информацию о outputStream, такую ​​как bitsPerSample, SamplesPerSec, и вы получите время в миллисекундах.

0 голосов
/ 29 января 2012

1) Я не уверен, как вы сохраните вывод в файл WAV, но размер файла 237 568 байт больше, чем обычно (, если частота дискретизации составляет 16 кГц ), как размер файла для WAV 5,377098 секундфайл

равен 5,377098 * 16000 * 2 = 172067 байт + заголовок (44 байта)

, поэтому, я думаю, ваш файл WAV также содержит событие фонемы.

2) TTSПотратьте время на генерацию вывода, чтобы вы не смогли рассчитать время таким образом, я предлагаю вам:

2.1) записать событие фонемы, как вы уже могли это сделать в 1

You can also refer to Windows SDK 

C: \Программные файлы \ Microsoft SDKs \ Windows \ v7.1 \ Samples \ winui \ speech \ ttsapplication

           if (SUCCEEDED(hr))
        {
        //  OriginalFmt.WaveFormatExPtr()->nSamplesPerSec;
            hr = SPBindToFile( m_szWFileName, SPFM_CREATE_ALWAYS, &cpWavStream, &OriginalFmt.FormatId(), OriginalFmt.WaveFormatExPtr(),SPFEI_ALL_TTS_EVENTS); 
        }
        if( SUCCEEDED( hr ) )
        {
            // Set the voice's output to the wav file instead of the speakers
            hr = m_cpVoice->SetOutput(cpWavStream, TRUE);

        }

2.2) Синхронизация с другим событием, таким как запуск потока <= Я не уверен в точном названии. </p>

в Windows SDK:

    while (m_cpVoice->GetEvents(1, &event, &ul) == S_OK) 
        { 
            if (event.eEventId == SPEI_VISEME) 
            { 
                printf("v: %i\'",event.lParam); // viseme 
                printf("t: %i\'",event.wParam); // duration of viseme 
            } 
            else if (event.eEventId == SPEI_END_INPUT_STREAM) 
            { 

            } else if (event.eEventId == SPEI_START_INPUT_STREAM)
            {
            }
        }

Но код не в C #

...