I have some audio buffer in usigned 8bit PCM format need to play via web audio which only accept signed 32bit PCM. And now I have ArrayBuffer for pieces of pcm_u8 data(come from Uint8array). How can I convert it to Float32Array?
3 Answers
ECMAScript 2015 and onwards has TypedArray.from which converts any typed array (and indeed, any iterable) to the specified typed array format.
So converting a Uint8Array to a Float32Array is now as easy as:
const intArray = new Uint8Array()
const floatArray = Float32Array.from(intArray)
3 Comments
Float32Array.from(uint8_array, octet => octet / 0xFF) is why I love Javascript.TypedArray.from was not universally available until 8 months after my answer (Safari was slow to adopt) :pThis function converts an ArrayBuffer to Float32Array
function convertBlock(buffer) { // incoming data is an ArrayBuffer
var incomingData = new Uint8Array(buffer); // create a uint8 view on the ArrayBuffer
var i, l = incomingData.length; // length, we need this for the loop
var outputData = new Float32Array(incomingData.length); // create the Float32Array for output
for (i = 0; i < l; i++) {
outputData[i] = (incomingData[i] - 128) / 128.0; // convert audio to float
}
return outputData; // return the Float32Array
}
This one converts a Uint8Array to Float32Array
function convertBlock(incomingData) { // incoming data is a UInt8Array
var i, l = incomingData.length;
var outputData = new Float32Array(incomingData.length);
for (i = 0; i < l; i++) {
outputData[i] = (incomingData[i] - 128) / 128.0;
}
return outputData;
}
Note: A few months after writing this answer, Safari finally caught up and made the TypedArray.from method available (as noted in another answer)
So, the code would be simply (for an ArrayBuffer input)
const convertBlock = input => Float32Array.from(new Uint8Array(input), v => (v - 128) / 128);
For Uint8Array input, you could still use the above, or simpler:
const convertBlock = input => Float32Array.from(input, v => (v - 128) / 128);
9 Comments
float32 has a range approx -3.4E+38 to +3.4E+38 but WebAudioAPI only use -1 to +1. Is it limited the precision(only part of 32bit)? Or something I misunderstood?outputData[i] = (incomingData[i] - 128) / 128.0 * 0xFFFFFFFF; or even 0xFFFF and it gives me the exactly same audio(and I can see the value really growing bcoz i wrote my only sine wave generator for testing). I'm really confuse about this.grab Uint8Array's underlying ArrayBuffer and pass it to the Float32Array constructor:
const f_sz = 42; // length of elements in f
const a = new Uint8Array();
const b = a.buffer; // ArrayBuffer
const f = new Float32Array(b, 0, f_sz);
may also work:
const b = a.buffer; // ArrayBuffer
const f = new Float32Array(b);
float32Arrayisn't "32bit pcm" - you'd wantint32Array, wouldn't you?32bit PCMis wrong. The fact is I have some usigned 8bit PCM audio buffer need to play via WebAudioAPI. What's the right way? And MDN said it's 32bit float non-interleaved PCM, however...