用c语言打印wav头文件
嗨,我有这段代码,用于输入一个wav文件,然后将wah头放入一个结构,然后输出它。除了audioFormat和NumChannel之外,其他都很好,但我不明白为什么。例如,它应该输出audioFormat:1和NumChannel:2,但它输出audioFormat:0和NumChannel:1。我不明白为什么会这样用c语言打印wav头文件,c,wav,C,Wav,嗨,我有这段代码,用于输入一个wav文件,然后将wah头放入一个结构,然后输出它。除了audioFormat和NumChannel之外,其他都很好,但我不明白为什么。例如,它应该输出audioFormat:1和NumChannel:2,但它输出audioFormat:0和NumChannel:1。我不明白为什么会这样 typedef struct wavHeader { byte chunckID[4]; dword chunckSize; byte format[4];
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);
}
}
原因是您的
struct wavHeader
看起来并不像您想象的那样。让我解释一下。允许C编译器更改结构中字段的对齐方式。通常这意味着字段以4字节或8字节边界对齐。请参阅有关的讨论
实际上,您的结构在内存中的布局可能如下所示:
Byte 1 2 3 4
+------+------+------+------+
| chunckID |
+------+------+------+------+
| chunckSize |
+------+------+------+------+
| format |
+------+------+------+------+
| subchunk1ID |
+------+------+------+------+
|subchunk1Size| ~~~~~ ~~~~~ << padding
+------+------+------+------+
| audioFormat | ~~~~~ ~~~~~ << padding
+------+------+------+------+
| numChannels | ~~~~~ ~~~~~ << padding
+------+------+------+------+
....
旁注:在编写此响应时,我突然想到,您可能还必须注意wave头中多字节值的不同endianness 原因是您的
struct wavHeader
看起来不像您想象的那样。让我解释一下。允许C编译器更改结构中字段的对齐方式。通常这意味着字段以4字节或8字节边界对齐。请参阅有关的讨论
实际上,您的结构在内存中的布局可能如下所示:
Byte 1 2 3 4
+------+------+------+------+
| chunckID |
+------+------+------+------+
| chunckSize |
+------+------+------+------+
| format |
+------+------+------+------+
| subchunk1ID |
+------+------+------+------+
|subchunk1Size| ~~~~~ ~~~~~ << padding
+------+------+------+------+
| audioFormat | ~~~~~ ~~~~~ << padding
+------+------+------+------+
| numChannels | ~~~~~ ~~~~~ << padding
+------+------+------+------+
....
旁注:在编写此响应时,我突然想到,您可能还必须注意wave头中多字节值的不同endianness
subchunk1Size
应该是一个dword
,而不是word
(参见示例)。您的其他块大小声明正确
因为您还需要指定包装,并担心端度。WAV头是16位压缩的,并且是小端。对于
gcc
,我更喜欢在结构声明之前使用#pragma-pack(push,2)
,在结构声明之后使用#pragma-pack(pop)
。如果你使用#include
,你可以使用le32toh
和le16toh
来阅读(以及它们的对应项htole32
和htole16
来写)。subchunk1Size
应该是dword
,而不是单词
(例如,请参见)。您的其他块大小声明正确
因为您还需要指定包装,并担心端度。WAV头是16位压缩的,并且是小端。对于
gcc
,我更喜欢在结构声明之前使用#pragma-pack(push,2)
,在结构声明之后使用#pragma-pack(pop)
。如果您#include
,您可以使用le32toh
和le16toh
来阅读(以及它们对应的htole32
和htole16
来写)。您是否尝试过使用其他工具查看.wav
文件的标题?也许您期望的值不正确,但您的程序正在打印正确的值。一个词:对齐。(可能也是:填充)wav文件中的音频格式annd num通道为01 00 02 00。因此0001表示音频格式,0002表示num通道。所以我希望它能输出audioFormat:1和numChannels 2您是否尝试过使用其他工具查看.wav
文件的标题?也许您期望的值不正确,但您的程序正在打印正确的值。一个词:对齐。(可能也是:填充)wav文件中的音频格式annd num通道为01 00 02 00。因此0001表示音频格式,0002表示num通道。所以我希望它能输出audioFormat:1和numChannels 2TNX,以供其他人使用。我把尺寸从word改为dword,现在一切都好了。我仍然不明白的是,我应该对endianess保持谨慎,但仅仅是我发布的代码,一切都很好。这是因为我在ubuntu linux 12.04上运行它吗?所有linux都是一样的吗?Endianness实际上取决于CPU,而不是操作系统。因此,如果您在x86或x86_64上运行,那么您的CPU已经为little endian设置好了。事实上,现在大端星已经很少见了,一些武器已经安装好了,还有一些斯巴克。它出现在许多嵌入式编程中,但通常不在桌面/移动设备上。不过,当您尝试将代码移植到BE处理器并在以后进行修复时,它确实很糟糕。更多信息:Thnx的回复家伙。我把尺寸从word改为dword,现在一切都好了。我仍然不明白的是,我应该对endianess保持谨慎,但仅仅是我发布的代码,一切都很好。这是因为我在ubuntu linux 12.04上运行它吗?所有linux都是一样的吗?Endianness实际上取决于CPU,而不是操作系统。因此,如果您在x86或x86_64上运行,那么您的CPU已经为little endian设置好了。事实上,现在大端星已经很少见了,一些武器已经安装好了,还有一些斯巴克。它出现在许多嵌入式编程中,但通常不在桌面/移动设备上。不过,当您尝试将代码移植到BE处理器并在以后进行修复时,它确实很糟糕。更多信息: