sfFDN
Loading...
Searching...
No Matches
sfFDN::TimeVaryingFeedbackMatrix Class Reference

An orthogonal time-varying feedback matrix for an FDN. More...

#include <time_varying_feedback_matrix.h>

Inheritance diagram for sfFDN::TimeVaryingFeedbackMatrix:
[legend]
Collaboration diagram for sfFDN::TimeVaryingFeedbackMatrix:
[legend]

Public Member Functions

 TimeVaryingFeedbackMatrix (const TimeVaryingFeedbackMatrixOptions &options)
 Constructs a time-varying feedback matrix.
 
void SetModulation (std::span< const ModulationOptions > modulation_configs)
 Sets the modulation options for each rotation block.
 
void SetLfoFrequency (std::span< const float > frequencies)
 Sets the LFO frequency for each rotation block.
 
void SetLfoAmplitude (std::span< const float > amplitudes)
 Sets the LFO amplitude for each rotation block.
 
void SetLfoPhaseOffset (std::span< const float > phase_offsets)
 Sets the LFO phase offset for each rotation block.
 
void SetBaseAngles (std::span< const float > radians)
 Sets the base rotation angle for each rotation block.
 
void Process (const AudioBuffer &input, AudioBuffer &output) noexcept SFFDN_NONBLOCKING override
 Processes the audio buffer.
 
uint32_t InputChannelCount () const noexcept SFFDN_NONBLOCKING override
 Gets the number of input channels.
 
uint32_t OutputChannelCount () const noexcept SFFDN_NONBLOCKING override
 Gets the number of output channels.
 
uint32_t RotationBlockCount () const noexcept SFFDN_NONBLOCKING
 Gets the number of 2x2 rotation blocks.
 
bool GetMatrix (std::span< float > matrix, uint64_t sample_index=0) const
 Materializes the feedback matrix that Process applies at a given sample index.
 
void Clear () override
 Resets the phase of all LFOs to their configured phase offsets.
 
std::unique_ptr< AudioProcessorClone () const override
 Creates a copy of the time-varying feedback matrix.
 
- Public Member Functions inherited from sfFDN::AudioProcessor

Friends

class detail::TimeVaryingFeedbackMatrixTestAccess
 

Additional Inherited Members

- Protected Member Functions inherited from sfFDN::AudioProcessor
 AudioProcessor (const AudioProcessor &)=default
 
AudioProcessoroperator= (const AudioProcessor &)=default
 
 AudioProcessor (AudioProcessor &&) noexcept=default
 
AudioProcessoroperator= (AudioProcessor &&) noexcept=default
 

Detailed Description

An orthogonal time-varying feedback matrix for an FDN.

At sample n, the construction is:

  • Hadamard mode: \(A(n) = H^T \mathop{\mathrm{blockdiag}}(R(\theta_k(n))) H\).
  • RealSchur mode: \(A(n) = V \mathop{\mathrm{blockdiag}}(R(\theta_k(n))) V^T\).

Each factor is orthogonal, so \(A(n)\) is exactly orthogonal at every sample. This makes a time-varying FDN stable and energy-preserving.

Modulation units and recommended setup
ModulationOptions::amplitude is normalized, with |amplitude| <= 1, following the AES paper's convention. It is multiplied by π exactly once internally to obtain the peak angular deviation in radians. Thus, amplitude = 0.7 means a peak deviation of 0.7π, approximately 2.2 radians, not 0.7 radians. The JASA paper instead uses the angular convention μ_A <= π. LFO frequency is in cycles per sample: 1 Hz at 48 kHz is 1.0f / 48000.0f.

Schlecht and Habets (2015, JASA 138(3) and AES Convention paper 9255) recommend an approximately 1 Hz modulation frequency, an amplitude of approximately 0.7, random initial phases, and per-block frequencies spread by about ±50%. Frequencies below 0.2 Hz make modulation imperceptible; above 2 Hz they introduce obvious periodic temporal patterns and detuning, although up to 4 Hz can still sound smooth and natural. Do not modulate every block synchronously: the papers report easily perceivable beating.

Limitations
Hadamard mode requires a power-of-two matrix_size; RealSchur mode accepts any even size. Both reject odd sizes because an odd-dimensional orthogonal matrix necessarily has a static real eigenvalue. Modulation is full-band.

Constructor & Destructor Documentation

◆ TimeVaryingFeedbackMatrix()

sfFDN::TimeVaryingFeedbackMatrix::TimeVaryingFeedbackMatrix ( const TimeVaryingFeedbackMatrixOptions & options)
explicit

Constructs a time-varying feedback matrix.

Parameters
optionsThe configuration options for the feedback matrix.
Exceptions
std::invalid_argumentIf the matrix size or mode is invalid, the Hadamard size is not a power of two, the modulation count is invalid, a modulation parameter is non-finite, an initial phase is outside [0, 1], or an amplitude is outside [-1, 1].

