wr93_
wr93_

Reputation: 150

Recording audio with NAudio and writing to a file when microphone input goes silent

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

Answers (1)

Bob C
Bob C

Reputation: 391

You can try the following:

  • Handle the RecordingStopped event from the NAudio wave device.
  • Create an Event or Semaphore or some other synchronization primitive at the class level.
  • When the RecordingStopped handler is triggered, kick the synchronization primitive.
  • Before you main method exits, just do a 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

Related Questions