tags:

views:

688

answers:

3

I need to mix two audio files. Audio 1 will be a static file and used to "tag" Audio 2. To be clear I'm talking about an audio tag not an ID3 tag.

There are two basic problems I can't wrap my head around.

1) How can I repeat Audio 1 when mixed with Audio 2 so that the result is the same length as Audio 2?

2) Audio 2 will be an MP3 and I don't want to re-encode it and possibly reduce it's quality.

Any libraries or ideas on how this can be done in C# will be much appreciated.

+2  A: 

You're going to have to decode the mp3 to a wave format, perform the mixing and then encode it back to an mp3 format.

Someone will have to point you to some mp3 libraries. I can help you with the actual mixing though.

It's kind of cool how this work actually. A sound file is just a bunch of amplitude samples recorded at a certain interval. This, for example, could be a sound:

0, 12, 128, 14, -1, -13, -128, -64, -32

Ok, it's a really short sound, but hang with me. Say I want to mix the above sound with this sound:

10, -12, -100, -150, -75, -25, -12, -0

This is the cool part, we just add the two arrays together:

10, 0, 28, -136, -76 ...

0 + 10 = 10 12 + -12 = 0 128 + -100 = 28 ...

The only thing you really need to watch out for is the fact that there are limits to the amplitudes you can store in a wave file. Most these days are 16-bit but you can still make 8-bit wave files. If your amplitudes exceed the limits of the wave file, you'll have to go as high or as low as you can and cap it off.

Anyway, that's the jist of it. The finer points, will need to be worked out.

Robert H.
Something else that should be taken into account when layering audio files of differing bit depths. If you try to blend an 8-bit file with a 16-bit file, you have greater precision in the 16-bit file. You'll need to either scale the 8-bit file up, or the 16-bit file down, before adding.
jrista
Indeed. This reminds me. Another element to mixing audio is volume. Each time you mix, you're basically adding volume. If your wave volume is pretty much maxed out (music often is), you'll have to loop through the original samples to find highest/lowest peak and then normalize the mixed audio to this peak. This means that you may want to use intermediate data type with more range (like a 32-bit integer) such that when you mix two really loud(?) sound samples, you don't end up truncating a lot of peaks. After normalizing, you can store the sound back in the 16/8 bit format.
Robert H.
+2  A: 

You can use NAudio to do this. Use the WaveFileReader class to make a WaveStream that can read from each of your files (the MP3 one would need to be converted to PCM first - see the use of Mp3FileReader in the NAudio demo code). Then I would make a derived WaveStream that loops round (i.e. in the Read method, when you get to the end of the source data, go back to the beginning).

Then mix them together, using the WaveMixerStream32. (they will need to be converted to 32 bit first - use the WaveChannel32 to do this). This class will also allow you to set the volume levels of each file. Finally, convert back to 16 bit using the Wave32To16Stream and then use the WaveFileWriter to make your final file. Then use LAME to convert to MP3.

Mark Heath
WaveChannel32 is giving me this error "Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection" whenever I try to use. Any ideas why? (more info on http://naudio.codeplex.com/Thread/View.aspx?ThreadId=79458)
J. Pablo Fernández
A: 

I would suggest the BASS Library. It does "mixing" as well as allow many formats to be played and also DSP like EQ/Fade/Compressor. http://un4seen.com/bass.html

Rick Ratayczak