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

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
TableSetoperator= (TableSet &&) noexcept
 TableSet (const TableSet &)=delete
TableSetoperator= (const TableSet &)=delete
 ~TableSet ()
const TableManifestmanifest () 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.

Detailed Description

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.

Constructor & Destructor Documentation

◆ TableSet() [1/2]

ts::TableSet::TableSet ( TableSet && )
noexcept

◆ TableSet() [2/2]

ts::TableSet::TableSet ( const TableSet & )
delete

◆ ~TableSet()

ts::TableSet::~TableSet ( )

Member Function Documentation

◆ from_rom()

TableSet ts::TableSet::from_rom ( const RomImage & rom)
staticnodiscard

Loads every table by slicing the DLL at its manifest offset.

◆ from_cache_directory()

TableSet ts::TableSet::from_cache_directory ( const std::filesystem::path & directory,
const TableManifest * manifest = nullptr )
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.

◆ operator=() [1/2]

TableSet & ts::TableSet::operator= ( TableSet && )
noexcept

◆ operator=() [2/2]

TableSet & ts::TableSet::operator= ( const TableSet & )
delete

◆ manifest()

const TableManifest & ts::TableSet::manifest ( ) const
inlinenodiscardnoexcept

The offset map these tables were loaded through.

◆ raw()

std::span< const std::uint8_t > ts::TableSet::raw ( std::string_view name) const
nodiscard

Returns the untouched bytes of one table; see names.

Throws std::out_of_range if no such table was loaded.

◆ amp_curve_hi()

std::span< const std::uint16_t > ts::TableSet::amp_curve_hi ( ) const
inlinenodiscardnoexcept

g_amp_curve_hi — 256 entries, high half of the log-to-linear amplitude lookup.

◆ amp_curve_lo()

std::span< const std::uint16_t > ts::TableSet::amp_curve_lo ( ) const
inlinenodiscardnoexcept

g_amp_curve_lo — 256 entries, low half of the log-to-linear amplitude lookup.

◆ tvf_env_depth()

std::span< const std::uint8_t > ts::TableSet::tvf_env_depth ( ) const
inlinenodiscardnoexcept

g_tvf_env_depth — TVF env-depth conversion region, addressed by VA-relative offset.

◆ filter_type_coef()

std::span< const std::uint32_t > ts::TableSet::filter_type_coef ( ) const
inlinenodiscardnoexcept

g_filter_type_coef — 16 entries; filter TYPE byte to tap/coefficient word.

◆ level_curve()

std::span< const std::uint16_t > ts::TableSet::level_curve ( ) const
inlinenodiscardnoexcept

g_level_curve — 128 entries; envelope stage byte to 16-bit log attenuation.

◆ pitch_bias()

std::span< const std::uint8_t > ts::TableSet::pitch_bias ( ) const
inlinenodiscardnoexcept

g_pitch_bias — 128 entries; pitch-envelope bias sub-table.

◆ pitch_depth_vs()

std::span< const std::uint16_t > ts::TableSet::pitch_depth_vs ( ) const
inlinenodiscardnoexcept

g_pitch_depth_vs — 64 entries; pitch-envelope depth versus velocity.

◆ pitch_env()

std::span< const std::uint8_t > ts::TableSet::pitch_env ( ) const
inlinenodiscardnoexcept

g_pitch_env — pitch-envelope conversion region, addressed by VA-relative offset.

◆ env_rate_out()

std::span< const std::uint16_t > ts::TableSet::env_rate_out ( ) const
inlinenodiscardnoexcept

g_env_rate_out — 512 entries; the rate-scale output curve, exactly 2^((i−0x80)/32) in 8.8.

◆ reso_curve()

std::span< const std::int16_t > ts::TableSet::reso_curve ( ) const
inlinenodiscardnoexcept

g_reso_curve — 64 entries; resonance curve for partial block byte 0x4a.

◆ env_scale_curve()

std::span< const std::uint8_t > ts::TableSet::env_scale_curve ( ) const
inlinenodiscardnoexcept

