supersonic-scsynth 0.1.2 → 0.1.3

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,134 +1,117 @@
1
1
  # SuperSonic
2
2
 
3
- > **Warning - Super Alpha Status**: SuperSonic is currently in active development (v0.1.1). The API is likely to change between releases. Feedback welcome!
3
+ > **Warning - Super Alpha Status**: SuperSonic is currently in active development. The API is likely to change between releases. Feedback welcome!
4
4
 
5
- This is a WebAssembly port of SuperCollider's highly flexible and powerful synthesis engine scsynth.
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
6
 
7
- SuperSonic's scsynth engine runs within a web AudioWorklet giving it access to a high-priority audio thread for real-time browser-based audio synthesis.
8
-
9
- The main API for SuperSonic is scsynth's OSC API with support for immediate and scheduled execution of OSC messages and bundles. It's also possible to register a handler to receive OSC replies from scsynth in addition to debug messages that would normally have been printed to stdout.
10
-
11
- Note: SuperSonic uses a SharedBuffer to send and receive OSC messages from scsynth which requires specific COOP/COEP headers to be set in your web browser (see below).
12
-
13
-
14
- ## Installation
15
-
16
- ### Option 1: npm Package (Recommended)
17
-
18
- ```bash
19
- # Core engine only (~450KB)
20
- npm install supersonic-scsynth
21
-
22
- # Or install everything (engine + synthdefs + samples)
23
- npm install supersonic-scsynth-bundle
24
- ```
25
-
26
- ### Option 2: CDN (No build required)
7
+ ## Quick Start
27
8
 
28
9
  ```html
29
10
  <script type="module">
30
11
  import { SuperSonic } from 'https://unpkg.com/supersonic-scsynth@latest';
31
12
 
32
13
  const sonic = new SuperSonic({
33
- audioBaseURL: 'https://unpkg.com/supersonic-scsynth-samples@latest/samples/'
14
+ sampleBaseURL: 'https://unpkg.com/supersonic-scsynth-samples@latest/samples/',
15
+ synthdefBaseURL: 'https://unpkg.com/supersonic-scsynth-synthdefs@latest/synthdefs/'
34
16
  });
35
17
 
36
18
  await sonic.init();
37
19
 
38
- // Load synthdefs from CDN
39
- await sonic.loadSynthDefs(
40
- ['sonic-pi-beep'],
41
- 'https://unpkg.com/supersonic-scsynth-synthdefs@latest/synthdefs/'
42
- );
43
- </script>
44
- ```
45
-
46
- ### Option 3: Pre-built Distribution
20
+ // Load a synthdef
21
+ await sonic.loadSynthDefs(['sonic-pi-beep']);
47
22
 
48
- The 'nightly' (i.e. for every new commit) pre-built distribution files are published here:
49
-
50
- https://samaaron.github.io/supersonic/supersonic-dist.zip
23
+ // Trigger the synth
24
+ sonic.send('/s_new', 'sonic-pi-beep', -1, 0, 1, 'note', 60);
51
25
 
52
- This includes:
53
- - Core engine (WASM + JS)
54
- - All 120 synthdefs
55
- - All 206 samples
56
- - Size: ~35MB
57
-
58
- ## Package Structure
59
-
60
- SuperSonic is published as multiple npm packages to keep the core engine small:
26
+ // Load and play a sample
27
+ sonic.send('/b_allocRead', 0, 'bd_haus.flac');
28
+ sonic.send('/s_new', 'sonic-pi-basic_mono_player', -1, 0, 1, 'buf', 0);
29
+ </script>
30
+ ```
61
31
 
62
- ### Core Package
63
- - **`supersonic-scsynth`** (~450KB) - The WebAssembly scsynth engine
64
- - GPL-3.0-or-later license
32
+ **Note:** Requires specific HTTP headers (COOP/COEP) for SharedArrayBuffer support. See [Browser Requirements](#browser-requirements) below.
65
33
 
66
- ### Resource Packages
67
- - **`supersonic-scsynth-synthdefs`** (~67KB) - All 120 Sonic Pi synthdefs
68
- - MIT license
69
- - From [Sonic Pi](https://github.com/sonic-pi-net/sonic-pi)
34
+ ## Installation
70
35
 
71
- - **`supersonic-scsynth-samples`** (~34MB) - All 206 Sonic Pi samples
72
- - CC0-1.0 license (public domain)
73
- - Categories: ambient, bass, drums, electronic, glitch, guitar, hi-hats, loops, percussion, snares, tabla, vinyl, and more
74
- - From [Sonic Pi](https://github.com/sonic-pi-net/sonic-pi)
36
+ **Via npm:**
37
+ ```bash
38
+ # Core engine only (~450KB)
39
+ npm install supersonic-scsynth
75
40
 
