简体   繁体   English

读取Wav文件,输出错误

[英]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. 基本上,问题是我正在尝试从.wav文件中读取数据,但是输出与MatLab中的输出不同。

In C++ the output is: 在C ++中,输出为:

-128 -128

Whereas in Matlab: 而在Matlab中:

0 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文件的头信息:

**** 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). 我已经尝试调试它,但是没有喜悦(我正在使用g ++进行编译)。 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. 我相信WAV文件中的块必须与最近的WORD边界对齐。 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. 如果在您解析的格式部分之后不在下一个单词边界,则您将不会进入while循环,并且您的代码将假定您在数据部分。

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. 我认为matlab中的值在-1到1之间进行了归一化,因此为了在c ++中获得相似的输出,您需要对其进行缩放。 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. 以-32768至32767为范围的16位样本的示例,您希望将它们缩放到-1.0至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). 这样做的方法是除以32768.0(-32768 / 32768.0 == -1,32767 / 32768.0略小于1)。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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