DSPark 1.8.0
Header-only C++20 DSP for real-time and offline audio
Loading...
Searching...
No Matches
dspark::Expander< T > Class Template Reference

Downward expander with ratio control, hysteresis, and sidechain. More...

#include <Expander.h>

Public Types

enum class  State { Closed , Open , Hold }
 

Public Member Functions

 ~Expander ()=default
 
void prepare (double sampleRate, int numChannels=2) noexcept
 Initializes the expander with a specific sample rate.
 
void prepare (const AudioSpec &spec) noexcept
 Initializes the expander using an AudioSpec struct.
 
void processBlock (AudioBufferView< T > buffer) noexcept
 Processes an audio block in place (internal detector key).
 
void processBlock (AudioBufferView< T > buffer, AudioBufferView< T > sidechain) noexcept
 Processes an audio block in place, keyed by an external sidechain.
 
void setThreshold (T dB) noexcept
 Sets the threshold in decibels.
 
void setRatio (T ratio) noexcept
 Sets the expansion ratio (e.g., 4.0 for 4:1).
 
void setHysteresis (T dB) noexcept
 Sets the hysteresis gap in decibels to prevent chattering.
 
void setRange (T dB) noexcept
 Sets the maximum gain reduction limit in decibels (<= 0).
 
void setAttack (T ms) noexcept
 Sets the attack time in milliseconds.
 
void setHold (T ms) noexcept
 Sets the hold time in milliseconds before release begins.
 
void setRelease (T ms) noexcept
 Sets the release time in milliseconds.
 
void setSidechainHPF (bool enabled, double cutoffHz=80.0) noexcept
 Enables and configures the sidechain high-pass filter.
 
void setLookahead (T ms) noexcept
 Sets the lookahead: the audio is delayed so the gain moves ahead of it. 0 (default) is latency-free.
 
T getLookahead () const noexcept
 Returns the lookahead in milliseconds.
 
int getLatency () const noexcept
 Latency in samples (the lookahead), correct right after setLookahead().
 
State getGateState () const noexcept
 
T getCurrentGainDb () const noexcept
 
void reset () noexcept
 Resets all internal DSP states to prevent clicks on playback start.
 
std::vector< uint8_t > getState () const
 Serializes the parameter state (setup/UI threads; allocates).
 
bool setState (const uint8_t *data, size_t size)
 Restores parameters from a blob (tolerant; rejects foreign ids).
 

Protected Member Functions

void cacheParams () noexcept
 
int lookaheadSamplesFor (T ms) const noexcept
 
template<bool UseHPF, bool UseSc>
void processBlockInternal (AudioBufferView< T > buffer, const AudioBufferView< T > *sidechain) noexcept
 Internal processing loop templated on HPF/sidechain to avoid branching.
 
void publishMeters () noexcept
 Publishes the metering words for cross-thread readout.
 
void updateStateMachine (T levelDb) noexcept
 
T computeGain (T levelDb) noexcept
 
void updateCoefficients () noexcept
 

Protected Attributes

double sampleRate_ = 48000.0
 
bool prepared_ = false
 
std::atomic< T > threshold_ { T(-40) }
 
std::atomic< T > ratio_ { T(4) }
 
std::atomic< T > hysteresis_ { T(4) }
 
std::atomic< T > attackMs_ { T(0.5) }
 
std::atomic< T > holdMs_ { T(50) }
 
std::atomic< T > releaseMs_ { T(100) }
 
std::atomic< T > rangeDb_ { T(-80) }
 
std::atomic< T > rangeLinear_ { T(0.0001) }
 
std::atomic< bool > scHpfEnabled_ { false }
 
std::atomic< T > scHpfFreqHz_ { T(80) }
 
std::atomic< T > scHpfCoeff_ { T(0.995) }
 
std::atomic< T > scHpfA0_ { T(0.9975) }
 
std::array< T, MAX_CHANNELS > scHpfState_ {}
 
std::array< T, MAX_CHANNELS > scHpfPrev_ {}
 
std::atomic< T > lookaheadMs_ { T(0) }
 
int cachedLookahead_ = 0
 Audio-side samples (per block).
 
int maxLookaheadSamples_ = 0
 Allocated delay (0 before prepare()).
 
int lookaheadChannels_ = 0
 Channels with a prepared delay line.
 
std::array< RingBuffer< T >, MAX_CHANNELS > lookahead_ {}
 
