Deluge Firmware
Loading...
Searching...
No Matches
playbackhandler.h
Go to the documentation of this file.
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#ifndef PLAYBACKHANDLER_H
19#define PLAYBACKHANDLER_H
20
21#include "r_typedefs.h"
22#include "definitions.h"
23
24
25#define MIDI_OUT_OFF 0
26#define MIDI_OUT_INCIDENTAL 1
27#define MIDI_OUT_MASTER 2
28
29#define RECORDING_OFF 0
30#define RECORDING_NORMAL 1
31#define RECORDING_ARRANGEMENT 2
32
33#define NUM_INPUT_TICKS_FOR_MOVING_AVERAGE 24
34
35#define PLAYBACK_CLOCK_INTERNAL_ACTIVE 1
36#define PLAYBACK_CLOCK_EXTERNAL_ACTIVE 2
37#define PLAYBACK_SWITCHED_ON 4
38
39#define PLAYBACK_CLOCK_EITHER_ACTIVE (PLAYBACK_CLOCK_INTERNAL_ACTIVE | PLAYBACK_CLOCK_EXTERNAL_ACTIVE)
40
41
42class Song;
43class InstrumentClip;
44class NoteRow;
45class Kit;
46class Clip;
47class Action;
48class MIDIDevice;
49
50const uint8_t metronomeValuesBPM[16] = {60, 63, 66, 69, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116};
51
52const uint16_t metronomeValueBoundaries[16] = {1793, 1709, 1633, 1542, 1490, 1413, 1345, 1282, 1225, 1173, 1125, 1081, 1040, 1002, 967, 934};
53
55{
56public:
58 void routine();
59
60 void playButtonPressed(int buttonPressLatency);
62 void setupPlaybackUsingInternalClock(int buttonPressLatencyForTempolessRecord = 0, bool allowCountIn = true);
63 void setupPlaybackUsingExternalClock(bool switchingFromInternalClock = false, bool fromContinueCommand = false);
64 void setupPlayback(int newPlaybackState, int32_t playFromPos, bool doOneLastAudioRoutineCall = false, bool shouldShiftAccordingToClipInstance = true, int buttonPressLatencyForTempolessRecord = 0);
65 void endPlayback();
66 void inputTick(bool fromTriggerClock = false, uint32_t time = 0);
70 void clockMessageReceived(uint32_t time);
71 void tempoEncoderAction(int8_t offset, bool encoderButtonPressed, bool shiftButtonPressed);
73 void positionPointerReceived(uint8_t data1, uint8_t data2);
74 void programChangeReceived(int channel, int program);
75 void doSongSwap(bool preservePlayPosition = false);
76 void forceResetPlayPos(Song* song);
77 void expectEvent();
78 void setMidiInClockEnabled(bool newValue);
81 void slowRoutine();
83 int getNumSwungTicksInSinceLastTimerTick(uint32_t* timeRemainder = NULL);
84 int getNumSwungTicksInSinceLastActionedSwungTick(uint32_t* timeRemainder = NULL);
85 int64_t getActualSwungTickCount(uint32_t* timeRemainder = NULL);
86 int64_t getCurrentInternalTickCount(uint32_t* remainder = NULL);
87 void scheduleSwungTick();
88 int32_t getInternalTickTime(int64_t internalTickCount);
91 void scheduleNextTimerTick(uint32_t doubleSwingInterval);
92
93
94 // MIDI-clock-out ticks
98
99
100
101 // Playback
103 bool usingAnalogClockInput; // Value is only valid if usingInternalClock is false
104 uint8_t recording;
106
107 int32_t posToNextContinuePlaybackFrom; // This will then have 1 subtracted from it when actually physically set
109
110 // Timer ticks
111 int64_t lastTimerTickActioned; // Not valid while playback being set up
112 int64_t nextTimerTickScheduled; // *Yes* valid while (internal clock) playback being set up. Will be zero during that time
113 uint64_t timeNextTimerTickBig; // Not valid while playback being set up
114 uint64_t timeLastTimerTickBig; // Not valid while playback being set up
115
116 // Input ticks
118 uint32_t timePerInputTickMovingAverage; // 0 means that a default will be set the first time it's used
120
122 //unsigned long timeFirstInputTick; // First tick received for current tally
123 unsigned long timeVeryFirstInputTick; // Very first tick received in playback. Only used for tempo magnitude matching
126
127 // Swung ticks
130 // Now, swung ticks are only "actioned" in the following circumstances:
131 // - A note starts or ends
132 // - Automation event
133 // - A clip loops
134 // - A "launch" event
135 // - Start of playback, including if count-in ends
136 int64_t lastSwungTickActioned; // Will be set to a phony-ish "0" while playback being set up
137
138 // Trigger-clock-out ticks
142
143 uint32_t analogOutTicksPPQN; // Relative to the "external world", which also means relative to the displayed tempo
147
149
150 // User options
156
158
161
163
164 void setLedStates();
169 void stopAnyRecording();
170 uint32_t getTimePerInternalTick();
171 uint64_t getTimePerInternalTickBig();
173 uint32_t getTimePerInternalTickInverse(bool getStickyValue = false);
174 void tapTempoButtonPress();
176 void doMIDIClockOutTick();
179 void analogClockRisingEdge(uint32_t time);
182 void displaySwingAmount();
183 void setMidiOutClockMode(bool newValue);
184 void pitchBendReceived(MIDIDevice* fromDevice, uint8_t channel, uint8_t data1, uint8_t data2, bool* doingMidiThru);
185 void midiCCReceived(MIDIDevice* fromDevice, uint8_t channel, uint8_t ccNumber, uint8_t value, bool* doingMidiThru);
186 void aftertouchReceived(MIDIDevice* fromDevice, int channel, int value, int noteCode, bool* doingMidiThru); // noteCode -1 means channel-wide
187 void loopCommand(int overdubNature);
188 void grabTempoFromClip(Clip* clip);
189 int32_t getTimeLeftInCountIn();
190
191 void noteMessageReceived(MIDIDevice* fromDevice, bool on, int channel, int note, int velocity, bool* doingMidiThru);
193
194 void songSelectReceived(uint8_t songId);
195 float calculateBPM(float timePerInternalTick);
196 void switchToArrangement();
197 void switchToSession();
198 void finishTempolessRecording(bool startPlaybackAgain, int buttonLatencyForTempolessRecord, bool shouldExitRecordMode = true);
199
201
203
204
205
206 void actionTimerTick();
208 void actionSwungTick();
211
212
213 inline bool isEitherClockActive() {
215 }
216
217
218private:
219
220 uint32_t timerTicksToOutputTicks(uint32_t timerTicks);
221
222 // These are all only relevant while playing synced.
223 uint32_t timePerInternalTickMovingAverage; // Recalculated every ~24 clocks
224 uint32_t veryCurrentTimePerInternalTickInverse; // Recalculated at every received clock message
225 uint32_t stickyCurrentTimePerInternalTickInverse; // Moving average kinda thing
226 uint32_t lowpassedTimePerInternalTick;
227 uint32_t slowpassedTimePerInternalTick;
228 uint32_t stickyTimePerInternalTick;
229
230
231 uint16_t tapTempoNumPresses;
232 uint32_t tapTempoFirstPressTime;
233
234 int numOutputClocksWaitingToBeSent;
235 int numInputTicksToSkip;
236
237
238 void resetTimePerInternalTickMovingAverage();
239 void getCurrentTempoParams(int32_t *magnitude, int8_t *whichValue);
240 void displayTempoFromParams(int32_t magnitude, int8_t whichValue);
241 void displayTempoBPM(float tempoBPM);
242 void getAnalogOutTicksToInternalTicksRatio(uint32_t* internalTicksPer, uint32_t* analogOutTicksPer);
243 void getMIDIClockOutTicksToInternalTicksRatio(uint32_t* internalTicksPer, uint32_t* midiClockOutTicksPer);
244 void getInternalTicksToInputTicksRatio(uint32_t* inputTicksPer, uint32_t* internalTicksPer);
245 void sendOutPositionViaMIDI(int32_t pos, bool outputClocksWereSwitchedOff = false);
246 //void scheduleNextTimerTick();
247 bool startIgnoringMidiClockInputIfNecessary();
248 uint32_t setTempoFromAudioClipLength(uint64_t loopLengthSamples, Action* action);
249 bool tryGlobalMIDICommands(MIDIDevice* device, int channel, int note);
250 void decideOnCurrentPlaybackMode();
251 float getCurrentInternalTickFloatFollowingExternalClock();
252 void scheduleTriggerClockOutTickParamsKnown(uint32_t analogOutTicksPer, uint64_t fractionLastTimerTick, uint64_t fractionNextAnalogOutTick);
253 void scheduleMIDIClockOutTickParamsKnown(uint32_t midiClockOutTicksPer, uint64_t fractionLastTimerTick, uint64_t fractionNextMIDIClockOutTick);
254
255};
256
258#endif // PLAYBACKHANDLER_H
Definition: Action.h:74
Definition: Clip.h:41
Definition: InstrumentClip.h:54
Definition: kit.h:35
Definition: MIDIDevice.h:74
Definition: NoteRow.h:72
Definition: playbackhandler.h:55
void songSelectReceived(uint8_t songId)
Definition: playbackhandler.cpp:2397
void inputTick(bool fromTriggerClock=false, uint32_t time=0)
Definition: playbackhandler.cpp:1403
void doTriggerClockOutTick()
Definition: playbackhandler.cpp:607
void setMidiOutClockMode(bool newValue)
Definition: playbackhandler.cpp:1827
void resyncAnalogOutTicksToInternalTicks()
Definition: playbackhandler.cpp:1600
float calculateBPM(float timePerInternalTick)
Definition: playbackhandler.cpp:1898
void switchToArrangement()
Definition: playbackhandler.cpp:2411
void programChangeReceived(int channel, int program)
Definition: playbackhandler.cpp:2289
int32_t getActualArrangementRecordPos()
Definition: playbackhandler.cpp:2559
void forceResetPlayPos(Song *song)
Definition: playbackhandler.cpp:2020
void noteMessageReceived(MIDIDevice *fromDevice, bool on, int channel, int note, int velocity, bool *doingMidiThru)
Definition: playbackhandler.cpp:2304
int getNumSwungTicksInSinceLastActionedSwungTick(uint32_t *timeRemainder=NULL)
Definition: playbackhandler.cpp:852
uint8_t numInputTickTimesCounted
Definition: playbackhandler.h:119
bool swungTickScheduled
Definition: playbackhandler.h:128
int32_t getArrangementRecordPosAtLastActionedSwungTick()
Definition: playbackhandler.cpp:2563
void stopAnyRecording()
Definition: playbackhandler.cpp:2195
int32_t getInternalTickTime(int64_t internalTickCount)
Definition: playbackhandler.cpp:1037
int64_t getCurrentInternalTickCount(uint32_t *remainder=NULL)
Definition: playbackhandler.cpp:935
void loopCommand(int overdubNature)
Definition: playbackhandler.cpp:2569
bool midiClockOutTickScheduled
Definition: playbackhandler.h:95
void displaySwingAmount()
Definition: playbackhandler.cpp:1621
void setupPlayback(int newPlaybackState, int32_t playFromPos, bool doOneLastAudioRoutineCall=false, bool shouldShiftAccordingToClipInstance=true, int buttonPressLatencyForTempolessRecord=0)
Definition: playbackhandler.cpp:360
void setupPlaybackUsingExternalClock(bool switchingFromInternalClock=false, bool fromContinueCommand=false)
Definition: playbackhandler.cpp:1190
int64_t lastSwungTickActioned
Definition: playbackhandler.h:136
void scheduleSwungTickFromExternalClock()
Definition: playbackhandler.cpp:1346
bool usingAnalogClockInput
Definition: playbackhandler.h:103
uint32_t scheduledSwungTickTime
Definition: playbackhandler.h:129
bool tempoMagnitudeMatchingActiveNow
Definition: playbackhandler.h:121
uint32_t analogInTicksPPQN
Definition: playbackhandler.h:144
bool isEitherClockActive()
Definition: playbackhandler.h:213
unsigned long targetedTimePerInputTick
Definition: playbackhandler.h:125
bool isCurrentlyRecording()
Definition: playbackhandler.cpp:2406
bool countInEnabled
Definition: playbackhandler.h:155
void scheduleMIDIClockOutTick()
Definition: playbackhandler.cpp:636
void routine()
Definition: playbackhandler.cpp:107
void resyncInternalTicksToInputTicks(Song *song)
Definition: playbackhandler.cpp:2006
float getTimePerInternalTickFloat()
Definition: playbackhandler.cpp:493
uint32_t timeNextTriggerClockOutTick
Definition: playbackhandler.h:140
int getNumSwungTicksInSinceLastTimerTick(uint32_t *timeRemainder=NULL)
Definition: playbackhandler.cpp:810
int64_t lastMIDIClockOutTickDone
Definition: playbackhandler.h:97
uint32_t timeNextMIDIClockOutTick
Definition: playbackhandler.h:96
void setLedStates()
Definition: playbackhandler.cpp:1976
void scheduleSwungTick()
Definition: playbackhandler.cpp:768
uint64_t getTimePerInternalTickBig()
Definition: playbackhandler.cpp:484
void doSongSwap(bool preservePlayPosition=false)
Definition: playbackhandler.cpp:1067
bool midiInClockEnabled
Definition: playbackhandler.h:153
bool analogClockInputAutoStart
Definition: playbackhandler.h:146
bool metronomeOn
Definition: playbackhandler.h:151
uint32_t timeLastMIDIStartOrContinueMessageSent
Definition: playbackhandler.h:108
uint32_t getTimePerInternalTickInverse(bool getStickyValue=false)
Definition: playbackhandler.cpp:1535
void reassessInputTickScaling()
uint32_t timePerInputTickMovingAverage
Definition: playbackhandler.h:118
void clockMessageReceived(uint32_t time)
Definition: playbackhandler.cpp:1336
int64_t nextTimerTickScheduled
Definition: playbackhandler.h:112
bool tempoMagnitudeMatchingEnabled
Definition: playbackhandler.h:154
uint32_t analogOutTicksPPQN
Definition: playbackhandler.h:143
void switchToSession()
Definition: playbackhandler.cpp:2429
unsigned long timeVeryFirstInputTick
Definition: playbackhandler.h:123
PlaybackHandler()
Definition: playbackhandler.cpp:84
void actionSwungTick()
Definition: playbackhandler.cpp:662
bool triggerClockOutTickScheduled
Definition: playbackhandler.h:139
int32_t posToNextContinuePlaybackFrom
Definition: playbackhandler.h:107
bool currentlySendingMIDIOutputClocks()
Definition: playbackhandler.cpp:319
void playButtonPressed(int buttonPressLatency)
Definition: playbackhandler.cpp:158
void scheduleNextTimerTick(uint32_t doubleSwingInterval)
Definition: playbackhandler.cpp:503
int64_t lastTriggerClockOutTickDone
Definition: playbackhandler.h:141
bool stopOutputRecordingAtLoopEnd
Definition: playbackhandler.h:202
bool songSwapShouldPreserveTempo
Definition: playbackhandler.h:148
uint32_t timeLastInputTicks[NUM_INPUT_TICKS_FOR_MOVING_AVERAGE]
Definition: playbackhandler.h:117
void finishTempolessRecording(bool startPlaybackAgain, int buttonLatencyForTempolessRecord, bool shouldExitRecordMode=true)
Definition: playbackhandler.cpp:2103
void continueMessageReceived()
Definition: playbackhandler.cpp:1307
void startMessageReceived()
Definition: playbackhandler.cpp:1277
void toggleMetronomeStatus()
Definition: playbackhandler.cpp:1996
uint32_t getTimePerInternalTick()
Definition: playbackhandler.cpp:475
uint64_t timeNextTimerTickBig
Definition: playbackhandler.h:113
uint64_t timeLastTimerTickBig
Definition: playbackhandler.h:114
void scheduleSwungTickFromInternalClock()
Definition: playbackhandler.cpp:774
int64_t lastInputTickReceived
Definition: playbackhandler.h:124
int32_t getTimeLeftInCountIn()
Definition: playbackhandler.cpp:2187
void actionTimerTickPart2()
Definition: playbackhandler.cpp:537
void displayTempoByCalculation()
Definition: playbackhandler.cpp:1893
void tapTempoAutoSwitchOff()
Definition: playbackhandler.cpp:338
void aftertouchReceived(MIDIDevice *fromDevice, int channel, int value, int noteCode, bool *doingMidiThru)
Definition: playbackhandler.cpp:2538
void recordButtonPressed()
Definition: playbackhandler.cpp:217
uint32_t timeLastAnalogClockInputRisingEdge
Definition: playbackhandler.h:145
void stopMessageReceived()
Definition: playbackhandler.cpp:1329
bool midiOutClockEnabled
Definition: playbackhandler.h:152
void actionTimerTick()
Definition: playbackhandler.cpp:516
void analogClockRisingEdge(uint32_t time)
Definition: playbackhandler.cpp:1171
void pitchBendReceived(MIDIDevice *fromDevice, uint8_t channel, uint8_t data1, uint8_t data2, bool *doingMidiThru)
Definition: playbackhandler.cpp:2448
bool ignoringMidiClockInput
Definition: playbackhandler.h:105
void resyncMIDIClockOutTicksToInternalTicks()
Definition: playbackhandler.cpp:1610
uint8_t recording
Definition: playbackhandler.h:104
int32_t ticksLeftInCountIn
Definition: playbackhandler.h:159
void midiCCReceived(MIDIDevice *fromDevice, uint8_t channel, uint8_t ccNumber, uint8_t value, bool *doingMidiThru)
Definition: playbackhandler.cpp:2489
void scheduleTriggerClockOutTick()
Definition: playbackhandler.cpp:615
int32_t arrangementPosToStartAtOnSwitch
Definition: playbackhandler.h:200
void tapTempoButtonPress()
Definition: playbackhandler.cpp:2205
int32_t swungTicksTilNextEvent
Definition: playbackhandler.h:157
void expectEvent()
Definition: playbackhandler.cpp:2381
void setupPlaybackUsingInternalClock(int buttonPressLatencyForTempolessRecord=0, bool allowCountIn=true)
Definition: playbackhandler.cpp:253
void positionPointerReceived(uint8_t data1, uint8_t data2)
Definition: playbackhandler.cpp:1254
void tempoEncoderAction(int8_t offset, bool encoderButtonPressed, bool shiftButtonPressed)
Definition: playbackhandler.cpp:1642
void endPlayback()
Definition: playbackhandler.cpp:418
bool subModeAllowsRecording()
Definition: playbackhandler.cpp:2392
int64_t getActualSwungTickCount(uint32_t *timeRemainder=NULL)
Definition: playbackhandler.cpp:861
void setMidiInClockEnabled(bool newValue)
Definition: playbackhandler.cpp:1850
uint8_t playbackState
Definition: playbackhandler.h:102
int32_t metronomeOffset
Definition: playbackhandler.h:162
bool shouldRecordNotesNow()
Definition: playbackhandler.cpp:2180
int64_t lastTimerTickActioned
Definition: playbackhandler.h:111
void slowRoutine()
Definition: playbackhandler.cpp:128
void doMIDIClockOutTick()
Definition: playbackhandler.cpp:656
int currentVisualCountForCountIn
Definition: playbackhandler.h:160
void grabTempoFromClip(Clip *clip)
Definition: playbackhandler.cpp:2036
Definition: song.h:72
const uint16_t metronomeValueBoundaries[16]
Definition: playbackhandler.h:52
PlaybackHandler playbackHandler
Definition: playbackhandler.cpp:70
#define NUM_INPUT_TICKS_FOR_MOVING_AVERAGE
Definition: playbackhandler.h:33
const uint8_t metronomeValuesBPM[16]
Definition: playbackhandler.h:50
#define PLAYBACK_CLOCK_EITHER_ACTIVE
Definition: playbackhandler.h:39