什么是SAPI TTS(c#)中“定时”音素的正确方法? (SpVoice.Phoneme() - > streamPosition)

时间:2012-01-29 01:54:04

标签: c# timing sapi text-to-speech

我的应用程序中有下一个“问题”,我写应用程序,有人会写文本,SAPI TTS将其翻译成语音,接下来我将使用输出WAV。 我需要的是关于音素的信息(输出中的WAV是一些音素,声音说多长时间等等)。 好吧,我使用了SpVoice.Phoneme(),我为phonemes添加了处理程序。好的,现在我可以获得持续时间等。但是在SpVoice.Phoneme()中是属性StreamPosition但我不知道这意味着什么..

来自MSDN的

  

StreamPosition
  音素开始的输出流中的字符位置。

我不明白它们是否意味着输出WAV中的“字节”位置(在WHICH字节是音素)..或输出WAV的毫秒时间。或者是什么意思??

例如,对于文字:

  

这很高。这很低。这很快。这很慢。

我得到了StreamPositions值:

  

位置:0
  您的位置:120
  您的位置:2562
  ....
  您的位置:143798
  您的位置:147874
  位置:151950

输出WAV文件有5.377098秒,最后一个音素“ow”大约在4.734s中被告知。 输出WAV文件有237 568bytes ..因此属性StreamPosition“147874”的值可能不是开始音素的字节。 “定时”相同(以ms为单位,因为WAV有5.3s但151950ms是151,950s ......所以这是关闭的......)。

那么什么是StreamPosition?(什么意思是StreamPosition中的值?)

我真的需要抓住音素开始时的确切时间。我用DateTime.Now.Ticks / 10000试了一下。当用户点击按钮开始翻译TTS我保存这个日期时间值,当一些处理程序捕获一些音素时,我再次捕获该值。然后我将使用currTime-startTime获取值。但这种“方法”并不那么精确。总有一些分歧。有SpVoice.Phoneme()一些“方法”或什么来获得关于音素开始的时间的确切信息? 如果没有,是否有更好的方法可以在ms中获得更准确的时间?

为我的英语而且非常感谢所有答案和建议..

2 个答案:

答案 0 :(得分:1)

好吧,我会自己回答..我的单身汉教授用C ++给我发了一些他写的代码......我最近2天就知道了,现在我看到我有多愚蠢。

所以我会回答..

属性 StreamPosition 在输出流中可能是“咬人”位置(可能是WAV)。

如果您想知道输出流中的毫秒位置,您需要编写如下内容:

  

(INT)StreamPosition /(双)wavFileFormat_samplesPerSec /((双)wavFileFormat_BitsPerSample / 8)

所以你需要找到有关outputStream的信息,比如bitsPerSample,SamplesPerSec,你将获得毫秒的时间。

答案 1 :(得分:0)

1)我不确定如何将输出保存到wav文件,但文件大小 237 568bytes比正常大(,如果采样率为16khz ),作为5.377098秒wav文件的文件大小

是5.377098 * 16000 * 2 = 172067字节+标题(44字节)

所以,我认为你的wav文件也包含了phoneme事件。

2)TTS需要时间来生成输出,所以你不能以这种方式计时,我建议你:

2.1)记录你可能已经在1

中完成的音素事件
You can also refer to Windows SDK 

C:\ Program Files \ 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)其他事件的时间,例如流启动< =我对确切名称不太确定。

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#