@libraz/libsonare 1.2.2 → 1.3.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 (44) hide show
  1. package/README.md +38 -1
  2. package/dist/index.d.ts +1 -2722
  3. package/dist/index.js +3659 -1896
  4. package/dist/index.js.map +1 -1
  5. package/dist/sonare-rt-module.js +1 -1
  6. package/dist/sonare-rt.js +1 -1
  7. package/dist/sonare-rt.wasm +0 -0
  8. package/dist/sonare.js +1 -1
  9. package/dist/sonare.wasm +0 -0
  10. package/dist/worklet.d.ts +4827 -455
  11. package/dist/worklet.js +1076 -494
  12. package/dist/worklet.js.map +1 -1
  13. package/package.json +2 -1
  14. package/src/analysis_helpers.ts +152 -0
  15. package/src/audio.ts +493 -0
  16. package/src/codes.ts +56 -0
  17. package/src/effects_mastering.ts +964 -0
  18. package/src/feature_core.ts +248 -0
  19. package/src/feature_music.ts +419 -0
  20. package/src/feature_pitch.ts +80 -0
  21. package/src/feature_resample.ts +21 -0
  22. package/src/feature_spectral.ts +330 -0
  23. package/src/feature_spectrogram.ts +454 -0
  24. package/src/features.ts +84 -0
  25. package/src/index.ts +352 -4793
  26. package/src/live_audio.ts +45 -0
  27. package/src/metering.ts +380 -0
  28. package/src/mixer.ts +523 -0
  29. package/src/module_state.ts +14 -0
  30. package/src/opfs_clip_pages.ts +188 -0
  31. package/src/project.ts +1614 -0
  32. package/src/public_types.ts +244 -2
  33. package/src/quick_analysis.ts +508 -0
  34. package/src/realtime_engine.ts +667 -0
  35. package/src/realtime_voice_changer.ts +275 -0
  36. package/src/scale.ts +42 -0
  37. package/src/sonare.js.d.ts +386 -4
  38. package/src/stream_analyzer.ts +275 -0
  39. package/src/stream_types.ts +29 -1
  40. package/src/streaming_mixing.ts +18 -0
  41. package/src/streaming_processors.ts +335 -0
  42. package/src/validation.ts +82 -0
  43. package/src/web_midi.ts +367 -0
  44. package/src/worklet.ts +525 -81
