I would like to use NAudio together with SpeechSynthesizer, but I cannot make it work without writing a .wav file to disk first.
I cannot figure out why, I tried both RAW wave data and wave with headers, see the following examples...
Example 1 - this works, but saves a .wav file
using (var synth = new SpeechSynthesizer())
{
synth.SetOutputToWaveFile(@".\Test.wav");
synth.Speak("This is sample text-to-speech output.");
synth.SetOutputToNull();
var reader = new WaveFileReader(@".\Test.wav");
var waveOut = new WaveOut();
waveOut.Init(reader);
waveOut.Play();
}
Example 2 - this also works, but still uses a file
using (var synth = new SpeechSynthesizer())
using (var stream = new MemoryStream())
{
synth.SetOutputToWaveStream(stream);
synth.Speak("This is sample text-to-speech output.");
using (var fileStream = File.Create(@".\Test.wav"))
{
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fileStream);
}
var reader = new WaveFileReader(@".\Test.wav");
var waveOut = new WaveOut();
waveOut.Init(reader);
waveOut.Play();
}
Example 3 - this don´t work, it just play a fraction of a second and stops
It´s on purpose that I use SetOutputToWaveStream to keep the RIFF header, to avoid setting wave format.
using (var synth = new SpeechSynthesizer())
using (var stream = new MemoryStream())
{
synth.SetOutputToWaveStream(stream);
synth.Speak("This is sample text-to-speech output.");
stream.Seek(0, SeekOrigin.Begin);
var reader = new WaveFileReader(stream);
var waveOut = new WaveOut();
waveOut.Init(reader);
waveOut.Play();
}
Example 4 - same result as example 3
This uses raw data and is a bit bulky.
using (var synth = new SpeechSynthesizer())
using (var stream = new MemoryStream())
{
synth.SetOutputToAudioStream(stream, new SpeechAudioFormatInfo(44100, AudioBitsPerSample.Sixteen, AudioChannel.Mono));
synth.Speak("This is sample text-to-speech output.");
stream.Seek(0, SeekOrigin.Begin);
IWaveProvider provider = new RawSourceWaveStream(stream, new WaveFormat(44100, 16, 1));
var waveOut = new WaveOut();
waveOut.Init(provider);
waveOut.Play();
}
I also tried using WasapiOut, but that was even worse.
You are just about there with Example 3. Call Flush
on your memory stream before repositioning to the start. Also, Play
only starts playing, so you need to either wait for playback to finish or move your WaveOut
instance to be outside the using
block. Otherwise it's just going to get garbage collected before it can get very far into playback.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With