supersonic-scsynth 0.8.0 → 0.11.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,6 +1,6 @@
1
1
  {
2
2
  "wasmFile": "scsynth-nrt.wasm",
3
- "buildId": "20251125-213819",
4
- "buildTime": "2025-11-25T21:38:19Z",
5
- "gitHash": "6b3db08b2"
3
+ "buildId": "20251127-192339",
4
+ "buildTime": "2025-11-27T19:23:39Z",
5
+ "gitHash": "031e1d105"
6
6
  }
Binary file
@@ -1 +1 @@
1
- (()=>{function $(e,t,s=0){for(let r=0;r<=s;r++)if(Atomics.compareExchange(e,t,0,1)===0)return!0;return!1}function j(e,t){Atomics.store(e,t,0)}function C({atomicView:e,dataView:t,uint8View:s,bufferConstants:r,ringBufferBase:c,controlIndices:E,oscMessage:a,maxSpins:M=0}){let K=a.length,d=r.MESSAGE_HEADER_SIZE+K;if(d>r.IN_BUFFER_SIZE-r.MESSAGE_HEADER_SIZE||!$(e,E.IN_WRITE_LOCK,M))return!1;try{let R=Atomics.load(e,E.IN_HEAD),X=Atomics.load(e,E.IN_TAIL);if((r.IN_BUFFER_SIZE-1-R+X)%r.IN_BUFFER_SIZE<d)return!1;let O=Atomics.add(e,E.IN_SEQUENCE,1),g=r.IN_BUFFER_SIZE-R;if(d>g){let u=new Uint8Array(r.MESSAGE_HEADER_SIZE),p=new DataView(u.buffer);p.setUint32(0,r.MESSAGE_MAGIC,!0),p.setUint32(4,d,!0),p.setUint32(8,O,!0),p.setUint32(12,0,!0);let I=c+r.IN_BUFFER_START+R,D=c+r.IN_BUFFER_START;if(g>=r.MESSAGE_HEADER_SIZE){s.set(u,I);let A=g-r.MESSAGE_HEADER_SIZE;s.set(a.subarray(0,A),I+r.MESSAGE_HEADER_SIZE),s.set(a.subarray(A),D)}else{s.set(u.subarray(0,g),I),s.set(u.subarray(g),D);let A=r.MESSAGE_HEADER_SIZE-g;s.set(a,D+A)}}else{let u=c+r.IN_BUFFER_START+R;t.setUint32(u,r.MESSAGE_MAGIC,!0),t.setUint32(u+4,d,!0),t.setUint32(u+8,O,!0),t.setUint32(u+12,0,!0),s.set(a,u+r.MESSAGE_HEADER_SIZE)}Atomics.load(e,E.IN_HEAD);let V=(R+d)%r.IN_BUFFER_SIZE;return Atomics.store(e,E.IN_HEAD,V),!0}finally{j(e,E.IN_WRITE_LOCK)}}var f=null,_=null,l=null,U=null,G=null,Z=null,k={},o=null,n=[],b=null,oe=0,F=!1,i=[],ce=100,w=5,Ee=2208988800,Q=25,ie=.1,S=(...e)=>{},v=()=>(performance.timeOrigin+performance.now())/1e3+Ee,le=e=>{if(e.length>=16&&e[0]===35){let t=new DataView(e.buffer,e.byteOffset),s=t.getUint32(8,!1),r=t.getUint32(12,!1);return s+r/4294967296}return null};var Se=()=>{if(!f||!l){console.error("[PreScheduler] Cannot init - missing buffer or constants");return}U=new Int32Array(f),G=new DataView(f),Z=new Uint8Array(f),k={IN_HEAD:(_+l.CONTROL_START+0)/4,IN_TAIL:(_+l.CONTROL_START+4)/4,IN_SEQUENCE:(_+l.CONTROL_START+24)/4,IN_WRITE_LOCK:(_+l.CONTROL_START+40)/4};let e=_+l.METRICS_START;o=new Uint32Array(f,e,l.METRICS_SIZE/4),S("[PreScheduler] SharedArrayBuffer initialized with direct ring buffer writing and metrics")},m=()=>{if(!o)return;Atomics.store(o,6,n.length);let e=n.length,t=Atomics.load(o,7);e>t&&Atomics.store(o,7,e)},h=(e,t)=>{if(!f||!U)return console.error("[PreScheduler] Not initialized for ring buffer writing"),!1;let s=e.length,r=l.MESSAGE_HEADER_SIZE+s;return r>l.IN_BUFFER_SIZE-l.MESSAGE_HEADER_SIZE?(console.error("[PreScheduler] Message too large:",r),!1):C({atomicView:U,dataView:G,uint8View:Z,bufferConstants:l,ringBufferBase:_,controlIndices:k,oscMessage:e,maxSpins:10})?(o&&Atomics.add(o,8,1),!0):(t||console.warn("[PreScheduler] Ring buffer full, message will be queued for retry"),!1)},T=(e,t)=>{if(i.length>=ce){console.error("[PreScheduler] Retry queue full, dropping message permanently"),o&&Atomics.add(o,10,1);return}if(i.push({oscData:e,retryCount:0,context:t||"unknown",queuedAt:performance.now()}),o){Atomics.store(o,15,i.length);let s=Atomics.load(o,16);i.length>s&&Atomics.store(o,16,i.length)}S("[PreScheduler] Queued message for retry:",t,"queue size:",i.length)},ue=()=>{if(i.length===0)return;let e=0;for(;e<i.length;){let t=i[e];h(t.oscData,!0)?(i.splice(e,1),o&&(Atomics.add(o,9,1),Atomics.add(o,14,1),Atomics.store(o,15,i.length)),S("[PreScheduler] Retry succeeded for:",t.context,"after",t.retryCount+1,"attempts")):(t.retryCount++,o&&Atomics.add(o,14,1),t.retryCount>=w?(console.error("[PreScheduler] Giving up on message after",w,"retries:",t.context),i.splice(e,1),o&&(Atomics.add(o,10,1),Atomics.store(o,15,i.length))):e++)}},ae=(e,t,s)=>{let r=le(e);if(r===null){S("[PreScheduler] Non-bundle message, dispatching immediately"),h(e,!1)||T(e,"immediate message");return}let c=v(),E=r-c,a={ntpTime:r,seq:oe++,editorId:t||0,runTag:s||"",oscData:e};fe(a),o&&Atomics.add(o,11,1),m(),S("[PreScheduler] Scheduled bundle:","NTP="+r.toFixed(3),"current="+c.toFixed(3),"wait="+(E*1e3).toFixed(1)+"ms","pending="+n.length)},fe=e=>{n.push(e),ge(n.length-1)},_e=()=>n.length>0?n[0]:null,de=()=>{if(n.length===0)return null;let e=n[0],t=n.pop();return n.length>0&&(n[0]=t,q(0)),e},ge=e=>{for(;e>0;){let t=Math.floor((e-1)/2);if(N(n[e],n[t])>=0)break;Y(e,t),e=t}},q=e=>{let t=n.length;for(;;){let s=2*e+1,r=2*e+2,c=e;if(s<t&&N(n[s],n[c])<0&&(c=s),r<t&&N(n[r],n[c])<0&&(c=r),c===e)break;Y(e,c),e=c}},N=(e,t)=>e.ntpTime===t.ntpTime?e.seq-t.seq:e.ntpTime-t.ntpTime,Y=(e,t)=>{let s=n[e];n[e]=n[t],n[t]=s},Re=()=>{if(b!==null){console.warn("[PreScheduler] Polling already started");return}S("[PreScheduler] Starting periodic polling (every "+Q+"ms)"),z()};var z=()=>{F=!0,ue();let e=v(),t=e+ie,s=0;for(;n.length>0;){let r=_e();if(r.ntpTime<=t){de(),m();let c=r.ntpTime-e;o&&Atomics.add(o,13,1),S("[PreScheduler] Dispatching bundle:","NTP="+r.ntpTime.toFixed(3),"current="+e.toFixed(3),"early="+(c*1e3).toFixed(1)+"ms","remaining="+n.length),h(r.oscData,!1)||T(r.oscData,"scheduled bundle NTP="+r.ntpTime.toFixed(3)),s++}else break}(s>0||n.length>0||i.length>0)&&S("[PreScheduler] Dispatch cycle complete:","dispatched="+s,"pending="+n.length,"retrying="+i.length),F=!1,b=setTimeout(z,Q)},W=e=>{if(n.length===0)return;let t=n.length,s=[];for(let c=0;c<n.length;c++){let E=n[c];e(E)||s.push(E)}let r=t-s.length;r>0&&(n=s,he(),o&&Atomics.add(o,12,r),m(),S("[PreScheduler] Cancelled "+r+" events, "+n.length+" remaining"))},he=()=>{for(let e=Math.floor(n.length/2)-1;e>=0;e--)q(e)},pe=(e,t)=>{W(s=>s.editorId===e&&s.runTag===t)},Ae=e=>{W(t=>t.editorId===e)},Te=()=>{if(n.length===0)return;let e=n.length;o&&Atomics.add(o,12,e),n=[],m(),S("[PreScheduler] Cancelled all "+e+" events")},me=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,Ie=e=>{let t=[],s=new DataView(e.buffer,e.byteOffset,e.byteLength),r=16;for(;r<e.length;){let c=s.getInt32(r,!1);if(r+=4,c<=0||r+c>e.length)break;let E=e.slice(r,r+c);for(t.push(E),r+=c;r%4!==0&&r<e.length;)r++}return t},De=e=>{if(me(e)){let t=Ie(e);for(let s=0;s<t.length;s++)h(t[s],!1)||T(t[s],"immediate bundle message "+s)}else h(e,!1)||T(e,"immediate message")};self.addEventListener("message",e=>{let{data:t}=e;try{switch(t.type){case"init":f=t.sharedBuffer,_=t.ringBufferBase,l=t.bufferConstants,Se(),Re(),S("[OSCPreSchedulerWorker] Initialized with NTP-based scheduling and direct ring buffer writing"),self.postMessage({type:"initialized"});break;case"send":ae(t.oscData,t.editorId||0,t.runTag||"");break;case"sendImmediate":De(t.oscData);break;case"cancelEditorTag":t.runTag!==void 0&&t.runTag!==null&&t.runTag!==""&&pe(t.editorId||0,t.runTag);break;case"cancelEditor":Ae(t.editorId||0);break;case"cancelAll":Te();break;default:console.warn("[OSCPreSchedulerWorker] Unknown message type:",t.type)}}catch(s){console.error("[OSCPreSchedulerWorker] Error:",s),self.postMessage({type:"error",error:s.message})}});S("[OSCPreSchedulerWorker] Script loaded");})();
1
+ (()=>{function $(e,t,s=0){for(let r=0;r<=s;r++)if(Atomics.compareExchange(e,t,0,1)===0)return!0;return!1}function ee(e,t){Atomics.store(e,t,0)}function x({atomicView:e,dataView:t,uint8View:s,bufferConstants:r,ringBufferBase:c,controlIndices:i,oscMessage:a,maxSpins:I=0}){let O=a.length,d=r.MESSAGE_HEADER_SIZE+O;if(d>r.IN_BUFFER_SIZE-r.MESSAGE_HEADER_SIZE||!$(e,i.IN_WRITE_LOCK,I))return!1;try{let h=Atomics.load(e,i.IN_HEAD),V=Atomics.load(e,i.IN_TAIL);if((r.IN_BUFFER_SIZE-1-h+V)%r.IN_BUFFER_SIZE<d)return!1;let C=Atomics.add(e,i.IN_SEQUENCE,1),g=r.IN_BUFFER_SIZE-h;if(d>g){let u=new Uint8Array(r.MESSAGE_HEADER_SIZE),A=new DataView(u.buffer);A.setUint32(0,r.MESSAGE_MAGIC,!0),A.setUint32(4,d,!0),A.setUint32(8,C,!0),A.setUint32(12,0,!0);let P=c+r.IN_BUFFER_START+h,D=c+r.IN_BUFFER_START;if(g>=r.MESSAGE_HEADER_SIZE){s.set(u,P);let R=g-r.MESSAGE_HEADER_SIZE;s.set(a.subarray(0,R),P+r.MESSAGE_HEADER_SIZE),s.set(a.subarray(R),D)}else{s.set(u.subarray(0,g),P),s.set(u.subarray(g),D);let R=r.MESSAGE_HEADER_SIZE-g;s.set(a,D+R)}}else{let u=c+r.IN_BUFFER_START+h;t.setUint32(u,r.MESSAGE_MAGIC,!0),t.setUint32(u+4,d,!0),t.setUint32(u+8,C,!0),t.setUint32(u+12,0,!0),s.set(a,u+r.MESSAGE_HEADER_SIZE)}Atomics.load(e,i.IN_HEAD);let j=(h+d)%r.IN_BUFFER_SIZE;return Atomics.store(e,i.IN_HEAD,j),!0}finally{ee(e,i.IN_WRITE_LOCK)}}var f=null,_=null,l=null,N=null,k=null,Z=null,b={},o=null,n=[],Q=null,ce=0,F=!1,E=[],B=5,v=500,ie=2208988800,q=25,Ee=.1,S=(...e)=>{},z=()=>(performance.timeOrigin+performance.now())/1e3+ie,le=e=>{if(e.length>=16&&e[0]===35){let t=new DataView(e.buffer,e.byteOffset),s=t.getUint32(8,!1),r=t.getUint32(12,!1);return s+r/4294967296}return null};var Se=()=>{if(!f||!l){console.error("[PreScheduler] Cannot init - missing buffer or constants");return}N=new Int32Array(f),k=new DataView(f),Z=new Uint8Array(f),b={IN_HEAD:(_+l.CONTROL_START+0)/4,IN_TAIL:(_+l.CONTROL_START+4)/4,IN_SEQUENCE:(_+l.CONTROL_START+24)/4,IN_WRITE_LOCK:(_+l.CONTROL_START+40)/4};let e=_+l.METRICS_START;o=new Uint32Array(f,e,l.METRICS_SIZE/4),S("[PreScheduler] SharedArrayBuffer initialized with direct ring buffer writing and metrics")},m=()=>{if(!o)return;Atomics.store(o,6,n.length);let e=n.length,t=Atomics.load(o,7);e>t&&Atomics.store(o,7,e)},p=(e,t)=>{if(!f||!N)return console.error("[PreScheduler] Not initialized for ring buffer writing"),!1;let s=e.length,r=l.MESSAGE_HEADER_SIZE+s;return r>l.IN_BUFFER_SIZE-l.MESSAGE_HEADER_SIZE?(console.error("[PreScheduler] Message too large:",r),!1):x({atomicView:N,dataView:k,uint8View:Z,bufferConstants:l,ringBufferBase:_,controlIndices:b,oscMessage:e,maxSpins:10})?(o&&Atomics.add(o,8,1),!0):(t||console.warn("[PreScheduler] Ring buffer full, message will be queued for retry"),!1)},T=(e,t)=>{let s=n.length+E.length;if(s>=v){console.error("[PreScheduler] Backpressure: dropping retry ("+s+" pending)"),o&&Atomics.add(o,10,1);return}if(E.push({oscData:e,retryCount:0,context:t||"unknown",queuedAt:performance.now()}),o){Atomics.store(o,15,E.length);let r=Atomics.load(o,16);E.length>r&&Atomics.store(o,16,E.length)}S("[PreScheduler] Queued message for retry:",t,"queue size:",E.length)},ue=()=>{if(E.length===0)return;let e=0;for(;e<E.length;){let t=E[e];p(t.oscData,!0)?(E.splice(e,1),o&&(Atomics.add(o,9,1),Atomics.add(o,14,1),Atomics.store(o,15,E.length)),S("[PreScheduler] Retry succeeded for:",t.context,"after",t.retryCount+1,"attempts")):(t.retryCount++,o&&Atomics.add(o,14,1),t.retryCount>=B?(console.error("[PreScheduler] Giving up on message after",B,"retries:",t.context),E.splice(e,1),o&&(Atomics.add(o,10,1),Atomics.store(o,15,E.length))):e++)}},ae=(e,t,s)=>{let r=n.length+E.length;if(r>=v)return console.warn("[PreScheduler] Backpressure: rejecting message ("+r+" pending)"),!1;let c=le(e);if(c===null)return S("[PreScheduler] Non-bundle message, dispatching immediately"),p(e,!1)||T(e,"immediate message"),!0;let i=z(),a=c-i,I={ntpTime:c,seq:ce++,editorId:t||0,runTag:s||"",oscData:e};return fe(I),o&&Atomics.add(o,11,1),m(),S("[PreScheduler] Scheduled bundle:","NTP="+c.toFixed(3),"current="+i.toFixed(3),"wait="+(a*1e3).toFixed(1)+"ms","pending="+n.length),!0},fe=e=>{n.push(e),ge(n.length-1)},_e=()=>n.length>0?n[0]:null,de=()=>{if(n.length===0)return null;let e=n[0],t=n.pop();return n.length>0&&(n[0]=t,Y(0)),e},ge=e=>{for(;e>0;){let t=Math.floor((e-1)/2);if(M(n[e],n[t])>=0)break;W(e,t),e=t}},Y=e=>{let t=n.length;for(;;){let s=2*e+1,r=2*e+2,c=e;if(s<t&&M(n[s],n[c])<0&&(c=s),r<t&&M(n[r],n[c])<0&&(c=r),c===e)break;W(e,c),e=c}},M=(e,t)=>e.ntpTime===t.ntpTime?e.seq-t.seq:e.ntpTime-t.ntpTime,W=(e,t)=>{let s=n[e];n[e]=n[t],n[t]=s},he=()=>{if(Q!==null){console.warn("[PreScheduler] Polling already started");return}S("[PreScheduler] Starting periodic polling (every "+q+"ms)"),K()};var K=()=>{F=!0,ue();let e=z(),t=e+Ee,s=0;for(;n.length>0;){let r=_e();if(r.ntpTime<=t){de(),m();let c=r.ntpTime-e;o&&Atomics.add(o,13,1),S("[PreScheduler] Dispatching bundle:","NTP="+r.ntpTime.toFixed(3),"current="+e.toFixed(3),"early="+(c*1e3).toFixed(1)+"ms","remaining="+n.length),p(r.oscData,!1)||T(r.oscData,"scheduled bundle NTP="+r.ntpTime.toFixed(3)),s++}else break}(s>0||n.length>0||E.length>0)&&S("[PreScheduler] Dispatch cycle complete:","dispatched="+s,"pending="+n.length,"retrying="+E.length),F=!1,Q=setTimeout(K,q)},X=e=>{if(n.length===0)return;let t=n.length,s=[];for(let c=0;c<n.length;c++){let i=n[c];e(i)||s.push(i)}let r=t-s.length;r>0&&(n=s,pe(),o&&Atomics.add(o,12,r),m(),S("[PreScheduler] Cancelled "+r+" events, "+n.length+" remaining"))},pe=()=>{for(let e=Math.floor(n.length/2)-1;e>=0;e--)Y(e)},Ae=(e,t)=>{X(s=>s.editorId===e&&s.runTag===t)},Re=e=>{X(t=>t.editorId===e)},Te=()=>{if(n.length===0)return;let e=n.length;o&&Atomics.add(o,12,e),n=[],m(),S("[PreScheduler] Cancelled all "+e+" events")},me=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,Ie=e=>{let t=[],s=new DataView(e.buffer,e.byteOffset,e.byteLength),r=16;for(;r<e.length;){let c=s.getInt32(r,!1);if(r+=4,c<=0||r+c>e.length)break;let i=e.slice(r,r+c);for(t.push(i),r+=c;r%4!==0&&r<e.length;)r++}return t},Pe=e=>{if(me(e)){let t=Ie(e);for(let s=0;s<t.length;s++)p(t[s],!1)||T(t[s],"immediate bundle message "+s)}else p(e,!1)||T(e,"immediate message")};self.addEventListener("message",e=>{let{data:t}=e;try{switch(t.type){case"init":f=t.sharedBuffer,_=t.ringBufferBase,l=t.bufferConstants,Se(),he(),S("[OSCPreSchedulerWorker] Initialized with NTP-based scheduling and direct ring buffer writing"),self.postMessage({type:"initialized"});break;case"send":ae(t.oscData,t.editorId||0,t.runTag||"");break;case"sendImmediate":Pe(t.oscData);break;case"cancelEditorTag":t.runTag!==void 0&&t.runTag!==null&&t.runTag!==""&&Ae(t.editorId||0,t.runTag);break;case"cancelEditor":Re(t.editorId||0);break;case"cancelAll":Te();break;default:console.warn("[OSCPreSchedulerWorker] Unknown message type:",t.type)}}catch(s){console.error("[OSCPreSchedulerWorker] Error:",s),self.postMessage({type:"error",error:s.message})}});S("[OSCPreSchedulerWorker] Script loaded");})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supersonic-scsynth",
3
- "version": "0.8.0",
3
+ "version": "0.11.0",
4
4
  "description": "SuperCollider scsynth WebAssembly port for AudioWorklet - Run SuperCollider synthesis in the browser",
5
5
  "main": "dist/supersonic.js",
6
6
  "unpkg": "dist/supersonic.js",
@@ -11,7 +11,7 @@
11
11
  "build:release": "./build.sh --release",
12
12
  "clean": "./clean.sh",
13
13
  "dev": "cd example && ruby server.rb",
14
- "test": "playwright test",
14
+ "test": "playwright test --reporter=list",
15
15
  "prepublishOnly": "./build.sh --release"
16
16
  },
17
17
  "repository": {