UNPKG

maia-markov

Version:

Markov analysis and generation functions supporting various applications by Music Artificial Intelligence Algorithms, Inc.

116 lines (105 loc) 3.68 kB
// Copyright Tom Collins, 3.3.2020 // Generating bass excerpts in 4-4 time for AI Eurovision 2020 project. // Individual user paths. const mainPaths = { "tom": { "stm": __dirname + "/stm/aiev2020_data_bass.js", "initial": __dirname + "/stm/aiev2020_data_bass_initial.js", "outputDir": __dirname + "/out/aiev_data_bass/" }, "anotherUser": { "stm": "", "initial": "", "outputDir": "" } } // Requires. const fs = require("fs") const sr = require('seed-random') const { Midi } = require('@tonejs/midi') const gn = require("./generate") // Set up parameters. let seeds = ["BBQ chicken", "Bianca", "Calzone", "Caprese", "Capricciosa", "Dessert", "Diavola", "Focaccia", "Funghi", "Frutti di mare", "Hawaiian", "La Reine", "Liguria", "Margherita", "Marinara", "Napoletana", "Pepperoni", "Pugliese", "Prosciutto", "Quattro formagi", "Quattro stagioni", "Romana", "Sfincione", "Sicilian", "Sloppy Guiseppe", "Tirolese", "Tuna", "Vegetariana", "Veronese", "Viennese"] let param = { "stateType": "beat_rel_MNN_state", "pointReconstruction": "rel_MNN", "timeSignatures": [ {"barNo": 1, "topNo": 4, "bottomNo": 4, "ontime": 0} ], "stm": null, "initial": null, "nosConsecutives": 4, "ontimeUpperLimit": 16, "indices": { "ontime": 0, "MNN": 1, "MPN": 2, "duration": 3, "channel": 4, "velocity": 5 }, "randCount": 0 } // Grab user name from command line to set path to data. let nextU = false let pathsEtc; process.argv.forEach(function(arg, ind){ if (arg === "-u"){ nextU = true } else if (nextU){ pathsEtc = mainPaths[arg] nextU = false } }) // fs.mkdir(outdir); const stmStr = fs.readFileSync(pathsEtc.stm); param.stm = JSON.parse(stmStr); const initialStr = fs.readFileSync(pathsEtc.initial); param.initial = JSON.parse(initialStr); // console.log("stm:", stm) // Seed random number generation. // sr('christianeriksen', {global: true}); // Overrides global Math.random. // var numA = Math.random(); // console.log(numA); // sr.resetGlobal();// Reset to default Math.random. seeds.map(function(seed){ // Seed random number generation. sr(seed, {global: true}) // Reset randCount, then generate states and points. param.randCount = 0 console.log("randCount before get_abs_suggestion:", param.randCount) var gendOutput = gn.get_suggestion(param) console.log("randCount after get_abs_suggestion:", gendOutput.randCount) // console.log("gendOutput.points:", gendOutput.points) // Convert points to a key according to the initial state. gendOutput.points = gendOutput.points.map(function(p){ p[param.indices.MNN] += gendOutput.stateContextPairs[0].context .tonic_pitch_closest[0] //60 p[param.indices.MPN] += gendOutput.stateContextPairs[0].context .tonic_pitch_closest[1] //60 return p }) // Save points as a MIDI file and state-context pairs as a text file. let midi = new Midi() console.log("midi.header:", midi.header) let track = midi.addTrack() gendOutput.points.map(function(p){ track.addNote({ midi: p[param.indices.MNN], time: p[param.indices.ontime], duration: p[param.indices.duration], velocity: p[param.indices.velocity] }) }) fs.writeFileSync( pathsEtc.outputDir + "bass_" + seed + ".mid", new Buffer(midi.toArray()) ) // track.notes = track.notes.map(function(n){ // n.time *= 0.5 // n.duration *= 0.5 // return n // }) // fs.writeFileSync( // pathsEtc.outputDir + "bass_" + seed + "_ableton.mid", // new Buffer(midi.toArray()) // ) fs.writeFileSync( pathsEtc.outputDir + "bass_" + seed + ".txt", JSON.stringify(gendOutput.stateContextPairs, null, 2) ) })