Deluge Firmware 1.3.0
Build date: 2026.11.13
Loading...
Searching...
No Matches
arpeggiator.h
1/*
2 * Copyright © 2017-2023 Synthstrom Audible Limited
3 *
4 * This file is part of The Synthstrom Audible Deluge Firmware.
5 *
6 * The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software Foundation,
8 * either version 3 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with this program.
15 * If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19
20#include "algorithm"
21#include "definitions_cxx.hpp"
22#include "model/sync.h"
23#include "storage/storage_manager.h"
24#include "util/container/array/ordered_resizeable_array.h"
25#include "util/container/array/resizeable_array.h"
26
27#include <algorithm>
28#include <array>
29#include <cstddef>
30#include <cstdint>
31
32class PostArpTriggerable;
35
36constexpr uint32_t RANDOMIZER_LOCK_MAX_SAVED_VALUES = 16;
37constexpr uint32_t ARP_MAX_INSTRUCTION_NOTES = 4;
38constexpr uint32_t PATTERN_MAX_BUFFER_SIZE = 16;
39
40constexpr int16_t ARP_NOTE_NONE = 32767;
41
42enum class ArpType : uint8_t {
43 SYNTH,
44 DRUM,
45 KIT,
46};
47
48class ArpeggiatorSettings {
49public:
50 ArpeggiatorSettings();
51
52 void updateParamsFromUnpatchedParamSet(UnpatchedParamSet* unpatchedParams);
53
54 void cloneFrom(ArpeggiatorSettings const* other);
55
56 bool readCommonTagsFromFile(Deserializer& reader, char const* tagName, Song* songToConvertSyncLevel);
57
58 bool readNonAudioTagsFromFile(Deserializer& reader, char const* tagName);
59
60 void writeCommonParamsToFile(Serializer& writer, Song* songToConvertSyncLevel);
61
62 void writeNonAudioParamsToFile(Serializer& writer);
63
64 void generateNewNotePattern();
65
66 void updatePresetFromCurrentSettings();
67
68 void updateSettingsFromCurrentPreset();
69
70 uint32_t getPhaseIncrement(int32_t arpRate);
71
72 // Main settings
73 ArpPreset preset{ArpPreset::OFF};
74 ArpMode mode{ArpMode::OFF};
75
76 bool includeInKitArp{true};
77
78 // Sequence settings
79 ArpOctaveMode octaveMode{ArpOctaveMode::UP};
80 ArpNoteMode noteMode{ArpNoteMode::UP};
81
82 // Octave settings
83 uint8_t numOctaves{2};
84
85 // Number of repetitions of each step
86 uint8_t numStepRepeats{1};
87
88 // Chord type (only for kit arpeggiators)
89 uint8_t chordTypeIndex{0};
90
91 // Sync settings
92 SyncLevel syncLevel;
93 SyncType syncType;
94
95 // Arp randomizer lock
96 bool randomizerLock{false};
97
98 // MPE settings
99 ArpMpeModSource mpeVelocity{ArpMpeModSource::OFF};
100
101 // Spread last lock
102 uint32_t lastLockedNoteProbabilityParameterValue{0};
103 uint32_t lastLockedBassProbabilityParameterValue{0};
104 uint32_t lastLockedSwapProbabilityParameterValue{0};
105 uint32_t lastLockedGlideProbabilityParameterValue{0};
106 uint32_t lastLockedReverseProbabilityParameterValue{0};
107 uint32_t lastLockedChordProbabilityParameterValue{0};
108 uint32_t lastLockedRatchetProbabilityParameterValue{0};
109 uint32_t lastLockedSpreadVelocityParameterValue{0};
110 uint32_t lastLockedSpreadGateParameterValue{0};
111 uint32_t lastLockedSpreadOctaveParameterValue{0};
112
113 // Pre-calculated randomized values for each parameter
114 std::array<int8_t, RANDOMIZER_LOCK_MAX_SAVED_VALUES> lockedNoteProbabilityValues;
115 std::array<int8_t, RANDOMIZER_LOCK_MAX_SAVED_VALUES> lockedBassProbabilityValues;
116 std::array<int8_t, RANDOMIZER_LOCK_MAX_SAVED_VALUES> lockedSwapProbabilityValues;
117 std::array<int8_t, RANDOMIZER_LOCK_MAX_SAVED_VALUES> lockedGlideProbabilityValues;
118 std::array<int8_t, RANDOMIZER_LOCK_MAX_SAVED_VALUES> lockedReverseProbabilityValues;
119 std::array<int8_t, RANDOMIZER_LOCK_MAX_SAVED_VALUES> lockedChordProbabilityValues;
120 std::array<int8_t, RANDOMIZER_LOCK_MAX_SAVED_VALUES> lockedRatchetProbabilityValues;
121 std::array<int8_t, RANDOMIZER_LOCK_MAX_SAVED_VALUES> lockedSpreadVelocityValues;
122 std::array<int8_t, RANDOMIZER_LOCK_MAX_SAVED_VALUES> lockedSpreadGateValues;
123 std::array<int8_t, RANDOMIZER_LOCK_MAX_SAVED_VALUES> lockedSpreadOctaveValues;
124
125 // Order for the pattern note mode
126 std::array<int8_t, PATTERN_MAX_BUFFER_SIZE> notePattern;
127
128 // Temporary flags
129 bool flagForceArpRestart{false};
130
131 // Automatable params
132 int32_t rate{0}; // Default to 25 if not set in XML
133 int32_t gate{0}; // Default to 25 if not set in XML
134 uint32_t rhythm{0};
135 uint32_t sequenceLength{0};
136 uint32_t chordPolyphony{0};
137 uint32_t ratchetAmount{0};
138 uint32_t noteProbability{4294967295u}; // Default to 25 if not set in XML
139 uint32_t bassProbability{0};
140 uint32_t swapProbability{0};
141 uint32_t glideProbability{0};
142 uint32_t reverseProbability{0};
143 uint32_t chordProbability{0};
144 uint32_t ratchetProbability{0};
145 uint32_t spreadVelocity{0};
146 uint32_t spreadGate{0};
147 uint32_t spreadOctave{0};
148};
149enum class ArpNoteStatus : uint8_t {
150 OFF,
151 PENDING,
152 PLAYING,
153};
154
155struct ArpNote {
156 ArpNote() {
157 outputMemberChannel.fill(MIDI_CHANNEL_NONE);
158 noteCodeOnPostArp.fill(ARP_NOTE_NONE);
159 noteStatus.fill(ArpNoteStatus::OFF);
160 }
161 bool isPending() {
162 return std::ranges::any_of(noteStatus, [](ArpNoteStatus status) { return status == ArpNoteStatus::PENDING; });
163 }
167 return noteStatus[0] == ArpNoteStatus::PENDING && noteCodeOnPostArp[0] != ARP_NOTE_NONE;
168 }
169 void resetPostArpArrays() {
170 outputMemberChannel.fill(MIDI_CHANNEL_NONE);
171 noteCodeOnPostArp.fill(ARP_NOTE_NONE);
172 noteStatus.fill(ArpNoteStatus::OFF);
173 }
174 int16_t inputCharacteristics[2]{}; // Before arpeggiation. And applying to MIDI input if that's happening. Or,
175 // channel might be MIDI_CHANNEL_NONE.
176 int16_t mpeValues[kNumExpressionDimensions]{};
177 uint8_t velocity{0};
178 uint8_t baseVelocity{0};
179 // Keep the stretch length with the note when its voice start is deferred to a later render.
180 uint32_t sampleSyncLength{0};
181
182 // For note-ons
183 std::array<ArpNoteStatus, ARP_MAX_INSTRUCTION_NOTES> noteStatus{};
184 std::array<uint8_t, ARP_MAX_INSTRUCTION_NOTES> outputMemberChannel{};
185 std::array<int16_t, ARP_MAX_INSTRUCTION_NOTES> noteCodeOnPostArp{};
186};
187
189 int16_t noteCode; // Before arpeggiation
190};
191
192class ArpReturnInstruction {
193public:
194 ArpReturnInstruction() {
195 sampleSyncLengthOn = 0;
196 invertReversed = false;
197 arpNoteOn = nullptr;
198 outputMIDIChannelOff.fill(MIDI_CHANNEL_NONE);
199 noteCodeOffPostArp.fill(ARP_NOTE_NONE);
200 glideOutputMIDIChannelOff.fill(MIDI_CHANNEL_NONE);
201 glideNoteCodeOffPostArp.fill(ARP_NOTE_NONE);
202 }
203
204 // These are only valid if doing a note-on, or when releasing the most recently played with the arp off when other
205 // notes are still playing (e.g. for mono note priority)
206 uint32_t sampleSyncLengthOn; // This defaults to zero, or may be overwritten by the caller to the Arp - and then
207 // the Arp itself may override that.
208
209 // If set to true by the arpeggiator, the reverse SAMPLE flag will be inverted for the next voices to be played
210 // and restored back to normal afterwards
211 bool invertReversed;
212
213 ArpNote* arpNoteOn;
214
215 // And these are only valid if doing a note-off
216 std::array<uint8_t, ARP_MAX_INSTRUCTION_NOTES> outputMIDIChannelOff; // For MPE
217 std::array<int16_t, ARP_MAX_INSTRUCTION_NOTES> noteCodeOffPostArp;
218 std::array<uint8_t, ARP_MAX_INSTRUCTION_NOTES> glideOutputMIDIChannelOff; // For MPE
219 std::array<int16_t, ARP_MAX_INSTRUCTION_NOTES> glideNoteCodeOffPostArp;
220};
221
222class ArpeggiatorBase {
223public:
224 virtual ~ArpeggiatorBase() = default;
225 ArpeggiatorBase() {
226 glideNoteCodeCurrentlyOnPostArp.fill(ARP_NOTE_NONE);
227 outputMIDIChannelForGlideNoteCurrentlyOnPostArp.fill(0);
228 }
229
230 virtual void noteOn(ArpeggiatorSettings* settings, int32_t noteCode, int32_t velocity,
231 ArpReturnInstruction* instruction, int32_t fromMIDIChannel, int16_t const* mpeValues) = 0;
232 virtual void noteOff(ArpeggiatorSettings* settings, int32_t noteCodePreArp, ArpReturnInstruction* instruction) = 0;
235 virtual bool handlePendingNotes(ArpeggiatorSettings* settings, ArpReturnInstruction* instruction);
238 virtual bool hasPendingNotes(ArpeggiatorSettings* settings);
239 void render(ArpeggiatorSettings* settings, ArpReturnInstruction* instruction, int32_t numSamples,
240 uint32_t gateThreshold, uint32_t phaseIncrement);
241 int32_t doTickForward(ArpeggiatorSettings* settings, ArpReturnInstruction* instruction, uint32_t ClipCurrentPos,
242 bool currentlyPlayingReversed);
243 void calculateRandomizerAmounts(ArpeggiatorSettings* settings);
244 virtual bool hasAnyInputNotesActive() = 0;
245 virtual void reset() = 0;
246 virtual ArpType getArpType() = 0;
249 static bool arpIsOff(ArpeggiatorSettings* settings) {
250 return (settings == nullptr) || settings->mode == ArpMode::OFF;
251 }
252 ArpNote active_note; // For the currently active note.
253
254 std::array<int16_t, ARP_MAX_INSTRUCTION_NOTES> glideNoteCodeCurrentlyOnPostArp;
255 std::array<uint8_t, ARP_MAX_INSTRUCTION_NOTES> outputMIDIChannelForGlideNoteCurrentlyOnPostArp;
256 uint32_t gatePos = 0;
257 uint8_t lastVelocity = 0;
258
259protected:
260 void calculateNextNoteAndOrOctave(ArpeggiatorSettings* settings, uint8_t numActiveNotes);
261 void setInitialNoteAndOctave(ArpeggiatorSettings* settings, uint8_t numActiveNotes);
262 void resetBase();
263 void resetRatchet();
264 void executeArpStep(ArpeggiatorSettings* settings, uint8_t numActiveNotes, bool isRatchet,
265 uint32_t maxSequenceLength, uint32_t rhythm, bool* shouldCarryOnRhythmNote,
266 bool* shouldPlayNote, bool* shouldPlayBassNote, bool* shouldPlayRandomStep,
267 bool* shouldPlayReverseNote, bool* shouldPlayChordNote);
268 void increasePatternIndexes(uint8_t numStepRepeats);
269 void increaseSequenceIndexes(uint32_t maxSequenceLength, uint32_t rhythm);
270 void maybeSetupNewRatchet(ArpeggiatorSettings* settings);
271 bool evaluateRhythm(uint32_t rhythm, bool isRatchet);
272 bool evaluateNoteProbability(bool isRatchet);
273 bool evaluateBassProbability(bool isRatchet);
274 bool evaluateSwapProbability(bool isRatchet);
275 bool evaluateReverseProbability(bool isRatchet);
276 bool evaluateChordProbability(bool isRatchet);
277 uint32_t calculateSpreadVelocity(uint8_t velocity, int32_t spreadVelocityForCurrentStep);
278 int32_t getOctaveDirection(ArpeggiatorSettings* settings);
279 virtual void switchNoteOn(ArpeggiatorSettings* settings, ArpReturnInstruction* instruction, bool isRatchet) = 0;
280 void switchAnyNoteOff(ArpReturnInstruction* instruction);
281 bool getRandomProbabilityResult(uint32_t value);
282 int8_t getRandomBipolarProbabilityAmount(uint32_t value);
283 int8_t getRandomWeighted2BitsAmount(uint32_t value);
284
285 bool gateCurrentlyActive = false;
286
287 bool playedFirstArpeggiatedNoteYet = false;
288
289 // Playing state
290 uint32_t notesPlayedFromSequence = 0;
291 uint32_t randomNotesPlayedFromOctave = 0;
292
293 // Sequence state
294 int16_t whichNoteCurrentlyOnPostArp; // As in, the index within our list
295 int8_t currentOctave = 0;
296 int8_t currentDirection = 1;
297 int8_t currentOctaveDirection = 1;
298
299 // Rhythm state
300 uint32_t notesPlayedFromRhythm = 0;
301 uint32_t lastNormalNotePlayedFromRhythm = 0;
302
303 // Locked randomizer state
304 uint32_t notesPlayedFromLockedRandomizer = 0;
305
306 // Note probability state
307 bool lastNormalNotePlayedFromNoteProbability = true;
308
309 // Bass probability state
310 bool lastNormalNotePlayedFromBassProbability = false;
311
312 // Swap probability state
313 bool lastNormalNotePlayedFromSwapProbability = false;
314
315 // Reverse probability state
316 bool lastNormalNotePlayedFromReverseProbability = false;
317
318 // Chord probability state
319 bool lastNormalNotePlayedFromChordProbability = false;
320
321 // Step repeat state
322 int32_t stepRepeatIndex = 0;
323
324 // Ratcheting state
325 uint32_t ratchetNotesIndex = 0;
326 uint32_t ratchetNotesMultiplier = 0;
327 uint32_t ratchetNotesCount = 0;
328 bool isRatcheting = false;
329
330 // Glide state
331 bool glideOnNextNoteOff = false;
332
333 // Calculated randomizer values
334 bool isPlayNoteForCurrentStep = true;
335 bool isPlayBassForCurrentStep = false;
336 bool isPlayRandomStepForCurrentStep = false;
337 bool isPlayReverseForCurrentStep = false;
338 bool isPlayChordForCurrentStep = false;
339 bool isPlayRatchetForCurrentStep = false;
340 bool isPlayGlideForCurrentStep = false;
341 int32_t spreadVelocityForCurrentStep = 0;
342 int32_t spreadGateForCurrentStep = 0;
343 int32_t spreadOctaveForCurrentStep = 0;
344 bool resetLockedRandomizerValuesNextTime = false;
345};
346
347class ArpeggiatorForDrum : public ArpeggiatorBase {
348public:
349 ~ArpeggiatorForDrum() override = default;
350 ArpeggiatorForDrum();
351 void noteOn(ArpeggiatorSettings* settings, int32_t noteCode, int32_t velocity, ArpReturnInstruction* instruction,
352 int32_t fromMIDIChannel, int16_t const* mpeValues) override;
353 void noteOff(ArpeggiatorSettings* settings, int32_t noteCodePreArp, ArpReturnInstruction* instruction) override;
354 void reset() override;
355 ArpType getArpType() override { return ArpType::DRUM; }
356 int16_t noteForDrum{0};
357
358 bool invertReversedFromKitArp{false};
359
360protected:
361 void switchNoteOn(ArpeggiatorSettings* settings, ArpReturnInstruction* instruction, bool isRatchet) override;
362 bool hasAnyInputNotesActive() override;
363};
364
365class Arpeggiator : public ArpeggiatorBase {
366public:
367 virtual ~Arpeggiator() = default;
368 Arpeggiator();
369
370 void reset() override;
371 ArpType getArpType() override { return ArpType::SYNTH; }
372
373 void noteOn(ArpeggiatorSettings* settings, int32_t noteCode, int32_t velocity, ArpReturnInstruction* instruction,
374 int32_t fromMIDIChannel, int16_t const* mpeValues) override;
375 void noteOff(ArpeggiatorSettings* settings, int32_t noteCodePreArp, ArpReturnInstruction* instruction) override;
376 bool handlePendingNotes(ArpeggiatorSettings* settings, ArpReturnInstruction* instruction) override;
377 bool hasPendingNotes(ArpeggiatorSettings* settings) override;
378 bool hasAnyInputNotesActive() override;
379 // This array tracks the notes ordered by noteCode
381 // This array tracks the notes as they were played by the user
382 ResizeableArray notesAsPlayed;
383 // This array tracks the notes as ordered by the Pattern note mode
384 ResizeableArray notesByPattern;
385
386protected:
387 void rearrangePatterntArpNotes(ArpeggiatorSettings* settings);
388 void switchNoteOn(ArpeggiatorSettings* settings, ArpReturnInstruction* instruction, bool isRatchet) override;
389 bool anyPending{false};
390};
391
392class ArpeggiatorForKit : public Arpeggiator {
393public:
394 ArpeggiatorForKit() = default;
395 ArpType getArpType() override { return ArpType::KIT; }
396 void removeDrumIndex(ArpeggiatorSettings* arpSettings, int32_t drumIndex);
397};
Definition arpeggiator.h:192
static bool arpIsOff(ArpeggiatorSettings *settings)
Definition arpeggiator.h:249
virtual bool handlePendingNotes(ArpeggiatorSettings *settings, ArpReturnInstruction *instruction)
Definition arpeggiator.cpp:1482
virtual bool hasPendingNotes(ArpeggiatorSettings *settings)
Definition arpeggiator.cpp:1492
Definition arpeggiator.h:48
bool hasPendingNotes(ArpeggiatorSettings *settings) override
Definition arpeggiator.cpp:531
bool handlePendingNotes(ArpeggiatorSettings *settings, ArpReturnInstruction *instruction) override
Definition arpeggiator.cpp:500
Definition storage_manager.h:190
Definition ordered_resizeable_array.h:22
Definition param_manager.h:155
Definition resizeable_array.h:29
Definition storage_manager.h:124
Definition song.h:103
Definition param_set.h:98
Definition arpeggiator.h:188
Definition arpeggiator.h:155
bool isStartablePending()
Definition arpeggiator.h:166