62 for (
auto& source :
depth) {
65 source = {
neutral,
neutral,
neutral,
neutral, 0, 0, 0,
neutral, 0, 0, 0};
74 return depth[
static_cast<std::size_t
>(source)][
static_cast<std::size_t
>(destination)];
79 return depth[
static_cast<std::size_t
>(source)][
static_cast<std::size_t
>(destination)];
97 at(source, destination) =
128 switch (destination) {
162 pitch += other.pitch;
199 const auto& row =
depth[
static_cast<std::size_t
>(source)];
202 const auto halved = [amount](
int value) {
203 const int offset = value -
neutral;
204 const int magnitude = (std::abs(offset) * amount) >> 1;
205 return offset < 0 ? -magnitude : magnitude;
209 const auto quartered = [amount](
int value) {
return (value * amount) >> 2; };
212 .pitch = (row[0] -
neutral) * amount,
214 .amplitude = halved(row[2]),
215 .lfo1_rate = halved(row[3]),
216 .lfo1_pitch = quartered(row[4]),
217 .lfo1_tvf = quartered(row[5]),
218 .lfo1_tva = quartered(row[6]),
219 .lfo2_rate = halved(row[7]),
220 .lfo2_pitch = quartered(row[8]),
221 .lfo2_tvf = quartered(row[9]),
222 .lfo2_tva = quartered(row[10]),
242 [[nodiscard]] Modulation
245 const auto& row =
depth[
static_cast<std::size_t
>(source)];
246 const int magnitude = (amount < 0 ? -amount : amount) << 2;
247 const bool amount_negative = amount < 0;
250 const auto centred = [magnitude, amount_negative](
int value,
int constant) {
251 const int offset = value -
neutral;
256 static_cast<int>((
static_cast<unsigned>(std::abs(offset) * magnitude) >> 8)
257 *
static_cast<unsigned>(constant)
259 return (offset < 0) != amount_negative ? -
scaled :
scaled;
263 const auto amountwise = [magnitude, amount_negative](
int value,
int constant) {
267 const int scaled =
static_cast<int>((
static_cast<unsigned>(value * magnitude) >> 8)
268 *
static_cast<unsigned>(constant)
273 constexpr int whole = 0xFE16;
274 constexpr int half = 0x7F00;
275 constexpr int quarter = 0x3F81;
278 .pitch = centred(pitch_depth, whole),
279 .tvf_cutoff = centred(row[1], half),
280 .amplitude = centred(row[2], half),
281 .lfo1_rate = centred(row[3], half),
282 .lfo1_pitch = amountwise(row[4], quarter),
283 .lfo1_tvf = amountwise(row[5], quarter),
284 .lfo1_tva = amountwise(row[6], quarter),
285 .lfo2_rate = centred(row[7], half),
286 .lfo2_pitch = amountwise(row[8], quarter),
287 .lfo2_tvf = amountwise(row[9], quarter),
288 .lfo2_tva = amountwise(row[10], quarter),
325 switch (destination) {
327 return Law{0xBE8, 3, 0xFBF8};
329 return Law{4000, 3, 0xC49C};
331 return Law{4000, 4, 0x820D};
334 return Law{4000, 1, 0xD1B8};
337 return Law{0xFC0, 1, 0xBE7A};
340 return Law{0xFC0, 1, 0xC30D};
345 return Law{0xFC0, 4, 0x8105};
358 const Law rule =
law(destination);
359 const unsigned magnitude =
360 static_cast<unsigned>(std::min(std::abs(sum), rule.
clamp) << rule.
shift);
362 static_cast<int>((magnitude *
static_cast<unsigned>(rule.
multiplier)) >> 16);
363 return sum < 0 ? -value : value;
Definition control_decode.hpp:7
What turns a summed destination into its own unit — part_mod_depth_recalc, once per destination.
Definition control_matrix.hpp:299
int multiplier
The 16.16 multiplier whose high word is the result.
Definition control_matrix.hpp:305
int shift
The left shift the magnitude takes first.
Definition control_matrix.hpp:303
int clamp
The magnitude ceiling, applied before the scale.
Definition control_matrix.hpp:301
What one source contributes, once its depths have been scaled by its current amount.
Definition control_matrix.hpp:107
int pitch
added to the voice's pitch
Definition control_matrix.hpp:108
int amplitude
scales the voice's level
Definition control_matrix.hpp:110
constexpr Modulation & operator+=(const Modulation &other) noexcept
Accumulates another source's contribution.
Definition control_matrix.hpp:160
int lfo1_tva
Definition control_matrix.hpp:114
int lfo2_pitch
Definition control_matrix.hpp:116
int lfo2_tva
Definition control_matrix.hpp:118
constexpr int at(Destination destination) const noexcept
One field, chosen by destination.
Definition control_matrix.hpp:126
int lfo1_rate
Definition control_matrix.hpp:111
int lfo2_tvf
Definition control_matrix.hpp:117
int lfo2_rate
Definition control_matrix.hpp:115
int lfo1_pitch
Definition control_matrix.hpp:112
int lfo1_tvf
Definition control_matrix.hpp:113
int tvf_cutoff
added to the cutoff sum
Definition control_matrix.hpp:109
static constexpr bool bend_pitch_lives_in_bend_range
Bend's pitch depth is not stored here, and this says so out loud.
Definition control_matrix.hpp:391
Source
Where a modulation comes from, in the order 40 2x addresses them.
Definition control_matrix.hpp:20
@ poly_pressure
polyphonic aftertouch, 40 2x 30-3A
Definition control_matrix.hpp:24
@ cc2
the part's CC2, 40 2x 50-5A
Definition control_matrix.hpp:26
@ modulation
CC#1, 40 2x 00-0A.
Definition control_matrix.hpp:21
@ cc1
the part's CC1, 40 2x 40-4A
Definition control_matrix.hpp:25
@ bend
pitch bend, 40 2x 10-1A
Definition control_matrix.hpp:22
@ channel_pressure
channel aftertouch, 40 2x 20-2A
Definition control_matrix.hpp:23
void reset() noexcept
Returns every route to power-on.
Definition control_matrix.hpp:60
int & at(Source source, Destination destination) noexcept
Definition control_matrix.hpp:72
ControlMatrix() noexcept
Definition control_matrix.hpp:57
static constexpr int neutral
The value every depth centres on, and the value of an unassigned route.
Definition control_matrix.hpp:48
static constexpr Modulation scaled(const Modulation &sums) noexcept
Every destination's summed sources, each scaled by its own law.
Definition control_matrix.hpp:367
void store(Source source, Destination destination, int value) noexcept
Stores one depth the way sysex_part_control_matrix does, which is not a plain assignment.
Definition control_matrix.hpp:95
static constexpr int destination_count
Definition control_matrix.hpp:45
static constexpr int scaled(Destination destination, int sum) noexcept
Clamps and scales a destination's summed sources into that destination's unit.
Definition control_matrix.hpp:352
Modulation applied_linear(Source source, int amount) const noexcept
Scales this source's depths by a controller amount — modmatrix_apply_linear.
Definition control_matrix.hpp:197
std::array< std::array< int, destination_count >, source_count > depth
[source][destination].
Definition control_matrix.hpp:55
Modulation applied_bipolar(Source source, int amount, int pitch_depth=neutral) const noexcept
Scales this source's depths by a signed amount — modmatrix_apply_bipolar.
Definition control_matrix.hpp:243
int at(Source source, Destination destination) const noexcept
Definition control_matrix.hpp:77
static constexpr int source_count
Definition control_matrix.hpp:44
static constexpr int default_modulation_lfo1_pitch
The mod wheel's LFO1 pitch depth at power-on — the one destination that is not zero or centred,...
Definition control_matrix.hpp:52
static constexpr Law law(Destination destination) noexcept
The three constants for one destination.
Definition control_matrix.hpp:323
Destination
What a modulation reaches. The index is the low nibble of the SysEx address.
Definition control_matrix.hpp:30
@ lfo1_pitch
0…600 cents
Definition control_matrix.hpp:35
@ lfo2_tva
0…100 %
Definition control_matrix.hpp:41
@ lfo2_tvf
0…2400 cents
Definition control_matrix.hpp:40
@ lfo2_rate
-10…+10 Hz
Definition control_matrix.hpp:38
@ lfo1_tvf
0…2400 cents
Definition control_matrix.hpp:36
@ pitch
-24…+24 semitones
Definition control_matrix.hpp:31
@ lfo1_rate
-10…+10 Hz
Definition control_matrix.hpp:34
@ lfo1_tva
0…100 %
Definition control_matrix.hpp:37
@ amplitude
-100…+100 %
Definition control_matrix.hpp:33
@ lfo2_pitch
0…600 cents
Definition control_matrix.hpp:39
@ tvf_cutoff
-9600…+9600 cents
Definition control_matrix.hpp:32