读取wav音频文件头源码详解

wav音频文件一般为PCM音频原始数据(很少有其他编码格式加wav头组成,如G711)加一个大小为44字节的wav文件头组成。
wav头具体组成见测试代码的wavhead_s结构体,在wav_head_parsing函数中解析并说明了44个字节代表的含义。
测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define WAV_HEAD_LEN 44

struct wavhead_s
{
	char RIFF_BUF[4];
	int wavFileLen;
	char WAVEfmt_BUF[8];
	int fmtLen;
	short code;
	short channels;
	int sampleRate;
	int bytePerSecond;
	short doubleBitsPerSample;
	short singleBitsPerSample;
	char DATA_BUF[4];
	int audioDataLen;
};


void wav_head_parsing(char *wav_head,struct wavhead_s *a)
{
	if(NULL == wav_head || NULL == a)
	{
		printf("%s %d parameter NULL\n",__FUNCTION__,__LINE__);
		return;
	}

	//wav文件头四个字节为固定格式:RIFF 表示这是一个WAVE文件头
	a->RIFF_BUF[0] = wav_head[0];//'R'	
	a->RIFF_BUF[1] = wav_head[1];//'I'	
	a->RIFF_BUF[2] = wav_head[2];//'F'	
	a->RIFF_BUF[3] = wav_head[3];//'F'	
	printf("RIFF_BUF = %c%c%c%c \n",a->RIFF_BUF[0],a->RIFF_BUF[1],a->RIFF_BUF[2],a->RIFF_BUF[3]);

	//wav文件总长度 不包含RIFF和自身 wavFileLen = 文件总长度 - 8
	a->wavFileLen |= ((wav_head[4] & 0xFF) << 0);
	a->wavFileLen |= ((wav_head[5] & 0xFF) << 8);
	a->wavFileLen |= ((wav_head[6] & 0xFF) << 16);
	a->wavFileLen |= ((wav_head[7] & 0xFF) << 24);
	printf("wavFileLen = %d\n",a->wavFileLen);

	//固定格式:WAVEfmt 表示后面开始是音频格式
	a->WAVEfmt_BUF[0] = wav_head[8];//'W'
	a->WAVEfmt_BUF[1] = wav_head[9];//'A'
	a->WAVEfmt_BUF[2] = wav_head[10];//'V'
	a->WAVEfmt_BUF[3] = wav_head[11];//'E'
	a->WAVEfmt_BUF[4] = wav_head[12];//'f'
	a->WAVEfmt_BUF[5] = wav_head[13];//'m'
	a->WAVEfmt_BUF[6] = wav_head[14];//'t'
	a->WAVEfmt_BUF[7] = wav_head[15];//''
	printf("WAVEfmt_BUF = %c%c%c%c%c%c%c%c \n",a->WAVEfmt_BUF[0],a->WAVEfmt_BUF[1],a->WAVEfmt_BUF[2],a->WAVEfmt_BUF[3],a->WAVEfmt_BUF[4],a->WAVEfmt_BUF[5],a->WAVEfmt_BUF[6],a->WAVEfmt_BUF[7]);

	
	//wav文件fmt格式块长度 
	//一般为16 表示是PCM数据 不需要解码 
	//G711A G711U为18
	a->fmtLen |= ((wav_head[16] & 0xFF) << 0);
	a->fmtLen |= ((wav_head[17] & 0xFF) << 8);
	a->fmtLen |= ((wav_head[18] & 0xFF) << 16);
	a->fmtLen |= ((wav_head[19] & 0xFF) << 24);
	printf("fmtLen = %d\n",a->fmtLen);

	
	//wav文件音频数据的编码格式
	//1:PCM 6:G711A 7:G711U 一般为1
	a->code |= ((wav_head[20] & 0xFF) << 0);
	a->code |= ((wav_head[21] & 0xFF) << 8);
	printf("code = %d\n",a->code);

	//声道数 1:单声道 2:双声道
	a->channels |= ((wav_head[22] & 0xFF) << 0);
	a->channels |= ((wav_head[23] & 0xFF) << 8);
	printf("channels = %d\n",a->channels);

	//采样率 例如:8000 16000 44100
	a->sampleRate |= ((wav_head[24] & 0xFF) << 0);
	a->sampleRate |= ((wav_head[25] & 0xFF) << 8);
	a->sampleRate |= ((wav_head[26] & 0xFF) << 16);
	a->sampleRate |= ((wav_head[27] & 0xFF) << 24);
	printf("sampleRate = %d\n",a->sampleRate);

	//音频每秒钟的数据量=采样率*声道数*采样位数/8
	a->bytePerSecond |= ((wav_head[28] & 0xFF) << 0);
	a->bytePerSecond |= ((wav_head[29] & 0xFF) << 8);
	a->bytePerSecond |= ((wav_head[30] & 0xFF) << 16);
	a->bytePerSecond |= ((wav_head[31] & 0xFF) << 24);
	printf("bytePerSecond = %d\n",a->bytePerSecond);

	//每次采样的大小=采样位数*声道数/8
	//播放器根据此值一次处理最小单位 单位为字节
	a->doubleBitsPerSample |= ((wav_head[32] & 0xFF) << 0);
	a->doubleBitsPerSample |= ((wav_head[33] & 0xFF) << 8);
	printf("doubleBitsPerSample = %d\n",a->doubleBitsPerSample);

	//单个声道每次采样的大小=采样位数
	//播放器根据此值一次处理最小单位 单位为位
	a->singleBitsPerSample |= ((wav_head[34] & 0xFF) << 0);
	a->singleBitsPerSample |= ((wav_head[35] & 0xFF) << 8);
	printf("singleBitsPerSample = %d\n",a->singleBitsPerSample);

	//固定字段 data 
	a->DATA_BUF[0] = wav_head[36];//'d'	
	a->DATA_BUF[1] = wav_head[37];//'a'	
	a->DATA_BUF[2] = wav_head[38];//'t'	
	a->DATA_BUF[3] = wav_head[39];//'a'	
	printf("DATA_BUF = %c%c%c%c \n",a->DATA_BUF[0],a->DATA_BUF[1],a->DATA_BUF[2],a->DATA_BUF[3]);
	
	//音频数据的长度=文件总长度 - 44(wav头长度)
	a->audioDataLen |= ((wav_head[40] & 0xFF) << 0);
	a->audioDataLen |= ((wav_head[41] & 0xFF) << 8);
	a->audioDataLen |= ((wav_head[42] & 0xFF) << 16);
	a->audioDataLen |= ((wav_head[43] & 0xFF) << 24);
	printf("audioDataLen = %d\n",a->audioDataLen);
}

int main(int argc,char **argv)
{
	char wav_head[WAV_HEAD_LEN] = {0};
	struct wavhead_s wav_test;

	FILE *wavfp = fopen(argv[1],"r");
	if(NULL == wavfp)
	{
		printf("fopen %s fail! err!!!\n",argv[1]);
		return -1;
	}

	fread(wav_head,sizeof(wav_head),1,wavfp);
	
	wav_head_parsing(wav_head,&wav_test);	

	fclose(wavfp);
	
	return 0;
}
	

随便找了一个wav文件的测试结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值