@libraz/libsonare 1.7.2 → 1.8.1
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/NOTICE +178 -0
- package/README.md +26 -203
- package/dist/_chain_config.d.ts +14 -0
- package/dist/_chain_config.d.ts.map +1 -0
- package/dist/_effects_common.d.ts +7 -0
- package/dist/_effects_common.d.ts.map +1 -0
- package/dist/_feature_validation.d.ts +8 -0
- package/dist/_feature_validation.d.ts.map +1 -0
- package/dist/_fft_options.d.ts +24 -0
- package/dist/_fft_options.d.ts.map +1 -0
- package/dist/align_take.d.ts +50 -0
- package/dist/align_take.d.ts.map +1 -0
- package/dist/analysis.d.ts +29 -5840
- package/dist/analysis.d.ts.map +1 -0
- package/dist/analysis.js +874 -722
- package/dist/analysis.js.map +1 -1
- package/dist/analysis_helpers.d.ts +9 -0
- package/dist/analysis_helpers.d.ts.map +1 -0
- package/dist/audio.d.ts +163 -0
- package/dist/audio.d.ts.map +1 -0
- package/dist/clip_page_streamer.d.ts +133 -0
- package/dist/clip_page_streamer.d.ts.map +1 -0
- package/dist/codes.d.ts +44 -0
- package/dist/codes.d.ts.map +1 -0
- package/dist/effects_mastering.d.ts +23 -0
- package/dist/effects_mastering.d.ts.map +1 -0
- package/dist/effects_note_ops.d.ts +502 -0
- package/dist/effects_note_ops.d.ts.map +1 -0
- package/dist/effects_percussive.d.ts +185 -0
- package/dist/effects_percussive.d.ts.map +1 -0
- package/dist/effects_separation.d.ts +65 -0
- package/dist/effects_separation.d.ts.map +1 -0
- package/dist/effects_spectral.d.ts +28 -0
- package/dist/effects_spectral.d.ts.map +1 -0
- package/dist/effects_timepitch.d.ts +134 -0
- package/dist/effects_timepitch.d.ts.map +1 -0
- package/dist/effects_voice_change.d.ts +53 -0
- package/dist/effects_voice_change.d.ts.map +1 -0
- package/dist/errors.d.ts +51 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/feature_core.d.ts +341 -0
- package/dist/feature_core.d.ts.map +1 -0
- package/dist/feature_decompose.d.ts +278 -0
- package/dist/feature_decompose.d.ts.map +1 -0
- package/dist/feature_inverse.d.ts +128 -0
- package/dist/feature_inverse.d.ts.map +1 -0
- package/dist/feature_loudness.d.ts +66 -0
- package/dist/feature_loudness.d.ts.map +1 -0
- package/dist/feature_music.d.ts +307 -0
- package/dist/feature_music.d.ts.map +1 -0
- package/dist/feature_pitch.d.ts +108 -0
- package/dist/feature_pitch.d.ts.map +1 -0
- package/dist/feature_resample.d.ts +16 -0
- package/dist/feature_resample.d.ts.map +1 -0
- package/dist/feature_spectral.d.ts +137 -0
- package/dist/feature_spectral.d.ts.map +1 -0
- package/dist/feature_spectrogram.d.ts +198 -0
- package/dist/feature_spectrogram.d.ts.map +1 -0
- package/dist/features.d.ts +10 -0
- package/dist/features.d.ts.map +1 -0
- package/dist/hrtf/default.shrf +0 -0
- package/dist/index.d.ts +74 -7431
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4173 -1621
- package/dist/index.js.map +1 -1
- package/dist/instrument_types.d.ts +517 -0
- package/dist/instrument_types.d.ts.map +1 -0
- package/dist/live_audio.d.ts +35 -0
- package/dist/live_audio.d.ts.map +1 -0
- package/dist/mastering_chain.d.ts +213 -0
- package/dist/mastering_chain.d.ts.map +1 -0
- package/dist/mastering_core.d.ts +483 -0
- package/dist/mastering_core.d.ts.map +1 -0
- package/dist/mastering_dynamics.d.ts +80 -0
- package/dist/mastering_dynamics.d.ts.map +1 -0
- package/dist/metering.d.ts +287 -0
- package/dist/metering.d.ts.map +1 -0
- package/dist/mixer.d.ts +464 -0
- package/dist/mixer.d.ts.map +1 -0
- package/dist/mixing_assistant.d.ts +62 -0
- package/dist/mixing_assistant.d.ts.map +1 -0
- package/dist/mixing_oneshot.d.ts +40 -0
- package/dist/mixing_oneshot.d.ts.map +1 -0
- package/dist/module_state.d.ts +15 -0
- package/dist/module_state.d.ts.map +1 -0
- package/dist/opfs_clip_pages.d.ts +28 -0
- package/dist/opfs_clip_pages.d.ts.map +1 -0
- package/dist/playback_renderer.d.ts +128 -0
- package/dist/playback_renderer.d.ts.map +1 -0
- package/dist/polyphony.d.ts +202 -0
- package/dist/polyphony.d.ts.map +1 -0
- package/dist/project.d.ts +8 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project_class.d.ts +562 -0
- package/dist/project_class.d.ts.map +1 -0
- package/dist/project_internal.d.ts +194 -0
- package/dist/project_internal.d.ts.map +1 -0
- package/dist/project_synth.d.ts +74 -0
- package/dist/project_synth.d.ts.map +1 -0
- package/dist/project_types.d.ts +654 -0
- package/dist/project_types.d.ts.map +1 -0
- package/dist/public_types.d.ts +185 -0
- package/dist/public_types.d.ts.map +1 -0
- package/dist/public_types_acoustic.d.ts +215 -0
- package/dist/public_types_acoustic.d.ts.map +1 -0
- package/dist/public_types_mastering.d.ts +528 -0
- package/dist/public_types_mastering.d.ts.map +1 -0
- package/dist/public_types_mixing.d.ts +436 -0
- package/dist/public_types_mixing.d.ts.map +1 -0
- package/dist/public_types_music.d.ts +619 -0
- package/dist/public_types_music.d.ts.map +1 -0
- package/dist/public_types_playback.d.ts +165 -0
- package/dist/public_types_playback.d.ts.map +1 -0
- package/dist/public_types_realtime.d.ts +174 -0
- package/dist/public_types_realtime.d.ts.map +1 -0
- package/dist/public_types_repair.d.ts +424 -0
- package/dist/public_types_repair.d.ts.map +1 -0
- package/dist/public_types_spectral.d.ts +697 -0
- package/dist/public_types_spectral.d.ts.map +1 -0
- package/dist/quick_analysis.d.ts +445 -0
- package/dist/quick_analysis.d.ts.map +1 -0
- package/dist/realtime_engine.d.ts +893 -0
- package/dist/realtime_engine.d.ts.map +1 -0
- package/dist/realtime_voice_changer.d.ts +158 -0
- package/dist/realtime_voice_changer.d.ts.map +1 -0
- package/dist/repair_dereverb.d.ts +187 -0
- package/dist/repair_dereverb.d.ts.map +1 -0
- package/dist/repair_impulsive.d.ts +186 -0
- package/dist/repair_impulsive.d.ts.map +1 -0
- package/dist/repair_noise.d.ts +239 -0
- package/dist/repair_noise.d.ts.map +1 -0
- package/dist/repair_trim.d.ts +123 -0
- package/dist/repair_trim.d.ts.map +1 -0
- package/dist/sample_bank.d.ts +84 -0
- package/dist/sample_bank.d.ts.map +1 -0
- package/dist/scale.d.ts +10 -0
- package/dist/scale.d.ts.map +1 -0
- package/dist/schemas/mixer-scene.schema.json +393 -0
- package/dist/schemas/playback-renderer-config.schema.json +392 -0
- package/dist/sonare-analysis.d.ts +8 -0
- package/dist/sonare-analysis.js +2 -2
- package/dist/sonare-analysis.wasm +0 -0
- package/dist/sonare.d.ts +3945 -0
- package/dist/sonare.js +2 -2
- package/dist/sonare.wasm +0 -0
- package/dist/stream_analyzer.d.ts +163 -0
- package/dist/stream_analyzer.d.ts.map +1 -0
- package/dist/stream_types.d.ts +214 -0
- package/dist/stream_types.d.ts.map +1 -0
- package/dist/streaming_mixing.d.ts +6 -0
- package/dist/streaming_mixing.d.ts.map +1 -0
- package/dist/streaming_processors.d.ts +340 -0
- package/dist/streaming_processors.d.ts.map +1 -0
- package/dist/transcribe.d.ts +77 -0
- package/dist/transcribe.d.ts.map +1 -0
- package/dist/validation.d.ts +140 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/web_midi.d.ts +77 -0
- package/dist/web_midi.d.ts.map +1 -0
- package/dist/worker.d.ts +5 -48
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +94 -41
- package/dist/worker.js.map +1 -1
- package/dist/worker_client.d.ts +96 -0
- package/dist/worker_client.d.ts.map +1 -0
- package/dist/worker_protocol.d.ts +43 -0
- package/dist/worker_protocol.d.ts.map +1 -0
- package/dist/worklet/audio_types.d.ts +21 -0
- package/dist/worklet/audio_types.d.ts.map +1 -0
- package/dist/worklet/engine-automation.d.ts +29 -0
- package/dist/worklet/engine-automation.d.ts.map +1 -0
- package/dist/worklet/engine-capture-facade.d.ts +35 -0
- package/dist/worklet/engine-capture-facade.d.ts.map +1 -0
- package/dist/worklet/engine-clips.d.ts +23 -0
- package/dist/worklet/engine-clips.d.ts.map +1 -0
- package/dist/worklet/engine-markers.d.ts +40 -0
- package/dist/worklet/engine-markers.d.ts.map +1 -0
- package/dist/worklet/engine-mixer-facade.d.ts +164 -0
- package/dist/worklet/engine-mixer-facade.d.ts.map +1 -0
- package/dist/worklet/engine-node.d.ts +83 -0
- package/dist/worklet/engine-node.d.ts.map +1 -0
- package/dist/worklet/engine-offline.d.ts +81 -0
- package/dist/worklet/engine-offline.d.ts.map +1 -0
- package/dist/worklet/engine-options.d.ts +12 -0
- package/dist/worklet/engine-options.d.ts.map +1 -0
- package/dist/worklet/engine-parameter-facade.d.ts +106 -0
- package/dist/worklet/engine-parameter-facade.d.ts.map +1 -0
- package/dist/worklet/engine-processor.d.ts +72 -0
- package/dist/worklet/engine-processor.d.ts.map +1 -0
- package/dist/worklet/engine-register.d.ts +2 -0
- package/dist/worklet/engine-register.d.ts.map +1 -0
- package/dist/worklet/engine-strips.d.ts +75 -0
- package/dist/worklet/engine-strips.d.ts.map +1 -0
- package/dist/worklet/engine-sync.d.ts +39 -0
- package/dist/worklet/engine-sync.d.ts.map +1 -0
- package/dist/worklet/engine-tempo-facade.d.ts +48 -0
- package/dist/worklet/engine-tempo-facade.d.ts.map +1 -0
- package/dist/worklet/engine.d.ts +418 -0
- package/dist/worklet/engine.d.ts.map +1 -0
- package/dist/worklet/guards.d.ts +53 -0
- package/dist/worklet/guards.d.ts.map +1 -0
- package/dist/worklet/messages.d.ts +710 -0
- package/dist/worklet/messages.d.ts.map +1 -0
- package/dist/worklet/mixer-processor.d.ts +46 -0
- package/dist/worklet/mixer-processor.d.ts.map +1 -0
- package/dist/worklet/playback-processor.d.ts +62 -0
- package/dist/worklet/playback-processor.d.ts.map +1 -0
- package/dist/worklet/protocol.d.ts +331 -0
- package/dist/worklet/protocol.d.ts.map +1 -0
- package/dist/worklet/voice-changer-processor.d.ts +41 -0
- package/dist/worklet/voice-changer-processor.d.ts.map +1 -0
- package/dist/worklet.d.ts +16 -2515
- package/dist/worklet.d.ts.map +1 -0
- package/dist/worklet.js +3200 -541
- package/dist/worklet.js.map +1 -1
- package/package.json +23 -12
- package/src/_effects_common.ts +47 -0
- package/src/_feature_validation.ts +34 -0
- package/src/_fft_options.ts +39 -0
- package/src/align_take.ts +64 -0
- package/src/analysis.ts +56 -3
- package/src/analysis_helpers.ts +7 -0
- package/src/audio.ts +106 -3
- package/src/codes.ts +39 -2
- package/src/effects_mastering.ts +101 -22
- package/src/effects_note_ops.ts +683 -0
- package/src/effects_percussive.ts +217 -0
- package/src/effects_separation.ts +150 -0
- package/src/effects_spectral.ts +60 -0
- package/src/effects_timepitch.ts +388 -0
- package/src/errors.ts +23 -1
- package/src/feature_core.ts +127 -2
- package/src/feature_decompose.ts +633 -0
- package/src/feature_inverse.ts +454 -0
- package/src/feature_loudness.ts +125 -0
- package/src/feature_music.ts +107 -14
- package/src/feature_pitch.ts +96 -1
- package/src/feature_spectral.ts +16 -611
- package/src/feature_spectrogram.ts +63 -450
- package/src/features.ts +36 -22
- package/src/index.ts +288 -30
- package/src/instrument_types.ts +645 -0
- package/src/live_audio.ts +27 -1
- package/src/mastering_chain.ts +184 -0
- package/src/mastering_core.ts +441 -32
- package/src/mastering_dynamics.ts +22 -11
- package/src/metering.ts +67 -24
- package/src/mixer.ts +251 -22
- package/src/mixing_assistant.ts +138 -0
- package/src/mixing_oneshot.ts +10 -5
- package/src/module_state.ts +24 -2
- package/src/playback_renderer.ts +252 -0
- package/src/polyphony.ts +279 -0
- package/src/project.ts +61 -24
- package/src/project_class.ts +450 -27
- package/src/project_internal.ts +149 -42
- package/src/project_synth.ts +67 -1
- package/src/project_types.ts +271 -271
- package/src/public_types.ts +122 -3
- package/src/public_types_acoustic.ts +112 -3
- package/src/public_types_mastering.ts +275 -73
- package/src/public_types_mixing.ts +363 -1
- package/src/public_types_music.ts +312 -2
- package/src/public_types_playback.ts +196 -0
- package/src/public_types_realtime.ts +39 -7
- package/src/public_types_repair.ts +446 -0
- package/src/public_types_spectral.ts +491 -5
- package/src/quick_analysis.ts +203 -26
- package/src/realtime_engine.ts +773 -34
- package/src/realtime_voice_changer.ts +55 -1
- package/src/repair_dereverb.ts +299 -0
- package/src/repair_impulsive.ts +395 -0
- package/src/repair_noise.ts +425 -0
- package/src/repair_trim.ts +226 -0
- package/src/sample_bank.ts +113 -0
- package/src/sonare.js.d.ts +1158 -30
- package/src/stream_analyzer.ts +36 -4
- package/src/stream_types.ts +37 -0
- package/src/streaming_mixing.ts +1 -1
- package/src/streaming_processors.ts +202 -10
- package/src/transcribe.ts +89 -0
- package/src/validation.ts +285 -11
- package/src/web_midi.ts +1 -6
- package/src/worker.ts +18 -2
- package/src/worklet/audio_types.ts +37 -0
- package/src/worklet/engine-mixer-facade.ts +800 -32
- package/src/worklet/engine-node.ts +99 -29
- package/src/worklet/engine-offline.ts +14 -8
- package/src/worklet/engine-parameter-facade.ts +21 -0
- package/src/worklet/engine-processor.ts +332 -93
- package/src/worklet/engine-register.ts +32 -18
- package/src/worklet/engine-strips.ts +275 -9
- package/src/worklet/engine-sync.ts +20 -7
- package/src/worklet/engine.ts +394 -48
- package/src/worklet/guards.ts +195 -44
- package/src/worklet/messages.ts +229 -2
- package/src/worklet/mixer-processor.ts +117 -48
- package/src/worklet/playback-processor.ts +300 -0
- package/src/worklet/protocol.ts +82 -11
- package/src/worklet/voice-changer-processor.ts +17 -11
- package/src/worklet.ts +17 -0
- package/src/effects_transform.ts +0 -718
- package/src/mastering_repair.ts +0 -273
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time and pitch transforms over a whole buffer: stretching, shifting, and
|
|
3
|
+
* correction onto a target pitch.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { assertPitchTrackLengths, toVoicedFloat32 } from './_effects_common';
|
|
7
|
+
import { resolveFftOptions } from './_fft_options';
|
|
8
|
+
import { getSonareModule } from './module_state';
|
|
9
|
+
import type { PitchCorrectOptions, VoicedFlags } from './public_types';
|
|
10
|
+
import type { ValidateOptions } from './validation';
|
|
11
|
+
import { assertFiniteScalar, assertSamples } from './validation';
|
|
12
|
+
|
|
13
|
+
function requireModule() {
|
|
14
|
+
return getSonareModule();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface TimeStretchRequest extends ValidateOptions {
|
|
18
|
+
samples: Float32Array;
|
|
19
|
+
sampleRate?: number;
|
|
20
|
+
rate: number;
|
|
21
|
+
nFft?: number;
|
|
22
|
+
hopLength?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface PitchShiftRequest extends ValidateOptions {
|
|
26
|
+
samples: Float32Array;
|
|
27
|
+
sampleRate?: number;
|
|
28
|
+
semitones: number;
|
|
29
|
+
nFft?: number;
|
|
30
|
+
hopLength?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface PitchCorrectToMidiRequest extends ValidateOptions {
|
|
34
|
+
samples: Float32Array;
|
|
35
|
+
sampleRate?: number;
|
|
36
|
+
currentMidi?: number;
|
|
37
|
+
targetMidi?: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface PitchCorrectToMidiTimevaryingRequest extends ValidateOptions {
|
|
41
|
+
samples: Float32Array;
|
|
42
|
+
f0Hz: Float32Array;
|
|
43
|
+
targetMidi: number;
|
|
44
|
+
sampleRate?: number;
|
|
45
|
+
hopLength?: number;
|
|
46
|
+
voiced?: VoicedFlags | null;
|
|
47
|
+
voicedProb?: Float32Array | null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface PitchCorrectTimevaryingRequest extends PitchCorrectOptions {
|
|
51
|
+
samples: Float32Array;
|
|
52
|
+
f0Hz: Float32Array;
|
|
53
|
+
sampleRate?: number;
|
|
54
|
+
hopLength?: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Time-stretch audio without changing pitch.
|
|
59
|
+
*
|
|
60
|
+
* @param samples - Audio samples (mono, float32)
|
|
61
|
+
* @param sampleRate - Sample rate in Hz (default: 22050)
|
|
62
|
+
* @param rate - Time stretch rate (0.5 = double duration, 2.0 = half duration)
|
|
63
|
+
* @param nFft - FFT size: an even integer >= 2 (default 2048)
|
|
64
|
+
* @param hopLength - Hop in samples, in `(0, nFft / 2]` (default 512), so
|
|
65
|
+
* frames overlap by at least half a window
|
|
66
|
+
* @returns Time-stretched audio
|
|
67
|
+
*/
|
|
68
|
+
export function timeStretch(request: TimeStretchRequest): Float32Array;
|
|
69
|
+
export function timeStretch(
|
|
70
|
+
samples: Float32Array,
|
|
71
|
+
sampleRate: number,
|
|
72
|
+
rate: number,
|
|
73
|
+
options?: ValidateOptions,
|
|
74
|
+
): Float32Array;
|
|
75
|
+
export function timeStretch(
|
|
76
|
+
samples: Float32Array,
|
|
77
|
+
sampleRate: number,
|
|
78
|
+
rate: number,
|
|
79
|
+
nFft?: number,
|
|
80
|
+
hopLength?: number,
|
|
81
|
+
options?: ValidateOptions,
|
|
82
|
+
): Float32Array;
|
|
83
|
+
export function timeStretch(
|
|
84
|
+
samples: Float32Array | TimeStretchRequest,
|
|
85
|
+
sampleRate?: number,
|
|
86
|
+
rate?: number,
|
|
87
|
+
nFftOrOptions?: number | ValidateOptions,
|
|
88
|
+
hopLength?: number,
|
|
89
|
+
options: ValidateOptions = {},
|
|
90
|
+
): Float32Array {
|
|
91
|
+
if (
|
|
92
|
+
nFftOrOptions !== undefined &&
|
|
93
|
+
nFftOrOptions !== null &&
|
|
94
|
+
typeof nFftOrOptions !== 'number' &&
|
|
95
|
+
typeof nFftOrOptions !== 'object'
|
|
96
|
+
) {
|
|
97
|
+
throw new TypeError('timeStretch: nFft must be an integer or options object');
|
|
98
|
+
}
|
|
99
|
+
if (nFftOrOptions === null) {
|
|
100
|
+
throw new TypeError('timeStretch: nFft must be an integer or options object');
|
|
101
|
+
}
|
|
102
|
+
const positionalOptions =
|
|
103
|
+
typeof nFftOrOptions === 'object' && nFftOrOptions !== null ? nFftOrOptions : options;
|
|
104
|
+
const positionalNFft = typeof nFftOrOptions === 'number' ? nFftOrOptions : undefined;
|
|
105
|
+
const request: TimeStretchRequest =
|
|
106
|
+
samples instanceof Float32Array
|
|
107
|
+
? {
|
|
108
|
+
samples,
|
|
109
|
+
sampleRate,
|
|
110
|
+
rate: rate as number,
|
|
111
|
+
nFft: positionalNFft,
|
|
112
|
+
hopLength,
|
|
113
|
+
...positionalOptions,
|
|
114
|
+
}
|
|
115
|
+
: samples;
|
|
116
|
+
assertSamples('timeStretch', request.samples, request.validate !== false);
|
|
117
|
+
// Matches the addon, which refuses a non-finite rate here rather than letting
|
|
118
|
+
// the core answer it. Does NOT cover a finite value too wide for a float:
|
|
119
|
+
// Number.isFinite(1e39) is true and the demotion to the f32 parameter makes it
|
|
120
|
+
// an infinity, which only the binding-side narrowing can see.
|
|
121
|
+
assertFiniteScalar('timeStretch', request.rate as number, 'rate');
|
|
122
|
+
const fftOptions = resolveFftOptions('timeStretch', request.nFft, request.hopLength);
|
|
123
|
+
return requireModule().timeStretchEx(
|
|
124
|
+
request.samples,
|
|
125
|
+
request.sampleRate ?? 22050,
|
|
126
|
+
request.rate,
|
|
127
|
+
fftOptions.nFft,
|
|
128
|
+
fftOptions.hopLength,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Pitch-shift audio without changing duration.
|
|
134
|
+
*
|
|
135
|
+
* @param samples - Audio samples (mono, float32)
|
|
136
|
+
* @param sampleRate - Sample rate in Hz (default: 22050)
|
|
137
|
+
* @param semitones - Pitch shift in semitones (+12 = one octave up, -12 = one octave down)
|
|
138
|
+
* @param nFft - FFT size: an even integer >= 2 (default 2048)
|
|
139
|
+
* @param hopLength - Hop in samples, in `(0, nFft / 2]` (default 512), so
|
|
140
|
+
* frames overlap by at least half a window
|
|
141
|
+
* @returns Pitch-shifted audio
|
|
142
|
+
*/
|
|
143
|
+
export function pitchShift(request: PitchShiftRequest): Float32Array;
|
|
144
|
+
export function pitchShift(
|
|
145
|
+
samples: Float32Array,
|
|
146
|
+
sampleRate: number,
|
|
147
|
+
semitones: number,
|
|
148
|
+
options?: ValidateOptions,
|
|
149
|
+
): Float32Array;
|
|
150
|
+
export function pitchShift(
|
|
151
|
+
samples: Float32Array,
|
|
152
|
+
sampleRate: number,
|
|
153
|
+
semitones: number,
|
|
154
|
+
nFft?: number,
|
|
155
|
+
hopLength?: number,
|
|
156
|
+
options?: ValidateOptions,
|
|
157
|
+
): Float32Array;
|
|
158
|
+
export function pitchShift(
|
|
159
|
+
samples: Float32Array | PitchShiftRequest,
|
|
160
|
+
sampleRate?: number,
|
|
161
|
+
semitones?: number,
|
|
162
|
+
nFftOrOptions?: number | ValidateOptions,
|
|
163
|
+
hopLength?: number,
|
|
164
|
+
options: ValidateOptions = {},
|
|
165
|
+
): Float32Array {
|
|
166
|
+
if (
|
|
167
|
+
nFftOrOptions !== undefined &&
|
|
168
|
+
nFftOrOptions !== null &&
|
|
169
|
+
typeof nFftOrOptions !== 'number' &&
|
|
170
|
+
typeof nFftOrOptions !== 'object'
|
|
171
|
+
) {
|
|
172
|
+
throw new TypeError('pitchShift: nFft must be an integer or options object');
|
|
173
|
+
}
|
|
174
|
+
if (nFftOrOptions === null) {
|
|
175
|
+
throw new TypeError('pitchShift: nFft must be an integer or options object');
|
|
176
|
+
}
|
|
177
|
+
const positionalOptions =
|
|
178
|
+
typeof nFftOrOptions === 'object' && nFftOrOptions !== null ? nFftOrOptions : options;
|
|
179
|
+
const positionalNFft = typeof nFftOrOptions === 'number' ? nFftOrOptions : undefined;
|
|
180
|
+
const request: PitchShiftRequest =
|
|
181
|
+
samples instanceof Float32Array
|
|
182
|
+
? {
|
|
183
|
+
samples,
|
|
184
|
+
sampleRate,
|
|
185
|
+
semitones: semitones as number,
|
|
186
|
+
nFft: positionalNFft,
|
|
187
|
+
hopLength,
|
|
188
|
+
...positionalOptions,
|
|
189
|
+
}
|
|
190
|
+
: samples;
|
|
191
|
+
assertSamples('pitchShift', request.samples, request.validate !== false);
|
|
192
|
+
// See timeStretch above for what this does and does not cover.
|
|
193
|
+
assertFiniteScalar('pitchShift', request.semitones as number, 'semitones');
|
|
194
|
+
const fftOptions = resolveFftOptions('pitchShift', request.nFft, request.hopLength);
|
|
195
|
+
return requireModule().pitchShiftEx(
|
|
196
|
+
request.samples,
|
|
197
|
+
request.sampleRate ?? 22050,
|
|
198
|
+
request.semitones,
|
|
199
|
+
fftOptions.nFft,
|
|
200
|
+
fftOptions.hopLength,
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Pitch-correct audio from a current MIDI note to a target MIDI note.
|
|
206
|
+
*
|
|
207
|
+
* Applies one constant, immediate transpose with no retune glide and preserves
|
|
208
|
+
* the input buffer length. The whole interval is applied however large it is:
|
|
209
|
+
* both endpoints are validated to [0, 127], so a two-octave move such as
|
|
210
|
+
* C3 -> C5 transposes by the full 24 semitones. Use
|
|
211
|
+
* {@link pitchCorrectToMidiTimevarying} for a caller-supplied pitch contour.
|
|
212
|
+
*
|
|
213
|
+
* @param samples - Audio samples (mono, float32)
|
|
214
|
+
* @param sampleRate - Sample rate in Hz
|
|
215
|
+
* @param currentMidi - Detected/current MIDI note number
|
|
216
|
+
* @param targetMidi - Desired MIDI note number
|
|
217
|
+
* @returns Pitch-corrected audio
|
|
218
|
+
*/
|
|
219
|
+
export function pitchCorrectToMidi(request: PitchCorrectToMidiRequest): Float32Array;
|
|
220
|
+
export function pitchCorrectToMidi(
|
|
221
|
+
samples: Float32Array,
|
|
222
|
+
sampleRate?: number,
|
|
223
|
+
currentMidi?: number,
|
|
224
|
+
targetMidi?: number,
|
|
225
|
+
options?: ValidateOptions,
|
|
226
|
+
): Float32Array;
|
|
227
|
+
export function pitchCorrectToMidi(
|
|
228
|
+
samples: Float32Array | PitchCorrectToMidiRequest,
|
|
229
|
+
sampleRate = 22050,
|
|
230
|
+
currentMidi = 69.0,
|
|
231
|
+
targetMidi = 69.0,
|
|
232
|
+
options: ValidateOptions = {},
|
|
233
|
+
): Float32Array {
|
|
234
|
+
const request =
|
|
235
|
+
samples instanceof Float32Array
|
|
236
|
+
? { samples, sampleRate, currentMidi, targetMidi, ...options }
|
|
237
|
+
: samples;
|
|
238
|
+
assertSamples('pitchCorrectToMidi', request.samples, request.validate !== false);
|
|
239
|
+
return requireModule().pitchCorrectToMidi(
|
|
240
|
+
request.samples,
|
|
241
|
+
request.sampleRate ?? 22050,
|
|
242
|
+
request.currentMidi ?? 69.0,
|
|
243
|
+
request.targetMidi ?? 69.0,
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Contour-following ("time-varying") pitch correction toward a MIDI target.
|
|
249
|
+
*
|
|
250
|
+
* Unlike {@link pitchCorrectToMidi} (a single constant transpose), this follows
|
|
251
|
+
* the caller-supplied per-frame `f0Hz` contour and retunes every voiced frame
|
|
252
|
+
* toward `targetMidi`, so vibrato/drift in the source is tracked rather than
|
|
253
|
+
* flattened. When `voiced` is supplied (truthy = voiced), it takes precedence
|
|
254
|
+
* over `voicedProb`; omitting it or passing `null` uses the probability array.
|
|
255
|
+
* When both are omitted, every frame is treated as voiced. An `f0Hz` NaN is
|
|
256
|
+
* accepted only for a frame marked unvoiced, matching pYIN output. The
|
|
257
|
+
* `voicedFlag` / `voicedProb` arrays of a {@link PitchResult} can
|
|
258
|
+
* be passed through directly.
|
|
259
|
+
*
|
|
260
|
+
* @param samples - Audio samples (mono, float32)
|
|
261
|
+
* @param f0Hz - Per-frame measured F0 in Hz (one entry per analysis frame)
|
|
262
|
+
* @param targetMidi - Desired MIDI note number
|
|
263
|
+
* @param sampleRate - Sample rate in Hz
|
|
264
|
+
* @param hopLength - F0 frame-center spacing in samples. Frame i is centered at
|
|
265
|
+
* sample i*hopLength; nearest-frame voicing switches halfway between centers.
|
|
266
|
+
* @param voiced - Optional per-frame voiced flags (truthy = voiced); takes
|
|
267
|
+
* precedence over `voicedProb`.
|
|
268
|
+
* @param voicedProb - Optional per-frame voicing probability in [0, 1]; used
|
|
269
|
+
* when `voiced` is omitted or `null`.
|
|
270
|
+
* @returns Pitch-corrected audio
|
|
271
|
+
*/
|
|
272
|
+
export function pitchCorrectToMidiTimevarying(
|
|
273
|
+
request: PitchCorrectToMidiTimevaryingRequest,
|
|
274
|
+
): Float32Array;
|
|
275
|
+
export function pitchCorrectToMidiTimevarying(
|
|
276
|
+
samples: Float32Array,
|
|
277
|
+
f0Hz: Float32Array,
|
|
278
|
+
targetMidi: number,
|
|
279
|
+
sampleRate?: number,
|
|
280
|
+
hopLength?: number,
|
|
281
|
+
voiced?: VoicedFlags | null,
|
|
282
|
+
voicedProb?: Float32Array | null,
|
|
283
|
+
options?: ValidateOptions,
|
|
284
|
+
): Float32Array;
|
|
285
|
+
export function pitchCorrectToMidiTimevarying(
|
|
286
|
+
samples: Float32Array | PitchCorrectToMidiTimevaryingRequest,
|
|
287
|
+
f0Hz?: Float32Array,
|
|
288
|
+
targetMidi?: number,
|
|
289
|
+
sampleRate = 22050,
|
|
290
|
+
hopLength = 512,
|
|
291
|
+
voiced?: VoicedFlags | null,
|
|
292
|
+
voicedProb?: Float32Array | null,
|
|
293
|
+
options: ValidateOptions = {},
|
|
294
|
+
): Float32Array {
|
|
295
|
+
const request: PitchCorrectToMidiTimevaryingRequest =
|
|
296
|
+
samples instanceof Float32Array
|
|
297
|
+
? {
|
|
298
|
+
samples,
|
|
299
|
+
f0Hz: f0Hz as Float32Array,
|
|
300
|
+
targetMidi: targetMidi as number,
|
|
301
|
+
sampleRate,
|
|
302
|
+
hopLength,
|
|
303
|
+
voiced,
|
|
304
|
+
voicedProb,
|
|
305
|
+
...options,
|
|
306
|
+
}
|
|
307
|
+
: samples;
|
|
308
|
+
assertSamples('pitchCorrectToMidiTimevarying', request.samples, request.validate !== false);
|
|
309
|
+
const voicedF32 =
|
|
310
|
+
request.voiced == null
|
|
311
|
+
? undefined
|
|
312
|
+
: toVoicedFloat32('pitchCorrectToMidiTimevarying', request.voiced);
|
|
313
|
+
assertPitchTrackLengths(
|
|
314
|
+
'pitchCorrectToMidiTimevarying',
|
|
315
|
+
request.f0Hz,
|
|
316
|
+
request.voiced,
|
|
317
|
+
request.voicedProb,
|
|
318
|
+
);
|
|
319
|
+
return requireModule().pitchCorrectToMidiTimevarying(
|
|
320
|
+
request.samples,
|
|
321
|
+
request.sampleRate ?? 22050,
|
|
322
|
+
request.f0Hz,
|
|
323
|
+
request.targetMidi,
|
|
324
|
+
request.hopLength ?? 512,
|
|
325
|
+
voicedF32,
|
|
326
|
+
request.voiced == null ? (request.voicedProb ?? undefined) : undefined,
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Contour-following pitch correction toward a fixed MIDI note OR a musical
|
|
332
|
+
* scale, with tunable retune strength and vibrato preservation.
|
|
333
|
+
*
|
|
334
|
+
* Generalises {@link pitchCorrectToMidiTimevarying}: the same caller-supplied
|
|
335
|
+
* per-frame `f0Hz` contour drives correction, but `options.mode` selects between
|
|
336
|
+
* a fixed-MIDI target (`'midi'`, default) and scale quantisation (`'scale'`),
|
|
337
|
+
* and the retune knobs shape natural-vs-robotic correction. An `f0Hz` NaN is
|
|
338
|
+
* accepted only for a frame marked unvoiced.
|
|
339
|
+
*
|
|
340
|
+
* @param samples - Audio samples (mono, float32)
|
|
341
|
+
* @param f0Hz - Per-frame measured F0 in Hz (one entry per analysis frame)
|
|
342
|
+
* @param sampleRate - Sample rate in Hz
|
|
343
|
+
* @param hopLength - F0 frame-center spacing in samples. Frame i is centered at
|
|
344
|
+
* sample i*hopLength; nearest-frame voicing switches halfway between centers.
|
|
345
|
+
* @param options - Target mode + retune knobs + optional voiced/voicedProb arrays
|
|
346
|
+
* @returns Pitch-corrected audio
|
|
347
|
+
*/
|
|
348
|
+
export function pitchCorrectTimevarying(request: PitchCorrectTimevaryingRequest): Float32Array;
|
|
349
|
+
export function pitchCorrectTimevarying(
|
|
350
|
+
samples: Float32Array,
|
|
351
|
+
f0Hz: Float32Array,
|
|
352
|
+
sampleRate?: number,
|
|
353
|
+
hopLength?: number,
|
|
354
|
+
options?: PitchCorrectOptions,
|
|
355
|
+
): Float32Array;
|
|
356
|
+
export function pitchCorrectTimevarying(
|
|
357
|
+
samples: Float32Array | PitchCorrectTimevaryingRequest,
|
|
358
|
+
f0Hz?: Float32Array,
|
|
359
|
+
sampleRate = 22050,
|
|
360
|
+
hopLength = 512,
|
|
361
|
+
options: PitchCorrectOptions = {},
|
|
362
|
+
): Float32Array {
|
|
363
|
+
const request: PitchCorrectTimevaryingRequest =
|
|
364
|
+
samples instanceof Float32Array
|
|
365
|
+
? { samples, f0Hz: f0Hz as Float32Array, sampleRate, hopLength, ...options }
|
|
366
|
+
: samples;
|
|
367
|
+
assertSamples('pitchCorrectTimevarying', request.samples, request.validate !== false);
|
|
368
|
+
const voicedF32 =
|
|
369
|
+
request.voiced == null ? undefined : toVoicedFloat32('pitchCorrectTimevarying', request.voiced);
|
|
370
|
+
assertPitchTrackLengths(
|
|
371
|
+
'pitchCorrectTimevarying',
|
|
372
|
+
request.f0Hz,
|
|
373
|
+
request.voiced,
|
|
374
|
+
request.voicedProb,
|
|
375
|
+
);
|
|
376
|
+
const nativeOptions = {
|
|
377
|
+
...request,
|
|
378
|
+
voiced: voicedF32,
|
|
379
|
+
voicedProb: request.voiced == null ? (request.voicedProb ?? undefined) : undefined,
|
|
380
|
+
};
|
|
381
|
+
return requireModule().pitchCorrectTimevarying(
|
|
382
|
+
request.samples,
|
|
383
|
+
request.sampleRate ?? 22050,
|
|
384
|
+
request.f0Hz,
|
|
385
|
+
request.hopLength ?? 512,
|
|
386
|
+
nativeOptions,
|
|
387
|
+
);
|
|
388
|
+
}
|
package/src/errors.ts
CHANGED
|
@@ -13,6 +13,7 @@ export enum ErrorCode {
|
|
|
13
13
|
NotSupported = 6,
|
|
14
14
|
InvalidState = 7,
|
|
15
15
|
Cancelled = 8,
|
|
16
|
+
EncodeFailed = 9,
|
|
16
17
|
Unknown = 99,
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -20,6 +21,10 @@ export enum ErrorCode {
|
|
|
20
21
|
* Error thrown by libsonare on a native (C++) failure. Carries a numeric
|
|
21
22
|
* {@link ErrorCode} `code` plus its canonical `codeName`, so callers can branch
|
|
22
23
|
* on the cause instead of matching message text.
|
|
24
|
+
*
|
|
25
|
+
* Narrow a caught value with {@link isSonareError} or with `instanceof`; both
|
|
26
|
+
* accept the same values. The Node package exports the same class under the
|
|
27
|
+
* same name.
|
|
23
28
|
*/
|
|
24
29
|
export class SonareError extends Error {
|
|
25
30
|
/** Numeric error code, equal to an {@link ErrorCode} value. */
|
|
@@ -33,9 +38,26 @@ export class SonareError extends Error {
|
|
|
33
38
|
this.code = code;
|
|
34
39
|
this.codeName = codeName;
|
|
35
40
|
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Brand-based `instanceof`: an error that carries the shape narrows here even
|
|
44
|
+
* when it is not literally an instance of this class. That is not a
|
|
45
|
+
* hypothetical — an error posted from the analysis worker arrives as a
|
|
46
|
+
* structured clone with its prototype gone, which a prototype-based
|
|
47
|
+
* `instanceof` would silently miss. Delegates to {@link isSonareError} so the
|
|
48
|
+
* two never disagree.
|
|
49
|
+
*/
|
|
50
|
+
static [Symbol.hasInstance](value: unknown): value is SonareError {
|
|
51
|
+
return isSonareError(value);
|
|
52
|
+
}
|
|
36
53
|
}
|
|
37
54
|
|
|
38
|
-
/**
|
|
55
|
+
/**
|
|
56
|
+
* Type guard: whether a caught value is a libsonare {@link SonareError}.
|
|
57
|
+
*
|
|
58
|
+
* Duck-typed on purpose: a value that crossed a worker boundary has lost its
|
|
59
|
+
* prototype, so a prototype check would miss it.
|
|
60
|
+
*/
|
|
39
61
|
export function isSonareError(value: unknown): value is SonareError {
|
|
40
62
|
return (
|
|
41
63
|
value instanceof Error &&
|
package/src/feature_core.ts
CHANGED
|
@@ -104,6 +104,72 @@ export interface SilenceRequest {
|
|
|
104
104
|
hopLength?: number;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
/** Canonical request form for the common-silence union of several signals. */
|
|
108
|
+
export interface SplitSilenceCommonRequest {
|
|
109
|
+
signals: Float32Array[];
|
|
110
|
+
topDb?: number;
|
|
111
|
+
frameLength?: number;
|
|
112
|
+
hopLength?: number;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Why {@link splitSilenceCommonWithReport} found the gaps it did.
|
|
117
|
+
*
|
|
118
|
+
* One interval covering everything is the answer to three different situations
|
|
119
|
+
* and the interval list cannot separate them: no take has a quiet moment at all,
|
|
120
|
+
* the takes each have one but not in the same place, or `topDb` was set too loose
|
|
121
|
+
* to see the ones they have.
|
|
122
|
+
*
|
|
123
|
+
* **Read {@link silenceCeilingDb} against the `topDb` that was passed**, which is
|
|
124
|
+
* the whole decision:
|
|
125
|
+
*
|
|
126
|
+
* - ceiling near 0 — a take is sounding continuously. No threshold helps, and a
|
|
127
|
+
* cut point has to come from somewhere other than silence.
|
|
128
|
+
* - ceiling below `topDb` — the threshold was too loose to see the quiet these
|
|
129
|
+
* takes do have. A `topDb` under the reported ceiling finds it.
|
|
130
|
+
* - ceiling at or above `topDb`, and still one interval — every take shows silence
|
|
131
|
+
* at this setting and they do not share any of it. That is the alignment case,
|
|
132
|
+
* and it is what {@link alignTakeToReference} is for.
|
|
133
|
+
*
|
|
134
|
+
* The figures come from the same RMS pass the intervals do, so they can never
|
|
135
|
+
* describe a different measurement.
|
|
136
|
+
*/
|
|
137
|
+
export interface SilenceCommonReport {
|
|
138
|
+
/**
|
|
139
|
+
* The largest `topDb` at which EVERY signal still shows silence.
|
|
140
|
+
*
|
|
141
|
+
* A frame counts as silent when it sits at least `topDb` under its own signal's
|
|
142
|
+
* peak RMS, so each signal's deepest dip decides whether any threshold can find
|
|
143
|
+
* silence in it, and the union needs all of them quiet at once — hence the
|
|
144
|
+
* minimum across the signals. 0 for an all-silent signal, where the peak is 0
|
|
145
|
+
* and the ratio has no value; 120 is the floor the dB conversion clamps at,
|
|
146
|
+
* reported for a signal holding a zero-valued frame.
|
|
147
|
+
*/
|
|
148
|
+
silenceCeilingDb: number;
|
|
149
|
+
/**
|
|
150
|
+
* How many intervals the most fragmented signal produced alone, counted before
|
|
151
|
+
* the union merges anything.
|
|
152
|
+
*
|
|
153
|
+
* A measure of shape rather than of cause: 1 is a take that sounds once and
|
|
154
|
+
* stops, so a take that is loud then silent counts 1 exactly as a take with no
|
|
155
|
+
* silence does. Use {@link silenceCeilingDb} to tell those apart; use these two
|
|
156
|
+
* to see whether any take has an interior gap at all (`>= 2`) and whether the
|
|
157
|
+
* takes differ in how broken up they are (`maxSignalIntervals !==
|
|
158
|
+
* minSignalIntervals`).
|
|
159
|
+
*/
|
|
160
|
+
maxSignalIntervals: number;
|
|
161
|
+
/** How many intervals the least fragmented signal produced alone. */
|
|
162
|
+
minSignalIntervals: number;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** Result of {@link splitSilenceCommonWithReport}. */
|
|
166
|
+
export interface SplitSilenceCommonWithReportResult {
|
|
167
|
+
/** Exactly what {@link splitSilenceCommon} returns for the same arguments. */
|
|
168
|
+
intervals: Int32Array;
|
|
169
|
+
/** Why those are the intervals. */
|
|
170
|
+
report: SilenceCommonReport;
|
|
171
|
+
}
|
|
172
|
+
|
|
107
173
|
export interface FrameSignalRequest {
|
|
108
174
|
samples: Float32Array;
|
|
109
175
|
frameLength: number;
|
|
@@ -228,6 +294,12 @@ export interface PlpRequest {
|
|
|
228
294
|
/**
|
|
229
295
|
* Convert frequency in Hz to Mel scale.
|
|
230
296
|
*
|
|
297
|
+
* A total function, matching the C ABI and librosa: a non-finite `hz`
|
|
298
|
+
* propagates rather than throwing, and a magnitude past the 32-bit float range
|
|
299
|
+
* saturates to an infinity the same way the C conversion does. Out-of-audio
|
|
300
|
+
* frequencies are not refused either — the mapping is defined over the whole
|
|
301
|
+
* real line.
|
|
302
|
+
*
|
|
231
303
|
* @param hz - Frequency in Hz
|
|
232
304
|
* @returns Mel frequency
|
|
233
305
|
*/
|
|
@@ -236,7 +308,8 @@ export function hzToMel(hz: number): number {
|
|
|
236
308
|
}
|
|
237
309
|
|
|
238
310
|
/**
|
|
239
|
-
* Convert Mel scale to frequency in Hz.
|
|
311
|
+
* Convert Mel scale to frequency in Hz. Total over the same domain as
|
|
312
|
+
* {@link hzToMel}.
|
|
240
313
|
*
|
|
241
314
|
* @param mel - Mel frequency
|
|
242
315
|
* @returns Frequency in Hz
|
|
@@ -248,6 +321,11 @@ export function melToHz(mel: number): number {
|
|
|
248
321
|
/**
|
|
249
322
|
* Convert frequency in Hz to MIDI note number.
|
|
250
323
|
*
|
|
324
|
+
* Total, like {@link hzToMel}. A non-positive `hz` returns `-Infinity`, the log2
|
|
325
|
+
* limit, and {@link midiToHz} maps that back to 0. A NaN propagates, which is
|
|
326
|
+
* what makes a default `pitchPyin` track — whose unvoiced frames are NaN — safe
|
|
327
|
+
* to map through.
|
|
328
|
+
*
|
|
251
329
|
* @param hz - Frequency in Hz
|
|
252
330
|
* @returns MIDI note number (A4 = 440 Hz = 69)
|
|
253
331
|
*/
|
|
@@ -256,7 +334,8 @@ export function hzToMidi(hz: number): number {
|
|
|
256
334
|
}
|
|
257
335
|
|
|
258
336
|
/**
|
|
259
|
-
* Convert MIDI note number to frequency in Hz.
|
|
337
|
+
* Convert MIDI note number to frequency in Hz. Total, like {@link hzToMel};
|
|
338
|
+
* `-Infinity` bottoms out at 0 rather than propagating its sign.
|
|
260
339
|
*
|
|
261
340
|
* @param midi - MIDI note number
|
|
262
341
|
* @returns Frequency in Hz
|
|
@@ -268,6 +347,11 @@ export function midiToHz(midi: number): number {
|
|
|
268
347
|
/**
|
|
269
348
|
* Convert frequency in Hz to note name.
|
|
270
349
|
*
|
|
350
|
+
* Every frequency with no note answers `"?"` rather than throwing: zero,
|
|
351
|
+
* negative, past the representable MIDI range, and non-finite alike. A default
|
|
352
|
+
* `pitchPyin` track fills unvoiced frames with NaN, so mapping one through this
|
|
353
|
+
* yields `"?"` at those frames.
|
|
354
|
+
*
|
|
271
355
|
* @param hz - Frequency in Hz
|
|
272
356
|
* @returns Note name (e.g., "A4", "C#5")
|
|
273
357
|
*/
|
|
@@ -427,6 +511,47 @@ export function splitSilence(
|
|
|
427
511
|
return requireModule().splitSilence(samples, topDb, frameLength, hopLength);
|
|
428
512
|
}
|
|
429
513
|
|
|
514
|
+
/**
|
|
515
|
+
* Lists the intervals where ANY of `signals` is sounding, so every gap
|
|
516
|
+
* between them is silent in all of them -- what several takes of one part
|
|
517
|
+
* share is their silence, not their sound.
|
|
518
|
+
*
|
|
519
|
+
* @returns The union of {@link splitSilence}'s per-signal intervals, merged
|
|
520
|
+
* where they touch. A single signal returns exactly what `splitSilence`
|
|
521
|
+
* does for it.
|
|
522
|
+
*/
|
|
523
|
+
export function splitSilenceCommon(request: SplitSilenceCommonRequest): Int32Array {
|
|
524
|
+
return requireModule().splitSilenceCommon(
|
|
525
|
+
request.signals,
|
|
526
|
+
request.topDb ?? 60.0,
|
|
527
|
+
request.frameLength ?? 2048,
|
|
528
|
+
request.hopLength ?? 512,
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* {@link splitSilenceCommon} plus the report that says why those are the
|
|
534
|
+
* intervals.
|
|
535
|
+
*
|
|
536
|
+
* Identical intervals, identical refusals, identical defaults; the only
|
|
537
|
+
* difference is the second field. The plain entry point stays because a caller
|
|
538
|
+
* cutting takes has no use for the diagnosis, and one interval covering
|
|
539
|
+
* everything is the answer to three different situations the interval list cannot
|
|
540
|
+
* separate — see {@link SilenceCommonReport} for reading them apart.
|
|
541
|
+
*
|
|
542
|
+
* @returns The union intervals and the report measured on the same RMS pass
|
|
543
|
+
*/
|
|
544
|
+
export function splitSilenceCommonWithReport(
|
|
545
|
+
request: SplitSilenceCommonRequest,
|
|
546
|
+
): SplitSilenceCommonWithReportResult {
|
|
547
|
+
return requireModule().splitSilenceCommonWithReport(
|
|
548
|
+
request.signals,
|
|
549
|
+
request.topDb ?? 60.0,
|
|
550
|
+
request.frameLength ?? 2048,
|
|
551
|
+
request.hopLength ?? 512,
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
|
|
430
555
|
export function frameSignal(request: FrameSignalRequest): WasmFrameResult;
|
|
431
556
|
export function frameSignal(
|
|
432
557
|
samples: Float32Array,
|