Deluge Firmware 1.3.0
Build date: 2025.04.16
Loading...
Searching...
No Matches
instrument_clip_view.h
1/*
2 * Copyright © 2014-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 "definitions_cxx.hpp"
21#include "gui/views/clip_view.h"
22#include "hid/button.h"
23#include "model/clip/instrument_clip_minder.h"
24#include "model/iterance/iterance.h"
25#include "model/note/note_row.h"
26#include "modulation/automation/copied_param_automation.h"
27#include "modulation/params/param_node.h"
28#include "util/d_string.h"
29
30class InstrumentClip;
31class NoteRow;
32class Note;
33class Editor;
34class Instrument;
35class Sound;
36class ModControllable;
37class Kit;
38class Drum;
39class SoundDrum;
41class Action;
42class ParamCollection;
43class CopiedNoteRow;
44class ParamNode;
47
49 bool isActive;
50 uint8_t yDisplay;
51 uint8_t xDisplay;
52 bool deleteOnDepress; // Can also mean to delete tail
53 uint8_t intendedVelocity;
54 uint8_t intendedProbability;
55 Iterance intendedIterance;
56 uint8_t intendedFill;
57 bool deleteOnScroll;
58 bool isBlurredSquare;
59 bool mpeCachedYet;
60 StolenParamNodes stolenMPE[kNumExpressionDimensions];
61 uint32_t intendedPos; // For "blurred squares", means start of square
62 uint32_t intendedLength; // For "blurred squares", means length of square
63};
64
65#define MPE_RECORD_LENGTH_FOR_NOTE_EDITING 3
66#define MPE_RECORD_INTERVAL_TIME (kSampleRate >> 2) // 250ms
67static constexpr const char* PATTERN_FILE_VERSION = "0.0.1";
68
69enum class NudgeMode { QUANTIZE, QUANTIZE_ALL };
70
71class InstrumentClipView final : public ClipView, public InstrumentClipMinder {
72public:
73 InstrumentClipView();
74 bool opened() override;
75 void focusRegained() override;
76 void displayOrLanguageChanged() final;
77
78 // BUTTON ACTION button press / release handling
79
80 ActionResult buttonAction(deluge::hid::Button b, bool on, bool inCardRoutine) override;
81 ActionResult handleScaleButtonAction(bool on, bool inCardRoutine);
82
83 // PAD ACTION pad press / release handling
84
85 ActionResult padAction(int32_t x, int32_t y, int32_t velocity) override;
86 ActionResult potentiallyRandomizeDrumSamples();
87 ActionResult potentiallyRandomizeDrumSample(Kit* kit, Drum* drum, char* chosenFilename);
88
89 // SCALE MODE related commands.
90
93 ActionResult commandLearnUserScale();
95 ActionResult commandCycleThroughScales();
97 ActionResult commandFlashRootNote();
99 ActionResult commandEnterScaleModeWithRoot(uint8_t root);
101 ActionResult commandEnterScaleMode();
103 ActionResult commandExitScaleMode();
105 ActionResult commandChangeRootNote(uint8_t yDisplay);
106
107 uint8_t getEditPadPressXDisplayOnScreen(uint8_t yDisplay);
108 void editPadAction(bool state, uint8_t yDisplay, uint8_t xDisplay, uint32_t xZoom);
109 void mutePadPress(uint8_t yDisplay);
110 bool ensureNoteRowExistsForYDisplay(uint8_t yDisplay);
111 void recalculateColours();
112 void recalculateColour(uint8_t yDisplay);
113 ActionResult scrollVertical(int32_t scrollAmount, bool inCardRoutine, bool shiftingNoteRow = false);
114 void reassessAllAuditionStatus();
115 void reassessAuditionStatus(uint8_t yDisplay);
116 uint8_t getVelocityForAudition(uint8_t yDisplay, uint32_t* sampleSyncLength);
117 uint8_t getNumNoteRowsAuditioning();
118 uint8_t oneNoteAuditioning();
119 void offsetNoteCodeAction(int32_t newOffset);
120 int32_t getYVisualFromYDisplay(int32_t yDisplay);
121 int32_t getYVisualWithinOctaveFromYDisplay(int32_t yDisplay);
122 ActionResult auditionPadAction(int32_t velocity, int32_t yDisplay, bool shiftButtonDown);
123 void potentiallyRefreshNoteRowMenu();
124 void enterScaleMode(uint8_t yDisplay = 255);
125 void exitScaleMode();
126 void drawMuteSquare(NoteRow* thisNoteRow, RGB thisImage[], uint8_t thisOccupancyMask[]);
127 void cutAuditionedNotesToOne();
128 ActionResult verticalEncoderAction(int32_t offset, bool inCardRoutine) override;
129 ActionResult horizontalEncoderAction(int32_t offset) override;
130 void fillOffScreenImageStores();
131 void graphicsRoutine() override;
132
133 void drawAuditionSquare(uint8_t yDisplay, RGB thisImage[]);
134 void flashDefaultRootNote();
135 void selectEncoderAction(int8_t offset) override;
136 void doubleClipLengthAction();
137 void setSelectedDrum(Drum* drum, bool shouldRedrawStuff = true, Kit* selectedKit = nullptr,
138 bool shouldSendMidiFeedback = true);
139 bool isDrumAuditioned(Drum* drum);
140 int32_t setupForEnteringScaleMode(int32_t newRootNote = 2147483647, int32_t yDisplay = (kDisplayHeight / 2));
141 int32_t setupForExitingScaleMode();
142 void setupChangingOfRootNote(int32_t newRootNote, int32_t yDisplay = (kDisplayHeight / 2));
143 void deleteDrum(SoundDrum* drum);
144 void cancelAllAuditioning();
145 void modEncoderButtonAction(uint8_t whichModEncoder, bool on) override;
146
147 void tellMatrixDriverWhichRowsContainSomethingZoomable() override;
148 void drawDrumName(Drum* drum, bool justPopUp = false);
149 void getDrumName(Drum* drum, StringBuf& drumName);
150 void notifyPlaybackBegun() override;
151 void openedInBackground();
152 bool renderMainPads(uint32_t whichRows, RGB image[][kDisplayWidth + kSideBarWidth],
153 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], bool drawUndefinedArea = true) override;
154 void performActualRender(uint32_t whichRows, RGB* image, uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth],
155 int32_t xScroll, uint32_t xZoom, int32_t renderWidth, int32_t imageWidth,
156 bool drawUndefinedArea = true);
157 bool renderSidebar(uint32_t whichRows, RGB image[][kDisplayWidth + kSideBarWidth],
158 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth]) override;
159
160 void playbackEnded() override;
161 void scrollFinished() override;
162 void clipNeedsReRendering(Clip* clip) override;
163 void modEncoderAction(int32_t whichModEncoder, int32_t offset) override;
164 ClipMinder* toClipMinder() override { return this; }
165 void reportMPEInitialValuesForNoteEditing(ModelStackWithNoteRow* modelStack, int16_t const* mpeValues);
166 void reportMPEValueForNoteEditing(int32_t expressionDimension, int32_t value);
167 void reportNoteOffForMPEEditing(ModelStackWithNoteRow* modelStack);
168 void dontDeleteNotesOnDepress();
169
170 void tempoEncoderAction(int8_t offset, bool encoderButtonPressed, bool shiftButtonPressed);
171 void sendAuditionNote(bool on, uint8_t yDisplay, uint8_t velocity, uint32_t sampleSyncLength);
172
173 // made these public so they can be accessed by the automation clip view
174 void setLedStates();
175 uint32_t getSquareWidth(int32_t square, int32_t effectiveLength);
176 void drawNoteCode(uint8_t yDisplay);
177 void createNewInstrument(OutputType instrumentType, bool is_fm = false);
178 void changeOutputType(OutputType newOutputType);
179 Sound* getSoundForNoteRow(NoteRow* noteRow, ParamManagerForTimeline** getParamManager);
180 void someAuditioningHasEnded(bool recalculateLastAuditionedNoteOnScreen);
181 bool getAffectEntire() override;
182 void checkIfAllEditPadPressesEnded(bool mayRenderSidebar = true);
183 void endEditPadPress(uint8_t i);
184 void endAllEditPadPresses();
185 void copyAutomation(int32_t whichModEncoder, int32_t navSysId = NAVIGATION_CLIP);
186 void pasteAutomation(int32_t whichModEncoder, int32_t navSysId = NAVIGATION_CLIP);
187 // made these public so they can be accessed by the automation clip view
188
189 void renderOLED(deluge::hid::display::oled_canvas::Canvas& canvas) override {
190 InstrumentClipMinder::renderOLED(canvas);
191 }
192
193 CopiedParamAutomation copiedParamAutomation;
194 // Sometimes the user will want to hold an audition pad without actually sounding the note, by holding an encoder
195 bool auditioningSilently;
196 // Archaic leftover feature that users wouldn't let me get rid of
197 bool fileBrowserShouldNotPreview;
198
199 int16_t mpeValuesAtHighestPressure[MPE_RECORD_LENGTH_FOR_NOTE_EDITING][kNumExpressionDimensions];
200 int16_t mpeMostRecentPressure;
201 uint32_t mpeRecordLastUpdateTime;
202
203 // made these public so they can be accessed by the automation clip view
204 EditPadPress editPadPresses[kEditPadPressBufferSize];
205 uint8_t lastAuditionedVelocityOnScreen[kDisplayHeight]; // 255 seems to mean none
206 uint8_t auditionPadIsPressed[kDisplayHeight];
207 uint8_t numEditPadPressesPerNoteRowOnScreen[kDisplayHeight];
208 uint8_t lastAuditionedYDisplay;
209 uint8_t numEditPadPresses;
210 uint32_t timeLastEditPadPress;
211 uint32_t timeFirstEditPadPress;
212 // Only to be looked at if shouldIgnoreHorizontalScrollKnobActionIfNotAlsoPressedForThisNotePress is true after they
213 // rotated a NoteRow and might now be wanting to instead edit its length after releasing the knob
214 uint32_t timeHorizontalKnobLastReleased;
215 bool shouldIgnoreVerticalScrollKnobActionIfNotAlsoPressedForThisNotePress;
216 bool shouldIgnoreHorizontalScrollKnobActionIfNotAlsoPressedForThisNotePress;
217 // Because in this case we can assume that if they press a main pad while auditioning, they're not intending to do
218 // that shortcut into the SoundEditor!
219 bool editedAnyPerNoteRowStuffSinceAuditioningBegan;
220 // made these public so they can be accessed by the automation clip view
221
222 // ui
223 UIType getUIType() override { return UIType::INSTRUMENT_CLIP; }
224
225 // note editor
226 bool enterNoteEditor();
227 void exitNoteEditor();
228 void handleNoteEditorEditPadAction(int32_t x, int32_t y, int32_t on);
229 void deselectNoteAndGoUpOneLevel();
230 ActionResult handleNoteEditorVerticalEncoderAction(int32_t offset, bool inCardRoutine);
231 ActionResult handleNoteEditorHorizontalEncoderAction(int32_t offset);
232 ActionResult handleNoteEditorButtonAction(deluge::hid::Button b, bool on, bool inCardRoutine);
233
234 SquareInfo gridSquareInfo[kDisplayHeight][kDisplayWidth];
235 int32_t lastSelectedNoteXDisplay;
236 int32_t lastSelectedNoteYDisplay;
237
238 // adjust note parameters
239 void adjustVelocity(int32_t velocityChange);
240 void updateVelocityValue(int32_t& velocityValue, int32_t newVelocity);
241 void displayVelocity(int32_t velocityValue, int32_t velocityChange);
242 void popupVelocity(char const* displayString);
243
244 void adjustNoteProbabilityWithOffset(int32_t offset);
245 void adjustNoteIteranceWithOffset(int32_t offset, bool allowTogglingBetweenPresetsAndCustom = true);
246 void adjustNoteIteranceWithFinalValue(Iterance finalValue);
247 void adjustNoteFillWithOffset(int32_t offset);
248 Note* getLeftMostNotePressed();
249 void adjustNoteParameterValue(int32_t withOffset, int32_t withFinalValue, int32_t changeType,
250 int32_t parameterMinValue, int32_t parameterMaxValue,
251 bool allowTogglingBetweenPresetsAndCustom = true);
252
253 // other note functions
254 void editNoteRepeat(int32_t offset);
255
256 // blink selected note
257 void blinkSelectedNote(int32_t whichMainRows = 0);
258 void resetSelectedNoteBlinking();
259
260 // note row editor
261 bool enterNoteRowEditor();
262 void exitNoteRowEditor();
263 bool handleNoteRowEditorPadAction(int32_t x, int32_t y, int32_t on);
264 bool handleNoteRowEditorMainPadAction(int32_t x, int32_t y, int32_t on);
265 void handleNoteRowEditorAuditionPadAction(int32_t y);
266 void copyNotesToFile(Serializer& writer, bool selectedDrumOnly = false);
267 Error pasteNotesFromFile(Deserializer& reader, bool overwriteExisting, bool noScaling, bool previewOnly,
268 bool selectedDrumOnly);
269 void patternPreview();
270 void patternClear();
271 ActionResult handleNoteRowEditorVerticalEncoderAction(int32_t offset, bool inCardRoutine);
272 ActionResult handleNoteRowEditorHorizontalEncoderAction(int32_t offset);
273 ActionResult handleNoteRowEditorButtonAction(deluge::hid::Button b, bool on, bool inCardRoutine);
274
275 // adjust note row parameters
276 int32_t setNoteRowProbabilityWithOffset(int32_t offset);
277 int32_t setNoteRowIteranceWithOffset(int32_t offset, bool allowTogglingBetweenPresetsAndCustom = true);
278 int32_t setNoteRowIteranceWithFinalValue(Iterance finalValue);
279 int32_t setNoteRowFillWithOffset(int32_t offset);
280 int32_t setNoteRowParameterValue(int32_t withOffset, int32_t withFinalValue, int32_t changeType,
281 int32_t parameterMinValue, int32_t parameterMaxValue,
282 bool allowTogglingBetweenPresetsAndCustom = true);
283 // other note row functions
284 ModelStackWithNoteRow* createNoteRowForYDisplay(ModelStackWithTimelineCounter* modelStack, int32_t yDisplay);
285 ModelStackWithNoteRow* getOrCreateNoteRowForYDisplay(ModelStackWithTimelineCounter* modelStack, int32_t yDisplay);
286 void editNumEuclideanEvents(ModelStackWithNoteRow* modelStack, int32_t offset, int32_t yDisplay);
287 void editNoteRowLength(int32_t offset);
288 void rotateNoteRowHorizontally(int32_t offset);
289 void editNoteRowLength(ModelStackWithNoteRow* modelStack, int32_t offset, int32_t yDisplay);
290 void noteRowChanged(InstrumentClip* clip, NoteRow* noteRow) override;
291
292 // blink selected note row
293 void blinkSelectedNoteRow(int32_t whichMainRows = 0);
294 void resetSelectedNoteRowBlinking();
295 bool noteRowFlashOn;
296 bool noteRowBlinking;
297
298 const char* getFillString(uint8_t fill);
299
300 // public for velocity keyboard view to access
301 void enterDrumCreator(ModelStackWithNoteRow* modelStack, bool doRecording = false);
302
303private:
304 bool doneAnyNudgingSinceFirstEditPadPress;
305 bool offsettingNudgeNumberDisplay;
306
307 uint8_t flashScaleModeLedErrorCount;
308
309 Drum* selectedDrum;
310
311 Drum* drumForNewNoteRow;
312 uint8_t yDisplayOfNewNoteRow;
313
314 int32_t quantizeAmount;
315 uint32_t timeSongButtonPressed;
316
317 std::array<RGB, kDisplayHeight> rowColour;
318 std::array<RGB, kDisplayHeight> rowTailColour;
319 std::array<RGB, kDisplayHeight> rowBlurColour;
320
321 // note functions
322 void nudgeNotes(int32_t offset);
323 void displayProbability(uint8_t probability, bool prevBase);
324 void displayIterance(Iterance iterance);
325
326 // note row functions
327 void copyNotes(Serializer* writer, bool selectedDrumOnly = false);
328 void pasteNotes(bool overwriteExisting = true, bool pasteFromFile = false, bool noScaling = false,
329 bool previewOnly = false, bool selectedDrumOnly = false);
330 void deleteCopiedNoteRows();
331 CopiedNoteRow* firstCopiedNoteRow;
332 int32_t copiedScreenWidth;
333 ScaleType copiedScaleType;
334 int16_t copiedYNoteOfBottomRow;
335
336 void rotateNoteRowHorizontally(ModelStackWithNoteRow* modelStack, int32_t offset, int32_t yDisplay,
337 bool shouldDisplayDirectionEvenIfNoNoteRow = false);
338
339 Drum* getNextDrum(Drum* oldDrum, bool mayBeNone = false);
340 Drum* flipThroughAvailableDrums(int32_t newOffset, Drum* drum, bool mayBeNone = false);
341 NoteRow* createNewNoteRowForKit(ModelStackWithTimelineCounter* modelStack, int32_t yDisplay,
342 int32_t* getIndex = nullptr);
343 void createDrumForAuditionedNoteRow(DrumType drumType);
344 bool isRowAuditionedByInstrument(int32_t yDisplay);
345
346 // TEMPO encoder commands
347 void commandQuantizeNotes(int8_t offset, NudgeMode nudgeMode);
348 void commandStartQuantize(int8_t offset, NudgeMode nudgeMode);
349 ActionResult commandStopQuantize(int32_t y);
350 void silenceAllAuditions();
351
352 // auditionPadAction functions
353 Drum* getAuditionedDrum(int32_t velocity, int32_t yDisplay, bool shiftButtonDown, Instrument* instrument,
354 ModelStackWithTimelineCounter* modelStackWithTimelineCounter,
355 ModelStackWithNoteRow* modelStackWithNoteRowOnCurrentClip);
356 void potentiallyUpdateMultiRangeMenu(int32_t velocity, int32_t yDisplay, Instrument* instrument);
357 void recordNoteOnEarly(int32_t velocity, int32_t yDisplay, Instrument* instrument, bool isKit,
358 ModelStackWithNoteRow* modelStackWithNoteRowOnCurrentClip, Drum* drum);
359 void recordNoteOn(int32_t velocity, int32_t yDisplay, Instrument* instrument,
360 ModelStackWithTimelineCounter* modelStackWithTimelineCounter,
361 ModelStackWithNoteRow* modelStackWithNoteRowOnCurrentClip);
362 void recordNoteOff(int32_t yDisplay, ModelStackWithNoteRow* modelStackWithNoteRowOnCurrentClip);
363 NoteRow* getNoteRowOnActiveClip(int32_t yDisplay, Instrument* instrument, bool clipIsActiveOnInstrument,
364 ModelStackWithNoteRow* modelStackWithNoteRowOnCurrentClip, Drum* drum);
365 int32_t getVelocityToSound(int32_t velocity);
366 bool startAuditioningRow(int32_t velocity, int32_t yDisplay, bool shiftButtonDown, bool isKit,
367 NoteRow* noteRowOnActiveClip, Drum* drum);
368 void finishAuditioningRow(int32_t yDisplay, ModelStackWithNoteRow* modelStack, NoteRow* noteRowOnActiveClip);
369};
370
371extern InstrumentClipView instrumentClipView;
Definition action.h:75
Definition clip_minder.h:23
Definition clip.h:46
Definition copied_note_row.h:23
Definition drum.h:44
Definition instrument_clip_view.h:71
ClipMinder * toClipMinder() override
Definition instrument_clip_view.h:164
ActionResult commandCycleThroughScales()
Cycle through preset scales. SHIFT + SCALE in scale mode.
Definition instrument_clip_view.cpp:205
ActionResult commandLearnUserScale()
Definition instrument_clip_view.cpp:190
ActionResult commandExitScaleMode()
Exit scale mdoe. SCALE when in scale mode.
Definition instrument_clip_view.cpp:254
ActionResult commandChangeRootNote(uint8_t yDisplay)
Change current root note. AUDITION + SCALE or SCALE + AUDITION in scale mod.
Definition instrument_clip_view.cpp:230
ActionResult commandFlashRootNote()
Flash the current root note. Part of SCALE down.
Definition instrument_clip_view.cpp:214
ActionResult commandEnterScaleMode()
Enter scale mode. SCALE when in chromatic mode.
Definition instrument_clip_view.cpp:249
ActionResult commandEnterScaleModeWithRoot(uint8_t root)
Enter scale mode with selected root. AUDITION + SCALE or SCALE + AUDITION in schromatic mode.
Definition instrument_clip_view.cpp:224
Definition instrument_clip.h:48
Definition instrument.h:45
Definition kit.h:34
Definition mod_controllable.h:40
Definition model_stack.h:189
Definition model_stack.h:129
Definition note_row.h:98
Definition note.h:24
Definition param_collection.h:39
Definition param_manager.h:174
Definition param_node.h:23
This class represents the colour format most used by the Deluge globally.
Definition rgb.h:14
Definition sound_drum.h:28
Definition sound.h:71
Definition d_string.h:106
Definition instrument_clip_view.h:48
Definition iterance.h:23
Definition param_node.h:45