@libraz/libsonare 1.7.2 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (303) hide show
  1. package/NOTICE +178 -0
  2. package/README.md +26 -203
  3. package/dist/_chain_config.d.ts +14 -0
  4. package/dist/_chain_config.d.ts.map +1 -0
  5. package/dist/_effects_common.d.ts +6 -0
  6. package/dist/_effects_common.d.ts.map +1 -0
  7. package/dist/_feature_validation.d.ts +8 -0
  8. package/dist/_feature_validation.d.ts.map +1 -0
  9. package/dist/_fft_options.d.ts +24 -0
  10. package/dist/_fft_options.d.ts.map +1 -0
  11. package/dist/align_take.d.ts +50 -0
  12. package/dist/align_take.d.ts.map +1 -0
  13. package/dist/analysis.d.ts +29 -5840
  14. package/dist/analysis.d.ts.map +1 -0
  15. package/dist/analysis.js +873 -722
  16. package/dist/analysis.js.map +1 -1
  17. package/dist/analysis_helpers.d.ts +9 -0
  18. package/dist/analysis_helpers.d.ts.map +1 -0
  19. package/dist/audio.d.ts +163 -0
  20. package/dist/audio.d.ts.map +1 -0
  21. package/dist/clip_page_streamer.d.ts +133 -0
  22. package/dist/clip_page_streamer.d.ts.map +1 -0
  23. package/dist/codes.d.ts +44 -0
  24. package/dist/codes.d.ts.map +1 -0
  25. package/dist/effects_mastering.d.ts +23 -0
  26. package/dist/effects_mastering.d.ts.map +1 -0
  27. package/dist/effects_note_ops.d.ts +477 -0
  28. package/dist/effects_note_ops.d.ts.map +1 -0
  29. package/dist/effects_percussive.d.ts +185 -0
  30. package/dist/effects_percussive.d.ts.map +1 -0
  31. package/dist/effects_separation.d.ts +65 -0
  32. package/dist/effects_separation.d.ts.map +1 -0
  33. package/dist/effects_spectral.d.ts +28 -0
  34. package/dist/effects_spectral.d.ts.map +1 -0
  35. package/dist/effects_timepitch.d.ts +129 -0
  36. package/dist/effects_timepitch.d.ts.map +1 -0
  37. package/dist/effects_voice_change.d.ts +53 -0
  38. package/dist/effects_voice_change.d.ts.map +1 -0
  39. package/dist/errors.d.ts +51 -0
  40. package/dist/errors.d.ts.map +1 -0
  41. package/dist/feature_core.d.ts +341 -0
  42. package/dist/feature_core.d.ts.map +1 -0
  43. package/dist/feature_decompose.d.ts +278 -0
  44. package/dist/feature_decompose.d.ts.map +1 -0
  45. package/dist/feature_inverse.d.ts +128 -0
  46. package/dist/feature_inverse.d.ts.map +1 -0
  47. package/dist/feature_loudness.d.ts +66 -0
  48. package/dist/feature_loudness.d.ts.map +1 -0
  49. package/dist/feature_music.d.ts +307 -0
  50. package/dist/feature_music.d.ts.map +1 -0
  51. package/dist/feature_pitch.d.ts +108 -0
  52. package/dist/feature_pitch.d.ts.map +1 -0
  53. package/dist/feature_resample.d.ts +16 -0
  54. package/dist/feature_resample.d.ts.map +1 -0
  55. package/dist/feature_spectral.d.ts +137 -0
  56. package/dist/feature_spectral.d.ts.map +1 -0
  57. package/dist/feature_spectrogram.d.ts +198 -0
  58. package/dist/feature_spectrogram.d.ts.map +1 -0
  59. package/dist/features.d.ts +10 -0
  60. package/dist/features.d.ts.map +1 -0
  61. package/dist/hrtf/default.shrf +0 -0
  62. package/dist/index.d.ts +74 -7431
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +3758 -1362
  65. package/dist/index.js.map +1 -1
  66. package/dist/instrument_types.d.ts +517 -0
  67. package/dist/instrument_types.d.ts.map +1 -0
  68. package/dist/live_audio.d.ts +35 -0
  69. package/dist/live_audio.d.ts.map +1 -0
  70. package/dist/mastering_chain.d.ts +213 -0
  71. package/dist/mastering_chain.d.ts.map +1 -0
  72. package/dist/mastering_core.d.ts +457 -0
  73. package/dist/mastering_core.d.ts.map +1 -0
  74. package/dist/mastering_dynamics.d.ts +80 -0
  75. package/dist/mastering_dynamics.d.ts.map +1 -0
  76. package/dist/metering.d.ts +287 -0
  77. package/dist/metering.d.ts.map +1 -0
  78. package/dist/mixer.d.ts +464 -0
  79. package/dist/mixer.d.ts.map +1 -0
  80. package/dist/mixing_assistant.d.ts +62 -0
  81. package/dist/mixing_assistant.d.ts.map +1 -0
  82. package/dist/mixing_oneshot.d.ts +40 -0
  83. package/dist/mixing_oneshot.d.ts.map +1 -0
  84. package/dist/module_state.d.ts +15 -0
  85. package/dist/module_state.d.ts.map +1 -0
  86. package/dist/opfs_clip_pages.d.ts +28 -0
  87. package/dist/opfs_clip_pages.d.ts.map +1 -0
  88. package/dist/playback_renderer.d.ts +128 -0
  89. package/dist/playback_renderer.d.ts.map +1 -0
  90. package/dist/polyphony.d.ts +202 -0
  91. package/dist/polyphony.d.ts.map +1 -0
  92. package/dist/project.d.ts +8 -0
  93. package/dist/project.d.ts.map +1 -0
  94. package/dist/project_class.d.ts +562 -0
  95. package/dist/project_class.d.ts.map +1 -0
  96. package/dist/project_internal.d.ts +194 -0
  97. package/dist/project_internal.d.ts.map +1 -0
  98. package/dist/project_synth.d.ts +74 -0
  99. package/dist/project_synth.d.ts.map +1 -0
  100. package/dist/project_types.d.ts +652 -0
  101. package/dist/project_types.d.ts.map +1 -0
  102. package/dist/public_types.d.ts +185 -0
  103. package/dist/public_types.d.ts.map +1 -0
  104. package/dist/public_types_acoustic.d.ts +215 -0
  105. package/dist/public_types_acoustic.d.ts.map +1 -0
  106. package/dist/public_types_mastering.d.ts +510 -0
  107. package/dist/public_types_mastering.d.ts.map +1 -0
  108. package/dist/public_types_mixing.d.ts +436 -0
  109. package/dist/public_types_mixing.d.ts.map +1 -0
  110. package/dist/public_types_music.d.ts +619 -0
  111. package/dist/public_types_music.d.ts.map +1 -0
  112. package/dist/public_types_playback.d.ts +164 -0
  113. package/dist/public_types_playback.d.ts.map +1 -0
  114. package/dist/public_types_realtime.d.ts +174 -0
  115. package/dist/public_types_realtime.d.ts.map +1 -0
  116. package/dist/public_types_repair.d.ts +424 -0
  117. package/dist/public_types_repair.d.ts.map +1 -0
  118. package/dist/public_types_spectral.d.ts +697 -0
  119. package/dist/public_types_spectral.d.ts.map +1 -0
  120. package/dist/quick_analysis.d.ts +445 -0
  121. package/dist/quick_analysis.d.ts.map +1 -0
  122. package/dist/realtime_engine.d.ts +850 -0
  123. package/dist/realtime_engine.d.ts.map +1 -0
  124. package/dist/realtime_voice_changer.d.ts +158 -0
  125. package/dist/realtime_voice_changer.d.ts.map +1 -0
  126. package/dist/repair_dereverb.d.ts +187 -0
  127. package/dist/repair_dereverb.d.ts.map +1 -0
  128. package/dist/repair_impulsive.d.ts +186 -0
  129. package/dist/repair_impulsive.d.ts.map +1 -0
  130. package/dist/repair_noise.d.ts +239 -0
  131. package/dist/repair_noise.d.ts.map +1 -0
  132. package/dist/repair_trim.d.ts +123 -0
  133. package/dist/repair_trim.d.ts.map +1 -0
  134. package/dist/sample_bank.d.ts +84 -0
  135. package/dist/sample_bank.d.ts.map +1 -0
  136. package/dist/scale.d.ts +10 -0
  137. package/dist/scale.d.ts.map +1 -0
  138. package/dist/schemas/mixer-scene.schema.json +393 -0
  139. package/dist/schemas/playback-renderer-config.schema.json +392 -0
  140. package/dist/sonare-analysis.d.ts +8 -0
  141. package/dist/sonare-analysis.js +2 -2
  142. package/dist/sonare-analysis.wasm +0 -0
  143. package/dist/sonare.d.ts +3909 -0
  144. package/dist/sonare.js +2 -2
  145. package/dist/sonare.wasm +0 -0
  146. package/dist/stream_analyzer.d.ts +163 -0
  147. package/dist/stream_analyzer.d.ts.map +1 -0
  148. package/dist/stream_types.d.ts +214 -0
  149. package/dist/stream_types.d.ts.map +1 -0
  150. package/dist/streaming_mixing.d.ts +6 -0
  151. package/dist/streaming_mixing.d.ts.map +1 -0
  152. package/dist/streaming_processors.d.ts +335 -0
  153. package/dist/streaming_processors.d.ts.map +1 -0
  154. package/dist/transcribe.d.ts +77 -0
  155. package/dist/transcribe.d.ts.map +1 -0
  156. package/dist/validation.d.ts +140 -0
  157. package/dist/validation.d.ts.map +1 -0
  158. package/dist/web_midi.d.ts +77 -0
  159. package/dist/web_midi.d.ts.map +1 -0
  160. package/dist/worker.d.ts +5 -48
  161. package/dist/worker.d.ts.map +1 -0
  162. package/dist/worker.js +94 -41
  163. package/dist/worker.js.map +1 -1
  164. package/dist/worker_client.d.ts +96 -0
  165. package/dist/worker_client.d.ts.map +1 -0
  166. package/dist/worker_protocol.d.ts +43 -0
  167. package/dist/worker_protocol.d.ts.map +1 -0
  168. package/dist/worklet/audio_types.d.ts +21 -0
  169. package/dist/worklet/audio_types.d.ts.map +1 -0
  170. package/dist/worklet/engine-automation.d.ts +29 -0
  171. package/dist/worklet/engine-automation.d.ts.map +1 -0
  172. package/dist/worklet/engine-capture-facade.d.ts +35 -0
  173. package/dist/worklet/engine-capture-facade.d.ts.map +1 -0
  174. package/dist/worklet/engine-clips.d.ts +23 -0
  175. package/dist/worklet/engine-clips.d.ts.map +1 -0
  176. package/dist/worklet/engine-markers.d.ts +40 -0
  177. package/dist/worklet/engine-markers.d.ts.map +1 -0
  178. package/dist/worklet/engine-mixer-facade.d.ts +128 -0
  179. package/dist/worklet/engine-mixer-facade.d.ts.map +1 -0
  180. package/dist/worklet/engine-node.d.ts +81 -0
  181. package/dist/worklet/engine-node.d.ts.map +1 -0
  182. package/dist/worklet/engine-offline.d.ts +81 -0
  183. package/dist/worklet/engine-offline.d.ts.map +1 -0
  184. package/dist/worklet/engine-options.d.ts +12 -0
  185. package/dist/worklet/engine-options.d.ts.map +1 -0
  186. package/dist/worklet/engine-parameter-facade.d.ts +106 -0
  187. package/dist/worklet/engine-parameter-facade.d.ts.map +1 -0
  188. package/dist/worklet/engine-processor.d.ts +68 -0
  189. package/dist/worklet/engine-processor.d.ts.map +1 -0
  190. package/dist/worklet/engine-register.d.ts +2 -0
  191. package/dist/worklet/engine-register.d.ts.map +1 -0
  192. package/dist/worklet/engine-strips.d.ts +73 -0
  193. package/dist/worklet/engine-strips.d.ts.map +1 -0
  194. package/dist/worklet/engine-sync.d.ts +37 -0
  195. package/dist/worklet/engine-sync.d.ts.map +1 -0
  196. package/dist/worklet/engine-tempo-facade.d.ts +48 -0
  197. package/dist/worklet/engine-tempo-facade.d.ts.map +1 -0
  198. package/dist/worklet/engine.d.ts +397 -0
  199. package/dist/worklet/engine.d.ts.map +1 -0
  200. package/dist/worklet/guards.d.ts +47 -0
  201. package/dist/worklet/guards.d.ts.map +1 -0
  202. package/dist/worklet/messages.d.ts +710 -0
  203. package/dist/worklet/messages.d.ts.map +1 -0
  204. package/dist/worklet/mixer-processor.d.ts +46 -0
  205. package/dist/worklet/mixer-processor.d.ts.map +1 -0
  206. package/dist/worklet/playback-processor.d.ts +62 -0
  207. package/dist/worklet/playback-processor.d.ts.map +1 -0
  208. package/dist/worklet/protocol.d.ts +323 -0
  209. package/dist/worklet/protocol.d.ts.map +1 -0
  210. package/dist/worklet/voice-changer-processor.d.ts +41 -0
  211. package/dist/worklet/voice-changer-processor.d.ts.map +1 -0
  212. package/dist/worklet.d.ts +16 -2515
  213. package/dist/worklet.d.ts.map +1 -0
  214. package/dist/worklet.js +2763 -501
  215. package/dist/worklet.js.map +1 -1
  216. package/package.json +23 -12
  217. package/src/_effects_common.ts +17 -0
  218. package/src/_feature_validation.ts +34 -0
  219. package/src/_fft_options.ts +39 -0
  220. package/src/align_take.ts +64 -0
  221. package/src/analysis.ts +56 -3
  222. package/src/analysis_helpers.ts +7 -0
  223. package/src/audio.ts +106 -3
  224. package/src/codes.ts +39 -2
  225. package/src/effects_mastering.ts +97 -22
  226. package/src/effects_note_ops.ts +635 -0
  227. package/src/effects_percussive.ts +217 -0
  228. package/src/effects_separation.ts +150 -0
  229. package/src/effects_spectral.ts +60 -0
  230. package/src/effects_timepitch.ts +377 -0
  231. package/src/errors.ts +23 -1
  232. package/src/feature_core.ts +127 -2
  233. package/src/feature_decompose.ts +633 -0
  234. package/src/feature_inverse.ts +454 -0
  235. package/src/feature_loudness.ts +125 -0
  236. package/src/feature_music.ts +107 -14
  237. package/src/feature_pitch.ts +96 -1
  238. package/src/feature_spectral.ts +16 -611
  239. package/src/feature_spectrogram.ts +63 -450
  240. package/src/features.ts +36 -22
  241. package/src/index.ts +282 -30
  242. package/src/instrument_types.ts +645 -0
  243. package/src/live_audio.ts +27 -1
  244. package/src/mastering_chain.ts +184 -0
  245. package/src/mastering_core.ts +346 -32
  246. package/src/mastering_dynamics.ts +22 -11
  247. package/src/metering.ts +67 -24
  248. package/src/mixer.ts +212 -3
  249. package/src/mixing_assistant.ts +138 -0
  250. package/src/mixing_oneshot.ts +10 -5
  251. package/src/module_state.ts +24 -2
  252. package/src/playback_renderer.ts +252 -0
  253. package/src/polyphony.ts +279 -0
  254. package/src/project.ts +61 -24
  255. package/src/project_class.ts +450 -27
  256. package/src/project_internal.ts +149 -42
  257. package/src/project_synth.ts +67 -1
  258. package/src/project_types.ts +268 -270
  259. package/src/public_types.ts +122 -3
  260. package/src/public_types_acoustic.ts +112 -3
  261. package/src/public_types_mastering.ts +254 -73
  262. package/src/public_types_mixing.ts +363 -1
  263. package/src/public_types_music.ts +312 -2
  264. package/src/public_types_playback.ts +195 -0
  265. package/src/public_types_realtime.ts +39 -7
  266. package/src/public_types_repair.ts +446 -0
  267. package/src/public_types_spectral.ts +487 -1
  268. package/src/quick_analysis.ts +203 -26
  269. package/src/realtime_engine.ts +711 -28
  270. package/src/realtime_voice_changer.ts +55 -1
  271. package/src/repair_dereverb.ts +299 -0
  272. package/src/repair_impulsive.ts +395 -0
  273. package/src/repair_noise.ts +425 -0
  274. package/src/repair_trim.ts +226 -0
  275. package/src/sample_bank.ts +113 -0
  276. package/src/sonare.js.d.ts +1122 -30
  277. package/src/stream_analyzer.ts +36 -4
  278. package/src/stream_types.ts +37 -0
  279. package/src/streaming_mixing.ts +1 -1
  280. package/src/streaming_processors.ts +194 -10
  281. package/src/transcribe.ts +89 -0
  282. package/src/validation.ts +285 -11
  283. package/src/web_midi.ts +1 -6
  284. package/src/worker.ts +18 -2
  285. package/src/worklet/audio_types.ts +37 -0
  286. package/src/worklet/engine-mixer-facade.ts +444 -10
  287. package/src/worklet/engine-node.ts +78 -26
  288. package/src/worklet/engine-offline.ts +14 -8
  289. package/src/worklet/engine-parameter-facade.ts +21 -0
  290. package/src/worklet/engine-processor.ts +272 -83
  291. package/src/worklet/engine-register.ts +32 -18
  292. package/src/worklet/engine-strips.ts +280 -9
  293. package/src/worklet/engine-sync.ts +14 -6
  294. package/src/worklet/engine.ts +365 -31
  295. package/src/worklet/guards.ts +140 -44
  296. package/src/worklet/messages.ts +227 -2
  297. package/src/worklet/mixer-processor.ts +109 -47
  298. package/src/worklet/playback-processor.ts +300 -0
  299. package/src/worklet/protocol.ts +53 -3
  300. package/src/worklet/voice-changer-processor.ts +17 -11
  301. package/src/worklet.ts +17 -0
  302. package/src/effects_transform.ts +0 -718
  303. package/src/mastering_repair.ts +0 -273
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Per-call validation options accepted by guarded wrappers. Empty-buffer
3
+ * checks are always performed; pass `{ validate: false }` to opt out of the
4
+ * O(n) NaN/Inf scan on hot paths.
5
+ *
6
+ * `{ validate: false }` only skips this JS-side pre-scan (which raises a
7
+ * `RangeError` naming the exact offending index). It is NOT a way to push
8
+ * non-finite samples into the core: the native layer always re-validates the
9
+ * buffer — through `validate_offline_audio_input` for the offline-analysis
10
+ * entry points, and through the computation's own per-sample guard where a call
11
+ * takes no sample rate to validate against (the waveform bucket kernels) —
12
+ * matching the C ABI / Node / Python surfaces, so an NaN/Inf buffer still
13
+ * throws, just with a generic native message instead of the indexed JS one.
14
+ */
15
+ export interface ValidateOptions {
16
+ validate?: boolean;
17
+ }
18
+ /**
19
+ * Offline-analysis sample-rate bounds, mirroring the C++ core limits
20
+ * (`sonare::kMinAudioSampleRate` / `kMaxAudioSampleRate` in `core/audio.h`).
21
+ * Every guarded WASM entry point rejects the same out-of-range rates the C ABI,
22
+ * Node, and Python surfaces do.
23
+ */
24
+ export declare const MIN_AUDIO_SAMPLE_RATE = 8000;
25
+ export declare const MAX_AUDIO_SAMPLE_RATE = 384000;
26
+ export declare function assertSamples(fnName: string, samples: ArrayLike<number>, validate: boolean, argName?: string): void;
27
+ /**
28
+ * `assertSamples` restricted to the span a windowed entry point actually reads.
29
+ *
30
+ * The emptiness check still covers the whole buffer, and the reported index is
31
+ * the absolute one, so the message keeps naming the sample the caller passed.
32
+ * What narrows is the scan: a windowed call refuses a non-finite sample inside
33
+ * its frame and is indifferent to one outside it, which is the contract the C
34
+ * ABI states and the cost model it promises -- per call the scan is bounded by
35
+ * the frame, not by the length of the buffer being polled.
36
+ */
37
+ export declare function assertSamplesInWindow(fnName: string, samples: ArrayLike<number>, validate: boolean, windowStart: number, windowLength: number, argName?: string): void;
38
+ export declare function assertFiniteScalar(fnName: string, value: number, argName: string): void;
39
+ /**
40
+ * A NaN gamma is the automatic-bandwidth sentinel the variable-Q transform
41
+ * documents, alongside a negative value, so only an infinity is out of domain.
42
+ */
43
+ export declare function assertVqtGamma(fnName: string, gamma: number): void;
44
+ export declare function assertSampleRate(fnName: string, sampleRate: number, argName?: string): void;
45
+ /** Validate and retain the public Audio.fromBuffer construction contract. */
46
+ export declare function validateAudioBuffer(samples: Float32Array, sampleRate: number): void;
47
+ /** Bounds of the native `int` every embind argument below is narrowed into. */
48
+ export declare const C_INT_MIN = -2147483648;
49
+ export declare const C_INT_MAX = 2147483647;
50
+ /**
51
+ * Reject an argument embind's declared-`int` narrowing would wrap.
52
+ *
53
+ * A positional embind parameter declared `int` WRAPS rather than saturates, so
54
+ * a kernel of `2 ** 32` arrives as 0 and `2 ** 32 + 1` as 1 — both values the
55
+ * native guards accept, so the call succeeds having separated on a setting the
56
+ * caller never asked for. (The options-object path narrows through
57
+ * `checkedIntFromVal`, which refuses the same inputs in the module; this is the
58
+ * positional path's equivalent.)
59
+ *
60
+ * Reported as the branded `SonareError` carrying `InvalidParameter` rather than
61
+ * a `RangeError`, because the class follows what the rejection stands in for: a
62
+ * `RangeError` is this surface refusing an argument on its own authority, while
63
+ * this one pre-empts a native refusal the caller would have received under that
64
+ * code had the narrowing not wrapped the value into the accepted domain first.
65
+ * The agreement with the Node and Python surfaces is asserted by the Node
66
+ * package's `tests/narrowing-code-parity.test.ts`, which drives one value
67
+ * through all three — weakening this check turns that red.
68
+ */
69
+ export declare function assertInt32(fnName: string, value: number, argName: string): void;
70
+ /**
71
+ * Check both HPSS kernels before embind narrows them.
72
+ *
73
+ * Parity, positivity and the ceiling stay the core's to enforce, and it names
74
+ * the median filter that rejected the value. What cannot be deferred is the
75
+ * narrowing itself: a wrapped kernel arrives as a legal one and separates on it.
76
+ *
77
+ * These two arrive POSITIONALLY, so they never pass through the options-bag
78
+ * reader and inherit none of its checks. That is what separates this from
79
+ * {@link assertPercussiveSeparation}, which duplicates a reader check to improve
80
+ * a message; here there is no reader to duplicate.
81
+ */
82
+ export declare function assertHpssKernels(fnName: string, kernelHarmonic: number, kernelPercussive: number): void;
83
+ /**
84
+ * Percussive-event separation fields, as the request objects carry them.
85
+ */
86
+ export interface PercussiveSeparationFields {
87
+ nFft?: number;
88
+ hopLength?: number;
89
+ hpssKernelHarmonic?: number;
90
+ hpssKernelPercussive?: number;
91
+ }
92
+ /**
93
+ * Check the percussive-event separation's framing and kernels for integrality.
94
+ *
95
+ * All four fields reach the module through one options-bag reader, which now
96
+ * refuses a fractional value itself, so this is the diagnostic rather than the
97
+ * guarantee: it fires first and names the function, where the reader can only
98
+ * name the field. Both reject the same set, so they cannot disagree about an
99
+ * input — only about how the message reads. Do not narrow this to fields the
100
+ * reader misses; there are none, and a check scoped to a gap that no longer
101
+ * exists is how a stale justification outlives its divergence.
102
+ *
103
+ * The fields are iterated rather than named at each call site so a new one is
104
+ * visible here. Absence means the default, so an omitted field is not resolved.
105
+ */
106
+ export declare function assertPercussiveSeparation(fnName: string, options: PercussiveSeparationFields): void;
107
+ export declare function assertNonNegativeInteger(fnName: string, value: number, argName: string): void;
108
+ /** Integer strictly greater than zero, up to the native `int` ceiling. */
109
+ export declare function assertPositiveInteger(fnName: string, value: number, argName: string): void;
110
+ /**
111
+ * Split "not an integer" into the two mistakes it can be: `TypeError` when the
112
+ * value is not a `number` at all, `RangeError` when it is a number but not
113
+ * integral -- the right-type, wrong-domain half of the same message.
114
+ *
115
+ * `Number.isInteger` alone answers both, which is why a single check reads as
116
+ * sufficient; what it cannot do is say which one happened, and a caller can act
117
+ * only on the mistake they made. The classes are the contract on this surface,
118
+ * so a sibling argument in the same call must not report a fraction differently
119
+ * from this one.
120
+ */
121
+ export declare function assertIntegerValue(fnName: string, value: unknown, argName: string): asserts value is number;
122
+ /** Even integer in `[min, max]`, for an FFT-style size where only parity matters. */
123
+ export declare function assertEvenIntegerAtLeast(fnName: string, value: number, argName: string, min: number, max: number): void;
124
+ /** General integer-in-`[min, max]` check, for a bound {@link assertU7}/{@link assertNibble} don't cover. */
125
+ export declare function assertBoundedInteger(fnName: string, value: number, argName: string, min: number, max: number): void;
126
+ export declare function assertU7(fnName: string, value: number, argName: string): number;
127
+ export declare function assertNibble(fnName: string, value: number, argName: string): number;
128
+ export declare function assertU32(fnName: string, value: number, argName: string): void;
129
+ /**
130
+ * Convert a caller-supplied index array to `Int32Array`, refusing any element
131
+ * the conversion would change rather than folding it.
132
+ *
133
+ * `Int32Array.from(values, Math.trunc)` turns the sample index `1000.7` into
134
+ * `1000` and `2 ** 31` into `-2 ** 31`. The C ABI takes `const int*`, so both
135
+ * arrive as values nothing downstream can separate from ones the caller chose.
136
+ * An `Int32Array` is returned as-is: its elements are already exact.
137
+ */
138
+ export declare function toInt32Array(fnName: string, values: Int32Array | ArrayLike<number>, argName: string): Int32Array;
139
+ export declare function assertInterleavedSamples(fnName: string, samples: ArrayLike<number>, channels: number, validate: boolean): void;
140
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ import type { MidiCcBindOptions } from './realtime_engine';
2
+ export interface WebMidiEngine {
3
+ bindMidiCc(channel: number, controller: number, paramId: number, options?: MidiCcBindOptions): void;
4
+ setMidiInputSource(destinationId?: number): void;
5
+ clearMidiInputSource(): void;
6
+ pushMidiInputNoteOn(group: number, channel: number, note: number, velocity: number, time?: number): void;
7
+ pushMidiInputNoteOff(group: number, channel: number, note: number, velocity?: number, time?: number): void;
8
+ pushMidiInputCc(group: number, channel: number, controller: number, value: number, time?: number): void;
9
+ }
10
+ type MidiInputState = 'connected' | 'disconnected';
11
+ interface MidiPortLike {
12
+ id: string;
13
+ name?: string | null;
14
+ manufacturer?: string | null;
15
+ state?: MidiInputState;
16
+ }
17
+ interface MidiMessageEventLike {
18
+ data: ArrayLike<number>;
19
+ timeStamp?: number;
20
+ receivedTime?: number;
21
+ target?: MidiPortLike;
22
+ currentTarget?: MidiPortLike;
23
+ }
24
+ interface MidiInputLike extends MidiPortLike {
25
+ type?: 'input';
26
+ onmidimessage: ((event: MidiMessageEventLike) => void) | null;
27
+ addEventListener?: (type: 'midimessage', listener: (event: MidiMessageEventLike) => void) => void;
28
+ removeEventListener?: (type: 'midimessage', listener: (event: MidiMessageEventLike) => void) => void;
29
+ }
30
+ interface MidiConnectionEventLike {
31
+ port?: MidiPortLike | null;
32
+ }
33
+ interface MidiAccessLike {
34
+ inputs: Map<string, MidiInputLike> | Iterable<[string, MidiInputLike]>;
35
+ onstatechange: ((event: MidiConnectionEventLike) => void) | null;
36
+ addEventListener?: (type: 'statechange', listener: (event: MidiConnectionEventLike) => void) => void;
37
+ removeEventListener?: (type: 'statechange', listener: (event: MidiConnectionEventLike) => void) => void;
38
+ }
39
+ export interface WebMidiCcBinding {
40
+ channel: number;
41
+ controller: number;
42
+ paramId: number;
43
+ options?: MidiCcBindOptions;
44
+ }
45
+ export interface WebMidiInputInfo {
46
+ id: string;
47
+ name: string;
48
+ manufacturer: string;
49
+ state: MidiInputState;
50
+ }
51
+ export interface BindWebMidiOptions {
52
+ /** Realtime-engine MIDI destination receiving the live input source. Default `0`. */
53
+ destinationId?: number;
54
+ /** UMP group used for MIDI 1.0 channel voice events. Default `0`. */
55
+ group?: number;
56
+ /** Restrict binding to specific Web MIDI input ids. Omit or empty = all connected inputs. */
57
+ inputIds?: readonly string[];
58
+ /** Request SysEx-capable access from the browser. Default `false`. */
59
+ sysex?: boolean;
60
+ /** Request software ports from the browser where supported. Default `true`. */
61
+ software?: boolean;
62
+ /** Bind CC-to-parameter mappings before ports are connected. */
63
+ ccBindings?: readonly WebMidiCcBinding[];
64
+ /** Convert a Web MIDI event timestamp to engine port-time samples. */
65
+ timestampToSamples?: (eventTimeMs: number) => number;
66
+ /** Observe hot-plug updates after the helper rebinds matching inputs. */
67
+ onInputsChanged?: (inputs: WebMidiInputInfo[]) => void;
68
+ }
69
+ export interface WebMidiBinding {
70
+ access: MidiAccessLike;
71
+ inputs(): WebMidiInputInfo[];
72
+ close(): void;
73
+ }
74
+ export declare function isWebMidiAvailable(): boolean;
75
+ export declare function bindWebMidi(engine: WebMidiEngine, options?: BindWebMidiOptions): Promise<WebMidiBinding>;
76
+ export {};
77
+ //# sourceMappingURL=web_midi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web_midi.d.ts","sourceRoot":"","sources":["../src/web_midi.ts"],"names":[],"mappings":"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"}
package/dist/worker.d.ts CHANGED
@@ -1,46 +1,3 @@
1
- /**
2
- * Internal structured-clone protocol for the offline Web Worker bridge.
3
- *
4
- * Keep this deliberately limited to one-shot operations. Embind handles own
5
- * native resources and cannot safely cross a worker boundary.
6
- */
7
- type OfflineWorkerOperation = 'analyze' | 'detectBpm' | 'detectKey' | 'detectChords' | 'masterAudio' | 'masterAudioStereo';
8
- interface OfflineWorkerRunMessage {
9
- type: 'sonare:offline-run';
10
- id: number;
11
- operation: OfflineWorkerOperation;
12
- request: Record<string, unknown>;
13
- /** A shared flag lets cancellation reach synchronous WASM progress callbacks. */
14
- cancelBuffer?: SharedArrayBuffer;
15
- }
16
- interface OfflineWorkerCancelMessage {
17
- type: 'sonare:offline-cancel';
18
- id: number;
19
- }
20
- type OfflineWorkerRequestMessage = OfflineWorkerRunMessage | OfflineWorkerCancelMessage;
21
- interface OfflineWorkerProgressMessage {
22
- type: 'sonare:offline-progress';
23
- id: number;
24
- progress: number;
25
- stage: string;
26
- }
27
- interface OfflineWorkerResultMessage {
28
- type: 'sonare:offline-result';
29
- id: number;
30
- result: unknown;
31
- }
32
- interface OfflineWorkerErrorMessage {
33
- type: 'sonare:offline-error';
34
- id: number;
35
- error: {
36
- name: string;
37
- message: string;
38
- code?: number;
39
- codeName?: string;
40
- };
41
- }
42
- type OfflineWorkerResponseMessage = OfflineWorkerProgressMessage | OfflineWorkerResultMessage | OfflineWorkerErrorMessage;
43
-
44
1
  /**
45
2
  * Offline one-shot operations hosted inside a dedicated Web Worker.
46
3
  *
@@ -49,9 +6,10 @@ type OfflineWorkerResponseMessage = OfflineWorkerProgressMessage | OfflineWorker
49
6
  * bound to one JavaScript realm, so moving them across a Worker boundary would
50
7
  * make ownership and `delete()` semantics unsound.
51
8
  */
