Использование NAudio для повторной выборки аудио-данных Wav и конвертации в или из необработанного PCM - PullRequest
0 голосов
/ 13 мая 2018

Моя серверная программа принимает аудиоданные от клиентского программного обеспечения в формате PCM Wave с правильным заголовком RIFF (48000 Гц, 16 бит, может быть 1 или 2 каналами).После этого необходимо повторно сэмплировать эти данные в 16000 Гц, 16 бит и только 1 канал за исключением: это должны быть необработанные данные PCM без заголовка RIFF, чтобы данные могли быть переданы во внешнюю службу для воспроизведения.Кроме того, эта служба будет передавать обратно тот же тип необработанных аудиоданных PCM.Таким образом, программа также должна будет работать в обратном направлении (с повышением частоты до 48000 Гц и в формате RIFF Wave).

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

Вот код, который я использовал для даунсамплинга и преобразования в raw:

var processingData = GetAudioData(); // This is the input audio data in Wav format
using (Stream stream = new MemoryStream(processingData))
{
    using (var wavFileReader = new WaveFileReader(stream))
    {
        var resampler = new WdlResamplingSampleProvider(wavFileReader.ToSampleProvider(), 16000);
        var monoSource = resampler.ToMono().ToWaveProvider16();
        using (var outputStream = new MemoryStream())
        {
            byte[] bytesOutput = new byte[monoSource.WaveFormat.AverageBytesPerSecond];
            while (true)
            {
                int bytesRead = monoSource.Read(bytesOutput, 0, bytesOutput.Length);
                if (bytesRead == 0)
                    break;
                outputStream.Write(bytesOutput, 0, bytesRead);
            }

            var outputData = outputStream.ToArray(); // This is raw PCM data
        }
    }
}

Интересно, есть лилучший и эффективный способ получить необработанный PCM от WavProvider вместо чтения его побайтно в MemoryStream.Например, я пробовал ресамплер ACM, и это WaveStream, поэтому легко скопировать данные потока в поток памяти, но этот ресэмплер не может одновременно изменять частоту дискретизации и количество каналов.Я хочу, чтобы эта часть была максимально быстрой, чтобы получить необработанный PCM и быстро отправить его во внешнюю службу с минимальной задержкой.

Аналогично, это логический код процесса реверсирования:

var processingData = GetRawData(); // This is the raw PCM data
using (Stream stream = new MemoryStream(processingData))
{
    using (var rawStream = new RawSourceWaveStream(stream, new WaveFormat(16000, 16, 1)))
    using (var upsample = new WaveFormatConversionStream(new WaveFormat(48000, 16, 2), rawStream))
    using (var outputStream = new MemoryStream())
    {
        WaveFileWriter.WriteWavFileToStream(outputStream, upsample.ToSampleProvider().ToWaveProvider16());
        var outputData = outputStream.ToArray();
    }           
}

Поскольку в NAudio есть несколько утилит для генерации данных Wave, я использовал метод WaveFileWriter.WriteWavFileToStream для генерации всего необходимого заголовка RIFF, но вместо сохранения его в файл я передаю данные в MemoryStream.Тем не менее у меня есть некоторые опасения по поводу совместимости, а также эффективности в этом смысле.Я считаю, что WaveFormatConversionStream использует ACM вместо Wdl, поэтому у него могут быть проблемы с более новым программным / аппаратным обеспечением сервера.Есть ли способ использовать образец Wdl для этого шага так же, как и ранее?

...