Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixing two audio samples from MP3 files

Tags:

c#

audio

I am having problem mixing two different audio samples into one by simply adding the bytes of both audio samples.

After below process when I try to open mixed.mp3 file in media player it says:

Windows Media Player encountered a problem while playing the file.

Here is the code I'm using to mix the audio files:

byte[] bytes1,bytes2,final;
int length1,length2,max;

// Getting byte[] of audio file
using ( BinaryReader b = new BinaryReader(File.Open("background.mp3" , FileMode.Open)) )
{
    length1 = (int)b.BaseStream.Length;
    bytes1 = b.ReadBytes(length1);
}

using ( BinaryReader b = new BinaryReader(File.Open("voice.mp3" , FileMode.Open)) )
{
    length2 = (int)b.BaseStream.Length;
    bytes2 = b.ReadBytes(length2);
}

// Getting max length
if(length1 > length2){
    max = length1;
}else{
    max = length2;
}

// Initializing output byte[] of max length
final = new byte[max];

// Adding byte1 and byte2 and copying into final
for (int i=0;i<max;i++)
{
    byte b1 , b2;

    if(i < length1){
        b1 = bytes1[i];
    }else{
        b1 = 0;
    }

    if ( i < length2 ){
        b2 = bytes2[i];
    }
    else{
        b2 = 0;
    }

    final[i] = (byte)(b1 + b2);
}

// Writing final[] as an mp3 file
File.WriteAllBytes("mixed.mp3" , final);

Note: I tried to mix two same files and it worked, that is, the media player didn't throw any errors and played it correctly.

like image 713
TaLha Khan Avatar asked Oct 04 '15 19:10

TaLha Khan


1 Answers

This is mostly likely due to the fact that you aren't decoding the MP3 files before you mix them. And you're "just adding" the samples together, which is going to result in clipping; you should first use a library to decode the MP3 files to PCM, which will then allow you to mix them.

To correctly mix the samples you should be doing:

final[i] = (byte)(b1 / 2 + b2 / 2);

Otherwise your calculations will overflow (also, I'd generally recommend normalising your audio to floats before manipulating them). It should also be noted that you're mixing all the bytes in the MP3 files, i.e., you're messing with the headers (hence WMP refusing to play your "Mixed" file). You should only mix the actual audio data (the samples) of the files, not the entire file.

I've provided a (commented) working example1 using the NAudio library (it exports the mixed audio to a wav file to avoid further complications):

// You can get the library via NuGet if preferred.
using NAudio.Wave;

...

var fileA = new AudioFileReader("Input path 1");

// Calculate our buffer size, since we're normalizing our samples to floats
// we'll need to account for that by dividing the file's audio byte count
// by its bit depth / 8.
var bufferA = new float[fileA.Length / (fileA.WaveFormat.BitsPerSample / 8)];

// Now let's populate our buffer with samples.
fileA.Read(bufferA, 0, bufferA.Length);

// Do it all over again for the other file.
var fileB = new AudioFileReader("Input path 2");
var bufferB = new float[fileB.Length / (fileB.WaveFormat.BitsPerSample / 8)];
fileB.Read(bufferB, 0, bufferB.Length);

// Calculate the largest file (simpler than using an 'if').
var maxLen = (long)Math.Max(bufferA.Length, bufferB.Length);
var final = new byte[maxLen];

// For now, we'll just save our mixed data to a wav file.
// (Things can get a little complicated when encoding to MP3.)
using (var writer = new WaveFileWriter("Output path", fileA.WaveFormat))
{
    for (var i = 0; i < maxLen; i++)
    {
        float a, b;

        if (i < bufferA.Length)
        {
            // Reduce the amplitude of the sample by 2
            // to avoid clipping.
            a = bufferA[i] / 2;
        }
        else
        {
            a = 0;
        }

        if (i < bufferB.Length)
        {
            b = bufferB[i] / 2;
        }
        else
        {
            b = 0;
        }

        writer.WriteSample(a + b);
    }
}

1 The input files must be of the same sample rate, bit depth and channel count in order for it to work correctly.

like image 118
Sam Avatar answered Sep 21 '22 06:09

Sam