当前位置 : 主页 > 编程语言 > c语言 >

WAV 音频文件解读和分析

来源:互联网 收集:自由互联 发布时间:2023-09-07
格式说明 wav是一种无损的音频文件格式。所有的WAV都有一个文件头,包含了这个音频的编码参数。wav对音频流的编码没有硬性规定,除了PCM之外,还有几乎所有支持ACM规范的编码都可以

格式说明

wav是一种无损的音频文件格式。所有的WAV都有一个文件头,包含了这个音频的编码参数。wav对音频流的编码没有硬性规定,除了PCM之外,还有几乎所有支持ACM规范的编码都可以为WAV的音频流进行编码。

对PCM数据来说,加上wav文件头就变成了wav格式。

不同格式的数据,wav文件头的格式也略有不同,标准PCM数据的wav文件头是44字节,而ulaw或alaw的文件头会多一个区块,占58字节。

PCM数据对应的WAV文件头:

区块名

bytes

端序

内容

说明

ChunkID

4

"RIFF"


ChunkSzie

4

N+sizeof(head)-8

N是音频数据的长度

Format

4

"WAVE"


Subchunk1ID

4

"fmt "

fmt加空格

Subchunk1IDsize

4

16or18


AudioFormat

2

音频格式

PCM: 0x01;a-law: 0x06;u-law: 0x07

NumChannels

2

通道数

单声道:1,立体声:2

SampleRate

4

采样频率Hz


ByteRate

4


SampleRate * NumChannels * BitsPerSample/8

BlockAlign

2


NumChannels * BitsPerSample/8

BitPerSample

2or4

8bits=8, 16bits=16


采样位深

是压缩编码数据时占4字节,正常编码数据占2字节


factchunkID

4

"fact"

压缩编码的数据需要这个块,否则不需要

factchunkIDsize

4

4


factData

4


可以是音频数据长度

Subchunk2ID

4

"data"


Subchunk2IDsize

4

N

音频数据的长度

data

N


十六进制文件说明

原始数据

52 49 46 46 0e 82 01 00 57 41 56 45 66 6d 74

20 10 00 00 00 01 00 01 00 80 3e 00 00 00 7d

00 00 02 00 10 00 64 61 74 61 ea 81 01 00 a3

ff a3 ff a5 ff a7 ff a8 ff  

数据分析

52 49 46 46:对应的 ASCII 字符为:RIFF

0e 82 01 00:ChunkSize,对应的十六进制是 0x1820e=98830 +8 和上面的文件大小一致

57 41 56 45:对应的 ASCII 字符为 WAVE

66 6d 74 20:对应的 ASCII 字符为 fmt

10 00 00 00:FmtSize 0x10=16 代表PCM编码方式

01 00:对应为1,代表PCM编码方式

01 00:通道个数,通道数为1

80 3e 00 00:采样频率 0x3e80=16000=16KHz

00 7d 00 00:每秒所需的字节数,转化为十六进制为: 0x7d00=32000 通过此值可以计算该音频的时长:98838/32000 = 3s

02 00:数据对齐单位

10 00:采样位数 0x10=16

64 61 74 61:对应的 ASCII 字符为 data

ea 81 01 00:对应该音频的raw数据的大小

代码解析格式头

//WAVE文件一般有四种块,它们依次是:RIFF块、格式块、附加块(可选),数据块    
#pragma pack(1)    
typedef struct {
	//RIFF块        
	uint8_t   riffID[4];     //RIFF标识
	uint32_t  fileSize;      //文件大小        
	uint8_t   fccType[4];    //WAVE标志        
	//fmt块        
	uint8_t   fmtID[4];        //fmt         
	uint32_t  ckLen;           //块大小  pcm-0x10;ulaw-0x12;alaw-0x12
	uint16_t  wFormatTag;      //音频格式 pcm-0x01;ulaw-0x07;alaw-0x06
	uint16_t  nChannels;       //采样声道数
	uint32_t  nSamplesPerSec;  //采样率
	uint32_t  nAvgBytesPerSec; //每秒字节数  采样率*采样精度/8(字节位数)
	uint16_t  cbSize;
	uint32_t  bPerSample;      //每个采样位数,量化数(pcm为2byte)
	//fact块,压缩编码须有该块        
	uint8_t   factID[4]; //fact
	uint32_t  factSzie;  //4
	uint32_t  factData;
	//data块
	uint8_t   wdid[4];   //data 标志
	uint32_t  wdSize;    //块大小    
} WAVFILEHEADER;
//0x3A(58)字节
//针对ulaw和alaw,未经压缩的原始pcm对应的wav文件头有所不同
#pragma pack()

void TestWAVFile()
{
	int nWaveHeaderLen = sizeof(WAVFILEHEADER);
	FILE *fp = fopen("F:/ffmpeg/audio/7221/libg7221-master/test-data/local/short_wb_voice.wav", "rb+");
	if (fp == NULL)
	{
		std::cout << "打开文件失败" << std::endl;
		return;
	}
	char *pWavBuffer = (char *)calloc(nWaveHeaderLen, sizeof(char));
	if (fread(pWavBuffer, 1, nWaveHeaderLen, fp) != nWaveHeaderLen)
	{
		std::cout << "读取文件失败" << std::endl;
		return;
	}
	WAVFILEHEADER *pWavHeader = (WAVFILEHEADER *)pWavBuffer;
	return;
}


参考

wav文件格式分析与详解 - nigaopeng - 博客园 (cnblogs.com)

上一篇:数据结构--&gt;用栈实现队列(OJ_02)
下一篇:没有了
网友评论