76
- ### Convenience Package
77
- - **`supersonic-scsynth-bundle`** - Includes core + synthdefs + all samples
78
- - Install this to get everything in one command
41
+ # Everything (engine + synthdefs + samples)
42
+ npm install supersonic-scsynth-bundle
43
+ ```
79
44
 
80
- ## Building from Source
45
+ **Via CDN:**
46
+ ```javascript
47
+ import { SuperSonic } from 'https://unpkg.com/supersonic-scsynth@latest';
48
+ ```
81
49
 
82
- If you are familiar with Docker, you can build and run the example using the following commands:
50
+ **Pre-built distribution:**
51
+ Download the 'nightly' build (~35MB with all synthdefs and samples):
52
+ https://samaaron.github.io/supersonic/supersonic-dist.zip
83
53
 
84
- ```bash
85
- docker build -t supersonic .
86
- docker run --rm -it -p 8002:8002 supersonic
87
- ```
54
+ ## Packages
88
55
 
89
- Or to build and run locally follow the instructions below.
56
+ SuperSonic is split into multiple packages:
90
57
 
91
- ### 1. Build
58
+ | Package | Size | License | Contents |
59
+ |---------|------|---------|----------|
60
+ | `supersonic-scsynth` | ~450KB | GPL-3.0-or-later | Core WASM engine |
61
+ | `supersonic-scsynth-synthdefs` | ~67KB | MIT | 120 Sonic Pi synthdefs |
62
+ | `supersonic-scsynth-samples` | ~34MB | CC0-1.0 | 206 Sonic Pi samples |
63
+ | `supersonic-scsynth-bundle` | - | - | All of the above |
92
64
 
93
- **Prerequisites:**
94
- - [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html)
95
- - [esbuild](https://esbuild.github.io/)
65
+ All synthdefs and samples are from [Sonic Pi](https://github.com/sonic-pi-net/sonic-pi).
96
66
 
97
- ```bash
98
- # Activate Emscripten
99
- source ~/path/to/emsdk_env.sh
67
+ ## API Reference
100
68
 
101
- # Build (compiles C++ to WASM and bundles JavaScript)
102
- ./build.sh
69
+ **Creating an instance:**
70
+ ```javascript
71
+ const sonic = new SuperSonic({
72
+ sampleBaseURL: 'https://unpkg.com/supersonic-scsynth-samples@latest/samples/',
73
+ synthdefBaseURL: 'https://unpkg.com/supersonic-scsynth-synthdefs@latest/synthdefs/',
74
+ audioPathMap: { /* optional custom path mappings */ }
75
+ });
103
76
  ```
104
77
 
105
- Outputs to `dist/` directory (~1.5MB WASM + ~76KB JS + symlinks to synthdefs/samples).
106
-
107
- ### 2. Serve Demo
78
+ **Core methods:**
79
+ - `await sonic.init()` - Initialize the audio engine
80
+ - `await sonic.loadSynthDefs(names)` - Load synth definitions
81
+ - `sonic.send(address, ...args)` - Send OSC message (types auto-detected)
82
+ - `sonic.sendOSC(oscBytes, options)` - Send pre-encoded OSC bytes
108
83
 
109
- Start the basic Ruby webserver with the correct headers:
84
+ **Callbacks:**
85
+ - `sonic.onInitialized` - Called when ready
86
+ - `sonic.onError(error)` - Error handling
87
+ - `sonic.onMessageReceived(msg)` - Incoming OSC messages
88
+ - `sonic.onMessageSent(oscData)` - Outgoing OSC messages
110
89
 
111
- ```bash
112
- ruby example/server.rb
90
+ **Common OSC commands:**
91
+ ```javascript
92
+ sonic.send('/notify', 1); // Enable notifications
93
+ sonic.send('/s_new', 'synth-name', -1, 0, 1); // Create synth
94
+ sonic.send('/n_set', 1000, 'freq', 440.0, 'amp', 0.5); // Set parameters
95
+ sonic.send('/n_free', 1000); // Free node
96
+ sonic.send('/b_allocRead', 0, 'sample.flac'); // Load audio buffer
113
97
  ```
114
98
 
115
- Open: http://localhost:8002/demo.html
99
+ See [SuperCollider Server Command Reference](https://doc.sccode.org/Reference/Server-Command-Reference.html) for the full OSC API.
116
100
 
117
101
  ## Browser Requirements
118
102
 
119
- **Minimum Versions:**
103
+ **Minimum browser versions:**
120
104
  - Chrome/Edge 92+
121
105
  - Firefox 79+
122
106
  - Safari 15.2+
123
107
 
124
- **Required Features:**
125
- - SharedArrayBuffer (requires COOP/COEP headers - see below)
108
+ **Required features:**
109
+ - SharedArrayBuffer (requires COOP/COEP headers)
126
110
  - AudioWorklet
127
- - WebAssembly with threads support
111
+ - WebAssembly with threads
128
112
 
129
- **Required HTTP Headers:**
130
-
131
- Important: your server must send these headers for SharedArrayBuffer to work:
113
+ **Required HTTP headers:**
114
+ Your server must send these headers for SharedArrayBuffer support:
132
115
 
133
116
  ```