52
-
9
+ import type { OfflineWorkerRequestMessage, OfflineWorkerResponseMessage } from './worker_protocol';
10
+ export type { OfflineWorkerOperation } from './worker_protocol';
53
11
  /** Minimal endpoint shared by browser Workers and the Node worker-thread test bridge. */
54
- interface OfflineWorkerEndpoint {
12
+ export interface OfflineWorkerEndpoint {
55
13
  postMessage(message: OfflineWorkerResponseMessage, transfer?: Transferable[]): void;
56
14
  addEventListener(type: 'message', listener: (event: MessageEvent<OfflineWorkerRequestMessage>) => void): void;
57
15
  }
@@ -60,6 +18,5 @@ interface OfflineWorkerEndpoint {
60
18
  * the Node `worker_threads` test adapter; browsers install it automatically
61
19
  * when this module is loaded as a Worker entry point.
62
20
  */
63
- declare function installOfflineWorkerEndpoint(endpoint: OfflineWorkerEndpoint): void;
64
-
65
- export { type OfflineWorkerEndpoint, type OfflineWorkerOperation, installOfflineWorkerEndpoint };
21
+ export declare function installOfflineWorkerEndpoint(endpoint: OfflineWorkerEndpoint): void;
22
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH,OAAO,KAAK,EAEV,2BAA2B,EAC3B,4BAA4B,EAE7B,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEhE,yFAAyF;AACzF,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,OAAO,EAAE,4BAA4B,EAAE,QAAQ,CAAC,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IACpF,gBAAgB,CACd,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,2BAA2B,CAAC,KAAK,IAAI,GACnE,IAAI,CAAC;CACT;AAyDD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CA0FlF"}
package/dist/worker.js CHANGED
@@ -6,7 +6,21 @@ var SonareError = class extends Error {
6
6
  this.code = code;
7
7
  this.codeName = codeName;
8
8
  }
9
+ /**
10
+ * Brand-based `instanceof`: an error that carries the shape narrows here even
11
+ * when it is not literally an instance of this class. That is not a
12
+ * hypothetical — an error posted from the analysis worker arrives as a
13
+ * structured clone with its prototype gone, which a prototype-based
14
+ * `instanceof` would silently miss. Delegates to {@link isSonareError} so the
15
+ * two never disagree.
16
+ */
17
+ static [Symbol.hasInstance](value) {
18
+ return isSonareError(value);
19
+ }
9
20
  };
21
+ function isSonareError(value) {
22
+ return value instanceof Error && value.name === "SonareError" && typeof value.code === "number";
23
+ }
10
24
 
11
25
  // src/module_state.ts
12
26
  var wrappedModule = null;
@@ -34,6 +48,11 @@ function makeSonareError(raw, thrown) {
34
48
  message = info.message || message;
35
49
  }
36
50
  } catch {
51
+ } finally {
52
+ try {
53
+ raw.sonareReleaseException(thrown);
54
+ } catch {
55
+ }
37
56
  }
