/** * Sine wave organ * @module lib/sine.js; */ import Tone from "tone"; import { roundInterval } from "./util"; let root = 440; let oscillators = {}; let output; let lastPlayed; function load(out) { output = out; } function isPlaying(interval) { const rounded = roundInterval(interval); const osc = oscillators[rounded]; return osc && osc.playing; } function play(interval) { if (!output) { return; } const rounded = roundInterval(interval); const osc = (oscillators[rounded] = oscillators[rounded] || {}); if (!osc.el) { osc.interval = interval; osc.el = new Tone.Oscillator(interval * root, "sine"); osc.gain = new Tone.Gain(0.025); osc.el.connect(osc.gain); osc.gain.connect(output); } osc.el.start(); osc.playing = true; lastPlayed = osc; return osc; } function pause(interval) { const rounded = roundInterval(interval); if (!oscillators[rounded]) return; const osc = (oscillators[rounded] = oscillators[rounded] || {}); if (osc.el) { osc.el.stop(); } osc.playing = false; return osc; } function toggle(interval) { const rounded = roundInterval(interval); const osc = (oscillators[rounded] = oscillators[rounded] || {}); if (osc && osc.playing) { pause(interval); } else { play(interval); } } function setRoot(newRoot) { root = newRoot; for (const osc of Object.values(oscillators)) { osc.el.frequency.value = osc.interval * newRoot; } } function stop() { for (const osc of Object.values(oscillators)) { osc.el.stop(); osc.el.disconnect(); osc.playing = false; delete osc.el; } oscillators = {}; } function getPlaying() { return Object.values(oscillators) .filter((osc) => osc.playing) .map((osc) => osc.interval); } export default { load, isPlaying, getPlaying, play, pause, toggle, stop, setRoot, };