Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert signed int (2bytes, 16 bits) in double format. With 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

like image 563
Davide Avatar asked Sep 14 '26 14:09

Davide


1 Answers

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.

like image 129
robert_x44 Avatar answered Sep 17 '26 03:09

robert_x44



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!