supersonic-scsynth 0.55.0 → 0.57.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 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
+ 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;#T;#e;#t;#A;#E;#l;#d;#I;#p;#a;#_;#u;#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.#u=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.#T={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.#T.atomicView,dataView:this.#T.dataView,uint8View:this.#T.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.#_<=this.#u>>>1&&this.#h(),t}#C(){if(this.#c){let t=this.#c(this.#u);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.#u*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.#u;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};
@@ -0,0 +1 @@
1
+ var S=new Uint8Array(2097152),C=new DataView(S.buffer),f=S,l=C,a=new Map,O=1e3,Z=new TextDecoder,W=new TextEncoder,X=2208988800,b=4294967296,_=new Uint8Array([35,98,117,110,100,108,101,0]),z=44,g=105,x=102,U=115,T=98,E=84,k=70,G=104,D=100,P=116,L=117;function y(e,t){let n=e.length+4;n+=t.length+4;for(let r of t)if(r instanceof Uint8Array)n+=4+r.length+3;else if(r instanceof ArrayBuffer)n+=4+r.byteLength+3;else if(typeof r=="string")n+=r.length*3+4;else if(r&&r.type==="string")n+=r.value.length*3+4;else if(r&&r.type==="blob"){let i=r.value,c=i instanceof Uint8Array?i.length:i.byteLength;n+=4+c+3}else r&&r.type==="uuid"?n+=16:n+=8;return n}function M(e){let t=16;for(let n of e)t+=4,Array.isArray(n)?t+=y(n[0],n.slice(1)):n.packets!==void 0?t+=M(n.packets):t+=y(n.address,n.args||[]);return t}function I(e){if(e<=2097152){f=S,l=C;return}f=new Uint8Array(e),l=new DataView(f.buffer)}function j(e,t=[]){let n=y(e,t);I(n);let r=0;r=F(e,r),r=v(t,r);for(let i=0;i<t.length;i++)r=d(t[i],r);return f.subarray(0,r)}function q(e,t){let n=M(t);I(n);let r=0;f.set(_,r),r+=8,r=w(e,r);for(let i=0;i<t.length;i++){let c=t[i],u=r;r+=4;let s=r;Array.isArray(c)?r=h(c[0],c.slice(1),r):c.packets!==void 0?r=N(c.timeTag,c.packets,r):r=h(c.address,c.args||[],r);let o=r-s;l.setUint32(u,o,!1)}return f.subarray(0,r)}function ee(e,t,n=[]){let r=20+y(t,n);I(r);let i=0;f.set(_,i),i+=8,i=w(e,i);let c=i;i+=4;let u=i;i=F(t,i),i=v(n,i);for(let s=0;s<n.length;s++)i=d(n[s],i);return l.setUint32(c,i-u,!1),f.subarray(0,i)}function h(e,t,n){n=F(e,n),n=v(t,n);for(let r=0;r<t.length;r++)n=d(t[r],n);return n}function N(e,t,n){f.set(_,n),n+=8,n=w(e,n);for(let r=0;r<t.length;r++){let i=t[r],c=n;n+=4;let u=n;Array.isArray(i)?n=h(i[0],i.slice(1),n):i.packets!==void 0?n=N(i.timeTag,i.packets,n):n=h(i.address,i.args||[],n),l.setUint32(c,n-u,!1)}return n}function F(e,t){let n=a.get(e);if(n)return f.set(n,t),t+n.length;let r=t;if(t=B(e,t),a.size<O){let i=f.slice(r,t);a.set(e,i)}return t}function B(e,t){let n=!1;for(let r=0;r<e.length;r++)if(e.charCodeAt(r)>=128){n=!0;break}if(n){let r=W.encodeInto(e,f.subarray(t));t+=r.written}else for(let r=0;r<e.length;r++)f[t++]=e.charCodeAt(r);for(f[t++]=0;t&3;)f[t++]=0;return t}function v(e,t){f[t++]=z;for(let n=0;n<e.length;n++){let r=e[n],i=typeof r;if(i==="number")f[t++]=Number.isInteger(r)?g:x;else if(i==="string")f[t++]=U;else if(i==="boolean")f[t++]=r?E:k;else if(r instanceof Uint8Array||r instanceof ArrayBuffer)f[t++]=T;else if(r&&r.type==="int")f[t++]=g;else if(r&&r.type==="float")f[t++]=x;else if(r&&r.type==="string")f[t++]=U;else if(r&&r.type==="blob")f[t++]=T;else if(r&&r.type==="bool")f[t++]=r.value?E:k;else if(r&&r.type==="int64")f[t++]=G;else if(r&&r.type==="double")f[t++]=D;else if(r&&r.type==="timetag")f[t++]=P;else if(r&&r.type==="uuid")f[t++]=L;else throw r==null?new Error(`OSC argument at index ${n} is ${r}`):new Error(`Unknown OSC argument type at index ${n}: ${i}`)}for(f[t++]=0;t&3;)f[t++]=0;return t}function d(e,t){let n=typeof e;if(n==="number")return Number.isInteger(e)?(l.setInt32(t,e,!1),t+4):(l.setFloat32(t,e,!1),t+4);if(n==="string")return B(e,t);if(n==="boolean")return t;if(e instanceof Uint8Array){let r=e.length;for(l.setUint32(t,r,!1),t+=4,f.set(e,t),t+=r;t&3;)f[t++]=0;return t}if(e instanceof ArrayBuffer)return d(new Uint8Array(e),t);if(e&&e.type==="int")return l.setInt32(t,e.value,!1),t+4;if(e&&e.type==="float")return l.setFloat32(t,e.value,!1),t+4;if(e&&e.type==="string")return B(e.value,t);if(e&&e.type==="blob"){let r=e.value instanceof Uint8Array?e.value:new Uint8Array(e.value),i=r.length;for(l.setUint32(t,i,!1),t+=4,f.set(r,t),t+=i;t&3;)f[t++]=0;return t}return e&&e.type==="bool"?t:e&&e.type==="int64"?(l.setBigInt64(t,BigInt(e.value),!1),t+8):e&&e.type==="double"?(l.setFloat64(t,e.value,!1),t+8):e&&e.type==="timetag"?w(e.value,t):e&&e.type==="uuid"?(f.set(e.value,t),t+16):t}function w(e,t){if(e===1||e===null||e===void 0)return l.setUint32(t,0,!1),l.setUint32(t+4,1,!1),t+8;if(Array.isArray(e)){if(e.length!==2)throw new Error(`TimeTag array must have exactly 2 elements [seconds, fraction], got ${e.length}`);return l.setUint32(t,e[0]>>>0,!1),l.setUint32(t+4,e[1]>>>0,!1),t+8}if(typeof e!="number")throw new TypeError(`TimeTag must be a number, array, null, or undefined, got ${typeof e}`);e>1&&e<X&&console.warn(`TimeTag ${e} looks like a Unix timestamp (< NTP_EPOCH_OFFSET). Did you mean to add NTP_EPOCH_OFFSET (2208988800)?`);let n=e>>>0,r=(e-Math.floor(e))*b>>>0;return l.setUint32(t,n,!1),l.setUint32(t+4,r,!1),t+8}function J(e){return e instanceof Uint8Array||(e=new Uint8Array(e)),e[0]===35&&e[1]===98?Q(e):K(e)}function K(e){e instanceof Uint8Array||(e=new Uint8Array(e));let t=new DataView(e.buffer,e.byteOffset,e.byteLength),n=0,[r,i]=A(e,n);if(n=i,n>=e.length||e[n]!==z)return[r];let[c,u]=A(e,n);n=u;let s=[r];for(let o=1;o<c.length;o++)switch(c.charCodeAt(o)){case g:s.push(t.getInt32(n,!1)),n+=4;break;case x:s.push(t.getFloat32(n,!1)),n+=4;break;case U:let[V,R]=A(e,n);s.push(V),n=R;break;case T:let m=t.getUint32(n,!1);n+=4,s.push(e.slice(n,n+m)),n+=m,n=n+3&-4;break;case G:s.push(t.getBigInt64(n,!1)),n+=8;break;case D:s.push(t.getFloat64(n,!1)),n+=8;break;case E:s.push(!0);break;case k:s.push(!1);break;case P:let $=t.getUint32(n,!1),H=t.getUint32(n+4,!1);s.push($+H/b),n+=8;break;case L:s.push({type:"uuid",value:e.slice(n,n+16)}),n+=16;break}return s}function Q(e){e instanceof Uint8Array||(e=new Uint8Array(e));let t=new DataView(e.buffer,e.byteOffset,e.byteLength),n=8,r=t.getUint32(n,!1),i=t.getUint32(n+4,!1),c=r+i/b;n+=8;let u=[];for(;n<e.length;){let s=t.getUint32(n,!1);if(n+=4,s>0&&n+s<=e.length){let o=e.subarray(n,n+s);u.push(J(o))}n+=s}return{timeTag:c,packets:u}}function A(e,t){let n=t;for(;n<e.length&&e[n]!==0;)n++;let r=Z.decode(e.subarray(t,n));return n++,n=n+3&-4,[r,n]}function te(e){return e.slice()}function ne(e,t,n,r){let i=j(e,t);return n.set(i,r),i.length}function re(e,t,n,r){let i=q(e,t);return n.set(i,r),i.length}function ie(){a.clear()}function fe(){return{stringCacheSize:a.size,maxSize:O}}function Y(e){return!e||e.length<8?!1:e[0]===35&&e[1]===98}function se(e){if(!Y(e))return null;let t=new DataView(e.buffer,e.byteOffset,e.byteLength),n=t.getUint32(8,!1),r=t.getUint32(12,!1);return n+r/b}export{X as NTP_EPOCH_OFFSET,b as TWO_POW_32,ie as clearCache,te as copyEncoded,Q as decodeBundle,K as decodeMessage,J as decodePacket,q as encodeBundle,re as encodeBundleIntoBuffer,j as encodeMessage,ne as encodeMessageIntoBuffer,ee as encodeSingleBundle,se as getBundleTimeTag,fe as getCacheStats,Y as isBundle};
@@ -1,8 +1,8 @@
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.
1
+ var C=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 ue=new Map;function ze(i){try{return new URL(i,window.location.href).origin!==window.location.origin}catch{return!1}}async function $e(i){if(ue.has(i))return ue.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 ue.set(i,r),r}async function R(i,e={}){let t=i;return ze(i)&&(t=await $e(i)),new Worker(t,e)}async function Ye(i,e){let t=e;ze(e)&&(t=await $e(e)),await i.addModule(t)}function Ge(i,e,t){return(t-1-i+e)%t}function We({uint8View:i,dataView:e,bufferStart:t,bufferSize:s,head:r,payload:n,sequence:o,messageMagic:a,headerSize:c,sourceId:u=0,headerScratch:l=null,headerScratchView:f=null}){let h=n.length,p=c+h+3&-4,g=s-r;if(p>g){let m=l||new Uint8Array(c),S=f||new DataView(m.buffer);S.setUint32(0,a,!0),S.setUint32(4,p,!0),S.setUint32(8,o,!0),S.setUint32(12,u,!0);let _=t+r,d=t;if(g>=c){i.set(m,_);let M=g-c;M>0&&i.set(n.subarray(0,M),_+c),i.set(n.subarray(M),d)}else{i.set(m.subarray(0,g),_),i.set(m.subarray(g),d);let M=c-g;i.set(n,d+M)}}else{let m=t+r;e.setUint32(m,a,!0),e.setUint32(m+4,p,!0),e.setUint32(m+8,o,!0),e.setUint32(m+12,u,!0),i.set(n,m+c)}return(r+p)%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 Ve({atomicView:i,dataView:e,uint8View:t,bufferConstants:s,ringBufferBase:r,controlIndices:n,oscMessage:o,sourceId:a=0,maxSpins:c=0,useWait:u=!1}){let l=o.length,f=s.MESSAGE_HEADER_SIZE+l;if(f>s.IN_BUFFER_SIZE-s.MESSAGE_HEADER_SIZE||!It(i,n.IN_WRITE_LOCK,c,u))return!1;try{let h=Atomics.load(i,n.IN_HEAD),E=Atomics.load(i,n.IN_TAIL),p=f+3&-4;if(Ge(h,E,s.IN_BUFFER_SIZE)<p)return!1;let m=Atomics.add(i,n.IN_SEQUENCE,1),S=We({uint8View:t,dataView:e,bufferStart:r+s.IN_BUFFER_START,bufferSize:s.IN_BUFFER_SIZE,head:h,payload:o,sequence:m,messageMagic:s.MESSAGE_MAGIC,headerSize:s.MESSAGE_HEADER_SIZE,sourceId:a});return Atomics.load(i,n.IN_HEAD),Atomics.store(i,n.IN_HEAD,S),Atomics.notify(i,n.IN_HEAD,1),!0}finally{Dt(i,n.IN_WRITE_LOCK)}}function W(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 Ze(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 fe(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 A(){return(performance.timeOrigin+performance.now())/1e3+2208988800}function Xe(i,e={}){let{getCurrentNTP:t=A,bypassLookaheadS:s=.5}=e;if(!Lt(i))return"nonBundle";let r=fe(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 u=n+o/4294967296-a;return u<0?"late":u<s?"nearFuture":"farFuture"}function V(i){return i!=="farFuture"}var B=class i{#i;#e;#t;#y;#n;#r;#u;#c;#a;#l;#f;#p;#b;#h;#m;#d;#_;#g;#s;#o={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.#c=t.sourceId??0,this.#a=t.blocking??this.#c!==0,this.#l=t.getCurrentNTP??A,this.#m=1e3,e==="postMessage")this.#e=t.port;else{if(this.#t={sharedBuffer:t.sharedBuffer,ringBufferBase:t.ringBufferBase,bufferConstants:t.bufferConstants,controlIndices:t.controlIndices},this.#S(),t.sharedBuffer&&t.bufferConstants){let s=t.ringBufferBase+t.bufferConstants.METRICS_START;this.#r=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())}#S(){let e=this.#t.sharedBuffer;this.#y={atomicView:new Int32Array(e),dataView:new DataView(e),uint8View:new Uint8Array(e)}}classify(e){return Xe(e,{getCurrentNTP:this.#l,bypassLookaheadS:this.#u})}#E(e,t=null){if(this.#i==="sab"&&this.#r){if(Atomics.add(this.#r,24,1),Atomics.add(this.#r,25,e),t){let r={nonBundle:38,immediate:39,nearFuture:40,late:41}[t];r!==void 0&&(Atomics.add(this.#r,r,1),Atomics.add(this.#r,22,1))}}else this.#o.messagesSent++,this.#o.bytesSent+=e,t&&t in this.#o&&(this.#o[t]++,this.#o.bypassed++)}getAndResetMetrics(){let e={...this.#o};return this.#o={messagesSent:0,bytesSent:0,nonBundle:0,immediate:0,nearFuture:0,late:0,bypassed:0},e}getMetrics(){return this.#i==="sab"&&this.#r?{messagesSent:Atomics.load(this.#r,24),bytesSent:Atomics.load(this.#r,25),nonBundle:Atomics.load(this.#r,38),immediate:Atomics.load(this.#r,39),nearFuture:Atomics.load(this.#r,40),late:Atomics.load(this.#r,41),bypassed:Atomics.load(this.#r,22)}:{...this.#o}}#A(e,t=null,s=!0){if(this.#i==="postMessage")return this.#e?(this.#e.postMessage({type:"osc",oscData:e,bypassCategory:t,sourceId:this.#c}),!0):!1;{let r=this.#a,n=Ve({atomicView:this.#y.atomicView,dataView:this.#y.dataView,uint8View:this.#y.uint8View,bufferConstants:this.#t.bufferConstants,ringBufferBase:this.#t.ringBufferBase,controlIndices:this.#t.controlIndices,oscMessage:e,sourceId:this.#c,maxSpins:r?10:0,useWait:r});return!n&&!r&&s&&this.#n?(this.#r&&Atomics.add(this.#r,45,1),this.#n.postMessage({type:"directDispatch",oscData:e,sourceId:this.#c}),!0):n}}#w(e){return this.#n?(this.#n.postMessage({type:"osc",oscData:e,sourceId:this.#c}),!0):(console.error("[OscChannel] No prescheduler port, sending direct"),this.#A(e))}send(e){let t=this.classify(e);if(V(t)){let s=this.#A(e,t);return s&&this.#E(e.length,t),s}else{let s=this.#w(e);return s&&this.#E(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<=this.#m>>>1&&this.#M(),e}#B(){if(this.#d){let e=this.#d(this.#m);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.#l=e}get mode(){return this.#i}get transferable(){let e={mode:this.#i,preschedulerPort:this.#n,bypassLookaheadS:this.#u,sourceId:this.#c,blocking:this.#a};if(this.#i==="postMessage"){let t=this.#m*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.#m;o.port1.onmessage=u=>{if(u.data.type==="requestNodeIdRange"){let l=a(c);o.port1.postMessage({type:"nodeIdRange",from:l.from,to:l.to})}},r=o.port2,this.#s=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.#s&&(e.push(this.#s),this.#s=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=W(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 C{#i;#e;#t;#y;#n;#r;#u;#c;#a;#l;#f;#p;#b;#h;#m;#d;#_=1;#g=!1;#s;#o=0;#S=0;#E=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.#s=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([R(this.#p+"osc_out_prescheduler_worker.js",{type:"module"}),R(this.#p+"osc_in_worker.js",{type:"module"}),R(this.#p+"debug_worker.js",{type:"module"}),R(this.#p+"osc_out_log_sab_worker.js",{type:"module"})]);this.#c=e,this.#a=t,this.#l=s,this.#f=r,this.#M(),await Promise.all([this.#B(this.#c,"OSC OUT",{maxPendingMessages:this.#s,bypassLookaheadS:this._config.bypassLookaheadS}),this.#B(this.#a,"OSC IN"),this.#B(this.#l,"DEBUG"),this.#B(this.#f,"OSC OUT LOG")]),this.#a.postMessage({type:"start"}),this.#l.postMessage({type:"start"}),this.#f.postMessage({type:"start"}),this.#g=!0}send(e,t){return!this.#g||this._disposed?!1:(this.#c.postMessage({type:"send",oscData:e,sessionId:0,runTag:"",audioTimeS:null,currentTimeS:null}),this.#o++,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.#c.postMessage({type:"send",oscData:e,sessionId:s,runTag:r,audioTimeS:n,currentTimeS:o}),this.#o++,this.#E+=e.length,!0}sendImmediate(e){return!this.#g||this._disposed?!1:(this.#c.postMessage({type:"sendImmediate",oscData:e}),this.#o++,this.#E+=e.length,!0)}createOscChannel(e={}){if(!this.#g)throw new Error("Transport not initialized");let t=e.sourceId??this.#_++,s=new MessageChannel;return this.#c.postMessage({type:"addOscSource"},[s.port1]),B.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.#c.postMessage({type:"cancelSessionTag",sessionId:e,runTag:t})}cancelSession(e){this.#g&&this.#c.postMessage({type:"cancelSession",sessionId:e})}cancelTag(e){this.#g&&this.#c.postMessage({type:"cancelTag",runTag:e})}cancelAll(){this.#g&&this.#c.postMessage({type:"cancelAll"})}cancelAllWithAck(){return this.#g?new Promise(e=>{let t=s=>{s.data.type==="cancelAllAck"&&(this.#c.removeEventListener("message",t),e())};this.#c.addEventListener("message",t),this.#c.postMessage({type:"cancelAll",ack:!0})}):Promise.resolve()}onReply(e){this.#b=e}onDebug(e){this.#h=e}onError(e){this.#m=e}onOscLog(e){this.#d=e}handleOscLog(e){this.#d&&this.#d(e)}getMetrics(){return{oscOutMessagesSent:this.#o,oscOutMessagesDropped:this.#S,oscOutBytesSent:this.#E}}get ready(){return this.#g&&!this._disposed}dispose(){this._disposed||(this.#c&&(this.#c.postMessage({type:"stop"}),this.#c.terminate(),this.#c=null),this.#a&&(this.#a.postMessage({type:"stop"}),this.#a.terminate(),this.#a=null),this.#l&&(this.#l.postMessage({type:"stop"}),this.#l.terminate(),this.#l=null),this.#f&&(this.#f.postMessage({type:"stop"}),this.#f.terminate(),this.#f=null),this.#g=!1,super.dispose())}#w(){this.#y=new Int32Array(this.#i),this.#n=new DataView(this.#i),this.#r=new Uint8Array(this.#i),this.#u=W(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.#a.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.#m&&this.#m(t.error,"oscIn"))},this.#l.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.#m&&this.#m(t.error,"debug"))},this.#c.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.#S++,this.#m&&this.#m(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.#m&&this.#m(t.error,"oscOutLog"))}}getPreschedulerMetrics(){return this.#A}};var v=class extends C{#i;#e;#t;#y;#n;#r;#u;#c=1;#a=null;#l=!1;#f;#p;#b=null;#h=0;#m=0;#d=0;#_=0;#g=0;#s=-1;#o=0;#S=0;#E;#A;constructor(e){super({...e,mode:"postMessage"}),this.#t=e.workerBaseURL,this.#f=e.preschedulerCapacity||65536,this.#p=e.snapshotIntervalMs,this.#E=e.getAudioContextTime,this.#A=e.getNTPStartTime}async initialize(e){if(this.#l)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 R(this.#t+"osc_out_prescheduler_worker.js",{type:"module"}),this.#e.onmessage=s=>{this.#M(s.data)},await this.#w(t.port2),this.#l=!0}setBufferConstants(e){this.#b=e}send(e,t){return!this.#l||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.#l||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.#l||this._disposed?!1:(this.#i.postMessage({type:"osc",oscData:e,bypassCategory:t}),this.#h++,this.#d+=e.length,!0)}createOscChannel(e={}){if(!this.#l)throw new Error("Transport not initialized");let t=e.sourceId??this.#c++,s=new MessageChannel;this.#i.postMessage({type:"addOscPort",sourceId:t},[s.port1]);let r=new MessageChannel;return this.#e.postMessage({type:"addOscSource"},[r.port1]),B.createPostMessage({port:s.port2,preschedulerPort:r.port2,bypassLookaheadS:this._config.bypassLookaheadS,sourceId:t,blocking:e.blocking,nodeIdSource:this._config.nodeIdSource})}cancelSessionTag(e,t){this.#l&&this.#e.postMessage({type:"cancelSessionTag",sessionId:e,runTag:t})}cancelSession(e){this.#l&&this.#e.postMessage({type:"cancelSession",sessionId:e})}cancelTag(e){this.#l&&this.#e.postMessage({type:"cancelTag",runTag:e})}cancelAll(){this.#l&&this.#e.postMessage({type:"cancelAll"})}cancelAllWithAck(){return this.#l?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.#y=e}onDebug(e){this.#n=e}onError(e){this.#r=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.#o++,this.#S+=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.#a}getMetrics(){return{oscInMessagesReceived:this.#_,oscInBytesReceived:this.#g,oscInMessagesDropped:this.#m,debugMessagesReceived:this.#o,debugBytesReceived:this.#S}}get ready(){return this.#l&&!this._disposed}dispose(){this._disposed||(this.#e&&(this.#e.postMessage({type:"stop"}),this.#e.terminate(),this.#e=null),this.#i=null,this.#l=!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.#s>=0){let o=this.#s+1&4294967295;if(r.sequence!==o){let a=r.sequence-o+4294967296&4294967295;a<1e3&&(this.#m+=a)}}r.sequence!==void 0&&(this.#s=r.sequence),this.#_++,this.#g+=r.length,this.#y&&this.#y(n,r.sequence,A())}}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:A(),truncated:n.length<n.originalLength,originalLength:n.originalLength})}this.#u(s)}break;case"error":console.error("[PostMessageTransport] Worklet error:",e.error),this.#m++,this.#r&&this.#r(e.error,"worklet");break;case"debug":break}}#M(e){switch(e.type){case"preschedulerMetrics":this.#a=e.metrics;break;case"error":console.error("[PostMessageTransport] Prescheduler error:",e.error),this.#m++,this.#r&&this.#r(e.error,"oscOut");break}}};function Ke(i,e){if(i==="sab")return new x(e);if(i==="postMessage")return new v(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 je={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},Nt={i8:Int8Array,i16:Int16Array,i32:Int32Array},xt={u8:Uint8Array,u8c:Uint8ClampedArray,u16:Uint16Array,u32:Uint32Array},vt={i64:BigInt64Array,u64:BigUint64Array},Ht={...Ft,...Nt,...xt},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 H=(i,e)=>(e--,i+e&~e);var Je=i=>typeof i=="number";var q=(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 $t=q(()=>"Assertion failed"),de=(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 $t(typeof e=="function"?e():e)}:()=>{};var Yt=q(()=>"illegal argument(s)"),et=i=>{throw new Yt(i)};var tt=0,st=1,rt=2,it=3,nt=4,F=5,ot=6,pe=1,me=2,at=7*4,ye=0,Se=1,w=2*4,$=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?H(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,at/4),!e.skipInitialization){let t=e.align||8;de(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&&et(`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*je[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=H(e+w,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,z(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 z(e)}realloc(e,t){if(t<=0)return 0;let s=Ee(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(z(r),z(s),o),z(r)}reallocBlock(e,t){let s=this.blockSize(e),r=e+s,n=r>=this.top,o=H(t+w,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),[Ee(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=Ee(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[nt]}set align(e){this.state[nt]=e}get end(){return this.state[it]}set end(e){this.state[it]=e}get top(){return this.state[rt]}set top(e){this.state[rt]=e}get _free(){return this.state[tt]}set _free(e){this.state[tt]=e}get _used(){return this.state[st]}set _used(e){this.state[st]=e}get doCompact(){return!!(this.state[F]&pe)}set doCompact(e){e?this.state[F]|=1<<pe-1:this.state[F]&=~pe}get doSplit(){return!!(this.state[F]&me)}set doSplit(e){e?this.state[F]|=1<<me-1:this.state[F]&=~me}get minSplit(){return this.state[ot]}set minSplit(e){de(e>w,`illegal min split threshold: ${e}, require at least ${w+1}`),this.state[ot]=e}blockSize(e){return this.u32[(e>>2)+ye]}setBlockSize(e,t){return this.u32[(e>>2)+ye]=t,t}blockNext(e){return this.u32[(e>>2)+Se]}setBlockNext(e,t){this.u32[(e>>2)+Se]=t}initBlock(e,t,s){let r=e>>>2;return this.u32[r+ye]=t,this.u32[r+Se]=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 H(this.start+at+w,e)-w}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 u=this.blockNext(c);this.setBlockNext(c,0),c=u}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)}},z=i=>i>0?i+w:0,Ee=i=>i>0?i-w:0;function ct(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 Gt(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 ge(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 lt(i){let e=new DataView(i),t=String.fromCharCode(e.getUint8(8),e.getUint8(9),e.getUint8(10),e.getUint8(11)),s=ge(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=Gt(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 u=ge(e,"SSND");if(!u)throw new Error("AIFF file missing SSND chunk");let l=e.getUint32(u.offset,!1),f=u.offset+8+l,h=o/8,E=n*r*h;if(f+E>i.byteLength)throw new Error("AIFF file truncated: not enough audio data");let p=44,g=new ArrayBuffer(p+E),m=new DataView(g),S=new Uint8Array(g);ut(m,{numChannels:r,sampleRate:Math.round(c),bitsPerSample:o,dataSize:E});let _=new Uint8Array(i,f,E);if(h===1)for(let d=0;d<E;d++)S[p+d]=_[d]+128;else if(h===2)for(let d=0;d<E;d+=2)S[p+d]=_[d+1],S[p+d+1]=_[d];else if(h===3)for(let d=0;d<E;d+=3)S[p+d]=_[d+2],S[p+d+1]=_[d+1],S[p+d+2]=_[d];else if(h===4)for(let d=0;d<E;d+=4)S[p+d]=_[d+3],S[p+d+1]=_[d+2],S[p+d+2]=_[d+1],S[p+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=ge(n,"SSND");if(!o)throw new Error("AIFF file missing SSND chunk");let a=n.getUint32(o.offset,!1),c=o.offset+8+a,u=s/8,l=t*e*u;if(c+l>i.byteLength)throw new Error("AIFF file truncated: not enough audio data");let f=44,h=new ArrayBuffer(f+l),E=new DataView(h),p=new Uint8Array(h);ut(E,{numChannels:e,sampleRate:Math.round(r),bitsPerSample:s,dataSize:l});let g=new Uint8Array(i,c,l);if(u===1)for(let m=0;m<l;m++)p[f+m]=g[m]+128;else p.set(g,f);return h}function ut(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 ft=8,Z=class{#i;#e;#t;#y;#n;#r;#u;#c;#a;#l;#f;#p;constructor(e){let{mode:t="sab",audioContext:s,sharedBuffer:r,bufferPoolConfig:n,sampleBaseURL:o,maxBuffers:a=1024,assetLoader:c=null,workletPort:u=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.#y=s,this.#n=r,this.#e=o,this.#t=c,this.#p=u,t==="sab")this.#r=new $({buf:r,start:n.start,size:n.size,align:ft}),this.#u=n.size,this.#c=n.start;else{let h=new ArrayBuffer(n.start+n.size);this.#r=new $({buf:h,start:n.start,size:n.size,align:ft}),this.#u=n.size,this.#c=n.start}this.#a=new Map,this.#l=new Map,this.#f=new Map,this.GUARD_BEFORE=3,this.GUARD_AFTER=1,this.MAX_BUFFERS=a;let l=(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 m=this.#g(e),S=e.split("/").pop();n=await this.#t.fetch(m,{type:"sample",name:S}),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)),u=a.length-c,l=s&&s>0?Math.min(Math.floor(s),u):u;if(l<=0)throw new Error("No audio frames available");let f=this.#S(r,a.numberOfChannels),h=f.length,E=l*h+(this.GUARD_BEFORE+this.GUARD_AFTER)*h,p=new Float32Array(E),g=this.GUARD_BEFORE*h;for(let m=0;m<l;m++)for(let S=0;S<h;S++){let _=a.getChannelData(f[S]);p[g+m*h+S]=_[c+m]}return{interleaved:p,numFrames:l,numChannels:h,sampleRate:a.sampleRate,sourceInfo:o}}async#m(e){let t=this.#E(e.length);return await this.#A(t,e),t}async#d(e,t,s,r){let n,o=await this.#o(e,t,async()=>{let[c,u]=await Promise.all([this.#b(s.interleaved),this.#m(s.interleaved)]);return n=c,{ptr:u,sizeBytes:s.interleaved.length*4,numFrames:s.numFrames,numChannels:s.numChannels,sampleRate:s.sampleRate,source:r||null}}),a=this.#a.get(e);return a&&(a.hash=n),{...o,hash:n}}async#_(e){return ct(e)&&(e=lt(e)),this.#y.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}#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.
5
+ Or install: npm install supersonic-scsynth-samples`);return this.#e+e}#s(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#o(e,t,s){let r=null,n=null,o=!1,a=await this.#M(e),c=!1;try{await this.#I(e);let{ptr:u,sizeBytes:l,numFrames:f,numChannels:h,sampleRate:E,source:p,...g}=await s();r=u;let{uuid:m,allocationComplete:S}=this.#B(e,t);n=m,this.#R(e,r,l,m,S,{numFrames:f,numChannels:h,sampleRate:E,source:p}),o=!0;let _=this.#O(e,m,S);return a(),c=!0,{ptr:r,uuid:m,allocationComplete:_,numFrames:f,numChannels:h,sampleRate:E,...g}}catch(u){throw o&&n?this.#C(e,n,!1):r&&this.#r.free(r),u}finally{c||a()}}async prepareFromBlob(e){let{bufnum:t,blob:s,startFrame:r=0,numFrames:n=0,channels:o=null}=e;if(this.#s(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.#s(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.#s(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,l={interleaved:new Float32Array(c),numFrames:o,numChannels:a,sampleRate:n||this.#y.sampleRate};return this.#d(t,5e3,l,null)}#S(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.#r.malloc(t);if(s===0){let r=this.#r.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),u=l=>{let f=l.data;f.type==="bufferCopied"&&f.copyId===s&&(this.#p.removeEventListener("message",u),clearTimeout(c),f.success?o():a(new Error(f.error||"Buffer copy failed")))};this.#p.addEventListener("message",u)}),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.#l.delete(e),n(new Error(`Buffer ${t} allocation timeout (${s}ms)`))},s);this.#l.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.#a.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.#a.set(e,c),c}async#I(e){let t=this.#a.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.#a.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.#r.free(n.ptr);return}r.ptr&&this.#r.free(r.ptr),r.pendingPromise=null,n?.ptr?this.#a.set(e,{ptr:n.ptr,size:n.size,pendingToken:null,previousAllocation:null}):this.#a.delete(e)}handleBufferFreed(e){let t=e[0],s=e[1],r=this.#a.get(t);if(!r){typeof s=="number"&&s!==0&&this.#r.free(s);return}if(typeof s=="number"&&s===r.ptr){this.#r.free(r.ptr),this.#a.delete(t);return}if(typeof s=="number"&&r.previousAllocation&&r.previousAllocation.ptr===s){this.#r.free(s),r.previousAllocation=null;return}this.#r.free(r.ptr),this.#a.delete(t)}handleBufferAllocated(e){let t=e[0],s=e[1],r=this.#l.get(t);r&&(clearTimeout(r.timeout),r.resolve({bufnum:s}),this.#l.delete(t))}allocate(e){let t=e*4,s=this.#r.malloc(t);if(s===0){let r=this.#r.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.#r.free(e)}getView(e,t){return new Float32Array(this.#n,e,t)}getStats(){return this.#r?this.#r.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.#a.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.#y=e}getDiagnostics(){let e=this.#r.stats(),t=0,s=0;for(let r of this.#a.values())r&&(t+=r.size||0,r.pendingToken&&s++);return{active:this.#a.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.#l.entries())clearTimeout(t.timeout),t.reject(new Error("BufferManager destroyed"));this.#l.clear();for(let[e,t]of this.#a.entries())t.ptr&&this.#r.free(t.ptr);this.#a.clear(),this.#f.clear()}};var X=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.#y(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#y(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.#r(n)}}throw t}#r(e){return new Promise(t=>setTimeout(t,e))}};var K=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.#a(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.#y(s),changed:!0};case"/b_allocRead":return{message:await this.#n(s),changed:!0};case"/b_allocReadChannel":return{message:await this.#r(s),changed:!0};case"/b_allocFile":return{message:await this.#u(s),changed:!0};default:return{message:e,changed:!1}}}async#y(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.#l(e,r))&&(n=Math.max(1,this.#b(e,r,1)),r++),this.#l(e,r)?.type==="b"&&r++,this.#d(this.#l(e,r))&&(o=this.#f(this.#l(e,r)));let a=await this.#i.prepareEmpty({bufnum:t,numFrames:s,numChannels:n,sampleRate:o});return this.#_(a.allocationComplete,`/b_alloc ${t}`),this.#c(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.#c(t,o)}async#r(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.#c(t,a)}async#u(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.#i.prepareFromBlob({bufnum:t,blob:s});return this.#_(r.allocationComplete,`/b_allocFile ${t}`),this.#c(t,r)}#c(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)]}#a(e){return e&&e.timeTag!==void 0&&Array.isArray(e.packets)}#l(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.#l(e,t));if(!Number.isFinite(r))throw new Error(s);return Math.floor(r)}#b(e,t,s=0){let r=this.#f(this.#l(e,t));return Number.isFinite(r)?Math.floor(r):s}#h(e,t,s){let r=this.#f(this.#l(e,t));if(typeof r!="string")throw new Error(s);return r}#m(e,t,s){let r=this.#f(this.#l(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 N(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{#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 Q=class{#i;#e;#t;#y;#n;#r;#u;#c=null;#a=new Uint32Array(64);#l=new DataView(this.#a.buffer);constructor(e={}){this.#y=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.#y==="sab"&&e&&s){this.#n=new Int32Array(e),this.#u=Ze(t,s.CONTROL_START);let r=t+s.METRICS_START;this.#r=new Uint32Array(e,r,s.METRICS_SIZE/4)}}updateSnapshot(e){this.#c=e}getSnapshotBuffer(){return this.#c}getMetricsView(){return this.#r}addMetric(e,t=1){if(!this.#r)return;let r={oscOutMessagesSent:24,oscOutBytesSent:25,preschedulerBypassed:22,bypassNonBundle:38,bypassImmediate:39,bypassNearFuture:40,bypassLate:41}[e];r!==void 0&&Atomics.add(this.#r,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.#r?this.parseMetricsBuffer(this.#r):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),u=Atomics.load(s,t.DEBUG_TAIL),l=(r-n+e.IN_BUFFER_SIZE)%e.IN_BUFFER_SIZE,f=(o-a+e.OUT_BUFFER_SIZE)%e.OUT_BUFFER_SIZE,h=(c-u+e.DEBUG_BUFFER_SIZE)%e.DEBUG_BUFFER_SIZE;return{inBufferUsed:{bytes:l,percentage:l/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.#c||!e)return;let t=new Uint32Array(this.#c,0,46),s=9,r=13;t.set(e.subarray(s,s+r),s),t[23]=e[23]}gatherMetrics(e={}){let t;if(this.#y==="postMessage")if(e.preschedulerMetrics&&this.overlayPreschedulerMetrics(e.preschedulerMetrics),this.#c){let s=new Uint32Array(this.#c,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.#y,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.#y==="postMessage"&&e.transportMetrics&&Object.assign(t,e.transportMetrics),t}updateMergedArray(e={}){let t=this.#a;if(this.#y==="postMessage"){if(e.preschedulerMetrics&&this.overlayPreschedulerMetrics(e.preschedulerMetrics),this.#c){let a=new Uint32Array(this.#c,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.#r&&t.set(this.#r);let s=this.#l;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.#y==="sab"?0:1}getMergedArray(){return this.#a}get bufferConstants(){return this.#t}get ringBufferBase(){return this.#e}get sharedBuffer(){return this.#i}};function J(i){return i/1e3+2208988800}function Te(i,e){return i-e}function ht(i,e){let t=i-e;return Math.round(t*1e3)}var ee=class{#i;#e;#t;#y;#n;#r;#u;#c;#a;#l=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.#y=s,this.#i==="sab"&&e&&s&&(this.#r=new Float64Array(e,t+s.NTP_START_TIME_START,1),this.#u=new Int32Array(e,t+s.DRIFT_OFFSET_START,1),this.#c=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=J(t),r=e.contextTime,n=Te(s,r);this.#i==="sab"&&this.#r?this.#r[0]=n:this.#t&&this.#t.postMessage({type:"setNTPStartTime",ntpStartTime:n}),this.#a=n,await new Promise(o=>setTimeout(o,500)),this.updateDriftOffset()}updateDriftOffset(){if(!this.#e||this.#a===void 0)return;let e=this.#e.getOutputTimestamp(),t=performance.timeOrigin+e.performanceTime,r=J(t)-this.#a,n=ht(r,e.contextTime);this.#l=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=J(t),r=Te(s,e.contextTime);this.#i==="sab"&&this.#r?this.#r[0]=r:this.#t&&this.#t.postMessage({type:"setNTPStartTime",ntpStartTime:r}),this.#a=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.#l}getNTPStartTime(){return this.#r?this.#r[0]:this.#a??0}getClockOffset(){return this.#c?Atomics.load(this.#c,0):this.#f}setClockOffset(e){let t=Math.round(e*1e3);this.#f=t,this.#i==="sab"&&this.#c?Atomics.store(this.#c,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,u=new DataView(e.buffer,e.byteOffset),l=u.getUint32(8,!1),f=u.getUint32(12,!1);if(l===0&&(f===0||f===1))return null;let E=l+f/4294967296-c,p=this.#e?.currentTime??0;return{audioTimeS:E,currentTimeS:p}}reset(){this.stopDriftTimer(),this.#a=void 0,this.#l=0,this.#f=0,this.#r=null,this.#u=null,this.#c=null}};var te=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),u=new Float32Array(r),l=o>1?new Float32Array(r):null;for(let f=0;f<r;f++)u[f]=c[f*o],l&&(l[f]=c[f*o+1]);return{sampleRate:n,channels:o,frames:r,left:u,right:l}}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 dt(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,u=s.NODE_TREE_MIRROR_MAX_NODES,l=s.NODE_TREE_ENTRY_SIZE,f=s.NODE_TREE_DEF_NAME_SIZE,h=new DataView(i,c,u*l),E=new TextDecoder("utf-8"),p=[],g=0;for(let m=0;m<u&&g<n;m++){let S=m*l,_=h.getInt32(S,!0);if(_===-1)continue;g++;let d=c+S+24,M=new Uint8Array(i,d,f),ce=new Uint8Array(f);ce.set(M);let le=ce.indexOf(0);le===-1&&(le=f);let Ut=E.decode(ce.subarray(0,le));p.push({id:_,parentId:h.getInt32(S+4,!0),isGroup:h.getInt32(S+8,!0)===1,prevId:h.getInt32(S+12,!0),nextId:h.getInt32(S+16,!0),headId:h.getInt32(S+20,!0),defName:Ut})}return{nodeCount:n,version:o,droppedCount:a,nodes:p}}var De=new Uint8Array(2097152),pt=new DataView(De.buffer),y=De,b=pt,Ae=new Map,Zs=1e3,Xs=new TextDecoder,Ks=new TextEncoder,Le=2208988800,ie=4294967296,Pe=new Uint8Array([35,98,117,110,100,108,101,0]),mt=44,we=105,Me=102,Ce=115,Re=98,Oe=84,Ue=70,yt=104,St=100,Et=116,gt=117;function se(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 s&&s.type==="uuid"?t+=16:t+=8;return t}function _t(i){let e=16;for(let t of i)e+=4,Array.isArray(t)?e+=se(t[0],t.slice(1)):t.packets!==void 0?e+=_t(t.packets):e+=se(t.address,t.args||[]);return e}function ke(i){if(i<=2097152){y=De,b=pt;return}y=new Uint8Array(i),b=new DataView(y.buffer)}function bt(i,e=[]){let t=se(i,e);ke(t);let s=0;s=Fe(i,s),s=Ne(e,s);for(let r=0;r<e.length;r++)s=ne(e[r],s);return y.subarray(0,s)}function Tt(i,e){let t=_t(e);ke(t);let s=0;y.set(Pe,s),s+=8,s=oe(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=re(n[0],n.slice(1),s):n.packets!==void 0?s=Bt(n.timeTag,n.packets,s):s=re(n.address,n.args||[],s);let c=s-a;b.setUint32(o,c,!1)}return y.subarray(0,s)}function At(i,e,t=[]){let s=20+se(e,t);ke(s);let r=0;y.set(Pe,r),r+=8,r=oe(i,r);let n=r;r+=4;let o=r;r=Fe(e,r),r=Ne(t,r);for(let a=0;a<t.length;a++)r=ne(t[a],r);return b.setUint32(n,r-o,!1),y.subarray(0,r)}function re(i,e,t){t=Fe(i,t),t=Ne(e,t);for(let s=0;s<e.length;s++)t=ne(e[s],t);return t}function Bt(i,e,t){y.set(Pe,t),t+=8,t=oe(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=re(r[0],r.slice(1),t):r.packets!==void 0?t=Bt(r.timeTag,r.packets,t):t=re(r.address,r.args||[],t),b.setUint32(n,t-o,!1)}return t}function Fe(i,e){let t=Ae.get(i);if(t)return y.set(t,e),e+t.length;let s=e;if(e=Ie(i,e),Ae.size<Zs){let r=y.slice(s,e);Ae.set(i,r)}return e}function Ie(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=Ks.encodeInto(i,y.subarray(e));e+=s.written}else for(let s=0;s<i.length;s++)y[e++]=i.charCodeAt(s);for(y[e++]=0;e&3;)y[e++]=0;return e}function Ne(i,e){y[e++]=mt;for(let t=0;t<i.length;t++){let s=i[t],r=typeof s;if(r==="number")y[e++]=Number.isInteger(s)?we:Me;else if(r==="string")y[e++]=Ce;else if(r==="boolean")y[e++]=s?Oe:Ue;else if(s instanceof Uint8Array||s instanceof ArrayBuffer)y[e++]=Re;else if(s&&s.type==="int")y[e++]=we;else if(s&&s.type==="float")y[e++]=Me;else if(s&&s.type==="string")y[e++]=Ce;else if(s&&s.type==="blob")y[e++]=Re;else if(s&&s.type==="bool")y[e++]=s.value?Oe:Ue;else if(s&&s.type==="int64")y[e++]=yt;else if(s&&s.type==="double")y[e++]=St;else if(s&&s.type==="timetag")y[e++]=Et;else if(s&&s.type==="uuid")y[e++]=gt;else throw s==null?new Error(`OSC argument at index ${t} is ${s}`):new Error(`Unknown OSC argument type at index ${t}: ${r}`)}for(y[e++]=0;e&3;)y[e++]=0;return e}function ne(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 Ie(i,e);if(t==="boolean")return e;if(i instanceof Uint8Array){let s=i.length;for(b.setUint32(e,s,!1),e+=4,y.set(i,e),e+=s;e&3;)y[e++]=0;return e}if(i instanceof ArrayBuffer)return ne(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 Ie(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,y.set(s,e),e+=r;e&3;)y[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"?oe(i.value,e):i&&i.type==="uuid"?(y.set(i.value,e),e+16):e}function oe(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<Le&&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))*ie>>>0;return b.setUint32(e,t,!1),b.setUint32(e+4,s,!1),e+8}function Y(i){return i instanceof Uint8Array||(i=new Uint8Array(i)),i[0]===35&&i[1]===98?Qs(i):js(i)}function js(i){i instanceof Uint8Array||(i=new Uint8Array(i));let e=new DataView(i.buffer,i.byteOffset,i.byteLength),t=0,[s,r]=Be(i,t);if(t=r,t>=i.length||i[t]!==mt)return[s];let[n,o]=Be(i,t);t=o;let a=[s];for(let c=1;c<n.length;c++)switch(n.charCodeAt(c)){case we:a.push(e.getInt32(t,!1)),t+=4;break;case Me:a.push(e.getFloat32(t,!1)),t+=4;break;case Ce:let[l,f]=Be(i,t);a.push(l),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 St:a.push(e.getFloat64(t,!1)),t+=8;break;case Oe:a.push(!0);break;case Ue:a.push(!1);break;case Et:let E=e.getUint32(t,!1),p=e.getUint32(t+4,!1);a.push(E+p/ie),t+=8;break;case gt:a.push({type:"uuid",value:i.slice(t,t+16)}),t+=16;break}return a}function Qs(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/ie;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(Y(c))}t+=a}return{timeTag:n,packets:o}}function Be(i,e){let t=e;for(;t<i.length&&i[t]!==0;)t++;let s=Xs.decode(i.subarray(e,t));return t++,t=t+3&-4,[s,t]}function ae(i){return i.slice()}function Js(i){return!i||i.length<8?!1:i[0]===35&&i[1]===98}function xe(i){if(!Js(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/ie}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 ir=new Set(["/b_alloc","/b_allocRead","/b_allocReadChannel","/b_allocFile"]),T=[];for(let i=0;i<256;i++)T[i]=i.toString(16).padStart(2,"0");function Rt(i){return T[i[0]]+T[i[1]]+T[i[2]]+T[i[3]]+"-"+T[i[4]]+T[i[5]]+"-"+T[i[6]]+T[i[7]]+"-"+T[i[8]]+T[i[9]]+"-"+T[i[10]]+T[i[11]]+T[i[12]]+T[i[13]]+T[i[14]]+T[i[15]]}function Ct(i,e){if(i&&i.type==="uuid"&&i.value)return Rt(i.value);if(i instanceof Uint8Array||i instanceof ArrayBuffer)return`<${i.byteLength||i.length} bytes>`;let t=JSON.stringify(i);return e&&t.length>e?t.slice(0,e)+"...":t}function G(i){return String(i).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Ot(i,e,t){if(i&&i.type==="uuid"&&i.value)return`<span class="supersonic-scsynth-string">${Rt(i.value)}</span>`;let s=i,r=null;if(typeof i=="object"&&i!==null&&i.value!==void 0&&(s=i.value,r=i.type),r==="b"||s instanceof Uint8Array||s instanceof ArrayBuffer)return`<span class="supersonic-scsynth-binary">&lt;${s.byteLength??s.length??"?"} bytes&gt;</span>`;let n=r==="f"||r===null&&typeof s=="number"&&!Number.isInteger(s),o=r==="i"||r===null&&Number.isInteger(s),c=e==="/s_new"&&t>=4&&(t-4)%2===0&&typeof s=="string";return n?`<span class="supersonic-scsynth-float">${parseFloat(s.toFixed(3))}</span>`:o?`<span class="supersonic-scsynth-int">${s}</span>`:c?`<span class="supersonic-scsynth-param">${G(s)}</span>`:typeof s=="string"?`<span class="supersonic-scsynth-string">${G(JSON.stringify(s))}</span>`:`<span class="supersonic-scsynth-string">${G(s)}</span>`}function ve(i,e,t,s,r){let n=i[0],o=i.slice(1),a=s&&t?(t-s).toFixed(2):"",c=`<span class="supersonic-scsynth-seq">[${e}]</span>`;if(a&&(c+=` <span class="supersonic-scsynth-time">${a}</span>`),r!==void 0&&(c+=` <span class="supersonic-scsynth-source">ch${r}</span>`),c+=` <span class="supersonic-scsynth-address">${G(n)}</span>`,o.length>0){let u=o.map((l,f)=>Ot(l,n,f)).join(", ");c+=" "+u}return c}function nr(i,e,t,s,r){if(!i.packets)return ve(i,e,t,s,r);if(i.packets.length===1)return ve(i.packets[0],e,t,s,r);let n=s&&t?(t-s).toFixed(2):"",o=`<span class="supersonic-scsynth-seq">[${e}]</span>`;n&&(o+=` <span class="supersonic-scsynth-time">${n}</span>`),r!==void 0&&(o+=` <span class="supersonic-scsynth-source">ch${r}</span>`),o+=` <span class="supersonic-scsynth-bundle">Bundle (${i.packets.length})</span>`;for(let a of i.packets){let c=a[0],u=a.slice(1);o+=`<br><span class="supersonic-scsynth-address">${G(c)}</span>`,u.length>0&&(o+=" "+u.map((l,f)=>Ot(l,c,f)).join(", "))}return o}var He=class i{static osc={encodeMessage:(e,t)=>ae(bt(e,t)),encodeBundle:(e,t)=>ae(Tt(e,t)),decode:e=>Y(e),encodeSingleBundle:(e,t,s)=>ae(At(e,t,s)),readTimetag:e=>fe(e),ntpNow:()=>A(),NTP_EPOCH_OFFSET:Le};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;#y=null;#n;#r;#u;#c;#a;#l;#f;#p;#b;#h;#m;#d;#_;#g;#s;#o;#S;#E;#A;#w;#B=1e3;#M=null;#R=null;#I=0;#O=[];#C=null;#U=Promise.resolve();#$(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.#m=!1,this.#d=null,this.#_={},this.#g=null,this.#o=new j,this.#S=new Q({mode:e.mode||"postMessage"}),this.#A=new te({}),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={...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+=`
17
+ See: https://github.com/samaaron/supersonic#configuration`);let o={...Mt,...e.scsynthOptions};this.#$(o);let a=e.mode||"postMessage";this.#s={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},this.#l=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 X({onLoadingEvent:(c,u)=>this.#o.emit(c,u),maxRetries:this.#p.maxRetries,baseDelay:this.#p.baseDelay}),this.bootStats={initStartTime:null,initDuration:null}}get initialized(){return this.#h}get initializing(){return this.#m}get audioContext(){return this.#e}get mode(){return this.#s.mode}get bufferConstants(){return this.#S.bufferConstants}get ringBufferBase(){return this.#S.ringBufferBase}get sharedBuffer(){return this.#S.sharedBuffer}get node(){return this.#y}get osc(){return this.#n}get initTime(){return this.#E?.getNTPStartTime()??0}on(e,t){return this.#o.on(e,t)}off(e,t){return this.#o.off(e,t),this}once(e,t){return this.#o.once(e,t)}removeAllListeners(e){return this.#o.removeAllListeners(e),this}async init(){if(!this.#h)return this.#d?this.#d:(this.#d=this.#Y(),this.#d)}async#Y(){this.#m=!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.#N()}catch(e){throw this.#m=!1,this.#d=null,console.error("[SuperSonic] Initialization failed:",e),this.#o.emit("error",e),e}}getMetrics(){return this.#v()}getMetricsArray(){return this.#Q(),this.#S.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.#E?.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.#E?.startDriftTimer();let e=this.#H();if(e===null){let r=this.#e.state==="running";return r&&(this.#E?.resync(),this.#o.emit("resumed")),r}await new Promise(r=>setTimeout(r,200));let t=this.#H(),s=t!==null&&t>e;return s&&(this.#E?.resync(),this.#o.emit("resumed")),s}async suspend(){if(this.#h){this.#E?.stopDriftTimer();try{await this.#e?.suspend()}catch{}}}async reload(){if(!this.#h)return!1;this.#o.emit("reload:start");let e=new Map(this.loadedSynthDefs),t=this.#u?.getAllocatedBuffers()||[];await this.#G(),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.#s.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.#o.emit("reload:complete",{success:!0}),!0}async#G(){this.#E?.stopDriftTimer(),this.#a?.clear(),this.#a=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.#E?.reset()}async#W(){this.#m=!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.#N()}catch(e){throw this.#m=!1,this.#d=null,console.error("[SuperSonic] Partial init failed:",e),this.#o.emit("error",e),e}}getRawTree(){if(!this.#h)return{nodeCount:0,version:0,droppedCount:0,nodes:[]};let e=this.#S.bufferConstants;if(!e)return{nodeCount:0,version:0,droppedCount:0,nodes:[]};let t,s;if(this.#s.mode==="postMessage"){let r=this.#S.getSnapshotBuffer();if(!r)return{nodeCount:0,version:0,droppedCount:0,nodes:[]};t=r,s=e.METRICS_SIZE}else{let r=this.#S.sharedBuffer;if(!r)return{nodeCount:0,version:0,droppedCount:0,nodes:[]};t=r,s=this.#S.ringBufferBase+e.NODE_TREE_START}return dt(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=N(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(ir.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=N(r),o=await this.#b.fetch(r,{type:"synthdef",name:n});t=new Uint8Array(o),s=N(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=N(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=N(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 u=await t.arrayBuffer();n=await this.#u.prepareFromBlob({bufnum:e,blob:u,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.#a?.delete(e),r(new Error("Timeout waiting for /synced response"))},1e4),o=()=>{clearTimeout(n),this.#a.delete(e),s()};this.#a||(this.#a=new Map),this.#a.set(e,o)});this.send("/sync",e),await t,this.#s.mode==="postMessage"&&await new Promise(s=>setTimeout(s,this.#s.snapshotIntervalMs*2))}getInfo(){return this.#T("get info"),{sampleRate:this.#e.sampleRate,numBuffers:this.#s.worldOptions.numBuffers,totalMemory:this.#s.memory.totalMemory,wasmHeapSize:this.#s.memory.wasmHeapSize,bufferPoolSize:this.#s.memory.bufferPoolSize,bootTimeMs:this.bootStats.initDuration,capabilities:{...this.#_},version:this.#g}}async shutdown(){!this.#h&&!this.#m||(this.#o.emit("shutdown"),this.#E?.stopDriftTimer(),this.#a?.clear(),this.#a=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.#c=null,this.#w=null,this.#U=Promise.resolve(),this.#h=!1,this.loadedSynthDefs.clear(),this.#d=null,this.#r=null,this.#E?.reset(),this.bootStats={initStartTime:null,initDuration:null})}async destroy(){this.#o.emit("destroy"),await this.shutdown(),this.#R=null,this.#o.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.#s.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'.`)}#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};
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.#s.memory;this.#s.mode==="sab"?this.#r=new WebAssembly.Memory({initial:e.totalPages,maximum:e.totalPages,shared:!0}):this.#r=null}#D(){this.#s.audioContext?this.#e=this.#s.audioContext:this.#e=new AudioContext(this.#s.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.#E?.resync(),this.#o.emit("audiocontext:statechange",{state:e}),e==="suspended"?this.#o.emit("audiocontext:suspended"):e==="running"?this.#o.emit("audiocontext:resumed"):e==="interrupted"&&this.#o.emit("audiocontext:interrupted")})}#Z(){let e=this.#s.mode==="sab"?this.#r.buffer:null;this.#u=new Z({mode:this.#s.mode,audioContext:this.#e,sharedBuffer:e,bufferPoolConfig:{start:this.#s.memory.bufferPoolOffset,size:this.#s.memory.bufferPoolSize},sampleBaseURL:this.#l,maxBuffers:this.#s.worldOptions.numBuffers,assetLoader:this.#b})}#L(){this.#c=new K({bufferManager:this.#u,getDefaultSampleRate:()=>this.#e?.sampleRate||44100})}async#P(){if(this.#R)return this.#R;let e=this.#s.wasmUrl.split("/").pop();this.#o.emit("loading:start",{type:"wasm",name:e});let t=await fetch(this.#s.wasmUrl);if(!t.ok)throw new Error(`Failed to load WASM: ${t.status} ${t.statusText}`);let s=await t.arrayBuffer();return this.#o.emit("loading:complete",{type:"wasm",name:e,size:s.byteLength}),this.#R=s,s}async#k(e){await Ye(this.#e.audioWorklet,this.#s.workletUrl);let t=this.#s.worldOptions.numOutputBusChannels;if(this.#t=new AudioWorkletNode(this.#e,"scsynth-processor",{numberOfInputs:1,numberOfOutputs:1,outputChannelCount:[t]}),this.#s.autoConnect){let o=this.#e.destination;t>2&&(o.channelCount=Math.min(t,o.maxChannelCount),o.channelInterpretation="discrete"),this.#t.connect(o)}this.#y=this.#X(),this.#t.port.start(),this.#j();let s=this.#s.mode,r=s==="sab"?this.#r.buffer:null;this.#t.port.postMessage({type:"init",mode:s,sharedBuffer:r,snapshotIntervalMs:this.#s.snapshotIntervalMs});let n={type:"loadWasm",wasmBytes:e,worldOptions:this.#s.worldOptions,sampleRate:this.#e.sampleRate};s==="sab"?n.wasmMemory=this.#r:n.memoryPages=this.#s.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.#s.mode,t=this.#S.bufferConstants,s=this.#S.ringBufferBase,r=this.#S.sharedBuffer,n={workerBaseURL:this.#s.workerBaseURL,preschedulerCapacity:this.#s.preschedulerCapacity,snapshotIntervalMs:this.#s.snapshotIntervalMs,bypassLookaheadS:this.#s.bypassLookaheadMs/1e3,getAudioContextTime:()=>this.#e?.currentTime??0,getNTPStartTime:()=>this.#E?.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=l=>{let f=this.#B;return this.#B+=l,{from:f,to:f+l}};let o=1e4,a=n.nodeIdSource(o),c=new MessageChannel,u=n.nodeIdSource;c.port1.onmessage=l=>{if(l.data.type==="requestNodeIdRange"){let f=u(o);c.port1.postMessage({type:"nodeIdRange",from:f.from,to:f.to})}},this.#t.port.postMessage({type:"nodeIdRange",from:a.from,to:a.to},[c.port2])}if(this.#n=Ke(e,n),this.#n.onReply((o,a,c)=>{let u=xe(o)||null;this.#o.emit("in:osc",{oscData:o,sequence:a,timestamp:c,scheduledTime:u});try{let l=Y(o),f=l[0],h=l.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 E=h[0];this.#a?.has(E)&&this.#a.get(E)(l)}if(this.#o.emit("in",l),this.#o.hasListeners("in:text")||this.#s.debug||this.#s.debugOscIn){let E=this.#s.activityEvent.oscInMaxLineLength??this.#s.activityEvent.maxLineLength,p=h.map(m=>Ct(m,E)).join(", ")||"",g=`${f}${p?" "+p:""}`;this.#o.emit("in:text",{text:g,sequence:a,timestamp:c})}if(this.#o.hasListeners("in:html")){let E=ve(l,a,c,this.initTime);this.#o.emit("in:html",{html:E,sequence:a,timestamp:c})}}catch(l){console.error("[SuperSonic] Failed to decode OSC message:",l)}}),this.#n.onDebug(o=>{let a=this.#s.activityEvent.scsynthMaxLineLength??this.#s.activityEvent.maxLineLength;a>0&&o.text?.length>a&&(o={...o,text:o.text.slice(0,a)+"..."}),this.#o.emit("debug",o)}),this.#n.onError((o,a)=>{console.error(`[SuperSonic] ${a} error:`,o),this.#o.emit("error",new Error(`${a}: ${o}`))}),this.#n.onOscLog(o=>{for(let a of o){let c=xe(a.oscData)||null;if(this.#o.emit("out:osc",{oscData:a.oscData,sourceId:a.sourceId,sequence:a.sequence,timestamp:a.timestamp,scheduledTime:c}),this.#o.hasListeners("out")||this.#o.hasListeners("out:text")||this.#o.hasListeners("out:html")||this.#s.debug||this.#s.debugOscOut)try{let l=Y(a.oscData);if(this.#o.emit("out",l),this.#o.hasListeners("out:text")||this.#s.debug||this.#s.debugOscOut){let f=this.#s.activityEvent.oscOutMaxLineLength??this.#s.activityEvent.maxLineLength,h=l[0],p=l.slice(1).map(m=>Ct(m,f)).join(", "),g=`${h}${p?" "+p:""}`;this.#o.emit("out:text",{text:g,sequence:a.sequence,timestamp:a.timestamp})}if(this.#o.hasListeners("out:html")){let f=nr(l,a.sequence,a.timestamp,this.initTime,a.sourceId);this.#o.emit("out:html",{html:f,sequence:a.sequence,timestamp:a.timestamp})}}catch{}}}),(this.#s.debug||this.#s.debugOscIn)&&this.on("in:text",({text:o})=>console.log(`[\u2190 OSC] ${o}`)),(this.#s.debug||this.#s.debugOscOut)&&this.on("out:text",({text:o})=>console.log(`[OSC \u2192] ${o}`)),(this.#s.debug||this.#s.debugScsynth)&&this.on("debug",o=>console.log(`[synth] ${o.text}`)),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#N(){this.#h=!0,this.#m=!1,this.bootStats.initDuration=performance.now()-this.bootStats.initStartTime,await this.#o.emitAsync("setup"),this.#o.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.#s.mode==="sab"?this.#r.buffer:null;this.#S.initSharedViews(c,o,a);let u=this.#s.worldOptions?.maxNodes??1024,l=a?.NODE_TREE_MIRROR_MAX_NODES??1024;u>l&&console.warn(`SuperSonic: maxNodes (${u}) exceeds NODE_TREE_MIRROR_MAX_NODES (${l}). The node tree mirror will not show all nodes. Rebuild with NODE_TREE_MIRROR_MAX_NODES=${u} to fix.`),this.#E=new ee({mode:this.#s.mode,audioContext:this.#e,workletPort:this.#t.port}),this.#E.initSharedViews(c,o,a),await this.#E.initialize(),this.#E.startDriftTimer(),this.#s.mode==="sab"&&this.#A.update(c,o,a),this.#s.mode==="postMessage"&&n.data.initialSnapshot&&this.#S.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()})}#j(){this.#t.port.addEventListener("message",e=>{let{data:t}=e;switch(t.type){case"error":console.error("[Worklet] Error:",t.error),this.#o.emit("error",new Error(t.error));break;case"version":this.#g=t.version;break;case"snapshot":t.buffer&&(this.#S.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}})}#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.#u?.getStats(),loadedSynthDefsCount:this.loadedSynthDefs?.size||0,preschedulerCapacity:this.#s.preschedulerCapacity}}#v(){return this.#S.gatherMetrics(this.#x())}#Q(){this.#S.updateMergedArray(this.#x())}#H(){if(this.#s.mode==="sab"){let t=this.#S.getMetricsView();return t?t[0]:null}let e=this.#S.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.#S.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(V(s))this.#s.mode==="sab"?this.#w.send(e):this.#n.sendImmediate(e,s);else{let r=this.#S.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.#c.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.#o.emit("error",s)})}#re(){return this.#U}},Ui=He.osc;export{B as OscChannel,He as SuperSonic,Ui as osc};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supersonic-scsynth",
3
- "version": "0.55.0",
3
+ "version": "0.57.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",
@@ -49,12 +49,14 @@
49
49
  "./osc-channel": "./dist/osc_channel.js",
50
50
  "./metrics": "./dist/metrics_component.js",
51
51
  "./metrics-dark.css": "./dist/metrics-dark.css",
52
- "./metrics-light.css": "./dist/metrics-light.css"
52
+ "./metrics-light.css": "./dist/metrics-light.css",
53
+ "./osc-fast": "./dist/osc_fast.js"
53
54
  },
54
55
  "files": [
55
56
  "dist/supersonic.js",
56
57
  "supersonic.d.ts",
57
58
  "dist/osc_channel.js",
59
+ "dist/osc_fast.js",
58
60
  "dist/metrics_component.js",
59
61
  "dist/metrics-dark.css",
60
62
  "dist/metrics-light.css",
package/supersonic.d.ts CHANGED
@@ -6,6 +6,22 @@
6
6
  // For narrative documentation, usage examples, and comparison tables
7
7
  // see docs/API.md
8
8
 
9
+ // ============================================================================
10
+ // Core Types
11
+ // ============================================================================
12
+
13
+ /** A v7 UUID as 16 raw bytes. */
14
+ export type UUID = Uint8Array;
15
+
16
+ /**
17
+ * A node identifier — either a classic i32 or a v7 UUID.
18
+ *
19
+ * UUIDs are rewritten to i32s at the AudioWorklet boundary and back again
20
+ * on the way out, so concurrent clients can create and track synths without
21
+ * coordinating over a shared integer numbering system.
22
+ */
23
+ export type NodeID = number | UUID;
24
+
9
25
  // ============================================================================
10
26
  // OSC Types
11
27
  // ============================================================================
@@ -20,7 +36,7 @@
20
36
  * - `boolean` → `T` / `F`
21
37
  * - `Uint8Array` / `ArrayBuffer` → `b` (blob)
22
38
  *
23
- * For 64-bit or timetag types, use the tagged object form:
39
+ * For 64-bit, timetag, or UUID types, use the tagged object form:
24
40
  * @example
25
41
  * { type: 'int', value: 42 }
26
42
  * { type: 'float', value: 440 } // force float32 for whole numbers
@@ -30,6 +46,7 @@
30
46
  * { type: 'int64', value: 9007199254740992n }
31
47
  * { type: 'double', value: 3.141592653589793 }
32
48
  * { type: 'timetag', value: ntpTimestamp }
49
+ * { type: 'uuid', value: new Uint8Array(16) }
33
50
  */
34
51
  export type OscArg =
35
52
  | number
@@ -44,7 +61,8 @@ export type OscArg =
44
61
  | { type: 'bool'; value: boolean }
45
62
  | { type: 'int64'; value: number | bigint }
46
63
  | { type: 'double'; value: number }
47
- | { type: 'timetag'; value: number };
64
+ | { type: 'timetag'; value: number }
65
+ | { type: 'uuid'; value: UUID };
48
66
 
49
67
  /**
50
68
  * Decoded OSC message as a plain array.
@@ -110,9 +128,9 @@ export type OscBundlePacket =
110
128
  export type TransportMode = 'sab' | 'postMessage';
111
129
 
112
130
  /**
113
- * scsynth engine options passed to World_New().
131
+ * Engine configuration options controlling resource limits and audio behaviour.
114
132
  *
115
- * These configure the internal SuperCollider engine. All values have sensible defaults.
133
+ * All values have sensible defaults.
116
134
  * Override via `new SuperSonic({ scsynthOptions: { ... } })`.
117
135
  */
118
136
  export interface ScsynthOptions {
@@ -229,7 +247,7 @@ export interface SuperSonicOptions {
229
247
  snapshotIntervalMs?: number;
230
248
  /** Max pending events in the JS prescheduler. Default: 65536. */
231
249
  preschedulerCapacity?: number;
232
- /** Bundles within this many ms of now bypass the prescheduler. Default: 500. */
250
+ /** Bundles scheduled within this many ms of now are dispatched immediately for lowest latency. Bundles further in the future are held and dispatched closer to their scheduled time. Default: 500. */
233
251
  bypassLookaheadMs?: number;
234
252
 
235
253
  /** Enable all debug console logging. Default: false. */
@@ -243,8 +261,6 @@ export interface SuperSonicOptions {
243
261
 
244
262
  /** Line length limits for activity events emitted to listeners. */
245
263
  activityEvent?: ActivityLineConfig;
246
- /** Line length limits for activity console.log output. */
247
- activityConsoleLog?: ActivityLineConfig;
248
264
 
249
265
  /** Max fetch retries when loading assets. Default: 3. */
250
266
  fetchMaxRetries?: number;
@@ -467,7 +483,7 @@ export interface MetricsSchema {
467
483
  */
468
484
  export interface TreeNode {
469
485
  /** Unique node ID. */
470
- id: number;
486
+ id: NodeID;
471
487
  /** `'group'` for groups, `'synth'` for synth nodes. */
472
488
  type: 'group' | 'synth';
473
489
  /** SynthDef name (synths only, empty string for groups). */
@@ -498,17 +514,17 @@ export interface Tree {
498
514
  /** A node in the flat (raw) tree representation with linkage pointers. */
499
515
  export interface RawTreeNode {
500
516
  /** Unique node ID. */
501
- id: number;
517
+ id: NodeID;
502
518
  /** Parent node ID (-1 for root). */
503
- parentId: number;
519
+ parentId: NodeID;
504
520
  /** true if group, false if synth. */
505
521
  isGroup: boolean;
506
522
  /** Previous sibling node ID (-1 if none). */
507
- prevId: number;
523
+ prevId: NodeID;
508
524
  /** Next sibling node ID (-1 if none). */
509
- nextId: number;
525
+ nextId: NodeID;
510
526
  /** First child node ID (groups only, -1 if empty). */
511
- headId: number;
527
+ headId: NodeID;
512
528
  /** SynthDef name (synths only, empty string for groups). */
513
529
  defName: string;
514
530
  }
@@ -642,7 +658,7 @@ export interface BootStats {
642
658
  * for type-safe event subscriptions.
643
659
  *
644
660
  * @example
645
- * sonic.on('message', (msg) => {
661
+ * sonic.on('in', (msg) => {
646
662
  * // msg is typed as OscMessage — [address, ...args]
647
663
  * if (msg[0] === '/n_go') {
648
664
  * console.log('Node started:', msg[1]);
@@ -670,13 +686,31 @@ export interface SuperSonicEventMap {
670
686
  * Decoded OSC message received from scsynth.
671
687
  * Messages are plain arrays: `[address, ...args]`.
672
688
  */
673
- 'message': (msg: OscMessage) => void;
689
+ 'in': (msg: OscMessage) => void;
674
690
 
675
691
  /** Raw OSC bytes received from scsynth (before decoding). Includes NTP timestamps for timing analysis. */
676
- 'message:raw': (data: { oscData: Uint8Array; sequence: number; timestamp: number; scheduledTime: number | null }) => void;
692
+ 'in:osc': (data: { oscData: Uint8Array; sequence: number; timestamp: number; scheduledTime: number | null }) => void;
693
+
694
+ /** Pre-formatted text representation of an incoming OSC message. Only emitted when listeners are attached or debug logging is enabled. */
695
+ 'in:text': (data: { text: string; sequence: number; timestamp: number }) => void;
677
696
 
678
- /** Fired when an OSC message is sent to scsynth. Includes source worker ID, sequence number, and NTP timestamps. */
679
- 'message:sent': (data: { oscData: Uint8Array; sourceId: number; sequence: number; timestamp: number; scheduledTime: number | null }) => void;
697
+ /** Pre-formatted HTML representation of an incoming OSC message with CSS classes for colorization. Only emitted when listeners are attached. */
698
+ 'in:html': (data: { html: string; sequence: number; timestamp: number }) => void;
699
+
700
+ /**
701
+ * Decoded OSC message sent to scsynth.
702
+ * Messages are plain arrays: `[address, ...args]`. Mirrors the `'in'` event for outgoing messages.
703
+ */
704
+ 'out': (msg: OscMessage) => void;
705
+
706
+ /** Raw OSC bytes sent to scsynth. Includes source worker ID, sequence number, and NTP timestamps. */
707
+ 'out:osc': (data: { oscData: Uint8Array; sourceId: number; sequence: number; timestamp: number; scheduledTime: number | null }) => void;
708
+
709
+ /** Pre-formatted text representation of an outgoing OSC message. Only emitted when listeners are attached or debug logging is enabled. */
710
+ 'out:text': (data: { text: string; sequence: number; timestamp: number }) => void;
711
+
712
+ /** Pre-formatted HTML representation of an outgoing OSC message with CSS classes for colorization. Only emitted when listeners are attached. */
713
+ 'out:html': (data: { html: string; sequence: number; timestamp: number }) => void;
680
714
 
681
715
  /** Debug text output from scsynth (e.g. synthdef compilation messages). Includes NTP timestamp and sequence number. */
682
716
  'debug': (msg: { text: string; timestamp: number; sequence: number }) => void;
@@ -834,12 +868,9 @@ export class OscChannel {
834
868
  /**
835
869
  * Get the next unique node ID.
836
870
  *
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.
871
+ * Thread-safe can be called concurrently from multiple workers and no
872
+ * two callers will ever receive the same ID. IDs start at 1000 (0 is
873
+ * the root group, 1 is the default group, 2–999 are reserved for manual use).
843
874
  *
844
875
  * @returns A unique node ID (>= 1000)
845
876
  */
@@ -1035,7 +1066,7 @@ export interface SendOSCOptions {
1035
1066
  * await sonic.loadSynthDef('beep');
1036
1067
  * });
1037
1068
  *
1038
- * sonic.on('message', (msg) => {
1069
+ * sonic.on('in', (msg) => {
1039
1070
  * console.log('OSC from scsynth:', msg[0], msg.slice(1));
1040
1071
  * });
1041
1072
  *
@@ -1165,7 +1196,7 @@ export class SuperSonic {
1165
1196
  * @returns Unsubscribe function — call it to remove the listener
1166
1197
  *
1167
1198
  * @example
1168
- * const unsub = sonic.on('message', (msg) => {
1199
+ * const unsub = sonic.on('in', (msg) => {
1169
1200
  * console.log(msg[0], msg.slice(1));
1170
1201
  * });
1171
1202
  *
@@ -1379,68 +1410,68 @@ export class SuperSonic {
1379
1410
  // ── Synth commands ─────────────────────────────────────────────────
1380
1411
 
1381
1412
  /** Create a new synth from a loaded synthdef. addAction: 0=head, 1=tail, 2=before, 3=after, 4=replace. Controls are alternating name/index and value pairs. Values can be numbers or bus mapping strings like `"c0"` (control bus 0) or `"a0"` (audio bus 0). Use nodeID=-1 for auto-assign. */
1382
- send(address: '/s_new', defName: string, nodeID: number, addAction: AddAction, targetID: number, ...controls: (string | number)[]): void;
1413
+ send(address: '/s_new', defName: string, nodeID: NodeID, addAction: AddAction, targetID: NodeID, ...controls: (string | number)[]): void;
1383
1414
  /** Get synth control values. Controls can be indices or names. Replies with `/n_set nodeID control value ...`. */
1384
- send(address: '/s_get', nodeID: number, ...controls: (string | number)[]): void;
1415
+ send(address: '/s_get', nodeID: NodeID, ...controls: (string | number)[]): void;
1385
1416
  /** Get sequential synth control values. Control can be an index or name. Replies with `/n_setn nodeID control count values...`. For multiple ranges, use the catch-all overload. */
1386
- send(address: '/s_getn', nodeID: number, control: number | string, count: number): void;
1417
+ send(address: '/s_getn', nodeID: NodeID, control: number | string, count: number): void;
1387
1418
  /** Release client-side synth ID tracking. Synths continue running but are reassigned to reserved negative IDs. Use when you no longer need to communicate with the synth and want to reuse the ID. */
1388
- send(address: '/s_noid', ...nodeIDs: [number, ...number[]]): void;
1419
+ send(address: '/s_noid', ...nodeIDs: [NodeID, ...NodeID[]]): void;
1389
1420
 
1390
1421
  // ── Node commands ──────────────────────────────────────────────────
1391
1422
 
1392
1423
  /** Free (delete) one or more nodes. */
1393
- send(address: '/n_free', ...nodeIDs: [number, ...number[]]): void;
1424
+ send(address: '/n_free', ...nodeIDs: [NodeID, ...NodeID[]]): void;
1394
1425
  /** Set node control values. Controls are alternating name/index and value pairs. If the node is a group, sets the control on all nodes in the group. */
1395
- send(address: '/n_set', nodeID: number, ...controls: (string | number)[]): void;
1426
+ send(address: '/n_set', nodeID: NodeID, ...controls: (string | number)[]): void;
1396
1427
  /** Set sequential control values starting at the given control index/name. For multiple ranges, use the catch-all overload. */
1397
- send(address: '/n_setn', nodeID: number, control: number | string, count: number, ...values: number[]): void;
1428
+ send(address: '/n_setn', nodeID: NodeID, control: number | string, count: number, ...values: number[]): void;
1398
1429
  /** Fill sequential controls with a single value. For multiple ranges, use the catch-all overload. */
1399
- send(address: '/n_fill', nodeID: number, control: number | string, count: number, value: number): void;
1430
+ send(address: '/n_fill', nodeID: NodeID, control: number | string, count: number, value: number): void;
1400
1431
  /** Turn nodes on (1) or off (0). Args are repeating [nodeID, flag] pairs. */
1401
- send(address: '/n_run', ...pairs: [number, 0 | 1, ...(number | 0 | 1)[]]): void;
1432
+ send(address: '/n_run', ...pairs: [NodeID, 0 | 1, ...(NodeID | 0 | 1)[]]): void;
1402
1433
  /** Move nodeA to execute immediately before nodeB. Args are repeating [nodeA, nodeB] pairs. */
1403
- send(address: '/n_before', ...pairs: [number, number, ...number[]]): void;
1434
+ send(address: '/n_before', ...pairs: [NodeID, NodeID, ...NodeID[]]): void;
1404
1435
  /** Move nodeA to execute immediately after nodeB. Args are repeating [nodeA, nodeB] pairs. */
1405
- send(address: '/n_after', ...pairs: [number, number, ...number[]]): void;
1436
+ send(address: '/n_after', ...pairs: [NodeID, NodeID, ...NodeID[]]): void;
1406
1437
  /** Reorder nodes within a group. addAction: 0=head, 1=tail, 2=before target, 3=after target. Does not support 4 (replace). */
1407
- send(address: '/n_order', addAction: 0 | 1 | 2 | 3, targetID: number, ...nodeIDs: [number, ...number[]]): void;
1438
+ send(address: '/n_order', addAction: 0 | 1 | 2 | 3, targetID: NodeID, ...nodeIDs: [NodeID, ...NodeID[]]): void;
1408
1439
  /** Query node info. Replies with `/n_info` for each node: nodeID, parentGroupID, prevNodeID, nextNodeID, isGroup, [headNodeID, tailNodeID]. */
1409
- send(address: '/n_query', ...nodeIDs: [number, ...number[]]): void;
1440
+ send(address: '/n_query', ...nodeIDs: [NodeID, ...NodeID[]]): void;
1410
1441
  /** Print control values and calculation rates for each node to debug output. No reply message. */
1411
- send(address: '/n_trace', ...nodeIDs: [number, ...number[]]): void;
1442
+ send(address: '/n_trace', ...nodeIDs: [NodeID, ...NodeID[]]): void;
1412
1443
  /** Map controls to read from control buses. Mappings are repeating [control, busIndex] pairs. Set busIndex to -1 to unmap. */
1413
- send(address: '/n_map', nodeID: number, ...mappings: (string | number)[]): void;
1444
+ send(address: '/n_map', nodeID: NodeID, ...mappings: (string | number)[]): void;
1414
1445
  /** Map a range of sequential controls to sequential control buses. Mappings are repeating [control, busIndex, count] triplets. */
1415
- send(address: '/n_mapn', nodeID: number, ...mappings: (string | number)[]): void;
1446
+ send(address: '/n_mapn', nodeID: NodeID, ...mappings: (string | number)[]): void;
1416
1447
  /** Map controls to read from audio buses. Mappings are repeating [control, busIndex] pairs. Set busIndex to -1 to unmap. */
1417
- send(address: '/n_mapa', nodeID: number, ...mappings: (string | number)[]): void;
1448
+ send(address: '/n_mapa', nodeID: NodeID, ...mappings: (string | number)[]): void;
1418
1449
  /** Map a range of sequential controls to sequential audio buses. Mappings are repeating [control, busIndex, count] triplets. */
1419
- send(address: '/n_mapan', nodeID: number, ...mappings: (string | number)[]): void;
1450
+ send(address: '/n_mapan', nodeID: NodeID, ...mappings: (string | number)[]): void;
1420
1451
 
1421
1452
  // ── Group commands ─────────────────────────────────────────────────
1422
1453
 
1423
1454
  /** Create new groups. Args are repeating [groupID, addAction, targetID] triplets. addAction: 0=head, 1=tail, 2=before, 3=after, 4=replace. */
1424
- send(address: '/g_new', ...args: [number, AddAction, number, ...(number | AddAction)[]]): void;
1455
+ send(address: '/g_new', ...args: [NodeID, AddAction, NodeID, ...(NodeID | AddAction)[]]): void;
1425
1456
  /** Create new parallel groups (children evaluated in unspecified order). Same signature as /g_new. */
1426
- send(address: '/p_new', ...args: [number, AddAction, number, ...(number | AddAction)[]]): void;
1457
+ send(address: '/p_new', ...args: [NodeID, AddAction, NodeID, ...(NodeID | AddAction)[]]): void;
1427
1458
  /** Free all immediate children of one or more groups (groups themselves remain). */
1428
- send(address: '/g_freeAll', ...groupIDs: [number, ...number[]]): void;
1459
+ send(address: '/g_freeAll', ...groupIDs: [NodeID, ...NodeID[]]): void;
1429
1460
  /** Recursively free all synths inside one or more groups and their nested sub-groups. */
1430
- send(address: '/g_deepFree', ...groupIDs: [number, ...number[]]): void;
1461
+ send(address: '/g_deepFree', ...groupIDs: [NodeID, ...NodeID[]]): void;
1431
1462
  /** Move node to head of group. Args are repeating [groupID, nodeID] pairs. */
1432
- send(address: '/g_head', ...pairs: [number, number, ...number[]]): void;
1463
+ send(address: '/g_head', ...pairs: [NodeID, NodeID, ...NodeID[]]): void;
1433
1464
  /** Move node to tail of group. Args are repeating [groupID, nodeID] pairs. */
1434
- send(address: '/g_tail', ...pairs: [number, number, ...number[]]): void;
1465
+ send(address: '/g_tail', ...pairs: [NodeID, NodeID, ...NodeID[]]): void;
1435
1466
  /** Print group's node tree to debug output. Args are repeating [groupID, flag] pairs. flag: 0=structure only, non-zero=include control values. No reply message. */
1436
- send(address: '/g_dumpTree', ...groupFlagPairs: [number, number, ...number[]]): void;
1467
+ send(address: '/g_dumpTree', ...groupFlagPairs: [NodeID, number, ...(NodeID | number)[]]): void;
1437
1468
  /** Query group tree structure. Args are repeating [groupID, flag] pairs. flag: 0=structure only, non-zero=include control values. Replies with `/g_queryTree.reply`. */
1438
- send(address: '/g_queryTree', ...groupFlagPairs: [number, number, ...number[]]): void;
1469
+ send(address: '/g_queryTree', ...groupFlagPairs: [NodeID, number, ...(NodeID | number)[]]): void;
1439
1470
 
1440
1471
  // ── UGen commands ──────────────────────────────────────────────────
1441
1472
 
1442
1473
  /** Send a command to a specific UGen instance within a synth. The command name and args are UGen-specific. */
1443
- send(address: '/u_cmd', nodeID: number, ugenIndex: number, command: string, ...args: OscArg[]): void;
1474
+ send(address: '/u_cmd', nodeID: NodeID, ugenIndex: number, command: string, ...args: OscArg[]): void;
1444
1475
 
1445
1476
  // ── Buffer commands ────────────────────────────────────────────────
1446
1477
 
@@ -1495,11 +1526,11 @@ export class SuperSonic {
1495
1526
  * Use this when you've already encoded the message (e.g. via `SuperSonic.osc.encodeMessage`)
1496
1527
  * or when sending from a worker that produces raw OSC. Sends bytes as-is without
1497
1528
  * rewriting — buffer allocation commands (`/b_alloc*`) are not transformed.
1498
- * Use {@link send} for buffer commands so they get rewritten to `/b_allocPtr`.
1529
+ * Use {@link send} for buffer commands so they are handled correctly.
1499
1530
  *
1500
1531
  * @param oscData - Encoded OSC message or bundle bytes
1501
1532
  * @param options - Optional session/tag for cancellation
1502
- * @throws If the bundle is too large for the WASM scheduler slot size
1533
+ * @throws If the bundle exceeds the maximum schedulable size
1503
1534
  *
1504
1535
  * @example
1505
1536
  * const msg = SuperSonic.osc.encodeMessage('/n_set', [1001, 'freq', 880]);
@@ -1535,16 +1566,11 @@ export class SuperSonic {
1535
1566
  cancelAll(): void;
1536
1567
 
1537
1568
  /**
1538
- * Flush all pending OSC messages from both the JS prescheduler and the
1539
- * WASM BundleScheduler.
1569
+ * Cancel all pending scheduled messages everywhere in the pipeline.
1540
1570
  *
1541
- * Unlike {@link cancelAll} which only clears the JS prescheduler, this also
1542
- * clears bundles already consumed from the ring buffer and sitting in the
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.
1571
+ * Unlike {@link cancelAll} which only clears messages still waiting in JS,
1572
+ * `purge()` guarantees that nothing already in-flight will fire either.
1573
+ * Resolves when the flush is confirmed complete.
1548
1574
  */
1549
1575
  purge(): Promise<void>;
1550
1576
 
@@ -1580,12 +1606,9 @@ export class SuperSonic {
1580
1606
  /**
1581
1607
  * Get the next unique node ID.
1582
1608
  *
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.
1609
+ * Thread-safe can be called concurrently from multiple workers and no
1610
+ * two callers will ever receive the same ID. IDs start at 1000 (0 is
1611
+ * the root group, 1 is the default group, 2–999 are reserved for manual use).
1589
1612
  *
1590
1613
  * Also available on {@link OscChannel} for use in Web Workers.
1591
1614
  *