Member Function Documentation

◆ Clear()

void sfFDN::TimeVaryingFeedbackMatrix::Clear ( )
overridevirtual

Resets the phase of all LFOs to their configured phase offsets.

Implements sfFDN::AudioProcessor.

◆ Clone()

std::unique_ptr< AudioProcessor > sfFDN::TimeVaryingFeedbackMatrix::Clone ( ) const
overridevirtual

Creates a copy of the time-varying feedback matrix.

Returns
A unique pointer to the cloned processor.

Implements sfFDN::AudioProcessor.

◆ GetMatrix()

bool sfFDN::TimeVaryingFeedbackMatrix::GetMatrix ( std::span< float > matrix,
uint64_t sample_index = 0 ) const

Materializes the feedback matrix that Process applies at a given sample index.

Parameters
matrixDestination for matrix_size * matrix_size values in row-major order, matching ScalarFeedbackMatrix::GetMatrix: matrix[row * matrix_size + column] = A[row, column], where y = A * x.
sample_indexThe index, counted from the start of an unprocessed stream, of the sample whose matrix is wanted. Zero yields the matrix applied to the very first sample.
Returns
False if the span does not contain exactly matrix_size * matrix_size values.

This is a pure query: it neither reads nor mutates the running LFO phases, so its result depends only on the configuration and sample_index. It allocates and is not realtime-safe; call it from a control or UI thread. Because it ignores the processing state, it is safe to call concurrently with Process.

◆ InputChannelCount()

uint32_t sfFDN::TimeVaryingFeedbackMatrix::InputChannelCount ( ) const
overridevirtualnoexcept

Gets the number of input channels.

Returns
The matrix size.

Implements sfFDN::AudioProcessor.

◆ OutputChannelCount()

uint32_t sfFDN::TimeVaryingFeedbackMatrix::OutputChannelCount ( ) const
overridevirtualnoexcept

Gets the number of output channels.

Returns
The matrix size.

Implements sfFDN::AudioProcessor.

◆ Process()

void sfFDN::TimeVaryingFeedbackMatrix::Process ( const AudioBuffer & input,
AudioBuffer & output )
overridevirtualnoexcept

Processes the audio buffer.

Parameters
inputThe input audio buffer.
outputThe output audio buffer. The input and output channel counts must both equal the matrix size, and their sample counts must match.

Implements sfFDN::AudioProcessor.

◆ RotationBlockCount()

uint32_t sfFDN::TimeVaryingFeedbackMatrix::RotationBlockCount ( ) const
noexcept

Gets the number of 2x2 rotation blocks.

Returns
The number of independently modulatable rotation blocks.
Note
Query this after construction before sizing a RealSchur time_varying_config, because its block count depends on the constructed basis. Hadamard mode always has matrix_size / 2 blocks.

◆ SetBaseAngles()

void sfFDN::TimeVaryingFeedbackMatrix::SetBaseAngles ( std::span< const float > radians)

Sets the base rotation angle for each rotation block.

Parameters
radiansThe finite base angles in radians, one per rotation block. Angles are range-reduced to [-π, π].

◆ SetLfoAmplitude()

void sfFDN::TimeVaryingFeedbackMatrix::SetLfoAmplitude ( std::span< const float > amplitudes)

Sets the LFO amplitude for each rotation block.

Parameters
amplitudesThe normalized LFO amplitudes, one per rotation block. Each amplitude must be in [-1, 1] and is multiplied by π once internally to obtain its peak deviation in radians. For example, 0.7 denotes 0.7π, not 0.7 radians.

◆ SetLfoFrequency()

void sfFDN::TimeVaryingFeedbackMatrix::SetLfoFrequency ( std::span< const float > frequencies)

Sets the LFO frequency for each rotation block.

Parameters
frequenciesThe normalized LFO frequencies, one per rotation block. Frequencies are finite values in cycles per sample; for example, 1 Hz at 48 kHz is 1.0f / 48000.0f.

◆ SetLfoPhaseOffset()

void sfFDN::TimeVaryingFeedbackMatrix::SetLfoPhaseOffset ( std::span< const float > phase_offsets)

Sets the LFO phase offset for each rotation block.

Parameters
phase_offsetsThe normalized LFO phase offsets, one per rotation block. Each offset is finite and in [0, 1] cycles, where 1 is a full cycle.

◆ SetModulation()

void sfFDN::TimeVaryingFeedbackMatrix::SetModulation ( std::span< const ModulationOptions > modulation_configs)

Sets the modulation options for each rotation block.

Parameters
modulation_configsThe modulation options, one per rotation block. An empty span disables modulation. Otherwise, the span must contain exactly one configuration per rotation block.

The documentation for this class was generated from the following file: