wav标头错误NAudio c#

时间:2017-10-06 09:31:49

标签: c# wav naudio

当我更改wav文件的waveFormat时,"数据"标识符向右移动。表示da chunk开头的数据标识符必须位于0x24位置,但在我使用NAudio库更改waveFormat后,它会移动到0x26位置。

WAV格式

enter image description here

这是我用来更改waveFormat的代码:

private void TurnTo16bitsAudio(string path)
        {
            NAudio.Wave.WaveFileReader wave = new NAudio.Wave.WaveFileReader(@path);
            System.Console.WriteLine(wave.WaveFormat);
            if (wave.WaveFormat.BitsPerSample >= 16 && wave.WaveFormat.Channels<2)
            {
                wave.Dispose();
                return;
            }

            var newFormat = new WaveFormat(44100, 16, 1);
            var conversionStream = new WaveFormatConversionStream(newFormat, wave);
            WaveFileWriter.CreateWaveFile(@path + '1', conversionStream);
            wave.Dispose();
            wave = new NAudio.Wave.WaveFileReader(@path + '1');
            conversionStream = new WaveFormatConversionStream(newFormat, wave);
            WaveFileWriter.CreateWaveFile(@path, conversionStream);
            wave.Dispose();
            conversionStream.Dispose();
            System.IO.File.Delete(@path + '1');

        }

有可能使用NAudio更改wav标头或更改waveFormat而不会删除&#34;数据&#34;标识符

1 个答案:

答案 0 :(得分:1)

WaveFormat 类中的序列化方法永远不会在 Subchunk1Size 字段中输出0x10。最小值为0x12。

public virtual void Serialize(BinaryWriter writer)
{
    writer.Write((int)(18 + extraSize)); // wave format length
    writer.Write((short)Encoding);
    writer.Write((short)Channels);
    writer.Write((int)SampleRate);
    writer.Write((int)AverageBytesPerSecond);
    writer.Write((short)BlockAlign);
    writer.Write((short)BitsPerSample);
    writer.Write((short)extraSize);
}

额外的2个字节用于ExtraParamSize,当编码设置为WaveFormatEncoding.Pcm(其值== 0)时,将忽略该字节。 这与引入WAVEFORMATEX时Microsoft(Windows 2000及更高版本)完成的WAV格式的更改有关。

在这里你可以找到关于subchunk1size 16/18不同大小问题的答案: C++ read wav file, subchunk1size = 18

有关WAVEFORMATEX结构的详细信息: https://msdn.microsoft.com/library/windows/hardware/ff538799

如果你真的想在没有extraSize字段的情况下强制创建wav标题,你可以扩展WaveFormat类。

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 2)]
class CustomWaveFormat : WaveFormat
{
    public CustomWaveFormat(int rate, int bits, int channels) 
        : base(rate, bits, channels)
    {
        extraSize = 0;
    }

    public override void Serialize(BinaryWriter writer)
    {
        writer.Write((int)16); // wave format length
        writer.Write((short)Encoding);
        writer.Write((short)Channels);
        writer.Write((int)SampleRate);
        writer.Write((int)AverageBytesPerSecond);
        writer.Write((short)BlockAlign);
        writer.Write((short)BitsPerSample);
    }
}

用法:

...
    var newFormat = new CustomWaveFormat(44100, 16, 1);

    using (var conversionStream = new WaveFormatConversionStream(newFormat, waveFileReader))
    {
        WaveFileWriter.CreateWaveFile("example_new.wav", conversionStream);
    }
...