Search code examples
c#audionaudio

How To Mix two bytes[] audio Chunk with NAudio to retrieve one mixed byte[]


I’m new with NAudio and I need to achieve following:

I have a sip Event that return to me an uint rtp buffer that I convert in byte[] Chunk with following code:

rtpChunk = new byte[buflen];
Marshal.Copy(buf, rtpChunk, 0, buflen);

I have one other bytes[] chunk of background music.

var backChunk = new byte[buflen];
Array.Copy(bot.BackgroundBuffer, bot.BackgroundBufferIndex, backChunk, 0, buflen);

I need to mix together and retrieve the mixed chunk in byte[] and send back as uint rtp packet with following code:

Marshal.Copy(mixedChunk, 0, buf, buflen);

So how can I achieve with NAudio:

byte[] mixedChunk = MixChunks(rtpChunk, backChunk);

P.S: The sample Rate, Bits, Channel are equals for bought chunks:

8000, 16, 1

Thank you for help, Piercarlo


Solution

  • Dears, thanking for suggestions, I searched and I adapted some source code found on NAudio github repository to achieve my goal, so I post the solution that is working, may be will be usefull for some other else.

    I premise that this code is handling only Raw Audio bytes, if you want to save the result on a ".wav" file you need to add the Header.

    Method is the following:

    public static byte[] MixBuffers(int count, params byte[][] bSources)
    {
        byte[] buffer = new byte[count];
        int offset = 0;
        byte[] sourceBuffer = new byte[count];
        List<Stream> sources = new();
        foreach (var chunk in bSources)
            sources.Add(new MemoryStream(chunk));
        int outputSamples = 0;
        sourceBuffer = BufferHelpers.Ensure(sourceBuffer, count);
        lock (sources)
        {
            int index = sources.Count - 1;
            while (index >= 0)
            {
                var source = sources[index];
                int samplesRead = source.Read(sourceBuffer, 0, count);
                int outIndex = offset;
                for (int n = 0; n < samplesRead; n++)
                    if (n >= outputSamples)
                        buffer[outIndex++] = sourceBuffer[n];
                    else
                        buffer[outIndex++] += sourceBuffer[n];
                outputSamples = Math.Max(samplesRead, outputSamples);
                index--;
            }
        }
        foreach (var source in sources)
            source.Dispose();
        return buffer;
    }