0

I would like to open chosen WAV file, read it's header and then put audio samples from this into arrays. I have already managed to read header and I think it looks quite fine but there is one question. After header in WAV file are placed samples and I would like to know which of parameter of header specify how many of samples there are because I don't quite understand these parameters yet. Also I would like to know if it is good when SubChunk2Size is equal to 3452816845.

EDIT// As I already know that received value of SubChunk2Size is wrong, I want to know why is that and how can I correct this.

Here is page I took under consideration: http://soundfile.sapp.org/doc/WaveFormat/

Here is my code:

#include "pch.h"
#include <iostream>
#include <time.h>
#include <cstdlib>
#include <stdio.h>
#include <cmath>
#include <iostream>
#include <Windows.h>



using namespace std;


struct WAVfile {
    FILE *fp;
    //The "RIFF" chunk descriptor
    char  ChunkID[4];
    DWORD ChunkSize;
    char  Format[4];
    //The "fmt" sub-chunk
    char  Subchunk1ID[4];
    DWORD Subchunk1Size;
    short AudioFormat;
    short NumChannels;
    DWORD SampleRate;
    DWORD ByteRate;
    short BlockAlign;
    short BitsPerSample;
    //The "data" sub-chunk
    char  Subchunk2ID[4];
    DWORD Subchunk2Size;


    WAVfile(const char* title) {
        this->fp = NULL;
        fp = fopen(title, "r");
        if (!fp) {
            getError("Error: Failed to open file");
        }
        fread(ChunkID, sizeof(char), 4, fp);
        if (!strcmp(ChunkID, "RIFF")) {
            getError("Error: Not RIFF format");
        }
        fread(&ChunkSize, sizeof(DWORD), 1, fp);
        fread(Format, sizeof(char), 4, fp);
        if (!strcmp(Format, "WAVE")) {
            getError("Error: Not WAVE format");
        }
        fread(Subchunk1ID, sizeof(char), 4, fp);
        if (!strcmp(Subchunk1ID, "fmt ")) {
            getError("Error: Not fmt");
        }
        fread(&Subchunk1Size, sizeof(DWORD), 1, fp);
        fread(&AudioFormat, sizeof(short), 1, fp);
        fread(&NumChannels, sizeof(short), 1, fp);
        fread(&SampleRate, sizeof(DWORD), 1, fp);
        fread(&ByteRate, sizeof(DWORD), 1, fp);
        fread(&BlockAlign, sizeof(short), 1, fp);
        fread(&BitsPerSample, sizeof(short), 1, fp);
        fread(Subchunk2ID, sizeof(char), 4, fp);
        if (!strcmp(Subchunk2ID, "data")) {
            getError("Error: Missing Data");
        }
        fread(&Subchunk2Size, sizeof(DWORD), 1, fp);

        cout << "The \"RIFF\" chunk descriptor" << endl;
        cout << "ChunkID:\t\t" << ChunkID << endl;
        cout << "ChunkSize:\t\t" << ChunkSize << endl;
        cout << "Format:\t\t\t" << Format << endl;
        cout << endl;
        cout << "The \"fmt\" sub-chunk" << endl;
        cout << "Subchunk1ID:\t\t" << Subchunk1ID << endl;
        cout << "Subchunk1Size:\t\t" << Subchunk1Size << endl;
        cout << "AudioFormat:\t\t" << AudioFormat << endl;
        cout << "NumChannels:\t\t" << NumChannels << endl;
        cout << "SampleRate:\t\t" << SampleRate << endl;
        cout << "ByteRate:\t\t" << ByteRate << endl;
        cout << "BlockAlign:\t\t" << BlockAlign << endl;
        cout << "BitsPerSample:\t\t" << BitsPerSample << endl;
        cout << endl;
        cout << "The \"data\" sub-chunk" << endl;
        cout << "Subchunk2ID:\t\t" << Subchunk2ID << endl;
        cout << "Subchunk2Size:\t\t" << Subchunk2Size << endl;

        char n;
        cin >> n;
    }

    void getError(const char* message) {
        cout << message << endl;
        char n;
        cin >> n;
    }

};



