- From: Chris Wilson <cwilso@google.com>
- Date: Thu, 6 Nov 2014 14:43:06 -0800
- To: Joseph Berkovitz <joe@noteflight.com>
- Cc: Audio WG <public-audio@w3.org>
- Message-ID: <CAJK2wqX5Q-jde8vjWk3yFerkBw_CdGrZpR919Nx_8pVW6_RQ7A@mail.gmail.com>
Mostly, I wanted to be clear that the idea of having a worker node constructor that returned a promise was a bad idea imo, after consideration. Your proposal - 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. Would probably be okay (with the caveat that "synchronously creates nodes" still means the node needs to instantiate on the other thread to actually start processing audio); it makes yet another layer of indirection, which I'm not overly fond of, but could be okay; I haven't looked at the cross-thread implications yet. I'm a bit worried it's one more scope to manage, but I'd be interested to see what it would look like. Presumably the model there is any custom worker node types you might want to use later, you'd need to call their factory constructors first. In this case, the only problem is we STILL can't replicate the current behavior (since AudioContext construction isn't asynchronous) - we really need a synchronous bit that enables node creation (and subsequent AudioParam usage) in the main thread, and the async "load up the worker scripts" in the audio thread to be independent. Otherwise, you can't do: var ac = new AudioContext(); ...some synchronous steps?? var gain = ac.createMyCustomGainNode(); gain.gain.value = 0.5; 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. On Thu, Nov 6, 2014 at 2:18 PM, Joseph Berkovitz <joe@noteflight.com> wrote: > > On Nov 6, 2014, at 4:50 PM, Chris Wilson <cwilso@google.com> wrote: > > *Conclusion:* > Keeping in mind your custom code can encapsulate the worker scripts, I > think it's better if we just presume that "component" scripts will be > main-thread scripts that package up (as blob, e.g.) the worker script, and > then encapsulate a factory method or object constructor. > > E.g.: > > <script src="worker-based-gain.js"></js> <!-- packages up the worker, and > exposes MyGainNode constructor --> > <script> > var gain = new MyGainNode( audioContext ); > gain.gain.value = 0.5; > </script> > > > OK, so IIRC your suggestion corresponds to this proposal in my list, yes? > > - 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). >> > > As a best practice you are suggesting that a library that “fronts” for > custom nodes can do some local caching of worker scripts as Blobs, etc. > which will minimize the delay between the node’s instantiation and its > subsequent loading of the script and processing audio. It seems to me that > this still means that JS loading/parsing (albeit from some kind of local > storage) is taking place on a per-node basis. > > That may be workable, but could you please explain why the two proposals > in which a node factory is created from a preloaded script don’t work for > you? It would seem desirable to separate worker-script loading from worker > node instantiation if at all possible, much as the API separates buffer > loading from buffer node creation. > > …Joe >
Received on Thursday, 6 November 2014 22:43:34 UTC