Introduction
Professional Audio Recorder (PAR) is an audio recorder for Windows Phone 7. PAR uses the built-in microphone (via XNA) and the NAudio audio library to record and visualize audio.
NAudio
“NAudio is an Open Source .NET audio and MIDI library, containing dozens of useful audio related classes intended to speed the development of audio related utilities in .NET. It has been in development since 2001, and has grown to include a wide variety of features. While some parts of the library are relatively new and incomplete, the more mature features have undergone extensive testing and can be quickly used to add audio capabilities to an existing .NET application”
I have ported the parts from NAudio that I needed to help me write Wave files and visualize the audio data!
XNA in Silverlight
When using XNA audio services, a Silverlight program must call the static
FrameworkDispatcher.Update
method at approximately the same rate as the video refresh rate, which on Windows Phone 7 is approximately 30 times a second. There’s a description of how to do this in the article “Enable XNA Framework Events in Windows Phone Applications” within the XNA online documentation. In Professional Audio Recorder, the XNAAsyncDispatcher
class handles this job. This class is instantiated in the App.xaml file.
public class XNAAsyncDispatcher : IApplicationService
{
private DispatcherTimer frameworkDispatcherTimer;
public XNAAsyncDispatcher(TimeSpan dispatchInterval)
{
this.frameworkDispatcherTimer = new DispatcherTimer();
this.frameworkDispatcherTimer.Tick +=
new EventHandler(frameworkDispatcherTimer_Tick);
this.frameworkDispatcherTimer.Interval = dispatchInterval;
}
void IApplicationService.StartService(ApplicationServiceContext context)
{
this.frameworkDispatcherTimer.Start();
}
void IApplicationService.StopService()
{
this.frameworkDispatcherTimer.Stop();
}
void frameworkDispatcherTimer_Tick(object sender, EventArgs e)
{
FrameworkDispatcher.Update();
}
}
Recording Audio
To record audio, get the default microphone and setup the data buffers used to capture/store the audio. NAudio has an interface
, IWaveIn
, which abstracts away the Wave capturing; here is my implementation:
namespace PAR.Audio
{
using System;
using Microsoft.Xna.Framework.Audio;
using NAudio.Wave;
public class PhoneWaveIn : IWaveIn
{
readonly Microphone _mic;
byte[] _buffer;
public PhoneWaveIn()
{
_mic = Microphone.Default;
}
public void StartRecording()
{
_mic.BufferDuration = TimeSpan.FromSeconds(1);
_buffer = new byte[_mic.GetSampleSizeInBytes(_mic.BufferDuration)];
_mic.BufferReady += _mic_BufferReady;
_mic.Start();
}
void _mic_BufferReady(object sender, EventArgs e)
{
_mic.GetData(_buffer);
if (DataAvailable != null)
DataAvailable(this, new WaveInEventArgs(_buffer, _buffer.Length));
}
public void StopRecording()
{
_mic.Stop();
_mic.BufferReady -= _mic_BufferReady;
}
public event EventHandler<WaveInEventArgs> DataAvailable;
public void Dispose()
{
if (_mic.State == MicrophoneState.Started)
{
StopRecording();
}
}
}
}
Next, how do we save it to file? Again, NAudio to the rescue… NAudio provides a WaveFileWriter
that helps formatting all the data from the microphone in a proper Wave file and then stores it in a stream! On the phone, we will be storing the audio recordings in the isolated storage!
Visualizing the Audio
Currently, Professional Audio Recorder supports two visualization modes! The first one I will preview is the Incognito mode/visualization.
This mode/visualization is actually a hidden mode where you are trying to hide the fact that you are recording the conversation! It simulates the “normal” lock screen.
Next is the more traditional wave form visualization!
Here, we use more NAudio magic to visualize the actual audio data
Playback
Since all the recordings are stored on the phone in Isolated Storage, we can use the following helper method to play a file:
private void PlayFromIS(string filename)
{
Stream stream = new IsolatedStorageFileStream(filename, FileMode.Open,
IsolatedStorageFile.GetUserStoreForApplication());
var buffer = new byte[stream.Length];
stream.Read(buffer, 0, (int)stream.Length);
int sampleRate = Microphone.Default.SampleRate;
var se = new SoundEffect(buffer, sampleRate, AudioChannels.Mono);
SoundEffect.MasterVolume = 0.7f;
se.Play();
}
And that’s it!
Also Read