Sample Value | size in byte | Description | offset |
---|---|---|---|
Chunk ID | 4 | Marks the file as a riff file.,Characters are each 1 byte long That should be "RIFF". |
0 |
Chunk Size | 4 | 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size) | 4 |
Format | 4 | File Type Header.,For wave purposes, it always equals "WAVE". | 8 |
Format Mark | 4 | Format chunk marker.,Includes trailing null. should be "fmt " | 12 |
Sub-chunk 1 Size | 4 | Length of format data | 16 |
Audio Format | 2 | PCM = 1 (i.e. Linear quantization),Values other than 1 indicate some,form of compression. | 20 |
Number of Channels | 2 | Mono = 1, Stereo = 2, etc. | 22 |
Sampling Rate | 4 | Number of Samples per second | 24 |
Byte Rate | 4 | Byte per second, it should be SamplingRate*NumberOfChannel*BitsPerSample/8 | 28 |
Block Align | 2 | Byte for whole sampling point,, it should be NumberOfChannel*BitsPerSample/8 | 32 |
Bits Per Sample | 2 | 8 bits = 8, 16 bits = 16 | 34 |
Extra Data Header | ?(2) | Extra wave note, in most,case, that "size" is 0 (no extra data), or 2. This size could be computed by "Subchunk1Size - 16 " |
36 |
Extra Data | ? | extra data, most for audio notes(artist, album, publish year, music type. etc) | ? |
Sub chunk 2 ID | 4 | Contains the letters "data" | ?? |
Sub chunk 2 size | 4 | Audio data length | ?? + 4 |
Audio data | Audio data length | Audio data | ?? + 8 |
#include <stdio.h> #include <stdlib.h> #include <string.h> #ifndef TRUE #define TRUE (1) #define FALSE (0) #endif #define MAX_STR_LEN 256 #define IS_STR_EQUAL(STR1, STR2) ((0 == strncmp((STR1),(STR2), MAX_STR_LEN) )?TRUE:FALSE ) #ifdef _MSC_VER #pragma warning(disable:4996)/*fuss*/ #include <stdarg.h> int snprintf(char *pBuf, size_t maxN, const char *pFmt, ...) { int len; va_list argList; va_start(argList, pFmt); len = vsprintf_s(pBuf, maxN, pFmt, argList); va_end(argList); return len; }/*snprintf*/ #endif unsigned int GetFileSize(FILE *pFile) { unsigned int currentLen, fileSize; currentLen = ftell(pFile); fseek(pFile,0, SEEK_END); fileSize = ftell(pFile); fseek(pFile,currentLen ,SEEK_SET); return (unsigned int)fileSize; }/*GetFileSize*/ unsigned int GetRemainderFileSize(FILE *pFile) { unsigned int currentLen, fileSize; currentLen = ftell(pFile); fseek(pFile,0, SEEK_END); fileSize = ftell(pFile); fseek(pFile,currentLen ,SEEK_SET); return (unsigned int)(fileSize - currentLen ); }/*GetRemainderFileSize*/ typedef struct _WaveFeature { char ChunkID[4]; /* "RIFF" Header */ unsigned int ChunkSize; /* 36 + SubChunk2Size, or more precisely:4 + (8 + SubChunk1Size) + (8 + SubChunk2Size) */ char Format[4]; /* "WAVE" */ char fmt[4]; /* "fmt "*/ unsigned int Subchunk1Size; /* Size of the fmt chunk */ unsigned short AudioFormat; /* Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM */ unsigned short NumChannels; /* Number of channels 1=Mono 2=Sterio */ unsigned int SampleRate; /* Sampling Frequency in Hz*/ unsigned int ByteRate; /* bytes per second, SampleRate * NumChannels * BitsPerSample/8*/ unsigned short BlockAlign; /* 2=16-bit mono, 4=16-bit stereo, NumChannels * BitsPerSample/8*/ unsigned short BitsPerSample; /* Number of bits per sample */ } WaveFeature; typedef struct _WaveData { char Subchunk2ID[4]; /* "data" string */ unsigned int Subchunk2Size; /* Sampled data length */ } WaveData; int GetWaveFeatures(unsigned char *pWaveHead, unsigned short *pNumChannel, unsigned int *pNumSamplesPerSec, unsigned short *pBitsPerSample, unsigned int *pBytesPerSec, int *pIsContentExtaBytes) { char charWord[MAX_STR_LEN]; snprintf(&charWord[0], MAX_STR_LEN, "RIFF"); if(0 != memcmp( &pWaveHead[0], &charWord[0], 4) ) return -1; snprintf(&charWord[0], MAX_STR_LEN, "WAVE"); if(0 != memcmp( &pWaveHead[8], &charWord[0], 4) ) return -1; snprintf(&charWord[0], MAX_STR_LEN, "fmt "); if(0 != memcmp( &pWaveHead[12], &charWord[0], 4) ) return -1; unsigned int chunkSize; memcpy( &chunkSize, &pWaveHead[16], 4); *pNumChannel = *((unsigned short*)(pWaveHead + 22)); *pNumSamplesPerSec = *((unsigned int*)(pWaveHead + 24)); *pBitsPerSample = *((unsigned short*)(pWaveHead + 34)); *pBytesPerSec = *((unsigned int*)(pWaveHead + 28)); /*ByteRate */ if(*pBytesPerSec != (*pNumSamplesPerSec)*(*pNumChannel)*(*pBitsPerSample/8)) return -2; int blockAlign; blockAlign = *((unsigned short*)(pWaveHead + 32)); if(blockAlign != (*pNumChannel)*(*pBitsPerSample/8)) return -2; int extraWavHeaderBytes; extraWavHeaderBytes = *((unsigned int*)(pWaveHead + 16)) - 16; if(2 == extraWavHeaderBytes) { *pIsContentExtaBytes = TRUE; } else { return -3; }/*if 2 == extraWavHeaderBytes*/ return 0; }/*GetWaveInfo*/ int GetWaveLength(unsigned char *pWaveHead, unsigned int *pAudioDataLen) { char charWord[MAX_STR_LEN]; snprintf(&charWord[0], MAX_STR_LEN, "data"); if(0 != memcmp( &pWaveHead[0], &charWord[0], 4) ) return -1; *pAudioDataLen = *((unsigned int*)(pWaveHead + 4)); return 0; }/*GetWaveLength*/ #define KB (1024) #define BLOCK_SIZE (8*KB) #define SEND_SIZE (8*KB) int main(int argc, char *argv[]) { char inputFileName[MAX_STR_LEN]; snprintf(&inputFileName[0], MAX_STR_LEN, "03 Rondeau in C Minor.wav"); #if defined(__MACH__) && defined(_DEBUG)/*xcode stupid...*/ char tempStr[MAX_STR_LEN]; snprintf(&tempStr[0], MAX_STR_LEN, "../../../../../"); strncat(&tempStr[0], &inputFileName[0], strnlen(&inputFileName[0],MAX_STR_LEN)); memset(&inputFileName[0], 0, MAX_STR_LEN); strncpy(&inputFileName[0], &tempStr[0], strnlen(&tempStr[0],MAX_STR_LEN)); #endif int k; k = 0; while (k < argc) { if( 0 == strncmp("-i",argv[k], MAX_STR_LEN)) { if(k + 1 < argc) { snprintf(inputFileName, MAX_STR_LEN, "%s", argv[k + 1]); } else { printf("-i should be fellowed by input wav file."); }/*if*/ }/*if strncmp*/ k++; }/*while opt*/ FILE *pWaveFile; pWaveFile = fopen(&inputFileName[0], "rb"); if(NULL == pWaveFile) { printf("open file %s error \n", inputFileName); return -1; }/*if NULL == pWaveFile*/ printf("file : %s\n", inputFileName); WaveFeature wavFea; fread(&wavFea, sizeof(WaveFeature), 1, pWaveFile); unsigned short nChannel; unsigned int nSamplesPerSec; unsigned short bitsPerSample; unsigned int audioDataLen; unsigned int bytesPerSec; int isContentExtaBytes; int sts; sts = GetWaveFeatures((unsigned char*)&wavFea, &nChannel, &nSamplesPerSec, &bitsPerSample,&bytesPerSec, &isContentExtaBytes); if(-1 == sts) { printf("not a wav format\n"); return -1; } else if(-2 == sts) { printf("wav format do not be consisted\n"); return -1; } else if(-3 == sts) { printf("extra parameters are not known\n"); }/*if -1 == sts*/ printf("%u channel\n", nChannel); printf("simpling frequency = %u\n", nSamplesPerSec); printf("%u bits Per Sample\n", bitsPerSample); if(FALSE != isContentExtaBytes) { char exteraParameter[2*MAX_STR_LEN]; char readBuff[MAX_STR_LEN]; char charWord[8]; int ii; memset(&exteraParameter[0], 0, 2*MAX_STR_LEN); memset(&readBuff[0], 0, MAX_STR_LEN); memset(&charWord[0], 0, 8); sprintf(&charWord[0], "data"); ii = 0; while(1) { fread(&readBuff[0], 1, 4, pWaveFile); if(0 == memcmp( &readBuff[0], &charWord[0], 4)) { fseek(pWaveFile, -4, SEEK_CUR); break; }/*if*/ if(2*MAX_STR_LEN - ii > 0 ) { memcpy(&exteraParameter[ii], &readBuff[0], 4); ii += 4; }/*if surplusLen > 0*/ }/*while 1*/ printf("extera parameter:\n"); for(int i = 0; i< ii; i++) { if(0 != i && 0 == exteraParameter[i] && 0 != exteraParameter[i - 1]) printf("\n"); else printf("%c", exteraParameter[i]); }/*fir */ printf("\n"); }/*if FALSE != isContentExtaBytes*/ WaveData wavData; fread(&wavData, sizeof(WaveData), 1, pWaveFile); sts = GetWaveLength((unsigned char*)&wavData, &audioDataLen); if(-1 == sts) { printf("not a wav format\n"); return -1; } audioDataLen = wavData.Subchunk2Size; if(GetRemainderFileSize(pWaveFile) != audioDataLen) { printf("warning: data length is not consistency\n"); unsigned int remainderLen; remainderLen = GetRemainderFileSize(pWaveFile); printf("remainderLen = %u\n", remainderLen); printf("audioDataLen = %u\n", audioDataLen); if((unsigned int)audioDataLen > remainderLen) audioDataLen = remainderLen; }/*if */ float audioTime; audioTime = (float)audioDataLen/bytesPerSec; printf("audio time = %3.2f sec", audioTime); if(audioTime > 60.0f) printf(" (%4.3fmins)\n", audioTime/60.0f); else printf("\n"); return 0; }/*main*/