@jadujoel/web-audio-clip-node 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/audio/ClipNode.js +312 -0
  2. package/dist/audio/processor-code.js +2 -0
  3. package/dist/audio/processor-kernel.js +861 -0
  4. package/dist/audio/processor.js +80 -0
  5. package/dist/audio/types.js +9 -0
  6. package/dist/audio/utils.js +128 -0
  7. package/dist/audio/version.d.ts +1 -0
  8. package/dist/audio/version.js +2 -0
  9. package/dist/audio/workletUrl.js +17 -0
  10. package/dist/components/AudioControl.js +99 -0
  11. package/dist/components/ContextMenu.js +73 -0
  12. package/dist/components/ControlSection.js +74 -0
  13. package/dist/components/DetuneControl.js +44 -0
  14. package/dist/components/DisplayPanel.js +6 -0
  15. package/dist/components/FilterControl.js +48 -0
  16. package/dist/components/GainControl.js +44 -0
  17. package/dist/components/PanControl.js +50 -0
  18. package/dist/components/PlaybackRateControl.js +44 -0
  19. package/dist/components/PlayheadSlider.js +20 -0
  20. package/dist/components/SnappableSlider.js +174 -0
  21. package/dist/components/TransportButtons.js +9 -0
  22. package/dist/controls/controlDefs.js +211 -0
  23. package/dist/controls/formatValueText.js +80 -0
  24. package/dist/controls/linkedControlPairs.js +51 -0
  25. package/dist/data/cache.js +17 -0
  26. package/dist/data/fileStore.js +39 -0
  27. package/dist/hooks/useClipNode.js +338 -0
  28. package/dist/lib-react.js +17 -19
  29. package/dist/lib.js +16 -44
  30. package/dist/store/clipStore.js +71 -0
  31. package/examples/README.md +10 -0
  32. package/examples/cdn-vanilla/README.md +13 -0
  33. package/examples/cdn-vanilla/index.html +61 -0
  34. package/examples/esm-bundler/README.md +8 -0
  35. package/examples/esm-bundler/index.html +12 -0
  36. package/examples/esm-bundler/package.json +15 -0
  37. package/examples/esm-bundler/src/main.ts +43 -0
  38. package/examples/react/README.md +10 -0
  39. package/examples/react/index.html +12 -0
  40. package/examples/react/package.json +21 -0
  41. package/examples/react/src/App.tsx +20 -0
  42. package/examples/react/src/main.tsx +9 -0
  43. package/examples/react/vite.config.ts +6 -0
  44. package/examples/self-hosted/README.md +11 -0
  45. package/examples/self-hosted/index.html +12 -0
  46. package/examples/self-hosted/package.json +16 -0
  47. package/examples/self-hosted/public/.gitkeep +1 -0
  48. package/examples/self-hosted/src/main.ts +46 -0
  49. package/package.json +3 -2
  50. package/dist/lib-react.js.map +0 -9
  51. package/dist/lib.js.map +0 -9
