Home > Mobile >  Convert javascript array to Float32Array to buffer and Back
Convert javascript array to Float32Array to buffer and Back

Time:02-02

I have a JS array with floats like so [0.0028808217, -0.027968751, -0.029748825] and I transform it to a Float32 Buffer with the following function:

function toFloat32Buffer(array) {
  return Buffer.from(new Float32Array(array).buffer)
}

The issue I'm facing is making the conversion from the Float32 Buffer back to a JS array, so I can use the same values as the original array.

I've tried

function toJSArray(buffer) {
 const newBuffer = Buffer.from(buffer) 
 const floatArray = new Float32Array(newBuffer)

 return Array.from(floatArray)
}

function toFloat32Buffer(arr) {
   return Buffer.from(new Float32Array(arr).buffer)
}

const array = [0.0028808217, -0.027968751, -0.029748825]
const bufferFromFloat32 = toFloat32Buffer(array);
const array2 = toJSArray(bufferFromFloat32);

console.log('array', array)
console.log('array2', array2)

array and array2 have different values. How should I transform back the buffer to get the same values as the original array? I'm running this in NodeJS

CodePudding user response:

Rewrite your toJsArray function to:

function toJSArray(buffer) {
     return new Float32Array(buffer.buffer);
}

The buffer property of buffer returns the underlying ArrayBuffer of the buffer. But as @Matt mentioned in his comment:

Javascript numbers are double-precision 64-bit. I don't think you can get back the precision that is removed converting to 32bit, short of storing it somewhere else. – Matt

For more details: buff.buffer

CodePudding user response:

Here is the fixed code to convert a JavaScript array to a Float32Array, then to a buffer, and back:

function toFloat32Array(buffer) {
  return new Float32Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / Float32Array.BYTES_PER_ELEMENT)
}

function toFloat32Buffer(array) {
  return Buffer.from(new Float32Array(array).buffer)
}

function fromFloat32Buffer(buffer) {
  return toFloat32Array(buffer)
}

And here's an example of how you can use these functions:

const array = [1, 2, 3, 4, 5];

const float32Buffer = toFloat32Buffer(array);
console.log(float32Buffer); // <Buffer 00 00 80 3f 00 00 00 40 00 00 40 40 00 00 40 C0>

const float32Array = fromFloat32Buffer(float32Buffer);
console.log(float32Array); // Float32Array [ 1, 2, 3, 4, 5 ]

const originalArray = Array.from(float32Array);
console.log(originalArray); // [ 1, 2, 3, 4, 5 ]

CodePudding user response:

This is alternative solution. Considering using "unsafe" alloc, could be safer in terms of knowing what exactly are you doing. You can also use the var size as a parameter to be more precise, depending on the data you manage

 function bufferToArray(buffer, size) {
    let arr = [];
    for (let i = 0; i < buffer.length / size; i  )
      arr.push(buffer.readDoubleLE(i * size));
    return arr;
  }

  function arrayToBuffer(arr, size) {
    const buffer = Buffer.allocUnsafe(size * arr.length);
    arr.map((val, index) => buffer.writeDoubleLE(val, size * index));
    return buffer;
  }

  let array = [0.0028808217, -0.027968751, -0.029748825];
  const size = Float64Array.BYTES_PER_ELEMENT; // double-precision

  const buffer = arrayToBuffer(array, size);
  const array2 = bufferToArray(buffer, size);

  console.log(array); // [0.0028808217, -0.027968751, -0.029748825]
  console.log(array2); // [0.0028808217, -0.027968751, -0.029748825]
  • Related