#ifndef CALL_AND_RESPONSE_STRATEGY_H #define CALL_AND_RESPONSE_STRATEGY_H #include "MelodyStrategy.h" #include class CallAndResponseStrategy : public MelodyStrategy { public: void generate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int* chordNotes, int numChordNotes, int seed, int intensity) override { randomSeed(seed); int* sourceNotes = (numChordNotes > 0) ? chordNotes : scaleNotes; int sourceNoteCount = (numChordNotes > 0) ? numChordNotes : numScaleNotes; if (sourceNoteCount == 0) return; // Clear sequence first for (int i = 0; i < numSteps; i++) { sequence[track][i].note = -1; sequence[track][i].accent = false; sequence[track][i].tie = false; } int callLength = random(2, numSteps / 2); int responseLength = callLength; int callStart = 0; int responseStart = numSteps / 2; // Generate Call for (int i = 0; i < callLength; i++) { if (random(100) < intensity * 9) { int octave = 3 + random(3); sequence[track][callStart + i].note = 12 * octave + sourceNotes[random(sourceNoteCount)]; sequence[track][callStart + i].accent = (i == 0); } } // Generate Response (variation of call) for (int i = 0; i < responseLength; i++) { sequence[track][responseStart + i] = sequence[track][callStart + i]; // Small chance to change note if (sequence[track][responseStart + i].note != -1 && random(100) < 30) { int octave = (sequence[track][responseStart + i].note / 12) + random(-1, 2); if (octave < 3) octave = 3; if (octave > 5) octave = 5; sequence[track][responseStart + i].note = 12 * octave + sourceNotes[random(sourceNoteCount)]; } } randomSeed(micros()); } void generateScale(int* scaleNotes, int& numScaleNotes) override { // This strategy doesn't generate its own scales, but the method must be implemented. } void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int* chordNotes, int numChordNotes, int intensity) override { // For simplicity, just regenerate with a new seed. generate(sequence, track, numSteps, scaleNotes, numScaleNotes, chordNotes, numChordNotes, random(65536), intensity); } const char* getName() override { return "Call/Resp"; } }; #endif