std::atomic< T > attackCoeff_ { T(0) }
 
std::atomic< T > releaseCoeff_ { T(0) }
 
std::atomic< T > detAttCoeff_ { T(0.01) }
 
std::atomic< T > detRelCoeff_ { T(0.001) }
 
std::atomic< int > holdSamples_ { 0 }
 
T cachedThreshold_ = T(-40)
 
T cachedRatio_ = T(4)
 
T cachedHysteresis_ = T(4)
 
T cachedRangeLinear_ = T(0.0001)
 
T cachedAttackCoeff_ = T(0)
 
T cachedReleaseCoeff_ = T(0)
 
T cachedDetAttCoeff_ = T(0.01)
 
T cachedDetRelCoeff_ = T(0.001)
 
T cachedScHpfCoeff_ = T(0.995)
 
T cachedScHpfA0_ = T(0.9975)
 
int cachedHoldSamples_ = 0
 
bool cachedScHpfEnabled_ = false
 
State state_ = State::Closed
 
T gateGain_ = T(0)
 
std::atomic< State > publishedState_ { State::Closed }
 
std::atomic< T > publishedGateGain_ { T(0) }
 
T envelope_ = T(0)
 
int holdCounter_ = 0
 

Static Protected Attributes

static constexpr int MAX_CHANNELS = 16
 
static constexpr double kMaxLookaheadMs = 10.0
 

Detailed Description

template<FloatType T>
class dspark::Expander< T >

Downward expander with ratio control, hysteresis, and sidechain.

Template Parameters
TSample type (float or double).

Definition at line 64 of file Expander.h.

Member Enumeration Documentation

◆ State

template<FloatType T>
enum class dspark::Expander::State
strong
Enumerator
Closed 
Open 
Hold 

Definition at line 69 of file Expander.h.

Constructor & Destructor Documentation

◆ ~Expander()

template<FloatType T>
dspark::Expander< T >::~Expander ( )
default

Member Function Documentation

◆ cacheParams()

template<FloatType T>
void dspark::Expander< T >::cacheParams ( )
inlineprotectednoexcept

Definition at line 342 of file Expander.h.

◆ computeGain()

template<FloatType T>
T dspark::Expander< T >::computeGain ( T  levelDb)
inlineprotectednoexcept

Definition at line 475 of file Expander.h.

◆ getCurrentGainDb()

template<FloatType T>
T dspark::Expander< T >::getCurrentGainDb ( ) const
inlinenoexcept
Returns
The current actual gain being applied, in decibels. Safe from any thread: loads a published atomic word, so it may be up to one block behind (same reason as getGateState()).

Definition at line 284 of file Expander.h.

◆ getGateState()

template<FloatType T>
State dspark::Expander< T >::getGateState ( ) const
inlinenoexcept
Returns
The current state of the expander's logic gate. Safe from any thread: loads a published atomic word, so it may be up to one block behind. It used to read the plain member the audio thread writes per sample – a data race, not merely an approximate number. (Renamed from getState(), which now follows the framework-wide preset serialization convention.)

Definition at line 276 of file Expander.h.

◆ getLatency()

template<FloatType T>
int dspark::Expander< T >::getLatency ( ) const
inlinenoexcept

Latency in samples (the lookahead), correct right after setLookahead().

Definition at line 263 of file Expander.h.

◆ getLookahead()

template<FloatType T>
T dspark::Expander< T >::getLookahead ( ) const
inlinenoexcept

Returns the lookahead in milliseconds.

Definition at line 260 of file Expander.h.

◆ getState()

template<FloatType T>
std::vector< uint8_t > dspark::Expander< T >::getState ( ) const
inline

Serializes the parameter state (setup/UI threads; allocates).

Definition at line 305 of file Expander.h.

◆ lookaheadSamplesFor()

template<FloatType T>
int dspark::Expander< T >::lookaheadSamplesFor ( T  ms) const
inlineprotectednoexcept

Lookahead in samples for a ms value (shared by cacheParams() and getLatency()).

Definition at line 360 of file Expander.h.

◆ prepare() [1/2]

template<FloatType T>
void dspark::Expander< T >::prepare ( const AudioSpec &  spec)
inlinenoexcept

Initializes the expander using an AudioSpec struct.

Parameters
specFramework audio specification object (invalid specs are ignored).

Definition at line 102 of file Expander.h.

◆ prepare() [2/2]

