преобразование файла wav из PCM со скоростью 48 кГц / 16 бит в U-закон 8 кГц / 8 бит с использованием NAudio

У меня есть файл wav, который мне нужно преобразовать в формат, который может быть прочитан одним из наших приложений. Файл, который я хочу преобразовать, имеет формат:

  • Кодировка: PCM
  • Частота дискретизации: 48 кГц
  • Битрейт: 16 бит
  • Каналы: 1

Читаемый формат файла, в который я хочу преобразовать:

  • Кодировка: u-Law
  • Частота дискретизации: 8 кГц
  • Битрейт: 8 бит
  • Каналы: 1

Для этого я использую библиотеку NAudio. Код, который я использую для преобразования, выглядит примерно так:

using (WaveFileReader reader = new WaveFileReader(inputWavFilePath))
{
    WaveFormat newFormat = WaveFormat.CreateMuLawFormat(8000, 1);
    using (var conversionStream = new WaveFormatConversionStream(newFormat, reader))
    {
        WaveFileWriter.CreateWaveFile(outputWavFilePath, conversionStream);
    }
}

Приведенное выше преобразование вызывает ошибку

AcmNotPossible вызов acmStreamOpen

Я видел несколько ссылок для перехода с U-закона на PCM, но у меня проблемы с обратным.

Я изо всех сил пытаюсь понять, почему, когда я конвертирую PCM/48kHz/16bit -> uLaw/48kHz/8bit, исключение не генерируется. Но когда я затем пытаюсь преобразовать полученный файл в uLaw/8kHz/8bit, создается исключение.

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

Может ли кто-нибудь объяснить, почему преобразование вызывает исключение только при преобразовании частоты дискретизации, а не в двух других преобразованиях (кодирование PCM -> uLaw && 16bit -> 8bit)?


person Pleebo    schedule 11.04.2018    source источник


Ответы (2)


Я написал довольно подробную статью, чтобы объяснить, как конвертировать между различными типами аудио в .NET (многие используют NAudio)

С кодеками ACM вы обычно можете изменять только одну вещь за раз - например,

  • Изменение частоты дискретизации (например, 48 кГц -> 8 кГц)
  • Изменение количества каналов (например, моно -> стерео)
  • Изменение разрядности (например, 32-разрядное число с плавающей запятой -> 16-разрядное целое число)
  • Кодирование или декодирование с помощью кодека (например, переход от PCM к mu-law)

Вы можете связать их вместе, чтобы выполнить двухэтапное преобразование - например, нравится:

using (var reader = new WaveFileReader(inputWav))
using (var conversionStream1 = new WaveFormatConversionStream(pcm8k16bit, reader))
using (var conversionStream2 = new WaveFormatConversionStream(muLaw8k8bit, conversionStream1))
{
    WaveFileWriter.CreateWaveFile(outputWav, conversionStream2);
}
person Mark Heath    schedule 12.04.2018
comment
Ах, это имеет смысл. Итак, проблема, с которой я изначально столкнулся, заключалась в попытке кодировать / декодировать И изменить битовую глубину с тем же потоком преобразования. Статья тоже очень информативная. Спасибо. - person Pleebo; 13.04.2018

Я считаю, что нашел, какие преобразования и в каком порядке они должны быть, чтобы это работало правильно. Кажется, что приведенный ниже код работает.

String inputWav = "D:\\test-input.wav";
String tempWav = "D:\\test-input-temp.wav";
String outputWav = "D:\\test-output.wav";

WaveFormat pcm8k16bit = new WaveFormat(8000, 16, 1);
WaveFormat muLaw8k8bit = WaveFormat.CreateMuLawFormat(8000, 1);

using (var reader = new WaveFileReader(inputWav))
using (var conversionStream = new WaveFormatConversionStream(pcm8k16bit, reader))
{
    WaveFileWriter.CreateWaveFile(tempWav, conversionStream);
}

using (var fs = new FileStream(tempWav, FileMode.Open))
using (var rawSrcReader = new RawSourceWaveStream(fs, pcm8k16bit))
using (var conversionStream = new WaveFormatConversionStream(muLaw8k8bit, rawSrcReader))
{
    WaveFileWriter.CreateWaveFile(outputWav, conversionStream);
}

Проблема в том, что я до сих пор не могу понять, почему это так. Я пробовал много других вариантов того же и похожего кода, но безрезультатно. Например, почему происходит сбой преобразования при преобразовании из PCM 48 кГц / 8 бит в MuLaw 48 кГц / 8 бит?

person Pleebo    schedule 11.04.2018
comment
это не будет работать правильно - используйте WaveFileReader на втором этапе, а не FileStream и RawSourceWaveStream, которые в конечном итоге интерпретируют заголовок файла WAV как образцы - person Mark Heath; 12.04.2018
comment
@MarkHeath Я не могу объяснить, почему, но приведенный выше код действительно работал и в настоящее время работает у меня правильно при преобразовании PCM 48 кГц / 16-битной глубины в MuLaw 8kHz / 8-битной глубины. - person Pleebo; 13.04.2018