@libraz/libsonare 1.4.1 → 1.5.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 (66) hide show
  1. package/README.md +51 -20
  2. package/dist/index.d.ts +5416 -1
  3. package/dist/index.js +938 -583
  4. package/dist/index.js.map +1 -1
  5. package/dist/sonare.js +2 -2
  6. package/dist/sonare.wasm +0 -0
  7. package/dist/worklet.d.ts +1083 -5227
  8. package/dist/worklet.js +2683 -2451
  9. package/dist/worklet.js.map +1 -1
  10. package/package.json +4 -9
  11. package/src/clip_page_streamer.ts +298 -0
  12. package/src/effects_mastering.ts +85 -1089
  13. package/src/effects_transform.ts +286 -0
  14. package/src/effects_voice_change.ts +118 -0
  15. package/src/feature_music.ts +5 -2
  16. package/src/feature_spectrogram.ts +42 -2
  17. package/src/features.ts +1 -0
  18. package/src/index.ts +23 -0
  19. package/src/mastering_chain.ts +200 -0
  20. package/src/mastering_core.ts +248 -0
  21. package/src/mastering_dynamics.ts +105 -0
  22. package/src/mastering_repair.ts +161 -0
  23. package/src/mixer.ts +8 -0
  24. package/src/mixing_oneshot.ts +54 -0
  25. package/src/module_state.ts +1 -2
  26. package/src/project.ts +71 -1712
  27. package/src/project_class.ts +871 -0
  28. package/src/project_internal.ts +333 -0
  29. package/src/project_synth.ts +43 -0
  30. package/src/project_types.ts +570 -0
  31. package/src/public_types.ts +6 -1221
  32. package/src/public_types_acoustic.ts +115 -0
  33. package/src/public_types_mastering.ts +333 -0
  34. package/src/public_types_mixing.ts +97 -0
  35. package/src/public_types_music.ts +352 -0
  36. package/src/public_types_realtime.ts +163 -0
  37. package/src/public_types_spectral.ts +194 -0
  38. package/src/realtime_engine.ts +94 -0
  39. package/src/sonare.js.d.ts +117 -38
  40. package/src/stream_analyzer.ts +3 -0
  41. package/src/stream_types.ts +4 -0
  42. package/src/worklet/engine-automation.ts +73 -0
  43. package/src/worklet/engine-capture-facade.ts +80 -0
  44. package/src/worklet/engine-clips.ts +71 -0
  45. package/src/worklet/engine-markers.ts +93 -0
  46. package/src/worklet/engine-mixer-facade.ts +186 -0
  47. package/src/worklet/engine-node.ts +451 -0
  48. package/src/worklet/engine-offline.ts +162 -0
  49. package/src/worklet/engine-options.ts +13 -0
  50. package/src/worklet/engine-parameter-facade.ts +172 -0
  51. package/src/worklet/engine-processor.ts +764 -0
  52. package/src/worklet/engine-register.ts +136 -0
  53. package/src/worklet/engine-strips.ts +315 -0
  54. package/src/worklet/engine-sync.ts +94 -0
  55. package/src/worklet/engine-tempo-facade.ts +141 -0
  56. package/src/worklet/engine.ts +998 -0
  57. package/src/worklet/guards.ts +14 -1
  58. package/src/worklet/messages.ts +60 -20
  59. package/src/worklet/mixer-processor.ts +368 -0
  60. package/src/worklet/protocol.ts +3 -0
  61. package/src/worklet/voice-changer-processor.ts +246 -0
  62. package/src/worklet.ts +20 -3549
  63. package/dist/sonare-rt-module.js +0 -2
  64. package/dist/sonare-rt.js +0 -2
  65. package/dist/sonare-rt.wasm +0 -0
  66. package/src/sonare-rt.d.ts +0 -93
