将有符号整型(2 字节,16 位)转换为双精度格式。使用Java

发布于 2024-10-10 20:08:00 字数 349 浏览 12 评论 0原文

我有一个问题。 在 Java 中,我需要从 wav 文件中读取样本。 文件格式为:wav、PCM_SIGNED、signed int of 2bytes = 16bits、little endian... 该对象读取字节中的音频样本,我需要将这两个字节转换为一个双精度值。 我尝试使用这个公式,但它并不完全正确:

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

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

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:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

心在旅行 2024-10-17 20:08:00

您没有向我们提供足够的信息来了解为什么在 Matlab 和 Java 中得到不同的结果。通常,您会将短通道数据 [-32768..32767] 缩放到 [-1..1] 范围内的双倍,这看起来像是您正在尝试执行的操作。您的 java 结果:-3.0517578125E-5 对于短值 -1:-1/32768 是正确的。我不知道为什么你的Matlab结果不同。您还没有向我们展示您是如何得出 Matlab 结果的。

如果你有一个大的字节序列(我猜你有),并且你不想担心 BIG-ENDIAN 与 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;
    ...
}

< a href="http://download.oracle.com/javase/6/docs/api/java/nio/ByteBuffer.html#getShort%28%29" rel="nofollow">ByteBuffer.getShort() 读取缓冲区的接下来两个字节,处理 Little-Endian 排序,将字节转换为短字节,并为下一个 getXXX() 调用定位自身。

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.

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:

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.

等你爱我 2024-10-17 20:08:00

这是正确的方法:(

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

更改索引以交换小/大)

This is the correct way:

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

(Change indices to swap little/big)

对你再特殊 2024-10-17 20:08:00

难道你不能只做most_significant byte * 256+least_significant_byte然后转换为double吗?

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文