转换签名int(2字节,16位)为双格式。与Java

时间:2021-04-18 19:40:31

I've got a problem. In Java I need to read samples from a wav file. The file format is: wav, PCM_SIGNED, signed int of 2bytes = 16bits, little endian... The object reads the audio samples in BYTES and I need to convert this two bytes in one double value. I tried to use this formula but it's not completely correct:

我有一个问题。在Java中,我需要从wav文件中读取示例。文件格式为:wav, PCM_SIGNED,签名int(2字节= 16位),小endian…对象以字节读取音频样本,我需要将这两个字节转换为一个双值。我试着用这个公式,但它并不完全正确:

mono = (double)((audioBytes[k] & 0xFF) | (audioBytes[k + 1] << 8));

Comparing the results with Matlab I always notice differences between the real value in Matlab and the converted one in Java. Can anybody help me please? Thank you, Dave

将结果与Matlab进行比较,我总是注意到Matlab中的实际值与Java中的转换值之间的差异。谁能帮帮我吗?谢谢你,戴夫

3 个解决方案

#1


2  

You haven't given us enough information to know why you're getting different results in Matlab and Java. Usually you scale the short channel data [-32768..32767] to a double in the range [-1..1] which it looks like you are attempting to do. Your java result: -3.0517578125E-5 is correct for the short value -1: -1/32768. I don't know why your Matlab result is different. You haven't shown us how you are arriving at your Matlab results.

您没有给我们足够的信息来了解为什么在Matlab和Java中会得到不同的结果。通常你会扩展短通道数据[-32768..]在范围内加倍[-1.. .]看起来你正试图这么做。您的java结果:-3.0517578125E-5是正确的短值-1:-1/32768。我不知道为什么你们的Matlab结果不同。您还没有向我们展示如何得到Matlab结果。

If you have a large sequence of bytes (which I'm guessing you do), and you don't want to worry about BIG-ENDIAN vs LITTLE-ENDIAN or shifting bits and bytes, let java take care of it for you:

如果你有一个大的字节序列(我猜你有),并且你不想担心BIG-ENDIAN vs LITTLE-ENDIAN或者移动比特和字节,让java来替你处理:

import java.nio.*;
...
ByteBuffer buf = ByteBuffer.wrap(audioBytes);
buf.order(ByteOrder.LITTLE_ENDIAN);

while (buf.remaining() >= 2) {
    short s = buf.getShort();
    double mono = (double) s;
    double mono_norm = mono / 32768.0;
    ...
}

ByteBuffer.getShort() reads the next two bytes of the buffer, takes care of the Little-Endian ordering, converts the bytes to a short, and positions itself for the next getXXX() call.

ByteBuffer.getShort()读取缓冲区的下两个字节,处理Little-Endian排序,将字节转换为短字节,并为下一个getXXX()调用定位自身。

#2


0  

This is the correct way:

这是正确的方法:

double sampleValue = (double)(( bytes[0]<<8 ) | ( bytes[1]&0x00FF ));

(Change indices to swap little/big)

(改变指数以交换小/大)

#3


-1  

Cant you just do most_significant byte * 256 + least_significant_byte and then cast to double?

难道你就不能只执行大部分有意义的字节* 256 +最小有意义的字节然后转换为双字节吗?

#1


2  

You haven't given us enough information to know why you're getting different results in Matlab and Java. Usually you scale the short channel data [-32768..32767] to a double in the range [-1..1] which it looks like you are attempting to do. Your java result: -3.0517578125E-5 is correct for the short value -1: -1/32768. I don't know why your Matlab result is different. You haven't shown us how you are arriving at your Matlab results.

您没有给我们足够的信息来了解为什么在Matlab和Java中会得到不同的结果。通常你会扩展短通道数据[-32768..]在范围内加倍[-1.. .]看起来你正试图这么做。您的java结果:-3.0517578125E-5是正确的短值-1:-1/32768。我不知道为什么你们的Matlab结果不同。您还没有向我们展示如何得到Matlab结果。

If you have a large sequence of bytes (which I'm guessing you do), and you don't want to worry about BIG-ENDIAN vs LITTLE-ENDIAN or shifting bits and bytes, let java take care of it for you:

如果你有一个大的字节序列(我猜你有),并且你不想担心BIG-ENDIAN vs LITTLE-ENDIAN或者移动比特和字节,让java来替你处理:

import java.nio.*;
...
ByteBuffer buf = ByteBuffer.wrap(audioBytes);
buf.order(ByteOrder.LITTLE_ENDIAN);

while (buf.remaining() >= 2) {
    short s = buf.getShort();
    double mono = (double) s;
    double mono_norm = mono / 32768.0;
    ...
}

ByteBuffer.getShort() reads the next two bytes of the buffer, takes care of the Little-Endian ordering, converts the bytes to a short, and positions itself for the next getXXX() call.

ByteBuffer.getShort()读取缓冲区的下两个字节,处理Little-Endian排序,将字节转换为短字节,并为下一个getXXX()调用定位自身。

#2


0  

This is the correct way:

这是正确的方法:

double sampleValue = (double)(( bytes[0]<<8 ) | ( bytes[1]&0x00FF ));

(Change indices to swap little/big)

(改变指数以交换小/大)

#3


-1  

Cant you just do most_significant byte * 256 + least_significant_byte and then cast to double?

难道你就不能只执行大部分有意义的字节* 256 +最小有意义的字节然后转换为双字节吗?