[英]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.