Reputation: 150
I have these two functions written to record and write to a wave file using NAudio. I cannot find a tactic to stop the first function without executing the last line and going out of the local scope.
The audio_Rec method is called from the main function and audioSource_DataAvailable function executes when there is data buffered in the WaveInEvent. As I think, audioSource_DataAvailable function runs only within the scope of audio_Rec method and when the code comes to the last line of audio_Rec (below line),
Console.Write("Recording Starts...\n");
it goes out of the scope and next line of main function executes. (main is not mentioned). I want a method to hold out the audio_Rec method while recording audio until recording is stopped under the given condition in audioSource_DataAvailable function.
count and summation are public member variables.
audio_Rec method
public void audio_Rec()
{
audioSource = new WaveInEvent();
audioSource.DeviceNumber = 0;
audioSource.WaveFormat = new WaveFormat(16000, 16, 1);
audioSource.DataAvailable += new EventHandler<WaveInEventArgs>(audioSource_DataAvailable);
waveFile = new WaveFileWriter(@"d:/dev/csharp/wspeechrec/new_wave.wav", audioSource.WaveFormat);
audioSource.StartRecording();
Console.Write("Recording Starts...\n");
//Thread.Sleep(7000);
}
audioSource_DataAvailable function
void audioSource_DataAvailable(object sender, WaveInEventArgs e)
{
count++;
if (count%5 == 0)
{
if (summation < 150000) {
audioSource.StopRecording();
Console.Write("Recording Stopped!");
}
Console.WriteLine(count * 100 + "ms :"+summation);
summation = 0;
}
Console.WriteLine(count+" "+summation);
byte[] buf = new byte[e.BytesRecorded];
buf = e.Buffer;
int[] Ints = new int[e.BytesRecorded / 2];
for(int i=0;i<buf.Length;i+=2)
{
Ints[i/2] = BitConverter.ToInt16(buf, i);
}
int[] newInts = Ints.Select(x => Math.Abs(x)).ToArray();
summation = newInts.Sum();
if (waveFile != null)
{
waveFile.Write(e.Buffer, 0, e.BytesRecorded);
waveFile.Flush();
}
}
Free to disregard the algorithms in second function. They can be neglected. Any help is highly appreciated. Thanks
Upvotes: 0
Views: 1589
Reputation: 391
You can try the following:
RecordingStopped
event from the NAudio wave device.Event
or Semaphore
or some other synchronization primitive at the class level.RecordingStopped
handler is triggered, kick the synchronization primitive.WaitOne()
on that primitive.Your StopRecording
call in the DataAvailable
handler results in a call to the Stopped
handler, which triggers the Semaphore, which then wakes up your main thread so that it can exit.
Example (I'm partial to Semaphores, so that's what I'm using):
using System.Threading;
Semaphore AudioSync = new Semaphore(0, int.MaxValue);
public void audio_Rec()
{
audioSource = new WaveInEvent();
audioSource.DeviceNumber = 0;
audioSource.WaveFormat = new WaveFormat(16000, 16, 1);
// Register for the 'RecordingStopped' event.
audioSource.PlaybackStopped += this.audioSource_PlaybackStopped;
audioSource.DataAvailable += new EventHandler<WaveInEventArgs>(audioSource_DataAvailable);
waveFile = new WaveFileWriter(@"d:/dev/csharp/wspeechrec/new_wave.wav", audioSource.WaveFormat);
audioSource.StartRecording();
Console.Write("Recording Starts...\n");
// Now just wait for the "PlaybackStopped" event handler to signal completion.
AudioSync.WaitOne(); // <-------------------------------------
}
Stopped
event handler:
void audioSource_PlaybackStopped( object sender, StoppedEventArgs e )
{
// Wakes up the main thread.
AudioSync.Release();
}
Upvotes: 1