supersonic-scsynth-core 0.50.0 → 0.52.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.
package/README.md CHANGED
@@ -4,10 +4,12 @@ The SuperCollider scsynth WebAssembly engine and AudioWorklet processor for [Sup
4
4
 
5
5
  ## Overview
6
6
 
7
- This package contains the GPL-licensed runtime components:
7
+ This package contains only the GPL-licensed runtime components:
8
8
 
9
9
  - `wasm/scsynth-nrt.wasm` - The scsynth engine compiled to WebAssembly
10
- - `workers/*.js` - AudioWorklet processor and supporting workers
10
+ - `workers/scsynth_audio_worklet.js` - AudioWorklet processor
11
+
12
+ The MIT-licensed workers (prescheduler, osc_in, debug, osc_out_log) are distributed with the main `supersonic-scsynth` package.
11
13
 
12
14
  ## Usage
13
15
 
@@ -38,7 +40,7 @@ const supersonic = new SuperSonic({
38
40
  npm install supersonic-scsynth-core
39
41
  ```
40
42
 
41
- Then serve the `wasm/` and `workers/` directories from your static file server.
43
+ Then serve the `wasm/` directory and `workers/scsynth_audio_worklet.js` from your static file server.
42
44
 
43
45
  ## License
44
46
 
package/index.js CHANGED
@@ -6,4 +6,7 @@
6
6
 
7
7
  export const CORE_CDN = 'https://unpkg.com/supersonic-scsynth-core@latest/';
8
8
  export const WASM_CDN = 'https://unpkg.com/supersonic-scsynth-core@latest/wasm/';
9
+ export const WORKLET_CDN = 'https://unpkg.com/supersonic-scsynth-core@latest/workers/scsynth_audio_worklet.js';
10
+
11
+ /** @deprecated Use WORKLET_CDN instead */
9
12
  export const WORKERS_CDN = 'https://unpkg.com/supersonic-scsynth-core@latest/workers/';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supersonic-scsynth-core",
3
- "version": "0.50.0",
3
+ "version": "0.52.0",
4
4
  "description": "SuperCollider scsynth WebAssembly engine and AudioWorklet for SuperSonic",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -27,7 +27,7 @@
27
27
  "homepage": "https://github.com/samaaron/supersonic#readme",
28
28
  "files": [
29
29
  "wasm/",
30
- "workers/",
30
+ "workers/scsynth_audio_worklet.js",
31
31
  "index.js",
32
32
  "README.md",
33
33
  "LICENSE"
Binary file
@@ -1,3 +0,0 @@
1
- (()=>{function g({uint8View:o,dataView:t,bufferStart:e,bufferSize:E,head:S,tail:C,messageMagic:I,paddingMagic:B,headerSize:R,maxMessages:p=1/0,onMessage:U,onCorruption:_}){let s=C,u=0,l=O=>{let T=O;if(T+4<=E)return t.getUint32(e+T,!0);let D=0;for(let a=0;a<4;a++)D|=o[e+(T+a)%E]<<a*8;return D};for(;s!==S&&u<p;){let O=E-s,T;if(O>=4?T=t.getUint32(e+s,!0):T=l(s),T===B){s=0;continue}if(T!==I){_&&_(s),s=(s+1)%E;continue}let D=l((s+4)%E),a=l((s+8)%E),F=l((s+12)%E);if(D<R||D>E){_&&_(s),s=(s+1)%E;continue}let d=D-R,m=e+(s+R)%E;U(m,d,a,F),s=(s+D)%E,u++}return{newTail:s,messagesRead:u}}function f(o,t){let e=o+t;return{DEBUG_HEAD:(e+16)/4,DEBUG_TAIL:(e+20)/4}}var i="sab",A=null,L=null,r=null,P=null,H=null,n=null,c={},x=null,N=!1,G=new TextDecoder("utf-8"),b=(...o)=>{},w=(o,t,e)=>{A=o,L=t,n=e,r=new Int32Array(A),P=new DataView(A),H=new Uint8Array(A),c=f(L,n.CONTROL_START);let E=L+n.METRICS_START;x=new Uint32Array(A,E,n.METRICS_SIZE/4)},W=()=>{let o=Atomics.load(r,c.DEBUG_HEAD),t=Atomics.load(r,c.DEBUG_TAIL);if(o===t)return null;let e=[],{newTail:E,messagesRead:S}=g({uint8View:H,dataView:P,bufferStart:L+n.DEBUG_BUFFER_START,bufferSize:n.DEBUG_BUFFER_SIZE,head:o,tail:t,messageMagic:n.MESSAGE_MAGIC,paddingMagic:n.PADDING_MAGIC,headerSize:n.MESSAGE_HEADER_SIZE,maxMessages:1e3,onMessage:(C,I,B,R)=>{let p=new Uint8Array(I);for(let _=0;_<I;_++)p[_]=H[C+_];let U=G.decode(p);U.endsWith(`
2
- `)&&(U=U.slice(0,-1)),e.push({text:U,timestamp:performance.now(),sequence:B}),x&&(Atomics.add(x,30,1),Atomics.add(x,31,I))},onCorruption:C=>{console.error("[DebugWorker] Corrupted message at position",C)}});return S>0&&Atomics.store(r,c.DEBUG_TAIL,E),e.length>0?e:null},X=()=>{for(;N;)try{let o=Atomics.load(r,c.DEBUG_HEAD),t=Atomics.load(r,c.DEBUG_TAIL);o===t&&Atomics.wait(r,c.DEBUG_HEAD,o);let e=W();e&&e.length>0&&self.postMessage({type:"debug",messages:e})}catch(o){console.error("[DebugWorker] Error in wait loop:",o),self.postMessage({type:"error",error:o.message}),Atomics.wait(r,0,r[0],10)}},k=()=>{if(!A){console.error("[DebugWorker] Cannot start - not initialized");return}N||(N=!0,X())},Q=()=>{N=!1},K=()=>{A&&(Atomics.store(r,c.DEBUG_HEAD,0),Atomics.store(r,c.DEBUG_TAIL,0))},h=o=>{let t=[];for(let e of o)try{let E=new Uint8Array(e.bytes),S=G.decode(E);S.endsWith(`
3
- `)&&(S=S.slice(0,-1)),t.push({text:S,timestamp:performance.now(),sequence:e.sequence})}catch(E){console.error("[DebugWorker] Failed to decode message:",E)}t.length>0&&self.postMessage({type:"debug",messages:t})};self.addEventListener("message",o=>{let{data:t}=o;try{switch(t.type){case"init":i=t.mode||"sab",i==="sab"&&w(t.sharedBuffer,t.ringBufferBase,t.bufferConstants),self.postMessage({type:"initialized"});break;case"start":i==="sab"&&k();break;case"stop":Q();break;case"clear":i==="sab"&&K();break;case"debugRaw":t.messages&&h(t.messages);break;default:}}catch(e){console.error("[DebugWorker] Error:",e),self.postMessage({type:"error",error:e.message})}});b("[DebugWorker] Script loaded");})();
@@ -1 +0,0 @@
1
- (()=>{function P({uint8View:o,dataView:e,bufferStart:t,bufferSize:s,head:N,tail:R,messageMagic:a,paddingMagic:A,headerSize:p,maxMessages:i=1/0,onMessage:_,onCorruption:S}){let E=R,x=0,O=B=>{let T=B;if(T+4<=s)return e.getUint32(t+T,!0);let C=0;for(let I=0;I<4;I++)C|=o[t+(T+I)%s]<<I*8;return C};for(;E!==N&&x<i;){let B=s-E,T;if(B>=4?T=e.getUint32(t+E,!0):T=O(E),T===A){E=0;continue}if(T!==a){S&&S(E),E=(E+1)%s;continue}let C=O((E+4)%s),I=O((E+8)%s),G=O((E+12)%s);if(C<p||C>s){S&&S(E),E=(E+1)%s;continue}let d=C-p,g=t+(E+p)%s;_(g,d,I,G),E=(E+C)%s,x++}return{newTail:E,messagesRead:x}}function f(o,e){let t=o+e;return{OUT_HEAD:(t+8)/4,OUT_TAIL:(t+12)/4}}var W=2208988800,X=()=>(performance.timeOrigin+performance.now())/1e3+W,D=null,l=null,n=null,M=null,F=null,c=null,U={},r=null,L=!1,Q=(...o)=>{},H=-1,K=(o,e,t)=>{D=o,l=e,c=t,n=new Int32Array(D),M=new DataView(D),F=new Uint8Array(D),U=f(l,c.CONTROL_START);let s=l+c.METRICS_START;r=new Uint32Array(D,s,c.METRICS_SIZE/4)},k=()=>{let o=Atomics.load(n,U.OUT_HEAD),e=Atomics.load(n,U.OUT_TAIL);if(o===e)return[];let t=[],{newTail:s,messagesRead:N}=P({uint8View:F,dataView:M,bufferStart:l+c.OUT_BUFFER_START,bufferSize:c.OUT_BUFFER_SIZE,head:o,tail:e,messageMagic:c.MESSAGE_MAGIC,paddingMagic:c.PADDING_MAGIC,headerSize:c.MESSAGE_HEADER_SIZE,maxMessages:100,onMessage:(R,a,A,p)=>{if(H>=0){let _=H+1&4294967295;if(A!==_){let S=A-_+4294967296&4294967295;S<1e3&&(console.error("[OSCInWorker] Detected",S,"dropped messages (expected seq",_,"got",A,")"),r&&Atomics.add(r,28,S))}}H=A;let i=new Uint8Array(a);for(let _=0;_<a;_++)i[_]=F[R+_];t.push({oscData:i,sequence:A,timestamp:X()}),r&&(Atomics.add(r,26,1),Atomics.add(r,27,a))},onCorruption:R=>{console.error("[OSCInWorker] Corrupted message at position",R),r&&(Atomics.add(r,28,1),Atomics.add(r,29,1))}});return N>0&&Atomics.store(n,U.OUT_TAIL,s),t},V=()=>{for(;L;)try{let o=Atomics.load(n,U.OUT_HEAD),e=Atomics.load(n,U.OUT_TAIL);o===e&&Atomics.wait(n,U.OUT_HEAD,o);let t=k();t.length>0&&self.postMessage({type:"messages",messages:t})}catch(o){console.error("[OSCInWorker] Error in wait loop:",o),self.postMessage({type:"error",error:o.message}),Atomics.wait(n,0,n[0],10)}},Z=()=>{if(!D){console.error("[OSCInWorker] Cannot start - not initialized");return}L||(L=!0,V())},b=()=>{L=!1};self.addEventListener("message",o=>{let{data:e}=o;try{switch(e.type){case"init":K(e.sharedBuffer,e.ringBufferBase,e.bufferConstants),self.postMessage({type:"initialized"});break;case"start":Z();break;case"stop":b();break;default:}}catch(t){console.error("[OSCInWorker] Error:",t),self.postMessage({type:"error",error:t.message})}});Q("[OSCInWorker] Script loaded");})();
@@ -1 +0,0 @@
1
- (()=>{function m({uint8View:t,dataView:o,bufferStart:e,bufferSize:r,head:l,tail:d,messageMagic:g,paddingMagic:i,headerSize:u,maxMessages:N=1/0,onMessage:p,onCorruption:a}){let s=d,O=0,C=G=>{let E=G;if(E+4<=r)return o.getUint32(e+E,!0);let A=0;for(let U=0;U<4;U++)A|=t[e+(E+U)%r]<<U*8;return A};for(;s!==l&&O<N;){let G=r-s,E;if(G>=4?E=o.getUint32(e+s,!0):E=C(s),E===i){s=0;continue}if(E!==g){a&&a(s),s=(s+1)%r;continue}let A=C((s+4)%r),U=C((s+8)%r),x=C((s+12)%r);if(A<u||A>r){a&&a(s),s=(s+1)%r;continue}let R=A-u,H=e+(s+u)%r;p(H,R,U,x),s=(s+A)%r,O++}return{newTail:s,messagesRead:O}}function B(t,o){let e=t+o;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}}var F=2208988800,M=()=>(performance.timeOrigin+performance.now())/1e3+F,f=null,L=null,c=null,S=null,I=null,n=null,_={},D=!1,y=(...t)=>{},w=(t,o,e)=>{f=t,L=o,n=e,c=new Int32Array(f),S=new DataView(f),I=new Uint8Array(f),_=B(L,n.CONTROL_START);let r=Atomics.load(c,_.IN_HEAD);Atomics.store(c,_.IN_LOG_TAIL,r),y("Initialized, IN_LOG_TAIL set to",r)},$=t=>{let o=L+n.IN_BUFFER_START,e=n.IN_BUFFER_SIZE;if(t+4<=e)return S.getUint32(o+t,!0);let r=0;for(let l=0;l<4;l++)r|=I[o+(t+l)%e]<<l*8;return r},T=()=>{let t=Atomics.load(c,_.IN_HEAD),o=Atomics.load(c,_.IN_LOG_TAIL);if(t===o)return[];if($(o)!==n.MESSAGE_MAGIC)return Atomics.store(c,_.IN_LOG_TAIL,t),[];let r=[],{newTail:l,messagesRead:d}=m({uint8View:I,dataView:S,bufferStart:L+n.IN_BUFFER_START,bufferSize:n.IN_BUFFER_SIZE,head:t,tail:o,messageMagic:n.MESSAGE_MAGIC,paddingMagic:n.PADDING_MAGIC,headerSize:n.MESSAGE_HEADER_SIZE,maxMessages:100,onMessage:(g,i,u,N)=>{let p=new Uint8Array(i);for(let a=0;a<i;a++)p[a]=I[g+a];r.push({sourceId:N,oscData:p,sequence:u,timestamp:M()})},onCorruption:g=>{if(T._corruptCount||(T._corruptCount=0),T._corruptCount++,T._corruptCount<=3){let i=L+n.IN_BUFFER_START+g,u=S.getUint32(i,!0),N=I[i],p=I[i+1],a=I[i+2],s=I[i+3],O=Atomics.load(c,_.IN_TAIL);console.error(`[OSCOutLogWorker] Corrupted message at position ${g}: head=${t} logTail=${o} inTail=${O} got=0x${(u>>>0).toString(16).padStart(8,"0")} expected=0x${(n.MESSAGE_MAGIC>>>0).toString(16).padStart(8,"0")} bytes=[${N},${p},${a},${s}] bufStart=${L+n.IN_BUFFER_START} bufSize=${n.IN_BUFFER_SIZE}`)}else T._corruptCount===4&&console.error(`[OSCOutLogWorker] Suppressing further corruption logs (${T._corruptCount}+ total)`)}});return d>0&&Atomics.store(c,_.IN_LOG_TAIL,l),r},b=()=>{for(;D;)try{let t=Atomics.load(c,_.IN_HEAD),o=Atomics.load(c,_.IN_LOG_TAIL);t===o&&Atomics.wait(c,_.IN_HEAD,t);let e=T();e.length>0&&self.postMessage({type:"oscLog",entries:e})}catch(t){console.error("[OSCOutLogWorker] Error in wait loop:",t),self.postMessage({type:"error",error:t.message}),Atomics.wait(c,0,c[0],10)}},k=()=>{if(!f){console.error("[OSCOutLogWorker] Cannot start - not initialized");return}D||(D=!0,b())},W=()=>{D=!1};self.addEventListener("message",t=>{let{data:o}=t;try{switch(o.type){case"init":w(o.sharedBuffer,o.ringBufferBase,o.bufferConstants),self.postMessage({type:"initialized"});break;case"start":k();break;case"stop":W();break;default:}}catch(e){console.error("[OSCOutLogWorker] Error:",e),self.postMessage({type:"error",error:e.message})}});y("Script loaded");})();
@@ -1 +0,0 @@
1
- (()=>{function j(e,t,r){return(r-1-e+t)%r}function ee({uint8View:e,dataView:t,bufferStart:r,bufferSize:s,head:n,payload:c,sequence:i,messageMagic:a,headerSize:f,sourceId:_=0,headerScratch:Y=null,headerScratchView:M=null}){let m=c.length,I=f+m+3&-4,U=s-n;if(I>U){let u=Y||new Uint8Array(f),C=M||new DataView(u.buffer);C.setUint32(0,a,!0),C.setUint32(4,I,!0),C.setUint32(8,i,!0),C.setUint32(12,_,!0);let b=r+n,w=r;if(U>=f){e.set(u,b);let L=U-f;L>0&&e.set(c.subarray(0,L),b+f),e.set(c.subarray(L),w)}else{e.set(u.subarray(0,U),b),e.set(u.subarray(U),w);let L=f-U;e.set(c,w+L)}}else{let u=r+n;t.setUint32(u,a,!0),t.setUint32(u+4,I,!0),t.setUint32(u+8,i,!0),t.setUint32(u+12,_,!0),e.set(c,u+f)}return(n+I)%s}function Ie(e,t,r=0,s=!1){for(let n=0;n<=r;n++)if(Atomics.compareExchange(e,t,0,1)===0)return!0;if(s){for(let c=0;c<100;c++)if(Atomics.wait(e,t,1,100),Atomics.compareExchange(e,t,0,1)===0)return!0;return console.error("[RingBuffer] Lock acquisition timeout after 10s - possible deadlock"),!1}return!1}function Ce(e,t){Atomics.store(e,t,0),Atomics.notify(e,t,1)}function te({atomicView:e,dataView:t,uint8View:r,bufferConstants:s,ringBufferBase:n,controlIndices:c,oscMessage:i,sourceId:a=0,maxSpins:f=0,useWait:_=!1}){let Y=i.length,M=s.MESSAGE_HEADER_SIZE+Y;if(M>s.IN_BUFFER_SIZE-s.MESSAGE_HEADER_SIZE||!Ie(e,c.IN_WRITE_LOCK,f,_))return!1;try{let m=Atomics.load(e,c.IN_HEAD),J=Atomics.load(e,c.IN_TAIL),I=M+3&-4;if(j(m,J,s.IN_BUFFER_SIZE)<I)return!1;let u=Atomics.add(e,c.IN_SEQUENCE,1),C=ee({uint8View:r,dataView:t,bufferStart:n+s.IN_BUFFER_START,bufferSize:s.IN_BUFFER_SIZE,head:m,payload:i,sequence:u,messageMagic:s.MESSAGE_MAGIC,headerSize:s.MESSAGE_HEADER_SIZE,sourceId:a});return Atomics.load(e,c.IN_HEAD),Atomics.store(e,c.IN_HEAD,C),Atomics.notify(e,c.IN_HEAD,1),!0}finally{Ce(e,c.IN_WRITE_LOCK)}}function se(e,t){let r=e+t;return{IN_HEAD:(r+0)/4,IN_TAIL:(r+4)/4,IN_SEQUENCE:(r+24)/4,IN_WRITE_LOCK:(r+40)/4,IN_LOG_TAIL:(r+44)/4}}var A="sab",v=null,K=1024,Oe=65536,ce=3600,Se=4294967295,D=null,H=null,T=null,P=null,ue=null,Te=null,B={},E=null,F=null,Ee=null,W=150,g=(e,t)=>{E&&(A==="sab"?Atomics.store(E,e,t):E[e]=t)},fe=e=>E?A==="sab"?Atomics.load(E,e):E[e]:0,p=(e,t)=>{E&&(A==="sab"?Atomics.add(E,e,t):E[e]+=t)},y=(e,t)=>{E&&(A==="sab"?Atomics.store(E,e,t):E[e]=t)},le=e=>E?A==="sab"?Atomics.load(E,e):E[e]:0,Me=()=>{if(A!=="postMessage"||Ee!==null)return;let e=()=>{F&&E&&self.postMessage({type:"preschedulerMetrics",metrics:new Uint32Array(F.slice(0))}),Ee=setTimeout(e,W)};e(),S("[PreScheduler] Started metrics sending (every "+W+"ms)")};var o=[],R=null,x=1/0,me=0,ie=!1,l=[],k=!1,h=65536,xe=2208988800,$=.5,S=(...e)=>{},V=()=>(performance.timeOrigin+performance.now())/1e3+xe,He=e=>{if(e.length>=16&&e[0]===35){let t=new DataView(e.buffer,e.byteOffset),r=t.getUint32(8,!1),s=t.getUint32(12,!1);return r+s/4294967296}return null},Be=()=>{if(!D||!T){console.error("[PreScheduler] Cannot init - missing buffer or constants");return}P=new Int32Array(D),ue=new DataView(D),Te=new Uint8Array(D),B=se(H,T.CONTROL_START);let e=H+T.METRICS_START;E=new Uint32Array(D,e,T.METRICS_SIZE/4),S("[PreScheduler] SharedArrayBuffer initialized with direct ring buffer writing and metrics")},G=()=>{if(!E)return;g(9,o.length);let e=o.length,t=fe(10);e>t&&g(10,e)},d=(e,t,r=0,s=!1)=>{if(A==="postMessage")return v?(v.postMessage({type:"osc",oscData:e,sourceId:r}),p(12,1),!0):(console.error("[PreScheduler] No worklet port available"),!1);if(!D||!P)return console.error("[PreScheduler] Not initialized for ring buffer writing"),!1;let n=e.length,c=T.MESSAGE_HEADER_SIZE+n;return c>T.IN_BUFFER_SIZE-T.MESSAGE_HEADER_SIZE?(console.error("[PreScheduler] Message too large:",c),!1):te({atomicView:P,dataView:ue,uint8View:Te,bufferConstants:T,ringBufferBase:H,controlIndices:B,oscMessage:e,sourceId:r,maxSpins:10,useWait:s})?(p(12,1),!0):!1},N=(e,t,r=0)=>{let s=o.length+l.length;if(s>=h){console.error("[PreScheduler] Backpressure: dropping retry ("+s+" pending)"),p(17,1);return}l.push({oscData:e,context:t||"unknown",queuedAt:performance.now(),sourceId:r}),g(18,l.length);let n=fe(19);l.length>n&&g(19,l.length),S("[PreScheduler] Queued message for retry:",t,"queue size:",l.length),Ae()},Ae=()=>{if(k||l.length===0||A!=="sab")return;k=!0;let e=Atomics.load(P,B.IN_TAIL),t=Atomics.waitAsync(P,B.IN_TAIL,e),r=()=>{k=!1,Fe(),l.length>0&&Ae()};t.async?t.value.then(r):queueMicrotask(r)},Fe=()=>{if(l.length===0)return;let e=0;for(;e<l.length;){let t=l[e];if(d(t.oscData,!0,t.sourceId,!0))l.splice(e,1),p(16,1),g(18,l.length);else break}},_e=(e,t,r,s=0)=>{let n=o.length+l.length;if(n>=h){let _=`Prescheduler queue full (${n} >= ${h} max)`;return console.error("[PreScheduler]",_),self.postMessage({type:"error",error:_,code:"PRESCHEDULER_QUEUE_FULL"}),!1}let c=He(e);if(c===null)return S("[PreScheduler] Non-bundle message, dispatching immediately"),d(e,!1,s,!0)||N(e,"immediate message",s),!0;let i=V(),a=c-i;if(e.length>K){let _=`Bundle too large for scheduler (${e.length} > ${K} bytes)`;return console.error("[PreScheduler]",_),self.postMessage({type:"error",error:_,code:"BUNDLE_TOO_LARGE"}),!1}if(a>ce){let _=`Bundle scheduled too far in future (${a.toFixed(0)}s > ${ce}s max)`;return console.error("[PreScheduler]",_),self.postMessage({type:"error",error:_,code:"BUNDLE_TOO_FAR_FUTURE"}),!1}let f={ntpTime:c,seq:me++,sessionId:t||0,runTag:r||"",oscData:e,sourceId:s};return ye(f),p(11,1),G(),S("[PreScheduler] Scheduled bundle:","NTP="+c.toFixed(3),"current="+i.toFixed(3),"wait="+(a*1e3).toFixed(1)+"ms","pending="+o.length),O(),!0},ye=e=>{o.push(e),Ye(o.length-1)},pe=()=>o.length>0?o[0]:null,Ge=()=>{if(o.length===0)return null;let e=o[0],t=o.pop();return o.length>0&&(o[0]=t,Re(0)),e},Ye=e=>{for(;e>0;){let t=Math.floor((e-1)/2);if(Z(o[e],o[t])>=0)break;Ue(e,t),e=t}},Re=e=>{let t=o.length;for(;;){let r=2*e+1,s=2*e+2,n=e;if(r<t&&Z(o[r],o[n])<0&&(n=r),s<t&&Z(o[s],o[n])<0&&(n=s),n===e)break;Ue(e,n),e=n}},Z=(e,t)=>e.ntpTime===t.ntpTime?e.seq-t.seq:e.ntpTime-t.ntpTime,Ue=(e,t)=>{let r=o[e];o[e]=o[t],o[t]=r},O=()=>{if(o.length===0){R!==null&&(clearTimeout(R),R=null,x=1/0);return}let e=pe().ntpTime-$,t=V();if(e<x){R!==null&&clearTimeout(R);let r=Math.max(0,(e-t)*1e3);x=e,R=setTimeout(we,r)}},be=()=>{R===null&&(S("[PreScheduler] Starting demand-driven dispatching"),O())};var we=()=>{ie=!0;let e=V(),t=e+$,r=0;for(;o.length>0;){let s=pe();if(s.ntpTime<=t){Ge(),G();let n=s.ntpTime-e;if(p(21,1),n<0){let i=Math.round(-n*1e3);p(15,1);let a=le(23);i>a&&y(23,i)}else{let i=Math.round(n*1e3),a=le(14);(a===Se||i<a)&&y(14,i)}S("[PreScheduler] Dispatching bundle:","NTP="+s.ntpTime.toFixed(3),"current="+e.toFixed(3),"early="+(n*1e3).toFixed(1)+"ms","remaining="+o.length),d(s.oscData,!1,s.sourceId,!0)||N(s.oscData,"scheduled bundle NTP="+s.ntpTime.toFixed(3),s.sourceId),r++}else break}(r>0||o.length>0||l.length>0)&&S("[PreScheduler] Dispatch cycle complete:","dispatched="+r,"pending="+o.length,"retrying="+l.length),ie=!1,R=null,x=1/0,O()},z=e=>{if(o.length===0)return;let t=o.length,r=[];for(let n=0;n<o.length;n++){let c=o[n];e(c)||r.push(c)}let s=t-r.length;s>0&&(o=r,ke(),p(13,s),G(),S("[PreScheduler] Cancelled "+s+" events, "+o.length+" remaining"),O())},ke=()=>{for(let e=Math.floor(o.length/2)-1;e>=0;e--)Re(e)},Qe=(e,t)=>{z(r=>r.sessionId===e&&r.runTag===t)},Xe=e=>{z(t=>t.sessionId===e)},ve=e=>{z(t=>t.runTag===e)},Ke=()=>{let e=o.length,t=l.length;e===0&&t===0||(p(13,e+t),o=[],l=[],g(18,0),G(),S("[PreScheduler] Cancelled all "+e+" events, "+t+" retries"),O())},We=e=>!e||e.length<8?!1:e[0]===35&&e[1]===98&&e[2]===117&&e[3]===110&&e[4]===100&&e[5]===108&&e[6]===101&&e[7]===0,Ze=e=>{let t=[],r=new DataView(e.buffer,e.byteOffset,e.byteLength),s=16;for(;s+4<=e.length;){let n=r.getInt32(s,!1);if(s+=4,n<=0||n>Oe||s+n>e.length)break;let c=e.slice(s,s+n);for(t.push(c),s+=n;s%4!==0&&s<e.length;)s++}return t},qe=(e,t=0)=>{if(We(e)){let r=Ze(e);for(let s=0;s<r.length;s++)d(r[s],!1,t,!0)||N(r[s],"immediate bundle message "+s,t)}else d(e,!1,t,!0)||N(e,"immediate message",t)};self.addEventListener("message",e=>{let{data:t}=e;try{switch(t.type){case"init":if(A=t.mode||"sab",t.maxPendingMessages&&(h=t.maxPendingMessages),t.snapshotIntervalMs&&(W=t.snapshotIntervalMs),t.bypassLookaheadS!==void 0&&($=t.bypassLookaheadS),A==="sab")D=t.sharedBuffer,H=t.ringBufferBase,T=t.bufferConstants,Be(),T&&T.scheduler_slot_size&&(K=T.scheduler_slot_size);else{v=t.workletPort;let s=184;F=new ArrayBuffer(s),E=new Uint32Array(F),Me()}y(14,Se),y(23,0),be(),S("[OSCPreSchedulerWorker] Initialized with NTP-based scheduling, mode="+A+", capacity="+h),self.postMessage({type:"initialized"});break;case"addOscSource":let r=e.ports[0];r&&(r.onmessage=s=>{s.data.type==="osc"&&s.data.oscData&&_e(s.data.oscData,0,"",s.data.sourceId||0)},S("[OSCPreSchedulerWorker] Added external OSC source"));break;case"send":_e(t.oscData,t.sessionId||0,t.runTag||"",t.sourceId||0);break;case"sendImmediate":qe(t.oscData,t.sourceId||0);break;case"directDispatch":d(t.oscData,!1,t.sourceId||0,!0)||N(t.oscData,"directDispatch fallback",t.sourceId||0);break;case"cancelSessionTag":t.runTag!==void 0&&t.runTag!==null&&t.runTag!==""&&Qe(t.sessionId||0,t.runTag);break;case"cancelSession":Xe(t.sessionId||0);break;case"cancelTag":t.runTag!==void 0&&t.runTag!==null&&t.runTag!==""&&ve(t.runTag);break;case"cancelAll":Ke(),t.ack&&self.postMessage({type:"cancelAllAck"});break;default:}}catch(r){console.error("[OSCPreSchedulerWorker] Error:",r),self.postMessage({type:"error",error:r.message})}});S("[OSCPreSchedulerWorker] Script loaded");})();