|
| | Reverb ()=default |
| |
| | ~Reverb () noexcept |
| |
| | Reverb (const Reverb &)=delete |
| |
| Reverb & | operator= (const Reverb &)=delete |
| |
| | Reverb (Reverb &&)=delete |
| |
| Reverb & | operator= (Reverb &&)=delete |
| |
| 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.
|
| |
| bool | loadIR (AudioBufferView< const T > ir, double irSampleRate) |
| | Loads a multi-channel IR from memory.
|
| |
| 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).
|
| |
| T | getDecayScale () const noexcept |
| | Returns the current IR decay scale.
|
| |
| T | 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 (processing thread).
|
| |
| bool | isLoaded () const noexcept |
| | Returns true if an IR has been loaded and applied.
|
| |
| T | getMix () const noexcept |
| | Returns the current mix value.
|
| |
| T | 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).
|
| |
|
| int | calculatePreDelaySamples (const AudioSpec &spec) const noexcept |
| |
| void | updatePreDelay () noexcept |
| |
| bool | commitImpulseResponse (std::vector< T > nextStorage, int nextLength, int nextChannels, double nextSampleRate) |
| |
| std::unique_ptr< ConvolverBank > | buildBank (const std::vector< T > &source, int sourceLength, int sourceChannels, double sourceSampleRate, const AudioSpec &processingSpec, int fftBlock, T decayScale, T stretchRatio) const |
| |
| std::vector< T > | shapeDecay (const T *ir, int len, double factor) const |
| | Returns a decay-scaled copy of one IR channel (see setDecayScale).
|
| |
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
-
| T | Sample type (float or double). |
Definition at line 589 of file Reverb.h.
Direct access to a channel's Convolver (GUI thread only).
Lifetime of the returned reference: valid until YOUR next call to getConvolver() on this object, or until the object is destroyed. It is NOT invalidated by a concurrent loadIR() / setDecayScale() / setStretch() / setState() / prepare(), because this accessor pins the exact slot and generation it hands a reference into; the publication those calls make simply is not what you are looking at any more, so what you hold is the bank as of your call, kept alive for you.
Getting that wrong is what this accessor used to do: it took a local snapshot of the bank, returned a reference into it, and let the snapshot die at the closing brace – so the next publication freed the storage under the caller's reference (a heap-use-after-free reachable single-threaded through this documented usage). Ownership at the moment of the call is not the same question as how long the result lives.
Still GUI thread only, and still not for the audio thread: one caller owns the pin, and the Convolver it hands back is not synchronized with the audio thread's use of the live bank. 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
-
| channel | Channel index (clamped into the bank's range). |
Definition at line 1027 of file Reverb.h.
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, plus - for an IR converted from another rate or stretched - the kernel's ringing ahead of the IR's first sample wherever the IR's own leading silence cannot hold it (the direct sound of a unit impulse at 44.1 kHz played at 48 kHz lands exactly here; an IR with a few milliseconds of pre-delay adds nothing). 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 or changing the stretch.
Definition at line 1073 of file Reverb.h.
Loads a multi-channel IR from memory.
The in-memory counterpart of loadIR(path), for a host that keeps its impulse responses in its own asset store rather than as files: the same resampling, the same one-convolver-per-channel layout (a one-channel view is duplicated across all channels) and the same atomic publication. The samples are copied, so the view need not outlive the call.
- Parameters
-
| ir | One IR channel per view channel, all the same length. |
| irSampleRate | Sample rate of the IR data (must be > 0 and finite). |
- Returns
- True if the IR was accepted (an empty view or an invalid rate is rejected).
Definition at line 881 of file Reverb.h.
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: a fixed four-slot ownership handoff adopts at most one complete bank at the block boundary. The audio path performs one atomic exchange and uses a raw pointer whose slot cannot be reclaimed until a later boundary release-retires it.
- Parameters
-
| buffer | Audio data to process in-place. |
Definition at line 704 of file Reverb.h.
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 769 of file Reverb.h.
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
-
| scale | T60 multiplier, clamped to [0.25, 2]. 1 = as loaded. |
Definition at line 940 of file Reverb.h.
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
-
| ratio | Time-stretch ratio, clamped to [0.5, 2]. 1 = as loaded. |
Definition at line 973 of file Reverb.h.
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 1336 of file Reverb.h.