将一个wav文件转换为8000Hz 16Bit Mono Wav

4
我需要将一个wav文件转换为8000Hz的16位单声道Wav格式。我已经有一段代码,可以使用NAudio库很好地完成此操作,但我想使用MemoryStream代替临时文件。
using System.IO;
using NAudio.Wave;

    static void Main()
    {
        var input = File.ReadAllBytes("C:/input.wav");
        var output = ConvertWavTo8000Hz16BitMonoWav(input);
        File.WriteAllBytes("C:/output.wav", output);
    }

    public static byte[] ConvertWavTo8000Hz16BitMonoWav(byte[] inArray)
    {
        using (var mem = new MemoryStream(inArray))
        using (var reader = new WaveFileReader(mem))
        using (var converter = WaveFormatConversionStream.CreatePcmStream(reader))
        using (var upsampler = new WaveFormatConversionStream(new WaveFormat(8000, 16, 1), converter))
        {
            // todo: without saving to file using MemoryStream or similar
            WaveFileWriter.CreateWaveFile("C:/tmp_pcm_8000_16_mono.wav", upsampler);
            return File.ReadAllBytes("C:/tmp_pcm_8000_16_mono.wav");
        }
    }

你可以使用WaveFileWriter的其中一个构造函数,该构造函数接受一个流作为参数。取自NAudio源代码 - doomgg
@bob1024 我已经尝试过了,但没有转换器的参数...或者我漏掉了什么。 - Sergey Malyutin
您可以在 WaveFormat 变量中指定速率、位数和通道,并将其传递给 WaveFileWriter 构造函数。 - doomgg
@bob1024,可以的,就像使用(var mem = new MemoryStream(inArray)) { var waveFileWriter = new WaveFileWriter(mem, new WaveFormat(8000, 16, 1)); }但接下来呢? - Sergey Malyutin
我认为你可以使用WaveFileReader.ReadNextSampleFrameWaveFileWriter.WriteSample将音频样本从读取器传输到写入器。我没有看到其他的方法。 - doomgg
显示剩余2条评论
2个回答

3

不确定这是否是最优的方式,但它能够正常工作...

    public static byte[] ConvertWavTo8000Hz16BitMonoWav(byte[] inArray)
    {
        using (var mem = new MemoryStream(inArray))
        {
            using (var reader = new WaveFileReader(mem))
            {
                using (var converter = WaveFormatConversionStream.CreatePcmStream(reader))
                {
                    using (var upsampler = new WaveFormatConversionStream(new WaveFormat(8000, 16, 1), converter))
                    {
                        byte[] data;
                        using (var m = new MemoryStream())
                        {
                            upsampler.CopyTo(m);
                            data = m.ToArray();
                        }
                        using (var m = new MemoryStream())
                        {
                            // to create a propper WAV header (44 bytes), which begins with RIFF 
                            var w = new WaveFileWriter(m, upsampler.WaveFormat);
                            // append WAV data body
                            w.Write(data,0,data.Length);
                            return m.ToArray();
                        }   
                    }
                }
            }
        }
    }

1
由于缺乏积分,我无法发表评论,但是可能会添加。在某些情况下,NAudio始终写入46字节的标头,这可能会导致崩溃。如果有人在搜索naudio wav文件仅开始崩溃某些程序的线索时遇到此问题,我想要添加这个。
我在使用NAudio转换和/或采样wav后遇到了这个问题,并且已经卡住了2天,只有通过十六进制编辑器才找到了解决方法。
(额外的2个字节位于数据子块[d,a,t,a,size<4bytes>]之前的第37和38个字节处。 这里是两个波形文件头的比较,左边是由NAudio保存的46个字节;右边是Audacity保存的44个字节
你可以通过查看NAudio源代码中的WaveFormat.cs第310行来验证这一点,其中fmt chunck不是16个字节而是保留了18+额外的字节(因为有些wav文件甚至包含比46个字节更大的头文件),但NAudio似乎总是写入46个字节的头文件而从不写入44个字节的头文件(符合MS标准)。还应该注意的是,实际上NAudio能够读取44个字节的头文件(WaveFormat.cs中的第210行)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接