134
117
  Cross-Origin-Opener-Policy: same-origin
@@ -138,121 +121,39 @@ Cross-Origin-Resource-Policy: cross-origin
138
121
 
139
122
  See `example/server.rb` for a reference implementation.
140
123
 
141
- ## Basic Usage
142
-
143
- ### Minimal Example (Core Only)
144
-
145
- ```javascript
146
- import { SuperSonic } from './dist/supersonic.js';
147
-
148
- const sonic = new SuperSonic();
149
- await sonic.init();
150
-
151
- sonic.send('/notify', 1);
152
- ```
153
-
154
- ### With Synthdefs and Samples (npm/CDN)
155
-
156
- ```javascript
157
- import { SuperSonic } from 'https://unpkg.com/supersonic-scsynth@latest';
158
-
159
- // Configure sample path (required for buffer loading)
160
- const sonic = new SuperSonic({
161
- audioBaseURL: 'https://unpkg.com/supersonic-scsynth-samples@latest/samples/'
162
- });
163
-
164
- await sonic.init();
165
-
166
- // Load synthdefs (baseUrl is required)
167
- await sonic.loadSynthDefs(
168
- ['sonic-pi-beep', 'sonic-pi-tb303'],
169
- 'https://unpkg.com/supersonic-scsynth-synthdefs@latest/synthdefs/'
170
- );
124
+ ## Building from Source
171
125
 
172
- // Play a synth
173
- sonic.send('/s_new', 'sonic-pi-beep', -1, 0, 1, 'note', 60);
126
+ **Prerequisites:**
127
+ - [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html)
128
+ - [esbuild](https://esbuild.github.io/)
174
129
 
175
- // Load and play a sample
176
- await sonic.allocReadBuffer(0, 'bd_haus.flac');
177
- sonic.send('/s_new', 'sonic-pi-basic_mono_player', -1, 0, 1, 'buf', 0);
178
- ```
130
+ **Build:**
131
+ ```bash
132
+ # Activate Emscripten
133
+ source ~/path/to/emsdk_env.sh
179
134
 
180
- See `example/demo.html` for a complete working example.
181
-
182
- ### API Reference
183
-
184
- **SuperSonic Class:**
185
- - `new SuperSonic(options)` - Create instance
186
- - `options.audioBaseURL` - Base URL for sample files (required for buffer loading)
187
- - `options.audioPathMap` - Custom mapping of sample names to URLs
188
- - `async init()` - Initialize audio engine
189
- - `async loadSynthDefs(names, baseUrl)` - Load synth definitions (baseUrl required)
190
- - `async allocReadBuffer(bufnum, filename)` - Load audio file into buffer
191
- - `send(address, ...args)` - Send OSC message (auto-detects types)
192
- - `sendOSC(oscBytes, options)` - Send pre-encoded OSC bytes
193
- - `onInitialized` - Callback when ready
194
- - `onError(error)` - Error callback
195
- - `onMessageReceived(msg)` - Incoming OSC message callback
196
- - `onMessageSent(oscData)` - Outgoing OSC message callback
197
-
198
- **Sending OSC Messages:**
199
- ```javascript
200
- // Types are auto-detected: strings → 's', integers → 'i', floats → 'f'
201
- sonic.send('/notify', 1);
202
- sonic.send('/s_new', 'sonic-pi-beep', -1, 0, 0);
203
- sonic.send('/n_set', 1000, 'freq', 440.0, 'amp', 0.5);
135
+ # Compile and bundle
136
+ ./build.sh
204
137
  ```
205
138
 
206
- **Common OSC Commands:**
207
- - `/d_recv` - Load synth definition
208
- - `/s_new` - Create synth
209
- - `/n_free` - Free node
210
- - `/n_set` - Set node parameters
211
- - `/notify` - Enable server notifications
212
-
213
- See [SuperCollider Server Command Reference](https://doc.sccode.org/Reference/Server-Command-Reference.html) for full OSC API.
214
-
215
- ## Integration Guide
216
-
217
- ### Recommended: npm Packages
218
-
219
- Install the core package and any resources you need:
139
+ Output goes to `dist/` directory (~1.5MB WASM + ~76KB JS + workers).
220
140
 
141
+ **Run demo:**
221
142
  ```bash
