DSPark 1.6.1
Header-only audio DSP framework in pure C++20 — zero dependencies
Loading...
Searching...
No Matches
dspark::Reverb< T > Class Template Reference

Convolution reverb with IR loading, dry/wet, and pre-delay. More...

#include <Reverb.h>

Collaboration diagram for dspark::Reverb< T >:

Classes

struct  ConvolverBank
 

Public Member Functions

 ~Reverb ()=default
 
void prepare (const AudioSpec &spec)
 Prepares the reverb for processing.
 
void processBlock (AudioBufferView< T > buffer) noexcept
 Processes audio through the reverb.
 
void reset () noexcept
 Resets the DSP state (convolver tails, pre-delay, mixer). RT-Safe.
 
bool loadIR (const char *wavFilePath)
 Loads an impulse response from a WAV file.
 
void setMix (T dryWet) noexcept
 Sets the dry/wet mix.
 
bool loadIR (const T *data, int length, double irSampleRate)
 Loads an IR from raw sample data.
 
void setPreDelay (T ms) noexcept
 Sets the pre-delay time in milliseconds.
 
void setDecayScale (T scale)
 Scales the decay time (T60) of the loaded IR.
 
void setStretch (T ratio)
 Stretches the loaded IR in time (tape-speed style).
 
getDecayScale () const noexcept
 Returns the current IR decay scale.
 
getStretch () const noexcept
 Returns the current IR stretch ratio.
 
Convolver< T > & getConvolver (int channel=0)
 Direct access to a channel's Convolver (GUI thread only).
 
DryWetMixer< T > & getMixer ()
 Direct access to the DryWetMixer.
 
bool isLoaded () const noexcept
 Returns true if an IR has been loaded and applied.
 
getMix () const noexcept
 Returns the current mix value.
 
getPreDelay () const noexcept
 Returns the current pre-delay in ms.
 
int getLatency () const noexcept
 Returns the convolution latency in samples.
 
std::vector< uint8_t > getState () const
 Serializes the parameter state. The impulse response itself is content (load it with loadIR), not a preset parameter.
 
bool setState (const uint8_t *data, size_t size)
 Restores parameters from a blob (tolerant; rejects foreign ids).
 

Protected Member Functions

void updatePreDelay () noexcept
 
void applyIR ()
 
std::vector< T > shapeDecay (const T *ir, int len, double factor) const
 Returns a decay-scaled copy of one IR channel (see setDecayScale).
 
std::shared_ptr< ConvolverBankloadBank () const noexcept
 
void storeBank (std::shared_ptr< ConvolverBank > next) noexcept
 

Protected Attributes

AudioSpec spec_ {}
 
int fftBlockSize_ = 0
 Convolver partition size = engine latency (set in prepare()).
 
std::atomic< T > mix_ { T(0.3) }
 
std::atomic< T > preDelayMs_ { T(0) }
 
std::atomic< int > preDelaySamples_ { 0 }
 
std::atomic< T > decayScale_ { T(1) }
 
std::atomic< T > stretch_ { T(1) }
 
std::vector< T > irStorage_
 
int irLength_ = 0
 
int irChannels_ = 0
 
double irSampleRate_ = 0
 
std::atomic_flag bankLock_ = ATOMIC_FLAG_INIT
 
std::shared_ptr< ConvolverBankbankPtr_
 
std::vector< RingBuffer< T > > preDelayBuffers_
 
DryWetMixer< T > mixer_
 
Convolver< T > fallbackConvolver_
 Inert engine for getConvolver() with no bank.
 

Detailed Description

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

Convolution reverb with IR loading, dry/wet, and pre-delay.

Internally manages one Convolver per channel. The IR is automatically resampled if its sample rate differs from the processing sample rate.

Template Parameters
TSample type (float or double).

Definition at line 92 of file Reverb.h.

Constructor & Destructor Documentation

◆ ~Reverb()

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

Member Function Documentation

◆ applyIR()

template<FloatType T>
void dspark::Reverb< T >::applyIR ( )
inlineprotected

