Tabula Sonora 0.1.0
A native C++20 implementation of the Roland Sound Canvas VA synth voice
Loading...
Searching...
No Matches
ts::DrumKeyOverrides Class Reference

Per-part coarse-pitch and panpot overrides, set by NRPN. More...

#include <tabulasonora/sequence.hpp>

Public Member Functions

 DrumKeyOverrides ()
bool is_empty () const noexcept
 Whether any override has been recorded.
void reset () noexcept
 Clears every override.
void set_pitch (int note, int entry) noexcept
 Records a coarse-pitch override for one key; centre is no change.
void set_pan (int note, int entry) noexcept
 Records a panpot override for one key, used directly as the key's pan.
void set_play_key (int note, int entry) noexcept
 Records an absolute play-key override for one key, from drum-setup SysEx 41 m1 kk.
void set_level (int note, int entry) noexcept
 Records a level override for one key, replacing the kit's level plane entry.
void set_group (int note, int entry) noexcept
 Records an assign-group override for one key.
void set_reverb (int note, int entry) noexcept
 Records per-key send depths, from NRPN 1D/1E/1F or drum-setup SysEx.
void set_chorus (int note, int entry) noexcept
void set_delay (int note, int entry) noexcept
void set_rx_note_off (int note, bool on) noexcept
 Records the per-key receive switches, from drum-setup SysEx 41 m7 kk / 41 m8 kk.
void set_rx_note_on (int note, bool on) noexcept
int pitch_offset (int note) const noexcept
 The coarse-pitch offset held for a key, in kit-plane steps.
std::optional< int > pan (int note) const noexcept
 The panpot held for a key, or nothing when the key follows its kit record.
std::optional< int > play_key (int note) const noexcept
 The absolute play-key override for a key, or nothing when it follows the kit.
std::optional< int > level (int note) const noexcept
 The level override for a key, or nothing when it follows the kit.
std::optional< int > group (int note) const noexcept
 The assign-group override for a key, or nothing when it follows the kit.
std::optional< bool > rx_note_off (int note) const noexcept
 The receive-switch overrides for a key, or nothing when it follows the kit.
std::optional< bool > rx_note_on (int note) const noexcept
std::optional< int > pan_for_hit (int note, EngineNoise &noise) const
 Resolves the panpot for one strike, spreading a randomly-panned key.

Static Public Member Functions

static DrumKey apply (DrumKey key, int pitch_offset, std::optional< int > pan) noexcept
 Layers a latched pair of overrides over a key read from the kit record.

Static Public Attributes

static constexpr int centre = 0x40
 Data-entry value meaning no change.
static constexpr int random_pan = 0
 The panpot entry that means "random", which only the GS SysEx panpot can write.

Detailed Description

Per-part coarse-pitch and panpot overrides, set by NRPN.

Drum keys only: a melodic part never reaches these.

Constructor & Destructor Documentation

◆ DrumKeyOverrides()

ts::DrumKeyOverrides::DrumKeyOverrides ( )
inline

Member Function Documentation

◆ is_empty()

bool ts::DrumKeyOverrides::is_empty ( ) const
inlinenodiscardnoexcept

Whether any override has been recorded.

◆ reset()

void ts::DrumKeyOverrides::reset ( )
noexcept

Clears every override.

◆ set_pitch()

void ts::DrumKeyOverrides::set_pitch ( int note,
int entry )
noexcept

Records a coarse-pitch override for one key; centre is no change.

◆ set_pan()

void ts::DrumKeyOverrides::set_pan ( int note,
int entry )
noexcept

Records a panpot override for one key, used directly as the key's pan.

◆ set_play_key()

void ts::DrumKeyOverrides::set_play_key ( int note,
int entry )
noexcept

Records an absolute play-key override for one key, from drum-setup SysEx 41 m1 kk.

Unlike the pitch NRPN this is not relative: the value replaces the kit's coarse-pitch plane entry outright.

◆ set_level()

void ts::DrumKeyOverrides::set_level ( int note,
int entry )
noexcept

Records a level override for one key, replacing the kit's level plane entry.

◆ set_group()

