@jadujoel/web-audio-clip-node 0.1.0

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 (38) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +91 -0
  3. package/dist/audio/ClipNode.d.ts +86 -0
  4. package/dist/audio/processor-code.d.ts +1 -0
  5. package/dist/audio/processor-kernel.d.ts +43 -0
  6. package/dist/audio/processor.d.ts +1 -0
  7. package/dist/audio/types.d.ts +192 -0
  8. package/dist/audio/utils.d.ts +22 -0
  9. package/dist/audio/workletUrl.d.ts +6 -0
  10. package/dist/components/AudioControl.d.ts +28 -0
  11. package/dist/components/ContextMenu.d.ts +17 -0
  12. package/dist/components/ControlSection.d.ts +26 -0
  13. package/dist/components/DetuneControl.d.ts +10 -0
  14. package/dist/components/DisplayPanel.d.ts +14 -0
  15. package/dist/components/FilterControl.d.ts +12 -0
  16. package/dist/components/GainControl.d.ts +10 -0
  17. package/dist/components/PanControl.d.ts +10 -0
  18. package/dist/components/PlaybackRateControl.d.ts +10 -0
  19. package/dist/components/PlayheadSlider.d.ts +13 -0
  20. package/dist/components/SnappableSlider.d.ts +18 -0
  21. package/dist/components/TransportButtons.d.ts +14 -0
  22. package/dist/controls/controlDefs.d.ts +31 -0
  23. package/dist/controls/formatValueText.d.ts +2 -0
  24. package/dist/controls/linkedControlPairs.d.ts +20 -0
  25. package/dist/data/cache.d.ts +1 -0
  26. package/dist/data/fileStore.d.ts +6 -0
  27. package/dist/hooks/useClipNode.d.ts +31 -0
  28. package/dist/lib-react.d.ts +15 -0
  29. package/dist/lib-react.js +19 -0
  30. package/dist/lib-react.js.map +9 -0
  31. package/dist/lib.d.ts +16 -0
  32. package/dist/lib.js +44 -0
  33. package/dist/lib.js.map +9 -0
  34. package/dist/processor.js +4 -0
  35. package/dist/processor.js.map +12 -0
  36. package/dist/store/clipStore.d.ts +63 -0
  37. package/dist/styles.css +739 -0
  38. package/package.json +87 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Joel Löf
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # @jadujoel/web-audio-clip-node
2
+
3
+ Full-featured AudioWorklet-based audio clip player for the Web Audio API.
4
+
5
+ ## Features
6
+
7
+ - Playback rate control (-2x to 2x, including reverse)
8
+ - Detune (-2400 to +2400 cents)
9
+ - Gain (dB scale with equal-power curves)
10
+ - Stereo pan
11
+ - Highpass / lowpass filters
12
+ - Loop with crossfade
13
+ - Fade in / fade out
14
+ - Streaming buffer support
15
+ - Offset & duration control
16
+ - React components & hooks (optional)
17
+
18
+ ## Install
19
+
20
+ ```sh
21
+ npm install @jadujoel/web-audio-clip-node
22
+ ```
23
+
24
+ ## Quick Start (Core API)
25
+
26
+ ```ts
27
+ import { ClipNode, getProcessorBlobUrl } from "@jadujoel/web-audio-clip-node";
28
+
29
+ const ctx = new AudioContext();
30
+ await ctx.audioWorklet.addModule(getProcessorBlobUrl());
31
+
32
+ const clip = new ClipNode(ctx, {
33
+ processorOptions: { sampleRate: ctx.sampleRate },
34
+ });
35
+ clip.connect(ctx.destination);
36
+
37
+ const response = await fetch("audio.mp3");
38
+ const buffer = await ctx.decodeAudioData(await response.arrayBuffer());
39
+ clip.buffer = buffer;
40
+ clip.start();
41
+ ```
42
+
43
+ ## Quick Start (React)
44
+
45
+ ```tsx
46
+ import { useClipNode, useClipControls, TransportButtons, AudioControl } from "@jadujoel/web-audio-clip-node/react";
47
+ import "@jadujoel/web-audio-clip-node/styles.css";
48
+
49
+ function Player() {
50
+ const controls = useClipControls();
51
+ const clip = useClipNode({ ...controls });
52
+ return (
53
+ <>
54
+ <TransportButtons />
55
+ <AudioControl />
56
+ </>
57
+ );
58
+ }
59
+ ```
60
+
61
+ ## CDN Usage (No Bundler)
62
+
63
+ ```html
64
+ <script type="module">
65
+ const ctx = new AudioContext();
66
+ await ctx.audioWorklet.addModule(
67
+ "https://cdn.jsdelivr.net/npm/@jadujoel/web-audio-clip-node@0.1.0/dist/processor.js"
68
+ );
69
+ </script>
70
+ ```
71
+
72
+ ## Processor Loading Options
73
+
74
+ | Method | Function | Use case |
75
+ |--------|----------|----------|
76
+ | Blob URL (default) | `getProcessorBlobUrl()` | Zero-config, works everywhere |
77
+ | CDN | `getProcessorCdnUrl("0.1.0")` | No bundler / script-tag usage |
78
+ | Self-hosted | `getProcessorModuleUrl(baseUrl)` | You serve `processor.js` yourself |
79
+
80
+ ## Exports
81
+
82
+ | Entry point | Import path | Contents |
83
+ |-------------|-------------|----------|
84
+ | Core | `@jadujoel/web-audio-clip-node` | `ClipNode`, types, utils, controls, processor kernel |
85
+ | React | `@jadujoel/web-audio-clip-node/react` | Store, hooks, UI components |
86
+ | Processor | `@jadujoel/web-audio-clip-node/processor` | Standalone worklet script |
87
+ | Styles | `@jadujoel/web-audio-clip-node/styles.css` | CSS for React components |
88
+
89
+ ## License
90
+
91
+ MIT
@@ -0,0 +1,86 @@
1
+ import type { ClipNodeState, ClipWorkletOptions, FrameData } from "./types";
2
+ export declare class ClipNode extends AudioWorkletNode {
3
+ onscheduled?: () => void;
4
+ onstarted?: () => void;
5
+ onpaused?: () => void;
6
+ onresumed?: () => void;
7
+ onended?: () => void;
8
+ onlooped?: () => void;
9
+ onstopped?: () => void;
10
+ onframe?: (data: FrameData) => void;
11
+ ondisposed?: () => void;
12
+ onstatechange?: (state: ClipNodeState) => void;
13
+ private _buffer?;
14
+ private _loopStart;
15
+ private _loopEnd;
16
+ private _loop;
17
+ private _offset;
18
+ private _playhead;
19
+ private _fadeIn;
20
+ private _fadeOut;
21
+ private _loopCrossfade;
22
+ private _duration;
23
+ private _previousState;
24
+ private _bufferWriteCursor;
25
+ timesLooped: number;
26
+ state: ClipNodeState;
27
+ cpu: number;
28
+ constructor(context: BaseAudioContext, options?: ClipWorkletOptions);
29
+ private handleMessage;
30
+ private setState;
31
+ toggleGain(value?: boolean): void;
32
+ togglePlaybackRate(value?: boolean): void;
33
+ toggleDetune(value?: boolean): void;
34
+ togglePan(value?: boolean): void;
35
+ toggleHighpass(value?: boolean): void;
36
+ toggleLowpass(value?: boolean): void;
37
+ toggleFadeIn(value?: boolean): void;
38
+ toggleFadeOut(value?: boolean): void;
39
+ toggleLoopCrossfade(value?: boolean): void;
40
+ toggleLoopStart(value?: boolean): void;
41
+ toggleLoopEnd(value?: boolean): void;
42
+ logState(): void;
43
+ get buffer(): AudioBuffer | undefined;
44
+ set buffer(ab: AudioBuffer);
45
+ initializeBuffer(totalLength: number, channels: number, options?: {
46
+ streaming?: boolean;
47
+ }): void;
48
+ replaceBufferRange(startSample: number, channelData: Float32Array[], options?: {
49
+ totalLength?: number | null;
50
+ streamEnded?: boolean;
51
+ }): void;
52
+ appendBufferRange(channelData: Float32Array[], options?: {
53
+ totalLength?: number | null;
54
+ streamEnded?: boolean;
55
+ }): void;
56
+ finalizeBuffer(totalLength?: number): void;
57
+ start(when?: number, offset?: number, duration?: number): void;
58
+ stop(when?: number, initialDelay?: number): void;
59
+ pause(when?: number): void;
60
+ resume(when?: number): void;
61
+ get loop(): boolean;
62
+ set loop(value: boolean);
63
+ get loopStart(): number;
64
+ set loopStart(value: number);
65
+ get loopEnd(): number;
66
+ set loopEnd(value: number);
67
+ get duration(): number;
68
+ set duration(value: number);
69
+ get offset(): number;
70
+ set offset(value: number);
71
+ get playhead(): number;
72
+ set playhead(value: number);
73
+ get playbackRate(): AudioParam;
74
+ get detune(): AudioParam;
75
+ get highpass(): AudioParam;
76
+ get lowpass(): AudioParam;
77
+ get gain(): AudioParam;
78
+ get pan(): AudioParam;
79
+ get fadeIn(): number;
80
+ set fadeIn(value: number);
81
+ get fadeOut(): number;
82
+ set fadeOut(value: number);
83
+ get loopCrossfade(): number;
84
+ set loopCrossfade(value: number);
85
+ dispose(): void;
86
+ }
@@ -0,0 +1 @@
1
+ export declare const processorCode = "var z={Initial:0,Started:1,Stopped:2,Paused:3,Scheduled:4,Ended:5,Disposed:6};var y=128;function i(V=[]){let A=V[0]?.length??0,F=A>0;return{totalLength:F?A:null,committedLength:F?A:0,streamEnded:F,streaming:!1,writtenSpans:F?[{startSample:0,endSample:A}]:[],pendingWrites:[],lowWaterThreshold:y*4,lowWaterNotified:!1,lastUnderrunSample:null}}function M0(V){return V[0]?.length??0}function o(V){return V.streamBuffer.totalLength??M0(V.buffer)}function G0(V,A){return Array.from({length:V},()=>new Float32Array(A))}function E0(V,A){let F=[...V,A].sort((Q,J)=>Q.startSample-J.startSample),T=[];for(let Q of F){let J=T[T.length-1];if(!J||Q.startSample>J.endSample){T.push({...Q});continue}J.endSample=Math.max(J.endSample,Q.endSample)}return T}function I0(V){let A=0;for(let F of V){if(F.startSample>A)break;A=Math.max(A,F.endSample)}return A}function w0(V,A){if(V.committedLength-Math.floor(A)>=V.lowWaterThreshold)V.lowWaterNotified=!1}function R0(V,A,F){let T=M0(V.buffer),Q=V.buffer.length;if(T>=F&&Q>=A)return;let J=Math.max(T,F),U=Math.max(Q,A),Y=G0(U,J);for(let X=0;X<Q;X++)Y[X].set(V.buffer[X].subarray(0,T));if(V.buffer=Y,V.streamBuffer.totalLength==null||V.streamBuffer.totalLength<J)V.streamBuffer.totalLength=J}function B0(V,A){let F=Math.max(Math.floor(A.startSample),0),T=A.channelData[0]?.length??0,Q=A.totalLength??null,J=Math.max(F+T,Q??0);R0(V,Math.max(A.channelData.length,V.buffer.length,1),J);for(let U=0;U<A.channelData.length;U++)V.buffer[U].set(A.channelData[U],F);if(Q!=null)V.streamBuffer.totalLength=Q;if(T>0)V.streamBuffer.writtenSpans=E0(V.streamBuffer.writtenSpans,{startSample:F,endSample:F+T}),V.streamBuffer.committedLength=I0(V.streamBuffer.writtenSpans);if(A.streamEnded===!0)V.streamBuffer.streamEnded=!0;w0(V.streamBuffer,V.playhead)}function _0(V){if(V.streamBuffer.pendingWrites.length===0)return;for(let A of V.streamBuffer.pendingWrites)B0(V,A);V.streamBuffer.pendingWrites=[]}function y0(V,A){V.buffer=A,V.streamBuffer=i(A)}function v0(V={},A){let{buffer:F=[],streamBuffer:T=i(F),duration:Q=-1,loop:J=!1,loopStart:U=0,loopEnd:Y=(F[0]?.length??0)/A,loopCrossfade:X=0,playhead:k=0,offset:H=0,startWhen:$=0,stopWhen:j=0,pauseWhen:P=0,resumeWhen:C=0,playedSamples:N=0,state:K=z.Initial,timesLooped:w=0,fadeInDuration:v=0,fadeOutDuration:Z=0,enableFadeIn:E=v>0,enableFadeOut:O=Z>0,enableLoopStart:R=!0,enableLoopEnd:h=!0,enableLoopCrossfade:b=X>0,enableHighpass:c=!0,enableLowpass:g=!0,enableGain:s=!0,enablePan:r=!0,enableDetune:t=!0,enablePlaybackRate:p=!0}=V;return{buffer:F,streamBuffer:T,loop:J,loopStart:U,loopEnd:Y,loopCrossfade:X,duration:Q,playhead:k,offset:H,startWhen:$,stopWhen:j,pauseWhen:P,resumeWhen:C,playedSamples:N,state:K,timesLooped:w,fadeInDuration:v,fadeOutDuration:Z,enableFadeIn:E,enableFadeOut:O,enableLoopStart:R,enableLoopEnd:h,enableHighpass:c,enableLowpass:g,enableGain:s,enablePan:r,enableDetune:t,enablePlaybackRate:p,enableLoopCrossfade:b}}function b0(V,A){return o(V)/A}function n(V,A){let F=b0(V,A);if(F<=0){V.loopStart=0,V.loopEnd=0;return}if(!Number.isFinite(V.loopStart)||V.loopStart<0)V.loopStart=0;if(V.loopStart>=F)V.loopStart=0;if(!Number.isFinite(V.loopEnd)||V.loopEnd<=V.loopStart||V.loopEnd>F)V.loopEnd=F}function e(V,A,F){if(A===void 0)return V.offset=0,0;if(A<0)return e(V,o(V)+A,F);if(A>(o(V)||1)-1)return e(V,o(V)%A,F);let T=Math.floor(A*F);return V.offset=T,T}function L0(V){let{playhead:A,bufferLength:F,loop:T,loopStartSamples:Q,loopEndSamples:J}=V,U=128;if(!T&&A+128>F)U=Math.max(F-A,0);let Y=Array(U);if(!T){for(let $=0,j=A;$<U;$++,j++)Y[$]=j;let H=A+U;return{playhead:H,indexes:Y,looped:!1,ended:H>=F}}let X=A,k=!1;for(let H=0;H<U;H++,X++){if(X>=J)X=Q+(X-J),k=!0;Y[H]=X}return{indexes:Y,looped:k,ended:!1,playhead:X}}function x0(V){let{playhead:A,bufferLength:F,loop:T,loopStartSamples:Q,loopEndSamples:J,playbackRates:U}=V,Y=128;if(!T&&A+128>F)Y=Math.max(F-A,0);let X=Array(Y),k=A,H=!1;if(T){for(let $=0;$<Y;$++){X[$]=Math.min(Math.max(Math.floor(k),0),F-1);let j=U[$]??U[0]??1;if(k+=j,j>=0&&(k>J||k>F))k=Q,H=!0;else if(j<0&&(k<Q||k<0))k=J,H=!0}return{playhead:k,indexes:X,looped:H,ended:!1}}for(let $=0;$<Y;$++)X[$]=Math.min(Math.max(Math.floor(k),0),F-1),k+=U[$]??U[0]??1;return{playhead:k,indexes:X,looped:!1,ended:k>=F||k<0}}function m0(V,A,F){for(let T=0;T<F.length;T++)for(let Q=0;Q<V.length;Q++)V[Q][T]=A[Q][F[T]];for(let T=F.length;T<V[0].length;T++)for(let Q=0;Q<V.length;Q++)V[Q][T]=0}function d(V){for(let A=0;A<V.length;A++)for(let F=0;F<V[A].length;F++)V[A][F]=0}function S0(V){let A=new Float32Array(V[0].length);for(let F=0;F<V[0].length;F++)A[F]=V[0][F];V.push(A)}function H0(V,A){for(let F=A.length;F<V.length;F++)A[F]=new Float32Array(V[F].length);for(let F=0;F<V.length;F++)for(let T=0;T<V[F].length;T++)A[F][T]=V[F][T]}function c0(V){let A=0;for(let F=0;F<V.length;F++)for(let T=0;T<V[F].length;T++)if(Number.isNaN(V[F][T]))A++,V[F][T]=0;return A}function V0(){return[{x_1:0,x_2:0,y_1:0,y_2:0},{x_1:0,x_2:0,y_1:0,y_2:0}]}function g0(V,A){if(A.length===1){let T=A[0];if(T===1)return;for(let Q of V)for(let J=0;J<Q.length;J++)Q[J]*=T;return}let F=A[0];for(let T of V)for(let Q=0;Q<T.length;Q++)F=A[Q]??F,T[Q]*=F}function d0(V,A){let F=A[0];for(let T=0;T<V[0].length;T++){F=A[T]??F;let Q=F<=0?1:1-F,J=F>=0?1:1+F;V[0][T]*=Q,V[1][T]*=J}}function h0(V,A,F,T){for(let Q=0;Q<V.length;Q++){let J=V[Q],{x_1:U,x_2:Y,y_1:X,y_2:k}=T[Q]??{x_1:0,x_2:0,y_1:0,y_2:0};if(A.length===1){let H=A[0];if(H>=20000)return;let $=2*Math.PI*H/F,j=Math.sin($)/2,P=(1-Math.cos($))/2,C=1-Math.cos($),N=(1-Math.cos($))/2,K=1+j,w=-2*Math.cos($),v=1-j,Z=P/K,E=C/K,O=N/K,R=w/K,h=v/K;for(let b=0;b<J.length;b++){let c=J[b],g=Z*c+E*U+O*Y-R*X-h*k;Y=U,U=c,k=X,X=g,J[b]=g}}else{let H=A[0];for(let $=0;$<J.length;$++){let j=A[$]??H,P=2*Math.PI*j/F,C=Math.sin(P)/2,N=(1-Math.cos(P))/2,K=1-Math.cos(P),w=(1-Math.cos(P))/2,v=1+C,Z=-2*Math.cos(P),E=1-C,O=J[$],R=N/v*O+K/v*U+w/v*Y-Z/v*X-E/v*k;Y=U,U=O,k=X,X=R,J[$]=R}}T[Q]={x_1:U,x_2:Y,y_1:X,y_2:k}}}function l0(V,A,F,T){for(let Q=0;Q<V.length;Q++){let J=V[Q],{x_1:U,x_2:Y,y_1:X,y_2:k}=T[Q]??{x_1:0,x_2:0,y_1:0,y_2:0};if(A.length===1){let H=A[0];if(H<=20)return;let $=2*Math.PI*H/F,j=Math.sin($)/2,P=(1+Math.cos($))/2,C=-(1+Math.cos($)),N=(1+Math.cos($))/2,K=1+j,w=-2*Math.cos($),v=1-j;for(let Z=0;Z<J.length;Z++){let E=J[Z],O=P/K*E+C/K*U+N/K*Y-w/K*X-v/K*k;Y=U,U=E,k=X,X=O,J[Z]=O}}else{let H=A[0];for(let $=0;$<J.length;$++){let j=A[$]??H,P=2*Math.PI*j/F,C=Math.sin(P)/2,N=(1+Math.cos(P))/2,K=-(1+Math.cos(P)),w=(1+Math.cos(P))/2,v=1+C,Z=-2*Math.cos(P),E=1-C,O=J[$],R=N/v*O+K/v*U+w/v*Y-Z/v*X-E/v*k;Y=U,U=O,k=X,X=R,J[$]=R}}T[Q]={x_1:U,x_2:Y,y_1:X,y_2:k}}}function z0(V,A,F,T){let{type:Q,data:J}=A;switch(Q){case\"buffer\":return y0(V,J),n(V,T),[];case\"bufferInit\":{let U=J;return V.buffer=G0(U.channels,U.totalLength),V.streamBuffer={...i(),totalLength:U.totalLength,streamEnded:!1,streaming:U.streaming??!0},n(V,T),[]}case\"bufferRange\":return V.streamBuffer.pendingWrites.push(J),[];case\"bufferEnd\":{let U=J;if(U?.totalLength!=null)V.streamBuffer.totalLength=U.totalLength;return V.streamBuffer.streamEnded=!0,[]}case\"bufferReset\":return V.buffer=[],V.streamBuffer=i(),n(V,T),[];case\"start\":V.timesLooped=0;{let U=J;if(V.duration=U?.duration??-1,V.duration===-1)V.duration=V.loop?Number.MAX_SAFE_INTEGER:(V.buffer[0]?.length??0)/T;e(V,U?.offset,T),n(V,T),V.playhead=V.offset,V.startWhen=U?.when??F,V.stopWhen=V.startWhen+V.duration,V.playedSamples=0,V.state=z.Scheduled}return[{type:\"scheduled\"}];case\"stop\":if(V.state===z.Ended||V.state===z.Initial)return[];return V.stopWhen=J??V.stopWhen,V.state=z.Stopped,[{type:\"stopped\"}];case\"pause\":return V.state=z.Paused,V.pauseWhen=J??F,[{type:\"paused\"}];case\"resume\":return V.state=z.Started,V.startWhen=J??F,[{type:\"resume\"}];case\"dispose\":return V.state=z.Disposed,V.buffer=[],V.streamBuffer=i(),[{type:\"disposed\"}];case\"loop\":{let U=J,Y=V.state;if(U&&(Y===z.Scheduled||Y===z.Started))V.stopWhen=Number.MAX_SAFE_INTEGER,V.duration=Number.MAX_SAFE_INTEGER;if(V.loop=U,U)n(V,T);return[]}case\"loopStart\":return V.loopStart=J,[];case\"loopEnd\":return V.loopEnd=J,[];case\"loopCrossfade\":return V.loopCrossfade=J,[];case\"playhead\":return V.playhead=Math.floor(J),[];case\"fadeIn\":return V.fadeInDuration=J,[];case\"fadeOut\":return V.fadeOutDuration=J,[];case\"toggleGain\":return V.enableGain=J??!V.enableGain,[];case\"togglePan\":return V.enablePan=J??!V.enablePan,[];case\"toggleLowpass\":return V.enableLowpass=J??!V.enableLowpass,[];case\"toggleHighpass\":return V.enableHighpass=J??!V.enableHighpass,[];case\"toggleDetune\":return V.enableDetune=J??!V.enableDetune,[];case\"togglePlaybackRate\":return V.enablePlaybackRate=J??!V.enablePlaybackRate,[];case\"toggleFadeIn\":return V.enableFadeIn=J??!V.enableFadeIn,[];case\"toggleFadeOut\":return V.enableFadeOut=J??!V.enableFadeOut,[];case\"toggleLoopStart\":return V.enableLoopStart=J??!V.enableLoopStart,[];case\"toggleLoopEnd\":return V.enableLoopEnd=J??!V.enableLoopEnd,[];case\"toggleLoopCrossfade\":return V.enableLoopCrossfade=J??!V.enableLoopCrossfade,[];case\"logState\":return[]}return[]}function j0(V,A,F,T,Q){let J=[],U=V.state;if(U===z.Disposed)return{keepAlive:!1,messages:J};if(_0(V),U===z.Initial)return{keepAlive:!0,messages:J};if(U===z.Ended)return d(A[0]),{keepAlive:!0,messages:J};if(U===z.Scheduled)if(T.currentTime>=V.startWhen)U=V.state=z.Started,J.push({type:\"started\"});else return d(A[0]),{keepAlive:!0,messages:J};else if(U===z.Paused){if(T.currentTime>V.pauseWhen)return d(A[0]),{keepAlive:!0,messages:J}}if(T.currentTime>V.stopWhen)return d(A[0]),V.state=z.Ended,J.push({type:\"ended\"}),V.playedSamples=0,{keepAlive:!0,messages:J};let Y=A[0],X=o(V);if(X===0)return d(Y),{keepAlive:!0,messages:J};let{playbackRate:k,detune:H,lowpass:$,highpass:j,gain:P,pan:C}=F,{buffer:N,loopStart:K,loopEnd:w,loopCrossfade:v,stopWhen:Z,playedSamples:E,enableLowpass:O,enableHighpass:R,enableGain:h,enablePan:b,enableDetune:c,enableFadeOut:g,enableFadeIn:s,enableLoopStart:r,enableLoopEnd:t,enableLoopCrossfade:p,playhead:D,fadeInDuration:A0,fadeOutDuration:F0}=V,K0=V.streamBuffer.streaming&&V.streamBuffer.committedLength<X,T0=V.loop&&!K0,l=Math.min(N.length,Y.length),W0=V.duration*T.sampleRate,Z0=Math.floor(T.sampleRate*v),q0=Math.max(X-y,0),L=r?Math.min(Math.floor(K*T.sampleRate),q0):0,x=t?Math.min(Math.floor(w*T.sampleRate),X):X,N0=x-L,J0=c&&H.length>0&&H[0]!==0,u=k;if(J0){let M=Math.max(k.length,H.length,y);u=new Float32Array(M);for(let W=0;W<M;W++){let I=k[W]??k[k.length-1],G=H[W]??H[H.length-1];u[W]=I*2**(G/1200)}}let Q0=V.enablePlaybackRate||J0,O0=Q0&&u.length>0&&u.every((M)=>M===0);if(V.streamBuffer.streaming&&!V.streamBuffer.streamEnded&&!V.streamBuffer.lowWaterNotified&&V.streamBuffer.committedLength-Math.floor(D)<V.streamBuffer.lowWaterThreshold)J.push({type:\"bufferLowWater\",data:{playhead:Math.floor(D),committedLength:V.streamBuffer.committedLength}}),V.streamBuffer.lowWaterNotified=!0;if(O0){d(Y);for(let M=1;M<A.length;M++)H0(Y,A[M]);return{keepAlive:!0,messages:J}}let U0={bufferLength:X,loop:T0,playhead:D,loopStartSamples:L,loopEndSamples:x,durationSamples:W0,playbackRates:u},{indexes:a,ended:X0,looped:Y0,playhead:$0}=Q0?x0(U0):L0(U0),f=a.find((M)=>M>=V.streamBuffer.committedLength&&M<X);if(f!==void 0&&!V.streamBuffer.streamEnded&&V.streamBuffer.lastUnderrunSample!==f)J.push({type:\"bufferUnderrun\",data:{playhead:Math.floor(D),committedLength:V.streamBuffer.committedLength,requestedSample:f}}),V.streamBuffer.lastUnderrunSample=f;else if(f===void 0)V.streamBuffer.lastUnderrunSample=null;m0(Y,N,a);let m=Math.min(Math.floor(v*T.sampleRate),N0),D0=T0&&D>L&&D<x,C0=p&&Z0>0&&X>y;if(D0&&C0){{let M=L+m;if(m>0&&D>L&&D<M){let W=D-L,I=Math.min(Math.floor(M-D),y);for(let G=0;G<I;G++){let B=(W+G)/m,S=Math.cos(Math.PI*B/2),q=Math.floor(x-m+W+G);if(q>=0&&q<X)for(let _=0;_<l;_++)Y[_][G]+=N[_][q]*S}}}{let M=x-m;if(m>0&&D>M&&D<x){let W=D-M,I=Math.min(Math.floor(x-D),y);for(let G=0;G<I;G++){let B=(W+G)/m,S=Math.sin(Math.PI*B/2),q=Math.floor(L+W+G);if(q>=0&&q<X)for(let _=0;_<l;_++)Y[_][G]+=N[_][q]*S}}}}if(s&&A0>0){let M=Math.floor(A0*T.sampleRate),W=M-E;if(W>0){let I=Math.min(W,y);for(let G=0;G<I;G++){let B=(E+G)/M,S=B*B*B;for(let q=0;q<l;q++)Y[q][G]*=S}}}if(g&&F0>0){let M=Math.floor(F0*T.sampleRate),W=Math.floor(T.sampleRate*(Z-T.currentTime));if(W<M+y)for(let I=0;I<y;I++){let G=W-I;if(G>=M)continue;let B=G<=0?0:G/M,S=B*B*B;for(let q=0;q<l;q++)Y[q][I]*=S}}if(O)h0(Y,$,T.sampleRate,Q.lowpass);if(R)l0(Y,j,T.sampleRate,Q.highpass);if(h)g0(Y,P);if(l===1)S0(Y);if(b)d0(Y,C);if(Y0)V.timesLooped++,J.push({type:\"looped\",data:V.timesLooped});if(X0)V.state=z.Ended,J.push({type:\"ended\"});V.playedSamples+=a.length,V.playhead=$0;let k0=c0(Y);if(k0>0)return console.log({numNans:k0,indexes:a,playhead:$0,ended:X0,looped:Y0,sourceLength:X}),{keepAlive:!0,messages:J};for(let M=1;M<A.length;M++)H0(Y,A[M]);return{keepAlive:!0,messages:J}}class P0 extends AudioWorkletProcessor{static get parameterDescriptors(){return[{name:\"playbackRate\",automationRate:\"a-rate\",defaultValue:1},{name:\"detune\",automationRate:\"a-rate\",defaultValue:0},{name:\"gain\",automationRate:\"a-rate\",defaultValue:1,minValue:0},{name:\"pan\",automationRate:\"a-rate\",defaultValue:0},{name:\"highpass\",automationRate:\"a-rate\",defaultValue:20,minValue:20,maxValue:20000},{name:\"lowpass\",automationRate:\"a-rate\",defaultValue:20000,minValue:20,maxValue:20000}]}properties;filterState={lowpass:V0(),highpass:V0()};lastFrameTime=0;constructor(V){super(V);this.properties=v0(V?.processorOptions,sampleRate),this.port.onmessage=(A)=>{let F=z0(this.properties,A.data,currentTime,sampleRate);for(let T of F)this.port.postMessage(T);if(this.properties.state===z.Disposed)this.port.close()}}process(V,A,F){try{let T=j0(this.properties,A,F,{currentTime,currentFrame,sampleRate},this.filterState);for(let J of T.messages)this.port.postMessage(J);let Q=currentTime-this.lastFrameTime;return this.lastFrameTime=currentTime,this.port.postMessage({type:\"frame\",data:[currentTime,currentFrame,Math.floor(this.properties.playhead),Q*1000]}),T.keepAlive}catch(T){return console.log(T),!0}}}registerProcessor(\"ClipProcessor\",P0);\n\n//# debugId=5101232AAE128B1064756E2164756E21\n//# sourceMappingURL=processor.js.map\n";
@@ -0,0 +1,43 @@
1
+ import { type BlockParameters, type BlockReturnState, type ClipProcessorOptions } from "./types";
2
+ export declare const SAMPLE_BLOCK_SIZE = 128;
3
+ export declare function getProperties(opts: ClipProcessorOptions | undefined, sampleRate: number): Required<ClipProcessorOptions>;
4
+ export declare function setOffset(properties: Required<ClipProcessorOptions>, offset: number | undefined, sampleRate: number): number;
5
+ export declare function findIndexesNormal(p: BlockParameters): BlockReturnState;
6
+ export declare function findIndexesWithPlaybackRates(p: BlockParameters): BlockReturnState;
7
+ export declare function fill(target: Float32Array[], source: Float32Array[], indexes: number[]): void;
8
+ export declare function fillWithSilence(buffer: Float32Array[]): void;
9
+ export declare function monoToStereo(signal: Float32Array[]): void;
10
+ export declare function copy(source: Float32Array[], target: Float32Array[]): void;
11
+ export declare function checkNans(output: Float32Array[]): number;
12
+ export interface BiquadState {
13
+ x_1: number;
14
+ x_2: number;
15
+ y_1: number;
16
+ y_2: number;
17
+ }
18
+ export declare function createFilterState(): BiquadState[];
19
+ export declare function gainFilter(arr: Float32Array[], gains: Float32Array): void;
20
+ export declare function panFilter(signal: Float32Array[], pans: Float32Array): void;
21
+ export declare function lowpassFilter(buffer: Float32Array[], cutoffs: Float32Array, sampleRate: number, states: BiquadState[]): void;
22
+ export declare function highpassFilter(buffer: Float32Array[], cutoffs: Float32Array, sampleRate: number, states: BiquadState[]): void;
23
+ export interface OutboundMessage {
24
+ type: string;
25
+ data?: unknown;
26
+ }
27
+ export declare function handleProcessorMessage(properties: Required<ClipProcessorOptions>, message: {
28
+ type: string;
29
+ data?: unknown;
30
+ }, currentTime: number, sampleRate: number): OutboundMessage[];
31
+ export interface ProcessContext {
32
+ currentTime: number;
33
+ currentFrame: number;
34
+ sampleRate: number;
35
+ }
36
+ export interface ProcessResult {
37
+ keepAlive: boolean;
38
+ messages: OutboundMessage[];
39
+ }
40
+ export declare function processBlock(props: Required<ClipProcessorOptions>, outputs: Float32Array[][], parameters: Record<string, Float32Array>, ctx: ProcessContext, filterState: {
41
+ lowpass: BiquadState[];
42
+ highpass: BiquadState[];
43
+ }): ProcessResult;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,192 @@
1
+ export declare const State: {
2
+ readonly Initial: 0;
3
+ readonly Started: 1;
4
+ readonly Stopped: 2;
5
+ readonly Paused: 3;
6
+ readonly Scheduled: 4;
7
+ readonly Ended: 5;
8
+ readonly Disposed: 6;
9
+ };
10
+ export type ClipProcessorState = (typeof State)[keyof typeof State];
11
+ export interface ClipProcessorOptions {
12
+ buffer?: Float32Array[];
13
+ streamBuffer?: StreamBufferState;
14
+ loop?: boolean;
15
+ loopStart?: number;
16
+ loopEnd?: number;
17
+ loopCrossfade?: number;
18
+ offset?: number;
19
+ duration?: number;
20
+ playhead?: number;
21
+ state?: ClipProcessorState;
22
+ startWhen?: number;
23
+ stopWhen?: number;
24
+ pauseWhen?: number;
25
+ resumeWhen?: number;
26
+ playedSamples?: number;
27
+ timesLooped?: number;
28
+ fadeInDuration?: number;
29
+ fadeOutDuration?: number;
30
+ enableFadeIn?: boolean;
31
+ enableFadeOut?: boolean;
32
+ enableLoopStart?: boolean;
33
+ enableLoopEnd?: boolean;
34
+ enableLoopCrossfade?: boolean;
35
+ enableGain?: boolean;
36
+ enablePan?: boolean;
37
+ enableHighpass?: boolean;
38
+ enableLowpass?: boolean;
39
+ enableDetune?: boolean;
40
+ enablePlaybackRate?: boolean;
41
+ }
42
+ export interface ClipWorkletOptions extends AudioWorkletNodeOptions {
43
+ processorOptions?: ClipProcessorOptions;
44
+ }
45
+ export type ClipNodeState = "initial" | "scheduled" | "started" | "stopped" | "paused" | "resumed" | "ended" | "disposed";
46
+ export type FrameData = readonly [
47
+ currentTime: number,
48
+ currentFrame: number,
49
+ playhead: number,
50
+ timeTaken: number
51
+ ];
52
+ export type ClipProcessorToggleMessageType = "toggleFadeIn" | "toggleFadeOut" | "toggleLoopStart" | "toggleLoopEnd" | "toggleLoopCrossfade" | "toggleGain" | "togglePan" | "toggleHighpass" | "toggleLowpass" | "toggleDetune" | "togglePlaybackRate";
53
+ export interface ClipProcessorOnmessageEvent {
54
+ readonly data: ClipProcessorMessageRx;
55
+ }
56
+ export type ClipProcessorOnmessage = (ev: ClipProcessorOnmessageEvent) => void;
57
+ export interface ProcessorWorkletOptions extends AudioWorkletNodeOptions {
58
+ readonly processorOptions?: ClipProcessorOptions;
59
+ }
60
+ export interface ClipProcessorStateMap {
61
+ readonly Initial: 0;
62
+ readonly Started: 1;
63
+ readonly Stopped: 2;
64
+ readonly Paused: 3;
65
+ readonly Scheduled: 4;
66
+ readonly Ended: 5;
67
+ readonly Disposed: 6;
68
+ }
69
+ export type ClipProcessorMessageRx = ClipProcessorBufferMessageRx | ClipProcessorBufferInitMessageRx | ClipProcessorBufferRangeMessageRx | ClipProcessorBufferEndMessageRx | ClipProcessorBufferResetMessageRx | ClipProcessorStartMessageRx | ClipProcessorStopMessageRx | ClipProcessorPauseMessageRx | ClipProcessorResumeMessageRx | ClipProcessorDisposeMessageRx | ClipProcessorLoopMessageRx | ClipProcessorLoopStartMessageRx | ClipProcessorLoopEndMessageRx | ClipProcessorPlayheadMessageRx | ClipProcessorFadeInMessageRx | ClipProcessorFadeOutMessageRx | ClipProcessorLoopCrossfadeMessageRx | ClipProcessorToggleMessageRx | ClipProcessorLogStateMessageRx;
70
+ export type ClipProcessorMessageType = "buffer" | "bufferInit" | "bufferRange" | "bufferEnd" | "bufferReset" | "start" | "stop" | "pause" | "resume" | "dispose" | "loop" | "loopStart" | "loopEnd" | "playhead" | "playbackRate" | "offset" | "fadeIn" | "fadeOut" | "loopCrossfade" | ClipProcessorToggleMessageType | "logState";
71
+ export interface ClipProcessorLogStateMessageRx {
72
+ readonly type: "logState";
73
+ readonly data?: never;
74
+ }
75
+ export interface ClipProcessorToggleMessageRx {
76
+ readonly type: ClipProcessorToggleMessageType;
77
+ readonly data?: boolean;
78
+ }
79
+ export interface ClipProcessorBufferMessageRx {
80
+ readonly type: "buffer";
81
+ readonly data: Float32Array[];
82
+ }
83
+ export interface StreamBufferSpan {
84
+ startSample: number;
85
+ endSample: number;
86
+ }
87
+ export interface BufferRangeWrite {
88
+ readonly startSample: number;
89
+ readonly channelData: Float32Array[];
90
+ readonly totalLength?: number | null;
91
+ readonly streamEnded?: boolean;
92
+ }
93
+ export interface StreamBufferState {
94
+ totalLength: number | null;
95
+ committedLength: number;
96
+ streamEnded: boolean;
97
+ streaming: boolean;
98
+ writtenSpans: StreamBufferSpan[];
99
+ pendingWrites: BufferRangeWrite[];
100
+ lowWaterThreshold: number;
101
+ lowWaterNotified: boolean;
102
+ lastUnderrunSample: number | null;
103
+ }
104
+ export interface ClipProcessorBufferInitMessageRx {
105
+ readonly type: "bufferInit";
106
+ readonly data: {
107
+ readonly channels: number;
108
+ readonly totalLength: number;
109
+ readonly streaming?: boolean;
110
+ };
111
+ }
112
+ export interface ClipProcessorBufferRangeMessageRx {
113
+ readonly type: "bufferRange";
114
+ readonly data: BufferRangeWrite;
115
+ }
116
+ export interface ClipProcessorBufferEndMessageRx {
117
+ readonly type: "bufferEnd";
118
+ readonly data?: {
119
+ readonly totalLength?: number;
120
+ };
121
+ }
122
+ export interface ClipProcessorBufferResetMessageRx {
123
+ readonly type: "bufferReset";
124
+ readonly data?: never;
125
+ }
126
+ export interface ClipProcessorStartMessageRx {
127
+ readonly type: "start";
128
+ readonly data?: {
129
+ readonly duration?: number;
130
+ readonly offset?: number;
131
+ readonly when?: number;
132
+ };
133
+ }
134
+ export interface ClipProcessorStopMessageRx {
135
+ readonly type: "stop";
136
+ readonly data?: number;
137
+ }
138
+ export interface ClipProcessorPauseMessageRx {
139
+ readonly type: "pause";
140
+ readonly data?: number;
141
+ }
142
+ export interface ClipProcessorResumeMessageRx {
143
+ readonly type: "resume";
144
+ readonly data?: number;
145
+ }
146
+ export interface ClipProcessorDisposeMessageRx {
147
+ readonly type: "dispose";
148
+ readonly data?: never;
149
+ }
150
+ export interface ClipProcessorLoopMessageRx {
151
+ readonly type: "loop";
152
+ readonly data: boolean;
153
+ }
154
+ export interface ClipProcessorLoopStartMessageRx {
155
+ readonly type: "loopStart";
156
+ readonly data: number;
157
+ }
158
+ export interface ClipProcessorLoopEndMessageRx {
159
+ readonly type: "loopEnd";
160
+ readonly data: number;
161
+ }
162
+ export interface ClipProcessorPlayheadMessageRx {
163
+ readonly type: "playhead";
164
+ readonly data: number;
165
+ }
166
+ export interface ClipProcessorFadeInMessageRx {
167
+ readonly type: "fadeIn";
168
+ readonly data: number;
169
+ }
170
+ export interface ClipProcessorFadeOutMessageRx {
171
+ readonly type: "fadeOut";
172
+ readonly data: number;
173
+ }
174
+ export interface ClipProcessorLoopCrossfadeMessageRx {
175
+ readonly type: "loopCrossfade";
176
+ readonly data: number;
177
+ }
178
+ export interface BlockParameters {
179
+ readonly playhead: number;
180
+ readonly durationSamples: number;
181
+ readonly loop: boolean;
182
+ readonly loopStartSamples: number;
183
+ readonly loopEndSamples: number;
184
+ readonly bufferLength: number;
185
+ readonly playbackRates: Float32Array;
186
+ }
187
+ export interface BlockReturnState {
188
+ readonly playhead: number;
189
+ readonly ended: boolean;
190
+ readonly looped: boolean;
191
+ readonly indexes: number[];
192
+ }
@@ -0,0 +1,22 @@
1
+ export declare function dbFromLin(lin: number): number;
2
+ export declare function linFromDb(db: number): number;
3
+ declare const TEMPO_RELATIVE_SNAPS: readonly ["beat", "bar", "8th", "16th"];
4
+ export type TempoRelativeSnap = (typeof TEMPO_RELATIVE_SNAPS)[number];
5
+ export declare function isTempoRelativeSnap(snap: string): snap is TempoRelativeSnap;
6
+ export declare function getTempoSnapInterval(snap: string, tempo: number): number | null;
7
+ export declare function remapTempoRelativeValue(value: number, snap: string, oldTempo: number, newTempo: number, min: number, max: number): number;
8
+ export declare function getSnappedValue(value: number, snap: string, tempo: number): number;
9
+ export interface SliderPreset {
10
+ snaps?: number[];
11
+ ticks?: number[];
12
+ min?: number;
13
+ max?: number;
14
+ skew?: number;
15
+ step?: number;
16
+ logarithmic?: boolean;
17
+ }
18
+ export declare const presets: Record<string, SliderPreset>;
19
+ export declare function float32ArrayFromAudioBuffer(buffer: AudioBuffer): Float32Array[];
20
+ export declare function audioBufferFromFloat32Array(context: BaseAudioContext, data?: Float32Array[]): AudioBuffer | undefined;
21
+ export declare function generateSnapPoints(snap: string, tempo: number, min: number, max: number): number[];
22
+ export {};
@@ -0,0 +1,6 @@
1
+ /** Blob URL from embedded processor code. Zero-config, default for npm users. */
2
+ export declare function getProcessorBlobUrl(): string;
3
+ /** jsDelivr CDN URL. For script-tag / no-bundler usage. */
4
+ export declare function getProcessorCdnUrl(version?: string): string;
5
+ /** Custom URL relative to a base. For self-hosted processor.js. */
6
+ export declare function getProcessorModuleUrl(baseUrl?: string): string;
@@ -0,0 +1,28 @@
1
+ export interface AudioControlProps {
2
+ label: string;
3
+ controlKey?: string;
4
+ min: number;
5
+ max: number;
6
+ value: number;
7
+ defaultValue?: number;
8
+ step?: number;
9
+ tempo?: number;
10
+ snap?: string;
11
+ preset?: string;
12
+ title?: string;
13
+ enabled?: boolean;
14
+ hasToggle?: boolean;
15
+ hasSnap?: boolean;
16
+ hasMaxLock?: boolean;
17
+ audioDuration?: number | null;
18
+ maxLocked?: boolean;
19
+ onChange?: (value: number) => void;
20
+ onToggle?: (enabled: boolean) => void;
21
+ onSnapChange?: (snap: string) => void;
22
+ onMinChange?: (val: number) => void;
23
+ onMaxChange?: (val: number) => void;
24
+ onMaxLockedChange?: (locked: boolean) => void;
25
+ }
26
+ declare function AudioControlInner({ label, controlKey, min: propMin, max: propMax, value, defaultValue, step, tempo, snap, preset, title, enabled, hasToggle, hasSnap, hasMaxLock, audioDuration, maxLocked, onChange, onToggle, onSnapChange, onMinChange, onMaxChange, onMaxLockedChange, }: AudioControlProps): import("react/jsx-runtime").JSX.Element;
27
+ export declare const AudioControl: import("react").MemoExoticComponent<typeof AudioControlInner>;
28
+ export {};
@@ -0,0 +1,17 @@
1
+ export interface ContextMenuProps {
2
+ x: number;
3
+ y: number;
4
+ snap: string;
5
+ snapMode?: "tempo" | "preset";
6
+ min: number;
7
+ max: number;
8
+ maxLocked?: boolean;
9
+ showMaxLock?: boolean;
10
+ audioDuration: number | null;
11
+ onSnapChange: (snap: string) => void;
12
+ onMinChange: (val: number) => void;
13
+ onMaxChange: (val: number) => void;
14
+ onMaxLockedChange?: (locked: boolean) => void;
15
+ onClose: () => void;
16
+ }
17
+ export declare function ContextMenu({ x, y, snap, snapMode, min, max, maxLocked, showMaxLock, audioDuration, onSnapChange, onMinChange, onMaxChange, onMaxLockedChange, onClose, }: ContextMenuProps): import("react").ReactPortal;
@@ -0,0 +1,26 @@
1
+ import type { ControlDef, ControlKey } from "../controls/controlDefs";
2
+ import type { LinkedControlPairDef, LinkedControlPairKey } from "../controls/linkedControlPairs";
3
+ interface ControlSectionProps {
4
+ legend: string;
5
+ defs: ControlDef[];
6
+ values: Record<ControlKey, number>;
7
+ snaps: Record<ControlKey, string>;
8
+ enabled: Record<ControlKey, boolean>;
9
+ mins: Record<ControlKey, number>;
10
+ maxs: Record<ControlKey, number>;
11
+ maxLocked: Record<ControlKey, boolean>;
12
+ linked?: Record<LinkedControlPairKey, boolean>;
13
+ linkedPairs?: readonly LinkedControlPairDef[];
14
+ tempo: number;
15
+ audioDuration?: number | null;
16
+ onValueChange: (key: ControlKey, val: number) => void;
17
+ onToggle: (key: ControlKey, on: boolean) => void;
18
+ onLinkedChange?: (key: LinkedControlPairKey, linked: boolean) => void;
19
+ onSnapChange: (key: ControlKey, snap: string) => void;
20
+ onMinChange: (key: ControlKey, val: number) => void;
21
+ onMaxChange: (key: ControlKey, val: number) => void;
22
+ onMaxLockedChange: (key: ControlKey, locked: boolean) => void;
23
+ }
24
+ declare function ControlSectionInner({ legend, defs, linked, linkedPairs, onLinkedChange, ...controlProps }: ControlSectionProps): import("react/jsx-runtime").JSX.Element;
25
+ export declare const ControlSection: import("react").MemoExoticComponent<typeof ControlSectionInner>;
26
+ export {};
@@ -0,0 +1,10 @@
1
+ interface DetuneControlProps {
2
+ value: number;
3
+ defaultValue: number;
4
+ enabled: boolean;
5
+ onChange: (value: number) => void;
6
+ onToggle: (enabled: boolean) => void;
7
+ }
8
+ declare function DetuneControlInner({ value, defaultValue, enabled, onChange, onToggle, }: DetuneControlProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare const DetuneControl: import("react").MemoExoticComponent<typeof DetuneControlInner>;
10
+ export {};
@@ -0,0 +1,14 @@
1
+ import type { ClipNodeState } from "../audio/types";
2
+ interface DisplayPanelProps {
3
+ nodeState: ClipNodeState;
4
+ statusMessage: string | null;
5
+ soundName: string | null;
6
+ currentTime: string;
7
+ currentFrame: string;
8
+ timesLooped: string;
9
+ latency: string;
10
+ timeTaken: string;
11
+ }
12
+ declare function DisplayPanelInner({ nodeState, statusMessage, soundName, currentTime, currentFrame, timesLooped, latency, timeTaken, }: DisplayPanelProps): import("react/jsx-runtime").JSX.Element;
13
+ export declare const DisplayPanel: import("react").MemoExoticComponent<typeof DisplayPanelInner>;
14
+ export {};
@@ -0,0 +1,12 @@
1
+ interface FilterControlProps {
2
+ label: string;
3
+ controlKey: string;
4
+ value: number;
5
+ defaultValue: number;
6
+ enabled: boolean;
7
+ onChange: (value: number) => void;
8
+ onToggle: (enabled: boolean) => void;
9
+ }
10
+ declare function FilterControlInner({ label, controlKey: _controlKey, value, defaultValue, enabled, onChange, onToggle, }: FilterControlProps): import("react/jsx-runtime").JSX.Element;
11
+ export declare const FilterControl: import("react").MemoExoticComponent<typeof FilterControlInner>;
12
+ export {};
@@ -0,0 +1,10 @@
1
+ interface GainControlProps {
2
+ value: number;
3
+ defaultValue: number;
4
+ enabled: boolean;
5
+ onChange: (value: number) => void;
6
+ onToggle: (enabled: boolean) => void;
7
+ }
8
+ declare function GainControlInner({ value, defaultValue, enabled, onChange, onToggle, }: GainControlProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare const GainControl: import("react").MemoExoticComponent<typeof GainControlInner>;
10
+ export {};
@@ -0,0 +1,10 @@
1
+ interface PanControlProps {
2
+ value: number;
3
+ defaultValue: number;
4
+ enabled: boolean;
5
+ onChange: (value: number) => void;
6
+ onToggle: (enabled: boolean) => void;
7
+ }
8
+ declare function PanControlInner({ value, defaultValue, enabled, onChange, onToggle, }: PanControlProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare const PanControl: import("react").MemoExoticComponent<typeof PanControlInner>;
10
+ export {};
@@ -0,0 +1,10 @@
1
+ interface PlaybackRateControlProps {
2
+ value: number;
3
+ defaultValue: number;
4
+ enabled: boolean;
5
+ onChange: (value: number) => void;
6
+ onToggle: (enabled: boolean) => void;
7
+ }
8
+ declare function PlaybackRateControlInner({ value, defaultValue, enabled, onChange, onToggle, }: PlaybackRateControlProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare const PlaybackRateControl: import("react").MemoExoticComponent<typeof PlaybackRateControlInner>;
10
+ export {};