Channels#
-
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 CHANNEL#
-
namespace CHANNEL#
-
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.Functions
-
channel &ChannelMaster()#
Root of the channel tree.
Every channel ultimately routes here. < This macro is added to all public class declarations.
-
channel &ChannelFX()#
Pre-built channel for short sound effects.
< This macro is added to all public class declarations.
-
channel &ChannelMusic()#
Pre-built channel for playlists and music tracks.
< This macro is added to all public class declarations.
-
channel &ChannelAmbient()#
Pre-built channel for environmental and ambient sounds.
< This macro is added to all public class declarations.
-
class channel#
A node in the channel tree — a group of sounds that mix together.
Channels work like the channel groups on a mixing console: every sound is attached to a channel, and channels can themselves be attached to a parent channel, forming a tree rooted at
MainMix. Each channel is rendered on its own DSP thread, so spreading sounds across multiple channels can help scale across cores.Several pre-built channels are created for you and exposed through free functions:
ChannelMaster()— the root of the tree.ChannelFX()— short sound effects.ChannelMusic()— playlists and music.ChannelAmbient()— environmental loops.ChannelVoice()— dialogue.ChannelGui()— UI feedback.
Use them as-is or as roots for your own subtrees.
See also
Output peak metering
Lock-free getters returning the latest per-block peak of this channel’s output buffers.
Refresh granularity is one audio block (so polling faster than the audio block rate yields no new data).
Prereads the peak measured at the end ofdsp()(after inserts and reverb, before the channel volume is applied);Postreads the peak measured immediately afteradjustVolume()— what listeners hear. Per-output overloads take an index in[0, getNumOutputs()); out-of-range indices return 0. dB getters convert the linear value on the fly with a -120 dB floor for silence. Returns 0 on an invalid channel.-
int getNumOutputs()#
Number of output channels currently allocated (matches the open device’s layout).
-
float getPeakLinearPre()#
Combined (max-over-outputs) pre-volume peak as a linear sample value.
-
float getPeakLinearPost()#
Combined (max-over-outputs) post-volume peak as a linear sample value.
-
float getPeakDbPre()#
Combined pre-volume peak in dBFS (
-120floor for silence).
-
float getPeakDbPost()#
Combined post-volume peak in dBFS (
-120floor for silence).
-
float getPeakLinearPre(int outputIdx)#
Per-output pre-volume peak as a linear sample value.
-
float getPeakLinearPost(int outputIdx)#
Per-output post-volume peak as a linear sample value.
-
float getPeakDbPre(int outputIdx)#
Per-output pre-volume peak in dBFS (
-120floor for silence).
-
float getPeakDbPost(int outputIdx)#
Per-output post-volume peak in dBFS (
-120floor for silence).
Public Functions
-
channel &create(const char *name, channel &parent, int sendSlots = 4)#
Create the channel and attach it to the tree.
Must be called before any other method. The pre-built channels (
ChannelFXetc.) call this internally.- Parameters:
name – Channel name, used for log output.
parent – Existing channel to attach to. Use
ChannelMaster()for a top-level channel.sendSlots – Number of aux-send slots to allocate for this channel (issue #165). Sized once off the audio thread and never resized. Default 4; raise it for a channel that fans out to many return buses.
-
channel &makeReturn(const char *name = "return", int sendSlots = 4)#
Create this channel as a send/return bus.
A return bus is an ordinary channel (it keeps
setDSPinserts,attachReverb,setVolume, and metering) with two differences: it is excluded from the normal mix tree, and other channels route scaled copies of their signal into it viasend. Its output folds intoMainMixafter the source tree, so a single reverb or delay on a return can serve many channels (the classic aux-send topology). A return may itselfsendinto another return (an acyclic delay→reverb chain, for example); cycles are rejected at wiring time.Call this instead of
create— not after it. The engine takes no ownership of any effect attached withsetDSP.- Parameters:
name – Channel name, used for log output.
sendSlots – Number of aux-send slots on the return itself (for return→return routing). Default 4.
- Returns:
*thisfor fluent chaining (e.g.r.makeReturn("verb").setDSP(&plate)).
-
bool isReturn() const#
Whether this channel is a send/return bus (issue #165).
-
channel &send(int slot, channel &returnBus, float level, bool preFader = false)#
Route a scaled copy of this channel into a return bus.
Wires send slot
slot(in[0, sendSlots)) toreturnBusat the givenlevel. The send is post-fader by default (it follows this channel’s own volume); passpreFader = truefor a cue-style send independent of the fader. Re-callingsendon the same slot re-points it. The level ramps in, so wiring a live send never clicks.Illegal wirings are rejected on the calling (control) thread and logged, never reaching the audio thread: a target that is not a return, a self-send, or a return→return edge that would close a cycle.
- Parameters:
slot – Send-slot index in
[0, sendSlots).returnBus – A channel created with
makeReturn.level – Send gain (typically
[0, 1]).preFader – Tap before this channel’s fader when true (default false).
- Returns:
*thisfor fluent chaining.
-
channel &setSendLevel(int slot, float level)#
Set a send slot’s level, ramped and click-free.
Safe to call every control tick — send levels are designed as modulation targets (a patcher outlet, a live-coded expression, a proximity rule), so continuous writes fuse into the per-block ramp without zippering.
- Parameters:
slot – Send-slot index in
[0, sendSlots).level – New send gain.
- Returns:
*thisfor fluent chaining.
-
float getSendLevel(int slot) const#
Current target level of send slot
slot, or 0 if unset/invalid.
-
channel &name(const std::string &n)#
Assign a bus-addressable name to this channel.
Names the channel on the global named bus (issue #123, epic #119) so live coders can drive it by string address. Once named
music, the channel subscribes tochannel.music.volume→float(also acceptsint), callingsetVolume().This is independent of the log name passed to
create. Anonymous channels (the default) are not addressable; passing""clears the name and removes the subscription. Two channels cannot share a name — the secondname()is rejected and logged, the first wins. The bus is only live betweenSystem::init()andSystem::close().- Parameters:
n – The name, or
""to make the channel anonymous again.- Returns:
*thisfor fluent chaining.
-
float getVolume()#
Current channel volume.
-
channel &moveTo(channel &parent)#
Re-parent this channel.
Detaches from the current parent and links to
parent. All sounds and subchannels move along.
-
channel &attachReverb()#
Move the global reverb effect onto this channel.
libYSE runs a single reverb instance for performance reasons. By default it sits on
MainMixand affects every channel; call this to restrict reverb to a subtree.
-
channel &setDSP(DSP::dspObject *value)#
Attach a pre-fader insert DSP effect to this channel.
Mirrors
YSE::sound::setDSPbut at the channel level: the effect processes this channel’s summed output (all its sounds and subchannels mixed together) in place, pre-fader — before reverb and before the channel volume is applied. This is the DAW “insert” slot; put a delay onChannelMusic()or a compressor onChannelVoice().The effect must honour the N-channel
dspObject::processcontract (process every channel of the buffer). Chain several effects withdspObject::link. Passnullptrto detach. The engine takes no ownership — thedspObjectmust outlive the channel or be detached first.- Parameters:
value – The effect chain head, or
nullptrto detach.- Returns:
*thisfor fluent chaining.
-
channel &setVirtual(bool value)#
Allow or disallow sounds on this channel to be virtualised.
Virtualised sounds keep their playback state but stop consuming DSP budget — the engine uses this to stay within
System().maxSounds(...).
-
bool getVirtual()#
Whether virtualisation is permitted on this channel.
-
bool isValid()#
Whether this channel has a live implementation.
-
inline const char *getName()#
Channel name (the value passed to
create).
-
channel()#
Construct an empty channel.
Channels are only usable after
createhas been called.
-
~channel()#
Private Members
-
Flt volume#
-
Bool allowVirtual#
-
std::string logName#
-
std::string busName#
-
std::uint64_t busVolumeHandle = {0}#
-
bool busOwner = {false}#
-
bool _isReturn = {false}#
-
int _sendSlots = {0}#
-
std::vector<SendMirror> _sends#
Friends
- friend class YSE::system
-
struct SendMirror#
-
channel &ChannelMaster()#