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

The GS part modify offsets, as the synthesis chains consume them. More...

#include <tabulasonora/part_modifiers.hpp>

Public Member Functions

constexpr bool is_neutral () const noexcept
 True when nothing here would change a result.
constexpr int attack_bias () const noexcept
 The envelope rate bias for segments 0 and 1, in rate-curve index steps.
constexpr int decay_bias () const noexcept
 The envelope rate bias for segments 2 and 3.
constexpr int release_bias () const noexcept
 The envelope rate bias for the release segment.
constexpr int cutoff_offset () const noexcept
 The cutoff offset, in the 15-bit cutoff units the filter chain sums.

Public Attributes

int vibrato_rate = neutral
 CC#76 / NRPN 01 08 / 40 1x 30part+0x3e4.
int vibrato_depth = neutral
 CC#77 / NRPN 01 09 / 40 1x 31part+0x3e5.
int vibrato_delay = neutral
 CC#78 / NRPN 01 0A / 40 1x 37part+0x3eb.
int tvf_cutoff = neutral
 CC#74 / NRPN 01 20 / 40 1x 32part+0x3e6.
int env_attack = neutral
 CC#73 / NRPN 01 63 / 40 1x 34part+0x3e8.
int env_decay = neutral
 CC#75 / NRPN 01 64 / 40 1x 35part+0x3e9.
int env_release = neutral
 CC#72 / NRPN 01 66 / 40 1x 36part+0x3ea.

Static Public Attributes

static constexpr int neutral = 0x40
 The neutral value every one of these centres on.

Detailed Description

The GS part modify offsets, as the synthesis chains consume them.

Every one of these is a 0x40-centred byte that three writers share — the sound controllers (CC#71-78), the NRPNs (01 08-01 66) and the part SysEx (40 1x 30-37) all land on the same byte in the engine, at part+0x3e4 through part+0x3eb.

They are carried as a value rather than read off the part because the chains that consume them build voices, not parts: TvaChain and TvfChain are pure functions of a partial and a note, and the offline renderer drives them with no Part in sight. A default-constructed set is neutral and must leave every result bit-identical to having no modifiers at all, which is what makes it safe to pass one everywhere.

The engine pairs each of these with a second byte at part+0x453-0x45a, filled from the tone table only when the part is on a user bank (MSB 0x40 or 0x41) and reset to 0x40 otherwise. A standard MIDI file never programs a user tone, so that sibling is neutral throughout and the combined law reduces to the offsets here. Modelling it belongs with user tones, not here.

Member Function Documentation

◆ is_neutral()

bool ts::PartModifiers::is_neutral ( ) const
inlinenodiscardconstexprnoexcept

True when nothing here would change a result.

◆ attack_bias()

int ts::PartModifiers::attack_bias ( ) const
inlinenodiscardconstexprnoexcept

The envelope rate bias for segments 0 and 1, in rate-curve index steps.

The engine sums the modify byte with its user-tone sibling and doubles the pair's distance from centre — (0x457 + 0x3e8) * 2 - 0x100 — so one step of the controller moves the rate curve two entries. It biases the index, not the duration, which is why a segment can be driven clean off either end of the curve.

◆ decay_bias()

int ts::PartModifiers::decay_bias ( ) const
inlinenodiscardconstexprnoexcept

The envelope rate bias for segments 2 and 3.

◆ release_bias()

int ts::PartModifiers::release_bias ( ) const
inlinenodiscardconstexprnoexcept

The envelope rate bias for the release segment.

◆ cutoff_offset()

int ts::PartModifiers::cutoff_offset ( ) const
inlinenodiscardconstexprnoexcept

The cutoff offset, in the 15-bit cutoff units the filter chain sums.

A controller step is a whole 0x100 here, which is why cutoff sweeps over CC#74 are coarse on this module: 128 steps span the entire cutoff range.

Member Data Documentation

◆ vibrato_rate

int ts::PartModifiers::vibrato_rate = neutral

CC#76 / NRPN 01 08 / 40 1x 30part+0x3e4.

◆ vibrato_depth

int ts::PartModifiers::vibrato_depth = neutral

CC#77 / NRPN 01 09 / 40 1x 31part+0x3e5.

◆ vibrato_delay

int ts::PartModifiers::vibrato_delay = neutral

CC#78 / NRPN 01 0A / 40 1x 37part+0x3eb.

◆ tvf_cutoff

int ts::PartModifiers::tvf_cutoff = neutral

CC#74 / NRPN 01 20 / 40 1x 32part+0x3e6.

◆ env_attack

int ts::PartModifiers::env_attack = neutral

CC#73 / NRPN 01 63 / 40 1x 34part+0x3e8.

◆ env_decay

int ts::PartModifiers::env_decay = neutral

CC#75 / NRPN 01 64 / 40 1x 35part+0x3e9.

◆ env_release

int ts::PartModifiers::env_release = neutral

CC#72 / NRPN 01 66 / 40 1x 36part+0x3ea.

◆ neutral

int ts::PartModifiers::neutral = 0x40
staticconstexpr

The neutral value every one of these centres on.


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