pyFDN.trainable_from_build#

pyFDN.trainable_from_build(build, *, trainable=None, matrix='orthogonal', post_delay=None, post_matrix=None, post_output=None, nfft=16384, alias_decay_db=0.0, device=None, dtype=None)[source]#

Build a trainable flamo Shell initialized from an FDNBuild.

The gains and the feedback matrix come from the build. The three filter hooks are the build’s own baked SOS banks, frozen, unless you hand in a module for that position – which is how a designed, trainable filter gets in, since a baked build no longer remembers the reverberation time or the EQ curve it was designed from:

model = pyFDN.trainable_from_build(
    build,
    post_delay=pyFDN.AttenuationFilter(
        1.0, build.delays, build.fs, rt_nyquist=1.0,
        design="first_order_shelf", nfft=nfft),
    post_output=pyFDN.OutputEQ(
        0.0, build.C.shape[0], build.fs,
        design="first_order_shelf", nfft=nfft),
)

Each of those modules is trained because it says so itself (both default to requires_grad=True); pass requires_grad=False for a designed filter that must not move.

Parameters:
  • build (FDNBuild) – Initial FDN (A/B/C/D/delays/fs + optional post_delay/post_output SOS banks).

  • trainable (Trainable | None) – Which gain groups are trained (default Trainable). It says nothing about the filter hooks: each module below carries its own requires_grad, and is wired in exactly as it was built.

  • matrix (Literal['orthogonal', 'random']) – Feedback-matrix parametrization.

  • post_delay (Any) – In-loop filter, replacing build.post_delay. A AttenuationFilter here makes the trained parameter the reverberation time itself, which keeps the loop contractive for every value it can take.

  • post_matrix (Any) – Filter on the feedback path, replacing build.post_matrix.

  • post_output (Any) – Output EQ, replacing build.post_output; typically an OutputEQ. It sits outside the recursion, which makes it the only part of an FDN that can shape the response’s spectral envelope without touching the decay – b and c are single numbers per delay line, with no frequency dependence at all.

  • nfft (int) – FFT size.

  • alias_decay_db (float) –

    The accuracy of the rendered impulse response, in dB. Applies a \(\gamma^n\) envelope to every module (evaluating the system on a circle of radius \(\gamma < 1\)); the shell’s output layer removes it again, so the response is the true one and only the time-aliased wrap-around remains, suppressed by exactly alias_decay_db. In float32 the reconstruction amplifies round-off by the same factor, so ~60 dB is the practical ceiling; use dtype=torch.float64 beyond that.

    Leave at 0 for a decaying FDN, which damps itself within nfft samples. A lossless FDN needs it: with its poles exactly on the unit circle the FFT-domain evaluation is near-singular and the response comes out wrong, not merely aliased. It does not affect the extracted build (it enters the frequency-domain evaluation, not the parameter map, so pyFDN.extract_build() still returns the undamped A/B/ C). A module you pass into a hook must have been built with the same value: it is a change of evaluation radius for the whole system, not a per-module gain.

  • device (Any) – Torch device / dtype (default cpu-or-cuda / float32).

  • dtype (Any) – Torch device / dtype (default cpu-or-cuda / float32).

Return type:

Any