38
57
  return new SonareError(code, codeName, message);
39
58
  }
@@ -54,6 +73,10 @@ function wrapModuleErrors(raw) {
54
73
  if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer || value instanceof Promise) {
55
74
  return value;
56
75
  }
76
+ const proto = Object.getPrototypeOf(value);
77
+ if (Array.isArray(value) || proto === Object.prototype || proto === null) {
78
+ return value;
79
+ }
57
80
  const objectValue = value;
58
81
  const cached = objectCache.get(objectValue);
59
82
  if (cached) {
@@ -150,6 +173,46 @@ function getSonareModule() {
150
173
  return wrappedModule;
151
174
  }
152
175
 
176
+ // src/codes.ts
177
+ function resolveOrdinalInRange(value, min, max, enumName) {
178
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < min || value > max) {
179
+ throw new RangeError(`Invalid ${enumName}: ${String(value)}`);
180
+ }
181
+ return value;
182
+ }
183
+ function resolveEnumOrdinal(value, values, enumName) {
184
+ if (typeof value === "number") {
185
+ const ordinals = Object.values(values);
186
+ const ordinal = resolveOrdinalInRange(
187
+ value,
188
+ Math.min(...ordinals),
189
+ Math.max(...ordinals),
190
+ enumName
191
+ );
192
+ if (!ordinals.includes(ordinal)) {
193
+ throw new RangeError(`Invalid ${enumName}: ${String(value)}`);
194
+ }
195
+ return ordinal;
196
+ }
197
+ if (typeof value === "string") {
198
+ const ordinal = values[value];
199
+ if (ordinal !== void 0) {
200
+ return ordinal;
201
+ }
202
+ }
203
+ throw new RangeError(`Invalid ${enumName}: ${String(value)}`);
204
+ }
205
+ var AUTOMATION_CURVE_VALUES = {
206
+ linear: 0,
207
+ exponential: 1,
208
+ hold: 2,
209
+ "s-curve": 3
210
+ };
211
+ var PROJECT_AUTOMATION_CURVE_VALUES = {
212
+ ...AUTOMATION_CURVE_VALUES,
213
+ scurve: 3
214
+ };
215
+
153
216
  // src/validation.ts