int main()
{
    //MOJE
    //const int N = 8;// 2 * 16;    // 65536 sampli na sekundę
    //complex *x,   *Xfft;
    //complex *d_x, *d_Xfft;
    //int size = N * sizeof(complex);
    WAVfile *wavfile = new WAVfile("Test2.wav");


    return 0;
}
Zekhire
  • 115
  • 1
  • 2
  • 8
  • 3452816845 seems odd. If you look at the file properties in another program, does it show a mono file with 8 bit sampes? – Ted Lyngmo Dec 16 '18 at 12:06
  • in your link it is written "Subchunk2Size == NumSamples * NumChannels * BitsPerSample/8" and Subchunk2Size and NumChannels and BitsPerSample are known, so easy to compute NumSamples no ? – bruno Dec 16 '18 at 12:07
  • Is there possibility that I have not correctly read these parameters? Some of these are big endians and the others are little endians. I read everything in one way and don't consider if it is big or small endians. – Zekhire Dec 16 '18 at 12:14
  • What is weird is that that value of SubChunk2Size is equal to 3452816845 for every file I check. – Zekhire Dec 16 '18 at 13:22
  • That's definitely wrong :-) – Ted Lyngmo Dec 16 '18 at 14:00
  • This question is pretty much unclear, I don't think it can be answered as such and therefore should probably be closed. Unless you can edit it to clarify what you are asking for ? (see https://stackoverflow.com/help/how-to-ask ) – kebs Dec 16 '18 at 14:05
  • I have edited title of my post and added to content "EDIT//" section. – Zekhire Dec 16 '18 at 14:23
  • Such values need to be inspected in hex: 3452816845 = 0xCDCDCDCD. Once you realized it looks fancy you go [there](https://stackoverflow.com/a/127404/868014) to find out how exactly environment helps you out by providing a "special" value. At this time you read uninitialized memory, so most likely the variable is never actually read into. From there you have no more reason to look how it's related to audio file exactly, instead you should be checking your code about how it comes it skips variable initialization. – Roman R. Dec 16 '18 at 15:32
  • That is very weird. Why is that that despite I have instruction that read value from file into variable, this variable hasn't this value? Moreover when I changing conditions in if instructions from "!strcmp(ChunkID, "RIFF")" into !strcmp(ChunkID, "fooo") then i don't get communicate about "Not RIFF format". – Zekhire Dec 16 '18 at 15:55
  • You have some places where you do stuff that can go terribly wrong: Example: `char Format[4]; fread(Format, sizeof(char), 4, fp); strcmp(Format, "WAVE");` The `strcmp` will check if `Format[4] == '\0'` which is out of bounds. In this comparison, you'd need `strncmp` (or `memcmp`) to limit it to 4 chars. – Ted Lyngmo Dec 17 '18 at 16:29

1 Answers1

1

In all likelihood, your file exists, but is very short.
strcmp() doesn't work the way you think it does - it returns 0 ("FALSE") when strings are equal and a non-zero value if they aren't. Since you also don't control what fread() returns to you (number of bytes) and your usage of strcmp() is also wrong for the reason pointed out in comments, the file can contain anything and you won't notice. For the reference, here's the output of your program for my test WAV file:

The "RIFF" chunk descriptor
ChunkID:                RIFF$фW
ChunkSize:              5760036
Format:                 WAVEfmt ►

The "fmt" sub-chunk
Subchunk1ID:            fmt ►
Subchunk1Size:          16
AudioFormat:            1
NumChannels:            2
SampleRate:             8000
ByteRate:               32000
BlockAlign:             4
BitsPerSample:          16

The "data" sub-chunk
Subchunk2ID:            data
Subchunk2Size:          5760000

Notice odd symbols and especially Format: WAVEfmt ► line. std::cout expects null-terminated strings, with special symbol \0 at the end, and reads symbols from the memory until it finds one or OS kills your process for reading illegal memory. One way to fix this part would be to declare ChunkID and such as char ChunkID[5]; and then initialize ChunkID[4] = '\0'. Another approach would be to stop treating these byte arrays as strings and output them as random bytes they are:
std::cout << ChunkID[0] << ChunkID[1] << ChunkID[2] << ChunkID[3]; or
std::cout << std::string(ChunkID, 4);

Community
  • 1
  • 1
Abstraction
  • 1,108
  • 11
  • 25