Tabula Sonora 0.1.0
A native C++20 implementation of the Roland Sound Canvas VA synth voice
Loading...
Searching...
No Matches
pitch_chain.hpp
Go to the documentation of this file.
1#pragma once
2
8
9#include <array>
10#include <cstdint>
11#include <optional>
12#include <vector>
13
14namespace ts {
15
19 int start = 0;
21 std::array<int, 4> targets{};
23 int release = 0;
25 std::array<double, 4> times{};
27 double release_ms = 0.0;
28};
29
40public:
46 explicit PitchEnvelopeRunner(const PitchEnvelope& envelope, bool ignore_note_off = false);
47
51 [[nodiscard]] static PitchEnvelopeRunner constant(double level);
52
54 [[nodiscard]] double level() const noexcept { return level_; }
55
60 void set_release_damper(int damper) noexcept;
61
63 double tick(bool released) noexcept;
64
65private:
66 PitchEnvelopeRunner() = default;
67
68 [[nodiscard]] int scaled_release_rate() const noexcept;
69
70 std::vector<int> targets_;
71 std::vector<int> rates_;
72 int release_ = 0;
73 int release_rate_ = 0;
74 bool ignore_note_off_ = false;
75
76 double segment_start_ = 0.0;
77 double level_ = 0.0;
78 int segment_ = 0;
79 int phase_ = 0;
80 bool released_ = false;
81 int release_damper_ = 0;
82};
83
91public:
93 static constexpr int max_pitch_milli_semitones = 0x1F018;
94
96 static constexpr int drum_key_centre = 60;
97
99 struct KeyFollow {
100 int key = 0;
101 int weight = 0;
102 };
103
108 PitchChain(const TableSet& tables,
109 const EnvelopeMachine& envelope,
110 EngineNoise* noise = nullptr);
111
118 [[nodiscard]] static KeyFollow
119 key_follow_key(const PartialParameters& partial, int note, int key_center = 0x3C) noexcept;
120
122 [[nodiscard]] int base_pitch_milli_semitones(const PartialParameters& partial,
123 int note,
124 int key_center = 0x3C) const noexcept;
125
136 [[nodiscard]] static int drum_pitch_milli_semitones(const PartialParameters& partial,
137 int coarse_pitch) noexcept;
138
140 [[nodiscard]] int portamento_step(int time) const noexcept;
141
146 [[nodiscard]] static int portamento_offset(int from_key, int target_pitch) noexcept;
147
149 [[nodiscard]] static double bend_offset_milli_semitones(int bend = 8192,
150 double semitone_range = 2.0) noexcept;
151
153 [[nodiscard]] std::optional<PitchEnvelope>
154 envelope_offsets(const PartialParameters& partial, int key, int velocity) const noexcept;
155
160 [[nodiscard]] static int segment_rate_word(double milliseconds) noexcept;
161
165 [[nodiscard]] std::optional<std::vector<double>>
167 int key,
168 int velocity,
169 double hold_seconds,
170 int tick_count) const;
171
177 [[nodiscard]] static int start_jitter_milli_semitones(int depth, std::uint16_t draw) noexcept;
178
187 [[nodiscard]] std::optional<PitchEnvelopeRunner>
188 create_envelope_runner(const PartialParameters& partial, int key, int velocity) const;
189
191 [[nodiscard]] static double ratio(const PartialParameters& partial,
192 const WaveDescriptor& descriptor,
193 double pitch_milli_semitones) noexcept;
194
196 [[nodiscard]] static double clamp(double milli_semitones) noexcept;
197
198private:
199 const EnvelopeMachine* envelope_;
200 EngineNoise* noise_;
201 EngineNoise owned_noise_;
202
203 std::span<const std::uint16_t> portamento_step_;
204 std::span<const std::uint8_t> pitch_bias_;
205 std::span<const std::uint16_t> depth_velocity_sensitivity_;
206 std::span<const std::uint8_t> rate_key_follow0_;
207 std::span<const std::uint8_t> rate_key_follow1_;
208 std::span<const std::int16_t> key_follow_;
209 std::span<const std::uint16_t> rate_curve_;
210
213 std::array<std::int16_t, 0x80> depth_slope_{};
214};
215
216} // namespace ts
The engine's shared pseudo-random generator.
Definition engine_noise.hpp:18
The segment-rate and segment-shape machine shared by the TVA, TVF and pitch envelopes.
Definition envelope_machine.hpp:22
A zero-copy typed view over one 0x6e-byte partial parameter block inside a tone record.
Definition partial_parameters.hpp:20
static KeyFollow key_follow_key(const PartialParameters &partial, int note, int key_center=0x3C) noexcept
The effective pitch key and its fractional crossfade weight.
static int drum_pitch_milli_semitones(const PartialParameters &partial, int coarse_pitch) noexcept
A drum key's absolute pitch in milli-semitones, from its coarse-pitch plane value.
static constexpr int max_pitch_milli_semitones
Upper clamp of the pitch accumulator: 127 semitones in milli-semitones.
Definition pitch_chain.hpp:93
static double ratio(const PartialParameters &partial, const WaveDescriptor &descriptor, double pitch_milli_semitones) noexcept
The playback ratio for a partial, from its absolute pitch against the sample's own root.
int portamento_step(int time) const noexcept
The portamento glide step for a CC#5 time byte, in milli-semitones per control tick.
int base_pitch_milli_semitones(const PartialParameters &partial, int note, int key_center=0x3C) const noexcept
The note's absolute base pitch in milli-semitones.
static constexpr int drum_key_centre
The key a drum's coarse-pitch plane pivots around: 60 is its natural pitch.
Definition pitch_chain.hpp:96
static double bend_offset_milli_semitones(int bend=8192, double semitone_range=2.0) noexcept
Pitch-bend offset in milli-semitones, from a 14-bit bend with 8192 centre.
PitchChain(const TableSet &tables, const EnvelopeMachine &envelope, EngineNoise *noise=nullptr)
Creates the chain over a loaded table set and machine, both of which must outlive it.
static int start_jitter_milli_semitones(int depth, std::uint16_t draw) noexcept
The random start-pitch jitter for one note-on, in milli-semitones.
std::optional< std::vector< double > > envelope_ticks(const PartialParameters &partial, int key, int velocity, double hold_seconds, int tick_count) const
The pitch envelope's offset at each control tick, or nothing when it is inactive.
std::optional< PitchEnvelopeRunner > create_envelope_runner(const PartialParameters &partial, int key, int velocity) const
Creates a runner for a partial's pitch envelope, or nothing when it does nothing.
static double clamp(double milli_semitones) noexcept
Clamps an absolute pitch the way the engine's accumulator does.
std::optional< PitchEnvelope > envelope_offsets(const PartialParameters &partial, int key, int velocity) const noexcept
Decodes the pitch envelope's targets and timings, or nothing when it is disabled.
static int segment_rate_word(double milliseconds) noexcept
The segment machine's rate word for a duration.
static int portamento_offset(int from_key, int target_pitch) noexcept
The glide offset a note starts with, in milli-semitones, decaying to zero as it completes.
Walks a pitch envelope one control tick at a time.
Definition pitch_chain.hpp:39
void set_release_damper(int damper) noexcept
Sets the half-damper pedal value the release will be scaled by, 1–0x3f or zero.
static PitchEnvelopeRunner constant(double level)
A runner that holds one level forever, in milli-semitones.
double tick(bool released) noexcept
Advances one control tick and returns the offset in milli-semitones.
double level() const noexcept
The offset in milli-semitones after the last tick.
Definition pitch_chain.hpp:54
PitchEnvelopeRunner(const PitchEnvelope &envelope, bool ignore_note_off=false)
Creates a runner over a decoded envelope.
The static tables the engine needs, loaded from SCCore.dll or from a directory of extracted ....
Definition table_set.hpp:30
Definition control_decode.hpp:7
@ damper
Definition control_decode.hpp:22
The effective pitch key and its fractional crossfade weight.
Definition pitch_chain.hpp:99
int weight
Definition pitch_chain.hpp:101
int key
Definition pitch_chain.hpp:100
The pitch envelope's decoded segment targets and timings.
Definition pitch_chain.hpp:17
std::array< double, 4 > times
Segment durations in milliseconds.
Definition pitch_chain.hpp:25
std::array< int, 4 > targets
The four segment targets.
Definition pitch_chain.hpp:21
int release
The release target.
Definition pitch_chain.hpp:23
int start
Starting offset, in milli-semitones.
Definition pitch_chain.hpp:19
double release_ms
Release duration in milliseconds.
Definition pitch_chain.hpp:27
One entry of the wave-descriptor table: where a sample lives in the wave ROM, how it is tuned,...
Definition wave_descriptor.hpp:14