在c中打印wav标题

嗨,我有这个代码,用于输入一个wav文件,然后将wah头放入一个结构,然后输出它。 一切都很好除了audioFormat和numChannels但我无法理解为什么。例如它应该输出audioFormat:1和numChannels:2但它输出audioFormat:0和numChannels:1。 我不明白为什么会这样。

typedef struct wavHeader { byte chunckID[4]; dword chunckSize; byte format[4]; byte subchunk1ID[4]; word subchunk1Size; word audioFormat; word numChannels; dword sampleRate; dword byteRate; word blockAlign; word bitsPerSample; byte subchunk2ID[4]; dword subchunk2Size; }wav_header; int check_file_name(char *filename); void list(char **array) //argv { wav_header wavHeader; FILE *pFile; if(check_file_name(array[2]) == 0) { printf("wrong file name\n"); exit(1); } pFile = fopen (array[2] ,"r"); if( pFile != NULL) { fread(&wavHeader, sizeof(wav_header), 1, pFile); fclose(pFile); printf("ChunkID: %c%c%c%c\n",wavHeader.chunckID[0],wavHeader.chunckID[1],wavHeader.chunckID[2],wavHeader.chunckID[3]); printf("ChunkSize: %d\n",wavHeader.chunckSize); printf("Format: %c%c%c%c\n",wavHeader.format[0],wavHeader.format[1],wavHeader.format[2],wavHeader.format[3]); printf("SubChunk1ID: %c%c%c%c\n",wavHeader.subchunk1ID[0],wavHeader.subchunk1ID[1],wavHeader.subchunk1ID[2],wavHeader.subchunk1ID[3]); printf("Subchunk1Size: %d\n",wavHeader.subchunk1Size); printf("AudioFormat: %d\n",wavHeader.audioFormat); printf("NumChannels: %d\n",wavHeader.numChannels); printf("SampleRate: %d\n",wavHeader.sampleRate); printf("ByteRate: %d\n",wavHeader.byteRate); printf("BlockAlign: %d\n",wavHeader.blockAlign); printf("BitsPerSample: %d\n",wavHeader.bitsPerSample); printf("Subchunk2ID: %c%c%c%c\n",wavHeader.subchunk2ID[0],wavHeader.subchunk2ID[1],wavHeader.subchunk2ID[2],wavHeader.subchunk2ID[3]); printf("Subchunk2Size: %d\n",wavHeader.subchunk2Size); } else { printf("This file doesn't exit\n"); exit(1); } } 

subchunk1Size应该是dword ,而不是word (例如,参见http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html )。 您的其他块大小已正确声明。

正如djf指出的那样,你还需要指定包装并担心字节序。 WAV标头是16位打包的,并且是小端的。 使用gcc ,我更喜欢在struct声明之前使用#pragma pack(push, 2)之后使用#pragma pack(pop) 。 如果你#include 你可以使用le32tohle16toh来阅读(和他们的同行htole32htole16写)。

原因是你的struct wavHeader并不像你认为的那样。 让我解释。 允许C编译器更改结构中字段的对齐方式。 通常,这意味着字段以4字节或8字节边界对齐。 请参阅有关C struct memory layout的讨论。

实际上,您的结构可能在内存中布局如下:

 Byte 1 2 3 4 +------+------+------+------+ | chunckID | +------+------+------+------+ | chunckSize | +------+------+------+------+ | format | +------+------+------+------+ | subchunk1ID | +------+------+------+------+ |subchunk1Size| ~~~~~ ~~~~~ << padding +------+------+------+------+ | audioFormat | ~~~~~ ~~~~~ << padding +------+------+------+------+ | numChannels | ~~~~~ ~~~~~ << padding +------+------+------+------+ .... 

所以你看到字段audioFormataudioFormatnumChannels不是连续的! 但是,您可以使用指令#pragma pack来强制执行您想要的布局。 像这样:

 #pragma pack(push, 1) // exact fit - align at byte-boundary, no padding typedef struct wavHeader { byte chunckID[4]; dword chunckSize; byte format[4]; byte subchunk1ID[4]; word subchunk1Size; word audioFormat; word numChannels; dword sampleRate; dword byteRate; word blockAlign; word bitsPerSample; byte subchunk2ID[4]; dword subchunk2Size; } wavHeader; #pragma pack(pop) 

旁注:在编写此响应时,我发现您可能还需要注意波头中多字节值的不同字节顺序。