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