Mixing effects#
Mix-grade effect modules for building channel strips and effect returns.
Each is a YSE::DSP::dspObject subclass, so it chains with
dspObject::link and mixes wet/dry through the inherited impact.
Routing them is a channel-level concern:
Inserts — attach a (chained) module to a channel’s pre-fader insert slot with
YSE::channel::setDSP(). Every sound on the channel is processed through the chain before the fader.Sends and returns — create a return bus with
YSE::channel::makeReturn(), attach an effect to it withsetDSP, then feed it from any channel withYSE::channel::send()/YSE::channel::setSendLevel().
Both are documented on the Channels page. The Mixing with inserts and sends tutorial walks through a complete console mixer built from these pieces.
Parametric EQ#
-
namespace YSE
Public API of libYSE — sound playback, mixing, and 3D positional audio.
Entry points:
YSE::System(lifecycle and audio device),YSE::Listener(3D origin),YSE::sound(a playable source),YSE::channel(mixing tree),YSE::reverb(positioned reverb zone),YSE::patcher(modular DSP graph),YSE::player(note sequencer). Sub-namespaces group domain-specific types:YSE::DSPfor signal processing,YSE::MIDIfor MIDI I/O,YSE::MUSICfor note / chord / motif primitives.Note
Apart from their constructors, the oscillator and
vcfclasses must only be invoked from inside a DSP callback /processbody.-
namespace DSP
Audio buffers, oscillators, filters, envelopes, and effect modules.
Build chains of
DSP::dspObjectto process a sound,DSP::dspSourceObjectto feed one. Single-channel audio data lives inDSP::bufferand its drawing / file / wavetable subclasses.-
namespace MODULES
Enums
-
enum eqBand#
The four fixed bands of the
parametricEQ.Values:
-
enumerator EQ_LOW_SHELF#
Low shelf — boosts/cuts everything below its corner.
-
enumerator EQ_PEAK_1#
Lower peaking (bell) band.
-
enumerator EQ_PEAK_2#
Upper peaking (bell) band.
-
enumerator EQ_HIGH_SHELF#
High shelf — boosts/cuts everything above its corner.
-
enumerator EQ_BAND_COUNT#
Number of bands (sentinel).
-
enumerator EQ_LOW_SHELF#
-
class parametricEQ : public YSE::DSP::dspObject#
Channel-strip parametric EQ packaged as a chainable
dspObject.Four cascaded biquad bands — a low shelf, two peaking (bell) bands, and a high shelf — each with its own frequency, gain (dB), and Q. This is the corrective/tone-shaping half of the channel strip (the compressor is the dynamics half); together they make the channel insert chain a usable mixing tool.
The bands are the standard RBJ “Audio EQ Cookbook” biquads (the same transfer functions the engine’s
biQuadprimitive implements). Each band’s five coefficients are shared across all channels and recomputed only when one of its parameters changes (or the sample rate changes), gated by a dirty flag — never per sample and never allocating. The recompute is a bounded handful of transcendentals for at most four bands and runs at the very top ofprocessonly on a block where a parameter actually moved, which keeps the audio path allocation- and lock-free.N-channel behaviour#
Every channel is filtered independently: the coefficients are shared but each channel owns its biquad delay memory (via
perChannel), so no filter state bleeds between channels (see the N-channel contract ondspObject::process). A mono buffer is the degenerate single-channel case, and the module tolerates a changing channel count between calls (the device-restart resize path is the only place per-channel state allocates).The wet/dry balance is the inherited
impact();impact(1)(the default) is the natural fully-processed insert. All state is sized on thecreate()/ channel-count-change path;processallocates nothing in steady state.Public Functions
-
parametricEQ()#
-
inline ~parametricEQ() override#
-
parametricEQ &frequency(eqBand band, Flt hz)#
Set a band’s centre/corner frequency in Hz (clamped to a sane audio range).
-
parametricEQ &gain(eqBand band, Flt db)#
Set a band’s gain in dB (clamped to +/-24 dB).
Positive boosts, negative cuts; 0 leaves the band flat (a bypass for that band).
-
parametricEQ &q(eqBand band, Flt value)#
Set a band’s Q (clamped to a sane range).
For the peaking bands Q is the bell width; for the shelves it shapes the corner steepness.
Private Members
-
aFlt parmFreq[EQ_BAND_COUNT]#
-
aFlt parmGain[EQ_BAND_COUNT]#
-
aFlt parmQ[EQ_BAND_COUNT]#
-
std::atomic<bool> dirty#
-
Coeffs coeffs[EQ_BAND_COUNT]#
-
perChannel<ChannelState> channels#
-
std::size_t blockLength#
-
struct Coeffs#
One band’s shared biquad coefficients (Direct Form I, normalised so a0 == 1).
Public Functions
-
Coeffs()#
-
Coeffs()#
-
struct BandState#
One channel’s per-band biquad delay memory (Direct Form I).
Public Functions
-
BandState()#
-
BandState()#
-
struct ChannelState#
Public Members
-
BandState bands[EQ_BAND_COUNT]#
-
BandState bands[EQ_BAND_COUNT]#
-
parametricEQ()#
-
enum eqBand#
-
namespace MODULES
-
namespace DSP
Compressor#
-
namespace YSE
Public API of libYSE — sound playback, mixing, and 3D positional audio.
Entry points:
YSE::System(lifecycle and audio device),YSE::Listener(3D origin),YSE::sound(a playable source),YSE::channel(mixing tree),YSE::reverb(positioned reverb zone),YSE::patcher(modular DSP graph),YSE::player(note sequencer). Sub-namespaces group domain-specific types:YSE::DSPfor signal processing,YSE::MIDIfor MIDI I/O,YSE::MUSICfor note / chord / motif primitives.Note
Apart from their constructors, the oscillator and
vcfclasses must only be invoked from inside a DSP callback /processbody.-
namespace DSP
Audio buffers, oscillators, filters, envelopes, and effect modules.
Build chains of
DSP::dspObjectto process a sound,DSP::dspSourceObjectto feed one. Single-channel audio data lives inDSP::bufferand its drawing / file / wavetable subclasses.-
namespace MODULES
Enums
-
enum compressorDetector#
Level-detector mode for the
compressor.Values:
-
enumerator DETECT_PEAK#
Track the instantaneous linked peak — fast, hits transients.
-
enumerator DETECT_RMS#
Track a short mean-square window — smoother, loudness-like.
-
enumerator DETECT_COUNT_#
Sentinel: number of detectors, not a valid value. Keep last.
-
enumerator DETECT_PEAK#
-
class compressor : public YSE::DSP::dspObject#
Feed-forward dynamics compressor packaged as a chainable
dspObject.The dynamics half of the channel strip (the parametric EQ is the tone half). A classic feed-forward design: a switchable peak/RMS detector drives a static compression curve (threshold + ratio), the resulting gain is smoothed by separate attack and release time constants, and a makeup gain restores level.
Stereo-linked detection (N-channel)#
The detector and the gain it computes are shared across every channel — one sidechain for the whole buffer. Each sample’s detector level is taken from all channels at once (the peak across them, or their summed mean-square for RMS), one gain-reduction value is derived, and that same gain is applied to every channel. This is what keeps a stereo (or N-channel) image stable: if the channels were each detected and compressed independently, a transient on one side would duck only that side and the stereo image would wobble/pump. Linking guarantees the relative balance between channels is preserved through gain changes.
A mono buffer is the degenerate single-channel case. The module holds no per-channel history (the gain is global), so it tolerates a changing channel count between calls for free (see the N-channel contract on
dspObject::process).The wet/dry balance is the inherited
impact();impact(1)(the default) is the fully-compressed insert.processallocates nothing in steady state.Public Functions
-
compressor()#
-
inline ~compressor() override#
-
compressor &detector(compressorDetector value)#
Select the peak or RMS level detector.
-
compressorDetector detector()#
Current detector mode.
-
compressor &threshold(Flt db)#
Set the threshold in dBFS (clamped to [-60, 0]).
Signal above the threshold is compressed; below it passes unchanged.
-
compressor &ratio(Flt value)#
Set the compression ratio (clamped to [1, 20]).
1 is no compression; 4 means 4 dB in above threshold yields 1 dB out.
-
compressor &attack(Flt ms)#
Set the attack time in milliseconds (clamped to a sane range) — how fast gain reduction engages when the signal rises.
-
compressor &release(Flt ms)#
Set the release time in milliseconds (clamped to a sane range) — how fast gain recovers when the signal falls.
-
compressor &makeup(Flt db)#
Set the makeup gain in dB (clamped to [-24, 24]) — a fixed gain applied after compression to restore level.
-
compressor()#
-
enum compressorDetector#
-
namespace MODULES
-
namespace DSP
Chorus / flanger#
-
namespace YSE
Public API of libYSE — sound playback, mixing, and 3D positional audio.
Entry points:
YSE::System(lifecycle and audio device),YSE::Listener(3D origin),YSE::sound(a playable source),YSE::channel(mixing tree),YSE::reverb(positioned reverb zone),YSE::patcher(modular DSP graph),YSE::player(note sequencer). Sub-namespaces group domain-specific types:YSE::DSPfor signal processing,YSE::MIDIfor MIDI I/O,YSE::MUSICfor note / chord / motif primitives.Note
Apart from their constructors, the oscillator and
vcfclasses must only be invoked from inside a DSP callback /processbody.-
namespace DSP
Audio buffers, oscillators, filters, envelopes, and effect modules.
Build chains of
DSP::dspObjectto process a sound,DSP::dspSourceObjectto feed one. Single-channel audio data lives inDSP::bufferand its drawing / file / wavetable subclasses.-
namespace MODULES
Enums
-
class chorus : public YSE::DSP::dspObject#
Chorus / flanger effect packaged as a chainable
dspObject.Chorus and flanger are the same modulated-delay topology with different ranges and feedback, so this is one module with a
mode()switch. An internal LFO sweeps a per-channel fractional (linearly interpolated) delay line; the sweep is click-free by construction — the delay time is a continuous signal and the read is fractional, so no read-pointer step is ever taken.MODE_CHORUSuses a longer base delay and no feedback by default (thickening / detune);MODE_FLANGERuses a short base delay and a feedback path (the classic resonant jet-sweep comb).Processes every channel of the multichannel buffer independently, each with its own delay line and LFO phase (see the N-channel contract on
dspObject::process). The LFO is shared — one sweep for the whole buffer — butspread()fans a per-channel phase offset across the channels for stereo width; atspread(0)every channel is in phase (and a mono buffer is the degenerate single-channel case).The wet/dry balance is the inherited
impact():impact(0.5)is a natural insert mix,impact(1)is fully wet. All buffers are sized on thecreate()/ channel-count-change path;processallocates nothing in steady state.Public Functions
-
chorus()#
-
inline ~chorus() override#
-
chorus &mode(chorusMode value)#
Select chorus or flanger topology.
-
chorusMode mode()#
Current mode.
-
chorus &feedback(Flt value)#
Set the feedback amount in [-0.95, 0.95].
Drives the resonant flanger comb; negative values invert the fed-back signal (the hollow “through-zero”-style comb). Typically 0 for chorus.
-
chorus()#
-
class chorus : public YSE::DSP::dspObject#
-
namespace MODULES
-
namespace DSP
Feedback delay#
-
namespace YSE
Public API of libYSE — sound playback, mixing, and 3D positional audio.
Entry points:
YSE::System(lifecycle and audio device),YSE::Listener(3D origin),YSE::sound(a playable source),YSE::channel(mixing tree),YSE::reverb(positioned reverb zone),YSE::patcher(modular DSP graph),YSE::player(note sequencer). Sub-namespaces group domain-specific types:YSE::DSPfor signal processing,YSE::MIDIfor MIDI I/O,YSE::MUSICfor note / chord / motif primitives.Note
Apart from their constructors, the oscillator and
vcfclasses must only be invoked from inside a DSP callback /processbody.-
namespace DSP
Audio buffers, oscillators, filters, envelopes, and effect modules.
Build chains of
DSP::dspObjectto process a sound,DSP::dspSourceObjectto feed one. Single-channel audio data lives inDSP::bufferand its drawing / file / wavetable subclasses.-
namespace MODULES
-
class feedbackDelay : public YSE::DSP::dspObject#
Mix-grade feedback delay packaged as a chainable
dspObject.Where
basicDelayis a three-tap feed-forward building block, this is a recirculating delay meant to sit on a channel insert or a send return: a per-channel delay line with a feedback path, a damping low-pass filter in that path (successive echoes darken, the classic tape character), and cross-feed between channel pairs for ping-pong. The wet/dry balance is the inheritedimpact()—impact(1)is echoes only (send use), a lower value keeps the dry signal (insert use).Processes every channel of the multichannel buffer independently, each with its own delay line and damping filter (see the N-channel contract on
dspObject::process). Cross-feed pairs adjacent channels (0<->1, 2<->3, …); an unpaired trailing channel feeds back only into itself.Delay-time changes are smoothed per-sample so retuning the delay does not click. All buffers are sized on the
create()/ channel-count change path;processallocates nothing in steady state.Public Functions
-
feedbackDelay()#
-
inline ~feedbackDelay() override#
-
feedbackDelay &time(Flt ms)#
Set the delay time in milliseconds (clamped to the module’s maximum).
Changes are ramped to avoid zipper noise.
-
feedbackDelay &feedback(Flt amount)#
Set the feedback amount in [0, 0.99].
Higher sustains echoes longer; the upper bound keeps the loop stable.
-
feedbackDelay &damping(Flt hz)#
Set the damping cut-off in Hz — a low-pass in the feedback path.
Lower values darken successive echoes faster.
-
feedbackDelay &crossfeed(Flt amount)#
Set the cross-feed amount in [0, 1] between channel pairs.
0 keeps channels independent; 1 is full ping-pong (each channel’s feedback comes entirely from its partner).
-
feedbackDelay()#
-
class feedbackDelay : public YSE::DSP::dspObject#
-
namespace MODULES
-
namespace DSP
Plate reverb#
A Dattorro-style plate reverb, well suited to a send/return bus.
-
namespace YSE
Public API of libYSE — sound playback, mixing, and 3D positional audio.
Entry points:
YSE::System(lifecycle and audio device),YSE::Listener(3D origin),YSE::sound(a playable source),YSE::channel(mixing tree),YSE::reverb(positioned reverb zone),YSE::patcher(modular DSP graph),YSE::player(note sequencer). Sub-namespaces group domain-specific types:YSE::DSPfor signal processing,YSE::MIDIfor MIDI I/O,YSE::MUSICfor note / chord / motif primitives.Note
Apart from their constructors, the oscillator and
vcfclasses must only be invoked from inside a DSP callback /processbody.-
namespace DSP
Audio buffers, oscillators, filters, envelopes, and effect modules.
Build chains of
DSP::dspObjectto process a sound,DSP::dspSourceObjectto feed one. Single-channel audio data lives inDSP::bufferand its drawing / file / wavetable subclasses.-
namespace MODULES
-
class plateReverb : public YSE::DSP::dspObject#
Insert/return-grade plate reverb packaged as a chainable
dspObject.Implements the classic Dattorro plate topology (“Effect Design, Part 1”, JAES 1997): a four-allpass input diffuser feeding a cross-coupled figure-eight tank of two symmetric halves, each a modulated allpass, a long delay, a damping low-pass, a second allpass, and a final delay. The stereo output is read from seven fixed taps across the tank nodes, giving the smooth, dense, slightly shimmering plate character.
This is distinct from the engine’s existing global spatial reverb (
INTERNAL::reverbDSP, welded to the listener/zone system): the plate is a plain effect you drop on a channel insert or a send return.N-channel behaviour#
The plate is a genuinely stereo device — its figure-eight tank cross-couples its two halves — so it is not a per-channel fan-out. Instead the whole multichannel buffer is downmixed to a mono tank input (the average of all input channels), the single stereo tank runs, and the two wet outputs are distributed back across the channels:
1 channel (mono): the two tank outputs are averaged into the one channel.
2 channels (stereo): left tank output to channel 0, right to channel 1.
N > 2: even channels receive the left tank output, odd channels the right (a plain, predictable spread).
Every input channel contributes to the tank and every output channel receives wet signal, and the module tolerates a changing channel count between calls (see the N-channel contract on
dspObject::process). The tank buffers are sized once from the engine sample rate, so a device restart at a new channel count allocates nothing.The wet/dry balance is the inherited
impact():impact(0.25)is a natural insert mix,impact(1)is fully wet (send-return use). All buffers are sized on thecreate()/ sample-rate-change path;processallocates nothing in steady state. Every delay, allpass, and output-tap length is derived fromSAMPLERATE(relative to the paper’s 29761 Hz reference), so the reverb sounds the same at any rate.Public Functions
-
plateReverb()#
-
inline ~plateReverb() override#
-
plateReverb &decay(Flt value)#
Set the tank decay in [0, 0.98].
Higher values recirculate the tank longer, lengthening the reverb tail (RT60).
-
plateReverb &damping(Flt hz)#
Set the damping cut-off in Hz — a low-pass inside each tank half.
Lower values shed high-frequency energy faster, so the tail darkens as it decays.
-
plateReverb &preDelay(Flt ms)#
Set the pre-delay in milliseconds (clamped to the module’s maximum).
Offsets the onset of the reverb from the dry signal.
Private Functions
-
void build()#
Private Members
-
ModAllpass apL1#
-
ModAllpass apR1#
-
std::size_t tapL[7]#
-
std::size_t tapR[7]#
-
std::size_t blockLength#
-
struct DelayLine#
Fixed-length delay line with node tapping for output reads.
-
struct Allpass#
Schroeder allpass with node tapping.
-
struct ModAllpass#
Allpass whose delay is modulated by a fractional excursion — the plate’s tank chorusing.
Read is linearly interpolated.
-
class plateReverb : public YSE::DSP::dspObject#
-
namespace MODULES
-
namespace DSP
Morphing reverb#
The engine’s zone/global reverb core as a chainable insert, with preset
interpolation exposed as a morph control input.
-
namespace YSE
Public API of libYSE — sound playback, mixing, and 3D positional audio.
Entry points:
YSE::System(lifecycle and audio device),YSE::Listener(3D origin),YSE::sound(a playable source),YSE::channel(mixing tree),YSE::reverb(positioned reverb zone),YSE::patcher(modular DSP graph),YSE::player(note sequencer). Sub-namespaces group domain-specific types:YSE::DSPfor signal processing,YSE::MIDIfor MIDI I/O,YSE::MUSICfor note / chord / motif primitives.Note
Apart from their constructors, the oscillator and
vcfclasses must only be invoked from inside a DSP callback /processbody.-
namespace DSP
Audio buffers, oscillators, filters, envelopes, and effect modules.
Build chains of
DSP::dspObjectto process a sound,DSP::dspSourceObjectto feed one. Single-channel audio data lives inDSP::bufferand its drawing / file / wavetable subclasses.-
namespace MODULES
-
class morphingReverb : public YSE::DSP::dspObject#
A reverb whose preset interpolation is a control input.
This is the engine’s zone/global reverb core (
INTERNAL::reverbDSP) packaged as an ordinary chainabledspObject, with the parameter blend generalized into a morph control (issue #326). Two endpoint parameter sets — slot A and slot B, each a namedREVERB_PRESETor a customREVERB::presetValues— are linearly interpolated bymorph(t): 0 is pure A (“cathedral”), 1 is pure B (“closet”), anything in between is a genuine hybrid space.Drivers#
morphis deliberately driver-agnostic: a UI slider, a patcher ramp, a live-coded expression, MIDI — anything running on a control thread can call it at control rate. Writes are plain atomic stores (allocation-free, wait-free); the audio thread picks the value up on the next block and moves every underlying parameter through the reverb core’s faders (~1000-sample ramps), so sweeps and jumps are click-free.Listener-zone proximity — the classic game-audio driver — is not wired into this module: it remains the default driver of the same reverb core through the legacy
REVERB::Managerpath, computed exactly as before. Same core, different drivers.Placement#
The module is a plain
dspObject: attach it withYSE::channel::setDSP/YSE::sound::setDSP, on any channel or on a return bus (r.makeReturn("verb").setDSP(&morphVerb)) — it is not welded to the global manager attach. The wet/dry balance rides the morphed presets themselves (each preset carriesdry/wet), so the inheritedimpact()is not applied; for send/return use, give both slots custompresetValueswithdry = 0, wet = 1. Unlike the legacy zone path (which applies historical makeup gain), the module mapsdry = 1to unity — morphing fully toREVERB_OFFis a true bypass — andwet = 1to the reverb tank at its computed level.Trajectory note (design record, issue #326)#
With zone-bound return buses (
docs/design/send_return_buses.md§12b in the repository), a reverb zone can instead be a return bus tied to a region of space, with proximity modulating the send levels into it — distinct spaces crossfading as real wet signals. The two tools coexist: parameter morph (this module) is one space transforming; zone returns are spaces crossfading. This module is kept an ordinary insert precisely so it can be dropped on such a return when zone returns land; the in-placeREVERB::Managerpath stays legacy-bound (bug fixes yes, new features no).N-channel behaviour#
Per-channel reverb state is sized to
buffer.size()on the firstprocesscall and re-sized only when the channel count changes (the device-restart path — the only place thedspObjectcontract allows allocation). Steady-stateprocessallocates nothing.Public Functions
-
inline ~morphingReverb() override#
-
morphingReverb &presetA(REVERB_PRESET value)#
Set morph endpoint A from a named preset.
-
morphingReverb &presetA(const REVERB::presetValues &value)#
Set morph endpoint A from a custom parameter set.
Fields are stored individually-atomically; the faders smooth the (rare) block that observes a partly-updated slot.
-
morphingReverb &presetB(REVERB_PRESET value)#
Set morph endpoint B from a named preset.
-
morphingReverb &presetB(const REVERB::presetValues &value)#
Set morph endpoint B from a custom parameter set.
-
morphingReverb &morph(Flt value)#
The morph control input: 0 = pure A, 1 = pure B, clamped to [0, 1].
Callable from any control thread at control rate — allocation-free, click-free (see class docs).
-
struct slot#
-
inline ~morphingReverb() override#
-
class morphingReverb : public YSE::DSP::dspObject#
-
namespace MODULES
-
namespace DSP
Underwater#
The classic underwater treatment — a depth-driven low-pass blended toward a position-neutral mixdown — re-expressed as an ordinary insert.
-
namespace YSE
Public API of libYSE — sound playback, mixing, and 3D positional audio.
Entry points:
YSE::System(lifecycle and audio device),YSE::Listener(3D origin),YSE::sound(a playable source),YSE::channel(mixing tree),YSE::reverb(positioned reverb zone),YSE::patcher(modular DSP graph),YSE::player(note sequencer). Sub-namespaces group domain-specific types:YSE::DSPfor signal processing,YSE::MIDIfor MIDI I/O,YSE::MUSICfor note / chord / motif primitives.Note
Apart from their constructors, the oscillator and
vcfclasses must only be invoked from inside a DSP callback /processbody.-
namespace DSP
Audio buffers, oscillators, filters, envelopes, and effect modules.
Build chains of
DSP::dspObjectto process a sound,DSP::dspSourceObjectto feed one. Single-channel audio data lives inDSP::bufferand its drawing / file / wavetable subclasses.-
namespace MODULES
-
class underWater : public YSE::DSP::dspObject#
The underwater treatment as an ordinary chainable
dspObject.This is the DSP half of the engine’s classic underwater effect (issue #327), extracted from the hard-wired slot it used to occupy in the channel path. Sound underwater is more position neutral — the speed of sound is much higher, so the ear cannot tell what direction it comes from. The module therefore mixes all channels down to a position-neutral average, darkens it with a depth-driven low-pass, and crossfades the original image toward that neutral version as the listener sinks.
The depth control#
depthis the distance below the water surface, in world distance units (meters):depth <= 1: transparent — the buffer passes through untouched.1 < depth < 5: the positioned signal is progressively replaced by the low-passed neutral mix (linear crossfade over the range).depth >= 5: position information is discarded entirely; every channel carries the same low-passed mix.
The low-pass cutoff falls with depth as
MidiToFreq(140 - 5 * depth)and is floored at 200 Hz — the same curve the legacy channel-path effect has always applied.Drivers#
depthis deliberately driver-agnostic: writes are plain atomic stores (allocation-free, wait-free), callable from any control thread at control rate — a game tick, a patcher ramp, a live-coded expression. The classic spatial binding — listener depth below the water plane, plus the matchingREVERB_UNDERWATERzone — remains the default driver throughSystem().underWaterFX()/System().setUnderWaterDepth(), which drive the engine’s own instance of this module (seeINTERNAL::underWaterEffect). Same module, different drivers — the idiom established bymorphingReverb(issue #326).Placement#
Attach it with
YSE::channel::setDSP/YSE::sound::setDSP, on any channel, return bus, or sound — it is no longer welded to the channel implementation. Note one deliberate difference from the legacy hard-wired slot: an insert runs pre-fader, before the global manager reverb, whereas the old slot ran after it. When the module and the (legacy-bound) global reverb sit on the same channel the reverb tail is no longer low-passed; place the module after a reverb insert (dspObject::link) or on a return to author that ordering explicitly. The wet/dry balance is inherent indepth, so the inheritedimpact()slider is not applied.RT discipline#
Steady-state
processallocates nothing. The mixdown scratch is (re)sized only when the block length changes — the device-restart path, the one place thedspObjectcontract permits allocation. (The legacy implementation also carried the previous block’s mixdown into the next one at 1/N gain — an accumulate-without-clear that diverges on mono buffers. This module zeroes the scratch every block instead.)Public Functions
-
inline ~underWater() override#
-
underWater &depth(Flt value)#
The depth control input, in distance units below the water surface.
Negative values clamp to 0 (above water). Callable from any control thread at control rate — allocation-free, wait-free (see class docs for the response curve).
-
class underWater : public YSE::DSP::dspObject#
-
namespace MODULES
-
namespace DSP