@libraz/libsonare 1.8.0 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +2 -2
  2. package/dist/_effects_common.d.ts +2 -1
  3. package/dist/_effects_common.d.ts.map +1 -1
  4. package/dist/analysis.js +1 -0
  5. package/dist/analysis.js.map +1 -1
  6. package/dist/effects_mastering.d.ts +2 -2
  7. package/dist/effects_mastering.d.ts.map +1 -1
  8. package/dist/effects_note_ops.d.ts +55 -30
  9. package/dist/effects_note_ops.d.ts.map +1 -1
  10. package/dist/effects_timepitch.d.ts +17 -12
  11. package/dist/effects_timepitch.d.ts.map +1 -1
  12. package/dist/feature_decompose.d.ts +1 -1
  13. package/dist/feature_decompose.d.ts.map +1 -1
  14. package/dist/index.d.ts +3 -3
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +216 -60
  17. package/dist/index.js.map +1 -1
  18. package/dist/mastering_core.d.ts +27 -1
  19. package/dist/mastering_core.d.ts.map +1 -1
  20. package/dist/mixer.d.ts.map +1 -1
  21. package/dist/project_types.d.ts +7 -5
  22. package/dist/project_types.d.ts.map +1 -1
  23. package/dist/public_types_mastering.d.ts +19 -1
  24. package/dist/public_types_mastering.d.ts.map +1 -1
  25. package/dist/public_types_playback.d.ts +1 -0
  26. package/dist/public_types_playback.d.ts.map +1 -1
  27. package/dist/public_types_spectral.d.ts +5 -5
  28. package/dist/public_types_spectral.d.ts.map +1 -1
  29. package/dist/realtime_engine.d.ts +49 -6
  30. package/dist/realtime_engine.d.ts.map +1 -1
  31. package/dist/sonare-analysis.wasm +0 -0
  32. package/dist/sonare.d.ts +36 -0
  33. package/dist/sonare.js +1 -1
  34. package/dist/sonare.wasm +0 -0
  35. package/dist/streaming_processors.d.ts +5 -0
  36. package/dist/streaming_processors.d.ts.map +1 -1
  37. package/dist/worker.js.map +1 -1
  38. package/dist/worklet/engine-mixer-facade.d.ts +40 -4
  39. package/dist/worklet/engine-mixer-facade.d.ts.map +1 -1
  40. package/dist/worklet/engine-node.d.ts +2 -0
  41. package/dist/worklet/engine-node.d.ts.map +1 -1
  42. package/dist/worklet/engine-processor.d.ts +4 -0
  43. package/dist/worklet/engine-processor.d.ts.map +1 -1
  44. package/dist/worklet/engine-strips.d.ts +4 -2
  45. package/dist/worklet/engine-strips.d.ts.map +1 -1
  46. package/dist/worklet/engine-sync.d.ts +4 -2
  47. package/dist/worklet/engine-sync.d.ts.map +1 -1
  48. package/dist/worklet/engine.d.ts +27 -6
  49. package/dist/worklet/engine.d.ts.map +1 -1
  50. package/dist/worklet/guards.d.ts +7 -1
  51. package/dist/worklet/guards.d.ts.map +1 -1
  52. package/dist/worklet/messages.d.ts +4 -4
  53. package/dist/worklet/messages.d.ts.map +1 -1
  54. package/dist/worklet/mixer-processor.d.ts +2 -2
  55. package/dist/worklet/mixer-processor.d.ts.map +1 -1
  56. package/dist/worklet/protocol.d.ts +10 -2
  57. package/dist/worklet/protocol.d.ts.map +1 -1
  58. package/dist/worklet.js +585 -188
  59. package/dist/worklet.js.map +1 -1
  60. package/package.json +1 -1
  61. package/src/_effects_common.ts +36 -6
  62. package/src/effects_mastering.ts +4 -0
  63. package/src/effects_note_ops.ts +92 -44
  64. package/src/effects_timepitch.ts +42 -31
  65. package/src/feature_decompose.ts +2 -2
  66. package/src/index.ts +6 -0
  67. package/src/mastering_core.ts +95 -0
  68. package/src/mixer.ts +39 -19
  69. package/src/project_types.ts +7 -5
  70. package/src/public_types_mastering.ts +21 -0
  71. package/src/public_types_playback.ts +1 -0
  72. package/src/public_types_spectral.ts +5 -5
  73. package/src/realtime_engine.ts +71 -15
  74. package/src/sonare.js.d.ts +36 -0
  75. package/src/streaming_processors.ts +8 -0
  76. package/src/worklet/engine-mixer-facade.ts +420 -86
  77. package/src/worklet/engine-node.ts +22 -4
  78. package/src/worklet/engine-processor.ts +83 -33
  79. package/src/worklet/engine-strips.ts +5 -10
  80. package/src/worklet/engine-sync.ts +6 -1
  81. package/src/worklet/engine.ts +49 -37
  82. package/src/worklet/guards.ts +55 -0
  83. package/src/worklet/messages.ts +4 -2
  84. package/src/worklet/mixer-processor.ts +10 -3
  85. package/src/worklet/protocol.ts +29 -8
