@libraz/libsonare 1.7.2 → 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 -203
  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 -5840
  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 -7431
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +3758 -1362
  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 -2515
  213. package/dist/worklet.d.ts.map +1 -0
  214. package/dist/worklet.js +2763 -501
  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 +282 -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 +61 -24
  255. package/src/project_class.ts +450 -27
  256. package/src/project_internal.ts +149 -42
  257. package/src/project_synth.ts +67 -1
  258. package/src/project_types.ts +268 -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 +711 -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 +1122 -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 +194 -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 +78 -26
  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 +272 -83
  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 +227 -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 +17 -0
  302. package/src/effects_transform.ts +0 -718
  303. package/src/mastering_repair.ts +0 -273
@@ -1,14 +1,19 @@
1
+ /**
2
+ * Spectrogram and chroma representations, and the silence trim that shares
3
+ * their input checks.
4
+ */
5
+
6
+ import type { GuardedOptions } from './_feature_validation';
7
+ import { validateMelFrequencyRange, validatePositiveIntegers } from './_feature_validation';
8
+ import { resolveFftOptions } from './_fft_options';
1
9
  import { getSonareModule } from './module_state';
2
10
  import type {
3
11
  ChromaResult,
4
- MelPowerResult,
5
12
  MelSpectrogramResult,
6
13
  MfccResult,
7
14
  ReassignedSpectrogramResult,
8
- StftPowerResult,
9
15
  StftResult,
10
16
  } from './public_types';
