WAV文件格式
WAVE文件是非常简单的一种RIFF文件,它的格式类型为"WAVE"。RIFF块包含两个子块,这两个子块的ID分别是"fmt"和"data",其中"fmt"子块由结构PCMWAVEFORMAT所组成,其子块的大小就是sizeofof(PCMWAVEFORMAT),数据组成就是PCMWAVEFORMAT结构中的数据。
typedef struct _TWavHeader
{
int rId; //标志符(RIFF)
int rLen; //数据大小,包括数据头的大小和音频文件的大小
int wId; //格式类型("WAVE")
int fId; //"fmt"
int fLen; //Sizeof(WAVEFORMATEX)
short wFormatTag; //编码格式,包括WAVE_FORMAT_PCM,WAVEFORMAT_ADPCM等
short nChannels; //声道数,单声道为1,双声道为2
int nSamplesPerSec; //采样频率
int nAvgBytesPerSec; //每秒的数据量
short nBlockAlign; //块对齐
short wBitsPerSample; //WAVE文件的采样大小
int dId; //"data"
int wSampleLength; //音频数据的大小
}TWavHeader;
- /*
- * File name: resolving.c
- * Author: xubinbin (xubbwd@gmail.com)
- * Version: ver.1.0
- * Date: 2013.04.17
- * Description: The type wav file header parameter parsing.
- */
- #include
- #include
- #define SIZE_LONG 4
- #define SIZE_SHORT 2
- #define SIZE_ID 4
- #define BITS_PER_BYTE 8
- #define WAVE_FORMAT_PCM (0x0001)
- #define FILE_NAME "aplay_test.wav"
- typedef struct _fa_wavfmt_t
- {
- unsigned short format;
- unsigned short channels; //音频通道数 1:单声道 2:立体声
- unsigned long samplerate; //声音采样频率
- unsigned short bytes_per_sample; //每帧数据大小(单声道)
- unsigned short block_align;
- unsigned long data_size; //数据总长度
- }fa_wavfmt_t;
- /*
- * Function: fa_read_u32
- * Description: read from the file stream 4 bytes data
- */
- static unsigned long fa_read_u32(FILE *fp)
- {
- unsigned long cx;
- unsigned char temp[SIZE_LONG];
- fread(temp, sizeof(*temp), SIZE_LONG, fp);
- cx = (unsigned long)temp[0];
- cx |= (unsigned long)temp[1] << 8;
- cx |= (unsigned long)temp[2] << 16;
- cx |= (unsigned long)temp[3] << 24;
- return cx;
- }
- /*
- * Function: fa_read_u16
- * Description: read from the file stream 2 bytes data
- */
- static unsigned short fa_read_u16(FILE *fp)
- {
- unsigned short cx;
- unsigned char temp[SIZE_SHORT];
- fread(temp, sizeof(*temp), SIZE_SHORT, fp);
- cx = temp[0] | (temp[1] * 256);
- return cx;
- }
- void printf_fun(fa_wavfmt_t *fmt)
- {
- printf("************************************************************\n");
- printf("* *\n");
- printf("* Copyright (C) 2013 xubinbin 徐彬彬 (Beijing China) *\n");
- printf("* Free Software *\n");
- printf("* Email: xubbwd@gmail.com *\n");
- printf("* *\n");
- printf("************************************************************\n\n");
- printf("##############################################################\n");
- printf("###### format = %d ######\n",fmt->format);
- printf("###### channels = %d ######\n",fmt->channels);
- printf("###### samplerate = %ld ######\n",fmt->samplerate);
- printf("###### bytes_per_sample = %d ######\n",fmt->bytes_per_sample);
- printf("###### block_align = %d ######\n",fmt->block_align);
- printf("###### data_size = %ld ######\n",fmt->data_size);
- printf("##############################################################\n");
- return;
- }
-
- int main()
- {
- long nskip, x_size;
- unsigned short format;
- unsigned short channels, block_align;
- unsigned long samplerate;
- unsigned long bits_per_sample;
- unsigned long bytes_per_sample;
- unsigned long data_size;
- unsigned char temp[SIZE_ID];
- fa_wavfmt_t fmt;
- FILE * fp = NULL;
- if ((fp = fopen(FILE_NAME, "rb")) == NULL) {
- printf("input file can not be opened;\n");
- return 0;
- }
-
- /*wav的文件标识符为RIFF,对标识符进行判断*/
- fread(temp, sizeof(*temp), SIZE_ID, fp);
- if (memcmp(temp, "RIFF", (size_t)SIZE_ID)!=0) {
- fprintf(stderr, "file is not WAVE format!\n");
- return -1;
- }
- fread(temp, sizeof(*temp), SIZE_LONG, fp);
-
- /*文件的格式类型为WAVE*/
- fread(temp, sizeof(*temp), SIZE_ID, fp);
- if (memcmp(temp, "WAVE", (size_t)SIZE_ID)!=0) {
- fprintf(stderr, "file is not WAVE format!\n");
- return -1;
- }
-
- /* fmt标志,最后一位为空 */
- fread(temp, sizeof(*temp), SIZE_ID, fp);
- /* skip chunks except for "fmt " or "data" */
- while (memcmp(temp, "fmt ", (size_t)SIZE_ID)!=0) {
- nskip = fa_read_u32(fp);
- if (nskip!=0) {
- fseek(fp, nskip, SEEK_CUR);
- }
- }
- /*sizeof(PCMWAVEFORMAT)*/
- x_size = fa_read_u32(fp);
- // printf("LINE[%d]#### %ld\n",__LINE__,x_size);
- /* 1(WAVE_FORMAT_PCM) 格式类别,1表示为PCM形式的声音数据*/
- format = fa_read_u16(fp);
- x_size -= SIZE_SHORT;
- if (WAVE_FORMAT_PCM != format) {
- fprintf(stderr, "error! unsupported WAVE file format.\n");
- return -1;
- }
- /*声音通道数*/
- channels = fa_read_u16(fp);
- x_size -= SIZE_SHORT;
- /*声音采样率*/
- samplerate = fa_read_u32(fp);
- x_size -= SIZE_LONG;
- fa_read_u32(fp); /* skip bytes/s 每秒数据量 */
- block_align = fa_read_u16(fp); /* skip block align 数据块的调整数 */
- bits_per_sample = fa_read_u16(fp); /* bits/sample 每样本的数据位数 */
- bytes_per_sample= (bits_per_sample + BITS_PER_BYTE - 1)/BITS_PER_BYTE;
- block_align = bytes_per_sample * channels;
- x_size -= SIZE_LONG + SIZE_SHORT + SIZE_SHORT; /* skip additional part of "fmt " header */
- // printf("LINE[%d]#### %ld\n",__LINE__,x_size);
- if (x_size!=0) {
- fseek(fp, x_size, SEEK_CUR);
- }
- /* skip chunks except for "data" */
- fread(temp, sizeof(*temp), SIZE_ID, fp);
- while (memcmp(temp, "data", SIZE_ID)!=0) {
- nskip = fa_read_u32(fp); /* read chunk size */
- fseek(fp, nskip, SEEK_CUR);
- fread(temp, sizeof(*temp), SIZE_ID, fp);
- }
- data_size = fa_read_u32(fp); /*语音数据大小*/
- fmt.format = format;
- fmt.channels = channels;
- fmt.samplerate = samplerate;
- fmt.bytes_per_sample = bytes_per_sample;
- fmt.block_align = block_align;
- fmt.data_size = data_size / block_align; /* byte to short */
- printf_fun(&fmt);
- return 0;
- }
程序的解析结果:
file:///C:\Users\Administrator.GSTBKSL8FUFWFLH\AppData\Roaming\Tencent\Users\285988185\QQ\WinTemp\RichOle\EO{X$RKZ60H$5@B8DAF`GEP.jpg
希望对大家能够有帮助。
xubbwd@gmail.com
[
本帖最后由 37°男人 于 2013-4-17 21:47 编辑 ]