@libraz/libsonare 1.7.1 → 1.8.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 (303) hide show
  1. package/NOTICE +178 -0
  2. package/README.md +26 -170
  3. package/dist/_chain_config.d.ts +14 -0
  4. package/dist/_chain_config.d.ts.map +1 -0
  5. package/dist/_effects_common.d.ts +6 -0
  6. package/dist/_effects_common.d.ts.map +1 -0
  7. package/dist/_feature_validation.d.ts +8 -0
  8. package/dist/_feature_validation.d.ts.map +1 -0
  9. package/dist/_fft_options.d.ts +24 -0
  10. package/dist/_fft_options.d.ts.map +1 -0
  11. package/dist/align_take.d.ts +50 -0
  12. package/dist/align_take.d.ts.map +1 -0
  13. package/dist/analysis.d.ts +29 -5837
  14. package/dist/analysis.d.ts.map +1 -0
  15. package/dist/analysis.js +873 -722
  16. package/dist/analysis.js.map +1 -1
  17. package/dist/analysis_helpers.d.ts +9 -0
  18. package/dist/analysis_helpers.d.ts.map +1 -0
  19. package/dist/audio.d.ts +163 -0
  20. package/dist/audio.d.ts.map +1 -0
  21. package/dist/clip_page_streamer.d.ts +133 -0
  22. package/dist/clip_page_streamer.d.ts.map +1 -0
  23. package/dist/codes.d.ts +44 -0
  24. package/dist/codes.d.ts.map +1 -0
  25. package/dist/effects_mastering.d.ts +23 -0
  26. package/dist/effects_mastering.d.ts.map +1 -0
  27. package/dist/effects_note_ops.d.ts +477 -0
  28. package/dist/effects_note_ops.d.ts.map +1 -0
  29. package/dist/effects_percussive.d.ts +185 -0
  30. package/dist/effects_percussive.d.ts.map +1 -0
  31. package/dist/effects_separation.d.ts +65 -0
  32. package/dist/effects_separation.d.ts.map +1 -0
  33. package/dist/effects_spectral.d.ts +28 -0
  34. package/dist/effects_spectral.d.ts.map +1 -0
  35. package/dist/effects_timepitch.d.ts +129 -0
  36. package/dist/effects_timepitch.d.ts.map +1 -0
  37. package/dist/effects_voice_change.d.ts +53 -0
  38. package/dist/effects_voice_change.d.ts.map +1 -0
  39. package/dist/errors.d.ts +51 -0
  40. package/dist/errors.d.ts.map +1 -0
  41. package/dist/feature_core.d.ts +341 -0
  42. package/dist/feature_core.d.ts.map +1 -0
  43. package/dist/feature_decompose.d.ts +278 -0
  44. package/dist/feature_decompose.d.ts.map +1 -0
  45. package/dist/feature_inverse.d.ts +128 -0
  46. package/dist/feature_inverse.d.ts.map +1 -0
  47. package/dist/feature_loudness.d.ts +66 -0
  48. package/dist/feature_loudness.d.ts.map +1 -0
  49. package/dist/feature_music.d.ts +307 -0
  50. package/dist/feature_music.d.ts.map +1 -0
  51. package/dist/feature_pitch.d.ts +108 -0
  52. package/dist/feature_pitch.d.ts.map +1 -0
  53. package/dist/feature_resample.d.ts +16 -0
  54. package/dist/feature_resample.d.ts.map +1 -0
  55. package/dist/feature_spectral.d.ts +137 -0
  56. package/dist/feature_spectral.d.ts.map +1 -0
  57. package/dist/feature_spectrogram.d.ts +198 -0
  58. package/dist/feature_spectrogram.d.ts.map +1 -0
  59. package/dist/features.d.ts +10 -0
  60. package/dist/features.d.ts.map +1 -0
  61. package/dist/hrtf/default.shrf +0 -0
  62. package/dist/index.d.ts +74 -7329
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +3816 -1359
  65. package/dist/index.js.map +1 -1
  66. package/dist/instrument_types.d.ts +517 -0
  67. package/dist/instrument_types.d.ts.map +1 -0
  68. package/dist/live_audio.d.ts +35 -0
  69. package/dist/live_audio.d.ts.map +1 -0
  70. package/dist/mastering_chain.d.ts +213 -0
  71. package/dist/mastering_chain.d.ts.map +1 -0
  72. package/dist/mastering_core.d.ts +457 -0
  73. package/dist/mastering_core.d.ts.map +1 -0
  74. package/dist/mastering_dynamics.d.ts +80 -0
  75. package/dist/mastering_dynamics.d.ts.map +1 -0
  76. package/dist/metering.d.ts +287 -0
  77. package/dist/metering.d.ts.map +1 -0
  78. package/dist/mixer.d.ts +464 -0
  79. package/dist/mixer.d.ts.map +1 -0
  80. package/dist/mixing_assistant.d.ts +62 -0
  81. package/dist/mixing_assistant.d.ts.map +1 -0
  82. package/dist/mixing_oneshot.d.ts +40 -0
  83. package/dist/mixing_oneshot.d.ts.map +1 -0
  84. package/dist/module_state.d.ts +15 -0
  85. package/dist/module_state.d.ts.map +1 -0
  86. package/dist/opfs_clip_pages.d.ts +28 -0
  87. package/dist/opfs_clip_pages.d.ts.map +1 -0
  88. package/dist/playback_renderer.d.ts +128 -0
  89. package/dist/playback_renderer.d.ts.map +1 -0
  90. package/dist/polyphony.d.ts +202 -0
  91. package/dist/polyphony.d.ts.map +1 -0
  92. package/dist/project.d.ts +8 -0
  93. package/dist/project.d.ts.map +1 -0
  94. package/dist/project_class.d.ts +562 -0
  95. package/dist/project_class.d.ts.map +1 -0
  96. package/dist/project_internal.d.ts +194 -0
  97. package/dist/project_internal.d.ts.map +1 -0
  98. package/dist/project_synth.d.ts +74 -0
  99. package/dist/project_synth.d.ts.map +1 -0
  100. package/dist/project_types.d.ts +652 -0
  101. package/dist/project_types.d.ts.map +1 -0
  102. package/dist/public_types.d.ts +185 -0
  103. package/dist/public_types.d.ts.map +1 -0
  104. package/dist/public_types_acoustic.d.ts +215 -0
  105. package/dist/public_types_acoustic.d.ts.map +1 -0
  106. package/dist/public_types_mastering.d.ts +510 -0
  107. package/dist/public_types_mastering.d.ts.map +1 -0
  108. package/dist/public_types_mixing.d.ts +436 -0
  109. package/dist/public_types_mixing.d.ts.map +1 -0
  110. package/dist/public_types_music.d.ts +619 -0
  111. package/dist/public_types_music.d.ts.map +1 -0
  112. package/dist/public_types_playback.d.ts +164 -0
  113. package/dist/public_types_playback.d.ts.map +1 -0
  114. package/dist/public_types_realtime.d.ts +174 -0
  115. package/dist/public_types_realtime.d.ts.map +1 -0
  116. package/dist/public_types_repair.d.ts +424 -0
  117. package/dist/public_types_repair.d.ts.map +1 -0
  118. package/dist/public_types_spectral.d.ts +697 -0
  119. package/dist/public_types_spectral.d.ts.map +1 -0
  120. package/dist/quick_analysis.d.ts +445 -0
  121. package/dist/quick_analysis.d.ts.map +1 -0
  122. package/dist/realtime_engine.d.ts +850 -0
  123. package/dist/realtime_engine.d.ts.map +1 -0
  124. package/dist/realtime_voice_changer.d.ts +158 -0
  125. package/dist/realtime_voice_changer.d.ts.map +1 -0
  126. package/dist/repair_dereverb.d.ts +187 -0
  127. package/dist/repair_dereverb.d.ts.map +1 -0
  128. package/dist/repair_impulsive.d.ts +186 -0
  129. package/dist/repair_impulsive.d.ts.map +1 -0
  130. package/dist/repair_noise.d.ts +239 -0
  131. package/dist/repair_noise.d.ts.map +1 -0
  132. package/dist/repair_trim.d.ts +123 -0
  133. package/dist/repair_trim.d.ts.map +1 -0
  134. package/dist/sample_bank.d.ts +84 -0
  135. package/dist/sample_bank.d.ts.map +1 -0
  136. package/dist/scale.d.ts +10 -0
  137. package/dist/scale.d.ts.map +1 -0
  138. package/dist/schemas/mixer-scene.schema.json +393 -0
  139. package/dist/schemas/playback-renderer-config.schema.json +392 -0
  140. package/dist/sonare-analysis.d.ts +8 -0
  141. package/dist/sonare-analysis.js +2 -2
  142. package/dist/sonare-analysis.wasm +0 -0
  143. package/dist/sonare.d.ts +3909 -0
  144. package/dist/sonare.js +2 -2
  145. package/dist/sonare.wasm +0 -0
  146. package/dist/stream_analyzer.d.ts +163 -0
  147. package/dist/stream_analyzer.d.ts.map +1 -0
  148. package/dist/stream_types.d.ts +214 -0
  149. package/dist/stream_types.d.ts.map +1 -0
  150. package/dist/streaming_mixing.d.ts +6 -0
  151. package/dist/streaming_mixing.d.ts.map +1 -0
  152. package/dist/streaming_processors.d.ts +335 -0
  153. package/dist/streaming_processors.d.ts.map +1 -0
  154. package/dist/transcribe.d.ts +77 -0
  155. package/dist/transcribe.d.ts.map +1 -0
  156. package/dist/validation.d.ts +140 -0
  157. package/dist/validation.d.ts.map +1 -0
  158. package/dist/web_midi.d.ts +77 -0
  159. package/dist/web_midi.d.ts.map +1 -0
  160. package/dist/worker.d.ts +5 -48
  161. package/dist/worker.d.ts.map +1 -0
  162. package/dist/worker.js +94 -41
  163. package/dist/worker.js.map +1 -1
  164. package/dist/worker_client.d.ts +96 -0
  165. package/dist/worker_client.d.ts.map +1 -0
  166. package/dist/worker_protocol.d.ts +43 -0
  167. package/dist/worker_protocol.d.ts.map +1 -0
  168. package/dist/worklet/audio_types.d.ts +21 -0
  169. package/dist/worklet/audio_types.d.ts.map +1 -0
  170. package/dist/worklet/engine-automation.d.ts +29 -0
  171. package/dist/worklet/engine-automation.d.ts.map +1 -0
  172. package/dist/worklet/engine-capture-facade.d.ts +35 -0
  173. package/dist/worklet/engine-capture-facade.d.ts.map +1 -0
  174. package/dist/worklet/engine-clips.d.ts +23 -0
  175. package/dist/worklet/engine-clips.d.ts.map +1 -0
  176. package/dist/worklet/engine-markers.d.ts +40 -0
  177. package/dist/worklet/engine-markers.d.ts.map +1 -0
  178. package/dist/worklet/engine-mixer-facade.d.ts +128 -0
  179. package/dist/worklet/engine-mixer-facade.d.ts.map +1 -0
  180. package/dist/worklet/engine-node.d.ts +81 -0
  181. package/dist/worklet/engine-node.d.ts.map +1 -0
  182. package/dist/worklet/engine-offline.d.ts +81 -0
  183. package/dist/worklet/engine-offline.d.ts.map +1 -0
  184. package/dist/worklet/engine-options.d.ts +12 -0
  185. package/dist/worklet/engine-options.d.ts.map +1 -0
  186. package/dist/worklet/engine-parameter-facade.d.ts +106 -0
  187. package/dist/worklet/engine-parameter-facade.d.ts.map +1 -0
  188. package/dist/worklet/engine-processor.d.ts +68 -0
  189. package/dist/worklet/engine-processor.d.ts.map +1 -0
  190. package/dist/worklet/engine-register.d.ts +2 -0
  191. package/dist/worklet/engine-register.d.ts.map +1 -0
  192. package/dist/worklet/engine-strips.d.ts +73 -0
  193. package/dist/worklet/engine-strips.d.ts.map +1 -0
  194. package/dist/worklet/engine-sync.d.ts +37 -0
  195. package/dist/worklet/engine-sync.d.ts.map +1 -0
  196. package/dist/worklet/engine-tempo-facade.d.ts +48 -0
  197. package/dist/worklet/engine-tempo-facade.d.ts.map +1 -0
  198. package/dist/worklet/engine.d.ts +397 -0
  199. package/dist/worklet/engine.d.ts.map +1 -0
  200. package/dist/worklet/guards.d.ts +47 -0
  201. package/dist/worklet/guards.d.ts.map +1 -0
  202. package/dist/worklet/messages.d.ts +710 -0
  203. package/dist/worklet/messages.d.ts.map +1 -0
  204. package/dist/worklet/mixer-processor.d.ts +46 -0
  205. package/dist/worklet/mixer-processor.d.ts.map +1 -0
  206. package/dist/worklet/playback-processor.d.ts +62 -0
  207. package/dist/worklet/playback-processor.d.ts.map +1 -0
  208. package/dist/worklet/protocol.d.ts +323 -0
  209. package/dist/worklet/protocol.d.ts.map +1 -0
  210. package/dist/worklet/voice-changer-processor.d.ts +41 -0
  211. package/dist/worklet/voice-changer-processor.d.ts.map +1 -0
  212. package/dist/worklet.d.ts +16 -2142
  213. package/dist/worklet.d.ts.map +1 -0
  214. package/dist/worklet.js +2889 -466
  215. package/dist/worklet.js.map +1 -1
  216. package/package.json +23 -12
  217. package/src/_effects_common.ts +17 -0
  218. package/src/_feature_validation.ts +34 -0
  219. package/src/_fft_options.ts +39 -0
  220. package/src/align_take.ts +64 -0
  221. package/src/analysis.ts +56 -3
  222. package/src/analysis_helpers.ts +7 -0
  223. package/src/audio.ts +106 -3
  224. package/src/codes.ts +39 -2
  225. package/src/effects_mastering.ts +97 -22
  226. package/src/effects_note_ops.ts +635 -0
  227. package/src/effects_percussive.ts +217 -0
  228. package/src/effects_separation.ts +150 -0
  229. package/src/effects_spectral.ts +60 -0
  230. package/src/effects_timepitch.ts +377 -0
  231. package/src/errors.ts +23 -1
  232. package/src/feature_core.ts +127 -2
  233. package/src/feature_decompose.ts +633 -0
  234. package/src/feature_inverse.ts +454 -0
  235. package/src/feature_loudness.ts +125 -0
  236. package/src/feature_music.ts +107 -14
  237. package/src/feature_pitch.ts +96 -1
  238. package/src/feature_spectral.ts +16 -611
  239. package/src/feature_spectrogram.ts +63 -450
  240. package/src/features.ts +36 -22
  241. package/src/index.ts +285 -30
  242. package/src/instrument_types.ts +645 -0
  243. package/src/live_audio.ts +27 -1
  244. package/src/mastering_chain.ts +184 -0
  245. package/src/mastering_core.ts +346 -32
  246. package/src/mastering_dynamics.ts +22 -11
  247. package/src/metering.ts +67 -24
  248. package/src/mixer.ts +212 -3
  249. package/src/mixing_assistant.ts +138 -0
  250. package/src/mixing_oneshot.ts +10 -5
  251. package/src/module_state.ts +24 -2
  252. package/src/playback_renderer.ts +252 -0
  253. package/src/polyphony.ts +279 -0
  254. package/src/project.ts +64 -24
  255. package/src/project_class.ts +502 -29
  256. package/src/project_internal.ts +151 -42
  257. package/src/project_synth.ts +67 -1
  258. package/src/project_types.ts +302 -270
  259. package/src/public_types.ts +122 -3
  260. package/src/public_types_acoustic.ts +112 -3
  261. package/src/public_types_mastering.ts +254 -73
  262. package/src/public_types_mixing.ts +363 -1
  263. package/src/public_types_music.ts +312 -2
  264. package/src/public_types_playback.ts +195 -0
  265. package/src/public_types_realtime.ts +39 -7
  266. package/src/public_types_repair.ts +446 -0
  267. package/src/public_types_spectral.ts +487 -1
  268. package/src/quick_analysis.ts +203 -26
  269. package/src/realtime_engine.ts +750 -28
  270. package/src/realtime_voice_changer.ts +55 -1
  271. package/src/repair_dereverb.ts +299 -0
  272. package/src/repair_impulsive.ts +395 -0
  273. package/src/repair_noise.ts +425 -0
  274. package/src/repair_trim.ts +226 -0
  275. package/src/sample_bank.ts +113 -0
  276. package/src/sonare.js.d.ts +1125 -30
  277. package/src/stream_analyzer.ts +36 -4
  278. package/src/stream_types.ts +37 -0
  279. package/src/streaming_mixing.ts +1 -1
  280. package/src/streaming_processors.ts +212 -10
  281. package/src/transcribe.ts +89 -0
  282. package/src/validation.ts +285 -11
  283. package/src/web_midi.ts +1 -6
  284. package/src/worker.ts +18 -2
  285. package/src/worklet/audio_types.ts +37 -0
  286. package/src/worklet/engine-mixer-facade.ts +444 -10
  287. package/src/worklet/engine-node.ts +85 -28
  288. package/src/worklet/engine-offline.ts +14 -8
  289. package/src/worklet/engine-parameter-facade.ts +21 -0
  290. package/src/worklet/engine-processor.ts +307 -71
  291. package/src/worklet/engine-register.ts +32 -18
  292. package/src/worklet/engine-strips.ts +280 -9
  293. package/src/worklet/engine-sync.ts +14 -6
  294. package/src/worklet/engine.ts +365 -31
  295. package/src/worklet/guards.ts +140 -44
  296. package/src/worklet/messages.ts +239 -2
  297. package/src/worklet/mixer-processor.ts +109 -47
  298. package/src/worklet/playback-processor.ts +300 -0
  299. package/src/worklet/protocol.ts +53 -3
  300. package/src/worklet/voice-changer-processor.ts +17 -11
  301. package/src/worklet.ts +22 -0
  302. package/src/effects_transform.ts +0 -718
  303. package/src/mastering_repair.ts +0 -273
