【发布时间】:2021-10-26 03:08:01
【问题描述】:
我有一个程序可以读取所有 wav 文件的元数据。我使用了以下解析的 struct 和 fread 函数。
此代码遇到的问题是,对于某些 .wav RIFF 标头 fmt 文件,即使在对结构进行了如下所示的解析后,元数据读取也不正确,如果我在每个读取函数之间使用 fseek 函数会有所帮助吗?
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
using std::string;
typedef struct RIFF_CHUNCK_DISCRIPTOR {
char RIFF[4]; // RIFF Header Magic header
unsigned long ChunkSize; // RIFF Chunk Size
char WAVE[4]; // WAVE Header
};
typedef struct FMT_CHUNCK_DISCRIPTOR {
char fmt[4]; // FMT header
unsigned long Subchunk1Size; // Size of the fmt chunk
unsigned short AudioFormat; // Audio format
unsigned short NumOfChan; // Number of channels
unsigned long SamplesPerSec; // Sampling Frequency in Hz
unsigned long bytesPerSec; // bytes per second
unsigned short blockAlign; // 2=16-bit mono, 4=16-bit stereo
unsigned short bitsPerSample; // Number of bits per sample
};
typedef struct DATA_SUB_CHUNCK {
char Subchunk2ID[4]; // "data" string
unsigned long Subchunk2Size; // Sampled data length
};
int main(int argc, char* argv[]) {
const char* fileName;
cout << "enter f name " << fileName;
RIFF_CHUNCK_DISCRIPTOR RCD;
FMT_CHUNCK_DISCRIPTOR FCD;
DATA_SUB_CHUNCK DSC;
FILE* InFile = fopen(fileName, "r");
fread(&RCD, 1, sizeof(RIFF_CHUNCK_DISCRIPTOR), InFile);
fread(&FCD, 1, sizeof(FMT_CHUNCK_DISCRIPTOR), InFile);
fread(&DSC, 1, sizeof(DATA_SUB_CHUNCK), InFile);
}
我使用多个结构的原因是为了确保头文件的所有数据都被正确读取,因为尽管大多数 wav 文件头数据是有序的,但这有时是不正确的。
【问题讨论】:
-
你确定结构没有被填充对齐吗?如果你不这样做,那可能就是问题所在。你如何做到这一点是特定于实现的。你用的是什么编译器?
-
我支持@JerryJeremiah 的评论:尝试从文件中逐个字段读取结构,如果它们是正确的,那么您就有答案了。另外:为什么在 C++ 代码中使用 C 风格的读取?
-
如果您按顺序阅读,则不需要
seek。但是(1)你确定 FMT_CHUNCK_DISCRIPTOR 是完整的吗? This documentation 在块格式(wValidBitsPerSample、dwChannelMask 和 SubFormat)中显示多 2 个字节(cbSize)和 0 或 22 个字节,具体取决于该值。 (ctd.) -
(ctd. ...) (2) 通常简单地读取二进制数据并将其解释为结构是一个坏主意,至少有 3 个原因: (2.1) 它不容纳变量像这样的结构,以及 (2.2) 程序中的结构布局可能会改变即使在同一平台上使用相同的编译器具有不同的优化选项,例如当您从调试模式切换到发布模式时,更不用说在编译器和平台之间切换了,并且(2.3)整数大小和字节序在不同的平台上可能会有所不同。正确的方法是解析数据并按成员填充结构成员。
-
在 C++ 中,可以使用构造函数来获取指向二进制数据缓冲区的指针 :-)。