const ui = document.getElementById("ui"); const bpm = document.getElementById("bpm"); bpm.addEventListener("change", (e) => { Tone.Transport.bpm.value = e.target.value; }); const newChannel = document.getElementById("new-channel"); const insert = document.getElementById("insert"); insert.addEventListener("click", (e) => { const newSequence = newChannel.querySelector("input[type=text]").value; if (newSequence) { createChannel(rebuildArray(newSequence)); newChannel.value = ""; } }); document.getElementById("start")?.addEventListener("click", async () => { await Tone.start(); console.log("Audio is ready"); Tone.Transport.bpm.value = bpm.value; newChannel.classList.remove("hidden"); createChannel(["C4", null, null, "F4", null, null, null]); createChannel([["C3", ["F3", "G3", "A#3"]], "C3", ["D#3", "D3"], "F3"]); createChannel(["C3", ["G3", ["F3", "A#3"]], "C3", ["D#3", "D3"], "F3"]); createChannel(["C3", "F3"]); }); let createSequence = function (sequence) { const synth = new Tone.Synth(); const seq = new Tone.Sequence((time, note) => { synth.triggerAttackRelease(note, 0.1, time); }, sequence).start(0); Tone.Transport.start(); return synth; }; let createChannel = function (sequence) { const channel = new Tone.Channel().toDestination(); const synth = new Tone.Synth(); let seq = new Tone.Sequence((time, note) => { synth.triggerAttackRelease(note, 0.1, time); }, sequence).start(0); Tone.Transport.start(); synth.connect(channel); let container = document.createElement("div"); container.classList.add("channel"); let control = document.createElement("input"); control.setAttribute("type", "range"); control.value = 0; control.setAttribute("min", -48); control.setAttribute("max", 6); control.addEventListener("change", (e) => { channel.volume.value = e.target.value; }); let notation = document.createElement("input"); notation.value = simplifyArray(JSON.stringify(sequence)); notation.classList.add("notation"); notation.addEventListener("change", (e) => { try { let newSeq = rebuildArray(e.target.value); seq.dispose(); seq = new Tone.Sequence((time, note) => { synth.triggerAttackRelease(note, 0.1, time); }, newSeq).start(0); } catch (e) { console.warn(e); } }); container.appendChild(notation); container.appendChild(control); ui.prepend(container); }; function simplifyArray(literal) { // Sorry for this return literal.replaceAll('"', "").replaceAll("'", "").replaceAll(",", ", "); } function rebuildArray(literal) { // And also for this let rebuild = literal .replaceAll(/\s+/gi, "") .replaceAll("[", '["') .replaceAll(",", '","') .replaceAll("]", '"]') .replaceAll('"[', "[") .replaceAll(']"', "]"); let array = JSON.parse(rebuild); try { getAllIndexes(array, "null").forEach((index) => (array[index] = null)); } catch (e) { console.log(e); } return array; } function getAllIndexes(arr, val) { var indexes = [], i; for (i = 0; i < arr.length; i++) if (arr[i] === val) indexes.push(i); return indexes; }