@libraz/libsonare 1.5.5 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +109 -20
  2. package/dist/analysis.d.ts +5730 -0
  3. package/dist/analysis.js +2464 -0
  4. package/dist/analysis.js.map +1 -0
  5. package/dist/index.d.ts +759 -35
  6. package/dist/index.js +904 -209
  7. package/dist/index.js.map +1 -1
  8. package/dist/schemas/realtime-voice-changer-preset-pack.schema.json +27 -0
  9. package/dist/schemas/realtime-voice-changer-preset.schema.json +140 -0
  10. package/dist/sonare-analysis.js +2 -0
  11. package/dist/sonare-analysis.wasm +0 -0
  12. package/dist/sonare.js +1 -1
  13. package/dist/sonare.wasm +0 -0
  14. package/dist/worker.d.ts +65 -0
  15. package/dist/worker.js +707 -0
  16. package/dist/worker.js.map +1 -0
  17. package/dist/worklet.d.ts +574 -86
  18. package/dist/worklet.js +1634 -235
  19. package/dist/worklet.js.map +1 -1
  20. package/package.json +23 -11
  21. package/src/_chain_config.ts +5 -3
  22. package/src/analysis.ts +137 -0
  23. package/src/analysis_helpers.ts +6 -0
  24. package/src/clip_page_streamer.ts +62 -8
  25. package/src/codes.ts +51 -64
  26. package/src/effects_mastering.ts +1 -0
  27. package/src/errors.ts +1 -0
  28. package/src/feature_core.ts +140 -2
  29. package/src/feature_music.ts +17 -2
  30. package/src/feature_pitch.ts +70 -1
  31. package/src/feature_spectral.ts +231 -5
  32. package/src/feature_spectrogram.ts +159 -0
  33. package/src/features.ts +16 -1
  34. package/src/index.ts +101 -7
  35. package/src/mastering_chain.ts +20 -8
  36. package/src/mastering_core.ts +5 -0
  37. package/src/mastering_dynamics.ts +7 -1
  38. package/src/metering.ts +6 -1
  39. package/src/opfs_clip_pages.ts +26 -1
  40. package/src/project.ts +7 -0
  41. package/src/project_class.ts +62 -8
  42. package/src/project_internal.ts +24 -29
  43. package/src/project_types.ts +69 -10
  44. package/src/public_types.ts +68 -0
  45. package/src/public_types_mastering.ts +22 -0
  46. package/src/public_types_mixing.ts +11 -2
  47. package/src/public_types_music.ts +9 -0
  48. package/src/public_types_spectral.ts +33 -0
  49. package/src/quick_analysis.ts +25 -7
  50. package/src/realtime_engine.ts +153 -3
  51. package/src/realtime_voice_changer.ts +51 -77
  52. package/src/sonare-analysis.js.d.ts +8 -0
  53. package/src/sonare.js.d.ts +276 -6
  54. package/src/streaming_processors.ts +15 -0
  55. package/src/web_midi.ts +36 -4
  56. package/src/worker.ts +196 -0
  57. package/src/worker_client.ts +352 -0
  58. package/src/worker_protocol.ts +59 -0
  59. package/src/worklet/engine-automation.ts +2 -1
  60. package/src/worklet/engine-capture-facade.ts +13 -4
  61. package/src/worklet/engine-clips.ts +12 -3
  62. package/src/worklet/engine-node.ts +212 -4
  63. package/src/worklet/engine-offline.ts +7 -2
  64. package/src/worklet/engine-parameter-facade.ts +26 -5
  65. package/src/worklet/engine-processor.ts +383 -42
  66. package/src/worklet/engine-register.ts +8 -0
  67. package/src/worklet/engine-strips.ts +17 -1
  68. package/src/worklet/engine-sync.ts +2 -6
  69. package/src/worklet/engine-tempo-facade.ts +8 -6
  70. package/src/worklet/engine.ts +380 -13
  71. package/src/worklet/guards.ts +22 -1
  72. package/src/worklet/messages.ts +125 -7
  73. package/src/worklet/protocol.ts +301 -17
  74. package/src/worklet/voice-changer-processor.ts +12 -15
  75. package/src/worklet.ts +20 -1
package/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
  (BPM, key, chords, loudness), master and mix to broadcast loudness, and render
13
13
  MIDI through built-in instruments, all client-side via WebAssembly — the same
14
14
  C++ engine that runs natively, with zero dependencies and no Python or model
15
- weights. 76 named mastering DSP processors implemented against published
15
+ weights. 88 named mastering DSP processors implemented against published
16
16
  references (ITU-R BS.1770-4 true-peak limiting, Linkwitz-Riley crossovers,
17
17
  Vicanek matched-Z biquads, ADAA-antialiased saturation); analysis defaults match
18
18
  librosa where the two overlap.
@@ -31,17 +31,26 @@ Everything runs client-side — no server, nothing uploaded.
31
31
  npm install @libraz/libsonare
