Wav详细解析(subChunk1Size/subChunk2Size) 附带部分C代码

WAVE文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。RIFF是英文Resource Interchange File Format的缩写,每个WAVE文件的头四个字节便是“RIFF”。WAVE文件由文件头和数据体两大部分组成。其中文件头又分为RIFF/WAV文件标识段和声音数据格式说明段两部分。

Wave主要包含size:

1,ChunkSize 整个文件大小,不能用它提取音频数据,Chunk1Size不固定而且文件结尾可能有填充描述信息

2,SubChunk1Size 如若不是10H,说明Chunk1有附加信息,Size就不固定,Chunk2的offset就不再是36,如要找Chunk2,需要检索 64 61 74 61 data的关键字。

3,SubChunk2Size 音频数据的真实大小。

OffsetBlockNameSizeComment
0ChunkID452 49 46 46 RIFF
4ChunkSize4ChunkSize + 8(chunkId和chunksize)= 整个文件大小
8Format457 41 56 45 WAVE
12Subchunk1ID466 6D 74 20 fmt
16SubChunk1Size4

10H:subchunk1没有附加信息,常规size,

e.g:12H:chunk1包含附加信息,chunk size不固定

20AudioFormat21:pcm编码
22NumChannels2Channel Number
24SampleRate4Sample Rate
28ByteRate4SampleRate * NumChannels * BitsPerSample/8
32BlockAlign2NumChannels * BitsPerSample/8
34BitsPerSample2BitsPerSample
36SubChunk2ID464 61 74 61 data
40SubChunk2Size4数据Data真实的Size
44Data Data
44+DataLenInformation 有些wave会填充描述信息

 分析Header的方案一,

直接定义一个头信息的结构体如下,然后直接fread到wav_header。

但是有个大小端的问题,比如uint32_t是由四个字节组合而成的。

struct wav_header {
    uint32_t riff_id;
    uint32_t riff_sz;
    uint32_t riff_fmt;
    uint32_t fmt_id;
    uint32_t fmt_sz;
    uint16_t audio_format;
    uint16_t num_channels;
    uint32_t sample_rate;
    uint32_t byte_rate;
    uint16_t block_align;
    uint16_t bits_per_sample;
    uint32_t data_id;
    uint32_t data_sz;
};

 分析Header的方案二

定义一个44个字节的数组,灵活但是不简洁

/*read the header*/
    if(fread(head, sizeof(char), ID_WAVE_HEADER, fp) != ID_WAVE_HEADER)
    {
        printf("not a wave file\n");
        return -1;        
    } 
/*check the format pcm = 1*/
    if (head[20] != PCM_FORMAT_16BITS_1)
    {
        printf("format != 1(pcm) :%d\n",head[20]);
        return -1;
    }

/*check the channel num = 2*/
    if (head[22] != CHANNEL_2)
    {
        printf("channel num != 2 :%d\n",head[22]);
        return -1;
    }
/*check the samplerate = 48kHz*/
    samplerate = head[24] + (head[25] << 8)  + (head[26] << 8*2)  + (head[27] << 8*3);
    if (samplerate != SAMPLERATE_48KHZ)
    {
        printf("samplerate != 48000 :%d\n",samplerate);
        return -1;
    }

/*check the bits per frame*/    
    if (head[34] != SAMPLEBITS_16)
    {
        printf("bitsnum != 16 :%d\n",head[34]);
        return -1;
    }
/*calculate pcm data size*/    
    datanum = head[40] + (head[41] << 8)  + (head[42] << 8*2)  + (head[43] << 8*3);
    printf("datanum :%d\n",datanum);

    pcmdata = (char*)malloc(datanum);

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值