@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
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/module_state.ts","../src/validation.ts","../src/effects_transform.ts","../src/effects_voice_change.ts","../src/_chain_config.ts","../src/mastering_chain.ts","../src/mastering_core.ts","../src/mastering_dynamics.ts","../src/mastering_repair.ts","../src/mixing_oneshot.ts","../src/feature_core.ts","../src/feature_music.ts","../src/feature_pitch.ts","../src/feature_resample.ts","../src/feature_spectral.ts","../src/feature_spectrogram.ts","../src/codes.ts","../src/public_types_music.ts","../src/analysis_helpers.ts","../src/quick_analysis.ts","../src/audio.ts","../src/opfs_clip_pages.ts","../src/clip_page_streamer.ts","../src/live_audio.ts","../src/metering.ts","../src/project_internal.ts","../src/project_class.ts","../src/project_synth.ts","../src/project_types.ts","../src/realtime_engine.ts","../src/scale.ts","../src/stream_analyzer.ts","../src/mixer.ts","../src/realtime_voice_changer.ts","../src/streaming_processors.ts","../src/web_midi.ts","../src/worker_client.ts","../src/index.ts"],"sourcesContent":["/**\n * Numeric error codes carried by a {@link SonareError}. Mirrors the C ABI\n * `SonareError` enum (and the Node / Python surfaces), so the same failure\n * reports the same numeric code on every binding.\n */\nexport enum ErrorCode {\n Ok = 0,\n FileNotFound = 1,\n InvalidFormat = 2,\n DecodeFailed = 3,\n InvalidParameter = 4,\n OutOfMemory = 5,\n NotSupported = 6,\n InvalidState = 7,\n Cancelled = 8,\n Unknown = 99,\n}\n\n/**\n * Error thrown by libsonare on a native (C++) failure. Carries a numeric\n * {@link ErrorCode} `code` plus its canonical `codeName`, so callers can branch\n * on the cause instead of matching message text.\n */\nexport class SonareError extends Error {\n /** Numeric error code, equal to an {@link ErrorCode} value. */\n readonly code: number;\n /** Canonical name of `code`, e.g. `'InvalidParameter'`. */\n readonly codeName: string;\n\n constructor(code: number, codeName: string, message: string) {\n super(message);\n this.name = 'SonareError';\n this.code = code;\n this.codeName = codeName;\n }\n}\n\n/** Type guard: whether a caught value is a libsonare {@link SonareError}. */\nexport function isSonareError(value: unknown): value is SonareError {\n return (\n value instanceof Error &&\n (value as { name?: unknown }).name === 'SonareError' &&\n typeof (value as { code?: unknown }).code === 'number'\n );\n}\n","import { ErrorCode, SonareError } from './errors';\nimport type { SonareModule } from './sonare.js';\n\nlet wrappedModule: SonareModule | null = null;\n\n/**\n * Shape of the structured info the native `sonareExceptionInfo(ptr)` returns.\n */\ninterface NativeExceptionInfo {\n code: number;\n codeName: string;\n message: string;\n}\n\n/**\n * Recover the native exception-object pointer from a value thrown across the\n * WASM boundary. emscripten surfaces a C++ throw in two shapes depending on the\n * toolchain/exception mode:\n * - a raw pointer number (older / classic surfacing), or\n * - a `CppException` object exposing the pointer as `excPtr` (emscripten with\n * `-fexceptions`).\n * Returns null when the thrown value is neither (a genuine JS error), so the\n * caller rethrows it unchanged.\n */\nfunction nativeExceptionPtr(error: unknown): number | null {\n if (typeof error === 'number') {\n return error;\n }\n if (error !== null && typeof error === 'object') {\n const ptr = (error as { excPtr?: unknown }).excPtr;\n if (typeof ptr === 'number') {\n return ptr;\n }\n }\n return null;\n}\n\n/**\n * Turn a thrown native exception pointer into a {@link SonareError}. The bound\n * `sonareExceptionInfo` decodes the pointer back into { code, codeName,\n * message }.\n */\nfunction makeSonareError(raw: SonareModule, thrown: number): SonareError {\n let code: number = ErrorCode.Unknown;\n let codeName = 'Unknown';\n let message = `libsonare native exception (${thrown})`;\n try {\n const info = (\n raw as unknown as { sonareExceptionInfo?: (ptr: number) => NativeExceptionInfo }\n ).sonareExceptionInfo?.(thrown);\n if (info) {\n code = info.code ?? code;\n codeName = info.codeName ?? codeName;\n message = info.message || message;\n }\n } catch {\n // Fall back to the generic message if decoding fails.\n }\n return new SonareError(code, codeName, message);\n}\n\n/**\n * Wrap the embind module so a native C++ exception (which surfaces as a raw\n * pointer number or a `CppException` carrying one) is rethrown as a\n * {@link SonareError}. Only function-valued\n * members are wrapped, and the wrapper is cached per member so repeated access\n * stays cheap; non-function members (typed-array heap views, etc.) pass through\n * unchanged.\n */\nfunction wrapModuleErrors(raw: SonareModule): SonareModule {\n const cache = new Map<PropertyKey, unknown>();\n const objectCache = new WeakMap<object, unknown>();\n const convert = (error: unknown): never => {\n const ptr = nativeExceptionPtr(error);\n if (ptr !== null) {\n throw makeSonareError(raw, ptr);\n }\n throw error;\n };\n\n const wrapNativeObject = (value: unknown): unknown => {\n if (value === null || typeof value !== 'object') {\n return value;\n }\n if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer || value instanceof Promise) {\n return value;\n }\n const objectValue = value as object;\n const cached = objectCache.get(objectValue);\n if (cached) {\n return cached;\n }\n const methodCache = new Map<PropertyKey, unknown>();\n const wrapped = new Proxy(objectValue, {\n get(target, prop, receiver) {\n const member = Reflect.get(target, prop, receiver);\n if (typeof member !== 'function') {\n return member;\n }\n const cachedMethod = methodCache.get(prop);\n if (cachedMethod) {\n return cachedMethod;\n }\n const method = member as (...a: unknown[]) => unknown;\n const wrappedMethod = (...args: unknown[]) => {\n try {\n return wrapNativeObject(Reflect.apply(method, target, args));\n } catch (error) {\n return convert(error);\n }\n };\n methodCache.set(prop, wrappedMethod);\n return wrappedMethod;\n },\n });\n objectCache.set(objectValue, wrapped);\n return wrapped;\n };\n\n const wrapFunction = (value: (...a: unknown[]) => unknown): unknown => {\n const fnCache = new Map<PropertyKey, unknown>();\n return new Proxy(value, {\n get(target, prop, receiver) {\n const member = Reflect.get(target, prop, receiver);\n if (typeof member !== 'function') {\n return member;\n }\n const cachedMember = fnCache.get(prop);\n if (cachedMember) {\n return cachedMember;\n }\n const fn = member as (...a: unknown[]) => unknown;\n const wrappedMember = (...args: unknown[]) => {\n try {\n return wrapNativeObject(Reflect.apply(fn, target, args));\n } catch (error) {\n return convert(error);\n }\n };\n fnCache.set(prop, wrappedMember);\n return wrappedMember;\n },\n apply(t, thisArg, args) {\n try {\n return wrapNativeObject(Reflect.apply(t, thisArg, args as unknown[]));\n } catch (error) {\n return convert(error);\n }\n },\n construct(t, args, newTarget) {\n try {\n return wrapNativeObject(Reflect.construct(t, args as unknown[], newTarget)) as object;\n } catch (error) {\n return convert(error) as object;\n }\n },\n });\n };\n\n return new Proxy(raw, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (typeof value !== 'function') {\n return value;\n }\n const cached = cache.get(prop);\n if (cached) {\n return cached;\n }\n // Wrap as a Proxy (not a plain function) so embind class constructors\n // invoked via `new module.Foo(...)` keep their `[[Construct]]` behaviour\n // and prototype while still converting thrown native pointers.\n const wrapped = wrapFunction(value as (...a: unknown[]) => unknown);\n cache.set(prop, wrapped);\n return wrapped;\n },\n }) as SonareModule;\n}\n\nexport function setSonareModule(module: SonareModule): void {\n wrappedModule = wrapModuleErrors(module);\n}\n\nexport function getSonareModule(): SonareModule {\n if (!wrappedModule) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return wrappedModule;\n}\n","/**\n * Per-call validation options accepted by guarded wrappers. Empty-buffer\n * checks are always performed; pass `{ validate: false }` to opt out of the\n * O(n) NaN/Inf scan on hot paths.\n *\n * `{ validate: false }` only skips this JS-side pre-scan (which raises a\n * `RangeError` naming the exact offending index). It is NOT a way to push\n * non-finite samples into the core: the native layer always re-validates the\n * buffer (see `validate_offline_audio_input` in the C++ core), matching the C\n * ABI / Node / Python surfaces, so an NaN/Inf buffer still throws — just with a\n * generic native message instead of the indexed JS one.\n */\nexport interface ValidateOptions {\n validate?: boolean;\n}\n\n/**\n * Offline-analysis sample-rate bounds, mirroring the C++ core limits\n * (`sonare::kMinAudioSampleRate` / `kMaxAudioSampleRate` in `core/audio.h`).\n * Every guarded WASM entry point rejects the same out-of-range rates the C ABI,\n * Node, and Python surfaces do.\n */\nexport const MIN_AUDIO_SAMPLE_RATE = 8000;\nexport const MAX_AUDIO_SAMPLE_RATE = 384000;\n\nfunction assertNonEmptySamples(\n fnName: string,\n samples: ArrayLike<number>,\n argName = 'samples',\n): void {\n if (samples.length === 0) {\n throw new RangeError(`${fnName}: ${argName} must not be empty`);\n }\n}\n\nfunction assertFiniteSamples(\n fnName: string,\n samples: ArrayLike<number>,\n validate: boolean,\n argName = 'samples',\n): void {\n if (!validate) {\n return;\n }\n for (let i = 0; i < samples.length; i++) {\n const v = samples[i] as number;\n if (!Number.isFinite(v)) {\n throw new RangeError(`${fnName}: ${argName} contains NaN or Inf at index ${i}`);\n }\n }\n}\n\nexport function assertSamples(\n fnName: string,\n samples: ArrayLike<number>,\n validate: boolean,\n argName = 'samples',\n): void {\n assertNonEmptySamples(fnName, samples, argName);\n assertFiniteSamples(fnName, samples, validate, argName);\n}\n\nexport function assertFiniteScalar(fnName: string, value: number, argName: string): void {\n if (!Number.isFinite(value)) {\n throw new RangeError(`${fnName}: ${argName} must be a finite number`);\n }\n}\n\nexport function assertSampleRate(fnName: string, sampleRate: number): void {\n if (\n !Number.isInteger(sampleRate) ||\n sampleRate < MIN_AUDIO_SAMPLE_RATE ||\n sampleRate > MAX_AUDIO_SAMPLE_RATE\n ) {\n throw new RangeError(\n `${fnName}: sampleRate out of supported range [${MIN_AUDIO_SAMPLE_RATE}, ${MAX_AUDIO_SAMPLE_RATE}]`,\n );\n }\n}\n\n/** Validate and retain the public Audio.fromBuffer construction contract. */\nexport function validateAudioBuffer(samples: Float32Array, sampleRate: number): void {\n assertSamples('Audio.fromBuffer', samples, true);\n assertSampleRate('Audio.fromBuffer', sampleRate);\n}\n\nexport function assertNonNegativeInteger(fnName: string, value: number, argName: string): void {\n if (!Number.isInteger(value) || value < 0) {\n throw new RangeError(`${fnName}: ${argName} must be a non-negative integer`);\n }\n}\n\nexport function assertPositiveInteger(fnName: string, value: number, argName: string): void {\n if (!Number.isInteger(value) || value <= 0) {\n throw new RangeError(`${fnName}: ${argName} must be a positive integer`);\n }\n}\n\nexport function assertInterleavedSamples(\n fnName: string,\n samples: ArrayLike<number>,\n channels: number,\n validate: boolean,\n): void {\n assertSamples(fnName, samples, validate);\n assertPositiveInteger(fnName, channels, 'channels');\n if (samples.length % channels !== 0) {\n throw new RangeError(`${fnName}: samples length must be a multiple of channels`);\n }\n}\n","import { getSonareModule } from './module_state';\nimport type {\n HpssResult,\n NoteMoveOptions,\n NoteStretchOptions,\n PitchCorrectOptions,\n SpectralEditOptions,\n SpectralRegionOp,\n VoicedFlags,\n} from './public_types';\nimport type { ValidateOptions } from './validation';\nimport { assertSampleRate, assertSamples } from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n// The embind layer reads the companion voicing array as Float32Array. A flag is\n// a decision, not a magnitude: collapse to 1/0 on truthiness, which is the same\n// reduction the Node facade applies, so both surfaces agree on every accepted\n// input type.\nfunction toVoicedFloat32(voiced: VoicedFlags): Float32Array {\n const out = new Float32Array(voiced.length);\n for (let index = 0; index < voiced.length; index += 1) {\n out[index] = voiced[index] ? 1 : 0;\n }\n return out;\n}\n\nfunction resolveEffectFftOptions(\n fnName: string,\n nFft: unknown,\n hopLength: unknown,\n): { nFft: number; hopLength: number } {\n const resolvedNFft = nFft === undefined ? 2048 : nFft;\n const resolvedHopLength = hopLength === undefined ? 512 : hopLength;\n if (typeof resolvedNFft !== 'number' || !Number.isInteger(resolvedNFft)) {\n throw new TypeError(`${fnName}: nFft must be an integer`);\n }\n if (resolvedNFft < 2 || resolvedNFft > 2 ** 30) {\n throw new RangeError(`${fnName}: nFft must be an even power of two >= 2`);\n }\n if ((resolvedNFft & (resolvedNFft - 1)) !== 0) {\n throw new RangeError(`${fnName}: nFft must be an even power of two >= 2`);\n }\n if (typeof resolvedHopLength !== 'number' || !Number.isInteger(resolvedHopLength)) {\n throw new TypeError(`${fnName}: hopLength must be an integer`);\n }\n if (resolvedHopLength <= 0 || resolvedHopLength > 2 ** 31 - 1) {\n throw new RangeError(`${fnName}: hopLength must be a positive integer`);\n }\n return { nFft: resolvedNFft, hopLength: resolvedHopLength };\n}\n\nexport type NormalizeMode = 'peak' | 'rms';\n\nfunction resolveNormalizeMode(value: unknown): NormalizeMode {\n if (value === undefined) {\n return 'peak';\n }\n if (typeof value !== 'string') {\n throw new TypeError(\"normalize: mode must be the string 'peak' or 'rms'\");\n }\n if (value !== 'peak' && value !== 'rms') {\n throw new RangeError(\"normalize: mode must be the string 'peak' or 'rms'\");\n }\n return value;\n}\n\nfunction resolveHardMask(value: unknown, fnName: string): boolean {\n if (value === undefined) {\n return false;\n }\n if (typeof value !== 'boolean') {\n throw new TypeError(`${fnName}: hardMask must be a boolean`);\n }\n return value;\n}\n\n/** Canonical request form for HPSS. */\nexport interface HpssRequest {\n samples: Float32Array;\n sampleRate?: number;\n kernelHarmonic?: number;\n kernelPercussive?: number;\n nFft?: number;\n hopLength?: number;\n hardMask?: boolean;\n}\n\nexport interface HarmonicRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\nexport interface PercussiveRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\nexport interface TimeStretchRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n rate: number;\n nFft?: number;\n hopLength?: number;\n}\n\nexport interface PitchShiftRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n semitones: number;\n nFft?: number;\n hopLength?: number;\n}\n\nexport interface PitchCorrectToMidiRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n currentMidi?: number;\n targetMidi?: number;\n}\n\nexport interface PitchCorrectToMidiTimevaryingRequest extends ValidateOptions {\n samples: Float32Array;\n f0Hz: Float32Array;\n targetMidi: number;\n sampleRate?: number;\n hopLength?: number;\n voiced?: VoicedFlags;\n voicedProb?: Float32Array;\n}\n\nexport interface PitchCorrectTimevaryingRequest extends PitchCorrectOptions {\n samples: Float32Array;\n f0Hz: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n}\n\nexport interface NoteStretchRequest extends NoteStretchOptions, ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\nexport interface NoteMoveRequest extends NoteMoveOptions, ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\nexport interface NormalizeRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n targetDb?: number;\n mode?: NormalizeMode;\n}\n\nexport interface SpectralEditRequest extends SpectralEditOptions, ValidateOptions {\n samples: Float32Array;\n sampleRate: number;\n ops?: SpectralRegionOp[];\n}\n\n// ============================================================================\n// Effects\n// ============================================================================\n\n/**\n * Perform Harmonic-Percussive Source Separation (HPSS).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param kernelHarmonic - Horizontal median filter size for harmonic (default: 31)\n * @param kernelPercussive - Vertical median filter size for percussive (default: 31)\n * @returns Separated harmonic and percussive components\n */\nexport function hpss(request: HpssRequest): HpssResult;\nexport function hpss(\n samples: Float32Array,\n sampleRate?: number,\n kernelHarmonic?: number,\n kernelPercussive?: number,\n nFft?: number,\n hopLength?: number,\n hardMask?: boolean,\n): HpssResult;\nexport function hpss(\n samples: Float32Array | HpssRequest,\n sampleRate = 22050,\n kernelHarmonic = 31,\n kernelPercussive = 31,\n nFft?: number,\n hopLength?: number,\n hardMask?: boolean,\n): HpssResult {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate, kernelHarmonic, kernelPercussive, nFft, hopLength, hardMask }\n : samples;\n const fftOptions = resolveEffectFftOptions('hpss', request.nFft, request.hopLength);\n const resolvedHardMask = resolveHardMask(request.hardMask, 'hpss');\n return requireModule().hpssEx(\n request.samples,\n request.sampleRate ?? 22050,\n request.kernelHarmonic ?? 31,\n request.kernelPercussive ?? 31,\n fftOptions.nFft,\n fftOptions.hopLength,\n resolvedHardMask,\n );\n}\n\n/**\n * Extract harmonic component from audio.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz\n * @returns Harmonic component\n */\nexport function harmonic(request: HarmonicRequest): Float32Array;\nexport function harmonic(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function harmonic(\n samples: Float32Array | HarmonicRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('harmonic', request.samples, request.validate !== false);\n return requireModule().harmonic(request.samples, request.sampleRate ?? 22050);\n}\n\n/**\n * Extract percussive component from audio.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz\n * @returns Percussive component\n */\nexport function percussive(request: PercussiveRequest): Float32Array;\nexport function percussive(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function percussive(\n samples: Float32Array | PercussiveRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('percussive', request.samples, request.validate !== false);\n return requireModule().percussive(request.samples, request.sampleRate ?? 22050);\n}\n\n/**\n * Time-stretch audio without changing pitch.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param rate - Time stretch rate (0.5 = double duration, 2.0 = half duration)\n * @returns Time-stretched audio\n */\nexport function timeStretch(request: TimeStretchRequest): Float32Array;\nexport function timeStretch(\n samples: Float32Array,\n sampleRate: number,\n rate: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function timeStretch(\n samples: Float32Array,\n sampleRate: number,\n rate: number,\n nFft?: number,\n hopLength?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function timeStretch(\n samples: Float32Array | TimeStretchRequest,\n sampleRate?: number,\n rate?: number,\n nFftOrOptions?: number | ValidateOptions,\n hopLength?: number,\n options: ValidateOptions = {},\n): Float32Array {\n if (\n nFftOrOptions !== undefined &&\n nFftOrOptions !== null &&\n typeof nFftOrOptions !== 'number' &&\n typeof nFftOrOptions !== 'object'\n ) {\n throw new TypeError('timeStretch: nFft must be an integer or options object');\n }\n if (nFftOrOptions === null) {\n throw new TypeError('timeStretch: nFft must be an integer or options object');\n }\n const positionalOptions =\n typeof nFftOrOptions === 'object' && nFftOrOptions !== null ? nFftOrOptions : options;\n const positionalNFft = typeof nFftOrOptions === 'number' ? nFftOrOptions : undefined;\n const request: TimeStretchRequest =\n samples instanceof Float32Array\n ? {\n samples,\n sampleRate,\n rate: rate as number,\n nFft: positionalNFft,\n hopLength,\n ...positionalOptions,\n }\n : samples;\n assertSamples('timeStretch', request.samples, request.validate !== false);\n const fftOptions = resolveEffectFftOptions('timeStretch', request.nFft, request.hopLength);\n return requireModule().timeStretchEx(\n request.samples,\n request.sampleRate ?? 22050,\n request.rate,\n fftOptions.nFft,\n fftOptions.hopLength,\n );\n}\n\n/**\n * Pitch-shift audio without changing duration.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param semitones - Pitch shift in semitones (+12 = one octave up, -12 = one octave down)\n * @returns Pitch-shifted audio\n */\nexport function pitchShift(request: PitchShiftRequest): Float32Array;\nexport function pitchShift(\n samples: Float32Array,\n sampleRate: number,\n semitones: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function pitchShift(\n samples: Float32Array,\n sampleRate: number,\n semitones: number,\n nFft?: number,\n hopLength?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function pitchShift(\n samples: Float32Array | PitchShiftRequest,\n sampleRate?: number,\n semitones?: number,\n nFftOrOptions?: number | ValidateOptions,\n hopLength?: number,\n options: ValidateOptions = {},\n): Float32Array {\n if (\n nFftOrOptions !== undefined &&\n nFftOrOptions !== null &&\n typeof nFftOrOptions !== 'number' &&\n typeof nFftOrOptions !== 'object'\n ) {\n throw new TypeError('pitchShift: nFft must be an integer or options object');\n }\n if (nFftOrOptions === null) {\n throw new TypeError('pitchShift: nFft must be an integer or options object');\n }\n const positionalOptions =\n typeof nFftOrOptions === 'object' && nFftOrOptions !== null ? nFftOrOptions : options;\n const positionalNFft = typeof nFftOrOptions === 'number' ? nFftOrOptions : undefined;\n const request: PitchShiftRequest =\n samples instanceof Float32Array\n ? {\n samples,\n sampleRate,\n semitones: semitones as number,\n nFft: positionalNFft,\n hopLength,\n ...positionalOptions,\n }\n : samples;\n assertSamples('pitchShift', request.samples, request.validate !== false);\n const fftOptions = resolveEffectFftOptions('pitchShift', request.nFft, request.hopLength);\n return requireModule().pitchShiftEx(\n request.samples,\n request.sampleRate ?? 22050,\n request.semitones,\n fftOptions.nFft,\n fftOptions.hopLength,\n );\n}\n\n/**\n * Pitch-correct audio from a current MIDI note to a target MIDI note.\n *\n * Applies one constant, immediate transpose with no retune glide and preserves\n * the input buffer length. Use {@link pitchCorrectToMidiTimevarying} for a\n * caller-supplied pitch contour.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz\n * @param currentMidi - Detected/current MIDI note number\n * @param targetMidi - Desired MIDI note number\n * @returns Pitch-corrected audio\n */\nexport function pitchCorrectToMidi(request: PitchCorrectToMidiRequest): Float32Array;\nexport function pitchCorrectToMidi(\n samples: Float32Array,\n sampleRate?: number,\n currentMidi?: number,\n targetMidi?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function pitchCorrectToMidi(\n samples: Float32Array | PitchCorrectToMidiRequest,\n sampleRate = 22050,\n currentMidi = 69.0,\n targetMidi = 69.0,\n options: ValidateOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate, currentMidi, targetMidi, ...options }\n : samples;\n assertSamples('pitchCorrectToMidi', request.samples, request.validate !== false);\n return requireModule().pitchCorrectToMidi(\n request.samples,\n request.sampleRate ?? 22050,\n request.currentMidi ?? 69.0,\n request.targetMidi ?? 69.0,\n );\n}\n\n/**\n * Contour-following (\"time-varying\") pitch correction toward a MIDI target.\n *\n * Unlike {@link pitchCorrectToMidi} (a single constant transpose), this follows\n * the caller-supplied per-frame `f0Hz` contour and retunes every voiced frame\n * toward `targetMidi`, so vibrato/drift in the source is tracked rather than\n * flattened. `voiced` (truthy = voiced) and `voicedProb` ([0,1]) are optional;\n * omitting them treats every frame as voiced. An `f0Hz` NaN is accepted only\n * when the corresponding `voiced` entry is falsy, matching pYIN output. The\n * `voicedFlag` / `voicedProb` arrays of a {@link PitchResult} can be passed\n * through directly.\n *\n * @param samples - Audio samples (mono, float32)\n * @param f0Hz - Per-frame measured F0 in Hz (one entry per analysis frame)\n * @param targetMidi - Desired MIDI note number\n * @param sampleRate - Sample rate in Hz\n * @param hopLength - F0 hop in samples (frame i covers sample i*hopLength)\n * @param voiced - Optional per-frame voiced flags (truthy = voiced)\n * @param voicedProb - Optional per-frame voicing probability in [0, 1]\n * @returns Pitch-corrected audio\n */\nexport function pitchCorrectToMidiTimevarying(\n request: PitchCorrectToMidiTimevaryingRequest,\n): Float32Array;\nexport function pitchCorrectToMidiTimevarying(\n samples: Float32Array,\n f0Hz: Float32Array,\n targetMidi: number,\n sampleRate?: number,\n hopLength?: number,\n voiced?: VoicedFlags,\n voicedProb?: Float32Array,\n options?: ValidateOptions,\n): Float32Array;\nexport function pitchCorrectToMidiTimevarying(\n samples: Float32Array | PitchCorrectToMidiTimevaryingRequest,\n f0Hz?: Float32Array,\n targetMidi?: number,\n sampleRate = 22050,\n hopLength = 512,\n voiced?: VoicedFlags,\n voicedProb?: Float32Array,\n options: ValidateOptions = {},\n): Float32Array {\n const request: PitchCorrectToMidiTimevaryingRequest =\n samples instanceof Float32Array\n ? {\n samples,\n f0Hz: f0Hz as Float32Array,\n targetMidi: targetMidi as number,\n sampleRate,\n hopLength,\n voiced,\n voicedProb,\n ...options,\n }\n : samples;\n assertSamples('pitchCorrectToMidiTimevarying', request.samples, request.validate !== false);\n if (request.voiced && request.voiced.length !== request.f0Hz.length) {\n throw new RangeError('pitchCorrectToMidiTimevarying: voiced length must match f0Hz length');\n }\n if (request.voicedProb && request.voicedProb.length !== request.f0Hz.length) {\n throw new RangeError('pitchCorrectToMidiTimevarying: voicedProb length must match f0Hz length');\n }\n const voicedF32 = request.voiced ? toVoicedFloat32(request.voiced) : undefined;\n return requireModule().pitchCorrectToMidiTimevarying(\n request.samples,\n request.sampleRate ?? 22050,\n request.f0Hz,\n request.targetMidi,\n request.hopLength ?? 512,\n voicedF32,\n request.voicedProb,\n );\n}\n\n/**\n * Contour-following pitch correction toward a fixed MIDI note OR a musical\n * scale, with tunable retune strength and vibrato preservation.\n *\n * Generalises {@link pitchCorrectToMidiTimevarying}: the same caller-supplied\n * per-frame `f0Hz` contour drives correction, but `options.mode` selects between\n * a fixed-MIDI target (`'midi'`, default) and scale quantisation (`'scale'`),\n * and the retune knobs shape natural-vs-robotic correction. An `f0Hz` NaN is\n * accepted only for a frame marked unvoiced.\n *\n * @param samples - Audio samples (mono, float32)\n * @param f0Hz - Per-frame measured F0 in Hz (one entry per analysis frame)\n * @param sampleRate - Sample rate in Hz\n * @param hopLength - F0 hop in samples (frame i covers sample i*hopLength)\n * @param options - Target mode + retune knobs + optional voiced/voicedProb arrays\n * @returns Pitch-corrected audio\n */\nexport function pitchCorrectTimevarying(request: PitchCorrectTimevaryingRequest): Float32Array;\nexport function pitchCorrectTimevarying(\n samples: Float32Array,\n f0Hz: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n options?: PitchCorrectOptions,\n): Float32Array;\nexport function pitchCorrectTimevarying(\n samples: Float32Array | PitchCorrectTimevaryingRequest,\n f0Hz?: Float32Array,\n sampleRate = 22050,\n hopLength = 512,\n options: PitchCorrectOptions = {},\n): Float32Array {\n const request: PitchCorrectTimevaryingRequest =\n samples instanceof Float32Array\n ? { samples, f0Hz: f0Hz as Float32Array, sampleRate, hopLength, ...options }\n : samples;\n assertSamples('pitchCorrectTimevarying', request.samples, request.validate !== false);\n if (request.voiced && request.voiced.length !== request.f0Hz.length) {\n throw new RangeError('pitchCorrectTimevarying: voiced length must match f0Hz length');\n }\n if (request.voicedProb && request.voicedProb.length !== request.f0Hz.length) {\n throw new RangeError('pitchCorrectTimevarying: voicedProb length must match f0Hz length');\n }\n const nativeOptions = {\n ...request,\n voiced: request.voiced ? toVoicedFloat32(request.voiced) : undefined,\n };\n return requireModule().pitchCorrectTimevarying(\n request.samples,\n request.sampleRate ?? 22050,\n request.f0Hz,\n request.hopLength ?? 512,\n nativeOptions,\n );\n}\n\n/**\n * Time-stretch a note region between two sample offsets without changing pitch.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz\n * @param onsetSample - Note onset position in samples\n * @param offsetSample - Note offset position in samples\n * @param stretchRatio - Stretch ratio (0.5 = half duration, 2.0 = double duration)\n * @returns Audio with the note region stretched\n */\nexport function noteStretch(request: NoteStretchRequest): Float32Array;\nexport function noteStretch(\n samples: Float32Array,\n sampleRate?: number,\n options?: NoteStretchOptions & ValidateOptions,\n): Float32Array;\nexport function noteStretch(\n samples: Float32Array | NoteStretchRequest,\n sampleRate = 22050,\n options: NoteStretchOptions & ValidateOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('noteStretch', request.samples, request.validate !== false);\n return requireModule().noteStretch(\n request.samples,\n request.sampleRate ?? 22050,\n request.onsetSample ?? 0,\n request.offsetSample ?? request.samples.length,\n request.stretchRatio ?? 1.0,\n );\n}\n\n/** Move a note region to a new onset without changing its duration. */\nexport function noteMove(request: NoteMoveRequest): Float32Array;\nexport function noteMove(\n samples: Float32Array,\n sampleRate?: number,\n options?: NoteMoveOptions & ValidateOptions,\n): Float32Array;\nexport function noteMove(\n samples: Float32Array | NoteMoveRequest,\n sampleRate = 22050,\n options: NoteMoveOptions & ValidateOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('noteMove', request.samples, request.validate !== false);\n return requireModule().noteMove(\n request.samples,\n request.sampleRate ?? 22050,\n request.onsetSample ?? 0,\n request.offsetSample ?? request.samples.length,\n request.targetOnsetSample ?? 0,\n );\n}\n\n/**\n * Normalize audio to a target peak or RMS level.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param targetDb - Finite target at or below 0 dBFS (default: 0 dB = full scale).\n * For `mode: 'peak'`, this is the peak target; for `mode: 'rms'`, this is the RMS target.\n * @param mode - Normalization mode: `'peak'` (default) or `'rms'`.\n * @returns Normalized audio\n */\nexport function normalize(request: NormalizeRequest): Float32Array;\nexport function normalize(\n samples: Float32Array,\n sampleRate: number,\n targetDb?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function normalize(\n samples: Float32Array,\n sampleRate: number,\n targetDb?: number,\n mode?: NormalizeMode,\n options?: ValidateOptions,\n): Float32Array;\nexport function normalize(\n samples: Float32Array | NormalizeRequest,\n sampleRate?: number,\n targetDb = 0.0,\n modeOrOptions: NormalizeMode | ValidateOptions = 'peak',\n options: ValidateOptions = {},\n): Float32Array {\n if (\n modeOrOptions !== undefined &&\n modeOrOptions !== null &&\n typeof modeOrOptions !== 'string' &&\n typeof modeOrOptions !== 'object'\n ) {\n throw new TypeError(\"normalize: mode must be the string 'peak' or 'rms'\");\n }\n if (modeOrOptions === null) {\n throw new TypeError(\"normalize: mode must be the string 'peak' or 'rms'\");\n }\n const positionalOptions =\n typeof modeOrOptions === 'object' && modeOrOptions !== null ? modeOrOptions : options;\n const positionalMode = typeof modeOrOptions === 'string' ? modeOrOptions : undefined;\n const request: NormalizeRequest =\n samples instanceof Float32Array\n ? { samples, sampleRate, targetDb, mode: positionalMode, ...positionalOptions }\n : samples;\n assertSamples('normalize', request.samples, request.validate !== false);\n const mode = resolveNormalizeMode(request.mode);\n return requireModule().normalizeEx(\n request.samples,\n request.sampleRate ?? 22050,\n request.targetDb ?? 0.0,\n mode,\n );\n}\n\n/**\n * Apply region-based spectral edits (gain/attenuate/mute/heal) to mono audio.\n *\n * Each op is a time x frequency rectangle applied in array order over a single\n * STFT buffer, so a later op observes the result of earlier ops. The output has\n * the same length and sample rate as the input; an empty `ops` list is an\n * identity transform (within the iSTFT's own tolerance).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz\n * @param ops - Region edit ops applied in order ({@link SpectralRegionOp})\n * @param options - STFT + heal configuration ({@link SpectralEditOptions})\n * @returns Edited audio\n */\nexport function spectralEdit(request: SpectralEditRequest): Float32Array;\nexport function spectralEdit(\n samples: Float32Array,\n sampleRate: number,\n ops?: SpectralRegionOp[],\n options?: SpectralEditOptions & ValidateOptions,\n): Float32Array;\nexport function spectralEdit(\n samples: Float32Array | SpectralEditRequest,\n sampleRate?: number,\n ops: SpectralRegionOp[] = [],\n options: SpectralEditOptions & ValidateOptions = {},\n): Float32Array {\n const request: SpectralEditRequest =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ops, ...options }\n : samples;\n assertSamples('spectralEdit', request.samples, request.validate !== false);\n assertSampleRate('spectralEdit', request.sampleRate);\n return requireModule().spectralEdit(\n request.samples,\n request.sampleRate,\n request.ops ?? [],\n request as unknown as Record<string, unknown>,\n );\n}\n","import { getSonareModule } from './module_state';\nimport type { RealtimeVoiceChangerConfigInput } from './public_types';\nimport type { ValidateOptions } from './validation';\nimport { assertSamples } from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n/** Options for {@link voiceChange}. All fields are optional. */\nexport interface VoiceChangeOptions extends ValidateOptions {\n /** Pitch shift in semitones (negative = down). Default 0. */\n pitchSemitones?: number;\n /** Formant scale factor (>1 brightens, <1 darkens). Default 1. */\n formantFactor?: number;\n}\n\n/** Canonical request form for one-shot voice changing. */\nexport interface VoiceChangeRequest extends VoiceChangeOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\n/**\n * Apply a voice change by shifting pitch and formants independently.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz\n * @param options - Pitch/formant settings ({@link VoiceChangeOptions})\n * @returns Voice-changed audio\n */\nexport function voiceChange(request: VoiceChangeRequest): Float32Array;\nexport function voiceChange(\n samples: Float32Array,\n sampleRate?: number,\n options?: VoiceChangeOptions,\n): Float32Array;\nexport function voiceChange(\n samples: Float32Array | VoiceChangeRequest,\n sampleRate = 22050,\n options: VoiceChangeOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('voiceChange', request.samples, request.validate !== false);\n return requireModule().voiceChange(\n request.samples,\n request.sampleRate ?? 22050,\n request.pitchSemitones ?? 0.0,\n request.formantFactor ?? 1.0,\n );\n}\n\n/** Options for the offline {@link voiceChangeRealtime} convenience wrapper. */\nexport interface VoiceChangeRealtimeOptions extends ValidateOptions {\n /** Channel count (1 = mono, 2 = interleaved stereo). */\n channels?: 1 | 2;\n /** @deprecated The shared C-ABI renderer uses a fixed cross-surface block size. */\n blockSize?: number;\n}\n\n/** Canonical request form for offline realtime voice changing. */\nexport interface VoiceChangeRealtimeRequest extends VoiceChangeRealtimeOptions {\n samples: Float32Array;\n sampleRate?: number;\n preset?: RealtimeVoiceChangerConfigInput;\n}\n\n/**\n * Applies the realtime voice-changer chain to a whole buffer in one call.\n *\n * Uses the shared C-ABI renderer, so Python, Node, and WASM use the same\n * fixed block size and latency compensation. For mono, `samples` is a plain\n * buffer; for stereo, it is interleaved (L0,R0,L1,R1,...).\n *\n * @param samples - Audio samples (mono, or interleaved stereo when channels=2)\n * @param sampleRate - Sample rate in Hz (default 48000, matching Python/Node)\n * @param preset - Voice-changer preset id or full config object\n * @param options - Channel count and block size ({@link VoiceChangeRealtimeOptions})\n * @returns The processed buffer (same layout/length as the input).\n */\nexport function voiceChangeRealtime(request: VoiceChangeRealtimeRequest): Float32Array;\nexport function voiceChangeRealtime(\n samples: Float32Array,\n sampleRate?: number,\n preset?: RealtimeVoiceChangerConfigInput,\n options?: VoiceChangeRealtimeOptions,\n): Float32Array;\nexport function voiceChangeRealtime(\n samples: Float32Array | VoiceChangeRealtimeRequest,\n sampleRate = 48000,\n preset: RealtimeVoiceChangerConfigInput = 'neutral-monitor',\n options: VoiceChangeRealtimeOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array ? { samples, sampleRate, preset, ...options } : samples;\n assertSamples('voiceChangeRealtime', request.samples, request.validate !== false);\n const channels = request.channels ?? 1;\n if (channels !== 1 && channels !== 2) {\n throw new Error('voiceChangeRealtime: channels must be 1 or 2.');\n }\n if (channels === 2 && request.samples.length % 2 !== 0) {\n throw new Error('voiceChangeRealtime: stereo input length must be a multiple of 2.');\n }\n const presetConfig = request.preset ?? 'neutral-monitor';\n return requireModule().voiceChangeRealtime(\n request.samples,\n request.sampleRate ?? 48000,\n typeof presetConfig === 'string' ? presetConfig : JSON.stringify(presetConfig),\n channels,\n );\n}\n","import type { MasteringChainConfig } from './public_types';\n\ntype ChainSection = { [key: string]: number | boolean | ChainSection | undefined };\n\n/**\n * Flattens a nested {@link MasteringChainConfig} into the dot-notation\n * `{ \"module.processor.param\": value }` map the core consumes. Internal helper\n * shared by the mastering-chain / master-audio entry points. The core owns\n * legacy leaf-name aliases, so this remains a structural flattening step.\n *\n * A key the caller already wrote in dot notation carries through untouched, so\n * both spellings a {@link MasteringChainConfig} accepts reach the core as the\n * same parameter — matching what the Python binding documents. An unknown key\n * in either spelling is rejected by the core, not here.\n */\nexport function flattenChainConfig(config: MasteringChainConfig): Record<string, number | boolean> {\n const out: Record<string, number | boolean> = {};\n const walk = (node: ChainSection, prefix: string): void => {\n for (const [key, value] of Object.entries(node)) {\n const path = prefix ? `${prefix}.${key}` : key;\n if (typeof value === 'number' || typeof value === 'boolean') {\n out[path] = value;\n } else if (value !== null && typeof value === 'object') {\n walk(value, path);\n } else if (value !== undefined) {\n throw new TypeError(`Mastering override '${path}' must be a number or boolean.`);\n }\n }\n };\n walk(config as ChainSection, '');\n\n return out;\n}\n","import { flattenChainConfig } from './_chain_config';\nimport { getSonareModule } from './module_state';\nimport type {\n MasteringChainConfig,\n MasteringChainResult,\n MasteringChainStereoResult,\n MasteringPreset,\n} from './public_types';\nimport type { ProgressCallback } from './sonare.js';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n/** Internal envelope selecting the core dotted-param parser in the embind layer. */\nfunction canonicalChainConfig(config: MasteringChainConfig): Record<string, unknown> {\n return { __flatParams: flattenChainConfig(config) };\n}\n\nexport interface MasteringChainRequest {\n samples: Float32Array;\n sampleRate?: number;\n config?: MasteringChainConfig;\n onProgress?: ProgressCallback;\n cancel?: () => boolean;\n}\n\nexport interface MasteringChainStereoRequest {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n config?: MasteringChainConfig;\n onProgress?: ProgressCallback;\n cancel?: () => boolean;\n}\n\n/** Canonical request form for one-shot preset mastering. */\nexport interface MasterAudioRequest {\n samples: Float32Array;\n sampleRate?: number;\n preset?: MasteringPreset;\n overrides?: MasteringChainConfig;\n onProgress?: ProgressCallback;\n cancel?: () => boolean;\n}\n\n/** Canonical request form for one-shot stereo preset mastering. */\nexport interface MasterAudioStereoRequest {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n preset?: MasteringPreset;\n overrides?: MasteringChainConfig;\n onProgress?: ProgressCallback;\n cancel?: () => boolean;\n}\n\nfunction masterAudioRequest(\n requestOrSamples: MasterAudioRequest | Float32Array,\n sampleRate: number,\n preset: MasteringPreset,\n overrides: MasteringChainConfig | null,\n onProgress?: ProgressCallback,\n): MasterAudioRequest {\n if (requestOrSamples instanceof Float32Array) {\n return {\n samples: requestOrSamples,\n sampleRate,\n preset,\n overrides: overrides ?? {},\n onProgress,\n };\n }\n return requestOrSamples;\n}\n\nfunction masterAudioStereoRequest(\n requestOrLeft: MasterAudioStereoRequest | Float32Array,\n right: Float32Array | undefined,\n sampleRate: number,\n preset: MasteringPreset,\n overrides: MasteringChainConfig | null,\n onProgress?: ProgressCallback,\n): MasterAudioStereoRequest {\n if (requestOrLeft instanceof Float32Array) {\n return {\n left: requestOrLeft,\n right: right as Float32Array,\n sampleRate,\n preset,\n overrides: overrides ?? {},\n onProgress,\n };\n }\n return requestOrLeft;\n}\n\n/**\n * Apply a configurable mastering chain in WASM.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param config - Chain stage configuration\n * @returns Processed audio, loudness metadata, and applied stage names\n */\nexport function masteringChain(request: MasteringChainRequest): MasteringChainResult;\nexport function masteringChain(\n samples: Float32Array,\n sampleRate?: number,\n config?: MasteringChainConfig,\n onProgress?: ProgressCallback,\n): MasteringChainResult;\nexport function masteringChain(\n samples: Float32Array | MasteringChainRequest,\n sampleRate = 22050,\n config: MasteringChainConfig = {},\n onProgress?: ProgressCallback,\n): MasteringChainResult {\n const request =\n samples instanceof Float32Array ? { samples, sampleRate, config, onProgress } : samples;\n if (request.onProgress || request.cancel) {\n return requireModule().masteringChainWithProgress(\n request.samples,\n request.sampleRate ?? 22050,\n canonicalChainConfig(request.config ?? {}),\n request.onProgress ?? (() => {}),\n request.cancel ?? (() => false),\n );\n }\n return requireModule().masteringChain(\n request.samples,\n request.sampleRate ?? 22050,\n canonicalChainConfig(request.config ?? {}),\n );\n}\n\n/**\n * Apply a configurable stereo mastering chain in WASM.\n *\n * @param left - Left channel samples\n * @param right - Right channel samples\n * @param sampleRate - Sample rate in Hz\n * @param config - Chain stage configuration\n * @returns Processed stereo audio, loudness metadata, and applied stage names\n */\nexport function masteringChainStereo(\n request: MasteringChainStereoRequest,\n): MasteringChainStereoResult;\nexport function masteringChainStereo(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n config?: MasteringChainConfig,\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult;\nexport function masteringChainStereo(\n left: Float32Array | MasteringChainStereoRequest,\n right?: Float32Array,\n sampleRate = 22050,\n config: MasteringChainConfig = {},\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, config, onProgress }\n : left;\n if (request.left.length !== request.right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n if (request.onProgress || request.cancel) {\n return requireModule().masteringChainStereoWithProgress(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n canonicalChainConfig(request.config ?? {}),\n request.onProgress ?? (() => {}),\n request.cancel ?? (() => false),\n );\n }\n return requireModule().masteringChainStereo(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n canonicalChainConfig(request.config ?? {}),\n );\n}\n\n/**\n * Apply a configurable mastering chain in WASM with progress reporting.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param config - Chain stage configuration\n * @param onProgress - Progress callback (progress: 0-1, stage: string)\n * @returns Processed audio, loudness metadata, and applied stage names\n */\nexport function masteringChainWithProgress(\n request: MasteringChainRequest & Required<Pick<MasteringChainRequest, 'onProgress'>>,\n): MasteringChainResult;\nexport function masteringChainWithProgress(\n samples: Float32Array,\n sampleRate?: number,\n config?: MasteringChainConfig,\n onProgress?: ProgressCallback,\n): MasteringChainResult;\nexport function masteringChainWithProgress(\n samples: Float32Array | MasteringChainRequest,\n sampleRate = 22050,\n config: MasteringChainConfig = {},\n onProgress?: ProgressCallback,\n): MasteringChainResult {\n const request =\n samples instanceof Float32Array ? { samples, sampleRate, config, onProgress } : samples;\n if (!request.onProgress) {\n throw new TypeError('masteringChainWithProgress: onProgress is required');\n }\n return requireModule().masteringChainWithProgress(\n request.samples,\n request.sampleRate ?? 22050,\n canonicalChainConfig(request.config ?? {}),\n request.onProgress,\n request.cancel ?? (() => false),\n );\n}\n\n/**\n * Apply a configurable stereo mastering chain in WASM with progress reporting.\n *\n * @param left - Left channel samples\n * @param right - Right channel samples\n * @param sampleRate - Sample rate in Hz\n * @param config - Chain stage configuration\n * @param onProgress - Progress callback (progress: 0-1, stage: string)\n * @returns Processed stereo audio, loudness metadata, and applied stage names\n */\nexport function masteringChainStereoWithProgress(\n request: MasteringChainStereoRequest & Required<Pick<MasteringChainStereoRequest, 'onProgress'>>,\n): MasteringChainStereoResult;\nexport function masteringChainStereoWithProgress(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n config?: MasteringChainConfig,\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult;\nexport function masteringChainStereoWithProgress(\n left: Float32Array | MasteringChainStereoRequest,\n right?: Float32Array,\n sampleRate = 22050,\n config: MasteringChainConfig = {},\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, config, onProgress }\n : left;\n if (!request.onProgress) {\n throw new TypeError('masteringChainStereoWithProgress: onProgress is required');\n }\n if (request.left.length !== request.right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n return requireModule().masteringChainStereoWithProgress(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n canonicalChainConfig(request.config ?? {}),\n request.onProgress,\n request.cancel ?? (() => false),\n );\n}\n\n/**\n * List built-in mastering preset identifiers.\n *\n * @returns Preset names in display order (e.g. \"pop\", \"edm\", \"aiMusic\")\n */\nexport function masteringPresetNames(): MasteringPreset[] {\n return Array.from(requireModule().masteringPresetNames()) as MasteringPreset[];\n}\n\n/**\n * Apply a named mastering preset chain to mono audio.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param presetName - Preset identifier from {@link masteringPresetNames}\n * @param overrides - Optional nested {@link MasteringChainConfig} applied on top of the preset (e.g. `{ loudness: { targetLufs: -14 } }`). Pass `null` for preset defaults.\n * @param onProgress - Optional per-stage progress callback (progress: 0-1, stage: string).\n * @returns Processed audio, loudness metadata, and applied stage names\n */\nexport function masterAudio(request: MasterAudioRequest): MasteringChainResult;\nexport function masterAudio(\n samples: Float32Array,\n sampleRate?: number,\n presetName?: MasteringPreset,\n overrides?: MasteringChainConfig,\n onProgress?: ProgressCallback,\n): MasteringChainResult;\nexport function masterAudio(\n samples: MasterAudioRequest | Float32Array,\n sampleRate = 22050,\n presetName: MasteringPreset = 'pop',\n overrides: MasteringChainConfig = {},\n onProgress?: ProgressCallback,\n): MasteringChainResult {\n const request = masterAudioRequest(samples, sampleRate, presetName, overrides, onProgress);\n const flat = flattenChainConfig(request.overrides ?? {});\n if (request.onProgress || request.cancel) {\n return requireModule().masterAudioWithProgress(\n request.preset ?? 'pop',\n request.samples,\n request.sampleRate ?? 22050,\n flat,\n request.onProgress ?? (() => {}),\n request.cancel ?? (() => false),\n );\n }\n return requireModule().masterAudio(\n request.preset ?? 'pop',\n request.samples,\n request.sampleRate ?? 22050,\n flat,\n );\n}\n\n/**\n * Apply a named mastering preset chain to stereo audio.\n *\n * @param left - Left channel samples\n * @param right - Right channel samples\n * @param sampleRate - Sample rate in Hz\n * @param presetName - Preset identifier from {@link masteringPresetNames}\n * @param overrides - Optional nested {@link MasteringChainConfig} applied on top of the preset (e.g. `{ loudness: { targetLufs: -14 } }`). Pass `null` for preset defaults.\n * @param onProgress - Optional per-stage progress callback (progress: 0-1, stage: string).\n * @returns Processed stereo audio, loudness metadata, and applied stage names\n */\nexport function masterAudioStereo(request: MasterAudioStereoRequest): MasteringChainStereoResult;\nexport function masterAudioStereo(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n presetName?: MasteringPreset,\n overrides?: MasteringChainConfig,\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult;\nexport function masterAudioStereo(\n left: MasterAudioStereoRequest | Float32Array,\n right: Float32Array | undefined = undefined,\n sampleRate = 22050,\n presetName: MasteringPreset = 'pop',\n overrides: MasteringChainConfig = {},\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult {\n const request = masterAudioStereoRequest(\n left,\n right,\n sampleRate,\n presetName,\n overrides,\n onProgress,\n );\n const flat = flattenChainConfig(request.overrides ?? {});\n if (request.left.length !== request.right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n if (request.onProgress || request.cancel) {\n return requireModule().masterAudioStereoWithProgress(\n request.preset ?? 'pop',\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n flat,\n request.onProgress ?? (() => {}),\n request.cancel ?? (() => false),\n );\n }\n return requireModule().masterAudioStereo(\n request.preset ?? 'pop',\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n flat,\n );\n}\n\n/**\n * Mono `masterAudio` with per-stage progress reporting. `onProgress` is invoked\n * with `(progress, stage)` between each chain stage (progress is in [0,1]).\n */\nexport function masterAudioWithProgress(\n request: MasterAudioRequest & Required<Pick<MasterAudioRequest, 'onProgress'>>,\n): MasteringChainResult;\nexport function masterAudioWithProgress(\n samples: Float32Array,\n sampleRate?: number,\n presetName?: MasteringPreset,\n overrides?: MasteringChainConfig | null,\n onProgress?: ProgressCallback,\n): MasteringChainResult;\nexport function masterAudioWithProgress(\n samples: MasterAudioRequest | Float32Array,\n sampleRate = 22050,\n presetName: MasteringPreset = 'pop',\n overrides: MasteringChainConfig | null = null,\n onProgress?: ProgressCallback,\n): MasteringChainResult {\n const request = masterAudioRequest(samples, sampleRate, presetName, overrides, onProgress);\n if (!request.onProgress) {\n throw new TypeError('masterAudioWithProgress: onProgress is required');\n }\n return requireModule().masterAudioWithProgress(\n request.preset ?? 'pop',\n request.samples,\n request.sampleRate ?? 22050,\n flattenChainConfig(request.overrides ?? {}),\n request.onProgress,\n request.cancel ?? (() => false),\n );\n}\n\n/**\n * Stereo `masterAudio` with per-stage progress reporting.\n */\nexport function masterAudioStereoWithProgress(\n request: MasterAudioStereoRequest & Required<Pick<MasterAudioStereoRequest, 'onProgress'>>,\n): MasteringChainStereoResult;\nexport function masterAudioStereoWithProgress(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n presetName?: MasteringPreset,\n overrides?: MasteringChainConfig | null,\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult;\nexport function masterAudioStereoWithProgress(\n left: MasterAudioStereoRequest | Float32Array,\n right: Float32Array | undefined = undefined,\n sampleRate = 22050,\n presetName: MasteringPreset = 'pop',\n overrides: MasteringChainConfig | null = null,\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult {\n const request = masterAudioStereoRequest(\n left,\n right,\n sampleRate,\n presetName,\n overrides,\n onProgress,\n );\n if (!request.onProgress) {\n throw new TypeError('masterAudioStereoWithProgress: onProgress is required');\n }\n if (request.left.length !== request.right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n return requireModule().masterAudioStereoWithProgress(\n request.preset ?? 'pop',\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n flattenChainConfig(request.overrides ?? {}),\n request.onProgress,\n request.cancel ?? (() => false),\n );\n}\n","import { getSonareModule } from './module_state';\nimport type {\n MasteringOptions,\n MasteringProcessorParams,\n MasteringResult,\n MasteringStereoResult,\n PairAnalysis,\n PairProcessor,\n SoloProcessor,\n StereoAnalysis,\n StreamingPlatform,\n} from './public_types';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n/** Canonical request form for loudness/true-peak mastering. */\nexport interface MasteringRequest extends MasteringOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\nexport interface MasteringProcessRequest {\n processorName: SoloProcessor;\n samples: Float32Array;\n sampleRate?: number;\n params?: MasteringProcessorParams;\n}\n\nexport interface MasteringProcessStereoRequest {\n processorName: SoloProcessor;\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n params?: MasteringProcessorParams;\n}\n\n/** Canonical request form for a two-input match processor. */\nexport interface MasteringPairProcessRequest {\n processorName: PairProcessor;\n source: Float32Array;\n reference: Float32Array;\n sampleRate?: number;\n params?: MasteringProcessorParams;\n}\n\n/** Canonical request form for a two-input match analysis. */\nexport interface MasteringPairAnalyzeRequest {\n analysisName: PairAnalysis;\n source: Float32Array;\n reference: Float32Array;\n sampleRate?: number;\n params?: MasteringProcessorParams;\n}\n\n/** Canonical request form for a stereo analysis. */\nexport interface MasteringStereoAnalyzeRequest {\n analysisName: StereoAnalysis;\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n params?: MasteringProcessorParams;\n}\n\n/** Canonical request form for assistant/profile calls. */\nexport interface MasteringSamplesParamsRequest {\n samples: Float32Array;\n sampleRate?: number;\n params?: MasteringProcessorParams;\n}\n\n/** Canonical request form for streaming-platform preview. */\nexport interface MasteringStreamingPreviewRequest {\n samples: Float32Array;\n sampleRate?: number;\n platforms?: StreamingPlatform[];\n}\n\n/** Canonical request form for the stereo analysis entry points. */\nexport interface MasteringStereoParamsRequest {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n params?: MasteringProcessorParams;\n}\n\n/** Canonical request form for the stereo streaming-platform preview. */\nexport interface MasteringStreamingPreviewStereoRequest {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n platforms?: StreamingPlatform[];\n}\n\n/**\n * Apply mastering loudness normalization with a true-peak ceiling.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param options - Loudness/ceiling settings ({@link MasteringOptions})\n * @returns Processed audio and loudness metadata\n */\nexport function mastering(request: MasteringRequest): MasteringResult;\nexport function mastering(\n samples: Float32Array,\n sampleRate?: number,\n options?: MasteringOptions,\n): MasteringResult;\nexport function mastering(\n samples: MasteringRequest | Float32Array,\n sampleRate = 22050,\n options: MasteringOptions = {},\n): MasteringResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n return requireModule().mastering(\n request.samples,\n request.sampleRate ?? 22050,\n request.targetLufs ?? -14.0,\n request.ceilingDb ?? -1.0,\n request.truePeakOversample ?? 4,\n request.releaseMs ?? 0, // 0 => library default (50 ms)\n request.applyGainAtInputRate ?? false,\n );\n}\n\nexport function masteringProcessorNames(): SoloProcessor[] {\n // embind hands back a vector whose constructor is not this realm's Array, so the\n // result is not structured-cloneable (breaks postMessage to a Worker).\n // Array.from() re-roots it as a plain Array. Same for the sibling *Names() below.\n return Array.from(requireModule().masteringProcessorNames()) as SoloProcessor[];\n}\n\n/**\n * Names of the insert processors the mastering chain can instantiate by name\n * (`mastering::api::insert_factory_names`). Mirrors the C-ABI\n * `sonare_mastering_insert_names` (which joins this list) as a `string[]`.\n */\nexport function masteringInsertNames(): string[] {\n return (\n requireModule() as unknown as { masteringInsertNames: () => string[] }\n ).masteringInsertNames();\n}\n\n/**\n * Returns the camelCase parameter names a given insert / FX processor reads, for\n * tooling/validation. Any key NOT in this list is silently ignored by the\n * processor (and would be reported via {@link Mixer.sceneWarnings} when a scene\n * carrying it is loaded). Band/sub-band processors enumerate their indexed\n * `band{i}.<field>` keys. Returns an empty array for an unknown name (or one\n * whose insert needs an unavailable build feature, e.g. FX).\n *\n * @param name - Insert processor name (see {@link masteringInsertNames}).\n */\nexport function masteringInsertParamNames(name: string): string[] {\n return Array.from(\n (\n requireModule() as unknown as { masteringInsertParamNames: (name: string) => string[] }\n ).masteringInsertParamNames(name),\n );\n}\n\n/** One realtime-automatable parameter of an insert processor. */\nexport interface MasteringInsertParamInfo {\n /** JSON-key parameter name, as used in scene insert params. */\n name: string;\n /** Integer param id for realtime automation lanes / MIDI-CC binding. */\n id: number;\n /** Whether the param can be changed live from the audio thread. */\n rtSafe: boolean;\n /** Physical unit when the parameter is not unitless. */\n unit?: string;\n}\n\n/**\n * Returns the realtime-automatable parameter descriptors for an insert / FX\n * processor: each entry maps a JSON-key parameter name to the integer id used by\n * realtime automation and reports whether it is realtime-safe. Unlike\n * {@link masteringInsertParamNames} (every construction key), this lists only the\n * realtime-controllable subset — the keys accepted by\n * {@link RealtimeEngine.setTrackStripInsertParamByName}. Returns an empty array\n * for an unknown name or a processor with no automatable parameters.\n *\n * @param name - Insert processor name (see {@link masteringInsertNames}).\n */\nexport function masteringInsertParamInfo(name: string): MasteringInsertParamInfo[] {\n const json = (\n requireModule() as unknown as { masteringInsertParamInfo: (name: string) => string }\n ).masteringInsertParamInfo(name);\n return JSON.parse(json) as MasteringInsertParamInfo[];\n}\n\n/**\n * How a processor handles a buffer with more than two channels (a surround\n * bed). \"multichannel\" processes every plane in one call; \"stereoPairOnly\"\n * operates on the front L/R pair and passes any surround planes through dry.\n * \"perChannel\"/\"passthrough\" are reserved and unused by the current catalog.\n */\nexport type MasteringChannelPolicy =\n | 'multichannel'\n | 'stereoPairOnly'\n | 'perChannel'\n | 'passthrough';\n\n/** Coarse algorithmic work estimate for a realtime insert; not a benchmark. */\nexport type MasteringRealtimeCost = 'low' | 'moderate' | 'high';\n\n/** One processor's realtime/offline/pair classification in the catalog. */\nexport interface MasteringProcessorCatalogEntry {\n /** Processor id (the name used for scene inserts / named processors). */\n id: string;\n /**\n * Primary classification, by precedence pair > realtime > offline: \"pair\" for\n * two-input match.* processors, \"realtime\" for ids that build as a realtime\n * scene insert, \"offline\" for whole-file-only processors.\n */\n kind: 'realtime' | 'offline' | 'pair';\n /** True exactly for ids that always succeed as a realtime scene insert. */\n realtimeInsertable: boolean;\n /** True for processors with no mono implementation (stereo-only). */\n stereoOnly: boolean;\n /**\n * Reported latency for the default 48 kHz / 512-sample probe configuration.\n * Zero for offline processors; configuration-dependent values are estimates.\n */\n latencySamples: number;\n /**\n * Audible decay length for the same default prepared probe. Zero for\n * offline, dry-only, and no-tail processors.\n */\n tailSamples: number;\n /** Coarse realtime work estimate, or null when the processor is not an insert. */\n realtimeCost: MasteringRealtimeCost | null;\n /**\n * How the mixer wraps the processor on a >2-channel (surround) bus insert:\n * \"multichannel\" (one full-buffer call) or \"stereoPairOnly\" (front L/R pair,\n * surround planes passed through dry).\n */\n channelPolicy: MasteringChannelPolicy;\n}\n\n/**\n * Returns the machine-readable classification catalog for every named processor\n * id, merging the offline registry, the realtime insert factory, and the pair\n * registry. Lets a host filter a processor picker by realtime insertability\n * instead of offering ids the realtime strip would reject.\n */\nexport function masteringProcessorCatalog(): MasteringProcessorCatalogEntry[] {\n const json = (\n requireModule() as unknown as { masteringProcessorCatalog: () => string }\n ).masteringProcessorCatalog();\n return JSON.parse(json) as MasteringProcessorCatalogEntry[];\n}\n\nexport function masteringPairProcessorNames(): PairProcessor[] {\n return Array.from(requireModule().masteringPairProcessorNames()) as PairProcessor[];\n}\n\nexport function masteringPairAnalysisNames(): PairAnalysis[] {\n return Array.from(requireModule().masteringPairAnalysisNames()) as PairAnalysis[];\n}\n\nexport function masteringStereoAnalysisNames(): StereoAnalysis[] {\n return Array.from(requireModule().masteringStereoAnalysisNames()) as StereoAnalysis[];\n}\n\nexport function masteringProcess(request: MasteringProcessRequest): MasteringResult;\nexport function masteringProcess(\n processorName: SoloProcessor,\n samples: Float32Array,\n sampleRate?: number,\n params?: MasteringProcessorParams,\n): MasteringResult;\nexport function masteringProcess(\n processorName: SoloProcessor | MasteringProcessRequest,\n samples?: Float32Array,\n sampleRate = 22050,\n params: MasteringProcessorParams = {},\n): MasteringResult {\n const request =\n typeof processorName === 'string'\n ? { processorName, samples: samples as Float32Array, sampleRate, params }\n : processorName;\n return requireModule().masteringProcess(\n request.processorName,\n request.samples,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\nexport function masteringProcessStereo(\n request: MasteringProcessStereoRequest,\n): MasteringStereoResult;\nexport function masteringProcessStereo(\n processorName: SoloProcessor,\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n params?: MasteringProcessorParams,\n): MasteringStereoResult;\nexport function masteringProcessStereo(\n processorName: SoloProcessor | MasteringProcessStereoRequest,\n left?: Float32Array,\n right?: Float32Array,\n sampleRate = 22050,\n params: MasteringProcessorParams = {},\n): MasteringStereoResult {\n const request =\n typeof processorName === 'string'\n ? {\n processorName,\n left: left as Float32Array,\n right: right as Float32Array,\n sampleRate,\n params,\n }\n : processorName;\n if (request.left.length !== request.right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n return requireModule().masteringProcessStereo(\n request.processorName,\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\n/**\n * Apply a two-input `match.*` processor. `source` and `reference` may have\n * independent lengths — the match primitives consume each buffer at its own\n * length.\n */\nexport function masteringPairProcess(request: MasteringPairProcessRequest): MasteringResult;\nexport function masteringPairProcess(\n processorName: PairProcessor,\n source: Float32Array,\n reference: Float32Array,\n sampleRate?: number,\n params?: MasteringProcessorParams,\n): MasteringResult;\nexport function masteringPairProcess(\n processorName: PairProcessor | MasteringPairProcessRequest,\n source?: Float32Array,\n reference?: Float32Array,\n sampleRate = 22050,\n params: MasteringProcessorParams = {},\n): MasteringResult {\n const request =\n typeof processorName === 'string'\n ? {\n processorName,\n source: source as Float32Array,\n reference: reference as Float32Array,\n sampleRate,\n params,\n }\n : processorName;\n return requireModule().masteringPairProcess(\n request.processorName,\n request.source,\n request.reference,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\n/**\n * Analyze a `source` against a `reference` with a two-input analysis. The two\n * buffers may have independent lengths.\n */\nexport function masteringPairAnalyze(request: MasteringPairAnalyzeRequest): string;\nexport function masteringPairAnalyze(\n analysisName: PairAnalysis,\n source: Float32Array,\n reference: Float32Array,\n sampleRate?: number,\n params?: MasteringProcessorParams,\n): string;\nexport function masteringPairAnalyze(\n analysisName: PairAnalysis | MasteringPairAnalyzeRequest,\n source?: Float32Array,\n reference?: Float32Array,\n sampleRate = 22050,\n params: MasteringProcessorParams = {},\n): string {\n const request =\n typeof analysisName === 'string'\n ? {\n analysisName,\n source: source as Float32Array,\n reference: reference as Float32Array,\n sampleRate,\n params,\n }\n : analysisName;\n return requireModule().masteringPairAnalyze(\n request.analysisName,\n request.source,\n request.reference,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\nexport function masteringStereoAnalyze(request: MasteringStereoAnalyzeRequest): string;\nexport function masteringStereoAnalyze(\n analysisName: StereoAnalysis,\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n params?: MasteringProcessorParams,\n): string;\nexport function masteringStereoAnalyze(\n analysisName: StereoAnalysis | MasteringStereoAnalyzeRequest,\n left?: Float32Array,\n right?: Float32Array,\n sampleRate = 22050,\n params: MasteringProcessorParams = {},\n): string {\n const request =\n typeof analysisName === 'string'\n ? {\n analysisName,\n left: left as Float32Array,\n right: right as Float32Array,\n sampleRate,\n params,\n }\n : analysisName;\n return requireModule().masteringStereoAnalyze(\n request.analysisName,\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\nexport function masteringAssistantSuggest(request: MasteringSamplesParamsRequest): string;\nexport function masteringAssistantSuggest(\n samples: Float32Array,\n sampleRate?: number,\n params?: MasteringProcessorParams,\n): string;\nexport function masteringAssistantSuggest(\n samples: Float32Array | MasteringSamplesParamsRequest,\n sampleRate = 22050,\n params: MasteringProcessorParams = {},\n): string {\n const request = samples instanceof Float32Array ? { samples, sampleRate, params } : samples;\n return requireModule().masteringAssistantSuggest(\n request.samples,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\nexport function masteringAudioProfile(request: MasteringSamplesParamsRequest): string;\nexport function masteringAudioProfile(\n samples: Float32Array,\n sampleRate?: number,\n params?: MasteringProcessorParams,\n): string;\nexport function masteringAudioProfile(\n samples: Float32Array | MasteringSamplesParamsRequest,\n sampleRate = 22050,\n params: MasteringProcessorParams = {},\n): string {\n const request = samples instanceof Float32Array ? { samples, sampleRate, params } : samples;\n return requireModule().masteringAudioProfile(\n request.samples,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\nexport function masteringStreamingPreview(request: MasteringStreamingPreviewRequest): string;\nexport function masteringStreamingPreview(\n samples: Float32Array,\n sampleRate?: number,\n platforms?: StreamingPlatform[],\n): string;\nexport function masteringStreamingPreview(\n samples: Float32Array | MasteringStreamingPreviewRequest,\n sampleRate = 22050,\n platforms: StreamingPlatform[] = [],\n): string {\n const request = samples instanceof Float32Array ? { samples, sampleRate, platforms } : samples;\n return requireModule().masteringStreamingPreview(\n request.samples,\n request.sampleRate ?? 22050,\n request.platforms ?? [],\n );\n}\n\n/**\n * Suggest a mastering chain for a stereo pair, as shared JSON.\n *\n * Profiles through {@link masteringAudioProfileStereo}, so the loudness stage\n * of the suggestion is built on the channel-summed program rather than a\n * downmix that reads roughly 6 dB low.\n */\nexport function masteringAssistantSuggestStereo(request: MasteringStereoParamsRequest): string {\n return requireModule().masteringAssistantSuggestStereo(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\n/**\n * Mastering assistant profile of a stereo pair, as shared JSON.\n *\n * Only the `loudness` block is measured from the two channels: integrated LUFS\n * and LRA come from the channel-summed program and the true peak is the larger\n * of the two. The spectral, dynamics and tempo fields describe shape and timing\n * rather than absolute level and are measured on the downmix, which keeps them\n * comparable with {@link masteringAudioProfile}.\n */\nexport function masteringAudioProfileStereo(request: MasteringStereoParamsRequest): string {\n return requireModule().masteringAudioProfileStereo(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\n/**\n * Preview streaming-platform normalization for a stereo pair, as shared JSON.\n *\n * Measures the integrated loudness with BS.1770 channel summing and reports the\n * larger of the two channel true peaks. Passing a `0.5 * (left + right)` downmix\n * to {@link masteringStreamingPreview} instead reads roughly 6 dB low on\n * decorrelated material, and both the normalization gain and the ceiling-risk\n * flag follow from that measurement.\n */\nexport function masteringStreamingPreviewStereo(\n request: MasteringStreamingPreviewStereoRequest,\n): string {\n return requireModule().masteringStreamingPreviewStereo(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.platforms ?? [],\n );\n}\n","import { getSonareModule } from './module_state';\nimport type { ValidateOptions } from './validation';\nimport { assertSamples } from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n// ============================================================================\n// Mastering — offline dynamics processors (compressor / gate / transient_shaper)\n// ============================================================================\n\n/** Compressor sidechain detector mode. */\nexport type CompressorDetector = 'peak' | 'rms' | 'log_rms';\n\n/** Options for `masteringDynamicsCompressor`. */\nexport interface CompressorOptions extends ValidateOptions {\n thresholdDb?: number;\n ratio?: number;\n attackMs?: number;\n releaseMs?: number;\n kneeDb?: number;\n makeupGainDb?: number;\n autoMakeup?: boolean;\n detector?: CompressorDetector | number;\n sidechainHpfEnabled?: boolean;\n sidechainHpfHz?: number;\n pdrTimeMs?: number;\n pdrReleaseScale?: number;\n}\n\n/** Canonical request form for the offline compressor. */\nexport interface MasteringDynamicsCompressorRequest extends CompressorOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Options for `masteringDynamicsGate`. */\nexport interface GateOptions extends ValidateOptions {\n thresholdDb?: number;\n attackMs?: number;\n releaseMs?: number;\n rangeDb?: number;\n holdMs?: number;\n closeThresholdDb?: number;\n keyHpfHz?: number;\n}\n\n/** Canonical request form for the offline gate. */\nexport interface MasteringDynamicsGateRequest extends GateOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Options for `masteringDynamicsTransientShaper`. */\nexport interface TransientShaperOptions extends ValidateOptions {\n attackGainDb?: number;\n sustainGainDb?: number;\n fastAttackMs?: number;\n fastReleaseMs?: number;\n slowAttackMs?: number;\n slowReleaseMs?: number;\n sensitivity?: number;\n maxGainDb?: number;\n gainSmoothingMs?: number;\n lookaheadMs?: number;\n}\n\n/** Canonical request form for the offline transient shaper. */\nexport interface MasteringDynamicsTransientShaperRequest extends TransientShaperOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Result envelope returned by offline mastering dynamics processors. */\nexport interface DynamicsResult {\n samples: Float32Array;\n latencySamples: number;\n}\n\nconst COMPRESSOR_DETECTOR_MAP: Record<CompressorDetector, number> = {\n peak: 0,\n rms: 1,\n log_rms: 2,\n};\n\n/** Offline feed-forward compressor (soft knee, optional auto-makeup / sidechain HPF). */\nexport function masteringDynamicsCompressor(\n request: MasteringDynamicsCompressorRequest,\n): DynamicsResult;\nexport function masteringDynamicsCompressor(\n samples: Float32Array,\n sampleRate: number,\n options?: CompressorOptions,\n): DynamicsResult;\nexport function masteringDynamicsCompressor(\n samples: Float32Array | MasteringDynamicsCompressorRequest,\n sampleRate?: number,\n options: CompressorOptions = {},\n): DynamicsResult {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n assertSamples('masteringDynamicsCompressor', request.samples, request.validate !== false);\n const detector =\n typeof request.detector === 'string'\n ? COMPRESSOR_DETECTOR_MAP[request.detector]\n : request.detector;\n // Preserve inherited option values as well as own properties. The embind\n // boundary's hasProperty() intentionally follows the prototype chain, so a\n // spread copy here would otherwise erase values before C++ can read them.\n const opts: Record<string, unknown> = Object.assign(\n Object.create(Object.getPrototypeOf(request)) as Record<string, unknown>,\n request,\n );\n if (detector !== undefined) {\n opts.detector = detector;\n }\n return requireModule().masteringDynamicsCompressor(request.samples, request.sampleRate, opts);\n}\n\n/** Offline noise gate (hysteresis, hold, optional key HPF). */\nexport function masteringDynamicsGate(request: MasteringDynamicsGateRequest): DynamicsResult;\nexport function masteringDynamicsGate(\n samples: Float32Array,\n sampleRate: number,\n options?: GateOptions,\n): DynamicsResult;\nexport function masteringDynamicsGate(\n samples: Float32Array | MasteringDynamicsGateRequest,\n sampleRate?: number,\n options: GateOptions = {},\n): DynamicsResult {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n assertSamples('masteringDynamicsGate', request.samples, request.validate !== false);\n return requireModule().masteringDynamicsGate(request.samples, request.sampleRate, request);\n}\n\n/** Offline transient shaper (envelope-difference attack/sustain control). */\nexport function masteringDynamicsTransientShaper(\n request: MasteringDynamicsTransientShaperRequest,\n): DynamicsResult;\nexport function masteringDynamicsTransientShaper(\n samples: Float32Array,\n sampleRate: number,\n options?: TransientShaperOptions,\n): DynamicsResult;\nexport function masteringDynamicsTransientShaper(\n samples: Float32Array | MasteringDynamicsTransientShaperRequest,\n sampleRate?: number,\n options: TransientShaperOptions = {},\n): DynamicsResult {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n assertSamples('masteringDynamicsTransientShaper', request.samples, request.validate !== false);\n return requireModule().masteringDynamicsTransientShaper(\n request.samples,\n request.sampleRate,\n request,\n );\n}\n","import { getSonareModule } from './module_state';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n// ============================================================================\n// Mastering repair (declick, denoise_classical, declip, decrackle, dehum,\n// dereverb_classical, trim_silence) — hand-written bindings.\n// ============================================================================\n\n/** Options for `masteringRepairDeclick`. */\nexport interface DeclickOptions {\n threshold?: number;\n neighborRatio?: number;\n maxClickSamples?: number;\n lpcOrder?: number;\n residualRatio?: number;\n}\nexport interface MasteringRepairDeclickRequest extends DeclickOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Algorithms accepted by `masteringRepairDenoiseClassical`. */\nexport type DenoiseClassicalMode = 'logMmse' | 'mmseStsa' | 'spectralSubtraction';\n\n/** Noise PSD estimators accepted by `masteringRepairDenoiseClassical`. */\nexport type DenoiseClassicalNoiseEstimator = 'quantile' | 'mcra' | 'imcra';\n\n/** Options for `masteringRepairDenoiseClassical`. */\nexport interface DenoiseClassicalOptions {\n mode?: DenoiseClassicalMode;\n noiseEstimator?: DenoiseClassicalNoiseEstimator;\n nFft?: number;\n hopLength?: number;\n ddAlpha?: number;\n gainFloor?: number;\n overSubtraction?: number;\n spectralFloor?: number;\n noiseEstimationQuantile?: number;\n speechPresenceGain?: boolean;\n gainSmoothing?: boolean;\n}\nexport interface MasteringRepairDenoiseClassicalRequest extends DenoiseClassicalOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Offline LPC-based declicker. */\nexport function masteringRepairDeclick(request: MasteringRepairDeclickRequest): Float32Array;\nexport function masteringRepairDeclick(\n samples: Float32Array,\n sampleRate: number,\n options?: DeclickOptions,\n): Float32Array;\nexport function masteringRepairDeclick(\n samples: Float32Array | MasteringRepairDeclickRequest,\n sampleRate?: number,\n options: DeclickOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDeclick(request.samples, request.sampleRate, request);\n}\n\n/** Offline STFT-domain classical denoiser (LogMMSE / MMSE-STSA / SpectralSubtraction). */\nexport function masteringRepairDenoiseClassical(\n request: MasteringRepairDenoiseClassicalRequest,\n): Float32Array;\nexport function masteringRepairDenoiseClassical(\n samples: Float32Array,\n sampleRate: number,\n options?: DenoiseClassicalOptions,\n): Float32Array;\nexport function masteringRepairDenoiseClassical(\n samples: Float32Array | MasteringRepairDenoiseClassicalRequest,\n sampleRate?: number,\n options: DenoiseClassicalOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDenoiseClassical(\n request.samples,\n request.sampleRate,\n request,\n );\n}\n\n/** Options for `masteringRepairDeclip`. */\nexport interface DeclipOptions {\n clipThreshold?: number;\n lpcOrder?: number;\n iterations?: number;\n lpcBlend?: number;\n}\nexport interface MasteringRepairDeclipRequest extends DeclipOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Algorithms accepted by `masteringRepairDecrackle`. */\nexport type DecrackleMode = 'median' | 'waveletShrinkage';\n\n/** Options for `masteringRepairDecrackle`. */\nexport interface DecrackleOptions {\n threshold?: number;\n mode?: DecrackleMode;\n levels?: number;\n}\nexport interface MasteringRepairDecrackleRequest extends DecrackleOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Options for `masteringRepairDehum`. */\nexport interface DehumOptions {\n fundamentalHz?: number;\n harmonics?: number;\n q?: number;\n adaptive?: boolean;\n searchRangeHz?: number;\n adaptation?: number;\n frameSize?: number;\n pllBandwidth?: number;\n}\nexport interface MasteringRepairDehumRequest extends DehumOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Options for `masteringRepairDereverbClassical`. */\nexport interface DereverbClassicalOptions {\n threshold?: number;\n attenuation?: number;\n nFft?: number;\n hopLength?: number;\n t60Sec?: number;\n lateDelayMs?: number;\n overSubtraction?: number;\n spectralFloor?: number;\n wpeEnabled?: boolean;\n wpeIterations?: number;\n wpeTaps?: number;\n wpeStrength?: number;\n}\nexport interface MasteringRepairDereverbClassicalRequest extends DereverbClassicalOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Trimming modes accepted by `masteringRepairTrimSilence`. */\nexport type TrimSilenceMode = 'peak' | 'lufsGated';\n\n/** Options for `masteringRepairTrimSilence`. */\nexport interface TrimSilenceOptions {\n threshold?: number;\n paddingSamples?: number;\n mode?: TrimSilenceMode;\n gateLufs?: number;\n windowMs?: number;\n}\nexport interface MasteringRepairTrimSilenceRequest extends TrimSilenceOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Offline LPC-based declipper. */\nexport function masteringRepairDeclip(request: MasteringRepairDeclipRequest): Float32Array;\nexport function masteringRepairDeclip(\n samples: Float32Array,\n sampleRate: number,\n options?: DeclipOptions,\n): Float32Array;\nexport function masteringRepairDeclip(\n samples: Float32Array | MasteringRepairDeclipRequest,\n sampleRate?: number,\n options: DeclipOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDeclip(request.samples, request.sampleRate, request);\n}\n\n/** Offline crackle suppressor (median or wavelet-shrinkage). */\nexport function masteringRepairDecrackle(request: MasteringRepairDecrackleRequest): Float32Array;\nexport function masteringRepairDecrackle(\n samples: Float32Array,\n sampleRate: number,\n options?: DecrackleOptions,\n): Float32Array;\nexport function masteringRepairDecrackle(\n samples: Float32Array | MasteringRepairDecrackleRequest,\n sampleRate?: number,\n options: DecrackleOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDecrackle(request.samples, request.sampleRate, request);\n}\n\n/** Offline mains-hum remover. */\nexport function masteringRepairDehum(request: MasteringRepairDehumRequest): Float32Array;\nexport function masteringRepairDehum(\n samples: Float32Array,\n sampleRate: number,\n options?: DehumOptions,\n): Float32Array;\nexport function masteringRepairDehum(\n samples: Float32Array | MasteringRepairDehumRequest,\n sampleRate?: number,\n options: DehumOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDehum(request.samples, request.sampleRate, request);\n}\n\n/** Offline classical dereverberator (spectral subtraction + optional WPE). */\nexport function masteringRepairDereverbClassical(\n request: MasteringRepairDereverbClassicalRequest,\n): Float32Array;\nexport function masteringRepairDereverbClassical(\n samples: Float32Array,\n sampleRate: number,\n options?: DereverbClassicalOptions,\n): Float32Array;\nexport function masteringRepairDereverbClassical(\n samples: Float32Array | MasteringRepairDereverbClassicalRequest,\n sampleRate?: number,\n options: DereverbClassicalOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDereverbClassical(\n request.samples,\n request.sampleRate,\n request,\n );\n}\n\n/** Offline silence trimmer (peak threshold or LUFS-gated). */\nexport function masteringRepairTrimSilence(\n request: MasteringRepairTrimSilenceRequest,\n): Float32Array;\nexport function masteringRepairTrimSilence(\n samples: Float32Array,\n sampleRate: number,\n options?: TrimSilenceOptions,\n): Float32Array;\nexport function masteringRepairTrimSilence(\n samples: Float32Array | MasteringRepairTrimSilenceRequest,\n sampleRate?: number,\n options: TrimSilenceOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairTrimSilence(request.samples, request.sampleRate, request);\n}\n","import { getSonareModule } from './module_state';\nimport type { MixOptions, MixResult } from './public_types';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\nexport function mixingScenePresetNames(): string[] {\n return Array.from(requireModule().mixingScenePresetNames());\n}\n\n/**\n * Get a built-in mixing scene preset serialized as JSON. This is the canonical\n * name shared with the Node and Python bindings; the returned JSON loads\n * directly into a {@link Mixer} via {@link Mixer.fromSceneJson}.\n *\n * @param presetName - Preset name (see {@link mixingScenePresetNames})\n * @returns Scene JSON string\n */\nexport function mixingScenePresetJson(presetName: string): string {\n return requireModule().mixingScenePresetJson(presetName);\n}\n\n/** Inputs for the one-shot {@link mixStereo} facade. */\nexport interface MixStereoRequest extends MixOptions {\n leftChannels: Float32Array[];\n rightChannels: Float32Array[];\n sampleRate?: number;\n}\n\n/**\n * One-shot stereo mix of multiple strips through the routing graph + master bus.\n *\n * Each returned per-strip meter reflects only this single one-shot block. The\n * integrating-meter fields (`momentaryLufs`, `shortTermLufs`, `integratedLufs`\n * and the true-peak fields) require sustained streaming to populate; on a short\n * one-shot mix they read the -120 dB floor sentinel. Drive a streaming\n * {@link Mixer} block-by-block if you need meaningful loudness/true-peak\n * readings.\n *\n * @param leftChannels - Per-strip left input buffers (all the same length)\n * @param rightChannels - Per-strip right input buffers (all the same length)\n * @param sampleRate - Sample rate in Hz\n * @param options - Per-strip mix options (trim, fader, pan, width, mute)\n */\nexport function mixStereo(request: MixStereoRequest): MixResult;\nexport function mixStereo(\n leftChannels: Float32Array[],\n rightChannels: Float32Array[],\n sampleRate?: number,\n options?: MixOptions,\n): MixResult;\nexport function mixStereo(\n leftChannels: Float32Array[] | MixStereoRequest,\n rightChannels?: Float32Array[],\n sampleRate = 48000,\n options: MixOptions = {},\n): MixResult {\n const request = Array.isArray(leftChannels)\n ? { leftChannels, rightChannels: rightChannels ?? [], sampleRate, ...options }\n : leftChannels;\n if (\n request.leftChannels.length === 0 ||\n request.leftChannels.length !== request.rightChannels.length\n ) {\n throw new Error('leftChannels and rightChannels must have the same non-zero length.');\n }\n return requireModule().mixStereo(\n request.leftChannels,\n request.rightChannels,\n request.sampleRate ?? 48000,\n request as unknown as Record<string, unknown>,\n );\n}\n","import { getSonareModule } from './module_state';\nimport type { TempogramMode } from './public_types';\nimport type {\n WasmCyclicTempogramResult,\n WasmFrameResult,\n WasmTempogramResult,\n WasmTrimResult,\n} from './sonare.js';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\nexport function tone(request?: ToneRequest): Float32Array;\nexport function tone(\n frequency?: number,\n sampleRate?: number,\n duration?: number,\n phase?: number,\n amplitude?: number,\n): Float32Array;\nexport function tone(\n frequency: number | ToneRequest = 440,\n sampleRate = 22050,\n duration = 1,\n phase = 0,\n amplitude = 1,\n): Float32Array {\n const request =\n typeof frequency === 'number'\n ? { frequency, sampleRate, duration, phase, amplitude }\n : frequency;\n return requireModule().tone(\n request.frequency ?? 440,\n request.sampleRate ?? 22050,\n request.duration ?? 1,\n request.phase ?? 0,\n request.amplitude ?? 1,\n );\n}\n\nexport function chirp(request?: ChirpRequest): Float32Array;\nexport function chirp(\n fmin?: number,\n fmax?: number,\n sampleRate?: number,\n duration?: number,\n linear?: boolean,\n): Float32Array;\nexport function chirp(\n fmin: number | ChirpRequest = 440,\n fmax = 880,\n sampleRate = 22050,\n duration = 1,\n linear = true,\n): Float32Array {\n const request = typeof fmin === 'number' ? { fmin, fmax, sampleRate, duration, linear } : fmin;\n return requireModule().chirp(\n request.fmin ?? 440,\n request.fmax ?? 880,\n request.sampleRate ?? 22050,\n request.duration ?? 1,\n request.linear ?? true,\n );\n}\n\nexport function clicks(request: ClicksRequest): Float32Array;\nexport function clicks(\n times: Float32Array,\n sampleRate?: number,\n length?: number,\n frequency?: number,\n clickDuration?: number,\n): Float32Array;\nexport function clicks(\n times: Float32Array | ClicksRequest,\n sampleRate = 22050,\n length = 0,\n frequency = 1000,\n clickDuration = 0.1,\n): Float32Array {\n const request =\n times instanceof Float32Array ? { times, sampleRate, length, frequency, clickDuration } : times;\n return requireModule().clicks(\n request.times,\n request.sampleRate ?? 22050,\n request.length ?? 0,\n request.frequency ?? 1000,\n request.clickDuration ?? 0.1,\n );\n}\n\nexport interface DbConversionRequest {\n values: Float32Array;\n ref?: number;\n amin?: number;\n topDb?: number;\n}\n\nexport interface SilenceRequest {\n samples: Float32Array;\n topDb?: number;\n frameLength?: number;\n hopLength?: number;\n}\n\nexport interface FrameSignalRequest {\n samples: Float32Array;\n frameLength: number;\n hopLength: number;\n}\nexport interface ToneRequest {\n frequency?: number;\n sampleRate?: number;\n duration?: number;\n phase?: number;\n amplitude?: number;\n}\nexport interface ChirpRequest {\n fmin?: number;\n fmax?: number;\n sampleRate?: number;\n duration?: number;\n linear?: boolean;\n}\nexport interface ClicksRequest {\n times: Float32Array;\n sampleRate?: number;\n length?: number;\n frequency?: number;\n clickDuration?: number;\n}\n/** Canonical request form for pre/de-emphasis filters. */\nexport interface EmphasisRequest {\n samples: Float32Array;\n coef?: number;\n zi?: number;\n}\n/** Canonical request form for centering or extending a vector. */\nexport interface PadCenterRequest {\n values: Float32Array;\n targetSize: number;\n padValue?: number;\n}\n/** Canonical request form for resizing a vector. */\nexport interface FixLengthRequest {\n values: Float32Array;\n targetSize: number;\n padValue?: number;\n}\n/** Canonical request form for bounding a frame-index vector. */\nexport interface FixFramesRequest {\n frames: Int32Array;\n xMin?: number;\n xMax?: number;\n pad?: boolean;\n}\nexport interface OnsetBacktrackRequest {\n events: Int32Array;\n energy: Float32Array;\n}\n/** Canonical request form for peak selection. */\nexport interface PeakPickRequest {\n values: Float32Array;\n preMax: number;\n postMax: number;\n preAvg: number;\n postAvg: number;\n delta: number;\n wait: number;\n}\n/** Canonical request form for vector normalization. */\nexport interface VectorNormalizeRequest {\n values: Float32Array;\n normType?: number;\n threshold?: number;\n}\n/** Canonical request form for tonal centroid projection. */\nexport interface TonnetzRequest {\n chromagram: Float32Array;\n nChroma: number;\n nFrames: number;\n}\nexport interface PcenRequest {\n values: Float32Array;\n nBins: number;\n nFrames: number;\n sampleRate?: number;\n hopLength?: number;\n timeConstant?: number;\n gain?: number;\n bias?: number;\n power?: number;\n eps?: number;\n /** @deprecated Put PCEN fields directly on the request object. */\n options?: Record<string, number>;\n}\nexport interface TempogramRequest {\n onsetEnvelope: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n winLength?: number;\n mode?: TempogramMode;\n center?: boolean;\n norm?: boolean;\n}\nexport interface CyclicTempogramRequest {\n onsetEnvelope: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n winLength?: number;\n bpmMin?: number;\n nBins?: number;\n}\nexport interface PlpRequest {\n onsetEnvelope: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n tempoMin?: number;\n tempoMax?: number;\n winLength?: number;\n}\n\n// ============================================================================\n// Core - Unit Conversion\n// ============================================================================\n\n/**\n * Convert frequency in Hz to Mel scale.\n *\n * @param hz - Frequency in Hz\n * @returns Mel frequency\n */\nexport function hzToMel(hz: number): number {\n return requireModule().hzToMel(hz);\n}\n\n/**\n * Convert Mel scale to frequency in Hz.\n *\n * @param mel - Mel frequency\n * @returns Frequency in Hz\n */\nexport function melToHz(mel: number): number {\n return requireModule().melToHz(mel);\n}\n\n/**\n * Convert frequency in Hz to MIDI note number.\n *\n * @param hz - Frequency in Hz\n * @returns MIDI note number (A4 = 440 Hz = 69)\n */\nexport function hzToMidi(hz: number): number {\n return requireModule().hzToMidi(hz);\n}\n\n/**\n * Convert MIDI note number to frequency in Hz.\n *\n * @param midi - MIDI note number\n * @returns Frequency in Hz\n */\nexport function midiToHz(midi: number): number {\n return requireModule().midiToHz(midi);\n}\n\n/**\n * Convert frequency in Hz to note name.\n *\n * @param hz - Frequency in Hz\n * @returns Note name (e.g., \"A4\", \"C#5\")\n */\nexport function hzToNote(hz: number): string {\n return requireModule().hzToNote(hz);\n}\n\n/**\n * Convert note name to frequency in Hz.\n *\n * @param note - Note name (e.g., \"A4\", \"C#5\")\n * @returns Frequency in Hz\n */\nexport function noteToHz(note: string): number {\n return requireModule().noteToHz(note);\n}\n\n/**\n * Convert frame index to time in seconds.\n *\n * @param frames - Frame index\n * @param sr - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length in samples (default: 512)\n * @returns Time in seconds\n */\nexport function framesToTime(frames: number, sr = 22050, hopLength = 512): number {\n return requireModule().framesToTime(frames, sr, hopLength);\n}\n\n/**\n * Convert time in seconds to frame index.\n *\n * @param time - Time in seconds\n * @param sr - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length in samples (default: 512)\n * @returns Frame index\n */\nexport function timeToFrames(time: number, sr = 22050, hopLength = 512): number {\n return requireModule().timeToFrames(time, sr, hopLength);\n}\n\nexport function framesToSamples(frames: number, hopLength = 512, nFft = 0): number {\n return requireModule().framesToSamples(frames, hopLength, nFft);\n}\n\nexport function samplesToFrames(samples: number, hopLength = 512, nFft = 0): number {\n return requireModule().samplesToFrames(samples, hopLength, nFft);\n}\n\nexport function powerToDb(request: DbConversionRequest): Float32Array;\nexport function powerToDb(\n values: Float32Array,\n ref?: number,\n amin?: number,\n topDb?: number,\n): Float32Array;\nexport function powerToDb(\n values: Float32Array | DbConversionRequest,\n ref = 1.0,\n amin = 1e-10,\n topDb = 80.0,\n): Float32Array {\n if (!(values instanceof Float32Array)) {\n return powerToDb(values.values, values.ref, values.amin, values.topDb);\n }\n return requireModule().powerToDb(values, ref, amin, topDb);\n}\n\nexport function amplitudeToDb(request: DbConversionRequest): Float32Array;\nexport function amplitudeToDb(\n values: Float32Array,\n ref?: number,\n amin?: number,\n topDb?: number,\n): Float32Array;\nexport function amplitudeToDb(\n values: Float32Array | DbConversionRequest,\n ref = 1.0,\n amin = 1e-5,\n topDb = 80.0,\n): Float32Array {\n if (!(values instanceof Float32Array)) {\n return amplitudeToDb(values.values, values.ref, values.amin, values.topDb);\n }\n return requireModule().amplitudeToDb(values, ref, amin, topDb);\n}\n\nexport function dbToPower(values: Float32Array, ref = 1.0): Float32Array {\n return requireModule().dbToPower(values, ref);\n}\n\nexport function dbToAmplitude(values: Float32Array, ref = 1.0): Float32Array {\n return requireModule().dbToAmplitude(values, ref);\n}\n\nexport function preemphasis(request: EmphasisRequest): Float32Array;\nexport function preemphasis(samples: Float32Array, coef?: number, zi?: number): Float32Array;\nexport function preemphasis(\n samples: Float32Array | EmphasisRequest,\n coef = 0.97,\n zi?: number,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return preemphasis(samples.samples, samples.coef, samples.zi);\n }\n return requireModule().preemphasis(samples, coef, zi ?? null);\n}\n\nexport function deemphasis(request: EmphasisRequest): Float32Array;\nexport function deemphasis(samples: Float32Array, coef?: number, zi?: number): Float32Array;\nexport function deemphasis(\n samples: Float32Array | EmphasisRequest,\n coef = 0.97,\n zi?: number,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return deemphasis(samples.samples, samples.coef, samples.zi);\n }\n return requireModule().deemphasis(samples, coef, zi ?? null);\n}\n\nexport function trimSilence(request: SilenceRequest): WasmTrimResult;\nexport function trimSilence(\n samples: Float32Array,\n topDb?: number,\n frameLength?: number,\n hopLength?: number,\n): WasmTrimResult;\nexport function trimSilence(\n samples: Float32Array | SilenceRequest,\n topDb = 60.0,\n frameLength = 2048,\n hopLength = 512,\n): WasmTrimResult {\n if (!(samples instanceof Float32Array)) {\n return trimSilence(samples.samples, samples.topDb, samples.frameLength, samples.hopLength);\n }\n return requireModule().trimSilence(samples, topDb, frameLength, hopLength);\n}\n\nexport function splitSilence(request: SilenceRequest): Int32Array;\nexport function splitSilence(\n samples: Float32Array,\n topDb?: number,\n frameLength?: number,\n hopLength?: number,\n): Int32Array;\nexport function splitSilence(\n samples: Float32Array | SilenceRequest,\n topDb = 60.0,\n frameLength = 2048,\n hopLength = 512,\n): Int32Array {\n if (!(samples instanceof Float32Array)) {\n return splitSilence(samples.samples, samples.topDb, samples.frameLength, samples.hopLength);\n }\n return requireModule().splitSilence(samples, topDb, frameLength, hopLength);\n}\n\nexport function frameSignal(request: FrameSignalRequest): WasmFrameResult;\nexport function frameSignal(\n samples: Float32Array,\n frameLength: number,\n hopLength: number,\n): WasmFrameResult;\nexport function frameSignal(\n samples: Float32Array | FrameSignalRequest,\n frameLength?: number,\n hopLength?: number,\n): WasmFrameResult {\n if (!(samples instanceof Float32Array)) {\n return frameSignal(samples.samples, samples.frameLength, samples.hopLength);\n }\n return requireModule().frameSignal(samples, frameLength as number, hopLength as number);\n}\n\nexport function padCenter(request: PadCenterRequest): Float32Array;\nexport function padCenter(\n values: Float32Array,\n targetSize: number,\n padValue?: number,\n): Float32Array;\nexport function padCenter(\n values: Float32Array | PadCenterRequest,\n targetSize?: number,\n padValue = 0.0,\n): Float32Array {\n if (!(values instanceof Float32Array)) {\n return padCenter(values.values, values.targetSize, values.padValue);\n }\n return requireModule().padCenter(values, targetSize as number, padValue);\n}\n\nexport function fixLength(request: FixLengthRequest): Float32Array;\nexport function fixLength(\n values: Float32Array,\n targetSize: number,\n padValue?: number,\n): Float32Array;\nexport function fixLength(\n values: Float32Array | FixLengthRequest,\n targetSize?: number,\n padValue = 0.0,\n): Float32Array {\n if (!(values instanceof Float32Array)) {\n return fixLength(values.values, values.targetSize, values.padValue);\n }\n return requireModule().fixLength(values, targetSize as number, padValue);\n}\n\nexport function fixFrames(request: FixFramesRequest): Int32Array;\nexport function fixFrames(\n frames: Int32Array,\n xMin?: number,\n xMax?: number,\n pad?: boolean,\n): Int32Array;\nexport function fixFrames(\n frames: Int32Array | FixFramesRequest,\n xMin = 0,\n xMax = -1,\n pad = true,\n): Int32Array {\n if (!(frames instanceof Int32Array)) {\n return fixFrames(frames.frames, frames.xMin, frames.xMax, frames.pad);\n }\n return requireModule().fixFrames(frames, xMin, xMax, pad);\n}\n\nexport function onsetBacktrack(request: OnsetBacktrackRequest): Int32Array;\nexport function onsetBacktrack(events: Int32Array, energy: Float32Array): Int32Array;\nexport function onsetBacktrack(\n events: Int32Array | OnsetBacktrackRequest,\n energy?: Float32Array,\n): Int32Array {\n if (!(events instanceof Int32Array)) {\n return onsetBacktrack(events.events, events.energy);\n }\n return requireModule().onsetBacktrack(events, energy as Float32Array);\n}\n\nexport function peakPick(request: PeakPickRequest): Int32Array;\nexport function peakPick(\n values: Float32Array,\n preMax: number,\n postMax: number,\n preAvg: number,\n postAvg: number,\n delta: number,\n wait: number,\n): Int32Array;\nexport function peakPick(\n values: Float32Array | PeakPickRequest,\n preMax?: number,\n postMax?: number,\n preAvg?: number,\n postAvg?: number,\n delta?: number,\n wait?: number,\n): Int32Array {\n if (!(values instanceof Float32Array)) {\n const r = values;\n return peakPick(r.values, r.preMax, r.postMax, r.preAvg, r.postAvg, r.delta, r.wait);\n }\n return requireModule().peakPick(\n values,\n preMax as number,\n postMax as number,\n preAvg as number,\n postAvg as number,\n delta as number,\n wait as number,\n );\n}\n\nexport function vectorNormalize(request: VectorNormalizeRequest): Float32Array;\nexport function vectorNormalize(\n values: Float32Array,\n normType?: number,\n threshold?: number,\n): Float32Array;\nexport function vectorNormalize(\n values: Float32Array | VectorNormalizeRequest,\n normType = 0,\n threshold = 0.0,\n): Float32Array {\n if (!(values instanceof Float32Array)) {\n return vectorNormalize(values.values, values.normType, values.threshold);\n }\n return requireModule().vectorNormalize(values, normType, threshold);\n}\n\nexport function pcen(request: PcenRequest): Float32Array;\nexport function pcen(\n values: Float32Array,\n nBins: number,\n nFrames: number,\n options?: Record<string, number>,\n): Float32Array;\nexport function pcen(\n values: Float32Array | PcenRequest,\n nBins = 0,\n nFrames = 0,\n options: Record<string, number> = {},\n): Float32Array {\n if (!(values instanceof Float32Array)) {\n const r = values;\n const {\n values: requestValues,\n nBins: requestBins,\n nFrames: requestFrames,\n options: legacyOptions,\n ...flatOptions\n } = r;\n return pcen(requestValues, requestBins, requestFrames, {\n ...legacyOptions,\n ...flatOptions,\n });\n }\n return requireModule().pcen(values, nBins, nFrames, options);\n}\n\nexport function tonnetz(request: TonnetzRequest): Float32Array;\nexport function tonnetz(chromagram: Float32Array, nChroma: number, nFrames: number): Float32Array;\nexport function tonnetz(\n chromagram: Float32Array | TonnetzRequest,\n nChroma?: number,\n nFrames?: number,\n): Float32Array {\n if (!(chromagram instanceof Float32Array)) {\n return tonnetz(chromagram.chromagram, chromagram.nChroma, chromagram.nFrames);\n }\n return requireModule().tonnetz(chromagram, nChroma as number, nFrames as number);\n}\n\nexport function tempogram(request: TempogramRequest): WasmTempogramResult;\nexport function tempogram(\n onsetEnvelope: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n winLength?: number,\n mode?: TempogramMode,\n center?: boolean,\n norm?: boolean,\n): WasmTempogramResult;\nexport function tempogram(\n onsetEnvelope: Float32Array | TempogramRequest,\n sampleRate = 22050,\n hopLength = 512,\n winLength = 384,\n mode: TempogramMode = 'autocorrelation',\n center = true,\n norm = true,\n): WasmTempogramResult {\n if (!(onsetEnvelope instanceof Float32Array)) {\n const r = onsetEnvelope;\n return tempogram(\n r.onsetEnvelope,\n r.sampleRate,\n r.hopLength,\n r.winLength,\n r.mode,\n r.center,\n r.norm,\n );\n }\n return requireModule().tempogram(\n onsetEnvelope,\n sampleRate,\n hopLength,\n winLength,\n mode,\n center,\n norm,\n );\n}\n\nexport function cyclicTempogram(request: CyclicTempogramRequest): WasmCyclicTempogramResult;\nexport function cyclicTempogram(\n onsetEnvelope: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n winLength?: number,\n bpmMin?: number,\n nBins?: number,\n): WasmCyclicTempogramResult;\nexport function cyclicTempogram(\n onsetEnvelope: Float32Array | CyclicTempogramRequest,\n sampleRate = 22050,\n hopLength = 512,\n winLength = 384,\n bpmMin = 60.0,\n nBins = 60,\n): WasmCyclicTempogramResult {\n if (!(onsetEnvelope instanceof Float32Array)) {\n const r = onsetEnvelope;\n return cyclicTempogram(\n r.onsetEnvelope,\n r.sampleRate,\n r.hopLength,\n r.winLength,\n r.bpmMin,\n r.nBins,\n );\n }\n return requireModule().cyclicTempogram(\n onsetEnvelope,\n sampleRate,\n hopLength,\n winLength,\n bpmMin,\n nBins,\n );\n}\n\nexport function plp(request: PlpRequest): Float32Array;\nexport function plp(\n onsetEnvelope: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n tempoMin?: number,\n tempoMax?: number,\n winLength?: number,\n): Float32Array;\nexport function plp(\n onsetEnvelope: Float32Array | PlpRequest,\n sampleRate = 22050,\n hopLength = 512,\n tempoMin = 30.0,\n tempoMax = 300.0,\n winLength = 384,\n): Float32Array {\n if (!(onsetEnvelope instanceof Float32Array)) {\n const r = onsetEnvelope;\n return plp(r.onsetEnvelope, r.sampleRate, r.hopLength, r.tempoMin, r.tempoMax, r.winLength);\n }\n return requireModule().plp(onsetEnvelope, sampleRate, hopLength, tempoMin, tempoMax, winLength);\n}\n","import { ErrorCode, SonareError } from './errors';\nimport { getSonareModule } from './module_state';\nimport type {\n AnalyzeSectionsOptions,\n CqtResult,\n LufsResult,\n MelodyResult,\n OnsetStrengthMultiResult,\n Section,\n SectionType,\n} from './public_types';\nimport type { WasmFourierTempogramResult, WasmNnlsChromaResult } from './sonare.js';\nimport type { ValidateOptions } from './validation';\nimport {\n assertFiniteScalar,\n assertPositiveInteger,\n assertSampleRate,\n assertSamples,\n} from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\ntype GuardedOptions = ValidateOptions;\ntype AnalyzeSectionsGuardedOptions = AnalyzeSectionsOptions & ValidateOptions;\ntype MelodyGuardedOptions = MelodyOptions & ValidateOptions;\n\n/** Canonical request form shared by the Constant-Q transform variants. */\nexport interface CqtRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n fmin?: number;\n nBins?: number;\n binsPerOctave?: number;\n}\n\n/** Canonical request form for {@link vqt}. */\nexport interface VqtRequest extends CqtRequest {\n gamma?: number;\n}\n\nexport interface OnsetEnvelopeRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n nFft?: number;\n hopLength?: number;\n nMels?: number;\n}\n\nexport interface OnsetStrengthMultiRequest extends OnsetEnvelopeRequest {\n nBands?: number;\n}\n\nexport interface FourierTempogramRequest extends GuardedOptions {\n onsetEnvelope: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n winLength?: number;\n center?: boolean;\n norm?: boolean;\n}\n\nexport interface TempogramRatioRequest extends GuardedOptions {\n tempogramData: Float32Array;\n winLength?: number;\n sampleRate?: number;\n hopLength?: number;\n factors?: Float32Array | number[];\n}\n\nexport interface CqtToAudioRequest extends GuardedOptions {\n magnitude: Float32Array;\n nBins: number;\n nFrames: number;\n sampleRate?: number;\n hopLength?: number;\n fmin?: number;\n binsPerOctave?: number;\n nIter?: number;\n}\n\nexport interface VqtToAudioRequest extends CqtToAudioRequest {\n gamma?: number;\n}\n\nexport interface AnalyzeSectionsRequest extends AnalyzeSectionsGuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\nexport interface AnalyzeMelodyRequest extends MelodyGuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\nexport interface LufsRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\nexport interface NnlsChromaRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n enableStftBlend?: boolean;\n stftBlendWeight?: number;\n stftBlendNFft?: number;\n hopLength?: number;\n}\n\nfunction validateMusicSamples(\n fnName: string,\n samples: Float32Array,\n sampleRate: number,\n options: GuardedOptions = {},\n): void {\n assertSampleRate(fnName, sampleRate);\n assertSamples(fnName, samples, options.validate !== false);\n}\n\nfunction validatePositiveIntegers(fnName: string, values: Record<string, number>): void {\n for (const [name, value] of Object.entries(values)) {\n assertPositiveInteger(fnName, value, name);\n }\n}\n\nfunction validateFrequencyBounds(fnName: string, fmin: number, fmax?: number): void {\n assertFiniteScalar(fnName, fmin, 'fmin');\n if (fmin < 0) {\n throw new RangeError(`${fnName}: fmin must be non-negative`);\n }\n if (fmax !== undefined) {\n assertFiniteScalar(fnName, fmax, 'fmax');\n if (fmax <= fmin) {\n throw new RangeError(`${fnName}: fmax must be greater than fmin`);\n }\n }\n}\n\n/**\n * Compute NNLS (non-negative least squares) chromagram.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @returns NNLS chroma result\n */\nexport function nnlsChroma(request: NnlsChromaRequest): WasmNnlsChromaResult;\nexport function nnlsChroma(\n samples: Float32Array,\n sampleRate?: number,\n options?: Omit<NnlsChromaRequest, 'samples' | 'sampleRate'>,\n): WasmNnlsChromaResult;\nexport function nnlsChroma(\n samples: Float32Array | NnlsChromaRequest,\n sampleRate = 22050,\n options: Omit<NnlsChromaRequest, 'samples' | 'sampleRate'> = {},\n): WasmNnlsChromaResult {\n if (!(samples instanceof Float32Array)) {\n return nnlsChroma(samples.samples, samples.sampleRate, samples);\n }\n validateMusicSamples('nnlsChroma', samples, sampleRate, options);\n const hopLength = options.hopLength === undefined ? 512 : options.hopLength;\n assertPositiveInteger('nnlsChroma', hopLength, 'hopLength');\n if (hopLength > 2 ** 31 - 1) {\n throw new RangeError('nnlsChroma: hopLength must fit in a signed 32-bit integer');\n }\n return requireModule().nnlsChromaEx(\n samples,\n sampleRate,\n options.enableStftBlend ?? true,\n options.stftBlendWeight ?? 0.55,\n options.stftBlendNFft ?? 4096,\n hopLength,\n );\n}\n\n/**\n * Compute the Constant-Q Transform magnitude.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum frequency in Hz (default: 32.70319566257483, C1)\n * @param nBins - Number of frequency bins (default: 84)\n * @param binsPerOctave - Bins per octave (default: 12)\n * @returns CQT magnitude result\n */\nexport function cqt(request: CqtRequest): CqtResult;\nexport function cqt(\n samples: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n fmin?: number,\n nBins?: number,\n binsPerOctave?: number,\n options?: GuardedOptions,\n): CqtResult;\nexport function cqt(\n samples: Float32Array | CqtRequest,\n sampleRate = 22050,\n hopLength = 512,\n fmin = 32.70319566257483,\n nBins = 84,\n binsPerOctave = 12,\n options: GuardedOptions = {},\n): CqtResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return cqt(\n request.samples,\n request.sampleRate,\n request.hopLength,\n request.fmin,\n request.nBins,\n request.binsPerOctave,\n request,\n );\n }\n validateMusicSamples('cqt', samples, sampleRate, options);\n validatePositiveIntegers('cqt', { hopLength, nBins, binsPerOctave });\n validateFrequencyBounds('cqt', fmin);\n return requireModule().cqt(samples, sampleRate, hopLength, fmin, nBins, binsPerOctave);\n}\n\n/**\n * Compute the pseudo Constant-Q Transform magnitude.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum frequency in Hz (default: 32.70319566257483, C1)\n * @param nBins - Number of frequency bins (default: 84)\n * @param binsPerOctave - Bins per octave (default: 12)\n * @returns CQT magnitude result\n */\nexport function pseudoCqt(request: CqtRequest): CqtResult;\nexport function pseudoCqt(\n samples: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n fmin?: number,\n nBins?: number,\n binsPerOctave?: number,\n options?: GuardedOptions,\n): CqtResult;\nexport function pseudoCqt(\n samples: Float32Array | CqtRequest,\n sampleRate = 22050,\n hopLength = 512,\n fmin = 32.70319566257483,\n nBins = 84,\n binsPerOctave = 12,\n options: GuardedOptions = {},\n): CqtResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return pseudoCqt(\n request.samples,\n request.sampleRate,\n request.hopLength,\n request.fmin,\n request.nBins,\n request.binsPerOctave,\n request,\n );\n }\n validateMusicSamples('pseudoCqt', samples, sampleRate, options);\n validatePositiveIntegers('pseudoCqt', { hopLength, nBins, binsPerOctave });\n validateFrequencyBounds('pseudoCqt', fmin);\n return requireModule().pseudoCqt(samples, sampleRate, hopLength, fmin, nBins, binsPerOctave);\n}\n\n/**\n * Compute the hybrid Constant-Q Transform magnitude.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum frequency in Hz (default: 32.70319566257483, C1)\n * @param nBins - Number of frequency bins (default: 84)\n * @param binsPerOctave - Bins per octave (default: 12)\n * @returns CQT magnitude result\n */\nexport function hybridCqt(request: CqtRequest): CqtResult;\nexport function hybridCqt(\n samples: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n fmin?: number,\n nBins?: number,\n binsPerOctave?: number,\n options?: GuardedOptions,\n): CqtResult;\nexport function hybridCqt(\n samples: Float32Array | CqtRequest,\n sampleRate = 22050,\n hopLength = 512,\n fmin = 32.70319566257483,\n nBins = 84,\n binsPerOctave = 12,\n options: GuardedOptions = {},\n): CqtResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return hybridCqt(\n request.samples,\n request.sampleRate,\n request.hopLength,\n request.fmin,\n request.nBins,\n request.binsPerOctave,\n request,\n );\n }\n validateMusicSamples('hybridCqt', samples, sampleRate, options);\n validatePositiveIntegers('hybridCqt', { hopLength, nBins, binsPerOctave });\n validateFrequencyBounds('hybridCqt', fmin);\n return requireModule().hybridCqt(samples, sampleRate, hopLength, fmin, nBins, binsPerOctave);\n}\n\n/**\n * Compute the Variable-Q Transform magnitude (gamma controls Q).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum frequency in Hz (default: 32.70319566257483, C1)\n * @param nBins - Number of frequency bins (default: 84)\n * @param binsPerOctave - Bins per octave (default: 12)\n * @param gamma - Bandwidth offset; negative selects the automatic ERB-derived\n * value, while 0 is equivalent to CQT (default: -1)\n * @returns VQT magnitude result (same shape as CQT)\n */\nexport function vqt(request: VqtRequest): CqtResult;\nexport function vqt(\n samples: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n fmin?: number,\n nBins?: number,\n binsPerOctave?: number,\n gamma?: number,\n options?: GuardedOptions,\n): CqtResult;\nexport function vqt(\n samples: Float32Array | VqtRequest,\n sampleRate = 22050,\n hopLength = 512,\n fmin = 32.70319566257483,\n nBins = 84,\n binsPerOctave = 12,\n gamma = -1,\n options: GuardedOptions = {},\n): CqtResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return vqt(\n request.samples,\n request.sampleRate,\n request.hopLength,\n request.fmin,\n request.nBins,\n request.binsPerOctave,\n request.gamma,\n request,\n );\n }\n validateMusicSamples('vqt', samples, sampleRate, options);\n validatePositiveIntegers('vqt', { hopLength, nBins, binsPerOctave });\n validateFrequencyBounds('vqt', fmin);\n assertFiniteScalar('vqt', gamma, 'gamma');\n return requireModule().vqt(samples, sampleRate, hopLength, fmin, nBins, binsPerOctave, gamma);\n}\n\nfunction validateCqtInverse(\n fnName: string,\n magnitude: Float32Array,\n nBins: number,\n nFrames: number,\n sampleRate: number,\n hopLength: number,\n fmin: number,\n binsPerOctave: number,\n nIter: number,\n options: GuardedOptions,\n): void {\n assertSampleRate(fnName, sampleRate);\n validatePositiveIntegers(fnName, { nBins, nFrames, hopLength, binsPerOctave, nIter });\n if (nIter > 256) {\n throw new RangeError(`${fnName}: nIter must be at most 256`);\n }\n validateFrequencyBounds(fnName, fmin);\n if (fmin === 0) {\n throw new RangeError(`${fnName}: fmin must be positive`);\n }\n if (magnitude.length !== nBins * nFrames) {\n throw new RangeError(`${fnName}: magnitude length must equal nBins * nFrames`);\n }\n assertSamples(fnName, magnitude, options.validate !== false);\n}\n\n/** Reconstruct mono audio from row-major CQT magnitude via Griffin-Lim. */\nexport function cqtToAudio(request: CqtToAudioRequest): Float32Array;\nexport function cqtToAudio(\n magnitude: Float32Array,\n nBins: number,\n nFrames: number,\n sampleRate?: number,\n hopLength?: number,\n fmin?: number,\n binsPerOctave?: number,\n nIter?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function cqtToAudio(\n magnitude: Float32Array | CqtToAudioRequest,\n nBins = 0,\n nFrames = 0,\n sampleRate = 22050,\n hopLength = 512,\n fmin = 32.70319566257483,\n binsPerOctave = 12,\n nIter = 32,\n options: GuardedOptions = {},\n): Float32Array {\n if (!(magnitude instanceof Float32Array)) {\n const request = magnitude;\n return cqtToAudio(\n request.magnitude,\n request.nBins,\n request.nFrames,\n request.sampleRate,\n request.hopLength,\n request.fmin,\n request.binsPerOctave,\n request.nIter,\n request,\n );\n }\n validateCqtInverse(\n 'cqtToAudio',\n magnitude,\n nBins,\n nFrames,\n sampleRate,\n hopLength,\n fmin,\n binsPerOctave,\n nIter,\n options,\n );\n return requireModule().cqtToAudio(\n magnitude,\n nBins,\n nFrames,\n sampleRate,\n hopLength,\n fmin,\n binsPerOctave,\n nIter,\n );\n}\n\n/** Reconstruct mono audio from row-major VQT magnitude via Griffin-Lim. */\nexport function vqtToAudio(request: VqtToAudioRequest): Float32Array;\nexport function vqtToAudio(\n magnitude: Float32Array,\n nBins: number,\n nFrames: number,\n sampleRate?: number,\n hopLength?: number,\n fmin?: number,\n binsPerOctave?: number,\n gamma?: number,\n nIter?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function vqtToAudio(\n magnitude: Float32Array | VqtToAudioRequest,\n nBins = 0,\n nFrames = 0,\n sampleRate = 22050,\n hopLength = 512,\n fmin = 32.70319566257483,\n binsPerOctave = 12,\n gamma = -1,\n nIter = 32,\n options: GuardedOptions = {},\n): Float32Array {\n if (!(magnitude instanceof Float32Array)) {\n const request = magnitude;\n return vqtToAudio(\n request.magnitude,\n request.nBins,\n request.nFrames,\n request.sampleRate,\n request.hopLength,\n request.fmin,\n request.binsPerOctave,\n request.gamma,\n request.nIter,\n request,\n );\n }\n validateCqtInverse(\n 'vqtToAudio',\n magnitude,\n nBins,\n nFrames,\n sampleRate,\n hopLength,\n fmin,\n binsPerOctave,\n nIter,\n options,\n );\n assertFiniteScalar('vqtToAudio', gamma, 'gamma');\n return requireModule().vqtToAudio(\n magnitude,\n nBins,\n nFrames,\n sampleRate,\n hopLength,\n fmin,\n binsPerOctave,\n gamma,\n nIter,\n );\n}\n\n/**\n * Detect song-structure sections (intro/verse/chorus/...).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param minSectionSec - Minimum section duration in seconds (default: 4.0)\n * @returns Array of detected sections\n */\nexport function analyzeSections(request: AnalyzeSectionsRequest): Section[];\nexport function analyzeSections(\n samples: Float32Array,\n sampleRate?: number,\n options?: AnalyzeSectionsGuardedOptions,\n): Section[];\nexport function analyzeSections(\n samples: Float32Array | AnalyzeSectionsRequest,\n sampleRate = 22050,\n options: AnalyzeSectionsGuardedOptions = {},\n): Section[] {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return analyzeSections(r.samples, r.sampleRate, r);\n }\n validateMusicSamples('analyzeSections', samples, sampleRate, options);\n validatePositiveIntegers('analyzeSections', {\n nFft: options.nFft ?? 2048,\n hopLength: options.hopLength ?? 512,\n });\n assertFiniteScalar('analyzeSections', options.minSectionSec ?? 4.0, 'minSectionSec');\n if ((options.minSectionSec ?? 4.0) < 0) {\n throw new RangeError('analyzeSections: minSectionSec must be non-negative');\n }\n // The embind value marshalling returns an array whose constructor is not this\n // realm's Array; chaining .map() onto it propagates that constructor via\n // Symbol.species, leaving a result that structuredClone (and so postMessage to\n // a Worker) rejects with \"could not be cloned\". Array.from() re-roots it as a\n // plain Array before mapping.\n const sections = requireModule().analyzeSections(\n samples,\n sampleRate,\n options.nFft ?? 2048,\n options.hopLength ?? 512,\n options.minSectionSec ?? 4.0,\n );\n return Array.from(sections, (s) => ({ ...s, type: s.type as SectionType }));\n}\n\n/** Options for {@link analyzeMelody}. All fields are optional. */\nexport interface MelodyOptions {\n /** Lowest f0 (Hz) the tracker will consider. Default 65 (≈ C2). */\n fmin?: number;\n /** Highest f0 (Hz) the tracker will consider. Default 2093 (≈ C7). */\n fmax?: number;\n /** Analysis frame length in samples. Default 2048. */\n frameLength?: number;\n /** Hop length between frames in samples. Default 256. */\n hopLength?: number;\n /** Voicing confidence threshold in [0,1]; frames below are unvoiced. Default 0.1. */\n threshold?: number;\n /**\n * Use the pYIN tracker (Viterbi-smoothed) instead of plain per-frame YIN.\n * Produces a less octave-jumpy contour. Defaults to `false`.\n */\n usePyin?: boolean;\n /**\n * When {@link usePyin} is `true`, zero-pad by `frameLength / 2` so frame\n * `i` is centered at `i * hopLength` (matches `librosa.pyin(center=True)`).\n * Ignored by the plain-YIN path. Defaults to `true`.\n */\n center?: boolean;\n}\n\n/**\n * Extract the melody contour from monophonic audio via YIN (or pYIN).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param options - Tracker + tuning options ({@link MelodyOptions})\n * @returns Melody contour with per-frame pitch points and summary stats\n */\nexport function analyzeMelody(request: AnalyzeMelodyRequest): MelodyResult;\nexport function analyzeMelody(\n samples: Float32Array,\n sampleRate?: number,\n options?: MelodyGuardedOptions,\n): MelodyResult;\nexport function analyzeMelody(\n samples: Float32Array | AnalyzeMelodyRequest,\n sampleRate = 22050,\n options: MelodyGuardedOptions = {},\n): MelodyResult {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return analyzeMelody(r.samples, r.sampleRate, r);\n }\n validateMusicSamples('analyzeMelody', samples, sampleRate, options);\n const fmin = options.fmin ?? 65.0;\n const fmax = options.fmax ?? 2093.0;\n validateFrequencyBounds('analyzeMelody', fmin, fmax);\n // The melody tracker's fmin is a YIN pitch floor: 0 is meaningless, and the\n // flat C ABI (sonare_analyze_melody) rejects it with InvalidParameter.\n // validateFrequencyBounds only guards fmin >= 0, so enforce strict positivity\n // here and report the same branded error the Node/Python surfaces raise.\n if (fmin <= 0) {\n throw new SonareError(\n ErrorCode.InvalidParameter,\n 'InvalidParameter',\n 'analyzeMelody: fmin must be positive',\n );\n }\n validatePositiveIntegers('analyzeMelody', {\n frameLength: options.frameLength ?? 2048,\n hopLength: options.hopLength ?? 256,\n });\n const threshold = options.threshold ?? 0.1;\n assertFiniteScalar('analyzeMelody', threshold, 'threshold');\n if (threshold <= 0) {\n throw new SonareError(\n ErrorCode.InvalidParameter,\n 'InvalidParameter',\n 'analyzeMelody: threshold must be positive',\n );\n }\n return requireModule().analyzeMelody(\n samples,\n sampleRate,\n options.fmin ?? 65.0,\n options.fmax ?? 2093.0,\n options.frameLength ?? 2048,\n options.hopLength ?? 256,\n options.threshold ?? 0.1,\n options.usePyin ?? false,\n options.center ?? true,\n );\n}\n\n/**\n * Compute the onset strength envelope.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param nMels - Number of Mel bands (default: 128)\n * @returns Onset envelope for each frame\n */\nexport function onsetEnvelope(request: OnsetEnvelopeRequest): Float32Array;\nexport function onsetEnvelope(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n nMels?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function onsetEnvelope(\n samples: Float32Array | OnsetEnvelopeRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n nMels = 128,\n options: GuardedOptions = {},\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return onsetEnvelope(\n request.samples,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.nMels,\n request,\n );\n }\n validateMusicSamples('onsetEnvelope', samples, sampleRate, options);\n validatePositiveIntegers('onsetEnvelope', { nFft, hopLength, nMels });\n return requireModule().onsetEnvelope(samples, sampleRate, nFft, hopLength, nMels);\n}\n\n/**\n * Compute multi-band onset strength envelopes.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param nMels - Number of Mel bands (default: 128)\n * @param nBands - Number of onset bands (default: 3)\n * @returns Multi-band onset matrix\n */\nexport function onsetStrengthMulti(request: OnsetStrengthMultiRequest): OnsetStrengthMultiResult;\nexport function onsetStrengthMulti(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n nMels?: number,\n nBands?: number,\n options?: GuardedOptions,\n): OnsetStrengthMultiResult;\nexport function onsetStrengthMulti(\n samples: Float32Array | OnsetStrengthMultiRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n nMels = 128,\n nBands = 3,\n options: GuardedOptions = {},\n): OnsetStrengthMultiResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return onsetStrengthMulti(\n request.samples,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.nMels,\n request.nBands,\n request,\n );\n }\n validateMusicSamples('onsetStrengthMulti', samples, sampleRate, options);\n validatePositiveIntegers('onsetStrengthMulti', { nFft, hopLength, nMels, nBands });\n return requireModule().onsetStrengthMulti(samples, sampleRate, nFft, hopLength, nMels, nBands);\n}\n\n/**\n * Compute the Fourier tempogram from an onset envelope.\n *\n * @param onsetEnvelope - Onset strength envelope (float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param winLength - Window length in frames (default: 384)\n * @returns Fourier tempogram result\n */\nexport function fourierTempogram(request: FourierTempogramRequest): WasmFourierTempogramResult;\nexport function fourierTempogram(\n onsetEnvelope: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n winLength?: number,\n center?: boolean,\n norm?: boolean,\n options?: GuardedOptions,\n): WasmFourierTempogramResult;\nexport function fourierTempogram(\n onsetEnvelope: Float32Array | FourierTempogramRequest,\n sampleRate = 22050,\n hopLength = 512,\n winLength = 384,\n center = true,\n norm = true,\n options: GuardedOptions = {},\n): WasmFourierTempogramResult {\n if (!(onsetEnvelope instanceof Float32Array)) {\n const request = onsetEnvelope;\n return fourierTempogram(\n request.onsetEnvelope,\n request.sampleRate,\n request.hopLength,\n request.winLength,\n request.center,\n request.norm,\n request,\n );\n }\n assertSampleRate('fourierTempogram', sampleRate);\n assertSamples('fourierTempogram', onsetEnvelope, options.validate !== false, 'onsetEnvelope');\n validatePositiveIntegers('fourierTempogram', { hopLength, winLength });\n return requireModule().fourierTempogram(\n onsetEnvelope,\n sampleRate,\n hopLength,\n winLength,\n center,\n norm,\n );\n}\n\n/**\n * Compute tempogram ratio features.\n *\n * @param tempogramData - Tempogram data (float32)\n * @param winLength - Window length in frames (default: 384)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param factors - Lag ratios to evaluate. When omitted or empty, the library\n * default {0.5, 1, 2, 3, 4} is used.\n * @returns Tempogram ratio features (one value per factor)\n */\nexport function tempogramRatio(request: TempogramRatioRequest): Float32Array;\nexport function tempogramRatio(\n tempogramData: Float32Array,\n winLength?: number,\n sampleRate?: number,\n hopLength?: number,\n factors?: Float32Array | number[],\n options?: GuardedOptions,\n): Float32Array;\nexport function tempogramRatio(\n tempogramData: Float32Array | TempogramRatioRequest,\n winLength = 384,\n sampleRate = 22050,\n hopLength = 512,\n factors?: Float32Array | number[],\n options: GuardedOptions = {},\n): Float32Array {\n if (!(tempogramData instanceof Float32Array)) {\n const request = tempogramData;\n return tempogramRatio(\n request.tempogramData,\n request.winLength,\n request.sampleRate,\n request.hopLength,\n request.factors,\n request,\n );\n }\n assertSampleRate('tempogramRatio', sampleRate);\n assertSamples('tempogramRatio', tempogramData, options.validate !== false, 'tempogramData');\n validatePositiveIntegers('tempogramRatio', { winLength, hopLength });\n return requireModule().tempogramRatio(tempogramData, winLength, sampleRate, hopLength, factors);\n}\n\n/**\n * Measure loudness (EBU R128 / ITU-R BS.1770).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz. The default (22050) is non-standard for\n * audio; pass the buffer's actual rate, as K-weighting is sample-rate\n * dependent and a wrong rate yields wrong loudness.\n * @returns Loudness measurement result\n */\nexport function lufs(request: LufsRequest): LufsResult;\nexport function lufs(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): LufsResult;\nexport function lufs(\n samples: Float32Array | LufsRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): LufsResult {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return lufs(r.samples, r.sampleRate, r);\n }\n assertSampleRate('lufs', sampleRate);\n assertSamples('lufs', samples, options.validate !== false);\n return requireModule().lufs(samples, sampleRate);\n}\n\n/**\n * Compute the momentary loudness (LUFS) over time.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz. The default (22050) is non-standard and\n * K-weighting is sample-rate dependent; pass the buffer's actual rate.\n * @returns Momentary LUFS values over time\n */\nexport function momentaryLufs(request: LufsRequest): Float32Array;\nexport function momentaryLufs(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function momentaryLufs(\n samples: Float32Array | LufsRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return momentaryLufs(r.samples, r.sampleRate, r);\n }\n assertSampleRate('momentaryLufs', sampleRate);\n assertSamples('momentaryLufs', samples, options.validate !== false);\n return requireModule().momentaryLufs(samples, sampleRate);\n}\n\n/**\n * Compute the short-term loudness (LUFS) over time.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz. The default (22050) is non-standard and\n * K-weighting is sample-rate dependent; pass the buffer's actual rate.\n * @returns Short-term LUFS values over time\n */\nexport function shortTermLufs(request: LufsRequest): Float32Array;\nexport function shortTermLufs(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function shortTermLufs(\n samples: Float32Array | LufsRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return shortTermLufs(r.samples, r.sampleRate, r);\n }\n assertSampleRate('shortTermLufs', sampleRate);\n assertSamples('shortTermLufs', samples, options.validate !== false);\n return requireModule().shortTermLufs(samples, sampleRate);\n}\n","import { getSonareModule } from './module_state';\nimport type { NoteSegment, PiptrackResult, PitchResult } from './public_types';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n// ============================================================================\n// Features - Pitch\n// ============================================================================\n\n/**\n * Detect pitch using YIN algorithm.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param frameLength - Frame length (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum frequency in Hz (default: 65)\n * @param fmax - Maximum frequency in Hz (default: 2093)\n * @param threshold - YIN threshold (default: 0.1)\n * @param fillNa - Retained for compatibility; YIN always returns a finite per-frame estimate.\n * @returns Pitch detection result\n */\nexport interface PitchYinRequest {\n samples: Float32Array;\n sampleRate?: number;\n frameLength?: number;\n hopLength?: number;\n fmin?: number;\n fmax?: number;\n threshold?: number;\n fillNa?: boolean;\n}\n\nexport interface PiptrackRequest {\n samples: Float32Array;\n sampleRate?: number;\n nFft?: number;\n hopLength?: number;\n fmin?: number;\n fmax?: number;\n threshold?: number;\n}\n\n/** Per-bin spectral pitch candidates and peak magnitudes (librosa.piptrack). */\nexport function piptrack(request: PiptrackRequest): PiptrackResult;\nexport function piptrack(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n fmin?: number,\n fmax?: number,\n threshold?: number,\n): PiptrackResult;\nexport function piptrack(\n samples: Float32Array | PiptrackRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n fmin = 150,\n fmax = 4000,\n threshold = 0.1,\n): PiptrackResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return piptrack(\n request.samples,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.fmin,\n request.fmax,\n request.threshold,\n );\n }\n return requireModule().piptrack(samples, sampleRate, nFft, hopLength, fmin, fmax, threshold);\n}\n\nexport function pitchYin(request: PitchYinRequest): PitchResult;\nexport function pitchYin(\n samples: Float32Array,\n sampleRate?: number,\n frameLength?: number,\n hopLength?: number,\n fmin?: number,\n fmax?: number,\n threshold?: number,\n fillNa?: boolean,\n): PitchResult;\nexport function pitchYin(\n samples: Float32Array | PitchYinRequest,\n sampleRate = 22050,\n frameLength = 2048,\n hopLength = 512,\n fmin = 65.0,\n fmax = 2093.0,\n threshold = 0.1,\n fillNa = false,\n): PitchResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return pitchYin(\n request.samples,\n request.sampleRate,\n request.frameLength,\n request.hopLength,\n request.fmin,\n request.fmax,\n request.threshold,\n request.fillNa,\n );\n }\n return requireModule().pitchYin(\n samples,\n sampleRate,\n frameLength,\n hopLength,\n fmin,\n fmax,\n threshold,\n fillNa,\n );\n}\n\n/**\n * Detect pitch using pYIN algorithm (probabilistic YIN with HMM smoothing).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param frameLength - Frame length (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum frequency in Hz (default: 65)\n * @param fmax - Maximum frequency in Hz (default: 2093)\n * @param threshold - YIN threshold (default: 0.1)\n * @param fillNa - If true, return 0 for unvoiced f0 frames; otherwise keep NaN (default: false)\n * @returns Pitch detection result\n */\nexport interface PitchPyinRequest extends PitchYinRequest {}\n\nexport function pitchPyin(request: PitchPyinRequest): PitchResult;\nexport function pitchPyin(\n samples: Float32Array,\n sampleRate?: number,\n frameLength?: number,\n hopLength?: number,\n fmin?: number,\n fmax?: number,\n threshold?: number,\n fillNa?: boolean,\n): PitchResult;\nexport function pitchPyin(\n samples: Float32Array | PitchPyinRequest,\n sampleRate = 22050,\n frameLength = 2048,\n hopLength = 512,\n fmin = 65.0,\n fmax = 2093.0,\n threshold = 0.1,\n fillNa = false,\n): PitchResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return pitchPyin(\n request.samples,\n request.sampleRate,\n request.frameLength,\n request.hopLength,\n request.fmin,\n request.fmax,\n request.threshold,\n request.fillNa,\n );\n }\n return requireModule().pitchPyin(\n samples,\n sampleRate,\n frameLength,\n hopLength,\n fmin,\n fmax,\n threshold,\n fillNa,\n );\n}\n\n/** Parameters for segmenting an F0 track into stable monophonic notes. */\nexport interface NoteSegmentsRequest {\n f0Hz: Float32Array;\n voicedProb: Float32Array;\n frameRate: number;\n segmentationThresholdCents?: number;\n minNoteMs?: number;\n referenceHz?: number;\n}\n\n/**\n * Segment a caller-supplied monophonic F0 track into stable note regions.\n *\n * `f0Hz` and `voicedProb` must have the same non-zero length. Zero-Hz frames\n * and probabilities below 0.5 are treated as unvoiced.\n */\nexport function noteSegments(request: NoteSegmentsRequest): NoteSegment[] {\n return requireModule().noteSegments(request.f0Hz, request.voicedProb, request.frameRate, {\n segmentationThresholdCents: request.segmentationThresholdCents,\n minNoteMs: request.minNoteMs,\n referenceHz: request.referenceHz,\n });\n}\n","import { getSonareModule } from './module_state';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n// ============================================================================\n// Core - Resample\n// ============================================================================\n\n/**\n * Resample audio to a different sample rate.\n *\n * @param samples - Audio samples (mono, float32)\n * @param srcSr - Source sample rate in Hz\n * @param targetSr - Target sample rate in Hz\n * @returns Resampled audio\n */\nexport interface ResampleRequest {\n samples: Float32Array;\n srcSr: number;\n targetSr: number;\n}\n\nexport function resample(request: ResampleRequest): Float32Array;\nexport function resample(samples: Float32Array, srcSr: number, targetSr: number): Float32Array;\nexport function resample(\n samples: Float32Array | ResampleRequest,\n srcSr?: number,\n targetSr?: number,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return resample(samples.samples, samples.srcSr, samples.targetSr);\n }\n return requireModule().resample(samples, srcSr as number, targetSr as number);\n}\n","import { getSonareModule } from './module_state';\nimport type { SegmentMatrix } from './public_types';\nimport type {\n WasmDecomposeResult,\n WasmHpssWithResidualResult,\n WasmLufsResult,\n WasmMatrix2dResult,\n} from './sonare.js';\nimport type { ValidateOptions } from './validation';\nimport {\n assertInterleavedSamples,\n assertNonNegativeInteger,\n assertPositiveInteger,\n assertSampleRate,\n assertSamples,\n} from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\nfunction resolveEffectFftOptions(\n fnName: string,\n nFft: unknown,\n hopLength: unknown,\n): { nFft: number; hopLength: number } {\n const resolvedNFft = nFft === undefined ? 2048 : nFft;\n const resolvedHopLength = hopLength === undefined ? 512 : hopLength;\n if (typeof resolvedNFft !== 'number' || !Number.isInteger(resolvedNFft)) {\n throw new TypeError(`${fnName}: nFft must be an integer`);\n }\n if (resolvedNFft < 2 || resolvedNFft > 2 ** 30) {\n throw new RangeError(`${fnName}: nFft must be an even power of two >= 2`);\n }\n if ((resolvedNFft & (resolvedNFft - 1)) !== 0) {\n throw new RangeError(`${fnName}: nFft must be an even power of two >= 2`);\n }\n if (typeof resolvedHopLength !== 'number' || !Number.isInteger(resolvedHopLength)) {\n throw new TypeError(`${fnName}: hopLength must be an integer`);\n }\n if (resolvedHopLength <= 0 || resolvedHopLength > 2 ** 31 - 1) {\n throw new RangeError(`${fnName}: hopLength must be a positive integer`);\n }\n return { nFft: resolvedNFft, hopLength: resolvedHopLength };\n}\n\nfunction resolveHardMask(fnName: string, value: unknown): boolean {\n if (value === undefined) {\n return false;\n }\n if (typeof value !== 'boolean') {\n throw new TypeError(`${fnName}: hardMask must be a boolean`);\n }\n return value;\n}\n\n/** Canonical request form for frame-based spectral feature extraction. */\nexport interface SpectralFrameRequest {\n samples: Float32Array;\n sampleRate?: number;\n nFft?: number;\n hopLength?: number;\n}\n\nexport interface SpectralRolloffRequest extends SpectralFrameRequest {\n rollPercent?: number;\n}\n\nexport interface ZeroCrossingRateRequest {\n samples: Float32Array;\n sampleRate?: number;\n frameLength?: number;\n hopLength?: number;\n}\n\nexport interface DecomposeRequest {\n s: Float32Array;\n nFeatures: number;\n nFrames: number;\n nComponents: number;\n nIter?: number;\n beta?: number;\n}\n\nexport interface DecomposeWithInitRequest extends DecomposeRequest {\n init?: 'random' | 'nndsvd';\n}\n\nexport interface SpectralContrastRequest extends SpectralFrameRequest {\n nBands?: number;\n fmin?: number;\n quantile?: number;\n}\nexport interface PolyFeaturesRequest extends SpectralFrameRequest {\n order?: number;\n}\nexport interface ZeroCrossingsRequest {\n samples: Float32Array;\n threshold?: number;\n refMagnitude?: boolean;\n pad?: boolean;\n zeroPos?: boolean;\n}\nexport interface PitchTuningRequest {\n frequencies: Float32Array;\n resolution?: number;\n binsPerOctave?: number;\n}\nexport interface EstimateTuningRequest extends SpectralFrameRequest {\n resolution?: number;\n binsPerOctave?: number;\n}\nexport interface NnFilterRequest {\n s: Float32Array;\n nFeatures: number;\n nFrames: number;\n aggregate?: string;\n k?: number;\n width?: number;\n}\nexport interface SegmentCrossSimilarityRequest {\n x: Float32Array;\n xRows: number;\n xCols: number;\n y: Float32Array;\n yRows: number;\n yCols: number;\n k?: number;\n metric?: 'cosine' | 'euclidean';\n mode?: 'connectivity' | 'affinity';\n}\nexport interface SegmentRecurrenceMatrixRequest {\n data: Float32Array;\n rows: number;\n cols: number;\n k?: number;\n width?: number;\n sym?: boolean;\n metric?: 'cosine' | 'euclidean';\n mode?: 'connectivity' | 'affinity';\n}\nexport interface SegmentRecurrenceToLagRequest {\n recurrence: Float32Array;\n n: number;\n pad?: boolean;\n}\nexport interface SegmentLagToRecurrenceRequest {\n lag: Float32Array;\n rows: number;\n lags: number;\n}\nexport interface SegmentSubsegmentRequest {\n data: Float32Array;\n rows: number;\n cols: number;\n boundaries: Int32Array;\n nSegments?: number;\n}\nexport interface SegmentAgglomerativeRequest {\n data: Float32Array;\n rows: number;\n cols: number;\n k: number;\n linkage?: 'average' | 'single' | 'complete' | 'ward';\n}\nexport interface SegmentPathEnhanceRequest {\n recurrence: Float32Array;\n n: number;\n win: number;\n maxRatio?: number;\n minRatio?: number;\n nFilters?: number;\n}\n\nfunction validateSegmentMatrix(\n fnName: string,\n data: Float32Array,\n rows: number,\n cols: number,\n dataName: string,\n): void {\n assertPositiveInteger(fnName, rows, 'rows');\n assertPositiveInteger(fnName, cols, 'cols');\n assertSamples(fnName, data, true, dataName);\n const expected = rows * cols;\n if (!Number.isSafeInteger(expected) || data.length !== expected) {\n throw new RangeError(`${fnName}: ${dataName} length must equal rows * cols`);\n }\n}\nexport interface RemixRequest {\n samples: Float32Array;\n intervals: Int32Array | ArrayLike<number>;\n sampleRate?: number;\n alignZeros?: boolean;\n}\nexport interface PhaseVocoderRequest extends SpectralFrameRequest {\n rate: number;\n}\nexport interface HpssWithResidualRequest {\n samples: Float32Array;\n sampleRate?: number;\n kernelHarmonic?: number;\n kernelPercussive?: number;\n nFft?: number;\n hopLength?: number;\n hardMask?: boolean;\n}\nexport interface LufsInterleavedRequest extends ValidateOptions {\n samples: Float32Array;\n channels: number;\n sampleRate?: number;\n}\nexport interface Ebur128LoudnessRangeRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\n// ============================================================================\n// Features - Spectral\n// ============================================================================\n\n/**\n * Compute spectral centroid (center of mass of spectrum).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns Spectral centroid in Hz for each frame\n */\nexport function spectralCentroid(request: SpectralFrameRequest): Float32Array;\nexport function spectralCentroid(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n): Float32Array;\nexport function spectralCentroid(\n samples: Float32Array | SpectralFrameRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return spectralCentroid(samples.samples, samples.sampleRate, samples.nFft, samples.hopLength);\n }\n return requireModule().spectralCentroid(samples, sampleRate, nFft, hopLength);\n}\n\n/**\n * Compute spectral contrast (librosa.feature.spectral_contrast).\n *\n * @returns Matrix2d of shape (nBands + 1) x nFrames.\n */\nexport function spectralContrast(request: SpectralContrastRequest): WasmMatrix2dResult;\nexport function spectralContrast(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n nBands?: number,\n fmin?: number,\n quantile?: number,\n): WasmMatrix2dResult;\nexport function spectralContrast(\n samples: Float32Array | SpectralContrastRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n nBands = 6,\n fmin = 200.0,\n quantile = 0.02,\n): WasmMatrix2dResult {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return spectralContrast(\n r.samples,\n r.sampleRate,\n r.nFft,\n r.hopLength,\n r.nBands,\n r.fmin,\n r.quantile,\n );\n }\n return requireModule().spectralContrast(\n samples,\n sampleRate,\n nFft,\n hopLength,\n nBands,\n fmin,\n quantile,\n );\n}\n\n/**\n * Fit per-frame polynomial coefficients (librosa.feature.poly_features).\n *\n * @returns Matrix2d of shape (order + 1) x nFrames.\n */\nexport function polyFeatures(request: PolyFeaturesRequest): WasmMatrix2dResult;\nexport function polyFeatures(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n order?: number,\n): WasmMatrix2dResult;\nexport function polyFeatures(\n samples: Float32Array | PolyFeaturesRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n order = 1,\n): WasmMatrix2dResult {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return polyFeatures(r.samples, r.sampleRate, r.nFft, r.hopLength, r.order);\n }\n return requireModule().polyFeatures(samples, sampleRate, nFft, hopLength, order);\n}\n\n/**\n * Locate zero-crossing indices of a signal (librosa.zero_crossings).\n */\nexport function zeroCrossings(request: ZeroCrossingsRequest): Int32Array;\nexport function zeroCrossings(\n samples: Float32Array,\n threshold?: number,\n refMagnitude?: boolean,\n pad?: boolean,\n zeroPos?: boolean,\n): Int32Array;\nexport function zeroCrossings(\n samples: Float32Array | ZeroCrossingsRequest,\n threshold = 1e-10,\n refMagnitude = false,\n pad = true,\n zeroPos = true,\n): Int32Array {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return zeroCrossings(r.samples, r.threshold, r.refMagnitude, r.pad, r.zeroPos);\n }\n return requireModule().zeroCrossings(samples, threshold, refMagnitude, pad, zeroPos);\n}\n\n/**\n * Estimate the global tuning offset from a set of frequencies\n * (librosa.pitch_tuning). Returns a deviation in fractions of a bin.\n */\nexport function pitchTuning(request: PitchTuningRequest): number;\nexport function pitchTuning(\n frequencies: Float32Array,\n resolution?: number,\n binsPerOctave?: number,\n): number;\nexport function pitchTuning(\n frequencies: Float32Array | PitchTuningRequest,\n resolution = 0.01,\n binsPerOctave = 12,\n): number {\n if (!(frequencies instanceof Float32Array)) {\n const r = frequencies;\n return pitchTuning(r.frequencies, r.resolution, r.binsPerOctave);\n }\n return requireModule().pitchTuning(frequencies, resolution, binsPerOctave);\n}\n\n/**\n * Estimate the tuning offset of an audio signal (librosa.estimate_tuning).\n */\nexport function estimateTuning(request: EstimateTuningRequest): number;\nexport function estimateTuning(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n resolution?: number,\n binsPerOctave?: number,\n): number;\nexport function estimateTuning(\n samples: Float32Array | EstimateTuningRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n resolution = 0.01,\n binsPerOctave = 12,\n): number {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return estimateTuning(\n r.samples,\n r.sampleRate,\n r.nFft,\n r.hopLength,\n r.resolution,\n r.binsPerOctave,\n );\n }\n return requireModule().estimateTuning(\n samples,\n sampleRate,\n nFft,\n hopLength,\n resolution,\n binsPerOctave,\n );\n}\n\n/**\n * Non-negative matrix factorisation of a flattened [nFeatures x nFrames]\n * spectrogram (librosa.decompose.decompose). Returns the W and H factors.\n */\nexport function decompose(request: DecomposeRequest): WasmDecomposeResult;\nexport function decompose(\n s: Float32Array,\n nFeatures: number,\n nFrames: number,\n nComponents: number,\n nIter?: number,\n beta?: number,\n): WasmDecomposeResult;\nexport function decompose(\n s: Float32Array | DecomposeRequest,\n nFeatures = 0,\n nFrames = 0,\n nComponents = 0,\n nIter = 50,\n beta = 2.0,\n): WasmDecomposeResult {\n if (!(s instanceof Float32Array)) {\n const request = s;\n return decompose(\n request.s,\n request.nFeatures,\n request.nFrames,\n request.nComponents,\n request.nIter,\n request.beta,\n );\n }\n return requireModule().decompose(s, nFeatures, nFrames, nComponents, nIter, beta);\n}\n\n/**\n * Non-negative matrix factorisation with a selectable initialiser\n * (librosa.decompose.decompose, `init`). Identical to {@link decompose} but\n * exposes the initialisation strategy: `'random'` (default, deterministic seed)\n * or `'nndsvd'` (SVD-based warm start, which tends to converge in fewer\n * iterations). Returns the W and H factors.\n */\nexport function decomposeWithInit(request: DecomposeWithInitRequest): WasmDecomposeResult;\nexport function decomposeWithInit(\n s: Float32Array,\n nFeatures: number,\n nFrames: number,\n nComponents: number,\n nIter?: number,\n beta?: number,\n init?: 'random' | 'nndsvd',\n): WasmDecomposeResult;\nexport function decomposeWithInit(\n s: Float32Array | DecomposeWithInitRequest,\n nFeatures = 0,\n nFrames = 0,\n nComponents = 0,\n nIter = 50,\n beta = 2.0,\n init: 'random' | 'nndsvd' = 'random',\n): WasmDecomposeResult {\n if (!(s instanceof Float32Array)) {\n const request = s;\n return decomposeWithInit(\n request.s,\n request.nFeatures,\n request.nFrames,\n request.nComponents,\n request.nIter,\n request.beta,\n request.init,\n );\n }\n return requireModule().decomposeWithInit(s, nFeatures, nFrames, nComponents, nIter, beta, init);\n}\n\n/**\n * Nearest-neighbour filtering of a flattened [nFeatures x nFrames] spectrogram\n * (librosa.decompose.nn_filter).\n */\nexport function nnFilter(request: NnFilterRequest): WasmMatrix2dResult;\nexport function nnFilter(\n s: Float32Array,\n nFeatures: number,\n nFrames: number,\n aggregate?: string,\n k?: number,\n width?: number,\n): WasmMatrix2dResult;\nexport function nnFilter(\n s: Float32Array | NnFilterRequest,\n nFeatures = 0,\n nFrames = 0,\n aggregate = 'mean',\n k = 7,\n width = 1,\n): WasmMatrix2dResult {\n if (!(s instanceof Float32Array)) {\n const r = s;\n return nnFilter(r.s, r.nFeatures, r.nFrames, r.aggregate, r.k, r.width);\n }\n return requireModule().nnFilter(s, nFeatures, nFrames, aggregate, k, width);\n}\n\n/**\n * Reorder/concatenate a signal by interval slices (librosa.effects.remix).\n *\n * @param intervals - Flat (start, end) sample pairs (even length).\n */\nexport function remix(request: RemixRequest): Float32Array;\nexport function remix(\n samples: Float32Array,\n intervals: Int32Array | ArrayLike<number>,\n sampleRate?: number,\n alignZeros?: boolean,\n): Float32Array;\nexport function remix(\n samples: Float32Array | RemixRequest,\n intervals?: Int32Array | ArrayLike<number>,\n sampleRate = 22050,\n alignZeros = false,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return remix(r.samples, r.intervals, r.sampleRate, r.alignZeros);\n }\n // Sample indices must reach the native side as exact 32-bit integers. Passing\n // a Float32Array (or a number[] holding fractional/large values) would round\n // boundaries above 2^24 and misalign the slice. Coerce to an Int32Array,\n // truncating toward zero, so callers can hand us any numeric array safely.\n const intervalsI32 =\n intervals instanceof Int32Array\n ? intervals\n : Int32Array.from(intervals as ArrayLike<number>, (v) => Math.trunc(v));\n return requireModule().remix(samples, intervalsI32, sampleRate, alignZeros);\n}\n\n/**\n * Phase-vocoder time-scale modification (rate > 1 faster, < 1 slower).\n */\nexport function phaseVocoder(request: PhaseVocoderRequest): Float32Array;\nexport function phaseVocoder(\n samples: Float32Array,\n sampleRate: number,\n rate: number,\n nFft?: number,\n hopLength?: number,\n): Float32Array;\nexport function phaseVocoder(\n samples: Float32Array | PhaseVocoderRequest,\n sampleRate = 22050,\n rate = 1,\n nFft = 2048,\n hopLength = 512,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return phaseVocoder(r.samples, r.sampleRate ?? 22050, r.rate, r.nFft, r.hopLength);\n }\n return requireModule().phaseVocoder(samples, sampleRate, rate, nFft, hopLength);\n}\n\n/**\n * HPSS into harmonic / percussive / residual signals.\n */\nexport function hpssWithResidual(request: HpssWithResidualRequest): WasmHpssWithResidualResult;\nexport function hpssWithResidual(\n samples: Float32Array,\n sampleRate?: number,\n kernelHarmonic?: number,\n kernelPercussive?: number,\n nFft?: number,\n hopLength?: number,\n hardMask?: boolean,\n): WasmHpssWithResidualResult;\nexport function hpssWithResidual(\n samples: Float32Array | HpssWithResidualRequest,\n sampleRate = 22050,\n kernelHarmonic = 31,\n kernelPercussive = 31,\n nFft?: number,\n hopLength?: number,\n hardMask?: boolean,\n): WasmHpssWithResidualResult {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return hpssWithResidual(\n r.samples,\n r.sampleRate,\n r.kernelHarmonic,\n r.kernelPercussive,\n r.nFft,\n r.hopLength,\n r.hardMask,\n );\n }\n const fftOptions = resolveEffectFftOptions('hpssWithResidual', nFft, hopLength);\n const resolvedHardMask = resolveHardMask('hpssWithResidual', hardMask);\n return requireModule().hpssWithResidualEx(\n samples,\n sampleRate,\n kernelHarmonic,\n kernelPercussive,\n fftOptions.nFft,\n fftOptions.hopLength,\n resolvedHardMask,\n );\n}\n\n/**\n * Channel-weighted multichannel integrated loudness + LRA (ITU-R BS.1770 /\n * EBU R128) from an interleaved buffer of `frames * channels` samples. The\n * per-channel frame count is derived from the buffer length and `channels`.\n *\n * Pass the buffer's actual `sampleRate`: the default (22050) is non-standard for\n * audio, and K-weighting is sample-rate dependent, so a wrong rate yields wrong\n * loudness.\n */\nexport function lufsInterleaved(request: LufsInterleavedRequest): WasmLufsResult;\nexport function lufsInterleaved(\n samples: Float32Array,\n channels: number,\n sampleRate?: number,\n options?: ValidateOptions,\n): WasmLufsResult;\nexport function lufsInterleaved(\n samples: Float32Array | LufsInterleavedRequest,\n channels = 0,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): WasmLufsResult {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return lufsInterleaved(r.samples, r.channels, r.sampleRate, r);\n }\n assertSampleRate('lufsInterleaved', sampleRate);\n assertInterleavedSamples('lufsInterleaved', samples, channels, options.validate !== false);\n return requireModule().lufsInterleaved(samples, channels, sampleRate);\n}\n\n/**\n * Standards-compliant EBU R128 loudness range (LRA) in LU. Pass the buffer's\n * actual `sampleRate`: the default (22050) is non-standard and K-weighting is\n * sample-rate dependent.\n */\nexport function ebur128LoudnessRange(request: Ebur128LoudnessRangeRequest): number;\nexport function ebur128LoudnessRange(samples: Float32Array, sampleRate?: number): number;\nexport function ebur128LoudnessRange(\n samples: Float32Array | Ebur128LoudnessRangeRequest,\n sampleRate = 22050,\n): number {\n if (!(samples instanceof Float32Array)) {\n return ebur128LoudnessRange(samples.samples, samples.sampleRate);\n }\n return requireModule().ebur128LoudnessRange(samples, sampleRate);\n}\n\n/**\n * Compute spectral bandwidth.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns Spectral bandwidth in Hz for each frame\n */\nexport function spectralBandwidth(request: SpectralFrameRequest & { p?: number }): Float32Array;\nexport function spectralBandwidth(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n p?: number,\n): Float32Array;\nexport function spectralBandwidth(\n samples: Float32Array | (SpectralFrameRequest & { p?: number }),\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n p = 2,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return spectralBandwidth(\n samples.samples,\n samples.sampleRate,\n samples.nFft,\n samples.hopLength,\n samples.p,\n );\n }\n return requireModule().spectralBandwidth(samples, sampleRate, nFft, hopLength, p);\n}\n\n/**\n * Compute spectral rolloff frequency.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param rollPercent - Percentage threshold (default: 0.85)\n * @returns Rolloff frequency in Hz for each frame\n */\nexport function spectralRolloff(request: SpectralRolloffRequest): Float32Array;\nexport function spectralRolloff(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n rollPercent?: number,\n): Float32Array;\nexport function spectralRolloff(\n samples: Float32Array | SpectralRolloffRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n rollPercent = 0.85,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return spectralRolloff(\n samples.samples,\n samples.sampleRate,\n samples.nFft,\n samples.hopLength,\n samples.rollPercent,\n );\n }\n return requireModule().spectralRolloff(samples, sampleRate, nFft, hopLength, rollPercent);\n}\n\n/**\n * Compute spectral flatness.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns Spectral flatness for each frame (0 = tonal, 1 = noise-like)\n */\nexport function spectralFlatness(request: SpectralFrameRequest): Float32Array;\nexport function spectralFlatness(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n): Float32Array;\nexport function spectralFlatness(\n samples: Float32Array | SpectralFrameRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return spectralFlatness(samples.samples, samples.sampleRate, samples.nFft, samples.hopLength);\n }\n return requireModule().spectralFlatness(samples, sampleRate, nFft, hopLength);\n}\n\nexport function spectralFlux(request: SpectralFrameRequest & { lag?: number }): Float32Array;\nexport function spectralFlux(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n lag?: number,\n): Float32Array;\nexport function spectralFlux(\n samples: Float32Array | (SpectralFrameRequest & { lag?: number }),\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n lag = 1,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return spectralFlux(\n samples.samples,\n samples.sampleRate,\n samples.nFft,\n samples.hopLength,\n samples.lag,\n );\n }\n return requireModule().spectralFlux(samples, sampleRate, nFft, hopLength, lag);\n}\n\n/**\n * Compute zero crossing rate.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param frameLength - Frame length (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns Zero crossing rate for each frame\n */\nexport function zeroCrossingRate(request: ZeroCrossingRateRequest): Float32Array;\nexport function zeroCrossingRate(\n samples: Float32Array,\n sampleRate?: number,\n frameLength?: number,\n hopLength?: number,\n): Float32Array;\nexport function zeroCrossingRate(\n samples: Float32Array | ZeroCrossingRateRequest,\n sampleRate = 22050,\n frameLength = 2048,\n hopLength = 512,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return zeroCrossingRate(\n samples.samples,\n samples.sampleRate,\n samples.frameLength,\n samples.hopLength,\n );\n }\n return requireModule().zeroCrossingRate(samples, sampleRate, frameLength, hopLength);\n}\n\n/**\n * Compute RMS energy.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param frameLength - Frame length (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns RMS energy for each frame\n */\nexport function rmsEnergy(request: ZeroCrossingRateRequest): Float32Array;\nexport function rmsEnergy(\n samples: Float32Array,\n sampleRate?: number,\n frameLength?: number,\n hopLength?: number,\n): Float32Array;\nexport function rmsEnergy(\n samples: Float32Array | ZeroCrossingRateRequest,\n sampleRate = 22050,\n frameLength = 2048,\n hopLength = 512,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return rmsEnergy(samples.samples, samples.sampleRate, samples.frameLength, samples.hopLength);\n }\n return requireModule().rmsEnergy(samples, sampleRate, frameLength, hopLength);\n}\n\n/** Column-wise cross-similarity (librosa.segment.cross_similarity). */\nexport function segmentCrossSimilarity(request: SegmentCrossSimilarityRequest): SegmentMatrix {\n validateSegmentMatrix('segmentCrossSimilarity', request.x, request.xRows, request.xCols, 'x');\n validateSegmentMatrix('segmentCrossSimilarity', request.y, request.yRows, request.yCols, 'y');\n if (request.xRows !== request.yRows) {\n throw new RangeError('segmentCrossSimilarity: feature dimensions must match');\n }\n assertNonNegativeInteger('segmentCrossSimilarity', request.k ?? 0, 'k');\n return requireModule().segmentCrossSimilarity(\n request.x,\n request.xRows,\n request.xCols,\n request.y,\n request.yRows,\n request.yCols,\n request.k ?? 0,\n request.metric ?? 'cosine',\n request.mode ?? 'connectivity',\n );\n}\n\n/** Self-similarity recurrence matrix (librosa.segment.recurrence_matrix). */\nexport function segmentRecurrenceMatrix(request: SegmentRecurrenceMatrixRequest): SegmentMatrix {\n validateSegmentMatrix(\n 'segmentRecurrenceMatrix',\n request.data,\n request.rows,\n request.cols,\n 'data',\n );\n assertNonNegativeInteger('segmentRecurrenceMatrix', request.k ?? 0, 'k');\n assertNonNegativeInteger('segmentRecurrenceMatrix', request.width ?? 1, 'width');\n return requireModule().segmentRecurrenceMatrix(\n request.data,\n request.rows,\n request.cols,\n request.k ?? 0,\n request.width ?? 1,\n request.sym ?? false,\n request.metric ?? 'euclidean',\n request.mode ?? 'connectivity',\n );\n}\n\n/** Convert an `n × n` recurrence matrix to a lag matrix. */\nexport function segmentRecurrenceToLag(request: SegmentRecurrenceToLagRequest): SegmentMatrix {\n validateSegmentMatrix(\n 'segmentRecurrenceToLag',\n request.recurrence,\n request.n,\n request.n,\n 'recurrence',\n );\n return requireModule().segmentRecurrenceToLag(\n request.recurrence,\n request.n,\n request.pad ?? false,\n );\n}\n\n/** Convert a lag matrix back to an `n × n` recurrence matrix. */\nexport function segmentLagToRecurrence(request: SegmentLagToRecurrenceRequest): SegmentMatrix {\n validateSegmentMatrix('segmentLagToRecurrence', request.lag, request.rows, request.lags, 'lag');\n return requireModule().segmentLagToRecurrence(request.lag, request.rows, request.lags);\n}\n\n/** Refine frame boundaries by clustering within each parent segment. */\nexport function segmentSubsegment(request: SegmentSubsegmentRequest): Int32Array {\n validateSegmentMatrix('segmentSubsegment', request.data, request.rows, request.cols, 'data');\n assertPositiveInteger('segmentSubsegment', request.nSegments ?? 4, 'nSegments');\n return requireModule().segmentSubsegment(\n request.data,\n request.rows,\n request.cols,\n request.boundaries,\n request.nSegments ?? 4,\n );\n}\n\n/** Cluster feature columns and return one label per column. */\nexport function segmentAgglomerative(request: SegmentAgglomerativeRequest): Int32Array {\n validateSegmentMatrix('segmentAgglomerative', request.data, request.rows, request.cols, 'data');\n assertPositiveInteger('segmentAgglomerative', request.k, 'k');\n return requireModule().segmentAgglomerative(\n request.data,\n request.rows,\n request.cols,\n request.k,\n request.linkage ?? 'average',\n );\n}\n\n/** Enhance diagonal paths in an `n × n` recurrence matrix. */\nexport function segmentPathEnhance(request: SegmentPathEnhanceRequest): SegmentMatrix {\n validateSegmentMatrix(\n 'segmentPathEnhance',\n request.recurrence,\n request.n,\n request.n,\n 'recurrence',\n );\n assertPositiveInteger('segmentPathEnhance', request.win, 'win');\n assertPositiveInteger('segmentPathEnhance', request.maxRatio ?? 2, 'maxRatio');\n assertNonNegativeInteger('segmentPathEnhance', request.minRatio ?? 0, 'minRatio');\n assertPositiveInteger('segmentPathEnhance', request.nFilters ?? 7, 'nFilters');\n return requireModule().segmentPathEnhance(\n request.recurrence,\n request.n,\n request.win,\n request.maxRatio ?? 2,\n request.minRatio ?? 0,\n request.nFilters ?? 7,\n );\n}\n","import { getSonareModule } from './module_state';\nimport type {\n ChromaResult,\n MelPowerResult,\n MelSpectrogramResult,\n MfccResult,\n ReassignedSpectrogramResult,\n StftPowerResult,\n StftResult,\n} from './public_types';\nimport type { ValidateOptions } from './validation';\nimport {\n assertFiniteScalar,\n assertPositiveInteger,\n assertSampleRate,\n assertSamples,\n} from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\ntype GuardedOptions = ValidateOptions;\n\n/** Canonical request form for basic frame-based spectrogram features. */\nexport interface SpectrogramRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n nFft?: number;\n hopLength?: number;\n}\n\nexport interface ChromaSpectrogramRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n nChroma?: number;\n binsPerOctave?: number;\n}\n\nexport interface MelSpectrogramRequest extends SpectrogramRequest {\n nMels?: number;\n fmin?: number;\n fmax?: number;\n htk?: boolean;\n}\n\nexport interface MfccRequest extends MelSpectrogramRequest {\n nMfcc?: number;\n lifter?: number;\n}\n\nexport interface MelDeltaRequest extends GuardedOptions {\n features: Float32Array;\n nFeatures: number;\n nFrames: number;\n width?: number;\n}\nexport interface ReassignedSpectrogramRequest extends SpectrogramRequest {\n refPower?: number;\n fillNan?: boolean;\n}\n\nexport interface MfccToMelRequest extends GuardedOptions {\n mfccCoefficients: Float32Array;\n nMfcc: number;\n nFrames: number;\n nMels?: number;\n /** Lifter used by the forward MFCC transform; zero means no liftering. */\n lifter?: number;\n}\n\n/** Canonical request form for reconstruction from a Mel power spectrogram. */\nexport interface MelToStftRequest extends GuardedOptions {\n melPower: Float32Array;\n nMels: number;\n nFrames: number;\n sampleRate?: number;\n nFft?: number;\n fmin?: number;\n fmax?: number;\n htk?: boolean;\n}\n\n/** Canonical request form for Griffin-Lim reconstruction from Mel power. */\nexport interface MelToAudioRequest extends MelToStftRequest {\n hopLength?: number;\n nIter?: number;\n}\nexport interface GriffinLimRequest extends GuardedOptions {\n magnitude: Float32Array;\n nBins: number;\n nFrames: number;\n sampleRate?: number;\n nFft?: number;\n hopLength?: number;\n nIter?: number;\n momentum?: number;\n}\n\n/** Canonical request form for Griffin-Lim reconstruction from MFCCs. */\nexport interface MfccToAudioRequest extends MfccToMelRequest {\n sampleRate?: number;\n nFft?: number;\n hopLength?: number;\n fmin?: number;\n fmax?: number;\n nIter?: number;\n htk?: boolean;\n}\n\nexport interface TrimRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate: number;\n thresholdDb?: number;\n frameLength?: number;\n hopLength?: number;\n}\n\nfunction validateSpectrogramSamples(\n fnName: string,\n samples: Float32Array,\n sampleRate: number,\n options: GuardedOptions = {},\n): void {\n assertSampleRate(fnName, sampleRate);\n assertSamples(fnName, samples, options.validate !== false);\n}\n\nfunction validatePositiveIntegers(fnName: string, values: Record<string, number>): void {\n for (const [name, value] of Object.entries(values)) {\n assertPositiveInteger(fnName, value, name);\n }\n}\n\nfunction validateMelFrequencyRange(\n fnName: string,\n fmin: number,\n fmax: number,\n sampleRate: number,\n): void {\n assertFiniteScalar(fnName, fmin, 'fmin');\n assertFiniteScalar(fnName, fmax, 'fmax');\n if (fmin < 0) {\n throw new RangeError(`${fnName}: fmin must be non-negative`);\n }\n if (fmax < 0) {\n throw new RangeError(`${fnName}: fmax must be non-negative`);\n }\n const effectiveFmax = fmax === 0 ? sampleRate / 2 : fmax;\n if (effectiveFmax <= fmin) {\n throw new RangeError(`${fnName}: fmax must be greater than fmin`);\n }\n}\n\nfunction validateMatrix(\n fnName: string,\n data: Float32Array,\n rows: number,\n frames: number,\n dataName: string,\n rowName: string,\n options: GuardedOptions = {},\n): void {\n validatePositiveIntegers(fnName, { [rowName]: rows, nFrames: frames });\n assertSamples(fnName, data, options.validate !== false, dataName);\n const expectedLength = rows * frames;\n if (!Number.isSafeInteger(expectedLength) || data.length !== expectedLength) {\n throw new RangeError(`${fnName}: ${dataName} length must equal ${rowName} * nFrames`);\n }\n}\n\n/**\n * Trim silence from beginning and end of audio.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz\n * @param thresholdDb - Silence threshold in dB (default: -60 dB)\n * @returns Trimmed audio\n */\nexport function trim(request: TrimRequest): Float32Array;\nexport function trim(\n samples: Float32Array,\n sampleRate: number,\n thresholdDb?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function trim(\n samples: Float32Array,\n sampleRate: number,\n thresholdDb?: number,\n frameLength?: number,\n hopLength?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function trim(\n samples: Float32Array | TrimRequest,\n sampleRate = 22050,\n thresholdDb = -60.0,\n frameLengthOrOptions?: number | GuardedOptions,\n hopLength?: number,\n options: GuardedOptions = {},\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return trim(r.samples, r.sampleRate, r.thresholdDb, r.frameLength, r.hopLength, r);\n }\n if (frameLengthOrOptions === null) {\n throw new TypeError('trim: frameLength must be an integer or options object');\n }\n if (\n frameLengthOrOptions !== undefined &&\n typeof frameLengthOrOptions !== 'number' &&\n typeof frameLengthOrOptions !== 'object'\n ) {\n throw new TypeError('trim: frameLength must be an integer or options object');\n }\n const positionalOptions =\n typeof frameLengthOrOptions === 'object' && frameLengthOrOptions !== null\n ? frameLengthOrOptions\n : options;\n const positionalFrameLength =\n typeof frameLengthOrOptions === 'number' ? frameLengthOrOptions : undefined;\n const resolvedFrameLength = positionalFrameLength ?? 2048;\n const resolvedHopLength = hopLength === undefined ? 512 : hopLength;\n validateSpectrogramSamples('trim', samples, sampleRate, positionalOptions);\n assertFiniteScalar('trim', thresholdDb, 'thresholdDb');\n assertPositiveInteger('trim', resolvedFrameLength, 'frameLength');\n assertPositiveInteger('trim', resolvedHopLength, 'hopLength');\n if (resolvedFrameLength > 2 ** 31 - 1 || resolvedHopLength > 2 ** 31 - 1) {\n throw new RangeError('trim: frameLength and hopLength must fit in a signed 32-bit integer');\n }\n return requireModule().trimEx(\n samples,\n sampleRate,\n thresholdDb,\n resolvedFrameLength,\n resolvedHopLength,\n );\n}\n\n// ============================================================================\n// Features - Spectrogram\n// ============================================================================\n\n/**\n * Compute Short-Time Fourier Transform (STFT).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns STFT result with magnitude and power spectrograms\n */\nexport function stft(request: SpectrogramRequest): StftResult;\nexport function stft(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n options?: GuardedOptions,\n): StftResult;\nexport function stft(\n samples: Float32Array | SpectrogramRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n options: GuardedOptions = {},\n): StftResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return stft(request.samples, request.sampleRate, request.nFft, request.hopLength, request);\n }\n validateSpectrogramSamples('stft', samples, sampleRate, options);\n validatePositiveIntegers('stft', { nFft, hopLength });\n return requireModule().stft(samples, sampleRate, nFft, hopLength);\n}\n\n/**\n * Compute STFT and return magnitude in decibels.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns STFT result with dB values\n */\nexport function stftDb(request: SpectrogramRequest): {\n nBins: number;\n nFrames: number;\n db: Float32Array;\n};\nexport function stftDb(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n options?: GuardedOptions,\n): { nBins: number; nFrames: number; db: Float32Array };\nexport function stftDb(\n samples: Float32Array | SpectrogramRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n options: GuardedOptions = {},\n): { nBins: number; nFrames: number; db: Float32Array } {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return stftDb(request.samples, request.sampleRate, request.nFft, request.hopLength, request);\n }\n validateSpectrogramSamples('stftDb', samples, sampleRate, options);\n validatePositiveIntegers('stftDb', { nFft, hopLength });\n return requireModule().stftDb(samples, sampleRate, nFft, hopLength);\n}\n\n/**\n * Compute Chroma Energy Normalized Statistics.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param nChroma - Number of chroma bins (default: 12)\n * @returns Chroma result\n */\nexport function chromaCens(request: ChromaSpectrogramRequest): ChromaResult;\nexport function chromaCens(\n samples: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n nChroma?: number,\n binsPerOctave?: number,\n options?: GuardedOptions,\n): ChromaResult;\nexport function chromaCens(\n samples: Float32Array | ChromaSpectrogramRequest,\n sampleRate = 22050,\n hopLength = 512,\n nChroma = 12,\n binsPerOctave = 36,\n options: GuardedOptions = {},\n): ChromaResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return chromaCens(\n request.samples,\n request.sampleRate,\n request.hopLength,\n request.nChroma,\n request.binsPerOctave,\n request,\n );\n }\n validateSpectrogramSamples('chromaCens', samples, sampleRate, options);\n validatePositiveIntegers('chromaCens', { hopLength, nChroma, binsPerOctave });\n if (binsPerOctave % nChroma !== 0) {\n throw new RangeError('chromaCens: binsPerOctave must be a multiple of nChroma');\n }\n return requireModule().chromaCens(samples, sampleRate, hopLength, nChroma, binsPerOctave);\n}\n\n/**\n * Compute a constant-Q chromagram (librosa.feature.chroma_cqt).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param nChroma - Number of chroma bins (default: 12)\n * @returns Chroma result\n */\nexport function chromaCqt(request: ChromaSpectrogramRequest): ChromaResult;\nexport function chromaCqt(\n samples: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n nChroma?: number,\n binsPerOctave?: number,\n options?: GuardedOptions,\n): ChromaResult;\nexport function chromaCqt(\n samples: Float32Array | ChromaSpectrogramRequest,\n sampleRate = 22050,\n hopLength = 512,\n nChroma = 12,\n binsPerOctave = 36,\n options: GuardedOptions = {},\n): ChromaResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return chromaCqt(\n request.samples,\n request.sampleRate,\n request.hopLength,\n request.nChroma,\n request.binsPerOctave,\n request,\n );\n }\n validateSpectrogramSamples('chromaCqt', samples, sampleRate, options);\n validatePositiveIntegers('chromaCqt', { hopLength, nChroma, binsPerOctave });\n if (binsPerOctave % nChroma !== 0) {\n throw new RangeError('chromaCqt: binsPerOctave must be a multiple of nChroma');\n }\n return requireModule().chromaCqt(samples, sampleRate, hopLength, nChroma, binsPerOctave);\n}\n\n/**\n * Compute low-frequency bass chroma.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param nChroma - Number of chroma bins (default: 12)\n * @returns Chroma result\n */\nexport function bassChroma(request: ChromaSpectrogramRequest): ChromaResult;\nexport function bassChroma(\n samples: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n nChroma?: number,\n options?: GuardedOptions,\n): ChromaResult;\nexport function bassChroma(\n samples: Float32Array | ChromaSpectrogramRequest,\n sampleRate = 22050,\n hopLength = 512,\n nChroma = 12,\n options: GuardedOptions = {},\n): ChromaResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return bassChroma(\n request.samples,\n request.sampleRate,\n request.hopLength,\n request.nChroma,\n request,\n );\n }\n validateSpectrogramSamples('bassChroma', samples, sampleRate, options);\n validatePositiveIntegers('bassChroma', { hopLength, nChroma });\n return requireModule().bassChroma(samples, sampleRate, hopLength, nChroma);\n}\n\n// ============================================================================\n// Features - Mel Spectrogram\n// ============================================================================\n\n/**\n * Compute Mel spectrogram.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param nMels - Number of Mel bands (default: 128)\n * @param fmin - Minimum Mel frequency in Hz (default: 0 = librosa default).\n * Set with `fmax` to round-trip with `melToStft` / `melToAudio`.\n * @param fmax - Maximum Mel frequency in Hz (default: 0 = sampleRate / 2)\n * @param htk - Use the HTK Mel formula instead of Slaney (default: false)\n * @returns Mel spectrogram result\n */\nexport function melSpectrogram(request: MelSpectrogramRequest): MelSpectrogramResult;\nexport function melSpectrogram(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n nMels?: number,\n fmin?: number,\n fmax?: number,\n htk?: boolean,\n options?: GuardedOptions,\n): MelSpectrogramResult;\nexport function melSpectrogram(\n samples: Float32Array | MelSpectrogramRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n nMels = 128,\n fmin = 0,\n fmax = 0,\n htk = false,\n options: GuardedOptions = {},\n): MelSpectrogramResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return melSpectrogram(\n request.samples,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.nMels,\n request.fmin,\n request.fmax,\n request.htk,\n request,\n );\n }\n validateSpectrogramSamples('melSpectrogram', samples, sampleRate, options);\n validatePositiveIntegers('melSpectrogram', { nFft, hopLength, nMels });\n validateMelFrequencyRange('melSpectrogram', fmin, fmax, sampleRate);\n return requireModule().melSpectrogram(\n samples,\n sampleRate,\n nFft,\n hopLength,\n nMels,\n fmin,\n fmax,\n htk,\n );\n}\n\n/**\n * Compute MFCC (Mel-Frequency Cepstral Coefficients).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param nMels - Number of Mel bands (default: 128)\n * @param nMfcc - Number of MFCC coefficients (default: 20)\n * @param fmin - Minimum Mel frequency in Hz (default: 0 = librosa default)\n * @param fmax - Maximum Mel frequency in Hz (default: 0 = sampleRate / 2)\n * @param htk - Use the HTK Mel formula instead of Slaney (default: false)\n * @param lifter - Cepstral liftering coefficient (default: 0 = no liftering)\n * @returns MFCC result\n */\nexport function mfcc(request: MfccRequest): MfccResult;\nexport function mfcc(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n nMels?: number,\n nMfcc?: number,\n fmin?: number,\n fmax?: number,\n htk?: boolean,\n lifter?: number,\n options?: GuardedOptions,\n): MfccResult;\nexport function mfcc(\n samples: Float32Array | MfccRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n nMels = 128,\n nMfcc = 20,\n fmin = 0,\n fmax = 0,\n htk = false,\n lifter = 0,\n options: GuardedOptions = {},\n): MfccResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return mfcc(\n request.samples,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.nMels,\n request.nMfcc,\n request.fmin,\n request.fmax,\n request.htk,\n request.lifter,\n request,\n );\n }\n validateSpectrogramSamples('mfcc', samples, sampleRate, options);\n validatePositiveIntegers('mfcc', { nFft, hopLength, nMels, nMfcc });\n validateMelFrequencyRange('mfcc', fmin, fmax, sampleRate);\n return requireModule().mfcc(\n samples,\n sampleRate,\n nFft,\n hopLength,\n nMels,\n nMfcc,\n fmin,\n fmax,\n htk,\n lifter,\n );\n}\n\n/** First-order regression delta of a row-major feature matrix. */\nexport function melDelta(request: MelDeltaRequest): Float32Array;\nexport function melDelta(\n features: Float32Array,\n nFeatures: number,\n nFrames: number,\n width?: number,\n): Float32Array;\nexport function melDelta(\n features: Float32Array | MelDeltaRequest,\n nFeatures?: number,\n nFrames?: number,\n width = 9,\n): Float32Array {\n const request: MelDeltaRequest =\n features instanceof Float32Array\n ? { features, nFeatures: nFeatures ?? 0, nFrames: nFrames ?? 0, width }\n : features;\n assertPositiveInteger('melDelta', request.nFeatures, 'nFeatures');\n assertPositiveInteger('melDelta', request.nFrames, 'nFrames');\n assertPositiveInteger('melDelta', request.width ?? 9, 'width');\n if ((request.width ?? 9) < 3 || (request.width ?? 9) % 2 === 0) {\n throw new RangeError('melDelta: width must be an odd integer of at least 3');\n }\n if (request.features.length !== request.nFeatures * request.nFrames) {\n throw new RangeError('melDelta: feature matrix length must equal nFeatures * nFrames');\n }\n return requireModule().melDelta(\n request.features,\n request.nFeatures,\n request.nFrames,\n request.width ?? 9,\n );\n}\n\n/** Auger-Flandrin reassigned spectrogram (row-major [nBins x nFrames] arrays). */\nexport function reassignedSpectrogram(\n request: ReassignedSpectrogramRequest,\n): ReassignedSpectrogramResult;\nexport function reassignedSpectrogram(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n refPower?: number,\n fillNan?: boolean,\n): ReassignedSpectrogramResult;\nexport function reassignedSpectrogram(\n samples: Float32Array | ReassignedSpectrogramRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n refPower = 1e-6,\n fillNan = false,\n): ReassignedSpectrogramResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return reassignedSpectrogram(\n request.samples,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.refPower,\n request.fillNan,\n );\n }\n assertSamples('reassignedSpectrogram', samples, true);\n assertSampleRate('reassignedSpectrogram', sampleRate);\n assertPositiveInteger('reassignedSpectrogram', nFft, 'nFft');\n assertPositiveInteger('reassignedSpectrogram', hopLength, 'hopLength');\n assertFiniteScalar('reassignedSpectrogram', refPower, 'refPower');\n if (refPower < 0) {\n throw new RangeError('reassignedSpectrogram: refPower must be non-negative');\n }\n return requireModule().reassignedSpectrogram(\n samples,\n sampleRate,\n nFft,\n hopLength,\n refPower,\n fillNan,\n );\n}\n\n// ============================================================================\n// Features - Inverse reconstruction\n// ============================================================================\n\n/**\n * Approximate inverse of a Mel filterbank: Mel power spectrogram -> STFT power\n * spectrogram. Mirrors `feature::mel_to_stft`.\n *\n * @param melPower - Mel power spectrogram [nMels x nFrames] row-major\n * @param nMels - Number of Mel bands\n * @param nFrames - Number of time frames\n * @param sampleRate - Sample rate in Hz\n * @param nFft - FFT size (default: 2048)\n * @param fmin - Lower Mel band edge in Hz (default: 0)\n * @param fmax - Upper Mel band edge in Hz (default: sr/2 when 0)\n * @param htk - Use the HTK Mel formula instead of Slaney (default: false)\n * @returns STFT power spectrogram result\n */\nexport function melToStft(request: MelToStftRequest): StftPowerResult;\nexport function melToStft(\n melPower: Float32Array,\n nMels: number,\n nFrames: number,\n sampleRate?: number,\n nFft?: number,\n fmin?: number,\n fmax?: number,\n htk?: boolean,\n options?: GuardedOptions,\n): StftPowerResult;\nexport function melToStft(\n melPower: Float32Array | MelToStftRequest,\n nMels = 0,\n nFrames = 0,\n sampleRate = 22050,\n nFft = 2048,\n fmin = 0,\n fmax = 0,\n htk = false,\n options: GuardedOptions = {},\n): StftPowerResult {\n if (!(melPower instanceof Float32Array)) {\n const request = melPower;\n return melToStft(\n request.melPower,\n request.nMels,\n request.nFrames,\n request.sampleRate,\n request.nFft,\n request.fmin,\n request.fmax,\n request.htk,\n request,\n );\n }\n assertSampleRate('melToStft', sampleRate);\n validateMatrix('melToStft', melPower, nMels, nFrames, 'melPower', 'nMels', options);\n validatePositiveIntegers('melToStft', { nFft });\n validateMelFrequencyRange('melToStft', fmin, fmax, sampleRate);\n return requireModule().melToStft(melPower, nMels, nFrames, sampleRate, nFft, fmin, fmax, htk);\n}\n\n/**\n * Reconstruct audio from a Mel power spectrogram via Griffin-Lim. Mirrors\n * `feature::mel_to_audio`.\n *\n * @param melPower - Mel power spectrogram [nMels x nFrames] row-major\n * @param nMels - Number of Mel bands\n * @param nFrames - Number of time frames\n * @param sampleRate - Sample rate in Hz\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum Mel frequency in Hz (default: 0)\n * @param fmax - Maximum Mel frequency in Hz (default: 0 = sr/2)\n * @param nIter - Griffin-Lim iterations (default: 32)\n * @param htk - Use the HTK Mel formula instead of Slaney (default: false)\n * @returns Reconstructed audio samples (mono, float32)\n */\nexport function melToAudio(request: MelToAudioRequest): Float32Array;\nexport function melToAudio(\n melPower: Float32Array,\n nMels: number,\n nFrames: number,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n fmin?: number,\n fmax?: number,\n nIter?: number,\n htk?: boolean,\n options?: GuardedOptions,\n): Float32Array;\nexport function melToAudio(\n melPower: Float32Array | MelToAudioRequest,\n nMels = 0,\n nFrames = 0,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n fmin = 0,\n fmax = 0,\n nIter = 32,\n htk = false,\n options: GuardedOptions = {},\n): Float32Array {\n if (!(melPower instanceof Float32Array)) {\n const request = melPower;\n return melToAudio(\n request.melPower,\n request.nMels,\n request.nFrames,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.fmin,\n request.fmax,\n request.nIter,\n request.htk,\n request,\n );\n }\n assertSampleRate('melToAudio', sampleRate);\n validateMatrix('melToAudio', melPower, nMels, nFrames, 'melPower', 'nMels', options);\n validatePositiveIntegers('melToAudio', { nFft, hopLength, nIter });\n validateMelFrequencyRange('melToAudio', fmin, fmax, sampleRate);\n return requireModule().melToAudio(\n melPower,\n nMels,\n nFrames,\n sampleRate,\n nFft,\n hopLength,\n fmin,\n fmax,\n nIter,\n htk,\n );\n}\n\n/** Reconstruct audio from an STFT magnitude matrix via Griffin-Lim. */\nexport function griffinLim(request: GriffinLimRequest): Float32Array;\nexport function griffinLim(\n magnitude: Float32Array,\n nBins: number,\n nFrames: number,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n nIter?: number,\n momentum?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function griffinLim(\n magnitude: Float32Array | GriffinLimRequest,\n nBins = 0,\n nFrames = 0,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n nIter = 32,\n momentum = 0.99,\n options: GuardedOptions = {},\n): Float32Array {\n if (!(magnitude instanceof Float32Array)) {\n const request = magnitude;\n return griffinLim(\n request.magnitude,\n request.nBins,\n request.nFrames,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.nIter,\n request.momentum,\n request,\n );\n }\n assertSampleRate('griffinLim', sampleRate);\n validateMatrix('griffinLim', magnitude, nBins, nFrames, 'magnitude', 'nBins', options);\n validatePositiveIntegers('griffinLim', { nFft, hopLength, nIter });\n return requireModule().griffinLim(\n magnitude,\n nBins,\n nFrames,\n sampleRate,\n nFft,\n hopLength,\n nIter,\n momentum,\n );\n}\n\n/**\n * Invert MFCC coefficients back to a Mel power spectrogram. Mirrors\n * `feature::mfcc_to_mel`.\n *\n * @param mfccCoefficients - MFCC matrix [nMfcc x nFrames] row-major\n * @param nMfcc - Number of MFCC coefficients\n * @param nFrames - Number of time frames\n * @param nMels - Number of Mel bins to reconstruct (default: 128)\n * @returns Mel power spectrogram result\n */\nexport function mfccToMel(request: MfccToMelRequest): MelPowerResult;\nexport function mfccToMel(\n mfccCoefficients: Float32Array,\n nMfcc: number,\n nFrames: number,\n nMels?: number,\n lifter?: number,\n options?: GuardedOptions,\n): MelPowerResult;\nexport function mfccToMel(\n mfccCoefficients: Float32Array | MfccToMelRequest,\n nMfcc = 0,\n nFrames = 0,\n nMels = 128,\n lifter = 0,\n options: GuardedOptions = {},\n): MelPowerResult {\n if (!(mfccCoefficients instanceof Float32Array)) {\n const request = mfccCoefficients;\n return mfccToMel(\n request.mfccCoefficients,\n request.nMfcc,\n request.nFrames,\n request.nMels,\n request.lifter,\n request,\n );\n }\n validateMatrix(\n 'mfccToMel',\n mfccCoefficients,\n nMfcc,\n nFrames,\n 'mfccCoefficients',\n 'nMfcc',\n options,\n );\n validatePositiveIntegers('mfccToMel', { nMels });\n return requireModule().mfccToMel(mfccCoefficients, nMfcc, nFrames, nMels, lifter);\n}\n\n/**\n * Reconstruct audio directly from MFCC coefficients via Griffin-Lim. Mirrors\n * `feature::mfcc_to_audio`.\n *\n * @param mfccCoefficients - MFCC matrix [nMfcc x nFrames] row-major\n * @param nMfcc - Number of MFCC coefficients\n * @param nFrames - Number of time frames\n * @param nMels - Number of Mel bins (default: 128)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum Mel frequency in Hz (default: 0)\n * @param fmax - Maximum Mel frequency in Hz (default: 0 = sr/2)\n * @param nIter - Griffin-Lim iterations (default: 32)\n * @param htk - Use the HTK Mel formula instead of Slaney (default: false)\n * @returns Reconstructed audio samples (mono, float32)\n */\nexport function mfccToAudio(request: MfccToAudioRequest): Float32Array;\nexport function mfccToAudio(\n mfccCoefficients: Float32Array,\n nMfcc: number,\n nFrames: number,\n nMels?: number,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n fmin?: number,\n fmax?: number,\n nIter?: number,\n htk?: boolean,\n lifter?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function mfccToAudio(\n mfccCoefficients: Float32Array | MfccToAudioRequest,\n nMfcc = 0,\n nFrames = 0,\n nMels = 128,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n fmin = 0,\n fmax = 0,\n nIter = 32,\n htk = false,\n lifter = 0,\n options: GuardedOptions = {},\n): Float32Array {\n if (!(mfccCoefficients instanceof Float32Array)) {\n const request = mfccCoefficients;\n return mfccToAudio(\n request.mfccCoefficients,\n request.nMfcc,\n request.nFrames,\n request.nMels,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.fmin,\n request.fmax,\n request.nIter,\n request.htk,\n request.lifter,\n request,\n );\n }\n assertSampleRate('mfccToAudio', sampleRate);\n validateMatrix(\n 'mfccToAudio',\n mfccCoefficients,\n nMfcc,\n nFrames,\n 'mfccCoefficients',\n 'nMfcc',\n options,\n );\n validatePositiveIntegers('mfccToAudio', { nMels, nFft, hopLength, nIter });\n validateMelFrequencyRange('mfccToAudio', fmin, fmax, sampleRate);\n return requireModule().mfccToAudio(\n mfccCoefficients,\n nMfcc,\n nFrames,\n nMels,\n sampleRate,\n nFft,\n hopLength,\n fmin,\n fmax,\n nIter,\n htk,\n lifter,\n );\n}\n\n// ============================================================================\n// Features - Chroma\n// ============================================================================\n\n/**\n * Compute STFT chromagram (librosa.feature.chroma_stft).\n *\n * The chroma filterbank uses a fixed tuning of 0 (concert A440). Unlike\n * librosa.feature.chroma_stft — which estimates tuning from the signal when none\n * is given — this does NOT auto-estimate and exposes no tuning argument, so\n * sharp/flat (non-A440) recordings smear across pitch classes. Estimate tuning\n * separately via {@link estimateTuning} if a non-A440 reference matters.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns Chroma features result\n */\nexport function chroma(request: SpectrogramRequest): ChromaResult;\nexport function chroma(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n options?: GuardedOptions,\n): ChromaResult;\nexport function chroma(\n samples: Float32Array | SpectrogramRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n options: GuardedOptions = {},\n): ChromaResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return chroma(request.samples, request.sampleRate, request.nFft, request.hopLength, request);\n }\n validateSpectrogramSamples('chroma', samples, sampleRate, options);\n validatePositiveIntegers('chroma', { nFft, hopLength });\n return requireModule().chroma(samples, sampleRate, nFft, hopLength);\n}\n","import type { AutomationCurve, MeterTap, PanLawInput, PanMode, SendTiming } from './public_types';\n\n/** Resolve a numeric ordinal in an inclusive range without coercion. */\nexport function resolveOrdinalInRange(\n value: unknown,\n min: number,\n max: number,\n enumName: string,\n): number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < min || value > max) {\n throw new RangeError(`Invalid ${enumName}: ${String(value)}`);\n }\n return value;\n}\n\n/** Resolve a public enum spelling or ordinal without permitting unknown values. */\nexport function resolveEnumOrdinal(\n value: unknown,\n values: Readonly<Record<string, number>>,\n enumName: string,\n): number {\n if (typeof value === 'number') {\n const ordinals = Object.values(values);\n const ordinal = resolveOrdinalInRange(\n value,\n Math.min(...ordinals),\n Math.max(...ordinals),\n enumName,\n );\n if (!ordinals.includes(ordinal)) {\n throw new RangeError(`Invalid ${enumName}: ${String(value)}`);\n }\n return ordinal;\n }\n if (typeof value === 'string') {\n const ordinal = values[value];\n if (ordinal !== undefined) {\n return ordinal;\n }\n }\n throw new RangeError(`Invalid ${enumName}: ${String(value)}`);\n}\n\nconst AUTOMATION_CURVE_VALUES = {\n linear: 0,\n exponential: 1,\n hold: 2,\n 's-curve': 3,\n} as const;\nconst PAN_LAW_VALUES: Readonly<Record<string, number>> = {\n const3db: 0,\n 'const-3db': 0,\n '-3db': 0,\n 'const4.5db': 1,\n 'const-4.5db': 1,\n '-4.5db': 1,\n const6db: 2,\n 'const-6db': 2,\n '-6db': 2,\n linear0db: 3,\n 'linear-0db': 3,\n linear: 3,\n '0db': 3,\n} as const;\nconst PAN_MODE_VALUES = {\n balance: 0,\n pan: 1,\n stereopan: 1,\n 'stereo-pan': 1,\n dualpan: 2,\n 'dual-pan': 2,\n} as const;\nconst METER_TAP_VALUES = { preFader: 0, postFader: 1 } as const;\nconst SEND_TIMING_VALUES = { postFader: 0, preFader: 1 } as const;\nconst TRACK_MONITOR_MODE_VALUES = { off: 0, pfl: 1, afl: 2 } as const;\n\nexport function automationCurveCode(curve: AutomationCurve): number {\n return resolveEnumOrdinal(curve, AUTOMATION_CURVE_VALUES, 'automation curve');\n}\n\nexport function panLawCode(panLaw: PanLawInput): number {\n const normalized = typeof panLaw === 'string' ? panLaw.toLowerCase().replace(/_/g, '-') : panLaw;\n return resolveEnumOrdinal(normalized, PAN_LAW_VALUES, 'pan law');\n}\n\nexport function panModeCode(panMode: PanMode | number): number {\n const normalized =\n typeof panMode === 'string' ? panMode.replace(/_/g, '-').toLowerCase() : panMode;\n return resolveEnumOrdinal(normalized, PAN_MODE_VALUES, 'pan mode');\n}\n\nexport function meterTapCode(tap: MeterTap | number): number {\n return resolveEnumOrdinal(tap, METER_TAP_VALUES, 'meter tap');\n}\n\nexport function sendTimingCode(timing: SendTiming | number): number {\n // Mirrors SonareSendTiming: post-fader is 0 (so an omitted/zeroed value is\n // post-fader), pre-fader is 1. A raw number is passed through as the C ABI int.\n // An unknown string is rejected rather than silently routed to post-fader,\n // matching the sibling enum-code helpers and Node's sendTimingValue.\n return resolveEnumOrdinal(timing, SEND_TIMING_VALUES, 'send timing');\n}\n\n/** Resolve a per-track PFL/AFL monitor mode to its C-ABI ordinal. */\nexport function trackMonitorModeCode(mode: unknown): number {\n return resolveEnumOrdinal(mode, TRACK_MONITOR_MODE_VALUES, 'track monitor mode');\n}\n","import type { ValidateOptions } from './validation';\n\n/**\n * Pitch class enum (C=0, C#=1, ..., B=11)\n */\nexport const PitchClass = {\n C: 0,\n Cs: 1,\n D: 2,\n Ds: 3,\n E: 4,\n F: 5,\n Fs: 6,\n G: 7,\n Gs: 8,\n A: 9,\n As: 10,\n B: 11,\n} as const;\n\nexport type PitchClass = (typeof PitchClass)[keyof typeof PitchClass];\n\n/**\n * Musical mode\n */\nexport const Mode = {\n Major: 0,\n Minor: 1,\n Dorian: 2,\n Phrygian: 3,\n Lydian: 4,\n Mixolydian: 5,\n Locrian: 6,\n} as const;\n\nexport type Mode = (typeof Mode)[keyof typeof Mode];\n\nexport type TempogramMode = 'autocorrelation' | 'auto' | 'ac' | 'cosine' | 0 | 1;\n\nexport const KeyProfile = {\n KrumhanslSchmuckler: 0,\n Temperley: 1,\n Shaath: 2,\n FaraldoEDMT: 3,\n FaraldoEDMA: 4,\n FaraldoEDMM: 5,\n BellmanBudge: 6,\n} as const;\n\nexport type KeyProfile = (typeof KeyProfile)[keyof typeof KeyProfile];\n\nexport type KeyProfileName =\n | 'ks'\n | 'krumhansl'\n | 'temperley'\n | 'shaath'\n | 'keyfinder'\n | 'faraldo-edmt'\n | 'edmt'\n | 'faraldo-edma'\n | 'edma'\n | 'faraldo-edmm'\n | 'edmm'\n | 'bellman-budge'\n | 'bellman';\n\n/**\n * Chord quality\n */\nexport const ChordQuality = {\n Major: 0,\n Minor: 1,\n Diminished: 2,\n Augmented: 3,\n Dominant7: 4,\n Major7: 5,\n Minor7: 6,\n Sus2: 7,\n Sus4: 8,\n Unknown: 9,\n Add9: 10,\n MinorAdd9: 11,\n Dim7: 12,\n HalfDim7: 13,\n Major9: 14,\n Dominant9: 15,\n Sus2Add4: 16,\n} as const;\n\nexport type ChordQuality = (typeof ChordQuality)[keyof typeof ChordQuality];\n\n/**\n * Section type\n */\nexport const SectionType = {\n Intro: 0,\n Verse: 1,\n PreChorus: 2,\n Chorus: 3,\n Bridge: 4,\n Instrumental: 5,\n Outro: 6,\n Unknown: 7,\n} as const;\n\nexport type SectionType = (typeof SectionType)[keyof typeof SectionType];\n\n/**\n * Detected musical key\n */\nexport interface Key {\n root: PitchClass;\n mode: Mode;\n confidence: number;\n name: string;\n shortName: string;\n}\n\nexport interface KeyDetectionOptions extends ValidateOptions {\n nFft?: number;\n hopLength?: number;\n useHpss?: boolean;\n loudnessWeighted?: boolean;\n highPassHz?: number;\n modes?:\n | Mode[]\n | ('major' | 'minor' | 'dorian' | 'phrygian' | 'lydian' | 'mixolydian' | 'locrian')[]\n | 'major-minor'\n | 'all'\n | 'modal';\n profile?: KeyProfile | KeyProfileName;\n genreHint?: 'auto' | 'edm' | 'electronic' | 'dance' | 'pop' | 'classical' | 'jazz' | string;\n}\n\nexport interface KeyCandidate {\n key: Key;\n correlation: number;\n}\n\nexport interface ChordDetectionOptions extends ValidateOptions {\n minDuration?: number;\n smoothingWindow?: number;\n /** Final-template correlation threshold in [0, 1]; below it emits Unknown / N.C. */\n threshold?: number;\n useTriadsOnly?: boolean;\n nFft?: number;\n hopLength?: number;\n useBeatSync?: boolean;\n useHmm?: boolean;\n hmmBeamWidth?: number;\n useKeyContext?: boolean;\n keyRoot?: PitchClass;\n keyMode?: Mode;\n detectInversions?: boolean;\n chromaMethod?: 'stft' | 'nnls';\n}\n\n/** Options for `analyzeBpm`. All fields are optional. */\nexport interface AnalyzeBpmOptions extends ValidateOptions {\n /** Lowest BPM to consider. Default 30. */\n bpmMin?: number;\n /** Highest BPM to consider. Default 300. */\n bpmMax?: number;\n /** Tempo prior the tracker is biased toward. Default 120. */\n startBpm?: number;\n /** FFT size for the onset envelope. Default 2048. */\n nFft?: number;\n /** Hop length for the onset envelope. Default 512. */\n hopLength?: number;\n /** Number of tempo candidates to return. Default 5. */\n maxCandidates?: number;\n}\n\n/** Options for `analyzeRhythm`. All fields are optional. */\nexport interface AnalyzeRhythmOptions extends ValidateOptions {\n /** Lowest BPM to consider. Default 60. */\n bpmMin?: number;\n /** Highest BPM to consider. Default 200. */\n bpmMax?: number;\n /** Tempo prior the tracker is biased toward. Default 120. */\n startBpm?: number;\n /** FFT size for the onset envelope. Default 2048. */\n nFft?: number;\n /** Hop length for the onset envelope. Default 512. */\n hopLength?: number;\n}\n\n/** Options for `analyzeDynamics`. All fields are optional. */\nexport interface AnalyzeDynamicsOptions extends ValidateOptions {\n /** Loudness-curve window length in seconds. Default 0.4. */\n windowSec?: number;\n /** Hop length for the loudness curve. Default 512. */\n hopLength?: number;\n /** Crest-factor (dB) below which the signal is flagged as compressed. Default 6. */\n compressionThreshold?: number;\n}\n\n/** Options for `analyzeTimbre`. All fields are optional. */\nexport interface AnalyzeTimbreOptions extends ValidateOptions {\n /** FFT size. Default 2048. */\n nFft?: number;\n /** Hop length. Default 512. */\n hopLength?: number;\n /** Number of Mel bands. Default 128. */\n nMels?: number;\n /** Number of MFCCs. Default 13. */\n nMfcc?: number;\n /** Per-window analysis length in seconds. Default 0.5. */\n windowSec?: number;\n}\n\n/** Options for `analyzeSections`. All fields are optional. */\nexport interface AnalyzeSectionsOptions {\n /** FFT size. Default 2048. */\n nFft?: number;\n /** Hop length. Default 512. */\n hopLength?: number;\n /** Minimum section duration in seconds. Default 4. */\n minSectionSec?: number;\n}\n\n/**\n * Detected beat\n */\nexport interface Beat {\n time: number;\n strength: number;\n}\n\n/**\n * Detected chord\n */\nexport interface Chord {\n root: PitchClass;\n bass: PitchClass;\n /** Canonical core spelling; stable across all language bindings. */\n rootName: string;\n /** Canonical core spelling; stable across all language bindings. */\n bassName: string;\n quality: ChordQuality;\n start: number;\n end: number;\n confidence: number;\n name: string;\n}\n\nexport interface ChordAnalysisResult {\n chords: Chord[];\n}\n\n/**\n * Detected section\n */\nexport interface Section {\n type: SectionType;\n start: number;\n end: number;\n energyLevel: number;\n confidence: number;\n name: string;\n}\n\n/**\n * A single melody contour point (mirrors the C `SonareMelodyPoint`).\n */\nexport interface MelodyPoint {\n /** Frame time in seconds. */\n time: number;\n /** Estimated fundamental frequency in Hz (0 when unvoiced). */\n frequency: number;\n /** Voicing confidence in `[0, 1]`. */\n confidence: number;\n}\n\n/**\n * Melody analysis result (mirrors the C `SonareMelodyResult`).\n */\nexport interface MelodyResult {\n points: MelodyPoint[];\n pitchRangeOctaves: number;\n pitchStability: number;\n meanFrequency: number;\n vibratoRate: number;\n}\n\n/**\n * Timbre characteristics\n */\nexport interface Timbre {\n brightness: number;\n warmth: number;\n density: number;\n roughness: number;\n complexity: number;\n}\n\n/**\n * Dynamics characteristics\n */\nexport interface Dynamics {\n dynamicRangeDb: number;\n peakDb: number;\n rmsDb: number;\n loudnessRangeDb: number;\n crestFactor: number;\n isCompressed: boolean;\n}\n\n/**\n * Time signature\n */\nexport interface TimeSignature {\n numerator: number;\n denominator: number;\n confidence: number;\n}\n\n/** Existing tempo-estimator hypothesis retained by unified analysis. */\nexport interface BpmHypothesis {\n value: number;\n confidence: number;\n relation: 'primary' | 'half' | 'double' | 'other';\n}\n\n/**\n * Rhythm features\n */\nexport interface RhythmFeatures {\n syncopation: number;\n grooveType: string;\n patternRegularity: number;\n tempoStability: number;\n timeSignature: TimeSignature;\n}\n\n/**\n * Melody contour from the unified analysis (pitch trajectory + summary stats).\n */\nexport interface MelodyContour {\n pitchRangeOctaves: number;\n pitchStability: number;\n meanFrequency: number;\n vibratoRate: number;\n pitches: MelodyPoint[];\n}\n\n/**\n * Complete analysis result\n */\nexport interface AnalysisResult {\n bpm: number;\n bpmConfidence: number;\n bpmCandidates: BpmHypothesis[];\n key: Key;\n timeSignature: TimeSignature;\n timeSignatureCandidates: TimeSignature[];\n beatTimes: Float32Array;\n beats: Beat[];\n chords: Chord[];\n sections: Section[];\n timbre: Timbre;\n dynamics: Dynamics;\n rhythm: RhythmFeatures;\n melody: MelodyContour;\n form: string;\n}\n","import { resolveEnumOrdinal } from './codes';\nimport type {\n AnalysisResult,\n ChordAnalysisResult,\n ChordDetectionOptions,\n ChordQuality,\n KeyCandidate,\n KeyDetectionOptions,\n KeyProfileName,\n PitchClass,\n SectionType,\n} from './public_types';\nimport { KeyProfile as KeyProfileValues, Mode } from './public_types';\nimport type {\n WasmAnalysisResult,\n WasmChordAnalysisResult,\n WasmKeyCandidateResult,\n} from './sonare.js';\n\nconst PITCH_CLASS_NAMES = [\n 'C',\n 'C#',\n 'D',\n 'D#',\n 'E',\n 'F',\n 'F#',\n 'G',\n 'G#',\n 'A',\n 'A#',\n 'B',\n] as const;\n\nfunction pitchClassName(value: number): string {\n return PITCH_CLASS_NAMES[value] ?? 'C';\n}\n\nexport function convertKeyCandidate(wasm: WasmKeyCandidateResult): KeyCandidate {\n return {\n key: {\n root: wasm.key.root as PitchClass,\n mode: wasm.key.mode as Mode,\n confidence: wasm.key.confidence,\n name: wasm.key.name,\n shortName: wasm.key.shortName,\n },\n correlation: wasm.correlation,\n };\n}\n\n// Consolidated spelling -> ordinal tables, resolved through the same\n// resolveEnumOrdinal() primitive as panModeCode/panLawCode/etc. in ./codes.\n// An unmapped string or an out-of-range numeric ordinal throws RangeError\n// instead of silently resolving to `undefined` (which used to reach the WASM\n// layer as a mistyped argument) or passing an unvalidated raw number through.\nconst KEY_MODE_VALUES: Readonly<Record<string, number>> = {\n major: Mode.Major,\n minor: Mode.Minor,\n dorian: Mode.Dorian,\n phrygian: Mode.Phrygian,\n lydian: Mode.Lydian,\n mixolydian: Mode.Mixolydian,\n locrian: Mode.Locrian,\n};\n\nconst KEY_PROFILE_VALUES: Readonly<Record<KeyProfileName, number>> = {\n ks: KeyProfileValues.KrumhanslSchmuckler,\n krumhansl: KeyProfileValues.KrumhanslSchmuckler,\n temperley: KeyProfileValues.Temperley,\n shaath: KeyProfileValues.Shaath,\n keyfinder: KeyProfileValues.Shaath,\n 'faraldo-edmt': KeyProfileValues.FaraldoEDMT,\n edmt: KeyProfileValues.FaraldoEDMT,\n 'faraldo-edma': KeyProfileValues.FaraldoEDMA,\n edma: KeyProfileValues.FaraldoEDMA,\n 'faraldo-edmm': KeyProfileValues.FaraldoEDMM,\n edmm: KeyProfileValues.FaraldoEDMM,\n 'bellman-budge': KeyProfileValues.BellmanBudge,\n bellman: KeyProfileValues.BellmanBudge,\n};\n\nexport function keyModeValues(modes: KeyDetectionOptions['modes'] | undefined): number[] {\n if (!modes) {\n return [];\n }\n if (modes === 'major-minor') {\n return [Mode.Major, Mode.Minor];\n }\n if (modes === 'all' || modes === 'modal') {\n return [\n Mode.Major,\n Mode.Minor,\n Mode.Dorian,\n Mode.Phrygian,\n Mode.Lydian,\n Mode.Mixolydian,\n Mode.Locrian,\n ];\n }\n return modes.map((mode) => resolveEnumOrdinal(mode, KEY_MODE_VALUES, 'key mode'));\n}\n\nexport function keyProfileValue(profile: KeyDetectionOptions['profile'] | undefined): number {\n if (profile === undefined) {\n return -1;\n }\n return resolveEnumOrdinal(profile, KEY_PROFILE_VALUES, 'key profile');\n}\n\nexport function convertChordAnalysisResult(wasm: WasmChordAnalysisResult): ChordAnalysisResult {\n return {\n chords: wasm.chords.map((c) => ({\n root: c.root as PitchClass,\n bass: c.bass as PitchClass,\n rootName: pitchClassName(c.root),\n bassName: pitchClassName(c.bass),\n quality: c.quality as ChordQuality,\n start: c.start,\n end: c.end,\n confidence: c.confidence,\n name: c.name,\n })),\n };\n}\n\nexport function chordChromaMethodValue(method: ChordDetectionOptions['chromaMethod']): number {\n if (method === 'stft') {\n return 0;\n }\n if (method === 'nnls') {\n return 1;\n }\n throw new Error(`Invalid chord chroma method: ${method}`);\n}\n\nexport function convertAnalysisResult(wasm: WasmAnalysisResult): AnalysisResult {\n const beatTimes = new Float32Array(wasm.beats.length);\n for (let i = 0; i < wasm.beats.length; i++) {\n beatTimes[i] = wasm.beats[i].time;\n }\n return {\n bpm: wasm.bpm,\n bpmConfidence: wasm.bpmConfidence,\n bpmCandidates: wasm.bpmCandidates.map((candidate) => ({\n value: candidate.value,\n confidence: candidate.confidence,\n relation: candidate.relation,\n })),\n key: {\n root: wasm.key.root as PitchClass,\n mode: wasm.key.mode as Mode,\n confidence: wasm.key.confidence,\n name: wasm.key.name,\n shortName: wasm.key.shortName,\n },\n timeSignature: wasm.timeSignature,\n timeSignatureCandidates: wasm.timeSignatureCandidates,\n beatTimes,\n beats: wasm.beats,\n chords: wasm.chords.map((c) => ({\n root: c.root as PitchClass,\n bass: c.bass as PitchClass,\n rootName: pitchClassName(c.root),\n bassName: pitchClassName(c.bass),\n quality: c.quality as ChordQuality,\n start: c.start,\n end: c.end,\n confidence: c.confidence,\n name: c.name,\n })),\n sections: wasm.sections.map((s) => ({\n type: s.type as SectionType,\n start: s.start,\n end: s.end,\n energyLevel: s.energyLevel,\n confidence: s.confidence,\n name: s.name,\n })),\n timbre: wasm.timbre,\n dynamics: wasm.dynamics,\n rhythm: wasm.rhythm,\n melody: wasm.melody,\n form: wasm.form,\n };\n}\n","import {\n chordChromaMethodValue,\n convertAnalysisResult,\n convertChordAnalysisResult,\n convertKeyCandidate,\n keyModeValues,\n keyProfileValue,\n} from './analysis_helpers';\nimport { getSonareModule } from './module_state';\nimport type {\n AcousticOptions,\n AcousticResult,\n AnalysisResult,\n AnalyzeBpmOptions,\n AnalyzeDynamicsOptions,\n AnalyzeRhythmOptions,\n AnalyzeTimbreOptions,\n ChordAnalysisResult,\n ChordDetectionOptions,\n Key,\n KeyCandidate,\n KeyDetectionOptions,\n RirResult,\n RirSynthOptions,\n RoomEstimateOptions,\n RoomEstimateResult,\n RoomMorphOptions,\n} from './public_types';\nimport { Mode, PitchClass } from './public_types';\nimport type { ProgressCallback, WasmAcousticResult } from './sonare.js';\nimport type { ValidateOptions } from './validation';\nimport {\n assertFiniteScalar,\n assertNonNegativeInteger,\n assertSampleRate,\n assertSamples,\n} from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\ntype GuardedOptions = ValidateOptions;\n\n/** Canonical request form for one-shot analysis functions. */\nexport interface SamplesRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\n/** Peak-picking configuration for {@link detectOnsets}. */\nexport interface OnsetDetectOptions {\n nFft?: number;\n hopLength?: number;\n threshold?: number;\n preMax?: number;\n postMax?: number;\n preAvg?: number;\n postAvg?: number;\n delta?: number;\n wait?: number;\n backtrack?: boolean;\n backtrackRange?: number;\n}\nexport interface DetectOnsetsRequest extends SamplesRequest, OnsetDetectOptions {}\n\n/** Canonical request form for key detection functions. */\nexport interface DetectKeyRequest extends KeyDetectionOptions, SamplesRequest {}\n\n/** Canonical request form for analysis with synchronous progress reporting. */\nexport interface AnalyzeWithProgressRequest extends SamplesRequest {\n onProgress?: ProgressCallback;\n cancel?: () => boolean;\n}\n\n/** Canonical request form for chord detection. */\nexport interface DetectChordsRequest extends ChordDetectionOptions, SamplesRequest {}\n\n/** Canonical request form for functional chord analysis. */\nexport interface ChordFunctionalAnalysisRequest extends DetectChordsRequest {\n keyRoot: PitchClass;\n /** Musical mode; defaults to {@link Mode.Major}. */\n keyMode?: Mode;\n}\n\n/** Canonical request form for impulse-response analysis. */\nexport interface AnalyzeImpulseResponseRequest extends SamplesRequest {\n nOctaveBands?: number;\n minDecayDb?: number;\n}\n\n/** Canonical request form for acoustic analysis. */\nexport interface DetectAcousticRequest extends AcousticOptions, SamplesRequest {}\n\n/** Canonical request form for equivalent-room estimation. */\nexport interface EstimateRoomRequest extends RoomEstimateOptions, SamplesRequest {}\n\n/** Canonical request form for room-reverb morphing. */\nexport interface RoomMorphRequest extends RoomMorphOptions, GuardedOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Canonical request forms for detailed music-analysis APIs. */\nexport interface AnalyzeBpmRequest extends AnalyzeBpmOptions, SamplesRequest {}\nexport interface AnalyzeRhythmRequest extends AnalyzeRhythmOptions, SamplesRequest {}\nexport interface AnalyzeDynamicsRequest extends AnalyzeDynamicsOptions, SamplesRequest {}\nexport interface AnalyzeTimbreRequest extends AnalyzeTimbreOptions, SamplesRequest {}\n\nfunction validateAnalysisInput(\n fnName: string,\n samples: Float32Array,\n sampleRate: number,\n options: GuardedOptions = {},\n): void {\n assertSampleRate(fnName, sampleRate);\n assertSamples(fnName, samples, options.validate !== false);\n}\n\n// ============================================================================\n// Quick API (High-level Analysis)\n// ============================================================================\n\n/**\n * Detect BPM from audio samples.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @returns Detected BPM\n */\nexport function detectBpm(request: SamplesRequest): number;\nexport function detectBpm(\n samples: Float32Array,\n sampleRate?: number,\n options?: GuardedOptions,\n): number;\nexport function detectBpm(\n samples: Float32Array | SamplesRequest,\n sampleRate = 22050,\n options: GuardedOptions = {},\n): number {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('detectBpm', request.samples, request.sampleRate ?? 22050, request);\n return requireModule().detectBpm(request.samples, request.sampleRate ?? 22050);\n}\n\n/**\n * Detect musical key from audio samples.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @returns Detected key\n */\nexport function detectKey(request: DetectKeyRequest): Key;\nexport function detectKey(\n samples: Float32Array,\n sampleRate?: number,\n options?: KeyDetectionOptions,\n): Key;\nexport function detectKey(\n samples: Float32Array | DetectKeyRequest,\n sampleRate = 22050,\n options: KeyDetectionOptions = {},\n): Key {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('detectKey', request.samples, request.sampleRate ?? 22050, request);\n const result = requireModule()._detectKeyWithOptions(\n request.samples,\n request.sampleRate ?? 22050,\n request.nFft ?? 4096,\n request.hopLength ?? 512,\n request.useHpss ?? false,\n request.loudnessWeighted ?? false,\n request.highPassHz ?? 0,\n keyModeValues(request.modes),\n keyProfileValue(request.profile),\n request.genreHint ?? '',\n );\n return {\n root: result.root as PitchClass,\n mode: result.mode as Mode,\n confidence: result.confidence,\n name: result.name,\n shortName: result.shortName,\n };\n}\n\nexport function detectKeyCandidates(request: DetectKeyRequest): KeyCandidate[];\nexport function detectKeyCandidates(\n samples: Float32Array,\n sampleRate?: number,\n options?: KeyDetectionOptions,\n): KeyCandidate[];\nexport function detectKeyCandidates(\n samples: Float32Array | DetectKeyRequest,\n sampleRate = 22050,\n options: KeyDetectionOptions = {},\n): KeyCandidate[] {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput(\n 'detectKeyCandidates',\n request.samples,\n request.sampleRate ?? 22050,\n request,\n );\n // The embind value marshalling returns an array whose constructor is not this\n // realm's Array; chaining .map() onto it propagates that constructor via\n // Symbol.species, leaving a result that structuredClone (and so postMessage to\n // a Worker) rejects with \"could not be cloned\". Array.from() re-roots it as a\n // plain Array before mapping.\n const candidates = requireModule()._detectKeyCandidates(\n request.samples,\n request.sampleRate ?? 22050,\n request.nFft ?? 4096,\n request.hopLength ?? 512,\n request.useHpss ?? false,\n request.loudnessWeighted ?? false,\n request.highPassHz ?? 0,\n keyModeValues(request.modes),\n keyProfileValue(request.profile),\n request.genreHint ?? '',\n );\n return Array.from(candidates, convertKeyCandidate);\n}\n\n/**\n * Detect onset times from audio samples.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @returns Array of onset times in seconds\n */\nexport function detectOnsets(request: DetectOnsetsRequest): Float32Array;\nexport function detectOnsets(\n samples: Float32Array,\n sampleRate?: number,\n options?: OnsetDetectOptions & GuardedOptions,\n): Float32Array;\nexport function detectOnsets(\n samples: Float32Array | DetectOnsetsRequest,\n sampleRate = 22050,\n options: OnsetDetectOptions & GuardedOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('detectOnsets', request.samples, request.sampleRate ?? 22050, request);\n return requireModule().detectOnsets(request.samples, request.sampleRate ?? 22050, request);\n}\n\n/**\n * Detect beat times from audio samples.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @returns Array of beat times in seconds\n */\nexport function detectBeats(request: SamplesRequest): Float32Array;\nexport function detectBeats(\n samples: Float32Array,\n sampleRate?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function detectBeats(\n samples: Float32Array | SamplesRequest,\n sampleRate = 22050,\n options: GuardedOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('detectBeats', request.samples, request.sampleRate ?? 22050, request);\n return requireModule().detectBeats(request.samples, request.sampleRate ?? 22050);\n}\n\n/**\n * Detect downbeat times from audio samples.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @returns Array of downbeat times in seconds\n */\nexport function detectDownbeats(request: SamplesRequest): Float32Array;\nexport function detectDownbeats(\n samples: Float32Array,\n sampleRate?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function detectDownbeats(\n samples: Float32Array | SamplesRequest,\n sampleRate = 22050,\n options: GuardedOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('detectDownbeats', request.samples, request.sampleRate ?? 22050, request);\n return requireModule().detectDownbeats(request.samples, request.sampleRate ?? 22050);\n}\n\n/**\n * Detect chords from audio samples.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param options - Optional chord detection settings\n * @returns Detected chord segments\n */\nexport function detectChords(request: DetectChordsRequest): ChordAnalysisResult;\nexport function detectChords(\n samples: Float32Array,\n sampleRate?: number,\n options?: ChordDetectionOptions,\n): ChordAnalysisResult;\nexport function detectChords(\n samples: Float32Array | DetectChordsRequest,\n sampleRate = 22050,\n options: ChordDetectionOptions = {},\n): ChordAnalysisResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('detectChords', request.samples, request.sampleRate ?? 22050, request);\n const result = requireModule().detectChords(\n request.samples,\n request.sampleRate ?? 22050,\n request.minDuration ?? 0.3,\n request.smoothingWindow ?? 2.0,\n request.threshold ?? 0.5,\n request.useTriadsOnly ?? false,\n request.nFft ?? 2048,\n request.hopLength ?? 512,\n request.useBeatSync ?? true,\n request.useHmm ?? false,\n request.hmmBeamWidth ?? 24,\n request.useKeyContext ?? false,\n request.keyRoot ?? PitchClass.C,\n request.keyMode ?? Mode.Major,\n request.detectInversions ?? false,\n chordChromaMethodValue(request.chromaMethod ?? 'stft'),\n );\n return convertChordAnalysisResult(result);\n}\n\n/**\n * Functional (Roman-numeral) harmonic analysis of the detected chord\n * progression, relative to the given key. Mirrors the C-ABI\n * `sonare_chord_functional_analysis` and the Node/Python `chordFunctionalAnalysis`.\n *\n * @returns One Roman-numeral label (e.g. \"I\", \"IV\", \"V\", \"vi\") per detected chord\n */\nexport function chordFunctionalAnalysis(request: ChordFunctionalAnalysisRequest): string[];\nexport function chordFunctionalAnalysis(\n samples: Float32Array,\n keyRoot: PitchClass,\n keyMode?: Mode,\n sampleRate?: number,\n options?: ChordDetectionOptions,\n): string[];\nexport function chordFunctionalAnalysis(\n samples: Float32Array | ChordFunctionalAnalysisRequest,\n keyRoot?: PitchClass,\n keyMode?: Mode,\n sampleRate = 22050,\n options: ChordDetectionOptions = {},\n): string[] {\n const request =\n samples instanceof Float32Array\n ? { samples, keyRoot, keyMode, sampleRate, ...options }\n : samples;\n validateAnalysisInput(\n 'chordFunctionalAnalysis',\n request.samples,\n request.sampleRate ?? 22050,\n request,\n );\n return requireModule().chordFunctionalAnalysis(\n request.samples,\n request.keyRoot as PitchClass,\n request.keyMode ?? Mode.Major,\n request.sampleRate ?? 22050,\n request.minDuration ?? 0.3,\n request.smoothingWindow ?? 2.0,\n request.threshold ?? 0.5,\n request.useTriadsOnly ?? false,\n request.nFft ?? 2048,\n request.hopLength ?? 512,\n request.useBeatSync ?? true,\n request.useHmm ?? false,\n request.hmmBeamWidth ?? 24,\n request.useKeyContext ?? false,\n request.detectInversions ?? false,\n chordChromaMethodValue(request.chromaMethod ?? 'stft'),\n );\n}\n\n/**\n * Perform complete music analysis.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @returns Complete analysis result\n *\n * @remarks\n * This call is synchronous and blocks until analysis completes. Unlike the\n * Node binding (which offers `analyzeAsync` on a libuv worker thread), the\n * WASM build runs on a single thread, so there is no non-blocking variant —\n * the DSP pipeline always runs to completion on the calling thread. To keep\n * the UI responsive for long inputs, drive this from a Web Worker and use\n * {@link analyzeWithProgress} to report progress.\n */\nexport interface MusicAnalyzeOptions {\n nFft?: number;\n hopLength?: number;\n bpmMin?: number;\n bpmMax?: number;\n startBpm?: number;\n useTriadsOnly?: boolean;\n useHpss?: boolean;\n chromaHighpassHz?: number;\n useBassWeighted?: boolean;\n chromaHopMultiplier?: number;\n useChordHmm?: boolean;\n useChordKeyContext?: boolean;\n chordHmmBeamWidth?: number;\n detectChordInversions?: boolean;\n}\nexport interface MusicAnalyzeRequest extends SamplesRequest, MusicAnalyzeOptions {}\n\nexport function analyze(request: MusicAnalyzeRequest): AnalysisResult;\nexport function analyze(\n samples: Float32Array,\n sampleRate?: number,\n options?: GuardedOptions & MusicAnalyzeOptions,\n): AnalysisResult;\nexport function analyze(\n samples: Float32Array | MusicAnalyzeRequest,\n sampleRate = 22050,\n options: GuardedOptions & MusicAnalyzeOptions = {},\n): AnalysisResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('analyze', request.samples, request.sampleRate ?? 22050, request);\n const result = requireModule().analyze(request.samples, request.sampleRate ?? 22050, request);\n return convertAnalysisResult(result);\n}\n\nexport function analyzeImpulseResponse(request: AnalyzeImpulseResponseRequest): AcousticResult;\nexport function analyzeImpulseResponse(\n samples: Float32Array,\n sampleRate?: number,\n nOctaveBands?: number,\n minDecayDb?: number,\n): AcousticResult;\nexport function analyzeImpulseResponse(\n samples: Float32Array | AnalyzeImpulseResponseRequest,\n sampleRate = 48000,\n nOctaveBands = 6,\n minDecayDb?: number,\n): AcousticResult {\n const request =\n samples instanceof Float32Array ? { samples, sampleRate, nOctaveBands, minDecayDb } : samples;\n if (request.minDecayDb === null) {\n throw new TypeError('analyzeImpulseResponse: minDecayDb must be a finite number');\n }\n const resolvedMinDecayDb = request.minDecayDb === undefined ? 30.0 : request.minDecayDb;\n assertFiniteScalar('analyzeImpulseResponse', resolvedMinDecayDb, 'minDecayDb');\n if (resolvedMinDecayDb <= 0) {\n throw new RangeError('analyzeImpulseResponse: minDecayDb must be greater than zero');\n }\n validateAnalysisInput(\n 'analyzeImpulseResponse',\n request.samples,\n request.sampleRate ?? 48000,\n request,\n );\n const result: WasmAcousticResult = requireModule().analyzeImpulseResponseEx(\n request.samples,\n request.sampleRate ?? 48000,\n request.nOctaveBands ?? 6,\n resolvedMinDecayDb,\n );\n return result;\n}\n\nexport function detectAcoustic(request: DetectAcousticRequest): AcousticResult;\nexport function detectAcoustic(\n samples: Float32Array,\n sampleRate?: number,\n options?: AcousticOptions,\n): AcousticResult;\nexport function detectAcoustic(\n samples: Float32Array | DetectAcousticRequest,\n sampleRate = 48000,\n options: AcousticOptions = {},\n): AcousticResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('detectAcoustic', request.samples, request.sampleRate ?? 48000, request);\n const result: WasmAcousticResult = requireModule().detectAcoustic(\n request.samples,\n request.sampleRate ?? 48000,\n request.nOctaveBands ?? 6,\n request.nThirdOctaveSubbands ?? 24,\n request.minDecayDb ?? 30.0,\n request.noiseFloorMarginDb ?? 10.0,\n );\n return result;\n}\n\n/**\n * Synthesize a room impulse response from shoebox geometry. `hasError` is true\n * when the source/listener falls outside the room (the RIR is then empty).\n */\nexport function synthesizeRir(options: RirSynthOptions = {}): RirResult {\n const module = requireModule();\n if (typeof module.synthesizeRir !== 'function') {\n throw new Error('libsonare was built without acoustic-simulation support');\n }\n return module.synthesizeRir(options);\n}\n\n/**\n * Estimate an equivalent room (volume/dimensions/absorption/DRR) from a\n * recording or impulse response.\n */\nexport function estimateRoom(request: EstimateRoomRequest): RoomEstimateResult;\nexport function estimateRoom(\n samples: Float32Array,\n sampleRate?: number,\n options?: RoomEstimateOptions,\n): RoomEstimateResult;\nexport function estimateRoom(\n samples: Float32Array | EstimateRoomRequest,\n sampleRate = 48000,\n options: RoomEstimateOptions = {},\n): RoomEstimateResult {\n const module = requireModule();\n if (typeof module.estimateRoom !== 'function') {\n throw new Error('libsonare was built without acoustic-simulation support');\n }\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('estimateRoom', request.samples, request.sampleRate ?? 48000, request);\n return module.estimateRoom(request.samples, request.sampleRate ?? 48000, request);\n}\n\n/**\n * Morph a recording's reverberation toward a target room (creative FX, not\n * dereverberation). Returns the morphed samples (input length plus the target\n * room's reverb tail).\n */\nexport function roomMorph(request: RoomMorphRequest): Float32Array;\nexport function roomMorph(\n samples: Float32Array,\n sampleRate: number,\n options?: RoomMorphOptions,\n): Float32Array;\nexport function roomMorph(\n samples: Float32Array | RoomMorphRequest,\n sampleRate?: number,\n options: RoomMorphOptions = {},\n): Float32Array {\n const module = requireModule();\n if (typeof module.roomMorph !== 'function') {\n throw new Error('libsonare was built without acoustic-simulation support');\n }\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n validateAnalysisInput('roomMorph', request.samples, request.sampleRate, request);\n return module.roomMorph(request.samples, request.sampleRate, request);\n}\n\n/**\n * Perform complete music analysis with progress reporting.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param onProgress - Progress callback (progress: 0-1, stage: string)\n * @returns Complete analysis result\n */\nexport function analyzeWithProgress(request: AnalyzeWithProgressRequest): AnalysisResult;\nexport function analyzeWithProgress(\n samples: Float32Array,\n sampleRate: number | undefined,\n onProgress: ProgressCallback,\n): AnalysisResult;\nexport function analyzeWithProgress(\n samples: Float32Array | AnalyzeWithProgressRequest,\n sampleRate = 22050,\n onProgress?: ProgressCallback,\n): AnalysisResult {\n const request: AnalyzeWithProgressRequest =\n samples instanceof Float32Array\n ? { samples, sampleRate, onProgress: onProgress as ProgressCallback }\n : samples;\n validateAnalysisInput(\n 'analyzeWithProgress',\n request.samples,\n request.sampleRate ?? 22050,\n request,\n );\n const result = requireModule().analyzeWithProgress(\n request.samples,\n request.sampleRate ?? 22050,\n request.onProgress ?? (() => {}),\n request.cancel ?? (() => false),\n );\n return convertAnalysisResult(result);\n}\n\nexport interface BpmCandidate {\n bpm: number;\n confidence: number;\n}\n\nexport interface BpmAnalysisResult {\n bpm: number;\n confidence: number;\n candidates: BpmCandidate[];\n autocorrelation: Float32Array;\n tempogram: Float32Array;\n}\n\nexport interface RhythmAnalysisResult {\n timeSignature: { numerator: number; denominator: number; confidence: number };\n syncopation: number;\n grooveType: string;\n patternRegularity: number;\n tempoStability: number;\n bpm: number;\n beatIntervals: Float32Array;\n}\n\nexport interface DynamicsAnalysisResult {\n dynamicRangeDb: number;\n peakDb: number;\n rmsDb: number;\n crestFactor: number;\n loudnessRangeDb: number;\n isCompressed: boolean;\n /** Loudness curve timestamps (seconds), parallel to {@link loudnessRmsDb}. */\n loudnessTimes: Float32Array;\n /** Loudness curve RMS values (dB), parallel to {@link loudnessTimes}. */\n loudnessRmsDb: Float32Array;\n}\n\n/** Timbre metrics for one analysis window. Entries are ordered by time in `timbreOverTime`. */\nexport interface TimbreFrame {\n brightness: number;\n warmth: number;\n density: number;\n roughness: number;\n complexity: number;\n}\n\nexport interface TimbreAnalysisResult extends TimbreFrame {\n spectralCentroid: Float32Array;\n spectralFlatness: Float32Array;\n spectralRolloff: Float32Array;\n /** Time-varying timbre metrics, one entry per analysis window. */\n timbreOverTime: TimbreFrame[];\n}\n\n/**\n * Detailed BPM analysis (BPM, confidence, alternate candidates, autocorrelation,\n * tempogram). Matches the Node `analyzeBpm` / Python `analyze_bpm` surface.\n */\nexport function analyzeBpm(request: AnalyzeBpmRequest): BpmAnalysisResult;\nexport function analyzeBpm(\n samples: Float32Array,\n sampleRate?: number,\n options?: AnalyzeBpmOptions,\n): BpmAnalysisResult;\nexport function analyzeBpm(\n samples: Float32Array | AnalyzeBpmRequest,\n sampleRate = 22050,\n options: AnalyzeBpmOptions = {},\n): BpmAnalysisResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('analyzeBpm', request.samples, request.sampleRate ?? 22050, request);\n assertNonNegativeInteger('analyzeBpm', request.maxCandidates ?? 5, 'maxCandidates');\n return requireModule().analyzeBpm(\n request.samples,\n request.sampleRate ?? 22050,\n request.bpmMin ?? 30.0,\n request.bpmMax ?? 300.0,\n request.startBpm ?? 120.0,\n request.nFft ?? 2048,\n request.hopLength ?? 512,\n request.maxCandidates ?? 5,\n );\n}\n\n/**\n * Detailed rhythm analysis (time signature, groove, syncopation, beat intervals).\n */\nexport function analyzeRhythm(request: AnalyzeRhythmRequest): RhythmAnalysisResult;\nexport function analyzeRhythm(\n samples: Float32Array,\n sampleRate?: number,\n options?: AnalyzeRhythmOptions,\n): RhythmAnalysisResult;\nexport function analyzeRhythm(\n samples: Float32Array | AnalyzeRhythmRequest,\n sampleRate = 22050,\n options: AnalyzeRhythmOptions = {},\n): RhythmAnalysisResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('analyzeRhythm', request.samples, request.sampleRate ?? 22050, request);\n return requireModule().analyzeRhythm(\n request.samples,\n request.sampleRate ?? 22050,\n request.bpmMin ?? 60.0,\n request.bpmMax ?? 200.0,\n request.startBpm ?? 120.0,\n request.nFft ?? 2048,\n request.hopLength ?? 512,\n );\n}\n\n/**\n * Dynamics analysis (RMS, peak, crest factor, LRA, loudness curve).\n */\nexport function analyzeDynamics(request: AnalyzeDynamicsRequest): DynamicsAnalysisResult;\nexport function analyzeDynamics(\n samples: Float32Array,\n sampleRate?: number,\n options?: AnalyzeDynamicsOptions,\n): DynamicsAnalysisResult;\nexport function analyzeDynamics(\n samples: Float32Array | AnalyzeDynamicsRequest,\n sampleRate = 22050,\n options: AnalyzeDynamicsOptions = {},\n): DynamicsAnalysisResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('analyzeDynamics', request.samples, request.sampleRate ?? 22050, request);\n return requireModule().analyzeDynamics(\n request.samples,\n request.sampleRate ?? 22050,\n request.windowSec ?? 0.4,\n request.hopLength ?? 512,\n request.compressionThreshold ?? 6.0,\n );\n}\n\n/**\n * Timbre analysis (brightness/warmth/density/roughness/complexity plus spectral\n * features and per-window timbre frames).\n */\nexport function analyzeTimbre(request: AnalyzeTimbreRequest): TimbreAnalysisResult;\nexport function analyzeTimbre(\n samples: Float32Array,\n sampleRate?: number,\n options?: AnalyzeTimbreOptions,\n): TimbreAnalysisResult;\nexport function analyzeTimbre(\n samples: Float32Array | AnalyzeTimbreRequest,\n sampleRate = 22050,\n options: AnalyzeTimbreOptions = {},\n): TimbreAnalysisResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('analyzeTimbre', request.samples, request.sampleRate ?? 22050, request);\n return requireModule().analyzeTimbre(\n request.samples,\n request.sampleRate ?? 22050,\n request.nFft ?? 2048,\n request.hopLength ?? 512,\n request.nMels ?? 128,\n request.nMfcc ?? 13,\n request.windowSec ?? 0.5,\n );\n}\n\n/**\n * Whether this WASM build was compiled with FFmpeg support. Mirrors Node /\n * Python `hasFfmpegSupport`. In the published WASM binding this currently\n * always returns `false` (FFmpeg is not bundled into the .wasm), but the API\n * exists so caller code can branch on capabilities portably.\n */\nexport function hasFfmpegSupport(): boolean {\n return requireModule().hasFfmpegSupport();\n}\n","import type { VoiceChangeOptions } from './effects_mastering';\nimport {\n harmonic,\n hpss,\n masterAudio,\n mastering,\n masteringChain,\n masteringProcess,\n normalize,\n noteMove,\n noteStretch,\n percussive,\n pitchCorrectToMidi,\n pitchShift,\n timeStretch,\n voiceChange,\n} from './effects_mastering';\nimport {\n chroma,\n lufs,\n melSpectrogram,\n mfcc,\n momentaryLufs,\n nnlsChroma,\n onsetEnvelope,\n pitchPyin,\n pitchYin,\n resample,\n rmsEnergy,\n shortTermLufs,\n spectralBandwidth,\n spectralCentroid,\n spectralFlatness,\n spectralRolloff,\n stft,\n stftDb,\n trim,\n zeroCrossingRate,\n} from './features';\nimport { getSonareModule } from './module_state';\nimport type {\n AnalysisResult,\n ChordAnalysisResult,\n ChordDetectionOptions,\n ChromaResult,\n HpssResult,\n Key,\n KeyCandidate,\n KeyDetectionOptions,\n LufsResult,\n MasteringChainConfig,\n MasteringChainResult,\n MasteringOptions,\n MasteringPreset,\n MasteringProcessorParams,\n MasteringResult,\n MelSpectrogramResult,\n MfccResult,\n Mode,\n NoteStretchOptions,\n PitchClass,\n PitchResult,\n SoloProcessor,\n StftResult,\n} from './public_types';\nimport {\n analyze,\n analyzeWithProgress,\n chordFunctionalAnalysis,\n detectBeats,\n detectBpm,\n detectChords,\n detectDownbeats,\n detectKey,\n detectKeyCandidates,\n detectOnsets,\n} from './quick_analysis';\nimport type { ProgressCallback, WasmNnlsChromaResult } from './sonare.js';\nimport { validateAudioBuffer } from './validation';\n\n// ============================================================================\n// Audio Class\n// ============================================================================\n\ntype BrowserDecodeContext = Pick<BaseAudioContext, 'decodeAudioData' | 'sampleRate'>;\n\nexport interface BrowserAudioDecodeOptions {\n /**\n * AudioContext/OfflineAudioContext used for browser codec fallback. Its\n * `sampleRate` becomes the returned Audio sample rate.\n */\n audioContext?: BrowserDecodeContext;\n /**\n * Factory used when `audioContext` is omitted. `targetSampleRate` is passed\n * through so browsers that honor AudioContextOptions decode directly at that\n * rate.\n */\n createAudioContext?: (options?: AudioContextOptions) => BrowserDecodeContext;\n /**\n * Requested fallback decode rate when this helper creates the context. If the\n * browser ignores it or a context is supplied, no extra resampling is applied.\n */\n targetSampleRate?: number;\n}\n\nfunction encodedBytesToArrayBuffer(bytes: Uint8Array): ArrayBuffer {\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n return copy.buffer;\n}\n\nfunction getBrowserAudioContextFactory():\n | ((options?: AudioContextOptions) => BrowserDecodeContext)\n | undefined {\n const root = globalThis as typeof globalThis & {\n AudioContext?: new (options?: AudioContextOptions) => BaseAudioContext;\n webkitAudioContext?: new (options?: AudioContextOptions) => BaseAudioContext;\n };\n const Ctor = root.AudioContext ?? root.webkitAudioContext;\n return Ctor ? (options?: AudioContextOptions) => new Ctor(options) : undefined;\n}\n\nfunction audioBufferToMono(buffer: AudioBuffer): Float32Array {\n const samples = new Float32Array(buffer.length);\n if (buffer.numberOfChannels <= 0) {\n return samples;\n }\n if (buffer.numberOfChannels === 1) {\n samples.set(buffer.getChannelData(0));\n return samples;\n }\n for (let channel = 0; channel < buffer.numberOfChannels; channel++) {\n const data = buffer.getChannelData(channel);\n for (let i = 0; i < buffer.length; i++) {\n samples[i] += data[i] / buffer.numberOfChannels;\n }\n }\n return samples;\n}\n\nasync function closeCreatedContext(context: BrowserDecodeContext): Promise<void> {\n const maybeClosable = context as BrowserDecodeContext & { close?: () => Promise<void> };\n if (maybeClosable.close) {\n await maybeClosable.close();\n }\n}\n\n/**\n * Wrapper around audio data that exposes all analysis and feature functions as instance methods.\n *\n * @example\n * ```typescript\n * import { init, Audio } from '@libraz/libsonare';\n *\n * await init();\n *\n * const audio = Audio.fromBuffer(samples, 44100);\n * console.log('BPM:', audio.detectBpm());\n * console.log('Key:', audio.detectKey().name);\n *\n * const mel = audio.melSpectrogram();\n * ```\n */\nexport class Audio {\n private _samples: Float32Array;\n private _sampleRate: number;\n\n private constructor(samples: Float32Array, sampleRate: number) {\n this._samples = samples;\n this._sampleRate = sampleRate;\n }\n\n /**\n * Create an Audio instance from raw sample data.\n *\n * @param samples - Mono float samples.\n * @param sampleRate - Sample rate in Hz (default `48000`, matching the\n * Node/Python surfaces).\n */\n static fromBuffer(samples: Float32Array, sampleRate = 48000): Audio {\n validateAudioBuffer(samples, sampleRate);\n return new Audio(samples.slice(), sampleRate);\n }\n\n /**\n * Create an Audio instance by decoding audio bytes in memory.\n *\n * @param bytes - Encoded audio bytes such as WAV or MP3.\n */\n static fromMemory(bytes: Uint8Array): Audio {\n const decoded = getSonareModule().audioFromMemory(bytes);\n return new Audio(decoded.samples, decoded.sampleRate);\n }\n\n /**\n * Decode audio bytes with the native WASM decoder first, then fall back to the\n * browser codec stack (`AudioContext.decodeAudioData`) for formats such as\n * AAC, OGG, and FLAC when available. Browser-decoded multi-channel audio is\n * mixed down to mono to match the `Audio` wrapper contract.\n */\n static async fromMemoryWithBrowserFallback(\n bytes: Uint8Array,\n options: BrowserAudioDecodeOptions = {},\n ): Promise<Audio> {\n try {\n return Audio.fromMemory(bytes);\n } catch (nativeError) {\n let createdContext = false;\n const contextFactory = options.createAudioContext ?? getBrowserAudioContextFactory();\n const context =\n options.audioContext ??\n contextFactory?.(\n options.targetSampleRate ? { sampleRate: options.targetSampleRate } : undefined,\n );\n\n if (!context) {\n throw new Error(\n `Audio.fromMemory failed and browser decodeAudioData is unavailable: ${\n nativeError instanceof Error ? nativeError.message : String(nativeError)\n }`,\n );\n }\n\n createdContext = !options.audioContext;\n try {\n const decoded = await context.decodeAudioData(encodedBytesToArrayBuffer(bytes));\n return new Audio(audioBufferToMono(decoded), decoded.sampleRate || context.sampleRate);\n } catch (fallbackError) {\n throw new Error(\n `Audio.fromMemory failed and browser decodeAudioData fallback failed: ${\n fallbackError instanceof Error ? fallbackError.message : String(fallbackError)\n }`,\n );\n } finally {\n if (createdContext) {\n await closeCreatedContext(context);\n }\n }\n }\n }\n\n /**\n * A copy of the raw audio samples. Mirrors Node's `getData()` contract: the\n * returned array is independent of the Audio's internal buffer, so mutating\n * it (or transferring it to a Worker) does not affect subsequent facade\n * calls, which all read the internal snapshot directly.\n */\n get data(): Float32Array {\n return this._samples.slice();\n }\n\n /** Number of samples. */\n get length(): number {\n return this._samples.length;\n }\n\n /** Sample rate in Hz. */\n get sampleRate(): number {\n return this._sampleRate;\n }\n\n /** Duration in seconds. */\n get duration(): number {\n return this._samples.length / this._sampleRate;\n }\n\n // -- Analysis --\n\n detectBpm(): number {\n return detectBpm(this._samples, this._sampleRate);\n }\n\n detectKey(options: KeyDetectionOptions = {}): Key {\n return detectKey(this._samples, this._sampleRate, options);\n }\n\n detectKeyCandidates(options: KeyDetectionOptions = {}): KeyCandidate[] {\n return detectKeyCandidates(this._samples, this._sampleRate, options);\n }\n\n detectOnsets(): Float32Array {\n return detectOnsets(this._samples, this._sampleRate);\n }\n\n detectBeats(): Float32Array {\n return detectBeats(this._samples, this._sampleRate);\n }\n\n detectDownbeats(): Float32Array {\n return detectDownbeats(this._samples, this._sampleRate);\n }\n\n detectChords(options: ChordDetectionOptions = {}): ChordAnalysisResult {\n return detectChords(this._samples, this._sampleRate, options);\n }\n\n chordFunctionalAnalysis(\n keyRoot: PitchClass,\n keyMode: Mode,\n options: ChordDetectionOptions = {},\n ): string[] {\n return chordFunctionalAnalysis(this._samples, keyRoot, keyMode, this._sampleRate, options);\n }\n\n analyze(): AnalysisResult {\n return analyze(this._samples, this._sampleRate);\n }\n\n analyzeWithProgress(onProgress: ProgressCallback): AnalysisResult {\n return analyzeWithProgress(this._samples, this._sampleRate, onProgress);\n }\n\n // -- Effects --\n\n hpss(kernelHarmonic = 31, kernelPercussive = 31): HpssResult {\n return hpss(this._samples, this._sampleRate, kernelHarmonic, kernelPercussive);\n }\n\n harmonic(): Float32Array {\n return harmonic(this._samples, this._sampleRate);\n }\n\n percussive(): Float32Array {\n return percussive(this._samples, this._sampleRate);\n }\n\n timeStretch(rate: number): Float32Array {\n return timeStretch(this._samples, this._sampleRate, rate);\n }\n\n pitchShift(semitones: number): Float32Array {\n return pitchShift(this._samples, this._sampleRate, semitones);\n }\n\n pitchCorrectToMidi(currentMidi = 69.0, targetMidi = 69.0): Float32Array {\n return pitchCorrectToMidi(this._samples, this._sampleRate, currentMidi, targetMidi);\n }\n\n noteStretch(options: NoteStretchOptions = {}): Float32Array {\n return noteStretch(this._samples, this._sampleRate, options);\n }\n\n noteMove(options: import('./public_types.js').NoteMoveOptions = {}): Float32Array {\n return noteMove(this._samples, this._sampleRate, options);\n }\n\n voiceChange(options: VoiceChangeOptions = {}): Float32Array {\n return voiceChange(this._samples, this._sampleRate, options);\n }\n\n normalize(targetDb = 0.0): Float32Array {\n return normalize(this._samples, this._sampleRate, targetDb);\n }\n\n mastering(options: MasteringOptions = {}): MasteringResult {\n return mastering(this._samples, this._sampleRate, options);\n }\n\n masteringChain(\n config: MasteringChainConfig = {},\n onProgress?: ProgressCallback,\n ): MasteringChainResult {\n return masteringChain({\n samples: this._samples,\n sampleRate: this._sampleRate,\n config,\n onProgress,\n });\n }\n\n masterAudio(\n presetName: MasteringPreset = 'pop',\n overrides: MasteringChainConfig | null = null,\n onProgress?: ProgressCallback,\n ): MasteringChainResult {\n return masterAudio({\n samples: this._samples,\n sampleRate: this._sampleRate,\n preset: presetName,\n overrides: overrides ?? {},\n onProgress,\n });\n }\n\n masteringProcess(\n processorName: SoloProcessor,\n params: MasteringProcessorParams = {},\n ): MasteringResult {\n return masteringProcess(processorName, this._samples, this._sampleRate, params);\n }\n\n trim(thresholdDb = -60.0): Float32Array {\n return trim(this._samples, this._sampleRate, thresholdDb);\n }\n\n // -- Features --\n\n stft(nFft = 2048, hopLength = 512): StftResult {\n return stft(this._samples, this._sampleRate, nFft, hopLength);\n }\n\n stftDb(nFft = 2048, hopLength = 512): { nBins: number; nFrames: number; db: Float32Array } {\n return stftDb(this._samples, this._sampleRate, nFft, hopLength);\n }\n\n melSpectrogram(\n nFft = 2048,\n hopLength = 512,\n nMels = 128,\n fmin = 0,\n fmax = 0,\n htk = false,\n ): MelSpectrogramResult {\n return melSpectrogram(this._samples, this._sampleRate, nFft, hopLength, nMels, fmin, fmax, htk);\n }\n\n mfcc(\n nFft = 2048,\n hopLength = 512,\n nMels = 128,\n nMfcc = 20,\n fmin = 0,\n fmax = 0,\n htk = false,\n ): MfccResult {\n return mfcc(this._samples, this._sampleRate, nFft, hopLength, nMels, nMfcc, fmin, fmax, htk);\n }\n\n chroma(nFft = 2048, hopLength = 512): ChromaResult {\n return chroma(this._samples, this._sampleRate, nFft, hopLength);\n }\n\n nnlsChroma(): WasmNnlsChromaResult {\n return nnlsChroma(this._samples, this._sampleRate);\n }\n\n onsetEnvelope(nFft = 2048, hopLength = 512, nMels = 128): Float32Array {\n return onsetEnvelope(this._samples, this._sampleRate, nFft, hopLength, nMels);\n }\n\n lufs(): LufsResult {\n return lufs(this._samples, this._sampleRate);\n }\n\n momentaryLufs(): Float32Array {\n return momentaryLufs(this._samples, this._sampleRate);\n }\n\n shortTermLufs(): Float32Array {\n return shortTermLufs(this._samples, this._sampleRate);\n }\n\n spectralCentroid(nFft = 2048, hopLength = 512): Float32Array {\n return spectralCentroid(this._samples, this._sampleRate, nFft, hopLength);\n }\n\n spectralBandwidth(nFft = 2048, hopLength = 512): Float32Array {\n return spectralBandwidth(this._samples, this._sampleRate, nFft, hopLength);\n }\n\n spectralRolloff(nFft = 2048, hopLength = 512, rollPercent = 0.85): Float32Array {\n return spectralRolloff(this._samples, this._sampleRate, nFft, hopLength, rollPercent);\n }\n\n spectralFlatness(nFft = 2048, hopLength = 512): Float32Array {\n return spectralFlatness(this._samples, this._sampleRate, nFft, hopLength);\n }\n\n zeroCrossingRate(frameLength = 2048, hopLength = 512): Float32Array {\n return zeroCrossingRate(this._samples, this._sampleRate, frameLength, hopLength);\n }\n\n rmsEnergy(frameLength = 2048, hopLength = 512): Float32Array {\n return rmsEnergy(this._samples, this._sampleRate, frameLength, hopLength);\n }\n\n pitchYin(\n frameLength = 2048,\n hopLength = 512,\n fmin = 65.0,\n fmax = 2093.0,\n threshold = 0.1,\n fillNa = false,\n ): PitchResult {\n return pitchYin(\n this._samples,\n this._sampleRate,\n frameLength,\n hopLength,\n fmin,\n fmax,\n threshold,\n fillNa,\n );\n }\n\n pitchPyin(\n frameLength = 2048,\n hopLength = 512,\n fmin = 65.0,\n fmax = 2093.0,\n threshold = 0.1,\n fillNa = false,\n ): PitchResult {\n return pitchPyin(\n this._samples,\n this._sampleRate,\n frameLength,\n hopLength,\n fmin,\n fmax,\n threshold,\n fillNa,\n );\n }\n\n resample(targetSr: number): Float32Array {\n return resample(this._samples, this._sampleRate, targetSr);\n }\n}\n","import type { ClipPageProvider, ClipPageRequest, RealtimeEngine } from './realtime_engine';\n\nexport interface OpfsClipPageProviderOptions {\n path: string;\n numChannels: number;\n numSamples: number;\n pageFrames: number;\n dataOffsetBytes?: number;\n worker?: Worker;\n terminateWorkerOnClose?: boolean;\n /** Internal bridge hook used to mirror a supplied page into an AudioWorklet. */\n onPageSupplied?: (pageIndex: number, channels: Float32Array[]) => void;\n /** Internal bridge hook used to mirror an eviction into an AudioWorklet. */\n onPageCleared?: (pageIndex: number) => void;\n /** Internal bridge hook called after the local provider is destroyed. */\n onClose?: () => void;\n}\n\nexport interface OpfsClipPageProviderBinding {\n provider: ClipPageProvider;\n supplyPage(pageIndex: number): Promise<boolean>;\n supplyRequest(request: ClipPageRequest): Promise<boolean>;\n /** Evict one resident page from every configured consumer. */\n clearPage?(pageIndex: number): void;\n close(): void;\n}\n\ninterface PageResponse {\n type: 'sonare:clip-page';\n requestId: number;\n pageIndex: number;\n ok: boolean;\n frames?: number;\n channels?: Float32Array[];\n channelBuffers?: ArrayBufferLike[];\n error?: string;\n}\n\nexport const opfsClipPageWorkerSource = `\nconst sonareClipPageReadQueues = new Map();\n\nfunction sonareEnqueueClipPageRead(key, task) {\n const previous = sonareClipPageReadQueues.get(key) || Promise.resolve();\n const next = previous.catch(() => undefined).then(task);\n const queued = next.finally(() => {\n if (sonareClipPageReadQueues.get(key) === queued) {\n sonareClipPageReadQueues.delete(key);\n }\n });\n sonareClipPageReadQueues.set(key, queued);\n return next;\n}\n\nself.onmessage = async (event) => {\n const message = event.data;\n if (!message || message.type !== 'sonare:read-clip-page') return;\n const { requestId, path, pageIndex, numChannels, numSamples, pageFrames, dataOffsetBytes = 0 } = message;\n await sonareEnqueueClipPageRead(String(path), async () => {\n try {\n if (pageIndex < 0) {\n self.postMessage({ type: 'sonare:clip-page', requestId, pageIndex, ok: false });\n return;\n }\n const startFrame = pageIndex * pageFrames;\n if (startFrame >= numSamples) {\n self.postMessage({ type: 'sonare:clip-page', requestId, pageIndex, ok: false });\n return;\n }\n const root = await self.navigator.storage.getDirectory();\n let dir = root;\n const parts = String(path).split('/').filter(Boolean);\n for (let i = 0; i < parts.length - 1; ++i) {\n dir = await dir.getDirectoryHandle(parts[i]);\n }\n const fileHandle = await dir.getFileHandle(parts[parts.length - 1]);\n const access = await fileHandle.createSyncAccessHandle();\n try {\n const frames = Math.min(pageFrames, numSamples - startFrame);\n const frameBytes = numChannels * 4;\n const bytes = new Uint8Array(frames * frameBytes);\n let bytesReadTotal = 0;\n const readOffset = dataOffsetBytes + startFrame * frameBytes;\n while (bytesReadTotal < bytes.byteLength) {\n const bytesRead = access.read(bytes.subarray(bytesReadTotal), {\n at: readOffset + bytesReadTotal,\n });\n if (bytesRead <= 0) {\n break;\n }\n bytesReadTotal += bytesRead;\n }\n if (bytesReadTotal !== bytes.byteLength || bytesReadTotal % frameBytes !== 0) {\n self.postMessage({ type: 'sonare:clip-page', requestId, pageIndex, ok: false });\n return;\n }\n const framesRead = bytesReadTotal / frameBytes;\n const view = new DataView(bytes.buffer, 0, framesRead * frameBytes);\n const channelBuffers = Array.from({ length: numChannels }, () => new ArrayBuffer(framesRead * 4));\n for (let ch = 0; ch < numChannels; ++ch) {\n const channel = new Float32Array(channelBuffers[ch]);\n for (let frame = 0; frame < framesRead; ++frame) {\n channel[frame] = view.getFloat32((frame * numChannels + ch) * 4, true);\n }\n }\n self.postMessage(\n { type: 'sonare:clip-page', requestId, pageIndex, ok: true, frames: framesRead, channelBuffers },\n channelBuffers,\n );\n } finally {\n access.close();\n }\n } catch (error) {\n self.postMessage({\n type: 'sonare:clip-page',\n requestId,\n pageIndex,\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n });\n};\n`;\n\nexport function createOpfsClipPageWorker(): Worker {\n const blob = new Blob([opfsClipPageWorkerSource], { type: 'text/javascript' });\n const url = URL.createObjectURL(blob);\n try {\n return new Worker(url);\n } finally {\n // Worker construction retains the script URL internally; keeping this\n // object URL alive after construction leaks one browser registration per\n // attach/close cycle.\n URL.revokeObjectURL(url);\n }\n}\n\nexport function createOpfsClipPageProvider(\n engine: RealtimeEngine,\n options: OpfsClipPageProviderOptions,\n): OpfsClipPageProviderBinding {\n if (options.numChannels <= 0 || options.numSamples <= 0 || options.pageFrames <= 0) {\n throw new Error('numChannels, numSamples, and pageFrames must be positive');\n }\n const provider = engine.createClipPageProvider(\n options.numChannels,\n options.numSamples,\n options.pageFrames,\n );\n const worker = options.worker ?? createOpfsClipPageWorker();\n const ownsWorker = options.worker === undefined || options.terminateWorkerOnClose === true;\n let nextRequestId = 1;\n let closed = false;\n let readQueue: Promise<void> = Promise.resolve();\n const pending = new Map<\n number,\n { resolve: (value: boolean) => void; reject: (reason: unknown) => void }\n >();\n\n const onMessage = (event: MessageEvent<PageResponse>) => {\n const response = event.data;\n if (response?.type !== 'sonare:clip-page') {\n return;\n }\n const entry = pending.get(response.requestId);\n if (!entry) {\n return;\n }\n pending.delete(response.requestId);\n if (!response.ok) {\n entry.resolve(false);\n return;\n }\n const channels =\n response.channels ??\n response.channelBuffers?.map(\n (buffer) => new Float32Array(buffer, 0, response.frames ?? buffer.byteLength / 4),\n );\n if (!channels || channels.length === 0) {\n entry.resolve(false);\n return;\n }\n try {\n provider.supply(response.pageIndex, channels);\n options.onPageSupplied?.(response.pageIndex, channels);\n } catch {\n entry.resolve(false);\n return;\n }\n entry.resolve(true);\n };\n worker.addEventListener('message', onMessage as EventListener);\n\n const supplyPage = (pageIndex: number): Promise<boolean> => {\n if (closed) {\n return Promise.reject(new Error('OpfsClipPageProvider is closed'));\n }\n const requestId = nextRequestId++;\n const promise = new Promise<boolean>((resolve, reject) => {\n pending.set(requestId, { resolve, reject });\n });\n readQueue = readQueue\n .catch(() => undefined)\n .then(() => {\n if (closed) {\n const entry = pending.get(requestId);\n pending.delete(requestId);\n entry?.reject(new Error('OpfsClipPageProvider is closed'));\n return;\n }\n worker.postMessage({\n type: 'sonare:read-clip-page',\n requestId,\n path: options.path,\n pageIndex,\n numChannels: options.numChannels,\n numSamples: options.numSamples,\n pageFrames: options.pageFrames,\n dataOffsetBytes: options.dataOffsetBytes ?? 0,\n });\n return promise.then(\n () => undefined,\n () => undefined,\n );\n });\n readQueue.catch(() => {\n // The per-request promise carries the user-visible failure.\n });\n return promise;\n };\n\n return {\n provider,\n supplyPage,\n supplyRequest(request: ClipPageRequest) {\n return supplyPage(Math.floor(request.sample / options.pageFrames));\n },\n clearPage(pageIndex: number) {\n if (closed) {\n return;\n }\n provider.clear(pageIndex);\n options.onPageCleared?.(pageIndex);\n },\n close() {\n if (closed) {\n return;\n }\n closed = true;\n worker.removeEventListener('message', onMessage as EventListener);\n for (const entry of pending.values()) {\n entry.reject(new Error('OpfsClipPageProvider is closed'));\n }\n pending.clear();\n provider.destroy();\n options.onClose?.();\n if (ownsWorker) {\n worker.terminate();\n }\n },\n };\n}\n","import {\n createOpfsClipPageProvider,\n type OpfsClipPageProviderBinding,\n type OpfsClipPageProviderOptions,\n} from './opfs_clip_pages';\nimport type { ClipPageProvider, ClipPageRequest, RealtimeEngine } from './realtime_engine';\n\n/**\n * Minimal engine surface the streamer drives. {@link RealtimeEngine} satisfies\n * this structurally; tests can supply a lightweight stand-in.\n */\nexport interface ClipPageStreamerEngine {\n /** Drain one pending audio-thread page-miss request, or `null` when empty. */\n popClipPageRequest(): ClipPageStreamerRequest | null;\n}\n\n/**\n * A page miss reported by either a direct engine (`sample`) or the worklet\n * bridge (`pageIndex`). Exactly one position form is required.\n */\nexport interface ClipPageStreamerRequest {\n clipId: number;\n sample?: number;\n pageIndex?: number;\n}\n\n/** A paged clip the streamer keeps fed from its backing store. */\nexport interface ClipPageStreamSource {\n /** Clip schedule id passed to `setClips` (matches {@link ClipPageRequest.clipId}). */\n clipId: number;\n /** OPFS-backed page provider binding for this clip. */\n binding: OpfsClipPageProviderBinding;\n /** Page size in frames (must equal the provider's `pageFrames`). */\n pageFrames: number;\n /** Total sample count of the clip source. */\n numSamples: number;\n}\n\nexport interface ClipPageStreamerOptions {\n /**\n * Pages to prefetch ahead of the page a miss was reported for. Larger values\n * hide fetch latency at the cost of more resident memory. Default 2.\n */\n readAheadPages?: number;\n /**\n * Pages to retain behind the playback frontier before eviction, so a small\n * backward seek does not immediately miss. Default 1.\n */\n retainBehindPages?: number;\n /**\n * Upper bound on requests drained per {@link ClipPageStreamer.pump} call, so a\n * burst of misses cannot spin unbounded. Default 256.\n */\n maxRequestsPerPump?: number;\n}\n\ninterface SourceState {\n source: ClipPageStreamSource;\n lastPage: number;\n /** Playback-window generation; advanced on reset or backward discontinuity. */\n generation: number;\n /** Most recently serviced playback frontier, or null before the first miss. */\n lastFrontier: number | null;\n /** Resident page -> generation, so in-flight stale fetches cannot alias. */\n resident: Map<number, number>;\n}\n\n/**\n * Keeps OPFS-paged clips fed within a bounded sliding window around the live\n * playback position, so a multitrack arrangement never holds its full PCM in\n * WASM memory.\n *\n * The audio thread reports a page miss whenever the {@link ClipPlayer} reads a\n * sample whose page is not resident. {@link pump} drains those requests, fetches\n * the missing page plus a read-ahead window from each clip's backing store, and\n * evicts pages that fall outside the window via the provider's `clear`. The\n * resident set per clip is therefore bounded to\n * `retainBehindPages + readAheadPages + 1` pages regardless of clip length.\n *\n * Call {@link pump} on a cadence that keeps up with playback — typically once\n * per animation frame or per worklet control tick on the main/control thread\n * (never the audio thread; fetches are asynchronous).\n */\nexport class ClipPageStreamer {\n private readonly engine: ClipPageStreamerEngine;\n private readonly readAheadPages: number;\n private readonly retainBehindPages: number;\n private readonly maxRequestsPerPump: number;\n private readonly sources = new Map<number, SourceState>();\n private closed = false;\n\n constructor(engine: ClipPageStreamerEngine, options: ClipPageStreamerOptions = {}) {\n this.engine = engine;\n this.readAheadPages = Math.max(0, Math.floor(options.readAheadPages ?? 2));\n this.retainBehindPages = Math.max(0, Math.floor(options.retainBehindPages ?? 1));\n this.maxRequestsPerPump = Math.max(1, Math.floor(options.maxRequestsPerPump ?? 256));\n }\n\n /**\n * Register a paged clip. Pages already supplied to the provider before\n * registration (for example a primed first page) should be passed in\n * `initialResidentPages` so they participate in eviction.\n */\n addSource(source: ClipPageStreamSource, initialResidentPages: Iterable<number> = []): void {\n if (source.pageFrames <= 0 || source.numSamples <= 0) {\n throw new Error('pageFrames and numSamples must be positive');\n }\n const lastPage = Math.ceil(source.numSamples / source.pageFrames) - 1;\n const previous = this.sources.get(source.clipId);\n if (previous) {\n this.resetState(previous);\n }\n this.sources.set(source.clipId, {\n source,\n lastPage,\n generation: 0,\n lastFrontier: null,\n resident: new Map(Array.from(initialResidentPages, (page) => [page, 0])),\n });\n }\n\n /** Stop tracking a clip. Does not close its binding (the caller owns that). */\n removeSource(clipId: number): void {\n const state = this.sources.get(clipId);\n if (state) {\n this.resetState(state);\n }\n this.sources.delete(clipId);\n }\n\n /**\n * Explicitly start a new playback generation after a host seek/loop. Resident\n * pages are evicted and any older in-flight fetch is cleared when it settles.\n * The next miss establishes the new bounded window.\n */\n resetSource(clipId: number): void {\n const state = this.sources.get(clipId);\n if (state) {\n this.resetState(state);\n }\n }\n\n /**\n * Drain pending page-miss requests, fetch the missing pages plus their\n * read-ahead window, and evict out-of-window pages. Resolves once this round's\n * fetches settle. Concurrent fetches are serialized inside each binding.\n */\n async pump(): Promise<void> {\n if (this.closed) {\n return;\n }\n // Collapse this round's misses to the latest observed frontier per clip.\n // Queue order reflects playback order, so a backward seek/loop request that\n // follows a stale high-page miss must win even though its page index is\n // smaller. Multiple channel misses still collapse to one service window.\n const frontiers = new Map<number, number>();\n for (let drained = 0; drained < this.maxRequestsPerPump; ++drained) {\n const request = this.engine.popClipPageRequest();\n if (!request) {\n break;\n }\n const state = this.sources.get(request.clipId);\n if (!state) {\n continue;\n }\n const page =\n request.pageIndex !== undefined\n ? request.pageIndex\n : Math.floor((request.sample ?? Number.NaN) / state.source.pageFrames);\n if (!Number.isInteger(page) || page < 0 || page > state.lastPage) {\n continue;\n }\n frontiers.set(request.clipId, page);\n }\n\n const fetches: Promise<unknown>[] = [];\n for (const [clipId, frontier] of frontiers) {\n const state = this.sources.get(clipId);\n if (!state) {\n continue;\n }\n fetches.push(...this.serviceFrontier(state, frontier));\n }\n await Promise.all(fetches);\n }\n\n /** Close every registered clip's binding and stop tracking. */\n close(): void {\n if (this.closed) {\n return;\n }\n this.closed = true;\n for (const state of this.sources.values()) {\n this.resetState(state);\n state.source.binding.close();\n }\n this.sources.clear();\n }\n\n private serviceFrontier(state: SourceState, frontier: number): Promise<unknown>[] {\n // A lower frontier after a previously serviced high page is a seek/loop\n // discontinuity. Advance generation before scheduling its new window so an\n // older asynchronous fetch can never become resident in the new window.\n if (state.lastFrontier !== null && frontier < state.lastFrontier) {\n this.resetState(state);\n }\n state.lastFrontier = frontier;\n const generation = state.generation;\n const low = Math.max(0, frontier - this.retainBehindPages);\n const high = Math.min(state.lastPage, frontier + this.readAheadPages);\n\n // Evict pages outside the window first so a burst of fetches never exceeds\n // the bound by transiently holding old pages alongside new ones.\n for (const page of state.resident.keys()) {\n if (page < low || page > high) {\n this.clearPage(state, page);\n state.resident.delete(page);\n }\n }\n\n const fetches: Promise<unknown>[] = [];\n for (let page = low; page <= high; ++page) {\n if (state.resident.get(page) === generation) {\n continue;\n }\n // Mark resident eagerly so the same page is not fetched twice across\n // overlapping windows; drop it again if the fetch reports a miss.\n state.resident.set(page, generation);\n const pageIndex = page;\n fetches.push(\n state.source.binding.supplyPage(pageIndex).then(\n (ok) => {\n if (state.generation !== generation) {\n // The fetch crossed a seek/reset boundary. supplyPage may have\n // installed it after resetState's clear pass, so clear it again.\n this.clearPage(state, pageIndex);\n } else if (!ok && state.resident.get(pageIndex) === generation) {\n state.resident.delete(pageIndex);\n }\n return ok;\n },\n (error) => {\n if (state.resident.get(pageIndex) === generation) {\n state.resident.delete(pageIndex);\n }\n throw error;\n },\n ),\n );\n }\n return fetches;\n }\n\n private resetState(state: SourceState): void {\n state.generation += 1;\n state.lastFrontier = null;\n for (const page of state.resident.keys()) {\n this.clearPage(state, page);\n }\n state.resident.clear();\n }\n\n private clearPage(state: SourceState, pageIndex: number): void {\n // `clearPage` mirrors eviction into the AudioWorklet. Keep the older\n // provider-only form working for direct-engine callers and test doubles.\n if (state.source.binding.clearPage) {\n state.source.binding.clearPage(pageIndex);\n } else {\n state.source.binding.provider.clear(pageIndex);\n }\n }\n}\n\nexport interface OpfsClipStreamOptions extends OpfsClipPageProviderOptions {\n /** Clip schedule id used in `setClips` (matches the page-miss request clipId). */\n clipId: number;\n /**\n * Leading pages fetched synchronously before returning, so playback can start\n * without an immediate miss. Default 1.\n */\n primePages?: number;\n}\n\nexport interface OpfsClipStream {\n binding: OpfsClipPageProviderBinding;\n /** Pass as `addClip`'s buffer argument to schedule the streaming clip. */\n provider: ClipPageProvider;\n}\n\n/** Structural seam implemented by the AudioWorklet-backed `SonareEngine`. */\nexport interface WorkletOpfsClipStreamHost {\n attachOpfsClipStream(options: OpfsClipStreamOptions): Promise<OpfsClipStream>;\n}\n\n/**\n * One-call wiring of an OPFS-backed streaming clip: creates the page provider,\n * primes the leading pages, and registers it with `streamer` so later misses are\n * serviced within the bounded window. Returns the binding (for `close`) and the\n * provider to schedule via `addClip(trackId, provider, startPpq, { id: clipId })`.\n *\n * @param streamer Shared streamer pumped on the control thread.\n * @param engine Engine the provider is created on (the same one `streamer` drives).\n * @param options Provider options plus `clipId` and optional `primePages`.\n */\nexport function attachOpfsClipStream(\n streamer: ClipPageStreamer,\n engine: RealtimeEngine,\n options: OpfsClipStreamOptions,\n): Promise<OpfsClipStream>;\n/**\n * Worklet overload: delegates to `SonareEngine.attachOpfsClipStream`, which\n * creates the remote provider and drives this same sliding-window policy from\n * worklet page-miss messages.\n */\nexport function attachOpfsClipStream(\n engine: WorkletOpfsClipStreamHost,\n options: OpfsClipStreamOptions,\n): Promise<OpfsClipStream>;\nexport async function attachOpfsClipStream(\n streamerOrEngine: ClipPageStreamer | WorkletOpfsClipStreamHost,\n engineOrOptions: RealtimeEngine | OpfsClipStreamOptions,\n maybeOptions?: OpfsClipStreamOptions,\n): Promise<OpfsClipStream> {\n if (!(streamerOrEngine instanceof ClipPageStreamer)) {\n return streamerOrEngine.attachOpfsClipStream(engineOrOptions as OpfsClipStreamOptions);\n }\n const streamer = streamerOrEngine;\n const engine = engineOrOptions as RealtimeEngine;\n const options = maybeOptions;\n if (!options) {\n throw new Error('attachOpfsClipStream requires options.');\n }\n const { clipId, primePages = 1, ...providerOptions } = options;\n const binding = createOpfsClipPageProvider(engine, providerOptions);\n const lastPage = Math.ceil(providerOptions.numSamples / providerOptions.pageFrames) - 1;\n const primed: number[] = [];\n for (let page = 0; page < primePages && page <= lastPage; ++page) {\n if (await binding.supplyPage(page)) {\n primed.push(page);\n }\n }\n streamer.addSource(\n {\n clipId,\n binding,\n pageFrames: providerOptions.pageFrames,\n numSamples: providerOptions.numSamples,\n },\n primed,\n );\n return { binding, provider: binding.provider };\n}\n","import type { SonareRealtimeEngineNode } from './worklet';\n\nexport interface BindMicrophoneInputOptions extends MediaStreamConstraints {\n stream?: MediaStream;\n stopTracksOnClose?: boolean;\n}\n\nexport interface MicrophoneInputBinding {\n stream: MediaStream;\n source: MediaStreamAudioSourceNode;\n close(): void;\n}\n\nexport async function bindMicrophoneInput(\n context: AudioContext,\n engine: SonareRealtimeEngineNode | AudioWorkletNode,\n options: BindMicrophoneInputOptions = {},\n): Promise<MicrophoneInputBinding> {\n const { stream: providedStream, stopTracksOnClose = true, ...constraints } = options;\n const stream =\n providedStream ??\n (await navigator.mediaDevices.getUserMedia({\n ...constraints,\n audio: constraints.audio ?? true,\n video: constraints.video ?? false,\n }));\n const source = context.createMediaStreamSource(stream);\n const node = 'node' in engine ? engine.node : engine;\n source.connect(node);\n let closed = false;\n return {\n stream,\n source,\n close() {\n if (closed) {\n return;\n }\n closed = true;\n source.disconnect();\n if (stopTracksOnClose) {\n for (const track of stream.getAudioTracks()) {\n track.stop();\n }\n }\n },\n };\n}\n","import { ErrorCode, SonareError } from './errors';\nimport { getSonareModule } from './module_state';\nimport type { ValidateOptions } from './validation';\nimport { assertSamples } from './validation';\n\n/**\n * Validates a true-peak oversample factor: `0` (meaning \"use the default 4\") or\n * a power of two in `[1, 16]`. The native layer applies the same `0 -> 4`\n * normalization (see `metering::true_peak_db`), so the raw factor can be passed\n * through unchanged after this check. Kept module-local (not exported) so it does\n * not surface as a WASM-only symbol with no C-API counterpart.\n */\nfunction assertOversampleFactor(fnName: string, factor: number): void {\n const normalized = factor === 0 ? 4 : factor;\n if (\n !Number.isInteger(normalized) ||\n normalized < 1 ||\n normalized > 16 ||\n (normalized & (normalized - 1)) !== 0\n ) {\n throw new SonareError(\n ErrorCode.InvalidParameter,\n 'InvalidParameter',\n `${fnName}: oversampleFactor must be 0 or a power of two from 1 to 16`,\n );\n }\n}\n\n// ============================================================================\n// Metering — basic / true-peak / clipping / dynamic range\n// ============================================================================\n\n/** One contiguous run of clipped samples reported by `meteringDetectClipping`. */\nexport interface ClippingRegion {\n startSample: number;\n endSample: number;\n length: number;\n peak: number;\n}\n\n/** Aggregated clipping report. */\nexport interface ClippingReport {\n clippedSamples: number;\n clippingRatio: number;\n maxClippedPeak: number;\n regions: ClippingRegion[];\n}\n\n/** Sliding-window dynamic range report. */\nexport interface DynamicRangeReport {\n dynamicRangeDb: number;\n lowPercentileDb: number;\n highPercentileDb: number;\n windowRmsDb: Float32Array;\n}\n\n/** Options for {@link meteringDetectClipping}. All fields are optional. */\nexport interface MeteringDetectClippingOptions extends ValidateOptions {\n /** Linear absolute threshold. Default 0.999. */\n threshold?: number;\n /** Minimum run length to report. Default 1. */\n minRegionSamples?: number;\n}\n\n/** Options for {@link meteringDynamicRange}. All fields are optional. */\nexport interface MeteringDynamicRangeOptions extends ValidateOptions {\n /** Window length in seconds (0 = library default, 3 s). Default 0. */\n windowSec?: number;\n /** Hop length in seconds (0 = library default, 1 s). Default 0. */\n hopSec?: number;\n /** Low percentile in [0,1] (negative = library default, 0.10). Default -1. */\n lowPercentile?: number;\n /** High percentile in [0,1] (negative = library default, 0.95). Default -1. */\n highPercentile?: number;\n}\n\n/** Canonical request form for single-channel meter readings. */\nexport interface MeteringSamplesRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\n/** Canonical request form for true-peak analysis. */\nexport interface MeteringTruePeakRequest extends MeteringSamplesRequest {\n oversampleFactor?: number;\n}\n\n/** Canonical request form for clipping analysis. */\nexport interface MeteringDetectClippingRequest extends MeteringDetectClippingOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\n/** Canonical request form for dynamic-range analysis. */\nexport interface MeteringDynamicRangeRequest extends MeteringDynamicRangeOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\nfunction requireModule() {\n return getSonareModule();\n}\n\nexport function meteringPeakDb(request: MeteringSamplesRequest): number;\nexport function meteringPeakDb(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringPeakDb(\n samples: Float32Array | MeteringSamplesRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): number {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('meteringPeakDb', request.samples, request.validate !== false);\n return requireModule().meteringPeakDb(request.samples, request.sampleRate ?? 22050);\n}\n\nexport function meteringRmsDb(request: MeteringSamplesRequest): number;\nexport function meteringRmsDb(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringRmsDb(\n samples: Float32Array | MeteringSamplesRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): number {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('meteringRmsDb', request.samples, request.validate !== false);\n return requireModule().meteringRmsDb(request.samples, request.sampleRate ?? 22050);\n}\n\nexport interface MeteringSilenceRatioRequest extends MeteringSamplesRequest {\n thresholdDb?: number;\n frameLength?: number;\n hopLength?: number;\n}\n\nexport function meteringSilenceRatio(request: MeteringSilenceRatioRequest): number;\nexport function meteringSilenceRatio(\n samples: Float32Array,\n sampleRate?: number,\n thresholdDb?: number,\n frameLength?: number,\n hopLength?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringSilenceRatio(\n samples: Float32Array | MeteringSilenceRatioRequest,\n sampleRate = 22050,\n thresholdDb = -45,\n frameLength = 1024,\n hopLength = 256,\n options: ValidateOptions = {},\n): number {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate, thresholdDb, frameLength, hopLength, ...options }\n : samples;\n assertSamples('meteringSilenceRatio', request.samples, request.validate !== false);\n return requireModule().meteringSilenceRatio(\n request.samples,\n request.sampleRate ?? 22050,\n request.thresholdDb ?? -45,\n request.frameLength ?? 1024,\n request.hopLength ?? 256,\n );\n}\n\nexport function meteringCrestFactorDb(request: MeteringSamplesRequest): number;\nexport function meteringCrestFactorDb(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringCrestFactorDb(\n samples: Float32Array | MeteringSamplesRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): number {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('meteringCrestFactorDb', request.samples, request.validate !== false);\n return requireModule().meteringCrestFactorDb(request.samples, request.sampleRate ?? 22050);\n}\n\n/**\n * Crest factor in dB across both channels of a stereo pair.\n *\n * Takes the peak across both channels and the RMS over both together. An\n * out-of-phase pair cancels in the `0.5 * (left + right)` downmix\n * {@link meteringCrestFactorDb} would need, which understates its RMS and so\n * overstates the crest factor.\n */\nexport function meteringCrestFactorDbStereo(request: MeteringStereoRequest): number {\n assertSamples('meteringCrestFactorDbStereo', request.left, request.validate !== false);\n assertSamples('meteringCrestFactorDbStereo', request.right, request.validate !== false);\n return requireModule().meteringCrestFactorDbStereo(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n );\n}\n\nexport function meteringDcOffset(request: MeteringSamplesRequest): number;\nexport function meteringDcOffset(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringDcOffset(\n samples: Float32Array | MeteringSamplesRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): number {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('meteringDcOffset', request.samples, request.validate !== false);\n return requireModule().meteringDcOffset(request.samples, request.sampleRate ?? 22050);\n}\n\n/**\n * Inter-sample (true) peak in dBFS. `oversampleFactor` must be a power of two\n * in [1, 16]; pass 0 to use the library default (4).\n */\nexport function meteringTruePeakDb(request: MeteringTruePeakRequest): number;\nexport function meteringTruePeakDb(\n samples: Float32Array,\n sampleRate?: number,\n oversampleFactor?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringTruePeakDb(\n samples: Float32Array | MeteringTruePeakRequest,\n sampleRate = 22050,\n oversampleFactor = 4,\n options: ValidateOptions = {},\n): number {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate, oversampleFactor, ...options }\n : samples;\n assertSamples('meteringTruePeakDb', request.samples, request.validate !== false);\n const factor = request.oversampleFactor ?? 4;\n assertOversampleFactor('meteringTruePeakDb', factor);\n return requireModule().meteringTruePeakDb(request.samples, request.sampleRate ?? 22050, factor);\n}\n\n/**\n * Detect contiguous runs of clipped samples.\n *\n * @param threshold Linear absolute threshold (default 0.999).\n * @param minRegionSamples Minimum run length to report (default 1).\n */\nexport function meteringDetectClipping(request: MeteringDetectClippingRequest): ClippingReport;\nexport function meteringDetectClipping(\n samples: Float32Array,\n sampleRate?: number,\n options?: MeteringDetectClippingOptions,\n): ClippingReport;\nexport function meteringDetectClipping(\n samples: Float32Array | MeteringDetectClippingRequest,\n sampleRate = 22050,\n options: MeteringDetectClippingOptions = {},\n): ClippingReport {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('meteringDetectClipping', request.samples, request.validate !== false);\n const minRegionSamples = request.minRegionSamples ?? 1;\n if (!Number.isInteger(minRegionSamples) || minRegionSamples < 0) {\n throw new RangeError('meteringDetectClipping: minRegionSamples must be a non-negative integer');\n }\n return requireModule().meteringDetectClipping(\n request.samples,\n request.sampleRate ?? 22050,\n request.threshold ?? 0.999,\n minRegionSamples,\n );\n}\n\n/**\n * Sliding-window dynamic range for mono audio. Pass 0 for window/hop to use the library\n * default (window=3 s, hop=1 s). The percentiles use a NEGATIVE sentinel for\n * \"use the library default\" (low=0.10, high=0.95) because 0 is a literal 0th\n * percentile; omitted percentiles therefore default to -1.\n */\nexport function meteringDynamicRange(request: MeteringDynamicRangeRequest): DynamicRangeReport;\nexport function meteringDynamicRange(\n samples: Float32Array,\n sampleRate?: number,\n options?: MeteringDynamicRangeOptions,\n): DynamicRangeReport;\nexport function meteringDynamicRange(\n samples: Float32Array | MeteringDynamicRangeRequest,\n sampleRate = 22050,\n options: MeteringDynamicRangeOptions = {},\n): DynamicRangeReport {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('meteringDynamicRange', request.samples, request.validate !== false);\n return requireModule().meteringDynamicRange(\n request.samples,\n request.sampleRate ?? 22050,\n request.windowSec ?? 0,\n request.hopSec ?? 0,\n request.lowPercentile ?? -1,\n request.highPercentile ?? -1,\n );\n}\n\n// ============================================================================\n// Metering — stereo / phase-scope / spectrum\n// ============================================================================\n\n/** Mid/side vectorscope point series for a (left, right) stereo pair. */\nexport interface VectorscopeReport {\n mid: Float32Array;\n side: Float32Array;\n}\n\n/** Phase-scope (Lissajous) point series plus summary stats. */\nexport interface PhaseScopeReport {\n mid: Float32Array;\n side: Float32Array;\n radius: Float32Array;\n angleRad: Float32Array;\n correlation: number;\n averageAbsAngleRad: number;\n maxRadius: number;\n}\n\n/** Options for `meteringSpectrum`. */\nexport interface SpectrumOptions {\n /** FFT size. Pass 0 / omit for the library default (2048). */\n nFft?: number;\n /** Apply fractional-octave smoothing to magnitude. */\n applyOctaveSmoothing?: boolean;\n /** Smoothing fraction (e.g. 3 = 1/3-octave). 0 / omit = library default (3). */\n octaveFraction?: number;\n /** Linear reference for the dB conversion. 0 / omit = 1.0. */\n dbRef?: number;\n /** Linear floor used to avoid log(0). 0 / omit = library default. */\n dbAmin?: number;\n}\n\n/** Single-frame magnitude / power / dB spectrum returned by `meteringSpectrum`. */\nexport interface SpectrumReport {\n frequencies: Float32Array;\n magnitude: Float32Array;\n power: Float32Array;\n db: Float32Array;\n nFft: number;\n sampleRate: number;\n}\n\n/** Options for {@link waveformPeaks}. All fields are optional. */\nexport interface WaveformPeaksOptions extends ValidateOptions {\n /** Bucket width in frames. Default 512. */\n samplesPerBucket?: number;\n}\n\n/** Options for {@link waveformPeakPyramid}. All fields are optional. */\nexport interface WaveformPeakPyramidOptions extends ValidateOptions {\n /** Bucket widths in frames, one per zoom level. Default [512, 1024, 2048, 4096]. */\n samplesPerBucketLevels?: number[];\n}\n\n/** Canonical request form for stereo meter readings. */\nexport interface MeteringStereoRequest extends ValidateOptions {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n}\n\n/** Canonical request form for display-decimated stereo scopes. */\nexport interface MeteringStereoDecimatedRequest extends MeteringStereoRequest {\n maxPoints?: number;\n}\n\n/** Options for the scope functions (mirrors the Node `ScopeOptions`). */\nexport interface ScopeOptions extends ValidateOptions {\n /**\n * Upper bound on the returned point count. Omit / `0` (or a value `>= length`)\n * yields one point per input sample; otherwise the point cloud is\n * deterministically decimated to at most `maxPoints` points for display.\n */\n maxPoints?: number;\n}\n\n/** Canonical request form for whole-signal spectrum analysis. */\nexport interface MeteringSpectrumRequest extends SpectrumOptions, ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\n/** Canonical request form for a single spectrum frame. */\nexport interface MeteringSpectrumFrameRequest extends MeteringSpectrumRequest {\n frameOffset?: number;\n}\n\n/** Canonical request form for waveform bucket generation. */\nexport interface WaveformPeaksRequest extends WaveformPeaksOptions {\n samples: Float32Array;\n channels: number;\n}\n\n/** Canonical request form for multi-resolution waveform bucket generation. */\nexport interface WaveformPeakPyramidRequest extends WaveformPeakPyramidOptions {\n samples: Float32Array;\n channels: number;\n}\n\n/** Per-channel min/max waveform buckets. Arrays are channel-major. */\nexport interface WaveformPeaksReport {\n min: Float32Array;\n max: Float32Array;\n channels: number;\n bucketCount: number;\n samplesPerBucket: number;\n}\n\n/** Uncentered correlation (cosine similarity) in [-1, 1] between equal-length channels. */\nexport function meteringStereoCorrelation(request: MeteringStereoRequest): number;\nexport function meteringStereoCorrelation(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringStereoCorrelation(\n left: Float32Array | MeteringStereoRequest,\n right?: Float32Array,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): number {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...options }\n : left;\n const validate = request.validate !== false;\n assertSamples('meteringStereoCorrelation', request.left, validate, 'left');\n assertSamples('meteringStereoCorrelation', request.right, validate, 'right');\n return requireModule().meteringStereoCorrelation(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n );\n}\n\n/**\n * Side / mid energy ratio in `[0, +Infinity)`: 0 = pure mono, ~1 = wide stereo,\n * larger = increasingly decorrelated / out-of-phase. The value is unbounded and\n * returns `Infinity` when the mid channel is silent (a mono-collapsed / fully\n * out-of-phase signal).\n */\nexport function meteringStereoWidth(request: MeteringStereoRequest): number;\nexport function meteringStereoWidth(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringStereoWidth(\n left: Float32Array | MeteringStereoRequest,\n right?: Float32Array,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): number {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...options }\n : left;\n const validate = request.validate !== false;\n assertSamples('meteringStereoWidth', request.left, validate, 'left');\n assertSamples('meteringStereoWidth', request.right, validate, 'right');\n return requireModule().meteringStereoWidth(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n );\n}\n\n/**\n * Mid/side vectorscope point series. By default emits one point per input\n * sample; pass `maxPoints` to get a display-sized decimated point set (matching\n * the Node `meteringVectorscope` shape).\n */\nexport function meteringVectorscope(request: MeteringStereoDecimatedRequest): VectorscopeReport;\nexport function meteringVectorscope(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n options?: ScopeOptions,\n): VectorscopeReport;\nexport function meteringVectorscope(\n left: Float32Array | MeteringStereoDecimatedRequest,\n right?: Float32Array,\n sampleRate = 22050,\n options: ScopeOptions = {},\n): VectorscopeReport {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...options }\n : left;\n const validate = request.validate !== false;\n assertSamples('meteringVectorscope', request.left, validate, 'left');\n assertSamples('meteringVectorscope', request.right, validate, 'right');\n return requireModule().meteringVectorscopeDecimated(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.maxPoints ?? 0,\n );\n}\n\n/**\n * Display-sized mid/side vectorscope.\n *\n * @deprecated Pass `maxPoints` to {@link meteringVectorscope} instead; it now\n * folds `maxPoints` into the request, matching the Node surface. This alias is\n * kept for backward compatibility and simply delegates.\n */\nexport function meteringVectorscopeDecimated(\n request: MeteringStereoDecimatedRequest,\n): VectorscopeReport;\nexport function meteringVectorscopeDecimated(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n maxPoints?: number,\n options?: ValidateOptions,\n): VectorscopeReport;\nexport function meteringVectorscopeDecimated(\n left: Float32Array | MeteringStereoDecimatedRequest,\n right?: Float32Array,\n sampleRate = 22050,\n maxPoints = 0,\n options: ValidateOptions = {},\n): VectorscopeReport {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, maxPoints, ...options }\n : left;\n const validate = request.validate !== false;\n assertSamples('meteringVectorscopeDecimated', request.left, validate, 'left');\n assertSamples('meteringVectorscopeDecimated', request.right, validate, 'right');\n return requireModule().meteringVectorscopeDecimated(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.maxPoints ?? 0,\n );\n}\n\n/**\n * Phase-scope point series plus summary stats. By default emits one point per\n * input sample; pass `maxPoints` to decimate the point cloud for display\n * (matching the Node `meteringPhaseScope` shape). The summary stats are always\n * computed over the full-resolution signal.\n */\nexport function meteringPhaseScope(request: MeteringStereoDecimatedRequest): PhaseScopeReport;\nexport function meteringPhaseScope(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n options?: ScopeOptions,\n): PhaseScopeReport;\nexport function meteringPhaseScope(\n left: Float32Array | MeteringStereoDecimatedRequest,\n right?: Float32Array,\n sampleRate = 22050,\n options: ScopeOptions = {},\n): PhaseScopeReport {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...options }\n : left;\n const validate = request.validate !== false;\n assertSamples('meteringPhaseScope', request.left, validate, 'left');\n assertSamples('meteringPhaseScope', request.right, validate, 'right');\n return requireModule().meteringPhaseScopeDecimated(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.maxPoints ?? 0,\n );\n}\n\n/**\n * Display-sized phase scope.\n *\n * @deprecated Pass `maxPoints` to {@link meteringPhaseScope} instead; it now\n * folds `maxPoints` into the request, matching the Node surface. This alias is\n * kept for backward compatibility and simply delegates.\n */\nexport function meteringPhaseScopeDecimated(\n request: MeteringStereoDecimatedRequest,\n): PhaseScopeReport;\nexport function meteringPhaseScopeDecimated(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n maxPoints?: number,\n options?: ValidateOptions,\n): PhaseScopeReport;\nexport function meteringPhaseScopeDecimated(\n left: Float32Array | MeteringStereoDecimatedRequest,\n right?: Float32Array,\n sampleRate = 22050,\n maxPoints = 0,\n options: ValidateOptions = {},\n): PhaseScopeReport {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, maxPoints, ...options }\n : left;\n const validate = request.validate !== false;\n assertSamples('meteringPhaseScopeDecimated', request.left, validate, 'left');\n assertSamples('meteringPhaseScopeDecimated', request.right, validate, 'right');\n return requireModule().meteringPhaseScopeDecimated(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.maxPoints ?? 0,\n );\n}\n\n/**\n * Welch-averaged magnitude / power / dB spectrum over the WHOLE mono signal (split\n * into Hann-windowed, 50%-overlapping `nFft`-length frames whose power spectra\n * are averaged). For a true single-frame snapshot, use\n * {@link meteringSpectrumFrame}.\n */\nexport function meteringSpectrum(request: MeteringSpectrumRequest): SpectrumReport;\nexport function meteringSpectrum(\n samples: Float32Array,\n sampleRate?: number,\n options?: SpectrumOptions & ValidateOptions,\n): SpectrumReport;\nexport function meteringSpectrum(\n samples: Float32Array | MeteringSpectrumRequest,\n sampleRate = 22050,\n options: SpectrumOptions & ValidateOptions = {},\n): SpectrumReport {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('meteringSpectrum', request.samples, request.validate !== false);\n return requireModule().meteringSpectrum(request.samples, request.sampleRate ?? 22050, request);\n}\n\n/**\n * True single-frame magnitude / power / dB spectrum (one Hann-windowed\n * `nFft`-length FFT), for spectrum-analyzer \"moment\" snapshots that must not be\n * time-averaged like {@link meteringSpectrum}. The analysis frame spans\n * `[frameOffset, frameOffset + nFft)`; samples past the end are zero-padded.\n */\nexport function meteringSpectrumFrame(request: MeteringSpectrumFrameRequest): SpectrumReport;\nexport function meteringSpectrumFrame(\n samples: Float32Array,\n sampleRate?: number,\n frameOffset?: number,\n options?: SpectrumOptions & ValidateOptions,\n): SpectrumReport;\nexport function meteringSpectrumFrame(\n samples: Float32Array | MeteringSpectrumFrameRequest,\n sampleRate = 22050,\n frameOffset = 0,\n options: SpectrumOptions & ValidateOptions = {},\n): SpectrumReport {\n const request =\n samples instanceof Float32Array ? { samples, sampleRate, frameOffset, ...options } : samples;\n assertSamples('meteringSpectrumFrame', request.samples, request.validate !== false);\n return requireModule().meteringSpectrumFrame(\n request.samples,\n request.sampleRate ?? 22050,\n request.frameOffset ?? 0,\n request,\n );\n}\n\n/** Compute per-channel min/max waveform buckets from interleaved audio. */\nexport function waveformPeaks(request: WaveformPeaksRequest): WaveformPeaksReport;\nexport function waveformPeaks(\n samples: Float32Array,\n channels: number,\n options?: WaveformPeaksOptions,\n): WaveformPeaksReport;\nexport function waveformPeaks(\n samples: Float32Array | WaveformPeaksRequest,\n channels?: number,\n options: WaveformPeaksOptions = {},\n): WaveformPeaksReport {\n const request =\n samples instanceof Float32Array\n ? { samples, channels: channels as number, ...options }\n : samples;\n assertSamples('waveformPeaks', request.samples, request.validate !== false);\n if (request.channels <= 0 || request.samples.length % request.channels !== 0) {\n throw new RangeError('waveformPeaks: samples length must be a multiple of channels');\n }\n const samplesPerBucket = request.samplesPerBucket ?? 512;\n if (samplesPerBucket <= 0) {\n throw new RangeError('waveformPeaks: samplesPerBucket must be > 0');\n }\n return requireModule().waveformPeaks(request.samples, request.channels, samplesPerBucket);\n}\n\n/** Compute waveform peak buckets for several zoom levels. */\nexport function waveformPeakPyramid(request: WaveformPeakPyramidRequest): WaveformPeaksReport[];\nexport function waveformPeakPyramid(\n samples: Float32Array,\n channels: number,\n options?: WaveformPeakPyramidOptions,\n): WaveformPeaksReport[];\nexport function waveformPeakPyramid(\n samples: Float32Array | WaveformPeakPyramidRequest,\n channels?: number,\n options: WaveformPeakPyramidOptions = {},\n): WaveformPeaksReport[] {\n const request =\n samples instanceof Float32Array\n ? { samples, channels: channels as number, ...options }\n : samples;\n assertSamples('waveformPeakPyramid', request.samples, request.validate !== false);\n if (request.channels <= 0 || request.samples.length % request.channels !== 0) {\n throw new RangeError('waveformPeakPyramid: samples length must be a multiple of channels');\n }\n const levels = request.samplesPerBucketLevels ?? [512, 1024, 2048, 4096];\n if (levels.length === 0 || levels.some((level) => level <= 0)) {\n throw new RangeError('waveformPeakPyramid: samplesPerBucketLevels must be non-empty and > 0');\n }\n return requireModule().waveformPeakPyramid(request.samples, request.channels, levels);\n}\n","import { resolveEnumOrdinal } from './codes';\nimport { getSonareModule } from './module_state';\nimport type {\n BuiltinSynthBinding,\n ProjectAssistSidecar,\n ProjectAutomationLaneDesc,\n ProjectAutomationPoint,\n ProjectAutomationTargetKind,\n ProjectBounceOptions,\n ProjectChordSymbol,\n ProjectClip,\n ProjectClipCompSegment,\n ProjectClipDesc,\n ProjectClipFade,\n ProjectClipTake,\n ProjectCompileResult,\n ProjectKeySegment,\n ProjectLoopMode,\n ProjectLoopRecordingDesc,\n ProjectLoopRecordingResult,\n ProjectMarker,\n ProjectMidiCcBinding,\n ProjectMidiClipResult,\n ProjectMidiEvent,\n ProjectMidiRouteConfig,\n ProjectMidiRouteResult,\n ProjectNotePairValidation,\n ProjectSource,\n ProjectTempoCandidate,\n ProjectTempoSegment,\n ProjectTimeSignatureSegment,\n ProjectTrack,\n ProjectTrackKind,\n ProjectWarpMapDesc,\n ProjectWarpMode,\n Sf2InstrumentConfig,\n Sf2ProgramStatus,\n SynthEnumTables,\n SynthPatch,\n} from './project_types';\n\n// Embind handle for the C++ `ProjectWasm` class. The generated `SonareModule`\n// type only gains `Project` / `projectAbiVersion` after a WASM rebuild, so the\n// module is cast through this shape here.\nexport interface WasmProject {\n toJson: () => string;\n setSampleRate: (sampleRate: number) => void;\n addTrack: (desc: { kind?: number | string; name?: string }) => number;\n addClip: (desc: ProjectClipDesc) => number;\n importExternalStems: (request: unknown) => { trackIds: number[]; clipIds: number[] };\n addLoopRecordingTakes: (desc: ProjectLoopRecordingDesc) => ProjectLoopRecordingResult;\n addMidiClip: (startPpq: number, lengthPpq: number) => ProjectMidiClipResult;\n splitClip: (clipId: number, splitPpq: number) => number;\n trimClip: (clipId: number, newStartPpq: number, newLengthPpq: number) => void;\n moveClip: (clipId: number, newStartPpq: number, newTrackId: number) => void;\n setTrackKind: (trackId: number, kind: number) => void;\n setClipWarpRef: (clipId: number, warpRefId: number) => void;\n setClipWarpMode: (clipId: number, mode: number) => void;\n setWarpMap: (map: ProjectWarpMapDesc) => void;\n removeWarpMap: (warpRefId: number) => void;\n setTrackMidiDestination: (trackId: number, destinationId: number) => void;\n setTrackGain: (trackId: number, gain: number) => void;\n setTrackMute: (trackId: number, mute: boolean) => void;\n setTrackSolo: (trackId: number, solo: boolean) => void;\n setTrackPan: (trackId: number, pan: number) => void;\n undo: () => void;\n redo: () => void;\n clearHistory: () => void;\n setMaxUndoDepth: (depth: number) => void;\n setMaxHistoryBytes: (bytes: number) => void;\n setMidiEvents: (\n clipId: number,\n events: ReadonlyArray<ProjectMidiEvent | readonly [number, number, number]>,\n ) => void;\n importSmf: (data: Uint8Array) => number;\n exportSmf: () => Uint8Array;\n importClipFile: (data: Uint8Array) => number;\n exportClipFile: () => Uint8Array;\n setProgram: (clipId: number, program: number, bank: number) => void;\n setProgramOnChannel: (\n clipId: number,\n group: number,\n channel: number,\n program: number,\n bank: number,\n ) => void;\n bakeMidiFx: (clipId: number, configJson: string) => void;\n setMidiFx: (clipId: number, configJson: string) => void;\n validateMidiNotes: (clipId: number) => ProjectNotePairValidation;\n analyzeTempo: (audio: Float32Array, sampleRate: number) => ProjectTempoCandidate[];\n autoTempo: (\n audio: Float32Array,\n sampleRate: number,\n candidateIndex: number,\n applyTimeSignatures: boolean,\n ) => number;\n snapToGrid: (ppq: number, strength: number, division: number) => number;\n compile: () => ProjectCompileResult;\n bounce: (options: ProjectBounceOptions) => Float32Array;\n bounceWithBuiltinInstrument: (\n bindings: BuiltinSynthBinding | ReadonlyArray<BuiltinSynthBinding> | undefined,\n options: ProjectBounceOptions,\n ) => Float32Array;\n bounceWithSynthInstrument: (\n bindings: SynthPatch | string | ReadonlyArray<SynthPatch | string> | undefined,\n options: ProjectBounceOptions,\n ) => Float32Array;\n loadSoundFont: (data: Uint8Array) => void;\n clearSoundFont: () => void;\n soundFontPresetCount: () => number;\n soundFontManifest: () => Sf2ProgramStatus[];\n bounceWithSf2Instrument: (\n bindings: Sf2InstrumentConfig | ReadonlyArray<Sf2InstrumentConfig> | undefined,\n options: ProjectBounceOptions,\n ) => Float32Array;\n removeClip: (clipId: number) => void;\n setClipGain: (clipId: number, gain: number) => void;\n setClipFade: (clipId: number, fadeIn: ProjectClipFade, fadeOut: ProjectClipFade) => void;\n unresolvedAudioSourceIds: () => number[];\n setSourceAudio: (\n sourceId: number,\n audio: Float32Array,\n channels: number,\n sampleRate: number,\n ) => void;\n setAudioSourceMetadata: (sourceId: number, contentHash: string, externalStemRole: string) => void;\n setClipTakes: (\n clipId: number,\n takes: ReadonlyArray<ProjectClipTake>,\n activeTakeId: number,\n ) => void;\n setClipCompSegments: (clipId: number, segments: ReadonlyArray<ProjectClipCompSegment>) => void;\n setClipLoop: (\n clipId: number,\n loopMode: number,\n loopLengthPpq: number,\n loopCrossfadePpq: number,\n ) => void;\n setClipSource: (clipId: number, sourceId: number) => void;\n duplicateClip: (clipId: number, newStartPpq: number) => number;\n removeTrack: (trackId: number) => void;\n renameTrack: (trackId: number, name: string) => void;\n setTrackRoute: (trackId: number, channelStripRef: string, outputTarget: string) => void;\n addAutomationLane: (trackId: number, desc: ProjectAutomationLaneDesc) => number;\n editAutomationLane: (\n trackId: number,\n targetParamId: number,\n desc: ProjectAutomationLaneDesc,\n ) => void;\n removeAutomationLane: (trackId: number, targetParamId: number) => void;\n annotateKeys: (keys: ReadonlyArray<ProjectKeySegment>) => void;\n annotateChords: (chords: ReadonlyArray<ProjectChordSymbol>) => void;\n setAssistSidecar: (\n moduleId: string,\n schemaVersion: number,\n targetTrackId: number,\n regionStartPpq: number,\n regionEndPpq: number,\n payload: Uint8Array,\n ) => void;\n assistSidecarCount: () => number;\n getAssistSidecar: (index: number) => ProjectAssistSidecar;\n setOverlapPolicy: (policy: number) => void;\n getOverlapPolicy: () => number;\n getSampleRate: () => number;\n setMixerSceneJson: (sceneJson: string) => void;\n setMarker: (markerId: number, ppq: number, name: string) => number;\n setMarkerEx: (marker: ProjectMarker) => number;\n markerByIndex: (index: number) => ProjectMarker;\n trackByIndex: (index: number) => ProjectTrack;\n clipByIndex: (index: number) => ProjectClip;\n sourceByIndex: (index: number) => ProjectSource;\n markerCount: () => number;\n trackCount: () => number;\n clipCount: () => number;\n sourceCount: () => number;\n tempoSegmentCount: () => number;\n timeSignatureCount: () => number;\n setTempoSegments: (segments: ReadonlyArray<ProjectTempoSegment>) => void;\n setTimeSignatures: (segments: ReadonlyArray<ProjectTimeSignatureSegment>) => void;\n lastBounceCompileResult: () => ProjectCompileResult;\n delete: () => void;\n}\n\nexport interface ProjectModule {\n Project: {\n new (): WasmProject;\n fromJson: (json: string) => WasmProject;\n fromJsonWithDiagnostics: (json: string) => { project: WasmProject; diagnostics: string };\n };\n projectAbiVersion: () => number;\n synthPresetNames: () => string[];\n synthPresetPatch: (name: string) => SynthPatch;\n _synthEnumTables: () => SynthEnumTables;\n _synthPatchRoundTrip: (patch: SynthPatch) => SynthPatch;\n midiGmInstrumentName: (program: number) => string | null;\n midiGmProgramForName: (name: string) => number;\n midiGmFamilyName: (family: number) => string | null;\n midiGmFamilyFirstProgram: (family: number) => number;\n midiGm2InstrumentName: (bankLsb: number, program: number) => string | null;\n midiGmDrumName: (note: number) => string | null;\n midiGmDrumNoteForName: (name: string) => number;\n midiGm2DrumSetName: (bankLsb: number) => string | null;\n midiGm2DrumName: (bankLsb: number, note: number) => string | null;\n midiCcName: (controller: number) => string | null;\n midiCcIndexForName: (name: string) => number;\n midiPerNoteControllerName: (index: number) => string | null;\n midiBankProgram: (\n ppq: number,\n group: number,\n channel: number,\n bankMsb: number,\n bankLsb: number,\n program: number,\n ) => ProjectMidiEvent[];\n midiRouteEvents: (\n events: ReadonlyArray<ProjectMidiEvent>,\n config: ProjectMidiRouteConfig,\n ) => ProjectMidiRouteResult;\n midiCcLearn: (\n events: ReadonlyArray<ProjectMidiEvent>,\n paramId: number,\n minValue: number,\n maxValue: number,\n minMovement: number,\n ) => ProjectMidiCcBinding | null;\n midiCcToBreakpoint: (\n bindings: ReadonlyArray<ProjectMidiCcBinding>,\n event: ProjectMidiEvent,\n ) => ProjectAutomationPoint | null;\n midiParamToCc: (\n bindings: ReadonlyArray<ProjectMidiCcBinding>,\n paramId: number,\n unitValue: number,\n group: number,\n ppq: number,\n ) => ProjectMidiEvent | null;\n}\n\nexport function projectModule(): ProjectModule {\n const candidate = getSonareModule() as unknown as Partial<ProjectModule>;\n if (typeof candidate.projectAbiVersion !== 'function' || candidate.Project === undefined) {\n throw new Error('libsonare was built without arrangement (headless DAW) support');\n }\n return candidate as ProjectModule;\n}\n\nexport function assertProjectU7(fnName: string, value: number, argName: string): number {\n if (!Number.isInteger(value) || value < 0 || value > 127) {\n throw new RangeError(`${fnName}: ${argName} must be an integer in [0, 127]`);\n }\n return value;\n}\n\nexport function assertProjectNibble(fnName: string, value: number, argName: string): number {\n if (!Number.isInteger(value) || value < 0 || value > 15) {\n throw new RangeError(`${fnName}: ${argName} must be an integer in [0, 15]`);\n }\n return value;\n}\n\nexport function projectMidi1Event(\n fnName: string,\n ppq: number,\n group: number,\n status: number,\n channel: number,\n data1: number,\n data2 = 0,\n): ProjectMidiEvent {\n if (!Number.isFinite(ppq) || ppq < 0) {\n throw new RangeError(`${fnName}: ppq must be a non-negative finite number`);\n }\n const g = assertProjectNibble(fnName, group, 'group');\n const ch = assertProjectNibble(fnName, channel, 'channel');\n const d1 = assertProjectU7(fnName, data1, 'data1');\n const d2 = assertProjectU7(fnName, data2, 'data2');\n // UMP MIDI-1.0 channel-voice word (message type 0x2). Canonical layout is\n // sonare::midi::make_midi1_* (C-ABI sonare_midi_*, which Python delegates to);\n // this hand-written copy is locked against those words by the golden vectors\n // in project.test.ts (mirrored in the Node suite) so it cannot silently drift.\n const word = ((0x2 << 28) | (g << 24) | (status << 20) | (ch << 16) | (d1 << 8) | d2) >>> 0;\n return { ppq, data0: word, data1: 0 };\n}\n\nexport function assertProjectU32(fnName: string, value: number, argName: string): void {\n if (!Number.isInteger(value) || value < 0 || value > 0xffffffff) {\n throw new RangeError(`${fnName}: ${argName} must be an integer in [0, 4294967295]`);\n }\n}\n\nexport function assertProjectMidiEvents(\n fnName: string,\n events: ReadonlyArray<ProjectMidiEvent | readonly [number, number, number]>,\n): void {\n if (!Array.isArray(events)) {\n throw new TypeError(`${fnName}: events must be an array`);\n }\n events.forEach((event, index) => {\n const prefix = `events[${index}]`;\n if (Array.isArray(event)) {\n if (event.length < 3) {\n throw new TypeError(`${fnName}: ${prefix} must contain [ppq, data0, data1]`);\n }\n if (!Number.isFinite(event[0]) || event[0] < 0) {\n throw new RangeError(`${fnName}: ${prefix}.ppq must be a non-negative finite number`);\n }\n assertProjectU32(fnName, event[1], `${prefix}.data0`);\n assertProjectU32(fnName, event[2], `${prefix}.data1`);\n return;\n }\n if (event === null || typeof event !== 'object') {\n throw new TypeError(`${fnName}: ${prefix} must be a MIDI event object or tuple`);\n }\n if (!Number.isFinite(event.ppq) || event.ppq < 0) {\n throw new RangeError(`${fnName}: ${prefix}.ppq must be a non-negative finite number`);\n }\n assertProjectU32(fnName, event.data0, `${prefix}.data0`);\n if (event.data1 !== undefined) {\n assertProjectU32(fnName, event.data1, `${prefix}.data1`);\n }\n });\n}\n\nexport function projectTrackKindValue(kind: ProjectTrackKind | undefined): number {\n return resolveEnumOrdinal(kind ?? 'audio', { audio: 0, midi: 1, aux: 2 }, 'project track kind');\n}\n\nexport function projectAutomationTargetKindValue(kind: ProjectAutomationTargetKind): number {\n return resolveEnumOrdinal(\n kind,\n { opaque: 0, 'track-fader-db': 1, 'track-pan': 2 },\n 'project automation target kind',\n );\n}\n\nexport function projectWarpModeValue(mode: ProjectWarpMode | undefined): number {\n return resolveEnumOrdinal(\n mode ?? 'off',\n { off: 0, repitch: 1, 'tempo-sync': 2 },\n 'project warp mode',\n );\n}\n\nexport function projectLoopModeValue(mode: ProjectLoopMode | undefined): number {\n return resolveEnumOrdinal(mode ?? 'off', { off: 0, loop: 1 }, 'project loop mode');\n}\n","import {\n assertProjectMidiEvents,\n projectAutomationTargetKindValue,\n projectLoopModeValue,\n projectMidi1Event,\n projectModule,\n projectTrackKindValue,\n projectWarpModeValue,\n type WasmProject,\n} from './project_internal';\nimport type {\n BuiltinSynthBinding,\n ExternalSeparatedStemImportRequest,\n ExternalSeparatedStemImportResult,\n MidiCcLearnOptions,\n ProjectAssistSidecar,\n ProjectAssistSidecarInput,\n ProjectAutomationLaneDesc,\n ProjectAutomationPoint,\n ProjectAutomationTargetKind,\n ProjectBounceOptions,\n ProjectChordSymbol,\n ProjectClip,\n ProjectClipCompSegment,\n ProjectClipDesc,\n ProjectClipFade,\n ProjectClipTake,\n ProjectCompileResult,\n ProjectDeserializeResult,\n ProjectKeySegment,\n ProjectLoopMode,\n ProjectLoopRecordingDesc,\n ProjectLoopRecordingResult,\n ProjectMarker,\n ProjectMidiCcBinding,\n ProjectMidiClipResult,\n ProjectMidiEvent,\n ProjectMidiRouteConfig,\n ProjectMidiRouteResult,\n ProjectNotePairValidation,\n ProjectSource,\n ProjectTempoCandidate,\n ProjectTempoSegment,\n ProjectTimeSignatureSegment,\n ProjectTrack,\n ProjectTrackDesc,\n ProjectTrackKind,\n ProjectWarpMapDesc,\n ProjectWarpMode,\n Sf2InstrumentConfig,\n Sf2ProgramStatus,\n SynthPatch,\n} from './project_types';\n\nfunction validateAssistSidecarUint32(value: unknown, field: string): number {\n if (\n typeof value !== 'number' ||\n !Number.isSafeInteger(value) ||\n value < 0 ||\n value > 0xffff_ffff\n ) {\n throw new RangeError(`Project.setAssistSidecar: ${field} must be a uint32`);\n }\n return value;\n}\n\nfunction validateAssistSidecarPpq(value: unknown, field: string): number {\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {\n throw new RangeError(\n `Project.setAssistSidecar: ${field} must be a finite, non-negative number`,\n );\n }\n return value;\n}\n\nfunction validateAssistSidecarPayload(value: unknown): Uint8Array {\n if (!(value instanceof Uint8Array)) {\n throw new TypeError('Project.setAssistSidecar: payload must be a Uint8Array');\n }\n return value;\n}\n\nfunction validateAssistSidecarModuleId(value: unknown): string {\n if (typeof value !== 'string' || value.length === 0) {\n throw new TypeError('Project.setAssistSidecar: moduleId must be a non-empty string');\n }\n return value;\n}\n\n/**\n * Headless DAW project (control-thread-only arrangement model).\n *\n * Wraps the embind `Project` class over the C-ABI keystone\n * `sonare_c_project.{h,cpp}`. Construct an empty project with `new Project()`,\n * or deserialize one with {@link Project.fromJson}; serialize back with\n * {@link toJson}; compile to a renderable timeline with {@link compile}; render\n * offline to interleaved float audio with {@link bounce}. The edit and MIDI\n * methods mirror the Node/Python project bindings.\n *\n * Call {@link delete} (or use a `try/finally`) to release the underlying WASM\n * object — the embind handle is not garbage-collected automatically.\n *\n * @example\n * ```typescript\n * const project = new Project();\n * try {\n * project.setSampleRate(48000);\n * const json = project.toJson();\n * const restored = Project.fromJson(json);\n * restored.delete();\n * } finally {\n * project.delete();\n * }\n * ```\n */\nexport class Project {\n private native: WasmProject;\n\n constructor() {\n this.native = new (projectModule().Project)();\n }\n\n /** Create a new empty project. */\n static create(): Project {\n return new Project();\n }\n\n /** Pack a MIDI 1.0 note-on event accepted by {@link setMidiEvents}. */\n static midiNoteOn(\n ppq: number,\n group: number,\n channel: number,\n note: number,\n velocity: number,\n ): ProjectMidiEvent {\n return projectMidi1Event('Project.midiNoteOn', ppq, group, 0x9, channel, note, velocity);\n }\n\n /** Pack a MIDI 1.0 note-off event accepted by {@link setMidiEvents}. */\n static midiNoteOff(\n ppq: number,\n group: number,\n channel: number,\n note: number,\n velocity = 0,\n ): ProjectMidiEvent {\n return projectMidi1Event('Project.midiNoteOff', ppq, group, 0x8, channel, note, velocity);\n }\n\n /** Pack a MIDI 1.0 control-change event. */\n static midiCc(\n ppq: number,\n group: number,\n channel: number,\n controller: number,\n value: number,\n ): ProjectMidiEvent {\n return projectMidi1Event('Project.midiCc', ppq, group, 0xb, channel, controller, value);\n }\n\n /** Pack a MIDI 1.0 poly-pressure event. */\n static midiPolyPressure(\n ppq: number,\n group: number,\n channel: number,\n note: number,\n pressure: number,\n ): ProjectMidiEvent {\n return projectMidi1Event('Project.midiPolyPressure', ppq, group, 0xa, channel, note, pressure);\n }\n\n /** Pack a MIDI 1.0 program-change event. */\n static midiProgram(\n ppq: number,\n group: number,\n channel: number,\n program: number,\n ): ProjectMidiEvent {\n return projectMidi1Event('Project.midiProgram', ppq, group, 0xc, channel, program, 0);\n }\n\n /** Return the General MIDI instrument name for `program`, or `null` when out of range. */\n static gmInstrumentName(program: number): string | null {\n return projectModule().midiGmInstrumentName(program);\n }\n\n /** Return the General MIDI program number for a canonical instrument name, or `-1`. */\n static gmProgramForName(name: string): number {\n return projectModule().midiGmProgramForName(name);\n }\n\n /** Return the General MIDI family name for `family`, or `null` when out of range. */\n static gmFamilyName(family: number): string | null {\n return projectModule().midiGmFamilyName(family);\n }\n\n /** Return the first General MIDI program number in `family`, or `-1`. */\n static gmFamilyFirstProgram(family: number): number {\n return projectModule().midiGmFamilyFirstProgram(family);\n }\n\n /** Return the GM2 bank/program instrument variation name, or `null` when unavailable. */\n static gm2InstrumentName(bankLsb: number, program: number): string | null {\n return projectModule().midiGm2InstrumentName(bankLsb, program);\n }\n\n /** Return the General MIDI drum name for `note`, or `null` when out of range. */\n static gmDrumName(note: number): string | null {\n return projectModule().midiGmDrumName(note);\n }\n\n /** Return the General MIDI drum note for a canonical drum name, or `-1`. */\n static gmDrumNoteForName(name: string): number {\n return projectModule().midiGmDrumNoteForName(name);\n }\n\n /** Return the GM2 drum-set name for `bankLsb`, or `null` when unavailable. */\n static gm2DrumSetName(bankLsb: number): string | null {\n return projectModule().midiGm2DrumSetName(bankLsb);\n }\n\n /** Return the GM2 drum name for `bankLsb`/`note`, or `null` when unavailable. */\n static gm2DrumName(bankLsb: number, note: number): string | null {\n return projectModule().midiGm2DrumName(bankLsb, note);\n }\n\n /** Return the MIDI CC name for `controller`, or `null` when out of range. */\n static midiCcName(controller: number): string | null {\n return projectModule().midiCcName(controller);\n }\n\n /** Return the MIDI CC number for a canonical controller name, or `-1`. */\n static midiCcIndexForName(name: string): number {\n return projectModule().midiCcIndexForName(name);\n }\n\n /** Return the MIDI 2.0 per-note controller name for `index`, or `null`. */\n static perNoteControllerName(index: number): string | null {\n return projectModule().midiPerNoteControllerName(index);\n }\n\n /** Expand bank-select + program-change into MIDI events accepted by {@link setMidiEvents}. */\n static midiBankProgram(\n ppq: number,\n group: number,\n channel: number,\n bankMsb: number,\n bankLsb: number,\n program: number,\n ): ProjectMidiEvent[] {\n return projectModule().midiBankProgram(ppq, group, channel, bankMsb, bankLsb, program);\n }\n\n /** Route MIDI events through the native MidiRouter filter/remap/thru logic. */\n static midiRouteEvents(\n events: ReadonlyArray<ProjectMidiEvent>,\n config: ProjectMidiRouteConfig = {},\n ): ProjectMidiRouteResult {\n return projectModule().midiRouteEvents(events, config);\n }\n\n /** Run native MIDI learn over an event stream; returns `null` when nothing is learned. */\n static midiCcLearn(\n events: ReadonlyArray<ProjectMidiEvent>,\n paramId: number,\n options: MidiCcLearnOptions = {},\n ): ProjectMidiCcBinding | null {\n return projectModule().midiCcLearn(\n events,\n paramId,\n options.minValue ?? 0,\n options.maxValue ?? 1,\n options.minMovement ?? 0,\n );\n }\n\n /** Convert one CC event to an automation breakpoint using native CcMap. */\n static midiCcToBreakpoint(\n bindings: ReadonlyArray<ProjectMidiCcBinding>,\n event: ProjectMidiEvent,\n ): ProjectAutomationPoint | null {\n return projectModule().midiCcToBreakpoint(bindings, event);\n }\n\n /** Convert one automation value back to a CC UMP event using native CcMap. */\n static midiParamToCc(\n bindings: ReadonlyArray<ProjectMidiCcBinding>,\n paramId: number,\n unitValue: number,\n group: number,\n ppq = 0,\n ): ProjectMidiEvent | null {\n return projectModule().midiParamToCc(bindings, paramId, unitValue, group, ppq);\n }\n\n /** Pack a MIDI 1.0 channel-pressure event. */\n static midiChannelPressure(\n ppq: number,\n group: number,\n channel: number,\n pressure: number,\n ): ProjectMidiEvent {\n return projectMidi1Event('Project.midiChannelPressure', ppq, group, 0xd, channel, pressure, 0);\n }\n\n /** Pack a MIDI 1.0 pitch-bend event (`bend` is unsigned 14-bit, center = 8192). */\n static midiPitchBend(\n ppq: number,\n group: number,\n channel: number,\n bend: number,\n ): ProjectMidiEvent {\n if (!Number.isInteger(bend) || bend < 0 || bend > 0x3fff) {\n throw new RangeError('Project.midiPitchBend: bend must be an integer in [0, 16383]');\n }\n return projectMidi1Event(\n 'Project.midiPitchBend',\n ppq,\n group,\n 0xe,\n channel,\n bend & 0x7f,\n bend >> 7,\n );\n }\n\n /**\n * Deserialize project JSON into a new {@link Project}. Throws if the JSON is\n * malformed, surfacing the joined diagnostic messages.\n */\n static fromJson(json: string): Project {\n const project = new Project();\n // Replace the freshly-created empty handle with the deserialized one. If\n // fromJson throws (malformed JSON) the empty handle is released first so no\n // WASM object leaks.\n const restored = (() => {\n try {\n return projectModule().Project.fromJson(json);\n } catch (error) {\n project.native.delete();\n throw error;\n }\n })();\n project.native.delete();\n project.native = restored;\n return project;\n }\n\n /**\n * Deserialize project JSON and return native warning diagnostics emitted on\n * successful loads, such as dangling source references preserved for repair.\n */\n static fromJsonWithDiagnostics(json: string): ProjectDeserializeResult {\n const project = new Project();\n const restored = (() => {\n try {\n return projectModule().Project.fromJsonWithDiagnostics(json);\n } catch (error) {\n project.native.delete();\n throw error;\n }\n })();\n project.native.delete();\n project.native = restored.project;\n return { project, diagnostics: restored.diagnostics };\n }\n\n /** Serialize the project (+ MIDI content) to deterministic JSON. */\n toJson(): string {\n return this.native.toJson();\n }\n\n /** Set the project sample rate in Hz. Must be > 0. */\n setSampleRate(sampleRate: number): void {\n this.native.setSampleRate(sampleRate);\n }\n\n /** Add a track and return its allocated stable id. */\n addTrack(desc: ProjectTrackDesc = {}): number {\n return this.native.addTrack({ ...desc, kind: projectTrackKindValue(desc.kind) });\n }\n\n /** Add an audio or MIDI clip and return its allocated clip id. */\n addClip(desc: ProjectClipDesc): number {\n return this.native.addClip(desc);\n }\n\n /** Import host-separated PCM through the normal audio-track/clip path. */\n importExternalStems(\n request: ExternalSeparatedStemImportRequest,\n ): ExternalSeparatedStemImportResult {\n return this.native.importExternalStems({\n ...request,\n stems: request.stems.map((stem) => ({\n ...stem,\n layout: stem.layout === 'mono' ? 1 : stem.layout === 'stereo' ? 2 : stem.layout,\n })),\n });\n }\n\n /** Split captured loop-recording audio into takes and add one clip. */\n addLoopRecordingTakes(desc: ProjectLoopRecordingDesc): ProjectLoopRecordingResult {\n return this.native.addLoopRecordingTakes(desc);\n }\n\n /** Create a MIDI track + clip; returns `{ trackId, clipId }`. */\n addMidiClip(startPpq: number, lengthPpq: number): ProjectMidiClipResult {\n return this.native.addMidiClip(startPpq, lengthPpq);\n }\n\n /** Split a clip at `splitPpq` and return the new clip id. */\n splitClip(clipId: number, splitPpq: number): number {\n return this.native.splitClip(clipId, splitPpq);\n }\n\n /** Trim a clip's start / length in PPQ. */\n trimClip(clipId: number, newStartPpq: number, newLengthPpq: number): void {\n this.native.trimClip(clipId, newStartPpq, newLengthPpq);\n }\n\n /** Move a clip to `newStartPpq` and optionally another track. */\n moveClip(clipId: number, newStartPpq: number, newTrackId = 0): void {\n this.native.moveClip(clipId, newStartPpq, newTrackId);\n }\n\n /** Change a track kind via an undoable edit. */\n setTrackKind(trackId: number, kind: ProjectTrackKind): void {\n this.native.setTrackKind(trackId, projectTrackKindValue(kind));\n }\n\n /** Set a clip's warp reference id (0 clears it). */\n setClipWarpRef(clipId: number, warpRefId: number): void {\n this.native.setClipWarpRef(clipId, warpRefId);\n }\n\n /** Set a clip's warp playback mode. */\n setClipWarpMode(clipId: number, mode: ProjectWarpMode): void {\n this.native.setClipWarpMode(clipId, projectWarpModeValue(mode));\n }\n\n /** Add or replace a first-class warp map referenced by clip warp ids. */\n setWarpMap(map: ProjectWarpMapDesc): void {\n this.native.setWarpMap(map);\n }\n\n /** Remove a first-class warp map by id. */\n removeWarpMap(warpRefId: number): void {\n this.native.removeWarpMap(warpRefId);\n }\n\n /**\n * Route a track's MIDI to host-instrument `destinationId` (0 = default). The\n * compiler stamps every MIDI clip on the track with this id so the engine\n * dispatches its events to the instrument registered for that destination.\n * Routes through an undoable edit command. Builtin, NativeSynth, and SF2\n * instruments retain source-track provenance inside a shared destination\n * voice pool. With only zero-latency instruments bound, live lanes and\n * channel-strip bounces remain aligned. Configure one live lane per source\n * track that needs strip processing.\n */\n setTrackMidiDestination(trackId: number, destinationId: number): void {\n this.native.setTrackMidiDestination(trackId, destinationId);\n }\n\n /** Set a track's linear playback gain (1.0 = unity; >= 0) via an undoable edit. */\n setTrackGain(trackId: number, gain: number): void {\n this.native.setTrackGain(trackId, gain);\n }\n\n /** Set a track's mute flag via an undoable edit (a muted track is silent). */\n setTrackMute(trackId: number, mute: boolean): void {\n this.native.setTrackMute(trackId, mute);\n }\n\n /** Set a track's solo flag via an undoable edit (when any track is soloed, only soloed tracks sound). */\n setTrackSolo(trackId: number, solo: boolean): void {\n this.native.setTrackSolo(trackId, solo);\n }\n\n /** Set a track's stereo balance in [-1, +1] (0 = center) via an undoable edit. */\n setTrackPan(trackId: number, pan: number): void {\n this.native.setTrackPan(trackId, pan);\n }\n\n /** Undo the most recent edit. */\n undo(): void {\n this.native.undo();\n }\n\n /** Redo the most recently undone edit. */\n redo(): void {\n this.native.redo();\n }\n\n /** Clear the undo/redo history without changing the current project state. */\n clearHistory(): void {\n this.native.clearHistory();\n }\n\n /** Cap the undo history depth (clamped to >= 1); evicts oldest entries beyond the cap. */\n setMaxUndoDepth(depth: number): void {\n if (!Number.isInteger(depth) || depth < 1) {\n throw new RangeError('Project.setMaxUndoDepth: depth must be an integer >= 1');\n }\n this.native.setMaxUndoDepth(depth);\n }\n\n /** Set the combined undo/redo history byte cap. Zero disables retention. */\n setMaxHistoryBytes(bytes: number): void {\n if (typeof bytes !== 'number') {\n throw new TypeError('Project.setMaxHistoryBytes: bytes must be a number');\n }\n if (!Number.isFinite(bytes) || !Number.isInteger(bytes) || bytes < 0 || bytes > 0xffff_ffff) {\n throw new RangeError(\n 'Project.setMaxHistoryBytes: bytes must be a finite integer in the uint32 range',\n );\n }\n this.native.setMaxHistoryBytes(bytes);\n }\n\n /** Replace a MIDI clip's entire event list. */\n setMidiEvents(\n clipId: number,\n events: ReadonlyArray<ProjectMidiEvent | readonly [number, number, number]>,\n ): void {\n assertProjectMidiEvents('Project.setMidiEvents', events);\n this.native.setMidiEvents(clipId, events);\n }\n\n /**\n * Import an in-memory SMF buffer; returns the first added clip id.\n * Malformed or partially truncated tracks are rejected instead of installing\n * a silently shortened clip.\n */\n importSmf(data: Uint8Array): number {\n return this.native.importSmf(data);\n }\n\n /** Export the project's tempo map + MIDI clips to an SMF byte buffer. */\n exportSmf(): Uint8Array {\n return this.native.exportSmf();\n }\n\n /**\n * Import a MIDI 2.0 Clip File (`SMF2CLIP`); returns the first added clip id.\n * Unlike {@link importSmf}, MIDI 2.0 channel-voice messages (16-bit velocity,\n * 32-bit CC, per-note / registered controllers, bank-valid Program Change)\n * survive without loss.\n */\n importClipFile(data: Uint8Array): number {\n return this.native.importClipFile(data);\n }\n\n /**\n * Export the project's tempo map + MIDI clips to a MIDI 2.0 Clip File\n * (`SMF2CLIP`) byte buffer. MIDI 2.0-only events are written without loss —\n * prefer this over {@link exportSmf} when MIDI 2.0 fidelity matters.\n */\n exportClipFile(): Uint8Array {\n return this.native.exportClipFile();\n }\n\n /**\n * Set a MIDI clip's channel-0 program / bank at source PPQ 0. `bank` defaults\n * to `-1` (no Bank Select emitted), matching `setProgramOnChannel` and the\n * Node/Python surfaces; pass `>= 0` to emit a Bank Select.\n */\n setProgram(clipId: number, program: number, bank = -1): void {\n this.native.setProgram(clipId, program, bank);\n }\n\n /** Set a MIDI clip's program / bank for one UMP group and channel. */\n setProgramOnChannel(\n clipId: number,\n group: number,\n channel: number,\n program: number,\n bank = -1,\n ): void {\n this.native.setProgramOnChannel(clipId, group, channel, program, bank);\n }\n\n /**\n * Destructively bake a MIDI-FX chain into all stored events. Large clips are\n * drained without truncation; failure leaves the original clip unchanged.\n */\n bakeMidiFx(clipId: number, configJson: string): void {\n this.native.bakeMidiFx(clipId, configJson);\n }\n\n /** Backward alias for {@link bakeMidiFx}. */\n setMidiFx(clipId: number, configJson: string): void {\n this.bakeMidiFx(clipId, configJson);\n }\n\n /**\n * Pre-flight check for hanging / unmatched notes in a MIDI clip: reports\n * whether every note-on in the exported half-open playback window has a\n * matching note-off (FIFO per group+channel+note). Useful before bouncing to\n * catch a stuck note. Throws if `clipId` is unknown or not a MIDI clip.\n */\n validateMidiNotes(clipId: number): ProjectNotePairValidation {\n return this.native.validateMidiNotes(clipId);\n }\n\n /** Return ranked tempo-octave and detected-meter candidates without editing. */\n analyzeTempo(audio: Float32Array, sampleRate: number): ProjectTempoCandidate[] {\n return this.native.analyzeTempo(audio, sampleRate);\n }\n\n /** Detect and install a ranked tempo candidate; optionally apply detected meter. */\n autoTempo(\n audio: Float32Array,\n sampleRate: number,\n candidateIndex = 0,\n applyTimeSignatures = false,\n ): number {\n return this.native.autoTempo(audio, sampleRate, candidateIndex, applyTimeSignatures);\n }\n\n /** Snap to a bar (`division=0`), beat (`1`), or beat subdivision (`2+`). */\n snapToGrid(ppq: number, strength = 1.0, division = 1): number {\n return this.native.snapToGrid(ppq, strength, division);\n }\n\n /** Compile the project into a renderable timeline, surfacing diagnostics. */\n compile(): ProjectCompileResult {\n return this.native.compile();\n }\n\n /**\n * Compile + render the project offline to interleaved float audio. MIDI\n * tracks render silently here (no instrument is bound) — use\n * {@link bounceWithBuiltinInstrument} to make MIDI audible.\n *\n * When `totalFrames` is omitted (or `<= 0`) the render length is auto-derived\n * from the arrangement, so a project with content renders without computing a\n * frame count; an empty project yields an empty buffer.\n *\n * @example\n * ```typescript\n * const audio = project.bounce({ numChannels: 2 });\n * ```\n */\n bounce(options: ProjectBounceOptions = {}): Float32Array {\n return this.native.bounce(options);\n }\n\n /**\n * Compile + render the project offline, routing MIDI tracks through the\n * built-in oscillator synth so a MIDI-only arrangement bounces to audible\n * audio. Pass a {@link BuiltinSynthBinding} (or an array of them) to choose\n * the patch and MIDI destination; omit it (or pass `{}`) for one\n * default-destination sine patch. Because the parameter defaults to `{}`,\n * omission and explicit `undefined` both create that one default binding.\n * Use an explicitly empty array `[]` (or runtime `null`) for zero bindings,\n * so MIDI tracks render silently.\n *\n * Like {@link bounce}, omitting `totalFrames` auto-derives the render length\n * from the arrangement plus the synth's release tail.\n *\n * @example\n * ```typescript\n * // MIDI-only project -> non-silent stereo audio.\n * const audio = project.bounceWithBuiltinInstrument(\n * { waveform: 'saw' },\n * { numChannels: 2 },\n * );\n * ```\n */\n bounceWithBuiltinInstrument(\n instrument: BuiltinSynthBinding | ReadonlyArray<BuiltinSynthBinding> = {},\n options: ProjectBounceOptions = {},\n ): Float32Array {\n return this.native.bounceWithBuiltinInstrument(instrument, options);\n }\n\n /**\n * Compile + render the project offline, routing MIDI tracks through the\n * patch-driven NativeSynth — the full synthesizer (subtractive / FM /\n * Karplus-Strong / modal / additive / percussion / extended-waveguide-piano\n * engines plus the realism layer). Pass a {@link SynthPatch}, a preset-name\n * string (`'saw-lead'` / `'va:saw-lead'`; see {@link synthPresetNames}), or\n * an array of either; each object entry may carry `destinationId` (default\n * 0) and `useGmPrograms` (default `false`) binding conveniences, neither of\n * which is part of the NativeSynth patch itself. When enabled, MIDI program\n * changes select the corresponding General MIDI voice while the patch remains\n * the fallback.\n * Because the parameter defaults to `{}`, omission and explicit `undefined`\n * both create one default binding. Use an explicitly empty array `[]` (or\n * runtime `null`) for zero bindings. Unknown preset names throw.\n * Deterministic for a fixed project + options + patch.\n */\n bounceWithSynthInstrument(\n instrument: SynthPatch | string | ReadonlyArray<SynthPatch | string> = {},\n options: ProjectBounceOptions = {},\n ): Float32Array {\n return this.native.bounceWithSynthInstrument(instrument, options);\n }\n\n /**\n * Load (parse) SoundFont 2 bytes into the project: presets / instruments /\n * sample headers plus the sample PCM decoded to a float pool. The host\n * fetches the `.sf2` and passes the raw bytes; they are copied into linear\n * memory for the call and not referenced afterwards. Replaces any previously\n * loaded SoundFont; throws on malformed input (the previous SoundFont is\n * kept).\n */\n loadSoundFont(data: Uint8Array): void {\n this.native.loadSoundFont(data);\n }\n\n /** Release the project's loaded SoundFont (no-op when none is loaded). */\n clearSoundFont(): void {\n this.native.clearSoundFont();\n }\n\n /** Number of presets in the loaded SoundFont (0 when none is loaded). */\n soundFontPresetCount(): number {\n return this.native.soundFontPresetCount();\n }\n\n /**\n * Enumerate every (channel, bank, program) combination the arrangement plays\n * a note through, in first-use order, reporting whether each resolves in the\n * loaded SoundFont (`'sf2'`, GS variation/drum fallbacks included) or would\n * fall back to the built-in synth (`'synth'`). Without a loaded SoundFont\n * every entry is a synth fallback.\n */\n soundFontManifest(): Sf2ProgramStatus[] {\n return this.native.soundFontManifest();\n }\n\n /**\n * Like {@link bounceWithBuiltinInstrument}, but each bound destination\n * renders through a GS-compatible SoundFont player fed by the project's\n * loaded SoundFont ({@link loadSoundFont}): 16 MIDI channels per player,\n * channel 10 drums via bank 128, GS NRPN part edits and GS/GM SysEx resets\n * honored. Programs the SoundFont does not cover — including bouncing with\n * no SoundFont loaded at all — play through the built-in synthesizer GM\n * fallback bank (the data-free floor; see {@link soundFontManifest} for the\n * per-program backend). Because the parameter defaults to `{}`, omission and\n * explicit `undefined` both create one default binding. Use an explicitly\n * empty array `[]` (or runtime `null`) for zero bindings, so MIDI tracks\n * render silently.\n */\n bounceWithSf2Instrument(\n instrument: Sf2InstrumentConfig | ReadonlyArray<Sf2InstrumentConfig> = {},\n options: ProjectBounceOptions = {},\n ): Float32Array {\n return this.native.bounceWithSf2Instrument(instrument, options);\n }\n\n /** Remove a clip (undoable). */\n removeClip(clipId: number): void {\n this.native.removeClip(clipId);\n }\n\n /** Set a clip's linear playback gain (>= 0; undoable). */\n setClipGain(clipId: number, gain: number): void {\n this.native.setClipGain(clipId, gain);\n }\n\n /** Set a clip's fade-in / fade-out regions (undoable). */\n setClipFade(clipId: number, fadeIn: ProjectClipFade = {}, fadeOut: ProjectClipFade = {}): void {\n this.native.setClipFade(clipId, fadeIn, fadeOut);\n }\n\n /** Audio source ids that need decoded PCM after deserialization. */\n unresolvedAudioSourceIds(): number[] {\n return this.native.unresolvedAudioSourceIds();\n }\n\n /** Register decoded interleaved PCM for an existing audio source (undoable). */\n setSourceAudio(\n sourceId: number,\n audio: Float32Array,\n channels: number,\n sampleRate: number,\n ): void {\n this.native.setSourceAudio(sourceId, audio, channels, sampleRate);\n }\n\n /** Replace an audio source's metadata strings as one undoable edit. */\n setAudioSourceMetadata(sourceId: number, contentHash: string, externalStemRole: string): void {\n this.native.setAudioSourceMetadata(sourceId, contentHash, externalStemRole);\n }\n\n /** Replace a clip's take list and active take id (undoable). */\n setClipTakes(clipId: number, takes: ReadonlyArray<ProjectClipTake>, activeTakeId = 0): void {\n this.native.setClipTakes(clipId, takes, activeTakeId);\n }\n\n /** Replace a clip's comp segments (undoable). */\n setClipCompSegments(clipId: number, segments: ReadonlyArray<ProjectClipCompSegment>): void {\n this.native.setClipCompSegments(clipId, segments);\n }\n\n /**\n * Set a clip's loop mode + loop length in PPQ (undoable). `loopCrossfadePpq`\n * is an optional equal-power crossfade at the loop seam (PPQ, finite and >= 0;\n * 0 = hard loop); the engine clamps it to the clip's pre-roll and half the loop.\n */\n setClipLoop(\n clipId: number,\n loopMode: ProjectLoopMode,\n loopLengthPpq = 0,\n loopCrossfadePpq = 0,\n ): void {\n this.native.setClipLoop(\n clipId,\n projectLoopModeValue(loopMode),\n loopLengthPpq,\n loopCrossfadePpq,\n );\n }\n\n /** Rebind a clip to a different (already-registered) source (undoable). */\n setClipSource(clipId: number, sourceId: number): void {\n this.native.setClipSource(clipId, sourceId);\n }\n\n /** Duplicate a clip at `newStartPpq` (same track); returns the new clip id. */\n duplicateClip(clipId: number, newStartPpq: number): number {\n return this.native.duplicateClip(clipId, newStartPpq);\n }\n\n /** Remove a track and its clips (undoable). */\n removeTrack(trackId: number): void {\n this.native.removeTrack(trackId);\n }\n\n /** Rename a track (undoable). */\n renameTrack(trackId: number, name: string): void {\n this.native.renameTrack(trackId, name);\n }\n\n /** Set a track's mixer-strip binding + output target (undoable; omit / '' clears). */\n setTrackRoute(trackId: number, channelStripRef?: string, outputTarget?: string): void {\n this.native.setTrackRoute(trackId, channelStripRef ?? '', outputTarget ?? '');\n }\n\n /** Append an automation lane; returns its stable target parameter id (undoable). */\n addAutomationLane(trackId: number, desc: ProjectAutomationLaneDesc): number {\n if (desc.targetParamId === 0) {\n throw new RangeError('project automation lane targetParamId must be non-zero');\n }\n const nativeDesc: ProjectAutomationLaneDesc = { ...desc };\n if (Object.keys(desc).includes('targetKind')) {\n nativeDesc.targetKind = projectAutomationTargetKindValue(\n desc.targetKind as ProjectAutomationTargetKind,\n ) as ProjectAutomationTargetKind;\n }\n return this.native.addAutomationLane(trackId, nativeDesc);\n }\n\n /** Replace the lane identified by its stable target parameter id (undoable). */\n editAutomationLane(\n trackId: number,\n targetParamId: number,\n desc: ProjectAutomationLaneDesc,\n ): void {\n if (desc.targetParamId === 0) {\n throw new RangeError('project automation lane targetParamId must be non-zero');\n }\n const nativeDesc: ProjectAutomationLaneDesc = { ...desc };\n if (Object.keys(desc).includes('targetKind')) {\n nativeDesc.targetKind = projectAutomationTargetKindValue(\n desc.targetKind as ProjectAutomationTargetKind,\n ) as ProjectAutomationTargetKind;\n }\n this.native.editAutomationLane(trackId, targetParamId, nativeDesc);\n }\n\n /** Remove the lane identified by its stable target parameter id (undoable). */\n removeAutomationLane(trackId: number, targetParamId: number): void {\n this.native.removeAutomationLane(trackId, targetParamId);\n }\n\n /** Replace the project's key annotation stream (undoable). */\n annotateKeys(keys: ReadonlyArray<ProjectKeySegment>): void {\n this.native.annotateKeys(keys);\n }\n\n /** Replace the project's chord-symbol annotation stream (undoable). */\n annotateChords(chords: ReadonlyArray<ProjectChordSymbol>): void {\n this.native.annotateChords(chords);\n }\n\n /**\n * Add or update an opaque assist sidecar via an undoable edit.\n *\n * The descriptor form is the canonical API and matches the Node binding;\n * the positional form remains available for compatibility with the original\n * WASM facade.\n */\n setAssistSidecar(sidecar: ProjectAssistSidecarInput): void;\n setAssistSidecar(\n moduleId: string,\n schemaVersion: number,\n targetTrackId: number,\n regionStartPpq: number,\n regionEndPpq: number,\n payload: Uint8Array,\n ): void;\n setAssistSidecar(\n sidecarOrModuleId: ProjectAssistSidecarInput | string,\n schemaVersion?: number,\n targetTrackId?: number,\n regionStartPpq?: number,\n regionEndPpq?: number,\n payload?: Uint8Array,\n ): void {\n if (typeof sidecarOrModuleId === 'string') {\n if (\n schemaVersion === undefined ||\n targetTrackId === undefined ||\n regionStartPpq === undefined ||\n regionEndPpq === undefined ||\n payload === undefined\n ) {\n throw new TypeError('Project.setAssistSidecar: positional form requires six arguments');\n }\n this.native.setAssistSidecar(\n validateAssistSidecarModuleId(sidecarOrModuleId),\n validateAssistSidecarUint32(schemaVersion, 'schemaVersion'),\n validateAssistSidecarUint32(targetTrackId, 'targetTrackId'),\n validateAssistSidecarPpq(regionStartPpq, 'regionStartPpq'),\n validateAssistSidecarPpq(regionEndPpq, 'regionEndPpq'),\n validateAssistSidecarPayload(payload),\n );\n return;\n }\n\n if (\n sidecarOrModuleId === null ||\n typeof sidecarOrModuleId !== 'object' ||\n Array.isArray(sidecarOrModuleId)\n ) {\n throw new TypeError('Project.setAssistSidecar: expected a sidecar descriptor object');\n }\n const sidecar = sidecarOrModuleId;\n const moduleId = validateAssistSidecarModuleId(sidecar.moduleId);\n this.native.setAssistSidecar(\n moduleId,\n validateAssistSidecarUint32(sidecar.schemaVersion ?? 0, 'schemaVersion'),\n validateAssistSidecarUint32(sidecar.targetTrackId ?? 0, 'targetTrackId'),\n validateAssistSidecarPpq(sidecar.regionStartPpq ?? 0, 'regionStartPpq'),\n validateAssistSidecarPpq(sidecar.regionEndPpq ?? 0, 'regionEndPpq'),\n validateAssistSidecarPayload(sidecar.payload ?? new Uint8Array()),\n );\n }\n\n /** Number of assist sidecars currently stored on the project. */\n assistSidecarCount(): number {\n return this.native.assistSidecarCount();\n }\n\n /** Read one assist sidecar by stable project order. */\n getAssistSidecar(index: number): ProjectAssistSidecar {\n return this.native.getAssistSidecar(index);\n }\n\n /** Read every stored assist sidecar in the same order as the index getter. */\n assistSidecars(): ProjectAssistSidecar[] {\n const count = this.assistSidecarCount();\n return Array.from({ length: count }, (_, index) => this.getAssistSidecar(index));\n }\n\n /** Set the project's clip-overlap policy (SonareProjectOverlapPolicy ordinal). */\n setOverlapPolicy(policy: number): void {\n this.native.setOverlapPolicy(policy);\n }\n\n /** Read the project's clip-overlap policy (SonareProjectOverlapPolicy ordinal). */\n getOverlapPolicy(): number {\n return this.native.getOverlapPolicy();\n }\n\n /** Read the project sample rate in Hz. */\n getSampleRate(): number {\n return this.native.getSampleRate();\n }\n\n /** Replace the project's mixer scene from a scene JSON string. */\n setMixerSceneJson(sceneJson: string): void {\n this.native.setMixerSceneJson(sceneJson);\n }\n\n /**\n * Add or replace a marker. Pass `markerId` 0 to allocate a new id; returns the\n * stable marker id (the allocated id when 0 was passed).\n */\n setMarker(markerId: number, ppq: number, name: string): number {\n return this.native.setMarker(markerId, ppq, name);\n }\n\n /**\n * Add or replace a marker from a full {@link ProjectMarker}, including its\n * {@link MarkerKind} and (for key signatures) the key. Pass `id` 0 to allocate\n * a new id; returns the stable marker id.\n */\n setMarkerEx(marker: ProjectMarker): number {\n return this.native.setMarkerEx(marker);\n }\n\n /** Read a project marker by index (0-based, in stored order). */\n markerByIndex(index: number): ProjectMarker {\n return this.native.markerByIndex(index);\n }\n\n /** Read a stored project track by 0-based index. */\n trackByIndex(index: number): ProjectTrack {\n return this.native.trackByIndex(index);\n }\n /** Read a stored project clip by 0-based index. */\n clipByIndex(index: number): ProjectClip {\n return this.native.clipByIndex(index);\n }\n /** Read a stored project source by 0-based index. */\n sourceByIndex(index: number): ProjectSource {\n return this.native.sourceByIndex(index);\n }\n\n /** Number of markers in the project. */\n markerCount(): number {\n return this.native.markerCount();\n }\n\n /** Number of tracks in the project. */\n trackCount(): number {\n return this.native.trackCount();\n }\n\n /** Number of clips in the project. */\n clipCount(): number {\n return this.native.clipCount();\n }\n\n /** Number of audio sources registered on the project. */\n sourceCount(): number {\n return this.native.sourceCount();\n }\n\n /** Number of tempo-map segments on the project. */\n tempoSegmentCount(): number {\n return this.native.tempoSegmentCount();\n }\n\n /** Number of time-signature segments on the project. */\n timeSignatureCount(): number {\n return this.native.timeSignatureCount();\n }\n\n /** Replace the project's tempo map with the given segments. */\n setTempoSegments(segments: ReadonlyArray<ProjectTempoSegment>): void {\n this.native.setTempoSegments(segments);\n }\n\n /** Replace the project's time-signature map with the given segments. */\n setTimeSignatures(segments: ReadonlyArray<ProjectTimeSignatureSegment>): void {\n this.native.setTimeSignatures(segments);\n }\n\n /**\n * Compile diagnostics produced by the most recent bounce on this project\n * (e.g. MIDI clips rendering silently without a bound instrument). When no\n * bounce has run, the result is empty with `hasTimeline` set.\n */\n lastBounceCompileResult(): ProjectCompileResult {\n return this.native.lastBounceCompileResult();\n }\n\n /** Release the underlying WASM object. Safe to call only once. */\n delete(): void {\n this.native.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n","import { projectModule } from './project_internal';\nimport type { SynthEnumTables, SynthPatch } from './project_types';\n\n/**\n * Runtime ABI version of the flat project POD layout exposed by this WASM\n * build. Equals {@link EXPECTED_PROJECT_ABI_VERSION} when the arrangement\n * subsystem is compiled in. Mirrors the C-ABI `sonare_project_abi_version`.\n */\nexport function projectAbiVersion(): number {\n return projectModule().projectAbiVersion();\n}\n\n/**\n * NativeSynth preset catalog names (`'sine'`, `'saw-lead'`, `'e-piano'`,\n * `'drum-kit'`, ...). Use these to discover valid {@link SynthPatch} preset\n * names instead of hardcoding magic strings.\n */\nexport function synthPresetNames(): string[] {\n // Array.from re-roots embind's vector as a plain, structured-cloneable Array.\n return Array.from(projectModule().synthPresetNames());\n}\n\n/**\n * Fetch a named catalog preset as a {@link SynthPatch} (the preset name plus\n * the wrapper-section values), so hosts can inspect a preset and tweak fields\n * before binding it. A `\"va:\"` routing prefix is accepted; unknown names\n * throw.\n */\nexport function synthPresetPatch(name: string): SynthPatch {\n // embind returns a val::object whose constructor is not this realm's Object, so a\n // direct return is not structured-cloneable (breaks postMessage to a Worker).\n // Spreading into a fresh literal re-roots it as a plain Object; modRoutings is\n // already a plain member array.\n return { ...projectModule().synthPresetPatch(name) };\n}\n\nexport function synthEnumTables(): SynthEnumTables {\n return projectModule()._synthEnumTables();\n}\n\nexport function synthPatchRoundTripForTest(patch: SynthPatch): SynthPatch {\n return projectModule()._synthPatchRoundTrip(patch);\n}\n","import type { Project } from './project_class';\n\n// ============================================================================\n// Headless DAW Project\n// ============================================================================\n\n/**\n * Expected project ABI version. Mirrors `SONARE_PROJECT_ABI_VERSION` in\n * `src/sonare_c_project.h`; checked against {@link projectAbiVersion} to detect\n * a WASM build whose flat project POD layout has drifted from this wrapper.\n */\nexport const EXPECTED_PROJECT_ABI_VERSION = 1;\n\n/** Render options for {@link Project.bounce}. All fields are optional. */\nexport interface ProjectBounceOptions {\n /** Render length in frames at the output sample rate. */\n totalFrames?: number;\n /** Render block size; <= 0 uses the engine default (128). */\n blockSize?: number;\n /** Output channel count; <= 0 uses the default (2). */\n numChannels?: number;\n /** Output sample rate; <= 0 uses the project sample rate. */\n sampleRate?: number;\n /** Host-instrument PDC (latency) fed to the compiler. */\n instrumentLatencySamples?: number;\n}\n\n/** One decoded output from a host-owned source-separation model. */\nexport interface ExternalSeparatedStem {\n name: string;\n /** Optional host metadata; it does not change DSP. */\n role?: string;\n layout: 'mono' | 'stereo' | 1 | 2;\n planarSamples: Float32Array[];\n /** Absolute project-rate frame at which this stem begins. */\n startFrame?: number;\n}\n\n/** Request for {@link Project.importExternalStems}. */\nexport interface ExternalSeparatedStemImportRequest {\n sampleRate: number;\n stems: ExternalSeparatedStem[];\n}\n\n/** Ids of the normal tracks and clips created by the import. */\nexport interface ExternalSeparatedStemImportResult {\n trackIds: number[];\n clipIds: number[];\n}\n\n/**\n * Marker kind ordinals. Mirrors `SonareMarkerKind` in `src/sonare_c_types.h`;\n * the values are part of the ABI and must not be renumbered.\n */\nexport const MarkerKind = {\n marker: 0,\n text: 1,\n lyric: 2,\n cuePoint: 3,\n keySignature: 4,\n} as const;\n\n/** A project timeline marker with its kind and (for key signatures) the key. */\nexport interface ProjectMarker {\n /** Stable marker id (0 when allocating a new id via {@link Project.setMarkerEx}). */\n id: number;\n /** Marker position in PPQ (quarter notes). */\n ppq: number;\n /** Marker label. */\n name?: string;\n /** {@link MarkerKind} ordinal (default 0 = marker). */\n kind?: number;\n /** Key signature only: -7..7 (sharps positive). */\n keyFifths?: number;\n /** Key signature only: false = major, true = minor. */\n keyMinor?: boolean;\n}\n\n/** Read-only stored project track returned by {@link Project.trackByIndex}. */\nexport interface ProjectTrack {\n id: number;\n kind: number;\n midiDestinationId: number;\n gain: number;\n pan: number;\n mute: boolean;\n solo: boolean;\n name: string;\n}\n\n/** Read-only stored project clip returned by {@link Project.clipByIndex}. */\nexport interface ProjectClip {\n id: number;\n trackId: number;\n sourceId: number;\n sourceKind: number;\n startPpq: number;\n lengthPpq: number;\n sourceOffsetPpq: number;\n gain: number;\n loopMode: number;\n loopLengthPpq: number;\n}\n\n/** Read-only stored project source returned by {@link Project.sourceByIndex}. */\nexport interface ProjectSource {\n id: number;\n kind: number;\n channelCount: number;\n storageHandleId: number;\n sampleRateHint: number;\n nameOrUri: string;\n /** Owning content hash for audio sources; empty for MIDI sources. */\n contentHash: string;\n /** External source-separation role for audio sources; empty for MIDI sources. */\n externalStemRole: string;\n}\n\n/** Names accepted by the minimal built-in oscillator synth. */\nexport const BUILTIN_SYNTH_WAVEFORMS = ['sine', 'saw', 'sawtooth', 'square', 'triangle'] as const;\n\n/** Oscillator waveform for the built-in synth. */\nexport type BuiltinSynthWaveform = (typeof BUILTIN_SYNTH_WAVEFORMS)[number] | 0 | 1 | 2 | 3;\n\n/**\n * Built-in synth patch + MIDI routing for\n * {@link Project.bounceWithBuiltinInstrument}. Every field is optional; a\n * non-positive (or omitted) numeric field falls back to the C-ABI default\n * (gain 0.2, attack 5ms, decay 60ms, sustain 0.7, release 120ms, 16 voices),\n * so `{}` is a usable default sine patch.\n */\nexport interface BuiltinSynthBinding {\n /** MIDI destination id this patch answers to (default 0; see {@link Project.setTrackMidiDestination}). */\n destinationId?: number;\n /** Oscillator waveform (default `'sine'`). */\n waveform?: BuiltinSynthWaveform;\n /** Master output gain, linear (0 => 0.2). */\n gain?: number;\n /** ADSR attack in ms (0 => 5). */\n attackMs?: number;\n /** ADSR decay in ms (0 => 60). */\n decayMs?: number;\n /** ADSR sustain level [0,1] (0 => 0.7). */\n sustain?: number;\n /** ADSR release in ms (0 => 120). */\n releaseMs?: number;\n /** Max simultaneous voices (0 => 16, clamped to [1, 64]). */\n polyphony?: number;\n}\n\n/**\n * Cross-binding alias of {@link BuiltinSynthBinding}. The same built-in-synth\n * patch concept is named `BuiltinSynthConfig` in the Python binding; this alias\n * lets portable code use that shared name on the WASM surface too.\n */\nexport type BuiltinSynthConfig = BuiltinSynthBinding;\n\n/**\n * SoundFont (SF2) player patch + MIDI routing for\n * {@link Project.bounceWithSf2Instrument}. Every field is optional; a\n * non-positive (or omitted) numeric field falls back to the C-ABI default\n * (gain 0.5, 48 voices), so `{}` is a usable default patch.\n */\nexport interface Sf2InstrumentConfig {\n /** MIDI destination id this player answers to (default 0; see {@link Project.setTrackMidiDestination}). */\n destinationId?: number;\n /** Master output gain, linear (0 => 0.5). */\n gain?: number;\n /** Max simultaneous voices (0 => 48, clamped to [1, 64]). */\n polyphony?: number;\n /** Prefer dedicated physical models for covered melodic GM programs. Defaults to false; drums stay SF2-first. */\n preferModelForModeledFamilies?: boolean;\n}\n\n/** Source backend a resolved MIDI program renders through. */\nexport type SourceBackend = 'sf2' | 'synth';\n\n/**\n * One {@link Project.soundFontManifest} entry: a (channel, bank, program)\n * combination the arrangement plays, with the backend it resolves to.\n */\nexport interface Sf2ProgramStatus {\n /** MIDI channel (0-15). */\n channel: number;\n /** Effective SF2 bank (drum channels report 128). */\n bank: number;\n /** Program number (0-127). */\n program: number;\n /** `'sf2'` when the loaded SoundFont covers the program, else `'synth'`. */\n backend: SourceBackend;\n /** Resolved SF2 preset name (GS fallback included); empty for `'synth'`. */\n presetName: string;\n}\n\nexport const SYNTH_ENGINE_MODES = [\n 'default',\n 'subtractive',\n 'fm',\n 'karplus-strong',\n 'modal',\n 'additive',\n 'percussion',\n 'piano',\n 'pipe-organ',\n 'bowed-string',\n 'reed',\n 'brass',\n 'flute',\n 'plucked-string',\n 'vocal',\n 'free-reed',\n] as const;\nexport const SYNTH_OSC_WAVEFORMS = [\n 'default',\n 'sine',\n 'saw',\n 'square',\n 'triangle',\n 'noise',\n] as const;\nexport const SYNTH_FILTER_MODELS = [\n 'default',\n 'svf',\n 'moog-ladder',\n 'diode-ladder',\n 'sallen-key',\n] as const;\nexport const SYNTH_FILTER_OUTPUTS = ['default', 'lowpass', 'bandpass', 'highpass'] as const;\nexport const SYNTH_BODY_TYPES = [\n 'default',\n 'none',\n 'guitar',\n 'violin',\n 'wood-tube',\n 'brass-bell',\n 'vocal',\n] as const;\nexport const SYNTH_MOD_SOURCES = [\n 'none',\n 'amp-env',\n 'filter-env',\n 'lfo1',\n 'lfo2',\n 'velocity',\n 'key-track',\n 'mod-wheel',\n 'random',\n] as const;\nexport const SYNTH_MOD_DESTINATIONS = [\n 'none',\n 'pitch-cents',\n 'cutoff-cents',\n 'amp-gain',\n 'pan-units',\n] as const;\n\nexport interface SynthEnumTables {\n engineModes: string[];\n waveforms: string[];\n builtinWaveforms: string[];\n filterModels: string[];\n filterOutputs: string[];\n bodyTypes: string[];\n modSources: string[];\n modDestinations: string[];\n}\n\n/** NativeSynth engine selector ({@link SynthPatch}; `'default'` keeps the base patch's). */\nexport type SynthEngineMode = (typeof SYNTH_ENGINE_MODES)[number];\n\n/** NativeSynth oscillator waveform (`'default'` keeps the base patch's). */\nexport type SynthOscWaveform = (typeof SYNTH_OSC_WAVEFORMS)[number];\n\n/** NativeSynth filter model — the character core (`'default'` keeps the base patch's). */\nexport type SynthFilterModel = (typeof SYNTH_FILTER_MODELS)[number];\n\n/** NativeSynth filter output (SVF only; `'default'` keeps the base patch's). */\nexport type SynthFilterOutput = (typeof SYNTH_FILTER_OUTPUTS)[number];\n\n/** NativeSynth body/formant resonance voicing (`'default'` keeps the base patch's). */\nexport type SynthBodyType = (typeof SYNTH_BODY_TYPES)[number];\n\n/** {@link SynthPatch} mod-matrix source. */\nexport type SynthModSource = (typeof SYNTH_MOD_SOURCES)[number];\n\n/** {@link SynthPatch} mod-matrix destination. */\nexport type SynthModDestination = (typeof SYNTH_MOD_DESTINATIONS)[number];\n\n/** One {@link SynthPatch} mod-matrix routing (name or C ordinal per field). */\nexport interface SynthModRouting {\n source: SynthModSource | number;\n destination: SynthModDestination | number;\n /** Destination units at full source deflection. */\n depth: number;\n}\n\n/**\n * Versioned NativeSynth patch for {@link Project.bounceWithSynthInstrument}\n * and {@link RealtimeEngine.setSynthInstrument}.\n *\n * The patch starts from a BASE — the named `preset` (see\n * {@link synthPresetNames}; a `\"va:\"` routing prefix is accepted) or, when\n * `preset` is omitted, the default subtractive patch. Omitting a numeric field\n * keeps the base value; supplying one overrides it (clamped to its audible\n * range), including an explicit `0` such as `stereoSpread: 0`. The enum fields\n * reserve `'default'` as keep. A `modRoutings` array REPLACES the base mod\n * matrix, and an empty array clears it, while omitting the key keeps it.\n *\n * Mode-specific deep parameters (FM operator stacks, modal mode tables,\n * drawbar registrations, kit pieces, piano strings) travel inside the named\n * presets; the patch exposes the wrapper sections every engine shares.\n */\nexport interface SynthPatch {\n /**\n * Optional binding convenience for JS realtime/offline helpers. It is not\n * part of the NativeSynth patch itself; Python uses explicit\n * `(destination_id, patch)` bindings instead. Defaults to `0`.\n */\n destinationId?: number;\n /** Resolve MIDI channels from incoming GM bank/program changes; defaults to false. */\n useGmPrograms?: boolean;\n /** Base preset name (see {@link synthPresetNames}); omit for the init patch. */\n preset?: string;\n engineMode?: SynthEngineMode | number;\n waveform?: SynthOscWaveform | number;\n /** Detuned-stack width [1, 7]. */\n unison?: number;\n detuneCents?: number;\n /** Per-voice slow pitch drift depth (cents). */\n driftCents?: number;\n /** Pre-filter drive [0, 1]. */\n drive?: number;\n filterModel?: SynthFilterModel | number;\n filterOutput?: SynthFilterOutput | number;\n cutoffHz?: number;\n resonanceQ?: number;\n /** Cutoff keyboard tracking [0, 1]. */\n keyTrack?: number;\n envToCutoffCents?: number;\n velToCutoffCents?: number;\n ampAttackMs?: number;\n ampDecayMs?: number;\n ampSustain?: number;\n ampReleaseMs?: number;\n filterAttackMs?: number;\n filterDecayMs?: number;\n filterSustain?: number;\n filterReleaseMs?: number;\n lfoRateHz?: number;\n lfoToPitchCents?: number;\n lfo2RateHz?: number;\n glideMs?: number;\n body?: SynthBodyType | number;\n /** Body resonance mix [0, 1]. */\n bodyMix?: number;\n /** Seeded per-voice pan scatter [0, 1]. */\n stereoSpread?: number;\n /** Mod matrix (at most 8 routings; REPLACES the base matrix when non-empty). */\n modRoutings?: SynthModRouting[];\n /** Master output gain (linear). */\n gain?: number;\n /** Max simultaneous voices [1, 64]. */\n polyphony?: number;\n /** Gain-neutral bus saturation [0, 1]. */\n busDrive?: number;\n}\n\n/** Clip fade-curve for {@link Project.setClipFade}. */\nexport type ProjectFadeCurve =\n | 'linear'\n | 'equal-power'\n | 'equal_power'\n | 'equalPower'\n | 'equalpower'\n | 'exponential'\n | 'exp'\n | 'logarithmic'\n | 'log'\n | 0\n | 1\n | 2\n | 3;\n\n/** One clip fade region for {@link Project.setClipFade}. */\nexport interface ProjectClipFade {\n /** Fade length in PPQ (>= 0; 0 = no fade). */\n lengthPpq?: number;\n /** Fade curve (default `'linear'`). */\n curve?: ProjectFadeCurve;\n}\n\n/** One alternate take for {@link Project.setClipTakes}. */\nexport interface ProjectClipTake {\n id: number;\n sourceId?: number;\n sourceOffsetPpq?: number;\n name?: string;\n}\n\n/** One comp segment for {@link Project.setClipCompSegments}. */\nexport interface ProjectClipCompSegment {\n startPpq: number;\n endPpq: number;\n takeId?: number;\n}\n\n/** Descriptor for {@link Project.addLoopRecordingTakes}. */\nexport interface ProjectLoopRecordingDesc {\n trackId: number;\n startPpq?: number;\n loopLengthPpq: number;\n audio: Float32Array;\n audioChannels?: number;\n audioSampleRate?: number;\n}\n\n/** Result returned by {@link Project.addLoopRecordingTakes}. */\nexport interface ProjectLoopRecordingResult {\n clipId: number;\n takeCount: number;\n}\n\n/** Clip loop mode for {@link Project.setClipLoop}. */\nexport type ProjectLoopMode = 'off' | 'loop' | 0 | 1;\nexport type ProjectWarpMode = 'off' | 'repitch' | 'tempo-sync' | 0 | 1 | 2;\n\n/**\n * Automation breakpoint interpolation for {@link ProjectAutomationPoint}.\n *\n * `'s-curve'` is the canonical spelling, matching the Node engine and the mixer\n * automation types. The legacy `'scurve'` remains accepted for compatibility.\n */\nexport type ProjectAutomationCurve =\n | 'linear'\n | 'exponential'\n | 'hold'\n | 's-curve'\n | 'scurve'\n | 0\n | 1\n | 2\n | 3;\n\n/** One automation breakpoint accepted by the automation-lane edit ops. */\nexport interface ProjectAutomationPoint {\n /** Breakpoint position in PPQ. */\n ppq: number;\n /** Breakpoint value. */\n value: number;\n /** Curve to the next breakpoint (default `'linear'`). */\n curve?: ProjectAutomationCurve;\n}\n\n/**\n * Persistent target classification for an automation lane.\n *\n * The numeric ordinals mirror `SonareAutomationTargetKind`; the string names\n * are the public WASM spellings accepted by the project facade.\n */\nexport const AutomationTargetKind = {\n opaque: 0,\n trackFaderDb: 1,\n trackPan: 2,\n} as const;\n\n/** Accepted automation target kind name or ABI ordinal. */\nexport type ProjectAutomationTargetKind = 'opaque' | 'track-fader-db' | 'track-pan' | 0 | 1 | 2;\n\n/** Numeric aliases matching the C-ABI enum names. */\nexport const PROJECT_AUTOMATION_TARGET_OPAQUE = AutomationTargetKind.opaque;\nexport const PROJECT_AUTOMATION_TARGET_TRACK_FADER_DB = AutomationTargetKind.trackFaderDb;\nexport const PROJECT_AUTOMATION_TARGET_TRACK_PAN = AutomationTargetKind.trackPan;\n\n/** Automation-lane descriptor for {@link Project.addAutomationLane}. */\nexport interface ProjectAutomationLaneDesc {\n /** Host-defined, non-zero id of the parameter the lane drives (zero is reserved). */\n targetParamId: number;\n /** Breakpoints (stored verbatim). */\n points: ReadonlyArray<ProjectAutomationPoint>;\n /** Optional persistent target classification; omission retains the legacy opaque route. */\n targetKind?: ProjectAutomationTargetKind;\n}\n\n/** One tempo segment for {@link Project.setTempoSegments}. */\nexport interface ProjectTempoSegment {\n /** Segment start in PPQ. */\n startPpq: number;\n /** Tempo in beats per minute at the segment start. */\n bpm: number;\n /** Derived segment start in samples. Accepted for compatibility, ignored on input. */\n startSample?: number;\n /** Optional ramp end tempo in BPM (0 = constant tempo over the segment). */\n endBpm?: number;\n}\n\n/** One time-signature segment for {@link Project.setTimeSignatures}. */\nexport interface ProjectTimeSignatureSegment {\n /** Segment start in PPQ. */\n startPpq: number;\n /** Beats per bar (time-signature numerator). */\n numerator: number;\n /** Beat unit (time-signature denominator, e.g. 4 or 8). */\n denominator: number;\n}\n\n/** A ranked primary/half/double tempo hypothesis returned by {@link Project.analyzeTempo}. */\nexport interface ProjectTempoCandidate {\n bpm: number;\n confidence: number;\n label: 'primary' | 'half' | 'double';\n timeSignatureCount: number;\n timeSignature: ProjectTimeSignatureSegment;\n}\n\n/** Key segment for {@link Project.annotateKeys}. */\nexport interface ProjectKeySegment {\n startPpq: number;\n endPpq: number;\n /** Tonic pitch class 0..11 (C=0) or 255 for unknown. */\n tonicPc?: number;\n /** KeyMode ordinal (0 unknown, 1 major, 2 minor, 3 dorian, ...). */\n mode?: number;\n}\n\n/** Chord symbol for {@link Project.annotateChords}. */\nexport interface ProjectChordSymbol {\n startPpq: number;\n endPpq: number;\n /** Root pitch class 0..11 (C=0) or 255 for unknown. */\n rootPc?: number;\n /** ChordQuality ordinal (0 unknown, 1 major, 2 minor, ...). */\n quality?: number;\n /** Extension semitone offsets (up to 8). */\n extensions?: ReadonlyArray<number>;\n /** Slash-bass pitch class 0..11 or 255 for none. */\n slashBassPc?: number;\n /** Optional roman-numeral label. */\n romanNumeral?: string;\n /** True at a modulation boundary. */\n modulationBoundary?: boolean;\n}\n\n/** Descriptor accepted by {@link Project.setAssistSidecar}. */\nexport interface ProjectAssistSidecarInput {\n /** Non-empty module id key. */\n moduleId: string;\n /** Module-defined schema version. Defaults to `0`. */\n schemaVersion?: number;\n /** Target track id (`0` = project scope). Defaults to `0`. */\n targetTrackId?: number;\n /** Region start in PPQ. Defaults to `0`. */\n regionStartPpq?: number;\n /** Region end in PPQ. Defaults to `0`. */\n regionEndPpq?: number;\n /** Opaque module-owned payload bytes. Defaults to an empty payload. */\n payload?: Uint8Array;\n}\n\n/** Assist sidecar snapshot returned by {@link Project.getAssistSidecar}. */\nexport interface ProjectAssistSidecar {\n moduleId: string;\n schemaVersion: number;\n targetTrackId: number;\n regionStartPpq: number;\n regionEndPpq: number;\n payload: Uint8Array;\n}\n\n/** Track kind for {@link Project.addTrack}. */\nexport type ProjectTrackKind = 'audio' | 'midi' | 'aux' | 0 | 1 | 2;\n\n/** Descriptor for {@link Project.addTrack}. */\nexport interface ProjectTrackDesc {\n kind?: ProjectTrackKind;\n name?: string;\n}\n\nexport interface ProjectWarpAnchor {\n warpSample: number;\n sourceSample: number;\n}\n\nexport interface ProjectWarpMapDesc {\n id: number;\n name?: string;\n anchors: ProjectWarpAnchor[];\n}\n\n/** Descriptor for {@link Project.addClip}. */\nexport interface ProjectClipDesc {\n trackId: number;\n isMidi?: boolean;\n startPpq?: number;\n lengthPpq: number;\n sourceOffsetPpq?: number;\n gain?: number;\n audio?: Float32Array;\n audioChannels?: number;\n audioSampleRate?: number;\n sourceUri?: string;\n}\n\n/** Result returned by {@link Project.addMidiClip}. */\nexport interface ProjectMidiClipResult {\n trackId: number;\n clipId: number;\n}\n\n/** Flat MIDI event accepted by {@link Project.setMidiEvents}. */\nexport interface ProjectMidiEvent {\n ppq: number;\n data0: number;\n data1?: number;\n}\n\n/** Options for {@link Project.midiRouteEvents}. `null`/omitted filter fields mean any/no remap. */\nexport interface ProjectMidiRouteConfig {\n filterGroup?: number | null;\n filterChannel?: number | null;\n remapChannel?: number | null;\n thru?: boolean;\n}\n\n/** Result of {@link Project.midiRouteEvents}. */\nexport interface ProjectMidiRouteResult {\n events: ProjectMidiEvent[];\n overflowed: boolean;\n overflowCount: number;\n}\n\nexport type ProjectMidiCcBindingKind = 0 | 1 | 2 | 3;\n\n/** Options for {@link Project.midiCcLearn}. All fields are optional. */\nexport interface MidiCcLearnOptions {\n /** Lower end of the mapped parameter range. Default `0`. */\n minValue?: number;\n /** Upper end of the mapped parameter range. Default `1`. */\n maxValue?: number;\n /** Minimum normalized CC movement required to learn a binding. Default `0`. */\n minMovement?: number;\n}\n\n/** MIDI CC <-> automation binding descriptor used by CC learn/conversion helpers. */\nexport interface ProjectMidiCcBinding {\n ccNumber: number;\n /** MIDI channel 0..15, or 255 for any channel. */\n channel: number;\n /** 0 = 7-bit CC, 1 = 14-bit CC, 2 = RPN, 3 = NRPN. */\n kind: ProjectMidiCcBindingKind;\n ccLsbNumber?: number;\n selectorMsb?: number;\n selectorLsb?: number;\n paramId: number;\n minValue: number;\n maxValue: number;\n}\n\n/** Result of {@link Project.validateMidiNotes}. */\nexport interface ProjectNotePairValidation {\n /** True when every note-on has a matching note-off (and vice versa). */\n ok: boolean;\n /** Count of note-ons that never received a matching note-off. */\n unmatchedNoteOns: number;\n /** Count of note-offs with no preceding matching note-on. */\n unmatchedNoteOffs: number;\n}\n\n/** One compile diagnostic (mirrors SonareProjectDiagnostic). */\nexport interface ProjectDiagnostic {\n code: number;\n /** 0 = error, 1 = warning. */\n severity: number;\n /** Affected clip / track / source id (0 = n/a). */\n targetId: number;\n /** Human-readable message for this diagnostic. */\n message: string;\n}\n\n/** Diagnostics summary returned by {@link Project.compile}. */\nexport interface ProjectCompileResult {\n /** Number of diagnostics surfaced by the compile. Kept for backward compatibility. */\n diagnosticCount: number;\n /** True when compilation produced a renderable timeline (no error diagnostics). */\n hasTimeline: boolean;\n /** Newline-joined human-readable detail of every diagnostic. */\n messages: string;\n diagnostics: ProjectDiagnostic[];\n}\n\nexport interface ProjectDeserializeResult {\n project: Project;\n diagnostics: string;\n}\n","import { panLawCode, panModeCode, sendTimingCode, trackMonitorModeCode } from './codes';\nimport { ErrorCode, SonareError } from './errors';\nimport { getSonareModule } from './module_state';\nimport type { ProjectMidiCcBinding, SynthPatch } from './project';\nimport type { EqBand, PanLawInput, PanMode, SendTiming } from './public_types';\nimport type {\n WasmClipPageRequest,\n WasmEngineAutomationPoint,\n WasmEngineBounceOptions,\n WasmEngineBounceResult,\n WasmEngineCaptureStatus,\n WasmEngineClip,\n WasmEngineFreezeOptions,\n WasmEngineFreezeResult,\n WasmEngineGraphSpec,\n WasmEngineMarker,\n WasmEngineMeterTelemetry,\n WasmEngineMeterTelemetryWide,\n WasmEngineMetronomeConfig,\n WasmEngineParameterInfo,\n WasmEngineProcessWithMonitorResult,\n WasmEngineScopeTelemetry,\n WasmEngineTelemetry,\n WasmEngineTempoSegment,\n WasmEngineTimeSignatureSegment,\n WasmEngineTransportState,\n WasmExternalMidiEvent,\n WasmRealtimeEngine,\n} from './sonare.js';\n\nexport type ExternalMidiEvent = WasmExternalMidiEvent;\n\nexport type EngineClip = WasmEngineClip;\nexport type ClipPageRequest = WasmClipPageRequest;\nexport type EngineParameterInfo = WasmEngineParameterInfo;\nexport type EngineAutomationPoint = WasmEngineAutomationPoint;\nexport type EngineMarker = WasmEngineMarker;\nexport type EngineMetronomeConfig = WasmEngineMetronomeConfig;\nexport type EngineGraphSpec = WasmEngineGraphSpec;\nexport type EngineCaptureStatus = WasmEngineCaptureStatus;\nexport type EngineCaptureSource = EngineCaptureStatus['source'] | number;\nexport type EngineBounceOptions = WasmEngineBounceOptions;\nexport type EngineBounceResult = WasmEngineBounceResult;\nexport type EngineFreezeOptions = WasmEngineFreezeOptions;\nexport type EngineFreezeResult = WasmEngineFreezeResult;\nexport type EngineTelemetry = WasmEngineTelemetry;\nexport type EngineMeterTelemetry = WasmEngineMeterTelemetry;\nexport type EngineMeterTelemetryWide = WasmEngineMeterTelemetryWide;\nexport type EngineScopeTelemetry = WasmEngineScopeTelemetry;\nexport type EngineTransportState = WasmEngineTransportState;\nexport type EngineTempoSegment = WasmEngineTempoSegment;\nexport type EngineTimeSignatureSegment = WasmEngineTimeSignatureSegment;\n\nexport interface EngineTrackSend {\n busId: number;\n levelDb?: number;\n enabled?: boolean;\n /**\n * Pre/post-fader tap point. Defaults to post-fader when omitted, matching the\n * historical lane-send behavior and the scene-JSON default.\n */\n sendTiming?: SendTiming | number;\n}\n\nexport interface EngineTrackLane {\n trackId: number;\n sends?: EngineTrackSend[];\n /**\n * Bus the lane's post-fader output sums into instead of the master mix\n * (group/folder routing); 0 or absent keeps the lane on the master mix.\n */\n outputBusId?: number;\n /**\n * Input channel layout of the source feeding this lane (`SonareChannelLayout`:\n * 0 mono, 1 stereo, 2 5.1, 3 7.1). Absent defaults to stereo. Stored but inert\n * until the surround DSP path lands.\n */\n sourceChannelLayout?: number;\n}\n\n/** Per-track cue/monitor tap mode: off, pre-fader listen, or after-fader listen. */\nexport type EngineTrackMonitorMode = 'off' | 'pfl' | 'afl' | 0 | 1 | 2;\n\n/** Short alias for {@link EngineTrackMonitorMode}. */\nexport type TrackMonitorMode = EngineTrackMonitorMode;\n\nexport interface EngineBus {\n busId: number;\n gainDb?: number;\n /**\n * Channel layout of the bus (`SonareChannelLayout`: 0 mono, 1 stereo, 2 5.1,\n * 3 7.1). A surround layout makes this a surround group bus: lanes routed to\n * it are surround-panned and it sums into the master plane-by-plane. Defaults\n * to stereo.\n */\n channelLayout?: number;\n}\n\nexport interface EngineMidiEvent {\n renderFrame: number;\n word0?: number;\n word1?: number;\n word2?: number;\n word3?: number;\n wordCount?: number;\n group?: number;\n sysexHandle?: number;\n data0?: number;\n data1?: number;\n}\n\nexport interface EngineMidiClipSchedule {\n id?: number;\n trackId?: number;\n destinationId?: number;\n startSample?: number;\n startPpq?: number;\n lengthSamples?: number;\n loop?: boolean;\n loopLengthSamples?: number;\n events: EngineMidiEvent[];\n}\n\nexport const EXPECTED_ENGINE_ABI_VERSION = 3;\n\n/** Options for {@link RealtimeEngine.bindMidiCc}. All fields are optional. */\nexport interface MidiCcBindOptions {\n /** Lower end of the mapped parameter range. Default `0`. */\n minValue?: number;\n /** Upper end of the mapped parameter range. Default `1`. */\n maxValue?: number;\n}\n\nexport interface EngineCapabilities {\n engineAbiVersion: number;\n expectedEngineAbiVersion: number;\n abiCompatible: boolean;\n sharedArrayBuffer: boolean;\n atomics: boolean;\n audioWorklet: boolean;\n mode: 'sab' | 'postMessage';\n}\n\nexport function engineCapabilities(): EngineCapabilities {\n const abiVersion = getSonareModule().engineAbiVersion();\n const sharedArrayBuffer = typeof globalThis.SharedArrayBuffer === 'function';\n const atomics = typeof globalThis.Atomics === 'object';\n const audioWorklet =\n typeof AudioWorkletNode !== 'undefined' ||\n typeof (globalThis as typeof globalThis & { AudioWorkletProcessor?: unknown })\n .AudioWorkletProcessor !== 'undefined';\n return {\n engineAbiVersion: abiVersion,\n expectedEngineAbiVersion: EXPECTED_ENGINE_ABI_VERSION,\n abiCompatible: abiVersion === EXPECTED_ENGINE_ABI_VERSION,\n sharedArrayBuffer,\n atomics,\n audioWorklet,\n mode: sharedArrayBuffer && atomics ? 'sab' : 'postMessage',\n };\n}\n\nexport class RealtimeEngine {\n private native: WasmRealtimeEngine;\n\n constructor(\n sampleRate = 48000,\n maxBlockSize = 128,\n commandCapacity = 1024,\n telemetryCapacity = 1024,\n maxChannels = 64,\n ) {\n const module = getSonareModule();\n const capabilities = engineCapabilities();\n if (!capabilities.abiCompatible) {\n throw new Error(\n `Engine ABI mismatch: wasm=${capabilities.engineAbiVersion}, expected=${capabilities.expectedEngineAbiVersion}`,\n );\n }\n this.native = new module.RealtimeEngine(\n sampleRate,\n maxBlockSize,\n commandCapacity,\n telemetryCapacity,\n maxChannels,\n );\n }\n\n prepare(\n sampleRate: number,\n maxBlockSize: number,\n commandCapacity = 1024,\n telemetryCapacity = 1024,\n maxChannels = 64,\n ): void {\n this.native.prepareWithChannels(\n sampleRate,\n maxBlockSize,\n commandCapacity,\n telemetryCapacity,\n maxChannels,\n );\n }\n\n /** Queue a sample-accurate parameter change (engine kSetParam). */\n setParameter(paramId: number, value: number, renderFrame = -1): void {\n this.native.setParameter(paramId, value, renderFrame);\n }\n\n /** Queue a smoothed parameter change (engine kSetParamSmoothed). */\n setParameterSmoothed(paramId: number, value: number, renderFrame = -1): void {\n this.native.setParameterSmoothed(paramId, value, renderFrame);\n }\n\n /**\n * Set the default ramp time (ms) for engine-level smoothed parameters —\n * fader/pan glides, insert-parameter automation, and MIDI-CC mappings. The\n * default is 20 ms; pass `0` for instant (un-ramped) changes.\n */\n setParamSmoothingMs(smoothingMs: number): void {\n this.native.setParamSmoothingMs(smoothingMs);\n }\n\n setSoloMute(laneIndex: number, solo: boolean, mute: boolean, renderFrame = -1): void {\n this.native.setSoloMute(laneIndex, solo, mute, renderFrame);\n }\n\n /** Queue a per-track PFL/AFL monitor tap mode change. */\n setTrackMonitorMode(laneIndex: number, mode: EngineTrackMonitorMode, renderFrame = -1): void {\n this.native.setTrackMonitorMode(laneIndex, trackMonitorModeCode(mode), renderFrame);\n }\n\n setMidiClips(clips: readonly EngineMidiClipSchedule[]): void {\n this.native.setMidiClips(clips);\n }\n\n setBuiltinInstrument(\n config: { destinationId?: number } & Record<string, unknown> = {},\n destinationId = config.destinationId ?? 0,\n ): void {\n this.native.setBuiltinInstrument(destinationId, config);\n }\n\n /**\n * Bind the patch-driven NativeSynth to a realtime MIDI destination. `patch`\n * is a {@link SynthPatch} or a preset-name string (`'saw-lead'` /\n * `'va:saw-lead'`; see {@link synthPresetNames}), resolving exactly like\n * {@link Project.bounceWithSynthInstrument}. Live note/CC commands and\n * scheduled MIDI clips routed to that destination render through the synth.\n * Unknown preset names throw. An object patch's `destinationId` is a JS\n * binding convenience, not part of the NativeSynth patch itself.\n */\n setSynthInstrument(\n patch: SynthPatch | string = {},\n destinationId = (typeof patch === 'object' ? patch.destinationId : undefined) ?? 0,\n ): void {\n this.native.setSynthInstrument(destinationId, patch);\n }\n\n /**\n * Load (parse) SoundFont 2 bytes into the engine so SF2 instruments can be\n * bound with {@link setSf2Instrument}. The host fetches the `.sf2` and\n * passes the raw bytes; they are copied into linear memory for the call and\n * not referenced afterwards. Replaces any previously loaded SoundFont.\n */\n loadSoundFont(data: Uint8Array): void {\n this.native.loadSoundFont(data);\n }\n\n /**\n * Bind a GS-compatible SoundFont player to a realtime MIDI destination, fed\n * by the engine's loaded SoundFont ({@link loadSoundFont}). Live note/CC\n * commands and scheduled MIDI clips routed to that destination render\n * through the player (16 MIDI channels, channel 10 drums, GS NRPN part\n * edits, GS/GM SysEx resets). Without a loaded SoundFont — or for programs\n * the SoundFont does not cover — notes play through the built-in\n * synthesizer GM fallback bank (the data-free floor).\n */\n setSf2Instrument(\n config: {\n destinationId?: number;\n gain?: number;\n polyphony?: number;\n preferModelForModeledFamilies?: boolean;\n } = {},\n destinationId = config.destinationId ?? 0,\n ): void {\n this.native.setSf2Instrument(destinationId, config);\n }\n\n clearMidiInstrument(destinationId = 0): void {\n this.native.clearMidiInstrument(destinationId);\n }\n\n midiInstrumentCount(): number {\n return this.native.midiInstrumentCount();\n }\n\n /**\n * Bind a live MIDI CC to an engine automation parameter. The MIDI event still\n * reaches the destination instrument; when bound, its 7-bit value is also\n * mapped into [minValue, maxValue] for `paramId`.\n */\n bindMidiCc(\n channel: number,\n controller: number,\n paramId: number,\n options: MidiCcBindOptions = {},\n ): void {\n this.native.bindMidiCc(\n channel,\n controller,\n paramId,\n options.minValue ?? 0,\n options.maxValue ?? 1,\n );\n }\n\n /** Bind a 7/14-bit CC, RPN, or NRPN descriptor to a live parameter. */\n bindMidiCcBinding(binding: ProjectMidiCcBinding): void {\n this.native.bindMidiCcBinding(binding);\n }\n\n clearMidiCcBindings(): void {\n this.native.clearMidiCcBindings();\n }\n\n midiCcBindingCount(): number {\n return this.native.midiCcBindingCount();\n }\n\n /** Install/replace a live non-destructive MIDI-FX insert for one destination. */\n setMidiFx(destinationId: number, configJson: string): void {\n this.native.setMidiFx(destinationId, configJson);\n }\n\n clearMidiFx(destinationId = 0): void {\n this.native.clearMidiFx(destinationId);\n }\n\n /** Enable the engine-owned live MIDI input source for a destination. */\n setMidiInputSource(destinationId = 0): void {\n this.native.setMidiInputSource(destinationId);\n }\n\n clearMidiInputSource(): void {\n this.native.clearMidiInputSource();\n }\n\n midiInputPendingCount(): number {\n return this.native.midiInputPendingCount();\n }\n\n /**\n * Route a destination's (track lane's) MIDI to the external output queue\n * instead of the internal instrument rack, so the track plays an external\n * device. Clearing it restores internal-synth playback.\n */\n setMidiDestinationExternal(destinationId: number, external: boolean): void {\n this.native.setMidiDestinationExternal(destinationId, external);\n }\n\n /**\n * Enable/disable forwarding MIDI clock + transport (start/continue/stop) to\n * the external output queue so external gear tracks the transport tempo.\n */\n setExternalMidiClockEnabled(enabled: boolean): void {\n this.native.setExternalMidiClockEnabled(enabled);\n }\n\n /** Count of external-MIDI events dropped because the output queue was full. */\n externalMidiDroppedCount(): number {\n return this.native.externalMidiDroppedCount();\n }\n\n externalMidiPendingCount(): number {\n return this.native.externalMidiPendingCount();\n }\n\n /**\n * Drain queued external-MIDI events, already lowered to MIDI 1.0 byte\n * messages ready to write to a Web MIDI output port. Call once per audio\n * block / animation frame. `maxRecords` caps the number of output events\n * returned — the shared unit across every surface. Events past the cap stay\n * queued for the next call (lossless); call again to drain the rest.\n */\n drainExternalMidi(maxRecords = 1024): WasmExternalMidiEvent[] {\n return this.native.drainExternalMidi(maxRecords);\n }\n\n /** Scalar, allocation-free external-MIDI drain for AudioWorklet SAB output. */\n popExternalMidiToScratch(): boolean {\n return this.native.popExternalMidiToScratch();\n }\n\n externalMidiScratchDestinationId(): number {\n return this.native.externalMidiScratchDestinationId();\n }\n\n externalMidiScratchRenderFrame(): number {\n return this.native.externalMidiScratchRenderFrame();\n }\n\n externalMidiScratchByteWord(): number {\n return this.native.externalMidiScratchByteWord();\n }\n\n externalMidiScratchByteCount(): number {\n return this.native.externalMidiScratchByteCount();\n }\n\n consumeExternalMidiScratch(): void {\n this.native.consumeExternalMidiScratch();\n }\n\n pushMidiInputNoteOn(\n group: number,\n channel: number,\n note: number,\n velocity: number,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputNoteOn(group, channel, note, velocity, portTimeSamples);\n }\n\n pushMidiInputNoteOff(\n group: number,\n channel: number,\n note: number,\n velocity = 0,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputNoteOff(group, channel, note, velocity, portTimeSamples);\n }\n\n pushMidiInputCc(\n group: number,\n channel: number,\n controller: number,\n value: number,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputCc(group, channel, controller, value, portTimeSamples);\n }\n\n pushMidiNoteOn(\n destinationId: number,\n group: number,\n channel: number,\n note: number,\n velocity: number,\n renderFrame = -1,\n ): void {\n this.native.pushMidiNoteOn(destinationId, group, channel, note, velocity, renderFrame);\n }\n\n pushMidiNoteOff(\n destinationId: number,\n group: number,\n channel: number,\n note: number,\n velocity = 0,\n renderFrame = -1,\n ): void {\n this.native.pushMidiNoteOff(destinationId, group, channel, note, velocity, renderFrame);\n }\n\n /**\n * Queue an immediate (live) MIDI control change to a MIDI destination\n * (engine kMidiCcImmediate). `group`/`channel` are 0..15; `controller`/`value`\n * are 7-bit (0..127). `renderFrame` is the frame to fire at, or -1 for\n * immediate. Mirrors the Node/Python/C-ABI `pushMidiCc`.\n */\n pushMidiCc(\n destinationId: number,\n group: number,\n channel: number,\n controller: number,\n value: number,\n renderFrame = -1,\n ): void {\n this.native.pushMidiCc(destinationId, group, channel, controller, value, renderFrame);\n }\n\n /** Queue one immediate MIDI 1.0 channel-voice UMP word for a destination. */\n pushMidiUmp(destinationId: number, word0: number, renderFrame = -1): void {\n this.native.pushMidiUmp(destinationId, word0, renderFrame);\n }\n\n /**\n * Queue an immediate (live) MIDI SysEx frame to a MIDI destination. `data` is\n * the full message including the leading 0xF0 and trailing 0xF7 (1..512\n * bytes). `renderFrame` is the frame to fire at, or -1 for immediate. Mirrors\n * the Node/Python/C-ABI `pushMidiSysex`.\n */\n pushMidiSysex(destinationId: number, data: Uint8Array, renderFrame = -1): void {\n this.native.pushMidiSysex(destinationId, data, renderFrame);\n }\n\n /**\n * Queue a MIDI panic (all-notes-off) releasing every sounding note at\n * `renderFrame` (-1 = immediate). Mirrors the C-ABI `pushMidiPanic`.\n */\n pushMidiPanic(renderFrame = -1): void {\n this.native.pushMidiPanic(renderFrame);\n }\n\n /**\n * Remove all registered parameters (and their automation lanes). Control-thread\n * only; not realtime-safe. Mirrors the C-ABI `clearParameters`.\n */\n clearParameters(): void {\n this.native.clearParameters();\n }\n\n /** Read back the current transport state snapshot. */\n getTransportState(): EngineTransportState {\n return this.native.getTransportState();\n }\n\n play(renderFrame = -1): void {\n this.native.play(renderFrame);\n }\n\n stop(renderFrame = -1): void {\n this.native.stop(renderFrame);\n }\n\n seekSample(timelineSample: number, renderFrame = -1): void {\n this.native.seekSample(timelineSample, renderFrame);\n }\n\n /**\n * Snaps every in-flight parameter ramp (engine-level smoothed params, mixer\n * lane fader/pan/gate, bus gains) to its target value. Offline renders call\n * this after a priming process() block so the first audible block renders at\n * settled values instead of ramping in from defaults.\n */\n settleParameters(): void {\n this.native.settleParameters();\n }\n\n /** Drains queued commands on an offline/control-only engine immediately. */\n flushControlCommands(): void {\n this.native.flushControlCommands();\n }\n\n seekPpq(ppq: number, renderFrame = -1): void {\n this.native.seekPpq(ppq, renderFrame);\n }\n\n /** Set a finite tempo in the range (0, 100000] BPM. */\n setTempo(bpm: number): void {\n this.native.setTempo(bpm);\n }\n\n setTempoSegments(segments: readonly EngineTempoSegment[]): void {\n this.native.setTempoSegments([...segments]);\n }\n\n setTimeSignature(numerator: number, denominator: number): void {\n this.native.setTimeSignature(numerator, denominator);\n }\n\n setTimeSignatureSegments(segments: readonly EngineTimeSignatureSegment[]): void {\n this.native.setTimeSignatureSegments([...segments]);\n }\n\n sampleAtPpq(ppq: number): number {\n return Number(this.native.sampleAtPpq(ppq));\n }\n\n setLoop(startPpq: number, endPpq: number, enabled = true): void {\n this.native.setLoop(startPpq, endPpq, enabled);\n }\n\n addParameter(info: EngineParameterInfo): void {\n this.native.addParameter(info);\n }\n\n parameterCount(): number {\n return this.native.parameterCount();\n }\n\n parameterInfoByIndex(index: number): EngineParameterInfo {\n return this.native.parameterInfoByIndex(index);\n }\n\n parameterInfo(id: number): EngineParameterInfo {\n return this.native.parameterInfo(id);\n }\n\n setAutomationLane(paramId: number, points: EngineAutomationPoint[]): void {\n this.native.setAutomationLane(paramId, points);\n }\n\n automationLaneCount(): number {\n return this.native.automationLaneCount();\n }\n\n setMarkers(markers: EngineMarker[]): void {\n this.native.setMarkers(markers);\n }\n\n markerCount(): number {\n return this.native.markerCount();\n }\n\n markerByIndex(index: number): EngineMarker {\n return this.native.markerByIndex(index);\n }\n\n marker(id: number): EngineMarker {\n return this.native.marker(id);\n }\n\n seekMarker(markerId: number, renderFrame = -1): void {\n this.native.seekMarker(markerId, renderFrame);\n }\n\n setLoopFromMarkers(startMarkerId: number, endMarkerId: number): void {\n this.native.setLoopFromMarkers(startMarkerId, endMarkerId);\n }\n\n /** Set a metronome config; click lengths are limited to one second. */\n setMetronome(config: EngineMetronomeConfig): void {\n this.native.setMetronome(config);\n }\n\n metronome(): Required<EngineMetronomeConfig> {\n return this.native.metronome();\n }\n\n countInEndSample(startSample: number, bars: number): number {\n return Number(this.native.countInEndSample(startSample, bars));\n }\n\n setGraph(spec: EngineGraphSpec): void {\n this.native.setGraph(spec);\n }\n\n graphNodeCount(): number {\n return this.native.graphNodeCount();\n }\n\n graphConnectionCount(): number {\n return this.native.graphConnectionCount();\n }\n\n setClips(clips: EngineClip[]): void {\n this.native.setClips(\n clips.map((clip) => ({\n ...clip,\n pageProvider:\n typeof clip.pageProvider === 'object' && clip.pageProvider !== null\n ? clip.pageProvider.id\n : clip.pageProvider,\n })),\n );\n }\n\n /**\n * Returns the PCM generated for a tempo-sync clip by the control-thread\n * setter, or `null` when the clip did not require a tempo-sync bake.\n */\n prebakedClipChannels(clipId: number): Float32Array[] | null {\n return this.native.prebakedClipChannels(clipId);\n }\n\n clipCount(): number {\n return this.native.clipCount();\n }\n\n setTrackLanes(lanes: Array<number | EngineTrackLane>): void {\n this.native.setTrackLanes(\n lanes.map((lane) => {\n if (typeof lane === 'number') {\n return { trackId: lane };\n }\n if (!lane.sends) {\n return lane;\n }\n // Normalize each send's pre/post tap point to the integer the native\n // layer reads (defaults to post-fader when omitted).\n return {\n ...lane,\n sends: lane.sends.map((send) => ({\n ...send,\n // Post-fader (0) is the default for an omitted sendTiming.\n sendTiming: send.sendTiming === undefined ? 0 : sendTimingCode(send.sendTiming),\n })),\n };\n }),\n );\n }\n\n /**\n * Keys one insert of a lane strip from another lane's post-strip audio\n * (ducking/sidechainRouter inserts). sourceTrackId 0 removes the binding.\n */\n setLaneSidechain(trackId: number, insertIndex: number, sourceTrackId: number): void {\n this.native.setLaneSidechain(trackId, insertIndex, sourceTrackId);\n }\n\n setTrackBuses(buses: EngineBus[]): void {\n this.native.setTrackBuses(buses);\n }\n\n setBusStripJson(busId: number, sceneJson: string): void {\n try {\n JSON.parse(sceneJson);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'invalid bus strip JSON';\n throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);\n }\n this.native.setBusStripJson(busId, sceneJson);\n }\n\n setTrackStripJson(trackId: number, sceneJson: string): void {\n try {\n JSON.parse(sceneJson);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'invalid track strip JSON';\n throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);\n }\n this.native.setTrackStripJson(trackId, sceneJson);\n }\n\n setTrackStripEqBand(trackId: number, bandIndex: number, band: EqBand | string): void {\n this.native.setTrackStripEqBandJson(\n trackId,\n bandIndex,\n typeof band === 'string' ? band : JSON.stringify(band),\n );\n }\n\n setTrackStripEqBandJson(trackId: number, bandIndex: number, bandJson: string): void {\n this.native.setTrackStripEqBandJson(trackId, bandIndex, bandJson);\n }\n\n setTrackStripInsertBypassed(\n trackId: number,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n this.native.setTrackStripInsertBypassed(trackId, insertIndex, bypassed, resetOnBypass);\n }\n\n setMasterStripJson(sceneJson: string): void {\n try {\n JSON.parse(sceneJson);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'invalid master strip JSON';\n throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);\n }\n this.native.setMasterStripJson(sceneJson);\n }\n\n setMasterStripEqBand(bandIndex: number, band: EqBand | string): void {\n this.native.setMasterStripEqBandJson(\n bandIndex,\n typeof band === 'string' ? band : JSON.stringify(band),\n );\n }\n\n setMasterStripEqBandJson(bandIndex: number, bandJson: string): void {\n this.native.setMasterStripEqBandJson(bandIndex, bandJson);\n }\n\n setMasterStripInsertBypassed(\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n this.native.setMasterStripInsertBypassed(insertIndex, bypassed, resetOnBypass);\n }\n\n /**\n * Changes one track-strip insert parameter in realtime, addressed by the\n * processor's JSON-key parameter name (see {@link masteringInsertParamInfo}).\n * Applied at the next block head via the engine command queue; safe during\n * playback. Throws if the track, insert, or name is unknown, the param is not\n * realtime-safe, or the command queue is full.\n */\n setTrackStripInsertParamByName(\n trackId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n this.native.setTrackStripInsertParamByName(trackId, insertIndex, paramName, value);\n }\n\n /** Master-strip counterpart of {@link setTrackStripInsertParamByName}. */\n setMasterStripInsertParamByName(insertIndex: number, paramName: string, value: number): void {\n this.native.setMasterStripInsertParamByName(insertIndex, paramName, value);\n }\n\n /** Bus-strip counterpart of {@link setTrackStripInsertParamByName}. */\n setBusStripInsertParamByName(\n busId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n this.native.setBusStripInsertParamByName(busId, insertIndex, paramName, value);\n }\n\n /** Bus-strip counterpart of {@link setTrackStripInsertBypassed}. */\n setBusStripInsertBypassed(\n busId: number,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n this.native.setBusStripInsertBypassed(busId, insertIndex, bypassed, resetOnBypass);\n }\n\n /**\n * Resolves a track-lane insert parameter (by its JSON-key name) to the\n * reserved automation id usable with `setAutomationLane` / `setParameter`.\n * Returns `-1` when the track, insert, or name is unknown. (The Python binding\n * raises a `SonareError` for an unknown id where Node/WASM return the `-1`\n * sentinel.)\n */\n resolveTrackInsertAutomationId(trackId: number, insertIndex: number, paramName: string): number {\n return this.native.resolveTrackInsertAutomationId(trackId, insertIndex, paramName);\n }\n\n resolveMasterInsertAutomationId(insertIndex: number, paramName: string): number {\n return this.native.resolveMasterInsertAutomationId(insertIndex, paramName);\n }\n\n resolveBusInsertAutomationId(busId: number, insertIndex: number, paramName: string): number {\n return this.native.resolveBusInsertAutomationId(busId, insertIndex, paramName);\n }\n\n /** Sets a track lane strip's pan position in realtime (glitch-free). */\n setTrackStripPan(trackId: number, pan: number): void {\n this.native.setTrackStripPan(trackId, pan);\n }\n\n /** Sets a track lane strip's pan law in realtime. */\n setTrackStripPanLaw(trackId: number, panLaw: PanLawInput): void {\n this.native.setTrackStripPanLaw(trackId, panLawCode(panLaw));\n }\n\n /** Sets a track lane strip's pan mode in realtime. */\n setTrackStripPanMode(trackId: number, panMode: PanMode | number): void {\n this.native.setTrackStripPanMode(trackId, panModeCode(panMode));\n }\n\n /** Sets a track lane strip's dual-pan left/right positions in realtime. */\n setTrackStripDualPan(trackId: number, leftPan: number, rightPan: number): void {\n this.native.setTrackStripDualPan(trackId, leftPan, rightPan);\n }\n\n /**\n * Sets a track lane strip's inter-channel alignment delay (whole samples).\n * Adjusts strip latency, so PDC and reported graph latency are refreshed.\n */\n setTrackStripChannelDelaySamples(trackId: number, delaySamples: number): void {\n this.native.setTrackStripChannelDelaySamples(trackId, delaySamples);\n }\n\n createClipPageProvider(\n numChannels: number,\n numSamples: number,\n pageFrames: number,\n ): ClipPageProvider {\n const id = this.native.createClipPageProvider(numChannels, numSamples, pageFrames);\n return new ClipPageProvider(this, id);\n }\n\n supplyClipPage(providerId: number, pageIndex: number, channels: Float32Array[]): void {\n this.native.supplyClipPage(providerId, pageIndex, channels);\n }\n\n clearClipPage(providerId: number, pageIndex: number): void {\n this.native.clearClipPage(providerId, pageIndex);\n }\n\n destroyClipPageProvider(providerId: number): void {\n this.native.destroyClipPageProvider(providerId);\n }\n\n popClipPageRequest(): ClipPageRequest | null {\n return this.native.popClipPageRequest();\n }\n\n /**\n * Moves one native request into the binding's persistent scalar scratch.\n * This avoids creating an embind JS object in AudioWorklet process().\n */\n popClipPageRequestToScratch(): boolean {\n return this.native.popClipPageRequestToScratch();\n }\n\n clipPageRequestScratchClipId(): number {\n return this.native.clipPageRequestScratchClipId();\n }\n\n clipPageRequestScratchSample(): number {\n return this.native.clipPageRequestScratchSample();\n }\n\n /** Cumulative page misses dropped because the native bounded request queue was full. */\n clipPageRequestOverflowCount(): number {\n return this.native.clipPageRequestOverflowCount();\n }\n\n setCaptureBuffer(numChannels: number, capacityFrames: number): void {\n this.native.setCaptureBuffer(numChannels, capacityFrames);\n }\n\n armCapture(armed = true): void {\n this.native.armCapture(armed);\n }\n\n setCapturePunch(startSample: number, endSample: number, enabled = true): void {\n this.native.setCapturePunch(startSample, endSample, enabled);\n }\n\n setCaptureSource(source: EngineCaptureSource): void {\n this.native.setCaptureSource(source);\n }\n\n /** Positive values delay capture relative to the punch window. */\n setRecordOffsetSamples(offsetSamples: number): void {\n this.native.setRecordOffsetSamples(offsetSamples);\n }\n\n setInputMonitor(enabled: boolean, gain = 1): void {\n this.native.setInputMonitor(enabled, gain);\n }\n\n resetCapture(): void {\n this.native.resetCapture();\n }\n\n captureStatus(): EngineCaptureStatus {\n return this.native.captureStatus();\n }\n\n capturedAudio(): Float32Array[] {\n return this.native.capturedAudio();\n }\n\n /**\n * Renders in place, adding engine output to `channels`. Zero each plane first\n * when it contains no upstream input.\n */\n process(channels: Float32Array[]): Float32Array[] {\n return this.native.process(channels);\n }\n\n /**\n * Allocates persistent per-channel WASM-heap scratch for the zero-copy\n * `getChannelBuffer` / `processPrepared` realtime path. Call once (off the\n * audio thread) before driving `processPrepared` from an AudioWorklet so the\n * render callback never allocates on the C++/JS heap.\n */\n prepareChannels(numChannels: number, maxFrames: number): void {\n this.native.prepareChannels(numChannels, maxFrames);\n }\n\n /**\n * Returns a Float32Array view onto the persistent WASM-heap scratch for one\n * channel (valid for up to `numFrames`). Fill it, call `processPrepared`, then\n * read the same view back. Re-acquire after WASM memory growth.\n */\n getChannelBuffer(channel: number, numFrames: number): Float32Array {\n return this.native.getChannelBuffer(channel, numFrames);\n }\n\n /**\n * Runs the engine in place over the prepared per-channel scratch buffers.\n * Zero each active span first when it contains no upstream input.\n * Allocation-free: safe to call on the AudioWorklet render thread after\n * `prepareChannels`.\n */\n processPrepared(numFrames: number): void {\n this.native.processPrepared(numFrames);\n }\n\n processWithMonitor(channels: Float32Array[]): WasmEngineProcessWithMonitorResult {\n return this.native.processWithMonitor(channels);\n }\n\n renderOffline(channels: Float32Array[], blockSize = 128): Float32Array[] {\n return this.native.renderOffline(channels, blockSize);\n }\n\n bounceOffline(options: EngineBounceOptions): EngineBounceResult {\n return this.native.bounceOffline(options);\n }\n\n freezeOffline(options: EngineFreezeOptions): EngineFreezeResult {\n return this.native.freezeOffline(options);\n }\n\n drainTelemetry(maxRecords = 1024): EngineTelemetry[] {\n return this.native.drainTelemetry(maxRecords);\n }\n\n popTelemetryToScratch(): boolean {\n return this.native.popTelemetryToScratch();\n }\n\n telemetryScratchType(): number {\n return this.native.telemetryScratchType();\n }\n\n telemetryScratchError(): number {\n return this.native.telemetryScratchError();\n }\n\n telemetryScratchRenderFrame(): number {\n return Number(this.native.telemetryScratchRenderFrame());\n }\n\n telemetryScratchTimelineSample(): number {\n return Number(this.native.telemetryScratchTimelineSample());\n }\n\n telemetryScratchAudibleTimelineSample(): number {\n return Number(this.native.telemetryScratchAudibleTimelineSample());\n }\n\n telemetryScratchGraphLatencySamplesQ8(): number {\n return this.native.telemetryScratchGraphLatencySamplesQ8();\n }\n\n telemetryScratchValue(): number {\n return this.native.telemetryScratchValue();\n }\n\n popMeterTelemetryToScratch(): boolean {\n return this.native.popMeterTelemetryToScratch();\n }\n meterScratchTargetId(): number {\n return this.native.meterScratchTargetId();\n }\n meterScratchRenderFrame(): number {\n return Number(this.native.meterScratchRenderFrame());\n }\n meterScratchValue(field: number): number {\n return this.native.meterScratchValue(field);\n }\n\n drainMeterTelemetry(maxRecords = 1024): EngineMeterTelemetry[] {\n return this.native.drainMeterTelemetry(maxRecords);\n }\n\n /**\n * Drains pending meter telemetry as per-plane (wide) records for a surround\n * target. Use this for a surround mix target; {@link drainMeterTelemetry}\n * stays the stereo fast path. The two share one queue — call only one per\n * target. The live AudioWorklet path owns the queue via the stereo drain, so\n * this wide drain is for an offline (non-worklet) engine instance; per-plane\n * surround meters are not delivered over the live worklet meter ring.\n */\n drainMeterTelemetryWide(maxRecords = 1024): EngineMeterTelemetryWide[] {\n return this.native.drainMeterTelemetryWide(maxRecords);\n }\n\n /**\n * Enables per-target spectrum + vectorscope capture. @param intervalFrames is\n * the minimum render-frame gap between snapshots (0 disables). @param bandCount\n * is the FFT band resolution (1..64); changing it re-prepares the tap. Returns\n * the band count actually applied.\n */\n configureScopeTelemetry(intervalFrames: number, bandCount: number): number {\n return this.native.configureScopeTelemetry(intervalFrames, bandCount);\n }\n\n /** Drains pending spectrum + vectorscope snapshots (per mix target). */\n drainScopeTelemetry(maxRecords = 1024): EngineScopeTelemetry[] {\n return this.native.drainScopeTelemetry(maxRecords);\n }\n\n popScopeTelemetryToScratch(): boolean {\n return this.native.popScopeTelemetryToScratch();\n }\n scopeScratchTargetId(): number {\n return this.native.scopeScratchTargetId();\n }\n scopeScratchRenderFrame(): number {\n return Number(this.native.scopeScratchRenderFrame());\n }\n scopeScratchBandCount(): number {\n return this.native.scopeScratchBandCount();\n }\n scopeScratchBand(index: number): number {\n return this.native.scopeScratchBand(index);\n }\n scopeScratchPointCount(): number {\n return this.native.scopeScratchPointCount();\n }\n scopeScratchPointLeft(index: number): number {\n return this.native.scopeScratchPointLeft(index);\n }\n scopeScratchPointRight(index: number): number {\n return this.native.scopeScratchPointRight(index);\n }\n\n destroy(): void {\n this.native.delete();\n }\n}\n\nexport class ClipPageProvider {\n private disposed = false;\n\n constructor(\n private readonly engine: RealtimeEngine,\n readonly id: number,\n ) {}\n\n supply(pageIndex: number, channels: Float32Array[]): void {\n if (this.disposed) {\n throw new Error('ClipPageProvider is destroyed');\n }\n this.engine.supplyClipPage(this.id, pageIndex, channels);\n }\n\n clear(pageIndex: number): void {\n if (this.disposed) {\n return;\n }\n this.engine.clearClipPage(this.id, pageIndex);\n }\n\n destroy(): void {\n if (this.disposed) {\n return;\n }\n this.disposed = true;\n this.engine.destroyClipPageProvider(this.id);\n }\n}\n","import { getSonareModule } from './module_state';\nimport { assertFiniteScalar } from './validation';\n\n// ============================================================================\n// Editing — 12-TET scale quantizer\n// ============================================================================\n\n/**\n * Snap a MIDI value to the nearest pitch class enabled by `modeMask`.\n *\n * `modeMask` is a 12-bit mask. For natural C major use `0b101010110101`.\n * `referenceMidi` defaults to A4 (69) when passed as 0.\n */\nexport function scaleQuantizeMidi(\n root: number,\n modeMask: number,\n midi: number,\n referenceMidi = 0,\n): number {\n assertFiniteScalar('scaleQuantizeMidi', midi, 'midi');\n assertFiniteScalar('scaleQuantizeMidi', referenceMidi, 'referenceMidi');\n return getSonareModule().scaleQuantizeMidi(root, modeMask, midi, referenceMidi);\n}\n\nexport function scaleCorrectionSemitones(\n root: number,\n modeMask: number,\n midi: number,\n referenceMidi = 0,\n): number {\n assertFiniteScalar('scaleCorrectionSemitones', midi, 'midi');\n assertFiniteScalar('scaleCorrectionSemitones', referenceMidi, 'referenceMidi');\n return getSonareModule().scaleCorrectionSemitones(root, modeMask, midi, referenceMidi);\n}\n\nexport function scalePitchClassEnabled(\n root: number,\n modeMask: number,\n pitchClass: number,\n): boolean {\n return getSonareModule().scalePitchClassEnabled(root, modeMask, pitchClass);\n}\n","import { resolveOrdinalInRange } from './codes';\nimport { getSonareModule } from './module_state';\nimport type { ChordQuality, PitchClass } from './public_types';\nimport type { WasmStreamAnalyzer } from './sonare.js';\nimport type {\n AnalyzerStats,\n FrameBuffer,\n StreamConfig,\n StreamConfigDefaults,\n StreamFramesI16,\n StreamFramesU8,\n StreamQuantizeConfig,\n} from './stream_types';\n\n// ============================================================================\n// StreamAnalyzer Class\n// ============================================================================\n\nexport function streamAnalyzerConfigDefaults(): StreamConfigDefaults {\n return getSonareModule().streamAnalyzerConfigDefault();\n}\n\n/**\n * Real-time streaming audio analyzer.\n *\n * @example\n * ```typescript\n * import { init, StreamAnalyzer } from '@libraz/libsonare';\n *\n * await init();\n *\n * const analyzer = new StreamAnalyzer({ sampleRate: 44100 });\n *\n * // In audio processing callback\n * analyzer.process(samples);\n *\n * // Get current analysis state\n * const stats = analyzer.stats();\n * console.log('BPM:', stats.estimate.bpm);\n * console.log('Key:', stats.estimate.key);\n * console.log('Chord progression:', stats.estimate.chordProgression);\n * ```\n *\n * The native analyzer supports one serialized producer (`process`,\n * `processWithOffset`, or `finalize`) concurrently with one serialized consumer\n * (`availableFrames`, a `readFrames*` method, `stats`, `frameCount`, or\n * `currentTime`) when a threaded WASM host shares the native instance.\n * Publication is allocation-free release/acquire. `reset`, setters, and\n * deletion require both roles to be stopped. A full pending ring drops the\n * newly produced output frame while analysis totals keep advancing. Ordinary\n * browser builds remain single-threaded unless the host explicitly provisions\n * shared-memory worker support.\n */\nexport class StreamAnalyzer {\n private analyzer: WasmStreamAnalyzer;\n\n /**\n * Create a new StreamAnalyzer.\n *\n * @param config - Configuration options\n */\n constructor(config: StreamConfig = {}) {\n if (config.computeMagnitude) {\n throw new Error(\n 'computeMagnitude is not supported because magnitude frames are not exposed by StreamAnalyzer read paths.',\n );\n }\n if (\n config.outputFormat !== undefined &&\n (typeof config.outputFormat !== 'number' ||\n !Number.isFinite(config.outputFormat) ||\n !Number.isInteger(config.outputFormat) ||\n config.outputFormat !== 0)\n ) {\n throw new TypeError('outputFormat must be the integer 0 (Float32)');\n }\n const window =\n config.window === undefined\n ? undefined\n : resolveOrdinalInRange(config.window, 0, 3, 'stream analyzer window');\n const module = getSonareModule();\n const defaults = streamAnalyzerConfigDefaults();\n this.analyzer = new module.StreamAnalyzer(\n config.sampleRate ?? defaults.sampleRate,\n config.nFft ?? defaults.nFft,\n config.hopLength ?? defaults.hopLength,\n config.nMels ?? defaults.nMels,\n config.fmin ?? defaults.fmin,\n config.fmax ?? defaults.fmax,\n config.tuningRefHz ?? defaults.tuningRefHz,\n config.computeMagnitude ?? defaults.computeMagnitude,\n config.computeMel ?? defaults.computeMel,\n config.computeChroma ?? defaults.computeChroma,\n config.computeOnset ?? defaults.computeOnset,\n config.computeSpectral ?? defaults.computeSpectral,\n config.emitEveryNFrames ?? defaults.emitEveryNFrames,\n config.magnitudeDownsample ?? defaults.magnitudeDownsample,\n config.maxPendingFrames ?? defaults.maxPendingFrames,\n config.maxProgressionEntries ?? defaults.maxProgressionEntries,\n config.keyUpdateIntervalSec ?? defaults.keyUpdateIntervalSec,\n config.bpmUpdateIntervalSec ?? defaults.bpmUpdateIntervalSec,\n window ?? defaults.window,\n config.outputFormat ?? defaults.outputFormat,\n );\n }\n\n /**\n * Process audio samples.\n *\n * @param samples - Audio samples (mono, float32)\n */\n process(samples: Float32Array): void {\n this.analyzer.process(samples);\n }\n\n /**\n * Process audio samples with a contiguous explicit sample offset. A gap,\n * seek, or switch from `process()` requires `reset()` first.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleOffset - Cumulative sample count at start of this chunk\n */\n processWithOffset(samples: Float32Array, sampleOffset: number): void {\n this.analyzer.processWithOffset(samples, sampleOffset);\n }\n\n /**\n * Drain any high-rate resampler tail, then zero-pad the final partial frame.\n */\n finalize(): void {\n this.analyzer.finalize();\n }\n\n /**\n * Get the number of frames available to read.\n */\n availableFrames(): number {\n return this.analyzer.availableFrames();\n }\n\n /**\n * Read processed frames as Structure of Arrays.\n *\n * @param maxFrames - Maximum number of frames to read\n * @returns Frame buffer with analysis results\n */\n readFrames(maxFrames: number): FrameBuffer {\n return this.analyzer.readFramesSoa(maxFrames);\n }\n\n /**\n * Read frames as uint8-quantized arrays.\n *\n * @param maxFrames - Maximum number of frames to read\n * @param quantizeConfig - Optional quantization ranges; widen these for a\n * stream louder or quieter than the defaults (omitted keeps the defaults)\n */\n readFramesU8(maxFrames: number, quantizeConfig?: StreamQuantizeConfig): StreamFramesU8 {\n return this.analyzer.readFramesU8(maxFrames, quantizeConfig) as StreamFramesU8;\n }\n\n /**\n * Read frames as int16-quantized arrays.\n *\n * @param maxFrames - Maximum number of frames to read\n * @param quantizeConfig - Optional quantization ranges; widen these for a\n * stream louder or quieter than the defaults (omitted keeps the defaults)\n */\n readFramesI16(maxFrames: number, quantizeConfig?: StreamQuantizeConfig): StreamFramesI16 {\n return this.analyzer.readFramesI16(maxFrames, quantizeConfig) as StreamFramesI16;\n }\n\n /**\n * Reset the analyzer state.\n *\n * @param baseSampleOffset - Starting sample offset (default 0)\n */\n reset(baseSampleOffset = 0): void {\n this.analyzer.reset(baseSampleOffset);\n }\n\n /**\n * Get current statistics and progressive estimates.\n *\n * @returns Analyzer statistics including BPM, key, and chord progression\n */\n stats(): AnalyzerStats {\n const s = this.analyzer.stats();\n return {\n totalFrames: s.totalFrames,\n totalSamples: s.totalSamples,\n durationSeconds: s.durationSeconds,\n pendingFrames: s.pendingFrames,\n droppedOutputFrames: s.droppedOutputFrames,\n droppedChordProgressionEntries: s.droppedChordProgressionEntries,\n droppedBarProgressionEntries: s.droppedBarProgressionEntries,\n estimate: {\n bpm: s.estimate.bpm,\n bpmConfidence: s.estimate.bpmConfidence,\n bpmCandidateCount: s.estimate.bpmCandidateCount,\n key: s.estimate.key as PitchClass,\n keyMinor: s.estimate.keyMinor,\n keyConfidence: s.estimate.keyConfidence,\n chordRoot: s.estimate.chordRoot as PitchClass,\n chordQuality: s.estimate.chordQuality as ChordQuality,\n chordConfidence: s.estimate.chordConfidence,\n chordStartTime: s.estimate.chordStartTime,\n chordProgression: s.estimate.chordProgression.map((c) => ({\n root: c.root as PitchClass,\n quality: c.quality as ChordQuality,\n startTime: c.startTime,\n confidence: c.confidence,\n })),\n barChordProgression: s.estimate.barChordProgression.map((c) => ({\n barIndex: c.barIndex,\n root: c.root as PitchClass,\n quality: c.quality as ChordQuality,\n startTime: c.startTime,\n confidence: c.confidence,\n })),\n currentBar: s.estimate.currentBar,\n barDuration: s.estimate.barDuration,\n votedPattern: (s.estimate.votedPattern || []).map((c) => ({\n barIndex: c.barIndex,\n root: c.root as PitchClass,\n quality: c.quality as ChordQuality,\n startTime: c.startTime,\n confidence: c.confidence,\n })),\n patternLength: s.estimate.patternLength,\n detectedPatternName: s.estimate.detectedPatternName || '',\n detectedPatternScore: s.estimate.detectedPatternScore || 0,\n allPatternScores: (s.estimate.allPatternScores || []).map((p) => ({\n name: p.name,\n score: p.score,\n })),\n accumulatedSeconds: s.estimate.accumulatedSeconds,\n usedFrames: s.estimate.usedFrames,\n updated: s.estimate.updated,\n },\n };\n }\n\n /**\n * Get total frames processed.\n */\n frameCount(): number {\n return this.analyzer.frameCount();\n }\n\n /**\n * Get current time position in seconds.\n */\n currentTime(): number {\n return this.analyzer.currentTime();\n }\n\n /**\n * Get the sample rate.\n */\n sampleRate(): number {\n return this.analyzer.sampleRate();\n }\n\n /**\n * Set the expected total duration for pattern lock timing.\n *\n * @param durationSeconds - Total duration in seconds\n */\n setExpectedDuration(durationSeconds: number): void {\n this.analyzer.setExpectedDuration(durationSeconds);\n }\n\n /**\n * Set normalization gain for loud/compressed audio.\n *\n * @param gain - Gain factor to apply (e.g., 0.5 for -6dB reduction)\n */\n setNormalizationGain(gain: number): void {\n this.analyzer.setNormalizationGain(gain);\n }\n\n /**\n * Set tuning reference frequency for non-standard tuning.\n *\n * @param refHz - Reference frequency for A4 (default 440 Hz)\n * @example\n * // If audio is 1 semitone sharp (A4 = 466.16 Hz)\n * analyzer.setTuningRefHz(466.16);\n * // If audio is 1 semitone flat (A4 = 415.30 Hz)\n * analyzer.setTuningRefHz(415.30);\n */\n setTuningRefHz(refHz: number): void {\n this.analyzer.setTuningRefHz(refHz);\n }\n\n /** Release the underlying WASM object. Safe to call only once. */\n delete(): void {\n this.analyzer.delete();\n }\n\n /** Alias for {@link delete}, kept for backward compatibility (historical name). */\n dispose(): void {\n this.delete();\n }\n}\n","import {\n automationCurveCode,\n meterTapCode,\n panLawCode,\n panModeCode,\n sendTimingCode,\n} from './codes';\nimport { getSonareModule } from './module_state';\nimport type {\n AutomationCurve,\n GoniometerPoint,\n MeterTap,\n MixerProcessResult,\n MixMeterSnapshot,\n PanLawInput,\n PanMode,\n SendTiming,\n SurroundPan,\n} from './public_types';\n\nexport interface MixerRealtimeBuffer {\n leftInputs: Float32Array[];\n rightInputs: Float32Array[];\n outLeft: Float32Array;\n outRight: Float32Array;\n process: (numSamples?: number) => void;\n}\n\n// ============================================================================\n// Mixer Class (scene-based persistent mixer)\n// ============================================================================\n\n/**\n * Persistent, scene-based stereo mixer.\n *\n * Build one from a scene JSON string (e.g. {@link mixingScenePresetJson} or a\n * hand-authored scene), then feed per-strip stereo blocks through\n * {@link processStereo} to get the routed stereo master. Strips, sends, buses,\n * and inserts are described entirely by the scene; the routing graph is\n * compiled lazily on the first {@link processStereo} call (or eagerly via\n * {@link compile}).\n *\n * Call {@link delete} (or use a `try/finally`) to release the underlying WASM\n * object — the embind handle is not garbage-collected automatically.\n *\n * @example\n * ```typescript\n * const mixer = Mixer.fromSceneJson(mixingScenePresetJson('basicStereo'), 48000, 512);\n * try {\n * const out = mixer.processStereo([stripL], [stripR]);\n * } finally {\n * mixer.delete();\n * }\n * ```\n */\nexport class Mixer {\n private mixer: import('./sonare.js').WasmMixer;\n private readonly blockSize: number;\n\n private constructor(mixer: import('./sonare.js').WasmMixer, blockSize: number) {\n this.mixer = mixer;\n this.blockSize = blockSize;\n }\n\n /**\n * Build a mixer from a scene JSON string.\n *\n * @param json - Scene JSON (strips, buses, sends, connections, inserts)\n * @param sampleRate - Sample rate in Hz (default: 48000)\n * @param blockSize - Maximum block size per {@link processStereo} call (default: 512)\n */\n static fromSceneJson(json: string, sampleRate = 48000, blockSize = 512): Mixer {\n const module = getSonareModule();\n return new Mixer(module.createMixerFromSceneJson(json, sampleRate, blockSize), blockSize);\n }\n\n /**\n * Rebuild and compile the routing graph without resetting its absolute\n * automation sample position or queued strip automation.\n */\n compile(): void {\n this.mixer.compile();\n }\n\n /**\n * Non-fatal warnings captured when this mixer was built from scene JSON: one\n * entry per channel-strip insert that was handed param keys it does not read\n * (a likely typo, or a key meant for a different processor). The scene still\n * loaded; these keys simply took no effect. Empty when every key was consumed.\n * Use {@link masteringInsertParamNames} to discover the keys an insert accepts.\n */\n sceneWarnings(): string[] {\n return this.mixer.sceneWarnings();\n }\n\n /**\n * Mix one block of per-strip stereo audio into the stereo master.\n *\n * @param leftChannels - `leftChannels[i]` is the left channel of strip `i`\n * @param rightChannels - `rightChannels[i]` is the right channel of strip `i`\n * @returns Mixed stereo master (`left`, `right`, `sampleRate`)\n */\n processStereo(leftChannels: Float32Array[], rightChannels: Float32Array[]): MixerProcessResult {\n if (leftChannels.length !== rightChannels.length) {\n throw new Error('leftChannels and rightChannels must have the same length.');\n }\n return this.mixer.processStereo(leftChannels, rightChannels);\n }\n\n /**\n * Mix one block into caller-owned output arrays.\n *\n * This avoids allocating the result object and result `Float32Array`s. It is\n * intended for realtime bridges such as AudioWorklet; the input channel count\n * must match the scene strip count and all arrays must have the same length.\n */\n processStereoInto(\n leftChannels: Float32Array[],\n rightChannels: Float32Array[],\n outLeft: Float32Array,\n outRight: Float32Array,\n ): void {\n if (leftChannels.length !== rightChannels.length) {\n throw new Error('leftChannels and rightChannels must have the same length.');\n }\n if (outLeft.length !== outRight.length) {\n throw new Error('outLeft and outRight must have the same length.');\n }\n this.mixer.processStereoInto(leftChannels, rightChannels, outLeft, outRight);\n }\n\n /**\n * Create reusable WASM-heap input/output views for realtime-style processing.\n *\n * Fill `leftInputs[i]` / `rightInputs[i]`, call `process()`, then read\n * `outLeft` / `outRight`. The views are owned by this mixer and become invalid\n * after {@link delete}.\n */\n createRealtimeBuffer(): MixerRealtimeBuffer {\n const stripCount = this.stripCount();\n let leftInputs: Float32Array[] = [];\n let rightInputs: Float32Array[] = [];\n let outLeft = this.mixer.outputLeftView();\n let outRight = this.mixer.outputRightView();\n const acquire = (): void => {\n leftInputs = [];\n rightInputs = [];\n for (let index = 0; index < stripCount; index++) {\n leftInputs.push(this.mixer.inputLeftView(index));\n rightInputs.push(this.mixer.inputRightView(index));\n }\n outLeft = this.mixer.outputLeftView();\n outRight = this.mixer.outputRightView();\n };\n acquire();\n // The cached heap views can detach if WASM linear memory grows (the embind\n // module is built ALLOW_MEMORY_GROWTH). Re-acquire them if detached\n // (byteLength === 0) before use, mirroring the worklet RT path.\n const reacquireIfDetached = (): void => {\n if (outLeft.byteLength === 0 || (leftInputs[0]?.byteLength ?? 1) === 0) {\n acquire();\n }\n };\n return {\n get leftInputs(): Float32Array[] {\n reacquireIfDetached();\n return leftInputs;\n },\n get rightInputs(): Float32Array[] {\n reacquireIfDetached();\n return rightInputs;\n },\n get outLeft(): Float32Array {\n reacquireIfDetached();\n return outLeft;\n },\n get outRight(): Float32Array {\n reacquireIfDetached();\n return outRight;\n },\n process: (numSamples = outLeft.length) => {\n reacquireIfDetached();\n this.mixer.processPreparedStereo(numSamples);\n },\n };\n }\n\n /** Number of strips in the mixer (e.g. strips loaded from the scene). */\n stripCount(): number {\n return this.mixer.stripCount();\n }\n\n /**\n * Schedule sample-accurate insert-parameter automation on a strip's insert.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param insertIndex - Index into the strip's combined insert sequence\n * (`[pre-inserts... post-inserts...]`)\n * @param paramId - Processor-specific parameter id\n * @param samplePos - Absolute samples from the start of processing (the mixer\n * advances an internal position from 0 on the first {@link processStereo}\n * call; recompiling resets it to 0)\n * @param value - Target parameter value\n * @param curve - Interpolation curve (default: `'linear'`)\n * @throws If the strip index is out of range or the schedule call fails\n * (unknown curve, out-of-range insert index, or full event lane)\n */\n scheduleInsertAutomation(\n stripIndex: number,\n insertIndex: number,\n paramId: number,\n samplePos: number,\n value: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleInsertAutomation(\n stripIndex,\n insertIndex,\n paramId,\n samplePos,\n value,\n automationCurveCode(curve),\n );\n }\n\n /**\n * Resolve a strip's index in `[0, stripCount())` from its scene id, or `null`\n * when no strip with that id exists (matches the Node binding's `number | null`).\n */\n stripById(id: string): number | null {\n const index = this.mixer.stripById(id);\n return index < 0 ? null : index;\n }\n\n /**\n * Add a bus to the mixer topology. `role` is one of `'master'`, `'aux'`, or\n * `'submix'` (defaults to `'aux'`). Marks the routing graph dirty; call\n * {@link compile} (or {@link processStereo}) to rebuild.\n */\n addBus(id: string, role = 'aux'): void {\n this.mixer.addBus(id, role);\n }\n\n /** Remove a bus by id. Marks the routing graph dirty. */\n removeBus(id: string): void {\n this.mixer.removeBus(id);\n }\n\n /** Number of buses in the mixer topology. */\n busCount(): number {\n return this.mixer.busCount();\n }\n\n /**\n * Add a VCA group with the given gain offset (dB). `members` is a list of\n * strip ids governed by the group (may be empty).\n */\n addVcaGroup(id: string, gainDb = 0.0, members: string[] = []): void {\n this.mixer.addVcaGroup(id, gainDb, members);\n }\n\n /** Set an existing VCA group's gain in dB. */\n setVcaGroupGainDb(id: string, gainDb: number): void {\n this.mixer.setVcaGroupGainDb(id, gainDb);\n }\n\n /** Replace an existing VCA group's strip membership. */\n setVcaGroupMembers(id: string, members: string[]): void {\n this.mixer.setVcaGroupMembers(id, members);\n }\n\n /** Remove a VCA group by id. */\n removeVcaGroup(id: string): void {\n this.mixer.removeVcaGroup(id);\n }\n\n /** Number of VCA groups in the mixer topology. */\n vcaGroupCount(): number {\n return this.mixer.vcaGroupCount();\n }\n\n /** Set the strip's input trim in dB. */\n setInputTrimDb(stripIndex: number, db: number): void {\n this.mixer.setInputTrimDb(stripIndex, db);\n }\n\n /** Set the strip's fader level in dB. */\n setFaderDb(stripIndex: number, db: number): void {\n this.mixer.setFaderDb(stripIndex, db);\n }\n\n /**\n * Set the strip's pan position.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param pan - Pan position in `[-1, 1]`\n * @param panMode - Optional pan mode. When omitted the strip's current pan\n * mode is kept (passes `SONARE_PAN_MODE_KEEP`), so a plain pan nudge does\n * not reset a scene-defined `'stereoPan'` / `'dualPan'` mode back to\n * balance. Pass `'balance'` (or `0`) explicitly to force balance mode.\n */\n setPan(stripIndex: number, pan: number, panMode?: PanMode | number): void {\n // SONARE_PAN_MODE_KEEP (-1) = keep the strip's current pan mode.\n const mode = panMode === undefined ? -1 : panModeCode(panMode);\n this.mixer.setPan(stripIndex, pan, mode);\n }\n\n /** Set the strip's stereo width. */\n setWidth(stripIndex: number, width: number): void {\n this.mixer.setWidth(stripIndex, width);\n }\n\n /** Set the strip's mute state. */\n setMuted(stripIndex: number, muted: boolean): void {\n this.mixer.setMuted(stripIndex, muted);\n }\n\n /**\n * Set a strip's solo state. Takes effect on the next process without a\n * graph recompile.\n */\n setSoloed(stripIndex: number, soloed: boolean): void {\n this.mixer.setSoloed(stripIndex, soloed);\n }\n\n /**\n * Mark a strip solo-safe so it is never implied-muted by another strip's\n * solo. Takes effect on the next process without a graph recompile.\n */\n setSoloSafe(stripIndex: number, soloSafe: boolean): void {\n this.mixer.setSoloSafe(stripIndex, soloSafe);\n }\n\n /** Invert the polarity of the left and/or right channel of a strip. */\n setPolarityInvert(stripIndex: number, invertLeft: boolean, invertRight: boolean): void {\n this.mixer.setPolarityInvert(stripIndex, invertLeft, invertRight);\n }\n\n /** Set the strip's pan law (a {@link PanLawName} alias or raw C ABI ordinal). */\n setPanLaw(stripIndex: number, panLaw: PanLawInput): void {\n this.mixer.setPanLaw(stripIndex, panLawCode(panLaw));\n }\n\n /**\n * Set a per-strip channel delay in samples. This changes the strip's reported\n * latency; recompile to re-run latency compensation.\n */\n setChannelDelaySamples(stripIndex: number, delaySamples: number): void {\n this.mixer.setChannelDelaySamples(stripIndex, delaySamples);\n }\n\n /** Set the strip's live VCA gain offset in dB (not persisted to the scene). */\n setVcaOffsetDb(stripIndex: number, offsetDb: number): void {\n this.mixer.setVcaOffsetDb(stripIndex, offsetDb);\n }\n\n /** Set independent left/right pan positions (dual-pan mode). */\n setDualPan(stripIndex: number, leftPan: number, rightPan: number): void {\n this.mixer.setDualPan(stripIndex, leftPan, rightPan);\n }\n\n /**\n * Set the strip's surround pan position, used when it feeds a >2-channel bus.\n * Stored on the scene; inert until the surround DSP path applies it.\n */\n setSurroundPan(stripIndex: number, pan: SurroundPan): void {\n this.mixer.setSurroundPan(stripIndex, pan);\n }\n\n /**\n * Add a send to a strip after construction.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param id - Send id\n * @param destinationBusId - Destination bus id\n * @param sendDb - Initial send level in dB\n * @param timing - `'preFader'` or `'postFader'` (default: `'postFader'`)\n * @returns The new send's index\n */\n addSend(\n stripIndex: number,\n id: string,\n destinationBusId: string,\n sendDb = 0.0,\n timing: SendTiming | number = 'postFader',\n ): number {\n return this.mixer.addSend(stripIndex, id, destinationBusId, sendDb, sendTimingCode(timing));\n }\n\n /** Set the send level (in dB) for an existing send by index. */\n setSendDb(stripIndex: number, sendIndex: number, sendDb: number): void {\n this.mixer.setSendDb(stripIndex, sendIndex, sendDb);\n }\n\n /**\n * Remove an existing send from a strip by index.\n *\n * Sends are addressed in add order. After removal, sends with a higher index\n * than `sendIndex` shift down by one. Recompile (or process) before reading\n * results so the routing graph rebuilds.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param sendIndex - Send index in add order\n */\n removeSend(stripIndex: number, sendIndex: number): void {\n this.mixer.removeSend(stripIndex, sendIndex);\n }\n\n /**\n * Read a strip's meter snapshot at the given tap point.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param tap - `'preFader'` or `'postFader'` (default: `'postFader'`)\n */\n meterTap(stripIndex: number, tap: MeterTap = 'postFader'): MixMeterSnapshot {\n return this.mixer.meterTap(stripIndex, meterTapCode(tap));\n }\n\n /**\n * Read a strip's meter snapshot.\n *\n * With no `tap` argument this reads the strip's own (post-fader) meter,\n * matching the Node/Python tap-less `stripMeter` contract. Pass an optional\n * `tap` (`'preFader'` / `'postFader'`) to read the tap-selectable snapshot\n * instead — the same backing call as {@link meterTap}.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param tap - Optional tap point (`'preFader'` / `'postFader'`); when omitted\n * the tap-less post-fader strip meter is read.\n */\n stripMeter(stripIndex: number, tap?: MeterTap | number): MixMeterSnapshot {\n if (tap === undefined) {\n return this.mixer.stripMeter(stripIndex);\n }\n return this.mixer.meterTap(stripIndex, meterTapCode(tap));\n }\n\n /** Read the post-insert meter for a compiled bus, including master. */\n busMeter(busId: string): MixMeterSnapshot {\n return this.mixer.busMeter(busId);\n }\n\n /**\n * Schedule sample-accurate fader automation on a strip.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param samplePos - Absolute samples from the start of processing\n * @param faderDb - Target fader level in dB\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n scheduleFaderAutomation(\n stripIndex: number,\n samplePos: number,\n faderDb: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleFaderAutomation(stripIndex, samplePos, faderDb, automationCurveCode(curve));\n }\n\n /**\n * Schedule sample-accurate pan automation on a strip.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param samplePos - Absolute samples from the start of processing\n * @param pan - Target pan position\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n schedulePanAutomation(\n stripIndex: number,\n samplePos: number,\n pan: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.schedulePanAutomation(stripIndex, samplePos, pan, automationCurveCode(curve));\n }\n\n /**\n * Schedule sample-accurate width automation on a strip.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param samplePos - Absolute samples from the start of processing\n * @param width - Target stereo width\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n scheduleWidthAutomation(\n stripIndex: number,\n samplePos: number,\n width: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleWidthAutomation(stripIndex, samplePos, width, automationCurveCode(curve));\n }\n\n /**\n * Schedule sample-accurate send-level automation on a strip's send.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param sendIndex - Send index in the strip's add order\n * @param samplePos - Absolute samples from the start of processing\n * @param db - Target send level in dB\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n scheduleSendAutomation(\n stripIndex: number,\n sendIndex: number,\n samplePos: number,\n db: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleSendAutomation(\n stripIndex,\n sendIndex,\n samplePos,\n db,\n automationCurveCode(curve),\n );\n }\n\n /**\n * Read up to `maxPoints` of a strip's most recent goniometer samples\n * (oldest to newest).\n */\n readGoniometerLatest(stripIndex: number, maxPoints: number): GoniometerPoint[] {\n return this.mixer.readGoniometerLatest(stripIndex, maxPoints);\n }\n\n /** Serialize the current scene (strips, buses, sends, connections) to JSON. */\n toSceneJson(): string {\n return this.mixer.toSceneJson();\n }\n\n /**\n * Longest audible serial processor-tail path to the master, in samples. Lazily\n * compiles the routing graph if the topology is dirty.\n */\n tailSamples(): number {\n return this.mixer.tailSamples();\n }\n\n /**\n * Reported latency (samples) of the compiled mixer graph, for aligning\n * dry/wet material. Lazily compiles the routing graph if the topology is dirty.\n */\n latencySamples(): number {\n return this.mixer.latencySamples();\n }\n\n /**\n * Drain delayed / tail audio by processing a zero-input block of `numSamples`\n * frames after the host stops feeding strip inputs. Returns the mixed stereo\n * master (`left`, `right`, `sampleRate`).\n */\n drainTailStereo(numSamples: number): MixerProcessResult {\n if (!Number.isSafeInteger(numSamples) || numSamples <= 0 || numSamples > this.blockSize) {\n throw new RangeError(\n `Mixer.drainTailStereo: numSamples must be an integer in [1, ${this.blockSize}]`,\n );\n }\n return this.mixer.drainTailStereo(numSamples);\n }\n\n /** Release the underlying WASM object. Safe to call only once. */\n delete(): void {\n this.mixer.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n","import { getSonareModule } from './module_state';\nimport type {\n RealtimeVoiceChangerConfigInput,\n RealtimeVoiceChangerPodConfig,\n VoicePresetId,\n} from './public_types';\n\n/**\n * Zero-copy realtime buffer pair for {@link RealtimeVoiceChanger} mono\n * processing. The `input` / `output` `Float32Array`s are typed-memory views\n * onto the WASM heap — write samples into `input`, call `process()`, then\n * read from `output`. The views are owned by the {@link RealtimeVoiceChanger}\n * and remain valid until `delete()` is called on it.\n */\nexport interface RealtimeVoiceChangerMonoBuffer {\n input: Float32Array;\n output: Float32Array;\n process: () => void;\n}\n\n/**\n * Zero-copy realtime buffer pair for {@link RealtimeVoiceChanger} interleaved\n * multi-channel processing. Layout is L0,R0,L1,R1,... for stereo. The views\n * are owned by the {@link RealtimeVoiceChanger}.\n */\nexport interface RealtimeVoiceChangerInterleavedBuffer {\n input: Float32Array;\n output: Float32Array;\n channels: number;\n process: () => void;\n}\n\n/**\n * Zero-copy realtime buffer for {@link RealtimeVoiceChanger} planar stereo\n * processing. Each entry in `channels` is a heap-backed `Float32Array` for one\n * channel (matching AudioWorklet's native layout). Process happens in place:\n * write samples into each channel view, call `process()`, then read back from\n * the same views.\n */\nexport interface RealtimeVoiceChangerPlanarBuffer {\n channels: Float32Array[];\n process: () => void;\n}\n\n// ============================================================================\n// RealtimeVoiceChanger Class\n// ============================================================================\n\nexport class RealtimeVoiceChanger {\n private changer: import('./sonare.js').WasmRealtimeVoiceChanger;\n\n /**\n * Creates a voice changer. Supplying `sampleRate` prepares it immediately,\n * matching the Node and Python constructors; omitting it preserves the\n * explicit {@link prepare} lifecycle for callers that configure later.\n */\n constructor(\n config: RealtimeVoiceChangerConfigInput | RealtimeVoiceChangerPodConfig = 'neutral-monitor',\n sampleRate?: number,\n maxBlockSize = 128,\n channels = 1,\n ) {\n const module = getSonareModule();\n this.changer = module.createRealtimeVoiceChanger(config as Record<string, unknown> | string);\n if (sampleRate !== undefined) {\n this.changer.prepare(sampleRate, maxBlockSize, channels);\n }\n }\n\n prepare(sampleRate: number, maxBlockSize = 128, channels = 1): void {\n this.changer.prepare(sampleRate, maxBlockSize, channels);\n }\n\n reset(): void {\n this.changer.reset();\n }\n\n setConfig(config: RealtimeVoiceChangerConfigInput | RealtimeVoiceChangerPodConfig): void {\n // The shared native parser recognizes the flat POD produced by\n // realtimeVoiceChangerPresetConfig, so bindings never duplicate its 36-field mapping.\n this.changer.setConfig(config as Record<string, unknown> | string);\n }\n\n /**\n * Apply a flat, pre-normalized config without JSON serialization. Intended\n * for AudioWorklet control messages whose sender prepared the POD on the\n * main thread.\n */\n setPodConfig(config: RealtimeVoiceChangerPodConfig): void {\n this.changer.setPodConfig(config);\n }\n\n configJson(): string {\n return this.changer.configJson();\n }\n\n latencySamples(): number {\n return this.changer.latencySamples();\n }\n\n /**\n * Monotonically increases whenever {@link prepare} can replace the native\n * scratch buffers. Cached WASM heap views must be reacquired after it changes.\n */\n bufferGeneration(): number {\n return this.changer.bufferGeneration();\n }\n\n processMono(samples: Float32Array): Float32Array {\n return this.changer.processMono(samples);\n }\n\n processMonoInto(samples: Float32Array, output: Float32Array): void {\n this.changer.processMonoInto(samples, output);\n }\n\n processInterleaved(samples: Float32Array, channels: number): Float32Array {\n return this.changer.processInterleaved(samples, channels);\n }\n\n processInterleavedInto(samples: Float32Array, channels: number, output: Float32Array): void {\n this.changer.processInterleavedInto(samples, channels, output);\n }\n\n /**\n * Acquire a typed-memory view onto the WASM heap for mono input.\n *\n * Write your input samples into the returned `Float32Array` directly (e.g.\n * via `input.set(source)`); no copy crosses the JS↔C++ bridge until\n * {@link processPreparedMono} is called. The view is owned by this\n * RealtimeVoiceChanger and becomes invalid after {@link delete}; it may\n * also be invalidated if you later call this method with a larger\n * `numSamples` value (the underlying buffer may be reallocated).\n */\n getMonoInputBuffer(numSamples: number): Float32Array {\n return this.changer.getMonoInputBuffer(numSamples);\n }\n\n /** Mono output view counterpart to {@link getMonoInputBuffer}. */\n getMonoOutputBuffer(numSamples: number): Float32Array {\n return this.changer.getMonoOutputBuffer(numSamples);\n }\n\n /**\n * Process the previously-acquired mono input buffer in place. The output\n * appears in the buffer returned by {@link getMonoOutputBuffer}. No JS↔C++\n * sample-level crossings happen on this call — it just hands control to\n * the underlying DSP on already-on-heap data.\n */\n processPreparedMono(numSamples: number): void {\n this.changer.processPreparedMono(numSamples);\n }\n\n /** Interleaved input view (layout L0,R0,L1,R1,...). */\n getInterleavedInputBuffer(numFrames: number, numChannels: number): Float32Array {\n return this.changer.getInterleavedInputBuffer(numFrames, numChannels);\n }\n\n /** Interleaved output view counterpart. */\n getInterleavedOutputBuffer(numFrames: number, numChannels: number): Float32Array {\n return this.changer.getInterleavedOutputBuffer(numFrames, numChannels);\n }\n\n /**\n * Process the previously-acquired interleaved buffer in place. Output\n * appears in the buffer returned by {@link getInterleavedOutputBuffer}.\n */\n processPreparedInterleaved(numFrames: number, numChannels: number): void {\n this.changer.processPreparedInterleaved(numFrames, numChannels);\n }\n\n /**\n * Planar-channel input/output view (one Float32Array per channel). Matches\n * AudioWorklet's native layout; processing happens in place.\n */\n getPlanarChannelBuffer(channel: number, numFrames: number): Float32Array {\n return this.changer.getPlanarChannelBuffer(channel, numFrames);\n }\n\n /**\n * Process the previously-acquired planar channel buffers in place. Each\n * channel must have been obtained from {@link getPlanarChannelBuffer}\n * with the same `numFrames`. Output replaces input in the same buffers.\n */\n processPreparedPlanar(numFrames: number): void {\n this.changer.processPreparedPlanar(numFrames);\n }\n\n /**\n * Convenience factory for the mono zero-copy path: returns the input/output\n * heap views plus a `process()` thunk wired to the same `numSamples`. The\n * views are reused across calls and become invalid after {@link delete}.\n */\n createRealtimeMonoBuffer(numSamples: number): RealtimeVoiceChangerMonoBuffer {\n let input = this.getMonoInputBuffer(numSamples);\n let output = this.getMonoOutputBuffer(numSamples);\n let generation = this.bufferGeneration();\n // The cached heap views can detach if WASM linear memory grows (the embind\n // module is built ALLOW_MEMORY_GROWTH). Re-acquire them if detached\n // (byteLength === 0) before use, mirroring the worklet RT path. In the\n // common no-growth case this is a cheap branch with no allocation.\n const reacquireIfDetached = (): void => {\n if (\n generation !== this.bufferGeneration() ||\n input.byteLength === 0 ||\n output.byteLength === 0\n ) {\n input = this.getMonoInputBuffer(numSamples);\n output = this.getMonoOutputBuffer(numSamples);\n generation = this.bufferGeneration();\n }\n };\n return {\n get input(): Float32Array {\n reacquireIfDetached();\n return input;\n },\n get output(): Float32Array {\n reacquireIfDetached();\n return output;\n },\n process: () => {\n reacquireIfDetached();\n this.processPreparedMono(numSamples);\n },\n };\n }\n\n /** Same as {@link createRealtimeMonoBuffer} but for interleaved I/O. */\n createRealtimeInterleavedBuffer(\n numFrames: number,\n numChannels: number,\n ): RealtimeVoiceChangerInterleavedBuffer {\n let input = this.getInterleavedInputBuffer(numFrames, numChannels);\n let output = this.getInterleavedOutputBuffer(numFrames, numChannels);\n let generation = this.bufferGeneration();\n // Re-acquire detached views after WASM memory growth (see\n // createRealtimeMonoBuffer for rationale).\n const reacquireIfDetached = (): void => {\n if (\n generation !== this.bufferGeneration() ||\n input.byteLength === 0 ||\n output.byteLength === 0\n ) {\n input = this.getInterleavedInputBuffer(numFrames, numChannels);\n output = this.getInterleavedOutputBuffer(numFrames, numChannels);\n generation = this.bufferGeneration();\n }\n };\n return {\n get input(): Float32Array {\n reacquireIfDetached();\n return input;\n },\n get output(): Float32Array {\n reacquireIfDetached();\n return output;\n },\n channels: numChannels,\n process: () => {\n reacquireIfDetached();\n this.processPreparedInterleaved(numFrames, numChannels);\n },\n };\n }\n\n /**\n * Convenience factory for the planar zero-copy path. Acquires one\n * heap-backed Float32Array per channel and returns a `process()` thunk\n * wired to the same `numFrames`. Buffers are reused across calls and\n * become invalid after {@link delete}.\n */\n createRealtimePlanarBuffer(\n numFrames: number,\n numChannels: number,\n ): RealtimeVoiceChangerPlanarBuffer {\n let channels: Float32Array[] = [];\n let generation = this.bufferGeneration();\n const acquire = (): void => {\n channels = [];\n for (let ch = 0; ch < numChannels; ch++) {\n channels.push(this.getPlanarChannelBuffer(ch, numFrames));\n }\n generation = this.bufferGeneration();\n };\n acquire();\n // Re-acquire detached views after WASM memory growth (see\n // createRealtimeMonoBuffer for rationale).\n const reacquireIfDetached = (): void => {\n if (generation !== this.bufferGeneration() || (channels[0]?.byteLength ?? 0) === 0) {\n acquire();\n }\n };\n return {\n get channels(): Float32Array[] {\n reacquireIfDetached();\n return channels;\n },\n process: () => {\n reacquireIfDetached();\n this.processPreparedPlanar(numFrames);\n },\n };\n }\n\n delete(): void {\n this.changer.delete();\n }\n}\n\nexport function realtimeVoiceChangerPresetNames(): VoicePresetId[] {\n // Array.from re-roots embind's vector as a plain, structured-cloneable Array.\n return Array.from(getSonareModule().realtimeVoiceChangerPresetNames()) as VoicePresetId[];\n}\n\nexport function realtimeVoiceChangerPresetJson(name: VoicePresetId): string {\n return getSonareModule().realtimeVoiceChangerPresetJson(name);\n}\n\nexport function validateRealtimeVoiceChangerPresetJson(json: string): {\n ok: boolean;\n normalizedJson?: string;\n error?: string;\n} {\n return getSonareModule().validateRealtimeVoiceChangerPresetJson(json);\n}\n","import { flattenChainConfig } from './_chain_config';\nimport { getSonareModule } from './module_state';\nimport type {\n EqBand,\n EqMatchOptions,\n EqSpectrumSnapshot,\n StreamingEqualizerConfig,\n StreamingMasteringChainConfig,\n StreamingRetuneConfig,\n} from './public_types';\n\ntype EqPhaseMode =\n | 'zero'\n | 'zero-latency'\n | 'zero_latency'\n | 'natural'\n | 'natural-phase'\n | 'natural_phase'\n | 'linear'\n | 'linear-phase'\n | 'linear_phase'\n | number;\n\nconst EQ_PHASE_MODES: Record<string, number> = {\n zero: 1,\n 'zero-latency': 1,\n zero_latency: 1,\n natural: 2,\n 'natural-phase': 2,\n natural_phase: 2,\n linear: 3,\n 'linear-phase': 3,\n linear_phase: 3,\n};\n\n// ============================================================================\n// StreamingMasteringChain Class\n// ============================================================================\n\n/**\n * Block-by-block streaming variant of {@link masteringChain}.\n *\n * Maintains processor state across {@link processMono}/{@link processStereo}\n * calls. Only ProcessorBase-backed stages are supported. Configurations that\n * enable `repair.denoise` throw at construction. An enabled `loudness` stage\n * also throws unless {@link StreamingMasteringChainConfig.loudnessStaticGainDb}\n * supplies a precomputed normalization gain.\n *\n * Call {@link delete} (or use a `try/finally`) to release the underlying WASM\n * object — the embind handle is not garbage-collected automatically.\n *\n * @example\n * ```typescript\n * const chain = new StreamingMasteringChain({ eq: { tiltDb: 1.0 } });\n * try {\n * chain.prepare(44100, 512, 1);\n * const out = chain.processMono(blockSamples);\n * } finally {\n * chain.delete();\n * }\n * ```\n */\nexport class StreamingMasteringChain {\n private chain: import('./sonare.js').WasmStreamingMasteringChain;\n\n constructor(config: StreamingMasteringChainConfig) {\n const module = getSonareModule();\n const { loudnessStaticGainDb, loudnessStaticGainPeakDb, ...chainConfig } = config;\n this.chain = module.createStreamingMasteringChain({\n __flatParams: flattenChainConfig(chainConfig),\n loudnessStaticGainDb,\n loudnessStaticGainPeakDb,\n });\n }\n\n /**\n * Initialize processors for the given sample rate and block layout.\n *\n * @param sampleRate - Sample rate in Hz\n * @param maxBlockSize - Maximum block size per process call\n * @param numChannels - 1 (mono) or 2 (stereo)\n */\n prepare(sampleRate: number, maxBlockSize: number, numChannels: number): void {\n this.chain.prepare(sampleRate, maxBlockSize, numChannels);\n }\n\n /**\n * Process one mono block, returning the processed samples (same length).\n */\n processMono(samples: Float32Array): Float32Array {\n return this.chain.processMono(samples);\n }\n\n /**\n * Process one stereo block, returning the processed channels.\n */\n processStereo(\n left: Float32Array,\n right: Float32Array,\n ): { left: Float32Array; right: Float32Array } {\n if (left.length !== right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n return this.chain.processStereo(left, right);\n }\n\n /**\n * Emit delayed audio and finite processor tails after the final mono block.\n * Call until this returns an empty array. The initial `latencySamples()`\n * samples of the concatenated stream are delayed and should be discarded for\n * time-aligned output.\n */\n flushMono(): Float32Array {\n return this.chain.flushMono();\n }\n\n /** Stereo counterpart of {@link flushMono}. */\n flushStereo(): { left: Float32Array; right: Float32Array } {\n return this.chain.flushStereo();\n }\n\n /** Reset all processor state without rebuilding. */\n reset(): void {\n this.chain.reset();\n }\n\n /** Total reported latency in samples across all active processors. */\n latencySamples(): number {\n return this.chain.latencySamples();\n }\n\n /** Ordered stage names that will run (e.g. `\"eq.tilt\"`). */\n stageNames(): string[] {\n return this.chain.stageNames();\n }\n\n /** Release the underlying WASM object. Safe to call only once. */\n delete(): void {\n this.chain.delete();\n }\n}\n\n// ============================================================================\n// StreamingEqualizer Class\n// ============================================================================\n\n/**\n * Block-by-block streaming equalizer wrapping the unified C++\n * `EqualizerProcessor` (up to 24 bands, RBJ/Vicanek biquads, dynamic EQ,\n * linear-phase FIR, mid/side processing, and auto-gain).\n *\n * State is maintained across {@link processMono}/{@link processStereo} calls.\n * Call {@link delete} (or use `try/finally`) to release the underlying WASM\n * object — the embind handle is not garbage-collected automatically.\n *\n * @example\n * ```typescript\n * const eq = new StreamingEqualizer({ sampleRate: 48000, maxBlockSize: 512 });\n * try {\n * eq.setBand(0, { type: 'HighShelf', frequencyHz: 8000, gainDb: 6, enabled: true });\n * const out = eq.processStereo(left, right);\n * const snapshot = eq.spectrum();\n * } finally {\n * eq.delete();\n * }\n * ```\n */\nexport class StreamingEqualizer {\n private eq: import('./sonare.js').WasmStreamingEqualizer;\n\n constructor(config: StreamingEqualizerConfig = {}) {\n const module = getSonareModule();\n this.eq = module.createEqualizer(config as Record<string, unknown>);\n }\n\n /**\n * Configure the band at `index` (0..23). Omitted fields use C++ defaults.\n */\n setBand(index: number, band: EqBand): void {\n this.eq.setBand(index, band as Record<string, unknown>);\n }\n\n /** Disable and reset every band. */\n clear(): void {\n this.eq.clear();\n }\n\n /**\n * Set the global phase mode: `'zero'` | `'natural'` | `'linear'` or 1/2/3.\n */\n setPhaseMode(mode: EqPhaseMode): void {\n const value = typeof mode === 'number' ? mode : EQ_PHASE_MODES[mode.toLowerCase()];\n if (value === undefined) {\n throw new Error(`unknown EQ phase mode: ${mode}`);\n }\n this.eq.setPhaseMode(value);\n }\n\n /** Enable or disable output auto-gain compensation. */\n setAutoGain(enabled: boolean): void {\n this.eq.setAutoGain(enabled);\n }\n\n /** Set all-band EQ gain scale as a 0.0..2.0 multiplier. */\n setGainScale(scale: number): void {\n this.eq.setGainScale(scale);\n }\n\n /** Set post-EQ output gain in dB. */\n setOutputGainDb(gainDb: number): void {\n this.eq.setOutputGainDb(gainDb);\n }\n\n /** Set post-EQ stereo balance in -1.0..1.0; mono input ignores pan. */\n setOutputPan(pan: number): void {\n this.eq.setOutputPan(pan);\n }\n\n /**\n * Provide a mono external sidechain key for dynamic bands that opt into\n * `external_sidechain`. The samples are copied into an owned buffer.\n */\n setSidechainMono(samples: Float32Array): void {\n this.eq.setSidechainMono(samples);\n }\n\n /**\n * Provide a stereo external sidechain key. Both channels must match length.\n */\n setSidechainStereo(left: Float32Array, right: Float32Array): void {\n if (left.length !== right.length) {\n throw new Error('Sidechain channel lengths must match.');\n }\n this.eq.setSidechainStereo(left, right);\n }\n\n /** Release any borrowed external sidechain buffers. */\n clearSidechain(): void {\n this.eq.clearSidechain();\n }\n\n /** Auto-gain applied on the most recent block, in dB. */\n lastAutoGainDb(): number {\n return this.eq.lastAutoGainDb();\n }\n\n /** Reported processing latency in samples (non-zero for linear-phase bands). */\n latencySamples(): number {\n return this.eq.latencySamples();\n }\n\n /**\n * Process one mono block, returning the equalized samples (same length).\n */\n processMono(samples: Float32Array): Float32Array {\n return this.eq.processMono(samples);\n }\n\n /**\n * Process one stereo block, returning the equalized channels.\n */\n processStereo(\n left: Float32Array,\n right: Float32Array,\n ): { left: Float32Array; right: Float32Array } {\n if (left.length !== right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n return this.eq.processStereo(left, right);\n }\n\n /**\n * Read the latest pre/post spectrum snapshot for metering. `seq` increments\n * each time a new snapshot is published.\n */\n spectrum(): EqSpectrumSnapshot {\n return this.eq.spectrum();\n }\n\n /**\n * Configure bands so the source spectrum matches the reference spectrum.\n *\n * @param source - Source audio (mono samples)\n * @param reference - Reference audio (mono samples)\n * @param options - `sampleRate` (default 48000) and `maxBands` (default 8)\n */\n match(source: Float32Array, reference: Float32Array, options: EqMatchOptions = {}): void {\n this.eq.match(source, reference, options as Record<string, unknown>);\n }\n\n /** Release the underlying WASM object. Safe to call only once. */\n delete(): void {\n this.eq.delete();\n }\n}\n\n// ============================================================================\n// StreamingRetune Class\n// ============================================================================\n\n/**\n * Block-by-block mono voice retune / pitch shifter.\n *\n * State is maintained across {@link processMono} calls. Call {@link prepare}\n * before processing, and call {@link delete} (or use `try/finally`) to release\n * the underlying WASM object.\n */\nexport class StreamingRetune {\n private retune: import('./sonare.js').WasmStreamingRetune;\n\n constructor(config: StreamingRetuneConfig = {}) {\n const module = getSonareModule();\n this.retune = module.createStreamingRetune(config as Record<string, unknown>);\n }\n\n /**\n * Allocate and initialize native state for the given sample rate and maximum\n * process block size.\n */\n prepare(sampleRate: number, maxBlockSize: number): void {\n this.retune.prepare(sampleRate, maxBlockSize);\n }\n\n /** Reset delay, grain, and overlap-add state without changing config. */\n reset(): void {\n this.retune.reset();\n }\n\n /**\n * Update retune settings. Changing `grainSize` takes effect after the next\n * {@link prepare} call.\n */\n setConfig(config: StreamingRetuneConfig): void {\n this.retune.setConfig(config as Record<string, unknown>);\n }\n\n /** Current native config. */\n config(): Required<StreamingRetuneConfig> {\n return this.retune.config();\n }\n\n /** Resolved grain size in samples after {@link prepare}. */\n grainSize(): number {\n return this.retune.grainSize();\n }\n\n /** Process one mono block, returning the shifted samples (same length). */\n processMono(samples: Float32Array): Float32Array {\n return this.retune.processMono(samples);\n }\n\n /** Release the underlying WASM object. Safe to call only once. */\n delete(): void {\n this.retune.delete();\n }\n}\n","import type { MidiCcBindOptions } from './realtime_engine';\n\nexport interface WebMidiEngine {\n bindMidiCc(\n channel: number,\n controller: number,\n paramId: number,\n options?: MidiCcBindOptions,\n ): void;\n setMidiInputSource(destinationId?: number): void;\n clearMidiInputSource(): void;\n pushMidiInputNoteOn(\n group: number,\n channel: number,\n note: number,\n velocity: number,\n time?: number,\n ): void;\n pushMidiInputNoteOff(\n group: number,\n channel: number,\n note: number,\n velocity?: number,\n time?: number,\n ): void;\n pushMidiInputCc(\n group: number,\n channel: number,\n controller: number,\n value: number,\n time?: number,\n ): void;\n}\n\ntype MidiInputState = 'connected' | 'disconnected';\n\ninterface MidiPortLike {\n id: string;\n name?: string | null;\n manufacturer?: string | null;\n state?: MidiInputState;\n}\n\ninterface MidiMessageEventLike {\n data: ArrayLike<number>;\n timeStamp?: number;\n receivedTime?: number;\n target?: MidiPortLike;\n currentTarget?: MidiPortLike;\n}\n\ninterface MidiInputLike extends MidiPortLike {\n type?: 'input';\n onmidimessage: ((event: MidiMessageEventLike) => void) | null;\n addEventListener?: (type: 'midimessage', listener: (event: MidiMessageEventLike) => void) => void;\n removeEventListener?: (\n type: 'midimessage',\n listener: (event: MidiMessageEventLike) => void,\n ) => void;\n}\n\ninterface MidiConnectionEventLike {\n port?: MidiPortLike | null;\n}\n\ninterface MidiAccessLike {\n inputs: Map<string, MidiInputLike> | Iterable<[string, MidiInputLike]>;\n onstatechange: ((event: MidiConnectionEventLike) => void) | null;\n addEventListener?: (\n type: 'statechange',\n listener: (event: MidiConnectionEventLike) => void,\n ) => void;\n removeEventListener?: (\n type: 'statechange',\n listener: (event: MidiConnectionEventLike) => void,\n ) => void;\n}\n\ninterface NavigatorWithMidi {\n requestMIDIAccess?: (options?: {\n sysex?: boolean;\n software?: boolean;\n }) => Promise<MidiAccessLike>;\n}\n\nexport interface WebMidiCcBinding {\n channel: number;\n controller: number;\n paramId: number;\n options?: MidiCcBindOptions;\n}\n\nexport interface WebMidiInputInfo {\n id: string;\n name: string;\n manufacturer: string;\n state: MidiInputState;\n}\n\nexport interface BindWebMidiOptions {\n /** Realtime-engine MIDI destination receiving the live input source. Default `0`. */\n destinationId?: number;\n /** UMP group used for MIDI 1.0 channel voice events. Default `0`. */\n group?: number;\n /** Restrict binding to specific Web MIDI input ids. Omit or empty = all connected inputs. */\n inputIds?: readonly string[];\n /** Request SysEx-capable access from the browser. Default `false`. */\n sysex?: boolean;\n /** Request software ports from the browser where supported. Default `true`. */\n software?: boolean;\n /** Bind CC-to-parameter mappings before ports are connected. */\n ccBindings?: readonly WebMidiCcBinding[];\n /** Convert a Web MIDI event timestamp to engine port-time samples. */\n timestampToSamples?: (eventTimeMs: number) => number;\n /** Observe hot-plug updates after the helper rebinds matching inputs. */\n onInputsChanged?: (inputs: WebMidiInputInfo[]) => void;\n}\n\nexport interface WebMidiBinding {\n access: MidiAccessLike;\n inputs(): WebMidiInputInfo[];\n close(): void;\n}\n\ntype BoundInput = {\n input: MidiInputLike;\n listener: (event: MidiMessageEventLike) => void;\n runningStatus: number;\n};\n\nexport function isWebMidiAvailable(): boolean {\n return (\n typeof (globalThis.navigator as NavigatorWithMidi | undefined)?.requestMIDIAccess === 'function'\n );\n}\n\nexport async function bindWebMidi(\n engine: WebMidiEngine,\n options: BindWebMidiOptions = {},\n): Promise<WebMidiBinding> {\n const navigatorWithMidi = globalThis.navigator as NavigatorWithMidi | undefined;\n if (typeof navigatorWithMidi?.requestMIDIAccess !== 'function') {\n throw new Error('Web MIDI is not available in this environment');\n }\n\n const group = options.group ?? 0;\n assertNibble('bindWebMidi', group, 'group');\n const destinationId = options.destinationId ?? 0;\n const selectedIds = new Set(options.inputIds ?? []);\n // Invoke through the navigator so the browser's native method keeps its\n // required `this` binding (detached calls throw \"Illegal invocation\").\n const access = await navigatorWithMidi.requestMIDIAccess({\n sysex: options.sysex ?? false,\n software: options.software ?? true,\n });\n\n for (const binding of options.ccBindings ?? []) {\n engine.bindMidiCc(binding.channel, binding.controller, binding.paramId, binding.options);\n }\n engine.setMidiInputSource(destinationId);\n\n const bound = new Map<string, BoundInput>();\n let closed = false;\n\n const shouldBind = (input: MidiInputLike) =>\n input.state !== 'disconnected' && (selectedIds.size === 0 || selectedIds.has(input.id));\n\n const snapshotInputs = (): WebMidiInputInfo[] =>\n Array.from(iterInputs(access), ([id, input]) => ({\n id,\n name: input.name ?? '',\n manufacturer: input.manufacturer ?? '',\n state: input.state ?? 'connected',\n }));\n\n const notify = () => options.onInputsChanged?.(snapshotInputs());\n\n const bindInput = (input: MidiInputLike) => {\n if (bound.has(input.id) || !shouldBind(input)) {\n return;\n }\n const entry: BoundInput = {\n input,\n listener: (event: MidiMessageEventLike) => {\n entry.runningStatus = dispatchMidiMessage(\n engine,\n event,\n group,\n entry.runningStatus,\n options.timestampToSamples,\n );\n },\n runningStatus: 0,\n };\n const listener = entry.listener;\n if (input.addEventListener) {\n input.addEventListener('midimessage', listener);\n } else {\n input.onmidimessage = listener;\n }\n bound.set(input.id, entry);\n };\n\n const unbindInput = (input: MidiInputLike) => {\n const entry = bound.get(input.id);\n if (!entry) {\n return;\n }\n if (entry.input.removeEventListener) {\n entry.input.removeEventListener('midimessage', entry.listener);\n } else if (entry.input.onmidimessage === entry.listener) {\n entry.input.onmidimessage = null;\n }\n bound.delete(input.id);\n };\n\n // Does not call notify() itself: both call sites below (the initial sync\n // and stateListener's fallback branch) already notify exactly once after\n // calling this, so notifying here too would fire onInputsChanged twice per\n // hotplug event that goes through the fallback branch.\n const refreshInputs = () => {\n for (const [, entry] of bound) {\n if (!shouldBind(entry.input)) {\n unbindInput(entry.input);\n }\n }\n for (const [, input] of iterInputs(access)) {\n bindInput(input);\n }\n };\n\n const stateListener = (event: MidiConnectionEventLike) => {\n if (closed) {\n return;\n }\n if (event.port && 'onmidimessage' in event.port) {\n const input = event.port as MidiInputLike;\n if (shouldBind(input)) {\n bindInput(input);\n } else {\n unbindInput(input);\n }\n } else {\n refreshInputs();\n }\n notify();\n };\n\n refreshInputs();\n notify();\n if (access.addEventListener) {\n access.addEventListener('statechange', stateListener);\n } else {\n access.onstatechange = stateListener;\n }\n\n return {\n access,\n inputs: snapshotInputs,\n close() {\n closed = true;\n if (access.removeEventListener) {\n access.removeEventListener('statechange', stateListener);\n } else if (access.onstatechange === stateListener) {\n access.onstatechange = null;\n }\n for (const [, entry] of Array.from(bound)) {\n unbindInput(entry.input);\n }\n engine.clearMidiInputSource();\n },\n };\n}\n\nfunction dispatchMidiMessage(\n engine: WebMidiEngine,\n event: MidiMessageEventLike,\n group: number,\n runningStatus: number,\n timestampToSamples?: (eventTimeMs: number) => number,\n): number {\n const data = event.data;\n if (data.length === 0) {\n return 0;\n }\n const first = data[0];\n if (first > 0xff) {\n dispatchUmpMessage(\n engine,\n data,\n timestampToSamples?.(event.receivedTime ?? event.timeStamp ?? 0) ?? 0,\n );\n return 0;\n }\n\n let offset = 0;\n let status = first & 0xff;\n if (status < 0x80) {\n if (runningStatus === 0) {\n return 0;\n }\n status = runningStatus;\n } else {\n offset = 1;\n }\n\n const message = status & 0xf0;\n const channel = status & 0x0f;\n if (message < 0x80 || message > 0xe0) {\n return status >= 0xf8 ? runningStatus : 0;\n }\n\n const a = readU7(data, offset);\n const b = readU7(data, offset + 1);\n if (a < 0 || b < 0) {\n return status;\n }\n\n const portTimeSamples = timestampToSamples\n ? timestampToSamples(event.receivedTime ?? event.timeStamp ?? 0)\n : 0;\n\n if (message === 0x80) {\n engine.pushMidiInputNoteOff(group, channel, a, b, portTimeSamples);\n } else if (message === 0x90) {\n if (b === 0) {\n engine.pushMidiInputNoteOff(group, channel, a, 0, portTimeSamples);\n } else {\n engine.pushMidiInputNoteOn(group, channel, a, b, portTimeSamples);\n }\n } else if (message === 0xb0 && b >= 0) {\n engine.pushMidiInputCc(group, channel, a, b, portTimeSamples);\n }\n\n return status;\n}\n\nfunction dispatchUmpMessage(\n engine: WebMidiEngine,\n words: ArrayLike<number>,\n portTimeSamples: number,\n): void {\n const word0 = words[0] >>> 0;\n const messageType = word0 >>> 28;\n const group = (word0 >>> 24) & 0x0f;\n\n if (messageType === 0x2) {\n const status = (word0 >>> 16) & 0xff;\n const message = status & 0xf0;\n const channel = status & 0x0f;\n const a = (word0 >>> 8) & 0x7f;\n const b = word0 & 0x7f;\n if (message === 0x80) {\n engine.pushMidiInputNoteOff(group, channel, a, b, portTimeSamples);\n } else if (message === 0x90) {\n if (b === 0) {\n engine.pushMidiInputNoteOff(group, channel, a, 0, portTimeSamples);\n } else {\n engine.pushMidiInputNoteOn(group, channel, a, b, portTimeSamples);\n }\n } else if (message === 0xb0) {\n engine.pushMidiInputCc(group, channel, a, b, portTimeSamples);\n }\n return;\n }\n\n if (messageType === 0x4 && words.length >= 2) {\n const status = (word0 >>> 20) & 0x0f;\n const channel = (word0 >>> 16) & 0x0f;\n const data1 = (word0 >>> 8) & 0x7f;\n const word1 = words[1] >>> 0;\n if (status === 0x8) {\n engine.pushMidiInputNoteOff(group, channel, data1, (word1 >>> 25) & 0x7f, portTimeSamples);\n } else if (status === 0x9) {\n // MIDI 2.0 note-on is distinct from note-off (status 0x8). Downsample\n // its 16-bit velocity to the engine's 7-bit API, retaining a nonzero\n // note-on even when the top seven bits are all zero.\n const velocity = Math.max(1, (word1 >>> 25) & 0x7f);\n engine.pushMidiInputNoteOn(group, channel, data1, velocity, portTimeSamples);\n } else if (status === 0xb) {\n engine.pushMidiInputCc(group, channel, data1, (word1 >>> 25) & 0x7f, portTimeSamples);\n }\n }\n}\n\nfunction readU7(data: ArrayLike<number>, index: number): number {\n if (index >= data.length) {\n return -1;\n }\n const value = data[index];\n if (!Number.isInteger(value) || value < 0 || value > 127) {\n return -1;\n }\n return value;\n}\n\nfunction assertNibble(fnName: string, value: number, field: string): void {\n if (!Number.isInteger(value) || value < 0 || value > 15) {\n throw new RangeError(`${fnName}: ${field} must be an integer in [0, 15]`);\n }\n}\n\nfunction iterInputs(access: MidiAccessLike): Iterable<[string, MidiInputLike]> {\n return access.inputs instanceof Map ? access.inputs.entries() : access.inputs;\n}\n","import { ErrorCode, SonareError } from './errors';\nimport type { MasterAudioRequest, MasterAudioStereoRequest } from './mastering_chain';\nimport type {\n DetectChordsRequest,\n DetectKeyRequest,\n MusicAnalyzeRequest,\n SamplesRequest,\n} from './quick_analysis';\nimport type { OfflineWorkerOperation, OfflineWorkerResponseMessage } from './worker_protocol';\n\ntype WorkerRequest<T> = Omit<T, 'onProgress'>;\n\n/** Progress relayed from the Worker at the core's native progress boundaries. */\nexport interface OfflineWorkerProgress {\n progress: number;\n stage: string;\n}\n\n/** Per-call behaviour for a one-shot operation. */\nexport interface OfflineWorkerCallOptions {\n /**\n * Preserve the caller's input arrays by copying them before dispatch.\n *\n * The default is `false`: `Float32Array` buffers are transferred to the\n * Worker and become detached on the calling thread, avoiding a second copy.\n */\n copy?: boolean;\n /** Receives native progress boundaries for analysis and mastering calls. */\n onProgress?: (update: OfflineWorkerProgress) => void;\n}\n\n/** Options used to create an {@link OfflineWorkerClient}. */\nexport interface OfflineWorkerClientOptions {\n /** Reuse a Worker owned by the host instead of creating one. */\n worker?: OfflineWorker;\n /** URL of the Worker entry; defaults to the adjacent published `worker.js`. */\n workerUrl?: string | URL;\n /** Test/host hook for creating a dedicated Worker. */\n workerFactory?: (url: URL) => OfflineWorker;\n /** Terminate a supplied Worker when {@link OfflineWorkerClient.dispose} runs. */\n terminateWorkerOnDispose?: boolean;\n}\n\n/** Browser Worker or Node `worker_threads.Worker` used by the client. */\nexport interface OfflineWorker {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n terminate(): unknown;\n addEventListener?(type: string, listener: EventListener): void;\n removeEventListener?(type: string, listener: EventListener): void;\n on?(type: 'message' | 'error', listener: (...args: unknown[]) => void): unknown;\n off?(type: 'message' | 'error', listener: (...args: unknown[]) => void): unknown;\n}\n\n/**\n * A cancellable promise returned by an {@link OfflineWorkerClient} call.\n *\n * It is Promise-like, so `await client.analyze(...)` works. Call `cancel()` to\n * request cancellation at the next native progress boundary. In browsers this\n * uses a `SharedArrayBuffer` flag, which requires cross-origin isolation for\n * prompt cancellation while synchronous WASM is running. The worker forwards\n * that flag through the same native cancellation callback used by synchronous\n * one-shot requests.\n */\nexport class OfflineWorkerTask<T> implements PromiseLike<T> {\n constructor(\n readonly result: Promise<T>,\n private readonly cancelRequest: () => void,\n ) {}\n\n cancel(): void {\n this.cancelRequest();\n }\n\n // biome-ignore lint/suspicious/noThenProperty: this intentionally implements PromiseLike so callers can await a task and cancel it.\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.result.then(onfulfilled, onrejected);\n }\n\n catch<TResult = never>(\n onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null,\n ): Promise<T | TResult> {\n return this.result.catch(onrejected);\n }\n\n finally(onfinally?: (() => void) | null): Promise<T> {\n return this.result.finally(onfinally);\n }\n}\n\ninterface PendingCall {\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n onProgress?: (update: OfflineWorkerProgress) => void;\n cancelFlag?: Int32Array;\n}\n\nfunction cloneForWorker(\n value: unknown,\n copy: boolean,\n transfers: Transferable[],\n transferred = new Set<ArrayBuffer>(),\n): unknown {\n if (value instanceof Float32Array) {\n const samples = copy ? value.slice() : value;\n const buffer = samples.buffer;\n if (!(buffer instanceof ArrayBuffer)) {\n throw new TypeError(\n 'OfflineWorkerClient only transfers Float32Array values backed by ArrayBuffer',\n );\n }\n if (!transferred.has(buffer)) {\n transferred.add(buffer);\n transfers.push(buffer);\n }\n return samples;\n }\n if (Array.isArray(value)) {\n return value.map((item) => cloneForWorker(item, copy, transfers, transferred));\n }\n if (value !== null && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [\n key,\n cloneForWorker(item, copy, transfers, transferred),\n ]),\n );\n }\n return value;\n}\n\nfunction cancellationFlag(): Int32Array | undefined {\n if (typeof SharedArrayBuffer === 'undefined') {\n return undefined;\n }\n return new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));\n}\n\nfunction workerError(\n message: Extract<OfflineWorkerResponseMessage, { type: 'sonare:offline-error' }>,\n): Error {\n if (message.error.code !== undefined) {\n return new SonareError(\n message.error.code,\n message.error.codeName ?? 'Unknown',\n message.error.message,\n );\n }\n const error = new Error(message.error.message);\n error.name = message.error.name;\n return error;\n}\n\n/**\n * Owns a dedicated Worker for value-based offline analysis and mastering.\n *\n * `Project`, `Mixer`, and realtime APIs are intentionally absent: their native\n * handles are local to one JavaScript realm and cannot be transferred safely.\n */\nexport class OfflineWorkerClient {\n private readonly worker: OfflineWorker;\n private readonly ownsWorker: boolean;\n private readonly pending = new Map<number, PendingCall>();\n private nextId = 1;\n private closed = false;\n private usesEventTarget = false;\n\n constructor(options: OfflineWorkerClientOptions = {}) {\n this.ownsWorker = options.worker === undefined || options.terminateWorkerOnDispose === true;\n if (options.worker) {\n this.worker = options.worker;\n } else {\n if (!options.workerFactory && typeof Worker === 'undefined') {\n throw new Error('OfflineWorkerClient requires a browser Worker implementation');\n }\n const url =\n options.workerUrl === undefined\n ? new URL('./worker.js', import.meta.url)\n : new URL(options.workerUrl, import.meta.url);\n this.worker =\n options.workerFactory?.(url) ?? new Worker(url, { type: 'module', name: 'sonare-offline' });\n }\n if (this.worker.addEventListener) {\n this.usesEventTarget = true;\n this.worker.addEventListener('message', this.onMessage as EventListener);\n this.worker.addEventListener('error', this.onError as EventListener);\n } else if (this.worker.on) {\n this.worker.on('message', this.onNodeMessage);\n this.worker.on('error', this.onNodeError);\n } else {\n throw new TypeError('OfflineWorkerClient requires Worker event listeners');\n }\n }\n\n /** Dispatch full music analysis to the Worker. */\n analyze(\n request: WorkerRequest<MusicAnalyzeRequest>,\n options?: OfflineWorkerCallOptions,\n ): OfflineWorkerTask<ReturnType<typeof import('./quick_analysis').analyze>> {\n return this.call('analyze', request, options);\n }\n\n /** Dispatch BPM detection to the Worker. */\n detectBpm(\n request: SamplesRequest,\n options?: OfflineWorkerCallOptions,\n ): OfflineWorkerTask<number> {\n return this.call('detectBpm', request, options);\n }\n\n /** Dispatch key detection to the Worker. */\n detectKey(\n request: DetectKeyRequest,\n options?: OfflineWorkerCallOptions,\n ): OfflineWorkerTask<ReturnType<typeof import('./quick_analysis').detectKey>> {\n return this.call('detectKey', request, options);\n }\n\n /** Dispatch chord detection to the Worker. */\n detectChords(\n request: DetectChordsRequest,\n options?: OfflineWorkerCallOptions,\n ): OfflineWorkerTask<ReturnType<typeof import('./quick_analysis').detectChords>> {\n return this.call('detectChords', request, options);\n }\n\n /** Dispatch mono preset mastering to the Worker. */\n masterAudio(\n request: WorkerRequest<MasterAudioRequest>,\n options?: OfflineWorkerCallOptions,\n ): OfflineWorkerTask<ReturnType<typeof import('./mastering_chain').masterAudio>> {\n return this.call('masterAudio', request, options);\n }\n\n /** Dispatch stereo preset mastering to the Worker. */\n masterAudioStereo(\n request: WorkerRequest<MasterAudioStereoRequest>,\n options?: OfflineWorkerCallOptions,\n ): OfflineWorkerTask<ReturnType<typeof import('./mastering_chain').masterAudioStereo>> {\n return this.call('masterAudioStereo', request, options);\n }\n\n /** Stop accepting calls, reject outstanding work, and release the Worker if owned. */\n dispose(): void {\n if (this.closed) {\n return;\n }\n this.closed = true;\n if (this.usesEventTarget) {\n this.worker.removeEventListener?.('message', this.onMessage as EventListener);\n this.worker.removeEventListener?.('error', this.onError as EventListener);\n } else {\n this.worker.off?.('message', this.onNodeMessage);\n this.worker.off?.('error', this.onNodeError);\n }\n for (const { reject } of this.pending.values()) {\n reject(new Error('OfflineWorkerClient was disposed'));\n }\n this.pending.clear();\n if (this.ownsWorker) {\n this.worker.terminate();\n }\n }\n\n private call<T>(\n operation: OfflineWorkerOperation,\n request: object,\n options: OfflineWorkerCallOptions = {},\n ): OfflineWorkerTask<T> {\n if (this.closed) {\n throw new Error('OfflineWorkerClient was disposed');\n }\n const id = this.nextId++;\n const transfers: Transferable[] = [];\n const preparedRequest = cloneForWorker(request, options.copy === true, transfers) as Record<\n string,\n unknown\n >;\n const cancelFlag = cancellationFlag();\n const result = new Promise<T>((resolve, reject) => {\n this.pending.set(id, {\n resolve: (value) => resolve(value as T),\n reject,\n onProgress: options.onProgress,\n cancelFlag,\n });\n });\n this.worker.postMessage(\n {\n type: 'sonare:offline-run',\n id,\n operation,\n request: preparedRequest,\n ...(cancelFlag ? { cancelBuffer: cancelFlag.buffer as SharedArrayBuffer } : {}),\n },\n transfers,\n );\n return new OfflineWorkerTask(result, () => {\n if (!this.pending.has(id)) {\n return;\n }\n if (cancelFlag) {\n Atomics.store(cancelFlag, 0, 1);\n }\n // A message also covers a call cancelled before it begins and is the\n // best available fallback where SharedArrayBuffer is unavailable.\n this.worker.postMessage({ type: 'sonare:offline-cancel', id });\n });\n }\n\n private readonly onMessage = (event: MessageEvent<OfflineWorkerResponseMessage>): void => {\n const message = event.data;\n const pending = this.pending.get(message.id);\n if (!pending) {\n return;\n }\n if (message.type === 'sonare:offline-progress') {\n pending.onProgress?.({ progress: message.progress, stage: message.stage });\n return;\n }\n this.pending.delete(message.id);\n if (message.type === 'sonare:offline-result') {\n pending.resolve(message.result);\n return;\n }\n pending.reject(workerError(message));\n };\n\n private readonly onError = (event: ErrorEvent): void => {\n const error = new Error(event.message || 'Offline Worker failed');\n for (const { reject } of this.pending.values()) {\n reject(error);\n }\n this.pending.clear();\n };\n\n private readonly onNodeMessage = (data: unknown): void => {\n this.onMessage({ data } as MessageEvent<OfflineWorkerResponseMessage>);\n };\n\n private readonly onNodeError = (error: unknown): void => {\n this.onError(\n error instanceof Error\n ? ({ message: error.message } as ErrorEvent)\n : ({ message: String(error) } as ErrorEvent),\n );\n };\n}\n\nexport { ErrorCode };\n","/**\n * sonare - Audio Analysis Library\n *\n * @example\n * ```typescript\n * import { init, detectBpm, detectKey, analyze } from '@libraz/libsonare';\n *\n * await init();\n *\n * // Detect BPM from audio samples\n * const bpm = detectBpm(samples, sampleRate);\n *\n * // Detect musical key\n * const key = detectKey(samples, sampleRate);\n *\n * // Full analysis\n * const result = analyze(samples, sampleRate);\n * ```\n */\n\nimport { setSonareModule } from './module_state';\nimport type {\n CapabilityCatalog,\n RealtimeVoiceChangerPodConfig,\n SonareCapabilities,\n VoicePresetId,\n} from './public_types';\nimport type {\n SonareModule,\n WasmDecomposeResult,\n WasmHpssWithResidualResult,\n WasmMatrix2dResult,\n} from './sonare.js';\n\nexport type { BrowserAudioDecodeOptions } from './audio';\nexport { Audio } from './audio';\nexport type {\n ClipPageStreamerEngine,\n ClipPageStreamerOptions,\n ClipPageStreamerRequest,\n ClipPageStreamSource,\n OpfsClipStream,\n OpfsClipStreamOptions,\n WorkletOpfsClipStreamHost,\n} from './clip_page_streamer';\nexport { attachOpfsClipStream, ClipPageStreamer } from './clip_page_streamer';\nexport type {\n CompressorDetector,\n CompressorOptions,\n DeclickOptions,\n DeclipOptions,\n DecrackleMode,\n DecrackleOptions,\n DehumOptions,\n DenoiseClassicalMode,\n DenoiseClassicalNoiseEstimator,\n DenoiseClassicalOptions,\n DereverbClassicalOptions,\n DynamicsResult,\n GateOptions,\n MasteringChannelPolicy,\n MasteringDynamicsCompressorRequest,\n MasteringDynamicsGateRequest,\n MasteringDynamicsTransientShaperRequest,\n MasteringInsertParamInfo,\n MasteringPairAnalyzeRequest,\n MasteringPairProcessRequest,\n MasteringProcessorCatalogEntry,\n MasteringProcessRequest,\n MasteringProcessStereoRequest,\n MasteringRealtimeCost,\n MasteringRepairDeclickRequest,\n MasteringRepairDeclipRequest,\n MasteringRepairDecrackleRequest,\n MasteringRepairDehumRequest,\n MasteringRepairDenoiseClassicalRequest,\n MasteringRepairDereverbClassicalRequest,\n MasteringRepairTrimSilenceRequest,\n MasteringSamplesParamsRequest,\n MasteringStereoAnalyzeRequest,\n MasteringStereoParamsRequest,\n MasteringStreamingPreviewRequest,\n MasteringStreamingPreviewStereoRequest,\n MixStereoRequest,\n TransientShaperOptions,\n TrimSilenceMode,\n TrimSilenceOptions,\n VoiceChangeOptions,\n VoiceChangeRealtimeOptions,\n VoiceChangeRealtimeRequest,\n VoiceChangeRequest,\n} from './effects_mastering';\nexport {\n harmonic,\n hpss,\n masterAudio,\n masterAudioStereo,\n masterAudioStereoWithProgress,\n masterAudioWithProgress,\n mastering,\n masteringAssistantSuggest,\n masteringAssistantSuggestStereo,\n masteringAudioProfile,\n masteringAudioProfileStereo,\n masteringChain,\n masteringChainStereo,\n masteringChainStereoWithProgress,\n masteringChainWithProgress,\n masteringDynamicsCompressor,\n masteringDynamicsGate,\n masteringDynamicsTransientShaper,\n masteringInsertNames,\n masteringInsertParamInfo,\n masteringInsertParamNames,\n masteringPairAnalysisNames,\n masteringPairAnalyze,\n masteringPairProcess,\n masteringPairProcessorNames,\n masteringPresetNames,\n masteringProcess,\n masteringProcessorCatalog,\n masteringProcessorNames,\n masteringProcessStereo,\n masteringRepairDeclick,\n masteringRepairDeclip,\n masteringRepairDecrackle,\n masteringRepairDehum,\n masteringRepairDenoiseClassical,\n masteringRepairDereverbClassical,\n masteringRepairTrimSilence,\n masteringStereoAnalysisNames,\n masteringStereoAnalyze,\n masteringStreamingPreview,\n masteringStreamingPreviewStereo,\n mixingScenePresetJson,\n mixingScenePresetNames,\n mixStereo,\n normalize,\n noteMove,\n noteStretch,\n percussive,\n pitchCorrectTimevarying,\n pitchCorrectToMidi,\n pitchCorrectToMidiTimevarying,\n pitchShift,\n spectralEdit,\n timeStretch,\n voiceChange,\n voiceChangeRealtime,\n} from './effects_mastering';\nexport type {\n HarmonicRequest,\n HpssRequest,\n NormalizeMode,\n NormalizeRequest,\n NoteMoveRequest,\n NoteStretchRequest,\n PercussiveRequest,\n PitchCorrectTimevaryingRequest,\n PitchCorrectToMidiRequest,\n PitchCorrectToMidiTimevaryingRequest,\n PitchShiftRequest,\n SpectralEditRequest,\n TimeStretchRequest,\n} from './effects_transform';\nexport { ErrorCode, isSonareError, SonareError } from './errors';\nexport type {\n ChirpRequest,\n ClicksRequest,\n CyclicTempogramRequest,\n DbConversionRequest,\n EmphasisRequest,\n FixFramesRequest,\n FixLengthRequest,\n FrameSignalRequest,\n OnsetBacktrackRequest,\n PadCenterRequest,\n PcenRequest,\n PeakPickRequest,\n PlpRequest,\n SilenceRequest,\n TempogramRequest,\n ToneRequest,\n TonnetzRequest,\n VectorNormalizeRequest,\n} from './feature_core';\nexport type {\n AnalyzeMelodyRequest,\n AnalyzeSectionsRequest,\n CqtRequest,\n CqtToAudioRequest,\n FourierTempogramRequest,\n LufsRequest,\n MelodyOptions,\n NnlsChromaRequest,\n OnsetEnvelopeRequest,\n OnsetStrengthMultiRequest,\n TempogramRatioRequest,\n VqtRequest,\n VqtToAudioRequest,\n} from './feature_music';\nexport type {\n NoteSegmentsRequest,\n PiptrackRequest,\n PitchPyinRequest,\n PitchYinRequest,\n} from './feature_pitch';\nexport type { ResampleRequest } from './feature_resample';\nexport type {\n DecomposeRequest,\n DecomposeWithInitRequest,\n Ebur128LoudnessRangeRequest,\n EstimateTuningRequest,\n HpssWithResidualRequest,\n LufsInterleavedRequest,\n NnFilterRequest,\n PhaseVocoderRequest,\n PitchTuningRequest,\n PolyFeaturesRequest,\n RemixRequest,\n SegmentAgglomerativeRequest,\n SegmentCrossSimilarityRequest,\n SegmentLagToRecurrenceRequest,\n SegmentPathEnhanceRequest,\n SegmentRecurrenceMatrixRequest,\n SegmentRecurrenceToLagRequest,\n SegmentSubsegmentRequest,\n SpectralContrastRequest,\n SpectralFrameRequest,\n SpectralRolloffRequest,\n ZeroCrossingRateRequest,\n ZeroCrossingsRequest,\n} from './feature_spectral';\nexport type {\n ChromaSpectrogramRequest,\n GriffinLimRequest,\n MelDeltaRequest,\n MelSpectrogramRequest,\n MelToAudioRequest,\n MelToStftRequest,\n MfccRequest,\n MfccToAudioRequest,\n MfccToMelRequest,\n ReassignedSpectrogramRequest,\n SpectrogramRequest,\n TrimRequest,\n} from './feature_spectrogram';\nexport {\n amplitudeToDb,\n analyzeMelody,\n analyzeSections,\n bassChroma,\n chirp,\n chroma,\n chromaCens,\n chromaCqt,\n clicks,\n cqt,\n cqtToAudio,\n cyclicTempogram,\n dbToAmplitude,\n dbToPower,\n decompose,\n decomposeWithInit,\n deemphasis,\n ebur128LoudnessRange,\n estimateTuning,\n fixFrames,\n fixLength,\n fourierTempogram,\n frameSignal,\n framesToSamples,\n framesToTime,\n griffinLim,\n hpssWithResidual,\n hybridCqt,\n hzToMel,\n hzToMidi,\n hzToNote,\n lufs,\n lufsInterleaved,\n melDelta,\n melSpectrogram,\n melToAudio,\n melToHz,\n melToStft,\n mfcc,\n mfccToAudio,\n mfccToMel,\n midiToHz,\n momentaryLufs,\n nnFilter,\n nnlsChroma,\n noteSegments,\n noteToHz,\n onsetBacktrack,\n onsetEnvelope,\n onsetStrengthMulti,\n padCenter,\n pcen,\n peakPick,\n phaseVocoder,\n piptrack,\n pitchPyin,\n pitchTuning,\n pitchYin,\n plp,\n polyFeatures,\n powerToDb,\n preemphasis,\n pseudoCqt,\n reassignedSpectrogram,\n remix,\n resample,\n rmsEnergy,\n samplesToFrames,\n segmentAgglomerative,\n segmentCrossSimilarity,\n segmentLagToRecurrence,\n segmentPathEnhance,\n segmentRecurrenceMatrix,\n segmentRecurrenceToLag,\n segmentSubsegment,\n shortTermLufs,\n spectralBandwidth,\n spectralCentroid,\n spectralContrast,\n spectralFlatness,\n spectralFlux,\n spectralRolloff,\n splitSilence,\n stft,\n stftDb,\n tempogram,\n tempogramRatio,\n timeToFrames,\n tone,\n tonnetz,\n trim,\n trimSilence,\n vectorNormalize,\n vqt,\n vqtToAudio,\n zeroCrossingRate,\n zeroCrossings,\n} from './features';\nexport type { BindMicrophoneInputOptions, MicrophoneInputBinding } from './live_audio';\nexport { bindMicrophoneInput } from './live_audio';\nexport type {\n MasterAudioRequest,\n MasterAudioStereoRequest,\n MasteringChainRequest,\n MasteringChainStereoRequest,\n} from './mastering_chain';\nexport type { MasteringRequest } from './mastering_core';\nexport type {\n ClippingRegion,\n ClippingReport,\n DynamicRangeReport,\n MeteringDetectClippingOptions,\n MeteringDetectClippingRequest,\n MeteringDynamicRangeOptions,\n MeteringDynamicRangeRequest,\n MeteringSamplesRequest,\n MeteringSilenceRatioRequest,\n MeteringSpectrumFrameRequest,\n MeteringSpectrumRequest,\n MeteringStereoDecimatedRequest,\n MeteringStereoRequest,\n MeteringTruePeakRequest,\n PhaseScopeReport,\n SpectrumOptions,\n SpectrumReport,\n VectorscopeReport,\n WaveformPeakPyramidOptions,\n WaveformPeakPyramidRequest,\n WaveformPeaksOptions,\n WaveformPeaksReport,\n WaveformPeaksRequest,\n} from './metering';\nexport {\n meteringCrestFactorDb,\n meteringCrestFactorDbStereo,\n meteringDcOffset,\n meteringDetectClipping,\n meteringDynamicRange,\n meteringPeakDb,\n meteringPhaseScope,\n meteringPhaseScopeDecimated,\n meteringRmsDb,\n meteringSilenceRatio,\n meteringSpectrum,\n meteringSpectrumFrame,\n meteringStereoCorrelation,\n meteringStereoWidth,\n meteringTruePeakDb,\n meteringVectorscope,\n meteringVectorscopeDecimated,\n waveformPeakPyramid,\n waveformPeaks,\n} from './metering';\nexport type {\n OpfsClipPageProviderBinding,\n OpfsClipPageProviderOptions,\n} from './opfs_clip_pages';\nexport {\n createOpfsClipPageProvider,\n createOpfsClipPageWorker,\n opfsClipPageWorkerSource,\n} from './opfs_clip_pages';\nexport type {\n BuiltinSynthBinding,\n BuiltinSynthConfig,\n BuiltinSynthWaveform,\n ExternalSeparatedStem,\n ExternalSeparatedStemImportRequest,\n ExternalSeparatedStemImportResult,\n MidiCcLearnOptions,\n ProjectAssistSidecar,\n ProjectAssistSidecarInput,\n ProjectAutomationCurve,\n ProjectAutomationLaneDesc,\n ProjectAutomationPoint,\n ProjectAutomationTargetKind,\n ProjectBounceOptions,\n ProjectChordSymbol,\n ProjectClip,\n ProjectClipCompSegment,\n ProjectClipDesc,\n ProjectClipFade,\n ProjectClipTake,\n ProjectCompileResult,\n ProjectFadeCurve,\n ProjectKeySegment,\n ProjectLoopMode,\n ProjectLoopRecordingDesc,\n ProjectLoopRecordingResult,\n ProjectMarker,\n ProjectMidiClipResult,\n ProjectMidiEvent,\n ProjectNotePairValidation,\n ProjectSource,\n ProjectTrack,\n ProjectTrackDesc,\n ProjectTrackKind,\n ProjectWarpAnchor,\n ProjectWarpMapDesc,\n Sf2InstrumentConfig,\n Sf2ProgramStatus,\n SourceBackend,\n SynthBodyType,\n SynthEngineMode,\n SynthEnumTables,\n SynthFilterModel,\n SynthFilterOutput,\n SynthModDestination,\n SynthModRouting,\n SynthModSource,\n SynthOscWaveform,\n SynthPatch,\n} from './project';\nexport {\n AutomationTargetKind,\n BUILTIN_SYNTH_WAVEFORMS,\n EXPECTED_PROJECT_ABI_VERSION,\n MarkerKind,\n PROJECT_AUTOMATION_TARGET_OPAQUE,\n PROJECT_AUTOMATION_TARGET_TRACK_FADER_DB,\n PROJECT_AUTOMATION_TARGET_TRACK_PAN,\n Project,\n projectAbiVersion,\n SYNTH_BODY_TYPES,\n SYNTH_ENGINE_MODES,\n SYNTH_FILTER_MODELS,\n SYNTH_FILTER_OUTPUTS,\n SYNTH_MOD_DESTINATIONS,\n SYNTH_MOD_SOURCES,\n SYNTH_OSC_WAVEFORMS,\n synthEnumTables,\n synthPresetNames,\n synthPresetPatch,\n} from './project';\nexport type {\n AcousticOptions,\n AcousticResult,\n AnalysisResult,\n AnalyzeBpmOptions,\n AnalyzeDynamicsOptions,\n AnalyzeRhythmOptions,\n AnalyzeSectionsOptions,\n AnalyzeTimbreOptions,\n AutomationCurve,\n Beat,\n BpmHypothesis,\n Chord,\n ChordAnalysisResult,\n ChordDetectionOptions,\n ChromaResult,\n CqtResult,\n Dynamics,\n EqBand,\n EqBandPhase,\n EqBandType,\n EqCoeffMode,\n EqMatchOptions,\n EqSpectrumSnapshot,\n EqStereoPlacement,\n GoniometerPoint,\n HpssResult,\n Key,\n KeyCandidate,\n KeyDetectionOptions,\n KeyProfileName,\n LufsResult,\n MasteringChainConfig,\n MasteringChainResult,\n MasteringChainStereoResult,\n MasteringLoudnessSummary,\n MasteringOptions,\n MasteringPreset,\n MasteringProcessorParams,\n MasteringReport,\n MasteringResult,\n MasteringStereoChainResult,\n MasteringStereoResult,\n MelodyPoint,\n MelodyResult,\n MelPowerResult,\n MelSpectrogramResult,\n MeterTap,\n MfccResult,\n MixerProcessResult,\n MixMeterSnapshot,\n MixOptions,\n MixResult,\n NoteSegment,\n NoteStretchOptions,\n PairAnalysis,\n PairProcessor,\n PanLaw,\n PanLawInput,\n PanLawName,\n PanMode,\n PitchCorrectOptions,\n PitchResult,\n RealtimeVoiceChangerConfigInput,\n RealtimeVoiceChangerPodConfig,\n RhythmFeatures,\n RirResult,\n RirSynthOptions,\n RoomEstimateOptions,\n RoomEstimateResult,\n RoomGeometryOptions,\n RoomMorphOptions,\n Section,\n SegmentMatrix,\n SendTiming,\n SoloProcessor,\n SonareCapabilities,\n SpectralEditMode,\n SpectralEditOptions,\n SpectralEditWindow,\n SpectralRegionOp,\n StageGainReduction,\n StereoAnalysis,\n StftPowerResult,\n StftResult,\n StreamingEqualizerConfig,\n StreamingMasteringChainConfig,\n StreamingPlatform,\n StreamingRetuneConfig,\n TempogramMode,\n Timbre,\n TimeSignature,\n VoicedFlags,\n VoicePresetId,\n} from './public_types';\nexport {\n ChordQuality,\n KeyProfile,\n Mode,\n PitchClass,\n SectionType,\n} from './public_types';\nexport type {\n AnalyzeBpmRequest,\n AnalyzeDynamicsRequest,\n AnalyzeImpulseResponseRequest,\n AnalyzeRhythmRequest,\n AnalyzeTimbreRequest,\n AnalyzeWithProgressRequest,\n BpmAnalysisResult,\n BpmCandidate,\n ChordFunctionalAnalysisRequest,\n DetectAcousticRequest,\n DetectChordsRequest,\n DetectKeyRequest,\n DetectOnsetsRequest,\n DynamicsAnalysisResult,\n EstimateRoomRequest,\n MusicAnalyzeRequest,\n RhythmAnalysisResult,\n RoomMorphRequest,\n SamplesRequest,\n TimbreAnalysisResult,\n TimbreFrame,\n} from './quick_analysis';\nexport {\n analyze,\n analyzeBpm,\n analyzeDynamics,\n analyzeImpulseResponse,\n analyzeRhythm,\n analyzeTimbre,\n analyzeWithProgress,\n chordFunctionalAnalysis,\n detectAcoustic,\n detectBeats,\n detectBpm,\n detectChords,\n detectDownbeats,\n detectKey,\n detectKeyCandidates,\n detectOnsets,\n estimateRoom,\n hasFfmpegSupport,\n roomMorph,\n synthesizeRir,\n} from './quick_analysis';\nexport type {\n ClipPageRequest,\n EngineAutomationPoint,\n EngineBounceOptions,\n EngineBounceResult,\n EngineBus,\n EngineCapabilities,\n EngineCaptureSource,\n EngineCaptureStatus,\n EngineClip,\n EngineFreezeOptions,\n EngineFreezeResult,\n EngineGraphSpec,\n EngineMarker,\n EngineMeterTelemetry,\n EngineMeterTelemetryWide,\n EngineMetronomeConfig,\n EngineMidiClipSchedule,\n EngineMidiEvent,\n EngineParameterInfo,\n EngineScopeTelemetry,\n EngineTelemetry,\n EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTrackLane,\n EngineTrackMonitorMode,\n EngineTrackSend,\n EngineTransportState,\n ExternalMidiEvent,\n MidiCcBindOptions,\n TrackMonitorMode,\n} from './realtime_engine';\nexport {\n ClipPageProvider,\n EXPECTED_ENGINE_ABI_VERSION,\n engineCapabilities,\n RealtimeEngine,\n} from './realtime_engine';\nexport { scaleCorrectionSemitones, scalePitchClassEnabled, scaleQuantizeMidi } from './scale';\nexport type { ProgressCallback } from './sonare.js';\nexport { StreamAnalyzer, streamAnalyzerConfigDefaults } from './stream_analyzer';\nexport type {\n AnalyzerStats,\n BarChord,\n ChordChange,\n FrameBuffer,\n PatternScore,\n ProgressiveEstimate,\n StreamConfig,\n StreamConfigDefaults,\n StreamFramesI16,\n StreamFramesU8,\n StreamQuantizeConfig,\n} from './stream_types';\nexport type {\n MixerRealtimeBuffer,\n RealtimeVoiceChangerInterleavedBuffer,\n RealtimeVoiceChangerMonoBuffer,\n RealtimeVoiceChangerPlanarBuffer,\n} from './streaming_mixing';\nexport {\n Mixer,\n RealtimeVoiceChanger,\n realtimeVoiceChangerPresetJson,\n realtimeVoiceChangerPresetNames,\n StreamingEqualizer,\n StreamingMasteringChain,\n StreamingRetune,\n validateRealtimeVoiceChangerPresetJson,\n} from './streaming_mixing';\nexport type { ValidateOptions } from './validation';\nexport type {\n BindWebMidiOptions,\n WebMidiBinding,\n WebMidiCcBinding,\n WebMidiInputInfo,\n} from './web_midi';\nexport { bindWebMidi, isWebMidiAvailable } from './web_midi';\nexport type {\n OfflineWorker,\n OfflineWorkerCallOptions,\n OfflineWorkerClientOptions,\n OfflineWorkerProgress,\n} from './worker_client';\nexport { OfflineWorkerClient, OfflineWorkerTask } from './worker_client';\n\n/** Row-major 2-D matrix as a flat buffer plus its dimensions. */\nexport type Matrix2dResult = WasmMatrix2dResult;\n/** NMF factor matrices { w, h } from {@link decompose}. */\nexport type DecomposeResult = WasmDecomposeResult;\n/** Harmonic / percussive / residual signals from {@link hpssWithResidual}. */\nexport type HpssWithResidualResult = WasmHpssWithResidualResult;\n\n// ============================================================================\n// Module State\n// ============================================================================\n\nlet module: SonareModule | null = null;\nlet initPromise: Promise<void> | null = null;\n\n// ============================================================================\n// Initialization\n// ============================================================================\n\n/**\n * Initialize the WASM module.\n * Must be called before using any analysis functions.\n *\n * @param options - Optional module configuration\n * @returns Promise that resolves when initialization is complete\n */\nexport async function init(options?: {\n locateFile?: (path: string, prefix: string) => string;\n wasmBinary?: ArrayBuffer | Uint8Array;\n moduleFactory?: (options?: {\n locateFile?: (path: string, prefix: string) => string;\n wasmBinary?: ArrayBuffer | Uint8Array;\n }) => Promise<SonareModule>;\n}): Promise<void> {\n if (module) {\n return;\n }\n\n if (initPromise) {\n return initPromise;\n }\n\n initPromise = (async () => {\n try {\n const createModule = options?.moduleFactory ?? (await import('./sonare.js')).default;\n module = await createModule(options);\n setSonareModule(module);\n } catch (error) {\n initPromise = null;\n throw error;\n }\n })();\n\n return initPromise;\n}\n\n/**\n * Check if the module is initialized.\n */\nexport function isInitialized(): boolean {\n return module !== null;\n}\n\n/**\n * Get the library version.\n */\nexport function version(): string {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.version();\n}\n\n/**\n * Return the capabilities of the loaded WASM build.\n *\n * This is synchronous and only describes the already-initialized module.\n */\nexport function capabilities(): SonareCapabilities {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.capabilities();\n}\n\n/** Return the initialized module's processors, parameters, and presets. */\nexport function capabilityCatalog(): CapabilityCatalog {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return JSON.parse(module.capabilityCatalog()) as CapabilityCatalog;\n}\n\n/**\n * Aggregate native ABI version: the per-subsystem ABI macros folded into one\n * 32-bit value. It bumps whenever any flat C POD layout changes, so callers can\n * detect an incompatible prebuilt binary. Matches the Node/Python `abiVersion()`.\n */\nexport function abiVersion(): number {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.abiVersion();\n}\n\nexport function engineAbiVersion(): number {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.engineAbiVersion();\n}\n\nexport function voiceChangerAbiVersion(): number {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.voiceChangerAbiVersion();\n}\n\n// Canonical ordinal order of the built-in voice-character presets, matching the\n// C ABI SonareVoiceCharacterPreset enum and SONARE_REALTIME_VOICE_CHANGER_PRESET_IDS.\nconst VOICE_PRESET_ORDINALS: readonly VoicePresetId[] = [\n 'neutral-monitor',\n 'bright-idol',\n 'soft-whisper',\n 'deep-narrator',\n 'robot-mascot',\n 'dark-villain',\n];\n\nfunction resolveVoicePresetOrdinal(preset: VoicePresetId | number): number {\n if (typeof preset === 'number') {\n if (!Number.isSafeInteger(preset) || preset < 0 || preset >= VOICE_PRESET_ORDINALS.length) {\n throw new RangeError(`Unknown voice-character preset ordinal: ${String(preset)}`);\n }\n return preset;\n }\n const ordinal = VOICE_PRESET_ORDINALS.indexOf(preset);\n if (ordinal < 0) {\n throw new Error(`Unknown voice character preset: ${preset}`);\n }\n return ordinal;\n}\n\n/**\n * Map a voice-character preset ordinal (or canonical id) to its canonical id\n * string (e.g. `'bright-idol'`). Unknown numeric ordinals return `null`;\n * unknown preset ids throw.\n */\nexport function voiceCharacterPresetId(preset: VoicePresetId | number): VoicePresetId | null {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n if (\n typeof preset === 'number' &&\n (!Number.isSafeInteger(preset) || preset < 0 || preset >= VOICE_PRESET_ORDINALS.length)\n ) {\n return null;\n }\n return module.voiceCharacterPresetId(resolveVoicePresetOrdinal(preset)) as VoicePresetId;\n}\n\n/**\n * Return the canonical (normalized) flat POD config for a built-in voice\n * preset, skipping the JSON round-trip. Accepts a canonical preset id or its\n * integer ordinal. Invalid ordinals throw.\n */\nexport function realtimeVoiceChangerPresetConfig(\n preset: VoicePresetId | number,\n): RealtimeVoiceChangerPodConfig {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.realtimeVoiceChangerPresetConfig(resolveVoicePresetOrdinal(preset));\n}\n\n// ============================================================================\n// Re-exports\n// ============================================================================\n\nexport { PitchClass as Pitch } from './public_types';\n"],"mappings":"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","names":["ErrorCode","module","requireModule","requireModule","requireModule","requireModule","requireModule","requireModule","requireModule","onsetEnvelope","requireModule","onsetEnvelope","requireModule","requireModule","requireModule","resolveEffectFftOptions","resolveHardMask","init","requireModule","validatePositiveIntegers","requireModule","module","requireModule","abiVersion","module","capabilities","module","module","module","module"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/module_state.ts","../src/codes.ts","../src/sample_bank.ts","../src/validation.ts","../src/project_internal.ts","../src/align_take.ts","../src/_effects_common.ts","../src/effects_note_ops.ts","../src/effects_percussive.ts","../src/_fft_options.ts","../src/effects_separation.ts","../src/effects_spectral.ts","../src/effects_timepitch.ts","../src/effects_voice_change.ts","../src/_chain_config.ts","../src/mastering_chain.ts","../src/mastering_core.ts","../src/mastering_dynamics.ts","../src/mixing_oneshot.ts","../src/repair_dereverb.ts","../src/repair_impulsive.ts","../src/repair_noise.ts","../src/repair_trim.ts","../src/feature_core.ts","../src/feature_decompose.ts","../src/_feature_validation.ts","../src/feature_inverse.ts","../src/feature_loudness.ts","../src/feature_music.ts","../src/feature_pitch.ts","../src/feature_resample.ts","../src/feature_spectral.ts","../src/feature_spectrogram.ts","../src/metering.ts","../src/public_types_music.ts","../src/analysis_helpers.ts","../src/quick_analysis.ts","../src/audio.ts","../src/opfs_clip_pages.ts","../src/clip_page_streamer.ts","../src/live_audio.ts","../src/mixing_assistant.ts","../src/playback_renderer.ts","../src/polyphony.ts","../src/instrument_types.ts","../src/project_class.ts","../src/project_synth.ts","../src/project_types.ts","../src/realtime_engine.ts","../src/scale.ts","../src/stream_analyzer.ts","../src/mixer.ts","../src/realtime_voice_changer.ts","../src/streaming_processors.ts","../src/transcribe.ts","../src/web_midi.ts","../src/worker_client.ts","../src/index.ts"],"sourcesContent":["/**\n * Numeric error codes carried by a {@link SonareError}. Mirrors the C ABI\n * `SonareError` enum (and the Node / Python surfaces), so the same failure\n * reports the same numeric code on every binding.\n */\nexport enum ErrorCode {\n Ok = 0,\n FileNotFound = 1,\n InvalidFormat = 2,\n DecodeFailed = 3,\n InvalidParameter = 4,\n OutOfMemory = 5,\n NotSupported = 6,\n InvalidState = 7,\n Cancelled = 8,\n EncodeFailed = 9,\n Unknown = 99,\n}\n\n/**\n * Error thrown by libsonare on a native (C++) failure. Carries a numeric\n * {@link ErrorCode} `code` plus its canonical `codeName`, so callers can branch\n * on the cause instead of matching message text.\n *\n * Narrow a caught value with {@link isSonareError} or with `instanceof`; both\n * accept the same values. The Node package exports the same class under the\n * same name.\n */\nexport class SonareError extends Error {\n /** Numeric error code, equal to an {@link ErrorCode} value. */\n readonly code: number;\n /** Canonical name of `code`, e.g. `'InvalidParameter'`. */\n readonly codeName: string;\n\n constructor(code: number, codeName: string, message: string) {\n super(message);\n this.name = 'SonareError';\n this.code = code;\n this.codeName = codeName;\n }\n\n /**\n * Brand-based `instanceof`: an error that carries the shape narrows here even\n * when it is not literally an instance of this class. That is not a\n * hypothetical — an error posted from the analysis worker arrives as a\n * structured clone with its prototype gone, which a prototype-based\n * `instanceof` would silently miss. Delegates to {@link isSonareError} so the\n * two never disagree.\n */\n static [Symbol.hasInstance](value: unknown): value is SonareError {\n return isSonareError(value);\n }\n}\n\n/**\n * Type guard: whether a caught value is a libsonare {@link SonareError}.\n *\n * Duck-typed on purpose: a value that crossed a worker boundary has lost its\n * prototype, so a prototype check would miss it.\n */\nexport function isSonareError(value: unknown): value is SonareError {\n return (\n value instanceof Error &&\n (value as { name?: unknown }).name === 'SonareError' &&\n typeof (value as { code?: unknown }).code === 'number'\n );\n}\n","import { ErrorCode, SonareError } from './errors';\nimport type { SonareModule } from './sonare.js';\n\nlet wrappedModule: SonareModule | null = null;\n\n/**\n * Shape of the structured info the native `sonareExceptionInfo(ptr)` returns.\n */\ninterface NativeExceptionInfo {\n code: number;\n codeName: string;\n message: string;\n}\n\n/**\n * Recover the native exception-object pointer from a value thrown across the\n * WASM boundary. emscripten surfaces a C++ throw in two shapes depending on the\n * toolchain/exception mode:\n * - a raw pointer number (older / classic surfacing), or\n * - a `CppException` object exposing the pointer as `excPtr` (emscripten with\n * `-fexceptions`).\n * Returns null when the thrown value is neither (a genuine JS error), so the\n * caller rethrows it unchanged.\n */\nexport function nativeExceptionPtr(error: unknown): number | null {\n if (typeof error === 'number') {\n return error;\n }\n if (error !== null && typeof error === 'object') {\n const ptr = (error as { excPtr?: unknown }).excPtr;\n if (typeof ptr === 'number') {\n return ptr;\n }\n }\n return null;\n}\n\n/**\n * Turn a thrown native exception pointer into a {@link SonareError}. The bound\n * `sonareExceptionInfo` decodes the pointer back into { code, codeName,\n * message }, then `sonareReleaseException` drops the reference emscripten's\n * `__cxa_throw` took before rethrowing the pointer into JS.\n *\n * The release is mandatory, not an optimization: no C++ frame catches the\n * exception, so that reference is the only one and nothing else ever drops it.\n * Every rejected input would otherwise leak its exception object for the\n * lifetime of the module — and rejection-as-control-flow (re-validating markers\n * or clips on each edit, a scrub handle seeking every pointer move) is a\n * documented usage of this API. It runs in a `finally` so a decode failure\n * still frees, and after decoding because freeing invalidates the message.\n */\nfunction makeSonareError(raw: SonareModule, thrown: number): SonareError {\n let code: number = ErrorCode.Unknown;\n let codeName = 'Unknown';\n let message = `libsonare native exception (${thrown})`;\n try {\n const info = (\n raw as unknown as { sonareExceptionInfo?: (ptr: number) => NativeExceptionInfo }\n ).sonareExceptionInfo?.(thrown);\n if (info) {\n code = info.code ?? code;\n codeName = info.codeName ?? codeName;\n message = info.message || message;\n }\n } catch {\n // Fall back to the generic message if decoding fails.\n } finally {\n try {\n raw.sonareReleaseException(thrown);\n } catch {\n // A module built before the release binding existed still yields an error\n // object; it just keeps leaking, which is what this replaces.\n }\n }\n return new SonareError(code, codeName, message);\n}\n\n/**\n * Wrap the embind module so a native C++ exception (which surfaces as a raw\n * pointer number or a `CppException` carrying one) is rethrown as a\n * {@link SonareError}. Only function-valued\n * members are wrapped, and the wrapper is cached per member so repeated access\n * stays cheap; non-function members (typed-array heap views, etc.) pass through\n * unchanged.\n */\nfunction wrapModuleErrors(raw: SonareModule): SonareModule {\n const cache = new Map<PropertyKey, unknown>();\n const objectCache = new WeakMap<object, unknown>();\n const convert = (error: unknown): never => {\n const ptr = nativeExceptionPtr(error);\n if (ptr !== null) {\n throw makeSonareError(raw, ptr);\n }\n throw error;\n };\n\n const wrapNativeObject = (value: unknown): unknown => {\n if (value === null || typeof value !== 'object') {\n return value;\n }\n if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer || value instanceof Promise) {\n return value;\n }\n // Plain result data carries no native methods, and a Proxy cannot be\n // structured-cloned, so wrapping it would block postMessage to a worker.\n const proto = Object.getPrototypeOf(value);\n if (Array.isArray(value) || proto === Object.prototype || proto === null) {\n return value;\n }\n const objectValue = value as object;\n const cached = objectCache.get(objectValue);\n if (cached) {\n return cached;\n }\n const methodCache = new Map<PropertyKey, unknown>();\n const wrapped = new Proxy(objectValue, {\n get(target, prop, receiver) {\n const member = Reflect.get(target, prop, receiver);\n if (typeof member !== 'function') {\n return member;\n }\n const cachedMethod = methodCache.get(prop);\n if (cachedMethod) {\n return cachedMethod;\n }\n const method = member as (...a: unknown[]) => unknown;\n const wrappedMethod = (...args: unknown[]) => {\n try {\n return wrapNativeObject(Reflect.apply(method, target, args));\n } catch (error) {\n return convert(error);\n }\n };\n methodCache.set(prop, wrappedMethod);\n return wrappedMethod;\n },\n });\n objectCache.set(objectValue, wrapped);\n return wrapped;\n };\n\n const wrapFunction = (value: (...a: unknown[]) => unknown): unknown => {\n const fnCache = new Map<PropertyKey, unknown>();\n return new Proxy(value, {\n get(target, prop, receiver) {\n const member = Reflect.get(target, prop, receiver);\n if (typeof member !== 'function') {\n return member;\n }\n const cachedMember = fnCache.get(prop);\n if (cachedMember) {\n return cachedMember;\n }\n const fn = member as (...a: unknown[]) => unknown;\n const wrappedMember = (...args: unknown[]) => {\n try {\n return wrapNativeObject(Reflect.apply(fn, target, args));\n } catch (error) {\n return convert(error);\n }\n };\n fnCache.set(prop, wrappedMember);\n return wrappedMember;\n },\n apply(t, thisArg, args) {\n try {\n return wrapNativeObject(Reflect.apply(t, thisArg, args as unknown[]));\n } catch (error) {\n return convert(error);\n }\n },\n construct(t, args, newTarget) {\n try {\n return wrapNativeObject(Reflect.construct(t, args as unknown[], newTarget)) as object;\n } catch (error) {\n return convert(error) as object;\n }\n },\n });\n };\n\n return new Proxy(raw, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (typeof value !== 'function') {\n return value;\n }\n const cached = cache.get(prop);\n if (cached) {\n return cached;\n }\n // Wrap as a Proxy (not a plain function) so embind class constructors\n // invoked via `new module.Foo(...)` keep their `[[Construct]]` behaviour\n // and prototype while still converting thrown native pointers.\n const wrapped = wrapFunction(value as (...a: unknown[]) => unknown);\n cache.set(prop, wrapped);\n return wrapped;\n },\n }) as SonareModule;\n}\n\nexport function setSonareModule(module: SonareModule): void {\n wrappedModule = wrapModuleErrors(module);\n}\n\nexport function getSonareModule(): SonareModule {\n if (!wrappedModule) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return wrappedModule;\n}\n","import type { ProjectAutomationCurve } from './project_types';\nimport type {\n AutomationCurve,\n MeterTap,\n PanLawInput,\n PanMode,\n SendTiming,\n SidechainSourceKind,\n} from './public_types';\n\n/** Resolve a numeric ordinal in an inclusive range without coercion. */\nexport function resolveOrdinalInRange(\n value: unknown,\n min: number,\n max: number,\n enumName: string,\n): number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < min || value > max) {\n throw new RangeError(`Invalid ${enumName}: ${String(value)}`);\n }\n return value;\n}\n\n/** Resolve a public enum spelling or ordinal without permitting unknown values. */\nexport function resolveEnumOrdinal(\n value: unknown,\n values: Readonly<Record<string, number>>,\n enumName: string,\n): number {\n if (typeof value === 'number') {\n const ordinals = Object.values(values);\n const ordinal = resolveOrdinalInRange(\n value,\n Math.min(...ordinals),\n Math.max(...ordinals),\n enumName,\n );\n if (!ordinals.includes(ordinal)) {\n throw new RangeError(`Invalid ${enumName}: ${String(value)}`);\n }\n return ordinal;\n }\n if (typeof value === 'string') {\n const ordinal = values[value];\n if (ordinal !== undefined) {\n return ordinal;\n }\n }\n throw new RangeError(`Invalid ${enumName}: ${String(value)}`);\n}\n\n/**\n * Automation curve spellings and their `SonareAutomationCurve` ordinals.\n *\n * Single source of truth for the vocabulary: {@link AutomationCurve} and\n * {@link ProjectAutomationCurve} are derived from these keys, so a spelling\n * cannot be documented without resolving, or resolve without being documented.\n */\nexport const AUTOMATION_CURVE_VALUES = {\n linear: 0,\n exponential: 1,\n hold: 2,\n 's-curve': 3,\n} as const;\n\n/**\n * The Project facade additionally accepts the legacy `'scurve'` spelling for\n * compatibility with project data written before `'s-curve'` was canonical.\n * The Node package declares the same pair of tables, so a breakpoint accepted\n * by one facade resolves to the same ordinal on the other.\n */\nexport const PROJECT_AUTOMATION_CURVE_VALUES = {\n ...AUTOMATION_CURVE_VALUES,\n scurve: 3,\n} as const;\nconst PAN_LAW_VALUES: Readonly<Record<string, number>> = {\n const3db: 0,\n 'const-3db': 0,\n '-3db': 0,\n 'const4.5db': 1,\n 'const-4.5db': 1,\n '-4.5db': 1,\n const6db: 2,\n 'const-6db': 2,\n '-6db': 2,\n linear0db: 3,\n 'linear-0db': 3,\n linear: 3,\n '0db': 3,\n} as const;\nconst PAN_MODE_VALUES = {\n balance: 0,\n pan: 1,\n stereopan: 1,\n 'stereo-pan': 1,\n dualpan: 2,\n 'dual-pan': 2,\n} as const;\nconst METER_TAP_VALUES = { preFader: 0, postFader: 1 } as const;\nconst SEND_TIMING_VALUES = { postFader: 0, preFader: 1 } as const;\nconst SIDECHAIN_SOURCE_KIND_VALUES = { track: 0, bus: 1 } as const;\nconst TRACK_MONITOR_MODE_VALUES = { off: 0, pfl: 1, afl: 2 } as const;\n\nexport function automationCurveCode(curve: AutomationCurve): number {\n return resolveEnumOrdinal(curve, AUTOMATION_CURVE_VALUES, 'automation curve');\n}\n\n/** Resolve a Project automation breakpoint curve, legacy spellings included. */\nexport function projectAutomationCurveCode(curve: ProjectAutomationCurve | undefined): number {\n return resolveEnumOrdinal(curve ?? 'linear', PROJECT_AUTOMATION_CURVE_VALUES, 'automation curve');\n}\n\nexport function panLawCode(panLaw: PanLawInput): number {\n const normalized = typeof panLaw === 'string' ? panLaw.toLowerCase().replace(/_/g, '-') : panLaw;\n return resolveEnumOrdinal(normalized, PAN_LAW_VALUES, 'pan law');\n}\n\nexport function panModeCode(panMode: PanMode | number): number {\n const normalized =\n typeof panMode === 'string' ? panMode.replace(/_/g, '-').toLowerCase() : panMode;\n return resolveEnumOrdinal(normalized, PAN_MODE_VALUES, 'pan mode');\n}\n\nexport function meterTapCode(tap: MeterTap | number): number {\n return resolveEnumOrdinal(tap, METER_TAP_VALUES, 'meter tap');\n}\n\nexport function sendTimingCode(timing: SendTiming | number): number {\n // Mirrors SonareSendTiming: post-fader is 0 (so an omitted/zeroed value is\n // post-fader), pre-fader is 1. A raw number is passed through as the C ABI int.\n // An unknown string is rejected rather than silently routed to post-fader,\n // matching the sibling enum-code helpers and Node's sendTimingValue.\n return resolveEnumOrdinal(timing, SEND_TIMING_VALUES, 'send timing');\n}\n\n/** Resolve a sidechain source kind to its `SonareSidechainSourceKind` ordinal. */\nexport function sidechainSourceKindCode(kind: SidechainSourceKind | number): number {\n return resolveEnumOrdinal(kind, SIDECHAIN_SOURCE_KIND_VALUES, 'sidechain source kind');\n}\n\n/** Resolve a per-track PFL/AFL monitor mode to its C-ABI ordinal. */\nexport function trackMonitorModeCode(mode: unknown): number {\n return resolveEnumOrdinal(mode, TRACK_MONITOR_MODE_VALUES, 'track monitor mode');\n}\n","import type { SampleDesc, SampleZoneDesc } from './instrument_types';\nimport { projectModule, type WasmSampleBank } from './project_internal';\n\n/**\n * Host-supplied PCM for the sample synthesis engine: a bank of float samples\n * plus key/velocity keymaps, bound alongside a {@link SynthPatch} whose\n * `engineMode` is `'sample'`.\n *\n * {@link Project.loadSoundFont} is the other door into sampled playback — it\n * parses a container and brings its own generator model. This one takes\n * waveforms a host already has, described by nothing but a keymap, so playing\n * them does not require authoring an SF2. Decoding is the caller's job, and\n * WASM has no host filesystem: the bank takes mono float frames from memory.\n *\n * A bank is built on the control thread and then read as immutable data. Add\n * every sample and zone BEFORE the bounce that binds it starts: the pool is\n * contiguous and moves as it grows, so a sample added while something sounds\n * invalidates the voices reading it.\n *\n * The embind handle is not garbage-collected, so release it with\n * {@link SampleBank.delete} once every bounce that names it has finished.\n *\n * @example\n * ```typescript\n * const bank = new SampleBank();\n * try {\n * const index = bank.addSample(pcm, { rootKey: 60, sourceRate: 44100 });\n * bank.addZone({ sampleIndex: index }); // the whole keyboard\n * const audio = project.bounceWithSynthInstrument(\n * { engineMode: 'sample', sampleSet: 0, sampleBank: bank },\n * { totalFrames: 24000 },\n * );\n * } finally {\n * bank.delete();\n * }\n * ```\n */\nexport class SampleBank {\n private readonly native: WasmSampleBank;\n private released = false;\n\n /**\n * Identity a binding names this bank by, so no raw pointer crosses into JS.\n * Hosts pass the `SampleBank` itself as `sampleBank`.\n *\n * @internal\n */\n readonly nativeId: number;\n\n /** Create an empty bank. */\n constructor() {\n this.native = new (projectModule().SampleBank)();\n this.nativeId = this.native.id;\n }\n\n /**\n * Copy mono float frames into the bank and return the new sample's index,\n * which {@link SampleZoneDesc.sampleIndex} names. The frames are copied, so\n * the array may be reused afterwards.\n *\n * Loop points are clamped inside the sample and a loop mode whose loop\n * survives the clamp empty is dropped, so a malformed loop plays as an\n * unlooped sample rather than as a wrap over nothing. An empty array, and a\n * bank that would exceed 67,108,864 sample points, throw.\n *\n * A NaN or Inf frame, `fineTuneCents` or `sourceRate` throws too, and the\n * bank is left unchanged. Such a value is unattributable once stored: the\n * reader's interpolation spreads one bad frame across the whole sustain, and\n * a bad tuning offset renders the voice silent with no error raised.\n */\n addSample(data: Float32Array, desc: SampleDesc = {}): number {\n return this.native.addSample(data, desc);\n }\n\n /**\n * Append a key/velocity rectangle to a keymap set, creating any sets below\n * it. A patch names a set; the first zone in it covering a note is the one\n * that sounds.\n *\n * Every bound defaults on its own (see {@link SampleZoneDesc}), so an empty\n * rectangle is the whole keyboard at every velocity and narrowing one axis\n * leaves the other whole. A `sampleIndex` the bank does not have, an inverted\n * key or velocity range, and a `setIndex` at or above 4096 all throw.\n */\n addZone(zone: SampleZoneDesc = {}): void {\n const { setIndex, ...rest } = zone;\n this.native.addZone(setIndex ?? 0, rest);\n }\n\n /** Samples added so far. */\n sampleCount(): number {\n return this.native.sampleCount();\n }\n\n /** Keymap sets the bank has (one past the highest index used). */\n setCount(): number {\n return this.native.setCount();\n }\n\n /** Release the underlying WASM object. Idempotent, as the Node facade is. */\n delete(): void {\n if (this.released) {\n return;\n }\n this.released = true;\n this.native.delete();\n }\n\n /** Alias for {@link SampleBank.delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n","import { ErrorCode, SonareError } from './errors';\n\n/**\n * Per-call validation options accepted by guarded wrappers. Empty-buffer\n * checks are always performed; pass `{ validate: false }` to opt out of the\n * O(n) NaN/Inf scan on hot paths.\n *\n * `{ validate: false }` only skips this JS-side pre-scan (which raises a\n * `RangeError` naming the exact offending index). It is NOT a way to push\n * non-finite samples into the core: the native layer always re-validates the\n * buffer — through `validate_offline_audio_input` for the offline-analysis\n * entry points, and through the computation's own per-sample guard where a call\n * takes no sample rate to validate against (the waveform bucket kernels) —\n * matching the C ABI / Node / Python surfaces, so an NaN/Inf buffer still\n * throws, just with a generic native message instead of the indexed JS one.\n */\nexport interface ValidateOptions {\n validate?: boolean;\n}\n\n/**\n * Offline-analysis sample-rate bounds, mirroring the C++ core limits\n * (`sonare::kMinAudioSampleRate` / `kMaxAudioSampleRate` in `core/audio.h`).\n * Every guarded WASM entry point rejects the same out-of-range rates the C ABI,\n * Node, and Python surfaces do.\n */\nexport const MIN_AUDIO_SAMPLE_RATE = 8000;\nexport const MAX_AUDIO_SAMPLE_RATE = 384000;\n\nfunction assertNonEmptySamples(\n fnName: string,\n samples: ArrayLike<number>,\n argName = 'samples',\n): void {\n if (samples.length === 0) {\n throw new RangeError(`${fnName}: ${argName} must not be empty`);\n }\n}\n\nfunction assertFiniteSamples(\n fnName: string,\n samples: ArrayLike<number>,\n validate: boolean,\n argName = 'samples',\n): void {\n if (!validate) {\n return;\n }\n for (let i = 0; i < samples.length; i++) {\n const v = samples[i] as number;\n if (!Number.isFinite(v)) {\n throw new RangeError(`${fnName}: ${argName} contains NaN or Inf at index ${i}`);\n }\n }\n}\n\nexport function assertSamples(\n fnName: string,\n samples: ArrayLike<number>,\n validate: boolean,\n argName = 'samples',\n): void {\n assertNonEmptySamples(fnName, samples, argName);\n assertFiniteSamples(fnName, samples, validate, argName);\n}\n\n/**\n * `assertSamples` restricted to the span a windowed entry point actually reads.\n *\n * The emptiness check still covers the whole buffer, and the reported index is\n * the absolute one, so the message keeps naming the sample the caller passed.\n * What narrows is the scan: a windowed call refuses a non-finite sample inside\n * its frame and is indifferent to one outside it, which is the contract the C\n * ABI states and the cost model it promises -- per call the scan is bounded by\n * the frame, not by the length of the buffer being polled.\n */\nexport function assertSamplesInWindow(\n fnName: string,\n samples: ArrayLike<number>,\n validate: boolean,\n windowStart: number,\n windowLength: number,\n argName = 'samples',\n): void {\n assertNonEmptySamples(fnName, samples, argName);\n if (!validate) {\n return;\n }\n // Floored and ceiled before use: a fractional offset is refused by the layer\n // that owns it, but an index of 100.5 reads `undefined` out of the buffer and\n // would be reported here as a non-finite sample that is not there.\n const start = Math.min(Math.max(Math.floor(windowStart), 0), samples.length);\n const stop = Math.min(start + Math.max(Math.ceil(windowLength), 0), samples.length);\n for (let i = start; i < stop; i++) {\n const v = samples[i] as number;\n if (!Number.isFinite(v)) {\n throw new RangeError(`${fnName}: ${argName} contains NaN or Inf at index ${i}`);\n }\n }\n}\n\nexport function assertFiniteScalar(fnName: string, value: number, argName: string): void {\n if (!Number.isFinite(value)) {\n throw new RangeError(`${fnName}: ${argName} must be a finite number`);\n }\n}\n\n/**\n * A NaN gamma is the automatic-bandwidth sentinel the variable-Q transform\n * documents, alongside a negative value, so only an infinity is out of domain.\n */\nexport function assertVqtGamma(fnName: string, gamma: number): void {\n if (gamma === Number.POSITIVE_INFINITY || gamma === Number.NEGATIVE_INFINITY) {\n throw new RangeError(`${fnName}: gamma must not be infinite`);\n }\n}\n\nexport function assertSampleRate(fnName: string, sampleRate: number, argName = 'sampleRate'): void {\n // Two refusals, not one: 22050.7 sits inside the range, so reporting it as\n // out of range names an argument that is not the one at fault. `argName` is\n // the same point for a rate the caller spelled something else, such as a\n // resampler's source and target.\n if (!Number.isInteger(sampleRate)) {\n throw new RangeError(`${fnName}: ${argName} must be an integer`);\n }\n if (sampleRate < MIN_AUDIO_SAMPLE_RATE || sampleRate > MAX_AUDIO_SAMPLE_RATE) {\n throw new RangeError(\n `${fnName}: ${argName} out of supported range [${MIN_AUDIO_SAMPLE_RATE}, ${MAX_AUDIO_SAMPLE_RATE}]`,\n );\n }\n}\n\n/** Validate and retain the public Audio.fromBuffer construction contract. */\nexport function validateAudioBuffer(samples: Float32Array, sampleRate: number): void {\n assertSamples('Audio.fromBuffer', samples, true);\n assertSampleRate('Audio.fromBuffer', sampleRate);\n}\n\n/** Bounds of the native `int` every embind argument below is narrowed into. */\nexport const C_INT_MIN = -2147483648;\nexport const C_INT_MAX = 2147483647;\n\n/**\n * Reject an argument embind's declared-`int` narrowing would wrap.\n *\n * A positional embind parameter declared `int` WRAPS rather than saturates, so\n * a kernel of `2 ** 32` arrives as 0 and `2 ** 32 + 1` as 1 — both values the\n * native guards accept, so the call succeeds having separated on a setting the\n * caller never asked for. (The options-object path narrows through\n * `checkedIntFromVal`, which refuses the same inputs in the module; this is the\n * positional path's equivalent.)\n *\n * Reported as the branded `SonareError` carrying `InvalidParameter` rather than\n * a `RangeError`, because the class follows what the rejection stands in for: a\n * `RangeError` is this surface refusing an argument on its own authority, while\n * this one pre-empts a native refusal the caller would have received under that\n * code had the narrowing not wrapped the value into the accepted domain first.\n * The agreement with the Node and Python surfaces is asserted by the Node\n * package's `tests/narrowing-code-parity.test.ts`, which drives one value\n * through all three — weakening this check turns that red.\n */\nexport function assertInt32(fnName: string, value: number, argName: string): void {\n if (!Number.isInteger(value) || value < C_INT_MIN || value > C_INT_MAX) {\n throw new SonareError(\n ErrorCode.InvalidParameter,\n 'InvalidParameter',\n `${fnName}: ${argName} must be an integer within the signed 32-bit range`,\n );\n }\n}\n\n/**\n * Check both HPSS kernels before embind narrows them.\n *\n * Parity, positivity and the ceiling stay the core's to enforce, and it names\n * the median filter that rejected the value. What cannot be deferred is the\n * narrowing itself: a wrapped kernel arrives as a legal one and separates on it.\n *\n * These two arrive POSITIONALLY, so they never pass through the options-bag\n * reader and inherit none of its checks. That is what separates this from\n * {@link assertPercussiveSeparation}, which duplicates a reader check to improve\n * a message; here there is no reader to duplicate.\n */\nexport function assertHpssKernels(\n fnName: string,\n kernelHarmonic: number,\n kernelPercussive: number,\n): void {\n assertInt32(fnName, kernelHarmonic, 'kernelHarmonic');\n assertInt32(fnName, kernelPercussive, 'kernelPercussive');\n}\n\nfunction assertIntegralField(fnName: string, value: number, argName: string): void {\n if (!Number.isInteger(value)) {\n throw new SonareError(\n ErrorCode.InvalidParameter,\n 'InvalidParameter',\n `${fnName}: ${argName} must be an integer`,\n );\n }\n}\n\n/**\n * Percussive-event separation fields, as the request objects carry them.\n */\nexport interface PercussiveSeparationFields {\n nFft?: number;\n hopLength?: number;\n hpssKernelHarmonic?: number;\n hpssKernelPercussive?: number;\n}\n\n/**\n * Check the percussive-event separation's framing and kernels for integrality.\n *\n * All four fields reach the module through one options-bag reader, which now\n * refuses a fractional value itself, so this is the diagnostic rather than the\n * guarantee: it fires first and names the function, where the reader can only\n * name the field. Both reject the same set, so they cannot disagree about an\n * input — only about how the message reads. Do not narrow this to fields the\n * reader misses; there are none, and a check scoped to a gap that no longer\n * exists is how a stale justification outlives its divergence.\n *\n * The fields are iterated rather than named at each call site so a new one is\n * visible here. Absence means the default, so an omitted field is not resolved.\n */\nexport function assertPercussiveSeparation(\n fnName: string,\n options: PercussiveSeparationFields,\n): void {\n const fields = ['nFft', 'hopLength', 'hpssKernelHarmonic', 'hpssKernelPercussive'] as const;\n for (const field of fields) {\n const value = options[field];\n if (value !== undefined) {\n assertIntegralField(fnName, value, field);\n }\n }\n}\n\nexport function assertNonNegativeInteger(fnName: string, value: number, argName: string): void {\n if (!Number.isInteger(value) || value < 0) {\n throw new RangeError(`${fnName}: ${argName} must be a non-negative integer`);\n }\n}\n\n/** Integer strictly greater than zero, up to the native `int` ceiling. */\nexport function assertPositiveInteger(fnName: string, value: number, argName: string): void {\n // Two refusals, not one: 512.7 is positive, so reporting it as non-positive\n // names a property it has. The ceiling travels with the sign rather than with\n // integrality, because both describe a value the native `int` can carry.\n if (!Number.isInteger(value)) {\n throw new RangeError(`${fnName}: ${argName} must be an integer`);\n }\n if (value <= 0 || value > C_INT_MAX) {\n throw new RangeError(`${fnName}: ${argName} must be a positive integer`);\n }\n}\n\n/**\n * Split \"not an integer\" into the two mistakes it can be: `TypeError` when the\n * value is not a `number` at all, `RangeError` when it is a number but not\n * integral -- the right-type, wrong-domain half of the same message.\n *\n * `Number.isInteger` alone answers both, which is why a single check reads as\n * sufficient; what it cannot do is say which one happened, and a caller can act\n * only on the mistake they made. The classes are the contract on this surface,\n * so a sibling argument in the same call must not report a fraction differently\n * from this one.\n */\nexport function assertIntegerValue(\n fnName: string,\n value: unknown,\n argName: string,\n): asserts value is number {\n if (typeof value !== 'number') {\n throw new TypeError(`${fnName}: ${argName} must be an integer`);\n }\n if (!Number.isInteger(value)) {\n throw new RangeError(`${fnName}: ${argName} must be an integer`);\n }\n}\n\n/** Even integer in `[min, max]`, for an FFT-style size where only parity matters. */\nexport function assertEvenIntegerAtLeast(\n fnName: string,\n value: number,\n argName: string,\n min: number,\n max: number,\n): void {\n // Range and parity are separate refusals: 2 ** 31 is already even, so telling\n // its caller the value must be even names a property it has.\n if (!Number.isInteger(value) || value < min || value > max) {\n throw new RangeError(`${fnName}: ${argName} must be an integer in [${min}, ${max}]`);\n }\n if (value % 2 !== 0) {\n throw new RangeError(`${fnName}: ${argName} must be an even integer`);\n }\n}\n\n/** General integer-in-`[min, max]` check, for a bound {@link assertU7}/{@link assertNibble} don't cover. */\nexport function assertBoundedInteger(\n fnName: string,\n value: number,\n argName: string,\n min: number,\n max: number,\n): void {\n if (!Number.isInteger(value) || value < min || value > max) {\n throw new RangeError(`${fnName}: ${argName} must be an integer in [${min}, ${max}]`);\n }\n}\n\nexport function assertU7(fnName: string, value: number, argName: string): number {\n if (!Number.isInteger(value) || value < 0 || value > 127) {\n throw new RangeError(`${fnName}: ${argName} must be an integer in [0, 127]`);\n }\n return value;\n}\n\nexport function assertNibble(fnName: string, value: number, argName: string): number {\n if (!Number.isInteger(value) || value < 0 || value > 15) {\n throw new RangeError(`${fnName}: ${argName} must be an integer in [0, 15]`);\n }\n return value;\n}\n\nexport function assertU32(fnName: string, value: number, argName: string): void {\n if (!Number.isInteger(value) || value < 0 || value > 0xffffffff) {\n throw new RangeError(`${fnName}: ${argName} must be an integer in [0, 4294967295]`);\n }\n}\n\n/**\n * Convert a caller-supplied index array to `Int32Array`, refusing any element\n * the conversion would change rather than folding it.\n *\n * `Int32Array.from(values, Math.trunc)` turns the sample index `1000.7` into\n * `1000` and `2 ** 31` into `-2 ** 31`. The C ABI takes `const int*`, so both\n * arrive as values nothing downstream can separate from ones the caller chose.\n * An `Int32Array` is returned as-is: its elements are already exact.\n */\nexport function toInt32Array(\n fnName: string,\n values: Int32Array | ArrayLike<number>,\n argName: string,\n): Int32Array {\n if (values instanceof Int32Array) {\n return values;\n }\n const out = new Int32Array(values.length);\n for (let i = 0; i < values.length; i++) {\n const element = values[i];\n // The element shape of `assertIntegerValue`, and it splits the same way: the\n // class says whether the entry was the wrong type or the wrong domain, and a\n // sibling element in the same array must not report a fraction differently.\n if (typeof element !== 'number') {\n throw new TypeError(`${fnName}: ${argName}[${i}] must be an integer`);\n }\n if (!Number.isInteger(element)) {\n throw new RangeError(`${fnName}: ${argName}[${i}] must be an integer`);\n }\n if (element < C_INT_MIN || element > C_INT_MAX) {\n throw new RangeError(\n `${fnName}: ${argName}[${i}] must be an integer in [${C_INT_MIN}, ${C_INT_MAX}]`,\n );\n }\n out[i] = element;\n }\n return out;\n}\n\nexport function assertInterleavedSamples(\n fnName: string,\n samples: ArrayLike<number>,\n channels: number,\n validate: boolean,\n): void {\n assertSamples(fnName, samples, validate);\n assertPositiveInteger(fnName, channels, 'channels');\n if (samples.length % channels !== 0) {\n throw new RangeError(`${fnName}: samples length must be a multiple of channels`);\n }\n}\n","import { projectAutomationCurveCode, resolveEnumOrdinal } from './codes';\nimport type {\n BuiltinSynthBinding,\n SampleDesc,\n SampleZoneDesc,\n Sf2InstrumentConfig,\n Sf2ProgramStatus,\n SynthEnumTables,\n SynthPatch,\n} from './instrument_types';\nimport { getSonareModule } from './module_state';\nimport type {\n AlignTakeToReferenceRequest,\n AlignTakeToReferenceResult,\n ProjectAssistSidecar,\n ProjectAutomationCurve,\n ProjectAutomationLaneDesc,\n ProjectAutomationPoint,\n ProjectAutomationTargetKind,\n ProjectBounceOptions,\n ProjectChordSymbol,\n ProjectClip,\n ProjectClipCompSegment,\n ProjectClipDesc,\n ProjectClipFade,\n ProjectClipTake,\n ProjectCompileResult,\n ProjectKeySegment,\n ProjectLoopMode,\n ProjectLoopRecordingDesc,\n ProjectLoopRecordingResult,\n ProjectMarker,\n ProjectMidiCcBinding,\n ProjectMidiClipResult,\n ProjectMidiEvent,\n ProjectMidiRouteConfig,\n ProjectMidiRouteResult,\n ProjectNotePairValidation,\n ProjectSource,\n ProjectTempoCandidate,\n ProjectTempoOptions,\n ProjectTempoSegment,\n ProjectTimeSignatureSegment,\n ProjectTrack,\n ProjectTrackKind,\n ProjectWarpMapDesc,\n ProjectWarpMode,\n TranscribeOptions,\n TranscribeResult,\n} from './project_types';\n// A value import, and this module's one import cycle: sample_bank.ts reaches\n// back here for projectModule(). Both directions are read inside function\n// bodies only, never while a module body runs, which is what makes the cycle\n// safe. Reading SampleBank at module scope here breaks ONE import order and\n// leaves the other working, so the property is pinned by\n// tests/sample-bank-module-cycle.test.ts rather than left to review.\nimport { SampleBank } from './sample_bank';\nimport { assertNibble, assertU7, assertU32 } from './validation';\n\n/**\n * A synth binding as the embind layer takes it: the public `sampleBank` handle\n * has already been resolved to the id the native registry looks the bank up by,\n * because an embind class instance cannot travel inside a plain JS object the\n * C++ side reads field by field.\n */\nexport type NativeSynthBinding = Omit<SynthPatch, 'sampleBank'> & { sampleBankId?: number };\n\n// Embind handle for the C++ `SampleBankWasm` class, narrowed the same way as\n// `WasmProject` below: it is registered next to the project, so a build without\n// arrangement support has neither.\nexport interface WasmSampleBank {\n readonly id: number;\n addSample: (data: Float32Array, desc: SampleDesc) => number;\n addZone: (setIndex: number, zone: Omit<SampleZoneDesc, 'setIndex'>) => void;\n sampleCount: () => number;\n setCount: () => number;\n delete: () => void;\n}\n\n/**\n * Swaps a facade {@link SampleBank} in a synth patch descriptor for the id the\n * embind layer looks the native bank up by, leaving every other field alone.\n *\n * Shared by the offline bounce and the realtime engine so `sampleBank` means\n * the same thing on both. It lives in this internal module rather than beside\n * the class because it hands out an internal identity that no caller has a use\n * for, and the entry point must not re-export it: a facade symbol with no C\n * counterpart is an active parity finding.\n *\n * The cast is the only one of its kind: `released` is private, and TypeScript's\n * private is a compile-time rule, so reading it once here beats widening the\n * class with a method the parity tool would then read as a facade op.\n */\nexport function normalizeSynthInstrument(patch: unknown): NativeSynthBinding | string {\n if (patch === null || typeof patch !== 'object') {\n // A preset-name string — and, at runtime, anything else — reaches the\n // embind layer unchanged, which is where such a value is validated.\n return patch as NativeSynthBinding | string;\n }\n const { sampleBank, ...rest } = patch as SynthPatch;\n if (!sampleBank) {\n // Omitted, and at runtime an explicit null: both mean no bank, which a\n // sample patch renders as silence.\n return rest;\n }\n if (!(sampleBank instanceof SampleBank)) {\n throw new TypeError('sampleBank must be a SampleBank instance');\n }\n if ((sampleBank as unknown as { released: boolean }).released) {\n // The id outlives the handle, so without this the native registry would be\n // the only thing that notices — and with a different error class than Node.\n throw new TypeError('sampleBank is destroyed');\n }\n return { ...rest, sampleBankId: sampleBank.nativeId };\n}\n\n// Embind handle for the C++ `ProjectWasm` class. `SonareModule` describes the\n// raw module's free functions and does not carry bound-class handles, so the\n// module is narrowed through this shape here — which is also where the\n// arrangement surface is probed for, since a build without arrangement support\n// registers neither the class nor its free functions.\nexport interface WasmProject {\n toJson: () => string;\n setSampleRate: (sampleRate: number) => void;\n addTrack: (desc: { kind?: number | string; name?: string }) => number;\n addClip: (desc: ProjectClipDesc) => number;\n importExternalStems: (request: unknown) => { trackIds: number[]; clipIds: number[] };\n addLoopRecordingTakes: (desc: ProjectLoopRecordingDesc) => ProjectLoopRecordingResult;\n addMidiClip: (startPpq: number, lengthPpq: number) => ProjectMidiClipResult;\n splitClip: (clipId: number, splitPpq: number) => number;\n trimClip: (clipId: number, newStartPpq: number, newLengthPpq: number) => void;\n moveClip: (clipId: number, newStartPpq: number, newTrackId: number) => void;\n setTrackKind: (trackId: number, kind: number) => void;\n setClipWarpRef: (clipId: number, warpRefId: number) => void;\n setClipWarpMode: (clipId: number, mode: number) => void;\n setWarpMap: (map: ProjectWarpMapDesc) => void;\n removeWarpMap: (warpRefId: number) => void;\n setTrackMidiDestination: (trackId: number, destinationId: number) => void;\n setTrackGain: (trackId: number, gain: number) => void;\n setTrackMute: (trackId: number, mute: boolean) => void;\n setTrackSolo: (trackId: number, solo: boolean) => void;\n setTrackPan: (trackId: number, pan: number) => void;\n undo: () => void;\n redo: () => void;\n clearHistory: () => void;\n setMaxUndoDepth: (depth: number) => void;\n setMaxHistoryBytes: (bytes: number) => void;\n setMidiEvents: (\n clipId: number,\n events: ReadonlyArray<ProjectMidiEvent | readonly [number, number, number]>,\n ) => void;\n importSmf: (data: Uint8Array) => number;\n exportSmf: () => Uint8Array<ArrayBuffer>;\n importClipFile: (data: Uint8Array) => number;\n exportClipFile: () => Uint8Array<ArrayBuffer>;\n setProgram: (clipId: number, program: number, bank: number) => void;\n setProgramOnChannel: (\n clipId: number,\n group: number,\n channel: number,\n program: number,\n bank: number,\n ) => void;\n bakeMidiFx: (clipId: number, configJson: string) => void;\n bakeMidiFxWithSourceIndex: (clipId: number, configJson: string) => Int32Array;\n previewMidiFxCount: (clipId: number, configJson: string) => number;\n setMidiFx: (clipId: number, configJson: string) => void;\n validateMidiNotes: (clipId: number) => ProjectNotePairValidation;\n transcribeToClip: (\n clipId: number,\n samples: Float32Array,\n sampleRate: number,\n config: TranscribeOptions,\n ) => number;\n analyzeTempo: (\n audio: Float32Array,\n sampleRate: number,\n options: ProjectTempoOptions | undefined,\n ) => ProjectTempoCandidate[];\n autoTempo: (\n audio: Float32Array,\n sampleRate: number,\n candidateIndex: number,\n applyTimeSignatures: boolean,\n options: ProjectTempoOptions | undefined,\n ) => number;\n snapToGrid: (ppq: number, strength: number, division: number) => number;\n compile: () => ProjectCompileResult;\n bounce: (options: ProjectBounceOptions) => Float32Array;\n bounceWithBuiltinInstrument: (\n bindings: BuiltinSynthBinding | ReadonlyArray<BuiltinSynthBinding> | undefined,\n options: ProjectBounceOptions,\n ) => Float32Array;\n bounceWithSynthInstrument: (\n bindings: NativeSynthBinding | string | ReadonlyArray<NativeSynthBinding | string> | undefined,\n options: ProjectBounceOptions,\n ) => Float32Array;\n loadSoundFont: (data: Uint8Array) => void;\n clearSoundFont: () => void;\n soundFontPresetCount: () => number;\n soundFontManifest: () => Sf2ProgramStatus[];\n bounceWithSf2Instrument: (\n bindings: Sf2InstrumentConfig | ReadonlyArray<Sf2InstrumentConfig> | undefined,\n options: ProjectBounceOptions,\n ) => Float32Array;\n removeClip: (clipId: number) => void;\n setClipGain: (clipId: number, gain: number) => void;\n setClipFade: (clipId: number, fadeIn: ProjectClipFade, fadeOut: ProjectClipFade) => void;\n unresolvedAudioSourceIds: () => number[];\n setSourceAudio: (\n sourceId: number,\n audio: Float32Array,\n channels: number,\n sampleRate: number,\n ) => void;\n setAudioSourceMetadata: (sourceId: number, contentHash: string, externalStemRole: string) => void;\n setClipTakes: (\n clipId: number,\n takes: ReadonlyArray<ProjectClipTake>,\n activeTakeId: number,\n ) => void;\n setClipCompSegments: (clipId: number, segments: ReadonlyArray<ProjectClipCompSegment>) => void;\n setClipLoop: (\n clipId: number,\n loopMode: number,\n loopLengthPpq: number,\n loopCrossfadePpq: number,\n ) => void;\n setClipSource: (clipId: number, sourceId: number) => void;\n duplicateClip: (clipId: number, newStartPpq: number) => number;\n removeTrack: (trackId: number) => void;\n renameTrack: (trackId: number, name: string) => void;\n setTrackRoute: (trackId: number, channelStripRef: string, outputTarget: string) => void;\n addAutomationLane: (trackId: number, desc: ProjectAutomationLaneDesc) => number;\n editAutomationLane: (\n trackId: number,\n targetParamId: number,\n desc: ProjectAutomationLaneDesc,\n ) => void;\n removeAutomationLane: (trackId: number, targetParamId: number) => void;\n annotateKeys: (keys: ReadonlyArray<ProjectKeySegment>) => void;\n annotateChords: (chords: ReadonlyArray<ProjectChordSymbol>) => void;\n setAssistSidecar: (\n moduleId: string,\n schemaVersion: number,\n targetTrackId: number,\n regionStartPpq: number,\n regionEndPpq: number,\n payload: Uint8Array,\n ) => void;\n assistSidecarCount: () => number;\n getAssistSidecar: (index: number) => ProjectAssistSidecar;\n setOverlapPolicy: (policy: number) => void;\n getOverlapPolicy: () => number;\n getSampleRate: () => number;\n setMixerSceneJson: (sceneJson: string) => void;\n setMarker: (markerId: number, ppq: number, name: string) => number;\n setMarkerEx: (marker: ProjectMarker) => number;\n markerByIndex: (index: number) => ProjectMarker;\n trackByIndex: (index: number) => ProjectTrack;\n clipByIndex: (index: number) => ProjectClip;\n sourceByIndex: (index: number) => ProjectSource;\n markerCount: () => number;\n trackCount: () => number;\n clipCount: () => number;\n sourceCount: () => number;\n tempoSegmentCount: () => number;\n tempoSegmentByIndex: (index: number) => ProjectTempoSegment;\n timeSignatureByIndex: (index: number) => ProjectTimeSignatureSegment;\n timeSignatureCount: () => number;\n setTempoSegments: (segments: ReadonlyArray<ProjectTempoSegment>) => void;\n setTimeSignatures: (segments: ReadonlyArray<ProjectTimeSignatureSegment>) => void;\n lastBounceCompileResult: () => ProjectCompileResult;\n delete: () => void;\n}\n\nexport interface ProjectModule {\n Project: {\n new (): WasmProject;\n fromJson: (json: string) => WasmProject;\n fromJsonWithDiagnostics: (json: string) => { project: WasmProject; diagnostics: string };\n };\n SampleBank: { new (): WasmSampleBank };\n projectAbiVersion: () => number;\n synthPresetNames: () => string[];\n synthPresetPatch: (name: string) => SynthPatch;\n synthGsDrumKitName: (program: number) => string | null;\n synthGsDrumKitIsVoicedApart: (program: number) => number;\n synthGsVariationIsVoicedApart: (bank: number, program: number) => number;\n controllerProfileNames: () => string[];\n _synthEnumTables: () => SynthEnumTables;\n _synthPatchRoundTrip: (patch: SynthPatch) => SynthPatch;\n midiGmInstrumentName: (program: number) => string | null;\n midiGmProgramForName: (name: string) => number;\n midiGmFamilyName: (family: number) => string | null;\n midiGmFamilyFirstProgram: (family: number) => number;\n midiGm2InstrumentName: (bankLsb: number, program: number) => string | null;\n midiGmDrumName: (note: number) => string | null;\n midiGmDrumNoteForName: (name: string) => number;\n midiGm2DrumSetName: (bankLsb: number) => string | null;\n midiGm2DrumName: (bankLsb: number, note: number) => string | null;\n midiCcName: (controller: number) => string | null;\n midiCcIndexForName: (name: string) => number;\n midiPerNoteControllerName: (index: number) => string | null;\n midiBankProgram: (\n ppq: number,\n group: number,\n channel: number,\n bankMsb: number,\n bankLsb: number,\n program: number,\n ) => ProjectMidiEvent[];\n midiRouteEvents: (\n events: ReadonlyArray<ProjectMidiEvent>,\n config: ProjectMidiRouteConfig,\n ) => ProjectMidiRouteResult;\n midiCcLearn: (\n events: ReadonlyArray<ProjectMidiEvent>,\n paramId: number,\n minValue: number,\n maxValue: number,\n minMovement: number,\n ) => ProjectMidiCcBinding | null;\n midiCcToBreakpoint: (\n bindings: ReadonlyArray<ProjectMidiCcBinding>,\n event: ProjectMidiEvent,\n ) => ProjectAutomationPoint | null;\n midiParamToCc: (\n bindings: ReadonlyArray<ProjectMidiCcBinding>,\n paramId: number,\n unitValue: number,\n group: number,\n ppq: number,\n ) => ProjectMidiEvent | null;\n transcribe: (\n samples: Float32Array,\n sampleRate: number,\n tempoBpm: number | undefined,\n config: TranscribeOptions,\n ) => TranscribeResult;\n // Positional in the C ABI's own order minus the derived lengths and the out\n // parameters. The request object is passed as `config` as well, the way\n // `transcribe` passes its own: the reader only looks at the resolution keys.\n alignTakeToReference: (\n reference: Float32Array,\n take: Float32Array,\n sampleRate: number,\n config: AlignTakeToReferenceRequest,\n ) => AlignTakeToReferenceResult;\n}\n\nexport function projectModule(): ProjectModule {\n const candidate = getSonareModule() as unknown as Partial<ProjectModule>;\n if (typeof candidate.projectAbiVersion !== 'function' || candidate.Project === undefined) {\n throw new Error('libsonare was built without arrangement (headless DAW) support');\n }\n return candidate as ProjectModule;\n}\n\nexport function projectMidi1Event(\n fnName: string,\n ppq: number,\n group: number,\n status: number,\n channel: number,\n data1: number,\n data2 = 0,\n): ProjectMidiEvent {\n if (!Number.isFinite(ppq) || ppq < 0) {\n throw new RangeError(`${fnName}: ppq must be a non-negative finite number`);\n }\n const g = assertNibble(fnName, group, 'group');\n const ch = assertNibble(fnName, channel, 'channel');\n const d1 = assertU7(fnName, data1, 'data1');\n const d2 = assertU7(fnName, data2, 'data2');\n // UMP MIDI-1.0 channel-voice word (message type 0x2). Canonical layout is\n // sonare::midi::make_midi1_* (C-ABI sonare_midi_*, which Python delegates to);\n // this hand-written copy is locked against those words by the golden vectors\n // in project.test.ts (mirrored in the Node suite) so it cannot silently drift.\n const word = ((0x2 << 28) | (g << 24) | (status << 20) | (ch << 16) | (d1 << 8) | d2) >>> 0;\n return { ppq, data0: word, data1: 0 };\n}\n\nexport function assertProjectMidiEvents(\n fnName: string,\n events: ReadonlyArray<ProjectMidiEvent | readonly [number, number, number]>,\n): void {\n if (!Array.isArray(events)) {\n throw new TypeError(`${fnName}: events must be an array`);\n }\n events.forEach((event, index) => {\n const prefix = `events[${index}]`;\n if (Array.isArray(event)) {\n if (event.length < 3) {\n throw new TypeError(`${fnName}: ${prefix} must contain [ppq, data0, data1]`);\n }\n if (!Number.isFinite(event[0]) || event[0] < 0) {\n throw new RangeError(`${fnName}: ${prefix}.ppq must be a non-negative finite number`);\n }\n assertU32(fnName, event[1], `${prefix}.data0`);\n assertU32(fnName, event[2], `${prefix}.data1`);\n return;\n }\n if (event === null || typeof event !== 'object') {\n throw new TypeError(`${fnName}: ${prefix} must be a MIDI event object or tuple`);\n }\n if (!Number.isFinite(event.ppq) || event.ppq < 0) {\n throw new RangeError(`${fnName}: ${prefix}.ppq must be a non-negative finite number`);\n }\n assertU32(fnName, event.data0, `${prefix}.data0`);\n if (event.data1 !== undefined) {\n assertU32(fnName, event.data1, `${prefix}.data1`);\n }\n });\n}\n\nexport function projectTrackKindValue(kind: ProjectTrackKind | undefined): number {\n return resolveEnumOrdinal(kind ?? 'audio', { audio: 0, midi: 1, aux: 2 }, 'project track kind');\n}\n\n/**\n * Resolve a breakpoint's curve spelling to its ordinal before it crosses into\n * embind, and fold the `curveToNext` alias onto `curve`.\n *\n * Mirrors the Node facade's `projectAutomationPointValue`: resolving here means\n * an unknown spelling is a `RangeError` from the same table both packages\n * declare, rather than a curve one binding renders and the other rejects.\n */\nexport function projectAutomationPointValue(point: ProjectAutomationPoint): ProjectAutomationPoint {\n const curve = projectAutomationCurveCode(point.curve ?? point.curveToNext);\n return {\n ...point,\n curve: curve as ProjectAutomationCurve,\n curveToNext: curve as ProjectAutomationCurve,\n };\n}\n\nexport function projectAutomationTargetKindValue(kind: ProjectAutomationTargetKind): number {\n return resolveEnumOrdinal(\n kind,\n { opaque: 0, 'track-fader-db': 1, 'track-pan': 2 },\n 'project automation target kind',\n );\n}\n\nexport function projectWarpModeValue(mode: ProjectWarpMode | undefined): number {\n return resolveEnumOrdinal(\n mode ?? 'off',\n { off: 0, repitch: 1, 'tempo-sync': 2, 'time-stretch': 3 },\n 'project warp mode',\n );\n}\n\nexport function projectLoopModeValue(mode: ProjectLoopMode | undefined): number {\n return resolveEnumOrdinal(mode ?? 'off', { off: 0, loop: 1 }, 'project loop mode');\n}\n","import { projectModule } from './project_internal';\nimport type { AlignTakeToReferenceRequest, AlignTakeToReferenceResult } from './project_types';\nimport { assertSampleRate, assertSamples } from './validation';\n\n/**\n * Aligns one take to a reference timeline and returns the warp anchors that place\n * the take under it.\n *\n * A chromagram is measured for each signal and the two are aligned, then the\n * alignment is reduced to anchors {@link Project.setWarpMap} accepts: at least\n * two finite, strictly increasing pairs. The reduction is needed rather than\n * decorative — an alignment path advances one axis at a time, so the raw\n * correspondence repeats a coordinate wherever one signal carries more frames\n * than the other, and those pairs are refused as a warp map.\n *\n * **The anchors are oriented for the take's own clip.** `warpSample` is a\n * position on the REFERENCE timeline and `sourceSample` the corresponding\n * position in the TAKE, which is the direction a clip whose source is that take\n * needs. This is why the entry point exists rather than the core alignment\n * primitive being exposed directly: that one names its arguments the other way\n * round, so passing the reference as its reference yields the inverse map and\n * nothing reports it.\n *\n * Both signals are read at `sampleRate`; resample first if they differ, since\n * the alignment does no I/O and no rate conversion.\n *\n * {@link AlignTakeToReferenceResult.alignment} is descriptive only — it says how\n * far the path strayed from a constant rate, so a caller can tell a take the\n * reference genuinely fits from one it does not, and supplies its own threshold.\n *\n * @param request - The two signals, their shared sample rate, and the chroma\n * resolution\n * @returns The anchors and how well the alignment was conditioned\n * @throws {RangeError} on an empty buffer, a non-finite sample, or a `sampleRate`\n * outside `[8000, 384000]`\n * @throws {SonareError} `InvalidParameter` on a non-positive `hopLength` or\n * `binsPerOctave`, on a `binsPerOctave` that is not a multiple of 12, on a\n * signal too short to measure two chroma frames, or when the two signals produce\n * no pair of distinct anchors — which is what an unalignable pair looks like,\n * and is reported rather than answered with a map you cannot use\n *\n * @example\n * ```typescript\n * const { anchors } = alignTakeToReference({ reference: guide, take, sampleRate });\n * const project = new Project();\n * const trackId = project.addTrack({ kind: 'audio' });\n * const clipId = project.addClip({ trackId, lengthPpq: 64, audio: take, audioSampleRate: sampleRate }); // 16 bars at 4/4, in quarter notes (PPQ)\n * project.setWarpMap({ id: 1, anchors });\n * project.setClipWarpRef(clipId, 1);\n * ```\n */\nexport function alignTakeToReference(\n request: AlignTakeToReferenceRequest,\n): AlignTakeToReferenceResult {\n assertSamples('alignTakeToReference', request.reference, true, 'reference');\n assertSamples('alignTakeToReference', request.take, true, 'take');\n assertSampleRate('alignTakeToReference', request.sampleRate);\n return projectModule().alignTakeToReference(\n request.reference,\n request.take,\n request.sampleRate,\n request,\n );\n}\n","/**\n * Input conversion the effect families share.\n */\n\nimport type { VoicedFlags } from './public_types';\n\n// The embind layer reads the companion voicing array as Float32Array. A flag is\n// a decision, not a magnitude: collapse to 1/0 on truthiness, which is the same\n// reduction the Node facade applies, so both surfaces agree on every accepted\n// input type.\nexport function toVoicedFloat32(voiced: VoicedFlags): Float32Array {\n const out = new Float32Array(voiced.length);\n for (let index = 0; index < voiced.length; index += 1) {\n out[index] = voiced[index] ? 1 : 0;\n }\n return out;\n}\n","/**\n * Note-level editing: segmenting audio and a pitch track into editable notes,\n * rendering an edited set back, and the split/merge operations over it.\n */\n\nimport { toVoicedFloat32 } from './_effects_common';\nimport { getSonareModule } from './module_state';\nimport type {\n NoteExtractorOptions,\n NoteMoveOptions,\n NoteObject,\n NoteObjectInput,\n NoteSetEntry,\n NoteStretchOptions,\n NoteTarget,\n NoteTargetAssignResult,\n NoteTargetUnmatchedPolicy,\n PitchDecompositionResult,\n VoicedFlags,\n} from './public_types';\nimport type { ValidateOptions } from './validation';\nimport { assertSampleRate, assertSamples } from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n// Shared input checks of the entry points that take audio plus a whole F0 track,\n// returning the voicing flags in the Float32Array form the embind layer reads. A\n// companion array of the wrong length is a RangeError here because the native\n// side can only report it as a flat InvalidParameter.\nfunction assertNoteTrack(\n fnName: string,\n request: ExtractNotesRequest | NoteSetRequest,\n): Float32Array | undefined {\n assertSamples(fnName, request.samples, request.validate !== false);\n assertSampleRate(fnName, request.sampleRate);\n if (request.voiced && request.voiced.length !== request.f0Hz.length) {\n throw new RangeError(`${fnName}: voiced length must match f0Hz length`);\n }\n if (request.voicedProb && request.voicedProb.length !== request.f0Hz.length) {\n throw new RangeError(`${fnName}: voicedProb length must match f0Hz length`);\n }\n return request.voiced ? toVoicedFloat32(request.voiced) : undefined;\n}\n\nexport interface NoteStretchRequest extends NoteStretchOptions, ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\nexport interface NoteMoveRequest extends NoteMoveOptions, ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\n/** Canonical request form for {@link extractNotes}. */\nexport interface ExtractNotesRequest extends NoteExtractorOptions, ValidateOptions {\n samples: Float32Array;\n /**\n * Sample rate in Hz. Required: `minNoteMs` and the per-frame RMS windows are\n * converted to samples with this rate, so a wrong/omitted value silently\n * segments differently.\n */\n sampleRate: number;\n /**\n * Per-frame F0 in Hz. A frame carrying no pitch is spelled as zero, a\n * negative value or a non-finite one, and all three read the same: that\n * frame contributes no measurement. A {@link pitchPyin} track can be passed\n * straight through — its `fillNa` is a choice about the contour you want,\n * not a requirement of this call.\n */\n f0Hz: Float32Array;\n /** F0 frames per second. */\n frameRate: number;\n /** Per-frame voiced flags (truthy = voiced). Takes precedence over `voicedProb`. */\n voiced?: VoicedFlags;\n /** Per-frame voicing probability in `[0, 1]`; read only when `voiced` is omitted. */\n voicedProb?: Float32Array;\n}\n\n/** Canonical request form for {@link renderNotes}. */\nexport interface RenderNotesRequest extends ValidateOptions {\n samples: Float32Array;\n /**\n * Sample rate in Hz. Required: `fadeMs` is converted to samples with this\n * rate, so a wrong/omitted value changes the cross-fade length.\n */\n sampleRate: number;\n /** The notes to render, with their edits. Source spans must not overlap. */\n notes: readonly NoteObjectInput[];\n /**\n * Equal-power cross-fade at each edited note's edges. Default 5 ms; a hard cut\n * is deliberately not selectable, because the seam it leaves is a click.\n */\n fadeMs?: number;\n /**\n * The F0 track the notes were extracted from. Required only by\n * `vibratoDepthChange` and `driftChange`, which act on the note's own pitch\n * curve; every other edit ignores it. The curve is not carried on a\n * {@link NoteObject} for the same reason it is not returned by\n * {@link extractNotes} — it is this array sliced by\n * `[frameStart, frameEnd)`, which the caller already holds.\n */\n f0Hz?: Float32Array;\n /** F0 frames per second. Required when `f0Hz` is given. */\n frameRate?: number;\n /**\n * Boundary between the drift and the vibrato that `vibratoDepthChange` and\n * `driftChange` act on, in Hz. Default 3 Hz.\n *\n * Pass whatever {@link decomposeNotePitch} was called with. A host that draws\n * the vibrato at one cutoff and edits it at another edits a curve it never\n * showed anyone.\n */\n vibratoCutoffHz?: number;\n}\n\n/** Canonical request form for {@link decomposeNotePitch}. */\nexport interface DecomposeNotePitchRequest {\n /**\n * The note's slice of the F0 track — `f0Hz.subarray(frameStart, frameEnd)`.\n * Every value must be finite and non-negative; zero denotes an unvoiced frame.\n */\n f0Hz: Float32Array;\n /** F0 frames per second. */\n frameRate: number;\n /**\n * The note's `medianHz`. A note with no pitch is spelled 0, so a negative\n * value is rejected rather than read as a second way of saying that.\n */\n medianHz: number;\n /** Where drift ends and vibrato begins, in Hz. Default 3 Hz. */\n vibratoCutoffHz?: number;\n}\n\n/** The audio, track and note set the two note-set reshaping calls share. */\nexport interface NoteSetRequest extends NoteExtractorOptions, ValidateOptions {\n /**\n * The audio the set was extracted from. Every note is re-measured against it,\n * so a different buffer re-derives the whole set against something else.\n */\n samples: Float32Array;\n sampleRate: number;\n /**\n * Per-frame F0 in Hz. A frame carrying no pitch is spelled as zero, a\n * negative value or a non-finite one, and all three read the same: that\n * frame contributes no measurement. A {@link pitchPyin} track can be passed\n * straight through — its `fillNa` is a choice about the contour you want,\n * not a requirement of this call.\n */\n f0Hz: Float32Array;\n /** F0 frames per second. */\n frameRate: number;\n /** Per-frame voiced flags (truthy = voiced). Takes precedence over `voicedProb`. */\n voiced?: VoicedFlags;\n /** Per-frame voicing probability in `[0, 1]`; read only when `voiced` is omitted. */\n voicedProb?: Float32Array;\n /** The current note set. Each note's `[frameStart, frameEnd)` must be non-empty and inside the track. */\n notes: readonly NoteSetEntry[];\n}\n\n/** Canonical request form for {@link splitNote}. */\nexport interface SplitNoteRequest extends NoteSetRequest {\n /** Index of the note to split. */\n index: number;\n /** Track frame to cut at, strictly inside that note's own span. */\n frame: number;\n}\n\n/** Canonical request form for {@link mergeNotes}. */\nexport interface MergeNotesRequest extends NoteSetRequest {\n /** Index of the first note to join; must be `< last`. */\n first: number;\n /** Index of the last note to join, inclusive. */\n last: number;\n}\n\n/** Canonical request form for {@link noteTargetsFromSmf}. */\nexport interface NoteTargetsFromSmfRequest {\n /** The Standard MIDI File, in memory. */\n data: Uint8Array;\n /**\n * Which MIDI-bearing track to read, NOT an index into the file's own tracks: a\n * track holding only meta events — a conductor track carrying the tempo map is\n * the usual one — is not counted. A file whose first track is a conductor track\n * therefore has its melody at 0, which is also the default.\n */\n trackIndex?: number;\n}\n\n/** Canonical request form for {@link assignNoteTargets}. */\nexport interface AssignNoteTargetsRequest {\n /**\n * The notes to assign targets to. Not modified; the result carries a new array.\n * Only `onsetSample`, `offsetSample` and `medianHz` are read.\n */\n notes: readonly NoteObject[];\n /** Converts each note's sample span to seconds, so the targets line up. Must be > 0. */\n sampleRate: number;\n /** The reference melody. An empty array assigns nothing and applies the policy. */\n targets: readonly NoteTarget[];\n /** What to do with a note that has a pitch and no target. Default `'leave'`. */\n unmatchedPolicy?: NoteTargetUnmatchedPolicy;\n /**\n * Fraction of the note that must overlap a target for it to count, in `[0, 1]`.\n * Default 0.5. `0` is its own meaning — any overlap at all counts — not a\n * request for the default.\n */\n minOverlapRatio?: number;\n /**\n * Where the assigned shift saturates, in semitones. Default 12. `0` is its own\n * meaning, as above: every correction saturates to nothing and the take is left\n * as recorded. Must not be negative.\n */\n maxCorrectionSemitones?: number;\n}\n\n/**\n * Time-stretch a note region between two sample offsets without changing pitch.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz\n * @param onsetSample - Note onset position in samples\n * @param offsetSample - Note offset position in samples\n * @param stretchRatio - Stretch ratio (0.5 = half duration, 2.0 = double duration)\n * @returns Audio with the note region stretched\n */\nexport function noteStretch(request: NoteStretchRequest): Float32Array;\nexport function noteStretch(\n samples: Float32Array,\n sampleRate?: number,\n options?: NoteStretchOptions & ValidateOptions,\n): Float32Array;\nexport function noteStretch(\n samples: Float32Array | NoteStretchRequest,\n sampleRate = 22050,\n options: NoteStretchOptions & ValidateOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('noteStretch', request.samples, request.validate !== false);\n return requireModule().noteStretch(\n request.samples,\n request.sampleRate ?? 22050,\n request.onsetSample ?? 0,\n request.offsetSample ?? request.samples.length,\n request.stretchRatio ?? 1.0,\n );\n}\n\n/** Move a note region to a new onset without changing its duration. */\nexport function noteMove(request: NoteMoveRequest): Float32Array;\nexport function noteMove(\n samples: Float32Array,\n sampleRate?: number,\n options?: NoteMoveOptions & ValidateOptions,\n): Float32Array;\nexport function noteMove(\n samples: Float32Array | NoteMoveRequest,\n sampleRate = 22050,\n options: NoteMoveOptions & ValidateOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('noteMove', request.samples, request.validate !== false);\n return requireModule().noteMove(\n request.samples,\n request.sampleRate ?? 22050,\n request.onsetSample ?? 0,\n request.offsetSample ?? request.samples.length,\n request.targetOnsetSample ?? 0,\n );\n}\n\n/**\n * Extract editable note objects from audio and a caller-supplied F0 track.\n *\n * The track is segmented into monophonic notes; each note carries its span in\n * source samples, its span in the track's own frames, its median pitch, two\n * measured quality figures, its per-frame amplitude (RMS) curve, and an identity\n * {@link NoteEdit}. Edit the notes and hand them to {@link renderNotes} to apply\n * the result — the source audio is never mutated, and a set whose edits are all\n * identity renders back to the input bit for bit.\n *\n * The per-note F0 curve is deliberately not returned: it is the caller's own\n * `f0Hz` sliced by `[frameStart, frameEnd)`. The amplitude curve is measured\n * here, so it is, one entry per F0 frame over that note's span.\n *\n * Voicing comes from `voiced` (truthy = voiced). `voicedProb` is read only when\n * `voiced` is absent, and then a frame counts as voiced at or above\n * `voicedThreshold` (default 0.5). At least one of the two is required. Because\n * `voicedProb` from pYIN rises with F0 for a fixed frame length, prefer passing\n * a {@link PitchResult}'s `voicedFlag` through `voiced`.\n *\n * @param request - Audio, F0 track, frame cadence and segmenter options\n * @returns One {@link NoteObject} per segmented note, in time order; an empty\n * array when the track segments to nothing\n * @throws RangeError when `voiced` / `voicedProb` do not match `f0Hz` in length,\n * or the samples/sample rate fail the shared input checks\n * @throws SonareError (`InvalidParameter`) on an empty `f0Hz`, a non-positive\n * `frameRate`, a negative or non-finite `f0Hz` value, a `voicedProb` outside\n * `[0, 1]`, or a negative option value\n *\n * @example\n * ```ts\n * // pitchPyin's default leaves unvoiced frames NaN, which reads here as a\n * // frame carrying no pitch, so fillNa is a choice rather than a requirement.\n * const pitch = pitchPyin({ samples, sampleRate });\n * const notes = extractNotes({\n * samples,\n * sampleRate,\n * f0Hz: pitch.f0,\n * voiced: pitch.voicedFlag,\n * frameRate: sampleRate / 512,\n * minNoteMs: 40,\n * });\n * // Lift the second note by a semitone and mute the third.\n * notes[1].edit.pitchShiftSemitones = 1;\n * notes[2].edit.muted = true;\n * const edited = renderNotes({ samples, sampleRate, notes });\n * ```\n */\nexport function extractNotes(request: ExtractNotesRequest): NoteObject[] {\n const voicedF32 = assertNoteTrack('extractNotes', request);\n return requireModule().extractNotes(\n request.samples,\n request.sampleRate,\n request.f0Hz,\n request.voicedProb,\n voicedF32,\n request.frameRate,\n request,\n );\n}\n\n/**\n * Render edited note objects back over their source audio.\n *\n * Only a note whose edit is non-identity is resynthesized; the source passes\n * through everywhere else, so a set of untouched {@link extractNotes} output\n * reproduces the input exactly. The output has the input's length: an edit that\n * pushes a note past either end is truncated there.\n *\n * Per note the order is: pitch curve, time stretch, pitch shift, formant warp,\n * amplitude envelope, then gain.\n *\n * Each note's `onsetSample`, `offsetSample` and `edit` are read, plus its\n * `frameStart`, `frameEnd` and `medianHz` when the request carries an `f0Hz`\n * track for a curve edit to act on; so an extracted note can be passed back\n * as-is, or a note can be built by hand from those fields alone. Overlap is\n * checked on the source spans only — where `timeOffsetSamples` lands a note is\n * not, and a note lengthened past its own span writes into its neighbours'\n * samples, so two moved or stretched notes may be written over each other.\n *\n * @param request - Source audio, the notes to render, the cross-fade length, and\n * the F0 track a vibrato or drift edit reads\n * @returns The rendered audio, the same length and sample rate as the input\n * @throws RangeError when the samples or sample rate fail the shared input checks\n * @throws SonareError (`InvalidParameter`) on a note whose span is empty,\n * reversed or missing, overlapping source spans, a non-finite or non-positive\n * edit field, a negative or non-finite envelope value, a negative `fadeMs` or\n * `vibratoCutoffHz`, a frame span outside `f0Hz`, or a `vibratoDepthChange` /\n * `driftChange` on a note with no usable pitch curve to apply it to\n *\n * @example\n * ```ts\n * const notes = extractNotes({ samples, sampleRate, f0Hz, voiced, frameRate });\n *\n * // Silence the third note and leave the rest untouched.\n * const muted = notes.map((note, index) =>\n * index === 2 ? { ...note, edit: { ...note.edit, muted: true } } : note,\n * );\n * const rendered = renderNotes({ samples, sampleRate, notes: muted, fadeMs: 10 });\n *\n * // Flatten the first note's vibrato, which needs the track it was measured on.\n * const flattened = notes.map((note, index) =>\n * index === 0 ? { ...note, edit: { ...note.edit, vibratoDepthChange: -1 } } : note,\n * );\n * const steady = renderNotes({\n * samples,\n * sampleRate,\n * notes: flattened,\n * f0Hz,\n * frameRate: sampleRate / 512,\n * });\n * ```\n */\nexport function renderNotes(request: RenderNotesRequest): Float32Array {\n assertSamples('renderNotes', request.samples, request.validate !== false);\n assertSampleRate('renderNotes', request.sampleRate);\n return requireModule().renderNotes(request.samples, request.sampleRate, request.notes, request);\n}\n\n/**\n * Split one note's pitch curve into a centre, a slow drift and a vibrato.\n *\n * A performed note's pitch is one curve carrying three things at once: the note\n * that was aimed at, a slow wander around it, and a periodic oscillation on top.\n * Editing any of them on its own needs them separated first, and the only thing\n * that decides where drift ends and vibrato begins is `vibratoCutoffHz`. Hand\n * the same cutoff to {@link renderNotes}, or it edits a curve nobody was shown.\n *\n * Frames whose F0 is unusable carry no measurement, so the curve is held at the\n * nearest usable neighbour across them. Both curves therefore have an entry\n * everywhere; a host marking the held ones reads them off `f0Hz`, which is exact.\n *\n * A note with no usable pitch is reported as a zero `centreHz` and two empty\n * curves rather than as an error — that is a measurement which came up empty,\n * not a bad argument.\n *\n * @param request - The note's slice of the F0 track, its cadence, its centre, and\n * the cutoff\n * @returns The centre and the two curves, each one entry per frame of `f0Hz`\n * @throws SonareError (`InvalidParameter`) on an empty `f0Hz`, a negative or\n * non-finite `f0Hz` value, a non-positive `frameRate`, a negative `medianHz`,\n * or a negative `vibratoCutoffHz`\n *\n * @example\n * ```ts\n * const note = notes[0];\n * const { centreHz, driftCents, vibratoCents } = decomposeNotePitch({\n * f0Hz: f0Hz.subarray(note.frameStart, note.frameEnd),\n * frameRate: sampleRate / 512,\n * medianHz: note.medianHz,\n * });\n * ```\n */\nexport function decomposeNotePitch(request: DecomposeNotePitchRequest): PitchDecompositionResult {\n return requireModule().decomposeNotePitch(\n request.f0Hz,\n request.frameRate,\n request.medianHz,\n request.vibratoCutoffHz ?? 0,\n );\n}\n\n/**\n * Split one note of a set in two at a track frame.\n *\n * Both halves are re-derived from the audio and the track the way\n * {@link extractNotes} derives its own, rather than by patching the fields of\n * the note they replace. Both inherit the source note's edit, and its amplitude\n * envelope is cut at the same proportion so each half keeps its own part of it —\n * a note whose edit is the identity therefore still renders bit for bit after\n * being split.\n *\n * Every note in the set, not just the two halves, has its spans, curves, medians\n * and stability re-derived from `samples` and the track, because a\n * {@link NoteSetEntry} carries no curves for this call to copy through. The\n * frame bounds are therefore what a note is identified by here, and the audio\n * and track must be the ones the set was extracted from or the whole set is\n * re-measured against something else.\n *\n * @param request - The source, the current note set, and where to cut\n * @returns The whole new note set, one note longer than the one handed in\n * @throws RangeError when `voiced` / `voicedProb` do not match `f0Hz` in length,\n * or the samples/sample rate fail the shared input checks\n * @throws SonareError (`InvalidParameter`) on an out-of-range `index`, a `frame`\n * that is not strictly inside that note's own span, a note whose frame span is\n * empty or runs past the track, or the track arguments {@link extractNotes}\n * itself rejects\n *\n * @example\n * ```ts\n * const notes = extractNotes({ samples, sampleRate, f0Hz, voiced, frameRate });\n * const halves = splitNote({\n * samples,\n * sampleRate,\n * f0Hz,\n * voiced,\n * frameRate,\n * notes,\n * index: 1,\n * frame: Math.floor((notes[1].frameStart + notes[1].frameEnd) / 2),\n * });\n * ```\n */\nexport function splitNote(request: SplitNoteRequest): NoteObject[] {\n const voicedF32 = assertNoteTrack('splitNote', request);\n return requireModule().splitNote(\n request.samples,\n request.sampleRate,\n request.f0Hz,\n request.voicedProb,\n voicedF32,\n request.frameRate,\n request.notes,\n request.index,\n request.frame,\n request,\n );\n}\n\n/**\n * Join a run of notes into one.\n *\n * The result spans from `notes[first]`'s onset to `notes[last]`'s offset,\n * including whatever the segmenter cut out between them, and its measured fields\n * are derived over that whole span — the pitch and amplitude of an unvoiced gap\n * live in the track and the audio, not in either neighbour.\n *\n * It takes `notes[first]`'s edit, envelope included. Notes carrying different\n * edits have no single correct answer here, so the rule is stated rather than\n * guessed at; a host that cares sets the edit afterwards. Every note in the set\n * is re-derived from `samples` and the track, exactly as {@link splitNote}\n * describes.\n *\n * @param request - The source, the current note set, and the run to join\n * @returns The whole new note set, `last - first` notes shorter than the one\n * handed in\n * @throws RangeError when `voiced` / `voicedProb` do not match `f0Hz` in length,\n * or the samples/sample rate fail the shared input checks\n * @throws SonareError (`InvalidParameter`) unless `first < last < notes.length`,\n * on a note whose frame span is empty or runs past the track, or on the track\n * arguments {@link extractNotes} itself rejects\n *\n * @example\n * ```ts\n * // Undo a split by rejoining the two halves it produced.\n * const rejoined = mergeNotes({\n * samples,\n * sampleRate,\n * f0Hz,\n * voiced,\n * frameRate,\n * notes: halves,\n * first: 1,\n * last: 2,\n * });\n * ```\n */\nexport function mergeNotes(request: MergeNotesRequest): NoteObject[] {\n const voicedF32 = assertNoteTrack('mergeNotes', request);\n return requireModule().mergeNotes(\n request.samples,\n request.sampleRate,\n request.f0Hz,\n request.voicedProb,\n voicedF32,\n request.frameRate,\n request.notes,\n request.first,\n request.last,\n request,\n );\n}\n\n/**\n * Read one track of an in-memory Standard MIDI File as a reference melody.\n *\n * Each note-on is paired with the next note-off of the same note number on the\n * same channel, and the pair becomes one {@link NoteTarget} at the note's own\n * pitch. Times come from the file's tempo map, so a tempo change or a ramp inside\n * it is followed rather than the initial tempo being scaled.\n *\n * A note-on the track never closes is dropped: it has no end, and the track's end\n * is not a substitute for one — with events after it the note would span the whole\n * remainder and, being the longest overlap everywhere, take the assignment away\n * from every note that follows. Zero-length notes are skipped for the mirror\n * reason: they overlap nothing, so they could never be assigned.\n *\n * @param request - The file's bytes and which MIDI-bearing track to read\n * @returns One target per closed note, sorted by `startSec`; an empty array for a\n * track with no closed note, which is a measurement that came up empty rather\n * than an error\n * @throws SonareError (`InvalidFormat`) when the bytes are not a readable SMF\n * @throws SonareError (`InvalidParameter`) when `trackIndex` names no\n * MIDI-bearing track\n *\n * @example\n * ```ts\n * // A project's own export writes the tempo map as a conductor track, which\n * // carries no MIDI, so the melody is at index 0 rather than 1.\n * const targets = noteTargetsFromSmf({ data: project.exportSmf() });\n * ```\n */\nexport function noteTargetsFromSmf(request: NoteTargetsFromSmfRequest): NoteTarget[] {\n const module = requireModule();\n if (typeof module.noteTargetsFromSmf !== 'function') {\n throw new Error('libsonare was built without arrangement support');\n }\n return module.noteTargetsFromSmf(request.data, request.trackIndex ?? 0);\n}\n\n/**\n * Write each note's `edit.pitchShiftSemitones` from the reference target it\n * overlaps, which is what makes a take follow a written melody instead of a\n * single stated interval.\n *\n * A note is matched to the target it overlaps longest, provided that overlap is\n * at least `minOverlapRatio` of the note's own span; an exact tie goes to the\n * target that starts first, so the answer does not depend on the order the\n * targets arrived in. The shift is `targetMidi` minus the note's own `medianHz`\n * as a MIDI number, saturated at `maxCorrectionSemitones` — a reference an octave\n * out is a wrong reference, and a rejected call would tell the caller less than a\n * bounded correction does.\n *\n * A note whose `medianHz` is not finite and positive is never assigned and never\n * edited, whatever `unmatchedPolicy` says. Such a note has no measured pitch to\n * correct from, so `'nearest'` would compute a shift from a pitch that does not\n * exist; the policy governs notes that have a pitch and no target, which is a\n * different thing from having no pitch.\n *\n * The notes handed in are not modified. Only `edit.pitchShiftSemitones` and\n * `edit.muted` are written on the returned copies; every other field of a note —\n * its spans, its metrics, its amplitude curve and its other edits — comes back\n * exactly as it went in.\n *\n * @param request - The notes, their sample rate, the reference melody, and the\n * three tunable knobs\n * @returns The new note set and how many notes received a target\n * @throws SonareError (`InvalidParameter`) on a non-positive `sampleRate`, an\n * unknown `unmatchedPolicy`, a `minOverlapRatio` outside `[0, 1]`, a negative\n * `maxCorrectionSemitones`, a note missing `onsetSample` / `offsetSample`, or a\n * target whose `startSec`, `endSec` or `targetMidi` is not finite\n *\n * @example\n * ```ts\n * const notes = extractNotes({ samples, sampleRate, f0Hz, voiced, frameRate });\n * const { notes: retuned, assignedCount } = assignNoteTargets({\n * notes,\n * sampleRate,\n * targets: noteTargetsFromSmf({ data: smf }),\n * unmatchedPolicy: 'mute',\n * });\n * const corrected = renderNotes({ samples, sampleRate, notes: retuned });\n * ```\n */\nexport function assignNoteTargets(request: AssignNoteTargetsRequest): NoteTargetAssignResult {\n return requireModule().assignNoteTargets(\n request.notes,\n request.sampleRate,\n request.targets,\n request,\n );\n}\n","/**\n * Percussive event editing: locating struck sounds in audio and rendering an\n * edited set of them back.\n */\n\nimport { getSonareModule } from './module_state';\nimport type { PercussiveEvent, PercussiveEventInput } from './public_types';\nimport type { ValidateOptions } from './validation';\nimport { assertPercussiveSeparation, assertSampleRate, assertSamples } from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n/**\n * The separation a percussive event's signal is lifted out with. Extraction\n * measures events against it and rendering has to repeat it, so both calls take\n * the same four fields and a render must be given what the extraction was.\n */\nexport interface PercussiveSeparationOptions {\n /**\n * FFT size and hop the separation and the onset detector share. They cannot be\n * set apart: an event measured on one framing and lifted out on another is not\n * the same signal. Default 2048 and 512. The pair must overlap-add — `nFft`\n * even and at least 2, `hopLength` no more than half of it — because the\n * separation inverts an STFT. A negative value is rejected on its own, before\n * the zero-is-default rule could swallow it.\n */\n nFft?: number;\n /** Hop length in samples. Default 512. */\n hopLength?: number;\n /**\n * Median filter lengths the separation runs, along time and along frequency. A\n * longer harmonic kernel calls more of a sustained sound harmonic. Default 31;\n * any other value must be odd and positive, so an even one is rejected rather\n * than rounded. 1 is legal and degenerate rather than an error: a length-1\n * median is the identity, so both components come back as the source.\n */\n hpssKernelHarmonic?: number;\n /** Vertical median filter length, under the same rule. Default 31. */\n hpssKernelPercussive?: number;\n}\n\n/** Canonical request form for {@link extractPercussiveEvents}. */\nexport interface ExtractPercussiveEventsRequest\n extends PercussiveSeparationOptions,\n ValidateOptions {\n samples: Float32Array | readonly number[];\n /**\n * Sample rate in Hz. Required: `maxEventMs` is converted to samples with this\n * rate, so a wrong/omitted value caps the spans differently.\n */\n sampleRate: number;\n /**\n * Minimum frames between consecutive onsets. Default 1, and a whole number:\n * 0 is how the default is spelled, so a fractional wait is refused rather\n * than truncated onto it. Negative is rejected.\n */\n onsetWait?: number;\n /**\n * Offset added to the detector's adaptive threshold; raising it finds fewer,\n * stronger hits and lowering it finds more. Default 0.06, so exactly zero is\n * the one value not selectable here — a negative one is accepted and puts the\n * threshold below the default, which is the direction a caller reaching for\n * zero wanted anyway.\n */\n onsetDelta?: number;\n /**\n * Caps a span that no onset follows. It binds at the end of a phrase and at the\n * end of the track; anywhere else the next onset closes the span first. Default\n * 500 ms.\n */\n maxEventMs?: number;\n /**\n * Drops an event whose `percussiveRatio` falls below this; must be in `[0, 1]`.\n * 0 is both the default and the meaningful \"keep everything\". Raising it is\n * useful on material that is mostly drums and wrong on a dense mix, where it\n * also drops real hits sitting over a loud sustain.\n */\n minPercussiveRatio?: number;\n}\n\n/** Canonical request form for {@link renderPercussiveEvents}. */\nexport interface RenderPercussiveEventsRequest\n extends PercussiveSeparationOptions,\n ValidateOptions {\n samples: Float32Array | readonly number[];\n /**\n * Sample rate in Hz. Required: `fadeMs` is converted to samples with this rate,\n * so a wrong/omitted value changes the fade length.\n */\n sampleRate: number;\n /** The events to render, with their edits. Source spans must not overlap. */\n events: readonly PercussiveEventInput[];\n /**\n * Fade-out at the tail of each lifted span. Default 5 ms, so a zero-length\n * fade is unreachable here rather than rejected — and a hard cut is not a thing\n * to want anyway, because what the fade shapes is the signal being subtracted,\n * so squaring it off leaves a step. There is deliberately\n * no matching fade-in: a span opens in front of its transient, where the\n * percussive component is near-silent, so cutting square there costs nothing\n * and keeps a muted hit's attack from surviving inside a fade.\n */\n fadeMs?: number;\n}\n\n/**\n * Extract editable percussive events from audio alone.\n *\n * Each event is a struck sound located in time: a span in source samples, its\n * detector strength, the percussive peak over the span, the share of the span's\n * energy the separation called percussive, and an identity\n * {@link PercussiveEventEdit}. Edit the events and hand them to\n * {@link renderPercussiveEvents} to apply the result — the source audio is never\n * mutated, and a set whose edits are all identity renders back to the input bit\n * for bit.\n *\n * Onsets are detected on the percussive component rather than on the source, so\n * a harmonic attack is attenuated before the detector sees it instead of being\n * filtered out afterwards. Each onset opens a span that the next one closes,\n * capped by `maxEventMs` and never running past the end of the audio.\n *\n * Each onset is backtracked to the transient's start, which is not optional and\n * is why there is no knob for it: peak-picking lands after the attack, and a span\n * that opened there would report the next hit's peak and leave its own attack\n * behind when muted.\n *\n * An event carries no pitch and is never associated with a {@link NoteObject} —\n * a struck sound has no steady F0 to edit, so the two models are extracted by\n * separate calls.\n *\n * @param request - Audio, its sample rate, and the separation, peak-picking and\n * span options\n * @returns One {@link PercussiveEvent} per detected hit, in time order; an empty\n * array when nothing was detected\n * @throws RangeError when the samples or sample rate fail the shared input checks\n * @throws SonareError (`InvalidParameter`) on a kernel size that is not an\n * integer within the 32-bit range, a framing size that is negative or outside\n * that range, a framing that breaks constant overlap-add, an `onsetWait` that\n * is fractional, negative or non-finite, a negative or non-finite `onsetDelta`\n * / `maxEventMs`, or a `minPercussiveRatio` outside `[0, 1]`\n *\n * @example\n * ```ts\n * const events = extractPercussiveEvents({ samples, sampleRate });\n * // Drop the second hit and push the third 10 ms late.\n * events[1].edit.muted = true;\n * events[2].edit.timeOffsetSamples = Math.round(0.01 * sampleRate);\n * const edited = renderPercussiveEvents({ samples, sampleRate, events });\n * ```\n */\nexport function extractPercussiveEvents(\n request: ExtractPercussiveEventsRequest,\n): PercussiveEvent[] {\n assertSamples('extractPercussiveEvents', request.samples, request.validate !== false);\n assertSampleRate('extractPercussiveEvents', request.sampleRate);\n assertPercussiveSeparation('extractPercussiveEvents', request);\n return requireModule().extractPercussiveEvents(request.samples, request.sampleRate, request);\n}\n\n/**\n * Render edited percussive events back over their source audio.\n *\n * Per event the lifted signal is the percussive component over\n * `[onsetSample, offsetSample)` under the tail fade. It is subtracted where it\n * sits and, unless the event is muted, added back at the shifted position scaled\n * by the gain. Only that signal moves, so muting a hit leaves the harmonic\n * content under it sounding and moving one does not drag its neighbours' sustain\n * along.\n *\n * Each event's span and `edit` are read; `strength`, `peakAmplitude` and\n * `percussiveRatio` are ignored, so an extracted event can be passed back as-is,\n * or an event can be built by hand from the span alone. A set whose edits are all\n * identity reproduces the input bit for bit and runs no separation at all.\n *\n * Pass the separation the events were extracted with: a different one lifts a\n * different signal out of the span than the one the events describe. It is\n * validated even when every edit is the identity and no separation runs, so an\n * unusable framing is an error on every set rather than on some of them.\n *\n * Overlap is checked on the source spans only. Where `timeOffsetSamples` lands an\n * event is not, so two moved events may be written over each other, and a shift\n * that pushes the signal past either end is truncated there rather than wrapped.\n *\n * @param request - Source audio, the events to render, the separation and the\n * tail fade\n * @returns The rendered audio, the same length and sample rate as the input\n * @throws RangeError when the samples or sample rate fail the shared input checks\n * @throws SonareError (`InvalidParameter`) on an event whose span is empty,\n * reversed or outside the audio, overlapping source spans, a non-finite\n * `gainDb`, a kernel size that is not an integer within the 32-bit range, a\n * framing that breaks constant overlap-add, or a negative or non-finite\n * `fadeMs`\n *\n * @example\n * ```ts\n * const events = extractPercussiveEvents({ samples, sampleRate });\n *\n * // Lift the loudest hit by 3 dB and leave the rest untouched.\n * const loudest = events.reduce((a, b) => (a.strength >= b.strength ? a : b));\n * const edited = events.map((event) =>\n * event === loudest ? { ...event, edit: { ...event.edit, gainDb: 3 } } : event,\n * );\n * const rendered = renderPercussiveEvents({ samples, sampleRate, events: edited });\n * ```\n */\nexport function renderPercussiveEvents(request: RenderPercussiveEventsRequest): Float32Array {\n assertSamples('renderPercussiveEvents', request.samples, request.validate !== false);\n assertSampleRate('renderPercussiveEvents', request.sampleRate);\n assertPercussiveSeparation('renderPercussiveEvents', request);\n return requireModule().renderPercussiveEvents(\n request.samples,\n request.sampleRate,\n request.events,\n request,\n );\n}\n","import {\n assertEvenIntegerAtLeast,\n assertIntegerValue,\n assertPositiveInteger,\n} from './validation.js';\n\n/**\n * The facade's single FFT-size/hop domain.\n *\n * This module is deliberately internal: sibling facade modules import it, but\n * nothing re-exports it, so it stays out of the package entry point and out of\n * the C-ABI parity surface (which is defined by the index's re-export closure).\n */\n\n/**\n * Resolves and validates the `nFft` / `hopLength` pair every STFT-backed entry\n * point takes.\n *\n * The core FFT is mixed-radix, so any even size transforms exactly; only the\n * real one-sided spectrum's `n_fft / 2 + 1` bin layout needs the evenness. A\n * power-of-two restriction rejects sizes the C ABI and the native CLI accept,\n * which is what a second copy of this rule used to do: `hpss({ nFft: 1536 })`\n * worked while `hpssWithResidual({ nFft: 1536 })` threw, with the message\n * asserting a constraint this project had explicitly written down as untrue.\n * One implementation, so the two cannot disagree again.\n */\nexport function resolveFftOptions(\n fnName: string,\n nFft: unknown,\n hopLength: unknown,\n): { nFft: number; hopLength: number } {\n const resolvedNFft = nFft === undefined ? 2048 : nFft;\n const resolvedHopLength = hopLength === undefined ? 512 : hopLength;\n assertIntegerValue(fnName, resolvedNFft, 'nFft');\n assertEvenIntegerAtLeast(fnName, resolvedNFft, 'nFft', 2, 2 ** 30);\n assertIntegerValue(fnName, resolvedHopLength, 'hopLength');\n assertPositiveInteger(fnName, resolvedHopLength, 'hopLength');\n return { nFft: resolvedNFft, hopLength: resolvedHopLength };\n}\n","/**\n * Harmonic/percussive separation: the masked split and the two shortcuts\n * that return a single component.\n */\n\nimport { resolveFftOptions } from './_fft_options';\nimport { getSonareModule } from './module_state';\nimport type { HpssResult } from './public_types';\nimport type { ValidateOptions } from './validation';\nimport { assertHpssKernels, assertSamples } from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\nfunction resolveHardMask(value: unknown, fnName: string): boolean {\n if (value === undefined) {\n return false;\n }\n if (typeof value !== 'boolean') {\n throw new TypeError(`${fnName}: hardMask must be a boolean`);\n }\n return value;\n}\n\n/** Canonical request form for HPSS. */\nexport interface HpssRequest {\n samples: Float32Array;\n sampleRate?: number;\n /**\n * Horizontal median filter size, in STFT frames: a positive odd integer at\n * most 524287. Default 31. The ceiling is 524288 and an even kernel is\n * refused, so 524287 is the largest legal value.\n */\n kernelHarmonic?: number;\n /** Vertical median filter size, in STFT bins, under the same rule. Default 31. */\n kernelPercussive?: number;\n nFft?: number;\n hopLength?: number;\n hardMask?: boolean;\n}\n\nexport interface HarmonicRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\nexport interface PercussiveRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\n/**\n * Perform Harmonic-Percussive Source Separation (HPSS).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param kernelHarmonic - Horizontal median filter size in STFT frames; a\n * positive odd integer at most 524287 (default: 31)\n * @param kernelPercussive - Vertical median filter size in STFT bins, under the\n * same rule (default: 31)\n * @returns Separated harmonic and percussive components\n * @throws SonareError (`InvalidParameter`) on a kernel that is not an integer\n * within the signed 32-bit range, or one the core rejects as even,\n * non-positive or above its ceiling\n */\nexport function hpss(request: HpssRequest): HpssResult;\nexport function hpss(\n samples: Float32Array,\n sampleRate?: number,\n kernelHarmonic?: number,\n kernelPercussive?: number,\n nFft?: number,\n hopLength?: number,\n hardMask?: boolean,\n): HpssResult;\nexport function hpss(\n samples: Float32Array | HpssRequest,\n sampleRate = 22050,\n kernelHarmonic = 31,\n kernelPercussive = 31,\n nFft?: number,\n hopLength?: number,\n hardMask?: boolean,\n): HpssResult {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate, kernelHarmonic, kernelPercussive, nFft, hopLength, hardMask }\n : samples;\n const fftOptions = resolveFftOptions('hpss', request.nFft, request.hopLength);\n const resolvedHardMask = resolveHardMask(request.hardMask, 'hpss');\n const resolvedKernelHarmonic = request.kernelHarmonic ?? 31;\n const resolvedKernelPercussive = request.kernelPercussive ?? 31;\n assertHpssKernels('hpss', resolvedKernelHarmonic, resolvedKernelPercussive);\n return requireModule().hpssEx(\n request.samples,\n request.sampleRate ?? 22050,\n resolvedKernelHarmonic,\n resolvedKernelPercussive,\n fftOptions.nFft,\n fftOptions.hopLength,\n resolvedHardMask,\n );\n}\n\n/**\n * Extract harmonic component from audio.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz\n * @returns Harmonic component\n */\nexport function harmonic(request: HarmonicRequest): Float32Array;\nexport function harmonic(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function harmonic(\n samples: Float32Array | HarmonicRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('harmonic', request.samples, request.validate !== false);\n return requireModule().harmonic(request.samples, request.sampleRate ?? 22050);\n}\n\n/**\n * Extract percussive component from audio.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz\n * @returns Percussive component\n */\nexport function percussive(request: PercussiveRequest): Float32Array;\nexport function percussive(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function percussive(\n samples: Float32Array | PercussiveRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('percussive', request.samples, request.validate !== false);\n return requireModule().percussive(request.samples, request.sampleRate ?? 22050);\n}\n","/**\n * Region-based spectral editing: time x frequency rectangles applied over an\n * STFT and resynthesized.\n */\n\nimport { getSonareModule } from './module_state';\nimport type { SpectralEditOptions, SpectralRegionOp } from './public_types';\nimport type { ValidateOptions } from './validation';\nimport { assertSampleRate, assertSamples } from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\nexport interface SpectralEditRequest extends SpectralEditOptions, ValidateOptions {\n samples: Float32Array;\n sampleRate: number;\n ops?: SpectralRegionOp[];\n}\n\n/**\n * Apply region-based spectral edits (gain/attenuate/mute/heal) to mono audio.\n *\n * Each op is a time x frequency rectangle applied in array order over a single\n * STFT buffer, so a later op observes the result of earlier ops. The output has\n * the same length and sample rate as the input; an empty `ops` list is an\n * identity transform (within the iSTFT's own tolerance).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz\n * @param ops - Region edit ops applied in order ({@link SpectralRegionOp})\n * @param options - STFT + heal configuration ({@link SpectralEditOptions})\n * @returns Edited audio\n */\nexport function spectralEdit(request: SpectralEditRequest): Float32Array;\nexport function spectralEdit(\n samples: Float32Array,\n sampleRate: number,\n ops?: SpectralRegionOp[],\n options?: SpectralEditOptions & ValidateOptions,\n): Float32Array;\nexport function spectralEdit(\n samples: Float32Array | SpectralEditRequest,\n sampleRate?: number,\n ops: SpectralRegionOp[] = [],\n options: SpectralEditOptions & ValidateOptions = {},\n): Float32Array {\n const request: SpectralEditRequest =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ops, ...options }\n : samples;\n assertSamples('spectralEdit', request.samples, request.validate !== false);\n assertSampleRate('spectralEdit', request.sampleRate);\n return requireModule().spectralEdit(\n request.samples,\n request.sampleRate,\n request.ops ?? [],\n request as unknown as Record<string, unknown>,\n );\n}\n","/**\n * Time and pitch transforms over a whole buffer: stretching, shifting, and\n * correction onto a target pitch.\n */\n\nimport { toVoicedFloat32 } from './_effects_common';\nimport { resolveFftOptions } from './_fft_options';\nimport { getSonareModule } from './module_state';\nimport type { PitchCorrectOptions, VoicedFlags } from './public_types';\nimport type { ValidateOptions } from './validation';\nimport { assertFiniteScalar, assertSamples } from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\nexport interface TimeStretchRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n rate: number;\n nFft?: number;\n hopLength?: number;\n}\n\nexport interface PitchShiftRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n semitones: number;\n nFft?: number;\n hopLength?: number;\n}\n\nexport interface PitchCorrectToMidiRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n currentMidi?: number;\n targetMidi?: number;\n}\n\nexport interface PitchCorrectToMidiTimevaryingRequest extends ValidateOptions {\n samples: Float32Array;\n f0Hz: Float32Array;\n targetMidi: number;\n sampleRate?: number;\n hopLength?: number;\n voiced?: VoicedFlags;\n voicedProb?: Float32Array;\n}\n\nexport interface PitchCorrectTimevaryingRequest extends PitchCorrectOptions {\n samples: Float32Array;\n f0Hz: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n}\n\n/**\n * Time-stretch audio without changing pitch.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param rate - Time stretch rate (0.5 = double duration, 2.0 = half duration)\n * @param nFft - FFT size: an even integer >= 2 (default 2048)\n * @param hopLength - Hop in samples, in `(0, nFft / 2]` (default 512), so\n * frames overlap by at least half a window\n * @returns Time-stretched audio\n */\nexport function timeStretch(request: TimeStretchRequest): Float32Array;\nexport function timeStretch(\n samples: Float32Array,\n sampleRate: number,\n rate: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function timeStretch(\n samples: Float32Array,\n sampleRate: number,\n rate: number,\n nFft?: number,\n hopLength?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function timeStretch(\n samples: Float32Array | TimeStretchRequest,\n sampleRate?: number,\n rate?: number,\n nFftOrOptions?: number | ValidateOptions,\n hopLength?: number,\n options: ValidateOptions = {},\n): Float32Array {\n if (\n nFftOrOptions !== undefined &&\n nFftOrOptions !== null &&\n typeof nFftOrOptions !== 'number' &&\n typeof nFftOrOptions !== 'object'\n ) {\n throw new TypeError('timeStretch: nFft must be an integer or options object');\n }\n if (nFftOrOptions === null) {\n throw new TypeError('timeStretch: nFft must be an integer or options object');\n }\n const positionalOptions =\n typeof nFftOrOptions === 'object' && nFftOrOptions !== null ? nFftOrOptions : options;\n const positionalNFft = typeof nFftOrOptions === 'number' ? nFftOrOptions : undefined;\n const request: TimeStretchRequest =\n samples instanceof Float32Array\n ? {\n samples,\n sampleRate,\n rate: rate as number,\n nFft: positionalNFft,\n hopLength,\n ...positionalOptions,\n }\n : samples;\n assertSamples('timeStretch', request.samples, request.validate !== false);\n // Matches the addon, which refuses a non-finite rate here rather than letting\n // the core answer it. Does NOT cover a finite value too wide for a float:\n // Number.isFinite(1e39) is true and the demotion to the f32 parameter makes it\n // an infinity, which only the binding-side narrowing can see.\n assertFiniteScalar('timeStretch', request.rate as number, 'rate');\n const fftOptions = resolveFftOptions('timeStretch', request.nFft, request.hopLength);\n return requireModule().timeStretchEx(\n request.samples,\n request.sampleRate ?? 22050,\n request.rate,\n fftOptions.nFft,\n fftOptions.hopLength,\n );\n}\n\n/**\n * Pitch-shift audio without changing duration.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param semitones - Pitch shift in semitones (+12 = one octave up, -12 = one octave down)\n * @param nFft - FFT size: an even integer >= 2 (default 2048)\n * @param hopLength - Hop in samples, in `(0, nFft / 2]` (default 512), so\n * frames overlap by at least half a window\n * @returns Pitch-shifted audio\n */\nexport function pitchShift(request: PitchShiftRequest): Float32Array;\nexport function pitchShift(\n samples: Float32Array,\n sampleRate: number,\n semitones: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function pitchShift(\n samples: Float32Array,\n sampleRate: number,\n semitones: number,\n nFft?: number,\n hopLength?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function pitchShift(\n samples: Float32Array | PitchShiftRequest,\n sampleRate?: number,\n semitones?: number,\n nFftOrOptions?: number | ValidateOptions,\n hopLength?: number,\n options: ValidateOptions = {},\n): Float32Array {\n if (\n nFftOrOptions !== undefined &&\n nFftOrOptions !== null &&\n typeof nFftOrOptions !== 'number' &&\n typeof nFftOrOptions !== 'object'\n ) {\n throw new TypeError('pitchShift: nFft must be an integer or options object');\n }\n if (nFftOrOptions === null) {\n throw new TypeError('pitchShift: nFft must be an integer or options object');\n }\n const positionalOptions =\n typeof nFftOrOptions === 'object' && nFftOrOptions !== null ? nFftOrOptions : options;\n const positionalNFft = typeof nFftOrOptions === 'number' ? nFftOrOptions : undefined;\n const request: PitchShiftRequest =\n samples instanceof Float32Array\n ? {\n samples,\n sampleRate,\n semitones: semitones as number,\n nFft: positionalNFft,\n hopLength,\n ...positionalOptions,\n }\n : samples;\n assertSamples('pitchShift', request.samples, request.validate !== false);\n // See timeStretch above for what this does and does not cover.\n assertFiniteScalar('pitchShift', request.semitones as number, 'semitones');\n const fftOptions = resolveFftOptions('pitchShift', request.nFft, request.hopLength);\n return requireModule().pitchShiftEx(\n request.samples,\n request.sampleRate ?? 22050,\n request.semitones,\n fftOptions.nFft,\n fftOptions.hopLength,\n );\n}\n\n/**\n * Pitch-correct audio from a current MIDI note to a target MIDI note.\n *\n * Applies one constant, immediate transpose with no retune glide and preserves\n * the input buffer length. The whole interval is applied however large it is:\n * both endpoints are validated to [0, 127], so a two-octave move such as\n * C3 -> C5 transposes by the full 24 semitones. Use\n * {@link pitchCorrectToMidiTimevarying} for a caller-supplied pitch contour.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz\n * @param currentMidi - Detected/current MIDI note number\n * @param targetMidi - Desired MIDI note number\n * @returns Pitch-corrected audio\n */\nexport function pitchCorrectToMidi(request: PitchCorrectToMidiRequest): Float32Array;\nexport function pitchCorrectToMidi(\n samples: Float32Array,\n sampleRate?: number,\n currentMidi?: number,\n targetMidi?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function pitchCorrectToMidi(\n samples: Float32Array | PitchCorrectToMidiRequest,\n sampleRate = 22050,\n currentMidi = 69.0,\n targetMidi = 69.0,\n options: ValidateOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate, currentMidi, targetMidi, ...options }\n : samples;\n assertSamples('pitchCorrectToMidi', request.samples, request.validate !== false);\n return requireModule().pitchCorrectToMidi(\n request.samples,\n request.sampleRate ?? 22050,\n request.currentMidi ?? 69.0,\n request.targetMidi ?? 69.0,\n );\n}\n\n/**\n * Contour-following (\"time-varying\") pitch correction toward a MIDI target.\n *\n * Unlike {@link pitchCorrectToMidi} (a single constant transpose), this follows\n * the caller-supplied per-frame `f0Hz` contour and retunes every voiced frame\n * toward `targetMidi`, so vibrato/drift in the source is tracked rather than\n * flattened. `voiced` (truthy = voiced) and `voicedProb` ([0,1]) are optional;\n * omitting them treats every frame as voiced. An `f0Hz` NaN is accepted only\n * when the corresponding `voiced` entry is falsy, matching pYIN output. The\n * `voicedFlag` / `voicedProb` arrays of a {@link PitchResult} can be passed\n * through directly.\n *\n * @param samples - Audio samples (mono, float32)\n * @param f0Hz - Per-frame measured F0 in Hz (one entry per analysis frame)\n * @param targetMidi - Desired MIDI note number\n * @param sampleRate - Sample rate in Hz\n * @param hopLength - F0 hop in samples (frame i covers sample i*hopLength)\n * @param voiced - Optional per-frame voiced flags (truthy = voiced)\n * @param voicedProb - Optional per-frame voicing probability in [0, 1]\n * @returns Pitch-corrected audio\n */\nexport function pitchCorrectToMidiTimevarying(\n request: PitchCorrectToMidiTimevaryingRequest,\n): Float32Array;\nexport function pitchCorrectToMidiTimevarying(\n samples: Float32Array,\n f0Hz: Float32Array,\n targetMidi: number,\n sampleRate?: number,\n hopLength?: number,\n voiced?: VoicedFlags,\n voicedProb?: Float32Array,\n options?: ValidateOptions,\n): Float32Array;\nexport function pitchCorrectToMidiTimevarying(\n samples: Float32Array | PitchCorrectToMidiTimevaryingRequest,\n f0Hz?: Float32Array,\n targetMidi?: number,\n sampleRate = 22050,\n hopLength = 512,\n voiced?: VoicedFlags,\n voicedProb?: Float32Array,\n options: ValidateOptions = {},\n): Float32Array {\n const request: PitchCorrectToMidiTimevaryingRequest =\n samples instanceof Float32Array\n ? {\n samples,\n f0Hz: f0Hz as Float32Array,\n targetMidi: targetMidi as number,\n sampleRate,\n hopLength,\n voiced,\n voicedProb,\n ...options,\n }\n : samples;\n assertSamples('pitchCorrectToMidiTimevarying', request.samples, request.validate !== false);\n if (request.voiced && request.voiced.length !== request.f0Hz.length) {\n throw new RangeError('pitchCorrectToMidiTimevarying: voiced length must match f0Hz length');\n }\n if (request.voicedProb && request.voicedProb.length !== request.f0Hz.length) {\n throw new RangeError('pitchCorrectToMidiTimevarying: voicedProb length must match f0Hz length');\n }\n const voicedF32 = request.voiced ? toVoicedFloat32(request.voiced) : undefined;\n return requireModule().pitchCorrectToMidiTimevarying(\n request.samples,\n request.sampleRate ?? 22050,\n request.f0Hz,\n request.targetMidi,\n request.hopLength ?? 512,\n voicedF32,\n request.voicedProb,\n );\n}\n\n/**\n * Contour-following pitch correction toward a fixed MIDI note OR a musical\n * scale, with tunable retune strength and vibrato preservation.\n *\n * Generalises {@link pitchCorrectToMidiTimevarying}: the same caller-supplied\n * per-frame `f0Hz` contour drives correction, but `options.mode` selects between\n * a fixed-MIDI target (`'midi'`, default) and scale quantisation (`'scale'`),\n * and the retune knobs shape natural-vs-robotic correction. An `f0Hz` NaN is\n * accepted only for a frame marked unvoiced.\n *\n * @param samples - Audio samples (mono, float32)\n * @param f0Hz - Per-frame measured F0 in Hz (one entry per analysis frame)\n * @param sampleRate - Sample rate in Hz\n * @param hopLength - F0 hop in samples (frame i covers sample i*hopLength)\n * @param options - Target mode + retune knobs + optional voiced/voicedProb arrays\n * @returns Pitch-corrected audio\n */\nexport function pitchCorrectTimevarying(request: PitchCorrectTimevaryingRequest): Float32Array;\nexport function pitchCorrectTimevarying(\n samples: Float32Array,\n f0Hz: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n options?: PitchCorrectOptions,\n): Float32Array;\nexport function pitchCorrectTimevarying(\n samples: Float32Array | PitchCorrectTimevaryingRequest,\n f0Hz?: Float32Array,\n sampleRate = 22050,\n hopLength = 512,\n options: PitchCorrectOptions = {},\n): Float32Array {\n const request: PitchCorrectTimevaryingRequest =\n samples instanceof Float32Array\n ? { samples, f0Hz: f0Hz as Float32Array, sampleRate, hopLength, ...options }\n : samples;\n assertSamples('pitchCorrectTimevarying', request.samples, request.validate !== false);\n if (request.voiced && request.voiced.length !== request.f0Hz.length) {\n throw new RangeError('pitchCorrectTimevarying: voiced length must match f0Hz length');\n }\n if (request.voicedProb && request.voicedProb.length !== request.f0Hz.length) {\n throw new RangeError('pitchCorrectTimevarying: voicedProb length must match f0Hz length');\n }\n const nativeOptions = {\n ...request,\n voiced: request.voiced ? toVoicedFloat32(request.voiced) : undefined,\n };\n return requireModule().pitchCorrectTimevarying(\n request.samples,\n request.sampleRate ?? 22050,\n request.f0Hz,\n request.hopLength ?? 512,\n nativeOptions,\n );\n}\n","import { getSonareModule } from './module_state';\nimport type { RealtimeVoiceChangerConfigInput } from './public_types';\nimport type { ValidateOptions } from './validation';\nimport { assertSamples } from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n/** Options for {@link voiceChange}. All fields are optional. */\nexport interface VoiceChangeOptions extends ValidateOptions {\n /** Pitch shift in semitones (negative = down). Default 0. */\n pitchSemitones?: number;\n /** Formant scale factor (>1 brightens, <1 darkens). Default 1. */\n formantFactor?: number;\n}\n\n/** Canonical request form for one-shot voice changing. */\nexport interface VoiceChangeRequest extends VoiceChangeOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\n/**\n * Apply a voice change by shifting pitch and formants independently.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz\n * @param options - Pitch/formant settings ({@link VoiceChangeOptions})\n * @returns Voice-changed audio\n */\nexport function voiceChange(request: VoiceChangeRequest): Float32Array;\nexport function voiceChange(\n samples: Float32Array,\n sampleRate?: number,\n options?: VoiceChangeOptions,\n): Float32Array;\nexport function voiceChange(\n samples: Float32Array | VoiceChangeRequest,\n sampleRate = 22050,\n options: VoiceChangeOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('voiceChange', request.samples, request.validate !== false);\n return requireModule().voiceChange(\n request.samples,\n request.sampleRate ?? 22050,\n request.pitchSemitones ?? 0.0,\n request.formantFactor ?? 1.0,\n );\n}\n\n/** Options for the offline {@link voiceChangeRealtime} convenience wrapper. */\nexport interface VoiceChangeRealtimeOptions extends ValidateOptions {\n /** Channel count (1 = mono, 2 = interleaved stereo). */\n channels?: 1 | 2;\n /** @deprecated The shared C-ABI renderer uses a fixed cross-surface block size. */\n blockSize?: number;\n}\n\n/** Canonical request form for offline realtime voice changing. */\nexport interface VoiceChangeRealtimeRequest extends VoiceChangeRealtimeOptions {\n samples: Float32Array;\n sampleRate?: number;\n preset?: RealtimeVoiceChangerConfigInput;\n}\n\n/**\n * Applies the realtime voice-changer chain to a whole buffer in one call.\n *\n * Uses the shared C-ABI renderer, so Python, Node, and WASM use the same\n * fixed block size and latency compensation. For mono, `samples` is a plain\n * buffer; for stereo, it is interleaved (L0,R0,L1,R1,...).\n *\n * @param samples - Audio samples (mono, or interleaved stereo when channels=2)\n * @param sampleRate - Sample rate in Hz (default 48000, matching Python/Node)\n * @param preset - Voice-changer preset id or full config object\n * @param options - Channel count and block size ({@link VoiceChangeRealtimeOptions})\n * @returns The processed buffer (same layout/length as the input).\n */\nexport function voiceChangeRealtime(request: VoiceChangeRealtimeRequest): Float32Array;\nexport function voiceChangeRealtime(\n samples: Float32Array,\n sampleRate?: number,\n preset?: RealtimeVoiceChangerConfigInput,\n options?: VoiceChangeRealtimeOptions,\n): Float32Array;\nexport function voiceChangeRealtime(\n samples: Float32Array | VoiceChangeRealtimeRequest,\n sampleRate = 48000,\n preset: RealtimeVoiceChangerConfigInput = 'neutral-monitor',\n options: VoiceChangeRealtimeOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array ? { samples, sampleRate, preset, ...options } : samples;\n assertSamples('voiceChangeRealtime', request.samples, request.validate !== false);\n const channels = request.channels ?? 1;\n if (channels !== 1 && channels !== 2) {\n throw new Error('voiceChangeRealtime: channels must be 1 or 2.');\n }\n if (channels === 2 && request.samples.length % 2 !== 0) {\n throw new Error('voiceChangeRealtime: stereo input length must be a multiple of 2.');\n }\n const presetConfig = request.preset ?? 'neutral-monitor';\n return requireModule().voiceChangeRealtime(\n request.samples,\n request.sampleRate ?? 48000,\n typeof presetConfig === 'string' ? presetConfig : JSON.stringify(presetConfig),\n channels,\n );\n}\n","import type { MasteringChainConfig } from './public_types';\n\ntype ChainSection = { [key: string]: number | boolean | ChainSection | undefined };\n\n/**\n * Flattens a nested {@link MasteringChainConfig} into the dot-notation\n * `{ \"module.processor.param\": value }` map the core consumes. Internal helper\n * shared by the mastering-chain / master-audio entry points. The core owns\n * legacy leaf-name aliases, so this remains a structural flattening step.\n *\n * A key the caller already wrote in dot notation carries through untouched, so\n * both spellings a {@link MasteringChainConfig} accepts reach the core as the\n * same parameter — matching what the Python binding documents. An unknown key\n * in either spelling is rejected by the core, not here.\n */\nexport function flattenChainConfig(config: MasteringChainConfig): Record<string, number | boolean> {\n const out: Record<string, number | boolean> = {};\n const walk = (node: ChainSection, prefix: string): void => {\n for (const [key, value] of Object.entries(node)) {\n const path = prefix ? `${prefix}.${key}` : key;\n if (typeof value === 'number' || typeof value === 'boolean') {\n out[path] = value;\n } else if (value !== null && typeof value === 'object') {\n walk(value, path);\n } else if (value !== undefined) {\n throw new TypeError(`Mastering override '${path}' must be a number or boolean.`);\n }\n }\n };\n walk(config as ChainSection, '');\n\n return out;\n}\n","import { flattenChainConfig } from './_chain_config';\nimport { getSonareModule } from './module_state';\nimport type {\n MasteringChainConfig,\n MasteringChainResult,\n MasteringChainStereoResult,\n MasteringPreset,\n} from './public_types';\nimport type { ProgressCallback } from './sonare.js';\nimport type { ValidateOptions } from './validation';\nimport { assertSamples } from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\nexport type NormalizeMode = 'peak' | 'rms';\n\n// `context` is the calling entry point's name: the refusal is about that\n// caller's argument, so naming a fixed one would send a normalizeStereo user\n// looking at normalize.\nfunction resolveNormalizeMode(value: unknown, context = 'normalize'): NormalizeMode {\n if (value === undefined) {\n return 'peak';\n }\n if (typeof value !== 'string') {\n throw new TypeError(`${context}: mode must be the string 'peak' or 'rms'`);\n }\n if (value !== 'peak' && value !== 'rms') {\n throw new RangeError(`${context}: mode must be the string 'peak' or 'rms'`);\n }\n return value;\n}\n\nexport interface NormalizeRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n targetDb?: number;\n mode?: NormalizeMode;\n}\n\n/**\n * Normalize audio to a target peak or RMS level.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param targetDb - Finite target at or below 0 dBFS (default: 0 dB = full scale).\n * For `mode: 'peak'`, this is the peak target; for `mode: 'rms'`, this is the RMS target.\n * @param mode - Normalization mode: `'peak'` (default) or `'rms'`.\n * @returns Normalized audio\n */\nexport function normalize(request: NormalizeRequest): Float32Array;\nexport function normalize(\n samples: Float32Array,\n sampleRate: number,\n targetDb?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function normalize(\n samples: Float32Array,\n sampleRate: number,\n targetDb?: number,\n mode?: NormalizeMode,\n options?: ValidateOptions,\n): Float32Array;\nexport function normalize(\n samples: Float32Array | NormalizeRequest,\n sampleRate?: number,\n targetDb = 0.0,\n modeOrOptions: NormalizeMode | ValidateOptions = 'peak',\n options: ValidateOptions = {},\n): Float32Array {\n if (\n modeOrOptions !== undefined &&\n modeOrOptions !== null &&\n typeof modeOrOptions !== 'string' &&\n typeof modeOrOptions !== 'object'\n ) {\n throw new TypeError(\"normalize: mode must be the string 'peak' or 'rms'\");\n }\n if (modeOrOptions === null) {\n throw new TypeError(\"normalize: mode must be the string 'peak' or 'rms'\");\n }\n const positionalOptions =\n typeof modeOrOptions === 'object' && modeOrOptions !== null ? modeOrOptions : options;\n const positionalMode = typeof modeOrOptions === 'string' ? modeOrOptions : undefined;\n const request: NormalizeRequest =\n samples instanceof Float32Array\n ? { samples, sampleRate, targetDb, mode: positionalMode, ...positionalOptions }\n : samples;\n assertSamples('normalize', request.samples, request.validate !== false);\n const mode = resolveNormalizeMode(request.mode);\n return requireModule().normalizeEx(\n request.samples,\n request.sampleRate ?? 22050,\n request.targetDb ?? 0.0,\n mode,\n );\n}\n\nexport interface NormalizeStereoRequest extends ValidateOptions {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n targetDb?: number;\n mode?: NormalizeMode;\n}\n\n/** A normalized channel pair and the gain both channels were moved by. */\nexport interface NormalizeStereoResult {\n left: Float32Array;\n right: Float32Array;\n /**\n * One figure rather than a pair: the gain is one decision shared by both\n * channels. Silence leaves the pair untouched and reports 0.\n */\n appliedGainDb: number;\n}\n\n/**\n * Normalize a stereo pair on a gain measured across both channels.\n *\n * Normalizing the two channels separately lifts the quieter one until the peaks\n * match, which changes the balance rather than the level. The level here is read\n * from the pair and the resulting gain goes to both channels, so the image is\n * preserved: for `mode: 'peak'` the louder channel reaches `targetDb` and the\n * other keeps its distance from it; for `mode: 'rms'` the quantity driven to\n * `targetDb` is the root mean square over both channels' samples together — the\n * quadratic mean of the per-channel figures, not their average — and the output\n * is hard-clipped to [-1, 1].\n *\n * @param request.left - Left channel samples (float32)\n * @param request.right - Right channel samples, same length as `left`\n * @param request.sampleRate - Sample rate in Hz (default: 22050)\n * @param request.targetDb - Finite target at or below 0 dBFS. Defaults to 0 for\n * `mode: 'peak'` and -20 for `mode: 'rms'`, matching the library and the other\n * language surfaces.\n * @param request.mode - `'peak'` (default) or `'rms'`\n * @returns The normalized pair and the shared gain in dB\n * @throws RangeError when the two channels differ in length\n *\n * @example\n * ```ts\n * const { left, right, appliedGainDb } = normalizeStereo({\n * left: leftSamples,\n * right: rightSamples,\n * sampleRate: 44100,\n * targetDb: -1,\n * });\n * ```\n */\nexport function normalizeStereo(request: NormalizeStereoRequest): NormalizeStereoResult {\n assertSamples('normalizeStereo', request.left, request.validate !== false);\n assertSamples('normalizeStereo', request.right, request.validate !== false);\n if (request.left.length !== request.right.length) {\n throw new RangeError('Stereo channel lengths must match.');\n }\n const mode = resolveNormalizeMode(request.mode, 'normalizeStereo');\n // Mode-dependent, unlike the mono `normalize` on this surface, which defaults\n // to 0 dB in both modes. 0 dBFS RMS is not a usable default -- the peaks sit\n // well above the RMS, so every one of them clips -- and the library and the\n // other surfaces all default RMS to -20. A new entry point takes the shared\n // default rather than inheriting a surface-local one.\n const targetDb = request.targetDb ?? (mode === 'rms' ? -20.0 : 0.0);\n return requireModule().normalizeStereo(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n targetDb,\n mode,\n );\n}\n\n/** Internal envelope selecting the core dotted-param parser in the embind layer. */\nfunction canonicalChainConfig(config: MasteringChainConfig): Record<string, unknown> {\n return { __flatParams: flattenChainConfig(config) };\n}\n\nexport interface MasteringChainRequest {\n samples: Float32Array;\n sampleRate?: number;\n config?: MasteringChainConfig;\n onProgress?: ProgressCallback;\n cancel?: () => boolean;\n}\n\nexport interface MasteringChainStereoRequest {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n config?: MasteringChainConfig;\n onProgress?: ProgressCallback;\n cancel?: () => boolean;\n}\n\n/** Canonical request form for one-shot preset mastering. */\nexport interface MasterAudioRequest {\n samples: Float32Array;\n sampleRate?: number;\n preset?: MasteringPreset;\n overrides?: MasteringChainConfig;\n onProgress?: ProgressCallback;\n cancel?: () => boolean;\n}\n\n/** Canonical request form for one-shot stereo preset mastering. */\nexport interface MasterAudioStereoRequest {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n preset?: MasteringPreset;\n overrides?: MasteringChainConfig;\n onProgress?: ProgressCallback;\n cancel?: () => boolean;\n}\n\nfunction masterAudioRequest(\n requestOrSamples: MasterAudioRequest | Float32Array,\n sampleRate: number,\n preset: MasteringPreset,\n overrides: MasteringChainConfig | null,\n onProgress?: ProgressCallback,\n): MasterAudioRequest {\n if (requestOrSamples instanceof Float32Array) {\n return {\n samples: requestOrSamples,\n sampleRate,\n preset,\n overrides: overrides ?? {},\n onProgress,\n };\n }\n return requestOrSamples;\n}\n\nfunction masterAudioStereoRequest(\n requestOrLeft: MasterAudioStereoRequest | Float32Array,\n right: Float32Array | undefined,\n sampleRate: number,\n preset: MasteringPreset,\n overrides: MasteringChainConfig | null,\n onProgress?: ProgressCallback,\n): MasterAudioStereoRequest {\n if (requestOrLeft instanceof Float32Array) {\n return {\n left: requestOrLeft,\n right: right as Float32Array,\n sampleRate,\n preset,\n overrides: overrides ?? {},\n onProgress,\n };\n }\n return requestOrLeft;\n}\n\n/**\n * Apply a configurable mastering chain in WASM.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param config - Chain stage configuration\n * @returns Processed audio, loudness metadata, and applied stage names\n */\nexport function masteringChain(request: MasteringChainRequest): MasteringChainResult;\nexport function masteringChain(\n samples: Float32Array,\n sampleRate?: number,\n config?: MasteringChainConfig,\n onProgress?: ProgressCallback,\n): MasteringChainResult;\nexport function masteringChain(\n samples: Float32Array | MasteringChainRequest,\n sampleRate = 22050,\n config: MasteringChainConfig = {},\n onProgress?: ProgressCallback,\n): MasteringChainResult {\n const request =\n samples instanceof Float32Array ? { samples, sampleRate, config, onProgress } : samples;\n if (request.onProgress || request.cancel) {\n return requireModule().masteringChainWithProgress(\n request.samples,\n request.sampleRate ?? 22050,\n canonicalChainConfig(request.config ?? {}),\n request.onProgress ?? (() => {}),\n request.cancel ?? (() => false),\n );\n }\n return requireModule().masteringChain(\n request.samples,\n request.sampleRate ?? 22050,\n canonicalChainConfig(request.config ?? {}),\n );\n}\n\n/**\n * Apply a configurable stereo mastering chain in WASM.\n *\n * @param left - Left channel samples\n * @param right - Right channel samples\n * @param sampleRate - Sample rate in Hz\n * @param config - Chain stage configuration\n * @returns Processed stereo audio, loudness metadata, and applied stage names\n */\nexport function masteringChainStereo(\n request: MasteringChainStereoRequest,\n): MasteringChainStereoResult;\nexport function masteringChainStereo(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n config?: MasteringChainConfig,\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult;\nexport function masteringChainStereo(\n left: Float32Array | MasteringChainStereoRequest,\n right?: Float32Array,\n sampleRate = 22050,\n config: MasteringChainConfig = {},\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, config, onProgress }\n : left;\n if (request.left.length !== request.right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n if (request.onProgress || request.cancel) {\n return requireModule().masteringChainStereoWithProgress(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n canonicalChainConfig(request.config ?? {}),\n request.onProgress ?? (() => {}),\n request.cancel ?? (() => false),\n );\n }\n return requireModule().masteringChainStereo(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n canonicalChainConfig(request.config ?? {}),\n );\n}\n\n/**\n * Apply a configurable mastering chain in WASM with progress reporting.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param config - Chain stage configuration\n * @param onProgress - Progress callback (progress: 0-1, stage: string)\n * @returns Processed audio, loudness metadata, and applied stage names\n */\nexport function masteringChainWithProgress(\n request: MasteringChainRequest & Required<Pick<MasteringChainRequest, 'onProgress'>>,\n): MasteringChainResult;\nexport function masteringChainWithProgress(\n samples: Float32Array,\n sampleRate?: number,\n config?: MasteringChainConfig,\n onProgress?: ProgressCallback,\n): MasteringChainResult;\nexport function masteringChainWithProgress(\n samples: Float32Array | MasteringChainRequest,\n sampleRate = 22050,\n config: MasteringChainConfig = {},\n onProgress?: ProgressCallback,\n): MasteringChainResult {\n const request =\n samples instanceof Float32Array ? { samples, sampleRate, config, onProgress } : samples;\n if (!request.onProgress) {\n throw new TypeError('masteringChainWithProgress: onProgress is required');\n }\n return requireModule().masteringChainWithProgress(\n request.samples,\n request.sampleRate ?? 22050,\n canonicalChainConfig(request.config ?? {}),\n request.onProgress,\n request.cancel ?? (() => false),\n );\n}\n\n/**\n * Apply a configurable stereo mastering chain in WASM with progress reporting.\n *\n * @param left - Left channel samples\n * @param right - Right channel samples\n * @param sampleRate - Sample rate in Hz\n * @param config - Chain stage configuration\n * @param onProgress - Progress callback (progress: 0-1, stage: string)\n * @returns Processed stereo audio, loudness metadata, and applied stage names\n */\nexport function masteringChainStereoWithProgress(\n request: MasteringChainStereoRequest & Required<Pick<MasteringChainStereoRequest, 'onProgress'>>,\n): MasteringChainStereoResult;\nexport function masteringChainStereoWithProgress(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n config?: MasteringChainConfig,\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult;\nexport function masteringChainStereoWithProgress(\n left: Float32Array | MasteringChainStereoRequest,\n right?: Float32Array,\n sampleRate = 22050,\n config: MasteringChainConfig = {},\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, config, onProgress }\n : left;\n if (!request.onProgress) {\n throw new TypeError('masteringChainStereoWithProgress: onProgress is required');\n }\n if (request.left.length !== request.right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n return requireModule().masteringChainStereoWithProgress(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n canonicalChainConfig(request.config ?? {}),\n request.onProgress,\n request.cancel ?? (() => false),\n );\n}\n\n/**\n * List built-in mastering preset identifiers.\n *\n * @returns Preset names in display order (e.g. \"pop\", \"edm\", \"aiMusic\")\n */\nexport function masteringPresetNames(): MasteringPreset[] {\n return Array.from(requireModule().masteringPresetNames()) as MasteringPreset[];\n}\n\n/**\n * The flat `{key: number|boolean}` params of preset `preset`'s built-in chain\n * configuration, in the same key space {@link masteringAssistantSuggestChain}\n * returns. Passing this straight through as `overrides` to {@link masterAudio}\n * reproduces the preset unchanged, bit for bit in the C++ core.\n *\n * @param preset - Preset identifier from {@link masteringPresetNames}.\n * @throws For an unknown `preset`.\n */\nexport function masteringPresetParams(preset: MasteringPreset): Record<string, number | boolean> {\n return requireModule().masteringPresetParams(preset);\n}\n\n/**\n * List the delivery targets the mastering assistant accepts as `targetPlatform`.\n *\n * Read from the library rather than from a list kept here, so a target added in\n * the core is discoverable without a binding change.\n *\n * @returns Target names in index order (e.g. \"streaming\", \"broadcast\", \"club\")\n */\nexport function masteringPlatformNames(): string[] {\n return Array.from(requireModule().masteringPlatformNames());\n}\n\n/**\n * Apply a named mastering preset chain to mono audio.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param presetName - Preset identifier from {@link masteringPresetNames}\n * @param overrides - Optional nested {@link MasteringChainConfig} applied on top of the preset (e.g. `{ loudness: { targetLufs: -14 } }`). Pass `null` for preset defaults.\n * @param onProgress - Optional per-stage progress callback (progress: 0-1, stage: string).\n * @returns Processed audio, loudness metadata, and applied stage names\n */\nexport function masterAudio(request: MasterAudioRequest): MasteringChainResult;\nexport function masterAudio(\n samples: Float32Array,\n sampleRate?: number,\n presetName?: MasteringPreset,\n overrides?: MasteringChainConfig,\n onProgress?: ProgressCallback,\n): MasteringChainResult;\nexport function masterAudio(\n samples: MasterAudioRequest | Float32Array,\n sampleRate = 22050,\n presetName: MasteringPreset = 'pop',\n overrides: MasteringChainConfig = {},\n onProgress?: ProgressCallback,\n): MasteringChainResult {\n const request = masterAudioRequest(samples, sampleRate, presetName, overrides, onProgress);\n const flat = flattenChainConfig(request.overrides ?? {});\n if (request.onProgress || request.cancel) {\n return requireModule().masterAudioWithProgress(\n request.preset ?? 'pop',\n request.samples,\n request.sampleRate ?? 22050,\n flat,\n request.onProgress ?? (() => {}),\n request.cancel ?? (() => false),\n );\n }\n return requireModule().masterAudio(\n request.preset ?? 'pop',\n request.samples,\n request.sampleRate ?? 22050,\n flat,\n );\n}\n\n/**\n * Apply a named mastering preset chain to stereo audio.\n *\n * @param left - Left channel samples\n * @param right - Right channel samples\n * @param sampleRate - Sample rate in Hz\n * @param presetName - Preset identifier from {@link masteringPresetNames}\n * @param overrides - Optional nested {@link MasteringChainConfig} applied on top of the preset (e.g. `{ loudness: { targetLufs: -14 } }`). Pass `null` for preset defaults.\n * @param onProgress - Optional per-stage progress callback (progress: 0-1, stage: string).\n * @returns Processed stereo audio, loudness metadata, and applied stage names\n */\nexport function masterAudioStereo(request: MasterAudioStereoRequest): MasteringChainStereoResult;\nexport function masterAudioStereo(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n presetName?: MasteringPreset,\n overrides?: MasteringChainConfig,\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult;\nexport function masterAudioStereo(\n left: MasterAudioStereoRequest | Float32Array,\n right: Float32Array | undefined = undefined,\n sampleRate = 22050,\n presetName: MasteringPreset = 'pop',\n overrides: MasteringChainConfig = {},\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult {\n const request = masterAudioStereoRequest(\n left,\n right,\n sampleRate,\n presetName,\n overrides,\n onProgress,\n );\n const flat = flattenChainConfig(request.overrides ?? {});\n if (request.left.length !== request.right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n if (request.onProgress || request.cancel) {\n return requireModule().masterAudioStereoWithProgress(\n request.preset ?? 'pop',\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n flat,\n request.onProgress ?? (() => {}),\n request.cancel ?? (() => false),\n );\n }\n return requireModule().masterAudioStereo(\n request.preset ?? 'pop',\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n flat,\n );\n}\n\n/**\n * Mono `masterAudio` with per-stage progress reporting. `onProgress` is invoked\n * with `(progress, stage)` between each chain stage (progress is in [0,1]).\n */\nexport function masterAudioWithProgress(\n request: MasterAudioRequest & Required<Pick<MasterAudioRequest, 'onProgress'>>,\n): MasteringChainResult;\nexport function masterAudioWithProgress(\n samples: Float32Array,\n sampleRate?: number,\n presetName?: MasteringPreset,\n overrides?: MasteringChainConfig | null,\n onProgress?: ProgressCallback,\n): MasteringChainResult;\nexport function masterAudioWithProgress(\n samples: MasterAudioRequest | Float32Array,\n sampleRate = 22050,\n presetName: MasteringPreset = 'pop',\n overrides: MasteringChainConfig | null = null,\n onProgress?: ProgressCallback,\n): MasteringChainResult {\n const request = masterAudioRequest(samples, sampleRate, presetName, overrides, onProgress);\n if (!request.onProgress) {\n throw new TypeError('masterAudioWithProgress: onProgress is required');\n }\n return requireModule().masterAudioWithProgress(\n request.preset ?? 'pop',\n request.samples,\n request.sampleRate ?? 22050,\n flattenChainConfig(request.overrides ?? {}),\n request.onProgress,\n request.cancel ?? (() => false),\n );\n}\n\n/**\n * Stereo `masterAudio` with per-stage progress reporting.\n */\nexport function masterAudioStereoWithProgress(\n request: MasterAudioStereoRequest & Required<Pick<MasterAudioStereoRequest, 'onProgress'>>,\n): MasteringChainStereoResult;\nexport function masterAudioStereoWithProgress(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n presetName?: MasteringPreset,\n overrides?: MasteringChainConfig | null,\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult;\nexport function masterAudioStereoWithProgress(\n left: MasterAudioStereoRequest | Float32Array,\n right: Float32Array | undefined = undefined,\n sampleRate = 22050,\n presetName: MasteringPreset = 'pop',\n overrides: MasteringChainConfig | null = null,\n onProgress?: ProgressCallback,\n): MasteringChainStereoResult {\n const request = masterAudioStereoRequest(\n left,\n right,\n sampleRate,\n presetName,\n overrides,\n onProgress,\n );\n if (!request.onProgress) {\n throw new TypeError('masterAudioStereoWithProgress: onProgress is required');\n }\n if (request.left.length !== request.right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n return requireModule().masterAudioStereoWithProgress(\n request.preset ?? 'pop',\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n flattenChainConfig(request.overrides ?? {}),\n request.onProgress,\n request.cancel ?? (() => false),\n );\n}\n","import { ErrorCode, SonareError } from './errors';\nimport { getSonareModule } from './module_state';\nimport type {\n LoudnessMatchResult,\n MasteringAssistantParams,\n MasteringInsertParamChoice,\n MasteringInsertSlot,\n MasteringOptions,\n MasteringProcessorParams,\n MasteringResult,\n MasteringStereoResult,\n PairAnalysis,\n PairProcessor,\n SoloProcessor,\n StereoAnalysis,\n StreamingPlatform,\n} from './public_types';\n\nexport type { MasteringInsertParamChoice, MasteringInsertSlot };\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n/** Canonical request form for loudness/true-peak mastering. */\nexport interface MasteringRequest extends MasteringOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\nexport interface MasteringProcessRequest {\n processorName: SoloProcessor;\n samples: Float32Array;\n sampleRate?: number;\n params?: MasteringProcessorParams;\n}\n\nexport interface MasteringProcessStereoRequest {\n processorName: SoloProcessor;\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n params?: MasteringProcessorParams;\n}\n\n/** Canonical request form for a two-input match processor. */\nexport interface MasteringPairProcessRequest {\n processorName: PairProcessor;\n source: Float32Array;\n reference: Float32Array;\n sampleRate?: number;\n params?: MasteringProcessorParams;\n}\n\n/** Canonical request form for {@link masteringAbMatchLoudness}. */\nexport interface MasteringAbMatchLoudnessRequest {\n /** The take to gain-match. */\n source: Float32Array;\n /** The take whose loudness `source` is matched to; returned untouched. */\n reference: Float32Array;\n sampleRate?: number;\n}\n\n/** Canonical request form for a two-input match analysis. */\nexport interface MasteringPairAnalyzeRequest {\n analysisName: PairAnalysis;\n source: Float32Array;\n reference: Float32Array;\n sampleRate?: number;\n params?: MasteringProcessorParams;\n}\n\n/** Canonical request form for a stereo analysis. */\nexport interface MasteringStereoAnalyzeRequest {\n analysisName: StereoAnalysis;\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n params?: MasteringProcessorParams;\n}\n\n/** Canonical request form for assistant/profile calls. */\nexport interface MasteringSamplesParamsRequest {\n samples: Float32Array;\n sampleRate?: number;\n params?: MasteringProcessorParams;\n}\n\n/** Canonical request form for the assistant, whose params carry a target platform. */\nexport interface MasteringAssistantParamsRequest {\n samples: Float32Array;\n sampleRate?: number;\n params?: MasteringAssistantParams;\n}\n\n/** Canonical request form for streaming-platform preview. */\nexport interface MasteringStreamingPreviewRequest {\n samples: Float32Array;\n sampleRate?: number;\n platforms?: StreamingPlatform[];\n}\n\n/** Canonical request form for the stereo analysis entry points. */\nexport interface MasteringStereoParamsRequest {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n params?: MasteringProcessorParams;\n}\n\n/** Stereo counterpart of {@link MasteringAssistantParamsRequest}. */\nexport interface MasteringAssistantStereoParamsRequest {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n params?: MasteringAssistantParams;\n}\n\n/** Canonical request form for the stereo streaming-platform preview. */\nexport interface MasteringStreamingPreviewStereoRequest {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n platforms?: StreamingPlatform[];\n}\n\n/**\n * Apply mastering loudness normalization with a true-peak ceiling.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param options - Loudness/ceiling settings ({@link MasteringOptions})\n * @returns Processed audio and loudness metadata\n */\nexport function mastering(request: MasteringRequest): MasteringResult;\nexport function mastering(\n samples: Float32Array,\n sampleRate?: number,\n options?: MasteringOptions,\n): MasteringResult;\nexport function mastering(\n samples: MasteringRequest | Float32Array,\n sampleRate = 22050,\n options: MasteringOptions = {},\n): MasteringResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n return requireModule().mastering(\n request.samples,\n request.sampleRate ?? 22050,\n request.targetLufs ?? -14.0,\n request.ceilingDb ?? -1.0,\n request.truePeakOversample ?? 4,\n request.releaseMs ?? 0, // 0 => library default (50 ms)\n request.applyGainAtInputRate ?? false,\n );\n}\n\nexport function masteringProcessorNames(): SoloProcessor[] {\n // embind hands back a vector whose constructor is not this realm's Array, so the\n // result is not structured-cloneable (breaks postMessage to a Worker).\n // Array.from() re-roots it as a plain Array. Same for the sibling *Names() below.\n return Array.from(requireModule().masteringProcessorNames()) as SoloProcessor[];\n}\n\n/**\n * Names of the insert processors the mastering chain can instantiate by name\n * (`mastering::api::insert_factory_names`). Mirrors the C-ABI\n * `sonare_mastering_insert_names` (which joins this list) as a `string[]`.\n */\nexport function masteringInsertNames(): string[] {\n return requireModule().masteringInsertNames();\n}\n\n/**\n * Returns the camelCase parameter names a given insert / FX processor reads, for\n * tooling/validation. Any key NOT in this list is silently ignored by the\n * processor (and would be reported via {@link Mixer.sceneWarnings} when a scene\n * carrying it is loaded). Band/sub-band processors enumerate their indexed\n * `band{i}.<field>` keys. Returns an empty array for an unknown name (or one\n * whose insert needs an unavailable build feature, e.g. FX).\n *\n * @param name - Insert processor name (see {@link masteringInsertNames}).\n */\nexport function masteringInsertParamNames(name: string): string[] {\n return Array.from(requireModule().masteringInsertParamNames(name));\n}\n\n/**\n * One parameter an insert processor's construction reads, whether or not it\n * is realtime-automatable.\n */\nexport interface MasteringInsertParamInfo {\n /** JSON-key parameter name, as used in scene insert params. */\n name: string;\n /**\n * Integer param id for realtime automation lanes / MIDI-CC binding, or null\n * for a construction-only key with no automation target.\n */\n id: number | null;\n /** Whether the param can be changed live from the audio thread; false when `id` is null. */\n rtSafe: boolean;\n /**\n * The C++ type the processor's config builder reads the key as. `\"enum\"` is\n * sent as the number in its `choices` entry; `\"string\"` / `\"array\"` (an\n * embedded impulse response, a per-band list) is construction-only and\n * reports null for `min`, `max`, `default` and `choices`.\n */\n type: 'boolean' | 'number' | 'enum' | 'string' | 'array';\n /**\n * Smallest value construction accepts, or null when the catalog states no\n * limit or `choices` is non-null. Measured, so it is a hard constraint\n * rather than a UI range; see {@link CapabilityCatalogParameter} for what a\n * measured bound does and does not promise.\n */\n min: number | null;\n /** Largest value construction accepts, or null when the catalog states no limit or `choices` is non-null. */\n max: number | null;\n /**\n * Value the processor uses when the key is absent — the config struct's own\n * field initializer, an enum as its number. Null for a param id with no\n * construction key, a `\"string\"` / `\"array\"` key, or a construction key with\n * no fallback.\n */\n default: boolean | number | null;\n /** Physical unit, or null when the parameter is unitless. */\n unit: string | null;\n /**\n * The closed set of values construction accepts, in value order, or null\n * when the accepted values are not a closed set. Non-null only for `\"enum\"`\n * (every declared enumerator construction accepts) or a `\"number\"` key\n * whose accepted integers have holes; `min` / `max` are then both null.\n */\n choices: MasteringInsertParamChoice[] | null;\n /**\n * The {@link MasteringInsertSlot} this key belongs to, or null for a key that\n * always exists.\n */\n slot: string | null;\n}\n\n/**\n * Returns every parameter an insert / FX processor's construction reads,\n * including construction-time-only keys with no realtime automation target.\n * Entries come in two runs: first the processor's realtime automation\n * targets in id order (the keys accepted by\n * {@link RealtimeEngine.setTrackStripInsertParamByName}, `id` non-null); then,\n * sorted by name, every other construction key with `id` null and `rtSafe`\n * false. The name set matches {@link masteringInsertParamNames} plus any\n * automation target construction does not read. Returns an empty array for an\n * unknown name.\n *\n * @param name - Insert processor name (see {@link masteringInsertNames}).\n */\nexport function masteringInsertParamInfo(name: string): MasteringInsertParamInfo[] {\n const json = requireModule().masteringInsertParamInfo(name);\n return JSON.parse(json) as MasteringInsertParamInfo[];\n}\n\n/** Latency and tail of one insert instance, in samples. */\nexport interface MasteringInsertTiming {\n /** Latency in samples at the queried sample rate. */\n latencySamples: number;\n /** Audible decay tail in samples at the queried sample rate. */\n tailSamples: number;\n}\n\n/** One built-in amp-sim rig with its resolved starting configuration. */\nexport interface MasteringAmpPresetCatalogEntry {\n /** Stable index used by the amp-sim `presetIndex` parameter. */\n index: number;\n /** Canonical preset identifier accepted by the amp-sim insert. */\n name: string;\n /** Effective values from the core preset, before sparse user overrides. */\n params: Record<string, number | boolean>;\n}\n\n/**\n * Returns the built-in amp-sim rigs and their resolved control values.\n *\n * The catalog is read-only metadata for hosts such as Studio. Persist only the\n * preset index and explicit overrides in a project so future core updates can\n * continue to define the canonical DSP configuration.\n */\nexport function masteringAmpPresetCatalog(): MasteringAmpPresetCatalogEntry[] {\n const json = requireModule().masteringAmpPresetCatalog();\n return JSON.parse(json) as MasteringAmpPresetCatalogEntry[];\n}\n\n/**\n * Reject a `params` value {@link masteringInsertTiming} cannot serialize:\n * anything other than a finite number or a boolean, naming the offending key.\n * Booleans serialize as JSON booleans, not 0/1, since the C++ reader accepts\n * `is_bool` alongside a number.\n */\nfunction insertTimingParamsToJson(fnName: string, params: Record<string, number | boolean>) {\n const out: Record<string, number | boolean> = {};\n for (const [key, value] of Object.entries(params)) {\n if (typeof value === 'boolean') {\n out[key] = value;\n continue;\n }\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new SonareError(\n ErrorCode.InvalidParameter,\n 'InvalidParameter',\n `${fnName}: params.${key} must be a finite number or boolean`,\n );\n }\n out[key] = value;\n }\n return JSON.stringify(out);\n}\n\n/**\n * Latency and tail of insert `name` built from `params` and prepared at\n * `sampleRate` (`mastering::api::insert_timing`). Answers for the exact\n * instance a scene or strip would build — an oversampled saturation path, a\n * linear-phase crossover, a lookahead all change the reported latency. The\n * capability catalog's `latencySamples` / `tailSamples` are this query at\n * default parameters and 48 kHz. `effects.reverb.convolution` answers for its\n * configuration without an impulse response: its latency is its fixed\n * partition size and does not depend on one.\n *\n * A key `name`'s construction does not read is refused rather than ignored,\n * because an ignored key would answer for a configuration the caller did not\n * ask for.\n *\n * @param name - Insert processor name (see {@link masteringInsertNames}).\n * @param params - Flat parameter values, keyed as in {@link masteringInsertParamInfo}.\n * @param sampleRate - Rate the insert is prepared at.\n * @throws For an unknown `name`, a key the insert does not read, a value its\n * construction or `prepare` refuses, or a `params` value that is not a\n * finite number or boolean.\n */\nexport function masteringInsertTiming(\n name: string,\n params: Record<string, number | boolean>,\n sampleRate: number,\n): MasteringInsertTiming {\n const json = insertTimingParamsToJson('masteringInsertTiming', params);\n return requireModule().masteringInsertTiming(name, json, sampleRate);\n}\n\n/**\n * How a processor handles a buffer with more than two channels (a surround\n * bed). \"multichannel\" processes every plane in one call; \"stereoPairOnly\"\n * operates on the front L/R pair and passes any surround planes through dry.\n * \"perChannel\"/\"passthrough\" are reserved and unused by the current catalog.\n */\nexport type MasteringChannelPolicy =\n | 'multichannel'\n | 'stereoPairOnly'\n | 'perChannel'\n | 'passthrough';\n\n/** Coarse algorithmic work estimate for a realtime insert; not a benchmark. */\nexport type MasteringRealtimeCost = 'low' | 'moderate' | 'high';\n\n/**\n * Catalog grouping for a processor picker, derived from the id's prefix\n * (\"eq.*\" -> \"eq\", \"match.*\" -> \"reference\"); anything unprefixed is \"other\".\n */\nexport type MasteringProcessorCategory =\n | 'dynamics'\n | 'effects'\n | 'eq'\n | 'final'\n | 'maximizer'\n | 'multiband'\n | 'other'\n | 'reference'\n | 'repair'\n | 'saturation'\n | 'spectral'\n | 'stereo'\n | 'utility';\n\n/** One processor's realtime/offline/pair classification in the catalog. */\nexport interface MasteringProcessorCatalogEntry {\n /** Processor id (the name used for scene inserts / named processors). */\n id: string;\n /**\n * Primary classification, by precedence pair > realtime > offline: \"pair\" for\n * two-input match.* processors, \"realtime\" for ids that build as a realtime\n * scene insert, \"offline\" for whole-file-only processors.\n */\n kind: 'realtime' | 'offline' | 'pair';\n /** True exactly for ids that always succeed as a realtime scene insert. */\n realtimeInsertable: boolean;\n /** True for processors with no mono implementation (stereo-only). */\n stereoOnly: boolean;\n /**\n * Reported latency for the default 48 kHz / 512-sample probe configuration.\n * Zero for offline processors; configuration-dependent values are estimates.\n */\n latencySamples: number;\n /**\n * Audible decay length for the same default prepared probe. Zero for\n * offline, dry-only, and no-tail processors.\n */\n tailSamples: number;\n /** Coarse realtime work estimate, or null when the processor is not an insert. */\n realtimeCost: MasteringRealtimeCost | null;\n /**\n * How the mixer wraps the processor on a >2-channel (surround) bus insert:\n * \"multichannel\" (one full-buffer call) or \"stereoPairOnly\" (front L/R pair,\n * surround planes passed through dry).\n */\n channelPolicy: MasteringChannelPolicy;\n /** Grouping for a processor picker; see {@link MasteringProcessorCategory}. */\n category: MasteringProcessorCategory;\n /**\n * The processor's construction parameters, the same list\n * {@link masteringInsertParamInfo} returns. Empty for entries that are not\n * realtime-insertable.\n */\n params: MasteringInsertParamInfo[];\n /**\n * The insert's conditional key groups in declaration order, named by each\n * parameter's `slot`. Empty for entries that are not realtime-insertable.\n */\n slots: MasteringInsertSlot[];\n}\n\n/**\n * Returns the machine-readable classification catalog for every named processor\n * id, merging the offline registry, the realtime insert factory, and the pair\n * registry. Lets a host filter a processor picker by realtime insertability\n * instead of offering ids the realtime strip would reject.\n */\nexport function masteringProcessorCatalog(): MasteringProcessorCatalogEntry[] {\n const json = requireModule().masteringProcessorCatalog();\n return JSON.parse(json) as MasteringProcessorCatalogEntry[];\n}\n\nexport function masteringPairProcessorNames(): PairProcessor[] {\n return Array.from(requireModule().masteringPairProcessorNames()) as PairProcessor[];\n}\n\nexport function masteringPairAnalysisNames(): PairAnalysis[] {\n return Array.from(requireModule().masteringPairAnalysisNames()) as PairAnalysis[];\n}\n\nexport function masteringStereoAnalysisNames(): StereoAnalysis[] {\n return Array.from(requireModule().masteringStereoAnalysisNames()) as StereoAnalysis[];\n}\n\nexport function masteringProcess(request: MasteringProcessRequest): MasteringResult;\nexport function masteringProcess(\n processorName: SoloProcessor,\n samples: Float32Array,\n sampleRate?: number,\n params?: MasteringProcessorParams,\n): MasteringResult;\nexport function masteringProcess(\n processorName: SoloProcessor | MasteringProcessRequest,\n samples?: Float32Array,\n sampleRate = 22050,\n params: MasteringProcessorParams = {},\n): MasteringResult {\n const request =\n typeof processorName === 'string'\n ? { processorName, samples: samples as Float32Array, sampleRate, params }\n : processorName;\n return requireModule().masteringProcess(\n request.processorName,\n request.samples,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\nexport function masteringProcessStereo(\n request: MasteringProcessStereoRequest,\n): MasteringStereoResult;\nexport function masteringProcessStereo(\n processorName: SoloProcessor,\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n params?: MasteringProcessorParams,\n): MasteringStereoResult;\nexport function masteringProcessStereo(\n processorName: SoloProcessor | MasteringProcessStereoRequest,\n left?: Float32Array,\n right?: Float32Array,\n sampleRate = 22050,\n params: MasteringProcessorParams = {},\n): MasteringStereoResult {\n const request =\n typeof processorName === 'string'\n ? {\n processorName,\n left: left as Float32Array,\n right: right as Float32Array,\n sampleRate,\n params,\n }\n : processorName;\n if (request.left.length !== request.right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n return requireModule().masteringProcessStereo(\n request.processorName,\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\n/**\n * Apply a two-input `match.*` processor. `source` and `reference` may have\n * independent lengths — the match primitives consume each buffer at its own\n * length.\n */\nexport function masteringPairProcess(request: MasteringPairProcessRequest): MasteringResult;\nexport function masteringPairProcess(\n processorName: PairProcessor,\n source: Float32Array,\n reference: Float32Array,\n sampleRate?: number,\n params?: MasteringProcessorParams,\n): MasteringResult;\nexport function masteringPairProcess(\n processorName: PairProcessor | MasteringPairProcessRequest,\n source?: Float32Array,\n reference?: Float32Array,\n sampleRate = 22050,\n params: MasteringProcessorParams = {},\n): MasteringResult {\n const request =\n typeof processorName === 'string'\n ? {\n processorName,\n source: source as Float32Array,\n reference: reference as Float32Array,\n sampleRate,\n params,\n }\n : processorName;\n return requireModule().masteringPairProcess(\n request.processorName,\n request.source,\n request.reference,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\n/**\n * Analyze a `source` against a `reference` with a two-input analysis. The two\n * buffers may have independent lengths.\n */\nexport function masteringPairAnalyze(request: MasteringPairAnalyzeRequest): string;\nexport function masteringPairAnalyze(\n analysisName: PairAnalysis,\n source: Float32Array,\n reference: Float32Array,\n sampleRate?: number,\n params?: MasteringProcessorParams,\n): string;\nexport function masteringPairAnalyze(\n analysisName: PairAnalysis | MasteringPairAnalyzeRequest,\n source?: Float32Array,\n reference?: Float32Array,\n sampleRate = 22050,\n params: MasteringProcessorParams = {},\n): string {\n const request =\n typeof analysisName === 'string'\n ? {\n analysisName,\n source: source as Float32Array,\n reference: reference as Float32Array,\n sampleRate,\n params,\n }\n : analysisName;\n return requireModule().masteringPairAnalyze(\n request.analysisName,\n request.source,\n request.reference,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\n/**\n * Gain-match `source` to `reference`'s integrated loudness, so an A/B between\n * the two is not decided by level. `source` and `reference` may have\n * independent lengths.\n *\n * The gain is applied with no upper bound and `matchedTruePeakDbtp` reports\n * where that left the peak, rather than the call capping it: a headroom clamp\n * would return `source` at its own loudness whenever it started near full\n * scale. Both loudness values are non-finite for a silent or below-gate take,\n * and `appliedGainDb` is then 0.\n *\n * @example\n * ```ts\n * const { samples, appliedGainDb, matchedTruePeakDbtp } = masteringAbMatchLoudness({\n * source: take,\n * reference: master,\n * sampleRate: 48000,\n * });\n * ```\n */\nexport function masteringAbMatchLoudness(\n request: MasteringAbMatchLoudnessRequest,\n): LoudnessMatchResult {\n return requireModule().masteringAbMatchLoudness(\n request.source,\n request.reference,\n request.sampleRate ?? 22050,\n );\n}\n\nexport function masteringStereoAnalyze(request: MasteringStereoAnalyzeRequest): string;\nexport function masteringStereoAnalyze(\n analysisName: StereoAnalysis,\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n params?: MasteringProcessorParams,\n): string;\nexport function masteringStereoAnalyze(\n analysisName: StereoAnalysis | MasteringStereoAnalyzeRequest,\n left?: Float32Array,\n right?: Float32Array,\n sampleRate = 22050,\n params: MasteringProcessorParams = {},\n): string {\n const request =\n typeof analysisName === 'string'\n ? {\n analysisName,\n left: left as Float32Array,\n right: right as Float32Array,\n sampleRate,\n params,\n }\n : analysisName;\n return requireModule().masteringStereoAnalyze(\n request.analysisName,\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\nexport function masteringAssistantSuggest(request: MasteringAssistantParamsRequest): string;\nexport function masteringAssistantSuggest(\n samples: Float32Array,\n sampleRate?: number,\n params?: MasteringAssistantParams,\n): string;\nexport function masteringAssistantSuggest(\n samples: Float32Array | MasteringAssistantParamsRequest,\n sampleRate = 22050,\n params: MasteringAssistantParams = {},\n): string {\n const request = samples instanceof Float32Array ? { samples, sampleRate, params } : samples;\n return requireModule().masteringAssistantSuggest(\n request.samples,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\n/**\n * Suggest a mastering chain, as the flat `{key: number|boolean}` params map\n * {@link masteringAssistantSuggest}'s `chainConfig` carries, without needing to\n * pull it out of the full assistant document. The returned map can be passed\n * straight through as `overrides` to {@link mastering} / {@link masterAudio}.\n */\nexport function masteringAssistantSuggestChain(\n request: MasteringAssistantParamsRequest,\n): Record<string, number | boolean> {\n return requireModule().masteringAssistantSuggestChain(\n request.samples,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\n/**\n * The shape {@link masteringAudioProfile}'s JSON parses to.\n *\n * The profile crosses as a string, so nothing type-checks it on arrival; this\n * declaration is what a conformance check compares against the paths the C++\n * writer publishes, so a field added on one side and not the other fails there\n * rather than reaching a caller as `undefined`.\n */\nexport interface MasteringAudioProfile {\n durationSec: number;\n bpm: number;\n bpmConfidence: number;\n loudness: {\n integratedLufs: number;\n lraLu: number;\n truePeakDb: number;\n crestFactorDb: number;\n };\n spectral: {\n subRmsDb: number;\n lowRmsDb: number;\n lowMidRmsDb: number;\n midRmsDb: number;\n highMidRmsDb: number;\n highRmsDb: number;\n airRmsDb: number;\n centroidHz: number;\n flatness: number;\n rolloffHz: number;\n };\n dynamics: {\n shortTermLufsStd: number;\n attackDensity: number;\n sustainRatio: number;\n };\n /**\n * What the repair detectors measured. `measured` is false when nothing ran —\n * either `detectDefects` was not asked for or the input was too short — and\n * every other field is then at its default rather than a reading.\n */\n defects: {\n measured: boolean;\n clickCount: number;\n clickRejected: number;\n clickLongestRunSamples: number;\n clickPerSecond: number;\n crackleSampleCount: number;\n crackleSampleFraction: number;\n cracklePerSecond: number;\n clipSampleCount: number;\n clipRunCount: number;\n clipLongestRunSamples: number;\n clipSampleFraction: number;\n clipFlatRunCount: number;\n clipFlatSampleCount: number;\n clipLongestFlatRunSamples: number;\n clipFlatLevel: number;\n noiseFloorDbfs: number;\n noiseBandPeakDbfs: number;\n noiseBandPeakIndex: number;\n humFundamentalHz: number;\n humFundamentalProminence: number;\n humHarmonics: number;\n humFundamentalDbfs: number;\n humPeakHarmonicDbfs: number;\n lateDecayRatioDb: number;\n };\n}\n\nexport function masteringAudioProfile(request: MasteringSamplesParamsRequest): string;\nexport function masteringAudioProfile(\n samples: Float32Array,\n sampleRate?: number,\n params?: MasteringProcessorParams,\n): string;\nexport function masteringAudioProfile(\n samples: Float32Array | MasteringSamplesParamsRequest,\n sampleRate = 22050,\n params: MasteringProcessorParams = {},\n): string {\n const request = samples instanceof Float32Array ? { samples, sampleRate, params } : samples;\n return requireModule().masteringAudioProfile(\n request.samples,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\nexport function masteringStreamingPreview(request: MasteringStreamingPreviewRequest): string;\nexport function masteringStreamingPreview(\n samples: Float32Array,\n sampleRate?: number,\n platforms?: StreamingPlatform[],\n): string;\nexport function masteringStreamingPreview(\n samples: Float32Array | MasteringStreamingPreviewRequest,\n sampleRate = 22050,\n platforms: StreamingPlatform[] = [],\n): string {\n const request = samples instanceof Float32Array ? { samples, sampleRate, platforms } : samples;\n return requireModule().masteringStreamingPreview(\n request.samples,\n request.sampleRate ?? 22050,\n request.platforms ?? [],\n );\n}\n\n/**\n * Suggest a mastering chain for a stereo pair, as shared JSON.\n *\n * Profiles through {@link masteringAudioProfileStereo}, so the loudness stage\n * of the suggestion is built on the channel-summed program rather than a\n * downmix that reads roughly 6 dB low.\n */\nexport function masteringAssistantSuggestStereo(\n request: MasteringAssistantStereoParamsRequest,\n): string {\n return requireModule().masteringAssistantSuggestStereo(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\n/**\n * Stereo counterpart of {@link masteringAssistantSuggestChain}: the flat\n * `{key: number|boolean}` params map without the surrounding assistant\n * document, ready to pass through as `overrides` to {@link masterAudioStereo}.\n */\nexport function masteringAssistantSuggestChainStereo(\n request: MasteringAssistantStereoParamsRequest,\n): Record<string, number | boolean> {\n return requireModule().masteringAssistantSuggestChainStereo(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\n/**\n * Mastering assistant profile of a stereo pair, as shared JSON.\n *\n * Only the `loudness` block is measured from the two channels: integrated LUFS\n * and LRA come from the channel-summed program and the true peak is the larger\n * of the two. The spectral, dynamics and tempo fields describe shape and timing\n * rather than absolute level and are measured on the downmix, which keeps them\n * comparable with {@link masteringAudioProfile}.\n */\nexport function masteringAudioProfileStereo(request: MasteringStereoParamsRequest): string {\n return requireModule().masteringAudioProfileStereo(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.params ?? {},\n );\n}\n\n/**\n * Preview streaming-platform normalization for a stereo pair, as shared JSON.\n *\n * Measures the integrated loudness with BS.1770 channel summing and reports the\n * larger of the two channel true peaks. Passing a `0.5 * (left + right)` downmix\n * to {@link masteringStreamingPreview} instead reads roughly 6 dB low on\n * decorrelated material, and both the normalization gain and the ceiling-risk\n * flag follow from that measurement.\n */\nexport function masteringStreamingPreviewStereo(\n request: MasteringStreamingPreviewStereoRequest,\n): string {\n return requireModule().masteringStreamingPreviewStereo(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.platforms ?? [],\n );\n}\n","import { getSonareModule } from './module_state';\nimport type { ValidateOptions } from './validation';\nimport { assertSamples } from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n// ============================================================================\n// Mastering — offline dynamics processors (compressor / gate / transient_shaper)\n// ============================================================================\n\n/** Compressor sidechain detector mode. */\nexport type CompressorDetector = 'peak' | 'rms' | 'log_rms';\n\n/** Options for `masteringDynamicsCompressor`. */\nexport interface CompressorOptions extends ValidateOptions {\n thresholdDb?: number;\n ratio?: number;\n attackMs?: number;\n releaseMs?: number;\n kneeDb?: number;\n makeupGainDb?: number;\n autoMakeup?: boolean;\n detector?: CompressorDetector | number;\n sidechainHpfEnabled?: boolean;\n sidechainHpfHz?: number;\n pdrTimeMs?: number;\n pdrReleaseScale?: number;\n}\n\n/** Canonical request form for the offline compressor. */\nexport interface MasteringDynamicsCompressorRequest extends CompressorOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Options for `masteringDynamicsGate`. */\nexport interface GateOptions extends ValidateOptions {\n thresholdDb?: number;\n attackMs?: number;\n releaseMs?: number;\n rangeDb?: number;\n holdMs?: number;\n closeThresholdDb?: number;\n keyHpfHz?: number;\n}\n\n/** Canonical request form for the offline gate. */\nexport interface MasteringDynamicsGateRequest extends GateOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Options for `masteringDynamicsTransientShaper`. */\nexport interface TransientShaperOptions extends ValidateOptions {\n attackGainDb?: number;\n sustainGainDb?: number;\n fastAttackMs?: number;\n fastReleaseMs?: number;\n slowAttackMs?: number;\n slowReleaseMs?: number;\n sensitivity?: number;\n maxGainDb?: number;\n gainSmoothingMs?: number;\n lookaheadMs?: number;\n}\n\n/** Canonical request form for the offline transient shaper. */\nexport interface MasteringDynamicsTransientShaperRequest extends TransientShaperOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/**\n * Result envelope returned by offline mastering dynamics processors.\n *\n * Named for what it is rather than for the module it lives in. {@link\n * DynamicsResult} is the *analysis* shape on every binding, so having that one\n * identifier mean two disjoint field lists across the Node and WASM packages\n * made a shared TypeScript module type-check against one and fail against the\n * other — with the identifier resolving either way, so only the member list\n * gave it away.\n */\nexport interface DynamicsProcessorResult {\n samples: Float32Array;\n latencySamples: number;\n}\n\nconst COMPRESSOR_DETECTOR_MAP: Record<CompressorDetector, number> = {\n peak: 0,\n rms: 1,\n log_rms: 2,\n};\n\n/** Offline feed-forward compressor (soft knee, optional auto-makeup / sidechain HPF). */\nexport function masteringDynamicsCompressor(\n request: MasteringDynamicsCompressorRequest,\n): DynamicsProcessorResult;\nexport function masteringDynamicsCompressor(\n samples: Float32Array,\n sampleRate: number,\n options?: CompressorOptions,\n): DynamicsProcessorResult;\nexport function masteringDynamicsCompressor(\n samples: Float32Array | MasteringDynamicsCompressorRequest,\n sampleRate?: number,\n options: CompressorOptions = {},\n): DynamicsProcessorResult {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n assertSamples('masteringDynamicsCompressor', request.samples, request.validate !== false);\n const detector =\n typeof request.detector === 'string'\n ? COMPRESSOR_DETECTOR_MAP[request.detector]\n : request.detector;\n // Preserve inherited option values as well as own properties. The embind\n // boundary's hasProperty() intentionally follows the prototype chain, so a\n // spread copy here would otherwise erase values before C++ can read them.\n const opts: Record<string, unknown> = Object.assign(\n Object.create(Object.getPrototypeOf(request)) as Record<string, unknown>,\n request,\n );\n if (detector !== undefined) {\n opts.detector = detector;\n }\n return requireModule().masteringDynamicsCompressor(request.samples, request.sampleRate, opts);\n}\n\n/** Offline noise gate (hysteresis, hold, optional key HPF). */\nexport function masteringDynamicsGate(\n request: MasteringDynamicsGateRequest,\n): DynamicsProcessorResult;\nexport function masteringDynamicsGate(\n samples: Float32Array,\n sampleRate: number,\n options?: GateOptions,\n): DynamicsProcessorResult;\nexport function masteringDynamicsGate(\n samples: Float32Array | MasteringDynamicsGateRequest,\n sampleRate?: number,\n options: GateOptions = {},\n): DynamicsProcessorResult {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n assertSamples('masteringDynamicsGate', request.samples, request.validate !== false);\n return requireModule().masteringDynamicsGate(request.samples, request.sampleRate, request);\n}\n\n/** Offline transient shaper (envelope-difference attack/sustain control). */\nexport function masteringDynamicsTransientShaper(\n request: MasteringDynamicsTransientShaperRequest,\n): DynamicsProcessorResult;\nexport function masteringDynamicsTransientShaper(\n samples: Float32Array,\n sampleRate: number,\n options?: TransientShaperOptions,\n): DynamicsProcessorResult;\nexport function masteringDynamicsTransientShaper(\n samples: Float32Array | MasteringDynamicsTransientShaperRequest,\n sampleRate?: number,\n options: TransientShaperOptions = {},\n): DynamicsProcessorResult {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n assertSamples('masteringDynamicsTransientShaper', request.samples, request.validate !== false);\n return requireModule().masteringDynamicsTransientShaper(\n request.samples,\n request.sampleRate,\n request,\n );\n}\n","import { getSonareModule } from './module_state';\nimport type { MixOptions, MixResult } from './public_types';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\nexport function mixingScenePresetNames(): string[] {\n return Array.from(requireModule().mixingScenePresetNames());\n}\n\n/**\n * Get a built-in mixing scene preset serialized as JSON. This is the canonical\n * name shared with the Node and Python bindings; the returned JSON loads\n * directly into a {@link Mixer} via {@link Mixer.fromSceneJson}.\n *\n * @param presetName - Preset name (see {@link mixingScenePresetNames})\n * @returns Scene JSON string\n */\nexport function mixingScenePresetJson(presetName: string): string {\n return requireModule().mixingScenePresetJson(presetName);\n}\n\n/** Inputs for the one-shot {@link mixStereo} facade. */\nexport interface MixStereoRequest extends MixOptions {\n leftChannels: Float32Array[];\n rightChannels: Float32Array[];\n sampleRate?: number;\n}\n\n/**\n * One-shot stereo mix of multiple strips through the routing graph + master bus.\n *\n * Each returned per-strip meter reflects only this single one-shot block. The\n * LUFS fields (`momentaryLufs`, `shortTermLufs`, `integratedLufs`) are\n * integrators whose windows that block does not fill, so they read the -120 dB\n * floor sentinel; drive a streaming {@link Mixer} block-by-block if you need\n * meaningful loudness.\n *\n * The true-peak fields are not integrators and need no streaming: each is a\n * max-hold over the block just processed and is valid from the first one,\n * flooring only on silence. This facade mixes the whole input as a single block,\n * which is the whole-signal case, so the block-edge under-read documented on\n * `MixMeterSnapshot.truePeakDbL` does not apply to the reading here.\n *\n * @param leftChannels - Per-strip left input buffers (all the same length)\n * @param rightChannels - Per-strip right input buffers (all the same length)\n * @param sampleRate - Sample rate in Hz\n * @param options - Per-strip mix options (trim, fader, pan, width, mute)\n */\nexport function mixStereo(request: MixStereoRequest): MixResult;\nexport function mixStereo(\n leftChannels: Float32Array[],\n rightChannels: Float32Array[],\n sampleRate?: number,\n options?: MixOptions,\n): MixResult;\nexport function mixStereo(\n leftChannels: Float32Array[] | MixStereoRequest,\n rightChannels?: Float32Array[],\n sampleRate = 48000,\n options: MixOptions = {},\n): MixResult {\n const request = Array.isArray(leftChannels)\n ? { leftChannels, rightChannels: rightChannels ?? [], sampleRate, ...options }\n : leftChannels;\n if (\n request.leftChannels.length === 0 ||\n request.leftChannels.length !== request.rightChannels.length\n ) {\n throw new Error('leftChannels and rightChannels must have the same non-zero length.');\n }\n return requireModule().mixStereo(\n request.leftChannels,\n request.rightChannels,\n request.sampleRate ?? 48000,\n request as unknown as Record<string, unknown>,\n );\n}\n","/**\n * Reverberation repair, with its detector and the room-driven configuration.\n */\n\nimport { getSonareModule } from './module_state';\nimport type { RoomEstimateResult } from './public_types_acoustic';\nimport type {\n MasteringRepairDereverbClassicalLinkedResult,\n MasteringRepairDereverbClassicalStereoResult,\n ReverbDetection,\n} from './public_types_repair';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n/** Options for `masteringRepairDereverbClassical`. */\nexport interface DereverbClassicalOptions {\n threshold?: number;\n attenuation?: number;\n nFft?: number;\n hopLength?: number;\n t60Sec?: number;\n lateDelayMs?: number;\n overSubtraction?: number;\n spectralFloor?: number;\n wpeEnabled?: boolean;\n wpeIterations?: number;\n wpeTaps?: number;\n wpeStrength?: number;\n}\n\nexport interface MasteringRepairDereverbClassicalRequest extends DereverbClassicalOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Request form of `masteringRepairDereverbClassicalStereo`. */\nexport interface MasteringRepairDereverbClassicalStereoRequest extends DereverbClassicalOptions {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n}\n\n/** Request form of `masteringRepairDereverbClassicalLinked`. */\nexport interface MasteringRepairDereverbClassicalLinkedRequest extends DereverbClassicalOptions {\n /** At least one channel; all the same length. */\n channels: Float32Array[];\n sampleRate?: number;\n}\n\n/** Request form of `masteringRepairDereverbConfigForRoom`. */\nexport interface MasteringRepairDereverbConfigForRoomRequest extends DereverbClassicalOptions {\n /** The measured room, from `estimateRoom`. Only `volume` and `rt60Bands` are read. */\n estimate: RoomEstimateResult;\n}\n\n/** Offline classical dereverberator (spectral subtraction + optional WPE). */\nexport function masteringRepairDereverbClassical(\n request: MasteringRepairDereverbClassicalRequest,\n): Float32Array;\nexport function masteringRepairDereverbClassical(\n samples: Float32Array,\n sampleRate: number,\n options?: DereverbClassicalOptions,\n): Float32Array;\nexport function masteringRepairDereverbClassical(\n samples: Float32Array | MasteringRepairDereverbClassicalRequest,\n sampleRate?: number,\n options: DereverbClassicalOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDereverbClassical(\n request.samples,\n request.sampleRate,\n request,\n );\n}\n\n/**\n * Offline classical dereverberator for a stereo pair (spectral subtraction plus an optional\n * WPE pre-stage), driven by one channel-linked mask.\n *\n * The mask is built from the channel-summed power, and the WPE stage accumulates over both\n * channels and applies one predictor set to each, so neither stage can move an interchannel\n * level or phase difference. That is also why the result carries a single `report` rather than\n * one per channel.\n *\n * Every field of that report is a ratio or a fraction, so unlike the denoise pair nothing in\n * it shifts with the channel count: a stereo figure here is comparable against a mono one.\n *\n * An input shorter than `nFft` is PADDED for analysis rather than rejected, the opposite of\n * {@link masteringRepairDenoiseClassicalStereo}.\n *\n * Two report fields are gated on the WPE stage, which is off unless `wpeEnabled` is set:\n * `detected.latePredictability` and `wpePredictorNorm` are then both exactly 0, which is the\n * measurement rather than an unset field. `detected.lateDecayRatioDb` runs the other way from\n * what its name suggests — less negative means the material sustains across the module's late\n * lag, so a reverberant input reads *higher* than the same material dry.\n *\n * `threshold` and `attenuation` are both validated to `[0, 1]`, so the strongest gate this\n * accepts is `threshold: 0.99`, not an arbitrarily large number.\n *\n * @example\n * ```ts\n * const { left, right, report } = masteringRepairDereverbClassicalStereo({\n * left: leftSamples,\n * right: rightSamples,\n * sampleRate: 48000,\n * wpeEnabled: true,\n * });\n * console.log(report.detected.lateDecayRatioDb, report.wpePredictorNorm);\n * ```\n */\nexport function masteringRepairDereverbClassicalStereo(\n request: MasteringRepairDereverbClassicalStereoRequest,\n): MasteringRepairDereverbClassicalStereoResult;\nexport function masteringRepairDereverbClassicalStereo(\n left: Float32Array,\n right: Float32Array,\n sampleRate: number,\n config?: DereverbClassicalOptions,\n): MasteringRepairDereverbClassicalStereoResult;\nexport function masteringRepairDereverbClassicalStereo(\n left: Float32Array | MasteringRepairDereverbClassicalStereoRequest,\n right?: Float32Array,\n sampleRate?: number,\n config: DereverbClassicalOptions = {},\n): MasteringRepairDereverbClassicalStereoResult {\n const request: MasteringRepairDereverbClassicalStereoRequest =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...config }\n : left;\n const { left: leftSamples, right: rightSamples, sampleRate: rate, ...options } = request;\n return requireModule().masteringRepairDereverbClassicalStereo(\n leftSamples,\n rightSamples,\n rate ?? 22050,\n options,\n );\n}\n\n/**\n * Offline classical dereverberator for any number of channels (spectral subtraction plus an\n * optional WPE pre-stage), driven by one channel-linked mask.\n *\n * The N-channel form of {@link masteringRepairDereverbClassicalStereo}: the mask is built from\n * the channel-summed power and the WPE stage accumulates over every channel and applies one\n * predictor set to each, so neither stage can move an interchannel level or phase difference\n * however many channels there are. One `report` for the set, and one output per input channel in\n * input order.\n *\n * A single channel reproduces {@link masteringRepairDereverbClassical} bit for bit, and two\n * reproduce {@link masteringRepairDereverbClassicalStereo} plane for plane — `channels[0]` is the\n * left plane and `channels[1]` the right.\n *\n * Every field of the report is a ratio or a fraction, so nothing in it shifts with the channel\n * count: a figure measured over a set is comparable against a mono one. That is the opposite of\n * {@link masteringRepairDenoiseClassicalLinked}, whose `detected` levels are absolute and move by\n * `10*log10(N)`.\n *\n * An input shorter than `nFft` is PADDED for analysis rather than rejected — again the opposite\n * of that entry, which refuses one.\n *\n * Two report fields are gated on the WPE stage, which is off unless `wpeEnabled` is set:\n * `detected.latePredictability` and `wpePredictorNorm` are then both exactly 0, which is the\n * measurement rather than an unset field.\n *\n * @example\n * ```ts\n * const { channels, report } = masteringRepairDereverbClassicalLinked({\n * channels: [frontLeft, frontRight, centre],\n * sampleRate: 48000,\n * wpeEnabled: true,\n * });\n * console.log(channels.length, report.detected.lateDecayRatioDb);\n * ```\n */\nexport function masteringRepairDereverbClassicalLinked(\n request: MasteringRepairDereverbClassicalLinkedRequest,\n): MasteringRepairDereverbClassicalLinkedResult;\nexport function masteringRepairDereverbClassicalLinked(\n channels: Float32Array[],\n sampleRate: number,\n config?: DereverbClassicalOptions,\n): MasteringRepairDereverbClassicalLinkedResult;\nexport function masteringRepairDereverbClassicalLinked(\n channels: Float32Array[] | MasteringRepairDereverbClassicalLinkedRequest,\n sampleRate?: number,\n config: DereverbClassicalOptions = {},\n): MasteringRepairDereverbClassicalLinkedResult {\n const request: MasteringRepairDereverbClassicalLinkedRequest = Array.isArray(channels)\n ? { channels, sampleRate, ...config }\n : channels;\n const { channels: input, sampleRate: rate, ...options } = request;\n return requireModule().masteringRepairDereverbClassicalLinked(input, rate ?? 22050, options);\n}\n\n/**\n * Point a dereverb config at a measured room.\n *\n * The pair to {@link estimateRoom}, which measures a recording blind. Returns a complete\n * config for {@link masteringRepairDereverbClassical}, so the caller does not have to know\n * which reverberation-time band to use or how the late delay relates to room size.\n *\n * What the room decides is *where* the tail is. Exactly two fields come back changed from\n * what was passed in:\n *\n * - `t60Sec` — the mid-frequency reverberation time, the average of the 500 Hz and 1 kHz\n * octaves an ISO 3382 room is quoted by.\n * - `lateDelayMs` — Polack's mixing time, sqrt(volume) in milliseconds, past which the\n * response is a diffuse tail rather than separable early reflections.\n *\n * How *much* to remove is taste rather than measurement, so `attenuation`, `threshold`,\n * `overSubtraction` and `spectralFloor` are never written. A measurement that did not\n * converge leaves its own field alone, so a partial estimate still configures the half it\n * measured; a low-`confidence` estimate is still applied, because whether to trust it is\n * the caller's call.\n *\n * Every field of `config` that is omitted falls back to the library's own dereverb default,\n * matching {@link masteringRepairDereverbClassical}, so calling this with only an estimate\n * returns a config that is ready to run. The C ABI underneath reads and writes the whole\n * config and takes every field literally — it has no \"zero means default\" rule — which is\n * why an omitted field resolves to its default here rather than to zero.\n *\n * @param estimate - The measured room, from {@link estimateRoom}. Only `volume` and\n * `rt60Bands` are read. The request form carries it as `estimate` alongside the config\n * fields.\n * @param config - The config to point at the room; omitted fields take the library default.\n * @returns A complete dereverb config.\n *\n * @example\n * ```ts\n * const estimate = estimateRoom(samples, sampleRate);\n * const config = masteringRepairDereverbConfigForRoom(estimate);\n * const clean = masteringRepairDereverbClassical(samples, sampleRate, config);\n * ```\n *\n * When NEITHER mid band converged, `t60Sec` falls back to the average of whatever\n * bands did, so a low-band-only estimate configures something rather than nothing --\n * that value is no longer a mid-frequency figure. Only `volume`, `rt60Bands` and the\n * band count are read; the rest of the estimate is ignored.\n */\nexport function masteringRepairDereverbConfigForRoom(\n request: MasteringRepairDereverbConfigForRoomRequest,\n): Required<DereverbClassicalOptions>;\nexport function masteringRepairDereverbConfigForRoom(\n estimate: RoomEstimateResult,\n config?: DereverbClassicalOptions,\n): Required<DereverbClassicalOptions>;\nexport function masteringRepairDereverbConfigForRoom(\n estimate: RoomEstimateResult | MasteringRepairDereverbConfigForRoomRequest,\n config: DereverbClassicalOptions = {},\n): Required<DereverbClassicalOptions> {\n const request = 'estimate' in estimate ? estimate : { estimate, ...config };\n return requireModule().masteringRepairDereverbConfigForRoom(request.estimate, request);\n}\n\n/** Request form of `masteringRepairDetectReverb`. */\nexport interface MasteringRepairDetectReverbRequest extends DereverbClassicalOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/**\n * Measures reverberation without dereverberating.\n *\n * NOT an ISO 3382 reverberation time — use `estimateRoom` for a graded RT60. This reports what\n * {@link masteringRepairDereverbClassical} itself measures while deciding how much to subtract.\n *\n * A buffer shorter than `nFft` is PADDED for analysis, as the repair pads it, which is the\n * opposite of {@link masteringRepairDetectNoiseFloor}.\n *\n * `latePredictability` comes from the WPE stage, which runs only under `wpeEnabled` — clear by\n * default — and then only its covariance and solve; the prediction is never subtracted. A\n * default-config call therefore reports exactly 0 there as its measurement.\n */\nexport function masteringRepairDetectReverb(\n request: MasteringRepairDetectReverbRequest,\n): ReverbDetection;\nexport function masteringRepairDetectReverb(\n samples: Float32Array,\n sampleRate: number,\n options?: DereverbClassicalOptions,\n): ReverbDetection;\nexport function masteringRepairDetectReverb(\n samples: Float32Array | MasteringRepairDetectReverbRequest,\n sampleRate?: number,\n options: DereverbClassicalOptions = {},\n): ReverbDetection {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDetectReverb(request.samples, request.sampleRate, request);\n}\n","/**\n * Impulsive-defect repair: declick, declip and decrackle, with their detectors.\n */\n\nimport { getSonareModule } from './module_state';\nimport type {\n ClickDetection,\n ClipDetection,\n CrackleDetection,\n MasteringRepairDeclickStereoResult,\n MasteringRepairDeclipStereoResult,\n MasteringRepairDecrackleStereoResult,\n} from './public_types_repair';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n/** Options for `masteringRepairDeclick`. */\nexport interface DeclickOptions {\n threshold?: number;\n neighborRatio?: number;\n maxClickSamples?: number;\n lpcOrder?: number;\n residualRatio?: number;\n}\n\nexport interface MasteringRepairDeclickRequest extends DeclickOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Request form of `masteringRepairDeclickStereo`. */\nexport interface MasteringRepairDeclickStereoRequest extends DeclickOptions {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n}\n\n/**\n * Offline LPC-based declicker for a stereo pair.\n *\n * A run either channel's own detection selects is repaired in BOTH channels —\n * a common-mode click repaired on one side only would move the stereo image.\n * Only the selection is shared: each channel's fill is computed from its own\n * samples and its own AR model, which is why `leftReport` and `rightReport`\n * genuinely differ. Prefer this over calling `masteringRepairDeclick` on each\n * channel separately whenever a click may land in only one channel — a\n * per-channel pass never repairs the other side's image-shifting click.\n */\nexport function masteringRepairDeclickStereo(\n request: MasteringRepairDeclickStereoRequest,\n): MasteringRepairDeclickStereoResult;\nexport function masteringRepairDeclickStereo(\n left: Float32Array,\n right: Float32Array,\n sampleRate: number,\n config?: DeclickOptions,\n): MasteringRepairDeclickStereoResult;\nexport function masteringRepairDeclickStereo(\n left: Float32Array | MasteringRepairDeclickStereoRequest,\n right?: Float32Array,\n sampleRate?: number,\n config: DeclickOptions = {},\n): MasteringRepairDeclickStereoResult {\n const request: MasteringRepairDeclickStereoRequest =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...config }\n : left;\n const { left: leftSamples, right: rightSamples, sampleRate: rate, ...options } = request;\n return requireModule().masteringRepairDeclickStereo(\n leftSamples,\n rightSamples,\n rate ?? 22050,\n options,\n );\n}\n\n/** Offline LPC-based declicker. */\nexport function masteringRepairDeclick(request: MasteringRepairDeclickRequest): Float32Array;\nexport function masteringRepairDeclick(\n samples: Float32Array,\n sampleRate: number,\n options?: DeclickOptions,\n): Float32Array;\nexport function masteringRepairDeclick(\n samples: Float32Array | MasteringRepairDeclickRequest,\n sampleRate?: number,\n options: DeclickOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDeclick(request.samples, request.sampleRate, request);\n}\n\n/** Options for `masteringRepairDeclip`. */\nexport interface DeclipOptions {\n clipThreshold?: number;\n lpcOrder?: number;\n iterations?: number;\n lpcBlend?: number;\n}\n\nexport interface MasteringRepairDeclipRequest extends DeclipOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Request form of `masteringRepairDeclipStereo`. */\nexport interface MasteringRepairDeclipStereoRequest extends DeclipOptions {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n}\n\n/** Algorithms accepted by `masteringRepairDecrackle`. */\nexport type DecrackleMode = 'median' | 'waveletShrinkage';\n\n/** Options for `masteringRepairDecrackle`. */\nexport interface DecrackleOptions {\n threshold?: number;\n mode?: DecrackleMode;\n levels?: number;\n}\n\nexport interface MasteringRepairDecrackleRequest extends DecrackleOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Request form of `masteringRepairDecrackleStereo`. */\nexport interface MasteringRepairDecrackleStereoRequest extends DecrackleOptions {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n}\n\n/**\n * Offline LPC-based declipper.\n *\n * Only clipped runs of at most 512 consecutive samples are reconstructed with the LPC solver.\n * The cap is a fixed sample count: it is not derived from `lpcOrder`, from `sampleRate`, or from\n * any other option, so its duration depends on the rate (~10.7 ms at 48 kHz). A longer run is\n * filled with cubic / linear interpolation instead, which keeps the solver's dense matrices\n * bounded by the cap rather than by the input. Exceeding the cap silently changes the\n * reconstruction method rather than throwing: `lpcOrder`, `iterations` and `lpcBlend` have no\n * effect on the interpolated run.\n */\nexport function masteringRepairDeclip(request: MasteringRepairDeclipRequest): Float32Array;\nexport function masteringRepairDeclip(\n samples: Float32Array,\n sampleRate: number,\n options?: DeclipOptions,\n): Float32Array;\nexport function masteringRepairDeclip(\n samples: Float32Array | MasteringRepairDeclipRequest,\n sampleRate?: number,\n options: DeclipOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDeclip(request.samples, request.sampleRate, request);\n}\n\n/**\n * Offline LPC-based declipper for a stereo pair.\n *\n * Takes the union of both channels' clipped runs. Each channel reconstructs\n * the whole of every union run it has at least one clipped sample in; a\n * channel with none is left untouched there — reconstructing unclipped audio\n * to match the other side would replace real samples with an estimate. A\n * plateau clipped in only one channel therefore produces no linking:\n * `linkedRuns` is non-zero only where both channels are clipped in the same\n * region with different extents.\n */\nexport function masteringRepairDeclipStereo(\n request: MasteringRepairDeclipStereoRequest,\n): MasteringRepairDeclipStereoResult;\nexport function masteringRepairDeclipStereo(\n left: Float32Array,\n right: Float32Array,\n sampleRate: number,\n config?: DeclipOptions,\n): MasteringRepairDeclipStereoResult;\nexport function masteringRepairDeclipStereo(\n left: Float32Array | MasteringRepairDeclipStereoRequest,\n right?: Float32Array,\n sampleRate?: number,\n config: DeclipOptions = {},\n): MasteringRepairDeclipStereoResult {\n const request: MasteringRepairDeclipStereoRequest =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...config }\n : left;\n const { left: leftSamples, right: rightSamples, sampleRate: rate, ...options } = request;\n return requireModule().masteringRepairDeclipStereo(\n leftSamples,\n rightSamples,\n rate ?? 22050,\n options,\n );\n}\n\n/** Offline crackle suppressor (median or wavelet-shrinkage). */\nexport function masteringRepairDecrackle(request: MasteringRepairDecrackleRequest): Float32Array;\nexport function masteringRepairDecrackle(\n samples: Float32Array,\n sampleRate: number,\n options?: DecrackleOptions,\n): Float32Array;\nexport function masteringRepairDecrackle(\n samples: Float32Array | MasteringRepairDecrackleRequest,\n sampleRate?: number,\n options: DecrackleOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDecrackle(request.samples, request.sampleRate, request);\n}\n\n/**\n * Offline crackle suppressor (median or wavelet-shrinkage) for a stereo pair.\n *\n * Crackle is surface damage: the two channels carry different scratches at different instants,\n * so there is no common event for a shared decision to agree about. Each channel is decrackled\n * on its own -- there is no linking, unlike {@link masteringRepairDeclickStereo} and\n * {@link masteringRepairDeclipStereo} -- and this entry point exists to keep the reports and\n * the channel-length contract in one place.\n */\nexport function masteringRepairDecrackleStereo(\n request: MasteringRepairDecrackleStereoRequest,\n): MasteringRepairDecrackleStereoResult;\nexport function masteringRepairDecrackleStereo(\n left: Float32Array,\n right: Float32Array,\n sampleRate: number,\n config?: DecrackleOptions,\n): MasteringRepairDecrackleStereoResult;\nexport function masteringRepairDecrackleStereo(\n left: Float32Array | MasteringRepairDecrackleStereoRequest,\n right?: Float32Array,\n sampleRate?: number,\n config: DecrackleOptions = {},\n): MasteringRepairDecrackleStereoResult {\n const request: MasteringRepairDecrackleStereoRequest =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...config }\n : left;\n const { left: leftSamples, right: rightSamples, sampleRate: rate, ...options } = request;\n return requireModule().masteringRepairDecrackleStereo(\n leftSamples,\n rightSamples,\n rate ?? 22050,\n options,\n );\n}\n\n/** Request form of `masteringRepairDetectClicks`. */\nexport interface MasteringRepairDetectClicksRequest extends DeclickOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Request form of `masteringRepairDetectClipping`. */\nexport interface MasteringRepairDetectClippingRequest extends DeclipOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Request form of `masteringRepairDetectCrackle`. */\nexport interface MasteringRepairDetectCrackleRequest extends DecrackleOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/**\n * Measures clicks without repairing.\n *\n * Runs the same LPC analysis {@link masteringRepairDeclick} runs, so a run counted here is one\n * the repair would act on — a cheaper threshold-only scan would report runs it leaves alone.\n * That also means the options that shape the repair shape the count: a large `rejected` says\n * `maxClickSamples` or `neighborRatio` is too tight for this material, not that the material is\n * clean.\n *\n * @example\n * ```ts\n * const detected = masteringRepairDetectClicks({ samples, sampleRate: 48000 });\n * if (detected.perSecond > 1) samples = masteringRepairDeclick({ samples, sampleRate: 48000 });\n * ```\n */\nexport function masteringRepairDetectClicks(\n request: MasteringRepairDetectClicksRequest,\n): ClickDetection;\nexport function masteringRepairDetectClicks(\n samples: Float32Array,\n sampleRate: number,\n options?: DeclickOptions,\n): ClickDetection;\nexport function masteringRepairDetectClicks(\n samples: Float32Array | MasteringRepairDetectClicksRequest,\n sampleRate?: number,\n options: DeclickOptions = {},\n): ClickDetection {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDetectClicks(request.samples, request.sampleRate, request);\n}\n\n/**\n * Measures clipping without repairing.\n *\n * Counts samples at or past `clipThreshold`. No other option reaches the result — `lpcOrder`,\n * `iterations` and `lpcBlend` are validated and then unread, since nothing here is\n * reconstructed. `sampleRate` is validated without being read for the same reason: no field of\n * the result is a rate.\n *\n * Compare `longestRunSamples` against the 512-sample LPC cap to tell in advance which runs\n * {@link masteringRepairDeclip} would fill by interpolation rather than with the solver.\n *\n * `flatRunCount`, `longestFlatRunSamples`, `flatSampleCount` and `flatLevel` answer a different\n * question from the four fields above: those are read against `clipThreshold`, so they count the\n * apex of any waveform that reaches it — a full-scale sine reports thousands of \"clipped\" samples\n * having never been clipped — and they miss material clipped in one tool and attenuated in the\n * next, which leaves nothing at the threshold. The flat-top fields instead count runs of at least\n * 3 consecutive bit-identical samples whose level sits within 1 dB of the signal's peak, so they\n * catch a clipped-then-attenuated waveform that `sampleCount` reports as clean.\n *\n * Two opposite errors follow from what a flat top actually is. A genuinely flat-topped waveform —\n * a square or pulse train, a fully limited master — counts as clipped here too and cannot be told\n * apart from clipping in the time domain: a false positive. In the other direction, anything that\n * moves the two channels' samples independently before this runs erases a real flat top, so a\n * zero reading is not proof the material was never clipped — a stereo downmix does this, and so\n * do resampling and lossy coding, because the plateau stops being exactly level once each sample\n * is nudged on its own. **Detect each channel of a stereo signal separately, before any downmix,\n * never on the mixed-down result.**\n */\nexport function masteringRepairDetectClipping(\n request: MasteringRepairDetectClippingRequest,\n): ClipDetection;\nexport function masteringRepairDetectClipping(\n samples: Float32Array,\n sampleRate: number,\n options?: DeclipOptions,\n): ClipDetection;\nexport function masteringRepairDetectClipping(\n samples: Float32Array | MasteringRepairDetectClippingRequest,\n sampleRate?: number,\n options: DeclipOptions = {},\n): ClipDetection {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDetectClipping(\n request.samples,\n request.sampleRate,\n request,\n );\n}\n\n/**\n * Measures crackle without repairing.\n *\n * Measured by the median criterion whatever `mode` is set to: wavelet shrinkage removes crackle\n * without ever deciding that a sample is crackle, so these counts do not describe what a\n * wavelet-mode repair would remove. A caller therefore gets the same answer before choosing a\n * mode.\n */\nexport function masteringRepairDetectCrackle(\n request: MasteringRepairDetectCrackleRequest,\n): CrackleDetection;\nexport function masteringRepairDetectCrackle(\n samples: Float32Array,\n sampleRate: number,\n options?: DecrackleOptions,\n): CrackleDetection;\nexport function masteringRepairDetectCrackle(\n samples: Float32Array | MasteringRepairDetectCrackleRequest,\n sampleRate?: number,\n options: DecrackleOptions = {},\n): CrackleDetection {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDetectCrackle(request.samples, request.sampleRate, request);\n}\n","/**\n * Broadband and tonal noise repair: denoise and dehum, with their detectors.\n */\n\nimport { getSonareModule } from './module_state';\nimport type {\n HumDetection,\n MasteringRepairDehumStereoResult,\n MasteringRepairDenoiseClassicalLinkedResult,\n MasteringRepairDenoiseClassicalStereoResult,\n NoiseDetection,\n} from './public_types_repair';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n/** Algorithms accepted by `masteringRepairDenoiseClassical`. */\nexport type DenoiseClassicalMode = 'logMmse' | 'mmseStsa' | 'spectralSubtraction';\n\n/** Noise PSD estimators accepted by `masteringRepairDenoiseClassical`. */\nexport type DenoiseClassicalNoiseEstimator = 'quantile' | 'mcra' | 'imcra' | 'spp';\n\n/** Options for `masteringRepairDenoiseClassical`. */\nexport interface DenoiseClassicalOptions {\n mode?: DenoiseClassicalMode;\n noiseEstimator?: DenoiseClassicalNoiseEstimator;\n nFft?: number;\n hopLength?: number;\n ddAlpha?: number;\n reductionDb?: number;\n overSubtraction?: number;\n spectralFloor?: number;\n noiseEstimationQuantile?: number;\n speechPresenceGain?: boolean;\n gainSmoothing?: boolean;\n}\n\nexport interface MasteringRepairDenoiseClassicalRequest extends DenoiseClassicalOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Request form of `masteringRepairDenoiseClassicalStereo`. */\nexport interface MasteringRepairDenoiseClassicalStereoRequest extends DenoiseClassicalOptions {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n}\n\n/** Request form of `masteringRepairDenoiseClassicalLinked`. */\nexport interface MasteringRepairDenoiseClassicalLinkedRequest extends DenoiseClassicalOptions {\n /** At least one channel; all the same length. */\n channels: Float32Array[];\n sampleRate?: number;\n}\n\n/** Offline STFT-domain classical denoiser (LogMMSE / MMSE-STSA / SpectralSubtraction). */\nexport function masteringRepairDenoiseClassical(\n request: MasteringRepairDenoiseClassicalRequest,\n): Float32Array;\nexport function masteringRepairDenoiseClassical(\n samples: Float32Array,\n sampleRate: number,\n options?: DenoiseClassicalOptions,\n): Float32Array;\nexport function masteringRepairDenoiseClassical(\n samples: Float32Array | MasteringRepairDenoiseClassicalRequest,\n sampleRate?: number,\n options: DenoiseClassicalOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDenoiseClassical(\n request.samples,\n request.sampleRate,\n request,\n );\n}\n\n/**\n * Offline STFT-domain classical denoiser for a stereo pair, driven by one channel-linked\n * gain mask.\n *\n * The mask is built from the channel-summed power and applied unchanged to both channels, so\n * the pass cannot move an interchannel level or phase difference. That is also why the result\n * carries a single `report` rather than one per channel: a pair would be two copies of one\n * measurement and would read as though the two could differ.\n *\n * `report.detected` is therefore a *pair-level* measurement, and the only absolute one in the\n * result. Its levels are dBFS on the channel-summed power, so two identical channels read\n * `10*log10(2)` — about 3.01 dB — above the same material through\n * {@link masteringRepairDenoiseClassical}. A stereo floor is comparable only against another\n * stereo floor, never against a mono one.\n *\n * Needs at least `nFft` samples and REJECTS a shorter input, which is the opposite of\n * {@link masteringRepairDereverbClassicalStereo} — that one pads.\n *\n * Which options are live depends on `mode`: `overSubtraction` and `spectralFloor` are read\n * only by `spectralSubtraction`, and `speechPresenceGain` and `gainSmoothing` only by the\n * other two, so at the default `logMmse` the first pair does nothing.\n *\n * @example\n * ```ts\n * const { left, right, report } = masteringRepairDenoiseClassicalStereo({\n * left: leftSamples,\n * right: rightSamples,\n * sampleRate: 48000,\n * reductionDb: 18,\n * });\n * console.log(report.detected.floorDbfs, report.meanReductionDb);\n * ```\n */\nexport function masteringRepairDenoiseClassicalStereo(\n request: MasteringRepairDenoiseClassicalStereoRequest,\n): MasteringRepairDenoiseClassicalStereoResult;\nexport function masteringRepairDenoiseClassicalStereo(\n left: Float32Array,\n right: Float32Array,\n sampleRate: number,\n config?: DenoiseClassicalOptions,\n): MasteringRepairDenoiseClassicalStereoResult;\nexport function masteringRepairDenoiseClassicalStereo(\n left: Float32Array | MasteringRepairDenoiseClassicalStereoRequest,\n right?: Float32Array,\n sampleRate?: number,\n config: DenoiseClassicalOptions = {},\n): MasteringRepairDenoiseClassicalStereoResult {\n const request: MasteringRepairDenoiseClassicalStereoRequest =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...config }\n : left;\n const { left: leftSamples, right: rightSamples, sampleRate: rate, ...options } = request;\n return requireModule().masteringRepairDenoiseClassicalStereo(\n leftSamples,\n rightSamples,\n rate ?? 22050,\n options,\n );\n}\n\n/**\n * Offline STFT-domain classical denoiser for any number of channels, driven by one\n * channel-linked gain mask.\n *\n * The N-channel form of {@link masteringRepairDenoiseClassicalStereo}, carrying the same\n * guarantee over the whole set: the mask is built from the channel-summed power and applied\n * unchanged to every channel, so no interchannel level or phase difference moves however many\n * channels there are. One `report` for the set, and one output per input channel in input order.\n *\n * A single channel reproduces {@link masteringRepairDenoiseClassical} bit for bit, and two\n * reproduce {@link masteringRepairDenoiseClassicalStereo} plane for plane — `channels[0]` is the\n * left plane and `channels[1]` the right.\n *\n * `report.detected` carries absolute levels and they are the SET's: the floor is referred to the\n * summed mean square of every channel, so N identical channels read `10*log10(N)` above\n * one of them — about 3.01 dB at two channels and 4.77 dB at three. Compare a floor only against\n * one measured over the same number of channels. Every other field of the report is a fraction\n * and does not move with the channel count.\n *\n * Needs at least `nFft` samples and REJECTS a shorter input, which is the opposite of\n * {@link masteringRepairDereverbClassicalLinked} — that one pads.\n *\n * @example\n * ```ts\n * const { channels, report } = masteringRepairDenoiseClassicalLinked({\n * channels: [frontLeft, frontRight, centre],\n * sampleRate: 48000,\n * reductionDb: 18,\n * });\n * console.log(channels.length, report.detected.floorDbfs);\n * ```\n */\nexport function masteringRepairDenoiseClassicalLinked(\n request: MasteringRepairDenoiseClassicalLinkedRequest,\n): MasteringRepairDenoiseClassicalLinkedResult;\nexport function masteringRepairDenoiseClassicalLinked(\n channels: Float32Array[],\n sampleRate: number,\n config?: DenoiseClassicalOptions,\n): MasteringRepairDenoiseClassicalLinkedResult;\nexport function masteringRepairDenoiseClassicalLinked(\n channels: Float32Array[] | MasteringRepairDenoiseClassicalLinkedRequest,\n sampleRate?: number,\n config: DenoiseClassicalOptions = {},\n): MasteringRepairDenoiseClassicalLinkedResult {\n const request: MasteringRepairDenoiseClassicalLinkedRequest = Array.isArray(channels)\n ? { channels, sampleRate, ...config }\n : channels;\n const { channels: input, sampleRate: rate, ...options } = request;\n return requireModule().masteringRepairDenoiseClassicalLinked(input, rate ?? 22050, options);\n}\n\n/**\n * How `masteringRepairDehum` removes the harmonic series.\n *\n * `subtract` tracks each harmonic's amplitude and phase and subtracts the tone they describe,\n * so material sitting at the same frequency but uncorrelated with the tracked series survives.\n * `notch` cascades one RBJ notch per harmonic and removes everything inside each notch's\n * bandwidth, hum or programme alike.\n */\nexport type DehumMode = 'subtract' | 'notch';\n\n/** Options for `masteringRepairDehum`. */\nexport interface DehumOptions {\n fundamentalHz?: number;\n harmonics?: number;\n q?: number;\n adaptive?: boolean;\n searchRangeHz?: number;\n adaptation?: number;\n frameSize?: number;\n pllBandwidth?: number;\n /** Defaults to `'subtract'`. */\n mode?: DehumMode;\n}\n\nexport interface MasteringRepairDehumRequest extends DehumOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Request form of `masteringRepairDehumStereo`. */\nexport interface MasteringRepairDehumStereoRequest extends DehumOptions {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n}\n\n/** Offline mains-hum remover. */\nexport function masteringRepairDehum(request: MasteringRepairDehumRequest): Float32Array;\nexport function masteringRepairDehum(\n samples: Float32Array,\n sampleRate: number,\n options?: DehumOptions,\n): Float32Array;\nexport function masteringRepairDehum(\n samples: Float32Array | MasteringRepairDehumRequest,\n sampleRate?: number,\n options: DehumOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDehum(request.samples, request.sampleRate, request);\n}\n\n/**\n * Offline mains-hum remover for a stereo pair.\n *\n * With `adaptive` set, mains hum is one physical source, so the tracker reads the channel\n * mean and both cascades follow the one frequency it finds: `appliedFundamentalHz` and\n * `fundamentalDriftHz` come back identical in both reports by construction, while each\n * report's `detected` still measures that channel's own input and each channel keeps its\n * own filter state, so neither channel's transient rings through the other. With `adaptive`\n * clear, which is the default, nothing is shared and the two channels are filtered\n * independently at the configured frequency.\n */\nexport function masteringRepairDehumStereo(\n request: MasteringRepairDehumStereoRequest,\n): MasteringRepairDehumStereoResult;\nexport function masteringRepairDehumStereo(\n left: Float32Array,\n right: Float32Array,\n sampleRate: number,\n config?: DehumOptions,\n): MasteringRepairDehumStereoResult;\nexport function masteringRepairDehumStereo(\n left: Float32Array | MasteringRepairDehumStereoRequest,\n right?: Float32Array,\n sampleRate?: number,\n config: DehumOptions = {},\n): MasteringRepairDehumStereoResult {\n const request: MasteringRepairDehumStereoRequest =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...config }\n : left;\n const { left: leftSamples, right: rightSamples, sampleRate: rate, ...options } = request;\n return requireModule().masteringRepairDehumStereo(\n leftSamples,\n rightSamples,\n rate ?? 22050,\n options,\n );\n}\n\n/** Request form of `masteringRepairDetectNoiseFloor`. */\nexport interface MasteringRepairDetectNoiseFloorRequest extends DenoiseClassicalOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Request form of `masteringRepairNoiseBandBins`. */\nexport interface MasteringRepairNoiseBandBinsRequest {\n nFft?: number;\n sampleRate?: number;\n}\n\n/** Request form of `masteringRepairDetectHum`. */\nexport interface MasteringRepairDetectHumRequest extends DehumOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/**\n * Measures the noise floor without denoising.\n *\n * Runs the STFT and the configured noise estimator — the two stages\n * {@link masteringRepairDenoiseClassical} runs — and stops before the gain mask, which is why\n * no attenuation figure appears here.\n *\n * Needs at least `nFft` samples and THROWS for a shorter buffer, the opposite of\n * {@link masteringRepairDetectReverb}, which pads one.\n *\n * `floorDbfs` is an absolute level, so it is comparable only against another figure measured\n * over the same channel count.\n */\nexport function masteringRepairDetectNoiseFloor(\n request: MasteringRepairDetectNoiseFloorRequest,\n): NoiseDetection;\nexport function masteringRepairDetectNoiseFloor(\n samples: Float32Array,\n sampleRate: number,\n options?: DenoiseClassicalOptions,\n): NoiseDetection;\nexport function masteringRepairDetectNoiseFloor(\n samples: Float32Array | MasteringRepairDetectNoiseFloorRequest,\n sampleRate?: number,\n options: DenoiseClassicalOptions = {},\n): NoiseDetection {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDetectNoiseFloor(\n request.samples,\n request.sampleRate,\n request,\n );\n}\n\n/**\n * Bin boundaries of the grid {@link masteringRepairDetectNoiseFloor} reports `bandFloorDbfs` on.\n *\n * Band `k` covers the one-sided STFT bins `[bins[k], bins[k + 1])`, and bin `b` sits at\n * `b * sampleRate / nFft` Hz.\n *\n * The geometric band edges are rounded to bins, so a band narrower than the bin spacing comes\n * out EMPTY — `bins[k] === bins[k + 1]` — and its `bandFloorDbfs[k]` reads as the floor\n * sentinel because no bin landed in it, NOT because that region was quiet. Telling those two\n * apart is what this grid is for, and the rounding cannot be recovered from the band count\n * alone.\n *\n * Nothing but the analysis geometry decides the grid, so no denoise config is taken: one call\n * describes every floor measured at that `nFft` and `sampleRate`, whatever mode or estimator\n * produced it.\n *\n * @param nFft - STFT size the bins belong to; a positive power of two, the same rule\n * {@link masteringRepairDetectNoiseFloor} applies to its config, so every grid returned here\n * is one that entry can report on. Defaults to 1024.\n * @param sampleRate - Sample rate the bins belong to, in Hz; positive. Defaults to 22050.\n * @returns 33 bin indices, low to high — one more than the 32 bands: the first bin of every\n * band plus the one-past-the-end bin of the last, which is `nFft / 2 + 1`. Non-decreasing.\n * @throws If `nFft` is not a positive power of two, or `sampleRate` is not positive.\n *\n * @example\n * ```ts\n * const bins = masteringRepairNoiseBandBins({ nFft: 1024, sampleRate: 48000 });\n * const floor = masteringRepairDetectNoiseFloor({ samples, sampleRate: 48000, nFft: 1024 });\n * floor.bandFloorDbfs.forEach((level, k) => {\n * if (bins[k] === bins[k + 1]) return; // empty band: `level` is the sentinel, not a measurement\n * console.log((bins[k] * 48000) / 1024, level);\n * });\n * ```\n */\nexport function masteringRepairNoiseBandBins(\n request?: MasteringRepairNoiseBandBinsRequest,\n): Int32Array;\nexport function masteringRepairNoiseBandBins(nFft?: number, sampleRate?: number): Int32Array;\nexport function masteringRepairNoiseBandBins(\n nFft?: number | MasteringRepairNoiseBandBinsRequest,\n sampleRate?: number,\n): Int32Array {\n // Both positional arguments are optional, so a default on `nFft` would swallow\n // an explicit `undefined` and take the request branch with `sampleRate` in hand\n // but unreachable. Discriminate on the value instead.\n const request = typeof nFft === 'object' && nFft !== null ? nFft : { nFft, sampleRate };\n return requireModule().masteringRepairNoiseBandBins(\n request.nFft ?? 1024,\n request.sampleRate ?? 22050,\n );\n}\n\n/**\n * Measures hum without filtering.\n *\n * Always runs the estimation path, whatever `adaptive` says: the fixed path notches the\n * configured frequency without ever looking for hum, so a detector following the flag would\n * hand back its own input. `fundamentalProminence` is the winning candidate's projected energy\n * over the median candidate, so `1.0` means no peak was found at all — it is not a lock flag.\n *\n * `harmonicDbfs` is measured at every `k*f0` the sample rate carries, not only the ones a\n * cascade would notch; a `k*f0` at or past Nyquist reads the dB floor because nothing is there\n * to measure.\n */\nexport function masteringRepairDetectHum(request: MasteringRepairDetectHumRequest): HumDetection;\nexport function masteringRepairDetectHum(\n samples: Float32Array,\n sampleRate: number,\n options?: DehumOptions,\n): HumDetection;\nexport function masteringRepairDetectHum(\n samples: Float32Array | MasteringRepairDetectHumRequest,\n sampleRate?: number,\n options: DehumOptions = {},\n): HumDetection {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDetectHum(request.samples, request.sampleRate, request);\n}\n","/**\n * Silence trimming, with the range detector it shares its geometry with.\n */\n\nimport { getSonareModule } from './module_state';\nimport type { MasteringRepairTrimSilenceStereoResult, TrimRange } from './public_types_repair';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n/** Trimming modes accepted by `masteringRepairTrimSilence`. */\nexport type TrimSilenceMode = 'peak' | 'lufsGated';\n\n/** Options for `masteringRepairTrimSilence`. */\nexport interface TrimSilenceOptions {\n threshold?: number;\n paddingSamples?: number;\n mode?: TrimSilenceMode;\n gateLufs?: number;\n windowMs?: number;\n}\n\nexport interface MasteringRepairTrimSilenceRequest extends TrimSilenceOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Request form of `masteringRepairTrimSilenceStereo`. */\nexport interface MasteringRepairTrimSilenceStereoRequest extends TrimSilenceOptions {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n}\n\n/** Offline silence trimmer (peak threshold or LUFS-gated). */\nexport function masteringRepairTrimSilence(\n request: MasteringRepairTrimSilenceRequest,\n): Float32Array;\nexport function masteringRepairTrimSilence(\n samples: Float32Array,\n sampleRate: number,\n options?: TrimSilenceOptions,\n): Float32Array;\nexport function masteringRepairTrimSilence(\n samples: Float32Array | MasteringRepairTrimSilenceRequest,\n sampleRate?: number,\n options: TrimSilenceOptions = {},\n): Float32Array {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairTrimSilence(request.samples, request.sampleRate, request);\n}\n\n/**\n * Offline silence trimmer for a stereo pair, cutting both channels to one shared range.\n *\n * Each channel is scanned on its own and the two ranges are UNIONED, so the pair keeps\n * whatever either channel calls signal and both outputs come back the same length. The scan\n * never reads a downmix: `0.5 * (left + right)` halves material carried by one channel alone,\n * which can drop it under the gate, and cancels an antiphase pair to exactly zero, which would\n * read full-level audio in both channels as silence. Trimming is destructive, so the rule errs\n * toward keeping.\n *\n * The only repair stereo entry that SHORTENS its input: `result.left.length` is the output\n * length, and the input's says nothing about it. A pair in which neither channel carries signal\n * returns two EMPTY arrays and succeeds — it does not throw and does not return null.\n *\n * `report.range` is the union that was applied to both channels. `leftRange` and `rightRange`\n * are the per-channel scans it was formed from, so a caller can see which channel decided each\n * edge; a channel carrying nothing reports an empty range and contributes nothing to the union.\n * With nothing kept, `report.range` is `(inputLength, inputLength)`, so `removedHeadSamples` is\n * the whole input and `removedTailSamples` is 0 — the two still sum to the input length and\n * only the split between the ends is arbitrary.\n *\n * Which option is live depends on `mode`: `threshold` is read ONLY by `'peak'`, and `gateLufs`\n * and `windowMs` ONLY by `'lufsGated'`. Changing an option the active mode does not read is\n * silently inert rather than an error.\n *\n * That gated mode compares an UNWEIGHTED RMS over a window centred on each sample against\n * `gateLufs`, so the figure it gates on is dBFS rather than a BS.1770 loudness, and `windowMs`\n * sizes that window and does nothing else. The window is clipped at the buffer ends, so a\n * sample near either edge is judged on a shorter one.\n *\n * `paddingSamples` widens the kept range in both directions and is clamped to the buffer, so it\n * can never reach past either end; a pass that kept nothing is not padded. A NEGATIVE count is\n * refused by name rather than absorbed into 0 or into the default — the underlying field is\n * unsigned, and a negative one would arrive as an enormous count instead.\n *\n * @example\n * ```ts\n * const { left, right, report, leftRange, rightRange } = masteringRepairTrimSilenceStereo({\n * left: leftSamples,\n * right: rightSamples,\n * sampleRate: 48000,\n * mode: 'peak',\n * threshold: 0.01,\n * });\n * console.log(left.length, report.removedHeadSamples, leftRange.first, rightRange.first);\n * ```\n */\nexport function masteringRepairTrimSilenceStereo(\n request: MasteringRepairTrimSilenceStereoRequest,\n): MasteringRepairTrimSilenceStereoResult;\nexport function masteringRepairTrimSilenceStereo(\n left: Float32Array,\n right: Float32Array,\n sampleRate: number,\n config?: TrimSilenceOptions,\n): MasteringRepairTrimSilenceStereoResult;\nexport function masteringRepairTrimSilenceStereo(\n left: Float32Array | MasteringRepairTrimSilenceStereoRequest,\n right?: Float32Array,\n sampleRate?: number,\n config: TrimSilenceOptions = {},\n): MasteringRepairTrimSilenceStereoResult {\n const request: MasteringRepairTrimSilenceStereoRequest =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...config }\n : left;\n const { left: leftSamples, right: rightSamples, sampleRate: rate, ...options } = request;\n return requireModule().masteringRepairTrimSilenceStereo(\n leftSamples,\n rightSamples,\n rate ?? 22050,\n options,\n );\n}\n\n/** Request form of `masteringRepairDetectTrimRange`. */\nexport interface MasteringRepairDetectTrimRangeRequest extends TrimSilenceOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Request form of `masteringRepairDetectTrimRangeStereo`. */\nexport interface MasteringRepairDetectTrimRangeStereoRequest extends TrimSilenceOptions {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n}\n\n/**\n * Measures the range {@link masteringRepairTrimSilence} would keep, without trimming.\n *\n * The padding `paddingSamples` asks for is already INSIDE the returned range, so this is the\n * range the repair would cut to rather than the detected extent of the signal. A buffer with\n * nothing above the threshold reports `(length, length)`.\n *\n * @example\n * ```ts\n * const range = masteringRepairDetectTrimRange({ samples, sampleRate: 48000, threshold: 0.01 });\n * const keptSeconds = (range.lastExclusive - range.first) / 48000;\n * ```\n */\nexport function masteringRepairDetectTrimRange(\n request: MasteringRepairDetectTrimRangeRequest,\n): TrimRange;\nexport function masteringRepairDetectTrimRange(\n samples: Float32Array,\n sampleRate: number,\n options?: TrimSilenceOptions,\n): TrimRange;\nexport function masteringRepairDetectTrimRange(\n samples: Float32Array | MasteringRepairDetectTrimRangeRequest,\n sampleRate?: number,\n options: TrimSilenceOptions = {},\n): TrimRange {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n return requireModule().masteringRepairDetectTrimRange(\n request.samples,\n request.sampleRate,\n request,\n );\n}\n\n/**\n * Measures the one range a stereo trim pass would cut both channels to.\n *\n * Each channel is scanned on its own and the two ranges are UNIONED, so the pair keeps whatever\n * either channel calls signal. A channel with nothing above the threshold contributes NO EDGE\n * rather than an edge at the buffer's end: the union of a silent channel and an active one is\n * the active channel's range exactly, where a naive `min`/`max` would push `lastExclusive` out\n * to the buffer end and keep the whole tail.\n *\n * A downmix is not read: summing to mono halves material carried by one channel alone and\n * cancels an antiphase pair outright, either of which would read full-level audio as silence.\n *\n * @example\n * ```ts\n * const range = masteringRepairDetectTrimRangeStereo({ left, right, sampleRate: 48000 });\n * console.log(range.first, range.lastExclusive);\n * ```\n */\nexport function masteringRepairDetectTrimRangeStereo(\n request: MasteringRepairDetectTrimRangeStereoRequest,\n): TrimRange;\nexport function masteringRepairDetectTrimRangeStereo(\n left: Float32Array,\n right: Float32Array,\n sampleRate: number,\n config?: TrimSilenceOptions,\n): TrimRange;\nexport function masteringRepairDetectTrimRangeStereo(\n left: Float32Array | MasteringRepairDetectTrimRangeStereoRequest,\n right?: Float32Array,\n sampleRate?: number,\n config: TrimSilenceOptions = {},\n): TrimRange {\n const request: MasteringRepairDetectTrimRangeStereoRequest =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...config }\n : left;\n const { left: leftSamples, right: rightSamples, sampleRate: rate, ...options } = request;\n return requireModule().masteringRepairDetectTrimRangeStereo(\n leftSamples,\n rightSamples,\n rate ?? 22050,\n options,\n );\n}\n","import { getSonareModule } from './module_state';\nimport type { TempogramMode } from './public_types';\nimport type {\n WasmCyclicTempogramResult,\n WasmFrameResult,\n WasmTempogramResult,\n WasmTrimResult,\n} from './sonare.js';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\nexport function tone(request?: ToneRequest): Float32Array;\nexport function tone(\n frequency?: number,\n sampleRate?: number,\n duration?: number,\n phase?: number,\n amplitude?: number,\n): Float32Array;\nexport function tone(\n frequency: number | ToneRequest = 440,\n sampleRate = 22050,\n duration = 1,\n phase = 0,\n amplitude = 1,\n): Float32Array {\n const request =\n typeof frequency === 'number'\n ? { frequency, sampleRate, duration, phase, amplitude }\n : frequency;\n return requireModule().tone(\n request.frequency ?? 440,\n request.sampleRate ?? 22050,\n request.duration ?? 1,\n request.phase ?? 0,\n request.amplitude ?? 1,\n );\n}\n\nexport function chirp(request?: ChirpRequest): Float32Array;\nexport function chirp(\n fmin?: number,\n fmax?: number,\n sampleRate?: number,\n duration?: number,\n linear?: boolean,\n): Float32Array;\nexport function chirp(\n fmin: number | ChirpRequest = 440,\n fmax = 880,\n sampleRate = 22050,\n duration = 1,\n linear = true,\n): Float32Array {\n const request = typeof fmin === 'number' ? { fmin, fmax, sampleRate, duration, linear } : fmin;\n return requireModule().chirp(\n request.fmin ?? 440,\n request.fmax ?? 880,\n request.sampleRate ?? 22050,\n request.duration ?? 1,\n request.linear ?? true,\n );\n}\n\nexport function clicks(request: ClicksRequest): Float32Array;\nexport function clicks(\n times: Float32Array,\n sampleRate?: number,\n length?: number,\n frequency?: number,\n clickDuration?: number,\n): Float32Array;\nexport function clicks(\n times: Float32Array | ClicksRequest,\n sampleRate = 22050,\n length = 0,\n frequency = 1000,\n clickDuration = 0.1,\n): Float32Array {\n const request =\n times instanceof Float32Array ? { times, sampleRate, length, frequency, clickDuration } : times;\n return requireModule().clicks(\n request.times,\n request.sampleRate ?? 22050,\n request.length ?? 0,\n request.frequency ?? 1000,\n request.clickDuration ?? 0.1,\n );\n}\n\nexport interface DbConversionRequest {\n values: Float32Array;\n ref?: number;\n amin?: number;\n topDb?: number;\n}\n\nexport interface SilenceRequest {\n samples: Float32Array;\n topDb?: number;\n frameLength?: number;\n hopLength?: number;\n}\n\n/** Canonical request form for the common-silence union of several signals. */\nexport interface SplitSilenceCommonRequest {\n signals: Float32Array[];\n topDb?: number;\n frameLength?: number;\n hopLength?: number;\n}\n\n/**\n * Why {@link splitSilenceCommonWithReport} found the gaps it did.\n *\n * One interval covering everything is the answer to three different situations\n * and the interval list cannot separate them: no take has a quiet moment at all,\n * the takes each have one but not in the same place, or `topDb` was set too loose\n * to see the ones they have.\n *\n * **Read {@link silenceCeilingDb} against the `topDb` that was passed**, which is\n * the whole decision:\n *\n * - ceiling near 0 — a take is sounding continuously. No threshold helps, and a\n * cut point has to come from somewhere other than silence.\n * - ceiling below `topDb` — the threshold was too loose to see the quiet these\n * takes do have. A `topDb` under the reported ceiling finds it.\n * - ceiling at or above `topDb`, and still one interval — every take shows silence\n * at this setting and they do not share any of it. That is the alignment case,\n * and it is what {@link alignTakeToReference} is for.\n *\n * The figures come from the same RMS pass the intervals do, so they can never\n * describe a different measurement.\n */\nexport interface SilenceCommonReport {\n /**\n * The largest `topDb` at which EVERY signal still shows silence.\n *\n * A frame counts as silent when it sits at least `topDb` under its own signal's\n * peak RMS, so each signal's deepest dip decides whether any threshold can find\n * silence in it, and the union needs all of them quiet at once — hence the\n * minimum across the signals. 0 for an all-silent signal, where the peak is 0\n * and the ratio has no value; 120 is the floor the dB conversion clamps at,\n * reported for a signal holding a zero-valued frame.\n */\n silenceCeilingDb: number;\n /**\n * How many intervals the most fragmented signal produced alone, counted before\n * the union merges anything.\n *\n * A measure of shape rather than of cause: 1 is a take that sounds once and\n * stops, so a take that is loud then silent counts 1 exactly as a take with no\n * silence does. Use {@link silenceCeilingDb} to tell those apart; use these two\n * to see whether any take has an interior gap at all (`>= 2`) and whether the\n * takes differ in how broken up they are (`maxSignalIntervals !==\n * minSignalIntervals`).\n */\n maxSignalIntervals: number;\n /** How many intervals the least fragmented signal produced alone. */\n minSignalIntervals: number;\n}\n\n/** Result of {@link splitSilenceCommonWithReport}. */\nexport interface SplitSilenceCommonWithReportResult {\n /** Exactly what {@link splitSilenceCommon} returns for the same arguments. */\n intervals: Int32Array;\n /** Why those are the intervals. */\n report: SilenceCommonReport;\n}\n\nexport interface FrameSignalRequest {\n samples: Float32Array;\n frameLength: number;\n hopLength: number;\n}\nexport interface ToneRequest {\n frequency?: number;\n sampleRate?: number;\n duration?: number;\n phase?: number;\n amplitude?: number;\n}\nexport interface ChirpRequest {\n fmin?: number;\n fmax?: number;\n sampleRate?: number;\n duration?: number;\n linear?: boolean;\n}\nexport interface ClicksRequest {\n times: Float32Array;\n sampleRate?: number;\n length?: number;\n frequency?: number;\n clickDuration?: number;\n}\n/** Canonical request form for pre/de-emphasis filters. */\nexport interface EmphasisRequest {\n samples: Float32Array;\n coef?: number;\n zi?: number;\n}\n/** Canonical request form for centering or extending a vector. */\nexport interface PadCenterRequest {\n values: Float32Array;\n targetSize: number;\n padValue?: number;\n}\n/** Canonical request form for resizing a vector. */\nexport interface FixLengthRequest {\n values: Float32Array;\n targetSize: number;\n padValue?: number;\n}\n/** Canonical request form for bounding a frame-index vector. */\nexport interface FixFramesRequest {\n frames: Int32Array;\n xMin?: number;\n xMax?: number;\n pad?: boolean;\n}\nexport interface OnsetBacktrackRequest {\n events: Int32Array;\n energy: Float32Array;\n}\n/** Canonical request form for peak selection. */\nexport interface PeakPickRequest {\n values: Float32Array;\n preMax: number;\n postMax: number;\n preAvg: number;\n postAvg: number;\n delta: number;\n wait: number;\n}\n/** Canonical request form for vector normalization. */\nexport interface VectorNormalizeRequest {\n values: Float32Array;\n normType?: number;\n threshold?: number;\n}\n/** Canonical request form for tonal centroid projection. */\nexport interface TonnetzRequest {\n chromagram: Float32Array;\n nChroma: number;\n nFrames: number;\n}\nexport interface PcenRequest {\n values: Float32Array;\n nBins: number;\n nFrames: number;\n sampleRate?: number;\n hopLength?: number;\n timeConstant?: number;\n gain?: number;\n bias?: number;\n power?: number;\n eps?: number;\n /** @deprecated Put PCEN fields directly on the request object. */\n options?: Record<string, number>;\n}\nexport interface TempogramRequest {\n onsetEnvelope: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n winLength?: number;\n mode?: TempogramMode;\n center?: boolean;\n norm?: boolean;\n}\nexport interface CyclicTempogramRequest {\n onsetEnvelope: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n winLength?: number;\n bpmMin?: number;\n nBins?: number;\n}\nexport interface PlpRequest {\n onsetEnvelope: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n tempoMin?: number;\n tempoMax?: number;\n winLength?: number;\n}\n\n// ============================================================================\n// Core - Unit Conversion\n// ============================================================================\n\n/**\n * Convert frequency in Hz to Mel scale.\n *\n * A total function, matching the C ABI and librosa: a non-finite `hz`\n * propagates rather than throwing, and a magnitude past the 32-bit float range\n * saturates to an infinity the same way the C conversion does. Out-of-audio\n * frequencies are not refused either — the mapping is defined over the whole\n * real line.\n *\n * @param hz - Frequency in Hz\n * @returns Mel frequency\n */\nexport function hzToMel(hz: number): number {\n return requireModule().hzToMel(hz);\n}\n\n/**\n * Convert Mel scale to frequency in Hz. Total over the same domain as\n * {@link hzToMel}.\n *\n * @param mel - Mel frequency\n * @returns Frequency in Hz\n */\nexport function melToHz(mel: number): number {\n return requireModule().melToHz(mel);\n}\n\n/**\n * Convert frequency in Hz to MIDI note number.\n *\n * Total, like {@link hzToMel}. A non-positive `hz` returns `-Infinity`, the log2\n * limit, and {@link midiToHz} maps that back to 0. A NaN propagates, which is\n * what makes a default `pitchPyin` track — whose unvoiced frames are NaN — safe\n * to map through.\n *\n * @param hz - Frequency in Hz\n * @returns MIDI note number (A4 = 440 Hz = 69)\n */\nexport function hzToMidi(hz: number): number {\n return requireModule().hzToMidi(hz);\n}\n\n/**\n * Convert MIDI note number to frequency in Hz. Total, like {@link hzToMel};\n * `-Infinity` bottoms out at 0 rather than propagating its sign.\n *\n * @param midi - MIDI note number\n * @returns Frequency in Hz\n */\nexport function midiToHz(midi: number): number {\n return requireModule().midiToHz(midi);\n}\n\n/**\n * Convert frequency in Hz to note name.\n *\n * Every frequency with no note answers `\"?\"` rather than throwing: zero,\n * negative, past the representable MIDI range, and non-finite alike. A default\n * `pitchPyin` track fills unvoiced frames with NaN, so mapping one through this\n * yields `\"?\"` at those frames.\n *\n * @param hz - Frequency in Hz\n * @returns Note name (e.g., \"A4\", \"C#5\")\n */\nexport function hzToNote(hz: number): string {\n return requireModule().hzToNote(hz);\n}\n\n/**\n * Convert note name to frequency in Hz.\n *\n * @param note - Note name (e.g., \"A4\", \"C#5\")\n * @returns Frequency in Hz\n */\nexport function noteToHz(note: string): number {\n return requireModule().noteToHz(note);\n}\n\n/**\n * Convert frame index to time in seconds.\n *\n * @param frames - Frame index\n * @param sr - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length in samples (default: 512)\n * @returns Time in seconds\n */\nexport function framesToTime(frames: number, sr = 22050, hopLength = 512): number {\n return requireModule().framesToTime(frames, sr, hopLength);\n}\n\n/**\n * Convert time in seconds to frame index.\n *\n * @param time - Time in seconds\n * @param sr - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length in samples (default: 512)\n * @returns Frame index\n */\nexport function timeToFrames(time: number, sr = 22050, hopLength = 512): number {\n return requireModule().timeToFrames(time, sr, hopLength);\n}\n\nexport function framesToSamples(frames: number, hopLength = 512, nFft = 0): number {\n return requireModule().framesToSamples(frames, hopLength, nFft);\n}\n\nexport function samplesToFrames(samples: number, hopLength = 512, nFft = 0): number {\n return requireModule().samplesToFrames(samples, hopLength, nFft);\n}\n\nexport function powerToDb(request: DbConversionRequest): Float32Array;\nexport function powerToDb(\n values: Float32Array,\n ref?: number,\n amin?: number,\n topDb?: number,\n): Float32Array;\nexport function powerToDb(\n values: Float32Array | DbConversionRequest,\n ref = 1.0,\n amin = 1e-10,\n topDb = 80.0,\n): Float32Array {\n if (!(values instanceof Float32Array)) {\n return powerToDb(values.values, values.ref, values.amin, values.topDb);\n }\n return requireModule().powerToDb(values, ref, amin, topDb);\n}\n\nexport function amplitudeToDb(request: DbConversionRequest): Float32Array;\nexport function amplitudeToDb(\n values: Float32Array,\n ref?: number,\n amin?: number,\n topDb?: number,\n): Float32Array;\nexport function amplitudeToDb(\n values: Float32Array | DbConversionRequest,\n ref = 1.0,\n amin = 1e-5,\n topDb = 80.0,\n): Float32Array {\n if (!(values instanceof Float32Array)) {\n return amplitudeToDb(values.values, values.ref, values.amin, values.topDb);\n }\n return requireModule().amplitudeToDb(values, ref, amin, topDb);\n}\n\nexport function dbToPower(values: Float32Array, ref = 1.0): Float32Array {\n return requireModule().dbToPower(values, ref);\n}\n\nexport function dbToAmplitude(values: Float32Array, ref = 1.0): Float32Array {\n return requireModule().dbToAmplitude(values, ref);\n}\n\nexport function preemphasis(request: EmphasisRequest): Float32Array;\nexport function preemphasis(samples: Float32Array, coef?: number, zi?: number): Float32Array;\nexport function preemphasis(\n samples: Float32Array | EmphasisRequest,\n coef = 0.97,\n zi?: number,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return preemphasis(samples.samples, samples.coef, samples.zi);\n }\n return requireModule().preemphasis(samples, coef, zi ?? null);\n}\n\nexport function deemphasis(request: EmphasisRequest): Float32Array;\nexport function deemphasis(samples: Float32Array, coef?: number, zi?: number): Float32Array;\nexport function deemphasis(\n samples: Float32Array | EmphasisRequest,\n coef = 0.97,\n zi?: number,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return deemphasis(samples.samples, samples.coef, samples.zi);\n }\n return requireModule().deemphasis(samples, coef, zi ?? null);\n}\n\nexport function trimSilence(request: SilenceRequest): WasmTrimResult;\nexport function trimSilence(\n samples: Float32Array,\n topDb?: number,\n frameLength?: number,\n hopLength?: number,\n): WasmTrimResult;\nexport function trimSilence(\n samples: Float32Array | SilenceRequest,\n topDb = 60.0,\n frameLength = 2048,\n hopLength = 512,\n): WasmTrimResult {\n if (!(samples instanceof Float32Array)) {\n return trimSilence(samples.samples, samples.topDb, samples.frameLength, samples.hopLength);\n }\n return requireModule().trimSilence(samples, topDb, frameLength, hopLength);\n}\n\nexport function splitSilence(request: SilenceRequest): Int32Array;\nexport function splitSilence(\n samples: Float32Array,\n topDb?: number,\n frameLength?: number,\n hopLength?: number,\n): Int32Array;\nexport function splitSilence(\n samples: Float32Array | SilenceRequest,\n topDb = 60.0,\n frameLength = 2048,\n hopLength = 512,\n): Int32Array {\n if (!(samples instanceof Float32Array)) {\n return splitSilence(samples.samples, samples.topDb, samples.frameLength, samples.hopLength);\n }\n return requireModule().splitSilence(samples, topDb, frameLength, hopLength);\n}\n\n/**\n * Lists the intervals where ANY of `signals` is sounding, so every gap\n * between them is silent in all of them -- what several takes of one part\n * share is their silence, not their sound.\n *\n * @returns The union of {@link splitSilence}'s per-signal intervals, merged\n * where they touch. A single signal returns exactly what `splitSilence`\n * does for it.\n */\nexport function splitSilenceCommon(request: SplitSilenceCommonRequest): Int32Array {\n return requireModule().splitSilenceCommon(\n request.signals,\n request.topDb ?? 60.0,\n request.frameLength ?? 2048,\n request.hopLength ?? 512,\n );\n}\n\n/**\n * {@link splitSilenceCommon} plus the report that says why those are the\n * intervals.\n *\n * Identical intervals, identical refusals, identical defaults; the only\n * difference is the second field. The plain entry point stays because a caller\n * cutting takes has no use for the diagnosis, and one interval covering\n * everything is the answer to three different situations the interval list cannot\n * separate — see {@link SilenceCommonReport} for reading them apart.\n *\n * @returns The union intervals and the report measured on the same RMS pass\n */\nexport function splitSilenceCommonWithReport(\n request: SplitSilenceCommonRequest,\n): SplitSilenceCommonWithReportResult {\n return requireModule().splitSilenceCommonWithReport(\n request.signals,\n request.topDb ?? 60.0,\n request.frameLength ?? 2048,\n request.hopLength ?? 512,\n );\n}\n\nexport function frameSignal(request: FrameSignalRequest): WasmFrameResult;\nexport function frameSignal(\n samples: Float32Array,\n frameLength: number,\n hopLength: number,\n): WasmFrameResult;\nexport function frameSignal(\n samples: Float32Array | FrameSignalRequest,\n frameLength?: number,\n hopLength?: number,\n): WasmFrameResult {\n if (!(samples instanceof Float32Array)) {\n return frameSignal(samples.samples, samples.frameLength, samples.hopLength);\n }\n return requireModule().frameSignal(samples, frameLength as number, hopLength as number);\n}\n\nexport function padCenter(request: PadCenterRequest): Float32Array;\nexport function padCenter(\n values: Float32Array,\n targetSize: number,\n padValue?: number,\n): Float32Array;\nexport function padCenter(\n values: Float32Array | PadCenterRequest,\n targetSize?: number,\n padValue = 0.0,\n): Float32Array {\n if (!(values instanceof Float32Array)) {\n return padCenter(values.values, values.targetSize, values.padValue);\n }\n return requireModule().padCenter(values, targetSize as number, padValue);\n}\n\nexport function fixLength(request: FixLengthRequest): Float32Array;\nexport function fixLength(\n values: Float32Array,\n targetSize: number,\n padValue?: number,\n): Float32Array;\nexport function fixLength(\n values: Float32Array | FixLengthRequest,\n targetSize?: number,\n padValue = 0.0,\n): Float32Array {\n if (!(values instanceof Float32Array)) {\n return fixLength(values.values, values.targetSize, values.padValue);\n }\n return requireModule().fixLength(values, targetSize as number, padValue);\n}\n\nexport function fixFrames(request: FixFramesRequest): Int32Array;\nexport function fixFrames(\n frames: Int32Array,\n xMin?: number,\n xMax?: number,\n pad?: boolean,\n): Int32Array;\nexport function fixFrames(\n frames: Int32Array | FixFramesRequest,\n xMin = 0,\n xMax = -1,\n pad = true,\n): Int32Array {\n if (!(frames instanceof Int32Array)) {\n return fixFrames(frames.frames, frames.xMin, frames.xMax, frames.pad);\n }\n return requireModule().fixFrames(frames, xMin, xMax, pad);\n}\n\nexport function onsetBacktrack(request: OnsetBacktrackRequest): Int32Array;\nexport function onsetBacktrack(events: Int32Array, energy: Float32Array): Int32Array;\nexport function onsetBacktrack(\n events: Int32Array | OnsetBacktrackRequest,\n energy?: Float32Array,\n): Int32Array {\n if (!(events instanceof Int32Array)) {\n return onsetBacktrack(events.events, events.energy);\n }\n return requireModule().onsetBacktrack(events, energy as Float32Array);\n}\n\nexport function peakPick(request: PeakPickRequest): Int32Array;\nexport function peakPick(\n values: Float32Array,\n preMax: number,\n postMax: number,\n preAvg: number,\n postAvg: number,\n delta: number,\n wait: number,\n): Int32Array;\nexport function peakPick(\n values: Float32Array | PeakPickRequest,\n preMax?: number,\n postMax?: number,\n preAvg?: number,\n postAvg?: number,\n delta?: number,\n wait?: number,\n): Int32Array {\n if (!(values instanceof Float32Array)) {\n const r = values;\n return peakPick(r.values, r.preMax, r.postMax, r.preAvg, r.postAvg, r.delta, r.wait);\n }\n return requireModule().peakPick(\n values,\n preMax as number,\n postMax as number,\n preAvg as number,\n postAvg as number,\n delta as number,\n wait as number,\n );\n}\n\nexport function vectorNormalize(request: VectorNormalizeRequest): Float32Array;\nexport function vectorNormalize(\n values: Float32Array,\n normType?: number,\n threshold?: number,\n): Float32Array;\nexport function vectorNormalize(\n values: Float32Array | VectorNormalizeRequest,\n normType = 0,\n threshold = 0.0,\n): Float32Array {\n if (!(values instanceof Float32Array)) {\n return vectorNormalize(values.values, values.normType, values.threshold);\n }\n return requireModule().vectorNormalize(values, normType, threshold);\n}\n\nexport function pcen(request: PcenRequest): Float32Array;\nexport function pcen(\n values: Float32Array,\n nBins: number,\n nFrames: number,\n options?: Record<string, number>,\n): Float32Array;\nexport function pcen(\n values: Float32Array | PcenRequest,\n nBins = 0,\n nFrames = 0,\n options: Record<string, number> = {},\n): Float32Array {\n if (!(values instanceof Float32Array)) {\n const r = values;\n const {\n values: requestValues,\n nBins: requestBins,\n nFrames: requestFrames,\n options: legacyOptions,\n ...flatOptions\n } = r;\n return pcen(requestValues, requestBins, requestFrames, {\n ...legacyOptions,\n ...flatOptions,\n });\n }\n return requireModule().pcen(values, nBins, nFrames, options);\n}\n\nexport function tonnetz(request: TonnetzRequest): Float32Array;\nexport function tonnetz(chromagram: Float32Array, nChroma: number, nFrames: number): Float32Array;\nexport function tonnetz(\n chromagram: Float32Array | TonnetzRequest,\n nChroma?: number,\n nFrames?: number,\n): Float32Array {\n if (!(chromagram instanceof Float32Array)) {\n return tonnetz(chromagram.chromagram, chromagram.nChroma, chromagram.nFrames);\n }\n return requireModule().tonnetz(chromagram, nChroma as number, nFrames as number);\n}\n\nexport function tempogram(request: TempogramRequest): WasmTempogramResult;\nexport function tempogram(\n onsetEnvelope: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n winLength?: number,\n mode?: TempogramMode,\n center?: boolean,\n norm?: boolean,\n): WasmTempogramResult;\nexport function tempogram(\n onsetEnvelope: Float32Array | TempogramRequest,\n sampleRate = 22050,\n hopLength = 512,\n winLength = 384,\n mode: TempogramMode = 'autocorrelation',\n center = true,\n norm = true,\n): WasmTempogramResult {\n if (!(onsetEnvelope instanceof Float32Array)) {\n const r = onsetEnvelope;\n return tempogram(\n r.onsetEnvelope,\n r.sampleRate,\n r.hopLength,\n r.winLength,\n r.mode,\n r.center,\n r.norm,\n );\n }\n return requireModule().tempogram(\n onsetEnvelope,\n sampleRate,\n hopLength,\n winLength,\n mode,\n center,\n norm,\n );\n}\n\nexport function cyclicTempogram(request: CyclicTempogramRequest): WasmCyclicTempogramResult;\nexport function cyclicTempogram(\n onsetEnvelope: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n winLength?: number,\n bpmMin?: number,\n nBins?: number,\n): WasmCyclicTempogramResult;\nexport function cyclicTempogram(\n onsetEnvelope: Float32Array | CyclicTempogramRequest,\n sampleRate = 22050,\n hopLength = 512,\n winLength = 384,\n bpmMin = 60.0,\n nBins = 60,\n): WasmCyclicTempogramResult {\n if (!(onsetEnvelope instanceof Float32Array)) {\n const r = onsetEnvelope;\n return cyclicTempogram(\n r.onsetEnvelope,\n r.sampleRate,\n r.hopLength,\n r.winLength,\n r.bpmMin,\n r.nBins,\n );\n }\n return requireModule().cyclicTempogram(\n onsetEnvelope,\n sampleRate,\n hopLength,\n winLength,\n bpmMin,\n nBins,\n );\n}\n\nexport function plp(request: PlpRequest): Float32Array;\nexport function plp(\n onsetEnvelope: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n tempoMin?: number,\n tempoMax?: number,\n winLength?: number,\n): Float32Array;\nexport function plp(\n onsetEnvelope: Float32Array | PlpRequest,\n sampleRate = 22050,\n hopLength = 512,\n tempoMin = 30.0,\n tempoMax = 300.0,\n winLength = 384,\n): Float32Array {\n if (!(onsetEnvelope instanceof Float32Array)) {\n const r = onsetEnvelope;\n return plp(r.onsetEnvelope, r.sampleRate, r.hopLength, r.tempoMin, r.tempoMax, r.winLength);\n }\n return requireModule().plp(onsetEnvelope, sampleRate, hopLength, tempoMin, tempoMax, winLength);\n}\n","/**\n * Source decomposition and self-similarity segmentation: NMF factorisation and\n * the masks built over it, and the recurrence structure of a track.\n */\n\nimport { resolveFftOptions } from './_fft_options';\nimport { getSonareModule } from './module_state';\nimport type { SegmentMatrix } from './public_types';\nimport type {\n WasmDecomposeResult,\n WasmHpssWithResidualResult,\n WasmMatrix2dResult,\n} from './sonare.js';\nimport {\n assertHpssKernels,\n assertNonNegativeInteger,\n assertPositiveInteger,\n assertSamples,\n toInt32Array,\n} from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\nfunction resolveHardMask(fnName: string, value: unknown): boolean {\n if (value === undefined) {\n return false;\n }\n if (typeof value !== 'boolean') {\n throw new TypeError(`${fnName}: hardMask must be a boolean`);\n }\n return value;\n}\n\nexport interface DecomposeRequest {\n s: Float32Array;\n nFeatures: number;\n nFrames: number;\n nComponents: number;\n nIter?: number;\n beta?: number;\n}\n\nexport interface DecomposeWithInitRequest extends DecomposeRequest {\n init?: 'random' | 'nndsvd';\n}\n\nexport interface NnFilterRequest {\n s: Float32Array;\n nFeatures: number;\n nFrames: number;\n aggregate?: string;\n k?: number;\n width?: number;\n}\n\nexport interface SegmentCrossSimilarityRequest {\n x: Float32Array;\n xRows: number;\n xCols: number;\n y: Float32Array;\n yRows: number;\n yCols: number;\n k?: number;\n metric?: 'cosine' | 'euclidean';\n mode?: 'connectivity' | 'affinity';\n}\n\nexport interface SegmentRecurrenceMatrixRequest {\n data: Float32Array;\n rows: number;\n cols: number;\n k?: number;\n width?: number;\n sym?: boolean;\n metric?: 'cosine' | 'euclidean';\n mode?: 'connectivity' | 'affinity';\n}\n\nexport interface SegmentRecurrenceToLagRequest {\n recurrence: Float32Array;\n n: number;\n pad?: boolean;\n}\n\nexport interface SegmentLagToRecurrenceRequest {\n lag: Float32Array;\n rows: number;\n lags: number;\n}\n\nexport interface SegmentSubsegmentRequest {\n data: Float32Array;\n rows: number;\n cols: number;\n boundaries: Int32Array;\n nSegments?: number;\n}\n\nexport interface SegmentAgglomerativeRequest {\n data: Float32Array;\n rows: number;\n cols: number;\n k: number;\n linkage?: 'average' | 'single' | 'complete' | 'ward';\n}\n\nexport interface SegmentPathEnhanceRequest {\n recurrence: Float32Array;\n n: number;\n win: number;\n maxRatio?: number;\n minRatio?: number;\n nFilters?: number;\n}\n\nfunction validateSegmentMatrix(\n fnName: string,\n data: Float32Array,\n rows: number,\n cols: number,\n dataName: string,\n): void {\n assertPositiveInteger(fnName, rows, 'rows');\n assertPositiveInteger(fnName, cols, 'cols');\n assertSamples(fnName, data, true, dataName);\n const expected = rows * cols;\n if (!Number.isSafeInteger(expected) || data.length !== expected) {\n throw new RangeError(`${fnName}: ${dataName} length must equal rows * cols`);\n }\n}\n\nexport interface RemixRequest {\n samples: Float32Array;\n intervals: Int32Array | ArrayLike<number>;\n sampleRate?: number;\n alignZeros?: boolean;\n}\n\nexport interface HpssWithResidualRequest {\n samples: Float32Array;\n sampleRate?: number;\n /**\n * Horizontal median filter size, in STFT frames: a positive odd integer at\n * most 524287. Default 31. The ceiling is 524288 and an even kernel is\n * refused, so 524287 is the largest legal value.\n */\n kernelHarmonic?: number;\n /** Vertical median filter size, in STFT bins, under the same rule. Default 31. */\n kernelPercussive?: number;\n nFft?: number;\n hopLength?: number;\n hardMask?: boolean;\n}\n\n/**\n * Non-negative matrix factorisation of a flattened [nFeatures x nFrames]\n * spectrogram (librosa.decompose.decompose). Returns the W and H factors.\n */\nexport function decompose(request: DecomposeRequest): WasmDecomposeResult;\nexport function decompose(\n s: Float32Array,\n nFeatures: number,\n nFrames: number,\n nComponents: number,\n nIter?: number,\n beta?: number,\n): WasmDecomposeResult;\nexport function decompose(\n s: Float32Array | DecomposeRequest,\n nFeatures = 0,\n nFrames = 0,\n nComponents = 0,\n nIter = 50,\n beta = 2.0,\n): WasmDecomposeResult {\n if (!(s instanceof Float32Array)) {\n const request = s;\n return decompose(\n request.s,\n request.nFeatures,\n request.nFrames,\n request.nComponents,\n request.nIter,\n request.beta,\n );\n }\n return requireModule().decompose(s, nFeatures, nFrames, nComponents, nIter, beta);\n}\n\n/**\n * Non-negative matrix factorisation with a selectable initialiser\n * (librosa.decompose.decompose, `init`). Identical to {@link decompose} but\n * exposes the initialisation strategy: `'random'` (default, deterministic seed)\n * or `'nndsvd'` (SVD-based warm start, which tends to converge in fewer\n * iterations). Returns the W and H factors.\n */\nexport function decomposeWithInit(request: DecomposeWithInitRequest): WasmDecomposeResult;\nexport function decomposeWithInit(\n s: Float32Array,\n nFeatures: number,\n nFrames: number,\n nComponents: number,\n nIter?: number,\n beta?: number,\n init?: 'random' | 'nndsvd',\n): WasmDecomposeResult;\nexport function decomposeWithInit(\n s: Float32Array | DecomposeWithInitRequest,\n nFeatures = 0,\n nFrames = 0,\n nComponents = 0,\n nIter = 50,\n beta = 2.0,\n init: 'random' | 'nndsvd' = 'random',\n): WasmDecomposeResult {\n if (!(s instanceof Float32Array)) {\n const request = s;\n return decomposeWithInit(\n request.s,\n request.nFeatures,\n request.nFrames,\n request.nComponents,\n request.nIter,\n request.beta,\n request.init,\n );\n }\n return requireModule().decomposeWithInit(s, nFeatures, nFrames, nComponents, nIter, beta, init);\n}\n\n/** Options for {@link decomposeStems}. */\nexport interface DecomposeStemsRequest {\n samples: Float32Array;\n sampleRate: number;\n /** Number of NMF components (default 4). */\n nComponents?: number;\n /** STFT size (default 2048). */\n nFft?: number;\n /** STFT hop (default 512). */\n hopLength?: number;\n /** NMF multiplicative-update iterations (default 100). */\n nIter?: number;\n /** Beta divergence: 2 = Frobenius (default), 1 = Kullback-Leibler. */\n beta?: number;\n /** NMF initialisation (default `'random'`). */\n init?: 'random' | 'nndsvd';\n /**\n * Soft-mask exponent (default 1). 1 keeps the magnitude ratio; 2 is the\n * Wiener-style power ratio, which separates harder at the cost of more\n * artefacts on overlapping partials. Must be >= 1.\n */\n maskPower?: number;\n}\n\n/** One time-domain signal per NMF component, plus the factorisation. */\nexport interface DecomposeStemsResult {\n /** Component signals, each the length of the input. */\n components: Float32Array[];\n /** Component matrix [nBins x nComponents], row-major. */\n w: Float32Array;\n /** Activation matrix [nComponents x nFrames], row-major. */\n h: Float32Array;\n sampleRate: number;\n}\n\n/**\n * NMF separation that **carries the original phase**, so each component is\n * directly listenable.\n *\n * {@link decompose} returns the W/H factors of a magnitude spectrogram, which\n * have no phase; reconstructing from them needs a phase estimator\n * ({@link griffinLim}), and an estimated phase does not hold up as a stem. This\n * instead builds a per-component soft mask from the factorisation and applies\n * it to the original complex spectrogram. The masks sum to one wherever the\n * model has energy and the inverse STFT is linear, so the components sum back\n * to the input.\n */\nexport function decomposeStems(request: DecomposeStemsRequest): DecomposeStemsResult {\n return requireModule().decomposeStems(request.samples, request.sampleRate, {\n nComponents: request.nComponents,\n nFft: request.nFft,\n hopLength: request.hopLength,\n nIter: request.nIter,\n beta: request.beta,\n init: request.init,\n maskPower: request.maskPower,\n });\n}\n\n/** Request form of {@link decomposeStemsLinked}. */\nexport interface DecomposeStemsLinkedRequest {\n /** At least one channel; all the same length. */\n channels: Float32Array[];\n sampleRate?: number;\n /** Number of NMF components (default 4). */\n nComponents?: number;\n /** STFT size (default 2048). */\n nFft?: number;\n /** STFT hop (default 512). */\n hopLength?: number;\n /** NMF multiplicative-update iterations (default 100). */\n nIter?: number;\n /** Beta divergence: 2 = Frobenius (default), 1 = Kullback-Leibler. */\n beta?: number;\n /** NMF initialisation (default `'random'`). */\n init?: 'random' | 'nndsvd';\n /** Soft-mask exponent (default 1); see {@link DecomposeStemsRequest.maskPower}. */\n maskPower?: number;\n}\n\n/** One time-domain signal per (component, channel), plus the factorisation. */\nexport interface DecomposeStemsLinkedResult {\n /**\n * Component signals: `components[k][c]` is component `k`'s signal on\n * channel `c`, each the length of the input.\n */\n components: Float32Array[][];\n /** Component matrix [nBins x nComponents], row-major. */\n w: Float32Array;\n /** Activation matrix [nComponents x nFrames], row-major. */\n h: Float32Array;\n sampleRate: number;\n}\n\n/**\n * Multi-channel form of {@link decomposeStems}: one NMF model and one soft\n * mask shared across every channel, built from the channels' averaged\n * magnitude spectrogram and applied UNCHANGED to each channel's own complex\n * spectrum, so no interchannel level or phase difference moves. A single\n * channel reproduces {@link decomposeStems} bit for bit.\n *\n * @throws On a null/empty channel set, mismatched channel lengths, a channel\n * count above the core's ceiling, or an invalid option.\n */\nexport function decomposeStemsLinked(\n request: DecomposeStemsLinkedRequest,\n): DecomposeStemsLinkedResult {\n return requireModule().decomposeStemsLinked(request.channels, request.sampleRate ?? 22050, {\n nComponents: request.nComponents,\n nFft: request.nFft,\n hopLength: request.hopLength,\n nIter: request.nIter,\n beta: request.beta,\n init: request.init,\n maskPower: request.maskPower,\n });\n}\n\n/**\n * Nearest-neighbour filtering of a flattened [nFeatures x nFrames] spectrogram\n * (librosa.decompose.nn_filter).\n */\nexport function nnFilter(request: NnFilterRequest): WasmMatrix2dResult;\nexport function nnFilter(\n s: Float32Array,\n nFeatures: number,\n nFrames: number,\n aggregate?: string,\n k?: number,\n width?: number,\n): WasmMatrix2dResult;\nexport function nnFilter(\n s: Float32Array | NnFilterRequest,\n nFeatures = 0,\n nFrames = 0,\n aggregate = 'mean',\n k = 7,\n width = 1,\n): WasmMatrix2dResult {\n if (!(s instanceof Float32Array)) {\n const r = s;\n return nnFilter(r.s, r.nFeatures, r.nFrames, r.aggregate, r.k, r.width);\n }\n return requireModule().nnFilter(s, nFeatures, nFrames, aggregate, k, width);\n}\n\n/**\n * Reorder/concatenate a signal by interval slices (librosa.effects.remix).\n *\n * With `alignZeros` the boundaries snap to the signal's zero-crossings. That is\n * a per-signal decision, so calling this per channel snaps each channel to a\n * different frame and drifts a stereo take apart; resolve one cut set with\n * {@link remixAlignedIntervals} and apply it to every channel instead.\n *\n * @param intervals - Flat (start, end) sample pairs (even length).\n */\nexport function remix(request: RemixRequest): Float32Array;\nexport function remix(\n samples: Float32Array,\n intervals: Int32Array | ArrayLike<number>,\n sampleRate?: number,\n alignZeros?: boolean,\n): Float32Array;\nexport function remix(\n samples: Float32Array | RemixRequest,\n intervals?: Int32Array | ArrayLike<number>,\n sampleRate = 22050,\n alignZeros = false,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return remix(r.samples, r.intervals, r.sampleRate, r.alignZeros);\n }\n // Sample indices must reach the native side as exact 32-bit integers, and a\n // boundary the conversion changed would cut the slice somewhere the caller\n // never named.\n const intervalsI32 = toInt32Array('remix', intervals as ArrayLike<number>, 'intervals');\n return requireModule().remix(samples, intervalsI32, sampleRate, alignZeros);\n}\n\n/**\n * Resolve the cut points {@link remix} would use, without cutting.\n *\n * Returns a flat `Int32Array` of one clamped `(start, end)` pair per input\n * interval. With `alignZeros` each boundary snaps to the nearest zero-crossing,\n * with two guards that stop a slice from vanishing: a signal with no sign\n * change at all (silence, a DC offset, any constant) is not snapped, and a\n * slice that had content but collapses to empty after snapping keeps its\n * unsnapped boundaries.\n *\n * Use this to cut a multichannel take on one common frame set: resolve once\n * from one channel, then slice every channel with the returned pairs.\n *\n * @param intervals - Flat (start, end) sample pairs (even length).\n */\nexport function remixAlignedIntervals(request: RemixRequest): Int32Array;\nexport function remixAlignedIntervals(\n samples: Float32Array,\n intervals: Int32Array | ArrayLike<number>,\n sampleRate?: number,\n alignZeros?: boolean,\n): Int32Array;\nexport function remixAlignedIntervals(\n samples: Float32Array | RemixRequest,\n intervals?: Int32Array | ArrayLike<number>,\n sampleRate = 22050,\n alignZeros = true,\n): Int32Array {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return remixAlignedIntervals(r.samples, r.intervals, r.sampleRate, r.alignZeros ?? true);\n }\n const intervalsI32 = toInt32Array(\n 'remixAlignedIntervals',\n intervals as ArrayLike<number>,\n 'intervals',\n );\n return requireModule().remixAlignedIntervals(samples, intervalsI32, sampleRate, alignZeros);\n}\n\n/**\n * HPSS into harmonic / percussive / residual signals.\n *\n * The three outputs always add back up to the input. `residual` is silent under\n * the default soft mask, whose two masks sum to one, so `harmonic` and\n * `percussive` already carry everything; it is returned anyway so the result\n * shape does not change with the mask. Pass `hardMask: true` for a residual that\n * holds signal — its thresholded masks leave the band where neither component\n * dominates, measured at 3 % of the input energy on a voice-plus-kick signal.\n *\n * @example\n * ```ts\n * const soft = hpssWithResidual({ samples, sampleRate });\n * // soft.residual is silence\n * const hard = hpssWithResidual({ samples, sampleRate, hardMask: true });\n * // hard.residual carries what neither component claimed\n * ```\n *\n * @throws SonareError (`InvalidParameter`) on a kernel that is not an integer\n * within the signed 32-bit range, or one the core rejects as even,\n * non-positive or above its ceiling\n */\nexport function hpssWithResidual(request: HpssWithResidualRequest): WasmHpssWithResidualResult;\nexport function hpssWithResidual(\n samples: Float32Array,\n sampleRate?: number,\n kernelHarmonic?: number,\n kernelPercussive?: number,\n nFft?: number,\n hopLength?: number,\n hardMask?: boolean,\n): WasmHpssWithResidualResult;\nexport function hpssWithResidual(\n samples: Float32Array | HpssWithResidualRequest,\n sampleRate = 22050,\n kernelHarmonic = 31,\n kernelPercussive = 31,\n nFft?: number,\n hopLength?: number,\n hardMask?: boolean,\n): WasmHpssWithResidualResult {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return hpssWithResidual(\n r.samples,\n r.sampleRate,\n r.kernelHarmonic,\n r.kernelPercussive,\n r.nFft,\n r.hopLength,\n r.hardMask,\n );\n }\n const fftOptions = resolveFftOptions('hpssWithResidual', nFft, hopLength);\n const resolvedHardMask = resolveHardMask('hpssWithResidual', hardMask);\n assertHpssKernels('hpssWithResidual', kernelHarmonic, kernelPercussive);\n return requireModule().hpssWithResidualEx(\n samples,\n sampleRate,\n kernelHarmonic,\n kernelPercussive,\n fftOptions.nFft,\n fftOptions.hopLength,\n resolvedHardMask,\n );\n}\n\n/** Column-wise cross-similarity (librosa.segment.cross_similarity). */\nexport function segmentCrossSimilarity(request: SegmentCrossSimilarityRequest): SegmentMatrix {\n validateSegmentMatrix('segmentCrossSimilarity', request.x, request.xRows, request.xCols, 'x');\n validateSegmentMatrix('segmentCrossSimilarity', request.y, request.yRows, request.yCols, 'y');\n if (request.xRows !== request.yRows) {\n throw new RangeError('segmentCrossSimilarity: feature dimensions must match');\n }\n assertNonNegativeInteger('segmentCrossSimilarity', request.k ?? 0, 'k');\n return requireModule().segmentCrossSimilarity(\n request.x,\n request.xRows,\n request.xCols,\n request.y,\n request.yRows,\n request.yCols,\n request.k ?? 0,\n request.metric ?? 'cosine',\n request.mode ?? 'connectivity',\n );\n}\n\n/** Self-similarity recurrence matrix (librosa.segment.recurrence_matrix). */\nexport function segmentRecurrenceMatrix(request: SegmentRecurrenceMatrixRequest): SegmentMatrix {\n validateSegmentMatrix(\n 'segmentRecurrenceMatrix',\n request.data,\n request.rows,\n request.cols,\n 'data',\n );\n assertNonNegativeInteger('segmentRecurrenceMatrix', request.k ?? 0, 'k');\n assertNonNegativeInteger('segmentRecurrenceMatrix', request.width ?? 1, 'width');\n return requireModule().segmentRecurrenceMatrix(\n request.data,\n request.rows,\n request.cols,\n request.k ?? 0,\n request.width ?? 1,\n request.sym ?? false,\n request.metric ?? 'euclidean',\n request.mode ?? 'connectivity',\n );\n}\n\n/** Convert an `n × n` recurrence matrix to a lag matrix. */\nexport function segmentRecurrenceToLag(request: SegmentRecurrenceToLagRequest): SegmentMatrix {\n validateSegmentMatrix(\n 'segmentRecurrenceToLag',\n request.recurrence,\n request.n,\n request.n,\n 'recurrence',\n );\n return requireModule().segmentRecurrenceToLag(\n request.recurrence,\n request.n,\n request.pad ?? false,\n );\n}\n\n/** Convert a lag matrix back to an `n × n` recurrence matrix. */\nexport function segmentLagToRecurrence(request: SegmentLagToRecurrenceRequest): SegmentMatrix {\n validateSegmentMatrix('segmentLagToRecurrence', request.lag, request.rows, request.lags, 'lag');\n return requireModule().segmentLagToRecurrence(request.lag, request.rows, request.lags);\n}\n\n/** Refine frame boundaries by clustering within each parent segment. */\nexport function segmentSubsegment(request: SegmentSubsegmentRequest): Int32Array {\n validateSegmentMatrix('segmentSubsegment', request.data, request.rows, request.cols, 'data');\n assertPositiveInteger('segmentSubsegment', request.nSegments ?? 4, 'nSegments');\n return requireModule().segmentSubsegment(\n request.data,\n request.rows,\n request.cols,\n request.boundaries,\n request.nSegments ?? 4,\n );\n}\n\n/** Cluster feature columns and return one label per column. */\nexport function segmentAgglomerative(request: SegmentAgglomerativeRequest): Int32Array {\n validateSegmentMatrix('segmentAgglomerative', request.data, request.rows, request.cols, 'data');\n assertPositiveInteger('segmentAgglomerative', request.k, 'k');\n return requireModule().segmentAgglomerative(\n request.data,\n request.rows,\n request.cols,\n request.k,\n request.linkage ?? 'average',\n );\n}\n\n/** Enhance diagonal paths in an `n × n` recurrence matrix. */\nexport function segmentPathEnhance(request: SegmentPathEnhanceRequest): SegmentMatrix {\n validateSegmentMatrix(\n 'segmentPathEnhance',\n request.recurrence,\n request.n,\n request.n,\n 'recurrence',\n );\n assertPositiveInteger('segmentPathEnhance', request.win, 'win');\n assertPositiveInteger('segmentPathEnhance', request.maxRatio ?? 2, 'maxRatio');\n assertNonNegativeInteger('segmentPathEnhance', request.minRatio ?? 0, 'minRatio');\n assertPositiveInteger('segmentPathEnhance', request.nFilters ?? 7, 'nFilters');\n return requireModule().segmentPathEnhance(\n request.recurrence,\n request.n,\n request.win,\n request.maxRatio ?? 2,\n request.minRatio ?? 0,\n request.nFilters ?? 7,\n );\n}\n","/**\n * Input checks the spectrogram and inverse-transform entries share.\n */\n\nimport type { ValidateOptions } from './validation';\nimport { assertFiniteScalar, assertPositiveInteger } from './validation';\n\nexport type GuardedOptions = ValidateOptions;\n\nexport function validatePositiveIntegers(fnName: string, values: Record<string, number>): void {\n for (const [name, value] of Object.entries(values)) {\n assertPositiveInteger(fnName, value, name);\n }\n}\n\nexport function validateMelFrequencyRange(\n fnName: string,\n fmin: number,\n fmax: number,\n sampleRate: number,\n): void {\n assertFiniteScalar(fnName, fmin, 'fmin');\n assertFiniteScalar(fnName, fmax, 'fmax');\n if (fmin < 0) {\n throw new RangeError(`${fnName}: fmin must be non-negative`);\n }\n if (fmax < 0) {\n throw new RangeError(`${fnName}: fmax must be non-negative`);\n }\n const effectiveFmax = fmax === 0 ? sampleRate / 2 : fmax;\n if (effectiveFmax <= fmin) {\n throw new RangeError(`${fnName}: fmax must be greater than fmin`);\n }\n}\n","/**\n * Inverse transforms: reconstructing a linear spectrogram or audio from a mel\n * or MFCC representation, and the phase reconstruction they share.\n */\n\nimport type { GuardedOptions } from './_feature_validation';\nimport { validateMelFrequencyRange, validatePositiveIntegers } from './_feature_validation';\nimport { resolveFftOptions } from './_fft_options';\nimport type { SpectralFrameRequest } from './feature_spectral';\nimport { getSonareModule } from './module_state';\nimport type { MelPowerResult, StftPowerResult } from './public_types';\nimport { assertFiniteScalar, assertSampleRate, assertSamples } from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\nexport interface MfccToMelRequest extends GuardedOptions {\n mfccCoefficients: Float32Array;\n nMfcc: number;\n nFrames: number;\n nMels?: number;\n /** Lifter used by the forward MFCC transform; zero means no liftering. */\n lifter?: number;\n}\n\n/** Canonical request form for reconstruction from a Mel power spectrogram. */\nexport interface MelToStftRequest extends GuardedOptions {\n melPower: Float32Array;\n nMels: number;\n nFrames: number;\n sampleRate?: number;\n nFft?: number;\n fmin?: number;\n fmax?: number;\n htk?: boolean;\n}\n\n/** Canonical request form for Griffin-Lim reconstruction from Mel power. */\nexport interface MelToAudioRequest extends MelToStftRequest {\n hopLength?: number;\n nIter?: number;\n}\n\nexport interface GriffinLimRequest extends GuardedOptions {\n magnitude: Float32Array;\n nBins: number;\n nFrames: number;\n sampleRate?: number;\n nFft?: number;\n hopLength?: number;\n nIter?: number;\n momentum?: number;\n}\n\n/** Canonical request form for Griffin-Lim reconstruction from MFCCs. */\nexport interface MfccToAudioRequest extends MfccToMelRequest {\n sampleRate?: number;\n nFft?: number;\n hopLength?: number;\n fmin?: number;\n fmax?: number;\n nIter?: number;\n htk?: boolean;\n}\n\nfunction validateMatrix(\n fnName: string,\n data: Float32Array,\n rows: number,\n frames: number,\n dataName: string,\n rowName: string,\n options: GuardedOptions = {},\n): void {\n validatePositiveIntegers(fnName, { [rowName]: rows, nFrames: frames });\n assertSamples(fnName, data, options.validate !== false, dataName);\n const expectedLength = rows * frames;\n if (!Number.isSafeInteger(expectedLength) || data.length !== expectedLength) {\n throw new RangeError(`${fnName}: ${dataName} length must equal ${rowName} * nFrames`);\n }\n}\n\n/**\n * Approximate inverse of a Mel filterbank: Mel power spectrogram -> STFT power\n * spectrogram. Mirrors `feature::mel_to_stft`.\n *\n * @param melPower - Mel power spectrogram [nMels x nFrames] row-major\n * @param nMels - Number of Mel bands\n * @param nFrames - Number of time frames\n * @param sampleRate - Sample rate in Hz\n * @param nFft - FFT size (default: 2048)\n * @param fmin - Lower Mel band edge in Hz (default: 0)\n * @param fmax - Upper Mel band edge in Hz (default: sr/2 when 0)\n * @param htk - Use the HTK Mel formula instead of Slaney (default: false)\n * @returns STFT power spectrogram result\n */\nexport function melToStft(request: MelToStftRequest): StftPowerResult;\nexport function melToStft(\n melPower: Float32Array,\n nMels: number,\n nFrames: number,\n sampleRate?: number,\n nFft?: number,\n fmin?: number,\n fmax?: number,\n htk?: boolean,\n options?: GuardedOptions,\n): StftPowerResult;\nexport function melToStft(\n melPower: Float32Array | MelToStftRequest,\n nMels = 0,\n nFrames = 0,\n sampleRate = 22050,\n nFft = 2048,\n fmin = 0,\n fmax = 0,\n htk = false,\n options: GuardedOptions = {},\n): StftPowerResult {\n if (!(melPower instanceof Float32Array)) {\n const request = melPower;\n return melToStft(\n request.melPower,\n request.nMels,\n request.nFrames,\n request.sampleRate,\n request.nFft,\n request.fmin,\n request.fmax,\n request.htk,\n request,\n );\n }\n assertSampleRate('melToStft', sampleRate);\n validateMatrix('melToStft', melPower, nMels, nFrames, 'melPower', 'nMels', options);\n // Not on the shared FFT rule: this inverts a filterbank rather than running a\n // transform, so `nFft` only sizes the output to `nFft / 2 + 1` bins and an odd\n // size is accepted by the core and by the Node surface alike.\n validatePositiveIntegers('melToStft', { nFft });\n validateMelFrequencyRange('melToStft', fmin, fmax, sampleRate);\n return requireModule().melToStft(melPower, nMels, nFrames, sampleRate, nFft, fmin, fmax, htk);\n}\n\n/**\n * Reconstruct audio from a Mel power spectrogram via Griffin-Lim. Mirrors\n * `feature::mel_to_audio`.\n *\n * @param melPower - Mel power spectrogram [nMels x nFrames] row-major\n * @param nMels - Number of Mel bands\n * @param nFrames - Number of time frames\n * @param sampleRate - Sample rate in Hz\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum Mel frequency in Hz (default: 0)\n * @param fmax - Maximum Mel frequency in Hz (default: 0 = sr/2)\n * @param nIter - Griffin-Lim iterations (default: 32)\n * @param htk - Use the HTK Mel formula instead of Slaney (default: false)\n * @returns Reconstructed audio samples (mono, float32)\n */\nexport function melToAudio(request: MelToAudioRequest): Float32Array;\nexport function melToAudio(\n melPower: Float32Array,\n nMels: number,\n nFrames: number,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n fmin?: number,\n fmax?: number,\n nIter?: number,\n htk?: boolean,\n options?: GuardedOptions,\n): Float32Array;\nexport function melToAudio(\n melPower: Float32Array | MelToAudioRequest,\n nMels = 0,\n nFrames = 0,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n fmin = 0,\n fmax = 0,\n nIter = 32,\n htk = false,\n options: GuardedOptions = {},\n): Float32Array {\n if (!(melPower instanceof Float32Array)) {\n const request = melPower;\n return melToAudio(\n request.melPower,\n request.nMels,\n request.nFrames,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.fmin,\n request.fmax,\n request.nIter,\n request.htk,\n request,\n );\n }\n assertSampleRate('melToAudio', sampleRate);\n validateMatrix('melToAudio', melPower, nMels, nFrames, 'melPower', 'nMels', options);\n const fft = resolveFftOptions('melToAudio', nFft, hopLength);\n validatePositiveIntegers('melToAudio', { nIter });\n validateMelFrequencyRange('melToAudio', fmin, fmax, sampleRate);\n return requireModule().melToAudio(\n melPower,\n nMels,\n nFrames,\n sampleRate,\n fft.nFft,\n fft.hopLength,\n fmin,\n fmax,\n nIter,\n htk,\n );\n}\n\n/** Reconstruct audio from an STFT magnitude matrix via Griffin-Lim. */\nexport function griffinLim(request: GriffinLimRequest): Float32Array;\nexport function griffinLim(\n magnitude: Float32Array,\n nBins: number,\n nFrames: number,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n nIter?: number,\n momentum?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function griffinLim(\n magnitude: Float32Array | GriffinLimRequest,\n nBins = 0,\n nFrames = 0,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n nIter = 32,\n momentum = 0.99,\n options: GuardedOptions = {},\n): Float32Array {\n if (!(magnitude instanceof Float32Array)) {\n const request = magnitude;\n return griffinLim(\n request.magnitude,\n request.nBins,\n request.nFrames,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.nIter,\n request.momentum,\n request,\n );\n }\n assertSampleRate('griffinLim', sampleRate);\n validateMatrix('griffinLim', magnitude, nBins, nFrames, 'magnitude', 'nBins', options);\n const fft = resolveFftOptions('griffinLim', nFft, hopLength);\n validatePositiveIntegers('griffinLim', { nIter });\n return requireModule().griffinLim(\n magnitude,\n nBins,\n nFrames,\n sampleRate,\n fft.nFft,\n fft.hopLength,\n nIter,\n momentum,\n );\n}\n\n/**\n * Invert MFCC coefficients back to a Mel power spectrogram. Mirrors\n * `feature::mfcc_to_mel`.\n *\n * @param mfccCoefficients - MFCC matrix [nMfcc x nFrames] row-major\n * @param nMfcc - Number of MFCC coefficients\n * @param nFrames - Number of time frames\n * @param nMels - Number of Mel bins to reconstruct (default: 128)\n * @returns Mel power spectrogram result\n */\nexport function mfccToMel(request: MfccToMelRequest): MelPowerResult;\nexport function mfccToMel(\n mfccCoefficients: Float32Array,\n nMfcc: number,\n nFrames: number,\n nMels?: number,\n lifter?: number,\n options?: GuardedOptions,\n): MelPowerResult;\nexport function mfccToMel(\n mfccCoefficients: Float32Array | MfccToMelRequest,\n nMfcc = 0,\n nFrames = 0,\n nMels = 128,\n lifter = 0,\n options: GuardedOptions = {},\n): MelPowerResult {\n if (!(mfccCoefficients instanceof Float32Array)) {\n const request = mfccCoefficients;\n return mfccToMel(\n request.mfccCoefficients,\n request.nMfcc,\n request.nFrames,\n request.nMels,\n request.lifter,\n request,\n );\n }\n validateMatrix(\n 'mfccToMel',\n mfccCoefficients,\n nMfcc,\n nFrames,\n 'mfccCoefficients',\n 'nMfcc',\n options,\n );\n validatePositiveIntegers('mfccToMel', { nMels });\n return requireModule().mfccToMel(mfccCoefficients, nMfcc, nFrames, nMels, lifter);\n}\n\n/**\n * Reconstruct audio directly from MFCC coefficients via Griffin-Lim. Mirrors\n * `feature::mfcc_to_audio`.\n *\n * @param mfccCoefficients - MFCC matrix [nMfcc x nFrames] row-major\n * @param nMfcc - Number of MFCC coefficients\n * @param nFrames - Number of time frames\n * @param nMels - Number of Mel bins (default: 128)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum Mel frequency in Hz (default: 0)\n * @param fmax - Maximum Mel frequency in Hz (default: 0 = sr/2)\n * @param nIter - Griffin-Lim iterations (default: 32)\n * @param htk - Use the HTK Mel formula instead of Slaney (default: false)\n * @returns Reconstructed audio samples (mono, float32)\n */\nexport function mfccToAudio(request: MfccToAudioRequest): Float32Array;\nexport function mfccToAudio(\n mfccCoefficients: Float32Array,\n nMfcc: number,\n nFrames: number,\n nMels?: number,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n fmin?: number,\n fmax?: number,\n nIter?: number,\n htk?: boolean,\n lifter?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function mfccToAudio(\n mfccCoefficients: Float32Array | MfccToAudioRequest,\n nMfcc = 0,\n nFrames = 0,\n nMels = 128,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n fmin = 0,\n fmax = 0,\n nIter = 32,\n htk = false,\n lifter = 0,\n options: GuardedOptions = {},\n): Float32Array {\n if (!(mfccCoefficients instanceof Float32Array)) {\n const request = mfccCoefficients;\n return mfccToAudio(\n request.mfccCoefficients,\n request.nMfcc,\n request.nFrames,\n request.nMels,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.fmin,\n request.fmax,\n request.nIter,\n request.htk,\n request.lifter,\n request,\n );\n }\n assertSampleRate('mfccToAudio', sampleRate);\n validateMatrix(\n 'mfccToAudio',\n mfccCoefficients,\n nMfcc,\n nFrames,\n 'mfccCoefficients',\n 'nMfcc',\n options,\n );\n const fft = resolveFftOptions('mfccToAudio', nFft, hopLength);\n validatePositiveIntegers('mfccToAudio', { nMels, nIter });\n validateMelFrequencyRange('mfccToAudio', fmin, fmax, sampleRate);\n return requireModule().mfccToAudio(\n mfccCoefficients,\n nMfcc,\n nFrames,\n nMels,\n sampleRate,\n fft.nFft,\n fft.hopLength,\n fmin,\n fmax,\n nIter,\n htk,\n lifter,\n );\n}\n\nexport interface PhaseVocoderRequest extends SpectralFrameRequest {\n rate: number;\n}\n\n/**\n * Phase-vocoder time-scale modification (rate > 1 faster, < 1 slower).\n */\nexport function phaseVocoder(request: PhaseVocoderRequest): Float32Array;\nexport function phaseVocoder(\n samples: Float32Array,\n sampleRate: number,\n rate: number,\n nFft?: number,\n hopLength?: number,\n): Float32Array;\nexport function phaseVocoder(\n samples: Float32Array | PhaseVocoderRequest,\n sampleRate = 22050,\n rate = 1,\n nFft = 2048,\n hopLength = 512,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return phaseVocoder(r.samples, r.sampleRate ?? 22050, r.rate, r.nFft, r.hopLength);\n }\n // Matches the addon. A finite value too wide for a float is not covered here\n // and cannot be — it is still finite to Number.isFinite; the core's own guard\n // refuses the infinity it becomes.\n assertFiniteScalar('phaseVocoder', rate, 'rate');\n return requireModule().phaseVocoder(samples, sampleRate, rate, nFft, hopLength);\n}\n","/**\n * Programme loudness over interleaved audio, as the broadcast standards define\n * it.\n */\n\nimport { getSonareModule } from './module_state';\nimport type { WasmLufsResult, WasmLufsSeriesResult } from './sonare.js';\nimport type { ValidateOptions } from './validation';\nimport { assertInterleavedSamples, assertSampleRate } from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\nexport interface LufsInterleavedRequest extends ValidateOptions {\n samples: Float32Array;\n channels: number;\n sampleRate?: number;\n}\n\nexport interface LufsSeriesInterleavedRequest extends ValidateOptions {\n samples: Float32Array;\n channels: number;\n sampleRate?: number;\n}\n\nexport interface Ebur128LoudnessRangeRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\n/**\n * Channel-weighted multichannel integrated loudness + LRA (ITU-R BS.1770 /\n * EBU R128) from an interleaved buffer of `frames * channels` samples. The\n * per-channel frame count is derived from the buffer length and `channels`.\n *\n * Pass the buffer's actual `sampleRate`: the default (22050) is non-standard for\n * audio, and K-weighting is sample-rate dependent, so a wrong rate yields wrong\n * loudness.\n */\nexport function lufsInterleaved(request: LufsInterleavedRequest): WasmLufsResult;\nexport function lufsInterleaved(\n samples: Float32Array,\n channels: number,\n sampleRate?: number,\n options?: ValidateOptions,\n): WasmLufsResult;\nexport function lufsInterleaved(\n samples: Float32Array | LufsInterleavedRequest,\n channels = 0,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): WasmLufsResult {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return lufsInterleaved(r.samples, r.channels, r.sampleRate, r);\n }\n assertSampleRate('lufsInterleaved', sampleRate);\n assertInterleavedSamples('lufsInterleaved', samples, channels, options.validate !== false);\n return requireModule().lufsInterleaved(samples, channels, sampleRate);\n}\n\n/**\n * Per-block momentary (400 ms) and short-term (3 s) LUFS series for an\n * interleaved buffer of `frames * channels` samples, measured with ITU-R\n * BS.1770-4 channel summing. The per-channel frame count is derived from the\n * buffer length and `channels`.\n *\n * This is not recoverable from `momentaryLufs` / `shortTermLufs`: those measure\n * one channel each, and the standard sums the K-weighted per-channel block\n * energies rather than mixing per-channel loudness in dB. Both series come out\n * of one K-weighting pass. For `channels === 1` they match the mono meters\n * element for element.\n *\n * Pass the buffer's actual `sampleRate`: the default (22050) is non-standard for\n * audio, and K-weighting is sample-rate dependent, so a wrong rate yields wrong\n * loudness.\n *\n * @example\n * ```ts\n * const { momentary, shortTerm } = lufsSeriesInterleaved({\n * samples: interleavedStereo,\n * channels: 2,\n * sampleRate: 48000,\n * });\n * ```\n */\nexport function lufsSeriesInterleaved(request: LufsSeriesInterleavedRequest): WasmLufsSeriesResult;\nexport function lufsSeriesInterleaved(\n samples: Float32Array,\n channels: number,\n sampleRate?: number,\n options?: ValidateOptions,\n): WasmLufsSeriesResult;\nexport function lufsSeriesInterleaved(\n samples: Float32Array | LufsSeriesInterleavedRequest,\n channels = 0,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): WasmLufsSeriesResult {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return lufsSeriesInterleaved(r.samples, r.channels, r.sampleRate, r);\n }\n assertSampleRate('lufsSeriesInterleaved', sampleRate);\n assertInterleavedSamples('lufsSeriesInterleaved', samples, channels, options.validate !== false);\n return requireModule().lufsSeriesInterleaved(samples, channels, sampleRate);\n}\n\n/**\n * Standards-compliant EBU R128 loudness range (LRA) in LU. Pass the buffer's\n * actual `sampleRate`: the default (22050) is non-standard and K-weighting is\n * sample-rate dependent.\n */\nexport function ebur128LoudnessRange(request: Ebur128LoudnessRangeRequest): number;\nexport function ebur128LoudnessRange(samples: Float32Array, sampleRate?: number): number;\nexport function ebur128LoudnessRange(\n samples: Float32Array | Ebur128LoudnessRangeRequest,\n sampleRate = 22050,\n): number {\n if (!(samples instanceof Float32Array)) {\n return ebur128LoudnessRange(samples.samples, samples.sampleRate);\n }\n return requireModule().ebur128LoudnessRange(samples, sampleRate);\n}\n","import { validatePositiveIntegers } from './_feature_validation';\nimport { resolveFftOptions } from './_fft_options';\nimport { ErrorCode, SonareError } from './errors';\nimport { getSonareModule } from './module_state';\nimport type {\n AnalyzeSectionsOptions,\n BoundaryOptions,\n BoundaryResult,\n CqtResult,\n LufsResult,\n MelodyResult,\n OnsetStrengthMultiResult,\n Section,\n SectionType,\n} from './public_types';\nimport type { WasmFourierTempogramResult, WasmNnlsChromaResult } from './sonare.js';\nimport type { ValidateOptions } from './validation';\nimport {\n assertFiniteScalar,\n assertPositiveInteger,\n assertSampleRate,\n assertSamples,\n assertVqtGamma,\n} from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\ntype GuardedOptions = ValidateOptions;\ntype AnalyzeSectionsGuardedOptions = AnalyzeSectionsOptions & ValidateOptions;\ntype BoundaryGuardedOptions = BoundaryOptions & ValidateOptions;\ntype MelodyGuardedOptions = MelodyOptions & ValidateOptions;\n\n/** Canonical request form shared by the Constant-Q transform variants. */\nexport interface CqtRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n fmin?: number;\n nBins?: number;\n binsPerOctave?: number;\n}\n\n/** Canonical request form for {@link vqt}. */\nexport interface VqtRequest extends CqtRequest {\n gamma?: number;\n}\n\nexport interface OnsetEnvelopeRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n nFft?: number;\n hopLength?: number;\n nMels?: number;\n}\n\nexport interface OnsetStrengthMultiRequest extends OnsetEnvelopeRequest {\n nBands?: number;\n}\n\nexport interface FourierTempogramRequest extends GuardedOptions {\n onsetEnvelope: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n winLength?: number;\n center?: boolean;\n norm?: boolean;\n}\n\nexport interface TempogramRatioRequest extends GuardedOptions {\n tempogramData: Float32Array;\n winLength?: number;\n sampleRate?: number;\n hopLength?: number;\n factors?: Float32Array | number[];\n}\n\nexport interface CqtToAudioRequest extends GuardedOptions {\n magnitude: Float32Array;\n nBins: number;\n nFrames: number;\n sampleRate?: number;\n hopLength?: number;\n fmin?: number;\n binsPerOctave?: number;\n nIter?: number;\n}\n\nexport interface VqtToAudioRequest extends CqtToAudioRequest {\n gamma?: number;\n}\n\nexport interface AnalyzeSectionsRequest extends AnalyzeSectionsGuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n/** Canonical (and only) call form for {@link detectBoundaries}. */\nexport interface DetectBoundariesRequest extends BoundaryGuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\nexport interface AnalyzeMelodyRequest extends MelodyGuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\nexport interface LufsRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\nexport interface NnlsChromaRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n enableStftBlend?: boolean;\n stftBlendWeight?: number;\n stftBlendNFft?: number;\n hopLength?: number;\n}\n\nfunction validateMusicSamples(\n fnName: string,\n samples: Float32Array,\n sampleRate: number,\n options: GuardedOptions = {},\n): void {\n assertSampleRate(fnName, sampleRate);\n assertSamples(fnName, samples, options.validate !== false);\n}\n\nfunction validateFrequencyBounds(fnName: string, fmin: number, fmax?: number): void {\n assertFiniteScalar(fnName, fmin, 'fmin');\n if (fmin < 0) {\n throw new RangeError(`${fnName}: fmin must be non-negative`);\n }\n if (fmax !== undefined) {\n assertFiniteScalar(fnName, fmax, 'fmax');\n if (fmax <= fmin) {\n throw new RangeError(`${fnName}: fmax must be greater than fmin`);\n }\n }\n}\n\n/**\n * Compute NNLS (non-negative least squares) chromagram.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @returns NNLS chroma result\n */\nexport function nnlsChroma(request: NnlsChromaRequest): WasmNnlsChromaResult;\nexport function nnlsChroma(\n samples: Float32Array,\n sampleRate?: number,\n options?: Omit<NnlsChromaRequest, 'samples' | 'sampleRate'>,\n): WasmNnlsChromaResult;\nexport function nnlsChroma(\n samples: Float32Array | NnlsChromaRequest,\n sampleRate = 22050,\n options: Omit<NnlsChromaRequest, 'samples' | 'sampleRate'> = {},\n): WasmNnlsChromaResult {\n if (!(samples instanceof Float32Array)) {\n return nnlsChroma(samples.samples, samples.sampleRate, samples);\n }\n validateMusicSamples('nnlsChroma', samples, sampleRate, options);\n const hopLength = options.hopLength === undefined ? 512 : options.hopLength;\n assertPositiveInteger('nnlsChroma', hopLength, 'hopLength');\n if (hopLength > 2 ** 31 - 1) {\n throw new RangeError('nnlsChroma: hopLength must fit in a signed 32-bit integer');\n }\n return requireModule().nnlsChromaEx(\n samples,\n sampleRate,\n options.enableStftBlend ?? true,\n options.stftBlendWeight ?? 0.55,\n options.stftBlendNFft ?? 4096,\n hopLength,\n );\n}\n\n/**\n * Compute the Constant-Q Transform magnitude.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum frequency in Hz (default: 32.70319566257483, C1)\n * @param nBins - Number of frequency bins (default: 84)\n * @param binsPerOctave - Bins per octave (default: 12)\n * @returns CQT magnitude result\n */\nexport function cqt(request: CqtRequest): CqtResult;\nexport function cqt(\n samples: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n fmin?: number,\n nBins?: number,\n binsPerOctave?: number,\n options?: GuardedOptions,\n): CqtResult;\nexport function cqt(\n samples: Float32Array | CqtRequest,\n sampleRate = 22050,\n hopLength = 512,\n fmin = 32.70319566257483,\n nBins = 84,\n binsPerOctave = 12,\n options: GuardedOptions = {},\n): CqtResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return cqt(\n request.samples,\n request.sampleRate,\n request.hopLength,\n request.fmin,\n request.nBins,\n request.binsPerOctave,\n request,\n );\n }\n validateMusicSamples('cqt', samples, sampleRate, options);\n validatePositiveIntegers('cqt', { hopLength, nBins, binsPerOctave });\n validateFrequencyBounds('cqt', fmin);\n return requireModule().cqt(samples, sampleRate, hopLength, fmin, nBins, binsPerOctave);\n}\n\n/**\n * Compute the pseudo Constant-Q Transform magnitude.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum frequency in Hz (default: 32.70319566257483, C1)\n * @param nBins - Number of frequency bins (default: 84)\n * @param binsPerOctave - Bins per octave (default: 12)\n * @returns CQT magnitude result\n */\nexport function pseudoCqt(request: CqtRequest): CqtResult;\nexport function pseudoCqt(\n samples: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n fmin?: number,\n nBins?: number,\n binsPerOctave?: number,\n options?: GuardedOptions,\n): CqtResult;\nexport function pseudoCqt(\n samples: Float32Array | CqtRequest,\n sampleRate = 22050,\n hopLength = 512,\n fmin = 32.70319566257483,\n nBins = 84,\n binsPerOctave = 12,\n options: GuardedOptions = {},\n): CqtResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return pseudoCqt(\n request.samples,\n request.sampleRate,\n request.hopLength,\n request.fmin,\n request.nBins,\n request.binsPerOctave,\n request,\n );\n }\n validateMusicSamples('pseudoCqt', samples, sampleRate, options);\n validatePositiveIntegers('pseudoCqt', { hopLength, nBins, binsPerOctave });\n validateFrequencyBounds('pseudoCqt', fmin);\n return requireModule().pseudoCqt(samples, sampleRate, hopLength, fmin, nBins, binsPerOctave);\n}\n\n/**\n * Compute the hybrid Constant-Q Transform magnitude.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum frequency in Hz (default: 32.70319566257483, C1)\n * @param nBins - Number of frequency bins (default: 84)\n * @param binsPerOctave - Bins per octave (default: 12)\n * @returns CQT magnitude result\n */\nexport function hybridCqt(request: CqtRequest): CqtResult;\nexport function hybridCqt(\n samples: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n fmin?: number,\n nBins?: number,\n binsPerOctave?: number,\n options?: GuardedOptions,\n): CqtResult;\nexport function hybridCqt(\n samples: Float32Array | CqtRequest,\n sampleRate = 22050,\n hopLength = 512,\n fmin = 32.70319566257483,\n nBins = 84,\n binsPerOctave = 12,\n options: GuardedOptions = {},\n): CqtResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return hybridCqt(\n request.samples,\n request.sampleRate,\n request.hopLength,\n request.fmin,\n request.nBins,\n request.binsPerOctave,\n request,\n );\n }\n validateMusicSamples('hybridCqt', samples, sampleRate, options);\n validatePositiveIntegers('hybridCqt', { hopLength, nBins, binsPerOctave });\n validateFrequencyBounds('hybridCqt', fmin);\n return requireModule().hybridCqt(samples, sampleRate, hopLength, fmin, nBins, binsPerOctave);\n}\n\n/**\n * Compute the Variable-Q Transform magnitude (gamma controls Q).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum frequency in Hz (default: 32.70319566257483, C1)\n * @param nBins - Number of frequency bins (default: 84)\n * @param binsPerOctave - Bins per octave (default: 12)\n * @param gamma - Bandwidth offset; a negative value or NaN selects the automatic\n * ERB-derived value, while 0 is equivalent to CQT (default: -1)\n * @returns VQT magnitude result (same shape as CQT)\n */\nexport function vqt(request: VqtRequest): CqtResult;\nexport function vqt(\n samples: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n fmin?: number,\n nBins?: number,\n binsPerOctave?: number,\n gamma?: number,\n options?: GuardedOptions,\n): CqtResult;\nexport function vqt(\n samples: Float32Array | VqtRequest,\n sampleRate = 22050,\n hopLength = 512,\n fmin = 32.70319566257483,\n nBins = 84,\n binsPerOctave = 12,\n gamma = -1,\n options: GuardedOptions = {},\n): CqtResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return vqt(\n request.samples,\n request.sampleRate,\n request.hopLength,\n request.fmin,\n request.nBins,\n request.binsPerOctave,\n request.gamma,\n request,\n );\n }\n validateMusicSamples('vqt', samples, sampleRate, options);\n validatePositiveIntegers('vqt', { hopLength, nBins, binsPerOctave });\n validateFrequencyBounds('vqt', fmin);\n assertVqtGamma('vqt', gamma);\n return requireModule().vqt(samples, sampleRate, hopLength, fmin, nBins, binsPerOctave, gamma);\n}\n\nfunction validateCqtInverse(\n fnName: string,\n magnitude: Float32Array,\n nBins: number,\n nFrames: number,\n sampleRate: number,\n hopLength: number,\n fmin: number,\n binsPerOctave: number,\n nIter: number,\n options: GuardedOptions,\n): void {\n assertSampleRate(fnName, sampleRate);\n validatePositiveIntegers(fnName, { nBins, nFrames, hopLength, binsPerOctave, nIter });\n if (nIter > 256) {\n throw new RangeError(`${fnName}: nIter must be at most 256`);\n }\n validateFrequencyBounds(fnName, fmin);\n if (fmin === 0) {\n throw new RangeError(`${fnName}: fmin must be positive`);\n }\n if (magnitude.length !== nBins * nFrames) {\n throw new RangeError(`${fnName}: magnitude length must equal nBins * nFrames`);\n }\n assertSamples(fnName, magnitude, options.validate !== false);\n}\n\n/** Reconstruct mono audio from row-major CQT magnitude via Griffin-Lim. */\nexport function cqtToAudio(request: CqtToAudioRequest): Float32Array;\nexport function cqtToAudio(\n magnitude: Float32Array,\n nBins: number,\n nFrames: number,\n sampleRate?: number,\n hopLength?: number,\n fmin?: number,\n binsPerOctave?: number,\n nIter?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function cqtToAudio(\n magnitude: Float32Array | CqtToAudioRequest,\n nBins = 0,\n nFrames = 0,\n sampleRate = 22050,\n hopLength = 512,\n fmin = 32.70319566257483,\n binsPerOctave = 12,\n nIter = 32,\n options: GuardedOptions = {},\n): Float32Array {\n if (!(magnitude instanceof Float32Array)) {\n const request = magnitude;\n return cqtToAudio(\n request.magnitude,\n request.nBins,\n request.nFrames,\n request.sampleRate,\n request.hopLength,\n request.fmin,\n request.binsPerOctave,\n request.nIter,\n request,\n );\n }\n validateCqtInverse(\n 'cqtToAudio',\n magnitude,\n nBins,\n nFrames,\n sampleRate,\n hopLength,\n fmin,\n binsPerOctave,\n nIter,\n options,\n );\n return requireModule().cqtToAudio(\n magnitude,\n nBins,\n nFrames,\n sampleRate,\n hopLength,\n fmin,\n binsPerOctave,\n nIter,\n );\n}\n\n/** Reconstruct mono audio from row-major VQT magnitude via Griffin-Lim. */\nexport function vqtToAudio(request: VqtToAudioRequest): Float32Array;\nexport function vqtToAudio(\n magnitude: Float32Array,\n nBins: number,\n nFrames: number,\n sampleRate?: number,\n hopLength?: number,\n fmin?: number,\n binsPerOctave?: number,\n gamma?: number,\n nIter?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function vqtToAudio(\n magnitude: Float32Array | VqtToAudioRequest,\n nBins = 0,\n nFrames = 0,\n sampleRate = 22050,\n hopLength = 512,\n fmin = 32.70319566257483,\n binsPerOctave = 12,\n gamma = -1,\n nIter = 32,\n options: GuardedOptions = {},\n): Float32Array {\n if (!(magnitude instanceof Float32Array)) {\n const request = magnitude;\n return vqtToAudio(\n request.magnitude,\n request.nBins,\n request.nFrames,\n request.sampleRate,\n request.hopLength,\n request.fmin,\n request.binsPerOctave,\n request.gamma,\n request.nIter,\n request,\n );\n }\n validateCqtInverse(\n 'vqtToAudio',\n magnitude,\n nBins,\n nFrames,\n sampleRate,\n hopLength,\n fmin,\n binsPerOctave,\n nIter,\n options,\n );\n assertVqtGamma('vqtToAudio', gamma);\n return requireModule().vqtToAudio(\n magnitude,\n nBins,\n nFrames,\n sampleRate,\n hopLength,\n fmin,\n binsPerOctave,\n gamma,\n nIter,\n );\n}\n\n/**\n * Detect song-structure sections (intro/verse/chorus/...).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param minSectionSec - Minimum section duration in seconds (default: 4.0)\n * @returns Array of detected sections\n */\nexport function analyzeSections(request: AnalyzeSectionsRequest): Section[];\nexport function analyzeSections(\n samples: Float32Array,\n sampleRate?: number,\n options?: AnalyzeSectionsGuardedOptions,\n): Section[];\nexport function analyzeSections(\n samples: Float32Array | AnalyzeSectionsRequest,\n sampleRate = 22050,\n options: AnalyzeSectionsGuardedOptions = {},\n): Section[] {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return analyzeSections(r.samples, r.sampleRate, r);\n }\n validateMusicSamples('analyzeSections', samples, sampleRate, options);\n validatePositiveIntegers('analyzeSections', {\n nFft: options.nFft ?? 2048,\n hopLength: options.hopLength ?? 512,\n });\n assertFiniteScalar('analyzeSections', options.minSectionSec ?? 4.0, 'minSectionSec');\n if ((options.minSectionSec ?? 4.0) < 0) {\n throw new RangeError('analyzeSections: minSectionSec must be non-negative');\n }\n // The embind value marshalling returns an array whose constructor is not this\n // realm's Array; chaining .map() onto it propagates that constructor via\n // Symbol.species, leaving a result that structuredClone (and so postMessage to\n // a Worker) rejects with \"could not be cloned\". Array.from() re-roots it as a\n // plain Array before mapping.\n const sections = requireModule().analyzeSections(\n samples,\n sampleRate,\n options.nFft ?? 2048,\n options.hopLength ?? 512,\n options.minSectionSec ?? 4.0,\n );\n return Array.from(sections, (s) => ({ ...s, type: s.type as SectionType }));\n}\n\n/**\n * Detect structural boundaries and return the novelty curve behind them.\n *\n * This is the unlabelled layer {@link analyzeSections} is built on, not a\n * coarser view of its output: sections are labelled spans, these are the\n * transitions plus the continuous curve they were picked from, so a caller\n * applying its own threshold needs this and cannot derive it from a section\n * list.\n *\n * @param request - Samples, sample rate and {@link BoundaryOptions}\n * @returns The boundaries, the novelty curve, and the analysis grid they live on\n * @throws {@link SonareError} with `InvalidParameter` when both `useMfcc` and\n * `useChroma` are `false`: the two feature streams are combined frame-for-frame,\n * so with neither enabled there is nothing to combine.\n *\n * @example\n * ```ts\n * const { boundaries, noveltyCurve, noveltyPeak } = detectBoundaries({\n * samples,\n * sampleRate: 44100,\n * absoluteThreshold: 0.01,\n * });\n * // `noveltyCurve` is scaled by its own maximum; recover the raw response with\n * // `noveltyCurve[i] * noveltyPeak`.\n * ```\n */\nexport function detectBoundaries(request: DetectBoundariesRequest): BoundaryResult {\n const { samples, sampleRate = 22050 } = request;\n validateMusicSamples('detectBoundaries', samples, sampleRate, request);\n // The request IS the options bag: every field is read straight off it, so an\n // omitted one reaches the embind wrapper absent and takes BoundaryConfig's own\n // default. Restating the ten defaults here would make them the effective ones\n // on npm and leave the core's unreachable, and nothing compares the two.\n const sizes: Record<string, number> = {};\n for (const name of ['nFft', 'hopLength', 'kernelSize', 'nMfcc', 'nChroma'] as const) {\n const value = request[name];\n if (value != null) {\n sizes[name] = value;\n }\n }\n validatePositiveIntegers('detectBoundaries', sizes);\n for (const name of ['threshold', 'absoluteThreshold', 'peakDistance'] as const) {\n const value = request[name];\n if (value == null) {\n continue;\n }\n assertFiniteScalar('detectBoundaries', value, name);\n if (value < 0) {\n throw new RangeError(`detectBoundaries: ${name} must be non-negative`);\n }\n }\n // Only an explicit pair of falses; either one omitted leaves the other stream\n // on, so there is still something to combine.\n if (request.useMfcc === false && request.useChroma === false) {\n throw new SonareError(\n ErrorCode.InvalidParameter,\n 'InvalidParameter',\n 'detectBoundaries: require useMfcc or useChroma',\n );\n }\n const result = requireModule().detectBoundaries(samples, sampleRate, request);\n // Re-root the embind array as a plain Array, for the reason analyzeSections\n // spells out: chaining onto it propagates a constructor structuredClone\n // rejects, so a result posted from a Worker would fail to clone.\n return {\n boundaries: Array.from(result.boundaries, (b) => ({\n time: b.time,\n frame: b.frame,\n strength: b.strength,\n })),\n noveltyCurve: result.noveltyCurve,\n noveltyPeak: result.noveltyPeak,\n sampleRate: result.sampleRate,\n hopLength: result.hopLength,\n nFrames: result.nFrames,\n frameStride: result.frameStride,\n };\n}\n\n/** Options for {@link analyzeMelody}. All fields are optional. */\nexport interface MelodyOptions {\n /** Lowest f0 (Hz) the tracker will consider. Default 65 (≈ C2). */\n fmin?: number;\n /** Highest f0 (Hz) the tracker will consider. Default 2093 (≈ C7). */\n fmax?: number;\n /** Analysis frame length in samples. Default 2048. */\n frameLength?: number;\n /** Hop length between frames in samples. Default 256. */\n hopLength?: number;\n /** Voicing confidence threshold in [0,1]; frames below are unvoiced. Default 0.1. */\n threshold?: number;\n /**\n * Use the pYIN tracker (Viterbi-smoothed) instead of plain per-frame YIN.\n * Produces a less octave-jumpy contour. Defaults to `false`.\n */\n usePyin?: boolean;\n /**\n * When {@link usePyin} is `true`, zero-pad by `frameLength / 2` so frame\n * `i` is centered at `i * hopLength` (matches `librosa.pyin(center=True)`).\n * Ignored by the plain-YIN path. Defaults to `true`.\n */\n center?: boolean;\n}\n\n/**\n * Extract the melody contour from monophonic audio via YIN (or pYIN).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param options - Tracker + tuning options ({@link MelodyOptions})\n * @returns Melody contour with per-frame pitch points and summary stats\n */\nexport function analyzeMelody(request: AnalyzeMelodyRequest): MelodyResult;\nexport function analyzeMelody(\n samples: Float32Array,\n sampleRate?: number,\n options?: MelodyGuardedOptions,\n): MelodyResult;\nexport function analyzeMelody(\n samples: Float32Array | AnalyzeMelodyRequest,\n sampleRate = 22050,\n options: MelodyGuardedOptions = {},\n): MelodyResult {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return analyzeMelody(r.samples, r.sampleRate, r);\n }\n validateMusicSamples('analyzeMelody', samples, sampleRate, options);\n const fmin = options.fmin ?? 65.0;\n const fmax = options.fmax ?? 2093.0;\n validateFrequencyBounds('analyzeMelody', fmin, fmax);\n // The melody tracker's fmin is a YIN pitch floor: 0 is meaningless, and the\n // flat C ABI (sonare_analyze_melody) rejects it with InvalidParameter.\n // validateFrequencyBounds only guards fmin >= 0, so enforce strict positivity\n // here and report the same branded error the Node/Python surfaces raise.\n if (fmin <= 0) {\n throw new SonareError(\n ErrorCode.InvalidParameter,\n 'InvalidParameter',\n 'analyzeMelody: fmin must be positive',\n );\n }\n validatePositiveIntegers('analyzeMelody', {\n frameLength: options.frameLength ?? 2048,\n hopLength: options.hopLength ?? 256,\n });\n const threshold = options.threshold ?? 0.1;\n assertFiniteScalar('analyzeMelody', threshold, 'threshold');\n if (threshold <= 0) {\n throw new SonareError(\n ErrorCode.InvalidParameter,\n 'InvalidParameter',\n 'analyzeMelody: threshold must be positive',\n );\n }\n return requireModule().analyzeMelody(\n samples,\n sampleRate,\n options.fmin ?? 65.0,\n options.fmax ?? 2093.0,\n options.frameLength ?? 2048,\n options.hopLength ?? 256,\n options.threshold ?? 0.1,\n options.usePyin ?? false,\n options.center ?? true,\n );\n}\n\n/**\n * Compute the onset strength envelope.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param nMels - Number of Mel bands (default: 128)\n * @returns Onset envelope for each frame\n */\nexport function onsetEnvelope(request: OnsetEnvelopeRequest): Float32Array;\nexport function onsetEnvelope(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n nMels?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function onsetEnvelope(\n samples: Float32Array | OnsetEnvelopeRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n nMels = 128,\n options: GuardedOptions = {},\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return onsetEnvelope(\n request.samples,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.nMels,\n request,\n );\n }\n validateMusicSamples('onsetEnvelope', samples, sampleRate, options);\n const fft = resolveFftOptions('onsetEnvelope', nFft, hopLength);\n validatePositiveIntegers('onsetEnvelope', { nMels });\n return requireModule().onsetEnvelope(samples, sampleRate, fft.nFft, fft.hopLength, nMels);\n}\n\n/**\n * Compute multi-band onset strength envelopes.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param nMels - Number of Mel bands (default: 128)\n * @param nBands - Number of onset bands (default: 3)\n * @returns Multi-band onset matrix\n */\nexport function onsetStrengthMulti(request: OnsetStrengthMultiRequest): OnsetStrengthMultiResult;\nexport function onsetStrengthMulti(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n nMels?: number,\n nBands?: number,\n options?: GuardedOptions,\n): OnsetStrengthMultiResult;\nexport function onsetStrengthMulti(\n samples: Float32Array | OnsetStrengthMultiRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n nMels = 128,\n nBands = 3,\n options: GuardedOptions = {},\n): OnsetStrengthMultiResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return onsetStrengthMulti(\n request.samples,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.nMels,\n request.nBands,\n request,\n );\n }\n validateMusicSamples('onsetStrengthMulti', samples, sampleRate, options);\n const fft = resolveFftOptions('onsetStrengthMulti', nFft, hopLength);\n validatePositiveIntegers('onsetStrengthMulti', { nMels, nBands });\n return requireModule().onsetStrengthMulti(\n samples,\n sampleRate,\n fft.nFft,\n fft.hopLength,\n nMels,\n nBands,\n );\n}\n\n/**\n * Compute the Fourier tempogram from an onset envelope.\n *\n * @param onsetEnvelope - Onset strength envelope (float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param winLength - Window length in frames (default: 384)\n * @returns Fourier tempogram result\n */\nexport function fourierTempogram(request: FourierTempogramRequest): WasmFourierTempogramResult;\nexport function fourierTempogram(\n onsetEnvelope: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n winLength?: number,\n center?: boolean,\n norm?: boolean,\n options?: GuardedOptions,\n): WasmFourierTempogramResult;\nexport function fourierTempogram(\n onsetEnvelope: Float32Array | FourierTempogramRequest,\n sampleRate = 22050,\n hopLength = 512,\n winLength = 384,\n center = true,\n norm = true,\n options: GuardedOptions = {},\n): WasmFourierTempogramResult {\n if (!(onsetEnvelope instanceof Float32Array)) {\n const request = onsetEnvelope;\n return fourierTempogram(\n request.onsetEnvelope,\n request.sampleRate,\n request.hopLength,\n request.winLength,\n request.center,\n request.norm,\n request,\n );\n }\n assertSampleRate('fourierTempogram', sampleRate);\n assertSamples('fourierTempogram', onsetEnvelope, options.validate !== false, 'onsetEnvelope');\n validatePositiveIntegers('fourierTempogram', { hopLength, winLength });\n return requireModule().fourierTempogram(\n onsetEnvelope,\n sampleRate,\n hopLength,\n winLength,\n center,\n norm,\n );\n}\n\n/**\n * Compute tempogram ratio features.\n *\n * @param tempogramData - Tempogram data (float32)\n * @param winLength - Window length in frames (default: 384)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param factors - Lag ratios to evaluate. When omitted or empty, the library\n * default {0.5, 1, 2, 3, 4} is used.\n * @returns Tempogram ratio features (one value per factor)\n */\nexport function tempogramRatio(request: TempogramRatioRequest): Float32Array;\nexport function tempogramRatio(\n tempogramData: Float32Array,\n winLength?: number,\n sampleRate?: number,\n hopLength?: number,\n factors?: Float32Array | number[],\n options?: GuardedOptions,\n): Float32Array;\nexport function tempogramRatio(\n tempogramData: Float32Array | TempogramRatioRequest,\n winLength = 384,\n sampleRate = 22050,\n hopLength = 512,\n factors?: Float32Array | number[],\n options: GuardedOptions = {},\n): Float32Array {\n if (!(tempogramData instanceof Float32Array)) {\n const request = tempogramData;\n return tempogramRatio(\n request.tempogramData,\n request.winLength,\n request.sampleRate,\n request.hopLength,\n request.factors,\n request,\n );\n }\n assertSampleRate('tempogramRatio', sampleRate);\n assertSamples('tempogramRatio', tempogramData, options.validate !== false, 'tempogramData');\n validatePositiveIntegers('tempogramRatio', { winLength, hopLength });\n return requireModule().tempogramRatio(tempogramData, winLength, sampleRate, hopLength, factors);\n}\n\n/**\n * Measure loudness (EBU R128 / ITU-R BS.1770).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz. The default (22050) is non-standard for\n * audio; pass the buffer's actual rate, as K-weighting is sample-rate\n * dependent and a wrong rate yields wrong loudness.\n * @returns Loudness measurement result\n */\nexport function lufs(request: LufsRequest): LufsResult;\nexport function lufs(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): LufsResult;\nexport function lufs(\n samples: Float32Array | LufsRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): LufsResult {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return lufs(r.samples, r.sampleRate, r);\n }\n assertSampleRate('lufs', sampleRate);\n assertSamples('lufs', samples, options.validate !== false);\n return requireModule().lufs(samples, sampleRate);\n}\n\n/**\n * Compute the momentary loudness (LUFS) over time.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz. The default (22050) is non-standard and\n * K-weighting is sample-rate dependent; pass the buffer's actual rate.\n * @returns Momentary LUFS values over time\n */\nexport function momentaryLufs(request: LufsRequest): Float32Array;\nexport function momentaryLufs(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function momentaryLufs(\n samples: Float32Array | LufsRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return momentaryLufs(r.samples, r.sampleRate, r);\n }\n assertSampleRate('momentaryLufs', sampleRate);\n assertSamples('momentaryLufs', samples, options.validate !== false);\n return requireModule().momentaryLufs(samples, sampleRate);\n}\n\n/**\n * Compute the short-term loudness (LUFS) over time.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz. The default (22050) is non-standard and\n * K-weighting is sample-rate dependent; pass the buffer's actual rate.\n * @returns Short-term LUFS values over time\n */\nexport function shortTermLufs(request: LufsRequest): Float32Array;\nexport function shortTermLufs(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): Float32Array;\nexport function shortTermLufs(\n samples: Float32Array | LufsRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return shortTermLufs(r.samples, r.sampleRate, r);\n }\n assertSampleRate('shortTermLufs', sampleRate);\n assertSamples('shortTermLufs', samples, options.validate !== false);\n return requireModule().shortTermLufs(samples, sampleRate);\n}\n","import type { SpectralFrameRequest } from './feature_spectral';\nimport { getSonareModule } from './module_state';\nimport type { NoteSegment, PiptrackResult, PitchResult } from './public_types';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n// ============================================================================\n// Features - Pitch\n// ============================================================================\n\n/**\n * Detect pitch using YIN algorithm.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param frameLength - Frame length (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum frequency in Hz (default: 65)\n * @param fmax - Maximum frequency in Hz (default: 2093)\n * @param threshold - YIN threshold (default: 0.1)\n * @param fillNa - Retained for compatibility; YIN always returns a finite per-frame estimate.\n * @returns Pitch detection result\n */\nexport interface PitchYinRequest {\n samples: Float32Array;\n sampleRate?: number;\n frameLength?: number;\n hopLength?: number;\n fmin?: number;\n fmax?: number;\n threshold?: number;\n fillNa?: boolean;\n}\n\nexport interface PiptrackRequest {\n samples: Float32Array;\n sampleRate?: number;\n nFft?: number;\n hopLength?: number;\n fmin?: number;\n fmax?: number;\n threshold?: number;\n}\n\n/** Per-bin spectral pitch candidates and peak magnitudes (librosa.piptrack). */\nexport function piptrack(request: PiptrackRequest): PiptrackResult;\nexport function piptrack(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n fmin?: number,\n fmax?: number,\n threshold?: number,\n): PiptrackResult;\nexport function piptrack(\n samples: Float32Array | PiptrackRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n fmin = 150,\n fmax = 4000,\n threshold = 0.1,\n): PiptrackResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return piptrack(\n request.samples,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.fmin,\n request.fmax,\n request.threshold,\n );\n }\n return requireModule().piptrack(samples, sampleRate, nFft, hopLength, fmin, fmax, threshold);\n}\n\nexport function pitchYin(request: PitchYinRequest): PitchResult;\nexport function pitchYin(\n samples: Float32Array,\n sampleRate?: number,\n frameLength?: number,\n hopLength?: number,\n fmin?: number,\n fmax?: number,\n threshold?: number,\n fillNa?: boolean,\n): PitchResult;\nexport function pitchYin(\n samples: Float32Array | PitchYinRequest,\n sampleRate = 22050,\n frameLength = 2048,\n hopLength = 512,\n fmin = 65.0,\n fmax = 2093.0,\n threshold = 0.1,\n fillNa = false,\n): PitchResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return pitchYin(\n request.samples,\n request.sampleRate,\n request.frameLength,\n request.hopLength,\n request.fmin,\n request.fmax,\n request.threshold,\n request.fillNa,\n );\n }\n return requireModule().pitchYin(\n samples,\n sampleRate,\n frameLength,\n hopLength,\n fmin,\n fmax,\n threshold,\n fillNa,\n );\n}\n\n/**\n * Detect pitch using pYIN algorithm (probabilistic YIN with HMM smoothing).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param frameLength - Frame length (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param fmin - Minimum frequency in Hz (default: 65)\n * @param fmax - Maximum frequency in Hz (default: 2093)\n * @param threshold - YIN threshold (default: 0.1)\n * @param fillNa - If true, return 0 for unvoiced f0 frames; otherwise keep NaN (default: false)\n * @returns Pitch detection result\n */\nexport interface PitchPyinRequest extends PitchYinRequest {}\n\nexport function pitchPyin(request: PitchPyinRequest): PitchResult;\nexport function pitchPyin(\n samples: Float32Array,\n sampleRate?: number,\n frameLength?: number,\n hopLength?: number,\n fmin?: number,\n fmax?: number,\n threshold?: number,\n fillNa?: boolean,\n): PitchResult;\nexport function pitchPyin(\n samples: Float32Array | PitchPyinRequest,\n sampleRate = 22050,\n frameLength = 2048,\n hopLength = 512,\n fmin = 65.0,\n fmax = 2093.0,\n threshold = 0.1,\n fillNa = false,\n): PitchResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return pitchPyin(\n request.samples,\n request.sampleRate,\n request.frameLength,\n request.hopLength,\n request.fmin,\n request.fmax,\n request.threshold,\n request.fillNa,\n );\n }\n return requireModule().pitchPyin(\n samples,\n sampleRate,\n frameLength,\n hopLength,\n fmin,\n fmax,\n threshold,\n fillNa,\n );\n}\n\n/** Parameters for segmenting an F0 track into stable monophonic notes. */\nexport interface NoteSegmentsRequest {\n f0Hz: Float32Array;\n /**\n * Per-frame voicing values in `[0, 1]`; anything below `voicedThreshold` is\n * unvoiced.\n *\n * Pass {@link PitchResult.voicedFlag} converted to `0`/`1`. Do **not** pass\n * {@link pitchPyin}'s `voicedProb`: that value is the frame's voiced\n * observation mass and rises with F0 for a fixed `frameLength`, so a fixed\n * threshold silently returns no segments at all for low-register material\n * (a steady tone below roughly C5 never reaches 0.5).\n */\n voicedProb: Float32Array;\n frameRate: number;\n /** Cents of pitch change that start a new segment. Default 50. */\n segmentationThresholdCents?: number;\n /** Shortest segment kept, in ms. Default 30. */\n minNoteMs?: number;\n /** Reference pitch each segment's cents are measured against. Default 440. */\n referenceHz?: number;\n /** Voicing threshold applied to `voicedProb`; defaults to `0.5`. */\n voicedThreshold?: number;\n}\n\n/**\n * Segment a caller-supplied monophonic F0 track into stable note regions.\n *\n * `f0Hz` and `voicedProb` must have the same non-zero length. Zero-Hz frames\n * and values below `voicedThreshold` (default `0.5`) are treated as unvoiced.\n */\nexport function noteSegments(request: NoteSegmentsRequest): NoteSegment[] {\n return requireModule().noteSegments(request.f0Hz, request.voicedProb, request.frameRate, {\n segmentationThresholdCents: request.segmentationThresholdCents,\n minNoteMs: request.minNoteMs,\n referenceHz: request.referenceHz,\n voicedThreshold: request.voicedThreshold,\n });\n}\n\n// ============================================================================\n// Features - Tuning\n// ============================================================================\n\nexport interface PitchTuningRequest {\n frequencies: Float32Array;\n resolution?: number;\n binsPerOctave?: number;\n}\n\nexport interface EstimateTuningRequest extends SpectralFrameRequest {\n resolution?: number;\n binsPerOctave?: number;\n}\n\n/**\n * Estimate the global tuning offset from a set of frequencies\n * (librosa.pitch_tuning). Returns a deviation in fractions of a bin.\n */\nexport function pitchTuning(request: PitchTuningRequest): number;\nexport function pitchTuning(\n frequencies: Float32Array,\n resolution?: number,\n binsPerOctave?: number,\n): number;\nexport function pitchTuning(\n frequencies: Float32Array | PitchTuningRequest,\n resolution = 0.01,\n binsPerOctave = 12,\n): number {\n if (!(frequencies instanceof Float32Array)) {\n const r = frequencies;\n return pitchTuning(r.frequencies, r.resolution, r.binsPerOctave);\n }\n return requireModule().pitchTuning(frequencies, resolution, binsPerOctave);\n}\n\n/**\n * Estimate the tuning offset of an audio signal (librosa.estimate_tuning).\n */\nexport function estimateTuning(request: EstimateTuningRequest): number;\nexport function estimateTuning(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n resolution?: number,\n binsPerOctave?: number,\n): number;\nexport function estimateTuning(\n samples: Float32Array | EstimateTuningRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n resolution = 0.01,\n binsPerOctave = 12,\n): number {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return estimateTuning(\n r.samples,\n r.sampleRate,\n r.nFft,\n r.hopLength,\n r.resolution,\n r.binsPerOctave,\n );\n }\n return requireModule().estimateTuning(\n samples,\n sampleRate,\n nFft,\n hopLength,\n resolution,\n binsPerOctave,\n );\n}\n","import { getSonareModule } from './module_state';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n// ============================================================================\n// Core - Resample\n// ============================================================================\n\n/**\n * Resample audio to a different sample rate.\n *\n * @param samples - Audio samples (mono, float32)\n * @param srcSr - Source sample rate in Hz\n * @param targetSr - Target sample rate in Hz\n * @returns Resampled audio\n */\nexport interface ResampleRequest {\n samples: Float32Array;\n srcSr: number;\n targetSr: number;\n}\n\nexport function resample(request: ResampleRequest): Float32Array;\nexport function resample(samples: Float32Array, srcSr: number, targetSr: number): Float32Array;\nexport function resample(\n samples: Float32Array | ResampleRequest,\n srcSr?: number,\n targetSr?: number,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return resample(samples.samples, samples.srcSr, samples.targetSr);\n }\n return requireModule().resample(samples, srcSr as number, targetSr as number);\n}\n","/**\n * Frame-level spectral descriptors: the scalar shape measures taken per STFT\n * frame, and the zero-crossing counts beside them.\n */\n\nimport { getSonareModule } from './module_state';\nimport type { WasmMatrix2dResult } from './sonare.js';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n/** Canonical request form for frame-based spectral feature extraction. */\nexport interface SpectralFrameRequest {\n samples: Float32Array;\n sampleRate?: number;\n nFft?: number;\n hopLength?: number;\n}\n\nexport interface SpectralRolloffRequest extends SpectralFrameRequest {\n rollPercent?: number;\n}\n\nexport interface ZeroCrossingRateRequest {\n samples: Float32Array;\n sampleRate?: number;\n frameLength?: number;\n hopLength?: number;\n}\n\nexport interface SpectralContrastRequest extends SpectralFrameRequest {\n nBands?: number;\n fmin?: number;\n quantile?: number;\n}\n\nexport interface PolyFeaturesRequest extends SpectralFrameRequest {\n order?: number;\n}\n\nexport interface ZeroCrossingsRequest {\n samples: Float32Array;\n threshold?: number;\n refMagnitude?: boolean;\n pad?: boolean;\n zeroPos?: boolean;\n}\n\n// ============================================================================\n// Features - Spectral\n// ============================================================================\n\n/**\n * Compute spectral centroid (center of mass of spectrum).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns Spectral centroid in Hz for each frame\n */\nexport function spectralCentroid(request: SpectralFrameRequest): Float32Array;\nexport function spectralCentroid(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n): Float32Array;\nexport function spectralCentroid(\n samples: Float32Array | SpectralFrameRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return spectralCentroid(samples.samples, samples.sampleRate, samples.nFft, samples.hopLength);\n }\n return requireModule().spectralCentroid(samples, sampleRate, nFft, hopLength);\n}\n\n/**\n * Compute spectral contrast (librosa.feature.spectral_contrast).\n *\n * @remarks\n * Band 0 spans `[0, fmin]`, so an `fmin` below one analysis bin\n * (`sampleRate / nFft`) leaves it empty after the band trim. Row 0 is still\n * finite, but comes from the other bands' extremes rather than from itself, and\n * is neither level-invariant nor confined to the band. Keep `fmin` at or above\n * one bin width for row 0 to mean anything — at the defaults (22050 Hz, 2048)\n * one bin is 10.8 Hz, so only a small `nFft` or a tiny `fmin` reaches this.\n *\n * @returns Matrix2d of shape (nBands + 1) x nFrames.\n */\nexport function spectralContrast(request: SpectralContrastRequest): WasmMatrix2dResult;\nexport function spectralContrast(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n nBands?: number,\n fmin?: number,\n quantile?: number,\n): WasmMatrix2dResult;\nexport function spectralContrast(\n samples: Float32Array | SpectralContrastRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n nBands = 6,\n fmin = 200.0,\n quantile = 0.02,\n): WasmMatrix2dResult {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return spectralContrast(\n r.samples,\n r.sampleRate,\n r.nFft,\n r.hopLength,\n r.nBands,\n r.fmin,\n r.quantile,\n );\n }\n return requireModule().spectralContrast(\n samples,\n sampleRate,\n nFft,\n hopLength,\n nBands,\n fmin,\n quantile,\n );\n}\n\n/**\n * Fit per-frame polynomial coefficients (librosa.feature.poly_features).\n *\n * @returns Matrix2d of shape (order + 1) x nFrames.\n */\nexport function polyFeatures(request: PolyFeaturesRequest): WasmMatrix2dResult;\nexport function polyFeatures(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n order?: number,\n): WasmMatrix2dResult;\nexport function polyFeatures(\n samples: Float32Array | PolyFeaturesRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n order = 1,\n): WasmMatrix2dResult {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return polyFeatures(r.samples, r.sampleRate, r.nFft, r.hopLength, r.order);\n }\n return requireModule().polyFeatures(samples, sampleRate, nFft, hopLength, order);\n}\n\n/**\n * Locate zero-crossing indices of a signal (librosa.zero_crossings).\n */\nexport function zeroCrossings(request: ZeroCrossingsRequest): Int32Array;\nexport function zeroCrossings(\n samples: Float32Array,\n threshold?: number,\n refMagnitude?: boolean,\n pad?: boolean,\n zeroPos?: boolean,\n): Int32Array;\nexport function zeroCrossings(\n samples: Float32Array | ZeroCrossingsRequest,\n threshold = 1e-10,\n refMagnitude = false,\n pad = true,\n zeroPos = true,\n): Int32Array {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return zeroCrossings(r.samples, r.threshold, r.refMagnitude, r.pad, r.zeroPos);\n }\n return requireModule().zeroCrossings(samples, threshold, refMagnitude, pad, zeroPos);\n}\n\n/**\n * Compute spectral bandwidth.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns Spectral bandwidth in Hz for each frame\n */\nexport function spectralBandwidth(request: SpectralFrameRequest & { p?: number }): Float32Array;\nexport function spectralBandwidth(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n p?: number,\n): Float32Array;\nexport function spectralBandwidth(\n samples: Float32Array | (SpectralFrameRequest & { p?: number }),\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n p = 2,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return spectralBandwidth(\n samples.samples,\n samples.sampleRate,\n samples.nFft,\n samples.hopLength,\n samples.p,\n );\n }\n return requireModule().spectralBandwidth(samples, sampleRate, nFft, hopLength, p);\n}\n\n/**\n * Compute spectral rolloff frequency.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param rollPercent - Percentage threshold (default: 0.85)\n * @returns Rolloff frequency in Hz for each frame\n */\nexport function spectralRolloff(request: SpectralRolloffRequest): Float32Array;\nexport function spectralRolloff(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n rollPercent?: number,\n): Float32Array;\nexport function spectralRolloff(\n samples: Float32Array | SpectralRolloffRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n rollPercent = 0.85,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return spectralRolloff(\n samples.samples,\n samples.sampleRate,\n samples.nFft,\n samples.hopLength,\n samples.rollPercent,\n );\n }\n return requireModule().spectralRolloff(samples, sampleRate, nFft, hopLength, rollPercent);\n}\n\n/**\n * Compute spectral flatness.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns Spectral flatness for each frame (0 = tonal, 1 = noise-like)\n */\nexport function spectralFlatness(request: SpectralFrameRequest): Float32Array;\nexport function spectralFlatness(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n): Float32Array;\nexport function spectralFlatness(\n samples: Float32Array | SpectralFrameRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return spectralFlatness(samples.samples, samples.sampleRate, samples.nFft, samples.hopLength);\n }\n return requireModule().spectralFlatness(samples, sampleRate, nFft, hopLength);\n}\n\nexport function spectralFlux(request: SpectralFrameRequest & { lag?: number }): Float32Array;\nexport function spectralFlux(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n lag?: number,\n): Float32Array;\nexport function spectralFlux(\n samples: Float32Array | (SpectralFrameRequest & { lag?: number }),\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n lag = 1,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return spectralFlux(\n samples.samples,\n samples.sampleRate,\n samples.nFft,\n samples.hopLength,\n samples.lag,\n );\n }\n return requireModule().spectralFlux(samples, sampleRate, nFft, hopLength, lag);\n}\n\n/**\n * Compute zero crossing rate.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param frameLength - Frame length (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns Zero crossing rate for each frame\n */\nexport function zeroCrossingRate(request: ZeroCrossingRateRequest): Float32Array;\nexport function zeroCrossingRate(\n samples: Float32Array,\n sampleRate?: number,\n frameLength?: number,\n hopLength?: number,\n): Float32Array;\nexport function zeroCrossingRate(\n samples: Float32Array | ZeroCrossingRateRequest,\n sampleRate = 22050,\n frameLength = 2048,\n hopLength = 512,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return zeroCrossingRate(\n samples.samples,\n samples.sampleRate,\n samples.frameLength,\n samples.hopLength,\n );\n }\n return requireModule().zeroCrossingRate(samples, sampleRate, frameLength, hopLength);\n}\n\n/**\n * Compute RMS energy.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param frameLength - Frame length (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns RMS energy for each frame\n */\nexport function rmsEnergy(request: ZeroCrossingRateRequest): Float32Array;\nexport function rmsEnergy(\n samples: Float32Array,\n sampleRate?: number,\n frameLength?: number,\n hopLength?: number,\n): Float32Array;\nexport function rmsEnergy(\n samples: Float32Array | ZeroCrossingRateRequest,\n sampleRate = 22050,\n frameLength = 2048,\n hopLength = 512,\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n return rmsEnergy(samples.samples, samples.sampleRate, samples.frameLength, samples.hopLength);\n }\n return requireModule().rmsEnergy(samples, sampleRate, frameLength, hopLength);\n}\n","/**\n * Spectrogram and chroma representations, and the silence trim that shares\n * their input checks.\n */\n\nimport type { GuardedOptions } from './_feature_validation';\nimport { validateMelFrequencyRange, validatePositiveIntegers } from './_feature_validation';\nimport { resolveFftOptions } from './_fft_options';\nimport { getSonareModule } from './module_state';\nimport type {\n ChromaResult,\n MelSpectrogramResult,\n MfccResult,\n ReassignedSpectrogramResult,\n StftResult,\n} from './public_types';\nimport {\n assertFiniteScalar,\n assertPositiveInteger,\n assertSampleRate,\n assertSamples,\n} from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n/** Canonical request form for basic frame-based spectrogram features. */\nexport interface SpectrogramRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n nFft?: number;\n hopLength?: number;\n}\n\n/**\n * Options for the constant-Q chroma variants.\n *\n * Carries no `nFft`: these are built on a constant-Q transform, which resolves\n * frequency through per-bin filter lengths rather than a framed FFT, so there\n * is no FFT size to set. Use `chroma` for the STFT-framed chromagram.\n */\nexport interface ChromaSpectrogramRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n nChroma?: number;\n binsPerOctave?: number;\n}\n\n/**\n * Options for the bass-focused chroma.\n *\n * Unlike {@link ChromaSpectrogramRequest} this carries no `binsPerOctave`: the\n * bass chroma fixes its bin count and its lowest frequency together, so the\n * resolution is not independently settable through this entry point.\n */\nexport interface BassChromaSpectrogramRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n hopLength?: number;\n nChroma?: number;\n}\n\n/**\n * Compile-time guard for the two request shapes above. A field the entry point\n * cannot forward is worse than a missing one: it type-checks, runs, and returns\n * the default silently. These aliases fail to compile if either field appears,\n * so adding one has to be a deliberate act.\n */\ntype AbsentKey<T extends never> = T;\n\ntype _ChromaRequestHasNoFftSize = AbsentKey<Extract<keyof ChromaSpectrogramRequest, 'nFft'>>;\n\ntype _BassChromaRequestHasNoResolutionControls = AbsentKey<\n Extract<keyof BassChromaSpectrogramRequest, 'nFft' | 'binsPerOctave'>\n>;\n\nexport interface MelSpectrogramRequest extends SpectrogramRequest {\n nMels?: number;\n fmin?: number;\n fmax?: number;\n htk?: boolean;\n}\n\nexport interface MfccRequest extends MelSpectrogramRequest {\n nMfcc?: number;\n lifter?: number;\n}\n\nexport interface MelDeltaRequest extends GuardedOptions {\n features: Float32Array;\n nFeatures: number;\n nFrames: number;\n width?: number;\n}\n\nexport interface ReassignedSpectrogramRequest extends SpectrogramRequest {\n refPower?: number;\n fillNan?: boolean;\n}\n\nexport interface TrimRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate: number;\n thresholdDb?: number;\n frameLength?: number;\n hopLength?: number;\n}\n\nfunction validateSpectrogramSamples(\n fnName: string,\n samples: Float32Array,\n sampleRate: number,\n options: GuardedOptions = {},\n): void {\n assertSampleRate(fnName, sampleRate);\n assertSamples(fnName, samples, options.validate !== false);\n}\n\n/**\n * Trim silence from beginning and end of audio.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz\n * @param thresholdDb - Silence threshold in dB (default: -60 dB)\n * @returns Trimmed audio\n */\nexport function trim(request: TrimRequest): Float32Array;\nexport function trim(\n samples: Float32Array,\n sampleRate: number,\n thresholdDb?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function trim(\n samples: Float32Array,\n sampleRate: number,\n thresholdDb?: number,\n frameLength?: number,\n hopLength?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function trim(\n samples: Float32Array | TrimRequest,\n sampleRate = 22050,\n thresholdDb = -60.0,\n frameLengthOrOptions?: number | GuardedOptions,\n hopLength?: number,\n options: GuardedOptions = {},\n): Float32Array {\n if (!(samples instanceof Float32Array)) {\n const r = samples;\n return trim(r.samples, r.sampleRate, r.thresholdDb, r.frameLength, r.hopLength, r);\n }\n if (frameLengthOrOptions === null) {\n throw new TypeError('trim: frameLength must be an integer or options object');\n }\n if (\n frameLengthOrOptions !== undefined &&\n typeof frameLengthOrOptions !== 'number' &&\n typeof frameLengthOrOptions !== 'object'\n ) {\n throw new TypeError('trim: frameLength must be an integer or options object');\n }\n const positionalOptions =\n typeof frameLengthOrOptions === 'object' && frameLengthOrOptions !== null\n ? frameLengthOrOptions\n : options;\n const positionalFrameLength =\n typeof frameLengthOrOptions === 'number' ? frameLengthOrOptions : undefined;\n const resolvedFrameLength = positionalFrameLength ?? 2048;\n const resolvedHopLength = hopLength === undefined ? 512 : hopLength;\n validateSpectrogramSamples('trim', samples, sampleRate, positionalOptions);\n assertFiniteScalar('trim', thresholdDb, 'thresholdDb');\n assertPositiveInteger('trim', resolvedFrameLength, 'frameLength');\n assertPositiveInteger('trim', resolvedHopLength, 'hopLength');\n if (resolvedFrameLength > 2 ** 31 - 1 || resolvedHopLength > 2 ** 31 - 1) {\n throw new RangeError('trim: frameLength and hopLength must fit in a signed 32-bit integer');\n }\n return requireModule().trimEx(\n samples,\n sampleRate,\n thresholdDb,\n resolvedFrameLength,\n resolvedHopLength,\n );\n}\n\n// ============================================================================\n// Features - Spectrogram\n// ============================================================================\n\n/**\n * Compute Short-Time Fourier Transform (STFT).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns STFT result with magnitude and power spectrograms\n */\nexport function stft(request: SpectrogramRequest): StftResult;\nexport function stft(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n options?: GuardedOptions,\n): StftResult;\nexport function stft(\n samples: Float32Array | SpectrogramRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n options: GuardedOptions = {},\n): StftResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return stft(request.samples, request.sampleRate, request.nFft, request.hopLength, request);\n }\n validateSpectrogramSamples('stft', samples, sampleRate, options);\n const fft = resolveFftOptions('stft', nFft, hopLength);\n return requireModule().stft(samples, sampleRate, fft.nFft, fft.hopLength);\n}\n\n/**\n * Compute STFT and return magnitude in decibels.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns STFT result with dB values\n */\nexport function stftDb(request: SpectrogramRequest): {\n nBins: number;\n nFrames: number;\n db: Float32Array;\n};\nexport function stftDb(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n options?: GuardedOptions,\n): { nBins: number; nFrames: number; db: Float32Array };\nexport function stftDb(\n samples: Float32Array | SpectrogramRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n options: GuardedOptions = {},\n): { nBins: number; nFrames: number; db: Float32Array } {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return stftDb(request.samples, request.sampleRate, request.nFft, request.hopLength, request);\n }\n validateSpectrogramSamples('stftDb', samples, sampleRate, options);\n const fft = resolveFftOptions('stftDb', nFft, hopLength);\n return requireModule().stftDb(samples, sampleRate, fft.nFft, fft.hopLength);\n}\n\n/**\n * Compute Chroma Energy Normalized Statistics.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param nChroma - Number of chroma bins (default: 12)\n * @returns Chroma result\n */\nexport function chromaCens(request: ChromaSpectrogramRequest): ChromaResult;\nexport function chromaCens(\n samples: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n nChroma?: number,\n binsPerOctave?: number,\n options?: GuardedOptions,\n): ChromaResult;\nexport function chromaCens(\n samples: Float32Array | ChromaSpectrogramRequest,\n sampleRate = 22050,\n hopLength = 512,\n nChroma = 12,\n binsPerOctave = 36,\n options: GuardedOptions = {},\n): ChromaResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return chromaCens(\n request.samples,\n request.sampleRate,\n request.hopLength,\n request.nChroma,\n request.binsPerOctave,\n request,\n );\n }\n validateSpectrogramSamples('chromaCens', samples, sampleRate, options);\n validatePositiveIntegers('chromaCens', { hopLength, nChroma, binsPerOctave });\n if (binsPerOctave % nChroma !== 0) {\n throw new RangeError('chromaCens: binsPerOctave must be a multiple of nChroma');\n }\n return requireModule().chromaCens(samples, sampleRate, hopLength, nChroma, binsPerOctave);\n}\n\n/**\n * Compute a constant-Q chromagram (librosa.feature.chroma_cqt).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param nChroma - Number of chroma bins (default: 12)\n * @returns Chroma result\n */\nexport function chromaCqt(request: ChromaSpectrogramRequest): ChromaResult;\nexport function chromaCqt(\n samples: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n nChroma?: number,\n binsPerOctave?: number,\n options?: GuardedOptions,\n): ChromaResult;\nexport function chromaCqt(\n samples: Float32Array | ChromaSpectrogramRequest,\n sampleRate = 22050,\n hopLength = 512,\n nChroma = 12,\n binsPerOctave = 36,\n options: GuardedOptions = {},\n): ChromaResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return chromaCqt(\n request.samples,\n request.sampleRate,\n request.hopLength,\n request.nChroma,\n request.binsPerOctave,\n request,\n );\n }\n validateSpectrogramSamples('chromaCqt', samples, sampleRate, options);\n validatePositiveIntegers('chromaCqt', { hopLength, nChroma, binsPerOctave });\n if (binsPerOctave % nChroma !== 0) {\n throw new RangeError('chromaCqt: binsPerOctave must be a multiple of nChroma');\n }\n return requireModule().chromaCqt(samples, sampleRate, hopLength, nChroma, binsPerOctave);\n}\n\n/**\n * Compute low-frequency bass chroma.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param hopLength - Hop length (default: 512)\n * @param nChroma - Number of chroma bins (default: 12)\n * @returns Chroma result\n */\nexport function bassChroma(request: BassChromaSpectrogramRequest): ChromaResult;\nexport function bassChroma(\n samples: Float32Array,\n sampleRate?: number,\n hopLength?: number,\n nChroma?: number,\n options?: GuardedOptions,\n): ChromaResult;\nexport function bassChroma(\n samples: Float32Array | BassChromaSpectrogramRequest,\n sampleRate = 22050,\n hopLength = 512,\n nChroma = 12,\n options: GuardedOptions = {},\n): ChromaResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return bassChroma(\n request.samples,\n request.sampleRate,\n request.hopLength,\n request.nChroma,\n request,\n );\n }\n validateSpectrogramSamples('bassChroma', samples, sampleRate, options);\n validatePositiveIntegers('bassChroma', { hopLength, nChroma });\n return requireModule().bassChroma(samples, sampleRate, hopLength, nChroma);\n}\n\n// ============================================================================\n// Features - Mel Spectrogram\n// ============================================================================\n\n/**\n * Compute Mel spectrogram.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param nMels - Number of Mel bands (default: 128)\n * @param fmin - Minimum Mel frequency in Hz (default: 0 = librosa default).\n * Set with `fmax` to round-trip with `melToStft` / `melToAudio`.\n * @param fmax - Maximum Mel frequency in Hz (default: 0 = sampleRate / 2)\n * @param htk - Use the HTK Mel formula instead of Slaney (default: false)\n * @returns Mel spectrogram result\n */\nexport function melSpectrogram(request: MelSpectrogramRequest): MelSpectrogramResult;\nexport function melSpectrogram(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n nMels?: number,\n fmin?: number,\n fmax?: number,\n htk?: boolean,\n options?: GuardedOptions,\n): MelSpectrogramResult;\nexport function melSpectrogram(\n samples: Float32Array | MelSpectrogramRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n nMels = 128,\n fmin = 0,\n fmax = 0,\n htk = false,\n options: GuardedOptions = {},\n): MelSpectrogramResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return melSpectrogram(\n request.samples,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.nMels,\n request.fmin,\n request.fmax,\n request.htk,\n request,\n );\n }\n validateSpectrogramSamples('melSpectrogram', samples, sampleRate, options);\n const fft = resolveFftOptions('melSpectrogram', nFft, hopLength);\n validatePositiveIntegers('melSpectrogram', { nMels });\n validateMelFrequencyRange('melSpectrogram', fmin, fmax, sampleRate);\n return requireModule().melSpectrogram(\n samples,\n sampleRate,\n fft.nFft,\n fft.hopLength,\n nMels,\n fmin,\n fmax,\n htk,\n );\n}\n\n/**\n * Compute MFCC (Mel-Frequency Cepstral Coefficients).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @param nMels - Number of Mel bands (default: 128)\n * @param nMfcc - Number of MFCC coefficients (default: 20)\n * @param fmin - Minimum Mel frequency in Hz (default: 0 = librosa default)\n * @param fmax - Maximum Mel frequency in Hz (default: 0 = sampleRate / 2)\n * @param htk - Use the HTK Mel formula instead of Slaney (default: false)\n * @param lifter - Cepstral liftering coefficient (default: 0 = no liftering)\n * @returns MFCC result\n */\nexport function mfcc(request: MfccRequest): MfccResult;\nexport function mfcc(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n nMels?: number,\n nMfcc?: number,\n fmin?: number,\n fmax?: number,\n htk?: boolean,\n lifter?: number,\n options?: GuardedOptions,\n): MfccResult;\nexport function mfcc(\n samples: Float32Array | MfccRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n nMels = 128,\n nMfcc = 20,\n fmin = 0,\n fmax = 0,\n htk = false,\n lifter = 0,\n options: GuardedOptions = {},\n): MfccResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return mfcc(\n request.samples,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.nMels,\n request.nMfcc,\n request.fmin,\n request.fmax,\n request.htk,\n request.lifter,\n request,\n );\n }\n validateSpectrogramSamples('mfcc', samples, sampleRate, options);\n const fft = resolveFftOptions('mfcc', nFft, hopLength);\n validatePositiveIntegers('mfcc', { nMels, nMfcc });\n validateMelFrequencyRange('mfcc', fmin, fmax, sampleRate);\n return requireModule().mfcc(\n samples,\n sampleRate,\n fft.nFft,\n fft.hopLength,\n nMels,\n nMfcc,\n fmin,\n fmax,\n htk,\n lifter,\n );\n}\n\n/** First-order regression delta of a row-major feature matrix. */\nexport function melDelta(request: MelDeltaRequest): Float32Array;\nexport function melDelta(\n features: Float32Array,\n nFeatures: number,\n nFrames: number,\n width?: number,\n): Float32Array;\nexport function melDelta(\n features: Float32Array | MelDeltaRequest,\n nFeatures?: number,\n nFrames?: number,\n width = 9,\n): Float32Array {\n const request: MelDeltaRequest =\n features instanceof Float32Array\n ? { features, nFeatures: nFeatures ?? 0, nFrames: nFrames ?? 0, width }\n : features;\n assertPositiveInteger('melDelta', request.nFeatures, 'nFeatures');\n assertPositiveInteger('melDelta', request.nFrames, 'nFrames');\n assertPositiveInteger('melDelta', request.width ?? 9, 'width');\n if ((request.width ?? 9) < 3 || (request.width ?? 9) % 2 === 0) {\n throw new RangeError('melDelta: width must be an odd integer of at least 3');\n }\n if (request.features.length !== request.nFeatures * request.nFrames) {\n throw new RangeError('melDelta: feature matrix length must equal nFeatures * nFrames');\n }\n return requireModule().melDelta(\n request.features,\n request.nFeatures,\n request.nFrames,\n request.width ?? 9,\n );\n}\n\n/** Auger-Flandrin reassigned spectrogram (row-major [nBins x nFrames] arrays). */\nexport function reassignedSpectrogram(\n request: ReassignedSpectrogramRequest,\n): ReassignedSpectrogramResult;\nexport function reassignedSpectrogram(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n refPower?: number,\n fillNan?: boolean,\n): ReassignedSpectrogramResult;\nexport function reassignedSpectrogram(\n samples: Float32Array | ReassignedSpectrogramRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n refPower = 1e-6,\n fillNan = false,\n): ReassignedSpectrogramResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return reassignedSpectrogram(\n request.samples,\n request.sampleRate,\n request.nFft,\n request.hopLength,\n request.refPower,\n request.fillNan,\n );\n }\n assertSamples('reassignedSpectrogram', samples, true);\n assertSampleRate('reassignedSpectrogram', sampleRate);\n assertPositiveInteger('reassignedSpectrogram', nFft, 'nFft');\n assertPositiveInteger('reassignedSpectrogram', hopLength, 'hopLength');\n assertFiniteScalar('reassignedSpectrogram', refPower, 'refPower');\n if (refPower < 0) {\n throw new RangeError('reassignedSpectrogram: refPower must be non-negative');\n }\n return requireModule().reassignedSpectrogram(\n samples,\n sampleRate,\n nFft,\n hopLength,\n refPower,\n fillNan,\n );\n}\n\n// ============================================================================\n// Features - Chroma\n// ============================================================================\n\n/**\n * Compute STFT chromagram (librosa.feature.chroma_stft).\n *\n * The chroma filterbank uses a fixed tuning of 0 (concert A440). Unlike\n * librosa.feature.chroma_stft — which estimates tuning from the signal when none\n * is given — this does NOT auto-estimate and takes no tuning argument. A\n * tuning offset from {@link estimateTuning} is applied through `analyze`'s\n * `tuning` option (and to chords through `detectChords`).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param nFft - FFT size (default: 2048)\n * @param hopLength - Hop length (default: 512)\n * @returns Chroma features result\n */\nexport function chroma(request: SpectrogramRequest): ChromaResult;\nexport function chroma(\n samples: Float32Array,\n sampleRate?: number,\n nFft?: number,\n hopLength?: number,\n options?: GuardedOptions,\n): ChromaResult;\nexport function chroma(\n samples: Float32Array | SpectrogramRequest,\n sampleRate = 22050,\n nFft = 2048,\n hopLength = 512,\n options: GuardedOptions = {},\n): ChromaResult {\n if (!(samples instanceof Float32Array)) {\n const request = samples;\n return chroma(request.samples, request.sampleRate, request.nFft, request.hopLength, request);\n }\n validateSpectrogramSamples('chroma', samples, sampleRate, options);\n const fft = resolveFftOptions('chroma', nFft, hopLength);\n return requireModule().chroma(samples, sampleRate, fft.nFft, fft.hopLength);\n}\n","import { ErrorCode, SonareError } from './errors';\nimport { getSonareModule } from './module_state';\nimport type { ValidateOptions } from './validation';\nimport {\n assertInterleavedSamples,\n assertNonNegativeInteger,\n assertPositiveInteger,\n assertSamples,\n assertSamplesInWindow,\n} from './validation';\n\n// The FFT size the library falls back to when `nFft` is 0 or omitted. Mirrored\n// here so the windowed pre-scan covers exactly the span the call will read; a\n// test pins it against the `nFft` the library reports back for a 0 request.\nconst DEFAULT_SPECTRUM_N_FFT = 2048;\n\n/**\n * Validates a true-peak oversample factor: `0` (meaning \"use the default 4\") or\n * a power of two in `[1, 16]`. The native layer applies the same `0 -> 4`\n * normalization (see `metering::true_peak_db`), so the raw factor can be passed\n * through unchanged after this check. Kept module-local (not exported) so it does\n * not surface as a WASM-only symbol with no C-API counterpart.\n */\nfunction assertOversampleFactor(fnName: string, factor: number): void {\n const normalized = factor === 0 ? 4 : factor;\n if (\n !Number.isInteger(normalized) ||\n normalized < 1 ||\n normalized > 16 ||\n (normalized & (normalized - 1)) !== 0\n ) {\n throw new SonareError(\n ErrorCode.InvalidParameter,\n 'InvalidParameter',\n `${fnName}: oversampleFactor must be 0 or a power of two from 1 to 16`,\n );\n }\n}\n\n// ============================================================================\n// Metering — basic / true-peak / clipping / dynamic range\n// ============================================================================\n\n/** One contiguous run of clipped samples reported by `meteringDetectClipping`. */\nexport interface ClippingRegion {\n startSample: number;\n endSample: number;\n length: number;\n peak: number;\n}\n\n/** Aggregated clipping report. */\nexport interface ClippingReport {\n clippedSamples: number;\n clippingRatio: number;\n maxClippedPeak: number;\n regions: ClippingRegion[];\n}\n\n/** Sliding-window dynamic range report. */\nexport interface DynamicRangeReport {\n dynamicRangeDb: number;\n lowPercentileDb: number;\n highPercentileDb: number;\n windowRmsDb: Float32Array;\n}\n\n/** Options for {@link meteringDetectClipping}. All fields are optional. */\nexport interface MeteringDetectClippingOptions extends ValidateOptions {\n /** Linear absolute threshold. Default 0.999. */\n threshold?: number;\n /** Minimum run length to report. Default 1. */\n minRegionSamples?: number;\n}\n\n/** Options for {@link meteringDynamicRange}. All fields are optional. */\nexport interface MeteringDynamicRangeOptions extends ValidateOptions {\n /** Window length in seconds (0 = library default, 3 s). Default 0. */\n windowSec?: number;\n /** Hop length in seconds (0 = library default, 1 s). Default 0. */\n hopSec?: number;\n /** Low percentile in [0,1] (negative = library default, 0.10). Default -1. */\n lowPercentile?: number;\n /** High percentile in [0,1] (negative = library default, 0.95). Default -1. */\n highPercentile?: number;\n}\n\n/** Canonical request form for single-channel meter readings. */\nexport interface MeteringSamplesRequest extends ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\n/** Canonical request form for true-peak analysis. */\nexport interface MeteringTruePeakRequest extends MeteringSamplesRequest {\n oversampleFactor?: number;\n}\n\n/** Canonical request form for clipping analysis. */\nexport interface MeteringDetectClippingRequest extends MeteringDetectClippingOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\n/** Canonical request form for dynamic-range analysis. */\nexport interface MeteringDynamicRangeRequest extends MeteringDynamicRangeOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\nfunction requireModule() {\n return getSonareModule();\n}\n\nexport function meteringPeakDb(request: MeteringSamplesRequest): number;\nexport function meteringPeakDb(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringPeakDb(\n samples: Float32Array | MeteringSamplesRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): number {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('meteringPeakDb', request.samples, request.validate !== false);\n return requireModule().meteringPeakDb(request.samples, request.sampleRate ?? 22050);\n}\n\nexport function meteringRmsDb(request: MeteringSamplesRequest): number;\nexport function meteringRmsDb(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringRmsDb(\n samples: Float32Array | MeteringSamplesRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): number {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('meteringRmsDb', request.samples, request.validate !== false);\n return requireModule().meteringRmsDb(request.samples, request.sampleRate ?? 22050);\n}\n\nexport interface MeteringSilenceRatioRequest extends MeteringSamplesRequest {\n thresholdDb?: number;\n frameLength?: number;\n hopLength?: number;\n}\n\nexport function meteringSilenceRatio(request: MeteringSilenceRatioRequest): number;\nexport function meteringSilenceRatio(\n samples: Float32Array,\n sampleRate?: number,\n thresholdDb?: number,\n frameLength?: number,\n hopLength?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringSilenceRatio(\n samples: Float32Array | MeteringSilenceRatioRequest,\n sampleRate = 22050,\n thresholdDb = -45,\n frameLength = 1024,\n hopLength = 256,\n options: ValidateOptions = {},\n): number {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate, thresholdDb, frameLength, hopLength, ...options }\n : samples;\n assertSamples('meteringSilenceRatio', request.samples, request.validate !== false);\n return requireModule().meteringSilenceRatio(\n request.samples,\n request.sampleRate ?? 22050,\n request.thresholdDb ?? -45,\n request.frameLength ?? 1024,\n request.hopLength ?? 256,\n );\n}\n\nexport function meteringCrestFactorDb(request: MeteringSamplesRequest): number;\nexport function meteringCrestFactorDb(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringCrestFactorDb(\n samples: Float32Array | MeteringSamplesRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): number {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('meteringCrestFactorDb', request.samples, request.validate !== false);\n return requireModule().meteringCrestFactorDb(request.samples, request.sampleRate ?? 22050);\n}\n\n/**\n * Crest factor in dB across both channels of a stereo pair.\n *\n * Takes the peak across both channels and the RMS over both together. An\n * out-of-phase pair cancels in the `0.5 * (left + right)` downmix\n * {@link meteringCrestFactorDb} would need, which understates its RMS and so\n * overstates the crest factor.\n */\nexport function meteringCrestFactorDbStereo(request: MeteringStereoRequest): number {\n assertSamples('meteringCrestFactorDbStereo', request.left, request.validate !== false);\n assertSamples('meteringCrestFactorDbStereo', request.right, request.validate !== false);\n return requireModule().meteringCrestFactorDbStereo(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n );\n}\n\nexport function meteringDcOffset(request: MeteringSamplesRequest): number;\nexport function meteringDcOffset(\n samples: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringDcOffset(\n samples: Float32Array | MeteringSamplesRequest,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): number {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('meteringDcOffset', request.samples, request.validate !== false);\n return requireModule().meteringDcOffset(request.samples, request.sampleRate ?? 22050);\n}\n\n/**\n * Inter-sample (true) peak in dBFS. `oversampleFactor` must be a power of two\n * in [1, 16]; pass 0 to use the library default (4).\n */\nexport function meteringTruePeakDb(request: MeteringTruePeakRequest): number;\nexport function meteringTruePeakDb(\n samples: Float32Array,\n sampleRate?: number,\n oversampleFactor?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringTruePeakDb(\n samples: Float32Array | MeteringTruePeakRequest,\n sampleRate = 22050,\n oversampleFactor = 4,\n options: ValidateOptions = {},\n): number {\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate, oversampleFactor, ...options }\n : samples;\n assertSamples('meteringTruePeakDb', request.samples, request.validate !== false);\n const factor = request.oversampleFactor ?? 4;\n assertOversampleFactor('meteringTruePeakDb', factor);\n return requireModule().meteringTruePeakDb(request.samples, request.sampleRate ?? 22050, factor);\n}\n\n/**\n * Detect contiguous runs of clipped samples.\n *\n * @param threshold Linear absolute threshold (default 0.999).\n * @param minRegionSamples Minimum run length to report (default 1).\n */\nexport function meteringDetectClipping(request: MeteringDetectClippingRequest): ClippingReport;\nexport function meteringDetectClipping(\n samples: Float32Array,\n sampleRate?: number,\n options?: MeteringDetectClippingOptions,\n): ClippingReport;\nexport function meteringDetectClipping(\n samples: Float32Array | MeteringDetectClippingRequest,\n sampleRate = 22050,\n options: MeteringDetectClippingOptions = {},\n): ClippingReport {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('meteringDetectClipping', request.samples, request.validate !== false);\n const minRegionSamples = request.minRegionSamples ?? 1;\n assertNonNegativeInteger('meteringDetectClipping', minRegionSamples, 'minRegionSamples');\n return requireModule().meteringDetectClipping(\n request.samples,\n request.sampleRate ?? 22050,\n request.threshold ?? 0.999,\n minRegionSamples,\n );\n}\n\n/**\n * Sliding-window dynamic range for mono audio. Pass 0 for window/hop to use the library\n * default (window=3 s, hop=1 s). The percentiles use a NEGATIVE sentinel for\n * \"use the library default\" (low=0.10, high=0.95) because 0 is a literal 0th\n * percentile; omitted percentiles therefore default to -1.\n */\nexport function meteringDynamicRange(request: MeteringDynamicRangeRequest): DynamicRangeReport;\nexport function meteringDynamicRange(\n samples: Float32Array,\n sampleRate?: number,\n options?: MeteringDynamicRangeOptions,\n): DynamicRangeReport;\nexport function meteringDynamicRange(\n samples: Float32Array | MeteringDynamicRangeRequest,\n sampleRate = 22050,\n options: MeteringDynamicRangeOptions = {},\n): DynamicRangeReport {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('meteringDynamicRange', request.samples, request.validate !== false);\n return requireModule().meteringDynamicRange(\n request.samples,\n request.sampleRate ?? 22050,\n request.windowSec ?? 0,\n request.hopSec ?? 0,\n request.lowPercentile ?? -1,\n request.highPercentile ?? -1,\n );\n}\n\n// ============================================================================\n// Metering — stereo / phase-scope / spectrum\n// ============================================================================\n\n/** Mid/side vectorscope point series for a (left, right) stereo pair. */\nexport interface VectorscopeReport {\n mid: Float32Array;\n side: Float32Array;\n}\n\n/** Phase-scope (Lissajous) point series plus summary stats. */\nexport interface PhaseScopeReport {\n mid: Float32Array;\n side: Float32Array;\n radius: Float32Array;\n angleRad: Float32Array;\n correlation: number;\n averageAbsAngleRad: number;\n maxRadius: number;\n}\n\n/** Options for `meteringSpectrum`. */\nexport interface SpectrumOptions {\n /** FFT size. Pass 0 / omit for the library default (2048). */\n nFft?: number;\n /** Apply fractional-octave smoothing to magnitude. */\n applyOctaveSmoothing?: boolean;\n /** Smoothing fraction (e.g. 3 = 1/3-octave). 0 / omit = library default (3). */\n octaveFraction?: number;\n /** Linear reference for the dB conversion. 0 / omit = 1.0. */\n dbRef?: number;\n /** Linear floor used to avoid log(0). 0 / omit = library default. */\n dbAmin?: number;\n}\n\n/** Single-frame magnitude / power / dB spectrum returned by `meteringSpectrum`. */\nexport interface SpectrumReport {\n frequencies: Float32Array;\n magnitude: Float32Array;\n power: Float32Array;\n db: Float32Array;\n nFft: number;\n sampleRate: number;\n}\n\n/** Options for {@link waveformPeaks}. All fields are optional. */\nexport interface WaveformPeaksOptions extends ValidateOptions {\n /** Bucket width in frames. Default 512. */\n samplesPerBucket?: number;\n}\n\n/** Options for {@link waveformPeakPyramid}. All fields are optional. */\nexport interface WaveformPeakPyramidOptions extends ValidateOptions {\n /** Bucket widths in frames, one per zoom level. Default [512, 1024, 2048, 4096]. */\n samplesPerBucketLevels?: number[];\n}\n\n/** Canonical request form for stereo meter readings. */\nexport interface MeteringStereoRequest extends ValidateOptions {\n left: Float32Array;\n right: Float32Array;\n sampleRate?: number;\n}\n\n/** Canonical request form for display-decimated stereo scopes. */\nexport interface MeteringStereoDecimatedRequest extends MeteringStereoRequest {\n maxPoints?: number;\n}\n\n/** Options for the scope functions (mirrors the Node `ScopeOptions`). */\nexport interface ScopeOptions extends ValidateOptions {\n /**\n * Upper bound on the returned point count. Omit / `0` (or a value `>= length`)\n * yields one point per input sample; otherwise the point cloud is\n * deterministically decimated to at most `maxPoints` points for display.\n */\n maxPoints?: number;\n}\n\n/** Canonical request form for whole-signal spectrum analysis. */\nexport interface MeteringSpectrumRequest extends SpectrumOptions, ValidateOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\n/** Canonical request form for a single spectrum frame. */\nexport interface MeteringSpectrumFrameRequest extends MeteringSpectrumRequest {\n frameOffset?: number;\n}\n\n/** Canonical request form for waveform bucket generation. */\nexport interface WaveformPeaksRequest extends WaveformPeaksOptions {\n samples: Float32Array;\n channels: number;\n}\n\n/** Canonical request form for multi-resolution waveform bucket generation. */\nexport interface WaveformPeakPyramidRequest extends WaveformPeakPyramidOptions {\n samples: Float32Array;\n channels: number;\n}\n\n/** Per-channel min/max waveform buckets. Arrays are channel-major. */\nexport interface WaveformPeaksReport {\n min: Float32Array;\n max: Float32Array;\n channels: number;\n bucketCount: number;\n samplesPerBucket: number;\n}\n\n/** Uncentered correlation (cosine similarity) in [-1, 1] between equal-length channels. */\nexport function meteringStereoCorrelation(request: MeteringStereoRequest): number;\nexport function meteringStereoCorrelation(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringStereoCorrelation(\n left: Float32Array | MeteringStereoRequest,\n right?: Float32Array,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): number {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...options }\n : left;\n const validate = request.validate !== false;\n assertSamples('meteringStereoCorrelation', request.left, validate, 'left');\n assertSamples('meteringStereoCorrelation', request.right, validate, 'right');\n return requireModule().meteringStereoCorrelation(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n );\n}\n\n/**\n * Stereo width as `sqrt(side_energy / mid_energy)` in `[0, +Infinity)`: the\n * side/mid RMS *amplitude* ratio, not the energy ratio. 0 = pure mono, ~1 =\n * wide stereo, larger = increasingly decorrelated / out-of-phase. The value is\n * unbounded and returns `Infinity` when the mid channel is silent (a\n * mono-collapsed / fully out-of-phase signal).\n *\n * Convert to dB with `20 * Math.log10(value)`; `10 * Math.log10` would\n * understate the true energy ratio by half.\n */\nexport function meteringStereoWidth(request: MeteringStereoRequest): number;\nexport function meteringStereoWidth(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n options?: ValidateOptions,\n): number;\nexport function meteringStereoWidth(\n left: Float32Array | MeteringStereoRequest,\n right?: Float32Array,\n sampleRate = 22050,\n options: ValidateOptions = {},\n): number {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...options }\n : left;\n const validate = request.validate !== false;\n assertSamples('meteringStereoWidth', request.left, validate, 'left');\n assertSamples('meteringStereoWidth', request.right, validate, 'right');\n return requireModule().meteringStereoWidth(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n );\n}\n\n/**\n * Mid/side vectorscope point series. By default emits one point per input\n * sample; pass `maxPoints` to get a display-sized decimated point set (matching\n * the Node `meteringVectorscope` shape).\n */\nexport function meteringVectorscope(request: MeteringStereoDecimatedRequest): VectorscopeReport;\nexport function meteringVectorscope(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n options?: ScopeOptions,\n): VectorscopeReport;\nexport function meteringVectorscope(\n left: Float32Array | MeteringStereoDecimatedRequest,\n right?: Float32Array,\n sampleRate = 22050,\n options: ScopeOptions = {},\n): VectorscopeReport {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...options }\n : left;\n const validate = request.validate !== false;\n assertSamples('meteringVectorscope', request.left, validate, 'left');\n assertSamples('meteringVectorscope', request.right, validate, 'right');\n return requireModule().meteringVectorscopeDecimated(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.maxPoints ?? 0,\n );\n}\n\n/**\n * Display-sized mid/side vectorscope.\n *\n * @deprecated Pass `maxPoints` to {@link meteringVectorscope} instead; it now\n * folds `maxPoints` into the request, matching the Node surface. This alias is\n * kept for backward compatibility and simply delegates.\n */\nexport function meteringVectorscopeDecimated(\n request: MeteringStereoDecimatedRequest,\n): VectorscopeReport;\nexport function meteringVectorscopeDecimated(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n maxPoints?: number,\n options?: ValidateOptions,\n): VectorscopeReport;\nexport function meteringVectorscopeDecimated(\n left: Float32Array | MeteringStereoDecimatedRequest,\n right?: Float32Array,\n sampleRate = 22050,\n maxPoints = 0,\n options: ValidateOptions = {},\n): VectorscopeReport {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, maxPoints, ...options }\n : left;\n const validate = request.validate !== false;\n assertSamples('meteringVectorscopeDecimated', request.left, validate, 'left');\n assertSamples('meteringVectorscopeDecimated', request.right, validate, 'right');\n return requireModule().meteringVectorscopeDecimated(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.maxPoints ?? 0,\n );\n}\n\n/**\n * Phase-scope point series plus summary stats. By default emits one point per\n * input sample; pass `maxPoints` to decimate the point cloud for display\n * (matching the Node `meteringPhaseScope` shape). The summary stats are always\n * computed over the full-resolution signal.\n */\nexport function meteringPhaseScope(request: MeteringStereoDecimatedRequest): PhaseScopeReport;\nexport function meteringPhaseScope(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n options?: ScopeOptions,\n): PhaseScopeReport;\nexport function meteringPhaseScope(\n left: Float32Array | MeteringStereoDecimatedRequest,\n right?: Float32Array,\n sampleRate = 22050,\n options: ScopeOptions = {},\n): PhaseScopeReport {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, ...options }\n : left;\n const validate = request.validate !== false;\n assertSamples('meteringPhaseScope', request.left, validate, 'left');\n assertSamples('meteringPhaseScope', request.right, validate, 'right');\n return requireModule().meteringPhaseScopeDecimated(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.maxPoints ?? 0,\n );\n}\n\n/**\n * Display-sized phase scope.\n *\n * @deprecated Pass `maxPoints` to {@link meteringPhaseScope} instead; it now\n * folds `maxPoints` into the request, matching the Node surface. This alias is\n * kept for backward compatibility and simply delegates.\n */\nexport function meteringPhaseScopeDecimated(\n request: MeteringStereoDecimatedRequest,\n): PhaseScopeReport;\nexport function meteringPhaseScopeDecimated(\n left: Float32Array,\n right: Float32Array,\n sampleRate?: number,\n maxPoints?: number,\n options?: ValidateOptions,\n): PhaseScopeReport;\nexport function meteringPhaseScopeDecimated(\n left: Float32Array | MeteringStereoDecimatedRequest,\n right?: Float32Array,\n sampleRate = 22050,\n maxPoints = 0,\n options: ValidateOptions = {},\n): PhaseScopeReport {\n const request =\n left instanceof Float32Array\n ? { left, right: right as Float32Array, sampleRate, maxPoints, ...options }\n : left;\n const validate = request.validate !== false;\n assertSamples('meteringPhaseScopeDecimated', request.left, validate, 'left');\n assertSamples('meteringPhaseScopeDecimated', request.right, validate, 'right');\n return requireModule().meteringPhaseScopeDecimated(\n request.left,\n request.right,\n request.sampleRate ?? 22050,\n request.maxPoints ?? 0,\n );\n}\n\n/**\n * Welch-averaged magnitude / power / dB spectrum over the WHOLE mono signal (split\n * into Hann-windowed, 50%-overlapping `nFft`-length frames whose power spectra\n * are averaged). For a true single-frame snapshot, use\n * {@link meteringSpectrumFrame}.\n */\nexport function meteringSpectrum(request: MeteringSpectrumRequest): SpectrumReport;\nexport function meteringSpectrum(\n samples: Float32Array,\n sampleRate?: number,\n options?: SpectrumOptions & ValidateOptions,\n): SpectrumReport;\nexport function meteringSpectrum(\n samples: Float32Array | MeteringSpectrumRequest,\n sampleRate = 22050,\n options: SpectrumOptions & ValidateOptions = {},\n): SpectrumReport {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n assertSamples('meteringSpectrum', request.samples, request.validate !== false);\n return requireModule().meteringSpectrum(request.samples, request.sampleRate ?? 22050, request);\n}\n\n/**\n * True single-frame magnitude / power / dB spectrum (one Hann-windowed\n * `nFft`-length FFT), for spectrum-analyzer \"moment\" snapshots that must not be\n * time-averaged like {@link meteringSpectrum}. The analysis frame spans\n * `[frameOffset, frameOffset + nFft)`; samples past the end are zero-padded.\n *\n * The frame is also the only span validated: a non-finite sample inside it is\n * rejected, while one outside it neither reaches the FFT nor refuses the call.\n * The emptiness and `sampleRate` checks still cover the whole buffer. Cost per\n * call is therefore set by `nFft` rather than by the length of the buffer, so an\n * analyzer may poll a long recording frame by frame.\n */\nexport function meteringSpectrumFrame(request: MeteringSpectrumFrameRequest): SpectrumReport;\nexport function meteringSpectrumFrame(\n samples: Float32Array,\n sampleRate?: number,\n frameOffset?: number,\n options?: SpectrumOptions & ValidateOptions,\n): SpectrumReport;\nexport function meteringSpectrumFrame(\n samples: Float32Array | MeteringSpectrumFrameRequest,\n sampleRate = 22050,\n frameOffset = 0,\n options: SpectrumOptions & ValidateOptions = {},\n): SpectrumReport {\n const request =\n samples instanceof Float32Array ? { samples, sampleRate, frameOffset, ...options } : samples;\n const nFft = request.nFft ?? 0;\n assertSamplesInWindow(\n 'meteringSpectrumFrame',\n request.samples,\n request.validate !== false,\n request.frameOffset ?? 0,\n nFft > 0 ? nFft : DEFAULT_SPECTRUM_N_FFT,\n );\n return requireModule().meteringSpectrumFrame(\n request.samples,\n request.sampleRate ?? 22050,\n request.frameOffset ?? 0,\n request,\n );\n}\n\n/**\n * Compute per-channel min/max waveform buckets from interleaved audio.\n *\n * A non-finite sample is rejected rather than skipped, and `{ validate: false }`\n * does not change that — it only skips the JS pre-scan that names the offending\n * index. A bucket whose samples are not finite has no min/max to report, and the\n * `0`/`0` it would otherwise carry is what a waveform display draws as silence.\n */\nexport function waveformPeaks(request: WaveformPeaksRequest): WaveformPeaksReport;\nexport function waveformPeaks(\n samples: Float32Array,\n channels: number,\n options?: WaveformPeaksOptions,\n): WaveformPeaksReport;\nexport function waveformPeaks(\n samples: Float32Array | WaveformPeaksRequest,\n channels?: number,\n options: WaveformPeaksOptions = {},\n): WaveformPeaksReport {\n const request =\n samples instanceof Float32Array\n ? { samples, channels: channels as number, ...options }\n : samples;\n assertInterleavedSamples(\n 'waveformPeaks',\n request.samples,\n request.channels,\n request.validate !== false,\n );\n const samplesPerBucket = request.samplesPerBucket ?? 512;\n assertPositiveInteger('waveformPeaks', samplesPerBucket, 'samplesPerBucket');\n return requireModule().waveformPeaks(request.samples, request.channels, samplesPerBucket);\n}\n\n/**\n * Compute waveform peak buckets for several zoom levels.\n *\n * Shares {@link waveformPeaks}' bucket kernel, so a non-finite sample is\n * rejected here on the same rule.\n */\nexport function waveformPeakPyramid(request: WaveformPeakPyramidRequest): WaveformPeaksReport[];\nexport function waveformPeakPyramid(\n samples: Float32Array,\n channels: number,\n options?: WaveformPeakPyramidOptions,\n): WaveformPeaksReport[];\nexport function waveformPeakPyramid(\n samples: Float32Array | WaveformPeakPyramidRequest,\n channels?: number,\n options: WaveformPeakPyramidOptions = {},\n): WaveformPeaksReport[] {\n const request =\n samples instanceof Float32Array\n ? { samples, channels: channels as number, ...options }\n : samples;\n assertInterleavedSamples(\n 'waveformPeakPyramid',\n request.samples,\n request.channels,\n request.validate !== false,\n );\n const levels = request.samplesPerBucketLevels ?? [512, 1024, 2048, 4096];\n if (levels.length === 0) {\n throw new RangeError('waveformPeakPyramid: samplesPerBucketLevels must not be empty');\n }\n levels.forEach((level, index) => {\n assertPositiveInteger('waveformPeakPyramid', level, `samplesPerBucketLevels[${index}]`);\n });\n return requireModule().waveformPeakPyramid(request.samples, request.channels, levels);\n}\n","import type { ValidateOptions } from './validation';\n\n/**\n * Pitch class enum (C=0, C#=1, ..., B=11)\n */\nexport const PitchClass = {\n C: 0,\n Cs: 1,\n D: 2,\n Ds: 3,\n E: 4,\n F: 5,\n Fs: 6,\n G: 7,\n Gs: 8,\n A: 9,\n As: 10,\n B: 11,\n} as const;\n\nexport type PitchClass = (typeof PitchClass)[keyof typeof PitchClass];\n\n/**\n * Musical mode\n */\nexport const Mode = {\n Major: 0,\n Minor: 1,\n Dorian: 2,\n Phrygian: 3,\n Lydian: 4,\n Mixolydian: 5,\n Locrian: 6,\n} as const;\n\nexport type Mode = (typeof Mode)[keyof typeof Mode];\n\nexport type TempogramMode = 'autocorrelation' | 'auto' | 'ac' | 'cosine' | 0 | 1;\n\nexport const KeyProfile = {\n KrumhanslSchmuckler: 0,\n Temperley: 1,\n Shaath: 2,\n FaraldoEDMT: 3,\n FaraldoEDMA: 4,\n FaraldoEDMM: 5,\n BellmanBudge: 6,\n} as const;\n\nexport type KeyProfile = (typeof KeyProfile)[keyof typeof KeyProfile];\n\nexport type KeyProfileName =\n | 'ks'\n | 'krumhansl'\n | 'temperley'\n | 'shaath'\n | 'keyfinder'\n | 'faraldo-edmt'\n | 'edmt'\n | 'faraldo-edma'\n | 'edma'\n | 'faraldo-edmm'\n | 'edmm'\n | 'bellman-budge'\n | 'bellman';\n\n/**\n * Chord quality\n */\nexport const ChordQuality = {\n Major: 0,\n Minor: 1,\n Diminished: 2,\n Augmented: 3,\n Dominant7: 4,\n Major7: 5,\n Minor7: 6,\n Sus2: 7,\n Sus4: 8,\n Unknown: 9,\n Add9: 10,\n MinorAdd9: 11,\n Dim7: 12,\n HalfDim7: 13,\n Major9: 14,\n Dominant9: 15,\n Sus2Add4: 16,\n Major6: 17,\n Minor6: 18,\n MinorMajor7: 19,\n Dominant7Sus4: 20,\n Dominant11: 21,\n Dominant13: 22,\n Dominant7Flat9: 23,\n Dominant7Sharp9: 24,\n} as const;\n\nexport type ChordQuality = (typeof ChordQuality)[keyof typeof ChordQuality];\n\n/**\n * Section type.\n *\n * `PreChorus` is never produced by `analyze()`: it has no detection branch, so\n * filtering sections on it always yields an empty result. Every other value is\n * reachable. `Unknown` means the analyzer did not name the segment: no\n * boundary was detected, the segment matched none of the positive branches, or\n * the evidence for a musical function was too weak to assert one. The first\n * case comes with `confidence` 0; the last keeps the sub-threshold score, so a\n * caller can see how close the segment came to a label.\n */\nexport const SectionType = {\n Intro: 0,\n Verse: 1,\n PreChorus: 2,\n Chorus: 3,\n Bridge: 4,\n Instrumental: 5,\n Outro: 6,\n Unknown: 7,\n} as const;\n\nexport type SectionType = (typeof SectionType)[keyof typeof SectionType];\n\n/**\n * Detected musical key\n */\nexport interface Key {\n root: PitchClass;\n mode: Mode;\n /**\n * Share of the model's belief that this key is the answer, in `[0, 1)`.\n *\n * A softmax over the profile correlations of every candidate that was scored,\n * so it falls as the runner-up closes in and two keys that split the evidence\n * -- a relative major and minor, typically -- each report about half.\n *\n * This is the model's own belief, **not** a measured accuracy. It says how\n * decisively the chroma picked this key out of the candidate set; it does not\n * say how often that pick is right, and nothing here has been fitted against\n * annotated recordings. A confident wrong answer is entirely possible, so a\n * pipeline that branches on it must choose its own threshold against its own\n * material.\n */\n confidence: number;\n name: string;\n shortName: string;\n}\n\nexport interface KeyDetectionOptions extends ValidateOptions {\n nFft?: number;\n hopLength?: number;\n useHpss?: boolean;\n loudnessWeighted?: boolean;\n highPassHz?: number;\n modes?:\n | Mode[]\n | ('major' | 'minor' | 'dorian' | 'phrygian' | 'lydian' | 'mixolydian' | 'locrian')[]\n | 'major-minor'\n | 'all'\n | 'modal';\n profile?: KeyProfile | KeyProfileName;\n genreHint?: 'auto' | 'edm' | 'electronic' | 'dance' | 'pop' | 'classical' | 'jazz' | string;\n}\n\nexport interface KeyCandidate {\n key: Key;\n correlation: number;\n}\n\nexport interface ChordDetectionOptions extends ValidateOptions {\n minDuration?: number;\n smoothingWindow?: number;\n /** Final-template correlation threshold in [0, 1]; below it emits Unknown / N.C. */\n threshold?: number;\n useTriadsOnly?: boolean;\n /** STFT chroma window in samples at 22050 Hz, rescaled to the input rate so its duration is the same at every rate. */\n nFft?: number;\n hopLength?: number;\n useBeatSync?: boolean;\n useHmm?: boolean;\n hmmBeamWidth?: number;\n useKeyContext?: boolean;\n keyRoot?: PitchClass;\n keyMode?: Mode;\n detectInversions?: boolean;\n chromaMethod?: 'stft' | 'nnls';\n /**\n * Tuning offset of the recording in fractions of a semitone, the unit\n * `estimateTuning` returns; must be in `[-0.5, 0.5)`. Default 0 (concert A440).\n */\n tuning?: number;\n}\n\n/** Options for `analyzeBpm`. All fields are optional. */\nexport interface AnalyzeBpmOptions extends ValidateOptions {\n /** Lowest BPM to consider. Default 30. */\n bpmMin?: number;\n /** Highest BPM to consider. Default 300. */\n bpmMax?: number;\n /** Tempo prior the tracker is biased toward. Default 120. */\n startBpm?: number;\n /** FFT size for the onset envelope. Default 2048. */\n nFft?: number;\n /** Hop length for the onset envelope. Default 512. */\n hopLength?: number;\n /** Number of tempo candidates to return. Default 5. */\n maxCandidates?: number;\n}\n\n/** Options for `analyzeRhythm`. All fields are optional. */\nexport interface AnalyzeRhythmOptions extends ValidateOptions {\n /** Lowest BPM to consider. Default 60. */\n bpmMin?: number;\n /** Highest BPM to consider. Default 200. */\n bpmMax?: number;\n /** Tempo prior the tracker is biased toward. Default 120. */\n startBpm?: number;\n /** FFT size for the onset envelope. Default 2048. */\n nFft?: number;\n /** Hop length for the onset envelope. Default 512. */\n hopLength?: number;\n}\n\n/** Options for `analyzeDynamics`. All fields are optional. */\nexport interface AnalyzeDynamicsOptions extends ValidateOptions {\n /** Loudness-curve window length in seconds. Default 0.4. */\n windowSec?: number;\n /** Hop length for the loudness curve. Default 512. */\n hopLength?: number;\n /** Crest-factor (dB) below which the signal is flagged as compressed. Default 6. */\n compressionThreshold?: number;\n}\n\n/** Options for `analyzeTimbre`. All fields are optional. */\nexport interface AnalyzeTimbreOptions extends ValidateOptions {\n /** FFT size. Default 2048. */\n nFft?: number;\n /** Hop length. Default 512. */\n hopLength?: number;\n /** Number of Mel bands. Default 128. */\n nMels?: number;\n /** Number of MFCCs. Default 13. */\n nMfcc?: number;\n /** Per-window analysis length in seconds. Default 0.5. */\n windowSec?: number;\n}\n\n/** Options for `analyzeSections`. All fields are optional. */\nexport interface AnalyzeSectionsOptions {\n /** FFT size. Default 2048. */\n nFft?: number;\n /** Hop length. Default 512. */\n hopLength?: number;\n /** Minimum section duration in seconds. Default 4. */\n minSectionSec?: number;\n}\n\n/**\n * Detected beat\n */\nexport interface Beat {\n /** Beat position in seconds. */\n time: number;\n /**\n * Onset-envelope value sampled at the beat's frame.\n *\n * @remarks\n * A single raw frame of the onset envelope, not a normalized or relative\n * salience: it is unbounded, its scale depends on the material, and it moves\n * with any jitter in the beat position. For accent scoring use\n * {@link BeatObservations.onsetStrength}, which is the windowed aggregate the\n * library's own downbeat pass scores.\n */\n strength: number;\n}\n\n/**\n * Beat-level evidence behind the downbeat and meter decisions.\n *\n * @remarks\n * These are inputs to the library's decision, not outputs of it, exposed so a\n * caller running its own meter work scores the same evidence instead of\n * reconstructing a weaker approximation from the frame-level onset envelope.\n * Each non-empty stream holds one value per entry of\n * {@link AnalysisResult.beats} and indexes in parallel with it. An empty stream\n * means the analysis could not produce it, which is not the same as every beat\n * having scored zero.\n */\nexport interface BeatObservations {\n /**\n * Beat-local onset-strength window.\n *\n * @remarks\n * Unlike {@link Beat.strength} this is aggregated over a window around the\n * beat rather than sampled at a single frame, so it is the stream to score\n * accents with.\n */\n onsetStrength: number[];\n /**\n * Beat-local low-frequency energy — the accent evidence a log-spectral\n * difference discards. Empty when the analysis ran without audio.\n */\n lowFrequencyEnergy: number[];\n /** Per-beat chord-change evidence. Empty until chords are analyzed. */\n chordChange: number[];\n}\n\n/**\n * Detected chord\n */\nexport interface Chord {\n root: PitchClass;\n bass: PitchClass;\n /** Canonical core spelling; stable across all language bindings. */\n rootName: string;\n /** Canonical core spelling; stable across all language bindings. */\n bassName: string;\n quality: ChordQuality;\n start: number;\n end: number;\n /** Derived from `end - start`; the core carries only the two endpoints. */\n duration: number;\n confidence: number;\n name: string;\n}\n\n/** A chord in {@link AnalysisResult.chords}, which carries its function in the key. */\nexport interface AnalysisChord extends Chord {\n /**\n * Roman numeral of the chord relative to {@link AnalysisResult.key}, e.g.\n * `'V7'`, `'vi'`, `'bVII'`. The same spelling `chordFunctionalAnalysis`\n * returns for that chord and key. Empty for a chord that is N.C.\n */\n romanNumeral: string;\n}\n\nexport interface ChordAnalysisResult {\n chords: Chord[];\n}\n\n/**\n * Detected section\n */\nexport interface Section {\n type: SectionType;\n start: number;\n end: number;\n energyLevel: number;\n confidence: number;\n name: string;\n}\n\n/** Options for `detectBoundaries`. All fields are optional. */\nexport interface BoundaryOptions {\n /** FFT size used for the structural features. Default 2048. */\n nFft?: number;\n /** Hop length in samples. Default 512. */\n hopLength?: number;\n /** Checkerboard kernel size in frames. Default 64. */\n kernelSize?: number;\n /**\n * Relative novelty threshold, applied to the curve after it has been scaled by\n * its own maximum. Selects how prominent a peak must be *within this track*; it\n * says nothing about how much the features actually changed. Default 0.3.\n */\n threshold?: number;\n /**\n * Novelty floor applied to the raw response before that scaling, asking whether\n * anything changed at all. Default 0.005. Set to 0 to gate on {@link threshold}\n * alone -- but self-scaling turns residual fluctuation into peaks of 1.0, so a\n * stationary input then segments anyway. Lowering the floor does not recover\n * level-only structure: a level change turns the feature vector about five times\n * less than a comparable pitch change, landing below what steady noise produces,\n * so the noise is admitted first.\n */\n absoluteThreshold?: number;\n /** Number of MFCC coefficients. Default 13. */\n nMfcc?: number;\n /** Number of chroma bins. Default 12. */\n nChroma?: number;\n /** Minimum spacing between peaks, in seconds. Default 2. */\n peakDistance?: number;\n /** Use MFCC features. Default `true`. */\n useMfcc?: boolean;\n /** Use chroma features. Default `true`. */\n useChroma?: boolean;\n}\n\n/**\n * A single detected structural boundary (mirrors the C `SonareBoundary`).\n */\nexport interface Boundary {\n /** Boundary time in seconds (the authoritative output). */\n time: number;\n /**\n * Index into the analysis grid, on {@link BoundaryResult.sampleRate}'s time\n * base rather than the source's. For a long-form input the feature grid is\n * additionally mean-pooled, so this indexes the pooled grid; use `time` for\n * sample/second mapping either way.\n */\n frame: number;\n /** Boundary strength (novelty score). */\n strength: number;\n}\n\n/**\n * Result of `detectBoundaries` (mirrors the C `SonareBoundaryResult`).\n */\nexport interface BoundaryResult {\n /** Detected transitions, in time order. */\n boundaries: Boundary[];\n /**\n * Novelty curve scaled by its own maximum, one value per analysis frame. A\n * peak of 1 means \"the most novel frame here\", not \"a large change\"; multiply\n * by {@link noveltyPeak} to recover the raw response\n * {@link BoundaryOptions.absoluteThreshold} is compared against.\n */\n noveltyCurve: Float32Array;\n /**\n * The largest raw checkerboard response, before normalization. Zero when the\n * curve was left unnormalized because nothing rose above the numerical floor.\n */\n noveltyPeak: number;\n /**\n * The rate the analysis ran at, not the input's: a source above 22050 Hz is\n * resampled to 22050 Hz before any feature is computed, which is what makes\n * {@link Boundary.frame} interpretable.\n */\n sampleRate: number;\n /** Hop length the analysis grid was built on. */\n hopLength: number;\n /** Analysis frame count, pooled for a long-form input. */\n nFrames: number;\n /**\n * Feature pooling stride: 1 for every realistic input length, otherwise the\n * number of raw STFT frames averaged into each analysis frame.\n */\n frameStride: number;\n}\n\n/**\n * A single melody contour point (mirrors the C `SonareMelodyPoint`).\n */\nexport interface MelodyPoint {\n /** Frame time in seconds. */\n time: number;\n /** Estimated fundamental frequency in Hz (0 when unvoiced). */\n frequency: number;\n /** Voicing confidence in `[0, 1]`. */\n confidence: number;\n}\n\n/**\n * Melody analysis result (mirrors the C `SonareMelodyResult`).\n */\nexport interface MelodyResult {\n points: MelodyPoint[];\n pitchRangeOctaves: number;\n pitchStability: number;\n meanFrequency: number;\n vibratoRate: number;\n}\n\n/**\n * Timbre characteristics\n */\nexport interface Timbre {\n brightness: number;\n warmth: number;\n density: number;\n roughness: number;\n complexity: number;\n}\n\n/**\n * Dynamics characteristics\n */\nexport interface Dynamics {\n dynamicRangeDb: number;\n peakDb: number;\n rmsDb: number;\n loudnessRangeDb: number;\n crestFactor: number;\n isCompressed: boolean;\n}\n\n/**\n * Time signature\n */\nexport interface TimeSignature {\n numerator: number;\n denominator: number;\n /**\n * Support for this signature in `[0, 1]`.\n *\n * @remarks\n * What it measures depends on which field the signature arrived in. On\n * {@link MeterEstimate.timeSignature} it is derived from the margin over the\n * runner-up; on a {@link MeterEstimate.candidates} entry it is that\n * candidate's share of the summed support. The two are not comparable, so\n * read the value from the field you meant rather than from whichever one is\n * to hand.\n */\n confidence: number;\n}\n\n/**\n * Meter estimated over a caller-supplied beat series.\n */\nexport interface MeterEstimate {\n /**\n * Selected time signature.\n *\n * @remarks\n * Its `confidence` is the margin over the runner-up — how separated the\n * winner is — not the share-of-support a {@link candidates} entry carries\n * under the same field name.\n */\n timeSignature: TimeSignature;\n /** Beat index the first measure starts on, in `[0, timeSignature.numerator)`. */\n downbeatPhase: number;\n /**\n * Whether a search ran, as opposed to the fixed fallback being reported.\n *\n * @remarks\n * `false` means the beat series was too short to score any candidate, and\n * every other field then carries that fallback rather than a measurement —\n * `timeSignature.confidence` included, which is 0, so an unchecked read\n * degrades toward \"no idea\" rather than toward a middling detection. Read\n * this before treating a short span's answer as a detection.\n */\n searched: boolean;\n /**\n * How the bar divides, in beats per accent group.\n *\n * @remarks\n * `[3, 2, 2]` is the 7/8 an aksak meter notates as 3+2+2, and `[2, 2]` an\n * ordinary four. Always sums to `timeSignature.numerator`.\n *\n * A single entry means no internal division was resolved — the numerator has\n * none to find, it was too wide to search, or the span was too short to\n * search at all.\n *\n * This is also what tells a compound bar from a simple one: per-beat accents\n * cannot say how a beat subdivides, so a six accented 3+3 keeps the requested\n * denominator and reports `[3, 3]` rather than being promoted to 6/8.\n */\n grouping: number[];\n /**\n * Multi-comb score per requested candidate numerator.\n *\n * @remarks\n * Parallel to the `candidateNumerators` that were requested, in the order\n * they were given. This does NOT index alike with {@link candidates}, which\n * is ordered by descending support.\n *\n * Standardized and signed: zero is the level a numerator reaches on beats\n * carrying no meter, so a negative entry means less support than noise would\n * produce. Only the ordering and the gaps between entries carry meaning.\n *\n * Comparable only within one result. A score grows with the square root of\n * how many beats were scored, so the same meter over twice the beats scores\n * about 1.41 times as high; a segmentation search comparing spans of\n * different lengths has to normalize for length first.\n */\n candidateScores: number[];\n /**\n * Candidate signatures ordered by descending support.\n *\n * @remarks\n * A ranking, so entry `k` is the k-th best hypothesis — not the k-th\n * requested numerator. Use {@link candidateScores} to read the score of a\n * specific requested numerator.\n *\n * Each entry's `confidence` is that candidate's share of the summed support,\n * so the entries sum to one. It is a different quantity from\n * {@link timeSignature}'s margin-derived confidence, which shares the field\n * name and nothing else.\n */\n candidates: TimeSignature[];\n}\n\n/** Existing tempo-estimator hypothesis retained by unified analysis. */\nexport interface BpmHypothesis {\n value: number;\n confidence: number;\n relation: 'primary' | 'half' | 'double' | 'other';\n}\n\n/**\n * Rhythm features\n */\nexport interface RhythmFeatures {\n syncopation: number;\n grooveType: string;\n patternRegularity: number;\n tempoStability: number;\n timeSignature: TimeSignature;\n}\n\n/**\n * Melody contour from the unified analysis (pitch trajectory + summary stats).\n */\nexport interface MelodyContour {\n pitchRangeOctaves: number;\n pitchStability: number;\n meanFrequency: number;\n vibratoRate: number;\n pitches: MelodyPoint[];\n}\n\n/**\n * Complete analysis result\n */\nexport interface AnalysisResult {\n bpm: number;\n bpmConfidence: number;\n bpmCandidates: BpmHypothesis[];\n key: Key;\n timeSignature: TimeSignature;\n timeSignatureCandidates: TimeSignature[];\n beatTimes: Float32Array;\n beats: Beat[];\n /**\n * Indices into {@link AnalysisResult.beats} that fall on a measure start.\n *\n * @remarks\n * Not the same length as `beats` — it holds one entry per detected downbeat,\n * and each entry indexes `beats`, so `beats[downbeatIndices[k]]` is the k-th\n * downbeat. Testing a beat for downbeat status is a membership check on this\n * list rather than a time comparison against a separate downbeat series.\n */\n downbeatIndices: number[];\n /**\n * Beat index the first measure starts on, in `[0, timeSignature.numerator)`.\n *\n * @remarks\n * The meter estimator's phase, so `downbeatIndices` normally begins at this\n * value. It is not re-derived when downbeats are refined from chord and\n * low-frequency-energy evidence, so the two can disagree when the refinement\n * moves the first measure start.\n */\n downbeatPhase: number;\n /**\n * Beat-level evidence behind the downbeat and meter decisions, parallel to\n * {@link AnalysisResult.beats}.\n */\n beatObservations: BeatObservations;\n /**\n * Smoothed local tempo at each beat, in BPM, parallel to\n * {@link AnalysisResult.beats}.\n *\n * @remarks\n * Empty unless `computeTempoCurve` was set, and empty regardless when fewer\n * than two beats were detected, since a tempo is a property of the interval\n * between two beats. The last entry repeats the tempo of the interval leading\n * into the final beat, which opens no interval of its own.\n *\n * Values are continuous, not points on a tempo grid: each is a weighted\n * average, in log tempo, of the beat intervals around it. A steady tempo\n * reads within about 1% at every beat, and a tempo that moves is followed a\n * few beats late.\n *\n * This is the local tempo rather than {@link AnalysisResult.bpm} resampled:\n * on material whose tempo moves it departs from `bpm`, and reading a single\n * number out of it is not how to get the global tempo.\n */\n beatLocalBpm: number[];\n chords: AnalysisChord[];\n sections: Section[];\n timbre: Timbre;\n dynamics: Dynamics;\n rhythm: RhythmFeatures;\n melody: MelodyContour;\n form: string;\n}\n","import { resolveEnumOrdinal } from './codes';\nimport type {\n AnalysisResult,\n ChordAnalysisResult,\n ChordDetectionOptions,\n ChordQuality,\n KeyCandidate,\n KeyDetectionOptions,\n KeyProfileName,\n PitchClass,\n SectionType,\n} from './public_types';\nimport { KeyProfile as KeyProfileValues, Mode } from './public_types';\nimport type {\n WasmAnalysisResult,\n WasmChordAnalysisResult,\n WasmKeyCandidateResult,\n} from './sonare.js';\n\nconst PITCH_CLASS_NAMES = [\n 'C',\n 'C#',\n 'D',\n 'D#',\n 'E',\n 'F',\n 'F#',\n 'G',\n 'G#',\n 'A',\n 'A#',\n 'B',\n] as const;\n\nfunction pitchClassName(value: number): string {\n return PITCH_CLASS_NAMES[value] ?? 'C';\n}\n\nexport function convertKeyCandidate(wasm: WasmKeyCandidateResult): KeyCandidate {\n return {\n key: {\n root: wasm.key.root as PitchClass,\n mode: wasm.key.mode as Mode,\n confidence: wasm.key.confidence,\n name: wasm.key.name,\n shortName: wasm.key.shortName,\n },\n correlation: wasm.correlation,\n };\n}\n\n// Consolidated spelling -> ordinal tables, resolved through the same\n// resolveEnumOrdinal() primitive as panModeCode/panLawCode/etc. in ./codes.\n// An unmapped string or an out-of-range numeric ordinal throws RangeError\n// instead of silently resolving to `undefined` (which used to reach the WASM\n// layer as a mistyped argument) or passing an unvalidated raw number through.\nconst KEY_MODE_VALUES: Readonly<Record<string, number>> = {\n major: Mode.Major,\n minor: Mode.Minor,\n dorian: Mode.Dorian,\n phrygian: Mode.Phrygian,\n lydian: Mode.Lydian,\n mixolydian: Mode.Mixolydian,\n locrian: Mode.Locrian,\n};\n\nconst KEY_PROFILE_VALUES: Readonly<Record<KeyProfileName, number>> = {\n ks: KeyProfileValues.KrumhanslSchmuckler,\n krumhansl: KeyProfileValues.KrumhanslSchmuckler,\n temperley: KeyProfileValues.Temperley,\n shaath: KeyProfileValues.Shaath,\n keyfinder: KeyProfileValues.Shaath,\n 'faraldo-edmt': KeyProfileValues.FaraldoEDMT,\n edmt: KeyProfileValues.FaraldoEDMT,\n 'faraldo-edma': KeyProfileValues.FaraldoEDMA,\n edma: KeyProfileValues.FaraldoEDMA,\n 'faraldo-edmm': KeyProfileValues.FaraldoEDMM,\n edmm: KeyProfileValues.FaraldoEDMM,\n 'bellman-budge': KeyProfileValues.BellmanBudge,\n bellman: KeyProfileValues.BellmanBudge,\n};\n\nexport function keyModeValues(modes: KeyDetectionOptions['modes'] | undefined): number[] {\n if (!modes) {\n return [];\n }\n if (modes === 'major-minor') {\n return [Mode.Major, Mode.Minor];\n }\n if (modes === 'all' || modes === 'modal') {\n return [\n Mode.Major,\n Mode.Minor,\n Mode.Dorian,\n Mode.Phrygian,\n Mode.Lydian,\n Mode.Mixolydian,\n Mode.Locrian,\n ];\n }\n return modes.map((mode) => resolveEnumOrdinal(mode, KEY_MODE_VALUES, 'key mode'));\n}\n\nexport function keyProfileValue(profile: KeyDetectionOptions['profile'] | undefined): number {\n if (profile === undefined) {\n return -1;\n }\n return resolveEnumOrdinal(profile, KEY_PROFILE_VALUES, 'key profile');\n}\n\nexport function convertChordAnalysisResult(wasm: WasmChordAnalysisResult): ChordAnalysisResult {\n return {\n chords: wasm.chords.map((c) => ({\n root: c.root as PitchClass,\n bass: c.bass as PitchClass,\n rootName: pitchClassName(c.root),\n bassName: pitchClassName(c.bass),\n quality: c.quality as ChordQuality,\n start: c.start,\n end: c.end,\n duration: c.end - c.start,\n confidence: c.confidence,\n name: c.name,\n })),\n };\n}\n\nexport function chordChromaMethodValue(method: ChordDetectionOptions['chromaMethod']): number {\n if (method === 'stft') {\n return 0;\n }\n if (method === 'nnls') {\n return 1;\n }\n throw new Error(`Invalid chord chroma method: ${method}`);\n}\n\nexport function convertAnalysisResult(wasm: WasmAnalysisResult): AnalysisResult {\n const beatTimes = new Float32Array(wasm.beats.length);\n for (let i = 0; i < wasm.beats.length; i++) {\n beatTimes[i] = wasm.beats[i].time;\n }\n return {\n bpm: wasm.bpm,\n bpmConfidence: wasm.bpmConfidence,\n bpmCandidates: wasm.bpmCandidates.map((candidate) => ({\n value: candidate.value,\n confidence: candidate.confidence,\n relation: candidate.relation,\n })),\n key: {\n root: wasm.key.root as PitchClass,\n mode: wasm.key.mode as Mode,\n confidence: wasm.key.confidence,\n name: wasm.key.name,\n shortName: wasm.key.shortName,\n },\n timeSignature: wasm.timeSignature,\n timeSignatureCandidates: wasm.timeSignatureCandidates,\n beatTimes,\n beats: wasm.beats,\n downbeatIndices: wasm.downbeatIndices,\n downbeatPhase: wasm.downbeatPhase,\n beatObservations: wasm.beatObservations,\n beatLocalBpm: wasm.beatLocalBpm,\n chords: wasm.chords.map((c) => ({\n root: c.root as PitchClass,\n bass: c.bass as PitchClass,\n rootName: pitchClassName(c.root),\n bassName: pitchClassName(c.bass),\n quality: c.quality as ChordQuality,\n start: c.start,\n end: c.end,\n duration: c.end - c.start,\n confidence: c.confidence,\n name: c.name,\n romanNumeral: c.romanNumeral,\n })),\n sections: wasm.sections.map((s) => ({\n type: s.type as SectionType,\n start: s.start,\n end: s.end,\n energyLevel: s.energyLevel,\n confidence: s.confidence,\n name: s.name,\n })),\n timbre: wasm.timbre,\n dynamics: wasm.dynamics,\n rhythm: wasm.rhythm,\n melody: wasm.melody,\n form: wasm.form,\n };\n}\n","import {\n chordChromaMethodValue,\n convertAnalysisResult,\n convertChordAnalysisResult,\n convertKeyCandidate,\n keyModeValues,\n keyProfileValue,\n} from './analysis_helpers';\nimport { getSonareModule } from './module_state';\nimport type {\n AcousticOptions,\n AcousticResult,\n AnalysisResult,\n AnalyzeBpmOptions,\n AnalyzeDynamicsOptions,\n AnalyzeRhythmOptions,\n AnalyzeTimbreOptions,\n ChordAnalysisResult,\n ChordDetectionOptions,\n Key,\n KeyCandidate,\n KeyDetectionOptions,\n MeterEstimate,\n RirResult,\n RirSynthOptions,\n RoomEstimateOptions,\n RoomEstimateResult,\n RoomMorphOptions,\n RoomMorphResult,\n} from './public_types';\nimport { Mode, PitchClass } from './public_types';\nimport type { ProgressCallback, WasmAcousticResult } from './sonare.js';\nimport type { ValidateOptions } from './validation';\nimport {\n assertFiniteScalar,\n assertNonNegativeInteger,\n assertSampleRate,\n assertSamples,\n} from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\ntype GuardedOptions = ValidateOptions;\n\n/** Canonical request form for one-shot analysis functions. */\nexport interface SamplesRequest extends GuardedOptions {\n samples: Float32Array;\n sampleRate?: number;\n}\n\n/** Peak-picking configuration for {@link detectOnsets}. */\nexport interface OnsetDetectOptions {\n nFft?: number;\n hopLength?: number;\n threshold?: number;\n preMax?: number;\n postMax?: number;\n preAvg?: number;\n postAvg?: number;\n delta?: number;\n wait?: number;\n backtrack?: boolean;\n backtrackRange?: number;\n}\nexport interface DetectOnsetsRequest extends SamplesRequest, OnsetDetectOptions {}\n\n/** Canonical request form for key detection functions. */\nexport interface DetectKeyRequest extends KeyDetectionOptions, SamplesRequest {}\n\n/** Canonical request form for analysis with synchronous progress reporting. */\nexport interface AnalyzeWithProgressRequest extends SamplesRequest {\n onProgress?: ProgressCallback;\n cancel?: () => boolean;\n /** Analysis options, with the same fields and defaults {@link analyze} takes. */\n options?: MusicAnalyzeOptions;\n}\n\n/** Canonical request form for chord detection. */\nexport interface DetectChordsRequest extends ChordDetectionOptions, SamplesRequest {}\n\n/** Canonical request form for functional chord analysis. */\nexport interface ChordFunctionalAnalysisRequest extends DetectChordsRequest {\n keyRoot: PitchClass;\n /** Musical mode; defaults to {@link Mode.Major}. */\n keyMode?: Mode;\n}\n\n/** Canonical request form for impulse-response analysis. */\nexport interface AnalyzeImpulseResponseRequest extends SamplesRequest {\n nOctaveBands?: number;\n minDecayDb?: number;\n}\n\n/** Canonical request form for acoustic analysis. */\nexport interface DetectAcousticRequest extends AcousticOptions, SamplesRequest {}\n\n/** Canonical request form for equivalent-room estimation. */\nexport interface EstimateRoomRequest extends RoomEstimateOptions, SamplesRequest {}\n\n/** Canonical request form for room-reverb morphing. */\nexport interface RoomMorphRequest extends RoomMorphOptions, GuardedOptions {\n samples: Float32Array;\n sampleRate: number;\n}\n\n/** Canonical request forms for detailed music-analysis APIs. */\nexport interface AnalyzeBpmRequest extends AnalyzeBpmOptions, SamplesRequest {}\nexport interface AnalyzeRhythmRequest extends AnalyzeRhythmOptions, SamplesRequest {}\nexport interface AnalyzeDynamicsRequest extends AnalyzeDynamicsOptions, SamplesRequest {}\nexport interface AnalyzeTimbreRequest extends AnalyzeTimbreOptions, SamplesRequest {}\n\nfunction validateAnalysisInput(\n fnName: string,\n samples: Float32Array,\n sampleRate: number,\n options: GuardedOptions = {},\n): void {\n assertSampleRate(fnName, sampleRate);\n assertSamples(fnName, samples, options.validate !== false);\n}\n\n// ============================================================================\n// Quick API (High-level Analysis)\n// ============================================================================\n\n/**\n * Detect BPM from audio samples.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @returns Detected BPM\n */\nexport function detectBpm(request: SamplesRequest): number;\nexport function detectBpm(\n samples: Float32Array,\n sampleRate?: number,\n options?: GuardedOptions,\n): number;\nexport function detectBpm(\n samples: Float32Array | SamplesRequest,\n sampleRate = 22050,\n options: GuardedOptions = {},\n): number {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('detectBpm', request.samples, request.sampleRate ?? 22050, request);\n return requireModule().detectBpm(request.samples, request.sampleRate ?? 22050);\n}\n\n/**\n * Detect musical key from audio samples.\n *\n * The chroma is read at concert A440; a tuning offset is applied through\n * {@link analyze}'s `tuning` option (and to chords through {@link detectChords}).\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @returns Detected key\n */\nexport function detectKey(request: DetectKeyRequest): Key;\nexport function detectKey(\n samples: Float32Array,\n sampleRate?: number,\n options?: KeyDetectionOptions,\n): Key;\nexport function detectKey(\n samples: Float32Array | DetectKeyRequest,\n sampleRate = 22050,\n options: KeyDetectionOptions = {},\n): Key {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('detectKey', request.samples, request.sampleRate ?? 22050, request);\n const result = requireModule()._detectKeyWithOptions(\n request.samples,\n request.sampleRate ?? 22050,\n request.nFft ?? 4096,\n request.hopLength ?? 512,\n request.useHpss ?? false,\n request.loudnessWeighted ?? false,\n request.highPassHz ?? 0,\n keyModeValues(request.modes),\n keyProfileValue(request.profile),\n request.genreHint ?? '',\n );\n return {\n root: result.root as PitchClass,\n mode: result.mode as Mode,\n confidence: result.confidence,\n name: result.name,\n shortName: result.shortName,\n };\n}\n\nexport function detectKeyCandidates(request: DetectKeyRequest): KeyCandidate[];\nexport function detectKeyCandidates(\n samples: Float32Array,\n sampleRate?: number,\n options?: KeyDetectionOptions,\n): KeyCandidate[];\nexport function detectKeyCandidates(\n samples: Float32Array | DetectKeyRequest,\n sampleRate = 22050,\n options: KeyDetectionOptions = {},\n): KeyCandidate[] {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput(\n 'detectKeyCandidates',\n request.samples,\n request.sampleRate ?? 22050,\n request,\n );\n // The embind value marshalling returns an array whose constructor is not this\n // realm's Array; chaining .map() onto it propagates that constructor via\n // Symbol.species, leaving a result that structuredClone (and so postMessage to\n // a Worker) rejects with \"could not be cloned\". Array.from() re-roots it as a\n // plain Array before mapping.\n const candidates = requireModule()._detectKeyCandidates(\n request.samples,\n request.sampleRate ?? 22050,\n request.nFft ?? 4096,\n request.hopLength ?? 512,\n request.useHpss ?? false,\n request.loudnessWeighted ?? false,\n request.highPassHz ?? 0,\n keyModeValues(request.modes),\n keyProfileValue(request.profile),\n request.genreHint ?? '',\n );\n return Array.from(candidates, convertKeyCandidate);\n}\n\n/**\n * Detect onset times from audio samples.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @returns Array of onset times in seconds\n */\nexport function detectOnsets(request: DetectOnsetsRequest): Float32Array;\nexport function detectOnsets(\n samples: Float32Array,\n sampleRate?: number,\n options?: OnsetDetectOptions & GuardedOptions,\n): Float32Array;\nexport function detectOnsets(\n samples: Float32Array | DetectOnsetsRequest,\n sampleRate = 22050,\n options: OnsetDetectOptions & GuardedOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('detectOnsets', request.samples, request.sampleRate ?? 22050, request);\n return requireModule().detectOnsets(request.samples, request.sampleRate ?? 22050, request);\n}\n\n/**\n * Detect beat times from audio samples.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @returns Array of beat times in seconds\n */\nexport function detectBeats(request: SamplesRequest): Float32Array;\nexport function detectBeats(\n samples: Float32Array,\n sampleRate?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function detectBeats(\n samples: Float32Array | SamplesRequest,\n sampleRate = 22050,\n options: GuardedOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('detectBeats', request.samples, request.sampleRate ?? 22050, request);\n return requireModule().detectBeats(request.samples, request.sampleRate ?? 22050);\n}\n\n/**\n * Detect downbeat times from audio samples.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @returns Array of downbeat times in seconds\n */\nexport function detectDownbeats(request: SamplesRequest): Float32Array;\nexport function detectDownbeats(\n samples: Float32Array,\n sampleRate?: number,\n options?: GuardedOptions,\n): Float32Array;\nexport function detectDownbeats(\n samples: Float32Array | SamplesRequest,\n sampleRate = 22050,\n options: GuardedOptions = {},\n): Float32Array {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('detectDownbeats', request.samples, request.sampleRate ?? 22050, request);\n return requireModule().detectDownbeats(request.samples, request.sampleRate ?? 22050);\n}\n\n/**\n * Detect chords from audio samples.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param options - Optional chord detection settings\n * @returns Detected chord segments\n */\nexport function detectChords(request: DetectChordsRequest): ChordAnalysisResult;\nexport function detectChords(\n samples: Float32Array,\n sampleRate?: number,\n options?: ChordDetectionOptions,\n): ChordAnalysisResult;\nexport function detectChords(\n samples: Float32Array | DetectChordsRequest,\n sampleRate = 22050,\n options: ChordDetectionOptions = {},\n): ChordAnalysisResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('detectChords', request.samples, request.sampleRate ?? 22050, request);\n const result = requireModule().detectChords(\n request.samples,\n request.sampleRate ?? 22050,\n request.minDuration ?? 0.3,\n request.smoothingWindow ?? 2.0,\n request.threshold ?? 0.5,\n request.useTriadsOnly ?? false,\n request.nFft ?? 2048,\n request.hopLength ?? 512,\n request.useBeatSync ?? true,\n request.useHmm ?? false,\n request.hmmBeamWidth ?? 24,\n request.useKeyContext ?? false,\n request.keyRoot ?? PitchClass.C,\n request.keyMode ?? Mode.Major,\n request.detectInversions ?? false,\n chordChromaMethodValue(request.chromaMethod ?? 'stft'),\n request.tuning ?? 0,\n );\n return convertChordAnalysisResult(result);\n}\n\n/**\n * Functional (Roman-numeral) harmonic analysis of the detected chord\n * progression, relative to the given key. Mirrors the C-ABI\n * `sonare_chord_functional_analysis` and the Node/Python `chordFunctionalAnalysis`.\n *\n * @returns One Roman-numeral label (e.g. \"I\", \"IV\", \"V\", \"vi\") per detected chord\n */\nexport function chordFunctionalAnalysis(request: ChordFunctionalAnalysisRequest): string[];\nexport function chordFunctionalAnalysis(\n samples: Float32Array,\n keyRoot: PitchClass,\n keyMode?: Mode,\n sampleRate?: number,\n options?: ChordDetectionOptions,\n): string[];\nexport function chordFunctionalAnalysis(\n samples: Float32Array | ChordFunctionalAnalysisRequest,\n keyRoot?: PitchClass,\n keyMode?: Mode,\n sampleRate = 22050,\n options: ChordDetectionOptions = {},\n): string[] {\n const request =\n samples instanceof Float32Array\n ? { samples, keyRoot, keyMode, sampleRate, ...options }\n : samples;\n validateAnalysisInput(\n 'chordFunctionalAnalysis',\n request.samples,\n request.sampleRate ?? 22050,\n request,\n );\n return requireModule().chordFunctionalAnalysis(\n request.samples,\n request.keyRoot as PitchClass,\n request.keyMode ?? Mode.Major,\n request.sampleRate ?? 22050,\n request.minDuration ?? 0.3,\n request.smoothingWindow ?? 2.0,\n request.threshold ?? 0.5,\n request.useTriadsOnly ?? false,\n request.nFft ?? 2048,\n request.hopLength ?? 512,\n request.useBeatSync ?? true,\n request.useHmm ?? false,\n request.hmmBeamWidth ?? 24,\n request.useKeyContext ?? false,\n request.detectInversions ?? false,\n chordChromaMethodValue(request.chromaMethod ?? 'stft'),\n request.tuning ?? 0,\n );\n}\n\n/**\n * Options for {@link analyze}. Every field is optional and falls back to the\n * core default when omitted.\n */\nexport interface MusicAnalyzeOptions {\n nFft?: number;\n hopLength?: number;\n bpmMin?: number;\n bpmMax?: number;\n startBpm?: number;\n useTriadsOnly?: boolean;\n useHpss?: boolean;\n chromaHighpassHz?: number;\n useBassWeighted?: boolean;\n chromaHopMultiplier?: number;\n useChordHmm?: boolean;\n useChordKeyContext?: boolean;\n chordHmmBeamWidth?: number;\n detectChordInversions?: boolean;\n /**\n * Track a locally updated tempo prior during beat tracking (default: false).\n */\n adaptiveTempo?: boolean;\n /**\n * Length of the local tempo context in beats (default: 8). Must be positive.\n */\n tempoUpdateIntervalBeats?: number;\n /**\n * Decode a per-beat local tempo curve into\n * {@link AnalysisResult.beatLocalBpm} (default: false).\n *\n * @remarks\n * Off by default because it is an extra output rather than a better analysis:\n * nothing else in the result changes, and a caller that does not read the\n * curve would pay a decode over the beat grid for nothing.\n *\n * The curve describes the beat grid it was decoded from, and beat tracking\n * holds a fixed tempo prior unless {@link MusicAnalyzeOptions.adaptiveTempo}\n * is also set, so measuring a tempo that moves needs both.\n */\n computeTempoCurve?: boolean;\n /**\n * Meter numerators the estimator scores (default: `[3, 4, 6]`).\n *\n * @remarks\n * Adding a numerator widens the search; it does not force the result. The\n * list must hold between 1 and 16 entries, each in `[2, 32]`.\n */\n meterCandidateNumerators?: number[];\n /**\n * Beat unit reported for the detected meter (default: 4). Must be a power of\n * two in `[1, 32]`. The estimator still reports 8 on its own when it resolves\n * a compound meter, so this is the unit for everything else.\n */\n meterDenominator?: number;\n /**\n * Tuning offset of the recording in fractions of a semitone, the unit\n * `estimateTuning` returns; must be in `[-0.5, 0.5)`. Every chroma the\n * analysis builds (key, chords, sections) is shifted by it, so a recording\n * that is not at A440 reads its key and chords on its own pitch grid.\n * Default 0 (concert A440).\n */\n tuning?: number;\n}\nexport interface MusicAnalyzeRequest extends SamplesRequest, MusicAnalyzeOptions {}\n\n/**\n * Perform complete music analysis.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @returns Complete analysis result\n *\n * @remarks\n * This call is synchronous and blocks until analysis completes. Unlike the\n * Node binding (which offers `analyzeAsync` on a libuv worker thread), the\n * WASM build runs on a single thread, so there is no non-blocking variant —\n * the DSP pipeline always runs to completion on the calling thread. To keep\n * the UI responsive for long inputs, drive this from a Web Worker and use\n * {@link analyzeWithProgress} to report progress.\n */\nexport function analyze(request: MusicAnalyzeRequest): AnalysisResult;\nexport function analyze(\n samples: Float32Array,\n sampleRate?: number,\n options?: GuardedOptions & MusicAnalyzeOptions,\n): AnalysisResult;\nexport function analyze(\n samples: Float32Array | MusicAnalyzeRequest,\n sampleRate = 22050,\n options: GuardedOptions & MusicAnalyzeOptions = {},\n): AnalysisResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('analyze', request.samples, request.sampleRate ?? 22050, request);\n const result = requireModule().analyze(request.samples, request.sampleRate ?? 22050, request);\n return convertAnalysisResult(result);\n}\n\n/**\n * Canonical request form for {@link estimateMeter}.\n *\n * @remarks\n * Every scoring field is optional and falls back to the core default when\n * omitted; the core validates them and rejects a value it cannot answer rather\n * than substituting one.\n */\nexport interface EstimateMeterRequest {\n /** Beat positions in seconds, non-decreasing. */\n beatTimes: ArrayLike<number>;\n /**\n * Per-beat accent value, the same length as {@link beatTimes}.\n *\n * @remarks\n * `AnalysisResult.beatObservations.onsetStrength` is the intended source —\n * it is the windowed value the library's own downbeat pass scores.\n * `beats[].strength` also works but is a single unwindowed envelope frame.\n * Neither needs pre-scaling: the series is divided by its own maximum before\n * scoring, so only the accent contrast within it is read.\n *\n * A series assembled by hand from {@link onsetEnvelope} — one frame read at\n * each beat time — is neither of those, and it carries a sample-rate\n * dependence neither of them has: a hop counted in samples frames a different\n * amount of time at each rate, so one waveform sampled at 32000, 44100 and\n * 48000 Hz has produced three different winning numerators off beat times\n * identical to the sample. Widening the read to a window around the beat does\n * not remove it. A browser decodes at the output device's rate, so that is a\n * different answer per visitor for the same clip.\n */\n beatStrengths: ArrayLike<number>;\n /**\n * Meter numerators to score (default: `[3, 4, 6]`).\n *\n * @remarks\n * Adding a numerator widens the search; it does not force the result. The\n * list must hold between 1 and 16 entries, each in `[2, 32]`.\n */\n candidateNumerators?: number[];\n /**\n * Beat unit reported for the detected meter (default: 4). Must be a power of\n * two in `[1, 32]`.\n *\n * @remarks\n * Reported as requested: whether a beat divides into three is measured from\n * energy *between* the beats, which per-beat accents do not carry, so a\n * compound meter is not resolvable here. A six accented 3+3 comes back with\n * this denominator and `grouping === [3, 3]`.\n */\n denominator?: number;\n /** Weight of the downbeat accent term (default: 1). */\n downbeatWeight?: number;\n /** Weight of the measure-periodicity term (default: 0.5). */\n measureWeight?: number;\n /** Weight of the subdivision term (default: 0.15). */\n subdivisionWeight?: number;\n /**\n * Score ratio above which a compound meter is preferred (default: 0.85).\n *\n * @remarks\n * Only consulted when there is a subdivision to measure, so it has no effect\n * here — this entry point scores per-beat accents alone.\n */\n compoundSubdivisionThreshold?: number;\n}\n\n/**\n * Estimate meter over a caller-supplied beat series.\n *\n * @param request - Beat series plus optional scoring configuration\n * @returns The selected signature, its downbeat phase and grouping, and the\n * scored candidates\n *\n * @remarks\n * Scores only the per-beat strengths, so no audio and no frame-level onset\n * envelope is needed: an arbitrary span of an existing analysis can be scored\n * without re-running it. Pass `beatObservations.onsetStrength` rather than\n * `beats[].strength` — see {@link EstimateMeterRequest.beatStrengths}.\n *\n * The result carries `grouping` alongside the numerator: how the bar divides\n * into accent groups of two and three beats, so a seven comes back as `[3, 2,\n * 2]` or `[2, 2, 3]` rather than as a bare seven.\n *\n * Check `searched` before reading anything as a detection: a series too short\n * to score any candidate reports a fixed fallback instead, and `candidateScores`\n * grows with the square root of how many beats were scored, so scores from\n * spans of different lengths are not directly comparable.\n */\nexport function estimateMeter(request: EstimateMeterRequest): MeterEstimate {\n return requireModule().estimateMeter(request.beatTimes, request.beatStrengths, request);\n}\n\nexport function analyzeImpulseResponse(request: AnalyzeImpulseResponseRequest): AcousticResult;\nexport function analyzeImpulseResponse(\n samples: Float32Array,\n sampleRate?: number,\n nOctaveBands?: number,\n minDecayDb?: number,\n): AcousticResult;\nexport function analyzeImpulseResponse(\n samples: Float32Array | AnalyzeImpulseResponseRequest,\n sampleRate = 48000,\n nOctaveBands = 6,\n minDecayDb?: number,\n): AcousticResult {\n const request =\n samples instanceof Float32Array ? { samples, sampleRate, nOctaveBands, minDecayDb } : samples;\n // Only `undefined` takes the default. `null` falls through to\n // assertFiniteScalar, which refuses it with the same wording as any other\n // non-finite value -- Number.isFinite(null) is false, so the case needs no\n // branch of its own, and the one that was here answered it with a different\n // error class than the check three lines down.\n const resolvedMinDecayDb = request.minDecayDb === undefined ? 30.0 : request.minDecayDb;\n assertFiniteScalar('analyzeImpulseResponse', resolvedMinDecayDb, 'minDecayDb');\n if (resolvedMinDecayDb <= 0) {\n throw new RangeError('analyzeImpulseResponse: minDecayDb must be greater than zero');\n }\n validateAnalysisInput(\n 'analyzeImpulseResponse',\n request.samples,\n request.sampleRate ?? 48000,\n request,\n );\n const result: WasmAcousticResult = requireModule().analyzeImpulseResponseEx(\n request.samples,\n request.sampleRate ?? 48000,\n request.nOctaveBands ?? 6,\n resolvedMinDecayDb,\n );\n return result;\n}\n\nexport function detectAcoustic(request: DetectAcousticRequest): AcousticResult;\nexport function detectAcoustic(\n samples: Float32Array,\n sampleRate?: number,\n options?: AcousticOptions,\n): AcousticResult;\nexport function detectAcoustic(\n samples: Float32Array | DetectAcousticRequest,\n sampleRate = 48000,\n options: AcousticOptions = {},\n): AcousticResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('detectAcoustic', request.samples, request.sampleRate ?? 48000, request);\n const result: WasmAcousticResult = requireModule().detectAcoustic(\n request.samples,\n request.sampleRate ?? 48000,\n request.nOctaveBands ?? 6,\n request.nThirdOctaveSubbands ?? 24,\n request.minDecayDb ?? 30.0,\n request.noiseFloorMarginDb ?? 10.0,\n );\n return result;\n}\n\n/**\n * Synthesize a room impulse response from shoebox geometry. `hasError` is true\n * when the source/listener falls outside the room (the RIR is then empty).\n */\nexport function synthesizeRir(options: RirSynthOptions = {}): RirResult {\n const module = requireModule();\n if (typeof module.synthesizeRir !== 'function') {\n throw new Error('libsonare was built without acoustic-simulation support');\n }\n return module.synthesizeRir(options);\n}\n\n/**\n * Estimate an equivalent room (volume/dimensions/absorption/DRR) from a\n * recording or impulse response.\n */\nexport function estimateRoom(request: EstimateRoomRequest): RoomEstimateResult;\nexport function estimateRoom(\n samples: Float32Array,\n sampleRate?: number,\n options?: RoomEstimateOptions,\n): RoomEstimateResult;\nexport function estimateRoom(\n samples: Float32Array | EstimateRoomRequest,\n sampleRate = 48000,\n options: RoomEstimateOptions = {},\n): RoomEstimateResult {\n const module = requireModule();\n if (typeof module.estimateRoom !== 'function') {\n throw new Error('libsonare was built without acoustic-simulation support');\n }\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('estimateRoom', request.samples, request.sampleRate ?? 48000, request);\n return module.estimateRoom(request.samples, request.sampleRate ?? 48000, request);\n}\n\n/**\n * Morph a recording's reverberation toward a target room (creative FX, not\n * dereverberation).\n *\n * Returns the morphed samples in `audio` (input length plus the target room's\n * reverb tail) alongside the target-room synthesis's own `diagnostics`, which\n * report a room other than the one requested — see {@link RoomMorphResult}.\n */\nexport function roomMorph(request: RoomMorphRequest): RoomMorphResult;\nexport function roomMorph(\n samples: Float32Array,\n sampleRate: number,\n options?: RoomMorphOptions,\n): RoomMorphResult;\nexport function roomMorph(\n samples: Float32Array | RoomMorphRequest,\n sampleRate?: number,\n options: RoomMorphOptions = {},\n): RoomMorphResult {\n const module = requireModule();\n if (typeof module.roomMorph !== 'function') {\n throw new Error('libsonare was built without acoustic-simulation support');\n }\n const request =\n samples instanceof Float32Array\n ? { samples, sampleRate: sampleRate as number, ...options }\n : samples;\n validateAnalysisInput('roomMorph', request.samples, request.sampleRate, request);\n return module.roomMorph(request.samples, request.sampleRate, request);\n}\n\n/**\n * Perform complete music analysis with progress reporting.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleRate - Sample rate in Hz (default: 22050)\n * @param onProgress - Progress callback (progress: 0-1, stage: string)\n * @returns Complete analysis result\n */\nexport function analyzeWithProgress(request: AnalyzeWithProgressRequest): AnalysisResult;\nexport function analyzeWithProgress(\n samples: Float32Array,\n sampleRate: number | undefined,\n onProgress: ProgressCallback,\n options?: MusicAnalyzeOptions,\n): AnalysisResult;\nexport function analyzeWithProgress(\n samples: Float32Array | AnalyzeWithProgressRequest,\n sampleRate = 22050,\n onProgress?: ProgressCallback,\n options?: MusicAnalyzeOptions,\n): AnalysisResult {\n const request: AnalyzeWithProgressRequest =\n samples instanceof Float32Array\n ? { samples, sampleRate, onProgress: onProgress as ProgressCallback, options }\n : samples;\n validateAnalysisInput(\n 'analyzeWithProgress',\n request.samples,\n request.sampleRate ?? 22050,\n request,\n );\n // The module reads options with the same reader analyze uses.\n const result = requireModule().analyzeWithProgress(\n request.samples,\n request.sampleRate ?? 22050,\n request.options ?? {},\n request.onProgress ?? (() => {}),\n request.cancel ?? (() => false),\n );\n return convertAnalysisResult(result);\n}\n\nexport interface BpmCandidate {\n bpm: number;\n confidence: number;\n}\n\nexport interface BpmAnalysisResult {\n bpm: number;\n confidence: number;\n candidates: BpmCandidate[];\n autocorrelation: Float32Array;\n tempogram: Float32Array;\n}\n\nexport interface RhythmAnalysisResult {\n timeSignature: { numerator: number; denominator: number; confidence: number };\n syncopation: number;\n grooveType: string;\n patternRegularity: number;\n tempoStability: number;\n /**\n * The beat tracker's own tempo, refined from the local beat period. It is a\n * third figure rather than either tempo entry point's: measured against\n * synthesized click trains it differs from both at every sample rate, and\n * lands closer to the known tempo than either. Analysed at the sample rate\n * you pass, so `nFft` and `hopLength` are in samples of your buffer.\n */\n bpm: number;\n beatIntervals: Float32Array;\n}\n\n/**\n * Dynamics metrics returned by {@link analyzeDynamics}.\n *\n * The Node package declares the same shape under the same name; the two are\n * pinned to one field list by `tests/conformance/shared_type_shapes.json`.\n */\nexport interface DynamicsResult {\n dynamicRangeDb: number;\n peakDb: number;\n rmsDb: number;\n crestFactor: number;\n loudnessRangeDb: number;\n isCompressed: boolean;\n /** Loudness curve timestamps (seconds), parallel to {@link loudnessRmsDb}. */\n loudnessTimes: Float32Array;\n /** Loudness curve RMS values (dB), parallel to {@link loudnessTimes}. */\n loudnessRmsDb: Float32Array;\n}\n\n/**\n * @deprecated Use {@link DynamicsResult}. Retained so code written against the\n * WASM-only spelling keeps compiling; the Node package exports the same alias.\n */\nexport type DynamicsAnalysisResult = DynamicsResult;\n\n/** Timbre metrics for one analysis window. Entries are ordered by time in `timbreOverTime`. */\nexport interface TimbreFrame {\n brightness: number;\n warmth: number;\n density: number;\n roughness: number;\n complexity: number;\n}\n\nexport interface TimbreAnalysisResult extends TimbreFrame {\n spectralCentroid: Float32Array;\n spectralFlatness: Float32Array;\n spectralRolloff: Float32Array;\n /** Time-varying timbre metrics, one entry per analysis window. */\n timbreOverTime: TimbreFrame[];\n}\n\n/**\n * Detailed BPM analysis (BPM, confidence, alternate candidates, autocorrelation,\n * tempogram). Matches the Node `analyzeBpm` / Python `analyze_bpm` surface.\n */\nexport function analyzeBpm(request: AnalyzeBpmRequest): BpmAnalysisResult;\nexport function analyzeBpm(\n samples: Float32Array,\n sampleRate?: number,\n options?: AnalyzeBpmOptions,\n): BpmAnalysisResult;\nexport function analyzeBpm(\n samples: Float32Array | AnalyzeBpmRequest,\n sampleRate = 22050,\n options: AnalyzeBpmOptions = {},\n): BpmAnalysisResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('analyzeBpm', request.samples, request.sampleRate ?? 22050, request);\n assertNonNegativeInteger('analyzeBpm', request.maxCandidates ?? 5, 'maxCandidates');\n return requireModule().analyzeBpm(\n request.samples,\n request.sampleRate ?? 22050,\n request.bpmMin ?? 30.0,\n request.bpmMax ?? 300.0,\n request.startBpm ?? 120.0,\n request.nFft ?? 2048,\n request.hopLength ?? 512,\n request.maxCandidates ?? 5,\n );\n}\n\n/**\n * Detailed rhythm analysis (time signature, groove, syncopation, beat intervals).\n */\nexport function analyzeRhythm(request: AnalyzeRhythmRequest): RhythmAnalysisResult;\nexport function analyzeRhythm(\n samples: Float32Array,\n sampleRate?: number,\n options?: AnalyzeRhythmOptions,\n): RhythmAnalysisResult;\nexport function analyzeRhythm(\n samples: Float32Array | AnalyzeRhythmRequest,\n sampleRate = 22050,\n options: AnalyzeRhythmOptions = {},\n): RhythmAnalysisResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('analyzeRhythm', request.samples, request.sampleRate ?? 22050, request);\n return requireModule().analyzeRhythm(\n request.samples,\n request.sampleRate ?? 22050,\n request.bpmMin ?? 60.0,\n request.bpmMax ?? 200.0,\n request.startBpm ?? 120.0,\n request.nFft ?? 2048,\n request.hopLength ?? 512,\n );\n}\n\n/**\n * Dynamics analysis (RMS, peak, crest factor, LRA, loudness curve).\n */\nexport function analyzeDynamics(request: AnalyzeDynamicsRequest): DynamicsResult;\nexport function analyzeDynamics(\n samples: Float32Array,\n sampleRate?: number,\n options?: AnalyzeDynamicsOptions,\n): DynamicsResult;\nexport function analyzeDynamics(\n samples: Float32Array | AnalyzeDynamicsRequest,\n sampleRate = 22050,\n options: AnalyzeDynamicsOptions = {},\n): DynamicsResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('analyzeDynamics', request.samples, request.sampleRate ?? 22050, request);\n return requireModule().analyzeDynamics(\n request.samples,\n request.sampleRate ?? 22050,\n request.windowSec ?? 0.4,\n request.hopLength ?? 512,\n request.compressionThreshold ?? 6.0,\n );\n}\n\n/**\n * Timbre analysis (brightness/warmth/density/roughness/complexity plus spectral\n * features and per-window timbre frames).\n */\nexport function analyzeTimbre(request: AnalyzeTimbreRequest): TimbreAnalysisResult;\nexport function analyzeTimbre(\n samples: Float32Array,\n sampleRate?: number,\n options?: AnalyzeTimbreOptions,\n): TimbreAnalysisResult;\nexport function analyzeTimbre(\n samples: Float32Array | AnalyzeTimbreRequest,\n sampleRate = 22050,\n options: AnalyzeTimbreOptions = {},\n): TimbreAnalysisResult {\n const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;\n validateAnalysisInput('analyzeTimbre', request.samples, request.sampleRate ?? 22050, request);\n return requireModule().analyzeTimbre(\n request.samples,\n request.sampleRate ?? 22050,\n request.nFft ?? 2048,\n request.hopLength ?? 512,\n request.nMels ?? 128,\n request.nMfcc ?? 13,\n request.windowSec ?? 0.5,\n );\n}\n\n/**\n * Whether this WASM build was compiled with FFmpeg support. Mirrors Node /\n * Python `hasFfmpegSupport`. In the published WASM binding this currently\n * always returns `false` (FFmpeg is not bundled into the .wasm), but the API\n * exists so caller code can branch on capabilities portably.\n */\nexport function hasFfmpegSupport(): boolean {\n return requireModule().hasFfmpegSupport();\n}\n","import type { VoiceChangeOptions } from './effects_mastering';\nimport {\n harmonic,\n hpss,\n masterAudio,\n mastering,\n masteringChain,\n masteringProcess,\n normalize,\n noteMove,\n noteStretch,\n percussive,\n pitchCorrectToMidi,\n pitchShift,\n timeStretch,\n voiceChange,\n} from './effects_mastering';\nimport {\n chroma,\n ebur128LoudnessRange,\n lufs,\n melSpectrogram,\n mfcc,\n momentaryLufs,\n nnlsChroma,\n onsetEnvelope,\n pitchPyin,\n pitchYin,\n resample,\n rmsEnergy,\n shortTermLufs,\n spectralBandwidth,\n spectralCentroid,\n spectralFlatness,\n spectralRolloff,\n stft,\n stftDb,\n trim,\n zeroCrossingRate,\n} from './features';\nimport type {\n ClippingReport,\n DynamicRangeReport,\n MeteringDetectClippingOptions,\n MeteringDynamicRangeOptions,\n SpectrumOptions,\n SpectrumReport,\n} from './metering';\nimport {\n meteringCrestFactorDb,\n meteringDcOffset,\n meteringDetectClipping,\n meteringDynamicRange,\n meteringPeakDb,\n meteringRmsDb,\n meteringSilenceRatio,\n meteringSpectrum,\n meteringSpectrumFrame,\n meteringTruePeakDb,\n} from './metering';\nimport { getSonareModule } from './module_state';\nimport type {\n AnalysisResult,\n ChordAnalysisResult,\n ChordDetectionOptions,\n ChromaResult,\n HpssResult,\n Key,\n KeyCandidate,\n KeyDetectionOptions,\n LufsResult,\n MasteringChainConfig,\n MasteringChainResult,\n MasteringOptions,\n MasteringPreset,\n MasteringProcessorParams,\n MasteringResult,\n MelSpectrogramResult,\n MfccResult,\n Mode,\n NoteStretchOptions,\n PitchClass,\n PitchResult,\n SoloProcessor,\n StftResult,\n} from './public_types';\nimport type { MusicAnalyzeOptions } from './quick_analysis';\nimport {\n analyze,\n analyzeWithProgress,\n chordFunctionalAnalysis,\n detectBeats,\n detectBpm,\n detectChords,\n detectDownbeats,\n detectKey,\n detectKeyCandidates,\n detectOnsets,\n} from './quick_analysis';\nimport type { ProgressCallback, WasmNnlsChromaResult } from './sonare.js';\nimport type { ValidateOptions } from './validation';\nimport { validateAudioBuffer } from './validation';\n\n// ============================================================================\n// Audio Class\n// ============================================================================\n\ntype BrowserDecodeContext = Pick<BaseAudioContext, 'decodeAudioData' | 'sampleRate'>;\n\nexport interface BrowserAudioDecodeOptions {\n /**\n * AudioContext/OfflineAudioContext used for browser codec fallback. Its\n * `sampleRate` becomes the returned Audio sample rate.\n */\n audioContext?: BrowserDecodeContext;\n /**\n * Factory used when `audioContext` is omitted. `targetSampleRate` is passed\n * through so browsers that honor AudioContextOptions decode directly at that\n * rate.\n */\n createAudioContext?: (options?: AudioContextOptions) => BrowserDecodeContext;\n /**\n * Requested fallback decode rate when this helper creates the context. If the\n * browser ignores it or a context is supplied, no extra resampling is applied.\n */\n targetSampleRate?: number;\n}\n\nfunction encodedBytesToArrayBuffer(bytes: Uint8Array): ArrayBuffer {\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n return copy.buffer;\n}\n\nfunction getBrowserAudioContextFactory():\n | ((options?: AudioContextOptions) => BrowserDecodeContext)\n | undefined {\n const root = globalThis as typeof globalThis & {\n AudioContext?: new (options?: AudioContextOptions) => BaseAudioContext;\n webkitAudioContext?: new (options?: AudioContextOptions) => BaseAudioContext;\n };\n const Ctor = root.AudioContext ?? root.webkitAudioContext;\n return Ctor ? (options?: AudioContextOptions) => new Ctor(options) : undefined;\n}\n\nfunction audioBufferToMono(buffer: AudioBuffer): Float32Array {\n const samples = new Float32Array(buffer.length);\n if (buffer.numberOfChannels <= 0) {\n return samples;\n }\n if (buffer.numberOfChannels === 1) {\n samples.set(buffer.getChannelData(0));\n return samples;\n }\n for (let channel = 0; channel < buffer.numberOfChannels; channel++) {\n const data = buffer.getChannelData(channel);\n for (let i = 0; i < buffer.length; i++) {\n samples[i] += data[i] / buffer.numberOfChannels;\n }\n }\n return samples;\n}\n\nasync function closeCreatedContext(context: BrowserDecodeContext): Promise<void> {\n const maybeClosable = context as BrowserDecodeContext & { close?: () => Promise<void> };\n if (maybeClosable.close) {\n await maybeClosable.close();\n }\n}\n\n/**\n * Wrapper around audio data that exposes analysis and feature functions as\n * instance methods.\n *\n * Not every module-level function has a method here — `analyzeBpm`,\n * `analyzeRhythm`, `analyzeDynamics`, `analyzeTimbre`, `analyzeImpulseResponse`\n * and `detectAcoustic` are reachable as free functions only, and the Node\n * facade exposes them as methods as well. Where a method does exist on both, it\n * takes the same arguments.\n *\n * @example\n * ```typescript\n * import { init, Audio } from '@libraz/libsonare';\n *\n * await init();\n *\n * const audio = Audio.fromBuffer(samples, 44100);\n * console.log('BPM:', audio.detectBpm());\n * console.log('Key:', audio.detectKey().name);\n *\n * const mel = audio.melSpectrogram();\n * ```\n */\nexport class Audio {\n private _samples: Float32Array;\n private _sampleRate: number;\n\n private constructor(samples: Float32Array, sampleRate: number) {\n this._samples = samples;\n this._sampleRate = sampleRate;\n }\n\n /**\n * Create an Audio instance from raw sample data.\n *\n * @param samples - Mono float samples.\n * @param sampleRate - Sample rate in Hz (default `48000`, matching the\n * Node/Python surfaces).\n */\n static fromBuffer(samples: Float32Array, sampleRate = 48000): Audio {\n validateAudioBuffer(samples, sampleRate);\n return new Audio(samples.slice(), sampleRate);\n }\n\n /**\n * Create an Audio instance by decoding audio bytes in memory.\n *\n * @param bytes - Encoded audio bytes such as WAV or MP3.\n */\n static fromMemory(bytes: Uint8Array): Audio {\n const decoded = getSonareModule().audioFromMemory(bytes);\n return new Audio(decoded.samples, decoded.sampleRate);\n }\n\n /**\n * Decode audio bytes with the native WASM decoder first, then fall back to the\n * browser codec stack (`AudioContext.decodeAudioData`) for formats such as\n * AAC, OGG, and FLAC when available. Browser-decoded multi-channel audio is\n * mixed down to mono to match the `Audio` wrapper contract.\n */\n static async fromMemoryWithBrowserFallback(\n bytes: Uint8Array,\n options: BrowserAudioDecodeOptions = {},\n ): Promise<Audio> {\n try {\n return Audio.fromMemory(bytes);\n } catch (nativeError) {\n let createdContext = false;\n const contextFactory = options.createAudioContext ?? getBrowserAudioContextFactory();\n const context =\n options.audioContext ??\n contextFactory?.(\n options.targetSampleRate ? { sampleRate: options.targetSampleRate } : undefined,\n );\n\n if (!context) {\n throw new Error(\n `Audio.fromMemory failed and browser decodeAudioData is unavailable: ${\n nativeError instanceof Error ? nativeError.message : String(nativeError)\n }`,\n );\n }\n\n createdContext = !options.audioContext;\n try {\n const decoded = await context.decodeAudioData(encodedBytesToArrayBuffer(bytes));\n return new Audio(audioBufferToMono(decoded), decoded.sampleRate || context.sampleRate);\n } catch (fallbackError) {\n throw new Error(\n `Audio.fromMemory failed and browser decodeAudioData fallback failed: ${\n fallbackError instanceof Error ? fallbackError.message : String(fallbackError)\n }`,\n );\n } finally {\n if (createdContext) {\n await closeCreatedContext(context);\n }\n }\n }\n }\n\n /**\n * A copy of the raw audio samples. Mirrors Node's `getData()` contract: the\n * returned array is independent of the Audio's internal buffer, so mutating\n * it (or transferring it to a Worker) does not affect subsequent facade\n * calls, which all read the internal snapshot directly.\n */\n get data(): Float32Array {\n return this._samples.slice();\n }\n\n /** Number of samples. */\n get length(): number {\n return this._samples.length;\n }\n\n /** Sample rate in Hz. */\n get sampleRate(): number {\n return this._sampleRate;\n }\n\n /** Duration in seconds. */\n get duration(): number {\n return this._samples.length / this._sampleRate;\n }\n\n // -- Analysis --\n\n detectBpm(): number {\n return detectBpm(this._samples, this._sampleRate);\n }\n\n detectKey(options: KeyDetectionOptions = {}): Key {\n return detectKey(this._samples, this._sampleRate, options);\n }\n\n detectKeyCandidates(options: KeyDetectionOptions = {}): KeyCandidate[] {\n return detectKeyCandidates(this._samples, this._sampleRate, options);\n }\n\n detectOnsets(): Float32Array {\n return detectOnsets(this._samples, this._sampleRate);\n }\n\n detectBeats(): Float32Array {\n return detectBeats(this._samples, this._sampleRate);\n }\n\n detectDownbeats(): Float32Array {\n return detectDownbeats(this._samples, this._sampleRate);\n }\n\n detectChords(options: ChordDetectionOptions = {}): ChordAnalysisResult {\n return detectChords(this._samples, this._sampleRate, options);\n }\n\n chordFunctionalAnalysis(\n keyRoot: PitchClass,\n keyMode: Mode,\n options: ChordDetectionOptions = {},\n ): string[] {\n return chordFunctionalAnalysis(this._samples, keyRoot, keyMode, this._sampleRate, options);\n }\n\n /**\n * Full music analysis of the held buffer.\n *\n * Takes the same option bag as the module-level {@link analyze} and as the\n * Node facade's `Audio.analyze`; this method used to drop it, so the same\n * call was tunable on one binding and fixed at the defaults on the other.\n */\n analyze(options: MusicAnalyzeOptions = {}): AnalysisResult {\n return analyze(this._samples, this._sampleRate, options);\n }\n\n analyzeWithProgress(onProgress: ProgressCallback): AnalysisResult {\n return analyzeWithProgress(this._samples, this._sampleRate, onProgress);\n }\n\n // -- Effects --\n\n hpss(kernelHarmonic = 31, kernelPercussive = 31): HpssResult {\n return hpss(this._samples, this._sampleRate, kernelHarmonic, kernelPercussive);\n }\n\n harmonic(): Float32Array {\n return harmonic(this._samples, this._sampleRate);\n }\n\n percussive(): Float32Array {\n return percussive(this._samples, this._sampleRate);\n }\n\n timeStretch(rate: number): Float32Array {\n return timeStretch(this._samples, this._sampleRate, rate);\n }\n\n pitchShift(semitones: number): Float32Array {\n return pitchShift(this._samples, this._sampleRate, semitones);\n }\n\n pitchCorrectToMidi(currentMidi = 69.0, targetMidi = 69.0): Float32Array {\n return pitchCorrectToMidi(this._samples, this._sampleRate, currentMidi, targetMidi);\n }\n\n noteStretch(options: NoteStretchOptions = {}): Float32Array {\n return noteStretch(this._samples, this._sampleRate, options);\n }\n\n noteMove(options: import('./public_types.js').NoteMoveOptions = {}): Float32Array {\n return noteMove(this._samples, this._sampleRate, options);\n }\n\n voiceChange(options: VoiceChangeOptions = {}): Float32Array {\n return voiceChange(this._samples, this._sampleRate, options);\n }\n\n normalize(targetDb = 0.0): Float32Array {\n return normalize(this._samples, this._sampleRate, targetDb);\n }\n\n mastering(options: MasteringOptions = {}): MasteringResult {\n return mastering(this._samples, this._sampleRate, options);\n }\n\n masteringChain(\n config: MasteringChainConfig = {},\n onProgress?: ProgressCallback,\n ): MasteringChainResult {\n return masteringChain({\n samples: this._samples,\n sampleRate: this._sampleRate,\n config,\n onProgress,\n });\n }\n\n masterAudio(\n presetName: MasteringPreset = 'pop',\n overrides: MasteringChainConfig | null = null,\n onProgress?: ProgressCallback,\n ): MasteringChainResult {\n return masterAudio({\n samples: this._samples,\n sampleRate: this._sampleRate,\n preset: presetName,\n overrides: overrides ?? {},\n onProgress,\n });\n }\n\n masteringProcess(\n processorName: SoloProcessor,\n params: MasteringProcessorParams = {},\n ): MasteringResult {\n return masteringProcess(processorName, this._samples, this._sampleRate, params);\n }\n\n trim(thresholdDb = -60.0): Float32Array {\n return trim(this._samples, this._sampleRate, thresholdDb);\n }\n\n // -- Features --\n\n stft(nFft = 2048, hopLength = 512): StftResult {\n return stft(this._samples, this._sampleRate, nFft, hopLength);\n }\n\n stftDb(nFft = 2048, hopLength = 512): { nBins: number; nFrames: number; db: Float32Array } {\n return stftDb(this._samples, this._sampleRate, nFft, hopLength);\n }\n\n melSpectrogram(\n nFft = 2048,\n hopLength = 512,\n nMels = 128,\n fmin = 0,\n fmax = 0,\n htk = false,\n ): MelSpectrogramResult {\n return melSpectrogram(this._samples, this._sampleRate, nFft, hopLength, nMels, fmin, fmax, htk);\n }\n\n mfcc(\n nFft = 2048,\n hopLength = 512,\n nMels = 128,\n nMfcc = 20,\n fmin = 0,\n fmax = 0,\n htk = false,\n ): MfccResult {\n return mfcc(this._samples, this._sampleRate, nFft, hopLength, nMels, nMfcc, fmin, fmax, htk);\n }\n\n chroma(nFft = 2048, hopLength = 512): ChromaResult {\n return chroma(this._samples, this._sampleRate, nFft, hopLength);\n }\n\n nnlsChroma(): WasmNnlsChromaResult {\n return nnlsChroma(this._samples, this._sampleRate);\n }\n\n onsetEnvelope(nFft = 2048, hopLength = 512, nMels = 128): Float32Array {\n return onsetEnvelope(this._samples, this._sampleRate, nFft, hopLength, nMels);\n }\n\n lufs(): LufsResult {\n return lufs(this._samples, this._sampleRate);\n }\n\n momentaryLufs(): Float32Array {\n return momentaryLufs(this._samples, this._sampleRate);\n }\n\n shortTermLufs(): Float32Array {\n return shortTermLufs(this._samples, this._sampleRate);\n }\n\n spectralCentroid(nFft = 2048, hopLength = 512): Float32Array {\n return spectralCentroid(this._samples, this._sampleRate, nFft, hopLength);\n }\n\n spectralBandwidth(nFft = 2048, hopLength = 512): Float32Array {\n return spectralBandwidth(this._samples, this._sampleRate, nFft, hopLength);\n }\n\n spectralRolloff(nFft = 2048, hopLength = 512, rollPercent = 0.85): Float32Array {\n return spectralRolloff(this._samples, this._sampleRate, nFft, hopLength, rollPercent);\n }\n\n spectralFlatness(nFft = 2048, hopLength = 512): Float32Array {\n return spectralFlatness(this._samples, this._sampleRate, nFft, hopLength);\n }\n\n zeroCrossingRate(frameLength = 2048, hopLength = 512): Float32Array {\n return zeroCrossingRate(this._samples, this._sampleRate, frameLength, hopLength);\n }\n\n rmsEnergy(frameLength = 2048, hopLength = 512): Float32Array {\n return rmsEnergy(this._samples, this._sampleRate, frameLength, hopLength);\n }\n\n pitchYin(\n frameLength = 2048,\n hopLength = 512,\n fmin = 65.0,\n fmax = 2093.0,\n threshold = 0.1,\n fillNa = false,\n ): PitchResult {\n return pitchYin(\n this._samples,\n this._sampleRate,\n frameLength,\n hopLength,\n fmin,\n fmax,\n threshold,\n fillNa,\n );\n }\n\n pitchPyin(\n frameLength = 2048,\n hopLength = 512,\n fmin = 65.0,\n fmax = 2093.0,\n threshold = 0.1,\n fillNa = false,\n ): PitchResult {\n return pitchPyin(\n this._samples,\n this._sampleRate,\n frameLength,\n hopLength,\n fmin,\n fmax,\n threshold,\n fillNa,\n );\n }\n\n resample(targetSr: number): Float32Array {\n return resample(this._samples, this._sampleRate, targetSr);\n }\n\n // -- Metering --\n //\n // These delegate to the module-level buffer-form functions rather than a\n // native handle: WASM's Audio is a plain JS wrapper around a Float32Array,\n // not an embind class, so there is no cheaper path to reach the same\n // measurement. The methods exist for call-shape parity with Node/Python,\n // which do hold a native handle here.\n\n peakDb(): number {\n return meteringPeakDb(this._samples, this._sampleRate);\n }\n\n rmsDb(): number {\n return meteringRmsDb(this._samples, this._sampleRate);\n }\n\n dcOffset(): number {\n return meteringDcOffset(this._samples, this._sampleRate);\n }\n\n crestFactorDb(): number {\n return meteringCrestFactorDb(this._samples, this._sampleRate);\n }\n\n silenceRatio(thresholdDb = -45, frameLength = 1024, hopLength = 256): number {\n return meteringSilenceRatio(\n this._samples,\n this._sampleRate,\n thresholdDb,\n frameLength,\n hopLength,\n );\n }\n\n /**\n * Inter-sample (true) peak in dBFS. `oversampleFactor` must be a power of two\n * in [1, 16]; pass 0 to use the library default (4).\n */\n truePeakDb(oversampleFactor = 4): number {\n return meteringTruePeakDb(this._samples, this._sampleRate, oversampleFactor);\n }\n\n detectClipping(options: MeteringDetectClippingOptions = {}): ClippingReport {\n return meteringDetectClipping(this._samples, this._sampleRate, options);\n }\n\n dynamicRange(options: MeteringDynamicRangeOptions = {}): DynamicRangeReport {\n return meteringDynamicRange(this._samples, this._sampleRate, options);\n }\n\n spectrum(options: SpectrumOptions & ValidateOptions = {}): SpectrumReport {\n return meteringSpectrum(this._samples, this._sampleRate, options);\n }\n\n /**\n * True single-frame magnitude / power / dB spectrum starting at `frameOffset`.\n * See {@link meteringSpectrumFrame} for the frame-validation contract.\n */\n spectrumFrame(frameOffset = 0, options: SpectrumOptions & ValidateOptions = {}): SpectrumReport {\n return meteringSpectrumFrame(this._samples, this._sampleRate, frameOffset, options);\n }\n\n ebur128LoudnessRange(): number {\n return ebur128LoudnessRange(this._samples, this._sampleRate);\n }\n}\n","import type { ClipPageProvider, ClipPageRequest, RealtimeEngine } from './realtime_engine';\n\nexport interface OpfsClipPageProviderOptions {\n path: string;\n numChannels: number;\n numSamples: number;\n pageFrames: number;\n dataOffsetBytes?: number;\n worker?: Worker;\n terminateWorkerOnClose?: boolean;\n /** Internal bridge hook used to mirror a supplied page into an AudioWorklet. */\n onPageSupplied?: (pageIndex: number, channels: Float32Array[]) => void;\n /** Internal bridge hook used to mirror an eviction into an AudioWorklet. */\n onPageCleared?: (pageIndex: number) => void;\n /** Internal bridge hook called after the local provider is destroyed. */\n onClose?: () => void;\n}\n\nexport interface OpfsClipPageProviderBinding {\n provider: ClipPageProvider;\n supplyPage(pageIndex: number): Promise<boolean>;\n supplyRequest(request: ClipPageRequest): Promise<boolean>;\n /** Evict one resident page from every configured consumer. */\n clearPage?(pageIndex: number): void;\n close(): void;\n}\n\ninterface PageResponse {\n type: 'sonare:clip-page';\n requestId: number;\n pageIndex: number;\n ok: boolean;\n frames?: number;\n channels?: Float32Array[];\n channelBuffers?: ArrayBufferLike[];\n error?: string;\n}\n\nexport const opfsClipPageWorkerSource = `\nconst sonareClipPageReadQueues = new Map();\n\nfunction sonareEnqueueClipPageRead(key, task) {\n const previous = sonareClipPageReadQueues.get(key) || Promise.resolve();\n const next = previous.catch(() => undefined).then(task);\n const queued = next.finally(() => {\n if (sonareClipPageReadQueues.get(key) === queued) {\n sonareClipPageReadQueues.delete(key);\n }\n });\n sonareClipPageReadQueues.set(key, queued);\n return next;\n}\n\nself.onmessage = async (event) => {\n const message = event.data;\n if (!message || message.type !== 'sonare:read-clip-page') return;\n const { requestId, path, pageIndex, numChannels, numSamples, pageFrames, dataOffsetBytes = 0 } = message;\n await sonareEnqueueClipPageRead(String(path), async () => {\n try {\n if (pageIndex < 0) {\n self.postMessage({ type: 'sonare:clip-page', requestId, pageIndex, ok: false });\n return;\n }\n const startFrame = pageIndex * pageFrames;\n if (startFrame >= numSamples) {\n self.postMessage({ type: 'sonare:clip-page', requestId, pageIndex, ok: false });\n return;\n }\n const root = await self.navigator.storage.getDirectory();\n let dir = root;\n const parts = String(path).split('/').filter(Boolean);\n for (let i = 0; i < parts.length - 1; ++i) {\n dir = await dir.getDirectoryHandle(parts[i]);\n }\n const fileHandle = await dir.getFileHandle(parts[parts.length - 1]);\n const access = await fileHandle.createSyncAccessHandle();\n try {\n const frames = Math.min(pageFrames, numSamples - startFrame);\n const frameBytes = numChannels * 4;\n const bytes = new Uint8Array(frames * frameBytes);\n let bytesReadTotal = 0;\n const readOffset = dataOffsetBytes + startFrame * frameBytes;\n while (bytesReadTotal < bytes.byteLength) {\n const bytesRead = access.read(bytes.subarray(bytesReadTotal), {\n at: readOffset + bytesReadTotal,\n });\n if (bytesRead <= 0) {\n break;\n }\n bytesReadTotal += bytesRead;\n }\n if (bytesReadTotal !== bytes.byteLength || bytesReadTotal % frameBytes !== 0) {\n self.postMessage({ type: 'sonare:clip-page', requestId, pageIndex, ok: false });\n return;\n }\n const framesRead = bytesReadTotal / frameBytes;\n const view = new DataView(bytes.buffer, 0, framesRead * frameBytes);\n const channelBuffers = Array.from({ length: numChannels }, () => new ArrayBuffer(framesRead * 4));\n for (let ch = 0; ch < numChannels; ++ch) {\n const channel = new Float32Array(channelBuffers[ch]);\n for (let frame = 0; frame < framesRead; ++frame) {\n channel[frame] = view.getFloat32((frame * numChannels + ch) * 4, true);\n }\n }\n self.postMessage(\n { type: 'sonare:clip-page', requestId, pageIndex, ok: true, frames: framesRead, channelBuffers },\n channelBuffers,\n );\n } finally {\n access.close();\n }\n } catch (error) {\n self.postMessage({\n type: 'sonare:clip-page',\n requestId,\n pageIndex,\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n });\n};\n`;\n\nexport function createOpfsClipPageWorker(): Worker {\n const blob = new Blob([opfsClipPageWorkerSource], { type: 'text/javascript' });\n const url = URL.createObjectURL(blob);\n try {\n return new Worker(url);\n } finally {\n // Worker construction retains the script URL internally; keeping this\n // object URL alive after construction leaks one browser registration per\n // attach/close cycle.\n URL.revokeObjectURL(url);\n }\n}\n\nexport function createOpfsClipPageProvider(\n engine: RealtimeEngine,\n options: OpfsClipPageProviderOptions,\n): OpfsClipPageProviderBinding {\n if (options.numChannels <= 0 || options.numSamples <= 0 || options.pageFrames <= 0) {\n throw new Error('numChannels, numSamples, and pageFrames must be positive');\n }\n const provider = engine.createClipPageProvider(\n options.numChannels,\n options.numSamples,\n options.pageFrames,\n );\n const worker = options.worker ?? createOpfsClipPageWorker();\n const ownsWorker = options.worker === undefined || options.terminateWorkerOnClose === true;\n let nextRequestId = 1;\n let closed = false;\n let readQueue: Promise<void> = Promise.resolve();\n const pending = new Map<\n number,\n { resolve: (value: boolean) => void; reject: (reason: unknown) => void }\n >();\n\n const onMessage = (event: MessageEvent<PageResponse>) => {\n const response = event.data;\n if (response?.type !== 'sonare:clip-page') {\n return;\n }\n const entry = pending.get(response.requestId);\n if (!entry) {\n return;\n }\n pending.delete(response.requestId);\n if (!response.ok) {\n entry.resolve(false);\n return;\n }\n const channels =\n response.channels ??\n response.channelBuffers?.map(\n (buffer) => new Float32Array(buffer, 0, response.frames ?? buffer.byteLength / 4),\n );\n if (!channels || channels.length === 0) {\n entry.resolve(false);\n return;\n }\n try {\n provider.supply(response.pageIndex, channels);\n options.onPageSupplied?.(response.pageIndex, channels);\n } catch {\n entry.resolve(false);\n return;\n }\n entry.resolve(true);\n };\n worker.addEventListener('message', onMessage as EventListener);\n\n const supplyPage = (pageIndex: number): Promise<boolean> => {\n if (closed) {\n return Promise.reject(new Error('OpfsClipPageProvider is closed'));\n }\n const requestId = nextRequestId++;\n const promise = new Promise<boolean>((resolve, reject) => {\n pending.set(requestId, { resolve, reject });\n });\n readQueue = readQueue\n .catch(() => undefined)\n .then(() => {\n if (closed) {\n const entry = pending.get(requestId);\n pending.delete(requestId);\n entry?.reject(new Error('OpfsClipPageProvider is closed'));\n return;\n }\n worker.postMessage({\n type: 'sonare:read-clip-page',\n requestId,\n path: options.path,\n pageIndex,\n numChannels: options.numChannels,\n numSamples: options.numSamples,\n pageFrames: options.pageFrames,\n dataOffsetBytes: options.dataOffsetBytes ?? 0,\n });\n return promise.then(\n () => undefined,\n () => undefined,\n );\n });\n readQueue.catch(() => {\n // The per-request promise carries the user-visible failure.\n });\n return promise;\n };\n\n return {\n provider,\n supplyPage,\n supplyRequest(request: ClipPageRequest) {\n return supplyPage(Math.floor(request.sample / options.pageFrames));\n },\n clearPage(pageIndex: number) {\n if (closed) {\n return;\n }\n provider.clear(pageIndex);\n options.onPageCleared?.(pageIndex);\n },\n close() {\n if (closed) {\n return;\n }\n closed = true;\n worker.removeEventListener('message', onMessage as EventListener);\n for (const entry of pending.values()) {\n entry.reject(new Error('OpfsClipPageProvider is closed'));\n }\n pending.clear();\n provider.destroy();\n options.onClose?.();\n if (ownsWorker) {\n worker.terminate();\n }\n },\n };\n}\n","import {\n createOpfsClipPageProvider,\n type OpfsClipPageProviderBinding,\n type OpfsClipPageProviderOptions,\n} from './opfs_clip_pages';\nimport type { ClipPageProvider, ClipPageRequest, RealtimeEngine } from './realtime_engine';\n\n/**\n * Minimal engine surface the streamer drives. {@link RealtimeEngine} satisfies\n * this structurally; tests can supply a lightweight stand-in.\n */\nexport interface ClipPageStreamerEngine {\n /** Drain one pending audio-thread page-miss request, or `null` when empty. */\n popClipPageRequest(): ClipPageStreamerRequest | null;\n}\n\n/**\n * A page miss reported by either a direct engine (`sample`) or the worklet\n * bridge (`pageIndex`). Exactly one position form is required.\n */\nexport interface ClipPageStreamerRequest {\n clipId: number;\n sample?: number;\n pageIndex?: number;\n}\n\n/** A paged clip the streamer keeps fed from its backing store. */\nexport interface ClipPageStreamSource {\n /** Clip schedule id passed to `setClips` (matches {@link ClipPageRequest.clipId}). */\n clipId: number;\n /** OPFS-backed page provider binding for this clip. */\n binding: OpfsClipPageProviderBinding;\n /** Page size in frames (must equal the provider's `pageFrames`). */\n pageFrames: number;\n /** Total sample count of the clip source. */\n numSamples: number;\n}\n\nexport interface ClipPageStreamerOptions {\n /**\n * Pages to prefetch ahead of the page a miss was reported for. Larger values\n * hide fetch latency at the cost of more resident memory. Default 2.\n */\n readAheadPages?: number;\n /**\n * Pages to retain behind the playback frontier before eviction, so a small\n * backward seek does not immediately miss. Default 1.\n */\n retainBehindPages?: number;\n /**\n * Upper bound on requests drained per {@link ClipPageStreamer.pump} call, so a\n * burst of misses cannot spin unbounded. Default 256.\n */\n maxRequestsPerPump?: number;\n}\n\ninterface SourceState {\n source: ClipPageStreamSource;\n lastPage: number;\n /** Playback-window generation; advanced on reset or backward discontinuity. */\n generation: number;\n /** Most recently serviced playback frontier, or null before the first miss. */\n lastFrontier: number | null;\n /** Resident page -> generation, so in-flight stale fetches cannot alias. */\n resident: Map<number, number>;\n}\n\n/**\n * Keeps OPFS-paged clips fed within a bounded sliding window around the live\n * playback position, so a multitrack arrangement never holds its full PCM in\n * WASM memory.\n *\n * The audio thread reports a page miss whenever the {@link ClipPlayer} reads a\n * sample whose page is not resident. {@link pump} drains those requests, fetches\n * the missing page plus a read-ahead window from each clip's backing store, and\n * evicts pages that fall outside the window via the provider's `clear`. The\n * resident set per clip is therefore bounded to\n * `retainBehindPages + readAheadPages + 1` pages regardless of clip length.\n *\n * Call {@link pump} on a cadence that keeps up with playback — typically once\n * per animation frame or per worklet control tick on the main/control thread\n * (never the audio thread; fetches are asynchronous).\n */\nexport class ClipPageStreamer {\n private readonly engine: ClipPageStreamerEngine;\n private readonly readAheadPages: number;\n private readonly retainBehindPages: number;\n private readonly maxRequestsPerPump: number;\n private readonly sources = new Map<number, SourceState>();\n private closed = false;\n\n constructor(engine: ClipPageStreamerEngine, options: ClipPageStreamerOptions = {}) {\n this.engine = engine;\n this.readAheadPages = Math.max(0, Math.floor(options.readAheadPages ?? 2));\n this.retainBehindPages = Math.max(0, Math.floor(options.retainBehindPages ?? 1));\n this.maxRequestsPerPump = Math.max(1, Math.floor(options.maxRequestsPerPump ?? 256));\n }\n\n /**\n * Register a paged clip. Pages already supplied to the provider before\n * registration (for example a primed first page) should be passed in\n * `initialResidentPages` so they participate in eviction.\n */\n addSource(source: ClipPageStreamSource, initialResidentPages: Iterable<number> = []): void {\n if (source.pageFrames <= 0 || source.numSamples <= 0) {\n throw new Error('pageFrames and numSamples must be positive');\n }\n const lastPage = Math.ceil(source.numSamples / source.pageFrames) - 1;\n const previous = this.sources.get(source.clipId);\n if (previous) {\n this.resetState(previous);\n }\n this.sources.set(source.clipId, {\n source,\n lastPage,\n generation: 0,\n lastFrontier: null,\n resident: new Map(Array.from(initialResidentPages, (page) => [page, 0])),\n });\n }\n\n /** Stop tracking a clip. Does not close its binding (the caller owns that). */\n removeSource(clipId: number): void {\n const state = this.sources.get(clipId);\n if (state) {\n this.resetState(state);\n }\n this.sources.delete(clipId);\n }\n\n /**\n * Explicitly start a new playback generation after a host seek/loop. Resident\n * pages are evicted and any older in-flight fetch is cleared when it settles.\n * The next miss establishes the new bounded window.\n */\n resetSource(clipId: number): void {\n const state = this.sources.get(clipId);\n if (state) {\n this.resetState(state);\n }\n }\n\n /**\n * Drain pending page-miss requests, fetch the missing pages plus their\n * read-ahead window, and evict out-of-window pages. Resolves once this round's\n * fetches settle. Concurrent fetches are serialized inside each binding.\n */\n async pump(): Promise<void> {\n if (this.closed) {\n return;\n }\n // Collapse this round's misses to the latest observed frontier per clip.\n // Queue order reflects playback order, so a backward seek/loop request that\n // follows a stale high-page miss must win even though its page index is\n // smaller. Multiple channel misses still collapse to one service window.\n const frontiers = new Map<number, number>();\n for (let drained = 0; drained < this.maxRequestsPerPump; ++drained) {\n const request = this.engine.popClipPageRequest();\n if (!request) {\n break;\n }\n const state = this.sources.get(request.clipId);\n if (!state) {\n continue;\n }\n const page =\n request.pageIndex !== undefined\n ? request.pageIndex\n : Math.floor((request.sample ?? Number.NaN) / state.source.pageFrames);\n if (!Number.isInteger(page) || page < 0 || page > state.lastPage) {\n continue;\n }\n frontiers.set(request.clipId, page);\n }\n\n const fetches: Promise<unknown>[] = [];\n for (const [clipId, frontier] of frontiers) {\n const state = this.sources.get(clipId);\n if (!state) {\n continue;\n }\n fetches.push(...this.serviceFrontier(state, frontier));\n }\n await Promise.all(fetches);\n }\n\n /** Close every registered clip's binding and stop tracking. */\n close(): void {\n if (this.closed) {\n return;\n }\n this.closed = true;\n for (const state of this.sources.values()) {\n this.resetState(state);\n state.source.binding.close();\n }\n this.sources.clear();\n }\n\n private serviceFrontier(state: SourceState, frontier: number): Promise<unknown>[] {\n // A lower frontier after a previously serviced high page is a seek/loop\n // discontinuity. Advance generation before scheduling its new window so an\n // older asynchronous fetch can never become resident in the new window.\n if (state.lastFrontier !== null && frontier < state.lastFrontier) {\n this.resetState(state);\n }\n state.lastFrontier = frontier;\n const generation = state.generation;\n const low = Math.max(0, frontier - this.retainBehindPages);\n const high = Math.min(state.lastPage, frontier + this.readAheadPages);\n\n // Evict pages outside the window first so a burst of fetches never exceeds\n // the bound by transiently holding old pages alongside new ones.\n for (const page of state.resident.keys()) {\n if (page < low || page > high) {\n this.clearPage(state, page);\n state.resident.delete(page);\n }\n }\n\n const fetches: Promise<unknown>[] = [];\n for (let page = low; page <= high; ++page) {\n if (state.resident.get(page) === generation) {\n continue;\n }\n // Mark resident eagerly so the same page is not fetched twice across\n // overlapping windows; drop it again if the fetch reports a miss.\n state.resident.set(page, generation);\n const pageIndex = page;\n fetches.push(\n state.source.binding.supplyPage(pageIndex).then(\n (ok) => {\n if (state.generation !== generation) {\n // The fetch crossed a seek/reset boundary. supplyPage may have\n // installed it after resetState's clear pass, so clear it again.\n this.clearPage(state, pageIndex);\n } else if (!ok && state.resident.get(pageIndex) === generation) {\n state.resident.delete(pageIndex);\n }\n return ok;\n },\n (error) => {\n if (state.resident.get(pageIndex) === generation) {\n state.resident.delete(pageIndex);\n }\n throw error;\n },\n ),\n );\n }\n return fetches;\n }\n\n private resetState(state: SourceState): void {\n state.generation += 1;\n state.lastFrontier = null;\n for (const page of state.resident.keys()) {\n this.clearPage(state, page);\n }\n state.resident.clear();\n }\n\n private clearPage(state: SourceState, pageIndex: number): void {\n // `clearPage` mirrors eviction into the AudioWorklet. Keep the older\n // provider-only form working for direct-engine callers and test doubles.\n if (state.source.binding.clearPage) {\n state.source.binding.clearPage(pageIndex);\n } else {\n state.source.binding.provider.clear(pageIndex);\n }\n }\n}\n\nexport interface OpfsClipStreamOptions extends OpfsClipPageProviderOptions {\n /** Clip schedule id used in `setClips` (matches the page-miss request clipId). */\n clipId: number;\n /**\n * Leading pages fetched synchronously before returning, so playback can start\n * without an immediate miss. Default 1.\n */\n primePages?: number;\n}\n\nexport interface OpfsClipStream {\n binding: OpfsClipPageProviderBinding;\n /** Pass as `addClip`'s buffer argument to schedule the streaming clip. */\n provider: ClipPageProvider;\n}\n\n/** Structural seam implemented by the AudioWorklet-backed `SonareEngine`. */\nexport interface WorkletOpfsClipStreamHost {\n attachOpfsClipStream(options: OpfsClipStreamOptions): Promise<OpfsClipStream>;\n}\n\n/**\n * One-call wiring of an OPFS-backed streaming clip: creates the page provider,\n * primes the leading pages, and registers it with `streamer` so later misses are\n * serviced within the bounded window. Returns the binding (for `close`) and the\n * provider to schedule via `addClip(trackId, provider, startPpq, { id: clipId })`.\n *\n * @param streamer Shared streamer pumped on the control thread.\n * @param engine Engine the provider is created on (the same one `streamer` drives).\n * @param options Provider options plus `clipId` and optional `primePages`.\n */\nexport function attachOpfsClipStream(\n streamer: ClipPageStreamer,\n engine: RealtimeEngine,\n options: OpfsClipStreamOptions,\n): Promise<OpfsClipStream>;\n/**\n * Worklet overload: delegates to `SonareEngine.attachOpfsClipStream`, which\n * creates the remote provider and drives this same sliding-window policy from\n * worklet page-miss messages.\n */\nexport function attachOpfsClipStream(\n engine: WorkletOpfsClipStreamHost,\n options: OpfsClipStreamOptions,\n): Promise<OpfsClipStream>;\nexport async function attachOpfsClipStream(\n streamerOrEngine: ClipPageStreamer | WorkletOpfsClipStreamHost,\n engineOrOptions: RealtimeEngine | OpfsClipStreamOptions,\n maybeOptions?: OpfsClipStreamOptions,\n): Promise<OpfsClipStream> {\n if (!(streamerOrEngine instanceof ClipPageStreamer)) {\n return streamerOrEngine.attachOpfsClipStream(engineOrOptions as OpfsClipStreamOptions);\n }\n const streamer = streamerOrEngine;\n const engine = engineOrOptions as RealtimeEngine;\n const options = maybeOptions;\n if (!options) {\n throw new Error('attachOpfsClipStream requires options.');\n }\n const { clipId, primePages = 1, ...providerOptions } = options;\n const binding = createOpfsClipPageProvider(engine, providerOptions);\n const lastPage = Math.ceil(providerOptions.numSamples / providerOptions.pageFrames) - 1;\n const primed: number[] = [];\n for (let page = 0; page < primePages && page <= lastPage; ++page) {\n if (await binding.supplyPage(page)) {\n primed.push(page);\n }\n }\n streamer.addSource(\n {\n clipId,\n binding,\n pageFrames: providerOptions.pageFrames,\n numSamples: providerOptions.numSamples,\n },\n primed,\n );\n return { binding, provider: binding.provider };\n}\n","import type { SonareRealtimeEngineNode } from './worklet';\n\nexport interface BindMicrophoneInputOptions extends MediaStreamConstraints {\n /**\n * Stream to bind instead of requesting one. Supplying it also transfers\n * ownership: {@link MicrophoneInputBinding.close} leaves its tracks running,\n * because they may be feeding a recorder, a level meter or a second\n * `AudioContext` that this binding knows nothing about.\n */\n stream?: MediaStream;\n /**\n * Whether {@link MicrophoneInputBinding.close} stops the stream's audio\n * tracks. Defaults to whether this binding acquired the stream itself: `true`\n * for a stream it requested through `getUserMedia`, `false` for one the\n * caller supplied. Set it explicitly to override in either direction.\n */\n stopTracksOnClose?: boolean;\n}\n\nexport interface MicrophoneInputBinding {\n stream: MediaStream;\n source: MediaStreamAudioSourceNode;\n /** Whether this binding acquired {@link stream} rather than being handed one. */\n ownsStream: boolean;\n close(): void;\n}\n\n/**\n * Route microphone audio into a realtime engine node.\n *\n * Ownership is decided by provenance, the same rule `ownsWorker` applies in\n * `opfs_clip_pages.ts` and `worker_client.ts`: a resource the caller handed in\n * is the caller's to release. `close()` used to stop the tracks of a supplied\n * stream by default, which killed a microphone the rest of the page was still\n * using.\n */\nexport async function bindMicrophoneInput(\n context: AudioContext,\n engine: SonareRealtimeEngineNode | AudioWorkletNode,\n options: BindMicrophoneInputOptions = {},\n): Promise<MicrophoneInputBinding> {\n const { stream: providedStream, stopTracksOnClose: stopTracksOverride, ...constraints } = options;\n const ownsStream = providedStream === undefined;\n const stopTracksOnClose = stopTracksOverride ?? ownsStream;\n const stream =\n providedStream ??\n (await navigator.mediaDevices.getUserMedia({\n ...constraints,\n audio: constraints.audio ?? true,\n video: constraints.video ?? false,\n }));\n const source = context.createMediaStreamSource(stream);\n const node = 'node' in engine ? engine.node : engine;\n source.connect(node);\n let closed = false;\n return {\n stream,\n source,\n ownsStream,\n close() {\n if (closed) {\n return;\n }\n closed = true;\n source.disconnect();\n if (stopTracksOnClose) {\n for (const track of stream.getAudioTracks()) {\n track.stop();\n }\n }\n },\n };\n}\n","import { getSonareModule } from './module_state';\nimport type { MixAssistantOptions, MixAssistantResult, MixAssistantTrack } from './public_types';\nimport { assertSampleRate } from './validation';\n\nfunction requireModule() {\n return getSonareModule();\n}\n\n/** Inputs for the {@link suggestMixScene} / {@link suggestMixSceneJson} facades. */\nexport interface SuggestMixSceneRequest {\n /** Tracks to mix, in the order their profiles are reported. */\n tracks: MixAssistantTrack[];\n /**\n * Shared sample rate in Hz for every track. Required: every band edge,\n * high-pass corner, sibilance band and alignment lag is derived from it, so a\n * guessed rate would silently misread 44.1 kHz material by 8.8% and report\n * `channelDelaySamples` and `durationSec` wrong with it.\n */\n sampleRate: number;\n /** Assistant tunables; every field falls back to the core default. */\n options?: MixAssistantOptions;\n}\n\n/** The four parallel arrays the embind entry points take. */\ninterface PlanarTracks {\n left: Float32Array[];\n right: (Float32Array | null)[];\n ids: string[];\n names: (string | null)[];\n}\n\n/**\n * Splits the request's track list into the planar per-track arrays the binding\n * takes, rejecting the shapes that would otherwise reach the analysis as a\n * missing buffer or a nameless strip.\n */\nfunction planarTracks(tracks: MixAssistantTrack[]): PlanarTracks {\n if (!Array.isArray(tracks)) {\n throw new Error('tracks must be an array.');\n }\n const left: Float32Array[] = [];\n const right: (Float32Array | null)[] = [];\n const ids: string[] = [];\n const names: (string | null)[] = [];\n for (let index = 0; index < tracks.length; index++) {\n const track = tracks[index];\n if (track === null || typeof track !== 'object') {\n throw new Error(`tracks[${index}] must be an object.`);\n }\n if (typeof track.id !== 'string' || track.id.length === 0) {\n throw new Error(`tracks[${index}].id must be a non-empty string.`);\n }\n if (!(track.left instanceof Float32Array)) {\n throw new Error(`tracks[${index}].left must be a Float32Array.`);\n }\n if (track.right !== undefined && !(track.right instanceof Float32Array)) {\n throw new Error(`tracks[${index}].right must be a Float32Array when present.`);\n }\n left.push(track.left);\n right.push(track.right ?? null);\n ids.push(track.id);\n names.push(track.name ?? null);\n }\n return { left, right, ids, names };\n}\n\nfunction suggestJson(fnName: string, request: SuggestMixSceneRequest, sceneOnly: boolean): string {\n // Required, not defaulted: this surface used to invent 48000, which read\n // 44.1 kHz material 8.8% off across every band edge and every lag without\n // saying so. Node and Python both demand it, and a request ported from either\n // must not change behaviour by arriving here.\n assertSampleRate(fnName, request.sampleRate);\n const { left, right, ids, names } = planarTracks(request.tracks);\n const sampleRate = request.sampleRate;\n const params = (request.options ?? {}) as Record<string, number | boolean>;\n const module = requireModule();\n return sceneOnly\n ? module.mixingAssistantSuggestSceneJson(left, right, ids, names, sampleRate, params)\n : module.mixingAssistantSuggest(left, right, ids, names, sampleRate, params);\n}\n\n/**\n * Analyze a set of tracks and suggest a mixer scene.\n *\n * Offline only: the pipeline runs an STFT per track and evaluates every track\n * pair, so it is measured in milliseconds per track and must never be called\n * from an audio callback.\n *\n * The assistant suggests, it does not apply. Nothing is processed and no audio\n * is returned; realizing the suggestion means handing the scene to\n * {@link Mixer.fromSceneJson} as an explicit second step, for which\n * {@link suggestMixSceneJson} returns the scene already serialized.\n *\n * Degenerate input is not an error: no tracks, all-silent tracks or tracks too\n * short to measure yield an empty scene and an empty `explanation`.\n *\n * @param request - Tracks, shared sample rate and assistant options\n * @returns The suggested scene, per-track profiles, cross-track measurements\n * and the explanation behind each change\n */\nexport function suggestMixScene(request: SuggestMixSceneRequest): MixAssistantResult {\n return JSON.parse(suggestJson('suggestMixScene', request, false)) as MixAssistantResult;\n}\n\n/**\n * Suggest a mixer scene and return only the scene, as JSON.\n *\n * The same analysis as {@link suggestMixScene}, serialized in the schema\n * {@link Mixer.fromSceneJson} reads, so a caller that only wants to apply the\n * suggestion neither digs the scene out of the fuller result nor re-serializes\n * it.\n *\n * @param request - Tracks, shared sample rate and assistant options\n * @returns Scene JSON string\n */\nexport function suggestMixSceneJson(request: SuggestMixSceneRequest): string {\n return suggestJson('suggestMixSceneJson', request, true);\n}\n\n/**\n * Source-class identifiers the assistant can report, in enum order.\n *\n * The index of a name in this list is the value\n * {@link mixSourceClassFromName} resolves it to.\n */\nexport function mixSourceClassNames(): string[] {\n return Array.from(requireModule().mixingAssistantSourceClassNames());\n}\n\n/**\n * Resolve a source-class identifier to its index in {@link mixSourceClassNames}.\n *\n * @param name - Source-class identifier, e.g. `\"kick\"`\n * @returns The index, or -1 when the name is unknown\n */\nexport function mixSourceClassFromName(name: string): number {\n return requireModule().mixingAssistantSourceClassFromName(name);\n}\n","import { getSonareModule } from './module_state';\nimport type {\n PlaybackDiagnostics,\n PlaybackRendererConfig,\n PlaybackRendererOptions,\n RenderPlaybackRequest,\n RenderPlaybackResult,\n} from './public_types_playback';\nimport type { WasmHrtfSet, WasmPlaybackLoudnessMeter, WasmPlaybackRenderer } from './sonare.js';\n\nfunction configJsonText(config: PlaybackRendererConfig | string): string {\n return typeof config === 'string' ? config : JSON.stringify(config);\n}\n\n/**\n * Reads {@link HrtfSet}'s private `native`: TypeScript's `private` is a\n * compile-time rule, so one reviewed read here beats widening the class with a\n * handle accessor no caller wants.\n */\nfunction nativeHrtf(hrtf: HrtfSet | undefined): WasmHrtfSet | null {\n if (hrtf === undefined) {\n return null;\n }\n if (!(hrtf instanceof HrtfSet)) {\n throw new TypeError('hrtf must be an HrtfSet');\n }\n return (hrtf as unknown as { native: WasmHrtfSet }).native;\n}\n\n/**\n * An HRTF set (SHRF v1): the direct-sound impulse responses and inter-aural\n * time delays a headphones-target {@link PlaybackRenderer} convolves each\n * virtual speaker's signal with.\n *\n * This build embeds no HRTF data. The package ships the default set as the\n * asset `@libraz/libsonare/hrtf/default.shrf`; fetch or read it and pass the\n * bytes to {@link HrtfSet.fromBytes}. A renderer built from a set keeps its\n * own copy, so deleting the set right after construction is safe.\n *\n * @example\n * ```ts\n * const bytes = new Uint8Array(await (await fetch(hrtfUrl)).arrayBuffer());\n * const hrtf = HrtfSet.fromBytes(bytes);\n * const renderer = new PlaybackRenderer({ config: {}, hrtf, sampleRate: 48000 });\n * hrtf.delete();\n * ```\n */\nexport class HrtfSet {\n private native: WasmHrtfSet;\n private released = false;\n\n private constructor(native: WasmHrtfSet) {\n this.native = native;\n }\n\n /** Builds an HRTF set from SHRF v1 bytes; malformed data throws. */\n static fromBytes(bytes: Uint8Array): HrtfSet {\n return new HrtfSet(getSonareModule().createHrtfSet(bytes));\n }\n\n /** Releases the native handle. Idempotent, as the Node facade is. */\n delete(): void {\n if (this.released) {\n return;\n }\n this.released = true;\n this.native.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n\n/**\n * Renders decoded movie audio (mono / stereo / 5.1 / 7.1 PCM) to headphones\n * (binaural, head tracking, room model) or to stereo / 5.1 / 7.1 speakers\n * (upmix, loudness alignment, night-mode DRC, dialogue level, speaker\n * calibration, bass management).\n *\n * `config` follows `schemas/playback-renderer-config.schema.json`; see\n * {@link PlaybackRendererConfig}. A headphones target requires `hrtf`.\n *\n * `processPlanar` copies every plane through the embind boundary, so it suits\n * the main thread; like `processInterleaved`, a non-finite sample is replaced\n * with 0 and counted rather than refused. The AudioWorklet path is\n * `SonarePlaybackWorkletProcessor` in the worklet bundle.\n */\nexport class PlaybackRenderer {\n private native: WasmPlaybackRenderer;\n private released = false;\n\n constructor(options: PlaybackRendererOptions) {\n this.native = getSonareModule().createPlaybackRenderer(\n configJsonText(options.config),\n nativeHrtf(options.hrtf),\n options.sampleRate ?? 48000,\n options.maxBlockSize ?? 1024,\n );\n }\n\n /**\n * Renders one planar block; every plane must carry the same frame count, at\n * most `maxBlockSize` (0 is a no-op). With a fixed input layout the plane\n * count must equal {@link inputChannels}; with `input.layout: \"auto\"` it\n * must be 1, 2, 6 or 8, and a change switches the input layout without\n * changing the latency. Non-finite input samples are replaced with 0 and\n * counted ({@link nonFiniteDiscardCount}).\n */\n processPlanar(planes: Float32Array[]): Float32Array[] {\n return this.native.processPlanar(planes);\n }\n\n /** Interleaved variant of {@link processPlanar}. Non-finite input samples are replaced with 0 and counted. */\n processInterleaved(samples: Float32Array, inChannels: number): Float32Array {\n return this.native.processInterleaved(samples, inChannels);\n }\n\n /** Applies a complete configuration document; a changed prepare key throws. */\n setConfig(config: PlaybackRendererConfig | string): void {\n this.native.setConfig(configJsonText(config));\n }\n\n /** The current complete configuration document. */\n config(): PlaybackRendererConfig {\n return JSON.parse(this.native.configJson()) as PlaybackRendererConfig;\n }\n\n /**\n * Publishes the listener head orientation in degrees: right-handed,\n * positive yaw turns the head right, positive pitch looks up, positive roll\n * lowers the right ear. Ignored by a speakers target; a non-finite angle is\n * ignored.\n */\n setHeadOrientation(yawDeg: number, pitchDeg = 0, rollDeg = 0): void {\n this.native.setHeadOrientation(yawDeg, pitchDeg, rollDeg);\n }\n\n /**\n * Clears DSP state (filters, FIFOs, dynamics, convolution history, pending\n * input-layout drains). Configuration and head pose are kept. Call it after\n * a seek, from the thread that processes.\n */\n reset(): void {\n this.native.reset();\n }\n\n /**\n * Renderer latency in samples (headphones: near ear). Depends only on the\n * target, the sample rate and distance compensation, never on realtime keys\n * or the input layout.\n */\n latencySamples(): number {\n return this.native.latencySamples();\n }\n\n /**\n * Channel count of the active input layout. With `input.layout: \"auto\"`\n * this follows the channel count of the most recent non-empty process call\n * (2 before the first call).\n */\n inputChannels(): number {\n return this.native.inputChannels();\n }\n\n /** Channel count of the output target. */\n outputChannels(): number {\n return this.native.outputChannels();\n }\n\n /**\n * Inactive stages, per-stage latency, clamps, the active input layout, and\n * the layout-switch / truncated-drain counters, as a plain object.\n */\n diagnostics(): PlaybackDiagnostics {\n return JSON.parse(this.native.diagnosticsJson()) as PlaybackDiagnostics;\n }\n\n /** Non-finite input samples replaced with 0 since construction. */\n nonFiniteDiscardCount(): number {\n return this.native.nonFiniteDiscardCount();\n }\n\n /** Releases the native handle. Idempotent, as the Node facade is. */\n delete(): void {\n if (this.released) {\n return;\n }\n this.released = true;\n this.native.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n\n/**\n * Integrated-loudness meter for multichannel program material (BS.1770\n * channel weights by channel count: 1, 2, 6 or 8), for measuring\n * `loudness.program_lufs` ahead of a {@link PlaybackRenderer}.\n */\nexport class PlaybackLoudnessMeter {\n private native: WasmPlaybackLoudnessMeter;\n private released = false;\n\n constructor(channels: number, sampleRate: number) {\n this.native = getSonareModule().createPlaybackLoudnessMeter(channels, sampleRate);\n }\n\n /** Feeds interleaved frames of any length. */\n pushInterleaved(samples: Float32Array): void {\n this.native.pushInterleaved(samples);\n }\n\n /** Integrated loudness of everything pushed so far, in LUFS. */\n integratedLufs(): number {\n return this.native.integratedLufs();\n }\n\n /** Releases the native handle. Idempotent, as the Node facade is. */\n delete(): void {\n if (this.released) {\n return;\n }\n this.released = true;\n this.native.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n\n/**\n * Offline one-shot playback render: builds a renderer internally, feeds the\n * whole interleaved signal through it, and removes the renderer's own latency\n * so the output aligns with the input frame for frame.\n * An empty or non-finite `samples` is refused with an `InvalidParameter` error.\n */\nexport function renderPlayback(request: RenderPlaybackRequest): RenderPlaybackResult {\n return getSonareModule().renderPlayback(\n request.samples,\n request.channels,\n request.sampleRate,\n configJsonText(request.config),\n nativeHrtf(request.hrtf),\n );\n}\n","import { ErrorCode, SonareError } from './errors';\nimport { getSonareModule } from './module_state';\nimport type {\n NoteEditInput,\n NoteObject,\n PolyphonicAnalysisOptions,\n PolyphonicRenderOptions,\n} from './public_types';\nimport type { WasmPolyphonicAnalysis } from './sonare.js';\nimport type { ValidateOptions } from './validation';\nimport { assertSampleRate, assertSamples } from './validation';\n\n/** Canonical request form for {@link analyzePolyphonic}. */\nexport interface AnalyzePolyphonicRequest extends PolyphonicAnalysisOptions, ValidateOptions {\n samples: Float32Array;\n /**\n * Sample rate in Hz. Required: every duration in the chain — the ridge\n * minimum, the note minimum, the per-frame windows — is converted to samples\n * with this rate, so a wrong value silently analyses differently.\n */\n sampleRate: number;\n}\n\n/**\n * A polyphonic analysis, held as a handle so one note of a chord can be edited\n * and the result re-rendered without analysing the audio again.\n *\n * Created by {@link analyzePolyphonic}. **Release it with {@link destroy} as soon\n * as you are done with it**: the handle owns the source's complex spectrogram plus\n * the claimed bins of every note, which is the input over again plus the claims.\n * That is the price of re-rendering an edit for free, and it is why this is a\n * handle and not a result object — the measurement never crosses into JS.\n *\n * What crosses is what a host acts on: the notes ({@link notes}), each note's\n * pending edit ({@link setNoteEdit}), the per-frame voice count\n * ({@link polyphony}), and per note a pitch, a level and a salience curve. The\n * spectrogram, the masks and the per-bin weights do not, and no method reports a\n * per-bin figure.\n *\n * Using the analysis after it has been released throws `InvalidState` rather than\n * reaching a freed native object.\n */\nexport class PolyphonicAnalysis {\n private native: WasmPolyphonicAnalysis | null;\n\n /** Analyses the request's audio. {@link analyzePolyphonic} is the same call. */\n constructor(request: AnalyzePolyphonicRequest) {\n assertSamples('analyzePolyphonic', request.samples, request.validate !== false);\n assertSampleRate('analyzePolyphonic', request.sampleRate);\n const module = getSonareModule();\n this.native = module.createPolyphonicAnalysis(\n request.samples,\n request.sampleRate,\n request as unknown as Record<string, unknown>,\n );\n }\n\n private handle(): WasmPolyphonicAnalysis {\n if (this.native === null) {\n throw new SonareError(\n ErrorCode.InvalidState,\n 'InvalidState',\n 'PolyphonicAnalysis has been released',\n );\n }\n return this.native;\n }\n\n /** Number of notes, which is also the number of claim sets. */\n get noteCount(): number {\n return this.handle().noteCount;\n }\n\n /** Number of STFT frames the analysis ran over. */\n get frameCount(): number {\n return this.handle().frameCount;\n }\n\n /**\n * Every note, in the order their claim sets are held in — the same\n * {@link NoteObject} shape `extractNotes` returns, so a host that edits through\n * both doors sees one note.\n *\n * Each note carries its sample span, its frame span (in the analysis's own\n * framing), its median pitch, its steadiness, its per-frame `amplitude` and its\n * pending edit. The curves a note does not carry inline have their own accessors:\n * {@link noteF0}, {@link noteSalience}, and {@link noteEnvelope} for the points\n * last set through {@link setNoteEdit}. `amplitude` is {@link noteAmplitude}'s\n * curve, read once per note.\n */\n notes(): NoteObject[] {\n return this.handle().notes();\n }\n\n /**\n * Replaces one note's pending edit.\n *\n * The only thing a host writes. Everything else on a note is a measurement, and\n * the order is the pairing with the claim sets, so neither is settable.\n *\n * An omitted field is the identity, so `{}` restores the identity edit. The\n * envelope is `edit.amplitudeEnvelope`, which the handle copies, and its points\n * are per-frame linear gains over the note's span on top of `gainDb` — stretched\n * over whatever length the note renders at, so one entry is a constant gain and\n * the count need not match the note's frame count. Every value must be finite\n * and non-negative, which {@link render} is where it is checked, so one refusal\n * names one place.\n *\n * @param note - Index below {@link noteCount}\n * @throws {SonareError} `InvalidParameter` when `note` is out of range\n */\n setNoteEdit(note: number, edit: NoteEditInput): void {\n this.handle().setNoteEdit(note, edit);\n }\n\n /**\n * Voices estimated per frame, before tracking dropped anything — one entry per\n * frame from frame 0.\n *\n * What the estimation saw rather than what survived: a frame reported as three\n * voices with two notes spanning it is the difference between the two stages,\n * which is the figure a host deciding what to edit wants.\n */\n polyphony(): Int32Array {\n return this.handle().polyphony();\n }\n\n /**\n * One note's F0 in Hz, per frame over its own span.\n *\n * `frameEnd - frameStart` entries, so the value at index `i` belongs to frame\n * `frameStart + i`. This is the curve the monophonic door makes a caller pass\n * back in; here the handle already holds it, so a curve edit needs nothing from\n * the caller.\n *\n * @throws {SonareError} `InvalidParameter` when `note` is out of range\n */\n noteF0(note: number): Float32Array {\n return this.handle().noteF0(note);\n }\n\n /** One note's linear RMS, per frame over its own span. Indexed as {@link noteF0}. */\n noteAmplitude(note: number): Float32Array {\n return this.handle().noteAmplitude(note);\n }\n\n /**\n * One note's salience, per frame over its own span. Indexed as {@link noteF0},\n * and the one curve here that is not the note's own: it is the tracked ridge's,\n * so a frame of the note the ridge does not reach reads 0.\n *\n * Salience is what the estimation scored the candidate at, so it says how well\n * the material supported this note rather than how loud the note is —\n * {@link noteAmplitude} is the loud.\n */\n noteSalience(note: number): Float32Array {\n return this.handle().noteSalience(note);\n }\n\n /**\n * The stretch fitted for each note, one entry per note in {@link notes}' order.\n *\n * Empty when `estimateInharmonicity` was not set, so an empty array means the\n * fit was never asked for. A non-negative entry is a fitted stretch; **exactly\n * `-1` is the refusal**, and a refused note's claims were placed at the\n * `inharmonicity` the request declared instead.\n *\n * **`0` is a fitted result and means the harmonic series**, which is why the\n * refusal is reported at all: the declared stretch also defaults to 0, so the\n * effective value alone cannot separate a fit that reached the material from one\n * that did not. The fit refuses a chord at the default framing, so the\n * distinction is the usual case rather than an edge one.\n *\n * @example\n * ```typescript\n * const analysis = analyzePolyphonic({ samples, sampleRate, estimateInharmonicity: true });\n * const fitted = analysis.noteInharmonicity();\n * const reached = [...fitted].filter((stretch) => stretch >= 0).length;\n * ```\n */\n noteInharmonicity(): Float32Array {\n return this.handle().noteInharmonicity();\n }\n\n /**\n * One note's amplitude envelope points, as last set — the same array\n * `notes()[note].edit.amplitudeEnvelope` carries.\n *\n * Indexed from 0 rather than over the note's span: an envelope is a set of gain\n * points stretched over whatever length the note renders at, not a per-frame\n * signal. The only one of the four curves that is not a measurement, and empty on\n * a note carrying no envelope.\n */\n noteEnvelope(note: number): Float32Array {\n return this.handle().noteEnvelope(note);\n }\n\n /**\n * Renders the analysis back to audio with whatever edits its notes carry, at the\n * source's length.\n *\n * Each note's claimed share is inverted, edited, and added to the residual — the\n * part of the input no note claimed. With every edit identity the result is the\n * analysis's own round trip, not the source bit for bit, the STFT round trip's\n * error being neither added to nor removed here.\n *\n * The render is additive per note with no cross-note term, so an unedited note's\n * contribution is identical between two renders. That is also the limit: a host\n * cannot tell from two renders whether a claim set divided the energy correctly.\n *\n * @throws {SonareError} `InvalidParameter` on an option or an edit field the\n * renderer rejects — a non-positive stretch ratio, a negative or non-finite\n * envelope point, or a vibrato or drift edit on a note carrying no usable\n * pitch curve\n */\n render(options: PolyphonicRenderOptions = {}): Float32Array {\n return this.handle().render(options as Record<string, unknown>);\n }\n\n /**\n * Releases the underlying WASM object and everything it holds. Idempotent,\n * as the Node facade is; any other method called after this one still\n * throws `InvalidState` rather than reaching a freed native object.\n */\n delete(): void {\n if (this.native === null) {\n return;\n }\n const native = this.native;\n this.native = null;\n native.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n\n/**\n * Analyses audio into editable notes and returns a handle to the analysis.\n *\n * One pass: one STFT, the multi-F0 extraction over it, a claim set per tracked\n * ridge, the apportionment of the bins two notes stand on, and the measured fields\n * of each note. Every note comes back with the identity edit, so rendering the\n * result unchanged reproduces the analysis's own round trip.\n *\n * An analysis finding no notes is not an error. Silence, or material the register\n * of the framing cannot resolve, tracks no ridge; rendering that is the residual\n * alone, which is the whole round trip.\n *\n * **This is for spans, not for whole songs.** The handle holds the source's\n * complex spectrogram plus every note's claimed bins — roughly 1,440 MiB for five\n * minutes of audio against a 2 GiB linear-memory cap — so analyse the passage you\n * are editing and {@link PolyphonicAnalysis.destroy} it when done.\n *\n * @throws {RangeError} on empty samples, a non-finite sample, or a `sampleRate`\n * outside `[8000, 384000]`\n * @throws {SonareError} `InvalidParameter` on a config value the chain rejects,\n * or on audio too short for two STFT frames at the configured `nFft`/`hopLength`\n * (roughly one `hopLength`, ~512 samples at the default)\n *\n * @example\n * ```typescript\n * const analysis = analyzePolyphonic({ samples, sampleRate, maxPolyphony: 3 });\n * try {\n * // Transpose the lowest note of the chord up a semitone.\n * const notes = analysis.notes();\n * const lowest = notes.reduce((a, b) => (a.medianHz <= b.medianHz ? a : b));\n * analysis.setNoteEdit(notes.indexOf(lowest), { pitchShiftSemitones: 1 });\n * const edited = analysis.render();\n * } finally {\n * analysis.destroy();\n * }\n * ```\n */\nexport function analyzePolyphonic(request: AnalyzePolyphonicRequest): PolyphonicAnalysis {\n return new PolyphonicAnalysis(request);\n}\n","/**\n * Instrument definitions a project source plays through: the built-in synth\n * patch, the SoundFont player, and the sample bank's descriptors.\n */\n\nimport type { SampleBank } from './sample_bank';\n\n/** Names accepted by the minimal built-in oscillator synth. */\nexport const BUILTIN_SYNTH_WAVEFORMS = ['sine', 'saw', 'sawtooth', 'square', 'triangle'] as const;\n\n/** Oscillator waveform for the built-in synth. */\nexport type BuiltinSynthWaveform = (typeof BUILTIN_SYNTH_WAVEFORMS)[number] | 0 | 1 | 2 | 3;\n\n/**\n * Built-in synth patch + MIDI routing for\n * {@link Project.bounceWithBuiltinInstrument}. Every field is optional; a\n * non-positive (or omitted) numeric field falls back to the C-ABI default\n * (gain 0.2, attack 5ms, decay 60ms, sustain 0.7, release 120ms, 16 voices),\n * so `{}` is a usable default sine patch.\n */\nexport interface BuiltinSynthBinding {\n /** MIDI destination id this patch answers to (default 0; see {@link Project.setTrackMidiDestination}). */\n destinationId?: number;\n /**\n * Oscillator waveform (default `'sine'`). The one field with no nearest\n * sensible value — a name or an ordinal outside the set throws rather than\n * falling back to sine.\n */\n waveform?: BuiltinSynthWaveform;\n /** Master output gain, linear (0 => 0.2). */\n gain?: number;\n /** ADSR attack in ms (0 => 5). */\n attackMs?: number;\n /** ADSR decay in ms (0 => 60). */\n decayMs?: number;\n /** ADSR sustain level [0,1] (0 => 0.7). */\n sustain?: number;\n /** ADSR release in ms (0 => 120). */\n releaseMs?: number;\n /** Max simultaneous voices (0 => 16, clamped to [1, 64]). */\n polyphony?: number;\n}\n\n/**\n * Cross-binding alias of {@link BuiltinSynthBinding}. The same built-in-synth\n * patch concept is named `BuiltinSynthConfig` in the Python binding; this alias\n * lets portable code use that shared name on the WASM surface too.\n */\nexport type BuiltinSynthConfig = BuiltinSynthBinding;\n\n/**\n * SoundFont (SF2) player patch + MIDI routing for\n * {@link Project.bounceWithSf2Instrument}. Every field is optional; a\n * non-positive (or omitted) numeric field falls back to the C-ABI default\n * (gain 0.5, 48 voices), so `{}` is a usable default patch.\n */\nexport interface Sf2InstrumentConfig {\n /** MIDI destination id this player answers to (default 0; see {@link Project.setTrackMidiDestination}). */\n destinationId?: number;\n /** Master output gain, linear (0 => 0.5). */\n gain?: number;\n /** Max simultaneous voices (0 => 48, clamped to [1, 64]). */\n polyphony?: number;\n /** Prefer dedicated physical models for covered melodic GM programs. Defaults to false; drums stay SF2-first. */\n preferModelForModeledFamilies?: boolean;\n /**\n * Render the instrument alone, without the stage the bank binds after its\n * voice — the amplifier and cabinet an electric guitar is never heard\n * without. Defaults to false, so a MIDI file that selects a distorted guitar\n * and asks for nothing else still comes out amplified. Set it to get the\n * direct signal, which is what a voice is calibrated against.\n */\n clearBankRig?: boolean;\n /**\n * How the GS insertion effects (EFX) are realised: 'modern' (default) or\n * 'classic'. Any other value is refused by name.\n */\n gsEfxRealization?: 'modern' | 'classic';\n}\n\n/** Source backend a resolved MIDI program renders through. */\nexport type SourceBackend = 'sf2' | 'synth';\n\n/**\n * One {@link Project.soundFontManifest} entry: a (channel, bank, program)\n * combination the arrangement plays, with the backend it resolves to.\n */\nexport interface Sf2ProgramStatus {\n /** MIDI channel (0-15). */\n channel: number;\n /** Effective SF2 bank (drum channels report 128). */\n bank: number;\n /** Program number (0-127). */\n program: number;\n /** `'sf2'` when the loaded SoundFont covers the program, else `'synth'`. */\n backend: SourceBackend;\n /** Resolved SF2 preset name (GS fallback included); empty for `'synth'`. */\n presetName: string;\n}\n\n/**\n * Every NativeSynth engine selector, by ordinal.\n *\n * @remarks\n * Not seventeen interchangeable choices. Selecting a mode blanks every engine\n * section but its own, and four engines have nothing to voice until a section\n * is supplied: `'fm'` needs operators, `'modal'` a mode table, `'percussion'` a\n * kit and `'sample'` a {@link SampleBank}. Each renders exact silence from an\n * otherwise default patch (measured: peak 0), while the other thirteen sound\n * and differ from one another. A host offering this array as a control offers\n * those four as dead entries unless it also supplies the section, which a\n * preset does.\n */\nexport const SYNTH_ENGINE_MODES = [\n 'default',\n 'subtractive',\n 'fm',\n 'karplus-strong',\n 'modal',\n 'additive',\n 'percussion',\n 'piano',\n 'pipe-organ',\n 'bowed-string',\n 'reed',\n 'brass',\n 'flute',\n 'plucked-string',\n 'vocal',\n 'free-reed',\n 'harpsichord',\n 'sample',\n] as const;\n\nexport const SAMPLE_LOOP_MODES = ['default', 'none', 'continuous', 'key-down'] as const;\n\nexport const SAMPLE_KEY_TRACKS = ['default', 'on', 'off'] as const;\n\nexport const SYNTH_RETRIGGERS = ['default', 'free', 'note'] as const;\n\nexport const SYNTH_OSC_WAVEFORMS = [\n 'default',\n 'sine',\n 'saw',\n 'square',\n 'triangle',\n 'noise',\n] as const;\n\nexport const SYNTH_FILTER_MODELS = [\n 'default',\n 'svf',\n 'moog-ladder',\n 'diode-ladder',\n 'sallen-key',\n] as const;\n\nexport const SYNTH_FILTER_OUTPUTS = ['default', 'lowpass', 'bandpass', 'highpass'] as const;\n\nexport const SYNTH_BODY_TYPES = [\n 'default',\n 'none',\n 'guitar',\n 'violin',\n 'wood-tube',\n 'brass-bell',\n 'vocal',\n] as const;\n\nexport const SYNTH_MOD_SOURCES = [\n 'none',\n 'amp-env',\n 'filter-env',\n 'lfo1',\n 'lfo2',\n 'velocity',\n 'key-track',\n 'mod-wheel',\n 'random',\n 'breath',\n 'aftertouch',\n 'expression-cc',\n 'pitch-bend',\n] as const;\n\nexport const SYNTH_MOD_DESTINATIONS = [\n 'none',\n 'pitch-cents',\n 'cutoff-cents',\n 'amp-gain',\n 'pan-units',\n 'resonance-q',\n 'vibrato-depth-cents',\n 'filter-env-depth',\n 'lfo1-rate-scale',\n 'excitation-force',\n 'excitation-position',\n 'excitation-brightness',\n 'spectrum-morph',\n] as const;\n\n/** How a device spells a gesture (see {@link ControllerBinding}). */\nexport const CONTROLLER_INPUTS = [\n 'control-change',\n 'channel-pressure',\n 'poly-pressure',\n 'pitch-bend',\n 'velocity',\n] as const;\n\n/** What a gesture means — the expression axis a binding drives. */\nexport const CONTROLLER_AXES = [\n 'none',\n 'excitation',\n 'position',\n 'brightness',\n 'morph',\n 'loudness',\n 'pitch-cents',\n 'vibrato-depth',\n] as const;\n\n/**\n * What a channel does with a note-on while another note on that channel is\n * still held. `'mono-legato'` carries the sounding voice and only moves its\n * pitch — a wind player's slur — and is deliberately out of reach of any MIDI\n * message: CC126 names a monophonic mode but not this one.\n */\nexport const ARTICULATIONS = ['poly', 'mono-retrigger', 'mono-legato'] as const;\n\n/** The three dimensions MPE carries per note ({@link RealtimeEngine.setControllerNoteTracking}). */\nexport const MPE_DIMENSIONS = ['bend', 'pressure', 'timbre'] as const;\n\n/**\n * Which note a value addressed to a whole MIDI channel belongs to when several\n * are sounding on it ({@link RealtimeEngine.setControllerNoteTracking}).\n *\n * MPE poses this question and declines to answer it — how a controller affects\n * the notes when more than one is active on a member channel is left to the\n * device — so this is a choice rather than a rule. A released note is never\n * selected, whatever the rule and however long a pedal keeps it sounding.\n */\nexport const NOTE_TRACKINGS = ['last', 'lowest', 'highest', 'all'] as const;\n\nexport interface SynthEnumTables {\n engineModes: string[];\n waveforms: string[];\n builtinWaveforms: string[];\n filterModels: string[];\n filterOutputs: string[];\n bodyTypes: string[];\n modSources: string[];\n modDestinations: string[];\n controllerInputs: string[];\n controllerAxes: string[];\n articulations: string[];\n mpeDimensions: string[];\n noteTrackings: string[];\n}\n\n/** NativeSynth engine selector ({@link SynthPatch}; `'default'` keeps the base patch's). */\nexport type SynthEngineMode = (typeof SYNTH_ENGINE_MODES)[number];\n\n/**\n * Per-patch loop override for the sample engine (`'default'` keeps what the\n * bank recorded for the sample the zone names).\n *\n * A different set of values from {@link SampleDesc.loopMode}, which is the\n * SoundFont `sampleModes` number describing the recording itself.\n */\nexport type SampleLoopMode = (typeof SAMPLE_LOOP_MODES)[number];\n\n/** Whether a sample follows the played key (`'default'` keeps the base patch's). */\nexport type SampleKeyTrack = (typeof SAMPLE_KEY_TRACKS)[number];\n\n/**\n * What a note-on restarts on a {@link SynthPatch} (`'default'` keeps the base\n * patch's). `'free'` seeds each voice's start phases and random streams from\n * the voice slot and a running note count, so two plays of one note differ;\n * `'note'` seeds them from the note number alone.\n */\nexport type SynthRetrigger = (typeof SYNTH_RETRIGGERS)[number];\n\n/**\n * Loop behaviour recorded for one sample in a {@link SampleBank}.\n *\n * A number is the raw SoundFont `sampleModes` value the C struct carries\n * (`0` no loop, `1` continuous, `3` while the key is held), so SF2-derived data\n * passes through untranslated; the names are the readable spellings of the same\n * three states. There is no `'default'`: a sample's own loop mode is where the\n * default comes from.\n */\nexport type SampleDescLoopMode = 'none' | 'continuous' | 'key-down';\n\n/**\n * Tuning and looping of one sample, in units relative to that sample\n * ({@link SampleBank.addSample}).\n *\n * Every field is optional and the omitted state is meaningful: the empty\n * descriptor is an unlooped sample rooted at middle C and played at the\n * render's own rate.\n */\nexport interface SampleDesc {\n /** MIDI key at which the sample sounds at its recorded pitch. Defaults to 60. */\n rootKey?: number;\n /** Fine tuning applied on top of {@link SampleDesc.rootKey}. */\n fineTuneCents?: number;\n /** Rate the sample was recorded at; omit to play it at the render's rate. */\n sourceRate?: number;\n /** Loop start, as a frame offset inside this sample. */\n loopStart?: number;\n /** Loop end, as a frame offset inside this sample. */\n loopEnd?: number;\n /**\n * The sample's own loop behaviour. A loop that survives clamping empty is\n * dropped, so a malformed loop plays unlooped rather than wrapping over\n * nothing. {@link SynthPatch.sampleLoop} overrides this per patch.\n */\n loopMode?: SampleDescLoopMode | number;\n}\n\n/**\n * One key/velocity rectangle mapped onto a sample ({@link SampleBank.addZone}).\n *\n * Every bound defaults on its own, so narrowing one edge never collapses\n * another: an omitted upper bound is `127`, an omitted `velLo` is `1` (velocity\n * zero is a note-off, not a dynamic), and an omitted `keyLo` is simply the\n * lowest key. `{ keyLo: 48 }` is therefore keys 48-127 at every velocity and\n * `{ velLo: 64 }` its exact mirror, while an empty rectangle is the whole\n * keyboard. The one rectangle this cannot express is the single key `0`.\n */\nexport interface SampleZoneDesc {\n /**\n * Keymap set the zone joins; a {@link SynthPatch} names a set through\n * {@link SynthPatch.sampleSet}. Sets below it are created. Defaults to `0`.\n */\n setIndex?: number;\n /** Sample the zone plays, as returned by {@link SampleBank.addSample}. */\n sampleIndex?: number;\n /** Lowest key of the rectangle. Defaults to `0`. */\n keyLo?: number;\n /** Highest key of the rectangle. Defaults to `127`. */\n keyHi?: number;\n /** Lowest velocity of the rectangle. Defaults to `1`. */\n velLo?: number;\n /** Highest velocity of the rectangle. Defaults to `127`. */\n velHi?: number;\n /** Added to the sample's own fine tuning. */\n tuneCents?: number;\n /** Linear gain; omit for unity. */\n gain?: number;\n /** Pan in the voice mixer's units, `-500` to `500`. */\n panUnits?: number;\n}\n\n/** NativeSynth oscillator waveform (`'default'` keeps the base patch's). */\nexport type SynthOscWaveform = (typeof SYNTH_OSC_WAVEFORMS)[number];\n\n/** NativeSynth filter model — the character core (`'default'` keeps the base patch's). */\nexport type SynthFilterModel = (typeof SYNTH_FILTER_MODELS)[number];\n\n/** NativeSynth filter output (SVF only; `'default'` keeps the base patch's). */\nexport type SynthFilterOutput = (typeof SYNTH_FILTER_OUTPUTS)[number];\n\n/** NativeSynth body/formant resonance voicing (`'default'` keeps the base patch's). */\nexport type SynthBodyType = (typeof SYNTH_BODY_TYPES)[number];\n\n/** {@link SynthPatch} mod-matrix source. */\nexport type SynthModSource = (typeof SYNTH_MOD_SOURCES)[number];\n\n/** {@link SynthPatch} mod-matrix destination. */\nexport type SynthModDestination = (typeof SYNTH_MOD_DESTINATIONS)[number];\n\n/** Input side of a {@link ControllerBinding}: how the device spells the gesture. */\nexport type ControllerInput = (typeof CONTROLLER_INPUTS)[number];\n\n/** Output side of a {@link ControllerBinding}: which expression axis it means. */\nexport type ControllerAxis = (typeof CONTROLLER_AXES)[number];\n\n/** Per-channel note-overlap rule ({@link RealtimeEngine.setArticulation}). */\nexport type Articulation = (typeof ARTICULATIONS)[number];\n\n/** One per-note MPE dimension ({@link MPE_DIMENSIONS}). */\nexport type MpeDimension = (typeof MPE_DIMENSIONS)[number];\n\n/** One note-attribution rule ({@link NOTE_TRACKINGS}). */\nexport type NoteTracking = (typeof NOTE_TRACKINGS)[number];\n\n/**\n * One device gesture bound to one expression axis\n * ({@link RealtimeEngine.bindController}).\n *\n * Binding the same input twice with different axes is how a single gesture\n * reaches two of them, which is what a breath controller driving both\n * excitation and loudness needs. `input` and `axis` are required and are the\n * canonical names (or their C ordinals); an unknown name throws rather than\n * resolving to the first member.\n *\n * @example\n * ```ts\n * engine.bindController(0, { input: 'control-change', index: 2, axis: 'excitation' });\n * ```\n */\nexport interface ControllerBinding {\n /** How the device spells the gesture. */\n input: ControllerInput | number;\n /**\n * CC number 0-127 for `'control-change'`. Every other input is identified by\n * its message status alone and ignores this. Default `0`.\n */\n index?: number;\n /**\n * Which expression axis the gesture means. `'none'` is refused: a binding\n * that means nothing is a caller mistake, not an empty slot.\n */\n axis: ControllerAxis | number;\n /**\n * Axis value at zero deflection, in the axis's own unit — normalized `[0,1]`\n * for the excitation axes and loudness, cents for pitch and vibrato depth.\n * Default `0`.\n */\n lo?: number;\n /** Axis value at full deflection; `lo > hi` inverts the gesture. Default `1`. */\n hi?: number;\n /**\n * Exponent applied to the normalized input before the range maps it. Default\n * `1` (linear) and deliberately so: a wind controller has already applied the\n * curve its player chose, and a second one on this side bends a gesture that\n * was already shaped. Must be finite and positive.\n */\n curve?: number;\n}\n\n/** One {@link SynthPatch} mod-matrix routing (name or C ordinal per field). */\nexport interface SynthModRouting {\n /**\n * Mod-matrix source. `'none'` is refused: a routing driven by nothing is a\n * caller mistake, not an empty slot.\n */\n source: SynthModSource | number;\n /**\n * Mod-matrix destination. `'none'` is refused, for the same reason as\n * `source`.\n */\n destination: SynthModDestination | number;\n /**\n * Destination units at full source deflection, summed onto whatever the\n * patch or a CC already set and then handled per destination:\n *\n * - `pan-units`: SF2 pan units, clamped to `[-500, 500]` — `1` moves the\n * image by about 0.2% of a side.\n * - `amp-gain` / `filter-env-depth`: multiplicative. Each routing's amount\n * composes onto a running multiplier that clamps to `[0, 4]`.\n * `filter-env-depth` has nothing to scale while the patch's\n * `envToCutoffCents` is `0` — the filter envelope contributes no cents for\n * it to multiply.\n * - `resonance-q`: added to the patch's own Q, then floored at a fixed\n * `0.5` (not at that patch's own Q).\n * - `lfo1-rate-scale`: multiplicative, clamped to `[1/16, 16]`. Audible only\n * once something else already reads LFO1's output — vibrato depth, the\n * filter's LFO amount, tremolo — since it retunes LFO1 rather than\n * sounding on its own; the bare patch's built-in mod-wheel vibrato is the\n * usual path.\n * - The three `excitation-*` destinations and `spectrum-morph`: an offset in\n * the engine's own normalized `[0, 1]` axis units, the same scale the\n * live-control CCs drive, clamped to `[-1, 1]`. Reach is per engine and not\n * uniform across the three: `excitation-force` reaches pipe organ, bowed\n * string, reed, brass, flute and free reed; `excitation-position` reaches\n * bowed string only; `excitation-brightness` reaches pipe organ, reed,\n * brass, flute, free reed and vocal. An engine outside a destination's list\n * ignores it — its exciter is finished before the second sample renders, or\n * it has none. `spectrum-morph` travels between the two spectral tables an\n * additive patch carries; a patch needs an explicit `drawbars_b` distinct\n * from `drawbars` to have a second table to travel to, and no catalog\n * preset ships one, so the destination is currently unreachable from a\n * preset name alone.\n *\n * Percussion reaches none of the above: a drum channel's voice runs the\n * per-note kit patch instead of this one, so the whole mod matrix is\n * discarded before the voice starts.\n */\n depth: number;\n}\n\n/**\n * Versioned NativeSynth patch for {@link Project.bounceWithSynthInstrument}\n * and {@link RealtimeEngine.setSynthInstrument}.\n *\n * The patch starts from a BASE — the named `preset` (see\n * {@link synthPresetNames}; a `\"va:\"` routing prefix is accepted) or, when\n * `preset` is omitted, the default subtractive patch. Omitting a numeric field\n * keeps the base value; supplying one overrides it (clamped to its audible\n * range), including an explicit `0` such as `stereoSpread: 0`. The enum fields\n * reserve `'default'` as keep. A `modRoutings` array REPLACES the base mod\n * matrix, and an empty array clears it, while omitting the key keeps it.\n *\n * Mode-specific deep parameters (FM operator stacks, modal mode tables,\n * drawbar registrations, kit pieces, piano strings) travel inside the named\n * presets; the patch exposes the wrapper sections most engines share. Two\n * exceptions: `waveform` is read by the subtractive engine only, and on a\n * percussion channel the whole section below is discarded in favor of the\n * per-note drum-kit patch — only `gain`, `busDrive` and `polyphony` still act.\n */\nexport interface SynthPatch {\n /**\n * Optional binding convenience for JS realtime/offline helpers. It is not\n * part of the NativeSynth patch itself; Python uses explicit\n * `(destination_id, patch)` bindings instead. Defaults to `0`.\n */\n destinationId?: number;\n /** Resolve MIDI channels from incoming GM bank/program changes; defaults to false. */\n useGmPrograms?: boolean;\n /** Base preset name (see {@link synthPresetNames}); omit for the init patch. */\n preset?: string;\n engineMode?: SynthEngineMode | number;\n /** Oscillator waveform. Read by the subtractive engine only; every other engine ignores it. */\n waveform?: SynthOscWaveform | number;\n /** Detuned-stack width [1, 7]. */\n unison?: number;\n detuneCents?: number;\n /** Per-voice slow pitch drift depth (cents). */\n driftCents?: number;\n /** Pre-filter drive [0, 1]. */\n drive?: number;\n filterModel?: SynthFilterModel | number;\n filterOutput?: SynthFilterOutput | number;\n cutoffHz?: number;\n /**\n * Series 12 dB/oct highpass after the main filter, in Hz; 0 disables the\n * stage. The other end of a band the lowpass alone cannot make. It runs at\n * Butterworth Q -- `resonanceQ` belongs to the main filter.\n */\n hpCutoffHz?: number;\n /**\n * Rate the voice's output is held at, in Hz; 0 disables the stage. The\n * voice's own converter, ahead of its amplitude envelope: the aliased images\n * it folds down are as much of a sound as its samples are. Per voice, so a\n * patch layering several voices can convert some and leave others alone.\n *\n * Percussion never reads this: a drum channel's voice runs the per-note kit\n * patch instead of this one, so the field is discarded before the voice\n * starts.\n */\n sampleHoldHz?: number;\n /**\n * Word length the held value is quantized to, in bits; 0 disables the\n * quantizer. Fractional values are meaningful — a converter's effective\n * resolution is rarely a whole number of bits.\n */\n bitDepth?: number;\n resonanceQ?: number;\n /** Cutoff keyboard tracking [0, 1]. */\n keyTrack?: number;\n /**\n * Filter envelope's cutoff depth, in cents at full envelope; 0 leaves the\n * envelope's cutoff contribution off. The cutoff is multiplied by\n * 2^(envelope × envToCutoffCents / 1200), so the response moves by exactly\n * that interval wherever the corner sits well below Nyquist; near the top the\n * `svf` moves slightly less and the ladders slightly more. `cutoffHz` is the\n * −3 dB corner only for `svf` at `resonanceQ` 0.707: with resonance the `svf`\n * corner sits above it, and the ladder and Sallen-Key models put their\n * resonant peak on it with the −3 dB point one to three octaves lower, so\n * measure a depth as a ratio of corners rather than against `cutoffHz`.\n */\n envToCutoffCents?: number;\n /**\n * Velocity's cutoff depth, in cents. The rendered term is\n * `velToCutoffCents * (velocity / 127 - 1)`, so velocity 127 is the anchor\n * where it is exactly zero: a positive value darkens softer notes, a\n * negative value brightens them, and both effects grow the further the\n * velocity sits below 127.\n */\n velToCutoffCents?: number;\n // --- pitch offset ---\n /**\n * Constant transposition of the voice's own pitch, in cents, clamped to\n * [-4800, 4800]; 0 leaves the pitch alone. Applied on top of the note, so it\n * shifts a whole patch without rewriting the part — a detuned layer, a sample\n * set mapped a semitone off, an instrument pitched to a reference other than\n * A440. Carried in the per-sample pitch factor every engine's render already\n * takes, so it applies the same amount on all of them — except percussion,\n * whose per-note kit patch replaces this whole section and never reads it.\n *\n * Also automatable under this same name through\n * {@link RealtimeEngine.resolveInstrumentAutomationId}; it is one of the names\n * that reaches a voice that is already sounding, rather than waiting for the\n * next note.\n */\n pitchOffsetCents?: number;\n ampAttackMs?: number;\n ampDecayMs?: number;\n ampSustain?: number;\n ampReleaseMs?: number;\n filterAttackMs?: number;\n filterDecayMs?: number;\n filterSustain?: number;\n filterReleaseMs?: number;\n lfoRateHz?: number;\n lfoToPitchCents?: number;\n lfo2RateHz?: number;\n glideMs?: number;\n body?: SynthBodyType | number;\n /** Body resonance mix [0, 1]. */\n bodyMix?: number;\n /** Seeded per-voice pan scatter [0, 1]. */\n stereoSpread?: number;\n /**\n * Seed source for each voice's start state. `'note'` derives oscillator start\n * phases, unison jitter, drift and every engine's noise stream from the note\n * number, so the same note played again after its tail has ended renders the\n * same samples; `'free'` (the built-in patches' choice) varies them per note.\n * State outside the voice is reset by neither: controllers, the bus DC\n * blocker, a piano's shared soundboard, a plucked string's sympathetic halo,\n * an organ's wind chest and effect tails. The `'drum-kit'` preset's per-note\n * pieces keep their own mode.\n */\n retrigger?: SynthRetrigger | number;\n /** Mod matrix (at most 8 routings; REPLACES the base matrix when non-empty). */\n modRoutings?: SynthModRouting[];\n /** Master output gain (linear). */\n gain?: number;\n /** Max simultaneous voices [1, 64]. */\n polyphony?: number;\n /** Gain-neutral bus saturation [0, 1]. */\n busDrive?: number;\n /**\n * Bank the sample engine reads its PCM from. Binding convenience for the JS\n * offline helpers rather than part of the patch itself, like `destinationId`:\n * it is resolved to a native handle before the patch crosses into WASM.\n * A `'sample'` patch bound without a bank renders silence.\n */\n sampleBank?: SampleBank;\n /**\n * Keymap set in the bound bank (negative selects none). Read only by a\n * `'sample'` patch, which is what lets set `0` stay addressable without a\n * \"keep the base value\" sentinel of its own.\n */\n sampleSet?: number;\n /** Linear gain on the sample. */\n sampleLevel?: number;\n sampleLoop?: SampleLoopMode | number;\n /** Attack skip, as a fraction of the mapped region. */\n sampleStartOffset?: number;\n sampleKeyTrack?: SampleKeyTrack | number;\n}\n","import type {\n BuiltinSynthBinding,\n Sf2InstrumentConfig,\n Sf2ProgramStatus,\n SynthPatch,\n} from './instrument_types';\nimport {\n assertProjectMidiEvents,\n normalizeSynthInstrument,\n projectAutomationPointValue,\n projectAutomationTargetKindValue,\n projectLoopModeValue,\n projectMidi1Event,\n projectModule,\n projectTrackKindValue,\n projectWarpModeValue,\n type WasmProject,\n} from './project_internal';\nimport type {\n ExternalSeparatedStemImportRequest,\n ExternalSeparatedStemImportResult,\n MidiCcLearnOptions,\n ProjectAssistSidecar,\n ProjectAssistSidecarInput,\n ProjectAutomationLaneDesc,\n ProjectAutomationPoint,\n ProjectAutomationTargetKind,\n ProjectBounceOptions,\n ProjectChordSymbol,\n ProjectClip,\n ProjectClipCompSegment,\n ProjectClipDesc,\n ProjectClipFade,\n ProjectClipTake,\n ProjectCompileResult,\n ProjectDeserializeResult,\n ProjectKeySegment,\n ProjectLoopMode,\n ProjectLoopRecordingDesc,\n ProjectLoopRecordingResult,\n ProjectMarker,\n ProjectMidiCcBinding,\n ProjectMidiClipResult,\n ProjectMidiEvent,\n ProjectMidiFxBakeRequest,\n ProjectMidiFxBakeResult,\n ProjectMidiFxPreviewRequest,\n ProjectMidiRouteConfig,\n ProjectMidiRouteResult,\n ProjectNotePairValidation,\n ProjectSource,\n ProjectTempoCandidate,\n ProjectTempoOptions,\n ProjectTempoSegment,\n ProjectTimeSignatureSegment,\n ProjectTrack,\n ProjectTrackDesc,\n ProjectTrackKind,\n ProjectTranscribeRequest,\n ProjectWarpMapDesc,\n ProjectWarpMode,\n} from './project_types';\nimport {\n assertBoundedInteger,\n assertNibble,\n assertSampleRate,\n assertSamples,\n assertU7,\n} from './validation';\n\n/**\n * Folds the positional and request call forms of `bakeMidiFx` into one shape,\n * so defaults, validation and errors cannot diverge between them.\n */\nfunction normalizeMidiFxBakeRequest(\n clipIdOrRequest: number | ProjectMidiFxBakeRequest,\n configJson?: string,\n): Required<ProjectMidiFxBakeRequest> {\n if (typeof clipIdOrRequest === 'number') {\n return {\n clipId: clipIdOrRequest,\n configJson: configJson ?? '',\n withSourceIndex: false,\n };\n }\n return {\n clipId: clipIdOrRequest.clipId,\n configJson: clipIdOrRequest.configJson,\n withSourceIndex: clipIdOrRequest.withSourceIndex ?? false,\n };\n}\n\nfunction validateAssistSidecarUint32(value: unknown, field: string): number {\n if (\n typeof value !== 'number' ||\n !Number.isSafeInteger(value) ||\n value < 0 ||\n value > 0xffff_ffff\n ) {\n throw new RangeError(`Project.setAssistSidecar: ${field} must be a uint32`);\n }\n return value;\n}\n\nfunction validateAssistSidecarPpq(value: unknown, field: string): number {\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {\n throw new RangeError(\n `Project.setAssistSidecar: ${field} must be a finite, non-negative number`,\n );\n }\n return value;\n}\n\nfunction validateAssistSidecarPayload(value: unknown): Uint8Array {\n if (!(value instanceof Uint8Array)) {\n throw new TypeError('Project.setAssistSidecar: payload must be a Uint8Array');\n }\n return value;\n}\n\nfunction validateAssistSidecarModuleId(value: unknown): string {\n if (typeof value !== 'string' || value.length === 0) {\n throw new TypeError('Project.setAssistSidecar: moduleId must be a non-empty string');\n }\n return value;\n}\n\nconst MIDI2_U16_MAX = 0xffff;\nconst MIDI2_U32_MAX = 0xffffffff;\n\n// UMP MIDI-2.0 channel-voice packet (message type 0x4). Canonical layout is\n// sonare::midi::make_midi2_* (C-ABI sonare_midi2_*); the golden vectors in\n// midi2-ump.test.ts lock this copy against it.\nfunction midi2Event(\n fnName: string,\n ppq: number,\n group: number,\n opcode: number,\n channel: number,\n byte2: number,\n byte3: number,\n word1: number,\n): ProjectMidiEvent {\n if (!Number.isFinite(ppq) || ppq < 0) {\n throw new RangeError(`${fnName}: ppq must be a non-negative finite number`);\n }\n const g = assertNibble(fnName, group, 'group');\n const ch = assertNibble(fnName, channel, 'channel');\n const word0 =\n ((0x4 << 28) | (g << 24) | (opcode << 20) | (ch << 16) | (byte2 << 8) | byte3) >>> 0;\n return { ppq, data0: word0, data1: word1 >>> 0 };\n}\n\nfunction midi2U32(fnName: string, value: number, argName: string): number {\n assertBoundedInteger(fnName, value, argName, 0, MIDI2_U32_MAX);\n return value;\n}\n\nfunction midi2U16(fnName: string, value: number, argName: string): number {\n assertBoundedInteger(fnName, value, argName, 0, MIDI2_U16_MAX);\n return value;\n}\n\nfunction midi2I32(fnName: string, value: number, argName: string): number {\n assertBoundedInteger(fnName, value, argName, -0x80000000, 0x7fffffff);\n return value;\n}\n\nfunction midi2Byte(fnName: string, value: number, argName: string): number {\n assertBoundedInteger(fnName, value, argName, 0, 0xff);\n return value;\n}\n\n/**\n * Headless DAW project (control-thread-only arrangement model).\n *\n * Wraps the embind `Project` class over the C-ABI keystone\n * `sonare_c_project.{h,cpp}`. Construct an empty project with `new Project()`,\n * or deserialize one with {@link Project.fromJson}; serialize back with\n * {@link toJson}; compile to a renderable timeline with {@link compile}; render\n * offline to interleaved float audio with {@link bounce}. The edit and MIDI\n * methods mirror the Node/Python project bindings.\n *\n * Call {@link delete} (or use a `try/finally`) to release the underlying WASM\n * object — the embind handle is not garbage-collected automatically.\n *\n * @example\n * ```typescript\n * const project = new Project();\n * try {\n * project.setSampleRate(48000);\n * const json = project.toJson();\n * const restored = Project.fromJson(json);\n * restored.delete();\n * } finally {\n * project.delete();\n * }\n * ```\n */\nexport class Project {\n private native: WasmProject;\n private released = false;\n\n constructor() {\n this.native = new (projectModule().Project)();\n }\n\n /** Create a new empty project. */\n static create(): Project {\n return new Project();\n }\n\n /** Pack a MIDI 1.0 note-on event accepted by {@link setMidiEvents}. */\n static midiNoteOn(\n ppq: number,\n group: number,\n channel: number,\n note: number,\n velocity: number,\n ): ProjectMidiEvent {\n return projectMidi1Event('Project.midiNoteOn', ppq, group, 0x9, channel, note, velocity);\n }\n\n /** Pack a MIDI 1.0 note-off event accepted by {@link setMidiEvents}. */\n static midiNoteOff(\n ppq: number,\n group: number,\n channel: number,\n note: number,\n velocity = 0,\n ): ProjectMidiEvent {\n return projectMidi1Event('Project.midiNoteOff', ppq, group, 0x8, channel, note, velocity);\n }\n\n /** Pack a MIDI 1.0 control-change event. */\n static midiCc(\n ppq: number,\n group: number,\n channel: number,\n controller: number,\n value: number,\n ): ProjectMidiEvent {\n return projectMidi1Event('Project.midiCc', ppq, group, 0xb, channel, controller, value);\n }\n\n /** Pack a MIDI 1.0 poly-pressure event. */\n static midiPolyPressure(\n ppq: number,\n group: number,\n channel: number,\n note: number,\n pressure: number,\n ): ProjectMidiEvent {\n return projectMidi1Event('Project.midiPolyPressure', ppq, group, 0xa, channel, note, pressure);\n }\n\n /** Pack a MIDI 1.0 program-change event. */\n static midiProgram(\n ppq: number,\n group: number,\n channel: number,\n program: number,\n ): ProjectMidiEvent {\n return projectMidi1Event('Project.midiProgram', ppq, group, 0xc, channel, program, 0);\n }\n\n /**\n * Pack a MIDI 2.0 note-on event accepted by {@link setMidiEvents}.\n * `velocity16` is the full 16-bit velocity (0 is a sounding note-on);\n * `attributeType` 0 is none, 3 is pitch 7.9.\n */\n static midi2NoteOn(\n ppq: number,\n group: number,\n channel: number,\n note: number,\n velocity16: number,\n attributeType = 0,\n attributeData = 0,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2NoteOn';\n const n = assertU7(fn, note, 'note');\n const vel = midi2U16(fn, velocity16, 'velocity16');\n const type = midi2Byte(fn, attributeType, 'attributeType');\n const data = midi2U16(fn, attributeData, 'attributeData');\n return midi2Event(fn, ppq, group, 0x9, channel, n, type, ((vel << 16) | data) >>> 0);\n }\n\n /** Pack a MIDI 2.0 note-off event (`velocity16` is the full 16-bit release velocity). */\n static midi2NoteOff(\n ppq: number,\n group: number,\n channel: number,\n note: number,\n velocity16 = 0,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2NoteOff';\n const n = assertU7(fn, note, 'note');\n const vel = midi2U16(fn, velocity16, 'velocity16');\n return midi2Event(fn, ppq, group, 0x8, channel, n, 0, (vel << 16) >>> 0);\n }\n\n /** Pack a MIDI 2.0 control-change event (`value32` is the full 32-bit value). */\n static midi2Cc(\n ppq: number,\n group: number,\n channel: number,\n controller: number,\n value32: number,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2Cc';\n const c = assertU7(fn, controller, 'controller');\n return midi2Event(fn, ppq, group, 0xb, channel, c, 0, midi2U32(fn, value32, 'value32'));\n }\n\n /** Pack a MIDI 2.0 poly-pressure event (`pressure32` is the full 32-bit pressure). */\n static midi2PolyPressure(\n ppq: number,\n group: number,\n channel: number,\n note: number,\n pressure32: number,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2PolyPressure';\n const n = assertU7(fn, note, 'note');\n return midi2Event(fn, ppq, group, 0xa, channel, n, 0, midi2U32(fn, pressure32, 'pressure32'));\n }\n\n /** Pack a MIDI 2.0 channel-pressure event (`pressure32` is the full 32-bit pressure). */\n static midi2ChannelPressure(\n ppq: number,\n group: number,\n channel: number,\n pressure32: number,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2ChannelPressure';\n return midi2Event(fn, ppq, group, 0xd, channel, 0, 0, midi2U32(fn, pressure32, 'pressure32'));\n }\n\n /** Pack a MIDI 2.0 pitch-bend event (`bend32` is unsigned 32-bit, center = 0x80000000). */\n static midi2PitchBend(\n ppq: number,\n group: number,\n channel: number,\n bend32: number,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2PitchBend';\n return midi2Event(fn, ppq, group, 0xe, channel, 0, 0, midi2U32(fn, bend32, 'bend32'));\n }\n\n /**\n * Pack a MIDI 2.0 program-change event. The bank travels in the same message\n * and is applied only when `bankValid` is true.\n */\n static midi2Program(\n ppq: number,\n group: number,\n channel: number,\n program: number,\n bankValid = false,\n bankMsb = 0,\n bankLsb = 0,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2Program';\n const p = assertU7(fn, program, 'program');\n const msb = assertU7(fn, bankMsb, 'bankMsb');\n const lsb = assertU7(fn, bankLsb, 'bankLsb');\n const word1 = ((p << 24) | (msb << 8) | lsb) >>> 0;\n return midi2Event(fn, ppq, group, 0xc, channel, 0, bankValid ? 1 : 0, word1);\n }\n\n /** Pack a MIDI 2.0 registered controller (RPN) event. */\n static midi2RegisteredController(\n ppq: number,\n group: number,\n channel: number,\n bank: number,\n index: number,\n value32: number,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2RegisteredController';\n const b = assertU7(fn, bank, 'bank');\n const i = assertU7(fn, index, 'index');\n return midi2Event(fn, ppq, group, 0x2, channel, b, i, midi2U32(fn, value32, 'value32'));\n }\n\n /** Pack a MIDI 2.0 assignable controller (NRPN) event. */\n static midi2AssignableController(\n ppq: number,\n group: number,\n channel: number,\n bank: number,\n index: number,\n value32: number,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2AssignableController';\n const b = assertU7(fn, bank, 'bank');\n const i = assertU7(fn, index, 'index');\n return midi2Event(fn, ppq, group, 0x3, channel, b, i, midi2U32(fn, value32, 'value32'));\n }\n\n /** Pack a MIDI 2.0 relative registered controller event (`delta32` is a signed change). */\n static midi2RelativeRegisteredController(\n ppq: number,\n group: number,\n channel: number,\n bank: number,\n index: number,\n delta32: number,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2RelativeRegisteredController';\n const b = assertU7(fn, bank, 'bank');\n const i = assertU7(fn, index, 'index');\n return midi2Event(fn, ppq, group, 0x4, channel, b, i, midi2I32(fn, delta32, 'delta32'));\n }\n\n /** Pack a MIDI 2.0 relative assignable controller event (`delta32` is a signed change). */\n static midi2RelativeAssignableController(\n ppq: number,\n group: number,\n channel: number,\n bank: number,\n index: number,\n delta32: number,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2RelativeAssignableController';\n const b = assertU7(fn, bank, 'bank');\n const i = assertU7(fn, index, 'index');\n return midi2Event(fn, ppq, group, 0x5, channel, b, i, midi2I32(fn, delta32, 'delta32'));\n }\n\n /** Pack a MIDI 2.0 registered per-note controller event (`index` is 0..255). */\n static midi2RegisteredPerNoteController(\n ppq: number,\n group: number,\n channel: number,\n note: number,\n index: number,\n value32: number,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2RegisteredPerNoteController';\n const n = assertU7(fn, note, 'note');\n const i = midi2Byte(fn, index, 'index');\n return midi2Event(fn, ppq, group, 0x0, channel, n, i, midi2U32(fn, value32, 'value32'));\n }\n\n /** Pack a MIDI 2.0 assignable per-note controller event (`index` is 0..255). */\n static midi2AssignablePerNoteController(\n ppq: number,\n group: number,\n channel: number,\n note: number,\n index: number,\n value32: number,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2AssignablePerNoteController';\n const n = assertU7(fn, note, 'note');\n const i = midi2Byte(fn, index, 'index');\n return midi2Event(fn, ppq, group, 0x1, channel, n, i, midi2U32(fn, value32, 'value32'));\n }\n\n /** Pack a MIDI 2.0 per-note pitch-bend event (`bend32` is unsigned 32-bit, center = 0x80000000). */\n static midi2PerNotePitchBend(\n ppq: number,\n group: number,\n channel: number,\n note: number,\n bend32: number,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2PerNotePitchBend';\n const n = assertU7(fn, note, 'note');\n return midi2Event(fn, ppq, group, 0x6, channel, n, 0, midi2U32(fn, bend32, 'bend32'));\n }\n\n /**\n * Pack a MIDI 2.0 per-note management event. `detach` sets the D flag\n * (detach per-note controllers from voices already sounding on `note`);\n * `reset` sets the S flag (reset the note's per-note controllers).\n */\n static midi2PerNoteManagement(\n ppq: number,\n group: number,\n channel: number,\n note: number,\n detach = false,\n reset = false,\n ): ProjectMidiEvent {\n const fn = 'Project.midi2PerNoteManagement';\n const n = assertU7(fn, note, 'note');\n const flags = (detach ? 0x02 : 0) | (reset ? 0x01 : 0);\n return midi2Event(fn, ppq, group, 0xf, channel, n, flags, 0);\n }\n\n /** Return the General MIDI instrument name for `program`, or `null` when out of range. */\n static gmInstrumentName(program: number): string | null {\n return projectModule().midiGmInstrumentName(program);\n }\n\n /** Return the General MIDI program number for a canonical instrument name, or `-1`. */\n static gmProgramForName(name: string): number {\n return projectModule().midiGmProgramForName(name);\n }\n\n /** Return the General MIDI family name for `family`, or `null` when out of range. */\n static gmFamilyName(family: number): string | null {\n return projectModule().midiGmFamilyName(family);\n }\n\n /** Return the first General MIDI program number in `family`, or `-1`. */\n static gmFamilyFirstProgram(family: number): number {\n return projectModule().midiGmFamilyFirstProgram(family);\n }\n\n /** Return the GM2 bank/program instrument variation name, or `null` when unavailable. */\n static gm2InstrumentName(bankLsb: number, program: number): string | null {\n return projectModule().midiGm2InstrumentName(bankLsb, program);\n }\n\n /** Return the General MIDI drum name for `note`, or `null` when out of range. */\n static gmDrumName(note: number): string | null {\n return projectModule().midiGmDrumName(note);\n }\n\n /** Return the General MIDI drum note for a canonical drum name, or `-1`. */\n static gmDrumNoteForName(name: string): number {\n return projectModule().midiGmDrumNoteForName(name);\n }\n\n /** Return the GM2 drum-set name for `bankLsb`, or `null` when unavailable. */\n static gm2DrumSetName(bankLsb: number): string | null {\n return projectModule().midiGm2DrumSetName(bankLsb);\n }\n\n /** Return the GM2 drum name for `bankLsb`/`note`, or `null` when unavailable. */\n static gm2DrumName(bankLsb: number, note: number): string | null {\n return projectModule().midiGm2DrumName(bankLsb, note);\n }\n\n /** Return the MIDI CC name for `controller`, or `null` when out of range. */\n static midiCcName(controller: number): string | null {\n return projectModule().midiCcName(controller);\n }\n\n /** Return the MIDI CC number for a canonical controller name, or `-1`. */\n static midiCcIndexForName(name: string): number {\n return projectModule().midiCcIndexForName(name);\n }\n\n /** Return the MIDI 2.0 per-note controller name for `index`, or `null`. */\n static perNoteControllerName(index: number): string | null {\n return projectModule().midiPerNoteControllerName(index);\n }\n\n /** Expand bank-select + program-change into MIDI events accepted by {@link setMidiEvents}. */\n static midiBankProgram(\n ppq: number,\n group: number,\n channel: number,\n bankMsb: number,\n bankLsb: number,\n program: number,\n ): ProjectMidiEvent[] {\n return projectModule().midiBankProgram(ppq, group, channel, bankMsb, bankLsb, program);\n }\n\n /** Route MIDI events through the native MidiRouter filter/remap/thru logic. */\n static midiRouteEvents(\n events: ReadonlyArray<ProjectMidiEvent>,\n config: ProjectMidiRouteConfig = {},\n ): ProjectMidiRouteResult {\n return projectModule().midiRouteEvents(events, config);\n }\n\n /** Run native MIDI learn over an event stream; returns `null` when nothing is learned. */\n static midiCcLearn(\n events: ReadonlyArray<ProjectMidiEvent>,\n paramId: number,\n options: MidiCcLearnOptions = {},\n ): ProjectMidiCcBinding | null {\n return projectModule().midiCcLearn(\n events,\n paramId,\n options.minValue ?? 0,\n options.maxValue ?? 1,\n options.minMovement ?? 0,\n );\n }\n\n /** Convert one CC event to an automation breakpoint using native CcMap. */\n static midiCcToBreakpoint(\n bindings: ReadonlyArray<ProjectMidiCcBinding>,\n event: ProjectMidiEvent,\n ): ProjectAutomationPoint | null {\n return projectModule().midiCcToBreakpoint(bindings, event);\n }\n\n /** Convert one automation value back to a CC UMP event using native CcMap. */\n static midiParamToCc(\n bindings: ReadonlyArray<ProjectMidiCcBinding>,\n paramId: number,\n unitValue: number,\n group: number,\n ppq = 0,\n ): ProjectMidiEvent | null {\n return projectModule().midiParamToCc(bindings, paramId, unitValue, group, ppq);\n }\n\n /** Pack a MIDI 1.0 channel-pressure event. */\n static midiChannelPressure(\n ppq: number,\n group: number,\n channel: number,\n pressure: number,\n ): ProjectMidiEvent {\n return projectMidi1Event('Project.midiChannelPressure', ppq, group, 0xd, channel, pressure, 0);\n }\n\n /** Pack a MIDI 1.0 pitch-bend event (`bend` is unsigned 14-bit, center = 8192). */\n static midiPitchBend(\n ppq: number,\n group: number,\n channel: number,\n bend: number,\n ): ProjectMidiEvent {\n assertBoundedInteger('Project.midiPitchBend', bend, 'bend', 0, 0x3fff);\n return projectMidi1Event(\n 'Project.midiPitchBend',\n ppq,\n group,\n 0xe,\n channel,\n bend & 0x7f,\n bend >> 7,\n );\n }\n\n /**\n * Deserialize project JSON into a new {@link Project}. Throws if the JSON is\n * malformed, surfacing the joined diagnostic messages.\n */\n static fromJson(json: string): Project {\n const project = new Project();\n // Replace the freshly-created empty handle with the deserialized one. If\n // fromJson throws (malformed JSON) the empty handle is released first so no\n // WASM object leaks.\n const restored = (() => {\n try {\n return projectModule().Project.fromJson(json);\n } catch (error) {\n project.native.delete();\n throw error;\n }\n })();\n project.native.delete();\n project.native = restored;\n return project;\n }\n\n /**\n * Deserialize project JSON and return native warning diagnostics emitted on\n * successful loads, such as dangling source references preserved for repair.\n */\n static fromJsonWithDiagnostics(json: string): ProjectDeserializeResult {\n const project = new Project();\n const restored = (() => {\n try {\n return projectModule().Project.fromJsonWithDiagnostics(json);\n } catch (error) {\n project.native.delete();\n throw error;\n }\n })();\n project.native.delete();\n project.native = restored.project;\n return { project, diagnostics: restored.diagnostics };\n }\n\n /** Serialize the project (+ MIDI content) to deterministic JSON. */\n toJson(): string {\n return this.native.toJson();\n }\n\n /**\n * Set the project sample rate in Hz. Must be in `[8000, 384000]`; anything\n * outside that range throws. Applied through the edit history, so it is\n * undoable.\n */\n setSampleRate(sampleRate: number): void {\n this.native.setSampleRate(sampleRate);\n }\n\n /** Add a track and return its allocated stable id. */\n addTrack(desc: ProjectTrackDesc = {}): number {\n return this.native.addTrack({ ...desc, kind: projectTrackKindValue(desc.kind) });\n }\n\n /** Add an audio or MIDI clip and return its allocated clip id. */\n addClip(desc: ProjectClipDesc): number {\n return this.native.addClip(desc);\n }\n\n /** Import host-separated PCM through the normal audio-track/clip path. */\n importExternalStems(\n request: ExternalSeparatedStemImportRequest,\n ): ExternalSeparatedStemImportResult {\n return this.native.importExternalStems({\n ...request,\n stems: request.stems.map((stem) => ({\n ...stem,\n layout: stem.layout === 'mono' ? 1 : stem.layout === 'stereo' ? 2 : stem.layout,\n })),\n });\n }\n\n /** Split captured loop-recording audio into takes and add one clip. */\n addLoopRecordingTakes(desc: ProjectLoopRecordingDesc): ProjectLoopRecordingResult {\n return this.native.addLoopRecordingTakes(desc);\n }\n\n /** Create a MIDI track + clip; returns `{ trackId, clipId }`. */\n addMidiClip(startPpq: number, lengthPpq: number): ProjectMidiClipResult {\n return this.native.addMidiClip(startPpq, lengthPpq);\n }\n\n /** Split a clip at `splitPpq` and return the new clip id. */\n splitClip(clipId: number, splitPpq: number): number {\n return this.native.splitClip(clipId, splitPpq);\n }\n\n /** Trim a clip's start / length in PPQ. */\n trimClip(clipId: number, newStartPpq: number, newLengthPpq: number): void {\n this.native.trimClip(clipId, newStartPpq, newLengthPpq);\n }\n\n /** Move a clip to `newStartPpq` and optionally another track. */\n moveClip(clipId: number, newStartPpq: number, newTrackId = 0): void {\n this.native.moveClip(clipId, newStartPpq, newTrackId);\n }\n\n /** Change a track kind via an undoable edit. */\n setTrackKind(trackId: number, kind: ProjectTrackKind): void {\n this.native.setTrackKind(trackId, projectTrackKindValue(kind));\n }\n\n /** Set a clip's warp reference id (0 clears it). */\n setClipWarpRef(clipId: number, warpRefId: number): void {\n this.native.setClipWarpRef(clipId, warpRefId);\n }\n\n /** Set a clip's warp playback mode. */\n setClipWarpMode(clipId: number, mode: ProjectWarpMode): void {\n this.native.setClipWarpMode(clipId, projectWarpModeValue(mode));\n }\n\n /** Add or replace a first-class warp map referenced by clip warp ids. */\n setWarpMap(map: ProjectWarpMapDesc): void {\n this.native.setWarpMap(map);\n }\n\n /** Remove a first-class warp map by id. */\n removeWarpMap(warpRefId: number): void {\n this.native.removeWarpMap(warpRefId);\n }\n\n /**\n * Route a track's MIDI to host-instrument `destinationId` (0 = default). The\n * compiler stamps every MIDI clip on the track with this id so the engine\n * dispatches its events to the instrument registered for that destination.\n * Routes through an undoable edit command. Builtin, NativeSynth, and SF2\n * instruments retain source-track provenance inside a shared destination\n * voice pool. With only zero-latency instruments bound, live lanes and\n * channel-strip bounces remain aligned. Configure one live lane per source\n * track that needs strip processing.\n */\n setTrackMidiDestination(trackId: number, destinationId: number): void {\n this.native.setTrackMidiDestination(trackId, destinationId);\n }\n\n /**\n * Set a track's linear playback gain (1.0 = unity; >= 0) via an undoable edit.\n *\n * The value reaches the track's audio and MIDI alike, but the stage it lands\n * on follows the track's channel strip. A strip bound by this track alone\n * (including one synthesized for an unbound track) carries the controls on its\n * own fader and panner. A strip several tracks share processes their sum and\n * carries none of them; each track applies its controls upstream instead — on\n * its own clip schedules for audio, on its track lane for MIDI.\n *\n * A MIDI track's gain/pan on a shared strip ride the track lane, which is fed\n * per source track only by an instrument that preserves source-track identity\n * (see {@link setTrackMidiDestination}). An opaque host-callback instrument, or\n * one reporting non-zero latency, renders one buffer per destination and has no\n * per-track stage on a shared strip, so its gain/pan do not reach the bounce\n * there; bind such an instrument to a track with an exclusive strip. Mute and\n * solo are unaffected: a silenced MIDI track schedules no events at all.\n */\n setTrackGain(trackId: number, gain: number): void {\n this.native.setTrackGain(trackId, gain);\n }\n\n /** Set a track's mute flag via an undoable edit (a muted track is silent). */\n setTrackMute(trackId: number, mute: boolean): void {\n this.native.setTrackMute(trackId, mute);\n }\n\n /** Set a track's solo flag via an undoable edit (when any track is soloed, only soloed tracks sound). */\n setTrackSolo(trackId: number, solo: boolean): void {\n this.native.setTrackSolo(trackId, solo);\n }\n\n /**\n * Set a track's stereo balance in [-1, +1] (0 = center) via an undoable edit.\n *\n * See {@link setTrackGain} for which stage a track's controls land on. The pan\n * law that shapes the balance belongs to that stage: the strip's configured law\n * on a channel strip and on the clips of an audio track sharing a strip, and\n * the track lane's law for a MIDI track sharing a strip (the law of whatever\n * strip the host bound to that lane, or a linear balance when none is bound).\n * Every law is normalized so a centered track stays at unity and only the away\n * channel is attenuated, so the difference is a taper, not a level offset.\n */\n setTrackPan(trackId: number, pan: number): void {\n this.native.setTrackPan(trackId, pan);\n }\n\n /** Undo the most recent edit. */\n undo(): void {\n this.native.undo();\n }\n\n /** Redo the most recently undone edit. */\n redo(): void {\n this.native.redo();\n }\n\n /** Clear the undo/redo history without changing the current project state. */\n clearHistory(): void {\n this.native.clearHistory();\n }\n\n /** Cap the undo history depth (clamped to >= 1); evicts oldest entries beyond the cap. */\n setMaxUndoDepth(depth: number): void {\n if (!Number.isInteger(depth) || depth < 1) {\n throw new RangeError('Project.setMaxUndoDepth: depth must be an integer >= 1');\n }\n this.native.setMaxUndoDepth(depth);\n }\n\n /** Set the combined undo/redo history byte cap. Zero disables retention. */\n setMaxHistoryBytes(bytes: number): void {\n if (typeof bytes !== 'number') {\n throw new TypeError('Project.setMaxHistoryBytes: bytes must be a number');\n }\n if (!Number.isFinite(bytes) || !Number.isInteger(bytes) || bytes < 0 || bytes > 0xffff_ffff) {\n throw new RangeError(\n 'Project.setMaxHistoryBytes: bytes must be a finite integer in the uint32 range',\n );\n }\n this.native.setMaxHistoryBytes(bytes);\n }\n\n /**\n * Replace a MIDI clip's entire event list.\n *\n * @remarks\n * Drops the clip's SysEx, which {@link importSmf} and {@link exportSmf} both\n * keep. A clip's SysEx payloads sit beside the event list and are reached by\n * a handle {@link ProjectMidiEvent} does not carry, so replacing the list\n * leaves nothing referring to them: a GS setup block that survives an import\n * and an export byte for byte is gone after one call here. Nothing reads the\n * handles back either, so a caller that must keep the setup edits the\n * exported file rather than the event list.\n */\n setMidiEvents(\n clipId: number,\n events: ReadonlyArray<ProjectMidiEvent | readonly [number, number, number]>,\n ): void {\n assertProjectMidiEvents('Project.setMidiEvents', events);\n this.native.setMidiEvents(clipId, events);\n }\n\n /**\n * Import an in-memory SMF buffer; returns the first added clip id.\n * Malformed or partially truncated tracks are rejected instead of installing\n * a silently shortened clip.\n */\n importSmf(data: Uint8Array): number {\n return this.native.importSmf(data);\n }\n\n /**\n * Export the project's tempo map + MIDI clips to an SMF byte buffer.\n *\n * @remarks\n * The buffer owns a plain `ArrayBuffer`, which is what the `Blob` / `File`\n * constructors accept — so `new Blob([project.exportSmf()])` compiles without\n * a copy through `new Uint8Array(...)` first.\n */\n exportSmf(): Uint8Array<ArrayBuffer> {\n return this.native.exportSmf();\n }\n\n /**\n * Import a MIDI 2.0 Clip File (`SMF2CLIP`); returns the first added clip id.\n * Unlike {@link importSmf}, MIDI 2.0 channel-voice messages (16-bit velocity,\n * 32-bit CC, per-note / registered controllers, bank-valid Program Change)\n * survive without loss.\n */\n importClipFile(data: Uint8Array): number {\n return this.native.importClipFile(data);\n }\n\n /**\n * Export the project's tempo map + MIDI clips to a MIDI 2.0 Clip File\n * (`SMF2CLIP`) byte buffer. MIDI 2.0-only events are written without loss —\n * prefer this over {@link exportSmf} when MIDI 2.0 fidelity matters.\n *\n * @remarks\n * As with {@link exportSmf}, the buffer owns a plain `ArrayBuffer` and goes\n * straight into a `Blob`.\n */\n exportClipFile(): Uint8Array<ArrayBuffer> {\n return this.native.exportClipFile();\n }\n\n /**\n * Set a MIDI clip's channel-0 program / bank at source PPQ 0. `bank` defaults\n * to `-1` (no Bank Select emitted), matching `setProgramOnChannel` and the\n * Node/Python surfaces; pass `>= 0` to emit a Bank Select.\n */\n setProgram(clipId: number, program: number, bank = -1): void {\n this.native.setProgram(clipId, program, bank);\n }\n\n /** Set a MIDI clip's program / bank for one UMP group and channel. */\n setProgramOnChannel(\n clipId: number,\n group: number,\n channel: number,\n program: number,\n bank = -1,\n ): void {\n this.native.setProgramOnChannel(clipId, group, channel, program, bank);\n }\n\n /**\n * Destructively bake a MIDI-FX chain into all stored events. Large clips are\n * drained without truncation; failure leaves the original clip unchanged.\n */\n bakeMidiFx(clipId: number, configJson: string): void;\n /**\n * Request form. Setting `withSourceIndex` also returns per-event provenance,\n * so a selection or an editorial annotation can be carried across the bake.\n */\n bakeMidiFx(request: ProjectMidiFxBakeRequest): ProjectMidiFxBakeResult;\n bakeMidiFx(\n clipIdOrRequest: number | ProjectMidiFxBakeRequest,\n configJson?: string,\n ): ProjectMidiFxBakeResult {\n const request = normalizeMidiFxBakeRequest(clipIdOrRequest, configJson);\n if (!request.withSourceIndex) {\n this.native.bakeMidiFx(request.clipId, request.configJson);\n return {};\n }\n return {\n sourceIndex: this.native.bakeMidiFxWithSourceIndex(request.clipId, request.configJson),\n };\n }\n\n /**\n * Count the events {@link bakeMidiFx} would produce for this clip and\n * configuration, without mutating the project. The transform is\n * deterministic, so the count matches what the bake goes on to produce.\n */\n previewMidiFxCount(request: ProjectMidiFxPreviewRequest): number {\n return this.native.previewMidiFxCount(request.clipId, request.configJson);\n }\n\n /** Backward alias for {@link bakeMidiFx}. */\n setMidiFx(clipId: number, configJson: string): void {\n this.bakeMidiFx(clipId, configJson);\n }\n\n /**\n * Pre-flight check for hanging / unmatched notes in a MIDI clip: reports\n * whether every note-on in the exported half-open playback window has a\n * matching note-off (FIFO per group+channel+note). Useful before bouncing to\n * catch a stuck note. Throws if `clipId` is unknown or not a MIDI clip.\n */\n validateMidiNotes(clipId: number): ProjectNotePairValidation {\n return this.native.validateMidiNotes(clipId);\n }\n\n /**\n * Transcribe mono audio straight into a MIDI clip's event list, **replacing**\n * whatever it held — exactly as {@link setMidiEvents} does.\n *\n * The PPQ grid is this project's own tempo map, which is why there is no\n * `tempoBpm` field: a project whose tempo was installed by {@link autoTempo}\n * transcribes onto that map rather than onto a second, separately detected\n * tempo. Use the standalone `transcribe` when you want events without a\n * project.\n *\n * Quantizing, tempo detection and key/chord annotation are not done here —\n * see `transcribe` for what each belongs to.\n *\n * @returns the number of notes written (half the events)\n * @throws {RangeError} on empty `samples`, a non-finite sample, or a\n * `sampleRate` outside `[8000, 384000]`\n * @throws {SonareError} `InvalidParameter` when `clipId` is unknown or not a\n * MIDI clip, or on an option outside its domain; `NotSupported` when the\n * library was built without the pitch editor\n */\n transcribeToClip(request: ProjectTranscribeRequest): number {\n assertSamples('Project.transcribeToClip', request.samples, true);\n assertSampleRate('Project.transcribeToClip', request.sampleRate);\n return this.native.transcribeToClip(\n request.clipId,\n request.samples,\n request.sampleRate,\n request,\n );\n }\n\n /** Return ranked tempo-octave and detected-meter candidates without editing. */\n analyzeTempo(\n audio: Float32Array,\n sampleRate: number,\n options?: ProjectTempoOptions,\n ): ProjectTempoCandidate[] {\n return this.native.analyzeTempo(audio, sampleRate, options);\n }\n\n /**\n * Detect and install a ranked tempo candidate; optionally apply detected meter.\n *\n * @remarks\n * `candidateIndex` indexes the ranking {@link analyzeTempo} produced, so pair\n * the two on the same `options`. Read the installed map back with\n * {@link tempoSegmentCount} and {@link tempoSegmentByIndex}.\n */\n autoTempo(\n audio: Float32Array,\n sampleRate: number,\n candidateIndex = 0,\n applyTimeSignatures = false,\n options?: ProjectTempoOptions,\n ): number {\n return this.native.autoTempo(audio, sampleRate, candidateIndex, applyTimeSignatures, options);\n }\n\n /** Snap to a bar (`division=0`), beat (`1`), or beat subdivision (`2+`). */\n snapToGrid(ppq: number, strength = 1.0, division = 1): number {\n return this.native.snapToGrid(ppq, strength, division);\n }\n\n /** Compile the project into a renderable timeline, surfacing diagnostics. */\n compile(): ProjectCompileResult {\n return this.native.compile();\n }\n\n /**\n * Compile + render the project offline to interleaved float audio. MIDI\n * tracks render silently here (no instrument is bound) — use\n * {@link bounceWithBuiltinInstrument} to make MIDI audible.\n *\n * When `totalFrames` is omitted (or `<= 0`) the render length is auto-derived\n * from the arrangement, so a project with content renders without computing a\n * frame count; an empty project yields an empty buffer.\n *\n * @example\n * ```typescript\n * const audio = project.bounce({ numChannels: 2 });\n * ```\n */\n bounce(options: ProjectBounceOptions = {}): Float32Array {\n return this.native.bounce(options);\n }\n\n /**\n * Compile + render the project offline, routing MIDI tracks through the\n * built-in oscillator synth so a MIDI-only arrangement bounces to audible\n * audio. Pass a {@link BuiltinSynthBinding} (or an array of them) to choose\n * the patch and MIDI destination; omit it (or pass `{}`) for one\n * default-destination sine patch. Because the parameter defaults to `{}`,\n * omission and explicit `undefined` both create that one default binding.\n * Use an explicitly empty array `[]` (or runtime `null`) for zero bindings,\n * so MIDI tracks render silently.\n *\n * Like {@link bounce}, omitting `totalFrames` auto-derives the render length\n * from the arrangement plus the synth's release tail.\n *\n * @example\n * ```typescript\n * // MIDI-only project -> non-silent stereo audio.\n * const audio = project.bounceWithBuiltinInstrument(\n * { waveform: 'saw' },\n * { numChannels: 2 },\n * );\n * ```\n */\n bounceWithBuiltinInstrument(\n instrument: BuiltinSynthBinding | ReadonlyArray<BuiltinSynthBinding> = {},\n options: ProjectBounceOptions = {},\n ): Float32Array {\n return this.native.bounceWithBuiltinInstrument(instrument, options);\n }\n\n /**\n * Compile + render the project offline, routing MIDI tracks through the\n * patch-driven NativeSynth — the full synthesizer (every\n * {@link SynthEngineMode} engine plus the realism layer; the modes are\n * enumerated by {@link SYNTH_ENGINE_MODES}). Pass a {@link SynthPatch}, a preset-name\n * string (`'saw-lead'` / `'va:saw-lead'`; see {@link synthPresetNames}), or\n * an array of either; each object entry may carry `destinationId` (default\n * 0) and `useGmPrograms` (default `false`) binding conveniences, neither of\n * which is part of the NativeSynth patch itself. When enabled, MIDI program\n * changes select the corresponding General MIDI voice while the patch remains\n * the fallback.\n * Because the parameter defaults to `{}`, omission and explicit `undefined`\n * both create one default binding. Use an explicitly empty array `[]` (or\n * runtime `null`) for zero bindings. Unknown preset names throw.\n * Deterministic for a fixed project + options + patch.\n *\n * An `engineMode: 'sample'` patch reads its PCM from the {@link SampleBank}\n * passed as `sampleBank`; the bank must still be alive when the bounce runs,\n * and one bound without a bank renders silence.\n */\n bounceWithSynthInstrument(\n instrument: SynthPatch | string | ReadonlyArray<SynthPatch | string> = {},\n options: ProjectBounceOptions = {},\n ): Float32Array {\n const normalized = Array.isArray(instrument)\n ? instrument.map((entry) => normalizeSynthInstrument(entry))\n : normalizeSynthInstrument(instrument);\n return this.native.bounceWithSynthInstrument(normalized, options);\n }\n\n /**\n * Load (parse) SoundFont 2 bytes into the project: presets / instruments /\n * sample headers plus the sample PCM decoded to a float pool. The host\n * fetches the `.sf2` and passes the raw bytes; they are copied into linear\n * memory for the call and not referenced afterwards. Replaces any previously\n * loaded SoundFont; throws on malformed input (the previous SoundFont is\n * kept).\n */\n loadSoundFont(data: Uint8Array): void {\n this.native.loadSoundFont(data);\n }\n\n /** Release the project's loaded SoundFont (no-op when none is loaded). */\n clearSoundFont(): void {\n this.native.clearSoundFont();\n }\n\n /** Number of presets in the loaded SoundFont (0 when none is loaded). */\n soundFontPresetCount(): number {\n return this.native.soundFontPresetCount();\n }\n\n /**\n * Enumerate every (channel, bank, program) combination the arrangement plays\n * a note through, in first-use order, reporting whether each resolves in the\n * loaded SoundFont (`'sf2'`, GS variation/drum fallbacks included) or would\n * fall back to the built-in synth (`'synth'`). Without a loaded SoundFont\n * every entry is a synth fallback.\n */\n soundFontManifest(): Sf2ProgramStatus[] {\n return this.native.soundFontManifest();\n }\n\n /**\n * Like {@link bounceWithBuiltinInstrument}, but each bound destination\n * renders through a GS-compatible SoundFont player fed by the project's\n * loaded SoundFont ({@link loadSoundFont}): 16 MIDI channels per player,\n * channel 10 drums via bank 128, GS NRPN part edits and GS/GM SysEx resets\n * honored. Programs the SoundFont does not cover — including bouncing with\n * no SoundFont loaded at all — play through the built-in synthesizer GM\n * fallback bank (the data-free floor; see {@link soundFontManifest} for the\n * per-program backend). Because the parameter defaults to `{}`, omission and\n * explicit `undefined` both create one default binding. Use an explicitly\n * empty array `[]` (or runtime `null`) for zero bindings, so MIDI tracks\n * render silently.\n */\n bounceWithSf2Instrument(\n instrument: Sf2InstrumentConfig | ReadonlyArray<Sf2InstrumentConfig> = {},\n options: ProjectBounceOptions = {},\n ): Float32Array {\n return this.native.bounceWithSf2Instrument(instrument, options);\n }\n\n /** Remove a clip (undoable). */\n removeClip(clipId: number): void {\n this.native.removeClip(clipId);\n }\n\n /** Set a clip's linear playback gain (>= 0; undoable). */\n setClipGain(clipId: number, gain: number): void {\n this.native.setClipGain(clipId, gain);\n }\n\n /** Set a clip's fade-in / fade-out regions (undoable). */\n setClipFade(clipId: number, fadeIn: ProjectClipFade = {}, fadeOut: ProjectClipFade = {}): void {\n this.native.setClipFade(clipId, fadeIn, fadeOut);\n }\n\n /** Audio source ids that need decoded PCM after deserialization. */\n unresolvedAudioSourceIds(): number[] {\n return this.native.unresolvedAudioSourceIds();\n }\n\n /** Register decoded interleaved PCM for an existing audio source (undoable). */\n setSourceAudio(\n sourceId: number,\n audio: Float32Array,\n channels: number,\n sampleRate: number,\n ): void {\n this.native.setSourceAudio(sourceId, audio, channels, sampleRate);\n }\n\n /** Replace an audio source's metadata strings as one undoable edit. */\n setAudioSourceMetadata(sourceId: number, contentHash: string, externalStemRole: string): void {\n this.native.setAudioSourceMetadata(sourceId, contentHash, externalStemRole);\n }\n\n /** Replace a clip's take list and active take id (undoable). */\n setClipTakes(clipId: number, takes: ReadonlyArray<ProjectClipTake>, activeTakeId = 0): void {\n this.native.setClipTakes(clipId, takes, activeTakeId);\n }\n\n /** Replace a clip's comp segments (undoable). */\n setClipCompSegments(clipId: number, segments: ReadonlyArray<ProjectClipCompSegment>): void {\n this.native.setClipCompSegments(clipId, segments);\n }\n\n /**\n * Set a clip's loop mode + loop length in PPQ (undoable). `loopCrossfadePpq`\n * is an optional equal-power crossfade at the loop seam (PPQ, finite and >= 0;\n * 0 = hard loop); the engine clamps it to the clip's pre-roll and half the loop.\n */\n setClipLoop(\n clipId: number,\n loopMode: ProjectLoopMode,\n loopLengthPpq = 0,\n loopCrossfadePpq = 0,\n ): void {\n this.native.setClipLoop(\n clipId,\n projectLoopModeValue(loopMode),\n loopLengthPpq,\n loopCrossfadePpq,\n );\n }\n\n /** Rebind a clip to a different (already-registered) source (undoable). */\n setClipSource(clipId: number, sourceId: number): void {\n this.native.setClipSource(clipId, sourceId);\n }\n\n /** Duplicate a clip at `newStartPpq` (same track); returns the new clip id. */\n duplicateClip(clipId: number, newStartPpq: number): number {\n return this.native.duplicateClip(clipId, newStartPpq);\n }\n\n /** Remove a track and its clips (undoable). */\n removeTrack(trackId: number): void {\n this.native.removeTrack(trackId);\n }\n\n /** Rename a track (undoable). */\n renameTrack(trackId: number, name: string): void {\n this.native.renameTrack(trackId, name);\n }\n\n /** Set a track's mixer-strip binding + output target (undoable; omit / '' clears). */\n setTrackRoute(trackId: number, channelStripRef?: string, outputTarget?: string): void {\n this.native.setTrackRoute(trackId, channelStripRef ?? '', outputTarget ?? '');\n }\n\n /** Append an automation lane; returns its stable target parameter id (undoable). */\n addAutomationLane(trackId: number, desc: ProjectAutomationLaneDesc): number {\n if (desc.targetParamId === 0) {\n throw new RangeError('project automation lane targetParamId must be non-zero');\n }\n const nativeDesc: ProjectAutomationLaneDesc = {\n ...desc,\n points: desc.points.map(projectAutomationPointValue),\n };\n if (Object.keys(desc).includes('targetKind')) {\n nativeDesc.targetKind = projectAutomationTargetKindValue(\n desc.targetKind as ProjectAutomationTargetKind,\n ) as ProjectAutomationTargetKind;\n }\n return this.native.addAutomationLane(trackId, nativeDesc);\n }\n\n /** Replace the lane identified by its stable target parameter id (undoable). */\n editAutomationLane(\n trackId: number,\n targetParamId: number,\n desc: ProjectAutomationLaneDesc,\n ): void {\n if (desc.targetParamId === 0) {\n throw new RangeError('project automation lane targetParamId must be non-zero');\n }\n const nativeDesc: ProjectAutomationLaneDesc = {\n ...desc,\n points: desc.points.map(projectAutomationPointValue),\n };\n if (Object.keys(desc).includes('targetKind')) {\n nativeDesc.targetKind = projectAutomationTargetKindValue(\n desc.targetKind as ProjectAutomationTargetKind,\n ) as ProjectAutomationTargetKind;\n }\n this.native.editAutomationLane(trackId, targetParamId, nativeDesc);\n }\n\n /** Remove the lane identified by its stable target parameter id (undoable). */\n removeAutomationLane(trackId: number, targetParamId: number): void {\n this.native.removeAutomationLane(trackId, targetParamId);\n }\n\n /** Replace the project's key annotation stream (undoable). */\n annotateKeys(keys: ReadonlyArray<ProjectKeySegment>): void {\n this.native.annotateKeys(keys);\n }\n\n /** Replace the project's chord-symbol annotation stream (undoable). */\n annotateChords(chords: ReadonlyArray<ProjectChordSymbol>): void {\n this.native.annotateChords(chords);\n }\n\n /**\n * Add or update an opaque assist sidecar via an undoable edit.\n *\n * The descriptor form is the canonical API and matches the Node binding;\n * the positional form remains available for compatibility with the original\n * WASM facade.\n */\n setAssistSidecar(sidecar: ProjectAssistSidecarInput): void;\n setAssistSidecar(\n moduleId: string,\n schemaVersion: number,\n targetTrackId: number,\n regionStartPpq: number,\n regionEndPpq: number,\n payload: Uint8Array,\n ): void;\n setAssistSidecar(\n sidecarOrModuleId: ProjectAssistSidecarInput | string,\n schemaVersion?: number,\n targetTrackId?: number,\n regionStartPpq?: number,\n regionEndPpq?: number,\n payload?: Uint8Array,\n ): void {\n if (typeof sidecarOrModuleId === 'string') {\n if (\n schemaVersion === undefined ||\n targetTrackId === undefined ||\n regionStartPpq === undefined ||\n regionEndPpq === undefined ||\n payload === undefined\n ) {\n throw new TypeError('Project.setAssistSidecar: positional form requires six arguments');\n }\n this.native.setAssistSidecar(\n validateAssistSidecarModuleId(sidecarOrModuleId),\n validateAssistSidecarUint32(schemaVersion, 'schemaVersion'),\n validateAssistSidecarUint32(targetTrackId, 'targetTrackId'),\n validateAssistSidecarPpq(regionStartPpq, 'regionStartPpq'),\n validateAssistSidecarPpq(regionEndPpq, 'regionEndPpq'),\n validateAssistSidecarPayload(payload),\n );\n return;\n }\n\n if (\n sidecarOrModuleId === null ||\n typeof sidecarOrModuleId !== 'object' ||\n Array.isArray(sidecarOrModuleId)\n ) {\n throw new TypeError('Project.setAssistSidecar: expected a sidecar descriptor object');\n }\n const sidecar = sidecarOrModuleId;\n const moduleId = validateAssistSidecarModuleId(sidecar.moduleId);\n this.native.setAssistSidecar(\n moduleId,\n validateAssistSidecarUint32(sidecar.schemaVersion ?? 0, 'schemaVersion'),\n validateAssistSidecarUint32(sidecar.targetTrackId ?? 0, 'targetTrackId'),\n validateAssistSidecarPpq(sidecar.regionStartPpq ?? 0, 'regionStartPpq'),\n validateAssistSidecarPpq(sidecar.regionEndPpq ?? 0, 'regionEndPpq'),\n validateAssistSidecarPayload(sidecar.payload ?? new Uint8Array()),\n );\n }\n\n /** Number of assist sidecars currently stored on the project. */\n assistSidecarCount(): number {\n return this.native.assistSidecarCount();\n }\n\n /** Read one assist sidecar by stable project order. */\n getAssistSidecar(index: number): ProjectAssistSidecar {\n return this.native.getAssistSidecar(index);\n }\n\n /** Read every stored assist sidecar in the same order as the index getter. */\n assistSidecars(): ProjectAssistSidecar[] {\n const count = this.assistSidecarCount();\n return Array.from({ length: count }, (_, index) => this.getAssistSidecar(index));\n }\n\n /** Set the project's clip-overlap policy (SonareProjectOverlapPolicy ordinal). */\n setOverlapPolicy(policy: number): void {\n this.native.setOverlapPolicy(policy);\n }\n\n /** Read the project's clip-overlap policy (SonareProjectOverlapPolicy ordinal). */\n getOverlapPolicy(): number {\n return this.native.getOverlapPolicy();\n }\n\n /** Read the project sample rate in Hz. */\n getSampleRate(): number {\n return this.native.getSampleRate();\n }\n\n /** Replace the project's mixer scene from a scene JSON string. */\n setMixerSceneJson(sceneJson: string): void {\n this.native.setMixerSceneJson(sceneJson);\n }\n\n /**\n * Add or replace a marker. Pass `markerId` 0 to allocate a new id; returns the\n * stable marker id (the allocated id when 0 was passed).\n */\n setMarker(markerId: number, ppq: number, name: string): number {\n return this.native.setMarker(markerId, ppq, name);\n }\n\n /**\n * Add or replace a marker from a full {@link ProjectMarker}, including its\n * {@link MarkerKind} and (for key signatures) the key. Pass `id` 0 to allocate\n * a new id; returns the stable marker id.\n */\n setMarkerEx(marker: ProjectMarker): number {\n return this.native.setMarkerEx(marker);\n }\n\n /** Read a project marker by index (0-based, in stored order). */\n markerByIndex(index: number): ProjectMarker {\n return this.native.markerByIndex(index);\n }\n\n /** Read a stored project track by 0-based index. */\n trackByIndex(index: number): ProjectTrack {\n return this.native.trackByIndex(index);\n }\n /** Read a stored project clip by 0-based index. */\n clipByIndex(index: number): ProjectClip {\n return this.native.clipByIndex(index);\n }\n /** Read a stored project source by 0-based index. */\n sourceByIndex(index: number): ProjectSource {\n return this.native.sourceByIndex(index);\n }\n\n /** Number of markers in the project. */\n markerCount(): number {\n return this.native.markerCount();\n }\n\n /** Number of tracks in the project. */\n trackCount(): number {\n return this.native.trackCount();\n }\n\n /** Number of clips in the project. */\n clipCount(): number {\n return this.native.clipCount();\n }\n\n /** Number of audio sources registered on the project. */\n sourceCount(): number {\n return this.native.sourceCount();\n }\n\n /** Number of tempo-map segments on the project. */\n tempoSegmentCount(): number {\n return this.native.tempoSegmentCount();\n }\n\n /**\n * Reads a tempo segment by index, in stored order.\n *\n * @param index - Zero-based index below {@link tempoSegmentCount}\n * @returns The segment, in the shape {@link setTempoSegments} accepts\n * @throws When the index is at or past the count\n */\n tempoSegmentByIndex(index: number): ProjectTempoSegment {\n return this.native.tempoSegmentByIndex(index);\n }\n\n /**\n * Reads a time-signature segment by index, in stored order.\n *\n * @param index - Zero-based index below {@link timeSignatureCount}\n * @returns The segment, in the shape {@link setTimeSignatures} accepts\n * @throws When the index is at or past the count\n */\n timeSignatureByIndex(index: number): ProjectTimeSignatureSegment {\n return this.native.timeSignatureByIndex(index);\n }\n\n /** Number of time-signature segments on the project. */\n timeSignatureCount(): number {\n return this.native.timeSignatureCount();\n }\n\n /** Replace the project's tempo map with the given segments. */\n setTempoSegments(segments: ReadonlyArray<ProjectTempoSegment>): void {\n this.native.setTempoSegments(segments);\n }\n\n /** Replace the project's time-signature map with the given segments. */\n setTimeSignatures(segments: ReadonlyArray<ProjectTimeSignatureSegment>): void {\n this.native.setTimeSignatures(segments);\n }\n\n /**\n * Compile diagnostics produced by the most recent bounce on this project\n * (e.g. MIDI clips rendering silently without a bound instrument). On a\n * project no bounce has ever run on, the result is empty in full:\n * `hasTimeline` is `false` and `diagnostics` is empty. A failed bounce is\n * distinguishable from that state, because a bounce only loses its timeline\n * through an error diagnostic and so always reports at least one.\n */\n lastBounceCompileResult(): ProjectCompileResult {\n return this.native.lastBounceCompileResult();\n }\n\n /** Release the underlying WASM object. Idempotent, as the Node facade is. */\n delete(): void {\n if (this.released) {\n return;\n }\n this.released = true;\n this.native.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n","import type { SynthEnumTables, SynthPatch } from './instrument_types';\nimport { projectModule } from './project_internal';\n\n/**\n * Runtime ABI version of the flat project POD layout exposed by this WASM\n * build. Equals {@link EXPECTED_PROJECT_ABI_VERSION} when the arrangement\n * subsystem is compiled in. Mirrors the C-ABI `sonare_project_abi_version`.\n */\nexport function projectAbiVersion(): number {\n return projectModule().projectAbiVersion();\n}\n\n/**\n * NativeSynth preset catalog names (`'sine'`, `'saw-lead'`, `'e-piano'`,\n * `'drum-kit'`, ...). Use these to discover valid {@link SynthPatch} preset\n * names instead of hardcoding magic strings.\n */\nexport function synthPresetNames(): string[] {\n // Array.from re-roots embind's vector as a plain, structured-cloneable Array.\n return Array.from(projectModule().synthPresetNames());\n}\n\n/**\n * GS rhythm-set name a rhythm part's `program` selects (`'Standard'`,\n * `'Room'`, `'Jazz'`, ...), or `null` when the module's own tone map defines\n * no set there.\n *\n * @remarks\n * The answer is the module's own map, which is the newest one and reaches\n * every set this build voices; a file selecting an older map reaches fewer.\n */\nexport function synthGsDrumKitName(program: number): string | null {\n return projectModule().synthGsDrumKitName(program);\n}\n\n/**\n * Whether the GS rhythm set at `program` is voiced apart from Standard: `true`\n * when at least one drum note differs, `false` when the set renders exactly as\n * Standard, `null` when no set sits at `program`.\n *\n * @remarks\n * Derived by applying the set to every note's resolved patch and comparing, so\n * the answer follows the voicing rather than a list that has to be kept in step\n * with it. Four sets GS fills with one-shots share the Standard voicing\n * deliberately, so a picker built from the set list alone offers four choices\n * that change nothing — annotate or disable them with this.\n *\n * @example\n * ```ts\n * const kits = Array.from({ length: 128 }, (_, program) => ({ program, name: synthGsDrumKitName(program) }))\n * .filter((kit): kit is { program: number; name: string } => kit.name !== null)\n * .map((kit) => ({ ...kit, placeholder: synthGsDrumKitIsVoicedApart(kit.program) === false }));\n * ```\n */\nexport function synthGsDrumKitIsVoicedApart(program: number): boolean | null {\n const r = projectModule().synthGsDrumKitIsVoicedApart(program);\n return r < 0 ? null : r === 1;\n}\n\n/**\n * Whether melodic Bank Select `bank` on `program` is voiced apart from the\n * capital tone: `true` when the bank has a patch of its own, `false` when it\n * resolves to the capital, `null` when either argument is outside `[0, 127]` —\n * both are seven-bit MIDI values, so `128` is out of range rather than the drum\n * bank here.\n *\n * @remarks\n * Resolving an unvoiced variation to its capital is what GS specifies, so a\n * `false` is correct behaviour rather than a gap — but only this query\n * separates it from a bank that is voiced, which otherwise takes rendering both\n * and comparing. Accepts the GS Bank Select MSB and the GM2 LSB alike, since\n * both address the same variation.\n */\nexport function synthGsVariationIsVoicedApart(bank: number, program: number): boolean | null {\n const r = projectModule().synthGsVariationIsVoicedApart(bank, program);\n return r < 0 ? null : r === 1;\n}\n\n/**\n * Controller-profile preset names (`'gm'`, `'breath'`, `'breath-aftertouch'`,\n * `'mpe'`). These are the names {@link RealtimeEngine.setControllerProfile}\n * accepts; an unknown one throws rather than resolving to a default.\n */\nexport function controllerProfileNames(): string[] {\n // Array.from re-roots embind's vector as a plain, structured-cloneable Array.\n return Array.from(projectModule().controllerProfileNames());\n}\n\n/**\n * Fetch a named catalog preset as a {@link SynthPatch} (the preset name plus\n * the wrapper-section values), so hosts can inspect a preset and tweak fields\n * before binding it. A `\"va:\"` routing prefix is accepted; unknown names\n * throw.\n */\nexport function synthPresetPatch(name: string): SynthPatch {\n // embind returns a val::object whose constructor is not this realm's Object, so a\n // direct return is not structured-cloneable (breaks postMessage to a Worker).\n // Spreading into a fresh literal re-roots it as a plain Object; modRoutings is\n // already a plain member array.\n return { ...projectModule().synthPresetPatch(name) };\n}\n\nexport function synthEnumTables(): SynthEnumTables {\n return projectModule()._synthEnumTables();\n}\n\nexport function synthPatchRoundTripForTest(patch: SynthPatch): SynthPatch {\n return projectModule()._synthPatchRoundTrip(patch);\n}\n","// Type-only, so the erased import adds no runtime edge to the codes module.\nimport type { PROJECT_AUTOMATION_CURVE_VALUES } from './codes';\nimport type { Project } from './project_class';\n\n// ============================================================================\n// Headless DAW Project\n// ============================================================================\n\n/**\n * Expected project ABI version. Mirrors `SONARE_PROJECT_ABI_VERSION` in\n * `src/sonare_c_project.h`; checked against {@link projectAbiVersion} to detect\n * a WASM build whose flat project POD layout has drifted from this wrapper.\n */\nexport const EXPECTED_PROJECT_ABI_VERSION = 2;\n\n/** Render options for {@link Project.bounce}. All fields are optional. */\nexport interface ProjectBounceOptions {\n /** Render length in frames at the output sample rate. */\n totalFrames?: number;\n /** Render block size; <= 0 uses the engine default (128). */\n blockSize?: number;\n /**\n * Output channel count: 1, 2, 6 or 8, and at most the width of the scene\n * master's layout (mono/stereo/no master allow 2). The master is mixed at\n * this width; 1 folds a 2-channel master to 0.5(L+R). <= 0 uses the default\n * (2).\n */\n numChannels?: number;\n /**\n * Output sample rate. This is not a resample: a positive value must equal\n * the project's own sample rate, or the bounce is refused. <= 0 uses the\n * project sample rate.\n */\n sampleRate?: number;\n /** Host-instrument PDC (latency) fed to the compiler. */\n instrumentLatencySamples?: number;\n}\n\n/** One decoded output from a host-owned source-separation model. */\nexport interface ExternalSeparatedStem {\n name: string;\n /** Optional host metadata; it does not change DSP. */\n role?: string;\n layout: 'mono' | 'stereo' | 1 | 2;\n planarSamples: Float32Array[];\n /** Absolute project-rate frame at which this stem begins. */\n startFrame?: number;\n}\n\n/** Request for {@link Project.importExternalStems}. */\nexport interface ExternalSeparatedStemImportRequest {\n sampleRate: number;\n stems: ExternalSeparatedStem[];\n}\n\n/** Ids of the normal tracks and clips created by the import. */\nexport interface ExternalSeparatedStemImportResult {\n trackIds: number[];\n clipIds: number[];\n}\n\n/**\n * Marker kind ordinals. Mirrors `SonareMarkerKind` in `src/sonare_c_types.h`;\n * the values are part of the ABI and must not be renumbered.\n */\nexport const MarkerKind = {\n marker: 0,\n text: 1,\n lyric: 2,\n cuePoint: 3,\n keySignature: 4,\n} as const;\n\n/** A project timeline marker with its kind and (for key signatures) the key. */\nexport interface ProjectMarker {\n /** Stable marker id (0 when allocating a new id via {@link Project.setMarkerEx}). */\n id: number;\n /** Marker position in PPQ (quarter notes). */\n ppq: number;\n /** Marker label. */\n name?: string;\n /** {@link MarkerKind} ordinal (default 0 = marker). */\n kind?: number;\n /** Key signature only: -7..7 (sharps positive). */\n keyFifths?: number;\n /** Key signature only: false = major, true = minor. */\n keyMinor?: boolean;\n}\n\n/** Read-only stored project track returned by {@link Project.trackByIndex}. */\nexport interface ProjectTrack {\n id: number;\n kind: number;\n midiDestinationId: number;\n gain: number;\n pan: number;\n mute: boolean;\n solo: boolean;\n name: string;\n}\n\n/** Read-only stored project clip returned by {@link Project.clipByIndex}. */\nexport interface ProjectClip {\n id: number;\n trackId: number;\n sourceId: number;\n sourceKind: number;\n startPpq: number;\n lengthPpq: number;\n sourceOffsetPpq: number;\n gain: number;\n loopMode: number;\n loopLengthPpq: number;\n}\n\n/** Read-only stored project source returned by {@link Project.sourceByIndex}. */\nexport interface ProjectSource {\n id: number;\n kind: number;\n channelCount: number;\n storageHandleId: number;\n sampleRateHint: number;\n nameOrUri: string;\n /** Owning content hash for audio sources; empty for MIDI sources. */\n contentHash: string;\n /** External source-separation role for audio sources; empty for MIDI sources. */\n externalStemRole: string;\n}\n\n/** Clip fade-curve for {@link Project.setClipFade}. */\nexport type ProjectFadeCurve =\n | 'linear'\n | 'equal-power'\n | 'equal_power'\n | 'equalPower'\n | 'equalpower'\n | 'exponential'\n | 'exp'\n | 'logarithmic'\n | 'log'\n | 0\n | 1\n | 2\n | 3;\n\n/** One clip fade region for {@link Project.setClipFade}. */\nexport interface ProjectClipFade {\n /** Fade length in PPQ (>= 0; 0 = no fade). */\n lengthPpq?: number;\n /** Fade curve (default `'linear'`). */\n curve?: ProjectFadeCurve;\n}\n\n/** One alternate take for {@link Project.setClipTakes}. */\nexport interface ProjectClipTake {\n id: number;\n sourceId?: number;\n sourceOffsetPpq?: number;\n name?: string;\n}\n\n/** One comp segment for {@link Project.setClipCompSegments}. */\nexport interface ProjectClipCompSegment {\n startPpq: number;\n endPpq: number;\n takeId?: number;\n /** Equal-power crossfade from the preceding segment, in PPQ (default 0 = butt join). */\n crossfadePpq?: number;\n}\n\n/** Descriptor for {@link Project.addLoopRecordingTakes}. */\nexport interface ProjectLoopRecordingDesc {\n trackId: number;\n startPpq?: number;\n loopLengthPpq: number;\n audio: Float32Array;\n audioChannels?: number;\n audioSampleRate?: number;\n}\n\n/** Result returned by {@link Project.addLoopRecordingTakes}. */\nexport interface ProjectLoopRecordingResult {\n clipId: number;\n takeCount: number;\n}\n\n/** Clip loop mode for {@link Project.setClipLoop}. */\nexport type ProjectLoopMode = 'off' | 'loop' | 0 | 1;\n/**\n * How a clip follows its warp map.\n *\n * - `'off'` — no warping.\n * - `'repitch'` — resample along the map, so a rate change moves the pitch with\n * the timing (tape-style).\n * - `'tempo-sync'` — control-thread bake against the tempo map.\n * - `'time-stretch'` — realtime pitch-preserving stretch. Follows the same map\n * as `'repitch'` but overlap-adds instead of resampling, so a new anchor set\n * takes effect from the next block with no re-bake. Falls back to `'repitch'`\n * behaviour when the stretcher's voice budget is exhausted.\n */\nexport type ProjectWarpMode = 'off' | 'repitch' | 'tempo-sync' | 'time-stretch' | 0 | 1 | 2 | 3;\n\n/**\n * Automation breakpoint interpolation for {@link ProjectAutomationPoint}.\n *\n * `'s-curve'` is the canonical spelling, matching the Node engine and the mixer\n * automation types. The legacy `'scurve'` remains accepted for compatibility.\n * The spellings are derived from the resolver's own table, so the documented\n * set and the accepted set cannot drift apart.\n */\nexport type ProjectAutomationCurve = 0 | 1 | 2 | 3 | keyof typeof PROJECT_AUTOMATION_CURVE_VALUES;\n\n/** One automation breakpoint accepted by the automation-lane edit ops. */\nexport interface ProjectAutomationPoint {\n /** Breakpoint position in PPQ. */\n ppq: number;\n /** Breakpoint value. */\n value: number;\n /** Curve to the next breakpoint (default `'linear'`). */\n curve?: ProjectAutomationCurve;\n /** Alias of {@link ProjectAutomationPoint.curve}; `curve` wins when both are set. */\n curveToNext?: ProjectAutomationCurve;\n}\n\n/**\n * Persistent target classification for an automation lane.\n *\n * The numeric ordinals mirror `SonareAutomationTargetKind`; the string names\n * are the public WASM spellings accepted by the project facade.\n */\nexport const AutomationTargetKind = {\n opaque: 0,\n trackFaderDb: 1,\n trackPan: 2,\n} as const;\n\n/** Accepted automation target kind name or ABI ordinal. */\nexport type ProjectAutomationTargetKind = 'opaque' | 'track-fader-db' | 'track-pan' | 0 | 1 | 2;\n\n/** Numeric aliases matching the C-ABI enum names. */\nexport const PROJECT_AUTOMATION_TARGET_OPAQUE = AutomationTargetKind.opaque;\nexport const PROJECT_AUTOMATION_TARGET_TRACK_FADER_DB = AutomationTargetKind.trackFaderDb;\nexport const PROJECT_AUTOMATION_TARGET_TRACK_PAN = AutomationTargetKind.trackPan;\n\n/** Automation-lane descriptor for {@link Project.addAutomationLane}. */\nexport interface ProjectAutomationLaneDesc {\n /** Host-defined, non-zero id of the parameter the lane drives (zero is reserved). */\n targetParamId: number;\n /** Breakpoints (stored verbatim). */\n points: ReadonlyArray<ProjectAutomationPoint>;\n /** Optional persistent target classification; omission retains the legacy opaque route. */\n targetKind?: ProjectAutomationTargetKind;\n}\n\n/** One tempo segment for {@link Project.setTempoSegments}. */\nexport interface ProjectTempoSegment {\n /** Segment start in PPQ. */\n startPpq: number;\n /** Tempo in beats per minute at the segment start. */\n bpm: number;\n /**\n * Derived segment start in samples. Accepted for compatibility and ignored on\n * input; never returned, because a project stores musical positions only and\n * sample positions are derived when it is compiled.\n */\n startSample?: number;\n /** Optional ramp end tempo in BPM (0 = constant tempo over the segment). */\n endBpm?: number;\n}\n\n/** One time-signature segment for {@link Project.setTimeSignatures}. */\nexport interface ProjectTimeSignatureSegment {\n /** Segment start in PPQ. */\n startPpq: number;\n /** Beats per bar (time-signature numerator). */\n numerator: number;\n /** Beat unit (time-signature denominator, e.g. 4 or 8). */\n denominator: number;\n}\n\n/** A ranked primary/half/double tempo hypothesis returned by {@link Project.analyzeTempo}. */\n/**\n * Scoring options for the beat-analysis to tempo-map bridge, shared by\n * {@link Project.analyzeTempo} and {@link Project.autoTempo}.\n *\n * @remarks\n * Every field is optional and falls back to the native default. Pair the two\n * calls on the same options: `candidateIndex` indexes the ranking `analyzeTempo`\n * produced under whatever options it was given.\n */\nexport interface ProjectTempoOptions {\n /**\n * Whether beat tracking may follow a tempo that moves during the take\n * (default: `false`).\n *\n * @remarks\n * With it off the tracker fits one tempo to the whole take, so on a\n * performance that accelerates, slows or breathes every segment the bridge\n * emits sits near the take's average. Leave it off for material recorded to a\n * click; turn it on for a performance. Constant-tempo material still comes\n * back as a single segment either way.\n */\n adaptiveTempo?: boolean;\n /** Beats of context the local tempo estimate is read over. Used only when {@link adaptiveTempo} is on. */\n tempoUpdateIntervalBeats?: number;\n /**\n * Relative tempo change at which one segment closes and the next opens\n * (default: `0.02`). Smaller follows the performance more closely and emits\n * more segments; larger merges more of it into constant stretches.\n */\n rampThreshold?: number;\n /** Whether to rank the half- and double-tempo alternatives alongside the primary (default: `true`). */\n includeOctaveCandidates?: boolean;\n}\n\nexport interface ProjectTempoCandidate {\n bpm: number;\n confidence: number;\n label: 'primary' | 'half' | 'double';\n timeSignatureCount: number;\n timeSignature: ProjectTimeSignatureSegment;\n}\n\n/** Key segment for {@link Project.annotateKeys}. */\nexport interface ProjectKeySegment {\n startPpq: number;\n endPpq: number;\n /** Tonic pitch class 0..11 (C=0) or 255 for unknown. */\n tonicPc?: number;\n /** KeyMode ordinal (0 unknown, 1 major, 2 minor, 3 dorian, ...). */\n mode?: number;\n}\n\n/** Chord symbol for {@link Project.annotateChords}. */\nexport interface ProjectChordSymbol {\n startPpq: number;\n endPpq: number;\n /** Root pitch class 0..11 (C=0) or 255 for unknown. */\n rootPc?: number;\n /** ChordQuality ordinal (0 unknown, 1 major, 2 minor, ...). */\n quality?: number;\n /** Extension semitone offsets (up to 8). */\n extensions?: ReadonlyArray<number>;\n /** Slash-bass pitch class 0..11 or 255 for none. */\n slashBassPc?: number;\n /** Optional roman-numeral label. */\n romanNumeral?: string;\n /** True at a modulation boundary. */\n modulationBoundary?: boolean;\n}\n\n/** Descriptor accepted by {@link Project.setAssistSidecar}. */\nexport interface ProjectAssistSidecarInput {\n /** Non-empty module id key. */\n moduleId: string;\n /** Module-defined schema version. Defaults to `0`. */\n schemaVersion?: number;\n /** Target track id (`0` = project scope). Defaults to `0`. */\n targetTrackId?: number;\n /** Region start in PPQ. Defaults to `0`. */\n regionStartPpq?: number;\n /** Region end in PPQ. Defaults to `0`. */\n regionEndPpq?: number;\n /** Opaque module-owned payload bytes. Defaults to an empty payload. */\n payload?: Uint8Array;\n}\n\n/** Assist sidecar snapshot returned by {@link Project.getAssistSidecar}. */\nexport interface ProjectAssistSidecar {\n moduleId: string;\n schemaVersion: number;\n targetTrackId: number;\n regionStartPpq: number;\n regionEndPpq: number;\n payload: Uint8Array;\n}\n\n/** Track kind for {@link Project.addTrack}. */\nexport type ProjectTrackKind = 'audio' | 'midi' | 'aux' | 0 | 1 | 2;\n\n/** Descriptor for {@link Project.addTrack}. */\nexport interface ProjectTrackDesc {\n kind?: ProjectTrackKind;\n name?: string;\n}\n\nexport interface ProjectWarpAnchor {\n warpSample: number;\n sourceSample: number;\n}\n\nexport interface ProjectWarpMapDesc {\n id: number;\n name?: string;\n anchors: ProjectWarpAnchor[];\n}\n\n/**\n * Canonical request form for {@link alignTakeToReference}.\n *\n * Both resolution fields are optional and omitting one takes the library value.\n * A `0` is **refused** rather than read as a request for the default: neither\n * field has a meaning at 0, so omission is already how you ask for the default,\n * and a substituted value is indistinguishable downstream from one you chose.\n */\nexport interface AlignTakeToReferenceRequest {\n /**\n * The reference timeline — the guide take, or the backing track the takes were\n * sung against. Must be non-empty and all-finite.\n */\n reference: Float32Array;\n /** The take to be placed under it. Must be non-empty and all-finite. */\n take: Float32Array;\n /**\n * Sample rate of **both** buffers in Hz, `[8000, 384000]`. Resample first if\n * they differ: the alignment does no rate conversion.\n */\n sampleRate: number;\n /**\n * Chroma hop in samples, which sets the time resolution of the anchors — a\n * smaller hop measures more frames and yields more anchors. Default `512`;\n * must be a positive integer.\n */\n hopLength?: number;\n /**\n * Chroma bins per octave — the CQT resolution the twelve pitch classes are\n * folded from. Default `12`; must be a positive **multiple of 12**, since each\n * pitch class takes the mean of a whole number of CQT bins.\n */\n binsPerOctave?: number;\n}\n\n/**\n * How well an alignment was conditioned, reported by\n * {@link AlignTakeToReferenceResult}.\n *\n * Every field is descriptive: none of them makes the call fail, and a caller\n * deciding what is acceptable supplies its own threshold.\n */\nexport interface TakeAlignment {\n /**\n * Mean absolute frame residual of the path around its diagonal trend. A coarse\n * indicator of how far the alignment strayed from a constant rate, not an error\n * bound.\n */\n meanResidualFrames: number;\n /** Chroma frames the reference produced. */\n referenceFrames: number;\n /**\n * Chroma frames the take produced. Its ratio to `referenceFrames` is the\n * overall rate difference the anchors encode.\n */\n takeFrames: number;\n}\n\n/** Result of {@link alignTakeToReference}. */\nexport interface AlignTakeToReferenceResult {\n /**\n * At least two finite, strictly increasing anchors, ready to hand to\n * {@link Project.setWarpMap} as the take clip's own warp map.\n *\n * `warpSample` is a position on the **reference** timeline and `sourceSample`\n * the corresponding position in the **take**, which is the direction a clip\n * whose source is that take needs.\n */\n anchors: ProjectWarpAnchor[];\n /** How well the alignment was conditioned. */\n alignment: TakeAlignment;\n}\n\n/** Descriptor for {@link Project.addClip}. */\nexport interface ProjectClipDesc {\n trackId: number;\n isMidi?: boolean;\n startPpq?: number;\n lengthPpq: number;\n sourceOffsetPpq?: number;\n gain?: number;\n audio?: Float32Array;\n audioChannels?: number;\n /**\n * Sample rate of `audio` in Hz. Required whenever `audio` is supplied, and\n * must be in `[8000, 384000]`: omitting it sends 0, which the native side\n * rejects. Ignored for a metadata-only clip.\n */\n audioSampleRate?: number;\n sourceUri?: string;\n}\n\n/** Result returned by {@link Project.addMidiClip}. */\nexport interface ProjectMidiClipResult {\n trackId: number;\n clipId: number;\n}\n\n/** Flat MIDI event accepted by {@link Project.setMidiEvents}. */\n/**\n * One MIDI event in a clip's list: a position plus the first two UMP words.\n *\n * @remarks\n * Channel-voice messages only. A clip's SysEx payloads live beside the event\n * list and are reached by a handle this type does not carry — they survive\n * {@link Project.importSmf}, {@link Project.exportSmf} and project\n * serialization, and are destroyed by {@link Project.setMidiEvents}.\n */\nexport interface ProjectMidiEvent {\n ppq: number;\n data0: number;\n data1?: number;\n}\n\n/** Options for {@link Project.midiRouteEvents}. `null`/omitted filter fields mean any/no remap. */\nexport interface ProjectMidiRouteConfig {\n filterGroup?: number | null;\n filterChannel?: number | null;\n remapChannel?: number | null;\n thru?: boolean;\n}\n\n/** Result of {@link Project.midiRouteEvents}. */\nexport interface ProjectMidiRouteResult {\n events: ProjectMidiEvent[];\n overflowed: boolean;\n overflowCount: number;\n}\n\nexport type ProjectMidiCcBindingKind = 0 | 1 | 2 | 3;\n\n/** Options for {@link Project.midiCcLearn}. All fields are optional. */\nexport interface MidiCcLearnOptions {\n /** Lower end of the mapped parameter range. Default `0`. */\n minValue?: number;\n /** Upper end of the mapped parameter range. Default `1`. */\n maxValue?: number;\n /** Minimum normalized CC movement required to learn a binding. Default `0`. */\n minMovement?: number;\n}\n\n/** MIDI CC <-> automation binding descriptor used by CC learn/conversion helpers. */\nexport interface ProjectMidiCcBinding {\n ccNumber: number;\n /** MIDI channel 0..15, or 255 for any channel. Omit for the any-channel sentinel `255`. */\n channel?: number;\n /** 0 = 7-bit CC, 1 = 14-bit CC, 2 = RPN, 3 = NRPN. Default `0`. */\n kind?: ProjectMidiCcBindingKind;\n ccLsbNumber?: number;\n selectorMsb?: number;\n selectorLsb?: number;\n paramId: number;\n /** Lower end of the mapped parameter range. Default `0`. */\n minValue?: number;\n /** Upper end of the mapped parameter range. Default `1`. */\n maxValue?: number;\n}\n\n/** Result of {@link Project.validateMidiNotes}. */\nexport interface ProjectNotePairValidation {\n /** True when every note-on has a matching note-off (and vice versa). */\n ok: boolean;\n /** Count of note-ons that never received a matching note-off. */\n unmatchedNoteOns: number;\n /** Count of note-offs with no preceding matching note-on. */\n unmatchedNoteOffs: number;\n}\n\n/**\n * Request form of {@link Project.bakeMidiFx}. The positional\n * `(clipId, configJson)` call stays supported and normalizes to this shape.\n */\nexport interface ProjectMidiFxBakeRequest {\n /** Target MIDI clip id. */\n clipId: number;\n /** MIDI-FX chain configuration as JSON. */\n configJson: string;\n /** Return per-event provenance in the result. Default false. */\n withSourceIndex?: boolean;\n}\n\n/** Result of the request form of {@link Project.bakeMidiFx}. */\nexport interface ProjectMidiFxBakeResult {\n /**\n * One entry per transformed event in canonical order: the index of the input\n * event it derives from, or -1 for an event with no originating input. Chord\n * and arpeggiator fan-out makes several outputs share one source index, so a\n * caller that treats the first output per index as the same event and the\n * rest as newly generated can carry a selection across the bake. Present only\n * when the request set `withSourceIndex`.\n */\n sourceIndex?: Int32Array;\n}\n\n/** Request form of {@link Project.previewMidiFxCount}. */\nexport interface ProjectMidiFxPreviewRequest {\n /** Target MIDI clip id. */\n clipId: number;\n /** MIDI-FX chain configuration as JSON. */\n configJson: string;\n}\n\n/**\n * Detector settings shared by {@link transcribe} and\n * {@link Project.transcribeToClip}.\n *\n * Every field is optional and omitting one takes the documented default. A\n * value outside a field's domain is **refused**, never silently replaced — a\n * substituted default is indistinguishable downstream from one you chose.\n *\n * That includes `0` on the fields whose domain excludes it (`referenceHz`,\n * `fmin`, `fmax`, `minNoteMs`, `segmentationThresholdCents`,\n * `velocityFloorDb`, `fixedVelocity`): omitting the field is how you ask for\n * the default, so a `0` you wrote is a value, and it is out of domain. Only\n * `group` and `channel` accept `0` — there it is a value you can mean.\n */\nexport interface TranscribeOptions {\n /**\n * `true` reads the multi-F0 chain, which finds overlapping notes at the cost\n * of a full STFT and a mask per tracked ridge. `false` (the default) reads\n * pYIN cut into notes, which follows one line at a time.\n */\n polyphonic?: boolean;\n /**\n * Tuning reference in Hz the MIDI note numbers are measured against.\n * Default `440`; must be finite and positive.\n *\n * **It is not measured for you.** A take recorded away from A440 should have\n * its reference measured first — run `pitchPyin` and feed its F0 array to\n * `pitchTuning` — and the answer passed in here. Measuring it internally\n * would track the pitch twice and hide which of the two answers a wrong\n * transcription came from.\n */\n referenceHz?: number;\n /**\n * Monophonic tracker range in Hz. Defaults `65` and `2093`; both must be\n * finite and positive, and `fmax` must exceed `fmin`. The polyphonic chain\n * sets its own range and reads neither.\n */\n fmin?: number;\n /** Upper end of the monophonic tracker range in Hz. Default `2093`. */\n fmax?: number;\n /** Shortest span kept as a note, in milliseconds. Default `30`; must be positive. */\n minNoteMs?: number;\n /**\n * Pitch movement, in cents, that ends one note and starts the next.\n * Default `50`; must be positive.\n */\n segmentationThresholdCents?: number;\n /**\n * Level mapped to velocity 1, in dBFS. Default `-48`; **must be negative**.\n *\n * A note's peak per-frame RMS is taken in dBFS and mapped linearly from\n * `[velocityFloorDb, 0]` onto `[1, 127]`, clamped at both ends.\n */\n velocityFloorDb?: number;\n /**\n * An integer in `[1, 127]` gives every note that velocity and skips the level\n * measurement. **Omit the field to measure** — `0` is refused, because it is\n * not a MIDI velocity and omission already says \"measure\".\n */\n fixedVelocity?: number;\n /** UMP group the events are emitted on, `0..15`. Default `0`. */\n group?: number;\n /** MIDI channel the events are emitted on, `0..15`. Default `0`. */\n channel?: number;\n}\n\n/** Result of {@link transcribe}. */\nexport interface TranscribeResult {\n /**\n * Note-on / note-off pairs in canonical PPQ order, ready to hand straight to\n * {@link Project.setMidiEvents}.\n *\n * Ordering is `(ppq, note-off before note-on)`. A note-off sharing a tick\n * with the next note's on comes first, so a consumer playing the events in\n * order does not start a legato repeat of the same pitch and immediately\n * stop it.\n */\n events: ProjectMidiEvent[];\n /** Number of notes, which is always half `events.length`. */\n noteCount: number;\n /** The tempo the PPQ coordinates were built on — yours when you gave one, the detected one otherwise. */\n tempoBpm: number;\n}\n\n/**\n * Request form of {@link Project.transcribeToClip}.\n *\n * No `tempoBpm`: the PPQ grid is the **project's own tempo map**, so a project\n * whose tempo was installed by {@link Project.autoTempo} transcribes onto that\n * map rather than onto a second, separately detected tempo.\n */\nexport interface ProjectTranscribeRequest extends TranscribeOptions {\n /** Target MIDI clip id. Its entire event list is replaced. */\n clipId: number;\n /** Mono source audio. Must be non-empty and all-finite. */\n samples: Float32Array;\n /** Sample rate of `samples` in Hz, `[8000, 384000]`. */\n sampleRate: number;\n}\n\n/** One compile diagnostic (mirrors SonareProjectDiagnostic). */\nexport interface ProjectDiagnostic {\n code: number;\n /** 0 = error, 1 = warning. */\n severity: number;\n /** Affected clip / track / source id (0 = n/a). */\n targetId: number;\n /** Human-readable message for this diagnostic. */\n message: string;\n}\n\n/** Diagnostics summary returned by {@link Project.compile}. */\nexport interface ProjectCompileResult {\n /** Number of diagnostics surfaced by the compile. Kept for backward compatibility. */\n diagnosticCount: number;\n /** True when compilation produced a renderable timeline (no error diagnostics). */\n hasTimeline: boolean;\n /** Newline-joined human-readable detail of every diagnostic. */\n messages: string;\n diagnostics: ProjectDiagnostic[];\n}\n\nexport interface ProjectDeserializeResult {\n project: Project;\n diagnostics: string;\n}\n","import {\n panLawCode,\n panModeCode,\n sendTimingCode,\n sidechainSourceKindCode,\n trackMonitorModeCode,\n} from './codes';\nimport { ErrorCode, SonareError } from './errors';\nimport { getSonareModule } from './module_state';\nimport type {\n Articulation,\n ControllerBinding,\n MpeDimension,\n NoteTracking,\n ProjectMidiCcBinding,\n SynthPatch,\n} from './project';\nimport { normalizeSynthInstrument } from './project_internal';\nimport type {\n EqBand,\n PanLawInput,\n PanMode,\n SendTiming,\n SidechainSourceKind,\n UmpWords,\n} from './public_types';\nimport type {\n WasmClipPageRequest,\n WasmEngineAutomationPoint,\n WasmEngineBounceOptions,\n WasmEngineBounceResult,\n WasmEngineCaptureStatus,\n WasmEngineClip,\n WasmEngineFreezeOptions,\n WasmEngineFreezeResult,\n WasmEngineGraphSpec,\n WasmEngineMarker,\n WasmEngineMeterTelemetry,\n WasmEngineMeterTelemetryWide,\n WasmEngineMetronomeConfig,\n WasmEngineParameterInfo,\n WasmEngineProcessWithMonitorResult,\n WasmEngineScopeTelemetry,\n WasmEngineTelemetry,\n WasmEngineTempoSegment,\n WasmEngineTimeSignatureSegment,\n WasmEngineTransportState,\n WasmExternalMidiEvent,\n WasmRealtimeEngine,\n} from './sonare.js';\n\nexport type ExternalMidiEvent = WasmExternalMidiEvent;\n\nexport type EngineClip = WasmEngineClip;\nexport type ClipPageRequest = WasmClipPageRequest;\nexport type EngineParameterInfo = WasmEngineParameterInfo;\nexport type EngineAutomationPoint = WasmEngineAutomationPoint;\nexport type EngineMarker = WasmEngineMarker;\nexport type EngineMetronomeConfig = WasmEngineMetronomeConfig;\nexport type EngineGraphSpec = WasmEngineGraphSpec;\nexport type EngineCaptureStatus = WasmEngineCaptureStatus;\nexport type EngineCaptureSource = EngineCaptureStatus['source'] | number;\nexport type EngineBounceOptions = WasmEngineBounceOptions;\nexport type EngineBounceResult = WasmEngineBounceResult;\nexport type EngineFreezeOptions = WasmEngineFreezeOptions;\nexport type EngineFreezeResult = WasmEngineFreezeResult;\nexport type EngineTelemetry = WasmEngineTelemetry;\nexport type EngineMeterTelemetry = WasmEngineMeterTelemetry;\nexport type EngineMeterTelemetryWide = WasmEngineMeterTelemetryWide;\nexport type EngineScopeTelemetry = WasmEngineScopeTelemetry;\nexport type EngineTransportState = WasmEngineTransportState;\nexport type EngineTempoSegment = WasmEngineTempoSegment;\nexport type EngineTimeSignatureSegment = WasmEngineTimeSignatureSegment;\n\nexport interface EngineTrackSend {\n busId: number;\n levelDb?: number;\n enabled?: boolean;\n /**\n * Pre/post-fader tap point. Defaults to post-fader when omitted, matching the\n * historical lane-send behavior and the scene-JSON default.\n */\n sendTiming?: SendTiming | number;\n}\n\nexport interface EngineTrackLane {\n trackId: number;\n sends?: EngineTrackSend[];\n /**\n * Bus the lane's post-fader output sums into instead of the master mix\n * (group/folder routing); 0 or absent keeps the lane on the master mix.\n */\n outputBusId?: number;\n /**\n * Input channel layout of the source feeding this lane (`SonareChannelLayout`:\n * 0 mono, 1 stereo, 2 5.1, 3 7.1). Absent defaults to stereo. Stored but inert\n * until the surround DSP path lands.\n */\n sourceChannelLayout?: number;\n}\n\n/** Per-track cue/monitor tap mode: off, pre-fader listen, or after-fader listen. */\nexport type EngineTrackMonitorMode = 'off' | 'pfl' | 'afl' | 0 | 1 | 2;\n\n/** Short alias for {@link EngineTrackMonitorMode}. */\nexport type TrackMonitorMode = EngineTrackMonitorMode;\n\nexport interface EngineBus {\n busId: number;\n gainDb?: number;\n /**\n * Channel layout of the bus (`SonareChannelLayout`: 0 mono, 1 stereo, 2 5.1,\n * 3 7.1). A surround layout makes this a surround group bus: lanes routed to\n * it are surround-panned and it sums into the master plane-by-plane. Defaults\n * to stereo.\n */\n channelLayout?: number;\n /**\n * Bus this bus's output sums into instead of the master mix (bus-to-bus\n * routing); 0 or absent keeps it on the master mix.\n */\n outputBusId?: number;\n /**\n * Sends to other buses, in the same shape as a track lane's sends. A\n * pre-fader send taps before `gainDb`, a post-fader one after it.\n */\n sends?: EngineTrackSend[];\n}\n\nexport interface EngineMidiEvent {\n /** Absolute render frame for this event. Default `0`. */\n renderFrame?: number;\n word0?: number;\n word1?: number;\n word2?: number;\n word3?: number;\n wordCount?: number;\n /**\n * Redundant with `word0`, which already carries the UMP group in bits 24..27.\n * The engine reads the group from `word0` — the form that reaches a device or\n * a file — so packing it there is sufficient and a value here that contradicts\n * `word0` is ignored. Must still be in `[0, 15]`; anything else is rejected as\n * a malformed event. Default `0`.\n *\n * Utility (`word0` type nibble `0x0`) and UMP Stream (`0xF`) messages have no\n * group field — those bits are Reserved and `form`/`status` respectively — so\n * they always read as group `0` and packing a group into them has no effect.\n */\n group?: number;\n sysexHandle?: number;\n data0?: number;\n data1?: number;\n}\n\nexport interface EngineMidiClipSchedule {\n id?: number;\n trackId?: number;\n destinationId?: number;\n startSample?: number;\n startPpq?: number;\n lengthSamples?: number;\n loop?: boolean;\n loopLengthSamples?: number;\n events: EngineMidiEvent[];\n /**\n * Linear gain applied to the destination instrument's rendered audio while\n * this clip is the most recently started active clip on it. Absent defaults\n * to `1` (unity).\n */\n gain?: number;\n /**\n * Linear fade lengths over the clip's full length (not per internal loop\n * repeat). Absent defaults to `0` (no fade). `fadeOutSamples` above `0` is\n * rejected when `lengthSamples` is absent or `<= 0` (open-ended): an\n * open-ended clip has no end to fade out towards.\n */\n fadeInSamples?: number;\n fadeOutSamples?: number;\n}\n\nexport const EXPECTED_ENGINE_ABI_VERSION = 3;\n\n/** Options for {@link RealtimeEngine.bindMidiCc}. All fields are optional. */\nexport interface MidiCcBindOptions {\n /** Lower end of the mapped parameter range. Default `0`. */\n minValue?: number;\n /** Upper end of the mapped parameter range. Default `1`. */\n maxValue?: number;\n}\n\n/** Request form of {@link RealtimeEngine.renderOffline}. */\nexport interface RenderOfflineRequest {\n /** One buffer per output plane; their common length is the render span. */\n channels: Float32Array[];\n /** Render block size. Default `128`. */\n blockSize?: number;\n /**\n * Whether this call ends the timeline. `true` (the default, and what a\n * one-shot bounce wants) releases every sounding note and flushes the PDC /\n * alignment delay lines before returning. `false` renders one CHUNK of a\n * longer timeline: a note held across the chunk boundary keeps sounding into\n * the next call and the delay lines carry their history over, so consecutive\n * chunks concatenate to exactly what one continuous render of the same span\n * produces. Call {@link RealtimeEngine.finishOfflineRender} once after the\n * last chunk.\n *\n * Sample-exact concatenation requires every chunk to use the same `blockSize`\n * and a frame count that is a whole number of blocks: each call restarts the\n * block grid at its own frame 0 and renders a short final block for the\n * remainder, and the clip / automation / MIDI-clip snapshots are frozen once\n * per block, so a chunk that ends mid-block shifts every later block\n * boundary. Audio stays continuous either way; only bit-identity is lost.\n */\n finalize?: boolean;\n}\n\nconst UMP_WORD_MIN = -0x80000000;\nconst UMP_WORD_MAX = 0xffffffff;\n\n// A word may be spelled `(0x4 << 28) | …`, which is a signed int once bit 31 is\n// set, so the signed 32-bit range is accepted alongside the unsigned one.\nfunction assertUmpWords(fnName: string, words: UmpWords): UmpWords {\n if (!(words instanceof Uint32Array) && !Array.isArray(words)) {\n throw new TypeError(`${fnName}: words must be a Uint32Array or a number array`);\n }\n if (words.length < 1 || words.length > 4) {\n throw new RangeError(`${fnName}: words must hold 1 to 4 words`);\n }\n for (let i = 0; i < words.length; i++) {\n const word = words[i];\n if (\n typeof word !== 'number' ||\n !Number.isInteger(word) ||\n word < UMP_WORD_MIN ||\n word > UMP_WORD_MAX\n ) {\n throw new RangeError(`${fnName}: words[${i}] must be an integer 32-bit word`);\n }\n }\n return words;\n}\n\n/**\n * One normalizer for both call forms, so the request object and the positional\n * overload cannot drift in their defaults.\n */\nfunction normalizeRenderOfflineRequest(\n channelsOrRequest: Float32Array[] | RenderOfflineRequest,\n blockSize: number,\n): { channels: Float32Array[]; blockSize: number; finalize: boolean } {\n const request = Array.isArray(channelsOrRequest)\n ? { channels: channelsOrRequest, blockSize }\n : channelsOrRequest;\n return {\n channels: request.channels,\n blockSize: request.blockSize ?? 128,\n finalize: request.finalize ?? true,\n };\n}\n\nexport interface EngineCapabilities {\n engineAbiVersion: number;\n expectedEngineAbiVersion: number;\n abiCompatible: boolean;\n sharedArrayBuffer: boolean;\n atomics: boolean;\n audioWorklet: boolean;\n mode: 'sab' | 'postMessage';\n}\n\nexport function engineCapabilities(): EngineCapabilities {\n const abiVersion = getSonareModule().engineAbiVersion();\n const sharedArrayBuffer = typeof globalThis.SharedArrayBuffer === 'function';\n const atomics = typeof globalThis.Atomics === 'object';\n const audioWorklet =\n typeof AudioWorkletNode !== 'undefined' ||\n typeof (globalThis as typeof globalThis & { AudioWorkletProcessor?: unknown })\n .AudioWorkletProcessor !== 'undefined';\n return {\n engineAbiVersion: abiVersion,\n expectedEngineAbiVersion: EXPECTED_ENGINE_ABI_VERSION,\n abiCompatible: abiVersion === EXPECTED_ENGINE_ABI_VERSION,\n sharedArrayBuffer,\n atomics,\n audioWorklet,\n mode: sharedArrayBuffer && atomics ? 'sab' : 'postMessage',\n };\n}\n\nexport class RealtimeEngine {\n private native: WasmRealtimeEngine;\n private released = false;\n\n constructor(\n sampleRate = 48000,\n maxBlockSize = 128,\n commandCapacity = 1024,\n telemetryCapacity = 1024,\n maxChannels = 64,\n ) {\n const module = getSonareModule();\n const capabilities = engineCapabilities();\n if (!capabilities.abiCompatible) {\n throw new Error(\n `Engine ABI mismatch: wasm=${capabilities.engineAbiVersion}, expected=${capabilities.expectedEngineAbiVersion}`,\n );\n }\n this.native = new module.RealtimeEngine(\n sampleRate,\n maxBlockSize,\n commandCapacity,\n telemetryCapacity,\n maxChannels,\n );\n }\n\n /**\n * Size the engine's queues and scratch for a sample rate and block size.\n *\n * `commandCapacity` must not exceed 65536 and `telemetryCapacity` must not\n * exceed 16384; a larger value throws and leaves the engine untouched. The\n * telemetry number is not a queue depth paid for one-for-one: the engine\n * reserves that many meter records per metered lane, so its memory cost is\n * far larger than the number given here.\n */\n prepare(\n sampleRate: number,\n maxBlockSize: number,\n commandCapacity = 1024,\n telemetryCapacity = 1024,\n maxChannels = 64,\n ): void {\n this.native.prepareWithChannels(\n sampleRate,\n maxBlockSize,\n commandCapacity,\n telemetryCapacity,\n maxChannels,\n );\n }\n\n /** Queue a sample-accurate parameter change (engine kSetParam). */\n setParameter(paramId: number, value: number, renderFrame = -1): void {\n this.native.setParameter(paramId, value, renderFrame);\n }\n\n /** Queue a smoothed parameter change (engine kSetParamSmoothed). */\n setParameterSmoothed(paramId: number, value: number, renderFrame = -1): void {\n this.native.setParameterSmoothed(paramId, value, renderFrame);\n }\n\n /**\n * Set the default ramp time (ms) for engine-level smoothed parameters —\n * fader/pan glides, insert-parameter automation, and MIDI-CC mappings. The\n * default is 20 ms; pass `0` for instant (un-ramped) changes.\n */\n setParamSmoothingMs(smoothingMs: number): void {\n this.native.setParamSmoothingMs(smoothingMs);\n }\n\n setSoloMute(laneIndex: number, solo: boolean, mute: boolean, renderFrame = -1): void {\n this.native.setSoloMute(laneIndex, solo, mute, renderFrame);\n }\n\n /** Queue a per-track PFL/AFL monitor tap mode change. */\n setTrackMonitorMode(laneIndex: number, mode: EngineTrackMonitorMode, renderFrame = -1): void {\n this.native.setTrackMonitorMode(laneIndex, trackMonitorModeCode(mode), renderFrame);\n }\n\n setMidiClips(clips: readonly EngineMidiClipSchedule[]): void {\n this.native.setMidiClips(clips);\n }\n\n setBuiltinInstrument(\n config: { destinationId?: number } & Record<string, unknown> = {},\n destinationId = config.destinationId ?? 0,\n ): void {\n this.native.setBuiltinInstrument(destinationId, config);\n }\n\n /**\n * Bind the patch-driven NativeSynth to a realtime MIDI destination. `patch`\n * is a {@link SynthPatch} or a preset-name string (`'saw-lead'` /\n * `'va:saw-lead'`; see {@link synthPresetNames}), resolving exactly like\n * {@link Project.bounceWithSynthInstrument}. Live note/CC commands and\n * scheduled MIDI clips routed to that destination render through the synth.\n * Unknown preset names throw. An object patch's `destinationId` is a JS\n * binding convenience, not part of the NativeSynth patch itself.\n *\n * An `engineMode: 'sample'` patch also carries the {@link SampleBank} its\n * keymap names. The synth takes a share of the bank, so it may be released\n * right after this call; a sample patch bound without one renders silence.\n */\n setSynthInstrument(\n patch: SynthPatch | string = {},\n destinationId = (typeof patch === 'object' ? patch.destinationId : undefined) ?? 0,\n ): void {\n this.native.setSynthInstrument(destinationId, normalizeSynthInstrument(patch));\n }\n\n /**\n * Load (parse) SoundFont 2 bytes into the engine so SF2 instruments can be\n * bound with {@link setSf2Instrument}. The host fetches the `.sf2` and\n * passes the raw bytes; they are copied into linear memory for the call and\n * not referenced afterwards. Replaces any previously loaded SoundFont.\n */\n loadSoundFont(data: Uint8Array): void {\n this.native.loadSoundFont(data);\n }\n\n /**\n * Bind a GS-compatible SoundFont player to a realtime MIDI destination, fed\n * by the engine's loaded SoundFont ({@link loadSoundFont}). Live note/CC\n * commands and scheduled MIDI clips routed to that destination render\n * through the player (16 MIDI channels, channel 10 drums, GS NRPN part\n * edits, GS/GM SysEx resets). Without a loaded SoundFont — or for programs\n * the SoundFont does not cover — notes play through the built-in\n * synthesizer GM fallback bank (the data-free floor).\n */\n setSf2Instrument(\n config: {\n destinationId?: number;\n gain?: number;\n polyphony?: number;\n preferModelForModeledFamilies?: boolean;\n clearBankRig?: boolean;\n gsEfxRealization?: 'modern' | 'classic';\n } = {},\n destinationId = config.destinationId ?? 0,\n ): void {\n this.native.setSf2Instrument(destinationId, config);\n }\n\n clearMidiInstrument(destinationId = 0): void {\n this.native.clearMidiInstrument(destinationId);\n }\n\n midiInstrumentCount(): number {\n return this.native.midiInstrumentCount();\n }\n\n /**\n * Bind a live MIDI CC to an engine automation parameter. The MIDI event still\n * reaches the destination instrument; when bound, its 7-bit value is also\n * mapped into [minValue, maxValue] for `paramId`.\n */\n bindMidiCc(\n channel: number,\n controller: number,\n paramId: number,\n options: MidiCcBindOptions = {},\n ): void {\n this.native.bindMidiCc(\n channel,\n controller,\n paramId,\n options.minValue ?? 0,\n options.maxValue ?? 1,\n );\n }\n\n /** Bind a 7/14-bit CC, RPN, or NRPN descriptor to a live parameter. */\n bindMidiCcBinding(binding: ProjectMidiCcBinding): void {\n this.native.bindMidiCcBinding(binding);\n }\n\n clearMidiCcBindings(): void {\n this.native.clearMidiCcBindings();\n }\n\n midiCcBindingCount(): number {\n return this.native.midiCcBindingCount();\n }\n\n /**\n * Replace a destination instrument's controller profile with a named preset\n * (see {@link controllerProfileNames}). Installing a profile drops every\n * channel's accumulated axis values: the new bindings say nothing about what\n * the old ones had reached. An unknown name throws, and so does a destination\n * with no instrument or one whose instrument holds no profile.\n */\n setControllerProfile(destinationId: number, presetName: string): void {\n this.native.setControllerProfile(destinationId, presetName);\n }\n\n /** Add one {@link ControllerBinding} on top of the destination's current profile. */\n bindController(destinationId: number, binding: ControllerBinding): void {\n this.native.bindController(destinationId, binding);\n }\n\n /**\n * Drop every binding of the destination's controller profile. The instrument\n * keeps a profile; it resolves nothing until something is bound again.\n */\n clearControllerBindings(destinationId: number): void {\n this.native.clearControllerBindings(destinationId);\n }\n\n controllerBindingCount(destinationId: number): number {\n return this.native.controllerBindingCount(destinationId);\n }\n\n /**\n * Whether note-on velocity is expression for this instrument. No fixed\n * default is possible — a wind controller ships sending breath-derived\n * velocity on one model and a constant on the next — so each preset states it\n * and a host building its own profile sets it. When false the synth takes\n * every note at full scale and the bound axes carry the dynamics alone.\n */\n setControllerVelocityMeaningful(destinationId: number, meaningful: boolean): void {\n this.native.setControllerVelocityMeaningful(destinationId, meaningful);\n }\n\n controllerVelocityMeaningful(destinationId: number): boolean {\n return this.native.controllerVelocityMeaningful(destinationId);\n }\n\n /**\n * Say which note a value addressed to a whole MIDI channel belongs to when\n * several are sounding on it, for one per-note dimension\n * ({@link MPE_DIMENSIONS}, {@link NOTE_TRACKINGS}).\n *\n * Set per dimension because the useful answers differ: pressure following the\n * newest note while bend reaches every one is a real configuration, not a\n * mistake. MPE poses this question and declines to answer it, so this is a\n * choice rather than a rule — and it is read only inside an MPE zone, and\n * only while more than one note is sounding on the channel, which an MPE\n * sender avoids by giving each note its own member channel.\n *\n * Both arguments are required and are a name or its ordinal; an unknown\n * spelling is refused rather than resolved to a default, as are a destination\n * with no instrument and one whose instrument holds no controller profile.\n */\n setControllerNoteTracking(\n destinationId: number,\n dimension: MpeDimension | number,\n tracking: NoteTracking | number,\n ): void {\n this.native.setControllerNoteTracking(destinationId, dimension, tracking);\n }\n\n /**\n * Read back {@link setControllerNoteTracking} for one dimension, as the\n * canonical name.\n */\n controllerNoteTracking(\n destinationId: number,\n dimension: MpeDimension | number,\n ): NoteTracking | number {\n return this.native.controllerNoteTracking(destinationId, dimension);\n }\n\n /**\n * Set how one MIDI channel (0–15) of a destination's instrument treats a\n * note-on while another note on that channel is still held: `'poly'` takes a\n * new voice each time, `'mono-retrigger'` stops and restarts the note (what\n * GS MONO MODE and CC126 mean), `'mono-legato'` carries the sounding voice\n * and only moves its pitch — a wind player's slur, which no MIDI message can\n * reach by design.\n *\n * `'mono-legato'` is a request, not a guarantee: an engine whose exciter is\n * spent at the onset — anything struck or plucked — and a target pitch below\n * what the engine's delay line can hold both fall back to an ordinary note,\n * which {@link legatoFallbackCount} counts. A channel outside [0,15] and an\n * articulation outside the enum are refused rather than clamped, and so is a\n * destination with no instrument or one whose instrument has no articulation\n * of its own.\n */\n setArticulation(\n destinationId: number,\n channel: number,\n articulation: Articulation | number,\n ): void {\n this.native.setArticulation(destinationId, channel, articulation);\n }\n\n /**\n * Read back {@link setArticulation} as the canonical name. An ordinal this\n * build cannot spell is handed back as the number, the way every other enum\n * leaves this surface.\n */\n articulation(destinationId: number, channel: number): Articulation | number {\n return this.native.articulation(destinationId, channel);\n }\n\n /**\n * How many times a legato continuation was asked for on this destination and\n * refused, so the note started a voice of its own instead. Counted rather\n * than inferred: a refusal sounds like an ordinary note, so nothing in the\n * audio separates \"this engine declines legato\" from \"the mode was never\n * set\". Saturates at 4294967295 rather than wrapping — matching the C ABI, so\n * the same phrase reports the same number on every surface — after which it\n * reads as \"at least this many\".\n *\n * Throws on a destination with no instrument, and on one whose instrument has\n * no articulation of its own — the same two refusals\n * {@link setArticulation} keeps apart. Reporting 0 for the second would read\n * as \"every slur took\", which is the reading this counter exists to prevent.\n */\n legatoFallbackCount(destinationId: number): number {\n return this.native.legatoFallbackCount(destinationId);\n }\n\n /** Install/replace a live non-destructive MIDI-FX insert for one destination. */\n setMidiFx(destinationId: number, configJson: string): void {\n this.native.setMidiFx(destinationId, configJson);\n }\n\n clearMidiFx(destinationId = 0): void {\n this.native.clearMidiFx(destinationId);\n }\n\n /** Enable the engine-owned live MIDI input source for a destination. */\n setMidiInputSource(destinationId = 0): void {\n this.native.setMidiInputSource(destinationId);\n }\n\n clearMidiInputSource(): void {\n this.native.clearMidiInputSource();\n }\n\n midiInputPendingCount(): number {\n return this.native.midiInputPendingCount();\n }\n\n /**\n * Route a destination's (track lane's) MIDI to the external output queue\n * instead of the internal instrument rack, so the track plays an external\n * device. Clearing it restores internal-synth playback.\n */\n setMidiDestinationExternal(destinationId: number, external: boolean): void {\n this.native.setMidiDestinationExternal(destinationId, external);\n }\n\n /**\n * Enable/disable forwarding MIDI clock + transport (start/continue/stop) to\n * the external output queue so external gear tracks the transport tempo.\n */\n setExternalMidiClockEnabled(enabled: boolean): void {\n this.native.setExternalMidiClockEnabled(enabled);\n }\n\n /** Count of external-MIDI events dropped because the output queue was full. */\n externalMidiDroppedCount(): number {\n return this.native.externalMidiDroppedCount();\n }\n\n externalMidiPendingCount(): number {\n return this.native.externalMidiPendingCount();\n }\n\n /**\n * Drain queued external-MIDI events, already lowered to MIDI 1.0 byte\n * messages ready to write to a Web MIDI output port. Call once per audio\n * block / animation frame. `maxRecords` caps the number of output events\n * returned — the shared unit across every surface. Events past the cap stay\n * queued for the next call (lossless); call again to drain the rest.\n *\n * One queued record lowers to at most 4 MIDI 1.0 messages (a MIDI 2.0\n * registered or assignable controller becomes CC 101/100 or 99/98 plus Data\n * Entry 6/38), so a positive `maxRecords` below 4 could never consume a record\n * and is rejected with an `InvalidParameter` `SonareError` instead of\n * returning nothing forever.\n */\n drainExternalMidi(maxRecords = 1024): WasmExternalMidiEvent[] {\n return this.native.drainExternalMidi(maxRecords);\n }\n\n /** Scalar, allocation-free external-MIDI drain for AudioWorklet SAB output. */\n popExternalMidiToScratch(): boolean {\n return this.native.popExternalMidiToScratch();\n }\n\n externalMidiScratchDestinationId(): number {\n return this.native.externalMidiScratchDestinationId();\n }\n\n externalMidiScratchRenderFrame(): number {\n // embind marshals the int64 render frame as a BigInt; the declared `number`\n // has to be a real number or the first consumer that does arithmetic on it\n // dies with \"Cannot mix BigInt\". Same normalization as the telemetry, meter\n // and scope scratch frames.\n return Number(this.native.externalMidiScratchRenderFrame());\n }\n\n externalMidiScratchByteWord(): number {\n return this.native.externalMidiScratchByteWord();\n }\n\n externalMidiScratchByteCount(): number {\n return this.native.externalMidiScratchByteCount();\n }\n\n consumeExternalMidiScratch(): void {\n this.native.consumeExternalMidiScratch();\n }\n\n pushMidiInputNoteOn(\n group: number,\n channel: number,\n note: number,\n velocity: number,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputNoteOn(group, channel, note, velocity, portTimeSamples);\n }\n\n pushMidiInputNoteOff(\n group: number,\n channel: number,\n note: number,\n velocity = 0,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputNoteOff(group, channel, note, velocity, portTimeSamples);\n }\n\n pushMidiInputCc(\n group: number,\n channel: number,\n controller: number,\n value: number,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputCc(group, channel, controller, value, portTimeSamples);\n }\n\n /**\n * Push a live MIDI pitch bend to the engine-owned MIDI input source.\n *\n * `bend14` is unsigned 14-bit with centre 8192 (0..16383) — the dimension is\n * not 7-bit, so a value past 16383 is refused rather than narrowed. The input\n * source must be enabled with {@link setMidiInputSource} first.\n */\n pushMidiInputPitchBend(\n group: number,\n channel: number,\n bend14: number,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputPitchBend(group, channel, bend14, portTimeSamples);\n }\n\n /**\n * Push a live MIDI channel pressure to the engine-owned MIDI input source.\n * `pressure` is 7-bit (0..127). Under MPE this is the member channel's\n * per-note pressure.\n */\n pushMidiInputChannelPressure(\n group: number,\n channel: number,\n pressure: number,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputChannelPressure(group, channel, pressure, portTimeSamples);\n }\n\n /**\n * Push a live MIDI polyphonic key pressure to the engine-owned MIDI input\n * source. `note` and `pressure` are 7-bit (0..127).\n */\n pushMidiInputPolyPressure(\n group: number,\n channel: number,\n note: number,\n pressure: number,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputPolyPressure(group, channel, note, pressure, portTimeSamples);\n }\n\n pushMidiNoteOn(\n destinationId: number,\n group: number,\n channel: number,\n note: number,\n velocity: number,\n renderFrame = -1,\n ): void {\n this.native.pushMidiNoteOn(destinationId, group, channel, note, velocity, renderFrame);\n }\n\n pushMidiNoteOff(\n destinationId: number,\n group: number,\n channel: number,\n note: number,\n velocity = 0,\n renderFrame = -1,\n ): void {\n this.native.pushMidiNoteOff(destinationId, group, channel, note, velocity, renderFrame);\n }\n\n /**\n * Queue an immediate (live) MIDI control change to a MIDI destination\n * (engine kMidiCcImmediate). `group`/`channel` are 0..15; `controller`/`value`\n * are 7-bit (0..127). `renderFrame` is the frame to fire at, or -1 for\n * immediate. Mirrors the Node/Python/C-ABI `pushMidiCc`.\n */\n pushMidiCc(\n destinationId: number,\n group: number,\n channel: number,\n controller: number,\n value: number,\n renderFrame = -1,\n ): void {\n this.native.pushMidiCc(destinationId, group, channel, controller, value, renderFrame);\n }\n\n /**\n * Queue an immediate (live) MIDI pitch bend to a MIDI destination. `bend14`\n * is unsigned 14-bit with centre 8192 (0..16383); `renderFrame` is the frame\n * to fire at, or -1 for immediate. Mirrors the Node/Python/C-ABI\n * `pushMidiPitchBend`.\n */\n pushMidiPitchBend(\n destinationId: number,\n group: number,\n channel: number,\n bend14: number,\n renderFrame = -1,\n ): void {\n this.native.pushMidiPitchBend(destinationId, group, channel, bend14, renderFrame);\n }\n\n /**\n * Queue an immediate (live) MIDI channel pressure to a MIDI destination.\n * `pressure` is 7-bit (0..127); `renderFrame` is the frame to fire at, or -1\n * for immediate. Mirrors the Node/Python/C-ABI `pushMidiChannelPressure`.\n */\n pushMidiChannelPressure(\n destinationId: number,\n group: number,\n channel: number,\n pressure: number,\n renderFrame = -1,\n ): void {\n this.native.pushMidiChannelPressure(destinationId, group, channel, pressure, renderFrame);\n }\n\n /**\n * Queue an immediate (live) MIDI polyphonic key pressure to a MIDI\n * destination. `note` and `pressure` are 7-bit (0..127); `renderFrame` is the\n * frame to fire at, or -1 for immediate. Mirrors the Node/Python/C-ABI\n * `pushMidiPolyPressure`.\n */\n pushMidiPolyPressure(\n destinationId: number,\n group: number,\n channel: number,\n note: number,\n pressure: number,\n renderFrame = -1,\n ): void {\n this.native.pushMidiPolyPressure(destinationId, group, channel, note, pressure, renderFrame);\n }\n\n /**\n * Queue an immediate (live) raw UMP message to a MIDI destination. `words` is\n * 1 to 4 words, most significant first, and its length must match the message\n * type of `words[0]`. MIDI 2.0 channel-voice messages (MT 0x4) arrive at full\n * width; SysEx7 / data messages (MT 0x3 / 0x5) are refused, use\n * {@link pushMidiSysex}. Throws when the slot ring or command queue is full\n * (retry after a process block). `renderFrame` is the render-frame time to\n * apply, or -1 for immediate. A bare number is accepted as a one-word\n * message.\n */\n pushMidiUmp(destinationId: number, words: UmpWords | number, renderFrame = -1): void {\n const list = typeof words === 'number' ? [words] : words;\n this.native.pushMidiUmp(destinationId, assertUmpWords('pushMidiUmp', list), renderFrame);\n }\n\n /**\n * Push one raw UMP message (1 to 4 words) to the engine-owned MIDI input\n * source. The message rules match {@link pushMidiUmp}. `portTimeSamples` is\n * the port timestamp in samples.\n */\n pushMidiInputUmp(words: UmpWords, portTimeSamples = 0): void {\n this.native.pushMidiInputUmp(assertUmpWords('pushMidiInputUmp', words), portTimeSamples);\n }\n\n /**\n * Queue an immediate (live) MIDI SysEx frame to a MIDI destination. `data` is\n * the full message including the leading 0xF0 and trailing 0xF7 (1..512\n * bytes). `renderFrame` is the frame to fire at, or -1 for immediate. Mirrors\n * the Node/Python/C-ABI `pushMidiSysex`.\n */\n pushMidiSysex(destinationId: number, data: Uint8Array, renderFrame = -1): void {\n this.native.pushMidiSysex(destinationId, data, renderFrame);\n }\n\n /**\n * Queue a MIDI panic (all-notes-off) releasing every sounding note at\n * `renderFrame` (-1 = immediate). Mirrors the C-ABI `pushMidiPanic`.\n */\n pushMidiPanic(renderFrame = -1): void {\n this.native.pushMidiPanic(renderFrame);\n }\n\n /**\n * Remove all registered parameters (and their automation lanes). Control-thread\n * only; not realtime-safe. Mirrors the C-ABI `clearParameters`.\n */\n clearParameters(): void {\n this.native.clearParameters();\n }\n\n /** Read back the current transport state snapshot. */\n getTransportState(): EngineTransportState {\n return this.native.getTransportState();\n }\n\n play(renderFrame = -1): void {\n this.native.play(renderFrame);\n }\n\n stop(renderFrame = -1): void {\n this.native.stop(renderFrame);\n }\n\n seekSample(timelineSample: number, renderFrame = -1): void {\n this.native.seekSample(timelineSample, renderFrame);\n }\n\n /**\n * Snaps every in-flight parameter ramp (engine-level smoothed params, mixer\n * lane fader/pan/gate, bus gains) to its target value. Offline renders call\n * this after a priming process() block so the first audible block renders at\n * settled values instead of ramping in from defaults.\n */\n settleParameters(): void {\n this.native.settleParameters();\n }\n\n /** Snap only insert automation slots after structural replay. */\n settleInsertParameters(): void {\n this.native.settleInsertParameters();\n }\n\n /** Drains queued commands on an offline/control-only engine immediately. */\n flushControlCommands(): void {\n this.native.flushControlCommands();\n }\n\n /** Applies commands already due on a control-only mirror, retaining future commands. */\n applyCommandsDueNowPreservingFuture(): void {\n this.native.applyCommandsDueNowPreservingFuture();\n }\n\n seekPpq(ppq: number, renderFrame = -1): void {\n this.native.seekPpq(ppq, renderFrame);\n }\n\n /** Set a finite tempo in the range (0, 100000] BPM. */\n setTempo(bpm: number): void {\n this.native.setTempo(bpm);\n }\n\n setTempoSegments(segments: readonly EngineTempoSegment[]): void {\n this.native.setTempoSegments([...segments]);\n }\n\n setTimeSignature(numerator: number, denominator: number): void {\n this.native.setTimeSignature(numerator, denominator);\n }\n\n setTimeSignatureSegments(segments: readonly EngineTimeSignatureSegment[]): void {\n this.native.setTimeSignatureSegments([...segments]);\n }\n\n sampleAtPpq(ppq: number): number {\n return Number(this.native.sampleAtPpq(ppq));\n }\n\n setLoop(startPpq: number, endPpq: number, enabled = true): void {\n this.native.setLoop(startPpq, endPpq, enabled);\n }\n\n addParameter(info: EngineParameterInfo): void {\n this.native.addParameter(info);\n }\n\n parameterCount(): number {\n return this.native.parameterCount();\n }\n\n parameterInfoByIndex(index: number): Required<EngineParameterInfo> {\n return this.native.parameterInfoByIndex(index);\n }\n\n parameterInfo(id: number): Required<EngineParameterInfo> {\n return this.native.parameterInfo(id);\n }\n\n setAutomationLane(paramId: number, points: EngineAutomationPoint[]): void {\n this.native.setAutomationLane(paramId, points);\n }\n\n automationLaneCount(): number {\n return this.native.automationLaneCount();\n }\n\n setMarkers(markers: EngineMarker[]): void {\n this.native.setMarkers(markers);\n }\n\n markerCount(): number {\n return this.native.markerCount();\n }\n\n markerByIndex(index: number): EngineMarker {\n return this.native.markerByIndex(index);\n }\n\n marker(id: number): EngineMarker {\n return this.native.marker(id);\n }\n\n seekMarker(markerId: number, renderFrame = -1): void {\n this.native.seekMarker(markerId, renderFrame);\n }\n\n setLoopFromMarkers(startMarkerId: number, endMarkerId: number): void {\n this.native.setLoopFromMarkers(startMarkerId, endMarkerId);\n }\n\n /** Set a metronome config; click lengths are limited to one second. */\n setMetronome(config: EngineMetronomeConfig): void {\n this.native.setMetronome(config);\n }\n\n metronome(): Required<EngineMetronomeConfig> {\n return this.native.metronome();\n }\n\n countInEndSample(startSample: number, bars: number): number {\n return Number(this.native.countInEndSample(startSample, bars));\n }\n\n setGraph(spec: EngineGraphSpec): void {\n this.native.setGraph(spec);\n }\n\n graphNodeCount(): number {\n return this.native.graphNodeCount();\n }\n\n graphConnectionCount(): number {\n return this.native.graphConnectionCount();\n }\n\n setClips(clips: EngineClip[]): void {\n this.native.setClips(\n clips.map((clip) => ({\n ...clip,\n pageProvider:\n typeof clip.pageProvider === 'object' && clip.pageProvider !== null\n ? clip.pageProvider.id\n : clip.pageProvider,\n })),\n );\n }\n\n /**\n * Returns the PCM generated for a tempo-sync clip by the control-thread\n * setter, or `null` when the clip did not require a tempo-sync bake.\n */\n prebakedClipChannels(clipId: number): Float32Array[] | null {\n return this.native.prebakedClipChannels(clipId);\n }\n\n clipCount(): number {\n return this.native.clipCount();\n }\n\n /**\n * Normalizes each send's pre/post tap point to the integer the native layer\n * reads (defaults to post-fader when omitted). Shared by track lanes and\n * buses, which carry the same send shape.\n */\n private static normalizeSends(sends: EngineTrackSend[]): EngineTrackSend[] {\n return sends.map((send) => ({\n ...send,\n // Post-fader (0) is the default for an omitted sendTiming.\n sendTiming: send.sendTiming === undefined ? 0 : sendTimingCode(send.sendTiming),\n }));\n }\n\n setTrackLanes(lanes: Array<number | EngineTrackLane>): void {\n this.native.setTrackLanes(\n lanes.map((lane) => {\n if (typeof lane === 'number') {\n return { trackId: lane };\n }\n if (!lane.sends) {\n return lane;\n }\n return { ...lane, sends: RealtimeEngine.normalizeSends(lane.sends) };\n }),\n );\n }\n\n /**\n * Keys one insert of a lane strip from another lane's post-strip audio\n * (ducking/sidechainRouter inserts). sourceTrackId 0 removes the binding.\n */\n setLaneSidechain(trackId: number, insertIndex: number, sourceTrackId: number): void {\n this.native.setLaneSidechain(trackId, insertIndex, sourceTrackId);\n }\n\n setTrackBuses(buses: EngineBus[]): void {\n // Array.isArray guards a caller-fabricated array-like (e.g. `{ length }`)\n // meant to probe the native array-length read: passing it through\n // unmodified lets that guard see the real (missing) length rather than\n // failing here on a `.map` that array-likes do not implement.\n this.native.setTrackBuses(\n Array.isArray(buses)\n ? buses.map((bus) =>\n bus.sends ? { ...bus, sends: RealtimeEngine.normalizeSends(bus.sends) } : bus,\n )\n : buses,\n );\n }\n\n /**\n * Keys one insert of a bus strip from a track lane or another bus\n * (ducking/sidechainRouter inserts). `sourceId` 0 removes the binding.\n */\n setBusSidechain(\n busId: number,\n insertIndex: number,\n sourceKind: SidechainSourceKind | number,\n sourceId: number,\n ): void {\n this.native.setBusSidechain(busId, insertIndex, sidechainSourceKindCode(sourceKind), sourceId);\n }\n\n /**\n * Keys one insert of the master strip from a track lane or a bus. Same\n * source rules as {@link setBusSidechain}.\n */\n setMasterSidechain(\n insertIndex: number,\n sourceKind: SidechainSourceKind | number,\n sourceId: number,\n ): void {\n this.native.setMasterSidechain(insertIndex, sidechainSourceKindCode(sourceKind), sourceId);\n }\n\n setBusStripJson(busId: number, sceneJson: string): void {\n try {\n JSON.parse(sceneJson);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'invalid bus strip JSON';\n throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);\n }\n this.native.setBusStripJson(busId, sceneJson);\n }\n\n setTrackStripJson(trackId: number, sceneJson: string): void {\n try {\n JSON.parse(sceneJson);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'invalid track strip JSON';\n throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);\n }\n this.native.setTrackStripJson(trackId, sceneJson);\n }\n\n setTrackStripEqBand(trackId: number, bandIndex: number, band: EqBand | string): void {\n this.native.setTrackStripEqBandJson(\n trackId,\n bandIndex,\n typeof band === 'string' ? band : JSON.stringify(band),\n );\n }\n\n setTrackStripEqBandJson(trackId: number, bandIndex: number, bandJson: string): void {\n this.native.setTrackStripEqBandJson(trackId, bandIndex, bandJson);\n }\n\n setTrackStripInsertBypassed(\n trackId: number,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n this.native.setTrackStripInsertBypassed(trackId, insertIndex, bypassed, resetOnBypass);\n }\n\n /** Bus-strip counterpart of {@link setTrackStripEqBand}. */\n setBusStripEqBand(busId: number, bandIndex: number, band: EqBand | string): void {\n this.native.setBusStripEqBandJson(\n busId,\n bandIndex,\n typeof band === 'string' ? band : JSON.stringify(band),\n );\n }\n\n setBusStripEqBandJson(busId: number, bandIndex: number, bandJson: string): void {\n this.native.setBusStripEqBandJson(busId, bandIndex, bandJson);\n }\n\n setMasterStripJson(sceneJson: string): void {\n try {\n JSON.parse(sceneJson);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'invalid master strip JSON';\n throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);\n }\n this.native.setMasterStripJson(sceneJson);\n }\n\n setMasterStripEqBand(bandIndex: number, band: EqBand | string): void {\n this.native.setMasterStripEqBandJson(\n bandIndex,\n typeof band === 'string' ? band : JSON.stringify(band),\n );\n }\n\n setMasterStripEqBandJson(bandIndex: number, bandJson: string): void {\n this.native.setMasterStripEqBandJson(bandIndex, bandJson);\n }\n\n setMasterStripInsertBypassed(\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n this.native.setMasterStripInsertBypassed(insertIndex, bypassed, resetOnBypass);\n }\n\n /**\n * Changes one track-strip insert parameter in realtime, addressed by the\n * processor's JSON-key parameter name — one of the entries\n * {@link masteringInsertParamInfo} reports with a non-null `id`; a\n * construction-only entry (`id` null) takes effect only when the insert is\n * built. Applied at the next block head via the engine command queue; safe\n * during playback. Throws if the track, insert, or name is unknown, the\n * param is not realtime-safe, or the command queue is full.\n */\n setTrackStripInsertParamByName(\n trackId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n this.native.setTrackStripInsertParamByName(trackId, insertIndex, paramName, value);\n }\n\n /** Apply a live insert edit on this engine's owning thread without draining its command queue. */\n applyTrackStripInsertParamByNameNow(\n trackId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): boolean {\n return this.native.applyTrackStripInsertParamByNameNow(trackId, insertIndex, paramName, value);\n }\n\n /** Restore a retained insert value exactly after a strip scene is replayed. */\n restoreTrackStripInsertParamByName(\n trackId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n this.native.restoreTrackStripInsertParamByName(trackId, insertIndex, paramName, value);\n }\n\n /** Master-strip counterpart of {@link setTrackStripInsertParamByName}. */\n setMasterStripInsertParamByName(insertIndex: number, paramName: string, value: number): void {\n this.native.setMasterStripInsertParamByName(insertIndex, paramName, value);\n }\n\n applyMasterStripInsertParamByNameNow(\n insertIndex: number,\n paramName: string,\n value: number,\n ): boolean {\n return this.native.applyMasterStripInsertParamByNameNow(insertIndex, paramName, value);\n }\n\n restoreMasterStripInsertParamByName(insertIndex: number, paramName: string, value: number): void {\n this.native.restoreMasterStripInsertParamByName(insertIndex, paramName, value);\n }\n\n /** Bus-strip counterpart of {@link setTrackStripInsertParamByName}. */\n setBusStripInsertParamByName(\n busId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n this.native.setBusStripInsertParamByName(busId, insertIndex, paramName, value);\n }\n\n applyBusStripInsertParamByNameNow(\n busId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): boolean {\n return this.native.applyBusStripInsertParamByNameNow(busId, insertIndex, paramName, value);\n }\n\n restoreBusStripInsertParamByName(\n busId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n this.native.restoreBusStripInsertParamByName(busId, insertIndex, paramName, value);\n }\n\n /**\n * Forgets the remembered manual insert-parameter values of one track strip\n * and discards its queued insert edits. Call before {@link setTrackStripJson}\n * replaces the strip when its old values must not carry over; the setter\n * never does this itself, since a queued edit may already target the new chain.\n */\n clearTrackInsertParameterBases(trackId: number): void {\n this.native.clearTrackInsertParameterBases(trackId);\n }\n\n clearBusInsertParameterBases(busId: number): void {\n this.native.clearBusInsertParameterBases(busId);\n }\n\n clearMasterInsertParameterBases(): void {\n this.native.clearMasterInsertParameterBases();\n }\n\n /** Bus-strip counterpart of {@link setTrackStripInsertBypassed}. */\n setBusStripInsertBypassed(\n busId: number,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n this.native.setBusStripInsertBypassed(busId, insertIndex, bypassed, resetOnBypass);\n }\n\n /**\n * Resolves a track-lane insert parameter (by its JSON-key name) to the\n * reserved automation id usable with `setAutomationLane` / `setParameter`.\n * Returns `-1` when the track, insert, or name is unknown. (The Python binding\n * raises a `SonareError` for an unknown id where Node/WASM return the `-1`\n * sentinel.)\n *\n * This trio is how a mastering processor gets time-varying automation: the\n * `eq.*`, `dynamics.*`, `saturation.*`, `spectral.*`, `stereo.*`,\n * `maximizer.*` and `multiband.*` processors are all available as strip\n * inserts, so placing one on a strip and resolving its parameter here drives\n * it at audio-block precision, live and offline alike. The whole-signal\n * stages of the offline mastering chain (`repair.*`, `loudness`, and the\n * match stages) have no insert form and no automation id: they buffer the\n * entire signal by construction and do not run on the realtime path.\n */\n resolveTrackInsertAutomationId(trackId: number, insertIndex: number, paramName: string): number {\n return this.native.resolveTrackInsertAutomationId(trackId, insertIndex, paramName);\n }\n\n resolveMasterInsertAutomationId(insertIndex: number, paramName: string): number {\n return this.native.resolveMasterInsertAutomationId(insertIndex, paramName);\n }\n\n resolveBusInsertAutomationId(busId: number, insertIndex: number, paramName: string): number {\n return this.native.resolveBusInsertAutomationId(busId, insertIndex, paramName);\n }\n\n /**\n * Resolves a hosted instrument's continuous parameter (by its JSON-key name)\n * to the reserved automation id usable with `setAutomationLane` /\n * `setParameter`, so an instrument parameter is driven at audio-block\n * precision exactly like a strip insert. Returns `-1` when the destination\n * has no bound instrument, the instrument exposes no automatable parameters,\n * or the name is unknown.\n *\n * For the NativeSynth ({@link setSynthInstrument}) the names are the\n * continuous {@link SynthPatch} fields: `gain`, `busDrive`, `cutoffHz`,\n * `resonanceQ`, `drive`, `keyTrack`, `envToCutoffCents`, `velToCutoffCents`,\n * `ampAttackMs`, `ampDecayMs`, `ampSustain`, `ampReleaseMs`,\n * `filterAttackMs`, `filterDecayMs`, `filterSustain`, `filterReleaseMs`,\n * `lfoRateHz`, `lfoToPitchCents`, `lfo2RateHz`, `glideMs`, `bodyMix`,\n * `stereoSpread`, `detuneCents`, `driftCents`, `pitchOffsetCents`,\n * `hpCutoffHz`, `sampleHoldHz`, `bitDepth`.\n *\n * Structural fields (`preset`, `engineMode`, `waveform`, `filterModel`,\n * `unison`, `polyphony`, `body`, `modRoutings`) are not automatable and\n * return `-1`: they resize voice pools or swap DSP topology, which is not\n * audio-thread safe. Rebind the instrument with a new patch instead.\n *\n * `gain`, `busDrive`, `cutoffHz`, `resonanceQ`, `envToCutoffCents`,\n * `lfoToPitchCents` and `pitchOffsetCents` reach voices that are already\n * sounding from the next block; the rest are cached into per-voice state at\n * note-on and take effect from the next note, so a lane that moves one of\n * them under a held note looks inert until the next one speaks — that is the\n * behaviour, not a dropped write.\n *\n * The id survives an unbind/rebind of the same destination and applies\n * nothing while that destination is unbound.\n */\n resolveInstrumentAutomationId(destinationId: number, paramName: string): number {\n return this.native.resolveInstrumentAutomationId(destinationId, paramName);\n }\n\n /** Sets a track lane strip's pan position in realtime (glitch-free). */\n setTrackStripPan(trackId: number, pan: number): void {\n this.native.setTrackStripPan(trackId, pan);\n }\n\n /** Sets a track lane strip's pan law in realtime. */\n setTrackStripPanLaw(trackId: number, panLaw: PanLawInput): void {\n this.native.setTrackStripPanLaw(trackId, panLawCode(panLaw));\n }\n\n /** Sets a track lane strip's pan mode in realtime. */\n setTrackStripPanMode(trackId: number, panMode: PanMode | number): void {\n this.native.setTrackStripPanMode(trackId, panModeCode(panMode));\n }\n\n /** Sets a track lane strip's dual-pan left/right positions in realtime. */\n setTrackStripDualPan(trackId: number, leftPan: number, rightPan: number): void {\n this.native.setTrackStripDualPan(trackId, leftPan, rightPan);\n }\n\n /**\n * Sets a bus strip's output pan position in realtime (glitch-free). Throws\n * for an unknown bus or one wider than stereo.\n */\n setBusStripPan(busId: number, pan: number): void {\n this.native.setBusStripPan(busId, pan);\n }\n\n /** Sets a bus strip's pan law in realtime. */\n setBusStripPanLaw(busId: number, panLaw: PanLawInput): void {\n this.native.setBusStripPanLaw(busId, panLawCode(panLaw));\n }\n\n /** Sets a bus strip's pan mode in realtime. */\n setBusStripPanMode(busId: number, panMode: PanMode | number): void {\n this.native.setBusStripPanMode(busId, panModeCode(panMode));\n }\n\n /** Sets a bus strip's dual-pan left/right positions in realtime. */\n setBusStripDualPan(busId: number, leftPan: number, rightPan: number): void {\n this.native.setBusStripDualPan(busId, leftPan, rightPan);\n }\n\n /**\n * Sets a track lane strip's inter-channel alignment delay (whole samples).\n * Adjusts strip latency, so PDC and reported graph latency are refreshed.\n */\n setTrackStripChannelDelaySamples(trackId: number, delaySamples: number): void {\n this.native.setTrackStripChannelDelaySamples(trackId, delaySamples);\n }\n\n createClipPageProvider(\n numChannels: number,\n numSamples: number,\n pageFrames: number,\n ): ClipPageProvider {\n const id = this.native.createClipPageProvider(numChannels, numSamples, pageFrames);\n return new ClipPageProvider(this, id);\n }\n\n supplyClipPage(providerId: number, pageIndex: number, channels: Float32Array[]): void {\n this.native.supplyClipPage(providerId, pageIndex, channels);\n }\n\n clearClipPage(providerId: number, pageIndex: number): void {\n this.native.clearClipPage(providerId, pageIndex);\n }\n\n destroyClipPageProvider(providerId: number): void {\n this.native.destroyClipPageProvider(providerId);\n }\n\n popClipPageRequest(): ClipPageRequest | null {\n return this.native.popClipPageRequest();\n }\n\n /**\n * Moves one native request into the binding's persistent scalar scratch.\n * This avoids creating an embind JS object in AudioWorklet process().\n */\n popClipPageRequestToScratch(): boolean {\n return this.native.popClipPageRequestToScratch();\n }\n\n clipPageRequestScratchClipId(): number {\n return this.native.clipPageRequestScratchClipId();\n }\n\n clipPageRequestScratchSample(): number {\n return this.native.clipPageRequestScratchSample();\n }\n\n /** Cumulative page misses dropped because the native bounded request queue was full. */\n clipPageRequestOverflowCount(): number {\n return this.native.clipPageRequestOverflowCount();\n }\n\n /** Cumulative warp-stretch requests dropped because the native queue was full. */\n warpStretchOverflowCount(): number {\n return this.native.warpStretchOverflowCount();\n }\n\n /**\n * Sets the number of concurrent time-stretch voices. `voices` must be an\n * integer in `[0, 64]`; a non-integer, negative, or larger value throws and\n * leaves the capacity unchanged. Default is 8. Capacity 0 disables\n * time-stretch, so every warped clip plays resampled instead and none of\n * that counts toward {@link warpStretchOverflowCount}. A change applied\n * while the engine is running restarts the splice state of any clip\n * stretching through a voice at that moment. Control-thread only.\n */\n setWarpVoiceCapacity(voices: number): void {\n this.native.setWarpVoiceCapacity(voices);\n }\n\n /** Reads the current time-stretch voice capacity (default 8). */\n warpVoiceCapacity(): number {\n return this.native.warpVoiceCapacity();\n }\n\n /**\n * Sets the clip-page look-ahead window in timeline frames.\n *\n * The player reports the pages it is *about to* read that are not resident\n * yet, so a streaming host can service them before the audio thread reaches\n * them. Without look-ahead a page miss is only reported after the read\n * already produced silence, which costs one block of silence at every page\n * boundary the host has not primed — the reason a sliding-window streamer\n * cannot keep a live playhead fed from miss reports alone.\n *\n * Look-ahead requests drain through the same `popClipPageRequest` queue and\n * are queued *after* the block's genuine misses, so a host that keeps only\n * the newest request per clip (as {@link ClipPageStreamer} does) tracks the\n * look-ahead frontier.\n *\n * `prepare` defaults this to half a second at the engine's sample rate. `0`\n * disables the look-ahead. A clip whose pages are all resident produces no\n * requests at all, with or without look-ahead. Safe to call during playback.\n */\n setClipPagePrefetchFrames(frames: number): void {\n this.native.setClipPagePrefetchFrames(frames);\n }\n\n /** Current clip-page look-ahead window in timeline frames. */\n clipPagePrefetchFrames(): number {\n return this.native.clipPagePrefetchFrames();\n }\n\n setCaptureBuffer(numChannels: number, capacityFrames: number): void {\n this.native.setCaptureBuffer(numChannels, capacityFrames);\n }\n\n armCapture(armed = true): void {\n this.native.armCapture(armed);\n }\n\n setCapturePunch(startSample: number, endSample: number, enabled = true): void {\n this.native.setCapturePunch(startSample, endSample, enabled);\n }\n\n setCaptureSource(source: EngineCaptureSource): void {\n this.native.setCaptureSource(source);\n }\n\n /** Positive values delay capture relative to the punch window. */\n setRecordOffsetSamples(offsetSamples: number): void {\n this.native.setRecordOffsetSamples(offsetSamples);\n }\n\n setInputMonitor(enabled: boolean, gain = 1): void {\n this.native.setInputMonitor(enabled, gain);\n }\n\n resetCapture(): void {\n this.native.resetCapture();\n }\n\n captureStatus(): EngineCaptureStatus {\n return this.native.captureStatus();\n }\n\n capturedAudio(): Float32Array[] {\n return this.native.capturedAudio();\n }\n\n /**\n * Renders in place, adding engine output to `channels`. Zero each plane first\n * when it contains no upstream input.\n */\n process(channels: Float32Array[]): Float32Array[] {\n return this.native.process(channels);\n }\n\n /**\n * Allocates persistent per-channel WASM-heap scratch for the zero-copy\n * `getChannelBuffer` / `processPrepared` realtime path. Call once (off the\n * audio thread) before driving `processPrepared` from an AudioWorklet so the\n * render callback never allocates on the C++/JS heap.\n */\n prepareChannels(numChannels: number, maxFrames: number): void {\n this.native.prepareChannels(numChannels, maxFrames);\n }\n\n /**\n * Returns a Float32Array view onto the persistent WASM-heap scratch for one\n * channel (valid for up to `numFrames`). Fill it, call `processPrepared`, then\n * read the same view back. Re-acquire after WASM memory growth.\n */\n getChannelBuffer(channel: number, numFrames: number): Float32Array {\n return this.native.getChannelBuffer(channel, numFrames);\n }\n\n /**\n * Runs the engine in place over the prepared per-channel scratch buffers.\n * Zero each active span first when it contains no upstream input.\n * Allocation-free: safe to call on the AudioWorklet render thread after\n * `prepareChannels`.\n */\n processPrepared(numFrames: number): void {\n this.native.processPrepared(numFrames);\n }\n\n /**\n * Allocates the cue-bus counterpart of {@link prepareChannels}. Needed only\n * when PFL/AFL monitoring must reach a separate output: `processPrepared`\n * folds the cue bus into the program output, while\n * {@link processPreparedWithMonitor} keeps the two apart. Call once, off the\n * audio thread, with at least as many channels as `prepareChannels` got.\n */\n prepareMonitorChannels(numChannels: number, maxFrames: number): void {\n this.native.prepareMonitorChannels(numChannels, maxFrames);\n }\n\n /**\n * Returns a Float32Array view onto the persistent cue-bus scratch for one\n * channel (valid for up to `numFrames`). Read it after\n * {@link processPreparedWithMonitor}. Re-acquire after WASM memory growth.\n */\n getMonitorChannelBuffer(channel: number, numFrames: number): Float32Array {\n return this.native.getMonitorChannelBuffer(channel, numFrames);\n }\n\n /**\n * Runs the engine in place over the prepared scratch, writing the cue bus to\n * the monitor scratch instead of folding it into the program output.\n * Allocation-free: safe on the AudioWorklet render thread after\n * `prepareChannels` and `prepareMonitorChannels`.\n */\n processPreparedWithMonitor(numFrames: number): void {\n this.native.processPreparedWithMonitor(numFrames);\n }\n\n processWithMonitor(channels: Float32Array[]): WasmEngineProcessWithMonitorResult {\n return this.native.processWithMonitor(channels);\n }\n\n /**\n * Render `channels` offline from the current transport position. Requesting\n * more planes than `prepare` reserved throws an `InvalidParameter`\n * `SonareError` rather than returning silence that reads as a finished render.\n *\n * Set `finalize: false` to render one chunk of a longer timeline; see\n * {@link RenderOfflineRequest.finalize} and {@link finishOfflineRender}.\n */\n renderOffline(request: RenderOfflineRequest): Float32Array[];\n renderOffline(channels: Float32Array[], blockSize?: number): Float32Array[];\n renderOffline(\n channelsOrRequest: Float32Array[] | RenderOfflineRequest,\n blockSize = 128,\n ): Float32Array[] {\n const request = normalizeRenderOfflineRequest(channelsOrRequest, blockSize);\n return this.native.renderOffline(request.channels, request.blockSize, request.finalize);\n }\n\n /**\n * End a chunked offline render: release every note the sequencer still holds\n * and flush the PDC / alignment delay lines. Required after\n * `renderOffline({ finalize: false })`; the finalizing form does it itself.\n *\n * Skipping it leaves every note still sounding at the last chunk held. On an\n * engine-internal instrument the tail simply never releases; on a destination\n * marked external ({@link RealtimeEngine.setMidiDestinationExternal}) the\n * note-ons already left through the external MIDI queue, so the note-offs\n * emitted here are the only ones the receiving device will get and the notes\n * otherwise hang outside the engine.\n */\n finishOfflineRender(): void {\n this.native.finishOfflineRender();\n }\n\n /**\n * Bounce the timeline to an interleaved buffer. `numChannels` above the\n * prepared channel count throws an `InvalidParameter` `SonareError`.\n */\n bounceOffline(options: EngineBounceOptions): EngineBounceResult {\n return this.native.bounceOffline(options);\n }\n\n /**\n * Freeze the current graph to audio. `numChannels` above the prepared channel\n * count throws an `InvalidParameter` `SonareError`.\n */\n freezeOffline(options: EngineFreezeOptions): EngineFreezeResult {\n return this.native.freezeOffline(options);\n }\n\n drainTelemetry(maxRecords = 1024): EngineTelemetry[] {\n return this.native.drainTelemetry(maxRecords);\n }\n\n popTelemetryToScratch(): boolean {\n return this.native.popTelemetryToScratch();\n }\n\n telemetryScratchType(): number {\n return this.native.telemetryScratchType();\n }\n\n telemetryScratchError(): number {\n return this.native.telemetryScratchError();\n }\n\n telemetryScratchRenderFrame(): number {\n return Number(this.native.telemetryScratchRenderFrame());\n }\n\n telemetryScratchTimelineSample(): number {\n return Number(this.native.telemetryScratchTimelineSample());\n }\n\n telemetryScratchAudibleTimelineSample(): number {\n return Number(this.native.telemetryScratchAudibleTimelineSample());\n }\n\n telemetryScratchGraphLatencySamplesQ8(): number {\n return this.native.telemetryScratchGraphLatencySamplesQ8();\n }\n\n telemetryScratchValue(): number {\n return this.native.telemetryScratchValue();\n }\n\n popMeterTelemetryToScratch(): boolean {\n return this.native.popMeterTelemetryToScratch();\n }\n meterScratchTargetId(): number {\n return this.native.meterScratchTargetId();\n }\n meterScratchRenderFrame(): number {\n return Number(this.native.meterScratchRenderFrame());\n }\n meterScratchValue(field: number): number {\n return this.native.meterScratchValue(field);\n }\n\n drainMeterTelemetry(maxRecords = 1024): EngineMeterTelemetry[] {\n return this.native.drainMeterTelemetry(maxRecords);\n }\n\n /**\n * Drains pending meter telemetry as per-plane (wide) records for a surround\n * target. Use this for a surround mix target; {@link drainMeterTelemetry}\n * stays the stereo fast path. The two share one queue — call only one per\n * target. The live AudioWorklet path owns the queue via the stereo drain, so\n * this wide drain is for an offline (non-worklet) engine instance; per-plane\n * surround meters are not delivered over the live worklet meter ring.\n */\n drainMeterTelemetryWide(maxRecords = 1024): EngineMeterTelemetryWide[] {\n return this.native.drainMeterTelemetryWide(maxRecords);\n }\n\n /**\n * Enables per-target spectrum + vectorscope capture. @param intervalFrames is\n * the minimum render-frame gap between snapshots (0 disables). @param bandCount\n * is the FFT band resolution (1..64); changing it re-prepares the tap. Returns\n * the band count actually applied.\n */\n configureScopeTelemetry(intervalFrames: number, bandCount: number): number {\n return this.native.configureScopeTelemetry(intervalFrames, bandCount);\n }\n\n /** Drains pending spectrum + vectorscope snapshots (per mix target). */\n drainScopeTelemetry(maxRecords = 1024): EngineScopeTelemetry[] {\n return this.native.drainScopeTelemetry(maxRecords);\n }\n\n popScopeTelemetryToScratch(): boolean {\n return this.native.popScopeTelemetryToScratch();\n }\n scopeScratchTargetId(): number {\n return this.native.scopeScratchTargetId();\n }\n scopeScratchRenderFrame(): number {\n return Number(this.native.scopeScratchRenderFrame());\n }\n scopeScratchBandCount(): number {\n return this.native.scopeScratchBandCount();\n }\n scopeScratchBand(index: number): number {\n return this.native.scopeScratchBand(index);\n }\n scopeScratchPointCount(): number {\n return this.native.scopeScratchPointCount();\n }\n scopeScratchPointLeft(index: number): number {\n return this.native.scopeScratchPointLeft(index);\n }\n scopeScratchPointRight(index: number): number {\n return this.native.scopeScratchPointRight(index);\n }\n\n /** Release the underlying WASM object. Idempotent, as the Node facade is. */\n destroy(): void {\n if (this.released) {\n return;\n }\n this.released = true;\n this.native.delete();\n }\n\n /** Alias for {@link destroy}, matching embind's own release method name. */\n delete(): void {\n this.destroy();\n }\n}\n\nexport class ClipPageProvider {\n private disposed = false;\n\n constructor(\n private readonly engine: RealtimeEngine,\n readonly id: number,\n ) {}\n\n supply(pageIndex: number, channels: Float32Array[]): void {\n if (this.disposed) {\n throw new Error('ClipPageProvider is destroyed');\n }\n this.engine.supplyClipPage(this.id, pageIndex, channels);\n }\n\n clear(pageIndex: number): void {\n if (this.disposed) {\n return;\n }\n this.engine.clearClipPage(this.id, pageIndex);\n }\n\n destroy(): void {\n if (this.disposed) {\n return;\n }\n this.disposed = true;\n this.engine.destroyClipPageProvider(this.id);\n }\n}\n","import { getSonareModule } from './module_state';\nimport { assertFiniteScalar } from './validation';\n\n// ============================================================================\n// Editing — 12-TET scale quantizer\n// ============================================================================\n\n/**\n * Snap a MIDI value to the nearest pitch class enabled by `modeMask`.\n *\n * `modeMask` is a 12-bit mask. For natural C major use `0b101010110101`.\n * `referenceMidi` defaults to A4 (69) when passed as 0.\n */\nexport function scaleQuantizeMidi(\n root: number,\n modeMask: number,\n midi: number,\n referenceMidi = 0,\n): number {\n assertFiniteScalar('scaleQuantizeMidi', midi, 'midi');\n assertFiniteScalar('scaleQuantizeMidi', referenceMidi, 'referenceMidi');\n return getSonareModule().scaleQuantizeMidi(root, modeMask, midi, referenceMidi);\n}\n\nexport function scaleCorrectionSemitones(\n root: number,\n modeMask: number,\n midi: number,\n referenceMidi = 0,\n): number {\n assertFiniteScalar('scaleCorrectionSemitones', midi, 'midi');\n assertFiniteScalar('scaleCorrectionSemitones', referenceMidi, 'referenceMidi');\n return getSonareModule().scaleCorrectionSemitones(root, modeMask, midi, referenceMidi);\n}\n\nexport function scalePitchClassEnabled(\n root: number,\n modeMask: number,\n pitchClass: number,\n): boolean {\n return getSonareModule().scalePitchClassEnabled(root, modeMask, pitchClass);\n}\n","import { resolveOrdinalInRange } from './codes';\nimport { getSonareModule } from './module_state';\nimport type { ChordQuality, PitchClass } from './public_types';\nimport type { WasmStreamAnalyzer } from './sonare.js';\nimport type {\n AnalyzerStats,\n FrameBuffer,\n StreamConfig,\n StreamConfigDefaults,\n StreamFramesI16,\n StreamFramesU8,\n StreamQuantizeConfig,\n} from './stream_types';\n\n// ============================================================================\n// StreamAnalyzer Class\n// ============================================================================\n\nexport function streamAnalyzerConfigDefaults(): StreamConfigDefaults {\n return getSonareModule().streamAnalyzerConfigDefault();\n}\n\n/**\n * Real-time streaming audio analyzer.\n *\n * @example\n * ```typescript\n * import { init, StreamAnalyzer } from '@libraz/libsonare';\n *\n * await init();\n *\n * const analyzer = new StreamAnalyzer({ sampleRate: 44100 });\n *\n * // In audio processing callback\n * analyzer.process(samples);\n *\n * // Get current analysis state\n * const stats = analyzer.stats();\n * console.log('BPM:', stats.estimate.bpm);\n * console.log('Key:', stats.estimate.key);\n * console.log('Chord progression:', stats.estimate.chordProgression);\n * ```\n *\n * The native analyzer supports one serialized producer (`process`,\n * `processWithOffset`, or `finalize`) concurrently with one serialized consumer\n * (`availableFrames`, a `readFrames*` method, `stats`, `frameCount`, or\n * `currentTime`) when a threaded WASM host shares the native instance.\n * Publication is allocation-free release/acquire. `reset`, setters, and\n * deletion require both roles to be stopped. A full pending ring drops the\n * newly produced output frame while analysis totals keep advancing. Ordinary\n * browser builds remain single-threaded unless the host explicitly provisions\n * shared-memory worker support.\n */\nexport class StreamAnalyzer {\n private analyzer: WasmStreamAnalyzer;\n private released = false;\n\n /**\n * Create a new StreamAnalyzer.\n *\n * @param config - Configuration options\n */\n constructor(config: StreamConfig = {}) {\n if (config.computeMagnitude) {\n throw new Error(\n 'computeMagnitude is not supported because magnitude frames are not exposed by StreamAnalyzer read paths.',\n );\n }\n if (\n config.outputFormat !== undefined &&\n (typeof config.outputFormat !== 'number' ||\n !Number.isFinite(config.outputFormat) ||\n !Number.isInteger(config.outputFormat) ||\n config.outputFormat !== 0)\n ) {\n throw new TypeError('outputFormat must be the integer 0 (Float32)');\n }\n const window =\n config.window === undefined\n ? undefined\n : resolveOrdinalInRange(config.window, 0, 3, 'stream analyzer window');\n const module = getSonareModule();\n const defaults = streamAnalyzerConfigDefaults();\n this.analyzer = new module.StreamAnalyzer(\n config.sampleRate ?? defaults.sampleRate,\n config.nFft ?? defaults.nFft,\n config.hopLength ?? defaults.hopLength,\n config.nMels ?? defaults.nMels,\n config.fmin ?? defaults.fmin,\n config.fmax ?? defaults.fmax,\n config.tuningRefHz ?? defaults.tuningRefHz,\n config.computeMagnitude ?? defaults.computeMagnitude,\n config.computeMel ?? defaults.computeMel,\n config.computeChroma ?? defaults.computeChroma,\n config.computeOnset ?? defaults.computeOnset,\n config.computeSpectral ?? defaults.computeSpectral,\n config.emitEveryNFrames ?? defaults.emitEveryNFrames,\n config.magnitudeDownsample ?? defaults.magnitudeDownsample,\n config.maxPendingFrames ?? defaults.maxPendingFrames,\n config.maxProgressionEntries ?? defaults.maxProgressionEntries,\n config.keyUpdateIntervalSec ?? defaults.keyUpdateIntervalSec,\n config.bpmUpdateIntervalSec ?? defaults.bpmUpdateIntervalSec,\n window ?? defaults.window,\n config.outputFormat ?? defaults.outputFormat,\n );\n }\n\n /**\n * Process audio samples.\n *\n * Feeding a finalized analyzer is an invalid-state error; call `reset()`\n * first to start a new stream.\n *\n * @param samples - Audio samples (mono, float32)\n */\n process(samples: Float32Array): void {\n this.analyzer.process(samples);\n }\n\n /**\n * Process audio samples with a contiguous explicit sample offset. A gap,\n * seek, or switch from `process()` requires `reset()` first, as does feeding\n * a finalized analyzer.\n *\n * @param samples - Audio samples (mono, float32)\n * @param sampleOffset - Cumulative sample count at start of this chunk\n */\n processWithOffset(samples: Float32Array, sampleOffset: number): void {\n this.analyzer.processWithOffset(samples, sampleOffset);\n }\n\n /**\n * Drain any high-rate resampler tail, then zero-pad the final partial frame.\n *\n * Repeating a successful call is a no-op, and a call that fails leaves the\n * stream un-finalized so a retry resumes from the same point. Call `reset()`\n * before reusing the analyzer for another stream: more audio fed to a\n * finalized analyzer is rejected rather than silently analyzed without the\n * overlap context the finalized tail consumed.\n */\n finalize(): void {\n this.analyzer.finalize();\n }\n\n /**\n * Get the number of frames available to read.\n */\n availableFrames(): number {\n return this.analyzer.availableFrames();\n }\n\n /**\n * Read processed frames as Structure of Arrays.\n *\n * @param maxFrames - Maximum number of frames to read\n * @returns Frame buffer with analysis results\n */\n readFrames(maxFrames: number): FrameBuffer {\n return this.analyzer.readFramesSoa(maxFrames);\n }\n\n /**\n * Read frames as uint8-quantized arrays.\n *\n * @param maxFrames - Maximum number of frames to read\n * @param quantizeConfig - Optional quantization ranges; widen these for a\n * stream louder or quieter than the defaults (omitted keeps the defaults)\n */\n readFramesU8(maxFrames: number, quantizeConfig?: StreamQuantizeConfig): StreamFramesU8 {\n return this.analyzer.readFramesU8(maxFrames, quantizeConfig) as StreamFramesU8;\n }\n\n /**\n * Read frames as int16-quantized arrays.\n *\n * @param maxFrames - Maximum number of frames to read\n * @param quantizeConfig - Optional quantization ranges; widen these for a\n * stream louder or quieter than the defaults (omitted keeps the defaults)\n */\n readFramesI16(maxFrames: number, quantizeConfig?: StreamQuantizeConfig): StreamFramesI16 {\n return this.analyzer.readFramesI16(maxFrames, quantizeConfig) as StreamFramesI16;\n }\n\n /**\n * Reset the analyzer state.\n *\n * @param baseSampleOffset - Starting sample offset (default 0)\n */\n reset(baseSampleOffset = 0): void {\n this.analyzer.reset(baseSampleOffset);\n }\n\n /**\n * Get current statistics and progressive estimates.\n *\n * @returns Analyzer statistics including BPM, key, and chord progression\n */\n stats(): AnalyzerStats {\n const s = this.analyzer.stats();\n return {\n totalFrames: s.totalFrames,\n totalSamples: s.totalSamples,\n durationSeconds: s.durationSeconds,\n pendingFrames: s.pendingFrames,\n droppedOutputFrames: s.droppedOutputFrames,\n droppedChordProgressionEntries: s.droppedChordProgressionEntries,\n droppedBarProgressionEntries: s.droppedBarProgressionEntries,\n nonFiniteDiscardBlocks: s.nonFiniteDiscardBlocks,\n estimate: {\n bpm: s.estimate.bpm,\n bpmConfidence: s.estimate.bpmConfidence,\n bpmCandidateCount: s.estimate.bpmCandidateCount,\n key: s.estimate.key as PitchClass,\n keyMinor: s.estimate.keyMinor,\n keyConfidence: s.estimate.keyConfidence,\n chordRoot: s.estimate.chordRoot as PitchClass,\n chordQuality: s.estimate.chordQuality as ChordQuality,\n chordConfidence: s.estimate.chordConfidence,\n chordStartTime: s.estimate.chordStartTime,\n chordProgression: s.estimate.chordProgression.map((c) => ({\n root: c.root as PitchClass,\n quality: c.quality as ChordQuality,\n startTime: c.startTime,\n confidence: c.confidence,\n })),\n barChordProgression: s.estimate.barChordProgression.map((c) => ({\n barIndex: c.barIndex,\n root: c.root as PitchClass,\n quality: c.quality as ChordQuality,\n startTime: c.startTime,\n confidence: c.confidence,\n })),\n currentBar: s.estimate.currentBar,\n barDuration: s.estimate.barDuration,\n votedPattern: (s.estimate.votedPattern || []).map((c) => ({\n barIndex: c.barIndex,\n root: c.root as PitchClass,\n quality: c.quality as ChordQuality,\n startTime: c.startTime,\n confidence: c.confidence,\n })),\n patternLength: s.estimate.patternLength,\n detectedPatternName: s.estimate.detectedPatternName || '',\n detectedPatternScore: s.estimate.detectedPatternScore || 0,\n allPatternScores: (s.estimate.allPatternScores || []).map((p) => ({\n name: p.name,\n score: p.score,\n })),\n accumulatedSeconds: s.estimate.accumulatedSeconds,\n usedFrames: s.estimate.usedFrames,\n updated: s.estimate.updated,\n },\n };\n }\n\n /**\n * Get total frames processed.\n */\n frameCount(): number {\n return this.analyzer.frameCount();\n }\n\n /**\n * Get current time position in seconds.\n */\n currentTime(): number {\n return this.analyzer.currentTime();\n }\n\n /**\n * Get the sample rate.\n */\n sampleRate(): number {\n return this.analyzer.sampleRate();\n }\n\n /**\n * Set the expected total duration for pattern lock timing.\n *\n * @param durationSeconds - Total duration in seconds\n */\n setExpectedDuration(durationSeconds: number): void {\n this.analyzer.setExpectedDuration(durationSeconds);\n }\n\n /**\n * Set normalization gain for loud/compressed audio.\n *\n * Throws for a value outside 0.01..100 rather than clamping into it. The\n * usual recipe (`gain = targetLevel / measuredLevel`) can land outside that\n * range for a buffer that is not in the conventional ±1 float domain — an\n * integer-scaled one asks for about 3e-4 — and no getter exposes the\n * effective gain, so a clamped request would leave the analysis far off\n * target undetectably. Convert such a buffer before feeding it instead.\n *\n * @param gain - Gain factor to apply (e.g., 0.5 for -6dB reduction, range\n * 0.01..100)\n */\n setNormalizationGain(gain: number): void {\n this.analyzer.setNormalizationGain(gain);\n }\n\n /**\n * Set tuning reference frequency for non-standard tuning.\n *\n * Throws for a value outside 220..880 Hz rather than clamping into it, so\n * this and `tuningRefHz` at create time accept exactly the same range.\n *\n * @param refHz - Reference frequency for A4 (default 440 Hz, range 220..880)\n * @example\n * // If audio is 1 semitone sharp (A4 = 466.16 Hz)\n * analyzer.setTuningRefHz(466.16);\n * // If audio is 1 semitone flat (A4 = 415.30 Hz)\n * analyzer.setTuningRefHz(415.30);\n */\n setTuningRefHz(refHz: number): void {\n this.analyzer.setTuningRefHz(refHz);\n }\n\n /** Release the underlying WASM object. Idempotent, as the Node facade is. */\n delete(): void {\n if (this.released) {\n return;\n }\n this.released = true;\n this.analyzer.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n\n /** Alias for {@link delete}, kept for backward compatibility (historical name). */\n dispose(): void {\n this.delete();\n }\n}\n","import {\n automationCurveCode,\n meterTapCode,\n panLawCode,\n panModeCode,\n sendTimingCode,\n} from './codes';\nimport { getSonareModule } from './module_state';\nimport type {\n AutomationCurve,\n GoniometerPoint,\n MeterTap,\n MixerProcessResult,\n MixMeterSnapshot,\n PanLawInput,\n PanMode,\n SendTiming,\n SurroundPan,\n} from './public_types';\n\n/**\n * One master-output meter reading. All dB fields are finite and floored at\n * -120; `truePeakDb*` is an inter-sample peak from the ITU-R BS.1770-4\n * polyphase reconstruction at 4x, not a sample peak. That reconstruction is a\n * streaming measurement: its centered stencil needs a few future samples a\n * realtime path does not have, so each block's last samples read marginally low\n * (about 0.1 dB across 64..8192-sample blocks on a near-Nyquist tone, always\n * under-reading). Use `meteringTruePeakDb` over the whole signal for an exact\n * dBTP number.\n */\nexport interface MixerMeterSnapshot {\n peakDbL: number;\n peakDbR: number;\n rmsDbL: number;\n rmsDbR: number;\n correlation: number;\n truePeakDbL: number;\n truePeakDbR: number;\n}\n\n/**\n * Meter configuration for a strip added with {@link Mixer.addStrip}.\n *\n * The field names and defaults are the scene document's `strips[].metering`\n * object, so a strip added imperatively and one declared in a scene describe the\n * same thing. A strip's meters size their buffers when the strip is built, so\n * this is the only place the configuration can be chosen — there is no setter.\n * A full meter costs about 646 KB at 48 kHz and a strip carries two of them.\n */\nexport interface StripMeteringOptions {\n /** Both meters; `false` drops them (about 145 KB for the strip instead of 1.4 MB). Default `true`. */\n enabled?: boolean;\n /** LUFS measurement; `false` takes one meter to about 83 KB. Default `true`. */\n lufs?: boolean;\n /** Inter-sample (true) peak measurement. Default `true`. */\n truePeak?: boolean;\n /**\n * Requested true-peak oversampling factor in `[0, 16]`; the meter resolves it\n * to the nearest of 2x / 4x / 8x. `0` selects the library default (4x).\n */\n truePeakOversample?: number;\n}\n\nexport interface MixerRealtimeBuffer {\n leftInputs: Float32Array[];\n rightInputs: Float32Array[];\n outLeft: Float32Array;\n outRight: Float32Array;\n process: (numSamples?: number) => void;\n}\n\n// ============================================================================\n// Mixer Class (scene-based persistent mixer)\n// ============================================================================\n\n/**\n * Persistent, scene-based stereo mixer.\n *\n * Build one from a scene JSON string (e.g. {@link mixingScenePresetJson} or a\n * hand-authored scene), then feed per-strip stereo blocks through\n * {@link processStereo} to get the routed stereo master. Strips, sends, buses,\n * and inserts are described entirely by the scene; the routing graph is\n * compiled lazily on the first {@link processStereo} call (or eagerly via\n * {@link compile}).\n *\n * Call {@link delete} (or use a `try/finally`) to release the underlying WASM\n * object — the embind handle is not garbage-collected automatically.\n *\n * @example\n * ```typescript\n * const mixer = Mixer.fromSceneJson(mixingScenePresetJson('vocalReverbSend'), 48000, 512);\n * try {\n * const out = mixer.processStereo([stripL], [stripR]);\n * } finally {\n * mixer.delete();\n * }\n * ```\n */\nexport class Mixer {\n private mixer: import('./sonare.js').WasmMixer;\n private released = false;\n private readonly blockSize: number;\n\n private constructor(mixer: import('./sonare.js').WasmMixer, blockSize: number) {\n this.mixer = mixer;\n this.blockSize = blockSize;\n }\n\n /**\n * Build a mixer from a scene JSON string.\n *\n * A strip's meters are sized when the strip is built, so this is where their\n * configuration is chosen: an optional `metering` object on the strip\n * (`enabled` / `lufs` / `truePeak` / `truePeakOversample`) selects it, and\n * leaving it out keeps the full default (LUFS + true peak at 4x, about 1.4 MB\n * per strip at 48 kHz). `{\"enabled\": false}` drops both meters for a strip\n * whose snapshots are never read.\n *\n * @param json - Scene JSON (strips, buses, sends, connections, inserts)\n * @param sampleRate - Sample rate in Hz (default: 48000)\n * @param blockSize - Maximum block size per {@link processStereo} call (default: 512)\n */\n static fromSceneJson(json: string, sampleRate = 48000, blockSize = 512): Mixer {\n const module = getSonareModule();\n return new Mixer(module.createMixerFromSceneJson(json, sampleRate, blockSize), blockSize);\n }\n\n /**\n * Rebuild and compile the routing graph without resetting its absolute\n * automation sample position or queued strip automation.\n */\n compile(): void {\n this.mixer.compile();\n }\n\n /**\n * Non-fatal warnings captured when this mixer was built from scene JSON: one\n * entry per channel-strip insert that was handed param keys it does not read\n * (a likely typo, or a key meant for a different processor). The scene still\n * loaded; these keys simply took no effect. Empty when every key was consumed.\n * Use {@link masteringInsertParamNames} to discover the keys an insert accepts.\n */\n sceneWarnings(): string[] {\n return this.mixer.sceneWarnings();\n }\n\n /**\n * Mix one block of per-strip stereo audio into the stereo master.\n *\n * @param leftChannels - `leftChannels[i]` is the left channel of strip `i`\n * @param rightChannels - `rightChannels[i]` is the right channel of strip `i`\n * @returns Mixed stereo master (`left`, `right`, `sampleRate`)\n */\n processStereo(leftChannels: Float32Array[], rightChannels: Float32Array[]): MixerProcessResult {\n if (leftChannels.length !== rightChannels.length) {\n throw new Error('leftChannels and rightChannels must have the same length.');\n }\n return this.mixer.processStereo(leftChannels, rightChannels);\n }\n\n /**\n * Mix one block into caller-owned output arrays.\n *\n * This avoids allocating the result object and result `Float32Array`s. It is\n * intended for realtime bridges such as AudioWorklet; the input channel count\n * must match the scene strip count and all arrays must have the same length.\n */\n processStereoInto(\n leftChannels: Float32Array[],\n rightChannels: Float32Array[],\n outLeft: Float32Array,\n outRight: Float32Array,\n ): void {\n if (leftChannels.length !== rightChannels.length) {\n throw new Error('leftChannels and rightChannels must have the same length.');\n }\n if (outLeft.length !== outRight.length) {\n throw new Error('outLeft and outRight must have the same length.');\n }\n this.mixer.processStereoInto(leftChannels, rightChannels, outLeft, outRight);\n }\n\n /**\n * Create reusable WASM-heap input/output views for realtime-style processing.\n *\n * Fill `leftInputs[i]` / `rightInputs[i]`, call `process()`, then read\n * `outLeft` / `outRight`. The views are owned by this mixer and become invalid\n * after {@link delete}.\n */\n createRealtimeBuffer(): MixerRealtimeBuffer {\n const stripCount = this.stripCount();\n let leftInputs: Float32Array[] = [];\n let rightInputs: Float32Array[] = [];\n let outLeft = this.mixer.outputLeftView();\n let outRight = this.mixer.outputRightView();\n const acquire = (): void => {\n leftInputs = [];\n rightInputs = [];\n for (let index = 0; index < stripCount; index++) {\n leftInputs.push(this.mixer.inputLeftView(index));\n rightInputs.push(this.mixer.inputRightView(index));\n }\n outLeft = this.mixer.outputLeftView();\n outRight = this.mixer.outputRightView();\n };\n acquire();\n // The cached heap views can detach if WASM linear memory grows (the embind\n // module is built ALLOW_MEMORY_GROWTH). Re-acquire them if detached\n // (byteLength === 0) before use, mirroring the worklet RT path.\n const reacquireIfDetached = (): void => {\n if (outLeft.byteLength === 0 || (leftInputs[0]?.byteLength ?? 1) === 0) {\n acquire();\n }\n };\n return {\n get leftInputs(): Float32Array[] {\n reacquireIfDetached();\n return leftInputs;\n },\n get rightInputs(): Float32Array[] {\n reacquireIfDetached();\n return rightInputs;\n },\n get outLeft(): Float32Array {\n reacquireIfDetached();\n return outLeft;\n },\n get outRight(): Float32Array {\n reacquireIfDetached();\n return outRight;\n },\n process: (numSamples = outLeft.length) => {\n reacquireIfDetached();\n this.mixer.processPreparedStereo(numSamples);\n },\n };\n }\n\n /**\n * Turn the master-output meter on or off.\n *\n * While on, every {@link MixerRealtimeBuffer.process} call meters the stereo\n * master it just produced, so a caller reads {@link meterSnapshot} instead of\n * copying the output and measuring it again. `truePeakDb*` is an inter-sample\n * peak taken after oversampling (ITU-R BS.1770-4 Annex 2 requires at least\n * 4x), which is a different and higher quantity than the sample peak.\n *\n * Enabling resets the meter, so a reading never mixes in audio from a period\n * when metering was off.\n *\n * @param enabled - Whether to meter the master output.\n * @param truePeakOversample - 0 (= 4x) or a power of two in [1, 16].\n */\n configureMeter(enabled: boolean, truePeakOversample = 4): void {\n this.mixer.configureMeter(enabled, truePeakOversample);\n }\n\n /**\n * Latest master-output meter reading, describing the most recently metered\n * block. All dB fields are finite and floored at -120.\n *\n * @throws When the meter has never been enabled.\n */\n meterSnapshot(): MixerMeterSnapshot {\n return this.mixer.meterSnapshot();\n }\n\n /**\n * Latch the latest meter reading into the mixer's internal scratch so\n * {@link meterScratchValue} can read it back one number at a time.\n *\n * This is the allocation-free form of {@link meterSnapshot}, for an audio\n * render callback that must not create a JS object per interval. It returns\n * `false` instead of throwing when the meter has never been enabled.\n *\n * @returns Whether a reading was latched.\n */\n latchMeterSnapshot(): boolean {\n return this.mixer.latchMeterSnapshot();\n }\n\n /**\n * Read one field of the snapshot latched by {@link latchMeterSnapshot}.\n *\n * @param field - `0` peakDbL, `1` peakDbR, `2` rmsDbL, `3` rmsDbR,\n * `4` correlation, `5` truePeakDbL, `6` truePeakDbR. Any other index\n * reads `0`.\n */\n meterScratchValue(field: number): number {\n return this.mixer.meterScratchValue(field);\n }\n\n /** Number of strips in the mixer (e.g. strips loaded from the scene). */\n stripCount(): number {\n return this.mixer.stripCount();\n }\n\n /**\n * Schedule sample-accurate insert-parameter automation on a strip's insert.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param insertIndex - Index into the strip's combined insert sequence\n * (`[pre-inserts... post-inserts...]`)\n * @param paramId - Processor-specific parameter id\n * @param samplePos - Absolute samples from the start of processing (the mixer\n * advances an internal position from 0 on the first {@link processStereo}\n * call; recompiling resets it to 0)\n * @param value - Target parameter value\n * @param curve - Interpolation curve (default: `'linear'`)\n * @throws If the strip index is out of range or the schedule call fails\n * (unknown curve, out-of-range insert index, or full event lane)\n */\n scheduleInsertAutomation(\n stripIndex: number,\n insertIndex: number,\n paramId: number,\n samplePos: number,\n value: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleInsertAutomation(\n stripIndex,\n insertIndex,\n paramId,\n samplePos,\n value,\n automationCurveCode(curve),\n );\n }\n\n /**\n * Resolve a strip's index in `[0, stripCount())` from its scene id, or `null`\n * when no strip with that id exists (matches the Node binding's `number | null`).\n */\n stripById(id: string): number | null {\n const index = this.mixer.stripById(id);\n return index < 0 ? null : index;\n }\n\n /**\n * Add a channel strip to the mixer topology. `metering` configures the strip's\n * pre/post taps; omitting it keeps the full default (LUFS + true peak at 4x,\n * about 1.4 MB per strip at 48 kHz). Marks the routing graph dirty; call\n * {@link compile} (or {@link processStereo}) to rebuild.\n *\n * @throws If the id is already taken, or `truePeakOversample` is outside `[0, 16]`\n */\n addStrip(id: string, metering: StripMeteringOptions = {}): void {\n this.mixer.addStrip(id, metering);\n }\n\n /**\n * Add a bus to the mixer topology. `role` is one of `'master'`, `'aux'`, or\n * `'submix'` (defaults to `'aux'`). Marks the routing graph dirty; call\n * {@link compile} (or {@link processStereo}) to rebuild.\n */\n addBus(id: string, role = 'aux'): void {\n this.mixer.addBus(id, role);\n }\n\n /** Remove a bus by id. Marks the routing graph dirty. */\n removeBus(id: string): void {\n this.mixer.removeBus(id);\n }\n\n /** Number of buses in the mixer topology. */\n busCount(): number {\n return this.mixer.busCount();\n }\n\n /**\n * Add a VCA group with the given gain offset (dB). `members` is a list of\n * strip ids governed by the group (may be empty).\n */\n addVcaGroup(id: string, gainDb = 0.0, members: string[] = []): void {\n this.mixer.addVcaGroup(id, gainDb, members);\n }\n\n /** Set an existing VCA group's gain in dB. */\n setVcaGroupGainDb(id: string, gainDb: number): void {\n this.mixer.setVcaGroupGainDb(id, gainDb);\n }\n\n /** Replace an existing VCA group's strip membership. */\n setVcaGroupMembers(id: string, members: string[]): void {\n this.mixer.setVcaGroupMembers(id, members);\n }\n\n /** Remove a VCA group by id. */\n removeVcaGroup(id: string): void {\n this.mixer.removeVcaGroup(id);\n }\n\n /** Number of VCA groups in the mixer topology. */\n vcaGroupCount(): number {\n return this.mixer.vcaGroupCount();\n }\n\n /** Set the strip's input trim in dB. */\n setInputTrimDb(stripIndex: number, db: number): void {\n this.mixer.setInputTrimDb(stripIndex, db);\n }\n\n /** Set the strip's fader level in dB. */\n setFaderDb(stripIndex: number, db: number): void {\n this.mixer.setFaderDb(stripIndex, db);\n }\n\n /**\n * Set the strip's pan position.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param pan - Pan position in `[-1, 1]`\n * @param panMode - Optional pan mode. When omitted the strip's current pan\n * mode is kept (passes `SONARE_PAN_MODE_KEEP`), so a plain pan nudge does\n * not reset a scene-defined `'stereoPan'` / `'dualPan'` mode back to\n * balance. Pass `'balance'` (or `0`) explicitly to force balance mode.\n */\n setPan(stripIndex: number, pan: number, panMode?: PanMode | number): void {\n // SONARE_PAN_MODE_KEEP (-1) = keep the strip's current pan mode.\n const mode = panMode === undefined ? -1 : panModeCode(panMode);\n this.mixer.setPan(stripIndex, pan, mode);\n }\n\n /** Set the strip's stereo width. */\n setWidth(stripIndex: number, width: number): void {\n this.mixer.setWidth(stripIndex, width);\n }\n\n /**\n * Snap the strip's input-trim, fader, pan and width smoothers to the values\n * already set on it, so the next processed block opens at those values\n * instead of gliding to them over the smoothing window (~5 ms).\n *\n * Call it after configuring a strip and before rendering a finite buffer: a\n * strip is smoothed for a live fader, and an offline render that does not\n * settle carries that glide as a level and image sweep across the head of\n * its output. Unlike a reset it clears nothing — automation, meters and\n * insert state are untouched.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n *\n * @example\n * ```typescript\n * mixer.setFaderDb(0, -3);\n * mixer.setPan(0, 0.3);\n * mixer.settle(0);\n * const { left, right } = mixer.processStereo([dryLeft], [dryRight]);\n * ```\n */\n settle(stripIndex: number): void {\n this.mixer.settle(stripIndex);\n }\n\n /** Set the strip's mute state. */\n setMuted(stripIndex: number, muted: boolean): void {\n this.mixer.setMuted(stripIndex, muted);\n }\n\n /**\n * Set a strip's solo state. Takes effect on the next process without a\n * graph recompile.\n */\n setSoloed(stripIndex: number, soloed: boolean): void {\n this.mixer.setSoloed(stripIndex, soloed);\n }\n\n /**\n * Mark a strip solo-safe so it is never implied-muted by another strip's\n * solo. Takes effect on the next process without a graph recompile.\n */\n setSoloSafe(stripIndex: number, soloSafe: boolean): void {\n this.mixer.setSoloSafe(stripIndex, soloSafe);\n }\n\n /** Invert the polarity of the left and/or right channel of a strip. */\n setPolarityInvert(stripIndex: number, invertLeft: boolean, invertRight: boolean): void {\n this.mixer.setPolarityInvert(stripIndex, invertLeft, invertRight);\n }\n\n /** Set the strip's pan law (a {@link PanLawName} alias or raw C ABI ordinal). */\n setPanLaw(stripIndex: number, panLaw: PanLawInput): void {\n this.mixer.setPanLaw(stripIndex, panLawCode(panLaw));\n }\n\n /**\n * Set a per-strip channel delay in samples. This changes the strip's reported\n * latency; recompile to re-run latency compensation.\n */\n setChannelDelaySamples(stripIndex: number, delaySamples: number): void {\n this.mixer.setChannelDelaySamples(stripIndex, delaySamples);\n }\n\n /** Set the strip's live VCA gain offset in dB (not persisted to the scene). */\n setVcaOffsetDb(stripIndex: number, offsetDb: number): void {\n this.mixer.setVcaOffsetDb(stripIndex, offsetDb);\n }\n\n /** Set independent left/right pan positions (dual-pan mode). */\n setDualPan(stripIndex: number, leftPan: number, rightPan: number): void {\n this.mixer.setDualPan(stripIndex, leftPan, rightPan);\n }\n\n /**\n * Set the strip's surround pan position, used when it feeds a >2-channel bus.\n *\n * Applied when the engine's track mixer renders this strip's lane into a\n * destination with more than two channels. This stereo-only mixer's own\n * block entry points ignore it.\n */\n setSurroundPan(stripIndex: number, pan: SurroundPan): void {\n this.mixer.setSurroundPan(stripIndex, pan);\n }\n\n /**\n * Add a send to a strip after construction.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param id - Send id\n * @param destinationBusId - Destination bus id\n * @param sendDb - Initial send level in dB\n * @param timing - `'preFader'` or `'postFader'` (default: `'postFader'`)\n * @returns The new send's index\n */\n addSend(\n stripIndex: number,\n id: string,\n destinationBusId: string,\n sendDb = 0.0,\n timing: SendTiming | number = 'postFader',\n ): number {\n return this.mixer.addSend(stripIndex, id, destinationBusId, sendDb, sendTimingCode(timing));\n }\n\n /** Set the send level (in dB) for an existing send by index. */\n setSendDb(stripIndex: number, sendIndex: number, sendDb: number): void {\n this.mixer.setSendDb(stripIndex, sendIndex, sendDb);\n }\n\n /**\n * Remove an existing send from a strip by index.\n *\n * Sends are addressed in add order. After removal, sends with a higher index\n * than `sendIndex` shift down by one. Recompile (or process) before reading\n * results so the routing graph rebuilds.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param sendIndex - Send index in add order\n */\n removeSend(stripIndex: number, sendIndex: number): void {\n this.mixer.removeSend(stripIndex, sendIndex);\n }\n\n /**\n * Read a strip's meter snapshot at the given tap point.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param tap - `'preFader'` or `'postFader'` (default: `'postFader'`)\n */\n meterTap(stripIndex: number, tap: MeterTap = 'postFader'): MixMeterSnapshot {\n return this.mixer.meterTap(stripIndex, meterTapCode(tap));\n }\n\n /**\n * Read a strip's meter snapshot.\n *\n * With no `tap` argument this reads the strip's own (post-fader) meter,\n * matching the Node/Python tap-less `stripMeter` contract. Pass an optional\n * `tap` (`'preFader'` / `'postFader'`) to read the tap-selectable snapshot\n * instead — the same backing call as {@link meterTap}.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param tap - Optional tap point (`'preFader'` / `'postFader'`); when omitted\n * the tap-less post-fader strip meter is read.\n */\n stripMeter(stripIndex: number, tap?: MeterTap | number): MixMeterSnapshot {\n if (tap === undefined) {\n return this.mixer.stripMeter(stripIndex);\n }\n return this.mixer.meterTap(stripIndex, meterTapCode(tap));\n }\n\n /** Read the post-insert meter for a compiled bus, including master. */\n busMeter(busId: string): MixMeterSnapshot {\n return this.mixer.busMeter(busId);\n }\n\n /**\n * Number of blocks in which the strip discarded recursive state because a\n * non-finite value had reached it.\n *\n * Advisory telemetry, and the only thing that separates a degraded strip\n * from a clean one. A discard returns the affected state to its\n * post-reset value, so the strip recovers in silence and the output stays\n * finite and in range while carrying samples unrelated to the input;\n * nothing else reports that this happened.\n *\n * The count covers the strip's own state, its EQ, every insert it owns and\n * both of its meters. None of those is separately addressable here, so a\n * discard inside one is observable only through this number -- and a\n * meter that loses its loudness window then reports the floor, which is\n * exactly what a genuinely silent strip reports, so nothing else\n * distinguishes the two.\n *\n * A meter's own discard lags by one block: it checks its loudness state at\n * the top of a block, before consuming that block's samples, so the block\n * that corrupts it is not the block the count moves on -- read this again\n * after one more block has processed. The EQ and inserts have no such lag;\n * they discard at the end of their own process, in the same block that\n * carried the poison.\n *\n * Cumulative since the strip was created and never cleared, so two\n * readings bracket a span of audio. The unit is one processed block, never\n * a channel, so a stereo block that discards on both channels adds one and\n * the number does not depend on a dimension the caller did not choose.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n */\n stripNonFiniteDiscardCount(stripIndex: number): number {\n return this.mixer.stripNonFiniteDiscardCount(stripIndex);\n }\n\n /**\n * Number of blocks in which a bus discarded recursive state because a\n * non-finite value had reached it. Same contract as\n * {@link stripNonFiniteDiscardCount}, for a bus: covers every insert the\n * bus owns and its meter, neither separately addressable, so a discard\n * inside one is observable only here. Cumulative across graph recompiles\n * -- the count lives with the bus, not the compiled node, so an unrelated\n * edit elsewhere in the mixer does not reset it.\n *\n * A bus's DSP record is created by the first {@link compile}. Throws for a\n * bus that has been declared with {@link addBus} but never compiled --\n * reading zero there would read as clean, and it is not. Also throws for\n * an unknown bus id.\n *\n * @param busId - Bus id, as passed to {@link addBus} or declared in scene JSON\n */\n busNonFiniteDiscardCount(busId: string): number {\n return this.mixer.busNonFiniteDiscardCount(busId);\n }\n\n /**\n * Schedule sample-accurate fader automation on a strip.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param samplePos - Absolute samples from the start of processing\n * @param faderDb - Target fader level in dB\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n scheduleFaderAutomation(\n stripIndex: number,\n samplePos: number,\n faderDb: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleFaderAutomation(stripIndex, samplePos, faderDb, automationCurveCode(curve));\n }\n\n /**\n * Schedule sample-accurate pan automation on a strip.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param samplePos - Absolute samples from the start of processing\n * @param pan - Target pan position\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n schedulePanAutomation(\n stripIndex: number,\n samplePos: number,\n pan: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.schedulePanAutomation(stripIndex, samplePos, pan, automationCurveCode(curve));\n }\n\n /**\n * Schedule sample-accurate width automation on a strip.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param samplePos - Absolute samples from the start of processing\n * @param width - Target stereo width\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n scheduleWidthAutomation(\n stripIndex: number,\n samplePos: number,\n width: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleWidthAutomation(stripIndex, samplePos, width, automationCurveCode(curve));\n }\n\n /**\n * Schedule sample-accurate send-level automation on a strip's send.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param sendIndex - Send index in the strip's add order\n * @param samplePos - Absolute samples from the start of processing\n * @param db - Target send level in dB\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n scheduleSendAutomation(\n stripIndex: number,\n sendIndex: number,\n samplePos: number,\n db: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleSendAutomation(\n stripIndex,\n sendIndex,\n samplePos,\n db,\n automationCurveCode(curve),\n );\n }\n\n /**\n * Read up to `maxPoints` of a strip's most recent goniometer samples\n * (oldest to newest).\n *\n * `maxPoints` must be a finite non-negative integer; anything else throws an\n * `InvalidParameter` error. It is a request rather than an allocation size —\n * a value beyond the strip's goniometer ring simply returns every point the\n * ring holds.\n */\n readGoniometerLatest(stripIndex: number, maxPoints: number): GoniometerPoint[] {\n return this.mixer.readGoniometerLatest(stripIndex, maxPoints);\n }\n\n /** Serialize the current scene (strips, buses, sends, connections) to JSON. */\n toSceneJson(): string {\n return this.mixer.toSceneJson();\n }\n\n /**\n * Longest audible serial processor-tail path to the master, in samples. Lazily\n * compiles the routing graph if the topology is dirty.\n */\n tailSamples(): number {\n return this.mixer.tailSamples();\n }\n\n /**\n * Reported latency (samples) of the compiled mixer graph, for aligning\n * dry/wet material. Lazily compiles the routing graph if the topology is dirty.\n */\n latencySamples(): number {\n return this.mixer.latencySamples();\n }\n\n /**\n * Drain delayed / tail audio by processing a zero-input block of `numSamples`\n * frames after the host stops feeding strip inputs. Returns the mixed stereo\n * master (`left`, `right`, `sampleRate`).\n */\n drainTailStereo(numSamples: number): MixerProcessResult {\n if (!Number.isSafeInteger(numSamples) || numSamples <= 0 || numSamples > this.blockSize) {\n throw new RangeError(\n `Mixer.drainTailStereo: numSamples must be an integer in [1, ${this.blockSize}]`,\n );\n }\n return this.mixer.drainTailStereo(numSamples);\n }\n\n /** Release the underlying WASM object. Idempotent, as the Node facade is. */\n delete(): void {\n if (this.released) {\n return;\n }\n this.released = true;\n this.mixer.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n","import { getSonareModule } from './module_state';\nimport type {\n RealtimeVoiceChangerConfigInput,\n RealtimeVoiceChangerPodConfig,\n VoicePresetId,\n} from './public_types';\n\n/**\n * Zero-copy realtime buffer pair for {@link RealtimeVoiceChanger} mono\n * processing. The `input` / `output` `Float32Array`s are typed-memory views\n * onto the WASM heap — write samples into `input`, call `process()`, then\n * read from `output`. The views are owned by the {@link RealtimeVoiceChanger}\n * and remain valid until `delete()` is called on it.\n */\nexport interface RealtimeVoiceChangerMonoBuffer {\n input: Float32Array;\n output: Float32Array;\n process: () => void;\n}\n\n/**\n * Zero-copy realtime buffer pair for {@link RealtimeVoiceChanger} interleaved\n * multi-channel processing. Layout is L0,R0,L1,R1,... for stereo. The views\n * are owned by the {@link RealtimeVoiceChanger}.\n */\nexport interface RealtimeVoiceChangerInterleavedBuffer {\n input: Float32Array;\n output: Float32Array;\n channels: number;\n process: () => void;\n}\n\n/**\n * Zero-copy realtime buffer for {@link RealtimeVoiceChanger} planar stereo\n * processing. Each entry in `channels` is a heap-backed `Float32Array` for one\n * channel (matching AudioWorklet's native layout). Process happens in place:\n * write samples into each channel view, call `process()`, then read back from\n * the same views.\n */\nexport interface RealtimeVoiceChangerPlanarBuffer {\n channels: Float32Array[];\n process: () => void;\n}\n\n// ============================================================================\n// RealtimeVoiceChanger Class\n// ============================================================================\n\nexport class RealtimeVoiceChanger {\n private changer: import('./sonare.js').WasmRealtimeVoiceChanger;\n private released = false;\n\n /**\n * Creates a voice changer. Supplying `sampleRate` prepares it immediately,\n * matching the Node and Python constructors; omitting it preserves the\n * explicit {@link prepare} lifecycle for callers that configure later.\n */\n constructor(\n config: RealtimeVoiceChangerConfigInput | RealtimeVoiceChangerPodConfig = 'neutral-monitor',\n sampleRate?: number,\n maxBlockSize = 128,\n channels = 1,\n ) {\n const module = getSonareModule();\n this.changer = module.createRealtimeVoiceChanger(config as Record<string, unknown> | string);\n if (sampleRate !== undefined) {\n // `prepare` rejects a non-positive sample rate, a negative block size and\n // a channel count outside [1, 2]. The handle is already allocated by\n // then, and a throwing constructor leaves `this` unreachable, so release\n // it here — embind has no GC finalizer, and a device-change handler that\n // retries on failure would otherwise leak one whole DSP chain per attempt\n // (retune ring, ISP limiter, reverb, scratch).\n let prepared = false;\n try {\n this.changer.prepare(sampleRate, maxBlockSize, channels);\n prepared = true;\n } finally {\n if (!prepared) {\n this.changer.delete();\n }\n }\n }\n }\n\n prepare(sampleRate: number, maxBlockSize = 128, channels = 1): void {\n this.changer.prepare(sampleRate, maxBlockSize, channels);\n }\n\n reset(): void {\n this.changer.reset();\n }\n\n setConfig(config: RealtimeVoiceChangerConfigInput | RealtimeVoiceChangerPodConfig): void {\n // The shared native parser recognizes the flat POD produced by\n // realtimeVoiceChangerPresetConfig, so bindings never duplicate its 36-field mapping.\n this.changer.setConfig(config as Record<string, unknown> | string);\n }\n\n /**\n * Apply a flat, pre-normalized config without JSON serialization. Intended\n * for AudioWorklet control messages whose sender prepared the POD on the\n * main thread.\n */\n setPodConfig(config: RealtimeVoiceChangerPodConfig): void {\n this.changer.setPodConfig(config);\n }\n\n configJson(): string {\n return this.changer.configJson();\n }\n\n latencySamples(): number {\n return this.changer.latencySamples();\n }\n\n /**\n * Channel-blocks in which the chain discarded its own state because a\n * non-finite value had reached it.\n *\n * Advisory telemetry, and the only thing that separates a degraded stream\n * from a clean one. Every stage of this chain leaves an in-domain finite\n * value where a non-finite one was — the input scrub and the\n * inter-sample-peak limiter substitute silence, the sample-domain limiter\n * folds an infinity onto its ceiling — so the output stays finite, in range\n * and free of any error while carrying samples unrelated to the input. A\n * non-zero count is what says the samples in between were not computed from\n * what you supplied.\n *\n * Monotonic for the lifetime of the instance. The unit is one processed\n * block, never a channel, so a stereo block that discards on both channels\n * adds one and the number does not depend on a dimension you did not choose.\n *\n * @example\n * ```ts\n * changer.processInterleaved(block, 2);\n * if (changer.nonFiniteDiscardCount() > 0) {\n * // the audio just produced is not a function of `block`\n * }\n * ```\n */\n nonFiniteDiscardCount(): number {\n return this.changer.nonFiniteDiscardCount();\n }\n\n /**\n * Monotonically increases whenever {@link prepare} can replace the native\n * scratch buffers. Cached WASM heap views must be reacquired after it changes.\n */\n bufferGeneration(): number {\n return this.changer.bufferGeneration();\n }\n\n processMono(samples: Float32Array): Float32Array {\n return this.changer.processMono(samples);\n }\n\n processMonoInto(samples: Float32Array, output: Float32Array): void {\n this.changer.processMonoInto(samples, output);\n }\n\n processInterleaved(samples: Float32Array, channels: number): Float32Array {\n return this.changer.processInterleaved(samples, channels);\n }\n\n processInterleavedInto(samples: Float32Array, channels: number, output: Float32Array): void {\n this.changer.processInterleavedInto(samples, channels, output);\n }\n\n /**\n * Acquire a typed-memory view onto the WASM heap for mono input.\n *\n * Write your input samples into the returned `Float32Array` directly (e.g.\n * via `input.set(source)`); no copy crosses the JS↔C++ bridge until\n * {@link processPreparedMono} is called. The view is owned by this\n * RealtimeVoiceChanger and becomes invalid after {@link delete}; it may\n * also be invalidated if you later call this method with a larger\n * `numSamples` value (the underlying buffer may be reallocated).\n */\n getMonoInputBuffer(numSamples: number): Float32Array {\n return this.changer.getMonoInputBuffer(numSamples);\n }\n\n /** Mono output view counterpart to {@link getMonoInputBuffer}. */\n getMonoOutputBuffer(numSamples: number): Float32Array {\n return this.changer.getMonoOutputBuffer(numSamples);\n }\n\n /**\n * Process the previously-acquired mono input buffer in place. The output\n * appears in the buffer returned by {@link getMonoOutputBuffer}. No JS↔C++\n * sample-level crossings happen on this call — it just hands control to\n * the underlying DSP on already-on-heap data.\n */\n processPreparedMono(numSamples: number): void {\n this.changer.processPreparedMono(numSamples);\n }\n\n /** Interleaved input view (layout L0,R0,L1,R1,...). */\n getInterleavedInputBuffer(numFrames: number, numChannels: number): Float32Array {\n return this.changer.getInterleavedInputBuffer(numFrames, numChannels);\n }\n\n /** Interleaved output view counterpart. */\n getInterleavedOutputBuffer(numFrames: number, numChannels: number): Float32Array {\n return this.changer.getInterleavedOutputBuffer(numFrames, numChannels);\n }\n\n /**\n * Process the previously-acquired interleaved buffer in place. Output\n * appears in the buffer returned by {@link getInterleavedOutputBuffer}.\n */\n processPreparedInterleaved(numFrames: number, numChannels: number): void {\n this.changer.processPreparedInterleaved(numFrames, numChannels);\n }\n\n /**\n * Planar-channel input/output view (one Float32Array per channel). Matches\n * AudioWorklet's native layout; processing happens in place.\n */\n getPlanarChannelBuffer(channel: number, numFrames: number): Float32Array {\n return this.changer.getPlanarChannelBuffer(channel, numFrames);\n }\n\n /**\n * Process the previously-acquired planar channel buffers in place. Each\n * channel must have been obtained from {@link getPlanarChannelBuffer}\n * with the same `numFrames`. Output replaces input in the same buffers.\n */\n processPreparedPlanar(numFrames: number): void {\n this.changer.processPreparedPlanar(numFrames);\n }\n\n /**\n * Convenience factory for the mono zero-copy path: returns the input/output\n * heap views plus a `process()` thunk wired to the same `numSamples`. The\n * views are reused across calls and become invalid after {@link delete}.\n */\n createRealtimeMonoBuffer(numSamples: number): RealtimeVoiceChangerMonoBuffer {\n let input = this.getMonoInputBuffer(numSamples);\n let output = this.getMonoOutputBuffer(numSamples);\n let generation = this.bufferGeneration();\n // The cached heap views can detach if WASM linear memory grows (the embind\n // module is built ALLOW_MEMORY_GROWTH). Re-acquire them if detached\n // (byteLength === 0) before use, mirroring the worklet RT path. In the\n // common no-growth case this is a cheap branch with no allocation.\n const reacquireIfDetached = (): void => {\n if (\n generation !== this.bufferGeneration() ||\n input.byteLength === 0 ||\n output.byteLength === 0\n ) {\n input = this.getMonoInputBuffer(numSamples);\n output = this.getMonoOutputBuffer(numSamples);\n generation = this.bufferGeneration();\n }\n };\n return {\n get input(): Float32Array {\n reacquireIfDetached();\n return input;\n },\n get output(): Float32Array {\n reacquireIfDetached();\n return output;\n },\n process: () => {\n reacquireIfDetached();\n this.processPreparedMono(numSamples);\n },\n };\n }\n\n /** Same as {@link createRealtimeMonoBuffer} but for interleaved I/O. */\n createRealtimeInterleavedBuffer(\n numFrames: number,\n numChannels: number,\n ): RealtimeVoiceChangerInterleavedBuffer {\n let input = this.getInterleavedInputBuffer(numFrames, numChannels);\n let output = this.getInterleavedOutputBuffer(numFrames, numChannels);\n let generation = this.bufferGeneration();\n // Re-acquire detached views after WASM memory growth (see\n // createRealtimeMonoBuffer for rationale).\n const reacquireIfDetached = (): void => {\n if (\n generation !== this.bufferGeneration() ||\n input.byteLength === 0 ||\n output.byteLength === 0\n ) {\n input = this.getInterleavedInputBuffer(numFrames, numChannels);\n output = this.getInterleavedOutputBuffer(numFrames, numChannels);\n generation = this.bufferGeneration();\n }\n };\n return {\n get input(): Float32Array {\n reacquireIfDetached();\n return input;\n },\n get output(): Float32Array {\n reacquireIfDetached();\n return output;\n },\n channels: numChannels,\n process: () => {\n reacquireIfDetached();\n this.processPreparedInterleaved(numFrames, numChannels);\n },\n };\n }\n\n /**\n * Convenience factory for the planar zero-copy path. Acquires one\n * heap-backed Float32Array per channel and returns a `process()` thunk\n * wired to the same `numFrames`. Buffers are reused across calls and\n * become invalid after {@link delete}.\n */\n createRealtimePlanarBuffer(\n numFrames: number,\n numChannels: number,\n ): RealtimeVoiceChangerPlanarBuffer {\n let channels: Float32Array[] = [];\n let generation = this.bufferGeneration();\n const acquire = (): void => {\n channels = [];\n for (let ch = 0; ch < numChannels; ch++) {\n channels.push(this.getPlanarChannelBuffer(ch, numFrames));\n }\n generation = this.bufferGeneration();\n };\n acquire();\n // Re-acquire detached views after WASM memory growth (see\n // createRealtimeMonoBuffer for rationale).\n const reacquireIfDetached = (): void => {\n if (generation !== this.bufferGeneration() || (channels[0]?.byteLength ?? 0) === 0) {\n acquire();\n }\n };\n return {\n get channels(): Float32Array[] {\n reacquireIfDetached();\n return channels;\n },\n process: () => {\n reacquireIfDetached();\n this.processPreparedPlanar(numFrames);\n },\n };\n }\n\n /** Releases the native handle. Idempotent, as the Node facade is. */\n delete(): void {\n if (this.released) {\n return;\n }\n this.released = true;\n this.changer.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n\nexport function realtimeVoiceChangerPresetNames(): VoicePresetId[] {\n // Array.from re-roots embind's vector as a plain, structured-cloneable Array.\n return Array.from(getSonareModule().realtimeVoiceChangerPresetNames()) as VoicePresetId[];\n}\n\nexport function realtimeVoiceChangerPresetJson(name: VoicePresetId): string {\n return getSonareModule().realtimeVoiceChangerPresetJson(name);\n}\n\nexport function validateRealtimeVoiceChangerPresetJson(json: string): {\n ok: boolean;\n normalizedJson?: string;\n error?: string;\n} {\n return getSonareModule().validateRealtimeVoiceChangerPresetJson(json);\n}\n","import { flattenChainConfig } from './_chain_config';\nimport { getSonareModule } from './module_state';\nimport type {\n EqBand,\n EqMatchOptions,\n EqSpectrumSnapshot,\n EqStereoPlacement,\n StreamingEqualizerConfig,\n StreamingMasteringChainConfig,\n StreamingRetuneConfig,\n} from './public_types';\n\ntype EqPhaseMode =\n | 'zero'\n | 'zero-latency'\n | 'zero_latency'\n | 'natural'\n | 'natural-phase'\n | 'natural_phase'\n | 'linear'\n | 'linear-phase'\n | 'linear_phase'\n | number;\n\nconst EQ_PLACEMENTS: Record<string, number> = {\n stereo: 0,\n left: 1,\n right: 2,\n mid: 3,\n side: 4,\n};\n\nconst EQ_PHASE_MODES: Record<string, number> = {\n zero: 1,\n 'zero-latency': 1,\n zero_latency: 1,\n natural: 2,\n 'natural-phase': 2,\n natural_phase: 2,\n linear: 3,\n 'linear-phase': 3,\n linear_phase: 3,\n};\n\n// ============================================================================\n// StreamingMasteringChain Class\n// ============================================================================\n\n/**\n * Block-by-block streaming variant of {@link masteringChain}.\n *\n * Maintains processor state across {@link processMono}/{@link processStereo}\n * calls. Only ProcessorBase-backed stages are supported: `eq.tilt`,\n * `dynamics.deesser`, `dynamics.transientShaper`, `dynamics.compressor`,\n * `dynamics.multibandComp`, `saturation.tape`, `saturation.exciter`,\n * `spectral.airBand`, `stereo.imager` (stereo only), `stereo.monoMaker`\n * (stereo only), `maximizer.truePeakLimiter`. Configurations that enable ANY of\n * the five whole-signal repair stages (`repair.declick`, `repair.declip`,\n * `repair.decrackle`, `repair.dehum`, `repair.dereverb`) throw at construction.\n *\n * `repair.denoise` runs here, but only with a noise estimator that is recursive\n * in time. Its default ranks every frame of the whole signal by energy, which a\n * stream never reaches the end of, so it is refused by name rather than\n * substituted; set `repair.denoise.noiseEstimator` to `1` (MCRA), `2` (IMCRA)\n * or `3` (speech-presence probability). The two minimum-tracking estimators\n * (`1` and `2`) seed their noise floor from the first frame they see and hold it\n * for the half second their minimum window spans, so a stream opened in the\n * middle of the programme is over-suppressed until it turns over; `3` tracks no\n * minimum and is unaffected. Prefer `3` past that opening too: `1` and `2`\n * over-report the floor for as long as the programme stays intermittent, and on\n * a gated tone they leave the result below the untreated input.\n *\n * An enabled `loudness` stage also throws unless\n * {@link StreamingMasteringChainConfig.loudnessStaticGainDb} supplies a\n * precomputed normalization gain.\n *\n * Call {@link delete} (or use a `try/finally`) to release the underlying WASM\n * object — the embind handle is not garbage-collected automatically.\n *\n * Reachable from the AudioWorklet realm through the `sonare/worklet` entry, but\n * the realtime contract is the caller's to keep:\n *\n * - {@link prepare} builds the processors and allocates. Call it once from a\n * message handler, never from `AudioWorkletProcessor.process()`.\n * - {@link processMono}/{@link processStereo} return fresh arrays. On the render\n * thread, reuse the returned reference for the block rather than retaining it.\n * - An enabled `loudness` stage needs `loudnessStaticGainDb` measured offline,\n * because whole-signal integrated LUFS cannot be measured block by block. Pass\n * `loudnessStaticGainPeakDb` too and the static gain is clamped exactly as the\n * offline chain clamps it, so the live preview matches the render.\n * - {@link flush} output starts {@link latencySamples} samples early; discard\n * that many leading samples when time alignment matters.\n *\n * The chain is a host-side stage, not an engine insert: it does not participate\n * in the engine's PDC or bypass, so latency compensation against other engine\n * outputs is also the caller's.\n *\n * @example\n * ```typescript\n * const chain = new StreamingMasteringChain({ eq: { tiltDb: 1.0 } });\n * try {\n * chain.prepare(44100, 512, 1);\n * const out = chain.processMono(blockSamples);\n * } finally {\n * chain.delete();\n * }\n * ```\n */\nexport class StreamingMasteringChain {\n private chain: import('./sonare.js').WasmStreamingMasteringChain;\n private released = false;\n\n constructor(config: StreamingMasteringChainConfig) {\n const module = getSonareModule();\n const { loudnessStaticGainDb, loudnessStaticGainPeakDb, ...chainConfig } = config;\n this.chain = module.createStreamingMasteringChain({\n __flatParams: flattenChainConfig(chainConfig),\n loudnessStaticGainDb,\n loudnessStaticGainPeakDb,\n });\n }\n\n /**\n * Initialize processors for the given sample rate and block layout.\n *\n * @param sampleRate - Sample rate in Hz\n * @param maxBlockSize - Maximum block size per process call\n * @param numChannels - 1 (mono) or 2 (stereo)\n */\n prepare(sampleRate: number, maxBlockSize: number, numChannels: number): void {\n this.chain.prepare(sampleRate, maxBlockSize, numChannels);\n }\n\n /**\n * Process one mono block, returning the processed samples (same length).\n */\n processMono(samples: Float32Array): Float32Array {\n return this.chain.processMono(samples);\n }\n\n /**\n * Process one stereo block, returning the processed channels.\n */\n processStereo(\n left: Float32Array,\n right: Float32Array,\n ): { left: Float32Array; right: Float32Array } {\n if (left.length !== right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n return this.chain.processStereo(left, right);\n }\n\n /**\n * Emit delayed audio and finite processor tails after the final mono block.\n * Call until this returns an empty array. The initial `latencySamples()`\n * samples of the concatenated stream are delayed and should be discarded for\n * time-aligned output.\n */\n flushMono(): Float32Array {\n return this.chain.flushMono();\n }\n\n /** Stereo counterpart of {@link flushMono}. */\n flushStereo(): { left: Float32Array; right: Float32Array } {\n return this.chain.flushStereo();\n }\n\n /** Reset all processor state without rebuilding. */\n reset(): void {\n this.chain.reset();\n }\n\n /** Total reported latency in samples across all active processors. */\n latencySamples(): number {\n return this.chain.latencySamples();\n }\n\n /** Ordered stage names that will run (e.g. `\"eq.tilt\"`). */\n stageNames(): string[] {\n return this.chain.stageNames();\n }\n\n /**\n * Samples a stage replaced with a finite in-domain one, keeping the output\n * finite and in range.\n *\n * A non-finite sample supplied by the caller is rejected before any stage\n * runs, so a replacement is always of a value a stage itself produced.\n *\n * Only the true-peak limiters replace anything, so with the maximizer's\n * limiter and the loudness stage both disabled a zero here means no stage was\n * able to replace anything rather than that nothing needed replacing.\n *\n * Cumulative over every block since {@link prepare}, and aggregated over the\n * stages and channels, so it identifies neither which block nor which stage.\n * Read it per block and compare against the previous reading to localize one.\n *\n * {@link prepare} rebuilds the stages and so clears it; {@link reset} does\n * not, because it drops processor state without rebuilding.\n *\n * @example\n * ```typescript\n * chain.processMono(block);\n * if (chain.nonFiniteSubstitutionCount() > previous) {\n * // the block just produced is not derived from `block` everywhere\n * }\n * ```\n */\n nonFiniteSubstitutionCount(): number {\n return this.chain.nonFiniteSubstitutionCount();\n }\n\n /**\n * Processing calls in which a stage discarded its own recursive state\n * because a non-finite value had reached it.\n *\n * The companion to {@link nonFiniteSubstitutionCount}, and not the same\n * measurement -- a caller who assumes they are will read one and think\n * they have the other. That one counts SAMPLES a stage replaced and so\n * sums across stages; a discard is a whole stage returning to its\n * post-reset value and is counted once per call however many stages did\n * it. A stage may run more than once per call, which is why this is a\n * delta over the call and never a sum.\n *\n * Non-finite input is rejected before any stage runs, so what a stage\n * discards is always state it produced itself -- a finite sample large\n * enough to overflow inside a filter, most often. Unlike the substitution\n * count every stage can contribute, so a zero here means no stage\n * discarded rather than that none could.\n *\n * Both {@link processMono}/{@link processStereo} and\n * {@link flushMono}/{@link flushStereo} count, since a flush drives the\n * same stages. {@link prepare} rebuilds the stages and so clears it (as it\n * does {@link nonFiniteSubstitutionCount}, so the two counters on one\n * handle share an epoch); {@link reset} does not, because it drops\n * processor state without rebuilding.\n */\n nonFiniteDiscardCount(): number {\n return this.chain.nonFiniteDiscardCount();\n }\n\n /** Release the underlying WASM object. Idempotent, as the Node facade is. */\n delete(): void {\n if (this.released) {\n return;\n }\n this.released = true;\n this.chain.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n\n// ============================================================================\n// StreamingEqualizer Class\n// ============================================================================\n\n/**\n * Block-by-block streaming equalizer wrapping the unified C++\n * `EqualizerProcessor` (up to 24 bands, RBJ/Vicanek biquads, dynamic EQ,\n * linear-phase FIR, mid/side processing, and auto-gain).\n *\n * State is maintained across {@link processMono}/{@link processStereo} calls.\n * Call {@link delete} (or use `try/finally`) to release the underlying WASM\n * object — the embind handle is not garbage-collected automatically.\n *\n * @example\n * ```typescript\n * const eq = new StreamingEqualizer({ sampleRate: 48000, maxBlockSize: 512 });\n * try {\n * eq.setBand(0, { type: 'HighShelf', frequencyHz: 8000, gainDb: 6, enabled: true });\n * const out = eq.processStereo(left, right);\n * const snapshot = eq.spectrum();\n * } finally {\n * eq.delete();\n * }\n * ```\n */\nexport class StreamingEqualizer {\n private eq: import('./sonare.js').WasmStreamingEqualizer;\n private released = false;\n\n constructor(config: StreamingEqualizerConfig = {}) {\n const module = getSonareModule();\n this.eq = module.createEqualizer(config as Record<string, unknown>);\n }\n\n /**\n * Configure the band at `index` (0..23). Omitted fields use C++ defaults.\n */\n setBand(index: number, band: EqBand): void {\n this.eq.setBand(index, band as Record<string, unknown>);\n }\n\n /** Disable and reset every band. */\n clear(): void {\n this.eq.clear();\n }\n\n /**\n * Set the global phase mode: `'zero'` | `'natural'` | `'linear'` or 1/2/3.\n */\n setPhaseMode(mode: EqPhaseMode): void {\n const value = typeof mode === 'number' ? mode : EQ_PHASE_MODES[mode.toLowerCase()];\n if (value === undefined) {\n throw new Error(`unknown EQ phase mode: ${mode}`);\n }\n this.eq.setPhaseMode(value);\n }\n\n /** Enable or disable output auto-gain compensation. */\n setAutoGain(enabled: boolean): void {\n this.eq.setAutoGain(enabled);\n }\n\n /** Set all-band EQ gain scale as a 0.0..2.0 multiplier. */\n setGainScale(scale: number): void {\n this.eq.setGainScale(scale);\n }\n\n /** Set post-EQ output gain in dB. */\n setOutputGainDb(gainDb: number): void {\n this.eq.setOutputGainDb(gainDb);\n }\n\n /** Set post-EQ stereo balance in -1.0..1.0; mono input ignores pan. */\n setOutputPan(pan: number): void {\n this.eq.setOutputPan(pan);\n }\n\n /**\n * Provide a mono external sidechain key for dynamic bands that opt into\n * `external_sidechain`. The samples are copied into an owned buffer.\n */\n setSidechainMono(samples: Float32Array): void {\n this.eq.setSidechainMono(samples);\n }\n\n /**\n * Provide a stereo external sidechain key. Both channels must match length.\n */\n setSidechainStereo(left: Float32Array, right: Float32Array): void {\n if (left.length !== right.length) {\n throw new Error('Sidechain channel lengths must match.');\n }\n this.eq.setSidechainStereo(left, right);\n }\n\n /** Release any borrowed external sidechain buffers. */\n clearSidechain(): void {\n this.eq.clearSidechain();\n }\n\n /** Auto-gain applied on the most recent block, in dB. */\n lastAutoGainDb(): number {\n return this.eq.lastAutoGainDb();\n }\n\n /** Reported processing latency in samples (non-zero for linear-phase bands). */\n latencySamples(): number {\n return this.eq.latencySamples();\n }\n\n /**\n * Number of blocks in which the EQ discarded recursive state because a\n * non-finite value had reached it.\n *\n * Advisory telemetry, and the only thing that separates a degraded EQ from\n * a clean one. A discard returns the affected filter cells to their\n * post-reset value, so the EQ recovers in silence and the output stays\n * finite and in range while carrying samples unrelated to the input;\n * nothing else reports that this happened.\n *\n * The count covers every IIR plane the band layout uses -- stereo, per\n * channel, and mid/side -- together with the automatic output gain and the\n * detector state the dynamic bands drive. Linear-phase bands are not\n * included and have nothing to include: an FIR keeps no recursive state,\n * so a non-finite sample leaves its history on its own.\n *\n * Unlike a mixer strip's meters, nothing here lags: this EQ has no meter of\n * its own, so a discard is always attributed to the block that carried it.\n *\n * Cumulative since this handle was created and never cleared, so two\n * readings bracket a span of audio. The unit is one processed block, never\n * a channel or a plane.\n */\n nonFiniteDiscardCount(): number {\n return this.eq.nonFiniteDiscardCount();\n }\n\n /**\n * Process one mono block, returning the equalized samples (same length).\n */\n processMono(samples: Float32Array): Float32Array {\n return this.eq.processMono(samples);\n }\n\n /**\n * Process one stereo block, returning the equalized channels.\n */\n processStereo(\n left: Float32Array,\n right: Float32Array,\n ): { left: Float32Array; right: Float32Array } {\n if (left.length !== right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n return this.eq.processStereo(left, right);\n }\n\n /**\n * The composite magnitude of the bands, in dB, at each requested frequency —\n * the curve to draw over {@link spectrum}.\n *\n * Built from the same coefficient design, tilt expansion and cut-slope\n * cascade the audio path uses, so it states what the equalizer does rather\n * than what its settings look like, and it carries the output gain, the gain\n * scale and whatever each dynamic band is applying at the moment of the call.\n * Disabled, bypassed and — when anything is soloed — unsoloed bands drop out,\n * and a soloed band is drawn as the band pass it is heard as.\n *\n * `placement` selects which signal path the curve is for. A band placed on\n * `'Stereo'` is on every path; one placed elsewhere appears only on its own,\n * a mid band having no per-channel magnitude to fold into a left or right\n * curve. Frequencies are clamped to [0 Hz, Nyquist].\n *\n * @example\n * ```ts\n * const freqs = new Float32Array([100, 1000, 10000]);\n * const db = eq.magnitudeResponse(freqs);\n * ```\n */\n magnitudeResponse(\n frequenciesHz: Float32Array,\n placement: EqStereoPlacement = 'Stereo',\n ): Float32Array {\n const value = EQ_PLACEMENTS[placement.toLowerCase()];\n if (value === undefined) {\n throw new Error(`unknown EQ band placement: ${placement}`);\n }\n return this.eq.magnitudeResponse(value, frequenciesHz);\n }\n\n /**\n * Read the latest pre/post spectrum snapshot for metering. `seq` increments\n * each time a new snapshot is published.\n */\n spectrum(): EqSpectrumSnapshot {\n return this.eq.spectrum();\n }\n\n /**\n * Configure bands so the source spectrum matches the reference spectrum.\n *\n * @param source - Source audio (mono samples)\n * @param reference - Reference audio (mono samples)\n * @param options - `sampleRate` (default 48000) and `maxBands` (default 8)\n */\n match(source: Float32Array, reference: Float32Array, options: EqMatchOptions = {}): void {\n this.eq.match(source, reference, options as Record<string, unknown>);\n }\n\n /** Release the underlying WASM object. Idempotent, as the Node facade is. */\n delete(): void {\n if (this.released) {\n return;\n }\n this.released = true;\n this.eq.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n\n// ============================================================================\n// StreamingRetune Class\n// ============================================================================\n\n/**\n * Block-by-block mono voice retune / pitch shifter.\n *\n * State is maintained across {@link processMono} calls. Call {@link prepare}\n * before processing, and call {@link delete} (or use `try/finally`) to release\n * the underlying WASM object.\n */\nexport class StreamingRetune {\n private retune: import('./sonare.js').WasmStreamingRetune;\n private released = false;\n\n constructor(config: StreamingRetuneConfig = {}) {\n const module = getSonareModule();\n this.retune = module.createStreamingRetune(config as Record<string, unknown>);\n }\n\n /**\n * Allocate and initialize native state for the given sample rate and maximum\n * process block size.\n */\n prepare(sampleRate: number, maxBlockSize: number): void {\n this.retune.prepare(sampleRate, maxBlockSize);\n }\n\n /** Reset delay, grain, and overlap-add state without changing config. */\n reset(): void {\n this.retune.reset();\n }\n\n /**\n * Update the live controls; omitted keys keep their current value. Changing\n * `grainSize` takes effect after the next {@link prepare} call, and an\n * omitted `grainSize` keeps whatever was last requested — including the `0`\n * sentinel, so a re-{@link prepare} at another sample rate re-derives it.\n */\n setConfig(config: StreamingRetuneConfig): void {\n this.retune.setConfig(config as Record<string, unknown>);\n }\n\n /** The currently applied controls, with `grainSize` as the effective one. */\n config(): Required<StreamingRetuneConfig> {\n return this.retune.config();\n }\n\n /** Resolved grain size in samples after {@link prepare}. */\n grainSize(): number {\n return this.retune.grainSize();\n }\n\n /** Fixed overlap-add latency in samples (one grain); 0 before prepare. */\n latencySamples(): number {\n return this.retune.latencySamples();\n }\n\n /** Process one mono block, returning the shifted samples (same length). */\n processMono(samples: Float32Array): Float32Array {\n return this.retune.processMono(samples);\n }\n\n /** Release the underlying WASM object. Idempotent, as the Node facade is. */\n delete(): void {\n if (this.released) {\n return;\n }\n this.released = true;\n this.retune.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n","import { projectModule } from './project_internal';\nimport type { TranscribeOptions, TranscribeResult } from './project_types';\nimport { assertSampleRate, assertSamples } from './validation';\n\n/**\n * Canonical request form for {@link transcribe}.\n *\n * Deliberately does NOT extend `ValidateOptions`. That option's contract is\n * that skipping the JS-side scan is safe because the native layer re-validates\n * with an equivalent result -- and here it would not be equivalent: the\n * transcription C ABI (`sonare_transcribe`) does re-validate the buffer,\n * including a non-finite scan, but a rejection there surfaces as a\n * `SonareError` `InvalidParameter`, not the `RangeError` this function\n * documents and every other empty/non-finite/rate check on this surface\n * raises. A `{ validate: false }` here would silently change the thrown error\n * class instead of skipping a redundant check. The scan is also nearly free\n * against this pipeline, which already reads every sample several times.\n */\nexport interface TranscribeRequest extends TranscribeOptions {\n /** Mono source audio. Must be non-empty and all-finite. */\n samples: Float32Array;\n /** Sample rate of `samples` in Hz, `[8000, 384000]`. */\n sampleRate: number;\n /**\n * Tempo the PPQ grid is built on, in BPM. **Omit to have it detected** from\n * `samples`, which costs an onset/tempo pass; a detector that finds nothing\n * usable falls back to 120 rather than failing the transcription.\n *\n * Supplying a tempo is not a claim about the audio — it is the coordinate\n * system the events come back in. Twice the tempo is twice as many beats per\n * second, so the same audio lands on twice the ppq.\n */\n tempoBpm?: number;\n}\n\n/**\n * Transcribes mono audio into MIDI events on a constant-tempo grid.\n *\n * This joins parts that already exist rather than adding a detector: the note\n * spans and their measured pitch and level come from the monophonic (pYIN) or\n * polyphonic (multi-F0) chain, and the output is the flat\n * {@link ProjectMidiEvent} shape {@link Project.setMidiEvents} takes, so\n * nothing is left to convert.\n *\n * Finding no notes is not an error. Silence, and material the chain cannot\n * resolve, come back with an empty `events` array and `noteCount` 0, and\n * `tempoBpm` still reports the tempo that was used or detected.\n *\n * Three things are deliberately **not** done here, because the library already\n * does each of them somewhere else and a second implementation would drift:\n *\n * - **Quantizing to a grid** — {@link Project.bakeMidiFx}'s `quantizePpq` /\n * `quantizeStrength`.\n * - **Detecting and installing a tempo map** — {@link Project.autoTempo}. The\n * `tempoBpm` fallback here builds one constant-tempo grid for this call and\n * installs nothing; use {@link Project.transcribeToClip} to transcribe onto a\n * project's real map.\n * - **Annotating key and chords** — {@link Project.annotateKeys} /\n * {@link Project.annotateChords}.\n *\n * The tuning reference is likewise not measured — see\n * {@link TranscribeOptions.referenceHz}.\n *\n * @throws {RangeError} on empty `samples`, a non-finite sample, or a\n * `sampleRate` outside `[8000, 384000]`\n * @throws {SonareError} `InvalidParameter` on an option outside its domain —\n * a non-negative `velocityFloorDb`, a `fixedVelocity` outside `[1, 127]`, a\n * `group` or `channel` outside `[0, 15]`, an `fmax` at or below `fmin`, or a\n * written `0` on any field but `group` and `channel` — or `NotSupported`\n * when the library was built without the pitch editor\n *\n * @example\n * ```typescript\n * const { events, noteCount, tempoBpm } = transcribe({ samples, sampleRate, tempoBpm: 120 });\n * const project = new Project();\n * const { clipId } = project.addMidiClip(0, 16); // 4 bars at 4/4, in quarter notes (PPQ)\n * project.setMidiEvents(clipId, events);\n * ```\n */\nexport function transcribe(request: TranscribeRequest): TranscribeResult {\n assertSamples('transcribe', request.samples, true);\n assertSampleRate('transcribe', request.sampleRate);\n return projectModule().transcribe(\n request.samples,\n request.sampleRate,\n request.tempoBpm,\n request as unknown as TranscribeOptions,\n );\n}\n","import type { MidiCcBindOptions } from './realtime_engine';\nimport { assertNibble } from './validation';\n\nexport interface WebMidiEngine {\n bindMidiCc(\n channel: number,\n controller: number,\n paramId: number,\n options?: MidiCcBindOptions,\n ): void;\n setMidiInputSource(destinationId?: number): void;\n clearMidiInputSource(): void;\n pushMidiInputNoteOn(\n group: number,\n channel: number,\n note: number,\n velocity: number,\n time?: number,\n ): void;\n pushMidiInputNoteOff(\n group: number,\n channel: number,\n note: number,\n velocity?: number,\n time?: number,\n ): void;\n pushMidiInputCc(\n group: number,\n channel: number,\n controller: number,\n value: number,\n time?: number,\n ): void;\n}\n\ntype MidiInputState = 'connected' | 'disconnected';\n\ninterface MidiPortLike {\n id: string;\n name?: string | null;\n manufacturer?: string | null;\n state?: MidiInputState;\n}\n\ninterface MidiMessageEventLike {\n data: ArrayLike<number>;\n timeStamp?: number;\n receivedTime?: number;\n target?: MidiPortLike;\n currentTarget?: MidiPortLike;\n}\n\ninterface MidiInputLike extends MidiPortLike {\n type?: 'input';\n onmidimessage: ((event: MidiMessageEventLike) => void) | null;\n addEventListener?: (type: 'midimessage', listener: (event: MidiMessageEventLike) => void) => void;\n removeEventListener?: (\n type: 'midimessage',\n listener: (event: MidiMessageEventLike) => void,\n ) => void;\n}\n\ninterface MidiConnectionEventLike {\n port?: MidiPortLike | null;\n}\n\ninterface MidiAccessLike {\n inputs: Map<string, MidiInputLike> | Iterable<[string, MidiInputLike]>;\n onstatechange: ((event: MidiConnectionEventLike) => void) | null;\n addEventListener?: (\n type: 'statechange',\n listener: (event: MidiConnectionEventLike) => void,\n ) => void;\n removeEventListener?: (\n type: 'statechange',\n listener: (event: MidiConnectionEventLike) => void,\n ) => void;\n}\n\ninterface NavigatorWithMidi {\n requestMIDIAccess?: (options?: {\n sysex?: boolean;\n software?: boolean;\n }) => Promise<MidiAccessLike>;\n}\n\nexport interface WebMidiCcBinding {\n channel: number;\n controller: number;\n paramId: number;\n options?: MidiCcBindOptions;\n}\n\nexport interface WebMidiInputInfo {\n id: string;\n name: string;\n manufacturer: string;\n state: MidiInputState;\n}\n\nexport interface BindWebMidiOptions {\n /** Realtime-engine MIDI destination receiving the live input source. Default `0`. */\n destinationId?: number;\n /** UMP group used for MIDI 1.0 channel voice events. Default `0`. */\n group?: number;\n /** Restrict binding to specific Web MIDI input ids. Omit or empty = all connected inputs. */\n inputIds?: readonly string[];\n /** Request SysEx-capable access from the browser. Default `false`. */\n sysex?: boolean;\n /** Request software ports from the browser where supported. Default `true`. */\n software?: boolean;\n /** Bind CC-to-parameter mappings before ports are connected. */\n ccBindings?: readonly WebMidiCcBinding[];\n /** Convert a Web MIDI event timestamp to engine port-time samples. */\n timestampToSamples?: (eventTimeMs: number) => number;\n /** Observe hot-plug updates after the helper rebinds matching inputs. */\n onInputsChanged?: (inputs: WebMidiInputInfo[]) => void;\n}\n\nexport interface WebMidiBinding {\n access: MidiAccessLike;\n inputs(): WebMidiInputInfo[];\n close(): void;\n}\n\ntype BoundInput = {\n input: MidiInputLike;\n listener: (event: MidiMessageEventLike) => void;\n runningStatus: number;\n};\n\nexport function isWebMidiAvailable(): boolean {\n return (\n typeof (globalThis.navigator as NavigatorWithMidi | undefined)?.requestMIDIAccess === 'function'\n );\n}\n\nexport async function bindWebMidi(\n engine: WebMidiEngine,\n options: BindWebMidiOptions = {},\n): Promise<WebMidiBinding> {\n const navigatorWithMidi = globalThis.navigator as NavigatorWithMidi | undefined;\n if (typeof navigatorWithMidi?.requestMIDIAccess !== 'function') {\n throw new Error('Web MIDI is not available in this environment');\n }\n\n const group = options.group ?? 0;\n assertNibble('bindWebMidi', group, 'group');\n const destinationId = options.destinationId ?? 0;\n const selectedIds = new Set(options.inputIds ?? []);\n // Invoke through the navigator so the browser's native method keeps its\n // required `this` binding (detached calls throw \"Illegal invocation\").\n const access = await navigatorWithMidi.requestMIDIAccess({\n sysex: options.sysex ?? false,\n software: options.software ?? true,\n });\n\n for (const binding of options.ccBindings ?? []) {\n engine.bindMidiCc(binding.channel, binding.controller, binding.paramId, binding.options);\n }\n engine.setMidiInputSource(destinationId);\n\n const bound = new Map<string, BoundInput>();\n let closed = false;\n\n const shouldBind = (input: MidiInputLike) =>\n input.state !== 'disconnected' && (selectedIds.size === 0 || selectedIds.has(input.id));\n\n const snapshotInputs = (): WebMidiInputInfo[] =>\n Array.from(iterInputs(access), ([id, input]) => ({\n id,\n name: input.name ?? '',\n manufacturer: input.manufacturer ?? '',\n state: input.state ?? 'connected',\n }));\n\n const notify = () => options.onInputsChanged?.(snapshotInputs());\n\n const bindInput = (input: MidiInputLike) => {\n if (bound.has(input.id) || !shouldBind(input)) {\n return;\n }\n const entry: BoundInput = {\n input,\n listener: (event: MidiMessageEventLike) => {\n entry.runningStatus = dispatchMidiMessage(\n engine,\n event,\n group,\n entry.runningStatus,\n options.timestampToSamples,\n );\n },\n runningStatus: 0,\n };\n const listener = entry.listener;\n if (input.addEventListener) {\n input.addEventListener('midimessage', listener);\n } else {\n input.onmidimessage = listener;\n }\n bound.set(input.id, entry);\n };\n\n const unbindInput = (input: MidiInputLike) => {\n const entry = bound.get(input.id);\n if (!entry) {\n return;\n }\n if (entry.input.removeEventListener) {\n entry.input.removeEventListener('midimessage', entry.listener);\n } else if (entry.input.onmidimessage === entry.listener) {\n entry.input.onmidimessage = null;\n }\n bound.delete(input.id);\n };\n\n // Does not call notify() itself: both call sites below (the initial sync\n // and stateListener's fallback branch) already notify exactly once after\n // calling this, so notifying here too would fire onInputsChanged twice per\n // hotplug event that goes through the fallback branch.\n const refreshInputs = () => {\n for (const [, entry] of bound) {\n if (!shouldBind(entry.input)) {\n unbindInput(entry.input);\n }\n }\n for (const [, input] of iterInputs(access)) {\n bindInput(input);\n }\n };\n\n const stateListener = (event: MidiConnectionEventLike) => {\n if (closed) {\n return;\n }\n if (event.port && 'onmidimessage' in event.port) {\n const input = event.port as MidiInputLike;\n if (shouldBind(input)) {\n bindInput(input);\n } else {\n unbindInput(input);\n }\n } else {\n refreshInputs();\n }\n notify();\n };\n\n refreshInputs();\n notify();\n if (access.addEventListener) {\n access.addEventListener('statechange', stateListener);\n } else {\n access.onstatechange = stateListener;\n }\n\n return {\n access,\n inputs: snapshotInputs,\n close() {\n closed = true;\n if (access.removeEventListener) {\n access.removeEventListener('statechange', stateListener);\n } else if (access.onstatechange === stateListener) {\n access.onstatechange = null;\n }\n for (const [, entry] of Array.from(bound)) {\n unbindInput(entry.input);\n }\n engine.clearMidiInputSource();\n },\n };\n}\n\nfunction dispatchMidiMessage(\n engine: WebMidiEngine,\n event: MidiMessageEventLike,\n group: number,\n runningStatus: number,\n timestampToSamples?: (eventTimeMs: number) => number,\n): number {\n const data = event.data;\n if (data.length === 0) {\n return 0;\n }\n const first = data[0];\n if (first > 0xff) {\n dispatchUmpMessage(\n engine,\n data,\n timestampToSamples?.(event.receivedTime ?? event.timeStamp ?? 0) ?? 0,\n );\n return 0;\n }\n\n let offset = 0;\n let status = first & 0xff;\n if (status < 0x80) {\n if (runningStatus === 0) {\n return 0;\n }\n status = runningStatus;\n } else {\n offset = 1;\n }\n\n const message = status & 0xf0;\n const channel = status & 0x0f;\n if (message < 0x80 || message > 0xe0) {\n return status >= 0xf8 ? runningStatus : 0;\n }\n\n const a = readU7(data, offset);\n const b = readU7(data, offset + 1);\n if (a < 0 || b < 0) {\n return status;\n }\n\n const portTimeSamples = timestampToSamples\n ? timestampToSamples(event.receivedTime ?? event.timeStamp ?? 0)\n : 0;\n\n if (message === 0x80) {\n engine.pushMidiInputNoteOff(group, channel, a, b, portTimeSamples);\n } else if (message === 0x90) {\n if (b === 0) {\n engine.pushMidiInputNoteOff(group, channel, a, 0, portTimeSamples);\n } else {\n engine.pushMidiInputNoteOn(group, channel, a, b, portTimeSamples);\n }\n } else if (message === 0xb0 && b >= 0) {\n engine.pushMidiInputCc(group, channel, a, b, portTimeSamples);\n }\n\n return status;\n}\n\nfunction dispatchUmpMessage(\n engine: WebMidiEngine,\n words: ArrayLike<number>,\n portTimeSamples: number,\n): void {\n const word0 = words[0] >>> 0;\n const messageType = word0 >>> 28;\n const group = (word0 >>> 24) & 0x0f;\n\n if (messageType === 0x2) {\n const status = (word0 >>> 16) & 0xff;\n const message = status & 0xf0;\n const channel = status & 0x0f;\n const a = (word0 >>> 8) & 0x7f;\n const b = word0 & 0x7f;\n if (message === 0x80) {\n engine.pushMidiInputNoteOff(group, channel, a, b, portTimeSamples);\n } else if (message === 0x90) {\n if (b === 0) {\n engine.pushMidiInputNoteOff(group, channel, a, 0, portTimeSamples);\n } else {\n engine.pushMidiInputNoteOn(group, channel, a, b, portTimeSamples);\n }\n } else if (message === 0xb0) {\n engine.pushMidiInputCc(group, channel, a, b, portTimeSamples);\n }\n return;\n }\n\n if (messageType === 0x4 && words.length >= 2) {\n const status = (word0 >>> 20) & 0x0f;\n const channel = (word0 >>> 16) & 0x0f;\n const data1 = (word0 >>> 8) & 0x7f;\n const word1 = words[1] >>> 0;\n if (status === 0x8) {\n engine.pushMidiInputNoteOff(group, channel, data1, (word1 >>> 25) & 0x7f, portTimeSamples);\n } else if (status === 0x9) {\n // MIDI 2.0 note-on is distinct from note-off (status 0x8). Downsample\n // its 16-bit velocity to the engine's 7-bit API, retaining a nonzero\n // note-on even when the top seven bits are all zero.\n const velocity = Math.max(1, (word1 >>> 25) & 0x7f);\n engine.pushMidiInputNoteOn(group, channel, data1, velocity, portTimeSamples);\n } else if (status === 0xb) {\n engine.pushMidiInputCc(group, channel, data1, (word1 >>> 25) & 0x7f, portTimeSamples);\n }\n }\n}\n\nfunction readU7(data: ArrayLike<number>, index: number): number {\n if (index >= data.length) {\n return -1;\n }\n const value = data[index];\n if (!Number.isInteger(value) || value < 0 || value > 127) {\n return -1;\n }\n return value;\n}\n\nfunction iterInputs(access: MidiAccessLike): Iterable<[string, MidiInputLike]> {\n return access.inputs instanceof Map ? access.inputs.entries() : access.inputs;\n}\n","import { ErrorCode, SonareError } from './errors';\nimport type { MasterAudioRequest, MasterAudioStereoRequest } from './mastering_chain';\nimport type {\n DetectChordsRequest,\n DetectKeyRequest,\n MusicAnalyzeRequest,\n SamplesRequest,\n} from './quick_analysis';\nimport type { OfflineWorkerOperation, OfflineWorkerResponseMessage } from './worker_protocol';\n\ntype WorkerRequest<T> = Omit<T, 'onProgress'>;\n\n/** Progress relayed from the Worker at the core's native progress boundaries. */\nexport interface OfflineWorkerProgress {\n progress: number;\n stage: string;\n}\n\n/** Per-call behaviour for a one-shot operation. */\nexport interface OfflineWorkerCallOptions {\n /**\n * Preserve the caller's input arrays by copying them before dispatch.\n *\n * The default is `false`: `Float32Array` buffers are transferred to the\n * Worker and become detached on the calling thread, avoiding a second copy.\n */\n copy?: boolean;\n /** Receives native progress boundaries for analysis and mastering calls. */\n onProgress?: (update: OfflineWorkerProgress) => void;\n}\n\n/** Options used to create an {@link OfflineWorkerClient}. */\nexport interface OfflineWorkerClientOptions {\n /** Reuse a Worker owned by the host instead of creating one. */\n worker?: OfflineWorker;\n /** URL of the Worker entry; defaults to the adjacent published `worker.js`. */\n workerUrl?: string | URL;\n /** Test/host hook for creating a dedicated Worker. */\n workerFactory?: (url: URL) => OfflineWorker;\n /** Terminate a supplied Worker when {@link OfflineWorkerClient.dispose} runs. */\n terminateWorkerOnDispose?: boolean;\n}\n\n/** Browser Worker or Node `worker_threads.Worker` used by the client. */\nexport interface OfflineWorker {\n postMessage(message: unknown, transfer?: Transferable[]): void;\n terminate(): unknown;\n addEventListener?(type: string, listener: EventListener): void;\n removeEventListener?(type: string, listener: EventListener): void;\n on?(type: 'message' | 'error', listener: (...args: unknown[]) => void): unknown;\n off?(type: 'message' | 'error', listener: (...args: unknown[]) => void): unknown;\n}\n\n/**\n * A cancellable promise returned by an {@link OfflineWorkerClient} call.\n *\n * It is Promise-like, so `await client.analyze(...)` works. Call `cancel()` to\n * request cancellation at the next native progress boundary. In browsers this\n * uses a `SharedArrayBuffer` flag, which requires cross-origin isolation for\n * prompt cancellation while synchronous WASM is running. The worker forwards\n * that flag through the same native cancellation callback used by synchronous\n * one-shot requests.\n */\nexport class OfflineWorkerTask<T> implements PromiseLike<T> {\n constructor(\n readonly result: Promise<T>,\n private readonly cancelRequest: () => void,\n ) {}\n\n cancel(): void {\n this.cancelRequest();\n }\n\n // biome-ignore lint/suspicious/noThenProperty: this intentionally implements PromiseLike so callers can await a task and cancel it.\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return this.result.then(onfulfilled, onrejected);\n }\n\n catch<TResult = never>(\n onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null,\n ): Promise<T | TResult> {\n return this.result.catch(onrejected);\n }\n\n finally(onfinally?: (() => void) | null): Promise<T> {\n return this.result.finally(onfinally);\n }\n}\n\ninterface PendingCall {\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n onProgress?: (update: OfflineWorkerProgress) => void;\n cancelFlag?: Int32Array;\n}\n\nfunction cloneForWorker(\n value: unknown,\n copy: boolean,\n transfers: Transferable[],\n transferred = new Set<ArrayBuffer>(),\n): unknown {\n if (value instanceof Float32Array) {\n const samples = copy ? value.slice() : value;\n const buffer = samples.buffer;\n if (!(buffer instanceof ArrayBuffer)) {\n throw new TypeError(\n 'OfflineWorkerClient only transfers Float32Array values backed by ArrayBuffer',\n );\n }\n if (!transferred.has(buffer)) {\n transferred.add(buffer);\n transfers.push(buffer);\n }\n return samples;\n }\n if (Array.isArray(value)) {\n return value.map((item) => cloneForWorker(item, copy, transfers, transferred));\n }\n if (value !== null && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [\n key,\n cloneForWorker(item, copy, transfers, transferred),\n ]),\n );\n }\n return value;\n}\n\nfunction cancellationFlag(): Int32Array | undefined {\n if (typeof SharedArrayBuffer === 'undefined') {\n return undefined;\n }\n return new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));\n}\n\nfunction workerError(\n message: Extract<OfflineWorkerResponseMessage, { type: 'sonare:offline-error' }>,\n): Error {\n if (message.error.code !== undefined) {\n return new SonareError(\n message.error.code,\n message.error.codeName ?? 'Unknown',\n message.error.message,\n );\n }\n const error = new Error(message.error.message);\n error.name = message.error.name;\n return error;\n}\n\n/**\n * Owns a dedicated Worker for value-based offline analysis and mastering.\n *\n * `Project`, `Mixer`, and realtime APIs are intentionally absent: their native\n * handles are local to one JavaScript realm and cannot be transferred safely.\n */\nexport class OfflineWorkerClient {\n private readonly worker: OfflineWorker;\n private readonly ownsWorker: boolean;\n private readonly pending = new Map<number, PendingCall>();\n private nextId = 1;\n private closed = false;\n private usesEventTarget = false;\n\n constructor(options: OfflineWorkerClientOptions = {}) {\n this.ownsWorker = options.worker === undefined || options.terminateWorkerOnDispose === true;\n if (options.worker) {\n this.worker = options.worker;\n } else {\n if (!options.workerFactory && typeof Worker === 'undefined') {\n throw new Error('OfflineWorkerClient requires a browser Worker implementation');\n }\n const url =\n options.workerUrl === undefined\n ? new URL('./worker.js', import.meta.url)\n : new URL(options.workerUrl, import.meta.url);\n this.worker =\n options.workerFactory?.(url) ?? new Worker(url, { type: 'module', name: 'sonare-offline' });\n }\n if (this.worker.addEventListener) {\n this.usesEventTarget = true;\n this.worker.addEventListener('message', this.onMessage as EventListener);\n this.worker.addEventListener('error', this.onError as EventListener);\n } else if (this.worker.on) {\n this.worker.on('message', this.onNodeMessage);\n this.worker.on('error', this.onNodeError);\n } else {\n throw new TypeError('OfflineWorkerClient requires Worker event listeners');\n }\n }\n\n /** Dispatch full music analysis to the Worker. */\n analyze(\n request: WorkerRequest<MusicAnalyzeRequest>,\n options?: OfflineWorkerCallOptions,\n ): OfflineWorkerTask<ReturnType<typeof import('./quick_analysis').analyze>> {\n return this.call('analyze', request, options);\n }\n\n /** Dispatch BPM detection to the Worker. */\n detectBpm(\n request: SamplesRequest,\n options?: OfflineWorkerCallOptions,\n ): OfflineWorkerTask<number> {\n return this.call('detectBpm', request, options);\n }\n\n /** Dispatch key detection to the Worker. */\n detectKey(\n request: DetectKeyRequest,\n options?: OfflineWorkerCallOptions,\n ): OfflineWorkerTask<ReturnType<typeof import('./quick_analysis').detectKey>> {\n return this.call('detectKey', request, options);\n }\n\n /** Dispatch chord detection to the Worker. */\n detectChords(\n request: DetectChordsRequest,\n options?: OfflineWorkerCallOptions,\n ): OfflineWorkerTask<ReturnType<typeof import('./quick_analysis').detectChords>> {\n return this.call('detectChords', request, options);\n }\n\n /** Dispatch mono preset mastering to the Worker. */\n masterAudio(\n request: WorkerRequest<MasterAudioRequest>,\n options?: OfflineWorkerCallOptions,\n ): OfflineWorkerTask<ReturnType<typeof import('./mastering_chain').masterAudio>> {\n return this.call('masterAudio', request, options);\n }\n\n /** Dispatch stereo preset mastering to the Worker. */\n masterAudioStereo(\n request: WorkerRequest<MasterAudioStereoRequest>,\n options?: OfflineWorkerCallOptions,\n ): OfflineWorkerTask<ReturnType<typeof import('./mastering_chain').masterAudioStereo>> {\n return this.call('masterAudioStereo', request, options);\n }\n\n /** Stop accepting calls, reject outstanding work, and release the Worker if owned. */\n dispose(): void {\n if (this.closed) {\n return;\n }\n this.closed = true;\n if (this.usesEventTarget) {\n this.worker.removeEventListener?.('message', this.onMessage as EventListener);\n this.worker.removeEventListener?.('error', this.onError as EventListener);\n } else {\n this.worker.off?.('message', this.onNodeMessage);\n this.worker.off?.('error', this.onNodeError);\n }\n for (const { reject } of this.pending.values()) {\n reject(new Error('OfflineWorkerClient was disposed'));\n }\n this.pending.clear();\n if (this.ownsWorker) {\n this.worker.terminate();\n }\n }\n\n private call<T>(\n operation: OfflineWorkerOperation,\n request: object,\n options: OfflineWorkerCallOptions = {},\n ): OfflineWorkerTask<T> {\n if (this.closed) {\n throw new Error('OfflineWorkerClient was disposed');\n }\n const id = this.nextId++;\n const transfers: Transferable[] = [];\n const preparedRequest = cloneForWorker(request, options.copy === true, transfers) as Record<\n string,\n unknown\n >;\n const cancelFlag = cancellationFlag();\n const result = new Promise<T>((resolve, reject) => {\n this.pending.set(id, {\n resolve: (value) => resolve(value as T),\n reject,\n onProgress: options.onProgress,\n cancelFlag,\n });\n });\n this.worker.postMessage(\n {\n type: 'sonare:offline-run',\n id,\n operation,\n request: preparedRequest,\n ...(cancelFlag ? { cancelBuffer: cancelFlag.buffer as SharedArrayBuffer } : {}),\n },\n transfers,\n );\n return new OfflineWorkerTask(result, () => {\n if (!this.pending.has(id)) {\n return;\n }\n if (cancelFlag) {\n Atomics.store(cancelFlag, 0, 1);\n }\n // A message also covers a call cancelled before it begins and is the\n // best available fallback where SharedArrayBuffer is unavailable.\n this.worker.postMessage({ type: 'sonare:offline-cancel', id });\n });\n }\n\n private readonly onMessage = (event: MessageEvent<OfflineWorkerResponseMessage>): void => {\n const message = event.data;\n const pending = this.pending.get(message.id);\n if (!pending) {\n return;\n }\n if (message.type === 'sonare:offline-progress') {\n pending.onProgress?.({ progress: message.progress, stage: message.stage });\n return;\n }\n this.pending.delete(message.id);\n if (message.type === 'sonare:offline-result') {\n pending.resolve(message.result);\n return;\n }\n pending.reject(workerError(message));\n };\n\n private readonly onError = (event: ErrorEvent): void => {\n const error = new Error(event.message || 'Offline Worker failed');\n for (const { reject } of this.pending.values()) {\n reject(error);\n }\n this.pending.clear();\n };\n\n private readonly onNodeMessage = (data: unknown): void => {\n this.onMessage({ data } as MessageEvent<OfflineWorkerResponseMessage>);\n };\n\n private readonly onNodeError = (error: unknown): void => {\n this.onError(\n error instanceof Error\n ? ({ message: error.message } as ErrorEvent)\n : ({ message: String(error) } as ErrorEvent),\n );\n };\n}\n\nexport { ErrorCode };\n","/**\n * sonare - Audio Analysis Library\n *\n * @example\n * ```typescript\n * import { init, detectBpm, detectKey, analyze } from '@libraz/libsonare';\n *\n * await init();\n *\n * // Detect BPM from audio samples\n * const bpm = detectBpm(samples, sampleRate);\n *\n * // Detect musical key\n * const key = detectKey(samples, sampleRate);\n *\n * // Full analysis\n * const result = analyze(samples, sampleRate);\n * ```\n */\n\nimport { setSonareModule } from './module_state';\nimport type {\n CapabilityCatalog,\n RealtimeVoiceChangerPodConfig,\n SonareCapabilities,\n VoicePresetId,\n} from './public_types';\nimport type {\n SonareModule,\n WasmDecomposeResult,\n WasmHpssWithResidualResult,\n WasmMatrix2dResult,\n} from './sonare.js';\n\nexport { alignTakeToReference } from './align_take';\nexport type { BrowserAudioDecodeOptions } from './audio';\nexport { Audio } from './audio';\nexport type {\n ClipPageStreamerEngine,\n ClipPageStreamerOptions,\n ClipPageStreamerRequest,\n ClipPageStreamSource,\n OpfsClipStream,\n OpfsClipStreamOptions,\n WorkletOpfsClipStreamHost,\n} from './clip_page_streamer';\nexport { attachOpfsClipStream, ClipPageStreamer } from './clip_page_streamer';\nexport type {\n CompressorDetector,\n CompressorOptions,\n DeclickOptions,\n DeclipOptions,\n DecrackleMode,\n DecrackleOptions,\n DehumMode,\n DehumOptions,\n DenoiseClassicalMode,\n DenoiseClassicalNoiseEstimator,\n DenoiseClassicalOptions,\n DereverbClassicalOptions,\n DynamicsProcessorResult,\n GateOptions,\n MasteringAbMatchLoudnessRequest,\n MasteringAmpPresetCatalogEntry,\n MasteringAssistantParamsRequest,\n MasteringAssistantStereoParamsRequest,\n MasteringChannelPolicy,\n MasteringDynamicsCompressorRequest,\n MasteringDynamicsGateRequest,\n MasteringDynamicsTransientShaperRequest,\n MasteringInsertParamChoice,\n MasteringInsertParamInfo,\n MasteringInsertSlot,\n MasteringInsertTiming,\n MasteringPairAnalyzeRequest,\n MasteringPairProcessRequest,\n MasteringProcessorCatalogEntry,\n MasteringProcessorCategory,\n MasteringProcessRequest,\n MasteringProcessStereoRequest,\n MasteringRealtimeCost,\n MasteringRepairDeclickRequest,\n MasteringRepairDeclickStereoRequest,\n MasteringRepairDeclipRequest,\n MasteringRepairDeclipStereoRequest,\n MasteringRepairDecrackleRequest,\n MasteringRepairDecrackleStereoRequest,\n MasteringRepairDehumRequest,\n MasteringRepairDehumStereoRequest,\n MasteringRepairDenoiseClassicalLinkedRequest,\n MasteringRepairDenoiseClassicalRequest,\n MasteringRepairDenoiseClassicalStereoRequest,\n MasteringRepairDereverbClassicalLinkedRequest,\n MasteringRepairDereverbClassicalRequest,\n MasteringRepairDereverbClassicalStereoRequest,\n MasteringRepairDereverbConfigForRoomRequest,\n MasteringRepairDetectClicksRequest,\n MasteringRepairDetectClippingRequest,\n MasteringRepairDetectCrackleRequest,\n MasteringRepairDetectHumRequest,\n MasteringRepairDetectNoiseFloorRequest,\n MasteringRepairDetectReverbRequest,\n MasteringRepairDetectTrimRangeRequest,\n MasteringRepairDetectTrimRangeStereoRequest,\n MasteringRepairNoiseBandBinsRequest,\n MasteringRepairTrimSilenceRequest,\n MasteringRepairTrimSilenceStereoRequest,\n MasteringSamplesParamsRequest,\n MasteringStereoAnalyzeRequest,\n MasteringStereoParamsRequest,\n MasteringStreamingPreviewRequest,\n MasteringStreamingPreviewStereoRequest,\n MixStereoRequest,\n TransientShaperOptions,\n TrimSilenceMode,\n TrimSilenceOptions,\n VoiceChangeOptions,\n VoiceChangeRealtimeOptions,\n VoiceChangeRealtimeRequest,\n VoiceChangeRequest,\n} from './effects_mastering';\nexport {\n assignNoteTargets,\n decomposeNotePitch,\n extractNotes,\n extractPercussiveEvents,\n harmonic,\n hpss,\n masterAudio,\n masterAudioStereo,\n masterAudioStereoWithProgress,\n masterAudioWithProgress,\n mastering,\n masteringAbMatchLoudness,\n masteringAmpPresetCatalog,\n masteringAssistantSuggest,\n masteringAssistantSuggestChain,\n masteringAssistantSuggestChainStereo,\n masteringAssistantSuggestStereo,\n masteringAudioProfile,\n masteringAudioProfileStereo,\n masteringChain,\n masteringChainStereo,\n masteringChainStereoWithProgress,\n masteringChainWithProgress,\n masteringDynamicsCompressor,\n masteringDynamicsGate,\n masteringDynamicsTransientShaper,\n masteringInsertNames,\n masteringInsertParamInfo,\n masteringInsertParamNames,\n masteringInsertTiming,\n masteringPairAnalysisNames,\n masteringPairAnalyze,\n masteringPairProcess,\n masteringPairProcessorNames,\n masteringPlatformNames,\n masteringPresetNames,\n masteringPresetParams,\n masteringProcess,\n masteringProcessorCatalog,\n masteringProcessorNames,\n masteringProcessStereo,\n masteringRepairDeclick,\n masteringRepairDeclickStereo,\n masteringRepairDeclip,\n masteringRepairDeclipStereo,\n masteringRepairDecrackle,\n masteringRepairDecrackleStereo,\n masteringRepairDehum,\n masteringRepairDehumStereo,\n masteringRepairDenoiseClassical,\n masteringRepairDenoiseClassicalLinked,\n masteringRepairDenoiseClassicalStereo,\n masteringRepairDereverbClassical,\n masteringRepairDereverbClassicalLinked,\n masteringRepairDereverbClassicalStereo,\n masteringRepairDereverbConfigForRoom,\n masteringRepairDetectClicks,\n masteringRepairDetectClipping,\n masteringRepairDetectCrackle,\n masteringRepairDetectHum,\n masteringRepairDetectNoiseFloor,\n masteringRepairDetectReverb,\n masteringRepairDetectTrimRange,\n masteringRepairDetectTrimRangeStereo,\n masteringRepairNoiseBandBins,\n masteringRepairTrimSilence,\n masteringRepairTrimSilenceStereo,\n masteringStereoAnalysisNames,\n masteringStereoAnalyze,\n masteringStreamingPreview,\n masteringStreamingPreviewStereo,\n mergeNotes,\n mixingScenePresetJson,\n mixingScenePresetNames,\n mixStereo,\n normalize,\n normalizeStereo,\n noteMove,\n noteStretch,\n noteTargetsFromSmf,\n percussive,\n pitchCorrectTimevarying,\n pitchCorrectToMidi,\n pitchCorrectToMidiTimevarying,\n pitchShift,\n renderNotes,\n renderPercussiveEvents,\n spectralEdit,\n splitNote,\n timeStretch,\n voiceChange,\n voiceChangeRealtime,\n} from './effects_mastering';\nexport type {\n AssignNoteTargetsRequest,\n DecomposeNotePitchRequest,\n ExtractNotesRequest,\n MergeNotesRequest,\n NoteMoveRequest,\n NoteSetRequest,\n NoteStretchRequest,\n NoteTargetsFromSmfRequest,\n RenderNotesRequest,\n SplitNoteRequest,\n} from './effects_note_ops';\nexport type {\n ExtractPercussiveEventsRequest,\n PercussiveSeparationOptions,\n RenderPercussiveEventsRequest,\n} from './effects_percussive';\nexport type { HarmonicRequest, HpssRequest, PercussiveRequest } from './effects_separation';\nexport type { SpectralEditRequest } from './effects_spectral';\nexport type {\n PitchCorrectTimevaryingRequest,\n PitchCorrectToMidiRequest,\n PitchCorrectToMidiTimevaryingRequest,\n PitchShiftRequest,\n TimeStretchRequest,\n} from './effects_timepitch';\nexport { ErrorCode, isSonareError, SonareError } from './errors';\nexport type {\n ChirpRequest,\n ClicksRequest,\n CyclicTempogramRequest,\n DbConversionRequest,\n EmphasisRequest,\n FixFramesRequest,\n FixLengthRequest,\n FrameSignalRequest,\n OnsetBacktrackRequest,\n PadCenterRequest,\n PcenRequest,\n PeakPickRequest,\n PlpRequest,\n SilenceCommonReport,\n SilenceRequest,\n SplitSilenceCommonRequest,\n SplitSilenceCommonWithReportResult,\n TempogramRequest,\n ToneRequest,\n TonnetzRequest,\n VectorNormalizeRequest,\n} from './feature_core';\nexport type {\n DecomposeRequest,\n DecomposeStemsLinkedRequest,\n DecomposeStemsLinkedResult,\n DecomposeStemsRequest,\n DecomposeStemsResult,\n DecomposeWithInitRequest,\n HpssWithResidualRequest,\n NnFilterRequest,\n RemixRequest,\n SegmentAgglomerativeRequest,\n SegmentCrossSimilarityRequest,\n SegmentLagToRecurrenceRequest,\n SegmentPathEnhanceRequest,\n SegmentRecurrenceMatrixRequest,\n SegmentRecurrenceToLagRequest,\n SegmentSubsegmentRequest,\n} from './feature_decompose';\nexport type {\n GriffinLimRequest,\n MelToAudioRequest,\n MelToStftRequest,\n MfccToAudioRequest,\n MfccToMelRequest,\n PhaseVocoderRequest,\n} from './feature_inverse';\nexport type {\n Ebur128LoudnessRangeRequest,\n LufsInterleavedRequest,\n LufsSeriesInterleavedRequest,\n} from './feature_loudness';\nexport type {\n AnalyzeMelodyRequest,\n AnalyzeSectionsRequest,\n CqtRequest,\n CqtToAudioRequest,\n DetectBoundariesRequest,\n FourierTempogramRequest,\n LufsRequest,\n MelodyOptions,\n NnlsChromaRequest,\n OnsetEnvelopeRequest,\n OnsetStrengthMultiRequest,\n TempogramRatioRequest,\n VqtRequest,\n VqtToAudioRequest,\n} from './feature_music';\nexport type {\n EstimateTuningRequest,\n NoteSegmentsRequest,\n PiptrackRequest,\n PitchPyinRequest,\n PitchTuningRequest,\n PitchYinRequest,\n} from './feature_pitch';\nexport type { ResampleRequest } from './feature_resample';\nexport type {\n PolyFeaturesRequest,\n SpectralContrastRequest,\n SpectralFrameRequest,\n SpectralRolloffRequest,\n ZeroCrossingRateRequest,\n ZeroCrossingsRequest,\n} from './feature_spectral';\nexport type {\n BassChromaSpectrogramRequest,\n ChromaSpectrogramRequest,\n MelDeltaRequest,\n MelSpectrogramRequest,\n MfccRequest,\n ReassignedSpectrogramRequest,\n SpectrogramRequest,\n TrimRequest,\n} from './feature_spectrogram';\nexport {\n amplitudeToDb,\n analyzeMelody,\n analyzeSections,\n bassChroma,\n chirp,\n chroma,\n chromaCens,\n chromaCqt,\n clicks,\n cqt,\n cqtToAudio,\n cyclicTempogram,\n dbToAmplitude,\n dbToPower,\n decompose,\n decomposeStems,\n decomposeStemsLinked,\n decomposeWithInit,\n deemphasis,\n detectBoundaries,\n ebur128LoudnessRange,\n estimateTuning,\n fixFrames,\n fixLength,\n fourierTempogram,\n frameSignal,\n framesToSamples,\n framesToTime,\n griffinLim,\n hpssWithResidual,\n hybridCqt,\n hzToMel,\n hzToMidi,\n hzToNote,\n lufs,\n lufsInterleaved,\n lufsSeriesInterleaved,\n melDelta,\n melSpectrogram,\n melToAudio,\n melToHz,\n melToStft,\n mfcc,\n mfccToAudio,\n mfccToMel,\n midiToHz,\n momentaryLufs,\n nnFilter,\n nnlsChroma,\n noteSegments,\n noteToHz,\n onsetBacktrack,\n onsetEnvelope,\n onsetStrengthMulti,\n padCenter,\n pcen,\n peakPick,\n phaseVocoder,\n piptrack,\n pitchPyin,\n pitchTuning,\n pitchYin,\n plp,\n polyFeatures,\n powerToDb,\n preemphasis,\n pseudoCqt,\n reassignedSpectrogram,\n remix,\n remixAlignedIntervals,\n resample,\n rmsEnergy,\n samplesToFrames,\n segmentAgglomerative,\n segmentCrossSimilarity,\n segmentLagToRecurrence,\n segmentPathEnhance,\n segmentRecurrenceMatrix,\n segmentRecurrenceToLag,\n segmentSubsegment,\n shortTermLufs,\n spectralBandwidth,\n spectralCentroid,\n spectralContrast,\n spectralFlatness,\n spectralFlux,\n spectralRolloff,\n splitSilence,\n splitSilenceCommon,\n splitSilenceCommonWithReport,\n stft,\n stftDb,\n tempogram,\n tempogramRatio,\n timeToFrames,\n tone,\n tonnetz,\n trim,\n trimSilence,\n vectorNormalize,\n vqt,\n vqtToAudio,\n zeroCrossingRate,\n zeroCrossings,\n} from './features';\nexport type { BindMicrophoneInputOptions, MicrophoneInputBinding } from './live_audio';\nexport { bindMicrophoneInput } from './live_audio';\nexport type {\n MasterAudioRequest,\n MasterAudioStereoRequest,\n MasteringChainRequest,\n MasteringChainStereoRequest,\n NormalizeMode,\n NormalizeRequest,\n NormalizeStereoRequest,\n NormalizeStereoResult,\n} from './mastering_chain';\nexport type { MasteringRequest } from './mastering_core';\nexport type {\n ClippingRegion,\n ClippingReport,\n DynamicRangeReport,\n MeteringDetectClippingOptions,\n MeteringDetectClippingRequest,\n MeteringDynamicRangeOptions,\n MeteringDynamicRangeRequest,\n MeteringSamplesRequest,\n MeteringSilenceRatioRequest,\n MeteringSpectrumFrameRequest,\n MeteringSpectrumRequest,\n MeteringStereoDecimatedRequest,\n MeteringStereoRequest,\n MeteringTruePeakRequest,\n PhaseScopeReport,\n SpectrumOptions,\n SpectrumReport,\n VectorscopeReport,\n WaveformPeakPyramidOptions,\n WaveformPeakPyramidRequest,\n WaveformPeaksOptions,\n WaveformPeaksReport,\n WaveformPeaksRequest,\n} from './metering';\nexport {\n meteringCrestFactorDb,\n meteringCrestFactorDbStereo,\n meteringDcOffset,\n meteringDetectClipping,\n meteringDynamicRange,\n meteringPeakDb,\n meteringPhaseScope,\n meteringPhaseScopeDecimated,\n meteringRmsDb,\n meteringSilenceRatio,\n meteringSpectrum,\n meteringSpectrumFrame,\n meteringStereoCorrelation,\n meteringStereoWidth,\n meteringTruePeakDb,\n meteringVectorscope,\n meteringVectorscopeDecimated,\n waveformPeakPyramid,\n waveformPeaks,\n} from './metering';\nexport type { SuggestMixSceneRequest } from './mixing_assistant';\nexport {\n mixSourceClassFromName,\n mixSourceClassNames,\n suggestMixScene,\n suggestMixSceneJson,\n} from './mixing_assistant';\nexport type {\n OpfsClipPageProviderBinding,\n OpfsClipPageProviderOptions,\n} from './opfs_clip_pages';\nexport {\n createOpfsClipPageProvider,\n createOpfsClipPageWorker,\n opfsClipPageWorkerSource,\n} from './opfs_clip_pages';\nexport {\n HrtfSet,\n PlaybackLoudnessMeter,\n PlaybackRenderer,\n renderPlayback,\n} from './playback_renderer';\nexport type { AnalyzePolyphonicRequest } from './polyphony';\nexport { analyzePolyphonic, PolyphonicAnalysis } from './polyphony';\nexport type {\n AlignTakeToReferenceRequest,\n AlignTakeToReferenceResult,\n Articulation,\n BuiltinSynthBinding,\n BuiltinSynthConfig,\n BuiltinSynthWaveform,\n ControllerAxis,\n ControllerBinding,\n ControllerInput,\n ExternalSeparatedStem,\n ExternalSeparatedStemImportRequest,\n ExternalSeparatedStemImportResult,\n MidiCcLearnOptions,\n MpeDimension,\n NoteTracking,\n ProjectAssistSidecar,\n ProjectAssistSidecarInput,\n ProjectAutomationCurve,\n ProjectAutomationLaneDesc,\n ProjectAutomationPoint,\n ProjectAutomationTargetKind,\n ProjectBounceOptions,\n ProjectChordSymbol,\n ProjectClip,\n ProjectClipCompSegment,\n ProjectClipDesc,\n ProjectClipFade,\n ProjectClipTake,\n ProjectCompileResult,\n ProjectFadeCurve,\n ProjectKeySegment,\n ProjectLoopMode,\n ProjectLoopRecordingDesc,\n ProjectLoopRecordingResult,\n ProjectMarker,\n ProjectMidiClipResult,\n ProjectMidiEvent,\n ProjectMidiFxBakeRequest,\n ProjectMidiFxBakeResult,\n ProjectMidiFxPreviewRequest,\n ProjectNotePairValidation,\n ProjectSource,\n ProjectTempoCandidate,\n ProjectTempoOptions,\n ProjectTempoSegment,\n ProjectTimeSignatureSegment,\n ProjectTrack,\n ProjectTrackDesc,\n ProjectTrackKind,\n ProjectTranscribeRequest,\n ProjectWarpAnchor,\n ProjectWarpMapDesc,\n SampleDesc,\n SampleDescLoopMode,\n SampleKeyTrack,\n SampleLoopMode,\n SampleZoneDesc,\n Sf2InstrumentConfig,\n Sf2ProgramStatus,\n SourceBackend,\n SynthBodyType,\n SynthEngineMode,\n SynthEnumTables,\n SynthFilterModel,\n SynthFilterOutput,\n SynthModDestination,\n SynthModRouting,\n SynthModSource,\n SynthOscWaveform,\n SynthPatch,\n SynthRetrigger,\n TakeAlignment,\n TranscribeOptions,\n TranscribeResult,\n} from './project';\nexport {\n ARTICULATIONS,\n AutomationTargetKind,\n BUILTIN_SYNTH_WAVEFORMS,\n CONTROLLER_AXES,\n CONTROLLER_INPUTS,\n controllerProfileNames,\n EXPECTED_PROJECT_ABI_VERSION,\n MarkerKind,\n MPE_DIMENSIONS,\n NOTE_TRACKINGS,\n PROJECT_AUTOMATION_TARGET_OPAQUE,\n PROJECT_AUTOMATION_TARGET_TRACK_FADER_DB,\n PROJECT_AUTOMATION_TARGET_TRACK_PAN,\n Project,\n projectAbiVersion,\n SAMPLE_KEY_TRACKS,\n SAMPLE_LOOP_MODES,\n SampleBank,\n SYNTH_BODY_TYPES,\n SYNTH_ENGINE_MODES,\n SYNTH_FILTER_MODELS,\n SYNTH_FILTER_OUTPUTS,\n SYNTH_MOD_DESTINATIONS,\n SYNTH_MOD_SOURCES,\n SYNTH_OSC_WAVEFORMS,\n SYNTH_RETRIGGERS,\n synthEnumTables,\n synthGsDrumKitIsVoicedApart,\n synthGsDrumKitName,\n synthGsVariationIsVoicedApart,\n synthPresetNames,\n synthPresetPatch,\n} from './project';\nexport type {\n AcousticOptions,\n AcousticResult,\n AnalysisChord,\n AnalysisResult,\n AnalyzeBpmOptions,\n AnalyzeDynamicsOptions,\n AnalyzeRhythmOptions,\n AnalyzeSectionsOptions,\n AnalyzeTimbreOptions,\n AutomationCurve,\n Beat,\n Boundary,\n BoundaryOptions,\n BoundaryResult,\n BpmHypothesis,\n CapabilityCatalog,\n CapabilityCatalogMasteringPreset,\n CapabilityCatalogParameter,\n CapabilityCatalogPresets,\n CapabilityCatalogProcessor,\n Chord,\n ChordAnalysisResult,\n ChordDetectionOptions,\n ChromaResult,\n ClickDetection,\n ClipDetection,\n CqtResult,\n CrackleDetection,\n DeclickReport,\n DeclipReport,\n DecrackleReport,\n DehumReport,\n DenoiseReport,\n DereverbReport,\n Dynamics,\n EqBand,\n EqBandPhase,\n EqBandType,\n EqCoeffMode,\n EqMatchOptions,\n EqSpectrumSnapshot,\n EqStereoPlacement,\n GoniometerPoint,\n HpssResult,\n HumDetection,\n Key,\n KeyCandidate,\n KeyDetectionOptions,\n KeyProfileName,\n LoudnessMatchResult,\n LufsResult,\n LufsSeriesResult,\n MasteringAssistantParams,\n MasteringChainConfig,\n MasteringChainResult,\n MasteringChainStereoResult,\n MasteringLoudnessSummary,\n MasteringOptions,\n MasteringPreset,\n MasteringProcessorParams,\n MasteringRepairDeclickStereoResult,\n MasteringRepairDeclipStereoResult,\n MasteringRepairDecrackleStereoResult,\n MasteringRepairDehumStereoResult,\n MasteringRepairDenoiseClassicalLinkedResult,\n MasteringRepairDenoiseClassicalStereoResult,\n MasteringRepairDereverbClassicalLinkedResult,\n MasteringRepairDereverbClassicalStereoResult,\n MasteringRepairTrimSilenceStereoResult,\n MasteringReport,\n MasteringResult,\n MasteringStereoChainResult,\n MasteringStereoResult,\n MelodyPoint,\n MelodyResult,\n MelPowerResult,\n MelSpectrogramResult,\n MeterTap,\n MfccResult,\n MixAnalysisBand,\n MixAssistantMixProfile,\n MixAssistantOptions,\n MixAssistantResult,\n MixAssistantTrack,\n MixAssistantTrackProfile,\n MixBandDominance,\n MixBandOccupancy,\n MixCrowdedBand,\n MixerProcessResult,\n MixMeterSnapshot,\n MixMonoRisk,\n MixOptions,\n MixResult,\n MixSceneBus,\n MixSceneConnection,\n MixSceneDocument,\n MixSceneInsert,\n MixSceneSend,\n MixSceneStrip,\n MixSceneVcaGroup,\n MixTrackAlignment,\n NoiseDetection,\n NoteEdit,\n NoteEditInput,\n NoteExtractorOptions,\n NoteObject,\n NoteObjectInput,\n NoteSegment,\n NoteSetEntry,\n NoteStretchOptions,\n NoteTarget,\n NoteTargetAssignResult,\n NoteTargetUnmatchedPolicy,\n PairAnalysis,\n PairProcessor,\n PanLaw,\n PanLawInput,\n PanLawName,\n PanMode,\n PercussiveEvent,\n PercussiveEventEdit,\n PercussiveEventEditInput,\n PercussiveEventInput,\n PitchCorrectOptions,\n PitchDecompositionResult,\n PitchResult,\n PlaybackBassManagementConfig,\n PlaybackChannelRole,\n PlaybackDiagnostics,\n PlaybackHeadTrackingConfig,\n PlaybackInputConfig,\n PlaybackLoudnessConfig,\n PlaybackNightModeConfig,\n PlaybackOutputLimiterConfig,\n PlaybackRendererConfig,\n PlaybackRendererOptions,\n PlaybackRoomConfig,\n PlaybackSpeakerConfig,\n PlaybackStageLatency,\n PlaybackStageName,\n PlaybackTargetConfig,\n PlaybackUpmixConfig,\n PolyphonicAnalysisOptions,\n PolyphonicRenderOptions,\n RealtimeVoiceChangerConfigInput,\n RealtimeVoiceChangerPodConfig,\n RenderPlaybackRequest,\n RenderPlaybackResult,\n ReverbDetection,\n RhythmFeatures,\n RirDiagnostic,\n RirResult,\n RirSynthOptions,\n RoomEstimateOptions,\n RoomEstimateResult,\n RoomGeometryOptions,\n RoomMorphOptions,\n RoomMorphResult,\n Section,\n SegmentMatrix,\n SendTiming,\n SidechainSourceKind,\n SoloProcessor,\n SonareCapabilities,\n SpectralEditMode,\n SpectralEditOptions,\n SpectralEditWindow,\n SpectralRegionOp,\n StageGainReduction,\n StereoAnalysis,\n StftPowerResult,\n StftResult,\n StreamingEqualizerConfig,\n StreamingMasteringChainConfig,\n StreamingPlatform,\n StreamingRetuneConfig,\n TempogramMode,\n Timbre,\n TimeSignature,\n TrimRange,\n TrimReport,\n UmpWords,\n VoicedFlags,\n VoicePresetId,\n} from './public_types';\nexport {\n ChordQuality,\n KeyProfile,\n Mode,\n PitchClass,\n SectionType,\n} from './public_types';\nexport type {\n AnalyzeBpmRequest,\n AnalyzeDynamicsRequest,\n AnalyzeImpulseResponseRequest,\n AnalyzeRhythmRequest,\n AnalyzeTimbreRequest,\n AnalyzeWithProgressRequest,\n BpmAnalysisResult,\n BpmCandidate,\n ChordFunctionalAnalysisRequest,\n DetectAcousticRequest,\n DetectChordsRequest,\n DetectKeyRequest,\n DetectOnsetsRequest,\n DynamicsAnalysisResult,\n DynamicsResult,\n EstimateMeterRequest,\n EstimateRoomRequest,\n MusicAnalyzeRequest,\n RhythmAnalysisResult,\n RoomMorphRequest,\n SamplesRequest,\n TimbreAnalysisResult,\n TimbreFrame,\n} from './quick_analysis';\nexport {\n analyze,\n analyzeBpm,\n analyzeDynamics,\n analyzeImpulseResponse,\n analyzeRhythm,\n analyzeTimbre,\n analyzeWithProgress,\n chordFunctionalAnalysis,\n detectAcoustic,\n detectBeats,\n detectBpm,\n detectChords,\n detectDownbeats,\n detectKey,\n detectKeyCandidates,\n detectOnsets,\n estimateMeter,\n estimateRoom,\n hasFfmpegSupport,\n roomMorph,\n synthesizeRir,\n} from './quick_analysis';\nexport type {\n ClipPageRequest,\n EngineAutomationPoint,\n EngineBounceOptions,\n EngineBounceResult,\n EngineBus,\n EngineCapabilities,\n EngineCaptureSource,\n EngineCaptureStatus,\n EngineClip,\n EngineFreezeOptions,\n EngineFreezeResult,\n EngineGraphSpec,\n EngineMarker,\n EngineMeterTelemetry,\n EngineMeterTelemetryWide,\n EngineMetronomeConfig,\n EngineMidiClipSchedule,\n EngineMidiEvent,\n EngineParameterInfo,\n EngineScopeTelemetry,\n EngineTelemetry,\n EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTrackLane,\n EngineTrackMonitorMode,\n EngineTrackSend,\n EngineTransportState,\n ExternalMidiEvent,\n MidiCcBindOptions,\n RenderOfflineRequest,\n TrackMonitorMode,\n} from './realtime_engine';\nexport {\n ClipPageProvider,\n EXPECTED_ENGINE_ABI_VERSION,\n engineCapabilities,\n RealtimeEngine,\n} from './realtime_engine';\nexport { scaleCorrectionSemitones, scalePitchClassEnabled, scaleQuantizeMidi } from './scale';\nexport type { ProgressCallback } from './sonare.js';\nexport { StreamAnalyzer, streamAnalyzerConfigDefaults } from './stream_analyzer';\nexport type {\n AnalyzerStats,\n BarChord,\n ChordChange,\n FrameBuffer,\n PatternScore,\n ProgressiveEstimate,\n StreamConfig,\n StreamConfigDefaults,\n StreamFramesI16,\n StreamFramesU8,\n StreamQuantizeConfig,\n} from './stream_types';\nexport type {\n MixerMeterSnapshot,\n MixerRealtimeBuffer,\n RealtimeVoiceChangerInterleavedBuffer,\n RealtimeVoiceChangerMonoBuffer,\n RealtimeVoiceChangerPlanarBuffer,\n StripMeteringOptions,\n} from './streaming_mixing';\nexport {\n Mixer,\n RealtimeVoiceChanger,\n realtimeVoiceChangerPresetJson,\n realtimeVoiceChangerPresetNames,\n StreamingEqualizer,\n StreamingMasteringChain,\n StreamingRetune,\n validateRealtimeVoiceChangerPresetJson,\n} from './streaming_mixing';\nexport type { TranscribeRequest } from './transcribe';\nexport { transcribe } from './transcribe';\nexport type { ValidateOptions } from './validation';\nexport type {\n BindWebMidiOptions,\n WebMidiBinding,\n WebMidiCcBinding,\n WebMidiInputInfo,\n} from './web_midi';\nexport { bindWebMidi, isWebMidiAvailable } from './web_midi';\nexport type {\n OfflineWorker,\n OfflineWorkerCallOptions,\n OfflineWorkerClientOptions,\n OfflineWorkerProgress,\n} from './worker_client';\nexport { OfflineWorkerClient, OfflineWorkerTask } from './worker_client';\n\n/** Row-major 2-D matrix as a flat buffer plus its dimensions. */\nexport type Matrix2dResult = WasmMatrix2dResult;\n/** NMF factor matrices { w, h } from {@link decompose}. */\nexport type DecomposeResult = WasmDecomposeResult;\n/** Harmonic / percussive / residual signals from {@link hpssWithResidual}. */\nexport type HpssWithResidualResult = WasmHpssWithResidualResult;\n\n// ============================================================================\n// Module State\n// ============================================================================\n\nlet module: SonareModule | null = null;\nlet initPromise: Promise<void> | null = null;\n\n// ============================================================================\n// Initialization\n// ============================================================================\n\n/**\n * Initialize the WASM module.\n * Must be called before using any analysis functions.\n *\n * @param options - Optional module configuration\n * @returns Promise that resolves when initialization is complete\n */\nexport async function init(options?: {\n locateFile?: (path: string, prefix: string) => string;\n wasmBinary?: ArrayBuffer | Uint8Array;\n moduleFactory?: (options?: {\n locateFile?: (path: string, prefix: string) => string;\n wasmBinary?: ArrayBuffer | Uint8Array;\n }) => Promise<SonareModule>;\n}): Promise<void> {\n if (module) {\n return;\n }\n\n if (initPromise) {\n return initPromise;\n }\n\n initPromise = (async () => {\n try {\n const createModule = options?.moduleFactory ?? (await import('./sonare.js')).default;\n module = await createModule(options);\n setSonareModule(module);\n } catch (error) {\n initPromise = null;\n throw error;\n }\n })();\n\n return initPromise;\n}\n\n/**\n * Check if the module is initialized.\n */\nexport function isInitialized(): boolean {\n return module !== null;\n}\n\n/**\n * Get the library version.\n */\nexport function version(): string {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.version();\n}\n\n/**\n * Return the capabilities of the loaded WASM build.\n *\n * This is synchronous and only describes the already-initialized module.\n */\nexport function capabilities(): SonareCapabilities {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.capabilities();\n}\n\n/** Return the initialized module's processors, parameters, and presets. */\nexport function capabilityCatalog(): CapabilityCatalog {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return JSON.parse(module.capabilityCatalog()) as CapabilityCatalog;\n}\n\n/**\n * Aggregate native ABI version: the per-subsystem ABI macros folded into one\n * 32-bit value. It bumps whenever any flat C POD layout changes, so callers can\n * detect an incompatible prebuilt binary. Matches the Node/Python `abiVersion()`.\n */\nexport function abiVersion(): number {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.abiVersion();\n}\n\nexport function engineAbiVersion(): number {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.engineAbiVersion();\n}\n\nexport function voiceChangerAbiVersion(): number {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.voiceChangerAbiVersion();\n}\n\n// Canonical ordinal order of the built-in voice-character presets, matching the\n// C ABI SonareVoiceCharacterPreset enum and SONARE_REALTIME_VOICE_CHANGER_PRESET_IDS.\nconst VOICE_PRESET_ORDINALS: readonly VoicePresetId[] = [\n 'neutral-monitor',\n 'bright-idol',\n 'soft-whisper',\n 'deep-narrator',\n 'robot-mascot',\n 'dark-villain',\n];\n\nfunction resolveVoicePresetOrdinal(preset: VoicePresetId | number): number {\n if (typeof preset === 'number') {\n if (!Number.isSafeInteger(preset) || preset < 0 || preset >= VOICE_PRESET_ORDINALS.length) {\n throw new RangeError(`Unknown voice-character preset ordinal: ${String(preset)}`);\n }\n return preset;\n }\n const ordinal = VOICE_PRESET_ORDINALS.indexOf(preset);\n if (ordinal < 0) {\n throw new Error(`Unknown voice character preset: ${preset}`);\n }\n return ordinal;\n}\n\n/**\n * Map a voice-character preset ordinal (or canonical id) to its canonical id\n * string (e.g. `'bright-idol'`). Unknown numeric ordinals return `null`;\n * unknown preset ids throw.\n */\nexport function voiceCharacterPresetId(preset: VoicePresetId | number): VoicePresetId | null {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n if (\n typeof preset === 'number' &&\n (!Number.isSafeInteger(preset) || preset < 0 || preset >= VOICE_PRESET_ORDINALS.length)\n ) {\n return null;\n }\n return module.voiceCharacterPresetId(resolveVoicePresetOrdinal(preset)) as VoicePresetId;\n}\n\n/**\n * Return the canonical (normalized) flat POD config for a built-in voice\n * preset, skipping the JSON round-trip. Accepts a canonical preset id or its\n * integer ordinal. Invalid ordinals throw.\n */\nexport function realtimeVoiceChangerPresetConfig(\n preset: VoicePresetId | number,\n): RealtimeVoiceChangerPodConfig {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.realtimeVoiceChangerPresetConfig(resolveVoicePresetOrdinal(preset));\n}\n\n// ============================================================================\n// Re-exports\n// ============================================================================\n\nexport { PitchClass as Pitch } from './public_types';\n"],"mappings":"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","names":["ErrorCode","module","module","requireModule","requireModule","requireModule","requireModule","requireModule","requireModule","requireModule","requireModule","requireModule","requireModule","requireModule","requireModule","requireModule","requireModule","onsetEnvelope","requireModule","resolveHardMask","init","requireModule","requireModule","requireModule","onsetEnvelope","requireModule","requireModule","requireModule","requireModule","requireModule","requireModule","module","requireModule","module","module","abiVersion","module","capabilities","module","module","module","module"]}