supersonic-scsynth 0.6.6 → 0.7.1

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
@@ -1,214 +1,86 @@
1
- # SuperSonic
1
+ > **Note: Alpha Status**: SuperSonic is in active development. The API may evolve, but the core synthesis engine is solid and ready for experimentation. Feedback and ideas are most welcome.
2
2
 
3
- > **Warning - Super Alpha Status**: SuperSonic is currently in active development. The API is likely to change between releases. Feedback welcome!
4
-
5
- A WebAssembly port of SuperCollider's scsynth audio synthesis engine for the browser. Runs in an AudioWorklet for real-time, high-priority audio processing with full OSC API support.
6
-
7
- ## Quick Start
8
-
9
- ```html
10
- <script type="module">
11
- import { SuperSonic } from './dist/supersonic.js';
12
-
13
- const sonic = new SuperSonic({
14
- workerBaseURL: './dist/workers/',
15
- wasmBaseURL: './dist/wasm/',
16
- sampleBaseURL: './dist/samples/',
17
- synthdefBaseURL: './dist/synthdefs/'
18
- });
19
-
20
- await sonic.init();
21
-
22
- // Load a synthdef
23
- await sonic.loadSynthDefs(['sonic-pi-beep']);
24
-
25
- // Trigger the synth
26
- sonic.send('/s_new', 'sonic-pi-beep', -1, 0, 0, 'note', 60);
27
-
28
- // Load and play a sample
29
- sonic.send('/b_allocRead', 0, 'bd_haus.flac');
30
- sonic.send('/s_new', 'sonic-pi-basic_mono_player', -1, 0, 0, 'buf', 0);
31
- </script>
32
3
  ```
