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
+75 -16
View File
@@ -3,24 +3,65 @@
#include "MidiDriver.h"
#include <Arduino.h>
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);
strategies[currentStrategyIndices[track]]->generate(target, track, numSteps[track], scaleNotes, numScaleNotes, melodySeeds[track] + themeType * 12345, trackIntensity[track]);
}
void SequenceGenerator::generateSequenceData(int themeType, Step (*target)[NUM_STEPS]) {
Serial.println(F("Generating sequence."));
for(int i=0; i<NUM_TRACKS; i++) {
SequenceGenerator::generateTrackData(i, themeType, target);
}
}
void SequenceGenerator::mutateSequence(Step (*target)[NUM_STEPS]) {
for(int i=0; i<NUM_TRACKS; i++) {
if (random(100) < (trackIntensity[i] * 10)) {
strategies[currentStrategyIndices[i]]->mutate(target, i, numSteps[i], scaleNotes, numScaleNotes, trackIntensity[i]);
}
}
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() {
@@ -75,6 +116,24 @@ void SequenceGenerator::updateScale() {
midi.unlock();
}
void SequenceGenerator::generateSequenceData(int themeType, Step (*target)[NUM_STEPS]) {
Serial.println(F("Generating sequence."));
for(int i=0; i<NUM_TRACKS; i++) {
SequenceGenerator::generateTrackData(i, themeType, target);
}
}
void SequenceGenerator::mutateSequence(Step (*target)[NUM_STEPS]) {
int chordNotes[12];
int numChordNotes = 0;
getChordNotes(chordNotes, numChordNotes);
for(int i=0; i<NUM_TRACKS; i++) {
if (random(100) < (trackIntensity[i] * 10)) {
strategies[currentStrategyIndices[i]]->mutate(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<NUM_TRACKS; i++) seed += melodySeeds[i];