template<FloatType T>
void dspark::Expander< T >::prepare ( double  sampleRate,
int  numChannels = 2 
)
inlinenoexcept

Initializes the expander with a specific sample rate.

Parameters
sampleRateThe sample rate in Hz. Non-finite or non-positive rates are ignored (previous state is kept).
numChannelsChannels that receive the lookahead delay (clamped to [1, 16]); further channels are processed undelayed.

Definition at line 80 of file Expander.h.

◆ processBlock() [1/2]

template<FloatType T>
void dspark::Expander< T >::processBlock ( AudioBufferView< T >  buffer)
inlinenoexcept

Processes an audio block in place (internal detector key).

Parameters
bufferView of the audio buffer to process.

Definition at line 112 of file Expander.h.

◆ processBlock() [2/2]

template<FloatType T>
void dspark::Expander< T >::processBlock ( AudioBufferView< T >  buffer,
AudioBufferView< T >  sidechain 
)
inlinenoexcept

Processes an audio block in place, keyed by an external sidechain.

The detector (and its optional HPF) runs on the sidechain channels; the resulting gain is applied to the audio buffer. If the sidechain is empty or shorter than the audio block, the internal key is used instead.

Parameters
bufferAudio to process in place.
sidechainDetector key signal (not modified).

Definition at line 134 of file Expander.h.

◆ processBlockInternal()

template<FloatType T>
template<bool UseHPF, bool UseSc>
void dspark::Expander< T >::processBlockInternal ( AudioBufferView< T >  buffer,
const AudioBufferView< T > *  sidechain 
)
inlineprotectednoexcept

Internal processing loop templated on HPF/sidechain to avoid branching.

Template Parameters
UseHPFCompile-time flag to include HPF processing.
UseScCompile-time flag: detector keyed by the external sidechain.
Parameters
bufferView of the audio buffer (gain target).
sidechainDetector key when UseSc (guaranteed >= buffer length).

Definition at line 374 of file Expander.h.

◆ publishMeters()

template<FloatType T>
void dspark::Expander< T >::publishMeters ( )
inlineprotectednoexcept

Publishes the metering words for cross-thread readout.

Two relaxed stores per block, outside the per-sample loop: the getters used to read state_ and gateGain_ directly, which are plain words the audio thread writes every sample.

Definition at line 443 of file Expander.h.

◆ reset()

template<FloatType T>
void dspark::Expander< T >::reset ( )
inlinenoexcept

Resets all internal DSP states to prevent clicks on playback start.

Definition at line 290 of file Expander.h.

◆ setAttack()

template<FloatType T>
void dspark::Expander< T >::setAttack ( T  ms)
inlinenoexcept

Sets the attack time in milliseconds.

Definition at line 192 of file Expander.h.

◆ setHold()

template<FloatType T>
void dspark::Expander< T >::setHold ( T  ms)
inlinenoexcept

Sets the hold time in milliseconds before release begins.

Definition at line 200 of file Expander.h.

◆ setHysteresis()

template<FloatType T>
void dspark::Expander< T >::setHysteresis ( T  dB)
inlinenoexcept

Sets the hysteresis gap in decibels to prevent chattering.

Definition at line 176 of file Expander.h.

◆ setLookahead()

template<FloatType T>
void dspark::Expander< T >::setLookahead ( T  ms)
inlinenoexcept

Sets the lookahead: the audio is delayed so the gain moves ahead of it. 0 (default) is latency-free.

RT-safe publication, consumed at the next block; change it while stopped (a live change jumps the delay and may click). Report getLatency() to the host for delay compensation.

Parameters
msLookahead in milliseconds, clamped to [0, 10]. Non-finite values are ignored.

Definition at line 253 of file Expander.h.

◆ setRange()

template<FloatType T>
void dspark::Expander< T >::setRange ( T  dB)
inlinenoexcept

Sets the maximum gain reduction limit in decibels (<= 0).

Definition at line 183 of file Expander.h.

◆ setRatio()

template<FloatType T>
void dspark::Expander< T >::setRatio ( T  ratio)
inlinenoexcept

Sets the expansion ratio (e.g., 4.0 for 4:1).

Definition at line 169 of file Expander.h.

◆ setRelease()

template<FloatType T>
void dspark::Expander< T >::setRelease ( T  ms)
inlinenoexcept

Sets the release time in milliseconds.

Definition at line 216 of file Expander.h.

◆ setSidechainHPF()

