Fixing the Microphone Audio cut-off issue in Windows Phone 7 Silverlight.

Thanks to some samples online it’s relatively straightforward to access the Microphone from a Silverlight application on Windows Phone 7. However when using these samples I noticed that sometimes the last half second of audio wasn’t

Getting Started

  • First add a reference to Microsoft.Xna.Framework to your Silverlight application. Words cannot describe how much this rubs me the wrong way, why it’s not part of the System namespaces or a separate shared Microsoft assembly is beyond me.
  • Add the dispatcher timer for XNA as described in this blog post.
  • Add two buttons to a page (Start and Stop). Call the StartRecording and StopRecording methods in the appropriate click event handlers.
 private bool isRecording;
 private MemoryStream ms;
 private readonly  Microphone mic = Microphone.Default;
 private byte[] buffer;
 
 private void StartRecording()
 {
     int bufferSize = mic.GetSampleSizeInBytes(mic.BufferDuration);
     this.buffer = new byte[bufferSize];
     mic.BufferReady += this.MicrophoneBufferReady;
     SoundEffect.MasterVolume = 1.0f;
 
     if (ms != null)
     {
         ms.Close();
     }
 
     ms = new MemoryStream();
     mic.Start();
     this.isRecording = true;
 }
 
 private void MicrophoneBufferReady(object sender, EventArgs e)
 {
     int bytesRead = 0;
     while ((bytesRead = mic.GetData(buffer, 0, buffer.Length)) > 0)
     {
         ms.Write(buffer, 0, bytesRead);
     }
 
     if (!this.isRecording)
     {
         ms.Flush();
         mic.Stop();
     }
 }
 
 private void StopRecording()
 {
     if (mic.State != MicrophoneState.Stopped)
     {
         // Calling stop here would stop receiving before  
         // the last buffer was complete. 
         //// mic.Stop(); 
         this.isRecording = false ;
     }
 }
 

Fixing the Audio cut-off issue.

The problem is that as buffers are being pushed to your application, the user pushes the stop button. Calling mic.Stop() immediately causes the buffers to stop being sent to your application and the last buffer that hadn’t completed is lost (leaving the audio chopped off).

The easiest fix for this is to have the Stop button request that the next buffer be the last to be recorded simply by setting a flag this.isRecording = false; and the event handler checks it after processing the last buffer. Viola! Problem solved.

Update: Added a link to blog regarding XNA dispatcher.

Advertisements
  1. #1 by Tom on October 12, 2011 - 7:40 am

    Thanks for the post! This does raise a question though. With this implementation, if a user keeps talking after hitting the stop button wouldn’t the microphone keep recording?

    • #2 by flatlinerdoa on October 12, 2011 - 8:23 am

      I had considered that, but the buffer is small enough that most users won’t notice it running over by a half second (better than chopping them off mid sentence). If it was really important you could split the last buffer after it has been captured

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: