Как использовать NAudio, чтобы объединить 3 файла WAV в один файл с 3 каналами в C #? - PullRequest
3 голосов
/ 06 августа 2011

Используя C # и NAudio, у меня есть три волновых файла, которые я хотел бы объединить в один волновой файл с тремя каналами, каждый из которых соответствует одному из трех входных файлов.Кроме того, я хотел бы, чтобы аудиоклип из каждого волнового файла начинался в другой точке финального потока.Например, если длина трех волновых файлов составляет 3 с, 5 с.и 2 с, соответственно, выходной волновой файл будет иметь длину 10 секунд, и ...

  • канал 1 содержит 3 секунды звука из файла 1, за которыми следуют 7 секунд молчания.

  • канал 2 содержит 3 секунды молчания, затем 5 секунд звука из файла 2 и 2 секунды молчания.

  • канал 3содержит 8 секунд тишины, а затем 2 секунды звука из файла 3.

Я экспериментировал, создавая экземпляр WaveChannel32 для каждого файла, а затем используя класс WaveOffsetStream, но яЯ новичок в подобных вещах, и я не добиваюсь большого успеха.

У кого-нибудь есть какие-либо предложения?

1 Ответ

2 голосов
/ 10 августа 2011

Вы могли бы сделать это, написав свой собственный IWaveProvider / WaveStream, выходной WaveFormat которого имеет три канала.Он содержит ссылку на каждый из трех ваших входных файлов.Затем в методе Read он определяет количество запрошенных выборок и считывает соответствующее число из каждого исходного файла.Затем образцы должны чередоваться - один из первого файла, один из второго, один из третьего.Для отсрочки вы просто вводите нули.

Вот пример неопробованного примера кода, который чередуется из различных исходных файлов (все должны иметь одинаковую битовую глубину и частоту дискретизации), которые, мы надеемся, укажут вам правильное направление:

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;
        } 
    }
}

Чтобы избежать чрезмерной сложности кода, вы можете выполнить вставку молчания, создав еще один производный IWaveProvider / WaveStream, метод Read которого вернул соответствующее количество молчания, а затем вернул реальные данные из входного файла.Затем его можно использовать как входную информацию для вашего чередования WaveStream.

...