【问题标题】:wav file conversion PCM 48kHz/16 bit rate to u-law 8kHz/8 bit rate using NAudio使用 NAudio 将 wav 文件转换 PCM 48kHz/16 比特率到 u-law 8kHz/8 比特率
【发布时间】:2018-04-11 13:37:49
【问题描述】:

我有一个 wav 文件,我需要将其转换为我们的一个应用程序可以读取的格式。我要转换的文件格式为:

  • 编码:PCM
  • 采样率:48kHz
  • 比特率:16 位
  • 频道:1

我要转换成的可读文件格式是:

  • 编码:u-Law
  • 采样率:8kHz
  • 比特率: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-law 转换为 PCM 的链接,但是在反向转换时遇到了问题。

我很难理解的是为什么当我转换 PCM/48kHz/16bit -> uLaw/48kHz/8bit 时异常没有抛出。但是,当我尝试将生成的文件转换为 uLaw/8kHz/8bit 时,抛出异常

我是处理音频文件和不同格式的新手,所以如果我遗漏了一些简单的东西,我深表歉意。

有人能解释一下为什么转换只在采样率转换时抛出异常,而不是在其他两个转换(编码PCM -> uLaw && 16bit -> 8bit)?

【问题讨论】:

    标签: c# naudio audio-converter


    【解决方案1】:

    我写了一个fairly detailed article 来解释如何在.NET 中的各种音频类型之间进行转换(许多使用NAudio)

    使用 ACM 编解码器,您通常一次只能更改一件事 - 例如

    • 更改采样率(例如 48kHz -> 8kHz)
    • 更改通道数(例如单声道 -> 立体声)
    • 更改位深度(例如 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);
    }
    

    【讨论】:

    • 啊,这很有道理。所以我最初遇到的问题是尝试使用相同的转换流进行编码/解码和更改位深度。文章也非常翔实。谢谢。
    【解决方案2】:

    我相信我找到了需要哪些转换以及转换的顺序才能正常工作。下面的代码似乎可以工作。

    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 48kHz/8bit 转换为 MuLaw 48kHz/8bit 时为什么会转换失败?

    【讨论】:

    • 这将无法正常工作 - 在第二阶段使用 WaveFileReader 而不是 FileStreamRawSourceWaveStream 最终会将 WAV 文件头解释为样本
    • @MarkHeath 我无法真正证明为什么,但上面的代码确实有效,并且目前在将 PCM 48kHz/16 位深度转换为 MuLaw 8kHz/8 位深度时可以正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-12
    • 1970-01-01
    • 2013-04-24
    相关资源
    最近更新 更多