@libraz/libsonare 1.8.0 → 1.8.2
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 +5 -5
- package/dist/_effects_common.d.ts +2 -1
- package/dist/_effects_common.d.ts.map +1 -1
- package/dist/analysis.js +3 -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 +11 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2098 -155
- package/dist/index.js.map +1 -1
- package/dist/instrument_types.d.ts +27 -3
- package/dist/instrument_types.d.ts.map +1 -1
- package/dist/mastering_core.d.ts +30 -3
- package/dist/mastering_core.d.ts.map +1 -1
- package/dist/mixer.d.ts +2 -2
- package/dist/mixer.d.ts.map +1 -1
- package/dist/project.d.ts +5 -4
- package/dist/project.d.ts.map +1 -1
- package/dist/project_class.d.ts +57 -3
- package/dist/project_class.d.ts.map +1 -1
- package/dist/project_internal.d.ts +35 -1
- package/dist/project_internal.d.ts.map +1 -1
- package/dist/project_types.d.ts +17 -6
- package/dist/project_types.d.ts.map +1 -1
- package/dist/public_types.d.ts +1 -0
- package/dist/public_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/public_types_vocal_edit.d.ts +250 -0
- package/dist/public_types_vocal_edit.d.ts.map +1 -0
- package/dist/public_types_vocal_project.d.ts +63 -0
- package/dist/public_types_vocal_project.d.ts.map +1 -0
- package/dist/realtime_engine.d.ts +106 -16
- package/dist/realtime_engine.d.ts.map +1 -1
- package/dist/repair_dereverb.d.ts +1 -0
- package/dist/repair_dereverb.d.ts.map +1 -1
- package/dist/repair_noise.d.ts +1 -0
- package/dist/repair_noise.d.ts.map +1 -1
- package/dist/sonare-analysis.wasm +0 -0
- package/dist/sonare.d.ts +89 -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/vocal_edit.d.ts +131 -0
- package/dist/vocal_edit.d.ts.map +1 -0
- package/dist/vocal_edit_worker.d.ts +51 -0
- package/dist/vocal_edit_worker.d.ts.map +1 -0
- package/dist/vocal_edit_worker.js +1462 -0
- package/dist/vocal_edit_worker.js.map +1 -0
- package/dist/vocal_edit_worker_client.d.ts +118 -0
- package/dist/vocal_edit_worker_client.d.ts.map +1 -0
- package/dist/vocal_edit_worker_protocol.d.ts +139 -0
- package/dist/vocal_edit_worker_protocol.d.ts.map +1 -0
- package/dist/vocal_project.d.ts +17 -0
- package/dist/vocal_project.d.ts.map +1 -0
- package/dist/web_midi.d.ts +4 -0
- package/dist/web_midi.d.ts.map +1 -1
- package/dist/worker.js.map +1 -1
- package/dist/worklet/engine-mixer-facade.d.ts +42 -5
- package/dist/worklet/engine-mixer-facade.d.ts.map +1 -1
- package/dist/worklet/engine-node.d.ts +10 -0
- package/dist/worklet/engine-node.d.ts.map +1 -1
- package/dist/worklet/engine-processor.d.ts +6 -1
- package/dist/worklet/engine-processor.d.ts.map +1 -1
- package/dist/worklet/engine-register.d.ts.map +1 -1
- package/dist/worklet/engine-strips.d.ts +8 -4
- 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 +42 -9
- package/dist/worklet/engine.d.ts.map +1 -1
- package/dist/worklet/guards.d.ts +10 -2
- package/dist/worklet/guards.d.ts.map +1 -1
- package/dist/worklet/messages.d.ts +54 -9
- 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 +20 -2
- package/dist/worklet/protocol.d.ts.map +1 -1
- package/dist/worklet.d.ts +1 -1
- package/dist/worklet.d.ts.map +1 -1
- package/dist/worklet.js +808 -204
- package/dist/worklet.js.map +1 -1
- package/package.json +6 -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 +39 -0
- package/src/instrument_types.ts +29 -3
- package/src/mastering_core.ts +98 -2
- package/src/mixer.ts +41 -21
- package/src/project.ts +8 -1
- package/src/project_class.ts +136 -1
- package/src/project_internal.ts +90 -0
- package/src/project_types.ts +18 -6
- package/src/public_types.ts +1 -0
- package/src/public_types_mastering.ts +23 -0
- package/src/public_types_playback.ts +1 -0
- package/src/public_types_spectral.ts +5 -5
- package/src/public_types_vocal_edit.ts +289 -0
- package/src/public_types_vocal_project.ts +69 -0
- package/src/realtime_engine.ts +157 -24
- package/src/repair_dereverb.ts +1 -0
- package/src/repair_noise.ts +1 -0
- package/src/sonare.js.d.ts +89 -0
- package/src/streaming_processors.ts +8 -0
- package/src/vocal_edit.ts +885 -0
- package/src/vocal_edit_worker.ts +832 -0
- package/src/vocal_edit_worker_client.ts +812 -0
- package/src/vocal_edit_worker_protocol.ts +206 -0
- package/src/vocal_project.ts +327 -0
- package/src/web_midi.ts +100 -5
- package/src/worklet/engine-mixer-facade.ts +422 -87
- package/src/worklet/engine-node.ts +69 -4
- package/src/worklet/engine-processor.ts +129 -34
- package/src/worklet/engine-register.ts +3 -0
- package/src/worklet/engine-strips.ts +36 -14
- package/src/worklet/engine-sync.ts +6 -1
- package/src/worklet/engine.ts +76 -40
- package/src/worklet/guards.ts +81 -0
- package/src/worklet/messages.ts +63 -4
- package/src/worklet/mixer-processor.ts +10 -3
- package/src/worklet/protocol.ts +39 -8
- package/src/worklet.ts +2 -0
package/dist/worklet.js
CHANGED
|
@@ -720,6 +720,13 @@ var SampleBank = class {
|
|
|
720
720
|
};
|
|
721
721
|
|
|
722
722
|
// src/project_internal.ts
|
|
723
|
+
var projectTimelineHandles = /* @__PURE__ */ new WeakMap();
|
|
724
|
+
function projectTimelineNativeId(owner) {
|
|
725
|
+
if (owner === null || typeof owner !== "object" && typeof owner !== "function") {
|
|
726
|
+
return void 0;
|
|
727
|
+
}
|
|
728
|
+
return projectTimelineHandles.get(owner)?.id;
|
|
729
|
+
}
|
|
723
730
|
function normalizeSynthInstrument(patch) {
|
|
724
731
|
if (patch === null || typeof patch !== "object") {
|
|
725
732
|
return patch;
|
|
@@ -736,6 +743,20 @@ function normalizeSynthInstrument(patch) {
|
|
|
736
743
|
}
|
|
737
744
|
return { ...rest, sampleBankId: sampleBank.nativeId };
|
|
738
745
|
}
|
|
746
|
+
function partRigInsertsJson(inserts) {
|
|
747
|
+
if (inserts === void 0 || inserts === null) {
|
|
748
|
+
return void 0;
|
|
749
|
+
}
|
|
750
|
+
if (!Array.isArray(inserts)) {
|
|
751
|
+
throw new TypeError("inserts must be an array");
|
|
752
|
+
}
|
|
753
|
+
return JSON.stringify(
|
|
754
|
+
inserts.map((insert) => {
|
|
755
|
+
const { processor, params } = insert;
|
|
756
|
+
return params === void 0 ? { processor } : { processor, params: typeof params === "string" ? params : JSON.stringify(params) };
|
|
757
|
+
})
|
|
758
|
+
);
|
|
759
|
+
}
|
|
739
760
|
function projectModule() {
|
|
740
761
|
const candidate = getSonareModule();
|
|
741
762
|
if (typeof candidate.projectAbiVersion !== "function" || candidate.Project === void 0) {
|
|
@@ -1149,6 +1170,17 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1149
1170
|
setArticulation(destinationId, channel, articulation) {
|
|
1150
1171
|
this.native.setArticulation(destinationId, channel, articulation);
|
|
1151
1172
|
}
|
|
1173
|
+
/**
|
|
1174
|
+
* Set the rig of one part (0-15), or of the destination's default when `part`
|
|
1175
|
+
* is `PART_RIG_ALL_PARTS`, on the instrument bound to `destinationId`. A
|
|
1176
|
+
* direct call, not a stored edit: a destination with no instrument is an
|
|
1177
|
+
* invalid parameter, and an instrument without part rigs (a builtin, a
|
|
1178
|
+
* host-callback instrument) is refused as not implemented rather than
|
|
1179
|
+
* succeeding quietly. `'chain'` takes 1-8 `inserts`; no other mode does.
|
|
1180
|
+
*/
|
|
1181
|
+
setPartRig(destinationId, part, mode, inserts) {
|
|
1182
|
+
this.native.setPartRig(destinationId, part, mode, partRigInsertsJson(inserts));
|
|
1183
|
+
}
|
|
1152
1184
|
/**
|
|
1153
1185
|
* Read back {@link setArticulation} as the canonical name. An ordinal this
|
|
1154
1186
|
* build cannot spell is handed back as the number, the way every other enum
|
|
@@ -1194,7 +1226,10 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1194
1226
|
/**
|
|
1195
1227
|
* Route a destination's (track lane's) MIDI to the external output queue
|
|
1196
1228
|
* instead of the internal instrument rack, so the track plays an external
|
|
1197
|
-
* device. Clearing it restores internal-synth playback.
|
|
1229
|
+
* device. Clearing it restores internal-synth playback. Control-thread only.
|
|
1230
|
+
* The change takes effect at the next processed block; switching a
|
|
1231
|
+
* destination's route first releases its notes and resets its controllers
|
|
1232
|
+
* through the old route, and drops its pending MIDI-FX events. Single writer.
|
|
1198
1233
|
*/
|
|
1199
1234
|
setMidiDestinationExternal(destinationId, external) {
|
|
1200
1235
|
this.native.setMidiDestinationExternal(destinationId, external);
|
|
@@ -1348,8 +1383,11 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1348
1383
|
/**
|
|
1349
1384
|
* Queue an immediate (live) MIDI SysEx frame to a MIDI destination. `data` is
|
|
1350
1385
|
* 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
|
|
1386
|
+
* bytes). `renderFrame` is the frame to fire at, or -1 for immediate. Throws
|
|
1387
|
+
* `InvalidParameter` when the destination instrument cannot prepare
|
|
1388
|
+
* the SysEx (retrying cannot help), and `OutOfMemory` when the payload
|
|
1389
|
+
* slots or the command queue are full (retry after a processed block).
|
|
1390
|
+
* Mirrors the Node/Python/C-ABI `pushMidiSysex`.
|
|
1353
1391
|
*/
|
|
1354
1392
|
pushMidiSysex(destinationId, data, renderFrame = -1) {
|
|
1355
1393
|
this.native.pushMidiSysex(destinationId, data, renderFrame);
|
|
@@ -1372,12 +1410,30 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1372
1410
|
getTransportState() {
|
|
1373
1411
|
return this.native.getTransportState();
|
|
1374
1412
|
}
|
|
1413
|
+
/** Queues an integrated-loudness reset; short-term and momentary windows are retained. */
|
|
1414
|
+
resetMasterLoudnessMeter(renderFrame = -1) {
|
|
1415
|
+
this.native.resetMasterLoudnessMeter(renderFrame);
|
|
1416
|
+
}
|
|
1417
|
+
/** Reads the immutable factory value for a resolved insert parameter id. */
|
|
1418
|
+
insertParameterConstructedValue(paramId) {
|
|
1419
|
+
return this.native.insertParameterConstructedValue(paramId);
|
|
1420
|
+
}
|
|
1375
1421
|
play(renderFrame = -1) {
|
|
1376
1422
|
this.native.play(renderFrame);
|
|
1377
1423
|
}
|
|
1424
|
+
/**
|
|
1425
|
+
* A loop wrap, seek or stop sends note-offs plus CC64=0, CC121, CC123 and a
|
|
1426
|
+
* centred pitch bend on every channel played since the last reset, so
|
|
1427
|
+
* controller values set before a loop region are not restored at the wrap.
|
|
1428
|
+
*/
|
|
1378
1429
|
stop(renderFrame = -1) {
|
|
1379
1430
|
this.native.stop(renderFrame);
|
|
1380
1431
|
}
|
|
1432
|
+
/**
|
|
1433
|
+
* A loop wrap, seek or stop sends note-offs plus CC64=0, CC121, CC123 and a
|
|
1434
|
+
* centred pitch bend on every channel played since the last reset, so
|
|
1435
|
+
* controller values set before a loop region are not restored at the wrap.
|
|
1436
|
+
*/
|
|
1381
1437
|
seekSample(timelineSample, renderFrame = -1) {
|
|
1382
1438
|
this.native.seekSample(timelineSample, renderFrame);
|
|
1383
1439
|
}
|
|
@@ -1402,6 +1458,11 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1402
1458
|
applyCommandsDueNowPreservingFuture() {
|
|
1403
1459
|
this.native.applyCommandsDueNowPreservingFuture();
|
|
1404
1460
|
}
|
|
1461
|
+
/**
|
|
1462
|
+
* A loop wrap, seek or stop sends note-offs plus CC64=0, CC121, CC123 and a
|
|
1463
|
+
* centred pitch bend on every channel played since the last reset, so
|
|
1464
|
+
* controller values set before a loop region are not restored at the wrap.
|
|
1465
|
+
*/
|
|
1405
1466
|
seekPpq(ppq, renderFrame = -1) {
|
|
1406
1467
|
this.native.seekPpq(ppq, renderFrame);
|
|
1407
1468
|
}
|
|
@@ -1421,6 +1482,11 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1421
1482
|
sampleAtPpq(ppq) {
|
|
1422
1483
|
return Number(this.native.sampleAtPpq(ppq));
|
|
1423
1484
|
}
|
|
1485
|
+
/**
|
|
1486
|
+
* A loop wrap, seek or stop sends note-offs plus CC64=0, CC121, CC123 and a
|
|
1487
|
+
* centred pitch bend on every channel played since the last reset, so
|
|
1488
|
+
* controller values set before a loop region are not restored at the wrap.
|
|
1489
|
+
*/
|
|
1424
1490
|
setLoop(startPpq, endPpq, enabled = true) {
|
|
1425
1491
|
this.native.setLoop(startPpq, endPpq, enabled);
|
|
1426
1492
|
}
|
|
@@ -1515,25 +1581,56 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1515
1581
|
if (typeof lane === "number") {
|
|
1516
1582
|
return { trackId: lane };
|
|
1517
1583
|
}
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1584
|
+
return {
|
|
1585
|
+
...lane,
|
|
1586
|
+
sends: lane.sends ? _RealtimeEngine.normalizeSends(lane.sends) : void 0
|
|
1587
|
+
};
|
|
1522
1588
|
})
|
|
1523
1589
|
);
|
|
1524
1590
|
}
|
|
1525
1591
|
/**
|
|
1526
1592
|
* Keys one insert of a lane strip from another lane's post-strip audio
|
|
1527
1593
|
* (ducking/sidechainRouter inserts). sourceTrackId 0 removes the binding.
|
|
1594
|
+
* Lanes are processed in key order and the key is delay-compensated to the
|
|
1595
|
+
* destination strip input, so the result depends on neither the lane order
|
|
1596
|
+
* nor the block size. Throws, leaving the bindings unchanged, for a lane
|
|
1597
|
+
* keying itself, a binding that would close a cycle over the lane bindings,
|
|
1598
|
+
* a full binding table and an alignment past the delay ceiling. Not callable
|
|
1599
|
+
* while a block is being processed.
|
|
1528
1600
|
*/
|
|
1529
1601
|
setLaneSidechain(trackId, insertIndex, sourceTrackId) {
|
|
1530
1602
|
this.native.setLaneSidechain(trackId, insertIndex, sourceTrackId);
|
|
1531
1603
|
}
|
|
1604
|
+
/**
|
|
1605
|
+
* Installs a compiled project timeline into this stopped engine, all or
|
|
1606
|
+
* nothing: tempo and time-signature segments, markers, track lanes, track
|
|
1607
|
+
* automation, audio and MIDI clips, and the per-track strips of the project's
|
|
1608
|
+
* mixer scene are replaced in full (a later low-level setter on those domains
|
|
1609
|
+
* is overwritten by the next apply). Instruments, buses, the master strip,
|
|
1610
|
+
* metronome, loop and capture are not touched; bind instruments separately.
|
|
1611
|
+
*
|
|
1612
|
+
* Throws while the transport is playing, for a timeline the engine cannot
|
|
1613
|
+
* hold, and for a scene strip routed from several tracks. A validation
|
|
1614
|
+
* failure leaves the engine unchanged. The engine keeps its own reference, so
|
|
1615
|
+
* {@link ProjectTimeline.dispose} may follow immediately.
|
|
1616
|
+
*
|
|
1617
|
+
* Also throws on an unprepared engine and on a timeline whose sample rate
|
|
1618
|
+
* differs from the engine's. Once a timeline is applied, a later prepare at
|
|
1619
|
+
* another rate is refused until the timeline's clips are cleared.
|
|
1620
|
+
*/
|
|
1621
|
+
applyProjectTimeline(timeline) {
|
|
1622
|
+
const timelineId = projectTimelineNativeId(timeline);
|
|
1623
|
+
if (timelineId === void 0) {
|
|
1624
|
+
throw new TypeError("timeline must be a ProjectTimeline instance");
|
|
1625
|
+
}
|
|
1626
|
+
this.native.applyProjectTimeline(timelineId);
|
|
1627
|
+
}
|
|
1532
1628
|
setTrackBuses(buses) {
|
|
1533
1629
|
this.native.setTrackBuses(
|
|
1534
|
-
Array.isArray(buses) ? buses.map(
|
|
1535
|
-
|
|
1536
|
-
|
|
1630
|
+
Array.isArray(buses) ? buses.map((bus) => ({
|
|
1631
|
+
...bus,
|
|
1632
|
+
sends: bus.sends ? _RealtimeEngine.normalizeSends(bus.sends) : void 0
|
|
1633
|
+
})) : buses
|
|
1537
1634
|
);
|
|
1538
1635
|
}
|
|
1539
1636
|
/**
|
|
@@ -1687,6 +1784,16 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1687
1784
|
* stages of the offline mastering chain (`repair.*`, `loudness`, and the
|
|
1688
1785
|
* match stages) have no insert form and no automation id: they buffer the
|
|
1689
1786
|
* entire signal by construction and do not run on the realtime path.
|
|
1787
|
+
*
|
|
1788
|
+
* The returned id uses the track's current positional lane selector. When
|
|
1789
|
+
* `setTrackLanes` successfully changes lane order or membership, the engine
|
|
1790
|
+
* remaps already queued and published track automation by track id, but it
|
|
1791
|
+
* cannot update a numeric id retained by the caller. Re-resolve every track
|
|
1792
|
+
* insert id after such a topology change before passing it to
|
|
1793
|
+
* `setAutomationLane`, `setParameter`, or `setParameterSmoothed`. Use
|
|
1794
|
+
* `setTrackStripInsertParamByName` when the operation needs a stable track
|
|
1795
|
+
* identity. Master and bus insert ids are separate and are not invalidated by
|
|
1796
|
+
* track-lane changes.
|
|
1690
1797
|
*/
|
|
1691
1798
|
resolveTrackInsertAutomationId(trackId, insertIndex, paramName) {
|
|
1692
1799
|
return this.native.resolveTrackInsertAutomationId(trackId, insertIndex, paramName);
|
|
@@ -1719,12 +1826,9 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1719
1826
|
* return `-1`: they resize voice pools or swap DSP topology, which is not
|
|
1720
1827
|
* audio-thread safe. Rebind the instrument with a new patch instead.
|
|
1721
1828
|
*
|
|
1722
|
-
*
|
|
1723
|
-
*
|
|
1724
|
-
*
|
|
1725
|
-
* note-on and take effect from the next note, so a lane that moves one of
|
|
1726
|
-
* them under a held note looks inert until the next one speaks — that is the
|
|
1727
|
-
* behaviour, not a dropped write.
|
|
1829
|
+
* All automatable parameters of a NativeSynth reach already-sounding voices
|
|
1830
|
+
* from the next processed block. Voices using GM program patches are
|
|
1831
|
+
* unaffected; parameters apply to NativeSynth's own patch only.
|
|
1728
1832
|
*
|
|
1729
1833
|
* The id survives an unbind/rebind of the same destination and applies
|
|
1730
1834
|
* nothing while that destination is unbound.
|
|
@@ -1748,6 +1852,16 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1748
1852
|
setTrackStripDualPan(trackId, leftPan, rightPan) {
|
|
1749
1853
|
this.native.setTrackStripDualPan(trackId, leftPan, rightPan);
|
|
1750
1854
|
}
|
|
1855
|
+
/**
|
|
1856
|
+
* Sets a track lane strip's surround placement in realtime (glitch-free; a
|
|
1857
|
+
* constant-power 5 ms one-pole glide). Used when the destination has more than
|
|
1858
|
+
* two channels. Omitted fields default to a centered point source
|
|
1859
|
+
* (`distance` 1); a `distance` of 0 or less is treated as 1. Throws for an
|
|
1860
|
+
* unknown track, a track without a lane strip, or a non-finite field.
|
|
1861
|
+
*/
|
|
1862
|
+
setTrackStripSurroundPan(trackId, pan) {
|
|
1863
|
+
this.native.setTrackStripSurroundPan(trackId, pan);
|
|
1864
|
+
}
|
|
1751
1865
|
/**
|
|
1752
1866
|
* Sets a bus strip's output pan position in realtime (glitch-free). Throws
|
|
1753
1867
|
* for an unknown bus or one wider than stereo.
|
|
@@ -1768,8 +1882,9 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
1768
1882
|
this.native.setBusStripDualPan(busId, leftPan, rightPan);
|
|
1769
1883
|
}
|
|
1770
1884
|
/**
|
|
1771
|
-
* Sets a track lane strip's
|
|
1772
|
-
*
|
|
1885
|
+
* Sets a track lane strip's alignment delay (whole samples), moving this lane
|
|
1886
|
+
* later relative to every other lane. It is not latency: PDC does not
|
|
1887
|
+
* compensate it and the reported graph latency is unchanged.
|
|
1773
1888
|
*/
|
|
1774
1889
|
setTrackStripChannelDelaySamples(trackId, delaySamples) {
|
|
1775
1890
|
this.native.setTrackStripChannelDelaySamples(trackId, delaySamples);
|
|
@@ -2013,6 +2128,12 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
2013
2128
|
meterScratchRenderFrame() {
|
|
2014
2129
|
return Number(this.native.meterScratchRenderFrame());
|
|
2015
2130
|
}
|
|
2131
|
+
meterScratchInputPeakDbL() {
|
|
2132
|
+
return this.native.meterScratchInputPeakDbL();
|
|
2133
|
+
}
|
|
2134
|
+
meterScratchInputPeakDbR() {
|
|
2135
|
+
return this.native.meterScratchInputPeakDbR();
|
|
2136
|
+
}
|
|
2016
2137
|
meterScratchValue(field) {
|
|
2017
2138
|
return this.native.meterScratchValue(field);
|
|
2018
2139
|
}
|
|
@@ -2022,14 +2143,24 @@ var RealtimeEngine = class _RealtimeEngine {
|
|
|
2022
2143
|
/**
|
|
2023
2144
|
* Drains pending meter telemetry as per-plane (wide) records for a surround
|
|
2024
2145
|
* 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
|
|
2146
|
+
* stays the stereo fast path. The two share one queue and each consumes every
|
|
2147
|
+
* target's records, so an engine uses only one of them. The live AudioWorklet
|
|
2148
|
+
* path owns the queue via the stereo drain, so this wide drain is for an
|
|
2149
|
+
* offline (non-worklet) engine instance; per-plane
|
|
2028
2150
|
* surround meters are not delivered over the live worklet meter ring.
|
|
2029
2151
|
*/
|
|
2030
2152
|
drainMeterTelemetryWide(maxRecords = 1024) {
|
|
2031
2153
|
return this.native.drainMeterTelemetryWide(maxRecords);
|
|
2032
2154
|
}
|
|
2155
|
+
/**
|
|
2156
|
+
* Per-insert gain reduction in dB (each <= 0) of a meter target's strip from the
|
|
2157
|
+
* last rendered block, in combined pre-to-post insert order. `targetId` uses the
|
|
2158
|
+
* meter-record encoding (0 master, 1..32 lanes, 33..40 buses; 0xFFFF monitor
|
|
2159
|
+
* yields an empty array). Throws for an id outside that range.
|
|
2160
|
+
*/
|
|
2161
|
+
meterTargetInsertGainReduction(targetId) {
|
|
2162
|
+
return this.native.meterTargetInsertGainReduction(targetId);
|
|
2163
|
+
}
|
|
2033
2164
|
/**
|
|
2034
2165
|
* Enables per-target spectrum + vectorscope capture. @param intervalFrames is
|
|
2035
2166
|
* the minimum render-frame gap between snapshots (0 disables). @param bandCount
|
|
@@ -2186,47 +2317,60 @@ var Mixer = class _Mixer {
|
|
|
2186
2317
|
* after {@link delete}.
|
|
2187
2318
|
*/
|
|
2188
2319
|
createRealtimeBuffer() {
|
|
2189
|
-
const
|
|
2190
|
-
|
|
2191
|
-
let rightInputs = [];
|
|
2320
|
+
const leftInputs = [];
|
|
2321
|
+
const rightInputs = [];
|
|
2192
2322
|
let outLeft = this.mixer.outputLeftView();
|
|
2193
2323
|
let outRight = this.mixer.outputRightView();
|
|
2324
|
+
let acquiredStripCount = -1;
|
|
2325
|
+
const viewsDetached = () => outLeft.byteLength === 0 || outRight.byteLength === 0;
|
|
2194
2326
|
const acquire = () => {
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2327
|
+
const stripCount = this.stripCount();
|
|
2328
|
+
const detached = viewsDetached();
|
|
2329
|
+
if (detached) {
|
|
2330
|
+
leftInputs.length = 0;
|
|
2331
|
+
rightInputs.length = 0;
|
|
2332
|
+
} else {
|
|
2333
|
+
leftInputs.length = Math.min(leftInputs.length, stripCount);
|
|
2334
|
+
rightInputs.length = Math.min(rightInputs.length, stripCount);
|
|
2335
|
+
}
|
|
2336
|
+
for (let index = leftInputs.length; index < stripCount; index++) {
|
|
2198
2337
|
leftInputs.push(this.mixer.inputLeftView(index));
|
|
2338
|
+
}
|
|
2339
|
+
for (let index = rightInputs.length; index < stripCount; index++) {
|
|
2199
2340
|
rightInputs.push(this.mixer.inputRightView(index));
|
|
2200
2341
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2342
|
+
if (detached) {
|
|
2343
|
+
outLeft = this.mixer.outputLeftView();
|
|
2344
|
+
outRight = this.mixer.outputRightView();
|
|
2345
|
+
}
|
|
2346
|
+
acquiredStripCount = stripCount;
|
|
2203
2347
|
};
|
|
2204
2348
|
acquire();
|
|
2205
|
-
const
|
|
2206
|
-
if (
|
|
2349
|
+
const acquireIfNeeded = () => {
|
|
2350
|
+
if (acquiredStripCount !== this.stripCount() || viewsDetached()) {
|
|
2207
2351
|
acquire();
|
|
2208
2352
|
}
|
|
2209
2353
|
};
|
|
2210
2354
|
return {
|
|
2211
2355
|
get leftInputs() {
|
|
2212
|
-
|
|
2356
|
+
acquireIfNeeded();
|
|
2213
2357
|
return leftInputs;
|
|
2214
2358
|
},
|
|
2215
2359
|
get rightInputs() {
|
|
2216
|
-
|
|
2360
|
+
acquireIfNeeded();
|
|
2217
2361
|
return rightInputs;
|
|
2218
2362
|
},
|
|
2219
2363
|
get outLeft() {
|
|
2220
|
-
|
|
2364
|
+
acquireIfNeeded();
|
|
2221
2365
|
return outLeft;
|
|
2222
2366
|
},
|
|
2223
2367
|
get outRight() {
|
|
2224
|
-
|
|
2368
|
+
acquireIfNeeded();
|
|
2225
2369
|
return outRight;
|
|
2226
2370
|
},
|
|
2227
|
-
process: (numSamples
|
|
2228
|
-
|
|
2229
|
-
this.mixer.processPreparedStereo(numSamples);
|
|
2371
|
+
process: (numSamples) => {
|
|
2372
|
+
acquireIfNeeded();
|
|
2373
|
+
this.mixer.processPreparedStereo(numSamples ?? outLeft.length);
|
|
2230
2374
|
}
|
|
2231
2375
|
};
|
|
2232
2376
|
}
|
|
@@ -2444,8 +2588,8 @@ var Mixer = class _Mixer {
|
|
|
2444
2588
|
this.mixer.setPanLaw(stripIndex, panLawCode(panLaw));
|
|
2445
2589
|
}
|
|
2446
2590
|
/**
|
|
2447
|
-
* Set a per-strip channel delay in samples
|
|
2448
|
-
*
|
|
2591
|
+
* Set a per-strip channel delay in samples, moving the strip later relative to
|
|
2592
|
+
* the others. It is not latency: latency compensation does not undo it.
|
|
2449
2593
|
*/
|
|
2450
2594
|
setChannelDelaySamples(stripIndex, delaySamples) {
|
|
2451
2595
|
this.mixer.setChannelDelaySamples(stripIndex, delaySamples);
|
|
@@ -2999,6 +3143,13 @@ var StreamingMasteringChain = class {
|
|
|
2999
3143
|
reset() {
|
|
3000
3144
|
this.chain.reset();
|
|
3001
3145
|
}
|
|
3146
|
+
/**
|
|
3147
|
+
* Set one realtime-safe full-chain parameter at a serialized block boundary.
|
|
3148
|
+
* Structural, disabled-stage and unknown parameters are rejected.
|
|
3149
|
+
*/
|
|
3150
|
+
setParameter(key, value) {
|
|
3151
|
+
this.chain.setParameter(key, value);
|
|
3152
|
+
}
|
|
3002
3153
|
/** Total reported latency in samples across all active processors. */
|
|
3003
3154
|
latencySamples() {
|
|
3004
3155
|
return this.chain.latencySamples();
|
|
@@ -3105,14 +3256,16 @@ function isInitialized() {
|
|
|
3105
3256
|
}
|
|
3106
3257
|
|
|
3107
3258
|
// src/worklet/engine-sync.ts
|
|
3108
|
-
function buildMixerLanes(trackLaneIds, trackSends, trackOutputBus) {
|
|
3259
|
+
function buildMixerLanes(trackLaneIds, trackSends, trackOutputBus, trackSourceChannelLayout) {
|
|
3109
3260
|
return trackLaneIds.map((trackId) => {
|
|
3110
3261
|
const sends = trackSends.get(trackId);
|
|
3111
3262
|
const outputBusId = trackOutputBus.get(trackId);
|
|
3263
|
+
const sourceChannelLayout = trackSourceChannelLayout.get(trackId);
|
|
3112
3264
|
return {
|
|
3113
3265
|
trackId,
|
|
3114
3266
|
...sends && sends.length > 0 ? { sends: sends.map((send) => ({ ...send })) } : {},
|
|
3115
|
-
...outputBusId !== void 0 ? { outputBusId } : {}
|
|
3267
|
+
...outputBusId !== void 0 ? { outputBusId } : {},
|
|
3268
|
+
...sourceChannelLayout !== void 0 ? { sourceChannelLayout } : {}
|
|
3116
3269
|
};
|
|
3117
3270
|
});
|
|
3118
3271
|
}
|
|
@@ -3187,10 +3340,12 @@ function engineMixerMasterTarget(paramKind) {
|
|
|
3187
3340
|
return ENGINE_MIXER_TARGET_BASE | 255 << 8 | paramKind & 255;
|
|
3188
3341
|
}
|
|
3189
3342
|
var SONARE_METER_RING_HEADER_INTS = 4;
|
|
3190
|
-
var SONARE_METER_RING_RECORD_FLOATS =
|
|
3343
|
+
var SONARE_METER_RING_RECORD_FLOATS = 16;
|
|
3191
3344
|
var SONARE_SPECTRUM_RING_HEADER_INTS = 5;
|
|
3192
3345
|
var SONARE_SCOPE_RING_HEADER_INTS = 6;
|
|
3193
3346
|
var SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS = 5;
|
|
3347
|
+
var SONARE_SCOPE_DEFAULT_BANDS = 48;
|
|
3348
|
+
var SONARE_SCOPE_DEFAULT_MAX_POINTS = 32;
|
|
3194
3349
|
var SONARE_FRAME_LANE_BASE = 16777216;
|
|
3195
3350
|
function encodeFrameLo(frame) {
|
|
3196
3351
|
const f = Math.max(0, Math.floor(frame));
|
|
@@ -3230,6 +3385,7 @@ var SonareEngineCommandType = /* @__PURE__ */ ((SonareEngineCommandType2) => {
|
|
|
3230
3385
|
SonareEngineCommandType2[SonareEngineCommandType2["SetMarker"] = 16] = "SetMarker";
|
|
3231
3386
|
SonareEngineCommandType2[SonareEngineCommandType2["SeekMarker"] = 17] = "SeekMarker";
|
|
3232
3387
|
SonareEngineCommandType2[SonareEngineCommandType2["SetTrackMonitorMode"] = 26] = "SetTrackMonitorMode";
|
|
3388
|
+
SonareEngineCommandType2[SonareEngineCommandType2["ResetMasterLoudnessMeter"] = 28] = "ResetMasterLoudnessMeter";
|
|
3233
3389
|
return SonareEngineCommandType2;
|
|
3234
3390
|
})(SonareEngineCommandType || {});
|
|
3235
3391
|
var SonareEngineTelemetryType = /* @__PURE__ */ ((SonareEngineTelemetryType2) => {
|
|
@@ -3262,6 +3418,7 @@ var SonareEngineTelemetryError = /* @__PURE__ */ ((SonareEngineTelemetryError2)
|
|
|
3262
3418
|
SonareEngineTelemetryError2[SonareEngineTelemetryError2["ParameterBaseOverflow"] = 21] = "ParameterBaseOverflow";
|
|
3263
3419
|
return SonareEngineTelemetryError2;
|
|
3264
3420
|
})(SonareEngineTelemetryError || {});
|
|
3421
|
+
var SONARE_FLOOR_DB = -120;
|
|
3265
3422
|
function isRecord(value) {
|
|
3266
3423
|
return typeof value === "object" && value !== null;
|
|
3267
3424
|
}
|
|
@@ -3301,7 +3458,9 @@ function readSonareMeterRingBuffer(ring, readIndex = 0) {
|
|
|
3301
3458
|
momentaryLufs: ring.records[offset + 10],
|
|
3302
3459
|
shortTermLufs: ring.records[offset + 11],
|
|
3303
3460
|
integratedLufs: ring.records[offset + 12],
|
|
3304
|
-
gainReductionDb: ring.records[offset + 13]
|
|
3461
|
+
gainReductionDb: ring.records[offset + 13],
|
|
3462
|
+
inputPeakDbL: ring.records[offset + 14],
|
|
3463
|
+
inputPeakDbR: ring.records[offset + 15]
|
|
3305
3464
|
});
|
|
3306
3465
|
}
|
|
3307
3466
|
return { nextReadIndex: writeIndex, meters };
|
|
@@ -3353,13 +3512,13 @@ function readSonareSpectrumRingBuffer(ring, readIndex = 0) {
|
|
|
3353
3512
|
function sonareScopeRingRecordFloats(bands, maxPoints) {
|
|
3354
3513
|
return SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS + bands + 2 * maxPoints;
|
|
3355
3514
|
}
|
|
3356
|
-
function sonareScopeRingBufferByteLength(capacity, bands =
|
|
3515
|
+
function sonareScopeRingBufferByteLength(capacity, bands = SONARE_SCOPE_DEFAULT_BANDS, maxPoints = SONARE_SCOPE_DEFAULT_MAX_POINTS) {
|
|
3357
3516
|
const clampedCapacity = Math.max(1, Math.floor(capacity));
|
|
3358
3517
|
const clampedBands = Math.max(1, Math.floor(bands));
|
|
3359
3518
|
const clampedPoints = Math.max(0, Math.floor(maxPoints));
|
|
3360
3519
|
return SONARE_SCOPE_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT + clampedCapacity * sonareScopeRingRecordFloats(clampedBands, clampedPoints) * Float32Array.BYTES_PER_ELEMENT;
|
|
3361
3520
|
}
|
|
3362
|
-
function createSonareScopeRingBuffer(capacity = 64, bands =
|
|
3521
|
+
function createSonareScopeRingBuffer(capacity = 64, bands = SONARE_SCOPE_DEFAULT_BANDS, maxPoints = SONARE_SCOPE_DEFAULT_MAX_POINTS) {
|
|
3363
3522
|
const clampedCapacity = Math.max(1, Math.floor(capacity));
|
|
3364
3523
|
const clampedBands = Math.max(1, Math.floor(bands));
|
|
3365
3524
|
const clampedPoints = Math.max(0, Math.floor(maxPoints));
|
|
@@ -3426,8 +3585,14 @@ function scopeRingFromSharedBuffer(sharedBuffer, fallbackCapacity, fallbackBands
|
|
|
3426
3585
|
const existingBands = Atomics.load(header, 3);
|
|
3427
3586
|
const existingMaxPoints = Atomics.load(header, 4);
|
|
3428
3587
|
const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));
|
|
3429
|
-
const bands = Math.max(
|
|
3430
|
-
|
|
3588
|
+
const bands = Math.max(
|
|
3589
|
+
1,
|
|
3590
|
+
Math.floor(existingBands || fallbackBands || SONARE_SCOPE_DEFAULT_BANDS)
|
|
3591
|
+
);
|
|
3592
|
+
const maxPoints = Math.max(
|
|
3593
|
+
0,
|
|
3594
|
+
Math.floor(existingMaxPoints || (fallbackMaxPoints ?? SONARE_SCOPE_DEFAULT_MAX_POINTS))
|
|
3595
|
+
);
|
|
3431
3596
|
const recordFloats = sonareScopeRingRecordFloats(bands, maxPoints);
|
|
3432
3597
|
const minBytes = sonareScopeRingBufferByteLength(capacity, bands, maxPoints);
|
|
3433
3598
|
if (sharedBuffer.byteLength < minBytes) {
|
|
@@ -3832,7 +3997,9 @@ function meterFromEngine(meter) {
|
|
|
3832
3997
|
momentaryLufs: meter.momentaryLufs,
|
|
3833
3998
|
shortTermLufs: meter.shortTermLufs,
|
|
3834
3999
|
integratedLufs: meter.integratedLufs,
|
|
3835
|
-
gainReductionDb: meter.gainReductionDb
|
|
4000
|
+
gainReductionDb: meter.gainReductionDb,
|
|
4001
|
+
inputPeakDbL: meter.inputPeakDbL,
|
|
4002
|
+
inputPeakDbR: meter.inputPeakDbR
|
|
3836
4003
|
};
|
|
3837
4004
|
}
|
|
3838
4005
|
function magnitudeToDb(value) {
|
|
@@ -3891,6 +4058,7 @@ var ENGINE_SYNC_MESSAGE_TYPES = {
|
|
|
3891
4058
|
syncMidiInputPitchBend: true,
|
|
3892
4059
|
syncMidiInputPolyPressure: true,
|
|
3893
4060
|
syncMidiInputSource: true,
|
|
4061
|
+
syncMidiInputUmp: true,
|
|
3894
4062
|
syncMidiNoteOff: true,
|
|
3895
4063
|
syncMidiNoteOn: true,
|
|
3896
4064
|
syncMidiPanic: true,
|
|
@@ -3911,6 +4079,7 @@ var ENGINE_SYNC_MESSAGE_TYPES = {
|
|
|
3911
4079
|
syncTrackStripPan: true,
|
|
3912
4080
|
syncTrackStripPanLaw: true,
|
|
3913
4081
|
syncTrackStripPanMode: true,
|
|
4082
|
+
syncTrackStripSurroundPan: true,
|
|
3914
4083
|
syncWarpVoiceCapacity: true
|
|
3915
4084
|
};
|
|
3916
4085
|
var engineSyncMessageTypes = new Set(Object.keys(ENGINE_SYNC_MESSAGE_TYPES));
|
|
@@ -3981,6 +4150,12 @@ function isEngineTransportRequestMessage(value) {
|
|
|
3981
4150
|
function isEngineTransportResponseMessage(value) {
|
|
3982
4151
|
return isRecord(value) && value.type === "transportResponse" && typeof value.requestId === "number" && typeof value.ok === "boolean";
|
|
3983
4152
|
}
|
|
4153
|
+
function isEngineInsertGainReductionRequestMessage(value) {
|
|
4154
|
+
return isRecord(value) && value.type === "insertGainReductionRequest" && typeof value.requestId === "number" && typeof value.targetId === "number";
|
|
4155
|
+
}
|
|
4156
|
+
function isEngineInsertGainReductionResponseMessage(value) {
|
|
4157
|
+
return isRecord(value) && value.type === "insertGainReductionResponse" && typeof value.requestId === "number" && typeof value.ok === "boolean";
|
|
4158
|
+
}
|
|
3984
4159
|
function isRealtimeVoiceChangerMessage(value) {
|
|
3985
4160
|
if (!isRecord(value) || typeof value.type !== "string") {
|
|
3986
4161
|
return false;
|
|
@@ -4017,7 +4192,23 @@ function isClipPageRequestMessage(value) {
|
|
|
4017
4192
|
);
|
|
4018
4193
|
}
|
|
4019
4194
|
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);
|
|
4195
|
+
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);
|
|
4196
|
+
}
|
|
4197
|
+
var SONARE_SCOPE_MAX_BANDS = 64;
|
|
4198
|
+
var SONARE_SCOPE_MAX_POINTS = 32;
|
|
4199
|
+
function isPlainFloat32Array(value, maxLength, evenLength = false) {
|
|
4200
|
+
if (!(value instanceof Float32Array) || typeof ArrayBuffer === "undefined" || !(value.buffer instanceof ArrayBuffer) || value.length > maxLength || evenLength && value.length % 2 !== 0) {
|
|
4201
|
+
return false;
|
|
4202
|
+
}
|
|
4203
|
+
for (const sample of value) {
|
|
4204
|
+
if (!Number.isFinite(sample)) {
|
|
4205
|
+
return false;
|
|
4206
|
+
}
|
|
4207
|
+
}
|
|
4208
|
+
return true;
|
|
4209
|
+
}
|
|
4210
|
+
function isScopeSnapshot(value) {
|
|
4211
|
+
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
4212
|
}
|
|
4022
4213
|
function requireIntegerOption(value, fallback, name, minimum) {
|
|
4023
4214
|
const resolved = value ?? fallback;
|
|
@@ -4026,6 +4217,9 @@ function requireIntegerOption(value, fallback, name, minimum) {
|
|
|
4026
4217
|
}
|
|
4027
4218
|
return resolved;
|
|
4028
4219
|
}
|
|
4220
|
+
function resolveScopeBandCount(value, fallback = SONARE_SCOPE_DEFAULT_BANDS) {
|
|
4221
|
+
return Math.min(requireIntegerOption(value, fallback, "scopeBands", 1), SONARE_SCOPE_MAX_BANDS);
|
|
4222
|
+
}
|
|
4029
4223
|
function requireInteger(value, fallback, name) {
|
|
4030
4224
|
const resolved = value ?? fallback;
|
|
4031
4225
|
if (!Number.isSafeInteger(resolved)) {
|
|
@@ -4325,6 +4519,156 @@ function syncMarkers(ctx) {
|
|
|
4325
4519
|
}
|
|
4326
4520
|
|
|
4327
4521
|
// src/worklet/engine-mixer-facade.ts
|
|
4522
|
+
function isSceneObject(value) {
|
|
4523
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4524
|
+
}
|
|
4525
|
+
function hasOwn2(object, key) {
|
|
4526
|
+
return Object.getOwnPropertyDescriptor(object, key) !== void 0;
|
|
4527
|
+
}
|
|
4528
|
+
function canonicalJson(value) {
|
|
4529
|
+
if (Array.isArray(value)) {
|
|
4530
|
+
return `[${value.map((item) => canonicalJson(item)).join(",")}]`;
|
|
4531
|
+
}
|
|
4532
|
+
if (value !== null && typeof value === "object") {
|
|
4533
|
+
const object = value;
|
|
4534
|
+
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(object[key])}`).join(",")}}`;
|
|
4535
|
+
}
|
|
4536
|
+
return JSON.stringify(value);
|
|
4537
|
+
}
|
|
4538
|
+
function aliasedValue(object, primary, legacy) {
|
|
4539
|
+
if (hasOwn2(object, primary)) {
|
|
4540
|
+
return { present: true, value: object[primary] };
|
|
4541
|
+
}
|
|
4542
|
+
if (hasOwn2(object, legacy)) {
|
|
4543
|
+
return { present: true, value: object[legacy] };
|
|
4544
|
+
}
|
|
4545
|
+
return { present: false, value: void 0 };
|
|
4546
|
+
}
|
|
4547
|
+
function insertSignature(insert) {
|
|
4548
|
+
const object = insert !== null && typeof insert === "object" ? insert : {};
|
|
4549
|
+
const slot = object.slot === void 0 ? "pre" : object.slot;
|
|
4550
|
+
const processor = aliasedValue(object, "processor", "processor_name");
|
|
4551
|
+
const params = aliasedValue(object, "params", "params_json");
|
|
4552
|
+
const sidechain = aliasedValue(object, "sidechainKey", "sidechain_key");
|
|
4553
|
+
const processorValue = typeof processor.value === "string" ? processor.value : "";
|
|
4554
|
+
const sidechainValue = typeof sidechain.value === "string" ? sidechain.value : "";
|
|
4555
|
+
let paramsValue;
|
|
4556
|
+
if (!params.present) {
|
|
4557
|
+
paramsValue = ["absent"];
|
|
4558
|
+
} else if (typeof params.value === "string") {
|
|
4559
|
+
if (params.value.length === 0) {
|
|
4560
|
+
paramsValue = ["absent"];
|
|
4561
|
+
} else {
|
|
4562
|
+
try {
|
|
4563
|
+
paramsValue = ["params", canonicalJson(JSON.parse(params.value))];
|
|
4564
|
+
} catch {
|
|
4565
|
+
paramsValue = ["params-invalid", params.value];
|
|
4566
|
+
}
|
|
4567
|
+
}
|
|
4568
|
+
} else {
|
|
4569
|
+
paramsValue = ["params", canonicalJson(params.value)];
|
|
4570
|
+
}
|
|
4571
|
+
return JSON.stringify([slot, processorValue, paramsValue, sidechainValue]);
|
|
4572
|
+
}
|
|
4573
|
+
function decodedInsertSignature(sceneJson, target) {
|
|
4574
|
+
const scene = JSON.parse(sceneJson);
|
|
4575
|
+
const entries = target.kind === "bus" ? scene.buses : scene.strips;
|
|
4576
|
+
const strip = Array.isArray(entries) ? entries.find(isSceneObject) : void 0;
|
|
4577
|
+
const object = isSceneObject(strip) ? strip : {};
|
|
4578
|
+
const inserts = Array.isArray(object.inserts) ? object.inserts.filter(isSceneObject) : [];
|
|
4579
|
+
const ordered = target.kind === "bus" ? inserts : [
|
|
4580
|
+
...inserts.filter((insert) => insert.slot !== "post"),
|
|
4581
|
+
...inserts.filter((insert) => insert.slot === "post")
|
|
4582
|
+
];
|
|
4583
|
+
return JSON.stringify(ordered.map(insertSignature));
|
|
4584
|
+
}
|
|
4585
|
+
function constructionValue(engine, target, override) {
|
|
4586
|
+
let parameterId = -1;
|
|
4587
|
+
switch (target.kind) {
|
|
4588
|
+
case "track":
|
|
4589
|
+
parameterId = engine.resolveTrackInsertAutomationId(
|
|
4590
|
+
target.trackId,
|
|
4591
|
+
override.insertIndex,
|
|
4592
|
+
override.paramName
|
|
4593
|
+
);
|
|
4594
|
+
break;
|
|
4595
|
+
case "bus":
|
|
4596
|
+
parameterId = engine.resolveBusInsertAutomationId(
|
|
4597
|
+
target.busId,
|
|
4598
|
+
override.insertIndex,
|
|
4599
|
+
override.paramName
|
|
4600
|
+
);
|
|
4601
|
+
break;
|
|
4602
|
+
case "master":
|
|
4603
|
+
parameterId = engine.resolveMasterInsertAutomationId(
|
|
4604
|
+
override.insertIndex,
|
|
4605
|
+
override.paramName
|
|
4606
|
+
);
|
|
4607
|
+
break;
|
|
4608
|
+
}
|
|
4609
|
+
if (parameterId < 0) {
|
|
4610
|
+
return void 0;
|
|
4611
|
+
}
|
|
4612
|
+
return engine.insertParameterConstructedValue(parameterId);
|
|
4613
|
+
}
|
|
4614
|
+
function constructionInsertOverrides(engine, target, overrides) {
|
|
4615
|
+
const restored = [];
|
|
4616
|
+
for (const override of overrides.values()) {
|
|
4617
|
+
if (!sameStripTarget(override.target, target)) {
|
|
4618
|
+
continue;
|
|
4619
|
+
}
|
|
4620
|
+
const value = constructionValue(engine, target, override);
|
|
4621
|
+
if (value !== void 0) {
|
|
4622
|
+
restored.push({ ...override, value });
|
|
4623
|
+
}
|
|
4624
|
+
}
|
|
4625
|
+
return restored;
|
|
4626
|
+
}
|
|
4627
|
+
function applyInsertParamOverride(engine, override) {
|
|
4628
|
+
switch (override.target.kind) {
|
|
4629
|
+
case "track":
|
|
4630
|
+
engine.restoreTrackStripInsertParamByName(
|
|
4631
|
+
override.target.trackId,
|
|
4632
|
+
override.insertIndex,
|
|
4633
|
+
override.paramName,
|
|
4634
|
+
override.value
|
|
4635
|
+
);
|
|
4636
|
+
break;
|
|
4637
|
+
case "bus":
|
|
4638
|
+
engine.restoreBusStripInsertParamByName(
|
|
4639
|
+
override.target.busId,
|
|
4640
|
+
override.insertIndex,
|
|
4641
|
+
override.paramName,
|
|
4642
|
+
override.value
|
|
4643
|
+
);
|
|
4644
|
+
break;
|
|
4645
|
+
case "master":
|
|
4646
|
+
engine.restoreMasterStripInsertParamByName(
|
|
4647
|
+
override.insertIndex,
|
|
4648
|
+
override.paramName,
|
|
4649
|
+
override.value
|
|
4650
|
+
);
|
|
4651
|
+
break;
|
|
4652
|
+
}
|
|
4653
|
+
}
|
|
4654
|
+
function applyConstructionInsertOverrides(engine, overrides) {
|
|
4655
|
+
for (const override of overrides) {
|
|
4656
|
+
applyInsertParamOverride(engine, override);
|
|
4657
|
+
}
|
|
4658
|
+
}
|
|
4659
|
+
function clearInsertParameterBases(engine, target) {
|
|
4660
|
+
switch (target.kind) {
|
|
4661
|
+
case "track":
|
|
4662
|
+
engine.clearTrackInsertParameterBases(target.trackId);
|
|
4663
|
+
break;
|
|
4664
|
+
case "bus":
|
|
4665
|
+
engine.clearBusInsertParameterBases(target.busId);
|
|
4666
|
+
break;
|
|
4667
|
+
case "master":
|
|
4668
|
+
engine.clearMasterInsertParameterBases();
|
|
4669
|
+
break;
|
|
4670
|
+
}
|
|
4671
|
+
}
|
|
4328
4672
|
function emptyStripJson(target) {
|
|
4329
4673
|
switch (target.kind) {
|
|
4330
4674
|
case "track":
|
|
@@ -4367,7 +4711,7 @@ function hasInsertParamOverrides(overrides, target) {
|
|
|
4367
4711
|
}
|
|
4368
4712
|
return false;
|
|
4369
4713
|
}
|
|
4370
|
-
function applyFullStripJson(engine, target, sceneJson
|
|
4714
|
+
function applyFullStripJson(engine, target, sceneJson) {
|
|
4371
4715
|
const apply = (json) => {
|
|
4372
4716
|
switch (target.kind) {
|
|
4373
4717
|
case "track":
|
|
@@ -4383,21 +4727,6 @@ function applyFullStripJson(engine, target, sceneJson, resetInserts) {
|
|
|
4383
4727
|
};
|
|
4384
4728
|
engine.applyCommandsDueNowPreservingFuture();
|
|
4385
4729
|
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
4730
|
}
|
|
4402
4731
|
function insertParamOverrideKey(override) {
|
|
4403
4732
|
const targetId = override.target.kind === "track" ? override.target.trackId : override.target.kind === "bus" ? override.target.busId : "master";
|
|
@@ -4473,42 +4802,64 @@ function cacheStripJson(ctx, target, sceneJson) {
|
|
|
4473
4802
|
}
|
|
4474
4803
|
}
|
|
4475
4804
|
function mixerLanes(ctx) {
|
|
4476
|
-
return buildMixerLanes(
|
|
4805
|
+
return buildMixerLanes(
|
|
4806
|
+
ctx.trackLaneIds,
|
|
4807
|
+
ctx.trackSends,
|
|
4808
|
+
ctx.trackOutputBus,
|
|
4809
|
+
ctx.trackSourceChannelLayout
|
|
4810
|
+
);
|
|
4811
|
+
}
|
|
4812
|
+
function cloneMixerRouting(ctx) {
|
|
4813
|
+
return {
|
|
4814
|
+
trackLaneIds: [...ctx.trackLaneIds],
|
|
4815
|
+
trackSends: new Map(
|
|
4816
|
+
Array.from(ctx.trackSends, ([trackId, sends]) => [
|
|
4817
|
+
trackId,
|
|
4818
|
+
sends.map((send) => ({ ...send }))
|
|
4819
|
+
])
|
|
4820
|
+
),
|
|
4821
|
+
trackOutputBus: new Map(ctx.trackOutputBus),
|
|
4822
|
+
trackSourceChannelLayout: new Map(ctx.trackSourceChannelLayout)
|
|
4823
|
+
};
|
|
4824
|
+
}
|
|
4825
|
+
function commitMixerRouting(ctx, draft) {
|
|
4826
|
+
ctx.trackLaneIds.splice(0, ctx.trackLaneIds.length, ...draft.trackLaneIds);
|
|
4827
|
+
ctx.trackSends.clear();
|
|
4828
|
+
for (const [trackId, sends] of draft.trackSends) {
|
|
4829
|
+
ctx.trackSends.set(
|
|
4830
|
+
trackId,
|
|
4831
|
+
sends.map((send) => ({ ...send }))
|
|
4832
|
+
);
|
|
4833
|
+
}
|
|
4834
|
+
ctx.trackOutputBus.clear();
|
|
4835
|
+
for (const [trackId, busId] of draft.trackOutputBus) {
|
|
4836
|
+
ctx.trackOutputBus.set(trackId, busId);
|
|
4837
|
+
}
|
|
4838
|
+
ctx.trackSourceChannelLayout.clear();
|
|
4839
|
+
for (const [trackId, layout] of draft.trackSourceChannelLayout) {
|
|
4840
|
+
ctx.trackSourceChannelLayout.set(trackId, layout);
|
|
4841
|
+
}
|
|
4477
4842
|
}
|
|
4478
|
-
function
|
|
4479
|
-
|
|
4843
|
+
function buildDraftMixerLanes(draft) {
|
|
4844
|
+
return buildMixerLanes(
|
|
4845
|
+
draft.trackLaneIds,
|
|
4846
|
+
draft.trackSends,
|
|
4847
|
+
draft.trackOutputBus,
|
|
4848
|
+
draft.trackSourceChannelLayout
|
|
4849
|
+
);
|
|
4850
|
+
}
|
|
4851
|
+
function applyMixerRouting(ctx, draft, busesAlreadyApplied) {
|
|
4852
|
+
const lanes = buildDraftMixerLanes(draft);
|
|
4480
4853
|
const buses = ctx.buses.map((bus) => ({ ...bus }));
|
|
4481
4854
|
if (!busesAlreadyApplied) {
|
|
4482
4855
|
ctx.offlineEngine.setTrackBuses(buses);
|
|
4483
4856
|
}
|
|
4484
4857
|
if (lanes.length > 0) {
|
|
4485
|
-
ctx.offlineEngine.settleInsertParameters();
|
|
4486
4858
|
ctx.offlineEngine.setTrackLanes(lanes);
|
|
4487
4859
|
}
|
|
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
|
-
}
|
|
4860
|
+
return { lanes, buses };
|
|
4861
|
+
}
|
|
4862
|
+
function postMixerSync(ctx, lanes, buses, insertBaseResets, oneShotInsertParamOverrides) {
|
|
4512
4863
|
replayInsertParamOverrides(ctx, lanes, buses);
|
|
4513
4864
|
const trackStrips = Array.from(ctx.trackStripJson, ([trackId, sceneJson]) => ({
|
|
4514
4865
|
trackId,
|
|
@@ -4518,10 +4869,10 @@ function syncMixer(ctx, busesAlreadyApplied = false, forceInsertResets = []) {
|
|
|
4518
4869
|
busId,
|
|
4519
4870
|
sceneJson
|
|
4520
4871
|
}));
|
|
4521
|
-
const insertParamOverrides =
|
|
4522
|
-
ctx.insertParamOverrides.values(),
|
|
4523
|
-
flattenInsertParamOverride
|
|
4524
|
-
|
|
4872
|
+
const insertParamOverrides = [
|
|
4873
|
+
...Array.from(ctx.insertParamOverrides.values(), flattenInsertParamOverride),
|
|
4874
|
+
...oneShotInsertParamOverrides.map(flattenInsertParamOverride)
|
|
4875
|
+
];
|
|
4525
4876
|
ctx.postSync({
|
|
4526
4877
|
type: "syncMixer",
|
|
4527
4878
|
lanes,
|
|
@@ -4533,9 +4884,23 @@ function syncMixer(ctx, busesAlreadyApplied = false, forceInsertResets = []) {
|
|
|
4533
4884
|
busSidechains: Array.from(ctx.busSidechains.values()),
|
|
4534
4885
|
masterSidechains: Array.from(ctx.masterSidechains.values()),
|
|
4535
4886
|
...insertParamOverrides.length > 0 ? { insertParamOverrides } : {},
|
|
4536
|
-
...
|
|
4887
|
+
...insertBaseResets.length > 0 ? { insertBaseResets } : {}
|
|
4537
4888
|
});
|
|
4538
4889
|
}
|
|
4890
|
+
function syncMixerDraft(ctx, draft, busesAlreadyApplied = false, insertBaseResets = [], oneShotInsertParamOverrides = []) {
|
|
4891
|
+
const { lanes, buses } = applyMixerRouting(ctx, draft, busesAlreadyApplied);
|
|
4892
|
+
commitMixerRouting(ctx, draft);
|
|
4893
|
+
postMixerSync(ctx, lanes, buses, insertBaseResets, oneShotInsertParamOverrides);
|
|
4894
|
+
}
|
|
4895
|
+
function syncMixer(ctx, busesAlreadyApplied = false, insertBaseResets = [], oneShotInsertParamOverrides = []) {
|
|
4896
|
+
syncMixerDraft(
|
|
4897
|
+
ctx,
|
|
4898
|
+
cloneMixerRouting(ctx),
|
|
4899
|
+
busesAlreadyApplied,
|
|
4900
|
+
insertBaseResets,
|
|
4901
|
+
oneShotInsertParamOverrides
|
|
4902
|
+
);
|
|
4903
|
+
}
|
|
4539
4904
|
function replayInsertParamOverrides(ctx, lanes = mixerLanes(ctx), buses = ctx.buses) {
|
|
4540
4905
|
const activeTrackIds = new Set(lanes.map((lane) => lane.trackId));
|
|
4541
4906
|
const activeBusIds = new Set(buses.map((bus) => bus.busId));
|
|
@@ -4573,34 +4938,59 @@ function replayInsertParamOverrides(ctx, lanes = mixerLanes(ctx), buses = ctx.bu
|
|
|
4573
4938
|
}
|
|
4574
4939
|
}
|
|
4575
4940
|
function setTrackLanes(ctx, lanes) {
|
|
4576
|
-
const
|
|
4941
|
+
const draft = cloneMixerRouting(ctx);
|
|
4942
|
+
const { entries, ids } = normalizeTrackLanes(draft.trackLaneIds, lanes);
|
|
4577
4943
|
for (const entry of entries) {
|
|
4578
4944
|
if (entry.sends) {
|
|
4579
|
-
|
|
4945
|
+
draft.trackSends.set(
|
|
4580
4946
|
entry.trackId,
|
|
4581
4947
|
entry.sends.map((send) => ({ ...send }))
|
|
4582
4948
|
);
|
|
4583
4949
|
}
|
|
4584
4950
|
if (entry.outputBusId !== void 0) {
|
|
4585
4951
|
if (entry.outputBusId === 0) {
|
|
4586
|
-
|
|
4952
|
+
draft.trackOutputBus.delete(entry.trackId);
|
|
4587
4953
|
} else {
|
|
4588
|
-
|
|
4954
|
+
draft.trackOutputBus.set(entry.trackId, entry.outputBusId);
|
|
4589
4955
|
}
|
|
4590
4956
|
}
|
|
4957
|
+
if (entry.sourceChannelLayout !== void 0) {
|
|
4958
|
+
draft.trackSourceChannelLayout.set(entry.trackId, entry.sourceChannelLayout);
|
|
4959
|
+
}
|
|
4591
4960
|
}
|
|
4592
|
-
|
|
4593
|
-
ctx
|
|
4961
|
+
draft.trackLaneIds = ids;
|
|
4962
|
+
syncMixerDraft(ctx, draft, true);
|
|
4963
|
+
}
|
|
4964
|
+
function ensureTrackLaneInDraft(draft, target) {
|
|
4965
|
+
const trackId = resolveTargetId(target);
|
|
4966
|
+
if (!Number.isInteger(trackId) || trackId <= 0) {
|
|
4967
|
+
throw new RangeError(`Invalid track id for mixer lane: ${String(target)}`);
|
|
4968
|
+
}
|
|
4969
|
+
const existing = draft.trackLaneIds.indexOf(trackId);
|
|
4970
|
+
if (existing >= 0) {
|
|
4971
|
+
return existing;
|
|
4972
|
+
}
|
|
4973
|
+
draft.trackLaneIds.push(trackId);
|
|
4974
|
+
return draft.trackLaneIds.length - 1;
|
|
4975
|
+
}
|
|
4976
|
+
function ensureTrackLane(ctx, target) {
|
|
4977
|
+
const draft = cloneMixerRouting(ctx);
|
|
4978
|
+
const laneIndex = ensureTrackLaneInDraft(draft, target);
|
|
4979
|
+
if (draft.trackLaneIds.length !== ctx.trackLaneIds.length) {
|
|
4980
|
+
syncMixerDraft(ctx, draft, true);
|
|
4981
|
+
}
|
|
4982
|
+
return laneIndex;
|
|
4594
4983
|
}
|
|
4595
4984
|
function setTrackOutputBus(ctx, target, busId) {
|
|
4596
|
-
const
|
|
4597
|
-
const
|
|
4985
|
+
const draft = cloneMixerRouting(ctx);
|
|
4986
|
+
const laneIndex = ensureTrackLaneInDraft(draft, target);
|
|
4987
|
+
const trackId = draft.trackLaneIds[laneIndex];
|
|
4598
4988
|
if (busId === 0) {
|
|
4599
|
-
|
|
4989
|
+
draft.trackOutputBus.delete(trackId);
|
|
4600
4990
|
} else {
|
|
4601
|
-
|
|
4991
|
+
draft.trackOutputBus.set(trackId, busId);
|
|
4602
4992
|
}
|
|
4603
|
-
ctx
|
|
4993
|
+
syncMixerDraft(ctx, draft, true);
|
|
4604
4994
|
}
|
|
4605
4995
|
function setLaneSidechain(ctx, target, insertIndex, sourceTarget) {
|
|
4606
4996
|
const laneIndex = ctx.ensureTrackLane(target);
|
|
@@ -4669,13 +5059,14 @@ function ensureSidechainSource(ctx, sourceKind, sourceId) {
|
|
|
4669
5059
|
}
|
|
4670
5060
|
}
|
|
4671
5061
|
function setSends(ctx, target, sends) {
|
|
4672
|
-
const
|
|
4673
|
-
const
|
|
4674
|
-
|
|
5062
|
+
const draft = cloneMixerRouting(ctx);
|
|
5063
|
+
const laneIndex = ensureTrackLaneInDraft(draft, target);
|
|
5064
|
+
const trackId = draft.trackLaneIds[laneIndex];
|
|
5065
|
+
draft.trackSends.set(
|
|
4675
5066
|
trackId,
|
|
4676
5067
|
sends.map((send) => ({ ...send }))
|
|
4677
5068
|
);
|
|
4678
|
-
ctx
|
|
5069
|
+
syncMixerDraft(ctx, draft, true);
|
|
4679
5070
|
}
|
|
4680
5071
|
function setTrackBuses(ctx, buses) {
|
|
4681
5072
|
ctx.offlineEngine.setTrackBuses(buses);
|
|
@@ -4709,18 +5100,45 @@ function setBusGain(ctx, busId, db) {
|
|
|
4709
5100
|
ctx.buses[busIndex] = { ...ctx.buses[busIndex], busId, gainDb: db };
|
|
4710
5101
|
return ctx.sendSmoothedParam(engineMixerBusTarget(busIndex, ENGINE_MIXER_PARAM_FADER_DB), db);
|
|
4711
5102
|
}
|
|
5103
|
+
function replaceStripScene(ctx, target, previousJson, sceneJson) {
|
|
5104
|
+
const chainChanged = previousJson !== void 0 && decodedInsertSignature(previousJson, target) !== decodedInsertSignature(sceneJson, target);
|
|
5105
|
+
const hasOverrides = hasInsertParamOverrides(ctx.insertParamOverrides, target);
|
|
5106
|
+
applyFullStripJson(ctx.offlineEngine, target, sceneJson);
|
|
5107
|
+
if (!chainChanged && !hasOverrides) {
|
|
5108
|
+
return { insertBaseResets: [], constructionOverrides: [] };
|
|
5109
|
+
}
|
|
5110
|
+
const constructionOverrides = chainChanged ? [] : constructionInsertOverrides(ctx.offlineEngine, target, ctx.insertParamOverrides);
|
|
5111
|
+
ctx.clearInsertAutomationLanes(target);
|
|
5112
|
+
clearInsertParameterBases(ctx.offlineEngine, target);
|
|
5113
|
+
applyConstructionInsertOverrides(ctx.offlineEngine, constructionOverrides);
|
|
5114
|
+
clearInsertParamOverrides(ctx.insertParamOverrides, target);
|
|
5115
|
+
return { insertBaseResets: [target], constructionOverrides };
|
|
5116
|
+
}
|
|
4712
5117
|
function setBusStripJson(ctx, busId, sceneJson) {
|
|
4713
|
-
ctx.ensureBus(busId);
|
|
4714
5118
|
const target = { kind: "bus", busId };
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
ctx
|
|
4719
|
-
|
|
5119
|
+
decodedInsertSignature(sceneJson, target);
|
|
5120
|
+
ctx.ensureBus(busId);
|
|
5121
|
+
const { insertBaseResets, constructionOverrides } = replaceStripScene(
|
|
5122
|
+
ctx,
|
|
5123
|
+
target,
|
|
5124
|
+
ctx.busStripJson.get(busId),
|
|
5125
|
+
sceneJson
|
|
5126
|
+
);
|
|
4720
5127
|
pruneStripSidechains(ctx, target, sceneJson);
|
|
4721
5128
|
ctx.busStripJson.set(busId, sceneJson);
|
|
4722
|
-
|
|
4723
|
-
|
|
5129
|
+
ctx.syncMixer(insertBaseResets, constructionOverrides);
|
|
5130
|
+
}
|
|
5131
|
+
function setMasterStripJson(ctx, sceneJson) {
|
|
5132
|
+
const target = { kind: "master" };
|
|
5133
|
+
const { insertBaseResets, constructionOverrides } = replaceStripScene(
|
|
5134
|
+
ctx,
|
|
5135
|
+
target,
|
|
5136
|
+
ctx.getMasterStripJson(),
|
|
5137
|
+
sceneJson
|
|
5138
|
+
);
|
|
5139
|
+
pruneStripSidechains(ctx, target, sceneJson);
|
|
5140
|
+
ctx.cacheMasterStripJson(sceneJson);
|
|
5141
|
+
ctx.syncMixer(insertBaseResets, constructionOverrides);
|
|
4724
5142
|
}
|
|
4725
5143
|
|
|
4726
5144
|
// src/worklet/engine-node.ts
|
|
@@ -4739,7 +5157,7 @@ function isTrackMonitorMode(value) {
|
|
|
4739
5157
|
}
|
|
4740
5158
|
function isValidCommandRecord(command) {
|
|
4741
5159
|
const type = Number(command.type);
|
|
4742
|
-
if (!Number.isSafeInteger(type) || type < 0 /* SetParam */ || type > 17 /* SeekMarker */ && type !== 26 /* SetTrackMonitorMode */) {
|
|
5160
|
+
if (!Number.isSafeInteger(type) || type < 0 /* SetParam */ || type > 17 /* SeekMarker */ && type !== 26 /* SetTrackMonitorMode */ && type !== 28 /* ResetMasterLoudnessMeter */) {
|
|
4743
5161
|
return false;
|
|
4744
5162
|
}
|
|
4745
5163
|
return (
|
|
@@ -4775,6 +5193,8 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
4775
5193
|
this.captureRequests = /* @__PURE__ */ new Map();
|
|
4776
5194
|
this.transportRequestId = 1;
|
|
4777
5195
|
this.transportRequests = /* @__PURE__ */ new Map();
|
|
5196
|
+
this.insertGainReductionRequestId = 1;
|
|
5197
|
+
this.insertGainReductionRequests = /* @__PURE__ */ new Map();
|
|
4778
5198
|
this.destroyed = false;
|
|
4779
5199
|
this.node = node;
|
|
4780
5200
|
this.capabilities = capabilities;
|
|
@@ -4820,10 +5240,22 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
4820
5240
|
pending.reject(new Error(event.data.error ?? "Transport request failed"));
|
|
4821
5241
|
}
|
|
4822
5242
|
}
|
|
5243
|
+
} else if (isEngineInsertGainReductionResponseMessage(event.data)) {
|
|
5244
|
+
const pending = this.insertGainReductionRequests.get(event.data.requestId);
|
|
5245
|
+
if (pending) {
|
|
5246
|
+
this.insertGainReductionRequests.delete(event.data.requestId);
|
|
5247
|
+
if (event.data.ok && Array.isArray(event.data.values)) {
|
|
5248
|
+
pending.resolve(event.data.values);
|
|
5249
|
+
} else {
|
|
5250
|
+
pending.reject(new Error(event.data.error ?? "Insert gain reduction request failed"));
|
|
5251
|
+
}
|
|
5252
|
+
}
|
|
4823
5253
|
} else if (isEngineTelemetryRecord(event.data)) {
|
|
4824
5254
|
this.emitTelemetry(event.data);
|
|
4825
5255
|
} else if (isMeterSnapshot(event.data)) {
|
|
4826
5256
|
this.emitMeter(event.data);
|
|
5257
|
+
} else if (isScopeSnapshot(event.data)) {
|
|
5258
|
+
this.emitScope(event.data);
|
|
4827
5259
|
} else if (isExternalMidiBatchMessage(event.data)) {
|
|
4828
5260
|
this.emitMidiOut(event.data.events);
|
|
4829
5261
|
} else if (isClipPageRequestMessage(event.data)) {
|
|
@@ -4876,6 +5308,12 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
4876
5308
|
"SharedArrayBuffer mode requested but SharedArrayBuffer/Atomics are unavailable."
|
|
4877
5309
|
);
|
|
4878
5310
|
}
|
|
5311
|
+
const meterIntervalFrames = requireIntegerOption(
|
|
5312
|
+
options.meterIntervalFrames,
|
|
5313
|
+
2048,
|
|
5314
|
+
"meterIntervalFrames",
|
|
5315
|
+
0
|
|
5316
|
+
);
|
|
4879
5317
|
const commandRingCapacity = requireIntegerOption(
|
|
4880
5318
|
options.commandRingCapacity,
|
|
4881
5319
|
128,
|
|
@@ -4903,7 +5341,7 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
4903
5341
|
"scopeRingCapacity",
|
|
4904
5342
|
1
|
|
4905
5343
|
);
|
|
4906
|
-
const scopeBands =
|
|
5344
|
+
const scopeBands = resolveScopeBandCount(options.scopeBands);
|
|
4907
5345
|
const clipPageRequestRingCapacity = requireIntegerOption(
|
|
4908
5346
|
options.clipPageRequestRingCapacity,
|
|
4909
5347
|
128,
|
|
@@ -4934,6 +5372,7 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
4934
5372
|
sampleRate: options.sampleRate ?? context.sampleRate,
|
|
4935
5373
|
blockSize,
|
|
4936
5374
|
channelCount,
|
|
5375
|
+
meterIntervalFrames,
|
|
4937
5376
|
cueOutput,
|
|
4938
5377
|
commandSharedBuffer: commandRing?.sharedBuffer,
|
|
4939
5378
|
commandRingCapacity: commandRing?.capacity,
|
|
@@ -4943,8 +5382,8 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
4943
5382
|
meterRingCapacity: meterRing?.capacity,
|
|
4944
5383
|
scopeSharedBuffer: scopeRing?.sharedBuffer,
|
|
4945
5384
|
scopeRingCapacity: scopeRing?.capacity,
|
|
4946
|
-
scopeBands: scopeRing?.bands,
|
|
4947
|
-
scopeIntervalFrames:
|
|
5385
|
+
scopeBands: scopeIntervalFrames > 0 ? scopeRing?.bands ?? scopeBands : void 0,
|
|
5386
|
+
scopeIntervalFrames: scopeIntervalFrames > 0 ? scopeIntervalFrames : void 0,
|
|
4948
5387
|
clipPageRequestSharedBuffer: clipPageRequestRing?.sharedBuffer,
|
|
4949
5388
|
clipPageRequestRingCapacity: clipPageRequestRing?.capacity,
|
|
4950
5389
|
externalMidiSharedBuffer: externalMidiRing?.sharedBuffer,
|
|
@@ -4993,6 +5432,10 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
4993
5432
|
play(sampleTime = -1) {
|
|
4994
5433
|
return this.sendCommand({ type: 2 /* TransportPlay */, sampleTime });
|
|
4995
5434
|
}
|
|
5435
|
+
/** Queues a reset of the master's integrated-loudness accumulator. */
|
|
5436
|
+
resetMasterLoudnessMeter(sampleTime = -1) {
|
|
5437
|
+
return this.sendCommand({ type: 28 /* ResetMasterLoudnessMeter */, sampleTime });
|
|
5438
|
+
}
|
|
4996
5439
|
stop(sampleTime = -1) {
|
|
4997
5440
|
return this.sendCommand({ type: 3 /* TransportStop */, sampleTime });
|
|
4998
5441
|
}
|
|
@@ -5200,6 +5643,10 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
5200
5643
|
pending.reject(new Error("Realtime engine node is destroyed."));
|
|
5201
5644
|
}
|
|
5202
5645
|
this.transportRequests.clear();
|
|
5646
|
+
for (const pending of this.insertGainReductionRequests.values()) {
|
|
5647
|
+
pending.reject(new Error("Realtime engine node is destroyed."));
|
|
5648
|
+
}
|
|
5649
|
+
this.insertGainReductionRequests.clear();
|
|
5203
5650
|
this.telemetryListeners.clear();
|
|
5204
5651
|
this.meterListeners.clear();
|
|
5205
5652
|
this.scopeListeners.clear();
|
|
@@ -5249,6 +5696,29 @@ var SonareRealtimeEngineNode = class _SonareRealtimeEngineNode {
|
|
|
5249
5696
|
listener(message);
|
|
5250
5697
|
}
|
|
5251
5698
|
}
|
|
5699
|
+
/**
|
|
5700
|
+
* Reads one target's per-insert gain reduction (dB, each <= 0, pre-to-post insert order)
|
|
5701
|
+
* from the worklet. Works in both ring and postMessage meter modes; rejects when the
|
|
5702
|
+
* target is invalid or mixing is not compiled in.
|
|
5703
|
+
*/
|
|
5704
|
+
pollInsertGainReduction(targetId) {
|
|
5705
|
+
if (this.destroyed) {
|
|
5706
|
+
return Promise.reject(new Error("Realtime engine node is destroyed."));
|
|
5707
|
+
}
|
|
5708
|
+
const requestId = this.insertGainReductionRequestId++;
|
|
5709
|
+
let rejectRequest;
|
|
5710
|
+
const promise = new Promise((resolve, reject) => {
|
|
5711
|
+
rejectRequest = reject;
|
|
5712
|
+
this.insertGainReductionRequests.set(requestId, { resolve, reject });
|
|
5713
|
+
});
|
|
5714
|
+
try {
|
|
5715
|
+
this.node.port.postMessage({ type: "insertGainReductionRequest", requestId, targetId });
|
|
5716
|
+
} catch (error) {
|
|
5717
|
+
this.insertGainReductionRequests.delete(requestId);
|
|
5718
|
+
rejectRequest(error);
|
|
5719
|
+
}
|
|
5720
|
+
return promise;
|
|
5721
|
+
}
|
|
5252
5722
|
emitScope(scope) {
|
|
5253
5723
|
for (const listener of this.scopeListeners) {
|
|
5254
5724
|
listener(scope);
|
|
@@ -5397,11 +5867,9 @@ function setInsertParamByName(ctx, target, insertIndex, paramName, value, applyN
|
|
|
5397
5867
|
}
|
|
5398
5868
|
function setTrackStripJson(ctx, trackId, sceneJson, trackStripJson) {
|
|
5399
5869
|
const target = { kind: "track", trackId };
|
|
5400
|
-
const
|
|
5401
|
-
applyFullStripJson(ctx.offlineEngine, target, sceneJson, resetInserts);
|
|
5402
|
-
clearInsertParamOverrides(ctx.insertParamOverrides, target);
|
|
5870
|
+
const result = replaceStripScene(ctx, target, trackStripJson.get(trackId), sceneJson);
|
|
5403
5871
|
trackStripJson.set(trackId, sceneJson);
|
|
5404
|
-
return
|
|
5872
|
+
return result;
|
|
5405
5873
|
}
|
|
5406
5874
|
function setTrackStripEqBand(ctx, target, bandIndex, band) {
|
|
5407
5875
|
const trackId = trackIdFor(ctx, target);
|
|
@@ -5468,6 +5936,21 @@ function setTrackStripDualPan(ctx, target, leftPan, rightPan) {
|
|
|
5468
5936
|
});
|
|
5469
5937
|
ctx.postSync({ type: "syncTrackStripDualPan", trackId, leftPan, rightPan });
|
|
5470
5938
|
}
|
|
5939
|
+
function setTrackStripSurroundPan(ctx, target, pan) {
|
|
5940
|
+
const trackId = trackIdFor(ctx, target);
|
|
5941
|
+
ctx.offlineEngine.setTrackStripSurroundPan(trackId, pan);
|
|
5942
|
+
const resolved = {
|
|
5943
|
+
azimuth: pan.azimuth ?? 0,
|
|
5944
|
+
elevation: pan.elevation ?? 0,
|
|
5945
|
+
divergence: pan.divergence ?? 0,
|
|
5946
|
+
lfe: pan.lfe ?? 0,
|
|
5947
|
+
distance: pan.distance === void 0 || pan.distance <= 0 ? 1 : pan.distance
|
|
5948
|
+
};
|
|
5949
|
+
mergeStripJson(ctx, { kind: "track", trackId }, (entry) => {
|
|
5950
|
+
entry.surroundPan = resolved;
|
|
5951
|
+
});
|
|
5952
|
+
ctx.postSync({ type: "syncTrackStripSurroundPan", trackId, pan: resolved });
|
|
5953
|
+
}
|
|
5471
5954
|
function setTrackStripChannelDelaySamples(ctx, target, delaySamples) {
|
|
5472
5955
|
const trackId = trackIdFor(ctx, target);
|
|
5473
5956
|
ctx.offlineEngine.setTrackStripChannelDelaySamples(trackId, delaySamples);
|
|
@@ -5641,8 +6124,14 @@ function pushMidiPolyPressure(ctx, trackId, group, channel, note, pressure, rend
|
|
|
5641
6124
|
}
|
|
5642
6125
|
function pushMidiUmp(ctx, trackId, word0, renderFrame) {
|
|
5643
6126
|
const destinationId = ctx.resolveTargetId(trackId);
|
|
5644
|
-
|
|
5645
|
-
|
|
6127
|
+
if (typeof word0 === "number") {
|
|
6128
|
+
ctx.offlineEngine.pushMidiUmp(destinationId, word0, renderFrame);
|
|
6129
|
+
ctx.postSync({ type: "syncMidiUmp", destinationId, word0, renderFrame });
|
|
6130
|
+
return;
|
|
6131
|
+
}
|
|
6132
|
+
const words = word0 instanceof Uint32Array ? new Uint32Array(word0) : word0.slice();
|
|
6133
|
+
ctx.offlineEngine.pushMidiUmp(destinationId, words, renderFrame);
|
|
6134
|
+
ctx.postSync({ type: "syncMidiUmp", destinationId, words, renderFrame });
|
|
5646
6135
|
}
|
|
5647
6136
|
function setBuiltinInstrument(ctx, trackId, config) {
|
|
5648
6137
|
const destinationId = ctx.resolveTargetId(trackId);
|
|
@@ -5774,6 +6263,7 @@ var SonareEngine = class _SonareEngine {
|
|
|
5774
6263
|
this.trackLaneIds = [];
|
|
5775
6264
|
this.trackSends = /* @__PURE__ */ new Map();
|
|
5776
6265
|
this.trackOutputBus = /* @__PURE__ */ new Map();
|
|
6266
|
+
this.trackSourceChannelLayout = /* @__PURE__ */ new Map();
|
|
5777
6267
|
this.laneSidechains = /* @__PURE__ */ new Map();
|
|
5778
6268
|
this.busSidechains = /* @__PURE__ */ new Map();
|
|
5779
6269
|
this.masterSidechains = /* @__PURE__ */ new Map();
|
|
@@ -5875,6 +6365,11 @@ var SonareEngine = class _SonareEngine {
|
|
|
5875
6365
|
setTimeSignatureSegments(segments) {
|
|
5876
6366
|
setTimeSignatureSegments(this.tempoContext, segments);
|
|
5877
6367
|
}
|
|
6368
|
+
/**
|
|
6369
|
+
* A loop wrap, seek or stop sends note-offs plus CC64=0, CC121, CC123 and a
|
|
6370
|
+
* centred pitch bend on every channel played since the last reset, so
|
|
6371
|
+
* controller values set before a loop region are not restored at the wrap.
|
|
6372
|
+
*/
|
|
5878
6373
|
setLoop(startPpq, endPpq, enabled = true) {
|
|
5879
6374
|
return setLoop(this.tempoContext, startPpq, endPpq, enabled);
|
|
5880
6375
|
}
|
|
@@ -5933,6 +6428,15 @@ var SonareEngine = class _SonareEngine {
|
|
|
5933
6428
|
* mixer lane first (like automationParamId) so the offline engine resolves the
|
|
5934
6429
|
* same strip selector the realtime engine uses.
|
|
5935
6430
|
*
|
|
6431
|
+
* The returned id uses the track's current positional lane selector. When
|
|
6432
|
+
* setTrackLanes successfully changes lane order or membership, the engine
|
|
6433
|
+
* remaps already queued and published track automation by track id, but it
|
|
6434
|
+
* cannot update a numeric id retained by the caller. Re-resolve every track
|
|
6435
|
+
* insert id after such a topology change before passing it to
|
|
6436
|
+
* setAutomationLane. Use setTrackStripInsertParamByName when the operation
|
|
6437
|
+
* needs a stable track identity. Master and bus insert ids are separate and
|
|
6438
|
+
* are not invalidated by track-lane changes.
|
|
6439
|
+
*
|
|
5936
6440
|
* @param target Track id (declares a mixer lane on first use).
|
|
5937
6441
|
* @param insertIndex Index into the strip's combined insert sequence.
|
|
5938
6442
|
* @param paramName Processor JSON-key parameter name.
|
|
@@ -6046,14 +6550,23 @@ var SonareEngine = class _SonareEngine {
|
|
|
6046
6550
|
}
|
|
6047
6551
|
return sent;
|
|
6048
6552
|
}
|
|
6553
|
+
/** Resets the master's integrated loudness accumulator in both engine mirrors. */
|
|
6554
|
+
resetMasterLoudnessMeter(renderFrame = -1) {
|
|
6555
|
+
this.offlineEngine.resetMasterLoudnessMeter(renderFrame);
|
|
6556
|
+
return this.sendMirroredCommand({
|
|
6557
|
+
type: 28 /* ResetMasterLoudnessMeter */,
|
|
6558
|
+
sampleTime: renderFrame
|
|
6559
|
+
});
|
|
6560
|
+
}
|
|
6049
6561
|
/**
|
|
6050
6562
|
* Declares the mixer track lanes in an explicit order.
|
|
6051
6563
|
*
|
|
6052
|
-
*
|
|
6053
|
-
*
|
|
6054
|
-
*
|
|
6055
|
-
*
|
|
6056
|
-
* track's send list; entries without `sends` leave
|
|
6564
|
+
* A successful call may reorder existing track ids, remove track ids, or add
|
|
6565
|
+
* new ones. Existing queued and published track automation follows the track
|
|
6566
|
+
* id, while numeric track-insert automation ids retained by the caller do
|
|
6567
|
+
* not; re-resolve those ids after every topology change. Entries carrying
|
|
6568
|
+
* `sends` replace that track's send list; entries without `sends` leave
|
|
6569
|
+
* existing sends untouched.
|
|
6057
6570
|
*
|
|
6058
6571
|
* @param lanes Track ids or lane descriptors in the desired lane order.
|
|
6059
6572
|
*/
|
|
@@ -6070,7 +6583,9 @@ var SonareEngine = class _SonareEngine {
|
|
|
6070
6583
|
/**
|
|
6071
6584
|
* Keys one insert of a lane strip from another lane's post-strip pre-fader
|
|
6072
6585
|
* audio (ducking/sidechainRouter inserts). sourceTarget null removes the
|
|
6073
|
-
* binding.
|
|
6586
|
+
* binding. Throws, leaving the existing bindings unchanged, for a lane keying
|
|
6587
|
+
* itself or a binding that would close a cycle over the lane bindings; a
|
|
6588
|
+
* refused binding is never recorded, so it is not replayed on resync.
|
|
6074
6589
|
*/
|
|
6075
6590
|
setLaneSidechain(target, insertIndex, sourceTarget) {
|
|
6076
6591
|
setLaneSidechain(this.mixerContext, target, insertIndex, sourceTarget);
|
|
@@ -6099,19 +6614,17 @@ var SonareEngine = class _SonareEngine {
|
|
|
6099
6614
|
return setBusGain(this.mixerContext, busId, db);
|
|
6100
6615
|
}
|
|
6101
6616
|
setTrackStripJson(target, sceneJson) {
|
|
6617
|
+
decodedInsertSignature(sceneJson, { kind: "track", trackId: 0 });
|
|
6102
6618
|
const laneIndex = this.ensureTrackLane(target);
|
|
6103
6619
|
const trackId = this.trackLaneIds[laneIndex];
|
|
6104
|
-
const {
|
|
6620
|
+
const { insertBaseResets, constructionOverrides } = setTrackStripJson(
|
|
6105
6621
|
this.stripContext,
|
|
6106
6622
|
trackId,
|
|
6107
6623
|
sceneJson,
|
|
6108
6624
|
this.trackStripJson
|
|
6109
6625
|
);
|
|
6110
|
-
if (resetInserts) {
|
|
6111
|
-
this.clearInsertAutomationLanes({ kind: "track", trackId });
|
|
6112
|
-
}
|
|
6113
6626
|
pruneStripSidechains(this.mixerContext, { kind: "track", trackId }, sceneJson);
|
|
6114
|
-
this.syncMixer(
|
|
6627
|
+
this.syncMixer(insertBaseResets, constructionOverrides);
|
|
6115
6628
|
}
|
|
6116
6629
|
setTrackStripEqBand(target, bandIndex, band) {
|
|
6117
6630
|
setTrackStripEqBand(this.stripContext, target, bandIndex, band);
|
|
@@ -6140,6 +6653,14 @@ var SonareEngine = class _SonareEngine {
|
|
|
6140
6653
|
setTrackStripDualPan(target, leftPan, rightPan) {
|
|
6141
6654
|
setTrackStripDualPan(this.stripContext, target, leftPan, rightPan);
|
|
6142
6655
|
}
|
|
6656
|
+
/**
|
|
6657
|
+
* Sets a track lane strip's surround placement (glitch-free, 5 ms placement
|
|
6658
|
+
* glide). Takes effect on a destination wider than stereo, so set `channelCount`
|
|
6659
|
+
* to the layout's plane count. Omitted fields default to a centered point source.
|
|
6660
|
+
*/
|
|
6661
|
+
setTrackStripSurroundPan(target, pan) {
|
|
6662
|
+
setTrackStripSurroundPan(this.stripContext, target, pan);
|
|
6663
|
+
}
|
|
6143
6664
|
setTrackStripChannelDelaySamples(target, delaySamples) {
|
|
6144
6665
|
setTrackStripChannelDelaySamples(this.stripContext, target, delaySamples);
|
|
6145
6666
|
}
|
|
@@ -6168,16 +6689,7 @@ var SonareEngine = class _SonareEngine {
|
|
|
6168
6689
|
setBusStripJson(this.mixerContext, busId, sceneJson);
|
|
6169
6690
|
}
|
|
6170
6691
|
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] : []);
|
|
6692
|
+
setMasterStripJson(this.mixerContext, sceneJson);
|
|
6181
6693
|
}
|
|
6182
6694
|
setMasterStripEqBand(bandIndex, band) {
|
|
6183
6695
|
setMasterStripEqBand(this.stripContext, bandIndex, band);
|
|
@@ -6380,7 +6892,10 @@ var SonareEngine = class _SonareEngine {
|
|
|
6380
6892
|
/**
|
|
6381
6893
|
* Route a track's MIDI to the external output (drained via {@link onMidiOut})
|
|
6382
6894
|
* instead of an internal instrument, so the track plays an external device.
|
|
6383
|
-
* Pass `external=false` to restore internal-synth playback.
|
|
6895
|
+
* Pass `external=false` to restore internal-synth playback. The change takes
|
|
6896
|
+
* effect at the next processed block; switching a destination's route first
|
|
6897
|
+
* releases its notes and resets its controllers through the old route, and
|
|
6898
|
+
* drops its pending MIDI-FX events.
|
|
6384
6899
|
*/
|
|
6385
6900
|
setMidiDestinationExternal(trackId, external) {
|
|
6386
6901
|
setMidiDestinationExternal(this.stripContext, trackId, external);
|
|
@@ -6441,8 +6956,8 @@ var SonareEngine = class _SonareEngine {
|
|
|
6441
6956
|
renderFrame
|
|
6442
6957
|
);
|
|
6443
6958
|
}
|
|
6444
|
-
pushMidiUmp(trackId,
|
|
6445
|
-
pushMidiUmp(this.stripContext, trackId,
|
|
6959
|
+
pushMidiUmp(trackId, words, renderFrame = -1) {
|
|
6960
|
+
pushMidiUmp(this.stripContext, trackId, words, renderFrame);
|
|
6446
6961
|
}
|
|
6447
6962
|
pushMidiSysex(trackId, data, renderFrame = -1) {
|
|
6448
6963
|
pushMidiSysex(this.stripContext, trackId, data, renderFrame);
|
|
@@ -6527,6 +7042,11 @@ var SonareEngine = class _SonareEngine {
|
|
|
6527
7042
|
portTimeSamples
|
|
6528
7043
|
});
|
|
6529
7044
|
}
|
|
7045
|
+
pushMidiInputUmp(words, portTimeSamples = 0) {
|
|
7046
|
+
const copiedWords = words instanceof Uint32Array ? new Uint32Array(words) : words.slice();
|
|
7047
|
+
this.offlineEngine.pushMidiInputUmp(copiedWords, portTimeSamples);
|
|
7048
|
+
this.postSync({ type: "syncMidiInputUmp", words: copiedWords, portTimeSamples });
|
|
7049
|
+
}
|
|
6530
7050
|
pushMidiPanic(renderFrame = -1) {
|
|
6531
7051
|
this.offlineEngine.pushMidiPanic(renderFrame);
|
|
6532
7052
|
this.postSync({ type: "syncMidiPanic", renderFrame });
|
|
@@ -6622,6 +7142,10 @@ var SonareEngine = class _SonareEngine {
|
|
|
6622
7142
|
pollScope() {
|
|
6623
7143
|
return this.realtimeNode.pollScope();
|
|
6624
7144
|
}
|
|
7145
|
+
/** Per-insert gain reduction for a meter target; see {@link SonareRealtimeEngineNode.pollInsertGainReduction}. */
|
|
7146
|
+
pollInsertGainReduction(targetId) {
|
|
7147
|
+
return this.realtimeNode.pollInsertGainReduction(targetId);
|
|
7148
|
+
}
|
|
6625
7149
|
destroy() {
|
|
6626
7150
|
if (this.destroyed) {
|
|
6627
7151
|
return;
|
|
@@ -6724,8 +7248,8 @@ var SonareEngine = class _SonareEngine {
|
|
|
6724
7248
|
mixerLanes() {
|
|
6725
7249
|
return mixerLanes(this.mixerContext);
|
|
6726
7250
|
}
|
|
6727
|
-
syncMixer(
|
|
6728
|
-
syncMixer(this.mixerContext, false,
|
|
7251
|
+
syncMixer(insertBaseResets = [], oneShotInsertParamOverrides = []) {
|
|
7252
|
+
syncMixer(this.mixerContext, false, insertBaseResets, oneShotInsertParamOverrides);
|
|
6729
7253
|
}
|
|
6730
7254
|
insertAutomationTargetKey(target) {
|
|
6731
7255
|
return target.kind === "track" ? `track:${target.trackId}` : target.kind === "bus" ? `bus:${target.busId}` : "master";
|
|
@@ -6803,6 +7327,7 @@ var SonareEngine = class _SonareEngine {
|
|
|
6803
7327
|
trackLaneIds: this.trackLaneIds,
|
|
6804
7328
|
trackSends: this.trackSends,
|
|
6805
7329
|
trackOutputBus: this.trackOutputBus,
|
|
7330
|
+
trackSourceChannelLayout: this.trackSourceChannelLayout,
|
|
6806
7331
|
laneSidechains: this.laneSidechains,
|
|
6807
7332
|
busSidechains: this.busSidechains,
|
|
6808
7333
|
masterSidechains: this.masterSidechains,
|
|
@@ -6815,7 +7340,7 @@ var SonareEngine = class _SonareEngine {
|
|
|
6815
7340
|
ensureTrackLane: (target) => this.ensureTrackLane(target),
|
|
6816
7341
|
ensureBus: (busId) => this.ensureBus(busId),
|
|
6817
7342
|
mixerLanes: () => this.mixerLanes(),
|
|
6818
|
-
syncMixer: (
|
|
7343
|
+
syncMixer: (insertBaseResets, oneShotInsertParamOverrides) => this.syncMixer(insertBaseResets, oneShotInsertParamOverrides),
|
|
6819
7344
|
clearInsertAutomationLanes: (target, forgetResolvedIds) => this.clearInsertAutomationLanes(target, forgetResolvedIds),
|
|
6820
7345
|
sendSmoothedParam: (paramId, value) => this.sendSmoothedParam(paramId, value),
|
|
6821
7346
|
getMasterStripJson: () => this.masterStripJson,
|
|
@@ -6837,7 +7362,8 @@ var SonareEngine = class _SonareEngine {
|
|
|
6837
7362
|
resolveTargetId: (target) => this.resolveTargetId(target),
|
|
6838
7363
|
readStripJson: (target) => cachedStripJson(this.mixerContext, target),
|
|
6839
7364
|
writeStripJson: (target, sceneJson) => cacheStripJson(this.mixerContext, target, sceneJson),
|
|
6840
|
-
insertParamOverrides: this.insertParamOverrides
|
|
7365
|
+
insertParamOverrides: this.insertParamOverrides,
|
|
7366
|
+
clearInsertAutomationLanes: (target) => this.clearInsertAutomationLanes(target)
|
|
6841
7367
|
};
|
|
6842
7368
|
}
|
|
6843
7369
|
// Collaborator surface handed to the automation-lane free functions so they
|
|
@@ -6977,17 +7503,7 @@ var SonareEngine = class _SonareEngine {
|
|
|
6977
7503
|
return resolveTargetId(target);
|
|
6978
7504
|
}
|
|
6979
7505
|
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;
|
|
7506
|
+
return ensureTrackLane(this.mixerContext, target);
|
|
6991
7507
|
}
|
|
6992
7508
|
ensureBus(busId) {
|
|
6993
7509
|
if (!Number.isInteger(busId) || busId <= 0) {
|
|
@@ -7099,6 +7615,14 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
7099
7615
|
options.scopeRingCapacity,
|
|
7100
7616
|
options.scopeBands
|
|
7101
7617
|
) : void 0;
|
|
7618
|
+
this.scopeIntervalFrames = requireIntegerOption(
|
|
7619
|
+
options.scopeIntervalFrames,
|
|
7620
|
+
this.scopeRing ? this.blockSize : 0,
|
|
7621
|
+
"scopeIntervalFrames",
|
|
7622
|
+
0
|
|
7623
|
+
);
|
|
7624
|
+
this.scopeBands = resolveScopeBandCount(options.scopeBands);
|
|
7625
|
+
this.scopeEnabled = this.scopeIntervalFrames > 0 && (this.scopeRing !== void 0 || typeof this.transport?.postMessage === "function");
|
|
7102
7626
|
this.clipPageRequestRing = options.clipPageRequestSharedBuffer ? clipPageRequestRingFromSharedBuffer(
|
|
7103
7627
|
options.clipPageRequestSharedBuffer,
|
|
7104
7628
|
options.clipPageRequestRingCapacity
|
|
@@ -7130,14 +7654,11 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
7130
7654
|
this.monitorBuffers[ch] = this.engine.getMonitorChannelBuffer(ch, this.blockSize);
|
|
7131
7655
|
}
|
|
7132
7656
|
}
|
|
7133
|
-
if (this.
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
this.
|
|
7137
|
-
"scopeIntervalFrames",
|
|
7138
|
-
0
|
|
7657
|
+
if (this.scopeEnabled) {
|
|
7658
|
+
this.engine.configureScopeTelemetry(
|
|
7659
|
+
this.scopeIntervalFrames,
|
|
7660
|
+
Math.min(this.scopeRing?.bands ?? this.scopeBands, SONARE_SCOPE_MAX_BANDS)
|
|
7139
7661
|
);
|
|
7140
|
-
this.engine.configureScopeTelemetry(interval, this.scopeRing.bands);
|
|
7141
7662
|
}
|
|
7142
7663
|
}
|
|
7143
7664
|
process(inputs, outputs) {
|
|
@@ -7398,37 +7919,32 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
7398
7919
|
this.drainCommands(Math.min(this.commandRing.capacity, Math.max(0, write - read)));
|
|
7399
7920
|
}
|
|
7400
7921
|
this.engine.applyCommandsDueNowPreservingFuture();
|
|
7401
|
-
this.engine.settleInsertParameters();
|
|
7402
7922
|
if (message.buses) {
|
|
7403
7923
|
this.engine.setTrackBuses(message.buses);
|
|
7404
7924
|
}
|
|
7405
7925
|
this.engine.setTrackLanes(message.lanes);
|
|
7406
|
-
for (const
|
|
7407
|
-
|
|
7926
|
+
for (const strip of message.trackStrips ?? []) {
|
|
7927
|
+
this.engine.setTrackStripJson(strip.trackId, strip.sceneJson);
|
|
7928
|
+
}
|
|
7929
|
+
for (const strip of message.busStrips ?? []) {
|
|
7930
|
+
this.engine.setBusStripJson(strip.busId, strip.sceneJson);
|
|
7931
|
+
}
|
|
7932
|
+
if (message.masterStripJson) {
|
|
7933
|
+
this.engine.setMasterStripJson(message.masterStripJson);
|
|
7934
|
+
}
|
|
7935
|
+
for (const target of message.insertBaseResets ?? []) {
|
|
7408
7936
|
switch (target.kind) {
|
|
7409
7937
|
case "track":
|
|
7410
7938
|
this.engine.clearTrackInsertParameterBases(target.trackId);
|
|
7411
|
-
this.engine.setTrackStripJson(target.trackId, emptyJson);
|
|
7412
7939
|
break;
|
|
7413
7940
|
case "bus":
|
|
7414
7941
|
this.engine.clearBusInsertParameterBases(target.busId);
|
|
7415
|
-
this.engine.setBusStripJson(target.busId, emptyJson);
|
|
7416
7942
|
break;
|
|
7417
7943
|
case "master":
|
|
7418
7944
|
this.engine.clearMasterInsertParameterBases();
|
|
7419
|
-
this.engine.setMasterStripJson(emptyJson);
|
|
7420
7945
|
break;
|
|
7421
7946
|
}
|
|
7422
7947
|
}
|
|
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
7948
|
for (const binding of message.laneSidechains ?? []) {
|
|
7433
7949
|
this.engine.setLaneSidechain(binding.trackId, binding.insertIndex, binding.sourceTrackId);
|
|
7434
7950
|
}
|
|
@@ -7568,6 +8084,9 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
7568
8084
|
case "syncTrackStripDualPan":
|
|
7569
8085
|
this.engine.setTrackStripDualPan(message.trackId, message.leftPan, message.rightPan);
|
|
7570
8086
|
break;
|
|
8087
|
+
case "syncTrackStripSurroundPan":
|
|
8088
|
+
this.engine.setTrackStripSurroundPan(message.trackId, message.pan);
|
|
8089
|
+
break;
|
|
7571
8090
|
case "syncBusStripPan":
|
|
7572
8091
|
this.engine.setBusStripPan(message.busId, message.pan);
|
|
7573
8092
|
break;
|
|
@@ -7660,7 +8179,11 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
7660
8179
|
);
|
|
7661
8180
|
break;
|
|
7662
8181
|
case "syncMidiUmp":
|
|
7663
|
-
this.engine.pushMidiUmp(
|
|
8182
|
+
this.engine.pushMidiUmp(
|
|
8183
|
+
message.destinationId,
|
|
8184
|
+
message.words ?? [message.word0],
|
|
8185
|
+
message.renderFrame
|
|
8186
|
+
);
|
|
7664
8187
|
break;
|
|
7665
8188
|
case "syncMidiSysex":
|
|
7666
8189
|
this.engine.pushMidiSysex(message.destinationId, message.data, message.renderFrame);
|
|
@@ -7738,6 +8261,9 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
7738
8261
|
message.portTimeSamples
|
|
7739
8262
|
);
|
|
7740
8263
|
break;
|
|
8264
|
+
case "syncMidiInputUmp":
|
|
8265
|
+
this.engine.pushMidiInputUmp(message.words, message.portTimeSamples);
|
|
8266
|
+
break;
|
|
7741
8267
|
}
|
|
7742
8268
|
}
|
|
7743
8269
|
receiveCaptureRequest(message) {
|
|
@@ -7811,6 +8337,26 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
7811
8337
|
});
|
|
7812
8338
|
}
|
|
7813
8339
|
}
|
|
8340
|
+
receiveInsertGainReductionRequest(message) {
|
|
8341
|
+
if (this.closed) {
|
|
8342
|
+
return;
|
|
8343
|
+
}
|
|
8344
|
+
try {
|
|
8345
|
+
this.transport?.postMessage?.({
|
|
8346
|
+
type: "insertGainReductionResponse",
|
|
8347
|
+
requestId: message.requestId,
|
|
8348
|
+
ok: true,
|
|
8349
|
+
values: this.engine.meterTargetInsertGainReduction(message.targetId)
|
|
8350
|
+
});
|
|
8351
|
+
} catch (error) {
|
|
8352
|
+
this.transport?.postMessage?.({
|
|
8353
|
+
type: "insertGainReductionResponse",
|
|
8354
|
+
requestId: message.requestId,
|
|
8355
|
+
ok: false,
|
|
8356
|
+
error: error instanceof Error ? error.message : String(error)
|
|
8357
|
+
});
|
|
8358
|
+
}
|
|
8359
|
+
}
|
|
7814
8360
|
destroy() {
|
|
7815
8361
|
if (!this.closed) {
|
|
7816
8362
|
this.clearPagedClipProviders();
|
|
@@ -7924,6 +8470,9 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
7924
8470
|
this.engine.setTrackMonitorMode(laneIndex, mode, sampleTime);
|
|
7925
8471
|
break;
|
|
7926
8472
|
}
|
|
8473
|
+
case 28 /* ResetMasterLoudnessMeter */:
|
|
8474
|
+
this.engine.resetMasterLoudnessMeter(sampleTime);
|
|
8475
|
+
break;
|
|
7927
8476
|
default:
|
|
7928
8477
|
this.publishTelemetryRecord({
|
|
7929
8478
|
type: 1 /* Error */,
|
|
@@ -8001,6 +8550,8 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
8001
8550
|
}
|
|
8002
8551
|
return;
|
|
8003
8552
|
}
|
|
8553
|
+
const delivered = [];
|
|
8554
|
+
const newestByTarget = /* @__PURE__ */ new Map();
|
|
8004
8555
|
for (const item of this.engine.drainMeterTelemetry(64)) {
|
|
8005
8556
|
const meter = meterFromEngine(item);
|
|
8006
8557
|
if (meter.frame !== this.lastMeterFrame && meter.frame - this.lastMeterFrame < this.meterIntervalFrames) {
|
|
@@ -8009,6 +8560,13 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
8009
8560
|
if (meter.frame !== this.lastMeterFrame) {
|
|
8010
8561
|
this.lastMeterFrame = meter.frame;
|
|
8011
8562
|
}
|
|
8563
|
+
delivered.push(meter);
|
|
8564
|
+
newestByTarget.set(meter.targetId, meter);
|
|
8565
|
+
}
|
|
8566
|
+
for (const meter of delivered) {
|
|
8567
|
+
if (newestByTarget.get(meter.targetId) === meter) {
|
|
8568
|
+
meter.insertGainReductionDb = this.engine.meterTargetInsertGainReduction(meter.targetId);
|
|
8569
|
+
}
|
|
8012
8570
|
if (this.transport?.onMeter) {
|
|
8013
8571
|
this.transport.onMeter(meter);
|
|
8014
8572
|
} else {
|
|
@@ -8026,6 +8584,8 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
8026
8584
|
for (let field = 0; field < 11; field++) {
|
|
8027
8585
|
ring.records[offset + 3 + field] = this.engine.meterScratchValue(field);
|
|
8028
8586
|
}
|
|
8587
|
+
ring.records[offset + 14] = this.engine.meterScratchInputPeakDbL();
|
|
8588
|
+
ring.records[offset + 15] = this.engine.meterScratchInputPeakDbR();
|
|
8029
8589
|
Atomics.store(ring.header, 0, writeIndex + 1);
|
|
8030
8590
|
}
|
|
8031
8591
|
// A snapshot-object ring writer used to live here as well. It was
|
|
@@ -8041,16 +8601,52 @@ var _SonareRealtimeEngineWorkletProcessor = class _SonareRealtimeEngineWorkletPr
|
|
|
8041
8601
|
// silent overrun via firstReadable = max(readIndex, writeIndex - capacity),
|
|
8042
8602
|
// so header slot 3 is left at its initial 0.
|
|
8043
8603
|
// Drains the engine's scope producer (FFT spectrum + goniometer points) into
|
|
8044
|
-
// the lock-free SAB scope ring
|
|
8045
|
-
//
|
|
8604
|
+
// the lock-free SAB scope ring or the bounded postMessage fallback. The SAB
|
|
8605
|
+
// path remains allocation-free; postMessage materialises only records that
|
|
8606
|
+
// are ready to publish.
|
|
8046
8607
|
publishScope() {
|
|
8047
|
-
|
|
8048
|
-
if (!ring) {
|
|
8608
|
+
if (!this.scopeEnabled) {
|
|
8049
8609
|
return;
|
|
8050
8610
|
}
|
|
8611
|
+
const ring = this.scopeRing;
|
|
8612
|
+
const transport = this.transport;
|
|
8051
8613
|
for (let count = 0; count < 64 && this.engine.popScopeTelemetryToScratch(); count++) {
|
|
8052
|
-
|
|
8614
|
+
if (ring) {
|
|
8615
|
+
this.writeScopeScratch(ring);
|
|
8616
|
+
} else {
|
|
8617
|
+
this.postScopeScratch(transport);
|
|
8618
|
+
}
|
|
8619
|
+
}
|
|
8620
|
+
}
|
|
8621
|
+
postScopeScratch(transport) {
|
|
8622
|
+
if (!transport?.postMessage) {
|
|
8623
|
+
return;
|
|
8053
8624
|
}
|
|
8625
|
+
const bandCount = Math.min(
|
|
8626
|
+
SONARE_SCOPE_MAX_BANDS,
|
|
8627
|
+
Math.max(0, Math.trunc(Number(this.engine.scopeScratchBandCount())))
|
|
8628
|
+
);
|
|
8629
|
+
const pointCount = Math.min(
|
|
8630
|
+
SONARE_SCOPE_MAX_POINTS,
|
|
8631
|
+
Math.max(0, Math.trunc(Number(this.engine.scopeScratchPointCount())))
|
|
8632
|
+
);
|
|
8633
|
+
const bands = new Float32Array(bandCount);
|
|
8634
|
+
for (let i = 0; i < bandCount; i++) {
|
|
8635
|
+
bands[i] = this.engine.scopeScratchBand(i);
|
|
8636
|
+
}
|
|
8637
|
+
const points = new Float32Array(pointCount * 2);
|
|
8638
|
+
for (let i = 0; i < pointCount; i++) {
|
|
8639
|
+
points[2 * i] = this.engine.scopeScratchPointLeft(i);
|
|
8640
|
+
points[2 * i + 1] = this.engine.scopeScratchPointRight(i);
|
|
8641
|
+
}
|
|
8642
|
+
const scope = {
|
|
8643
|
+
type: "scope",
|
|
8644
|
+
targetId: this.engine.scopeScratchTargetId(),
|
|
8645
|
+
frame: Number(this.engine.scopeScratchRenderFrame()),
|
|
8646
|
+
bands,
|
|
8647
|
+
points
|
|
8648
|
+
};
|
|
8649
|
+
transport.postMessage(scope, [bands.buffer, points.buffer]);
|
|
8054
8650
|
}
|
|
8055
8651
|
writeScopeScratch(ring) {
|
|
8056
8652
|
const writeIndex = Atomics.load(ring.header, 0);
|
|
@@ -8283,6 +8879,8 @@ function registerSonareRealtimeEngineWorkletProcessor(name = "sonare-realtime-en
|
|
|
8283
8879
|
bridge.receiveCaptureRequest(data);
|
|
8284
8880
|
} else if (isEngineTransportRequestMessage(data)) {
|
|
8285
8881
|
bridge.receiveTransportRequest(data);
|
|
8882
|
+
} else if (isEngineInsertGainReductionRequestMessage(data)) {
|
|
8883
|
+
bridge.receiveInsertGainReductionRequest(data);
|
|
8286
8884
|
} else if (isRecord(data) && typeof data.type === "string" && data.type.startsWith("sync")) {
|
|
8287
8885
|
this.port?.postMessage?.({
|
|
8288
8886
|
type: "syncError",
|
|
@@ -8352,8 +8950,8 @@ var SonareWorkletProcessor = class {
|
|
|
8352
8950
|
*
|
|
8353
8951
|
* `targetId` is always the master and the four LUFS / gain-reduction fields
|
|
8354
8952
|
* are always unavailable here — the mixer worklet does not run the
|
|
8355
|
-
* K-weighting filters
|
|
8356
|
-
* set once rather than per interval.
|
|
8953
|
+
* K-weighting filters or the engine's pre-trim input tap — so finite floor
|
|
8954
|
+
* values are set once rather than per interval.
|
|
8357
8955
|
*/
|
|
8358
8956
|
this.meterScratch = {
|
|
8359
8957
|
type: "meter",
|
|
@@ -8369,7 +8967,9 @@ var SonareWorkletProcessor = class {
|
|
|
8369
8967
|
momentaryLufs: Number.NaN,
|
|
8370
8968
|
shortTermLufs: Number.NaN,
|
|
8371
8969
|
integratedLufs: Number.NaN,
|
|
8372
|
-
gainReductionDb: Number.NaN
|
|
8970
|
+
gainReductionDb: Number.NaN,
|
|
8971
|
+
inputPeakDbL: SONARE_FLOOR_DB,
|
|
8972
|
+
inputPeakDbR: SONARE_FLOOR_DB
|
|
8373
8973
|
};
|
|
8374
8974
|
if (!options.sceneJson) {
|
|
8375
8975
|
throw new Error("sceneJson is required.");
|
|
@@ -8532,7 +9132,9 @@ var SonareWorkletProcessor = class {
|
|
|
8532
9132
|
momentaryLufs: Number.NaN,
|
|
8533
9133
|
shortTermLufs: Number.NaN,
|
|
8534
9134
|
integratedLufs: Number.NaN,
|
|
8535
|
-
gainReductionDb: Number.NaN
|
|
9135
|
+
gainReductionDb: Number.NaN,
|
|
9136
|
+
inputPeakDbL: SONARE_FLOOR_DB,
|
|
9137
|
+
inputPeakDbR: SONARE_FLOOR_DB
|
|
8536
9138
|
};
|
|
8537
9139
|
if (this.transport?.onMeter) {
|
|
8538
9140
|
this.transport.onMeter(meter);
|
|
@@ -8561,6 +9163,8 @@ var SonareWorkletProcessor = class {
|
|
|
8561
9163
|
ring.records[offset + 11] = meter.shortTermLufs;
|
|
8562
9164
|
ring.records[offset + 12] = meter.integratedLufs;
|
|
8563
9165
|
ring.records[offset + 13] = meter.gainReductionDb;
|
|
9166
|
+
ring.records[offset + 14] = meter.inputPeakDbL;
|
|
9167
|
+
ring.records[offset + 15] = meter.inputPeakDbR;
|
|
8564
9168
|
Atomics.store(ring.header, 0, writeIndex + 1);
|
|
8565
9169
|
}
|
|
8566
9170
|
publishSpectrum(left, right) {
|
|
@@ -8613,7 +9217,7 @@ var SonareWorkletProcessor = class {
|
|
|
8613
9217
|
return;
|
|
8614
9218
|
}
|
|
8615
9219
|
const writeIndex = Atomics.load(ring.header, 0);
|
|
8616
|
-
const offset = writeIndex % ring.capacity *
|
|
9220
|
+
const offset = writeIndex % ring.capacity * SONARE_METER_RING_RECORD_FLOATS;
|
|
8617
9221
|
ring.records[offset] = encodeFrameLo(frame);
|
|
8618
9222
|
ring.records[offset + 1] = encodeFrameHi(frame);
|
|
8619
9223
|
ring.records[offset + 2] = bands.length;
|