More harmony through chord notes

This commit is contained in:
Dejvino
2026-03-10 21:58:03 +01:00
parent f34f960358
commit aa51e1e95a
13 changed files with 269 additions and 242 deletions
+23 -15
View File
@@ -6,17 +6,21 @@
class MarkovStrategy : public MelodyStrategy {
public:
void generate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int seed, int intensity) override {
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);
if (numScaleNotes == 0) return;
int* sourceNotes = (numChordNotes > 0) ? chordNotes : scaleNotes;
int sourceNoteCount = (numChordNotes > 0) ? numChordNotes : numScaleNotes;
if (sourceNoteCount == 0) return;
// Transition matrix: weights for moving from index i to index j
// Max scale size is 12
uint8_t matrix[12][12];
// Initialize matrix with weighted probabilities
for (int i = 0; i < numScaleNotes; i++) {
for (int j = 0; j < numScaleNotes; j++) {
for (int i = 0; i < sourceNoteCount; i++) {
for (int j = 0; j < sourceNoteCount; j++) {
// Base random weight
matrix[i][j] = random(1, 8);
@@ -29,7 +33,7 @@ public:
}
}
int currentIdx = random(numScaleNotes);
int currentIdx = random(sourceNoteCount);
for (int i = 0; i < numSteps; i++) {
// Intensity 1 = 60% rest, Intensity 10 = 0% rest
@@ -44,13 +48,13 @@ public:
// Select next note based on matrix
int totalWeight = 0;
for (int j = 0; j < numScaleNotes; j++) {
for (int j = 0; j < sourceNoteCount; j++) {
totalWeight += matrix[currentIdx][j];
}
int r = random(totalWeight);
int nextIdx = 0;
for (int j = 0; j < numScaleNotes; j++) {
for (int j = 0; j < sourceNoteCount; j++) {
r -= matrix[currentIdx][j];
if (r < 0) {
nextIdx = j;
@@ -65,7 +69,7 @@ public:
if (rOct < 20) octave = 3;
else if (rOct > 80) octave = 5;
sequence[track][i].note = 12 * octave + scaleNotes[currentIdx];
sequence[track][i].note = 12 * octave + sourceNotes[currentIdx];
sequence[track][i].accent = (random(100) < 25);
sequence[track][i].tie = (random(100) < 15);
}
@@ -87,15 +91,19 @@ public:
sortArray(scaleNotes, numScaleNotes);
}
void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int intensity) override {
void mutate(Step (*sequence)[NUM_STEPS], int track, int numSteps, int* scaleNotes, int numScaleNotes, int* chordNotes, int numChordNotes, int intensity) override {
int* sourceNotes = (numChordNotes > 0) ? chordNotes : scaleNotes;
int sourceNoteCount = (numChordNotes > 0) ? numChordNotes : numScaleNotes;
if (sourceNoteCount == 0) return;
// Drift mutation: pick a note and move it stepwise in the scale
int s = random(numSteps);
if (sequence[track][s].note != -1) {
int currentNoteVal = sequence[track][s].note % 12;
int idx = -1;
// Find index in scale
for(int i=0; i<numScaleNotes; i++) {
if (scaleNotes[i] == currentNoteVal) {
for(int i=0; i<sourceNoteCount; i++) {
if (sourceNotes[i] == currentNoteVal) {
idx = i;
break;
}
@@ -103,17 +111,17 @@ public:
if (idx != -1) {
// Move up or down 1 step in scale
if (random(2) == 0) idx = (idx + 1) % numScaleNotes;
else idx = (idx - 1 + numScaleNotes) % numScaleNotes;
if (random(2) == 0) idx = (idx + 1) % sourceNoteCount;
else idx = (idx - 1 + sourceNoteCount) % sourceNoteCount;
int octave = sequence[track][s].note / 12;
sequence[track][s].note = 12 * octave + scaleNotes[idx];
sequence[track][s].note = 12 * octave + sourceNotes[idx];
}
} else {
// Chance to fill a rest
if (random(100) < 25) {
int octave = 3 + random(3);
sequence[track][s].note = 12 * octave + scaleNotes[random(numScaleNotes)];
sequence[track][s].note = 12 * octave + sourceNotes[random(sourceNoteCount)];
sequence[track][s].accent = false;
sequence[track][s].tie = false;
}