Tabula Sonora 0.1.0
A native C++20 implementation of the Roland Sound Canvas VA synth voice
Loading...
Searching...
No Matches
sequence.hpp
Go to the documentation of this file.
1#pragma once
2
6
7#include <array>
8#include <cstdint>
9#include <optional>
10#include <span>
11#include <vector>
12
13namespace ts {
14
20public:
22 void add(std::int64_t position, int value) { points_.push_back(Point{position, value}); }
23
25 [[nodiscard]] int value_at(std::int64_t position, int fallback) const noexcept;
26
28 [[nodiscard]] std::size_t size() const noexcept { return points_.size(); }
29
36 bool fill(std::int64_t start, std::span<int> destination, int fallback) const noexcept;
37
38private:
39 struct Point {
40 std::int64_t position = 0;
41 int value = 0;
42 };
43
44 std::vector<Point> points_;
45};
46
51public:
53 static constexpr int centre = 0x40;
54
56 static constexpr int random_pan = 0;
57
59
61 [[nodiscard]] bool is_empty() const noexcept { return !any_; }
62
64 void reset() noexcept;
65
67 void set_pitch(int note, int entry) noexcept;
68
70 void set_pan(int note, int entry) noexcept;
71
76 void set_play_key(int note, int entry) noexcept;
77
79 void set_level(int note, int entry) noexcept;
80
82 void set_group(int note, int entry) noexcept;
83
88 void set_reverb(int note, int entry) noexcept;
89 void set_chorus(int note, int entry) noexcept;
90 void set_delay(int note, int entry) noexcept;
91
97 void set_rx_note_off(int note, bool on) noexcept;
98 void set_rx_note_on(int note, bool on) noexcept;
99
105 [[nodiscard]] int pitch_offset(int note) const noexcept;
106
108 [[nodiscard]] std::optional<int> pan(int note) const noexcept;
109
111 [[nodiscard]] std::optional<int> play_key(int note) const noexcept;
112
114 [[nodiscard]] std::optional<int> level(int note) const noexcept;
115
117 [[nodiscard]] std::optional<int> group(int note) const noexcept;
118
120 [[nodiscard]] std::optional<bool> rx_note_off(int note) const noexcept;
121 [[nodiscard]] std::optional<bool> rx_note_on(int note) const noexcept;
122
130 [[nodiscard]] std::optional<int> pan_for_hit(int note, EngineNoise& noise) const;
131
139 [[nodiscard]] static DrumKey
140 apply(DrumKey key, int pitch_offset, std::optional<int> pan) noexcept;
141
142private:
143 std::array<int, DrumKitTable::key_count> pitch_{};
144 std::array<int, DrumKitTable::key_count> pan_{};
145 // The drum-setup planes, -1 where the key follows its kit record.
146 std::array<int, DrumKitTable::key_count> play_key_{};
147 std::array<int, DrumKitTable::key_count> level_{};
148 std::array<int, DrumKitTable::key_count> group_{};
149 std::array<int, DrumKitTable::key_count> reverb_{};
150 std::array<int, DrumKitTable::key_count> chorus_{};
151 std::array<int, DrumKitTable::key_count> delay_{};
152 std::array<int, DrumKitTable::key_count> rx_note_off_{};
153 std::array<int, DrumKitTable::key_count> rx_note_on_{};
154 bool any_ = false;
155};
156
159 int channel = 0;
160 int note = 0;
161 int velocity = 0;
163 std::int64_t on = 0;
165 std::int64_t off = 0;
166 int program = 0;
168 int bank = 0;
170 int pan = 0;
172 int volume = 0;
174 int expression = 0;
176 int reverb_send = 0;
178 int chorus_send = 0;
180 int delay_send = 0;
183 int drum_pitch = 0;
185 std::optional<int> drum_pan;
186};
187
235
237struct Sequence {
239 static constexpr int channel_count = 16;
240
242 std::array<PartTimelines, channel_count> parts;
244 std::vector<NoteRecord> notes;
256 std::int64_t last_event_position = 0;
257};
258
264
266inline constexpr int default_volume = 100;
268inline constexpr int default_expression = 127;
270inline constexpr int default_pan = 64;
272inline constexpr int default_master = 127;
274inline constexpr int default_reverb_send = 40;
276inline constexpr int default_chorus_send = 0;
277
279[[nodiscard]] Sequence build(std::span<const MidiEvent> events);
280
285[[nodiscard]] constexpr int channel_from_block(int block) noexcept
286{
287 return block == 0 ? 9 : block <= 9 ? block - 1 : block;
288}
289
290} // namespace sequence_builder
291} // namespace ts
A controller's value over time, as breakpoints.
Definition sequence.hpp:19
std::size_t size() const noexcept
Number of recorded changes.
Definition sequence.hpp:28
bool fill(std::int64_t start, std::span< int > destination, int fallback) const noexcept
Fills a span with this controller's value at every sample from a starting position.
void add(std::int64_t position, int value)
Records a change.
Definition sequence.hpp:22
int value_at(std::int64_t position, int fallback) const noexcept
The value in force at a position, or fallback before the first breakpoint.
static constexpr int random_pan
The panpot entry that means "random", which only the GS SysEx panpot can write.
Definition sequence.hpp:56
std::optional< int > level(int note) const noexcept
The level override for a key, or nothing when it follows the kit.
void reset() noexcept
Clears every override.
std::optional< int > group(int note) const noexcept
The assign-group override for a key, or nothing when it follows the kit.
static DrumKey apply(DrumKey key, int pitch_offset, std::optional< int > pan) noexcept
Layers a latched pair of overrides over a key read from the kit record.
void set_rx_note_on(int note, bool on) noexcept
void set_chorus(int note, int entry) noexcept
DrumKeyOverrides()
Definition sequence.hpp:58
void set_delay(int note, int entry) noexcept
std::optional< int > pan(int note) const noexcept
The panpot held for a key, or nothing when the key follows its kit record.
static constexpr int centre
Data-entry value meaning no change.
Definition sequence.hpp:53
std::optional< int > play_key(int note) const noexcept
The absolute play-key override for a key, or nothing when it follows the kit.
void set_level(int note, int entry) noexcept
Records a level override for one key, replacing the kit's level plane entry.
void set_pitch(int note, int entry) noexcept
Records a coarse-pitch override for one key; centre is no change.
std::optional< int > pan_for_hit(int note, EngineNoise &noise) const
Resolves the panpot for one strike, spreading a randomly-panned key.
int pitch_offset(int note) const noexcept
The coarse-pitch offset held for a key, in kit-plane steps.
void set_reverb(int note, int entry) noexcept
Records per-key send depths, from NRPN 1D/1E/1F or drum-setup SysEx.
void set_pan(int note, int entry) noexcept
Records a panpot override for one key, used directly as the key's pan.
std::optional< bool > rx_note_on(int note) const noexcept
bool is_empty() const noexcept
Whether any override has been recorded.
Definition sequence.hpp:61
void set_play_key(int note, int entry) noexcept
Records an absolute play-key override for one key, from drum-setup SysEx 41 m1 kk.
void set_group(int note, int entry) noexcept
Records an assign-group override for one key.
void set_rx_note_off(int note, bool on) noexcept
Records the per-key receive switches, from drum-setup SysEx 41 m7 kk / 41 m8 kk.
std::optional< bool > rx_note_off(int note) const noexcept
The receive-switch overrides for a key, or nothing when it follows the kit.
The drum kit records: for each of 128 keys, which tone sounds and how it is levelled,...
Definition drum_kit_table.hpp:57
The engine's shared pseudo-random generator.
Definition engine_noise.hpp:18
Turns a flat event list into per-part controller timelines and a note list.
Definition sequence.hpp:263
constexpr int default_chorus_send
GM default chorus send.
Definition sequence.hpp:276
constexpr int default_pan
Power-on pan.
Definition sequence.hpp:270
constexpr int channel_from_block(int block) noexcept
Converts a GS block number to a MIDI channel.
Definition sequence.hpp:285
constexpr int default_reverb_send
GM default reverb send.
Definition sequence.hpp:274
constexpr int default_expression
Power-on expression.
Definition sequence.hpp:268
constexpr int default_master
Power-on master volume.
Definition sequence.hpp:272
Sequence build(std::span< const MidiEvent > events)
Builds a sequence from a flat event list, ordered by position.
constexpr int default_volume
Power-on volume after a GM or GS reset.
Definition sequence.hpp:266
Definition control_decode.hpp:7
One drum key's settings within a kit.
Definition drum_kit_table.hpp:15
One note, with every parameter latched as it was at note-on.
Definition sequence.hpp:158
int program
Definition sequence.hpp:166
int chorus_send
CC#93.
Definition sequence.hpp:178
int velocity
Definition sequence.hpp:161
int channel
Definition sequence.hpp:159
std::optional< int > drum_pan
Panpot override for this drum key from NRPN 0x1C, or nothing when it follows the kit.
Definition sequence.hpp:185
int volume
CC#7.
Definition sequence.hpp:172
int reverb_send
CC#91.
Definition sequence.hpp:176
int expression
CC#11.
Definition sequence.hpp:174
std::int64_t on
Note-on position in samples.
Definition sequence.hpp:163
int delay_send
Part delay send, which has no Control Change and arrives only over SysEx.
Definition sequence.hpp:180
int drum_pitch
Coarse-pitch override for this drum key from NRPN 0x18, in steps of one semitone.
Definition sequence.hpp:183
int pan
CC#10.
Definition sequence.hpp:170
int bank
Bank select MSB.
Definition sequence.hpp:168
std::int64_t off
Note-off position in samples, after any damper extension.
Definition sequence.hpp:165
int note
Definition sequence.hpp:160
Per-channel controller timelines.
Definition sequence.hpp:189
ControllerTimeline matrix_pressure_pitch
Definition sequence.hpp:233
ControllerTimeline bend_range
Bend range in semitones, from RPN 00/00.
Definition sequence.hpp:196
ControllerTimeline matrix_modulation_pitch
Definition sequence.hpp:232
ControllerTimeline velocity_depth
GS velocity sense depth and offset (40 1x 1A/1B), latched at note-on.
Definition sequence.hpp:223
ControllerTimeline program
Definition sequence.hpp:205
ControllerTimeline modulation
CC#1 modulation.
Definition sequence.hpp:200
ControllerTimeline env_release
Definition sequence.hpp:220
ControllerTimeline bank
Bank select MSB.
Definition sequence.hpp:207
ControllerTimeline volume
Definition sequence.hpp:190
ControllerTimeline env_decay
Definition sequence.hpp:219
ControllerTimeline pan
Definition sequence.hpp:192
ControllerTimeline reverb_send
Definition sequence.hpp:201
ControllerTimeline channel_pressure
Channel aftertouch, and the control matrix's two pitch routes that this path can reach.
Definition sequence.hpp:231
ControllerTimeline delay_send
Delay send, set over SysEx.
Definition sequence.hpp:204
ControllerTimeline tvf_cutoff
Definition sequence.hpp:217
ControllerTimeline vibrato_delay
Definition sequence.hpp:216
ControllerTimeline bend
Pitch bend, as a 14-bit value.
Definition sequence.hpp:194
ControllerTimeline env_attack
Definition sequence.hpp:218
ControllerTimeline damper
CC#64 damper.
Definition sequence.hpp:198
ControllerTimeline vibrato_rate
The GS part modify offsets, in PartModifiers order, latched at note-on.
Definition sequence.hpp:214
ControllerTimeline chorus_send
Definition sequence.hpp:202
ControllerTimeline vibrato_depth
Definition sequence.hpp:215
ControllerTimeline expression
Definition sequence.hpp:191
ControllerTimeline velocity_offset
Definition sequence.hpp:224
A parsed sequence: controller timelines, notes, and the global effect selections.
Definition sequence.hpp:237
ControllerTimeline chorus_type
GS chorus macro selections.
Definition sequence.hpp:249
std::int64_t last_event_position
Position of the final event of any kind.
Definition sequence.hpp:256
ControllerTimeline delay_type
GS delay macro selections.
Definition sequence.hpp:251
ControllerTimeline master_volume
Definition sequence.hpp:245
static constexpr int channel_count
MIDI channels.
Definition sequence.hpp:239
ControllerTimeline reverb_type
GS reverb macro selections.
Definition sequence.hpp:247
std::array< PartTimelines, channel_count > parts
Per-channel timelines, indexed by MIDI channel.
Definition sequence.hpp:242
std::vector< NoteRecord > notes
Every note, with its parameters latched at note-on.
Definition sequence.hpp:244