Question

So I've pulled the channel data out of an AudioBuffer and sent it via transferable object to a web worker to do some processing on it, and now I want to put it back in. Do I really have to copy it back in like this?

var myData = new Float32Array(audioBuf.length);
var chanData = audioBuf.getChannelData(0);

for ( var n = 0; n < chanData.length; n++ ) {
    chanData[n] = myData[n];
}

I'm really hoping there is some way to just change out the ArrayBuffer each of the AudioBuffer channels reference. Something like...

audioBuf.channel[0].buffer = myData.buffer;

...would be wonderfully simple and effective, but seemingly does not exist. Is there any way at all like this to change the reference and avoid copying the data?

EDIT: With a little further investigation, I see the problem of using the web audio API with transferable objects is even more annoying. When you transfer the array buffers to the worker, the underlying array buffers of the AudioBuffer are cleared, I believe making even a copy operation through the Float32Array returned by getChannelData impossible. The only way I can see to accomplish what I want right now is to abandon the original AudioBuffer, create an entirely new AudioBuffer and then copy my data into it. Really??

No correct solution

OTHER TIPS

We recently added two new methods on AudioBuffer, from which use copyFromChannel could be useful to you. It does what it says on the tin (put an ArrayBuffer in a channel of an AudioBuffer), maybe saving a copy in the process (the reasons and condition to avoid the copy are explained here).

I believe it's only implemented in Firefox for the moment, but I haven't checked.

I struggled with this all day, so I figured I should share my solution.

var PCM = [0,1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1];


var room = new window.AudioContext();
var sampleRate = 44100;
var channels = 1;

var audioBuffer = room.createBuffer(channels, 0, sampleRate);

var channelObject = audioBuffer.getChannelData(0);

var audioBufferDataArray = channelObject.data;


// actual code to set the data

audioBuffer.length = PCM.length; // optional

for(var i=0; i<PCM.length; i++){
    audioBufferDataArray[i] = PCM[i];
}

You were so close! The method you want is AudioBuffer.copyToChannel() .

This will copy your Float32Array to an audio buffer node like so :

var myData = new Float32Array(audioBuf.length);

//copy mydata to first channel

audioBuf.copyToChannel( myData , 0 , 0 );

Deep in the docs:

https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer/copyToChannel

Hope this helps

A few things:

1) There's a pretty low-cost method for copying data from one typed array to another that doesn't require you to go through the headache of looping.

var copy = new Float32Array(orig.length);
copy.set(orig);

2) The issue of your AudioBuffer getting cleared is just part of the spec for transferable objects with web workers (https://developer.mozilla.org/en-US/docs/Web/Guide/Performance/Using_web_workers#Passing_data_by_transferring_ownership_(transferable_objects)). That's the only way they can guarantee thread safety. If two threads had access to the same object at the same time, they could both mutate it, and you'd end up with all kinds of craziness.

I'm not totally sure why you're so annoyed at the prospect of creating a new AudioBuffer and copying data into it. You can do that in 2 lines for a mono buffer. 3 lines for stereo. You've already done way more work than that by setting up all the boilerplate necessary to get a web worker up and running.

Anyway, if you could give some more specifics about your application and what it's doing, I'd be happy to make some recommendations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top