//number of notes
timevar = 100
timetracker = -timevar
//button to init program
window.onload = function() {
document.querySelector('button').addEventListener('click', () => initialise())
}
//main program
function initialise() {
//add to timetracker till == timevar
timetracker += timevar
//init matrix with probabilities
genmatrix = math.matrix([
[0.21, 0.26, 0.16, 0.18, 0.19],
[0.19, 0.24, 0.18, 0.18, 0.21],
[0.25, 0.05, 0.50, 0.10, 0.10],
[0.14, 0.10, 0.15, 0.50, 0.11],
[0.50, 0.25, 0.12, 0.06, 0.07]
])
//array to determine notes
initvec = math.matrix([1., 0., 0., 0., 0.])
//multiply matrices to get new probabilities
prod = math.multiply(initvec, genmatrix)
//assign value to array that plays note
notevec = initvec
//get timevar amount of notes
for (var i = 0; i <= timevar; i++) {
//new probabilities
prod = math.multiply(notevec, genmatrix)
//assign value to array that plays note
notevec = getnote(prod)
//function trigger notes
notes(i)
}
var BPM = 80
//function that triggers notes
function notes(a) {
//init synth tone
var synth = new Tone.Synth().toMaster()
Tone.Transport.bpm.value = 70;
var drum = new Tone.MembraneSynth().toMaster()
var loop = new Tone.Loop(function(time) {
//triggered every eighth note.
console.log(time);
}, "8n").start(0);
Tone.Transport.start();
//log value of array
console.log(notevec._data)
//dict with notes
var NoteDict = {
0: "G3",
1: "A#3",
2: "C3",
3: "D3",
4: "F3",
5: "G3",
6: "A#3"
}
var NoteDict2 = {
0: "G2",
1: "A#2",
2: "C2",
3: "D2",
4: "F2",
5: "G2",
6: "A#2"
}
//check which value is == 1
var i
for (i = 0; i <= 4; i++) {
if (notevec._data[i] == 1) {
break
}
}
//trigger note
Tone.Transport.scheduleRepeat(function(time) {
}, '8n')
synth.triggerAttackRelease(NoteDict[i], "8n", a / 4 + timetracker);
drum.triggerAttackRelease(NoteDict2[i], "2n", a + timetracker + math.random(0, 0.02))
//drum2.triggerAttackRelease("G5", "4n", a+timetracker)
}
function getnote(v) {
randno = math.random()
sel = 0
sumfore = 0
for (var i = 0; i <= v._size[0]; i++) {
sumfore = sumfore + v._data[i]
if (randno < sumfore) {
sel = i
break
}
}
vret = math.zeros(v._size[0])
vret._data[i] = 1
return vret
}
//keydown eventlistener
window.addEventListener("keydown", keysPressed, false);
keys_pressed = [0, 0]
keys_reset_counter = 0
function keysPressed(e) {
// store an entry for every key pressed
keys_reset_counter++
if (keys_reset_counter % 2 == 0) {
keys_pressed = [e, 0]
} else {
keys_pressed[1] = e
}
//assign keypress number to rowswitch function
if (keys_reset_counter % 2 != 0) {
if (keys_pressed[0].keyCode >= 49 && keys_pressed[0].keyCode <= 53 && keys_pressed[1].keyCode >= 49 && keys_pressed[1].keyCode <= 53) {
genmatrix = rowswitch(keys_pressed[0].keyCode - 49, keys_pressed[1].keyCode - 49, genmatrix)
console.log(genmatrix)
console.log(keys_pressed)
}
}
if (keys_reset_counter % 2 != 0) {
if (keys_pressed[0].keyCode >= 54 && keys_pressed[0].keyCode <= 57 && keys_pressed[1].keyCode >= 54 && keys_pressed[1].keyCode <= 57) {
genmatrix = colswitch(keys_pressed[0].keyCode - 54, keys_pressed[1].keyCode - 54, genmatrix)
console.log(genmatrix)
console.log(keys_pressed)
}
}
}
//switching rows
function rowswitch(i1, i2, mat) {
//take mat, construct row switching mat.
console.log(mat._size)
rowswitcher = math.identity(mat._size)
storage = rowswitcher[i2]
rowswitcher[i2] = rowswitcher[i1]
rowswitcher[i1] = storage
return math.multiply(rowswitcher, mat)
}
//switching columns
function colswitch(i1, i2, mat) {
//take matrice, construct col seitching matrice
colswitcher = math.identity(mat._size)
storage = colswitcher[i2]
colswitcher[i2] = colswitcher[i1]
colswitcher[i1] = storage
return math.multiply(mat, colswitcher)
}
function setup() {
}
}
По сути, мы генерируем музыку из вероятностей в матрице. В процессе генерации заметок мы хотим изменить матрицу. Используя прослушиватели событий, мы переключаем строки и столбцы исходной матрицы
genmatrix
. Проблема в том, что музыка генерируется до того, как мы получим возможность изменить принятые композиционные решения. Как мы проигрываем музыкальные ноты, как только сгенерированы массивы
notevec._data
Вероятно, это как-то связано с Tone.schedule. Пожалуйста, помогите!