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::DSP for signal processing, YSE::MIDI for MIDI I/O, YSE::MUSIC for note / chord / motif primitives.

Note

Apart from their constructors, the oscillator and vcf classes must only be invoked from inside a DSP callback / process body.

namespace CHANNEL#

Enums

enum MESSAGE#

Values:

enumerator VOLUME#
enumerator MOVE#
enumerator VIRTUAL#
enumerator ATTACH_REVERB#
enumerator ATTACH_DSP#
enumerator ADD_SEND#
enumerator SEND_LEVEL#
enumerator REMOVE_SEND#
enumerator SET_GENERATION#
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::DSP for signal processing, YSE::MIDI for MIDI I/O, YSE::MUSIC for note / chord / motif primitives.

Note

Apart from their constructors, the oscillator and vcf classes must only be invoked from inside a DSP callback / process body.

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.

channel &ChannelVoice()#

Pre-built channel for dialogue and voice-over.

< This macro is added to all public class declarations.

channel &ChannelGui()#

Pre-built channel for user-interface 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:

Use them as-is or as roots for your own subtrees.

See also

YSE::sound

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). Pre reads the peak measured at the end of dsp() (after inserts and reverb, before the channel volume is applied); Post reads the peak measured immediately after adjustVolume() — 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 (-120 floor for silence).

float getPeakDbPost()#

Combined post-volume peak in dBFS (-120 floor 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 (-120 floor for silence).

float getPeakDbPost(int outputIdx)#

Per-output post-volume peak in dBFS (-120 floor 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 (ChannelFX etc.) 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 setDSP inserts, 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 via send. Its output folds into MainMix after the source tree, so a single reverb or delay on a return can serve many channels (the classic aux-send topology). A return may itself send into 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 with setDSP.

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:

*this for 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)) to returnBus at the given level. The send is post-fader by default (it follows this channel’s own volume); pass preFader = true for a cue-style send independent of the fader. Re-calling send on 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:

*this for 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:

*this for fluent chaining.

channel &clearSend(int slot)#

Detach send slot slot (fully disconnects it from its return).

float getSendLevel(int slot) const#

Current target level of send slot slot, or 0 if unset/invalid.

channel &setVolume(float value)#

Set the channel volume in the range [0.0, 1.0].

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 to channel.music.volumefloat (also accepts int), calling setVolume().

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 second name() is rejected and logged, the first wins. The bus is only live between System::init() and System::close().

Parameters:

n – The name, or "" to make the channel anonymous again.

Returns:

*this for 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 MainMix and 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::setDSP but 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 on ChannelMusic() or a compressor on ChannelVoice().

The effect must honour the N-channel dspObject::process contract (process every channel of the buffer). Chain several effects with dspObject::link. Pass nullptr to detach. The engine takes no ownership — the dspObject must outlive the channel or be detached first.

Parameters:

value – The effect chain head, or nullptr to detach.

Returns:

*this for fluent chaining.

DSP::dspObject *getDSP()#

The currently attached insert effect, or nullptr if none.

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 create has been called.

~channel()#

Private Functions

void createGlobal()#
void registerOnBus()#
void unregisterFromBus()#

Private Members

Flt volume#
Bool allowVirtual#
std::string logName#
CHANNEL::implementationObject *pimpl#
DSP::dspObject *_dsp = {nullptr}#
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#

Public Members

channel *target = {nullptr}#
CHANNEL::implementationObject *targetImpl{nullptr}#
float level = {0.f}#
bool preFader = {false}#
bool graphEdge = {false}#