2013-06-26 2 views
1

안녕하세요 저는 wav 파일을 입력 한 다음 구조에 wah 헤더를 넣은 다음 출력하는 코드가 있습니다. audioFormat과 numChannels를 제외한 모든 것이 좋지만 이유를 이해할 수 없습니다. 예를 들어, audioFormat : 1 및 numChannels : 2를 출력해야하지만 audioFormat : 0 및 numChannels : 1을 출력합니다. 나는 이것이 왜 일어나는 지 이해할 수 없다.wav 헤더를 C로 인쇄하기

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

다른 도구로'.wav' 파일의 헤더를 보려고 했습니까? 어쩌면 잘못된 값을 기대하고 있지만 프로그램이 올바른 값을 인쇄 중일 수 있습니다. – Paulpro

+1

한 단어 : 맞춤. (어쩌면 역시 : 패딩) –

+0

오디오 포맷 annd num wav 파일에있는 채널은 01 00 02 00입니다. 따라서 0001은 오디오 포맷 용이고 0002는 num 채널 용입니다. 그래서 나는 audioFormat : 1과 numChannels 2를 출력 할 것을 기대하고 있었다. –

답변

2

subchunk1Sizeword이 아니라 dword이어야합니다 (예 : http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html 참조). 다른 청크 크기가 올바르게 선언되었습니다.

djf points out 패킹을 지정하고 엔디안에 대해 걱정할 필요가 있습니다. WAV 헤더는 16 비트 패킹되어 있고 리틀 엔디안입니다. gcc을 사용하면 구조체 선언 전에 #pragma pack(push, 2)을 사용하고 이후에는 #pragma pack(pop)을 사용하는 것을 선호합니다. 그리고 #include <endian.h> 인 경우 le32tohle16toh을 사용하면 (및 대응하는 htole32htole16을 쓸 수 있습니다).

+0

답장에 Thnx가있다. 나는 subchunk1Size를 word에서 dword로 바꿨고 모든 것이 이제 괜찮습니다. 내가 아직도 이해하지 못하는 것은 내가 endianess에 대해 신중해야한다고 생각하지만 모든 코드를 게시 한 코드 만 있으면됩니다. 내가 우분투 리눅스 12.04에서 실행하기 때문에 그 이유가 무엇입니까? 모든 리눅스에서 동일합니까? –

+1

엔디안은 실제로 OS가 아닌 CPU에 의존합니다. 따라서 x86 또는 x86_64에서 실행 중이면 CPU가 이미 리틀 엔디안 용으로 설정되어 있습니다. 요즘은 빅 엔디안이 거의 없으며, 일부 ARM은 BE와 SPARC를 사용합니다. 임베디드 프로그래밍에서는 무리가 생기지 만 대개 데스크톱/모바일에서는 그렇지 않습니다. 그것은 당신이 코드를 BE 프로세서로 이식하려고 시도 할 때 짜증이 나서 나중에 수정해야합니다. 추가 정보 : http://en.wikipedia.org/wiki/Endianness – mtrw

4

그 이유는 귀하가 struct wavHeader이 실제로 생각한 것처럼 보이지 않기 때문입니다. 설명하겠습니다. C 컴파일러는 구조체의 필드 정렬을 변경할 수 있습니다. 일반적으로 필드는 4 바이트 또는 8 바이트 경계로 정렬됩니다. C struct memory layout에 대한 설명을 참조하십시오. 사실상

은 구조체가 메모리에 같은 것을 배치 할 수 있습니다

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

그래서 당신이 subchunk1Size, audioFormatnumChannels가 연속하고 있지 않은 필드를 참조하십시오! 그러나 지시문 #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) 

(!) 참고 : 당신이 아마 또한 웨이브 헤더의 멀티 바이트 값의 다른 엔디안에주의해야 나에게 발생이 응답을 작성합니다.