@libraz/libsonare 1.8.0 → 1.8.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 +2 -2
- package/dist/_effects_common.d.ts +2 -1
- package/dist/_effects_common.d.ts.map +1 -1
- package/dist/analysis.js +1 -0
- package/dist/analysis.js.map +1 -1
- package/dist/effects_mastering.d.ts +2 -2
- package/dist/effects_mastering.d.ts.map +1 -1
- package/dist/effects_note_ops.d.ts +55 -30
- package/dist/effects_note_ops.d.ts.map +1 -1
- package/dist/effects_timepitch.d.ts +17 -12
- package/dist/effects_timepitch.d.ts.map +1 -1
- package/dist/feature_decompose.d.ts +1 -1
- package/dist/feature_decompose.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +216 -60
- package/dist/index.js.map +1 -1
- package/dist/mastering_core.d.ts +27 -1
- package/dist/mastering_core.d.ts.map +1 -1
- package/dist/mixer.d.ts.map +1 -1
- package/dist/project_types.d.ts +7 -5
- package/dist/project_types.d.ts.map +1 -1
- package/dist/public_types_mastering.d.ts +19 -1
- package/dist/public_types_mastering.d.ts.map +1 -1
- package/dist/public_types_playback.d.ts +1 -0
- package/dist/public_types_playback.d.ts.map +1 -1
- package/dist/public_types_spectral.d.ts +5 -5
- package/dist/public_types_spectral.d.ts.map +1 -1
- package/dist/realtime_engine.d.ts +49 -6
- package/dist/realtime_engine.d.ts.map +1 -1
- package/dist/sonare-analysis.wasm +0 -0
- package/dist/sonare.d.ts +36 -0
- package/dist/sonare.js +1 -1
- package/dist/sonare.wasm +0 -0
- package/dist/streaming_processors.d.ts +5 -0
- package/dist/streaming_processors.d.ts.map +1 -1
- package/dist/worker.js.map +1 -1
- package/dist/worklet/engine-mixer-facade.d.ts +40 -4
- package/dist/worklet/engine-mixer-facade.d.ts.map +1 -1
- package/dist/worklet/engine-node.d.ts +2 -0
- package/dist/worklet/engine-node.d.ts.map +1 -1
- package/dist/worklet/engine-processor.d.ts +4 -0
- package/dist/worklet/engine-processor.d.ts.map +1 -1
- package/dist/worklet/engine-strips.d.ts +4 -2
- package/dist/worklet/engine-strips.d.ts.map +1 -1
- package/dist/worklet/engine-sync.d.ts +4 -2
- package/dist/worklet/engine-sync.d.ts.map +1 -1
- package/dist/worklet/engine.d.ts +27 -6
- package/dist/worklet/engine.d.ts.map +1 -1
- package/dist/worklet/guards.d.ts +7 -1
- package/dist/worklet/guards.d.ts.map +1 -1
- package/dist/worklet/messages.d.ts +4 -4
- package/dist/worklet/messages.d.ts.map +1 -1
- package/dist/worklet/mixer-processor.d.ts +2 -2
- package/dist/worklet/mixer-processor.d.ts.map +1 -1
- package/dist/worklet/protocol.d.ts +10 -2
- package/dist/worklet/protocol.d.ts.map +1 -1
- package/dist/worklet.js +585 -188
- package/dist/worklet.js.map +1 -1
- package/package.json +1 -1
- package/src/_effects_common.ts +36 -6
- package/src/effects_mastering.ts +4 -0
- package/src/effects_note_ops.ts +92 -44
- package/src/effects_timepitch.ts +42 -31
- package/src/feature_decompose.ts +2 -2
- package/src/index.ts +6 -0
- package/src/mastering_core.ts +95 -0
- package/src/mixer.ts +39 -19
- package/src/project_types.ts +7 -5
- package/src/public_types_mastering.ts +21 -0
- package/src/public_types_playback.ts +1 -0
- package/src/public_types_spectral.ts +5 -5
- package/src/realtime_engine.ts +71 -15
- package/src/sonare.js.d.ts +36 -0
- package/src/streaming_processors.ts +8 -0
- package/src/worklet/engine-mixer-facade.ts +420 -86
- package/src/worklet/engine-node.ts +22 -4
- package/src/worklet/engine-processor.ts +83 -33
- package/src/worklet/engine-strips.ts +5 -10
- package/src/worklet/engine-sync.ts +6 -1
- package/src/worklet/engine.ts +49 -37
- package/src/worklet/guards.ts +55 -0
- package/src/worklet/messages.ts +4 -2
- package/src/worklet/mixer-processor.ts +10 -3
- package/src/worklet/protocol.ts +29 -8
package/dist/worklet.js
CHANGED
|
@@ -1194,7 +1194,10 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1194
1194
|
/**
|
|
1195
1195
|
* Route a destination's (track lane's) MIDI to the external output queue
|
|
1196
1196
|
* instead of the internal instrument rack, so the track plays an external
|
|
1197
|
-
* device. Clearing it restores internal-synth playback.
|
|
1197
|
+
* device. Clearing it restores internal-synth playback. Control-thread only.
|
|
1198
|
+
* The change takes effect at the next processed block; switching a
|
|
1199
|
+
* destination's route first releases its notes and resets its controllers
|
|
1200
|
+
* through the old route, and drops its pending MIDI-FX events. Single writer.
|
|
1198
1201
|
*/
|
|
1199
1202
|
setMidiDestinationExternal(destinationId, external) {
|
|
1200
1203
|
this.native.setMidiDestinationExternal(destinationId, external);
|
|
@@ -1348,8 +1351,11 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1348
1351
|
/**
|
|
1349
1352
|
* Queue an immediate (live) MIDI SysEx frame to a MIDI destination. `data` is
|
|
1350
1353
|
* the full message including the leading 0xF0 and trailing 0xF7 (1..512
|
|
1351
|
-
* bytes). `renderFrame` is the frame to fire at, or -1 for immediate.
|
|
1352
|
-
* the
|
|
1354
|
+
* bytes). `renderFrame` is the frame to fire at, or -1 for immediate. Throws
|
|
1355
|
+
* `InvalidParameter` when the destination instrument cannot prepare
|
|
1356
|
+
* the SysEx (retrying cannot help), and `OutOfMemory` when the payload
|
|
1357
|
+
* slots or the command queue are full (retry after a processed block).
|
|
1358
|
+
* Mirrors the Node/Python/C-ABI `pushMidiSysex`.
|
|
1353
1359
|
*/
|
|
1354
1360
|
pushMidiSysex(destinationId, data, renderFrame = -1) {
|
|
1355
1361
|
this.native.pushMidiSysex(destinationId, data, renderFrame);
|
|
@@ -1372,12 +1378,30 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1372
1378
|
getTransportState() {
|
|
1373
1379
|
return this.native.getTransportState();
|
|
1374
1380
|
}
|
|
1381
|
+
/** Queues an integrated-loudness reset; short-term and momentary windows are retained. */
|
|
1382
|
+
resetMasterLoudnessMeter(renderFrame = -1) {
|
|
1383
|
+
this.native.resetMasterLoudnessMeter(renderFrame);
|
|
1384
|
+
}
|
|
1385
|
+
/** Reads the immutable factory value for a resolved insert parameter id. */
|
|
1386
|
+
insertParameterConstructedValue(paramId) {
|
|
1387
|
+
return this.native.insertParameterConstructedValue(paramId);
|
|
1388
|
+
}
|
|
1375
1389
|
play(renderFrame = -1) {
|
|
1376
1390
|
this.native.play(renderFrame);
|
|
1377
1391
|
}
|
|
1392
|
+
/**
|
|
1393
|
+
* A loop wrap, seek or stop sends note-offs plus CC64=0, CC121, CC123 and a
|
|
1394
|
+
* centred pitch bend on every channel played since the last reset, so
|
|
1395
|
+
* controller values set before a loop region are not restored at the wrap.
|
|
1396
|
+
*/
|
|
1378
1397
|
stop(renderFrame = -1) {
|
|
1379
1398
|
this.native.stop(renderFrame);
|
|
1380
1399
|
}
|
|
1400
|
+
/**
|
|
1401
|
+
* A loop wrap, seek or stop sends note-offs plus CC64=0, CC121, CC123 and a
|
|
1402
|
+
* centred pitch bend on every channel played since the last reset, so
|
|
1403
|
+
* controller values set before a loop region are not restored at the wrap.
|
|
1404
|
+
*/
|
|
1381
1405
|
seekSample(timelineSample, renderFrame = -1) {
|
|
1382
1406
|
this.native.seekSample(timelineSample, renderFrame);
|
|
1383
1407
|
}
|
|
@@ -1402,6 +1426,11 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1402
1426
|
applyCommandsDueNowPreservingFuture() {
|
|
1403
1427
|
this.native.applyCommandsDueNowPreservingFuture();
|
|
1404
1428
|
}
|
|
1429
|
+
/**
|
|
1430
|
+
* A loop wrap, seek or stop sends note-offs plus CC64=0, CC121, CC123 and a
|
|
1431
|
+
* centred pitch bend on every channel played since the last reset, so
|
|
1432
|
+
* controller values set before a loop region are not restored at the wrap.
|
|
1433
|
+
*/
|
|
1405
1434
|
seekPpq(ppq, renderFrame = -1) {
|
|
1406
1435
|
this.native.seekPpq(ppq, renderFrame);
|
|
1407
1436
|
}
|
|
@@ -1421,6 +1450,11 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1421
1450
|
sampleAtPpq(ppq) {
|
|
1422
1451
|
return Number(this.native.sampleAtPpq(ppq));
|
|
1423
1452
|
}
|
|
1453
|
+
/**
|
|
1454
|
+
* A loop wrap, seek or stop sends note-offs plus CC64=0, CC121, CC123 and a
|
|
1455
|
+
* centred pitch bend on every channel played since the last reset, so
|
|
1456
|
+
* controller values set before a loop region are not restored at the wrap.
|
|
1457
|
+
*/
|
|
1424
1458
|
setLoop(startPpq, endPpq, enabled = true) {
|
|
1425
1459
|
this.native.setLoop(startPpq, endPpq, enabled);
|
|
1426
1460
|
}
|
|
@@ -1515,10 +1549,10 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1515
1549
|
if (typeof lane === "number") {
|
|
1516
1550
|
return { trackId: lane };
|
|
1517
1551
|
}
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1552
|
+
return {
|
|
1553
|
+
...lane,
|
|
1554
|
+
sends: lane.sends ? _RealtimeEngine.normalizeSends(lane.sends) : void 0
|
|
1555
|
+
};
|
|
1522
1556
|
})
|
|
1523
1557
|
);
|
|
1524
1558
|
}
|
|
@@ -1531,9 +1565,10 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1531
1565
|
}
|
|
1532
1566
|
setTrackBuses(buses) {
|
|
1533
1567
|
this.native.setTrackBuses(
|
|
1534
|
-
Array.isArray(buses) ? buses.map(
|
|
1535
|
-
|
|
1536
|
-
|
|
1568
|
+
Array.isArray(buses) ? buses.map((bus) => ({
|
|
1569
|
+
...bus,
|
|
1570
|
+
sends: bus.sends ? _RealtimeEngine.normalizeSends(bus.sends) : void 0
|
|
1571
|
+
})) : buses
|
|
1537
1572
|
);
|
|
1538
1573
|
}
|
|
1539
1574
|
/**
|
|
@@ -1687,6 +1722,16 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1687
1722
|
* stages of the offline mastering chain (`repair.*`, `loudness`, and the
|
|
1688
1723
|
* match stages) have no insert form and no automation id: they buffer the
|
|
1689
1724
|
* entire signal by construction and do not run on the realtime path.
|
|
1725
|
+
*
|
|
1726
|
+
* The returned id uses the track's current positional lane selector. When
|
|
1727
|
+
* `setTrackLanes` successfully changes lane order or membership, the engine
|
|
1728
|
+
* remaps already queued and published track automation by track id, but it
|
|
1729
|
+
* cannot update a numeric id retained by the caller. Re-resolve every track
|
|
1730
|
+
* insert id after such a topology change before passing it to
|
|
1731
|
+
* `setAutomationLane`, `setParameter`, or `setParameterSmoothed`. Use
|
|
1732
|
+
* `setTrackStripInsertParamByName` when the operation needs a stable track
|
|
1733
|
+
* identity. Master and bus insert ids are separate and are not invalidated by
|
|
1734
|
+
* track-lane changes.
|
|
1690
1735
|
*/
|
|
1691
1736
|
resolveTrackInsertAutomationId(trackId, insertIndex, paramName) {
|
|
1692
1737
|
return this.native.resolveTrackInsertAutomationId(trackId, insertIndex, paramName);
|
|
@@ -2013,6 +2058,12 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
2013
2058
|
meterScratchRenderFrame() {
|
|
2014
2059
|
return Number(this.native.meterScratchRenderFrame());
|
|
2015
2060
|
}
|
|
2061
|
+
meterScratchInputPeakDbL() {
|
|
2062
|
+
return this.native.meterScratchInputPeakDbL();
|
|
2063
|
+
}
|
|
2064
|
+
meterScratchInputPeakDbR() {
|
|
2065
|
+
return this.native.meterScratchInputPeakDbR();
|
|
2066
|
+
}
|
|
2016
2067
|
meterScratchValue(field) {
|
|
2017
2068
|
return this.native.meterScratchValue(field);
|
|
2018
2069
|
}
|
|
@@ -2022,9 +2073,10 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
2022
2073
|
/**
|
|
2023
2074
|
* Drains pending meter telemetry as per-plane (wide) records for a surround
|
|
2024
2075
|
* target. Use this for a surround mix target; {@link drainMeterTelemetry}
|
|
2025
|
-
* stays the stereo fast path. The two share one queue
|
|
2026
|
-
* target
|
|
2027
|
-
* this wide drain is for an
|
|
2076
|
+
* stays the stereo fast path. The two share one queue and each consumes every
|
|
2077
|
+
* target's records, so an engine uses only one of them. The live AudioWorklet
|
|
2078
|
+
* path owns the queue via the stereo drain, so this wide drain is for an
|
|
2079
|
+
* offline (non-worklet) engine instance; per-plane
|
|
2028
2080
|
* surround meters are not delivered over the live worklet meter ring.
|
|
2029
2081
|
*/
|
|
2030
2082
|
drainMeterTelemetryWide(maxRecords = 1024) {
|
|
@@ -2186,47 +2238,60 @@ var Mixer = class _Mixer {
|
|
|
2186
2238
|
* after {@link delete}.
|
|
2187
2239
|
*/
|
|
2188
2240
|
createRealtimeBuffer() {
|
|
2189
|
-
const
|
|
2190
|
-
|
|
2191
|
-
let rightInputs = [];
|
|
2241
|
+
const leftInputs = [];
|
|
2242
|
+
const rightInputs = [];
|
|
2192
2243
|
let outLeft = this.mixer.outputLeftView();
|
|
2193
2244
|
let outRight = this.mixer.outputRightView();
|
|
2245
|
+
let acquiredStripCount = -1;
|
|
2246
|
+
const viewsDetached = () => outLeft.byteLength === 0 || outRight.byteLength === 0;
|
|
2194
2247
|
const acquire = () => {
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2248
|
+
const stripCount = this.stripCount();
|
|
2249
|
+
const detached = viewsDetached();
|
|
2250
|
+
if (detached) {
|
|
2251
|
+
leftInputs.length = 0;
|
|
2252
|
+
rightInputs.length = 0;
|
|
2253
|
+
} else {
|
|
2254
|
+
leftInputs.length = Math.min(leftInputs.length, stripCount);
|
|
2255
|
+
rightInputs.length = Math.min(rightInputs.length, stripCount);
|
|
2256
|
+
}
|
|
2257
|
+
for (let index = leftInputs.length; index < stripCount; index++) {
|
|
2198
2258
|
leftInputs.push(this.mixer.inputLeftView(index));
|
|
2259
|
+
}
|
|
2260
|
+
for (let index = rightInputs.length; index < stripCount; index++) {
|
|
2199
2261
|
rightInputs.push(this.mixer.inputRightView(index));
|
|
2200
2262
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2263
|
+
if (detached) {
|
|
2264
|
+
outLeft = this.mixer.outputLeftView();
|
|
2265
|
+
outRight = this.mixer.outputRightView();
|
|
2266
|
+
}
|
|
2267
|
+
acquiredStripCount = stripCount;
|
|
2203
2268
|
};
|
|
2204
2269
|
acquire();
|
|
2205
|
-
const
|
|
2206
|
-
if (
|
|
2270
|
+
const acquireIfNeeded = () => {
|
|
2271
|
+
if (acquiredStripCount !== this.stripCount() || viewsDetached()) {
|
|
2207
2272
|
acquire();
|
|
2208
2273
|
}
|
|
2209
2274
|
};
|
|
2210
2275
|
return {
|
|
2211
2276
|
get leftInputs() {
|
|
2212
|
-
|
|
2277
|
+
acquireIfNeeded();
|
|
2213
2278
|
return leftInputs;
|
|
2214
2279
|
},
|
|
2215
2280
|
get rightInputs() {
|
|
2216
|
-
|
|
2281
|
+
acquireIfNeeded();
|
|
2217
2282
|
return rightInputs;
|
|
2218
2283
|
},
|
|
2219
2284
|
get outLeft() {
|
|
2220
|
-
|
|
2285
|
+
acquireIfNeeded();
|
|
2221
2286
|
return outLeft;
|
|
2222
2287
|
},
|
|
2223
2288
|
get outRight() {
|
|
2224
|
-
|
|
2289
|
+
acquireIfNeeded();
|
|
2225
2290
|
return outRight;
|
|
2226
2291
|
},
|
|
2227
|
-
process: (numSamples
|
|
2228
|
-
|
|
2229
|
-
this.mixer.processPreparedStereo(numSamples);
|
|
2292
|
+
process: (numSamples) => {
|
|
2293
|
+
acquireIfNeeded();
|
|
2294
|
+
this.mixer.processPreparedStereo(numSamples ?? outLeft.length);
|
|
2230
2295
|
}
|
|
2231
2296
|
};
|
|
2232
2297
|
}
|
|
@@ -2999,6 +3064,13 @@ var StreamingMasteringChain = class {
|
|
|
2999
3064
|
reset() {
|
|
3000
3065
|
this.chain.reset();
|
|
3001
3066
|
}
|
|
3067
|
+
/**
|
|
3068
|
+
* Set one realtime-safe full-chain parameter at a serialized block boundary.
|
|
3069
|
+
* Structural, disabled-stage and unknown parameters are rejected.
|
|
3070
|
+
*/
|
|
3071
|
+
setParameter(key, value) {
|
|
3072
|
+
this.chain.setParameter(key, value);
|
|
3073
|
+
}
|
|
3002
3074
|
/** Total reported latency in samples across all active processors. */
|
|
3003
3075
|
latencySamples() {
|
|
3004
3076
|
return this.chain.latencySamples();
|
|
@@ -3105,14 +3177,16 @@ function isInitialized() {
|
|
|
3105
3177
|
}
|
|
3106
3178
|
|
|
3107
3179
|
// src/worklet/engine-sync.ts
|
|
3108
|
-
function buildMixerLanes(trackLaneIds, trackSends, trackOutputBus) {
|
|
3180
|
+
function buildMixerLanes(trackLaneIds, trackSends, trackOutputBus, trackSourceChannelLayout) {
|
|
3109
3181
|
return trackLaneIds.map((trackId) => {
|
|
3110
3182
|
const sends = trackSends.get(trackId);
|
|
3111
3183
|
const outputBusId = trackOutputBus.get(trackId);
|
|
3184
|
+
const sourceChannelLayout = trackSourceChannelLayout.get(trackId);
|
|
3112
3185
|
return {
|
|
3113
3186
|
trackId,
|
|
3114
3187
|
...sends && sends.length > 0 ? { sends: sends.map((send) => ({ ...send })) } : {},
|
|
3115
|
-
...outputBusId !== void 0 ? { outputBusId } : {}
|
|
3188
|
+
...outputBusId !== void 0 ? { outputBusId } : {},
|
|
3189
|
+
...sourceChannelLayout !== void 0 ? { sourceChannelLayout } : {}
|
|
3116
3190
|
};
|
|
3117
3191
|
});
|
|
3118
3192
|
}
|
|
@@ -3187,10 +3261,12 @@ function engineMixerMasterTarget(paramKind) {
|
|
|
3187
3261
|
return ENGINE_MIXER_TARGET_BASE | 255 << 8 | paramKind & 255;
|
|
3188
3262
|
}
|
|
3189
3263
|
var SONARE_METER_RING_HEADER_INTS = 4;
|
|
3190
|
-
var SONARE_METER_RING_RECORD_FLOATS =
|
|
3264
|
+
var SONARE_METER_RING_RECORD_FLOATS = 16;
|
|
3191
3265
|
var SONARE_SPECTRUM_RING_HEADER_INTS = 5;
|
|
3192
3266
|
var SONARE_SCOPE_RING_HEADER_INTS = 6;
|
|
3193
3267
|
var SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS = 5;
|
|
3268
|
+
var SONARE_SCOPE_DEFAULT_BANDS = 48;
|
|
3269
|
+
var SONARE_SCOPE_DEFAULT_MAX_POINTS = 32;
|
|
3194
3270
|
var SONARE_FRAME_LANE_BASE = 16777216;
|
|
3195
3271
|
function encodeFrameLo(frame) {
|
|
3196
3272
|
const f = Math.max(0, Math.floor(frame));
|
|
@@ -3230,6 +3306,7 @@ var SonareEngineCommandType = /* @__PURE__ */ ((SonareEngineCommandType2) => {
|
|
|
3230
3306
|
SonareEngineCommandType2[SonareEngineCommandType2["SetMarker"] = 16] = "SetMarker";
|
|
3231
3307
|
SonareEngineCommandType2[SonareEngineCommandType2["SeekMarker"] = 17] = "SeekMarker";
|
|
3232
3308
|
SonareEngineCommandType2[SonareEngineCommandType2["SetTrackMonitorMode"] = 26] = "SetTrackMonitorMode";
|
|
3309
|
+
SonareEngineCommandType2[SonareEngineCommandType2["ResetMasterLoudnessMeter"] = 28] = "ResetMasterLoudnessMeter";
|
|
3233
3310
|
return SonareEngineCommandType2;
|
|
3234
3311
|
})(SonareEngineCommandType || {});
|
|
3235
3312
|
var SonareEngineTelemetryType = /* @__PURE__ */ ((SonareEngineTelemetryType2) => {
|
|
@@ -3262,6 +3339,7 @@ var SonareEngineTelemetryError = /* @__PURE__ */ ((SonareEngineTelemetryError2)
|
|
|
3262
3339
|
SonareEngineTelemetryError2[SonareEngineTelemetryError2["ParameterBaseOverflow"] = 21] = "ParameterBaseOverflow";
|
|
3263
3340
|
return SonareEngineTelemetryError2;
|
|
3264
3341
|
})(SonareEngineTelemetryError || {});
|
|
3342
|
+
var SONARE_FLOOR_DB = -120;
|
|
3265
3343
|
function isRecord(value) {
|
|
3266
3344
|
return typeof value === "object" && value !== null;
|
|
3267
3345
|
}
|
|
@@ -3301,7 +3379,9 @@ function readSonareMeterRingBuffer(ring, readIndex = 0) {
|
|
|
3301
3379
|
momentaryLufs: ring.records[offset + 10],
|
|
3302
3380
|
shortTermLufs: ring.records[offset + 11],
|
|
3303
3381
|
integratedLufs: ring.records[offset + 12],
|
|
3304
|
-
gainReductionDb: ring.records[offset + 13]
|
|
3382
|
+
gainReductionDb: ring.records[offset + 13],
|
|
3383
|
+
inputPeakDbL: ring.records[offset + 14],
|
|
3384
|
+
inputPeakDbR: ring.records[offset + 15]
|
|
3305
3385
|
});
|
|
3306
3386
|
}
|
|
3307
3387
|
return { nextReadIndex: writeIndex, meters };
|
|
@@ -3353,13 +3433,13 @@ function readSonareSpectrumRingBuffer(ring, readIndex = 0) {
|
|
|
3353
3433
|
function sonareScopeRingRecordFloats(bands, maxPoints) {
|
|
3354
3434
|
return SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS + bands + 2 * maxPoints;
|
|
3355
3435
|
}
|
|
3356
|
-
function sonareScopeRingBufferByteLength(capacity, bands =
|
|
3436
|
+
function sonareScopeRingBufferByteLength(capacity, bands = SONARE_SCOPE_DEFAULT_BANDS, maxPoints = SONARE_SCOPE_DEFAULT_MAX_POINTS) {
|
|
3357
3437
|
const clampedCapacity = Math.max(1, Math.floor(capacity));
|
|
3358
3438
|
const clampedBands = Math.max(1, Math.floor(bands));
|
|
3359
3439
|
const clampedPoints = Math.max(0, Math.floor(maxPoints));
|
|
3360
3440
|
return SONARE_SCOPE_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT + clampedCapacity * sonareScopeRingRecordFloats(clampedBands, clampedPoints) * Float32Array.BYTES_PER_ELEMENT;
|
|
3361
3441
|
}
|
|
3362
|
-
function createSonareScopeRingBuffer(capacity = 64, bands =
|
|
3442
|
+
function createSonareScopeRingBuffer(capacity = 64, bands = SONARE_SCOPE_DEFAULT_BANDS, maxPoints = SONARE_SCOPE_DEFAULT_MAX_POINTS) {
|
|
3363
3443
|
const clampedCapacity = Math.max(1, Math.floor(capacity));
|
|
3364
3444
|
const clampedBands = Math.max(1, Math.floor(bands));
|
|
3365
3445
|
const clampedPoints = Math.max(0, Math.floor(maxPoints));
|
|
@@ -3426,8 +3506,14 @@ function scopeRingFromSharedBuffer(sharedBuffer, fallbackCapacity, fallbackBands
|
|
|
3426
3506
|
const existingBands = Atomics.load(header, 3);
|
|
3427
3507
|
const existingMaxPoints = Atomics.load(header, 4);
|
|
3428
3508
|
const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));
|
|
3429
|
-
const bands = Math.max(
|
|
3430
|
-
|
|
3509
|
+
const bands = Math.max(
|
|
3510
|
+
1,
|
|
3511
|
+
Math.floor(existingBands || fallbackBands || SONARE_SCOPE_DEFAULT_BANDS)
|
|
3512
|
+
);
|
|
3513
|
+
const maxPoints = Math.max(
|
|
3514
|
+
0,
|
|
3515
|
+
Math.floor(existingMaxPoints || (fallbackMaxPoints ?? SONARE_SCOPE_DEFAULT_MAX_POINTS))
|
|
3516
|
+
);
|
|
3431
3517
|
const recordFloats = sonareScopeRingRecordFloats(bands, maxPoints);
|
|
3432
3518
|
const minBytes = sonareScopeRingBufferByteLength(capacity, bands, maxPoints);
|
|
3433
3519
|
if (sharedBuffer.byteLength < minBytes) {
|
|
@@ -3832,7 +3918,9 @@ function meterFromEngine(meter) {
|
|
|
3832
3918
|
momentaryLufs: meter.momentaryLufs,
|
|
3833
3919
|
shortTermLufs: meter.shortTermLufs,
|
|
3834
3920
|
integratedLufs: meter.integratedLufs,
|
|
3835
|
-
gainReductionDb: meter.gainReductionDb
|
|
3921
|
+
gainReductionDb: meter.gainReductionDb,
|
|
3922
|
+
inputPeakDbL: meter.inputPeakDbL,
|
|
3923
|
+
inputPeakDbR: meter.inputPeakDbR
|
|
3836
3924
|
};
|
|
3837
3925
|
}
|
|
3838
3926
|
function magnitudeToDb(value) {
|
|
@@ -4017,7 +4105,23 @@ function isClipPageRequestMessage(value) {
|
|
|
4017
4105
|
);
|
|
4018
4106
|
}
|
|
4019
4107
|
function isMeterSnapshot(value) {
|
|
4020
|
-
return isRecord(value) && value.type === "meter" && typeof value.frame === "number" && typeof value.peakDbL === "number" && typeof value.peakDbR === "number" && typeof value.rmsDbL === "number" && typeof value.rmsDbR === "number" && typeof value.correlation === "number" && (typeof value.targetId === "number" || value.targetId === void 0);
|
|
4108
|
+
return isRecord(value) && value.type === "meter" && typeof value.frame === "number" && typeof value.peakDbL === "number" && typeof value.peakDbR === "number" && typeof value.rmsDbL === "number" && typeof value.rmsDbR === "number" && typeof value.correlation === "number" && Number.isFinite(value.inputPeakDbL) && Number.isFinite(value.inputPeakDbR) && (typeof value.targetId === "number" || value.targetId === void 0);
|
|
4109
|
+
}
|
|
4110
|
+
var SONARE_SCOPE_MAX_BANDS = 64;
|
|
4111
|
+
var SONARE_SCOPE_MAX_POINTS = 32;
|
|
4112
|
+
function isPlainFloat32Array(value, maxLength, evenLength = false) {
|
|
4113
|
+
if (!(value instanceof Float32Array) || typeof ArrayBuffer === "undefined" || !(value.buffer instanceof ArrayBuffer) || value.length > maxLength || evenLength && value.length % 2 !== 0) {
|
|
4114
|
+
return false;
|
|
4115
|
+
}
|
|
4116
|
+
for (const sample of value) {
|
|
4117
|
+
if (!Number.isFinite(sample)) {
|
|
4118
|
+
return false;
|
|
4119
|
+
}
|
|
4120
|
+
}
|
|
4121
|
+
return true;
|
|
4122
|
+
}
|
|
4123
|
+
function isScopeSnapshot(value) {
|
|
4124
|
+
return isRecord(value) && value.type === "scope" && typeof value.targetId === "number" && Number.isSafeInteger(value.targetId) && value.targetId >= 0 && value.targetId <= 4294967295 && typeof value.frame === "number" && Number.isSafeInteger(value.frame) && value.frame >= 0 && isPlainFloat32Array(value.bands, SONARE_SCOPE_MAX_BANDS) && value.bands.length > 0 && isPlainFloat32Array(value.points, SONARE_SCOPE_MAX_POINTS * 2, true);
|
|
4021
4125
|
}
|
|
4022
4126
|
function requireIntegerOption(value, fallback, name, minimum) {
|
|
4023
4127
|
const resolved = value ?? fallback;
|
|
@@ -4026,6 +4130,9 @@ function requireIntegerOption(value, fallback, name, minimum) {
|
|
|
4026
4130
|
}
|
|
4027
4131
|
return resolved;
|
|
4028
4132
|
}
|
|
4133
|
+
function resolveScopeBandCount(value, fallback = SONARE_SCOPE_DEFAULT_BANDS) {
|
|
4134
|
+
return Math.min(requireIntegerOption(value, fallback, "scopeBands", 1), SONARE_SCOPE_MAX_BANDS);
|
|
4135
|
+
}
|
|
4029
4136
|
function requireInteger(value, fallback, name) {
|
|
4030
4137
|
const resolved = value ?? fallback;
|
|
4031
4138
|
if (!Number.isSafeInteger(resolved)) {
|
|
@@ -4325,6 +4432,156 @@ function syncMarkers(ctx) {
|
|
|
4325
4432
|
}
|
|
4326
4433
|
|
|
4327
4434
|
// src/worklet/engine-mixer-facade.ts
|
|
4435
|
+
function isSceneObject(value) {
|
|
4436
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4437
|
+
}
|
|
4438
|
+
function hasOwn2(object, key) {
|
|
4439
|
+
return Object.getOwnPropertyDescriptor(object, key) !== void 0;
|
|
4440
|
+
}
|
|
4441
|
+
function canonicalJson(value) {
|
|
4442
|
+
if (Array.isArray(value)) {
|
|
4443
|
+
return `[${value.map((item) => canonicalJson(item)).join(",")}]`;
|
|
4444
|
+
}
|
|
4445
|
+
if (value !== null && typeof value === "object") {
|
|
4446
|
+
const object = value;
|
|
4447
|
+
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(object[key])}`).join(",")}}`;
|
|
4448
|
+
}
|
|
4449
|
+
return JSON.stringify(value);
|
|
4450
|
+
}
|
|
4451
|
+
function aliasedValue(object, primary, legacy) {
|
|
4452
|
+
if (hasOwn2(object, primary)) {
|
|
4453
|
+
return { present: true, value: object[primary] };
|
|
4454
|
+
}
|
|
4455
|
+
if (hasOwn2(object, legacy)) {
|
|
4456
|
+
return { present: true, value: object[legacy] };
|
|
4457
|
+
}
|
|
4458
|
+
return { present: false, value: void 0 };
|
|
4459
|
+
}
|
|
4460
|
+
function insertSignature(insert) {
|
|
4461
|
+
const object = insert !== null && typeof insert === "object" ? insert : {};
|
|
4462
|
+
const slot = object.slot === void 0 ? "pre" : object.slot;
|
|
4463
|
+
const processor = aliasedValue(object, "processor", "processor_name");
|
|
4464
|
+
const params = aliasedValue(object, "params", "params_json");
|
|
4465
|
+
const sidechain = aliasedValue(object, "sidechainKey", "sidechain_key");
|
|
4466
|
+
const processorValue = typeof processor.value === "string" ? processor.value : "";
|
|
4467
|
+
const sidechainValue = typeof sidechain.value === "string" ? sidechain.value : "";
|
|
4468
|
+
let paramsValue;
|
|
4469
|
+
if (!params.present) {
|
|
4470
|
+
paramsValue = ["absent"];
|
|
4471
|
+
} else if (typeof params.value === "string") {
|
|
4472
|
+
if (params.value.length === 0) {
|
|
4473
|
+
paramsValue = ["absent"];
|
|
4474
|
+
} else {
|
|
4475
|
+
try {
|
|
4476
|
+
paramsValue = ["params", canonicalJson(JSON.parse(params.value))];
|
|
4477
|
+
} catch {
|
|
4478
|
+
paramsValue = ["params-invalid", params.value];
|
|
4479
|
+
}
|
|
4480
|
+
}
|
|
4481
|
+
} else {
|
|
4482
|
+
paramsValue = ["params", canonicalJson(params.value)];
|
|
4483
|
+
}
|
|
4484
|
+
return JSON.stringify([slot, processorValue, paramsValue, sidechainValue]);
|
|
4485
|
+
}
|
|
4486
|
+
function decodedInsertSignature(sceneJson, target) {
|
|
4487
|
+
const scene = JSON.parse(sceneJson);
|
|
4488
|
+
const entries = target.kind === "bus" ? scene.buses : scene.strips;
|
|
4489
|
+
const strip = Array.isArray(entries) ? entries.find(isSceneObject) : void 0;
|
|
4490
|
+
const object = isSceneObject(strip) ? strip : {};
|
|
4491
|
+
const inserts = Array.isArray(object.inserts) ? object.inserts.filter(isSceneObject) : [];
|
|
4492
|
+
const ordered = target.kind === "bus" ? inserts : [
|
|
4493
|
+
...inserts.filter((insert) => insert.slot !== "post"),
|
|
4494
|
+
...inserts.filter((insert) => insert.slot === "post")
|
|
4495
|
+
];
|
|
4496
|
+
return JSON.stringify(ordered.map(insertSignature));
|
|
4497
|
+
}
|
|
4498
|
+
function constructionValue(engine, target, override) {
|
|
4499
|
+
let parameterId = -1;
|
|
4500
|
+
switch (target.kind) {
|
|
4501
|
+
case "track":
|
|
4502
|
+
parameterId = engine.resolveTrackInsertAutomationId(
|
|
4503
|
+
target.trackId,
|
|
4504
|
+
override.insertIndex,
|
|
4505
|
+
override.paramName
|
|
4506
|
+
);
|
|
4507
|
+
break;
|
|
4508
|
+
case "bus":
|
|
4509
|
+
parameterId = engine.resolveBusInsertAutomationId(
|
|
4510
|
+
target.busId,
|
|
4511
|
+
override.insertIndex,
|
|
4512
|
+
override.paramName
|
|
4513
|
+
);
|
|
4514
|
+
break;
|
|
4515
|
+
case "master":
|
|
4516
|
+
parameterId = engine.resolveMasterInsertAutomationId(
|
|
4517
|
+
override.insertIndex,
|
|
4518
|
+
override.paramName
|
|
4519
|
+
);
|
|
4520
|
+
break;
|
|
4521
|
+
}
|
|
4522
|
+
if (parameterId < 0) {
|
|
4523
|
+
return void 0;
|
|
4524
|
+
}
|
|
4525
|
+
return engine.insertParameterConstructedValue(parameterId);
|
|
4526
|
+
}
|
|
4527
|
+
function constructionInsertOverrides(engine, target, overrides) {
|
|
4528
|
+
const restored = [];
|
|
4529
|
+
for (const override of overrides.values()) {
|
|
4530
|
+
if (!sameStripTarget(override.target, target)) {
|
|
4531
|
+
continue;
|
|
4532
|
+
}
|
|
4533
|
+
const value = constructionValue(engine, target, override);
|
|
4534
|
+
if (value !== void 0) {
|
|
4535
|
+
restored.push({ ...override, value });
|
|
4536
|
+
}
|
|
4537
|
+
}
|
|
4538
|
+
return restored;
|
|
4539
|
+
}
|
|
4540
|
+
function applyInsertParamOverride(engine, override) {
|
|
4541
|
+
switch (override.target.kind) {
|
|
4542
|
+
case "track":
|
|
4543
|
+
engine.restoreTrackStripInsertParamByName(
|
|
4544
|
+
override.target.trackId,
|
|
4545
|
+
override.insertIndex,
|
|
4546
|
+
override.paramName,
|
|
4547
|
+
override.value
|
|
4548
|
+
);
|
|
4549
|
+
break;
|
|
4550
|
+
case "bus":
|
|
4551
|
+
engine.restoreBusStripInsertParamByName(
|
|
4552
|
+
override.target.busId,
|
|
4553
|
+
override.insertIndex,
|
|
4554
|
+
override.paramName,
|
|
4555
|
+
override.value
|
|
4556
|
+
);
|
|
4557
|
+
break;
|
|
4558
|
+
case "master":
|
|
4559
|
+
engine.restoreMasterStripInsertParamByName(
|
|
4560
|
+
override.insertIndex,
|
|
4561
|
+
override.paramName,
|
|
4562
|
+
override.value
|
|
4563
|
+
);
|
|
4564
|
+
break;
|
|
4565
|
+
}
|
|
4566
|
+
}
|
|
4567
|
+
function applyConstructionInsertOverrides(engine, overrides) {
|
|
4568
|
+
for (const override of overrides) {
|
|
4569
|
+
applyInsertParamOverride(engine, override);
|
|
4570
|
+
}
|
|
4571
|
+
}
|
|
4572
|
+
function clearInsertParameterBases(engine, target) {
|
|
4573
|
+
switch (target.kind) {
|
|
4574
|
+
case "track":
|
|
4575
|
+
engine.clearTrackInsertParameterBases(target.trackId);
|
|
4576
|
+
break;
|
|
4577
|
+
case "bus":
|
|
4578
|
+
engine.clearBusInsertParameterBases(target.busId);
|
|
4579
|
+
break;
|
|
4580
|
+
case "master":
|
|
4581
|
+
engine.clearMasterInsertParameterBases();
|
|
4582
|
+
break;
|
|
4583
|
+
}
|
|
4584
|
+
}
|
|
4328
4585
|
function emptyStripJson(target) {
|
|
4329
4586
|
switch (target.kind) {
|
|
4330
4587
|
case "track":
|
|
@@ -4367,7 +4624,7 @@ function hasInsertParamOverrides(overrides, target) {
|
|
|
4367
4624
|
}
|
|
4368
4625
|
return false;
|
|
4369
4626
|
}
|
|
4370
|
-
function applyFullStripJson(engine, target, sceneJson
|
|
4627
|
+
function applyFullStripJson(engine, target, sceneJson) {
|
|
4371
4628
|
const apply = (json) => {
|
|
4372
4629
|
switch (target.kind) {
|
|
4373
4630
|
case "track":
|
|
@@ -4383,21 +4640,6 @@ function applyFullStripJson(engine, target, sceneJson, resetInserts) {
|
|
|
4383
4640
|
};
|
|
4384
4641
|
engine.applyCommandsDueNowPreservingFuture();
|
|
4385
4642
|
apply(sceneJson);
|
|
4386
|
-
if (resetInserts) {
|
|
4387
|
-
switch (target.kind) {
|
|
4388
|
-
case "track":
|
|
4389
|
-
engine.clearTrackInsertParameterBases(target.trackId);
|
|
4390
|
-
break;
|
|
4391
|
-
case "bus":
|
|
4392
|
-
engine.clearBusInsertParameterBases(target.busId);
|
|
4393
|
-
break;
|
|
4394
|
-
case "master":
|
|
4395
|
-
engine.clearMasterInsertParameterBases();
|
|
4396
|
-
break;
|
|
4397
|
-
}
|
|
4398
|
-
apply(emptyStripJson(target));
|
|
4399
|
-
apply(sceneJson);
|
|
4400
|
-
}
|
|
4401
4643
|
}
|
|
4402
4644
|
function insertParamOverrideKey(override) {
|
|
4403
4645
|
const targetId = override.target.kind === "track" ? override.target.trackId : override.target.kind === "bus" ? override.target.busId : "master";
|
|
@@ -4473,42 +4715,64 @@ function cacheStripJson(ctx, target, sceneJson) {
|
|
|
4473
4715
|
}
|
|
4474
4716
|
}
|
|
4475
4717
|
function mixerLanes(ctx) {
|
|
4476
|
-
return buildMixerLanes(
|
|
4718
|
+
return buildMixerLanes(
|
|
4719
|
+
ctx.trackLaneIds,
|
|
4720
|
+
ctx.trackSends,
|
|
4721
|
+
ctx.trackOutputBus,
|
|
4722
|
+
ctx.trackSourceChannelLayout
|
|
4723
|
+
);
|
|
4724
|
+
}
|
|
4725
|
+
function cloneMixerRouting(ctx) {
|
|
4726
|
+
return {
|
|
4727
|
+
trackLaneIds: [...ctx.trackLaneIds],
|
|
4728
|
+
trackSends: new Map(
|
|
4729
|
+
Array.from(ctx.trackSends, ([trackId, sends]) => [
|
|
4730
|
+
trackId,
|
|
4731
|
+
sends.map((send) => ({ ...send }))
|
|
4732
|
+
])
|
|
4733
|
+
),
|
|
4734
|
+
trackOutputBus: new Map(ctx.trackOutputBus),
|
|
4735
|
+
trackSourceChannelLayout: new Map(ctx.trackSourceChannelLayout)
|
|
4736
|
+
};
|
|
4737
|
+
}
|
|
4738
|
+
function commitMixerRouting(ctx, draft) {
|
|
4739
|
+
ctx.trackLaneIds.splice(0, ctx.trackLaneIds.length, ...draft.trackLaneIds);
|
|
4740
|
+
ctx.trackSends.clear();
|
|
4741
|
+
for (const [trackId, sends] of draft.trackSends) {
|
|
4742
|
+
ctx.trackSends.set(
|
|
4743
|
+
trackId,
|
|
4744
|
+
sends.map((send) => ({ ...send }))
|
|
4745
|
+
);
|
|
4746
|
+
}
|
|
4747
|
+
ctx.trackOutputBus.clear();
|
|
4748
|
+
for (const [trackId, busId] of draft.trackOutputBus) {
|
|
4749
|
+
ctx.trackOutputBus.set(trackId, busId);
|
|
4750
|
+
}
|
|
4751
|
+
ctx.trackSourceChannelLayout.clear();
|
|
4752
|
+
for (const [trackId, layout] of draft.trackSourceChannelLayout) {
|
|
4753
|
+
ctx.trackSourceChannelLayout.set(trackId, layout);
|
|
4754
|
+
}
|
|
4755
|
+
}
|
|
4756
|
+
function buildDraftMixerLanes(draft) {
|
|
4757
|
+
return buildMixerLanes(
|
|
4758
|
+
draft.trackLaneIds,
|
|
4759
|
+
draft.trackSends,
|
|
4760
|
+
draft.trackOutputBus,
|
|
4761
|
+
draft.trackSourceChannelLayout
|
|
4762
|
+
);
|
|
4477
4763
|
}
|
|
4478
|
-
function
|
|
4479
|
-
const lanes =
|
|
4764
|
+
function applyMixerRouting(ctx, draft, busesAlreadyApplied) {
|
|
4765
|
+
const lanes = buildDraftMixerLanes(draft);
|
|
4480
4766
|
const buses = ctx.buses.map((bus) => ({ ...bus }));
|
|
4481
4767
|
if (!busesAlreadyApplied) {
|
|
4482
4768
|
ctx.offlineEngine.setTrackBuses(buses);
|
|
4483
4769
|
}
|
|
4484
4770
|
if (lanes.length > 0) {
|
|
4485
|
-
ctx.offlineEngine.settleInsertParameters();
|
|
4486
4771
|
ctx.offlineEngine.setTrackLanes(lanes);
|
|
4487
4772
|
}
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
binding.trackId,
|
|
4492
|
-
binding.insertIndex,
|
|
4493
|
-
binding.sourceTrackId
|
|
4494
|
-
);
|
|
4495
|
-
}
|
|
4496
|
-
for (const binding of ctx.busSidechains.values()) {
|
|
4497
|
-
ctx.offlineEngine.setBusSidechain(
|
|
4498
|
-
binding.busId,
|
|
4499
|
-
binding.insertIndex,
|
|
4500
|
-
binding.sourceKind,
|
|
4501
|
-
binding.sourceId
|
|
4502
|
-
);
|
|
4503
|
-
}
|
|
4504
|
-
for (const binding of ctx.masterSidechains.values()) {
|
|
4505
|
-
ctx.offlineEngine.setMasterSidechain(
|
|
4506
|
-
binding.insertIndex,
|
|
4507
|
-
binding.sourceKind,
|
|
4508
|
-
binding.sourceId
|
|
4509
|
-
);
|
|
4510
|
-
}
|
|
4511
|
-
}
|
|
4773
|
+
return { lanes, buses };
|
|
4774
|
+
}
|
|
4775
|
+
function postMixerSync(ctx, lanes, buses, insertBaseResets, oneShotInsertParamOverrides) {
|
|
4512
4776
|
replayInsertParamOverrides(ctx, lanes, buses);
|
|
4513
4777
|
const trackStrips = Array.from(ctx.trackStripJson, ([trackId, sceneJson]) => ({
|
|
4514
4778
|
trackId,
|
|
@@ -4518,10 +4782,10 @@ function syncMixer(ctx, busesAlreadyApplied = false, forceInsertResets = []) {
|
|
|
4518
4782
|
busId,
|
|
4519
4783
|
sceneJson
|
|
4520
4784
|
}));
|
|
4521
|
-
const insertParamOverrides =
|
|
4522
|
-
ctx.insertParamOverrides.values(),
|
|
4523
|
-
flattenInsertParamOverride
|
|
4524
|
-
|
|
4785
|
+
const insertParamOverrides = [
|
|
4786
|
+
...Array.from(ctx.insertParamOverrides.values(), flattenInsertParamOverride),
|
|
4787
|
+
...oneShotInsertParamOverrides.map(flattenInsertParamOverride)
|
|
4788
|
+
];
|
|
4525
4789
|
ctx.postSync({
|
|
4526
4790
|
type: "syncMixer",
|
|
4527
4791
|
lanes,
|
|
@@ -4533,9 +4797,23 @@ function syncMixer(ctx, busesAlreadyApplied = false, forceInsertResets = []) {
|
|
|
4533
4797
|
busSidechains: Array.from(ctx.busSidechains.values()),
|
|
4534
4798
|
masterSidechains: Array.from(ctx.masterSidechains.values()),
|
|
4535
4799
|
...insertParamOverrides.length > 0 ? { insertParamOverrides } : {},
|
|
4536
|
-
...
|
|
4800
|
+
...insertBaseResets.length > 0 ? { insertBaseResets } : {}
|
|
4537
4801
|
});
|
|
4538
4802
|
}
|
|
4803
|
+
function syncMixerDraft(ctx, draft, busesAlreadyApplied = false, insertBaseResets = [], oneShotInsertParamOverrides = []) {
|
|
4804
|
+
const { lanes, buses } = applyMixerRouting(ctx, draft, busesAlreadyApplied);
|
|
4805
|
+
commitMixerRouting(ctx, draft);
|
|
4806
|
+
postMixerSync(ctx, lanes, buses, insertBaseResets, oneShotInsertParamOverrides);
|
|
4807
|
+
}
|
|
4808
|
+
function syncMixer(ctx, busesAlreadyApplied = false, insertBaseResets = [], oneShotInsertParamOverrides = []) {
|
|
4809
|
+
syncMixerDraft(
|
|
4810
|
+
ctx,
|
|
4811
|
+
cloneMixerRouting(ctx),
|
|
4812
|
+
busesAlreadyApplied,
|
|
4813
|
+
insertBaseResets,
|
|
4814
|
+
oneShotInsertParamOverrides
|
|
4815
|
+
);
|
|
4816
|
+
}
|
|
4539
4817
|
function replayInsertParamOverrides(ctx, lanes = mixerLanes(ctx), buses = ctx.buses) {
|
|
4540
4818
|
const activeTrackIds = new Set(lanes.map((lane) => lane.trackId));
|
|
4541
4819
|
const activeBusIds = new Set(buses.map((bus) => bus.busId));
|
|
@@ -4573,34 +4851,59 @@ function replayInsertParamOverrides(ctx, lanes = mixerLanes(ctx), buses = ctx.bu
|
|
|
4573
4851
|
}
|
|
4574
4852
|
}
|
|
4575
4853
|
function setTrackLanes(ctx, lanes) {
|
|
4576
|
-
const
|
|
4854
|
+
const draft = cloneMixerRouting(ctx);
|
|
4855
|
+
const { entries, ids } = normalizeTrackLanes(draft.trackLaneIds, lanes);
|
|
4577
4856
|
for (const entry of entries) {
|
|
4578
4857
|
if (entry.sends) {
|
|
4579
|
-
|
|
4858
|
+
draft.trackSends.set(
|
|
4580
4859
|
entry.trackId,
|
|
4581
4860
|
entry.sends.map((send) => ({ ...send }))
|
|
4582
4861
|
);
|
|
4583
4862
|
}
|
|
4584
4863
|
if (entry.outputBusId !== void 0) {
|
|
4585
4864
|
if (entry.outputBusId === 0) {
|
|
4586
|
-
|
|
4865
|
+
draft.trackOutputBus.delete(entry.trackId);
|
|
4587
4866
|
} else {
|
|
4588
|
-
|
|
4867
|
+
draft.trackOutputBus.set(entry.trackId, entry.outputBusId);
|
|
4589
4868
|
}
|
|
4590
4869
|
}
|
|
4870
|
+
if (entry.sourceChannelLayout !== void 0) {
|
|
4871
|
+
draft.trackSourceChannelLayout.set(entry.trackId, entry.sourceChannelLayout);
|
|
4872
|
+
}
|
|
4873
|
+
}
|
|
4874
|
+
draft.trackLaneIds = ids;
|
|
4875
|
+
syncMixerDraft(ctx, draft, true);
|
|
4876
|
+
}
|
|
4877
|
+
function ensureTrackLaneInDraft(draft, target) {
|
|
4878
|
+
const trackId = resolveTargetId(target);
|
|
4879
|
+
if (!Number.isInteger(trackId) || trackId <= 0) {
|
|
4880
|
+
throw new RangeError(`Invalid track id for mixer lane: ${String(target)}`);
|
|
4881
|
+
}
|
|
4882
|
+
const existing = draft.trackLaneIds.indexOf(trackId);
|
|
4883
|
+
if (existing >= 0) {
|
|
4884
|
+
return existing;
|
|
4885
|
+
}
|
|
4886
|
+
draft.trackLaneIds.push(trackId);
|
|
4887
|
+
return draft.trackLaneIds.length - 1;
|
|
4888
|
+
}
|
|
4889
|
+
function ensureTrackLane(ctx, target) {
|
|
4890
|
+
const draft = cloneMixerRouting(ctx);
|
|
4891
|
+
const laneIndex = ensureTrackLaneInDraft(draft, target);
|
|
4892
|
+
if (draft.trackLaneIds.length !== ctx.trackLaneIds.length) {
|
|
4893
|
+
syncMixerDraft(ctx, draft, true);
|
|
4591
4894
|
}
|
|
4592
|
-
|
|
4593
|
-
ctx.syncMixer();
|
|
4895
|
+
return laneIndex;
|
|
4594
4896
|
}
|
|
4595
4897
|
function setTrackOutputBus(ctx, target, busId) {
|
|
4596
|
-
const
|
|
4597
|
-
const
|
|
4898
|
+
const draft = cloneMixerRouting(ctx);
|
|
4899
|
+
const laneIndex = ensureTrackLaneInDraft(draft, target);
|
|
4900
|
+
const trackId = draft.trackLaneIds[laneIndex];
|
|
4598
4901
|
if (busId === 0) {
|
|
4599
|
-
|
|
4902
|
+
draft.trackOutputBus.delete(trackId);
|
|
4600
4903
|
} else {
|
|
4601
|
-
|
|
4904
|
+
draft.trackOutputBus.set(trackId, busId);
|
|
4602
4905
|
}
|
|
4603
|
-
ctx
|
|
4906
|
+
syncMixerDraft(ctx, draft, true);
|
|
4604
4907
|
}
|
|
4605
4908
|
function setLaneSidechain(ctx, target, insertIndex, sourceTarget) {
|
|
4606
4909
|
const laneIndex = ctx.ensureTrackLane(target);
|
|
@@ -4669,13 +4972,14 @@ function ensureSidechainSource(ctx, sourceKind, sourceId) {
|
|
|
4669
4972
|
}
|
|
4670
4973
|
}
|
|
4671
4974
|
function setSends(ctx, target, sends) {
|
|
4672
|
-
const
|
|
4673
|
-
const
|
|
4674
|
-
|
|
4975
|
+
const draft = cloneMixerRouting(ctx);
|
|
4976
|
+
const laneIndex = ensureTrackLaneInDraft(draft, target);
|
|
4977
|
+
const trackId = draft.trackLaneIds[laneIndex];
|
|
4978
|
+
draft.trackSends.set(
|
|
4675
4979
|
trackId,
|
|
4676
4980
|
sends.map((send) => ({ ...send }))
|
|
4677
4981
|
);
|
|
4678
|
-
ctx
|
|
4982
|
+
syncMixerDraft(ctx, draft, true);
|
|
4679
4983
|
}
|
|
4680
4984
|
function setTrackBuses(ctx, buses) {
|
|
4681
4985
|
ctx.offlineEngine.setTrackBuses(buses);
|
|
@@ -4709,18 +5013,45 @@ function setBusGain(ctx, busId, db) {
|
|
|
4709
5013
|
ctx.buses[busIndex] = { ...ctx.buses[busIndex], busId, gainDb: db };
|
|
4710
5014
|
return ctx.sendSmoothedParam(engineMixerBusTarget(busIndex, ENGINE_MIXER_PARAM_FADER_DB), db);
|
|
4711
5015
|
}
|
|
5016
|
+
function replaceStripScene(ctx, target, previousJson, sceneJson) {
|
|
5017
|
+
const chainChanged = previousJson !== void 0 && decodedInsertSignature(previousJson, target) !== decodedInsertSignature(sceneJson, target);
|
|
5018
|
+
const hasOverrides = hasInsertParamOverrides(ctx.insertParamOverrides, target);
|
|
5019
|
+
applyFullStripJson(ctx.offlineEngine, target, sceneJson);
|
|
5020
|
+
if (!chainChanged && !hasOverrides) {
|
|
5021
|
+
return { insertBaseResets: [], constructionOverrides: [] };
|
|
5022
|
+
}
|
|
5023
|
+
const constructionOverrides = chainChanged ? [] : constructionInsertOverrides(ctx.offlineEngine, target, ctx.insertParamOverrides);
|
|
5024
|
+
ctx.clearInsertAutomationLanes(target);
|
|
5025
|
+
clearInsertParameterBases(ctx.offlineEngine, target);
|
|
5026
|
+
applyConstructionInsertOverrides(ctx.offlineEngine, constructionOverrides);
|
|
5027
|
+
clearInsertParamOverrides(ctx.insertParamOverrides, target);
|
|
5028
|
+
return { insertBaseResets: [target], constructionOverrides };
|
|
5029
|
+
}
|
|
4712
5030
|
function setBusStripJson(ctx, busId, sceneJson) {
|
|
4713
|
-
ctx.ensureBus(busId);
|
|
4714
5031
|
const target = { kind: "bus", busId };
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
ctx
|
|
4719
|
-
|
|
5032
|
+
decodedInsertSignature(sceneJson, target);
|
|
5033
|
+
ctx.ensureBus(busId);
|
|
5034
|
+
const { insertBaseResets, constructionOverrides } = replaceStripScene(
|
|
5035
|
+
ctx,
|
|
5036
|
+
target,
|
|
5037
|
+
ctx.busStripJson.get(busId),
|
|
5038
|
+
sceneJson
|
|
5039
|
+
);
|
|
4720
5040
|
pruneStripSidechains(ctx, target, sceneJson);
|
|
4721
5041
|
ctx.busStripJson.set(busId, sceneJson);
|
|
4722
|
-
|
|
4723
|
-
|
|
5042
|
+
ctx.syncMixer(insertBaseResets, constructionOverrides);
|
|
5043
|
+
}
|
|
5044
|
+
function setMasterStripJson(ctx, sceneJson) {
|
|
5045
|
+
const target = { kind: "master" };
|
|
5046
|
+
const { insertBaseResets, constructionOverrides } = replaceStripScene(
|
|
5047
|
+
ctx,
|
|
5048
|
+
target,
|
|
5049
|
+
ctx.getMasterStripJson(),
|
|
5050
|
+
sceneJson
|
|
5051
|
+
);
|
|
5052
|
+
pruneStripSidechains(ctx, target, sceneJson);
|
|
5053
|
+
ctx.cacheMasterStripJson(sceneJson);
|
|
5054
|
+
ctx.syncMixer(insertBaseResets, constructionOverrides);
|
|
4724
5055
|
}
|
|
4725
5056
|
|
|
4726
5057
|
// src/worklet/engine-node.ts
|
|
@@ -4739,7 +5070,7 @@ function isTrackMonitorMode(value) {
|
|
|
4739
5070
|
}
|
|
4740
5071
|
function isValidCommandRecord(command) {
|
|
4741
5072
|
const type = Number(command.type);
|
|
4742
|
-
if (!Number.isSafeInteger(type) || type < 0 /* SetParam */ || type > 17 /* SeekMarker */ && type !== 26 /* SetTrackMonitorMode */) {
|
|
5073
|
+
if (!Number.isSafeInteger(type) || type < 0 /* SetParam */ || type > 17 /* SeekMarker */ && type !== 26 /* SetTrackMonitorMode */ && type !== 28 /* ResetMasterLoudnessMeter */) {
|
|
4743
5074
|
return false;
|
|
4744
5075
|
}
|
|
4745
5076
|
return (
|
|
@@ -4824,6 +5155,8 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
4824
5155
|
this.emitTelemetry(event.data);
|
|
4825
5156
|
} else if (isMeterSnapshot(event.data)) {
|
|
4826
5157
|
this.emitMeter(event.data);
|
|
5158
|
+
} else if (isScopeSnapshot(event.data)) {
|
|
5159
|
+
this.emitScope(event.data);
|
|
4827
5160
|
} else if (isExternalMidiBatchMessage(event.data)) {
|
|
4828
5161
|
this.emitMidiOut(event.data.events);
|
|
4829
5162
|
} else if (isClipPageRequestMessage(event.data)) {
|
|
@@ -4876,6 +5209,12 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
4876
5209
|
"SharedArrayBuffer mode requested but SharedArrayBuffer/Atomics are unavailable."
|
|
4877
5210
|
);
|
|
4878
5211
|
}
|
|
5212
|
+
const meterIntervalFrames = requireIntegerOption(
|
|
5213
|
+
options.meterIntervalFrames,
|
|
5214
|
+
2048,
|
|
5215
|
+
"meterIntervalFrames",
|
|
5216
|
+
0
|
|
5217
|
+
);
|
|
4879
5218
|
const commandRingCapacity = requireIntegerOption(
|
|
4880
5219
|
options.commandRingCapacity,
|
|
4881
5220
|
128,
|
|
@@ -4903,7 +5242,7 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
4903
5242
|
"scopeRingCapacity",
|
|
4904
5243
|
1
|
|
4905
5244
|
);
|
|
4906
|
-
const scopeBands =
|
|
5245
|
+
const scopeBands = resolveScopeBandCount(options.scopeBands);
|
|
4907
5246
|
const clipPageRequestRingCapacity = requireIntegerOption(
|
|
4908
5247
|
options.clipPageRequestRingCapacity,
|
|
4909
5248
|
128,
|
|
@@ -4934,6 +5273,7 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
4934
5273
|
sampleRate: options.sampleRate ?? context.sampleRate,
|
|
4935
5274
|
blockSize,
|
|
4936
5275
|
channelCount,
|
|
5276
|
+
meterIntervalFrames,
|
|
4937
5277
|
cueOutput,
|
|
4938
5278
|
commandSharedBuffer: commandRing?.sharedBuffer,
|
|
4939
5279
|
commandRingCapacity: commandRing?.capacity,
|
|
@@ -4943,8 +5283,8 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
4943
5283
|
meterRingCapacity: meterRing?.capacity,
|
|
4944
5284
|
scopeSharedBuffer: scopeRing?.sharedBuffer,
|
|
4945
5285
|
scopeRingCapacity: scopeRing?.capacity,
|
|
4946
|
-
scopeBands: scopeRing?.bands,
|
|
4947
|
-
scopeIntervalFrames:
|
|
5286
|
+
scopeBands: scopeIntervalFrames > 0 ? scopeRing?.bands ?? scopeBands : void 0,
|
|
5287
|
+
scopeIntervalFrames: scopeIntervalFrames > 0 ? scopeIntervalFrames : void 0,
|
|
4948
5288
|
clipPageRequestSharedBuffer: clipPageRequestRing?.sharedBuffer,
|
|
4949
5289
|
clipPageRequestRingCapacity: clipPageRequestRing?.capacity,
|
|
4950
5290
|
externalMidiSharedBuffer: externalMidiRing?.sharedBuffer,
|
|
@@ -4993,6 +5333,10 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
4993
5333
|
play(sampleTime = -1) {
|
|
4994
5334
|
return this.sendCommand({ type: 2 /* TransportPlay */, sampleTime });
|
|
4995
5335
|
}
|
|
5336
|
+
/** Queues a reset of the master's integrated-loudness accumulator. */
|
|
5337
|
+
resetMasterLoudnessMeter(sampleTime = -1) {
|
|
5338
|
+
return this.sendCommand({ type: 28 /* ResetMasterLoudnessMeter */, sampleTime });
|
|
5339
|
+
}
|
|
4996
5340
|
stop(sampleTime = -1) {
|
|
4997
5341
|
return this.sendCommand({ type: 3 /* TransportStop */, sampleTime });
|
|
4998
5342
|
}
|
|
@@ -5397,11 +5741,9 @@ function setInsertParamByName(ctx, target, insertIndex, paramName, value, applyN
|
|
|
5397
5741
|
}
|
|
5398
5742
|
function setTrackStripJson(ctx, trackId, sceneJson, trackStripJson) {
|
|
5399
5743
|
const target = { kind: "track", trackId };
|
|
5400
|
-
const
|
|
5401
|
-
applyFullStripJson(ctx.offlineEngine, target, sceneJson, resetInserts);
|
|
5402
|
-
clearInsertParamOverrides(ctx.insertParamOverrides, target);
|
|
5744
|
+
const result = replaceStripScene(ctx, target, trackStripJson.get(trackId), sceneJson);
|
|
5403
5745
|
trackStripJson.set(trackId, sceneJson);
|
|
5404
|
-
return
|
|
5746
|
+
return result;
|
|
5405
5747
|
}
|
|
5406
5748
|
function setTrackStripEqBand(ctx, target, bandIndex, band) {
|
|
5407
5749
|
const trackId = trackIdFor(ctx, target);
|
|
@@ -5774,6 +6116,7 @@ var SonareEngine = class _SonareEngine {
|
|
|
5774
6116
|
this.trackLaneIds = [];
|
|
5775
6117
|
this.trackSends = /* @__PURE__ */ new Map();
|
|
5776
6118
|
this.trackOutputBus = /* @__PURE__ */ new Map();
|
|
6119
|
+
this.trackSourceChannelLayout = /* @__PURE__ */ new Map();
|
|
5777
6120
|
this.laneSidechains = /* @__PURE__ */ new Map();
|
|
5778
6121
|
this.busSidechains = /* @__PURE__ */ new Map();
|
|
5779
6122
|
this.masterSidechains = /* @__PURE__ */ new Map();
|
|
@@ -5875,6 +6218,11 @@ var SonareEngine = class _SonareEngine {
|
|
|
5875
6218
|
setTimeSignatureSegments(segments) {
|
|
5876
6219
|
setTimeSignatureSegments(this.tempoContext, segments);
|
|
5877
6220
|
}
|
|
6221
|
+
/**
|
|
6222
|
+
* A loop wrap, seek or stop sends note-offs plus CC64=0, CC121, CC123 and a
|
|
6223
|
+
* centred pitch bend on every channel played since the last reset, so
|
|
6224
|
+
* controller values set before a loop region are not restored at the wrap.
|
|
6225
|
+
*/
|
|
5878
6226
|
setLoop(startPpq, endPpq, enabled = true) {
|
|
5879
6227
|
return setLoop(this.tempoContext, startPpq, endPpq, enabled);
|
|
5880
6228
|
}
|
|
@@ -5933,6 +6281,15 @@ var SonareEngine = class _SonareEngine {
|
|
|
5933
6281
|
* mixer lane first (like automationParamId) so the offline engine resolves the
|
|
5934
6282
|
* same strip selector the realtime engine uses.
|
|
5935
6283
|
*
|
|
6284
|
+
* The returned id uses the track's current positional lane selector. When
|
|
6285
|
+
* setTrackLanes successfully changes lane order or membership, the engine
|
|
6286
|
+
* remaps already queued and published track automation by track id, but it
|
|
6287
|
+
* cannot update a numeric id retained by the caller. Re-resolve every track
|
|
6288
|
+
* insert id after such a topology change before passing it to
|
|
6289
|
+
* setAutomationLane. Use setTrackStripInsertParamByName when the operation
|
|
6290
|
+
* needs a stable track identity. Master and bus insert ids are separate and
|
|
6291
|
+
* are not invalidated by track-lane changes.
|
|
6292
|
+
*
|
|
5936
6293
|
* @param target Track id (declares a mixer lane on first use).
|
|
5937
6294
|
* @param insertIndex Index into the strip's combined insert sequence.
|
|
5938
6295
|
* @param paramName Processor JSON-key parameter name.
|
|
@@ -6046,14 +6403,23 @@ var SonareEngine = class _SonareEngine {
|
|
|
6046
6403
|
}
|
|
6047
6404
|
return sent;
|
|
6048
6405
|
}
|
|
6406
|
+
/** Resets the master's integrated loudness accumulator in both engine mirrors. */
|
|
6407
|
+
resetMasterLoudnessMeter(renderFrame = -1) {
|
|
6408
|
+
this.offlineEngine.resetMasterLoudnessMeter(renderFrame);
|
|
6409
|
+
return this.sendMirroredCommand({
|
|
6410
|
+
type: 28 /* ResetMasterLoudnessMeter */,
|
|
6411
|
+
sampleTime: renderFrame
|
|
6412
|
+
});
|
|
6413
|
+
}
|
|
6049
6414
|
/**
|
|
6050
6415
|
* Declares the mixer track lanes in an explicit order.
|
|
6051
6416
|
*
|
|
6052
|
-
*
|
|
6053
|
-
*
|
|
6054
|
-
*
|
|
6055
|
-
*
|
|
6056
|
-
* track's send list; entries without `sends` leave
|
|
6417
|
+
* A successful call may reorder existing track ids, remove track ids, or add
|
|
6418
|
+
* new ones. Existing queued and published track automation follows the track
|
|
6419
|
+
* id, while numeric track-insert automation ids retained by the caller do
|
|
6420
|
+
* not; re-resolve those ids after every topology change. Entries carrying
|
|
6421
|
+
* `sends` replace that track's send list; entries without `sends` leave
|
|
6422
|
+
* existing sends untouched.
|
|
6057
6423
|
*
|
|
6058
6424
|
* @param lanes Track ids or lane descriptors in the desired lane order.
|
|
6059
6425
|
*/
|
|
@@ -6099,19 +6465,17 @@ var SonareEngine = class _SonareEngine {
|
|
|
6099
6465
|
return setBusGain(this.mixerContext, busId, db);
|
|
6100
6466
|
}
|
|
6101
6467
|
setTrackStripJson(target, sceneJson) {
|
|
6468
|
+
decodedInsertSignature(sceneJson, { kind: "track", trackId: 0 });
|
|
6102
6469
|
const laneIndex = this.ensureTrackLane(target);
|
|
6103
6470
|
const trackId = this.trackLaneIds[laneIndex];
|
|
6104
|
-
const {
|
|
6471
|
+
const { insertBaseResets, constructionOverrides } = setTrackStripJson(
|
|
6105
6472
|
this.stripContext,
|
|
6106
6473
|
trackId,
|
|
6107
6474
|
sceneJson,
|
|
6108
6475
|
this.trackStripJson
|
|
6109
6476
|
);
|
|
6110
|
-
if (resetInserts) {
|
|
6111
|
-
this.clearInsertAutomationLanes({ kind: "track", trackId });
|
|
6112
|
-
}
|
|
6113
6477
|
pruneStripSidechains(this.mixerContext, { kind: "track", trackId }, sceneJson);
|
|
6114
|
-
this.syncMixer(
|
|
6478
|
+
this.syncMixer(insertBaseResets, constructionOverrides);
|
|
6115
6479
|
}
|
|
6116
6480
|
setTrackStripEqBand(target, bandIndex, band) {
|
|
6117
6481
|
setTrackStripEqBand(this.stripContext, target, bandIndex, band);
|
|
@@ -6168,16 +6532,7 @@ var SonareEngine = class _SonareEngine {
|
|
|
6168
6532
|
setBusStripJson(this.mixerContext, busId, sceneJson);
|
|
6169
6533
|
}
|
|
6170
6534
|
setMasterStripJson(sceneJson) {
|
|
6171
|
-
|
|
6172
|
-
const resetInserts = this.masterStripJson !== void 0 && this.masterStripJson !== sceneJson || hasInsertParamOverrides(this.insertParamOverrides, target);
|
|
6173
|
-
applyFullStripJson(this.offlineEngine, target, sceneJson, resetInserts);
|
|
6174
|
-
if (resetInserts) {
|
|
6175
|
-
this.clearInsertAutomationLanes(target);
|
|
6176
|
-
}
|
|
6177
|
-
pruneStripSidechains(this.mixerContext, target, sceneJson);
|
|
6178
|
-
clearInsertParamOverrides(this.insertParamOverrides, target);
|
|
6179
|
-
this.masterStripJson = sceneJson;
|
|
6180
|
-
this.syncMixer(resetInserts ? [target] : []);
|
|
6535
|
+
setMasterStripJson(this.mixerContext, sceneJson);
|
|
6181
6536
|
}
|
|
6182
6537
|
setMasterStripEqBand(bandIndex, band) {
|
|
6183
6538
|
setMasterStripEqBand(this.stripContext, bandIndex, band);
|
|
@@ -6380,7 +6735,10 @@ var SonareEngine = class _SonareEngine {
|
|
|
6380
6735
|
/**
|
|
6381
6736
|
* Route a track's MIDI to the external output (drained via {@link onMidiOut})
|
|
6382
6737
|
* instead of an internal instrument, so the track plays an external device.
|
|
6383
|
-
* Pass `external=false` to restore internal-synth playback.
|
|
6738
|
+
* Pass `external=false` to restore internal-synth playback. The change takes
|
|
6739
|
+
* effect at the next processed block; switching a destination's route first
|
|
6740
|
+
* releases its notes and resets its controllers through the old route, and
|
|
6741
|
+
* drops its pending MIDI-FX events.
|
|
6384
6742
|
*/
|
|
6385
6743
|
setMidiDestinationExternal(trackId, external) {
|
|
6386
6744
|
setMidiDestinationExternal(this.stripContext, trackId, external);
|
|
@@ -6724,8 +7082,8 @@ var SonareEngine = class _SonareEngine {
|
|
|
6724
7082
|
mixerLanes() {
|
|
6725
7083
|
return mixerLanes(this.mixerContext);
|
|
6726
7084
|
}
|
|
6727
|
-
syncMixer(
|
|
6728
|
-
syncMixer(this.mixerContext, false,
|
|
7085
|
+
syncMixer(insertBaseResets = [], oneShotInsertParamOverrides = []) {
|
|
7086
|
+
syncMixer(this.mixerContext, false, insertBaseResets, oneShotInsertParamOverrides);
|
|
6729
7087
|
}
|
|
6730
7088
|
insertAutomationTargetKey(target) {
|
|
6731
7089
|
return target.kind === "track" ? `track:${target.trackId}` : target.kind === "bus" ? `bus:${target.busId}` : "master";
|
|
@@ -6803,6 +7161,7 @@ var SonareEngine = class _SonareEngine {
|
|
|
6803
7161
|
trackLaneIds: this.trackLaneIds,
|
|
6804
7162
|
trackSends: this.trackSends,
|
|
6805
7163
|
trackOutputBus: this.trackOutputBus,
|
|
7164
|
+
trackSourceChannelLayout: this.trackSourceChannelLayout,
|
|
6806
7165
|
laneSidechains: this.laneSidechains,
|
|
6807
7166
|
busSidechains: this.busSidechains,
|
|
6808
7167
|
masterSidechains: this.masterSidechains,
|
|
@@ -6815,7 +7174,7 @@ var SonareEngine = class _SonareEngine {
|
|
|
6815
7174
|
ensureTrackLane: (target) => this.ensureTrackLane(target),
|
|
6816
7175
|
ensureBus: (busId) => this.ensureBus(busId),
|
|
6817
7176
|
mixerLanes: () => this.mixerLanes(),
|
|
6818
|
-
syncMixer: (
|
|
7177
|
+
syncMixer: (insertBaseResets, oneShotInsertParamOverrides) => this.syncMixer(insertBaseResets, oneShotInsertParamOverrides),
|
|
6819
7178
|
clearInsertAutomationLanes: (target, forgetResolvedIds) => this.clearInsertAutomationLanes(target, forgetResolvedIds),
|
|
6820
7179
|
sendSmoothedParam: (paramId, value) => this.sendSmoothedParam(paramId, value),
|
|
6821
7180
|
getMasterStripJson: () => this.masterStripJson,
|
|
@@ -6837,7 +7196,8 @@ var SonareEngine = class _SonareEngine {
|
|
|
6837
7196
|
resolveTargetId: (target) => this.resolveTargetId(target),
|
|
6838
7197
|
readStripJson: (target) => cachedStripJson(this.mixerContext, target),
|
|
6839
7198
|
writeStripJson: (target, sceneJson) => cacheStripJson(this.mixerContext, target, sceneJson),
|
|
6840
|
-
insertParamOverrides: this.insertParamOverrides
|
|
7199
|
+
insertParamOverrides: this.insertParamOverrides,
|
|
7200
|
+
clearInsertAutomationLanes: (target) => this.clearInsertAutomationLanes(target)
|
|
6841
7201
|
};
|
|
6842
7202
|
}
|
|
6843
7203
|
// Collaborator surface handed to the automation-lane free functions so they
|
|
@@ -6977,17 +7337,7 @@ var SonareEngine = class _SonareEngine {
|
|
|
6977
7337
|
return resolveTargetId(target);
|
|
6978
7338
|
}
|
|
6979
7339
|
ensureTrackLane(target) {
|
|
6980
|
-
|
|
6981
|
-
if (!Number.isInteger(trackId) || trackId <= 0) {
|
|
6982
|
-
throw new RangeError(`Invalid track id for mixer lane: ${String(target)}`);
|
|
6983
|
-
}
|
|
6984
|
-
const existing = this.trackLaneIds.indexOf(trackId);
|
|
6985
|
-
if (existing >= 0) {
|
|
6986
|
-
return existing;
|
|
6987
|
-
}
|
|
6988
|
-
this.trackLaneIds.push(trackId);
|
|
6989
|
-
this.syncMixer();
|
|
6990
|
-
return this.trackLaneIds.length - 1;
|
|
7340
|
+
return ensureTrackLane(this.mixerContext, target);
|
|
6991
7341
|
}
|
|
6992
7342
|
ensureBus(busId) {
|
|
6993
7343
|
if (!Number.isInteger(busId) || busId <= 0) {
|
|
@@ -7099,6 +7449,14 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
7099
7449
|
options.scopeRingCapacity,
|
|
7100
7450
|
options.scopeBands
|
|
7101
7451
|
) : void 0;
|
|
7452
|
+
this.scopeIntervalFrames = requireIntegerOption(
|
|
7453
|
+
options.scopeIntervalFrames,
|
|
7454
|
+
this.scopeRing ? this.blockSize : 0,
|
|
7455
|
+
"scopeIntervalFrames",
|
|
7456
|
+
0
|
|
7457
|
+
);
|
|
7458
|
+
this.scopeBands = resolveScopeBandCount(options.scopeBands);
|
|
7459
|
+
this.scopeEnabled = this.scopeIntervalFrames > 0 && (this.scopeRing !== void 0 || typeof this.transport?.postMessage === "function");
|
|
7102
7460
|
this.clipPageRequestRing = options.clipPageRequestSharedBuffer ? clipPageRequestRingFromSharedBuffer(
|
|
7103
7461
|
options.clipPageRequestSharedBuffer,
|
|
7104
7462
|
options.clipPageRequestRingCapacity
|
|
@@ -7130,14 +7488,11 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
7130
7488
|
this.monitorBuffers[ch] = this.engine.getMonitorChannelBuffer(ch, this.blockSize);
|
|
7131
7489
|
}
|
|
7132
7490
|
}
|
|
7133
|
-
if (this.
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
this.
|
|
7137
|
-
"scopeIntervalFrames",
|
|
7138
|
-
0
|
|
7491
|
+
if (this.scopeEnabled) {
|
|
7492
|
+
this.engine.configureScopeTelemetry(
|
|
7493
|
+
this.scopeIntervalFrames,
|
|
7494
|
+
Math.min(this.scopeRing?.bands ?? this.scopeBands, SONARE_SCOPE_MAX_BANDS)
|
|
7139
7495
|
);
|
|
7140
|
-
this.engine.configureScopeTelemetry(interval, this.scopeRing.bands);
|
|
7141
7496
|
}
|
|
7142
7497
|
}
|
|
7143
7498
|
process(inputs, outputs) {
|
|
@@ -7398,37 +7753,32 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
7398
7753
|
this.drainCommands(Math.min(this.commandRing.capacity, Math.max(0, write - read)));
|
|
7399
7754
|
}
|
|
7400
7755
|
this.engine.applyCommandsDueNowPreservingFuture();
|
|
7401
|
-
this.engine.settleInsertParameters();
|
|
7402
7756
|
if (message.buses) {
|
|
7403
7757
|
this.engine.setTrackBuses(message.buses);
|
|
7404
7758
|
}
|
|
7405
7759
|
this.engine.setTrackLanes(message.lanes);
|
|
7406
|
-
for (const
|
|
7407
|
-
|
|
7760
|
+
for (const strip of message.trackStrips ?? []) {
|
|
7761
|
+
this.engine.setTrackStripJson(strip.trackId, strip.sceneJson);
|
|
7762
|
+
}
|
|
7763
|
+
for (const strip of message.busStrips ?? []) {
|
|
7764
|
+
this.engine.setBusStripJson(strip.busId, strip.sceneJson);
|
|
7765
|
+
}
|
|
7766
|
+
if (message.masterStripJson) {
|
|
7767
|
+
this.engine.setMasterStripJson(message.masterStripJson);
|
|
7768
|
+
}
|
|
7769
|
+
for (const target of message.insertBaseResets ?? []) {
|
|
7408
7770
|
switch (target.kind) {
|
|
7409
7771
|
case "track":
|
|
7410
7772
|
this.engine.clearTrackInsertParameterBases(target.trackId);
|
|
7411
|
-
this.engine.setTrackStripJson(target.trackId, emptyJson);
|
|
7412
7773
|
break;
|
|
7413
7774
|
case "bus":
|
|
7414
7775
|
this.engine.clearBusInsertParameterBases(target.busId);
|
|
7415
|
-
this.engine.setBusStripJson(target.busId, emptyJson);
|
|
7416
7776
|
break;
|
|
7417
7777
|
case "master":
|
|
7418
7778
|
this.engine.clearMasterInsertParameterBases();
|
|
7419
|
-
this.engine.setMasterStripJson(emptyJson);
|
|
7420
7779
|
break;
|
|
7421
7780
|
}
|
|
7422
7781
|
}
|
|
7423
|
-
for (const strip of message.trackStrips ?? []) {
|
|
7424
|
-
this.engine.setTrackStripJson(strip.trackId, strip.sceneJson);
|
|
7425
|
-
}
|
|
7426
|
-
for (const strip of message.busStrips ?? []) {
|
|
7427
|
-
this.engine.setBusStripJson(strip.busId, strip.sceneJson);
|
|
7428
|
-
}
|
|
7429
|
-
if (message.masterStripJson) {
|
|
7430
|
-
this.engine.setMasterStripJson(message.masterStripJson);
|
|
7431
|
-
}
|
|
7432
7782
|
for (const binding of message.laneSidechains ?? []) {
|
|
7433
7783
|
this.engine.setLaneSidechain(binding.trackId, binding.insertIndex, binding.sourceTrackId);
|
|
7434
7784
|
}
|
|
@@ -7924,6 +8274,9 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
7924
8274
|
this.engine.setTrackMonitorMode(laneIndex, mode, sampleTime);
|
|
7925
8275
|
break;
|
|
7926
8276
|
}
|
|
8277
|
+
case 28 /* ResetMasterLoudnessMeter */:
|
|
8278
|
+
this.engine.resetMasterLoudnessMeter(sampleTime);
|
|
8279
|
+
break;
|
|
7927
8280
|
default:
|
|
7928
8281
|
this.publishTelemetryRecord({
|
|
7929
8282
|
type: 1 /* Error */,
|
|
@@ -8026,6 +8379,8 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
8026
8379
|
for (let field = 0; field < 11; field++) {
|
|
8027
8380
|
ring.records[offset + 3 + field] = this.engine.meterScratchValue(field);
|
|
8028
8381
|
}
|
|
8382
|
+
ring.records[offset + 14] = this.engine.meterScratchInputPeakDbL();
|
|
8383
|
+
ring.records[offset + 15] = this.engine.meterScratchInputPeakDbR();
|
|
8029
8384
|
Atomics.store(ring.header, 0, writeIndex + 1);
|
|
8030
8385
|
}
|
|
8031
8386
|
// A snapshot-object ring writer used to live here as well. It was
|
|
@@ -8041,17 +8396,53 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
8041
8396
|
// silent overrun via firstReadable = max(readIndex, writeIndex - capacity),
|
|
8042
8397
|
// so header slot 3 is left at its initial 0.
|
|
8043
8398
|
// Drains the engine's scope producer (FFT spectrum + goniometer points) into
|
|
8044
|
-
// the lock-free SAB scope ring
|
|
8045
|
-
//
|
|
8399
|
+
// the lock-free SAB scope ring or the bounded postMessage fallback. The SAB
|
|
8400
|
+
// path remains allocation-free; postMessage materialises only records that
|
|
8401
|
+
// are ready to publish.
|
|
8046
8402
|
publishScope() {
|
|
8047
|
-
|
|
8048
|
-
if (!ring) {
|
|
8403
|
+
if (!this.scopeEnabled) {
|
|
8049
8404
|
return;
|
|
8050
8405
|
}
|
|
8406
|
+
const ring = this.scopeRing;
|
|
8407
|
+
const transport = this.transport;
|
|
8051
8408
|
for (let count = 0; count < 64 && this.engine.popScopeTelemetryToScratch(); count++) {
|
|
8052
|
-
|
|
8409
|
+
if (ring) {
|
|
8410
|
+
this.writeScopeScratch(ring);
|
|
8411
|
+
} else {
|
|
8412
|
+
this.postScopeScratch(transport);
|
|
8413
|
+
}
|
|
8053
8414
|
}
|
|
8054
8415
|
}
|
|
8416
|
+
postScopeScratch(transport) {
|
|
8417
|
+
if (!transport?.postMessage) {
|
|
8418
|
+
return;
|
|
8419
|
+
}
|
|
8420
|
+
const bandCount = Math.min(
|
|
8421
|
+
SONARE_SCOPE_MAX_BANDS,
|
|
8422
|
+
Math.max(0, Math.trunc(Number(this.engine.scopeScratchBandCount())))
|
|
8423
|
+
);
|
|
8424
|
+
const pointCount = Math.min(
|
|
8425
|
+
SONARE_SCOPE_MAX_POINTS,
|
|
8426
|
+
Math.max(0, Math.trunc(Number(this.engine.scopeScratchPointCount())))
|
|
8427
|
+
);
|
|
8428
|
+
const bands = new Float32Array(bandCount);
|
|
8429
|
+
for (let i = 0; i < bandCount; i++) {
|
|
8430
|
+
bands[i] = this.engine.scopeScratchBand(i);
|
|
8431
|
+
}
|
|
8432
|
+
const points = new Float32Array(pointCount * 2);
|
|
8433
|
+
for (let i = 0; i < pointCount; i++) {
|
|
8434
|
+
points[2 * i] = this.engine.scopeScratchPointLeft(i);
|
|
8435
|
+
points[2 * i + 1] = this.engine.scopeScratchPointRight(i);
|
|
8436
|
+
}
|
|
8437
|
+
const scope = {
|
|
8438
|
+
type: "scope",
|
|
8439
|
+
targetId: this.engine.scopeScratchTargetId(),
|
|
8440
|
+
frame: Number(this.engine.scopeScratchRenderFrame()),
|
|
8441
|
+
bands,
|
|
8442
|
+
points
|
|
8443
|
+
};
|
|
8444
|
+
transport.postMessage(scope, [bands.buffer, points.buffer]);
|
|
8445
|
+
}
|
|
8055
8446
|
writeScopeScratch(ring) {
|
|
8056
8447
|
const writeIndex = Atomics.load(ring.header, 0);
|
|
8057
8448
|
const base = writeIndex % ring.capacity * ring.recordFloats;
|
|
@@ -8352,8 +8743,8 @@ var SonareWorkletProcessor = class {
|
|
|
8352
8743
|
*
|
|
8353
8744
|
* `targetId` is always the master and the four LUFS / gain-reduction fields
|
|
8354
8745
|
* are always unavailable here — the mixer worklet does not run the
|
|
8355
|
-
* K-weighting filters
|
|
8356
|
-
* set once rather than per interval.
|
|
8746
|
+
* K-weighting filters or the engine's pre-trim input tap — so finite floor
|
|
8747
|
+
* values are set once rather than per interval.
|
|
8357
8748
|
*/
|
|
8358
8749
|
this.meterScratch = {
|
|
8359
8750
|
type: "meter",
|
|
@@ -8369,7 +8760,9 @@ var SonareWorkletProcessor = class {
|
|
|
8369
8760
|
momentaryLufs: Number.NaN,
|
|
8370
8761
|
shortTermLufs: Number.NaN,
|
|
8371
8762
|
integratedLufs: Number.NaN,
|
|
8372
|
-
gainReductionDb: Number.NaN
|
|
8763
|
+
gainReductionDb: Number.NaN,
|
|
8764
|
+
inputPeakDbL: SONARE_FLOOR_DB,
|
|
8765
|
+
inputPeakDbR: SONARE_FLOOR_DB
|
|
8373
8766
|
};
|
|
8374
8767
|
if (!options.sceneJson) {
|
|
8375
8768
|
throw new Error("sceneJson is required.");
|
|
@@ -8532,7 +8925,9 @@ var SonareWorkletProcessor = class {
|
|
|
8532
8925
|
momentaryLufs: Number.NaN,
|
|
8533
8926
|
shortTermLufs: Number.NaN,
|
|
8534
8927
|
integratedLufs: Number.NaN,
|
|
8535
|
-
gainReductionDb: Number.NaN
|
|
8928
|
+
gainReductionDb: Number.NaN,
|
|
8929
|
+
inputPeakDbL: SONARE_FLOOR_DB,
|
|
8930
|
+
inputPeakDbR: SONARE_FLOOR_DB
|
|
8536
8931
|
};
|
|
8537
8932
|
if (this.transport?.onMeter) {
|
|
8538
8933
|
this.transport.onMeter(meter);
|
|
@@ -8561,6 +8956,8 @@ var SonareWorkletProcessor = class {
|
|
|
8561
8956
|
ring.records[offset + 11] = meter.shortTermLufs;
|
|
8562
8957
|
ring.records[offset + 12] = meter.integratedLufs;
|
|
8563
8958
|
ring.records[offset + 13] = meter.gainReductionDb;
|
|
8959
|
+
ring.records[offset + 14] = meter.inputPeakDbL;
|
|
8960
|
+
ring.records[offset + 15] = meter.inputPeakDbR;
|
|
8564
8961
|
Atomics.store(ring.header, 0, writeIndex + 1);
|
|
8565
8962
|
}
|
|
8566
8963
|
publishSpectrum(left, right) {
|
|
@@ -8613,7 +9010,7 @@ var SonareWorkletProcessor = class {
|
|
|
8613
9010
|
return;
|
|
8614
9011
|
}
|
|
8615
9012
|
const writeIndex = Atomics.load(ring.header, 0);
|
|
8616
|
-
const offset = writeIndex % ring.capacity *
|
|
9013
|
+
const offset = writeIndex % ring.capacity * SONARE_METER_RING_RECORD_FLOATS;
|
|
8617
9014
|
ring.records[offset] = encodeFrameLo(frame);
|
|
8618
9015
|
ring.records[offset + 1] = encodeFrameHi(frame);
|
|
8619
9016
|
ring.records[offset + 2] = bands.length;
|