@libraz/libsonare 1.5.4 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +109 -20
  2. package/dist/analysis.d.ts +5730 -0
  3. package/dist/analysis.js +2464 -0
  4. package/dist/analysis.js.map +1 -0
  5. package/dist/index.d.ts +873 -63
  6. package/dist/index.js +1037 -265
  7. package/dist/index.js.map +1 -1
  8. package/dist/schemas/realtime-voice-changer-preset-pack.schema.json +27 -0
  9. package/dist/schemas/realtime-voice-changer-preset.schema.json +140 -0
  10. package/dist/sonare-analysis.js +2 -0
  11. package/dist/sonare-analysis.wasm +0 -0
  12. package/dist/sonare.js +1 -1
  13. package/dist/sonare.wasm +0 -0
  14. package/dist/worker.d.ts +65 -0
  15. package/dist/worker.js +707 -0
  16. package/dist/worker.js.map +1 -0
  17. package/dist/worklet.d.ts +596 -86
  18. package/dist/worklet.js +1658 -235
  19. package/dist/worklet.js.map +1 -1
  20. package/package.json +23 -11
  21. package/src/_chain_config.ts +5 -23
  22. package/src/analysis.ts +137 -0
  23. package/src/analysis_helpers.ts +29 -0
  24. package/src/audio.ts +5 -3
  25. package/src/clip_page_streamer.ts +62 -8
  26. package/src/codes.ts +51 -64
  27. package/src/effects_mastering.ts +1 -0
  28. package/src/effects_transform.ts +12 -6
  29. package/src/errors.ts +1 -0
  30. package/src/feature_core.ts +159 -3
  31. package/src/feature_music.ts +35 -16
  32. package/src/feature_pitch.ts +75 -6
  33. package/src/feature_spectral.ts +234 -8
  34. package/src/feature_spectrogram.ts +186 -5
  35. package/src/features.ts +16 -1
  36. package/src/index.ts +104 -7
  37. package/src/mastering_chain.ts +20 -8
  38. package/src/mastering_core.ts +7 -0
  39. package/src/mastering_dynamics.ts +7 -1
  40. package/src/metering.ts +51 -5
  41. package/src/mixer.ts +14 -1
  42. package/src/opfs_clip_pages.ts +26 -1
  43. package/src/project.ts +7 -0
  44. package/src/project_class.ts +74 -13
  45. package/src/project_internal.ts +24 -29
  46. package/src/project_types.ts +69 -10
  47. package/src/public_types.ts +68 -0
  48. package/src/public_types_mastering.ts +28 -0
  49. package/src/public_types_mixing.ts +11 -2
  50. package/src/public_types_music.ts +13 -0
  51. package/src/public_types_spectral.ts +43 -3
  52. package/src/quick_analysis.ts +48 -12
  53. package/src/realtime_engine.ts +162 -4
  54. package/src/realtime_voice_changer.ts +51 -77
  55. package/src/sonare-analysis.js.d.ts +8 -0
  56. package/src/sonare.js.d.ts +305 -9
  57. package/src/streaming_processors.ts +22 -1
  58. package/src/validation.ts +6 -0
  59. package/src/web_midi.ts +36 -4
  60. package/src/worker.ts +196 -0
  61. package/src/worker_client.ts +352 -0
  62. package/src/worker_protocol.ts +59 -0
  63. package/src/worklet/engine-automation.ts +2 -1
  64. package/src/worklet/engine-capture-facade.ts +13 -4
  65. package/src/worklet/engine-clips.ts +12 -3
  66. package/src/worklet/engine-node.ts +212 -4
  67. package/src/worklet/engine-offline.ts +7 -2
  68. package/src/worklet/engine-parameter-facade.ts +26 -5
  69. package/src/worklet/engine-processor.ts +383 -42
  70. package/src/worklet/engine-register.ts +8 -0
  71. package/src/worklet/engine-strips.ts +17 -1
  72. package/src/worklet/engine-sync.ts +2 -6
  73. package/src/worklet/engine-tempo-facade.ts +8 -6
  74. package/src/worklet/engine.ts +380 -13
  75. package/src/worklet/guards.ts +22 -1
  76. package/src/worklet/messages.ts +141 -9
  77. package/src/worklet/protocol.ts +303 -17
  78. package/src/worklet/voice-changer-processor.ts +12 -15
  79. package/src/worklet.ts +20 -1
