×
Namespaces

Variants
Actions
Revision as of 19:03, 9 October 2013 by kiran10182 (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Saving Microphone stream to wave format in Windows Phone

From Nokia Developer Wiki
Jump to: navigation, search

This article explains how to get audio input from the microphone, convert it to .wav format, and save it to IsolatedStorage.

WP Metro Icon File.png
WP Metro Icon Multimedia.png
WP Metro Icon WP8.png
SignpostIcon WP7 70px.png
Article Metadata
Tested with
Devices(s): Nokia Lumia 800
Compatibility
Platform(s): Windows Phone 7.5
Windows Phone 8
Windows Phone 7.5
Article
Keywords: WAV, format, Audio, saving, record, microphone
Created: galazzo (03 Sep 2012)
Last edited: kiran10182 (09 Oct 2013)

Introduction

As the microphone's stream buffer provide raw data we need to convert it into a well known file format before saving in order to allow users to play the recorded file everywhere. The easiest solution is to use the .wav file format.

Microphone Sample demonstrates how to get audio input from the microphone in a Silverlight for Windows Phone application. This project is used in this guide and we will be focused on saving process.

Note.pngNote: This article was created using un-attributed code samples from the Internet. Dmehers asserts the origin of this information is his blog post: Storing WP7 recorded audio as WAV format streams.


Saving into WAV format

As we use isolated storage we need to use the following namespaces:

using System.Windows;
using System.IO.IsolatedStorage;
using System.Windows.Resources;

Then add the following functions to your code:

private void SaveToIsolatedStorage()
{
// first, we grab the current apps isolated storage handle
IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
 
// we give our file a filename
string strSaveName = "myFile.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());
 
isfStream.Write(stream.ToArray(), 0, stream.ToArray().Length);
 
// ok, done with isolated storage... so close it
isfStream.Close();
}
 
public void UpdateWavHeader(Stream stream)
{
if (!stream.CanSeek) throw new Exception("Can't seek stream to update wav header");
 
var oldPos = stream.Position;
 
// ChunkSize 36 + SubChunk2Size
stream.Seek(4, SeekOrigin.Begin);
stream.Write(BitConverter.GetBytes((int)stream.Length - 8), 0, 4);
 
// Subchunk2Size == NumSamples * NumChannels * BitsPerSample/8 This is the number of bytes in the data.
stream.Seek(40, SeekOrigin.Begin);
stream.Write(BitConverter.GetBytes((int)stream.Length - 44), 0, 4);
 
stream.Seek(oldPos, SeekOrigin.Begin);
}
 
public void WriteWavHeader(Stream stream, int sampleRate)
{
const int bitsPerSample = 16;
const int bytesPerSample = bitsPerSample / 8;
var encoding = System.Text.Encoding.UTF8;
 
// ChunkID Contains the letters "RIFF" in ASCII form (0x52494646 big-endian form).
stream.Write(encoding.GetBytes("RIFF"), 0, 4);
 
// NOTE this will be filled in later
stream.Write(BitConverter.GetBytes(0), 0, 4);
 
// Format Contains the letters "WAVE"(0x57415645 big-endian form).
stream.Write(encoding.GetBytes("WAVE"), 0, 4);
 
// Subchunk1ID Contains the letters "fmt " (0x666d7420 big-endian form).
stream.Write(encoding.GetBytes("fmt "), 0, 4);
 
// Subchunk1Size 16 for PCM. This is the size of therest of the Subchunk which follows this number.
stream.Write(BitConverter.GetBytes(16), 0, 4);
 
// AudioFormat PCM = 1 (i.e. Linear quantization) Values other than 1 indicate some form of compression.
stream.Write(BitConverter.GetBytes((short)1), 0, 2);
 
// NumChannels Mono = 1, Stereo = 2, etc.
stream.Write(BitConverter.GetBytes((short)1), 0, 2);
 
// SampleRate 8000, 44100, etc.
stream.Write(BitConverter.GetBytes(sampleRate), 0, 4);
 
// ByteRate = SampleRate * NumChannels * BitsPerSample/8
stream.Write(BitConverter.GetBytes(sampleRate * bytesPerSample), 0, 4);
 
// BlockAlign NumChannels * BitsPerSample/8 The number of bytes for one sample including all channels.
stream.Write(BitConverter.GetBytes((short)(bytesPerSample)), 0, 2);
 
// BitsPerSample 8 bits = 8, 16 bits = 16, etc.
stream.Write(BitConverter.GetBytes((short)(bitsPerSample)), 0, 2);
 
// Subchunk2ID Contains the letters "data" (0x64617461 big-endian form).
stream.Write(encoding.GetBytes("data"), 0, 4);
 
// NOTE to be filled in later
stream.Write(BitConverter.GetBytes(0), 0, 4);
}

On function delegated to begin the record process include the call to WriteWavHeader() before the microphone.Start() function

private void recordButton_Click(object sender, EventArgs e)
{
...
stream.SetLength(0);
 
WriteWavHeader(stream, microphone.SampleRate);
 
// Start recording
microphone.Start();
...
}

After microphone.Stop() add the call to UpdateWavHeader and to SaveToIsolatedStorage

microphone.Stop();
UpdateWavHeader(stream);
SaveToIsolatedStorage();

Related links

This page was last modified on 9 October 2013, at 19:03.
264 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×