8

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?

8
  • float32Array isn't "32bit pcm" - you'd want int32Array, wouldn't you? Commented Jan 8, 2016 at 4: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... Commented Jan 8, 2016 at 4:36
  • 1
    ok, so, yes, you want Float32Array Commented Jan 8, 2016 at 4:37
  • oh yea, so let's talk about the conversion~ Commented Jan 8, 2016 at 4:39
  • So the output is a 32bit float, what is the range of values for the output? +/- 1.0? Commented Jan 8, 2016 at 4:49

3 Answers 3

16

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)
Sign up to request clarification or add additional context in comments.

3 Comments

Float32Array.from(uint8_array, octet => octet / 0xFF) is why I love Javascript.
This comment is underrated @КонстантинВан
FYI: TypedArray.from was not universally available until 8 months after my answer (Safari was slow to adopt) :p
14

This 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

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?
I have no idea to be honest - but float32 with a range of +/- 1 is not an uncommon audio range
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.
you may need to look into the range expected/allowed in the data
The 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.
|
0

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);

ref: Float32Array() constructor

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.