简体   繁体   中英

Reading Wav Files, wrong output

I have posted a simular problem before (Thought it would be better to start a fresh and hopefully, get more opinions on it). Basically, the problem is that I am trying to read the data from a .wav file, however, the output is different to that of what it is in MatLab.

In C++ the output is:

-128

Whereas in Matlab:

0

The output is completely different, not just small differences, but the whole dataset is wrong and I don't seem to know why. I think it might have something to do with endianness but, I am not sure. Here is the header information about the .wav file:

**** WAV FILE *****
Chunk IDRIFFN?
Chunk Size: 57934
Format: WAVEfmt 
Format: IDfmt 
FormatSize: 18
Format2: 1
Channel Num: 1
Sample Rate: 22050
Byte Rate: 22050
Align: 1
Bits Per Sample: 8

And the code:

file.read(this->chunkId,                                 4);
file.read(reinterpret_cast<char*>(&this->chunkSize),     4);
file.read(this->format,                                  4);

file.read(this->formatId,                                4);
file.read(reinterpret_cast<char*>(&this->formatSize),    4);
file.read(reinterpret_cast<char*>(&this->format2),       2);
file.read(reinterpret_cast<char*>(&this->numChannels),   2);
file.read(reinterpret_cast<char*>(&this->sampleRate),    4);
file.read(reinterpret_cast<char*>(&this->byteRate),      4);
file.read(reinterpret_cast<char*>(&this->align),         2);
file.read(reinterpret_cast<char*>(&this->bitsPerSample), 4);

char testing[4] = {0};
int testingSize = 0;

while(file.read(testing, 4) && (testing[0] != 'd' ||
                                testing[1] != 'a' ||
                                testing[2] != 't' ||
                                testing[3] != 'a'))
{

    file.read(reinterpret_cast<char*>(&testingSize), 4);
    file.seekg(testingSize, std::ios_base::cur);

}

this->dataId[0] = testing[0];
this->dataId[1] = testing[1];
this->dataId[2] = testing[2];
this->dataId[3] = testing[3];



file.read(reinterpret_cast<char*>(&this->dataSize),     4);

this->data = new char[this->dataSize];

file.read(data,this->dataSize);

cout << "**** WAV FILE *****" << endl;
cout << "Chunk ID" << this->chunkId << endl;
cout << "Chunk Size" << this->chunkSize << endl;
cout << "Format: " << this->format << endl;
cout << "Format ID" << this->formatId << endl;
cout << "FormatSize" << this->formatSize << endl;
cout << "Format2 " << this->format2 << endl;
cout << "Channel Num" << this->numChannels << endl;
cout << "Sample Rate" << this->sampleRate << endl;
cout << "Byte Rate" << this->byteRate << endl;
cout << "Align" << this->align << endl;
cout << "Bits Per Sample" << this->bitsPerSample << endl;
cout << "Size" << testingSize << endl;



for(unsigned i=0; (i < 20); i++){
    cout << (float) data[i] << endl;
}

return true;

Can anyone see where I am going wrong? I have tried to debug it, but, had no joy (I'm using g++ to compile). Any help would be greatly appreciated :) Sorry I keep asking this, it's really annoying me now!

Thanks

I believe chunks in a WAV file must be aligned to the nearest WORD boundary. If after the format section that you've parsed your not at the next word boundary, you wont enter the while loop and your code will assume that youre at the data section.

Similarly, if any of your chunks are an odd number of bytes long, you might run into trouble.

OK looking at the code it looks like a casting error. You are clearly trying to output twenty floats (made up of four bytes each) but what you actually output is just twenty bytes, each single byte converted to a single float. I think you might want this

for(unsigned i=0; (i < 20); i++){
    cout << ((float*) data)[i] << endl;
}

In other words you convert data to a float pointer and then apply the index. Not apply the index first and then convert to a float.

I think in matlab value are normalised in between -1 to 1, so in order to get the similar output in c++ you need to scale them. Example for the samples that are 16-bit in the range of -32768 to 32767 and you want them scaled to -1.0 to 1.0. The way to do this is to divide by 32768.0 (-32768/32768.0 == -1, 32767/32768.0 is slightly less than 1).

for(unsigned i=0; (i < 20); i++){
    cout << ((float) data[i])/32768.0 << endl;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM