What to do with an audio recording using the microphone on Windows Phone 7?

Most of the examples that you see for working with the microphone on Windows Phone 7 usually take the resulting byte array and either play it back (using the XNA audio namespace) or save it in its current form to IsolatedStorage. Unfortunately, the byte array isn’t much use by itself as it can’t be played back directly using say Media player. What you need to do is actually convert it to a wav file by wrapping the raw sample data in the appropriate header information. Following the WAV specifications you end up with a set of helper methods that look similar to the following:

using System;
using System.Text;

namespace MediaHelper
{
    public static class SoundUtilities
    {
        public class WaveFormat
        {
            public int Encoding { get; set; }
            public int AverageBytesPerSecond { get; set; }
            public int BlockAlign { get; set; }
            public int Channels { get; set; }
            public int SamplesPerSecond { get; set; }
        }

        public static byte[] ConvertRawSamplesToWav(
           byte[] samples, WaveFormat format)
        {
            var ascii = Encoding.UTF8;
            var byteArrayLength = 36 + samples.Length;
            var byteArray = new byte[byteArrayLength+10];
            var index = 0;

            // Specify that this is a RIFF file and the length of the file in bytes
            index += byteArray.CopyInto(index, ascii.GetBytes("RIFF"));
            index += byteArray.CopyInto(index, byteArrayLength.AsFixedByteArray(4));

            // Specify that this is a WAVE and start the format header
            index += byteArray.CopyInto(index, ascii.GetBytes("WAVE"));
            index += byteArray.CopyInto(index, ascii.GetBytes("fmt "));

            // Format header is fixed size of 16
            index += byteArray.CopyInto(index, (16).AsFixedByteArray(4));

            // Encoding: "1" for PCM
            index += byteArray.CopyInto(index, (format.Encoding).AsFixedByteArray(2));

            // Number of Channel
            index += byteArray.CopyInto(index, (format.Channels).AsFixedByteArray(2));

            // Samples per second
            index += byteArray.CopyInto(index, (format.SamplesPerSecond).AsFixedByteArray(4));

            // Average bytes per second
            index += byteArray.CopyInto(index, (format.AverageBytesPerSecond).AsFixedByteArray(4));

            // Block Align
            index += byteArray.CopyInto(index, (format.BlockAlign).AsFixedByteArray(2));

            // Bits per sample
            index += byteArray.CopyInto(index, ((8*format.AverageBytesPerSecond)/format.SamplesPerSecond).AsFixedByteArray(2));

            // The Samples themselves
            index += byteArray.CopyInto(index, ascii.GetBytes("data"));
            index += byteArray.CopyInto(index, samples.Length.AsFixedByteArray(4));
            index += byteArray.CopyInto(index, samples);

            return byteArray;

        }

        public static int CopyInto(this byte[] byteArray, int offset,byte[] bytes )
        {
            bytes.CopyTo(byteArray, offset);
            return bytes.Length;
        }

        public static byte[] AsFixedByteArray(this int number, int fixedByteArraySize)
        {
            int remainder, result;
            var returnarray = new byte[fixedByteArraySize];
                
            result = DivRem(number, 256, out remainder);

            if (result >= 1)
            {
                returnarray[0] = Convert.ToByte(remainder);
                var tmpArray = result.AsFixedByteArray(fixedByteArraySize - 1);
                tmpArray.CopyTo(returnarray, 1);
            }
            else 
            {
                returnarray[0] = Convert.ToByte(number);
            }
            return returnarray;
        }

        public static int DivRem(int a, int b, out int result)
        {
            result = a % b;
            return (a / b);
        }
    }
}

Of course, in order to make use of this code you need to know what the format of the raw samples are. This can be obtained by looking at the Microphone instance that you are using to record the audio. The following screenshot illustrates the various properties you will need to know

image

Leave a comment