222
- # Core engine
223
- npm install supersonic-scsynth
224
-
225
- # Synthdefs (optional)
226
- npm install supersonic-scsynth-synthdefs
227
-
228
- # Samples (optional)
229
- npm install supersonic-scsynth-samples
230
-
231
- # Or everything at once
232
- npm install supersonic-scsynth-bundle
143
+ ruby example/server.rb
233
144
  ```
234
145
 
235
- Then use via CDN in your HTML:
236
-
237
- ```html
238
- <script type="module">
239
- import { SuperSonic } from 'https://unpkg.com/supersonic-scsynth@latest';
240
-
241
- const sonic = new SuperSonic({
242
- audioBaseURL: 'https://unpkg.com/supersonic-scsynth-samples@latest/samples/'
243
- });
146
+ Open http://localhost:8002/demo.html
244
147
 
245
- await sonic.init();
246
- await sonic.loadSynthDefs(
247
- ['sonic-pi-beep'],
248
- 'https://unpkg.com/supersonic-scsynth-synthdefs@latest/synthdefs/'
249
- );
250
- </script>
148
+ **Docker:**
149
+ ```bash
150
+ docker build -t supersonic .
151
+ docker run --rm -it -p 8002:8002 supersonic
251
152
  ```
252
153
 
253
- ### Alternative: Manual File Integration
154
+ ## File Structure
254
155
 
255
- If you're building from source or need local files, copy these from `dist/`:
156
+ When building from source or using local files:
256
157
 
257
158
  ```
258
159
  dist/
@@ -260,40 +161,13 @@ dist/
260
161
  ├── wasm/
261
162
  │ └── scsynth-nrt.wasm # Audio engine (~1.5MB)
262
163
  └── workers/
263
- ├── osc_in_worker.js # OSC input handling
264
- ├── osc_out_worker.js # OSC output handling
265
- ├── debug_worker.js # Debug logging
266
- └── scsynth_audio_worklet.js # AudioWorklet processor
267
- ```
268
-
269
- Resources (synthdefs/samples) are available separately via npm packages.
270
-
271
- ### Path Configuration
272
-
273
- **Required Configuration:**
274
-
275
- Sample and synthdef paths must be explicitly configured:
276
-
277
- ```javascript
278
- const sonic = new SuperSonic({
279
- audioBaseURL: 'https://unpkg.com/supersonic-scsynth-samples@latest/samples/'
280
- });
281
-
282
- await sonic.loadSynthDefs(
283
- ['sonic-pi-beep'],
284
- 'https://unpkg.com/supersonic-scsynth-synthdefs@latest/synthdefs/'
285
- );
164
+ ├── scsynth_audio_worklet.js # AudioWorklet processor
165
+ ├── osc_in_worker.js # OSC input handler
166
+ ├── osc_out_worker.js # OSC output handler
167
+ └── debug_worker.js # Debug logger
286
168
  ```
287
169
 
288
- **Engine Paths:**
289
-
290
- The core engine expects these files relative to your HTML:
291
- - WASM: `./dist/wasm/scsynth-nrt.wasm`
292
- - AudioWorklet: `./dist/workers/scsynth_audio_worklet.js`
293
- - Workers: `./dist/workers/osc_out_worker.js`, `osc_in_worker.js`, `debug_worker.js`
294
-
295
- These paths are currently not configurable.
296
-
170
+ The engine expects these files at `./dist/` relative to your HTML. Paths are currently not configurable.
297
171
 
298
172
  ## License
299
173
 
@@ -301,5 +175,4 @@ GPL v3 - This is a derivative work of SuperCollider
301
175
 
302
176
  ## Credits
303
177
 
