From 33c6329f0b42ef28953ea23ea5ff660cb9905b6e Mon Sep 17 00:00:00 2001 From: Dejvino Date: Sun, 22 Feb 2026 22:25:17 +0100 Subject: [PATCH] Intensity setting --- ArpStrategy.h | 17 +++++--- CellularAutomataStrategy.h | 11 +++-- EuclideanStrategy.h | 14 +++++-- LSystemStrategy.h | 13 ++++-- LuckyStrategy.h | 11 +++-- MarkovStrategy.h | 10 +++-- MelodyStrategy.h | 4 +- SharedState.cpp | 4 +- SharedState.h | 1 + TrackerTypes.h | 1 + UIManager.cpp | 48 ++++++++++++++++++++-- UIManager.h | 6 ++- UIThread.cpp | 82 +++++++++++++++++++++++++++++++++++--- 13 files changed, 182 insertions(+), 40 deletions(-) diff --git a/ArpStrategy.h b/ArpStrategy.h index e56fcd2..0cfd751 100644 --- a/ArpStrategy.h +++ b/ArpStrategy.h @@ -6,7 +6,7 @@ class ArpStrategy : public MelodyStrategy { public: - void generate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int seed) override { + void generate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int seed, int intensity) override { randomSeed(seed); if (numScaleNotes == 0) return; @@ -51,8 +51,10 @@ public: } for (int i = 0; i < arpLength; i++) { - // Chance of rest (15%) - if (random(100) < 15) { + // Use intensity to control density (gaps) + // Intensity 10 (max) = 5% rest chance. Intensity 1 (min) = 50% rest chance. + int restChance = 55 - (intensity * 5); + if (random(100) < restChance) { arpPattern[i].note = -1; arpPattern[i].accent = false; arpPattern[i].tie = false; @@ -60,10 +62,13 @@ public: int octaveOffset = currentIndex / subsetSize; int noteIndex = currentIndex % subsetSize; int octave = baseOctave + octaveOffset; - + + // Use intensity to control note length (ties) + // Intensity 10 (max) = 4% tie chance. Intensity 1 (min) = 40% tie chance. + int tieChance = 44 - (intensity * 4); arpPattern[i].note = 12 * octave + subset[noteIndex]; arpPattern[i].accent = (i % 4 == 0); // Accent on beat - arpPattern[i].tie = false; + arpPattern[i].tie = (random(100) < tieChance); } if (mode == 0) { // Up @@ -106,7 +111,7 @@ public: sortArray(scaleNotes, numScaleNotes); } - void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes) override { + void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int intensity) override { // Swap two notes int s1 = random(numSteps); int s2 = random(numSteps); diff --git a/CellularAutomataStrategy.h b/CellularAutomataStrategy.h index 54bfd53..6887cec 100644 --- a/CellularAutomataStrategy.h +++ b/CellularAutomataStrategy.h @@ -6,7 +6,7 @@ class CellularAutomataStrategy : public MelodyStrategy { public: - void generate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int seed) override { + void generate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int seed, int intensity) override { randomSeed(seed); if (numScaleNotes == 0) return; @@ -23,7 +23,8 @@ public: for(int i=0; i numSteps) pulses = numSteps; + int offset = random(numSteps); // Euclidean distribution (Bresenham) @@ -61,7 +69,7 @@ public: sortArray(scaleNotes, numScaleNotes); } - void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes) override { + void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int intensity) override { // Rotate sequence if (random(2) == 0) { Step last = sequence[track][numSteps - 1]; diff --git a/LSystemStrategy.h b/LSystemStrategy.h index 9c2b96a..ee71c0f 100644 --- a/LSystemStrategy.h +++ b/LSystemStrategy.h @@ -29,7 +29,7 @@ const uint8_t numRuleSets = sizeof(ruleSets) / sizeof(RuleSet); class LSystemStrategy : public MelodyStrategy { public: - void generate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int seed) override { + void generate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int seed, int intensity) override { randomSeed(seed); if (numScaleNotes == 0) { // Fill with silence if no scale @@ -76,14 +76,19 @@ public: int octave_stack[8]; int stack_ptr = 0; + // High intensity = more accents, fewer ties (staccato) + // Low intensity = fewer accents, more ties (legato) + int accentChance = intensity * 6; // 6% to 60% + int tieChance = 50 - (intensity * 5); // 45% to 0% + for (char c : currentString) { if (stepIndex >= numSteps) break; switch(c) { case 'F': case 'G': case 'A': case 'B': // Characters that draw notes sequence[track][stepIndex].note = 12 * octave + scaleNotes[noteIndex]; - sequence[track][stepIndex].accent = (random(100) < 25); - sequence[track][stepIndex].tie = (random(100) < 10); + sequence[track][stepIndex].accent = (random(100) < accentChance); + sequence[track][stepIndex].tie = (random(100) < tieChance); stepIndex++; break; case '+': // Go up in scale @@ -135,7 +140,7 @@ public: sortArray(scaleNotes, numScaleNotes); } - void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes) override { + void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int intensity) override { // Swap two non-rest steps to create a variation int s1 = random(numSteps); int s2 = random(numSteps); diff --git a/LuckyStrategy.h b/LuckyStrategy.h index 2ea0dc1..b97e3da 100644 --- a/LuckyStrategy.h +++ b/LuckyStrategy.h @@ -6,14 +6,17 @@ class LuckyStrategy : public MelodyStrategy { public: - void generate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int seed) override { + void generate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int seed, int intensity) override { randomSeed(seed); if (numScaleNotes == 0) return; + int noteChance = intensity * 9; // 10% to 90% + int accentChance = intensity * 6; // 6% to 60% + for (int i = 0; i < numSteps; i++) { int octave = random(3) + 3; // 3, 4, 5 (Base is 4) - sequence[track][i].note = (random(100) < 50) ? (12 * octave + scaleNotes[random(numScaleNotes)]) : -1; - sequence[track][i].accent = (random(100) < 30); + sequence[track][i].note = (random(100) < noteChance) ? (12 * octave + scaleNotes[random(numScaleNotes)]) : -1; + sequence[track][i].accent = (random(100) < accentChance); sequence[track][i].tie = (random(100) < 20); } randomSeed(micros()); @@ -34,7 +37,7 @@ public: sortArray(scaleNotes, numScaleNotes); } - void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes) override { + void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int intensity) override { // Mutate 1 or 2 steps int count = random(1, 3); for (int i = 0; i < count; i++) { diff --git a/MarkovStrategy.h b/MarkovStrategy.h index 65adcc3..f6e32f5 100644 --- a/MarkovStrategy.h +++ b/MarkovStrategy.h @@ -6,7 +6,7 @@ class MarkovStrategy : public MelodyStrategy { public: - void generate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int seed) override { + void generate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int seed, int intensity) override { randomSeed(seed); if (numScaleNotes == 0) return; @@ -32,8 +32,10 @@ public: int currentIdx = random(numScaleNotes); for (int i = 0; i < numSteps; i++) { - // 20% chance of rest - if (random(100) < 20) { + // Intensity 1 = 60% rest, Intensity 10 = 0% rest + int restChance = 60 - (intensity * 6); + if (restChance < 0) restChance = 0; + if (random(100) < restChance) { sequence[track][i].note = -1; sequence[track][i].accent = false; sequence[track][i].tie = false; @@ -85,7 +87,7 @@ public: sortArray(scaleNotes, numScaleNotes); } - void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes) override { + void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int intensity) override { // Drift mutation: pick a note and move it stepwise in the scale int s = random(numSteps); if (sequence[track][s].note != -1) { diff --git a/MelodyStrategy.h b/MelodyStrategy.h index 4d9c040..8e98b99 100644 --- a/MelodyStrategy.h +++ b/MelodyStrategy.h @@ -6,9 +6,9 @@ class MelodyStrategy { public: - virtual void generate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int seed) = 0; + virtual void generate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int seed, int intensity) = 0; virtual void generateScale(int* scaleNotes, int& numScaleNotes) = 0; - virtual void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes) = 0; + virtual void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int intensity) = 0; virtual const char* getName() = 0; virtual ~MelodyStrategy() {} }; diff --git a/SharedState.cpp b/SharedState.cpp index 6a5f898..e05f032 100644 --- a/SharedState.cpp +++ b/SharedState.cpp @@ -15,6 +15,7 @@ volatile bool needsPanic = false; UIState currentState = UI_MENU_MAIN; bool protectedMode = false; +volatile int trackIntensity[NUM_TRACKS] = {10, 10, 10, 10}; // Menus MenuItem menuItems[] = { { "Main", MENU_ID_GROUP_MAIN, true, true, 0 }, @@ -28,6 +29,7 @@ MenuItem menuItems[] = { { "Track", MENU_ID_TRACK_SELECT, false, false, 1 }, { "Mute", MENU_ID_MUTE, false, false, 1 }, { "Flavour", MENU_ID_FLAVOUR, false, false, 1 }, + { "Intensity", MENU_ID_INTENSITY, false, false, 1 }, { "Mutation", MENU_ID_MUTATION, false, false, 1 }, { "Theme 1", MENU_ID_THEME_1, false, false, 1 }, { "Theme 2", MENU_ID_THEME_2, false, false, 1 }, @@ -109,7 +111,7 @@ int numScaleNotes = 0; int melodySeeds[NUM_TRACKS]; volatile int queuedTheme = -1; volatile int currentThemeIndex = 1; -extern const uint32_t EEPROM_MAGIC = 0x4242424D; +extern const uint32_t EEPROM_MAGIC = 0x4242424E; MelodyStrategy* strategies[] = { new LuckyStrategy(), new ArpStrategy(), new EuclideanStrategy(), diff --git a/SharedState.h b/SharedState.h index 1f914d7..cbedfd4 100644 --- a/SharedState.h +++ b/SharedState.h @@ -27,6 +27,7 @@ enum MenuItemID { MENU_ID_TRACK_SELECT, MENU_ID_MUTE, MENU_ID_FLAVOUR, + MENU_ID_INTENSITY, MENU_ID_MUTATION, MENU_ID_THEME_1, MENU_ID_THEME_2, diff --git a/TrackerTypes.h b/TrackerTypes.h index d8b0e3f..601be71 100644 --- a/TrackerTypes.h +++ b/TrackerTypes.h @@ -21,6 +21,7 @@ enum UIState { UI_EDIT_TEMPO, UI_EDIT_STEPS, UI_EDIT_FLAVOUR, + UI_EDIT_INTENSITY, UI_SETUP_PLAYMODE_EDIT, UI_RANDOMIZE_TRACK_EDIT, UI_SCALE_EDIT, diff --git a/UIManager.cpp b/UIManager.cpp index cc869a4..e446554 100644 --- a/UIManager.cpp +++ b/UIManager.cpp @@ -50,10 +50,10 @@ void UIManager::showMessage(const char* msg) { void UIManager::draw(UIState currentState, int menuSelection, int midiChannel, int tempo, MelodyStrategy* currentStrategy, int queuedTheme, int currentThemeIndex, - int numScaleNotes, const int* scaleNotes, int melodySeed, int numSteps, + int numScaleNotes, const int* scaleNotes, int melodySeed, int numSteps, bool mutationEnabled, bool songModeEnabled, const Step sequence[][NUM_STEPS], int playbackStep, bool isPlaying, - int randomizeTrack, const bool* trackMute) { + int randomizeTrack, const bool* trackMute, const int* trackIntensities) { display.clearDisplay(); display.setTextSize(1); @@ -62,7 +62,7 @@ void UIManager::draw(UIState currentState, int menuSelection, switch(currentState) { case UI_MENU_MAIN: - drawMenu(menuSelection, currentState, midiChannel, tempo, currentStrategy->getName(), queuedTheme, currentThemeIndex, numScaleNotes, scaleNotes, melodySeed, numSteps, mutationEnabled, songModeEnabled, isPlaying, randomizeTrack, trackMute); + drawMenu(menuSelection, currentState, midiChannel, tempo, currentStrategy->getName(), queuedTheme, currentThemeIndex, numScaleNotes, scaleNotes, melodySeed, numSteps, mutationEnabled, songModeEnabled, isPlaying, randomizeTrack, trackMute, trackIntensities); break; case UI_SETUP_CHANNEL_EDIT: display.println(F("SET MIDI CHANNEL")); @@ -108,6 +108,9 @@ void UIManager::draw(UIState currentState, int menuSelection, display.setCursor(0, 50); display.println(F(" (Press to confirm)")); break; + case UI_EDIT_INTENSITY: + drawNumberEditor("SET INTENSITY", trackIntensities[randomizeTrack], 1, 10); + break; case UI_RANDOMIZE_TRACK_EDIT: display.println(F("SET TRACK")); display.drawLine(0, 8, 128, 8, SSD1306_WHITE); @@ -202,10 +205,35 @@ void UIManager::draw(UIState currentState, int menuSelection, display.display(); } +void UIManager::drawNumberEditor(const char* title, int value, int minVal, int maxVal) { + display.println(title); + display.drawLine(0, 8, 128, 8, SSD1306_WHITE); + + // Display value + display.setCursor(20, 20); + display.setTextSize(2); + display.print(value); + + // Graphical bar + int barWidth = 100; + int barX = (SCREEN_WIDTH - barWidth) / 2; + int barY = 40; + int barHeight = 10; + float percentage = (float)(value - minVal) / (maxVal - minVal); + int fillWidth = (int)(percentage * barWidth); + + display.drawRect(barX, barY, barWidth, barHeight, SSD1306_WHITE); + display.fillRect(barX, barY, fillWidth, barHeight, SSD1306_WHITE); + + display.setTextSize(1); + display.setCursor(0, 54); + display.println(F(" (Press to confirm)")); +} + void UIManager::drawMenu(int selection, UIState currentState, int midiChannel, int tempo, const char* flavourName, int queuedTheme, int currentThemeIndex, int numScaleNotes, const int* scaleNotes, int melodySeed, int numSteps, bool mutationEnabled, - bool songModeEnabled, bool isPlaying, int randomizeTrack, const bool* trackMute) { + bool songModeEnabled, bool isPlaying, int randomizeTrack, const bool* trackMute, const int* trackIntensities) { // Calculate visual cursor position and scroll offset int visualCursor = 0; @@ -269,6 +297,18 @@ void UIManager::drawMenu(int selection, UIState currentState, int midiChannel, i else if (id == MENU_ID_TRACK_SELECT) { display.print(F(": ")); display.print(randomizeTrack + 1); } else if (id == MENU_ID_MUTE) { display.print(F(": ")); display.print(trackMute[randomizeTrack] ? F("YES") : F("NO")); } else if (id == MENU_ID_FLAVOUR) { display.print(F(": ")); display.print(flavourName); } + else if (id == MENU_ID_INTENSITY) { + display.print(F(": ")); + display.print(trackIntensities[randomizeTrack]); + int val = trackIntensities[randomizeTrack]; + int barX = display.getCursorX() + 3; + int barY = y + 2; + int maxW = 20; + int h = 5; + uint16_t color = (i == selection) ? SSD1306_BLACK : SSD1306_WHITE; + display.drawRect(barX, barY, maxW + 2, h, color); + display.fillRect(barX + 1, barY + 1, (val * maxW) / 10, h - 2, color); + } else if (id == MENU_ID_MUTATION) { display.print(F(": ")); display.print(mutationEnabled ? F("ON") : F("OFF")); } else if (id == MENU_ID_PROTECTED_MODE) { display.print(F(": ")); display.print(protectedMode ? F("ON") : F("OFF")); } diff --git a/UIManager.h b/UIManager.h index a9bd06f..f6643d1 100644 --- a/UIManager.h +++ b/UIManager.h @@ -20,7 +20,7 @@ public: int numScaleNotes, const int* scaleNotes, int melodySeed, int numSteps, bool mutationEnabled, bool songModeEnabled, const Step sequence[][NUM_STEPS], int playbackStep, bool isPlaying, - int randomizeTrack, const bool* trackMute); + int randomizeTrack, const bool* trackMute, const int* trackIntensities); void updateLeds(const Step sequence[][NUM_STEPS], int playbackStep, bool isPlaying, UIState currentState, bool songModeEnabled, @@ -35,7 +35,9 @@ private: void drawMenu(int selection, UIState currentState, int midiChannel, int tempo, const char* flavourName, int queuedTheme, int currentThemeIndex, int numScaleNotes, const int* scaleNotes, int melodySeed, int numSteps, - bool mutationEnabled, bool songModeEnabled, bool isPlaying, int randomizeTrack, const bool* trackMute); + bool mutationEnabled, bool songModeEnabled, bool isPlaying, int randomizeTrack, const bool* trackMute, const int* trackIntensities); + + void drawNumberEditor(const char* title, int value, int minVal, int maxVal); uint32_t getNoteColor(int note, bool dim); int getPixelIndex(int x, int y); diff --git a/UIThread.cpp b/UIThread.cpp index 681e947..00ab425 100644 --- a/UIThread.cpp +++ b/UIThread.cpp @@ -15,6 +15,8 @@ #include "UIThread.h" #include "SharedState.h" +extern volatile int trackIntensity[NUM_TRACKS]; + static Step local_sequence[NUM_TRACKS][NUM_STEPS]; static void handleInput(); @@ -40,6 +42,9 @@ void saveSequence(bool quiet) { for(int i=0; i 16) midiChannels[i] = 16; + } EEPROM.get(addr, melodySeeds); addr += sizeof(melodySeeds); EEPROM.get(addr, currentStrategyIndices); addr += sizeof(currentStrategyIndices); + for(int i=0; i= numStrategies) currentStrategyIndices[i] = 0; + } bool mutes[NUM_TRACKS]; EEPROM.get(addr, mutes); addr += sizeof(mutes); for(int i=0; i 240) tempo = 240; + int intensities[NUM_TRACKS]; + EEPROM.get(addr, intensities); addr += sizeof(intensities); + for(int i=0; i 10) trackIntensity[i] = 10; + } EEPROM.get(addr, t); addr += sizeof(int); numSteps = t; if (numSteps <= 0 || numSteps >= NUM_STEPS) numSteps = NUM_STEPS; EEPROM.get(addr, numScaleNotes); addr += sizeof(numScaleNotes); + if (numScaleNotes < 0 || numScaleNotes > 12) numScaleNotes = 0; for (int i = 0; i<12; i++) { EEPROM.get(addr, scaleNotes[i]); addr += sizeof(int); + if (scaleNotes[i] < 0) scaleNotes[i] = 0; + if (scaleNotes[i] > 11) scaleNotes[i] = 11; } EEPROM.get(addr, sequence); addr += sizeof(sequence); @@ -90,7 +114,7 @@ bool loadSequence() { static void savePatch(int bank, int slot) { int patchIndex = bank * 4 + slot; - int addr = 512 + patchIndex * 128; // Start after main save, 128 bytes per patch + int addr = 512 + patchIndex * 256; // Start after main save, 256 bytes per patch midi.lock(); EEPROM.put(addr, numScaleNotes); addr += sizeof(numScaleNotes); @@ -103,6 +127,9 @@ static void savePatch(int bank, int slot) { bool mutes[NUM_TRACKS]; for(int i=0; i 12) numScaleNotes = 0; for (int i = 0; i < 12; i++) { EEPROM.get(addr, scaleNotes[i]); addr += sizeof(int); + if (scaleNotes[i] < 0) scaleNotes[i] = 0; + if (scaleNotes[i] > 11) scaleNotes[i] = 11; } EEPROM.get(addr, currentStrategyIndices); addr += sizeof(currentStrategyIndices); + for(int i=0; i= numStrategies) currentStrategyIndices[i] = 0; + } EEPROM.get(addr, melodySeeds); addr += sizeof(melodySeeds); int t; EEPROM.get(addr, t); addr += sizeof(int); @@ -127,6 +160,14 @@ static void loadPatch(int bank, int slot) { bool mutes[NUM_TRACKS]; EEPROM.get(addr, mutes); addr += sizeof(mutes); for(int i=0; i 10) trackIntensity[i] = 10; + } if (isPlaying) { generateSequenceData(currentThemeIndex, nextSequence); @@ -141,6 +182,9 @@ static void loadPatch(int bank, int slot) { void factoryReset() { ui.showMessage("RESETTING..."); + for(int i=0; igenerate(target, track, numSteps, scaleNotes, numScaleNotes, melodySeeds[track] + themeType * 12345); + strategies[currentStrategyIndices[track]]->generate(target, track, numSteps, scaleNotes, numScaleNotes, melodySeeds[track] + themeType * 12345, trackIntensity[track]); } void generateRandomScale() { @@ -184,7 +228,7 @@ void generateTheme(int themeType) { } void mutateSequence(Step (*target)[NUM_STEPS]) { - for(int i=0; imutate(target, i, numSteps, scaleNotes, numScaleNotes); + for(int i=0; imutate(target, i, numSteps, scaleNotes, numScaleNotes, trackIntensity[i]); } static void handleInput() { @@ -234,6 +278,15 @@ static void handleInput() { if (currentStrategyIndices[randomizeTrack] >= numStrategies) currentStrategyIndices[randomizeTrack] = 0; } break; + case UI_EDIT_INTENSITY: + { + int current = trackIntensity[randomizeTrack]; + current += delta; + if (current < 1) current = 1; + if (current > 10) current = 10; + trackIntensity[randomizeTrack] = current; + } + break; case UI_SCALE_EDIT: scaleEditSelection += (delta > 0 ? 1 : -1); if (scaleEditSelection < 0) scaleEditSelection = numScaleNotes + 4; @@ -346,6 +399,7 @@ static void handleInput() { case MENU_ID_TRACK_SELECT: currentState = UI_RANDOMIZE_TRACK_EDIT; break; case MENU_ID_MUTE: trackMute[randomizeTrack] = !trackMute[randomizeTrack]; break; case MENU_ID_FLAVOUR: currentState = UI_EDIT_FLAVOUR; break; + case MENU_ID_INTENSITY: currentState = UI_EDIT_INTENSITY; break; case MENU_ID_MUTATION: mutationEnabled = !mutationEnabled; break; case MENU_ID_CHANNEL: currentState = UI_SETUP_CHANNEL_EDIT; break; @@ -405,6 +459,20 @@ static void handleInput() { } saveSequence(true); break; + case UI_EDIT_INTENSITY: + currentState = UI_MENU_MAIN; + if (isPlaying) { + int theme = (queuedTheme != -1) ? queuedTheme : currentThemeIndex; + midi.lock(); + if (!sequenceChangeScheduled) { + memcpy(nextSequence, sequence, sizeof(sequence)); + } + generateTrackData(randomizeTrack, theme, nextSequence); + sequenceChangeScheduled = true; + midi.unlock(); + } + saveSequence(true); + break; case UI_RANDOMIZE_TRACK_EDIT: currentState = UI_MENU_MAIN; saveSequence(true); @@ -505,6 +573,7 @@ static void drawUI() { bool local_mutationEnabled, local_songModeEnabled, local_isPlaying; bool local_trackMute[NUM_TRACKS]; int local_midiChannel; + int local_trackIntensities[NUM_TRACKS]; MelodyStrategy* local_strategy; int local_playbackStep; int local_scaleNotes[12]; @@ -533,12 +602,13 @@ static void drawUI() { local_playbackStep = playbackStep; local_isPlaying = isPlaying; memcpy(local_trackMute, (const void*)trackMute, sizeof(local_trackMute)); + memcpy(local_trackIntensities, (const void*)trackIntensity, sizeof(local_trackIntensities)); midi.unlock(); ui.draw(local_currentState, local_menuSelection, local_midiChannel, local_tempo, local_strategy, local_queuedTheme, local_currentThemeIndex, local_numScaleNotes, local_scaleNotes, local_melodySeed, local_numSteps, - local_mutationEnabled, local_songModeEnabled, (const Step (*)[NUM_STEPS])local_sequence, local_playbackStep, local_isPlaying, local_randomizeTrack, (const bool*)local_trackMute); + local_mutationEnabled, local_songModeEnabled, (const Step (*)[NUM_STEPS])local_sequence, local_playbackStep, local_isPlaying, local_randomizeTrack, (const bool*)local_trackMute, (const int*)local_trackIntensities); } static void updateLeds() {