- From: Robert O'Callahan <robert@ocallahan.org>
- Date: Tue, 30 Oct 2012 10:41:04 +1300
- To: Chris Rogers <crogers@google.com>
- Cc: public-audio@w3.org
- Message-ID: <CAOp6jLaLtH038U-nK+5vZc7nY_TpXTEbS306TooKG06GsSTBgA@mail.gmail.com>
On Tue, Oct 30, 2012 at 7:20 AM, Chris Rogers <crogers@google.com> wrote: > Hi Robert, the answer is that for efficiency the AudioBufferSourceNode is > expected to *directly* read the data stored in the AudioBuffer. As a > consequence of this, then any changes to the AudioBuffer after start() is > called can affect the result. As you point out this is an inherently racy > affair, but for all practical purposes is a non-issue because, in general, > it's not useful to modify the data dynamically in this way. In over two > years of developer use of this API, using it for a great variety of uses > cases, this issue has not been a problem because people know to not modify > the buffer. Elsewhere in the Web platform we have worked hard to ensure that races on shared memory cannot be exposed like this. Not even Web Workers has any features that allow it. Not only does this avoid exposing Web authors to various kinds of subtle bugs, but it also means that the Web platform can be implemented efficiently on hardware and software platforms that don't support parallelism with mutable shared memory. (There are experimental browsers around that are actually trying to do this.) I don't think we should abandon that position lightly. I'm not confident that the history of Web Audio so far guarantees that people won't run into problems in the future (either accidentally or deliberately). For example, a clever developer might realize that by modifying the contents of a playing AudioBuffer they can affect what gets played with minimum latency. I believe PulseAudio actually offers that as a feature, and some RTC implementations do tricks like that to try to handle late-arriving audio packets. So, what I think the specification should say is that the behavior is > undefined if the buffer is modified after start(). It's very important to > *not* require any buffer copies in AudioBufferSourceNode for efficiency. > Developers are free to make their own copies of the buffers, modify them, > and use them in other calls to start(). > Undefined behavior should always be avoided if at all possible. As far as I can tell we haven't even tried to avoid it. We shouldn't be lazy about this. I think in this case this problem is actually easy to solve without even changing the API. The typed array spec defines a "neuter" operation on ArrayBuffers that makes the underlying data inaccessible through the ArrayBuffer and any objects (such as Float32Array) that depend on the ArrayBuffer: http://www.khronos.org/registry/typedarray/specs/latest/#9.2 This is used by Web Workers to enable safe zero-copy transfer of ownership of the data from one thread to another. We could say that, for a given AudioBuffer B, the first time start() is called on an AudioBufferSourceNode whose 'buffer' is B, B's channel ArrayBuffers are neutered. Any future attempts to modify the data will then fail, probably with an "array index out of bounds" error. How does that sound? 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 Monday, 29 October 2012 21:41:33 UTC