Re: Comments on AudioWorklet examples

It took me a day to think about questions you raised. I think we have an
important decision to make. Please find my responses inline:


Hi Hongchan,
>
> Thanks for responding! I will attempt some stunted responses from my phone
> since I'm traveling today, to keep the discussion going.
>
> Based on our previous discussion, I'd expect that there needs to be a
>> subclass constructor that explicitly copies these values out of the
>> AudioNodeOptions into the new node's AudioParams, like this:
>>
>> class BitcrusherNode extends AudioWorkletNode {
>>   constructor(ctx, options) {
>>     super(ctx, 'Bitcrusher', options);
>>     if (options.hasOwnProperty('bitDepth') {
>>       this.bitDepth.value = options.bitDepth;
>>     }
>>     // ...initialize other params, initial state up front, possibly
>> utilizing postMessage()...
>> }
>>
>
> Just to confirm: so this is a node definition, not the processor?
> Initializing these values from the main thread is a definitely better idea,
> but the pattern here is quite involved and verbose. I think we can start
> from this idea and try to simplify the syntax to find a sweet spot. I
> really need to think about having two definitions for both threads. Very
> explicit, but that also makes us diverge from Worklet infrastructure which
> I am a bit afraid of.
>
>
> Sorry, I don't see where this diverges from Worklets -- what am I missing?
>

Worklet spec does not specify (nor expose) main thread interface. The class
definition is solely for off-main-thread processing. Now I am realizing
this is the biggest difference between AudioWorklet and other worklet
variants. Let's say you can define the node representation as shown above,
how can the browser match the corresponding processor object? That part
seems also magical to me. In that case, we might have to introduce a new
method that runs within global scope to define a `name` and to match the
processor accordingly. Is that okay?


The reason I made this a subclass is because otherwise I did not see how to
> make use of the custom AudioNodeOptions entries that your example employed
>  to initialize the bitcrusher AudioParams. The options are constructor
> args, so unless there is some behavior in AudioWorkletNode that
> automagically initializes AudioParams with matching names, I don't see how
> else it can happen.
>

> If you do envision this init behavior then please make it explicit. Would
> it apply only to AudioParams? (I assume so because nothing else about a
> Processor can be declared)
>
> Of course one could leave the Params out of the ctor options argument and
> just initialize them after creating the AudioWorkletNode.
>

One thing I also want to avoid is over-complicating the definition of
AudioWorkletNode. Your idea makes perfect sense to me, but I think it is
too burdensome to developers having to define a node and a processor only
for the initialization of AudioParams. Beyond the parameter initialization,
what else can we do? You can define a new method, but it is just a wrapper
function of postMessage(). I agree that being explicit always win at the
end, so this is something we have to decide.

2. When are the params for a node determined, and when can they change?
>> We've changed up the lifecycle quite a bit now, so I'm not sure what the
>> answer is. I recall that we went to some trouble before to ensure that the
>> set of params was known at the actual time that an AudioWorkerNode was
>> instantiated, just like they would be for a native node.
>>
>
> We can introduce event like `created` for the instance-specific
> initialization. I find this pattern is very useful when using Polymer.
>
> class BitCrusherProcessor extends AudioWorkletProcessor {
>   constructor () { /* this is called when the instance is created. */ }
>   created () { /* this is called the initialization for both threads is
> done. */ }
>   process () {...}
> }
>
> Create() Seems good but optional.
>
> I just wanted to make sure that our mechanism allows a new AudioWN to
> exhibit the parameters that were defined, from the moment of its
> instantiation.
>

I would like to work on the idea of using `created()` event for
initialization. I believe it can be done with this pattern, but we might
have to pass actual AudioParam references as an argument for `created()`.


> The only opportunity we have to discover parameter descriptors is before
>> the success of the promise from the script import for a node type.
>>
>   So *maybe* it works like this: after the script is imported for an
>> AudioWorkletProcessor, the Processor gets instantiated once prior to the
>> success of the Promise and its paramDescriptors getter is examined; the
>> result determines the set of parameters exposed by subsequent nodes of that
>> type. The Processor instance is then thrown away; its only purpose was to
>> figure out what params exist for this node type.
>>
>
> Can you elaborate on this a bit more? I am not sure if I am following you.
>
>
> Along the lines of my previous response, I was asking myself how the API
> can know what parameters exist for a Node whose Processor doesn't exist
> yet. Yet it is the Processor that exposes the param descriptors.
>

> The only way I see for this to happen is for a Processor to be created as
> part it's registration, solely for the purpose of interrogating its param
> descriptors.
>

I am still not sure about what is being asked, but let me try; you cannot
know the parameters of a node before its instantiation. Isn't this how a
regular audio node works? After the construction and when created() method
gets called, the node reference and AudioParams within will be accessible.
Or are you asking we implement the new feature for AudioWorkletNode? I can
see the benefit of figuring out parameters from a node that hasn't been
created, but I believe it is slightly off-topic.

This would make it hard to add/remove parameters on the fly. But I don't
>> know that this is important.
>>
>
> I am opposing to the idea of adding/removing parameters on the fly. The
> current AudioNodes do not support this, so I guess this is where we draw
> the line for V1.
>
>
> +1 on that.
>
> ...Joe
>

Received on Wednesday, 1 June 2016 17:43:32 UTC