@@ -1,59 +1,15 @@
1
+ /**
2
+ * Frame-level spectral descriptors: the scalar shape measures taken per STFT
3
+ * frame, and the zero-crossing counts beside them.
4
+ */
5
+
1
6
  import { getSonareModule } from './module_state';
2
- import type { SegmentMatrix } from './public_types';
3
- import type {
4
- WasmDecomposeResult,
5
- WasmHpssWithResidualResult,
6
- WasmLufsResult,
7
- WasmMatrix2dResult,
8
- } from './sonare.js';
9
- import type { ValidateOptions } from './validation';
10
- import {
11
- assertInterleavedSamples,
12
- assertNonNegativeInteger,
13
- assertPositiveInteger,
14
- assertSampleRate,
15
- assertSamples,
16
- } from './validation';
7
+ import type { WasmMatrix2dResult } from './sonare.js';
17
8
 
18
9
  function requireModule() {
19
10
  return getSonareModule();
20
11
  }
21
12
 
22
- function resolveEffectFftOptions(
23
- fnName: string,
24
- nFft: unknown,
25
- hopLength: unknown,
26
- ): { nFft: number; hopLength: number } {
27
- const resolvedNFft = nFft === undefined ? 2048 : nFft;
28
- const resolvedHopLength = hopLength === undefined ? 512 : hopLength;
29
- if (typeof resolvedNFft !== 'number' || !Number.isInteger(resolvedNFft)) {
30
- throw new TypeError(`${fnName}: nFft must be an integer`);
31
- }
32
- if (resolvedNFft < 2 || resolvedNFft > 2 ** 30) {
33
- throw new RangeError(`${fnName}: nFft must be an even power of two >= 2`);
34
- }
35
- if ((resolvedNFft & (resolvedNFft - 1)) !== 0) {
36
- throw new RangeError(`${fnName}: nFft must be an even power of two >= 2`);
37
- }
38
- if (typeof resolvedHopLength !== 'number' || !Number.isInteger(resolvedHopLength)) {
39
- throw new TypeError(`${fnName}: hopLength must be an integer`);
40
- }
41
- if (resolvedHopLength <= 0 || resolvedHopLength > 2 ** 31 - 1) {
42
- throw new RangeError(`${fnName}: hopLength must be a positive integer`);
43
- }
44
- return { nFft: resolvedNFft, hopLength: resolvedHopLength };
45
- }
46
-
47
- function resolveHardMask(fnName: string, value: unknown): boolean {
48
- if (value === undefined) {
49
- return false;
50
- }
51
- if (typeof value !== 'boolean') {
52
- throw new TypeError(`${fnName}: hardMask must be a boolean`);
53
- }
54
- return value;
55
- }
56
-
57
13
  /** Canonical request form for frame-based spectral feature extraction. */
