Deluge Firmware 1.3.0
Build date: 2025.04.16
Loading...
Searching...
No Matches
output.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 "hid/button.h"
22#include "model/clip/clip_instance_vector.h"
23#include "model/sample/sample_recorder.h"
24#include "modulation/params/param.h"
25#include "util/d_string.h"
26#include <cstdint>
27
28class InstrumentClip;
29class Song;
30class Clip;
32class Kit;
33class Sound;
34class StereoSample;
35class TimelineCounter;
36class ModControllable;
38class ModelStack;
41class MIDICable;
42class LearnedMIDI;
43class ParamManager;
44class Serializer;
45class Deserializer;
46
47inline const char* outputTypeToString(OutputType type) {
48 switch (type) {
49 case OutputType::SYNTH:
50 return "synth";
51 case OutputType::KIT:
52 return "kit";
53 case OutputType::MIDI_OUT:
54 return "MIDI";
55 case OutputType::CV:
56 return "CV";
57 case OutputType::AUDIO:
58 return "audio";
59 default:
60 return "none";
61 }
62}
63
64inline OutputType buttonToOutputType(deluge::hid::Button b) {
65 using namespace deluge::hid::button;
66 switch (b) {
67 case SYNTH:
68 return OutputType::SYNTH;
69 case MIDI:
70 return OutputType::MIDI_OUT;
71 case KIT:
72 return OutputType::KIT;
73 case CV:
74 return OutputType::CV;
75 case SELECT_ENC:
76 return OutputType::AUDIO;
77 default:
78 return OutputType::NONE;
79 }
80}
81class Output {
82public:
83 Output(OutputType newType);
84 virtual ~Output();
85 virtual bool matchesPreset(OutputType otherType, int32_t channel, int32_t channelSuffix, char const* otherName,
86 char const* dirPath) = 0;
87
88 ClipInstanceVector clipInstances;
89 [[nodiscard]] Clip* getActiveClip() const;
90 String name; // Contains the display name as the user sees it.
91 // E.g. on numeric Deluge, SYNT000 will be just "0". Definitely no leading zeros, so not "000".
92 // On OLED Deluge I thiiink SYNT000 would be "SYNT000"?
93 // Definitely does not contain the ".XML" on the end.
94 Output* next;
95 const OutputType type;
96 bool mutedInArrangementMode;
97 bool mutedInArrangementModeBeforeStemExport; // Used by stem export to restore previous state
98 bool exportStem; // Used by stem export to flag if this output should be exported
99 bool soloingInArrangementMode;
100 bool inValidState;
101 bool wasCreatedForAutoOverdub;
102 bool armedForRecording;
103 int16_t colour{0};
104
105 uint8_t modKnobMode;
106
107 // Temp stuff for doLaunch()
108 bool alreadyGotItsNewClip;
109 bool isGettingSoloingClip;
110
111 bool nextClipFoundShouldGetArmed; // Temp thing for Session::armClipsToStartOrSoloWithQuantization
112
113 // reverbAmountAdjust has "1" as 67108864
114 // Only gets called if there's an activeClip
115 virtual void renderOutput(ModelStack* modelStack, std::span<StereoSample> outputBuffer, int32_t* reverbBuffer,
116 int32_t reverbAmountAdjust, int32_t sideChainHitPending, bool shouldLimitDelayFeedback,
117 bool isClipActive) = 0;
118
119 virtual void setupWithoutActiveClip(ModelStack* modelStack);
120 virtual bool setActiveClip(
122 PgmChangeSend maySendMIDIPGMs = PgmChangeSend::ONCE); // Will have no effect if it already had that Clip
123 void pickAnActiveClipForArrangementPos(ModelStack* modelStack, int32_t arrangementPos,
124 PgmChangeSend maySendMIDIPGMs);
125 void pickAnActiveClipIfPossible(ModelStack* modelStack, bool searchSessionClipsIfNeeded = true,
126 PgmChangeSend maySendMIDIPGMs = PgmChangeSend::ONCE,
127 bool setupWithoutActiveClipIfNeeded = true);
128 void detachActiveClip(Song* currentSong);
129
130 virtual ModControllable* toModControllable() { return nullptr; }
131 virtual bool isSkippingRendering() { return true; } // Not valid for Kits
132 bool clipHasInstance(Clip* clip);
133 bool isEmpty(bool displayPopup = true);
134 void clipLengthChanged(Clip* clip, int32_t oldLength);
135 virtual void cutAllSound() {}
136 virtual void getThingWithMostReverb(Sound** soundWithMostReverb, ParamManager** paramManagerWithMostReverb,
137 GlobalEffectableForClip** globalEffectableWithMostReverb,
138 int32_t* highestReverbAmountFound) {}
141
143 virtual bool offerReceivedPitchBendToLearnedParams(MIDICable& cable, uint8_t channel, uint8_t data1, uint8_t data2,
144 ModelStackWithTimelineCounter* modelStack) {
145 return false;
146 } // A TimelineCounter is required
147 virtual void offerReceivedCCToLearnedParams(MIDICable& cable, uint8_t channel, uint8_t ccNumber, uint8_t value,
148 ModelStackWithTimelineCounter* modelStack) {
149 } // A TimelineCounter is required
150 virtual int32_t doTickForwardForArp(ModelStack* modelStack, int32_t currentPos) { return 2147483647; }
151 void endAnyArrangementRecording(Song* song, int32_t actualEndPos, uint32_t timeRemainder);
152 virtual bool wantsToBeginArrangementRecording() { return armedForRecording; }
153
154 // FIXME:I think that supplying clip here is only a hangover from old pre-2.0 files...
155 virtual Error readFromFile(Deserializer& reader, Song* song, Clip* clip, int32_t readAutomationUpToPos);
156
157 virtual bool readTagFromFile(Deserializer& reader, char const* tagName);
158 void writeToFile(Clip* clipForSavingOutputOnly, Song* song);
159 virtual bool writeDataToFile(Serializer& writer, Clip* clipForSavingOutputOnly,
160 Song* song); // Returns true if it's ended the opening tag and gone into the sub-tags
161
162 virtual Error loadAllAudioFiles(bool mayActuallyReadFiles) { return Error::NONE; }
163 virtual void loadCrucialAudioFilesOnly() {} // Caller must check that there is an activeClip.
164
165 // No activeClip needed. Call anytime the Instrument comes into existence on the main list thing
166 virtual void resyncLFOs() {};
167
168 virtual void sendMIDIPGM() {};
169 virtual void deleteBackedUpParamManagers(Song* song) {}
170 virtual void prepareForHibernationOrDeletion() {}
171
172 virtual char const* getXMLTag() = 0;
173 virtual ParamManager* getParamManager(Song* song);
174
175 virtual char const* getNameXMLTag() { return "name"; }
176
177 virtual void offerReceivedNote(ModelStackWithTimelineCounter* modelStackWithTimelineCounter, MIDICable& cable,
178 bool on, int32_t channel, int32_t note, int32_t velocity, bool shouldRecordNotes,
179 bool* doingMidiThru) {}
180 virtual void offerReceivedPitchBend(ModelStackWithTimelineCounter* modelStackWithTimelineCounter, MIDICable& cable,
181 uint8_t channel, uint8_t data1, uint8_t data2, bool* doingMidiThru) {}
182 virtual void offerReceivedCC(ModelStackWithTimelineCounter* modelStackWithTimelineCounter, MIDICable& cable,
183 uint8_t channel, uint8_t ccNumber, uint8_t value, bool* doingMidiThru) {}
184 virtual void offerReceivedAftertouch(ModelStackWithTimelineCounter* modelStackWithTimelineCounter, MIDICable& cable,
185 int32_t channel, int32_t value, int32_t noteCode, bool* doingMidiThru) {}
186
187 virtual void stopAnyAuditioning(ModelStack* modelStack) {}
188 virtual void offerBendRangeUpdate(ModelStack* modelStack, MIDICable& cable, int32_t channelOrZone,
189 int32_t whichBendRange, int32_t bendSemitones) {}
190
191 // Arrangement stuff
192 Error possiblyBeginArrangementRecording(Song* song, int32_t newPos);
193 void endArrangementPlayback(Song* song, int32_t actualEndPos, uint32_t timeRemainder);
194 bool recordingInArrangement;
195
196 virtual ModelStackWithAutoParam* getModelStackWithParam(ModelStackWithTimelineCounter* modelStack, Clip* clip,
197 int32_t paramID, deluge::modulation::params::Kind paramKind,
198 bool affectEntire, bool useMenuStack) = 0;
199 virtual bool needsEarlyPlayback() const { return false; }
200 bool hasRecorder() { return recorder; }
201 bool shouldRenderInSong() { return !(recorderIsEchoing); }
202
204 void setRenderingToAudioOutput(bool monitoring, Output* output) {
205 recorderIsEchoing = monitoring;
206 outputRecordingThisOutput = output;
207 }
208 bool addRecorder(SampleRecorder* newRecorder) {
209 if (recorder) {
210 return false;
211 }
212 recorder = newRecorder;
213 return true;
214 }
215 // returns whether a recorder was removed
216 bool removeRecorder() {
217 if (recorder) {
218 recorder->removeFromOutput();
219 recorder = nullptr;
220 return true;
221 }
222 return false;
223 }
224 Output* getOutputRecordingThis() { return outputRecordingThisOutput; }
225
226protected:
227 virtual Clip* createNewClipForArrangementRecording(ModelStack* modelStack) = 0;
228 bool recorderIsEchoing{false};
229 // for clearing pointers when this output is deleted
230 Output* outputRecordingThisOutput{nullptr};
231 // only for audio outputs, will be used for instruments when I implement routing notes between clips
232 virtual void clearRecordingFrom() {}
233 Clip* activeClip{nullptr};
234 SampleRecorder* recorder{nullptr};
235};
Definition clip_instance_vector.h:24
Definition clip.h:46
Definition storage_manager.h:185
Definition global_effectable_for_clip.h:33
Definition instrument_clip.h:48
Definition kit.h:34
Definition learned_midi.h:30
A MIDI cable connection. Stores all state specific to a given cable and its contained ports and chann...
Definition midi_device.h:94
Definition mod_controllable.h:40
Definition model_stack.h:269
Definition model_stack.h:129
Definition model_stack.h:123
void setRenderingToAudioOutput(bool monitoring, Output *output)
disable rendering to the song buffer if this clip is the input to an audio output that's monitoring
Definition output.h:204
virtual bool offerReceivedPitchBendToLearnedParams(MIDICable &cable, uint8_t channel, uint8_t data1, uint8_t data2, ModelStackWithTimelineCounter *modelStack)
Pitch bend is available in the mod matrix as X and shouldn't be learned to params anymore (post 4....
Definition output.h:143
Clip * getClipFromName(String *name)
If there's a clip matching the name on this output, returns it.
Definition output.cpp:56
Definition param_manager.h:174
Definition param_manager.h:45
Definition sample_recorder.h:49
Definition storage_manager.h:119
Definition song.h:104
Definition sound.h:71
Definition d_string.h:46
Definition timeline_counter.h:28
Kind
Definition param.h:42
Definition stereo_sample.h:25