@@ -15,6 +15,7 @@ import {
15
15
  meterRingFromSharedBuffer,
16
16
  type SharedMeterRingWriter,
17
17
  type SharedSpectrumRingWriter,
18
+ SONARE_FLOOR_DB,
18
19
  SONARE_METER_RING_RECORD_FLOATS,
19
20
  type SonareWorkletMeterSnapshot,
20
21
  type SonareWorkletSpectrumSnapshot,
@@ -47,8 +48,8 @@ export class SonareWorkletProcessor {
47
48
  *
48
49
  * `targetId` is always the master and the four LUFS / gain-reduction fields
49
50
  * are always unavailable here — the mixer worklet does not run the
50
- * K-weighting filters, and a floor value would read as silence — so both are
51
- * set once rather than per interval.
51
+ * K-weighting filters or the engine's pre-trim input tap — so finite floor
52
+ * values are set once rather than per interval.
52
53
  */
53
54
  private readonly meterScratch: SonareWorkletMeterSnapshot = {
54
55
  type: 'meter',
@@ -65,6 +66,8 @@ export class SonareWorkletProcessor {
65
66
  shortTermLufs: Number.NaN,
66
67
  integratedLufs: Number.NaN,
67
68
  gainReductionDb: Number.NaN,
69
+ inputPeakDbL: SONARE_FLOOR_DB,
70
+ inputPeakDbR: SONARE_FLOOR_DB,
68
71
  };
69
72
  private spectrumRing?: SharedSpectrumRingWriter;
70
73
  private spectrumBands: Float32Array;
@@ -276,6 +279,8 @@ export class SonareWorkletProcessor {
276
279
  shortTermLufs: Number.NaN,
277
280
  integratedLufs: Number.NaN,
278
281
  gainReductionDb: Number.NaN,
282
+ inputPeakDbL: SONARE_FLOOR_DB,
283
+ inputPeakDbR: SONARE_FLOOR_DB,
279
284
  };
280
285
  // Alternative channels for one record, not a broadcast pair: a transport
281
286
  // that supplies both (the engine registration resolves both to
@@ -309,6 +314,8 @@ export class SonareWorkletProcessor {
309
314
  ring.records[offset + 11] = meter.shortTermLufs;
310
315
  ring.records[offset + 12] = meter.integratedLufs;
311
316
  ring.records[offset + 13] = meter.gainReductionDb;
317
+ ring.records[offset + 14] = meter.inputPeakDbL;
318
+ ring.records[offset + 15] = meter.inputPeakDbR;
312
319
  Atomics.store(ring.header, 0, writeIndex + 1);
313
320
  // writeIndex is a free-running monotonic counter, so an overflow guard here
314
321
  // would fire on essentially every write past the first `capacity` records
@@ -377,7 +384,7 @@ export class SonareWorkletProcessor {
377
384
  return;
378
385
  }
379
386
  const writeIndex = Atomics.load(ring.header, 0);
380
- const offset = (writeIndex % ring.capacity) * ring.recordFloats;
387
+ const offset = (writeIndex % ring.capacity) * SONARE_METER_RING_RECORD_FLOATS;
381
388
  ring.records[offset] = encodeFrameLo(frame);
382
389
  ring.records[offset + 1] = encodeFrameHi(frame);
383
390
  ring.records[offset + 2] = bands.length;
@@ -41,6 +41,10 @@ export interface SonareWorkletMeterSnapshot {
41
41
  shortTermLufs: number;
42
42
  integratedLufs: number;
43
43
  gainReductionDb: number;
44
+ /** Maximum pre-trim input peak for the left channel, in dBFS. */
45
+ inputPeakDbL: number;
46
+ /** Maximum pre-trim input peak for the right channel, in dBFS. */
47
+ inputPeakDbR: number;
44
48
  }
45
49
 
46
50
  export interface SonareWorkletSpectrumSnapshot {
@@ -52,18 +56,21 @@ export interface SonareWorkletSpectrumSnapshot {
52
56
  export const SONARE_METER_RING_HEADER_INTS = 4;
53
57
  // Record layout: [frameLo, frameHi, targetId, peakDbL, peakDbR, rmsDbL, rmsDbR,
54
58
  // correlation, truePeakDbL, truePeakDbR, momentaryLufs, shortTermLufs,
55
- // integratedLufs, gainReductionDb].
59
+ // integratedLufs, gainReductionDb, inputPeakDbL, inputPeakDbR].
56
60
  // The sample-frame index is monotonically increasing and quickly exceeds the
57
61
  // 2^24 exact-integer range of a single Float32 slot (~349 s at 48 kHz), so it is
58
62
  // stored split across two Float32 lanes (low 24 bits + high bits) for exact
59
63
  // reconstruction. See encodeFrameLo/encodeFrameHi/decodeFrame.
60
- export const SONARE_METER_RING_RECORD_FLOATS = 14;
64
+ export const SONARE_METER_RING_RECORD_FLOATS = 16;
61
65
  export const SONARE_SPECTRUM_RING_HEADER_INTS = 5;
62
66
  // Scope ring header: [writeIndex, capacity, recordFloats, bands, maxPoints,
63
67
  // reserved]. Record layout: [frameLo, frameHi, targetId, bandCount, pointCount,
64
68
  // band0..band(bands-1), l0, r0, l1, r1, ... (maxPoints stereo pairs)].
65
69
  export const SONARE_SCOPE_RING_HEADER_INTS = 6;
66
70
  export const SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS = 5;
71
+ /** Scope band and goniometer point counts used when a caller supplies none. */
72
+ export const SONARE_SCOPE_DEFAULT_BANDS = 48;
73
+ export const SONARE_SCOPE_DEFAULT_MAX_POINTS = 32;
67
74
 
68
75
  /** Base for splitting a frame index into two exactly-representable Float32 lanes. */
69
76
  const SONARE_FRAME_LANE_BASE = 0x1000000; // 2^24
@@ -121,6 +128,10 @@ export enum SonareEngineCommandType {
121
128
  // Queueable lane monitor-mode transition. The worklet command vocabulary
122
129
  // deliberately leaves 18..25 unused; this is the stable ABI-v3 ordinal.
123
130
  SetTrackMonitorMode = 26,
131
+ // Queueable master-meter integrated-loudness reset. Numeric value 28 mirrors
132
+ // rt::CommandType::kResetMasterMeterIntegrated; 27 remains the appended MIDI
133
+ // UMP slot command in the native vocabulary.
134
+ ResetMasterLoudnessMeter = 28,
124
135
  }
125
136
 
126
137
  export enum SonareEngineTelemetryType {
@@ -387,6 +398,8 @@ export function readSonareMeterRingBuffer(
387
398
  shortTermLufs: ring.records[offset + 11],
388
399
  integratedLufs: ring.records[offset + 12],
389
400
  gainReductionDb: ring.records[offset + 13],
401
+ inputPeakDbL: ring.records[offset + 14],
402
+ inputPeakDbR: ring.records[offset + 15],
390
403
  });
391
404
  }
392
405
  return { nextReadIndex: writeIndex, meters };
@@ -456,8 +469,8 @@ export function sonareScopeRingRecordFloats(bands: number, maxPoints: number): n
456
469
 
457
470
  export function sonareScopeRingBufferByteLength(
458
471
  capacity: number,
459
- bands = 48,
460
- maxPoints = 32,
472
+ bands = SONARE_SCOPE_DEFAULT_BANDS,
473
+ maxPoints = SONARE_SCOPE_DEFAULT_MAX_POINTS,
461
474
  ): number {
462
475
  const clampedCapacity = Math.max(1, Math.floor(capacity));
463
476
  const clampedBands = Math.max(1, Math.floor(bands));
@@ -472,8 +485,8 @@ export function sonareScopeRingBufferByteLength(
472
485
 
473
486
  export function createSonareScopeRingBuffer(
474
487
  capacity = 64,
475
- bands = 48,
476
- maxPoints = 32,
488
+ bands = SONARE_SCOPE_DEFAULT_BANDS,
489
+ maxPoints = SONARE_SCOPE_DEFAULT_MAX_POINTS,
477
490
  ): SonareScopeRingBuffer {
478
491
  const clampedCapacity = Math.max(1, Math.floor(capacity));
479
492
  const clampedBands = Math.max(1, Math.floor(bands));
@@ -552,8 +565,14 @@ export function scopeRingFromSharedBuffer(
552
565
  const existingBands = Atomics.load(header, 3);
553
566
  const existingMaxPoints = Atomics.load(header, 4);
554
567
  const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));
555
- const bands = Math.max(1, Math.floor(existingBands || fallbackBands || 48));
556
- const maxPoints = Math.max(0, Math.floor(existingMaxPoints || (fallbackMaxPoints ?? 32)));
568
+ const bands = Math.max(
569
+ 1,
570
+ Math.floor(existingBands || fallbackBands || SONARE_SCOPE_DEFAULT_BANDS),
571
+ );
572
+ const maxPoints = Math.max(
573
+ 0,
574
+ Math.floor(existingMaxPoints || (fallbackMaxPoints ?? SONARE_SCOPE_DEFAULT_MAX_POINTS)),
575
+ );
557
576
  const recordFloats = sonareScopeRingRecordFloats(bands, maxPoints);
558
577
  const minBytes = sonareScopeRingBufferByteLength(capacity, bands, maxPoints);
559
578
  if (sharedBuffer.byteLength < minBytes) {
@@ -1102,6 +1121,8 @@ export function meterFromEngine(meter: EngineMeterTelemetry): SonareWorkletMeter
1102
1121
  shortTermLufs: meter.shortTermLufs,
1103
1122
  integratedLufs: meter.integratedLufs,
1104
1123
  gainReductionDb: meter.gainReductionDb,
1124
+ inputPeakDbL: meter.inputPeakDbL,
1125
+ inputPeakDbR: meter.inputPeakDbR,
1105
1126
  };
1106
1127
  }
1107
1128