@@ -1,4 +1,5 @@
1
1
  import { getSonareModule } from './module_state';
2
+ import type { SegmentMatrix } from './public_types';
2
3
  import type {
3
4
  WasmDecomposeResult,
4
5
  WasmHpssWithResidualResult,
@@ -6,7 +7,13 @@ import type {
6
7
  WasmMatrix2dResult,
7
8
  } from './sonare.js';
8
9
  import type { ValidateOptions } from './validation';
9
- import { assertInterleavedSamples, assertSampleRate } from './validation';
10
+ import {
11
+ assertInterleavedSamples,
12
+ assertNonNegativeInteger,
13
+ assertPositiveInteger,
14
+ assertSampleRate,
15
+ assertSamples,
16
+ } from './validation';
10
17
 
11
18
  function requireModule() {
12
19
  return getSonareModule();
@@ -76,6 +83,75 @@ export interface NnFilterRequest {
76
83
  k?: number;
77
84
  width?: number;
78
85
  }
86
+ export interface SegmentCrossSimilarityRequest {
87
+ x: Float32Array;
88
+ xRows: number;
89
+ xCols: number;
90
+ y: Float32Array;
91
+ yRows: number;
92
+ yCols: number;
93
+ k?: number;
94
+ metric?: 'cosine' | 'euclidean';
95
+ mode?: 'connectivity' | 'affinity';
96
+ }
97
+ export interface SegmentRecurrenceMatrixRequest {
98
+ data: Float32Array;
99
+ rows: number;
100
+ cols: number;
101
+ k?: number;
102
+ width?: number;
103
+ sym?: boolean;
104
+ metric?: 'cosine' | 'euclidean';
105
+ mode?: 'connectivity' | 'affinity';
106
+ }
107
+ export interface SegmentRecurrenceToLagRequest {
108
+ recurrence: Float32Array;
109
+ n: number;
110
+ pad?: boolean;
111
+ }
112
+ export interface SegmentLagToRecurrenceRequest {
113
+ lag: Float32Array;
114
+ rows: number;
115
+ lags: number;
116
+ }
117
+ export interface SegmentSubsegmentRequest {
118
+ data: Float32Array;
119
+ rows: number;
120
+ cols: number;
121
+ boundaries: Int32Array;
122
+ nSegments?: number;
123
+ }
124
+ export interface SegmentAgglomerativeRequest {
125
+ data: Float32Array;
126
+ rows: number;
127
+ cols: number;
128
+ k: number;
129
+ linkage?: 'average' | 'single' | 'complete' | 'ward';
130
+ }
131
+ export interface SegmentPathEnhanceRequest {
132
+ recurrence: Float32Array;
133
+ n: number;
134
+ win: number;
135
+ maxRatio?: number;
136
+ minRatio?: number;
137
+ nFilters?: number;
138
+ }
139
+
140
+ function validateSegmentMatrix(
141
+ fnName: string,
142
+ data: Float32Array,
143
+ rows: number,
144
+ cols: number,
145
+ dataName: string,
146
+ ): void {
147
+ assertPositiveInteger(fnName, rows, 'rows');
148
+ assertPositiveInteger(fnName, cols, 'cols');
149
+ assertSamples(fnName, data, true, dataName);
150
+ const expected = rows * cols;
151
+ if (!Number.isSafeInteger(expected) || data.length !== expected) {
152
+ throw new RangeError(`${fnName}: ${dataName} length must equal rows * cols`);
153
+ }
154
+ }
79
155
  export interface RemixRequest {
80
156
  samples: Float32Array;
81
157
  intervals: Int32Array | ArrayLike<number>;
@@ -438,21 +514,21 @@ export function remix(
438
514
  export function phaseVocoder(request: PhaseVocoderRequest): Float32Array;
439
515
  export function phaseVocoder(
440
516
  samples: Float32Array,
517
+ sampleRate: number,
441
518
  rate: number,
442
- sampleRate?: number,
443
519
  nFft?: number,
444
520
  hopLength?: number,
445
521
  ): Float32Array;
446
522
  export function phaseVocoder(
447
523
  samples: Float32Array | PhaseVocoderRequest,
448
- rate = 1,
449
524
  sampleRate = 22050,
525
+ rate = 1,
450
526
  nFft = 2048,
451
527
  hopLength = 512,
452
528
  ): Float32Array {
453
529
  if (!(samples instanceof Float32Array)) {
454
530
  const r = samples;
455
- return phaseVocoder(r.samples, r.rate, r.sampleRate, r.nFft, r.hopLength);
531
+ return phaseVocoder(r.samples, r.sampleRate ?? 22050, r.rate, r.nFft, r.hopLength);
456
532
  }
457
533
  return requireModule().phaseVocoder(samples, sampleRate, rate, nFft, hopLength);
458
534
  }
@@ -537,23 +613,31 @@ export function ebur128LoudnessRange(
537
613
  * @param hopLength - Hop length (default: 512)
538
614
  * @returns Spectral bandwidth in Hz for each frame
539
615
  */
540
- export function spectralBandwidth(request: SpectralFrameRequest): Float32Array;
616
+ export function spectralBandwidth(request: SpectralFrameRequest & { p?: number }): Float32Array;
541
617
  export function spectralBandwidth(
542
618
  samples: Float32Array,
543
619
  sampleRate?: number,
544
620
  nFft?: number,
545
621
  hopLength?: number,
622
+ p?: number,
546
623
  ): Float32Array;
547
624
  export function spectralBandwidth(
548
- samples: Float32Array | SpectralFrameRequest,
625
+ samples: Float32Array | (SpectralFrameRequest & { p?: number }),
549
626
  sampleRate = 22050,
550
627
  nFft = 2048,
551
628
  hopLength = 512,
629
+ p = 2,
552
630
  ): Float32Array {
553
631
  if (!(samples instanceof Float32Array)) {
554
- return spectralBandwidth(samples.samples, samples.sampleRate, samples.nFft, samples.hopLength);
632
+ return spectralBandwidth(
633
+ samples.samples,
634
+ samples.sampleRate,
635
+ samples.nFft,
636
+ samples.hopLength,
637
+ samples.p,
638
+ );
555
639
  }
556
- return requireModule().spectralBandwidth(samples, sampleRate, nFft, hopLength);
640
+ return requireModule().spectralBandwidth(samples, sampleRate, nFft, hopLength, p);
557
641
  }
558
642
 
559
643
  /**
@@ -621,6 +705,33 @@ export function spectralFlatness(
621
705
  return requireModule().spectralFlatness(samples, sampleRate, nFft, hopLength);
622
706
  }
623
707
 
708
+ export function spectralFlux(request: SpectralFrameRequest & { lag?: number }): Float32Array;
709
+ export function spectralFlux(
710
+ samples: Float32Array,
711
+ sampleRate?: number,
712
+ nFft?: number,
713
+ hopLength?: number,
714
+ lag?: number,
715
+ ): Float32Array;
716
+ export function spectralFlux(
717
+ samples: Float32Array | (SpectralFrameRequest & { lag?: number }),
718
+ sampleRate = 22050,
719
+ nFft = 2048,
720
+ hopLength = 512,
721
+ lag = 1,
722
+ ): Float32Array {
723
+ if (!(samples instanceof Float32Array)) {
724
+ return spectralFlux(
725
+ samples.samples,
726
+ samples.sampleRate,
727
+ samples.nFft,
728
+ samples.hopLength,
729
+ samples.lag,
730
+ );
731
+ }
732
+ return requireModule().spectralFlux(samples, sampleRate, nFft, hopLength, lag);
733
+ }
734
+
624
735
  /**
625
736
  * Compute zero crossing rate.
626
737
  *
@@ -681,3 +792,118 @@ export function rmsEnergy(
681
792
  }
682
793
  return requireModule().rmsEnergy(samples, sampleRate, frameLength, hopLength);
683
794
  }
795
+
796
+ /** Column-wise cross-similarity (librosa.segment.cross_similarity). */
797
+ export function segmentCrossSimilarity(request: SegmentCrossSimilarityRequest): SegmentMatrix {
798
+ validateSegmentMatrix('segmentCrossSimilarity', request.x, request.xRows, request.xCols, 'x');
799
+ validateSegmentMatrix('segmentCrossSimilarity', request.y, request.yRows, request.yCols, 'y');
800
+ if (request.xRows !== request.yRows) {
801
+ throw new RangeError('segmentCrossSimilarity: feature dimensions must match');
802
+ }
803
+ assertNonNegativeInteger('segmentCrossSimilarity', request.k ?? 0, 'k');
804
+ return requireModule().segmentCrossSimilarity(
805
+ request.x,
806
+ request.xRows,
807
+ request.xCols,
808
+ request.y,
809
+ request.yRows,
810
+ request.yCols,
811
+ request.k ?? 0,
812
+ request.metric ?? 'cosine',
813
+ request.mode ?? 'connectivity',
814
+ );
815
+ }
816
+
817
+ /** Self-similarity recurrence matrix (librosa.segment.recurrence_matrix). */
818
+ export function segmentRecurrenceMatrix(request: SegmentRecurrenceMatrixRequest): SegmentMatrix {
819
+ validateSegmentMatrix(
820
+ 'segmentRecurrenceMatrix',
821
+ request.data,
822
+ request.rows,
823
+ request.cols,
824
+ 'data',
825
+ );
826
+ assertNonNegativeInteger('segmentRecurrenceMatrix', request.k ?? 0, 'k');
827
+ assertNonNegativeInteger('segmentRecurrenceMatrix', request.width ?? 1, 'width');
828
+ return requireModule().segmentRecurrenceMatrix(
829
+ request.data,
830
+ request.rows,
831
+ request.cols,
832
+ request.k ?? 0,
833
+ request.width ?? 1,
834
+ request.sym ?? false,
835
+ request.metric ?? 'euclidean',
836
+ request.mode ?? 'connectivity',
837
+ );
838
+ }
839
+
840
+ /** Convert an `n × n` recurrence matrix to a lag matrix. */
841
+ export function segmentRecurrenceToLag(request: SegmentRecurrenceToLagRequest): SegmentMatrix {
842
+ validateSegmentMatrix(
843
+ 'segmentRecurrenceToLag',
844
+ request.recurrence,
845
+ request.n,
846
+ request.n,
847
+ 'recurrence',
848
+ );
849
+ return requireModule().segmentRecurrenceToLag(
850
+ request.recurrence,
851
+ request.n,
852
+ request.pad ?? false,
853
+ );
854
+ }
855
+
856
+ /** Convert a lag matrix back to an `n × n` recurrence matrix. */
857
+ export function segmentLagToRecurrence(request: SegmentLagToRecurrenceRequest): SegmentMatrix {
858
+ validateSegmentMatrix('segmentLagToRecurrence', request.lag, request.rows, request.lags, 'lag');
859
+ return requireModule().segmentLagToRecurrence(request.lag, request.rows, request.lags);
860
+ }
861
+
862
+ /** Refine frame boundaries by clustering within each parent segment. */
863
+ export function segmentSubsegment(request: SegmentSubsegmentRequest): Int32Array {
864
+ validateSegmentMatrix('segmentSubsegment', request.data, request.rows, request.cols, 'data');
865
+ assertPositiveInteger('segmentSubsegment', request.nSegments ?? 4, 'nSegments');
866
+ return requireModule().segmentSubsegment(
867
+ request.data,
868
+ request.rows,
869
+ request.cols,
870
+ request.boundaries,
871
+ request.nSegments ?? 4,
872
+ );
873
+ }
874
+
875
+ /** Cluster feature columns and return one label per column. */
876
+ export function segmentAgglomerative(request: SegmentAgglomerativeRequest): Int32Array {
877
+ validateSegmentMatrix('segmentAgglomerative', request.data, request.rows, request.cols, 'data');
878
+ assertPositiveInteger('segmentAgglomerative', request.k, 'k');
879
+ return requireModule().segmentAgglomerative(
880
+ request.data,
881
+ request.rows,
882
+ request.cols,
883
+ request.k,
884
+ request.linkage ?? 'average',
885
+ );
886
+ }
887
+
888
+ /** Enhance diagonal paths in an `n × n` recurrence matrix. */
889
+ export function segmentPathEnhance(request: SegmentPathEnhanceRequest): SegmentMatrix {
890
+ validateSegmentMatrix(
891
+ 'segmentPathEnhance',
892
+ request.recurrence,
893
+ request.n,
894
+ request.n,
895
+ 'recurrence',
896
+ );
897
+ assertPositiveInteger('segmentPathEnhance', request.win, 'win');
898
+ assertPositiveInteger('segmentPathEnhance', request.maxRatio ?? 2, 'maxRatio');
899
+ assertNonNegativeInteger('segmentPathEnhance', request.minRatio ?? 0, 'minRatio');
900
+ assertPositiveInteger('segmentPathEnhance', request.nFilters ?? 7, 'nFilters');
901
+ return requireModule().segmentPathEnhance(
902
+ request.recurrence,
903
+ request.n,
904
+ request.win,
905
+ request.maxRatio ?? 2,
906
+ request.minRatio ?? 0,
907
+ request.nFilters ?? 7,
908
+ );
909
+ }
@@ -4,6 +4,7 @@ import type {
4
4
  MelPowerResult,
5
5
  MelSpectrogramResult,
6
6
  MfccResult,
7
+ ReassignedSpectrogramResult,
7
8
  StftPowerResult,
8
9
  StftResult,
9
10
  } from './public_types';
@@ -34,6 +35,7 @@ export interface ChromaSpectrogramRequest extends GuardedOptions {
34
35
  sampleRate?: number;
35
36
  hopLength?: number;
36
37
  nChroma?: number;
38
+ binsPerOctave?: number;
37
39
  }
38
40
 
39
41
  export interface MelSpectrogramRequest extends SpectrogramRequest {
@@ -48,11 +50,24 @@ export interface MfccRequest extends MelSpectrogramRequest {
48
50
  lifter?: number;
49
51
  }
50
52
 
53
+ export interface MelDeltaRequest extends GuardedOptions {
54
+ features: Float32Array;
55
+ nFeatures: number;
56
+ nFrames: number;
57
+ width?: number;
58
+ }
59
+ export interface ReassignedSpectrogramRequest extends SpectrogramRequest {
60
+ refPower?: number;
61
+ fillNan?: boolean;
62
+ }
63
+
51
64
  export interface MfccToMelRequest extends GuardedOptions {
52
65
  mfccCoefficients: Float32Array;
53
66
  nMfcc: number;
54
67
  nFrames: number;
55
68
  nMels?: number;
69
+ /** Lifter used by the forward MFCC transform; zero means no liftering. */
70
+ lifter?: number;
56
71
  }
57
72
 
58
73
  /** Canonical request form for reconstruction from a Mel power spectrogram. */
@@ -72,6 +87,16 @@ export interface MelToAudioRequest extends MelToStftRequest {
72
87
  hopLength?: number;
73
88
  nIter?: number;
74
89
  }
90
+ export interface GriffinLimRequest extends GuardedOptions {
91
+ magnitude: Float32Array;
92
+ nBins: number;
93
+ nFrames: number;
94
+ sampleRate?: number;
95
+ nFft?: number;
96
+ hopLength?: number;
97
+ nIter?: number;
98
+ momentum?: number;
99
+ }
75
100
 
76
101
  /** Canonical request form for Griffin-Lim reconstruction from MFCCs. */
77
102
  export interface MfccToAudioRequest extends MfccToMelRequest {
@@ -262,6 +287,7 @@ export function chromaCens(
262
287
  sampleRate?: number,
263
288
  hopLength?: number,
264
289
  nChroma?: number,
290
+ binsPerOctave?: number,
265
291
  options?: GuardedOptions,
266
292
  ): ChromaResult;
267
293
  export function chromaCens(
@@ -269,6 +295,7 @@ export function chromaCens(
269
295
  sampleRate = 22050,
270
296
  hopLength = 512,
271
297
  nChroma = 12,
298
+ binsPerOctave = 36,
272
299
  options: GuardedOptions = {},
273
300
  ): ChromaResult {
274
301
  if (!(samples instanceof Float32Array)) {
@@ -278,12 +305,16 @@ export function chromaCens(
278
305
  request.sampleRate,
279
306
  request.hopLength,
280
307
  request.nChroma,
308
+ request.binsPerOctave,
281
309
  request,
282
310
  );
283
311
  }
284
312
  validateSpectrogramSamples('chromaCens', samples, sampleRate, options);
285
- validatePositiveIntegers('chromaCens', { hopLength, nChroma });
286
- return requireModule().chromaCens(samples, sampleRate, hopLength, nChroma);
313
+ validatePositiveIntegers('chromaCens', { hopLength, nChroma, binsPerOctave });
314
+ if (binsPerOctave % nChroma !== 0) {
315
+ throw new RangeError('chromaCens: binsPerOctave must be a multiple of nChroma');
316
+ }
317
+ return requireModule().chromaCens(samples, sampleRate, hopLength, nChroma, binsPerOctave);
287
318
  }
288
319
 
289
320
  /**
@@ -301,6 +332,7 @@ export function chromaCqt(
301
332
  sampleRate?: number,
302
333
  hopLength?: number,
303
334
  nChroma?: number,
335
+ binsPerOctave?: number,
304
336
  options?: GuardedOptions,
305
337
  ): ChromaResult;
306
338
  export function chromaCqt(
@@ -308,6 +340,7 @@ export function chromaCqt(
308
340
  sampleRate = 22050,
309
341
  hopLength = 512,
310
342
  nChroma = 12,
343
+ binsPerOctave = 36,
311
344
  options: GuardedOptions = {},
312
345
  ): ChromaResult {
313
346
  if (!(samples instanceof Float32Array)) {
@@ -317,12 +350,16 @@ export function chromaCqt(
317
350
  request.sampleRate,
318
351
  request.hopLength,
319
352
  request.nChroma,
353
+ request.binsPerOctave,
320
354
  request,
321
355
  );
322
356
  }
323
357
  validateSpectrogramSamples('chromaCqt', samples, sampleRate, options);
324
- validatePositiveIntegers('chromaCqt', { hopLength, nChroma });
325
- return requireModule().chromaCqt(samples, sampleRate, hopLength, nChroma);
358
+ validatePositiveIntegers('chromaCqt', { hopLength, nChroma, binsPerOctave });
359
+ if (binsPerOctave % nChroma !== 0) {
360
+ throw new RangeError('chromaCqt: binsPerOctave must be a multiple of nChroma');
361
+ }
362
+ return requireModule().chromaCqt(samples, sampleRate, hopLength, nChroma, binsPerOctave);
326
363
  }
327
364
 
328
365
  /**
@@ -509,6 +546,90 @@ export function mfcc(
509
546
  );
510
547
  }
511
548
 
549
+ /** First-order regression delta of a row-major feature matrix. */
550
+ export function melDelta(request: MelDeltaRequest): Float32Array;
551
+ export function melDelta(
552
+ features: Float32Array,
553
+ nFeatures: number,
554
+ nFrames: number,
555
+ width?: number,
556
+ ): Float32Array;
557
+ export function melDelta(
558
+ features: Float32Array | MelDeltaRequest,
559
+ nFeatures?: number,
560
+ nFrames?: number,
561
+ width = 9,
562
+ ): Float32Array {
563
+ const request: MelDeltaRequest =
564
+ features instanceof Float32Array
565
+ ? { features, nFeatures: nFeatures ?? 0, nFrames: nFrames ?? 0, width }
566
+ : features;
567
+ assertPositiveInteger('melDelta', request.nFeatures, 'nFeatures');
568
+ assertPositiveInteger('melDelta', request.nFrames, 'nFrames');
569
+ assertPositiveInteger('melDelta', request.width ?? 9, 'width');
570
+ if ((request.width ?? 9) < 3 || (request.width ?? 9) % 2 === 0) {
571
+ throw new RangeError('melDelta: width must be an odd integer of at least 3');
572
+ }
573
+ if (request.features.length !== request.nFeatures * request.nFrames) {
574
+ throw new RangeError('melDelta: feature matrix length must equal nFeatures * nFrames');
575
+ }
576
+ return requireModule().melDelta(
577
+ request.features,
578
+ request.nFeatures,
579
+ request.nFrames,
580
+ request.width ?? 9,
581
+ );
582
+ }
583
+
584
+ /** Auger-Flandrin reassigned spectrogram (row-major [nBins x nFrames] arrays). */
585
+ export function reassignedSpectrogram(
586
+ request: ReassignedSpectrogramRequest,
587
+ ): ReassignedSpectrogramResult;
588
+ export function reassignedSpectrogram(
589
+ samples: Float32Array,
590
+ sampleRate?: number,
591
+ nFft?: number,
592
+ hopLength?: number,
593
+ refPower?: number,
594
+ fillNan?: boolean,
595
+ ): ReassignedSpectrogramResult;
596
+ export function reassignedSpectrogram(
597
+ samples: Float32Array | ReassignedSpectrogramRequest,
598
+ sampleRate = 22050,
599
+ nFft = 2048,
600
+ hopLength = 512,
601
+ refPower = 1e-6,
602
+ fillNan = false,
603
+ ): ReassignedSpectrogramResult {
604
+ if (!(samples instanceof Float32Array)) {
605
+ const request = samples;
606
+ return reassignedSpectrogram(
607
+ request.samples,
608
+ request.sampleRate,
609
+ request.nFft,
610
+ request.hopLength,
611
+ request.refPower,
612
+ request.fillNan,
613
+ );
614
+ }
615
+ assertSamples('reassignedSpectrogram', samples, true);
616
+ assertSampleRate('reassignedSpectrogram', sampleRate);
617
+ assertPositiveInteger('reassignedSpectrogram', nFft, 'nFft');
618
+ assertPositiveInteger('reassignedSpectrogram', hopLength, 'hopLength');
619
+ assertFiniteScalar('reassignedSpectrogram', refPower, 'refPower');
620
+ if (refPower < 0) {
621
+ throw new RangeError('reassignedSpectrogram: refPower must be non-negative');
622
+ }
623
+ return requireModule().reassignedSpectrogram(
624
+ samples,
625
+ sampleRate,
626
+ nFft,
627
+ hopLength,
628
+ refPower,
629
+ fillNan,
630
+ );
631
+ }
632
+
512
633
  // ============================================================================
513
634
  // Features - Inverse reconstruction
514
635
  // ============================================================================
@@ -648,6 +769,59 @@ export function melToAudio(
648
769
  );
649
770
  }
650
771
 
772
+ /** Reconstruct audio from an STFT magnitude matrix via Griffin-Lim. */
773
+ export function griffinLim(request: GriffinLimRequest): Float32Array;
774
+ export function griffinLim(
775
+ magnitude: Float32Array,
776
+ nBins: number,
777
+ nFrames: number,
778
+ sampleRate?: number,
779
+ nFft?: number,
780
+ hopLength?: number,
781
+ nIter?: number,
782
+ momentum?: number,
783
+ options?: GuardedOptions,
784
+ ): Float32Array;
785
+ export function griffinLim(
786
+ magnitude: Float32Array | GriffinLimRequest,
787
+ nBins = 0,
788
+ nFrames = 0,
789
+ sampleRate = 22050,
790
+ nFft = 2048,
791
+ hopLength = 512,
792
+ nIter = 32,
793
+ momentum = 0.99,
794
+ options: GuardedOptions = {},
795
+ ): Float32Array {
796
+ if (!(magnitude instanceof Float32Array)) {
797
+ const request = magnitude;
798
+ return griffinLim(
799
+ request.magnitude,
800
+ request.nBins,
801
+ request.nFrames,
802
+ request.sampleRate,
803
+ request.nFft,
804
+ request.hopLength,
805
+ request.nIter,
806
+ request.momentum,
807
+ request,
808
+ );
809
+ }
810
+ assertSampleRate('griffinLim', sampleRate);
811
+ validateMatrix('griffinLim', magnitude, nBins, nFrames, 'magnitude', 'nBins', options);
812
+ validatePositiveIntegers('griffinLim', { nFft, hopLength, nIter });
813
+ return requireModule().griffinLim(
814
+ magnitude,
815
+ nBins,
816
+ nFrames,
817
+ sampleRate,
818
+ nFft,
819
+ hopLength,
820
+ nIter,
821
+ momentum,
822
+ );
823
+ }
824
+
651
825
  /**
652
826
  * Invert MFCC coefficients back to a Mel power spectrogram. Mirrors
653
827
  * `feature::mfcc_to_mel`.
@@ -664,6 +838,7 @@ export function mfccToMel(
664
838
  nMfcc: number,
665
839
  nFrames: number,
666
840
  nMels?: number,
841
+ lifter?: number,
667
842
  options?: GuardedOptions,
668
843
  ): MelPowerResult;
669
844
  export function mfccToMel(
@@ -671,6 +846,7 @@ export function mfccToMel(
671
846
  nMfcc = 0,
672
847
  nFrames = 0,
673
848
  nMels = 128,
849
+ lifter = 0,
674
850
  options: GuardedOptions = {},
675
851
  ): MelPowerResult {
676
852
  if (!(mfccCoefficients instanceof Float32Array)) {
@@ -680,6 +856,7 @@ export function mfccToMel(
680
856
  request.nMfcc,
681
857
  request.nFrames,
682
858
  request.nMels,
859
+ request.lifter,
683
860
  request,
684
861
  );
685
862
  }
@@ -693,7 +870,7 @@ export function mfccToMel(
693
870
  options,
694
871
  );
695
872
  validatePositiveIntegers('mfccToMel', { nMels });
696
- return requireModule().mfccToMel(mfccCoefficients, nMfcc, nFrames, nMels);
873
+ return requireModule().mfccToMel(mfccCoefficients, nMfcc, nFrames, nMels, lifter);
697
874
  }
698
875
 
699
876
  /**
@@ -726,6 +903,7 @@ export function mfccToAudio(
726
903
  fmax?: number,
727
904
  nIter?: number,
728
905
  htk?: boolean,
906
+ lifter?: number,
729
907
  options?: GuardedOptions,
730
908
  ): Float32Array;
731
909
  export function mfccToAudio(
@@ -740,6 +918,7 @@ export function mfccToAudio(
740
918
  fmax = 0,
741
919
  nIter = 32,
742
920
  htk = false,
921
+ lifter = 0,
743
922
  options: GuardedOptions = {},
744
923
  ): Float32Array {
745
924
  if (!(mfccCoefficients instanceof Float32Array)) {
@@ -756,6 +935,7 @@ export function mfccToAudio(
756
935
  request.fmax,
757
936
  request.nIter,
758
937
  request.htk,
938
+ request.lifter,
759
939
  request,
760
940
  );
761
941
  }
@@ -783,6 +963,7 @@ export function mfccToAudio(
783
963
  fmax,
784
964
  nIter,
785
965
  htk,
966
+ lifter,
786
967
  );
787
968
  }
788
969
 
package/src/features.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export {
2
2
  amplitudeToDb,
3
+ chirp,
4
+ clicks,
3
5
  cyclicTempogram,
4
6
  dbToAmplitude,
5
7
  dbToPower,
@@ -15,6 +17,7 @@ export {
15
17
  melToHz,
16
18
  midiToHz,
17
19
  noteToHz,
20
+ onsetBacktrack,
18
21
  padCenter,
19
22
  pcen,
20
23
  peakPick,
@@ -25,6 +28,7 @@ export {
25
28
  splitSilence,
26
29
  tempogram,
27
30
  timeToFrames,
31
+ tone,
28
32
  tonnetz,
29
33
  trimSilence,
30
34
  vectorNormalize,
@@ -47,7 +51,7 @@ export {
47
51
  vqt,
48
52
  vqtToAudio,
49
53
  } from './feature_music';
50
- export { pitchPyin, pitchYin } from './feature_pitch';
54
+ export { noteSegments, piptrack, pitchPyin, pitchYin } from './feature_pitch';
51
55
  export { resample } from './feature_resample';
52
56
  export {
53
57
  decompose,
@@ -62,10 +66,18 @@ export {
62
66
  polyFeatures,
63
67
  remix,
64
68
  rmsEnergy,
69
+ segmentAgglomerative,
70
+ segmentCrossSimilarity,
71
+ segmentLagToRecurrence,
72
+ segmentPathEnhance,
73
+ segmentRecurrenceMatrix,
74
+ segmentRecurrenceToLag,
75
+ segmentSubsegment,
65
76
  spectralBandwidth,
66
77
  spectralCentroid,
67
78
  spectralContrast,
68
79
  spectralFlatness,
80
+ spectralFlux,
69
81
  spectralRolloff,
70
82
  zeroCrossingRate,
71
83
  zeroCrossings,
@@ -75,12 +87,15 @@ export {
75
87
  chroma,
76
88
  chromaCens,
77
89
  chromaCqt,
90
+ griffinLim,
91
+ melDelta,
78
92
  melSpectrogram,
79
93
  melToAudio,
80
94
  melToStft,
81
95
  mfcc,
82
96
  mfccToAudio,
83
97
  mfccToMel,
98
+ reassignedSpectrogram,
84
99
  stft,
85
100
  stftDb,
86
101
  trim,