wav音频文件解析

2024-01-02 16:00:26

一、音频相关概念

1、样本

A/D转换器以每秒钟上万次的速率对声波进行采样,每个采样点都记录下了原始模拟声波在某一时刻的状态,通常称之为样本。通过将一串连续的样本连接起来,就可以在计算机中描述一段声音了。

2、采样频率

每一秒钟所采样的数目称为采样频率,单位hz,典型值是11025Hz、22050Hz和44100Hz。

采样频率的选择应该遵循奈奎斯特(Harry Nyquist)采样理论:如果对某一模拟信号进行采样,则采样后可还原的最高信号频率只有采样频率的一半,或者说只要采样频率高于输入信号最高频率的两倍,就能从采样信号系列重构原始信号。

3、采样分辩率(采样精度)

采样分辨率指的是在数字音频中用于表示每个采样值的位数。它决定了数字音频系统可以表示的动态范围和精度。常见的采样分辨率有8位、12位和16位等。位数越高,表示的动态范围越大,音频质量也更高。

4、数据传输速率

每秒平均传输的字节数,播放软件利用此值可以估计缓冲区的大小,计算公式:声道数×采样频率×每样本的数据位数 / 8

4、WAV文件

WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范, “RIFF”是wav文件识别码.

数据本身的格式为PCM或压缩型,属于无损音乐格式的一种。所有的WAV都有一个文件头,这个文件头音频流的编码参数。数据块的记录方式是little-endian字节顺序,标志符并不是字符串而是单独的符号。

  1. 偏移地址大小(字节)数据块类型内容
    00H~03H44字符大写字符串"RIFF",标明该文件为有效的 RIFF 格式文档。
    04H~07H?4长整数??从下一个字段首地址开始到文件末尾的总字节数。该字段的数值加 8 为当前文件的实际长度。
    ?08H~0BH44字符所有 WAV 格式的文件此处为字符串"WAVE",标明该文件是 WAV 格式文件。
    ?0CH~OFH44字符小写字符串"fmt ",最后一位空格。
    10H~13H4整数?过滤字节(一般为00000010H),若为00000012?H则说明数据头携带附加信息(见“附加信息”)。
    ?14H~15H2整数?PCM 脉冲编码调制格式种类(该数值通常为1,表示数据为线性PCM编码)
    16H~17H2整数通道数,单声道为1,双声道为2
    18H~1BH4长整数采样频率
    1CH~1FH4?长整数数据传输速率(每秒平均字节数)
    20H~21H2?整数采样帧大小。该数值为:声道数×位数/8。播放软件需要一次处理多个该值大小的字节数据,用该数值调整缓冲区。
    22H~23H2整数采样位数,存储每个采样值所用的二进制数位数
    ?随后2字节2?整数附加信息(可选,由上方过滤字节确定)
    随后...不定长度字符

    ?"fact",该部分是可选部分,一般当WAV文件是由某些软件转换而来时,包含该部分。

    若包含该部分:
    (1)该部分的前4字节为数据头,一般为4个字母,
    (2)随后4个字节表示长度,即除去头(4字节)和长度(4字节)之后,数据本身的长度。

    (3)最后的字节为数据本身。
    例如:“66 61?7374?04?00?00?00 F8?2F?14?00“,"66?61?73 74"是fact字段的数据头,"04 00 00?00是数据本身的长度,“F8 2F 14 00”是数据本身。(注意是little-endian字节顺序)

    随后4字节4?4字符数据标志符"data"
    随后4字节4?长整型DATA总数据长度字节
    ?随后...DATA数据块

    //数据头定义
    struct T_RecorderWavHeader
    {
        //RIFF chunk descriptor 12byte
        char            riff[4];            // = "RIFF"
        uint32_t        size_8;             // = FileSize - 8
        char            wave[4];            // = "WAVE"
    
        //fmt sub-chunk  24byte
        char            fmt[4];             // = "fmt "
        uint32_t        format_size;        // = 过滤字节(一般为00000010H,若为00000012H说明数据头携带附加信息)
        uint16_t        format_tag;         // = 常见的 WAV 文件使用 PCM 脉冲编码调制格式,该数值通常为 1
        uint16_t        channels;           // = 声道个数: 单声道为 1,立体声或双声道为 2
        uint32_t        samples_per_sec;    // = 采样频率 : 8000 | 6000 | 11025 | 16000 | 22050  | 44100
        uint32_t        avg_bytes_per_sec;  // = 数据传输速率(每秒平均字节数):声道数×采样频率×每样本的数据位数/8。播放软件利用此值可以估计缓冲区的大小。
                                            // = samples_per_sec * channels * bits_per_sample / 8
        uint16_t        block_align;        // = 每采样点字节数 : 声道数×位数/8。播放软件需要一次处理多个该值大小的字节数据,用该数值调整缓冲区。
                                            // = channels * bits_per_sample / 8
        uint16_t        bits_per_sample;    // = 采样位数: 存储每个采样值所用的二进制数位数, 8 | 16
    
        //data sub-chunk  8byte
        char            data[4];            // = "data";
        uint32_t        data_size;          // = 纯数据长度 : FileSize - 44
    };
    
    // 根据本系统的具体字节序处理的存放格式
    #if   __BYTE_ORDER == __LITTLE_ENDIAN
    
    	#define RIFF ('F'<<24 | 'F'<<16 | 'I'<<8 | 'R'<<0)
    	#define WAVE ('E'<<24 | 'V'<<16 | 'A'<<8 | 'W'<<0)
    	#define FMT  (' '<<24 | 't'<<16 | 'm'<<8 | 'f'<<0)
    	#define DATA ('a'<<24 | 't'<<16 | 'a'<<8 | 'd'<<0)
    
    	#define LE_SHORT(val) (val) 
    	#define LE_INT(val)   (val) 
    
    #elif __BYTE_ORDER == __BIG_ENDIAN
    
    	#define RIFF ('R'<<24 | 'I'<<16 | 'F'<<8 | 'F'<<0)
    	#define WAVE ('W'<<24 | 'A'<<16 | 'V'<<8 | 'E'<<0)
    	#define FMT  ('f'<<24 | 'm'<<16 | 't'<<8 | ' '<<0)
    	#define DATA ('d'<<24 | 'a'<<16 | 't'<<8 | 'a'<<0)
    
    	#define LE_SHORT(val) bswap_16(val) 
    	#define LE_INT(val)   bswap_32(val) 
    
    #endif
    

    根据对WAV格式的了解,编写了一个对wav音频文件的裁剪工具,欢迎大家点击下载

  2. 参考博客:【音频驱动】Linux之ALSA声卡、WAV文件相关概念_alsa 音频-CSDN博客

文章来源:https://blog.csdn.net/ckg3824278/article/details/135336769
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。