|
标志符(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