32
32
  ```
33
33
 
34
+ For BPM/key/chord detection, feature extraction, and metering without the
35
+ mastering, mixing, or realtime-engine APIs, import the smaller analysis entry:
36
+
37
+ ```typescript
38
+ import { detectBpm, init } from '@libraz/libsonare/analysis';
39
+ ```
40
+
41
+ With emsdk 5.0.2, the analysis binary is 0.86 MiB raw / 347 KiB gzip; the full
42
+ entry is 3.76 MiB raw / 1.26 MiB gzip. The analysis entry deliberately has no
43
+ `masterAudio`, `mixStereo`, `Project`, `Mixer`, or `RealtimeEngine` export.
44
+
34
45
  ## Quick Start
35
46
 
36
47
  `init()` loads the WASM module once; every API is available afterwards. Top-level
37
48
  one-shot functions accept a request object (recommended) or positional arguments.
38
49
 
39
- > **Audio input:** analysis works on decoded `Float32Array` mono samples.
40
- > `Audio.fromMemory` decodes WAV from an in-memory buffer, but the WebAssembly
41
- > build bundles no decoder for compressed formats — use the Web Audio API
42
- > (`decodeAudioData`) for MP3 / M4A / AAC / Opus / FLAC, or the native N-API
43
- > package [`@libraz/libsonare-native`](https://github.com/libraz/libsonare/tree/main/bindings/node)
44
- > to read files from disk.
50
+ > **Audio input:** start with `Audio.fromMemoryWithBrowserFallback(bytes)`. It
51
+ > decodes WAV/MP3 in WASM, then uses the browser's `decodeAudioData` for other
52
+ > browser-supported formats. Pass a decoded mono `Float32Array` only when one is
53
+ > already available.
45
54
 
46
55
  > **Platform constraints:** the WebAssembly build is single-threaded (analysis
47
56
  > runs to completion on the calling thread — there is no non-blocking variant)
@@ -49,17 +58,14 @@ one-shot functions accept a request object (recommended) or positional arguments
49
58
  > to keep the UI responsive.
50
59
 
51
60
  ```typescript
52
- import { init, analyze, masterAudio } from '@libraz/libsonare';
61
+ import { Audio, init } from '@libraz/libsonare';
53
62
 
54
63
  await init();
55
64
 
56
- // Analyze decoded Float32Array mono samples
57
- const { bpm, key } = analyze({ samples, sampleRate });
65
+ const bytes = new Uint8Array(await file.arrayBuffer());
66
+ const audio = await Audio.fromMemoryWithBrowserFallback(bytes);
67
+ const { bpm, key } = audio.analyze();
58
68
  console.log(`BPM: ${bpm} Key: ${key.name}`);
59
-
60
- // Master toward a target loudness with a named preset
61
- const mastered = masterAudio({ samples, sampleRate, preset: 'streaming' });
62
- console.log(mastered.outputLufs, mastered.appliedGainDb);
63
69
  ```
64
70
 
65
71
  Render a MIDI arrangement through a built-in instrument with the headless
@@ -83,16 +89,52 @@ try {
83
89
  }
84
90
  ```
85
91
 
86
- ### Decoding audio in the browser
92
+ ### Using already-decoded audio
87
93
 
88
- The WASM build takes decoded samples, so decode with the Web Audio API first:
94
+ Use `Float32Array` directly when another API already decoded the audio:
89
95
 
90
96
  ```typescript
91
- const buf = await fetch('song.m4a').then((r) => r.arrayBuffer());
92
- const decoded = await new AudioContext().decodeAudioData(buf);
93
- const { bpm, key } = analyze({ samples: decoded.getChannelData(0), sampleRate: decoded.sampleRate });
97
+ const audio = Audio.fromBuffer(decoded.getChannelData(0), decoded.sampleRate);
98
+ const { bpm, key } = audio.analyze();
99
+ ```
100
+
101
+ ### Offline Worker for longer audio
102
+
103
+ For audio longer than roughly 30 seconds, use `OfflineWorkerClient` to keep
104
+ analysis or preset mastering off the UI thread. The published `./worker`
105
+ subpath is resolved automatically. It intentionally exposes only one-shot
106
+ value APIs (`analyze`, BPM/key/chord detection, and `masterAudio`): native
107
+ handles such as `Project`, `Mixer`, and realtime engines stay in their owning
108
+ JavaScript realm.
109
+
110
+ ```typescript
111
+ import { OfflineWorkerClient } from '@libraz/libsonare';
112
+
113
+ const offline = new OfflineWorkerClient();
114
+ const task = offline.analyze(
115
+ { samples, sampleRate },
116
+ {
117
+ onProgress: ({ progress, stage }) => updateProgress(progress, stage),
118
+ // copy: true, // retain `samples`; the default transfers and detaches it
119
+ },
120
+ );
121
+
122
+ cancelButton.onclick = () => task.cancel();
123
+ try {
124
+ const result = await task;
125
+ console.log(result.bpm, result.key.name);
126
+ } finally {
127
+ offline.dispose();
128
+ }
94
129
  ```