void ts::DrumKeyOverrides::set_group ( int note,
int entry )
noexcept

Records an assign-group override for one key.

◆ set_reverb()

void ts::DrumKeyOverrides::set_reverb ( int note,
int entry )
noexcept

Records per-key send depths, from NRPN 1D/1E/1F or drum-setup SysEx.

Latched but not yet consumed: the mixer runs one send bus per part, so scaling a single key's contribution needs per-voice send gains it does not have yet.

◆ set_chorus()

void ts::DrumKeyOverrides::set_chorus ( int note,
int entry )
noexcept

◆ set_delay()

void ts::DrumKeyOverrides::set_delay ( int note,
int entry )
noexcept

◆ set_rx_note_off()

void ts::DrumKeyOverrides::set_rx_note_off ( int note,
bool on )
noexcept

Records the per-key receive switches, from drum-setup SysEx 41 m7 kk / 41 m8 kk.

The module keeps both in one per-key flag byte (0x480, bits 0 and 4) that the kit record seeds and these writes rewrite; there is no NRPN route – nrpn_apply leaves 0x19 and 0x1B empty.

◆ set_rx_note_on()

void ts::DrumKeyOverrides::set_rx_note_on ( int note,
bool on )
noexcept

◆ pitch_offset()

int ts::DrumKeyOverrides::pitch_offset ( int note) const
nodiscardnoexcept

The coarse-pitch offset held for a key, in kit-plane steps.

A step's worth in pitch is the tone's own key-follow: a semitone on a 100%-follow tone, half of one at 50%. The famous "SC-55 mode doubles the NRPN's range" is exactly this – the SC-55 kits use 100%-follow tones where the later standard kits use 50%.

◆ pan()

std::optional< int > ts::DrumKeyOverrides::pan ( int note) const
nodiscardnoexcept

The panpot held for a key, or nothing when the key follows its kit record.

◆ play_key()

std::optional< int > ts::DrumKeyOverrides::play_key ( int note) const
nodiscardnoexcept

The absolute play-key override for a key, or nothing when it follows the kit.

◆ level()

std::optional< int > ts::DrumKeyOverrides::level ( int note) const
nodiscardnoexcept

The level override for a key, or nothing when it follows the kit.

◆ group()

std::optional< int > ts::DrumKeyOverrides::group ( int note) const
nodiscardnoexcept

The assign-group override for a key, or nothing when it follows the kit.

◆ rx_note_off()

std::optional< bool > ts::DrumKeyOverrides::rx_note_off ( int note) const
nodiscardnoexcept

The receive-switch overrides for a key, or nothing when it follows the kit.

◆ rx_note_on()

std::optional< bool > ts::DrumKeyOverrides::rx_note_on ( int note) const
nodiscardnoexcept

◆ pan_for_hit()

std::optional< int > ts::DrumKeyOverrides::pan_for_hit ( int note,
EngineNoise & noise ) const
nodiscard

Resolves the panpot for one strike, spreading a randomly-panned key.

The spread is the engine's own: a draw from the shared generator, reduced to a pan position by its top seven bits. What still cannot match is the sequence under polyphony, since that depends on how many voices consume draws and in what order.

Consumes a draw for a randomly-panned key, so call it once per strike.

◆ apply()

DrumKey ts::DrumKeyOverrides::apply ( DrumKey key,
int pitch_offset,
std::optional< int > pan )
staticnodiscardnoexcept

Layers a latched pair of overrides over a key read from the kit record.

The offset lands on the plane unscaled and the sum clamps to 0-0x7F, which is the engine's own plane write (nrpn_apply case 0x18, confirmed by live plane reads: entry +12 moves the stored plane 60 to 72 on every map). The "absolute rate floor" measured but never located in earlier work is this clamp's bottom: keys with different kit planes floor at different offsets, which is what made it look like a rate limit rather than a pitch one.

Member Data Documentation

◆ centre

int ts::DrumKeyOverrides::centre = 0x40
staticconstexpr

Data-entry value meaning no change.

◆ random_pan

int ts::DrumKeyOverrides::random_pan = 0
staticconstexpr

The panpot entry that means "random", which only the GS SysEx panpot can write.


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