304
- Based on [SuperCollider](https://supercollider.github.io/) by James McCartney and the SuperCollider community. This AudioWorklet port was massively inspired and motivated by
305
- Hanns Holger Rutz who started the first port of scsynth to WASM and Dennis Scheiba who took the baton and continued this great work. Thank-you also to everyone in the SuperCollider community, you're all beautiful people.
178
+ Based on [SuperCollider](https://supercollider.github.io/) by James McCartney and the SuperCollider community. This AudioWorklet port was inspired by Hanns Holger Rutz who started the first port of scsynth to WASM and Dennis Scheiba who continued this work. Thank you to everyone in the SuperCollider community!
@@ -1616,7 +1616,8 @@ var SuperSonic = class {
1616
1616
  sampleRate: 48e3
1617
1617
  }
1618
1618
  };
1619
- this.audioBaseURL = options.audioBaseURL || null;
1619
+ this.sampleBaseURL = options.sampleBaseURL || null;
1620
+ this.synthdefBaseURL = options.synthdefBaseURL || null;
1620
1621
  this.audioPathMap = options.audioPathMap || {};
1621
1622
  this.allocatedBuffers = /* @__PURE__ */ new Map();
1622
1623
  this.stats = {
@@ -2099,12 +2100,12 @@ var SuperSonic = class {
2099
2100
  if (this.audioPathMap[scPath]) {
2100
2101
  return this.audioPathMap[scPath];
2101
2102
  }
2102
- if (!this.audioBaseURL) {
2103
+ if (!this.sampleBaseURL) {
2103
2104
  throw new Error(
2104
- 'audioBaseURL not configured. Please set it in SuperSonic constructor options.\nExample: new SuperSonic({ audioBaseURL: "https://unpkg.com/supersonic-scsynth-samples@latest/samples/" })\nOr install sample packages: npm install supersonic-scsynth-samples'
2105
+ 'sampleBaseURL not configured. Please set it in SuperSonic constructor options.\nExample: new SuperSonic({ sampleBaseURL: "https://unpkg.com/supersonic-scsynth-samples@latest/samples/" })\nOr install sample packages: npm install supersonic-scsynth-samples'
2105
2106
  );
2106
2107
  }
2107
- return this.audioBaseURL + scPath;
2108
+ return this.sampleBaseURL + scPath;
2108
2109
  }
2109
2110
  /**
2110
2111
  * Handle /buffer/freed message from WASM
@@ -2311,28 +2312,24 @@ var SuperSonic = class {
2311
2312
  /**
2312
2313
  * Load multiple synthdefs from a directory
2313
2314
  * @param {string[]} names - Array of synthdef names (without .scsyndef extension)
2314
- * @param {string} baseUrl - Base URL for synthdef files (required)
2315
2315
  * @returns {Promise<Object>} Map of name -> success/error
2316
2316
  * @example
2317
- * const results = await sonic.loadSynthDefs(
2318
- * ['sonic-pi-beep', 'sonic-pi-tb303'],
2319
- * 'https://unpkg.com/supersonic-scsynth-synthdefs@latest/synthdefs/'
2320
- * );
2317
+ * const results = await sonic.loadSynthDefs(['sonic-pi-beep', 'sonic-pi-tb303']);
2321
2318
  */
2322
- async loadSynthDefs(names, baseUrl) {
2319
+ async loadSynthDefs(names) {
2323
2320
  if (!this.initialized) {
2324
2321
  throw new Error("SuperSonic not initialized. Call init() first.");
2325
2322
  }
2326
- if (!baseUrl) {
2323
+ if (!this.synthdefBaseURL) {
2327
2324
  throw new Error(
2328
- 'baseUrl is required. Please specify the URL to your synthdefs.\nExample: await sonic.loadSynthDefs(["sonic-pi-beep"], "https://unpkg.com/supersonic-scsynth-synthdefs@latest/synthdefs/")\nOr install: npm install supersonic-scsynth-synthdefs'
2325
+ 'synthdefBaseURL not configured. Please set it in SuperSonic constructor options.\nExample: new SuperSonic({ synthdefBaseURL: "https://unpkg.com/supersonic-scsynth-synthdefs@latest/synthdefs/" })\nOr install: npm install supersonic-scsynth-synthdefs'
2329
2326
  );
2330
2327
  }
2331
2328
  const results = {};
2332
2329
  await Promise.all(
2333
2330
  names.map(async (name) => {
2334
2331
  try {
2335
- const path = `${baseUrl}${name}.scsyndef`;
2332
+ const path = `${this.synthdefBaseURL}${name}.scsyndef`;
2336
2333
  await this.loadSynthDef(path);
2337
2334
  results[name] = { success: true };
2338
2335
  } catch (error) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "wasmFile": "scsynth-nrt.wasm",
3
- "buildId": "20251104-122135",
4
- "buildTime": "2025-11-04T12:21:35Z",
5
- "gitHash": "261e158"
3
+ "buildId": "20251104-125406",
4
+ "buildTime": "2025-11-04T12:54:06Z",
5
+ "gitHash": "003a9a0"
6
6
  }
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supersonic-scsynth",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
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",