【问题标题】:Parsing a Riff wav header解析 Riff wav 标头
【发布时间】: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++ 中,可以使用构造函数来获取指向二进制数据缓冲区的指针 :-)。

标签: c++ wav riff


【解决方案1】:

我会以二进制模式打开文件,即替换 fopen(fileName, "r")fopen(fileName, "rb")

在某些系统上(您没有说明您使用的是哪个操作系统,我假设是 Windows?)在文本/非二进制模式下,某些字符会在读取过程中被替换。

【讨论】:

    猜你喜欢
    • 2014-11-19
    • 2021-01-03
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-31
    • 1970-01-01
    相关资源
    最近更新 更多