0

I have a header RiffWav which stores all the info of the wav file


typedef struct {

    unsigned char   ChunkID[4];
    long    ChunkSize;
    unsigned char   Format[4];
    unsigned char   SubChunk1ID[4];
    unsigned long   SubChunk1Size;
    unsigned short  AudioFormat;
    unsigned short  NumChannels;
    unsigned long   SampleRate;
    unsigned long   BytesRate;
    unsigned short  BlockAlign;
    unsigned short  BitsPerSample;
    unsigned char   SubChunk2ID[4];
    unsigned long   SubChunk2Size;

} RiffWav;

I use the following functions in order to read the header information about the wav file

RiffWav         Header;
InFile = fopen(m_strFileName, "rb");
uint64_t Header_Size = 44;// sizeof(InFile);
CHAR* HeaderBuffer = new CHAR[Header_Size];
fread(HeaderBuffer, 0x01, Header_Size, InFile);

int NumChannels = HeaderBuffer[22] + HeaderBuffer[23];
int BitsPerSample = HeaderBuffer[34] + HeaderBuffer[35];
uint64_t BUFFER_SIZE = HeaderBuffer [40]+ HeaderBuffer[41]+ HeaderBuffer[42]+ HeaderBuffer[43]/  (NumChannels* (BitsPerSample / 8));
CHAR* buffer = new CHAR[BUFFER_SIZE];

The info read thou is mostly wrong like the number of channels returned is 25153 and not 2

EDIT: So after testing with a few different wav files I'm pretty sure that the main issue is that the data read into the buffer is not always in the same order (most wav files are with a few exceptions), so my question now is there a way I can scan the header array after assigning it all the info about the file for the number of channels and all that important stuff

Omar
  • 164
  • 10
  • `sizeof(RiffWav)` - this is probably wrong because it'll have padding added by your compiler for your arch. If you really are going to map binary files directly to structs then you should also use fixed-size types instead of implementation-defined types (e.g. `int32_t` instead of `unsigned int`). – Dai Oct 20 '21 at 16:40
  • Also, in C++ you don't need to use C-style `typedef struct`. Just define a `struct` the same way you would a `class`. – Dai Oct 20 '21 at 16:41
  • how could I map binary files non-directly to structs – Omar Oct 20 '21 at 16:49
  • This is undefined behavior. Note that in standard C++ you don't have control over alignment so some fields can be in places you are not expecting. – Marek R Oct 20 '21 at 16:50
  • Note also that `sizeof(long)` changes depending on platform. See https://godbolt.org/z/f79brvb6n – Marek R Oct 20 '21 at 16:53
  • 1
    Another method is to allocate a buffer, read from file into buffer, then load your struct from the buffer (a lot of casting is involved). I prefer this method, as it doesn't involve the possible padding between members. – Thomas Matthews Oct 20 '21 at 16:53
  • 1
    https://godbolt.org/z/rxa7hvzbP – Marek R Oct 20 '21 at 17:00
  • @ThomasMatthews how could I allocate the buffer without knowing the size of it – Omar Oct 20 '21 at 17:01
  • @Omar did you noticed that your issue depends on compiler and its settings? You should provide information what compiler you are suing and its settings. Note also that reading directly into a struct is undefined behavior https://stackoverflow.com/q/3711233/1387438 – Marek R Oct 20 '21 at 17:04
  • Get the data sheet on wav format. Look at the size of the header, *according to the data sheet*. The wav format should describe the fields, and their widths. The buffer would be the size of the header. – Thomas Matthews Oct 20 '21 at 17:05
  • @Omar By using an auto-expanding buffer, like `std::vector` (though this isn't always the _best_ approach...) – Dai Oct 20 '21 at 17:36
  • If this is for Windows you can use [mmio](https://learn.microsoft.com/en-us/windows/win32/api/mmiscapi/) functions. Or at least use it as a guide to figure out the block sizes and adapt it. – Barmak Shemirani Oct 20 '21 at 18:12
  • @MarekR struct layout is not *undefined*, it's *platform defined*. Almost all platforms use natural alignment (which means a 4-byte `int` will always be aligned to an address that is a multiple of 4), and pack variables as close as possible without violating their alignment restrictions. The only thing wrong with the struct in the question is that `long` can be 4 or 8 bytes depending on the platform, using `uint32_t` would ensure it's always the 4 bytes expected by the WAV format. And of course also use `uint16_t` instead of `short`. – G. Sliepen Oct 22 '21 at 19:44

0 Answers0