06-20-2022, 09:41 AM
haha just kidding i made it betterer
now it instantly inserts the new melody into the sequencer, and it supports undo
you can also make it whatever instrument you want
have fun
Code:
function generateMelody(instr=instrument, swing=false, beatCount=16, keySignature='Minor', noteVarianceFactor=30, octave=5, note=1) {
note = clamp(note, 1, 12) | 0;
octave = clamp(octave, 2, 7) | 0;
while (noteVarianceFactor < 10) noteVarianceFactor += 5;
while (beatCount < 1) beatCount += 1;
const notes = [];
let noteDict;
switch (keySignature) {
case undefined: noteDict = settings.pianoNotes; break;
case 'Major': noteDict = settings.scales[1].slice(0, 7); break;
case 'Minor': noteDict = settings.scales[13].slice(0, 7); break;
case 'play infinitode 2': noteDict = ['C', 'D#', 'F', 'G', 'A#']; break;
default: throw new Error("That's not a real key signature. Come on, man. You're better than this. (valid key signatures are 'Minor', 'Major', or undefined)")
}
let midTendencyFactor = [10, 7, 4, 0, -5, -10];
function createNote(time, pitch, length, ID) {
notes.push(new Note(song, pitch, time, length, ID));
}
function randomlyShiftPitch() {
let lowerBound = -noteVarianceFactor + midTendencyFactor[octave-2];
let higherBound = noteVarianceFactor - midTendencyFactor[octave-2];
let offset = Math.round(
(Math.random() * (higherBound - lowerBound) + lowerBound) / 10
);
note += offset;
while (note > noteDict.length) {
if (octave == 7) {
note = noteDict.length;
} else {
note -= noteDict.length
octave += 1
}
}
while (note < 1)
if (octave == 2) {
note = 1
} else {
note += noteDict.length
octave -= 1
}
}
const quarterBased = [[0, 2], [1, 3], [0, 1, 2], [0, 2, 3], 0, 2, [0, 3], null],
thirdBased = [0, 8/3, [0, 8/3], [0, 4/3, 8/3]],
riff = [
[0, 1, 2, 3],
[0, 1, 6/3, 8/3, 10/3],
[0/3, 2/3, 4/3, 6/3, 8/3, 10/3],
[0/3, 2/3, 4/3, 2, 3]
// 0/3 and 6/3 are present so the triplets are clearer
],
riffing = !swing;
let beatCounter = 0, riffChancemaker = 0;
function generateBeat() {
let beatNotes = swing ? thirdBased[(Math.random() * thirdBased.length) | 0] : quarterBased[(Math.random() * quarterBased.length) | 0]
if (beatNotes === null) {
++beatCounter;
if (Math.round(Math.random())) riffChancemaker += Math.round(Math.random())
if (riffChancemaker == 4) generateRiff();
return;
};
if (typeof beatNotes == 'object') {
for (let x of beatNotes) {
randomlyShiftPitch(note, octave);
let noteLength = ((x | 0) === x) ? 1 : 2/3;
createNote(x + (beatCounter * 4), `${noteDict[note-1]}${octave}`, noteLength, instr)
}
} else {
randomlyShiftPitch(note, octave)
let noteLength = ((beatNotes | 0) === beatNotes) ? 1 : 2/3;
createNote(beatNotes + (beatCounter * 4), `${noteDict[note-1]}${octave}`, noteLength, instr)
}
++beatCounter;
if (Math.round(Math.random())) riffChancemaker += Math.round(Math.random())
if (riffChancemaker == 4) generateRiff();
}
function generateRiff() {
if (!riffing) return;
while (riffChancemaker > 0) {
let beatNotes = riff[(Math.random() * riff.length) | 0];
for (let x of beatNotes) {
randomlyShiftPitch(note, octave)
let noteLength = ((x | 0) === x) ? 1 : 2/3;
createNote(x + (beatCounter * 4), `${noteDict[note-1]}${octave}`, noteLength, instr)
}
riffChancemaker -= 2
beatCounter += 1
if (riffChancemaker < 0) break
}
}
while (beatCounter < beatCount) generateBeat();
exec(() => {
for(let note of notes) song.addNote(note);
SequencerView.repaint();
}, () => {
for (let note of notes) song.removeNote(note);
SequencerView.repaint();
})
}
you can also make it whatever instrument you want
have fun
pseudoname