When sending messages via postMessage to an AudioWorklet node within
an OfflineAudioContext, it is necessary to either introduce an artificial
delay (this isn't a deterministic or reliable solution), or post a message back to the main thread "acknowledging" the receipt of
the message before startRendering is called on the offline context.
This page sets up a very simple signal flow within an OfflineAudioContext:
An OscillatorNode is fed into an AudioWorklet node.
This AudioWorklet node is essentially a bypass, but it only passes audio if
it has received at least one message via its port.
It may be slightly surprising for a developer who writes the code which is run when pressing
the Render Immediately button to realize that no sound is rendered, even though
they have called postMessage. After some fiddling, they might
assume that the async nature of the postMessage call is to blame, and
insert a delay before calling startRendering on the context. This is
what happens when clicking on the Render With Delay button. This solution might
work for 99% of cases, but this poor developer will end up with strange bug reports in the
future, because adding a delay is inherently problematic since it depends on the thread
timings/scheduling of whatever platform you're running on.
Pressing this button will render the signal flow as outlined above for 1 second
inside an OfflineAudioContext. It will then play back the resulting
buffer. Because startRendering is called immediately after postMessage,
the resulting buffer will (almost always) be silent.
|
Pressing this button will render the signal flow as outlined above for 1 second
inside an OfflineAudioContext. It will then play back the resulting
buffer. Because startRendering is called a short time after postMessage,
the resulting buffer will (almost always) have audible output in it.
|
Perhaps it would make sense for AudioWorklet nodes inside an offline context to always
ensure that all pending postMessage calls are finished/handled before calls to
process?
Here's the code on github: Link. Alternatively, you can just view-source.