|
Tabula Sonora 0.1.0
A native C++20 implementation of the Roland Sound Canvas VA synth voice
|
The static patch directory: resolves a program change and a played note to the waves that sound, entirely from ROM tables with no engine involved. More...
#include <tabulasonora/patch_directory.hpp>
Public Member Functions | |
| PatchDirectory (const TableSet &tables) | |
| Creates a directory over a loaded table set, which must outlive it. | |
| int | tone_count () const noexcept |
| Number of tone records in the melodic table. | |
| int | multisample_count () const noexcept |
| Number of multisample records. | |
| int | wave_count () const noexcept |
| Number of wave descriptors. | |
| int | alternate_count () const noexcept |
| Number of alternate-articulation records. | |
| std::optional< WaveDescriptor > | wave (int wave_number) const |
| Reads a wave descriptor, or nothing if the number is out of range. | |
| std::optional< Tone > | tone (int tone_number) const |
| Reads a tone record, or nothing if the number is out of range. | |
| int | tone_level (int tone_number) const |
| Reads a tone's master level from its header. | |
| bool | half_damper (int tone_number) const |
| Whether a tone responds to half-damper (continuous CC64). | |
| PartialParameters | partial_by_slot (int tone_number, int slot) const |
| Reads a partial block by its slot rather than its position among the present partials. | |
| std::optional< int > | multisample_wave (int multisample, int transposed_key) const |
| Selects the wave a multisample yields for a transposed key, or nothing when silent. | |
| int | zone_level (int multisample, int key, int key_center) const |
| Reads the per-key-zone level, the second attenuation in the TVA base-level chain. | |
| std::vector< MultisampleZone > | multisample_zones (int multisample) const |
| Lists a multisample's key zones in transposed-key space, low to high. | |
| std::optional< std::string > | tone_zones (int tone_number, std::vector< ToneZone > &zones) const |
| Builds the full static zone map for a tone, with key bounds converted back to MIDI notes. | |
| std::optional< int > | lut3_raw (int program, ToneMap map, int bank) const |
| The raw unsigned word the three-level program lookup yields. | |
| std::optional< int > | lut3_resolved (int program, ToneMap map, int bank) const |
| The three-level lookup with the GS capital-tone fallback applied. | |
| std::optional< AlternateEntry > | alternate (int index) const |
| Decodes an entry of the alternate-articulation table, indexed by tone# - 0x6000. | |
| std::vector< int > | program_tones (int program, ToneMap map, int bank) const |
| Resolves a program change to the tone numbers that sound for an ordinary poly note. | |
| int | alternate_tone (int program, ToneMap map, int bank) const |
| The mono/solo alternate-articulation tone for a program, or -1. | |
| int | program_to_tone (int program, ToneMap map, int bank) const |
| Resolves a program change to a single tone number, or -1 when unassigned. | |
| ResolvedTone | resolve (int tone_number, int note, int velocity) const |
| Resolves a played note against a tone. | |
| ResolvedTone | resolve_midi (int program, int note, int velocity, ToneMap map, int bank) const |
| Resolves a MIDI program change and played note in one step. | |
Static Public Attributes | |
| static constexpr int | melodic_space_end = 0x4000 |
| Highest tone number in the melodic space, exclusive. | |
| static constexpr int | drum_space_start = 0x4000 |
| First tone number in the drum space. | |
| static constexpr int | alternate_space_start = 0x6000 |
| First tone number in the alternate-articulation space. | |
| static constexpr int | indirect_only_flag = 0x8000 |
| Tone numbers at or above this are reachable only indirectly. | |
| static constexpr int | multisample_stride = 0x8C |
| Bytes per multisample record. | |
| static constexpr int | alternate_stride = 0x18 |
| Bytes per alternate-articulation record. | |
| static constexpr int | unassigned = 0xFFFF |
| Value meaning "unassigned" in the third lookup level. | |
The static patch directory: resolves a program change and a played note to the waves that sound, entirely from ROM tables with no engine involved.
The chain is (map, bank, program) -> tone# -> partial -> multisample -> key/velocity zone -> wave# -> ROM coordinates. The program lookup is three levels deep and its result carries three distinct tone spaces, which is the part most likely to be got wrong.
|
explicit |
Creates a directory over a loaded table set, which must outlive it.
|
inlinenodiscardnoexcept |
Number of tone records in the melodic table.
|
inlinenodiscardnoexcept |
Number of multisample records.
|
inlinenodiscardnoexcept |
Number of wave descriptors.
|
inlinenodiscardnoexcept |
Number of alternate-articulation records.
|
nodiscard |
Reads a wave descriptor, or nothing if the number is out of range.
|
nodiscard |
Reads a tone record, or nothing if the number is out of range.
|
nodiscard |
Reads a tone's master level from its header.
|
nodiscard |
Whether a tone responds to half-damper (continuous CC64).
Tone header byte 0x0d bit 2, copied to the part on tone select. Set on exactly 57 of the 2363 tones — the piano family — matching the hardware, where half-pedal is a piano feature. Every other tone's pedal is quantised to fully up or fully down.
|
nodiscard |
Reads a partial block by its slot rather than its position among the present partials.
Tone::partials drops empty slots, so its indices are not slot numbers. Anything correlating against the reference or a voice dump needs the slot.
|
nodiscard |
Selects the wave a multisample yields for a transposed key, or nothing when silent.
An empty bottom zone means the note is below the multisample's sampled range, and the partial is silent — it must not fall through to the neighbouring wave. The engine does statically down-extrapolate, but the resulting voice is terminated, so the audible result is silence. Slap Bass 2 below note 40 is the case that proved it.
|
nodiscard |
Reads the per-key-zone level, the second attenuation in the TVA base-level chain.
|
nodiscard |
Lists a multisample's key zones in transposed-key space, low to high.
|
nodiscard |
Builds the full static zone map for a tone, with key bounds converted back to MIDI notes.
Returns the tone's name, or nothing when the tone is undefined. This is the static map, so it applies only the key centre — not the partial's key transpose, which belongs to the played-note path in resolve.
|
nodiscard |
The raw unsigned word the three-level program lookup yields.
It must be read as unsigned. Reading it signed and bailing on the sign bit is what once made four string patches look unassigned — the 0x8000 bit marks a tone reachable only through an alternate-articulation entry, not a missing one.
|
nodiscard |
The three-level lookup with the GS capital-tone fallback applied.
A bank select picks a variation. When the selected variation has no entry for the program, a Sound Canvas does not fall silent — it sounds the capital tone at bank 0 instead. Reproducing that is what lets a file play a note on a variation bank the ROM never filled in, which is exactly what one honky-tonk part in passport.mid does: it selects bank 5, whose program-3 slot is empty, and every note would otherwise be dropped.
|
nodiscard |
Decodes an entry of the alternate-articulation table, indexed by tone# - 0x6000.
|
nodiscard |
Resolves a program change to the tone numbers that sound for an ordinary poly note.
Returned as a list because the caller walks it, but an alternate-articulation entry's two references are not layers played together: the second is a conditional articulation that only the mono/solo path can reach.
|
nodiscard |
The mono/solo alternate-articulation tone for a program, or -1.
Not rendered: reproducing it needs the part's mono-mode flag and the inter-note timing test.
|
nodiscard |
Resolves a program change to a single tone number, or -1 when unassigned.
|
nodiscard |
Resolves a played note against a tone.
|
nodiscard |
Resolves a MIDI program change and played note in one step.
|
staticconstexpr |
Highest tone number in the melodic space, exclusive.
|
staticconstexpr |
First tone number in the drum space.
|
staticconstexpr |
First tone number in the alternate-articulation space.
|
staticconstexpr |
Tone numbers at or above this are reachable only indirectly.
|
staticconstexpr |
Bytes per multisample record.
|
staticconstexpr |
Bytes per alternate-articulation record.
|
staticconstexpr |
Value meaning "unassigned" in the third lookup level.