|
Tabula Sonora 0.1.0
A native C++20 implementation of the Roland Sound Canvas VA synth voice
|
The static tables the engine needs, loaded from SCCore.dll or from a directory of extracted .bin slices. More...
#include <tabulasonora/table_set.hpp>
Classes | |
| struct | names |
| Cache file names for every table in the manifest. More... | |
Public Member Functions | |
| TableSet (TableSet &&) noexcept | |
| TableSet & | operator= (TableSet &&) noexcept |
| TableSet (const TableSet &)=delete | |
| TableSet & | operator= (const TableSet &)=delete |
| ~TableSet () | |
| const TableManifest & | manifest () const noexcept |
| The offset map these tables were loaded through. | |
| std::span< const std::uint8_t > | raw (std::string_view name) const |
| Returns the untouched bytes of one table; see names. | |
| std::span< const std::uint16_t > | amp_curve_hi () const noexcept |
| g_amp_curve_hi — 256 entries, high half of the log-to-linear amplitude lookup. | |
| std::span< const std::uint16_t > | amp_curve_lo () const noexcept |
| g_amp_curve_lo — 256 entries, low half of the log-to-linear amplitude lookup. | |
| std::span< const std::uint8_t > | tvf_env_depth () const noexcept |
| g_tvf_env_depth — TVF env-depth conversion region, addressed by VA-relative offset. | |
| std::span< const std::uint32_t > | filter_type_coef () const noexcept |
| g_filter_type_coef — 16 entries; filter TYPE byte to tap/coefficient word. | |
| std::span< const std::uint16_t > | level_curve () const noexcept |
| g_level_curve — 128 entries; envelope stage byte to 16-bit log attenuation. | |
| std::span< const std::uint8_t > | pitch_bias () const noexcept |
| g_pitch_bias — 128 entries; pitch-envelope bias sub-table. | |
| std::span< const std::uint16_t > | pitch_depth_vs () const noexcept |
| g_pitch_depth_vs — 64 entries; pitch-envelope depth versus velocity. | |
| std::span< const std::uint8_t > | pitch_env () const noexcept |
| g_pitch_env — pitch-envelope conversion region, addressed by VA-relative offset. | |
| std::span< const std::uint16_t > | env_rate_out () const noexcept |
| g_env_rate_out — 512 entries; the rate-scale output curve, exactly 2^((i−0x80)/32) in 8.8. | |
| std::span< const std::int16_t > | reso_curve () const noexcept |
| g_reso_curve — 64 entries; resonance curve for partial block byte 0x4a. | |
| std::span< const std::uint8_t > | env_scale_curve () const noexcept |
| g_env_scale_curve — 256 entries; envelope rate/level scale, 0x40-neutral. | |
| std::span< const std::uint16_t > | rate_curve () const noexcept |
| g_rate_curve — 128 entries; rate byte to segment time. | |
| std::span< const std::uint8_t > | vel_curve () const noexcept |
| g_vel_curve — 256 entries; velocity response curve. | |
| std::span< const std::uint8_t > | vel_sens () const noexcept |
| g_vel_sens — the velocity response curves, 16 rows of 0x80 bytes. | |
| std::span< const std::uint8_t > | vel_xfade () const noexcept |
| g_vel_xfade — the multisample velocity-crossfade curve, 16 rows of 0x80 bytes. | |
| std::span< const std::uint16_t > | env_shape () const noexcept |
| g_env_shape — the fast-approach segment shape. | |
| std::span< const std::uint16_t > | env_start_phase () const noexcept |
| g_env_startphase — 128 entries; per-segment initial phase seed. | |
| std::span< const float > | interp_coef () const noexcept |
| g_interp_coef_table — the 4-tap FIR resample kernel as 128 phases of 4 taps, flattened to 512 floats. | |
| std::span< const std::int16_t > | kf_pitch () const noexcept |
| g_kf_pitch — 8 rows of 128; pitch key-follow, indexed row * 0x80 + key. | |
| std::span< const std::uint8_t > | kf_pitch_rate0 () const noexcept |
| g_kf_pitchrate0 — 128×128; pitch-envelope rate key-follow for the segments. | |
| std::span< const std::uint8_t > | kf_pitch_rate1 () const noexcept |
| g_kf_pitchrate1 — 128×128; pitch-envelope rate key-follow for the release. | |
| std::span< const std::uint8_t > | kf_tva_level () const noexcept |
| g_kf_tvalevel — 128×128; TVA base-level key-follow. | |
| std::span< const std::uint8_t > | kf_tva_level2 () const noexcept |
| g_kf_tvalevel2 — 128×128; TVA level key-follow, second term. | |
| std::span< const std::uint8_t > | kf_tva_rate0 () const noexcept |
| g_kf_tvarate0 — 128×128; TVA envelope rate key-follow for the segments. | |
| std::span< const std::uint8_t > | kf_tva_rate1 () const noexcept |
| g_kf_tvarate1 — 128×128; TVA envelope rate key-follow for the release. | |
| std::span< const std::int16_t > | kf_tvf_env () const noexcept |
| g_kf_tvfenv — TVF env-depth key-follow. | |
| std::span< const std::uint8_t > | kf_tvf_rate () const noexcept |
| g_kf_tvfrate — 128×128; TVF envelope rate key-follow. | |
| std::span< const std::uint8_t > | layered () const noexcept |
| g_layered_table — 50 alternate-articulation records of 0x18 bytes. | |
| std::span< const std::uint16_t > | lfo_cents () const noexcept |
| g_lfo_cents_tbl — 128 entries; LFO pitch-depth byte to milli-semitones. | |
| std::span< const std::uint16_t > | lfo_delay () const noexcept |
| g_lfo_delay_tbl — 128 entries; LFO1 delay byte to delay ticks. | |
| std::span< const std::uint16_t > | lfo_rate () const noexcept |
| g_lfo_rate_tbl — 128 entries; LFO1 rate byte to 16-bit phase increment. | |
| std::span< const std::uint16_t > | portamento_step () const noexcept |
| g_porta_step — 128 entries; portamento glide in milli-semitones per control tick, indexed by the CC#5 time byte. | |
| std::span< const std::uint8_t > | lfo_wave () const noexcept |
| g_lfo_wave — the half-sine LFO waveform used by selector 0. | |
| std::span< const std::int16_t > | lfo_wave_bank () const noexcept |
| g_lfo_wavebank — LFO wavetables 8..0x1f, 24 rows of 0x81 entries. | |
| std::span< const std::uint8_t > | lfo_wave_map () const noexcept |
| g_lfo_wavemap — 32 entries; waveform selector nibble to table index. | |
| std::span< const std::uint8_t > | dir_lut1 () const noexcept |
| g_dir_lut1 — 128 entries; tone-map to LUT2 row. | |
| std::span< const std::uint8_t > | dir_lut2 () const noexcept |
| g_dir_lut2 — bank to LUT3 row. | |
| std::span< const std::uint16_t > | dir_lut3 () const noexcept |
| g_dir_lut3 — 32768 entries; program to tone number. | |
| std::span< const std::uint8_t > | multisample () const noexcept |
| g_multisample_table — key/velocity zone to wave number, stride 0x8c. | |
| std::span< const std::uint8_t > | pan () const noexcept |
| g_pan_tbl — 128 entries. | |
| std::span< const std::uint8_t > | ramp_divider () const noexcept |
| g_ramp_divider — the anti-zipper zero-order-hold masks [0, 7, 31, 127]. | |
| std::span< const std::int32_t > | ramp_exp () const noexcept |
| g_ramp_exp_tbl — 257 entries of 2^17 · 2^(i/256), the SVF f-coefficient decode. | |
| std::span< const std::uint8_t > | ramp_flagword () const noexcept |
| g_ramp_flagword — per-destination ramp-divider selector bits. | |
| std::span< const float > | svf_f_ceil () const noexcept |
| g_svf_f_ceil — 1024 entries; the stability ceiling the filter's f is clamped to, indexed by the damping coefficient's raw integer shifted right by 8. | |
| std::span< const std::uint8_t > | tone () const noexcept |
| g_tone_table — tone records of stride 0x100: 0x24 header plus partial blocks of 0x6e. | |
| std::span< const std::uint16_t > | tvf_cutoff_ceil () const noexcept |
| g_tvf_cutoff_ceil — 128 entries; cutoff ceiling by resonance byte. | |
| std::span< const std::uint16_t > | tvf_q_lp () const noexcept |
| g_tvf_q_lp — 256 entries; Q trim for filter type 0 at neutral resonance. | |
| std::span< const std::uint16_t > | tvf_q_t6 () const noexcept |
| g_tvf_q_t6 — 256 entries; Q trim for filter type 6. | |
| std::span< const std::uint16_t > | tvf_cutoff_warp () const noexcept |
| g_tvf_cutoff_warp — 129 entries; the cutoff warp applied at stage C. | |
| std::span< const std::uint8_t > | wavedesc () const noexcept |
| g_wavedesc_table — wave descriptors of stride 0x16: ROM coordinates, root key, loop. | |
Static Public Member Functions | |
| static TableSet | from_rom (const RomImage &rom) |
| Loads every table by slicing the DLL at its manifest offset. | |
| static TableSet | from_cache_directory (const std::filesystem::path &directory, const TableManifest *manifest=nullptr) |
| Loads every table from a directory of extracted .bin slices. | |
The static tables the engine needs, loaded from SCCore.dll or from a directory of extracted .bin slices.
Accessor names follow the project's symbol labels (g_amp_curve_hi becomes amp_curve_hi) so the code greps cleanly against the reverse-engineering notes. Those labels are behavioural hypotheses, not Roland's own names.
Element counts are derived from each table's byte length, not from the manifest's shape string – several shapes record a byte count where an element count would be expected (curve_level_2a00.bin is 256 bytes holding 128 uint16_t entries, yet its shape reads 256).
The set owns its bytes. Byte-typed tables are spans into that storage and typed tables are converted copies, so every view here stays valid for the lifetime of the set and none of them depends on the RomImage outliving it.
|
noexcept |
|
delete |
| ts::TableSet::~TableSet | ( | ) |
Loads every table by slicing the DLL at its manifest offset.
|
staticnodiscard |
Loads every table from a directory of extracted .bin slices.
Throws std::runtime_error if a cache file is missing or has the wrong length. A length mismatch means the cache was extracted against an older manifest and must be regenerated; reading it anyway would silently misalign every table after it.
|
inlinenodiscardnoexcept |
The offset map these tables were loaded through.
|
nodiscard |
Returns the untouched bytes of one table; see names.
Throws std::out_of_range if no such table was loaded.
|
inlinenodiscardnoexcept |
g_amp_curve_hi — 256 entries, high half of the log-to-linear amplitude lookup.
|
inlinenodiscardnoexcept |
g_amp_curve_lo — 256 entries, low half of the log-to-linear amplitude lookup.
|
inlinenodiscardnoexcept |
g_tvf_env_depth — TVF env-depth conversion region, addressed by VA-relative offset.
|
inlinenodiscardnoexcept |
g_filter_type_coef — 16 entries; filter TYPE byte to tap/coefficient word.
|
inlinenodiscardnoexcept |
g_level_curve — 128 entries; envelope stage byte to 16-bit log attenuation.
|
inlinenodiscardnoexcept |
g_pitch_bias — 128 entries; pitch-envelope bias sub-table.
|
inlinenodiscardnoexcept |
g_pitch_depth_vs — 64 entries; pitch-envelope depth versus velocity.
|
inlinenodiscardnoexcept |
g_pitch_env — pitch-envelope conversion region, addressed by VA-relative offset.
|
inlinenodiscardnoexcept |
g_env_rate_out — 512 entries; the rate-scale output curve, exactly 2^((i−0x80)/32) in 8.8.
|
inlinenodiscardnoexcept |
g_reso_curve — 64 entries; resonance curve for partial block byte 0x4a.
|
inlinenodiscardnoexcept |
g_env_scale_curve — 256 entries; envelope rate/level scale, 0x40-neutral.
|
inlinenodiscardnoexcept |
g_rate_curve — 128 entries; rate byte to segment time.
|
inlinenodiscardnoexcept |
g_vel_curve — 256 entries; velocity response curve.
|
inlinenodiscardnoexcept |
g_vel_sens — the velocity response curves, 16 rows of 0x80 bytes.
Row 0 is the identity; the rest bend velocity progressively toward the top of the range. Like VelXfade the manifest records this as u16, but the engine indexes it byte-wise as [(selector & 0xf) * 0x80 + velocity].
|
inlinenodiscardnoexcept |
g_vel_xfade — the multisample velocity-crossfade curve, 16 rows of 0x80 bytes.
The manifest records this as u16, but the engine indexes it byte-wise as [(selector & 0xf) * 0x80 + position].
|
inlinenodiscardnoexcept |
g_env_shape — the fast-approach segment shape.
258 entries, and the 257th is not slack: env_ramp_segment interpolates from the entry it lands on to the next one, so a phase of zero reads entry 256. Must be interpolated, not looked up bare.
|
inlinenodiscardnoexcept |
g_env_startphase — 128 entries; per-segment initial phase seed.
|
inlinenodiscardnoexcept |
g_interp_coef_table — the 4-tap FIR resample kernel as 128 phases of 4 taps, flattened to 512 floats.
Index a phase as phase * 4 + tap. Every phase sums to 1.0.
|
inlinenodiscardnoexcept |
g_kf_pitch — 8 rows of 128; pitch key-follow, indexed row * 0x80 + key.
|
inlinenodiscardnoexcept |
g_kf_pitchrate0 — 128×128; pitch-envelope rate key-follow for the segments.
|
inlinenodiscardnoexcept |
g_kf_pitchrate1 — 128×128; pitch-envelope rate key-follow for the release.
|
inlinenodiscardnoexcept |
g_kf_tvalevel — 128×128; TVA base-level key-follow.
|
inlinenodiscardnoexcept |
g_kf_tvalevel2 — 128×128; TVA level key-follow, second term.
|
inlinenodiscardnoexcept |
g_kf_tvarate0 — 128×128; TVA envelope rate key-follow for the segments.
|
inlinenodiscardnoexcept |
g_kf_tvarate1 — 128×128; TVA envelope rate key-follow for the release.
|
inlinenodiscardnoexcept |
g_kf_tvfenv — TVF env-depth key-follow.
Only rows 0–15 are used; the cache is an over-read whose used prefix matches the DLL.
|
inlinenodiscardnoexcept |
g_kf_tvfrate — 128×128; TVF envelope rate key-follow.
Row 0 doubles as g_kf_tvfrate2, the release table, which covers 98% of partials.
|
inlinenodiscardnoexcept |
g_layered_table — 50 alternate-articulation records of 0x18 bytes.
|
inlinenodiscardnoexcept |
g_lfo_cents_tbl — 128 entries; LFO pitch-depth byte to milli-semitones.
|
inlinenodiscardnoexcept |
g_lfo_delay_tbl — 128 entries; LFO1 delay byte to delay ticks.
|
inlinenodiscardnoexcept |
g_lfo_rate_tbl — 128 entries; LFO1 rate byte to 16-bit phase increment.
|
inlinenodiscardnoexcept |
g_porta_step — 128 entries; portamento glide in milli-semitones per control tick, indexed by the CC#5 time byte.
The glide is linear in pitch, not in frequency: 0 is instant, 64 crosses an octave in about half a second, and 127 takes two minutes over the same octave.
|
inlinenodiscardnoexcept |
g_lfo_wave — the half-sine LFO waveform used by selector 0.
|
inlinenodiscardnoexcept |
g_lfo_wavebank — LFO wavetables 8..0x1f, 24 rows of 0x81 entries.
|
inlinenodiscardnoexcept |
g_lfo_wavemap — 32 entries; waveform selector nibble to table index.
|
inlinenodiscardnoexcept |
g_dir_lut1 — 128 entries; tone-map to LUT2 row.
|
inlinenodiscardnoexcept |
g_dir_lut2 — bank to LUT3 row.
|
inlinenodiscardnoexcept |
g_dir_lut3 — 32768 entries; program to tone number.
|
inlinenodiscardnoexcept |
g_multisample_table — key/velocity zone to wave number, stride 0x8c.
|
inlinenodiscardnoexcept |
g_pan_tbl — 128 entries.
Left gain is T[127 − p] / 127, right is T[p − 1] / 127; centre is 75/127, neither constant-power nor linear.
|
inlinenodiscardnoexcept |
g_ramp_divider — the anti-zipper zero-order-hold masks [0, 7, 31, 127].
|
inlinenodiscardnoexcept |
g_ramp_exp_tbl — 257 entries of 2^17 · 2^(i/256), the SVF f-coefficient decode.
|
inlinenodiscardnoexcept |
g_ramp_flagword — per-destination ramp-divider selector bits.
|
inlinenodiscardnoexcept |
g_svf_f_ceil — 1024 entries; the stability ceiling the filter's f is clamped to, indexed by the damping coefficient's raw integer shifted right by 8.
The curve is Chamberlin's own bound, sqrt(q^2 + 4) − q, to within 0.002 — it is neither a make-up nor a gain, despite the g_svf_makeup_gain_tbl label the decompile carries.
|
inlinenodiscardnoexcept |
g_tone_table — tone records of stride 0x100: 0x24 header plus partial blocks of 0x6e.
|
inlinenodiscardnoexcept |
g_tvf_cutoff_ceil — 128 entries; cutoff ceiling by resonance byte.
|
inlinenodiscardnoexcept |
g_tvf_q_lp — 256 entries; Q trim for filter type 0 at neutral resonance.
|
inlinenodiscardnoexcept |
g_tvf_q_t6 — 256 entries; Q trim for filter type 6.
|
inlinenodiscardnoexcept |
g_tvf_cutoff_warp — 129 entries; the cutoff warp applied at stage C.
|
inlinenodiscardnoexcept |
g_wavedesc_table — wave descriptors of stride 0x16: ROM coordinates, root key, loop.