簡體   English   中英

Struct C / C ++-讀取WAV標頭32位浮點數-字節偏移錯誤

[英]Struct C/C++ - Reading WAV Header 32 Bit Float - byte offset wrong

我使用一種結構來讀取音頻格式為3(= IEEE FLOAT 32位)的Wav文件,帶有58字節的wav標頭。 問題:字節38以“事實”塊開頭。 這似乎還可以。 DwFactSize應該具有42的偏移量。問題開始了! 偏移量是44 !!! 首先我想,問題出在填充位上。 所以我嘗試了uints,無符號字符和屬性 ((packed))。 這不會改變任何東西。

這是wav標頭的定義:

0-3'RIFF'/'RIFX'Little / Big-endian

4-7 wRiffLength文件長度減去8字節riff標頭

8-11'WAVE'

12-15'fmt'

16-19 wFmtSize格式塊的長度減去8個字節的標頭

20-21 wFormatTag標識PCM,ULAW等

22-23 wChannels

每通道每秒24-27 dwSamplesPerSecond個采樣

28-31 dwAvgBytesPerSec對於壓縮格式而言非常重要

32-33 wBlockAlign基本塊大小

34-35 wBitsPerSample對於壓縮格式而言非常重要

(直到字節35像通常的44字節標題一樣)

36-37 wExtSize = 0格式擴展名的長度

38-41“事實”

42-45 dwFactSize =事實塊的長度減去8個字節的標頭

46-49 dwSamples實際寫出的實際樣本數

50-53個“數據”

54-57 dwDataLength數據塊的長度減去8個字節的標頭


輸出:

...

直到這里...正確...

事實[4] 38

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

DwFactSize 44

dwSamplesWrited 48

數據[4] 52

dwDataLength 56

快速破解以顯示偏移問題:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <cstring>
#include <iostream>
#include <cstddef>

typedef struct  WAV_HEADER
{
unsigned char       RIFF[4];        /* RIFF Header      */ //Magic header
unsigned long       ChunkSize;      /* RIFF Chunk Size  */
unsigned char       WAVE[4];        /* WAVE Header      */
unsigned char       fmt[4];         /* FMT header       */
unsigned long       Subchunk1Size;  /* Size of the fmt chunk: 16=PCM, 18=IEEE Float, 40=Extensible                     */
unsigned short      AudioFormat;    /* Audio format 1=PCM, 3=IEEE Float, 6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM, 65534=Extensible */
unsigned short      NumOfChan;      /* Number of channels 1=Mono 2=Stereo                   */
unsigned long       SamplesPerSec;  /* Sampling Frequency in Hz                             */
unsigned long       bytesPerSec;    /* bytes per second */
unsigned short      blockAlign;     /* 2=16-bit mono, 4=16-bit stereo , 6=24-bit stereo,8=32-bit stereo*/
unsigned short      bitsPerSample;  /* Number of bits per sample, inkl. hier=36 bytes  */
unsigned short      wExtSize;       /*  2 byte, wExtSize = 0  the length of the format extension   */
unsigned char       Fact[4];        /* "fact"  string   */
/*Problem here! -> +2bytes*/
unsigned long       DwFactSize;     /* Sampled data length,  inkl. hier bei 44 bytes */
unsigned long       dwSamplesWritten;
unsigned char       Data[4];        /* leerer string falls extensible -> Beginn nicht nach 44 sondern 68!  */
unsigned long       dwDataLength;   /* raw DataLength */
}__attribute__((packed)) wav_hdr;


int getFileSize(FILE *inFile);

int main(int argc,char *argv[])
{
char *file;
file = argv[1];
wav_hdr wavHeader;
FILE *wavFile;
int headerSize = sizeof(wav_hdr),filelength = 0;
wavFile = fopen(file,"r");
if(wavFile == NULL)
{
    printf("\nCan not open wave file. Usage: program [file] \n");
    exit(EXIT_FAILURE);
}

fread(&wavHeader,headerSize,1,wavFile);
filelength = getFileSize(wavFile);
fclose(wavFile);


std::cout << "\nRIFF " << offsetof(WAV_HEADER, RIFF) <<  std::endl;
std::cout << "\nChunkSize " << offsetof(WAV_HEADER, ChunkSize) <<  std::endl;
std::cout << "\nWAVE[4] " << offsetof(WAV_HEADER, WAVE) <<  std::endl;
std::cout << "\nfmt[4] " << offsetof(WAV_HEADER, fmt) <<  std::endl;
std::cout << "\nSubchunk1Size " << offsetof(WAV_HEADER, Subchunk1Size) <<  std::endl;
std::cout << "\nAudioFormat " << offsetof(WAV_HEADER, AudioFormat) <<  std::endl;
std::cout << "\nNumOfChan " << offsetof(WAV_HEADER, NumOfChan) <<  std::endl;
std::cout << "\nSamplesPerSec " << offsetof(WAV_HEADER, SamplesPerSec) <<  std::endl;
std::cout << "\nbytesPerSec " << offsetof(WAV_HEADER, bytesPerSec) <<  std::endl;
std::cout << "\nblockAlign " << offsetof(WAV_HEADER, blockAlign) <<  std::endl;
std::cout << "\nbitsPerSample " << offsetof(WAV_HEADER, bitsPerSample) <<  std::endl;
std::cout << "\nwExtSize (2) " << offsetof(WAV_HEADER, wExtSize) <<  std::endl;
std::cout << "\nFact[4] " << offsetof(WAV_HEADER, Fact) <<  std::endl;

std::cout << "\nDwFactSize " << offsetof(WAV_HEADER, DwFactSize) <<  std::endl;
std::cout << "\ndwSamplesWritten " << offsetof(WAV_HEADER, dwSamplesWritten) <<  std::endl;
std::cout << "\nData[4] " << offsetof(WAV_HEADER, Data) <<  std::endl;
std::cout << "\ndwDataLength " << offsetof(WAV_HEADER, dwDataLength) <<  std::endl;


return 0;
}

int getFileSize(FILE *inFile)
{
int fileSize = 0;
fseek(inFile,0,SEEK_END);
fileSize=ftell(inFile);
fseek(inFile,0,SEEK_SET);
return fileSize;
}

要生成這樣的32位浮點型88200 Wav文件:sox input16_44100.wav -b 32 -e float output32F_88200.wav rate -s -a -v -L 88200

顯然, Fact[]DwFactSize之間有2個字節的填充。

我懷疑這是因為您在那里使用了typedef 只需將其編寫為常規C ++定義即可: struct __attribute__((packed)) WAV_HEADER { ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM