#filter #quad #state #unit #processing #surge #register

nightly surge-qfunit

surge synthesizer -- quad filter unit used for voice processing

26 releases

0.2.12-alpha.0 Apr 7, 2023
0.2.11-alpha.0 Dec 19, 2022
0.2.5-alpha.0 Jun 21, 2022
0.2.4-alpha.0 Mar 14, 2022
0.1.42-alpha.0 Oct 27, 2021

#6 in #surge

Download history 6/week @ 2023-12-30 42/week @ 2024-01-06 44/week @ 2024-01-13 32/week @ 2024-01-20 14/week @ 2024-01-27 39/week @ 2024-02-03 52/week @ 2024-02-10 67/week @ 2024-02-17 53/week @ 2024-02-24 55/week @ 2024-03-02 74/week @ 2024-03-09 65/week @ 2024-03-16 361/week @ 2024-03-23 104/week @ 2024-03-30 51/week @ 2024-04-06 76/week @ 2024-04-13

592 downloads per month
Used in 22 crates (16 directly)

GPL-3.0 license

325KB
5.5K SLoC

surge-qfunit

50> /file surge-rs/surge-qfunit/src/qf_unit_state.rs

This source file defines the QuadFilterUnitState struct, which represents the state of a quad filter unit. The struct contains fields for the filter coefficients, registers, delay buffers, activity masks, and comb write positions.

The struct provides methods for accessing and modifying the register values. The new method initializes a new QuadFilterUnitState instance with zeroed-out registers and an empty delay buffer. The TablesHandle struct is also passed in as a parameter and stored as a field in the QuadFilterUnitState.

Note that this source file makes use of the z128! macro, which returns an array of four __m128 vectors initialized to zero. These vectors are used throughout the codebase to represent four single-precision floating point values packed into a 128-bit SIMD register.

51> /file surge-rs/surge-qfunit/src/qf_chain_state.rs

This is the source code for the QuadFilterChain and QuadFilterChainState structs.

QuadFilterChain

QuadFilterChain is a struct that represents a chain of QuadFilterChainState structs. It is typically used with MAX_VOICES >> 2 elements, and each QuadFilterChainState performs filtering for four voices.

QuadFilterChainState

QuadFilterChainState is a struct that represents the state of a quad filter chain. It contains several fields that hold filter coefficients, registers, and delay buffers, as well as gain, feedback, mix, and drive parameters for each of four filter units. It also contains fields for wavedata, feedback stereo channels, and various other filter-related parameters.

The QuadFilterChainState struct has a method default_unit_state that returns an array of four QuadFilterUnitState structs, which represent the state of individual filter units in the quad filter chain.

The QuadFilterChainState struct also has several helper methods that create __m128 vectors filled with zeros.

52> /file surge-rs/surge-qfunit/src/do_dual1.rs

It looks like the do_dual1 method is one of several methods that perform filtering on a quad filter chain state. This method takes in four parameters:

  • A mutable reference to a WaveshaperState

  • A mutable reference to a QuadFilterChainState

  • A mutable reference to an FbqGlobal

  • A pointer to a f32 that will hold the left channel output

  • A pointer to a f32 that will hold the right channel output

The method performs the following operations:

  • Initializes a constant value hb_c with the value 0.5

  • For each sample in a block of audio data:

    • Updates the feedback value of the QuadFilterChainState by adding the d_feedback value

    • Multiplies the feedback value by the feedback_line_l value of the QuadFilterChainState and applies a softclip function to the result

    • Adds the feedback value to the dl[k] and dr[k] values of the QuadFilterChainState and stores the result in x and y, respectively

    • If a filter identified by the constant A_FILTER_ACTIVE is active, applies the filter to x using the first unit state of the QuadFilterChainState

    • If a filter identified by the constant B_FILTER_ACTIVE is active, applies the filter to y using the second unit state of the QuadFilterChainState

    • Adds the d_mix1 and d_mix2 values of the QuadFilterChainState to the mix1 and mix2 values, respectively

    • Calculates the mixed output by multiplying x by mix1 and y by mix2 and adding the results

    • If a waveshaper identified by the constant WAVESHAPER_ACTIVE is active, applies the waveshaper to the mixed output using the WaveshaperState and drive value of the QuadFilterChainState

    • Adds the d_gain value of the QuadFilterChainState to the gain value

    • Multiplies the mixed output by the gain value and applies a mask that is the result of applying a bitwise and operation to the active value of the first unit state of the QuadFilterChainState and the mixed output

    • Stores the masked output in the feedback_line_l value of the QuadFilterChainState

    • Writes the left and right channel output values by calling the qfc_write_outputs function with the appropriate arguments.

53> /file surge-rs/surge-qfunit/src/do_ring.rs

These two methods seem to perform filtering and processing on audio data using a QuadFilterChainState struct, which contains various data related to the state of the filter chain. The first method, do_dual1, appears to implement a dual filter topology, where two independent filters are applied to the audio data in parallel. The second method, do_ring, implements a ring modulation topology, where the output of one filter is used to modulate the input of the other filter.

Both methods perform operations on the QuadFilterChainState struct's fields, such as unit_state, which appears to contain information about each filter unit in the chain, and gain, which seems to determine the overall gain applied to the processed audio signal. Other fields like feedback and mix1 and mix2 appear to be used for intermediate calculations.

The methods also seem to use some external state, such as wss, a mutable reference to a WaveshaperState struct, and fbq, a mutable reference to a FbqGlobal struct. These references may be used to pass information between different parts of the program, or to access shared state.

Finally, both methods contain a call to qfc_write_outputs, which is not shown here but probably performs some output operations like writing the filtered audio data to a buffer.

54> /file surge-rs/surge-qfunit/src/do_serial1.rs

These are three methods of a Rust module, likely related to audio processing. The methods implement different filter topologies, which are used to process audio signals. All three methods share a similar structure where they iterate over a block of audio samples, process the samples with different filters, mix the results, and output the final signal.

The do_dual1 method seems to implement a dual-filter topology with feedback. The do_ring method seems to implement a ring modulation topology with feedback. The do_serial1 method seems to implement a serial filter topology without feedback.

Each method takes a WaveshaperState struct, a QuadFilterChainState struct, a FbqGlobal struct, and two *mut f32 pointers to output the left and right channels. The QuadFilterChainState struct seems to contain the state of the different filters, while the FbqGlobal struct contains pointers to the filter functions.

Overall, these methods appear to be low-level, performance-critical implementations of audio filters that leverage the SIMD capabilities of modern CPUs for speed.

55> /file surge-rs/surge-qfunit/src/do_stereo.rs

All of these functions seem to be part of a Rust crate called QFC (Quad Filter Chain), which implements various digital signal processing (DSP) algorithms, such as filtering, waveshaping, and mixing, among others. Each function seems to be a different implementation of the do_ prefix, which represents a specific processing topology for the filter chain. The different implementations seem to be optimized for different filter chains, and they take various boolean constants as parameters to determine which processing blocks to activate for a specific filter chain. All of these functions seem to be operating on f32 values using the SIMD instruction set provided by the sse Rust crate.

56> so, we have several hardcoded filter chains for different topologies

Yes, that's correct. These functions implement different filter topologies for the QuadFilterChainState struct. The different topologies correspond to different ways of connecting the two filters in series or in parallel. The specific topologies are chosen by calling the corresponding function based on the desired filter configuration.

57> what about QuadFilterChainState itself -- how is this used?

QuadFilterChainState is a struct used to store the state of a quad filter chain. It contains several arrays and values that are used to store the filter coefficients and state, as well as the mixing and feedback values used by the filter chain.

Here is the definition of the QuadFilterChainState struct:

pub struct QuadFilterChainState {
    pub dl:               [__m128; BLOCK_SIZE_OS],
    pub dr:               [__m128; BLOCK_SIZE_OS],
    pub feedback_line_l:  __m128,
    pub feedback:        __m128,
    pub mix1:            __m128,
    pub mix2:            __m128,
    pub gain:            __m128,
    pub d_feedback:      __m128,
    pub d_mix1:          __m128,
    pub d_mix2:          __m128,
    pub d_gain:          __m128,
    pub unit_state:      [UnitState; 2],
    pub active:          [bool; 4],
    pub drive:           __m128,
    pub d_drive:         __m128,
    pub ws_lpf:          __m128,
}

Some of the key fields in this struct include:

  • dl and dr: These are arrays of 4-element vectors (__m128) that store the input audio data for the left and right channels, respectively.

  • feedback_line_l and feedback: These are vectors that store the feedback values for the left channel filter chain.

  • mix1 and mix2: These are vectors that store the mixing values for the left and right channel filter chains, respectively.

  • gain: This is a vector that stores the overall gain for the filter chain.

  • d_feedback, d_mix1, d_mix2, d_gain, and d_drive: These are vectors that store the delta values (changes in value) for the feedback, mixing, gain, and drive parameters.

  • unit_state: This is an array of two UnitState structs that store the state for the two filter units in the filter chain.

  • active: This is an array of four booleans that indicate which filter units and channels are active in the filter chain.

  • drive and ws_lpf: These are vectors that store the drive and low-pass filter values used by the waveshaper.

The QuadFilterChainState struct is passed as an argument to the filter chain functions, which use its fields to perform the filtering and mixing operations. The values in the QuadFilterChainState struct are updated during each call to the filter chain functions to reflect the changes in the filter parameters and audio data.

58> interesting -- what distinguishes it from QuadFilterUnitState?

QuadFilterUnitState is a per-unit state struct that holds the state information for each of the four filter units in the QuadFilterChain. It contains parameters such as filter coefficients, filter state variables, and the like.

On the other hand, QuadFilterChainState is a struct that holds the state information for the entire QuadFilterChain. This includes the four QuadFilterUnitState structs, as well as state variables for the entire filter chain, such as feedback values, mix values, and gain values.

In other words, QuadFilterUnitState contains the state information for a single filter unit, while QuadFilterChainState contains the state information for the entire filter chain.

59> thanks -- it seems like we can select which topology to activate, which leverages several quad filter units. the chain is the overarching structure which manages the whole flow

Yes, that's correct. The QuadFilterChainState is the main structure that manages the flow of audio through the different quad filter units and other processing stages. It provides the necessary state information for each quad filter unit, such as the filter coefficients, filter state, and feedback parameters, as well as the mixing coefficients for combining the filtered signals. By activating different combinations of quad filter units, the quad filter chain can implement different filter topologies.

On the other hand, the QuadFilterUnitState contains the state information for each individual quad filter unit, such as the filter coefficients and state, and the gain and active flag. Each quad filter unit is responsible for processing a single channel of audio, and the QuadFilterUnitState is used to manage the state of each unit.

Dependencies

~12–22MB
~297K SLoC