Saving Recorded Audio to IsolatedStorage
So, after the Windows Phone 7 Developer Launch events, I've had several questions about how someone should store audio captured from the microphone for later playback. I said IsolatedStorage was the way to do it, but I left it to the attendees to figure it out.
It turns out some folks were having a little difficulty figuring it out, so here's a little cheater code for you.
This is a very simple bit of code that does three things... one, it allows you to record audio... two, it allows you to save that audio in IsolatedStorage and three, it allows you to play that audio back from IsolatedStorage.
I was going to write a tremendously long blog post about how to do this... however, the code is already commented very well... so here are the three important methods instead (plus the delegate handler.) :-)
private void startBtn_Click(object sender, RoutedEventArgs e)
{
// Don't start if we are already recording
if (recording == false)
{
// We're recording 1/10th of a second buffers at a time
microphone.BufferDuration = TimeSpan.FromMilliseconds(100);
// Here we size our byte array to hold the audio
buffer = new byte[microphone.GetSampleSizeInBytes(microphone.BufferDuration)];
// This is our delegate handler for when the buffer get's full
microphone.BufferReady += new EventHandler<EventArgs>(microphone_BufferReady);
// yep... we're recording now!
recording = true;
}
// Activate the Microphone
microphone.Start();
}
// This is our delegate (event) handler for when the buffer get's full
void microphone_BufferReady(object sender, EventArgs e)
{
// copy the microphone data into our buffer
microphone.GetData(buffer);
// tell the dispatcher to run this
this.Dispatcher.BeginInvoke(() =>
{
// copy it to our stream (remember, we need the stream to pass to the audio player)
stream.Write(buffer, 0, buffer.Length);
}
);
}
private void stopBtn_Click(object sender, RoutedEventArgs e)
{
//ok user doesn't want to record anymore
if (microphone.State == MicrophoneState.Started)
{
// so, if we were recording, we're not going to be after this line!
microphone.Stop();
// ok... no longer recording
recording = false;
}
// ok, here is where we store the file
// first, we grab the current apps isolated storage handle
IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
// we give our file a filename
string strSaveName = "MyRecording.wav";
// if that file exists...
if (isf.FileExists(strSaveName))
{
// then delete it
isf.DeleteFile(strSaveName);
}
// now we set up an isolated storage stream to point to store our data
IsolatedStorageFileStream isfStream =
new IsolatedStorageFileStream(strSaveName,
FileMode.Create, IsolatedStorageFile.GetUserStoreForApplication());
// tell it to actually write it out (remember, it's just raw data)
isfStream.Write(stream.ToArray(), 0, stream.ToArray().Length);
// ok, done with isolated storage... so close it
isfStream.Close();
}
// magic method
private void playBtn_Click(object sender, RoutedEventArgs e)
{
// again, grab the current apps isolated storage
IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
// yep... we want to play the same file we recorded
string strFileName = "MyRecording.wav";
// let's reverse what we did earlier... so we still need to get a
// file stream from isolated storage... but it's read mode
IsolatedStorageFileStream isfStream =
new IsolatedStorageFileStream(strFileName,
FileMode.Open, IsolatedStorageFile.GetUserStoreForApplication());
// remember, our data is raw, so we need to create a new buffer again
// to hold it (big enough to hold everything)
byte[] b = new byte[isfStream.Length];
// now we copy our file back in to our buffer
isfStream.Read(b, 0, b.Length);
// then we can pass it into our sound effect object...
// but tell it current samplerate and audio channels from the current hardware
// NOTE: if you wanted to get adventerous and have a mechanism where you play these on a different machine,
// you'll also need to encode the samplerate and audiochannels in your file store and restore them as well
// because those settings might be different for a different piece of hardware (phone)
// luckily, since we're using the same hardware, the settings won't change
SoundEffect se = new SoundEffect(b.ToArray(), microphone.SampleRate, AudioChannels.Mono);
// lastly... a miracle occurs
se.Play();
}
Note, the form is really simple... it looks like this.
The only other thing I had to do was follow the instructions to hook up the XNA Dispatcher to Silverlight here.
https://www.silverlightshow.net/items/Exploring-Silverlight-XNA-integration-on-Windows-Phone-7.aspx
Naturally, I've attached the code to this post... Have fun!
Bill
Comments
Anonymous
February 20, 2014
Really helpful code but in windows phone 8 it calls debugger while invoking microphone.Start().. if you have any solution for that please share it.. My mail id is shrenikshah26@yahoo.com Again thanx..Anonymous
August 10, 2014
Very helpful post. It helped me a lot. ThanksAnonymous
September 02, 2014
Hi , i am trying to post recorded audio file to server using rest service but after sending file to server that file is not playing. please help me Best regards Santosh