supersonic-scsynth 0.53.0 → 0.55.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.
@@ -1 +1 @@
1
- function B(e,t,s){return(s-1-e+t)%s}function L({uint8View:e,dataView:t,bufferStart:s,bufferSize:r,head:n,payload:o,sequence:i,messageMagic:c,headerSize:_,sourceId:S=0,headerScratch:p=null,headerScratchView:l=null}){let f=o.length,u=_+f+3&-4,T=r-n;if(u>T){let E=p||new Uint8Array(_),A=l||new DataView(E.buffer);A.setUint32(0,c,!0),A.setUint32(4,u,!0),A.setUint32(8,i,!0),A.setUint32(12,S,!0);let I=s+n,U=s;if(T>=_){e.set(E,I);let a=T-_;a>0&&e.set(o.subarray(0,a),I+_),e.set(o.subarray(a),U)}else{e.set(E.subarray(0,T),I),e.set(E.subarray(T),U);let a=_-T;e.set(o,U+a)}}else{let E=s+n;t.setUint32(E,c,!0),t.setUint32(E+4,u,!0),t.setUint32(E+8,i,!0),t.setUint32(E+12,S,!0),e.set(o,E+_)}return(n+u)%r}function Y(e,t,s=0,r=!1){for(let n=0;n<=s;n++)if(Atomics.compareExchange(e,t,0,1)===0)return!0;if(r){for(let o=0;o<100;o++)if(Atomics.wait(e,t,1,100),Atomics.compareExchange(e,t,0,1)===0)return!0;return console.error("[RingBuffer] Lock acquisition timeout after 10s - possible deadlock"),!1}return!1}function b(e,t){Atomics.store(e,t,0),Atomics.notify(e,t,1)}function N({atomicView:e,dataView:t,uint8View:s,bufferConstants:r,ringBufferBase:n,controlIndices:o,oscMessage:i,sourceId:c=0,maxSpins:_=0,useWait:S=!1}){let p=i.length,l=r.MESSAGE_HEADER_SIZE+p;if(l>r.IN_BUFFER_SIZE-r.MESSAGE_HEADER_SIZE||!Y(e,o.IN_WRITE_LOCK,_,S))return!1;try{let f=Atomics.load(e,o.IN_HEAD),R=Atomics.load(e,o.IN_TAIL),u=l+3&-4;if(B(f,R,r.IN_BUFFER_SIZE)<u)return!1;let E=Atomics.add(e,o.IN_SEQUENCE,1),A=L({uint8View:s,dataView:t,bufferStart:n+r.IN_BUFFER_START,bufferSize:r.IN_BUFFER_SIZE,head:f,payload:i,sequence:E,messageMagic:r.MESSAGE_MAGIC,headerSize:r.MESSAGE_HEADER_SIZE,sourceId:c});return Atomics.load(e,o.IN_HEAD),Atomics.store(e,o.IN_HEAD,A),Atomics.notify(e,o.IN_HEAD,1),!0}finally{b(e,o.IN_WRITE_LOCK)}}function d(e,t){let s=e+t;return{IN_HEAD:(s+0)/4,IN_TAIL:(s+4)/4,IN_SEQUENCE:(s+24)/4,IN_WRITE_LOCK:(s+40)/4,IN_LOG_TAIL:(s+44)/4}}function y(e){return e.length>=8&&e[0]===35&&e[1]===98&&e[2]===117&&e[3]===110&&e[4]===100&&e[5]===108&&e[6]===101&&e[7]===0}function k(e){if(e.length<16)return null;let t=new DataView(e.buffer,e.byteOffset,e.byteLength);return{ntpSeconds:t.getUint32(8,!1),ntpFraction:t.getUint32(12,!1)}}function C(){return(performance.timeOrigin+performance.now())/1e3+2208988800}function D(e,t={}){let{getCurrentNTP:s=C,bypassLookaheadS:r=.5}=t;if(!y(e))return"nonBundle";let n=k(e);if(!n)return"nonBundle";let{ntpSeconds:o,ntpFraction:i}=n;if(o===0&&i<=1)return"immediate";let c=s();if(c===null||c===0)return"immediate";let S=o+i/4294967296-c;return S<0?"late":S<r?"nearFuture":"farFuture"}function O(e){return e!=="farFuture"}var h=class e{#s;#r;#o;#_;#e;#t;#i;#E;#c;#S;#n={messagesSent:0,bytesSent:0,nonBundle:0,immediate:0,nearFuture:0,late:0,bypassed:0};constructor(t,s){if(this.#s=t,this.#e=s.preschedulerPort||null,this.#i=s.bypassLookaheadS??.5,this.#E=s.sourceId??0,this.#c=s.blocking??this.#E!==0,this.#S=s.getCurrentNTP??C,t==="postMessage")this.#r=s.port;else if(this.#o={sharedBuffer:s.sharedBuffer,ringBufferBase:s.ringBufferBase,bufferConstants:s.bufferConstants,controlIndices:s.controlIndices},this.#a(),s.sharedBuffer&&s.bufferConstants){let r=s.ringBufferBase+s.bufferConstants.METRICS_START;this.#t=new Int32Array(s.sharedBuffer,r,s.bufferConstants.METRICS_SIZE/4)}}#a(){let t=this.#o.sharedBuffer;this.#_={atomicView:new Int32Array(t),dataView:new DataView(t),uint8View:new Uint8Array(t)}}classify(t){return D(t,{getCurrentNTP:this.#S,bypassLookaheadS:this.#i})}#u(t,s=null){if(this.#s==="sab"&&this.#t){if(Atomics.add(this.#t,24,1),Atomics.add(this.#t,25,t),s){let n={nonBundle:38,immediate:39,nearFuture:40,late:41}[s];n!==void 0&&(Atomics.add(this.#t,n,1),Atomics.add(this.#t,22,1))}}else this.#n.messagesSent++,this.#n.bytesSent+=t,s&&s in this.#n&&(this.#n[s]++,this.#n.bypassed++)}getAndResetMetrics(){let t={...this.#n};return this.#n={messagesSent:0,bytesSent:0,nonBundle:0,immediate:0,nearFuture:0,late:0,bypassed:0},t}getMetrics(){return this.#s==="sab"&&this.#t?{messagesSent:Atomics.load(this.#t,24),bytesSent:Atomics.load(this.#t,25),nonBundle:Atomics.load(this.#t,38),immediate:Atomics.load(this.#t,39),nearFuture:Atomics.load(this.#t,40),late:Atomics.load(this.#t,41),bypassed:Atomics.load(this.#t,22)}:{...this.#n}}#T(t,s=null,r=!0){if(this.#s==="postMessage")return this.#r?(this.#r.postMessage({type:"osc",oscData:t,bypassCategory:s,sourceId:this.#E}),!0):!1;{let n=this.#c,o=N({atomicView:this.#_.atomicView,dataView:this.#_.dataView,uint8View:this.#_.uint8View,bufferConstants:this.#o.bufferConstants,ringBufferBase:this.#o.ringBufferBase,controlIndices:this.#o.controlIndices,oscMessage:t,sourceId:this.#E,maxSpins:n?10:0,useWait:n});return!o&&!n&&r&&this.#e?(this.#t&&Atomics.add(this.#t,45,1),this.#e.postMessage({type:"directDispatch",oscData:t,sourceId:this.#E}),!0):o}}#A(t){return this.#e?(this.#e.postMessage({type:"osc",oscData:t,sourceId:this.#E}),!0):(console.error("[OscChannel] No prescheduler port, sending direct"),this.#T(t))}send(t){let s=this.classify(t);if(O(s)){let r=this.#T(t,s);return r&&this.#u(t.length,s),r}else{let r=this.#A(t);return r&&this.#u(t.length,null),r}}sendDirect(t){return this.#T(t)}sendToPrescheduler(t){return this.#A(t)}set getCurrentNTP(t){this.#S=t}get mode(){return this.#s}get transferable(){let t={mode:this.#s,preschedulerPort:this.#e,bypassLookaheadS:this.#i,sourceId:this.#E,blocking:this.#c};return this.#s==="postMessage"?{...t,port:this.#r}:{...t,sharedBuffer:this.#o.sharedBuffer,ringBufferBase:this.#o.ringBufferBase,bufferConstants:this.#o.bufferConstants,controlIndices:this.#o.controlIndices}}get transferList(){let t=[];return this.#s==="postMessage"&&this.#r&&t.push(this.#r),this.#e&&t.push(this.#e),t}close(){this.#s==="postMessage"&&this.#r&&(this.#r.close(),this.#r=null),this.#e&&(this.#e.close(),this.#e=null)}static createPostMessage(t){return t instanceof MessagePort?new e("postMessage",{port:t}):new e("postMessage",t)}static createSAB(t){let s=t.controlIndices;return s||(s=d(t.ringBufferBase,t.bufferConstants.CONTROL_START)),new e("sab",{sharedBuffer:t.sharedBuffer,ringBufferBase:t.ringBufferBase,bufferConstants:t.bufferConstants,controlIndices:s,preschedulerPort:t.preschedulerPort,bypassLookaheadS:t.bypassLookaheadS,sourceId:t.sourceId,blocking:t.blocking})}static fromTransferable(t){return t.mode==="postMessage"?new e("postMessage",{port:t.port,preschedulerPort:t.preschedulerPort,bypassLookaheadS:t.bypassLookaheadS,sourceId:t.sourceId,blocking:t.blocking}):new e("sab",{sharedBuffer:t.sharedBuffer,ringBufferBase:t.ringBufferBase,bufferConstants:t.bufferConstants,controlIndices:t.controlIndices,preschedulerPort:t.preschedulerPort,bypassLookaheadS:t.bypassLookaheadS,sourceId:t.sourceId,blocking:t.blocking})}};export{h as OscChannel};
1
+ function U(s,t,e){return(e-1-s+t)%e}function B({uint8View:s,dataView:t,bufferStart:e,bufferSize:r,head:n,payload:o,sequence:E,messageMagic:c,headerSize:i,sourceId:S=0,headerScratch:u=null,headerScratchView:A=null}){let l=o.length,T=i+l+3&-4,a=r-n;if(T>a){let _=u||new Uint8Array(i),f=A||new DataView(_.buffer);f.setUint32(0,c,!0),f.setUint32(4,T,!0),f.setUint32(8,E,!0),f.setUint32(12,S,!0);let d=e+n,I=e;if(a>=i){s.set(_,d);let h=a-i;h>0&&s.set(o.subarray(0,h),d+i),s.set(o.subarray(h),I)}else{s.set(_.subarray(0,a),d),s.set(_.subarray(a),I);let h=i-a;s.set(o,I+h)}}else{let _=e+n;t.setUint32(_,c,!0),t.setUint32(_+4,T,!0),t.setUint32(_+8,E,!0),t.setUint32(_+12,S,!0),s.set(o,_+i)}return(n+T)%r}function b(s,t,e=0,r=!1){for(let n=0;n<=e;n++)if(Atomics.compareExchange(s,t,0,1)===0)return!0;if(r){for(let o=0;o<100;o++)if(Atomics.wait(s,t,1,100),Atomics.compareExchange(s,t,0,1)===0)return!0;return console.error("[RingBuffer] Lock acquisition timeout after 10s - possible deadlock"),!1}return!1}function Y(s,t){Atomics.store(s,t,0),Atomics.notify(s,t,1)}function N({atomicView:s,dataView:t,uint8View:e,bufferConstants:r,ringBufferBase:n,controlIndices:o,oscMessage:E,sourceId:c=0,maxSpins:i=0,useWait:S=!1}){let u=E.length,A=r.MESSAGE_HEADER_SIZE+u;if(A>r.IN_BUFFER_SIZE-r.MESSAGE_HEADER_SIZE||!b(s,o.IN_WRITE_LOCK,i,S))return!1;try{let l=Atomics.load(s,o.IN_HEAD),C=Atomics.load(s,o.IN_TAIL),T=A+3&-4;if(U(l,C,r.IN_BUFFER_SIZE)<T)return!1;let _=Atomics.add(s,o.IN_SEQUENCE,1),f=B({uint8View:e,dataView:t,bufferStart:n+r.IN_BUFFER_START,bufferSize:r.IN_BUFFER_SIZE,head:l,payload:E,sequence:_,messageMagic:r.MESSAGE_MAGIC,headerSize:r.MESSAGE_HEADER_SIZE,sourceId:c});return Atomics.load(s,o.IN_HEAD),Atomics.store(s,o.IN_HEAD,f),Atomics.notify(s,o.IN_HEAD,1),!0}finally{Y(s,o.IN_WRITE_LOCK)}}function L(s,t){let e=s+t;return{IN_HEAD:(e+0)/4,IN_TAIL:(e+4)/4,IN_SEQUENCE:(e+24)/4,IN_WRITE_LOCK:(e+40)/4,IN_LOG_TAIL:(e+44)/4}}function G(s){return s.length>=8&&s[0]===35&&s[1]===98&&s[2]===117&&s[3]===110&&s[4]===100&&s[5]===108&&s[6]===101&&s[7]===0}function w(s){if(s.length<16)return null;let t=new DataView(s.buffer,s.byteOffset,s.byteLength);return{ntpSeconds:t.getUint32(8,!1),ntpFraction:t.getUint32(12,!1)}}function p(){return(performance.timeOrigin+performance.now())/1e3+2208988800}function D(s,t={}){let{getCurrentNTP:e=p,bypassLookaheadS:r=.5}=t;if(!G(s))return"nonBundle";let n=w(s);if(!n)return"nonBundle";let{ntpSeconds:o,ntpFraction:E}=n;if(o===0&&E<=1)return"immediate";let c=e();if(c===null||c===0)return"immediate";let S=o+E/4294967296-c;return S<0?"late":S<r?"nearFuture":"farFuture"}function O(s){return s!=="farFuture"}var R=class s{#s;#r;#o;#u;#e;#t;#A;#E;#l;#d;#I;#p;#a;#_;#T;#c;#S;#i;#f;#n={messagesSent:0,bytesSent:0,nonBundle:0,immediate:0,nearFuture:0,late:0,bypassed:0};constructor(t,e){if(this.#s=t,this.#e=e.preschedulerPort||null,this.#A=e.bypassLookaheadS??.5,this.#E=e.sourceId??0,this.#l=e.blocking??this.#E!==0,this.#d=e.getCurrentNTP??p,this.#T=1e3,t==="postMessage")this.#r=e.port;else{if(this.#o={sharedBuffer:e.sharedBuffer,ringBufferBase:e.ringBufferBase,bufferConstants:e.bufferConstants,controlIndices:e.controlIndices},this.#N(),e.sharedBuffer&&e.bufferConstants){let r=e.ringBufferBase+e.bufferConstants.METRICS_START;this.#t=new Int32Array(e.sharedBuffer,r,e.bufferConstants.METRICS_SIZE/4)}if(e.sharedBuffer&&e.bufferConstants?.NODE_ID_COUNTER_START!==void 0){let r=e.ringBufferBase+e.bufferConstants.NODE_ID_COUNTER_START;this.#I=new Int32Array(e.sharedBuffer,r,1),this.#C()}}e.nodeIdSource&&(this.#c=e.nodeIdSource,this.#C()),e.nodeIdRange&&(this.#p=e.nodeIdRange.from,this.#a=e.nodeIdRange.to,this.#_=e.nodeIdRange.from),e.nodeIdPort&&(this.#S=e.nodeIdPort,this.#S.onmessage=r=>{r.data.type==="nodeIdRange"&&(this.#i={from:r.data.from,to:r.data.to})},this.#h())}#N(){let t=this.#o.sharedBuffer;this.#u={atomicView:new Int32Array(t),dataView:new DataView(t),uint8View:new Uint8Array(t)}}classify(t){return D(t,{getCurrentNTP:this.#d,bypassLookaheadS:this.#A})}#U(t,e=null){if(this.#s==="sab"&&this.#t){if(Atomics.add(this.#t,24,1),Atomics.add(this.#t,25,t),e){let n={nonBundle:38,immediate:39,nearFuture:40,late:41}[e];n!==void 0&&(Atomics.add(this.#t,n,1),Atomics.add(this.#t,22,1))}}else this.#n.messagesSent++,this.#n.bytesSent+=t,e&&e in this.#n&&(this.#n[e]++,this.#n.bypassed++)}getAndResetMetrics(){let t={...this.#n};return this.#n={messagesSent:0,bytesSent:0,nonBundle:0,immediate:0,nearFuture:0,late:0,bypassed:0},t}getMetrics(){return this.#s==="sab"&&this.#t?{messagesSent:Atomics.load(this.#t,24),bytesSent:Atomics.load(this.#t,25),nonBundle:Atomics.load(this.#t,38),immediate:Atomics.load(this.#t,39),nearFuture:Atomics.load(this.#t,40),late:Atomics.load(this.#t,41),bypassed:Atomics.load(this.#t,22)}:{...this.#n}}#R(t,e=null,r=!0){if(this.#s==="postMessage")return this.#r?(this.#r.postMessage({type:"osc",oscData:t,bypassCategory:e,sourceId:this.#E}),!0):!1;{let n=this.#l,o=N({atomicView:this.#u.atomicView,dataView:this.#u.dataView,uint8View:this.#u.uint8View,bufferConstants:this.#o.bufferConstants,ringBufferBase:this.#o.ringBufferBase,controlIndices:this.#o.controlIndices,oscMessage:t,sourceId:this.#E,maxSpins:n?10:0,useWait:n});return!o&&!n&&r&&this.#e?(this.#t&&Atomics.add(this.#t,45,1),this.#e.postMessage({type:"directDispatch",oscData:t,sourceId:this.#E}),!0):o}}#B(t){return this.#e?(this.#e.postMessage({type:"osc",oscData:t,sourceId:this.#E}),!0):(console.error("[OscChannel] No prescheduler port, sending direct"),this.#R(t))}send(t){let e=this.classify(t);if(O(e)){let r=this.#R(t,e);return r&&this.#U(t.length,e),r}else{let r=this.#B(t);return r&&this.#U(t.length,null),r}}sendDirect(t){return this.#R(t)}sendToPrescheduler(t){return this.#B(t)}nextNodeId(){if(this.#I)return Atomics.add(this.#I,0,1);this.#_>=this.#a&&this.#C();let t=this.#_++;return this.#S&&!this.#i&&this.#a-this.#_<=1e3&&this.#h(),t}#C(){if(this.#c){let t=this.#c(this.#T);this.#p=t.from,this.#a=t.to,this.#_=t.from}else this.#i?(this.#p=this.#i.from,this.#a=this.#i.to,this.#_=this.#i.from,this.#i=null,this.#h()):this.#S&&(console.warn("[OscChannel] nextNodeId() range exhausted before async refill arrived. IDs may not be unique. Yield to the event loop between large batches of nextNodeId() calls."),this.#h())}#h(){this.#S&&this.#S.postMessage({type:"requestNodeIdRange"})}set getCurrentNTP(t){this.#d=t}get mode(){return this.#s}get transferable(){let t={mode:this.#s,preschedulerPort:this.#e,bypassLookaheadS:this.#A,sourceId:this.#E,blocking:this.#l};if(this.#s==="postMessage"){let e=this.#T*10,r,n;if(this.#c){let o=this.#c(e);r={from:o.from,to:o.to};let E=new MessageChannel,c=this.#c,i=this.#T;E.port1.onmessage=S=>{if(S.data.type==="requestNodeIdRange"){let u=c(i);E.port1.postMessage({type:"nodeIdRange",from:u.from,to:u.to})}},n=E.port2,this.#f=n}return{...t,port:this.#r,nodeIdRange:r,nodeIdPort:n}}else return{...t,sharedBuffer:this.#o.sharedBuffer,ringBufferBase:this.#o.ringBufferBase,bufferConstants:this.#o.bufferConstants,controlIndices:this.#o.controlIndices}}get transferList(){let t=[];return this.#s==="postMessage"&&this.#r&&t.push(this.#r),this.#e&&t.push(this.#e),this.#f&&(t.push(this.#f),this.#f=null),t}close(){this.#s==="postMessage"&&this.#r&&(this.#r.close(),this.#r=null),this.#e&&(this.#e.close(),this.#e=null)}static createPostMessage(t){return t instanceof MessagePort?new s("postMessage",{port:t}):new s("postMessage",t)}static createSAB(t){let e=t.controlIndices;return e||(e=L(t.ringBufferBase,t.bufferConstants.CONTROL_START)),new s("sab",{sharedBuffer:t.sharedBuffer,ringBufferBase:t.ringBufferBase,bufferConstants:t.bufferConstants,controlIndices:e,preschedulerPort:t.preschedulerPort,bypassLookaheadS:t.bypassLookaheadS,sourceId:t.sourceId,blocking:t.blocking})}static fromTransferable(t){return t.mode==="postMessage"?new s("postMessage",{port:t.port,preschedulerPort:t.preschedulerPort,bypassLookaheadS:t.bypassLookaheadS,sourceId:t.sourceId,blocking:t.blocking,nodeIdRange:t.nodeIdRange,nodeIdPort:t.nodeIdPort}):new s("sab",{sharedBuffer:t.sharedBuffer,ringBufferBase:t.ringBufferBase,bufferConstants:t.bufferConstants,controlIndices:t.controlIndices,preschedulerPort:t.preschedulerPort,bypassLookaheadS:t.bypassLookaheadS,sourceId:t.sourceId,blocking:t.blocking})}};export{R as OscChannel};
@@ -1,8 +1,8 @@
1
- var Ut=Object.defineProperty;var Rt=(i,e)=>{for(var t in e)Ut(i,t,{get:e[t],enumerable:!0})};var M=class i{constructor(e){if(new.target===i)throw new Error("Transport is abstract - use SABTransport or PostMessageTransport");this._config=e,this._disposed=!1}get mode(){return this._config.mode}send(e,t){throw new Error("Abstract method - implement in subclass")}onReply(e){throw new Error("Abstract method - implement in subclass")}onDebug(e){throw new Error("Abstract method - implement in subclass")}onError(e){throw new Error("Abstract method - implement in subclass")}getMetrics(){throw new Error("Abstract method - implement in subclass")}async initialize(){throw new Error("Abstract method - implement in subclass")}createOscChannel(){throw new Error("Abstract method - implement in subclass")}dispose(){this._disposed=!0}get ready(){throw new Error("Abstract method - implement in subclass")}};var de=new Map;function He(i){try{return new URL(i,window.location.href).origin!==window.location.origin}catch{return!1}}async function ze(i){if(de.has(i))return de.get(i);let e=await fetch(i);if(!e.ok)throw new Error(`Failed to fetch ${i}: ${e.status} ${e.statusText}`);let t=await e.text(),s=new Blob([t],{type:"application/javascript"}),r=URL.createObjectURL(s);return de.set(i,r),r}async function C(i,e={}){let t=i;return He(i)&&(t=await ze(i)),new Worker(t,e)}async function Ye(i,e){let t=e;He(e)&&(t=await ze(e)),await i.addModule(t)}function Ge(i,e,t){return(t-1-i+e)%t}function $e({uint8View:i,dataView:e,bufferStart:t,bufferSize:s,head:r,payload:n,sequence:o,messageMagic:a,headerSize:c,sourceId:l=0,headerScratch:u=null,headerScratchView:f=null}){let h=n.length,m=c+h+3&-4,g=s-r;if(m>g){let p=u||new Uint8Array(c),y=f||new DataView(p.buffer);y.setUint32(0,a,!0),y.setUint32(4,m,!0),y.setUint32(8,o,!0),y.setUint32(12,l,!0);let _=t+r,d=t;if(g>=c){i.set(p,_);let w=g-c;w>0&&i.set(n.subarray(0,w),_+c),i.set(n.subarray(w),d)}else{i.set(p.subarray(0,g),_),i.set(p.subarray(g),d);let w=c-g;i.set(n,d+w)}}else{let p=t+r;e.setUint32(p,a,!0),e.setUint32(p+4,m,!0),e.setUint32(p+8,o,!0),e.setUint32(p+12,l,!0),i.set(n,p+c)}return(r+m)%s}function It(i,e,t=0,s=!1){for(let r=0;r<=t;r++)if(Atomics.compareExchange(i,e,0,1)===0)return!0;if(s){for(let n=0;n<100;n++)if(Atomics.wait(i,e,1,100),Atomics.compareExchange(i,e,0,1)===0)return!0;return console.error("[RingBuffer] Lock acquisition timeout after 10s - possible deadlock"),!1}return!1}function Dt(i,e){Atomics.store(i,e,0),Atomics.notify(i,e,1)}function We({atomicView:i,dataView:e,uint8View:t,bufferConstants:s,ringBufferBase:r,controlIndices:n,oscMessage:o,sourceId:a=0,maxSpins:c=0,useWait:l=!1}){let u=o.length,f=s.MESSAGE_HEADER_SIZE+u;if(f>s.IN_BUFFER_SIZE-s.MESSAGE_HEADER_SIZE||!It(i,n.IN_WRITE_LOCK,c,l))return!1;try{let h=Atomics.load(i,n.IN_HEAD),S=Atomics.load(i,n.IN_TAIL),m=f+3&-4;if(Ge(h,S,s.IN_BUFFER_SIZE)<m)return!1;let p=Atomics.add(i,n.IN_SEQUENCE,1),y=$e({uint8View:t,dataView:e,bufferStart:r+s.IN_BUFFER_START,bufferSize:s.IN_BUFFER_SIZE,head:h,payload:o,sequence:p,messageMagic:s.MESSAGE_MAGIC,headerSize:s.MESSAGE_HEADER_SIZE,sourceId:a});return Atomics.load(i,n.IN_HEAD),Atomics.store(i,n.IN_HEAD,y),Atomics.notify(i,n.IN_HEAD,1),!0}finally{Dt(i,n.IN_WRITE_LOCK)}}function V(i,e){let t=i+e;return{IN_HEAD:(t+0)/4,IN_TAIL:(t+4)/4,IN_SEQUENCE:(t+24)/4,IN_WRITE_LOCK:(t+40)/4,IN_LOG_TAIL:(t+44)/4}}function qe(i,e){let t=i+e;return{IN_HEAD:(t+0)/4,IN_TAIL:(t+4)/4,OUT_HEAD:(t+8)/4,OUT_TAIL:(t+12)/4,DEBUG_HEAD:(t+16)/4,DEBUG_TAIL:(t+20)/4,IN_SEQUENCE:(t+24)/4,OUT_SEQUENCE:(t+28)/4,DEBUG_SEQUENCE:(t+32)/4,STATUS_FLAGS:(t+36)/4,IN_WRITE_LOCK:(t+40)/4,IN_LOG_TAIL:(t+44)/4}}function Lt(i){return i.length>=8&&i[0]===35&&i[1]===98&&i[2]===117&&i[3]===110&&i[4]===100&&i[5]===108&&i[6]===101&&i[7]===0}function pe(i){if(i.length<16)return null;let e=new DataView(i.buffer,i.byteOffset,i.byteLength);return{ntpSeconds:e.getUint32(8,!1),ntpFraction:e.getUint32(12,!1)}}function T(){return(performance.timeOrigin+performance.now())/1e3+2208988800}function Ze(i,e={}){let{getCurrentNTP:t=T,bypassLookaheadS:s=.5}=e;if(!Lt(i))return"nonBundle";let r=pe(i);if(!r)return"nonBundle";let{ntpSeconds:n,ntpFraction:o}=r;if(n===0&&o<=1)return"immediate";let a=t();if(a===null||a===0)return"immediate";let l=n+o/4294967296-a;return l<0?"late":l<s?"nearFuture":"farFuture"}function q(i){return i!=="farFuture"}var A=class i{#r;#e;#t;#h;#n;#s;#l;#a;#o;#c;#u={messagesSent:0,bytesSent:0,nonBundle:0,immediate:0,nearFuture:0,late:0,bypassed:0};constructor(e,t){if(this.#r=e,this.#n=t.preschedulerPort||null,this.#l=t.bypassLookaheadS??.5,this.#a=t.sourceId??0,this.#o=t.blocking??this.#a!==0,this.#c=t.getCurrentNTP??T,e==="postMessage")this.#e=t.port;else if(this.#t={sharedBuffer:t.sharedBuffer,ringBufferBase:t.ringBufferBase,bufferConstants:t.bufferConstants,controlIndices:t.controlIndices},this.#p(),t.sharedBuffer&&t.bufferConstants){let s=t.ringBufferBase+t.bufferConstants.METRICS_START;this.#s=new Int32Array(t.sharedBuffer,s,t.bufferConstants.METRICS_SIZE/4)}}#p(){let e=this.#t.sharedBuffer;this.#h={atomicView:new Int32Array(e),dataView:new DataView(e),uint8View:new Uint8Array(e)}}classify(e){return Ze(e,{getCurrentNTP:this.#c,bypassLookaheadS:this.#l})}#_(e,t=null){if(this.#r==="sab"&&this.#s){if(Atomics.add(this.#s,24,1),Atomics.add(this.#s,25,e),t){let r={nonBundle:38,immediate:39,nearFuture:40,late:41}[t];r!==void 0&&(Atomics.add(this.#s,r,1),Atomics.add(this.#s,22,1))}}else this.#u.messagesSent++,this.#u.bytesSent+=e,t&&t in this.#u&&(this.#u[t]++,this.#u.bypassed++)}getAndResetMetrics(){let e={...this.#u};return this.#u={messagesSent:0,bytesSent:0,nonBundle:0,immediate:0,nearFuture:0,late:0,bypassed:0},e}getMetrics(){return this.#r==="sab"&&this.#s?{messagesSent:Atomics.load(this.#s,24),bytesSent:Atomics.load(this.#s,25),nonBundle:Atomics.load(this.#s,38),immediate:Atomics.load(this.#s,39),nearFuture:Atomics.load(this.#s,40),late:Atomics.load(this.#s,41),bypassed:Atomics.load(this.#s,22)}:{...this.#u}}#d(e,t=null,s=!0){if(this.#r==="postMessage")return this.#e?(this.#e.postMessage({type:"osc",oscData:e,bypassCategory:t,sourceId:this.#a}),!0):!1;{let r=this.#o,n=We({atomicView:this.#h.atomicView,dataView:this.#h.dataView,uint8View:this.#h.uint8View,bufferConstants:this.#t.bufferConstants,ringBufferBase:this.#t.ringBufferBase,controlIndices:this.#t.controlIndices,oscMessage:e,sourceId:this.#a,maxSpins:r?10:0,useWait:r});return!n&&!r&&s&&this.#n?(this.#s&&Atomics.add(this.#s,45,1),this.#n.postMessage({type:"directDispatch",oscData:e,sourceId:this.#a}),!0):n}}#m(e){return this.#n?(this.#n.postMessage({type:"osc",oscData:e,sourceId:this.#a}),!0):(console.error("[OscChannel] No prescheduler port, sending direct"),this.#d(e))}send(e){let t=this.classify(e);if(q(t)){let s=this.#d(e,t);return s&&this.#_(e.length,t),s}else{let s=this.#m(e);return s&&this.#_(e.length,null),s}}sendDirect(e){return this.#d(e)}sendToPrescheduler(e){return this.#m(e)}set getCurrentNTP(e){this.#c=e}get mode(){return this.#r}get transferable(){let e={mode:this.#r,preschedulerPort:this.#n,bypassLookaheadS:this.#l,sourceId:this.#a,blocking:this.#o};return this.#r==="postMessage"?{...e,port:this.#e}:{...e,sharedBuffer:this.#t.sharedBuffer,ringBufferBase:this.#t.ringBufferBase,bufferConstants:this.#t.bufferConstants,controlIndices:this.#t.controlIndices}}get transferList(){let e=[];return this.#r==="postMessage"&&this.#e&&e.push(this.#e),this.#n&&e.push(this.#n),e}close(){this.#r==="postMessage"&&this.#e&&(this.#e.close(),this.#e=null),this.#n&&(this.#n.close(),this.#n=null)}static createPostMessage(e){return e instanceof MessagePort?new i("postMessage",{port:e}):new i("postMessage",e)}static createSAB(e){let t=e.controlIndices;return t||(t=V(e.ringBufferBase,e.bufferConstants.CONTROL_START)),new i("sab",{sharedBuffer:e.sharedBuffer,ringBufferBase:e.ringBufferBase,bufferConstants:e.bufferConstants,controlIndices:t,preschedulerPort:e.preschedulerPort,bypassLookaheadS:e.bypassLookaheadS,sourceId:e.sourceId,blocking:e.blocking})}static fromTransferable(e){return e.mode==="postMessage"?new i("postMessage",{port:e.port,preschedulerPort:e.preschedulerPort,bypassLookaheadS:e.bypassLookaheadS,sourceId:e.sourceId,blocking:e.blocking}):new i("sab",{sharedBuffer:e.sharedBuffer,ringBufferBase:e.ringBufferBase,bufferConstants:e.bufferConstants,controlIndices:e.controlIndices,preschedulerPort:e.preschedulerPort,bypassLookaheadS:e.bypassLookaheadS,sourceId:e.sourceId,blocking:e.blocking})}};var x=class extends M{#r;#e;#t;#h;#n;#s;#l;#a;#o;#c;#u;#p;#_;#d;#m;#S;#b=1;#g=!1;#i;#f=0;#y=0;#E=0;#A=null;constructor(e){if(super({...e,mode:"sab"}),this.#r=e.sharedBuffer,this.#e=e.ringBufferBase,this.#t=e.bufferConstants,this.#p=e.workerBaseURL,this.#i=e.preschedulerCapacity||65536,!(this.#r instanceof SharedArrayBuffer))throw new Error("SABTransport requires a SharedArrayBuffer");this.#B()}async initialize(){if(this.#g)return;let[e,t,s,r]=await Promise.all([C(this.#p+"osc_out_prescheduler_worker.js",{type:"module"}),C(this.#p+"osc_in_worker.js",{type:"module"}),C(this.#p+"debug_worker.js",{type:"module"}),C(this.#p+"osc_out_log_sab_worker.js",{type:"module"})]);this.#a=e,this.#o=t,this.#c=s,this.#u=r,this.#M(),await Promise.all([this.#w(this.#a,"OSC OUT",{maxPendingMessages:this.#i,bypassLookaheadS:this._config.bypassLookaheadS}),this.#w(this.#o,"OSC IN"),this.#w(this.#c,"DEBUG"),this.#w(this.#u,"OSC OUT LOG")]),this.#o.postMessage({type:"start"}),this.#c.postMessage({type:"start"}),this.#u.postMessage({type:"start"}),this.#g=!0}send(e,t){return!this.#g||this._disposed?!1:(this.#a.postMessage({type:"send",oscData:e,sessionId:0,runTag:"",audioTimeS:null,currentTimeS:null}),this.#f++,this.#E+=e.length,!0)}sendWithOptions(e,t={}){if(!this.#g||this._disposed)return!1;let{sessionId:s=0,runTag:r="",audioTimeS:n=null,currentTimeS:o=null}=t;return this.#a.postMessage({type:"send",oscData:e,sessionId:s,runTag:r,audioTimeS:n,currentTimeS:o}),this.#f++,this.#E+=e.length,!0}sendImmediate(e){return!this.#g||this._disposed?!1:(this.#a.postMessage({type:"sendImmediate",oscData:e}),this.#f++,this.#E+=e.length,!0)}createOscChannel(e={}){if(!this.#g)throw new Error("Transport not initialized");let t=e.sourceId??this.#b++,s=new MessageChannel;return this.#a.postMessage({type:"addOscSource"},[s.port1]),A.createSAB({sharedBuffer:this.#r,ringBufferBase:this.#e,bufferConstants:this.#t,controlIndices:this.#l,preschedulerPort:s.port2,bypassLookaheadS:this._config.bypassLookaheadS,sourceId:t,blocking:e.blocking})}cancelSessionTag(e,t){this.#g&&this.#a.postMessage({type:"cancelSessionTag",sessionId:e,runTag:t})}cancelSession(e){this.#g&&this.#a.postMessage({type:"cancelSession",sessionId:e})}cancelTag(e){this.#g&&this.#a.postMessage({type:"cancelTag",runTag:e})}cancelAll(){this.#g&&this.#a.postMessage({type:"cancelAll"})}cancelAllWithAck(){return this.#g?new Promise(e=>{let t=s=>{s.data.type==="cancelAllAck"&&(this.#a.removeEventListener("message",t),e())};this.#a.addEventListener("message",t),this.#a.postMessage({type:"cancelAll",ack:!0})}):Promise.resolve()}onReply(e){this.#_=e}onDebug(e){this.#d=e}onError(e){this.#m=e}onOscLog(e){this.#S=e}handleOscLog(e){this.#S&&this.#S(e)}getMetrics(){return{oscOutMessagesSent:this.#f,oscOutMessagesDropped:this.#y,oscOutBytesSent:this.#E}}get ready(){return this.#g&&!this._disposed}dispose(){this._disposed||(this.#a&&(this.#a.postMessage({type:"stop"}),this.#a.terminate(),this.#a=null),this.#o&&(this.#o.postMessage({type:"stop"}),this.#o.terminate(),this.#o=null),this.#c&&(this.#c.postMessage({type:"stop"}),this.#c.terminate(),this.#c=null),this.#u&&(this.#u.postMessage({type:"stop"}),this.#u.terminate(),this.#u=null),this.#g=!1,super.dispose())}#B(){this.#h=new Int32Array(this.#r),this.#n=new DataView(this.#r),this.#s=new Uint8Array(this.#r),this.#l=V(this.#e,this.#t.CONTROL_START)}#w(e,t,s={}){return new Promise((r,n)=>{let o=setTimeout(()=>{n(new Error(`${t} worker initialization timeout`))},5e3),a=c=>{c.data.type==="initialized"&&(clearTimeout(o),e.removeEventListener("message",a),r())};e.addEventListener("message",a),e.postMessage({type:"init",sharedBuffer:this.#r,ringBufferBase:this.#e,bufferConstants:this.#t,...s})})}#M(){this.#o.onmessage=e=>{let t=e.data;t.type==="messages"&&this.#_?t.messages.forEach(s=>{s.oscData&&this.#_(s.oscData,s.sequence,s.timestamp)}):t.type==="error"&&(console.error("[SABTransport] OSC IN error:",t.error),this.#m&&this.#m(t.error,"oscIn"))},this.#c.onmessage=e=>{let t=e.data;t.type==="debug"&&this.#d?t.messages.forEach(s=>{this.#d(s)}):t.type==="error"&&(console.error("[SABTransport] DEBUG error:",t.error),this.#m&&this.#m(t.error,"debug"))},this.#a.onmessage=e=>{let t=e.data;t.type==="preschedulerMetrics"?this.#A=t.metrics:t.type==="error"&&(console.error("[SABTransport] OSC OUT error:",t.error),this.#y++,this.#m&&this.#m(t.error,"oscOut"))},this.#u.onmessage=e=>{let t=e.data;t.type==="oscLog"&&this.#S?this.#S(t.entries):t.type==="error"&&(console.error("[SABTransport] OSC OUT LOG error:",t.error),this.#m&&this.#m(t.error,"oscOutLog"))}}getPreschedulerMetrics(){return this.#A}};var N=class extends M{#r;#e;#t;#h;#n;#s;#l;#a=1;#o=null;#c=!1;#u;#p;#_=null;#d=0;#m=0;#S=0;#b=0;#g=0;#i=-1;#f=0;#y=0;#E;#A;constructor(e){super({...e,mode:"postMessage"}),this.#t=e.workerBaseURL,this.#u=e.preschedulerCapacity||65536,this.#p=e.snapshotIntervalMs,this.#E=e.getAudioContextTime,this.#A=e.getNTPStartTime}async initialize(e){if(this.#c)return;if(!e)throw new Error("PostMessageTransport requires workletPort");this.#r=e,this.#r.onmessage=s=>{this.#w(s.data)};let t=new MessageChannel;this.#r.postMessage({type:"addOscPort"},[t.port1]),this.#e=await C(this.#t+"osc_out_prescheduler_worker.js",{type:"module"}),this.#e.onmessage=s=>{this.#M(s.data)},await this.#B(t.port2),this.#c=!0}setBufferConstants(e){this.#_=e}send(e,t){return!this.#c||this._disposed?!1:(this.#e.postMessage({type:"send",oscData:e,sessionId:0,runTag:"",audioTimeS:null,currentTimeS:null}),this.#d++,this.#S+=e.length,!0)}sendWithOptions(e,t={}){if(!this.#c||this._disposed)return!1;let{sessionId:s=0,runTag:r="",audioTimeS:n=null,currentTimeS:o=null}=t;return this.#e.postMessage({type:"send",oscData:e,sessionId:s,runTag:r,audioTimeS:n,currentTimeS:o}),this.#d++,this.#S+=e.length,!0}sendImmediate(e,t){return!this.#c||this._disposed?!1:(this.#r.postMessage({type:"osc",oscData:e,bypassCategory:t}),this.#d++,this.#S+=e.length,!0)}createOscChannel(e={}){if(!this.#c)throw new Error("Transport not initialized");let t=e.sourceId??this.#a++,s=new MessageChannel;this.#r.postMessage({type:"addOscPort",sourceId:t},[s.port1]);let r=new MessageChannel;return this.#e.postMessage({type:"addOscSource"},[r.port1]),A.createPostMessage({port:s.port2,preschedulerPort:r.port2,bypassLookaheadS:this._config.bypassLookaheadS,sourceId:t,blocking:e.blocking})}cancelSessionTag(e,t){this.#c&&this.#e.postMessage({type:"cancelSessionTag",sessionId:e,runTag:t})}cancelSession(e){this.#c&&this.#e.postMessage({type:"cancelSession",sessionId:e})}cancelTag(e){this.#c&&this.#e.postMessage({type:"cancelTag",runTag:e})}cancelAll(){this.#c&&this.#e.postMessage({type:"cancelAll"})}cancelAllWithAck(){return this.#c?new Promise(e=>{let t=s=>{s.data.type==="cancelAllAck"&&(this.#e.removeEventListener("message",t),e())};this.#e.addEventListener("message",t),this.#e.postMessage({type:"cancelAll",ack:!0})}):Promise.resolve()}onReply(e){this.#h=e}onDebug(e){this.#n=e}onError(e){this.#s=e}onOscLog(e){this.#l=e}handleDebugRaw(e){if(e.messages&&e.count>0&&e.buffer){let t=new TextDecoder("utf-8"),s=new Uint8Array(e.buffer);for(let r=0;r<e.count;r++){let n=e.messages[r];try{let o=s.subarray(n.offset,n.offset+n.length),a=t.decode(o);a.endsWith(`
2
- `)&&(a=a.slice(0,-1)),this.#f++,this.#y+=n.length,this.#n&&this.#n({text:a,timestamp:performance.now(),sequence:n.sequence})}catch(o){console.error("[PostMessageTransport] Failed to decode debug message:",o)}}}}getPreschedulerMetrics(){return this.#o}getMetrics(){return{oscInMessagesReceived:this.#b,oscInBytesReceived:this.#g,oscInMessagesDropped:this.#m,debugMessagesReceived:this.#f,debugBytesReceived:this.#y}}get ready(){return this.#c&&!this._disposed}dispose(){this._disposed||(this.#e&&(this.#e.postMessage({type:"stop"}),this.#e.terminate(),this.#e=null),this.#r=null,this.#c=!1,super.dispose())}#B(e){return new Promise((t,s)=>{let r=setTimeout(()=>{s(new Error("Prescheduler worker initialization timeout"))},5e3),n=o=>{o.data.type==="initialized"&&(clearTimeout(r),this.#e.removeEventListener("message",n),t())};this.#e.addEventListener("message",n),this.#e.postMessage({type:"init",mode:"postMessage",maxPendingMessages:this.#u,snapshotIntervalMs:this.#p,bypassLookaheadS:this._config.bypassLookaheadS,workletPort:e},[e])})}#w(e){switch(e.type){case"oscReplies":if(e.messages&&e.count>0&&e.buffer){let t=new Uint8Array(e.buffer);for(let s=0;s<e.count;s++){let r=e.messages[s],n=t.subarray(r.offset,r.offset+r.length);if(r.sequence!==void 0&&this.#i>=0){let o=this.#i+1&4294967295;if(r.sequence!==o){let a=r.sequence-o+4294967296&4294967295;a<1e3&&(this.#m+=a)}}r.sequence!==void 0&&(this.#i=r.sequence),this.#b++,this.#g+=r.length,this.#h&&this.#h(n,r.sequence,T())}}break;case"metrics":break;case"bufferLoaded":break;case"debugRawBatch":this.handleDebugRaw(e);break;case"oscLog":if(this.#l&&e.count>0&&e.buffer&&e.entries){let t=new Uint8Array(e.buffer),s=[];for(let r=0;r<e.count;r++){let n=e.entries[r],o=t.subarray(n.offset,n.offset+n.length);s.push({oscData:o,sourceId:n.sourceId,sequence:n.sequence,timestamp:T(),truncated:n.length<n.originalLength,originalLength:n.originalLength})}this.#l(s)}break;case"error":console.error("[PostMessageTransport] Worklet error:",e.error),this.#m++,this.#s&&this.#s(e.error,"worklet");break;case"debug":break}}#M(e){switch(e.type){case"preschedulerMetrics":this.#o=e.metrics;break;case"error":console.error("[PostMessageTransport] Prescheduler error:",e.error),this.#m++,this.#s&&this.#s(e.error,"oscOut");break}}};function Xe(i,e){if(i==="sab")return new x(e);if(i==="postMessage")return new N(e);throw new Error(`Unknown transport mode: ${i}. Use 'sab' or 'postMessage'`)}var kt={5120:"i8",5121:"u8",5122:"i16",5123:"u16",5124:"i32",5125:"u32",5126:"f32"};var Ke={u8:1,u8c:1,i8:1,u16:2,i16:2,u32:4,i32:4,i64:8,u64:8,f32:4,f64:8};var Ft={f32:Float32Array,f64:Float64Array},xt={i8:Int8Array,i16:Int16Array,i32:Int32Array},Nt={u8:Uint8Array,u8c:Uint8ClampedArray,u16:Uint16Array,u32:Uint32Array},vt={i64:BigInt64Array,u64:BigUint64Array},Ht={...Ft,...xt,...Nt},zt=i=>{let e=kt[i];return e!==void 0?e:i};function Qe(i,...e){let t=vt[i];return new(t||Ht[zt(i)])(...e)}var v=(i,e)=>(e--,i+e&~e);var je=i=>typeof i=="number";var Z=(i,e=t=>t!==void 0?": "+t:"")=>class extends Error{origMessage;constructor(t){super(i(t)+e(t)),this.origMessage=t!==void 0?String(t):""}};var Yt=Z(()=>"Assertion failed"),ye=(typeof process<"u"&&process.env!==void 0?process.env.UMBRELLA_ASSERTS:!import.meta.env||import.meta.env.MODE!=="production"||import.meta.env.UMBRELLA_ASSERTS||import.meta.env.VITE_UMBRELLA_ASSERTS)?(i,e)=>{if(typeof i=="function"&&!i()||!i)throw new Yt(typeof e=="function"?e():e)}:()=>{};var Gt=Z(()=>"illegal argument(s)"),Je=i=>{throw new Gt(i)};var et=0,tt=1,st=2,rt=3,it=4,k=5,nt=6,Ee=1,Se=2,ot=7*4,ge=0,_e=1,B=2*4,z=class{buf;start;u8;u32;state;constructor(e={}){if(this.buf=e.buf?e.buf:new ArrayBuffer(e.size||4096),this.start=e.start!=null?v(Math.max(e.start,0),4):0,this.u8=new Uint8Array(this.buf),this.u32=new Uint32Array(this.buf),this.state=new Uint32Array(this.buf,this.start,ot/4),!e.skipInitialization){let t=e.align||8;ye(t>=8,`invalid alignment: ${t}, must be a pow2 and >= 8`);let s=this.initialTop(t),r=e.end!=null?Math.min(e.end,this.buf.byteLength):this.buf.byteLength;s>=r&&Je(`insufficient address range (0x${this.start.toString(16)} - 0x${r.toString(16)})`),this.align=t,this.doCompact=e.compact!==!1,this.doSplit=e.split!==!1,this.minSplit=e.minSplit||16,this.end=r,this.top=s,this._free=0,this._used=0}}stats(){let e=s=>{let r=0,n=0;for(;s;)r++,n+=this.blockSize(s),s=this.blockNext(s);return{count:r,size:n}},t=e(this._free);return{free:t,used:e(this._used),top:this.top,available:this.end-this.top+t.size,total:this.buf.byteLength}}callocAs(e,t,s=0){let r=this.mallocAs(e,t);return r?.fill(s),r}mallocAs(e,t){let s=this.malloc(t*Ke[e]);return s?Qe(e,this.buf,s,t):void 0}calloc(e,t=0){let s=this.malloc(e);return s&&this.u8.fill(t,s,s+e),s}malloc(e){if(e<=0)return 0;let t=v(e+B,this.align),s=this.end,r=this.top,n=this._free,o=0;for(;n;){let a=this.blockSize(n),c=n+a>=r;if(c||a>=t)return this.mallocTop(n,o,a,t,c);o=n,n=this.blockNext(n)}return n=r,r=n+t,r<=s?(this.initBlock(n,t,this._used),this._used=n,this.top=r,H(n)):0}mallocTop(e,t,s,r,n){if(n&&e+r>this.end)return 0;if(t?this.unlinkBlock(t,e):this._free=this.blockNext(e),this.setBlockNext(e,this._used),this._used=e,n)this.top=e+this.setBlockSize(e,r);else if(this.doSplit){let o=s-r;o>=this.minSplit&&this.splitBlock(e,r,o)}return H(e)}realloc(e,t){if(t<=0)return 0;let s=be(e),r=0,n=this._used,o=0;for(;n;){if(n===s){[r,o]=this.reallocBlock(n,t);break}n=this.blockNext(n)}return r&&r!==s&&this.u8.copyWithin(H(r),H(s),o),H(r)}reallocBlock(e,t){let s=this.blockSize(e),r=e+s,n=r>=this.top,o=v(t+B,this.align);if(o<=s){if(this.doSplit){let a=s-o;a>=this.minSplit?this.splitBlock(e,o,a):n&&(this.top=e+o)}else n&&(this.top=e+o);return[e,r]}return n&&e+o<this.end?(this.top=e+this.setBlockSize(e,o),[e,r]):(this.free(e),[be(this.malloc(t)),r])}reallocArray(e,t){if(e.buffer!==this.buf)return;let s=this.realloc(e.byteOffset,t*e.BYTES_PER_ELEMENT);return s?new e.constructor(this.buf,s,t):void 0}free(e){let t;if(je(e))t=e;else{if(e.buffer!==this.buf)return!1;t=e.byteOffset}t=be(t);let s=this._used,r=0;for(;s;){if(s===t)return r?this.unlinkBlock(r,s):this._used=this.blockNext(s),this.insert(s),this.doCompact&&this.compact(),!0;r=s,s=this.blockNext(s)}return!1}freeAll(){this._free=0,this._used=0,this.top=this.initialTop()}release(){return delete this.u8,delete this.u32,delete this.state,delete this.buf,!0}get align(){return this.state[it]}set align(e){this.state[it]=e}get end(){return this.state[rt]}set end(e){this.state[rt]=e}get top(){return this.state[st]}set top(e){this.state[st]=e}get _free(){return this.state[et]}set _free(e){this.state[et]=e}get _used(){return this.state[tt]}set _used(e){this.state[tt]=e}get doCompact(){return!!(this.state[k]&Ee)}set doCompact(e){e?this.state[k]|=1<<Ee-1:this.state[k]&=~Ee}get doSplit(){return!!(this.state[k]&Se)}set doSplit(e){e?this.state[k]|=1<<Se-1:this.state[k]&=~Se}get minSplit(){return this.state[nt]}set minSplit(e){ye(e>B,`illegal min split threshold: ${e}, require at least ${B+1}`),this.state[nt]=e}blockSize(e){return this.u32[(e>>2)+ge]}setBlockSize(e,t){return this.u32[(e>>2)+ge]=t,t}blockNext(e){return this.u32[(e>>2)+_e]}setBlockNext(e,t){this.u32[(e>>2)+_e]=t}initBlock(e,t,s){let r=e>>>2;return this.u32[r+ge]=t,this.u32[r+_e]=s,e}unlinkBlock(e,t){this.setBlockNext(e,this.blockNext(t))}splitBlock(e,t,s){this.insert(this.initBlock(e+this.setBlockSize(e,t),s,0)),this.doCompact&&this.compact()}initialTop(e=this.align){return v(this.start+ot+B,e)-B}compact(){let e=this._free,t=0,s=0,r,n=!1;for(;e;){for(r=e,s=this.blockNext(e);s&&r+this.blockSize(r)===s;)r=s,s=this.blockNext(s);if(r!==e){let o=r-e+this.blockSize(r);this.setBlockSize(e,o);let a=this.blockNext(r),c=this.blockNext(e);for(;c&&c!==a;){let l=this.blockNext(c);this.setBlockNext(c,0),c=l}this.setBlockNext(e,a),n=!0}e+this.blockSize(e)>=this.top&&(this.top=e,t?this.unlinkBlock(t,e):this._free=this.blockNext(e)),t=e,e=this.blockNext(e)}return n}insert(e){let t=this._free,s=0;for(;t&&!(e<=t);)s=t,t=this.blockNext(t);s?this.setBlockNext(s,e):this._free=e,this.setBlockNext(e,t)}},H=i=>i>0?i+B:0,be=i=>i>0?i-B:0;function at(i){if(i.byteLength<12)return!1;let e=new Uint8Array(i,0,12),t=String.fromCharCode(e[0],e[1],e[2],e[3]),s=String.fromCharCode(e[8],e[9],e[10],e[11]);return t==="FORM"&&(s==="AIFF"||s==="AIFC")}function $t(i){let e=i[0]>>7&1,t=(i[0]&127)<<8|i[1],s=0;for(let n=2;n<10;n++)s=s*256+i[n];if(t===0)return 0;let r=s*Math.pow(2,t-16383-63);return e?-r:r}function Te(i,e){let t=12;for(;t<i.byteLength-8;){let s=String.fromCharCode(i.getUint8(t),i.getUint8(t+1),i.getUint8(t+2),i.getUint8(t+3)),r=i.getUint32(t+4,!1);if(s===e)return{offset:t+8,size:r};t+=8+r+r%2}return null}function ct(i){let e=new DataView(i),t=String.fromCharCode(e.getUint8(8),e.getUint8(9),e.getUint8(10),e.getUint8(11)),s=Te(e,"COMM");if(!s)throw new Error("AIFF file missing COMM chunk");let r=e.getUint16(s.offset,!1),n=e.getUint32(s.offset+2,!1),o=e.getUint16(s.offset+6,!1),a=new Uint8Array(i,s.offset+8,10),c=$t(a);if(t==="AIFC"&&s.size>=22){let d=String.fromCharCode(e.getUint8(s.offset+18),e.getUint8(s.offset+19),e.getUint8(s.offset+20),e.getUint8(s.offset+21));if(d!=="NONE"&&d!=="sowt")throw new Error(`AIFC compression type '${d}' is not supported. Only uncompressed AIFF/AIFC files are supported.`);if(d==="sowt")return Wt(i,r,n,o,c)}let l=Te(e,"SSND");if(!l)throw new Error("AIFF file missing SSND chunk");let u=e.getUint32(l.offset,!1),f=l.offset+8+u,h=o/8,S=n*r*h;if(f+S>i.byteLength)throw new Error("AIFF file truncated: not enough audio data");let m=44,g=new ArrayBuffer(m+S),p=new DataView(g),y=new Uint8Array(g);lt(p,{numChannels:r,sampleRate:Math.round(c),bitsPerSample:o,dataSize:S});let _=new Uint8Array(i,f,S);if(h===1)for(let d=0;d<S;d++)y[m+d]=_[d]+128;else if(h===2)for(let d=0;d<S;d+=2)y[m+d]=_[d+1],y[m+d+1]=_[d];else if(h===3)for(let d=0;d<S;d+=3)y[m+d]=_[d+2],y[m+d+1]=_[d+1],y[m+d+2]=_[d];else if(h===4)for(let d=0;d<S;d+=4)y[m+d]=_[d+3],y[m+d+1]=_[d+2],y[m+d+2]=_[d+1],y[m+d+3]=_[d];else throw new Error(`Unsupported bit depth: ${o}`);return g}function Wt(i,e,t,s,r){let n=new DataView(i),o=Te(n,"SSND");if(!o)throw new Error("AIFF file missing SSND chunk");let a=n.getUint32(o.offset,!1),c=o.offset+8+a,l=s/8,u=t*e*l;if(c+u>i.byteLength)throw new Error("AIFF file truncated: not enough audio data");let f=44,h=new ArrayBuffer(f+u),S=new DataView(h),m=new Uint8Array(h);lt(S,{numChannels:e,sampleRate:Math.round(r),bitsPerSample:s,dataSize:u});let g=new Uint8Array(i,c,u);if(l===1)for(let p=0;p<u;p++)m[f+p]=g[p]+128;else m.set(g,f);return h}function lt(i,{numChannels:e,sampleRate:t,bitsPerSample:s,dataSize:r}){let n=t*e*(s/8),o=e*(s/8);i.setUint8(0,82),i.setUint8(1,73),i.setUint8(2,70),i.setUint8(3,70),i.setUint32(4,36+r,!0),i.setUint8(8,87),i.setUint8(9,65),i.setUint8(10,86),i.setUint8(11,69),i.setUint8(12,102),i.setUint8(13,109),i.setUint8(14,116),i.setUint8(15,32),i.setUint32(16,16,!0),i.setUint16(20,1,!0),i.setUint16(22,e,!0),i.setUint32(24,t,!0),i.setUint32(28,n,!0),i.setUint16(32,o,!0),i.setUint16(34,s,!0),i.setUint8(36,100),i.setUint8(37,97),i.setUint8(38,116),i.setUint8(39,97),i.setUint32(40,r,!0)}var ut=8,X=class{#r;#e;#t;#h;#n;#s;#l;#a;#o;#c;#u;#p;constructor(e){let{mode:t="sab",audioContext:s,sharedBuffer:r,bufferPoolConfig:n,sampleBaseURL:o,maxBuffers:a=1024,assetLoader:c=null,workletPort:l=null}=e;if(this.#r=t,!s)throw new Error("BufferManager requires audioContext");if(t==="sab"){if(!r||!(r instanceof SharedArrayBuffer))throw new Error("BufferManager requires sharedBuffer (SharedArrayBuffer) in SAB mode");if(!n||typeof n!="object")throw new Error("BufferManager requires bufferPoolConfig (object with start, size, align)");if(!Number.isFinite(n.start)||n.start<0)throw new Error("bufferPoolConfig.start must be a non-negative number");if(!Number.isFinite(n.size)||n.size<=0)throw new Error("bufferPoolConfig.size must be a positive number")}if(t==="postMessage"&&(!n||typeof n!="object"))throw new Error("BufferManager requires bufferPoolConfig in postMessage mode");if(!Number.isInteger(a)||a<=0)throw new Error("maxBuffers must be a positive integer");if(this.#h=s,this.#n=r,this.#e=o,this.#t=c,this.#p=l,t==="sab")this.#s=new z({buf:r,start:n.start,size:n.size,align:ut}),this.#l=n.size,this.#a=n.start;else{let h=new ArrayBuffer(n.start+n.size);this.#s=new z({buf:h,start:n.start,size:n.size,align:ut}),this.#l=n.size,this.#a=n.start}this.#o=new Map,this.#c=new Map,this.#u=new Map,this.GUARD_BEFORE=3,this.GUARD_AFTER=1,this.MAX_BUFFERS=a;let u=(n.size/(1024*1024)).toFixed(0),f=(n.start/(1024*1024)).toFixed(0)}async#_(e){let t=e.byteOffset===0&&e.byteLength===e.buffer.byteLength?e.buffer:e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength),s=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(s)).map(r=>r.toString(16).padStart(2,"0")).join("")}async#d({source:e,startFrame:t=0,numFrames:s=0,channels:r=null}){let n,o;if(typeof e=="string"){let p=this.#g(e),y=e.split("/").pop();n=await this.#t.fetch(p,{type:"sample",name:y}),o={type:"file",path:e,startFrame:t,numFrames:s,channels:r}}else n=e instanceof ArrayBuffer?e:e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength),o=null;let a=await this.#b(n),c=Math.max(0,Math.floor(t||0)),l=a.length-c,u=s&&s>0?Math.min(Math.floor(s),l):l;if(u<=0)throw new Error("No audio frames available");let f=this.#y(r,a.numberOfChannels),h=f.length,S=u*h+(this.GUARD_BEFORE+this.GUARD_AFTER)*h,m=new Float32Array(S),g=this.GUARD_BEFORE*h;for(let p=0;p<u;p++)for(let y=0;y<h;y++){let _=a.getChannelData(f[y]);m[g+p*h+y]=_[c+p]}return{interleaved:m,numFrames:u,numChannels:h,sampleRate:a.sampleRate,sourceInfo:o}}async#m(e){let t=this.#E(e.length);return await this.#A(t,e),t}async#S(e,t,s,r){let n,o=await this.#f(e,t,async()=>{let[c,l]=await Promise.all([this.#_(s.interleaved),this.#m(s.interleaved)]);return n=c,{ptr:l,sizeBytes:s.interleaved.length*4,numFrames:s.numFrames,numChannels:s.numChannels,sampleRate:s.sampleRate,source:r||null}}),a=this.#o.get(e);return a&&(a.hash=n),{...o,hash:n}}async#b(e){return at(e)&&(e=ct(e)),this.#h.decodeAudioData(e)}setWorkletPort(e){if(this.#r==="postMessage"){if(!e)throw new Error("BufferManager.setWorkletPort() requires a valid port");this.#p=e}}#g(e){if(typeof e!="string"||e.length===0)throw new Error("Invalid audio path: must be a non-empty string");if(e.includes(".."))throw new Error(`Invalid audio path: path cannot contain '..' (got: ${e})`);if(e.includes("%2e")||e.includes("%2E"))throw new Error(`Invalid audio path: path cannot contain URL-encoded characters (got: ${e})`);if(e.includes("\\"))throw new Error(`Invalid audio path: use forward slashes only (got: ${e})`);if(e.includes("://")||e.startsWith("/")||e.startsWith("./"))return e;if(!this.#e)throw new Error(`sampleBaseURL not configured. Please set it in SuperSonic constructor options.
1
+ var M=class i{constructor(e){if(new.target===i)throw new Error("Transport is abstract - use SABTransport or PostMessageTransport");this._config=e,this._disposed=!1}get mode(){return this._config.mode}send(e,t){throw new Error("Abstract method - implement in subclass")}onReply(e){throw new Error("Abstract method - implement in subclass")}onDebug(e){throw new Error("Abstract method - implement in subclass")}onError(e){throw new Error("Abstract method - implement in subclass")}getMetrics(){throw new Error("Abstract method - implement in subclass")}async initialize(){throw new Error("Abstract method - implement in subclass")}createOscChannel(){throw new Error("Abstract method - implement in subclass")}dispose(){this._disposed=!0}get ready(){throw new Error("Abstract method - implement in subclass")}};var ce=new Map;function Ne(i){try{return new URL(i,window.location.href).origin!==window.location.origin}catch{return!1}}async function ve(i){if(ce.has(i))return ce.get(i);let e=await fetch(i);if(!e.ok)throw new Error(`Failed to fetch ${i}: ${e.status} ${e.statusText}`);let t=await e.text(),s=new Blob([t],{type:"application/javascript"}),r=URL.createObjectURL(s);return ce.set(i,r),r}async function C(i,e={}){let t=i;return Ne(i)&&(t=await ve(i)),new Worker(t,e)}async function He(i,e){let t=e;Ne(e)&&(t=await ve(e)),await i.addModule(t)}function ze(i,e,t){return(t-1-i+e)%t}function Ye({uint8View:i,dataView:e,bufferStart:t,bufferSize:s,head:r,payload:n,sequence:o,messageMagic:a,headerSize:c,sourceId:l=0,headerScratch:u=null,headerScratchView:f=null}){let h=n.length,m=c+h+3&-4,g=s-r;if(m>g){let p=u||new Uint8Array(c),y=f||new DataView(p.buffer);y.setUint32(0,a,!0),y.setUint32(4,m,!0),y.setUint32(8,o,!0),y.setUint32(12,l,!0);let _=t+r,d=t;if(g>=c){i.set(p,_);let w=g-c;w>0&&i.set(n.subarray(0,w),_+c),i.set(n.subarray(w),d)}else{i.set(p.subarray(0,g),_),i.set(p.subarray(g),d);let w=c-g;i.set(n,d+w)}}else{let p=t+r;e.setUint32(p,a,!0),e.setUint32(p+4,m,!0),e.setUint32(p+8,o,!0),e.setUint32(p+12,l,!0),i.set(n,p+c)}return(r+m)%s}function Bt(i,e,t=0,s=!1){for(let r=0;r<=t;r++)if(Atomics.compareExchange(i,e,0,1)===0)return!0;if(s){for(let n=0;n<100;n++)if(Atomics.wait(i,e,1,100),Atomics.compareExchange(i,e,0,1)===0)return!0;return console.error("[RingBuffer] Lock acquisition timeout after 10s - possible deadlock"),!1}return!1}function wt(i,e){Atomics.store(i,e,0),Atomics.notify(i,e,1)}function Ge({atomicView:i,dataView:e,uint8View:t,bufferConstants:s,ringBufferBase:r,controlIndices:n,oscMessage:o,sourceId:a=0,maxSpins:c=0,useWait:l=!1}){let u=o.length,f=s.MESSAGE_HEADER_SIZE+u;if(f>s.IN_BUFFER_SIZE-s.MESSAGE_HEADER_SIZE||!Bt(i,n.IN_WRITE_LOCK,c,l))return!1;try{let h=Atomics.load(i,n.IN_HEAD),S=Atomics.load(i,n.IN_TAIL),m=f+3&-4;if(ze(h,S,s.IN_BUFFER_SIZE)<m)return!1;let p=Atomics.add(i,n.IN_SEQUENCE,1),y=Ye({uint8View:t,dataView:e,bufferStart:r+s.IN_BUFFER_START,bufferSize:s.IN_BUFFER_SIZE,head:h,payload:o,sequence:p,messageMagic:s.MESSAGE_MAGIC,headerSize:s.MESSAGE_HEADER_SIZE,sourceId:a});return Atomics.load(i,n.IN_HEAD),Atomics.store(i,n.IN_HEAD,y),Atomics.notify(i,n.IN_HEAD,1),!0}finally{wt(i,n.IN_WRITE_LOCK)}}function Y(i,e){let t=i+e;return{IN_HEAD:(t+0)/4,IN_TAIL:(t+4)/4,IN_SEQUENCE:(t+24)/4,IN_WRITE_LOCK:(t+40)/4,IN_LOG_TAIL:(t+44)/4}}function We(i,e){let t=i+e;return{IN_HEAD:(t+0)/4,IN_TAIL:(t+4)/4,OUT_HEAD:(t+8)/4,OUT_TAIL:(t+12)/4,DEBUG_HEAD:(t+16)/4,DEBUG_TAIL:(t+20)/4,IN_SEQUENCE:(t+24)/4,OUT_SEQUENCE:(t+28)/4,DEBUG_SEQUENCE:(t+32)/4,STATUS_FLAGS:(t+36)/4,IN_WRITE_LOCK:(t+40)/4,IN_LOG_TAIL:(t+44)/4}}function Mt(i){return i.length>=8&&i[0]===35&&i[1]===98&&i[2]===117&&i[3]===110&&i[4]===100&&i[5]===108&&i[6]===101&&i[7]===0}function le(i){if(i.length<16)return null;let e=new DataView(i.buffer,i.byteOffset,i.byteLength);return{ntpSeconds:e.getUint32(8,!1),ntpFraction:e.getUint32(12,!1)}}function T(){return(performance.timeOrigin+performance.now())/1e3+2208988800}function Ve(i,e={}){let{getCurrentNTP:t=T,bypassLookaheadS:s=.5}=e;if(!Mt(i))return"nonBundle";let r=le(i);if(!r)return"nonBundle";let{ntpSeconds:n,ntpFraction:o}=r;if(n===0&&o<=1)return"immediate";let a=t();if(a===null||a===0)return"immediate";let l=n+o/4294967296-a;return l<0?"late":l<s?"nearFuture":"farFuture"}function G(i){return i!=="farFuture"}var A=class i{#i;#e;#t;#m;#n;#s;#u;#a;#o;#c;#f;#p;#b;#h;#y;#d;#_;#g;#r;#l={messagesSent:0,bytesSent:0,nonBundle:0,immediate:0,nearFuture:0,late:0,bypassed:0};constructor(e,t){if(this.#i=e,this.#n=t.preschedulerPort||null,this.#u=t.bypassLookaheadS??.5,this.#a=t.sourceId??0,this.#o=t.blocking??this.#a!==0,this.#c=t.getCurrentNTP??T,this.#y=1e3,e==="postMessage")this.#e=t.port;else{if(this.#t={sharedBuffer:t.sharedBuffer,ringBufferBase:t.ringBufferBase,bufferConstants:t.bufferConstants,controlIndices:t.controlIndices},this.#E(),t.sharedBuffer&&t.bufferConstants){let s=t.ringBufferBase+t.bufferConstants.METRICS_START;this.#s=new Int32Array(t.sharedBuffer,s,t.bufferConstants.METRICS_SIZE/4)}if(t.sharedBuffer&&t.bufferConstants?.NODE_ID_COUNTER_START!==void 0){let s=t.ringBufferBase+t.bufferConstants.NODE_ID_COUNTER_START;this.#f=new Int32Array(t.sharedBuffer,s,1),this.#B()}}t.nodeIdSource&&(this.#d=t.nodeIdSource,this.#B()),t.nodeIdRange&&(this.#p=t.nodeIdRange.from,this.#b=t.nodeIdRange.to,this.#h=t.nodeIdRange.from),t.nodeIdPort&&(this.#_=t.nodeIdPort,this.#_.onmessage=s=>{s.data.type==="nodeIdRange"&&(this.#g={from:s.data.from,to:s.data.to})},this.#M())}#E(){let e=this.#t.sharedBuffer;this.#m={atomicView:new Int32Array(e),dataView:new DataView(e),uint8View:new Uint8Array(e)}}classify(e){return Ve(e,{getCurrentNTP:this.#c,bypassLookaheadS:this.#u})}#S(e,t=null){if(this.#i==="sab"&&this.#s){if(Atomics.add(this.#s,24,1),Atomics.add(this.#s,25,e),t){let r={nonBundle:38,immediate:39,nearFuture:40,late:41}[t];r!==void 0&&(Atomics.add(this.#s,r,1),Atomics.add(this.#s,22,1))}}else this.#l.messagesSent++,this.#l.bytesSent+=e,t&&t in this.#l&&(this.#l[t]++,this.#l.bypassed++)}getAndResetMetrics(){let e={...this.#l};return this.#l={messagesSent:0,bytesSent:0,nonBundle:0,immediate:0,nearFuture:0,late:0,bypassed:0},e}getMetrics(){return this.#i==="sab"&&this.#s?{messagesSent:Atomics.load(this.#s,24),bytesSent:Atomics.load(this.#s,25),nonBundle:Atomics.load(this.#s,38),immediate:Atomics.load(this.#s,39),nearFuture:Atomics.load(this.#s,40),late:Atomics.load(this.#s,41),bypassed:Atomics.load(this.#s,22)}:{...this.#l}}#A(e,t=null,s=!0){if(this.#i==="postMessage")return this.#e?(this.#e.postMessage({type:"osc",oscData:e,bypassCategory:t,sourceId:this.#a}),!0):!1;{let r=this.#o,n=Ge({atomicView:this.#m.atomicView,dataView:this.#m.dataView,uint8View:this.#m.uint8View,bufferConstants:this.#t.bufferConstants,ringBufferBase:this.#t.ringBufferBase,controlIndices:this.#t.controlIndices,oscMessage:e,sourceId:this.#a,maxSpins:r?10:0,useWait:r});return!n&&!r&&s&&this.#n?(this.#s&&Atomics.add(this.#s,45,1),this.#n.postMessage({type:"directDispatch",oscData:e,sourceId:this.#a}),!0):n}}#w(e){return this.#n?(this.#n.postMessage({type:"osc",oscData:e,sourceId:this.#a}),!0):(console.error("[OscChannel] No prescheduler port, sending direct"),this.#A(e))}send(e){let t=this.classify(e);if(G(t)){let s=this.#A(e,t);return s&&this.#S(e.length,t),s}else{let s=this.#w(e);return s&&this.#S(e.length,null),s}}sendDirect(e){return this.#A(e)}sendToPrescheduler(e){return this.#w(e)}nextNodeId(){if(this.#f)return Atomics.add(this.#f,0,1);this.#h>=this.#b&&this.#B();let e=this.#h++;return this.#_&&!this.#g&&this.#b-this.#h<=1e3&&this.#M(),e}#B(){if(this.#d){let e=this.#d(this.#y);this.#p=e.from,this.#b=e.to,this.#h=e.from}else this.#g?(this.#p=this.#g.from,this.#b=this.#g.to,this.#h=this.#g.from,this.#g=null,this.#M()):this.#_&&(console.warn("[OscChannel] nextNodeId() range exhausted before async refill arrived. IDs may not be unique. Yield to the event loop between large batches of nextNodeId() calls."),this.#M())}#M(){this.#_&&this.#_.postMessage({type:"requestNodeIdRange"})}set getCurrentNTP(e){this.#c=e}get mode(){return this.#i}get transferable(){let e={mode:this.#i,preschedulerPort:this.#n,bypassLookaheadS:this.#u,sourceId:this.#a,blocking:this.#o};if(this.#i==="postMessage"){let t=this.#y*10,s,r;if(this.#d){let n=this.#d(t);s={from:n.from,to:n.to};let o=new MessageChannel,a=this.#d,c=this.#y;o.port1.onmessage=l=>{if(l.data.type==="requestNodeIdRange"){let u=a(c);o.port1.postMessage({type:"nodeIdRange",from:u.from,to:u.to})}},r=o.port2,this.#r=r}return{...e,port:this.#e,nodeIdRange:s,nodeIdPort:r}}else return{...e,sharedBuffer:this.#t.sharedBuffer,ringBufferBase:this.#t.ringBufferBase,bufferConstants:this.#t.bufferConstants,controlIndices:this.#t.controlIndices}}get transferList(){let e=[];return this.#i==="postMessage"&&this.#e&&e.push(this.#e),this.#n&&e.push(this.#n),this.#r&&(e.push(this.#r),this.#r=null),e}close(){this.#i==="postMessage"&&this.#e&&(this.#e.close(),this.#e=null),this.#n&&(this.#n.close(),this.#n=null)}static createPostMessage(e){return e instanceof MessagePort?new i("postMessage",{port:e}):new i("postMessage",e)}static createSAB(e){let t=e.controlIndices;return t||(t=Y(e.ringBufferBase,e.bufferConstants.CONTROL_START)),new i("sab",{sharedBuffer:e.sharedBuffer,ringBufferBase:e.ringBufferBase,bufferConstants:e.bufferConstants,controlIndices:t,preschedulerPort:e.preschedulerPort,bypassLookaheadS:e.bypassLookaheadS,sourceId:e.sourceId,blocking:e.blocking})}static fromTransferable(e){return e.mode==="postMessage"?new i("postMessage",{port:e.port,preschedulerPort:e.preschedulerPort,bypassLookaheadS:e.bypassLookaheadS,sourceId:e.sourceId,blocking:e.blocking,nodeIdRange:e.nodeIdRange,nodeIdPort:e.nodeIdPort}):new i("sab",{sharedBuffer:e.sharedBuffer,ringBufferBase:e.ringBufferBase,bufferConstants:e.bufferConstants,controlIndices:e.controlIndices,preschedulerPort:e.preschedulerPort,bypassLookaheadS:e.bypassLookaheadS,sourceId:e.sourceId,blocking:e.blocking})}};var x=class extends M{#i;#e;#t;#m;#n;#s;#u;#a;#o;#c;#f;#p;#b;#h;#y;#d;#_=1;#g=!1;#r;#l=0;#E=0;#S=0;#A=null;constructor(e){if(super({...e,mode:"sab"}),this.#i=e.sharedBuffer,this.#e=e.ringBufferBase,this.#t=e.bufferConstants,this.#p=e.workerBaseURL,this.#r=e.preschedulerCapacity||65536,!(this.#i instanceof SharedArrayBuffer))throw new Error("SABTransport requires a SharedArrayBuffer");this.#w()}async initialize(){if(this.#g)return;let[e,t,s,r]=await Promise.all([C(this.#p+"osc_out_prescheduler_worker.js",{type:"module"}),C(this.#p+"osc_in_worker.js",{type:"module"}),C(this.#p+"debug_worker.js",{type:"module"}),C(this.#p+"osc_out_log_sab_worker.js",{type:"module"})]);this.#a=e,this.#o=t,this.#c=s,this.#f=r,this.#M(),await Promise.all([this.#B(this.#a,"OSC OUT",{maxPendingMessages:this.#r,bypassLookaheadS:this._config.bypassLookaheadS}),this.#B(this.#o,"OSC IN"),this.#B(this.#c,"DEBUG"),this.#B(this.#f,"OSC OUT LOG")]),this.#o.postMessage({type:"start"}),this.#c.postMessage({type:"start"}),this.#f.postMessage({type:"start"}),this.#g=!0}send(e,t){return!this.#g||this._disposed?!1:(this.#a.postMessage({type:"send",oscData:e,sessionId:0,runTag:"",audioTimeS:null,currentTimeS:null}),this.#l++,this.#S+=e.length,!0)}sendWithOptions(e,t={}){if(!this.#g||this._disposed)return!1;let{sessionId:s=0,runTag:r="",audioTimeS:n=null,currentTimeS:o=null}=t;return this.#a.postMessage({type:"send",oscData:e,sessionId:s,runTag:r,audioTimeS:n,currentTimeS:o}),this.#l++,this.#S+=e.length,!0}sendImmediate(e){return!this.#g||this._disposed?!1:(this.#a.postMessage({type:"sendImmediate",oscData:e}),this.#l++,this.#S+=e.length,!0)}createOscChannel(e={}){if(!this.#g)throw new Error("Transport not initialized");let t=e.sourceId??this.#_++,s=new MessageChannel;return this.#a.postMessage({type:"addOscSource"},[s.port1]),A.createSAB({sharedBuffer:this.#i,ringBufferBase:this.#e,bufferConstants:this.#t,controlIndices:this.#u,preschedulerPort:s.port2,bypassLookaheadS:this._config.bypassLookaheadS,sourceId:t,blocking:e.blocking})}cancelSessionTag(e,t){this.#g&&this.#a.postMessage({type:"cancelSessionTag",sessionId:e,runTag:t})}cancelSession(e){this.#g&&this.#a.postMessage({type:"cancelSession",sessionId:e})}cancelTag(e){this.#g&&this.#a.postMessage({type:"cancelTag",runTag:e})}cancelAll(){this.#g&&this.#a.postMessage({type:"cancelAll"})}cancelAllWithAck(){return this.#g?new Promise(e=>{let t=s=>{s.data.type==="cancelAllAck"&&(this.#a.removeEventListener("message",t),e())};this.#a.addEventListener("message",t),this.#a.postMessage({type:"cancelAll",ack:!0})}):Promise.resolve()}onReply(e){this.#b=e}onDebug(e){this.#h=e}onError(e){this.#y=e}onOscLog(e){this.#d=e}handleOscLog(e){this.#d&&this.#d(e)}getMetrics(){return{oscOutMessagesSent:this.#l,oscOutMessagesDropped:this.#E,oscOutBytesSent:this.#S}}get ready(){return this.#g&&!this._disposed}dispose(){this._disposed||(this.#a&&(this.#a.postMessage({type:"stop"}),this.#a.terminate(),this.#a=null),this.#o&&(this.#o.postMessage({type:"stop"}),this.#o.terminate(),this.#o=null),this.#c&&(this.#c.postMessage({type:"stop"}),this.#c.terminate(),this.#c=null),this.#f&&(this.#f.postMessage({type:"stop"}),this.#f.terminate(),this.#f=null),this.#g=!1,super.dispose())}#w(){this.#m=new Int32Array(this.#i),this.#n=new DataView(this.#i),this.#s=new Uint8Array(this.#i),this.#u=Y(this.#e,this.#t.CONTROL_START)}#B(e,t,s={}){return new Promise((r,n)=>{let o=setTimeout(()=>{n(new Error(`${t} worker initialization timeout`))},5e3),a=c=>{c.data.type==="initialized"&&(clearTimeout(o),e.removeEventListener("message",a),r())};e.addEventListener("message",a),e.postMessage({type:"init",sharedBuffer:this.#i,ringBufferBase:this.#e,bufferConstants:this.#t,...s})})}#M(){this.#o.onmessage=e=>{let t=e.data;t.type==="messages"&&this.#b?t.messages.forEach(s=>{s.oscData&&this.#b(s.oscData,s.sequence,s.timestamp)}):t.type==="error"&&(console.error("[SABTransport] OSC IN error:",t.error),this.#y&&this.#y(t.error,"oscIn"))},this.#c.onmessage=e=>{let t=e.data;t.type==="debug"&&this.#h?t.messages.forEach(s=>{this.#h(s)}):t.type==="error"&&(console.error("[SABTransport] DEBUG error:",t.error),this.#y&&this.#y(t.error,"debug"))},this.#a.onmessage=e=>{let t=e.data;t.type==="preschedulerMetrics"?this.#A=t.metrics:t.type==="error"&&(console.error("[SABTransport] OSC OUT error:",t.error),this.#E++,this.#y&&this.#y(t.error,"oscOut"))},this.#f.onmessage=e=>{let t=e.data;t.type==="oscLog"&&this.#d?this.#d(t.entries):t.type==="error"&&(console.error("[SABTransport] OSC OUT LOG error:",t.error),this.#y&&this.#y(t.error,"oscOutLog"))}}getPreschedulerMetrics(){return this.#A}};var N=class extends M{#i;#e;#t;#m;#n;#s;#u;#a=1;#o=null;#c=!1;#f;#p;#b=null;#h=0;#y=0;#d=0;#_=0;#g=0;#r=-1;#l=0;#E=0;#S;#A;constructor(e){super({...e,mode:"postMessage"}),this.#t=e.workerBaseURL,this.#f=e.preschedulerCapacity||65536,this.#p=e.snapshotIntervalMs,this.#S=e.getAudioContextTime,this.#A=e.getNTPStartTime}async initialize(e){if(this.#c)return;if(!e)throw new Error("PostMessageTransport requires workletPort");this.#i=e,this.#i.onmessage=s=>{this.#B(s.data)};let t=new MessageChannel;this.#i.postMessage({type:"addOscPort"},[t.port1]),this.#e=await C(this.#t+"osc_out_prescheduler_worker.js",{type:"module"}),this.#e.onmessage=s=>{this.#M(s.data)},await this.#w(t.port2),this.#c=!0}setBufferConstants(e){this.#b=e}send(e,t){return!this.#c||this._disposed?!1:(this.#e.postMessage({type:"send",oscData:e,sessionId:0,runTag:"",audioTimeS:null,currentTimeS:null}),this.#h++,this.#d+=e.length,!0)}sendWithOptions(e,t={}){if(!this.#c||this._disposed)return!1;let{sessionId:s=0,runTag:r="",audioTimeS:n=null,currentTimeS:o=null}=t;return this.#e.postMessage({type:"send",oscData:e,sessionId:s,runTag:r,audioTimeS:n,currentTimeS:o}),this.#h++,this.#d+=e.length,!0}sendImmediate(e,t){return!this.#c||this._disposed?!1:(this.#i.postMessage({type:"osc",oscData:e,bypassCategory:t}),this.#h++,this.#d+=e.length,!0)}createOscChannel(e={}){if(!this.#c)throw new Error("Transport not initialized");let t=e.sourceId??this.#a++,s=new MessageChannel;this.#i.postMessage({type:"addOscPort",sourceId:t},[s.port1]);let r=new MessageChannel;return this.#e.postMessage({type:"addOscSource"},[r.port1]),A.createPostMessage({port:s.port2,preschedulerPort:r.port2,bypassLookaheadS:this._config.bypassLookaheadS,sourceId:t,blocking:e.blocking,nodeIdSource:this._config.nodeIdSource})}cancelSessionTag(e,t){this.#c&&this.#e.postMessage({type:"cancelSessionTag",sessionId:e,runTag:t})}cancelSession(e){this.#c&&this.#e.postMessage({type:"cancelSession",sessionId:e})}cancelTag(e){this.#c&&this.#e.postMessage({type:"cancelTag",runTag:e})}cancelAll(){this.#c&&this.#e.postMessage({type:"cancelAll"})}cancelAllWithAck(){return this.#c?new Promise(e=>{let t=s=>{s.data.type==="cancelAllAck"&&(this.#e.removeEventListener("message",t),e())};this.#e.addEventListener("message",t),this.#e.postMessage({type:"cancelAll",ack:!0})}):Promise.resolve()}onReply(e){this.#m=e}onDebug(e){this.#n=e}onError(e){this.#s=e}onOscLog(e){this.#u=e}handleDebugRaw(e){if(e.messages&&e.count>0&&e.buffer){let t=new TextDecoder("utf-8"),s=new Uint8Array(e.buffer);for(let r=0;r<e.count;r++){let n=e.messages[r];try{let o=s.subarray(n.offset,n.offset+n.length),a=t.decode(o);a.endsWith(`
2
+ `)&&(a=a.slice(0,-1)),this.#l++,this.#E+=n.length,this.#n&&this.#n({text:a,timestamp:performance.now(),sequence:n.sequence})}catch(o){console.error("[PostMessageTransport] Failed to decode debug message:",o)}}}}getPreschedulerMetrics(){return this.#o}getMetrics(){return{oscInMessagesReceived:this.#_,oscInBytesReceived:this.#g,oscInMessagesDropped:this.#y,debugMessagesReceived:this.#l,debugBytesReceived:this.#E}}get ready(){return this.#c&&!this._disposed}dispose(){this._disposed||(this.#e&&(this.#e.postMessage({type:"stop"}),this.#e.terminate(),this.#e=null),this.#i=null,this.#c=!1,super.dispose())}#w(e){return new Promise((t,s)=>{let r=setTimeout(()=>{s(new Error("Prescheduler worker initialization timeout"))},5e3),n=o=>{o.data.type==="initialized"&&(clearTimeout(r),this.#e.removeEventListener("message",n),t())};this.#e.addEventListener("message",n),this.#e.postMessage({type:"init",mode:"postMessage",maxPendingMessages:this.#f,snapshotIntervalMs:this.#p,bypassLookaheadS:this._config.bypassLookaheadS,workletPort:e},[e])})}#B(e){switch(e.type){case"oscReplies":if(e.messages&&e.count>0&&e.buffer){let t=new Uint8Array(e.buffer);for(let s=0;s<e.count;s++){let r=e.messages[s],n=t.subarray(r.offset,r.offset+r.length);if(r.sequence!==void 0&&this.#r>=0){let o=this.#r+1&4294967295;if(r.sequence!==o){let a=r.sequence-o+4294967296&4294967295;a<1e3&&(this.#y+=a)}}r.sequence!==void 0&&(this.#r=r.sequence),this.#_++,this.#g+=r.length,this.#m&&this.#m(n,r.sequence,T())}}break;case"metrics":break;case"bufferLoaded":break;case"debugRawBatch":this.handleDebugRaw(e);break;case"oscLog":if(this.#u&&e.count>0&&e.buffer&&e.entries){let t=new Uint8Array(e.buffer),s=[];for(let r=0;r<e.count;r++){let n=e.entries[r],o=t.subarray(n.offset,n.offset+n.length);s.push({oscData:o,sourceId:n.sourceId,sequence:n.sequence,timestamp:T(),truncated:n.length<n.originalLength,originalLength:n.originalLength})}this.#u(s)}break;case"error":console.error("[PostMessageTransport] Worklet error:",e.error),this.#y++,this.#s&&this.#s(e.error,"worklet");break;case"debug":break}}#M(e){switch(e.type){case"preschedulerMetrics":this.#o=e.metrics;break;case"error":console.error("[PostMessageTransport] Prescheduler error:",e.error),this.#y++,this.#s&&this.#s(e.error,"oscOut");break}}};function qe(i,e){if(i==="sab")return new x(e);if(i==="postMessage")return new N(e);throw new Error(`Unknown transport mode: ${i}. Use 'sab' or 'postMessage'`)}var Rt={5120:"i8",5121:"u8",5122:"i16",5123:"u16",5124:"i32",5125:"u32",5126:"f32"};var Ze={u8:1,u8c:1,i8:1,u16:2,i16:2,u32:4,i32:4,i64:8,u64:8,f32:4,f64:8};var Ot={f32:Float32Array,f64:Float64Array},Ut={i8:Int8Array,i16:Int16Array,i32:Int32Array},It={u8:Uint8Array,u8c:Uint8ClampedArray,u16:Uint16Array,u32:Uint32Array},Dt={i64:BigInt64Array,u64:BigUint64Array},Lt={...Ot,...Ut,...It},Pt=i=>{let e=Rt[i];return e!==void 0?e:i};function Xe(i,...e){let t=Dt[i];return new(t||Lt[Pt(i)])(...e)}var v=(i,e)=>(e--,i+e&~e);var Ke=i=>typeof i=="number";var $=(i,e=t=>t!==void 0?": "+t:"")=>class extends Error{origMessage;constructor(t){super(i(t)+e(t)),this.origMessage=t!==void 0?String(t):""}};var kt=$(()=>"Assertion failed"),fe=(typeof process<"u"&&process.env!==void 0?process.env.UMBRELLA_ASSERTS:!import.meta.env||import.meta.env.MODE!=="production"||import.meta.env.UMBRELLA_ASSERTS||import.meta.env.VITE_UMBRELLA_ASSERTS)?(i,e)=>{if(typeof i=="function"&&!i()||!i)throw new kt(typeof e=="function"?e():e)}:()=>{};var Ft=$(()=>"illegal argument(s)"),Qe=i=>{throw new Ft(i)};var je=0,Je=1,et=2,tt=3,st=4,k=5,rt=6,he=1,de=2,it=7*4,pe=0,me=1,B=2*4,z=class{buf;start;u8;u32;state;constructor(e={}){if(this.buf=e.buf?e.buf:new ArrayBuffer(e.size||4096),this.start=e.start!=null?v(Math.max(e.start,0),4):0,this.u8=new Uint8Array(this.buf),this.u32=new Uint32Array(this.buf),this.state=new Uint32Array(this.buf,this.start,it/4),!e.skipInitialization){let t=e.align||8;fe(t>=8,`invalid alignment: ${t}, must be a pow2 and >= 8`);let s=this.initialTop(t),r=e.end!=null?Math.min(e.end,this.buf.byteLength):this.buf.byteLength;s>=r&&Qe(`insufficient address range (0x${this.start.toString(16)} - 0x${r.toString(16)})`),this.align=t,this.doCompact=e.compact!==!1,this.doSplit=e.split!==!1,this.minSplit=e.minSplit||16,this.end=r,this.top=s,this._free=0,this._used=0}}stats(){let e=s=>{let r=0,n=0;for(;s;)r++,n+=this.blockSize(s),s=this.blockNext(s);return{count:r,size:n}},t=e(this._free);return{free:t,used:e(this._used),top:this.top,available:this.end-this.top+t.size,total:this.buf.byteLength}}callocAs(e,t,s=0){let r=this.mallocAs(e,t);return r?.fill(s),r}mallocAs(e,t){let s=this.malloc(t*Ze[e]);return s?Xe(e,this.buf,s,t):void 0}calloc(e,t=0){let s=this.malloc(e);return s&&this.u8.fill(t,s,s+e),s}malloc(e){if(e<=0)return 0;let t=v(e+B,this.align),s=this.end,r=this.top,n=this._free,o=0;for(;n;){let a=this.blockSize(n),c=n+a>=r;if(c||a>=t)return this.mallocTop(n,o,a,t,c);o=n,n=this.blockNext(n)}return n=r,r=n+t,r<=s?(this.initBlock(n,t,this._used),this._used=n,this.top=r,H(n)):0}mallocTop(e,t,s,r,n){if(n&&e+r>this.end)return 0;if(t?this.unlinkBlock(t,e):this._free=this.blockNext(e),this.setBlockNext(e,this._used),this._used=e,n)this.top=e+this.setBlockSize(e,r);else if(this.doSplit){let o=s-r;o>=this.minSplit&&this.splitBlock(e,r,o)}return H(e)}realloc(e,t){if(t<=0)return 0;let s=ye(e),r=0,n=this._used,o=0;for(;n;){if(n===s){[r,o]=this.reallocBlock(n,t);break}n=this.blockNext(n)}return r&&r!==s&&this.u8.copyWithin(H(r),H(s),o),H(r)}reallocBlock(e,t){let s=this.blockSize(e),r=e+s,n=r>=this.top,o=v(t+B,this.align);if(o<=s){if(this.doSplit){let a=s-o;a>=this.minSplit?this.splitBlock(e,o,a):n&&(this.top=e+o)}else n&&(this.top=e+o);return[e,r]}return n&&e+o<this.end?(this.top=e+this.setBlockSize(e,o),[e,r]):(this.free(e),[ye(this.malloc(t)),r])}reallocArray(e,t){if(e.buffer!==this.buf)return;let s=this.realloc(e.byteOffset,t*e.BYTES_PER_ELEMENT);return s?new e.constructor(this.buf,s,t):void 0}free(e){let t;if(Ke(e))t=e;else{if(e.buffer!==this.buf)return!1;t=e.byteOffset}t=ye(t);let s=this._used,r=0;for(;s;){if(s===t)return r?this.unlinkBlock(r,s):this._used=this.blockNext(s),this.insert(s),this.doCompact&&this.compact(),!0;r=s,s=this.blockNext(s)}return!1}freeAll(){this._free=0,this._used=0,this.top=this.initialTop()}release(){return delete this.u8,delete this.u32,delete this.state,delete this.buf,!0}get align(){return this.state[st]}set align(e){this.state[st]=e}get end(){return this.state[tt]}set end(e){this.state[tt]=e}get top(){return this.state[et]}set top(e){this.state[et]=e}get _free(){return this.state[je]}set _free(e){this.state[je]=e}get _used(){return this.state[Je]}set _used(e){this.state[Je]=e}get doCompact(){return!!(this.state[k]&he)}set doCompact(e){e?this.state[k]|=1<<he-1:this.state[k]&=~he}get doSplit(){return!!(this.state[k]&de)}set doSplit(e){e?this.state[k]|=1<<de-1:this.state[k]&=~de}get minSplit(){return this.state[rt]}set minSplit(e){fe(e>B,`illegal min split threshold: ${e}, require at least ${B+1}`),this.state[rt]=e}blockSize(e){return this.u32[(e>>2)+pe]}setBlockSize(e,t){return this.u32[(e>>2)+pe]=t,t}blockNext(e){return this.u32[(e>>2)+me]}setBlockNext(e,t){this.u32[(e>>2)+me]=t}initBlock(e,t,s){let r=e>>>2;return this.u32[r+pe]=t,this.u32[r+me]=s,e}unlinkBlock(e,t){this.setBlockNext(e,this.blockNext(t))}splitBlock(e,t,s){this.insert(this.initBlock(e+this.setBlockSize(e,t),s,0)),this.doCompact&&this.compact()}initialTop(e=this.align){return v(this.start+it+B,e)-B}compact(){let e=this._free,t=0,s=0,r,n=!1;for(;e;){for(r=e,s=this.blockNext(e);s&&r+this.blockSize(r)===s;)r=s,s=this.blockNext(s);if(r!==e){let o=r-e+this.blockSize(r);this.setBlockSize(e,o);let a=this.blockNext(r),c=this.blockNext(e);for(;c&&c!==a;){let l=this.blockNext(c);this.setBlockNext(c,0),c=l}this.setBlockNext(e,a),n=!0}e+this.blockSize(e)>=this.top&&(this.top=e,t?this.unlinkBlock(t,e):this._free=this.blockNext(e)),t=e,e=this.blockNext(e)}return n}insert(e){let t=this._free,s=0;for(;t&&!(e<=t);)s=t,t=this.blockNext(t);s?this.setBlockNext(s,e):this._free=e,this.setBlockNext(e,t)}},H=i=>i>0?i+B:0,ye=i=>i>0?i-B:0;function nt(i){if(i.byteLength<12)return!1;let e=new Uint8Array(i,0,12),t=String.fromCharCode(e[0],e[1],e[2],e[3]),s=String.fromCharCode(e[8],e[9],e[10],e[11]);return t==="FORM"&&(s==="AIFF"||s==="AIFC")}function xt(i){let e=i[0]>>7&1,t=(i[0]&127)<<8|i[1],s=0;for(let n=2;n<10;n++)s=s*256+i[n];if(t===0)return 0;let r=s*Math.pow(2,t-16383-63);return e?-r:r}function Ee(i,e){let t=12;for(;t<i.byteLength-8;){let s=String.fromCharCode(i.getUint8(t),i.getUint8(t+1),i.getUint8(t+2),i.getUint8(t+3)),r=i.getUint32(t+4,!1);if(s===e)return{offset:t+8,size:r};t+=8+r+r%2}return null}function ot(i){let e=new DataView(i),t=String.fromCharCode(e.getUint8(8),e.getUint8(9),e.getUint8(10),e.getUint8(11)),s=Ee(e,"COMM");if(!s)throw new Error("AIFF file missing COMM chunk");let r=e.getUint16(s.offset,!1),n=e.getUint32(s.offset+2,!1),o=e.getUint16(s.offset+6,!1),a=new Uint8Array(i,s.offset+8,10),c=xt(a);if(t==="AIFC"&&s.size>=22){let d=String.fromCharCode(e.getUint8(s.offset+18),e.getUint8(s.offset+19),e.getUint8(s.offset+20),e.getUint8(s.offset+21));if(d!=="NONE"&&d!=="sowt")throw new Error(`AIFC compression type '${d}' is not supported. Only uncompressed AIFF/AIFC files are supported.`);if(d==="sowt")return Nt(i,r,n,o,c)}let l=Ee(e,"SSND");if(!l)throw new Error("AIFF file missing SSND chunk");let u=e.getUint32(l.offset,!1),f=l.offset+8+u,h=o/8,S=n*r*h;if(f+S>i.byteLength)throw new Error("AIFF file truncated: not enough audio data");let m=44,g=new ArrayBuffer(m+S),p=new DataView(g),y=new Uint8Array(g);at(p,{numChannels:r,sampleRate:Math.round(c),bitsPerSample:o,dataSize:S});let _=new Uint8Array(i,f,S);if(h===1)for(let d=0;d<S;d++)y[m+d]=_[d]+128;else if(h===2)for(let d=0;d<S;d+=2)y[m+d]=_[d+1],y[m+d+1]=_[d];else if(h===3)for(let d=0;d<S;d+=3)y[m+d]=_[d+2],y[m+d+1]=_[d+1],y[m+d+2]=_[d];else if(h===4)for(let d=0;d<S;d+=4)y[m+d]=_[d+3],y[m+d+1]=_[d+2],y[m+d+2]=_[d+1],y[m+d+3]=_[d];else throw new Error(`Unsupported bit depth: ${o}`);return g}function Nt(i,e,t,s,r){let n=new DataView(i),o=Ee(n,"SSND");if(!o)throw new Error("AIFF file missing SSND chunk");let a=n.getUint32(o.offset,!1),c=o.offset+8+a,l=s/8,u=t*e*l;if(c+u>i.byteLength)throw new Error("AIFF file truncated: not enough audio data");let f=44,h=new ArrayBuffer(f+u),S=new DataView(h),m=new Uint8Array(h);at(S,{numChannels:e,sampleRate:Math.round(r),bitsPerSample:s,dataSize:u});let g=new Uint8Array(i,c,u);if(l===1)for(let p=0;p<u;p++)m[f+p]=g[p]+128;else m.set(g,f);return h}function at(i,{numChannels:e,sampleRate:t,bitsPerSample:s,dataSize:r}){let n=t*e*(s/8),o=e*(s/8);i.setUint8(0,82),i.setUint8(1,73),i.setUint8(2,70),i.setUint8(3,70),i.setUint32(4,36+r,!0),i.setUint8(8,87),i.setUint8(9,65),i.setUint8(10,86),i.setUint8(11,69),i.setUint8(12,102),i.setUint8(13,109),i.setUint8(14,116),i.setUint8(15,32),i.setUint32(16,16,!0),i.setUint16(20,1,!0),i.setUint16(22,e,!0),i.setUint32(24,t,!0),i.setUint32(28,n,!0),i.setUint16(32,o,!0),i.setUint16(34,s,!0),i.setUint8(36,100),i.setUint8(37,97),i.setUint8(38,116),i.setUint8(39,97),i.setUint32(40,r,!0)}var ct=8,W=class{#i;#e;#t;#m;#n;#s;#u;#a;#o;#c;#f;#p;constructor(e){let{mode:t="sab",audioContext:s,sharedBuffer:r,bufferPoolConfig:n,sampleBaseURL:o,maxBuffers:a=1024,assetLoader:c=null,workletPort:l=null}=e;if(this.#i=t,!s)throw new Error("BufferManager requires audioContext");if(t==="sab"){if(!r||!(r instanceof SharedArrayBuffer))throw new Error("BufferManager requires sharedBuffer (SharedArrayBuffer) in SAB mode");if(!n||typeof n!="object")throw new Error("BufferManager requires bufferPoolConfig (object with start, size, align)");if(!Number.isFinite(n.start)||n.start<0)throw new Error("bufferPoolConfig.start must be a non-negative number");if(!Number.isFinite(n.size)||n.size<=0)throw new Error("bufferPoolConfig.size must be a positive number")}if(t==="postMessage"&&(!n||typeof n!="object"))throw new Error("BufferManager requires bufferPoolConfig in postMessage mode");if(!Number.isInteger(a)||a<=0)throw new Error("maxBuffers must be a positive integer");if(this.#m=s,this.#n=r,this.#e=o,this.#t=c,this.#p=l,t==="sab")this.#s=new z({buf:r,start:n.start,size:n.size,align:ct}),this.#u=n.size,this.#a=n.start;else{let h=new ArrayBuffer(n.start+n.size);this.#s=new z({buf:h,start:n.start,size:n.size,align:ct}),this.#u=n.size,this.#a=n.start}this.#o=new Map,this.#c=new Map,this.#f=new Map,this.GUARD_BEFORE=3,this.GUARD_AFTER=1,this.MAX_BUFFERS=a;let u=(n.size/(1024*1024)).toFixed(0),f=(n.start/(1024*1024)).toFixed(0)}async#b(e){let t=e.byteOffset===0&&e.byteLength===e.buffer.byteLength?e.buffer:e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength),s=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(s)).map(r=>r.toString(16).padStart(2,"0")).join("")}async#h({source:e,startFrame:t=0,numFrames:s=0,channels:r=null}){let n,o;if(typeof e=="string"){let p=this.#g(e),y=e.split("/").pop();n=await this.#t.fetch(p,{type:"sample",name:y}),o={type:"file",path:e,startFrame:t,numFrames:s,channels:r}}else n=e instanceof ArrayBuffer?e:e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength),o=null;let a=await this.#_(n),c=Math.max(0,Math.floor(t||0)),l=a.length-c,u=s&&s>0?Math.min(Math.floor(s),l):l;if(u<=0)throw new Error("No audio frames available");let f=this.#E(r,a.numberOfChannels),h=f.length,S=u*h+(this.GUARD_BEFORE+this.GUARD_AFTER)*h,m=new Float32Array(S),g=this.GUARD_BEFORE*h;for(let p=0;p<u;p++)for(let y=0;y<h;y++){let _=a.getChannelData(f[y]);m[g+p*h+y]=_[c+p]}return{interleaved:m,numFrames:u,numChannels:h,sampleRate:a.sampleRate,sourceInfo:o}}async#y(e){let t=this.#S(e.length);return await this.#A(t,e),t}async#d(e,t,s,r){let n,o=await this.#l(e,t,async()=>{let[c,l]=await Promise.all([this.#b(s.interleaved),this.#y(s.interleaved)]);return n=c,{ptr:l,sizeBytes:s.interleaved.length*4,numFrames:s.numFrames,numChannels:s.numChannels,sampleRate:s.sampleRate,source:r||null}}),a=this.#o.get(e);return a&&(a.hash=n),{...o,hash:n}}async#_(e){return nt(e)&&(e=ot(e)),this.#m.decodeAudioData(e)}setWorkletPort(e){if(this.#i==="postMessage"){if(!e)throw new Error("BufferManager.setWorkletPort() requires a valid port");this.#p=e}}#g(e){if(typeof e!="string"||e.length===0)throw new Error("Invalid audio path: must be a non-empty string");if(e.includes(".."))throw new Error(`Invalid audio path: path cannot contain '..' (got: ${e})`);if(e.includes("%2e")||e.includes("%2E"))throw new Error(`Invalid audio path: path cannot contain URL-encoded characters (got: ${e})`);if(e.includes("\\"))throw new Error(`Invalid audio path: use forward slashes only (got: ${e})`);if(e.includes("://")||e.startsWith("/")||e.startsWith("./"))return e;if(!this.#e)throw new Error(`sampleBaseURL not configured. Please set it in SuperSonic constructor options.
3
3
  Example: new SuperSonic({ sampleBaseURL: "./dist/samples/" })
4
4
  Or use CDN: new SuperSonic({ sampleBaseURL: "https://unpkg.com/supersonic-scsynth-samples@latest/samples/" })
5
- Or install: npm install supersonic-scsynth-samples`);return this.#e+e}#i(e){if(!Number.isInteger(e)||e<0||e>=this.MAX_BUFFERS)throw new Error(`Invalid buffer number ${e} (must be 0-${this.MAX_BUFFERS-1})`)}async#f(e,t,s){let r=null,n=null,o=!1,a=await this.#M(e),c=!1;try{await this.#O(e);let{ptr:l,sizeBytes:u,numFrames:f,numChannels:h,sampleRate:S,source:m,...g}=await s();r=l;let{uuid:p,allocationComplete:y}=this.#w(e,t);n=p,this.#R(e,r,u,p,y,{numFrames:f,numChannels:h,sampleRate:S,source:m}),o=!0;let _=this.#U(e,p,y);return a(),c=!0,{ptr:r,uuid:p,allocationComplete:_,numFrames:f,numChannels:h,sampleRate:S,...g}}catch(l){throw o&&n?this.#C(e,n,!1):r&&this.#s.free(r),l}finally{c||a()}}async prepareFromBlob(e){let{bufnum:t,blob:s,startFrame:r=0,numFrames:n=0,channels:o=null}=e;if(this.#i(t),!s||!(s instanceof ArrayBuffer||ArrayBuffer.isView(s)))throw new Error("/b_allocFile requires audio data as ArrayBuffer or typed array");let a=await this.#d({source:s,startFrame:r,numFrames:n,channels:o});return this.#S(t,3e4,a,null)}async prepareFromFile(e){let{bufnum:t,path:s,startFrame:r=0,numFrames:n=0,channels:o=null}=e;this.#i(t);let a=await this.#d({source:s,startFrame:r,numFrames:n,channels:o});return this.#S(t,6e4,a,a.sourceInfo)}async prepareEmpty(e){let{bufnum:t,numFrames:s,numChannels:r=1,sampleRate:n=null}=e;if(this.#i(t),!Number.isFinite(s)||s<=0)throw new Error(`/b_alloc requires a positive number of frames (got ${s})`);if(!Number.isFinite(r)||r<=0)throw new Error(`/b_alloc requires a positive channel count (got ${r})`);let o=Math.floor(s),a=Math.floor(r),c=o*a+(this.GUARD_BEFORE+this.GUARD_AFTER)*a,u={interleaved:new Float32Array(c),numFrames:o,numChannels:a,sampleRate:n||this.#h.sampleRate};return this.#S(t,5e3,u,null)}#y(e,t){return!e||e.length===0?Array.from({length:t},(s,r)=>r):(e.forEach(s=>{if(!Number.isInteger(s)||s<0||s>=t)throw new Error(`Channel ${s} is out of range (file has ${t} channels)`)}),e)}#E(e){let t=e*4,s=this.#s.malloc(t);if(s===0){let r=this.#s.stats(),n=((r.available||0)/(1024*1024)).toFixed(2),o=((r.total||0)/(1024*1024)).toFixed(2),a=(t/(1024*1024)).toFixed(2);throw new Error(`Buffer pool allocation failed: requested ${a}MB, available ${n}MB of ${o}MB total`)}return s}async#A(e,t){if(this.#r==="sab")new Float32Array(this.#n,e,t.length).set(t);else{let s=crypto.randomUUID(),r=new Promise((o,a)=>{let c=setTimeout(()=>{a(new Error("Buffer copy to WASM memory timed out"))},1e4),l=u=>{let f=u.data;f.type==="bufferCopied"&&f.copyId===s&&(this.#p.removeEventListener("message",l),clearTimeout(c),f.success?o():a(new Error(f.error||"Buffer copy failed")))};this.#p.addEventListener("message",l)}),n=t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength);this.#p.postMessage({type:"copyBufferData",copyId:s,ptr:e,data:n},[n]),await r}}#B(e,t,s){return new Promise((r,n)=>{let o=setTimeout(()=>{this.#c.delete(e),n(new Error(`Buffer ${t} allocation timeout (${s}ms)`))},s);this.#c.set(e,{resolve:r,reject:n,timeout:o})})}#w(e,t){let s=crypto.randomUUID(),r=this.#B(s,e,t);return{uuid:s,allocationComplete:r}}async#M(e){let t=this.#u.get(e)||Promise.resolve(),s,r=new Promise(n=>{s=n});return this.#u.set(e,t.then(()=>r)),await t,()=>{s&&(s(),s=null),this.#u.get(e)===r&&this.#u.delete(e)}}#R(e,t,s,r,n,o={}){let a=this.#o.get(e),c={ptr:t,size:s,numFrames:o.numFrames||0,numChannels:o.numChannels||1,sampleRate:o.sampleRate||48e3,pendingToken:r,pendingPromise:n,previousAllocation:a?{ptr:a.ptr,size:a.size}:null,source:o.source||null};return this.#o.set(e,c),c}async#O(e){let t=this.#o.get(e);if(t&&t.pendingToken&&t.pendingPromise)try{await t.pendingPromise}catch{}}#U(e,t,s){return!s||typeof s.then!="function"?(this.#C(e,t,!0),Promise.resolve()):s.then(r=>(this.#C(e,t,!0),r)).catch(r=>{throw this.#C(e,t,!1),r})}#C(e,t,s){let r=this.#o.get(e);if(!r||r.pendingToken!==t)return;let n=r.previousAllocation;if(s){r.pendingToken=null,r.pendingPromise=null,r.previousAllocation=null,n?.ptr&&this.#s.free(n.ptr);return}r.ptr&&this.#s.free(r.ptr),r.pendingPromise=null,n?.ptr?this.#o.set(e,{ptr:n.ptr,size:n.size,pendingToken:null,previousAllocation:null}):this.#o.delete(e)}handleBufferFreed(e){let t=e[0],s=e[1],r=this.#o.get(t);if(!r){typeof s=="number"&&s!==0&&this.#s.free(s);return}if(typeof s=="number"&&s===r.ptr){this.#s.free(r.ptr),this.#o.delete(t);return}if(typeof s=="number"&&r.previousAllocation&&r.previousAllocation.ptr===s){this.#s.free(s),r.previousAllocation=null;return}this.#s.free(r.ptr),this.#o.delete(t)}handleBufferAllocated(e){let t=e[0],s=e[1],r=this.#c.get(t);r&&(clearTimeout(r.timeout),r.resolve({bufnum:s}),this.#c.delete(t))}allocate(e){let t=e*4,s=this.#s.malloc(t);if(s===0){let r=this.#s.stats(),n=((r.available||0)/(1024*1024)).toFixed(2),o=((r.total||0)/(1024*1024)).toFixed(2),a=(t/(1024*1024)).toFixed(2);console.error(`[BufferManager] Allocation failed: requested ${a}MB, available ${n}MB of ${o}MB total`)}return s}free(e){return this.#s.free(e)}getView(e,t){return new Float32Array(this.#n,e,t)}getStats(){return this.#s?this.#s.stats():{total:0,available:0,used:0,allocations:0}}async sampleInfo({source:e,startFrame:t=0,numFrames:s=0,channels:r=null}){let n=await this.#d({source:e,startFrame:t,numFrames:s,channels:r});return{hash:await this.#_(n.interleaved),source:n.sourceInfo?.path||null,numFrames:n.numFrames,numChannels:n.numChannels,sampleRate:n.sampleRate,duration:n.sampleRate>0?n.numFrames/n.sampleRate:0}}getAllocatedBuffers(){let e=[];for(let[t,s]of this.#o.entries())!s||!s.ptr||e.push({bufnum:t,ptr:s.ptr,numFrames:s.numFrames,numChannels:s.numChannels,sampleRate:s.sampleRate,source:s.source||null,hash:s.hash||null});return e}updateAudioContext(e){if(!e)throw new Error("BufferManager.updateAudioContext requires audioContext");this.#h=e}getDiagnostics(){let e=this.#s.stats(),t=0,s=0;for(let r of this.#o.values())r&&(t+=r.size||0,r.pendingToken&&s++);return{active:this.#o.size,pending:s,bytesActive:t,pool:{total:this.#l,available:e.available||0,freeBytes:e.free?.size||0,freeBlocks:e.free?.count||0,usedBytes:e.used?.size||0,usedBlocks:e.used?.count||0}}}destroy(){for(let[e,t]of this.#c.entries())clearTimeout(t.timeout),t.reject(new Error("BufferManager destroyed"));this.#c.clear();for(let[e,t]of this.#o.entries())t.ptr&&this.#s.free(t.ptr);this.#o.clear(),this.#u.clear()}};var K=class{#r;#e;#t;constructor(e={}){let{onLoadingEvent:t=null,maxRetries:s=3,baseDelay:r=1e3}=e;this.#r=t,this.#e=s,this.#t=r}async fetch(e,{type:t,name:s}){let r=this.#h(e),n=this.#n(e),o=await r;this.#r?.("loading:start",{type:t,name:s,...o!=null&&{size:o}});let c=await(await n).arrayBuffer();return this.#r?.("loading:complete",{type:t,name:s,size:c.byteLength}),c}async#h(e){try{let t=await fetch(e,{method:"HEAD"});if(t.ok){let s=t.headers.get("Content-Length");return s?parseInt(s,10):null}return null}catch{return null}}async#n(e){let t;for(let s=0;s<=this.#e;s++)try{let r=await fetch(e);if(r.status>=400&&r.status<500)throw new Error(`Failed to fetch ${e}: ${r.status} ${r.statusText}`);if(!r.ok)throw new Error(`Server error fetching ${e}: ${r.status} ${r.statusText}`);return r}catch(r){if(t=r,r.message.includes("Failed to fetch")&&r.message.includes("4"))throw r;if(s<this.#e){let n=this.#t*Math.pow(2,s);await this.#s(n)}}throw t}#s(e){return new Promise(t=>setTimeout(t,e))}};var Q=class{#r;#e;constructor({bufferManager:e,getDefaultSampleRate:t}){if(!e)throw new Error("OSCRewriter requires bufferManager");if(typeof t!="function")throw new Error("OSCRewriter requires getDefaultSampleRate callback");this.#r=e,this.#e=t}async rewritePacket(e){if(Array.isArray(e)){let{message:t,changed:s}=await this.#t(e);return{packet:t,changed:s}}if(this.#o(e)){let t=await Promise.all(e.packets.map(n=>this.rewritePacket(n)));if(!t.some(n=>n.changed))return{packet:e,changed:!1};let r=t.map(n=>n.packet);return{packet:{timeTag:e.timeTag,packets:r},changed:!0}}return{packet:e,changed:!1}}async#t(e){let t=e[0],s=e.slice(1);switch(t){case"/b_alloc":return{message:await this.#h(s),changed:!0};case"/b_allocRead":return{message:await this.#n(s),changed:!0};case"/b_allocReadChannel":return{message:await this.#s(s),changed:!0};case"/b_allocFile":return{message:await this.#l(s),changed:!0};default:return{message:e,changed:!1}}}async#h(e){let t=this.#p(e,0,"/b_alloc requires a buffer number"),s=this.#p(e,1,"/b_alloc requires a frame count"),r=2,n=1,o=this.#e();this.#S(this.#c(e,r))&&(n=Math.max(1,this.#_(e,r,1)),r++),this.#c(e,r)?.type==="b"&&r++,this.#S(this.#c(e,r))&&(o=this.#u(this.#c(e,r)));let a=await this.#r.prepareEmpty({bufnum:t,numFrames:s,numChannels:n,sampleRate:o});return this.#b(a.allocationComplete,`/b_alloc ${t}`),this.#a(t,a)}async#n(e){let t=this.#p(e,0,"/b_allocRead requires a buffer number"),s=this.#d(e,1,"/b_allocRead requires a file path"),r=this.#_(e,2,0),n=this.#_(e,3,0),o=await this.#r.prepareFromFile({bufnum:t,path:s,startFrame:r,numFrames:n});return this.#b(o.allocationComplete,`/b_allocRead ${t}`),this.#a(t,o)}async#s(e){let t=this.#p(e,0,"/b_allocReadChannel requires a buffer number"),s=this.#d(e,1,"/b_allocReadChannel requires a file path"),r=this.#_(e,2,0),n=this.#_(e,3,0),o=[];for(let c=4;c<(e?.length||0)&&this.#S(e[c]);c++)o.push(Math.floor(this.#u(e[c])));let a=await this.#r.prepareFromFile({bufnum:t,path:s,startFrame:r,numFrames:n,channels:o.length>0?o:null});return this.#b(a.allocationComplete,`/b_allocReadChannel ${t}`),this.#a(t,a)}async#l(e){let t=this.#p(e,0,"/b_allocFile requires a buffer number"),s=this.#m(e,1,"/b_allocFile requires audio file data as blob"),r=await this.#r.prepareFromBlob({bufnum:t,blob:s});return this.#b(r.allocationComplete,`/b_allocFile ${t}`),this.#a(t,r)}#a(e,t){return["/b_allocPtr",Math.floor(e),Math.floor(t.ptr),Math.floor(t.numFrames),Math.floor(t.numChannels),t.sampleRate,String(t.uuid)]}#o(e){return e&&e.timeTag!==void 0&&Array.isArray(e.packets)}#c(e,t){if(Array.isArray(e))return e[t]}#u(e){if(e!=null)return typeof e=="object"&&Object.prototype.hasOwnProperty.call(e,"value")?e.value:e}#p(e,t,s){let r=this.#u(this.#c(e,t));if(!Number.isFinite(r))throw new Error(s);return Math.floor(r)}#_(e,t,s=0){let r=this.#u(this.#c(e,t));return Number.isFinite(r)?Math.floor(r):s}#d(e,t,s){let r=this.#u(this.#c(e,t));if(typeof r!="string")throw new Error(s);return r}#m(e,t,s){let r=this.#u(this.#c(e,t));if(!(r instanceof Uint8Array||r instanceof ArrayBuffer))throw new Error(s);return r}#S(e){if(!e)return!1;let t=this.#u(e);return Number.isFinite(t)}#b(e,t){!e||typeof e.catch!="function"||e.catch(s=>{console.error(`[OSCRewriter] ${t} allocation failed:`,s)})}};function F(i){if(!i)return null;if(typeof i=="string")return(i.split("/").filter(Boolean).pop()||i).replace(/\.scsyndef$/i,"");let e=i instanceof ArrayBuffer?new Uint8Array(i):i;if(!(e instanceof Uint8Array)||e.length<11||e[0]!==83||e[1]!==67||e[2]!==103||e[3]!==102)return null;let t=e[10];if(t===0||11+t>e.length)return null;try{return new TextDecoder().decode(e.slice(11,11+t))}catch{return null}}var j=class{#r=new Map;on(e,t){if(typeof t!="function")throw new Error("Callback must be a function");return this.#r.has(e)||this.#r.set(e,new Set),this.#r.get(e).add(t),()=>this.off(e,t)}off(e,t){let s=this.#r.get(e);return s&&s.delete(t),this}once(e,t){let s=(...r)=>{this.off(e,s),t(...r)};return this.on(e,s)}removeAllListeners(e){return e===void 0?this.#r.clear():this.#r.delete(e),this}hasListeners(e){let t=this.#r.get(e);return t?t.size>0:!1}emit(e,...t){let s=this.#r.get(e);if(s)for(let r of s)try{r(...t)}catch(n){console.error(`[EventEmitter] Error in ${e} listener:`,n)}}async emitAsync(e,...t){let s=this.#r.get(e);if(s)for(let r of s)try{await r(...t)}catch(n){console.error(`[EventEmitter] Error in ${e} listener:`,n)}}clearAllListeners(){this.#r.clear()}};var J=class{#r;#e;#t;#h;#n;#s;#l;#a=null;#o=new Uint32Array(64);#c=new DataView(this.#o.buffer);constructor(e={}){this.#h=e.mode||"sab",this.#r=e.sharedBuffer||null,this.#e=e.ringBufferBase||0,this.#t=e.bufferConstants||null}initSharedViews(e,t,s){if(this.#r=e,this.#e=t,this.#t=s,this.#h==="sab"&&e&&s){this.#n=new Int32Array(e),this.#l=qe(t,s.CONTROL_START);let r=t+s.METRICS_START;this.#s=new Uint32Array(e,r,s.METRICS_SIZE/4)}}updateSnapshot(e){this.#a=e}getSnapshotBuffer(){return this.#a}getMetricsView(){return this.#s}addMetric(e,t=1){if(!this.#s)return;let r={oscOutMessagesSent:24,oscOutBytesSent:25,preschedulerBypassed:22,bypassNonBundle:38,bypassImmediate:39,bypassNearFuture:40,bypassLate:41}[e];r!==void 0&&Atomics.add(this.#s,r,t)}parseMetricsBuffer(e){return{scsynthProcessCount:e[0],scsynthMessagesProcessed:e[1],scsynthMessagesDropped:e[2],scsynthSchedulerDepth:e[3],scsynthSchedulerPeakDepth:e[4],scsynthSchedulerDropped:e[5],scsynthSequenceGaps:e[6],scsynthSchedulerLates:e[8],scsynthSchedulerMaxLateMs:e[42],scsynthSchedulerLastLateMs:e[43],scsynthSchedulerLastLateTick:e[44],preschedulerPending:e[9],preschedulerPendingPeak:e[10],preschedulerDispatched:e[12],preschedulerRetriesSucceeded:e[16],preschedulerRetriesFailed:e[17],preschedulerBundlesScheduled:e[11],preschedulerEventsCancelled:e[13],preschedulerTotalDispatches:e[21],preschedulerMessagesRetried:e[20],preschedulerRetryQueueSize:e[18],preschedulerRetryQueuePeak:e[19],preschedulerBypassed:e[22],oscInMessagesReceived:e[26],oscInMessagesDropped:e[28],oscInBytesReceived:e[27],debugMessagesReceived:e[30],debugBytesReceived:e[31],oscOutMessagesSent:e[24],oscOutBytesSent:e[25],preschedulerMinHeadroomMs:e[14],preschedulerLates:e[15],preschedulerMaxLateMs:e[23],scsynthWasmErrors:e[7],oscInCorrupted:e[29],ringBufferDirectWriteFails:e[45],inBufferUsedBytes:e[32],outBufferUsedBytes:e[33],debugBufferUsedBytes:e[34],inBufferPeakBytes:e[35],outBufferPeakBytes:e[36],debugBufferPeakBytes:e[37],bypassNonBundle:e[38],bypassImmediate:e[39],bypassNearFuture:e[40],bypassLate:e[41]}}getSABMetrics(){return this.#s?this.parseMetricsBuffer(this.#s):null}getBufferUsage(){if(!this.#n||!this.#t||!this.#l)return null;let e=this.#t,t=this.#l,s=this.#n,r=Atomics.load(s,t.IN_HEAD),n=Atomics.load(s,t.IN_TAIL),o=Atomics.load(s,t.OUT_HEAD),a=Atomics.load(s,t.OUT_TAIL),c=Atomics.load(s,t.DEBUG_HEAD),l=Atomics.load(s,t.DEBUG_TAIL),u=(r-n+e.IN_BUFFER_SIZE)%e.IN_BUFFER_SIZE,f=(o-a+e.OUT_BUFFER_SIZE)%e.OUT_BUFFER_SIZE,h=(c-l+e.DEBUG_BUFFER_SIZE)%e.DEBUG_BUFFER_SIZE;return{inBufferUsed:{bytes:u,percentage:u/e.IN_BUFFER_SIZE*100,capacity:e.IN_BUFFER_SIZE},outBufferUsed:{bytes:f,percentage:f/e.OUT_BUFFER_SIZE*100,capacity:e.OUT_BUFFER_SIZE},debugBufferUsed:{bytes:h,percentage:h/e.DEBUG_BUFFER_SIZE*100,capacity:e.DEBUG_BUFFER_SIZE}}}overlayPreschedulerMetrics(e){if(!this.#a||!e)return;let t=new Uint32Array(this.#a,0,46),s=9,r=13;t.set(e.subarray(s,s+r),s),t[23]=e[23]}gatherMetrics(e={}){let t;if(this.#h==="postMessage")if(e.preschedulerMetrics&&this.overlayPreschedulerMetrics(e.preschedulerMetrics),this.#a){let s=new Uint32Array(this.#a,0,46);t=this.parseMetricsBuffer(s)}else t={};else t=this.getSABMetrics()||{};if(t.inBufferUsedBytes!==void 0&&this.#t){let s=this.#t;t.inBufferUsed={bytes:t.inBufferUsedBytes,percentage:t.inBufferUsedBytes/s.IN_BUFFER_SIZE*100,peakBytes:t.inBufferPeakBytes,peakPercentage:t.inBufferPeakBytes/s.IN_BUFFER_SIZE*100,capacity:s.IN_BUFFER_SIZE},t.outBufferUsed={bytes:t.outBufferUsedBytes,percentage:t.outBufferUsedBytes/s.OUT_BUFFER_SIZE*100,peakBytes:t.outBufferPeakBytes,peakPercentage:t.outBufferPeakBytes/s.OUT_BUFFER_SIZE*100,capacity:s.OUT_BUFFER_SIZE},t.debugBufferUsed={bytes:t.debugBufferUsedBytes,percentage:t.debugBufferUsedBytes/s.DEBUG_BUFFER_SIZE*100,peakBytes:t.debugBufferPeakBytes,peakPercentage:t.debugBufferPeakBytes/s.DEBUG_BUFFER_SIZE*100,capacity:s.DEBUG_BUFFER_SIZE},delete t.inBufferUsedBytes,delete t.outBufferUsedBytes,delete t.debugBufferUsedBytes,delete t.inBufferPeakBytes,delete t.outBufferPeakBytes,delete t.debugBufferPeakBytes}return t.mode=this.#h,this.#t?.scheduler_slot_count!==void 0&&(t.scsynthSchedulerCapacity=this.#t.scheduler_slot_count),e.driftOffsetMs!==void 0&&(t.driftOffsetMs=e.driftOffsetMs),e.ntpStartTime!==void 0&&(t.ntpStartTime=e.ntpStartTime),e.clockOffsetMs!==void 0&&(t.clockOffsetMs=e.clockOffsetMs),e.audioContextState&&(t.audioContextState=e.audioContextState),e.bufferPoolStats&&(t.bufferPoolUsedBytes=e.bufferPoolStats.used.size,t.bufferPoolAvailableBytes=e.bufferPoolStats.available,t.bufferPoolAllocations=e.bufferPoolStats.used.count),e.loadedSynthDefsCount!==void 0&&(t.loadedSynthDefs=e.loadedSynthDefsCount),e.preschedulerCapacity!==void 0&&(t.preschedulerCapacity=e.preschedulerCapacity),this.#h==="postMessage"&&e.transportMetrics&&Object.assign(t,e.transportMetrics),t}updateMergedArray(e={}){let t=this.#o;if(this.#h==="postMessage"){if(e.preschedulerMetrics&&this.overlayPreschedulerMetrics(e.preschedulerMetrics),this.#a){let a=new Uint32Array(this.#a,0,46);t.set(a)}e.transportMetrics&&(e.transportMetrics.oscOutMessagesSent!==void 0&&(t[24]=e.transportMetrics.oscOutMessagesSent),e.transportMetrics.oscOutBytesSent!==void 0&&(t[25]=e.transportMetrics.oscOutBytesSent),e.transportMetrics.preschedulerBypassed!==void 0&&(t[22]=e.transportMetrics.preschedulerBypassed),e.transportMetrics.bypassNonBundle!==void 0&&(t[38]=e.transportMetrics.bypassNonBundle),e.transportMetrics.bypassImmediate!==void 0&&(t[39]=e.transportMetrics.bypassImmediate),e.transportMetrics.bypassNearFuture!==void 0&&(t[40]=e.transportMetrics.bypassNearFuture),e.transportMetrics.bypassLate!==void 0&&(t[41]=e.transportMetrics.bypassLate))}else this.#s&&t.set(this.#s);let s=this.#c;s.setInt32(46*4,e.driftOffsetMs??0,!0),s.setInt32(47*4,e.clockOffsetMs??0,!0);let r=e.audioContextState||"unknown",n={unknown:0,running:1,suspended:2,closed:3,interrupted:4};t[48]=n[r]??0,e.bufferPoolStats&&(t[49]=e.bufferPoolStats.used?.size??0,t[50]=e.bufferPoolStats.available??0,t[51]=e.bufferPoolStats.used?.count??0),t[52]=e.loadedSynthDefsCount??0;let o=this.#t;t[53]=o?.scheduler_slot_count??0,t[54]=e.preschedulerCapacity??0,t[55]=o?.IN_BUFFER_SIZE??0,t[56]=o?.OUT_BUFFER_SIZE??0,t[57]=o?.DEBUG_BUFFER_SIZE??0,t[58]=this.#h==="sab"?0:1}getMergedArray(){return this.#o}get bufferConstants(){return this.#t}get ringBufferBase(){return this.#e}get sharedBuffer(){return this.#r}};function ee(i){return i/1e3+2208988800}function we(i,e){return i-e}function ft(i,e){let t=i-e;return Math.round(t*1e3)}var te=class{#r;#e;#t;#h;#n;#s;#l;#a;#o;#c=0;#u=0;#p=null;constructor(e={}){this.#r=e.mode||"sab",this.#e=e.audioContext,this.#t=e.workletPort||null}initSharedViews(e,t,s){this.#n=t,this.#h=s,this.#r==="sab"&&e&&s&&(this.#s=new Float64Array(e,t+s.NTP_START_TIME_START,1),this.#l=new Int32Array(e,t+s.DRIFT_OFFSET_START,1),this.#a=new Int32Array(e,t+s.GLOBAL_OFFSET_START,1))}setWorkletPort(e){this.#t=e}updateAudioContext(e){this.#e=e}async initialize(){if(!this.#e)return;let e;for(;e=this.#e.getOutputTimestamp(),!(e.contextTime>0);)await new Promise(o=>setTimeout(o,50));e=this.#e.getOutputTimestamp();let t=performance.timeOrigin+e.performanceTime,s=ee(t),r=e.contextTime,n=we(s,r);this.#r==="sab"&&this.#s?this.#s[0]=n:this.#t&&this.#t.postMessage({type:"setNTPStartTime",ntpStartTime:n}),this.#o=n,await new Promise(o=>setTimeout(o,500)),this.updateDriftOffset()}updateDriftOffset(){if(!this.#e||this.#o===void 0)return;let e=this.#e.getOutputTimestamp(),t=performance.timeOrigin+e.performanceTime,r=ee(t)-this.#o,n=ft(r,e.contextTime);this.#c=n,this.#r==="sab"&&this.#l?Atomics.store(this.#l,0,n):this.#t&&this.#t.postMessage({type:"setDriftOffset",driftOffsetMs:n})}resync(){if(!this.#e)return;let e=this.#e.getOutputTimestamp();if(!e||e.contextTime<=0)return;let t=performance.timeOrigin+e.performanceTime,s=ee(t),r=we(s,e.contextTime);this.#r==="sab"&&this.#s?this.#s[0]=r:this.#t&&this.#t.postMessage({type:"setNTPStartTime",ntpStartTime:r}),this.#o=r,this.updateDriftOffset()}startDriftTimer(){this.stopDriftTimer(),this.#p=setInterval(()=>{this.updateDriftOffset()},1e3)}stopDriftTimer(){this.#p&&(clearInterval(this.#p),this.#p=null)}getDriftOffset(){return this.#l?Atomics.load(this.#l,0):this.#c}getNTPStartTime(){return this.#s?this.#s[0]:this.#o??0}getClockOffset(){return this.#a?Atomics.load(this.#a,0):this.#u}setClockOffset(e){let t=Math.round(e*1e3);this.#u=t,this.#r==="sab"&&this.#a?Atomics.store(this.#a,0,t):this.#t&&this.#t.postMessage({type:"setClockOffset",clockOffsetMs:t})}calculateBundleWait(e){if(e.length<16||String.fromCharCode.apply(null,e.slice(0,8))!=="#bundle\0")return null;let s=this.getNTPStartTime();if(s===0)return console.warn("[NTPTiming] NTP start time not yet initialized"),null;let n=this.getDriftOffset()/1e3,a=this.getClockOffset()/1e3,c=s+n+a,l=new DataView(e.buffer,e.byteOffset),u=l.getUint32(8,!1),f=l.getUint32(12,!1);if(u===0&&(f===0||f===1))return null;let S=u+f/4294967296-c,m=this.#e?.currentTime??0;return{audioTimeS:S,currentTimeS:m}}reset(){this.stopDriftTimer(),this.#o=void 0,this.#c=0,this.#u=0,this.#s=null,this.#l=null,this.#a=null}};var se=class{#r;#e;#t;constructor(e={}){this.#r=e.sharedBuffer||null,this.#e=e.bufferConstants||null,this.#t=e.ringBufferBase||0}update(e,t,s){this.#r=e,this.#t=t,this.#e=s}isAvailable(){return!!(this.#r&&this.#e)}start(){if(!this.isAvailable())throw new Error("AudioCapture not initialized");let e=this.#e,t=this.#t+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#r,t,4);Atomics.store(s,1,0),Atomics.store(s,0,1)}stop(){if(!this.isAvailable())throw new Error("AudioCapture not initialized");let e=this.#e,t=this.#t+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#r,t,4);Atomics.store(s,0,0);let r=Atomics.load(s,1),n=s[2],o=s[3],a=t+e.AUDIO_CAPTURE_HEADER_SIZE,c=new Float32Array(this.#r,a,r*o),l=new Float32Array(r),u=o>1?new Float32Array(r):null;for(let f=0;f<r;f++)l[f]=c[f*o],u&&(u[f]=c[f*o+1]);return{sampleRate:n,channels:o,frames:r,left:l,right:u}}isEnabled(){if(!this.isAvailable())return!1;let e=this.#e,t=this.#t+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#r,t,1);return Atomics.load(s,0)===1}getFrameCount(){if(!this.isAvailable())return 0;let e=this.#e,t=this.#t+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#r,t,2);return Atomics.load(s,1)}getMaxDuration(){if(!this.#e)return 0;let e=this.#e;return e.AUDIO_CAPTURE_FRAMES/(e.AUDIO_CAPTURE_SAMPLE_RATE||48e3)}};function ht(i,e,t){let s=t,r=new Uint32Array(i,e,3),n=r[0],o=r[1],a=r[2],c=e+s.NODE_TREE_HEADER_SIZE,l=s.NODE_TREE_MIRROR_MAX_NODES,u=s.NODE_TREE_ENTRY_SIZE,f=s.NODE_TREE_DEF_NAME_SIZE,h=new DataView(i,c,l*u),S=new TextDecoder("utf-8"),m=[],g=0;for(let p=0;p<l&&g<n;p++){let y=p*u,_=h.getInt32(y,!0);if(_===-1)continue;g++;let d=c+y+24,w=new Uint8Array(i,d,f),fe=new Uint8Array(f);fe.set(w);let he=fe.indexOf(0);he===-1&&(he=f);let Ot=S.decode(fe.subarray(0,he));m.push({id:_,parentId:h.getInt32(y+4,!0),isGroup:h.getInt32(y+8,!0)===1,prevId:h.getInt32(y+12,!0),nextId:h.getInt32(y+16,!0),headId:h.getInt32(y+20,!0),defName:Ot})}return{nodeCount:n,version:o,droppedCount:a,nodes:m}}var Bt={};Rt(Bt,{NTP_EPOCH_OFFSET:()=>ne,TWO_POW_32:()=>G,clearCache:()=>js,copyEncoded:()=>W,decodeBundle:()=>Tt,decodeMessage:()=>bt,decodePacket:()=>$,encodeBundle:()=>ae,encodeBundleIntoBuffer:()=>Qs,encodeMessage:()=>oe,encodeMessageIntoBuffer:()=>Ks,encodeSingleBundle:()=>xe,getBundleTimeTag:()=>ue,getCacheStats:()=>Js,isBundle:()=>At});var Pe=new Uint8Array(2097152),dt=new DataView(Pe.buffer),E=Pe,b=dt,Y=new Map,pt=1e3,Zs=new TextDecoder,Xs=new TextEncoder,ne=2208988800,G=4294967296,ke=new Uint8Array([35,98,117,110,100,108,101,0]),mt=44,Ce=105,Oe=102,Ue=115,Re=98,Ie=84,De=70,yt=104,Et=100,St=116;function re(i,e){let t=i.length+4;t+=e.length+4;for(let s of e)if(s instanceof Uint8Array)t+=4+s.length+3;else if(s instanceof ArrayBuffer)t+=4+s.byteLength+3;else if(typeof s=="string")t+=s.length*3+4;else if(s&&s.type==="string")t+=s.value.length*3+4;else if(s&&s.type==="blob"){let r=s.value,n=r instanceof Uint8Array?r.length:r.byteLength;t+=4+n+3}else t+=8;return t}function gt(i){let e=16;for(let t of i)e+=4,Array.isArray(t)?e+=re(t[0],t.slice(1)):t.packets!==void 0?e+=gt(t.packets):e+=re(t.address,t.args||[]);return e}function Fe(i){if(i<=2097152){E=Pe,b=dt;return}E=new Uint8Array(i),b=new DataView(E.buffer)}function oe(i,e=[]){let t=re(i,e);Fe(t);let s=0;s=Ne(i,s),s=ve(e,s);for(let r=0;r<e.length;r++)s=ce(e[r],s);return E.subarray(0,s)}function ae(i,e){let t=gt(e);Fe(t);let s=0;E.set(ke,s),s+=8,s=le(i,s);for(let r=0;r<e.length;r++){let n=e[r],o=s;s+=4;let a=s;Array.isArray(n)?s=ie(n[0],n.slice(1),s):n.packets!==void 0?s=_t(n.timeTag,n.packets,s):s=ie(n.address,n.args||[],s);let c=s-a;b.setUint32(o,c,!1)}return E.subarray(0,s)}function xe(i,e,t=[]){let s=20+re(e,t);Fe(s);let r=0;E.set(ke,r),r+=8,r=le(i,r);let n=r;r+=4;let o=r;r=Ne(e,r),r=ve(t,r);for(let a=0;a<t.length;a++)r=ce(t[a],r);return b.setUint32(n,r-o,!1),E.subarray(0,r)}function ie(i,e,t){t=Ne(i,t),t=ve(e,t);for(let s=0;s<e.length;s++)t=ce(e[s],t);return t}function _t(i,e,t){E.set(ke,t),t+=8,t=le(i,t);for(let s=0;s<e.length;s++){let r=e[s],n=t;t+=4;let o=t;Array.isArray(r)?t=ie(r[0],r.slice(1),t):r.packets!==void 0?t=_t(r.timeTag,r.packets,t):t=ie(r.address,r.args||[],t),b.setUint32(n,t-o,!1)}return t}function Ne(i,e){let t=Y.get(i);if(t)return E.set(t,e),e+t.length;let s=e;if(e=Le(i,e),Y.size<pt){let r=E.slice(s,e);Y.set(i,r)}return e}function Le(i,e){let t=!1;for(let s=0;s<i.length;s++)if(i.charCodeAt(s)>=128){t=!0;break}if(t){let s=Xs.encodeInto(i,E.subarray(e));e+=s.written}else for(let s=0;s<i.length;s++)E[e++]=i.charCodeAt(s);for(E[e++]=0;e&3;)E[e++]=0;return e}function ve(i,e){E[e++]=mt;for(let t=0;t<i.length;t++){let s=i[t],r=typeof s;if(r==="number")E[e++]=Number.isInteger(s)?Ce:Oe;else if(r==="string")E[e++]=Ue;else if(r==="boolean")E[e++]=s?Ie:De;else if(s instanceof Uint8Array||s instanceof ArrayBuffer)E[e++]=Re;else if(s&&s.type==="int")E[e++]=Ce;else if(s&&s.type==="float")E[e++]=Oe;else if(s&&s.type==="string")E[e++]=Ue;else if(s&&s.type==="blob")E[e++]=Re;else if(s&&s.type==="bool")E[e++]=s.value?Ie:De;else if(s&&s.type==="int64")E[e++]=yt;else if(s&&s.type==="double")E[e++]=Et;else if(s&&s.type==="timetag")E[e++]=St;else throw s==null?new Error(`OSC argument at index ${t} is ${s}`):new Error(`Unknown OSC argument type at index ${t}: ${r}`)}for(E[e++]=0;e&3;)E[e++]=0;return e}function ce(i,e){let t=typeof i;if(t==="number")return Number.isInteger(i)?(b.setInt32(e,i,!1),e+4):(b.setFloat32(e,i,!1),e+4);if(t==="string")return Le(i,e);if(t==="boolean")return e;if(i instanceof Uint8Array){let s=i.length;for(b.setUint32(e,s,!1),e+=4,E.set(i,e),e+=s;e&3;)E[e++]=0;return e}if(i instanceof ArrayBuffer)return ce(new Uint8Array(i),e);if(i&&i.type==="int")return b.setInt32(e,i.value,!1),e+4;if(i&&i.type==="float")return b.setFloat32(e,i.value,!1),e+4;if(i&&i.type==="string")return Le(i.value,e);if(i&&i.type==="blob"){let s=i.value instanceof Uint8Array?i.value:new Uint8Array(i.value),r=s.length;for(b.setUint32(e,r,!1),e+=4,E.set(s,e),e+=r;e&3;)E[e++]=0;return e}return i&&i.type==="bool"?e:i&&i.type==="int64"?(b.setBigInt64(e,BigInt(i.value),!1),e+8):i&&i.type==="double"?(b.setFloat64(e,i.value,!1),e+8):i&&i.type==="timetag"?le(i.value,e):e}function le(i,e){if(i===1||i===null||i===void 0)return b.setUint32(e,0,!1),b.setUint32(e+4,1,!1),e+8;if(Array.isArray(i)){if(i.length!==2)throw new Error(`TimeTag array must have exactly 2 elements [seconds, fraction], got ${i.length}`);return b.setUint32(e,i[0]>>>0,!1),b.setUint32(e+4,i[1]>>>0,!1),e+8}if(typeof i!="number")throw new TypeError(`TimeTag must be a number, array, null, or undefined, got ${typeof i}`);i>1&&i<ne&&console.warn(`TimeTag ${i} looks like a Unix timestamp (< NTP_EPOCH_OFFSET). Did you mean to add NTP_EPOCH_OFFSET (2208988800)?`);let t=i>>>0,s=(i-Math.floor(i))*G>>>0;return b.setUint32(e,t,!1),b.setUint32(e+4,s,!1),e+8}function $(i){return i instanceof Uint8Array||(i=new Uint8Array(i)),i[0]===35&&i[1]===98?Tt(i):bt(i)}function bt(i){i instanceof Uint8Array||(i=new Uint8Array(i));let e=new DataView(i.buffer,i.byteOffset,i.byteLength),t=0,[s,r]=Me(i,t);if(t=r,t>=i.length||i[t]!==mt)return[s];let[n,o]=Me(i,t);t=o;let a=[s];for(let c=1;c<n.length;c++)switch(n.charCodeAt(c)){case Ce:a.push(e.getInt32(t,!1)),t+=4;break;case Oe:a.push(e.getFloat32(t,!1)),t+=4;break;case Ue:let[u,f]=Me(i,t);a.push(u),t=f;break;case Re:let h=e.getUint32(t,!1);t+=4,a.push(i.slice(t,t+h)),t+=h,t=t+3&-4;break;case yt:a.push(e.getBigInt64(t,!1)),t+=8;break;case Et:a.push(e.getFloat64(t,!1)),t+=8;break;case Ie:a.push(!0);break;case De:a.push(!1);break;case St:let S=e.getUint32(t,!1),m=e.getUint32(t+4,!1);a.push(S+m/G),t+=8;break}return a}function Tt(i){i instanceof Uint8Array||(i=new Uint8Array(i));let e=new DataView(i.buffer,i.byteOffset,i.byteLength),t=8,s=e.getUint32(t,!1),r=e.getUint32(t+4,!1),n=s+r/G;t+=8;let o=[];for(;t<i.length;){let a=e.getUint32(t,!1);if(t+=4,a>0&&t+a<=i.length){let c=i.subarray(t,t+a);o.push($(c))}t+=a}return{timeTag:n,packets:o}}function Me(i,e){let t=e;for(;t<i.length&&i[t]!==0;)t++;let s=Zs.decode(i.subarray(e,t));return t++,t=t+3&-4,[s,t]}function W(i){return i.slice()}function Ks(i,e,t,s){let r=oe(i,e);return t.set(r,s),r.length}function Qs(i,e,t,s){let r=ae(i,e);return t.set(r,s),r.length}function js(){Y.clear()}function Js(){return{stringCacheSize:Y.size,maxSize:pt}}function At(i){return!i||i.length<8?!1:i[0]===35&&i[1]===98}function ue(i){if(!At(i))return null;let e=new DataView(i.buffer,i.byteOffset,i.byteLength),t=e.getUint32(8,!1),s=e.getUint32(12,!1);return t+s/G}var wt={totalPages:1280,ringBufferReserved:3145728,bufferPoolOffset:19922944,bufferPoolSize:63963136,get totalMemory(){return this.bufferPoolOffset+this.bufferPoolSize},get wasmHeapSize(){return this.bufferPoolOffset-this.ringBufferReserved}};var Mt={numBuffers:1024,maxNodes:1024,maxGraphDefs:1024,maxWireBufs:64,numAudioBusChannels:128,numInputBusChannels:2,numOutputBusChannels:2,numControlBusChannels:4096,bufLength:128,realTimeMemorySize:8192,numRGens:64,realTime:!1,memoryLocking:!1,loadGraphDefs:0,preferredSampleRate:0,verbosity:0};var rr=new Set(["/b_alloc","/b_allocRead","/b_allocReadChannel","/b_allocFile"]),Ct=class i{static osc={encodeMessage:(e,t)=>W(oe(e,t)),encodeBundle:(e,t)=>W(ae(e,t)),decode:e=>$(e),encodeSingleBundle:(e,t,s)=>W(xe(e,t,s)),readTimetag:e=>pe(e),ntpNow:()=>T(),NTP_EPOCH_OFFSET:ne};static#r=null;static getMetricsSchema(){return this.#r??={metrics:{scsynthProcessCount:{offset:0,type:"counter",unit:"count",description:"Audio process() calls"},scsynthMessagesProcessed:{offset:1,type:"counter",unit:"count",description:"OSC messages processed by scsynth"},scsynthMessagesDropped:{offset:2,type:"counter",unit:"count",description:"Messages dropped (ring buffer full)"},scsynthSchedulerDepth:{offset:3,type:"gauge",unit:"count",description:"Current scheduler queue depth"},scsynthSchedulerPeakDepth:{offset:4,type:"gauge",unit:"count",description:"Peak scheduler queue depth (high water mark)"},scsynthSchedulerDropped:{offset:5,type:"counter",unit:"count",description:"Scheduled events dropped"},scsynthSequenceGaps:{offset:6,type:"counter",unit:"count",description:"Messages lost in transit from JS to scsynth"},scsynthWasmErrors:{offset:7,type:"counter",unit:"count",description:"WASM execution errors in audio worklet"},scsynthSchedulerLates:{offset:8,type:"counter",unit:"count",description:"Bundles executed after their scheduled time"},preschedulerPending:{offset:9,type:"gauge",unit:"count",description:"Events waiting to be scheduled"},preschedulerPendingPeak:{offset:10,type:"gauge",unit:"count",description:"Peak pending events"},preschedulerBundlesScheduled:{offset:11,type:"counter",unit:"count",description:"Bundles scheduled"},preschedulerDispatched:{offset:12,type:"counter",unit:"count",description:"Events sent to worklet"},preschedulerEventsCancelled:{offset:13,type:"counter",unit:"count",description:"Events cancelled"},preschedulerMinHeadroomMs:{offset:14,type:"gauge",unit:"ms",description:"Smallest time gap between JS prescheduler dispatch and scsynth scheduler execution"},preschedulerLates:{offset:15,type:"counter",unit:"count",description:"Bundles dispatched after their scheduled execution time"},preschedulerRetriesSucceeded:{offset:16,type:"counter",unit:"count",description:"Retries that succeeded"},preschedulerRetriesFailed:{offset:17,type:"counter",unit:"count",description:"Retries that failed"},preschedulerRetryQueueSize:{offset:18,type:"gauge",unit:"count",description:"Current retry queue size"},preschedulerRetryQueuePeak:{offset:19,type:"gauge",unit:"count",description:"Peak retry queue size"},preschedulerMessagesRetried:{offset:20,type:"counter",unit:"count",description:"Messages that needed retry"},preschedulerTotalDispatches:{offset:21,type:"counter",unit:"count",description:"Total dispatch attempts"},preschedulerBypassed:{offset:22,type:"counter",unit:"count",description:"Messages sent directly from JS to scsynth, bypassing prescheduler (aggregate)"},preschedulerMaxLateMs:{offset:23,type:"gauge",unit:"ms",description:"Maximum lateness at prescheduler (ms)"},oscOutMessagesSent:{offset:24,type:"counter",unit:"count",description:"OSC messages sent from JS to scsynth"},oscOutBytesSent:{offset:25,type:"counter",unit:"bytes",description:"Total bytes sent from JS to scsynth"},oscInMessagesReceived:{offset:26,type:"counter",unit:"count",description:"OSC replies received from scsynth to JS"},oscInBytesReceived:{offset:27,type:"counter",unit:"bytes",description:"Total bytes received from scsynth to JS"},oscInMessagesDropped:{offset:28,type:"counter",unit:"count",description:"Replies lost in transit from scsynth to JS"},oscInCorrupted:{offset:29,type:"counter",unit:"count",description:"Corrupted messages detected from scsynth to JS"},debugMessagesReceived:{offset:30,type:"counter",unit:"count",description:"Debug messages from scsynth"},debugBytesReceived:{offset:31,type:"counter",unit:"bytes",description:"Debug bytes received"},inBufferUsedBytes:{offset:32,type:"gauge",unit:"bytes",description:"Bytes used in IN ring buffer"},outBufferUsedBytes:{offset:33,type:"gauge",unit:"bytes",description:"Bytes used in OUT ring buffer"},debugBufferUsedBytes:{offset:34,type:"gauge",unit:"bytes",description:"Bytes used in DEBUG ring buffer"},inBufferPeakBytes:{offset:35,type:"gauge",unit:"bytes",description:"Peak bytes used in IN ring buffer"},outBufferPeakBytes:{offset:36,type:"gauge",unit:"bytes",description:"Peak bytes used in OUT ring buffer"},debugBufferPeakBytes:{offset:37,type:"gauge",unit:"bytes",description:"Peak bytes used in DEBUG ring buffer"},bypassNonBundle:{offset:38,type:"counter",unit:"count",description:"Plain OSC messages (not bundles) that bypassed prescheduler"},bypassImmediate:{offset:39,type:"counter",unit:"count",description:"Bundles with timetag 0 or 1 that bypassed prescheduler"},bypassNearFuture:{offset:40,type:"counter",unit:"count",description:"Bundles within bypass lookahead threshold that bypassed prescheduler"},bypassLate:{offset:41,type:"counter",unit:"count",description:"Timestamped OSC bundles arriving late into SuperSonic bypassing prescheduler"},scsynthSchedulerMaxLateMs:{offset:42,type:"gauge",unit:"ms",description:"Maximum lateness observed in scsynth scheduler (ms)"},scsynthSchedulerLastLateMs:{offset:43,type:"gauge",unit:"ms",description:"Most recent late magnitude in scsynth scheduler (ms)"},scsynthSchedulerLastLateTick:{offset:44,type:"gauge",unit:"count",description:"Process count when last scsynth late occurred"},ringBufferDirectWriteFails:{offset:45,type:"counter",unit:"count",description:"SAB mode only: optimistic direct writes attempted but failed due to ring buffer lock not being available (delivered via prescheduler instead)"},driftOffsetMs:{offset:46,type:"gauge",unit:"ms",signed:!0,description:"Clock drift between AudioContext and wall clock"},clockOffsetMs:{offset:47,type:"gauge",unit:"ms",signed:!0,description:"Clock offset for multi-system sync"},audioContextState:{offset:48,type:"enum",values:["unknown","running","suspended","closed","interrupted"],description:"AudioContext state"},bufferPoolUsedBytes:{offset:49,type:"gauge",unit:"bytes",description:"Buffer pool bytes used"},bufferPoolAvailableBytes:{offset:50,type:"gauge",unit:"bytes",description:"Buffer pool bytes available"},bufferPoolAllocations:{offset:51,type:"counter",unit:"count",description:"Total buffer allocations"},loadedSynthDefs:{offset:52,type:"gauge",unit:"count",description:"Number of loaded synthdefs"},scsynthSchedulerCapacity:{offset:53,type:"constant",unit:"count",description:"Maximum scheduler queue size"},preschedulerCapacity:{offset:54,type:"constant",unit:"count",description:"Maximum pending events in prescheduler"},inBufferCapacity:{offset:55,type:"constant",unit:"bytes",description:"IN ring buffer capacity"},outBufferCapacity:{offset:56,type:"constant",unit:"bytes",description:"OUT ring buffer capacity"},debugBufferCapacity:{offset:57,type:"constant",unit:"bytes",description:"DEBUG ring buffer capacity"},mode:{offset:58,type:"enum",values:["sab","postMessage"],description:"Transport mode"}},layout:{panels:[{title:"OSC Out",rows:[{label:"sent",cells:[{key:"oscOutMessagesSent"}]},{label:"bytes",cells:[{key:"oscOutBytesSent",kind:"muted",format:"bytes"}]},{label:"bypass",cells:[{key:"preschedulerBypassed",kind:"green"}]},{label:"lost",cells:[{key:"scsynthSequenceGaps",kind:"error"}]}]},{title:"Bypass",rows:[{label:"msg",cells:[{key:"bypassNonBundle",kind:"muted"}]},{label:"imm",cells:[{key:"bypassImmediate",kind:"muted"}]},{label:"near",cells:[{key:"bypassNearFuture",kind:"muted"}]},{label:"late",cells:[{key:"bypassLate",kind:"muted"}]}]},{title:"OSC In",rows:[{label:"received",cells:[{key:"oscInMessagesReceived"}]},{label:"bytes",cells:[{key:"oscInBytesReceived",kind:"muted",format:"bytes"}]},{label:"dropped",cells:[{key:"oscInMessagesDropped",kind:"error"}]},{label:"corrupted",cells:[{key:"oscInCorrupted",kind:"error"}]}]},{title:"Presched Flow",rows:[{label:"pending",cells:[{key:"preschedulerPending"},{sep:" | "},{key:"preschedulerPendingPeak",kind:"muted"}]},{label:"scheduled",cells:[{key:"preschedulerBundlesScheduled"}]},{label:"dispatched",cells:[{key:"preschedulerDispatched",kind:"dim"}]},{label:"min slack",cells:[{key:"preschedulerMinHeadroomMs",kind:"dim",format:"headroom"},{text:" ms",kind:"muted"}]}]},{title:"Presched Health",rows:[{label:"lates",cells:[{key:"preschedulerLates",kind:"error"},{sep:" ("},{key:"preschedulerMaxLateMs",kind:"dim"},{text:"ms max)",kind:"muted"}]},{label:"cancelled",cells:[{key:"preschedulerEventsCancelled",kind:"error"}]},{label:"retried",cells:[{key:"preschedulerMessagesRetried",kind:"dim"},{sep:" | "},{key:"preschedulerRetriesSucceeded",kind:"green"},{sep:" | "},{key:"preschedulerRetriesFailed",kind:"error"}]},{label:"retry queue",cells:[{key:"preschedulerRetryQueueSize"},{sep:" | "},{key:"preschedulerRetryQueuePeak",kind:"muted"}]}]},{title:"scsynth Scheduler",rows:[{label:"queue",cells:[{key:"scsynthSchedulerDepth"},{sep:" | "},{key:"scsynthSchedulerPeakDepth",kind:"muted"}]},{label:"dropped",cells:[{key:"scsynthSchedulerDropped",kind:"error"}]},{label:"lates",cells:[{key:"scsynthSchedulerLates",kind:"error"}]},{label:"max | last",cells:[{key:"scsynthSchedulerMaxLateMs",kind:"error"},{sep:" | "},{key:"scsynthSchedulerLastLateMs",kind:"dim"},{text:" ms",kind:"muted"}]}]},{title:"scsynth",rows:[{label:"processed",cells:[{key:"scsynthMessagesProcessed"}]},{label:"dropped",cells:[{key:"scsynthMessagesDropped",kind:"error"}]},{label:"synthdefs",cells:[{key:"loadedSynthDefs"}]},{label:"clock drift",cells:[{key:"driftOffsetMs",format:"signed"},{text:"ms",kind:"muted"}]}]},{title:"Ring Buffer Level",class:"wide",rows:[{type:"bar",label:"in",usedKey:"inBufferUsedBytes",peakKey:"inBufferPeakBytes",capacityKey:"inBufferCapacity",color:"blue"},{type:"bar",label:"out",usedKey:"outBufferUsedBytes",peakKey:"outBufferPeakBytes",capacityKey:"outBufferCapacity",color:"green"},{type:"bar",label:"dbg",usedKey:"debugBufferUsedBytes",peakKey:"debugBufferPeakBytes",capacityKey:"debugBufferCapacity",color:"purple"},{label:"direct write fails",cells:[{key:"ringBufferDirectWriteFails",kind:"error"}]}]},{title:"AudioWorklet",rows:[{label:"audio",cells:[{key:"audioContextState",kind:"green",format:"enum"}]},{label:"ticks",cells:[{key:"scsynthProcessCount",kind:"dim"}]},{label:"WASM errors",cells:[{key:"scsynthWasmErrors",kind:"error"}]},{label:"debug",cells:[{key:"debugMessagesReceived",kind:"muted"},{text:" ("},{key:"debugBytesReceived",kind:"muted",format:"bytes"},{text:")"}]}]},{title:"Audio Buffers",rows:[{label:"used",cells:[{key:"bufferPoolUsedBytes",format:"bytes"}]},{label:"free",cells:[{key:"bufferPoolAvailableBytes",kind:"green",format:"bytes"}]},{label:"allocs",cells:[{key:"bufferPoolAllocations",kind:"dim"}]}]}]},sentinels:{HEADROOM_UNSET:4294967295}}}static getTreeSchema(){return{nodeCount:{type:"number",description:"Total nodes in tree"},version:{type:"number",description:"Increments on any tree change, useful for detecting updates"},droppedCount:{type:"number",description:"Nodes that exceeded mirror capacity (tree may be incomplete)"},root:{type:"object",description:"Root node of the tree (always a group with id 0)",schema:{id:{type:"number",description:"Unique node ID"},type:{type:"string",values:["group","synth"],description:"Node type"},defName:{type:"string",description:"Synthdef name (synths only, empty for groups)"},children:{type:"array",description:"Child nodes (recursive)",itemSchema:"(self)"}}}}}static getRawTreeSchema(){return{nodeCount:{type:"number",description:"Total nodes in tree"},version:{type:"number",description:"Increments on any tree change, useful for detecting updates"},droppedCount:{type:"number",description:"Nodes that exceeded mirror capacity (tree may be incomplete)"},nodes:{type:"array",description:"Flat array of all nodes with internal linkage pointers",itemSchema:{id:{type:"number",description:"Unique node ID"},parentId:{type:"number",description:"Parent node ID (-1 for root)"},isGroup:{type:"boolean",description:"True if group, false if synth"},prevId:{type:"number",description:"Previous sibling node ID (-1 if none)"},nextId:{type:"number",description:"Next sibling node ID (-1 if none)"},headId:{type:"number",description:"First child node ID (groups only, -1 if empty)"},defName:{type:"string",description:"Synthdef name (synths only, empty for groups)"}}}}}#e;#t;#h=null;#n;#s;#l;#a;#o;#c;#u;#p;#_;#d;#m;#S;#b;#g;#i;#f;#y;#E;#A;#B;#w=null;#M=null;#R=0;#O=[];#U=null;#C=Promise.resolve();#z(e){let t=(s,r,{min:n,max:o,allowZero:a=!0}={})=>{if(typeof r!="number"||!Number.isFinite(r))throw new Error(`scsynthOptions.${s} must be a finite number, got: ${r}`);if(!a&&r===0)throw new Error(`scsynthOptions.${s} must be non-zero, got: ${r}`);if(n!==void 0&&r<n)throw new Error(`scsynthOptions.${s} must be >= ${n}, got: ${r}`);if(o!==void 0&&r>o)throw new Error(`scsynthOptions.${s} must be <= ${o}, got: ${r}`)};if(t("numBuffers",e.numBuffers,{min:1,max:65535}),t("maxNodes",e.maxNodes,{min:1}),t("maxGraphDefs",e.maxGraphDefs,{min:1}),t("maxWireBufs",e.maxWireBufs,{min:1}),t("numAudioBusChannels",e.numAudioBusChannels,{min:1}),t("numInputBusChannels",e.numInputBusChannels,{min:0}),t("numOutputBusChannels",e.numOutputBusChannels,{min:1,max:128}),t("numControlBusChannels",e.numControlBusChannels,{min:1}),e.bufLength!==128)throw new Error(`scsynthOptions.bufLength must be 128 (WebAudio API constraint), got: ${e.bufLength}`);if(t("realTimeMemorySize",e.realTimeMemorySize,{min:1}),t("numRGens",e.numRGens,{min:1}),typeof e.realTime!="boolean")throw new Error(`scsynthOptions.realTime must be a boolean, got: ${typeof e.realTime}`);if(typeof e.memoryLocking!="boolean")throw new Error(`scsynthOptions.memoryLocking must be a boolean, got: ${typeof e.memoryLocking}`);if(e.loadGraphDefs!==0&&e.loadGraphDefs!==1)throw new Error(`scsynthOptions.loadGraphDefs must be 0 or 1, got: ${e.loadGraphDefs}`);if(t("preferredSampleRate",e.preferredSampleRate,{min:0,max:384e3}),e.preferredSampleRate!==0&&e.preferredSampleRate<8e3)throw new Error(`scsynthOptions.preferredSampleRate must be 0 (auto) or >= 8000, got: ${e.preferredSampleRate}`);t("verbosity",e.verbosity,{min:0,max:4})}constructor(e={}){this.#d=!1,this.#m=!1,this.#S=null,this.#b={},this.#g=null,this.#f=new j,this.#y=new J({mode:e.mode||"postMessage"}),this.#A=new se({}),this.#e=null,this.#t=null,this.#n=null,this.#l=null,this.loadedSynthDefs=new Map;let t=e.baseURL||null,s=e.coreBaseURL||t,r=e.workerBaseURL||(t?`${t}workers/`:null),n=e.wasmBaseURL||(s?`${s}wasm/`:null);if(!r||!n)throw new Error(`SuperSonic requires explicit URL configuration.
5
+ Or install: npm install supersonic-scsynth-samples`);return this.#e+e}#r(e){if(!Number.isInteger(e)||e<0||e>=this.MAX_BUFFERS)throw new Error(`Invalid buffer number ${e} (must be 0-${this.MAX_BUFFERS-1})`)}async#l(e,t,s){let r=null,n=null,o=!1,a=await this.#M(e),c=!1;try{await this.#I(e);let{ptr:l,sizeBytes:u,numFrames:f,numChannels:h,sampleRate:S,source:m,...g}=await s();r=l;let{uuid:p,allocationComplete:y}=this.#B(e,t);n=p,this.#R(e,r,u,p,y,{numFrames:f,numChannels:h,sampleRate:S,source:m}),o=!0;let _=this.#O(e,p,y);return a(),c=!0,{ptr:r,uuid:p,allocationComplete:_,numFrames:f,numChannels:h,sampleRate:S,...g}}catch(l){throw o&&n?this.#C(e,n,!1):r&&this.#s.free(r),l}finally{c||a()}}async prepareFromBlob(e){let{bufnum:t,blob:s,startFrame:r=0,numFrames:n=0,channels:o=null}=e;if(this.#r(t),!s||!(s instanceof ArrayBuffer||ArrayBuffer.isView(s)))throw new Error("/b_allocFile requires audio data as ArrayBuffer or typed array");let a=await this.#h({source:s,startFrame:r,numFrames:n,channels:o});return this.#d(t,3e4,a,null)}async prepareFromFile(e){let{bufnum:t,path:s,startFrame:r=0,numFrames:n=0,channels:o=null}=e;this.#r(t);let a=await this.#h({source:s,startFrame:r,numFrames:n,channels:o});return this.#d(t,6e4,a,a.sourceInfo)}async prepareEmpty(e){let{bufnum:t,numFrames:s,numChannels:r=1,sampleRate:n=null}=e;if(this.#r(t),!Number.isFinite(s)||s<=0)throw new Error(`/b_alloc requires a positive number of frames (got ${s})`);if(!Number.isFinite(r)||r<=0)throw new Error(`/b_alloc requires a positive channel count (got ${r})`);let o=Math.floor(s),a=Math.floor(r),c=o*a+(this.GUARD_BEFORE+this.GUARD_AFTER)*a,u={interleaved:new Float32Array(c),numFrames:o,numChannels:a,sampleRate:n||this.#m.sampleRate};return this.#d(t,5e3,u,null)}#E(e,t){return!e||e.length===0?Array.from({length:t},(s,r)=>r):(e.forEach(s=>{if(!Number.isInteger(s)||s<0||s>=t)throw new Error(`Channel ${s} is out of range (file has ${t} channels)`)}),e)}#S(e){let t=e*4,s=this.#s.malloc(t);if(s===0){let r=this.#s.stats(),n=((r.available||0)/(1024*1024)).toFixed(2),o=((r.total||0)/(1024*1024)).toFixed(2),a=(t/(1024*1024)).toFixed(2);throw new Error(`Buffer pool allocation failed: requested ${a}MB, available ${n}MB of ${o}MB total`)}return s}async#A(e,t){if(this.#i==="sab")new Float32Array(this.#n,e,t.length).set(t);else{let s=crypto.randomUUID(),r=new Promise((o,a)=>{let c=setTimeout(()=>{a(new Error("Buffer copy to WASM memory timed out"))},1e4),l=u=>{let f=u.data;f.type==="bufferCopied"&&f.copyId===s&&(this.#p.removeEventListener("message",l),clearTimeout(c),f.success?o():a(new Error(f.error||"Buffer copy failed")))};this.#p.addEventListener("message",l)}),n=t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength);this.#p.postMessage({type:"copyBufferData",copyId:s,ptr:e,data:n},[n]),await r}}#w(e,t,s){return new Promise((r,n)=>{let o=setTimeout(()=>{this.#c.delete(e),n(new Error(`Buffer ${t} allocation timeout (${s}ms)`))},s);this.#c.set(e,{resolve:r,reject:n,timeout:o})})}#B(e,t){let s=crypto.randomUUID(),r=this.#w(s,e,t);return{uuid:s,allocationComplete:r}}async#M(e){let t=this.#f.get(e)||Promise.resolve(),s,r=new Promise(n=>{s=n});return this.#f.set(e,t.then(()=>r)),await t,()=>{s&&(s(),s=null),this.#f.get(e)===r&&this.#f.delete(e)}}#R(e,t,s,r,n,o={}){let a=this.#o.get(e),c={ptr:t,size:s,numFrames:o.numFrames||0,numChannels:o.numChannels||1,sampleRate:o.sampleRate||48e3,pendingToken:r,pendingPromise:n,previousAllocation:a?{ptr:a.ptr,size:a.size}:null,source:o.source||null};return this.#o.set(e,c),c}async#I(e){let t=this.#o.get(e);if(t&&t.pendingToken&&t.pendingPromise)try{await t.pendingPromise}catch{}}#O(e,t,s){return!s||typeof s.then!="function"?(this.#C(e,t,!0),Promise.resolve()):s.then(r=>(this.#C(e,t,!0),r)).catch(r=>{throw this.#C(e,t,!1),r})}#C(e,t,s){let r=this.#o.get(e);if(!r||r.pendingToken!==t)return;let n=r.previousAllocation;if(s){r.pendingToken=null,r.pendingPromise=null,r.previousAllocation=null,n?.ptr&&this.#s.free(n.ptr);return}r.ptr&&this.#s.free(r.ptr),r.pendingPromise=null,n?.ptr?this.#o.set(e,{ptr:n.ptr,size:n.size,pendingToken:null,previousAllocation:null}):this.#o.delete(e)}handleBufferFreed(e){let t=e[0],s=e[1],r=this.#o.get(t);if(!r){typeof s=="number"&&s!==0&&this.#s.free(s);return}if(typeof s=="number"&&s===r.ptr){this.#s.free(r.ptr),this.#o.delete(t);return}if(typeof s=="number"&&r.previousAllocation&&r.previousAllocation.ptr===s){this.#s.free(s),r.previousAllocation=null;return}this.#s.free(r.ptr),this.#o.delete(t)}handleBufferAllocated(e){let t=e[0],s=e[1],r=this.#c.get(t);r&&(clearTimeout(r.timeout),r.resolve({bufnum:s}),this.#c.delete(t))}allocate(e){let t=e*4,s=this.#s.malloc(t);if(s===0){let r=this.#s.stats(),n=((r.available||0)/(1024*1024)).toFixed(2),o=((r.total||0)/(1024*1024)).toFixed(2),a=(t/(1024*1024)).toFixed(2);console.error(`[BufferManager] Allocation failed: requested ${a}MB, available ${n}MB of ${o}MB total`)}return s}free(e){return this.#s.free(e)}getView(e,t){return new Float32Array(this.#n,e,t)}getStats(){return this.#s?this.#s.stats():{total:0,available:0,used:0,allocations:0}}async sampleInfo({source:e,startFrame:t=0,numFrames:s=0,channels:r=null}){let n=await this.#h({source:e,startFrame:t,numFrames:s,channels:r});return{hash:await this.#b(n.interleaved),source:n.sourceInfo?.path||null,numFrames:n.numFrames,numChannels:n.numChannels,sampleRate:n.sampleRate,duration:n.sampleRate>0?n.numFrames/n.sampleRate:0}}getAllocatedBuffers(){let e=[];for(let[t,s]of this.#o.entries())!s||!s.ptr||e.push({bufnum:t,ptr:s.ptr,numFrames:s.numFrames,numChannels:s.numChannels,sampleRate:s.sampleRate,source:s.source||null,hash:s.hash||null});return e}updateAudioContext(e){if(!e)throw new Error("BufferManager.updateAudioContext requires audioContext");this.#m=e}getDiagnostics(){let e=this.#s.stats(),t=0,s=0;for(let r of this.#o.values())r&&(t+=r.size||0,r.pendingToken&&s++);return{active:this.#o.size,pending:s,bytesActive:t,pool:{total:this.#u,available:e.available||0,freeBytes:e.free?.size||0,freeBlocks:e.free?.count||0,usedBytes:e.used?.size||0,usedBlocks:e.used?.count||0}}}destroy(){for(let[e,t]of this.#c.entries())clearTimeout(t.timeout),t.reject(new Error("BufferManager destroyed"));this.#c.clear();for(let[e,t]of this.#o.entries())t.ptr&&this.#s.free(t.ptr);this.#o.clear(),this.#f.clear()}};var V=class{#i;#e;#t;constructor(e={}){let{onLoadingEvent:t=null,maxRetries:s=3,baseDelay:r=1e3}=e;this.#i=t,this.#e=s,this.#t=r}async fetch(e,{type:t,name:s}){let r=this.#m(e),n=this.#n(e),o=await r;this.#i?.("loading:start",{type:t,name:s,...o!=null&&{size:o}});let c=await(await n).arrayBuffer();return this.#i?.("loading:complete",{type:t,name:s,size:c.byteLength}),c}async#m(e){try{let t=await fetch(e,{method:"HEAD"});if(t.ok){let s=t.headers.get("Content-Length");return s?parseInt(s,10):null}return null}catch{return null}}async#n(e){let t;for(let s=0;s<=this.#e;s++)try{let r=await fetch(e);if(r.status>=400&&r.status<500)throw new Error(`Failed to fetch ${e}: ${r.status} ${r.statusText}`);if(!r.ok)throw new Error(`Server error fetching ${e}: ${r.status} ${r.statusText}`);return r}catch(r){if(t=r,r.message.includes("Failed to fetch")&&r.message.includes("4"))throw r;if(s<this.#e){let n=this.#t*Math.pow(2,s);await this.#s(n)}}throw t}#s(e){return new Promise(t=>setTimeout(t,e))}};var q=class{#i;#e;constructor({bufferManager:e,getDefaultSampleRate:t}){if(!e)throw new Error("OSCRewriter requires bufferManager");if(typeof t!="function")throw new Error("OSCRewriter requires getDefaultSampleRate callback");this.#i=e,this.#e=t}async rewritePacket(e){if(Array.isArray(e)){let{message:t,changed:s}=await this.#t(e);return{packet:t,changed:s}}if(this.#o(e)){let t=await Promise.all(e.packets.map(n=>this.rewritePacket(n)));if(!t.some(n=>n.changed))return{packet:e,changed:!1};let r=t.map(n=>n.packet);return{packet:{timeTag:e.timeTag,packets:r},changed:!0}}return{packet:e,changed:!1}}async#t(e){let t=e[0],s=e.slice(1);switch(t){case"/b_alloc":return{message:await this.#m(s),changed:!0};case"/b_allocRead":return{message:await this.#n(s),changed:!0};case"/b_allocReadChannel":return{message:await this.#s(s),changed:!0};case"/b_allocFile":return{message:await this.#u(s),changed:!0};default:return{message:e,changed:!1}}}async#m(e){let t=this.#p(e,0,"/b_alloc requires a buffer number"),s=this.#p(e,1,"/b_alloc requires a frame count"),r=2,n=1,o=this.#e();this.#d(this.#c(e,r))&&(n=Math.max(1,this.#b(e,r,1)),r++),this.#c(e,r)?.type==="b"&&r++,this.#d(this.#c(e,r))&&(o=this.#f(this.#c(e,r)));let a=await this.#i.prepareEmpty({bufnum:t,numFrames:s,numChannels:n,sampleRate:o});return this.#_(a.allocationComplete,`/b_alloc ${t}`),this.#a(t,a)}async#n(e){let t=this.#p(e,0,"/b_allocRead requires a buffer number"),s=this.#h(e,1,"/b_allocRead requires a file path"),r=this.#b(e,2,0),n=this.#b(e,3,0),o=await this.#i.prepareFromFile({bufnum:t,path:s,startFrame:r,numFrames:n});return this.#_(o.allocationComplete,`/b_allocRead ${t}`),this.#a(t,o)}async#s(e){let t=this.#p(e,0,"/b_allocReadChannel requires a buffer number"),s=this.#h(e,1,"/b_allocReadChannel requires a file path"),r=this.#b(e,2,0),n=this.#b(e,3,0),o=[];for(let c=4;c<(e?.length||0)&&this.#d(e[c]);c++)o.push(Math.floor(this.#f(e[c])));let a=await this.#i.prepareFromFile({bufnum:t,path:s,startFrame:r,numFrames:n,channels:o.length>0?o:null});return this.#_(a.allocationComplete,`/b_allocReadChannel ${t}`),this.#a(t,a)}async#u(e){let t=this.#p(e,0,"/b_allocFile requires a buffer number"),s=this.#y(e,1,"/b_allocFile requires audio file data as blob"),r=await this.#i.prepareFromBlob({bufnum:t,blob:s});return this.#_(r.allocationComplete,`/b_allocFile ${t}`),this.#a(t,r)}#a(e,t){return["/b_allocPtr",Math.floor(e),Math.floor(t.ptr),Math.floor(t.numFrames),Math.floor(t.numChannels),t.sampleRate,String(t.uuid)]}#o(e){return e&&e.timeTag!==void 0&&Array.isArray(e.packets)}#c(e,t){if(Array.isArray(e))return e[t]}#f(e){if(e!=null)return typeof e=="object"&&Object.prototype.hasOwnProperty.call(e,"value")?e.value:e}#p(e,t,s){let r=this.#f(this.#c(e,t));if(!Number.isFinite(r))throw new Error(s);return Math.floor(r)}#b(e,t,s=0){let r=this.#f(this.#c(e,t));return Number.isFinite(r)?Math.floor(r):s}#h(e,t,s){let r=this.#f(this.#c(e,t));if(typeof r!="string")throw new Error(s);return r}#y(e,t,s){let r=this.#f(this.#c(e,t));if(!(r instanceof Uint8Array||r instanceof ArrayBuffer))throw new Error(s);return r}#d(e){if(!e)return!1;let t=this.#f(e);return Number.isFinite(t)}#_(e,t){!e||typeof e.catch!="function"||e.catch(s=>{console.error(`[OSCRewriter] ${t} allocation failed:`,s)})}};function F(i){if(!i)return null;if(typeof i=="string")return(i.split("/").filter(Boolean).pop()||i).replace(/\.scsyndef$/i,"");let e=i instanceof ArrayBuffer?new Uint8Array(i):i;if(!(e instanceof Uint8Array)||e.length<11||e[0]!==83||e[1]!==67||e[2]!==103||e[3]!==102)return null;let t=e[10];if(t===0||11+t>e.length)return null;try{return new TextDecoder().decode(e.slice(11,11+t))}catch{return null}}var Z=class{#i=new Map;on(e,t){if(typeof t!="function")throw new Error("Callback must be a function");return this.#i.has(e)||this.#i.set(e,new Set),this.#i.get(e).add(t),()=>this.off(e,t)}off(e,t){let s=this.#i.get(e);return s&&s.delete(t),this}once(e,t){let s=(...r)=>{this.off(e,s),t(...r)};return this.on(e,s)}removeAllListeners(e){return e===void 0?this.#i.clear():this.#i.delete(e),this}hasListeners(e){let t=this.#i.get(e);return t?t.size>0:!1}emit(e,...t){let s=this.#i.get(e);if(s)for(let r of s)try{r(...t)}catch(n){console.error(`[EventEmitter] Error in ${e} listener:`,n)}}async emitAsync(e,...t){let s=this.#i.get(e);if(s)for(let r of s)try{await r(...t)}catch(n){console.error(`[EventEmitter] Error in ${e} listener:`,n)}}clearAllListeners(){this.#i.clear()}};var X=class{#i;#e;#t;#m;#n;#s;#u;#a=null;#o=new Uint32Array(64);#c=new DataView(this.#o.buffer);constructor(e={}){this.#m=e.mode||"sab",this.#i=e.sharedBuffer||null,this.#e=e.ringBufferBase||0,this.#t=e.bufferConstants||null}initSharedViews(e,t,s){if(this.#i=e,this.#e=t,this.#t=s,this.#m==="sab"&&e&&s){this.#n=new Int32Array(e),this.#u=We(t,s.CONTROL_START);let r=t+s.METRICS_START;this.#s=new Uint32Array(e,r,s.METRICS_SIZE/4)}}updateSnapshot(e){this.#a=e}getSnapshotBuffer(){return this.#a}getMetricsView(){return this.#s}addMetric(e,t=1){if(!this.#s)return;let r={oscOutMessagesSent:24,oscOutBytesSent:25,preschedulerBypassed:22,bypassNonBundle:38,bypassImmediate:39,bypassNearFuture:40,bypassLate:41}[e];r!==void 0&&Atomics.add(this.#s,r,t)}parseMetricsBuffer(e){return{scsynthProcessCount:e[0],scsynthMessagesProcessed:e[1],scsynthMessagesDropped:e[2],scsynthSchedulerDepth:e[3],scsynthSchedulerPeakDepth:e[4],scsynthSchedulerDropped:e[5],scsynthSequenceGaps:e[6],scsynthSchedulerLates:e[8],scsynthSchedulerMaxLateMs:e[42],scsynthSchedulerLastLateMs:e[43],scsynthSchedulerLastLateTick:e[44],preschedulerPending:e[9],preschedulerPendingPeak:e[10],preschedulerDispatched:e[12],preschedulerRetriesSucceeded:e[16],preschedulerRetriesFailed:e[17],preschedulerBundlesScheduled:e[11],preschedulerEventsCancelled:e[13],preschedulerTotalDispatches:e[21],preschedulerMessagesRetried:e[20],preschedulerRetryQueueSize:e[18],preschedulerRetryQueuePeak:e[19],preschedulerBypassed:e[22],oscInMessagesReceived:e[26],oscInMessagesDropped:e[28],oscInBytesReceived:e[27],debugMessagesReceived:e[30],debugBytesReceived:e[31],oscOutMessagesSent:e[24],oscOutBytesSent:e[25],preschedulerMinHeadroomMs:e[14],preschedulerLates:e[15],preschedulerMaxLateMs:e[23],scsynthWasmErrors:e[7],oscInCorrupted:e[29],ringBufferDirectWriteFails:e[45],inBufferUsedBytes:e[32],outBufferUsedBytes:e[33],debugBufferUsedBytes:e[34],inBufferPeakBytes:e[35],outBufferPeakBytes:e[36],debugBufferPeakBytes:e[37],bypassNonBundle:e[38],bypassImmediate:e[39],bypassNearFuture:e[40],bypassLate:e[41]}}getSABMetrics(){return this.#s?this.parseMetricsBuffer(this.#s):null}getBufferUsage(){if(!this.#n||!this.#t||!this.#u)return null;let e=this.#t,t=this.#u,s=this.#n,r=Atomics.load(s,t.IN_HEAD),n=Atomics.load(s,t.IN_TAIL),o=Atomics.load(s,t.OUT_HEAD),a=Atomics.load(s,t.OUT_TAIL),c=Atomics.load(s,t.DEBUG_HEAD),l=Atomics.load(s,t.DEBUG_TAIL),u=(r-n+e.IN_BUFFER_SIZE)%e.IN_BUFFER_SIZE,f=(o-a+e.OUT_BUFFER_SIZE)%e.OUT_BUFFER_SIZE,h=(c-l+e.DEBUG_BUFFER_SIZE)%e.DEBUG_BUFFER_SIZE;return{inBufferUsed:{bytes:u,percentage:u/e.IN_BUFFER_SIZE*100,capacity:e.IN_BUFFER_SIZE},outBufferUsed:{bytes:f,percentage:f/e.OUT_BUFFER_SIZE*100,capacity:e.OUT_BUFFER_SIZE},debugBufferUsed:{bytes:h,percentage:h/e.DEBUG_BUFFER_SIZE*100,capacity:e.DEBUG_BUFFER_SIZE}}}overlayPreschedulerMetrics(e){if(!this.#a||!e)return;let t=new Uint32Array(this.#a,0,46),s=9,r=13;t.set(e.subarray(s,s+r),s),t[23]=e[23]}gatherMetrics(e={}){let t;if(this.#m==="postMessage")if(e.preschedulerMetrics&&this.overlayPreschedulerMetrics(e.preschedulerMetrics),this.#a){let s=new Uint32Array(this.#a,0,46);t=this.parseMetricsBuffer(s)}else t={};else t=this.getSABMetrics()||{};if(t.inBufferUsedBytes!==void 0&&this.#t){let s=this.#t;t.inBufferUsed={bytes:t.inBufferUsedBytes,percentage:t.inBufferUsedBytes/s.IN_BUFFER_SIZE*100,peakBytes:t.inBufferPeakBytes,peakPercentage:t.inBufferPeakBytes/s.IN_BUFFER_SIZE*100,capacity:s.IN_BUFFER_SIZE},t.outBufferUsed={bytes:t.outBufferUsedBytes,percentage:t.outBufferUsedBytes/s.OUT_BUFFER_SIZE*100,peakBytes:t.outBufferPeakBytes,peakPercentage:t.outBufferPeakBytes/s.OUT_BUFFER_SIZE*100,capacity:s.OUT_BUFFER_SIZE},t.debugBufferUsed={bytes:t.debugBufferUsedBytes,percentage:t.debugBufferUsedBytes/s.DEBUG_BUFFER_SIZE*100,peakBytes:t.debugBufferPeakBytes,peakPercentage:t.debugBufferPeakBytes/s.DEBUG_BUFFER_SIZE*100,capacity:s.DEBUG_BUFFER_SIZE},delete t.inBufferUsedBytes,delete t.outBufferUsedBytes,delete t.debugBufferUsedBytes,delete t.inBufferPeakBytes,delete t.outBufferPeakBytes,delete t.debugBufferPeakBytes}return t.mode=this.#m,this.#t?.scheduler_slot_count!==void 0&&(t.scsynthSchedulerCapacity=this.#t.scheduler_slot_count),e.driftOffsetMs!==void 0&&(t.driftOffsetMs=e.driftOffsetMs),e.ntpStartTime!==void 0&&(t.ntpStartTime=e.ntpStartTime),e.clockOffsetMs!==void 0&&(t.clockOffsetMs=e.clockOffsetMs),e.audioContextState&&(t.audioContextState=e.audioContextState),e.bufferPoolStats&&(t.bufferPoolUsedBytes=e.bufferPoolStats.used.size,t.bufferPoolAvailableBytes=e.bufferPoolStats.available,t.bufferPoolAllocations=e.bufferPoolStats.used.count),e.loadedSynthDefsCount!==void 0&&(t.loadedSynthDefs=e.loadedSynthDefsCount),e.preschedulerCapacity!==void 0&&(t.preschedulerCapacity=e.preschedulerCapacity),this.#m==="postMessage"&&e.transportMetrics&&Object.assign(t,e.transportMetrics),t}updateMergedArray(e={}){let t=this.#o;if(this.#m==="postMessage"){if(e.preschedulerMetrics&&this.overlayPreschedulerMetrics(e.preschedulerMetrics),this.#a){let a=new Uint32Array(this.#a,0,46);t.set(a)}e.transportMetrics&&(e.transportMetrics.oscOutMessagesSent!==void 0&&(t[24]=e.transportMetrics.oscOutMessagesSent),e.transportMetrics.oscOutBytesSent!==void 0&&(t[25]=e.transportMetrics.oscOutBytesSent),e.transportMetrics.preschedulerBypassed!==void 0&&(t[22]=e.transportMetrics.preschedulerBypassed),e.transportMetrics.bypassNonBundle!==void 0&&(t[38]=e.transportMetrics.bypassNonBundle),e.transportMetrics.bypassImmediate!==void 0&&(t[39]=e.transportMetrics.bypassImmediate),e.transportMetrics.bypassNearFuture!==void 0&&(t[40]=e.transportMetrics.bypassNearFuture),e.transportMetrics.bypassLate!==void 0&&(t[41]=e.transportMetrics.bypassLate))}else this.#s&&t.set(this.#s);let s=this.#c;s.setInt32(46*4,e.driftOffsetMs??0,!0),s.setInt32(47*4,e.clockOffsetMs??0,!0);let r=e.audioContextState||"unknown",n={unknown:0,running:1,suspended:2,closed:3,interrupted:4};t[48]=n[r]??0,e.bufferPoolStats&&(t[49]=e.bufferPoolStats.used?.size??0,t[50]=e.bufferPoolStats.available??0,t[51]=e.bufferPoolStats.used?.count??0),t[52]=e.loadedSynthDefsCount??0;let o=this.#t;t[53]=o?.scheduler_slot_count??0,t[54]=e.preschedulerCapacity??0,t[55]=o?.IN_BUFFER_SIZE??0,t[56]=o?.OUT_BUFFER_SIZE??0,t[57]=o?.DEBUG_BUFFER_SIZE??0,t[58]=this.#m==="sab"?0:1}getMergedArray(){return this.#o}get bufferConstants(){return this.#t}get ringBufferBase(){return this.#e}get sharedBuffer(){return this.#i}};function K(i){return i/1e3+2208988800}function _e(i,e){return i-e}function lt(i,e){let t=i-e;return Math.round(t*1e3)}var Q=class{#i;#e;#t;#m;#n;#s;#u;#a;#o;#c=0;#f=0;#p=null;constructor(e={}){this.#i=e.mode||"sab",this.#e=e.audioContext,this.#t=e.workletPort||null}initSharedViews(e,t,s){this.#n=t,this.#m=s,this.#i==="sab"&&e&&s&&(this.#s=new Float64Array(e,t+s.NTP_START_TIME_START,1),this.#u=new Int32Array(e,t+s.DRIFT_OFFSET_START,1),this.#a=new Int32Array(e,t+s.GLOBAL_OFFSET_START,1))}setWorkletPort(e){this.#t=e}updateAudioContext(e){this.#e=e}async initialize(){if(!this.#e)return;let e;for(;e=this.#e.getOutputTimestamp(),!(e.contextTime>0);)await new Promise(o=>setTimeout(o,50));e=this.#e.getOutputTimestamp();let t=performance.timeOrigin+e.performanceTime,s=K(t),r=e.contextTime,n=_e(s,r);this.#i==="sab"&&this.#s?this.#s[0]=n:this.#t&&this.#t.postMessage({type:"setNTPStartTime",ntpStartTime:n}),this.#o=n,await new Promise(o=>setTimeout(o,500)),this.updateDriftOffset()}updateDriftOffset(){if(!this.#e||this.#o===void 0)return;let e=this.#e.getOutputTimestamp(),t=performance.timeOrigin+e.performanceTime,r=K(t)-this.#o,n=lt(r,e.contextTime);this.#c=n,this.#i==="sab"&&this.#u?Atomics.store(this.#u,0,n):this.#t&&this.#t.postMessage({type:"setDriftOffset",driftOffsetMs:n})}resync(){if(!this.#e)return;let e=this.#e.getOutputTimestamp();if(!e||e.contextTime<=0)return;let t=performance.timeOrigin+e.performanceTime,s=K(t),r=_e(s,e.contextTime);this.#i==="sab"&&this.#s?this.#s[0]=r:this.#t&&this.#t.postMessage({type:"setNTPStartTime",ntpStartTime:r}),this.#o=r,this.updateDriftOffset()}startDriftTimer(){this.stopDriftTimer(),this.#p=setInterval(()=>{this.updateDriftOffset()},1e3)}stopDriftTimer(){this.#p&&(clearInterval(this.#p),this.#p=null)}getDriftOffset(){return this.#u?Atomics.load(this.#u,0):this.#c}getNTPStartTime(){return this.#s?this.#s[0]:this.#o??0}getClockOffset(){return this.#a?Atomics.load(this.#a,0):this.#f}setClockOffset(e){let t=Math.round(e*1e3);this.#f=t,this.#i==="sab"&&this.#a?Atomics.store(this.#a,0,t):this.#t&&this.#t.postMessage({type:"setClockOffset",clockOffsetMs:t})}calculateBundleWait(e){if(e.length<16||String.fromCharCode.apply(null,e.slice(0,8))!=="#bundle\0")return null;let s=this.getNTPStartTime();if(s===0)return console.warn("[NTPTiming] NTP start time not yet initialized"),null;let n=this.getDriftOffset()/1e3,a=this.getClockOffset()/1e3,c=s+n+a,l=new DataView(e.buffer,e.byteOffset),u=l.getUint32(8,!1),f=l.getUint32(12,!1);if(u===0&&(f===0||f===1))return null;let S=u+f/4294967296-c,m=this.#e?.currentTime??0;return{audioTimeS:S,currentTimeS:m}}reset(){this.stopDriftTimer(),this.#o=void 0,this.#c=0,this.#f=0,this.#s=null,this.#u=null,this.#a=null}};var j=class{#i;#e;#t;constructor(e={}){this.#i=e.sharedBuffer||null,this.#e=e.bufferConstants||null,this.#t=e.ringBufferBase||0}update(e,t,s){this.#i=e,this.#t=t,this.#e=s}isAvailable(){return!!(this.#i&&this.#e)}start(){if(!this.isAvailable())throw new Error("AudioCapture not initialized");let e=this.#e,t=this.#t+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#i,t,4);Atomics.store(s,1,0),Atomics.store(s,0,1)}stop(){if(!this.isAvailable())throw new Error("AudioCapture not initialized");let e=this.#e,t=this.#t+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#i,t,4);Atomics.store(s,0,0);let r=Atomics.load(s,1),n=s[2],o=s[3],a=t+e.AUDIO_CAPTURE_HEADER_SIZE,c=new Float32Array(this.#i,a,r*o),l=new Float32Array(r),u=o>1?new Float32Array(r):null;for(let f=0;f<r;f++)l[f]=c[f*o],u&&(u[f]=c[f*o+1]);return{sampleRate:n,channels:o,frames:r,left:l,right:u}}isEnabled(){if(!this.isAvailable())return!1;let e=this.#e,t=this.#t+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#i,t,1);return Atomics.load(s,0)===1}getFrameCount(){if(!this.isAvailable())return 0;let e=this.#e,t=this.#t+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#i,t,2);return Atomics.load(s,1)}getMaxDuration(){if(!this.#e)return 0;let e=this.#e;return e.AUDIO_CAPTURE_FRAMES/(e.AUDIO_CAPTURE_SAMPLE_RATE||48e3)}};function ut(i,e,t){let s=t,r=new Uint32Array(i,e,3),n=r[0],o=r[1],a=r[2],c=e+s.NODE_TREE_HEADER_SIZE,l=s.NODE_TREE_MIRROR_MAX_NODES,u=s.NODE_TREE_ENTRY_SIZE,f=s.NODE_TREE_DEF_NAME_SIZE,h=new DataView(i,c,l*u),S=new TextDecoder("utf-8"),m=[],g=0;for(let p=0;p<l&&g<n;p++){let y=p*u,_=h.getInt32(y,!0);if(_===-1)continue;g++;let d=c+y+24,w=new Uint8Array(i,d,f),oe=new Uint8Array(f);oe.set(w);let ae=oe.indexOf(0);ae===-1&&(ae=f);let At=S.decode(oe.subarray(0,ae));m.push({id:_,parentId:h.getInt32(y+4,!0),isGroup:h.getInt32(y+8,!0)===1,prevId:h.getInt32(y+12,!0),nextId:h.getInt32(y+16,!0),headId:h.getInt32(y+20,!0),defName:At})}return{nodeCount:n,version:o,droppedCount:a,nodes:m}}var Ue=new Uint8Array(2097152),ft=new DataView(Ue.buffer),E=Ue,b=ft,be=new Map,zs=1e3,Ys=new TextDecoder,Gs=new TextEncoder,Ie=2208988800,te=4294967296,De=new Uint8Array([35,98,117,110,100,108,101,0]),ht=44,Ae=105,Be=102,we=115,Me=98,Ce=84,Re=70,dt=104,pt=100,mt=116;function J(i,e){let t=i.length+4;t+=e.length+4;for(let s of e)if(s instanceof Uint8Array)t+=4+s.length+3;else if(s instanceof ArrayBuffer)t+=4+s.byteLength+3;else if(typeof s=="string")t+=s.length*3+4;else if(s&&s.type==="string")t+=s.value.length*3+4;else if(s&&s.type==="blob"){let r=s.value,n=r instanceof Uint8Array?r.length:r.byteLength;t+=4+n+3}else t+=8;return t}function yt(i){let e=16;for(let t of i)e+=4,Array.isArray(t)?e+=J(t[0],t.slice(1)):t.packets!==void 0?e+=yt(t.packets):e+=J(t.address,t.args||[]);return e}function Le(i){if(i<=2097152){E=Ue,b=ft;return}E=new Uint8Array(i),b=new DataView(E.buffer)}function Et(i,e=[]){let t=J(i,e);Le(t);let s=0;s=Pe(i,s),s=ke(e,s);for(let r=0;r<e.length;r++)s=se(e[r],s);return E.subarray(0,s)}function St(i,e){let t=yt(e);Le(t);let s=0;E.set(De,s),s+=8,s=re(i,s);for(let r=0;r<e.length;r++){let n=e[r],o=s;s+=4;let a=s;Array.isArray(n)?s=ee(n[0],n.slice(1),s):n.packets!==void 0?s=_t(n.timeTag,n.packets,s):s=ee(n.address,n.args||[],s);let c=s-a;b.setUint32(o,c,!1)}return E.subarray(0,s)}function gt(i,e,t=[]){let s=20+J(e,t);Le(s);let r=0;E.set(De,r),r+=8,r=re(i,r);let n=r;r+=4;let o=r;r=Pe(e,r),r=ke(t,r);for(let a=0;a<t.length;a++)r=se(t[a],r);return b.setUint32(n,r-o,!1),E.subarray(0,r)}function ee(i,e,t){t=Pe(i,t),t=ke(e,t);for(let s=0;s<e.length;s++)t=se(e[s],t);return t}function _t(i,e,t){E.set(De,t),t+=8,t=re(i,t);for(let s=0;s<e.length;s++){let r=e[s],n=t;t+=4;let o=t;Array.isArray(r)?t=ee(r[0],r.slice(1),t):r.packets!==void 0?t=_t(r.timeTag,r.packets,t):t=ee(r.address,r.args||[],t),b.setUint32(n,t-o,!1)}return t}function Pe(i,e){let t=be.get(i);if(t)return E.set(t,e),e+t.length;let s=e;if(e=Oe(i,e),be.size<zs){let r=E.slice(s,e);be.set(i,r)}return e}function Oe(i,e){let t=!1;for(let s=0;s<i.length;s++)if(i.charCodeAt(s)>=128){t=!0;break}if(t){let s=Gs.encodeInto(i,E.subarray(e));e+=s.written}else for(let s=0;s<i.length;s++)E[e++]=i.charCodeAt(s);for(E[e++]=0;e&3;)E[e++]=0;return e}function ke(i,e){E[e++]=ht;for(let t=0;t<i.length;t++){let s=i[t],r=typeof s;if(r==="number")E[e++]=Number.isInteger(s)?Ae:Be;else if(r==="string")E[e++]=we;else if(r==="boolean")E[e++]=s?Ce:Re;else if(s instanceof Uint8Array||s instanceof ArrayBuffer)E[e++]=Me;else if(s&&s.type==="int")E[e++]=Ae;else if(s&&s.type==="float")E[e++]=Be;else if(s&&s.type==="string")E[e++]=we;else if(s&&s.type==="blob")E[e++]=Me;else if(s&&s.type==="bool")E[e++]=s.value?Ce:Re;else if(s&&s.type==="int64")E[e++]=dt;else if(s&&s.type==="double")E[e++]=pt;else if(s&&s.type==="timetag")E[e++]=mt;else throw s==null?new Error(`OSC argument at index ${t} is ${s}`):new Error(`Unknown OSC argument type at index ${t}: ${r}`)}for(E[e++]=0;e&3;)E[e++]=0;return e}function se(i,e){let t=typeof i;if(t==="number")return Number.isInteger(i)?(b.setInt32(e,i,!1),e+4):(b.setFloat32(e,i,!1),e+4);if(t==="string")return Oe(i,e);if(t==="boolean")return e;if(i instanceof Uint8Array){let s=i.length;for(b.setUint32(e,s,!1),e+=4,E.set(i,e),e+=s;e&3;)E[e++]=0;return e}if(i instanceof ArrayBuffer)return se(new Uint8Array(i),e);if(i&&i.type==="int")return b.setInt32(e,i.value,!1),e+4;if(i&&i.type==="float")return b.setFloat32(e,i.value,!1),e+4;if(i&&i.type==="string")return Oe(i.value,e);if(i&&i.type==="blob"){let s=i.value instanceof Uint8Array?i.value:new Uint8Array(i.value),r=s.length;for(b.setUint32(e,r,!1),e+=4,E.set(s,e),e+=r;e&3;)E[e++]=0;return e}return i&&i.type==="bool"?e:i&&i.type==="int64"?(b.setBigInt64(e,BigInt(i.value),!1),e+8):i&&i.type==="double"?(b.setFloat64(e,i.value,!1),e+8):i&&i.type==="timetag"?re(i.value,e):e}function re(i,e){if(i===1||i===null||i===void 0)return b.setUint32(e,0,!1),b.setUint32(e+4,1,!1),e+8;if(Array.isArray(i)){if(i.length!==2)throw new Error(`TimeTag array must have exactly 2 elements [seconds, fraction], got ${i.length}`);return b.setUint32(e,i[0]>>>0,!1),b.setUint32(e+4,i[1]>>>0,!1),e+8}if(typeof i!="number")throw new TypeError(`TimeTag must be a number, array, null, or undefined, got ${typeof i}`);i>1&&i<Ie&&console.warn(`TimeTag ${i} looks like a Unix timestamp (< NTP_EPOCH_OFFSET). Did you mean to add NTP_EPOCH_OFFSET (2208988800)?`);let t=i>>>0,s=(i-Math.floor(i))*te>>>0;return b.setUint32(e,t,!1),b.setUint32(e+4,s,!1),e+8}function ie(i){return i instanceof Uint8Array||(i=new Uint8Array(i)),i[0]===35&&i[1]===98?Ws(i):$s(i)}function $s(i){i instanceof Uint8Array||(i=new Uint8Array(i));let e=new DataView(i.buffer,i.byteOffset,i.byteLength),t=0,[s,r]=Te(i,t);if(t=r,t>=i.length||i[t]!==ht)return[s];let[n,o]=Te(i,t);t=o;let a=[s];for(let c=1;c<n.length;c++)switch(n.charCodeAt(c)){case Ae:a.push(e.getInt32(t,!1)),t+=4;break;case Be:a.push(e.getFloat32(t,!1)),t+=4;break;case we:let[u,f]=Te(i,t);a.push(u),t=f;break;case Me:let h=e.getUint32(t,!1);t+=4,a.push(i.slice(t,t+h)),t+=h,t=t+3&-4;break;case dt:a.push(e.getBigInt64(t,!1)),t+=8;break;case pt:a.push(e.getFloat64(t,!1)),t+=8;break;case Ce:a.push(!0);break;case Re:a.push(!1);break;case mt:let S=e.getUint32(t,!1),m=e.getUint32(t+4,!1);a.push(S+m/te),t+=8;break}return a}function Ws(i){i instanceof Uint8Array||(i=new Uint8Array(i));let e=new DataView(i.buffer,i.byteOffset,i.byteLength),t=8,s=e.getUint32(t,!1),r=e.getUint32(t+4,!1),n=s+r/te;t+=8;let o=[];for(;t<i.length;){let a=e.getUint32(t,!1);if(t+=4,a>0&&t+a<=i.length){let c=i.subarray(t,t+a);o.push(ie(c))}t+=a}return{timeTag:n,packets:o}}function Te(i,e){let t=e;for(;t<i.length&&i[t]!==0;)t++;let s=Ys.decode(i.subarray(e,t));return t++,t=t+3&-4,[s,t]}function ne(i){return i.slice()}function Vs(i){return!i||i.length<8?!1:i[0]===35&&i[1]===98}function Fe(i){if(!Vs(i))return null;let e=new DataView(i.buffer,i.byteOffset,i.byteLength),t=e.getUint32(8,!1),s=e.getUint32(12,!1);return t+s/te}var bt={totalPages:1280,ringBufferReserved:3145728,bufferPoolOffset:19922944,bufferPoolSize:63963136,get totalMemory(){return this.bufferPoolOffset+this.bufferPoolSize},get wasmHeapSize(){return this.bufferPoolOffset-this.ringBufferReserved}};var Tt={numBuffers:1024,maxNodes:1024,maxGraphDefs:1024,maxWireBufs:64,numAudioBusChannels:128,numInputBusChannels:2,numOutputBusChannels:2,numControlBusChannels:4096,bufLength:128,realTimeMemorySize:8192,numRGens:64,realTime:!1,memoryLocking:!1,loadGraphDefs:0,preferredSampleRate:0,verbosity:0};var Qs=new Set(["/b_alloc","/b_allocRead","/b_allocReadChannel","/b_allocFile"]),xe=class i{static osc={encodeMessage:(e,t)=>ne(Et(e,t)),encodeBundle:(e,t)=>ne(St(e,t)),decode:e=>ie(e),encodeSingleBundle:(e,t,s)=>ne(gt(e,t,s)),readTimetag:e=>le(e),ntpNow:()=>T(),NTP_EPOCH_OFFSET:Ie};static#i=null;static getMetricsSchema(){return this.#i??={metrics:{scsynthProcessCount:{offset:0,type:"counter",unit:"count",description:"Audio process() calls"},scsynthMessagesProcessed:{offset:1,type:"counter",unit:"count",description:"OSC messages processed by scsynth"},scsynthMessagesDropped:{offset:2,type:"counter",unit:"count",description:"Messages dropped (ring buffer full)"},scsynthSchedulerDepth:{offset:3,type:"gauge",unit:"count",description:"Current scheduler queue depth"},scsynthSchedulerPeakDepth:{offset:4,type:"gauge",unit:"count",description:"Peak scheduler queue depth (high water mark)"},scsynthSchedulerDropped:{offset:5,type:"counter",unit:"count",description:"Scheduled events dropped"},scsynthSequenceGaps:{offset:6,type:"counter",unit:"count",description:"Messages lost in transit from JS to scsynth"},scsynthWasmErrors:{offset:7,type:"counter",unit:"count",description:"WASM execution errors in audio worklet"},scsynthSchedulerLates:{offset:8,type:"counter",unit:"count",description:"Bundles executed after their scheduled time"},preschedulerPending:{offset:9,type:"gauge",unit:"count",description:"Events waiting to be scheduled"},preschedulerPendingPeak:{offset:10,type:"gauge",unit:"count",description:"Peak pending events"},preschedulerBundlesScheduled:{offset:11,type:"counter",unit:"count",description:"Bundles scheduled"},preschedulerDispatched:{offset:12,type:"counter",unit:"count",description:"Events sent to worklet"},preschedulerEventsCancelled:{offset:13,type:"counter",unit:"count",description:"Events cancelled"},preschedulerMinHeadroomMs:{offset:14,type:"gauge",unit:"ms",description:"Smallest time gap between JS prescheduler dispatch and scsynth scheduler execution"},preschedulerLates:{offset:15,type:"counter",unit:"count",description:"Bundles dispatched after their scheduled execution time"},preschedulerRetriesSucceeded:{offset:16,type:"counter",unit:"count",description:"Retries that succeeded"},preschedulerRetriesFailed:{offset:17,type:"counter",unit:"count",description:"Retries that failed"},preschedulerRetryQueueSize:{offset:18,type:"gauge",unit:"count",description:"Current retry queue size"},preschedulerRetryQueuePeak:{offset:19,type:"gauge",unit:"count",description:"Peak retry queue size"},preschedulerMessagesRetried:{offset:20,type:"counter",unit:"count",description:"Messages that needed retry"},preschedulerTotalDispatches:{offset:21,type:"counter",unit:"count",description:"Total dispatch attempts"},preschedulerBypassed:{offset:22,type:"counter",unit:"count",description:"Messages sent directly from JS to scsynth, bypassing prescheduler (aggregate)"},preschedulerMaxLateMs:{offset:23,type:"gauge",unit:"ms",description:"Maximum lateness at prescheduler (ms)"},oscOutMessagesSent:{offset:24,type:"counter",unit:"count",description:"OSC messages sent from JS to scsynth"},oscOutBytesSent:{offset:25,type:"counter",unit:"bytes",description:"Total bytes sent from JS to scsynth"},oscInMessagesReceived:{offset:26,type:"counter",unit:"count",description:"OSC replies received from scsynth to JS"},oscInBytesReceived:{offset:27,type:"counter",unit:"bytes",description:"Total bytes received from scsynth to JS"},oscInMessagesDropped:{offset:28,type:"counter",unit:"count",description:"Replies lost in transit from scsynth to JS"},oscInCorrupted:{offset:29,type:"counter",unit:"count",description:"Corrupted messages detected from scsynth to JS"},debugMessagesReceived:{offset:30,type:"counter",unit:"count",description:"Debug messages from scsynth"},debugBytesReceived:{offset:31,type:"counter",unit:"bytes",description:"Debug bytes received"},inBufferUsedBytes:{offset:32,type:"gauge",unit:"bytes",description:"Bytes used in IN ring buffer"},outBufferUsedBytes:{offset:33,type:"gauge",unit:"bytes",description:"Bytes used in OUT ring buffer"},debugBufferUsedBytes:{offset:34,type:"gauge",unit:"bytes",description:"Bytes used in DEBUG ring buffer"},inBufferPeakBytes:{offset:35,type:"gauge",unit:"bytes",description:"Peak bytes used in IN ring buffer"},outBufferPeakBytes:{offset:36,type:"gauge",unit:"bytes",description:"Peak bytes used in OUT ring buffer"},debugBufferPeakBytes:{offset:37,type:"gauge",unit:"bytes",description:"Peak bytes used in DEBUG ring buffer"},bypassNonBundle:{offset:38,type:"counter",unit:"count",description:"Plain OSC messages (not bundles) that bypassed prescheduler"},bypassImmediate:{offset:39,type:"counter",unit:"count",description:"Bundles with timetag 0 or 1 that bypassed prescheduler"},bypassNearFuture:{offset:40,type:"counter",unit:"count",description:"Bundles within bypass lookahead threshold that bypassed prescheduler"},bypassLate:{offset:41,type:"counter",unit:"count",description:"Timestamped OSC bundles arriving late into SuperSonic bypassing prescheduler"},scsynthSchedulerMaxLateMs:{offset:42,type:"gauge",unit:"ms",description:"Maximum lateness observed in scsynth scheduler (ms)"},scsynthSchedulerLastLateMs:{offset:43,type:"gauge",unit:"ms",description:"Most recent late magnitude in scsynth scheduler (ms)"},scsynthSchedulerLastLateTick:{offset:44,type:"gauge",unit:"count",description:"Process count when last scsynth late occurred"},ringBufferDirectWriteFails:{offset:45,type:"counter",unit:"count",description:"SAB mode only: optimistic direct writes attempted but failed due to ring buffer lock not being available (delivered via prescheduler instead)"},driftOffsetMs:{offset:46,type:"gauge",unit:"ms",signed:!0,description:"Clock drift between AudioContext and wall clock"},clockOffsetMs:{offset:47,type:"gauge",unit:"ms",signed:!0,description:"Clock offset for multi-system sync"},audioContextState:{offset:48,type:"enum",values:["unknown","running","suspended","closed","interrupted"],description:"AudioContext state"},bufferPoolUsedBytes:{offset:49,type:"gauge",unit:"bytes",description:"Buffer pool bytes used"},bufferPoolAvailableBytes:{offset:50,type:"gauge",unit:"bytes",description:"Buffer pool bytes available"},bufferPoolAllocations:{offset:51,type:"counter",unit:"count",description:"Total buffer allocations"},loadedSynthDefs:{offset:52,type:"gauge",unit:"count",description:"Number of loaded synthdefs"},scsynthSchedulerCapacity:{offset:53,type:"constant",unit:"count",description:"Maximum scheduler queue size"},preschedulerCapacity:{offset:54,type:"constant",unit:"count",description:"Maximum pending events in prescheduler"},inBufferCapacity:{offset:55,type:"constant",unit:"bytes",description:"IN ring buffer capacity"},outBufferCapacity:{offset:56,type:"constant",unit:"bytes",description:"OUT ring buffer capacity"},debugBufferCapacity:{offset:57,type:"constant",unit:"bytes",description:"DEBUG ring buffer capacity"},mode:{offset:58,type:"enum",values:["sab","postMessage"],description:"Transport mode"}},layout:{panels:[{title:"OSC Out",rows:[{label:"sent",cells:[{key:"oscOutMessagesSent"}]},{label:"bytes",cells:[{key:"oscOutBytesSent",kind:"muted",format:"bytes"}]},{label:"bypass",cells:[{key:"preschedulerBypassed",kind:"green"}]},{label:"lost",cells:[{key:"scsynthSequenceGaps",kind:"error"}]}]},{title:"Bypass",rows:[{label:"msg",cells:[{key:"bypassNonBundle",kind:"muted"}]},{label:"imm",cells:[{key:"bypassImmediate",kind:"muted"}]},{label:"near",cells:[{key:"bypassNearFuture",kind:"muted"}]},{label:"late",cells:[{key:"bypassLate",kind:"muted"}]}]},{title:"OSC In",rows:[{label:"received",cells:[{key:"oscInMessagesReceived"}]},{label:"bytes",cells:[{key:"oscInBytesReceived",kind:"muted",format:"bytes"}]},{label:"dropped",cells:[{key:"oscInMessagesDropped",kind:"error"}]},{label:"corrupted",cells:[{key:"oscInCorrupted",kind:"error"}]}]},{title:"Presched Flow",rows:[{label:"pending",cells:[{key:"preschedulerPending"},{sep:" | "},{key:"preschedulerPendingPeak",kind:"muted"}]},{label:"scheduled",cells:[{key:"preschedulerBundlesScheduled"}]},{label:"dispatched",cells:[{key:"preschedulerDispatched",kind:"dim"}]},{label:"min slack",cells:[{key:"preschedulerMinHeadroomMs",kind:"dim",format:"headroom"},{text:" ms",kind:"muted"}]}]},{title:"Presched Health",rows:[{label:"lates",cells:[{key:"preschedulerLates",kind:"error"},{sep:" ("},{key:"preschedulerMaxLateMs",kind:"dim"},{text:"ms max)",kind:"muted"}]},{label:"cancelled",cells:[{key:"preschedulerEventsCancelled",kind:"error"}]},{label:"retried",cells:[{key:"preschedulerMessagesRetried",kind:"dim"},{sep:" | "},{key:"preschedulerRetriesSucceeded",kind:"green"},{sep:" | "},{key:"preschedulerRetriesFailed",kind:"error"}]},{label:"retry queue",cells:[{key:"preschedulerRetryQueueSize"},{sep:" | "},{key:"preschedulerRetryQueuePeak",kind:"muted"}]}]},{title:"scsynth Scheduler",rows:[{label:"queue",cells:[{key:"scsynthSchedulerDepth"},{sep:" | "},{key:"scsynthSchedulerPeakDepth",kind:"muted"}]},{label:"dropped",cells:[{key:"scsynthSchedulerDropped",kind:"error"}]},{label:"lates",cells:[{key:"scsynthSchedulerLates",kind:"error"}]},{label:"max | last",cells:[{key:"scsynthSchedulerMaxLateMs",kind:"error"},{sep:" | "},{key:"scsynthSchedulerLastLateMs",kind:"dim"},{text:" ms",kind:"muted"}]}]},{title:"scsynth",rows:[{label:"processed",cells:[{key:"scsynthMessagesProcessed"}]},{label:"dropped",cells:[{key:"scsynthMessagesDropped",kind:"error"}]},{label:"synthdefs",cells:[{key:"loadedSynthDefs"}]},{label:"clock drift",cells:[{key:"driftOffsetMs",format:"signed"},{text:"ms",kind:"muted"}]}]},{title:"Ring Buffer Level",class:"wide",rows:[{type:"bar",label:"in",usedKey:"inBufferUsedBytes",peakKey:"inBufferPeakBytes",capacityKey:"inBufferCapacity",color:"blue"},{type:"bar",label:"out",usedKey:"outBufferUsedBytes",peakKey:"outBufferPeakBytes",capacityKey:"outBufferCapacity",color:"green"},{type:"bar",label:"dbg",usedKey:"debugBufferUsedBytes",peakKey:"debugBufferPeakBytes",capacityKey:"debugBufferCapacity",color:"purple"},{label:"direct write fails",cells:[{key:"ringBufferDirectWriteFails",kind:"error"}]}]},{title:"AudioWorklet",rows:[{label:"audio",cells:[{key:"audioContextState",kind:"green",format:"enum"}]},{label:"ticks",cells:[{key:"scsynthProcessCount",kind:"dim"}]},{label:"WASM errors",cells:[{key:"scsynthWasmErrors",kind:"error"}]},{label:"debug",cells:[{key:"debugMessagesReceived",kind:"muted"},{text:" ("},{key:"debugBytesReceived",kind:"muted",format:"bytes"},{text:")"}]}]},{title:"Audio Buffers",rows:[{label:"used",cells:[{key:"bufferPoolUsedBytes",format:"bytes"}]},{label:"free",cells:[{key:"bufferPoolAvailableBytes",kind:"green",format:"bytes"}]},{label:"allocs",cells:[{key:"bufferPoolAllocations",kind:"dim"}]}]}]},sentinels:{HEADROOM_UNSET:4294967295}}}static getTreeSchema(){return{nodeCount:{type:"number",description:"Total nodes in tree"},version:{type:"number",description:"Increments on any tree change, useful for detecting updates"},droppedCount:{type:"number",description:"Nodes that exceeded mirror capacity (tree may be incomplete)"},root:{type:"object",description:"Root node of the tree (always a group with id 0)",schema:{id:{type:"number",description:"Unique node ID"},type:{type:"string",values:["group","synth"],description:"Node type"},defName:{type:"string",description:"Synthdef name (synths only, empty for groups)"},children:{type:"array",description:"Child nodes (recursive)",itemSchema:"(self)"}}}}}static getRawTreeSchema(){return{nodeCount:{type:"number",description:"Total nodes in tree"},version:{type:"number",description:"Increments on any tree change, useful for detecting updates"},droppedCount:{type:"number",description:"Nodes that exceeded mirror capacity (tree may be incomplete)"},nodes:{type:"array",description:"Flat array of all nodes with internal linkage pointers",itemSchema:{id:{type:"number",description:"Unique node ID"},parentId:{type:"number",description:"Parent node ID (-1 for root)"},isGroup:{type:"boolean",description:"True if group, false if synth"},prevId:{type:"number",description:"Previous sibling node ID (-1 if none)"},nextId:{type:"number",description:"Next sibling node ID (-1 if none)"},headId:{type:"number",description:"First child node ID (groups only, -1 if empty)"},defName:{type:"string",description:"Synthdef name (synths only, empty for groups)"}}}}}#e;#t;#m=null;#n;#s;#u;#a;#o;#c;#f;#p;#b;#h;#y;#d;#_;#g;#r;#l;#E;#S;#A;#w;#B=1e3;#M=null;#R=null;#I=0;#O=[];#C=null;#U=Promise.resolve();#Y(e){let t=(s,r,{min:n,max:o,allowZero:a=!0}={})=>{if(typeof r!="number"||!Number.isFinite(r))throw new Error(`scsynthOptions.${s} must be a finite number, got: ${r}`);if(!a&&r===0)throw new Error(`scsynthOptions.${s} must be non-zero, got: ${r}`);if(n!==void 0&&r<n)throw new Error(`scsynthOptions.${s} must be >= ${n}, got: ${r}`);if(o!==void 0&&r>o)throw new Error(`scsynthOptions.${s} must be <= ${o}, got: ${r}`)};if(t("numBuffers",e.numBuffers,{min:1,max:65535}),t("maxNodes",e.maxNodes,{min:1}),t("maxGraphDefs",e.maxGraphDefs,{min:1}),t("maxWireBufs",e.maxWireBufs,{min:1}),t("numAudioBusChannels",e.numAudioBusChannels,{min:1}),t("numInputBusChannels",e.numInputBusChannels,{min:0}),t("numOutputBusChannels",e.numOutputBusChannels,{min:1,max:128}),t("numControlBusChannels",e.numControlBusChannels,{min:1}),e.bufLength!==128)throw new Error(`scsynthOptions.bufLength must be 128 (WebAudio API constraint), got: ${e.bufLength}`);if(t("realTimeMemorySize",e.realTimeMemorySize,{min:1}),t("numRGens",e.numRGens,{min:1}),typeof e.realTime!="boolean")throw new Error(`scsynthOptions.realTime must be a boolean, got: ${typeof e.realTime}`);if(typeof e.memoryLocking!="boolean")throw new Error(`scsynthOptions.memoryLocking must be a boolean, got: ${typeof e.memoryLocking}`);if(e.loadGraphDefs!==0&&e.loadGraphDefs!==1)throw new Error(`scsynthOptions.loadGraphDefs must be 0 or 1, got: ${e.loadGraphDefs}`);if(t("preferredSampleRate",e.preferredSampleRate,{min:0,max:384e3}),e.preferredSampleRate!==0&&e.preferredSampleRate<8e3)throw new Error(`scsynthOptions.preferredSampleRate must be 0 (auto) or >= 8000, got: ${e.preferredSampleRate}`);t("verbosity",e.verbosity,{min:0,max:4})}constructor(e={}){this.#h=!1,this.#y=!1,this.#d=null,this.#_={},this.#g=null,this.#l=new Z,this.#E=new X({mode:e.mode||"postMessage"}),this.#A=new j({}),this.#e=null,this.#t=null,this.#n=null,this.#u=null,this.loadedSynthDefs=new Map;let t=e.baseURL||null,s=e.coreBaseURL||t,r=e.workerBaseURL||(t?`${t}workers/`:null),n=e.wasmBaseURL||(s?`${s}wasm/`:null);if(!r||!n)throw new Error(`SuperSonic requires explicit URL configuration.
6
6
 
7
7
  For CDN usage:
8
8
  import { SuperSonic } from 'https://unpkg.com/supersonic-scsynth@VERSION/dist/supersonic.js';
@@ -14,6 +14,6 @@ For CDN usage:
14
14
  For local usage:
15
15
  new SuperSonic({ baseURL: '/path/to/supersonic/dist/' })
16
16
 
17
- See: https://github.com/samaaron/supersonic#configuration`);let o={...Mt,...e.scsynthOptions};this.#z(o);let a=e.mode||"postMessage";this.#i={mode:a,snapshotIntervalMs:e.snapshotIntervalMs??150,wasmUrl:e.wasmUrl||n+"scsynth-nrt.wasm",wasmBaseURL:n,workletUrl:e.workletUrl||(s?`${s}workers/scsynth_audio_worklet.js`:r+"scsynth_audio_worklet.js"),workerBaseURL:r,audioContext:e.audioContext||null,autoConnect:e.autoConnect!==!1,audioContextOptions:{latencyHint:"interactive",sampleRate:48e3,...e.audioContextOptions},memory:wt,worldOptions:o,preschedulerCapacity:e.preschedulerCapacity||65536,bypassLookaheadMs:e.bypassLookaheadMs??500,activityEvent:{maxLineLength:e.activityEvent?.maxLineLength??200,scsynthMaxLineLength:e.activityEvent?.scsynthMaxLineLength??null,oscInMaxLineLength:e.activityEvent?.oscInMaxLineLength??null,oscOutMaxLineLength:e.activityEvent?.oscOutMaxLineLength??null},debug:e.debug??!1,debugScsynth:e.debugScsynth??!1,debugOscIn:e.debugOscIn??!1,debugOscOut:e.debugOscOut??!1,activityConsoleLog:{maxLineLength:e.activityConsoleLog?.maxLineLength??200,scsynthMaxLineLength:e.activityConsoleLog?.scsynthMaxLineLength??null,oscInMaxLineLength:e.activityConsoleLog?.oscInMaxLineLength??null,oscOutMaxLineLength:e.activityConsoleLog?.oscOutMaxLineLength??null}},this.#c=e.sampleBaseURL||(t?`${t}samples/`:null),this.#u=e.synthdefBaseURL||(t?`${t}synthdefs/`:null),this.#p={maxRetries:e.fetchMaxRetries??3,baseDelay:e.fetchRetryDelay??1e3},this.#_=new K({onLoadingEvent:(c,l)=>this.#f.emit(c,l),maxRetries:this.#p.maxRetries,baseDelay:this.#p.baseDelay}),this.bootStats={initStartTime:null,initDuration:null}}get initialized(){return this.#d}get initializing(){return this.#m}get audioContext(){return this.#e}get mode(){return this.#i.mode}get bufferConstants(){return this.#y.bufferConstants}get ringBufferBase(){return this.#y.ringBufferBase}get sharedBuffer(){return this.#y.sharedBuffer}get node(){return this.#h}get osc(){return this.#n}get initTime(){return this.#E?.getNTPStartTime()??0}on(e,t){return this.#f.on(e,t)}off(e,t){return this.#f.off(e,t),this}once(e,t){return this.#f.once(e,t)}removeAllListeners(e){return this.#f.removeAllListeners(e),this}async init(){if(!this.#d)return this.#S?this.#S:(this.#S=this.#Y(),this.#S)}async#Y(){this.#m=!0,this.bootStats.initStartTime=performance.now();try{this.#W(),this.#V(),this.#I(),this.#q(),this.#D();let e=await this.#L();await this.#P(e),await this.#k(),await this.#F()}catch(e){throw this.#m=!1,this.#S=null,console.error("[SuperSonic] Initialization failed:",e),this.#f.emit("error",e),e}}getMetrics(){return this.#N()}getMetricsArray(){return this.#Q(),this.#y.getMergedArray()}getSnapshot(){let e=this.#N(),t=i.getMetricsSchema()?.metrics||{},s={};for(let[n,o]of Object.entries(e)){let a=t[n];a?.description?s[n]={value:o,description:a.description}:s[n]={value:o}}let r=null;return typeof performance<"u"&&performance.memory&&(r={usedJSHeapSize:performance.memory.usedJSHeapSize,totalJSHeapSize:performance.memory.totalJSHeapSize,jsHeapSizeLimit:performance.memory.jsHeapSizeLimit}),{timestamp:new Date().toISOString(),metrics:s,nodeTree:this.getRawTree(),memory:r}}setClockOffset(e){this.#T("set clock offset"),this.#E?.setClockOffset(e)}async recover(){return this.#d?await this.resume()?!0:await this.reload():!1}async resume(){if(!this.#d||!this.#e)return!1;await this.purge();try{await this.#e.resume()}catch{}this.#E?.startDriftTimer();let e=this.#v();if(e===null){let r=this.#e.state==="running";return r&&(this.#E?.resync(),this.#f.emit("resumed")),r}await new Promise(r=>setTimeout(r,200));let t=this.#v(),s=t!==null&&t>e;return s&&(this.#E?.resync(),this.#f.emit("resumed")),s}async suspend(){if(this.#d){this.#E?.stopDriftTimer();try{await this.#e?.suspend()}catch{}}}async reload(){if(!this.#d)return!1;this.#f.emit("reload:start");let e=new Map(this.loadedSynthDefs),t=this.#l?.getAllocatedBuffers()||[];await this.#G(),await this.#$();for(let[s,r]of e)try{await this.send("/d_recv",r)}catch(n){console.error(`[SuperSonic] Failed to restore synthdef ${s}:`,n)}for(let s of t)try{if(this.#i.mode==="postMessage"&&s.source)s.source.type==="file"&&await this.loadSample(s.bufnum,s.source.path,s.source.startFrame||0,s.source.numFrames||0);else{let r=crypto.randomUUID();await this.send("/b_allocPtr",s.bufnum,s.ptr,s.numFrames,s.numChannels,s.sampleRate,r)}}catch(r){console.error(`[SuperSonic] Failed to restore buffer ${s.bufnum}:`,r)}return(e.size>0||t.length>0)&&await this.sync(),this.#f.emit("reload:complete",{success:!0}),!0}async#G(){this.#E?.stopDriftTimer(),this.#o?.clear(),this.#o=null,this.#n&&(this.#n.cancelAll(),this.#n.dispose(),this.#n=null),this.#t&&(this.#t.disconnect(),this.#t=null),this.#e&&(await this.#e.close(),this.#e=null),this.#d=!1,this.loadedSynthDefs.clear(),this.#S=null,this.#B=null,this.#E?.reset()}async#$(){this.#m=!0,this.bootStats.initStartTime=performance.now();try{this.#I(),this.#l&&this.#l.updateAudioContext(this.#e),this.#D();let e=await this.#L();await this.#P(e),await this.#k(),await this.#F()}catch(e){throw this.#m=!1,this.#S=null,console.error("[SuperSonic] Partial init failed:",e),this.#f.emit("error",e),e}}getRawTree(){if(!this.#d)return{nodeCount:0,version:0,droppedCount:0,nodes:[]};let e=this.#y.bufferConstants;if(!e)return{nodeCount:0,version:0,droppedCount:0,nodes:[]};let t,s;if(this.#i.mode==="postMessage"){let r=this.#y.getSnapshotBuffer();if(!r)return{nodeCount:0,version:0,droppedCount:0,nodes:[]};t=r,s=e.METRICS_SIZE}else{let r=this.#y.sharedBuffer;if(!r)return{nodeCount:0,version:0,droppedCount:0,nodes:[]};t=r,s=this.#y.ringBufferBase+e.NODE_TREE_START}return ht(t,s,e)}getTree(){let e=this.getRawTree(),t=n=>({id:n.id,type:n.isGroup?"group":"synth",defName:n.defName,children:[]}),s=new Map;for(let n of e.nodes)s.set(n.id,t(n));let r=null;for(let n of e.nodes){let o=s.get(n.id);if(n.parentId===-1||n.parentId===0&&n.id===0)r=o;else{let a=s.get(n.parentId);a&&a.children.push(o)}}return{nodeCount:e.nodeCount,version:e.version,droppedCount:e.droppedCount,root:r||{id:0,type:"group",defName:"",children:[]}}}startCapture(){this.#T("start capture"),this.#A.start()}stopCapture(){return this.#T("stop capture"),this.#A.stop()}isCaptureEnabled(){return this.#A.isEnabled()}getCaptureFrames(){return this.#A.getFrameCount()}getMaxCaptureDuration(){return this.#A.getMaxDuration()}send(e,...t){this.#T("send OSC messages");let s={"/d_load":"Use loadSynthDef() or send /d_recv with synthdef bytes instead.","/d_loadDir":"Use loadSynthDef() or send /d_recv with synthdef bytes instead.","/b_read":"Use loadSample() to load audio into a buffer.","/b_readChannel":"Use loadSample() to load audio into a buffer.","/b_write":"Writing audio files is not available in the browser.","/b_close":"Writing audio files is not available in the browser.","/clearSched":"Use purge() to clear both the JS prescheduler and WASM scheduler.","/error":"SuperSonic always enables error notifications so you never miss a /fail message."};if(s[e])throw new Error(`${e} is not supported in SuperSonic. ${s[e]}`);if(e==="/d_recv"){let o=t[0];if(o instanceof Uint8Array||o instanceof ArrayBuffer){let a=o instanceof ArrayBuffer?new Uint8Array(o):o,c=F(a)||"unknown";this.loadedSynthDefs.set(c,a)}}if(e==="/d_free")for(let o of t)typeof o=="string"&&this.loadedSynthDefs.delete(o);else e==="/d_freeAll"&&this.loadedSynthDefs.clear();let r=t.map(o=>o instanceof ArrayBuffer?new Uint8Array(o):o);if(this.#i.debug||this.#i.debugOscOut){let o=this.#i.activityConsoleLog.oscOutMaxLineLength??this.#i.activityConsoleLog.maxLineLength,a=t.map(c=>{if(c instanceof Uint8Array||c instanceof ArrayBuffer)return`<${c.byteLength||c.length} bytes>`;let l=JSON.stringify(c);return l.length>o?l.slice(0,o)+"...":l}).join(", ");console.log(`[OSC \u2192] ${e}${a?" "+a:""}`)}if(rr.has(e)){this.#ee(e,r),this.#te(e,r);return}let n=i.osc.encodeMessage(e,r);this.sendOSC(n)}sendOSC(e,t={}){this.#T("send OSC data");let s=this.#J(e);this.#H(s,t)}cancelTag(e){this.#T("cancel by tag"),this.#n.cancelTag(e)}cancelSession(e){this.#T("cancel by session"),this.#n.cancelSession(e)}cancelSessionTag(e,t){this.#T("cancel by session and tag"),this.#n.cancelSessionTag(e,t)}cancelAll(){this.#T("cancel all scheduled"),this.#n.cancelAll()}async purge(){this.#T("purge");let e=this.#n.cancelAllWithAck(),t=new Promise(s=>{let r=n=>{n.data.type==="clearSchedAck"&&(this.#t.port.removeEventListener("message",r),s())};this.#t.port.addEventListener("message",r),this.#t.port.postMessage({type:"clearSched",ack:!0})});await Promise.all([e,t])}createOscChannel(e={}){return this.#T("create OSC channel"),this.#n.createOscChannel(e)}async loadSynthDef(e){this.#T("load synthdef");let t,s;if(typeof e=="string"){let r;if(this.#j(e))r=e;else{if(!this.#u)throw new Error("synthdefBaseURL not configured.");r=`${this.#u}${e}.scsyndef`}let n=F(r),o=await this.#_.fetch(r,{type:"synthdef",name:n});t=new Uint8Array(o),s=F(t)||n}else if(e instanceof ArrayBuffer||ArrayBuffer.isView(e)){if(t=e instanceof ArrayBuffer?new Uint8Array(e):new Uint8Array(e.buffer,e.byteOffset,e.byteLength),s=F(t),!s)throw new Error("Could not extract synthdef name from binary data. Make sure it's a valid .scsyndef file.")}else if(e instanceof Blob){let r=await e.arrayBuffer();if(t=new Uint8Array(r),s=F(t),!s)throw new Error("Could not extract synthdef name from file. Make sure it's a valid .scsyndef file.")}else throw new Error("loadSynthDef source must be a name, path/URL string, ArrayBuffer, Uint8Array, or File/Blob");return await this.send("/d_recv",t),{name:s,size:t.length}}async loadSynthDefs(e){this.#T("load synthdefs");let t={};return await Promise.all(e.map(async s=>{try{await this.loadSynthDef(s),t[s]={success:!0}}catch(r){t[s]={success:!1,error:r.message}}})),t}async loadSample(e,t,s=0,r=0){this.#T("load samples");let n;if(typeof t=="string")n=await this.#l.prepareFromFile({bufnum:e,path:t,startFrame:s,numFrames:r});else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))n=await this.#l.prepareFromBlob({bufnum:e,blob:t,startFrame:s,numFrames:r});else if(t instanceof Blob){let l=await t.arrayBuffer();n=await this.#l.prepareFromBlob({bufnum:e,blob:l,startFrame:s,numFrames:r})}else throw new Error("loadSample source must be a path/URL string, ArrayBuffer, TypedArray, or File/Blob");await this.send("/b_allocPtr",e,n.ptr,n.numFrames,n.numChannels,n.sampleRate,n.uuid),await n.allocationComplete;let{numFrames:o,numChannels:a,sampleRate:c}=n;return{bufnum:e,hash:n.hash,source:typeof t=="string"?t:null,numFrames:o,numChannels:a,sampleRate:c,duration:c>0?o/c:0}}getLoadedBuffers(){return this.#T("get loaded buffers"),(this.#l?.getAllocatedBuffers()||[]).map(({bufnum:t,numFrames:s,numChannels:r,sampleRate:n,source:o,hash:a})=>({bufnum:t,hash:a||null,source:o?.path||o?.name||null,numFrames:s,numChannels:r,sampleRate:n,duration:n>0?s/n:0}))}async sampleInfo(e,t=0,s=0){this.#T("get sample info");let r;if(typeof e=="string")r=e;else if(e instanceof ArrayBuffer||ArrayBuffer.isView(e))r=e;else if(e instanceof Blob)r=await e.arrayBuffer();else throw new Error("sampleInfo source must be a path/URL string, ArrayBuffer, TypedArray, or File/Blob");return this.#l.sampleInfo({source:r,startFrame:t,numFrames:s})}async sync(e=Math.floor(Math.random()*2147483647)){this.#T("sync"),await this.#se();let t=new Promise((s,r)=>{let n=setTimeout(()=>{this.#o?.delete(e),r(new Error("Timeout waiting for /synced response"))},1e4),o=()=>{clearTimeout(n),this.#o.delete(e),s()};this.#o||(this.#o=new Map),this.#o.set(e,o)});this.send("/sync",e),await t,this.#i.mode==="postMessage"&&await new Promise(s=>setTimeout(s,this.#i.snapshotIntervalMs*2))}getInfo(){return this.#T("get info"),{sampleRate:this.#e.sampleRate,numBuffers:this.#i.worldOptions.numBuffers,totalMemory:this.#i.memory.totalMemory,wasmHeapSize:this.#i.memory.wasmHeapSize,bufferPoolSize:this.#i.memory.bufferPoolSize,bootTimeMs:this.bootStats.initDuration,capabilities:{...this.#b},version:this.#g}}async shutdown(){!this.#d&&!this.#m||(this.#f.emit("shutdown"),this.#E?.stopDriftTimer(),this.#o?.clear(),this.#o=null,this.#n&&(this.#n.cancelAll(),this.#n.dispose(),this.#n=null),this.#t&&(this.#t.disconnect(),this.#t=null),this.#e&&(await this.#e.close(),this.#e=null),this.#l&&(this.#l.destroy(),this.#l=null),this.#a=null,this.#B=null,this.#C=Promise.resolve(),this.#d=!1,this.loadedSynthDefs.clear(),this.#S=null,this.#s=null,this.#E?.reset(),this.bootStats={initStartTime:null,initDuration:null})}async destroy(){this.#f.emit("destroy"),await this.shutdown(),this.#M=null,this.#f.clearAllListeners()}async reset(){await this.shutdown(),await this.init()}#W(){this.#b={audioWorklet:typeof AudioWorklet<"u",sharedArrayBuffer:typeof SharedArrayBuffer<"u",crossOriginIsolated:window.crossOriginIsolated===!0,atomics:typeof Atomics<"u",webWorker:typeof Worker<"u"};let e=this.#i.mode,t=["audioWorklet","webWorker"];e==="sab"&&t.push("sharedArrayBuffer","crossOriginIsolated","atomics");let s=t.filter(r=>!this.#b[r]);if(s.length>0){let r=new Error(`Missing required features for ${e} mode: ${s.join(", ")}`);throw e==="sab"&&!this.#b.crossOriginIsolated&&(r.message+=`
17
+ See: https://github.com/samaaron/supersonic#configuration`);let o={...Tt,...e.scsynthOptions};this.#Y(o);let a=e.mode||"postMessage";this.#r={mode:a,snapshotIntervalMs:e.snapshotIntervalMs??150,wasmUrl:e.wasmUrl||n+"scsynth-nrt.wasm",wasmBaseURL:n,workletUrl:e.workletUrl||(s?`${s}workers/scsynth_audio_worklet.js`:r+"scsynth_audio_worklet.js"),workerBaseURL:r,audioContext:e.audioContext||null,autoConnect:e.autoConnect!==!1,audioContextOptions:{latencyHint:"interactive",sampleRate:48e3,...e.audioContextOptions},memory:bt,worldOptions:o,preschedulerCapacity:e.preschedulerCapacity||65536,bypassLookaheadMs:e.bypassLookaheadMs??500,activityEvent:{maxLineLength:e.activityEvent?.maxLineLength??200,scsynthMaxLineLength:e.activityEvent?.scsynthMaxLineLength??null,oscInMaxLineLength:e.activityEvent?.oscInMaxLineLength??null,oscOutMaxLineLength:e.activityEvent?.oscOutMaxLineLength??null},debug:e.debug??!1,debugScsynth:e.debugScsynth??!1,debugOscIn:e.debugOscIn??!1,debugOscOut:e.debugOscOut??!1,activityConsoleLog:{maxLineLength:e.activityConsoleLog?.maxLineLength??200,scsynthMaxLineLength:e.activityConsoleLog?.scsynthMaxLineLength??null,oscInMaxLineLength:e.activityConsoleLog?.oscInMaxLineLength??null,oscOutMaxLineLength:e.activityConsoleLog?.oscOutMaxLineLength??null}},this.#c=e.sampleBaseURL||(t?`${t}samples/`:null),this.#f=e.synthdefBaseURL||(t?`${t}synthdefs/`:null),this.#p={maxRetries:e.fetchMaxRetries??3,baseDelay:e.fetchRetryDelay??1e3},this.#b=new V({onLoadingEvent:(c,l)=>this.#l.emit(c,l),maxRetries:this.#p.maxRetries,baseDelay:this.#p.baseDelay}),this.bootStats={initStartTime:null,initDuration:null}}get initialized(){return this.#h}get initializing(){return this.#y}get audioContext(){return this.#e}get mode(){return this.#r.mode}get bufferConstants(){return this.#E.bufferConstants}get ringBufferBase(){return this.#E.ringBufferBase}get sharedBuffer(){return this.#E.sharedBuffer}get node(){return this.#m}get osc(){return this.#n}get initTime(){return this.#S?.getNTPStartTime()??0}on(e,t){return this.#l.on(e,t)}off(e,t){return this.#l.off(e,t),this}once(e,t){return this.#l.once(e,t)}removeAllListeners(e){return this.#l.removeAllListeners(e),this}async init(){if(!this.#h)return this.#d?this.#d:(this.#d=this.#G(),this.#d)}async#G(){this.#y=!0,this.bootStats.initStartTime=performance.now();try{this.#V(),this.#q(),this.#D(),this.#Z(),this.#L();let e=await this.#P();await this.#k(e),await this.#F(),await this.#x()}catch(e){throw this.#y=!1,this.#d=null,console.error("[SuperSonic] Initialization failed:",e),this.#l.emit("error",e),e}}getMetrics(){return this.#v()}getMetricsArray(){return this.#j(),this.#E.getMergedArray()}getSnapshot(){let e=this.#v(),t=i.getMetricsSchema()?.metrics||{},s={};for(let[n,o]of Object.entries(e)){let a=t[n];a?.description?s[n]={value:o,description:a.description}:s[n]={value:o}}let r=null;return typeof performance<"u"&&performance.memory&&(r={usedJSHeapSize:performance.memory.usedJSHeapSize,totalJSHeapSize:performance.memory.totalJSHeapSize,jsHeapSizeLimit:performance.memory.jsHeapSizeLimit}),{timestamp:new Date().toISOString(),metrics:s,nodeTree:this.getRawTree(),memory:r}}setClockOffset(e){this.#T("set clock offset"),this.#S?.setClockOffset(e)}async recover(){return this.#h?await this.resume()?!0:await this.reload():!1}async resume(){if(!this.#h||!this.#e)return!1;await this.purge();try{await this.#e.resume()}catch{}this.#S?.startDriftTimer();let e=this.#H();if(e===null){let r=this.#e.state==="running";return r&&(this.#S?.resync(),this.#l.emit("resumed")),r}await new Promise(r=>setTimeout(r,200));let t=this.#H(),s=t!==null&&t>e;return s&&(this.#S?.resync(),this.#l.emit("resumed")),s}async suspend(){if(this.#h){this.#S?.stopDriftTimer();try{await this.#e?.suspend()}catch{}}}async reload(){if(!this.#h)return!1;this.#l.emit("reload:start");let e=new Map(this.loadedSynthDefs),t=this.#u?.getAllocatedBuffers()||[];await this.#$(),await this.#W();for(let[s,r]of e)try{await this.send("/d_recv",r)}catch(n){console.error(`[SuperSonic] Failed to restore synthdef ${s}:`,n)}for(let s of t)try{if(this.#r.mode==="postMessage"&&s.source)s.source.type==="file"&&await this.loadSample(s.bufnum,s.source.path,s.source.startFrame||0,s.source.numFrames||0);else{let r=crypto.randomUUID();await this.send("/b_allocPtr",s.bufnum,s.ptr,s.numFrames,s.numChannels,s.sampleRate,r)}}catch(r){console.error(`[SuperSonic] Failed to restore buffer ${s.bufnum}:`,r)}return(e.size>0||t.length>0)&&await this.sync(),this.#l.emit("reload:complete",{success:!0}),!0}async#$(){this.#S?.stopDriftTimer(),this.#o?.clear(),this.#o=null,this.#n&&(this.#n.cancelAll(),this.#n.dispose(),this.#n=null),this.#t&&(this.#t.disconnect(),this.#t=null),this.#e&&(await this.#e.close(),this.#e=null),this.#h=!1,this.loadedSynthDefs.clear(),this.#d=null,this.#w=null,this.#S?.reset()}async#W(){this.#y=!0,this.bootStats.initStartTime=performance.now();try{this.#D(),this.#u&&this.#u.updateAudioContext(this.#e),this.#L();let e=await this.#P();await this.#k(e),await this.#F(),await this.#x()}catch(e){throw this.#y=!1,this.#d=null,console.error("[SuperSonic] Partial init failed:",e),this.#l.emit("error",e),e}}getRawTree(){if(!this.#h)return{nodeCount:0,version:0,droppedCount:0,nodes:[]};let e=this.#E.bufferConstants;if(!e)return{nodeCount:0,version:0,droppedCount:0,nodes:[]};let t,s;if(this.#r.mode==="postMessage"){let r=this.#E.getSnapshotBuffer();if(!r)return{nodeCount:0,version:0,droppedCount:0,nodes:[]};t=r,s=e.METRICS_SIZE}else{let r=this.#E.sharedBuffer;if(!r)return{nodeCount:0,version:0,droppedCount:0,nodes:[]};t=r,s=this.#E.ringBufferBase+e.NODE_TREE_START}return ut(t,s,e)}getTree(){let e=this.getRawTree(),t=n=>({id:n.id,type:n.isGroup?"group":"synth",defName:n.defName,children:[]}),s=new Map;for(let n of e.nodes)s.set(n.id,t(n));let r=null;for(let n of e.nodes){let o=s.get(n.id);if(n.parentId===-1||n.parentId===0&&n.id===0)r=o;else{let a=s.get(n.parentId);a&&a.children.push(o)}}return{nodeCount:e.nodeCount,version:e.version,droppedCount:e.droppedCount,root:r||{id:0,type:"group",defName:"",children:[]}}}startCapture(){this.#T("start capture"),this.#A.start()}stopCapture(){return this.#T("stop capture"),this.#A.stop()}isCaptureEnabled(){return this.#A.isEnabled()}getCaptureFrames(){return this.#A.getFrameCount()}getMaxCaptureDuration(){return this.#A.getMaxDuration()}send(e,...t){this.#T("send OSC messages");let s={"/d_load":"Use loadSynthDef() or send /d_recv with synthdef bytes instead.","/d_loadDir":"Use loadSynthDef() or send /d_recv with synthdef bytes instead.","/b_read":"Use loadSample() to load audio into a buffer.","/b_readChannel":"Use loadSample() to load audio into a buffer.","/b_write":"Writing audio files is not available in the browser.","/b_close":"Writing audio files is not available in the browser.","/clearSched":"Use purge() to clear both the JS prescheduler and WASM scheduler.","/error":"SuperSonic always enables error notifications so you never miss a /fail message.","/quit":"Use destroy() to shut down SuperSonic."};if(s[e])throw new Error(`${e} is not supported in SuperSonic. ${s[e]}`);if(e==="/d_recv"){let o=t[0];if(o instanceof Uint8Array||o instanceof ArrayBuffer){let a=o instanceof ArrayBuffer?new Uint8Array(o):o,c=F(a)||"unknown";this.loadedSynthDefs.set(c,a)}}if(e==="/d_free")for(let o of t)typeof o=="string"&&this.loadedSynthDefs.delete(o);else e==="/d_freeAll"&&this.loadedSynthDefs.clear();let r=t.map(o=>o instanceof ArrayBuffer?new Uint8Array(o):o);if(this.#r.debug||this.#r.debugOscOut){let o=this.#r.activityConsoleLog.oscOutMaxLineLength??this.#r.activityConsoleLog.maxLineLength,a=t.map(c=>{if(c instanceof Uint8Array||c instanceof ArrayBuffer)return`<${c.byteLength||c.length} bytes>`;let l=JSON.stringify(c);return l.length>o?l.slice(0,o)+"...":l}).join(", ");console.log(`[OSC \u2192] ${e}${a?" "+a:""}`)}if(Qs.has(e)){this.#te(e,r),this.#se(e,r);return}let n=i.osc.encodeMessage(e,r);this.sendOSC(n)}sendOSC(e,t={}){this.#T("send OSC data");let s=this.#ee(e);this.#z(s,t)}cancelTag(e){this.#T("cancel by tag"),this.#n.cancelTag(e)}cancelSession(e){this.#T("cancel by session"),this.#n.cancelSession(e)}cancelSessionTag(e,t){this.#T("cancel by session and tag"),this.#n.cancelSessionTag(e,t)}cancelAll(){this.#T("cancel all scheduled"),this.#n.cancelAll()}async purge(){this.#T("purge");let e=this.#n.cancelAllWithAck(),t=new Promise(s=>{let r=n=>{n.data.type==="clearSchedAck"&&(this.#t.port.removeEventListener("message",r),s())};this.#t.port.addEventListener("message",r),this.#t.port.postMessage({type:"clearSched",ack:!0})});await Promise.all([e,t])}createOscChannel(e={}){return this.#T("create OSC channel"),this.#n.createOscChannel(e)}nextNodeId(){return this.#T("allocate node IDs"),this.#w.nextNodeId()}async loadSynthDef(e){this.#T("load synthdef");let t,s;if(typeof e=="string"){let r;if(this.#J(e))r=e;else{if(!this.#f)throw new Error("synthdefBaseURL not configured.");r=`${this.#f}${e}.scsyndef`}let n=F(r),o=await this.#b.fetch(r,{type:"synthdef",name:n});t=new Uint8Array(o),s=F(t)||n}else if(e instanceof ArrayBuffer||ArrayBuffer.isView(e)){if(t=e instanceof ArrayBuffer?new Uint8Array(e):new Uint8Array(e.buffer,e.byteOffset,e.byteLength),s=F(t),!s)throw new Error("Could not extract synthdef name from binary data. Make sure it's a valid .scsyndef file.")}else if(e instanceof Blob){let r=await e.arrayBuffer();if(t=new Uint8Array(r),s=F(t),!s)throw new Error("Could not extract synthdef name from file. Make sure it's a valid .scsyndef file.")}else throw new Error("loadSynthDef source must be a name, path/URL string, ArrayBuffer, Uint8Array, or File/Blob");return await this.send("/d_recv",t),{name:s,size:t.length}}async loadSynthDefs(e){this.#T("load synthdefs");let t={};return await Promise.all(e.map(async s=>{try{await this.loadSynthDef(s),t[s]={success:!0}}catch(r){t[s]={success:!1,error:r.message}}})),t}async loadSample(e,t,s=0,r=0){this.#T("load samples");let n;if(typeof t=="string")n=await this.#u.prepareFromFile({bufnum:e,path:t,startFrame:s,numFrames:r});else if(t instanceof ArrayBuffer||ArrayBuffer.isView(t))n=await this.#u.prepareFromBlob({bufnum:e,blob:t,startFrame:s,numFrames:r});else if(t instanceof Blob){let l=await t.arrayBuffer();n=await this.#u.prepareFromBlob({bufnum:e,blob:l,startFrame:s,numFrames:r})}else throw new Error("loadSample source must be a path/URL string, ArrayBuffer, TypedArray, or File/Blob");await this.send("/b_allocPtr",e,n.ptr,n.numFrames,n.numChannels,n.sampleRate,n.uuid),await n.allocationComplete;let{numFrames:o,numChannels:a,sampleRate:c}=n;return{bufnum:e,hash:n.hash,source:typeof t=="string"?t:null,numFrames:o,numChannels:a,sampleRate:c,duration:c>0?o/c:0}}getLoadedBuffers(){return this.#T("get loaded buffers"),(this.#u?.getAllocatedBuffers()||[]).map(({bufnum:t,numFrames:s,numChannels:r,sampleRate:n,source:o,hash:a})=>({bufnum:t,hash:a||null,source:o?.path||o?.name||null,numFrames:s,numChannels:r,sampleRate:n,duration:n>0?s/n:0}))}async sampleInfo(e,t=0,s=0){this.#T("get sample info");let r;if(typeof e=="string")r=e;else if(e instanceof ArrayBuffer||ArrayBuffer.isView(e))r=e;else if(e instanceof Blob)r=await e.arrayBuffer();else throw new Error("sampleInfo source must be a path/URL string, ArrayBuffer, TypedArray, or File/Blob");return this.#u.sampleInfo({source:r,startFrame:t,numFrames:s})}async sync(e=Math.floor(Math.random()*2147483647)){this.#T("sync"),await this.#re();let t=new Promise((s,r)=>{let n=setTimeout(()=>{this.#o?.delete(e),r(new Error("Timeout waiting for /synced response"))},1e4),o=()=>{clearTimeout(n),this.#o.delete(e),s()};this.#o||(this.#o=new Map),this.#o.set(e,o)});this.send("/sync",e),await t,this.#r.mode==="postMessage"&&await new Promise(s=>setTimeout(s,this.#r.snapshotIntervalMs*2))}getInfo(){return this.#T("get info"),{sampleRate:this.#e.sampleRate,numBuffers:this.#r.worldOptions.numBuffers,totalMemory:this.#r.memory.totalMemory,wasmHeapSize:this.#r.memory.wasmHeapSize,bufferPoolSize:this.#r.memory.bufferPoolSize,bootTimeMs:this.bootStats.initDuration,capabilities:{...this.#_},version:this.#g}}async shutdown(){!this.#h&&!this.#y||(this.#l.emit("shutdown"),this.#S?.stopDriftTimer(),this.#o?.clear(),this.#o=null,this.#n&&(this.#n.cancelAll(),this.#n.dispose(),this.#n=null),this.#t&&(this.#t.disconnect(),this.#t=null),this.#e&&(await this.#e.close(),this.#e=null),this.#u&&(this.#u.destroy(),this.#u=null),this.#a=null,this.#w=null,this.#U=Promise.resolve(),this.#h=!1,this.loadedSynthDefs.clear(),this.#d=null,this.#s=null,this.#S?.reset(),this.bootStats={initStartTime:null,initDuration:null})}async destroy(){this.#l.emit("destroy"),await this.shutdown(),this.#R=null,this.#l.clearAllListeners()}async reset(){await this.shutdown(),await this.init()}#V(){this.#_={audioWorklet:typeof AudioWorklet<"u",sharedArrayBuffer:typeof SharedArrayBuffer<"u",crossOriginIsolated:window.crossOriginIsolated===!0,atomics:typeof Atomics<"u",webWorker:typeof Worker<"u"};let e=this.#r.mode,t=["audioWorklet","webWorker"];e==="sab"&&t.push("sharedArrayBuffer","crossOriginIsolated","atomics");let s=t.filter(r=>!this.#_[r]);if(s.length>0){let r=new Error(`Missing required features for ${e} mode: ${s.join(", ")}`);throw e==="sab"&&!this.#_.crossOriginIsolated&&(r.message+=`
18
18
 
19
- Consider using mode: 'postMessage' which doesn't require COOP/COEP headers.`),r}if(e!=="sab"&&e!=="postMessage")throw new Error(`Invalid mode: '${e}'. Use 'sab' or 'postMessage'.`)}#V(){let e=this.#i.memory;this.#i.mode==="sab"?this.#s=new WebAssembly.Memory({initial:e.totalPages,maximum:e.totalPages,shared:!0}):this.#s=null}#I(){this.#i.audioContext?this.#e=this.#i.audioContext:this.#e=new AudioContext(this.#i.audioContextOptions),this.#e.addEventListener("statechange",()=>{let e=this.#e?.state;if(!e)return;let t=this.#w;this.#w=e,e==="running"&&(t==="suspended"||t==="interrupted")&&this.#E?.resync(),this.#f.emit("audiocontext:statechange",{state:e}),e==="suspended"?this.#f.emit("audiocontext:suspended"):e==="running"?this.#f.emit("audiocontext:resumed"):e==="interrupted"&&this.#f.emit("audiocontext:interrupted")})}#q(){let e=this.#i.mode==="sab"?this.#s.buffer:null;this.#l=new X({mode:this.#i.mode,audioContext:this.#e,sharedBuffer:e,bufferPoolConfig:{start:this.#i.memory.bufferPoolOffset,size:this.#i.memory.bufferPoolSize},sampleBaseURL:this.#c,maxBuffers:this.#i.worldOptions.numBuffers,assetLoader:this.#_})}#D(){this.#a=new Q({bufferManager:this.#l,getDefaultSampleRate:()=>this.#e?.sampleRate||44100})}async#L(){if(this.#M)return this.#M;let e=this.#i.wasmUrl.split("/").pop();this.#f.emit("loading:start",{type:"wasm",name:e});let t=await fetch(this.#i.wasmUrl);if(!t.ok)throw new Error(`Failed to load WASM: ${t.status} ${t.statusText}`);let s=await t.arrayBuffer();return this.#f.emit("loading:complete",{type:"wasm",name:e,size:s.byteLength}),this.#M=s,s}async#P(e){await Ye(this.#e.audioWorklet,this.#i.workletUrl);let t=this.#i.worldOptions.numOutputBusChannels;if(this.#t=new AudioWorkletNode(this.#e,"scsynth-processor",{numberOfInputs:1,numberOfOutputs:1,outputChannelCount:[t]}),this.#i.autoConnect){let o=this.#e.destination;t>2&&(o.channelCount=Math.min(t,o.maxChannelCount),o.channelInterpretation="discrete"),this.#t.connect(o)}this.#h=this.#Z(),this.#t.port.start(),this.#K();let s=this.#i.mode,r=s==="sab"?this.#s.buffer:null;this.#t.port.postMessage({type:"init",mode:s,sharedBuffer:r,snapshotIntervalMs:this.#i.snapshotIntervalMs});let n={type:"loadWasm",wasmBytes:e,worldOptions:this.#i.worldOptions,sampleRate:this.#e.sampleRate};s==="sab"?n.wasmMemory=this.#s:n.memoryPages=this.#i.memoryPages||1280,this.#t.port.postMessage(n),await this.#X(),this.#l.setWorkletPort(this.#t.port)}#Z(){let e=this.#t;return Object.freeze({connect:(...t)=>e.connect(...t),disconnect:(...t)=>e.disconnect(...t),get context(){return e.context},get numberOfOutputs(){return e.numberOfOutputs},get numberOfInputs(){return e.numberOfInputs},get channelCount(){return e.channelCount},get input(){return e}})}async#k(){let e=this.#i.mode,t=this.#y.bufferConstants,s=this.#y.ringBufferBase,r=this.#y.sharedBuffer,n={workerBaseURL:this.#i.workerBaseURL,preschedulerCapacity:this.#i.preschedulerCapacity,snapshotIntervalMs:this.#i.snapshotIntervalMs,bypassLookaheadS:this.#i.bypassLookaheadMs/1e3,getAudioContextTime:()=>this.#e?.currentTime??0,getNTPStartTime:()=>this.#E?.getNTPStartTime()??0};if(e==="sab"&&(n.sharedBuffer=r,n.ringBufferBase=s,n.bufferConstants=t),this.#n=Xe(e,n),this.#n.onReply((o,a,c)=>{let l=ue(o)||null;this.#f.emit("message:raw",{oscData:o,sequence:a,timestamp:c,scheduledTime:l});try{let u=$(o),f=u[0],h=u.slice(1);if(f==="/supersonic/buffer/freed")this.#l?.handleBufferFreed(h);else if(f==="/supersonic/buffer/allocated")this.#l?.handleBufferAllocated(h);else if(f==="/synced"&&h.length>0){let S=h[0];this.#o?.has(S)&&this.#o.get(S)(u)}if(this.#f.emit("message",u),this.#i.debug||this.#i.debugOscIn){let S=this.#i.activityConsoleLog.oscInMaxLineLength??this.#i.activityConsoleLog.maxLineLength,m=h.map(g=>{let p=JSON.stringify(g);return p.length>S?p.slice(0,S)+"...":p}).join(", ")||"";console.log(`[\u2190 OSC] ${f}${m?" "+m:""}`)}}catch(u){console.error("[SuperSonic] Failed to decode OSC message:",u)}}),this.#n.onDebug(o=>{let a=this.#i.activityEvent.scsynthMaxLineLength??this.#i.activityEvent.maxLineLength;if(a>0&&o.text?.length>a&&(o={...o,text:o.text.slice(0,a)+"..."}),this.#f.emit("debug",o),this.#i.debug||this.#i.debugScsynth){let c=this.#i.activityConsoleLog.scsynthMaxLineLength??this.#i.activityConsoleLog.maxLineLength,l=o.text.length>c?o.text.slice(0,c)+"...":o.text;console.log(`[synth] ${l}`)}}),this.#n.onError((o,a)=>{console.error(`[SuperSonic] ${a} error:`,o),this.#f.emit("error",new Error(`${a}: ${o}`))}),this.#n.onOscLog(o=>{for(let a of o){let c=ue(a.oscData)||null;this.#f.emit("message:sent",{oscData:a.oscData,sourceId:a.sourceId,sequence:a.sequence,timestamp:a.timestamp,scheduledTime:c})}}),e==="sab")await this.#n.initialize();else{if(await this.#n.initialize(this.#t.port),this.#n.setBufferConstants(t),this.#O?.length>0)for(let o of this.#O)this.#n.handleDebugRaw(o);this.#U=o=>this.#n.handleDebugRaw(o),this.#O=[]}this.#B=this.#n.createOscChannel({sourceId:0})}async#F(){this.#d=!0,this.#m=!1,this.bootStats.initDuration=performance.now()-this.bootStats.initStartTime,await this.#f.emitAsync("setup"),this.#f.emit("ready",{capabilities:this.#b,bootStats:this.bootStats})}#X(){return new Promise((e,t)=>{let s=setTimeout(()=>{t(new Error("AudioWorklet initialization timeout"))},5e3),r=async n=>{if(n.data.type==="error"){clearTimeout(s),this.#t.port.removeEventListener("message",r),t(new Error(n.data.error||"AudioWorklet error"));return}if(n.data.type==="initialized")if(clearTimeout(s),this.#t.port.removeEventListener("message",r),n.data.success){let o=n.data.ringBufferBase??0,a=n.data.bufferConstants,c=this.#i.mode==="sab"?this.#s.buffer:null;this.#y.initSharedViews(c,o,a);let l=this.#i.worldOptions?.maxNodes??1024,u=a?.NODE_TREE_MIRROR_MAX_NODES??1024;l>u&&console.warn(`SuperSonic: maxNodes (${l}) exceeds NODE_TREE_MIRROR_MAX_NODES (${u}). The node tree mirror will not show all nodes. Rebuild with NODE_TREE_MIRROR_MAX_NODES=${l} to fix.`),this.#E=new te({mode:this.#i.mode,audioContext:this.#e,workletPort:this.#t.port}),this.#E.initSharedViews(c,o,a),await this.#E.initialize(),this.#E.startDriftTimer(),this.#i.mode==="sab"&&this.#A.update(c,o,a),this.#i.mode==="postMessage"&&n.data.initialSnapshot&&this.#y.updateSnapshot(n.data.initialSnapshot),e()}else t(new Error(n.data.error||"AudioWorklet initialization failed"))};this.#t.port.addEventListener("message",r),this.#t.port.start()})}#K(){this.#t.port.addEventListener("message",e=>{let{data:t}=e;switch(t.type){case"error":console.error("[Worklet] Error:",t.error),this.#f.emit("error",new Error(t.error));break;case"version":this.#g=t.version;break;case"snapshot":t.buffer&&(this.#y.updateSnapshot(t.buffer),this.#R=t.snapshotsSent);break;case"debugRawBatch":this.#U?this.#U(t):this.#O.push(t);break;case"oscLog":t.entries&&this.#n?.handleOscLog&&this.#n.handleOscLog(t.entries);break}})}#x(){return{preschedulerMetrics:this.#n?.getPreschedulerMetrics(),transportMetrics:this.#n?.getMetrics(),driftOffsetMs:this.#E?.getDriftOffset()??0,ntpStartTime:this.#E?.getNTPStartTime()??0,clockOffsetMs:this.#E?.getClockOffset()??0,audioContextState:this.#e?.state||"unknown",bufferPoolStats:this.#l?.getStats(),loadedSynthDefsCount:this.loadedSynthDefs?.size||0,preschedulerCapacity:this.#i.preschedulerCapacity}}#N(){return this.#y.gatherMetrics(this.#x())}#Q(){this.#y.updateMergedArray(this.#x())}#v(){if(this.#i.mode==="sab"){let t=this.#y.getMetricsView();return t?t[0]:null}let e=this.#y.getSnapshotBuffer();return e?new Uint32Array(e,0,1)[0]:null}#T(e="perform this operation"){if(!this.#d)throw new Error(`SuperSonic not initialized. Call init() before attempting to ${e}.`)}#re(e){let s={nonBundle:"bypassNonBundle",immediate:"bypassImmediate",nearFuture:"bypassNearFuture",late:"bypassLate"}[e];s&&this.#y.addMetric(s)}#j(e){return e.includes("/")||e.includes("://")}#J(e){if(e instanceof Uint8Array)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);throw new Error("oscData must be ArrayBuffer or Uint8Array")}#H(e,t={}){let s=this.#B.classify(e);if(q(s))this.#i.mode==="sab"?this.#B.send(e):this.#n.sendImmediate(e,s);else{let r=this.#y.bufferConstants?.scheduler_slot_size;if(r&&e.length>r)throw new Error(`OSC bundle too large to schedule (${e.length} > ${r} bytes). Use immediate timestamp (0 or 1) for large messages, or reduce bundle size.`);this.#n.sendWithOptions(e,t)}}#ee(e,t){let s=(o,a)=>{let c=t[o];if(!Number.isFinite(c))throw new Error(a)},r=(o,a)=>{if(typeof t[o]!="string")throw new Error(a)},n=(o,a)=>{let c=t[o];if(!(c instanceof Uint8Array||c instanceof ArrayBuffer))throw new Error(a)};switch(e){case"/b_alloc":s(0,"/b_alloc requires a buffer number"),s(1,"/b_alloc requires a frame count");break;case"/b_allocRead":s(0,"/b_allocRead requires a buffer number"),r(1,"/b_allocRead requires a file path");break;case"/b_allocReadChannel":s(0,"/b_allocReadChannel requires a buffer number"),r(1,"/b_allocReadChannel requires a file path");break;case"/b_allocFile":s(0,"/b_allocFile requires a buffer number"),n(1,"/b_allocFile requires audio file data as blob");break}}#te(e,t){this.#C=this.#C.then(async()=>{let s=[e,...t],{packet:r}=await this.#a.rewritePacket(s),n=i.osc.encodeMessage(r[0],r.slice(1));this.#H(n)}).catch(s=>{console.error(`[SuperSonic] Buffer command ${e} failed:`,s),this.#f.emit("error",s)})}#se(){return this.#C}};export{A as OscChannel,Ct as SuperSonic,Bt as osc};
19
+ Consider using mode: 'postMessage' which doesn't require COOP/COEP headers.`),r}if(e!=="sab"&&e!=="postMessage")throw new Error(`Invalid mode: '${e}'. Use 'sab' or 'postMessage'.`)}#q(){let e=this.#r.memory;this.#r.mode==="sab"?this.#s=new WebAssembly.Memory({initial:e.totalPages,maximum:e.totalPages,shared:!0}):this.#s=null}#D(){this.#r.audioContext?this.#e=this.#r.audioContext:this.#e=new AudioContext(this.#r.audioContextOptions),this.#e.addEventListener("statechange",()=>{let e=this.#e?.state;if(!e)return;let t=this.#M;this.#M=e,e==="running"&&(t==="suspended"||t==="interrupted")&&this.#S?.resync(),this.#l.emit("audiocontext:statechange",{state:e}),e==="suspended"?this.#l.emit("audiocontext:suspended"):e==="running"?this.#l.emit("audiocontext:resumed"):e==="interrupted"&&this.#l.emit("audiocontext:interrupted")})}#Z(){let e=this.#r.mode==="sab"?this.#s.buffer:null;this.#u=new W({mode:this.#r.mode,audioContext:this.#e,sharedBuffer:e,bufferPoolConfig:{start:this.#r.memory.bufferPoolOffset,size:this.#r.memory.bufferPoolSize},sampleBaseURL:this.#c,maxBuffers:this.#r.worldOptions.numBuffers,assetLoader:this.#b})}#L(){this.#a=new q({bufferManager:this.#u,getDefaultSampleRate:()=>this.#e?.sampleRate||44100})}async#P(){if(this.#R)return this.#R;let e=this.#r.wasmUrl.split("/").pop();this.#l.emit("loading:start",{type:"wasm",name:e});let t=await fetch(this.#r.wasmUrl);if(!t.ok)throw new Error(`Failed to load WASM: ${t.status} ${t.statusText}`);let s=await t.arrayBuffer();return this.#l.emit("loading:complete",{type:"wasm",name:e,size:s.byteLength}),this.#R=s,s}async#k(e){await He(this.#e.audioWorklet,this.#r.workletUrl);let t=this.#r.worldOptions.numOutputBusChannels;if(this.#t=new AudioWorkletNode(this.#e,"scsynth-processor",{numberOfInputs:1,numberOfOutputs:1,outputChannelCount:[t]}),this.#r.autoConnect){let o=this.#e.destination;t>2&&(o.channelCount=Math.min(t,o.maxChannelCount),o.channelInterpretation="discrete"),this.#t.connect(o)}this.#m=this.#X(),this.#t.port.start(),this.#Q();let s=this.#r.mode,r=s==="sab"?this.#s.buffer:null;this.#t.port.postMessage({type:"init",mode:s,sharedBuffer:r,snapshotIntervalMs:this.#r.snapshotIntervalMs});let n={type:"loadWasm",wasmBytes:e,worldOptions:this.#r.worldOptions,sampleRate:this.#e.sampleRate};s==="sab"?n.wasmMemory=this.#s:n.memoryPages=this.#r.memoryPages||1280,this.#t.port.postMessage(n),await this.#K(),this.#u.setWorkletPort(this.#t.port)}#X(){let e=this.#t;return Object.freeze({connect:(...t)=>e.connect(...t),disconnect:(...t)=>e.disconnect(...t),get context(){return e.context},get numberOfOutputs(){return e.numberOfOutputs},get numberOfInputs(){return e.numberOfInputs},get channelCount(){return e.channelCount},get input(){return e}})}async#F(){let e=this.#r.mode,t=this.#E.bufferConstants,s=this.#E.ringBufferBase,r=this.#E.sharedBuffer,n={workerBaseURL:this.#r.workerBaseURL,preschedulerCapacity:this.#r.preschedulerCapacity,snapshotIntervalMs:this.#r.snapshotIntervalMs,bypassLookaheadS:this.#r.bypassLookaheadMs/1e3,getAudioContextTime:()=>this.#e?.currentTime??0,getNTPStartTime:()=>this.#S?.getNTPStartTime()??0};if(e==="sab"){if(n.sharedBuffer=r,n.ringBufferBase=s,n.bufferConstants=t,t?.NODE_ID_COUNTER_START!==void 0){let o=s+t.NODE_ID_COUNTER_START,a=new Int32Array(r,o,1);Atomics.store(a,0,1e3)}}else this.#B=1e3,n.nodeIdSource=o=>{let a=this.#B;return this.#B+=o,{from:a,to:a+o}};if(this.#n=qe(e,n),this.#n.onReply((o,a,c)=>{let l=Fe(o)||null;this.#l.emit("message:raw",{oscData:o,sequence:a,timestamp:c,scheduledTime:l});try{let u=ie(o),f=u[0],h=u.slice(1);if(f==="/supersonic/buffer/freed")this.#u?.handleBufferFreed(h);else if(f==="/supersonic/buffer/allocated")this.#u?.handleBufferAllocated(h);else if(f==="/synced"&&h.length>0){let S=h[0];this.#o?.has(S)&&this.#o.get(S)(u)}if(this.#l.emit("message",u),this.#r.debug||this.#r.debugOscIn){let S=this.#r.activityConsoleLog.oscInMaxLineLength??this.#r.activityConsoleLog.maxLineLength,m=h.map(g=>{let p=JSON.stringify(g);return p.length>S?p.slice(0,S)+"...":p}).join(", ")||"";console.log(`[\u2190 OSC] ${f}${m?" "+m:""}`)}}catch(u){console.error("[SuperSonic] Failed to decode OSC message:",u)}}),this.#n.onDebug(o=>{let a=this.#r.activityEvent.scsynthMaxLineLength??this.#r.activityEvent.maxLineLength;if(a>0&&o.text?.length>a&&(o={...o,text:o.text.slice(0,a)+"..."}),this.#l.emit("debug",o),this.#r.debug||this.#r.debugScsynth){let c=this.#r.activityConsoleLog.scsynthMaxLineLength??this.#r.activityConsoleLog.maxLineLength,l=o.text.length>c?o.text.slice(0,c)+"...":o.text;console.log(`[synth] ${l}`)}}),this.#n.onError((o,a)=>{console.error(`[SuperSonic] ${a} error:`,o),this.#l.emit("error",new Error(`${a}: ${o}`))}),this.#n.onOscLog(o=>{for(let a of o){let c=Fe(a.oscData)||null;this.#l.emit("message:sent",{oscData:a.oscData,sourceId:a.sourceId,sequence:a.sequence,timestamp:a.timestamp,scheduledTime:c})}}),e==="sab")await this.#n.initialize();else{if(await this.#n.initialize(this.#t.port),this.#n.setBufferConstants(t),this.#O?.length>0)for(let o of this.#O)this.#n.handleDebugRaw(o);this.#C=o=>this.#n.handleDebugRaw(o),this.#O=[]}this.#w=this.#n.createOscChannel({sourceId:0})}async#x(){this.#h=!0,this.#y=!1,this.bootStats.initDuration=performance.now()-this.bootStats.initStartTime,await this.#l.emitAsync("setup"),this.#l.emit("ready",{capabilities:this.#_,bootStats:this.bootStats})}#K(){return new Promise((e,t)=>{let s=setTimeout(()=>{t(new Error("AudioWorklet initialization timeout"))},5e3),r=async n=>{if(n.data.type==="error"){clearTimeout(s),this.#t.port.removeEventListener("message",r),t(new Error(n.data.error||"AudioWorklet error"));return}if(n.data.type==="initialized")if(clearTimeout(s),this.#t.port.removeEventListener("message",r),n.data.success){let o=n.data.ringBufferBase??0,a=n.data.bufferConstants,c=this.#r.mode==="sab"?this.#s.buffer:null;this.#E.initSharedViews(c,o,a);let l=this.#r.worldOptions?.maxNodes??1024,u=a?.NODE_TREE_MIRROR_MAX_NODES??1024;l>u&&console.warn(`SuperSonic: maxNodes (${l}) exceeds NODE_TREE_MIRROR_MAX_NODES (${u}). The node tree mirror will not show all nodes. Rebuild with NODE_TREE_MIRROR_MAX_NODES=${l} to fix.`),this.#S=new Q({mode:this.#r.mode,audioContext:this.#e,workletPort:this.#t.port}),this.#S.initSharedViews(c,o,a),await this.#S.initialize(),this.#S.startDriftTimer(),this.#r.mode==="sab"&&this.#A.update(c,o,a),this.#r.mode==="postMessage"&&n.data.initialSnapshot&&this.#E.updateSnapshot(n.data.initialSnapshot),e()}else t(new Error(n.data.error||"AudioWorklet initialization failed"))};this.#t.port.addEventListener("message",r),this.#t.port.start()})}#Q(){this.#t.port.addEventListener("message",e=>{let{data:t}=e;switch(t.type){case"error":console.error("[Worklet] Error:",t.error),this.#l.emit("error",new Error(t.error));break;case"version":this.#g=t.version;break;case"snapshot":t.buffer&&(this.#E.updateSnapshot(t.buffer),this.#I=t.snapshotsSent);break;case"debugRawBatch":this.#C?this.#C(t):this.#O.push(t);break;case"oscLog":t.entries&&this.#n?.handleOscLog&&this.#n.handleOscLog(t.entries);break}})}#N(){return{preschedulerMetrics:this.#n?.getPreschedulerMetrics(),transportMetrics:this.#n?.getMetrics(),driftOffsetMs:this.#S?.getDriftOffset()??0,ntpStartTime:this.#S?.getNTPStartTime()??0,clockOffsetMs:this.#S?.getClockOffset()??0,audioContextState:this.#e?.state||"unknown",bufferPoolStats:this.#u?.getStats(),loadedSynthDefsCount:this.loadedSynthDefs?.size||0,preschedulerCapacity:this.#r.preschedulerCapacity}}#v(){return this.#E.gatherMetrics(this.#N())}#j(){this.#E.updateMergedArray(this.#N())}#H(){if(this.#r.mode==="sab"){let t=this.#E.getMetricsView();return t?t[0]:null}let e=this.#E.getSnapshotBuffer();return e?new Uint32Array(e,0,1)[0]:null}#T(e="perform this operation"){if(!this.#h)throw new Error(`SuperSonic not initialized. Call init() before attempting to ${e}.`)}#ie(e){let s={nonBundle:"bypassNonBundle",immediate:"bypassImmediate",nearFuture:"bypassNearFuture",late:"bypassLate"}[e];s&&this.#E.addMetric(s)}#J(e){return e.includes("/")||e.includes("://")}#ee(e){if(e instanceof Uint8Array)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);throw new Error("oscData must be ArrayBuffer or Uint8Array")}#z(e,t={}){let s=this.#w.classify(e);if(G(s))this.#r.mode==="sab"?this.#w.send(e):this.#n.sendImmediate(e,s);else{let r=this.#E.bufferConstants?.scheduler_slot_size;if(r&&e.length>r)throw new Error(`OSC bundle too large to schedule (${e.length} > ${r} bytes). Use immediate timestamp (0 or 1) for large messages, or reduce bundle size.`);this.#n.sendWithOptions(e,t)}}#te(e,t){let s=(o,a)=>{let c=t[o];if(!Number.isFinite(c))throw new Error(a)},r=(o,a)=>{if(typeof t[o]!="string")throw new Error(a)},n=(o,a)=>{let c=t[o];if(!(c instanceof Uint8Array||c instanceof ArrayBuffer))throw new Error(a)};switch(e){case"/b_alloc":s(0,"/b_alloc requires a buffer number"),s(1,"/b_alloc requires a frame count");break;case"/b_allocRead":s(0,"/b_allocRead requires a buffer number"),r(1,"/b_allocRead requires a file path");break;case"/b_allocReadChannel":s(0,"/b_allocReadChannel requires a buffer number"),r(1,"/b_allocReadChannel requires a file path");break;case"/b_allocFile":s(0,"/b_allocFile requires a buffer number"),n(1,"/b_allocFile requires audio file data as blob");break}}#se(e,t){this.#U=this.#U.then(async()=>{let s=[e,...t],{packet:r}=await this.#a.rewritePacket(s),n=i.osc.encodeMessage(r[0],r.slice(1));this.#z(n)}).catch(s=>{console.error(`[SuperSonic] Buffer command ${e} failed:`,s),this.#l.emit("error",s)})}#re(){return this.#U}},Ti=xe.osc;export{A as OscChannel,xe as SuperSonic,Ti as osc};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supersonic-scsynth",
3
- "version": "0.53.0",
3
+ "version": "0.55.0",
4
4
  "description": "SuperCollider scsynth WebAssembly port for AudioWorklet - Run SuperCollider synthesis in the browser",
5
5
  "main": "dist/supersonic.js",
6
6
  "types": "supersonic.d.ts",
@@ -15,7 +15,8 @@
15
15
  "test": "playwright test --reporter=list --max-failures=1",
16
16
  "test:all": "playwright test --reporter=list",
17
17
  "prepublishOnly": "./build.sh --release",
18
- "test:types": "tsd"
18
+ "test:types": "tsd",
19
+ "docs:api": "typedoc && mv docs/api-generated/README.md docs/API.md && rm -rf docs/api-generated"
19
20
  },
20
21
  "tsd": {
21
22
  "compilerOptions": {
@@ -70,7 +71,12 @@
70
71
  "devDependencies": {
71
72
  "@playwright/test": "^1.49.0",
72
73
  "esbuild": "^0.24.0",
73
- "tsd": "^0.33.0"
74
+ "remark-gfm": "^4.0.1",
75
+ "tsd": "^0.33.0",
76
+ "typedoc": "^0.28.17",
77
+ "typedoc-plugin-markdown": "^4.10.0",
78
+ "typedoc-plugin-remark": "^2.0.1",
79
+ "typescript": "^5.9.3"
74
80
  },
75
81
  "engines": {
76
82
  "node": ">=18.0.0"
package/supersonic.d.ts CHANGED
@@ -52,12 +52,12 @@ export type OscArg =
52
52
  * The first element is always the address string, followed by zero or more arguments.
53
53
  *
54
54
  * @example
55
- * // A decoded /s_new message:
56
- * ["/s_new", "beep", 1001, 0, 1, "freq", 440]
55
+ * // A decoded /n_go message received from scsynth:
56
+ * ["/n_go", 1001, 0, -1, -1, 0]
57
57
  *
58
58
  * // Access parts:
59
- * const address = msg[0]; // "/s_new"
60
- * const args = msg.slice(1); // ["beep", 1001, 0, 1, "freq", 440]
59
+ * const address = msg[0]; // "/n_go"
60
+ * const args = msg.slice(1); // [1001, 0, -1, -1, 0]
61
61
  */
62
62
  export type OscMessage = [string, ...OscArg[]];
63
63
 
@@ -192,6 +192,8 @@ export interface SuperSonicOptions {
192
192
  * Transport mode.
193
193
  * - `'postMessage'` (default) — works everywhere, no special headers needed
194
194
  * - `'sab'` — lowest latency, requires Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers
195
+ *
196
+ * See docs/MODES.md for a full comparison of communication modes.
195
197
  */
196
198
  mode?: TransportMode;
197
199
 
@@ -657,10 +659,11 @@ export interface SuperSonicEventMap {
657
659
  * Fired after init completes, before `'ready'`.
658
660
  * Use for setting up groups, FX chains, and bus routing.
659
661
  * Can be async — init waits for all setup handlers to resolve.
662
+ * Also fires after `recover()` triggers a `reload()`.
660
663
  */
661
664
  'setup': () => void | Promise<void>;
662
665
 
663
- /** Fired when the engine is fully booted and ready to receive messages. */
666
+ /** Fired when the engine is fully booted and ready to receive messages. Payload includes browser capabilities and boot timing. */
664
667
  'ready': (data: { capabilities: SuperSonicInfo['capabilities']; bootStats: BootStats }) => void;
665
668
 
666
669
  /**
@@ -675,19 +678,19 @@ export interface SuperSonicEventMap {
675
678
  /** Fired when an OSC message is sent to scsynth. Includes source worker ID, sequence number, and NTP timestamps. */
676
679
  'message:sent': (data: { oscData: Uint8Array; sourceId: number; sequence: number; timestamp: number; scheduledTime: number | null }) => void;
677
680
 
678
- /** Debug text output from scsynth (e.g. synthdef compilation messages). */
679
- 'debug': (msg: { text: string }) => void;
681
+ /** Debug text output from scsynth (e.g. synthdef compilation messages). Includes NTP timestamp and sequence number. */
682
+ 'debug': (msg: { text: string; timestamp: number; sequence: number }) => void;
680
683
 
681
684
  /** Error from any component (worklet, transport, workers). */
682
685
  'error': (error: Error) => void;
683
686
 
684
- /** Engine is shutting down. */
687
+ /** Engine is shutting down. Fired by `shutdown()`, `reset()`, and `destroy()`. */
685
688
  'shutdown': () => void;
686
689
 
687
- /** Engine has been destroyed. */
690
+ /** Engine has been destroyed. Only fired by `destroy()`, not by `shutdown()` or `reset()`. Last chance to clean up before all listeners are cleared. */
688
691
  'destroy': () => void;
689
692
 
690
- /** Audio resumed after a suspend (AudioContext was re-started). */
693
+ /** Audio resumed after a suspend (AudioContext was re-started). Emitted after `resume()` succeeds. */
691
694
  'resumed': () => void;
692
695
 
693
696
  /** Full reload started (worklet and WASM will be recreated). */
@@ -696,22 +699,22 @@ export interface SuperSonicEventMap {
696
699
  /** Full reload completed. */
697
700
  'reload:complete': (data: { success: boolean }) => void;
698
701
 
699
- /** AudioContext state changed. */
702
+ /** AudioContext state changed. State is one of: `'running'`, `'suspended'`, `'closed'`, or `'interrupted'`. */
700
703
  'audiocontext:statechange': (data: { state: AudioContextState }) => void;
701
704
 
702
- /** AudioContext was suspended (e.g. tab backgrounded, autoplay policy). */
705
+ /** AudioContext was suspended (e.g. tab backgrounded, autoplay policy, iOS audio interruption). Show a restart UI and call `recover()` when the user interacts. */
703
706
  'audiocontext:suspended': () => void;
704
707
 
705
708
  /** AudioContext resumed to 'running' state. */
706
709
  'audiocontext:resumed': () => void;
707
710
 
708
- /** AudioContext was interrupted (iOS-specific). */
711
+ /** AudioContext was interrupted (iOS-specific). Another app or system event took audio focus. Similar to suspended but triggered externally. */
709
712
  'audiocontext:interrupted': () => void;
710
713
 
711
- /** An asset (WASM, synthdef, sample) started loading. */
714
+ /** An asset started loading. Type is `'wasm'`, `'synthdef'`, or `'sample'`. */
712
715
  'loading:start': (data: { type: string; name: string }) => void;
713
716
 
714
- /** An asset finished loading. */
717
+ /** An asset finished loading. Size is in bytes. */
715
718
  'loading:complete': (data: { type: string; name: string; size: number }) => void;
716
719
  }
717
720
 
@@ -828,6 +831,20 @@ export class OscChannel {
828
831
  /** Get and reset local metrics (for periodic reporting). */
829
832
  getAndResetMetrics(): OscChannelMetrics;
830
833
 
834
+ /**
835
+ * Get the next unique node ID.
836
+ *
837
+ * Returns globally unique scsynth node IDs. IDs start at 1000 following
838
+ * sclang convention — 0 is the root group, 1 is the default group, and
839
+ * 2–999 are left free for manual use.
840
+ *
841
+ * SAB mode: single atomic increment via `Atomics.add` — lock-free and
842
+ * thread-safe. PM mode: range-based allocation with async pre-fetching.
843
+ *
844
+ * @returns A unique node ID (>= 1000)
845
+ */
846
+ nextNodeId(): number;
847
+
831
848
  /** Close the channel and release its ports. */
832
849
  close(): void;
833
850
 
@@ -971,7 +988,8 @@ export type BlockedCommand =
971
988
  | '/d_load' | '/d_loadDir'
972
989
  | '/b_read' | '/b_readChannel'
973
990
  | '/b_write' | '/b_close'
974
- | '/clearSched' | '/error';
991
+ | '/clearSched' | '/error'
992
+ | '/quit';
975
993
 
976
994
  // ============================================================================
977
995
  // SuperSonic
@@ -992,6 +1010,23 @@ export interface SendOSCOptions {
992
1010
  * scsynth with low latency inside a web page.
993
1011
  *
994
1012
  * @example
1013
+ * // CDN Quick Start
1014
+ * import { SuperSonic } from 'supersonic-scsynth';
1015
+ *
1016
+ * const sonic = new SuperSonic({
1017
+ * baseURL: 'https://unpkg.com/supersonic-scsynth@latest/dist/',
1018
+ * synthdefBaseURL: 'https://unpkg.com/supersonic-scsynth-synthdefs@latest/synthdefs/',
1019
+ * });
1020
+ *
1021
+ * // Call init after a user gesture (click/tap) due to browser autoplay policies
1022
+ * myButton.onclick = async () => {
1023
+ * await sonic.init();
1024
+ * await sonic.loadSynthDef('sonic-pi-beep');
1025
+ * sonic.send('/s_new', 'sonic-pi-beep', -1, 0, 0, 'note', 60);
1026
+ * };
1027
+ *
1028
+ * @example
1029
+ * // Setup + message listeners
995
1030
  * import { SuperSonic } from 'supersonic-scsynth';
996
1031
  *
997
1032
  * const sonic = new SuperSonic({ baseURL: '/dist/' });
@@ -1033,7 +1068,7 @@ export class SuperSonic {
1033
1068
  * OSC encoding/decoding utilities.
1034
1069
  *
1035
1070
  * @example
1036
- * const msg = SuperSonic.osc.encodeMessage('/s_new', ['beep', 1001]);
1071
+ * const msg = SuperSonic.osc.encodeMessage('/s_new', ['beep', 1001, 0, 0]);
1037
1072
  * const decoded = SuperSonic.osc.decode(msg);
1038
1073
  */
1039
1074
  static osc: typeof osc;
@@ -1044,6 +1079,8 @@ export class SuperSonic {
1044
1079
  * Includes array offsets for zero-allocation reading via {@link getMetricsArray},
1045
1080
  * metric types/units/descriptions, and a declarative UI layout used by the
1046
1081
  * `<supersonic-metrics>` web component.
1082
+ *
1083
+ * See docs/METRICS_COMPONENT.md for the metrics component guide.
1047
1084
  */
1048
1085
  static getMetricsSchema(): MetricsSchema;
1049
1086
 
@@ -1109,10 +1146,8 @@ export class SuperSonic {
1109
1146
  readonly input: AudioWorkletNode;
1110
1147
  } | null;
1111
1148
 
1112
- /** The internal OscChannel used by the main thread. Advanced use only. */
1113
- get osc(): OscChannel | null;
1114
1149
 
1115
- /** Map of loaded SynthDef names to their binary data. */
1150
+ /** Map of loaded SynthDef names to their binary data. SynthDefs appear after `/d_recv` or `loadSynthDef()`. Removed on `/d_free` or `/d_freeAll`. Cached for automatic restoration after `reload()`. */
1116
1151
  loadedSynthDefs: Map<string, Uint8Array>;
1117
1152
 
1118
1153
  /** Boot timing statistics. */
@@ -1173,6 +1208,7 @@ export class SuperSonic {
1173
1208
  * when complete.
1174
1209
  *
1175
1210
  * Safe to call multiple times — subsequent calls are no-ops.
1211
+ * Must be called from a user gesture (click/tap) due to browser autoplay policies.
1176
1212
  *
1177
1213
  * @throws If required browser features are missing or WASM fails to load.
1178
1214
  *
@@ -1216,6 +1252,11 @@ export class SuperSonic {
1216
1252
  * from a long background period).
1217
1253
  *
1218
1254
  * @returns true if audio is running after recovery
1255
+ *
1256
+ * @example
1257
+ * document.addEventListener('visibilitychange', () => {
1258
+ * if (document.visibilityState === 'visible') sonic.recover();
1259
+ * });
1219
1260
  */
1220
1261
  recover(): Promise<boolean>;
1221
1262
 
@@ -1308,14 +1349,16 @@ export class SuperSonic {
1308
1349
  send(address: '/clearSched', ...args: OscArg[]): never;
1309
1350
  /** @deprecated SuperSonic always enables error notifications so you never miss a /fail reply. */
1310
1351
  send(address: '/error', ...args: OscArg[]): never;
1352
+ /** @deprecated Use destroy() to shut down SuperSonic. */
1353
+ send(address: '/quit', ...args: OscArg[]): never;
1311
1354
 
1312
1355
  // ── Top-level commands ─────────────────────────────────────────────
1313
1356
 
1314
1357
  /** Query server status. Replies with `/status.reply`: unused, numUGens, numSynths, numGroups, numSynthDefs, avgCPU%, peakCPU%, nominalSampleRate, actualSampleRate. */
1315
1358
  send(address: '/status'): void;
1316
- /** Query server version. Replies with `/version.reply`: programName, majorVersion, minorVersion, patchName, gitBranch, commitHash. */
1359
+ /** Query server version. Replies with `/version.reply`: programName, majorVersion, minorVersion, patchVersion, gitBranch, commitHash. */
1317
1360
  send(address: '/version'): void;
1318
- /** Register (1) or unregister (0) for server notifications (`/n_go`, `/n_end`, `/n_on`, `/n_off`, `/n_move`). Replies with `/done /notify clientID`. */
1361
+ /** Register (1) or unregister (0) for server notifications (`/n_go`, `/n_end`, `/n_on`, `/n_off`, `/n_move`). Replies with `/done /notify clientID [maxLogins]`. */
1319
1362
  send(address: '/notify', flag: 0 | 1, clientID?: number): void;
1320
1363
  /** Enable/disable OSC message dumping to debug output. 0=off, 1=parsed, 2=hex, 3=both. */
1321
1364
  send(address: '/dumpOSC', flag: 0 | 1 | 2 | 3): void;
@@ -1401,13 +1444,13 @@ export class SuperSonic {
1401
1444
 
1402
1445
  // ── Buffer commands ────────────────────────────────────────────────
1403
1446
 
1404
- /** Async. Allocate an empty buffer. Queued and rewritten to /b_allocPtr internally. Use sync() after to ensure completion. Replies with `/done /b_allocPtr bufnum`. */
1447
+ /** Async. Allocate an empty buffer. Queued and rewritten to /b_allocPtr internally. Use sync() after to ensure completion. Replies with `/done /b_allocPtr bufnum`. Note: completion messages are not supported (dropped during rewrite). */
1405
1448
  send(address: '/b_alloc', bufnum: number, numFrames: number, numChannels?: number, sampleRate?: number): void;
1406
1449
  /** Async. Allocate a buffer and read an audio file into it. The path is fetched via the configured sampleBaseURL. Queued and rewritten internally. Replies with `/done /b_allocPtr bufnum`. */
1407
1450
  send(address: '/b_allocRead', bufnum: number, path: string, startFrame?: number, numFrames?: number): void;
1408
1451
  /** Async. Allocate a buffer and read specific channels from an audio file. Queued and rewritten internally. Replies with `/done /b_allocPtr bufnum`. */
1409
1452
  send(address: '/b_allocReadChannel', bufnum: number, path: string, startFrame: number, numFrames: number, ...channels: number[]): void;
1410
- /** Async. SuperSonic extension: allocate a buffer from inline audio file bytes (WAV, FLAC, OGG, etc.) without URL fetch. Queued and rewritten internally. */
1453
+ /** Async. SuperSonic extension: allocate a buffer from inline audio file bytes (WAV, FLAC, OGG, etc.) without URL fetch. Queued and rewritten internally. Replies with `/done /b_allocPtr bufnum`. */
1411
1454
  send(address: '/b_allocFile', bufnum: number, data: Uint8Array | ArrayBuffer): void;
1412
1455
  /** Async. Free a buffer. Optional completionMessage is an encoded OSC message executed after freeing. Replies with `/done /b_free bufnum`. */
1413
1456
  send(address: '/b_free', bufnum: number, completionMessage?: Uint8Array | ArrayBuffer): void;
@@ -1498,6 +1541,10 @@ export class SuperSonic {
1498
1541
  * Unlike {@link cancelAll} which only clears the JS prescheduler, this also
1499
1542
  * clears bundles already consumed from the ring buffer and sitting in the
1500
1543
  * WASM scheduler's priority queue. Resolves when both are confirmed empty.
1544
+ *
1545
+ * Uses a postMessage flag (not the ring buffer) to signal the WASM scheduler,
1546
+ * avoiding the race condition where stale scheduled bundles fire before a
1547
+ * clear command is read from the ring buffer.
1501
1548
  */
1502
1549
  purge(): Promise<void>;
1503
1550
 
@@ -1508,8 +1555,18 @@ export class SuperSonic {
1508
1555
  * worker to send OSC directly to the AudioWorklet without going through
1509
1556
  * the main thread. Works in both SAB and postMessage modes.
1510
1557
  *
1558
+ * The `blocking` option defaults to `true` for worker channels (sourceId !== 0)
1559
+ * and `false` for main thread. Set to `false` for AudioWorkletProcessor use.
1560
+ * In postMessage mode this has no effect.
1561
+ *
1562
+ * For AudioWorkletProcessor use, import from `'supersonic-scsynth/osc-channel'`
1563
+ * which avoids DOM APIs unavailable in the worklet scope.
1564
+ *
1565
+ * See docs/WORKERS.md for the full workers guide.
1566
+ *
1511
1567
  * @param options - Channel options
1512
1568
  * @param options.sourceId - Numeric source ID (0 = main thread, 1+ = workers)
1569
+ * @param options.blocking - Whether sends block until the worklet reads the message
1513
1570
  *
1514
1571
  * @example
1515
1572
  * const channel = sonic.createOscChannel();
@@ -1520,6 +1577,26 @@ export class SuperSonic {
1520
1577
  */
1521
1578
  createOscChannel(options?: { sourceId?: number; blocking?: boolean }): OscChannel;
1522
1579
 
1580
+ /**
1581
+ * Get the next unique node ID.
1582
+ *
1583
+ * Returns globally unique scsynth node IDs without coordination conflicts.
1584
+ * IDs start at 1000 following sclang convention — 0 is the root group,
1585
+ * 1 is the default group, and 2–999 are left free for manual use.
1586
+ *
1587
+ * SAB mode uses a single atomic increment per call. PM mode uses
1588
+ * range-based allocation with async pre-fetching from the main thread.
1589
+ *
1590
+ * Also available on {@link OscChannel} for use in Web Workers.
1591
+ *
1592
+ * @returns A unique node ID (>= 1000)
1593
+ *
1594
+ * @example
1595
+ * const id = sonic.nextNodeId();
1596
+ * sonic.send('/s_new', 'beep', id, 0, 1, 'freq', 440);
1597
+ */
1598
+ nextNodeId(): number;
1599
+
1523
1600
  // ──────────────────────────────────────────────────────────────────────────
1524
1601
  // Asset Loading
1525
1602
  // ──────────────────────────────────────────────────────────────────────────
@@ -1641,7 +1718,7 @@ export class SuperSonic {
1641
1718
  * loading synthdefs or buffers to ensure they're ready before creating synths.
1642
1719
  *
1643
1720
  * @param syncId - Optional custom sync ID (random if omitted)
1644
- * @throws After timeout if scsynth doesn't respond
1721
+ * @throws Rejects after 10 seconds if scsynth doesn't respond.
1645
1722
  *
1646
1723
  * @example
1647
1724
  * await sonic.loadSynthDef('beep');
@@ -1658,6 +1735,11 @@ export class SuperSonic {
1658
1735
  /**
1659
1736
  * Get current metrics as a named object.
1660
1737
  *
1738
+ * This is a cheap local memory read in both SAB and postMessage modes — no IPC
1739
+ * or copying. Safe to call from `requestAnimationFrame`.
1740
+ *
1741
+ * See docs/METRICS.md for the full metrics guide.
1742
+ *
1661
1743
  * @example
1662
1744
  * const m = sonic.getMetrics();
1663
1745
  * console.log(`Messages sent: ${m.oscOutMessagesSent}`);
@@ -1699,6 +1781,10 @@ export class SuperSonic {
1699
1781
  /**
1700
1782
  * Get the node tree in hierarchical format.
1701
1783
  *
1784
+ * The mirror has a default capacity of 1024 nodes. If exceeded,
1785
+ * `droppedCount` will be non-zero and the tree may be incomplete,
1786
+ * but audio continues normally.
1787
+ *
1702
1788
  * @example
1703
1789
  * const tree = sonic.getTree();
1704
1790
  * function printTree(node, indent = 0) {