0

I have a program that should read the metadata of all wav files. I used the following parsed struct and fread functions.

The issue this code runs into is that with some .wav RIFF header fmt files the meta data read is incorrect even after paring the struct as shown below, could it help if I use a fseek function between every read function.

#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);
    
 }

The reason I used multiple structs is to ensure that all the data of the header file is read correctly since although most wav file header data is in order this is sometimes not true.

Omar
  • 164
  • 10
  • 1
    Are you sure the structs are not padded for alignment? If you aren't doing that it will probably be the problem. How you do that is implementation-specific. What compiler are you using? – Jerry Jeremiah Oct 26 '21 at 03:37
  • I second @JerryJeremiah's comment: try reading the structs field by field from the file, if they're right this way you have an answer. Also: why do you use C-style reads in C++ code? – alagner Oct 26 '21 at 05:20
  • If you read sequentially, a `seek` should not be necessary. But (1) are you sure that FMT_CHUNCK_DISCRIPTOR is complete? [This documentation](http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html) shows 2 more bytes (cbSize) an, depending on that value, 0 or 22 more bytes in the chunk format (wValidBitsPerSample, dwChannelMask and SubFormat). (ctd.) – Peter - Reinstate Monica Oct 26 '21 at 12:02
  • (ctd. ...) (2) Generally it's a bad idea to simply read binary data and interpret it as a struct, for at least 3 reasons: (2.1) It doesn't accommodate variable structures like this one, and (2.2) the structure layout in your program may change *even with the same compiler on the same platform* with different optimization options, e.g. when you switch from debug to release mode, let alone between compilers and platforms, and (2.3) integer sizes and endianness may be different on a different platform. The proper way is to parse the data and fill your struct member by member. – Peter - Reinstate Monica Oct 26 '21 at 12:03
  • In C++ one could use a constructor that gets a pointer to the binary data buffer :-). – Peter - Reinstate Monica Oct 26 '21 at 12:06

1 Answers1

3

I would open the files in binary mode, i.e. replace fopen(fileName, "r") with fopen(fileName, "rb")

On some systems (you did not tell which OS you are using, I assume Windows?) in text / non-binary mode certain chars get replace during reading.