Deluge Firmware 1.3.0
Build date: 2025.09.14
Loading...
Searching...
No Matches
instrument_clip.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/ui/keyboard/state_data.h"
22#include "gui/views/instrument_clip_view.h"
23#include "model/note/note_row_vector.h"
24#include "modulation/arpeggiator.h"
25
26class Song;
27
28class NoteRow;
29class InstrumentClip;
30class Instrument;
31class ModControllable;
32class Drum;
34class Sound;
35class Note;
36class Action;
38class TimelineView;
42
43struct PendingNoteOn;
44
45enum class VerticalNudgeType { ROW, OCTAVE };
46
47class InstrumentClip final : public Clip {
48public:
49 explicit InstrumentClip(Song* song = nullptr);
50 ~InstrumentClip() override;
51 void increaseLengthWithRepeats(ModelStackWithTimelineCounter* modelStack, int32_t newLength,
52 IndependentNoteRowLengthIncrease independentNoteRowInstruction,
53 bool completelyRenderOutIterationDependence = false,
54 Action* action = nullptr) override;
55 void halveNoteRowsWithIndependentLength(ModelStackWithTimelineCounter* modelStack);
56 void repeatOrChopToExactLength(ModelStackWithTimelineCounter* modelStack, int32_t newLength);
57 void processCurrentPos(ModelStackWithTimelineCounter* modelStack, uint32_t posIncrement) override;
58 bool renderAsSingleRow(ModelStackWithTimelineCounter* modelStack, TimelineView* editorScreen, int32_t xScroll,
59 uint32_t xZoom, RGB* image, uint8_t occupancyMask[], bool addUndefinedArea,
60 int32_t noteRowIndexStart = 0, int32_t noteRowIndexEnd = 2147483647, int32_t xStart = 0,
61 int32_t xEnd = kDisplayWidth, bool allowBlur = true, bool drawRepeats = false) override;
62 void toggleNoteRowMute(ModelStackWithNoteRow* modelStack);
63 RGB getMainColourFromY(int32_t yNote, int8_t);
64 void stopAllNotesPlaying(ModelStackWithTimelineCounter* modelStack, bool actuallySoundChange = true);
65 void resumePlayback(ModelStackWithTimelineCounter* modelStack, bool mayMakeSound = true) override;
66 void setPos(ModelStackWithTimelineCounter* modelStack, int32_t newPos,
67 bool useActualPosForParamManagers = true) override;
68 void replaceMusicalMode(const ScaleChange& changes, ModelStackWithTimelineCounter* modelStack);
69 void seeWhatNotesWithinOctaveArePresent(NoteSet&, MusicalKey);
70 void transpose(int32_t, ModelStackWithTimelineCounter* modelStack);
71 void nudgeNotesVertically(int32_t direction, VerticalNudgeType, ModelStackWithTimelineCounter* modelStack);
72 void expectNoFurtherTicks(Song* song, bool actuallySoundChange = true) override;
73 Error clone(ModelStackWithTimelineCounter* modelStack, bool shouldFlattenReversing = false) const override;
74 NoteRow* createNewNoteRowForYVisual(int32_t, Song* song);
75 int32_t getYVisualFromYNote(int32_t, Song* song);
76 int32_t getYNoteFromYVisual(int32_t, Song* song);
77 int32_t getYNoteFromYDisplay(int32_t yDisplay, Song* song);
78 int32_t guessRootNote(Song* song, int32_t previousRoot);
79 int32_t getNumNoteRows();
80 void ensureInaccessibleParamPresetValuesWithoutKnobsAreZero(ModelStackWithTimelineCounter* modelStack,
81 Sound* sound);
82 bool deleteSoundsWhichWontSound(Song* song) override;
83 void setBackedUpParamManagerMIDI(ParamManagerForTimeline* newOne);
84 void restoreBackedUpParamManagerMIDI(ModelStackWithModControllable* modelStack);
85 int32_t getNoteRowId(NoteRow* noteRow, int32_t noteRowIndex);
86 NoteRow* getNoteRowFromId(int32_t id);
88 bool shiftHorizontally(ModelStackWithTimelineCounter* modelStack, int32_t amount, bool shiftAutomation,
89 bool shiftSequenceAndMPE) override;
90 bool isEmpty(bool displayPopup = true) override;
91 bool containsAnyNotes();
92 ModelStackWithNoteRow* getNoteRowOnScreen(int32_t yDisplay, ModelStackWithTimelineCounter* modelStack);
93 NoteRow* getNoteRowOnScreen(int32_t yDisplay, Song* song, int32_t* getIndex = nullptr);
94 bool currentlyScrollableAndZoomable() override;
95 void recordNoteOn(ModelStackWithNoteRow* modelStack, int32_t velocity, bool forcePos0 = false,
96 int16_t const* mpeValuesOrNull = nullptr, int32_t fromMIDIChannel = MIDI_CHANNEL_NONE);
97 void recordNoteOff(ModelStackWithNoteRow* modelStack, int32_t velocity = kDefaultLiftValue);
98
99 void copyBasicsFrom(Clip const* otherClip) override;
100
101 ArpeggiatorSettings arpSettings;
102
103 ParamManagerForTimeline backedUpParamManagerMIDI;
104
105 bool inScaleMode; // Probably don't quiz this directly - call isScaleModeClip() instead
106
107 int32_t yScroll;
108
109 // TODO: Unscope this once namespacing is done
111
112 int32_t ticksTilNextNoteRowEvent{};
113 int32_t noteRowsNumTicksBehindClip{};
114
115 LearnedMIDI soundMidiCommand; // This is now handled by the Instrument, but for loading old songs, we need to
116 // capture and store this
117
118 NoteRowVector noteRows;
119
120 bool wrapEditing;
121 uint32_t wrapEditLevel{};
122
123 // These *only* store a valid preset number for the instrument-types that the Clip is not currently on
124 int8_t backedUpInstrumentSlot[4]{};
125 int8_t backedUpInstrumentSubSlot[4]{};
126 String backedUpInstrumentName[2];
127 String backedUpInstrumentDirPath[2];
128
129 bool affectEntire;
130
131 bool onKeyboardScreen;
132
133 uint8_t midiBank; // 128 means none
134 uint8_t midiSub; // 128 means none
135 uint8_t midiPGM; // 128 means none
136
137 OutputType outputTypeWhileLoading; // For use only while loading song
138
139 void lengthChanged(ModelStackWithTimelineCounter* modelStack, int32_t oldLength, Action* action = nullptr) override;
140 NoteRow* createNewNoteRowForKit(ModelStackWithTimelineCounter* modelStack, bool atStart,
141 int32_t* getIndex = nullptr);
142 Error changeInstrument(ModelStackWithTimelineCounter* modelStack, Instrument* newInstrument,
143 ParamManagerForTimeline* paramManager, InstrumentRemoval instrumentRemovalInstruction,
144 InstrumentClip* favourClipForCloningParamManager = nullptr,
145 bool keepNoteRowsWithMIDIInput = true, bool giveMidiAssignmentsToNewInstrument = false);
146 void detachFromOutput(ModelStackWithTimelineCounter* modelStack, bool shouldRememberDrumName,
147 bool shouldDeleteEmptyNoteRowsAtEndOfList = false, bool shouldRetainLinksToSounds = false,
148 bool keepNoteRowsWithMIDIInput = true, bool shouldGrabMidiCommands = false,
149 bool shouldBackUpExpressionParamsToo = true) override;
150 void assignDrumsToNoteRows(ModelStackWithTimelineCounter* modelStack, bool shouldGiveMIDICommandsToDrums = false,
151 int32_t numNoteRowsPreviouslyDeletedFromBottom = 0);
152 void unassignAllNoteRowsFromDrums(ModelStackWithTimelineCounter* modelStack, bool shouldRememberDrumNames,
153 bool shouldRetainLinksToSounds, bool shouldGrabMidiCommands,
154 bool shouldBackUpExpressionParamsToo);
155 Error readFromFile(Deserializer& reader, Song* song) override;
156 void writeDataToFile(Serializer& writer, Song* song) override;
157 void prepNoteRowsForExitingKitMode(Song* song);
158 void deleteNoteRow(ModelStackWithTimelineCounter* modelStack, int32_t i);
159 int16_t getTopYNote();
160 int16_t getBottomYNote();
161 uint32_t getWrapEditLevel();
162 ModelStackWithNoteRow* getNoteRowForYNote(int32_t yNote, ModelStackWithTimelineCounter* modelStack);
163 NoteRow* getNoteRowForYNote(int32_t, int32_t* getIndex = nullptr);
164 ModelStackWithNoteRow* getNoteRowForSelectedDrum(ModelStackWithTimelineCounter* modelStack);
165 ModelStackWithNoteRow* getNoteRowForDrum(ModelStackWithTimelineCounter* modelStack, Drum* drum);
166 NoteRow* getNoteRowForDrum(Drum* drum, int32_t* getIndex = nullptr);
167 ModelStackWithNoteRow* getOrCreateNoteRowForYNote(int32_t yNote, ModelStackWithTimelineCounter* modelStack,
168 Action* action = nullptr, bool* scaleAltered = nullptr);
169
170 bool hasSameInstrument(InstrumentClip* otherClip);
171 bool isScaleModeClip();
172 bool allowNoteTails(ModelStackWithNoteRow* modelStack);
173 Error setAudioInstrument(Instrument* newInstrument, Song* song, bool shouldNotifyInstrument,
174 ParamManager* newParamManager, InstrumentClip* favourClipForCloningParamManager = nullptr);
175
176 void expectEvent() override;
177 int32_t getDistanceToNextNote(Note* givenNote, ModelStackWithNoteRow* modelStack);
178 void reGetParameterAutomation(ModelStackWithTimelineCounter* modelStack) override;
179 void stopAllNotesForMIDIOrCV(ModelStackWithTimelineCounter* modelStack);
180 void sendMIDIPGM();
181 void noteRemovedFromMode(int32_t yNoteWithinOctave, Song* song);
182 void clear(Action* action, ModelStackWithTimelineCounter* modelStack, bool clearAutomation,
183 bool clearSequenceAndMPE) override;
184 bool doesProbabilityExist(int32_t apartFromPos, int32_t probability, int32_t secondProbability = -1);
185 void clearArea(ModelStackWithTimelineCounter* modelStack, int32_t startPos, int32_t endPos, Action* action);
186 ScaleType getScaleType();
187 void backupPresetSlot();
188 void setPosForParamManagers(ModelStackWithTimelineCounter* modelStack, bool useActualPos = true) override;
189 ModelStackWithNoteRow* getNoteRowForDrumName(ModelStackWithTimelineCounter* modelStack, char const* name);
190 void compensateVolumeForResonance(ModelStackWithTimelineCounter* modelStack);
191 Error undoDetachmentFromOutput(ModelStackWithTimelineCounter* modelStack) override;
192 Error setNonAudioInstrument(Instrument* newInstrument, Song* song, ParamManager* newParamManager = nullptr);
193 Error setInstrument(Instrument* newInstrument, Song* song, ParamManager* newParamManager,
194 InstrumentClip* favourClipForCloningParamManager = nullptr);
195 void deleteOldDrumNames();
196 void ensureScrollWithinKitBounds();
197 bool isScrollWithinRange(int32_t scrollAmount, int32_t newYNote);
198 Error appendClip(ModelStackWithTimelineCounter* thisModelStack,
199 ModelStackWithTimelineCounter* otherModelStack) override;
200 void instrumentBeenEdited() override;
201 Instrument* changeOutputType(ModelStackWithTimelineCounter* modelStack, OutputType newOutputType);
202 Error transferVoicesToOriginalClipFromThisClone(ModelStackWithTimelineCounter* modelStackOriginal,
203 ModelStackWithTimelineCounter* modelStackClone) override;
204 void getSuggestedParamManager(Clip* newClip, ParamManagerForTimeline** suggestedParamManager,
205 Sound* sound) override;
206 ParamManagerForTimeline* getCurrentParamManager() override;
207 Error claimOutput(ModelStackWithTimelineCounter* modelStack) override;
208 char const* getXMLTag() override { return "instrumentClip"; }
209 void finishLinearRecording(ModelStackWithTimelineCounter* modelStack, Clip* nextPendingLoop,
210 int32_t buttonLatencyForTempolessRecord) override;
211 Error beginLinearRecording(ModelStackWithTimelineCounter* modelStack, int32_t buttonPressLatency) override;
212 Clip* cloneAsNewOverdub(ModelStackWithTimelineCounter* modelStack, OverDubType newOverdubNature) override;
213 bool isAbandonedOverdub() override;
214 void quantizeLengthForArrangementRecording(ModelStackWithTimelineCounter* modelStack, int32_t lengthSoFar,
215 uint32_t timeRemainder, int32_t suggestedLength,
216 int32_t alternativeLongerLength) override;
217 void setupAsNewKitClipIfNecessary(ModelStackWithTimelineCounter* modelStack);
218 bool getCurrentlyRecordingLinearly() override;
219 void abortRecording() override;
220 void yDisplayNoLongerAuditioning(int32_t yDisplay, Song* song);
221 void shiftOnlyOneNoteRowHorizontally(ModelStackWithNoteRow* modelStack, int32_t shiftAmount, bool shiftAutomation,
222 bool shiftSequenceAndMPE);
223 int32_t getMaxLength() override;
224 bool hasAnyPitchExpressionAutomationOnNoteRows();
225 ModelStackWithNoteRow* duplicateModelStackForClipBeingRecordedFrom(ModelStackWithNoteRow* modelStack,
226 char* otherModelStackMemory);
227 void incrementPos(ModelStackWithTimelineCounter* modelStack, int32_t numTicks) override;
228
229 // ----- TimelineCounter implementation -------
230 void getActiveModControllable(ModelStackWithTimelineCounter* modelStack) override;
231
232 bool renderSidebar(uint32_t whichRows = 0, RGB image[][kDisplayWidth + kSideBarWidth] = nullptr,
233 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth] = nullptr) override {
234 return instrumentClipView.renderSidebar(whichRows, image, occupancyMask);
235 };
236
237protected:
238 void posReachedEnd(ModelStackWithTimelineCounter* modelStack) override;
239 bool wantsToBeginLinearRecording(Song* song) override;
240 bool cloneOutput(ModelStackWithTimelineCounter* modelStack) override;
241 void pingpongOccurred(ModelStackWithTimelineCounter* modelStack) override;
242
243private:
244 InstrumentClip* instrumentWasLoadedByReferenceFromClip{};
245
246 void deleteEmptyNoteRowsAtEitherEnd(bool onlyIfNoDrum, ModelStackWithTimelineCounter* modelStack,
247 bool mustKeepLastOne = true, bool keepOnesWithMIDIInput = true);
248 void sendPendingNoteOn(ModelStackWithTimelineCounter* modelStack, PendingNoteOn* pendingNoteOn);
249 Error undoUnassignmentOfAllNoteRowsFromDrums(ModelStackWithTimelineCounter* modelStack);
250 void deleteBackedUpParamManagerMIDI();
251 bool possiblyDeleteEmptyNoteRow(NoteRow* noteRow, bool onlyIfNoDrum, Song* song, bool onlyIfNonNumeric = false,
252 bool keepIfHasMIDIInput = true);
253 void actuallyDeleteEmptyNoteRow(ModelStackWithNoteRow* modelStack);
254 void prepareToEnterKitMode(Song* song);
255 Error readMIDIParamsFromFile(Deserializer& reader, int32_t readAutomationUpToPos);
256
257 bool lastProbabilities[kNumProbabilityValues]{};
258 int32_t lastProbabiltyPos[kNumProbabilityValues]{};
259 bool currentlyRecordingLinearly;
260};
Definition action.h:75
Definition arpeggiator.h:46
Definition storage_manager.h:185
Definition drum.h:44
Definition instrument_clip.h:47
bool shiftHorizontally(ModelStackWithTimelineCounter *modelStack, int32_t amount, bool shiftAutomation, bool shiftSequenceAndMPE) override
Return true if successfully shifted. Instrument clips always succeed.
Definition instrument_clip.cpp:3431
Definition instrument.h:44
Definition learned_midi.h:30
Definition mod_controllable.h:40
Definition model_stack.h:225
Definition model_stack.h:189
Definition model_stack.h:129
Definition musical_key.h:10
Definition note_row_vector.h:24
Definition note_row.h:98
Definition note_set.h:20
Definition note.h:24
Definition param_manager.h:174
Definition param_manager.h:45
This class represents the colour format most used by the Deluge globally.
Definition rgb.h:14
Definition scale_change.h:5
Definition storage_manager.h:119
Definition song.h:104
Definition sound.h:71
Definition d_string.h:41
Definition timeline_view.h:27
Definition note_row.h:71