Re: asynchronous vs synchronous instantiation of AudioWorkerNodes

On Thu, Nov 6, 2014 at 7:09 PM, Joseph Berkovitz <joe@noteflight.com> wrote:

> 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.)
>

FWIW, I just made a complete example on how to implement a Sine node on top
of my proposal:
https://gist.github.com/jussi-kalliokoski/aa84fbb4cde7fc54ff01


>
> 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 Sunday, 9 November 2014 13:09:50 UTC