supersonic-scsynth 0.66.0 → 0.67.2

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,3 +1,3 @@
1
- (()=>{function f({uint8View:o,dataView:t,bufferStart:e,bufferSize:E,head:T,tail:C,messageMagic:I,paddingMagic:O,headerSize:R,maxMessages:l=1/0,onMessage:U,onCorruption:r}){let s=C,u=0,p=B=>{let S=B;if(S+4<=E)return t.getUint32(e+S,!0);let A=0;for(let D=0;D<4;D++)A|=o[e+(S+D)%E]<<D*8;return A};for(;s!==T&&u<l;){let B=E-s,S;if(B>=4?S=t.getUint32(e+s,!0):S=p(s),S===O){s=0;continue}if(S!==I){r&&r(s),s=(s+1)%E;continue}let A=p((s+4)%E),D=p((s+8)%E),G=p((s+12)%E);if(A<R||A>E){r&&r(s),s=(s+1)%E;continue}let M=A-R,d=e+(s+R)%E;U(d,M,D,G),s=(s+A)%E,u++}return{newTail:s,messagesRead:u}}function P(o,t){let e=o+t;return{DEBUG_HEAD:(e+16)/4,DEBUG_TAIL:(e+20)/4}}var i="sab",a=null,L=null,_=null,g=null,H=null,n=null,c={},N=null,x=!1,F=new TextDecoder("utf-8"),X=(...o)=>{},b=(o,t,e)=>{a=o,L=t,n=e,_=new Int32Array(a),g=new DataView(a),H=new Uint8Array(a),c=P(L,n.CONTROL_START);let E=L+n.METRICS_START;N=new Uint32Array(a,E,n.METRICS_SIZE/4)},W=()=>{let o=Atomics.load(_,c.DEBUG_HEAD),t=Atomics.load(_,c.DEBUG_TAIL);if(o===t)return null;let e=[],{newTail:E,messagesRead:T}=f({uint8View:H,dataView:g,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,O,R)=>{let l=new Uint8Array(I);for(let r=0;r<I;r++)l[r]=H[C+r];let U=F.decode(l);U.endsWith(`
2
- `)&&(U=U.slice(0,-1)),e.push({text:U,timestamp:performance.now(),sequence:O}),N&&(Atomics.add(N,30,1),Atomics.add(N,31,I))},onCorruption:C=>{console.error("[DebugWorker] Corrupted message at position",C)}});return T>0&&Atomics.store(_,c.DEBUG_TAIL,E),e.length>0?e:null},w=()=>{for(;x;)try{let o=Atomics.load(_,c.DEBUG_HEAD),t=Atomics.load(_,c.DEBUG_TAIL);o===t&&Atomics.wait(_,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(_,0,_[0],10)}},k=()=>{if(!a){console.error("[DebugWorker] Cannot start - not initialized");return}x||(x=!0,w())},K=()=>{x=!1},Q=()=>{a&&(Atomics.store(_,c.DEBUG_HEAD,0),Atomics.store(_,c.DEBUG_TAIL,0))},h=o=>{let t=[];for(let e of o)try{let E=new Uint8Array(e.bytes),T=F.decode(E);T.endsWith(`
3
- `)&&(T=T.slice(0,-1)),t.push({text:T,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"&&b(t.sharedBuffer,t.ringBufferBase,t.bufferConstants),self.postMessage({type:"initialized"});break;case"start":i==="sab"&&k();break;case"stop":K();break;case"clear":i==="sab"&&Q();break;case"debugRaw":t.messages&&h(t.messages);break;default:}}catch(e){console.error("[DebugWorker] Error:",e),self.postMessage({type:"error",error:e.message})}});X("[DebugWorker] Script loaded");})();
1
+ (()=>{function L({uint8View:_,dataView:o,bufferStart:c,bufferSize:t,head:A,tail:T,messageMagic:I,paddingMagic:R,headerSize:C,maxMessages:D=1/0,onMessage:e,onCorruption:S}){let E=T,a=0,i=U=>{let r=U;if(r+4<=t)return o.getUint32(c+r,!0);let s=0;for(let n=0;n<4;n++)s|=_[c+(r+n)%t]<<n*8;return s};for(;E!==A&&a<D;){let U=t-E,r;if(U>=4?r=o.getUint32(c+E,!0):r=i(E),r===R){E=0;continue}if(r!==I){S&&S(E),E=(E+1)%t;continue}let s=i((E+4)%t),n=i((E+8)%t),l=i((E+12)%t);if(s<C||s>t){S&&S(E),E=(E+1)%t;continue}let p=s-C,O=c+(E+C)%t;e(O,p,n,l),E=(E+s)%t,a++}return{newTail:E,messagesRead:a}}function N(_,o){let c=_+o;return{DEBUG_HEAD:(c+16)/4,DEBUG_TAIL:(c+20)/4}}function x(_){let{name:o,calculateControlIndices:c,headIndex:t,tailIndex:A,readMessages:T,postResults:I,initMetrics:R=!0,onInit:C,extraHandlers:D}=_,e={sharedBuffer:null,ringBufferBase:null,bufferConstants:null,atomicView:null,dataView:null,uint8View:null,metricsView:null,CONTROL_INDICES:{}},S=!1;function E(r,s,n){if(e.sharedBuffer=r,e.ringBufferBase=s,e.bufferConstants=n,e.atomicView=new Int32Array(r),e.dataView=new DataView(r),e.uint8View=new Uint8Array(r),e.CONTROL_INDICES=c(s,n.CONTROL_START),R){let l=s+n.METRICS_START;e.metricsView=new Uint32Array(r,l,n.METRICS_SIZE/4)}C?.(e)}function a(){let r=t(e.CONTROL_INDICES),s=A(e.CONTROL_INDICES);for(;S;)try{let n=Atomics.load(e.atomicView,r),l=Atomics.load(e.atomicView,s);n===l&&Atomics.wait(e.atomicView,r,n);let p=T(e);p&&p.length>0&&I(p)}catch(n){console.error(`[${o}] Error in wait loop:`,n),self.postMessage({type:"error",error:n.message}),Atomics.wait(e.atomicView,0,e.atomicView[0],10)}}function i(){if(!e.sharedBuffer){console.error(`[${o}] Cannot start - not initialized`);return}S||(S=!0,a())}function U(){S=!1}self.addEventListener("message",r=>{let{data:s}=r;try{if(D?.[s.type]){D[s.type](s,e);return}switch(s.type){case"init":s.sharedBuffer&&E(s.sharedBuffer,s.ringBufferBase,s.bufferConstants),self.postMessage({type:"initialized"});break;case"start":e.sharedBuffer&&i();break;case"stop":U();break;default:}}catch(n){console.error(`[${o}] Error:`,n),self.postMessage({type:"error",error:n.message})}})}var u=new TextDecoder("utf-8");function d(_,o,c){let t=new Uint8Array(c);for(let T=0;T<c;T++)t[T]=_[o+T];let A=u.decode(t);return A.endsWith(`
2
+ `)&&(A=A.slice(0,-1)),A}function P(_){let{atomicView:o,uint8View:c,dataView:t,ringBufferBase:A,bufferConstants:T,metricsView:I,CONTROL_INDICES:R}=_,C=Atomics.load(o,R.DEBUG_HEAD),D=Atomics.load(o,R.DEBUG_TAIL);if(C===D)return[];let e=[],{newTail:S,messagesRead:E}=L({uint8View:c,dataView:t,bufferStart:A+T.DEBUG_BUFFER_START,bufferSize:T.DEBUG_BUFFER_SIZE,head:C,tail:D,messageMagic:T.MESSAGE_MAGIC,paddingMagic:T.PADDING_MAGIC,headerSize:T.MESSAGE_HEADER_SIZE,maxMessages:1e3,onMessage:(a,i,U)=>{e.push({text:d(c,a,i),timestamp:performance.now(),sequence:U}),I&&(Atomics.add(I,30,1),Atomics.add(I,31,i))},onCorruption:a=>{console.error("[DebugWorker] Corrupted message at position",a)}});return E>0&&Atomics.store(o,R.DEBUG_TAIL,S),e}function m(_){let o=[];for(let c of _)try{let t=u.decode(new Uint8Array(c.bytes));t.endsWith(`
3
+ `)&&(t=t.slice(0,-1)),o.push({text:t,timestamp:performance.now(),sequence:c.sequence})}catch(t){console.error("[DebugWorker] Failed to decode message:",t)}o.length>0&&self.postMessage({type:"debug",messages:o})}x({name:"DebugWorker",calculateControlIndices:N,headIndex:_=>_.DEBUG_HEAD,tailIndex:_=>_.DEBUG_TAIL,readMessages:P,postResults:_=>self.postMessage({type:"debug",messages:_}),extraHandlers:{clear:(_,o)=>{o.sharedBuffer&&(Atomics.store(o.atomicView,o.CONTROL_INDICES.DEBUG_HEAD,0),Atomics.store(o.atomicView,o.CONTROL_INDICES.DEBUG_TAIL,0))},debugRaw:_=>{_.messages&&m(_.messages)}}});})();
@@ -1 +1 @@
1
- (()=>{function P({uint8View:o,dataView:E,bufferStart:t,bufferSize:r,head:L,tail:a,messageMagic:p,paddingMagic:A,headerSize:R,maxMessages:l=1/0,onMessage:_,onCorruption:c}){let e=a,x=0,O=u=>{let T=u;if(T+4<=r)return E.getUint32(t+T,!0);let C=0;for(let I=0;I<4;I++)C|=o[t+(T+I)%r]<<I*8;return C};for(;e!==L&&x<l;){let u=r-e,T;if(u>=4?T=E.getUint32(t+e,!0):T=O(e),T===A){e=0;continue}if(T!==p){c&&c(e),e=(e+1)%r;continue}let C=O((e+4)%r),I=O((e+8)%r),g=O((e+12)%r);if(C<R||C>r){c&&c(e),e=(e+1)%r;continue}let m=C-R,G=t+(e+R)%r;_(G,m,I,g),e=(e+C)%r,x++}return{newTail:e,messagesRead:x}}function B(o,E){let t=o+E;return{OUT_HEAD:(t+8)/4,OUT_TAIL:(t+12)/4}}function H(){return(performance.timeOrigin+performance.now())/1e3+2208988800}var i=null,D=null,n=null,d=null,F=null,S=null,U={},s=null,N=!1,w=(...o)=>{},f=-1,K=(o,E,t)=>{i=o,D=E,S=t,n=new Int32Array(i),d=new DataView(i),F=new Uint8Array(i),U=B(D,S.CONTROL_START);let r=D+S.METRICS_START;s=new Uint32Array(i,r,S.METRICS_SIZE/4)},Q=()=>{let o=Atomics.load(n,U.OUT_HEAD),E=Atomics.load(n,U.OUT_TAIL);if(o===E)return[];let t=[],{newTail:r,messagesRead:L}=P({uint8View:F,dataView:d,bufferStart:D+S.OUT_BUFFER_START,bufferSize:S.OUT_BUFFER_SIZE,head:o,tail:E,messageMagic:S.MESSAGE_MAGIC,paddingMagic:S.PADDING_MAGIC,headerSize:S.MESSAGE_HEADER_SIZE,maxMessages:100,onMessage:(a,p,A,R)=>{if(f>=0){let _=f+1&4294967295;if(A!==_){let c=A-_+4294967296&4294967295;c<1e3&&(console.error("[OSCInWorker] Detected",c,"dropped messages (expected seq",_,"got",A,")"),s&&Atomics.add(s,28,c))}}f=A;let l=new Uint8Array(p);for(let _=0;_<p;_++)l[_]=F[a+_];t.push({oscData:l,sequence:A,timestamp:H()}),s&&(Atomics.add(s,26,1),Atomics.add(s,27,p))},onCorruption:a=>{console.error("[OSCInWorker] Corrupted message at position",a),s&&(Atomics.add(s,28,1),Atomics.add(s,29,1))}});return L>0&&Atomics.store(n,U.OUT_TAIL,r),t},k=()=>{for(;N;)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=Q();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)}},h=()=>{if(!i){console.error("[OSCInWorker] Cannot start - not initialized");return}N||(N=!0,k())},Z=()=>{N=!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":h();break;case"stop":Z();break;default:}}catch(t){console.error("[OSCInWorker] Error:",t),self.postMessage({type:"error",error:t.message})}});w("[OSCInWorker] Script loaded");})();
1
+ (()=>{function O(E,e,s){return(s-1-E+e)%s}function D({uint8View:E,dataView:e,bufferStart:s,bufferSize:_,head:i,payload:A,sequence:l,messageMagic:U,headerSize:C,sourceId:f=0,headerScratch:r=null,headerScratchView:p=null}){let c=A.length,I=C+c+3&-4,a=_-i;if(I>a){let o=r||new Uint8Array(C),n=p||new DataView(o.buffer);n.setUint32(0,U,!0),n.setUint32(4,I,!0),n.setUint32(8,l,!0),n.setUint32(12,f,!0);let t=s+i,S=s;if(a>=C){E.set(o,t);let R=a-C;for(let T=0;T<R;T++)E[t+C+T]=A[T];for(let T=R;T<c;T++)E[S+T-R]=A[T]}else{for(let T=0;T<a;T++)E[t+T]=o[T];for(let T=a;T<C;T++)E[S+T-a]=o[T];let R=C-a;E.set(A,S+R)}}else{let o=s+i;e.setUint32(o,U,!0),e.setUint32(o+4,I,!0),e.setUint32(o+8,l,!0),e.setUint32(o+12,f,!0),E.set(A,o+C)}return(i+I)%_}function d({uint8View:E,dataView:e,bufferStart:s,bufferSize:_,head:i,tail:A,messageMagic:l,paddingMagic:U,headerSize:C,maxMessages:f=1/0,onMessage:r,onCorruption:p}){let c=A,L=0,I=a=>{let o=a;if(o+4<=_)return e.getUint32(s+o,!0);let n=0;for(let t=0;t<4;t++)n|=E[s+(o+t)%_]<<t*8;return n};for(;c!==i&&L<f;){let a=_-c,o;if(a>=4?o=e.getUint32(s+c,!0):o=I(c),o===U){c=0;continue}if(o!==l){p&&p(c),c=(c+1)%_;continue}let n=I((c+4)%_),t=I((c+8)%_),S=I((c+12)%_);if(n<C||n>_){p&&p(c),c=(c+1)%_;continue}let R=n-C,T=s+(c+C)%_;r(T,R,t,S),c=(c+n)%_,L++}return{newTail:c,messagesRead:L}}function P(E,e,s,_){let i=E+e+_*s;return{controlBase:i,headIndex:(i+0)/4,tailIndex:(i+4)/4,activeIndex:(i+8)/4,dropsIndex:(i+12)/4}}function B(E,e){let s=E+e;return{OUT_HEAD:(s+8)/4,OUT_TAIL:(s+12)/4}}function F(){return(performance.timeOrigin+performance.now())/1e3+2208988800}function H(E){let{name:e,calculateControlIndices:s,headIndex:_,tailIndex:i,readMessages:A,postResults:l,initMetrics:U=!0,onInit:C,extraHandlers:f}=E,r={sharedBuffer:null,ringBufferBase:null,bufferConstants:null,atomicView:null,dataView:null,uint8View:null,metricsView:null,CONTROL_INDICES:{}},p=!1;function c(o,n,t){if(r.sharedBuffer=o,r.ringBufferBase=n,r.bufferConstants=t,r.atomicView=new Int32Array(o),r.dataView=new DataView(o),r.uint8View=new Uint8Array(o),r.CONTROL_INDICES=s(n,t.CONTROL_START),U){let S=n+t.METRICS_START;r.metricsView=new Uint32Array(o,S,t.METRICS_SIZE/4)}C?.(r)}function L(){let o=_(r.CONTROL_INDICES),n=i(r.CONTROL_INDICES);for(;p;)try{let t=Atomics.load(r.atomicView,o),S=Atomics.load(r.atomicView,n);t===S&&Atomics.wait(r.atomicView,o,t);let R=A(r);R&&R.length>0&&l(R)}catch(t){console.error(`[${e}] Error in wait loop:`,t),self.postMessage({type:"error",error:t.message}),Atomics.wait(r.atomicView,0,r.atomicView[0],10)}}function I(){if(!r.sharedBuffer){console.error(`[${e}] Cannot start - not initialized`);return}p||(p=!0,L())}function a(){p=!1}self.addEventListener("message",o=>{let{data:n}=o;try{if(f?.[n.type]){f[n.type](n,r);return}switch(n.type){case"init":n.sharedBuffer&&c(n.sharedBuffer,n.ringBufferBase,n.bufferConstants),self.postMessage({type:"initialized"});break;case"start":r.sharedBuffer&&I();break;case"stop":a();break;default:}}catch(t){console.error(`[${e}] Error:`,t),self.postMessage({type:"error",error:t.message})}})}var x=-1,u=null,N=null,M=null;function X(E){let{atomicView:e,uint8View:s,dataView:_,ringBufferBase:i,bufferConstants:A,metricsView:l,CONTROL_INDICES:U}=E,C=Atomics.load(e,U.OUT_HEAD),f=Atomics.load(e,U.OUT_TAIL);if(C===f)return[];let r=[],{newTail:p,messagesRead:c}=d({uint8View:s,dataView:_,bufferStart:i+A.OUT_BUFFER_START,bufferSize:A.OUT_BUFFER_SIZE,head:C,tail:f,messageMagic:A.MESSAGE_MAGIC,paddingMagic:A.PADDING_MAGIC,headerSize:A.MESSAGE_HEADER_SIZE,maxMessages:100,onMessage:(L,I,a,o)=>{if(x>=0){let t=x+1&4294967295;if(a!==t){let S=a-t+4294967296&4294967295;S<1e3&&(console.error("[OSCInWorker] Detected",S,"dropped messages (expected seq",t,"got",a,")"),l&&Atomics.add(l,28,S))}}x=a;let n=new Uint8Array(I);for(let t=0;t<I;t++)n[t]=s[L+t];if(r.push({oscData:n,sequence:a,timestamp:F()}),u)for(let t=0;t<u.length;t++){let S=u[t];if(Atomics.load(e,S.activeIndex)!==1)continue;let R=Atomics.load(e,S.headIndex),T=Atomics.load(e,S.tailIndex),g=O(R,T,S.bufferSize);if((A.MESSAGE_HEADER_SIZE+I+3&-4)>g){Atomics.add(e,S.dropsIndex,1);continue}let G=D({uint8View:s,dataView:_,bufferStart:S.bufferStart,bufferSize:S.bufferSize,head:R,payload:n,sequence:a,messageMagic:A.MESSAGE_MAGIC,headerSize:A.MESSAGE_HEADER_SIZE,headerScratch:N,headerScratchView:M});Atomics.store(e,S.headIndex,G),Atomics.notify(e,S.headIndex)}l&&(Atomics.add(l,26,1),Atomics.add(l,27,I))},onCorruption:L=>{console.error("[OSCInWorker] Corrupted message at position",L),l&&(Atomics.add(l,28,1),Atomics.add(l,29,1))}});return c>0&&Atomics.store(e,U.OUT_TAIL,p),r}H({name:"OSCInWorker",calculateControlIndices:B,headIndex:E=>E.OUT_HEAD,tailIndex:E=>E.OUT_TAIL,readMessages:X,postResults:E=>self.postMessage({type:"messages",messages:E}),onInit:E=>{let e=E.bufferConstants;if(!e.REPLY_CHANNEL_COUNT)return;N=new Uint8Array(e.MESSAGE_HEADER_SIZE),M=new DataView(N.buffer);let s=E.ringBufferBase;u=[];for(let _=0;_<e.REPLY_CHANNEL_COUNT;_++){let i=P(s,e.REPLY_CHANNELS_CONTROL_START,e.REPLY_CHANNEL_CONTROL_SIZE,_);u.push({bufferStart:s+e.REPLY_CHANNELS_BUFFER_START+_*e.REPLY_CHANNEL_BUFFER_SIZE,bufferSize:e.REPLY_CHANNEL_BUFFER_SIZE,headIndex:i.headIndex,tailIndex:i.tailIndex,activeIndex:i.activeIndex,dropsIndex:i.dropsIndex})}}});})();
@@ -1 +1 @@
1
- (()=>{function G({uint8View:t,dataView:r,bufferStart:e,bufferSize:o,head:l,tail:C,messageMagic:f,paddingMagic:_,headerSize:A,maxMessages:S=1/0,onMessage:g,onCorruption:c}){let n=C,L=0,O=B=>{let E=B;if(E+4<=o)return r.getUint32(e+E,!0);let I=0;for(let p=0;p<4;p++)I|=t[e+(E+p)%o]<<p*8;return I};for(;n!==l&&L<S;){let B=o-n,E;if(B>=4?E=r.getUint32(e+n,!0):E=O(n),E===_){n=0;continue}if(E!==f){c&&c(n),n=(n+1)%o;continue}let I=O((n+4)%o),p=O((n+8)%o),F=O((n+12)%o);if(I<A||I>o){c&&c(n),n=(n+1)%o;continue}let R=I-A,H=e+(n+A)%o;g(H,R,p,F),n=(n+I)%o,L++}return{newTail:n,messagesRead:L}}function x(t,r){let e=t+r;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 D(){return(performance.timeOrigin+performance.now())/1e3+2208988800}var U=null,N=null,a=null,d=null,u=null,s=null,i={},m=!1,y=(...t)=>{},M=(t,r,e)=>{U=t,N=r,s=e,a=new Int32Array(U),d=new DataView(U),u=new Uint8Array(U),i=x(N,s.CONTROL_START);let o=Atomics.load(a,i.IN_HEAD);Atomics.store(a,i.IN_LOG_TAIL,o),y("Initialized, IN_LOG_TAIL set to",o)},P=t=>{let r=N+s.IN_BUFFER_START,e=s.IN_BUFFER_SIZE;if(t+4<=e)return d.getUint32(r+t,!0);let o=0;for(let l=0;l<4;l++)o|=u[r+(t+l)%e]<<l*8;return o},T=()=>{let t=Atomics.load(a,i.IN_HEAD),r=Atomics.load(a,i.IN_LOG_TAIL);if(t===r)return[];if(P(r)!==s.MESSAGE_MAGIC)return Atomics.store(a,i.IN_LOG_TAIL,t),[];let o=[],{newTail:l,messagesRead:C}=G({uint8View:u,dataView:d,bufferStart:N+s.IN_BUFFER_START,bufferSize:s.IN_BUFFER_SIZE,head:t,tail:r,messageMagic:s.MESSAGE_MAGIC,paddingMagic:s.PADDING_MAGIC,headerSize:s.MESSAGE_HEADER_SIZE,maxMessages:100,onMessage:(f,_,A,S)=>{let g=new Uint8Array(_);for(let c=0;c<_;c++)g[c]=u[f+c];o.push({sourceId:S,oscData:g,sequence:A,timestamp:D()})},onCorruption:f=>{if(T._corruptCount||(T._corruptCount=0),T._corruptCount++,T._corruptCount<=3){let _=N+s.IN_BUFFER_START+f,A=d.getUint32(_,!0),S=u[_],g=u[_+1],c=u[_+2],n=u[_+3],L=Atomics.load(a,i.IN_TAIL);console.error(`[OSCOutLogWorker] Corrupted message at position ${f}: head=${t} logTail=${r} inTail=${L} got=0x${(A>>>0).toString(16).padStart(8,"0")} expected=0x${(s.MESSAGE_MAGIC>>>0).toString(16).padStart(8,"0")} bytes=[${S},${g},${c},${n}] bufStart=${N+s.IN_BUFFER_START} bufSize=${s.IN_BUFFER_SIZE}`)}else T._corruptCount===4&&console.error(`[OSCOutLogWorker] Suppressing further corruption logs (${T._corruptCount}+ total)`)}});return C>0&&Atomics.store(a,i.IN_LOG_TAIL,l),o},b=()=>{for(;m;)try{let t=Atomics.load(a,i.IN_HEAD),r=Atomics.load(a,i.IN_LOG_TAIL);t===r&&Atomics.wait(a,i.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(a,0,a[0],10)}},h=()=>{if(!U){console.error("[OSCOutLogWorker] Cannot start - not initialized");return}m||(m=!0,b())},W=()=>{m=!1};self.addEventListener("message",t=>{let{data:r}=t;try{switch(r.type){case"init":M(r.sharedBuffer,r.ringBufferBase,r.bufferConstants),self.postMessage({type:"initialized"});break;case"start":h();break;case"stop":W();break;default:}}catch(e){console.error("[OSCOutLogWorker] Error:",e),self.postMessage({type:"error",error:e.message})}});y("Script loaded");})();
1
+ (()=>{function m({uint8View:i,dataView:c,bufferStart:s,bufferSize:a,head:g,tail:E,messageMagic:T,paddingMagic:p,headerSize:u,maxMessages:f=1/0,onMessage:e,onCorruption:_}){let o=E,d=0,L=l=>{let t=l;if(t+4<=a)return c.getUint32(s+t,!0);let n=0;for(let r=0;r<4;r++)n|=i[s+(t+r)%a]<<r*8;return n};for(;o!==g&&d<f;){let l=a-o,t;if(l>=4?t=c.getUint32(s+o,!0):t=L(o),t===p){o=0;continue}if(t!==T){_&&_(o),o=(o+1)%a;continue}let n=L((o+4)%a),r=L((o+8)%a),A=L((o+12)%a);if(n<u||n>a){_&&_(o),o=(o+1)%a;continue}let I=n-u,S=s+(o+u)%a;e(S,I,r,A),o=(o+n)%a,d++}return{newTail:o,messagesRead:d}}function O(i,c){let s=i+c;return{IN_HEAD:(s+0)/4,IN_TAIL:(s+4)/4,IN_SEQUENCE:(s+24)/4,IN_WRITE_LOCK:(s+40)/4,IN_LOG_TAIL:(s+44)/4}}function C(){return(performance.timeOrigin+performance.now())/1e3+2208988800}function U(i){let{name:c,calculateControlIndices:s,headIndex:a,tailIndex:g,readMessages:E,postResults:T,initMetrics:p=!0,onInit:u,extraHandlers:f}=i,e={sharedBuffer:null,ringBufferBase:null,bufferConstants:null,atomicView:null,dataView:null,uint8View:null,metricsView:null,CONTROL_INDICES:{}},_=!1;function o(t,n,r){if(e.sharedBuffer=t,e.ringBufferBase=n,e.bufferConstants=r,e.atomicView=new Int32Array(t),e.dataView=new DataView(t),e.uint8View=new Uint8Array(t),e.CONTROL_INDICES=s(n,r.CONTROL_START),p){let A=n+r.METRICS_START;e.metricsView=new Uint32Array(t,A,r.METRICS_SIZE/4)}u?.(e)}function d(){let t=a(e.CONTROL_INDICES),n=g(e.CONTROL_INDICES);for(;_;)try{let r=Atomics.load(e.atomicView,t),A=Atomics.load(e.atomicView,n);r===A&&Atomics.wait(e.atomicView,t,r);let I=E(e);I&&I.length>0&&T(I)}catch(r){console.error(`[${c}] Error in wait loop:`,r),self.postMessage({type:"error",error:r.message}),Atomics.wait(e.atomicView,0,e.atomicView[0],10)}}function L(){if(!e.sharedBuffer){console.error(`[${c}] Cannot start - not initialized`);return}_||(_=!0,d())}function l(){_=!1}self.addEventListener("message",t=>{let{data:n}=t;try{if(f?.[n.type]){f[n.type](n,e);return}switch(n.type){case"init":n.sharedBuffer&&o(n.sharedBuffer,n.ringBufferBase,n.bufferConstants),self.postMessage({type:"initialized"});break;case"start":e.sharedBuffer&&L();break;case"stop":l();break;default:}}catch(r){console.error(`[${c}] Error:`,r),self.postMessage({type:"error",error:r.message})}})}var N=0;function x(i){let{atomicView:c,uint8View:s,dataView:a,ringBufferBase:g,bufferConstants:E,CONTROL_INDICES:T}=i,p=Atomics.load(c,T.IN_HEAD),u=Atomics.load(c,T.IN_LOG_TAIL);if(p===u)return[];let f=g+E.IN_BUFFER_START,e=E.IN_BUFFER_SIZE,_;if(u+4<=e)_=a.getUint32(f+u,!0);else{_=0;for(let l=0;l<4;l++)_|=s[f+(u+l)%e]<<l*8}if(_!==E.MESSAGE_MAGIC)return Atomics.store(c,T.IN_LOG_TAIL,p),[];let o=[],{newTail:d,messagesRead:L}=m({uint8View:s,dataView:a,bufferStart:f,bufferSize:e,head:p,tail:u,messageMagic:E.MESSAGE_MAGIC,paddingMagic:E.PADDING_MAGIC,headerSize:E.MESSAGE_HEADER_SIZE,maxMessages:100,onMessage:(l,t,n,r)=>{let A=new Uint8Array(t);for(let I=0;I<t;I++)A[I]=s[l+I];o.push({sourceId:r,oscData:A,sequence:n,timestamp:C()})},onCorruption:l=>{if(N++,N<=3){let t=g+E.IN_BUFFER_START+l,n=a.getUint32(t,!0),r=s[t],A=s[t+1],I=s[t+2],S=s[t+3],R=Atomics.load(c,T.IN_TAIL);console.error(`[OSCOutLogWorker] Corrupted message at position ${l}: head=${p} logTail=${u} inTail=${R} got=0x${(n>>>0).toString(16).padStart(8,"0")} expected=0x${(E.MESSAGE_MAGIC>>>0).toString(16).padStart(8,"0")} bytes=[${r},${A},${I},${S}] bufStart=${f} bufSize=${e}`)}else N===4&&console.error(`[OSCOutLogWorker] Suppressing further corruption logs (${N}+ total)`)}});return L>0&&Atomics.store(c,T.IN_LOG_TAIL,d),o}U({name:"OSCOutLogWorker",calculateControlIndices:O,headIndex:i=>i.IN_HEAD,tailIndex:i=>i.IN_LOG_TAIL,readMessages:x,postResults:i=>self.postMessage({type:"oscLog",entries:i}),initMetrics:!1,onInit:i=>{let c=Atomics.load(i.atomicView,i.CONTROL_INDICES.IN_HEAD);Atomics.store(i.atomicView,i.CONTROL_INDICES.IN_LOG_TAIL,c)}});})();
@@ -1 +1 @@
1
- (()=>{function he(e,t,s){return(s-1-e+t)%s}function pe({uint8View:e,dataView:t,bufferStart:s,bufferSize:n,head:r,payload:c,sequence:l,messageMagic:u,headerSize:T,sourceId:E=0,headerScratch:w=null,headerScratchView:N=null}){let y=c.length,h=T+y+3&-4,R=n-r;if(h>R){let _=w||new Uint8Array(T),p=N||new DataView(_.buffer);p.setUint32(0,u,!0),p.setUint32(4,h,!0),p.setUint32(8,l,!0),p.setUint32(12,E,!0);let G=s+r,k=s;if(R>=T){e.set(_,G);let D=R-T;D>0&&e.set(c.subarray(0,D),G+T),e.set(c.subarray(D),k)}else{e.set(_.subarray(0,R),G),e.set(_.subarray(R),k);let D=T-R;e.set(c,k+D)}}else{let _=s+r;t.setUint32(_,u,!0),t.setUint32(_+4,h,!0),t.setUint32(_+8,l,!0),t.setUint32(_+12,E,!0),e.set(c,_+T)}return(r+h)%n}function Ie(e,t,s=0,n=!1){for(let r=0;r<=s;r++)if(Atomics.compareExchange(e,t,0,1)===0)return!0;if(n){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 De(e,t){Atomics.store(e,t,0),Atomics.notify(e,t,1)}function ee({atomicView:e,dataView:t,uint8View:s,bufferConstants:n,ringBufferBase:r,controlIndices:c,oscMessage:l,sourceId:u=0,maxSpins:T=0,useWait:E=!1}){let w=l.length,N=n.MESSAGE_HEADER_SIZE+w;if(N>n.IN_BUFFER_SIZE-n.MESSAGE_HEADER_SIZE||!Ie(e,c.IN_WRITE_LOCK,T,E))return!1;try{let y=Atomics.load(e,c.IN_HEAD),j=Atomics.load(e,c.IN_TAIL),h=N+3&-4;if(he(y,j,n.IN_BUFFER_SIZE)<h)return!1;let _=Atomics.add(e,c.IN_SEQUENCE,1),p=pe({uint8View:s,dataView:t,bufferStart:r+n.IN_BUFFER_START,bufferSize:n.IN_BUFFER_SIZE,head:y,payload:l,sequence:_,messageMagic:n.MESSAGE_MAGIC,headerSize:n.MESSAGE_HEADER_SIZE,sourceId:u});return Atomics.load(e,c.IN_HEAD),Atomics.store(e,c.IN_HEAD,p),Atomics.notify(e,c.IN_HEAD,1),!0}finally{De(e,c.IN_WRITE_LOCK)}}function te(e,t){let s=e+t;return{IN_HEAD:(s+0)/4,IN_TAIL:(s+4)/4,IN_SEQUENCE:(s+24)/4,IN_WRITE_LOCK:(s+40)/4,IN_LOG_TAIL:(s+44)/4}}function ne(e){return e.length>=8&&e[0]===35&&e[1]===98&&e[2]===117&&e[3]===110&&e[4]===100&&e[5]===108&&e[6]===101&&e[7]===0}function se(){return(performance.timeOrigin+performance.now())/1e3+2208988800}var Pe=new Uint8Array(2097152),st=new DataView(Pe.buffer);var rt=new TextDecoder,ot=new TextEncoder;var Le=4294967296,ct=new Uint8Array([35,98,117,110,100,108,101,0]);function xe(e){return!e||e.length<8?!1:e[0]===35&&e[1]===98}function re(e){if(!xe(e))return null;let t=new DataView(e.buffer,e.byteOffset,e.byteLength),s=t.getUint32(8,!1),n=t.getUint32(12,!1);return s+n/Le}var A="sab",Q=null,K=1024,Fe=65536,le=3600,Se=4294967295,g=null,M=null,S=null,P=null,Te=null,Ae=null,B={},a=null,F=null,Ee=null,W=150,C=(e,t)=>{a&&(A==="sab"?Atomics.store(a,e,t):a[e]=t)},V=e=>a?A==="sab"?Atomics.load(a,e):a[e]:0,U=(e,t)=>{a&&(A==="sab"?Atomics.add(a,e,t):a[e]+=t)},H=C,ue=V,He=()=>{if(A!=="postMessage"||Ee!==null)return;let e=()=>{F&&a&&self.postMessage({type:"preschedulerMetrics",metrics:new Uint32Array(F.slice(0))}),Ee=setTimeout(e,W)};e(),f("[PreScheduler] Started metrics sending (every "+W+"ms)")};var o=[],d=null,m=1/0,be=0,ae=!1,i=[],Y=!1,L=65536,q=.5,f=(...e)=>{},$=se,we=e=>re(e),Ge=()=>{if(!g||!S){console.error("[PreScheduler] Cannot init - missing buffer or constants");return}P=new Int32Array(g),Te=new DataView(g),Ae=new Uint8Array(g),B=te(M,S.CONTROL_START);let e=M+S.METRICS_START;a=new Uint32Array(g,e,S.METRICS_SIZE/4),f("[PreScheduler] SharedArrayBuffer initialized with direct ring buffer writing and metrics")},b=()=>{if(!a)return;C(9,o.length);let e=o.length,t=V(10);e>t&&C(10,e)},I=(e,t,s=0,n=!1)=>{if(A==="postMessage")return Q?(Q.postMessage({type:"osc",oscData:e,sourceId:s}),U(12,1),!0):(console.error("[PreScheduler] No worklet port available"),!1);if(!g||!P)return console.error("[PreScheduler] Not initialized for ring buffer writing"),!1;let r=e.length,c=S.MESSAGE_HEADER_SIZE+r;return c>S.IN_BUFFER_SIZE-S.MESSAGE_HEADER_SIZE?(console.error("[PreScheduler] Message too large:",c),!1):ee({atomicView:P,dataView:Te,uint8View:Ae,bufferConstants:S,ringBufferBase:M,controlIndices:B,oscMessage:e,sourceId:s,maxSpins:10,useWait:n})?(U(12,1),!0):!1},x=(e,t,s=0)=>{let n=o.length+i.length;if(n>=L){console.error("[PreScheduler] Backpressure: dropping retry ("+n+" pending)"),U(17,1);return}i.push({oscData:e,context:t||"unknown",queuedAt:performance.now(),sourceId:s}),C(18,i.length);let r=V(19);i.length>r&&C(19,i.length),f("[PreScheduler] Queued message for retry:",t,"queue size:",i.length),Ue()},Ue=()=>{if(Y||i.length===0||A!=="sab")return;Y=!0;let e=Atomics.load(P,B.IN_TAIL),t=Atomics.waitAsync(P,B.IN_TAIL,e),s=()=>{Y=!1,ke(),i.length>0&&Ue()};t.async?t.value.then(s):queueMicrotask(s)},ke=()=>{if(i.length===0)return;let e=0;for(let t=0;t<i.length;t++){let s=i[t];if(I(s.oscData,!0,s.sourceId,!0))e++,U(16,1);else break}e>0&&(i.splice(0,e),C(18,i.length))},fe=(e,t,s,n=0)=>{let r=o.length+i.length;if(r>=L){let E=`Prescheduler queue full (${r} >= ${L} max)`;return console.error("[PreScheduler]",E),self.postMessage({type:"error",error:E,code:"PRESCHEDULER_QUEUE_FULL"}),!1}let c=we(e);if(c===null)return f("[PreScheduler] Non-bundle message, dispatching immediately"),I(e,!1,n,!0)||x(e,"immediate message",n),!0;let l=$(),u=c-l;if(e.length>K){let E=`Bundle too large for scheduler (${e.length} > ${K} bytes)`;return console.error("[PreScheduler]",E),self.postMessage({type:"error",error:E,code:"BUNDLE_TOO_LARGE"}),!1}if(u>le){let E=`Bundle scheduled too far in future (${u.toFixed(0)}s > ${le}s max)`;return console.error("[PreScheduler]",E),self.postMessage({type:"error",error:E,code:"BUNDLE_TOO_FAR_FUTURE"}),!1}let T={ntpTime:c,seq:be++,sessionId:t||0,runTag:s||"",oscData:e,sourceId:n};return Ye(T),U(11,1),b(),f("[PreScheduler] Scheduled bundle:","NTP="+c.toFixed(3),"current="+l.toFixed(3),"wait="+(u*1e3).toFixed(1)+"ms","pending="+o.length),O(),!0},Ye=e=>{o.push(e),Xe(o.length-1)},de=()=>o.length>0?o[0]:null,ve=()=>{if(o.length===0)return null;let e=o[0],t=o.pop();return o.length>0&&(o[0]=t,Re(0)),e},Xe=e=>{for(;e>0;){let t=Math.floor((e-1)/2);if(Z(o[e],o[t])>=0)break;ge(e,t),e=t}},Re=e=>{let t=o.length;for(;;){let s=2*e+1,n=2*e+2,r=e;if(s<t&&Z(o[s],o[r])<0&&(r=s),n<t&&Z(o[n],o[r])<0&&(r=n),r===e)break;ge(e,r),e=r}},Z=(e,t)=>e.ntpTime===t.ntpTime?e.seq-t.seq:e.ntpTime-t.ntpTime,ge=(e,t)=>{let s=o[e];o[e]=o[t],o[t]=s},O=()=>{if(o.length===0){d!==null&&(clearTimeout(d),d=null,m=1/0);return}let e=de().ntpTime-q,t=$();if(e<m){d!==null&&clearTimeout(d);let s=Math.max(0,(e-t)*1e3);m=e,d=setTimeout(Ke,s)}},Qe=()=>{d===null&&(f("[PreScheduler] Starting demand-driven dispatching"),O())};var Ke=()=>{ae=!0;let e=$(),t=e+q,s=0;for(;o.length>0;){let n=de();if(n.ntpTime<=t){ve(),b();let r=n.ntpTime-e;if(U(21,1),r<0){let l=Math.round(-r*1e3);U(15,1);let u=ue(23);l>u&&H(23,l)}else{let l=Math.round(r*1e3),u=ue(14);(u===Se||l<u)&&H(14,l)}f("[PreScheduler] Dispatching bundle:","NTP="+n.ntpTime.toFixed(3),"current="+e.toFixed(3),"early="+(r*1e3).toFixed(1)+"ms","remaining="+o.length),I(n.oscData,!1,n.sourceId,!0)||x(n.oscData,"scheduled bundle NTP="+n.ntpTime.toFixed(3),n.sourceId),s++}else break}(s>0||o.length>0||i.length>0)&&f("[PreScheduler] Dispatch cycle complete:","dispatched="+s,"pending="+o.length,"retrying="+i.length),ae=!1,d=null,m=1/0,O()},J=e=>{if(o.length===0)return;let t=o.length,s=[];for(let r=0;r<o.length;r++){let c=o[r];e(c)||s.push(c)}let n=t-s.length;n>0&&(o=s,We(),U(13,n),b(),f("[PreScheduler] Cancelled "+n+" events, "+o.length+" remaining"),O())},We=()=>{for(let e=Math.floor(o.length/2)-1;e>=0;e--)Re(e)},Ze=(e,t)=>{J(s=>s.sessionId===e&&s.runTag===t)},ze=e=>{J(t=>t.sessionId===e)},Ve=e=>{J(t=>t.runTag===e)},qe=()=>{let e=o.length,t=i.length;e===0&&t===0||(U(13,e+t),o=[],i=[],C(18,0),b(),f("[PreScheduler] Cancelled all "+e+" events, "+t+" retries"),O())},$e=ne,Je=e=>{let t=[],s=new DataView(e.buffer,e.byteOffset,e.byteLength),n=16;for(;n+4<=e.length;){let r=s.getInt32(n,!1);if(n+=4,r<=0||r>Fe||n+r>e.length)break;let c=e.slice(n,n+r);for(t.push(c),n+=r;n%4!==0&&n<e.length;)n++}return t},je=(e,t=0)=>{if($e(e)){let s=Je(e);for(let n=0;n<s.length;n++)I(s[n],!1,t,!0)||x(s[n],"immediate bundle message "+n,t)}else I(e,!1,t,!0)||x(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&&(L=t.maxPendingMessages),t.snapshotIntervalMs&&(W=t.snapshotIntervalMs),t.bypassLookaheadS!==void 0&&(q=t.bypassLookaheadS),A==="sab")g=t.sharedBuffer,M=t.ringBufferBase,S=t.bufferConstants,Ge(),S&&S.scheduler_slot_size&&(K=S.scheduler_slot_size);else{Q=t.workletPort;let n=184;F=new ArrayBuffer(n),a=new Uint32Array(F),He()}H(14,Se),H(23,0),Qe(),f("[OSCPreSchedulerWorker] Initialized with NTP-based scheduling, mode="+A+", capacity="+L),self.postMessage({type:"initialized"});break;case"addOscSource":let s=e.ports[0];s&&(s.onmessage=n=>{n.data.type==="osc"&&n.data.oscData&&fe(n.data.oscData,0,"",n.data.sourceId||0)},f("[OSCPreSchedulerWorker] Added external OSC source"));break;case"send":fe(t.oscData,t.sessionId||0,t.runTag||"",t.sourceId||0);break;case"sendImmediate":je(t.oscData,t.sourceId||0);break;case"directDispatch":I(t.oscData,!1,t.sourceId||0,!0)||x(t.oscData,"directDispatch fallback",t.sourceId||0);break;case"cancelSessionTag":t.runTag!==void 0&&t.runTag!==null&&t.runTag!==""&&Ze(t.sessionId||0,t.runTag);break;case"cancelSession":ze(t.sessionId||0);break;case"cancelTag":t.runTag!==void 0&&t.runTag!==null&&t.runTag!==""&&Ve(t.runTag);break;case"cancelAll":qe(),t.ack&&self.postMessage({type:"cancelAllAck"});break;default:}}catch(s){console.error("[OSCPreSchedulerWorker] Error:",s),self.postMessage({type:"error",error:s.message})}});f("[OSCPreSchedulerWorker] Script loaded");})();
1
+ (()=>{function De(e,t,r){return(r-1-e+t)%r}function Le({uint8View:e,dataView:t,bufferStart:r,bufferSize:n,head:s,payload:c,sequence:E,messageMagic:a,headerSize:T,sourceId:u=0,headerScratch:k=null,headerScratchView:Y=null}){let M=c.length,h=T+M+3&-4,U=n-s;if(h>U){let A=k||new Uint8Array(T),D=Y||new DataView(A.buffer);D.setUint32(0,a,!0),D.setUint32(4,h,!0),D.setUint32(8,E,!0),D.setUint32(12,u,!0);let L=r+s,P=r;if(U>=T){e.set(A,L);let x=U-T;for(let i=0;i<x;i++)e[L+T+i]=c[i];for(let i=x;i<M;i++)e[P+i-x]=c[i]}else{for(let i=0;i<U;i++)e[L+i]=A[i];for(let i=U;i<T;i++)e[P+i-U]=A[i];let x=T-U;e.set(c,P+x)}}else{let A=r+s;t.setUint32(A,a,!0),t.setUint32(A+4,h,!0),t.setUint32(A+8,E,!0),t.setUint32(A+12,u,!0),e.set(c,A+T)}return(s+h)%n}function Pe(e,t,r=0,n=!1){for(let s=0;s<=r;s++)if(Atomics.compareExchange(e,t,0,1)===0)return!0;if(n){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 xe(e,t){Atomics.store(e,t,0),Atomics.notify(e,t,1)}function ne({atomicView:e,dataView:t,uint8View:r,bufferConstants:n,ringBufferBase:s,controlIndices:c,oscMessage:E,sourceId:a=0,maxSpins:T=0,useWait:u=!1,headerScratch:k=null,headerScratchView:Y=null}){let M=E.length,v=n.MESSAGE_HEADER_SIZE+M;if(v>n.IN_BUFFER_SIZE-n.MESSAGE_HEADER_SIZE||!Pe(e,c.IN_WRITE_LOCK,T,u))return!1;try{let h=Atomics.load(e,c.IN_HEAD),U=Atomics.load(e,c.IN_TAIL),A=v+3&-4;if(De(h,U,n.IN_BUFFER_SIZE)<A)return!1;let L=Atomics.add(e,c.IN_SEQUENCE,1),P=Le({uint8View:r,dataView:t,bufferStart:s+n.IN_BUFFER_START,bufferSize:n.IN_BUFFER_SIZE,head:h,payload:E,sequence:L,messageMagic:n.MESSAGE_MAGIC,headerSize:n.MESSAGE_HEADER_SIZE,sourceId:a,headerScratch:k,headerScratchView:Y});return Atomics.load(e,c.IN_HEAD),Atomics.store(e,c.IN_HEAD,P),Atomics.notify(e,c.IN_HEAD,1),!0}finally{xe(e,c.IN_WRITE_LOCK)}}function re(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}}function se(e){return e.length>=8&&e[0]===35&&e[1]===98&&e[2]===117&&e[3]===110&&e[4]===100&&e[5]===108&&e[6]===101&&e[7]===0}function oe(){return(performance.timeOrigin+performance.now())/1e3+2208988800}var Oe=new Uint8Array(2097152),ct=new DataView(Oe.buffer);var it=new TextDecoder,lt=new TextEncoder;var Ne=4294967296,Et=new Uint8Array([35,98,117,110,100,108,101,0]);function ye(e){return!e||e.length<8?!1:e[0]===35&&e[1]===98}function ce(e){if(!ye(e))return null;let t=new DataView(e.buffer,e.byteOffset,e.byteLength),r=t.getUint32(8,!1),n=t.getUint32(12,!1);return r+n/Ne}var d="sab",W=null,Z=524288,we=65536,ue=3600,Ae=4294967295,g=null,H=null,f=null,O=null,Ue=null,de=null,V=null,Re=null,F={},_=null,b=null,ae=null,q=150,p=(e,t)=>{_&&(d==="sab"?Atomics.store(_,e,t):_[e]=t)},J=e=>_?d==="sab"?Atomics.load(_,e):_[e]:0,R=(e,t)=>{_&&(d==="sab"?Atomics.add(_,e,t):_[e]+=t)},w=p,fe=J,Ge=()=>{if(d!=="postMessage"||ae!==null)return;let e=()=>{b&&_&&self.postMessage({type:"preschedulerMetrics",metrics:new Uint32Array(b.slice(0))}),ae=setTimeout(e,q)};e(),S("[PreScheduler] Started metrics sending (every "+q+"ms)")};var o=[],C=null,B=1/0,ke=0,_e=!1,l=[],X=!1,N=65536,j=.5,S=(...e)=>{},ee=oe,Ye=e=>ce(e),ve=()=>{if(!g||!f){console.error("[PreScheduler] Cannot init - missing buffer or constants");return}O=new Int32Array(g),Ue=new DataView(g),de=new Uint8Array(g);let e=f.MESSAGE_HEADER_SIZE||16;V=new Uint8Array(e),Re=new DataView(V.buffer),F=re(H,f.CONTROL_START);let t=H+f.METRICS_START;_=new Uint32Array(g,t,f.METRICS_SIZE/4),S("[PreScheduler] SharedArrayBuffer initialized with direct ring buffer writing and metrics")},G=()=>{if(!_)return;p(9,o.length);let e=o.length,t=J(10);e>t&&p(10,e)},I=(e,t,r=0,n=!1)=>{if(d==="postMessage")return W?(W.postMessage({type:"osc",oscData:e,sourceId:r}),R(12,1),!0):(console.error("[PreScheduler] No worklet port available"),!1);if(!g||!O)return console.error("[PreScheduler] Not initialized for ring buffer writing"),!1;let s=e.length,c=f.MESSAGE_HEADER_SIZE+s;return c>f.IN_BUFFER_SIZE-f.MESSAGE_HEADER_SIZE?(console.error("[PreScheduler] Message too large:",c),!1):ne({atomicView:O,dataView:Ue,uint8View:de,bufferConstants:f,ringBufferBase:H,controlIndices:F,oscMessage:e,sourceId:r,maxSpins:10,useWait:n,headerScratch:V,headerScratchView:Re})?(R(12,1),!0):!1},y=(e,t,r=0)=>{let n=o.length+l.length;if(n>=N){console.error("[PreScheduler] Backpressure: dropping retry ("+n+" pending)"),R(17,1);return}l.push({oscData:e,context:t||"unknown",queuedAt:performance.now(),sourceId:r}),p(18,l.length);let s=J(19);l.length>s&&p(19,l.length),S("[PreScheduler] Queued message for retry:",t,"queue size:",l.length),Ce()},Ce=()=>{if(X||l.length===0||d!=="sab")return;X=!0;let e=Atomics.load(O,F.IN_TAIL),t=Atomics.waitAsync(O,F.IN_TAIL,e),r=()=>{X=!1,Xe(),l.length>0&&Ce()};t.async?t.value.then(r):queueMicrotask(r)},Xe=()=>{if(l.length===0)return;let e=0;for(let t=0;t<l.length;t++){let r=l[t];if(I(r.oscData,!0,r.sourceId,!0))e++,R(16,1);else break}e>0&&(l.splice(0,e),p(18,l.length))},Se=(e,t,r,n=0)=>{let s=o.length+l.length;if(s>=N){let u=`Prescheduler queue full (${s} >= ${N} max)`;return console.error("[PreScheduler]",u),self.postMessage({type:"error",error:u,code:"PRESCHEDULER_QUEUE_FULL"}),!1}let c=Ye(e);if(c===null)return S("[PreScheduler] Non-bundle message, dispatching immediately"),I(e,!1,n,!0)||y(e,"immediate message",n),!0;let E=ee(),a=c-E;if(e.length>Z){let u=`Bundle too large for scheduler pool (${e.length} > ${Z} bytes)`;return console.error("[PreScheduler]",u),self.postMessage({type:"error",error:u,code:"BUNDLE_TOO_LARGE"}),!1}if(a>ue){let u=`Bundle scheduled too far in future (${a.toFixed(0)}s > ${ue}s max)`;return console.error("[PreScheduler]",u),self.postMessage({type:"error",error:u,code:"BUNDLE_TOO_FAR_FUTURE"}),!1}let T={ntpTime:c,seq:ke++,sessionId:t||0,runTag:r||"",oscData:e,sourceId:n};return Qe(T),R(11,1),G(),S("[PreScheduler] Scheduled bundle:","NTP="+c.toFixed(3),"current="+E.toFixed(3),"wait="+(a*1e3).toFixed(1)+"ms","pending="+o.length),m(),!0},Qe=e=>{o.push(e),We(o.length-1)},he=()=>o.length>0?o[0]:null,Ke=()=>{if(o.length===0)return null;let e=o[0],t=o.pop();return o.length>0&&(o[0]=t,ge(0)),e},We=e=>{for(;e>0;){let t=Math.floor((e-1)/2);if(z(o[e],o[t])>=0)break;pe(e,t),e=t}},ge=e=>{let t=o.length;for(;;){let r=2*e+1,n=2*e+2,s=e;if(r<t&&z(o[r],o[s])<0&&(s=r),n<t&&z(o[n],o[s])<0&&(s=n),s===e)break;pe(e,s),e=s}},z=(e,t)=>e.ntpTime===t.ntpTime?e.seq-t.seq:e.ntpTime-t.ntpTime,pe=(e,t)=>{let r=o[e];o[e]=o[t],o[t]=r},m=()=>{if(o.length===0){C!==null&&(clearTimeout(C),C=null,B=1/0);return}let e=he().ntpTime-j,t=ee();if(e<B){C!==null&&clearTimeout(C);let r=Math.max(0,(e-t)*1e3);B=e,C=setTimeout(Ve,r)}},Ze=()=>{C===null&&(S("[PreScheduler] Starting demand-driven dispatching"),m())};var Ve=()=>{_e=!0;let e=ee(),t=e+j,r=0;for(;o.length>0;){let n=he();if(n.ntpTime<=t){Ke(),G();let s=n.ntpTime-e;if(R(21,1),s<0){let E=Math.round(-s*1e3);R(15,1);let a=fe(23);E>a&&w(23,E)}else{let E=Math.round(s*1e3),a=fe(14);(a===Ae||E<a)&&w(14,E)}S("[PreScheduler] Dispatching bundle:","NTP="+n.ntpTime.toFixed(3),"current="+e.toFixed(3),"early="+(s*1e3).toFixed(1)+"ms","remaining="+o.length),I(n.oscData,!1,n.sourceId,!0)||y(n.oscData,"scheduled bundle NTP="+n.ntpTime.toFixed(3),n.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),_e=!1,C=null,B=1/0,m()},te=e=>{if(o.length===0)return;let t=o.length,r=[];for(let s=0;s<o.length;s++){let c=o[s];e(c)||r.push(c)}let n=t-r.length;n>0&&(o=r,qe(),R(13,n),G(),S("[PreScheduler] Cancelled "+n+" events, "+o.length+" remaining"),m())},qe=()=>{for(let e=Math.floor(o.length/2)-1;e>=0;e--)ge(e)},ze=(e,t)=>{te(r=>r.sessionId===e&&r.runTag===t)},$e=e=>{te(t=>t.sessionId===e)},Je=e=>{te(t=>t.runTag===e)},je=()=>{let e=o.length,t=l.length;e===0&&t===0||(R(13,e+t),o=[],l=[],p(18,0),G(),S("[PreScheduler] Cancelled all "+e+" events, "+t+" retries"),m())},et=se,tt=e=>{let t=[],r=new DataView(e.buffer,e.byteOffset,e.byteLength),n=16;for(;n+4<=e.length;){let s=r.getInt32(n,!1);if(n+=4,s<=0||s>we||n+s>e.length)break;let c=e.slice(n,n+s);for(t.push(c),n+=s;n%4!==0&&n<e.length;)n++}return t},nt=(e,t=0)=>{if(et(e)){let r=tt(e);for(let n=0;n<r.length;n++)I(r[n],!1,t,!0)||y(r[n],"immediate bundle message "+n,t)}else I(e,!1,t,!0)||y(e,"immediate message",t)};self.addEventListener("message",e=>{let{data:t}=e;try{switch(t.type){case"init":if(d=t.mode||"sab",t.maxPendingMessages&&(N=t.maxPendingMessages),t.snapshotIntervalMs&&(q=t.snapshotIntervalMs),t.bypassLookaheadS!==void 0&&(j=t.bypassLookaheadS),d==="sab")g=t.sharedBuffer,H=t.ringBufferBase,f=t.bufferConstants,ve(),f&&f.scheduler_data_pool_size&&(Z=f.scheduler_data_pool_size);else{W=t.workletPort;let n=184;b=new ArrayBuffer(n),_=new Uint32Array(b),Ge()}w(14,Ae),w(23,0),Ze(),S("[OSCPreSchedulerWorker] Initialized with NTP-based scheduling, mode="+d+", capacity="+N),self.postMessage({type:"initialized"});break;case"addOscSource":let r=e.ports[0];r&&(r.onmessage=n=>{n.data.type==="osc"&&n.data.oscData&&Se(n.data.oscData,0,"",n.data.sourceId||0)},S("[OSCPreSchedulerWorker] Added external OSC source"));break;case"send":Se(t.oscData,t.sessionId||0,t.runTag||"",t.sourceId||0);break;case"sendImmediate":nt(t.oscData,t.sourceId||0);break;case"directDispatch":I(t.oscData,!1,t.sourceId||0,!0)||y(t.oscData,"directDispatch fallback",t.sourceId||0);break;case"cancelSessionTag":t.runTag!==void 0&&t.runTag!==null&&t.runTag!==""&&ze(t.sessionId||0,t.runTag);break;case"cancelSession":$e(t.sessionId||0);break;case"cancelTag":t.runTag!==void 0&&t.runTag!==null&&t.runTag!==""&&Je(t.runTag);break;case"cancelAll":je(),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");})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supersonic-scsynth",
3
- "version": "0.66.0",
3
+ "version": "0.67.2",
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",
package/supersonic.d.ts CHANGED
@@ -14,13 +14,9 @@
14
14
  export type UUID = Uint8Array;
15
15
 
16
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.
17
+ * A node identifier (int32).
22
18
  */
23
- export type NodeID = number | UUID;
19
+ export type NodeID = number;
24
20
 
25
21
  // ============================================================================
26
22
  // OSC Types
@@ -36,7 +32,7 @@ export type NodeID = number | UUID;
36
32
  * - `boolean` → `T` / `F`
37
33
  * - `Uint8Array` / `ArrayBuffer` → `b` (blob)
38
34
  *
39
- * For 64-bit, timetag, or UUID types, use the tagged object form:
35
+ * For 64-bit or timetag types, use the tagged object form:
40
36
  * @example
41
37
  * { type: 'int', value: 42 }
42
38
  * { type: 'float', value: 440 } // force float32 for whole numbers
@@ -46,7 +42,6 @@ export type NodeID = number | UUID;
46
42
  * { type: 'int64', value: 9007199254740992n }
47
43
  * { type: 'double', value: 3.141592653589793 }
48
44
  * { type: 'timetag', value: ntpTimestamp }
49
- * { type: 'uuid', value: new Uint8Array(16) }
50
45
  */
51
46
  export type OscArg =
52
47
  | number
@@ -61,8 +56,7 @@ export type OscArg =
61
56
  | { type: 'bool'; value: boolean }
62
57
  | { type: 'int64'; value: number | bigint }
63
58
  | { type: 'double'; value: number }
64
- | { type: 'timetag'; value: number }
65
- | { type: 'uuid'; value: UUID };
59
+ | { type: 'timetag'; value: number };
66
60
 
67
61
  /**
68
62
  * Decoded OSC message as a plain array.
@@ -552,6 +546,8 @@ export interface RawTreeNode {
552
546
  headId: NodeID;
553
547
  /** SynthDef name (synths only, empty string for groups). */
554
548
  defName: string;
549
+ /** UUID if the node was created with a UUID node ID, null otherwise. */
550
+ uuid: UUID | null;
555
551
  }
556
552
 
557
553
  /**
@@ -955,6 +951,73 @@ export class OscChannel {
955
951
  */
956
952
  nextNodeId(): number;
957
953
 
954
+ /**
955
+ * Register a handler for OSC replies from scsynth. Idempotent — replaces
956
+ * any previously-registered handler. In AudioWorklet contexts the worklet
957
+ * must call {@link pollReplies} from `process()` to drain; in all other
958
+ * contexts delivery is automatic. All registered channels receive all
959
+ * replies (broadcast); filter locally if you only need specific addresses.
960
+ *
961
+ * SAB mode: handler receives `(view, offset, length, sequence)` — zero-copy
962
+ * into the shared buffer. Read bytes from `view[offset..offset+length]`.
963
+ * Data is valid only for the duration of the handler call.
964
+ *
965
+ * PM mode: handler receives `(oscData, sequence)` where `oscData` is a copy.
966
+ *
967
+ * @example
968
+ * channel.setReplyHandler((view, offset, length, sequence) => {
969
+ * // SAB: read raw OSC bytes from view[offset..offset+length]
970
+ * });
971
+ */
972
+ setReplyHandler(
973
+ handler:
974
+ | ((view: Uint8Array, offset: number, length: number, sequence: number) => void)
975
+ | ((oscData: Uint8Array, sequence: number) => void),
976
+ ): void;
977
+
978
+ /**
979
+ * Clear the reply handler and release the reply channel. Idempotent.
980
+ */
981
+ clearReplyHandler(): void;
982
+
983
+ /**
984
+ * Activate the reply slot without registering a handler. Usually called
985
+ * for you by {@link setReplyHandler}; only call directly if you want to
986
+ * claim the slot before installing a handler (or to use the optional
987
+ * one-shot handler argument of {@link pollReplies}).
988
+ */
989
+ activateReplies(): void;
990
+
991
+ /**
992
+ * Release the reply slot. Usually called for you by {@link clearReplyHandler}.
993
+ */
994
+ deactivateReplies(): void;
995
+
996
+ /**
997
+ * Drain pending replies, calling the registered handler (or `handler`
998
+ * argument, if given) once per message. Returns the number of messages
999
+ * processed. Zero-allocation on the hot path.
1000
+ *
1001
+ * Call from an AudioWorklet's `process()` method to receive replies on
1002
+ * the audio thread. In other contexts automatic delivery already calls
1003
+ * this for you.
1004
+ *
1005
+ * @param handler - Optional override for this call only
1006
+ * @returns Number of messages drained
1007
+ */
1008
+ pollReplies(
1009
+ handler?:
1010
+ | ((view: Uint8Array, offset: number, length: number, sequence: number) => void)
1011
+ | ((oscData: Uint8Array, sequence: number) => void),
1012
+ ): number;
1013
+
1014
+ /**
1015
+ * Number of reply messages dropped because the reply buffer was full.
1016
+ * SAB mode only — undefined in PM mode or before {@link activateReplies}.
1017
+ * Counter resets each time the slot is (re)claimed.
1018
+ */
1019
+ get replyDrops(): number | undefined;
1020
+
958
1021
  /** Close the channel and release its ports. */
959
1022
  close(): void;
960
1023
 
@@ -1400,6 +1463,35 @@ export class SuperSonic {
1400
1463
  */
1401
1464
  reload(): Promise<boolean>;
1402
1465
 
1466
+ // ──────────────────────────────────────────────────────────────────────────
1467
+ // State observation
1468
+ // ──────────────────────────────────────────────────────────────────────────
1469
+
1470
+ /**
1471
+ * Returns true if the engine has finished booting and is ready to send
1472
+ * and receive messages.
1473
+ *
1474
+ * Mirrors the C++ `SupersonicEngine::isRunning()` accessor; returns the
1475
+ * same value as the existing `initialized` getter, exposed as a method
1476
+ * to match the C++ API shape.
1477
+ */
1478
+ isRunning(): boolean;
1479
+
1480
+ /**
1481
+ * Returns the current engine lifecycle state.
1482
+ *
1483
+ * One of:
1484
+ * - `'stopped'` — before `init()` or after `shutdown()`/`destroy()`.
1485
+ * - `'booting'` — while `init()` is in progress.
1486
+ * - `'running'` — after `init()` resolves and before any teardown.
1487
+ *
1488
+ * Mirrors the C++ `SupersonicEngine::engineState()` accessor. The C++
1489
+ * enum also has `'restarting'` and `'error'` states that the web runtime
1490
+ * does not currently distinguish — `recover()` and `resume()` do not
1491
+ * surface a `'restarting'` state from JS.
1492
+ */
1493
+ getEngineState(): 'stopped' | 'booting' | 'running';
1494
+
1403
1495
  // ──────────────────────────────────────────────────────────────────────────
1404
1496
  // OSC Messaging
1405
1497
  // ──────────────────────────────────────────────────────────────────────────