154
217
  var MIN_AUDIO_SAMPLE_RATE = 8e3;
155
218
  var MAX_AUDIO_SAMPLE_RATE = 384e3;
@@ -173,10 +236,13 @@ function assertSamples(fnName, samples, validate, argName = "samples") {
173
236
  assertNonEmptySamples(fnName, samples, argName);
174
237
  assertFiniteSamples(fnName, samples, validate, argName);
175
238
  }
176
- function assertSampleRate(fnName, sampleRate) {
177
- if (!Number.isInteger(sampleRate) || sampleRate < MIN_AUDIO_SAMPLE_RATE || sampleRate > MAX_AUDIO_SAMPLE_RATE) {
239
+ function assertSampleRate(fnName, sampleRate, argName = "sampleRate") {
240
+ if (!Number.isInteger(sampleRate)) {
241
+ throw new RangeError(`${fnName}: ${argName} must be an integer`);
242
+ }
243
+ if (sampleRate < MIN_AUDIO_SAMPLE_RATE || sampleRate > MAX_AUDIO_SAMPLE_RATE) {
178
244
  throw new RangeError(
179
- `${fnName}: sampleRate out of supported range [${MIN_AUDIO_SAMPLE_RATE}, ${MAX_AUDIO_SAMPLE_RATE}]`
245
+ `${fnName}: ${argName} out of supported range [${MIN_AUDIO_SAMPLE_RATE}, ${MAX_AUDIO_SAMPLE_RATE}]`
180
246
  );
181
247
  }
182
248
  }
@@ -284,36 +350,6 @@ function masterAudioStereo(left, right = void 0, sampleRate = 22050, presetName
284
350
  );
285
351
  }
286
352
 
287
- // src/codes.ts
288
- function resolveOrdinalInRange(value, min, max, enumName) {
289
- if (typeof value !== "number" || !Number.isSafeInteger(value) || value < min || value > max) {
290
- throw new RangeError(`Invalid ${enumName}: ${String(value)}`);
291
- }
292
- return value;
293
- }
294
- function resolveEnumOrdinal(value, values, enumName) {
295
- if (typeof value === "number") {
296
- const ordinals = Object.values(values);
297
- const ordinal = resolveOrdinalInRange(
298
- value,
299
- Math.min(...ordinals),
300
- Math.max(...ordinals),
301
- enumName
302
- );
303
- if (!ordinals.includes(ordinal)) {
304
- throw new RangeError(`Invalid ${enumName}: ${String(value)}`);
305
- }
306
- return ordinal;
307
- }
308
- if (typeof value === "string") {
309
- const ordinal = values[value];
310
- if (ordinal !== void 0) {
311
- return ordinal;
312
- }
313
- }
314
- throw new RangeError(`Invalid ${enumName}: ${String(value)}`);
315
- }
316
-
317
353
  // src/public_types_music.ts
318
354
  var PitchClass = {
319
355
  C: 0,
@@ -426,6 +462,7 @@ function convertChordAnalysisResult(wasm) {
426
462
  quality: c.quality,
427
463
  start: c.start,
428
464
  end: c.end,
465
+ duration: c.end - c.start,
429
466
  confidence: c.confidence,
430
467
  name: c.name
431
468
  }))
