标志符(RIFF) |
余下所有数据的长度 |
格式类型("WAVE") |
"fmt" |
PCMWAVEFORMAT的长度 |
PCMWAVEFORMAT |
"data" |
声音数据大小 |
声音数据 |
/* RIFF WAVE file struct. * For details see WAVE file format documentation * (for example at http://www.wotsit.org). */ typedef struct WAV_HEADER_S { char riffType[4]; //4byte,资源交换文件标志:RIFF unsigned int riffSize; //4byte,从下个地址到文件结尾的总字节数 char waveType[4]; //4byte,wav文件标志:WAVE char formatType[4]; //4byte,波形文件标志:FMT(最后一位空格符) unsigned int formatSize; //4byte,音频属性(compressionCode,numChannels,sampleRate,bytesPerSecond,blockAlign,bitsPerSample)所占字节数 unsigned short compressionCode;//2byte,格式种类(1-线性pcm-WAVE_FORMAT_PCM,WAVEFORMAT_ADPCM) unsigned short numChannels; //2byte,通道数 unsigned int sampleRate; //4byte,采样率 unsigned int bytesPerSecond; //4byte,传输速率 unsigned short blockAlign; //2byte,数据块的对齐,即DATA数据块长度 unsigned short bitsPerSample; //2byte,采样精度-PCM位宽 char dataType[4]; //4byte,数据标志:data unsigned int dataSize; //4byte,从下个地址到文件结尾的总字节数,即除了wav header以外的pcm data length }WAV_HEADER;
#ifndef __WAV_H__ #define __WAV_H__ #define debug(fmt...) do { printf("[%s::%d] ", __func__, __LINE__); printf(fmt); }while(0) /* RIFF WAVE file struct. * For details see WAVE file format documentation * (for example at http://www.wotsit.org). */ typedef struct WAV_HEADER_S { char riffType[4]; //4byte,资源交换文件标志:RIFF unsigned int riffSize; //4byte,从下个地址到文件结尾的总字节数 char waveType[4]; //4byte,wave文件标志:WAVE char formatType[4]; //4byte,波形文件标志:FMT unsigned int formatSize; //4byte,音频属性(compressionCode,numChannels,sampleRate,bytesPerSecond,blockAlign,bitsPerSample)所占字节数 unsigned short compressionCode;//2byte,编码格式(1-线性pcm-WAVE_FORMAT_PCM,WAVEFORMAT_ADPCM) unsigned short numChannels; //2byte,通道数 unsigned int sampleRate; //4byte,采样率 unsigned int bytesPerSecond; //4byte,传输速率 unsigned short blockAlign; //2byte,数据块的对齐 unsigned short bitsPerSample; //2byte,采样精度 char dataType[4]; //4byte,数据标志:data unsigned int dataSize; //4byte,从下个地址到文件结尾的总字节数,即除了wav header以外的pcm data length }WAV_HEADER; typedef struct WAV_INFO_S { WAV_HEADER header; FILE *fp; unsigned int channelMask; }WAV_INFO; #endif
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "wav.h" /* func : endian judge * return : 0-big-endian othes-<span style="color: rgb(51, 51, 51); font-family: 'Courier New';font-size:12px; line-height: 24px; text-indent: 24px;">little</span>-endian */ int IS_LITTLE_ENDIAN(void) { int __dummy = 1; return ( *( (unsigned char*)(&(__dummy) ) ) ); } unsigned int readHeader(void *dst, signed int size, signed int nmemb, FILE *fp) { unsigned int n, s0, s1, err; unsigned char tmp, *ptr; if ((err = fread(dst, size, nmemb, fp)) != nmemb) { return err; } if (!IS_LITTLE_ENDIAN() && size > 1) { //debug("big-endian \n"); ptr = (unsigned char*)dst; for (n=0; n<nmemb; n++) { for (s0=0, s1=size-1; s0 < s1; s0++, s1--) { tmp = ptr[s0]; ptr[s0] = ptr[s1]; ptr[s1] = tmp; } ptr += size; } } else { //debug("<span style="color: rgb(51, 51, 51); font-family: 'Courier New';font-size:12px; line-height: 24px; text-indent: 24px;">little</span>-endian \n"); } return err; } void dumpWavInfo(WAV_INFO wavInfo) { debug("compressionCode:%d \n",wavInfo.header.compressionCode); debug("numChannels:%d \n",wavInfo.header.numChannels); debug("sampleRate:%d \n",wavInfo.header.sampleRate); debug("bytesPerSecond:%d \n",wavInfo.header.bytesPerSecond); debug("blockAlign:%d \n",wavInfo.header.blockAlign); debug("bitsPerSample:%d \n",wavInfo.header.bitsPerSample); } int wavInputOpen(WAV_INFO *pWav, const char *filename) { signed int offset; WAV_INFO *wav = pWav ; if (wav == NULL) { debug("Unable to allocate WAV struct.\n"); goto error; } wav->fp = fopen(filename, "rb"); if (wav->fp == NULL) { debug("Unable to open wav file. %s\n", filename); goto error; } /* RIFF标志符判断 */ if (fread(&(wav->header.riffType), 1, 4, wav->fp) != 4) { debug("couldn't read RIFF_ID\n"); goto error; /* bad error "couldn't read RIFF_ID" */ } if (strncmp("RIFF", wav->header.riffType, 4)) { debug("RIFF descriptor not found.\n") ; goto error; } debug("Find RIFF \n"); /* Read RIFF size. Ignored. */ readHeader(&(wav->header.riffSize), 4, 1, wav->fp); debug("wav->header.riffSize:%d \n",wav->header.riffSize); /* WAVE标志符判断 */ if (fread(&wav->header.waveType, 1, 4, wav->fp) !=4) { debug("couldn't read format\n"); goto error; /* bad error "couldn't read format" */ } if (strncmp("WAVE", wav->header.waveType, 4)) { debug("WAVE chunk ID not found.\n") ; goto error; } debug("Find WAVE \n"); /* fmt标志符判断 */ if (fread(&(wav->header.formatType), 1, 4, wav->fp) != 4) { debug("couldn't read format_ID\n"); goto error; /* bad error "couldn't read format_ID" */ } if (strncmp("fmt", wav->header.formatType, 3)) { debug("fmt chunk format not found.\n") ; goto error; } debug("Find fmt \n"); readHeader(&wav->header.formatSize, 4, 1, wav->fp); // Ignored debug("wav->header.formatSize:%d \n",wav->header.formatSize); /* read info */ readHeader(&(wav->header.compressionCode), 2, 1, wav->fp); readHeader(&(wav->header.numChannels), 2, 1, wav->fp); readHeader(&(wav->header.sampleRate), 4, 1, wav->fp); readHeader(&(wav->header.bytesPerSecond), 4, 1, wav->fp); readHeader(&(wav->header.blockAlign), 2, 1, wav->fp); readHeader(&(wav->header.bitsPerSample), 2, 1, wav->fp); offset = wav->header.formatSize - 16; /* Wav format extensible */ if (wav->header.compressionCode == 0xFFFE) { static const unsigned char guidPCM[16] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }; unsigned short extraFormatBytes, validBitsPerSample; unsigned char guid[16]; signed int i; /* read extra bytes */ readHeader(&(extraFormatBytes), 2, 1, wav->fp); offset -= 2; if (extraFormatBytes >= 22) { readHeader(&(validBitsPerSample), 2, 1, wav->fp); readHeader(&(wav->channelMask), 4, 1, wav->fp); readHeader(&(guid), 16, 1, wav->fp); /* check for PCM GUID */ for (i = 0; i < 16; i++) if (guid[i] != guidPCM[i]) break; if (i == 16) wav->header.compressionCode = 0x01; offset -= 22; } } debug("wav->header.compressionCode:%d \n",wav->header.compressionCode); /* Skip rest of fmt header if any. */ for (;offset > 0; offset--) { fread(&wav->header.formatSize, 1, 1, wav->fp); } #if 1 do { /* Read data chunk ID */ if (fread(wav->header.dataType, 1, 4, wav->fp) != 4) { debug("Unable to read data chunk ID.\n"); free(wav); goto error; } /* Read chunk length. */ readHeader(&offset, 4, 1, wav->fp); /* Check for data chunk signature. */ if (strncmp("data", wav->header.dataType, 4) == 0) { debug("Find data \n"); wav->header.dataSize = offset; break; } /* Jump over non data chunk. */ for (;offset > 0; offset--) { fread(&(wav->header.dataSize), 1, 1, wav->fp); } } while (!feof(wav->fp)); debug("wav->header.dataSize:%d \n",wav->header.dataSize); #endif /* return success */ return 0; /* Error path */ error: if (wav) { if (wav->fp) { fclose(wav->fp); wav->fp = NULL; } //free(wav); } return -1; } #if 0 int main(int argc,char **argv) { WAV_INFO wavInfo; char fileName[128]; if(argc<2 || strlen(&argv[1][0])>=sizeof(fileName)) { debug("argument error !!! \n"); return -1 ; } debug("size : %d \n",sizeof(WAV_HEADER)); strcpy(fileName,argv[1]); wavInputOpen(&wavInfo, fileName); return 0; } #endif
原文地址:http://blog.csdn.net/u013286409/article/details/47414273