System.Speech.Synthesis.SpeechSynthesizerを使用してテキストを音声に変換しています。また、Microsoft の貧血に関するドキュメント (私のリンクを参照してください。コメントやコード例はありません) のために、2 つの方法の違いを理解するのに苦労しています。
SetOutputToAudioStream と SetOutputToWaveStream。
これが私が推測したものです:
SetOutputToAudioStream は、ストリームと、wave ファイルの形式 (1 秒あたりのサンプル数、1 秒あたりのビット数、オーディオ チャネルなど) を定義する SpeechAudioFormatInfo インスタンスを受け取り、ストリームにテキストを書き込みます。
SetOutputToWaveStream は、ストリームだけを受け取り、16 ビット、モノラル、22kHz、PCM ウェーブ ファイルをストリームに書き込みます。SpeechAudioFormatInfo を渡す方法はありません。
私の問題は、 SetOutputToAudioStream が有効なウェーブ ファイルをストリームに書き込めないことです。たとえば、ストリームを System.Media.SoundPlayer に渡すと、InvalidOperationException (「ウェーブ ヘッダーが壊れています」) が発生します。ストリームをディスクに書き込んで WMP で再生しようとすると、「Windows Media Player はファイルを再生できません...」というエラーが表示されますが、SetOutputToWaveStream によって書き込まれたストリームは両方で正しく再生されます。私の理論は、SetOutputToAudioStream が (有効な) ヘッダーを書き込んでいないというものです。
奇妙なことに、SetOutputTo*Blah* の命名規則には一貫性がありません。SetOutputToWaveFile は SpeechAudioFormatInfo を受け取りますが、SetOutputToWaveStream は受け取りません。
SetOutputToAudioStream や SetOutputToWaveStream ではできないことですが、8kHz、16 ビット、モノラル ウェーブ ファイルをストリームに書き込めるようにする必要があります。SpeechSynthesizer とこれら 2 つの方法について洞察を持っている人はいますか?
参考までに、いくつかのコードを次に示します。
Stream ret = new MemoryStream();
using (SpeechSynthesizer synth = new SpeechSynthesizer())
{
synth.SelectVoice(voiceName);
synth.SetOutputToWaveStream(ret);
//synth.SetOutputToAudioStream(ret, new SpeechAudioFormatInfo(8000, AudioBitsPerSample.Sixteen, AudioChannel.Mono));
synth.Speak(textToSpeak);
}
解決:
@Hans Passantに感謝します。これが私が現在使用しているものの要点です:
Stream ret = new MemoryStream();
using (SpeechSynthesizer synth = new SpeechSynthesizer())
{
var mi = synth.GetType().GetMethod("SetOutputStream", BindingFlags.Instance | BindingFlags.NonPublic);
var fmt = new SpeechAudioFormatInfo(8000, AudioBitsPerSample.Sixteen, AudioChannel.Mono);
mi.Invoke(synth, new object[] { ret, fmt, true, true });
synth.SelectVoice(voiceName);
synth.Speak(textToSpeak);
}
return ret;
私の大まかなテストでは、リフレクションを使用するのは少し厄介ですが、ファイルをディスクに書き込んでストリームを開くよりはましですが、うまく機能します。