@@ -464,6 +501,10 @@ function convertAnalysisResult(wasm) {
464
501
  timeSignatureCandidates: wasm.timeSignatureCandidates,
465
502
  beatTimes,
466
503
  beats: wasm.beats,
504
+ downbeatIndices: wasm.downbeatIndices,
505
+ downbeatPhase: wasm.downbeatPhase,
506
+ beatObservations: wasm.beatObservations,
507
+ beatLocalBpm: wasm.beatLocalBpm,
467
508
  chords: wasm.chords.map((c) => ({
468
509
  root: c.root,
469
510
  bass: c.bass,
@@ -472,8 +513,10 @@ function convertAnalysisResult(wasm) {
472
513
  quality: c.quality,
473
514
  start: c.start,
474
515
  end: c.end,
516
+ duration: c.end - c.start,
475
517
  confidence: c.confidence,
476
- name: c.name
518
+ name: c.name,
519
+ romanNumeral: c.romanNumeral
477
520
  })),
478
521
  sections: wasm.sections.map((s) => ({
479
522
  type: s.type,
@@ -546,12 +589,13 @@ function detectChords(samples, sampleRate = 22050, options = {}) {
546
589
  request.keyRoot ?? PitchClass.C,
547
590
  request.keyMode ?? Mode.Major,
548
591
  request.detectInversions ?? false,
549
- chordChromaMethodValue(request.chromaMethod ?? "stft")
592
+ chordChromaMethodValue(request.chromaMethod ?? "stft"),
593
+ request.tuning ?? 0
550
594
  );
551
595
  return convertChordAnalysisResult(result);
552
596
  }
553
- function analyzeWithProgress(samples, sampleRate = 22050, onProgress) {
554
- const request = samples instanceof Float32Array ? { samples, sampleRate, onProgress } : samples;
597
+ function analyzeWithProgress(samples, sampleRate = 22050, onProgress, options) {
598
+ const request = samples instanceof Float32Array ? { samples, sampleRate, onProgress, options } : samples;
555
599
  validateAnalysisInput(
556
600
  "analyzeWithProgress",
557
601
  request.samples,
@@ -561,6 +605,7 @@ function analyzeWithProgress(samples, sampleRate = 22050, onProgress) {
561
605
  const result = requireModule2().analyzeWithProgress(
562
606
  request.samples,
563
607
  request.sampleRate ?? 22050,
608
+ request.options ?? {},
564
609
  request.onProgress ?? (() => {
565
610
  }),
566
611
  request.cancel ?? (() => false)
@@ -646,7 +691,9 @@ function cancelledError() {
646
691
  }
647
692
  function installOfflineWorkerEndpoint(endpoint2) {
648
693
  const cancelled = /* @__PURE__ */ new Set();
694
+ const inFlight = /* @__PURE__ */ new Set();
649
695
  const run = async (message) => {
696
+ inFlight.add(message.id);
650
697
  const cancelFlag = message.cancelBuffer ? new Int32Array(message.cancelBuffer) : void 0;
651
698
  const isCancelled = () => cancelled.has(message.id) || cancelFlag !== void 0 && Atomics.load(cancelFlag, 0) !== 0;
652
699
  const onProgress = (progress, stage) => {
@@ -663,7 +710,8 @@ function installOfflineWorkerEndpoint(endpoint2) {
663
710
  case "analyze":
664
711
  result = analyzeWithProgress({
665
712
  ...message.request,
666
- onProgress
713
+ onProgress,
714
+ cancel: isCancelled
667
715
  });
668
716
  break;
669
717
  case "detectBpm":
@@ -678,13 +726,15 @@ function installOfflineWorkerEndpoint(endpoint2) {
678
726
  case "masterAudio":
679
727
  result = masterAudio({
680
728
  ...message.request,
681
- onProgress
729
+ onProgress,
730
+ cancel: isCancelled
682
731
  });
683
732
  break;
684
733
  case "masterAudioStereo":
685
734
  result = masterAudioStereo({
686
735
  ...message.request,
687
- onProgress
736
+ onProgress,
737
+ cancel: isCancelled
688
738
  });
689
739
  break;
690
740
  }
@@ -703,12 +753,15 @@ function installOfflineWorkerEndpoint(endpoint2) {
703
753
  });
704
754
  } finally {
705
755
  cancelled.delete(message.id);
756
+ inFlight.delete(message.id);
706
757
  }
707
758
  };
708
759
  endpoint2.addEventListener("message", (event) => {
709
760
  const message = event.data;
710
761
  if (message.type === "sonare:offline-cancel") {
711
- cancelled.add(message.id);
762
+ if (inFlight.has(message.id)) {
763
+ cancelled.add(message.id);
764
+ }
712
765
  return;
713
766
  }
714
767
  void run(message);