Considere los bytes de entrada que son un Uint8Array de 400 bytes. El siguiente código lo convierte primero en un ArrayBuffer a través del método .buffer y luego en un Float32Array :
static bytesToFloatArray(bytes) { let buffer = bytes.buffer; // Get the ArrayBuffer from the Uint8Array. let floats = new Float32Array(buffer); return floats }La sorpresa es que la conversión a ArrayBuffer antepone 32 bytes, lo que se refleja en tener 8 valores flotantes "0" adicionales al comienzo del Float32Array subsiguiente:
¿Por qué el método del búfer agrega los 32 bytes y cómo se puede evitar (o corregir)?
¿Por qué el método de búfer agrega los 32 bytes?
no lo hizo El búfer tenía 432 bytes en primer lugar, incluso antes de que se creara Uint8Array en él. La diferencia proviene de la matriz tipeada que usa un desplazamiento y/o una longitud que esencialmente restringe la vista a una porción del búfer.
¿Y cómo se puede evitar (o corregir) eso?
Utilice el mismo desplazamiento y longitud ajustada:
function bytesToFloatArray(bytes) { return new Float32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength/Float32Array.BYTES_PER_ELEMENT); }Publicación: la respuesta de @Bergi es correcta, ni siquiera miré el búfer desde el que se creó Uint8.
No pude reproducir el comportamiento que tenía en la consola de Chrome, pero siempre puede recurrir al uso de DataView para tener un control detallado, algo como esto:
(cuidado con el endianness, y no probé el código a continuación, podría haber cometido un error en las órdenes de bytes)
let test8 = new Uint8Array(400); test8.forEach((d,i,a) => a[i] = 0xff * Math.random() | 0); function c8to32(uint8, endian = false){ //big endian by default var cpBuff = new ArrayBuffer(uint8.length), view = new DataView(cpBuff); for (let i = 0,v = void(0); i < uint8.length; i += 4){ if(!endian) { //big v = uint8[i] << 24 | uint8[i + 1] << 16 | uint8[i + 2] << 8 | uint8[i + 3]; } else { //little v = uint8[i] | uint8[i + 1] << 8 | uint8[i + 2] << 16 | uint8[i + 3] << 24; } view.setFloat32( i, v, endian ); } return cpBuff; } document.getElementById("resultbig").textContent = c8to32(test8).byteLength; document.getElementById("resultlittle").textContent = c8to32(test8, true).byteLength; <div id="resultbig">test</div> <div id="resultlittle">test</div>