@@ -0,0 +1,43 @@
1
+ import { ClipNode, getProcessorBlobUrl } from "@jadujoel/web-audio-clip-node";
2
+
3
+ const app = document.getElementById("app")!;
4
+ app.innerHTML = `
5
+ <h1>ClipNode – Vite + TypeScript</h1>
6
+ <button id="play">▶ Play</button>
7
+ <button id="stop">■ Stop</button>
8
+ <p id="status">Click Play to start.</p>
9
+ `;
10
+
11
+ function createToneBuffer(ctx: AudioContext, freq = 440, duration = 2) {
12
+ const length = ctx.sampleRate * duration;
13
+ const buf = ctx.createBuffer(1, length, ctx.sampleRate);
14
+ const data = buf.getChannelData(0);
15
+ for (let i = 0; i < length; i++) {
16
+ data[i] = Math.sin((2 * Math.PI * freq * i) / ctx.sampleRate);
17
+ }
18
+ return buf;
19
+ }
20
+
21
+ let ctx: AudioContext;
22
+ let clip: ClipNode;
23
+
24
+ document.getElementById("play")!.addEventListener("click", async () => {
25
+ if (!ctx) {
26
+ ctx = new AudioContext();
27
+ await ctx.audioWorklet.addModule(getProcessorBlobUrl());
28
+ clip = new ClipNode(ctx, {
29
+ processorOptions: { sampleRate: ctx.sampleRate },
30
+ });
31
+ clip.connect(ctx.destination);
32
+ clip.buffer = createToneBuffer(ctx);
33
+ }
34
+ clip.start();
35
+ document.getElementById("status")!.textContent = "Playing…";
36
+ });
37
+
38
+ document.getElementById("stop")!.addEventListener("click", () => {
39
+ if (clip) {
40
+ clip.stop();
41
+ document.getElementById("status")!.textContent = "Stopped.";
42
+ }
43
+ });
@@ -0,0 +1,10 @@
1
+ # React Example
2
+
3
+ Minimal React app using the built-in hooks and UI components.
4
+
5
+ ```sh
6
+ npm install
7
+ npm run dev
8
+ ```
9
+
10
+ Uses `useClipNode` + `useClipControls` to wire everything up, and renders `<TransportButtons />` and `<AudioControl />` out of the box.
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>ClipNode – React Example</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="./src/main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "react-example",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "vite",
7
+ "build": "vite build"
8
+ },
9
+ "dependencies": {
10
+ "@jadujoel/web-audio-clip-node": "^0.1.1",
11
+ "react": "^19",
12
+ "react-dom": "^19",
13
+ "zustand": "^5"
14
+ },
15
+ "devDependencies": {
16
+ "@types/react": "^19",
17
+ "@types/react-dom": "^19",
18
+ "@vitejs/plugin-react": "^4",
19
+ "vite": "^6"
20
+ }
21
+ }
@@ -0,0 +1,20 @@
1
+ import {
2
+ AudioControl,
3
+ TransportButtons,
4
+ useClipControls,
5
+ useClipNode,
6
+ } from "@jadujoel/web-audio-clip-node/react";
7
+ import "@jadujoel/web-audio-clip-node/styles.css";
8
+
9
+ export function App() {
10
+ const controls = useClipControls();
11
+ useClipNode({ ...controls });
12
+
13
+ return (
14
+ <div style={{ maxWidth: 480, margin: "2rem auto", fontFamily: "system-ui, sans-serif" }}>
15
+ <h1>ClipNode – React</h1>
16
+ <TransportButtons />
17
+ <AudioControl />
18
+ </div>
19
+ );
20
+ }
@@ -0,0 +1,9 @@
1
+ import { StrictMode } from "react";
2
+ import { createRoot } from "react-dom/client";
3
+ import { App } from "./App";
4
+
5
+ createRoot(document.getElementById("root")!).render(
6
+ <StrictMode>
7
+ <App />
8
+ </StrictMode>,
9
+ );
@@ -0,0 +1,6 @@
1
+ import react from "@vitejs/plugin-react";
2
+ import { defineConfig } from "vite";
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ });
@@ -0,0 +1,11 @@
1
+ # Self-Hosted Processor Example
2
+
3
+ Demonstrates serving `processor.js` from your own origin instead of using the embedded blob URL or CDN.
4
+
5
+ ```sh
6
+ npm install
7
+ npm run setup # copies processor.js into public/
8
+ npm run dev
9
+ ```
10
+
11
+ The `setup` script copies the worklet file from the installed package into `public/`, where Vite serves it as a static asset. `getProcessorModuleUrl()` resolves it relative to the page URL.
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>ClipNode – Self-Hosted Processor</title>
7
+ </head>
8
+ <body>
9
+ <div id="app"></div>
10
+ <script type="module" src="./src/main.ts"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "self-hosted-example",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "setup": "cp node_modules/@jadujoel/web-audio-clip-node/dist/processor.js public/processor.js",
7
+ "dev": "vite",
8
+ "build": "vite build"
9
+ },
10
+ "dependencies": {
11
+ "@jadujoel/web-audio-clip-node": "^0.1.1"
12
+ },
13
+ "devDependencies": {
14
+ "vite": "^6"
15
+ }
16
+ }
@@ -0,0 +1 @@
1
+ .gitkeep
@@ -0,0 +1,46 @@
1
+ import { ClipNode, getProcessorModuleUrl } from "@jadujoel/web-audio-clip-node";
2
+
3
+ const app = document.getElementById("app")!;
4
+ app.innerHTML = `
5
+ <h1>ClipNode – Self-Hosted Processor</h1>
6
+ <p>The <code>processor.js</code> file is served from <code>/processor.js</code> on your own server.</p>
7
+ <button id="play">▶ Play</button>
8
+ <button id="stop">■ Stop</button>
9
+ <p id="status">Click Play to start.</p>
10
+ `;
11
+
12
+ function createToneBuffer(ctx: AudioContext, freq = 440, duration = 2) {
13
+ const length = ctx.sampleRate * duration;
14
+ const buf = ctx.createBuffer(1, length, ctx.sampleRate);
15
+ const data = buf.getChannelData(0);
16
+ for (let i = 0; i < length; i++) {
17
+ data[i] = Math.sin((2 * Math.PI * freq * i) / ctx.sampleRate);
18
+ }
19
+ return buf;
20
+ }
21
+
22
+ let ctx: AudioContext;
23
+ let clip: ClipNode;
24
+
25
+ document.getElementById("play")!.addEventListener("click", async () => {
26
+ if (!ctx) {
27
+ ctx = new AudioContext();
28
+ // Load the processor from your own server (public/processor.js)
29
+ const processorUrl = getProcessorModuleUrl(window.location.href);
30
+ await ctx.audioWorklet.addModule(processorUrl);
31
+ clip = new ClipNode(ctx, {
32
+ processorOptions: { sampleRate: ctx.sampleRate },
33
+ });
34
+ clip.connect(ctx.destination);
35
+ clip.buffer = createToneBuffer(ctx);
36
+ }
37
+ clip.start();
38
+ document.getElementById("status")!.textContent = "Playing…";
39
+ });
40
+
41
+ document.getElementById("stop")!.addEventListener("click", () => {
42
+ if (clip) {
43
+ clip.stop();
44
+ document.getElementById("status")!.textContent = "Stopped.";
45
+ }
46
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jadujoel/web-audio-clip-node",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "description": "Full-featured AudioWorklet clip player with playback rate, detune, gain, pan, filters, looping, fades, crossfade, and streaming buffer support. React components included.",
6
6
  "keywords": [
@@ -36,7 +36,8 @@
36
36
  "files": [
37
37
  "dist",
38
38
  "README.md",
39
- "LICENSE"
39
+ "LICENSE",
40
+ "examples"
40
41
  ],
41
42
  "sideEffects": false,
42
43
  "scripts": {
@@ -1,9 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "sourcesContent": [
5
- ],
6
- "mappings": "",
7
- "debugId": "030B87E04A0B95F064756E2164756E21",
8
- "names": []
9
- }
package/dist/lib.js.map DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "sourcesContent": [
5
- ],
6
- "mappings": "",
7
- "debugId": "9B64F311A83C9C3D64756E2164756E21",
8
- "names": []
9
- }