Convert Float32Array to Uint8Array while preserving IEEE 754 representation

I have a float32Array method from decodeAudioData that I want to convert to Uint8Array and store the audio data float32 IEEE 754 .

So far I've tried

var length = float32Array.length;

var emptyBuffer = new ArrayBuffer(length * 4);
var view = new DataView(emptyBuffer);

for (var i = 0; i < length; i++) {
  view.setFloat32(i * 4, float32Array[i], true);

var outputArray = new Uint8Array(length);

for (var j = 0; j < length; j++) {
  outputArray[j] = view.getUint8(j * 4);

return outputArray;



I just need to keep the binary representation the same as in this answer.


source to share

2 answers

var output = new Uint8Array(float32Array.length);

for (var i = 0; i < float32Array.length; i++) {
  var tmp = Math.max(-1, Math.min(1, float32Array[i]));
  tmp = tmp < 0 ? (tmp * 0x8000) : (tmp * 0x7FFF);
  tmp = tmp / 256;
  output[i] = tmp + 128;

return output;


Anyone who has doubts about it can easily check it with Audacity Import Raw Data.

  • Download the raw data sample that I decoded from the video file using the Web Audio Api decodeAudioData method.
  • Convert a Float32Array in which raw data samples are filled with a Uint8Array using the method above (or use your own method, for example new Uint8Array(float32Array.buffer)

    , to hear corrupted audio) and load the uint8 pcm file.

    forceDownload(new Blob([output], { type: 'application/octet-binary' }));

  • Encode the loaded data in Audacity with File-> Import -> Raw Data ... Encoding should be set to Unsigned 8-bit PCM and the sampling rate should be 16000 Hz since the original decoded audio file was at 16000 Hz.



It is not very clear what you are asking; or rather, what you seem to be asking for is a thing that doesn't make any sense.

A Float32Array

instance is a buffer representation of "raw" byte values, like all typed arrays. Each element in the array represents 4 of these raw bytes. Retrieving a value using a simple array lookup:

var n = float32array[1];


implicitly interprets these 4 bytes as a 32-bit IEEE floating point value, and then this value is converted to a standard JavaScript number. JavaScript numbers are always 64-bit IEEE floating point values.

Likewise, a Uint8Array

is a buffer representation and each element gives an unsigned integer of one byte. I.e

var n = uint8array[1];


accesses this element, interprets it as an unsigned single-byte integer, and converts it to a JavaScript number.

So: if you want to view a list of 32-bit floating point values ​​as the raw integer value of each byte, you can create Uint8Array

one that "shares" the same buffer as Float32Array


var uintShared = new Uint8Array(float32array.buffer);


The numbers you see when you view the values Uint8Array

will have nothing to do with the amount you get from viewing the items Float32Array

, as you would expect.

On the other hand, if you want to create a new one Uint8Array

to store the visible values ​​from Float32Array

, you can simply create a new array with the same length and copy each value:

var uintCopy = new Uint8Array(float32array.length);
for (let i = 0; i < float32array.length; ++i)
  uintCopy[i] = float32array[i]; // deeply problematic; see below


Now this won't work too well, in general, because the numeric range of values ​​in is Float32Array

significantly larger than the number of values ​​in Uint8Array

. On the one hand, 32-bit floating point values ​​can be negative. What's more, even if you know that floating point values ​​are integers between 0 and 255, you definitely won't get the same bit patterns in Uint8Array

for the simple reason that a 32-bit floating point number is simply not the same. that's an 8-bit unsigned integer. "Save IEEE-754 representation" doesn't make sense.

So, the reality of the situation. If you could explain why you think you want to somehow insert all 32 bits of an IEEE 32-bit float into an 8-bit unsigned integer, a more convenient answer could be provided.



All Articles