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