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?
Asked
Active
Viewed 1.1k times
7
-
`float32Array` isn't "32bit pcm" - you'd want `int32Array`, wouldn't you? – Jaromanda X Jan 08 '16 at 04:32
-
maybe the term `32bit PCM` is 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... – Wilson Luniz Jan 08 '16 at 04:36
-
1ok, so, yes, you want Float32Array – Jaromanda X Jan 08 '16 at 04:37
-
oh yea, so let's talk about the conversion~ – Wilson Luniz Jan 08 '16 at 04:39
-
So the output is a 32bit float, what is the range of values for the output? +/- 1.0? – Jaromanda X Jan 08 '16 at 04:49
-
can you provide a link to the MDN page with the specifications you are referring to – Jaromanda X Jan 08 '16 at 04:50
-
https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer – Wilson Luniz Jan 08 '16 at 04:51
-
how many channels is the input? is the input audio data interleaved? – Jaromanda X Jan 08 '16 at 04:54
2 Answers
15
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)

robjtede
- 736
- 5
- 16
-
`Float32Array.from(uint8_array, octet => octet / 0xFF)` is why I love Javascript. – Константин Ван Nov 12 '22 at 19:34
13
This function converts an ArrayBuffer to Float32Array
var 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
var 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;
}

Jaromanda X
- 53,868
- 5
- 73
- 87
-
This works great! Thank you! I'm curious, `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? – Wilson Luniz Jan 08 '16 at 07:33
-
I have no idea to be honest - but float32 with a range of +/- 1 is not an uncommon audio range – Jaromanda X Jan 08 '16 at 07:36
-
I tried to change `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. – Wilson Luniz Jan 08 '16 at 08:07
-
-
-
Within the WebAudio graph, you can use full float range to do whatever you want. But if you eventually want to hear it you have to map it back to the +/- 1 range in some way. In Chrome, if you don't, all of your values will get clamped to +/-1 for you so the signal you hear will be distorted. – Raymond Toy Jan 08 '16 at 16:28
-
1The point of using floating point is that the "range" of -1/+1 is a NOMINAL range - that is, when you output it to the speakers, it should be [-1,+1] or it will clip, but audio signals elsewhere in the pipeline may go well outside that range. – cwilso Jan 08 '16 at 17:14
-
-