@@ -0,0 +1,80 @@
1
+ import { getSonareModule } from './module_state';
2
+ import type { PitchResult } from './public_types';
3
+
4
+ function requireModule() {
5
+ return getSonareModule();
6
+ }
7
+
8
+ // ============================================================================
9
+ // Features - Pitch
10
+ // ============================================================================
11
+
12
+ /**
13
+ * Detect pitch using YIN algorithm.
14
+ *
15
+ * @param samples - Audio samples (mono, float32)
16
+ * @param sampleRate - Sample rate in Hz (default: 22050)
17
+ * @param frameLength - Frame length (default: 2048)
18
+ * @param hopLength - Hop length (default: 512)
19
+ * @param fmin - Minimum frequency in Hz (default: 65)
20
+ * @param fmax - Maximum frequency in Hz (default: 2093)
21
+ * @param threshold - YIN threshold (default: 0.3)
22
+ * @param fillNa - If true, return 0 for unvoiced f0 frames; otherwise keep NaN (default: false)
23
+ * @returns Pitch detection result
24
+ */
25
+ export function pitchYin(
26
+ samples: Float32Array,
27
+ sampleRate = 22050,
28
+ frameLength = 2048,
29
+ hopLength = 512,
30
+ fmin = 65.0,
31
+ fmax = 2093.0,
32
+ threshold = 0.3,
33
+ fillNa = false,
34
+ ): PitchResult {
35
+ return requireModule().pitchYin(
36
+ samples,
37
+ sampleRate,
38
+ frameLength,
39
+ hopLength,
40
+ fmin,
41
+ fmax,
42
+ threshold,
43
+ fillNa,
44
+ );
45
+ }
46
+
47
+ /**
48
+ * Detect pitch using pYIN algorithm (probabilistic YIN with HMM smoothing).
49
+ *
50
+ * @param samples - Audio samples (mono, float32)
51
+ * @param sampleRate - Sample rate in Hz (default: 22050)
52
+ * @param frameLength - Frame length (default: 2048)
53
+ * @param hopLength - Hop length (default: 512)
54
+ * @param fmin - Minimum frequency in Hz (default: 65)
55
+ * @param fmax - Maximum frequency in Hz (default: 2093)
56
+ * @param threshold - YIN threshold (default: 0.3)
57
+ * @param fillNa - If true, return 0 for unvoiced f0 frames; otherwise keep NaN (default: false)
58
+ * @returns Pitch detection result
59
+ */
60
+ export function pitchPyin(
61
+ samples: Float32Array,
62
+ sampleRate = 22050,
63
+ frameLength = 2048,
64
+ hopLength = 512,
65
+ fmin = 65.0,
66
+ fmax = 2093.0,
67
+ threshold = 0.3,
68
+ fillNa = false,
69
+ ): PitchResult {
70
+ return requireModule().pitchPyin(
71
+ samples,
72
+ sampleRate,
73
+ frameLength,
74
+ hopLength,
75
+ fmin,
76
+ fmax,
77
+ threshold,
78
+ fillNa,
79
+ );
80
+ }
@@ -0,0 +1,21 @@
1
+ import { getSonareModule } from './module_state';
2
+
3
+ function requireModule() {
4
+ return getSonareModule();
5
+ }
6
+
7
+ // ============================================================================
8
+ // Core - Resample
9
+ // ============================================================================
10
+
11
+ /**
12
+ * Resample audio to a different sample rate.
13
+ *
14
+ * @param samples - Audio samples (mono, float32)
15
+ * @param srcSr - Source sample rate in Hz
16
+ * @param targetSr - Target sample rate in Hz
17
+ * @returns Resampled audio
18
+ */
19
+ export function resample(samples: Float32Array, srcSr: number, targetSr: number): Float32Array {
20
+ return requireModule().resample(samples, srcSr, targetSr);
21
+ }
@@ -0,0 +1,330 @@
1
+ import { getSonareModule } from './module_state';
2
+ import type {
3
+ WasmDecomposeResult,
4
+ WasmHpssWithResidualResult,
5
+ WasmLufsResult,
6
+ WasmMatrix2dResult,
7
+ } from './sonare.js';
8
+ import type { ValidateOptions } from './validation';
9
+ import { assertInterleavedSamples, assertSampleRate } from './validation';
10
+
11
+ function requireModule() {
12
+ return getSonareModule();
13
+ }
14
+
15
+ // ============================================================================
16
+ // Features - Spectral
17
+ // ============================================================================
18
+
19
+ /**
20
+ * Compute spectral centroid (center of mass of spectrum).
21
+ *
22
+ * @param samples - Audio samples (mono, float32)
23
+ * @param sampleRate - Sample rate in Hz (default: 22050)
24
+ * @param nFft - FFT size (default: 2048)
25
+ * @param hopLength - Hop length (default: 512)
26
+ * @returns Spectral centroid in Hz for each frame
27
+ */
28
+ export function spectralCentroid(
29
+ samples: Float32Array,
30
+ sampleRate = 22050,
31
+ nFft = 2048,
32
+ hopLength = 512,
33
+ ): Float32Array {
34
+ return requireModule().spectralCentroid(samples, sampleRate, nFft, hopLength);
35
+ }
36
+
37
+ /**
38
+ * Compute spectral contrast (librosa.feature.spectral_contrast).
39
+ *
40
+ * @returns Matrix2d of shape (nBands + 1) x nFrames.
41
+ */
42
+ export function spectralContrast(
43
+ samples: Float32Array,
44
+ sampleRate = 22050,
45
+ nFft = 2048,
46
+ hopLength = 512,
47
+ nBands = 6,
48
+ fmin = 200.0,
49
+ quantile = 0.02,
50
+ ): WasmMatrix2dResult {
51
+ return requireModule().spectralContrast(
52
+ samples,
53
+ sampleRate,
54
+ nFft,
55
+ hopLength,
56
+ nBands,
57
+ fmin,
58
+ quantile,
59
+ );
60
+ }
61
+
62
+ /**
63
+ * Fit per-frame polynomial coefficients (librosa.feature.poly_features).
64
+ *
65
+ * @returns Matrix2d of shape (order + 1) x nFrames.
66
+ */
67
+ export function polyFeatures(
68
+ samples: Float32Array,
69
+ sampleRate = 22050,
70
+ nFft = 2048,
71
+ hopLength = 512,
72
+ order = 1,
73
+ ): WasmMatrix2dResult {
74
+ return requireModule().polyFeatures(samples, sampleRate, nFft, hopLength, order);
75
+ }
76
+
77
+ /**
78
+ * Locate zero-crossing indices of a signal (librosa.zero_crossings).
79
+ */
80
+ export function zeroCrossings(
81
+ samples: Float32Array,
82
+ threshold = 1e-10,
83
+ refMagnitude = false,
84
+ pad = true,
85
+ zeroPos = true,
86
+ ): Int32Array {
87
+ return requireModule().zeroCrossings(samples, threshold, refMagnitude, pad, zeroPos);
88
+ }
89
+
90
+ /**
91
+ * Estimate the global tuning offset from a set of frequencies
92
+ * (librosa.pitch_tuning). Returns a deviation in fractions of a bin.
93
+ */
94
+ export function pitchTuning(
95
+ frequencies: Float32Array,
96
+ resolution = 0.01,
97
+ binsPerOctave = 12,
98
+ ): number {
99
+ return requireModule().pitchTuning(frequencies, resolution, binsPerOctave);
100
+ }
101
+
102
+ /**
103
+ * Estimate the tuning offset of an audio signal (librosa.estimate_tuning).
104
+ */
105
+ export function estimateTuning(
106
+ samples: Float32Array,
107
+ sampleRate = 22050,
108
+ nFft = 2048,
109
+ hopLength = 512,
110
+ resolution = 0.01,
111
+ binsPerOctave = 12,
112
+ ): number {
113
+ return requireModule().estimateTuning(
114
+ samples,
115
+ sampleRate,
116
+ nFft,
117
+ hopLength,
118
+ resolution,
119
+ binsPerOctave,
120
+ );
121
+ }
122
+
123
+ /**
124
+ * Non-negative matrix factorisation of a flattened [nFeatures x nFrames]
125
+ * spectrogram (librosa.decompose.decompose). Returns the W and H factors.
126
+ */
127
+ export function decompose(
128
+ s: Float32Array,
129
+ nFeatures: number,
130
+ nFrames: number,
131
+ nComponents: number,
132
+ nIter = 50,
133
+ beta = 2.0,
134
+ ): WasmDecomposeResult {
135
+ return requireModule().decompose(s, nFeatures, nFrames, nComponents, nIter, beta);
136
+ }
137
+
138
+ /**
139
+ * Non-negative matrix factorisation with a selectable initialiser
140
+ * (librosa.decompose.decompose, `init`). Identical to {@link decompose} but
141
+ * exposes the initialisation strategy: `'random'` (default, deterministic seed)
142
+ * or `'nndsvd'` (SVD-based warm start, which tends to converge in fewer
143
+ * iterations). Returns the W and H factors.
144
+ */
145
+ export function decomposeWithInit(
146
+ s: Float32Array,
147
+ nFeatures: number,
148
+ nFrames: number,
149
+ nComponents: number,
150
+ nIter = 50,
151
+ beta = 2.0,
152
+ init: 'random' | 'nndsvd' = 'random',
153
+ ): WasmDecomposeResult {
154
+ return requireModule().decomposeWithInit(s, nFeatures, nFrames, nComponents, nIter, beta, init);
155
+ }
156
+
157
+ /**
158
+ * Nearest-neighbour filtering of a flattened [nFeatures x nFrames] spectrogram
159
+ * (librosa.decompose.nn_filter).
160
+ */
161
+ export function nnFilter(
162
+ s: Float32Array,
163
+ nFeatures: number,
164
+ nFrames: number,
165
+ aggregate = 'mean',
166
+ k = 7,
167
+ width = 1,
168
+ ): WasmMatrix2dResult {
169
+ return requireModule().nnFilter(s, nFeatures, nFrames, aggregate, k, width);
170
+ }
171
+
172
+ /**
173
+ * Reorder/concatenate a signal by interval slices (librosa.effects.remix).
174
+ *
175
+ * @param intervals - Flat (start, end) sample pairs (even length).
176
+ */
177
+ export function remix(
178
+ samples: Float32Array,
179
+ intervals: Int32Array | ArrayLike<number>,
180
+ sampleRate = 22050,
181
+ alignZeros = false,
182
+ ): Float32Array {
183
+ // Sample indices must reach the native side as exact 32-bit integers. Passing
184
+ // a Float32Array (or a number[] holding fractional/large values) would round
185
+ // boundaries above 2^24 and misalign the slice. Coerce to an Int32Array,
186
+ // truncating toward zero, so callers can hand us any numeric array safely.
187
+ const intervalsI32 =
188
+ intervals instanceof Int32Array ? intervals : Int32Array.from(intervals, (v) => Math.trunc(v));
189
+ return requireModule().remix(samples, intervalsI32, sampleRate, alignZeros);
190
+ }
191
+
192
+ /**
193
+ * Phase-vocoder time-scale modification (rate > 1 faster, < 1 slower).
194
+ */
195
+ export function phaseVocoder(
196
+ samples: Float32Array,
197
+ rate: number,
198
+ sampleRate = 22050,
199
+ nFft = 2048,
200
+ hopLength = 512,
201
+ ): Float32Array {
202
+ return requireModule().phaseVocoder(samples, sampleRate, rate, nFft, hopLength);
203
+ }
204
+
205
+ /**
206
+ * HPSS into harmonic / percussive / residual signals.
207
+ */
208
+ export function hpssWithResidual(
209
+ samples: Float32Array,
210
+ sampleRate = 22050,
211
+ kernelHarmonic = 31,
212
+ kernelPercussive = 31,
213
+ ): WasmHpssWithResidualResult {
214
+ return requireModule().hpssWithResidual(samples, sampleRate, kernelHarmonic, kernelPercussive);
215
+ }
216
+
217
+ /**
218
+ * Channel-weighted multichannel integrated loudness + LRA (ITU-R BS.1770 /
219
+ * EBU R128) from an interleaved buffer of `frames * channels` samples. The
220
+ * per-channel frame count is derived from the buffer length and `channels`.
221
+ */
222
+ export function lufsInterleaved(
223
+ samples: Float32Array,
224
+ channels: number,
225
+ sampleRate = 22050,
226
+ options: ValidateOptions = {},
227
+ ): WasmLufsResult {
228
+ assertSampleRate('lufsInterleaved', sampleRate);
229
+ assertInterleavedSamples('lufsInterleaved', samples, channels, options.validate !== false);
230
+ return requireModule().lufsInterleaved(samples, channels, sampleRate);
231
+ }
232
+
233
+ /**
234
+ * Standards-compliant EBU R128 loudness range (LRA) in LU.
235
+ */
236
+ export function ebur128LoudnessRange(samples: Float32Array, sampleRate = 22050): number {
237
+ return requireModule().ebur128LoudnessRange(samples, sampleRate);
238
+ }
239
+
240
+ /**
241
+ * Compute spectral bandwidth.
242
+ *
243
+ * @param samples - Audio samples (mono, float32)
244
+ * @param sampleRate - Sample rate in Hz (default: 22050)
245
+ * @param nFft - FFT size (default: 2048)
246
+ * @param hopLength - Hop length (default: 512)
247
+ * @returns Spectral bandwidth in Hz for each frame
248
+ */
249
+ export function spectralBandwidth(
250
+ samples: Float32Array,
251
+ sampleRate = 22050,
252
+ nFft = 2048,
253
+ hopLength = 512,
254
+ ): Float32Array {
255
+ return requireModule().spectralBandwidth(samples, sampleRate, nFft, hopLength);
256
+ }
257
+
258
+ /**
259
+ * Compute spectral rolloff frequency.
260
+ *
261
+ * @param samples - Audio samples (mono, float32)
262
+ * @param sampleRate - Sample rate in Hz (default: 22050)
263
+ * @param nFft - FFT size (default: 2048)
264
+ * @param hopLength - Hop length (default: 512)
265
+ * @param rollPercent - Percentage threshold (default: 0.85)
266
+ * @returns Rolloff frequency in Hz for each frame
267
+ */
268
+ export function spectralRolloff(
269
+ samples: Float32Array,
270
+ sampleRate = 22050,
271
+ nFft = 2048,
272
+ hopLength = 512,
273
+ rollPercent = 0.85,
274
+ ): Float32Array {
275
+ return requireModule().spectralRolloff(samples, sampleRate, nFft, hopLength, rollPercent);
276
+ }
277
+
278
+ /**
279
+ * Compute spectral flatness.
280
+ *
281
+ * @param samples - Audio samples (mono, float32)
282
+ * @param sampleRate - Sample rate in Hz (default: 22050)
283
+ * @param nFft - FFT size (default: 2048)
284
+ * @param hopLength - Hop length (default: 512)
285
+ * @returns Spectral flatness for each frame (0 = tonal, 1 = noise-like)
286
+ */
287
+ export function spectralFlatness(
288
+ samples: Float32Array,
289
+ sampleRate = 22050,
290
+ nFft = 2048,
291
+ hopLength = 512,
292
+ ): Float32Array {
293
+ return requireModule().spectralFlatness(samples, sampleRate, nFft, hopLength);
294
+ }
295
+
296
+ /**
297
+ * Compute zero crossing rate.
298
+ *
299
+ * @param samples - Audio samples (mono, float32)
300
+ * @param sampleRate - Sample rate in Hz (default: 22050)
301
+ * @param frameLength - Frame length (default: 2048)
302
+ * @param hopLength - Hop length (default: 512)
303
+ * @returns Zero crossing rate for each frame
304
+ */
305
+ export function zeroCrossingRate(
306
+ samples: Float32Array,
307
+ sampleRate = 22050,
308
+ frameLength = 2048,
309
+ hopLength = 512,
310
+ ): Float32Array {
311
+ return requireModule().zeroCrossingRate(samples, sampleRate, frameLength, hopLength);
312
+ }
313
+
314
+ /**
315
+ * Compute RMS energy.
316
+ *
317
+ * @param samples - Audio samples (mono, float32)
318
+ * @param sampleRate - Sample rate in Hz (default: 22050)
319
+ * @param frameLength - Frame length (default: 2048)
320
+ * @param hopLength - Hop length (default: 512)
321
+ * @returns RMS energy for each frame
322
+ */
323
+ export function rmsEnergy(
324
+ samples: Float32Array,
325
+ sampleRate = 22050,
326
+ frameLength = 2048,
327
+ hopLength = 512,
328
+ ): Float32Array {
329
+ return requireModule().rmsEnergy(samples, sampleRate, frameLength, hopLength);
330
+ }