#ifndef DRONE_STRATEGY_H #define DRONE_STRATEGY_H #include "MelodyStrategy.h" #include class DroneStrategy : public MelodyStrategy { public: 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; // Intensity 1: Very long notes (1-2 per sequence) // Intensity 10: Short notes (active) // Map intensity to duration range // Low intensity (1) -> Max duration is full sequence // High intensity (10) -> Max duration is short (e.g. 4 steps) int maxDur = map(intensity, 1, 10, numSteps, 4); int minDur = map(intensity, 1, 10, numSteps, 1); if (minDur < 1) minDur = 1; if (maxDur < minDur) maxDur = minDur; int currentStep = 0; while (currentStep < numSteps) { int duration = random(minDur, maxDur + 1); // Pick a note from the scale // Prefer lower octaves for drones (3 and 4) int octave = 3 + random(2); int noteIndex = random(numScaleNotes); int note = 12 * octave + scaleNotes[noteIndex]; for (int k = 0; k < duration; k++) { int stepIndex = currentStep + k; if (stepIndex >= numSteps) break; sequence[track][stepIndex].note = note; // Tie notes to create continuous sound (legato) sequence[track][stepIndex].tie = true; // Accent only the start of the note sequence[track][stepIndex].accent = (k == 0); } currentStep += duration; } randomSeed(micros()); } void generateScale(int* scaleNotes, int& numScaleNotes) override { // Drones work well with fewer notes (Pentatonic or Triad) numScaleNotes = random(3, 6); for (int i = 0; i < 12; i++) { scaleNotes[i] = i; } // Shuffle for (int i = 0; i < 12; i++) { int j = random(12); int temp = scaleNotes[i]; scaleNotes[i] = scaleNotes[j]; scaleNotes[j] = temp; } sortArray(scaleNotes, numScaleNotes); } void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int intensity) override { // Mutate by shifting the pitch of a random segment int s = random(numSteps); if (sequence[track][s].note != -1) { int originalNote = sequence[track][s].note; // Find the bounds of this note int start = s; while (start > 0 && sequence[track][start-1].note == originalNote && sequence[track][start-1].tie) { start--; } int end = s; while (end < numSteps - 1 && sequence[track][end].tie && sequence[track][end+1].note == originalNote) { end++; } // Pick a new note int octave = 3 + random(2); int newNote = 12 * octave + scaleNotes[random(numScaleNotes)]; for (int i = start; i <= end; i++) { sequence[track][i].note = newNote; } } } const char* getName() override { return "Drone"; } }; #endif