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

Re: AudioBuffer mutability

From: Joseph Berkovitz <joe@noteflight.com>
Date: Mon, 29 Oct 2012 09:32:11 -0400
Cc: public-audio@w3.org
Message-Id: <66E0C21D-270A-4F85-9603-BBEA44461BC4@noteflight.com>
To: robert@ocallahan.org
Robert,

I have encountered the same question as an API user (not implementor). The spec is definitely not clear on this point.

I think it's reasonable to say that AudioBuffers should be either 1) effectively immutable (equivalent to your "if they don't" choice) or 2) free of any guarantees for what happens if you mutate their data.  In either case, the client code must construct a new AudioBuffer with modified data read from the old one, if predictable output is to occur.

But it's clearly unacceptable to deny read-only access to the raw data altogether, as this would leave developers with no ability to access samples decoded from media. It's also unacceptable to leave the API with no way to fill an AudioBuffer from unencoded raw sample data. There are many situations in which an AudioBuffer is loaded from media, but where the samples need to be programmatically accessed and/or modified, sometimes dynamically. This is not hypothetical; many synthesizer-type applications (including mine) require it.

So I'm suggesting two other approaches here, both of which seem implementor- and client-friendly. #2 is a form of the "no direct array access" that you favor:

1. Specify that there are no guarantees in terms of audio output when live modifications to AudioBuffer channel data occur.

2. Deprecate getChannelData(), add a new API call that is specced to provide only a copy of the buffer data, and add a new createBufferFromChannelData() method to AudioContext that creates a new, immutable AudioBuffer from a set of ArrayBuffers with raw channel data

In both cases, API users must copy AudioBuffers if they want predictable results. Note that today, this can only be done by creating a raw zeroed-out AudioBuffer and using TypedArray setters on getChannelData() to move data into that buffer.

For the time being (v1 of the API) I would propose that we go with #1 -- no guarantees if you modify a live AudioBuffer -- and file a spec bug. I think #1 is actually perfectly reasonable, but if a more shuttered approach to channel data is deemed desirable, #2 seems fine to me also.

…Joe

On Oct 29, 2012, at 6:31 AM, Robert O'Callahan <robert@ocallahan.org> wrote:

> If someone attaches an AudioBuffer to an AudioBufferSourceNode, then calls start(T) on the node, and then modifies the contents of the AudioBuffer (by calling getChannelData() and then modifying the returned array), do the changes affect what will be played by the AudioBufferSourceNode?
> 
> If they don't, we have to make a copy of the buffer in the start() call, in case the buffer is mutated later.
> 
> If they do, then we are exposed to race conditions where depending on exactly where the playback position is when script modifies the array, how much audio is buffered and how everything is implemented, changes to the buffer may or may not be played. Even worse, on machines with non-sequentially-consistent memory (or very aggressive optimizing JS compilers), some subsets of the modifications may be played while others are mysteriously ignored.
> 
> Both options are undesirable. If AudioBuffer didn't provide direct array access to its samples, we'd have better options. Is it too late to change that?
> 
> 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]
> 

... .  .    .       Joe

Joe Berkovitz
President

Noteflight LLC
Boston, Mass.
phone: +1 978 314 6271
www.noteflight.com
Received on Monday, 29 October 2012 13:32:42 UTC

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