g_env_scale_curve — 256 entries; envelope rate/level scale, 0x40-neutral.

◆ rate_curve()

std::span< const std::uint16_t > ts::TableSet::rate_curve ( ) const
inlinenodiscardnoexcept

g_rate_curve — 128 entries; rate byte to segment time.

◆ vel_curve()

std::span< const std::uint8_t > ts::TableSet::vel_curve ( ) const
inlinenodiscardnoexcept

g_vel_curve — 256 entries; velocity response curve.

◆ vel_sens()

std::span< const std::uint8_t > ts::TableSet::vel_sens ( ) const
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].

◆ vel_xfade()

std::span< const std::uint8_t > ts::TableSet::vel_xfade ( ) const
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].

◆ env_shape()

std::span< const std::uint16_t > ts::TableSet::env_shape ( ) const
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.

◆ env_start_phase()

std::span< const std::uint16_t > ts::TableSet::env_start_phase ( ) const
inlinenodiscardnoexcept

g_env_startphase — 128 entries; per-segment initial phase seed.

◆ interp_coef()

std::span< const float > ts::TableSet::interp_coef ( ) const
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.

◆ kf_pitch()

std::span< const std::int16_t > ts::TableSet::kf_pitch ( ) const
inlinenodiscardnoexcept

g_kf_pitch — 8 rows of 128; pitch key-follow, indexed row * 0x80 + key.

◆ kf_pitch_rate0()

std::span< const std::uint8_t > ts::TableSet::kf_pitch_rate0 ( ) const
inlinenodiscardnoexcept

g_kf_pitchrate0 — 128×128; pitch-envelope rate key-follow for the segments.

◆ kf_pitch_rate1()

std::span< const std::uint8_t > ts::TableSet::kf_pitch_rate1 ( ) const
inlinenodiscardnoexcept

g_kf_pitchrate1 — 128×128; pitch-envelope rate key-follow for the release.

◆ kf_tva_level()

std::span< const std::uint8_t > ts::TableSet::kf_tva_level ( ) const
inlinenodiscardnoexcept

g_kf_tvalevel — 128×128; TVA base-level key-follow.

◆ kf_tva_level2()

std::span< const std::uint8_t > ts::TableSet::kf_tva_level2 ( ) const
inlinenodiscardnoexcept

g_kf_tvalevel2 — 128×128; TVA level key-follow, second term.

◆ kf_tva_rate0()

std::span< const std::uint8_t > ts::TableSet::kf_tva_rate0 ( ) const
inlinenodiscardnoexcept

g_kf_tvarate0 — 128×128; TVA envelope rate key-follow for the segments.

◆ kf_tva_rate1()

std::span< const std::uint8_t > ts::TableSet::kf_tva_rate1 ( ) const
inlinenodiscardnoexcept

g_kf_tvarate1 — 128×128; TVA envelope rate key-follow for the release.

◆ kf_tvf_env()

std::span< const std::int16_t > ts::TableSet::kf_tvf_env ( ) const
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.

◆ kf_tvf_rate()

std::span< const std::uint8_t > ts::TableSet::kf_tvf_rate ( ) const
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.

◆ layered()

std::span< const std::uint8_t > ts::TableSet::layered ( ) const
inlinenodiscardnoexcept

g_layered_table — 50 alternate-articulation records of 0x18 bytes.

◆ lfo_cents()

std::span< const std::uint16_t > ts::TableSet::lfo_cents ( ) const
inlinenodiscardnoexcept

g_lfo_cents_tbl — 128 entries; LFO pitch-depth byte to milli-semitones.

◆ lfo_delay()

std::span< const std::uint16_t > ts::TableSet::lfo_delay ( ) const
inlinenodiscardnoexcept

g_lfo_delay_tbl — 128 entries; LFO1 delay byte to delay ticks.

◆ lfo_rate()

std::span< const std::uint16_t > ts::TableSet::lfo_rate ( ) const
inlinenodiscardnoexcept

g_lfo_rate_tbl — 128 entries; LFO1 rate byte to 16-bit phase increment.

◆ portamento_step()

