summaryrefslogtreecommitdiff
path: root/client/lib/bandpass.js
blob: 3e1ed16872898bda81c5e5c9659b2576f29d7ba3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/**
 * 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,
};