printing of a wav header in c

时间秒杀一切 提交于 2019-12-10 11:45:17

问题


Hi i have this code for taking as input a wav file and then putting the wah header into a struct and then output it. Everything is good except audioFormat and numChannels but i can't understand why.For example it should output audioFormat: 1 and numChannels: 2 but it outputs audioFormat:0 and numChannels: 1 . I can't understand why this happens.

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);
    }
}

回答1:


subchunk1Size should be a dword, not a word (see http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html for instance). Your other chunk sizes are declared correctly.

As djf points out you also need to specify the packing and worry about endianness. The WAV header is 16-bit packed, and little-endian. With gcc, I prefer to use #pragma pack(push, 2) before the struct declaration, and #pragma pack(pop) after. And if you #include <endian.h> you can use le32toh and le16toh to read (and their counterparts htole32 and htole16 to write).




回答2:


The reason is that your struct wavHeader doesn't really look like you think it does. Let me explain. The C compiler is allowed to change the alignment of the fields in a struct. Typically that means fields are aligned at 4-byte or 8-byte-boundaries. See this discussion about C struct memory layout.

In effect your struct might be laid out something like this in memory:

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

So you see the fields subchunk1Size, audioFormat and numChannels are not contiguous! However, you can use the directive #pragma pack to enforce the layout you intended. Like this:

#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)

Sidenote: When writing this response it occurred to me that you probably also have to be careful about different endianness of multibyte values in the wave header.



来源:https://stackoverflow.com/questions/17318685/printing-of-a-wav-header-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!