11
- import type { ValidateOptions } from './validation';
12
17
  import {
13
18
  assertFiniteScalar,
14
19
  assertPositiveInteger,
@@ -20,8 +25,6 @@ function requireModule() {
20
25
  return getSonareModule();
21
26
  }
22
27
 
23
- type GuardedOptions = ValidateOptions;
24
-
25
28
  /** Canonical request form for basic frame-based spectrogram features. */
26
29
  export interface SpectrogramRequest extends GuardedOptions {
27
30
  samples: Float32Array;
@@ -30,6 +33,13 @@ export interface SpectrogramRequest extends GuardedOptions {
30
33
  hopLength?: number;
31
34
  }
32
35
 
36
+ /**
37
+ * Options for the constant-Q chroma variants.
38
+ *
39
+ * Carries no `nFft`: these are built on a constant-Q transform, which resolves
40
+ * frequency through per-bin filter lengths rather than a framed FFT, so there
41
+ * is no FFT size to set. Use `chroma` for the STFT-framed chromagram.
42
+ */
33
43
  export interface ChromaSpectrogramRequest extends GuardedOptions {
34
44
  samples: Float32Array;
35
45
  sampleRate?: number;
@@ -38,6 +48,34 @@ export interface ChromaSpectrogramRequest extends GuardedOptions {
38
48
  binsPerOctave?: number;
39
49
  }
40
50
 
51
+ /**
52
+ * Options for the bass-focused chroma.
53
+ *
54
+ * Unlike {@link ChromaSpectrogramRequest} this carries no `binsPerOctave`: the
55
+ * bass chroma fixes its bin count and its lowest frequency together, so the
56
+ * resolution is not independently settable through this entry point.
57
+ */
58
+ export interface BassChromaSpectrogramRequest extends GuardedOptions {
59
+ samples: Float32Array;
60
+ sampleRate?: number;
61
+ hopLength?: number;
62
+ nChroma?: number;
63
+ }
64
+
65
+ /**
66
+ * Compile-time guard for the two request shapes above. A field the entry point
67
+ * cannot forward is worse than a missing one: it type-checks, runs, and returns
68
+ * the default silently. These aliases fail to compile if either field appears,
69
+ * so adding one has to be a deliberate act.
70
+ */
71
+ type AbsentKey<T extends never> = T;
72
+
73
+ type _ChromaRequestHasNoFftSize = AbsentKey<Extract<keyof ChromaSpectrogramRequest, 'nFft'>>;
74
+
75
+ type _BassChromaRequestHasNoResolutionControls = AbsentKey<
76
+ Extract<keyof BassChromaSpectrogramRequest, 'nFft' | 'binsPerOctave'>
77
+ >;
78
+
41
79
  export interface MelSpectrogramRequest extends SpectrogramRequest {
42
80
  nMels?: number;
43
81
  fmin?: number;
@@ -56,59 +94,12 @@ export interface MelDeltaRequest extends GuardedOptions {
56
94
  nFrames: number;
57
95
  width?: number;
58
96
  }
97
+
59
98
  export interface ReassignedSpectrogramRequest extends SpectrogramRequest {
60
99
  refPower?: number;
61
100
  fillNan?: boolean;
62
101
  }
63
102
 
64
- export interface MfccToMelRequest extends GuardedOptions {
65
- mfccCoefficients: Float32Array;
66
- nMfcc: number;
67
- nFrames: number;
68
- nMels?: number;
69
- /** Lifter used by the forward MFCC transform; zero means no liftering. */
70
- lifter?: number;
71
- }
72
-
73
- /** Canonical request form for reconstruction from a Mel power spectrogram. */
74
- export interface MelToStftRequest extends GuardedOptions {
75
- melPower: Float32Array;
76
- nMels: number;
77
- nFrames: number;
78
- sampleRate?: number;
79
- nFft?: number;
80
- fmin?: number;
81
- fmax?: number;
82
- htk?: boolean;
83
- }
84
-
85
- /** Canonical request form for Griffin-Lim reconstruction from Mel power. */
86
- export interface MelToAudioRequest extends MelToStftRequest {
87
- hopLength?: number;
88
- nIter?: number;
89
- }
90
- export interface GriffinLimRequest extends GuardedOptions {
91
- magnitude: Float32Array;
92
- nBins: number;
93
- nFrames: number;
94
- sampleRate?: number;
95
- nFft?: number;
96
- hopLength?: number;
97
- nIter?: number;
98
- momentum?: number;
99
- }
100
-
101
- /** Canonical request form for Griffin-Lim reconstruction from MFCCs. */
102
- export interface MfccToAudioRequest extends MfccToMelRequest {
103
- sampleRate?: number;
104
- nFft?: number;
105
- hopLength?: number;
106
- fmin?: number;
107
- fmax?: number;
108
- nIter?: number;
109
- htk?: boolean;
110
- }
111
-
112
103
  export interface TrimRequest extends GuardedOptions {
113
104
  samples: Float32Array;
114
105
  sampleRate: number;
@@ -127,49 +118,6 @@ function validateSpectrogramSamples(
127
118
  assertSamples(fnName, samples, options.validate !== false);
128
119
  }
129
120
 
130
- function validatePositiveIntegers(fnName: string, values: Record<string, number>): void {
131
- for (const [name, value] of Object.entries(values)) {
132
- assertPositiveInteger(fnName, value, name);
133
- }
134
- }
135
-
136
- function validateMelFrequencyRange(
137
- fnName: string,
138
- fmin: number,
139
- fmax: number,
140
- sampleRate: number,
141
- ): void {
142
- assertFiniteScalar(fnName, fmin, 'fmin');
143
- assertFiniteScalar(fnName, fmax, 'fmax');
144
- if (fmin < 0) {
145
- throw new RangeError(`${fnName}: fmin must be non-negative`);
146
- }
147
- if (fmax < 0) {
148
- throw new RangeError(`${fnName}: fmax must be non-negative`);
149
- }
150
- const effectiveFmax = fmax === 0 ? sampleRate / 2 : fmax;
151
- if (effectiveFmax <= fmin) {
152
- throw new RangeError(`${fnName}: fmax must be greater than fmin`);
153
- }
154
- }
155
-
156
- function validateMatrix(
157
- fnName: string,
158
- data: Float32Array,
159
- rows: number,
160
- frames: number,
161
- dataName: string,
162
- rowName: string,
163
- options: GuardedOptions = {},
164
- ): void {
165
- validatePositiveIntegers(fnName, { [rowName]: rows, nFrames: frames });
166
- assertSamples(fnName, data, options.validate !== false, dataName);
167
- const expectedLength = rows * frames;
168
- if (!Number.isSafeInteger(expectedLength) || data.length !== expectedLength) {
169
- throw new RangeError(`${fnName}: ${dataName} length must equal ${rowName} * nFrames`);
170
- }
171
- }
172
-
173
121
  /**
174
122
  * Trim silence from beginning and end of audio.
175
123
  *
@@ -272,8 +220,8 @@ export function stft(
272
220
  return stft(request.samples, request.sampleRate, request.nFft, request.hopLength, request);
273
221
  }
274
222
  validateSpectrogramSamples('stft', samples, sampleRate, options);
275
- validatePositiveIntegers('stft', { nFft, hopLength });
276
- return requireModule().stft(samples, sampleRate, nFft, hopLength);
223
+ const fft = resolveFftOptions('stft', nFft, hopLength);
224
+ return requireModule().stft(samples, sampleRate, fft.nFft, fft.hopLength);
277
225
  }
278
226
 
279
227
  /**
@@ -309,8 +257,8 @@ export function stftDb(
309
257
  return stftDb(request.samples, request.sampleRate, request.nFft, request.hopLength, request);
310
258
  }
311
259
  validateSpectrogramSamples('stftDb', samples, sampleRate, options);
312
- validatePositiveIntegers('stftDb', { nFft, hopLength });
313
- return requireModule().stftDb(samples, sampleRate, nFft, hopLength);
260
+ const fft = resolveFftOptions('stftDb', nFft, hopLength);
261
+ return requireModule().stftDb(samples, sampleRate, fft.nFft, fft.hopLength);
314
262
  }
315
263
 
316
264
  /**
@@ -412,7 +360,7 @@ export function chromaCqt(
412
360
  * @param nChroma - Number of chroma bins (default: 12)
413
361
  * @returns Chroma result
414
362
  */
415
- export function bassChroma(request: ChromaSpectrogramRequest): ChromaResult;
363
+ export function bassChroma(request: BassChromaSpectrogramRequest): ChromaResult;
416
364
  export function bassChroma(
417
365
  samples: Float32Array,
418
366
  sampleRate?: number,
@@ -421,7 +369,7 @@ export function bassChroma(
421
369
  options?: GuardedOptions,
422
370
  ): ChromaResult;
423
371
  export function bassChroma(
424
- samples: Float32Array | ChromaSpectrogramRequest,
372
+ samples: Float32Array | BassChromaSpectrogramRequest,
425
373
  sampleRate = 22050,
426
374
  hopLength = 512,
427
375
  nChroma = 12,
@@ -498,13 +446,14 @@ export function melSpectrogram(
498
446
  );
499
447
  }
500
448
  validateSpectrogramSamples('melSpectrogram', samples, sampleRate, options);
501
- validatePositiveIntegers('melSpectrogram', { nFft, hopLength, nMels });
449
+ const fft = resolveFftOptions('melSpectrogram', nFft, hopLength);
450
+ validatePositiveIntegers('melSpectrogram', { nMels });
502
451
  validateMelFrequencyRange('melSpectrogram', fmin, fmax, sampleRate);
503
452
  return requireModule().melSpectrogram(
504
453
  samples,
505
454
  sampleRate,
506
- nFft,
507
- hopLength,
455
+ fft.nFft,
456
+ fft.hopLength,
508
457
  nMels,
509
458
  fmin,
510
459
  fmax,
@@ -571,13 +520,14 @@ export function mfcc(
571
520
  );
572
521
  }
573
522
  validateSpectrogramSamples('mfcc', samples, sampleRate, options);
574
- validatePositiveIntegers('mfcc', { nFft, hopLength, nMels, nMfcc });
523
+ const fft = resolveFftOptions('mfcc', nFft, hopLength);
524
+ validatePositiveIntegers('mfcc', { nMels, nMfcc });
575
525
  validateMelFrequencyRange('mfcc', fmin, fmax, sampleRate);
576
526
  return requireModule().mfcc(
577
527
  samples,
578
528
  sampleRate,
579
- nFft,
580
- hopLength,
529
+ fft.nFft,
530
+ fft.hopLength,
581
531
  nMels,
582
532
  nMfcc,
583
533
  fmin,
@@ -671,343 +621,6 @@ export function reassignedSpectrogram(
671
621
  );
672
622
  }
673
623
 
674
- // ============================================================================
675
- // Features - Inverse reconstruction
676
- // ============================================================================
677
-
678
- /**
679
- * Approximate inverse of a Mel filterbank: Mel power spectrogram -> STFT power
680
- * spectrogram. Mirrors `feature::mel_to_stft`.
681
- *
682
- * @param melPower - Mel power spectrogram [nMels x nFrames] row-major
683
- * @param nMels - Number of Mel bands
684
- * @param nFrames - Number of time frames
685
- * @param sampleRate - Sample rate in Hz
686
- * @param nFft - FFT size (default: 2048)
687
- * @param fmin - Lower Mel band edge in Hz (default: 0)
688
- * @param fmax - Upper Mel band edge in Hz (default: sr/2 when 0)
689
- * @param htk - Use the HTK Mel formula instead of Slaney (default: false)
690
- * @returns STFT power spectrogram result
691
- */
692
- export function melToStft(request: MelToStftRequest): StftPowerResult;
693
- export function melToStft(
694
- melPower: Float32Array,
695
- nMels: number,
696
- nFrames: number,
697
- sampleRate?: number,
698
- nFft?: number,
699
- fmin?: number,
700
- fmax?: number,
701
- htk?: boolean,
702
- options?: GuardedOptions,
703
- ): StftPowerResult;
704
- export function melToStft(
705
- melPower: Float32Array | MelToStftRequest,
706
- nMels = 0,
707
- nFrames = 0,
708
- sampleRate = 22050,
709
- nFft = 2048,
710
- fmin = 0,
711
- fmax = 0,
712
- htk = false,
713
- options: GuardedOptions = {},
714
- ): StftPowerResult {
715
- if (!(melPower instanceof Float32Array)) {
716
- const request = melPower;
717
- return melToStft(
718
- request.melPower,
719
- request.nMels,
720
- request.nFrames,
721
- request.sampleRate,
722
- request.nFft,
723
- request.fmin,
724
- request.fmax,
725
- request.htk,
726
- request,
727
- );
728
- }
729
- assertSampleRate('melToStft', sampleRate);
730
- validateMatrix('melToStft', melPower, nMels, nFrames, 'melPower', 'nMels', options);
731
- validatePositiveIntegers('melToStft', { nFft });
732
- validateMelFrequencyRange('melToStft', fmin, fmax, sampleRate);
733
- return requireModule().melToStft(melPower, nMels, nFrames, sampleRate, nFft, fmin, fmax, htk);
734
- }
735
-
736
- /**
737
- * Reconstruct audio from a Mel power spectrogram via Griffin-Lim. Mirrors
738
- * `feature::mel_to_audio`.
739
- *
740
- * @param melPower - Mel power spectrogram [nMels x nFrames] row-major
741
- * @param nMels - Number of Mel bands
742
- * @param nFrames - Number of time frames
743
- * @param sampleRate - Sample rate in Hz
744
- * @param nFft - FFT size (default: 2048)
745
- * @param hopLength - Hop length (default: 512)
746
- * @param fmin - Minimum Mel frequency in Hz (default: 0)
747
- * @param fmax - Maximum Mel frequency in Hz (default: 0 = sr/2)
748
- * @param nIter - Griffin-Lim iterations (default: 32)
749
- * @param htk - Use the HTK Mel formula instead of Slaney (default: false)
750
- * @returns Reconstructed audio samples (mono, float32)
751
- */
752
- export function melToAudio(request: MelToAudioRequest): Float32Array;
753
- export function melToAudio(
754
- melPower: Float32Array,
755
- nMels: number,
756
- nFrames: number,
757
- sampleRate?: number,
758
- nFft?: number,
759
- hopLength?: number,
760
- fmin?: number,
761
- fmax?: number,
762
- nIter?: number,
763
- htk?: boolean,
764
- options?: GuardedOptions,
765
- ): Float32Array;
766
- export function melToAudio(
767
- melPower: Float32Array | MelToAudioRequest,
768
- nMels = 0,
769
- nFrames = 0,
770
- sampleRate = 22050,
771
- nFft = 2048,
772
- hopLength = 512,
773
- fmin = 0,
774
- fmax = 0,
775
- nIter = 32,
776
- htk = false,
777
- options: GuardedOptions = {},
778
- ): Float32Array {
779
- if (!(melPower instanceof Float32Array)) {
780
- const request = melPower;
781
- return melToAudio(
782
- request.melPower,
783
- request.nMels,
784
- request.nFrames,
785
- request.sampleRate,
786
- request.nFft,
787
- request.hopLength,
788
- request.fmin,
789
- request.fmax,
790
- request.nIter,
791
- request.htk,
792
- request,
793
- );
794
- }
795
- assertSampleRate('melToAudio', sampleRate);
796
- validateMatrix('melToAudio', melPower, nMels, nFrames, 'melPower', 'nMels', options);
797
- validatePositiveIntegers('melToAudio', { nFft, hopLength, nIter });
798
- validateMelFrequencyRange('melToAudio', fmin, fmax, sampleRate);
799
- return requireModule().melToAudio(
800
- melPower,
801
- nMels,
802
- nFrames,
803
- sampleRate,
804
- nFft,
805
- hopLength,
806
- fmin,
807
- fmax,
808
- nIter,
809
- htk,
810
- );
811
- }
812
-
813
- /** Reconstruct audio from an STFT magnitude matrix via Griffin-Lim. */
814
- export function griffinLim(request: GriffinLimRequest): Float32Array;
815
- export function griffinLim(
816
- magnitude: Float32Array,
817
- nBins: number,
818
- nFrames: number,
819
- sampleRate?: number,
820
- nFft?: number,
821
- hopLength?: number,
822
- nIter?: number,
823
- momentum?: number,
824
- options?: GuardedOptions,
825
- ): Float32Array;
826
- export function griffinLim(
827
- magnitude: Float32Array | GriffinLimRequest,
828
- nBins = 0,
829
- nFrames = 0,
830
- sampleRate = 22050,
831
- nFft = 2048,
832
- hopLength = 512,
833
- nIter = 32,
834
- momentum = 0.99,
835
- options: GuardedOptions = {},
836
- ): Float32Array {
837
- if (!(magnitude instanceof Float32Array)) {
838
- const request = magnitude;
839
- return griffinLim(
840
- request.magnitude,
841
- request.nBins,
842
- request.nFrames,
843
- request.sampleRate,
844
- request.nFft,
845
- request.hopLength,
846
- request.nIter,
847
- request.momentum,
848
- request,
849
- );
850
- }
851
- assertSampleRate('griffinLim', sampleRate);
852
- validateMatrix('griffinLim', magnitude, nBins, nFrames, 'magnitude', 'nBins', options);
853
- validatePositiveIntegers('griffinLim', { nFft, hopLength, nIter });
854
- return requireModule().griffinLim(
855
- magnitude,
856
- nBins,
857
- nFrames,
858
- sampleRate,
859
- nFft,
860
- hopLength,
861
- nIter,
862
- momentum,
863
- );
864
- }
865
-
866
- /**
867
- * Invert MFCC coefficients back to a Mel power spectrogram. Mirrors
868
- * `feature::mfcc_to_mel`.
869
- *
870
- * @param mfccCoefficients - MFCC matrix [nMfcc x nFrames] row-major
871
- * @param nMfcc - Number of MFCC coefficients
872
- * @param nFrames - Number of time frames
873
- * @param nMels - Number of Mel bins to reconstruct (default: 128)
874
- * @returns Mel power spectrogram result
875
- */
876
- export function mfccToMel(request: MfccToMelRequest): MelPowerResult;
877
- export function mfccToMel(
878
- mfccCoefficients: Float32Array,
879
- nMfcc: number,
880
- nFrames: number,
881
- nMels?: number,
882
- lifter?: number,
883
- options?: GuardedOptions,
884
- ): MelPowerResult;
885
- export function mfccToMel(
886
- mfccCoefficients: Float32Array | MfccToMelRequest,
887
- nMfcc = 0,
888
- nFrames = 0,
889
- nMels = 128,
890
- lifter = 0,
891
- options: GuardedOptions = {},
892
- ): MelPowerResult {
893
- if (!(mfccCoefficients instanceof Float32Array)) {
894
- const request = mfccCoefficients;
895
- return mfccToMel(
896
- request.mfccCoefficients,
897
- request.nMfcc,
898
- request.nFrames,
899
- request.nMels,
900
- request.lifter,
901
- request,
902
- );
903
- }
904
- validateMatrix(
905
- 'mfccToMel',
906
- mfccCoefficients,
907
- nMfcc,
908
- nFrames,
909
- 'mfccCoefficients',
910
- 'nMfcc',
911
- options,
912
- );
913
- validatePositiveIntegers('mfccToMel', { nMels });
914
- return requireModule().mfccToMel(mfccCoefficients, nMfcc, nFrames, nMels, lifter);
915
- }
916
-
917
- /**
918
- * Reconstruct audio directly from MFCC coefficients via Griffin-Lim. Mirrors
919
- * `feature::mfcc_to_audio`.
920
- *
921
- * @param mfccCoefficients - MFCC matrix [nMfcc x nFrames] row-major
922
- * @param nMfcc - Number of MFCC coefficients
923
- * @param nFrames - Number of time frames
924
- * @param nMels - Number of Mel bins (default: 128)
925
- * @param sampleRate - Sample rate in Hz (default: 22050)
926
- * @param nFft - FFT size (default: 2048)
927
- * @param hopLength - Hop length (default: 512)
928
- * @param fmin - Minimum Mel frequency in Hz (default: 0)
929
- * @param fmax - Maximum Mel frequency in Hz (default: 0 = sr/2)
930
- * @param nIter - Griffin-Lim iterations (default: 32)
931
- * @param htk - Use the HTK Mel formula instead of Slaney (default: false)
932
- * @returns Reconstructed audio samples (mono, float32)
933
- */
934
- export function mfccToAudio(request: MfccToAudioRequest): Float32Array;
935
- export function mfccToAudio(
936
- mfccCoefficients: Float32Array,
937
- nMfcc: number,
938
- nFrames: number,
939
- nMels?: number,
940
- sampleRate?: number,
941
- nFft?: number,
942
- hopLength?: number,
943
- fmin?: number,
944
- fmax?: number,
945
- nIter?: number,
946
- htk?: boolean,
947
- lifter?: number,
948
- options?: GuardedOptions,
949
- ): Float32Array;
950
- export function mfccToAudio(
951
- mfccCoefficients: Float32Array | MfccToAudioRequest,
952
- nMfcc = 0,
953
- nFrames = 0,
954
- nMels = 128,
955
- sampleRate = 22050,
956
- nFft = 2048,
957
- hopLength = 512,
958
- fmin = 0,
959
- fmax = 0,
960
- nIter = 32,
961
- htk = false,
962
- lifter = 0,
963
- options: GuardedOptions = {},
964
- ): Float32Array {
965
- if (!(mfccCoefficients instanceof Float32Array)) {
966
- const request = mfccCoefficients;
967
- return mfccToAudio(
968
- request.mfccCoefficients,
969
- request.nMfcc,
970
- request.nFrames,
971
- request.nMels,
972
- request.sampleRate,
973
- request.nFft,
974
- request.hopLength,
975
- request.fmin,
976
- request.fmax,
977
- request.nIter,
978
- request.htk,
979
- request.lifter,
980
- request,
981
- );
982
- }
983
- assertSampleRate('mfccToAudio', sampleRate);
984
- validateMatrix(
985
- 'mfccToAudio',
986
- mfccCoefficients,
987
- nMfcc,
988
- nFrames,
989
- 'mfccCoefficients',
990
- 'nMfcc',
991
- options,
992
- );
993
- validatePositiveIntegers('mfccToAudio', { nMels, nFft, hopLength, nIter });
994
- validateMelFrequencyRange('mfccToAudio', fmin, fmax, sampleRate);
995
- return requireModule().mfccToAudio(
996
- mfccCoefficients,
997
- nMfcc,
998
- nFrames,
999
- nMels,
1000
- sampleRate,
1001
- nFft,
1002
- hopLength,
1003
- fmin,
1004
- fmax,
1005
- nIter,
1006
- htk,
1007
- lifter,
1008
- );
1009
- }
1010
-
1011
624
  // ============================================================================
1012
625
  // Features - Chroma
1013
626
  // ============================================================================
@@ -1017,9 +630,9 @@ export function mfccToAudio(
1017
630
  *
1018
631
  * The chroma filterbank uses a fixed tuning of 0 (concert A440). Unlike
1019
632
  * librosa.feature.chroma_stft — which estimates tuning from the signal when none
1020
- * is given — this does NOT auto-estimate and exposes no tuning argument, so
1021
- * sharp/flat (non-A440) recordings smear across pitch classes. Estimate tuning
1022
- * separately via {@link estimateTuning} if a non-A440 reference matters.
633
+ * is given — this does NOT auto-estimate and takes no tuning argument. A
634
+ * tuning offset from {@link estimateTuning} is applied through `analyze`'s
635
+ * `tuning` option (and to chords through `detectChords`).
1023
636
  *
1024
637
  * @param samples - Audio samples (mono, float32)
1025
638
  * @param sampleRate - Sample rate in Hz (default: 22050)
@@ -1047,6 +660,6 @@ export function chroma(
1047
660
  return chroma(request.samples, request.sampleRate, request.nFft, request.hopLength, request);
1048
661
  }
1049
662
  validateSpectrogramSamples('chroma', samples, sampleRate, options);
1050
- validatePositiveIntegers('chroma', { nFft, hopLength });
1051
- return requireModule().chroma(samples, sampleRate, nFft, hopLength);
663
+ const fft = resolveFftOptions('chroma', nFft, hopLength);
664
+ return requireModule().chroma(samples, sampleRate, fft.nFft, fft.hopLength);
1052
665
  }