std::span< const std::uint16_t > ts::TableSet::portamento_step ( ) const
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.

◆ lfo_wave()

std::span< const std::uint8_t > ts::TableSet::lfo_wave ( ) const
inlinenodiscardnoexcept

g_lfo_wave — the half-sine LFO waveform used by selector 0.

◆ lfo_wave_bank()

std::span< const std::int16_t > ts::TableSet::lfo_wave_bank ( ) const
inlinenodiscardnoexcept

g_lfo_wavebank — LFO wavetables 8..0x1f, 24 rows of 0x81 entries.

◆ lfo_wave_map()

std::span< const std::uint8_t > ts::TableSet::lfo_wave_map ( ) const
inlinenodiscardnoexcept

g_lfo_wavemap — 32 entries; waveform selector nibble to table index.

◆ dir_lut1()

std::span< const std::uint8_t > ts::TableSet::dir_lut1 ( ) const
inlinenodiscardnoexcept

g_dir_lut1 — 128 entries; tone-map to LUT2 row.

◆ dir_lut2()

std::span< const std::uint8_t > ts::TableSet::dir_lut2 ( ) const
inlinenodiscardnoexcept

g_dir_lut2 — bank to LUT3 row.

◆ dir_lut3()

std::span< const std::uint16_t > ts::TableSet::dir_lut3 ( ) const
inlinenodiscardnoexcept

g_dir_lut3 — 32768 entries; program to tone number.

◆ multisample()

std::span< const std::uint8_t > ts::TableSet::multisample ( ) const
inlinenodiscardnoexcept

g_multisample_table — key/velocity zone to wave number, stride 0x8c.

◆ pan()

std::span< const std::uint8_t > ts::TableSet::pan ( ) const
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.

◆ ramp_divider()

std::span< const std::uint8_t > ts::TableSet::ramp_divider ( ) const
inlinenodiscardnoexcept

g_ramp_divider — the anti-zipper zero-order-hold masks [0, 7, 31, 127].

◆ ramp_exp()

std::span< const std::int32_t > ts::TableSet::ramp_exp ( ) const
inlinenodiscardnoexcept

g_ramp_exp_tbl — 257 entries of 2^17 · 2^(i/256), the SVF f-coefficient decode.

◆ ramp_flagword()

std::span< const std::uint8_t > ts::TableSet::ramp_flagword ( ) const
inlinenodiscardnoexcept

g_ramp_flagword — per-destination ramp-divider selector bits.

◆ svf_f_ceil()

std::span< const float > ts::TableSet::svf_f_ceil ( ) const
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.

◆ tone()

std::span< const std::uint8_t > ts::TableSet::tone ( ) const
inlinenodiscardnoexcept

g_tone_table — tone records of stride 0x100: 0x24 header plus partial blocks of 0x6e.

◆ tvf_cutoff_ceil()

std::span< const std::uint16_t > ts::TableSet::tvf_cutoff_ceil ( ) const
inlinenodiscardnoexcept

g_tvf_cutoff_ceil — 128 entries; cutoff ceiling by resonance byte.

◆ tvf_q_lp()

std::span< const std::uint16_t > ts::TableSet::tvf_q_lp ( ) const
inlinenodiscardnoexcept

g_tvf_q_lp — 256 entries; Q trim for filter type 0 at neutral resonance.

◆ tvf_q_t6()

std::span< const std::uint16_t > ts::TableSet::tvf_q_t6 ( ) const
inlinenodiscardnoexcept

g_tvf_q_t6 — 256 entries; Q trim for filter type 6.

◆ tvf_cutoff_warp()

std::span< const std::uint16_t > ts::TableSet::tvf_cutoff_warp ( ) const
inlinenodiscardnoexcept

g_tvf_cutoff_warp — 129 entries; the cutoff warp applied at stage C.

◆ wavedesc()

std::span< const std::uint8_t > ts::TableSet::wavedesc ( ) const
inlinenodiscardnoexcept

g_wavedesc_table — wave descriptors of stride 0x16: ROM coordinates, root key, loop.


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