pyFDN.td.TimeVaryingKroneckerMatrix#

class pyFDN.td.TimeVaryingKroneckerMatrix(angles, fs, *, rate=0.0, depth=0.0, phase=0.0, kernel_type='rotation', waveform='sine')[source]#

Kronecker feedback matrix with per-kernel angle modulation (time-varying feedback).

Each kernel angle follows theta_i(t) = angles[i] + depth[i] * w(2 * pi * rate[i] * t + phase[i]) with w a unit-amplitude sine or triangle, so the matrix is orthogonal at every sample yet never constant. This is the matrix modulation of Coppola (2026, Section 5.4): unlike delay-line modulation it changes only the routing coefficients between delay lines, which breaks up fixed modal resonances without the chorusing that modulated delays introduce.

Because the angles are consumed by the fast butterfly, per-sample modulation costs no more than the static matrix – there is no N x N matrix to rebuild when an angle moves.

Sits on the feedback path of a Recursion, or goes straight into the post_matrix argument of pyFDN.process_dss() with A left as the identity, in which case this operator is the feedback matrix.

Parameters:
  • angles (ArrayLike) – M unmodulated kernel angles in radians, innermost first. The modulation is centred on these.

  • fs (float) – Sampling rate in Hz; the modulation clock.

  • rate (ArrayLike) – Modulation frequency in Hz, one value or one per kernel.

  • depth (ArrayLike) – Modulation amplitude in radians, one value or one per kernel. Zero leaves a kernel static, which is how a single level is singled out for modulation (the paper modulates theta_{M-1}).

  • phase (ArrayLike) – Initial modulation phase in radians, one value or one per kernel.

  • kernel_type (str | Sequence[str]) – "rotation" or "reflection", either once for all kernels or one per kernel.

  • waveform (str) – Modulation shape.

Variables:
  • sample_index (int) – Current sample index; the modulation clock. reset() rewinds it.

  • Example:: –

    # 16 channels, stereo halves decoupled, theta_3 modulated at 0.2 Hz depth = [0.0, 0.0, 0.2 * np.pi, 0.0] td.TimeVaryingKroneckerMatrix(

    pyFDN.kronecker_angles(16, theta4=0.0), fs, rate=0.2, depth=depth

    )

__init__(angles, fs, *, rate=0.0, depth=0.0, phase=0.0, kernel_type='rotation', waveform='sine')[source]#

Methods

__init__(angles, fs, *[, rate, depth, ...])

angles_at(sample_indices)

Kernel angles at the given sample indices, shape (len(indices), M).

process_block(block)

Process one block and advance internal state.

process_signal(signal, *[, squeeze])

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

reset()

Rewind the modulation clock to sample zero.

Attributes

in_channels

out_channels

angles_at(sample_indices)[source]#

Kernel angles at the given sample indices, shape (len(indices), M).

Exposed so the modulation trajectory can be plotted or fed to pyFDN.kronecker_matrix() for analysis without rendering audio.

Return type:

ndarray

process_block(block)[source]#

Process one block and advance internal state.

Return type:

ndarray

reset()[source]#

Rewind the modulation clock to sample zero.

Return type:

None