A/D转换器以每秒钟上万次的速率对声波进行采样,每个采样点都记录下了原始模拟声波在某一时刻的状态,通常称之为样本。通过将一串连续的样本连接起来,就可以在计算机中描述一段声音了。
每一秒钟所采样的数目称为采样频率,单位hz,典型值是11025Hz、22050Hz和44100Hz。
采样频率的选择应该遵循奈奎斯特(Harry Nyquist)采样理论:如果对某一模拟信号进行采样,则采样后可还原的最高信号频率只有采样频率的一半,或者说只要采样频率高于输入信号最高频率的两倍,就能从采样信号系列重构原始信号。
采样分辨率指的是在数字音频中用于表示每个采样值的位数。它决定了数字音频系统可以表示的动态范围和精度。常见的采样分辨率有8位、12位和16位等。位数越高,表示的动态范围越大,音频质量也更高。
每秒平均传输的字节数,播放软件利用此值可以估计缓冲区的大小,计算公式:声道数×采样频率×每样本的数据位数 / 8
WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范, “RIFF”是wav文件识别码.
数据本身的格式为PCM或压缩型,属于无损音乐格式的一种。所有的WAV都有一个文件头,这个文件头音频流的编码参数。数据块的记录方式是little-endian字节顺序,标志符并不是字符串而是单独的符号。
偏移地址 | 大小(字节) | 数据块类型 | 内容 |
---|---|---|---|
00H~03H | 4 | 4字符 | 大写字符串"RIFF",标明该文件为有效的 RIFF 格式文档。 |
04H~07H? | 4 | 长整数?? | 从下一个字段首地址开始到文件末尾的总字节数。该字段的数值加 8 为当前文件的实际长度。 |
?08H~0BH | 4 | 4字符 | 所有 WAV 格式的文件此处为字符串"WAVE",标明该文件是 WAV 格式文件。 |
?0CH~OFH | 4 | 4字符 | 小写字符串"fmt ",最后一位空格。 |
10H~13H | 4 | 整数 | ?过滤字节(一般为00000010H),若为00000012?H则说明数据头携带附加信息(见“附加信息”)。 |
?14H~15H | 2 | 整数 | ?PCM 脉冲编码调制格式种类(该数值通常为1,表示数据为线性PCM编码) |
16H~17H | 2 | 整数 | 通道数,单声道为1,双声道为2 |
18H~1BH | 4 | 长整数 | 采样频率 |
1CH~1FH | 4? | 长整数 | 数据传输速率(每秒平均字节数) |
20H~21H | 2? | 整数 | 采样帧大小。该数值为:声道数×位数/8。播放软件需要一次处理多个该值大小的字节数据,用该数值调整缓冲区。 |
22H~23H | 2 | 整数 | 采样位数,存储每个采样值所用的二进制数位数 |
?随后2字节 | 2? | 整数 | 附加信息(可选,由上方过滤字节确定) |
随后 | ... | 不定长度字符 | ?"fact",该部分是可选部分,一般当WAV文件是由某些软件转换而来时,包含该部分。 若包含该部分: (3)最后的字节为数据本身。 |
随后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音频文件的裁剪工具,欢迎大家点击下载。