@octoseq/mir 0.1.0-main.ef9b77a → 0.1.0-main.f485112

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.
@@ -158,6 +158,212 @@ async function gpuOnsetEnvelopeFromMelFlat(gpu, input) {
158
158
  };
159
159
  }
160
160
 
161
+ // src/dsp/silenceGating.ts
162
+ var DEFAULT_SILENCE_GATE_CONFIG = {
163
+ enabled: false,
164
+ // Disabled by default to avoid breaking existing behavior
165
+ energyPercentile: 10,
166
+ enterMargin: 6,
167
+ exitMargin: 3,
168
+ hangoverMs: 50,
169
+ minActiveMs: 0,
170
+ postSilenceSuppressMs: 50
171
+ };
172
+ var DEFAULT_BIN_GATE_CONFIG = {
173
+ enabled: true,
174
+ binFloorRel: 0.05
175
+ };
176
+ function withSilenceGateDefaults(config) {
177
+ return {
178
+ enabled: config?.enabled ?? DEFAULT_SILENCE_GATE_CONFIG.enabled,
179
+ energyPercentile: config?.energyPercentile ?? DEFAULT_SILENCE_GATE_CONFIG.energyPercentile,
180
+ enterMargin: config?.enterMargin ?? DEFAULT_SILENCE_GATE_CONFIG.enterMargin,
181
+ exitMargin: config?.exitMargin ?? DEFAULT_SILENCE_GATE_CONFIG.exitMargin,
182
+ hangoverMs: config?.hangoverMs ?? DEFAULT_SILENCE_GATE_CONFIG.hangoverMs,
183
+ minActiveMs: config?.minActiveMs ?? DEFAULT_SILENCE_GATE_CONFIG.minActiveMs,
184
+ postSilenceSuppressMs: config?.postSilenceSuppressMs ?? DEFAULT_SILENCE_GATE_CONFIG.postSilenceSuppressMs
185
+ };
186
+ }
187
+ function withBinGateDefaults(config) {
188
+ return {
189
+ enabled: config?.enabled ?? DEFAULT_BIN_GATE_CONFIG.enabled,
190
+ binFloorRel: config?.binFloorRel ?? DEFAULT_BIN_GATE_CONFIG.binFloorRel
191
+ };
192
+ }
193
+ function computeFrameEnergyFromMel(melBands) {
194
+ const nFrames = melBands.length;
195
+ const energy = new Float32Array(nFrames);
196
+ for (let t = 0; t < nFrames; t++) {
197
+ const bands = melBands[t];
198
+ if (!bands || bands.length === 0) {
199
+ energy[t] = -100;
200
+ continue;
201
+ }
202
+ let sum = 0;
203
+ for (let m = 0; m < bands.length; m++) {
204
+ sum += bands[m] ?? -100;
205
+ }
206
+ energy[t] = sum / bands.length;
207
+ }
208
+ return energy;
209
+ }
210
+ function computeFrameEnergyFromSpectrogram(magnitudes, usePower = false) {
211
+ const nFrames = magnitudes.length;
212
+ const energy = new Float32Array(nFrames);
213
+ for (let t = 0; t < nFrames; t++) {
214
+ const mags = magnitudes[t];
215
+ if (!mags || mags.length === 0) {
216
+ energy[t] = 0;
217
+ continue;
218
+ }
219
+ let sum = 0;
220
+ for (let k = 0; k < mags.length; k++) {
221
+ const m = mags[k] ?? 0;
222
+ sum += usePower ? m * m : m;
223
+ }
224
+ energy[t] = sum / mags.length;
225
+ }
226
+ return energy;
227
+ }
228
+ function computePercentile(values, percentile) {
229
+ if (values.length === 0) return 0;
230
+ const sorted = Float32Array.from(values).sort((a, b) => a - b);
231
+ const p = Math.max(0, Math.min(100, percentile));
232
+ const idx = p / 100 * (sorted.length - 1);
233
+ const lower = Math.floor(idx);
234
+ const upper = Math.ceil(idx);
235
+ if (lower === upper) {
236
+ return sorted[lower] ?? 0;
237
+ }
238
+ const frac = idx - lower;
239
+ const lowVal = sorted[lower] ?? 0;
240
+ const highVal = sorted[upper] ?? 0;
241
+ return lowVal + frac * (highVal - lowVal);
242
+ }
243
+ function estimateNoiseFloor(frameEnergy, percentile) {
244
+ return computePercentile(frameEnergy, percentile);
245
+ }
246
+ function buildActivityMask(frameEnergy, enterThreshold, exitThreshold, hangoverFrames) {
247
+ const nFrames = frameEnergy.length;
248
+ const mask = new Uint8Array(nFrames);
249
+ let isActive = false;
250
+ let hangoverRemaining = 0;
251
+ for (let t = 0; t < nFrames; t++) {
252
+ const e = frameEnergy[t] ?? 0;
253
+ if (!isActive) {
254
+ if (e >= enterThreshold) {
255
+ isActive = true;
256
+ hangoverRemaining = hangoverFrames;
257
+ mask[t] = 1;
258
+ } else {
259
+ mask[t] = 0;
260
+ }
261
+ } else {
262
+ if (e >= exitThreshold) {
263
+ hangoverRemaining = hangoverFrames;
264
+ mask[t] = 1;
265
+ } else if (hangoverRemaining > 0) {
266
+ hangoverRemaining--;
267
+ mask[t] = 1;
268
+ } else {
269
+ isActive = false;
270
+ mask[t] = 0;
271
+ }
272
+ }
273
+ }
274
+ return mask;
275
+ }
276
+ function buildSuppressionMask(activityMask, suppressFrames) {
277
+ const nFrames = activityMask.length;
278
+ const suppress = new Uint8Array(nFrames);
279
+ let suppressRemaining = 0;
280
+ let wasActive = false;
281
+ for (let t = 0; t < nFrames; t++) {
282
+ const isActive = (activityMask[t] ?? 0) === 1;
283
+ if (isActive && !wasActive) {
284
+ suppressRemaining = suppressFrames;
285
+ }
286
+ if (isActive && suppressRemaining > 0) {
287
+ suppress[t] = 1;
288
+ suppressRemaining--;
289
+ } else {
290
+ suppress[t] = 0;
291
+ }
292
+ wasActive = isActive;
293
+ }
294
+ return suppress;
295
+ }
296
+ function applyMinActiveDuration(activityMask, minActiveFrames) {
297
+ if (minActiveFrames <= 1) return;
298
+ const nFrames = activityMask.length;
299
+ const regions = [];
300
+ let regionStart = -1;
301
+ for (let t = 0; t <= nFrames; t++) {
302
+ const isActive = t < nFrames && (activityMask[t] ?? 0) === 1;
303
+ if (isActive && regionStart < 0) {
304
+ regionStart = t;
305
+ } else if (!isActive && regionStart >= 0) {
306
+ regions.push({ start: regionStart, end: t });
307
+ regionStart = -1;
308
+ }
309
+ }
310
+ for (const region of regions) {
311
+ const length = region.end - region.start;
312
+ if (length < minActiveFrames) {
313
+ for (let t = region.start; t < region.end; t++) {
314
+ activityMask[t] = 0;
315
+ }
316
+ }
317
+ }
318
+ }
319
+ function computeSilenceGating(frameEnergy, frameDurationSec, config) {
320
+ const cfg = withSilenceGateDefaults(config);
321
+ const nFrames = frameEnergy.length;
322
+ if (!cfg.enabled) {
323
+ return {
324
+ frameEnergy,
325
+ noiseFloor: -Infinity,
326
+ enterThreshold: -Infinity,
327
+ exitThreshold: -Infinity,
328
+ activityMask: new Uint8Array(nFrames).fill(1),
329
+ suppressionMask: new Uint8Array(nFrames)
330
+ // All zeros = no suppression
331
+ };
332
+ }
333
+ const noiseFloor = estimateNoiseFloor(frameEnergy, cfg.energyPercentile);
334
+ const enterThreshold = noiseFloor + cfg.enterMargin;
335
+ const exitThreshold = noiseFloor + cfg.exitMargin;
336
+ const hangoverFrames = Math.max(0, Math.round(cfg.hangoverMs / 1e3 / frameDurationSec));
337
+ const suppressFrames = Math.max(0, Math.round(cfg.postSilenceSuppressMs / 1e3 / frameDurationSec));
338
+ const minActiveFrames = Math.max(0, Math.round(cfg.minActiveMs / 1e3 / frameDurationSec));
339
+ const activityMask = buildActivityMask(frameEnergy, enterThreshold, exitThreshold, hangoverFrames);
340
+ if (minActiveFrames > 1) {
341
+ applyMinActiveDuration(activityMask, minActiveFrames);
342
+ }
343
+ const suppressionMask = buildSuppressionMask(activityMask, suppressFrames);
344
+ return {
345
+ frameEnergy,
346
+ noiseFloor,
347
+ enterThreshold,
348
+ exitThreshold,
349
+ activityMask,
350
+ suppressionMask
351
+ };
352
+ }
353
+ function applySilenceGating(novelty, activityMask, suppressionMask) {
354
+ const nFrames = novelty.length;
355
+ for (let t = 0; t < nFrames; t++) {
356
+ const isActive = (activityMask[t] ?? 0) === 1;
357
+ const isSuppressed = (suppressionMask[t] ?? 0) === 1;
358
+ if (!isActive || isSuppressed) {
359
+ novelty[t] = 0;
360
+ }
361
+ }
362
+ }
363
+ function computeBinFloor(frameEnergy, binFloorRel) {
364
+ return frameEnergy * binFloorRel;
365
+ }
366
+
161
367
  // src/dsp/onset.ts
