Refactor and locking cleanup
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
#include "MidiDriver.h"
|
||||
#include "TrackerTypes.h"
|
||||
#include "UIThread.h"
|
||||
#include "config.h"
|
||||
#include "SharedState.h"
|
||||
|
||||
bool wasPlaying = false;
|
||||
|
||||
static void handlePlayback() {
|
||||
bool nowPlaying = isPlaying;
|
||||
int tracksToPlay = (playMode == MODE_POLY) ? NUM_TRACKS : 1;
|
||||
if (!wasPlaying && !nowPlaying) {
|
||||
midi.sendRealtime(0xFA); // MIDI Start
|
||||
} else if (wasPlaying && !nowPlaying) {
|
||||
midi.sendRealtime(0xFC); // MIDI Stop
|
||||
for (int i=0; i<tracksToPlay; i++) midi.panic(midiChannels[i]);
|
||||
}
|
||||
wasPlaying = nowPlaying;
|
||||
|
||||
if (!nowPlaying) return;
|
||||
|
||||
unsigned long currentMicros = micros();
|
||||
unsigned long clockInterval = 2500000 / tempo; // 60s * 1000000us / (tempo * 24ppqn)
|
||||
|
||||
if (currentMicros - lastClockTime >= clockInterval) {
|
||||
lastClockTime += clockInterval;
|
||||
|
||||
midi.sendRealtime(0xF8); // MIDI Clock
|
||||
|
||||
clockCount++;
|
||||
if (clockCount < 6) return; // 24 ppqn / 4 = 6 pulses per 16th note
|
||||
clockCount = 0;
|
||||
|
||||
midi.lock();
|
||||
Step local_sequence[NUM_TRACKS][NUM_STEPS];
|
||||
memcpy(local_sequence, sequence, sizeof(local_sequence));
|
||||
Step local_nextSequence[NUM_TRACKS][NUM_STEPS];
|
||||
memcpy(local_nextSequence, nextSequence, sizeof(local_nextSequence));
|
||||
midi.unlock();
|
||||
|
||||
for(int t=0; t<tracksToPlay; t++) {
|
||||
int trackChannel = playMode == MODE_POLY ? midiChannels[t] : midiChannels[0];
|
||||
int nextStep = playbackStep + 1;
|
||||
if (nextStep >= NUM_STEPS) nextStep = 0;
|
||||
|
||||
// Determine if we are tying to the next note
|
||||
bool isTied = local_sequence[t][playbackStep].tie && (local_sequence[t][nextStep].note != -1);
|
||||
int prevNote = local_sequence[t][playbackStep].note;
|
||||
|
||||
// Note Off for previous step (if NOT tied)
|
||||
if (!isTied && prevNote != -1) {
|
||||
midi.sendNoteOff(prevNote, trackChannel);
|
||||
}
|
||||
}
|
||||
|
||||
playbackStep++;
|
||||
if (playbackStep >= NUM_STEPS) {
|
||||
playbackStep = 0;
|
||||
|
||||
// Theme change
|
||||
if (sequenceChangeScheduled && queuedTheme != -1) {
|
||||
currentThemeIndex = queuedTheme;
|
||||
queuedTheme = -1;
|
||||
// nextSequence is already generated
|
||||
}
|
||||
|
||||
// Mutation
|
||||
if (mutationEnabled) {
|
||||
if (!sequenceChangeScheduled) {
|
||||
memcpy(local_nextSequence, local_sequence, sizeof(sequence));
|
||||
}
|
||||
mutateSequence(local_nextSequence);
|
||||
midi.lock();
|
||||
memcpy(nextSequence, local_nextSequence, sizeof(sequence));
|
||||
sequenceChangeScheduled = true;
|
||||
midi.unlock();
|
||||
}
|
||||
|
||||
for (int i=0; i<tracksToPlay; i++) midi.panic(midiChannels[i]);
|
||||
|
||||
if (sequenceChangeScheduled) {
|
||||
memcpy(local_sequence, local_nextSequence, sizeof(local_sequence));
|
||||
midi.lock();
|
||||
memcpy(sequence, local_sequence, sizeof(local_sequence));
|
||||
sequenceChangeScheduled = false;
|
||||
midi.unlock();
|
||||
}
|
||||
|
||||
// Song Mode? Advance repeats
|
||||
if (songModeEnabled) {
|
||||
// we just used one repeat
|
||||
if (songRepeatsRemaining <= 1) {
|
||||
// let's start another round
|
||||
songRepeatsRemaining = nextSongRepeats;
|
||||
} else {
|
||||
// next repeat
|
||||
songRepeatsRemaining--;
|
||||
}
|
||||
// Trigger next song segment generation if we are on the last repeat
|
||||
if (songRepeatsRemaining <= 1 && !sequenceChangeScheduled && !songModeNeedsNext) {
|
||||
songModeNeedsNext = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note On for new step
|
||||
for(int t=0; t<tracksToPlay; t++) {
|
||||
int trackChannel = playMode == MODE_POLY ? midiChannels[t] : midiChannels[0];
|
||||
if (!trackMute[t] && local_sequence[t][playbackStep].note != -1) {
|
||||
uint8_t velocity = local_sequence[t][playbackStep].accent ? 127 : 100;
|
||||
midi.sendNoteOn(local_sequence[t][playbackStep].note, velocity, trackChannel);
|
||||
}
|
||||
|
||||
int prevStep = (playbackStep == 0) ? NUM_STEPS - 1 : playbackStep - 1;
|
||||
bool wasTied = local_sequence[t][prevStep].tie && (local_sequence[t][playbackStep].note != -1);
|
||||
int prevNote = local_sequence[t][prevStep].note;
|
||||
// Note Off for previous step (if tied - delayed Note Off)
|
||||
if (wasTied && prevNote != -1) {
|
||||
midi.sendNoteOff(prevNote, trackChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loopPlayback() {
|
||||
unsigned long now = millis();
|
||||
lastLoop1Time = now;
|
||||
if (watchdogActive && (now - lastLoop0Time > 1000)) {
|
||||
Serial.println("Core 0 Freeze detected");
|
||||
rp2040.reboot();
|
||||
}
|
||||
|
||||
if (needsPanic) {
|
||||
if (playMode == MODE_POLY) {
|
||||
for (int i=0; i<NUM_TRACKS; i++) midi.panic(midiChannels[i]);
|
||||
} else {
|
||||
midi.panic(midiChannels[0]);
|
||||
}
|
||||
needsPanic = false;
|
||||
}
|
||||
handlePlayback();
|
||||
}
|
||||
Reference in New Issue
Block a user