template<FloatType T>
void dspark::Expander< T >::setSidechainHPF ( bool  enabled,
double  cutoffHz = 80.0 
)
inlinenoexcept

Enables and configures the sidechain high-pass filter.

Invalid cutoffs (non-finite or <= 0) keep the previous frequency and only apply the toggle; the design clamp is [1, 0.45 * sampleRate]. A negative cutoff used to flip the one-pole into an unstable growth filter, blowing up the detector and pinning the expander open.

Parameters
enabledTrue to engage the HPF.
cutoffHzCutoff frequency in Hz.

Definition at line 234 of file Expander.h.

◆ setState()

template<FloatType T>
bool dspark::Expander< T >::setState ( const uint8_t *  data,
size_t  size 
)
inline

Restores parameters from a blob (tolerant; rejects foreign ids).

Definition at line 324 of file Expander.h.

◆ setThreshold()

template<FloatType T>
void dspark::Expander< T >::setThreshold ( T  dB)
inlinenoexcept

Sets the threshold in decibels.

Definition at line 162 of file Expander.h.

◆ updateCoefficients()

template<FloatType T>
void dspark::Expander< T >::updateCoefficients ( )
inlineprotectednoexcept

Definition at line 507 of file Expander.h.

◆ updateStateMachine()

template<FloatType T>
void dspark::Expander< T >::updateStateMachine ( T  levelDb)
inlineprotectednoexcept

Definition at line 449 of file Expander.h.

Member Data Documentation

◆ attackCoeff_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::attackCoeff_ { T(0) }
protected

Definition at line 562 of file Expander.h.

◆ attackMs_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::attackMs_ { T(0.5) }
protected

Definition at line 538 of file Expander.h.

◆ cachedAttackCoeff_

template<FloatType T>
T dspark::Expander< T >::cachedAttackCoeff_ = T(0)
protected

Definition at line 573 of file Expander.h.

◆ cachedDetAttCoeff_

template<FloatType T>
T dspark::Expander< T >::cachedDetAttCoeff_ = T(0.01)
protected

Definition at line 575 of file Expander.h.

◆ cachedDetRelCoeff_

template<FloatType T>
T dspark::Expander< T >::cachedDetRelCoeff_ = T(0.001)
protected

Definition at line 576 of file Expander.h.

◆ cachedHoldSamples_

template<FloatType T>
int dspark::Expander< T >::cachedHoldSamples_ = 0
protected

Definition at line 579 of file Expander.h.

◆ cachedHysteresis_

template<FloatType T>
T dspark::Expander< T >::cachedHysteresis_ = T(4)
protected

Definition at line 571 of file Expander.h.

◆ cachedLookahead_

template<FloatType T>
int dspark::Expander< T >::cachedLookahead_ = 0
protected

Audio-side samples (per block).

Definition at line 557 of file Expander.h.

◆ cachedRangeLinear_

template<FloatType T>
T dspark::Expander< T >::cachedRangeLinear_ = T(0.0001)
protected

Definition at line 572 of file Expander.h.

◆ cachedRatio_

template<FloatType T>
T dspark::Expander< T >::cachedRatio_ = T(4)
protected

Definition at line 570 of file Expander.h.

◆ cachedReleaseCoeff_

template<FloatType T>
T dspark::Expander< T >::cachedReleaseCoeff_ = T(0)
protected

Definition at line 574 of file Expander.h.

◆ cachedScHpfA0_

template<FloatType T>
T dspark::Expander< T >::cachedScHpfA0_ = T(0.9975)
protected

Definition at line 578 of file Expander.h.

◆ cachedScHpfCoeff_

template<FloatType T>
T dspark::Expander< T >::cachedScHpfCoeff_ = T(0.995)
protected

Definition at line 577 of file Expander.h.

◆ cachedScHpfEnabled_

template<FloatType T>
bool dspark::Expander< T >::cachedScHpfEnabled_ = false
protected

Definition at line 580 of file Expander.h.

◆ cachedThreshold_

template<FloatType T>
T dspark::Expander< T >::cachedThreshold_ = T(-40)
protected

Definition at line 569 of file Expander.h.

◆ detAttCoeff_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::detAttCoeff_ { T(0.01) }
protected

Definition at line 564 of file Expander.h.

◆ detRelCoeff_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::detRelCoeff_ { T(0.001) }
protected

Definition at line 565 of file Expander.h.

◆ envelope_

template<FloatType T>
T dspark::Expander< T >::envelope_ = T(0)
protected

