@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.
- package/README.md +109 -20
- package/dist/analysis.d.ts +5730 -0
- package/dist/analysis.js +2464 -0
- package/dist/analysis.js.map +1 -0
- package/dist/index.d.ts +873 -63
- package/dist/index.js +1037 -265
- package/dist/index.js.map +1 -1
- package/dist/schemas/realtime-voice-changer-preset-pack.schema.json +27 -0
- package/dist/schemas/realtime-voice-changer-preset.schema.json +140 -0
- package/dist/sonare-analysis.js +2 -0
- package/dist/sonare-analysis.wasm +0 -0
- package/dist/sonare.js +1 -1
- package/dist/sonare.wasm +0 -0
- package/dist/worker.d.ts +65 -0
- package/dist/worker.js +707 -0
- package/dist/worker.js.map +1 -0
- package/dist/worklet.d.ts +596 -86
- package/dist/worklet.js +1658 -235
- package/dist/worklet.js.map +1 -1
- package/package.json +23 -11
- package/src/_chain_config.ts +5 -23
- package/src/analysis.ts +137 -0
- package/src/analysis_helpers.ts +29 -0
- package/src/audio.ts +5 -3
- package/src/clip_page_streamer.ts +62 -8
- package/src/codes.ts +51 -64
- package/src/effects_mastering.ts +1 -0
- package/src/effects_transform.ts +12 -6
- package/src/errors.ts +1 -0
- package/src/feature_core.ts +159 -3
- package/src/feature_music.ts +35 -16
- package/src/feature_pitch.ts +75 -6
- package/src/feature_spectral.ts +234 -8
- package/src/feature_spectrogram.ts +186 -5
- package/src/features.ts +16 -1
- package/src/index.ts +104 -7
- package/src/mastering_chain.ts +20 -8
- package/src/mastering_core.ts +7 -0
- package/src/mastering_dynamics.ts +7 -1
- package/src/metering.ts +51 -5
- package/src/mixer.ts +14 -1
- package/src/opfs_clip_pages.ts +26 -1
- package/src/project.ts +7 -0
- package/src/project_class.ts +74 -13
- package/src/project_internal.ts +24 -29
- package/src/project_types.ts +69 -10
- package/src/public_types.ts +68 -0
- package/src/public_types_mastering.ts +28 -0
- package/src/public_types_mixing.ts +11 -2
- package/src/public_types_music.ts +13 -0
- package/src/public_types_spectral.ts +43 -3
- package/src/quick_analysis.ts +48 -12
- package/src/realtime_engine.ts +162 -4
- package/src/realtime_voice_changer.ts +51 -77
- package/src/sonare-analysis.js.d.ts +8 -0
- package/src/sonare.js.d.ts +305 -9
- package/src/streaming_processors.ts +22 -1
- package/src/validation.ts +6 -0
- package/src/web_midi.ts +36 -4
- package/src/worker.ts +196 -0
- package/src/worker_client.ts +352 -0
- package/src/worker_protocol.ts +59 -0
- package/src/worklet/engine-automation.ts +2 -1
- package/src/worklet/engine-capture-facade.ts +13 -4
- package/src/worklet/engine-clips.ts +12 -3
- package/src/worklet/engine-node.ts +212 -4
- package/src/worklet/engine-offline.ts +7 -2
- package/src/worklet/engine-parameter-facade.ts +26 -5
- package/src/worklet/engine-processor.ts +383 -42
- package/src/worklet/engine-register.ts +8 -0
- package/src/worklet/engine-strips.ts +17 -1
- package/src/worklet/engine-sync.ts +2 -6
- package/src/worklet/engine-tempo-facade.ts +8 -6
- package/src/worklet/engine.ts +380 -13
- package/src/worklet/guards.ts +22 -1
- package/src/worklet/messages.ts +141 -9
- package/src/worklet/protocol.ts +303 -17
- package/src/worklet/voice-changer-processor.ts +12 -15
- package/src/worklet.ts +20 -1
package/src/feature_spectral.ts
CHANGED
|
@@ -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 {
|
|
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.
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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,
|