Преобразовать подписанный int (2bytes, 16 бит) в двойном формате. С Java
Вопрос
У меня есть проблема. В Java мне нужно прочитать образцы из файла WAV. Формат файла: WAV, PCM_Signed, подписанный int в размере 2bytes = 16bits, маленький Endian ... Объект читает образцы аудио в байтах, и мне нужно преобразовать эти два байта в одном двойном значении. Я пытался использовать эту формулу, но это не совсем правильно:
mono = (double)((audioBytes[k] & 0xFF) | (audioBytes[k + 1] << 8));
Сравнивая результаты с MATLAB, я всегда замечаю различия между реальным значением в MatLab и преобразованном в Java. Кто-нибудь может помочь мне, пожалуйста? Спасибо, Дэйв
Решение
Вы не дали нам достаточно информации, чтобы узнать, почему вы получаете разные результаты в Matlab и Java. Обычно вы масштабируете короткие данные канала [-32768..32767] к двойным в диапазоне [-1..1], который похоже, вы пытаетесь сделать. Ваш результат Java: -3.0517578125E-5 правильно для короткого значения -1: -1/32768. Я не знаю, почему ваш результат Matlab отличается. Вы не показали нам, как вы приходите к результатам MatLab.
Если у вас есть большая последовательность байтов (которые я догадаюсь, что вы делаете), и вы не хотите беспокоиться о 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 () Читает следующие два байта буфера, заботится о том, чтобы поставить за заказ маленькой эндена, преобразует байты на короткие и позиции для следующего вызова GetXXX ().
Другие советы
Это правильный путь:
double sampleValue = (double)(( bytes[0]<<8 ) | ( bytes[1]&0x00FF ));
(Измените индексы, чтобы поменяться мало / большой)
Вы не можете просто сделать Most_signefant Byte * 256 + MILL_Significant_byte, а затем отбрасывают в двойное?