@octoseq/mir 0.1.0-main.4ecb074 → 0.1.0-main.5fdb072
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.
- package/dist/chunk-HF3QHCRK.js +3234 -0
- package/dist/chunk-HF3QHCRK.js.map +1 -0
- package/dist/index.d.ts +2122 -47
- package/dist/index.js +3524 -39
- package/dist/index.js.map +1 -1
- package/dist/runMir-CnJQbBr8.d.ts +187 -0
- package/dist/runner/runMir.d.ts +2 -2
- package/dist/runner/runMir.js +1 -1
- package/dist/runner/workerProtocol.d.ts +8 -1
- package/dist/runner/workerProtocol.js.map +1 -1
- package/dist/types-DqH4umN8.d.ts +761 -0
- package/package.json +2 -2
- package/src/dsp/activity.ts +544 -0
- package/src/dsp/bandCqt.ts +662 -0
- package/src/dsp/bandEvents.ts +351 -0
- package/src/dsp/bandMask.ts +225 -0
- package/src/dsp/bandMir.ts +524 -0
- package/src/dsp/bandProposal.ts +552 -0
- package/src/dsp/beatCandidates.ts +299 -0
- package/src/dsp/cqt.ts +386 -0
- package/src/dsp/cqtSignals.ts +462 -0
- package/src/dsp/customSignalReduction.ts +841 -0
- package/src/dsp/eventToSignal.ts +531 -0
- package/src/dsp/frequencyBand.ts +956 -0
- package/src/dsp/mel.ts +56 -3
- package/src/dsp/musicalTime.ts +240 -0
- package/src/dsp/onset.ts +296 -30
- package/src/dsp/peakPicking.ts +519 -0
- package/src/dsp/phaseAlignment.ts +153 -0
- package/src/dsp/pitch.ts +289 -0
- package/src/dsp/resample.ts +44 -0
- package/src/dsp/signalTransforms.ts +660 -0
- package/src/dsp/silenceGating.ts +511 -0
- package/src/dsp/spectral.ts +124 -4
- package/src/dsp/tempoHypotheses.ts +395 -0
- package/src/gpu/bufferPool.ts +266 -0
- package/src/gpu/context.ts +30 -6
- package/src/gpu/helpers.ts +85 -0
- package/src/gpu/melProject.ts +83 -0
- package/src/index.ts +366 -5
- package/src/runner/runMir.ts +234 -2
- package/src/runner/workerProtocol.ts +9 -1
- package/src/types.ts +768 -3
- package/dist/chunk-DUWYCAVG.js +0 -1525
- package/dist/chunk-DUWYCAVG.js.map +0 -1
- package/dist/runMir-CSIBwNZ3.d.ts +0 -84
- package/dist/types-BE3py4fZ.d.ts +0 -83
package/dist/index.d.ts
CHANGED
|
@@ -1,23 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Spectral centroid per frame (Hz).
|
|
7
|
-
*
|
|
8
|
-
* Output is aligned 1:1 with `spec.times`.
|
|
9
|
-
*/
|
|
10
|
-
declare function spectralCentroid(spec: Spectrogram): Float32Array;
|
|
11
|
-
/**
|
|
12
|
-
* Spectral flux per frame (unitless).
|
|
13
|
-
*
|
|
14
|
-
* Definition used here:
|
|
15
|
-
* - L1 distance between successive *normalised* magnitude spectra.
|
|
16
|
-
* - First frame flux is 0.
|
|
17
|
-
*
|
|
18
|
-
* Output is aligned 1:1 with `spec.times`.
|
|
19
|
-
*/
|
|
20
|
-
declare function spectralFlux(spec: Spectrogram): Float32Array;
|
|
1
|
+
import { B as BeatCandidate, T as TempoHypothesis, P as PhaseAlignmentConfig, a as PhaseHypothesis, M as MusicalTimeSegment, b as BeatPosition, c as MusicalTimeStructure, d as BeatGrid, F as FrequencySegment, e as FrequencyBand, f as FrequencyBandStructure, g as FrequencyBoundsAtTime, h as FrequencyKeyframe, i as BandMirFunctionId, j as BandMir1DResult, k as BandEventFunctionId, l as BandEventsResult, C as CqtConfig, m as BandCqtFunctionId, n as BandCqt1DResult, o as CqtSpectrogram, p as MirRunMeta, q as CqtSignalResult, r as CqtSignalId, s as BandProposalConfig, t as BandProposalResult } from './types-DqH4umN8.js';
|
|
2
|
+
export { S as BandEventDiagnostics, Q as BandMirDiagnostics, R as BandMirEvent, V as BandProposal, U as BandProposalSource, H as BeatCandidateSource, I as BeatCandidatesResult, O as FrequencyBandProvenance, N as FrequencyBandTimeScope, w as Mir1DResult, x as Mir2DResult, y as MirActivityDiagnostics, z as MirActivityResult, G as MirAudioPayload, u as MirBackend, D as MirFunctionId, A as MirResult, E as MirRunRequest, v as MirRunTimings, L as MusicalTimeProvenance, K as TempoHypothesesResult, J as TempoHypothesisEvidence } from './types-DqH4umN8.js';
|
|
3
|
+
import { S as Spectrogram, M as MirGPU, A as AudioBufferLike$1 } from './runMir-CnJQbBr8.js';
|
|
4
|
+
export { a as SpectrogramConfig, r as runMir, s as spectrogram } from './runMir-CnJQbBr8.js';
|
|
21
5
|
|
|
22
6
|
type MelConfig = {
|
|
23
7
|
nMels: number;
|
|
@@ -32,6 +16,42 @@ type MelSpectrogram = {
|
|
|
32
16
|
gpuSubmitToReadbackMs: number;
|
|
33
17
|
};
|
|
34
18
|
};
|
|
19
|
+
/**
|
|
20
|
+
* Convert frequency in Hz to mel scale.
|
|
21
|
+
* Uses Slaney-style (HTK-like) approximation.
|
|
22
|
+
*/
|
|
23
|
+
declare function hzToMel(hz: number): number;
|
|
24
|
+
/**
|
|
25
|
+
* Convert mel scale value to frequency in Hz.
|
|
26
|
+
* Inverse of hzToMel.
|
|
27
|
+
*/
|
|
28
|
+
declare function melToHz(mel: number): number;
|
|
29
|
+
/**
|
|
30
|
+
* Configuration for mel frequency conversions.
|
|
31
|
+
*/
|
|
32
|
+
type MelConversionConfig = {
|
|
33
|
+
nMels: number;
|
|
34
|
+
fMin: number;
|
|
35
|
+
fMax: number;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Convert a frequency in Hz to a feature index (0 to nMels-1).
|
|
39
|
+
* The mapping is linear in mel space.
|
|
40
|
+
*
|
|
41
|
+
* @param hz - Frequency in Hz
|
|
42
|
+
* @param config - Mel configuration with nMels, fMin, fMax
|
|
43
|
+
* @returns Feature index as a continuous value (may be fractional)
|
|
44
|
+
*/
|
|
45
|
+
declare function hzToFeatureIndex(hz: number, config: MelConversionConfig): number;
|
|
46
|
+
/**
|
|
47
|
+
* Convert a feature index (0 to nMels-1) to frequency in Hz.
|
|
48
|
+
* Inverse of hzToFeatureIndex.
|
|
49
|
+
*
|
|
50
|
+
* @param index - Feature index (can be fractional)
|
|
51
|
+
* @param config - Mel configuration with nMels, fMin, fMax
|
|
52
|
+
* @returns Frequency in Hz
|
|
53
|
+
*/
|
|
54
|
+
declare function featureIndexToHz(index: number, config: MelConversionConfig): number;
|
|
35
55
|
/**
|
|
36
56
|
* Compute a (log) mel spectrogram by projecting an existing spectrogram.
|
|
37
57
|
*
|
|
@@ -41,10 +61,437 @@ type MelSpectrogram = {
|
|
|
41
61
|
*/
|
|
42
62
|
declare function melSpectrogram(spec: Spectrogram, config: MelConfig, gpu?: MirGPU): Promise<MelSpectrogram>;
|
|
43
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Activity Signal - First-class MIR feature for audibility detection.
|
|
66
|
+
*
|
|
67
|
+
* The Activity Signal represents whether audible content is present at each frame.
|
|
68
|
+
* It is the foundation for silence-aware MIR processing across all features.
|
|
69
|
+
*
|
|
70
|
+
* Design Principles:
|
|
71
|
+
* 1. Silence is a distinct state, not "low energy sound"
|
|
72
|
+
* 2. Activity detection is shared, not reimplemented per feature
|
|
73
|
+
* 3. Activity is computed from whole-track context (adaptive thresholds)
|
|
74
|
+
* 4. The signal is inspectable and visualizable
|
|
75
|
+
*
|
|
76
|
+
* Semantics:
|
|
77
|
+
* - activity_level: 0 = silence/inaudible, 1 = confidently audible
|
|
78
|
+
* - is_active: boolean derived from activity_level
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Configuration for activity detection.
|
|
83
|
+
*/
|
|
84
|
+
type ActivityConfig = {
|
|
85
|
+
/**
|
|
86
|
+
* Percentile (0-100) used to estimate the noise floor from frame energies.
|
|
87
|
+
* Lower values are more conservative (estimate floor from quieter frames).
|
|
88
|
+
* @default 10
|
|
89
|
+
*/
|
|
90
|
+
energyPercentile?: number;
|
|
91
|
+
/**
|
|
92
|
+
* Margin above noise floor to enter active state.
|
|
93
|
+
* For log-scale energies (mel), this is effectively dB.
|
|
94
|
+
* @default 6
|
|
95
|
+
*/
|
|
96
|
+
enterMargin?: number;
|
|
97
|
+
/**
|
|
98
|
+
* Margin above noise floor to remain in active state.
|
|
99
|
+
* Must be less than enterMargin for proper hysteresis.
|
|
100
|
+
* @default 3
|
|
101
|
+
*/
|
|
102
|
+
exitMargin?: number;
|
|
103
|
+
/**
|
|
104
|
+
* Duration in milliseconds to remain active after energy drops below exit threshold.
|
|
105
|
+
* Prevents rapid toggling near silence.
|
|
106
|
+
* @default 50
|
|
107
|
+
*/
|
|
108
|
+
hangoverMs?: number;
|
|
109
|
+
/**
|
|
110
|
+
* Minimum duration in milliseconds a region must be active.
|
|
111
|
+
* Regions shorter than this are marked inactive.
|
|
112
|
+
* @default 30
|
|
113
|
+
*/
|
|
114
|
+
minActiveMs?: number;
|
|
115
|
+
/**
|
|
116
|
+
* Smoothing window in milliseconds for activity_level output.
|
|
117
|
+
* Produces smoother transitions. 0 = no smoothing.
|
|
118
|
+
* @default 20
|
|
119
|
+
*/
|
|
120
|
+
smoothMs?: number;
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Activity Signal result - the main output type.
|
|
124
|
+
*/
|
|
125
|
+
type ActivitySignal = {
|
|
126
|
+
/** Frame times in seconds, aligned with source spectrogram/mel. */
|
|
127
|
+
times: Float32Array;
|
|
128
|
+
/**
|
|
129
|
+
* Continuous activity level in range [0, 1].
|
|
130
|
+
* 0 = silence, 1 = confidently active.
|
|
131
|
+
* Intermediate values occur at transitions and represent uncertainty.
|
|
132
|
+
*/
|
|
133
|
+
activityLevel: Float32Array;
|
|
134
|
+
/**
|
|
135
|
+
* Binary activity mask (0 = inactive, 1 = active).
|
|
136
|
+
* Derived from the underlying hysteresis state machine.
|
|
137
|
+
*/
|
|
138
|
+
isActive: Uint8Array;
|
|
139
|
+
/**
|
|
140
|
+
* Per-frame suppression mask (0 = allow, 1 = suppress).
|
|
141
|
+
* Used to suppress features immediately after silence-to-active transitions.
|
|
142
|
+
*/
|
|
143
|
+
suppressMask: Uint8Array;
|
|
144
|
+
/** Diagnostic information for debugging and visualization. */
|
|
145
|
+
diagnostics: ActivityDiagnostics;
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Diagnostics for inspecting activity detection behavior.
|
|
149
|
+
*/
|
|
150
|
+
type ActivityDiagnostics = {
|
|
151
|
+
/** Per-frame energy values used for detection. */
|
|
152
|
+
frameEnergy: Float32Array;
|
|
153
|
+
/** Estimated noise floor value. */
|
|
154
|
+
noiseFloor: number;
|
|
155
|
+
/** Threshold for entering active state. */
|
|
156
|
+
enterThreshold: number;
|
|
157
|
+
/** Threshold for exiting active state. */
|
|
158
|
+
exitThreshold: number;
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* Compute Activity Signal from mel spectrogram.
|
|
162
|
+
*
|
|
163
|
+
* This is the primary entry point for activity detection.
|
|
164
|
+
* Mel spectrograms are preferred because their log-scale energies
|
|
165
|
+
* provide more perceptually meaningful thresholds.
|
|
166
|
+
*
|
|
167
|
+
* @param mel - Mel spectrogram (log-scale energies)
|
|
168
|
+
* @param config - Activity detection configuration
|
|
169
|
+
* @returns Complete activity signal with diagnostics
|
|
170
|
+
*/
|
|
171
|
+
declare function computeActivityFromMel(mel: MelSpectrogram, config?: ActivityConfig): ActivitySignal;
|
|
172
|
+
/**
|
|
173
|
+
* Compute Activity Signal from linear magnitude spectrogram.
|
|
174
|
+
*
|
|
175
|
+
* This function first converts magnitudes to log scale for threshold computation.
|
|
176
|
+
*
|
|
177
|
+
* @param spec - Linear magnitude spectrogram
|
|
178
|
+
* @param config - Activity detection configuration
|
|
179
|
+
* @returns Complete activity signal with diagnostics
|
|
180
|
+
*/
|
|
181
|
+
declare function computeActivityFromSpectrogram(spec: Spectrogram, config?: ActivityConfig): ActivitySignal;
|
|
182
|
+
/**
|
|
183
|
+
* Compute Activity Signal from raw audio samples.
|
|
184
|
+
*
|
|
185
|
+
* Uses a simple RMS-based energy computation. This is useful when
|
|
186
|
+
* no spectrogram is available, but mel-based detection is preferred.
|
|
187
|
+
*
|
|
188
|
+
* @param samples - Mono audio samples
|
|
189
|
+
* @param sampleRate - Sample rate of the audio
|
|
190
|
+
* @param hopSize - Analysis hop size in samples
|
|
191
|
+
* @param windowSize - Analysis window size in samples
|
|
192
|
+
* @param config - Activity detection configuration
|
|
193
|
+
* @returns Complete activity signal with diagnostics
|
|
194
|
+
*/
|
|
195
|
+
declare function computeActivityFromAudio(samples: Float32Array, sampleRate: number, hopSize: number, windowSize: number, config?: ActivityConfig): ActivitySignal;
|
|
196
|
+
/**
|
|
197
|
+
* Apply activity gating to a 1D signal.
|
|
198
|
+
*
|
|
199
|
+
* Zeros out values where activity is low.
|
|
200
|
+
*
|
|
201
|
+
* @param values - Signal values to gate (modified in place)
|
|
202
|
+
* @param activity - Activity signal
|
|
203
|
+
* @param options - Gating options
|
|
204
|
+
*/
|
|
205
|
+
declare function applyActivityGating(values: Float32Array, activity: ActivitySignal, options?: {
|
|
206
|
+
/** Use binary mask instead of continuous level. Default: true */
|
|
207
|
+
useBinaryMask?: boolean;
|
|
208
|
+
/** Also apply post-silence suppression. Default: true */
|
|
209
|
+
suppressPostSilence?: boolean;
|
|
210
|
+
/** Threshold for activity_level when not using binary mask. Default: 0.5 */
|
|
211
|
+
levelThreshold?: number;
|
|
212
|
+
}): void;
|
|
213
|
+
/**
|
|
214
|
+
* Interpolate activity signal to a different time grid.
|
|
215
|
+
*
|
|
216
|
+
* Useful when you have activity computed at one resolution (e.g., mel frames)
|
|
217
|
+
* but need it at another resolution (e.g., pitch frames).
|
|
218
|
+
*
|
|
219
|
+
* @param activity - Source activity signal
|
|
220
|
+
* @param targetTimes - Target time grid
|
|
221
|
+
* @returns Activity signal interpolated to target times
|
|
222
|
+
*/
|
|
223
|
+
declare function interpolateActivity(activity: ActivitySignal, targetTimes: Float32Array): ActivitySignal;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Options for activity-aware spectral features.
|
|
227
|
+
*/
|
|
228
|
+
type SpectralActivityOptions = {
|
|
229
|
+
/**
|
|
230
|
+
* Activity signal to use for gating.
|
|
231
|
+
* If provided, feature values will be zeroed in inactive regions.
|
|
232
|
+
*/
|
|
233
|
+
activity?: ActivitySignal;
|
|
234
|
+
/**
|
|
235
|
+
* Behavior for inactive frames.
|
|
236
|
+
* - "zero": Output 0 (default)
|
|
237
|
+
* - "hold": Hold the last active value
|
|
238
|
+
*/
|
|
239
|
+
inactiveBehavior?: "zero" | "hold";
|
|
240
|
+
};
|
|
241
|
+
type AmplitudeEnvelopeConfig = {
|
|
242
|
+
/** Hop size in samples (determines time resolution). Default: 512 */
|
|
243
|
+
hopSize?: number;
|
|
244
|
+
/** Window size for RMS calculation. Default: same as hopSize */
|
|
245
|
+
windowSize?: number;
|
|
246
|
+
};
|
|
247
|
+
type AmplitudeEnvelopeResult = {
|
|
248
|
+
times: Float32Array;
|
|
249
|
+
values: Float32Array;
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
252
|
+
* Amplitude envelope from raw audio samples.
|
|
253
|
+
*
|
|
254
|
+
* Computes RMS amplitude over windows of the time-domain signal.
|
|
255
|
+
* More efficient than spectrogram-based computation for full spectrum.
|
|
256
|
+
*
|
|
257
|
+
* @param samples - Mono audio samples
|
|
258
|
+
* @param sampleRate - Sample rate of the audio
|
|
259
|
+
* @param config - Configuration options
|
|
260
|
+
* @returns Times (seconds) and RMS amplitude values
|
|
261
|
+
*/
|
|
262
|
+
declare function amplitudeEnvelope(samples: Float32Array, sampleRate: number, config?: AmplitudeEnvelopeConfig): AmplitudeEnvelopeResult;
|
|
263
|
+
/**
|
|
264
|
+
* Spectral centroid per frame (Hz).
|
|
265
|
+
*
|
|
266
|
+
* Output is aligned 1:1 with `spec.times`.
|
|
267
|
+
*
|
|
268
|
+
* When activity gating is enabled:
|
|
269
|
+
* - Inactive frames output 0 (or hold last valid value if configured)
|
|
270
|
+
* - This prevents noise-induced centroid values during silence
|
|
271
|
+
*
|
|
272
|
+
* @param spec - Input spectrogram
|
|
273
|
+
* @param options - Activity gating options
|
|
274
|
+
*/
|
|
275
|
+
declare function spectralCentroid(spec: Spectrogram, options?: SpectralActivityOptions): Float32Array;
|
|
276
|
+
/**
|
|
277
|
+
* Spectral flux per frame (unitless).
|
|
278
|
+
*
|
|
279
|
+
* Definition used here:
|
|
280
|
+
* - L1 distance between successive *normalised* magnitude spectra.
|
|
281
|
+
* - First frame flux is 0.
|
|
282
|
+
*
|
|
283
|
+
* Output is aligned 1:1 with `spec.times`.
|
|
284
|
+
*
|
|
285
|
+
* When activity gating is enabled:
|
|
286
|
+
* - Inactive frames output 0
|
|
287
|
+
* - Post-silence suppression is applied (first active frames after silence are zeroed)
|
|
288
|
+
* - This prevents false flux spikes at silence/sound boundaries
|
|
289
|
+
*
|
|
290
|
+
* @param spec - Input spectrogram
|
|
291
|
+
* @param options - Activity gating options
|
|
292
|
+
*/
|
|
293
|
+
declare function spectralFlux(spec: Spectrogram, options?: SpectralActivityOptions): Float32Array;
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Silence-aware gating for onset detection.
|
|
297
|
+
*
|
|
298
|
+
* This module implements a production-grade silence detection and activity masking
|
|
299
|
+
* pipeline. Silence is treated as a first-class state, not "low energy sound".
|
|
300
|
+
*
|
|
301
|
+
* Pipeline stages:
|
|
302
|
+
* 1. Frame-level energy computation
|
|
303
|
+
* 2. Adaptive noise floor estimation (percentile-based)
|
|
304
|
+
* 3. Activity mask with hysteresis and hangover
|
|
305
|
+
* 4. Post-silence suppression window
|
|
306
|
+
*
|
|
307
|
+
* Design principles:
|
|
308
|
+
* - No fixed absolute thresholds - all thresholds are relative to estimated noise floor
|
|
309
|
+
* - Hysteresis prevents oscillation at threshold boundaries
|
|
310
|
+
* - Hangover prevents premature exit from active state
|
|
311
|
+
* - Post-silence suppression prevents the first audible frame from being an onset
|
|
312
|
+
*/
|
|
313
|
+
/**
|
|
314
|
+
* Configuration for silence-aware gating.
|
|
315
|
+
*/
|
|
316
|
+
type SilenceGateConfig = {
|
|
317
|
+
/**
|
|
318
|
+
* Whether gating is enabled. If false, all frames are considered active.
|
|
319
|
+
* @default true
|
|
320
|
+
*/
|
|
321
|
+
enabled?: boolean;
|
|
322
|
+
/**
|
|
323
|
+
* Percentile (0-100) used to estimate the noise floor from frame energies.
|
|
324
|
+
* Lower values are more conservative (estimate floor from quieter frames).
|
|
325
|
+
* @default 10
|
|
326
|
+
*/
|
|
327
|
+
energyPercentile?: number;
|
|
328
|
+
/**
|
|
329
|
+
* Margin above noise floor (in the same units as frame energy) to enter active state.
|
|
330
|
+
* For log-scale energies (mel), this is effectively dB.
|
|
331
|
+
* @default 6 (approximately 6 dB above floor for mel-based energy)
|
|
332
|
+
*/
|
|
333
|
+
enterMargin?: number;
|
|
334
|
+
/**
|
|
335
|
+
* Margin above noise floor to remain in active state.
|
|
336
|
+
* Must be less than enterMargin for proper hysteresis.
|
|
337
|
+
* @default 3 (approximately 3 dB above floor)
|
|
338
|
+
*/
|
|
339
|
+
exitMargin?: number;
|
|
340
|
+
/**
|
|
341
|
+
* Duration in milliseconds to remain active after energy drops below exit threshold.
|
|
342
|
+
* Prevents premature exit during brief dips.
|
|
343
|
+
* @default 50
|
|
344
|
+
*/
|
|
345
|
+
hangoverMs?: number;
|
|
346
|
+
/**
|
|
347
|
+
* Minimum duration in milliseconds a region must be active before allowing onsets.
|
|
348
|
+
* @default 0
|
|
349
|
+
*/
|
|
350
|
+
minActiveMs?: number;
|
|
351
|
+
/**
|
|
352
|
+
* Duration in milliseconds after transitioning from inactive to active
|
|
353
|
+
* during which onsets are suppressed.
|
|
354
|
+
* Prevents the first audible frame from being detected as an onset.
|
|
355
|
+
* @default 50
|
|
356
|
+
*/
|
|
357
|
+
postSilenceSuppressMs?: number;
|
|
358
|
+
};
|
|
359
|
+
/**
|
|
360
|
+
* Configuration for bin-level gating (CPU paths only).
|
|
361
|
+
* Ignores bins whose energy is below a relative floor.
|
|
362
|
+
*/
|
|
363
|
+
type BinGateConfig = {
|
|
364
|
+
/**
|
|
365
|
+
* Whether bin-level gating is enabled.
|
|
366
|
+
* @default true
|
|
367
|
+
*/
|
|
368
|
+
enabled?: boolean;
|
|
369
|
+
/**
|
|
370
|
+
* Relative floor as a fraction of frame energy.
|
|
371
|
+
* Bins with value < frameEnergy * binFloorRel are ignored.
|
|
372
|
+
* @default 0.05
|
|
373
|
+
*/
|
|
374
|
+
binFloorRel?: number;
|
|
375
|
+
};
|
|
376
|
+
/**
|
|
377
|
+
* Result of silence gating analysis.
|
|
378
|
+
* Useful for debugging and visualization.
|
|
379
|
+
*/
|
|
380
|
+
type SilenceGateResult = {
|
|
381
|
+
/** Per-frame energy values used for gating. */
|
|
382
|
+
frameEnergy: Float32Array;
|
|
383
|
+
/** Estimated noise floor value. */
|
|
384
|
+
noiseFloor: number;
|
|
385
|
+
/** Threshold for entering active state. */
|
|
386
|
+
enterThreshold: number;
|
|
387
|
+
/** Threshold for exiting active state. */
|
|
388
|
+
exitThreshold: number;
|
|
389
|
+
/** Per-frame activity mask (true = active). */
|
|
390
|
+
activityMask: Uint8Array;
|
|
391
|
+
/** Per-frame onset suppression mask (true = suppress onset). */
|
|
392
|
+
suppressionMask: Uint8Array;
|
|
393
|
+
};
|
|
394
|
+
/**
|
|
395
|
+
* Merge user config with defaults.
|
|
396
|
+
*/
|
|
397
|
+
declare function withSilenceGateDefaults(config?: SilenceGateConfig): Required<SilenceGateConfig>;
|
|
398
|
+
/**
|
|
399
|
+
* Merge user config with defaults for bin gating.
|
|
400
|
+
*/
|
|
401
|
+
declare function withBinGateDefaults(config?: BinGateConfig): Required<BinGateConfig>;
|
|
402
|
+
/**
|
|
403
|
+
* Compute per-frame energy from mel spectrogram.
|
|
404
|
+
*
|
|
405
|
+
* Since mel bands are already log10(eps + energy), we compute the mean
|
|
406
|
+
* of the log-energy values. This gives us a perceptually-relevant
|
|
407
|
+
* frame energy proxy in log space.
|
|
408
|
+
*
|
|
409
|
+
* @param melBands - Array of frames, each containing mel band values (log10 scale)
|
|
410
|
+
* @returns Per-frame energy values (log scale)
|
|
411
|
+
*/
|
|
412
|
+
declare function computeFrameEnergyFromMel(melBands: Float32Array[]): Float32Array;
|
|
413
|
+
/**
|
|
414
|
+
* Compute per-frame energy from linear magnitude spectrogram.
|
|
415
|
+
*
|
|
416
|
+
* Uses mean magnitude (or power) across bins as the energy proxy.
|
|
417
|
+
*
|
|
418
|
+
* @param magnitudes - Array of frames, each containing magnitude values (linear scale)
|
|
419
|
+
* @param usePower - If true, use sum of squared magnitudes (power). Default: false (RMS-like).
|
|
420
|
+
* @returns Per-frame energy values (linear scale)
|
|
421
|
+
*/
|
|
422
|
+
declare function computeFrameEnergyFromSpectrogram(magnitudes: Float32Array[], usePower?: boolean): Float32Array;
|
|
423
|
+
/**
|
|
424
|
+
* Estimate adaptive noise floor from frame energies.
|
|
425
|
+
*
|
|
426
|
+
* Uses a robust percentile-based estimation rather than absolute thresholds.
|
|
427
|
+
*
|
|
428
|
+
* @param frameEnergy - Per-frame energy values
|
|
429
|
+
* @param percentile - Percentile to use for floor estimation (0-100)
|
|
430
|
+
* @returns Estimated noise floor
|
|
431
|
+
*/
|
|
432
|
+
declare function estimateNoiseFloor(frameEnergy: Float32Array, percentile: number): number;
|
|
433
|
+
/**
|
|
434
|
+
* Build activity mask with hysteresis and hangover.
|
|
435
|
+
*
|
|
436
|
+
* State machine:
|
|
437
|
+
* - INACTIVE: energy < enterThreshold -> stay inactive
|
|
438
|
+
* - INACTIVE: energy >= enterThreshold -> enter ACTIVE
|
|
439
|
+
* - ACTIVE: energy >= exitThreshold -> stay active, reset hangover counter
|
|
440
|
+
* - ACTIVE: energy < exitThreshold -> decrement hangover counter
|
|
441
|
+
* - ACTIVE: hangover counter exhausted -> enter INACTIVE
|
|
442
|
+
*
|
|
443
|
+
* @param frameEnergy - Per-frame energy values
|
|
444
|
+
* @param enterThreshold - Threshold to enter active state
|
|
445
|
+
* @param exitThreshold - Threshold to remain in active state
|
|
446
|
+
* @param hangoverFrames - Number of frames to remain active after dropping below exit threshold
|
|
447
|
+
* @returns Activity mask (1 = active, 0 = inactive)
|
|
448
|
+
*/
|
|
449
|
+
declare function buildActivityMask(frameEnergy: Float32Array, enterThreshold: number, exitThreshold: number, hangoverFrames: number): Uint8Array;
|
|
450
|
+
/**
|
|
451
|
+
* Full silence gating analysis.
|
|
452
|
+
*
|
|
453
|
+
* Computes frame energy, noise floor, thresholds, activity mask, and suppression mask.
|
|
454
|
+
*
|
|
455
|
+
* @param frameEnergy - Per-frame energy values
|
|
456
|
+
* @param frameDurationSec - Duration of one frame in seconds
|
|
457
|
+
* @param config - Silence gate configuration
|
|
458
|
+
* @returns Complete gating result including all intermediate values
|
|
459
|
+
*/
|
|
460
|
+
declare function computeSilenceGating(frameEnergy: Float32Array, frameDurationSec: number, config?: SilenceGateConfig): SilenceGateResult;
|
|
461
|
+
|
|
44
462
|
type OnsetEnvelope = {
|
|
45
463
|
times: Float32Array;
|
|
46
464
|
values: Float32Array;
|
|
47
465
|
};
|
|
466
|
+
/**
|
|
467
|
+
* Extended onset envelope result with optional debugging info.
|
|
468
|
+
*/
|
|
469
|
+
type OnsetEnvelopeResult = OnsetEnvelope & {
|
|
470
|
+
/**
|
|
471
|
+
* Optional silence gating diagnostics.
|
|
472
|
+
* Present when silenceGate.enabled is true and returnDiagnostics is true.
|
|
473
|
+
*/
|
|
474
|
+
diagnostics?: OnsetDiagnostics;
|
|
475
|
+
};
|
|
476
|
+
/**
|
|
477
|
+
* Diagnostics for inspecting onset detection behavior.
|
|
478
|
+
*/
|
|
479
|
+
type OnsetDiagnostics = {
|
|
480
|
+
/** Per-frame energy used for gating. */
|
|
481
|
+
frameEnergy: Float32Array;
|
|
482
|
+
/** Estimated noise floor. */
|
|
483
|
+
noiseFloor: number;
|
|
484
|
+
/** Threshold for entering active state. */
|
|
485
|
+
enterThreshold: number;
|
|
486
|
+
/** Threshold for exiting active state. */
|
|
487
|
+
exitThreshold: number;
|
|
488
|
+
/** Per-frame activity mask (1 = active, 0 = inactive). */
|
|
489
|
+
activityMask: Uint8Array;
|
|
490
|
+
/** Per-frame suppression mask (1 = suppressed, 0 = allowed). */
|
|
491
|
+
suppressionMask: Uint8Array;
|
|
492
|
+
/** Raw onset novelty before gating was applied. */
|
|
493
|
+
rawNovelty: Float32Array;
|
|
494
|
+
};
|
|
48
495
|
type OnsetEnvelopeOptions = {
|
|
49
496
|
/** If true, log-compress magnitudes/energies before differencing. */
|
|
50
497
|
useLog?: boolean;
|
|
@@ -52,45 +499,1032 @@ type OnsetEnvelopeOptions = {
|
|
|
52
499
|
smoothMs?: number;
|
|
53
500
|
/** How to convert temporal differences into novelty. */
|
|
54
501
|
diffMethod?: "rectified" | "abs";
|
|
502
|
+
/**
|
|
503
|
+
* Silence-aware gating configuration.
|
|
504
|
+
* Suppresses false onsets in silence or near-silence regions.
|
|
505
|
+
* @default { enabled: true }
|
|
506
|
+
*/
|
|
507
|
+
silenceGate?: SilenceGateConfig;
|
|
508
|
+
/**
|
|
509
|
+
* Bin-level gating configuration (CPU paths only).
|
|
510
|
+
* Ignores bins with energy below a relative threshold.
|
|
511
|
+
* @default { enabled: true }
|
|
512
|
+
*/
|
|
513
|
+
binGate?: BinGateConfig;
|
|
514
|
+
/**
|
|
515
|
+
* If true, include diagnostics in the result for debugging.
|
|
516
|
+
* @default false
|
|
517
|
+
*/
|
|
518
|
+
returnDiagnostics?: boolean;
|
|
55
519
|
};
|
|
56
|
-
|
|
57
|
-
|
|
520
|
+
/**
|
|
521
|
+
* Compute onset envelope from spectrogram with silence-aware gating.
|
|
522
|
+
*
|
|
523
|
+
* The pipeline:
|
|
524
|
+
* 1. Compute per-frame spectral flux (novelty)
|
|
525
|
+
* 2. Compute per-frame energy from magnitudes
|
|
526
|
+
* 3. Build activity mask using adaptive noise floor + hysteresis
|
|
527
|
+
* 4. Apply silence gating and post-silence suppression
|
|
528
|
+
* 5. Apply optional smoothing
|
|
529
|
+
*/
|
|
530
|
+
declare function onsetEnvelopeFromSpectrogram(spec: Spectrogram, options?: OnsetEnvelopeOptions): OnsetEnvelopeResult;
|
|
531
|
+
/**
|
|
532
|
+
* Compute onset envelope from mel spectrogram with silence-aware gating.
|
|
533
|
+
*
|
|
534
|
+
* The pipeline:
|
|
535
|
+
* 1. Compute per-frame mel flux (novelty)
|
|
536
|
+
* 2. Compute per-frame energy from mel bands (already log scale)
|
|
537
|
+
* 3. Build activity mask using adaptive noise floor + hysteresis
|
|
538
|
+
* 4. Apply silence gating and post-silence suppression
|
|
539
|
+
* 5. Apply optional smoothing
|
|
540
|
+
*/
|
|
541
|
+
declare function onsetEnvelopeFromMel(mel: MelSpectrogram, options?: OnsetEnvelopeOptions): OnsetEnvelopeResult;
|
|
58
542
|
type OnsetEnvelopeGpuResult = {
|
|
59
543
|
times: Float32Array;
|
|
60
544
|
values: Float32Array;
|
|
61
545
|
gpuTimings: {
|
|
62
546
|
gpuSubmitToReadbackMs: number;
|
|
63
547
|
};
|
|
548
|
+
/** Optional silence gating diagnostics. */
|
|
549
|
+
diagnostics?: OnsetDiagnostics;
|
|
550
|
+
};
|
|
551
|
+
/**
|
|
552
|
+
* GPU-accelerated onset envelope from mel spectrogram with silence-aware gating.
|
|
553
|
+
*
|
|
554
|
+
* Notes:
|
|
555
|
+
* - GPU kernel handles diff+reduction only (keeps WGSL simple)
|
|
556
|
+
* - Silence gating is applied on CPU after GPU readback
|
|
557
|
+
* - CPU and GPU paths produce comparable results
|
|
558
|
+
* - Callers should fall back to CPU on errors
|
|
559
|
+
*/
|
|
560
|
+
declare function onsetEnvelopeFromMelGpu(mel: MelSpectrogram, gpu: MirGPU, options?: Pick<OnsetEnvelopeOptions, "diffMethod" | "silenceGate" | "returnDiagnostics" | "smoothMs">): Promise<OnsetEnvelopeGpuResult>;
|
|
561
|
+
|
|
562
|
+
type PeakPickEvent = {
|
|
563
|
+
time: number;
|
|
564
|
+
strength: number;
|
|
565
|
+
index: number;
|
|
566
|
+
};
|
|
567
|
+
type PeakPickOptions = {
|
|
568
|
+
/** Minimum peak height (absolute). */
|
|
569
|
+
threshold?: number;
|
|
570
|
+
/** Minimum inter-peak interval (seconds). */
|
|
571
|
+
minIntervalSec?: number;
|
|
572
|
+
/** If provided, use adaptive threshold: mean(values) + factor*std(values). */
|
|
573
|
+
adaptive?: {
|
|
574
|
+
method?: "meanStd" | "median";
|
|
575
|
+
factor?: number;
|
|
576
|
+
};
|
|
577
|
+
/** If true, prefer strict maxima (> neighbors); else allow flat plateaus. */
|
|
578
|
+
strict?: boolean;
|
|
579
|
+
};
|
|
580
|
+
declare function peakPick(times: Float32Array, values: Float32Array, options?: PeakPickOptions): PeakPickEvent[];
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Configuration for beat candidate detection.
|
|
584
|
+
*/
|
|
585
|
+
type BeatCandidatesOptions = {
|
|
586
|
+
/** Minimum inter-candidate interval in seconds. Default: 0.1 (100ms). */
|
|
587
|
+
minIntervalSec?: number;
|
|
588
|
+
/** Threshold factor for adaptive peak detection. Lower = more candidates. Default: 0.5. */
|
|
589
|
+
thresholdFactor?: number;
|
|
590
|
+
/** Smoothing window for salience signal in ms. Default: 50. */
|
|
591
|
+
smoothMs?: number;
|
|
592
|
+
};
|
|
593
|
+
/**
|
|
594
|
+
* Result of beat candidate detection.
|
|
595
|
+
*/
|
|
596
|
+
type BeatCandidatesOutput = {
|
|
597
|
+
candidates: BeatCandidate[];
|
|
598
|
+
/** The computed salience signal (for debugging/visualization). */
|
|
599
|
+
salience: {
|
|
600
|
+
times: Float32Array;
|
|
601
|
+
values: Float32Array;
|
|
602
|
+
};
|
|
603
|
+
};
|
|
604
|
+
/**
|
|
605
|
+
* Compute a beat-oriented salience signal from mel spectrogram.
|
|
606
|
+
*
|
|
607
|
+
* This combines:
|
|
608
|
+
* - Onset envelope (captures transients/attacks)
|
|
609
|
+
* - Spectral flux from the underlying spectrogram (captures spectral change)
|
|
610
|
+
*
|
|
611
|
+
* The signals are normalized and combined to produce a single salience curve
|
|
612
|
+
* suitable for peak picking.
|
|
613
|
+
*
|
|
614
|
+
* Key design choices:
|
|
615
|
+
* - Whole-track normalization (z-score) for consistent behavior
|
|
616
|
+
* - Gentle smoothing to suppress micro-transients while preserving beat structure
|
|
617
|
+
* - No BPM inference or grid assumptions
|
|
618
|
+
*/
|
|
619
|
+
type BeatSalienceSignal = {
|
|
620
|
+
times: Float32Array;
|
|
621
|
+
values: Float32Array;
|
|
622
|
+
};
|
|
623
|
+
/**
|
|
624
|
+
* Compute beat salience signal from mel spectrogram.
|
|
625
|
+
*
|
|
626
|
+
* This is an intermediate signal suitable for peak picking to extract
|
|
627
|
+
* beat candidates. It combines onset envelope with additional smoothing
|
|
628
|
+
* tuned for beat-like (rather than onset-like) detection.
|
|
629
|
+
*/
|
|
630
|
+
declare function beatSalienceFromMel(mel: MelSpectrogram, spec: Spectrogram, options?: {
|
|
631
|
+
smoothMs?: number;
|
|
632
|
+
}): BeatSalienceSignal;
|
|
633
|
+
/**
|
|
634
|
+
* Detect beat candidates from mel spectrogram and spectrogram.
|
|
635
|
+
*
|
|
636
|
+
* This is the main entry point for beat candidate detection.
|
|
637
|
+
*
|
|
638
|
+
* Design principles:
|
|
639
|
+
* - Dense candidates (err on side of too many)
|
|
640
|
+
* - No BPM inference
|
|
641
|
+
* - No grid assumptions
|
|
642
|
+
* - Whole-track normalization for consistency
|
|
643
|
+
* - Deterministic (same input -> same output)
|
|
644
|
+
*/
|
|
645
|
+
declare function detectBeatCandidates(mel: MelSpectrogram, spec: Spectrogram, options?: BeatCandidatesOptions): BeatCandidatesOutput;
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Configuration for tempo hypothesis generation.
|
|
649
|
+
*/
|
|
650
|
+
type TempoHypothesesOptions = {
|
|
651
|
+
/** Minimum BPM to consider. Default: 24. */
|
|
652
|
+
minBpm?: number;
|
|
653
|
+
/** Maximum BPM to consider. Default: 300. */
|
|
654
|
+
maxBpm?: number;
|
|
655
|
+
/** Histogram bin size in BPM. Default: 1.0. */
|
|
656
|
+
binSizeBpm?: number;
|
|
657
|
+
/** Maximum hypotheses to return. Default: 10. */
|
|
658
|
+
maxHypotheses?: number;
|
|
659
|
+
/** Minimum confidence threshold (0-1). Default: 0.05. */
|
|
660
|
+
minConfidence?: number;
|
|
661
|
+
/** Weight IOIs by candidate strength. Default: true. */
|
|
662
|
+
weightByStrength?: boolean;
|
|
663
|
+
/** Include histogram data in output. Default: false. */
|
|
664
|
+
includeHistogram?: boolean;
|
|
665
|
+
};
|
|
666
|
+
type TempoHypothesesOutput = {
|
|
667
|
+
hypotheses: TempoHypothesis[];
|
|
668
|
+
inputCandidateCount: number;
|
|
669
|
+
histogram?: {
|
|
670
|
+
bpmBins: Float32Array;
|
|
671
|
+
counts: Float32Array;
|
|
672
|
+
};
|
|
64
673
|
};
|
|
65
674
|
/**
|
|
66
|
-
*
|
|
675
|
+
* Generate tempo hypotheses from beat candidates.
|
|
676
|
+
*
|
|
677
|
+
* Algorithm:
|
|
678
|
+
* 1. Compute inter-onset intervals (IOIs) from beat candidates
|
|
679
|
+
* 2. Filter IOIs to musically plausible range (0.2s-2.5s -> 24-300 BPM)
|
|
680
|
+
* 3. Build weighted histogram with configurable bin size
|
|
681
|
+
* 4. Extract peaks as tempo candidates
|
|
682
|
+
* 5. Refine BPM estimates using weighted centroid
|
|
683
|
+
* 6. Group into harmonic families
|
|
684
|
+
* 7. Normalize confidence scores
|
|
685
|
+
*
|
|
686
|
+
* @param candidates - Beat candidates from B1
|
|
687
|
+
* @param options - Configuration options
|
|
688
|
+
* @returns Tempo hypotheses with confidence and family groupings
|
|
689
|
+
*/
|
|
690
|
+
declare function generateTempoHypotheses(candidates: BeatCandidate[], options?: TempoHypothesesOptions): TempoHypothesesOutput;
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* Phase alignment algorithm for beat grid generation.
|
|
694
|
+
*
|
|
695
|
+
* Given a BPM and beat candidates, this module computes optimal phase offsets
|
|
696
|
+
* that align the beat grid with detected beat candidates.
|
|
697
|
+
*
|
|
698
|
+
* The algorithm is deterministic: same inputs always produce same outputs.
|
|
699
|
+
*/
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* Compute phase hypotheses for a given BPM against beat candidates.
|
|
703
|
+
*
|
|
704
|
+
* Algorithm:
|
|
705
|
+
* 1. Compute beat period = 60 / bpm
|
|
706
|
+
* 2. Generate N phase offsets spanning [0, period) at resolution = period/N
|
|
707
|
+
* 3. For each phase offset:
|
|
708
|
+
* a. For each beat candidate, find closest grid line
|
|
709
|
+
* b. If within tolerance, add weighted score based on candidate strength
|
|
710
|
+
* c. Track systematic offset error for penalty
|
|
711
|
+
* 4. Normalize scores and apply offset penalty
|
|
712
|
+
* 5. Return top K phases sorted by score
|
|
713
|
+
*
|
|
714
|
+
* @param bpm - Tempo in beats per minute
|
|
715
|
+
* @param candidates - Beat candidate events with time and strength
|
|
716
|
+
* @param audioDuration - Total audio duration in seconds
|
|
717
|
+
* @param config - Optional configuration overrides
|
|
718
|
+
* @returns Array of top K phase hypotheses, sorted by score descending
|
|
719
|
+
*/
|
|
720
|
+
declare function computePhaseHypotheses(bpm: number, candidates: BeatCandidate[], audioDuration: number, config?: PhaseAlignmentConfig): PhaseHypothesis[];
|
|
721
|
+
/**
|
|
722
|
+
* Generate beat times for a given grid within the audio duration.
|
|
723
|
+
*
|
|
724
|
+
* @param bpm - Tempo in beats per minute
|
|
725
|
+
* @param phaseOffset - Base phase offset in seconds
|
|
726
|
+
* @param userNudge - User adjustment in seconds (additive)
|
|
727
|
+
* @param audioDuration - Total audio duration in seconds
|
|
728
|
+
* @returns Array of beat times in seconds
|
|
729
|
+
*/
|
|
730
|
+
declare function generateBeatTimes(bpm: number, phaseOffset: number, userNudge: number, audioDuration: number): number[];
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Peak Picking Algorithm
|
|
734
|
+
*
|
|
735
|
+
* Detects local maxima in a 1D signal that exceed a threshold.
|
|
736
|
+
* Used to create event streams from continuous signals.
|
|
737
|
+
*/
|
|
738
|
+
interface PeakPickingParams {
|
|
739
|
+
/** Minimum normalized value (0-1) for a peak to be considered. Default: 0.3 */
|
|
740
|
+
threshold: number;
|
|
741
|
+
/** Minimum time between peaks in seconds. Default: 0.1 */
|
|
742
|
+
minDistance: number;
|
|
743
|
+
/** Number of samples to look back for local max comparison. Default: 2 */
|
|
744
|
+
preMax?: number;
|
|
745
|
+
/** Number of samples to look forward for local max comparison. Default: 2 */
|
|
746
|
+
postMax?: number;
|
|
747
|
+
}
|
|
748
|
+
interface PeakPickingResult {
|
|
749
|
+
/** Times of detected peaks (seconds) */
|
|
750
|
+
times: Float32Array;
|
|
751
|
+
/** Normalized strength of each peak (0-1, based on normalized value) */
|
|
752
|
+
strengths: Float32Array;
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Default peak picking parameters
|
|
756
|
+
*/
|
|
757
|
+
declare const DEFAULT_PEAK_PICKING_PARAMS: Required<PeakPickingParams>;
|
|
758
|
+
/**
|
|
759
|
+
* Pick peaks from a continuous signal.
|
|
760
|
+
*
|
|
761
|
+
* @param times - Time values in seconds (Float32Array)
|
|
762
|
+
* @param values - Signal values (Float32Array)
|
|
763
|
+
* @param params - Peak picking parameters
|
|
764
|
+
* @returns Detected peaks with times and strengths
|
|
765
|
+
*/
|
|
766
|
+
declare function pickPeaks(times: Float32Array, values: Float32Array, params?: Partial<PeakPickingParams>): PeakPickingResult;
|
|
767
|
+
/**
|
|
768
|
+
* Result from adaptive peak picking, including the threshold curve for visualization.
|
|
769
|
+
*/
|
|
770
|
+
interface AdaptivePeakPickingResult extends PeakPickingResult {
|
|
771
|
+
/** The adaptive threshold curve (normalized 0-1) for visualization */
|
|
772
|
+
thresholdCurve: Float32Array;
|
|
773
|
+
/** Time values corresponding to threshold curve samples */
|
|
774
|
+
thresholdTimes: Float32Array;
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* Compute the adaptive threshold curve for visualization.
|
|
778
|
+
* This is the normalized threshold that would be used by pickPeaksAdaptive.
|
|
779
|
+
*
|
|
780
|
+
* @param values - Signal values (Float32Array)
|
|
781
|
+
* @param windowSize - Window size for local statistics (in samples)
|
|
782
|
+
* @param thresholdMultiplier - Multiplier for local std (default 1.5)
|
|
783
|
+
* @returns Normalized threshold curve (0-1 range)
|
|
784
|
+
*/
|
|
785
|
+
declare function computeAdaptiveThreshold(values: Float32Array, windowSize?: number, thresholdMultiplier?: number): Float32Array;
|
|
786
|
+
/**
|
|
787
|
+
* Pick peaks with adaptive threshold based on local statistics.
|
|
788
|
+
*
|
|
789
|
+
* @param times - Time values in seconds
|
|
790
|
+
* @param values - Signal values
|
|
791
|
+
* @param windowSize - Window size for local statistics (in samples)
|
|
792
|
+
* @param params - Base peak picking parameters (threshold used as multiplier of local std)
|
|
793
|
+
* @param includeThresholdCurve - If true, returns the threshold curve for visualization
|
|
794
|
+
*/
|
|
795
|
+
declare function pickPeaksAdaptive(times: Float32Array, values: Float32Array, windowSize?: number, params?: Partial<PeakPickingParams>, includeThresholdCurve?: boolean): PeakPickingResult | AdaptivePeakPickingResult;
|
|
796
|
+
/**
|
|
797
|
+
* Hysteresis gate parameters for peak filtering.
|
|
798
|
+
*/
|
|
799
|
+
interface HysteresisGateParams {
|
|
800
|
+
/** Upper threshold (0-1) - signal must exceed this to trigger "on" state */
|
|
801
|
+
onThreshold: number;
|
|
802
|
+
/** Lower threshold (0-1) - signal must fall below this to trigger "off" state */
|
|
803
|
+
offThreshold: number;
|
|
804
|
+
/** Minimum time between peaks in seconds */
|
|
805
|
+
minDistance: number;
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* Apply hysteresis gating to peaks.
|
|
809
|
+
* Peaks are only kept if the signal has dropped below offThreshold since the last peak.
|
|
810
|
+
* This prevents multiple triggers during sustained high-value regions.
|
|
811
|
+
*
|
|
812
|
+
* @param times - Time values of the original signal
|
|
813
|
+
* @param values - Values of the original signal (for checking hysteresis)
|
|
814
|
+
* @param peakTimes - Times of detected peaks
|
|
815
|
+
* @param peakStrengths - Strengths of detected peaks
|
|
816
|
+
* @param params - Hysteresis gate parameters
|
|
817
|
+
* @returns Filtered peaks after hysteresis gating
|
|
818
|
+
*/
|
|
819
|
+
declare function applyHysteresisGate(times: Float32Array, values: Float32Array, peakTimes: Float32Array, peakStrengths: Float32Array, params: HysteresisGateParams): PeakPickingResult;
|
|
820
|
+
|
|
821
|
+
/**
|
|
822
|
+
* Musical Time utilities for B4.
|
|
823
|
+
*
|
|
824
|
+
* These functions compute derived values from musical time structures.
|
|
825
|
+
* All computations are deterministic and pure.
|
|
826
|
+
*/
|
|
827
|
+
|
|
828
|
+
/**
|
|
829
|
+
* Find the segment containing a given time.
|
|
830
|
+
* Segments are non-overlapping, so at most one segment contains any time.
|
|
831
|
+
*
|
|
832
|
+
* @param time - Time in seconds from track start
|
|
833
|
+
* @param segments - Ordered list of segments (by startTime ascending)
|
|
834
|
+
* @returns The containing segment, or null if time is outside all segments
|
|
835
|
+
*/
|
|
836
|
+
declare function findSegmentAtTime(time: number, segments: MusicalTimeSegment[]): MusicalTimeSegment | null;
|
|
837
|
+
/**
|
|
838
|
+
* Compute the beat position at a given time.
|
|
839
|
+
*
|
|
840
|
+
* Beat position formula:
|
|
841
|
+
* period = 60 / bpm
|
|
842
|
+
* beatsFromStart = (time - phaseOffset) / period
|
|
843
|
+
* beatIndex = floor(beatsFromStart)
|
|
844
|
+
* beatPhase = beatsFromStart - beatIndex (fractional part, 0-1)
|
|
845
|
+
* beatPosition = beatsFromStart (continuous)
|
|
846
|
+
*
|
|
847
|
+
* @param time - Time in seconds from track start
|
|
848
|
+
* @param segments - Ordered list of segments (by startTime ascending)
|
|
849
|
+
* @returns BeatPosition if time is within a segment, null otherwise
|
|
850
|
+
*/
|
|
851
|
+
declare function computeBeatPosition(time: number, segments: MusicalTimeSegment[]): BeatPosition | null;
|
|
852
|
+
/**
|
|
853
|
+
* Compute beat position from a MusicalTimeStructure.
|
|
854
|
+
* Convenience wrapper for computeBeatPosition.
|
|
855
|
+
*/
|
|
856
|
+
declare function computeBeatPositionFromStructure(time: number, structure: MusicalTimeStructure | null): BeatPosition | null;
|
|
857
|
+
/**
|
|
858
|
+
* Generate a unique segment ID.
|
|
859
|
+
*/
|
|
860
|
+
declare function generateSegmentId(): string;
|
|
861
|
+
/**
|
|
862
|
+
* Create a new MusicalTimeSegment from a BeatGrid.
|
|
863
|
+
*
|
|
864
|
+
* @param grid - The beat grid to promote
|
|
865
|
+
* @param startTime - Segment start boundary in seconds
|
|
866
|
+
* @param endTime - Segment end boundary in seconds
|
|
867
|
+
* @returns A new MusicalTimeSegment
|
|
868
|
+
*/
|
|
869
|
+
declare function createSegmentFromGrid(grid: BeatGrid, startTime: number, endTime: number): MusicalTimeSegment;
|
|
870
|
+
/**
|
|
871
|
+
* Create a new empty MusicalTimeStructure.
|
|
872
|
+
*/
|
|
873
|
+
declare function createMusicalTimeStructure(): MusicalTimeStructure;
|
|
874
|
+
/**
|
|
875
|
+
* Validate that segments are non-overlapping and ordered.
|
|
876
|
+
*
|
|
877
|
+
* @param segments - List of segments to validate
|
|
878
|
+
* @returns Array of validation errors (empty if valid)
|
|
879
|
+
*/
|
|
880
|
+
declare function validateSegments(segments: MusicalTimeSegment[]): string[];
|
|
881
|
+
/**
|
|
882
|
+
* Sort segments by startTime ascending.
|
|
883
|
+
* Returns a new array (does not mutate input).
|
|
884
|
+
*/
|
|
885
|
+
declare function sortSegments(segments: MusicalTimeSegment[]): MusicalTimeSegment[];
|
|
886
|
+
/**
|
|
887
|
+
* Split a segment at a given time.
|
|
888
|
+
*
|
|
889
|
+
* @param segment - The segment to split
|
|
890
|
+
* @param splitTime - Time in seconds where to split
|
|
891
|
+
* @returns Tuple of [beforeSegment, afterSegment]
|
|
892
|
+
* @throws If splitTime is outside segment bounds
|
|
893
|
+
*/
|
|
894
|
+
declare function splitSegment(segment: MusicalTimeSegment, splitTime: number): [MusicalTimeSegment, MusicalTimeSegment];
|
|
895
|
+
/**
|
|
896
|
+
* Generate beat times within a segment.
|
|
897
|
+
* Used for rendering beat markers.
|
|
898
|
+
*
|
|
899
|
+
* @param segment - The segment to generate beats for
|
|
900
|
+
* @returns Array of beat times in seconds
|
|
901
|
+
*/
|
|
902
|
+
declare function generateSegmentBeatTimes(segment: MusicalTimeSegment): number[];
|
|
903
|
+
|
|
904
|
+
/**
|
|
905
|
+
* Frequency Band utilities for F1.
|
|
906
|
+
*
|
|
907
|
+
* These functions provide validation, creation, and query operations
|
|
908
|
+
* for frequency band structures. All computations are deterministic and pure.
|
|
909
|
+
*/
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* Generate a unique band ID.
|
|
913
|
+
*/
|
|
914
|
+
declare function generateBandId(): string;
|
|
915
|
+
/**
|
|
916
|
+
* Validate frequency segments for a band.
|
|
917
|
+
*
|
|
918
|
+
* Checks:
|
|
919
|
+
* - lowHz < highHz at all segment boundaries
|
|
920
|
+
* - All frequency values are non-negative
|
|
921
|
+
* - startTime < endTime for each segment
|
|
922
|
+
* - Segments don't overlap in time
|
|
923
|
+
* - Segments are ordered by startTime
|
|
924
|
+
*
|
|
925
|
+
* @param segments - Frequency segments to validate
|
|
926
|
+
* @returns Array of validation errors (empty if valid)
|
|
927
|
+
*/
|
|
928
|
+
declare function validateFrequencySegments(segments: FrequencySegment[]): string[];
|
|
929
|
+
/**
|
|
930
|
+
* Validate a frequency band.
|
|
931
|
+
*
|
|
932
|
+
* @param band - Frequency band to validate
|
|
933
|
+
* @returns Array of validation errors (empty if valid)
|
|
934
|
+
*/
|
|
935
|
+
declare function validateFrequencyBand(band: FrequencyBand): string[];
|
|
936
|
+
/**
|
|
937
|
+
* Validate a complete frequency band structure.
|
|
938
|
+
*
|
|
939
|
+
* @param structure - Structure to validate
|
|
940
|
+
* @returns Array of validation errors (empty if valid)
|
|
941
|
+
*/
|
|
942
|
+
declare function validateBandStructure(structure: FrequencyBandStructure): string[];
|
|
943
|
+
/**
|
|
944
|
+
* Create an empty FrequencyBandStructure.
|
|
945
|
+
*/
|
|
946
|
+
declare function createBandStructure(): FrequencyBandStructure;
|
|
947
|
+
/**
|
|
948
|
+
* Create a simple constant-frequency band (no time variation).
|
|
949
|
+
*
|
|
950
|
+
* @param label - Human-readable band label
|
|
951
|
+
* @param lowHz - Lower frequency bound in Hz
|
|
952
|
+
* @param highHz - Upper frequency bound in Hz
|
|
953
|
+
* @param duration - Duration in seconds (defines segment end time)
|
|
954
|
+
* @param options - Optional configuration
|
|
955
|
+
* @returns A new FrequencyBand
|
|
956
|
+
*/
|
|
957
|
+
declare function createConstantBand(label: string, lowHz: number, highHz: number, duration: number, options?: {
|
|
958
|
+
enabled?: boolean;
|
|
959
|
+
sortOrder?: number;
|
|
960
|
+
id?: string;
|
|
961
|
+
/** The audio source this band belongs to. Defaults to "mixdown". */
|
|
962
|
+
sourceId?: string;
|
|
963
|
+
}): FrequencyBand;
|
|
964
|
+
/**
|
|
965
|
+
* Create a sectioned band (applies only to a time range).
|
|
966
|
+
*
|
|
967
|
+
* @param label - Human-readable band label
|
|
968
|
+
* @param lowHz - Lower frequency bound in Hz
|
|
969
|
+
* @param highHz - Upper frequency bound in Hz
|
|
970
|
+
* @param startTime - Section start time in seconds
|
|
971
|
+
* @param endTime - Section end time in seconds
|
|
972
|
+
* @param options - Optional configuration
|
|
973
|
+
* @returns A new FrequencyBand
|
|
974
|
+
*/
|
|
975
|
+
declare function createSectionedBand(label: string, lowHz: number, highHz: number, startTime: number, endTime: number, options?: {
|
|
976
|
+
enabled?: boolean;
|
|
977
|
+
sortOrder?: number;
|
|
978
|
+
id?: string;
|
|
979
|
+
/** The audio source this band belongs to. Defaults to "mixdown". */
|
|
980
|
+
sourceId?: string;
|
|
981
|
+
}): FrequencyBand;
|
|
982
|
+
/**
|
|
983
|
+
* Create standard frequency bands for a track.
|
|
984
|
+
*
|
|
985
|
+
* Creates a standard 6-band frequency split:
|
|
986
|
+
* - Sub Bass: 20-60 Hz
|
|
987
|
+
* - Bass: 60-250 Hz
|
|
988
|
+
* - Low Mids: 250-500 Hz
|
|
989
|
+
* - Mids: 500-2000 Hz
|
|
990
|
+
* - High Mids: 2000-4000 Hz
|
|
991
|
+
* - Highs: 4000-20000 Hz
|
|
992
|
+
*
|
|
993
|
+
* @param duration - Track duration in seconds
|
|
994
|
+
* @param sourceId - The audio source these bands belong to. Defaults to "mixdown".
|
|
995
|
+
* @returns Array of FrequencyBand objects
|
|
996
|
+
*/
|
|
997
|
+
declare function createStandardBands(duration: number, sourceId?: string): FrequencyBand[];
|
|
998
|
+
/**
|
|
999
|
+
* Get all bands active at a given time.
|
|
1000
|
+
*
|
|
1001
|
+
* A band is active if:
|
|
1002
|
+
* - It is enabled
|
|
1003
|
+
* - The time falls within its time scope
|
|
1004
|
+
*
|
|
1005
|
+
* @param structure - Frequency band structure (can be null)
|
|
1006
|
+
* @param time - Time in seconds
|
|
1007
|
+
* @param sourceId - Optional: filter to a specific audio source
|
|
1008
|
+
* @returns Array of active bands
|
|
1009
|
+
*/
|
|
1010
|
+
declare function bandsActiveAt(structure: FrequencyBandStructure | null, time: number, sourceId?: string): FrequencyBand[];
|
|
1011
|
+
/**
|
|
1012
|
+
* Get frequency bounds for a band at a given time.
|
|
1013
|
+
*
|
|
1014
|
+
* Uses linear interpolation within segments.
|
|
1015
|
+
*
|
|
1016
|
+
* @param band - The frequency band to query
|
|
1017
|
+
* @param time - Time in seconds
|
|
1018
|
+
* @returns Frequency bounds if band is active and has defined bounds, null otherwise
|
|
1019
|
+
*/
|
|
1020
|
+
declare function frequencyBoundsAt(band: FrequencyBand, time: number): FrequencyBoundsAtTime | null;
|
|
1021
|
+
/**
|
|
1022
|
+
* Get all frequency bounds at a given time.
|
|
1023
|
+
*
|
|
1024
|
+
* Returns bounds for all active bands that have defined frequency at the given time.
|
|
1025
|
+
*
|
|
1026
|
+
* @param structure - Frequency band structure (can be null)
|
|
1027
|
+
* @param time - Time in seconds
|
|
1028
|
+
* @returns Array of frequency bounds, sorted by sortOrder
|
|
1029
|
+
*/
|
|
1030
|
+
declare function allFrequencyBoundsAt(structure: FrequencyBandStructure | null, time: number): FrequencyBoundsAtTime[];
|
|
1031
|
+
/**
|
|
1032
|
+
* Find a band by its ID.
|
|
1033
|
+
*
|
|
1034
|
+
* @param structure - Frequency band structure (can be null)
|
|
1035
|
+
* @param id - Band ID to find
|
|
1036
|
+
* @returns The band if found, null otherwise
|
|
1037
|
+
*/
|
|
1038
|
+
declare function findBandById(structure: FrequencyBandStructure | null, id: string): FrequencyBand | null;
|
|
1039
|
+
/**
|
|
1040
|
+
* Sort bands by sortOrder.
|
|
1041
|
+
* Returns a new array (does not mutate input).
|
|
1042
|
+
*
|
|
1043
|
+
* @param bands - Bands to sort
|
|
1044
|
+
* @returns New array sorted by sortOrder ascending
|
|
1045
|
+
*/
|
|
1046
|
+
declare function sortBands(bands: FrequencyBand[]): FrequencyBand[];
|
|
1047
|
+
/**
|
|
1048
|
+
* Sort frequency segments by startTime.
|
|
1049
|
+
* Returns a new array (does not mutate input).
|
|
1050
|
+
*
|
|
1051
|
+
* @param segments - Segments to sort
|
|
1052
|
+
* @returns New array sorted by startTime ascending
|
|
1053
|
+
*/
|
|
1054
|
+
declare function sortFrequencySegments(segments: FrequencySegment[]): FrequencySegment[];
|
|
1055
|
+
/**
|
|
1056
|
+
* Update the modifiedAt timestamp of a structure.
|
|
1057
|
+
* Returns a new structure (does not mutate input).
|
|
1058
|
+
*
|
|
1059
|
+
* @param structure - Structure to update
|
|
1060
|
+
* @returns New structure with updated modifiedAt
|
|
1061
|
+
*/
|
|
1062
|
+
declare function touchStructure(structure: FrequencyBandStructure): FrequencyBandStructure;
|
|
1063
|
+
/**
|
|
1064
|
+
* Add a band to a structure.
|
|
1065
|
+
* Returns a new structure (does not mutate input).
|
|
1066
|
+
*
|
|
1067
|
+
* @param structure - Structure to add to
|
|
1068
|
+
* @param band - Band to add
|
|
1069
|
+
* @returns New structure with the band added
|
|
1070
|
+
*/
|
|
1071
|
+
declare function addBandToStructure(structure: FrequencyBandStructure, band: FrequencyBand): FrequencyBandStructure;
|
|
1072
|
+
/**
|
|
1073
|
+
* Remove a band from a structure by ID.
|
|
1074
|
+
* Returns a new structure (does not mutate input).
|
|
1075
|
+
*
|
|
1076
|
+
* @param structure - Structure to remove from
|
|
1077
|
+
* @param bandId - ID of band to remove
|
|
1078
|
+
* @returns New structure with the band removed
|
|
1079
|
+
*/
|
|
1080
|
+
declare function removeBandFromStructure(structure: FrequencyBandStructure, bandId: string): FrequencyBandStructure;
|
|
1081
|
+
/**
|
|
1082
|
+
* Update a band in a structure.
|
|
1083
|
+
* Returns a new structure (does not mutate input).
|
|
1084
|
+
*
|
|
1085
|
+
* @param structure - Structure containing the band
|
|
1086
|
+
* @param bandId - ID of band to update
|
|
1087
|
+
* @param updates - Partial band updates to apply
|
|
1088
|
+
* @returns New structure with the band updated
|
|
1089
|
+
*/
|
|
1090
|
+
declare function updateBandInStructure(structure: FrequencyBandStructure, bandId: string, updates: Partial<Omit<FrequencyBand, "id">>): FrequencyBandStructure;
|
|
1091
|
+
/**
|
|
1092
|
+
* Extract keyframes from a band's frequency shape.
|
|
1093
|
+
*
|
|
1094
|
+
* Keyframes are a UI abstraction over the segment model.
|
|
1095
|
+
* Each segment has a start keyframe and an end keyframe.
|
|
1096
|
+
* Adjacent segments share keyframes at their boundaries.
|
|
1097
|
+
*
|
|
1098
|
+
* @param band - The frequency band to extract keyframes from
|
|
1099
|
+
* @returns Array of keyframes sorted by time
|
|
1100
|
+
*/
|
|
1101
|
+
declare function keyframesFromBand(band: FrequencyBand): FrequencyKeyframe[];
|
|
1102
|
+
/**
|
|
1103
|
+
* Convert keyframes back to frequency segments.
|
|
1104
|
+
*
|
|
1105
|
+
* Consecutive keyframes become segment boundaries.
|
|
1106
|
+
* This is the inverse of keyframesFromBand.
|
|
1107
|
+
*
|
|
1108
|
+
* @param keyframes - Array of keyframes (must be sorted by time)
|
|
1109
|
+
* @returns Array of frequency segments
|
|
1110
|
+
*/
|
|
1111
|
+
declare function segmentsFromKeyframes(keyframes: FrequencyKeyframe[]): FrequencySegment[];
|
|
1112
|
+
/**
|
|
1113
|
+
* Split a band's segment at a given time, creating a new keyframe.
|
|
1114
|
+
*
|
|
1115
|
+
* The frequency values at the split point are interpolated from the
|
|
1116
|
+
* existing segment. Returns a new band with updated frequencyShape.
|
|
1117
|
+
*
|
|
1118
|
+
* @param band - The band to split
|
|
1119
|
+
* @param time - Time in seconds to split at
|
|
1120
|
+
* @returns New band with the split segment, or original band if time is invalid
|
|
1121
|
+
*/
|
|
1122
|
+
declare function splitBandSegmentAt(band: FrequencyBand, time: number): FrequencyBand;
|
|
1123
|
+
/**
|
|
1124
|
+
* Merge adjacent segments where frequencies match at the boundary.
|
|
1125
|
+
*
|
|
1126
|
+
* This is useful after deleting a keyframe to clean up redundant segments.
|
|
1127
|
+
*
|
|
1128
|
+
* @param band - The band to merge segments in
|
|
1129
|
+
* @param tolerance - Frequency tolerance for considering values equal (default 0.1 Hz)
|
|
1130
|
+
* @returns New band with merged segments
|
|
1131
|
+
*/
|
|
1132
|
+
declare function mergeAdjacentSegments(band: FrequencyBand, tolerance?: number): FrequencyBand;
|
|
1133
|
+
/**
|
|
1134
|
+
* Remove a keyframe from a band.
|
|
1135
|
+
*
|
|
1136
|
+
* This merges the two adjacent segments into one.
|
|
1137
|
+
* Cannot remove first or last keyframe (would make band invalid).
|
|
1138
|
+
*
|
|
1139
|
+
* @param band - The band to modify
|
|
1140
|
+
* @param time - Time of the keyframe to remove
|
|
1141
|
+
* @returns New band with keyframe removed, or original if removal is invalid
|
|
1142
|
+
*/
|
|
1143
|
+
declare function removeKeyframe(band: FrequencyBand, time: number): FrequencyBand;
|
|
1144
|
+
/**
|
|
1145
|
+
* Update a keyframe's frequency values.
|
|
1146
|
+
*
|
|
1147
|
+
* This updates the corresponding segment boundary.
|
|
1148
|
+
*
|
|
1149
|
+
* @param band - The band to modify
|
|
1150
|
+
* @param time - Time of the keyframe to update
|
|
1151
|
+
* @param lowHz - New lower frequency (or undefined to keep current)
|
|
1152
|
+
* @param highHz - New upper frequency (or undefined to keep current)
|
|
1153
|
+
* @returns New band with updated keyframe
|
|
1154
|
+
*/
|
|
1155
|
+
declare function updateKeyframe(band: FrequencyBand, time: number, lowHz?: number, highHz?: number): FrequencyBand;
|
|
1156
|
+
/**
|
|
1157
|
+
* Move a keyframe in time.
|
|
1158
|
+
*
|
|
1159
|
+
* Updates the endTime of the segment before and startTime of the segment after.
|
|
1160
|
+
* Cannot move first or last keyframe.
|
|
1161
|
+
*
|
|
1162
|
+
* @param band - The band to modify
|
|
1163
|
+
* @param oldTime - Current time of the keyframe
|
|
1164
|
+
* @param newTime - New time for the keyframe
|
|
1165
|
+
* @returns New band with moved keyframe, or original if move is invalid
|
|
1166
|
+
*/
|
|
1167
|
+
declare function moveKeyframeTime(band: FrequencyBand, oldTime: number, newTime: number): FrequencyBand;
|
|
1168
|
+
|
|
1169
|
+
/**
|
|
1170
|
+
* Band Masking utilities for F3.
|
|
1171
|
+
*
|
|
1172
|
+
* These functions apply frequency band boundaries as spectral masks
|
|
1173
|
+
* to an existing spectrogram, enabling per-band MIR analysis.
|
|
1174
|
+
*/
|
|
1175
|
+
|
|
1176
|
+
type BandMaskOptions = {
|
|
1177
|
+
/** Soft edge width in Hz for smooth transitions (0 = hard edge). Default: 0 */
|
|
1178
|
+
edgeSmoothHz?: number;
|
|
1179
|
+
};
|
|
1180
|
+
type MaskedSpectrogram = Spectrogram & {
|
|
1181
|
+
/** ID of the band this mask was computed for */
|
|
1182
|
+
bandId: string;
|
|
1183
|
+
/** Fraction of energy retained per frame (0-1) for diagnostics */
|
|
1184
|
+
energyRetainedPerFrame: Float32Array;
|
|
1185
|
+
};
|
|
1186
|
+
/**
|
|
1187
|
+
* Convert an FFT bin index to frequency in Hz.
|
|
1188
|
+
*
|
|
1189
|
+
* @param bin - FFT bin index (0 to fftSize/2)
|
|
1190
|
+
* @param sampleRate - Audio sample rate in Hz
|
|
1191
|
+
* @param fftSize - FFT size (number of samples)
|
|
1192
|
+
* @returns Frequency in Hz
|
|
1193
|
+
*/
|
|
1194
|
+
declare function binToHz(bin: number, sampleRate: number, fftSize: number): number;
|
|
1195
|
+
/**
|
|
1196
|
+
* Convert a frequency in Hz to an FFT bin index.
|
|
1197
|
+
*
|
|
1198
|
+
* @param hz - Frequency in Hz
|
|
1199
|
+
* @param sampleRate - Audio sample rate in Hz
|
|
1200
|
+
* @param fftSize - FFT size (number of samples)
|
|
1201
|
+
* @returns FFT bin index (may be fractional)
|
|
1202
|
+
*/
|
|
1203
|
+
declare function hzToBin(hz: number, sampleRate: number, fftSize: number): number;
|
|
1204
|
+
/**
|
|
1205
|
+
* Compute a spectral mask for a band at a specific time.
|
|
1206
|
+
*
|
|
1207
|
+
* Returns a Float32Array of length (fftSize/2 + 1) containing
|
|
1208
|
+
* mask values between 0 and 1.
|
|
1209
|
+
*
|
|
1210
|
+
* @param band - The frequency band to mask
|
|
1211
|
+
* @param time - Time in seconds
|
|
1212
|
+
* @param sampleRate - Audio sample rate in Hz
|
|
1213
|
+
* @param fftSize - FFT size
|
|
1214
|
+
* @param options - Mask options
|
|
1215
|
+
* @returns Mask array, or null if band is inactive at this time
|
|
1216
|
+
*/
|
|
1217
|
+
declare function computeBandMaskAtTime(band: FrequencyBand, time: number, sampleRate: number, fftSize: number, options?: BandMaskOptions): Float32Array | null;
|
|
1218
|
+
/**
|
|
1219
|
+
* Apply a band mask to an entire spectrogram.
|
|
1220
|
+
*
|
|
1221
|
+
* Creates a new spectrogram with band-masked magnitudes.
|
|
1222
|
+
* Uses linear interpolation of band bounds for time-varying bands.
|
|
1223
|
+
*
|
|
1224
|
+
* @param spec - Source spectrogram
|
|
1225
|
+
* @param band - Frequency band to apply
|
|
1226
|
+
* @param options - Mask options
|
|
1227
|
+
* @returns Masked spectrogram with energy retention diagnostics
|
|
1228
|
+
*/
|
|
1229
|
+
declare function applyBandMaskToSpectrogram(spec: Spectrogram, band: FrequencyBand, options?: BandMaskOptions): MaskedSpectrogram;
|
|
1230
|
+
/**
|
|
1231
|
+
* Compute the energy of a magnitude spectrum.
|
|
1232
|
+
*
|
|
1233
|
+
* @param magnitudes - Magnitude spectrum (one frame)
|
|
1234
|
+
* @returns Sum of squared magnitudes
|
|
1235
|
+
*/
|
|
1236
|
+
declare function computeFrameEnergy(magnitudes: Float32Array): number;
|
|
1237
|
+
/**
|
|
1238
|
+
* Compute the amplitude (sum of magnitudes) of a frame.
|
|
1239
|
+
*
|
|
1240
|
+
* @param magnitudes - Magnitude spectrum (one frame)
|
|
1241
|
+
* @returns Sum of magnitudes
|
|
1242
|
+
*/
|
|
1243
|
+
declare function computeFrameAmplitude(magnitudes: Float32Array): number;
|
|
1244
|
+
|
|
1245
|
+
/**
|
|
1246
|
+
* Band-Scoped MIR utilities for F3.
|
|
1247
|
+
*
|
|
1248
|
+
* These functions compute MIR features (amplitude envelope, onset strength,
|
|
1249
|
+
* spectral flux) for frequency bands by applying spectral masks to an
|
|
1250
|
+
* existing spectrogram.
|
|
1251
|
+
*/
|
|
1252
|
+
|
|
1253
|
+
type BandMirOptions = {
|
|
1254
|
+
/** Soft edge width in Hz for mask transitions. Default: 0 */
|
|
1255
|
+
edgeSmoothHz?: number;
|
|
1256
|
+
/** Options for onset strength computation */
|
|
1257
|
+
onset?: {
|
|
1258
|
+
/** If true, log-compress magnitudes before differencing. */
|
|
1259
|
+
useLog?: boolean;
|
|
1260
|
+
/** Moving-average smoothing window length in milliseconds. 0 disables smoothing. */
|
|
1261
|
+
smoothMs?: number;
|
|
1262
|
+
/** How to convert temporal differences into novelty. */
|
|
1263
|
+
diffMethod?: "rectified" | "abs";
|
|
1264
|
+
};
|
|
1265
|
+
/** Optional cancellation hook */
|
|
1266
|
+
isCancelled?: () => boolean;
|
|
1267
|
+
};
|
|
1268
|
+
/**
|
|
1269
|
+
* Compute amplitude envelope for a frequency band.
|
|
1270
|
+
*
|
|
1271
|
+
* Returns the sum of magnitudes per frame within the band's frequency range.
|
|
1272
|
+
*
|
|
1273
|
+
* @param spec - Source spectrogram
|
|
1274
|
+
* @param band - Frequency band to analyze
|
|
1275
|
+
* @param options - Computation options
|
|
1276
|
+
* @returns Band MIR result with amplitude envelope
|
|
1277
|
+
*/
|
|
1278
|
+
declare function bandAmplitudeEnvelope(spec: Spectrogram, band: FrequencyBand, options?: BandMirOptions): BandMir1DResult;
|
|
1279
|
+
/**
|
|
1280
|
+
* Compute onset strength for a frequency band.
|
|
1281
|
+
*
|
|
1282
|
+
* Uses temporal differences of band-masked magnitudes.
|
|
1283
|
+
* Adapted from onset.ts:onsetEnvelopeFromSpectrogram.
|
|
1284
|
+
*
|
|
1285
|
+
* @param spec - Source spectrogram
|
|
1286
|
+
* @param band - Frequency band to analyze
|
|
1287
|
+
* @param options - Computation options
|
|
1288
|
+
* @returns Band MIR result with onset strength
|
|
1289
|
+
*/
|
|
1290
|
+
declare function bandOnsetStrength(spec: Spectrogram, band: FrequencyBand, options?: BandMirOptions): BandMir1DResult;
|
|
1291
|
+
/**
|
|
1292
|
+
* Compute spectral flux for a frequency band.
|
|
1293
|
+
*
|
|
1294
|
+
* Uses L1 distance between consecutive normalized band-masked spectra.
|
|
1295
|
+
* Adapted from spectral.ts:spectralFlux.
|
|
1296
|
+
*
|
|
1297
|
+
* @param spec - Source spectrogram
|
|
1298
|
+
* @param band - Frequency band to analyze
|
|
1299
|
+
* @param options - Computation options
|
|
1300
|
+
* @returns Band MIR result with spectral flux
|
|
1301
|
+
*/
|
|
1302
|
+
declare function bandSpectralFlux(spec: Spectrogram, band: FrequencyBand, options?: BandMirOptions): BandMir1DResult;
|
|
1303
|
+
/**
|
|
1304
|
+
* Compute spectral centroid for a frequency band.
|
|
1305
|
+
*
|
|
1306
|
+
* Returns the weighted average of frequency bins within the band (center of mass).
|
|
1307
|
+
* Output is in Hz per frame.
|
|
1308
|
+
*
|
|
1309
|
+
* @param spec - Source spectrogram
|
|
1310
|
+
* @param band - Frequency band to analyze
|
|
1311
|
+
* @param options - Computation options
|
|
1312
|
+
* @returns Band MIR result with spectral centroid in Hz
|
|
1313
|
+
*/
|
|
1314
|
+
declare function bandSpectralCentroid(spec: Spectrogram, band: FrequencyBand, options?: BandMirOptions): BandMir1DResult;
|
|
1315
|
+
type BandMirBatchRequest = {
|
|
1316
|
+
bands: FrequencyBand[];
|
|
1317
|
+
functions: BandMirFunctionId[];
|
|
1318
|
+
/** Maximum number of bands to process concurrently. Default: 4 */
|
|
1319
|
+
maxConcurrent?: number;
|
|
1320
|
+
};
|
|
1321
|
+
type BandMirBatchResult = {
|
|
1322
|
+
/** Results keyed by bandId, each containing results for requested functions */
|
|
1323
|
+
results: Map<string, BandMir1DResult[]>;
|
|
1324
|
+
/** Total computation time in ms */
|
|
1325
|
+
totalTimingMs: number;
|
|
1326
|
+
};
|
|
1327
|
+
/**
|
|
1328
|
+
* Run band MIR analysis for multiple bands.
|
|
1329
|
+
*
|
|
1330
|
+
* Processes bands sequentially (web workers don't have real parallelism
|
|
1331
|
+
* within a single thread). The maxConcurrent option is reserved for
|
|
1332
|
+
* future multi-worker support.
|
|
1333
|
+
*
|
|
1334
|
+
* @param spec - Source spectrogram
|
|
1335
|
+
* @param request - Batch request specifying bands and functions
|
|
1336
|
+
* @param options - Computation options
|
|
1337
|
+
* @returns Map of results by band ID
|
|
1338
|
+
*/
|
|
1339
|
+
declare function runBandMirBatch(spec: Spectrogram, request: BandMirBatchRequest, options?: BandMirOptions): Promise<BandMirBatchResult>;
|
|
1340
|
+
/**
|
|
1341
|
+
* Get a human-readable label for a band MIR function.
|
|
1342
|
+
*
|
|
1343
|
+
* @param fn - Band MIR function ID
|
|
1344
|
+
* @returns Human-readable label
|
|
1345
|
+
*/
|
|
1346
|
+
declare function getBandMirFunctionLabel(fn: BandMirFunctionId): string;
|
|
1347
|
+
|
|
1348
|
+
/**
|
|
1349
|
+
* Band Event Extraction for F3.
|
|
1350
|
+
*
|
|
1351
|
+
* These functions extract discrete events (onset peaks, beat candidates)
|
|
1352
|
+
* from band-scoped 1D signals.
|
|
1353
|
+
*/
|
|
1354
|
+
|
|
1355
|
+
type BandOnsetPeaksOptions = {
|
|
1356
|
+
/** Minimum inter-peak interval in seconds. Default: 0.0625 (~0.125 beats at 120 BPM). */
|
|
1357
|
+
minIntervalSec?: number;
|
|
1358
|
+
/** Adaptive threshold factor. Default: 0.8 (conservative for bands). */
|
|
1359
|
+
adaptiveFactor?: number;
|
|
1360
|
+
/** Use strict peak detection (> neighbors). Default: true. */
|
|
1361
|
+
strict?: boolean;
|
|
1362
|
+
};
|
|
1363
|
+
type BandBeatCandidatesOptions = {
|
|
1364
|
+
/** Minimum inter-candidate interval in seconds. Default: 0.1. */
|
|
1365
|
+
minIntervalSec?: number;
|
|
1366
|
+
/** Threshold factor for adaptive detection. Lower = more candidates. Default: 0.5. */
|
|
1367
|
+
thresholdFactor?: number;
|
|
1368
|
+
};
|
|
1369
|
+
/**
|
|
1370
|
+
* Extract onset peaks from a band MIR 1D signal.
|
|
1371
|
+
*
|
|
1372
|
+
* Uses peak picking with conservative defaults optimized for band-scoped
|
|
1373
|
+
* extraction. Typically applied to bandOnsetStrength or bandAmplitudeEnvelope.
|
|
1374
|
+
*
|
|
1375
|
+
* @param signal - The band MIR 1D result to extract peaks from
|
|
1376
|
+
* @param options - Peak picking options
|
|
1377
|
+
* @returns Band events result with onset peaks
|
|
1378
|
+
*/
|
|
1379
|
+
declare function bandOnsetPeaks(signal: BandMir1DResult, options?: BandOnsetPeaksOptions): BandEventsResult;
|
|
1380
|
+
/**
|
|
1381
|
+
* Extract beat candidates from a band's onset peaks.
|
|
1382
|
+
*
|
|
1383
|
+
* Similar to full-track beat candidate detection but simplified for
|
|
1384
|
+
* single-band input. Uses the onset peaks to identify beat-like events.
|
|
1385
|
+
*
|
|
1386
|
+
* @param onsetPeaks - Band onset peaks result
|
|
1387
|
+
* @param options - Beat candidate options
|
|
1388
|
+
* @returns Band events result with beat candidates
|
|
1389
|
+
*/
|
|
1390
|
+
declare function bandBeatCandidates(onsetPeaks: BandEventsResult, options?: BandBeatCandidatesOptions): BandEventsResult;
|
|
1391
|
+
type BandEventsBatchRequest = {
|
|
1392
|
+
/** Band MIR results to extract events from (keyed by bandId) */
|
|
1393
|
+
bandMirResults: Map<string, BandMir1DResult[]>;
|
|
1394
|
+
/** Event functions to run */
|
|
1395
|
+
functions: BandEventFunctionId[];
|
|
1396
|
+
/** Source signal function to use for onset peaks. Default: bandOnsetStrength */
|
|
1397
|
+
sourceFunction?: "bandOnsetStrength" | "bandAmplitudeEnvelope";
|
|
1398
|
+
/** Options for onset peaks extraction */
|
|
1399
|
+
onsetPeaksOptions?: BandOnsetPeaksOptions;
|
|
1400
|
+
/** Options for beat candidates extraction */
|
|
1401
|
+
beatCandidatesOptions?: BandBeatCandidatesOptions;
|
|
1402
|
+
};
|
|
1403
|
+
type BandEventsBatchResult = {
|
|
1404
|
+
/** Results keyed by bandId, each containing results for requested functions */
|
|
1405
|
+
results: Map<string, BandEventsResult[]>;
|
|
1406
|
+
/** Total computation time in ms */
|
|
1407
|
+
totalTimingMs: number;
|
|
1408
|
+
};
|
|
1409
|
+
/**
|
|
1410
|
+
* Run band event extraction for multiple bands.
|
|
1411
|
+
*
|
|
1412
|
+
* @param request - Batch request specifying bands, functions, and options
|
|
1413
|
+
* @returns Map of results by band ID
|
|
1414
|
+
*/
|
|
1415
|
+
declare function runBandEventsBatch(request: BandEventsBatchRequest): Promise<BandEventsBatchResult>;
|
|
1416
|
+
/**
|
|
1417
|
+
* Get a human-readable label for a band event function.
|
|
1418
|
+
*
|
|
1419
|
+
* @param fn - Band event function ID
|
|
1420
|
+
* @returns Human-readable label
|
|
1421
|
+
*/
|
|
1422
|
+
declare function getBandEventFunctionLabel(fn: BandEventFunctionId): string;
|
|
1423
|
+
|
|
1424
|
+
/**
|
|
1425
|
+
* Band-Scoped CQT utilities for F3.
|
|
1426
|
+
*
|
|
1427
|
+
* These functions compute CQT-derived features (harmonic energy, bass pitch motion,
|
|
1428
|
+
* tonal stability) for frequency bands by applying spectral masks to a CQT
|
|
1429
|
+
* spectrogram.
|
|
1430
|
+
*
|
|
1431
|
+
* CQT uses log-frequency bins, so band masking requires mapping Hz ranges
|
|
1432
|
+
* to CQT bin indices using hzToCqtBin().
|
|
1433
|
+
*/
|
|
1434
|
+
|
|
1435
|
+
type BandCqtOptions = {
|
|
1436
|
+
/** Soft edge width in bins for mask transitions. Default: 0 */
|
|
1437
|
+
edgeSmoothBins?: number;
|
|
1438
|
+
/** Optional cancellation hook */
|
|
1439
|
+
isCancelled?: () => boolean;
|
|
1440
|
+
};
|
|
1441
|
+
type MaskedCqtSpectrogram = {
|
|
1442
|
+
/** Original CQT times */
|
|
1443
|
+
times: Float32Array;
|
|
1444
|
+
/** Masked CQT magnitudes */
|
|
1445
|
+
magnitudes: Float32Array[];
|
|
1446
|
+
/** CQT config */
|
|
1447
|
+
config: CqtConfig;
|
|
1448
|
+
/** Energy retained per frame (0-1) */
|
|
1449
|
+
energyRetainedPerFrame: Float32Array;
|
|
1450
|
+
/** CQT bin frequencies */
|
|
1451
|
+
binFrequencies: Float32Array;
|
|
1452
|
+
};
|
|
1453
|
+
/**
|
|
1454
|
+
* Apply a frequency band mask to a CQT spectrogram.
|
|
1455
|
+
*
|
|
1456
|
+
* Maps the band's Hz range to CQT bin indices and masks accordingly.
|
|
1457
|
+
*
|
|
1458
|
+
* @param cqt - Source CQT spectrogram
|
|
1459
|
+
* @param band - Frequency band to apply
|
|
1460
|
+
* @param options - Masking options
|
|
1461
|
+
* @returns Masked CQT spectrogram with energy retention diagnostics
|
|
1462
|
+
*/
|
|
1463
|
+
declare function applyBandMaskToCqt(cqt: CqtSpectrogram, band: FrequencyBand, options?: BandCqtOptions): MaskedCqtSpectrogram;
|
|
1464
|
+
/**
|
|
1465
|
+
* Compute harmonic energy for a frequency band using CQT.
|
|
1466
|
+
*
|
|
1467
|
+
* Measures the ratio of energy at harmonic intervals within the band.
|
|
1468
|
+
* Adapted from cqtSignals.ts:harmonicEnergy.
|
|
1469
|
+
*
|
|
1470
|
+
* @param cqt - Source CQT spectrogram
|
|
1471
|
+
* @param band - Frequency band to analyze
|
|
1472
|
+
* @param options - Computation options
|
|
1473
|
+
* @returns Band CQT result with harmonic energy
|
|
1474
|
+
*/
|
|
1475
|
+
declare function bandCqtHarmonicEnergy(cqt: CqtSpectrogram, band: FrequencyBand, options?: BandCqtOptions): BandCqt1DResult;
|
|
1476
|
+
/**
|
|
1477
|
+
* Compute bass pitch motion for a frequency band using CQT.
|
|
67
1478
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
1479
|
+
* Measures pitch movement in bass-range CQT bins within the band.
|
|
1480
|
+
* Most meaningful for bands overlapping the bass range (20-300 Hz).
|
|
1481
|
+
*
|
|
1482
|
+
* @param cqt - Source CQT spectrogram
|
|
1483
|
+
* @param band - Frequency band to analyze
|
|
1484
|
+
* @param options - Computation options
|
|
1485
|
+
* @returns Band CQT result with bass pitch motion
|
|
72
1486
|
*/
|
|
73
|
-
declare function
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
1487
|
+
declare function bandCqtBassPitchMotion(cqt: CqtSpectrogram, band: FrequencyBand, options?: BandCqtOptions): BandCqt1DResult;
|
|
1488
|
+
/**
|
|
1489
|
+
* Compute tonal stability for a frequency band using CQT.
|
|
1490
|
+
*
|
|
1491
|
+
* Measures consistency of chroma distribution over time within the band.
|
|
1492
|
+
* Adapted from cqtSignals.ts:tonalStability.
|
|
1493
|
+
*
|
|
1494
|
+
* @param cqt - Source CQT spectrogram
|
|
1495
|
+
* @param band - Frequency band to analyze
|
|
1496
|
+
* @param options - Computation options
|
|
1497
|
+
* @returns Band CQT result with tonal stability
|
|
1498
|
+
*/
|
|
1499
|
+
declare function bandCqtTonalStability(cqt: CqtSpectrogram, band: FrequencyBand, options?: BandCqtOptions): BandCqt1DResult;
|
|
1500
|
+
type BandCqtBatchRequest = {
|
|
1501
|
+
bands: FrequencyBand[];
|
|
1502
|
+
functions: BandCqtFunctionId[];
|
|
1503
|
+
/** Maximum number of bands to process concurrently. Default: 4 */
|
|
1504
|
+
maxConcurrent?: number;
|
|
79
1505
|
};
|
|
80
|
-
type
|
|
81
|
-
/**
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
|
|
85
|
-
/** If provided, use adaptive threshold: mean(values) + factor*std(values). */
|
|
86
|
-
adaptive?: {
|
|
87
|
-
method?: "meanStd" | "median";
|
|
88
|
-
factor?: number;
|
|
89
|
-
};
|
|
90
|
-
/** If true, prefer strict maxima (> neighbors); else allow flat plateaus. */
|
|
91
|
-
strict?: boolean;
|
|
1506
|
+
type BandCqtBatchResult = {
|
|
1507
|
+
/** Results keyed by bandId */
|
|
1508
|
+
results: Map<string, BandCqt1DResult[]>;
|
|
1509
|
+
/** Total computation time in ms */
|
|
1510
|
+
totalTimingMs: number;
|
|
92
1511
|
};
|
|
93
|
-
|
|
1512
|
+
/**
|
|
1513
|
+
* Run band CQT analysis for multiple bands.
|
|
1514
|
+
*
|
|
1515
|
+
* @param cqt - Source CQT spectrogram
|
|
1516
|
+
* @param request - Batch request specifying bands and functions
|
|
1517
|
+
* @param options - Computation options
|
|
1518
|
+
* @returns Map of results by band ID
|
|
1519
|
+
*/
|
|
1520
|
+
declare function runBandCqtBatch(cqt: CqtSpectrogram, request: BandCqtBatchRequest, options?: BandCqtOptions): Promise<BandCqtBatchResult>;
|
|
1521
|
+
/**
|
|
1522
|
+
* Get a human-readable label for a band CQT function.
|
|
1523
|
+
*
|
|
1524
|
+
* @param fn - Band CQT function ID
|
|
1525
|
+
* @returns Human-readable label
|
|
1526
|
+
*/
|
|
1527
|
+
declare function getBandCqtFunctionLabel(fn: BandCqtFunctionId): string;
|
|
94
1528
|
|
|
95
1529
|
type SpectrogramLike2D = {
|
|
96
1530
|
times: Float32Array;
|
|
@@ -132,6 +1566,634 @@ type Features2D = {
|
|
|
132
1566
|
declare function delta(features: Features2D, options?: DeltaOptions): Features2D;
|
|
133
1567
|
declare function deltaDelta(features: Features2D, options?: DeltaOptions): Features2D;
|
|
134
1568
|
|
|
1569
|
+
/**
|
|
1570
|
+
* Constant-Q Transform (CQT) implementation for F5.
|
|
1571
|
+
*
|
|
1572
|
+
* CQT provides log-frequency resolution aligned to musical pitch ratios.
|
|
1573
|
+
* This implementation builds on the existing STFT infrastructure by:
|
|
1574
|
+
* 1. Computing an STFT using the existing spectrogram function
|
|
1575
|
+
* 2. Applying a CQT filterbank in the frequency domain
|
|
1576
|
+
*
|
|
1577
|
+
* The CQT is an internal spectral view, not a user-facing spectrogram.
|
|
1578
|
+
*/
|
|
1579
|
+
|
|
1580
|
+
/** Default CQT configuration values */
|
|
1581
|
+
declare const CQT_DEFAULTS: {
|
|
1582
|
+
/** Quarter-tone resolution (24 bins per octave) */
|
|
1583
|
+
readonly binsPerOctave: 24;
|
|
1584
|
+
/** C1 (lowest note on a standard piano) */
|
|
1585
|
+
readonly fMin: 32.7;
|
|
1586
|
+
/** C9 (well above audible range for most content) */
|
|
1587
|
+
readonly fMax: 8372;
|
|
1588
|
+
};
|
|
1589
|
+
/**
|
|
1590
|
+
* Convert CQT bin index to frequency in Hz.
|
|
1591
|
+
*/
|
|
1592
|
+
declare function cqtBinToHz(bin: number, config: CqtConfig): number;
|
|
1593
|
+
/**
|
|
1594
|
+
* Convert frequency in Hz to CQT bin index (may be fractional).
|
|
1595
|
+
*/
|
|
1596
|
+
declare function hzToCqtBin(hz: number, config: CqtConfig): number;
|
|
1597
|
+
/**
|
|
1598
|
+
* Calculate number of octaves covered by the CQT config.
|
|
1599
|
+
*/
|
|
1600
|
+
declare function getNumOctaves(config: CqtConfig): number;
|
|
1601
|
+
/**
|
|
1602
|
+
* Calculate total number of CQT bins.
|
|
1603
|
+
*/
|
|
1604
|
+
declare function getNumBins(config: CqtConfig): number;
|
|
1605
|
+
/**
|
|
1606
|
+
* Generate the center frequencies for all CQT bins.
|
|
1607
|
+
*/
|
|
1608
|
+
declare function getCqtBinFrequencies(config: CqtConfig): Float32Array;
|
|
1609
|
+
type CqtOptions = {
|
|
1610
|
+
/** Optional cancellation hook; checked periodically. */
|
|
1611
|
+
isCancelled?: () => boolean;
|
|
1612
|
+
};
|
|
1613
|
+
/**
|
|
1614
|
+
* Apply default values to a partial CQT config.
|
|
1615
|
+
*/
|
|
1616
|
+
declare function withCqtDefaults(partial?: Partial<CqtConfig>): CqtConfig;
|
|
1617
|
+
/**
|
|
1618
|
+
* Compute a CQT spectrogram from audio.
|
|
1619
|
+
*
|
|
1620
|
+
* This function:
|
|
1621
|
+
* 1. Computes an STFT using the existing spectrogram infrastructure
|
|
1622
|
+
* 2. Applies a CQT filterbank to each STFT frame
|
|
1623
|
+
* 3. Returns a log-frequency representation
|
|
1624
|
+
*
|
|
1625
|
+
* @param audio - Audio buffer to analyze
|
|
1626
|
+
* @param config - CQT configuration
|
|
1627
|
+
* @param options - Optional processing options
|
|
1628
|
+
* @returns CQT spectrogram with log-frequency resolution
|
|
1629
|
+
*/
|
|
1630
|
+
declare function cqtSpectrogram(audio: AudioBufferLike$1, config: CqtConfig, options?: CqtOptions): Promise<CqtSpectrogram>;
|
|
1631
|
+
/**
|
|
1632
|
+
* Compute CQT and return with metadata for MIR pipeline.
|
|
1633
|
+
*/
|
|
1634
|
+
declare function computeCqt(audio: AudioBufferLike$1, config?: Partial<CqtConfig>, options?: CqtOptions): Promise<{
|
|
1635
|
+
cqt: CqtSpectrogram;
|
|
1636
|
+
meta: MirRunMeta;
|
|
1637
|
+
}>;
|
|
1638
|
+
|
|
1639
|
+
/**
|
|
1640
|
+
* CQT-Derived 1D Signals for F5.
|
|
1641
|
+
*
|
|
1642
|
+
* These signals extract musically meaningful 1D features from the CQT representation:
|
|
1643
|
+
* - harmonicEnergy: Measures tonal presence vs noise
|
|
1644
|
+
* - bassPitchMotion: Measures bassline activity and low-end groove
|
|
1645
|
+
* - tonalStability: Measures harmonic stability vs modulation
|
|
1646
|
+
*
|
|
1647
|
+
* All signals are:
|
|
1648
|
+
* - 1D (one value per frame)
|
|
1649
|
+
* - Time-aligned with the CQT frames
|
|
1650
|
+
* - Deterministic
|
|
1651
|
+
* - Normalized to [0, 1] range
|
|
1652
|
+
*/
|
|
1653
|
+
|
|
1654
|
+
/**
|
|
1655
|
+
* Compute harmonic energy signal from CQT.
|
|
1656
|
+
*
|
|
1657
|
+
* Measures sustained, pitch-aligned energy across harmonic bins.
|
|
1658
|
+
* Intended to capture "tonal presence" vs noise.
|
|
1659
|
+
*/
|
|
1660
|
+
declare function harmonicEnergy(cqt: CqtSpectrogram): CqtSignalResult;
|
|
1661
|
+
/**
|
|
1662
|
+
* Compute bass pitch motion signal from CQT.
|
|
1663
|
+
*
|
|
1664
|
+
* Measures rate and magnitude of pitch movement in low-frequency CQT bins.
|
|
1665
|
+
* Intended to capture bassline motion, groove, and low-end activity.
|
|
1666
|
+
*
|
|
1667
|
+
* Algorithm:
|
|
1668
|
+
* 1. Extract bass-range bins from each frame
|
|
1669
|
+
* 2. Compute pitch centroid in bass range
|
|
1670
|
+
* 3. Compute absolute difference between consecutive frames
|
|
1671
|
+
*/
|
|
1672
|
+
declare function bassPitchMotion(cqt: CqtSpectrogram): CqtSignalResult;
|
|
1673
|
+
/**
|
|
1674
|
+
* Compute tonal stability signal from CQT.
|
|
1675
|
+
*
|
|
1676
|
+
* Measures consistency of dominant pitch structure over time.
|
|
1677
|
+
* High values imply harmonic stability; low values imply modulation or noise.
|
|
1678
|
+
*
|
|
1679
|
+
* Algorithm:
|
|
1680
|
+
* 1. Compute chroma histogram for each frame
|
|
1681
|
+
* 2. Over a sliding window, compute variance of chroma distribution
|
|
1682
|
+
* 3. Low variance = stable tonality; high variance = unstable
|
|
1683
|
+
* 4. Invert so that high values = stable
|
|
1684
|
+
*/
|
|
1685
|
+
declare function tonalStability(cqt: CqtSpectrogram): CqtSignalResult;
|
|
1686
|
+
/**
|
|
1687
|
+
* Compute a CQT-derived signal by ID.
|
|
1688
|
+
*/
|
|
1689
|
+
declare function computeCqtSignal(cqt: CqtSpectrogram, signalId: CqtSignalId): CqtSignalResult;
|
|
1690
|
+
/**
|
|
1691
|
+
* Compute all CQT-derived signals.
|
|
1692
|
+
*/
|
|
1693
|
+
declare function computeAllCqtSignals(cqt: CqtSpectrogram): Map<CqtSignalId, CqtSignalResult>;
|
|
1694
|
+
|
|
1695
|
+
/**
|
|
1696
|
+
* YIN-based monophonic pitch detection.
|
|
1697
|
+
*
|
|
1698
|
+
* Implements the YIN algorithm for fundamental frequency (f0) estimation.
|
|
1699
|
+
* Designed for monophonic sources: vocals, bass, lead synths.
|
|
1700
|
+
*
|
|
1701
|
+
* Reference: de Cheveigné, A., & Kawahara, H. (2002).
|
|
1702
|
+
* "YIN, a fundamental frequency estimator for speech and music."
|
|
1703
|
+
* Journal of the Acoustical Society of America, 111(4), 1917-1930.
|
|
1704
|
+
*/
|
|
1705
|
+
|
|
1706
|
+
/** Options for activity gating in pitch detection */
|
|
1707
|
+
type PitchActivityOptions = {
|
|
1708
|
+
/** Pre-computed activity signal to use for gating */
|
|
1709
|
+
activity?: ActivitySignal;
|
|
1710
|
+
/** How to handle inactive frames. Default: "zero" */
|
|
1711
|
+
inactiveBehavior?: "zero" | "hold";
|
|
1712
|
+
};
|
|
1713
|
+
type PitchConfig = {
|
|
1714
|
+
/** Minimum detectable frequency in Hz. Default: 50 */
|
|
1715
|
+
fMinHz?: number;
|
|
1716
|
+
/** Maximum detectable frequency in Hz. Default: 1000 */
|
|
1717
|
+
fMaxHz?: number;
|
|
1718
|
+
/** Hop size in samples (determines time resolution). Default: 512 */
|
|
1719
|
+
hopSize?: number;
|
|
1720
|
+
/** Window size for analysis. Default: 2048 */
|
|
1721
|
+
windowSize?: number;
|
|
1722
|
+
/** YIN threshold for voiced detection (0-1). Default: 0.15 */
|
|
1723
|
+
threshold?: number;
|
|
1724
|
+
/** Activity gating options */
|
|
1725
|
+
activityOptions?: PitchActivityOptions;
|
|
1726
|
+
};
|
|
1727
|
+
type PitchResult = {
|
|
1728
|
+
times: Float32Array;
|
|
1729
|
+
values: Float32Array;
|
|
1730
|
+
};
|
|
1731
|
+
/**
|
|
1732
|
+
* Extract fundamental frequency (f0) from mono audio.
|
|
1733
|
+
*
|
|
1734
|
+
* Uses the YIN algorithm for robust pitch detection.
|
|
1735
|
+
* Returns 0 Hz for unvoiced/silent frames.
|
|
1736
|
+
*
|
|
1737
|
+
* @param samples - Mono audio samples
|
|
1738
|
+
* @param sampleRate - Sample rate of the audio
|
|
1739
|
+
* @param config - Configuration options
|
|
1740
|
+
* @returns Times (seconds) and f0 values (Hz, 0 for unvoiced)
|
|
1741
|
+
*/
|
|
1742
|
+
declare function pitchF0(samples: Float32Array, sampleRate: number, config?: PitchConfig): PitchResult;
|
|
1743
|
+
/**
|
|
1744
|
+
* Extract pitch detection confidence from mono audio.
|
|
1745
|
+
*
|
|
1746
|
+
* Uses the YIN algorithm's aperiodicity measure.
|
|
1747
|
+
* Returns values in [0, 1] where 1 = highly periodic (confident pitch).
|
|
1748
|
+
*
|
|
1749
|
+
* @param samples - Mono audio samples
|
|
1750
|
+
* @param sampleRate - Sample rate of the audio
|
|
1751
|
+
* @param config - Configuration options
|
|
1752
|
+
* @returns Times (seconds) and confidence values (0-1)
|
|
1753
|
+
*/
|
|
1754
|
+
declare function pitchConfidence(samples: Float32Array, sampleRate: number, config?: PitchConfig): PitchResult;
|
|
1755
|
+
|
|
1756
|
+
/**
|
|
1757
|
+
* Band Proposal Generation for F5.
|
|
1758
|
+
*
|
|
1759
|
+
* Generates automated suggestions for "interesting" frequency bands.
|
|
1760
|
+
* Proposals are advisory only - they must be explicitly promoted by the user.
|
|
1761
|
+
*
|
|
1762
|
+
* Algorithm overview:
|
|
1763
|
+
* 1. Analyze spectral structure using CQT
|
|
1764
|
+
* 2. Identify regions with concentrated energy or distinct activity
|
|
1765
|
+
* 3. Score and rank candidates
|
|
1766
|
+
* 4. Generate proposal objects with explanations
|
|
1767
|
+
*/
|
|
1768
|
+
|
|
1769
|
+
type BandProposalOptions = {
|
|
1770
|
+
config?: BandProposalConfig;
|
|
1771
|
+
isCancelled?: () => boolean;
|
|
1772
|
+
};
|
|
1773
|
+
/**
|
|
1774
|
+
* Generate band proposals from audio.
|
|
1775
|
+
*
|
|
1776
|
+
* @param audio - Audio buffer to analyze
|
|
1777
|
+
* @param duration - Track duration in seconds
|
|
1778
|
+
* @param options - Optional configuration
|
|
1779
|
+
* @returns Array of band proposals with salience scores and reasons
|
|
1780
|
+
*/
|
|
1781
|
+
declare function generateBandProposals(audio: AudioBufferLike$1, duration: number, options?: BandProposalOptions): Promise<BandProposalResult>;
|
|
1782
|
+
|
|
1783
|
+
/**
|
|
1784
|
+
* Custom Signal Reduction
|
|
1785
|
+
*
|
|
1786
|
+
* Provides algorithms for reducing 2D spectral data (mel spectrogram, HPSS,
|
|
1787
|
+
* MFCC, etc.) to 1D signals with configurable bin ranges and reduction methods.
|
|
1788
|
+
*/
|
|
1789
|
+
/**
|
|
1790
|
+
* Input format for 2D time-aligned data.
|
|
1791
|
+
* Shape: data[timeIndex][featureIndex]
|
|
1792
|
+
*/
|
|
1793
|
+
interface ReductionInput {
|
|
1794
|
+
/** 2D data: data[timeIndex][featureIndex] */
|
|
1795
|
+
data: Float32Array[];
|
|
1796
|
+
/** Time in seconds for each frame */
|
|
1797
|
+
times: Float32Array;
|
|
1798
|
+
}
|
|
1799
|
+
/**
|
|
1800
|
+
* Reduction algorithm identifiers.
|
|
1801
|
+
*/
|
|
1802
|
+
type ReductionAlgorithmId = "mean" | "max" | "sum" | "variance" | "amplitude" | "spectralFlux" | "spectralCentroid" | "onsetStrength";
|
|
1803
|
+
/**
|
|
1804
|
+
* Options for bin range selection.
|
|
1805
|
+
*/
|
|
1806
|
+
interface BinRangeOptions {
|
|
1807
|
+
/** Low bin index (inclusive). Default: 0 */
|
|
1808
|
+
lowBin?: number;
|
|
1809
|
+
/** High bin index (exclusive). Default: all bins */
|
|
1810
|
+
highBin?: number;
|
|
1811
|
+
}
|
|
1812
|
+
/**
|
|
1813
|
+
* Options for onset strength algorithm.
|
|
1814
|
+
*/
|
|
1815
|
+
interface OnsetStrengthOptions {
|
|
1816
|
+
/** Smoothing window in milliseconds. Default: 10 */
|
|
1817
|
+
smoothMs?: number;
|
|
1818
|
+
/** Whether to log-compress before differencing. Default: true */
|
|
1819
|
+
useLog?: boolean;
|
|
1820
|
+
/** Difference method. Default: "rectified" */
|
|
1821
|
+
diffMethod?: "rectified" | "abs";
|
|
1822
|
+
}
|
|
1823
|
+
/**
|
|
1824
|
+
* Options for spectral flux algorithm.
|
|
1825
|
+
*/
|
|
1826
|
+
interface SpectralFluxOptions {
|
|
1827
|
+
/** Whether to normalize frames before computing flux. Default: true */
|
|
1828
|
+
normalized?: boolean;
|
|
1829
|
+
}
|
|
1830
|
+
/**
|
|
1831
|
+
* Combined options for reduction.
|
|
1832
|
+
*/
|
|
1833
|
+
interface ReductionOptions {
|
|
1834
|
+
/** Bin range selection */
|
|
1835
|
+
binRange?: BinRangeOptions;
|
|
1836
|
+
/** Onset strength parameters */
|
|
1837
|
+
onsetStrength?: OnsetStrengthOptions;
|
|
1838
|
+
/** Spectral flux parameters */
|
|
1839
|
+
spectralFlux?: SpectralFluxOptions;
|
|
1840
|
+
}
|
|
1841
|
+
/**
|
|
1842
|
+
* Result of a reduction operation.
|
|
1843
|
+
*/
|
|
1844
|
+
interface ReductionResult {
|
|
1845
|
+
/** Frame times in seconds */
|
|
1846
|
+
times: Float32Array;
|
|
1847
|
+
/** Reduced values per frame */
|
|
1848
|
+
values: Float32Array;
|
|
1849
|
+
/** Value range for normalization */
|
|
1850
|
+
valueRange: {
|
|
1851
|
+
min: number;
|
|
1852
|
+
max: number;
|
|
1853
|
+
};
|
|
1854
|
+
}
|
|
1855
|
+
/**
|
|
1856
|
+
* Reduce 2D time-aligned data to a 1D signal using the specified algorithm.
|
|
1857
|
+
*
|
|
1858
|
+
* @param input - 2D input data (frames x bins)
|
|
1859
|
+
* @param algorithm - Reduction algorithm to use
|
|
1860
|
+
* @param options - Algorithm options including bin range selection
|
|
1861
|
+
* @returns Reduction result with times, values, and value range
|
|
1862
|
+
*/
|
|
1863
|
+
declare function reduce2DToSignal(input: ReductionInput, algorithm: ReductionAlgorithmId, options?: ReductionOptions): ReductionResult;
|
|
1864
|
+
/**
|
|
1865
|
+
* Get human-readable label for a reduction algorithm.
|
|
1866
|
+
*/
|
|
1867
|
+
declare function getReductionAlgorithmLabel(algorithm: ReductionAlgorithmId): string;
|
|
1868
|
+
/**
|
|
1869
|
+
* Get description for a reduction algorithm.
|
|
1870
|
+
*/
|
|
1871
|
+
declare function getReductionAlgorithmDescription(algorithm: ReductionAlgorithmId): string;
|
|
1872
|
+
/**
|
|
1873
|
+
* Polarity interpretation mode.
|
|
1874
|
+
* - "signed": Preserve direction (signal can be positive or negative)
|
|
1875
|
+
* - "magnitude": Activity level only (always positive, uses absolute value)
|
|
1876
|
+
*/
|
|
1877
|
+
type PolarityMode = "signed" | "magnitude";
|
|
1878
|
+
/**
|
|
1879
|
+
* Apply polarity interpretation to a signal.
|
|
1880
|
+
* Called after reduction, before stabilization.
|
|
1881
|
+
*
|
|
1882
|
+
* @param values - Input signal values
|
|
1883
|
+
* @param mode - Polarity mode to apply
|
|
1884
|
+
* @returns Transformed signal values
|
|
1885
|
+
*/
|
|
1886
|
+
declare function applyPolarity(values: Float32Array, mode: PolarityMode): Float32Array;
|
|
1887
|
+
/**
|
|
1888
|
+
* Stabilization mode presets.
|
|
1889
|
+
*/
|
|
1890
|
+
type StabilizationMode = "none" | "light" | "medium" | "heavy";
|
|
1891
|
+
/**
|
|
1892
|
+
* Envelope mode for signal shaping.
|
|
1893
|
+
*/
|
|
1894
|
+
type EnvelopeMode = "raw" | "attackRelease";
|
|
1895
|
+
/**
|
|
1896
|
+
* Options for signal stabilization.
|
|
1897
|
+
*/
|
|
1898
|
+
interface StabilizationOptions {
|
|
1899
|
+
/** Smoothing intensity preset. */
|
|
1900
|
+
mode: StabilizationMode;
|
|
1901
|
+
/** Envelope shaping mode. */
|
|
1902
|
+
envelopeMode: EnvelopeMode;
|
|
1903
|
+
/** Attack time in seconds (only for attackRelease mode). */
|
|
1904
|
+
attackTimeSec?: number;
|
|
1905
|
+
/** Release time in seconds (only for attackRelease mode). */
|
|
1906
|
+
releaseTimeSec?: number;
|
|
1907
|
+
}
|
|
1908
|
+
/**
|
|
1909
|
+
* Apply stabilization to a signal.
|
|
1910
|
+
*
|
|
1911
|
+
* @param values - Input signal values
|
|
1912
|
+
* @param times - Frame times in seconds
|
|
1913
|
+
* @param options - Stabilization options
|
|
1914
|
+
* @returns Stabilized signal values
|
|
1915
|
+
*/
|
|
1916
|
+
declare function stabilizeSignal(values: Float32Array, times: Float32Array, options: StabilizationOptions): Float32Array;
|
|
1917
|
+
/**
|
|
1918
|
+
* Compute percentile values from a signal.
|
|
1919
|
+
*
|
|
1920
|
+
* @param values - Signal values
|
|
1921
|
+
* @param percentiles - Array of percentiles to compute (0-100)
|
|
1922
|
+
* @returns Object mapping percentile to value
|
|
1923
|
+
*/
|
|
1924
|
+
declare function computePercentiles(values: Float32Array, percentiles: number[]): Record<number, number>;
|
|
1925
|
+
/**
|
|
1926
|
+
* Compute local (viewport) statistics for a signal.
|
|
1927
|
+
*
|
|
1928
|
+
* @param values - Signal values
|
|
1929
|
+
* @param times - Frame times in seconds
|
|
1930
|
+
* @param startTime - Viewport start time
|
|
1931
|
+
* @param endTime - Viewport end time
|
|
1932
|
+
* @returns Statistics within the viewport
|
|
1933
|
+
*/
|
|
1934
|
+
declare function computeLocalStats(values: Float32Array, times: Float32Array, startTime: number, endTime: number): {
|
|
1935
|
+
min: number;
|
|
1936
|
+
max: number;
|
|
1937
|
+
p5: number;
|
|
1938
|
+
p95: number;
|
|
1939
|
+
};
|
|
1940
|
+
|
|
1941
|
+
/**
|
|
1942
|
+
* Event to Signal Conversion
|
|
1943
|
+
*
|
|
1944
|
+
* Converts discrete event streams (onsets, beats, authored events)
|
|
1945
|
+
* into continuous 1D signals for use in derived signal pipelines.
|
|
1946
|
+
*
|
|
1947
|
+
* Reducer algorithms:
|
|
1948
|
+
* - eventCount: Count events per window
|
|
1949
|
+
* - eventDensity: Normalized count (events per second)
|
|
1950
|
+
* - weightedSum: Sum of event weights per window
|
|
1951
|
+
* - weightedMean: Mean of event weights per window
|
|
1952
|
+
* - envelope: Generate continuous envelope from events
|
|
1953
|
+
*/
|
|
1954
|
+
/**
|
|
1955
|
+
* A discrete event with time and optional weight.
|
|
1956
|
+
*/
|
|
1957
|
+
interface DiscreteEvent {
|
|
1958
|
+
/** Event time in seconds. */
|
|
1959
|
+
time: number;
|
|
1960
|
+
/** Event weight (default 1.0). */
|
|
1961
|
+
weight?: number;
|
|
1962
|
+
/** Optional duration in seconds. */
|
|
1963
|
+
duration?: number;
|
|
1964
|
+
}
|
|
1965
|
+
/**
|
|
1966
|
+
* Window specification for event aggregation.
|
|
1967
|
+
*/
|
|
1968
|
+
type EventWindowSpec = {
|
|
1969
|
+
kind: "seconds";
|
|
1970
|
+
windowSize: number;
|
|
1971
|
+
} | {
|
|
1972
|
+
kind: "samples";
|
|
1973
|
+
windowSize: number;
|
|
1974
|
+
};
|
|
1975
|
+
/**
|
|
1976
|
+
* Envelope shape for event-to-signal conversion.
|
|
1977
|
+
*/
|
|
1978
|
+
type EnvelopeShape = {
|
|
1979
|
+
kind: "impulse";
|
|
1980
|
+
} | {
|
|
1981
|
+
kind: "gaussian";
|
|
1982
|
+
widthMs: number;
|
|
1983
|
+
} | {
|
|
1984
|
+
kind: "attackDecay";
|
|
1985
|
+
attackMs: number;
|
|
1986
|
+
decayMs: number;
|
|
1987
|
+
} | {
|
|
1988
|
+
kind: "gate";
|
|
1989
|
+
};
|
|
1990
|
+
/**
|
|
1991
|
+
* Options for event-to-signal conversion.
|
|
1992
|
+
*/
|
|
1993
|
+
interface EventToSignalOptions {
|
|
1994
|
+
/** Sample rate for output signal (samples per second). */
|
|
1995
|
+
sampleRate: number;
|
|
1996
|
+
/** Total duration in seconds. */
|
|
1997
|
+
duration: number;
|
|
1998
|
+
/** Whether to normalize output to 0-1 range. */
|
|
1999
|
+
normalize?: boolean;
|
|
2000
|
+
}
|
|
2001
|
+
/**
|
|
2002
|
+
* Result of event-to-signal conversion.
|
|
2003
|
+
*/
|
|
2004
|
+
interface EventSignalResult {
|
|
2005
|
+
/** Signal values. */
|
|
2006
|
+
values: Float32Array;
|
|
2007
|
+
/** Time points in seconds. */
|
|
2008
|
+
times: Float32Array;
|
|
2009
|
+
/** Value range before normalization. */
|
|
2010
|
+
rawRange: {
|
|
2011
|
+
min: number;
|
|
2012
|
+
max: number;
|
|
2013
|
+
};
|
|
2014
|
+
}
|
|
2015
|
+
/**
|
|
2016
|
+
* Count events per window (sliding window approach).
|
|
2017
|
+
*/
|
|
2018
|
+
declare function eventCount(events: DiscreteEvent[], windowSpec: EventWindowSpec, options: EventToSignalOptions): EventSignalResult;
|
|
2019
|
+
/**
|
|
2020
|
+
* Event density: events per second in each window.
|
|
2021
|
+
*/
|
|
2022
|
+
declare function eventDensity(events: DiscreteEvent[], windowSpec: EventWindowSpec, options: EventToSignalOptions): EventSignalResult;
|
|
2023
|
+
/**
|
|
2024
|
+
* Weighted sum of events per window.
|
|
2025
|
+
*/
|
|
2026
|
+
declare function weightedSum(events: DiscreteEvent[], windowSpec: EventWindowSpec, options: EventToSignalOptions): EventSignalResult;
|
|
2027
|
+
/**
|
|
2028
|
+
* Weighted mean of events per window.
|
|
2029
|
+
*/
|
|
2030
|
+
declare function weightedMean(events: DiscreteEvent[], windowSpec: EventWindowSpec, options: EventToSignalOptions): EventSignalResult;
|
|
2031
|
+
/**
|
|
2032
|
+
* Generate continuous envelope from events.
|
|
2033
|
+
* Each event contributes an envelope shape to the output.
|
|
2034
|
+
*/
|
|
2035
|
+
declare function eventEnvelope(events: DiscreteEvent[], shape: EnvelopeShape, options: EventToSignalOptions): EventSignalResult;
|
|
2036
|
+
/**
|
|
2037
|
+
* Convert events to signal using specified reducer.
|
|
2038
|
+
*/
|
|
2039
|
+
type EventReducer = "eventCount" | "eventDensity" | "weightedSum" | "weightedMean" | "envelope";
|
|
2040
|
+
interface EventToSignalParams {
|
|
2041
|
+
/** Reducer algorithm. */
|
|
2042
|
+
reducer: EventReducer;
|
|
2043
|
+
/** Window spec for count/density/sum/mean reducers. */
|
|
2044
|
+
window?: EventWindowSpec;
|
|
2045
|
+
/** Envelope shape for envelope reducer. */
|
|
2046
|
+
envelopeShape?: EnvelopeShape;
|
|
2047
|
+
}
|
|
2048
|
+
declare function eventsToSignal(events: DiscreteEvent[], params: EventToSignalParams, options: EventToSignalOptions): EventSignalResult;
|
|
2049
|
+
|
|
2050
|
+
/**
|
|
2051
|
+
* Signal Transforms
|
|
2052
|
+
*
|
|
2053
|
+
* Transform chain implementation for derived signals.
|
|
2054
|
+
* All transforms are pure functions that operate on Float32Array values.
|
|
2055
|
+
*
|
|
2056
|
+
* Transform categories:
|
|
2057
|
+
* - Smooth: movingAverage, exponential, gaussian
|
|
2058
|
+
* - Normalize: minMax, robust, zScore
|
|
2059
|
+
* - Scale: linear scaling with offset
|
|
2060
|
+
* - Polarity: signed, magnitude
|
|
2061
|
+
* - Clamp: min/max bounds
|
|
2062
|
+
* - Remap: input range to output range with curve
|
|
2063
|
+
*/
|
|
2064
|
+
/**
|
|
2065
|
+
* Base transform type.
|
|
2066
|
+
*/
|
|
2067
|
+
interface TransformBase {
|
|
2068
|
+
kind: string;
|
|
2069
|
+
}
|
|
2070
|
+
/**
|
|
2071
|
+
* Smooth with moving average.
|
|
2072
|
+
*/
|
|
2073
|
+
interface TransformSmoothMovingAverage extends TransformBase {
|
|
2074
|
+
kind: "smooth";
|
|
2075
|
+
method: "movingAverage";
|
|
2076
|
+
windowMs: number;
|
|
2077
|
+
}
|
|
2078
|
+
/**
|
|
2079
|
+
* Smooth with exponential filter.
|
|
2080
|
+
*/
|
|
2081
|
+
interface TransformSmoothExponential extends TransformBase {
|
|
2082
|
+
kind: "smooth";
|
|
2083
|
+
method: "exponential";
|
|
2084
|
+
timeConstantMs: number;
|
|
2085
|
+
}
|
|
2086
|
+
/**
|
|
2087
|
+
* Smooth with Gaussian kernel.
|
|
2088
|
+
*/
|
|
2089
|
+
interface TransformSmoothGaussian extends TransformBase {
|
|
2090
|
+
kind: "smooth";
|
|
2091
|
+
method: "gaussian";
|
|
2092
|
+
windowMs: number;
|
|
2093
|
+
}
|
|
2094
|
+
/**
|
|
2095
|
+
* All smoothing transform types.
|
|
2096
|
+
*/
|
|
2097
|
+
type TransformSmooth = TransformSmoothMovingAverage | TransformSmoothExponential | TransformSmoothGaussian;
|
|
2098
|
+
/**
|
|
2099
|
+
* Normalize to 0-1 range using min/max.
|
|
2100
|
+
*/
|
|
2101
|
+
interface TransformNormalizeMinMax extends TransformBase {
|
|
2102
|
+
kind: "normalize";
|
|
2103
|
+
method: "minMax";
|
|
2104
|
+
targetMin?: number;
|
|
2105
|
+
targetMax?: number;
|
|
2106
|
+
}
|
|
2107
|
+
/**
|
|
2108
|
+
* Normalize using robust percentile range.
|
|
2109
|
+
*/
|
|
2110
|
+
interface TransformNormalizeRobust extends TransformBase {
|
|
2111
|
+
kind: "normalize";
|
|
2112
|
+
method: "robust";
|
|
2113
|
+
percentileLow?: number;
|
|
2114
|
+
percentileHigh?: number;
|
|
2115
|
+
targetMin?: number;
|
|
2116
|
+
targetMax?: number;
|
|
2117
|
+
}
|
|
2118
|
+
/**
|
|
2119
|
+
* Normalize using z-score (mean and std dev).
|
|
2120
|
+
*/
|
|
2121
|
+
interface TransformNormalizeZScore extends TransformBase {
|
|
2122
|
+
kind: "normalize";
|
|
2123
|
+
method: "zScore";
|
|
2124
|
+
}
|
|
2125
|
+
/**
|
|
2126
|
+
* All normalization transform types.
|
|
2127
|
+
*/
|
|
2128
|
+
type TransformNormalize = TransformNormalizeMinMax | TransformNormalizeRobust | TransformNormalizeZScore;
|
|
2129
|
+
/**
|
|
2130
|
+
* Linear scale and offset.
|
|
2131
|
+
*/
|
|
2132
|
+
interface TransformScale extends TransformBase {
|
|
2133
|
+
kind: "scale";
|
|
2134
|
+
scale: number;
|
|
2135
|
+
offset: number;
|
|
2136
|
+
}
|
|
2137
|
+
/**
|
|
2138
|
+
* Polarity mode.
|
|
2139
|
+
*/
|
|
2140
|
+
interface TransformPolarity extends TransformBase {
|
|
2141
|
+
kind: "polarity";
|
|
2142
|
+
mode: "signed" | "magnitude";
|
|
2143
|
+
}
|
|
2144
|
+
/**
|
|
2145
|
+
* Clamp to bounds.
|
|
2146
|
+
*/
|
|
2147
|
+
interface TransformClamp extends TransformBase {
|
|
2148
|
+
kind: "clamp";
|
|
2149
|
+
min?: number;
|
|
2150
|
+
max?: number;
|
|
2151
|
+
}
|
|
2152
|
+
/**
|
|
2153
|
+
* Remap from input range to output range.
|
|
2154
|
+
*/
|
|
2155
|
+
interface TransformRemap extends TransformBase {
|
|
2156
|
+
kind: "remap";
|
|
2157
|
+
inputMin: number;
|
|
2158
|
+
inputMax: number;
|
|
2159
|
+
outputMin: number;
|
|
2160
|
+
outputMax: number;
|
|
2161
|
+
curve?: "linear" | "ease" | "easeIn" | "easeOut";
|
|
2162
|
+
}
|
|
2163
|
+
/**
|
|
2164
|
+
* Union of all transform step types.
|
|
2165
|
+
*/
|
|
2166
|
+
type TransformStep = TransformSmooth | TransformNormalize | TransformScale | TransformPolarity | TransformClamp | TransformRemap;
|
|
2167
|
+
/**
|
|
2168
|
+
* A chain of transforms to apply in sequence.
|
|
2169
|
+
*/
|
|
2170
|
+
type TransformChain = TransformStep[];
|
|
2171
|
+
/**
|
|
2172
|
+
* Context for transform chain execution.
|
|
2173
|
+
*/
|
|
2174
|
+
interface TransformContext {
|
|
2175
|
+
/** Sample rate of the signal (samples per second). */
|
|
2176
|
+
sampleRate: number;
|
|
2177
|
+
/** Time points in seconds (optional, for time-aware transforms). */
|
|
2178
|
+
times?: Float32Array;
|
|
2179
|
+
}
|
|
2180
|
+
/**
|
|
2181
|
+
* Apply a single transform step.
|
|
2182
|
+
*/
|
|
2183
|
+
declare function applyTransformStep(values: Float32Array, step: TransformStep, context: TransformContext): Float32Array;
|
|
2184
|
+
/**
|
|
2185
|
+
* Apply a chain of transforms to a signal.
|
|
2186
|
+
*/
|
|
2187
|
+
declare function applyTransformChain(values: Float32Array, chain: TransformChain, context: TransformContext): Float32Array;
|
|
2188
|
+
/**
|
|
2189
|
+
* Get human-readable label for a transform step.
|
|
2190
|
+
*/
|
|
2191
|
+
declare function getTransformLabel(step: TransformStep): string;
|
|
2192
|
+
/**
|
|
2193
|
+
* Create a default transform step for a kind.
|
|
2194
|
+
*/
|
|
2195
|
+
declare function createDefaultTransform(kind: TransformStep["kind"]): TransformStep | null;
|
|
2196
|
+
|
|
135
2197
|
type NormaliseForWaveformOptions = {
|
|
136
2198
|
min?: number;
|
|
137
2199
|
max?: number;
|
|
@@ -189,6 +2251,19 @@ declare function spectrogramToDb(magnitudes2d: Spectrogram2D, options?: Spectrog
|
|
|
189
2251
|
*/
|
|
190
2252
|
declare function clampDb(db2d: Spectrogram2D, minDb: number, maxDb: number): Spectrogram2D;
|
|
191
2253
|
|
|
2254
|
+
/**
|
|
2255
|
+
* Resample audio using linear interpolation.
|
|
2256
|
+
*
|
|
2257
|
+
* This is a simple, fast resampling algorithm suitable for MIR analysis
|
|
2258
|
+
* where perfect reconstruction is not critical.
|
|
2259
|
+
*
|
|
2260
|
+
* @param samples - Input audio samples
|
|
2261
|
+
* @param fromRate - Original sample rate (Hz)
|
|
2262
|
+
* @param toRate - Target sample rate (Hz)
|
|
2263
|
+
* @returns Resampled audio samples
|
|
2264
|
+
*/
|
|
2265
|
+
declare function resample(samples: Float32Array, fromRate: number, toRate: number): Float32Array;
|
|
2266
|
+
|
|
192
2267
|
type MinMax = {
|
|
193
2268
|
min: number;
|
|
194
2269
|
max: number;
|
|
@@ -447,4 +2522,4 @@ type AudioBufferLike = {
|
|
|
447
2522
|
*/
|
|
448
2523
|
declare function helloMir(name?: string): string;
|
|
449
2524
|
|
|
450
|
-
export { type AudioBufferLike, type DeltaOptions, type Features2D, type HpssOptions, MIR_VERSION, type MelConfig, type MelSpectrogram, type MfccOptions, type MfccResult, type MinMax, type MirFingerprintV1, type MirFingerprintVectorWeights, MirGPU, type MirRefinementCandidateLabelV1, type MirSearchCandidate, type MirSearchCurveKindV1, type MirSearchGuidedOptionsV1, type MirSearchOptionsV1, type MirSearchResultV1, type MirSearchResultV1Guided, type MirVersion, type OnsetEnvelope, type OnsetEnvelopeGpuResult, type OnsetEnvelopeOptions, type PeakPickEvent, type PeakPickOptions, Spectrogram, type Spectrogram2D, type SpectrogramLike2D, type SpectrogramToDbOptions, clampDb, delta, deltaDelta, fingerprintToVectorV1, fingerprintV1, helloMir, hpss, melSpectrogram, mfcc, minMax, normaliseForWaveform, onsetEnvelopeFromMel, onsetEnvelopeFromMelGpu, onsetEnvelopeFromSpectrogram, peakPick, searchTrackV1, searchTrackV1Guided, similarityFingerprintV1, spectralCentroid, spectralFlux, spectrogramToDb };
|
|
2525
|
+
export { type ActivityConfig, type ActivityDiagnostics, type ActivitySignal, type AdaptivePeakPickingResult, type AmplitudeEnvelopeConfig, type AmplitudeEnvelopeResult, type AudioBufferLike, type BandBeatCandidatesOptions, BandCqt1DResult, type BandCqtBatchRequest, type BandCqtBatchResult, BandCqtFunctionId, type BandCqtOptions, BandEventFunctionId, type BandEventsBatchRequest, type BandEventsBatchResult, BandEventsResult, type BandMaskOptions, BandMir1DResult, type BandMirBatchRequest, type BandMirBatchResult, BandMirFunctionId, type BandMirOptions, type BandOnsetPeaksOptions, BandProposalConfig, type BandProposalOptions, BandProposalResult, BeatCandidate, type BeatCandidatesOptions, type BeatCandidatesOutput, BeatGrid, BeatPosition, type BeatSalienceSignal, type BinGateConfig, type BinRangeOptions, CQT_DEFAULTS, CqtConfig, type CqtOptions, CqtSignalId, CqtSignalResult, CqtSpectrogram, DEFAULT_PEAK_PICKING_PARAMS, type DeltaOptions, type DiscreteEvent, type EnvelopeMode, type EnvelopeShape, type EventReducer, type EventSignalResult, type EventToSignalOptions, type EventToSignalParams, type EventWindowSpec, type Features2D, FrequencyBand, FrequencyBandStructure, FrequencyBoundsAtTime, FrequencyKeyframe, FrequencySegment, type HpssOptions, type HysteresisGateParams, MIR_VERSION, type MaskedCqtSpectrogram, type MaskedSpectrogram, type MelConfig, type MelConversionConfig, type MelSpectrogram, type MfccOptions, type MfccResult, type MinMax, type MirFingerprintV1, type MirFingerprintVectorWeights, MirGPU, type MirRefinementCandidateLabelV1, MirRunMeta, type MirSearchCandidate, type MirSearchCurveKindV1, type MirSearchGuidedOptionsV1, type MirSearchOptionsV1, type MirSearchResultV1, type MirSearchResultV1Guided, type MirVersion, MusicalTimeSegment, MusicalTimeStructure, type OnsetDiagnostics, type OnsetEnvelope, type OnsetEnvelopeGpuResult, type OnsetEnvelopeOptions, type OnsetEnvelopeResult, type OnsetStrengthOptions, type PeakPickEvent, type PeakPickOptions, type PeakPickingParams, type PeakPickingResult, PhaseAlignmentConfig, PhaseHypothesis, type PitchActivityOptions, type PitchConfig, type PitchResult, type PolarityMode, type ReductionAlgorithmId, type ReductionInput, type ReductionOptions, type ReductionResult, type SilenceGateConfig, type SilenceGateResult, type SpectralFluxOptions, Spectrogram, type Spectrogram2D, type SpectrogramLike2D, type SpectrogramToDbOptions, type StabilizationMode, type StabilizationOptions, type TempoHypothesesOptions, type TempoHypothesesOutput, TempoHypothesis, type TransformChain, type TransformClamp, type TransformContext, type TransformNormalize, type TransformNormalizeMinMax, type TransformNormalizeRobust, type TransformNormalizeZScore, type TransformPolarity, type TransformRemap, type TransformScale, type TransformSmooth, type TransformSmoothExponential, type TransformSmoothGaussian, type TransformSmoothMovingAverage, type TransformStep, addBandToStructure, allFrequencyBoundsAt, amplitudeEnvelope, applyActivityGating, applyBandMaskToCqt, applyBandMaskToSpectrogram, applyHysteresisGate, applyPolarity, applyTransformChain, applyTransformStep, bandAmplitudeEnvelope, bandBeatCandidates, bandCqtBassPitchMotion, bandCqtHarmonicEnergy, bandCqtTonalStability, bandOnsetPeaks, bandOnsetStrength, bandSpectralCentroid, bandSpectralFlux, bandsActiveAt, bassPitchMotion, beatSalienceFromMel, binToHz, buildActivityMask, clampDb, computeActivityFromAudio, computeActivityFromMel, computeActivityFromSpectrogram, computeAdaptiveThreshold, computeAllCqtSignals, computeBandMaskAtTime, computeBeatPosition, computeBeatPositionFromStructure, computeCqt, computeCqtSignal, computeFrameAmplitude, computeFrameEnergy, computeFrameEnergyFromMel, computeFrameEnergyFromSpectrogram, computeLocalStats, computePercentiles, computePhaseHypotheses, computeSilenceGating, cqtBinToHz, cqtSpectrogram, createBandStructure, createConstantBand, createDefaultTransform, createMusicalTimeStructure, createSectionedBand, createSegmentFromGrid, createStandardBands, delta, deltaDelta, detectBeatCandidates, estimateNoiseFloor, eventCount, eventDensity, eventEnvelope, eventsToSignal, featureIndexToHz, findBandById, findSegmentAtTime, fingerprintToVectorV1, fingerprintV1, frequencyBoundsAt, generateBandId, generateBandProposals, generateBeatTimes, generateSegmentBeatTimes, generateSegmentId, generateTempoHypotheses, getBandCqtFunctionLabel, getBandEventFunctionLabel, getBandMirFunctionLabel, getCqtBinFrequencies, getNumBins, getNumOctaves, getReductionAlgorithmDescription, getReductionAlgorithmLabel, getTransformLabel, harmonicEnergy, helloMir, hpss, hzToBin, hzToCqtBin, hzToFeatureIndex, hzToMel, interpolateActivity, keyframesFromBand, melSpectrogram, melToHz, mergeAdjacentSegments, mfcc, minMax, moveKeyframeTime, normaliseForWaveform, onsetEnvelopeFromMel, onsetEnvelopeFromMelGpu, onsetEnvelopeFromSpectrogram, peakPick, pickPeaks, pickPeaksAdaptive, pitchConfidence, pitchF0, reduce2DToSignal, removeBandFromStructure, removeKeyframe, resample, runBandCqtBatch, runBandEventsBatch, runBandMirBatch, searchTrackV1, searchTrackV1Guided, segmentsFromKeyframes, similarityFingerprintV1, sortBands, sortFrequencySegments, sortSegments, spectralCentroid, spectralFlux, spectrogramToDb, splitBandSegmentAt, splitSegment, stabilizeSignal, tonalStability, touchStructure, updateBandInStructure, updateKeyframe, validateBandStructure, validateFrequencyBand, validateFrequencySegments, validateSegments, weightedMean, weightedSum, withBinGateDefaults, withCqtDefaults, withSilenceGateDefaults };
|