W3C home > Mailing lists > Public > public-audio@w3.org > October to December 2012

Re: AudioBuffer mutability

From: Robert O'Callahan <robert@ocallahan.org>
Date: Wed, 31 Oct 2012 09:39:08 +1300
Message-ID: <CAOp6jLZo8gXp0Ms7sBo0TSWoEWbkczaBxHNncMiZigUYCrk+8w@mail.gmail.com>
To: Srikumar Karaikudi Subramanian <srikumarks@gmail.com>
Cc: Chris Rogers <crogers@google.com>, Joseph Berkovitz <joe@noteflight.com>, Ehsan Akhgari <ehsan.akhgari@gmail.com>, public-audio@w3.org
On Wed, Oct 31, 2012 at 5:11 AM, Srikumar Karaikudi Subramanian <
srikumarks@gmail.com> wrote:

> Although that's true, the getChannelData() API suggests a symmetry of
> buffer access between the JS side and the audio system. If the buffer were
> to be read+write locked upon binding to a source node, we'd end up with a
> reference to a typed array on the JS side that can neither be written to
> nor read from ... which is a very unusual state to leave a common JS object
> in.
>

I wouldn't say that, since typed arrays being transferred to Web Workers
--- the closest analogue the Web platform currently has to the situation
we're talking about --- work exactly like this.

To isolate the two sides, the AudioBuffer API has to change to something
> like this -
>
> var f32 = new Float32Array([...]);
> var buf = context.createBuffer(numChannels, numFrames, sampleRate);
> buf.writeChannelData(chan, f32, offset);
> buf.readChannelData(chan, f32, offset);
>
> If a buffer is "in use", then the write can be specd to complete after a
> render quantum and the read can be specd to block during the current render
> quantum (or perhaps take a callback argument for async read). The "f32"
> then remains exclusive to JS land.
>

Something like that would work.

I've got another suggestion though, which I think is simpler and more
compatible with existing usage:
-- Neuter ArrayBuffers on first start() using the buffer, as I proposed
before
-- If getChannelData() is called on the AudioBuffer after its ArrayBuffers
have been neutered, make a copy of the underlying data and return it in a
fresh ArrayBuffer.

This provides applications with read and write access to the AudioBuffer's
data at all times, providing that after any start() call, getChannelData()
is called again to acquire a new ArrayBuffer.

This should be implementable efficiently in any system that permits
*read-only* shared memory between threads, which is reasonable I think. It
does sometimes require data copying, but it only needs to copy when you
actually access data after a start(). An implementation could potentially
do something fancy with copy-on-write to avoid copying when the result of
getChannelData() is not modified. And note that if getChannelData() is
called after all nodes have stopped playing the AudioBuffer, then the
user-agent can transfer ownership of the data back to the main thread to
avoid copying.

Rob
-- 
Jesus called them together and said, “You know that the rulers of the
Gentiles lord it over them, and their high officials exercise authority
over them. Not so with you. Instead, whoever wants to become great among
you must be your servant, and whoever wants to be first must be your
slave — just
as the Son of Man did not come to be served, but to serve, and to give his
life as a ransom for many.” [Matthew 20:25-28]
Received on Tuesday, 30 October 2012 20:39:37 UTC

This archive was generated by hypermail 2.3.1 : Tuesday, 6 January 2015 21:50:03 UTC