package/README.md CHANGED
@@ -7,13 +7,14 @@
7
7
  [![License](https://img.shields.io/github/license/libraz/libsonare)](https://github.com/libraz/libsonare/blob/main/LICENSE)
8
8
  [![PyPI](https://img.shields.io/pypi/v/libsonare?label=PyPI)](https://pypi.org/project/libsonare/)
9
9
 
10
- A dependency-free audio DSP toolkit for browser and Node.js via WebAssembly —
11
- librosa-compatible analysis plus broadcast-grade mastering, mixing, and editing.
12
- The same C++ processors run client-side in the browser: 66 named mastering DSP
13
- processors implemented against published references (ITU-R BS.1770-4 true-peak
14
- limiting, Linkwitz-Riley crossovers, Vicanek matched-Z biquads, ADAA-antialiased
15
- saturation), with analysis defaults matching librosa — Apache-2.0, no Python,
16
- no model weights.
10
+ **Turn audio into data and back — entirely in the browser.** Analyze songs
11
+ (BPM, key, chords, loudness), master and mix to broadcast loudness, and render
12
+ MIDI through built-in instruments, all client-side via WebAssembly — the same
13
+ C++ engine that runs natively, with zero dependencies and no Python or model
14
+ weights. 66 named mastering DSP processors implemented against published
15
+ references (ITU-R BS.1770-4 true-peak limiting, Linkwitz-Riley crossovers,
16
+ Vicanek matched-Z biquads, ADAA-antialiased saturation); analysis defaults match
17
+ librosa where the two overlap.
17
18
 
18
19
  > **Audio input:** This package expects already-decoded `Float32Array` mono
19
20
  > samples (it does not bundle a file decoder). Use the Web Audio API in the
@@ -124,7 +125,8 @@ import { init, analyzeImpulseResponse, detectAcoustic } from '@libraz/libsonare'
124
125
 
125
126
  await init();
126
127
 
127
- const blind = detectAcoustic(samples, sampleRate, 6, 24, 30.0, 10.0);
128
+ // Blind estimation from ordinary audio; tuning options (nOctaveBands, …) are optional.
129
+ const blind = detectAcoustic(samples, sampleRate);
128
130
  const room = analyzeImpulseResponse(irSamples, sampleRate);
129
131
  console.log(blind.rt60, room.c50);
130
132
  ```
@@ -245,16 +247,15 @@ import { init, masteringChain, masteringChainStereo } from '@libraz/libsonare';
245
247
 
246
248
  await init();
247
249
 
250
+ // Config is a tree of processor sections; set only what you want to change.
248
251
  const mastered = masteringChain(samples, sampleRate, {
249
- eq: { tiltDb: 1.0 },
250
252
  dynamics: { compressor: { thresholdDb: -24, ratio: 1.5 } },
251
- saturation: { tape: { driveDb: 1.0, saturation: 0.2 } },
252
- loudness: { targetLufs: -14, ceilingDb: -1, truePeakOversample: 4 },
253
+ loudness: { targetLufs: -14, ceilingDb: -1 },
253
254
  });
254
255
 
255
256
  const stereo = masteringChainStereo(left, right, sampleRate, {
256
- stereo: { imager: { width: 1.1 }, monoMaker: { amount: 0.2 } },
257
- loudness: { targetLufs: -14, ceilingDb: -1, truePeakOversample: 4 },
257
+ stereo: { imager: { width: 1.1 } },
258
+ loudness: { targetLufs: -14, ceilingDb: -1 },
258
259
  });
259
260
  ```
260
261
 
@@ -495,11 +496,42 @@ Capabilities:
495
496
  `renderOffline`, `bounceOffline`, `freezeOffline`.
496
497
  - **Clip page providers**: `createClipPageProvider` + `supplyClipPage` for
497
498
  streaming large clip audio in pages; pair with the OPFS helpers
498
- (`createOpfsClipPageProvider`).
499
+ (`createOpfsClipPageProvider`) and the bounded-memory `ClipPageStreamer`
500
+ (see below) so a long multitrack arrangement never holds its full PCM in
501
+ WASM memory.
499
502
  - **Telemetry**: `drainTelemetry` / `drainMeterTelemetry`. Inspect runtime
500
503
  capabilities (ABI compatibility, SharedArrayBuffer/Atomics) via
501
504
  `engineCapabilities()`.
502
505
 
506
+ #### Bounded-memory clip streaming
507
+
508
+ `ClipPageStreamer` keeps OPFS-paged clips fed within a sliding window around the
509
+ playback position, evicting pages that fall outside it. Resident memory per clip
510
+ is bounded to `retainBehindPages + readAheadPages + 1` pages regardless of clip
511
+ length. `attachOpfsClipStream` wires the provider, primes the leading page, and
512
+ registers it in one call; `setClips` schedules the returned `provider`, and
513
+ `pump()` (called on your control-thread tick) services page misses.
514
+
515
+ ```typescript
516
+ import { ClipPageStreamer, attachOpfsClipStream, RealtimeEngine } from '@libraz/libsonare';
517
+
518
+ const engine = new RealtimeEngine(48000, 128);
519
+ const streamer = new ClipPageStreamer(engine, { readAheadPages: 2, retainBehindPages: 1 });
520
+
521
+ const { provider } = await attachOpfsClipStream(streamer, engine, {
522
+ path: 'clips/vocal.f32',
523
+ clipId: 1,
524
+ numChannels: 2,
525
+ numSamples: 26_460_000, // ~10 min at 44.1 kHz, never fully resident
526
+ pageFrames: 65_536,
527
+ });
528
+ engine.setClips([{ id: 1, pageProvider: provider, startPpq: 0 }]);
529
+ engine.play();
530
+
531
+ // On each animation frame / control tick:
532
+ await streamer.pump(); // fetch upcoming pages, evict old ones
533
+ ```
534
+
503
535
  ### Real-time voice changer
504
536
 
505
537
  `RealtimeVoiceChanger` runs a block-by-block voice transformation chain (retune,
@@ -520,7 +552,7 @@ try {
520
552
  }
521
553
 
522
554
  // Whole-buffer convenience wrapper (constructs/prepares/disposes internally).
523
- const processed = voiceChangeRealtime(samples, { preset: 'deep-narrator', sampleRate: 48000 });
555
+ const processed = voiceChangeRealtime(samples, 48000, 'deep-narrator');
524
556
  ```
525
557
 
526
558
  For a simple offline pitch + formant shift without the full chain, use
@@ -627,8 +659,8 @@ function readMeters() {
627
659
 
628
660
  For browser DAW-style playback, `SonareEngine` keeps a main-thread
629
661
  `RealtimeEngine` mirror for offline renders and synchronizes the live worklet
630
- engine through control messages. The default runtime target is the embind engine;
631
- the `sonare-rt` runtime remains a transport-focused fallback.
662
+ engine through control messages. There is a single runtime: the full-featured
663
+ embind engine runs both the main-thread mirror and the AudioWorklet.
632
664
 
633
665
  ```typescript
634
666
  import { init } from '@libraz/libsonare';
@@ -665,8 +697,7 @@ Studio integration notes:
665
697
  `sync*`, `captureRequest`, and `transportRequest` message used above to that
666
698
  allowlist; otherwise the host may silently drop the new control messages.
667
699
  - If a host vendors built worklet bundles, regenerate and reimport
668
- `worklet.js`, `worklet.d.ts`, `sonare.js`, `sonare.wasm`,
669
- `sonare-rt.js`, `sonare-rt-module.js`, and `sonare-rt.wasm` together.
700
+ `worklet.js`, `worklet.d.ts`, `sonare.js`, and `sonare.wasm` together.
670
701
 
671
702
  ### Progress callback
672
703
 
@@ -757,7 +788,7 @@ try {
757
788
  - **Pitch**: YIN, pYIN algorithms with optional `fillNa`
758
789
  - **Decomposition & loudness**: NMF decomposition, nearest-neighbour filtering, multichannel LUFS, EBU R128 LRA
759
790
  - **Streaming**: Real-time analysis with progressive estimates; streaming mastering chain, equalizer, and retune
760
- - **Instruments**: built-in synth, patch-driven NativeSynth, SoundFont (SF2) player — bound to `Project` bounces or the `RealtimeEngine`
791
+ - **Instruments**: built-in synth, patch-driven NativeSynth (12 synthesis engines, incl. physically-modeled piano/strings/winds — being tuned over time), SoundFont (SF2) player — bound to `Project` bounces or the `RealtimeEngine`
761
792
  - **Real-time**: `RealtimeEngine` transport/MIDI/render, `RealtimeVoiceChanger`, AudioWorklet bridge
762
793
  - **Room acoustics**: blind RT60/EDT, impulse-response clarity metrics, RIR synthesis, room estimation, room morphing
763
794
  - **Headless DAW**: `Project` arrangement model — audio/MIDI tracks & clips, undo/redo, MIDI sequencing, clip warp, SMF / MIDI 2.0 Clip File I/O, deterministic JSON, offline `bounce`