Reputation: 557
I might be wrong on this, but it appears that my WAV file in NAudio is playing asynchronously, and if I call it from a library, I can hear the WAV start, but it exits (and stops playing) almost immediately.
If I run it from a Form (which stays open) it is fine. But if I try to run it from code as a background thread, I only hear a small fragment in the beginning. It SEEMS like the method is exiting before the sound is finished playing.
I am using the Text To Speech Synthesizer to create the WAV on a Memory stream:
SpeechSynthesizer m_speechSynth = new SpeechSynthesizer();
m_speechSynth.Volume = 100;
m_speechSynth.Rate = 2;
MemoryStream waveStream = new MemoryStream();
m_speechSynth.SetOutputToWaveStream(waveStream);
m_speechSynth.Speak(txtToRead);
m_speechSynth.SetOutputToNull();
waveStream.Position = 0; // reset counter to start
That works fine. I then create a class that I wrapped around NAudio:
VoiceThroughNetAudio netAudio = new VoiceThroughNetAudio(waveStream, "WAV");
I'm trying to keep the code sample here easy to follow... but what this class does is simply initializes things, and gives me a higher level of control to do the main things on an NAudio player... Inside the VoiceThroughNetAudio constructor,
First I create a reader Stream from the MemStream:
readerStream = new WaveFileReader(memStream);
readerStream = WaveFormatConversionStream.CreatePcmStream(readerStream);
readerStream = new BlockAlignReductionStream(readerStream);
And attach a Volume Control (so I can amplify it):
_volumeStream = new WaveChannel32(Reader);
This all works fine when I call it from my WinForm Code:
MemoryStream waveStream = new MemoryStream();
ReadStringAmplified(readTextField.Text, waveStream); // TTS to waveStream
VoiceThroughNetAudio PlaySound = new VoiceThroughNetAudio (waveStream, "WAV");
PlaySound.Volume = 9;
PlaySound.Play();
But when I move this code into the Voice class instead, the sound STARTS to play, and then stops (almost immediately). Like it is starting an event and then exiting before the sound finishes? If so, is there a good way of making the method wait until the sound is finished? (I tried putting a while loop in and check the state, but this just ends up going into the while loop for an infinite period (commented out here...)
Here is how the code looks when I move it to the Voice Class. If I instantiate it from the form, and run it all there, and I get the truncated sound:
SpeechSynthesizer m_speechSynth = new SpeechSynthesizer();
m_speechSynth.Volume = 100;
m_speechSynth.Rate = 2;
MemoryStream waveStream = new MemoryStream();
m_speechSynth.SetOutputToWaveStream(waveStream);
m_speechSynth.Speak(txtToRead);
m_speechSynth.SetOutputToNull();
waveStream.Position = 0; // reset counter to start
VoiceThroughNetAudio netAudio = new VoiceThroughNetAudio(waveStream, "WAV");
netAudio.Volume = 9;
TimeSpan ts = netAudio.TotalDuration;
string len = ts.Milliseconds.ToString();
netAudio.Play();
//VoiceThroughNetAudio.PlayBackState chkState = netAudio.State;
//while (netAudio.State != VoiceThroughNetAudio.PlayBackState.Stopped)
//{
// chkState = netAudio.State;
//}
It seems like I am missing something simple, but I can't seem to get this to work in the Voice Class, only from the Form.
Upvotes: 0
Views: 1412
Reputation: 49482
Most likely explanations for your problem are:
MemoryStream
that is still being written toTry subscribing to the PlaybackStopped
event of your IWavePlayer
to see when and why it is firing (it can contain an exception if there is a problem).
Also, I very much doubt you need a WaveFormatConversionStream
and a BlockAlignReductionStream,
so simplify your code by removing those.
Upvotes: 1