58
14
  export interface SpectralFrameRequest {
59
15
  samples: Float32Array;
@@ -73,27 +29,16 @@ export interface ZeroCrossingRateRequest {
73
29
  hopLength?: number;
74
30
  }
75
31
 
76
- export interface DecomposeRequest {
77
- s: Float32Array;
78
- nFeatures: number;
79
- nFrames: number;
80
- nComponents: number;
81
- nIter?: number;
82
- beta?: number;
83
- }
84
-
85
- export interface DecomposeWithInitRequest extends DecomposeRequest {
86
- init?: 'random' | 'nndsvd';
87
- }
88
-
89
32
  export interface SpectralContrastRequest extends SpectralFrameRequest {
90
33
  nBands?: number;
91
34
  fmin?: number;
92
35
  quantile?: number;
93
36
  }
37
+
94
38
  export interface PolyFeaturesRequest extends SpectralFrameRequest {
95
39
  order?: number;
96
40
  }
41
+
97
42
  export interface ZeroCrossingsRequest {
98
43
  samples: Float32Array;
99
44
  threshold?: number;
@@ -101,119 +46,6 @@ export interface ZeroCrossingsRequest {
101
46
  pad?: boolean;
102
47
  zeroPos?: boolean;
103
48
  }
104
- export interface PitchTuningRequest {
105
- frequencies: Float32Array;
106
- resolution?: number;
107
- binsPerOctave?: number;
108
- }
109
- export interface EstimateTuningRequest extends SpectralFrameRequest {
110
- resolution?: number;
111
- binsPerOctave?: number;
112
- }
113
- export interface NnFilterRequest {
114
- s: Float32Array;
115
- nFeatures: number;
116
- nFrames: number;
117
- aggregate?: string;
118
- k?: number;
119
- width?: number;
120
- }
121
- export interface SegmentCrossSimilarityRequest {
122
- x: Float32Array;
123
- xRows: number;
124
- xCols: number;
125
- y: Float32Array;
126
- yRows: number;
127
- yCols: number;
128
- k?: number;
129
- metric?: 'cosine' | 'euclidean';
130
- mode?: 'connectivity' | 'affinity';
131
- }
132
- export interface SegmentRecurrenceMatrixRequest {
133
- data: Float32Array;
134
- rows: number;
135
- cols: number;
136
- k?: number;
137
- width?: number;
138
- sym?: boolean;
139
- metric?: 'cosine' | 'euclidean';
140
- mode?: 'connectivity' | 'affinity';
141
- }
142
- export interface SegmentRecurrenceToLagRequest {
143
- recurrence: Float32Array;
144
- n: number;
145
- pad?: boolean;
146
- }
147
- export interface SegmentLagToRecurrenceRequest {
148
- lag: Float32Array;
149
- rows: number;
150
- lags: number;
151
- }
152
- export interface SegmentSubsegmentRequest {
153
- data: Float32Array;
154
- rows: number;
155
- cols: number;
156
- boundaries: Int32Array;
157
- nSegments?: number;
158
- }
159
- export interface SegmentAgglomerativeRequest {
160
- data: Float32Array;
161
- rows: number;
162
- cols: number;
163
- k: number;
164
- linkage?: 'average' | 'single' | 'complete' | 'ward';
165
- }
166
- export interface SegmentPathEnhanceRequest {
167
- recurrence: Float32Array;
168
- n: number;
169
- win: number;
170
- maxRatio?: number;
171
- minRatio?: number;
172
- nFilters?: number;
173
- }
174
-
175
- function validateSegmentMatrix(
176
- fnName: string,
177
- data: Float32Array,
178
- rows: number,
179
- cols: number,
180
- dataName: string,
181
- ): void {
182
- assertPositiveInteger(fnName, rows, 'rows');
183
- assertPositiveInteger(fnName, cols, 'cols');
184
- assertSamples(fnName, data, true, dataName);
185
- const expected = rows * cols;
186
- if (!Number.isSafeInteger(expected) || data.length !== expected) {
187
- throw new RangeError(`${fnName}: ${dataName} length must equal rows * cols`);
188
- }
189
- }
190
- export interface RemixRequest {
191
- samples: Float32Array;
192
- intervals: Int32Array | ArrayLike<number>;
193
- sampleRate?: number;
194
- alignZeros?: boolean;
195
- }
196
- export interface PhaseVocoderRequest extends SpectralFrameRequest {
197
- rate: number;
198
- }
199
- export interface HpssWithResidualRequest {
200
- samples: Float32Array;
201
- sampleRate?: number;
202
- kernelHarmonic?: number;
203
- kernelPercussive?: number;
204
- nFft?: number;
205
- hopLength?: number;
206
- hardMask?: boolean;
207
- }
208
- export interface LufsInterleavedRequest extends ValidateOptions {
209
- samples: Float32Array;
210
- channels: number;
211
- sampleRate?: number;
212
- }
213
- export interface Ebur128LoudnessRangeRequest extends ValidateOptions {
214
- samples: Float32Array;
215
- sampleRate?: number;
216
- }
217
49
 
218
50
  // ============================================================================
219
51
  // Features - Spectral
@@ -250,6 +82,14 @@ export function spectralCentroid(
250
82
  /**
251
83
  * Compute spectral contrast (librosa.feature.spectral_contrast).
252
84
  *
85
+ * @remarks
86
+ * Band 0 spans `[0, fmin]`, so an `fmin` below one analysis bin
87
+ * (`sampleRate / nFft`) leaves it empty after the band trim. Row 0 is still
88
+ * finite, but comes from the other bands' extremes rather than from itself, and
89
+ * is neither level-invariant nor confined to the band. Keep `fmin` at or above
90
+ * one bin width for row 0 to mean anything — at the defaults (22050 Hz, 2048)
91
+ * one bin is 10.8 Hz, so only a small `nFft` or a tiny `fmin` reaches this.
92
+ *
253
93
  * @returns Matrix2d of shape (nBands + 1) x nFrames.
254
94
  */
255
95
  export function spectralContrast(request: SpectralContrastRequest): WasmMatrix2dResult;
@@ -346,326 +186,6 @@ export function zeroCrossings(
346
186
  return requireModule().zeroCrossings(samples, threshold, refMagnitude, pad, zeroPos);
347
187
  }
348
188
 
349
- /**
350
- * Estimate the global tuning offset from a set of frequencies
351
- * (librosa.pitch_tuning). Returns a deviation in fractions of a bin.
352
- */
353
- export function pitchTuning(request: PitchTuningRequest): number;
354
- export function pitchTuning(
355
- frequencies: Float32Array,
356
- resolution?: number,
357
- binsPerOctave?: number,
358
- ): number;
359
- export function pitchTuning(
360
- frequencies: Float32Array | PitchTuningRequest,
361
- resolution = 0.01,
362
- binsPerOctave = 12,
363
- ): number {
364
- if (!(frequencies instanceof Float32Array)) {
365
- const r = frequencies;
366
- return pitchTuning(r.frequencies, r.resolution, r.binsPerOctave);
367
- }
368
- return requireModule().pitchTuning(frequencies, resolution, binsPerOctave);
369
- }
370
-
371
- /**
372
- * Estimate the tuning offset of an audio signal (librosa.estimate_tuning).
373
- */
374
- export function estimateTuning(request: EstimateTuningRequest): number;
375
- export function estimateTuning(
376
- samples: Float32Array,
377
- sampleRate?: number,
378
- nFft?: number,
379
- hopLength?: number,
380
- resolution?: number,
381
- binsPerOctave?: number,
382
- ): number;
383
- export function estimateTuning(
384
- samples: Float32Array | EstimateTuningRequest,
385
- sampleRate = 22050,
386
- nFft = 2048,
387
- hopLength = 512,
388
- resolution = 0.01,
389
- binsPerOctave = 12,
390
- ): number {
391
- if (!(samples instanceof Float32Array)) {
392
- const r = samples;
393
- return estimateTuning(
394
- r.samples,
395
- r.sampleRate,
396
- r.nFft,
397
- r.hopLength,
398
- r.resolution,
399
- r.binsPerOctave,
400
- );
401
- }
402
- return requireModule().estimateTuning(
403
- samples,
404
- sampleRate,
405
- nFft,
406
- hopLength,
407
- resolution,
408
- binsPerOctave,
409
- );
410
- }
411
-
412
- /**
413
- * Non-negative matrix factorisation of a flattened [nFeatures x nFrames]
414
- * spectrogram (librosa.decompose.decompose). Returns the W and H factors.
415
- */
416
- export function decompose(request: DecomposeRequest): WasmDecomposeResult;
417
- export function decompose(
418
- s: Float32Array,
419
- nFeatures: number,
420
- nFrames: number,
421
- nComponents: number,
422
- nIter?: number,
423
- beta?: number,
424
- ): WasmDecomposeResult;
425
- export function decompose(
426
- s: Float32Array | DecomposeRequest,
427
- nFeatures = 0,
428
- nFrames = 0,
429
- nComponents = 0,
430
- nIter = 50,
431
- beta = 2.0,
432
- ): WasmDecomposeResult {
433
- if (!(s instanceof Float32Array)) {
434
- const request = s;
435
- return decompose(
436
- request.s,
437
- request.nFeatures,
438
- request.nFrames,
439
- request.nComponents,
440
- request.nIter,
441
- request.beta,
442
- );
443
- }
444
- return requireModule().decompose(s, nFeatures, nFrames, nComponents, nIter, beta);
445
- }
446
-
447
- /**
448
- * Non-negative matrix factorisation with a selectable initialiser
449
- * (librosa.decompose.decompose, `init`). Identical to {@link decompose} but
450
- * exposes the initialisation strategy: `'random'` (default, deterministic seed)
451
- * or `'nndsvd'` (SVD-based warm start, which tends to converge in fewer
452
- * iterations). Returns the W and H factors.
453
- */
454
- export function decomposeWithInit(request: DecomposeWithInitRequest): WasmDecomposeResult;
455
- export function decomposeWithInit(
456
- s: Float32Array,
457
- nFeatures: number,
458
- nFrames: number,
459
- nComponents: number,
460
- nIter?: number,
461
- beta?: number,
462
- init?: 'random' | 'nndsvd',
463
- ): WasmDecomposeResult;
464
- export function decomposeWithInit(
465
- s: Float32Array | DecomposeWithInitRequest,
466
- nFeatures = 0,
467
- nFrames = 0,
468
- nComponents = 0,
469
- nIter = 50,
470
- beta = 2.0,
471
- init: 'random' | 'nndsvd' = 'random',
472
- ): WasmDecomposeResult {
473
- if (!(s instanceof Float32Array)) {
474
- const request = s;
475
- return decomposeWithInit(
476
- request.s,
477
- request.nFeatures,
478
- request.nFrames,
479
- request.nComponents,
480
- request.nIter,
481
- request.beta,
482
- request.init,
483
- );
484
- }
485
- return requireModule().decomposeWithInit(s, nFeatures, nFrames, nComponents, nIter, beta, init);
486
- }
487
-
488
- /**
489
- * Nearest-neighbour filtering of a flattened [nFeatures x nFrames] spectrogram
490
- * (librosa.decompose.nn_filter).
491
- */
492
- export function nnFilter(request: NnFilterRequest): WasmMatrix2dResult;
493
- export function nnFilter(
494
- s: Float32Array,
495
- nFeatures: number,
496
- nFrames: number,
497
- aggregate?: string,
498
- k?: number,
499
- width?: number,
500
- ): WasmMatrix2dResult;
501
- export function nnFilter(
502
- s: Float32Array | NnFilterRequest,
503
- nFeatures = 0,
504
- nFrames = 0,
505
- aggregate = 'mean',
506
- k = 7,
507
- width = 1,
508
- ): WasmMatrix2dResult {
509
- if (!(s instanceof Float32Array)) {
510
- const r = s;
511
- return nnFilter(r.s, r.nFeatures, r.nFrames, r.aggregate, r.k, r.width);
512
- }
513
- return requireModule().nnFilter(s, nFeatures, nFrames, aggregate, k, width);
514
- }
515
-
516
- /**
517
- * Reorder/concatenate a signal by interval slices (librosa.effects.remix).
518
- *
519
- * @param intervals - Flat (start, end) sample pairs (even length).
520
- */
521
- export function remix(request: RemixRequest): Float32Array;
522
- export function remix(
523
- samples: Float32Array,
524
- intervals: Int32Array | ArrayLike<number>,
525
- sampleRate?: number,
526
- alignZeros?: boolean,
527
- ): Float32Array;
528
- export function remix(
529
- samples: Float32Array | RemixRequest,
530
- intervals?: Int32Array | ArrayLike<number>,
531
- sampleRate = 22050,
532
- alignZeros = false,
533
- ): Float32Array {
534
- if (!(samples instanceof Float32Array)) {
535
- const r = samples;
536
- return remix(r.samples, r.intervals, r.sampleRate, r.alignZeros);
537
- }
538
- // Sample indices must reach the native side as exact 32-bit integers. Passing
539
- // a Float32Array (or a number[] holding fractional/large values) would round
540
- // boundaries above 2^24 and misalign the slice. Coerce to an Int32Array,
541
- // truncating toward zero, so callers can hand us any numeric array safely.
542
- const intervalsI32 =
543
- intervals instanceof Int32Array
544
- ? intervals
545
- : Int32Array.from(intervals as ArrayLike<number>, (v) => Math.trunc(v));
546
- return requireModule().remix(samples, intervalsI32, sampleRate, alignZeros);
547
- }
548
-
549
- /**
550
- * Phase-vocoder time-scale modification (rate > 1 faster, < 1 slower).
551
- */
552
- export function phaseVocoder(request: PhaseVocoderRequest): Float32Array;
553
- export function phaseVocoder(
554
- samples: Float32Array,
555
- sampleRate: number,
556
- rate: number,
557
- nFft?: number,
558
- hopLength?: number,
559
- ): Float32Array;
560
- export function phaseVocoder(
561
- samples: Float32Array | PhaseVocoderRequest,
562
- sampleRate = 22050,
563
- rate = 1,
564
- nFft = 2048,
565
- hopLength = 512,
566
- ): Float32Array {
567
- if (!(samples instanceof Float32Array)) {
568
- const r = samples;
569
- return phaseVocoder(r.samples, r.sampleRate ?? 22050, r.rate, r.nFft, r.hopLength);
570
- }
571
- return requireModule().phaseVocoder(samples, sampleRate, rate, nFft, hopLength);
572
- }
573
-
574
- /**
575
- * HPSS into harmonic / percussive / residual signals.
576
- */
577
- export function hpssWithResidual(request: HpssWithResidualRequest): WasmHpssWithResidualResult;
578
- export function hpssWithResidual(
579
- samples: Float32Array,
580
- sampleRate?: number,
581
- kernelHarmonic?: number,
582
- kernelPercussive?: number,
583
- nFft?: number,
584
- hopLength?: number,
585
- hardMask?: boolean,
586
- ): WasmHpssWithResidualResult;
587
- export function hpssWithResidual(
588
- samples: Float32Array | HpssWithResidualRequest,
589
- sampleRate = 22050,
590
- kernelHarmonic = 31,
591
- kernelPercussive = 31,
592
- nFft?: number,
593
- hopLength?: number,
594
- hardMask?: boolean,
595
- ): WasmHpssWithResidualResult {
596
- if (!(samples instanceof Float32Array)) {
597
- const r = samples;
598
- return hpssWithResidual(
599
- r.samples,
600
- r.sampleRate,
601
- r.kernelHarmonic,
602
- r.kernelPercussive,
603
- r.nFft,
604
- r.hopLength,
605
- r.hardMask,
606
- );
607
- }
608
- const fftOptions = resolveEffectFftOptions('hpssWithResidual', nFft, hopLength);
609
- const resolvedHardMask = resolveHardMask('hpssWithResidual', hardMask);
610
- return requireModule().hpssWithResidualEx(
611
- samples,
612
- sampleRate,
613
- kernelHarmonic,
614
- kernelPercussive,
615
- fftOptions.nFft,
616
- fftOptions.hopLength,
617
- resolvedHardMask,
618
- );
619
- }
620
-
621
- /**
622
- * Channel-weighted multichannel integrated loudness + LRA (ITU-R BS.1770 /
623
- * EBU R128) from an interleaved buffer of `frames * channels` samples. The
624
- * per-channel frame count is derived from the buffer length and `channels`.
625
- *
626
- * Pass the buffer's actual `sampleRate`: the default (22050) is non-standard for
627
- * audio, and K-weighting is sample-rate dependent, so a wrong rate yields wrong
628
- * loudness.
629
- */
630
- export function lufsInterleaved(request: LufsInterleavedRequest): WasmLufsResult;
631
- export function lufsInterleaved(
632
- samples: Float32Array,
633
- channels: number,
634
- sampleRate?: number,
635
- options?: ValidateOptions,
636
- ): WasmLufsResult;
637
- export function lufsInterleaved(
638
- samples: Float32Array | LufsInterleavedRequest,
639
- channels = 0,
640
- sampleRate = 22050,
641
- options: ValidateOptions = {},
642
- ): WasmLufsResult {
643
- if (!(samples instanceof Float32Array)) {
644
- const r = samples;
645
- return lufsInterleaved(r.samples, r.channels, r.sampleRate, r);
646
- }
647
- assertSampleRate('lufsInterleaved', sampleRate);
648
- assertInterleavedSamples('lufsInterleaved', samples, channels, options.validate !== false);
649
- return requireModule().lufsInterleaved(samples, channels, sampleRate);
650
- }
651
-
652
- /**
653
- * Standards-compliant EBU R128 loudness range (LRA) in LU. Pass the buffer's
654
- * actual `sampleRate`: the default (22050) is non-standard and K-weighting is
655
- * sample-rate dependent.
656
- */
657
- export function ebur128LoudnessRange(request: Ebur128LoudnessRangeRequest): number;
658
- export function ebur128LoudnessRange(samples: Float32Array, sampleRate?: number): number;
659
- export function ebur128LoudnessRange(
660
- samples: Float32Array | Ebur128LoudnessRangeRequest,
661
- sampleRate = 22050,
662
- ): number {
663
- if (!(samples instanceof Float32Array)) {
664
- return ebur128LoudnessRange(samples.samples, samples.sampleRate);
665
- }
666
- return requireModule().ebur128LoudnessRange(samples, sampleRate);
667
- }
668
-
669
189
  /**
670
190
  * Compute spectral bandwidth.
671
191
  *
@@ -854,118 +374,3 @@ export function rmsEnergy(
854
374
  }
855
375
  return requireModule().rmsEnergy(samples, sampleRate, frameLength, hopLength);
856
376
  }
857
-
858
- /** Column-wise cross-similarity (librosa.segment.cross_similarity). */
859
- export function segmentCrossSimilarity(request: SegmentCrossSimilarityRequest): SegmentMatrix {
860
- validateSegmentMatrix('segmentCrossSimilarity', request.x, request.xRows, request.xCols, 'x');
861
- validateSegmentMatrix('segmentCrossSimilarity', request.y, request.yRows, request.yCols, 'y');
862
- if (request.xRows !== request.yRows) {
863
- throw new RangeError('segmentCrossSimilarity: feature dimensions must match');
864
- }
865
- assertNonNegativeInteger('segmentCrossSimilarity', request.k ?? 0, 'k');
866
- return requireModule().segmentCrossSimilarity(
867
- request.x,
868
- request.xRows,
869
- request.xCols,
870
- request.y,
871
- request.yRows,
872
- request.yCols,
873
- request.k ?? 0,
874
- request.metric ?? 'cosine',
875
- request.mode ?? 'connectivity',
876
- );
877
- }
878
-
879
- /** Self-similarity recurrence matrix (librosa.segment.recurrence_matrix). */
880
- export function segmentRecurrenceMatrix(request: SegmentRecurrenceMatrixRequest): SegmentMatrix {
881
- validateSegmentMatrix(
882
- 'segmentRecurrenceMatrix',
883
- request.data,
884
- request.rows,
885
- request.cols,
886
- 'data',
887
- );
888
- assertNonNegativeInteger('segmentRecurrenceMatrix', request.k ?? 0, 'k');
889
- assertNonNegativeInteger('segmentRecurrenceMatrix', request.width ?? 1, 'width');
890
- return requireModule().segmentRecurrenceMatrix(
891
- request.data,
892
- request.rows,
893
- request.cols,
894
- request.k ?? 0,
895
- request.width ?? 1,
896
- request.sym ?? false,
897
- request.metric ?? 'euclidean',
898
- request.mode ?? 'connectivity',
899
- );
900
- }
901
-
902
- /** Convert an `n × n` recurrence matrix to a lag matrix. */
903
- export function segmentRecurrenceToLag(request: SegmentRecurrenceToLagRequest): SegmentMatrix {
904
- validateSegmentMatrix(
905
- 'segmentRecurrenceToLag',
906
- request.recurrence,
907
- request.n,
908
- request.n,
909
- 'recurrence',
910
- );
911
- return requireModule().segmentRecurrenceToLag(
912
- request.recurrence,
913
- request.n,
914
- request.pad ?? false,
915
- );
916
- }
917
-
918
- /** Convert a lag matrix back to an `n × n` recurrence matrix. */
919
- export function segmentLagToRecurrence(request: SegmentLagToRecurrenceRequest): SegmentMatrix {
920
- validateSegmentMatrix('segmentLagToRecurrence', request.lag, request.rows, request.lags, 'lag');
921
- return requireModule().segmentLagToRecurrence(request.lag, request.rows, request.lags);
922
- }
923
-
924
- /** Refine frame boundaries by clustering within each parent segment. */
925
- export function segmentSubsegment(request: SegmentSubsegmentRequest): Int32Array {
926
- validateSegmentMatrix('segmentSubsegment', request.data, request.rows, request.cols, 'data');
927
- assertPositiveInteger('segmentSubsegment', request.nSegments ?? 4, 'nSegments');
928
- return requireModule().segmentSubsegment(
929
- request.data,
930
- request.rows,
931
- request.cols,
932
- request.boundaries,
933
- request.nSegments ?? 4,
934
- );
935
- }
936
-
937
- /** Cluster feature columns and return one label per column. */
938
- export function segmentAgglomerative(request: SegmentAgglomerativeRequest): Int32Array {
939
- validateSegmentMatrix('segmentAgglomerative', request.data, request.rows, request.cols, 'data');
940
- assertPositiveInteger('segmentAgglomerative', request.k, 'k');
941
- return requireModule().segmentAgglomerative(
942
- request.data,
943
- request.rows,
944
- request.cols,
945
- request.k,
946
- request.linkage ?? 'average',
947
- );
948
- }
949
-
950
- /** Enhance diagonal paths in an `n × n` recurrence matrix. */
951
- export function segmentPathEnhance(request: SegmentPathEnhanceRequest): SegmentMatrix {
952
- validateSegmentMatrix(
953
- 'segmentPathEnhance',
954
- request.recurrence,
955
- request.n,
956
- request.n,
957
- 'recurrence',
958
- );
959
- assertPositiveInteger('segmentPathEnhance', request.win, 'win');
960
- assertPositiveInteger('segmentPathEnhance', request.maxRatio ?? 2, 'maxRatio');
961
- assertNonNegativeInteger('segmentPathEnhance', request.minRatio ?? 0, 'minRatio');
962
- assertPositiveInteger('segmentPathEnhance', request.nFilters ?? 7, 'nFilters');
963
- return requireModule().segmentPathEnhance(
964
- request.recurrence,
965
- request.n,
966
- request.win,
967
- request.maxRatio ?? 2,
968
- request.minRatio ?? 0,
969
- request.nFilters ?? 7,
970
- );
971
- }