RustAudio/dsp-chain

Support multiple-output nodes' audio_requested methods properly within `Graph`.

mitchmindtree opened this issue · 0 comments

In the case that a node has multiple outputs, it's audio_requested method will be called more than once per buffer. This is an issue for any mutable nodes who update their state during the audio_requested method. For example, a synth's phase is updated during it's audio_requested - if it is updated more than once per buffer, this will create clipping when the phase is misaligned for the following buffer. Similar problems would occur in reverb and delay effects.

This is only possible within the Graph data structure, as it is the only design in dsp-chain that allows for a node to act as an input to multiple other nodes.

To support this, the generic D: Dsp could be wrapped in something like this when added to the graph.

struct DspNodeBuffer<S, D>
    where
        S: Sample,
        D: Dsp<S>
{
    dsp_node: D,
    maybe_buffer: Option<Vec<S>>
} 

This would mean that, rather than calling audio_requested directly on D, we could call it on DspNodeBuffer who would

  1. Check to see how many outputs the node has.
  2. If it has only one, generate a buffer and move it straight to the output and leave maybe_buffer as None.
  3. If it has more than one, check to see if maybe_buffer is Some(_)
  4. If it is Some, clone the existing buffer to output.
  5. Otherwise, call audio_requested on dsp_node to fill a buffer, clone it to the output and store it in maybe_buffer.
  6. At the end of audio_requested, Graph resets all maybe_buffers within all DspNodeBuffers to None.