103class Song final :
public TimelineCounter {
107 bool mayDoubleTempo();
108 bool ensureAtLeastOneSessionClip();
109 void transposeAllScaleModeClips(int32_t interval);
110 void transposeAllScaleModeClips(int32_t offset,
bool chromatic);
111 bool anyScaleModeClips();
112 void changeMusicalMode(uint8_t yVisualWithinOctave, int8_t change);
113 void rotateMusicalMode(int8_t change);
114 void replaceMusicalMode(
const ScaleChange& changes,
bool affectMIDITranspose);
115 int32_t getYVisualFromYNote(int32_t yNote,
bool inKeyMode);
116 int32_t getYVisualFromYNote(int32_t yNote,
bool inKeyMode,
const MusicalKey& key);
117 int32_t getYNoteFromYVisual(int32_t yVisual,
bool inKeyMode);
118 int32_t getYNoteFromYVisual(int32_t yVisual,
bool inKeyMode,
const MusicalKey& key);
119 bool mayMoveModeNote(int16_t yVisualWithinOctave, int8_t newOffset);
121 void setupPatchingForAllParamManagersForDrum(
SoundDrum* drum);
122 void setupPatchingForAllParamManagersForInstrument(
SoundInstrument* sound);
123 void grabVelocityToLevelFromMIDICableAndSetupPatchingForAllParamManagersForInstrument(
MIDICable& cable,
125 void grabVelocityToLevelFromMIDICableAndSetupPatchingForAllParamManagersForDrum(
MIDICable& cable,
SoundDrum* drum,
127 void grabVelocityToLevelFromMIDICableAndSetupPatchingForEverything(
MIDICable& cable);
128 void getCurrentRootNoteAndScaleName(
StringBuf& buffer);
129 void displayCurrentRootNoteAndScaleName();
153 void setTempoFromNumSamples(
double newTempoSamples,
bool shouldLogAction);
155 void setBPM(
float tempoBPM,
bool shouldLogAction);
156 void setTempoFromParams(int32_t magnitude, int8_t whichValue,
bool shouldLogAction);
157 void deleteSoundsWhichWontSound();
158 void writeTemplateSong(
const char* templateSong);
160 deleteClipObject(
Clip* clip,
bool songBeingDestroyedToo =
false,
161 InstrumentRemoval instrumentRemovalInstruction = InstrumentRemoval::DELETE_OR_HIBERNATE_IF_UNUSED);
162 int32_t getMaxMIDIChannelSuffix(int32_t channel);
163 void addOutput(
Output* output,
bool atStart =
true);
164 void deleteOutputThatIsInMainList(
Output* output,
bool stopAnyAuditioningFirst =
true);
165 void markAllInstrumentsAsEdited();
166 Instrument* getInstrumentFromPresetSlot(OutputType outputType, int32_t presetNumber, int32_t presetSubSlotNumber,
167 char const* name,
char const* dirPath,
bool searchHibernatingToo =
true,
168 bool searchNonHibernating =
true);
170 void setupPatchingForAllParamManagers();
171 void replaceInstrument(
Instrument* oldInstrument,
Instrument* newInstrument,
bool keepNoteRowsWithMIDIInput =
true);
172 void stopAllMIDIAndGateNotesPlaying();
173 void stopAllAuditioning();
174 void deleteOrHibernateOutput(
Output* output);
175 Instrument* getNonAudioInstrumentToSwitchTo(OutputType newOutputType, Availability availabilityRequirement,
176 int16_t newSlot, int8_t newSubSlot,
bool* instrumentWasAlreadyInSong);
177 void removeSessionClipLowLevel(
Clip* clip, int32_t clipIndex);
178 void changeSwingInterval(int32_t newValue);
179 int32_t convertSyncLevelFromFileValueToInternalValue(int32_t fileValue);
180 int32_t convertSyncLevelFromInternalValueToFileValue(int32_t internalValue);
182 void setSongFullPath(
const char* fullPath);
183 int32_t getInputTickMagnitude()
const {
return insideWorldTickMagnitude + insideWorldTickMagnitudeOffsetFromBPM; }
192 firstHibernatingInstrument;
198 int32_t xScrollForReturnToSongView;
199 int32_t xZoomForReturnToSongView;
201 uint32_t tripletsLevel;
203 uint64_t timePerTimerTickBig;
204 int32_t divideByTimePerTimerTick;
211 int32_t insideWorldTickMagnitude;
215 int32_t insideWorldTickMagnitudeOffsetFromBPM;
218 uint8_t swingInterval;
220 Section sections[kMaxNumSections];
223 std::bitset<NUM_PRESET_SCALES> disabledPresetScales;
231 SessionLayoutType sessionLayout = FlashStorage::defaultSessionLayout;
232 int32_t songGridScrollX = 0;
233 int32_t songGridScrollY = 0;
234 int32_t songViewYScroll;
235 int32_t arrangementYScroll;
237 uint8_t sectionToReturnToAfterSongEnd;
239 bool wasLastInArrangementEditor;
240 int32_t lastClipInstanceEnteredStartPos;
243 bool arrangerAutoScrollModeActive;
247 bool outputClipInstanceListIsCurrentlyInvalid;
250 bool paramsInAutomationMode;
252 bool inClipMinderViewOnLoad;
254 int32_t unautomatedParamValues[deluge::modulation::params::kMaxNumUnpatchedParams];
258 std::array<SessionMacro, 8> sessionMacros{};
260 bool getAnyClipsSoloing()
const;
261 Clip* getCurrentClip();
262 void setCurrentClip(Clip* clip) {
263 if (currentClip !=
nullptr) {
264 previousClip = currentClip;
268 uint32_t getInputTickScale();
269 Clip* getSyncScalingClip();
270 void setInputTickScaleClip(Clip* clip);
271 inline bool isFillModeActive() {
return fillModeActive; }
272 void changeFillMode(
bool on);
274 void setClipLength(Clip* clip, uint32_t newLength, Action* action,
bool mayReSyncClip =
true);
275 void doubleClipLength(InstrumentClip* clip, Action* action =
nullptr);
276 Clip* getClipWithOutput(Output* output,
bool mustBeActive =
false, Clip* excludeClip =
nullptr);
277 Error readFromFile(Deserializer& reader);
279 void loadAllSamples(
bool mayActuallyReadFiles =
true);
280 void renderAudio(std::span<StereoSample> outputBuffer, int32_t* reverbBuffer, int32_t sideChainHitPending);
281 bool isYNoteAllowed(int32_t yNote,
bool inKeyMode);
282 Clip* syncScalingClip;
283 void setTimePerTimerTick(uint64_t newTimeBig,
bool shouldLogAction =
false);
286 void ensureInaccessibleParamPresetValuesWithoutKnobsAreZero(Sound* sound);
287 bool areAllClipsInSectionPlaying(int32_t section);
288 void removeYNoteFromMode(int32_t yNoteWithinOctave);
289 void turnSoloingIntoJustPlaying(
bool getRidOfArmingToo =
true);
290 void reassessWhetherAnyClipsSoloing();
291 float getTimePerTimerTickFloat();
292 uint32_t getTimePerTimerTickRounded();
293 int32_t getNumOutputs();
294 Clip* getNextSessionClipWithOutput(int32_t offset, Output* output, Clip* prevClip);
295 bool anyClipsSoloing;
297 ParamManager* getBackedUpParamManagerForExactClip(ModControllableAudio* modControllable, Clip* clip,
298 ParamManager* stealInto =
nullptr);
299 ParamManager* getBackedUpParamManagerPreferablyWithClip(ModControllableAudio* modControllable, Clip* clip,
300 ParamManager* stealInto =
nullptr);
301 void backUpParamManager(ModControllableAudio* modControllable, Clip* clip, ParamManagerForTimeline* paramManager,
302 bool shouldStealExpressionParamsToo =
false);
303 void moveInstrumentToHibernationList(Instrument* instrument);
304 void deleteOrHibernateOutputIfNoClips(Output* output);
305 void removeInstrumentFromHibernationList(Instrument* instrument);
306 bool doesOutputHaveActiveClipInSession(Output* output);
307 bool doesNonAudioSlotHaveActiveClipInSession(OutputType outputType, int32_t slot, int32_t subSlot = -1);
308 bool doesOutputHaveAnyClips(Output* output);
309 void deleteBackedUpParamManagersForClip(Clip* clip);
310 void deleteBackedUpParamManagersForModControllable(ModControllableAudio* modControllable);
311 void deleteHibernatingInstrumentWithSlot(OutputType outputType,
char const* name);
312 void loadCrucialSamplesOnly();
313 Clip* getSessionClipWithOutput(Output* output, int32_t requireSection = -1, Clip* excludeClip =
nullptr,
314 int32_t* clipIndex =
nullptr,
bool excludePendingOverdubs =
false);
315 void restoreClipStatesBeforeArrangementPlay();
316 void deleteOrAddToHibernationListOutput(Output* output);
317 int32_t getLowestSectionWithNoSessionClipForOutput(Output* output);
318 void assertActiveness(ModelStackWithTimelineCounter* modelStack, int32_t endInstanceAtTime = -1);
319 [[nodiscard]]
bool isClipActive(Clip
const* clip)
const;
320 void sendAllMIDIPGMs();
321 void sortOutWhichClipsAreActiveWithoutSendingPGMs(ModelStack* modelStack, int32_t playbackWillStartInArrangerAtPos);
322 void deactivateAnyArrangementOnlyClips();
323 Clip* getLongestClip(
bool includePlayDisabled,
bool includeArrangementOnly);
324 Clip* getLongestActiveClipWithMultipleOrFactorLength(int32_t targetLength,
bool revertToAnyActiveClipIfNone =
true,
325 Clip* excludeClip =
nullptr);
326 int32_t getOutputIndex(Output* output);
327 void setHibernatingMIDIInstrument(MIDIInstrument* newInstrument);
328 void deleteHibernatingMIDIInstrument();
329 MIDIInstrument* grabHibernatingMIDIInstrument(int32_t newSlot, int32_t newSubSlot);
330 NoteRow* findNoteRowForDrum(Kit* kit, Drum* drum, Clip* stopTraversalAtClip =
nullptr);
332 bool anyOutputsSoloingInArrangement;
333 bool getAnyOutputsSoloingInArrangement();
334 void reassessWhetherAnyOutputsSoloingInArrangement();
335 bool isOutputActiveInArrangement(Output* output);
336 Output* getOutputFromIndex(int32_t index);
337 void ensureAllInstrumentsHaveAClipOrBackedUpParamManager(
char const* errorMessageNormal,
338 char const* errorMessageHibernating);
339 Error placeFirstInstancesOfActiveClips(int32_t pos);
340 void endInstancesOfActiveClips(int32_t pos,
bool detachClipsToo =
false);
341 void clearArrangementBeyondPos(int32_t pos, Action* action);
342 void deletingClipInstanceForClip(Output* output, Clip* clip, Action* action,
bool shouldPickNewActiveClip);
343 bool arrangementHasAnyClipInstances();
344 void resumeClipsClonedForArrangementRecording();
345 void setParamsInAutomationMode(
bool newState);
346 bool shouldOldOutputBeReplaced(Clip* clip, Availability* availabilityRequirement =
nullptr);
347 Output* navigateThroughPresetsForInstrument(Output* output, int32_t offset);
348 void instrumentSwapped(Instrument* newInstrument);
349 Instrument* changeOutputType(Instrument* oldInstrument, OutputType newOutputType);
350 AudioOutput* getFirstAudioOutput();
351 AudioOutput* createNewAudioOutput(Output* replaceOutput =
nullptr);
353 void getNoteLengthName(StringBuf& buffer, uint32_t noteLength,
char const* notesString =
"-notes",
354 bool clarifyPerColumn =
false)
const;
355 void replaceOutputLowLevel(Output* newOutput, Output* oldOutput);
356 void removeSessionClip(Clip* clip, int32_t clipIndex,
bool forceClipsAboveToMoveVertically =
false);
357 bool deletePendingOverdubs(Output* onlyWithOutput =
nullptr, int32_t* originalClipIndex =
nullptr,
358 bool createConsequencesForOtherLinearlyRecordingClips =
false);
359 Clip* getPendingOverdubWithOutput(Output* output);
360 Clip* getClipWithOutputAboutToBeginLinearRecording(Output* output);
361 Clip* createPendingNextOverdubBelowClip(Clip* clip, int32_t clipIndex, OverDubType newOverdubNature);
362 bool hasAnyPendingNextOverdubs();
363 Output* getNextAudioOutput(int32_t offset, Output* oldOutput, Availability availabilityRequirement);
364 void deleteOutput(Output* output);
365 void cullAudioClipVoice();
366 int32_t getYScrollSongViewWithoutPendingOverdubs();
367 int32_t removeOutputFromMainList(Output* output,
bool stopAnyAuditioningFirst =
true);
368 void swapClips(Clip* newClip, Clip* oldClip, int32_t clipIndex);
369 Clip* replaceInstrumentClipWithAudioClip(Clip* oldClip, int32_t clipIndex);
370 void setDefaultVelocityForAllInstruments(uint8_t newDefaultVelocity);
371 void midiCableBendRangeUpdatedViaMessage(ModelStack* modelStack, MIDICable& cable, int32_t channelOrZone,
372 int32_t whichBendRange, int32_t bendSemitones);
373 Error addInstrumentsToFileItems(OutputType outputType);
375 uint32_t getQuarterNoteLength();
376 uint32_t getBarLength();
377 uint32_t getSixteenthNoteLength();
378 ModelStackWithThreeMainThings* setupModelStackWithSongAsTimelineCounter(
void* memory);
379 ModelStackWithTimelineCounter* setupModelStackWithCurrentClip(
void* memory);
380 ModelStackWithThreeMainThings* addToModelStack(ModelStack* modelStack);
383 ModelStackWithAutoParam*
getModelStackWithParam(ModelStackWithThreeMainThings* modelStack, int32_t paramID);
387 [[nodiscard]] uint32_t
getLivePos()
const override;
388 [[nodiscard]] int32_t getLoopLength()
const override;
389 [[nodiscard]]
bool isPlayingAutomationNow()
const override;
390 [[nodiscard]]
bool backtrackingCouldLoopBackToEnd()
const override;
391 [[nodiscard]] int32_t getPosAtWhichPlaybackWillCut(ModelStackWithTimelineCounter
const* modelStack)
const override;
392 void getActiveModControllable(ModelStackWithTimelineCounter* modelStack)
override;
393 void expectEvent()
override;
394 TimelineCounter* getTimelineCounterToRecordTo()
override;
397 dsp::Reverb::Model model;
398 float reverbRoomSize;
404 int32_t reverbSidechainVolume;
405 int32_t reverbSidechainShape;
406 int32_t reverbSidechainAttack;
407 int32_t reverbSidechainRelease;
408 SyncLevel reverbSidechainSync;
411 int32_t lastSelectedParamID;
413 lastSelectedParamKind;
414 int32_t lastSelectedParamShortcutX;
415 int32_t lastSelectedParamShortcutY;
416 int32_t lastSelectedParamArrayPosition;
420 int32_t masterTransposeInterval;
421 void transpose(int32_t interval);
422 void adjustMasterTransposeInterval(int32_t interval);
423 void displayMasterTransposeInterval();
426 bool hasBeenTransposed = 0;
427 int16_t transposeOffset = 0;
429 int32_t countAudioClips()
const;
432 uint8_t chordMemNoteCount[kDisplayHeight] = {0};
433 uint8_t chordMem[kDisplayHeight][MAX_NOTES_CHORD_MEM] = {0};
436 void clearTempoAutomation();
437 void updateBPMFromAutomation();
439 float calculateBPM() {
440 float timePerTimerTick = getTimePerTimerTickFloat();
441 return calculateBPM(timePerTimerTick);
443 float calculateBPM(
float timePerTimerTick) {
445 if (insideWorldTickMagnitude > 0) {
446 timePerTimerTick *= ((uint32_t)1 << (insideWorldTickMagnitude));
448 float tempoBPM = (float)110250 / timePerTimerTick;
449 if (insideWorldTickMagnitude < 0) {
450 tempoBPM *= ((uint32_t)1 << (-insideWorldTickMagnitude));
455 int8_t defaultAudioClipOverdubOutputCloning = -1;
458 void changeThresholdRecordingMode(int8_t offset);
459 void displayThresholdRecordingMode();
460 ThresholdRecordingMode thresholdRecordingMode;
463 ScaleMapper scaleMapper;
464 NoteSet userScaleNotes;
466 Clip* currentClip =
nullptr;
467 Clip* previousClip =
nullptr;
468 void inputTickScalePotentiallyJustChanged(uint32_t oldScale);
469 Error readClipsFromFile(Deserializer& reader, ClipArray* clipArray);
470 void addInstrumentToHibernationList(Instrument* instrument);
471 void deleteAllBackedUpParamManagers(
bool shouldAlsoEmptyVector =
true);
472 void deleteAllBackedUpParamManagersWithClips();
473 void deleteAllOutputs(Output** prevPointer);
474 void setupClipIndexesForSaving();
475 void setBPMInner(
float tempoBPM,
bool shouldLogAction);
476 void clearTempoAutomation(
float tempoBPM);