#include "SequenceGenerator.h" #include "SharedState.h" #include "MidiDriver.h" #include void SequenceGenerator::getChordNotes(int* chordNotes, int& numChordNotes) { numChordNotes = 0; if (numScaleNotes == 0) return; // For explicit chord types, chord notes are the scale notes if (currentScaleType >= 6 && currentScaleType <= 9) { numChordNotes = numScaleNotes; for (int i = 0; i < numScaleNotes; i++) { chordNotes[i] = scaleNotes[i]; } return; } // For other scales, derive the basic triad (root, third, fifth) from the current scale chordNotes[numChordNotes++] = currentRoot; // Find the third (major or minor) int majorThird = (currentRoot + 4) % 12; int minorThird = (currentRoot + 3) % 12; bool thirdFound = false; for (int i = 0; i < numScaleNotes; i++) { if (scaleNotes[i] == majorThird) { chordNotes[numChordNotes++] = majorThird; thirdFound = true; break; } } if (!thirdFound) { for (int i = 0; i < numScaleNotes; i++) { if (scaleNotes[i] == minorThird) { chordNotes[numChordNotes++] = minorThird; break; } } } // Find the fifth (perfect, or diminished if not found) int perfectFifth = (currentRoot + 7) % 12; int diminishedFifth = (currentRoot + 6) % 12; for (int i = 0; i < numScaleNotes; i++) { if (scaleNotes[i] == perfectFifth) { chordNotes[numChordNotes++] = perfectFifth; return; } } for (int i = 0; i < numScaleNotes; i++) { if (scaleNotes[i] == diminishedFifth) { chordNotes[numChordNotes++] = diminishedFifth; break; } } } void SequenceGenerator::generateTrackData(int track, int themeType, Step (*target)[NUM_STEPS]) { randomSeed(melodySeeds[track] + themeType * 12345); int chordNotes[12]; int numChordNotes = 0; getChordNotes(chordNotes, numChordNotes); strategies[currentStrategyIndices[track]]->generate(target, track, numSteps[track], scaleNotes, numScaleNotes, chordNotes, numChordNotes, melodySeeds[track] + themeType * 12345, trackIntensity[track]); } void SequenceGenerator::generateRandomScale() { Serial.println(F("Generating new scale.")); SequenceGenerator::updateScale(); } void SequenceGenerator::updateScale() { // 0: Chromatic, 1: Major, 2: Minor, 3: Harm Min, 4: Pent Maj, 5: Pent Min, 6: Chord Maj, 7: Chord Min, 8: Chord Dim, 9: Chord 7 int intervals[12]; int count = 0; switch(currentScaleType) { case 0: // Chromatic for(int i=0; i<12; i++) intervals[count++] = i; break; case 1: // Major intervals[0]=0; intervals[1]=2; intervals[2]=4; intervals[3]=5; intervals[4]=7; intervals[5]=9; intervals[6]=11; count=7; break; case 2: // Minor intervals[0]=0; intervals[1]=2; intervals[2]=3; intervals[3]=5; intervals[4]=7; intervals[5]=8; intervals[6]=10; count=7; break; case 3: // Harmonic Minor intervals[0]=0; intervals[1]=2; intervals[2]=3; intervals[3]=5; intervals[4]=7; intervals[5]=8; intervals[6]=11; count=7; break; case 4: // Pentatonic Major intervals[0]=0; intervals[1]=2; intervals[2]=4; intervals[3]=7; intervals[4]=9; count=5; break; case 5: // Pentatonic Minor intervals[0]=0; intervals[1]=3; intervals[2]=5; intervals[3]=7; intervals[4]=10; count=5; break; case 6: // Chord Major intervals[0]=0; intervals[1]=4; intervals[2]=7; count=3; break; case 7: // Chord Minor intervals[0]=0; intervals[1]=3; intervals[2]=7; count=3; break; case 8: // Chord Dim intervals[0]=0; intervals[1]=3; intervals[2]=6; count=3; break; case 9: // Chord 7 intervals[0]=0; intervals[1]=4; intervals[2]=7; intervals[3]=10; count=4; break; } midi.lock(); numScaleNotes = count; for(int i=0; imutate(target, i, numSteps[i], scaleNotes, numScaleNotes, chordNotes, numChordNotes, trackIntensity[i]); } } } void SequenceGenerator::pickRandomScaleType(int themeType) { unsigned long seed = themeType * 9999; for(int i=0; i