Преобразование массива int16 в число с плавающей запятой

У меня есть массив байтов из аудиофайла, и я хочу преобразовать его в данные, которые я могу обработать для фильтрации аудиосигнала. У меня есть такой массив: [239,246,96,247.....]; Каждый элемент представляет собой uint8 байт

Каждые 2 байта (16 бит) представляют собой выборку, поэтому я преобразовал этот массив в массив элементов int16.

Как я могу затем преобразовать этот массив в сигнал со значениями в диапазоне [-1,1]?


person user7597554    schedule 12.09.2017    source источник


Ответы (2)


У вас уже есть подписанные int16, поэтому вам просто нужно разделить на минимальное и максимальное значение int16, соответствующее знаку.

let buffer = new Int16Array([0x0001, 0x7fff, 0x000, 0xffff, 0x8000]);
// [1, 32767, 0, -1, -32768]
let result = new Float32Array(buffer.length);
for(let i=0; i<buffer.length; i++) result[i] = buffer[i] / (buffer[i] >= 0 ? 32767 : 32768);
console.log(result[0], result[1], result[2], result[3], result[4]);
// 0.000030518509447574615 1 0 -0.000030517578125 -1
person Louis Ricci    schedule 12.09.2017
comment
И можно ли сделать обратную функцию? Из массива значений с плавающей запятой получить массив uint8? - person user7597554; 13.09.2017
comment
@user7597554 user7597554 - вы бы перешли от Float32 к Int16, умножив на значение int16 min / ax, затем вы бы перешли от int16 к uint8 путем сдвига битов и маскирования. u8buffer[0] = буфер[0] & 0xff; u8buffer[1] = (buffer[0] ›› 8) & 0xff; - person Louis Ricci; 15.09.2017

x является элементом моего массива. x должен быть uint16, а не int16.

Далее foreach x вы должны сделать (x - maxUInt16/2) / maxUInt16/2

So => y = (x - (2^15 - 1)) / (2^15 - 1)

maxUint16 поврежден, поэтому вам нужно справиться с возможным переполнением

Код :

let init = new Uint8Array(22);

for (let i = 0; i < 16; i++) {
    init[i] = Math.trunc(Math.random() * 255) % 255;
}
/* Interested test case */
init[16] = 0;
init[17] = 0;    // Should return -1
init[18] = 255;
init[19] = 255;  // Should return 1
init[20] = 127;
init[21] = 255;  // Should return 0

let sample = new Uint16Array(11);

for (let i = 0; i < 11; i++) {
    sample[i] = (init[i*2] << 8) | init[i*2+1];
}

let ranged = [];

for (let i = 0; i < 11; i++) {
     ranged.push(Math.min(( Number(sample[i]) -  32767) / 32767 , 1));
}

console.log(init);
console.log(sample);
console.log(ranged);
person Fefux    schedule 12.09.2017