summaryrefslogtreecommitdiff
path: root/client/lib
diff options
context:
space:
mode:
authorjulian laplace <julescarbon@gmail.com>2025-07-14 16:58:49 +0200
committerjulian laplace <julescarbon@gmail.com>2025-07-14 16:58:49 +0200
commit6e53264b8fc0ed94282bcce022f07c551e925547 (patch)
tree32694b45fbe228d5f905615755a56ceb24f87a84 /client/lib
parentedaae6d07fa1abb1e3a9ae8e113bddd663c89c5b (diff)
pitched noise mode
Diffstat (limited to 'client/lib')
-rw-r--r--client/lib/bandpass.js97
-rw-r--r--client/lib/kalimba.js2
-rw-r--r--client/lib/sine.js (renamed from client/lib/organ.js)31
3 files changed, 126 insertions, 4 deletions
diff --git a/client/lib/bandpass.js b/client/lib/bandpass.js
new file mode 100644
index 0000000..3e1ed16
--- /dev/null
+++ b/client/lib/bandpass.js
@@ -0,0 +1,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,
+};
diff --git a/client/lib/kalimba.js b/client/lib/kalimba.js
index 53fcb99..c3ee30f 100644
--- a/client/lib/kalimba.js
+++ b/client/lib/kalimba.js
@@ -33,7 +33,7 @@ function load({ output }) {
playbackRate: 1,
});
player.name = fn;
- const gain = new Tone.Gain(1.6);
+ const gain = new Tone.Gain(0.15);
player.connect(gain);
gain.connect(output);
sample.players.push(player);
diff --git a/client/lib/organ.js b/client/lib/sine.js
index e66f89d..b414b27 100644
--- a/client/lib/organ.js
+++ b/client/lib/sine.js
@@ -1,6 +1,6 @@
/**
* Sine wave organ
- * @module lib/organ.js;
+ * @module lib/sine.js;
*/
import Tone from "tone";
@@ -29,7 +29,9 @@ function play(interval) {
if (!osc.el) {
osc.interval = interval;
osc.el = new Tone.Oscillator(interval * root, "sine");
- osc.el.connect(output);
+ osc.gain = new Tone.Gain(0.025);
+ osc.el.connect(osc.gain);
+ osc.gain.connect(output);
}
osc.el.start();
osc.playing = true;
@@ -47,6 +49,15 @@ function pause(interval) {
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;
@@ -63,5 +74,19 @@ function stop() {
}
oscillators = {};
}
+function getPlaying() {
+ return Object.values(oscillators)
+ .filter((osc) => osc.playing)
+ .map((osc) => osc.interval);
+}
-export default { load, isPlaying, play, pause, stop, setRoot };
+export default {
+ load,
+ isPlaying,
+ getPlaying,
+ play,
+ pause,
+ toggle,
+ stop,
+ setRoot,
+};