pyFDN.td.Recursion#

class pyFDN.td.Recursion(forward, feedback, *, block_size, delay_position='forward')[source]#

Closed feedback loop, y[n] = fF(x[n] + fB(y[n - block_size])).

A feedback loop cannot be evaluated sample by sample without an algebraic loop, so Recursion computes whole blocks of block_size samples at a time: it reads the loop state written by the previous block, runs both paths over the block, and writes the result back. That read-before-write is what breaks the loop – and it inserts exactly ``block_size`` samples of delay into the loop, on top of whatever delay the operators themselves have.

The inserted delay is not compensated automatically; a warning is issued at construction as a reminder. To compensate, shorten the delay lines on the path named by delay_position by block_size samples, e.g. Delay(delays - block_size). The uncompensated delays must be at least block_size long; a shortened Delay may be zero.

Parameters:
  • forward (TimeOperator) – Forward path fF, from the loop input to the loop output.

  • feedback (TimeOperator) – Feedback path fB, from the loop output back to the loop input.

  • block_size (int) – Processing block size in samples, and therefore the amount of delay inserted into the loop. Required: it is a property of the loop the caller has to choose and compensate for, not an implementation detail. When compensating explicit delay lines, it must not exceed their shortest uncompensated delay.

  • delay_position (str) –

    Which side of the loop the inserted block_size delay lands on, i.e. where the state buffer sits:

    "forward" (default)

    After the forward path: the loop output is read out of the state buffer, so it is the forward output that arrives block_size samples late (y[n] = fF(...)[n - block_size]). Compensate on the forward path. Use this when the delay lines are in the forward path (the usual FDN layout: delays forward, mixing matrix feedback).

    "feedback"

    After the feedback path: the forward output is returned immediately and it is the signal fed back that is block_size samples late (y[n] = fF(x[n] + fB(y)[n - block_size])). Compensate on the feedback path. Use this when the delay lines are in the feedback path, e.g. an outer acoustic-feedback loop around a whole system.

    Both give the same total loop delay; they differ in where in the loop that delay sits, hence in which path has to absorb the compensation and whether the operator’s own output is delayed.

__init__(forward, feedback, *, block_size, delay_position='forward')[source]#

Methods

__init__(forward, feedback, *, block_size[, ...])

process_block(block)

Process one block of audio.

process_signal(signal, *[, squeeze])

Process a whole signal in one call, from the current state.

reset()

Resets the state of all internal TimeOperators.

Attributes

in_channels

out_channels

process_block(block)[source]#

Process one block of audio.

Parameters:

block (ArrayLike) – Input block of audio.

Raises:

ValueError – Mismatch between audio-block channels and Recursion input channels

Returns:

Output block of audio.

Return type:

ndarray

reset()[source]#

Resets the state of all internal TimeOperators.

Return type:

None