162
368
  function movingAverage(values, windowFrames) {
163
369
  if (windowFrames <= 1) return values;
@@ -178,22 +384,26 @@ function movingAverage(values, windowFrames) {
178
384
  }
179
385
  return out;
180
386
  }
181
- function defaultOptions(opts) {
387
+ function resolveOptions(opts) {
182
388
  return {
183
389
  useLog: opts?.useLog ?? false,
184
390
  smoothMs: opts?.smoothMs ?? 30,
185
- diffMethod: opts?.diffMethod ?? "rectified"
391
+ diffMethod: opts?.diffMethod ?? "rectified",
392
+ silenceGate: withSilenceGateDefaults(opts?.silenceGate),
393
+ binGate: withBinGateDefaults(opts?.binGate),
394
+ returnDiagnostics: opts?.returnDiagnostics ?? false
186
395
  };
187
396
  }
188
397
  function logCompress(x) {
189
398
  return Math.log1p(Math.max(0, x));
190
399
  }
191
400
  function onsetEnvelopeFromSpectrogram(spec, options) {
192
- const opts = defaultOptions(options);
401
+ const opts = resolveOptions(options);
193
402
  const nFrames = spec.times.length;
194
- const out = new Float32Array(nFrames);
195
403
  const nBins = (spec.fftSize >>> 1) + 1;
404
+ const out = new Float32Array(nFrames);
196
405
  out[0] = 0;
406
+ const frameEnergies = opts.binGate.enabled ? computeFrameEnergyFromSpectrogram(spec.magnitudes, false) : null;
197
407
  for (let t = 1; t < nFrames; t++) {
198
408
  const cur = spec.magnitudes[t];
199
409
  const prev = spec.magnitudes[t - 1];
@@ -201,35 +411,65 @@ function onsetEnvelopeFromSpectrogram(spec, options) {
201
411
  out[t] = 0;
202
412
  continue;
203
413
  }
414
+ const binFloor = frameEnergies && opts.binGate.enabled ? computeBinFloor(frameEnergies[t] ?? 0, opts.binGate.binFloorRel) : 0;
204
415
  let sum = 0;
416
+ let validBins = 0;
205
417
  for (let k = 0; k < nBins; k++) {
206
418
  let a = cur[k] ?? 0;
207
419
  let b = prev[k] ?? 0;
420
+ if (opts.binGate.enabled && a < binFloor && b < binFloor) {
421
+ continue;
422
+ }
208
423
  if (opts.useLog) {
209
424
  a = logCompress(a);
210
425
  b = logCompress(b);
211
426
  }
212
427
  const d = a - b;
213
428
  sum += opts.diffMethod === "abs" ? Math.abs(d) : Math.max(0, d);
429
+ validBins++;
214
430
  }
215
- out[t] = nBins > 0 ? sum / nBins : 0;
431
+ out[t] = validBins > 0 ? sum / validBins : 0;
432
+ }
433
+ const linearEnergy = computeFrameEnergyFromSpectrogram(spec.magnitudes, false);
434
+ const frameEnergy = new Float32Array(nFrames);
435
+ const eps = 1e-12;
436
+ for (let t = 0; t < nFrames; t++) {
437
+ frameEnergy[t] = Math.log10(eps + (linearEnergy[t] ?? 0));
216
438
  }
439
+ const frameDurationSec = nFrames >= 2 ? (spec.times[1] ?? 0) - (spec.times[0] ?? 0) : 0.01;
440
+ const gating = computeSilenceGating(frameEnergy, frameDurationSec, opts.silenceGate);
441
+ const rawNovelty = opts.returnDiagnostics ? Float32Array.from(out) : void 0;
442
+ if (opts.silenceGate.enabled) {
443
+ applySilenceGating(out, gating.activityMask, gating.suppressionMask);
444
+ }
445
+ let values = out;
217
446
  const smoothMs = opts.smoothMs;
218
447
  if (smoothMs > 0 && nFrames >= 2) {
219
- const dt = (spec.times[1] ?? 0) - (spec.times[0] ?? 0);
448
+ const dt = frameDurationSec;
220
449
  const windowFrames = Math.max(1, Math.round(smoothMs / 1e3 / Math.max(1e-9, dt)));
221
- return {
222
- times: spec.times,
223
- values: movingAverage(out, windowFrames | 1)
450
+ const smoothed = movingAverage(out, windowFrames | 1);
451
+ values = new Float32Array(smoothed);
452
+ }
453
+ const result = { times: spec.times, values };
454
+ if (opts.returnDiagnostics && rawNovelty) {
455
+ result.diagnostics = {
456
+ frameEnergy,
457
+ noiseFloor: gating.noiseFloor,
458
+ enterThreshold: gating.enterThreshold,
459
+ exitThreshold: gating.exitThreshold,
460
+ activityMask: gating.activityMask,
461
+ suppressionMask: gating.suppressionMask,
462
+ rawNovelty
224
463
  };
225
464
  }
226
- return { times: spec.times, values: out };
465
+ return result;
227
466
  }
228
467
  function onsetEnvelopeFromMel(mel, options) {
229
- const opts = defaultOptions(options);
468
+ const opts = resolveOptions(options);
230
469
  const nFrames = mel.times.length;
231
470
  const out = new Float32Array(nFrames);
232
471
  out[0] = 0;
472
+ const melFrameEnergies = opts.binGate.enabled ? computeFrameEnergyFromMel(mel.melBands) : null;
233
473
  for (let t = 1; t < nFrames; t++) {
234
474
  const cur = mel.melBands[t];
235
475
  const prev = mel.melBands[t - 1];
@@ -238,29 +478,58 @@ function onsetEnvelopeFromMel(mel, options) {
238
478
  continue;
239
479
  }
240
480
  const nBands = cur.length;
481
+ const frameEnergyLinear = melFrameEnergies ? Math.pow(10, melFrameEnergies[t] ?? -100) : 0;
482
+ const binFloorLinear = opts.binGate.enabled ? computeBinFloor(frameEnergyLinear, opts.binGate.binFloorRel) : 0;
241
483
  let sum = 0;
484
+ let validBands = 0;
242
485
  for (let m = 0; m < nBands; m++) {
243
486
  let a = cur[m] ?? 0;
244
487
  let b = prev[m] ?? 0;
488
+ if (opts.binGate.enabled) {
489
+ const aLinear = Math.pow(10, a);
490
+ const bLinear = Math.pow(10, b);
491
+ if (aLinear < binFloorLinear && bLinear < binFloorLinear) {
492
+ continue;
493
+ }
494
+ }
245
495
  if (opts.useLog) {
246
496
  a = logCompress(a);
247
497
  b = logCompress(b);
248
498
  }
249
499
  const d = a - b;
250
500
  sum += opts.diffMethod === "abs" ? Math.abs(d) : Math.max(0, d);
501
+ validBands++;
251
502
  }
252
- out[t] = nBands > 0 ? sum / nBands : 0;
503
+ out[t] = validBands > 0 ? sum / validBands : 0;
504
+ }
505
+ const frameEnergy = computeFrameEnergyFromMel(mel.melBands);
506
+ const frameDurationSec = nFrames >= 2 ? (mel.times[1] ?? 0) - (mel.times[0] ?? 0) : 0.01;
507
+ const gating = computeSilenceGating(frameEnergy, frameDurationSec, opts.silenceGate);
508
+ const rawNovelty = opts.returnDiagnostics ? Float32Array.from(out) : void 0;
509
+ if (opts.silenceGate.enabled) {
510
+ applySilenceGating(out, gating.activityMask, gating.suppressionMask);
253
511
  }
512
+ let values = out;
254
513
  const smoothMs = opts.smoothMs;
255
514
  if (smoothMs > 0 && nFrames >= 2) {
256
- const dt = (mel.times[1] ?? 0) - (mel.times[0] ?? 0);
515
+ const dt = frameDurationSec;
257
516
  const windowFrames = Math.max(1, Math.round(smoothMs / 1e3 / Math.max(1e-9, dt)));
258
- return {
259
- times: mel.times,
260
- values: movingAverage(out, windowFrames | 1)
517
+ const smoothed = movingAverage(out, windowFrames | 1);
518
+ values = new Float32Array(smoothed);
519
+ }
520
+ const result = { times: mel.times, values };
521
+ if (opts.returnDiagnostics && rawNovelty) {
522
+ result.diagnostics = {
523
+ frameEnergy,
524
+ noiseFloor: gating.noiseFloor,
525
+ enterThreshold: gating.enterThreshold,
526
+ exitThreshold: gating.exitThreshold,
527
+ activityMask: gating.activityMask,
528
+ suppressionMask: gating.suppressionMask,
529
+ rawNovelty
261
530
  };
262
531
  }
263
- return { times: mel.times, values: out };
532
+ return result;
264
533
  }
265
534
  async function onsetEnvelopeFromMelGpu(mel, gpu, options) {
266
535
  const nFrames = mel.times.length;
@@ -272,29 +541,87 @@ async function onsetEnvelopeFromMelGpu(mel, gpu, options) {
272
541
  melFlat.set(row, t * nMels);
273
542
  }
274
543
  const diffMethod = options?.diffMethod ?? "rectified";
544
+ const silenceGateConfig = withSilenceGateDefaults(options?.silenceGate);
545
+ const returnDiagnostics = options?.returnDiagnostics ?? false;
546
+ const smoothMs = options?.smoothMs ?? 30;
275
547
  const { value, timing } = await gpuOnsetEnvelopeFromMelFlat(gpu, {
276
548
  nFrames,
277
549
  nMels,
278
550
  melFlat,
279
551
  diffMethod
280
552
  });
281
- return {
553
+ const out = Float32Array.from(value.out);
554
+ const rawNovelty = returnDiagnostics ? Float32Array.from(out) : void 0;
555
+ const frameEnergy = computeFrameEnergyFromMel(mel.melBands);
556
+ const frameDurationSec = nFrames >= 2 ? (mel.times[1] ?? 0) - (mel.times[0] ?? 0) : 0.01;
557
+ const gating = computeSilenceGating(frameEnergy, frameDurationSec, silenceGateConfig);
558
+ if (silenceGateConfig.enabled) {
559
+ applySilenceGating(out, gating.activityMask, gating.suppressionMask);
560
+ }
561
+ let values = out;
562
+ if (smoothMs > 0 && nFrames >= 2) {
563
+ const dt = frameDurationSec;
564
+ const windowFrames = Math.max(1, Math.round(smoothMs / 1e3 / Math.max(1e-9, dt)));
565
+ const smoothed = movingAverage(out, windowFrames | 1);
566
+ values = new Float32Array(smoothed);
567
+ }
568
+ const result = {
282
569
  times: mel.times,
283
- values: value.out,
570
+ values,
284
571
  gpuTimings: { gpuSubmitToReadbackMs: timing.gpuSubmitToReadbackMs }
285
572
  };
573
+ if (returnDiagnostics && rawNovelty) {
574
+ result.diagnostics = {
575
+ frameEnergy,
576
+ noiseFloor: gating.noiseFloor,
577
+ enterThreshold: gating.enterThreshold,
578
+ exitThreshold: gating.exitThreshold,
579
+ activityMask: gating.activityMask,
580
+ suppressionMask: gating.suppressionMask,
581
+ rawNovelty
582
+ };
583
+ }
584
+ return result;
286
585
  }
287
586
 
288
587
  // src/dsp/spectral.ts
289
- function spectralCentroid(spec) {
588
+ function amplitudeEnvelope(samples, sampleRate, config) {
589
+ const hopSize = config?.hopSize ?? 512;
590
+ const windowSize = config?.windowSize ?? hopSize;
591
+ const nFrames = Math.floor((samples.length - windowSize) / hopSize) + 1;
592
+ const times = new Float32Array(nFrames);
593
+ const values = new Float32Array(nFrames);
594
+ for (let t = 0; t < nFrames; t++) {
595
+ const start = t * hopSize;
596
+ const end = Math.min(start + windowSize, samples.length);
597
+ let sumSq = 0;
598
+ for (let i = start; i < end; i++) {
599
+ const s = samples[i] ?? 0;
600
+ sumSq += s * s;
601
+ }
602
+ const rms = Math.sqrt(sumSq / (end - start));
603
+ times[t] = (start + windowSize / 2) / sampleRate;
604
+ values[t] = rms;
605
+ }
606
+ return { times, values };
607
+ }
608
+ function spectralCentroid(spec, options) {
290
609
  const nFrames = spec.times.length;
291
610
  const out = new Float32Array(nFrames);
292
611
  const nBins = (spec.fftSize >>> 1) + 1;
293
612
  const binHz = spec.sampleRate / spec.fftSize;
613
+ const activity = options?.activity;
614
+ const holdBehavior = options?.inactiveBehavior === "hold";
615
+ let lastActiveValue = 0;
294
616
  for (let t = 0; t < nFrames; t++) {
617
+ const isActive = activity ? (activity.isActive[t] ?? 0) === 1 : true;
618
+ if (!isActive) {
619
+ out[t] = holdBehavior ? lastActiveValue : 0;
620
+ continue;
621
+ }
295
622
  const mags = spec.magnitudes[t];
296
623
  if (!mags) {
297
- out[t] = 0;
624
+ out[t] = holdBehavior ? lastActiveValue : 0;
298
625
  continue;
299
626
  }
300
627
  let num = 0;
@@ -305,16 +632,26 @@ function spectralCentroid(spec) {
305
632
  num += f * m;
306
633
  den += m;
307
634
  }
308
- out[t] = den > 0 ? num / den : 0;
635
+ const centroid = den > 0 ? num / den : 0;
636
+ out[t] = centroid;
637
+ lastActiveValue = centroid;
309
638
  }
310
639
  return out;
311
640
  }
312
- function spectralFlux(spec) {
641
+ function spectralFlux(spec, options) {
313
642
  const nFrames = spec.times.length;
314
643
  const out = new Float32Array(nFrames);
315
644
  const nBins = (spec.fftSize >>> 1) + 1;
645
+ const activity = options?.activity;
316
646
  let prev = null;
317
647
  for (let t = 0; t < nFrames; t++) {
648
+ const isActive = activity ? (activity.isActive[t] ?? 0) === 1 : true;
649
+ const isSuppressed = activity ? (activity.suppressMask[t] ?? 0) === 1 : false;
650
+ if (!isActive || isSuppressed) {
651
+ out[t] = 0;
652
+ prev = null;
653
+ continue;
654
+ }
318
655
  const mags = spec.magnitudes[t];
319
656
  if (!mags) {
320
657
  out[t] = 0;
@@ -2013,6 +2350,395 @@ function computeAllCqtSignals(cqt) {
2013
2350
  return results;
2014
2351
  }
2015
2352
 
2353
+ // src/dsp/activity.ts
2354
+ var DEFAULT_ACTIVITY_CONFIG = {
2355
+ energyPercentile: 10,
2356
+ enterMargin: 6,
2357
+ exitMargin: 3,
2358
+ hangoverMs: 50,
2359
+ minActiveMs: 30,
2360
+ smoothMs: 20
2361
+ };
2362
+ function withActivityDefaults(config) {
2363
+ return {
2364
+ energyPercentile: config?.energyPercentile ?? DEFAULT_ACTIVITY_CONFIG.energyPercentile,
2365
+ enterMargin: config?.enterMargin ?? DEFAULT_ACTIVITY_CONFIG.enterMargin,
2366
+ exitMargin: config?.exitMargin ?? DEFAULT_ACTIVITY_CONFIG.exitMargin,
2367
+ hangoverMs: config?.hangoverMs ?? DEFAULT_ACTIVITY_CONFIG.hangoverMs,
2368
+ minActiveMs: config?.minActiveMs ?? DEFAULT_ACTIVITY_CONFIG.minActiveMs,
2369
+ smoothMs: config?.smoothMs ?? DEFAULT_ACTIVITY_CONFIG.smoothMs
2370
+ };
2371
+ }
2372
+ function smoothSignal(values, windowFrames) {
2373
+ if (windowFrames <= 1) return values;
2374
+ const n = values.length;
2375
+ const out = new Float32Array(n);
2376
+ const half = Math.floor(windowFrames / 2);
2377
+ const prefix = new Float64Array(n + 1);
2378
+ prefix[0] = 0;
2379
+ for (let i = 0; i < n; i++) {
2380
+ prefix[i + 1] = (prefix[i] ?? 0) + (values[i] ?? 0);
2381
+ }
2382
+ for (let i = 0; i < n; i++) {
2383
+ const start = Math.max(0, i - half);
2384
+ const end = Math.min(n, i + half + 1);
2385
+ const sum = (prefix[end] ?? 0) - (prefix[start] ?? 0);
2386
+ const count = Math.max(1, end - start);
2387
+ out[i] = sum / count;
2388
+ }
2389
+ return out;
2390
+ }
2391
+ function maskToActivityLevel(mask, smoothFrames) {
2392
+ const n = mask.length;
2393
+ const level = new Float32Array(n);
2394
+ for (let i = 0; i < n; i++) {
2395
+ level[i] = mask[i] ?? 0;
2396
+ }
2397
+ if (smoothFrames > 1) {
2398
+ return smoothSignal(level, smoothFrames);
2399
+ }
2400
+ return level;
2401
+ }
2402
+ function computeActivityFromMel(mel, config) {
2403
+ const cfg = withActivityDefaults(config);
2404
+ const nFrames = mel.times.length;
2405
+ const frameEnergy = computeFrameEnergyFromMel(mel.melBands);
2406
+ const noiseFloor = estimateNoiseFloor(frameEnergy, cfg.energyPercentile);
2407
+ const enterThreshold = noiseFloor + cfg.enterMargin;
2408
+ const exitThreshold = noiseFloor + cfg.exitMargin;
2409
+ const frameDurationSec = nFrames >= 2 ? (mel.times[1] ?? 0) - (mel.times[0] ?? 0) : 0.01;
2410
+ const hangoverFrames = Math.max(0, Math.round(cfg.hangoverMs / 1e3 / frameDurationSec));
2411
+ const minActiveFrames = Math.max(0, Math.round(cfg.minActiveMs / 1e3 / frameDurationSec));
2412
+ const smoothFrames = Math.max(1, Math.round(cfg.smoothMs / 1e3 / frameDurationSec)) | 1;
2413
+ const isActive = buildActivityMask(frameEnergy, enterThreshold, exitThreshold, hangoverFrames);
2414
+ if (minActiveFrames > 1) {
2415
+ applyMinActiveDuration(isActive, minActiveFrames);
2416
+ }
2417
+ const suppressFrames = Math.max(0, Math.round(50 / 1e3 / frameDurationSec));
2418
+ const suppressMask = buildSuppressionMask(isActive, suppressFrames);
2419
+ const activityLevel = maskToActivityLevel(isActive, smoothFrames);
2420
+ return {
2421
+ times: mel.times,
2422
+ activityLevel,
2423
+ isActive,
2424
+ suppressMask,
2425
+ diagnostics: {
2426
+ frameEnergy,
2427
+ noiseFloor,
2428
+ enterThreshold,
2429
+ exitThreshold
2430
+ }
2431
+ };
2432
+ }
2433
+ function computeActivityFromSpectrogram(spec, config) {
2434
+ const cfg = withActivityDefaults(config);
2435
+ const nFrames = spec.times.length;
2436
+ const linearEnergy = computeFrameEnergyFromSpectrogram(spec.magnitudes, false);
2437
+ const frameEnergy = new Float32Array(nFrames);
2438
+ const eps = 1e-12;
2439
+ for (let t = 0; t < nFrames; t++) {
2440
+ frameEnergy[t] = Math.log10(eps + (linearEnergy[t] ?? 0));
2441
+ }
2442
+ const noiseFloor = estimateNoiseFloor(frameEnergy, cfg.energyPercentile);
2443
+ const enterThreshold = noiseFloor + cfg.enterMargin;
2444
+ const exitThreshold = noiseFloor + cfg.exitMargin;
2445
+ const frameDurationSec = nFrames >= 2 ? (spec.times[1] ?? 0) - (spec.times[0] ?? 0) : 0.01;
2446
+ const hangoverFrames = Math.max(0, Math.round(cfg.hangoverMs / 1e3 / frameDurationSec));
2447
+ const minActiveFrames = Math.max(0, Math.round(cfg.minActiveMs / 1e3 / frameDurationSec));
2448
+ const smoothFrames = Math.max(1, Math.round(cfg.smoothMs / 1e3 / frameDurationSec)) | 1;
2449
+ const isActive = buildActivityMask(frameEnergy, enterThreshold, exitThreshold, hangoverFrames);
2450
+ if (minActiveFrames > 1) {
2451
+ applyMinActiveDuration(isActive, minActiveFrames);
2452
+ }
2453
+ const suppressFrames = Math.max(0, Math.round(50 / 1e3 / frameDurationSec));
2454
+ const suppressMask = buildSuppressionMask(isActive, suppressFrames);
2455
+ const activityLevel = maskToActivityLevel(isActive, smoothFrames);
2456
+ return {
2457
+ times: spec.times,
2458
+ activityLevel,
2459
+ isActive,
2460
+ suppressMask,
2461
+ diagnostics: {
2462
+ frameEnergy,
2463
+ noiseFloor,
2464
+ enterThreshold,
2465
+ exitThreshold
2466
+ }
2467
+ };
2468
+ }
2469
+ function computeActivityFromAudio(samples, sampleRate, hopSize, windowSize, config) {
2470
+ const cfg = withActivityDefaults(config);
2471
+ const nFrames = Math.max(0, Math.floor((samples.length - windowSize) / hopSize) + 1);
2472
+ const times = new Float32Array(nFrames);
2473
+ const frameEnergy = new Float32Array(nFrames);
2474
+ const eps = 1e-12;
2475
+ for (let frame = 0; frame < nFrames; frame++) {
2476
+ const start = frame * hopSize;
2477
+ const end = Math.min(start + windowSize, samples.length);
2478
+ let sumSq = 0;
2479
+ for (let i = start; i < end; i++) {
2480
+ const s = samples[i] ?? 0;
2481
+ sumSq += s * s;
2482
+ }
2483
+ const rms = Math.sqrt(sumSq / (end - start));
2484
+ times[frame] = (start + windowSize / 2) / sampleRate;
2485
+ frameEnergy[frame] = Math.log10(eps + rms);
2486
+ }
2487
+ const noiseFloor = estimateNoiseFloor(frameEnergy, cfg.energyPercentile);
2488
+ const enterThreshold = noiseFloor + cfg.enterMargin;
2489
+ const exitThreshold = noiseFloor + cfg.exitMargin;
2490
+ const frameDurationSec = hopSize / sampleRate;
2491
+ const hangoverFrames = Math.max(0, Math.round(cfg.hangoverMs / 1e3 / frameDurationSec));
2492
+ const minActiveFrames = Math.max(0, Math.round(cfg.minActiveMs / 1e3 / frameDurationSec));
2493
+ const smoothFrames = Math.max(1, Math.round(cfg.smoothMs / 1e3 / frameDurationSec)) | 1;
2494
+ const isActive = buildActivityMask(frameEnergy, enterThreshold, exitThreshold, hangoverFrames);
2495
+ if (minActiveFrames > 1) {
2496
+ applyMinActiveDuration(isActive, minActiveFrames);
2497
+ }
2498
+ const suppressFrames = Math.max(0, Math.round(50 / 1e3 / frameDurationSec));
2499
+ const suppressMask = buildSuppressionMask(isActive, suppressFrames);
2500
+ const activityLevel = maskToActivityLevel(isActive, smoothFrames);
2501
+ return {
2502
+ times,
2503
+ activityLevel,
2504
+ isActive,
2505
+ suppressMask,
2506
+ diagnostics: {
2507
+ frameEnergy,
2508
+ noiseFloor,
2509
+ enterThreshold,
2510
+ exitThreshold
2511
+ }
2512
+ };
2513
+ }
2514
+ function applyActivityGating(values, activity, options) {
2515
+ const useBinary = options?.useBinaryMask ?? true;
2516
+ const suppressPostSilence = options?.suppressPostSilence ?? true;
2517
+ const levelThreshold = options?.levelThreshold ?? 0.5;
2518
+ const n = Math.min(values.length, activity.activityLevel.length);
2519
+ for (let i = 0; i < n; i++) {
2520
+ let shouldGate = false;
2521
+ if (useBinary) {
2522
+ shouldGate = (activity.isActive[i] ?? 0) === 0;
2523
+ } else {
2524
+ shouldGate = (activity.activityLevel[i] ?? 0) < levelThreshold;
2525
+ }
2526
+ if (suppressPostSilence && (activity.suppressMask[i] ?? 0) === 1) {
2527
+ shouldGate = true;
2528
+ }
2529
+ if (shouldGate) {
2530
+ values[i] = 0;
2531
+ }
2532
+ }
2533
+ }
2534
+ function interpolateActivity(activity, targetTimes) {
2535
+ const n = targetTimes.length;
2536
+ const activityLevel = new Float32Array(n);
2537
+ const isActive = new Uint8Array(n);
2538
+ const suppressMask = new Uint8Array(n);
2539
+ const frameEnergy = new Float32Array(n);
2540
+ const srcTimes = activity.times;
2541
+ const srcN = srcTimes.length;
2542
+ if (srcN === 0) {
2543
+ return {
2544
+ times: targetTimes,
2545
+ activityLevel,
2546
+ isActive,
2547
+ suppressMask,
2548
+ diagnostics: {
2549
+ frameEnergy,
2550
+ noiseFloor: activity.diagnostics.noiseFloor,
2551
+ enterThreshold: activity.diagnostics.enterThreshold,
2552
+ exitThreshold: activity.diagnostics.exitThreshold
2553
+ }
2554
+ };
2555
+ }
2556
+ for (let i = 0; i < n; i++) {
2557
+ const t = targetTimes[i] ?? 0;
2558
+ let lo = 0;
2559
+ let hi = srcN - 1;
2560
+ while (lo < hi) {
2561
+ const mid = lo + hi >> 1;
2562
+ if ((srcTimes[mid] ?? 0) < t) {
2563
+ lo = mid + 1;
2564
+ } else {
2565
+ hi = mid;
2566
+ }
2567
+ }
2568
+ let nearest = lo;
2569
+ if (lo > 0 && Math.abs((srcTimes[lo - 1] ?? 0) - t) < Math.abs((srcTimes[lo] ?? 0) - t)) {
2570
+ nearest = lo - 1;
2571
+ }
2572
+ activityLevel[i] = activity.activityLevel[nearest] ?? 0;
2573
+ isActive[i] = activity.isActive[nearest] ?? 0;
2574
+ suppressMask[i] = activity.suppressMask[nearest] ?? 0;
2575
+ frameEnergy[i] = activity.diagnostics.frameEnergy[nearest] ?? 0;
2576
+ }
2577
+ return {
2578
+ times: targetTimes,
2579
+ activityLevel,
2580
+ isActive,
2581
+ suppressMask,
2582
+ diagnostics: {
2583
+ frameEnergy,
2584
+ noiseFloor: activity.diagnostics.noiseFloor,
2585
+ enterThreshold: activity.diagnostics.enterThreshold,
2586
+ exitThreshold: activity.diagnostics.exitThreshold
2587
+ }
2588
+ };
2589
+ }
2590
+
2591
+ // src/dsp/pitch.ts
2592
+ function pitchF0(samples, sampleRate, config) {
2593
+ const result = yinPitchDetection(samples, sampleRate, config);
2594
+ const f0 = result.f0;
2595
+ const activityOpts = config?.activityOptions;
2596
+ if (activityOpts?.activity) {
2597
+ const activity = interpolateActivity(activityOpts.activity, result.times);
2598
+ const behavior = activityOpts.inactiveBehavior ?? "zero";
2599
+ let lastActiveValue = 0;
2600
+ for (let i = 0; i < f0.length; i++) {
2601
+ if (!activity.isActive[i]) {
2602
+ if (behavior === "zero") {
2603
+ f0[i] = 0;
2604
+ } else {
2605
+ f0[i] = lastActiveValue;
2606
+ }
2607
+ } else {
2608
+ lastActiveValue = f0[i] ?? 0;
2609
+ }
2610
+ }
2611
+ }
2612
+ return {
2613
+ times: result.times,
2614
+ values: f0
2615
+ };
2616
+ }
2617
+ function pitchConfidence(samples, sampleRate, config) {
2618
+ const result = yinPitchDetection(samples, sampleRate, config);
2619
+ const confidence = result.confidence;
2620
+ const activityOpts = config?.activityOptions;
2621
+ if (activityOpts?.activity) {
2622
+ const activity = interpolateActivity(activityOpts.activity, result.times);
2623
+ const behavior = activityOpts.inactiveBehavior ?? "zero";
2624
+ let lastActiveValue = 0;
2625
+ for (let i = 0; i < confidence.length; i++) {
2626
+ if (!activity.isActive[i]) {
2627
+ if (behavior === "zero") {
2628
+ confidence[i] = 0;
2629
+ } else {
2630
+ confidence[i] = lastActiveValue;
2631
+ }
2632
+ } else {
2633
+ lastActiveValue = confidence[i] ?? 0;
2634
+ }
2635
+ }
2636
+ }
2637
+ return {
2638
+ times: result.times,
2639
+ values: confidence
2640
+ };
2641
+ }
2642
+ function yinPitchDetection(samples, sampleRate, config) {
2643
+ const fMinHz = config?.fMinHz ?? 50;
2644
+ const fMaxHz = config?.fMaxHz ?? 1e3;
2645
+ const hopSize = config?.hopSize ?? 512;
2646
+ const windowSize = config?.windowSize ?? 2048;
2647
+ const threshold = config?.threshold ?? 0.15;
2648
+ const tauMin = Math.max(2, Math.floor(sampleRate / fMaxHz));
2649
+ const tauMax = Math.min(windowSize / 2, Math.ceil(sampleRate / fMinHz));
2650
+ const nFrames = Math.max(0, Math.floor((samples.length - windowSize) / hopSize) + 1);
2651
+ const times = new Float32Array(nFrames);
2652
+ const f0 = new Float32Array(nFrames);
2653
+ const confidence = new Float32Array(nFrames);
2654
+ const d = new Float32Array(tauMax + 1);
2655
+ const dPrime = new Float32Array(tauMax + 1);
2656
+ for (let frame = 0; frame < nFrames; frame++) {
2657
+ const start = frame * hopSize;
2658
+ const frameCenter = start + windowSize / 2;
2659
+ times[frame] = frameCenter / sampleRate;
2660
+ const frameEnd = Math.min(start + windowSize, samples.length);
2661
+ const frameLen = frameEnd - start;
2662
+ let energy = 0;
2663
+ for (let i = 0; i < frameLen; i++) {
2664
+ const s = samples[start + i] ?? 0;
2665
+ energy += s * s;
2666
+ }
2667
+ const rms = Math.sqrt(energy / frameLen);
2668
+ if (rms < 1e-6) {
2669
+ f0[frame] = 0;
2670
+ confidence[frame] = 0;
2671
+ continue;
2672
+ }
2673
+ d[0] = 0;
2674
+ for (let tau = 1; tau <= tauMax && tau < frameLen; tau++) {
2675
+ let sum = 0;
2676
+ const limit = Math.min(frameLen - tau, windowSize - tau);
2677
+ for (let j = 0; j < limit; j++) {
2678
+ const diff = (samples[start + j] ?? 0) - (samples[start + j + tau] ?? 0);
2679
+ sum += diff * diff;
2680
+ }
2681
+ d[tau] = sum;
2682
+ }
2683
+ dPrime[0] = 1;
2684
+ let runningSum = 0;
2685
+ for (let tau = 1; tau <= tauMax && tau < frameLen; tau++) {
2686
+ const dVal = d[tau] ?? 0;
2687
+ runningSum += dVal;
2688
+ if (runningSum > 0) {
2689
+ dPrime[tau] = dVal * tau / runningSum;
2690
+ } else {
2691
+ dPrime[tau] = 1;
2692
+ }
2693
+ }
2694
+ let bestTau = -1;
2695
+ let bestDPrime = 1;
2696
+ for (let tau = tauMin; tau <= tauMax && tau < frameLen - 1; tau++) {
2697
+ const dPrimeVal = dPrime[tau] ?? 1;
2698
+ if (dPrimeVal < threshold) {
2699
+ while (tau + 1 <= tauMax && tau + 1 < frameLen - 1 && (dPrime[tau + 1] ?? 1) < (dPrime[tau] ?? 1)) {
2700
+ tau++;
2701
+ }
2702
+ bestTau = tau;
2703
+ bestDPrime = dPrime[tau] ?? 1;
2704
+ break;
2705
+ }
2706
+ }
2707
+ if (bestTau < 0) {
2708
+ for (let tau = tauMin; tau <= tauMax && tau < frameLen; tau++) {
2709
+ const dPrimeVal = dPrime[tau] ?? 1;
2710
+ if (dPrimeVal < bestDPrime) {
2711
+ bestDPrime = dPrimeVal;
2712
+ bestTau = tau;
2713
+ }
2714
+ }
2715
+ }
2716
+ if (bestTau > tauMin && bestTau < tauMax - 1 && bestTau < frameLen - 1) {
2717
+ const y0 = dPrime[bestTau - 1] ?? 1;
2718
+ const y1 = dPrime[bestTau] ?? 1;
2719
+ const y2 = dPrime[bestTau + 1] ?? 1;
2720
+ const denom = 2 * (2 * y1 - y0 - y2);
2721
+ if (Math.abs(denom) > 1e-10) {
2722
+ const delta2 = (y0 - y2) / denom;
2723
+ const interpolatedTau = bestTau + delta2;
2724
+ if (interpolatedTau >= tauMin && interpolatedTau <= tauMax) {
2725
+ f0[frame] = sampleRate / interpolatedTau;
2726
+ confidence[frame] = Math.max(0, Math.min(1, 1 - bestDPrime));
2727
+ continue;
2728
+ }
2729
+ }
2730
+ }
2731
+ if (bestTau >= tauMin && bestTau <= tauMax) {
2732
+ f0[frame] = sampleRate / bestTau;
2733
+ confidence[frame] = Math.max(0, Math.min(1, 1 - bestDPrime));
2734
+ } else {
2735
+ f0[frame] = 0;
2736
+ confidence[frame] = 0;
2737
+ }
2738
+ }
2739
+ return { times, f0, confidence };
2740
+ }
2741
+
2016
2742
  // src/runner/runMir.ts
2017
2743
  function nowMs2() {
2018
2744
  return typeof performance !== "undefined" ? performance.now() : Date.now();
@@ -2039,6 +2765,27 @@ async function runMir(audio, request, options = {}) {
2039
2765
  hopSize: 512,
2040
2766
  window: "hann"
2041
2767
  };
2768
+ if (request.fn === "amplitudeEnvelope") {
2769
+ const cpuStart2 = nowMs2();
2770
+ const result = amplitudeEnvelope(audio.mono, audio.sampleRate, {
2771
+ hopSize: specConfig.hopSize,
2772
+ windowSize: specConfig.fftSize
2773
+ });
2774
+ const cpuEnd = nowMs2();
2775
+ return {
2776
+ kind: "1d",
2777
+ times: result.times,
2778
+ values: result.values,
2779
+ meta: {
2780
+ backend: "cpu",
2781
+ usedGpu: false,
2782
+ timings: {
2783
+ totalMs: cpuEnd - t0,
2784
+ cpuMs: cpuEnd - cpuStart2
2785
+ }
2786
+ }
2787
+ };
2788
+ }
2042
2789
  const cpuStart = nowMs2();
2043
2790
  const spec = await spectrogram(asAudioBufferLike(audio), specConfig, void 0, {
2044
2791
  isCancelled: options.isCancelled
@@ -2398,6 +3145,72 @@ async function runMir(audio, request, options = {}) {
2398
3145
  }
2399
3146
  };
2400
3147
  }
3148
+ if (request.fn === "pitchF0" || request.fn === "pitchConfidence") {
3149
+ const pitchStart = nowMs2();
3150
+ const pitchConfig = {
3151
+ fMinHz: request.pitch?.fMinHz,
3152
+ fMaxHz: request.pitch?.fMaxHz,
3153
+ threshold: request.pitch?.threshold,
3154
+ hopSize: specConfig.hopSize,
3155
+ windowSize: specConfig.fftSize
3156
+ };
3157
+ const result = request.fn === "pitchF0" ? pitchF0(audio.mono, audio.sampleRate, pitchConfig) : pitchConfidence(audio.mono, audio.sampleRate, pitchConfig);
3158
+ const end2 = nowMs2();
3159
+ return {
3160
+ kind: "1d",
3161
+ times: result.times,
3162
+ values: result.values,
3163
+ meta: {
3164
+ backend: "cpu",
3165
+ usedGpu: false,
3166
+ timings: {
3167
+ totalMs: end2 - t0,
3168
+ cpuMs: end2 - pitchStart
3169
+ }
3170
+ }
3171
+ };
3172
+ }
3173
+ if (request.fn === "activity") {
3174
+ const { mel: mel2, cpuExtraMs: melCpuMs } = await computeMel(false);
3175
+ const activityStart = nowMs2();
3176
+ const activityConfig = {
3177
+ energyPercentile: request.activity?.energyPercentile,
3178
+ enterMargin: request.activity?.enterMargin,
3179
+ exitMargin: request.activity?.exitMargin,
3180
+ hangoverMs: request.activity?.hangoverMs,
3181
+ minActiveMs: request.activity?.minActiveMs,
3182
+ smoothMs: request.activity?.smoothMs
3183
+ };
3184
+ const activity = computeActivityFromMel(mel2, activityConfig);
3185
+ const end2 = nowMs2();
3186
+ let activeCount = 0;
3187
+ for (let i = 0; i < activity.isActive.length; i++) {
3188
+ if (activity.isActive[i]) activeCount++;
3189
+ }
3190
+ return {
3191
+ kind: "activity",
3192
+ times: activity.times,
3193
+ activityLevel: activity.activityLevel,
3194
+ isActive: activity.isActive,
3195
+ suppressMask: activity.suppressMask,
3196
+ meta: {
3197
+ backend: "cpu",
3198
+ usedGpu: false,
3199
+ timings: {
3200
+ totalMs: end2 - t0,
3201
+ cpuMs: cpuAfterSpec - cpuStart + melCpuMs + (end2 - activityStart)
3202
+ }
3203
+ },
3204
+ diagnostics: {
3205
+ noiseFloor: activity.diagnostics.noiseFloor,
3206
+ enterThreshold: activity.diagnostics.enterThreshold,
3207
+ exitThreshold: activity.diagnostics.exitThreshold,
3208
+ totalFrames: activity.times.length,
3209
+ activeFrames: activeCount,
3210
+ activeFraction: activity.times.length > 0 ? activeCount / activity.times.length : 0
3211
+ }
3212
+ };
3213
+ }
2401
3214
  const { mel, usedGpu, gpuMs, cpuExtraMs } = await computeMel(backend === "gpu");
2402
3215
  const end = nowMs2();
2403
3216
  return {
@@ -2416,6 +3229,6 @@ async function runMir(audio, request, options = {}) {
2416
3229
  };
2417
3230
  }
2418
3231
 
2419
- export { CQT_DEFAULTS, bassPitchMotion, beatSalienceFromMel, computeAllCqtSignals, computeCqt, computeCqtSignal, cqtBinToHz, cqtSpectrogram, delta, deltaDelta, detectBeatCandidates, featureIndexToHz, generateTempoHypotheses, getCqtBinFrequencies, getNumBins, getNumOctaves, harmonicEnergy, hpss, hzToCqtBin, hzToFeatureIndex, hzToMel, melSpectrogram, melToHz, mfcc, onsetEnvelopeFromMel, onsetEnvelopeFromMelGpu, onsetEnvelopeFromSpectrogram, peakPick, runMir, spectralCentroid, spectralFlux, spectrogram, tonalStability, withCqtDefaults };
2420
- //# sourceMappingURL=chunk-OLIDGECY.js.map
2421
- //# sourceMappingURL=chunk-OLIDGECY.js.map
3232
+ export { CQT_DEFAULTS, amplitudeEnvelope, applyActivityGating, bassPitchMotion, beatSalienceFromMel, buildActivityMask, computeActivityFromAudio, computeActivityFromMel, computeActivityFromSpectrogram, computeAllCqtSignals, computeCqt, computeCqtSignal, computeFrameEnergyFromMel, computeFrameEnergyFromSpectrogram, computeSilenceGating, cqtBinToHz, cqtSpectrogram, delta, deltaDelta, detectBeatCandidates, estimateNoiseFloor, featureIndexToHz, generateTempoHypotheses, getCqtBinFrequencies, getNumBins, getNumOctaves, harmonicEnergy, hpss, hzToCqtBin, hzToFeatureIndex, hzToMel, interpolateActivity, melSpectrogram, melToHz, mfcc, onsetEnvelopeFromMel, onsetEnvelopeFromMelGpu, onsetEnvelopeFromSpectrogram, peakPick, pitchConfidence, pitchF0, runMir, spectralCentroid, spectralFlux, spectrogram, tonalStability, withBinGateDefaults, withCqtDefaults, withSilenceGateDefaults };
3233
+ //# sourceMappingURL=chunk-5WZ7TTDW.js.map
3234
+ //# sourceMappingURL=chunk-5WZ7TTDW.js.map