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.