PicoWaveTracker/CellularAutomataStrategy.h
2026-03-10 21:58:03 +01:00

63 lines
2.4 KiB
C++

#ifndef CELLULAR_AUTOMATA_STRATEGY_H
#define CELLULAR_AUTOMATA_STRATEGY_H
#include "MelodyStrategy.h"
#include <Arduino.h>
class CellularAutomataStrategy : 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;
bool cells[NUM_STEPS];
for (int i = 0; i < numSteps; i++) {
cells[i] = (random(100) < (intensity * 8)); // Initial density
}
int rule = random(256); // Wolfram rule
for (int gen = 0; gen < 4; gen++) { // A few generations
bool next_cells[NUM_STEPS];
for (int i = 0; i < numSteps; i++) {
bool left = cells[(i - 1 + numSteps) % numSteps];
bool middle = cells[i];
bool right = cells[(i + 1) % numSteps];
int index = (left << 2) | (middle << 1) | right;
next_cells[i] = (rule >> index) & 1;
}
memcpy(cells, next_cells, sizeof(cells));
}
for (int i = 0; i < numSteps; i++) {
if (cells[i]) {
int octave = 3 + random(3);
sequence[track][i].note = 12 * octave + sourceNotes[random(sourceNoteCount)];
sequence[track][i].accent = (random(100) < 20);
sequence[track][i].tie = false;
} else {
sequence[track][i].note = -1;
sequence[track][i].accent = false;
sequence[track][i].tie = false;
}
}
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 "Cellular";
}
};
#endif