33
-
34
- **Important:** SuperSonic requires self-hosting (cannot load from CDN). See [CDN Usage](#cdn-usage) below.
35
-
36
- ## Installation
37
-
38
- **Via npm (for local bundling):**
39
- ```bash
40
- # Core engine only (~450KB)
41
- npm install supersonic-scsynth
42
-
43
- # Everything (engine + synthdefs + samples)
44
- npm install supersonic-scsynth-bundle
4
+ ░█▀▀░█░█░█▀█░█▀▀░█▀▄░█▀▀░█▀█░█▀█░▀█▀░█▀▀
5
+ ░▀▀█░█░█░█▀▀░█▀▀░█▀▄░▀▀█░█░█░█░█░░█░░█░░
6
+ ░▀▀▀░▀▀▀░▀░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀▀▀
45
7
  ```
46
8
 
47
- **Pre-built distribution (recommended):**
48
- Download the pre-built package (~35MB with all synthdefs and samples) and serve from your own domain:
49
- https://samaaron.github.io/supersonic/supersonic-dist.zip
50
-
51
- Extract to your web server and import as:
52
- ```javascript
53
- import { SuperSonic } from './dist/supersonic.js';
54
- ```
9
+ **SuperSonic** - [SuperCollider](https://supercollider.github.io/)'s powerful audio synthesis engine scsynth running in the browser as an [AudioWorklet](https://developer.mozilla.org/en-US/docs/Web/API/AudioWorklet).
55
10
 
56
- ## Packages
11
+ - _AudioWorklet_ - runs in a dedicated high priority audio thread
12
+ - _WebAssembly_ - scsynth's C++ code compiled for the web
13
+ - _OSC API_ - talk to the scsynth server through its native OSC API
57
14
 
58
- SuperSonic is split into multiple packages:
15
+ **[Try the live demo](https://sonic-pi.net/supersonic/demo.html)**
59
16
 
60
- | Package | Size | License | Contents |
61
- |---------|------|---------|----------|
62
- | `supersonic-scsynth` | ~450KB | GPL-3.0-or-later | Core WASM engine |
63
- | `supersonic-scsynth-synthdefs` | ~67KB | MIT | 120 Sonic Pi synthdefs |
64
- | `supersonic-scsynth-samples` | ~34MB | CC0-1.0 | 206 Sonic Pi samples |
65
- | `supersonic-scsynth-bundle` | - | - | All of the above |
17
+ ## Getting Started
66
18
 
67
- All synthdefs and samples are from [Sonic Pi](https://github.com/sonic-pi-net/sonic-pi).
19
+ Injecting the full power of SuperCollider's scsynth audio engine into your browser is simple.
68
20
 
69
- ## API Reference
21
+ Import SuperSonic and initialise it:
70
22
 
71
- **Creating an instance:**
72
23
  ```javascript
24
+ import { SuperSonic } from "supersonic-scsynth";
25
+
26
+ const baseURL = "/supersonic"; // Configure for your setup
73
27
  const sonic = new SuperSonic({
74
- workerBaseURL: './dist/workers/', // Required: Path to worker files
75
- wasmBaseURL: './dist/wasm/', // Required: Path to WASM files
76
- sampleBaseURL: './dist/samples/', // Optional: Path to audio samples
77
- synthdefBaseURL: './dist/synthdefs/', // Optional: Path to synthdefs
78
- audioPathMap: { /* optional custom path mappings */ }
28
+ workerBaseURL: `${baseURL}/workers/`,
29
+ wasmBaseURL: `${baseURL}/wasm/`,
30
+ synthdefBaseURL: `${baseURL}/synthdefs/`,
31
+ sampleBaseURL: `${baseURL}/samples/`,
79
32
  });
33
+ await sonic.init();
80
34
  ```
81
35
 
82
- **Core methods:**
83
- - `await sonic.init()` - Initialize the audio engine
84
- - `await sonic.loadSynthDefs(names)` - Load synth definitions
85
- - `sonic.send(address, ...args)` - Send OSC message (types auto-detected)
86
- - `sonic.sendOSC(oscBytes, options)` - Send pre-encoded OSC bytes
87
-
88
- **Callbacks:**
89
- - `sonic.onInitialized` - Called when ready
90
- - `sonic.onError(error)` - Error handling
91
- - `sonic.onMessageReceived(msg)` - Incoming OSC messages
92
- - `sonic.onMessageSent(oscData)` - Outgoing OSC messages
36
+ Load and play a synth:
93
37
 
94
- **Common OSC commands:**
95
38
  ```javascript
96
- sonic.send('/notify', 1); // Enable notifications
97
- sonic.send('/s_new', 'synth-name', -1, 0, 0); // Create synth
98
- sonic.send('/n_set', 1000, 'freq', 440.0, 'amp', 0.5); // Set parameters
99
- sonic.send('/n_free', 1000); // Free node
100
- sonic.send('/b_allocRead', 0, 'sample.flac'); // Load audio buffer
39
+ await sonic.loadSynthDef("sonic-pi-prophet");
40
+ sonic.send("/s_new", "sonic-pi-prophet", -1, 0, 0, "note", 60);
101
41
  ```
102
42
 
103
- See [SuperCollider Server Command Reference](https://doc.sccode.org/Reference/Server-Command-Reference.html) for the full OSC API.
104
-
105
- ## Browser Requirements
106
-
107
- **Minimum browser versions:**
108
- - Chrome/Edge 92+
109
- - Firefox 79+
110
- - Safari 15.2+
111
-
112
- **Required features:**
113
- - SharedArrayBuffer (requires COOP/COEP headers)
114
- - AudioWorklet
115
- - WebAssembly with threads
116
-
117
- **Required HTTP headers:**
118
- Your server must send these headers for SharedArrayBuffer support:
119
-
120
- ```
121
- Cross-Origin-Opener-Policy: same-origin
122
- Cross-Origin-Embedder-Policy: require-corp
123
- Cross-Origin-Resource-Policy: cross-origin
124
- ```
125
-
126
- See `example/server.rb` for a reference implementation.
127
-
128
- ## CDN Usage
129
-
130
- SuperSonic cannot be loaded from a CDN. The core library must be self-hosted on your domain.
131
-
132
- ### Why Self-Hosting is Required
133
-
134
- SuperSonic uses `SharedArrayBuffer` for real-time audio performance. Browsers require workers that use `SharedArrayBuffer` to come from the same origin as the page. Even with proper COOP/COEP headers, cross-origin workers with shared memory are blocked. This is a fundamental browser security requirement stemming from Spectre attack mitigation.
135
-
136
- What this means:
137
- - You cannot use `import { SuperSonic } from 'https://unpkg.com/supersonic/...'`
138
- - You must download and self-host the core library on your own domain
139
- - The npm packages exist for convenience but must be bundled and deployed to your server
140
-
141
- ### Synthdefs and Samples Can Use CDN
142
-
143
- Pre-compiled synthdefs and audio samples can be loaded from CDNs. They're just data files, not workers.
43
+ Load and play a sample:
144
44
 
145
45
  ```javascript
146
- // Self-hosted core library
147
- import { SuperSonic } from './dist/supersonic.js';
148
-
149
- // CDN-hosted synthdefs and samples work fine
150
- const sonic = new SuperSonic({
151
- workerBaseURL: './dist/workers/', // Must be self-hosted
152
- wasmBaseURL: './dist/wasm/', // Must be self-hosted
153
- sampleBaseURL: 'https://unpkg.com/supersonic-scsynth-samples@0.1.6/samples/',
154
- synthdefBaseURL: 'https://unpkg.com/supersonic-scsynth-synthdefs@0.1.6/synthdefs/'
155
- });
156
-
157
- await sonic.init();
158
- await sonic.loadSynthDefs(['sonic-pi-beep', 'sonic-pi-tb303']);
46
+ await sonic.loadSynthDef("sonic-pi-basic_stereo_player");
47
+ await sonic.loadSample(0, "loop_amen.flac");
48
+ sonic.send("/s_new", "sonic-pi-basic_stereo_player", -1, 0, 0, "buf", 0);
159
49
  ```
160
50
 
161
- ### Hybrid Approach
162
-
163
- Self-host the SuperSonic core (JS, WASM, workers) with COOP/COEP headers. Use CDN for synthdefs and samples to save bandwidth. See `example/simple-cdn.html` for a working example.
51
+ Take a look at `example/simple.html` for a minimal working example.
164
52
 
165
- ## Building from Source
53
+ ## Installation
166
54
 
167
- **Prerequisites:**
168
- - [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html)
169
- - [esbuild](https://esbuild.github.io/)
55
+ Grab the latest pre-built distribution and host it on your server:
170
56
 
171
- **Build:**
172
57
  ```bash
173
- # Activate Emscripten
174
- source ~/path/to/emsdk_env.sh
175
-
176
- # Compile and bundle
177
- ./build.sh
58
+ curl -O https://samaaron.github.io/supersonic/supersonic-dist.zip
59
+ unzip supersonic-dist.zip
178
60
  ```
179
61
 
180
- Output goes to `dist/` directory (~1.5MB WASM + ~76KB JS + workers).
62
+ Or install via npm:
181
63
 
182
- **Run demo:**
183
64
  ```bash
184
- ruby example/server.rb
65
+ npm install supersonic-scsynth-bundle
185
66
  ```
186
67
 
187
- Open http://localhost:8002/demo.html
68
+ **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.
188
69
 
189
- **Docker:**
190
- ```bash
191
- docker build -t supersonic .
192
- docker run --rm -it -p 8002:8002 supersonic
193
- ```
70
+ ## Documentation
194
71
 
195
- ## File Structure
72
+ - [API Reference](docs/API.md) - Methods, callbacks, and configuration
73
+ - [Metrics](docs/METRICS.md) - Performance monitoring and debugging
74
+ - [Browser Setup](docs/BROWSER_SETUP.md) - Required headers and browser requirements
75
+ - [CDN and Self-Hosting](docs/CDN.md) - Why self-hosting is required
76
+ - [Building from Source](docs/BUILDING.md) - Compiling the WASM yourself
196
77
 
197
- When building from source or using local files:
78
+ ## Support
198
79
 
199
- ```
200
- dist/
201
- ├── supersonic.js # Main entry point (ES module)
202
- ├── wasm/
203
- │ └── scsynth-nrt.wasm # Audio engine (~1.5MB)
204
- └── workers/
205
- ├── scsynth_audio_worklet.js # AudioWorklet processor
206
- ├── osc_in_worker.js # OSC input handler
207
- ├── osc_out_prescheduler_worker.js # OSC pre-scheduler (timers & tag cancellation)
208
- └── debug_worker.js # Debug logger
209
- ```
80
+ SuperSonic is brought to you by Sam Aaron. Please consider joining the community of supporters enabling Sam's work on creative coding projects like this, [Sonic Pi](https://sonic-pi.net) and [Tau5](https://tau5.live).
210
81
 
211
- You must specify the paths to `workers/` and `wasm/` directories when creating a SuperSonic instance using the `workerBaseURL` and `wasmBaseURL` options.
82
+ - [Patreon](https://patreon.com/samaaron)
83
+ - [GitHub Sponsors](https://github.com/sponsors/samaaron)
212
84
 
213
85
  ## License
214
86
 
@@ -1,11 +1,11 @@
1
- var n={},n=n||{};(function(){"use strict";n.SECS_70YRS=2208988800,n.TWO_32=4294967296,n.defaults={metadata:!1,unpackSingleArgs:!0},n.isCommonJS=!!(typeof module<"u"&&module.exports),n.isNode=n.isCommonJS&&typeof window>"u",n.isElectron=!!(typeof process<"u"&&process.versions&&process.versions.electron),n.isBufferEnv=n.isNode||n.isElectron,n.isArray=function(s){return s&&Object.prototype.toString.call(s)==="[object Array]"},n.isTypedArrayView=function(s){return s.buffer&&s.buffer instanceof ArrayBuffer},n.isBuffer=function(s){return n.isBufferEnv&&s instanceof Buffer},n.Long=typeof Long<"u"?Long:void 0,n.TextDecoder=typeof TextDecoder<"u"?new TextDecoder("utf-8"):typeof util<"u"&&typeof(util.TextDecoder!=="undefined")?new util.TextDecoder("utf-8"):void 0,n.TextEncoder=typeof TextEncoder<"u"?new TextEncoder("utf-8"):typeof util<"u"&&typeof(util.TextEncoder!=="undefined")?new util.TextEncoder("utf-8"):void 0,n.dataView=function(s,e,t){return s.buffer?new DataView(s.buffer,e,t):s instanceof ArrayBuffer?new DataView(s,e,t):new DataView(new Uint8Array(s),e,t)},n.byteArray=function(s){if(s instanceof Uint8Array)return s;var e=s.buffer?s.buffer:s;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(s,null,2));return new Uint8Array(e)},n.nativeBuffer=function(s){return n.isBufferEnv?n.isBuffer(s)?s:Buffer.from(s.buffer?s:new Uint8Array(s)):n.isTypedArrayView(s)?s:new Uint8Array(s)},n.copyByteArray=function(s,e,t){if(n.isTypedArrayView(s)&&n.isTypedArrayView(e))e.set(s,t);else for(var r=t===void 0?0:t,i=Math.min(e.length-t,s.length),o=0,a=r;o<i;o++,a++)e[a]=s[o];return e},n.readString=function(s,e){for(var t=[],r=e.idx;r<s.byteLength;r++){var i=s.getUint8(r);if(i!==0)t.push(i);else{r++;break}}r=r+3&-4,e.idx=r;var o=n.isBufferEnv?n.readString.withBuffer:n.TextDecoder?n.readString.withTextDecoder:n.readString.raw;return o(t)},n.readString.raw=function(s){for(var e="",t=1e4,r=0;r<s.length;r+=t)e+=String.fromCharCode.apply(null,s.slice(r,r+t));return e},n.readString.withTextDecoder=function(s){var e=new Int8Array(s);return n.TextDecoder.decode(e)},n.readString.withBuffer=function(s){return Buffer.from(s).toString("utf-8")},n.writeString=function(s){var e=n.isBufferEnv?n.writeString.withBuffer:n.TextEncoder?n.writeString.withTextEncoder:null,t=s+"\0",r;e&&(r=e(t));for(var i=e?r.length:t.length,o=i+3&-4,a=new Uint8Array(o),c=0;c<i-1;c++){var l=e?r[c]:t.charCodeAt(c);a[c]=l}return a},n.writeString.withTextEncoder=function(s){return n.TextEncoder.encode(s)},n.writeString.withBuffer=function(s){return Buffer.from(s)},n.readPrimitive=function(s,e,t,r){var i=s[e](r.idx,!1);return r.idx+=t,i},n.writePrimitive=function(s,e,t,r,i){i=i===void 0?0:i;var o;return e?o=new Uint8Array(e.buffer):(o=new Uint8Array(r),e=new DataView(o.buffer)),e[t](i,s,!1),o},n.readInt32=function(s,e){return n.readPrimitive(s,"getInt32",4,e)},n.writeInt32=function(s,e,t){return n.writePrimitive(s,e,"setInt32",4,t)},n.readInt64=function(s,e){var t=n.readPrimitive(s,"getInt32",4,e),r=n.readPrimitive(s,"getInt32",4,e);return n.Long?new n.Long(r,t):{high:t,low:r,unsigned:!1}},n.writeInt64=function(s,e,t){var r=new Uint8Array(8);return r.set(n.writePrimitive(s.high,e,"setInt32",4,t),0),r.set(n.writePrimitive(s.low,e,"setInt32",4,t+4),4),r},n.readFloat32=function(s,e){return n.readPrimitive(s,"getFloat32",4,e)},n.writeFloat32=function(s,e,t){return n.writePrimitive(s,e,"setFloat32",4,t)},n.readFloat64=function(s,e){return n.readPrimitive(s,"getFloat64",8,e)},n.writeFloat64=function(s,e,t){return n.writePrimitive(s,e,"setFloat64",8,t)},n.readChar32=function(s,e){var t=n.readPrimitive(s,"getUint32",4,e);return String.fromCharCode(t)},n.writeChar32=function(s,e,t){var r=s.charCodeAt(0);if(!(r===void 0||r<-1))return n.writePrimitive(r,e,"setUint32",4,t)},n.readBlob=function(s,e){var t=n.readInt32(s,e),r=t+3&-4,i=new Uint8Array(s.buffer,e.idx,t);return e.idx+=r,i},n.writeBlob=function(s){s=n.byteArray(s);var e=s.byteLength,t=e+3&-4,r=4,i=t+r,o=new Uint8Array(i),a=new DataView(o.buffer);return n.writeInt32(e,a),o.set(s,r),o},n.readMIDIBytes=function(s,e){var t=new Uint8Array(s.buffer,e.idx,4);return e.idx+=4,t},n.writeMIDIBytes=function(s){s=n.byteArray(s);var e=new Uint8Array(4);return e.set(s),e},n.readColor=function(s,e){var t=new Uint8Array(s.buffer,e.idx,4),r=t[3]/255;return e.idx+=4,{r:t[0],g:t[1],b:t[2],a:r}},n.writeColor=function(s){var e=Math.round(s.a*255),t=new Uint8Array([s.r,s.g,s.b,e]);return t},n.readTrue=function(){return!0},n.readFalse=function(){return!1},n.readNull=function(){return null},n.readImpulse=function(){return 1},n.readTimeTag=function(s,e){var t=n.readPrimitive(s,"getUint32",4,e),r=n.readPrimitive(s,"getUint32",4,e),i=t===0&&r===1?Date.now():n.ntpToJSTime(t,r);return{raw:[t,r],native:i}},n.writeTimeTag=function(s){var e=s.raw?s.raw:n.jsToNTPTime(s.native),t=new Uint8Array(8),r=new DataView(t.buffer);return n.writeInt32(e[0],r,0),n.writeInt32(e[1],r,4),t},n.timeTag=function(s,e){s=s||0,e=e||Date.now();var t=e/1e3,r=Math.floor(t),i=t-r,o=Math.floor(s),a=s-o,c=i+a;if(c>1){var l=Math.floor(c),u=c-l;o+=l,c=u}var f=r+o+n.SECS_70YRS,h=Math.round(n.TWO_32*c);return{raw:[f,h]}},n.ntpToJSTime=function(s,e){var t=s-n.SECS_70YRS,r=e/n.TWO_32,i=(t+r)*1e3;return i},n.jsToNTPTime=function(s){var e=s/1e3,t=Math.floor(e),r=e-t,i=t+n.SECS_70YRS,o=Math.round(n.TWO_32*r);return[i,o]},n.readArguments=function(s,e,t){var r=n.readString(s,t);if(r.indexOf(",")!==0)throw new Error("A malformed type tag string was found while reading the arguments of an OSC message. String was: "+r," at offset: "+t.idx);var i=r.substring(1).split(""),o=[];return n.readArgumentsIntoArray(o,i,r,s,e,t),o},n.readArgument=function(s,e,t,r,i){var o=n.argumentTypes[s];if(!o)throw new Error("'"+s+"' is not a valid OSC type tag. Type tag string was: "+e);var a=o.reader,c=n[a](t,i);return r.metadata&&(c={type:s,value:c}),c},n.readArgumentsIntoArray=function(s,e,t,r,i,o){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=n.readArgumentsIntoArray([],h,t,r,i,o),a+=f+2}else l=n.readArgument(c,t,r,i,o),a++;s.push(l)}return s},n.writeArguments=function(s,e){var t=n.collectArguments(s,e);return n.joinParts(t)},n.joinParts=function(s){for(var e=new Uint8Array(s.byteLength),t=s.parts,r=0,i=0;i<t.length;i++){var o=t[i];n.copyByteArray(o,e,r),r+=o.length}return e},n.addDataPart=function(s,e){e.parts.push(s),e.byteLength+=s.length},n.writeArrayArguments=function(s,e){for(var t="[",r=0;r<s.length;r++){var i=s[r];t+=n.writeArgument(i,e)}return t+="]",t},n.writeArgument=function(s,e){if(n.isArray(s))return n.writeArrayArguments(s,e);var t=s.type,r=n.argumentTypes[t].writer;if(r){var i=n[r](s.value);n.addDataPart(i,e)}return s.type},n.collectArguments=function(s,e,t){n.isArray(s)||(s=typeof s>"u"?[]:[s]),t=t||{byteLength:0,parts:[]},e.metadata||(s=n.annotateArguments(s));for(var r=",",i=t.parts.length,o=0;o<s.length;o++){var a=s[o];r+=n.writeArgument(a,t)}var c=n.writeString(r);return t.byteLength+=c.byteLength,t.parts.splice(i,0,c),t},n.readMessage=function(s,e,t){e=e||n.defaults;var r=n.dataView(s,s.byteOffset,s.byteLength);t=t||{idx:0};var i=n.readString(r,t);return n.readMessageContents(i,r,e,t)},n.readMessageContents=function(s,e,t,r){if(s.indexOf("/")!==0)throw new Error("A malformed OSC address was found while reading an OSC message. String was: "+s);var i=n.readArguments(e,t,r);return{address:s,args:i.length===1&&t.unpackSingleArgs?i[0]:i}},n.collectMessageParts=function(s,e,t){return t=t||{byteLength:0,parts:[]},n.addDataPart(n.writeString(s.address),t),n.collectArguments(s.args,e,t)},n.writeMessage=function(s,e){if(e=e||n.defaults,!n.isValidMessage(s))throw new Error("An OSC message must contain a valid address. Message was: "+JSON.stringify(s,null,2));var t=n.collectMessageParts(s,e);return n.joinParts(t)},n.isValidMessage=function(s){return s.address&&s.address.indexOf("/")===0},n.readBundle=function(s,e,t){return n.readPacket(s,e,t)},n.collectBundlePackets=function(s,e,t){t=t||{byteLength:0,parts:[]},n.addDataPart(n.writeString("#bundle"),t),n.addDataPart(n.writeTimeTag(s.timeTag),t);for(var r=0;r<s.packets.length;r++){var i=s.packets[r],o=i.address?n.collectMessageParts:n.collectBundlePackets,a=o(i,e);t.byteLength+=a.byteLength,n.addDataPart(n.writeInt32(a.byteLength),t),t.parts=t.parts.concat(a.parts)}return t},n.writeBundle=function(s,e){if(!n.isValidBundle(s))throw new Error("An OSC bundle must contain 'timeTag' and 'packets' properties. Bundle was: "+JSON.stringify(s,null,2));e=e||n.defaults;var t=n.collectBundlePackets(s,e);return n.joinParts(t)},n.isValidBundle=function(s){return s.timeTag!==void 0&&s.packets!==void 0},n.readBundleContents=function(s,e,t,r){for(var i=n.readTimeTag(s,t),o=[];t.idx<r;){var a=n.readInt32(s,t),c=t.idx+a,l=n.readPacket(s,e,t,c);o.push(l)}return{timeTag:i,packets:o}},n.readPacket=function(s,e,t,r){var i=n.dataView(s,s.byteOffset,s.byteLength);r=r===void 0?i.byteLength:r,t=t||{idx:0};var o=n.readString(i,t),a=o[0];if(a==="#")return n.readBundleContents(i,e,t,r);if(a==="/")return n.readMessageContents(o,i,e,t);throw new Error("The header of an OSC packet didn't contain an OSC address or a #bundle string. Header was: "+o)},n.writePacket=function(s,e){if(n.isValidMessage(s))return n.writeMessage(s,e);if(n.isValidBundle(s))return n.writeBundle(s,e);throw new Error("The specified packet was not recognized as a valid OSC message or bundle. Packet was: "+JSON.stringify(s,null,2))},n.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"}},n.inferTypeForArgument=function(s){var e=typeof s;switch(e){case"boolean":return s?"T":"F";case"string":return"s";case"number":return"f";case"undefined":return"N";case"object":if(s===null)return"N";if(s instanceof Uint8Array||s instanceof ArrayBuffer)return"b";if(typeof s.high=="number"&&typeof s.low=="number")return"h";break}throw new Error("Can't infer OSC argument type for value: "+JSON.stringify(s,null,2))},n.annotateArguments=function(s){for(var e=[],t=0;t<s.length;t++){var r=s[t],i;if(typeof r=="object"&&r.type&&r.value!==void 0)i=r;else if(n.isArray(r))i=n.annotateArguments(r);else{var o=n.inferTypeForArgument(r);i={type:o,value:r}}e.push(i)}return e}})();var b=function(){};b.prototype.on=function(){};b.prototype.emit=function(){};b.prototype.removeListener=function(){};(function(){"use strict";n.supportsSerial=!1,n.firePacketEvents=function(e,t,r,i){t.address?e.emit("message",t,r,i):n.fireBundleEvents(e,t,r,i)},n.fireBundleEvents=function(e,t,r,i){e.emit("bundle",t,r,i);for(var o=0;o<t.packets.length;o++){var a=t.packets[o];n.firePacketEvents(e,a,t.timeTag,i)}},n.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)},n.Port=function(e){this.options=e||{},this.on("data",this.decodeOSC.bind(this))};var s=n.Port.prototype=Object.create(b.prototype);s.constructor=n.Port,s.send=function(e){var t=Array.prototype.slice.call(arguments),r=this.encodeOSC(e),i=n.nativeBuffer(r);t[0]=i,this.sendRaw.apply(this,t)},s.encodeOSC=function(e){e=e.buffer?e.buffer:e;var t;try{t=n.writePacket(e,this.options)}catch(r){this.emit("error",r)}return t},s.decodeOSC=function(e,t){e=n.byteArray(e),this.emit("raw",e,t);try{var r=n.readPacket(e,this.options);this.emit("osc",r,t),n.firePacketEvents(this,r,void 0,t)}catch(i){this.emit("error",i)}},n.SLIPPort=function(e){var t=this,r=this.options=e||{};r.useSLIP=r.useSLIP===void 0?!0:r.useSLIP,this.decoder=new slip.Decoder({onMessage:this.decodeOSC.bind(this),onError:function(o){t.emit("error",o)}});var i=r.useSLIP?this.decodeSLIPData:this.decodeOSC;this.on("data",i.bind(this))},s=n.SLIPPort.prototype=Object.create(n.Port.prototype),s.constructor=n.SLIPPort,s.encodeOSC=function(e){e=e.buffer?e.buffer:e;var t;try{var r=n.writePacket(e,this.options);t=slip.encode(r)}catch(i){this.emit("error",i)}return t},s.decodeSLIPData=function(e,t){this.decoder.decode(e,t)},n.relay=function(e,t,r,i,o,a){r=r||"message",i=i||"send",o=o||function(){},a=a?[null].concat(a):[];var c=function(l){a[0]=l,l=o(l),t[i].apply(t,a)};return e.on(r,c),{eventName:r,listener:c}},n.relayPorts=function(e,t,r){var i=r.raw?"raw":"osc",o=r.raw?"sendRaw":"send";return n.relay(e,t,i,o,r.transform)},n.stopRelaying=function(e,t){e.removeListener(t.eventName,t.listener)},n.Relay=function(e,t,r){var i=this.options=r||{};i.raw=!1,this.port1=e,this.port2=t,this.listen()},s=n.Relay.prototype=Object.create(b.prototype),s.constructor=n.Relay,s.open=function(){this.port1.open(),this.port2.open()},s.listen=function(){this.port1Spec&&this.port2Spec&&this.close(),this.port1Spec=n.relayPorts(this.port1,this.port2,this.options),this.port2Spec=n.relayPorts(this.port2,this.port1,this.options);var e=this.close.bind(this);this.port1.on("close",e),this.port2.on("close",e)},s.close=function(){n.stopRelaying(this.port1,this.port1Spec),n.stopRelaying(this.port2,this.port2Spec),this.emit("close",this.port1,this.port2)}})();(function(){"use strict";n.WebSocket=typeof WebSocket<"u"?WebSocket:void 0,n.WebSocketPort=function(e){n.Port.call(this,e),this.on("open",this.listen.bind(this)),this.socket=e.socket,this.socket&&(this.socket.readyState===1?(n.WebSocketPort.setupSocketForBinary(this.socket),this.emit("open",this.socket)):this.open())};var s=n.WebSocketPort.prototype=Object.create(n.Port.prototype);s.constructor=n.WebSocketPort,s.open=function(){(!this.socket||this.socket.readyState>1)&&(this.socket=new n.WebSocket(this.options.url)),n.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)}},s.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")},s.sendRaw=function(e){if(!this.socket||this.socket.readyState!==1){n.fireClosedPortSendError(this);return}this.socket.send(e)},s.close=function(e,t){this.socket.close(e,t)},n.WebSocketPort.setupSocketForBinary=function(e){e.binaryType=n.isNode?"nodebuffer":"arraybuffer"}})();var B=n,{readPacket:Ne,writePacket:Le,readMessage:ze,writeMessage:We,readBundle:Ve,writeBundle:$e}=n;var R=class{constructor(e=null){this.workerBaseURL=e,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}async init(e,t,r){if(this.initialized){console.warn("[ScsynthOSC] Already initialized");return}this.sharedBuffer=e,this.ringBufferBase=t,this.bufferConstants=r;try{this.workers.oscOut=new Worker(this.workerBaseURL+"osc_out_prescheduler_worker.js",{type:"module"}),this.workers.oscIn=new Worker(this.workerBaseURL+"osc_in_worker.js",{type:"module"}),this.workers.debug=new Worker(this.workerBaseURL+"debug_worker.js",{type:"module"}),this.setupWorkerHandlers();let i=[this.initWorker(this.workers.oscOut,"OSC SCHEDULER+WRITER"),this.initWorker(this.workers.oscIn,"OSC IN"),this.initWorker(this.workers.debug,"DEBUG")];await Promise.all(i),this.workers.oscIn.postMessage({type:"start"}),this.workers.debug.postMessage({type:"start"}),this.initialized=!0,this.callbacks.onInitialized&&this.callbacks.onInitialized()}catch(i){throw console.error("[ScsynthOSC] Initialization failed:",i),this.callbacks.onError&&this.callbacks.onError(i),i}}initWorker(e,t){return new Promise((r,i)=>{let o=setTimeout(()=>{i(new Error(`${t} worker initialization timeout`))},5e3),a=c=>{c.data.type==="initialized"&&(clearTimeout(o),e.removeEventListener("message",a),r())};e.addEventListener("message",a),e.postMessage({type:"init",sharedBuffer:this.sharedBuffer,ringBufferBase:this.ringBufferBase,bufferConstants:this.bufferConstants})})}setupWorkerHandlers(){this.workers.oscIn.onmessage=e=>{let t=e.data;switch(t.type){case"messages":t.messages.forEach(r=>{if(r.oscData&&(this.callbacks.onRawOSC&&this.callbacks.onRawOSC({oscData:r.oscData,sequence:r.sequence}),this.callbacks.onParsedOSC))try{let i={metadata:!1,unpackSingleArgs:!1},o=B.readPacket(r.oscData,i);this.callbacks.onParsedOSC(o)}catch(i){console.error("[ScsynthOSC] Failed to decode OSC message:",i,r)}});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(r=>{this.callbacks.onDebugMessage(r)});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;switch(t.type){case"error":console.error("[ScsynthOSC] OSC OUT error:",t.error),this.callbacks.onError&&this.callbacks.onError(t.error,"oscOut");break}}}send(e,t={}){if(!this.initialized){console.error("[ScsynthOSC] Not initialized");return}let{editorId:r=0,runTag:i="",audioTimeS:o=null,currentTimeS:a=null}=t;this.workers.oscOut.postMessage({type:"send",oscData:e,editorId:r,runTag:i,audioTimeS:o,currentTimeS:a})}sendImmediate(e){if(!this.initialized){console.error("[ScsynthOSC] Not initialized");return}this.workers.oscOut.postMessage({type:"sendImmediate",oscData:e})}cancelEditorTag(e,t){this.initialized&&this.workers.oscOut.postMessage({type:"cancelEditorTag",editorId:e,runTag:t})}cancelEditor(e){this.initialized&&this.workers.oscOut.postMessage({type:"cancelEditor",editorId:e})}cancelAll(){this.initialized&&this.workers.oscOut.postMessage({type:"cancelAll"})}clearDebug(){this.initialized&&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.initialized=!1}};var ae={5120:"i8",5121:"u8",5122:"i16",5123:"u16",5124:"i32",5125:"u32",5126:"f32"};var z={u8:1,u8c:1,i8:1,u16:2,i16:2,u32:4,i32:4,i64:8,u64:8,f32:4,f64:8};var ce={f32:Float32Array,f64:Float64Array},le={i8:Int8Array,i16:Int16Array,i32:Int32Array},ue={u8:Uint8Array,u8c:Uint8ClampedArray,u16:Uint16Array,u32:Uint32Array},fe={i64:BigInt64Array,u64:BigUint64Array},he={...ce,...le,...ue},de=s=>{let e=ae[s];return e!==void 0?e:s};function W(s,...e){let t=fe[s];return new(t||he[de(s)])(...e)}var I=(s,e)=>(e--,s+e&~e);var V=s=>typeof s=="number";var k=(s,e=t=>t!==void 0?": "+t:"")=>class extends Error{origMessage;constructor(t){super(s(t)+e(t)),this.origMessage=t!==void 0?String(t):""}};var pe=k(()=>"Assertion failed"),D=(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)?(s,e)=>{if(typeof s=="function"&&!s()||!s)throw new pe(typeof e=="function"?e():e)}:()=>{};var me=k(()=>"illegal argument(s)"),$=s=>{throw new me(s)};var G=0,H=1,Z=2,q=3,Y=4,A=5,Q=6,U=1,F=2,j=7*4,x=0,N=1,E=2*4,C=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?I(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,j/4),!e.skipInitialization){let t=e.align||8;D(t>=8,`invalid alignment: ${t}, must be a pow2 and >= 8`);let r=this.initialTop(t),i=e.end!=null?Math.min(e.end,this.buf.byteLength):this.buf.byteLength;r>=i&&$(`insufficient address range (0x${this.start.toString(16)} - 0x${i.toString(16)})`),this.align=t,this.doCompact=e.compact!==!1,this.doSplit=e.split!==!1,this.minSplit=e.minSplit||16,this.end=i,this.top=r,this._free=0,this._used=0}}stats(){let e=r=>{let i=0,o=0;for(;r;)i++,o+=this.blockSize(r),r=this.blockNext(r);return{count:i,size:o}},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,r=0){let i=this.mallocAs(e,t);return i?.fill(r),i}mallocAs(e,t){let r=this.malloc(t*z[e]);return r?W(e,this.buf,r,t):void 0}calloc(e,t=0){let r=this.malloc(e);return r&&this.u8.fill(t,r,r+e),r}malloc(e){if(e<=0)return 0;let t=I(e+E,this.align),r=this.end,i=this.top,o=this._free,a=0;for(;o;){let c=this.blockSize(o),l=o+c>=i;if(l||c>=t)return this.mallocTop(o,a,c,t,l);a=o,o=this.blockNext(o)}return o=i,i=o+t,i<=r?(this.initBlock(o,t,this._used),this._used=o,this.top=i,O(o)):0}mallocTop(e,t,r,i,o){if(o&&e+i>this.end)return 0;if(t?this.unlinkBlock(t,e):this._free=this.blockNext(e),this.setBlockNext(e,this._used),this._used=e,o)this.top=e+this.setBlockSize(e,i);else if(this.doSplit){let a=r-i;a>=this.minSplit&&this.splitBlock(e,i,a)}return O(e)}realloc(e,t){if(t<=0)return 0;let r=L(e),i=0,o=this._used,a=0;for(;o;){if(o===r){[i,a]=this.reallocBlock(o,t);break}o=this.blockNext(o)}return i&&i!==r&&this.u8.copyWithin(O(i),O(r),a),O(i)}reallocBlock(e,t){let r=this.blockSize(e),i=e+r,o=i>=this.top,a=I(t+E,this.align);if(a<=r){if(this.doSplit){let c=r-a;c>=this.minSplit?this.splitBlock(e,a,c):o&&(this.top=e+a)}else o&&(this.top=e+a);return[e,i]}return o&&e+a<this.end?(this.top=e+this.setBlockSize(e,a),[e,i]):(this.free(e),[L(this.malloc(t)),i])}reallocArray(e,t){if(e.buffer!==this.buf)return;let r=this.realloc(e.byteOffset,t*e.BYTES_PER_ELEMENT);return r?new e.constructor(this.buf,r,t):void 0}free(e){let t;if(V(e))t=e;else{if(e.buffer!==this.buf)return!1;t=e.byteOffset}t=L(t);let r=this._used,i=0;for(;r;){if(r===t)return i?this.unlinkBlock(i,r):this._used=this.blockNext(r),this.insert(r),this.doCompact&&this.compact(),!0;i=r,r=this.blockNext(r)}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[Y]}set align(e){this.state[Y]=e}get end(){return this.state[q]}set end(e){this.state[q]=e}get top(){return this.state[Z]}set top(e){this.state[Z]=e}get _free(){return this.state[G]}set _free(e){this.state[G]=e}get _used(){return this.state[H]}set _used(e){this.state[H]=e}get doCompact(){return!!(this.state[A]&U)}set doCompact(e){e?this.state[A]|=1<<U-1:this.state[A]&=~U}get doSplit(){return!!(this.state[A]&F)}set doSplit(e){e?this.state[A]|=1<<F-1:this.state[A]&=~F}get minSplit(){return this.state[Q]}set minSplit(e){D(e>E,`illegal min split threshold: ${e}, require at least ${E+1}`),this.state[Q]=e}blockSize(e){return this.u32[(e>>2)+x]}setBlockSize(e,t){return this.u32[(e>>2)+x]=t,t}blockNext(e){return this.u32[(e>>2)+N]}setBlockNext(e,t){this.u32[(e>>2)+N]=t}initBlock(e,t,r){let i=e>>>2;return this.u32[i+x]=t,this.u32[i+N]=r,e}unlinkBlock(e,t){this.setBlockNext(e,this.blockNext(t))}splitBlock(e,t,r){this.insert(this.initBlock(e+this.setBlockSize(e,t),r,0)),this.doCompact&&this.compact()}initialTop(e=this.align){return I(this.start+j+E,e)-E}compact(){let e=this._free,t=0,r=0,i,o=!1;for(;e;){for(i=e,r=this.blockNext(e);r&&i+this.blockSize(i)===r;)i=r,r=this.blockNext(r);if(i!==e){let a=i-e+this.blockSize(i);this.setBlockSize(e,a);let c=this.blockNext(i),l=this.blockNext(e);for(;l&&l!==c;){let u=this.blockNext(l);this.setBlockNext(l,0),l=u}this.setBlockNext(e,c),o=!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 o}insert(e){let t=this._free,r=0;for(;t&&!(e<=t);)r=t,t=this.blockNext(t);r?this.setBlockNext(r,e):this._free=e,this.setBlockNext(e,t)}},O=s=>s>0?s+E:0,L=s=>s>0?s-E:0;var Se=8,P=class{#i;#n;#o;#p;#t;#r;#e;#s;#c;constructor(e){let{audioContext:t,sharedBuffer:r,bufferPoolConfig:i,sampleBaseURL:o,audioPathMap:a={},maxBuffers:c=1024}=e;if(!t)throw new Error("BufferManager requires audioContext");if(!r||!(r instanceof SharedArrayBuffer))throw new Error("BufferManager requires sharedBuffer (SharedArrayBuffer)");if(!i||typeof i!="object")throw new Error("BufferManager requires bufferPoolConfig (object with start, size, align)");if(!Number.isFinite(i.start)||i.start<0)throw new Error("bufferPoolConfig.start must be a non-negative number");if(!Number.isFinite(i.size)||i.size<=0)throw new Error("bufferPoolConfig.size must be a positive number");if(a&&typeof a!="object")throw new Error("audioPathMap must be an object");if(!Number.isInteger(c)||c<=0)throw new Error("maxBuffers must be a positive integer");this.#o=t,this.#p=r,this.#i=o,this.#n=a,this.#t=new C({buf:r,start:i.start,size:i.size,align:Se}),this.#r=i.size,this.#e=new Map,this.#s=new Map,this.#c=new Map,this.GUARD_BEFORE=3,this.GUARD_AFTER=1,this.MAX_BUFFERS=c;let l=(i.size/(1024*1024)).toFixed(0),u=(i.start/(1024*1024)).toFixed(0)}#l(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.startsWith("/")||/^[a-zA-Z]:/.test(e))throw new Error(`Invalid audio path: path must be relative (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(this.#n[e])return this.#n[e];if(!this.#i)throw new Error(`sampleBaseURL not configured. Please set it in SuperSonic constructor options.
1
+ var n={},n=n||{};(function(){"use strict";n.SECS_70YRS=2208988800,n.TWO_32=4294967296,n.defaults={metadata:!1,unpackSingleArgs:!0},n.isCommonJS=!!(typeof module<"u"&&module.exports),n.isNode=n.isCommonJS&&typeof window>"u",n.isElectron=!!(typeof process<"u"&&process.versions&&process.versions.electron),n.isBufferEnv=n.isNode||n.isElectron,n.isArray=function(s){return s&&Object.prototype.toString.call(s)==="[object Array]"},n.isTypedArrayView=function(s){return s.buffer&&s.buffer instanceof ArrayBuffer},n.isBuffer=function(s){return n.isBufferEnv&&s instanceof Buffer},n.Long=typeof Long<"u"?Long:void 0,n.TextDecoder=typeof TextDecoder<"u"?new TextDecoder("utf-8"):typeof util<"u"&&typeof(util.TextDecoder!=="undefined")?new util.TextDecoder("utf-8"):void 0,n.TextEncoder=typeof TextEncoder<"u"?new TextEncoder("utf-8"):typeof util<"u"&&typeof(util.TextEncoder!=="undefined")?new util.TextEncoder("utf-8"):void 0,n.dataView=function(s,e,t){return s.buffer?new DataView(s.buffer,e,t):s instanceof ArrayBuffer?new DataView(s,e,t):new DataView(new Uint8Array(s),e,t)},n.byteArray=function(s){if(s instanceof Uint8Array)return s;var e=s.buffer?s.buffer:s;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(s,null,2));return new Uint8Array(e)},n.nativeBuffer=function(s){return n.isBufferEnv?n.isBuffer(s)?s:Buffer.from(s.buffer?s:new Uint8Array(s)):n.isTypedArrayView(s)?s:new Uint8Array(s)},n.copyByteArray=function(s,e,t){if(n.isTypedArrayView(s)&&n.isTypedArrayView(e))e.set(s,t);else for(var r=t===void 0?0:t,i=Math.min(e.length-t,s.length),o=0,a=r;o<i;o++,a++)e[a]=s[o];return e},n.readString=function(s,e){for(var t=[],r=e.idx;r<s.byteLength;r++){var i=s.getUint8(r);if(i!==0)t.push(i);else{r++;break}}r=r+3&-4,e.idx=r;var o=n.isBufferEnv?n.readString.withBuffer:n.TextDecoder?n.readString.withTextDecoder:n.readString.raw;return o(t)},n.readString.raw=function(s){for(var e="",t=1e4,r=0;r<s.length;r+=t)e+=String.fromCharCode.apply(null,s.slice(r,r+t));return e},n.readString.withTextDecoder=function(s){var e=new Int8Array(s);return n.TextDecoder.decode(e)},n.readString.withBuffer=function(s){return Buffer.from(s).toString("utf-8")},n.writeString=function(s){var e=n.isBufferEnv?n.writeString.withBuffer:n.TextEncoder?n.writeString.withTextEncoder:null,t=s+"\0",r;e&&(r=e(t));for(var i=e?r.length:t.length,o=i+3&-4,a=new Uint8Array(o),l=0;l<i-1;l++){var c=e?r[l]:t.charCodeAt(l);a[l]=c}return a},n.writeString.withTextEncoder=function(s){return n.TextEncoder.encode(s)},n.writeString.withBuffer=function(s){return Buffer.from(s)},n.readPrimitive=function(s,e,t,r){var i=s[e](r.idx,!1);return r.idx+=t,i},n.writePrimitive=function(s,e,t,r,i){i=i===void 0?0:i;var o;return e?o=new Uint8Array(e.buffer):(o=new Uint8Array(r),e=new DataView(o.buffer)),e[t](i,s,!1),o},n.readInt32=function(s,e){return n.readPrimitive(s,"getInt32",4,e)},n.writeInt32=function(s,e,t){return n.writePrimitive(s,e,"setInt32",4,t)},n.readInt64=function(s,e){var t=n.readPrimitive(s,"getInt32",4,e),r=n.readPrimitive(s,"getInt32",4,e);return n.Long?new n.Long(r,t):{high:t,low:r,unsigned:!1}},n.writeInt64=function(s,e,t){var r=new Uint8Array(8);return r.set(n.writePrimitive(s.high,e,"setInt32",4,t),0),r.set(n.writePrimitive(s.low,e,"setInt32",4,t+4),4),r},n.readFloat32=function(s,e){return n.readPrimitive(s,"getFloat32",4,e)},n.writeFloat32=function(s,e,t){return n.writePrimitive(s,e,"setFloat32",4,t)},n.readFloat64=function(s,e){return n.readPrimitive(s,"getFloat64",8,e)},n.writeFloat64=function(s,e,t){return n.writePrimitive(s,e,"setFloat64",8,t)},n.readChar32=function(s,e){var t=n.readPrimitive(s,"getUint32",4,e);return String.fromCharCode(t)},n.writeChar32=function(s,e,t){var r=s.charCodeAt(0);if(!(r===void 0||r<-1))return n.writePrimitive(r,e,"setUint32",4,t)},n.readBlob=function(s,e){var t=n.readInt32(s,e),r=t+3&-4,i=new Uint8Array(s.buffer,e.idx,t);return e.idx+=r,i},n.writeBlob=function(s){s=n.byteArray(s);var e=s.byteLength,t=e+3&-4,r=4,i=t+r,o=new Uint8Array(i),a=new DataView(o.buffer);return n.writeInt32(e,a),o.set(s,r),o},n.readMIDIBytes=function(s,e){var t=new Uint8Array(s.buffer,e.idx,4);return e.idx+=4,t},n.writeMIDIBytes=function(s){s=n.byteArray(s);var e=new Uint8Array(4);return e.set(s),e},n.readColor=function(s,e){var t=new Uint8Array(s.buffer,e.idx,4),r=t[3]/255;return e.idx+=4,{r:t[0],g:t[1],b:t[2],a:r}},n.writeColor=function(s){var e=Math.round(s.a*255),t=new Uint8Array([s.r,s.g,s.b,e]);return t},n.readTrue=function(){return!0},n.readFalse=function(){return!1},n.readNull=function(){return null},n.readImpulse=function(){return 1},n.readTimeTag=function(s,e){var t=n.readPrimitive(s,"getUint32",4,e),r=n.readPrimitive(s,"getUint32",4,e),i=t===0&&r===1?Date.now():n.ntpToJSTime(t,r);return{raw:[t,r],native:i}},n.writeTimeTag=function(s){var e=s.raw?s.raw:n.jsToNTPTime(s.native),t=new Uint8Array(8),r=new DataView(t.buffer);return n.writeInt32(e[0],r,0),n.writeInt32(e[1],r,4),t},n.timeTag=function(s,e){s=s||0,e=e||Date.now();var t=e/1e3,r=Math.floor(t),i=t-r,o=Math.floor(s),a=s-o,l=i+a;if(l>1){var c=Math.floor(l),u=l-c;o+=c,l=u}var f=r+o+n.SECS_70YRS,h=Math.round(n.TWO_32*l);return{raw:[f,h]}},n.ntpToJSTime=function(s,e){var t=s-n.SECS_70YRS,r=e/n.TWO_32,i=(t+r)*1e3;return i},n.jsToNTPTime=function(s){var e=s/1e3,t=Math.floor(e),r=e-t,i=t+n.SECS_70YRS,o=Math.round(n.TWO_32*r);return[i,o]},n.readArguments=function(s,e,t){var r=n.readString(s,t);if(r.indexOf(",")!==0)throw new Error("A malformed type tag string was found while reading the arguments of an OSC message. String was: "+r," at offset: "+t.idx);var i=r.substring(1).split(""),o=[];return n.readArgumentsIntoArray(o,i,r,s,e,t),o},n.readArgument=function(s,e,t,r,i){var o=n.argumentTypes[s];if(!o)throw new Error("'"+s+"' is not a valid OSC type tag. Type tag string was: "+e);var a=o.reader,l=n[a](t,i);return r.metadata&&(l={type:s,value:l}),l},n.readArgumentsIntoArray=function(s,e,t,r,i,o){for(var a=0;a<e.length;){var l=e[a],c;if(l==="["){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);c=n.readArgumentsIntoArray([],h,t,r,i,o),a+=f+2}else c=n.readArgument(l,t,r,i,o),a++;s.push(c)}return s},n.writeArguments=function(s,e){var t=n.collectArguments(s,e);return n.joinParts(t)},n.joinParts=function(s){for(var e=new Uint8Array(s.byteLength),t=s.parts,r=0,i=0;i<t.length;i++){var o=t[i];n.copyByteArray(o,e,r),r+=o.length}return e},n.addDataPart=function(s,e){e.parts.push(s),e.byteLength+=s.length},n.writeArrayArguments=function(s,e){for(var t="[",r=0;r<s.length;r++){var i=s[r];t+=n.writeArgument(i,e)}return t+="]",t},n.writeArgument=function(s,e){if(n.isArray(s))return n.writeArrayArguments(s,e);var t=s.type,r=n.argumentTypes[t].writer;if(r){var i=n[r](s.value);n.addDataPart(i,e)}return s.type},n.collectArguments=function(s,e,t){n.isArray(s)||(s=typeof s>"u"?[]:[s]),t=t||{byteLength:0,parts:[]},e.metadata||(s=n.annotateArguments(s));for(var r=",",i=t.parts.length,o=0;o<s.length;o++){var a=s[o];r+=n.writeArgument(a,t)}var l=n.writeString(r);return t.byteLength+=l.byteLength,t.parts.splice(i,0,l),t},n.readMessage=function(s,e,t){e=e||n.defaults;var r=n.dataView(s,s.byteOffset,s.byteLength);t=t||{idx:0};var i=n.readString(r,t);return n.readMessageContents(i,r,e,t)},n.readMessageContents=function(s,e,t,r){if(s.indexOf("/")!==0)throw new Error("A malformed OSC address was found while reading an OSC message. String was: "+s);var i=n.readArguments(e,t,r);return{address:s,args:i.length===1&&t.unpackSingleArgs?i[0]:i}},n.collectMessageParts=function(s,e,t){return t=t||{byteLength:0,parts:[]},n.addDataPart(n.writeString(s.address),t),n.collectArguments(s.args,e,t)},n.writeMessage=function(s,e){if(e=e||n.defaults,!n.isValidMessage(s))throw new Error("An OSC message must contain a valid address. Message was: "+JSON.stringify(s,null,2));var t=n.collectMessageParts(s,e);return n.joinParts(t)},n.isValidMessage=function(s){return s.address&&s.address.indexOf("/")===0},n.readBundle=function(s,e,t){return n.readPacket(s,e,t)},n.collectBundlePackets=function(s,e,t){t=t||{byteLength:0,parts:[]},n.addDataPart(n.writeString("#bundle"),t),n.addDataPart(n.writeTimeTag(s.timeTag),t);for(var r=0;r<s.packets.length;r++){var i=s.packets[r],o=i.address?n.collectMessageParts:n.collectBundlePackets,a=o(i,e);t.byteLength+=a.byteLength,n.addDataPart(n.writeInt32(a.byteLength),t),t.parts=t.parts.concat(a.parts)}return t},n.writeBundle=function(s,e){if(!n.isValidBundle(s))throw new Error("An OSC bundle must contain 'timeTag' and 'packets' properties. Bundle was: "+JSON.stringify(s,null,2));e=e||n.defaults;var t=n.collectBundlePackets(s,e);return n.joinParts(t)},n.isValidBundle=function(s){return s.timeTag!==void 0&&s.packets!==void 0},n.readBundleContents=function(s,e,t,r){for(var i=n.readTimeTag(s,t),o=[];t.idx<r;){var a=n.readInt32(s,t),l=t.idx+a,c=n.readPacket(s,e,t,l);o.push(c)}return{timeTag:i,packets:o}},n.readPacket=function(s,e,t,r){var i=n.dataView(s,s.byteOffset,s.byteLength);r=r===void 0?i.byteLength:r,t=t||{idx:0};var o=n.readString(i,t),a=o[0];if(a==="#")return n.readBundleContents(i,e,t,r);if(a==="/")return n.readMessageContents(o,i,e,t);throw new Error("The header of an OSC packet didn't contain an OSC address or a #bundle string. Header was: "+o)},n.writePacket=function(s,e){if(n.isValidMessage(s))return n.writeMessage(s,e);if(n.isValidBundle(s))return n.writeBundle(s,e);throw new Error("The specified packet was not recognized as a valid OSC message or bundle. Packet was: "+JSON.stringify(s,null,2))},n.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"}},n.inferTypeForArgument=function(s){var e=typeof s;switch(e){case"boolean":return s?"T":"F";case"string":return"s";case"number":return"f";case"undefined":return"N";case"object":if(s===null)return"N";if(s instanceof Uint8Array||s instanceof ArrayBuffer)return"b";if(typeof s.high=="number"&&typeof s.low=="number")return"h";break}throw new Error("Can't infer OSC argument type for value: "+JSON.stringify(s,null,2))},n.annotateArguments=function(s){for(var e=[],t=0;t<s.length;t++){var r=s[t],i;if(typeof r=="object"&&r.type&&r.value!==void 0)i=r;else if(n.isArray(r))i=n.annotateArguments(r);else{var o=n.inferTypeForArgument(r);i={type:o,value:r}}e.push(i)}return e}})();var b=function(){};b.prototype.on=function(){};b.prototype.emit=function(){};b.prototype.removeListener=function(){};(function(){"use strict";n.supportsSerial=!1,n.firePacketEvents=function(e,t,r,i){t.address?e.emit("message",t,r,i):n.fireBundleEvents(e,t,r,i)},n.fireBundleEvents=function(e,t,r,i){e.emit("bundle",t,r,i);for(var o=0;o<t.packets.length;o++){var a=t.packets[o];n.firePacketEvents(e,a,t.timeTag,i)}},n.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)},n.Port=function(e){this.options=e||{},this.on("data",this.decodeOSC.bind(this))};var s=n.Port.prototype=Object.create(b.prototype);s.constructor=n.Port,s.send=function(e){var t=Array.prototype.slice.call(arguments),r=this.encodeOSC(e),i=n.nativeBuffer(r);t[0]=i,this.sendRaw.apply(this,t)},s.encodeOSC=function(e){e=e.buffer?e.buffer:e;var t;try{t=n.writePacket(e,this.options)}catch(r){this.emit("error",r)}return t},s.decodeOSC=function(e,t){e=n.byteArray(e),this.emit("raw",e,t);try{var r=n.readPacket(e,this.options);this.emit("osc",r,t),n.firePacketEvents(this,r,void 0,t)}catch(i){this.emit("error",i)}},n.SLIPPort=function(e){var t=this,r=this.options=e||{};r.useSLIP=r.useSLIP===void 0?!0:r.useSLIP,this.decoder=new slip.Decoder({onMessage:this.decodeOSC.bind(this),onError:function(o){t.emit("error",o)}});var i=r.useSLIP?this.decodeSLIPData:this.decodeOSC;this.on("data",i.bind(this))},s=n.SLIPPort.prototype=Object.create(n.Port.prototype),s.constructor=n.SLIPPort,s.encodeOSC=function(e){e=e.buffer?e.buffer:e;var t;try{var r=n.writePacket(e,this.options);t=slip.encode(r)}catch(i){this.emit("error",i)}return t},s.decodeSLIPData=function(e,t){this.decoder.decode(e,t)},n.relay=function(e,t,r,i,o,a){r=r||"message",i=i||"send",o=o||function(){},a=a?[null].concat(a):[];var l=function(c){a[0]=c,c=o(c),t[i].apply(t,a)};return e.on(r,l),{eventName:r,listener:l}},n.relayPorts=function(e,t,r){var i=r.raw?"raw":"osc",o=r.raw?"sendRaw":"send";return n.relay(e,t,i,o,r.transform)},n.stopRelaying=function(e,t){e.removeListener(t.eventName,t.listener)},n.Relay=function(e,t,r){var i=this.options=r||{};i.raw=!1,this.port1=e,this.port2=t,this.listen()},s=n.Relay.prototype=Object.create(b.prototype),s.constructor=n.Relay,s.open=function(){this.port1.open(),this.port2.open()},s.listen=function(){this.port1Spec&&this.port2Spec&&this.close(),this.port1Spec=n.relayPorts(this.port1,this.port2,this.options),this.port2Spec=n.relayPorts(this.port2,this.port1,this.options);var e=this.close.bind(this);this.port1.on("close",e),this.port2.on("close",e)},s.close=function(){n.stopRelaying(this.port1,this.port1Spec),n.stopRelaying(this.port2,this.port2Spec),this.emit("close",this.port1,this.port2)}})();(function(){"use strict";n.WebSocket=typeof WebSocket<"u"?WebSocket:void 0,n.WebSocketPort=function(e){n.Port.call(this,e),this.on("open",this.listen.bind(this)),this.socket=e.socket,this.socket&&(this.socket.readyState===1?(n.WebSocketPort.setupSocketForBinary(this.socket),this.emit("open",this.socket)):this.open())};var s=n.WebSocketPort.prototype=Object.create(n.Port.prototype);s.constructor=n.WebSocketPort,s.open=function(){(!this.socket||this.socket.readyState>1)&&(this.socket=new n.WebSocket(this.options.url)),n.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)}},s.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")},s.sendRaw=function(e){if(!this.socket||this.socket.readyState!==1){n.fireClosedPortSendError(this);return}this.socket.send(e)},s.close=function(e,t){this.socket.close(e,t)},n.WebSocketPort.setupSocketForBinary=function(e){e.binaryType=n.isNode?"nodebuffer":"arraybuffer"}})();var B=n,{readPacket:He,writePacket:Ge,readMessage:Ze,writeMessage:qe,readBundle:Ye,writeBundle:Qe}=n;var R=class{constructor(e=null){this.workerBaseURL=e,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}async init(e,t,r){if(this.initialized){console.warn("[ScsynthOSC] Already initialized");return}this.sharedBuffer=e,this.ringBufferBase=t,this.bufferConstants=r;try{this.workers.oscOut=new Worker(this.workerBaseURL+"osc_out_prescheduler_worker.js",{type:"module"}),this.workers.oscIn=new Worker(this.workerBaseURL+"osc_in_worker.js",{type:"module"}),this.workers.debug=new Worker(this.workerBaseURL+"debug_worker.js",{type:"module"}),this.setupWorkerHandlers();let i=[this.initWorker(this.workers.oscOut,"OSC SCHEDULER+WRITER"),this.initWorker(this.workers.oscIn,"OSC IN"),this.initWorker(this.workers.debug,"DEBUG")];await Promise.all(i),this.workers.oscIn.postMessage({type:"start"}),this.workers.debug.postMessage({type:"start"}),this.initialized=!0,this.callbacks.onInitialized&&this.callbacks.onInitialized()}catch(i){throw console.error("[ScsynthOSC] Initialization failed:",i),this.callbacks.onError&&this.callbacks.onError(i),i}}initWorker(e,t){return new Promise((r,i)=>{let o=setTimeout(()=>{i(new Error(`${t} worker initialization timeout`))},5e3),a=l=>{l.data.type==="initialized"&&(clearTimeout(o),e.removeEventListener("message",a),r())};e.addEventListener("message",a),e.postMessage({type:"init",sharedBuffer:this.sharedBuffer,ringBufferBase:this.ringBufferBase,bufferConstants:this.bufferConstants})})}setupWorkerHandlers(){this.workers.oscIn.onmessage=e=>{let t=e.data;switch(t.type){case"messages":t.messages.forEach(r=>{if(r.oscData&&(this.callbacks.onRawOSC&&this.callbacks.onRawOSC({oscData:r.oscData,sequence:r.sequence}),this.callbacks.onParsedOSC))try{let i={metadata:!1,unpackSingleArgs:!1},o=B.readPacket(r.oscData,i);this.callbacks.onParsedOSC(o)}catch(i){console.error("[ScsynthOSC] Failed to decode OSC message:",i,r)}});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(r=>{this.callbacks.onDebugMessage(r)});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;switch(t.type){case"error":console.error("[ScsynthOSC] OSC OUT error:",t.error),this.callbacks.onError&&this.callbacks.onError(t.error,"oscOut");break}}}send(e,t={}){if(!this.initialized){console.error("[ScsynthOSC] Not initialized");return}let{editorId:r=0,runTag:i="",audioTimeS:o=null,currentTimeS:a=null}=t;this.workers.oscOut.postMessage({type:"send",oscData:e,editorId:r,runTag:i,audioTimeS:o,currentTimeS:a})}sendImmediate(e){if(!this.initialized){console.error("[ScsynthOSC] Not initialized");return}this.workers.oscOut.postMessage({type:"sendImmediate",oscData:e})}cancelEditorTag(e,t){this.initialized&&this.workers.oscOut.postMessage({type:"cancelEditorTag",editorId:e,runTag:t})}cancelEditor(e){this.initialized&&this.workers.oscOut.postMessage({type:"cancelEditor",editorId:e})}cancelAll(){this.initialized&&this.workers.oscOut.postMessage({type:"cancelAll"})}clearDebug(){this.initialized&&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.initialized=!1}};var ae={5120:"i8",5121:"u8",5122:"i16",5123:"u16",5124:"i32",5125:"u32",5126:"f32"};var z={u8:1,u8c:1,i8:1,u16:2,i16:2,u32:4,i32:4,i64:8,u64:8,f32:4,f64:8};var le={f32:Float32Array,f64:Float64Array},ce={i8:Int8Array,i16:Int16Array,i32:Int32Array},ue={u8:Uint8Array,u8c:Uint8ClampedArray,u16:Uint16Array,u32:Uint32Array},fe={i64:BigInt64Array,u64:BigUint64Array},he={...le,...ce,...ue},de=s=>{let e=ae[s];return e!==void 0?e:s};function $(s,...e){let t=fe[s];return new(t||he[de(s)])(...e)}var M=(s,e)=>(e--,s+e&~e);var W=s=>typeof s=="number";var k=(s,e=t=>t!==void 0?": "+t:"")=>class extends Error{origMessage;constructor(t){super(s(t)+e(t)),this.origMessage=t!==void 0?String(t):""}};var pe=k(()=>"Assertion failed"),D=(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)?(s,e)=>{if(typeof s=="function"&&!s()||!s)throw new pe(typeof e=="function"?e():e)}:()=>{};var me=k(()=>"illegal argument(s)"),V=s=>{throw new me(s)};var H=0,G=1,Z=2,q=3,Y=4,A=5,Q=6,U=1,F=2,j=7*4,x=0,N=1,g=2*4,P=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?M(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,j/4),!e.skipInitialization){let t=e.align||8;D(t>=8,`invalid alignment: ${t}, must be a pow2 and >= 8`);let r=this.initialTop(t),i=e.end!=null?Math.min(e.end,this.buf.byteLength):this.buf.byteLength;r>=i&&V(`insufficient address range (0x${this.start.toString(16)} - 0x${i.toString(16)})`),this.align=t,this.doCompact=e.compact!==!1,this.doSplit=e.split!==!1,this.minSplit=e.minSplit||16,this.end=i,this.top=r,this._free=0,this._used=0}}stats(){let e=r=>{let i=0,o=0;for(;r;)i++,o+=this.blockSize(r),r=this.blockNext(r);return{count:i,size:o}},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,r=0){let i=this.mallocAs(e,t);return i?.fill(r),i}mallocAs(e,t){let r=this.malloc(t*z[e]);return r?$(e,this.buf,r,t):void 0}calloc(e,t=0){let r=this.malloc(e);return r&&this.u8.fill(t,r,r+e),r}malloc(e){if(e<=0)return 0;let t=M(e+g,this.align),r=this.end,i=this.top,o=this._free,a=0;for(;o;){let l=this.blockSize(o),c=o+l>=i;if(c||l>=t)return this.mallocTop(o,a,l,t,c);a=o,o=this.blockNext(o)}return o=i,i=o+t,i<=r?(this.initBlock(o,t,this._used),this._used=o,this.top=i,v(o)):0}mallocTop(e,t,r,i,o){if(o&&e+i>this.end)return 0;if(t?this.unlinkBlock(t,e):this._free=this.blockNext(e),this.setBlockNext(e,this._used),this._used=e,o)this.top=e+this.setBlockSize(e,i);else if(this.doSplit){let a=r-i;a>=this.minSplit&&this.splitBlock(e,i,a)}return v(e)}realloc(e,t){if(t<=0)return 0;let r=L(e),i=0,o=this._used,a=0;for(;o;){if(o===r){[i,a]=this.reallocBlock(o,t);break}o=this.blockNext(o)}return i&&i!==r&&this.u8.copyWithin(v(i),v(r),a),v(i)}reallocBlock(e,t){let r=this.blockSize(e),i=e+r,o=i>=this.top,a=M(t+g,this.align);if(a<=r){if(this.doSplit){let l=r-a;l>=this.minSplit?this.splitBlock(e,a,l):o&&(this.top=e+a)}else o&&(this.top=e+a);return[e,i]}return o&&e+a<this.end?(this.top=e+this.setBlockSize(e,a),[e,i]):(this.free(e),[L(this.malloc(t)),i])}reallocArray(e,t){if(e.buffer!==this.buf)return;let r=this.realloc(e.byteOffset,t*e.BYTES_PER_ELEMENT);return r?new e.constructor(this.buf,r,t):void 0}free(e){let t;if(W(e))t=e;else{if(e.buffer!==this.buf)return!1;t=e.byteOffset}t=L(t);let r=this._used,i=0;for(;r;){if(r===t)return i?this.unlinkBlock(i,r):this._used=this.blockNext(r),this.insert(r),this.doCompact&&this.compact(),!0;i=r,r=this.blockNext(r)}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[Y]}set align(e){this.state[Y]=e}get end(){return this.state[q]}set end(e){this.state[q]=e}get top(){return this.state[Z]}set top(e){this.state[Z]=e}get _free(){return this.state[H]}set _free(e){this.state[H]=e}get _used(){return this.state[G]}set _used(e){this.state[G]=e}get doCompact(){return!!(this.state[A]&U)}set doCompact(e){e?this.state[A]|=1<<U-1:this.state[A]&=~U}get doSplit(){return!!(this.state[A]&F)}set doSplit(e){e?this.state[A]|=1<<F-1:this.state[A]&=~F}get minSplit(){return this.state[Q]}set minSplit(e){D(e>g,`illegal min split threshold: ${e}, require at least ${g+1}`),this.state[Q]=e}blockSize(e){return this.u32[(e>>2)+x]}setBlockSize(e,t){return this.u32[(e>>2)+x]=t,t}blockNext(e){return this.u32[(e>>2)+N]}setBlockNext(e,t){this.u32[(e>>2)+N]=t}initBlock(e,t,r){let i=e>>>2;return this.u32[i+x]=t,this.u32[i+N]=r,e}unlinkBlock(e,t){this.setBlockNext(e,this.blockNext(t))}splitBlock(e,t,r){this.insert(this.initBlock(e+this.setBlockSize(e,t),r,0)),this.doCompact&&this.compact()}initialTop(e=this.align){return M(this.start+j+g,e)-g}compact(){let e=this._free,t=0,r=0,i,o=!1;for(;e;){for(i=e,r=this.blockNext(e);r&&i+this.blockSize(i)===r;)i=r,r=this.blockNext(r);if(i!==e){let a=i-e+this.blockSize(i);this.setBlockSize(e,a);let l=this.blockNext(i),c=this.blockNext(e);for(;c&&c!==l;){let u=this.blockNext(c);this.setBlockNext(c,0),c=u}this.setBlockNext(e,l),o=!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 o}insert(e){let t=this._free,r=0;for(;t&&!(e<=t);)r=t,t=this.blockNext(t);r?this.setBlockNext(r,e):this._free=e,this.setBlockNext(e,t)}},v=s=>s>0?s+g:0,L=s=>s>0?s-g:0;var Se=8,C=class{#r;#n;#o;#d;#t;#i;#e;#s;#l;constructor(e){let{audioContext:t,sharedBuffer:r,bufferPoolConfig:i,sampleBaseURL:o,audioPathMap:a={},maxBuffers:l=1024}=e;if(!t)throw new Error("BufferManager requires audioContext");if(!r||!(r instanceof SharedArrayBuffer))throw new Error("BufferManager requires sharedBuffer (SharedArrayBuffer)");if(!i||typeof i!="object")throw new Error("BufferManager requires bufferPoolConfig (object with start, size, align)");if(!Number.isFinite(i.start)||i.start<0)throw new Error("bufferPoolConfig.start must be a non-negative number");if(!Number.isFinite(i.size)||i.size<=0)throw new Error("bufferPoolConfig.size must be a positive number");if(a&&typeof a!="object")throw new Error("audioPathMap must be an object");if(!Number.isInteger(l)||l<=0)throw new Error("maxBuffers must be a positive integer");this.#o=t,this.#d=r,this.#r=o,this.#n=a,this.#t=new P({buf:r,start:i.start,size:i.size,align:Se}),this.#i=i.size,this.#e=new Map,this.#s=new Map,this.#l=new Map,this.GUARD_BEFORE=3,this.GUARD_AFTER=1,this.MAX_BUFFERS=l;let c=(i.size/(1024*1024)).toFixed(0),u=(i.start/(1024*1024)).toFixed(0)}#c(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.startsWith("/")||/^[a-zA-Z]:/.test(e))throw new Error(`Invalid audio path: path must be relative (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(this.#n[e])return this.#n[e];if(!this.#r)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}#S(e){if(!Number.isInteger(e)||e<0||e>=this.MAX_BUFFERS)throw new Error(`Invalid buffer number ${e} (must be 0-${this.MAX_BUFFERS-1})`)}async#g(e,t,r){let i=null,o=null,a=!1,c=await this.#_(e),l=!1;try{await this.#B(e);let{ptr:u,sizeBytes:f,...h}=await r();i=u;let{uuid:S,allocationComplete:m}=this.#u(e,t);o=S,this.#b(e,i,f,S,m),a=!0;let d=this.#A(e,S,m);return c(),l=!0,{ptr:i,uuid:S,allocationComplete:d,...h}}catch(u){throw a&&o?this.#f(e,o,!1):i&&this.#t.free(i),u}finally{l||c()}}async prepareFromFile(e){let{bufnum:t,path:r,startFrame:i=0,numFrames:o=0,channels:a=null}=e;return this.#S(t),this.#g(t,6e4,async()=>{let c=this.#l(r),l=await fetch(c);if(!l.ok)throw new Error(`Failed to fetch ${c}: ${l.status} ${l.statusText}`);let u=await l.arrayBuffer(),f=await this.#o.decodeAudioData(u),h=Math.max(0,Math.floor(i||0)),S=f.length-h,m=o&&o>0?Math.min(Math.floor(o),S):S;if(m<=0)throw new Error(`No audio frames available for buffer ${t} from ${r}`);let d=this.#E(a,f.numberOfChannels),w=d.length,p=m*w+(this.GUARD_BEFORE+this.GUARD_AFTER)*w,g=this.#y(p),y=new Float32Array(p),T=this.GUARD_BEFORE*w;for(let M=0;M<m;M++)for(let v=0;v<w;v++){let ne=d[v],oe=f.getChannelData(ne);y[T+M*w+v]=oe[h+M]}this.#a(g,y);let _=y.length*4;return{ptr:g,sizeBytes:_,numFrames:m,numChannels:w,sampleRate:f.sampleRate}})}async prepareEmpty(e){let{bufnum:t,numFrames:r,numChannels:i=1,sampleRate:o=null}=e;if(this.#S(t),!Number.isFinite(r)||r<=0)throw new Error(`/b_alloc requires a positive number of frames (got ${r})`);if(!Number.isFinite(i)||i<=0)throw new Error(`/b_alloc requires a positive channel count (got ${i})`);let a=Math.floor(r),c=Math.floor(i);return this.#g(t,5e3,async()=>{let l=a*c+(this.GUARD_BEFORE+this.GUARD_AFTER)*c,u=this.#y(l),f=new Float32Array(l);this.#a(u,f);let h=f.length*4;return{ptr:u,sizeBytes:h,numFrames:a,numChannels:c,sampleRate:o||this.#o.sampleRate}})}#E(e,t){return!e||e.length===0?Array.from({length:t},(r,i)=>i):(e.forEach(r=>{if(!Number.isInteger(r)||r<0||r>=t)throw new Error(`Channel ${r} is out of range (file has ${t} channels)`)}),e)}#y(e){let t=e*4,r=this.#t.malloc(t);if(r===0){let i=this.#t.stats(),o=((i.available||0)/(1024*1024)).toFixed(2),a=((i.total||0)/(1024*1024)).toFixed(2),c=(t/(1024*1024)).toFixed(2);throw new Error(`Buffer pool allocation failed: requested ${c}MB, available ${o}MB of ${a}MB total`)}return r}#a(e,t){new Float32Array(this.#p,e,t.length).set(t)}#d(e,t,r){return new Promise((i,o)=>{let a=setTimeout(()=>{this.#s.delete(e),o(new Error(`Buffer ${t} allocation timeout (${r}ms)`))},r);this.#s.set(e,{resolve:i,reject:o,timeout:a})})}#u(e,t){let r=crypto.randomUUID(),i=this.#d(r,e,t);return{uuid:r,allocationComplete:i}}async#_(e){let t=this.#c.get(e)||Promise.resolve(),r,i=new Promise(o=>{r=o});return this.#c.set(e,t.then(()=>i)),await t,()=>{r&&(r(),r=null),this.#c.get(e)===i&&this.#c.delete(e)}}#b(e,t,r,i,o){let a=this.#e.get(e),c={ptr:t,size:r,pendingToken:i,pendingPromise:o,previousAllocation:a?{ptr:a.ptr,size:a.size}:null};return this.#e.set(e,c),c}async#B(e){let t=this.#e.get(e);if(t&&t.pendingToken&&t.pendingPromise)try{await t.pendingPromise}catch{}}#A(e,t,r){return!r||typeof r.then!="function"?(this.#f(e,t,!0),Promise.resolve()):r.then(i=>(this.#f(e,t,!0),i)).catch(i=>{throw this.#f(e,t,!1),i})}#f(e,t,r){let i=this.#e.get(e);if(!i||i.pendingToken!==t)return;let o=i.previousAllocation;if(r){i.pendingToken=null,i.pendingPromise=null,i.previousAllocation=null,o?.ptr&&this.#t.free(o.ptr);return}i.ptr&&this.#t.free(i.ptr),i.pendingPromise=null,o?.ptr?this.#e.set(e,{ptr:o.ptr,size:o.size,pendingToken:null,previousAllocation:null}):this.#e.delete(e)}handleBufferFreed(e){let t=e[0],r=e[1],i=this.#e.get(t);if(!i){typeof r=="number"&&r!==0&&this.#t.free(r);return}if(typeof r=="number"&&r===i.ptr){this.#t.free(i.ptr),this.#e.delete(t);return}if(typeof r=="number"&&i.previousAllocation&&i.previousAllocation.ptr===r){this.#t.free(r),i.previousAllocation=null;return}this.#t.free(i.ptr),this.#e.delete(t)}handleBufferAllocated(e){let t=e[0],r=e[1],i=this.#s.get(t);i&&(clearTimeout(i.timeout),i.resolve({bufnum:r}),this.#s.delete(t))}allocate(e){let t=e*4,r=this.#t.malloc(t);if(r===0){let i=this.#t.stats(),o=((i.available||0)/(1024*1024)).toFixed(2),a=((i.total||0)/(1024*1024)).toFixed(2),c=(t/(1024*1024)).toFixed(2);console.error(`[BufferManager] Allocation failed: requested ${c}MB, available ${o}MB of ${a}MB total`)}return r}free(e){return this.#t.free(e)}getView(e,t){return new Float32Array(this.#p,e,t)}getStats(){return this.#t.stats()}getDiagnostics(){let e=this.#t.stats(),t=0,r=0;for(let i of this.#e.values())i&&(t+=i.size||0,i.pendingToken&&r++);return{active:this.#e.size,pending:r,bytesActive:t,pool:{total:this.#r,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.#s.entries())clearTimeout(t.timeout),t.reject(new Error("BufferManager destroyed"));this.#s.clear();for(let[e,t]of this.#e.entries())t.ptr&&this.#t.free(t.ptr);this.#e.clear(),this.#c.clear()}};var K={totalPages:1280,ringBufferReserved:1048576,bufferPoolOffset:17825792,bufferPoolSize:66060288,get totalMemory(){return this.bufferPoolOffset+this.bufferPoolSize},get wasmHeapSize(){return this.bufferPoolOffset-this.ringBufferReserved}};var J={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};function ge(s,e,t=0){for(let r=0;r<=t;r++)if(Atomics.compareExchange(s,e,0,1)===0)return!0;return!1}function Ee(s,e){Atomics.store(s,e,0)}function X({atomicView:s,dataView:e,uint8View:t,bufferConstants:r,ringBufferBase:i,controlIndices:o,oscMessage:a,maxSpins:c=0}){let l=a.length,u=r.MESSAGE_HEADER_SIZE+l;if(u>r.IN_BUFFER_SIZE-r.MESSAGE_HEADER_SIZE||!ge(s,o.IN_WRITE_LOCK,c))return!1;try{let f=Atomics.load(s,o.IN_HEAD),h=Atomics.load(s,o.IN_TAIL);if((r.IN_BUFFER_SIZE-1-f+h)%r.IN_BUFFER_SIZE<u)return!1;let m=Atomics.add(s,o.IN_SEQUENCE,1),d=r.IN_BUFFER_SIZE-f;if(u>d){let p=new Uint8Array(r.MESSAGE_HEADER_SIZE),g=new DataView(p.buffer);g.setUint32(0,r.MESSAGE_MAGIC,!0),g.setUint32(4,u,!0),g.setUint32(8,m,!0),g.setUint32(12,0,!0);let y=i+r.IN_BUFFER_START+f,T=i+r.IN_BUFFER_START;if(d>=r.MESSAGE_HEADER_SIZE){t.set(p,y);let _=d-r.MESSAGE_HEADER_SIZE;t.set(a.subarray(0,_),y+r.MESSAGE_HEADER_SIZE),t.set(a.subarray(_),T)}else{t.set(p.subarray(0,d),y),t.set(p.subarray(d),T);let _=r.MESSAGE_HEADER_SIZE-d;t.set(a,T+_)}}else{let p=i+r.IN_BUFFER_START+f;e.setUint32(p,r.MESSAGE_MAGIC,!0),e.setUint32(p+4,u,!0),e.setUint32(p+8,m,!0),e.setUint32(p+12,0,!0),t.set(a,p+r.MESSAGE_HEADER_SIZE)}Atomics.load(s,o.IN_HEAD);let w=(f+u)%r.IN_BUFFER_SIZE;return Atomics.store(s,o.IN_HEAD,w),!0}finally{Ee(s,o.IN_WRITE_LOCK)}}var se=class s{static osc={encode:e=>B.writePacket(e),decode:(e,t={metadata:!1})=>B.readPacket(e,t)};#i;#n;#o;#p;#t;#r;#e;#s;#c;#l;#S;#g;#E;#y;#a;#d;#u;#_;#b;#B;#A;#f=null;#M=!1;constructor(e={}){if(this.#a=!1,this.#d=!1,this.#u={},this.#t=null,this.#r=null,this.#e=null,this.#i=null,this.#n=null,this.#o=null,this.#s=null,this.loadedSynthDefs=new Set,this.onOSC=null,this.onMessage=null,this.onMessageSent=null,this.onMetricsUpdate=null,this.onDebugMessage=null,this.onInitialized=null,this.onError=null,!e.workerBaseURL||!e.wasmBaseURL)throw new Error(`SuperSonic requires workerBaseURL and wasmBaseURL options. Example:
4
+ Or install: npm install supersonic-scsynth-samples`);return this.#r+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#p(e,t,r){let i=null,o=null,a=!1,l=await this.#m(e),c=!1;try{await this.#B(e);let{ptr:u,sizeBytes:f,...h}=await r();i=u;let{uuid:S,allocationComplete:m}=this.#u(e,t);o=S,this.#b(e,i,f,S,m),a=!0;let d=this.#_(e,S,m);return l(),c=!0,{ptr:i,uuid:S,allocationComplete:d,...h}}catch(u){throw a&&o?this.#f(e,o,!1):i&&this.#t.free(i),u}finally{c||l()}}async prepareFromFile(e){let{bufnum:t,path:r,startFrame:i=0,numFrames:o=0,channels:a=null}=e;return this.#w(t),this.#p(t,6e4,async()=>{let l=this.#c(r),c=await fetch(l);if(!c.ok)throw new Error(`Failed to fetch ${l}: ${c.status} ${c.statusText}`);let u=await c.arrayBuffer(),f=await this.#o.decodeAudioData(u),h=Math.max(0,Math.floor(i||0)),S=f.length-h,m=o&&o>0?Math.min(Math.floor(o),S):S;if(m<=0)throw new Error(`No audio frames available for buffer ${t} from ${r}`);let d=this.#g(a,f.numberOfChannels),w=d.length,p=m*w+(this.GUARD_BEFORE+this.GUARD_AFTER)*w,E=this.#y(p),y=new Float32Array(p),T=this.GUARD_BEFORE*w;for(let O=0;O<m;O++)for(let I=0;I<w;I++){let ne=d[I],oe=f.getChannelData(ne);y[T+O*w+I]=oe[h+O]}this.#a(E,y);let _=y.length*4;return{ptr:E,sizeBytes:_,numFrames:m,numChannels:w,sampleRate:f.sampleRate}})}async prepareEmpty(e){let{bufnum:t,numFrames:r,numChannels:i=1,sampleRate:o=null}=e;if(this.#w(t),!Number.isFinite(r)||r<=0)throw new Error(`/b_alloc requires a positive number of frames (got ${r})`);if(!Number.isFinite(i)||i<=0)throw new Error(`/b_alloc requires a positive channel count (got ${i})`);let a=Math.floor(r),l=Math.floor(i);return this.#p(t,5e3,async()=>{let c=a*l+(this.GUARD_BEFORE+this.GUARD_AFTER)*l,u=this.#y(c),f=new Float32Array(c);this.#a(u,f);let h=f.length*4;return{ptr:u,sizeBytes:h,numFrames:a,numChannels:l,sampleRate:o||this.#o.sampleRate}})}#g(e,t){return!e||e.length===0?Array.from({length:t},(r,i)=>i):(e.forEach(r=>{if(!Number.isInteger(r)||r<0||r>=t)throw new Error(`Channel ${r} is out of range (file has ${t} channels)`)}),e)}#y(e){let t=e*4,r=this.#t.malloc(t);if(r===0){let i=this.#t.stats(),o=((i.available||0)/(1024*1024)).toFixed(2),a=((i.total||0)/(1024*1024)).toFixed(2),l=(t/(1024*1024)).toFixed(2);throw new Error(`Buffer pool allocation failed: requested ${l}MB, available ${o}MB of ${a}MB total`)}return r}#a(e,t){new Float32Array(this.#d,e,t.length).set(t)}#h(e,t,r){return new Promise((i,o)=>{let a=setTimeout(()=>{this.#s.delete(e),o(new Error(`Buffer ${t} allocation timeout (${r}ms)`))},r);this.#s.set(e,{resolve:i,reject:o,timeout:a})})}#u(e,t){let r=crypto.randomUUID(),i=this.#h(r,e,t);return{uuid:r,allocationComplete:i}}async#m(e){let t=this.#l.get(e)||Promise.resolve(),r,i=new Promise(o=>{r=o});return this.#l.set(e,t.then(()=>i)),await t,()=>{r&&(r(),r=null),this.#l.get(e)===i&&this.#l.delete(e)}}#b(e,t,r,i,o){let a=this.#e.get(e),l={ptr:t,size:r,pendingToken:i,pendingPromise:o,previousAllocation:a?{ptr:a.ptr,size:a.size}:null};return this.#e.set(e,l),l}async#B(e){let t=this.#e.get(e);if(t&&t.pendingToken&&t.pendingPromise)try{await t.pendingPromise}catch{}}#_(e,t,r){return!r||typeof r.then!="function"?(this.#f(e,t,!0),Promise.resolve()):r.then(i=>(this.#f(e,t,!0),i)).catch(i=>{throw this.#f(e,t,!1),i})}#f(e,t,r){let i=this.#e.get(e);if(!i||i.pendingToken!==t)return;let o=i.previousAllocation;if(r){i.pendingToken=null,i.pendingPromise=null,i.previousAllocation=null,o?.ptr&&this.#t.free(o.ptr);return}i.ptr&&this.#t.free(i.ptr),i.pendingPromise=null,o?.ptr?this.#e.set(e,{ptr:o.ptr,size:o.size,pendingToken:null,previousAllocation:null}):this.#e.delete(e)}handleBufferFreed(e){let t=e[0],r=e[1],i=this.#e.get(t);if(!i){typeof r=="number"&&r!==0&&this.#t.free(r);return}if(typeof r=="number"&&r===i.ptr){this.#t.free(i.ptr),this.#e.delete(t);return}if(typeof r=="number"&&i.previousAllocation&&i.previousAllocation.ptr===r){this.#t.free(r),i.previousAllocation=null;return}this.#t.free(i.ptr),this.#e.delete(t)}handleBufferAllocated(e){let t=e[0],r=e[1],i=this.#s.get(t);i&&(clearTimeout(i.timeout),i.resolve({bufnum:r}),this.#s.delete(t))}allocate(e){let t=e*4,r=this.#t.malloc(t);if(r===0){let i=this.#t.stats(),o=((i.available||0)/(1024*1024)).toFixed(2),a=((i.total||0)/(1024*1024)).toFixed(2),l=(t/(1024*1024)).toFixed(2);console.error(`[BufferManager] Allocation failed: requested ${l}MB, available ${o}MB of ${a}MB total`)}return r}free(e){return this.#t.free(e)}getView(e,t){return new Float32Array(this.#d,e,t)}getStats(){return this.#t.stats()}getDiagnostics(){let e=this.#t.stats(),t=0,r=0;for(let i of this.#e.values())i&&(t+=i.size||0,i.pendingToken&&r++);return{active:this.#e.size,pending:r,bytesActive:t,pool:{total:this.#i,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.#s.entries())clearTimeout(t.timeout),t.reject(new Error("BufferManager destroyed"));this.#s.clear();for(let[e,t]of this.#e.entries())t.ptr&&this.#t.free(t.ptr);this.#e.clear(),this.#l.clear()}};var K={totalPages:1280,ringBufferReserved:1048576,bufferPoolOffset:17825792,bufferPoolSize:66060288,get totalMemory(){return this.bufferPoolOffset+this.bufferPoolSize},get wasmHeapSize(){return this.bufferPoolOffset-this.ringBufferReserved}};var J={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};function Ee(s,e,t=0){for(let r=0;r<=t;r++)if(Atomics.compareExchange(s,e,0,1)===0)return!0;return!1}function ge(s,e){Atomics.store(s,e,0)}function X({atomicView:s,dataView:e,uint8View:t,bufferConstants:r,ringBufferBase:i,controlIndices:o,oscMessage:a,maxSpins:l=0}){let c=a.length,u=r.MESSAGE_HEADER_SIZE+c;if(u>r.IN_BUFFER_SIZE-r.MESSAGE_HEADER_SIZE||!Ee(s,o.IN_WRITE_LOCK,l))return!1;try{let f=Atomics.load(s,o.IN_HEAD),h=Atomics.load(s,o.IN_TAIL);if((r.IN_BUFFER_SIZE-1-f+h)%r.IN_BUFFER_SIZE<u)return!1;let m=Atomics.add(s,o.IN_SEQUENCE,1),d=r.IN_BUFFER_SIZE-f;if(u>d){let p=new Uint8Array(r.MESSAGE_HEADER_SIZE),E=new DataView(p.buffer);E.setUint32(0,r.MESSAGE_MAGIC,!0),E.setUint32(4,u,!0),E.setUint32(8,m,!0),E.setUint32(12,0,!0);let y=i+r.IN_BUFFER_START+f,T=i+r.IN_BUFFER_START;if(d>=r.MESSAGE_HEADER_SIZE){t.set(p,y);let _=d-r.MESSAGE_HEADER_SIZE;t.set(a.subarray(0,_),y+r.MESSAGE_HEADER_SIZE),t.set(a.subarray(_),T)}else{t.set(p.subarray(0,d),y),t.set(p.subarray(d),T);let _=r.MESSAGE_HEADER_SIZE-d;t.set(a,T+_)}}else{let p=i+r.IN_BUFFER_START+f;e.setUint32(p,r.MESSAGE_MAGIC,!0),e.setUint32(p+4,u,!0),e.setUint32(p+8,m,!0),e.setUint32(p+12,0,!0),t.set(a,p+r.MESSAGE_HEADER_SIZE)}Atomics.load(s,o.IN_HEAD);let w=(f+u)%r.IN_BUFFER_SIZE;return Atomics.store(s,o.IN_HEAD,w),!0}finally{ge(s,o.IN_WRITE_LOCK)}}var se=class s{static osc={encode:e=>B.writePacket(e),decode:(e,t={metadata:!1})=>B.readPacket(e,t)};#r;#n;#o;#d;#t;#i;#e;#s;#l;#c;#w;#p;#g;#y;#a;#h;#u;#m;#b;#B;#_;#f;#R=null;#I=!1;#F=100;constructor(e={}){if(this.#a=!1,this.#h=!1,this.#u={},this.#t=null,this.#i=null,this.#e=null,this.#r=null,this.#n=null,this.#o=null,this.#s=null,this.loadedSynthDefs=new Set,this.onOSC=null,this.onMessage=null,this.onMessageSent=null,this.onDebugMessage=null,this.onInitialized=null,this.onError=null,this.onMetricsUpdate=null,!e.workerBaseURL||!e.wasmBaseURL)throw new Error(`SuperSonic requires workerBaseURL and wasmBaseURL options. Example:
5
5
  new SuperSonic({
6
6
  workerBaseURL: "/supersonic/workers/",
7
7
  wasmBaseURL: "/supersonic/wasm/"
8
- })`);let t=e.workerBaseURL,r=e.wasmBaseURL,i={...J,...e.scsynthOptions};this.config={wasmUrl:e.wasmUrl||r+"scsynth-nrt.wasm",wasmBaseURL:r,workletUrl:e.workletUrl||t+"scsynth_audio_worklet.js",workerBaseURL:t,development:!1,audioContextOptions:{latencyHint:"interactive",sampleRate:48e3},memory:K,worldOptions:i},this.#g=e.sampleBaseURL||null,this.#E=e.synthdefBaseURL||null,this.#y=e.audioPathMap||{},this.bootStats={initStartTime:null,initDuration:null}}get initialized(){return this.#a}get initializing(){return this.#d}get capabilities(){return this.#u}setAndValidateCapabilities(){this.#u={audioWorklet:typeof AudioWorklet<"u",sharedArrayBuffer:typeof SharedArrayBuffer<"u",crossOriginIsolated:window.crossOriginIsolated===!0,atomics:typeof Atomics<"u",webWorker:typeof Worker<"u"};let t=["audioWorklet","sharedArrayBuffer","crossOriginIsolated","atomics","webWorker"].filter(r=>!this.#u[r]);if(t.length>0){let r=new Error(`Missing required features: ${t.join(", ")}`);throw this.#u.crossOriginIsolated||(this.#u.sharedArrayBuffer?r.message+=`
8
+ })`);let t=e.workerBaseURL,r=e.wasmBaseURL,i={...J,...e.scsynthOptions};this.config={wasmUrl:e.wasmUrl||r+"scsynth-nrt.wasm",wasmBaseURL:r,workletUrl:e.workletUrl||t+"scsynth_audio_worklet.js",workerBaseURL:t,development:!1,audioContextOptions:{latencyHint:"interactive",sampleRate:48e3},memory:K,worldOptions:i},this.#p=e.sampleBaseURL||null,this.#g=e.synthdefBaseURL||null,this.#y=e.audioPathMap||{},this.bootStats={initStartTime:null,initDuration:null}}get initialized(){return this.#a}get initializing(){return this.#h}get capabilities(){return this.#u}setAndValidateCapabilities(){this.#u={audioWorklet:typeof AudioWorklet<"u",sharedArrayBuffer:typeof SharedArrayBuffer<"u",crossOriginIsolated:window.crossOriginIsolated===!0,atomics:typeof Atomics<"u",webWorker:typeof Worker<"u"};let t=["audioWorklet","sharedArrayBuffer","crossOriginIsolated","atomics","webWorker"].filter(r=>!this.#u[r]);if(t.length>0){let r=new Error(`Missing required features: ${t.join(", ")}`);throw this.#u.crossOriginIsolated||(this.#u.sharedArrayBuffer?r.message+=`
9
9
 
10
10
  SharedArrayBuffer is available but cross-origin isolation is not enabled. Please ensure COOP and COEP headers are set correctly:
11
11
  Cross-Origin-Opener-Policy: same-origin
@@ -14,8 +14,5 @@ SharedArrayBuffer is available but cross-origin isolation is not enabled. Please
14
14
  SharedArrayBuffer is not available. This may be due to:
15
15
  1. Missing COOP/COEP headers
16
16
  2. Browser doesn't support SharedArrayBuffer
17
- 3. Browser security settings`),r}return this.#u}#x(){let e=this.config.memory;this.#p=new WebAssembly.Memory({initial:e.totalPages,maximum:e.totalPages,shared:!0}),this.#t=this.#p.buffer}#N(){return this.#i=new AudioContext(this.config.audioContextOptions),this.#i}#L(){this.#s=new P({audioContext:this.#i,sharedBuffer:this.#t,bufferPoolConfig:{start:this.config.memory.bufferPoolOffset,size:this.config.memory.bufferPoolSize},sampleBaseURL:this.#g,audioPathMap:this.#y,maxBuffers:this.config.worldOptions.numBuffers})}async#z(){let e=this.config.wasmBaseURL+"manifest.json";try{let t=await fetch(e);if(!t.ok)return;let r=await t.json();this.config.wasmUrl=this.config.wasmBaseURL+r.wasmFile}catch{}}async#W(){this.config.development&&await this.#z();let e=await fetch(this.config.wasmUrl);if(!e.ok)throw new Error(`Failed to load WASM: ${e.status} ${e.statusText}`);return await e.arrayBuffer()}async#V(e){await this.#i.audioWorklet.addModule(this.config.workletUrl),this.#n=new AudioWorkletNode(this.#i,"scsynth-processor",{numberOfInputs:0,numberOfOutputs:1,outputChannelCount:[2]}),this.#n.connect(this.#i.destination),this.#n.port.postMessage({type:"init",sharedBuffer:this.#t}),this.#n.port.postMessage({type:"loadWasm",wasmBytes:e,wasmMemory:this.#p,worldOptions:this.config.worldOptions,sampleRate:this.#i.sampleRate}),await this.#H()}async#$(){this.#o=new R(this.config.workerBaseURL),this.#o.onRawOSC(e=>{this.onOSC&&this.onOSC(e)}),this.#o.onParsedOSC(e=>{if(e.address==="/buffer/freed")this.#s?.handleBufferFreed(e.args);else if(e.address==="/buffer/allocated")this.#s?.handleBufferAllocated(e.args);else if(e.address==="/synced"&&e.args.length>0){let t=e.args[0];this.#l&&this.#l.has(t)&&this.#l.get(t)(e)}this.onMessage&&this.onMessage(e)}),this.#o.onDebugMessage(e=>{this.onDebugMessage&&this.onDebugMessage(e)}),this.#o.onError((e,t)=>{console.error(`[SuperSonic] ${t} error:`,e),this.onError&&this.onError(new Error(`${t}: ${e}`))}),await this.#o.init(this.#t,this.#r,this.#e)}#G(){this.#a=!0,this.#d=!1,this.bootStats.initDuration=performance.now()-this.bootStats.initStartTime,this.onInitialized&&this.onInitialized({capabilities:this.#u,bootStats:this.bootStats})}async init(e={}){if(this.#a){console.warn("[SuperSonic] Already initialized");return}if(this.#d){console.warn("[SuperSonic] Initialization already in progress");return}this.config={...this.config,...e,audioContextOptions:{...this.config.audioContextOptions,...e.audioContextOptions||{}}},this.#d=!0,this.bootStats.initStartTime=performance.now();try{this.setAndValidateCapabilities(),this.#x(),this.#N(),this.#L();let t=await this.#W();await this.#V(t),await this.#$(),this.#Z(),this.#K(),this.#G()}catch(t){throw this.#d=!1,console.error("[SuperSonic] Initialization failed:",t),this.onError&&this.onError(t),t}}#H(){return new Promise((e,t)=>{let r=setTimeout(()=>{t(new Error("AudioWorklet initialization timeout"))},5e3),i=async o=>{if(o.data.type!=="debug"){if(o.data.type==="error"){console.error("[AudioWorklet] Error:",o.data.error),clearTimeout(r),this.#n.port.removeEventListener("message",i),t(new Error(o.data.error||"AudioWorklet error"));return}o.data.type==="initialized"&&(clearTimeout(r),this.#n.port.removeEventListener("message",i),o.data.success?(o.data.ringBufferBase!==void 0?this.#r=o.data.ringBufferBase:console.warn("[SuperSonic] Warning: ringBufferBase not provided by worklet"),o.data.bufferConstants!==void 0?(this.#e=o.data.bufferConstants,this.#X(),await this.initializeNTPTiming(),this.#re()):console.warn("[SuperSonic] Warning: bufferConstants not provided by worklet"),e()):t(new Error(o.data.error||"AudioWorklet initialization failed")))}};this.#n.port.addEventListener("message",i),this.#n.port.start()})}#Z(){this.#n.port.onmessage=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.onError&&this.onError(new Error(t.error));break;case"process_debug":break;case"debug":break;case"console":this.onConsoleMessage&&this.onConsoleMessage(t.message);break;case"version":this.onVersion&&this.onVersion(t.version);break}}}#q(){if(!this.#t||!this.#e||!this.#r)return null;let e=this.#r+this.#e.METRICS_START,t=this.#e.METRICS_SIZE/4,r=new Uint32Array(this.#t,e,t);return{processCount:Atomics.load(r,0),messagesProcessed:Atomics.load(r,1),messagesDropped:Atomics.load(r,2),schedulerQueueDepth:Atomics.load(r,3),schedulerQueueMax:Atomics.load(r,4),schedulerQueueDropped:Atomics.load(r,5)}}#Y(){if(!this.#t||!this.#e||!this.#r)return null;let e=new Int32Array(this.#t),t=this.#r+this.#e.CONTROL_START,r=Atomics.load(e,(t+0)/4),i=Atomics.load(e,(t+4)/4),o=Atomics.load(e,(t+8)/4),a=Atomics.load(e,(t+12)/4),c=Atomics.load(e,(t+16)/4),l=Atomics.load(e,(t+20)/4),u=(r-i+this.#e.IN_BUFFER_SIZE)%this.#e.IN_BUFFER_SIZE,f=(o-a+this.#e.OUT_BUFFER_SIZE)%this.#e.OUT_BUFFER_SIZE,h=(c-l+this.#e.DEBUG_BUFFER_SIZE)%this.#e.DEBUG_BUFFER_SIZE;return{inBufferUsed:{bytes:u,percentage:u/this.#e.IN_BUFFER_SIZE*100},outBufferUsed:{bytes:f,percentage:f/this.#e.OUT_BUFFER_SIZE*100},debugBufferUsed:{bytes:h,percentage:h/this.#e.DEBUG_BUFFER_SIZE*100}}}#Q(){if(!this.#t||!this.#e||!this.#r)return null;let e=this.#r+this.#e.METRICS_START,t=this.#e.METRICS_SIZE/4,r=new Uint32Array(this.#t,e,t);return{preschedulerPending:r[6],preschedulerPeak:r[7],preschedulerSent:r[8],retriesSucceeded:r[9],retriesFailed:r[10],bundlesScheduled:r[11],eventsCancelled:r[12],totalDispatches:r[13],messagesRetried:r[14],retryQueueSize:r[15],retryQueueMax:r[16],oscInMessagesReceived:r[17],oscInDroppedMessages:r[18],oscInBytesReceived:r[19],debugMessagesReceived:r[20],debugBytesReceived:r[21],messagesSent:r[22],bytesSent:r[23],directWrites:r[25],sequenceGaps:r[24]}}#v(e,t=1){if(!this.#t||!this.#e||!this.#r)return;let r=this.#r+this.#e.METRICS_START,i=new Uint32Array(this.#t,r,this.#e.METRICS_SIZE/4),o={messagesSent:22,bytesSent:23,directWrites:25};Atomics.add(i,o[e],t)}#j(){let e=performance.now(),t={},r=this.#q();r&&Object.assign(t,r);let i=this.#Y();i&&Object.assign(t,i);let o=this.#Q();o&&Object.assign(t,o),t.driftOffsetMs=this.getDriftOffset();let a=performance.now()-e;return a>1&&console.warn(`[SuperSonic] Slow metrics gathering: ${a.toFixed(2)}ms`),t}#K(){this.#f&&clearInterval(this.#f),this.#f=setInterval(()=>{if(this.onMetricsUpdate){if(this.#M){console.warn("[SuperSonic] Metrics gathering took >100ms, skipping this interval");return}this.#M=!0;try{let e=this.#j();this.onMetricsUpdate(e)}catch(e){console.error("[SuperSonic] Metrics gathering failed:",e)}finally{this.#M=!1}}},100)}#J(){this.#f&&(clearInterval(this.#f),this.#f=null)}async send(e,...t){this.#h("send OSC messages");let r=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}`)}),i={address:e,args:r},o=s.osc.encode(i);return this.sendOSC(o)}#h(e="perform this operation"){if(!this.#a)throw new Error(`SuperSonic not initialized. Call init() before attempting to ${e}.`)}#X(){if(!this.#t||!this.#r||!this.#e){console.warn("[SuperSonic] Cannot initialize direct write views - missing buffer info");return}this.#_=new Int32Array(this.#t),this.#b=new DataView(this.#t),this.#B=new Uint8Array(this.#t);let e=this.#e.CONTROL_START;this.#A={IN_HEAD:(this.#r+e+0)/4,IN_TAIL:(this.#r+e+4)/4,IN_SEQUENCE:(this.#r+e+24)/4,IN_WRITE_LOCK:(this.#r+e+40)/4}}#ee(e){return e.length>=8&&e[0]===35}#te(e){return!this.#_||!this.#A?!1:X({atomicView:this.#_,dataView:this.#b,uint8View:this.#B,bufferConstants:this.#e,ringBufferBase:this.#r,controlIndices:this.#A,oscMessage:e})}async sendOSC(e,t={}){this.#h("send OSC data");let r=this.#se(e),i=await this.#ne(r);if(this.#v("messagesSent"),this.#v("bytesSent",i.length),this.onMessageSent&&this.onMessageSent(i),!this.#ee(i)&&this.#te(i)){this.#v("directWrites");return}let o=this.#de(i),a={...t};o&&(a.audioTimeS=o.audioTimeS,a.currentTimeS=o.currentTimeS),this.#o.send(i,a)}get audioContext(){return this.#i}get workletNode(){return this.#n}get osc(){return this.#o}getStatus(){return{initialized:this.#a,capabilities:this.#u,bootStats:this.bootStats,audioContextState:this.#i?.state}}getConfig(){return this.config?{memory:{...this.config.memory},worldOptions:{...this.config.worldOptions}}:null}async destroy(){this.#D(),this.#J(),this.#o&&(this.#o.terminate(),this.#o=null),this.#n&&(this.#n.disconnect(),this.#n=null),this.#i&&(await this.#i.close(),this.#i=null),this.#s&&(this.#s.destroy(),this.#s=null),this.#t=null,this.#a=!1,this.loadedSynthDefs.clear()}waitForTimeSync(){return this.#h("wait for time sync"),new Float64Array(this.#t,this.#r+this.#e.NTP_START_TIME_START,1)[0]}async loadSample(e,t,r=0,i=0){this.#h("load samples");let o=await this.#O().prepareFromFile({bufnum:e,path:t,startFrame:r,numFrames:i});return await this.send("/b_allocPtr",e,o.ptr,o.numFrames,o.numChannels,o.sampleRate,o.uuid),o.allocationComplete}async loadSynthDef(e){if(!this.#a)throw new Error("SuperSonic not initialized. Call init() first.");try{let t=await fetch(e);if(!t.ok)throw new Error(`Failed to load synthdef from ${e}: ${t.status} ${t.statusText}`);let r=await t.arrayBuffer(),i=new Uint8Array(r);await this.send("/d_recv",i);let o=this.#ie(e);o&&this.loadedSynthDefs.add(o)}catch(t){throw console.error("[SuperSonic] Failed to load synthdef:",t),t}}async loadSynthDefs(e){if(!this.#a)throw new Error("SuperSonic not initialized. Call init() first.");if(!this.#E)throw new Error(`synthdefBaseURL not configured. Please set it in SuperSonic constructor options.
18
- Example: new SuperSonic({ synthdefBaseURL: "./dist/synthdefs/" })
19
- Or use CDN: new SuperSonic({ synthdefBaseURL: "https://unpkg.com/supersonic-scsynth-synthdefs@latest/synthdefs/" })
20
- Or install: npm install supersonic-scsynth-synthdefs`);let t={};await Promise.all(e.map(async i=>{try{let o=`${this.#E}${i}.scsyndef`;await this.loadSynthDef(o),t[i]={success:!0}}catch(o){console.error(`[SuperSonic] Failed to load ${i}:`,o),t[i]={success:!1,error:o.message}}}));let r=Object.values(t).filter(i=>i.success).length;return t}async sync(e){if(!this.#a)throw new Error("SuperSonic not initialized. Call init() first.");if(!Number.isInteger(e))throw new Error("sync() requires an integer syncId parameter");let t=new Promise((r,i)=>{let o=setTimeout(()=>{this.#l&&this.#l.delete(e),i(new Error("Timeout waiting for /synced response"))},1e4),a=c=>{clearTimeout(o),this.#l.delete(e),r()};this.#l||(this.#l=new Map),this.#l.set(e,a)});await this.send("/sync",e),await t}allocBuffer(e){return this.#h("allocate buffers"),this.#s.allocate(e)}freeBuffer(e){return this.#h("free buffers"),this.#s.free(e)}getBufferView(e,t){return this.#h("get buffer views"),this.#s.getView(e,t)}getBufferPoolStats(){return this.#h("get buffer pool stats"),this.#s.getStats()}getDiagnostics(){return this.#h("get diagnostics"),{buffers:this.#s.getDiagnostics(),synthdefs:{count:this.loadedSynthDefs.size}}}async initializeNTPTiming(){if(!this.#e||!this.#i)return;let e;for(;e=this.#i.getOutputTimestamp(),!(e.contextTime>0);)await new Promise(a=>setTimeout(a,50));let i=(performance.timeOrigin+e.performanceTime)/1e3+2208988800-e.contextTime,o=new Float64Array(this.#t,this.#r+this.#e.NTP_START_TIME_START,1);o[0]=i,this.#S=i}updateDriftOffset(){if(!this.#e||!this.#i||this.#S===void 0)return;let e=this.#i.getOutputTimestamp(),o=(performance.timeOrigin+e.performanceTime)/1e3+2208988800-this.#S-e.contextTime,a=Math.round(o*1e3),c=new Int32Array(this.#t,this.#r+this.#e.DRIFT_OFFSET_START,1);Atomics.store(c,0,a)}getDriftOffset(){if(!this.#e)return 0;let e=new Int32Array(this.#t,this.#r+this.#e.DRIFT_OFFSET_START,1);return Atomics.load(e,0)}#re(){this.#D(),this.#c=setInterval(()=>{this.updateDriftOffset()},15e3)}#D(){this.#c&&(clearInterval(this.#c),this.#c=null)}#ie(e){return!e||typeof e!="string"?null:(e.split("/").filter(Boolean).pop()||e).replace(/\.scsyndef$/i,"")}#se(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#ne(e){let t={metadata:!0,unpackSingleArgs:!1};try{let r=s.osc.decode(e,t),{packet:i,changed:o}=await this.#U(r);return o?s.osc.encode(i):e}catch(r){throw console.error("[SuperSonic] Failed to prepare OSC packet:",r),r}}async#U(e){if(e&&e.address){let{message:t,changed:r}=await this.#oe(e);return{packet:t,changed:r}}if(this.#he(e)){let t=await Promise.all(e.packets.map(o=>this.#U(o)));if(!t.some(o=>o.changed))return{packet:e,changed:!1};let i=t.map(o=>o.packet);return{packet:{timeTag:e.timeTag,packets:i},changed:!0}}return{packet:e,changed:!1}}async#oe(e){switch(e.address){case"/b_alloc":return{message:await this.#le(e),changed:!0};case"/b_allocRead":return{message:await this.#ae(e),changed:!0};case"/b_allocReadChannel":return{message:await this.#ce(e),changed:!0};default:return{message:e,changed:!1}}}async#ae(e){let t=this.#O(),r=this.#I(e.args,0,"/b_allocRead requires a buffer number"),i=this.#F(e.args,1,"/b_allocRead requires a file path"),o=this.#T(e.args,2,0),a=this.#T(e.args,3,0),c=await t.prepareFromFile({bufnum:r,path:i,startFrame:o,numFrames:a});return this.#P(c.allocationComplete,`/b_allocRead ${r}`),this.#k(r,c)}async#ce(e){let t=this.#O(),r=this.#I(e.args,0,"/b_allocReadChannel requires a buffer number"),i=this.#F(e.args,1,"/b_allocReadChannel requires a file path"),o=this.#T(e.args,2,0),a=this.#T(e.args,3,0),c=[];for(let u=4;u<(e.args?.length||0)&&this.#C(e.args[u]);u++)c.push(Math.floor(this.#w(e.args[u])));let l=await t.prepareFromFile({bufnum:r,path:i,startFrame:o,numFrames:a,channels:c.length>0?c:null});return this.#P(l.allocationComplete,`/b_allocReadChannel ${r}`),this.#k(r,l)}async#le(e){let t=this.#O(),r=this.#I(e.args,0,"/b_alloc requires a buffer number"),i=this.#I(e.args,1,"/b_alloc requires a frame count"),o=2,a=1,c=this.#i?.sampleRate||44100;this.#C(this.#m(e.args,o))&&(a=Math.max(1,this.#T(e.args,o,1)),o++),this.#m(e.args,o)?.type==="b"&&o++,this.#C(this.#m(e.args,o))&&(c=this.#w(this.#m(e.args,o)));let l=await t.prepareEmpty({bufnum:r,numFrames:i,numChannels:a,sampleRate:c});return this.#P(l.allocationComplete,`/b_alloc ${r}`),this.#k(r,l)}#k(e,t){return{address:"/b_allocPtr",args:[this.#R(e),this.#R(t.ptr),this.#R(t.numFrames),this.#R(t.numChannels),this.#ue(t.sampleRate),this.#fe(t.uuid)]}}#R(e){return{type:"i",value:Math.floor(e)}}#ue(e){return{type:"f",value:e}}#fe(e){return{type:"s",value:String(e)}}#m(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}#I(e,t,r){let i=this.#w(this.#m(e,t));if(!Number.isFinite(i))throw new Error(r);return Math.floor(i)}#T(e,t,r=0){let i=this.#w(this.#m(e,t));return Number.isFinite(i)?Math.floor(i):r}#F(e,t,r){let i=this.#w(this.#m(e,t));if(typeof i!="string")throw new Error(r);return i}#C(e){if(!e)return!1;let t=this.#w(e);return Number.isFinite(t)}#P(e,t){!e||typeof e.catch!="function"||e.catch(r=>{console.error(`[SuperSonic] ${t} allocation failed:`,r)})}#O(){if(!this.#s)throw new Error("Buffer manager not ready. Call init() before issuing buffer commands.");return this.#s}#he(e){return e&&e.timeTag!==void 0&&Array.isArray(e.packets)}#de(e){if(e.length<16||String.fromCharCode.apply(null,e.slice(0,8))!=="#bundle\0")return null;let i=new Float64Array(this.#t,this.#r+this.#e.NTP_START_TIME_START,1)[0];if(i===0)return console.warn("[SuperSonic] NTP start time not yet initialized"),null;let o=new Int32Array(this.#t,this.#r+this.#e.DRIFT_OFFSET_START,1),c=Atomics.load(o,0)/1e3,l=new Int32Array(this.#t,this.#r+this.#e.GLOBAL_OFFSET_START,1),f=Atomics.load(l,0)/1e3,h=i+c+f,S=new DataView(e.buffer,e.byteOffset),m=S.getUint32(8,!1),d=S.getUint32(12,!1);if(m===0&&(d===0||d===1))return null;let p=m+d/4294967296-h,g=this.#i.currentTime;return{audioTimeS:p,currentTimeS:g}}};export{se as SuperSonic};
17
+ 3. Browser security settings`),r}return this.#u}#V(){let e=this.config.memory;this.#d=new WebAssembly.Memory({initial:e.totalPages,maximum:e.totalPages,shared:!0}),this.#t=this.#d.buffer}#H(){return this.#r=new AudioContext(this.config.audioContextOptions),this.#r}#G(){this.#s=new C({audioContext:this.#r,sharedBuffer:this.#t,bufferPoolConfig:{start:this.config.memory.bufferPoolOffset,size:this.config.memory.bufferPoolSize},sampleBaseURL:this.#p,audioPathMap:this.#y,maxBuffers:this.config.worldOptions.numBuffers})}async#Z(){let e=this.config.wasmBaseURL+"manifest.json";try{let t=await fetch(e);if(!t.ok)return;let r=await t.json();this.config.wasmUrl=this.config.wasmBaseURL+r.wasmFile}catch{}}async#q(){this.config.development&&await this.#Z();let e=await fetch(this.config.wasmUrl);if(!e.ok)throw new Error(`Failed to load WASM: ${e.status} ${e.statusText}`);return await e.arrayBuffer()}async#Y(e){await this.#r.audioWorklet.addModule(this.config.workletUrl),this.#n=new AudioWorkletNode(this.#r,"scsynth-processor",{numberOfInputs:0,numberOfOutputs:1,outputChannelCount:[2]}),this.#n.connect(this.#r.destination),this.#n.port.postMessage({type:"init",sharedBuffer:this.#t}),this.#n.port.postMessage({type:"loadWasm",wasmBytes:e,wasmMemory:this.#d,worldOptions:this.config.worldOptions,sampleRate:this.#r.sampleRate}),await this.#K()}async#Q(){this.#o=new R(this.config.workerBaseURL),this.#o.onRawOSC(e=>{this.onOSC&&this.onOSC(e)}),this.#o.onParsedOSC(e=>{if(e.address==="/buffer/freed")this.#s?.handleBufferFreed(e.args);else if(e.address==="/buffer/allocated")this.#s?.handleBufferAllocated(e.args);else if(e.address==="/synced"&&e.args.length>0){let t=e.args[0];this.#c&&this.#c.has(t)&&this.#c.get(t)(e)}this.onMessage&&this.onMessage(e)}),this.#o.onDebugMessage(e=>{this.onDebugMessage&&this.onDebugMessage(e)}),this.#o.onError((e,t)=>{console.error(`[SuperSonic] ${t} error:`,e),this.onError&&this.onError(new Error(`${t}: ${e}`))}),await this.#o.init(this.#t,this.#i,this.#e)}#j(){this.#a=!0,this.#h=!1,this.bootStats.initDuration=performance.now()-this.bootStats.initStartTime,this.onInitialized&&this.onInitialized({capabilities:this.#u,bootStats:this.bootStats})}async init(e={}){if(this.#a){console.warn("[SuperSonic] Already initialized");return}if(this.#h){console.warn("[SuperSonic] Initialization already in progress");return}this.config={...this.config,...e,audioContextOptions:{...this.config.audioContextOptions,...e.audioContextOptions||{}}},this.#h=!0,this.bootStats.initStartTime=performance.now();try{this.setAndValidateCapabilities(),this.#V(),this.#H(),this.#G();let t=await this.#q();await this.#Y(t),await this.#Q(),this.#J(),this.#N(),this.#j()}catch(t){throw this.#h=!1,console.error("[SuperSonic] Initialization failed:",t),this.onError&&this.onError(t),t}}#K(){return new Promise((e,t)=>{let r=setTimeout(()=>{t(new Error("AudioWorklet initialization timeout"))},5e3),i=async o=>{if(o.data.type!=="debug"){if(o.data.type==="error"){console.error("[AudioWorklet] Error:",o.data.error),clearTimeout(r),this.#n.port.removeEventListener("message",i),t(new Error(o.data.error||"AudioWorklet error"));return}o.data.type==="initialized"&&(clearTimeout(r),this.#n.port.removeEventListener("message",i),o.data.success?(o.data.ringBufferBase!==void 0?this.#i=o.data.ringBufferBase:console.warn("[SuperSonic] Warning: ringBufferBase not provided by worklet"),o.data.bufferConstants!==void 0?(this.#e=o.data.bufferConstants,this.#te(),await this.initializeNTPTiming(),this.#se()):console.warn("[SuperSonic] Warning: bufferConstants not provided by worklet"),e()):t(new Error(o.data.error||"AudioWorklet initialization failed")))}};this.#n.port.addEventListener("message",i),this.#n.port.start()})}#J(){this.#n.port.onmessage=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.onError&&this.onError(new Error(t.error));break;case"process_debug":break;case"debug":break;case"console":this.onConsoleMessage&&this.onConsoleMessage(t.message);break;case"version":this.onVersion&&this.onVersion(t.version);break}}}#X(){if(!this.#f)return null;let e=this.#f;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]}}#ee(){if(!this.#m||!this.#e||!this.#i)return null;let e=this.#i+this.#e.CONTROL_START,t=this.#m,r=Atomics.load(t,(e+0)/4),i=Atomics.load(t,(e+4)/4),o=Atomics.load(t,(e+8)/4),a=Atomics.load(t,(e+12)/4),l=Atomics.load(t,(e+16)/4),c=Atomics.load(t,(e+20)/4),u=(r-i+this.#e.IN_BUFFER_SIZE)%this.#e.IN_BUFFER_SIZE,f=(o-a+this.#e.OUT_BUFFER_SIZE)%this.#e.OUT_BUFFER_SIZE,h=(l-c+this.#e.DEBUG_BUFFER_SIZE)%this.#e.DEBUG_BUFFER_SIZE;return{inBufferUsed:{bytes:u,percentage:u/this.#e.IN_BUFFER_SIZE*100},outBufferUsed:{bytes:f,percentage:f/this.#e.OUT_BUFFER_SIZE*100},debugBufferUsed:{bytes:h,percentage:h/this.#e.DEBUG_BUFFER_SIZE*100}}}#k(e,t=1){if(!this.#f)return;let r={mainMessagesSent:22,mainBytesSent:23,preschedulerBypassed:25};Atomics.add(this.#f,r[e],t)}#x(){let e=performance.now(),t=this.#X()||{},r=this.#ee();if(r&&Object.assign(t,r),t.driftOffsetMs=this.getDriftOffset(),t.audioContextState=this.#r?.state||"unknown",this.#s){let o=this.#s.getStats();t.bufferPoolUsedBytes=o.used,t.bufferPoolAvailableBytes=o.available,t.bufferPoolAllocations=o.allocations}t.loadedSynthDefs=this.loadedSynthDefs?.size||0;let i=performance.now()-e;return i>1&&console.warn(`[SuperSonic] Slow metrics gathering: ${i.toFixed(2)}ms`),t}#N(){this.#P();let e=this.#F;this.#R=setInterval(()=>{if(this.onMetricsUpdate){if(this.#I){console.warn(`[SuperSonic] Metrics gathering took >${e}ms, skipping this interval`);return}this.#I=!0;try{let t=this.#x();this.onMetricsUpdate(t)}catch(t){console.error("[SuperSonic] Metrics gathering failed:",t)}finally{this.#I=!1}}},e)}#P(){this.#R&&(clearInterval(this.#R),this.#R=null)}getMetrics(){return this.#x()}setMetricsInterval(e){this.#F=e,this.#N()}stopMetricsPolling(){this.#P()}async send(e,...t){this.#A("send OSC messages");let r=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}`)}),i={address:e,args:r},o=s.osc.encode(i);return this.sendOSC(o)}#A(e="perform this operation"){if(!this.#a)throw new Error(`SuperSonic not initialized. Call init() before attempting to ${e}.`)}#te(){if(!this.#t||!this.#i||!this.#e){console.warn("[SuperSonic] Cannot initialize direct write views - missing buffer info");return}this.#m=new Int32Array(this.#t),this.#b=new DataView(this.#t),this.#B=new Uint8Array(this.#t);let e=this.#i+this.#e.METRICS_START;this.#f=new Uint32Array(this.#t,e,this.#e.METRICS_SIZE/4);let t=this.#e.CONTROL_START;this.#_={IN_HEAD:(this.#i+t+0)/4,IN_TAIL:(this.#i+t+4)/4,IN_SEQUENCE:(this.#i+t+24)/4,IN_WRITE_LOCK:(this.#i+t+40)/4}}#re(e){return e.length>=8&&e[0]===35}#ie(e){return!this.#m||!this.#_?!1:X({atomicView:this.#m,dataView:this.#b,uint8View:this.#B,bufferConstants:this.#e,ringBufferBase:this.#i,controlIndices:this.#_,oscMessage:e})}async sendOSC(e,t={}){this.#A("send OSC data");let r=this.#oe(e),i=await this.#ae(r);if(this.#k("mainMessagesSent"),this.#k("mainBytesSent",i.length),this.onMessageSent&&this.onMessageSent(i),!this.#re(i)&&this.#ie(i)){this.#k("preschedulerBypassed");return}let o=this.#me(i),a={...t};o&&(a.audioTimeS=o.audioTimeS,a.currentTimeS=o.currentTimeS),this.#o.send(i,a)}get audioContext(){return this.#r}get workletNode(){return this.#n}get osc(){return this.#o}getInfo(){return this.#A("get info"),{sampleRate:this.#r.sampleRate,numBuffers:this.config.worldOptions.numBuffers,totalMemory:this.config.memory.totalMemory,wasmHeapSize:this.config.memory.wasmHeapSize,bufferPoolSize:this.config.memory.bufferPoolSize,bootTimeMs:this.bootStats.initDuration,capabilities:{...this.#u}}}async destroy(){this.#z(),this.#P(),this.#o&&(this.#o.terminate(),this.#o=null),this.#n&&(this.#n.disconnect(),this.#n=null),this.#r&&(await this.#r.close(),this.#r=null),this.#s&&(this.#s.destroy(),this.#s=null),this.#t=null,this.#a=!1,this.loadedSynthDefs.clear()}waitForTimeSync(){return this.#A("wait for time sync"),new Float64Array(this.#t,this.#i+this.#e.NTP_START_TIME_START,1)[0]}async loadSample(e,t,r=0,i=0){this.#A("load samples");let o;if(this.#L(t))o=t;else{if(!this.#p)throw new Error("sampleBaseURL not configured. Either provide a full path or set sampleBaseURL in constructor options.");o=`${this.#p}${t}`}let a=await this.#O().prepareFromFile({bufnum:e,path:o,startFrame:r,numFrames:i});return await this.send("/b_allocPtr",e,a.ptr,a.numFrames,a.numChannels,a.sampleRate,a.uuid),a.allocationComplete}#L(e){return e.includes("/")||e.includes("://")}async loadSynthDef(e){if(!this.#a)throw new Error("SuperSonic not initialized. Call init() first.");let t;if(this.#L(e))t=e;else{if(!this.#g)throw new Error("synthdefBaseURL not configured. Either provide a full path or set synthdefBaseURL in constructor options.");t=`${this.#g}${e}.scsyndef`}try{let r=await fetch(t);if(!r.ok)throw new Error(`Failed to load synthdef from ${t}: ${r.status} ${r.statusText}`);let i=await r.arrayBuffer(),o=new Uint8Array(i);await this.send("/d_recv",o);let a=this.#ne(t);a&&this.loadedSynthDefs.add(a)}catch(r){throw console.error("[SuperSonic] Failed to load synthdef:",r),r}}async loadSynthDefs(e){if(!this.#a)throw new Error("SuperSonic not initialized. Call init() first.");let t={};await Promise.all(e.map(async i=>{try{await this.loadSynthDef(i),t[i]={success:!0}}catch(o){console.error(`[SuperSonic] Failed to load ${i}:`,o),t[i]={success:!1,error:o.message}}}));let r=Object.values(t).filter(i=>i.success).length;return t}async sync(e=Math.floor(Math.random()*2147483647)){if(!this.#a)throw new Error("SuperSonic not initialized. Call init() first.");let t=new Promise((r,i)=>{let o=setTimeout(()=>{this.#c&&this.#c.delete(e),i(new Error("Timeout waiting for /synced response"))},1e4),a=l=>{clearTimeout(o),this.#c.delete(e),r()};this.#c||(this.#c=new Map),this.#c.set(e,a)});await this.send("/sync",e),await t}#Se(){return this.#s?.getStats()}async initializeNTPTiming(){if(!this.#e||!this.#r)return;let e;for(;e=this.#r.getOutputTimestamp(),!(e.contextTime>0);)await new Promise(a=>setTimeout(a,50));let i=(performance.timeOrigin+e.performanceTime)/1e3+2208988800-e.contextTime,o=new Float64Array(this.#t,this.#i+this.#e.NTP_START_TIME_START,1);o[0]=i,this.#w=i}updateDriftOffset(){if(!this.#e||!this.#r||this.#w===void 0)return;let e=this.#r.getOutputTimestamp(),o=(performance.timeOrigin+e.performanceTime)/1e3+2208988800-this.#w-e.contextTime,a=Math.round(o*1e3),l=new Int32Array(this.#t,this.#i+this.#e.DRIFT_OFFSET_START,1);Atomics.store(l,0,a)}getDriftOffset(){if(!this.#e)return 0;let e=new Int32Array(this.#t,this.#i+this.#e.DRIFT_OFFSET_START,1);return Atomics.load(e,0)}#se(){this.#z(),this.#l=setInterval(()=>{this.updateDriftOffset()},15e3)}#z(){this.#l&&(clearInterval(this.#l),this.#l=null)}#ne(e){return!e||typeof e!="string"?null:(e.split("/").filter(Boolean).pop()||e).replace(/\.scsyndef$/i,"")}#oe(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 r=s.osc.decode(e,t),{packet:i,changed:o}=await this.#$(r);return o?s.osc.encode(i):e}catch(r){throw console.error("[SuperSonic] Failed to prepare OSC packet:",r),r}}async#$(e){if(e&&e.address){let{message:t,changed:r}=await this.#le(e);return{packet:t,changed:r}}if(this.#pe(e)){let t=await Promise.all(e.packets.map(o=>this.#$(o)));if(!t.some(o=>o.changed))return{packet:e,changed:!1};let i=t.map(o=>o.packet);return{packet:{timeTag:e.timeTag,packets:i},changed:!0}}return{packet:e,changed:!1}}async#le(e){switch(e.address){case"/b_alloc":return{message:await this.#fe(e),changed:!0};case"/b_allocRead":return{message:await this.#ce(e),changed:!0};case"/b_allocReadChannel":return{message:await this.#ue(e),changed:!0};default:return{message:e,changed:!1}}}async#ce(e){let t=this.#O(),r=this.#v(e.args,0,"/b_allocRead requires a buffer number"),i=this.#W(e.args,1,"/b_allocRead requires a file path"),o=this.#T(e.args,2,0),a=this.#T(e.args,3,0),l=await t.prepareFromFile({bufnum:r,path:i,startFrame:o,numFrames:a});return this.#U(l.allocationComplete,`/b_allocRead ${r}`),this.#C(r,l)}async#ue(e){let t=this.#O(),r=this.#v(e.args,0,"/b_allocReadChannel requires a buffer number"),i=this.#W(e.args,1,"/b_allocReadChannel requires a file path"),o=this.#T(e.args,2,0),a=this.#T(e.args,3,0),l=[];for(let u=4;u<(e.args?.length||0)&&this.#D(e.args[u]);u++)l.push(Math.floor(this.#E(e.args[u])));let c=await t.prepareFromFile({bufnum:r,path:i,startFrame:o,numFrames:a,channels:l.length>0?l:null});return this.#U(c.allocationComplete,`/b_allocReadChannel ${r}`),this.#C(r,c)}async#fe(e){let t=this.#O(),r=this.#v(e.args,0,"/b_alloc requires a buffer number"),i=this.#v(e.args,1,"/b_alloc requires a frame count"),o=2,a=1,l=this.#r?.sampleRate||44100;this.#D(this.#S(e.args,o))&&(a=Math.max(1,this.#T(e.args,o,1)),o++),this.#S(e.args,o)?.type==="b"&&o++,this.#D(this.#S(e.args,o))&&(l=this.#E(this.#S(e.args,o)));let c=await t.prepareEmpty({bufnum:r,numFrames:i,numChannels:a,sampleRate:l});return this.#U(c.allocationComplete,`/b_alloc ${r}`),this.#C(r,c)}#C(e,t){return{address:"/b_allocPtr",args:[this.#M(e),this.#M(t.ptr),this.#M(t.numFrames),this.#M(t.numChannels),this.#he(t.sampleRate),this.#de(t.uuid)]}}#M(e){return{type:"i",value:Math.floor(e)}}#he(e){return{type:"f",value:e}}#de(e){return{type:"s",value:String(e)}}#S(e,t){if(Array.isArray(e))return e[t]}#E(e){if(e!=null)return typeof e=="object"&&Object.prototype.hasOwnProperty.call(e,"value")?e.value:e}#v(e,t,r){let i=this.#E(this.#S(e,t));if(!Number.isFinite(i))throw new Error(r);return Math.floor(i)}#T(e,t,r=0){let i=this.#E(this.#S(e,t));return Number.isFinite(i)?Math.floor(i):r}#W(e,t,r){let i=this.#E(this.#S(e,t));if(typeof i!="string")throw new Error(r);return i}#D(e){if(!e)return!1;let t=this.#E(e);return Number.isFinite(t)}#U(e,t){!e||typeof e.catch!="function"||e.catch(r=>{console.error(`[SuperSonic] ${t} allocation failed:`,r)})}#O(){if(!this.#s)throw new Error("Buffer manager not ready. Call init() before issuing buffer commands.");return this.#s}#pe(e){return e&&e.timeTag!==void 0&&Array.isArray(e.packets)}#me(e){if(e.length<16||String.fromCharCode.apply(null,e.slice(0,8))!=="#bundle\0")return null;let i=new Float64Array(this.#t,this.#i+this.#e.NTP_START_TIME_START,1)[0];if(i===0)return console.warn("[SuperSonic] NTP start time not yet initialized"),null;let o=new Int32Array(this.#t,this.#i+this.#e.DRIFT_OFFSET_START,1),l=Atomics.load(o,0)/1e3,c=new Int32Array(this.#t,this.#i+this.#e.GLOBAL_OFFSET_START,1),f=Atomics.load(c,0)/1e3,h=i+l+f,S=new DataView(e.buffer,e.byteOffset),m=S.getUint32(8,!1),d=S.getUint32(12,!1);if(m===0&&(d===0||d===1))return null;let p=m+d/4294967296-h,E=this.#r.currentTime;return{audioTimeS:p,currentTimeS:E}}};export{se as SuperSonic};
21
18
  /*! osc.js 2.4.5, Copyright 2024 Colin Clark | github.com/colinbdclark/osc.js */
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "wasmFile": "scsynth-nrt.wasm",
3
- "buildId": "20251123-223028",
4
- "buildTime": "2025-11-23T22:30:28Z",
5
- "gitHash": "36a2c4fe5"
3
+ "buildId": "20251124-140859",
4
+ "buildTime": "2025-11-24T14:08:59Z",
5
+ "gitHash": "eb272104c"
6
6
  }
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supersonic-scsynth",
3
- "version": "0.6.6",
3
+ "version": "0.7.1",
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",