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

How a running engine should behave. More...

#include <tabulasonora/tone_generator.hpp>

Public Attributes

int polyphony = 64
 Maximum simultaneous voices, or unlimited_polyphony.
int ports = 2
 MIDI ports to accept input on: 1, 2 or 4, giving 16, 32 or 64 parts.
ToneMap map = ToneMap::sc8820
 Which tone map program changes resolve against.
int drum_channel = 9
 MIDI channel routed to the drum path.
bool reverb = true
bool chorus = true
bool delay = true
bool efx = true
 The insertion EFX block, 40 03 and the per-part 40 4x 22 switch.
std::optional< int > reverb_type
 Force an effect type instead of taking it from the stream.
std::optional< int > chorus_type
std::optional< int > delay_type
double output_gain = 1.0
 Linear gain applied to the audio handed to the host.
const ChannelMaskchannels = nullptr
 Per-channel mute and solo, read live so a mixer can change it while sound is running.

Static Public Attributes

static constexpr int unlimited_polyphony = 0
 Asks for polyphony that grows on demand instead of stealing.

Detailed Description

How a running engine should behave.

Member Data Documentation

◆ unlimited_polyphony

int ts::ToneGeneratorOptions::unlimited_polyphony = 0
staticconstexpr

Asks for polyphony that grows on demand instead of stealing.

◆ polyphony

int ts::ToneGeneratorOptions::polyphony = 64

Maximum simultaneous voices, or unlimited_polyphony.

A note costs one voice per sounding partial, so a two-partial patch halves the note count. The default is the hardware's 64, which is what makes a stream sound like the module — including the stealing, which is audible and part of the character. Raising it is a deliberate departure.

unlimited_polyphony makes the pool grow rather than steal: when it runs out it allocates another chunk of slots, so every note in the file sounds. That is what an offline render wants and what an audio thread must not have — growing allocates, and allocating inside the block loop is the thing a real-time thread cannot do. It also has no upper bound on memory or CPU beyond what the file asks for, which is acceptable when the only requirement is to be right.

◆ ports

int ts::ToneGeneratorOptions::ports = 2

MIDI ports to accept input on: 1, 2 or 4, giving 16, 32 or 64 parts.

Two is the hardware and the default. Four is a deliberate extension past what the module can do – see ToneGenerator::max_port_count – and wants a raised polyphony beside it, since sixty-four parts sharing sixty-four voices would steal without pause. Values that are not 1, 2 or 4 are rejected: the part index is formed by masking, which needs a power of two.

◆ map

ToneMap ts::ToneGeneratorOptions::map = ToneMap::sc8820

Which tone map program changes resolve against.

ToneMap::xg is the switch that starts the engine in XG mode, rather than a separate flag, because on the module the two are one thing: XG System On is precisely what moves every part onto the XG map. Setting it here is the same state a file would have reached by sending it.

It is a starting state, not a lock. A file is still free to change mode – any Roland SysEx leaves XG parsing, exactly as it would have – and this remains the default map that a part with no map selected falls back to, the same way sc8820 does. ToneGenerator::reset returns to it.

There is deliberately no detection: nothing here infers XG from the shape of a file's bank selects. A bank LSB of 18 is a legitimate if unusual GS map selector, and guessing would break the files that mean it. A file that wants XG says so, or the host does.

◆ drum_channel

int ts::ToneGeneratorOptions::drum_channel = 9

MIDI channel routed to the drum path.

◆ reverb

bool ts::ToneGeneratorOptions::reverb = true

◆ chorus

bool ts::ToneGeneratorOptions::chorus = true

◆ delay

bool ts::ToneGeneratorOptions::delay = true

◆ efx

bool ts::ToneGeneratorOptions::efx = true

The insertion EFX block, 40 03 and the per-part 40 4x 22 switch.

Only a first tranche of the 65 algorithms is transcribed; a type outside it passes the signal through unchanged, with routing and send levels still honoured.

◆ reverb_type

std::optional<int> ts::ToneGeneratorOptions::reverb_type

Force an effect type instead of taking it from the stream.

◆ chorus_type

std::optional<int> ts::ToneGeneratorOptions::chorus_type

◆ delay_type

std::optional<int> ts::ToneGeneratorOptions::delay_type

◆ output_gain

double ts::ToneGeneratorOptions::output_gain = 1.0

Linear gain applied to the audio handed to the host.

◆ channels

const ChannelMask* ts::ToneGeneratorOptions::channels = nullptr

Per-channel mute and solo, read live so a mixer can change it while sound is running.


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