Definition at line 587 of file Expander.h.

◆ gateGain_

template<FloatType T>
T dspark::Expander< T >::gateGain_ = T(0)
protected

Definition at line 583 of file Expander.h.

◆ holdCounter_

template<FloatType T>
int dspark::Expander< T >::holdCounter_ = 0
protected

Definition at line 588 of file Expander.h.

◆ holdMs_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::holdMs_ { T(50) }
protected

Definition at line 539 of file Expander.h.

◆ holdSamples_

template<FloatType T>
std::atomic<int> dspark::Expander< T >::holdSamples_ { 0 }
protected

Definition at line 566 of file Expander.h.

◆ hysteresis_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::hysteresis_ { T(4) }
protected

Definition at line 537 of file Expander.h.

◆ kMaxLookaheadMs

template<FloatType T>
constexpr double dspark::Expander< T >::kMaxLookaheadMs = 10.0
staticconstexprprotected

Definition at line 555 of file Expander.h.

◆ lookahead_

template<FloatType T>
std::array<RingBuffer<T>, MAX_CHANNELS> dspark::Expander< T >::lookahead_ {}
protected

Definition at line 560 of file Expander.h.

◆ lookaheadChannels_

template<FloatType T>
int dspark::Expander< T >::lookaheadChannels_ = 0
protected

Channels with a prepared delay line.

Definition at line 559 of file Expander.h.

◆ lookaheadMs_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::lookaheadMs_ { T(0) }
protected

Definition at line 556 of file Expander.h.

◆ MAX_CHANNELS

template<FloatType T>
constexpr int dspark::Expander< T >::MAX_CHANNELS = 16
staticconstexprprotected

Definition at line 550 of file Expander.h.

◆ maxLookaheadSamples_

template<FloatType T>
int dspark::Expander< T >::maxLookaheadSamples_ = 0
protected

Allocated delay (0 before prepare()).

Definition at line 558 of file Expander.h.

◆ prepared_

template<FloatType T>
bool dspark::Expander< T >::prepared_ = false
protected

Definition at line 533 of file Expander.h.

◆ publishedGateGain_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::publishedGateGain_ { T(0) }
protected

Definition at line 586 of file Expander.h.

◆ publishedState_

template<FloatType T>
std::atomic<State> dspark::Expander< T >::publishedState_ { State::Closed }
protected

Definition at line 585 of file Expander.h.

◆ rangeDb_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::rangeDb_ { T(-80) }
protected

Definition at line 541 of file Expander.h.

◆ rangeLinear_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::rangeLinear_ { T(0.0001) }
protected

Definition at line 542 of file Expander.h.

◆ ratio_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::ratio_ { T(4) }
protected

Definition at line 536 of file Expander.h.

◆ releaseCoeff_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::releaseCoeff_ { T(0) }
protected

Definition at line 563 of file Expander.h.

◆ releaseMs_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::releaseMs_ { T(100) }
protected

Definition at line 540 of file Expander.h.

◆ sampleRate_

template<FloatType T>
double dspark::Expander< T >::sampleRate_ = 48000.0
protected

Definition at line 532 of file Expander.h.

◆ scHpfA0_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::scHpfA0_ { T(0.9975) }
protected

Definition at line 547 of file Expander.h.

◆ scHpfCoeff_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::scHpfCoeff_ { T(0.995) }
protected

Definition at line 546 of file Expander.h.

◆ scHpfEnabled_

template<FloatType T>
std::atomic<bool> dspark::Expander< T >::scHpfEnabled_ { false }
protected

Definition at line 544 of file Expander.h.

◆ scHpfFreqHz_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::scHpfFreqHz_ { T(80) }
protected

Definition at line 545 of file Expander.h.

◆ scHpfPrev_

template<FloatType T>
std::array<T, MAX_CHANNELS> dspark::Expander< T >::scHpfPrev_ {}
protected

Definition at line 552 of file Expander.h.

◆ scHpfState_

template<FloatType T>
std::array<T, MAX_CHANNELS> dspark::Expander< T >::scHpfState_ {}
protected

Definition at line 551 of file Expander.h.

◆ state_

template<FloatType T>
State dspark::Expander< T >::state_ = State::Closed
protected

Definition at line 582 of file Expander.h.

◆ threshold_

template<FloatType T>
std::atomic<T> dspark::Expander< T >::threshold_ { T(-40) }
protected

Definition at line 535 of file Expander.h.


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