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