A Windows* Store App Case Study – Recording Audio Notes and Playback for Healthcare (C#)

I’d like to share a useful example for recording audio in a Windows Store App.  Particularly, I will present an app that targets the enterprise healthcare sector.  Audio recordings can enable doctors to “attach” speech to notes for patients.  This aides doctors in the event that if their hands are occupied, they can simply use voice to make a recording or play it back with a single button click.  Also, when a doctor’s working with many patients, on-the-fly dictation makes it easier to track accurate medical records.  Thus, recorded notes serve as a great addendum to the traditional keyboard and mouse method.

This blog provides an example on how I implemented audio notes within a healthcare app.  The healthcare app already had the infrastructure for typing out notes and saving the changes to a database along with database retrieval.  C# and XAML were used for the healthcare app. 

To start, follow this great article that gives a basic rundown on how to record audio: 

http://visualstudiomagazine.com/articles/2013/03/21/audio-in-a-windows-store-app.aspx

I went ahead and followed the guide as it served to be the initial backbone for my solution.  I did need to make some small syntactic changes.  For example, I changed this:

var audioQualities = Enum.GetValues(typeof (AudioEncodingQuality)).Cast();

 

to this:

var audioQualities = Enum.GetValues(typeof(AudioEncodingQuality)).Cast<AudioEncodingQuality>();

 

Figure 1: Slight Cast Syntax Change***

 

Refer to this reference on casting if needed: http://msdn.microsoft.com/en-us/library/bb341406.aspx.

Then, for occurrences of Dispatcher.RunAsync, I had to make changes.  For example, I changed this:

await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>

 

to this:

await Window.Current.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>

 

Figure 2: Slight Dispatcher Syntax Change***

This reference discusses the slight syntax change: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/e01e59d9-920c-46aa-b84e-fdd4dca933d8/

 

Afterwards, I decided that I wanted to limit how long a recording could be so that our database wouldn’t get cluttered.  You can define a simple parameter as follows:

        //place a limit on recording length, in seconds

        private int MAX_RECORDING_LENGTH = 30;

 

        //invoked when the dispatcher timer fires

        private void TimerOnTick(object sender, object o)

        {

            _elapsedTime = _elapsedTime.Add(_timer.Interval);

 

            seconds_elapsed = _elapsedTime.Seconds;

 

            if (seconds_elapsed > MAX_RECORDING_LENGTH) //cut off the recording as it's too long

            {

              //stop recording via delegate here…

Figure 3: Limiting Recording Length***

 

Whenever recording is stopped, whether by exceeding the time limit or by user interaction, a delegated event is invoked to stop the recording session.  The reason I did this was because my view class was separate from the class containing this audio logic.  Delegates are useful for generically invoking functions across classes.  Just in case, here’s a good reference on delegates if needed: http://msdn.microsoft.com/en-us/library/vstudio/ms173171.aspx

 

Since I use a recording time limit, I must track elapsed time.  I needed to reset the elapsed time once recording has stopped just in case recording is repeated later.  Here is what I did:

 

//stops the recording

        public async Task<AUDIO_STATUS> stopRecording()

        {

            _timer.Stop();

 

            //clear any elapsed time in case recording will be invoked again

            _elapsedTime = _elapsedTime.Subtract(new TimeSpan(_elapsedTime.Hours, _elapsedTime.Minutes, _elapsedTime.Seconds));

Figure 4: Resetting the Elapsed Time***

 

At this point, audio recording functionality was complete.  One thing was missing though: saving recordings to the database, and retrieving them when needed.  In order to do this, some steps were followed:

Serializing and storing the audio on the database:

1)      Write the contents of the audio stream to a byte[] buffer

2)      Encode the string using base 64 conversion.  This essentially serializes the string as raw bytes that can then be stored onto the database

De-serializing the raw byte contents on the database and wrapping the bytes in an audio stream:

1)      Follow the previous steps in reverse

For the (de) serialization steps, please refer to the section "Encoding and decoding image buffers into/from base64 encoded strings" in the following article:

http://software.intel.com/en-us/articles/camera-usage-and-features-from-ios-to-windows-8-store-app

 

The last step: playback.  The best practice for playing back audio is using the MediaElement APIs.  Please refer to the following link:

http://msdn.microsoft.com/library/windows/apps/BR242926

 

Assuming the audio recording was saved to file “recording.mp3”, here is how you can play back the clip:

StorageFile file = await localFolder.GetFileAsync("recording.mp3");

var stream = await file.OpenAsync(FileAccessMode.Read);

 

MediaElement audio_note = new MediaElement();

 

//now, set the media element source to the audio file we created!

audio_note.SetSource(stream, file.ContentType);

audio_note.Play();

Figure 5: Playback***

That’s it!  Thanks for reading!  Let me know if there are any questions, comments, ideas, etc.

 

***This sample source code is released under the Microsoft Limited Public License (MS-LPL) and is released under the Intel OBL Sample Source Code License (MS-LPL Compatible)