95
130
 
131
+ By default the input `Float32Array` is transferred, so its buffer is detached
132
+ on the calling thread. Pass `{ copy: true }` when it must remain usable. Prompt
133
+ cancellation of a running synchronous WASM call uses `SharedArrayBuffer`; serve
134
+ the page with cross-origin isolation (COOP/COEP) when a cancel button must take
135
+ effect immediately. `workerUrl` lets a host point the client at a separately
136
+ hosted copy of `@libraz/libsonare/worker`.
137
+
96
138
  ### Loading the `.wasm` file
97
139
 
98
140
  Bundlers that don't auto-resolve the `.wasm` asset need its URL. Pass a
@@ -109,13 +151,60 @@ From a CDN, `import { init } from 'https://esm.sh/@libraz/libsonare'` resolves t
109
151
  [getting-started guide](https://libsonare.libraz.net/docs/getting-started) for
110
152
  per-bundler setup and the AudioWorklet bridge.
111
153
 
154
+ ### Realtime voice changer preset schemas
155
+
156
+ The published package includes the JSON Schema documents for third-party voice
157
+ changer presets. Resolve them through the package exports rather than copying a
158
+ schema from the repository:
159
+
160
+ ```text
161
+ @libraz/libsonare/schemas/realtime-voice-changer-preset.schema.json
162
+ @libraz/libsonare/schemas/realtime-voice-changer-preset-pack.schema.json
163
+ ```
164
+
165
+ Validate data against the schema before saving it, then pass the JSON text to
166
+ `validateRealtimeVoiceChangerPresetJson()` before applying it. The runtime check
167
+ is authoritative and also rejects malformed JSON such as duplicate keys.
168
+
169
+ ### Bounded-memory OPFS clip streaming
170
+
171
+ For long raw float32 clips stored in OPFS, `attachOpfsClipStream` supplies only
172
+ the current playback window to WASM. It primes the first page, then fetches page
173
+ misses on the main thread and evicts pages outside the configured read-ahead /
174
+ retain-behind window. The AudioWorklet path uses the same helper: the worklet
175
+ posts a bounded batch of misses, and it outputs silence until a page arrives.
176
+
177
+ ```typescript
178
+ import { attachOpfsClipStream } from '@libraz/libsonare';
179
+ import { SonareEngine } from '@libraz/libsonare/worklet';
180
+
181
+ const engine = await SonareEngine.create(audioContext);
182
+ const stream = await attachOpfsClipStream(engine, {
183
+ path: 'takes/lead.f32',
184
+ clipId: 42,
185
+ numChannels: 2,
186
+ numSamples: 48_000 * 600,
187
+ pageFrames: 16_384,
188
+ });
189
+
190
+ // `clipId` must equal the explicit id supplied here.
191
+ engine.addClip(trackId, stream.provider, 0, { id: 42 });
192
+
193
+ // Close the returned binding after removing the clip (or when the host closes).
194
+ stream.binding.close();
195
+ ```
196
+
197
+ The bounded-memory guarantee applies only to an OPFS/page-provider source.
198
+ Passing a `Float32Array[]` to `addClip` keeps that full array in the JavaScript
199
+ heap, so it is appropriate for short clips but does not make long clips bounded.
200
+
112
201
  ## Capabilities
113
202
 
114
203
  Every area below has runnable examples and the full API in the
115
204
  [documentation](https://libsonare.libraz.net/docs/wasm).
116
205
 
117
206
  - **Analysis** — BPM, key (+ candidates), chords, downbeats, sections, melody, tuning; pitch (YIN / pYIN), timbre, and the full spectral feature set (STFT, mel, MFCC, chroma, CQT/VQT, spectral contrast); metering (true-peak, LUFS, correlation, vectorscope, waveform peaks). → [API](https://libsonare.libraz.net/docs/wasm)
118
- - **Mastering** — 76 named DSP processors, the configurable `masteringChain`, 25 named presets via `masterAudio`, and reference-matching. → [Mastering processors](https://libsonare.libraz.net/docs/mastering-processors)
207
+ - **Mastering** — 88 named DSP processors, the configurable `masteringChain`, 25 named presets via `masterAudio`, and reference-matching. → [Mastering processors](https://libsonare.libraz.net/docs/mastering-processors)
119
208
  - **Mixing** — offline `mixStereo` and the block-based `Mixer` with scene presets. → [Mixing](https://libsonare.libraz.net/docs/mixing)
120
209
  - **Editing DSP** — time-stretch, pitch-shift, HPSS (+ residual), phase vocoder, normalize, trim, remix. → [Editing DSP](https://libsonare.libraz.net/docs/editing-dsp)
121
210
  - **Room acoustics** — blind RT60 / EDT, impulse-response clarity metrics, RIR synthesis, room estimation and morphing. → [Room acoustics](https://libsonare.libraz.net/docs/acoustic-analysis)