# AudioNode Tail Processing
The WebAudio API has a concept of a
[tail-time](https://webaudio.github.io/web-audio-api/#tail-time) in
which an AudioNode must continue to process even if the input(s) to
the node are disconnected. For example, if you have a `DelayNode` with
a delay of 1 sec, the node must continue to output data for at least 1
sec to flush out all the delayed data.
# Implementation Details
## Basic Concepts
To implement this, we introduce the `TailTime` and `LatencyTime`
methods for each node. This isn't required in the spec, but the
implementation makes this distinction. (Not sure why). TailTime is
how long it takes before a node that has silent input will produce
silent output. LatencyTime is how long it takes non-silent input to
produce non-silent output.
The sum of these two terms tells us how long a node needs to process
to flush out its internal state.
## Details
To support tail processing several routines are used:
- `PropagatesSilence`: returns true if the node is producing silence
after knowing the inputs are silent
- `RequiresTailProcessing: returns true if the node needs tail
processing. For example, `GainNode`s have no memory so tail
processing is not needed.
## Triggering Tail Processing
### Silent Inputs
The actual details are a bit complicated, but basically
`AudioNode::ProcessIfNecessary` manages this. It keeps track of when
the node was last non-silent. If the inputs are silent and
`PropagatesSilence` returns false, the nodes `Process` method is still
called.
For most nodes, `PropagatesSilence` checks to see if the last
non-silent time plus the `TailTime` plus the `LatencyTime` is greater
than the context `currentTime`. If so, then the node produces silence
now because the internal state has been flushed out.
### Disabled Outputs
There is another way to start tail processing, and this is the more
difficult case that we need to handle. Consider an `OscillatorNode`
connected to a `DelayNode`. When the `OscillatorNode` stops, it
disables its output, basically marking its output as silent. This
normally propagates down the graph disabling the output of each node.
However, the `DelayNode` needs to continue processing. The logic for
tail processing is in `AudioNode::DisableOutputsIfNecessary`. If
`RequiresTailProcessing()` returns true, this node is added to the
tail processing handler list (`tail_processing_handlers_`) via
`DeferredTaskHandler::AddTailProcessingHandler()`. If not, the output
of the node is disabled which propagates through the downstream
nodes.
Then during the beginning and end of each render quantum, we check the
tail processing list to see if the handler would be silent (via
`PropagatesSilence()`). If it would produce silence, it's removed from
the list. Otherwise, nothing is done.
Note also that if a connection is made to the node, it is removed from
the tail processing list since it's not processing the tail anymore.
### Some Complications
Because WebAudio has two threads: the main thread and the audio
rendering thread, things are a bit more complicated. Removing a
handler from tail processing cannot be done on the audio thread
because it requires changing the state of the output. Thus, when this
happens, the handler is removed from the tail processing list and
placed on the `finished_tail_processing_handlers_` list. At Each
render quantum, a task is posted to the main thread to update the
output state.
### Additional Complications
In addition, we had to make some guesses on the tail time for
`BiquadFilterNodes` and `IIRFilterNodes`. In theory, these have an
infinite tail since the both of thse are infinite impulse response
filters. In practice, we don't really want the `TailTime` to be
infinite because then the nodes basically never go away.
For an `IIRFilterNode`, we actually compute the impulse response and
determine approximately where the impulse response is low enough to
say it is done. We also arbirarily limit the maximum value, just to
prevent huge tail times.
For a `BiquadFilterNode`, we don't compute the impulse response
because automations of the filter parameters can change the tail.
Instead, we determine the poles of the filter and from that determine
roughly the analytical impulse response. From the response, we
determine when the response is low enough to say the tail is done.
Like the `IIRFIlterNode`, this is limited to a max value.
For a `DelayNode`, we just set the tail time to be the max delay value
for the node instead of trying to determine a tail time from the
actual `delayTime` parameter.
# Summary
## Important Variables
- `DeferredTaskHandler::tail_processing_handlers_`
- `DeferredTaskHandler::finished_tail_processing_handlers_`
## Important Methods
- `AudioNodeHandler::ProcessIfNecessary`
- `AudioNodeHandler::EnableOutputsIfNecessary`
- `AudioNodeHandler::TailTime`
- `AudioNodeHandler::LatencyTime`
- `AudioNodeHandler::PropagatesSilence`
- `AudioNodeHandler::RequiresTailProcessing`
- `DeferredTaskHandler::AddTailProcessingHandler`
- `DeferredTaskHandler::RemoveTailProcessingHandler`
- `DeferredTaskHandler::UpdateTailProcessingHandlers`