Skip to content

Instantly share code, notes, and snippets.

@ricardoalcocer
Last active January 4, 2023 15:58
Show Gist options
  • Save ricardoalcocer/cb3042acf7f7ece1bc62390a34756812 to your computer and use it in GitHub Desktop.
Save ricardoalcocer/cb3042acf7f7ece1bc62390a34756812 to your computer and use it in GitHub Desktop.
Generate Musical Motif

This code was generated by a conversation with ChatGPT

  1. The function starts by defining an object modes that maps mode names to arrays of pitch classes, in the same way as the previous version of the function.
  2. It then extracts the tonic of the key and determines whether the key is minor or major, in the same way as the previous version of the function.
  3. It calculates the key number of the tonic (i.e., its position in the chromatic scale starting from C) by looking it up in the array of pitch names, in the same way as the previous version of the function.
  4. It calculates the pitch classes of the mode by adding the key number to the pitch classes of the mode in the modes object, and taking the modulo 12 of the result to wrap around the octave, in the same way as the previous version of the function.
  5. It initializes an empty array motifs that will store the motifs, and a Set object usedPitchClasses that will store the pitch classes used in the current motif.
  6. It enters a loop that will run until the number of motifs in the motifs array reaches the number specified by the numMotifs argument.
  7. In each iteration of the loop, it initializes an empty array motif that will store the notes of the current motif, and a boolean flag foundUniqueMotif that will be used to check whether the current motif is unique.
  8. It enters another loop that will run for the length of the motif specified by the motifLength argument.
  9. In each iteration of the inner loop, it generates a random index between 0 and the length of the pitchClasses array.
  10. It retrieves the pitch class at this index, and checks whether it has already been used in the current motif by checking whether it is in the usedPitchClasses set.
  11. If the pitch class has not been used, it adds it to the motif array and the usedPitchClasses set. If the pitch class has already been used, it sets the foundUniqueMotif flag to false and breaks out of the inner loop.
  12. When the inner loop finishes, it checks the value of the foundUniqueMotif flag. If it is true, it adds the motif array to the motifs array, clears the usedPitchClasses set, and continues the outer loop. If it is false, it discards the current motif and continues the outer loop.
  13. When the outer loop finishes, it returns the motifs array.

Here's an example: https://jsbin.com/dayisat/edit?js,console,output

function getMotifs(key, mode, motifLength, numMotifs) {
const modes = {
"ionian": [0, 2, 4, 5, 7, 9, 11],
"dorian": [0, 2, 3, 5, 7, 9, 10],
"phrygian": [0, 1, 3, 5, 7, 8, 10],
"lydian": [0, 2, 4, 6, 7, 9, 11],
"mixolydian": [0, 2, 4, 5, 7, 9, 10],
"aeolian": [0, 2, 3, 5, 7, 8, 10],
"locrian": [0, 1, 3, 5, 6, 8, 10]
};
const tonic = key[0].toUpperCase();
const isMinor = key[1] === "m";
const keyNumber = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"].indexOf(tonic);
const pitchClasses = modes[mode.toLowerCase()].map(pitchClass => (pitchClass + keyNumber) % 12);
const motifs = [];
const usedPitchClasses = new Set();
while (motifs.length < numMotifs) {
const motif = [];
let foundUniqueMotif = true;
for (let j = 0; j < motifLength; j++) {
const pitchClassIndex = Math.floor(Math.random() * pitchClasses.length);
const pitchClass = pitchClasses[pitchClassIndex];
if (usedPitchClasses.has(pitchClass)) {
foundUniqueMotif = false;
break;
}
motif.push(["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"][pitchClass]);
}
if (foundUniqueMotif) {
usedPitchClasses.clear();
motifs.push(motif);
}
}
return motifs;
}
console.log(getMotifs("Em", "Aeolian", 5, 1));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment