C++读取wav文件,subchunk1size = 18

Kel*_*Tan 3 c++ header wav

通常 wav 文件的 subchunk1size 是 16。但是,我有一些 subchunk1size = 18 的 wav 文件。我有 C++ 代码来读取 subchunk1size = 16 的 wav 文件。现在我想读取 subchunk1size = 18 的 wav 文件。任何帮助,将不胜感激。

typedef struct header_file
{
    char chunk_id[4];
    int chunk_size;
    char format[4];
    char subchunk1_id[4];
    int subchunk1_size;
    short int audio_format;
    short int num_channels;
    int sample_rate;            
    int byte_rate;
    short int block_align;
    short int bits_per_sample;
    char subchunk2_id[4];
    int subchunk2_size;         
} header;
Run Code Online (Sandbox Code Playgroud)

上面是我的代码中的struct header_file,用于读取subchunk1size = 16的wav文件。

Tri*_*ian 5

Wav 文件没有您想象的那么严格的结构。“fmt”块不一定是文件头后面的第一个块(尽管通常是),并且其大小不一定是 16 字节(尽管通常也是这种情况)。压缩音频可以存储在 wav 文件中,在这种情况下,该audio_format字段将不同于 1,并且“fmt”块的大小可以不同于 16 字节。

解析 wav 文件的正确且灵活的方法是使用更细粒度的结构:

struct wave_header
{
    char chunk_id[4];
    int chunk_size;
    char format[4];     
};

struct riff_chunk_header
{
    char id[4];
    int size;
};

struct wave_fmt_chunk
{
    short audio_format;
    short num_channels;
    int sample_rate;            
    int byte_rate;
    short block_align;
    short bits_per_sample;
};
Run Code Online (Sandbox Code Playgroud)

那么你的解析逻辑应该是(注意验证你在每一步读取的数据):

  1. 读一读wave_header
  2. 读一读riff_chunk_header
  3. 如果您读取的块头的 ID 不是“fmt”,则跳过该块(您的大小以字节为单位)并循环回到步骤 2 以读取下一个块头
  4. 读取audio_format字段
  5. 根据此解释“fmt”块的其余数据audio_format。如果它是 1,则您有 PCM 数据,并且块应该具有您预期的 16 字节。如果不是 1,则必须查找有关该压缩格式的文档。

一般来说,优雅地忽略附加数据也是一个好主意,因此,如果您确实看到带有 18 字节“fmt”块的 PCM 编码 wav 文件,请尝试忽略最后 2 个字节,看看会发生什么。