supersonic-scsynth 0.21.6 → 0.21.7

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
@@ -11,24 +11,51 @@
11
11
  - _AudioWorklet_ - runs in a dedicated high priority audio thread
12
12
  - _WebAssembly_ - scsynth's C++ code compiled for the web
13
13
  - _OSC API_ - talk to the scsynth server through its native OSC API
14
+ - _Zero Config CDN_ - works directly from unpkg with no server setup
14
15
 
15
16
  **[Try the live demo](https://sonic-pi.net/supersonic/demo.html)**
16
17
 
17
18
  ## Getting Started
18
19
 
19
- Injecting the full power of SuperCollider's scsynth audio engine into your browser is simple.
20
+ ### CDN (Zero Config)
20
21
 
21
- Import SuperSonic and initialise it:
22
+ The simplest way to use SuperSonic - no server setup required:
23
+
24
+ ```html
25
+ <script type="module">
26
+ import { SuperSonic } from "https://unpkg.com/supersonic-scsynth@latest";
27
+
28
+ const supersonic = new SuperSonic();
29
+ await supersonic.init();
30
+ await supersonic.loadSynthDef("sonic-pi-prophet");
31
+ supersonic.send("/s_new", "sonic-pi-prophet", -1, 0, 0, "note", 60);
32
+ </script>
33
+ ```
34
+
35
+ All URLs are auto-detected from the import path. See `example/cdn.html` for a working example.
36
+
37
+ ### Self-Hosted
38
+
39
+ You can also host the files yourself:
22
40
 
23
41
  ```javascript
24
- import { SuperSonic } from "supersonic-scsynth";
42
+ import { SuperSonic } from "./supersonic/supersonic.js";
43
+
44
+ const supersonic = new SuperSonic(); // URLs auto-detected from import path
45
+ await supersonic.init();
46
+ ```
25
47
 
48
+ Or with explicit configuration:
49
+
50
+ ```javascript
26
51
  const supersonic = new SuperSonic({
27
52
  baseURL: "/supersonic/"
28
53
  });
29
54
  await supersonic.init();
30
55
  ```
31
56
 
57
+ ### Playing Sounds
58
+
32
59
  Load and play a synth:
33
60
 
34
61
  ```javascript
@@ -44,11 +71,27 @@ await supersonic.loadSample(0, "loop_amen.flac");
44
71
  supersonic.send("/s_new", "sonic-pi-basic_stereo_player", -1, 0, 0, "buf", 0);
45
72
  ```
46
73
 
47
- Take a look at `example/simple.html` for a minimal working example.
74
+ See `example/simple.html` for a minimal working example.
48
75
 
49
76
  ## Installation
50
77
 
51
- Grab the latest pre-built distribution from [GitHub Releases](https://github.com/samaaron/supersonic/releases) and host it on your server:
78
+ ### Option 1: CDN (Recommended for Getting Started)
79
+
80
+ No installation needed - just import directly:
81
+
82
+ ```javascript
83
+ import { SuperSonic } from "https://unpkg.com/supersonic-scsynth@latest";
84
+ ```
85
+
86
+ ### Option 2: npm
87
+
88
+ ```bash
89
+ npm install supersonic-scsynth
90
+ ```
91
+
92
+ ### Option 3: Self-Hosted Bundle
93
+
94
+ Download the pre-built distribution from [GitHub Releases](https://github.com/samaaron/supersonic/releases):
52
95
 
53
96
  ```bash
54
97
  curl -LO https://github.com/samaaron/supersonic/releases/latest/download/supersonic.zip
@@ -62,18 +105,10 @@ supersonic/
62
105
  ├── supersonic.js # Main library
63
106
  ├── wasm/ # WebAssembly binaries
64
107
  ├── workers/ # Web Workers
65
- ├── synthdefs/ # 120 synth definitions
108
+ ├── synthdefs/ # 127 synth definitions
66
109
  └── samples/ # 206 audio samples
67
110
  ```
68
111
 
69
- Or install via npm:
70
-
71
- ```bash
72
- npm install supersonic-scsynth-bundle
73
- ```
74
-
75
- **Note:** SuperSonic must be self-hosted due to browser security requirements around SharedArrayBuffer. It cannot be loaded from a CDN. See [Browser Setup](docs/BROWSER_SETUP.md) for the details.
76
-
77
112
  ## Documentation
78
113
 
79
114
  - [API Reference](docs/API.md) - Methods, callbacks, and configuration
@@ -1,7 +1,7 @@
1
- var o={},o=o||{};(function(){"use strict";o.SECS_70YRS=2208988800,o.TWO_32=4294967296,o.defaults={metadata:!1,unpackSingleArgs:!0},o.isCommonJS=!!(typeof module<"u"&&module.exports),o.isNode=o.isCommonJS&&typeof window>"u",o.isElectron=!!(typeof process<"u"&&process.versions&&process.versions.electron),o.isBufferEnv=o.isNode||o.isElectron,o.isArray=function(i){return i&&Object.prototype.toString.call(i)==="[object Array]"},o.isTypedArrayView=function(i){return i.buffer&&i.buffer instanceof ArrayBuffer},o.isBuffer=function(i){return o.isBufferEnv&&i instanceof Buffer},o.Long=typeof Long<"u"?Long:void 0,o.TextDecoder=typeof TextDecoder<"u"?new TextDecoder("utf-8"):typeof util<"u"&&typeof(util.TextDecoder!=="undefined")?new util.TextDecoder("utf-8"):void 0,o.TextEncoder=typeof TextEncoder<"u"?new TextEncoder("utf-8"):typeof util<"u"&&typeof(util.TextEncoder!=="undefined")?new util.TextEncoder("utf-8"):void 0,o.dataView=function(i,e,t){return i.buffer?new DataView(i.buffer,e,t):i instanceof ArrayBuffer?new DataView(i,e,t):new DataView(new Uint8Array(i),e,t)},o.byteArray=function(i){if(i instanceof Uint8Array)return i;var e=i.buffer?i.buffer:i;if(!(e instanceof ArrayBuffer)&&(typeof e.length>"u"||typeof e=="string"))throw new Error("Can't wrap a non-array-like object as Uint8Array. Object was: "+JSON.stringify(i,null,2));return new Uint8Array(e)},o.nativeBuffer=function(i){return o.isBufferEnv?o.isBuffer(i)?i:Buffer.from(i.buffer?i:new Uint8Array(i)):o.isTypedArrayView(i)?i:new Uint8Array(i)},o.copyByteArray=function(i,e,t){if(o.isTypedArrayView(i)&&o.isTypedArrayView(e))e.set(i,t);else for(var s=t===void 0?0:t,r=Math.min(e.length-t,i.length),n=0,a=s;n<r;n++,a++)e[a]=i[n];return e},o.readString=function(i,e){for(var t=[],s=e.idx;s<i.byteLength;s++){var r=i.getUint8(s);if(r!==0)t.push(r);else{s++;break}}s=s+3&-4,e.idx=s;var n=o.isBufferEnv?o.readString.withBuffer:o.TextDecoder?o.readString.withTextDecoder:o.readString.raw;return n(t)},o.readString.raw=function(i){for(var e="",t=1e4,s=0;s<i.length;s+=t)e+=String.fromCharCode.apply(null,i.slice(s,s+t));return e},o.readString.withTextDecoder=function(i){var e=new Int8Array(i);return o.TextDecoder.decode(e)},o.readString.withBuffer=function(i){return Buffer.from(i).toString("utf-8")},o.writeString=function(i){var e=o.isBufferEnv?o.writeString.withBuffer:o.TextEncoder?o.writeString.withTextEncoder:null,t=i+"\0",s;e&&(s=e(t));for(var r=e?s.length:t.length,n=r+3&-4,a=new Uint8Array(n),c=0;c<r-1;c++){var l=e?s[c]:t.charCodeAt(c);a[c]=l}return a},o.writeString.withTextEncoder=function(i){return o.TextEncoder.encode(i)},o.writeString.withBuffer=function(i){return Buffer.from(i)},o.readPrimitive=function(i,e,t,s){var r=i[e](s.idx,!1);return s.idx+=t,r},o.writePrimitive=function(i,e,t,s,r){r=r===void 0?0:r;var n;return e?n=new Uint8Array(e.buffer):(n=new Uint8Array(s),e=new DataView(n.buffer)),e[t](r,i,!1),n},o.readInt32=function(i,e){return o.readPrimitive(i,"getInt32",4,e)},o.writeInt32=function(i,e,t){return o.writePrimitive(i,e,"setInt32",4,t)},o.readInt64=function(i,e){var t=o.readPrimitive(i,"getInt32",4,e),s=o.readPrimitive(i,"getInt32",4,e);return o.Long?new o.Long(s,t):{high:t,low:s,unsigned:!1}},o.writeInt64=function(i,e,t){var s=new Uint8Array(8);return s.set(o.writePrimitive(i.high,e,"setInt32",4,t),0),s.set(o.writePrimitive(i.low,e,"setInt32",4,t+4),4),s},o.readFloat32=function(i,e){return o.readPrimitive(i,"getFloat32",4,e)},o.writeFloat32=function(i,e,t){return o.writePrimitive(i,e,"setFloat32",4,t)},o.readFloat64=function(i,e){return o.readPrimitive(i,"getFloat64",8,e)},o.writeFloat64=function(i,e,t){return o.writePrimitive(i,e,"setFloat64",8,t)},o.readChar32=function(i,e){var t=o.readPrimitive(i,"getUint32",4,e);return String.fromCharCode(t)},o.writeChar32=function(i,e,t){var s=i.charCodeAt(0);if(!(s===void 0||s<-1))return o.writePrimitive(s,e,"setUint32",4,t)},o.readBlob=function(i,e){var t=o.readInt32(i,e),s=t+3&-4,r=new Uint8Array(i.buffer,e.idx,t);return e.idx+=s,r},o.writeBlob=function(i){i=o.byteArray(i);var e=i.byteLength,t=e+3&-4,s=4,r=t+s,n=new Uint8Array(r),a=new DataView(n.buffer);return o.writeInt32(e,a),n.set(i,s),n},o.readMIDIBytes=function(i,e){var t=new Uint8Array(i.buffer,e.idx,4);return e.idx+=4,t},o.writeMIDIBytes=function(i){i=o.byteArray(i);var e=new Uint8Array(4);return e.set(i),e},o.readColor=function(i,e){var t=new Uint8Array(i.buffer,e.idx,4),s=t[3]/255;return e.idx+=4,{r:t[0],g:t[1],b:t[2],a:s}},o.writeColor=function(i){var e=Math.round(i.a*255),t=new Uint8Array([i.r,i.g,i.b,e]);return t},o.readTrue=function(){return!0},o.readFalse=function(){return!1},o.readNull=function(){return null},o.readImpulse=function(){return 1},o.readTimeTag=function(i,e){var t=o.readPrimitive(i,"getUint32",4,e),s=o.readPrimitive(i,"getUint32",4,e),r=t===0&&s===1?Date.now():o.ntpToJSTime(t,s);return{raw:[t,s],native:r}},o.writeTimeTag=function(i){var e=i.raw?i.raw:o.jsToNTPTime(i.native),t=new Uint8Array(8),s=new DataView(t.buffer);return o.writeInt32(e[0],s,0),o.writeInt32(e[1],s,4),t},o.timeTag=function(i,e){i=i||0,e=e||Date.now();var t=e/1e3,s=Math.floor(t),r=t-s,n=Math.floor(i),a=i-n,c=r+a;if(c>1){var l=Math.floor(c),u=c-l;n+=l,c=u}var f=s+n+o.SECS_70YRS,h=Math.round(o.TWO_32*c);return{raw:[f,h]}},o.ntpToJSTime=function(i,e){var t=i-o.SECS_70YRS,s=e/o.TWO_32,r=(t+s)*1e3;return r},o.jsToNTPTime=function(i){var e=i/1e3,t=Math.floor(e),s=e-t,r=t+o.SECS_70YRS,n=Math.round(o.TWO_32*s);return[r,n]},o.readArguments=function(i,e,t){var s=o.readString(i,t);if(s.indexOf(",")!==0)throw new Error("A malformed type tag string was found while reading the arguments of an OSC message. String was: "+s," at offset: "+t.idx);var r=s.substring(1).split(""),n=[];return o.readArgumentsIntoArray(n,r,s,i,e,t),n},o.readArgument=function(i,e,t,s,r){var n=o.argumentTypes[i];if(!n)throw new Error("'"+i+"' is not a valid OSC type tag. Type tag string was: "+e);var a=n.reader,c=o[a](t,r);return s.metadata&&(c={type:i,value:c}),c},o.readArgumentsIntoArray=function(i,e,t,s,r,n){for(var a=0;a<e.length;){var c=e[a],l;if(c==="["){var u=e.slice(a+1),f=u.indexOf("]");if(f<0)throw new Error("Invalid argument type tag: an open array type tag ('[') was found without a matching close array tag ('[]'). Type tag was: "+t);var h=u.slice(0,f);l=o.readArgumentsIntoArray([],h,t,s,r,n),a+=f+2}else l=o.readArgument(c,t,s,r,n),a++;i.push(l)}return i},o.writeArguments=function(i,e){var t=o.collectArguments(i,e);return o.joinParts(t)},o.joinParts=function(i){for(var e=new Uint8Array(i.byteLength),t=i.parts,s=0,r=0;r<t.length;r++){var n=t[r];o.copyByteArray(n,e,s),s+=n.length}return e},o.addDataPart=function(i,e){e.parts.push(i),e.byteLength+=i.length},o.writeArrayArguments=function(i,e){for(var t="[",s=0;s<i.length;s++){var r=i[s];t+=o.writeArgument(r,e)}return t+="]",t},o.writeArgument=function(i,e){if(o.isArray(i))return o.writeArrayArguments(i,e);var t=i.type,s=o.argumentTypes[t].writer;if(s){var r=o[s](i.value);o.addDataPart(r,e)}return i.type},o.collectArguments=function(i,e,t){o.isArray(i)||(i=typeof i>"u"?[]:[i]),t=t||{byteLength:0,parts:[]},e.metadata||(i=o.annotateArguments(i));for(var s=",",r=t.parts.length,n=0;n<i.length;n++){var a=i[n];s+=o.writeArgument(a,t)}var c=o.writeString(s);return t.byteLength+=c.byteLength,t.parts.splice(r,0,c),t},o.readMessage=function(i,e,t){e=e||o.defaults;var s=o.dataView(i,i.byteOffset,i.byteLength);t=t||{idx:0};var r=o.readString(s,t);return o.readMessageContents(r,s,e,t)},o.readMessageContents=function(i,e,t,s){if(i.indexOf("/")!==0)throw new Error("A malformed OSC address was found while reading an OSC message. String was: "+i);var r=o.readArguments(e,t,s);return{address:i,args:r.length===1&&t.unpackSingleArgs?r[0]:r}},o.collectMessageParts=function(i,e,t){return t=t||{byteLength:0,parts:[]},o.addDataPart(o.writeString(i.address),t),o.collectArguments(i.args,e,t)},o.writeMessage=function(i,e){if(e=e||o.defaults,!o.isValidMessage(i))throw new Error("An OSC message must contain a valid address. Message was: "+JSON.stringify(i,null,2));var t=o.collectMessageParts(i,e);return o.joinParts(t)},o.isValidMessage=function(i){return i.address&&i.address.indexOf("/")===0},o.readBundle=function(i,e,t){return o.readPacket(i,e,t)},o.collectBundlePackets=function(i,e,t){t=t||{byteLength:0,parts:[]},o.addDataPart(o.writeString("#bundle"),t),o.addDataPart(o.writeTimeTag(i.timeTag),t);for(var s=0;s<i.packets.length;s++){var r=i.packets[s],n=r.address?o.collectMessageParts:o.collectBundlePackets,a=n(r,e);t.byteLength+=a.byteLength,o.addDataPart(o.writeInt32(a.byteLength),t),t.parts=t.parts.concat(a.parts)}return t},o.writeBundle=function(i,e){if(!o.isValidBundle(i))throw new Error("An OSC bundle must contain 'timeTag' and 'packets' properties. Bundle was: "+JSON.stringify(i,null,2));e=e||o.defaults;var t=o.collectBundlePackets(i,e);return o.joinParts(t)},o.isValidBundle=function(i){return i.timeTag!==void 0&&i.packets!==void 0},o.readBundleContents=function(i,e,t,s){for(var r=o.readTimeTag(i,t),n=[];t.idx<s;){var a=o.readInt32(i,t),c=t.idx+a,l=o.readPacket(i,e,t,c);n.push(l)}return{timeTag:r,packets:n}},o.readPacket=function(i,e,t,s){var r=o.dataView(i,i.byteOffset,i.byteLength);s=s===void 0?r.byteLength:s,t=t||{idx:0};var n=o.readString(r,t),a=n[0];if(a==="#")return o.readBundleContents(r,e,t,s);if(a==="/")return o.readMessageContents(n,r,e,t);throw new Error("The header of an OSC packet didn't contain an OSC address or a #bundle string. Header was: "+n)},o.writePacket=function(i,e){if(o.isValidMessage(i))return o.writeMessage(i,e);if(o.isValidBundle(i))return o.writeBundle(i,e);throw new Error("The specified packet was not recognized as a valid OSC message or bundle. Packet was: "+JSON.stringify(i,null,2))},o.argumentTypes={i:{reader:"readInt32",writer:"writeInt32"},h:{reader:"readInt64",writer:"writeInt64"},f:{reader:"readFloat32",writer:"writeFloat32"},s:{reader:"readString",writer:"writeString"},S:{reader:"readString",writer:"writeString"},b:{reader:"readBlob",writer:"writeBlob"},t:{reader:"readTimeTag",writer:"writeTimeTag"},T:{reader:"readTrue"},F:{reader:"readFalse"},N:{reader:"readNull"},I:{reader:"readImpulse"},d:{reader:"readFloat64",writer:"writeFloat64"},c:{reader:"readChar32",writer:"writeChar32"},r:{reader:"readColor",writer:"writeColor"},m:{reader:"readMIDIBytes",writer:"writeMIDIBytes"}},o.inferTypeForArgument=function(i){var e=typeof i;switch(e){case"boolean":return i?"T":"F";case"string":return"s";case"number":return"f";case"undefined":return"N";case"object":if(i===null)return"N";if(i instanceof Uint8Array||i instanceof ArrayBuffer)return"b";if(typeof i.high=="number"&&typeof i.low=="number")return"h";break}throw new Error("Can't infer OSC argument type for value: "+JSON.stringify(i,null,2))},o.annotateArguments=function(i){for(var e=[],t=0;t<i.length;t++){var s=i[t],r;if(typeof s=="object"&&s.type&&s.value!==void 0)r=s;else if(o.isArray(s))r=o.annotateArguments(s);else{var n=o.inferTypeForArgument(s);r={type:n,value:s}}e.push(r)}return e}})();var O=function(){};O.prototype.on=function(){};O.prototype.emit=function(){};O.prototype.removeListener=function(){};(function(){"use strict";o.supportsSerial=!1,o.firePacketEvents=function(e,t,s,r){t.address?e.emit("message",t,s,r):o.fireBundleEvents(e,t,s,r)},o.fireBundleEvents=function(e,t,s,r){e.emit("bundle",t,s,r);for(var n=0;n<t.packets.length;n++){var a=t.packets[n];o.firePacketEvents(e,a,t.timeTag,r)}},o.fireClosedPortSendError=function(e,t){t=t||"Can't send packets on a closed osc.Port object. Please open (or reopen) this Port by calling open().",e.emit("error",t)},o.Port=function(e){this.options=e||{},this.on("data",this.decodeOSC.bind(this))};var i=o.Port.prototype=Object.create(O.prototype);i.constructor=o.Port,i.send=function(e){var t=Array.prototype.slice.call(arguments),s=this.encodeOSC(e),r=o.nativeBuffer(s);t[0]=r,this.sendRaw.apply(this,t)},i.encodeOSC=function(e){e=e.buffer?e.buffer:e;var t;try{t=o.writePacket(e,this.options)}catch(s){this.emit("error",s)}return t},i.decodeOSC=function(e,t){e=o.byteArray(e),this.emit("raw",e,t);try{var s=o.readPacket(e,this.options);this.emit("osc",s,t),o.firePacketEvents(this,s,void 0,t)}catch(r){this.emit("error",r)}},o.SLIPPort=function(e){var t=this,s=this.options=e||{};s.useSLIP=s.useSLIP===void 0?!0:s.useSLIP,this.decoder=new slip.Decoder({onMessage:this.decodeOSC.bind(this),onError:function(n){t.emit("error",n)}});var r=s.useSLIP?this.decodeSLIPData:this.decodeOSC;this.on("data",r.bind(this))},i=o.SLIPPort.prototype=Object.create(o.Port.prototype),i.constructor=o.SLIPPort,i.encodeOSC=function(e){e=e.buffer?e.buffer:e;var t;try{var s=o.writePacket(e,this.options);t=slip.encode(s)}catch(r){this.emit("error",r)}return t},i.decodeSLIPData=function(e,t){this.decoder.decode(e,t)},o.relay=function(e,t,s,r,n,a){s=s||"message",r=r||"send",n=n||function(){},a=a?[null].concat(a):[];var c=function(l){a[0]=l,l=n(l),t[r].apply(t,a)};return e.on(s,c),{eventName:s,listener:c}},o.relayPorts=function(e,t,s){var r=s.raw?"raw":"osc",n=s.raw?"sendRaw":"send";return o.relay(e,t,r,n,s.transform)},o.stopRelaying=function(e,t){e.removeListener(t.eventName,t.listener)},o.Relay=function(e,t,s){var r=this.options=s||{};r.raw=!1,this.port1=e,this.port2=t,this.listen()},i=o.Relay.prototype=Object.create(O.prototype),i.constructor=o.Relay,i.open=function(){this.port1.open(),this.port2.open()},i.listen=function(){this.port1Spec&&this.port2Spec&&this.close(),this.port1Spec=o.relayPorts(this.port1,this.port2,this.options),this.port2Spec=o.relayPorts(this.port2,this.port1,this.options);var e=this.close.bind(this);this.port1.on("close",e),this.port2.on("close",e)},i.close=function(){o.stopRelaying(this.port1,this.port1Spec),o.stopRelaying(this.port2,this.port2Spec),this.emit("close",this.port1,this.port2)}})();(function(){"use strict";o.WebSocket=typeof WebSocket<"u"?WebSocket:void 0,o.WebSocketPort=function(e){o.Port.call(this,e),this.on("open",this.listen.bind(this)),this.socket=e.socket,this.socket&&(this.socket.readyState===1?(o.WebSocketPort.setupSocketForBinary(this.socket),this.emit("open",this.socket)):this.open())};var i=o.WebSocketPort.prototype=Object.create(o.Port.prototype);i.constructor=o.WebSocketPort,i.open=function(){(!this.socket||this.socket.readyState>1)&&(this.socket=new o.WebSocket(this.options.url)),o.WebSocketPort.setupSocketForBinary(this.socket);var e=this;this.socket.onopen=function(){e.emit("open",e.socket)},this.socket.onerror=function(t){e.emit("error",t)}},i.listen=function(){var e=this;this.socket.onmessage=function(t){e.emit("data",t.data,t)},this.socket.onclose=function(t){e.emit("close",t)},e.emit("ready")},i.sendRaw=function(e){if(!this.socket||this.socket.readyState!==1){o.fireClosedPortSendError(this);return}this.socket.send(e)},i.close=function(e,t){this.socket.close(e,t)},o.WebSocketPort.setupSocketForBinary=function(e){e.binaryType=o.isNode?"nodebuffer":"arraybuffer"}})();var D=o,{readPacket:ct,writePacket:lt,readMessage:ut,writeMessage:ht,readBundle:ft,writeBundle:dt}=o;var $=new Map;function K(i){try{return new URL(i,window.location.href).origin!==window.location.origin}catch{return!1}}async function X(i){if($.has(i))return $.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 $.set(i,r),r}async function B(i,e={}){let t=i;return K(i)&&(t=await X(i)),new Worker(t,e)}async function J(i,e){let t=e;K(e)&&(t=await X(e)),await i.addModule(t)}var M=class{constructor(e=null){this.workerBaseURL=e,this.mode="sab",this.workletPort=null,this.workers={oscOut:null,oscIn:null,debug:null},this.callbacks={onRawOSC:null,onParsedOSC:null,onDebugMessage:null,onError:null,onInitialized:null},this.initialized=!1,this.sharedBuffer=null,this.ringBufferBase=null,this.bufferConstants=null,this.cachedPreschedulerMetrics=null}getPreschedulerMetrics(){return this.cachedPreschedulerMetrics}async init(e={}){if(this.initialized){console.warn("[ScsynthOSC] Already initialized");return}if(this.mode=e.mode||"sab",this.preschedulerCapacity=e.preschedulerCapacity||65536,this.mode==="sab")await this.#s(e);else if(this.mode==="postMessage")await this.#i(e);else throw new Error(`Unknown mode: ${this.mode}`);this.initialized=!0,this.callbacks.onInitialized&&this.callbacks.onInitialized()}async#s(e){if(this.sharedBuffer=e.sharedBuffer,this.ringBufferBase=e.ringBufferBase,this.bufferConstants=e.bufferConstants,!this.sharedBuffer||!this.bufferConstants)throw new Error("SAB mode requires sharedBuffer and bufferConstants");try{let[t,s,r]=await Promise.all([B(this.workerBaseURL+"osc_out_prescheduler_worker.js",{type:"module"}),B(this.workerBaseURL+"osc_in_worker.js",{type:"module"}),B(this.workerBaseURL+"debug_worker.js",{type:"module"})]);this.workers.oscOut=t,this.workers.oscIn=s,this.workers.debug=r,this.#n();let n=[this.#h(this.workers.oscOut,"OSC SCHEDULER+WRITER",{mode:"sab",maxPendingMessages:this.preschedulerCapacity}),this.#h(this.workers.oscIn,"OSC IN"),this.#h(this.workers.debug,"DEBUG")];await Promise.all(n),this.workers.oscIn.postMessage({type:"start"}),this.workers.debug.postMessage({type:"start"})}catch(t){throw console.error("[ScsynthOSC] SAB mode initialization failed:",t),this.callbacks.onError&&this.callbacks.onError(t),t}}async#i(e){if(this.workletPort=e.workletPort,!this.workletPort)throw new Error("postMessage mode requires workletPort");try{let[t,s]=await Promise.all([B(this.workerBaseURL+"osc_out_prescheduler_worker.js",{type:"module"}),B(this.workerBaseURL+"debug_worker.js",{type:"module"})]);this.workers.oscOut=t,this.workers.debug=s,this.#f();let r=[this.#h(this.workers.oscOut,"OSC SCHEDULER",{mode:"postMessage",maxPendingMessages:this.preschedulerCapacity}),this.#h(this.workers.debug,"DEBUG",{mode:"postMessage"})];await Promise.all(r)}catch(t){throw console.error("[ScsynthOSC] postMessage mode initialization failed:",t),this.callbacks.onError&&this.callbacks.onError(t),t}}#h(e,t,s={}){return new Promise((r,n)=>{let a=setTimeout(()=>{n(new Error(`${t} worker initialization timeout`))},5e3),c=u=>{u.data.type==="initialized"&&(clearTimeout(a),e.removeEventListener("message",c),r())};e.addEventListener("message",c);let l={type:"init",...s};this.mode==="sab"&&this.sharedBuffer&&(l.sharedBuffer=this.sharedBuffer,l.ringBufferBase=this.ringBufferBase,l.bufferConstants=this.bufferConstants),e.postMessage(l)})}#n(){this.workers.oscIn.onmessage=e=>{let t=e.data;switch(t.type){case"messages":this.#e(t.messages);break;case"error":console.error("[ScsynthOSC] OSC IN error:",t.error),this.callbacks.onError&&this.callbacks.onError(t.error,"oscIn");break}},this.workers.debug.onmessage=e=>{let t=e.data;switch(t.type){case"debug":this.callbacks.onDebugMessage&&t.messages.forEach(s=>{this.callbacks.onDebugMessage(s)});break;case"error":console.error("[ScsynthOSC] DEBUG error:",t.error),this.callbacks.onError&&this.callbacks.onError(t.error,"debug");break}},this.workers.oscOut.onmessage=e=>{let t=e.data;t.type==="error"&&(console.error("[ScsynthOSC] OSC OUT error:",t.error),this.callbacks.onError&&this.callbacks.onError(t.error,"oscOut"))}}#f(){this.workers.oscOut.onmessage=e=>{let t=e.data;switch(t.type){case"dispatch":this.workletPort&&this.workletPort.postMessage({type:"osc",oscData:t.oscData,timestamp:t.timestamp});break;case"preschedulerMetrics":this.cachedPreschedulerMetrics=t.metrics;break;case"error":console.error("[ScsynthOSC] OSC OUT error:",t.error),this.callbacks.onError&&this.callbacks.onError(t.error,"oscOut");break}},this.workers.debug.onmessage=e=>{let t=e.data;switch(t.type){case"debug":this.callbacks.onDebugMessage&&t.messages.forEach(s=>{this.callbacks.onDebugMessage(s)});break;case"error":console.error("[ScsynthOSC] DEBUG error:",t.error),this.callbacks.onError&&this.callbacks.onError(t.error,"debug");break}},this.workletPort.addEventListener("message",e=>{let t=e.data;switch(t.type){case"oscReply":t.oscData&&this.#e([{oscData:t.oscData}]);break;case"oscReplies":t.messages&&this.#e(t.messages);break;case"debugRawBatch":this.workers.debug&&t.messages&&this.workers.debug.postMessage({type:"debugRaw",messages:t.messages});break}})}#e(e){e.forEach(t=>{if(t.oscData&&(this.callbacks.onRawOSC&&this.callbacks.onRawOSC({oscData:t.oscData,sequence:t.sequence}),this.callbacks.onParsedOSC))try{let s={metadata:!1,unpackSingleArgs:!1},r=D.readPacket(t.oscData,s);this.callbacks.onParsedOSC(r)}catch(s){console.error("[ScsynthOSC] Failed to decode OSC message:",s,t)}})}send(e,t={}){if(!this.initialized){console.error("[ScsynthOSC] Not initialized");return}let{sessionId:s=0,runTag:r="",audioTimeS:n=null,currentTimeS:a=null}=t;this.workers.oscOut.postMessage({type:"send",oscData:e,sessionId:s,runTag:r,audioTimeS:n,currentTimeS:a})}sendImmediate(e){if(!this.initialized){console.error("[ScsynthOSC] Not initialized");return}this.workers.oscOut.postMessage({type:"sendImmediate",oscData:e})}cancelSessionTag(e,t){this.initialized&&this.workers.oscOut.postMessage({type:"cancelSessionTag",sessionId:e,runTag:t})}cancelSession(e){this.initialized&&this.workers.oscOut.postMessage({type:"cancelSession",sessionId:e})}cancelTag(e){this.initialized&&this.workers.oscOut.postMessage({type:"cancelTag",runTag:e})}cancelAll(){this.initialized&&this.workers.oscOut.postMessage({type:"cancelAll"})}clearDebug(){this.initialized&&this.mode==="sab"&&this.workers.debug&&this.workers.debug.postMessage({type:"clear"})}onRawOSC(e){this.callbacks.onRawOSC=e}onParsedOSC(e){this.callbacks.onParsedOSC=e}onDebugMessage(e){this.callbacks.onDebugMessage=e}onError(e){this.callbacks.onError=e}onInitialized(e){this.callbacks.onInitialized=e}terminate(){this.workers.oscOut&&(this.workers.oscOut.postMessage({type:"stop"}),this.workers.oscOut.terminate()),this.workers.oscIn&&(this.workers.oscIn.postMessage({type:"stop"}),this.workers.oscIn.terminate()),this.workers.debug&&(this.workers.debug.postMessage({type:"stop"}),this.workers.debug.terminate()),this.workers={oscOut:null,oscIn:null,debug:null},this.workletPort=null,this.initialized=!1}};var Me={5120:"i8",5121:"u8",5122:"i16",5123:"u16",5124:"i32",5125:"u32",5126:"f32"};var ee={u8:1,u8c:1,i8:1,u16:2,i16:2,u32:4,i32:4,i64:8,u64:8,f32:4,f64:8};var Ue={f32:Float32Array,f64:Float64Array},Ce={i8:Int8Array,i16:Int16Array,i32:Int32Array},ve={u8:Uint8Array,u8c:Uint8ClampedArray,u16:Uint16Array,u32:Uint32Array},Ie={i64:BigInt64Array,u64:BigUint64Array},ke={...Ue,...Ce,...ve},Pe=i=>{let e=Me[i];return e!==void 0?e:i};function te(i,...e){let t=Ie[i];return new(t||ke[Pe(i)])(...e)}var U=(i,e)=>(e--,i+e&~e);var se=i=>typeof i=="number";var I=(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 xe=I(()=>"Assertion failed"),V=(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 xe(typeof e=="function"?e():e)}:()=>{};var Fe=I(()=>"illegal argument(s)"),re=i=>{throw new Fe(i)};var ie=0,ne=1,oe=2,ae=3,ce=4,R=5,le=6,W=1,H=2,ue=7*4,G=0,q=1,T=2*4,v=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?U(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,ue/4),!e.skipInitialization){let t=e.align||8;V(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&&re(`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*ee[e]);return s?te(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=U(e+T,this.align),s=this.end,r=this.top,n=this._free,a=0;for(;n;){let c=this.blockSize(n),l=n+c>=r;if(l||c>=t)return this.mallocTop(n,a,c,t,l);a=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,C(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 a=s-r;a>=this.minSplit&&this.splitBlock(e,r,a)}return C(e)}realloc(e,t){if(t<=0)return 0;let s=Z(e),r=0,n=this._used,a=0;for(;n;){if(n===s){[r,a]=this.reallocBlock(n,t);break}n=this.blockNext(n)}return r&&r!==s&&this.u8.copyWithin(C(r),C(s),a),C(r)}reallocBlock(e,t){let s=this.blockSize(e),r=e+s,n=r>=this.top,a=U(t+T,this.align);if(a<=s){if(this.doSplit){let c=s-a;c>=this.minSplit?this.splitBlock(e,a,c):n&&(this.top=e+a)}else n&&(this.top=e+a);return[e,r]}return n&&e+a<this.end?(this.top=e+this.setBlockSize(e,a),[e,r]):(this.free(e),[Z(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(se(e))t=e;else{if(e.buffer!==this.buf)return!1;t=e.byteOffset}t=Z(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[ce]}set align(e){this.state[ce]=e}get end(){return this.state[ae]}set end(e){this.state[ae]=e}get top(){return this.state[oe]}set top(e){this.state[oe]=e}get _free(){return this.state[ie]}set _free(e){this.state[ie]=e}get _used(){return this.state[ne]}set _used(e){this.state[ne]=e}get doCompact(){return!!(this.state[R]&W)}set doCompact(e){e?this.state[R]|=1<<W-1:this.state[R]&=~W}get doSplit(){return!!(this.state[R]&H)}set doSplit(e){e?this.state[R]|=1<<H-1:this.state[R]&=~H}get minSplit(){return this.state[le]}set minSplit(e){V(e>T,`illegal min split threshold: ${e}, require at least ${T+1}`),this.state[le]=e}blockSize(e){return this.u32[(e>>2)+G]}setBlockSize(e,t){return this.u32[(e>>2)+G]=t,t}blockNext(e){return this.u32[(e>>2)+q]}setBlockNext(e,t){this.u32[(e>>2)+q]=t}initBlock(e,t,s){let r=e>>>2;return this.u32[r+G]=t,this.u32[r+q]=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 U(this.start+ue+T,e)-T}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 a=r-e+this.blockSize(r);this.setBlockSize(e,a);let c=this.blockNext(r),l=this.blockNext(e);for(;l&&l!==c;){let u=this.blockNext(l);this.setBlockNext(l,0),l=u}this.setBlockNext(e,c),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)}},C=i=>i>0?i+T:0,Z=i=>i>0?i-T:0;var he=8,k=class{#s;#i;#h;#n;#f;#e;#a;#r;#o;#d;#S;#l;constructor(e){let{mode:t="sab",audioContext:s,sharedBuffer:r,bufferPoolConfig:n,sampleBaseURL:a,maxBuffers:c=1024,assetLoader:l=null,workletPort:u=null}=e;if(this.#s=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(c)||c<=0)throw new Error("maxBuffers must be a positive integer");if(this.#n=s,this.#f=r,this.#i=a,this.#h=l,this.#l=u,t==="sab")this.#e=new v({buf:r,start:n.start,size:n.size,align:he}),this.#a=n.size,this.#r=n.start;else{let g=new ArrayBuffer(n.start+n.size);this.#e=new v({buf:g,start:n.start,size:n.size,align:he}),this.#a=n.size,this.#r=n.start}this.#o=new Map,this.#d=new Map,this.#S=new Map,this.GUARD_BEFORE=3,this.GUARD_AFTER=1,this.MAX_BUFFERS=c;let f=(n.size/(1024*1024)).toFixed(0),h=(n.start/(1024*1024)).toFixed(0)}setWorkletPort(e){if(this.#s==="postMessage"){if(!e)throw new Error("BufferManager.setWorkletPort() requires a valid port");this.#l=e}}#p(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.#i)throw new Error(`sampleBaseURL not configured. Please set it in SuperSonic constructor options.
1
+ var o={},o=o||{};(function(){"use strict";o.SECS_70YRS=2208988800,o.TWO_32=4294967296,o.defaults={metadata:!1,unpackSingleArgs:!0},o.isCommonJS=!!(typeof module<"u"&&module.exports),o.isNode=o.isCommonJS&&typeof window>"u",o.isElectron=!!(typeof process<"u"&&process.versions&&process.versions.electron),o.isBufferEnv=o.isNode||o.isElectron,o.isArray=function(i){return i&&Object.prototype.toString.call(i)==="[object Array]"},o.isTypedArrayView=function(i){return i.buffer&&i.buffer instanceof ArrayBuffer},o.isBuffer=function(i){return o.isBufferEnv&&i instanceof Buffer},o.Long=typeof Long<"u"?Long:void 0,o.TextDecoder=typeof TextDecoder<"u"?new TextDecoder("utf-8"):typeof util<"u"&&typeof(util.TextDecoder!=="undefined")?new util.TextDecoder("utf-8"):void 0,o.TextEncoder=typeof TextEncoder<"u"?new TextEncoder("utf-8"):typeof util<"u"&&typeof(util.TextEncoder!=="undefined")?new util.TextEncoder("utf-8"):void 0,o.dataView=function(i,e,t){return i.buffer?new DataView(i.buffer,e,t):i instanceof ArrayBuffer?new DataView(i,e,t):new DataView(new Uint8Array(i),e,t)},o.byteArray=function(i){if(i instanceof Uint8Array)return i;var e=i.buffer?i.buffer:i;if(!(e instanceof ArrayBuffer)&&(typeof e.length>"u"||typeof e=="string"))throw new Error("Can't wrap a non-array-like object as Uint8Array. Object was: "+JSON.stringify(i,null,2));return new Uint8Array(e)},o.nativeBuffer=function(i){return o.isBufferEnv?o.isBuffer(i)?i:Buffer.from(i.buffer?i:new Uint8Array(i)):o.isTypedArrayView(i)?i:new Uint8Array(i)},o.copyByteArray=function(i,e,t){if(o.isTypedArrayView(i)&&o.isTypedArrayView(e))e.set(i,t);else for(var s=t===void 0?0:t,r=Math.min(e.length-t,i.length),n=0,a=s;n<r;n++,a++)e[a]=i[n];return e},o.readString=function(i,e){for(var t=[],s=e.idx;s<i.byteLength;s++){var r=i.getUint8(s);if(r!==0)t.push(r);else{s++;break}}s=s+3&-4,e.idx=s;var n=o.isBufferEnv?o.readString.withBuffer:o.TextDecoder?o.readString.withTextDecoder:o.readString.raw;return n(t)},o.readString.raw=function(i){for(var e="",t=1e4,s=0;s<i.length;s+=t)e+=String.fromCharCode.apply(null,i.slice(s,s+t));return e},o.readString.withTextDecoder=function(i){var e=new Int8Array(i);return o.TextDecoder.decode(e)},o.readString.withBuffer=function(i){return Buffer.from(i).toString("utf-8")},o.writeString=function(i){var e=o.isBufferEnv?o.writeString.withBuffer:o.TextEncoder?o.writeString.withTextEncoder:null,t=i+"\0",s;e&&(s=e(t));for(var r=e?s.length:t.length,n=r+3&-4,a=new Uint8Array(n),c=0;c<r-1;c++){var l=e?s[c]:t.charCodeAt(c);a[c]=l}return a},o.writeString.withTextEncoder=function(i){return o.TextEncoder.encode(i)},o.writeString.withBuffer=function(i){return Buffer.from(i)},o.readPrimitive=function(i,e,t,s){var r=i[e](s.idx,!1);return s.idx+=t,r},o.writePrimitive=function(i,e,t,s,r){r=r===void 0?0:r;var n;return e?n=new Uint8Array(e.buffer):(n=new Uint8Array(s),e=new DataView(n.buffer)),e[t](r,i,!1),n},o.readInt32=function(i,e){return o.readPrimitive(i,"getInt32",4,e)},o.writeInt32=function(i,e,t){return o.writePrimitive(i,e,"setInt32",4,t)},o.readInt64=function(i,e){var t=o.readPrimitive(i,"getInt32",4,e),s=o.readPrimitive(i,"getInt32",4,e);return o.Long?new o.Long(s,t):{high:t,low:s,unsigned:!1}},o.writeInt64=function(i,e,t){var s=new Uint8Array(8);return s.set(o.writePrimitive(i.high,e,"setInt32",4,t),0),s.set(o.writePrimitive(i.low,e,"setInt32",4,t+4),4),s},o.readFloat32=function(i,e){return o.readPrimitive(i,"getFloat32",4,e)},o.writeFloat32=function(i,e,t){return o.writePrimitive(i,e,"setFloat32",4,t)},o.readFloat64=function(i,e){return o.readPrimitive(i,"getFloat64",8,e)},o.writeFloat64=function(i,e,t){return o.writePrimitive(i,e,"setFloat64",8,t)},o.readChar32=function(i,e){var t=o.readPrimitive(i,"getUint32",4,e);return String.fromCharCode(t)},o.writeChar32=function(i,e,t){var s=i.charCodeAt(0);if(!(s===void 0||s<-1))return o.writePrimitive(s,e,"setUint32",4,t)},o.readBlob=function(i,e){var t=o.readInt32(i,e),s=t+3&-4,r=new Uint8Array(i.buffer,e.idx,t);return e.idx+=s,r},o.writeBlob=function(i){i=o.byteArray(i);var e=i.byteLength,t=e+3&-4,s=4,r=t+s,n=new Uint8Array(r),a=new DataView(n.buffer);return o.writeInt32(e,a),n.set(i,s),n},o.readMIDIBytes=function(i,e){var t=new Uint8Array(i.buffer,e.idx,4);return e.idx+=4,t},o.writeMIDIBytes=function(i){i=o.byteArray(i);var e=new Uint8Array(4);return e.set(i),e},o.readColor=function(i,e){var t=new Uint8Array(i.buffer,e.idx,4),s=t[3]/255;return e.idx+=4,{r:t[0],g:t[1],b:t[2],a:s}},o.writeColor=function(i){var e=Math.round(i.a*255),t=new Uint8Array([i.r,i.g,i.b,e]);return t},o.readTrue=function(){return!0},o.readFalse=function(){return!1},o.readNull=function(){return null},o.readImpulse=function(){return 1},o.readTimeTag=function(i,e){var t=o.readPrimitive(i,"getUint32",4,e),s=o.readPrimitive(i,"getUint32",4,e),r=t===0&&s===1?Date.now():o.ntpToJSTime(t,s);return{raw:[t,s],native:r}},o.writeTimeTag=function(i){var e=i.raw?i.raw:o.jsToNTPTime(i.native),t=new Uint8Array(8),s=new DataView(t.buffer);return o.writeInt32(e[0],s,0),o.writeInt32(e[1],s,4),t},o.timeTag=function(i,e){i=i||0,e=e||Date.now();var t=e/1e3,s=Math.floor(t),r=t-s,n=Math.floor(i),a=i-n,c=r+a;if(c>1){var l=Math.floor(c),u=c-l;n+=l,c=u}var f=s+n+o.SECS_70YRS,h=Math.round(o.TWO_32*c);return{raw:[f,h]}},o.ntpToJSTime=function(i,e){var t=i-o.SECS_70YRS,s=e/o.TWO_32,r=(t+s)*1e3;return r},o.jsToNTPTime=function(i){var e=i/1e3,t=Math.floor(e),s=e-t,r=t+o.SECS_70YRS,n=Math.round(o.TWO_32*s);return[r,n]},o.readArguments=function(i,e,t){var s=o.readString(i,t);if(s.indexOf(",")!==0)throw new Error("A malformed type tag string was found while reading the arguments of an OSC message. String was: "+s," at offset: "+t.idx);var r=s.substring(1).split(""),n=[];return o.readArgumentsIntoArray(n,r,s,i,e,t),n},o.readArgument=function(i,e,t,s,r){var n=o.argumentTypes[i];if(!n)throw new Error("'"+i+"' is not a valid OSC type tag. Type tag string was: "+e);var a=n.reader,c=o[a](t,r);return s.metadata&&(c={type:i,value:c}),c},o.readArgumentsIntoArray=function(i,e,t,s,r,n){for(var a=0;a<e.length;){var c=e[a],l;if(c==="["){var u=e.slice(a+1),f=u.indexOf("]");if(f<0)throw new Error("Invalid argument type tag: an open array type tag ('[') was found without a matching close array tag ('[]'). Type tag was: "+t);var h=u.slice(0,f);l=o.readArgumentsIntoArray([],h,t,s,r,n),a+=f+2}else l=o.readArgument(c,t,s,r,n),a++;i.push(l)}return i},o.writeArguments=function(i,e){var t=o.collectArguments(i,e);return o.joinParts(t)},o.joinParts=function(i){for(var e=new Uint8Array(i.byteLength),t=i.parts,s=0,r=0;r<t.length;r++){var n=t[r];o.copyByteArray(n,e,s),s+=n.length}return e},o.addDataPart=function(i,e){e.parts.push(i),e.byteLength+=i.length},o.writeArrayArguments=function(i,e){for(var t="[",s=0;s<i.length;s++){var r=i[s];t+=o.writeArgument(r,e)}return t+="]",t},o.writeArgument=function(i,e){if(o.isArray(i))return o.writeArrayArguments(i,e);var t=i.type,s=o.argumentTypes[t].writer;if(s){var r=o[s](i.value);o.addDataPart(r,e)}return i.type},o.collectArguments=function(i,e,t){o.isArray(i)||(i=typeof i>"u"?[]:[i]),t=t||{byteLength:0,parts:[]},e.metadata||(i=o.annotateArguments(i));for(var s=",",r=t.parts.length,n=0;n<i.length;n++){var a=i[n];s+=o.writeArgument(a,t)}var c=o.writeString(s);return t.byteLength+=c.byteLength,t.parts.splice(r,0,c),t},o.readMessage=function(i,e,t){e=e||o.defaults;var s=o.dataView(i,i.byteOffset,i.byteLength);t=t||{idx:0};var r=o.readString(s,t);return o.readMessageContents(r,s,e,t)},o.readMessageContents=function(i,e,t,s){if(i.indexOf("/")!==0)throw new Error("A malformed OSC address was found while reading an OSC message. String was: "+i);var r=o.readArguments(e,t,s);return{address:i,args:r.length===1&&t.unpackSingleArgs?r[0]:r}},o.collectMessageParts=function(i,e,t){return t=t||{byteLength:0,parts:[]},o.addDataPart(o.writeString(i.address),t),o.collectArguments(i.args,e,t)},o.writeMessage=function(i,e){if(e=e||o.defaults,!o.isValidMessage(i))throw new Error("An OSC message must contain a valid address. Message was: "+JSON.stringify(i,null,2));var t=o.collectMessageParts(i,e);return o.joinParts(t)},o.isValidMessage=function(i){return i.address&&i.address.indexOf("/")===0},o.readBundle=function(i,e,t){return o.readPacket(i,e,t)},o.collectBundlePackets=function(i,e,t){t=t||{byteLength:0,parts:[]},o.addDataPart(o.writeString("#bundle"),t),o.addDataPart(o.writeTimeTag(i.timeTag),t);for(var s=0;s<i.packets.length;s++){var r=i.packets[s],n=r.address?o.collectMessageParts:o.collectBundlePackets,a=n(r,e);t.byteLength+=a.byteLength,o.addDataPart(o.writeInt32(a.byteLength),t),t.parts=t.parts.concat(a.parts)}return t},o.writeBundle=function(i,e){if(!o.isValidBundle(i))throw new Error("An OSC bundle must contain 'timeTag' and 'packets' properties. Bundle was: "+JSON.stringify(i,null,2));e=e||o.defaults;var t=o.collectBundlePackets(i,e);return o.joinParts(t)},o.isValidBundle=function(i){return i.timeTag!==void 0&&i.packets!==void 0},o.readBundleContents=function(i,e,t,s){for(var r=o.readTimeTag(i,t),n=[];t.idx<s;){var a=o.readInt32(i,t),c=t.idx+a,l=o.readPacket(i,e,t,c);n.push(l)}return{timeTag:r,packets:n}},o.readPacket=function(i,e,t,s){var r=o.dataView(i,i.byteOffset,i.byteLength);s=s===void 0?r.byteLength:s,t=t||{idx:0};var n=o.readString(r,t),a=n[0];if(a==="#")return o.readBundleContents(r,e,t,s);if(a==="/")return o.readMessageContents(n,r,e,t);throw new Error("The header of an OSC packet didn't contain an OSC address or a #bundle string. Header was: "+n)},o.writePacket=function(i,e){if(o.isValidMessage(i))return o.writeMessage(i,e);if(o.isValidBundle(i))return o.writeBundle(i,e);throw new Error("The specified packet was not recognized as a valid OSC message or bundle. Packet was: "+JSON.stringify(i,null,2))},o.argumentTypes={i:{reader:"readInt32",writer:"writeInt32"},h:{reader:"readInt64",writer:"writeInt64"},f:{reader:"readFloat32",writer:"writeFloat32"},s:{reader:"readString",writer:"writeString"},S:{reader:"readString",writer:"writeString"},b:{reader:"readBlob",writer:"writeBlob"},t:{reader:"readTimeTag",writer:"writeTimeTag"},T:{reader:"readTrue"},F:{reader:"readFalse"},N:{reader:"readNull"},I:{reader:"readImpulse"},d:{reader:"readFloat64",writer:"writeFloat64"},c:{reader:"readChar32",writer:"writeChar32"},r:{reader:"readColor",writer:"writeColor"},m:{reader:"readMIDIBytes",writer:"writeMIDIBytes"}},o.inferTypeForArgument=function(i){var e=typeof i;switch(e){case"boolean":return i?"T":"F";case"string":return"s";case"number":return"f";case"undefined":return"N";case"object":if(i===null)return"N";if(i instanceof Uint8Array||i instanceof ArrayBuffer)return"b";if(typeof i.high=="number"&&typeof i.low=="number")return"h";break}throw new Error("Can't infer OSC argument type for value: "+JSON.stringify(i,null,2))},o.annotateArguments=function(i){for(var e=[],t=0;t<i.length;t++){var s=i[t],r;if(typeof s=="object"&&s.type&&s.value!==void 0)r=s;else if(o.isArray(s))r=o.annotateArguments(s);else{var n=o.inferTypeForArgument(s);r={type:n,value:s}}e.push(r)}return e}})();var O=function(){};O.prototype.on=function(){};O.prototype.emit=function(){};O.prototype.removeListener=function(){};(function(){"use strict";o.supportsSerial=!1,o.firePacketEvents=function(e,t,s,r){t.address?e.emit("message",t,s,r):o.fireBundleEvents(e,t,s,r)},o.fireBundleEvents=function(e,t,s,r){e.emit("bundle",t,s,r);for(var n=0;n<t.packets.length;n++){var a=t.packets[n];o.firePacketEvents(e,a,t.timeTag,r)}},o.fireClosedPortSendError=function(e,t){t=t||"Can't send packets on a closed osc.Port object. Please open (or reopen) this Port by calling open().",e.emit("error",t)},o.Port=function(e){this.options=e||{},this.on("data",this.decodeOSC.bind(this))};var i=o.Port.prototype=Object.create(O.prototype);i.constructor=o.Port,i.send=function(e){var t=Array.prototype.slice.call(arguments),s=this.encodeOSC(e),r=o.nativeBuffer(s);t[0]=r,this.sendRaw.apply(this,t)},i.encodeOSC=function(e){e=e.buffer?e.buffer:e;var t;try{t=o.writePacket(e,this.options)}catch(s){this.emit("error",s)}return t},i.decodeOSC=function(e,t){e=o.byteArray(e),this.emit("raw",e,t);try{var s=o.readPacket(e,this.options);this.emit("osc",s,t),o.firePacketEvents(this,s,void 0,t)}catch(r){this.emit("error",r)}},o.SLIPPort=function(e){var t=this,s=this.options=e||{};s.useSLIP=s.useSLIP===void 0?!0:s.useSLIP,this.decoder=new slip.Decoder({onMessage:this.decodeOSC.bind(this),onError:function(n){t.emit("error",n)}});var r=s.useSLIP?this.decodeSLIPData:this.decodeOSC;this.on("data",r.bind(this))},i=o.SLIPPort.prototype=Object.create(o.Port.prototype),i.constructor=o.SLIPPort,i.encodeOSC=function(e){e=e.buffer?e.buffer:e;var t;try{var s=o.writePacket(e,this.options);t=slip.encode(s)}catch(r){this.emit("error",r)}return t},i.decodeSLIPData=function(e,t){this.decoder.decode(e,t)},o.relay=function(e,t,s,r,n,a){s=s||"message",r=r||"send",n=n||function(){},a=a?[null].concat(a):[];var c=function(l){a[0]=l,l=n(l),t[r].apply(t,a)};return e.on(s,c),{eventName:s,listener:c}},o.relayPorts=function(e,t,s){var r=s.raw?"raw":"osc",n=s.raw?"sendRaw":"send";return o.relay(e,t,r,n,s.transform)},o.stopRelaying=function(e,t){e.removeListener(t.eventName,t.listener)},o.Relay=function(e,t,s){var r=this.options=s||{};r.raw=!1,this.port1=e,this.port2=t,this.listen()},i=o.Relay.prototype=Object.create(O.prototype),i.constructor=o.Relay,i.open=function(){this.port1.open(),this.port2.open()},i.listen=function(){this.port1Spec&&this.port2Spec&&this.close(),this.port1Spec=o.relayPorts(this.port1,this.port2,this.options),this.port2Spec=o.relayPorts(this.port2,this.port1,this.options);var e=this.close.bind(this);this.port1.on("close",e),this.port2.on("close",e)},i.close=function(){o.stopRelaying(this.port1,this.port1Spec),o.stopRelaying(this.port2,this.port2Spec),this.emit("close",this.port1,this.port2)}})();(function(){"use strict";o.WebSocket=typeof WebSocket<"u"?WebSocket:void 0,o.WebSocketPort=function(e){o.Port.call(this,e),this.on("open",this.listen.bind(this)),this.socket=e.socket,this.socket&&(this.socket.readyState===1?(o.WebSocketPort.setupSocketForBinary(this.socket),this.emit("open",this.socket)):this.open())};var i=o.WebSocketPort.prototype=Object.create(o.Port.prototype);i.constructor=o.WebSocketPort,i.open=function(){(!this.socket||this.socket.readyState>1)&&(this.socket=new o.WebSocket(this.options.url)),o.WebSocketPort.setupSocketForBinary(this.socket);var e=this;this.socket.onopen=function(){e.emit("open",e.socket)},this.socket.onerror=function(t){e.emit("error",t)}},i.listen=function(){var e=this;this.socket.onmessage=function(t){e.emit("data",t.data,t)},this.socket.onclose=function(t){e.emit("close",t)},e.emit("ready")},i.sendRaw=function(e){if(!this.socket||this.socket.readyState!==1){o.fireClosedPortSendError(this);return}this.socket.send(e)},i.close=function(e,t){this.socket.close(e,t)},o.WebSocketPort.setupSocketForBinary=function(e){e.binaryType=o.isNode?"nodebuffer":"arraybuffer"}})();var D=o,{readPacket:ct,writePacket:lt,readMessage:ut,writeMessage:ht,readBundle:ft,writeBundle:dt}=o;var $=new Map;function K(i){try{return new URL(i,window.location.href).origin!==window.location.origin}catch{return!1}}async function X(i){if($.has(i))return $.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 $.set(i,r),r}async function B(i,e={}){let t=i;return K(i)&&(t=await X(i)),new Worker(t,e)}async function J(i,e){let t=e;K(e)&&(t=await X(e)),await i.addModule(t)}var M=class{constructor(e=null){this.workerBaseURL=e,this.mode="sab",this.workletPort=null,this.workers={oscOut:null,oscIn:null,debug:null},this.callbacks={onRawOSC:null,onParsedOSC:null,onDebugMessage:null,onError:null,onInitialized:null},this.initialized=!1,this.sharedBuffer=null,this.ringBufferBase=null,this.bufferConstants=null,this.cachedPreschedulerMetrics=null}getPreschedulerMetrics(){return this.cachedPreschedulerMetrics}async init(e={}){if(this.initialized){console.warn("[ScsynthOSC] Already initialized");return}if(this.mode=e.mode||"sab",this.preschedulerCapacity=e.preschedulerCapacity||65536,this.mode==="sab")await this.#s(e);else if(this.mode==="postMessage")await this.#i(e);else throw new Error(`Unknown mode: ${this.mode}`);this.initialized=!0,this.callbacks.onInitialized&&this.callbacks.onInitialized()}async#s(e){if(this.sharedBuffer=e.sharedBuffer,this.ringBufferBase=e.ringBufferBase,this.bufferConstants=e.bufferConstants,!this.sharedBuffer||!this.bufferConstants)throw new Error("SAB mode requires sharedBuffer and bufferConstants");try{let[t,s,r]=await Promise.all([B(this.workerBaseURL+"osc_out_prescheduler_worker.js",{type:"module"}),B(this.workerBaseURL+"osc_in_worker.js",{type:"module"}),B(this.workerBaseURL+"debug_worker.js",{type:"module"})]);this.workers.oscOut=t,this.workers.oscIn=s,this.workers.debug=r,this.#n();let n=[this.#h(this.workers.oscOut,"OSC SCHEDULER+WRITER",{mode:"sab",maxPendingMessages:this.preschedulerCapacity}),this.#h(this.workers.oscIn,"OSC IN"),this.#h(this.workers.debug,"DEBUG")];await Promise.all(n),this.workers.oscIn.postMessage({type:"start"}),this.workers.debug.postMessage({type:"start"})}catch(t){throw console.error("[ScsynthOSC] SAB mode initialization failed:",t),this.callbacks.onError&&this.callbacks.onError(t),t}}async#i(e){if(this.workletPort=e.workletPort,!this.workletPort)throw new Error("postMessage mode requires workletPort");try{let[t,s]=await Promise.all([B(this.workerBaseURL+"osc_out_prescheduler_worker.js",{type:"module"}),B(this.workerBaseURL+"debug_worker.js",{type:"module"})]);this.workers.oscOut=t,this.workers.debug=s,this.#f();let r=[this.#h(this.workers.oscOut,"OSC SCHEDULER",{mode:"postMessage",maxPendingMessages:this.preschedulerCapacity}),this.#h(this.workers.debug,"DEBUG",{mode:"postMessage"})];if(await Promise.all(r),e.earlyDebugMessages&&e.earlyDebugMessages.length>0)for(let n of e.earlyDebugMessages)this.handleDebugRaw(n)}catch(t){throw console.error("[ScsynthOSC] postMessage mode initialization failed:",t),this.callbacks.onError&&this.callbacks.onError(t),t}}handleDebugRaw(e){this.workers.debug&&e.messages&&this.workers.debug.postMessage({type:"debugRaw",messages:e.messages})}#h(e,t,s={}){return new Promise((r,n)=>{let a=setTimeout(()=>{n(new Error(`${t} worker initialization timeout`))},5e3),c=u=>{u.data.type==="initialized"&&(clearTimeout(a),e.removeEventListener("message",c),r())};e.addEventListener("message",c);let l={type:"init",...s};this.mode==="sab"&&this.sharedBuffer&&(l.sharedBuffer=this.sharedBuffer,l.ringBufferBase=this.ringBufferBase,l.bufferConstants=this.bufferConstants),e.postMessage(l)})}#n(){this.workers.oscIn.onmessage=e=>{let t=e.data;switch(t.type){case"messages":this.#e(t.messages);break;case"error":console.error("[ScsynthOSC] OSC IN error:",t.error),this.callbacks.onError&&this.callbacks.onError(t.error,"oscIn");break}},this.workers.debug.onmessage=e=>{let t=e.data;switch(t.type){case"debug":this.callbacks.onDebugMessage&&t.messages.forEach(s=>{this.callbacks.onDebugMessage(s)});break;case"error":console.error("[ScsynthOSC] DEBUG error:",t.error),this.callbacks.onError&&this.callbacks.onError(t.error,"debug");break}},this.workers.oscOut.onmessage=e=>{let t=e.data;t.type==="error"&&(console.error("[ScsynthOSC] OSC OUT error:",t.error),this.callbacks.onError&&this.callbacks.onError(t.error,"oscOut"))}}#f(){this.workers.oscOut.onmessage=e=>{let t=e.data;switch(t.type){case"dispatch":this.workletPort&&this.workletPort.postMessage({type:"osc",oscData:t.oscData,timestamp:t.timestamp});break;case"preschedulerMetrics":this.cachedPreschedulerMetrics=t.metrics;break;case"error":console.error("[ScsynthOSC] OSC OUT error:",t.error),this.callbacks.onError&&this.callbacks.onError(t.error,"oscOut");break}},this.workers.debug.onmessage=e=>{let t=e.data;switch(t.type){case"debug":this.callbacks.onDebugMessage&&t.messages.forEach(s=>{this.callbacks.onDebugMessage(s)});break;case"error":console.error("[ScsynthOSC] DEBUG error:",t.error),this.callbacks.onError&&this.callbacks.onError(t.error,"debug");break}},this.workletPort.addEventListener("message",e=>{let t=e.data;switch(t.type){case"oscReply":t.oscData&&this.#e([{oscData:t.oscData}]);break;case"oscReplies":t.messages&&this.#e(t.messages);break}})}#e(e){e.forEach(t=>{if(t.oscData&&(this.callbacks.onRawOSC&&this.callbacks.onRawOSC({oscData:t.oscData,sequence:t.sequence}),this.callbacks.onParsedOSC))try{let s={metadata:!1,unpackSingleArgs:!1},r=D.readPacket(t.oscData,s);this.callbacks.onParsedOSC(r)}catch(s){console.error("[ScsynthOSC] Failed to decode OSC message:",s,t)}})}send(e,t={}){if(!this.initialized){console.error("[ScsynthOSC] Not initialized");return}let{sessionId:s=0,runTag:r="",audioTimeS:n=null,currentTimeS:a=null}=t;this.workers.oscOut.postMessage({type:"send",oscData:e,sessionId:s,runTag:r,audioTimeS:n,currentTimeS:a})}sendImmediate(e){if(!this.initialized){console.error("[ScsynthOSC] Not initialized");return}this.workers.oscOut.postMessage({type:"sendImmediate",oscData:e})}cancelSessionTag(e,t){this.initialized&&this.workers.oscOut.postMessage({type:"cancelSessionTag",sessionId:e,runTag:t})}cancelSession(e){this.initialized&&this.workers.oscOut.postMessage({type:"cancelSession",sessionId:e})}cancelTag(e){this.initialized&&this.workers.oscOut.postMessage({type:"cancelTag",runTag:e})}cancelAll(){this.initialized&&this.workers.oscOut.postMessage({type:"cancelAll"})}clearDebug(){this.initialized&&this.mode==="sab"&&this.workers.debug&&this.workers.debug.postMessage({type:"clear"})}onRawOSC(e){this.callbacks.onRawOSC=e}onParsedOSC(e){this.callbacks.onParsedOSC=e}onDebugMessage(e){this.callbacks.onDebugMessage=e}onError(e){this.callbacks.onError=e}onInitialized(e){this.callbacks.onInitialized=e}terminate(){this.workers.oscOut&&(this.workers.oscOut.postMessage({type:"stop"}),this.workers.oscOut.terminate()),this.workers.oscIn&&(this.workers.oscIn.postMessage({type:"stop"}),this.workers.oscIn.terminate()),this.workers.debug&&(this.workers.debug.postMessage({type:"stop"}),this.workers.debug.terminate()),this.workers={oscOut:null,oscIn:null,debug:null},this.workletPort=null,this.initialized=!1}};var Me={5120:"i8",5121:"u8",5122:"i16",5123:"u16",5124:"i32",5125:"u32",5126:"f32"};var ee={u8:1,u8c:1,i8:1,u16:2,i16:2,u32:4,i32:4,i64:8,u64:8,f32:4,f64:8};var Ue={f32:Float32Array,f64:Float64Array},Ce={i8:Int8Array,i16:Int16Array,i32:Int32Array},ve={u8:Uint8Array,u8c:Uint8ClampedArray,u16:Uint16Array,u32:Uint32Array},Ie={i64:BigInt64Array,u64:BigUint64Array},ke={...Ue,...Ce,...ve},Pe=i=>{let e=Me[i];return e!==void 0?e:i};function te(i,...e){let t=Ie[i];return new(t||ke[Pe(i)])(...e)}var U=(i,e)=>(e--,i+e&~e);var se=i=>typeof i=="number";var I=(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 xe=I(()=>"Assertion failed"),V=(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 xe(typeof e=="function"?e():e)}:()=>{};var Fe=I(()=>"illegal argument(s)"),re=i=>{throw new Fe(i)};var ie=0,ne=1,oe=2,ae=3,ce=4,R=5,le=6,W=1,H=2,ue=7*4,G=0,q=1,T=2*4,v=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?U(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,ue/4),!e.skipInitialization){let t=e.align||8;V(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&&re(`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*ee[e]);return s?te(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=U(e+T,this.align),s=this.end,r=this.top,n=this._free,a=0;for(;n;){let c=this.blockSize(n),l=n+c>=r;if(l||c>=t)return this.mallocTop(n,a,c,t,l);a=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,C(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 a=s-r;a>=this.minSplit&&this.splitBlock(e,r,a)}return C(e)}realloc(e,t){if(t<=0)return 0;let s=Z(e),r=0,n=this._used,a=0;for(;n;){if(n===s){[r,a]=this.reallocBlock(n,t);break}n=this.blockNext(n)}return r&&r!==s&&this.u8.copyWithin(C(r),C(s),a),C(r)}reallocBlock(e,t){let s=this.blockSize(e),r=e+s,n=r>=this.top,a=U(t+T,this.align);if(a<=s){if(this.doSplit){let c=s-a;c>=this.minSplit?this.splitBlock(e,a,c):n&&(this.top=e+a)}else n&&(this.top=e+a);return[e,r]}return n&&e+a<this.end?(this.top=e+this.setBlockSize(e,a),[e,r]):(this.free(e),[Z(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(se(e))t=e;else{if(e.buffer!==this.buf)return!1;t=e.byteOffset}t=Z(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[ce]}set align(e){this.state[ce]=e}get end(){return this.state[ae]}set end(e){this.state[ae]=e}get top(){return this.state[oe]}set top(e){this.state[oe]=e}get _free(){return this.state[ie]}set _free(e){this.state[ie]=e}get _used(){return this.state[ne]}set _used(e){this.state[ne]=e}get doCompact(){return!!(this.state[R]&W)}set doCompact(e){e?this.state[R]|=1<<W-1:this.state[R]&=~W}get doSplit(){return!!(this.state[R]&H)}set doSplit(e){e?this.state[R]|=1<<H-1:this.state[R]&=~H}get minSplit(){return this.state[le]}set minSplit(e){V(e>T,`illegal min split threshold: ${e}, require at least ${T+1}`),this.state[le]=e}blockSize(e){return this.u32[(e>>2)+G]}setBlockSize(e,t){return this.u32[(e>>2)+G]=t,t}blockNext(e){return this.u32[(e>>2)+q]}setBlockNext(e,t){this.u32[(e>>2)+q]=t}initBlock(e,t,s){let r=e>>>2;return this.u32[r+G]=t,this.u32[r+q]=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 U(this.start+ue+T,e)-T}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 a=r-e+this.blockSize(r);this.setBlockSize(e,a);let c=this.blockNext(r),l=this.blockNext(e);for(;l&&l!==c;){let u=this.blockNext(l);this.setBlockNext(l,0),l=u}this.setBlockNext(e,c),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)}},C=i=>i>0?i+T:0,Z=i=>i>0?i-T:0;var he=8,k=class{#s;#i;#h;#n;#f;#e;#a;#r;#o;#d;#g;#l;constructor(e){let{mode:t="sab",audioContext:s,sharedBuffer:r,bufferPoolConfig:n,sampleBaseURL:a,maxBuffers:c=1024,assetLoader:l=null,workletPort:u=null}=e;if(this.#s=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(c)||c<=0)throw new Error("maxBuffers must be a positive integer");if(this.#n=s,this.#f=r,this.#i=a,this.#h=l,this.#l=u,t==="sab")this.#e=new v({buf:r,start:n.start,size:n.size,align:he}),this.#a=n.size,this.#r=n.start;else{let w=new ArrayBuffer(n.start+n.size);this.#e=new v({buf:w,start:n.start,size:n.size,align:he}),this.#a=n.size,this.#r=n.start}this.#o=new Map,this.#d=new Map,this.#g=new Map,this.GUARD_BEFORE=3,this.GUARD_AFTER=1,this.MAX_BUFFERS=c;let f=(n.size/(1024*1024)).toFixed(0),h=(n.start/(1024*1024)).toFixed(0)}setWorkletPort(e){if(this.#s==="postMessage"){if(!e)throw new Error("BufferManager.setWorkletPort() requires a valid port");this.#l=e}}#p(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.#i)throw new Error(`sampleBaseURL not configured. Please set it in SuperSonic constructor options.
2
2
  Example: new SuperSonic({ sampleBaseURL: "./dist/samples/" })
3
3
  Or use CDN: new SuperSonic({ sampleBaseURL: "https://unpkg.com/supersonic-scsynth-samples@latest/samples/" })
4
- Or install: npm install supersonic-scsynth-samples`);return this.#i+e}#g(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#E(e,t,s){let r=null,n=null,a=!1,c=await this.#A(e),l=!1;try{await this.#t(e);let{ptr:u,sizeBytes:f,numFrames:h,numChannels:g,sampleRate:p,source:m,...S}=await s();r=u;let{uuid:d,allocationComplete:w}=this.#m(e,t);n=d,this.#v(e,r,f,d,w,{numFrames:h,numChannels:g,sampleRate:p,source:m}),a=!0;let y=this.#C(e,d,w);return c(),l=!0,{ptr:r,uuid:d,allocationComplete:y,numFrames:h,numChannels:g,sampleRate:p,...S}}catch(u){throw a&&n?this.#T(e,n,!1):r&&this.#e.free(r),u}finally{l||c()}}async prepareFromBlob(e){let{bufnum:t,blob:s,startFrame:r=0,numFrames:n=0,channels:a=null}=e;if(this.#g(t),!s||!(s instanceof ArrayBuffer||ArrayBuffer.isView(s)))throw new Error("/b_allocFile requires audio data as ArrayBuffer or typed array");let c=s instanceof ArrayBuffer?s:s.buffer.slice(s.byteOffset,s.byteOffset+s.byteLength);return this.#E(t,3e4,async()=>{let l=await this.#n.decodeAudioData(c),u=Math.max(0,Math.floor(r||0)),f=l.length-u,h=n&&n>0?Math.min(Math.floor(n),f):f;if(h<=0)throw new Error(`No audio frames available for buffer ${t}`);let g=this.#y(a,l.numberOfChannels),p=g.length,m=h*p+(this.GUARD_BEFORE+this.GUARD_AFTER)*p,S=this.#b(m),d=new Float32Array(m),w=this.GUARD_BEFORE*p;for(let _=0;_<h;_++)for(let E=0;E<p;E++){let b=g[E],A=l.getChannelData(b);d[w+_*p+E]=A[u+_]}await this.#c(S,d);let y=d.length*4;return{ptr:S,sizeBytes:y,numFrames:h,numChannels:p,sampleRate:l.sampleRate}})}async prepareFromFile(e){let{bufnum:t,path:s,startFrame:r=0,numFrames:n=0,channels:a=null}=e;return this.#g(t),this.#E(t,6e4,async()=>{let c=this.#p(s),l=s.split("/").pop(),u=await this.#h.fetch(c,{type:"sample",name:l}),f=await this.#n.decodeAudioData(u),h=Math.max(0,Math.floor(r||0)),g=f.length-h,p=n&&n>0?Math.min(Math.floor(n),g):g;if(p<=0)throw new Error(`No audio frames available for buffer ${t} from ${s}`);let m=this.#y(a,f.numberOfChannels),S=m.length,d=p*S+(this.GUARD_BEFORE+this.GUARD_AFTER)*S,w=this.#b(d),y=new Float32Array(d),_=this.GUARD_BEFORE*S;for(let b=0;b<p;b++)for(let A=0;A<S;A++){let Oe=m[A],De=f.getChannelData(Oe);y[_+b*S+A]=De[h+b]}await this.#c(w,y);let E=y.length*4;return{ptr:w,sizeBytes:E,numFrames:p,numChannels:S,sampleRate:f.sampleRate,source:this.#s==="postMessage"?{type:"file",path:s,startFrame:r,numFrames:n,channels:a}:null}})}async prepareEmpty(e){let{bufnum:t,numFrames:s,numChannels:r=1,sampleRate:n=null}=e;if(this.#g(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 a=Math.floor(s),c=Math.floor(r);return this.#E(t,5e3,async()=>{let l=a*c+(this.GUARD_BEFORE+this.GUARD_AFTER)*c,u=this.#b(l),f=new Float32Array(l);await this.#c(u,f);let h=f.length*4;return{ptr:u,sizeBytes:h,numFrames:a,numChannels:c,sampleRate:n||this.#n.sampleRate}})}#y(e,t){return!e||e.length===0?Array.from({length:t},(s,r)=>r):(e.forEach(s=>{if(!Number.isInteger(s)||s<0||s>=t)throw new Error(`Channel ${s} is out of range (file has ${t} channels)`)}),e)}#b(e){let t=e*4,s=this.#e.malloc(t);if(s===0){let r=this.#e.stats(),n=((r.available||0)/(1024*1024)).toFixed(2),a=((r.total||0)/(1024*1024)).toFixed(2),c=(t/(1024*1024)).toFixed(2);throw new Error(`Buffer pool allocation failed: requested ${c}MB, available ${n}MB of ${a}MB total`)}return s}async#c(e,t){if(this.#s==="sab")new Float32Array(this.#f,e,t.length).set(t);else{let s=crypto.randomUUID(),r=new Promise((a,c)=>{let l=setTimeout(()=>{c(new Error("Buffer copy to WASM memory timed out"))},1e4),u=f=>{let h=f.data;h.type==="bufferCopied"&&h.copyId===s&&(this.#l.removeEventListener("message",u),clearTimeout(l),h.success?a():c(new Error(h.error||"Buffer copy failed")))};this.#l.addEventListener("message",u)}),n=t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength);this.#l.postMessage({type:"copyBufferData",copyId:s,ptr:e,data:n},[n]),await r}}#w(e,t,s){return new Promise((r,n)=>{let a=setTimeout(()=>{this.#d.delete(e),n(new Error(`Buffer ${t} allocation timeout (${s}ms)`))},s);this.#d.set(e,{resolve:r,reject:n,timeout:a})})}#m(e,t){let s=crypto.randomUUID(),r=this.#w(s,e,t);return{uuid:s,allocationComplete:r}}async#A(e){let t=this.#S.get(e)||Promise.resolve(),s,r=new Promise(n=>{s=n});return this.#S.set(e,t.then(()=>r)),await t,()=>{s&&(s(),s=null),this.#S.get(e)===r&&this.#S.delete(e)}}#v(e,t,s,r,n,a={}){let c=this.#o.get(e),l={ptr:t,size:s,numFrames:a.numFrames||0,numChannels:a.numChannels||1,sampleRate:a.sampleRate||48e3,pendingToken:r,pendingPromise:n,previousAllocation:c?{ptr:c.ptr,size:c.size}:null,source:a.source||null};return this.#o.set(e,l),l}async#t(e){let t=this.#o.get(e);if(t&&t.pendingToken&&t.pendingPromise)try{await t.pendingPromise}catch{}}#C(e,t,s){return!s||typeof s.then!="function"?(this.#T(e,t,!0),Promise.resolve()):s.then(r=>(this.#T(e,t,!0),r)).catch(r=>{throw this.#T(e,t,!1),r})}#T(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.#e.free(n.ptr);return}r.ptr&&this.#e.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.#e.free(s);return}if(typeof s=="number"&&s===r.ptr){this.#e.free(r.ptr),this.#o.delete(t);return}if(typeof s=="number"&&r.previousAllocation&&r.previousAllocation.ptr===s){this.#e.free(s),r.previousAllocation=null;return}this.#e.free(r.ptr),this.#o.delete(t)}handleBufferAllocated(e){let t=e[0],s=e[1],r=this.#d.get(t);r&&(clearTimeout(r.timeout),r.resolve({bufnum:s}),this.#d.delete(t))}allocate(e){let t=e*4,s=this.#e.malloc(t);if(s===0){let r=this.#e.stats(),n=((r.available||0)/(1024*1024)).toFixed(2),a=((r.total||0)/(1024*1024)).toFixed(2),c=(t/(1024*1024)).toFixed(2);console.error(`[BufferManager] Allocation failed: requested ${c}MB, available ${n}MB of ${a}MB total`)}return s}free(e){return this.#e.free(e)}getView(e,t){return new Float32Array(this.#f,e,t)}getStats(){return this.#e?this.#e.stats():{total:0,available:0,used:0,allocations: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});return e}updateAudioContext(e){if(!e)throw new Error("BufferManager.updateAudioContext requires audioContext");this.#n=e}getDiagnostics(){let e=this.#e.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.#a,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.#d.entries())clearTimeout(t.timeout),t.reject(new Error("BufferManager destroyed"));this.#d.clear();for(let[e,t]of this.#o.entries())t.ptr&&this.#e.free(t.ptr);this.#o.clear(),this.#S.clear()}};var P=class{#s;#i;#h;constructor(e={}){let{onLoadingEvent:t=null,maxRetries:s=3,baseDelay:r=1e3}=e;this.#s=t,this.#i=s,this.#h=r}async fetch(e,{type:t,name:s}){let r=this.#n(e),n=this.#f(e),a=await r;this.#s?.("loading:start",{type:t,name:s,...a!=null&&{size:a}});let l=await(await n).arrayBuffer();return this.#s?.("loading:complete",{type:t,name:s,size:l.byteLength}),l}async#n(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#f(e){let t;for(let s=0;s<=this.#i;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.#i){let n=this.#h*Math.pow(2,s);await this.#e(n)}}throw t}#e(e){return new Promise(t=>setTimeout(t,e))}};var x=class{#s;#i;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.#s=e,this.#i=t}async rewritePacket(e){if(e&&e.address){let{message:t,changed:s}=await this.#h(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#h(e){switch(e.address){case"/b_alloc":return{message:await this.#n(e),changed:!0};case"/b_allocRead":return{message:await this.#f(e),changed:!0};case"/b_allocReadChannel":return{message:await this.#e(e),changed:!0};case"/b_allocFile":return{message:await this.#a(e),changed:!0};default:return{message:e,changed:!1}}}async#n(e){let t=this.#E(e.args,0,"/b_alloc requires a buffer number"),s=this.#E(e.args,1,"/b_alloc requires a frame count"),r=2,n=1,a=this.#i();this.#w(this.#p(e.args,r))&&(n=Math.max(1,this.#y(e.args,r,1)),r++),this.#p(e.args,r)?.type==="b"&&r++,this.#w(this.#p(e.args,r))&&(a=this.#g(this.#p(e.args,r)));let c=await this.#s.prepareEmpty({bufnum:t,numFrames:s,numChannels:n,sampleRate:a});return this.#m(c.allocationComplete,`/b_alloc ${t}`),this.#r(t,c)}async#f(e){let t=this.#E(e.args,0,"/b_allocRead requires a buffer number"),s=this.#b(e.args,1,"/b_allocRead requires a file path"),r=this.#y(e.args,2,0),n=this.#y(e.args,3,0),a=await this.#s.prepareFromFile({bufnum:t,path:s,startFrame:r,numFrames:n});return this.#m(a.allocationComplete,`/b_allocRead ${t}`),this.#r(t,a)}async#e(e){let t=this.#E(e.args,0,"/b_allocReadChannel requires a buffer number"),s=this.#b(e.args,1,"/b_allocReadChannel requires a file path"),r=this.#y(e.args,2,0),n=this.#y(e.args,3,0),a=[];for(let l=4;l<(e.args?.length||0)&&this.#w(e.args[l]);l++)a.push(Math.floor(this.#g(e.args[l])));let c=await this.#s.prepareFromFile({bufnum:t,path:s,startFrame:r,numFrames:n,channels:a.length>0?a:null});return this.#m(c.allocationComplete,`/b_allocReadChannel ${t}`),this.#r(t,c)}async#a(e){let t=this.#E(e.args,0,"/b_allocFile requires a buffer number"),s=this.#c(e.args,1,"/b_allocFile requires audio file data as blob"),r=await this.#s.prepareFromBlob({bufnum:t,blob:s});return this.#m(r.allocationComplete,`/b_allocFile ${t}`),this.#r(t,r)}#r(e,t){return{address:"/b_allocPtr",args:[this.#d(e),this.#d(t.ptr),this.#d(t.numFrames),this.#d(t.numChannels),this.#S(t.sampleRate),this.#l(t.uuid)]}}#o(e){return e&&e.timeTag!==void 0&&Array.isArray(e.packets)}#d(e){return{type:"i",value:Math.floor(e)}}#S(e){return{type:"f",value:e}}#l(e){return{type:"s",value:String(e)}}#p(e,t){if(Array.isArray(e))return e[t]}#g(e){if(e!=null)return typeof e=="object"&&Object.prototype.hasOwnProperty.call(e,"value")?e.value:e}#E(e,t,s){let r=this.#g(this.#p(e,t));if(!Number.isFinite(r))throw new Error(s);return Math.floor(r)}#y(e,t,s=0){let r=this.#g(this.#p(e,t));return Number.isFinite(r)?Math.floor(r):s}#b(e,t,s){let r=this.#g(this.#p(e,t));if(typeof r!="string")throw new Error(s);return r}#c(e,t,s){let r=this.#p(e,t);if(!r||r.type!=="b")throw new Error(s);let n=this.#g(r);if(!(n instanceof Uint8Array||n instanceof ArrayBuffer))throw new Error(s);return n}#w(e){if(!e)return!1;let t=this.#g(e);return Number.isFinite(t)}#m(e,t){!e||typeof e.catch!="function"||e.catch(s=>{console.error(`[OSCRewriter] ${t} allocation failed:`,s)})}};function Le(i,e,t=0){for(let s=0;s<=t;s++)if(Atomics.compareExchange(i,e,0,1)===0)return!0;return!1}function Ne(i,e){Atomics.store(i,e,0)}function fe({atomicView:i,dataView:e,uint8View:t,bufferConstants:s,ringBufferBase:r,controlIndices:n,oscMessage:a,maxSpins:c=0}){let l=a.length,u=s.MESSAGE_HEADER_SIZE+l;if(u>s.IN_BUFFER_SIZE-s.MESSAGE_HEADER_SIZE||!Le(i,n.IN_WRITE_LOCK,c))return!1;try{let f=Atomics.load(i,n.IN_HEAD),h=Atomics.load(i,n.IN_TAIL);if((s.IN_BUFFER_SIZE-1-f+h)%s.IN_BUFFER_SIZE<u)return!1;let p=Atomics.add(i,n.IN_SEQUENCE,1),m=s.IN_BUFFER_SIZE-f;if(u>m){let d=new Uint8Array(s.MESSAGE_HEADER_SIZE),w=new DataView(d.buffer);w.setUint32(0,s.MESSAGE_MAGIC,!0),w.setUint32(4,u,!0),w.setUint32(8,p,!0),w.setUint32(12,0,!0);let y=r+s.IN_BUFFER_START+f,_=r+s.IN_BUFFER_START;if(m>=s.MESSAGE_HEADER_SIZE){t.set(d,y);let E=m-s.MESSAGE_HEADER_SIZE;t.set(a.subarray(0,E),y+s.MESSAGE_HEADER_SIZE),t.set(a.subarray(E),_)}else{t.set(d.subarray(0,m),y),t.set(d.subarray(m),_);let E=s.MESSAGE_HEADER_SIZE-m;t.set(a,_+E)}}else{let d=r+s.IN_BUFFER_START+f;e.setUint32(d,s.MESSAGE_MAGIC,!0),e.setUint32(d+4,u,!0),e.setUint32(d+8,p,!0),e.setUint32(d+12,0,!0),t.set(a,d+s.MESSAGE_HEADER_SIZE)}Atomics.load(i,n.IN_HEAD);let S=(f+u)%s.IN_BUFFER_SIZE;return Atomics.store(i,n.IN_HEAD,S),!0}finally{Ne(i,n.IN_WRITE_LOCK)}}var ze=.2,F=class{#s;#i;#h;#n;#f;#e;#a;#r;#o;constructor({sharedBuffer:e,ringBufferBase:t,bufferConstants:s,getAudioContextTime:r,getNTPStartTime:n}){if(!e||!s)throw new Error("DirectWriter requires sharedBuffer and bufferConstants");if(typeof r!="function")throw new Error("DirectWriter requires getAudioContextTime callback");if(typeof n!="function")throw new Error("DirectWriter requires getNTPStartTime callback");this.#s=e,this.#i=t,this.#h=s,this.#n=r,this.#f=n,this.#d()}tryWrite(e){return!this.#e||!this.#o||!this.#S(e)?!1:fe({atomicView:this.#e,dataView:this.#a,uint8View:this.#r,bufferConstants:this.#h,ringBufferBase:this.#i,controlIndices:this.#o,oscMessage:e})}isBundle(e){return e.length>=8&&e[0]===35}#d(){this.#e=new Int32Array(this.#s),this.#a=new DataView(this.#s),this.#r=new Uint8Array(this.#s);let e=this.#h.CONTROL_START;this.#o={IN_HEAD:(this.#i+e+0)/4,IN_TAIL:(this.#i+e+4)/4,IN_SEQUENCE:(this.#i+e+24)/4,IN_WRITE_LOCK:(this.#i+e+40)/4}}#S(e){if(!this.isBundle(e)||e.length<16)return!0;let t=new DataView(e.buffer,e.byteOffset,e.byteLength),s=t.getUint32(8,!1),r=t.getUint32(12,!1);if(s===0&&(r===0||r===1))return!0;let n=this.#n(),a=this.#f();if(n===null||a===0)return!0;let c=n+a;return s+r/4294967296-c<ze}};function Y(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}}function L(i){return i/1e3+2208988800}function Q(i,e){return i-e}function de(i,e){let t=i-e;return Math.round(t*1e3)}var pe={totalPages:1280,ringBufferReserved:3145728,bufferPoolOffset:19922944,bufferPoolSize:63963136,get totalMemory(){return this.bufferPoolOffset+this.bufferPoolSize},get wasmHeapSize(){return this.bufferPoolOffset-this.ringBufferReserved}};var me={numBuffers:1024,maxNodes:1024,maxGraphDefs:1024,maxWireBufs:64,numAudioBusChannels:128,numInputBusChannels:0,numOutputBusChannels:2,numControlBusChannels:4096,bufLength:128,realTimeMemorySize:8192,numRGens:64,realTime:!1,memoryLocking:!1,loadGraphDefs:0,preferredSampleRate:0,verbosity:0};var z=import.meta.url;function at(){try{let i=new URL(z),e=z.substring(0,z.lastIndexOf("/")+1),t=z.match(/^(https:\/\/unpkg\.com\/)supersonic-scsynth@([^/]+)\/dist\/supersonic\.js$/);if(t){let s=t[1],r=t[2];return{baseURL:e,sampleBaseURL:`${s}supersonic-scsynth-samples@${r}/samples/`,synthdefBaseURL:`${s}supersonic-scsynth-synthdefs@${r}/synthdefs/`}}return{baseURL:e,sampleBaseURL:null,synthdefBaseURL:null}}catch{return{baseURL:null,sampleBaseURL:null,synthdefBaseURL:null}}}var j=at(),Re=class i{static osc={encode:e=>D.writePacket(e),decode:(e,t={metadata:!1})=>D.readPacket(e,t)};static inspect(e){let t,s,r;if(e instanceof i)t=e.sharedBuffer,s=e.ringBufferBase,r=e.bufferConstants;else if(e&&e.sab)t=e.sab,s=e.ringBufferBase??0,r=e.layout;else throw new Error("SuperSonic.inspect() requires an instance or {sab, ringBufferBase, layout}");if(!t||!r)return{error:"Not initialized - sab or layout missing"};let n=new Int32Array(t),a=s+r.CONTROL_START,c={inHead:Atomics.load(n,(a+0)/4),inTail:Atomics.load(n,(a+4)/4),outHead:Atomics.load(n,(a+8)/4),outTail:Atomics.load(n,(a+12)/4),debugHead:Atomics.load(n,(a+16)/4),debugTail:Atomics.load(n,(a+20)/4),inSequence:Atomics.load(n,(a+24)/4),outSequence:Atomics.load(n,(a+28)/4),debugSequence:Atomics.load(n,(a+32)/4),statusFlags:Atomics.load(n,(a+36)/4),inWriteLock:Atomics.load(n,(a+40)/4)},l=new Float64Array(t,s+r.NTP_START_TIME_START,1),u=new Int32Array(t,s+r.DRIFT_OFFSET_START,1),f=new Int32Array(t,s+r.GLOBAL_OFFSET_START,1),h={ntpStartTime:l[0],driftOffsetMs:Atomics.load(u,0),globalOffsetMs:Atomics.load(f,0)},g=(c.inHead-c.inTail+r.IN_BUFFER_SIZE)%r.IN_BUFFER_SIZE,p=(c.outHead-c.outTail+r.OUT_BUFFER_SIZE)%r.OUT_BUFFER_SIZE,m=(c.debugHead-c.debugTail+r.DEBUG_BUFFER_SIZE)%r.DEBUG_BUFFER_SIZE,S={in:{bytes:g,percent:g/r.IN_BUFFER_SIZE*100},out:{bytes:p,percent:p/r.OUT_BUFFER_SIZE*100},debug:{bytes:m,percent:m/r.DEBUG_BUFFER_SIZE*100}},d=new Uint32Array(t,s+r.METRICS_START,r.METRICS_SIZE/4),w={processCount:d[0],messagesProcessed:d[1],messagesDropped:d[2],schedulerQueueDepth:d[3],schedulerQueueMax:d[4],schedulerQueueDropped:d[5]};return{layout:r,ringBufferBase:s,control:c,timing:h,bufferUsage:S,metrics:w,sabByteLength:t.byteLength}}#s;#i;#h=null;#n;#f;#e;#a;#r;#o;#d;#S;#l;#p;#g;#E;#y;#b;#c;#w;#m;#A;#v;#t;#C;#T;#B;#M;#O;#I;#$=0;#te=0;#k=null;#F=!1;#V=100;#R=new Map;#W=null;#D=null;#P=null;#_=null;#H=0;constructor(e={}){this.#c=!1,this.#w=!1,this.#m=null,this.#A={},this.#v=null,this.#e=null,this.#a=null,this.#r=null,this.#s=null,this.#i=null,this.#n=null,this.#o=null,this.loadedSynthDefs=new Map;let t=e.baseURL||j.baseURL,s=e.workerBaseURL||(t?`${t}workers/`:null),r=e.wasmBaseURL||(t?`${t}wasm/`:null);if(!s||!r)throw new Error(`SuperSonic requires baseURL or explicit workerBaseURL and wasmBaseURL options. Example:
4
+ Or install: npm install supersonic-scsynth-samples`);return this.#i+e}#w(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#y(e,t,s){let r=null,n=null,a=!1,c=await this.#A(e),l=!1;try{await this.#t(e);let{ptr:u,sizeBytes:f,numFrames:h,numChannels:w,sampleRate:p,source:m,...g}=await s();r=u;let{uuid:d,allocationComplete:S}=this.#m(e,t);n=d,this.#v(e,r,f,d,S,{numFrames:h,numChannels:w,sampleRate:p,source:m}),a=!0;let E=this.#C(e,d,S);return c(),l=!0,{ptr:r,uuid:d,allocationComplete:E,numFrames:h,numChannels:w,sampleRate:p,...g}}catch(u){throw a&&n?this.#T(e,n,!1):r&&this.#e.free(r),u}finally{l||c()}}async prepareFromBlob(e){let{bufnum:t,blob:s,startFrame:r=0,numFrames:n=0,channels:a=null}=e;if(this.#w(t),!s||!(s instanceof ArrayBuffer||ArrayBuffer.isView(s)))throw new Error("/b_allocFile requires audio data as ArrayBuffer or typed array");let c=s instanceof ArrayBuffer?s:s.buffer.slice(s.byteOffset,s.byteOffset+s.byteLength);return this.#y(t,3e4,async()=>{let l=await this.#n.decodeAudioData(c),u=Math.max(0,Math.floor(r||0)),f=l.length-u,h=n&&n>0?Math.min(Math.floor(n),f):f;if(h<=0)throw new Error(`No audio frames available for buffer ${t}`);let w=this.#E(a,l.numberOfChannels),p=w.length,m=h*p+(this.GUARD_BEFORE+this.GUARD_AFTER)*p,g=this.#_(m),d=new Float32Array(m),S=this.GUARD_BEFORE*p;for(let b=0;b<h;b++)for(let y=0;y<p;y++){let _=w[y],A=l.getChannelData(_);d[S+b*p+y]=A[u+b]}await this.#c(g,d);let E=d.length*4;return{ptr:g,sizeBytes:E,numFrames:h,numChannels:p,sampleRate:l.sampleRate}})}async prepareFromFile(e){let{bufnum:t,path:s,startFrame:r=0,numFrames:n=0,channels:a=null}=e;return this.#w(t),this.#y(t,6e4,async()=>{let c=this.#p(s),l=s.split("/").pop(),u=await this.#h.fetch(c,{type:"sample",name:l}),f=await this.#n.decodeAudioData(u),h=Math.max(0,Math.floor(r||0)),w=f.length-h,p=n&&n>0?Math.min(Math.floor(n),w):w;if(p<=0)throw new Error(`No audio frames available for buffer ${t} from ${s}`);let m=this.#E(a,f.numberOfChannels),g=m.length,d=p*g+(this.GUARD_BEFORE+this.GUARD_AFTER)*g,S=this.#_(d),E=new Float32Array(d),b=this.GUARD_BEFORE*g;for(let _=0;_<p;_++)for(let A=0;A<g;A++){let Oe=m[A],De=f.getChannelData(Oe);E[b+_*g+A]=De[h+_]}await this.#c(S,E);let y=E.length*4;return{ptr:S,sizeBytes:y,numFrames:p,numChannels:g,sampleRate:f.sampleRate,source:this.#s==="postMessage"?{type:"file",path:s,startFrame:r,numFrames:n,channels:a}:null}})}async prepareEmpty(e){let{bufnum:t,numFrames:s,numChannels:r=1,sampleRate:n=null}=e;if(this.#w(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 a=Math.floor(s),c=Math.floor(r);return this.#y(t,5e3,async()=>{let l=a*c+(this.GUARD_BEFORE+this.GUARD_AFTER)*c,u=this.#_(l),f=new Float32Array(l);await this.#c(u,f);let h=f.length*4;return{ptr:u,sizeBytes:h,numFrames:a,numChannels:c,sampleRate:n||this.#n.sampleRate}})}#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)}#_(e){let t=e*4,s=this.#e.malloc(t);if(s===0){let r=this.#e.stats(),n=((r.available||0)/(1024*1024)).toFixed(2),a=((r.total||0)/(1024*1024)).toFixed(2),c=(t/(1024*1024)).toFixed(2);throw new Error(`Buffer pool allocation failed: requested ${c}MB, available ${n}MB of ${a}MB total`)}return s}async#c(e,t){if(this.#s==="sab")new Float32Array(this.#f,e,t.length).set(t);else{let s=crypto.randomUUID(),r=new Promise((a,c)=>{let l=setTimeout(()=>{c(new Error("Buffer copy to WASM memory timed out"))},1e4),u=f=>{let h=f.data;h.type==="bufferCopied"&&h.copyId===s&&(this.#l.removeEventListener("message",u),clearTimeout(l),h.success?a():c(new Error(h.error||"Buffer copy failed")))};this.#l.addEventListener("message",u)}),n=t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength);this.#l.postMessage({type:"copyBufferData",copyId:s,ptr:e,data:n},[n]),await r}}#S(e,t,s){return new Promise((r,n)=>{let a=setTimeout(()=>{this.#d.delete(e),n(new Error(`Buffer ${t} allocation timeout (${s}ms)`))},s);this.#d.set(e,{resolve:r,reject:n,timeout:a})})}#m(e,t){let s=crypto.randomUUID(),r=this.#S(s,e,t);return{uuid:s,allocationComplete:r}}async#A(e){let t=this.#g.get(e)||Promise.resolve(),s,r=new Promise(n=>{s=n});return this.#g.set(e,t.then(()=>r)),await t,()=>{s&&(s(),s=null),this.#g.get(e)===r&&this.#g.delete(e)}}#v(e,t,s,r,n,a={}){let c=this.#o.get(e),l={ptr:t,size:s,numFrames:a.numFrames||0,numChannels:a.numChannels||1,sampleRate:a.sampleRate||48e3,pendingToken:r,pendingPromise:n,previousAllocation:c?{ptr:c.ptr,size:c.size}:null,source:a.source||null};return this.#o.set(e,l),l}async#t(e){let t=this.#o.get(e);if(t&&t.pendingToken&&t.pendingPromise)try{await t.pendingPromise}catch{}}#C(e,t,s){return!s||typeof s.then!="function"?(this.#T(e,t,!0),Promise.resolve()):s.then(r=>(this.#T(e,t,!0),r)).catch(r=>{throw this.#T(e,t,!1),r})}#T(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.#e.free(n.ptr);return}r.ptr&&this.#e.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.#e.free(s);return}if(typeof s=="number"&&s===r.ptr){this.#e.free(r.ptr),this.#o.delete(t);return}if(typeof s=="number"&&r.previousAllocation&&r.previousAllocation.ptr===s){this.#e.free(s),r.previousAllocation=null;return}this.#e.free(r.ptr),this.#o.delete(t)}handleBufferAllocated(e){let t=e[0],s=e[1],r=this.#d.get(t);r&&(clearTimeout(r.timeout),r.resolve({bufnum:s}),this.#d.delete(t))}allocate(e){let t=e*4,s=this.#e.malloc(t);if(s===0){let r=this.#e.stats(),n=((r.available||0)/(1024*1024)).toFixed(2),a=((r.total||0)/(1024*1024)).toFixed(2),c=(t/(1024*1024)).toFixed(2);console.error(`[BufferManager] Allocation failed: requested ${c}MB, available ${n}MB of ${a}MB total`)}return s}free(e){return this.#e.free(e)}getView(e,t){return new Float32Array(this.#f,e,t)}getStats(){return this.#e?this.#e.stats():{total:0,available:0,used:0,allocations: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});return e}updateAudioContext(e){if(!e)throw new Error("BufferManager.updateAudioContext requires audioContext");this.#n=e}getDiagnostics(){let e=this.#e.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.#a,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.#d.entries())clearTimeout(t.timeout),t.reject(new Error("BufferManager destroyed"));this.#d.clear();for(let[e,t]of this.#o.entries())t.ptr&&this.#e.free(t.ptr);this.#o.clear(),this.#g.clear()}};var P=class{#s;#i;#h;constructor(e={}){let{onLoadingEvent:t=null,maxRetries:s=3,baseDelay:r=1e3}=e;this.#s=t,this.#i=s,this.#h=r}async fetch(e,{type:t,name:s}){let r=this.#n(e),n=this.#f(e),a=await r;this.#s?.("loading:start",{type:t,name:s,...a!=null&&{size:a}});let l=await(await n).arrayBuffer();return this.#s?.("loading:complete",{type:t,name:s,size:l.byteLength}),l}async#n(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#f(e){let t;for(let s=0;s<=this.#i;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.#i){let n=this.#h*Math.pow(2,s);await this.#e(n)}}throw t}#e(e){return new Promise(t=>setTimeout(t,e))}};var x=class{#s;#i;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.#s=e,this.#i=t}async rewritePacket(e){if(e&&e.address){let{message:t,changed:s}=await this.#h(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#h(e){switch(e.address){case"/b_alloc":return{message:await this.#n(e),changed:!0};case"/b_allocRead":return{message:await this.#f(e),changed:!0};case"/b_allocReadChannel":return{message:await this.#e(e),changed:!0};case"/b_allocFile":return{message:await this.#a(e),changed:!0};default:return{message:e,changed:!1}}}async#n(e){let t=this.#y(e.args,0,"/b_alloc requires a buffer number"),s=this.#y(e.args,1,"/b_alloc requires a frame count"),r=2,n=1,a=this.#i();this.#S(this.#p(e.args,r))&&(n=Math.max(1,this.#E(e.args,r,1)),r++),this.#p(e.args,r)?.type==="b"&&r++,this.#S(this.#p(e.args,r))&&(a=this.#w(this.#p(e.args,r)));let c=await this.#s.prepareEmpty({bufnum:t,numFrames:s,numChannels:n,sampleRate:a});return this.#m(c.allocationComplete,`/b_alloc ${t}`),this.#r(t,c)}async#f(e){let t=this.#y(e.args,0,"/b_allocRead requires a buffer number"),s=this.#_(e.args,1,"/b_allocRead requires a file path"),r=this.#E(e.args,2,0),n=this.#E(e.args,3,0),a=await this.#s.prepareFromFile({bufnum:t,path:s,startFrame:r,numFrames:n});return this.#m(a.allocationComplete,`/b_allocRead ${t}`),this.#r(t,a)}async#e(e){let t=this.#y(e.args,0,"/b_allocReadChannel requires a buffer number"),s=this.#_(e.args,1,"/b_allocReadChannel requires a file path"),r=this.#E(e.args,2,0),n=this.#E(e.args,3,0),a=[];for(let l=4;l<(e.args?.length||0)&&this.#S(e.args[l]);l++)a.push(Math.floor(this.#w(e.args[l])));let c=await this.#s.prepareFromFile({bufnum:t,path:s,startFrame:r,numFrames:n,channels:a.length>0?a:null});return this.#m(c.allocationComplete,`/b_allocReadChannel ${t}`),this.#r(t,c)}async#a(e){let t=this.#y(e.args,0,"/b_allocFile requires a buffer number"),s=this.#c(e.args,1,"/b_allocFile requires audio file data as blob"),r=await this.#s.prepareFromBlob({bufnum:t,blob:s});return this.#m(r.allocationComplete,`/b_allocFile ${t}`),this.#r(t,r)}#r(e,t){return{address:"/b_allocPtr",args:[this.#d(e),this.#d(t.ptr),this.#d(t.numFrames),this.#d(t.numChannels),this.#g(t.sampleRate),this.#l(t.uuid)]}}#o(e){return e&&e.timeTag!==void 0&&Array.isArray(e.packets)}#d(e){return{type:"i",value:Math.floor(e)}}#g(e){return{type:"f",value:e}}#l(e){return{type:"s",value:String(e)}}#p(e,t){if(Array.isArray(e))return e[t]}#w(e){if(e!=null)return typeof e=="object"&&Object.prototype.hasOwnProperty.call(e,"value")?e.value:e}#y(e,t,s){let r=this.#w(this.#p(e,t));if(!Number.isFinite(r))throw new Error(s);return Math.floor(r)}#E(e,t,s=0){let r=this.#w(this.#p(e,t));return Number.isFinite(r)?Math.floor(r):s}#_(e,t,s){let r=this.#w(this.#p(e,t));if(typeof r!="string")throw new Error(s);return r}#c(e,t,s){let r=this.#p(e,t);if(!r||r.type!=="b")throw new Error(s);let n=this.#w(r);if(!(n instanceof Uint8Array||n instanceof ArrayBuffer))throw new Error(s);return n}#S(e){if(!e)return!1;let t=this.#w(e);return Number.isFinite(t)}#m(e,t){!e||typeof e.catch!="function"||e.catch(s=>{console.error(`[OSCRewriter] ${t} allocation failed:`,s)})}};function Le(i,e,t=0){for(let s=0;s<=t;s++)if(Atomics.compareExchange(i,e,0,1)===0)return!0;return!1}function Ne(i,e){Atomics.store(i,e,0)}function fe({atomicView:i,dataView:e,uint8View:t,bufferConstants:s,ringBufferBase:r,controlIndices:n,oscMessage:a,maxSpins:c=0}){let l=a.length,u=s.MESSAGE_HEADER_SIZE+l;if(u>s.IN_BUFFER_SIZE-s.MESSAGE_HEADER_SIZE||!Le(i,n.IN_WRITE_LOCK,c))return!1;try{let f=Atomics.load(i,n.IN_HEAD),h=Atomics.load(i,n.IN_TAIL);if((s.IN_BUFFER_SIZE-1-f+h)%s.IN_BUFFER_SIZE<u)return!1;let p=Atomics.add(i,n.IN_SEQUENCE,1),m=s.IN_BUFFER_SIZE-f;if(u>m){let d=new Uint8Array(s.MESSAGE_HEADER_SIZE),S=new DataView(d.buffer);S.setUint32(0,s.MESSAGE_MAGIC,!0),S.setUint32(4,u,!0),S.setUint32(8,p,!0),S.setUint32(12,0,!0);let E=r+s.IN_BUFFER_START+f,b=r+s.IN_BUFFER_START;if(m>=s.MESSAGE_HEADER_SIZE){t.set(d,E);let y=m-s.MESSAGE_HEADER_SIZE;t.set(a.subarray(0,y),E+s.MESSAGE_HEADER_SIZE),t.set(a.subarray(y),b)}else{t.set(d.subarray(0,m),E),t.set(d.subarray(m),b);let y=s.MESSAGE_HEADER_SIZE-m;t.set(a,b+y)}}else{let d=r+s.IN_BUFFER_START+f;e.setUint32(d,s.MESSAGE_MAGIC,!0),e.setUint32(d+4,u,!0),e.setUint32(d+8,p,!0),e.setUint32(d+12,0,!0),t.set(a,d+s.MESSAGE_HEADER_SIZE)}Atomics.load(i,n.IN_HEAD);let g=(f+u)%s.IN_BUFFER_SIZE;return Atomics.store(i,n.IN_HEAD,g),!0}finally{Ne(i,n.IN_WRITE_LOCK)}}var ze=.2,F=class{#s;#i;#h;#n;#f;#e;#a;#r;#o;constructor({sharedBuffer:e,ringBufferBase:t,bufferConstants:s,getAudioContextTime:r,getNTPStartTime:n}){if(!e||!s)throw new Error("DirectWriter requires sharedBuffer and bufferConstants");if(typeof r!="function")throw new Error("DirectWriter requires getAudioContextTime callback");if(typeof n!="function")throw new Error("DirectWriter requires getNTPStartTime callback");this.#s=e,this.#i=t,this.#h=s,this.#n=r,this.#f=n,this.#d()}tryWrite(e){return!this.#e||!this.#o||!this.#g(e)?!1:fe({atomicView:this.#e,dataView:this.#a,uint8View:this.#r,bufferConstants:this.#h,ringBufferBase:this.#i,controlIndices:this.#o,oscMessage:e})}isBundle(e){return e.length>=8&&e[0]===35}#d(){this.#e=new Int32Array(this.#s),this.#a=new DataView(this.#s),this.#r=new Uint8Array(this.#s);let e=this.#h.CONTROL_START;this.#o={IN_HEAD:(this.#i+e+0)/4,IN_TAIL:(this.#i+e+4)/4,IN_SEQUENCE:(this.#i+e+24)/4,IN_WRITE_LOCK:(this.#i+e+40)/4}}#g(e){if(!this.isBundle(e)||e.length<16)return!0;let t=new DataView(e.buffer,e.byteOffset,e.byteLength),s=t.getUint32(8,!1),r=t.getUint32(12,!1);if(s===0&&(r===0||r===1))return!0;let n=this.#n(),a=this.#f();if(n===null||a===0)return!0;let c=n+a;return s+r/4294967296-c<ze}};function Y(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}}function L(i){return i/1e3+2208988800}function Q(i,e){return i-e}function de(i,e){let t=i-e;return Math.round(t*1e3)}var pe={totalPages:1280,ringBufferReserved:3145728,bufferPoolOffset:19922944,bufferPoolSize:63963136,get totalMemory(){return this.bufferPoolOffset+this.bufferPoolSize},get wasmHeapSize(){return this.bufferPoolOffset-this.ringBufferReserved}};var me={numBuffers:1024,maxNodes:1024,maxGraphDefs:1024,maxWireBufs:64,numAudioBusChannels:128,numInputBusChannels:0,numOutputBusChannels:2,numControlBusChannels:4096,bufLength:128,realTimeMemorySize:8192,numRGens:64,realTime:!1,memoryLocking:!1,loadGraphDefs:0,preferredSampleRate:0,verbosity:0};var z=import.meta.url;function at(){try{let i=new URL(z),e=z.substring(0,z.lastIndexOf("/")+1),t=z.match(/^(https:\/\/unpkg\.com\/)supersonic-scsynth@([^/]+)\/dist\/supersonic\.js$/);if(t){let s=t[1],r=t[2];return{baseURL:e,sampleBaseURL:`${s}supersonic-scsynth-samples@${r}/samples/`,synthdefBaseURL:`${s}supersonic-scsynth-synthdefs@${r}/synthdefs/`}}return{baseURL:e,sampleBaseURL:null,synthdefBaseURL:null}}catch{return{baseURL:null,sampleBaseURL:null,synthdefBaseURL:null}}}var j=at(),Re=class i{static osc={encode:e=>D.writePacket(e),decode:(e,t={metadata:!1})=>D.readPacket(e,t)};static inspect(e){let t,s,r;if(e instanceof i)t=e.sharedBuffer,s=e.ringBufferBase,r=e.bufferConstants;else if(e&&e.sab)t=e.sab,s=e.ringBufferBase??0,r=e.layout;else throw new Error("SuperSonic.inspect() requires an instance or {sab, ringBufferBase, layout}");if(!t||!r)return{error:"Not initialized - sab or layout missing"};let n=new Int32Array(t),a=s+r.CONTROL_START,c={inHead:Atomics.load(n,(a+0)/4),inTail:Atomics.load(n,(a+4)/4),outHead:Atomics.load(n,(a+8)/4),outTail:Atomics.load(n,(a+12)/4),debugHead:Atomics.load(n,(a+16)/4),debugTail:Atomics.load(n,(a+20)/4),inSequence:Atomics.load(n,(a+24)/4),outSequence:Atomics.load(n,(a+28)/4),debugSequence:Atomics.load(n,(a+32)/4),statusFlags:Atomics.load(n,(a+36)/4),inWriteLock:Atomics.load(n,(a+40)/4)},l=new Float64Array(t,s+r.NTP_START_TIME_START,1),u=new Int32Array(t,s+r.DRIFT_OFFSET_START,1),f=new Int32Array(t,s+r.GLOBAL_OFFSET_START,1),h={ntpStartTime:l[0],driftOffsetMs:Atomics.load(u,0),globalOffsetMs:Atomics.load(f,0)},w=(c.inHead-c.inTail+r.IN_BUFFER_SIZE)%r.IN_BUFFER_SIZE,p=(c.outHead-c.outTail+r.OUT_BUFFER_SIZE)%r.OUT_BUFFER_SIZE,m=(c.debugHead-c.debugTail+r.DEBUG_BUFFER_SIZE)%r.DEBUG_BUFFER_SIZE,g={in:{bytes:w,percent:w/r.IN_BUFFER_SIZE*100},out:{bytes:p,percent:p/r.OUT_BUFFER_SIZE*100},debug:{bytes:m,percent:m/r.DEBUG_BUFFER_SIZE*100}},d=new Uint32Array(t,s+r.METRICS_START,r.METRICS_SIZE/4),S={processCount:d[0],messagesProcessed:d[1],messagesDropped:d[2],schedulerQueueDepth:d[3],schedulerQueueMax:d[4],schedulerQueueDropped:d[5]};return{layout:r,ringBufferBase:s,control:c,timing:h,bufferUsage:g,metrics:S,sabByteLength:t.byteLength}}#s;#i;#h=null;#n;#f;#e;#a;#r;#o;#d;#g;#l;#p;#w;#y;#E;#_;#c;#S;#m;#A;#v;#t;#C;#T;#B;#M;#O;#I;#W=0;#re=0;#k=null;#F=!1;#H=100;#R=new Map;#G=null;#D=null;#P=null;#b=null;#q=0;#L=[];#N=null;constructor(e={}){this.#c=!1,this.#S=!1,this.#m=null,this.#A={},this.#v=null,this.#e=null,this.#a=null,this.#r=null,this.#s=null,this.#i=null,this.#n=null,this.#o=null,this.loadedSynthDefs=new Map;let t=e.baseURL||j.baseURL,s=e.workerBaseURL||(t?`${t}workers/`:null),r=e.wasmBaseURL||(t?`${t}wasm/`:null);if(!s||!r)throw new Error(`SuperSonic requires baseURL or explicit workerBaseURL and wasmBaseURL options. Example:
5
5
  new SuperSonic({
6
6
  baseURL: "/supersonic/"
7
7
  })
@@ -9,7 +9,7 @@ new SuperSonic({
9
9
  new SuperSonic({
10
10
  workerBaseURL: "/supersonic/workers/",
11
11
  wasmBaseURL: "/supersonic/wasm/"
12
- })`);let n={...me,...e.scsynthOptions},a=e.mode||"postMessage";this.#t={mode:a,snapshotIntervalMs:e.snapshotIntervalMs??25,wasmUrl:e.wasmUrl||r+"scsynth-nrt.wasm",wasmBaseURL:r,workletUrl:e.workletUrl||s+"scsynth_audio_worklet.js",workerBaseURL:s,audioContext:e.audioContext||null,autoConnect:e.autoConnect!==!1,audioContextOptions:{latencyHint:"interactive",sampleRate:48e3},memory:pe,worldOptions:n,preschedulerCapacity:e.preschedulerCapacity||65536,activityEvent:{maxLineLength:e.activityEvent?.maxLineLength??200,scsynth:e.activityEvent?.scsynth??null,oscIn:e.activityEvent?.oscIn??null,oscOut:e.activityEvent?.oscOut??null},debug:e.debug??!1,debugScsynth:e.debugScsynth??!1,debugOscIn:e.debugOscIn??!1,debugOscOut:e.debugOscOut??!1,activityConsoleLog:{maxLineLength:e.activityConsoleLog?.maxLineLength??200,scsynth:e.activityConsoleLog?.scsynth??null,oscIn:e.activityConsoleLog?.oscIn??null,oscOut:e.activityConsoleLog?.oscOut??null}},this.#g=e.sampleBaseURL||j.sampleBaseURL||(t?`${t}samples/`:null),this.#E=e.synthdefBaseURL||j.synthdefBaseURL||(t?`${t}synthdefs/`:null),this.#y={maxRetries:e.fetchMaxRetries??3,baseDelay:e.fetchRetryDelay??1e3},this.#b=new P({onLoadingEvent:(c,l)=>this.#u(c,l),maxRetries:this.#y.maxRetries,baseDelay:this.#y.baseDelay}),this.bootStats={initStartTime:null,initDuration:null}}get initialized(){return this.#c}get initializing(){return this.#w}get mode(){return this.#t.mode}on(e,t){if(typeof t!="function")throw new Error("Callback must be a function");return this.#R.has(e)||this.#R.set(e,new Set),this.#R.get(e).add(t),()=>this.off(e,t)}off(e,t){let s=this.#R.get(e);return s&&s.delete(t),this}once(e,t){let s=(...r)=>{this.off(e,s),t(...r)};return this.on(e,s)}removeAllListeners(e){return e===void 0?this.#R.clear():this.#R.delete(e),this}#u(e,...t){let s=this.#R.get(e);if(s)for(let r of s)try{r(...t)}catch(n){console.error(`[SuperSonic] Error in ${e} listener:`,n)}}async init(e={}){if(!this.#c)return this.#m?this.#m:(this.#m=this.#se(e),this.#m)}async#se(e){this.#t={...this.#t,...e,audioContextOptions:{...this.#t.audioContextOptions,...e.audioContextOptions||{}}},this.#w=!0,this.bootStats.initStartTime=performance.now();try{this.#ae(),this.#ce(),this.#G(),this.#le(),this.#q();let t=await this.#Z();await this.#Y(t),await this.#Q(),this.#N(),await this.#j()}catch(t){throw this.#w=!1,this.#m=null,console.error("[SuperSonic] Initialization failed:",t),this.#u("error",t),t}}getMetrics(){return this.#X()}setMetricsInterval(e){this.#V=e,this.#N()}stopMetricsPolling(){this.#x()}async#re(){if(!this.#s||!this.#B)return!1;try{await this.#s.resume()}catch{}let e=this.#B[0];await new Promise(r=>setTimeout(r,200));let s=this.#B[0]>e;return s&&this.#ee(),s}async recover(){if(!this.#c)return!1;if(await this.#re())return!0;this.#u("recover:start");let e=await this.#ie();return this.#u("recover:complete",{success:e}),e}async#ie(){if(!this.#c)return!1;let e=new Map(this.loadedSynthDefs),t=this.#o?.getAllocatedBuffers()||[];await this.#ne(),await this.#oe();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.#t.mode==="postMessage"&&s.source)s.source.type==="file"?await this.loadSample(s.bufnum,s.source.path,s.source.startFrame||0,s.source.numFrames||0):console.warn(`[SuperSonic] Unknown buffer source type: ${s.source.type}`);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(),!0}async#ne(){this.#z(),this.#x(),this.#l?.clear(),this.#l=null,this.#n&&(this.#n.cancelAll(),this.#n.terminate(),this.#n=null),this.#i&&(this.#i.disconnect(),this.#i=null),this.#s&&(await this.#s.close(),this.#s=null),this.#c=!1,this.loadedSynthDefs.clear(),this.#m=null,this.#a=null,this.#r=null,this.#C=null,this.#T=null,this.#B=null,this.#M=null,this.#O=null,this.#I=null,this.#p=void 0}async#oe(){this.#w=!0,this.bootStats.initStartTime=performance.now();try{this.#G(),this.#o&&this.#o.updateAudioContext(this.#s),this.#q();let e=await this.#Z();await this.#Y(e),await this.#Q(),this.#N(),await this.#j()}catch(e){throw this.#w=!1,this.#m=null,console.error("[SuperSonic] Partial init failed:",e),this.#u("error",e),e}}getTree(){if(!this.#c)return{nodeCount:0,version:0,nodes:[]};let e,t;if(this.#t.mode==="postMessage"){if(!this.#_||!this.#r)return{nodeCount:0,version:0,nodes:[]};e=this.#_,t=this.#r.METRICS_SIZE}else{if(!this.#e||!this.#r)return{nodeCount:0,version:0,nodes:[]};e=this.#e,t=this.#a+this.#r.NODE_TREE_START}let s=this.#r,r=new Uint32Array(e,t,2),n=r[0],a=r[1],c=t+s.NODE_TREE_HEADER_SIZE,l=s.NODE_TREE_MAX_NODES,u=s.NODE_TREE_ENTRY_SIZE,f=s.NODE_TREE_DEF_NAME_SIZE,h=new DataView(e,c,l*u),g=new TextDecoder("utf-8"),p=[],m=0;for(let S=0;S<l&&m<n;S++){let d=S*u,w=h.getInt32(d,!0);if(w===-1)continue;m++;let y=c+d+24,_=new Uint8Array(e,y,f),E=new Uint8Array(f);E.set(_);let b=E.indexOf(0);b===-1&&(b=f);let A=g.decode(E.subarray(0,b));p.push({id:w,parentId:h.getInt32(d+4,!0),isGroup:h.getInt32(d+8,!0)===1,prevId:h.getInt32(d+12,!0),nextId:h.getInt32(d+16,!0),headId:h.getInt32(d+20,!0),defName:A})}return{nodeCount:n,version:a,nodes:p}}get bufferConstants(){return this.#r}get ringBufferBase(){return this.#a}get sharedBuffer(){return this.#e}startCapture(){if(!this.#c||!this.#e||!this.#r)throw new Error("SuperSonic not initialized");let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,4);Atomics.store(s,1,0),Atomics.store(s,0,1)}stopCapture(){if(!this.#c||!this.#e||!this.#r)throw new Error("SuperSonic not initialized");let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,4);Atomics.store(s,0,0);let r=Atomics.load(s,1),n=s[2],a=s[3],c=t+e.AUDIO_CAPTURE_HEADER_SIZE,l=new Float32Array(this.#e,c,r*a),u=new Float32Array(r),f=a>1?new Float32Array(r):null;for(let h=0;h<r;h++)u[h]=l[h*a],f&&(f[h]=l[h*a+1]);return{sampleRate:n,channels:a,frames:r,left:u,right:f}}isCaptureEnabled(){if(!this.#c||!this.#e||!this.#r)return!1;let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,1);return Atomics.load(s,0)===1}getCaptureFrames(){if(!this.#c||!this.#e||!this.#r)return 0;let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,2);return Atomics.load(s,1)}getMaxCaptureDuration(){if(!this.#r)return 0;let e=this.#r;return e.AUDIO_CAPTURE_FRAMES/(e.AUDIO_CAPTURE_SAMPLE_RATE||48e3)}async send(e,...t){if(this.#U("send OSC messages"),e==="/d_load"||e==="/d_loadDir")throw new Error(`${e} is not supported in SuperSonic (no filesystem). Use loadSynthDef() or send /d_recv with synthdef bytes instead.`);if(e==="/b_read"||e==="/b_readChannel")throw new Error(`${e} is not supported in SuperSonic (no filesystem). Use loadSample() to load audio into a buffer.`);if(e==="/b_write"||e==="/b_close")throw new Error(`${e} is not supported in SuperSonic (no filesystem). Writing audio files is not available in the browser.`);if(e==="/clearSched")throw new Error("/clearSched is not supported in SuperSonic. Bundle scheduling works differently in the browser AudioWorklet environment.");if(e==="/dumpOSC")throw new Error("/dumpOSC is not supported in SuperSonic. Use browser developer tools to inspect OSC messages.");if(e==="/error")throw new Error("/error is not supported in SuperSonic. Error notifications are always enabled.");if(e==="/d_recv"){let a=t[0];if(a instanceof Uint8Array||a instanceof ArrayBuffer){let c=a instanceof ArrayBuffer?new Uint8Array(a):a,l=Y(c)||"unknown";this.loadedSynthDefs.set(l,c)}}if(e==="/d_free")for(let a of t)typeof a=="string"&&this.loadedSynthDefs.delete(a);else e==="/d_freeAll"&&this.loadedSynthDefs.clear();let s=t.map(a=>{if(typeof a=="string")return{type:"s",value:a};if(typeof a=="number")return{type:Number.isInteger(a)?"i":"f",value:a};if(a instanceof Uint8Array||a instanceof ArrayBuffer)return{type:"b",value:a instanceof ArrayBuffer?new Uint8Array(a):a};throw new Error(`Unsupported argument type: ${typeof a}`)}),r={address:e,args:s},n=i.osc.encode(r);if(this.#t.debug||this.#t.debugOscOut){let a=this.#t.activityConsoleLog.oscOut??this.#t.activityConsoleLog.maxLineLength,c=t.map(l=>{if(l instanceof Uint8Array||l instanceof ArrayBuffer)return`<${l.byteLength||l.length} bytes>`;let u=JSON.stringify(l);return u.length>a?u.slice(0,a)+"...":u}).join(", ");console.log(`[OSC \u2192] ${e}${c?" "+c:""}`)}return this.sendOSC(n)}async sendOSC(e,t={}){this.#U("send OSC data");let s=this.#be(e),r=await this.#Ae(s);if(this.#L("mainMessagesSent"),this.#L("mainBytesSent",r.length),this.#u("message:sent",r),this.#C?.tryWrite(r)){this.#L("preschedulerBypassed");return}let n=this.#Te(r);if(this.#t.mode==="postMessage"&&!n){this.#i.port.postMessage({type:"osc",oscData:r});return}let a=this.#r?.scheduler_slot_size;if(n&&a&&r.length>a)throw new Error(`OSC bundle too large to schedule (${r.length} > ${a} bytes). Use immediate timestamp (0 or 1) for large messages, or reduce bundle size.`);let c={...t};n&&(c.audioTimeS=n.audioTimeS,c.currentTimeS=n.currentTimeS),this.#n.send(r,c)}cancelTag(e){this.#U("cancel by tag"),this.#n.cancelTag(e)}cancelSession(e){this.#U("cancel by session"),this.#n.cancelSession(e)}cancelSessionTag(e,t){this.#U("cancel by session and tag"),this.#n.cancelSessionTag(e,t)}cancelAllScheduled(){this.#U("cancel all scheduled"),this.#n.cancelAll()}get node(){return this.#h}get osc(){return this.#n}async loadSynthDef(e){if(!this.#c)throw new Error("SuperSonic not initialized. Call init() first.");let t;if(this.#we(e))t=e;else{if(!this.#E)throw new Error("synthdefBaseURL not configured. Either provide a full path or set synthdefBaseURL in constructor options.");t=`${this.#E}${e}.scsyndef`}let s=Y(t);try{let r=await this.#b.fetch(t,{type:"synthdef",name:s}),n=new Uint8Array(r);return await this.send("/d_recv",n),{name:s,size:n.length}}catch(r){throw console.error("[SuperSonic] Failed to load synthdef:",r),r}}async loadSynthDefs(e){if(!this.#c)throw new Error("SuperSonic not initialized. Call init() first.");let t={};await Promise.all(e.map(async r=>{try{await this.loadSynthDef(r),t[r]={success:!0}}catch(n){console.error(`[SuperSonic] Failed to load ${r}:`,n),t[r]={success:!1,error:n.message}}}));let s=Object.values(t).filter(r=>r.success).length;return t}async loadSample(e,t,s=0,r=0){this.#U("load samples");let n=await this.#o.prepareFromFile({bufnum:e,path:t,startFrame:s,numFrames:r});return await this.send("/b_allocPtr",e,n.ptr,n.numFrames,n.numChannels,n.sampleRate,n.uuid),n.allocationComplete}async sync(e=Math.floor(Math.random()*2147483647)){if(!this.#c)throw new Error("SuperSonic not initialized. Call init() first.");let t=new Promise((s,r)=>{let n=setTimeout(()=>{this.#l&&this.#l.delete(e),r(new Error("Timeout waiting for /synced response"))},1e4),a=c=>{clearTimeout(n),this.#l.delete(e),s()};this.#l||(this.#l=new Map),this.#l.set(e,a)});await this.send("/sync",e),await t,this.#t.mode==="postMessage"&&await new Promise(s=>setTimeout(s,this.#t.snapshotIntervalMs*2))}getInfo(){return this.#U("get info"),{sampleRate:this.#s.sampleRate,numBuffers:this.#t.worldOptions.numBuffers,totalMemory:this.#t.memory.totalMemory,wasmHeapSize:this.#t.memory.wasmHeapSize,bufferPoolSize:this.#t.memory.bufferPoolSize,bootTimeMs:this.bootStats.initDuration,capabilities:{...this.#A},version:this.#v}}async shutdown(){!this.#c&&!this.#w||(this.#u("shutdown"),this.#z(),this.#x(),this.#l?.clear(),this.#l=null,this.#n&&(this.#n.cancelAll(),this.#n.terminate(),this.#n=null),this.#i&&(this.#i.disconnect(),this.#i=null),this.#s&&(await this.#s.close(),this.#s=null),this.#o&&(this.#o.destroy(),this.#o=null),this.#d=null,this.#C=null,this.#e=null,this.#c=!1,this.loadedSynthDefs.clear(),this.#m=null,this.#f=null,this.#a=null,this.#r=null,this.#T=null,this.#B=null,this.#M=null,this.#O=null,this.#I=null,this.#_=null,this.#H=0,this.#p=void 0,this.bootStats={initStartTime:null,initDuration:null})}async destroy(){this.#u("destroy"),await this.shutdown(),this.#P=null,this.#R.clear()}async reset(e={}){await this.shutdown(),await this.init(e)}#ae(){this.#A={audioWorklet:typeof AudioWorklet<"u",sharedArrayBuffer:typeof SharedArrayBuffer<"u",crossOriginIsolated:window.crossOriginIsolated===!0,atomics:typeof Atomics<"u",webWorker:typeof Worker<"u"};let e=this.#t.mode,t=["audioWorklet","webWorker"];e==="sab"&&t.push("sharedArrayBuffer","crossOriginIsolated","atomics");let s=t.filter(r=>!this.#A[r]);if(s.length>0){let r=new Error(`Missing required features for ${e} mode: ${s.join(", ")}`);throw e==="sab"&&!this.#A.crossOriginIsolated&&(this.#A.sharedArrayBuffer?r.message+=`
12
+ })`);let n={...me,...e.scsynthOptions},a=e.mode||"postMessage";this.#t={mode:a,snapshotIntervalMs:e.snapshotIntervalMs??25,wasmUrl:e.wasmUrl||r+"scsynth-nrt.wasm",wasmBaseURL:r,workletUrl:e.workletUrl||s+"scsynth_audio_worklet.js",workerBaseURL:s,audioContext:e.audioContext||null,autoConnect:e.autoConnect!==!1,audioContextOptions:{latencyHint:"interactive",sampleRate:48e3},memory:pe,worldOptions:n,preschedulerCapacity:e.preschedulerCapacity||65536,activityEvent:{maxLineLength:e.activityEvent?.maxLineLength??200,scsynth:e.activityEvent?.scsynth??null,oscIn:e.activityEvent?.oscIn??null,oscOut:e.activityEvent?.oscOut??null},debug:e.debug??!1,debugScsynth:e.debugScsynth??!1,debugOscIn:e.debugOscIn??!1,debugOscOut:e.debugOscOut??!1,activityConsoleLog:{maxLineLength:e.activityConsoleLog?.maxLineLength??200,scsynth:e.activityConsoleLog?.scsynth??null,oscIn:e.activityConsoleLog?.oscIn??null,oscOut:e.activityConsoleLog?.oscOut??null}},this.#w=e.sampleBaseURL||j.sampleBaseURL||(t?`${t}samples/`:null),this.#y=e.synthdefBaseURL||j.synthdefBaseURL||(t?`${t}synthdefs/`:null),this.#E={maxRetries:e.fetchMaxRetries??3,baseDelay:e.fetchRetryDelay??1e3},this.#_=new P({onLoadingEvent:(c,l)=>this.#u(c,l),maxRetries:this.#E.maxRetries,baseDelay:this.#E.baseDelay}),this.bootStats={initStartTime:null,initDuration:null}}get initialized(){return this.#c}get initializing(){return this.#S}get mode(){return this.#t.mode}on(e,t){if(typeof t!="function")throw new Error("Callback must be a function");return this.#R.has(e)||this.#R.set(e,new Set),this.#R.get(e).add(t),()=>this.off(e,t)}off(e,t){let s=this.#R.get(e);return s&&s.delete(t),this}once(e,t){let s=(...r)=>{this.off(e,s),t(...r)};return this.on(e,s)}removeAllListeners(e){return e===void 0?this.#R.clear():this.#R.delete(e),this}#u(e,...t){let s=this.#R.get(e);if(s)for(let r of s)try{r(...t)}catch(n){console.error(`[SuperSonic] Error in ${e} listener:`,n)}}async init(e={}){if(!this.#c)return this.#m?this.#m:(this.#m=this.#ie(e),this.#m)}async#ie(e){this.#t={...this.#t,...e,audioContextOptions:{...this.#t.audioContextOptions,...e.audioContextOptions||{}}},this.#S=!0,this.bootStats.initStartTime=performance.now();try{this.#le(),this.#ue(),this.#Z(),this.#he(),this.#Y();let t=await this.#Q();await this.#j(t),await this.#K(),this.#$(),await this.#X()}catch(t){throw this.#S=!1,this.#m=null,console.error("[SuperSonic] Initialization failed:",t),this.#u("error",t),t}}getMetrics(){return this.#ee()}setMetricsInterval(e){this.#H=e,this.#$()}stopMetricsPolling(){this.#x()}async#ne(){if(!this.#s||!this.#B)return!1;try{await this.#s.resume()}catch{}let e=this.#B[0];await new Promise(r=>setTimeout(r,200));let s=this.#B[0]>e;return s&&this.#se(),s}async recover(){if(!this.#c)return!1;if(await this.#ne())return!0;this.#u("recover:start");let e=await this.#oe();return this.#u("recover:complete",{success:e}),e}async#oe(){if(!this.#c)return!1;let e=new Map(this.loadedSynthDefs),t=this.#o?.getAllocatedBuffers()||[];await this.#ae(),await this.#ce();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.#t.mode==="postMessage"&&s.source)s.source.type==="file"?await this.loadSample(s.bufnum,s.source.path,s.source.startFrame||0,s.source.numFrames||0):console.warn(`[SuperSonic] Unknown buffer source type: ${s.source.type}`);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(),!0}async#ae(){this.#V(),this.#x(),this.#l?.clear(),this.#l=null,this.#n&&(this.#n.cancelAll(),this.#n.terminate(),this.#n=null),this.#i&&(this.#i.disconnect(),this.#i=null),this.#s&&(await this.#s.close(),this.#s=null),this.#c=!1,this.loadedSynthDefs.clear(),this.#m=null,this.#a=null,this.#r=null,this.#C=null,this.#T=null,this.#B=null,this.#M=null,this.#O=null,this.#I=null,this.#p=void 0}async#ce(){this.#S=!0,this.bootStats.initStartTime=performance.now();try{this.#Z(),this.#o&&this.#o.updateAudioContext(this.#s),this.#Y();let e=await this.#Q();await this.#j(e),await this.#K(),this.#$(),await this.#X()}catch(e){throw this.#S=!1,this.#m=null,console.error("[SuperSonic] Partial init failed:",e),this.#u("error",e),e}}getTree(){if(!this.#c)return{nodeCount:0,version:0,nodes:[]};let e,t;if(this.#t.mode==="postMessage"){if(!this.#b||!this.#r)return{nodeCount:0,version:0,nodes:[]};e=this.#b,t=this.#r.METRICS_SIZE}else{if(!this.#e||!this.#r)return{nodeCount:0,version:0,nodes:[]};e=this.#e,t=this.#a+this.#r.NODE_TREE_START}let s=this.#r,r=new Uint32Array(e,t,2),n=r[0],a=r[1],c=t+s.NODE_TREE_HEADER_SIZE,l=s.NODE_TREE_MAX_NODES,u=s.NODE_TREE_ENTRY_SIZE,f=s.NODE_TREE_DEF_NAME_SIZE,h=new DataView(e,c,l*u),w=new TextDecoder("utf-8"),p=[],m=0;for(let g=0;g<l&&m<n;g++){let d=g*u,S=h.getInt32(d,!0);if(S===-1)continue;m++;let E=c+d+24,b=new Uint8Array(e,E,f),y=new Uint8Array(f);y.set(b);let _=y.indexOf(0);_===-1&&(_=f);let A=w.decode(y.subarray(0,_));p.push({id:S,parentId:h.getInt32(d+4,!0),isGroup:h.getInt32(d+8,!0)===1,prevId:h.getInt32(d+12,!0),nextId:h.getInt32(d+16,!0),headId:h.getInt32(d+20,!0),defName:A})}return{nodeCount:n,version:a,nodes:p}}get bufferConstants(){return this.#r}get ringBufferBase(){return this.#a}get sharedBuffer(){return this.#e}startCapture(){if(!this.#c||!this.#e||!this.#r)throw new Error("SuperSonic not initialized");let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,4);Atomics.store(s,1,0),Atomics.store(s,0,1)}stopCapture(){if(!this.#c||!this.#e||!this.#r)throw new Error("SuperSonic not initialized");let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,4);Atomics.store(s,0,0);let r=Atomics.load(s,1),n=s[2],a=s[3],c=t+e.AUDIO_CAPTURE_HEADER_SIZE,l=new Float32Array(this.#e,c,r*a),u=new Float32Array(r),f=a>1?new Float32Array(r):null;for(let h=0;h<r;h++)u[h]=l[h*a],f&&(f[h]=l[h*a+1]);return{sampleRate:n,channels:a,frames:r,left:u,right:f}}isCaptureEnabled(){if(!this.#c||!this.#e||!this.#r)return!1;let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,1);return Atomics.load(s,0)===1}getCaptureFrames(){if(!this.#c||!this.#e||!this.#r)return 0;let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,2);return Atomics.load(s,1)}getMaxCaptureDuration(){if(!this.#r)return 0;let e=this.#r;return e.AUDIO_CAPTURE_FRAMES/(e.AUDIO_CAPTURE_SAMPLE_RATE||48e3)}async send(e,...t){if(this.#U("send OSC messages"),e==="/d_load"||e==="/d_loadDir")throw new Error(`${e} is not supported in SuperSonic (no filesystem). Use loadSynthDef() or send /d_recv with synthdef bytes instead.`);if(e==="/b_read"||e==="/b_readChannel")throw new Error(`${e} is not supported in SuperSonic (no filesystem). Use loadSample() to load audio into a buffer.`);if(e==="/b_write"||e==="/b_close")throw new Error(`${e} is not supported in SuperSonic (no filesystem). Writing audio files is not available in the browser.`);if(e==="/clearSched")throw new Error("/clearSched is not supported in SuperSonic. Bundle scheduling works differently in the browser AudioWorklet environment.");if(e==="/dumpOSC")throw new Error("/dumpOSC is not supported in SuperSonic. Use browser developer tools to inspect OSC messages.");if(e==="/error")throw new Error("/error is not supported in SuperSonic. Error notifications are always enabled.");if(e==="/d_recv"){let a=t[0];if(a instanceof Uint8Array||a instanceof ArrayBuffer){let c=a instanceof ArrayBuffer?new Uint8Array(a):a,l=Y(c)||"unknown";this.loadedSynthDefs.set(l,c)}}if(e==="/d_free")for(let a of t)typeof a=="string"&&this.loadedSynthDefs.delete(a);else e==="/d_freeAll"&&this.loadedSynthDefs.clear();let s=t.map(a=>{if(typeof a=="string")return{type:"s",value:a};if(typeof a=="number")return{type:Number.isInteger(a)?"i":"f",value:a};if(a instanceof Uint8Array||a instanceof ArrayBuffer)return{type:"b",value:a instanceof ArrayBuffer?new Uint8Array(a):a};throw new Error(`Unsupported argument type: ${typeof a}`)}),r={address:e,args:s},n=i.osc.encode(r);if(this.#t.debug||this.#t.debugOscOut){let a=this.#t.activityConsoleLog.oscOut??this.#t.activityConsoleLog.maxLineLength,c=t.map(l=>{if(l instanceof Uint8Array||l instanceof ArrayBuffer)return`<${l.byteLength||l.length} bytes>`;let u=JSON.stringify(l);return u.length>a?u.slice(0,a)+"...":u}).join(", ");console.log(`[OSC \u2192] ${e}${c?" "+c:""}`)}return this.sendOSC(n)}async sendOSC(e,t={}){this.#U("send OSC data");let s=this.#Te(e),r=await this.#Be(s);if(this.#z("mainMessagesSent"),this.#z("mainBytesSent",r.length),this.#u("message:sent",r),this.#C?.tryWrite(r)){this.#z("preschedulerBypassed");return}let n=this.#Re(r);if(this.#t.mode==="postMessage"&&!n){this.#i.port.postMessage({type:"osc",oscData:r});return}let a=this.#r?.scheduler_slot_size;if(n&&a&&r.length>a)throw new Error(`OSC bundle too large to schedule (${r.length} > ${a} bytes). Use immediate timestamp (0 or 1) for large messages, or reduce bundle size.`);let c={...t};n&&(c.audioTimeS=n.audioTimeS,c.currentTimeS=n.currentTimeS),this.#n.send(r,c)}cancelTag(e){this.#U("cancel by tag"),this.#n.cancelTag(e)}cancelSession(e){this.#U("cancel by session"),this.#n.cancelSession(e)}cancelSessionTag(e,t){this.#U("cancel by session and tag"),this.#n.cancelSessionTag(e,t)}cancelAllScheduled(){this.#U("cancel all scheduled"),this.#n.cancelAll()}get node(){return this.#h}get osc(){return this.#n}async loadSynthDef(e){if(!this.#c)throw new Error("SuperSonic not initialized. Call init() first.");let t;if(this.#Ee(e))t=e;else{if(!this.#y)throw new Error("synthdefBaseURL not configured. Either provide a full path or set synthdefBaseURL in constructor options.");t=`${this.#y}${e}.scsyndef`}let s=Y(t);try{let r=await this.#_.fetch(t,{type:"synthdef",name:s}),n=new Uint8Array(r);return await this.send("/d_recv",n),{name:s,size:n.length}}catch(r){throw console.error("[SuperSonic] Failed to load synthdef:",r),r}}async loadSynthDefs(e){if(!this.#c)throw new Error("SuperSonic not initialized. Call init() first.");let t={};await Promise.all(e.map(async r=>{try{await this.loadSynthDef(r),t[r]={success:!0}}catch(n){console.error(`[SuperSonic] Failed to load ${r}:`,n),t[r]={success:!1,error:n.message}}}));let s=Object.values(t).filter(r=>r.success).length;return t}async loadSample(e,t,s=0,r=0){this.#U("load samples");let n=await this.#o.prepareFromFile({bufnum:e,path:t,startFrame:s,numFrames:r});return await this.send("/b_allocPtr",e,n.ptr,n.numFrames,n.numChannels,n.sampleRate,n.uuid),n.allocationComplete}async sync(e=Math.floor(Math.random()*2147483647)){if(!this.#c)throw new Error("SuperSonic not initialized. Call init() first.");let t=new Promise((s,r)=>{let n=setTimeout(()=>{this.#l&&this.#l.delete(e),r(new Error("Timeout waiting for /synced response"))},1e4),a=c=>{clearTimeout(n),this.#l.delete(e),s()};this.#l||(this.#l=new Map),this.#l.set(e,a)});await this.send("/sync",e),await t,this.#t.mode==="postMessage"&&await new Promise(s=>setTimeout(s,this.#t.snapshotIntervalMs*2))}getInfo(){return this.#U("get info"),{sampleRate:this.#s.sampleRate,numBuffers:this.#t.worldOptions.numBuffers,totalMemory:this.#t.memory.totalMemory,wasmHeapSize:this.#t.memory.wasmHeapSize,bufferPoolSize:this.#t.memory.bufferPoolSize,bootTimeMs:this.bootStats.initDuration,capabilities:{...this.#A},version:this.#v}}async shutdown(){!this.#c&&!this.#S||(this.#u("shutdown"),this.#V(),this.#x(),this.#l?.clear(),this.#l=null,this.#n&&(this.#n.cancelAll(),this.#n.terminate(),this.#n=null),this.#i&&(this.#i.disconnect(),this.#i=null),this.#s&&(await this.#s.close(),this.#s=null),this.#o&&(this.#o.destroy(),this.#o=null),this.#d=null,this.#C=null,this.#e=null,this.#c=!1,this.loadedSynthDefs.clear(),this.#m=null,this.#f=null,this.#a=null,this.#r=null,this.#T=null,this.#B=null,this.#M=null,this.#O=null,this.#I=null,this.#b=null,this.#q=0,this.#p=void 0,this.bootStats={initStartTime:null,initDuration:null})}async destroy(){this.#u("destroy"),await this.shutdown(),this.#P=null,this.#R.clear()}async reset(e={}){await this.shutdown(),await this.init(e)}#le(){this.#A={audioWorklet:typeof AudioWorklet<"u",sharedArrayBuffer:typeof SharedArrayBuffer<"u",crossOriginIsolated:window.crossOriginIsolated===!0,atomics:typeof Atomics<"u",webWorker:typeof Worker<"u"};let e=this.#t.mode,t=["audioWorklet","webWorker"];e==="sab"&&t.push("sharedArrayBuffer","crossOriginIsolated","atomics");let s=t.filter(r=>!this.#A[r]);if(s.length>0){let r=new Error(`Missing required features for ${e} mode: ${s.join(", ")}`);throw e==="sab"&&!this.#A.crossOriginIsolated&&(this.#A.sharedArrayBuffer?r.message+=`
13
13
 
14
14
  SharedArrayBuffer is available but cross-origin isolation is not enabled. Please ensure COOP and COEP headers are set correctly:
15
15
  Cross-Origin-Opener-Policy: same-origin
@@ -22,5 +22,5 @@ SharedArrayBuffer is not available. This may be due to:
22
22
  2. Browser doesn't support SharedArrayBuffer
23
23
  3. Browser security settings
24
24
 
25
- Consider using mode: 'postMessage' which doesn't require SharedArrayBuffer.`),r}if(e!=="sab"&&e!=="postMessage")throw new Error(`Invalid mode: '${e}'. Use 'sab' or 'postMessage'.`);return this.#A}#ce(){let e=this.#t.memory;this.#t.mode==="sab"?(this.#f=new WebAssembly.Memory({initial:e.totalPages,maximum:e.totalPages,shared:!0}),this.#e=this.#f.buffer):(this.#f=null,this.#e=null)}#G(){return this.#t.audioContext?this.#s=this.#t.audioContext:this.#s=new AudioContext(this.#t.audioContextOptions),this.#s.addEventListener("statechange",()=>{let e=this.#s?.state;if(!e)return;let t=this.#W;this.#W=e,e==="running"&&(t==="suspended"||t==="interrupted")&&this.#ee(),this.#u("audiocontext:statechange",{state:e}),e==="suspended"?this.#u("audiocontext:suspended"):e==="running"?this.#u("audiocontext:resumed"):e==="interrupted"&&this.#u("audiocontext:interrupted")}),this.#s}#le(){let e=this.#t.mode;this.#o=new k({mode:e,audioContext:this.#s,sharedBuffer:this.#e,bufferPoolConfig:{start:this.#t.memory.bufferPoolOffset,size:this.#t.memory.bufferPoolSize},sampleBaseURL:this.#g,maxBuffers:this.#t.worldOptions.numBuffers,assetLoader:this.#b})}#q(){this.#d=new x({bufferManager:this.#o,getDefaultSampleRate:()=>this.#s?.sampleRate||44100})}async#Z(){if(this.#P)return this.#P;let e=this.#t.wasmUrl.split("/").pop();this.#u("loading:start",{type:"wasm",name:e});let t;try{t=await fetch(this.#t.wasmUrl)}catch(r){throw new Error(`Failed to fetch WASM from ${this.#t.wasmUrl}: ${r.message}`)}if(!t.ok)throw new Error(`Failed to load WASM: ${t.status} ${t.statusText}`);let s=await t.arrayBuffer();return this.#u("loading:complete",{type:"wasm",name:e,size:s.byteLength}),this.#P=s,s}async#Y(e){await J(this.#s.audioWorklet,this.#t.workletUrl),this.#i=new AudioWorkletNode(this.#s,"scsynth-processor",{numberOfInputs:0,numberOfOutputs:1,outputChannelCount:[2]}),this.#t.autoConnect&&this.#i.connect(this.#s.destination),this.#h=this.#ue(),this.#i.port.start(),this.#fe();let t=this.#t.mode;this.#i.port.postMessage({type:"init",mode:t,sharedBuffer:t==="sab"?this.#e:null,snapshotIntervalMs:this.#t.snapshotIntervalMs});let s={type:"loadWasm",wasmBytes:e,worldOptions:this.#t.worldOptions,sampleRate:this.#s.sampleRate};t==="sab"?s.wasmMemory=this.#f:s.memoryPages=this.#t.memoryPages||1280,this.#i.port.postMessage(s),await this.#he(),this.#o.setWorkletPort(this.#i.port)}#ue(){let e=this.#i;return Object.freeze({connect:(...t)=>e.connect(...t),disconnect:(...t)=>e.disconnect(...t),get context(){return e.context},get numberOfOutputs(){return e.numberOfOutputs},get channelCount(){return e.channelCount}})}async#Q(){this.#n=new M(this.#t.workerBaseURL),this.#n.onRawOSC(t=>{this.#u("message:raw",t)}),this.#n.onParsedOSC(t=>{if(t.address==="/supersonic/buffer/freed")this.#o?.handleBufferFreed(t.args);else if(t.address==="/supersonic/buffer/allocated")this.#o?.handleBufferAllocated(t.args);else if(t.address==="/supersonic/synthdef/loaded"){let s=t.args[0]}else if(t.address==="/synced"&&t.args.length>0){let s=t.args[0];this.#l&&this.#l.has(s)&&this.#l.get(s)(t)}if(this.#u("message",t),this.#t.debug||this.#t.debugOscIn){let s=this.#t.activityConsoleLog.oscIn??this.#t.activityConsoleLog.maxLineLength,r=t.args?.map(n=>{let a=JSON.stringify(n);return a.length>s?a.slice(0,s)+"...":a}).join(", ")||"";console.log(`[\u2190 OSC] ${t.address}${r?" "+r:""}`)}}),this.#n.onDebugMessage(t=>{let s=this.#t.activityEvent.scsynth??this.#t.activityEvent.maxLineLength;if(s>0&&t.text&&t.text.length>s&&(t={...t,text:t.text.slice(0,s)+"..."}),this.#u("debug",t),this.#t.debug||this.#t.debugScsynth){let r=this.#t.activityConsoleLog.scsynth??this.#t.activityConsoleLog.maxLineLength,n=t.text.length>r?t.text.slice(0,r)+"...":t.text;console.log(`[synth] ${n}`)}}),this.#n.onError((t,s)=>{console.error(`[SuperSonic] ${s} error:`,t),this.#u("error",new Error(`${s}: ${t}`))}),this.#t.mode==="sab"?await this.#n.init({mode:"sab",sharedBuffer:this.#e,ringBufferBase:this.#a,bufferConstants:this.#r,preschedulerCapacity:this.#t.preschedulerCapacity}):await this.#n.init({mode:"postMessage",workletPort:this.#i.port,preschedulerCapacity:this.#t.preschedulerCapacity})}async#j(){this.#c=!0,this.#w=!1,this.bootStats.initDuration=performance.now()-this.bootStats.initStartTime,this.#u("ready",{capabilities:this.#A,bootStats:this.bootStats})}#he(){return new Promise((e,t)=>{let s=setTimeout(()=>{t(new Error("AudioWorklet initialization timeout"))},5e3),r=async n=>{if(n.data.type!=="debug"){if(n.data.type==="error"){console.error("[AudioWorklet] Error:",n.data.error),clearTimeout(s),this.#i.port.removeEventListener("message",r),t(new Error(n.data.error||"AudioWorklet error"));return}n.data.type==="initialized"&&(clearTimeout(s),this.#i.port.removeEventListener("message",r),n.data.success?(n.data.ringBufferBase!==void 0?this.#a=n.data.ringBufferBase:console.warn("[SuperSonic] Warning: ringBufferBase not provided by worklet"),n.data.bufferConstants!==void 0?(this.#r=n.data.bufferConstants,this.#t.mode==="sab"&&(this.#Se(),this.#ge()),await this.#Ee(),this.#_e()):console.warn("[SuperSonic] Warning: bufferConstants not provided by worklet"),this.#t.mode==="postMessage"&&n.data.initialSnapshot&&(this.#_=n.data.initialSnapshot),e()):t(new Error(n.data.error||"AudioWorklet initialization failed")))}};this.#i.port.addEventListener("message",r),this.#i.port.start()})}#fe(){this.#i.port.addEventListener("message",e=>{let{data:t}=e;switch(t.type){case"error":console.error("[Worklet] Error:",t.error),t.diagnostics&&(console.error("[Worklet] Diagnostics:",t.diagnostics),console.table(t.diagnostics)),this.#u("error",new Error(t.error));break;case"process_debug":break;case"debug":break;case"version":this.#v=t.version;break;case"metricsSnapshot":if(this.#D&&t.requestId===this.#D.id){let s=this.#_?new Uint32Array(this.#_,0,32):null;this.#D.resolve(s),this.#D=null}break;case"snapshot":t.buffer&&(this.#_=t.buffer,this.#H=t.snapshotsSent);break;default:break}})}#K(e){return{workletProcessCount:e[0],workletMessagesProcessed:e[1],workletMessagesDropped:e[2],workletSchedulerDepth:e[3],workletSchedulerMax:e[4],workletSchedulerDropped:e[5],workletSequenceGaps:e[24],preschedulerPending:e[6],preschedulerPeak:e[7],preschedulerSent:e[8],preschedulerRetriesSucceeded:e[9],preschedulerRetriesFailed:e[10],preschedulerBundlesScheduled:e[11],preschedulerEventsCancelled:e[12],preschedulerTotalDispatches:e[13],preschedulerMessagesRetried:e[14],preschedulerRetryQueueSize:e[15],preschedulerRetryQueueMax:e[16],preschedulerBypassed:e[25],oscInMessagesReceived:e[17],oscInMessagesDropped:e[18],oscInBytesReceived:e[19],debugMessagesReceived:e[20],debugBytesReceived:e[21],mainMessagesSent:e[22],mainBytesSent:e[23]}}#de(){return this.#B?this.#K(this.#B):null}async#Be(e=1e3){if(!this.#i)return null;this.#D&&this.#D.resolve(null);let t=Date.now()+Math.random();return new Promise(s=>{let r=setTimeout(()=>{this.#D?.id===t&&(this.#D=null,s(null))},e);this.#D={id:t,resolve:n=>{clearTimeout(r),s(n)}},this.#i.port.postMessage({type:"getMetrics",requestId:t})})}#pe(){if(!this.#T||!this.#r||!this.#a)return null;let e=this.#a+this.#r.CONTROL_START,t=this.#T,s=Atomics.load(t,(e+0)/4),r=Atomics.load(t,(e+4)/4),n=Atomics.load(t,(e+8)/4),a=Atomics.load(t,(e+12)/4),c=Atomics.load(t,(e+16)/4),l=Atomics.load(t,(e+20)/4),u=(s-r+this.#r.IN_BUFFER_SIZE)%this.#r.IN_BUFFER_SIZE,f=(n-a+this.#r.OUT_BUFFER_SIZE)%this.#r.OUT_BUFFER_SIZE,h=(c-l+this.#r.DEBUG_BUFFER_SIZE)%this.#r.DEBUG_BUFFER_SIZE;return{inBufferUsed:{bytes:u,percentage:u/this.#r.IN_BUFFER_SIZE*100},outBufferUsed:{bytes:f,percentage:f/this.#r.OUT_BUFFER_SIZE*100},debugBufferUsed:{bytes:h,percentage:h/this.#r.DEBUG_BUFFER_SIZE*100}}}#L(e,t=1){if(!this.#B)return;let s={mainMessagesSent:22,mainBytesSent:23,preschedulerBypassed:25};Atomics.add(this.#B,s[e],t)}#me(){if(!this.#_)return;let e=this.#n?.getPreschedulerMetrics();if(!e)return;let t=new Uint32Array(this.#_,0,32),s=6,r=16-s+1;t.set(e.subarray(s,s+r),s)}#X(){let e=performance.now(),t;if(this.mode==="postMessage")if(this.#me(),this.#_){let r=new Uint32Array(this.#_,0,32);t=this.#K(r)}else t={};else{t=this.#de()||{};let r=this.#pe();r&&Object.assign(t,r)}if(t.driftOffsetMs=this.#ye(),t.audioContextState=this.#s?.state||"unknown",this.#o){let r=this.#o.getStats();t.bufferPoolUsedBytes=r.used.size,t.bufferPoolAvailableBytes=r.available,t.bufferPoolAllocations=r.used.count}t.loadedSynthDefs=this.loadedSynthDefs?.size||0;let s=performance.now()-e;return s>1&&console.warn(`[SuperSonic] Slow metrics gathering: ${s.toFixed(2)}ms`),t}#N(){this.#x();let e=this.mode==="postMessage"?1e3:this.#V;this.#k=setInterval(()=>{if(!(!this.#R.has("metrics")||this.#R.get("metrics").size===0)){if(this.#F){console.warn(`[SuperSonic] Metrics gathering took >${e}ms, skipping this interval`);return}this.#F=!0;try{let t=this.#X();this.#u("metrics",t)}catch(t){console.error("[SuperSonic] Metrics gathering failed:",t)}finally{this.#F=!1}}},e)}#x(){this.#k&&(clearInterval(this.#k),this.#k=null)}#U(e="perform this operation"){if(!this.#c)throw new Error(`SuperSonic not initialized. Call init() before attempting to ${e}.`)}#Se(){if(!this.#e||!this.#a||!this.#r){console.warn("[SuperSonic] Cannot initialize shared views - missing buffer info");return}this.#T=new Int32Array(this.#e);let e=this.#a+this.#r.METRICS_START;this.#B=new Uint32Array(this.#e,e,this.#r.METRICS_SIZE/4),this.#M=new Float64Array(this.#e,this.#a+this.#r.NTP_START_TIME_START,1),this.#O=new Int32Array(this.#e,this.#a+this.#r.DRIFT_OFFSET_START,1),this.#I=new Int32Array(this.#e,this.#a+this.#r.GLOBAL_OFFSET_START,1)}#ge(){this.#C=new F({sharedBuffer:this.#e,ringBufferBase:this.#a,bufferConstants:this.#r,getAudioContextTime:()=>this.#s?.currentTime??null,getNTPStartTime:()=>this.#M?.[0]??0})}#we(e){return e.includes("/")||e.includes("://")}#Re(){return this.#o?.getStats()}async#Ee(){if(!this.#r||!this.#s)return;let e;for(;e=this.#s.getOutputTimestamp(),!(e.contextTime>0);)await new Promise(n=>setTimeout(n,50));let t=performance.timeOrigin+e.performanceTime,s=L(t),r=Q(s,e.contextTime);this.#t.mode==="sab"?this.#M[0]=r:this.#i.port.postMessage({type:"setNTPStartTime",ntpStartTime:r}),this.#p=r}#J(){if(!this.#r||!this.#s||this.#p===void 0)return;let e=this.#s.getOutputTimestamp(),t=performance.timeOrigin+e.performanceTime,r=L(t)-this.#p,n=de(r,e.contextTime);this.#$=n,this.#t.mode==="sab"?Atomics.store(this.#O,0,n):this.#i.port.postMessage({type:"setDriftOffset",driftOffsetMs:n})}#ye(){return this.#O?Atomics.load(this.#O,0):0}#ee(){if(!this.#s||!this.#M||!this.#O)return;let e=this.#s.getOutputTimestamp();if(!e||e.contextTime<=0)return;let t=performance.timeOrigin+e.performanceTime,s=L(t),r=Q(s,e.contextTime);this.#M[0]=r,this.#p=r,this.#J()}#_e(){this.#z(),this.#S=setInterval(()=>{this.#J()},15e3)}#z(){this.#S&&(clearInterval(this.#S),this.#S=null)}#be(e){if(e instanceof Uint8Array)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);throw new Error("oscData must be ArrayBuffer or Uint8Array")}async#Ae(e){let t={metadata:!0,unpackSingleArgs:!1};try{let s=i.osc.decode(e,t),{packet:r,changed:n}=await this.#d.rewritePacket(s);return n?i.osc.encode(r):e}catch(s){throw console.error("[SuperSonic] Failed to prepare OSC packet:",s),s}}#Te(e){if(e.length<16||String.fromCharCode.apply(null,e.slice(0,8))!=="#bundle\0")return null;let s=this.#M?.[0]??this.#p??0;if(s===0)return console.warn("[SuperSonic] NTP start time not yet initialized"),null;let n=(this.#O?Atomics.load(this.#O,0):this.#$)/1e3,c=(this.#I?Atomics.load(this.#I,0):this.#te)/1e3,l=s+n+c,u=new DataView(e.buffer,e.byteOffset),f=u.getUint32(8,!1),h=u.getUint32(12,!1);if(f===0&&(h===0||h===1))return null;let p=f+h/4294967296-l,m=this.#s.currentTime;return{audioTimeS:p,currentTimeS:m}}};export{Re as SuperSonic};
25
+ Consider using mode: 'postMessage' which doesn't require SharedArrayBuffer.`),r}if(e!=="sab"&&e!=="postMessage")throw new Error(`Invalid mode: '${e}'. Use 'sab' or 'postMessage'.`);return this.#A}#ue(){let e=this.#t.memory;this.#t.mode==="sab"?(this.#f=new WebAssembly.Memory({initial:e.totalPages,maximum:e.totalPages,shared:!0}),this.#e=this.#f.buffer):(this.#f=null,this.#e=null)}#Z(){return this.#t.audioContext?this.#s=this.#t.audioContext:this.#s=new AudioContext(this.#t.audioContextOptions),this.#s.addEventListener("statechange",()=>{let e=this.#s?.state;if(!e)return;let t=this.#G;this.#G=e,e==="running"&&(t==="suspended"||t==="interrupted")&&this.#se(),this.#u("audiocontext:statechange",{state:e}),e==="suspended"?this.#u("audiocontext:suspended"):e==="running"?this.#u("audiocontext:resumed"):e==="interrupted"&&this.#u("audiocontext:interrupted")}),this.#s}#he(){let e=this.#t.mode;this.#o=new k({mode:e,audioContext:this.#s,sharedBuffer:this.#e,bufferPoolConfig:{start:this.#t.memory.bufferPoolOffset,size:this.#t.memory.bufferPoolSize},sampleBaseURL:this.#w,maxBuffers:this.#t.worldOptions.numBuffers,assetLoader:this.#_})}#Y(){this.#d=new x({bufferManager:this.#o,getDefaultSampleRate:()=>this.#s?.sampleRate||44100})}async#Q(){if(this.#P)return this.#P;let e=this.#t.wasmUrl.split("/").pop();this.#u("loading:start",{type:"wasm",name:e});let t;try{t=await fetch(this.#t.wasmUrl)}catch(r){throw new Error(`Failed to fetch WASM from ${this.#t.wasmUrl}: ${r.message}`)}if(!t.ok)throw new Error(`Failed to load WASM: ${t.status} ${t.statusText}`);let s=await t.arrayBuffer();return this.#u("loading:complete",{type:"wasm",name:e,size:s.byteLength}),this.#P=s,s}async#j(e){await J(this.#s.audioWorklet,this.#t.workletUrl),this.#i=new AudioWorkletNode(this.#s,"scsynth-processor",{numberOfInputs:0,numberOfOutputs:1,outputChannelCount:[2]}),this.#t.autoConnect&&this.#i.connect(this.#s.destination),this.#h=this.#fe(),this.#i.port.start(),this.#pe();let t=this.#t.mode;this.#i.port.postMessage({type:"init",mode:t,sharedBuffer:t==="sab"?this.#e:null,snapshotIntervalMs:this.#t.snapshotIntervalMs});let s={type:"loadWasm",wasmBytes:e,worldOptions:this.#t.worldOptions,sampleRate:this.#s.sampleRate};t==="sab"?s.wasmMemory=this.#f:s.memoryPages=this.#t.memoryPages||1280,this.#i.port.postMessage(s),await this.#de(),this.#o.setWorkletPort(this.#i.port)}#fe(){let e=this.#i;return Object.freeze({connect:(...t)=>e.connect(...t),disconnect:(...t)=>e.disconnect(...t),get context(){return e.context},get numberOfOutputs(){return e.numberOfOutputs},get channelCount(){return e.channelCount}})}async#K(){this.#n=new M(this.#t.workerBaseURL),this.#n.onRawOSC(t=>{this.#u("message:raw",t)}),this.#n.onParsedOSC(t=>{if(t.address==="/supersonic/buffer/freed")this.#o?.handleBufferFreed(t.args);else if(t.address==="/supersonic/buffer/allocated")this.#o?.handleBufferAllocated(t.args);else if(t.address==="/supersonic/synthdef/loaded"){let s=t.args[0]}else if(t.address==="/synced"&&t.args.length>0){let s=t.args[0];this.#l&&this.#l.has(s)&&this.#l.get(s)(t)}if(this.#u("message",t),this.#t.debug||this.#t.debugOscIn){let s=this.#t.activityConsoleLog.oscIn??this.#t.activityConsoleLog.maxLineLength,r=t.args?.map(n=>{let a=JSON.stringify(n);return a.length>s?a.slice(0,s)+"...":a}).join(", ")||"";console.log(`[\u2190 OSC] ${t.address}${r?" "+r:""}`)}}),this.#n.onDebugMessage(t=>{let s=this.#t.activityEvent.scsynth??this.#t.activityEvent.maxLineLength;if(s>0&&t.text&&t.text.length>s&&(t={...t,text:t.text.slice(0,s)+"..."}),this.#u("debug",t),this.#t.debug||this.#t.debugScsynth){let r=this.#t.activityConsoleLog.scsynth??this.#t.activityConsoleLog.maxLineLength,n=t.text.length>r?t.text.slice(0,r)+"...":t.text;console.log(`[synth] ${n}`)}}),this.#n.onError((t,s)=>{console.error(`[SuperSonic] ${s} error:`,t),this.#u("error",new Error(`${s}: ${t}`))}),this.#t.mode==="sab"?await this.#n.init({mode:"sab",sharedBuffer:this.#e,ringBufferBase:this.#a,bufferConstants:this.#r,preschedulerCapacity:this.#t.preschedulerCapacity}):(await this.#n.init({mode:"postMessage",workletPort:this.#i.port,preschedulerCapacity:this.#t.preschedulerCapacity,earlyDebugMessages:this.#L}),this.#N=t=>{this.#n.handleDebugRaw(t)},this.#L=[])}async#X(){this.#c=!0,this.#S=!1,this.bootStats.initDuration=performance.now()-this.bootStats.initStartTime,this.#u("ready",{capabilities:this.#A,bootStats:this.bootStats})}#de(){return new Promise((e,t)=>{let s=setTimeout(()=>{t(new Error("AudioWorklet initialization timeout"))},5e3),r=async n=>{if(n.data.type!=="debug"){if(n.data.type==="error"){console.error("[AudioWorklet] Error:",n.data.error),clearTimeout(s),this.#i.port.removeEventListener("message",r),t(new Error(n.data.error||"AudioWorklet error"));return}n.data.type==="initialized"&&(clearTimeout(s),this.#i.port.removeEventListener("message",r),n.data.success?(n.data.ringBufferBase!==void 0?this.#a=n.data.ringBufferBase:console.warn("[SuperSonic] Warning: ringBufferBase not provided by worklet"),n.data.bufferConstants!==void 0?(this.#r=n.data.bufferConstants,this.#t.mode==="sab"&&(this.#Se(),this.#ye()),await this.#be(),this.#Ae()):console.warn("[SuperSonic] Warning: bufferConstants not provided by worklet"),this.#t.mode==="postMessage"&&n.data.initialSnapshot&&(this.#b=n.data.initialSnapshot),e()):t(new Error(n.data.error||"AudioWorklet initialization failed")))}};this.#i.port.addEventListener("message",r),this.#i.port.start()})}#pe(){this.#i.port.addEventListener("message",e=>{let{data:t}=e;switch(t.type){case"error":console.error("[Worklet] Error:",t.error),t.diagnostics&&(console.error("[Worklet] Diagnostics:",t.diagnostics),console.table(t.diagnostics)),this.#u("error",new Error(t.error));break;case"process_debug":break;case"debug":break;case"version":this.#v=t.version;break;case"metricsSnapshot":if(this.#D&&t.requestId===this.#D.id){let s=this.#b?new Uint32Array(this.#b,0,32):null;this.#D.resolve(s),this.#D=null}break;case"snapshot":t.buffer&&(this.#b=t.buffer,this.#q=t.snapshotsSent);break;case"debugRawBatch":this.#N?this.#N(t):this.#L.push(t);break;default:break}})}#J(e){return{workletProcessCount:e[0],workletMessagesProcessed:e[1],workletMessagesDropped:e[2],workletSchedulerDepth:e[3],workletSchedulerMax:e[4],workletSchedulerDropped:e[5],workletSequenceGaps:e[24],preschedulerPending:e[6],preschedulerPeak:e[7],preschedulerSent:e[8],preschedulerRetriesSucceeded:e[9],preschedulerRetriesFailed:e[10],preschedulerBundlesScheduled:e[11],preschedulerEventsCancelled:e[12],preschedulerTotalDispatches:e[13],preschedulerMessagesRetried:e[14],preschedulerRetryQueueSize:e[15],preschedulerRetryQueueMax:e[16],preschedulerBypassed:e[25],oscInMessagesReceived:e[17],oscInMessagesDropped:e[18],oscInBytesReceived:e[19],debugMessagesReceived:e[20],debugBytesReceived:e[21],mainMessagesSent:e[22],mainBytesSent:e[23]}}#me(){return this.#B?this.#J(this.#B):null}async#Oe(e=1e3){if(!this.#i)return null;this.#D&&this.#D.resolve(null);let t=Date.now()+Math.random();return new Promise(s=>{let r=setTimeout(()=>{this.#D?.id===t&&(this.#D=null,s(null))},e);this.#D={id:t,resolve:n=>{clearTimeout(r),s(n)}},this.#i.port.postMessage({type:"getMetrics",requestId:t})})}#ge(){if(!this.#T||!this.#r||!this.#a)return null;let e=this.#a+this.#r.CONTROL_START,t=this.#T,s=Atomics.load(t,(e+0)/4),r=Atomics.load(t,(e+4)/4),n=Atomics.load(t,(e+8)/4),a=Atomics.load(t,(e+12)/4),c=Atomics.load(t,(e+16)/4),l=Atomics.load(t,(e+20)/4),u=(s-r+this.#r.IN_BUFFER_SIZE)%this.#r.IN_BUFFER_SIZE,f=(n-a+this.#r.OUT_BUFFER_SIZE)%this.#r.OUT_BUFFER_SIZE,h=(c-l+this.#r.DEBUG_BUFFER_SIZE)%this.#r.DEBUG_BUFFER_SIZE;return{inBufferUsed:{bytes:u,percentage:u/this.#r.IN_BUFFER_SIZE*100},outBufferUsed:{bytes:f,percentage:f/this.#r.OUT_BUFFER_SIZE*100},debugBufferUsed:{bytes:h,percentage:h/this.#r.DEBUG_BUFFER_SIZE*100}}}#z(e,t=1){if(!this.#B)return;let s={mainMessagesSent:22,mainBytesSent:23,preschedulerBypassed:25};Atomics.add(this.#B,s[e],t)}#we(){if(!this.#b)return;let e=this.#n?.getPreschedulerMetrics();if(!e)return;let t=new Uint32Array(this.#b,0,32),s=6,r=16-s+1;t.set(e.subarray(s,s+r),s)}#ee(){let e=performance.now(),t;if(this.mode==="postMessage")if(this.#we(),this.#b){let r=new Uint32Array(this.#b,0,32);t=this.#J(r)}else t={};else{t=this.#me()||{};let r=this.#ge();r&&Object.assign(t,r)}if(t.driftOffsetMs=this.#_e(),t.audioContextState=this.#s?.state||"unknown",this.#o){let r=this.#o.getStats();t.bufferPoolUsedBytes=r.used.size,t.bufferPoolAvailableBytes=r.available,t.bufferPoolAllocations=r.used.count}t.loadedSynthDefs=this.loadedSynthDefs?.size||0;let s=performance.now()-e;return s>1&&console.warn(`[SuperSonic] Slow metrics gathering: ${s.toFixed(2)}ms`),t}#$(){this.#x();let e=this.mode==="postMessage"?1e3:this.#H;this.#k=setInterval(()=>{if(!(!this.#R.has("metrics")||this.#R.get("metrics").size===0)){if(this.#F){console.warn(`[SuperSonic] Metrics gathering took >${e}ms, skipping this interval`);return}this.#F=!0;try{let t=this.#ee();this.#u("metrics",t)}catch(t){console.error("[SuperSonic] Metrics gathering failed:",t)}finally{this.#F=!1}}},e)}#x(){this.#k&&(clearInterval(this.#k),this.#k=null)}#U(e="perform this operation"){if(!this.#c)throw new Error(`SuperSonic not initialized. Call init() before attempting to ${e}.`)}#Se(){if(!this.#e||!this.#a||!this.#r){console.warn("[SuperSonic] Cannot initialize shared views - missing buffer info");return}this.#T=new Int32Array(this.#e);let e=this.#a+this.#r.METRICS_START;this.#B=new Uint32Array(this.#e,e,this.#r.METRICS_SIZE/4),this.#M=new Float64Array(this.#e,this.#a+this.#r.NTP_START_TIME_START,1),this.#O=new Int32Array(this.#e,this.#a+this.#r.DRIFT_OFFSET_START,1),this.#I=new Int32Array(this.#e,this.#a+this.#r.GLOBAL_OFFSET_START,1)}#ye(){this.#C=new F({sharedBuffer:this.#e,ringBufferBase:this.#a,bufferConstants:this.#r,getAudioContextTime:()=>this.#s?.currentTime??null,getNTPStartTime:()=>this.#M?.[0]??0})}#Ee(e){return e.includes("/")||e.includes("://")}#De(){return this.#o?.getStats()}async#be(){if(!this.#r||!this.#s)return;let e;for(;e=this.#s.getOutputTimestamp(),!(e.contextTime>0);)await new Promise(n=>setTimeout(n,50));let t=performance.timeOrigin+e.performanceTime,s=L(t),r=Q(s,e.contextTime);this.#t.mode==="sab"?this.#M[0]=r:this.#i.port.postMessage({type:"setNTPStartTime",ntpStartTime:r}),this.#p=r}#te(){if(!this.#r||!this.#s||this.#p===void 0)return;let e=this.#s.getOutputTimestamp(),t=performance.timeOrigin+e.performanceTime,r=L(t)-this.#p,n=de(r,e.contextTime);this.#W=n,this.#t.mode==="sab"?Atomics.store(this.#O,0,n):this.#i.port.postMessage({type:"setDriftOffset",driftOffsetMs:n})}#_e(){return this.#O?Atomics.load(this.#O,0):0}#se(){if(!this.#s||!this.#M||!this.#O)return;let e=this.#s.getOutputTimestamp();if(!e||e.contextTime<=0)return;let t=performance.timeOrigin+e.performanceTime,s=L(t),r=Q(s,e.contextTime);this.#M[0]=r,this.#p=r,this.#te()}#Ae(){this.#V(),this.#g=setInterval(()=>{this.#te()},15e3)}#V(){this.#g&&(clearInterval(this.#g),this.#g=null)}#Te(e){if(e instanceof Uint8Array)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);throw new Error("oscData must be ArrayBuffer or Uint8Array")}async#Be(e){let t={metadata:!0,unpackSingleArgs:!1};try{let s=i.osc.decode(e,t),{packet:r,changed:n}=await this.#d.rewritePacket(s);return n?i.osc.encode(r):e}catch(s){throw console.error("[SuperSonic] Failed to prepare OSC packet:",s),s}}#Re(e){if(e.length<16||String.fromCharCode.apply(null,e.slice(0,8))!=="#bundle\0")return null;let s=this.#M?.[0]??this.#p??0;if(s===0)return console.warn("[SuperSonic] NTP start time not yet initialized"),null;let n=(this.#O?Atomics.load(this.#O,0):this.#W)/1e3,c=(this.#I?Atomics.load(this.#I,0):this.#re)/1e3,l=s+n+c,u=new DataView(e.buffer,e.byteOffset),f=u.getUint32(8,!1),h=u.getUint32(12,!1);if(f===0&&(h===0||h===1))return null;let p=f+h/4294967296-l,m=this.#s.currentTime;return{audioTimeS:p,currentTimeS:m}}};export{Re as SuperSonic};
26
26
  /*! osc.js 2.4.5, Copyright 2024 Colin Clark | github.com/colinbdclark/osc.js */
Binary file
@@ -1,2 +1,2 @@
1
- (()=>{var p=class extends AudioWorkletProcessor{constructor(){super(),this.mode="sab",this.sharedBuffer=null,this.wasmModule=null,this.wasmInstance=null,this.isInitialized=!1,this.processCallCount=0,this.lastStatusCheck=0,this.ringBufferBase=null,this.audioView=null,this.lastAudioBufferPtr=0,this.lastWasmBufferSize=0,this.lastTreeVersion=-1,this.treeSnapshotsSent=0,this.lastTreeSendTime=-1,this.treeSnapshotMinInterval=.025,this.atomicView=null,this.uint8View=null,this.dataView=null,this.localClockOffsetView=null,this.bufferConstants=null,this.CONTROL_INDICES=null,this.metricsView=null,this.STATUS_FLAGS={OK:0,BUFFER_FULL:1,OVERRUN:2,WASM_ERROR:4,FRAGMENTED_MSG:8},this.oscQueue=[],this.port.onmessage=this.handleMessage.bind(this)}loadBufferConstants(){if(!this.wasmInstance||!this.wasmInstance.exports.get_buffer_layout)throw new Error("WASM instance does not export get_buffer_layout");let e=this.wasmInstance.exports.get_buffer_layout(),t=this.wasmMemory;if(!t)throw new Error("WASM memory not available");let s=new Uint32Array(t.buffer,e,34),o=new Uint8Array(t.buffer,e,140);if(this.bufferConstants={IN_BUFFER_START:s[0],IN_BUFFER_SIZE:s[1],OUT_BUFFER_START:s[2],OUT_BUFFER_SIZE:s[3],DEBUG_BUFFER_START:s[4],DEBUG_BUFFER_SIZE:s[5],CONTROL_START:s[6],CONTROL_SIZE:s[7],METRICS_START:s[8],METRICS_SIZE:s[9],NODE_TREE_START:s[10],NODE_TREE_SIZE:s[11],NODE_TREE_HEADER_SIZE:s[12],NODE_TREE_ENTRY_SIZE:s[13],NODE_TREE_DEF_NAME_SIZE:s[14],NODE_TREE_MAX_NODES:s[15],NTP_START_TIME_START:s[16],NTP_START_TIME_SIZE:s[17],DRIFT_OFFSET_START:s[18],DRIFT_OFFSET_SIZE:s[19],GLOBAL_OFFSET_START:s[20],GLOBAL_OFFSET_SIZE:s[21],AUDIO_CAPTURE_START:s[22],AUDIO_CAPTURE_SIZE:s[23],AUDIO_CAPTURE_HEADER_SIZE:s[24],AUDIO_CAPTURE_FRAMES:s[25],AUDIO_CAPTURE_CHANNELS:s[26],AUDIO_CAPTURE_SAMPLE_RATE:s[27],TOTAL_BUFFER_SIZE:s[28],MAX_MESSAGE_SIZE:s[29],MESSAGE_MAGIC:s[30],PADDING_MAGIC:s[31],scheduler_slot_size:s[32],scheduler_slot_count:s[33],DEBUG_PADDING_MARKER:o[136],MESSAGE_HEADER_SIZE:16},this.bufferConstants.MESSAGE_MAGIC!==3735928559)throw new Error("Invalid buffer constants from WASM")}calculateBufferIndices(e){if(!this.bufferConstants)throw new Error("Buffer constants not loaded. Call loadBufferConstants() first.");let t=this.bufferConstants.CONTROL_START,s=this.bufferConstants.METRICS_START;if(this.CONTROL_INDICES={IN_HEAD:(e+t+0)/4,IN_TAIL:(e+t+4)/4,OUT_HEAD:(e+t+8)/4,OUT_TAIL:(e+t+12)/4,DEBUG_HEAD:(e+t+16)/4,DEBUG_TAIL:(e+t+20)/4,IN_SEQUENCE:(e+t+24)/4,OUT_SEQUENCE:(e+t+28)/4,DEBUG_SEQUENCE:(e+t+32)/4,STATUS_FLAGS:(e+t+36)/4,IN_WRITE_LOCK:(e+t+40)/4},this.mode==="sab"){let o=e+s;this.metricsView=new Uint32Array(this.sharedBuffer,o,this.bufferConstants.METRICS_SIZE/4)}else{this.atomicView=new Int32Array(this.wasmMemory.buffer),this.uint8View=new Uint8Array(this.wasmMemory.buffer),this.dataView=new DataView(this.wasmMemory.buffer);let o=e+s;this.metricsView=new Uint32Array(this.wasmMemory.buffer,o,this.bufferConstants.METRICS_SIZE/4)}}writeWorldOptionsToMemory(){if(!this.worldOptions||!this.wasmMemory)return;let e=this.ringBufferBase+65536,t=new Uint32Array(this.wasmMemory.buffer,e,32),s=new Float32Array(this.wasmMemory.buffer,e,32);t[0]=this.worldOptions.numBuffers||1024,t[1]=this.worldOptions.maxNodes||1024,t[2]=this.worldOptions.maxGraphDefs||1024,t[3]=this.worldOptions.maxWireBufs||64,t[4]=this.worldOptions.numAudioBusChannels||128,t[5]=this.worldOptions.numInputBusChannels||0,t[6]=this.worldOptions.numOutputBusChannels||2,t[7]=this.worldOptions.numControlBusChannels||4096,t[8]=this.worldOptions.bufLength||128,t[9]=this.worldOptions.realTimeMemorySize||16384,t[10]=this.worldOptions.numRGens||64,t[11]=this.worldOptions.realTime?1:0,t[12]=this.worldOptions.memoryLocking?1:0,t[13]=this.worldOptions.loadGraphDefs||0,t[14]=this.worldOptions.preferredSampleRate||0,t[15]=this.worldOptions.verbosity||0}js_debug(e){if(!(!this.uint8View||!this.atomicView||!this.CONTROL_INDICES||!this.ringBufferBase))try{let t=this.bufferConstants.DEBUG_BUFFER_START,s=this.bufferConstants.DEBUG_BUFFER_SIZE,o=this.bufferConstants.DEBUG_PADDING_MARKER,a="[JS] "+e+`
2
- `,n=new TextEncoder().encode(a);if(n.length>s)return;let _=this.CONTROL_INDICES.DEBUG_HEAD,r=this.atomicLoad(_),h=s-r,f=r;n.length>h&&(this.uint8View[this.ringBufferBase+t+r]=o,f=0);let S=this.ringBufferBase+t;for(let c=0;c<n.length;c++)this.uint8View[S+f+c]=n[c];let E=f+n.length;this.atomicStore(_,E)}catch{}}atomicLoad(e){return this.mode==="sab"?Atomics.load(this.atomicView,e):this.atomicView[e]}atomicStore(e,t){this.mode==="sab"?Atomics.store(this.atomicView,e,t):this.atomicView[e]=t}drainOscQueue(){if(this.oscQueue.length===0)return;let e=this.bufferConstants.IN_BUFFER_START,t=this.bufferConstants.IN_BUFFER_SIZE,s=this.bufferConstants.MESSAGE_MAGIC,o=this.bufferConstants.MESSAGE_HEADER_SIZE,a=this.ringBufferBase+e;for(;this.oscQueue.length>0;){let i=this.oscQueue[0],n=i.byteLength,r=o+n+3&-4,h=this.atomicLoad(this.CONTROL_INDICES.IN_HEAD),f=this.atomicLoad(this.CONTROL_INDICES.IN_TAIL),S;if(h>=f?S=t-h+f-1:S=f-h-1,r>S)break;this.oscQueue.shift();let E=h;this.dataView.setUint32(a+E,s,!0),this.dataView.setUint32(a+E+4,r,!0);let c=this.atomicLoad(this.CONTROL_INDICES.IN_SEQUENCE);this.dataView.setUint32(a+E+8,c,!0),this.dataView.setUint32(a+E+12,0,!0),this.atomicStore(this.CONTROL_INDICES.IN_SEQUENCE,c+1);let m=new Uint8Array(i);for(let l=0;l<n;l++)this.uint8View[a+E+o+l]=m[l];let u=(E+r)%t;this.atomicStore(this.CONTROL_INDICES.IN_HEAD,u)}}readOscReplies(){let e=this.bufferConstants.OUT_BUFFER_START,t=this.bufferConstants.OUT_BUFFER_SIZE,s=this.bufferConstants.MESSAGE_MAGIC,o=this.bufferConstants.PADDING_MAGIC,a=this.bufferConstants.MESSAGE_HEADER_SIZE,i=this.ringBufferBase+e,n=[],_=this.atomicLoad(this.CONTROL_INDICES.OUT_HEAD),r=this.atomicLoad(this.CONTROL_INDICES.OUT_TAIL);for(;_!==r;){let h=this.dataView.getUint32(i+r,!0);if(h===o){r=0;continue}if(h!==s){r=(r+1)%t;continue}let f=this.dataView.getUint32(i+r+4,!0),S=this.dataView.getUint32(i+r+8,!0);if(f<a||f>t){r=(r+1)%t;continue}let E=f-a,c=new Uint8Array(E);for(let u=0;u<E;u++)c[u]=this.uint8View[i+r+a+u];n.push({oscData:c.buffer,sequence:S});let m=f+3&-4;r=(r+m)%t}this.atomicStore(this.CONTROL_INDICES.OUT_TAIL,r),n.length>0&&this.port.postMessage({type:"oscReplies",messages:n})}readNodeTree(){if(!this.bufferConstants||!this.wasmMemory||this.ringBufferBase===null)return null;let e=this.bufferConstants,t=this.ringBufferBase+e.NODE_TREE_START,s=new Uint32Array(this.wasmMemory.buffer,t,2),o=s[0],a=s[1],i=t+e.NODE_TREE_HEADER_SIZE,n=e.NODE_TREE_MAX_NODES,_=e.NODE_TREE_ENTRY_SIZE,r=e.NODE_TREE_DEF_NAME_SIZE,h=new DataView(this.wasmMemory.buffer,i,n*_),f=[],S=0;for(let E=0;E<n&&S<o;E++){let c=E*_,m=h.getInt32(c,!0);if(m===-1)continue;S++;let u=i+c+24,l=new Uint8Array(this.wasmMemory.buffer,u,r),T="";for(let d=0;d<r&&l[d]!==0;d++)T+=String.fromCharCode(l[d]);f.push({id:m,parentId:h.getInt32(c+4,!0),isGroup:h.getInt32(c+8,!0)===1,prevId:h.getInt32(c+12,!0),nextId:h.getInt32(c+16,!0),headId:h.getInt32(c+20,!0),defName:T})}return{nodeCount:o,version:a,nodes:f}}readMetrics(){return this.metricsView?new Uint32Array(this.metricsView):null}checkAndSendSnapshot(e){let t=this.bufferConstants;if(!t||!this.wasmMemory||this.ringBufferBase===null)return;let s=this.ringBufferBase+t.NODE_TREE_START,a=new Uint32Array(this.wasmMemory.buffer,s,2)[1];if(a!==this.lastTreeVersion)this.lastTreeVersion=a,this.lastTreeSendTime=e;else{if(this.lastTreeSendTime>=0&&e-this.lastTreeSendTime<this.treeSnapshotMinInterval)return;this.lastTreeSendTime=e}let n=this.readMetricsAndTreeBuffer();n&&(this.treeSnapshotsSent++,this.port.postMessage({type:"snapshot",buffer:n,snapshotsSent:this.treeSnapshotsSent},[n]))}readMetricsAndTreeBuffer(){if(!this.bufferConstants||!this.wasmMemory||this.ringBufferBase===null)return null;let e=this.bufferConstants,t=this.ringBufferBase+e.METRICS_START,s=e.METRICS_SIZE+e.NODE_TREE_SIZE,o=new Uint8Array(this.wasmMemory.buffer,t,s),a=new ArrayBuffer(s);return new Uint8Array(a).set(o),a}readDebugMessages(){let e=this.bufferConstants.DEBUG_BUFFER_START,t=this.bufferConstants.DEBUG_BUFFER_SIZE,s=this.bufferConstants.MESSAGE_MAGIC,o=this.bufferConstants.PADDING_MAGIC,a=this.bufferConstants.MESSAGE_HEADER_SIZE,i=this.ringBufferBase+e,n=[],_=this.atomicLoad(this.CONTROL_INDICES.DEBUG_HEAD),r=this.atomicLoad(this.CONTROL_INDICES.DEBUG_TAIL);for(;_!==r;){let h=this.dataView.getUint32(i+r,!0);if(h===o){r=0;continue}if(h!==s){r=(r+1)%t;continue}let f=this.dataView.getUint32(i+r+4,!0),S=this.dataView.getUint32(i+r+8,!0);if(f<a||f>t){r=(r+1)%t;continue}let E=f-a,c=i+r+a,m=new Uint8Array(E);for(let u=0;u<E;u++)m[u]=this.uint8View[c+u];n.push({bytes:m.buffer,sequence:S}),r=(r+f)%t}this.atomicStore(this.CONTROL_INDICES.DEBUG_TAIL,r),n.length>0&&this.port.postMessage({type:"debugRawBatch",messages:n},n.map(h=>h.bytes))}async handleMessage(e){let{data:t}=e;t.type!=="osc"&&t.type!=="init"&&t.type!=="loadWasm"&&console.log("[AudioWorklet] Received message type:",t.type);try{if(t.type==="osc"){this.mode==="postMessage"&&t.oscData&&this.oscQueue.push(t.oscData);return}if(t.type==="init"&&(this.mode=t.mode||"sab",t.snapshotIntervalMs&&(this.treeSnapshotMinInterval=t.snapshotIntervalMs/1e3),this.mode==="sab"&&t.sharedBuffer&&(this.sharedBuffer=t.sharedBuffer,this.atomicView=new Int32Array(this.sharedBuffer),this.uint8View=new Uint8Array(this.sharedBuffer),this.dataView=new DataView(this.sharedBuffer))),t.type==="loadWasm"){if(t.wasmBytes){let s;if(this.mode==="sab"){if(s=t.wasmMemory,!s){this.port.postMessage({type:"error",error:"No WASM memory provided!"});return}}else{let i=t.memoryPages||1280;s=new WebAssembly.Memory({initial:i,maximum:i,shared:!0})}this.wasmMemory=s,this.worldOptions=t.worldOptions||{},this.sampleRate=t.sampleRate||48e3;let o={env:{memory:s,emscripten_asm_const_double:()=>Date.now()*1e3,__syscall_getdents64:()=>0,__syscall_unlinkat:()=>0,_emscripten_init_main_thread_js:()=>{},_emscripten_thread_mailbox_await:()=>{},_emscripten_thread_set_strongref:()=>{},emscripten_exit_with_live_runtime:()=>{},_emscripten_receive_on_main_thread_js:()=>{},emscripten_check_blocking_allowed:()=>{},_emscripten_thread_cleanup:()=>{},emscripten_num_logical_cores:()=>1,_emscripten_notify_mailbox_postmessage:()=>{}},wasi_snapshot_preview1:{clock_time_get:(i,n,_)=>{let r=new DataView(s.buffer),h=BigInt(Math.floor(Date.now()*1e6));return r.setBigUint64(_,h,!0),0},environ_sizes_get:()=>0,environ_get:()=>0,fd_close:()=>0,fd_write:()=>0,fd_seek:()=>0,fd_read:()=>0,proc_exit:i=>{console.error("[AudioWorklet] WASM tried to exit with code:",i)}}},a=await WebAssembly.compile(t.wasmBytes);if(this.wasmInstance=await WebAssembly.instantiate(a,o),this.wasmInstance.exports.get_ring_buffer_base&&(this.ringBufferBase=this.wasmInstance.exports.get_ring_buffer_base(),this.loadBufferConstants(),this.calculateBufferIndices(this.ringBufferBase),this.writeWorldOptionsToMemory(),this.wasmInstance.exports.init_memory)){this.wasmInstance.exports.init_memory(this.sampleRate),this.isInitialized=!0;let i=this.mode==="postMessage"?this.readMetricsAndTreeBuffer():void 0,n={type:"initialized",success:!0,ringBufferBase:this.ringBufferBase,bufferConstants:this.bufferConstants,exports:Object.keys(this.wasmInstance.exports),initialSnapshot:i};this.port.postMessage(n,i?[i]:[])}}else if(t.wasmInstance&&(this.wasmInstance=t.wasmInstance,this.wasmInstance.exports.get_ring_buffer_base&&(this.ringBufferBase=this.wasmInstance.exports.get_ring_buffer_base(),this.loadBufferConstants(),this.calculateBufferIndices(this.ringBufferBase),this.writeWorldOptionsToMemory(),this.wasmInstance.exports.init_memory))){this.wasmInstance.exports.init_memory(this.sampleRate),this.isInitialized=!0;let s=this.mode==="postMessage"?this.readMetricsAndTreeBuffer():void 0,o={type:"initialized",success:!0,ringBufferBase:this.ringBufferBase,bufferConstants:this.bufferConstants,exports:Object.keys(this.wasmInstance.exports),initialSnapshot:s};this.port.postMessage(o,s?[s]:[])}}if(t.type==="getVersion")if(this.wasmInstance&&this.wasmInstance.exports.get_supersonic_version_string){let s=this.wasmInstance.exports.get_supersonic_version_string(),o=new Uint8Array(this.wasmMemory.buffer),a="";for(let i=s;o[i]!==0;i++)a+=String.fromCharCode(o[i]);this.port.postMessage({type:"version",version:a})}else this.port.postMessage({type:"version",version:"unknown"});if(t.type==="getTimeOffset")if(this.wasmInstance&&this.wasmInstance.exports.get_time_offset){let s=this.wasmInstance.exports.get_time_offset();this.port.postMessage({type:"timeOffset",offset:s})}else console.error("[AudioWorklet] get_time_offset not available! wasmInstance:",!!this.wasmInstance),this.port.postMessage({type:"error",error:"get_time_offset function not available in WASM exports"});if(t.type==="setNTPStartTime"&&this.wasmMemory&&this.ringBufferBase!==null&&this.bufferConstants){let s=this.ringBufferBase+this.bufferConstants.NTP_START_TIME_START,o=new Float64Array(this.wasmMemory.buffer,s,1);o[0]=t.ntpStartTime}if(t.type==="setDriftOffset"&&this.wasmMemory&&this.ringBufferBase!==null&&this.bufferConstants){let s=this.ringBufferBase+this.bufferConstants.DRIFT_OFFSET_START,o=new Int32Array(this.wasmMemory.buffer,s,1);o[0]=t.driftOffsetMs}if(t.type==="setGlobalOffset"&&this.wasmMemory&&this.ringBufferBase!==null&&this.bufferConstants){let s=this.ringBufferBase+this.bufferConstants.GLOBAL_OFFSET_START,o=new Int32Array(this.wasmMemory.buffer,s,1);o[0]=t.globalOffsetMs}if(t.type==="getMetrics"){let s=this.metricsView?new Uint32Array(this.metricsView):null;this.port.postMessage({type:"metricsSnapshot",requestId:t.requestId,metrics:s})}if(t.type==="copyBufferData")try{let{copyId:s,ptr:o,data:a}=t;if(!this.wasmMemory||!this.wasmMemory.buffer)throw new Error("WASM memory not initialized");let i=new Float32Array(a);new Float32Array(this.wasmMemory.buffer,o,i.length).set(i),this.port.postMessage({type:"bufferCopied",copyId:s,success:!0})}catch(s){console.error("[AudioWorklet] Buffer copy failed:",s),this.port.postMessage({type:"bufferCopied",copyId:t.copyId,success:!1,error:s.message})}}catch(s){console.error("[AudioWorklet] Error handling message:",s),this.port.postMessage({type:"error",error:s.message,stack:s.stack})}}process(e,t,s){if(this.processCallCount++,!this.isInitialized)return!0;try{if(this.wasmInstance&&this.wasmInstance.exports.process_audio){this.mode==="postMessage"&&this.drainOscQueue();let o=currentTime,a=this.wasmInstance.exports.process_audio(o);if(this.wasmInstance.exports.get_audio_output_bus&&t[0]&&t[0].length>=2)try{let i=this.wasmInstance.exports.get_audio_output_bus(),n=this.wasmInstance.exports.get_audio_buffer_samples();if(i&&i>0){let _=this.wasmInstance.exports.memory||this.wasmMemory;if(!_||!_.buffer)return!0;let r=_.buffer,h=r.byteLength,f=i+n*2*4;if(i<0||i>h||f>h)return!0;(!this.audioView||this.lastAudioBufferPtr!==i||this.lastWasmBufferSize!==h||r!==this.audioView.buffer)&&(this.audioView=new Float32Array(r,i,n*2),this.lastAudioBufferPtr=i,this.lastWasmBufferSize=h),t[0][0].set(this.audioView.subarray(0,n)),t[0][1].set(this.audioView.subarray(n,n*2))}}catch{}if(this.mode==="postMessage")this.readOscReplies(),this.readDebugMessages(),this.checkAndSendSnapshot(o);else if(this.atomicView){let i=this.atomicLoad(this.CONTROL_INDICES.OUT_HEAD),n=this.atomicLoad(this.CONTROL_INDICES.OUT_TAIL);i!==n&&Atomics.notify(this.atomicView,this.CONTROL_INDICES.OUT_HEAD,1)}return this.processCallCount%3750===0&&this.checkStatus(),a!==0}}catch(o){console.error("[AudioWorklet] process() error:",o),console.error("[AudioWorklet] Stack:",o.stack),this.atomicView&&this.mode==="sab"&&Atomics.or(this.atomicView,this.CONTROL_INDICES.STATUS_FLAGS,this.STATUS_FLAGS.WASM_ERROR)}return!0}checkStatus(){if(!this.atomicView)return;let e=this.atomicLoad(this.CONTROL_INDICES.STATUS_FLAGS);if(e!==this.STATUS_FLAGS.OK){let t={bufferFull:!!(e&this.STATUS_FLAGS.BUFFER_FULL),overrun:!!(e&this.STATUS_FLAGS.OVERRUN),wasmError:!!(e&this.STATUS_FLAGS.WASM_ERROR),fragmented:!!(e&this.STATUS_FLAGS.FRAGMENTED_MSG)},s={processCount:this.metricsView[0],messagesProcessed:this.metricsView[1],messagesDropped:this.metricsView[2],schedulerQueueDepth:this.metricsView[3],schedulerQueueMax:this.metricsView[4],schedulerQueueDropped:this.metricsView[5]};this.port.postMessage({type:"status",flags:e,status:t,metrics:s});let o=e&this.STATUS_FLAGS.BUFFER_FULL;this.atomicStore(this.CONTROL_INDICES.STATUS_FLAGS,o)}}};registerProcessor("scsynth-processor",p);})();
1
+ (()=>{var T=class extends AudioWorkletProcessor{constructor(){super(),this.mode="sab",this.sharedBuffer=null,this.wasmModule=null,this.wasmInstance=null,this.isInitialized=!1,this.processCallCount=0,this.lastStatusCheck=0,this.ringBufferBase=null,this.audioView=null,this.lastAudioBufferPtr=0,this.lastWasmBufferSize=0,this.lastTreeVersion=-1,this.treeSnapshotsSent=0,this.lastTreeSendTime=-1,this.treeSnapshotMinInterval=.025,this.atomicView=null,this.uint8View=null,this.dataView=null,this.localClockOffsetView=null,this.bufferConstants=null,this.CONTROL_INDICES=null,this.metricsView=null,this.STATUS_FLAGS={OK:0,BUFFER_FULL:1,OVERRUN:2,WASM_ERROR:4,FRAGMENTED_MSG:8},this.oscQueue=[],this.port.onmessage=this.handleMessage.bind(this)}loadBufferConstants(){if(!this.wasmInstance||!this.wasmInstance.exports.get_buffer_layout)throw new Error("WASM instance does not export get_buffer_layout");let e=this.wasmInstance.exports.get_buffer_layout(),t=this.wasmMemory;if(!t)throw new Error("WASM memory not available");let s=new Uint32Array(t.buffer,e,34),o=new Uint8Array(t.buffer,e,140);if(this.bufferConstants={IN_BUFFER_START:s[0],IN_BUFFER_SIZE:s[1],OUT_BUFFER_START:s[2],OUT_BUFFER_SIZE:s[3],DEBUG_BUFFER_START:s[4],DEBUG_BUFFER_SIZE:s[5],CONTROL_START:s[6],CONTROL_SIZE:s[7],METRICS_START:s[8],METRICS_SIZE:s[9],NODE_TREE_START:s[10],NODE_TREE_SIZE:s[11],NODE_TREE_HEADER_SIZE:s[12],NODE_TREE_ENTRY_SIZE:s[13],NODE_TREE_DEF_NAME_SIZE:s[14],NODE_TREE_MAX_NODES:s[15],NTP_START_TIME_START:s[16],NTP_START_TIME_SIZE:s[17],DRIFT_OFFSET_START:s[18],DRIFT_OFFSET_SIZE:s[19],GLOBAL_OFFSET_START:s[20],GLOBAL_OFFSET_SIZE:s[21],AUDIO_CAPTURE_START:s[22],AUDIO_CAPTURE_SIZE:s[23],AUDIO_CAPTURE_HEADER_SIZE:s[24],AUDIO_CAPTURE_FRAMES:s[25],AUDIO_CAPTURE_CHANNELS:s[26],AUDIO_CAPTURE_SAMPLE_RATE:s[27],TOTAL_BUFFER_SIZE:s[28],MAX_MESSAGE_SIZE:s[29],MESSAGE_MAGIC:s[30],PADDING_MAGIC:s[31],scheduler_slot_size:s[32],scheduler_slot_count:s[33],DEBUG_PADDING_MARKER:o[136],MESSAGE_HEADER_SIZE:16},this.bufferConstants.MESSAGE_MAGIC!==3735928559)throw new Error("Invalid buffer constants from WASM")}calculateBufferIndices(e){if(!this.bufferConstants)throw new Error("Buffer constants not loaded. Call loadBufferConstants() first.");let t=this.bufferConstants.CONTROL_START,s=this.bufferConstants.METRICS_START;if(this.CONTROL_INDICES={IN_HEAD:(e+t+0)/4,IN_TAIL:(e+t+4)/4,OUT_HEAD:(e+t+8)/4,OUT_TAIL:(e+t+12)/4,DEBUG_HEAD:(e+t+16)/4,DEBUG_TAIL:(e+t+20)/4,IN_SEQUENCE:(e+t+24)/4,OUT_SEQUENCE:(e+t+28)/4,DEBUG_SEQUENCE:(e+t+32)/4,STATUS_FLAGS:(e+t+36)/4,IN_WRITE_LOCK:(e+t+40)/4},this.mode==="sab"){let o=e+s;this.metricsView=new Uint32Array(this.sharedBuffer,o,this.bufferConstants.METRICS_SIZE/4)}else{this.atomicView=new Int32Array(this.wasmMemory.buffer),this.uint8View=new Uint8Array(this.wasmMemory.buffer),this.dataView=new DataView(this.wasmMemory.buffer);let o=e+s;this.metricsView=new Uint32Array(this.wasmMemory.buffer,o,this.bufferConstants.METRICS_SIZE/4)}}writeWorldOptionsToMemory(){if(!this.worldOptions||!this.wasmMemory)return;let e=this.ringBufferBase+65536,t=new Uint32Array(this.wasmMemory.buffer,e,32),s=new Float32Array(this.wasmMemory.buffer,e,32);t[0]=this.worldOptions.numBuffers||1024,t[1]=this.worldOptions.maxNodes||1024,t[2]=this.worldOptions.maxGraphDefs||1024,t[3]=this.worldOptions.maxWireBufs||64,t[4]=this.worldOptions.numAudioBusChannels||128,t[5]=this.worldOptions.numInputBusChannels||0,t[6]=this.worldOptions.numOutputBusChannels||2,t[7]=this.worldOptions.numControlBusChannels||4096,t[8]=this.worldOptions.bufLength||128,t[9]=this.worldOptions.realTimeMemorySize||16384,t[10]=this.worldOptions.numRGens||64,t[11]=this.worldOptions.realTime?1:0,t[12]=this.worldOptions.memoryLocking?1:0,t[13]=this.worldOptions.loadGraphDefs||0,t[14]=this.worldOptions.preferredSampleRate||0,t[15]=this.worldOptions.verbosity||0}js_debug(e){if(!(!this.uint8View||!this.atomicView||!this.CONTROL_INDICES||!this.ringBufferBase))try{let t=this.bufferConstants.DEBUG_BUFFER_START,s=this.bufferConstants.DEBUG_BUFFER_SIZE,o=this.bufferConstants.DEBUG_PADDING_MARKER,a="[JS] "+e+`
2
+ `,n=new TextEncoder().encode(a);if(n.length>s)return;let _=this.CONTROL_INDICES.DEBUG_HEAD,r=this.atomicLoad(_),h=s-r,f=r;n.length>h&&(this.uint8View[this.ringBufferBase+t+r]=o,f=0);let S=this.ringBufferBase+t;for(let c=0;c<n.length;c++)this.uint8View[S+f+c]=n[c];let E=f+n.length;this.atomicStore(_,E)}catch{}}atomicLoad(e){return this.mode==="sab"?Atomics.load(this.atomicView,e):this.atomicView[e]}atomicStore(e,t){this.mode==="sab"?Atomics.store(this.atomicView,e,t):this.atomicView[e]=t}drainOscQueue(){if(this.oscQueue.length===0)return;let e=this.bufferConstants.IN_BUFFER_START,t=this.bufferConstants.IN_BUFFER_SIZE,s=this.bufferConstants.MESSAGE_MAGIC,o=this.bufferConstants.MESSAGE_HEADER_SIZE,a=this.ringBufferBase+e;for(;this.oscQueue.length>0;){let i=this.oscQueue[0],n=i.byteLength,r=o+n+3&-4,h=this.atomicLoad(this.CONTROL_INDICES.IN_HEAD),f=this.atomicLoad(this.CONTROL_INDICES.IN_TAIL),S;if(h>=f?S=t-h+f-1:S=f-h-1,r>S)break;this.oscQueue.shift();let E=h;this.dataView.setUint32(a+E,s,!0),this.dataView.setUint32(a+E+4,r,!0);let c=this.atomicLoad(this.CONTROL_INDICES.IN_SEQUENCE);this.dataView.setUint32(a+E+8,c,!0),this.dataView.setUint32(a+E+12,0,!0),this.atomicStore(this.CONTROL_INDICES.IN_SEQUENCE,c+1);let m=new Uint8Array(i);for(let l=0;l<n;l++)this.uint8View[a+E+o+l]=m[l];let u=(E+r)%t;this.atomicStore(this.CONTROL_INDICES.IN_HEAD,u)}}readOscReplies(){let e=this.bufferConstants.OUT_BUFFER_START,t=this.bufferConstants.OUT_BUFFER_SIZE,s=this.bufferConstants.MESSAGE_MAGIC,o=this.bufferConstants.PADDING_MAGIC,a=this.bufferConstants.MESSAGE_HEADER_SIZE,i=this.ringBufferBase+e,n=[],_=this.atomicLoad(this.CONTROL_INDICES.OUT_HEAD),r=this.atomicLoad(this.CONTROL_INDICES.OUT_TAIL);for(;_!==r;){let h=this.dataView.getUint32(i+r,!0);if(h===o){r=0;continue}if(h!==s){r=(r+1)%t;continue}let f=this.dataView.getUint32(i+r+4,!0),S=this.dataView.getUint32(i+r+8,!0);if(f<a||f>t){r=(r+1)%t;continue}let E=f-a,c=new Uint8Array(E);for(let u=0;u<E;u++)c[u]=this.uint8View[i+r+a+u];n.push({oscData:c.buffer,sequence:S});let m=f+3&-4;r=(r+m)%t}this.atomicStore(this.CONTROL_INDICES.OUT_TAIL,r),n.length>0&&this.port.postMessage({type:"oscReplies",messages:n})}readNodeTree(){if(!this.bufferConstants||!this.wasmMemory||this.ringBufferBase===null)return null;let e=this.bufferConstants,t=this.ringBufferBase+e.NODE_TREE_START,s=new Uint32Array(this.wasmMemory.buffer,t,2),o=s[0],a=s[1],i=t+e.NODE_TREE_HEADER_SIZE,n=e.NODE_TREE_MAX_NODES,_=e.NODE_TREE_ENTRY_SIZE,r=e.NODE_TREE_DEF_NAME_SIZE,h=new DataView(this.wasmMemory.buffer,i,n*_),f=[],S=0;for(let E=0;E<n&&S<o;E++){let c=E*_,m=h.getInt32(c,!0);if(m===-1)continue;S++;let u=i+c+24,l=new Uint8Array(this.wasmMemory.buffer,u,r),A="";for(let d=0;d<r&&l[d]!==0;d++)A+=String.fromCharCode(l[d]);f.push({id:m,parentId:h.getInt32(c+4,!0),isGroup:h.getInt32(c+8,!0)===1,prevId:h.getInt32(c+12,!0),nextId:h.getInt32(c+16,!0),headId:h.getInt32(c+20,!0),defName:A})}return{nodeCount:o,version:a,nodes:f}}readMetrics(){return this.metricsView?new Uint32Array(this.metricsView):null}checkAndSendSnapshot(e){let t=this.bufferConstants;if(!t||!this.wasmMemory||this.ringBufferBase===null)return;let s=this.ringBufferBase+t.NODE_TREE_START,a=new Uint32Array(this.wasmMemory.buffer,s,2)[1];if(a!==this.lastTreeVersion)this.lastTreeVersion=a,this.lastTreeSendTime=e;else{if(this.lastTreeSendTime>=0&&e-this.lastTreeSendTime<this.treeSnapshotMinInterval)return;this.lastTreeSendTime=e}let n=this.readMetricsAndTreeBuffer();n&&(this.treeSnapshotsSent++,this.port.postMessage({type:"snapshot",buffer:n,snapshotsSent:this.treeSnapshotsSent},[n]))}readMetricsAndTreeBuffer(){if(!this.bufferConstants||!this.wasmMemory||this.ringBufferBase===null)return null;let e=this.bufferConstants,t=this.ringBufferBase+e.METRICS_START,s=e.METRICS_SIZE+e.NODE_TREE_SIZE,o=new Uint8Array(this.wasmMemory.buffer,t,s),a=new ArrayBuffer(s);return new Uint8Array(a).set(o),a}readDebugMessages(){let e=this.bufferConstants.DEBUG_BUFFER_START,t=this.bufferConstants.DEBUG_BUFFER_SIZE,s=this.bufferConstants.MESSAGE_MAGIC,o=this.bufferConstants.PADDING_MAGIC,a=this.bufferConstants.MESSAGE_HEADER_SIZE,i=this.ringBufferBase+e,n=[],_=this.atomicLoad(this.CONTROL_INDICES.DEBUG_HEAD),r=this.atomicLoad(this.CONTROL_INDICES.DEBUG_TAIL);for(;_!==r;){let h=this.dataView.getUint32(i+r,!0);if(h===o){r=0;continue}if(h!==s){r=(r+1)%t;continue}let f=this.dataView.getUint32(i+r+4,!0),S=this.dataView.getUint32(i+r+8,!0);if(f<a||f>t){r=(r+1)%t;continue}let E=f-a,c=i+r+a,m=new Uint8Array(E);for(let u=0;u<E;u++)m[u]=this.uint8View[c+u];n.push({bytes:m.buffer,sequence:S}),r=(r+f)%t}this.atomicStore(this.CONTROL_INDICES.DEBUG_TAIL,r),n.length>0&&this.port.postMessage({type:"debugRawBatch",messages:n},n.map(h=>h.bytes))}async handleMessage(e){let{data:t}=e;try{if(t.type==="osc"){this.mode==="postMessage"&&t.oscData&&this.oscQueue.push(t.oscData);return}if(t.type==="init"&&(this.mode=t.mode||"sab",t.snapshotIntervalMs&&(this.treeSnapshotMinInterval=t.snapshotIntervalMs/1e3),this.mode==="sab"&&t.sharedBuffer&&(this.sharedBuffer=t.sharedBuffer,this.atomicView=new Int32Array(this.sharedBuffer),this.uint8View=new Uint8Array(this.sharedBuffer),this.dataView=new DataView(this.sharedBuffer))),t.type==="loadWasm"){if(t.wasmBytes){let s;if(this.mode==="sab"){if(s=t.wasmMemory,!s){this.port.postMessage({type:"error",error:"No WASM memory provided!"});return}}else{let i=t.memoryPages||1280;s=new WebAssembly.Memory({initial:i,maximum:i,shared:!0})}this.wasmMemory=s,this.worldOptions=t.worldOptions||{},this.sampleRate=t.sampleRate||48e3;let o={env:{memory:s,emscripten_asm_const_double:()=>Date.now()*1e3,__syscall_getdents64:()=>0,__syscall_unlinkat:()=>0,_emscripten_init_main_thread_js:()=>{},_emscripten_thread_mailbox_await:()=>{},_emscripten_thread_set_strongref:()=>{},emscripten_exit_with_live_runtime:()=>{},_emscripten_receive_on_main_thread_js:()=>{},emscripten_check_blocking_allowed:()=>{},_emscripten_thread_cleanup:()=>{},emscripten_num_logical_cores:()=>1,_emscripten_notify_mailbox_postmessage:()=>{}},wasi_snapshot_preview1:{clock_time_get:(i,n,_)=>{let r=new DataView(s.buffer),h=BigInt(Math.floor(Date.now()*1e6));return r.setBigUint64(_,h,!0),0},environ_sizes_get:()=>0,environ_get:()=>0,fd_close:()=>0,fd_write:()=>0,fd_seek:()=>0,fd_read:()=>0,proc_exit:i=>{console.error("[AudioWorklet] WASM tried to exit with code:",i)}}},a=await WebAssembly.compile(t.wasmBytes);if(this.wasmInstance=await WebAssembly.instantiate(a,o),this.wasmInstance.exports.get_ring_buffer_base&&(this.ringBufferBase=this.wasmInstance.exports.get_ring_buffer_base(),this.loadBufferConstants(),this.calculateBufferIndices(this.ringBufferBase),this.writeWorldOptionsToMemory(),this.wasmInstance.exports.init_memory)){this.wasmInstance.exports.init_memory(this.sampleRate),this.isInitialized=!0;let i=this.mode==="postMessage"?this.readMetricsAndTreeBuffer():void 0,n={type:"initialized",success:!0,ringBufferBase:this.ringBufferBase,bufferConstants:this.bufferConstants,exports:Object.keys(this.wasmInstance.exports),initialSnapshot:i};this.port.postMessage(n,i?[i]:[])}}else if(t.wasmInstance&&(this.wasmInstance=t.wasmInstance,this.wasmInstance.exports.get_ring_buffer_base&&(this.ringBufferBase=this.wasmInstance.exports.get_ring_buffer_base(),this.loadBufferConstants(),this.calculateBufferIndices(this.ringBufferBase),this.writeWorldOptionsToMemory(),this.wasmInstance.exports.init_memory))){this.wasmInstance.exports.init_memory(this.sampleRate),this.isInitialized=!0;let s=this.mode==="postMessage"?this.readMetricsAndTreeBuffer():void 0,o={type:"initialized",success:!0,ringBufferBase:this.ringBufferBase,bufferConstants:this.bufferConstants,exports:Object.keys(this.wasmInstance.exports),initialSnapshot:s};this.port.postMessage(o,s?[s]:[])}}if(t.type==="getVersion")if(this.wasmInstance&&this.wasmInstance.exports.get_supersonic_version_string){let s=this.wasmInstance.exports.get_supersonic_version_string(),o=new Uint8Array(this.wasmMemory.buffer),a="";for(let i=s;o[i]!==0;i++)a+=String.fromCharCode(o[i]);this.port.postMessage({type:"version",version:a})}else this.port.postMessage({type:"version",version:"unknown"});if(t.type==="getTimeOffset")if(this.wasmInstance&&this.wasmInstance.exports.get_time_offset){let s=this.wasmInstance.exports.get_time_offset();this.port.postMessage({type:"timeOffset",offset:s})}else console.error("[AudioWorklet] get_time_offset not available! wasmInstance:",!!this.wasmInstance),this.port.postMessage({type:"error",error:"get_time_offset function not available in WASM exports"});if(t.type==="setNTPStartTime"&&this.wasmMemory&&this.ringBufferBase!==null&&this.bufferConstants){let s=this.ringBufferBase+this.bufferConstants.NTP_START_TIME_START,o=new Float64Array(this.wasmMemory.buffer,s,1);o[0]=t.ntpStartTime}if(t.type==="setDriftOffset"&&this.wasmMemory&&this.ringBufferBase!==null&&this.bufferConstants){let s=this.ringBufferBase+this.bufferConstants.DRIFT_OFFSET_START,o=new Int32Array(this.wasmMemory.buffer,s,1);o[0]=t.driftOffsetMs}if(t.type==="setGlobalOffset"&&this.wasmMemory&&this.ringBufferBase!==null&&this.bufferConstants){let s=this.ringBufferBase+this.bufferConstants.GLOBAL_OFFSET_START,o=new Int32Array(this.wasmMemory.buffer,s,1);o[0]=t.globalOffsetMs}if(t.type==="getMetrics"){let s=this.metricsView?new Uint32Array(this.metricsView):null;this.port.postMessage({type:"metricsSnapshot",requestId:t.requestId,metrics:s})}if(t.type==="copyBufferData")try{let{copyId:s,ptr:o,data:a}=t;if(!this.wasmMemory||!this.wasmMemory.buffer)throw new Error("WASM memory not initialized");let i=new Float32Array(a);new Float32Array(this.wasmMemory.buffer,o,i.length).set(i),this.port.postMessage({type:"bufferCopied",copyId:s,success:!0})}catch(s){console.error("[AudioWorklet] Buffer copy failed:",s),this.port.postMessage({type:"bufferCopied",copyId:t.copyId,success:!1,error:s.message})}}catch(s){console.error("[AudioWorklet] Error handling message:",s),this.port.postMessage({type:"error",error:s.message,stack:s.stack})}}process(e,t,s){if(this.processCallCount++,!this.isInitialized)return!0;try{if(this.wasmInstance&&this.wasmInstance.exports.process_audio){this.mode==="postMessage"&&this.drainOscQueue();let o=currentTime,a=this.wasmInstance.exports.process_audio(o);if(this.wasmInstance.exports.get_audio_output_bus&&t[0]&&t[0].length>=2)try{let i=this.wasmInstance.exports.get_audio_output_bus(),n=this.wasmInstance.exports.get_audio_buffer_samples();if(i&&i>0){let _=this.wasmInstance.exports.memory||this.wasmMemory;if(!_||!_.buffer)return!0;let r=_.buffer,h=r.byteLength,f=i+n*2*4;if(i<0||i>h||f>h)return!0;(!this.audioView||this.lastAudioBufferPtr!==i||this.lastWasmBufferSize!==h||r!==this.audioView.buffer)&&(this.audioView=new Float32Array(r,i,n*2),this.lastAudioBufferPtr=i,this.lastWasmBufferSize=h),t[0][0].set(this.audioView.subarray(0,n)),t[0][1].set(this.audioView.subarray(n,n*2))}}catch{}if(this.mode==="postMessage")this.readOscReplies(),this.readDebugMessages(),this.checkAndSendSnapshot(o);else if(this.atomicView){let i=this.atomicLoad(this.CONTROL_INDICES.OUT_HEAD),n=this.atomicLoad(this.CONTROL_INDICES.OUT_TAIL);i!==n&&Atomics.notify(this.atomicView,this.CONTROL_INDICES.OUT_HEAD,1)}return this.processCallCount%3750===0&&this.checkStatus(),a!==0}}catch(o){console.error("[AudioWorklet] process() error:",o),console.error("[AudioWorklet] Stack:",o.stack),this.atomicView&&this.mode==="sab"&&Atomics.or(this.atomicView,this.CONTROL_INDICES.STATUS_FLAGS,this.STATUS_FLAGS.WASM_ERROR)}return!0}checkStatus(){if(!this.atomicView)return;let e=this.atomicLoad(this.CONTROL_INDICES.STATUS_FLAGS);if(e!==this.STATUS_FLAGS.OK){let t={bufferFull:!!(e&this.STATUS_FLAGS.BUFFER_FULL),overrun:!!(e&this.STATUS_FLAGS.OVERRUN),wasmError:!!(e&this.STATUS_FLAGS.WASM_ERROR),fragmented:!!(e&this.STATUS_FLAGS.FRAGMENTED_MSG)},s={processCount:this.metricsView[0],messagesProcessed:this.metricsView[1],messagesDropped:this.metricsView[2],schedulerQueueDepth:this.metricsView[3],schedulerQueueMax:this.metricsView[4],schedulerQueueDropped:this.metricsView[5]};this.port.postMessage({type:"status",flags:e,status:t,metrics:s});let o=e&this.STATUS_FLAGS.BUFFER_FULL;this.atomicStore(this.CONTROL_INDICES.STATUS_FLAGS,o)}}};registerProcessor("scsynth-processor",T);})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supersonic-scsynth",
3
- "version": "0.21.6",
3
+ "version": "0.21.7",
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",