Definition at line 497 of file Reverb.h.

◆ getConvolver()

template<FloatType T>
Convolver< T > & dspark::Reverb< T >::getConvolver ( int  channel = 0)
inline

Direct access to a channel's Convolver (GUI thread only).

NOTE: the live convolver bank is published atomically and may be replaced by a future loadIR() call. This accessor returns a reference into the currently-published bank and MUST NOT be used from the audio thread. Before an IR is loaded (or with an out-of-range channel) it returns an inert fallback engine instead of dereferencing a null bank.

Parameters
channelChannel index (clamped into the bank's range).

Definition at line 404 of file Reverb.h.

◆ getDecayScale()

template<FloatType T>
T dspark::Reverb< T >::getDecayScale ( ) const
inlinenoexcept

Returns the current IR decay scale.

Definition at line 386 of file Reverb.h.

◆ getLatency()

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

Returns the convolution latency in samples.

0 without an IR (the audio passes through untouched); the convolver's partition latency once an IR is loaded. The dry path is internally delayed by the same amount, so this is the whole effect's latency. Hosts must re-read it after loading an IR.

Definition at line 437 of file Reverb.h.

◆ getMix()

template<FloatType T>
T dspark::Reverb< T >::getMix ( ) const
inlinenoexcept

Returns the current mix value.

Definition at line 424 of file Reverb.h.

◆ getMixer()

template<FloatType T>
DryWetMixer< T > & dspark::Reverb< T >::getMixer ( )
inline

Direct access to the DryWetMixer.

Definition at line 415 of file Reverb.h.

◆ getPreDelay()

template<FloatType T>
T dspark::Reverb< T >::getPreDelay ( ) const
inlinenoexcept

Returns the current pre-delay in ms.

Definition at line 427 of file Reverb.h.

◆ getState()

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

Serializes the parameter state. The impulse response itself is content (load it with loadIR), not a preset parameter.

Definition at line 447 of file Reverb.h.

◆ getStretch()

template<FloatType T>
T dspark::Reverb< T >::getStretch ( ) const
inlinenoexcept

Returns the current IR stretch ratio.

Definition at line 389 of file Reverb.h.

◆ isLoaded()

template<FloatType T>
bool dspark::Reverb< T >::isLoaded ( ) const
inlinenoexcept

Returns true if an IR has been loaded and applied.

Definition at line 418 of file Reverb.h.

◆ loadBank()

template<FloatType T>
std::shared_ptr< ConvolverBank > dspark::Reverb< T >::loadBank ( ) const
inlineprotectednoexcept

Definition at line 708 of file Reverb.h.

◆ loadIR() [1/2]

template<FloatType T>
bool dspark::Reverb< T >::loadIR ( const char *  wavFilePath)
inline

Loads an impulse response from a WAV file.

The IR is automatically resampled if the WAV sample rate differs from the processing sample rate. Multi-channel IRs are supported (one convolver per channel); mono IRs are duplicated across all channels. Empty or degenerate files are rejected.

Parameters
wavFilePathPath to the WAV file.
Returns
True if the IR was loaded successfully.

Definition at line 233 of file Reverb.h.

◆ loadIR() [2/2]

template<FloatType T>
bool dspark::Reverb< T >::loadIR ( const T *  data,
int  length,
double  irSampleRate 
)
inline

Loads an IR from raw sample data.

Parameters
dataPointer to mono IR samples.
lengthNumber of samples (must be > 0).
irSampleRateSample rate of the IR data (must be > 0 and finite).
Returns
True if the IR was accepted (invalid arguments are rejected).

Definition at line 295 of file Reverb.h.

◆ prepare()

template<FloatType T>
void dspark::Reverb< T >::prepare ( const AudioSpec spec)
inline

Prepares the reverb for processing.

Allocates internal buffers, sets up the dry/wet mixer (including the dry-path compensation for the convolution latency) and the pre-delay. If an IR was loaded before prepare(), it will be re-applied. An invalid spec (non-positive or non-finite fields) is a no-op that keeps the previous state.

Parameters
specAudio environment (sample rate, block size, channels).

Definition at line 110 of file Reverb.h.

◆ processBlock()

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

Processes audio through the reverb.

Flow: pushDry -> pre-delay -> convolve -> mixWet (with the dry delayed by the convolution latency so both paths stay aligned). Without a loaded IR the audio passes through untouched (and getLatency() is 0). Channels beyond the prepared count pass through untouched.

Thread-safety: the ConvolverBank is published atomically by loadIR/applyIR. We snapshot the current bank once at the top of the block into a local shared_ptr, so even if the GUI thread publishes a replacement mid-block, the audio thread keeps using a stable bank until the block completes. No resize of a live vector, no torn reads.

Parameters
bufferAudio data to process in-place.

Definition at line 161 of file Reverb.h.

◆ reset()

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

Resets the DSP state (convolver tails, pre-delay, mixer). RT-Safe.

The loaded IR stays loaded: resetting used to drop the convolver bank entirely, silently unloading the reverb (a host reset on stop/start left it as a dry passthrough until the next loadIR()).

Definition at line 207 of file Reverb.h.

◆ setDecayScale()

template<FloatType T>
void dspark::Reverb< T >::setDecayScale ( scale)
inline

Scales the decay time (T60) of the loaded IR.

The IR's own decay rate is estimated from its Schroeder backward energy curve (T20 fit between -5 dB and -25 dB), then an exponential envelope is applied from the direct-sound peak onward so the shaped IR decays at scale times the original T60. The direct sound and early part are preserved.

Values below 1 shorten the tail AND trim the IR where its energy falls below -100 dB, so the convolution gets proportionally cheaper (about half the CPU at 0.5 on a typical exponential hall). Values above 1 lengthen the tail; this also lifts whatever noise floor the recording has, so moderate boosts (up to 2x) are the useful range. IRs without a broadly exponential tail (gated/reversed effects) are left unshaped.

Setup/UI threads only: rebuilds the convolver bank (allocates) and publishes it atomically, exactly like loadIR(). Not meant for per-block automation. Non-finite values are ignored.

Parameters
scaleT60 multiplier, clamped to [0.25, 2]. 1 = as loaded.

Definition at line 353 of file Reverb.h.

◆ setMix()

template<FloatType T>
void dspark::Reverb< T >::setMix ( dryWet)
inlinenoexcept

Sets the dry/wet mix.

Parameters
dryWet0.0 = fully dry (no reverb), 1.0 = fully wet. Non-finite values are ignored.

Definition at line 279 of file Reverb.h.

◆ setPreDelay()

template<FloatType T>
void dspark::Reverb< T >::setPreDelay ( ms)
inlinenoexcept

Sets the pre-delay time in milliseconds.

Pre-delay adds a gap before the reverb tail starts, creating a sense of room size. Typical values: 0-50 ms. Applied immediately (a live change may click); intended as a setup control, not for automation.

Parameters
msPre-delay in milliseconds, clamped to [0, 500] (the ring buffer allocation). Non-finite values are ignored.

Definition at line 323 of file Reverb.h.

◆ setState()

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

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

Definition at line 458 of file Reverb.h.

◆ setStretch()

template<FloatType T>
void dspark::Reverb< T >::setStretch ( ratio)
inline

Stretches the loaded IR in time (tape-speed style).

The IR is resampled by the given ratio: 2.0 doubles its length (larger, darker space, roughly an octave down in coloration), 0.5 halves it (smaller, brighter). Decay scale and stretch compose: effective T60 is approximately original * decayScale * stretch.

Setup/UI threads only: rebuilds the convolver bank (allocates) and publishes it atomically, exactly like loadIR(). Non-finite values are ignored.

Parameters
ratioTime-stretch ratio, clamped to [0.5, 2]. 1 = as loaded.

Definition at line 376 of file Reverb.h.

◆ shapeDecay()

template<FloatType T>
std::vector< T > dspark::Reverb< T >::shapeDecay ( const T *  ir,
int  len,
double  factor 
) const
inlineprotected

Returns a decay-scaled copy of one IR channel (see setDecayScale).

Estimates the source decay rate from the Schroeder backward-energy curve (T20 fit: -5 dB to -25 dB crossings of the EDC), then applies exp(-k * (n - peak)) so the result decays at factor times the original T60. The direct sound (up to the peak) is untouched. Returns an empty vector when the IR has no measurable exponential decay (too short, or gated); the caller then uses the original data.

Definition at line 581 of file Reverb.h.

◆ storeBank()

template<FloatType T>
void dspark::Reverb< T >::storeBank ( std::shared_ptr< ConvolverBank next)
inlineprotectednoexcept

Definition at line 715 of file Reverb.h.

◆ updatePreDelay()

template<FloatType T>
void dspark::Reverb< T >::updatePreDelay ( )
inlineprotectednoexcept

Definition at line 484 of file Reverb.h.

Member Data Documentation

◆ bankLock_

template<FloatType T>
std::atomic_flag dspark::Reverb< T >::bankLock_ = ATOMIC_FLAG_INIT
mutableprotected

Definition at line 723 of file Reverb.h.

◆ bankPtr_

template<FloatType T>
std::shared_ptr<ConvolverBank> dspark::Reverb< T >::bankPtr_
protected

Definition at line 724 of file Reverb.h.

◆ decayScale_

template<FloatType T>
std::atomic<T> dspark::Reverb< T >::decayScale_ { T(1) }
protected

Definition at line 683 of file Reverb.h.

◆ fallbackConvolver_

template<FloatType T>
Convolver<T> dspark::Reverb< T >::fallbackConvolver_
protected

Inert engine for getConvolver() with no bank.

Definition at line 727 of file Reverb.h.

◆ fftBlockSize_

template<FloatType T>
int dspark::Reverb< T >::fftBlockSize_ = 0
protected

Convolver partition size = engine latency (set in prepare()).

Definition at line 679 of file Reverb.h.

◆ irChannels_

template<FloatType T>
int dspark::Reverb< T >::irChannels_ = 0
protected

Definition at line 689 of file Reverb.h.

◆ irLength_

template<FloatType T>
int dspark::Reverb< T >::irLength_ = 0
protected

Definition at line 688 of file Reverb.h.

◆ irSampleRate_

template<FloatType T>
double dspark::Reverb< T >::irSampleRate_ = 0
protected

Definition at line 690 of file Reverb.h.

◆ irStorage_

template<FloatType T>
std::vector<T> dspark::Reverb< T >::irStorage_
protected

Definition at line 687 of file Reverb.h.

◆ mix_

template<FloatType T>
std::atomic<T> dspark::Reverb< T >::mix_ { T(0.3) }
protected

Definition at line 680 of file Reverb.h.

◆ mixer_

template<FloatType T>
DryWetMixer<T> dspark::Reverb< T >::mixer_
protected

Definition at line 726 of file Reverb.h.

◆ preDelayBuffers_

template<FloatType T>
std::vector<RingBuffer<T> > dspark::Reverb< T >::preDelayBuffers_
protected

Definition at line 725 of file Reverb.h.

◆ preDelayMs_

template<FloatType T>
std::atomic<T> dspark::Reverb< T >::preDelayMs_ { T(0) }
protected

Definition at line 681 of file Reverb.h.

◆ preDelaySamples_

template<FloatType T>
std::atomic<int> dspark::Reverb< T >::preDelaySamples_ { 0 }
protected

Definition at line 682 of file Reverb.h.

◆ spec_

template<FloatType T>
AudioSpec dspark::Reverb< T >::spec_ {}
protected

Definition at line 678 of file Reverb.h.

◆ stretch_

template<FloatType T>
std::atomic<T> dspark::Reverb< T >::stretch_ { T(1) }
protected

Definition at line 684 of file Reverb.h.


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