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) – which requires every delay on that path to be at least 2 * block_size long, since the shortened line still has to be at least one block long.

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. It must not exceed the shortest delay on the loop, or the loop would run ahead of its own delay lines.

  • 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[, ...])

filter(block)

Filter block of audio.

process(signal, *[, squeeze])

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

reset()

Resets the state of all internal TimeOperators.

Attributes

in_channels

out_channels

filter(block)[source]#

Filter 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