asynchronous vs synchronous instantiation of AudioWorkerNodes

Hi group,

There’s an issue noted in the AudioWorker proposal (issue #113) that I want to highlight as a discussion point, so some public exchange can happen prior to the next revised AudioWorker proposal from Chris. (One was already expected in order to deal with dynamic input/output counts.)  The discussion so far has been limited to the github issue thread but it feels worthy of broader attention.

The issue is this: the createAudioWorker factory method on AudioContext takes a script URL. Currently it returns a Node (see http://cwilso.github.io/web-audio-api/#widl-AudioContext-createAudioWorker-AudioWorkerNode-DOMString-scriptURL-unsigned-long-numberOfInputChannels-unsigned-long-numberOfOutputChannels).

That script could take an arbitrary amount of time to load, so the returned Node would not be functional at the time of its instantiation. It also might not be able to expose AudioParams at that time, if such parameters are defined by executing the loaded script (as has been proposed). In response Chris W suggested that this factory method might return a Promise, not the actual Node.

The Promise makes sense given the asynchrony of script loading, but the need to employ a Promise here makes it hard to synchronously construct a graph or subgraph using an AudioWorker node as part of that graph. This is a very big leap away from the way one uses native nodes, working against the notion of architectural layering built on top of the AudioWorker concept. It imposes both script-loading overhead and the use of callbacks on every instantiation of a node using some given script.

This is not necessarily so bad for use cases in which a fairly static graph is built once, for the duration of some audio session. But it’s more serious w/r/t use cases that incorporate many individual AudioWorker instances in small subgraphs built on demand (e.g. game sound effects or musical notes in a synth). It makes it hard to factor out a one-time asynchronous operation that loads assets (in this case, the script) from repeated instantiation of objects (the nodes) that employ those same assets.

Ideas to date (forgive me if I left yours out, and please re-propose it) have included:

- Don’t return a Promise. Continue to have createAudioWorker() return an AudioWorkerNode, synchronously. This node presumably isn’t ready to function yet, but it could be inserted into the graph. Script loading would happen later, after which the node would initialize (possibly posting a message back to the main thread to signal this).  This is a bit like what happens with other nodes that have delayed initialization e.g. HRTF spatialization. However it might leave important script-determined details like input/output count up in the air until the script has loaded and run.

- Have createAudioWorker() return Promises that yield individual nodes, and live with the potential delays and inconvenience to developers. Script loading and execution takes place each time a node is needed. Developers could preload scripts into local Blobs or data URLs to minimize delays.

- Have createAudioWorker() return a Promise that yields a factory object with a method that synchronously creates nodes, with each node having its own AudioWorkerGlobalScope based on the already-loaded script.  Script *loading* would thus occur once per factory instance, but script *execution* would occur once per node instance. (this is my proposal, though I have little idea of what any implementation objections would be.)

- Have createAudioWorker() return a Promise that yields a factory object containing a live AudioWorkerGlobalScope, and allow further nodes to be instantiated which share this same scope. Script loading and execution both occur once per factory, because the scope is shared. However this programming model does not isolate node instances’ state from each other. (This is my understanding of a proposal that Jussi made, I haven’t been able to track down the original. Jussi has said that some simple use of closures would make the state bookkeeping easy but I don’t think an example was provided.)

It would be great to surface some thinking on this via email, so that when we do discuss it on a telcon we’ll have already seen what the landscape looks like.

Best,

.            .       .    .  . ...Joe

PS  if you want to debate some other aspect of AudioWorkers, it would be great to start a new thread instead of using this one.

Received on Thursday, 6 November 2014 17:10:19 UTC