Правильный способ преобразования 16-битных данных PCM PCM для плавания
-
08-10-2019 - |
Вопрос
У меня есть волновой файл в 16-битной форме PCM. У меня есть необработанные данные в byte[]
и способ извлечения образцов, и мне нужен их в формате поплавка, то есть float[]
сделать преобразование Фурье. Вот мой код, это выглядит правильно? Я работаю над Android так javax.sound.sampled
и т. Д. Не доступен.
private static short getSample(byte[] buffer, int position) {
return (short) (((buffer[position + 1] & 0xff) << 8) | (buffer[position] & 0xff));
}
...
float[] samples = new float[samplesLength];
for (int i = 0;i<input.length/2;i+=2){
samples[i/2] = (float)getSample(input,i) / (float)Short.MAX_VALUE;
}
Решение
У меня было подобное решение, но ИМХО немного чище. К сожалению, нет хорошего метода библиотеки, насколько я знаю: * Это предполагает, что даже байты - это нижние байты
private static float[] bytesToFloats(byte[] bytes) {
float[] floats = new float[bytes.length / 2];
for(int i=0; i < bytes.length; i+=2) {
floats[i/2] = bytes[i] | (bytes[i+1] << 8);
}
return floats;
}
Другие советы
Вы можете попробовать использовать API BYTEBUFFER.http://developer.android.com/reference/java/nio/bytebuffer.html#asfloatbuffer.()
Как указано hertzsprung Ответ JK. работает только для PCM беззнаков. На Android PCM16 подписан Big-Endian, поэтому вам нужно учитывать потенциально отрицательное значение, закодированное в Два дополнения. Отказ Это означает, что нам нужно проверить, превышает ли высокий байт более 127, и если начнет примите 256 от него сначала, прежде чем умножить его на 256.
private static float[] bytesToFloats(byte[] bytes) {
float[] floats = new float[bytes.length / 2];
for(int i=0; i < bytes.length; i+=2) {
floats[i/2] = bytes[i] | (bytes[i+1] < 128 ? (bytes[i+1] << 8) : ((bytes[i+1] - 256) << 8));
}
return floats;
}