summaryrefslogtreecommitdiff
path: root/client/lib/sampler.js
diff options
context:
space:
mode:
authorjulian laplace <julescarbon@gmail.com>2025-07-05 17:06:59 +0200
committerjulian laplace <julescarbon@gmail.com>2025-07-05 17:06:59 +0200
commit200c1a4f0ebd3188faebaea8e7278fc5105227cf (patch)
tree12f61dcd756ba57e0f718b87e4eb0e9c30d90f4d /client/lib/sampler.js
parentd82f99fd89e23fdb62598b616e39537360a10f74 (diff)
laod sample
Diffstat (limited to 'client/lib/sampler.js')
-rw-r--r--client/lib/sampler.js112
1 files changed, 112 insertions, 0 deletions
diff --git a/client/lib/sampler.js b/client/lib/sampler.js
new file mode 100644
index 0000000..08f253d
--- /dev/null
+++ b/client/lib/sampler.js
@@ -0,0 +1,112 @@
+/**
+ * Sampler
+ * @module lib/sampler.js;
+ */
+
+import Tone from "tone";
+
+let output;
+let ready;
+let current = "";
+let samples = {};
+
+const player_count = 12;
+
+export function load(out, readyCallback) {
+ output = out;
+ ready = readyCallback;
+ document.body.addEventListener("dragover", dragOver);
+ document.body.addEventListener("drop", drop);
+}
+
+/**
+ * Drag and drop
+ */
+export function dragOver(event) {
+ event.preventDefault();
+}
+export function drop(event) {
+ event.preventDefault();
+ const files = event.dataTransfer.items
+ ? [...event.dataTransfer.items]
+ .filter((item) => item.kind === "file")
+ .map((item) => item.getAsFile())
+ : [...event.dataTransfer.files];
+
+ const file = files[0];
+ const reader = new FileReader();
+
+ reader.addEventListener(
+ "load",
+ () => loadSampleFromFile(file, reader.result),
+ false,
+ );
+
+ if (file) {
+ reader.readAsDataURL(file);
+ }
+}
+
+export function loadSampleFromFile(file, url) {
+ const { name } = file;
+ current = name;
+
+ const sample = (samples[name] = samples[name] || {});
+ sample.root = 440;
+ sample.players = [];
+ sample.index = -1;
+ for (let i = 0; i < player_count; i++) {
+ let player = new Tone.Player({
+ url,
+ retrigger: true,
+ playbackRate: 1,
+ });
+ player.name = name;
+ player.connect(output);
+ sample.players.push(player);
+ }
+ console.log("+ Sampler:", name, `(${sample.players.length} voices)`);
+ ready();
+}
+
+/**
+ * Player
+ */
+let last = 440;
+
+function play(freq) {
+ last = freq;
+ const sample = samples[current];
+ sample.index = (sample.index + 1) % sample.players.length;
+ const player = sample.players[sample.index];
+ player.playbackRate = freq / sample.root;
+ player.start();
+}
+
+function pause() {
+ // no-op
+}
+
+export default { load, play, pause };
+
+// for help tuning
+function keydown(e) {
+ // console.log(e.keyCode)
+ if (e.metaKey && last && current) {
+ const sample = samples[current];
+ const step = e.shiftKey ? (e.ctrlKey ? 0.1 : 1) : 10;
+ switch (e.keyCode) {
+ case 38: // up
+ e.preventDefault();
+ sample.root -= step;
+ play(last);
+ break;
+ case 40: // down
+ e.preventDefault();
+ sample.root += step;
+ play(last);
+ break;
+ }
+ }
+}
+window.addEventListener("keydown", keydown, true);