Understanding ArrayBuffer, Float32Array, and Uint8Array for Binary Data Handling
The ArrayBuffer object represents a fixed-length raw binary data buffer. It is a generic container for a sequence of bytes.
const dataBuffer = new ArrayBuffer(16); // Allocates 16 bytes of memory
console.log(dataBuffer.byteLength); // 16
Once created, an ArrayBuffer cannot be resized. However, you can create a new buffer containing a portion of the original data using the slice method.
const originalBuffer = new ArrayBuffer(16);
const slicedBuffer = originalBuffer.slice(4, 12);
console.log(slicedBuffer.byteLength); // 8
Float32Array is a typed array that provides a view into an ArrayBuffer for storing 32-bit floating-point numbers. It has a fixed length.
Fixed Length Demonstration:
let floatArray = new Float32Array(2);
floatArray[0] = 10.5;
floatArray[1] = 20.3;
floatArray[2] = 30.7; // This assignment is ignored; index is out of bounds.
console.log(floatArray); // Float32Array(2) [10.5, 20.3]
Unlike a regular JavaScript Array, a Float32Array cannot dynamically grow.
Numeric Type Enforcement:
The array only accepts numeric values. Non-numeric assignments result in NaN.
let numericArray = new Float32Array(3);
numericArray[0] = 100;
numericArray[1] = "text"; // Converts to NaN
numericArray[2] = true; // Converts to 1 (boolean true becomes 1)
console.log(numericArray); // Float32Array(3) [100, NaN, 1]
Creating a Float32Array:
- By specifying a length (elements initilaize to 0):
let arrByLength = new Float32Array(5); console.log(arrByLength); // Float32Array(5) [0, 0, 0, 0, 0] - From a standard array:
Non-numeric elements in the source array becomelet arrFromStandard = new Float32Array([5.1, 10.2, 15.3]); console.log(arrFromStandard); // Float32Array(3) [5.1, 10.2, 15.3]NaN.let arrWithMixed = new Float32Array([9, null, {}, [1,2]]); console.log(arrWithMixed); // Float32Array(4) [9, 0, NaN, NaN] - From another typed array (creates a copy):
let sourceArray = new Float32Array([1.5, 2.5]); let copiedArray = new Float32Array(sourceArray); console.log(copiedArray); // Float32Array(2) [1.5, 2.5]
Properties:
length: The number of elements in the array.let demoArray = new Float32Array(7); console.log(demoArray.length); // 7BYTES_PER_ELEMENT: Returns the size, in bytes, of each element.console.log(Float32Array.BYTES_PER_ELEMENT); // 4buffer: A read-only reference to the underlyingArrayBuffer.let fArray = new Float32Array(4); console.log(fArray.buffer instanceof ArrayBuffer); // true console.log(fArray.buffer.byteLength); // 16 (4 elements * 4 bytes each)
Uint8Array represents an array of 8-bit unsigned integers. Its behavior is similar to Float32Array but each element is a single byte (0 to 255).
// Create from a length
let uintArr = new Uint8Array(3);
uintArr[0] = 255;
console.log(uintArr[0]); // 255
console.log(uintArr.length); // 3
console.log(Uint8Array.BYTES_PER_ELEMENT); // 1
// Create from an array
let fromList = new Uint8Array([40, 80, 160]);
console.log(fromList[2]); // 160
// Create from another TypedArray
let original = new Uint8Array([10, 20, 30]);
let duplicate = new Uint8Array(original);
console.log(duplicate[1]); // 20
// Create a view on a specific portion of an ArrayBuffer
let mainBuffer = new ArrayBuffer(10);
let partialView = new Uint8Array(mainBuffer, 2, 5); // Offset 2 bytes, length 5 elements
console.log(partialView.length); // 5
// Create from an iterable
function* numberGenerator() { yield* [99, 199, 299]; }
let fromIterable = new Uint8Array(numberGenerator());
console.log(fromIterable); // Uint8Array(3) [99, 199, 43] (299 is clamped to 255)
Data Conversion Between Types:
Covnerting Uint8Array data (byte values 0-255) to normalized Float32Array data (often in the range -1.0 to 1.0 for audio processing).
function normalizeAudioData(inputData) {
// Input can be an ArrayBuffer or a Uint8Array
const byteArray = inputData instanceof Uint8Array ? inputData : new Uint8Array(inputData);
const sampleCount = byteArray.length;
const floatArray = new Float32Array(sampleCount);
for (let i = 0; i < sampleCount; i++) {
// Map unsigned byte (0-255) to signed float (-1.0 to ~0.992)
floatArray[i] = (byteArray[i] - 128) / 128.0;
}
return floatArray;
}
// Example usage with an ArrayBuffer
const testBuffer = new ArrayBuffer(4);
const testView = new Uint8Array(testBuffer);
testView.set([0, 128, 255, 64]);
const normalizedFloats = normalizeAudioData(testBuffer);
console.log(normalizedFloats); // Float32Array(4) [-1, 0, 0.9921875, -0.5]
// Example usage directly with a Uint8Array
const directUintArray = new Uint8Array([32, 192]);
const normalizedDirect = normalizeAudioData(directUintArray);
console.log(normalizedDirect); // Float32Array(2) [-0.75, 0.5]