开发者

How to use NAudio to join 3 wav files into single file with 3 channels in C#?

开发者 https://www.devze.com 2023-03-26 00:45 出处:网络
Using C# and NAudio, I have have three wave files I would like to join into a single wave file having three channels, each corresponding to one of the three input files. Furthermore, I would like the

Using C# and NAudio, I have have three wave files I would like to join into a single wave file having three channels, each corresponding to one of the three input files. Furthermore, I would like the audio clip from each wave file to begin at a different point in the final stream. For example, if the lengths of the three wave files are 3 sec., 5 sec. and 2 sec., respectively, the output wave file would be 10 seconds long and...

  • channel 1 contains the 3 seconds of sound from file 1 follow开发者_StackOverflowed by 7 seconds of silence.

  • channel 2 contains 3 seconds of silence followed by the 5 seconds of sound from file 2 followed by 2 seconds of silence.

  • channel 3 contains 8 seconds of silence followed by the 2 seconds of sound from file 3.

I have been experimenting by creating a WaveChannel32 instance for each file and then using the WaveOffsetStream class, but I'm new to this sort of thing and I'm not having much success.

Anyone have any suggestions?


You would do this by writing your own custom IWaveProvider/WaveStream whose output WaveFormat has three channels. It holds a reference to each of your three input files. Then, in the Read method, it works out the number of samples requested, and reads the appropriate number from each source file. The samples then need to be interleaved - one from first file, one from second, one from third. To delay you simply put zeroes in.

Here's some untested example code that interleaves from various source files (must all be of same bit depth and sample rate) which will hopefully point you in the right direction:

int Read(byte[] buffer, int offset, int bytesRequired)
{
    int bytesPerSample = this.WaveFormat.BitsPerSample / 8;
    int samplesRequired = bytesRequired / bytesPerSample;
    int channels = this.WaveFormat.Channels; // 3
    int samplesPerChannel = samplesRequired / channels;
    byte[] readBuffer = new byte[samplesPerChannel * bytesPerSample];
    for (int channel = 0; channel < channels; channel++)
    {
        int read = inputs[channel].Read(readBuffer, 0, samplesPerChannel * bytesPerSample);
        int outOffset = offset + channel * bytesPerSample;
        for (int i = 0; i < read; i += bytesPerSample)
        {
             Array.Copy(readBuffer, i, buffer, outOffset, bytesPerSample);
             outOffset += channels * bytesPerSample;
        } 
    }
}

To keep the code from becoming overly complicated, you could do your silence insertion by creating another derived IWaveProvider / WaveStream, whose Read method returned the appropriate amount of silence, before then returning the real data from the input file. This can then be used as an input to your interleaving WaveStream.

0

精彩评论

暂无评论...
验证码 换一张
取 消