/** * Bandpassed noise organ * @module lib/bandpass.js; */ import Tone from "tone"; import { roundInterval } from "./util"; let root = 440; let oscillators = {}; let output; let lastPlayed; let noise; 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; } if (!noise) { noise = new Tone.Noise().start(); } const rounded = roundInterval(interval); const osc = (oscillators[rounded] = oscillators[rounded] || {}); if (!osc.el) { osc.interval = interval; osc.el = new Tone.Filter(interval * root, "bandpass"); osc.el.Q.value = 100; } noise.connect(osc.el); osc.el.connect(output); osc.playing = true; lastPlayed = osc; return osc; } function pause(interval) { const rounded = roundInterval(interval); if (!oscillators[rounded]) return; const osc = (oscillators[rounded] = oscillators[rounded] || {}); osc.el.disconnect(output); noise.disconnect(osc.el); 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)) { if (!osc.playing) { continue; } osc.el.disconnect(output); noise.disconnect(osc.el); 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, };