Re: asynchronous vs synchronous instantiation of AudioWorkerNodes

I'll attempt an approach that enables state-sharing across instances in the
next edit (when I take on dynamic channels and inputs/outputs).  It's going
to be a couple of weeks due to Chrome Dev Summit and Thanksgiving.

It will be a bit more complex, since you can't just tack expandos onto the
params object; params needs to be read-only, since the members are "owned"
by the AudioParam setup in the main thread (need to avoid conflicts).  Will
have to do something like that that be a sub-object of a node state object.

On Fri, Nov 7, 2014 at 10:12 AM, Joseph Berkovitz <joe@noteflight.com>
wrote:

> On Nov 6, 2014, at 7:42 PM, Robert O'Callahan <robert@ocallahan.org>
> wrote:
>
> On Fri, Nov 7, 2014 at 6:09 AM, Joseph Berkovitz <joe@noteflight.com>
> wrote:
>
>> - 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... [snip]
>>
>> - 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.)
>>
>
> I prefer the latter, although the former works too. The ability to share
> resources easily in the latter approach seems worth having.
>
>
> I am starting to feel that a Jussi-style proposal is better myself,
> although I originally felt otherwise. For instance, a node with substantial
> preloaded data (as today’s native HRTF implementation) would surely not
> want to load it up once per node.
>
> Also, the value of preloading the script in my first proposal feels
> questionable if the script still has to be parsed and then fired up into a
> private scope on every node instantiation. In the latter approach, scripts
> are loaded, parsed and activated once and then it’s all over. Seems cleaner.
>
> On Nov 6, 2014, at 7:44 PM, Robert O'Callahan <robert@ocallahan.org>
> wrote:
>
> On Fri, Nov 7, 2014 at 11:43 AM, Chris Wilson <cwilso@google.com> wrote:
>
>> I DON'T like the proposal of sharing the scope across node instances,
>> because I don't see how you could store state then; but on the other hand,
>> some state MIGHT want to be shared across nodes (e.g. HRTF database).
>> Hmm.  Complexifies the design quite a bit to have a global scope and a node
>> scope, though.
>>
>
> One option would be to have the spec *required* that
> AudioProcessEvent.parameters is the same object every time the event fires
> for a given Node. Then the worker script can attach its own per-node state
> to the parameters object (using regular JS expandos).
>
>
> I agree with RoC’s direction: something like this can make the design
> reasonably simple and make it clear to developers. I’ve arrived at a
> slightly different flavor of this idea, which I’ll try to describe here.
>
> The spec could state that the “target” and “currentTarget” properties of
> all events delivered to this script are an object of type
> AudioWorkerProcessor. This object's identity must be preserved across *all
> events that pertain to any given node*. You can think of it as an
> audio-thread proxy for the node; it is also considered to be the dispatcher
> of node-related audio events.
>
> The IDL for it might look like this:
>
> interface AudioWorkerProcessor : EventTarget
>  {
>     attribute object data;        // this is initially an empty object;
> the script can store arbitrary state in its properties
>     void postMessage(…);     // posts a message back to the main-thread
> AudioWorkerNode
>     void terminate();               // kills audio-engine reference to
> node resources; no further events will be dispatched and GC is enabled
> };
>
> In this scheme, the AudioWorkerGlobalScope handlers onmessage and
> onaudioprocess continue to be common to all nodes, but they deliver events
> that have different AudioWorkerProcessors as targets.
>
> If you don’t like common handlers, a variation of this approach could move
> onaudioprocess and onmessage into the AudioWorkerProcessor as EventHandler
> attributes.  A shared oncreate handler in the AudioWorkerGlobalScope would
> then set up these handlers for each node, when it was created. (This would
> even allow different nodes created by the same script to behave
> differently, if the oncreate event were able to communicate some
> node-construction parameter from the main thread.)
>
> For this to work, I think the Promise from the original
> createAudioWorker() needs to yield something like this:
>
> interface AudioWorkerNodeFactory
> {
>     AudioWorkerNode createAudioWorkerNode(…);
> }
>
> I’m not being fussy about all of these names, by the way, I assume they’d
> all need to be improved.
>
> …Joe
>
>

Received on Saturday, 8 November 2014 15:07:51 UTC