xxxxxxxxxx
119
let markovChain = {};
let midiData;
let currentNote = "C4"; // Starting note, adjust as needed
function preload() {
loadMIDIFile('Fly_Me_to_the_Moon.mid');
}
function loadMIDIFile(filename) {
httpDo(filename, {
method: 'GET',
responseType: 'arraybuffer'
}, function(result) {
midiData = result; // This will be an ArrayBuffer of the MIDI file
onMIDILoaded();
}, function(error) {
console.error("Failed to load MIDI file:", error);
});
}
function onMIDILoaded() {
// Ensure MIDI data is loaded
if (midiData) {
// Parse MIDI data here using a MIDI parsing library
parseMIDI(midiData);
// Rest of the code that depends on midiData
}
}
function parseMIDI(data) {
// Implement MIDI parsing logic here
// After parsing, you can build the Markov chain and generate melodies
}
function setup() {
noCanvas();
// Parse MIDI file and build Markov chain
buildMarkovChain();
// Set up Tone.js
const synth = new Tone.Synth().toDestination();
Tone.Transport.start();
// Schedule melody generation and playback
Tone.Transport.scheduleRepeat(time => {
playMelody(synth);
}, "1m"); // '1m' is one measure in Tone.js timing
}
function buildMarkovChain(midiData) {
// Initialize an empty object for the Markov chain
let chain = {};
// Iterate over the MIDI data to fill the Markov chain
for (let i = 0; i < midiData.length - 1; i++) {
let currentNote = midiData[i];
let nextNote = midiData[i + 1];
if (!chain[currentNote]) {
chain[currentNote] = {};
}
if (!chain[currentNote][nextNote]) {
chain[currentNote][nextNote] = 0;
}
// Increment the count of this transition
chain[currentNote][nextNote]++;
}
// Convert counts to probabilities
for (let note in chain) {
let total = 0;
for (let next in chain[note]) {
total += chain[note][next];
}
for (let next in chain[note]) {
chain[note][next] /= total;
}
}
return chain;
}
function generateMelody(markovChain, startNote, length) {
let melody = [startNote];
let currentNote = startNote;
for (let i = 1; i < length; i++) {
currentNote = chooseNextNote(markovChain, currentNote);
melody.push(currentNote);
}
return melody;
}
function chooseNextNote(markovChain, currentNote) {
let nextNotes = markovChain[currentNote];
let total = 0;
let r = Math.random();
for (let note in nextNotes) {
total += nextNotes[note];
if (r <= total) {
return note;
}
}
// Fallback in case of rounding errors or empty chain
return Object.keys(markovChain)[Math.floor(Math.random() * Object.keys(markovChain).length)];
}
function playMelody(synth) {
let nextNote = generateNextNote();
synth.triggerAttackRelease(nextNote, "8n"); // Play note for an eighth note duration
currentNote = nextNote; // Update the current note
}