问题描述
我正在尝试读取 2 的补码中存储在波形文件中的 24 位二进制数据。它存储为小端。 我正在尝试将 3 个字符数组重新解释为 int32_t,然后将其转换为 double。 我非常接近,但不知何故无法正常工作。
if (wavHead.getBits_per_Sample() == 24) {
unsigned char int24[3];
while (!is.eof()) {
int32_t val = 0;
is.read((char *) &int24,sizeof(char) * 3); //ifstream
if(int24[2] & 0x80) {
val = 0xff; //Checking for sign (MSB) and inverting it to bitshift to int32 MSB
int24[2] &= ~(0x80);
}
val = (val << 8) | ((u_int32_t)int24[2]);
val = (val << 8) | ((u_int32_t)int24[1]);
val = (val << 8) | ((u_int32_t)int24[0]);
cout << val / 8388608.0 << endl;
data.push_back(val / 8388608.0);
}
}
这是信号图。它应该是一个简单的 440 Hz 正弦音,但它没有居中,看起来有点可疑: plot of the wave file
感谢您的帮助:)
解决方法
这是错误的:
int24[2] &= ~(0x80);
考虑数字-1,编码成3个字节为FF FF FF。我们在 val
中想要的结果是 0xFFFFFFFF,其中没有未设置的位,这通常适用:在符号扩展时,您要扩展的位本身不会改变。重置它会将 -8388608 的偏移量添加到负值,因此将 -1.0 的偏移量添加到负结果(与绘图匹配)。只需删除该行就可以解决问题。这里还有一种符号扩展的替代方法(还有其他方法):
// note: nothing before this,the sign extension is applied *after* rebuilding
val = (u_int32_t)int24[2];
val = (val << 8) | ((u_int32_t)int24[1]);
val = (val << 8) | ((u_int32_t)int24[0]);
val = (val ^ (1 << 23)) - (1 << 23);