Scratchy Audio Fix


Audio In XNA

Recently I downloaded a few audio clips from Pond5, and there were problems! Not with the audio nor with Pond5, althought the audio was a bit pricey it is good quality. The problem came when I was trying to get them into my game content. I was trying to make a demo of 3D sound using multiple point sources, the textbook example “The Waterfall.” The first Issue I ran into was a simple of to solve, a bunch of the audio on Pond5 comes in 24bit format, so I needed to convert it to 16bit format, I used Voxengo r8brain, which makes the
conversion stupid simple, targeting(16bit, 48000khz). TakeawayXNA dynamic audio features expect the audio data to be 16-bit Integer-PCM, sample rate from 8000 Hz to 48000 Hz, mono or stereo [ref].
So now I have my audio in the right format, or so I thought…. I added the references in the content file loaded the assets started the tests, amnient was good dramaitic was good all the rest of my waterfall sounds, tranquil pond sounds etcetera… came thru the content pipeline as a mechanical scratiching or industrial electrical fence discharge (very similar to what I imagine it sounds like putting your ear to a large power conduction line.

VS.

o.k so how do we fix it? First we need a little more information…

XNA Audio Classes

Microsoft.Xna.Framework.Audio Microsoft.Xna.Framework.Media
SoundEffect
DynamicSoundEffect
SoundEffectInstance
Song

Sound Effect

Designed to optimize memory usage by allowing all
multiple simultaneous playing instances to share the source audio data while
still allowing each instance to have unique playback characteristics such as
pitch, volume, pan, or 3D position, and looping control. Each platform has limits on the
number of sounds playing simultaneously. An InstancePlayLimitException is thrown if this limit is exceeded.

Platform Number of sounds that can play simultaneously
Windows Phone 64
Xbox 360 300
Windows No limit

DynamicSoundEffect

There is a post on MSDN Blogs that talks about creating a sound effect dynamically from a stream (see below for more).

SoundEffectInstance

You can modify the volume, panning, and pitch of the SoundEffectInstance by setting the Volume, Pitch, and Pan properties.

Song

Basically gives you access to use Windows Medial Player type functionality, and has access to your media library. A downfall of using sons is that you are limited to being able to play only one at a time. AppHub has a good WP7 tutorial.

DynamicSoundStream

Using the post here I slopped together this class:

pub lic class DynamicSoundStream{
		DynamicSoundEffectInstance dynamicSound;
		int position;
		int count;
		byte[] byteArray;

		private DynamicSoundStream() { }
		public static DynamicSoundStream CreateFromStream(Stream waveFileStream) {

			BinaryReader reader = new BinaryReader(waveFileStream);

			int chunkID = reader.ReadInt32();
			int fileSize = reader.ReadInt32();
			int riffType = reader.ReadInt32();
			int fmtID = reader.ReadInt32();
			int fmtSize = reader.ReadInt32();
			int fmtCode = reader.ReadInt16();
			int channels = reader.ReadInt16();
			int sampleRate = reader.ReadInt32();
			int fmtAvgBPS = reader.ReadInt32();
			int fmtBlockAlign = reader.ReadInt16();
			int bitDepth = reader.ReadInt16();

			if (fmtSize == 18)
			{
				// Read any extra values
				int fmtExtraSize = reader.ReadInt16();
				reader.ReadBytes(fmtExtraSize);
			}

			int dataID = reader.ReadInt32();
			int dataSize = reader.ReadInt32();
			var ret = new DynamicSoundStream();
			ret.byteArray = reader.ReadBytes(dataSize);
			ret.dynamicSound = new DynamicSoundEffectInstance(sampleRate, (AudioChannels)channels);
			ret.count = ret.dynamicSound.GetSampleSizeInBytes(TimeSpan.FromMilliseconds(100));
			ret.dynamicSound.BufferNeeded += new EventHandler<EventArgs>(ret.DynamicSound_BufferNeeded);
			return ret;
		}
		public void DynamicSound_BufferNeeded(object sender, EventArgs e)
		{
			dynamicSound.SubmitBuffer(byteArray, position, count / 2);
			dynamicSound.SubmitBuffer(byteArray, position + count / 2, count / 2);

			position += count;
			if (position + count > byteArray.Length)
			{
				position = 0;
			}
		}
		public void Play() { this.dynamicSound.Play(); }
		public void Stop() { this.dynamicSound.Stop(); }
	}

It is not a fully complete class however when I run my scratchy electronic sample thru it, voilà I clearly have a babbeling brook… Yay!

Advertisements

About Larry Louisiana

I'm a Microsoft Partner Consultant.
This entry was posted in Computers and Internet, Game Development, Programming and tagged , , , . Bookmark the permalink.

One Response to Scratchy Audio Fix

  1. Pingback: Playing with Audio | Ely Bob's space

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s