supersonic-scsynth 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/supersonic.js
CHANGED
|
@@ -2098,6 +2098,12 @@ var SuperSonic = class _SuperSonic {
|
|
|
2098
2098
|
this._handleBufferFreed(msg.args);
|
|
2099
2099
|
} else if (msg.address === "/buffer/allocated") {
|
|
2100
2100
|
this._handleBufferAllocated(msg.args);
|
|
2101
|
+
} else if (msg.address === "/synced" && msg.args.length > 0) {
|
|
2102
|
+
const syncId = msg.args[0];
|
|
2103
|
+
if (this._syncListeners && this._syncListeners.has(syncId)) {
|
|
2104
|
+
const listener = this._syncListeners.get(syncId);
|
|
2105
|
+
listener(msg);
|
|
2106
|
+
}
|
|
2101
2107
|
}
|
|
2102
2108
|
if (this.onMessage) {
|
|
2103
2109
|
this.stats.messagesReceived++;
|
|
@@ -2512,7 +2518,7 @@ var SuperSonic = class _SuperSonic {
|
|
|
2512
2518
|
if (synthName) {
|
|
2513
2519
|
this.loadedSynthDefs.add(synthName);
|
|
2514
2520
|
}
|
|
2515
|
-
console.log(`[SuperSonic]
|
|
2521
|
+
console.log(`[SuperSonic] Sent synthdef from ${path} (${synthdefData.length} bytes)`);
|
|
2516
2522
|
} catch (error) {
|
|
2517
2523
|
console.error("[SuperSonic] Failed to load synthdef:", error);
|
|
2518
2524
|
throw error;
|
|
@@ -2548,9 +2554,45 @@ var SuperSonic = class _SuperSonic {
|
|
|
2548
2554
|
})
|
|
2549
2555
|
);
|
|
2550
2556
|
const successCount = Object.values(results).filter((r) => r.success).length;
|
|
2551
|
-
console.log(`[SuperSonic]
|
|
2557
|
+
console.log(`[SuperSonic] Sent ${successCount}/${names.length} synthdef loads`);
|
|
2552
2558
|
return results;
|
|
2553
2559
|
}
|
|
2560
|
+
/**
|
|
2561
|
+
* Send /sync command and wait for /synced response
|
|
2562
|
+
* Use this to ensure all previous asynchronous commands have completed
|
|
2563
|
+
* @param {number} syncId - Unique integer identifier for this sync operation
|
|
2564
|
+
* @returns {Promise<void>}
|
|
2565
|
+
* @example
|
|
2566
|
+
* await sonic.loadSynthDefs(['synth1', 'synth2']);
|
|
2567
|
+
* await sonic.sync(12345); // Wait for all synthdefs to be processed
|
|
2568
|
+
*/
|
|
2569
|
+
async sync(syncId) {
|
|
2570
|
+
if (!this.initialized) {
|
|
2571
|
+
throw new Error("SuperSonic not initialized. Call init() first.");
|
|
2572
|
+
}
|
|
2573
|
+
if (!Number.isInteger(syncId)) {
|
|
2574
|
+
throw new Error("sync() requires an integer syncId parameter");
|
|
2575
|
+
}
|
|
2576
|
+
const syncPromise = new Promise((resolve, reject) => {
|
|
2577
|
+
const timeout = setTimeout(() => {
|
|
2578
|
+
if (this._syncListeners) {
|
|
2579
|
+
this._syncListeners.delete(syncId);
|
|
2580
|
+
}
|
|
2581
|
+
reject(new Error("Timeout waiting for /synced response"));
|
|
2582
|
+
}, 1e4);
|
|
2583
|
+
const messageHandler = (msg) => {
|
|
2584
|
+
clearTimeout(timeout);
|
|
2585
|
+
this._syncListeners.delete(syncId);
|
|
2586
|
+
resolve();
|
|
2587
|
+
};
|
|
2588
|
+
if (!this._syncListeners) {
|
|
2589
|
+
this._syncListeners = /* @__PURE__ */ new Map();
|
|
2590
|
+
}
|
|
2591
|
+
this._syncListeners.set(syncId, messageHandler);
|
|
2592
|
+
});
|
|
2593
|
+
await this.send("/sync", syncId);
|
|
2594
|
+
await syncPromise;
|
|
2595
|
+
}
|
|
2554
2596
|
/**
|
|
2555
2597
|
* Allocate memory for an audio buffer (includes guard samples)
|
|
2556
2598
|
* @param {number} numSamples - Number of Float32 samples to allocate
|
package/dist/wasm/manifest.json
CHANGED
|
Binary file
|
|
@@ -171,40 +171,55 @@ function writeToRingBuffer(oscMessage, isRetry) {
|
|
|
171
171
|
return false;
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
//
|
|
174
|
+
// ringbuf.js approach: split writes across wrap boundary
|
|
175
|
+
// No padding markers - just split the write into two parts if it wraps
|
|
176
|
+
|
|
175
177
|
var spaceToEnd = bufferConstants.IN_BUFFER_SIZE - head;
|
|
176
178
|
|
|
177
179
|
if (totalSize > spaceToEnd) {
|
|
180
|
+
// Message will wrap - write in two parts
|
|
181
|
+
// Create header as byte array to simplify split writes
|
|
182
|
+
var headerBytes = new Uint8Array(bufferConstants.MESSAGE_HEADER_SIZE);
|
|
183
|
+
var headerView = new DataView(headerBytes.buffer);
|
|
184
|
+
headerView.setUint32(0, bufferConstants.MESSAGE_MAGIC, true);
|
|
185
|
+
headerView.setUint32(4, totalSize, true);
|
|
186
|
+
headerView.setUint32(8, stats.bundlesWritten, true);
|
|
187
|
+
headerView.setUint32(12, 0, true);
|
|
188
|
+
|
|
189
|
+
var writePos1 = ringBufferBase + bufferConstants.IN_BUFFER_START + head;
|
|
190
|
+
var writePos2 = ringBufferBase + bufferConstants.IN_BUFFER_START;
|
|
191
|
+
|
|
192
|
+
// Write header (may be split)
|
|
178
193
|
if (spaceToEnd >= bufferConstants.MESSAGE_HEADER_SIZE) {
|
|
179
|
-
//
|
|
180
|
-
|
|
181
|
-
dataView.setUint32(paddingPos, bufferConstants.PADDING_MAGIC, true);
|
|
182
|
-
dataView.setUint32(paddingPos + 4, 0, true);
|
|
183
|
-
dataView.setUint32(paddingPos + 8, 0, true);
|
|
184
|
-
dataView.setUint32(paddingPos + 12, 0, true);
|
|
185
|
-
} else if (spaceToEnd > 0) {
|
|
186
|
-
// Not enough room for a padding header - clear remaining bytes
|
|
187
|
-
var padStart = ringBufferBase + bufferConstants.IN_BUFFER_START + head;
|
|
188
|
-
for (var i = 0; i < spaceToEnd; i++) {
|
|
189
|
-
uint8View[padStart + i] = 0;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
194
|
+
// Header fits contiguously
|
|
195
|
+
uint8View.set(headerBytes, writePos1);
|
|
192
196
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
197
|
+
// Write payload (split across boundary)
|
|
198
|
+
var payloadBytesInFirstPart = spaceToEnd - bufferConstants.MESSAGE_HEADER_SIZE;
|
|
199
|
+
uint8View.set(oscMessage.subarray(0, payloadBytesInFirstPart), writePos1 + bufferConstants.MESSAGE_HEADER_SIZE);
|
|
200
|
+
uint8View.set(oscMessage.subarray(payloadBytesInFirstPart), writePos2);
|
|
201
|
+
} else {
|
|
202
|
+
// Header is split across boundary
|
|
203
|
+
uint8View.set(headerBytes.subarray(0, spaceToEnd), writePos1);
|
|
204
|
+
uint8View.set(headerBytes.subarray(spaceToEnd), writePos2);
|
|
196
205
|
|
|
197
|
-
|
|
198
|
-
|
|
206
|
+
// All payload goes at beginning
|
|
207
|
+
var payloadOffset = bufferConstants.MESSAGE_HEADER_SIZE - spaceToEnd;
|
|
208
|
+
uint8View.set(oscMessage, writePos2 + payloadOffset);
|
|
209
|
+
}
|
|
210
|
+
} else {
|
|
211
|
+
// Message fits contiguously - write normally
|
|
212
|
+
var writePos = ringBufferBase + bufferConstants.IN_BUFFER_START + head;
|
|
199
213
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
214
|
+
// Write header
|
|
215
|
+
dataView.setUint32(writePos, bufferConstants.MESSAGE_MAGIC, true);
|
|
216
|
+
dataView.setUint32(writePos + 4, totalSize, true);
|
|
217
|
+
dataView.setUint32(writePos + 8, stats.bundlesWritten, true);
|
|
218
|
+
dataView.setUint32(writePos + 12, 0, true);
|
|
205
219
|
|
|
206
|
-
|
|
207
|
-
|
|
220
|
+
// Write payload
|
|
221
|
+
uint8View.set(oscMessage, writePos + bufferConstants.MESSAGE_HEADER_SIZE);
|
|
222
|
+
}
|
|
208
223
|
|
|
209
224
|
// Diagnostic: Log first few writes
|
|
210
225
|
if (stats.bundlesWritten < 5) {
|
package/package.json
CHANGED