@libraz/libsonare 1.7.2 → 1.8.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/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 +6 -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 +873 -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 +477 -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 +129 -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 +3758 -1362
- 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 +457 -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 +652 -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 +510 -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 +164 -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 +850 -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 +3909 -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 +335 -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 +128 -0
- package/dist/worklet/engine-mixer-facade.d.ts.map +1 -0
- package/dist/worklet/engine-node.d.ts +81 -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 +68 -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 +73 -0
- package/dist/worklet/engine-strips.d.ts.map +1 -0
- package/dist/worklet/engine-sync.d.ts +37 -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 +397 -0
- package/dist/worklet/engine.d.ts.map +1 -0
- package/dist/worklet/guards.d.ts +47 -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 +323 -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 +2763 -501
- package/dist/worklet.js.map +1 -1
- package/package.json +23 -12
- package/src/_effects_common.ts +17 -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 +97 -22
- package/src/effects_note_ops.ts +635 -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 +377 -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 +282 -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 +346 -32
- package/src/mastering_dynamics.ts +22 -11
- package/src/metering.ts +67 -24
- package/src/mixer.ts +212 -3
- 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 +268 -270
- package/src/public_types.ts +122 -3
- package/src/public_types_acoustic.ts +112 -3
- package/src/public_types_mastering.ts +254 -73
- package/src/public_types_mixing.ts +363 -1
- package/src/public_types_music.ts +312 -2
- package/src/public_types_playback.ts +195 -0
- package/src/public_types_realtime.ts +39 -7
- package/src/public_types_repair.ts +446 -0
- package/src/public_types_spectral.ts +487 -1
- package/src/quick_analysis.ts +203 -26
- package/src/realtime_engine.ts +711 -28
- 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 +1122 -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 +194 -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 +444 -10
- package/src/worklet/engine-node.ts +78 -26
- package/src/worklet/engine-offline.ts +14 -8
- package/src/worklet/engine-parameter-facade.ts +21 -0
- package/src/worklet/engine-processor.ts +272 -83
- package/src/worklet/engine-register.ts +32 -18
- package/src/worklet/engine-strips.ts +280 -9
- package/src/worklet/engine-sync.ts +14 -6
- package/src/worklet/engine.ts +365 -31
- package/src/worklet/guards.ts +140 -44
- package/src/worklet/messages.ts +227 -2
- package/src/worklet/mixer-processor.ts +109 -47
- package/src/worklet/playback-processor.ts +300 -0
- package/src/worklet/protocol.ts +53 -3
- 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,425 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Broadband and tonal noise repair: denoise and dehum, with their detectors.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { getSonareModule } from './module_state';
|
|
6
|
+
import type {
|
|
7
|
+
HumDetection,
|
|
8
|
+
MasteringRepairDehumStereoResult,
|
|
9
|
+
MasteringRepairDenoiseClassicalLinkedResult,
|
|
10
|
+
MasteringRepairDenoiseClassicalStereoResult,
|
|
11
|
+
NoiseDetection,
|
|
12
|
+
} from './public_types_repair';
|
|
13
|
+
|
|
14
|
+
function requireModule() {
|
|
15
|
+
return getSonareModule();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Algorithms accepted by `masteringRepairDenoiseClassical`. */
|
|
19
|
+
export type DenoiseClassicalMode = 'logMmse' | 'mmseStsa' | 'spectralSubtraction';
|
|
20
|
+
|
|
21
|
+
/** Noise PSD estimators accepted by `masteringRepairDenoiseClassical`. */
|
|
22
|
+
export type DenoiseClassicalNoiseEstimator = 'quantile' | 'mcra' | 'imcra' | 'spp';
|
|
23
|
+
|
|
24
|
+
/** Options for `masteringRepairDenoiseClassical`. */
|
|
25
|
+
export interface DenoiseClassicalOptions {
|
|
26
|
+
mode?: DenoiseClassicalMode;
|
|
27
|
+
noiseEstimator?: DenoiseClassicalNoiseEstimator;
|
|
28
|
+
nFft?: number;
|
|
29
|
+
hopLength?: number;
|
|
30
|
+
ddAlpha?: number;
|
|
31
|
+
reductionDb?: number;
|
|
32
|
+
overSubtraction?: number;
|
|
33
|
+
spectralFloor?: number;
|
|
34
|
+
noiseEstimationQuantile?: number;
|
|
35
|
+
speechPresenceGain?: boolean;
|
|
36
|
+
gainSmoothing?: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface MasteringRepairDenoiseClassicalRequest extends DenoiseClassicalOptions {
|
|
40
|
+
samples: Float32Array;
|
|
41
|
+
sampleRate: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Request form of `masteringRepairDenoiseClassicalStereo`. */
|
|
45
|
+
export interface MasteringRepairDenoiseClassicalStereoRequest extends DenoiseClassicalOptions {
|
|
46
|
+
left: Float32Array;
|
|
47
|
+
right: Float32Array;
|
|
48
|
+
sampleRate?: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Request form of `masteringRepairDenoiseClassicalLinked`. */
|
|
52
|
+
export interface MasteringRepairDenoiseClassicalLinkedRequest extends DenoiseClassicalOptions {
|
|
53
|
+
/** At least one channel; all the same length. */
|
|
54
|
+
channels: Float32Array[];
|
|
55
|
+
sampleRate?: number;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Offline STFT-domain classical denoiser (LogMMSE / MMSE-STSA / SpectralSubtraction). */
|
|
59
|
+
export function masteringRepairDenoiseClassical(
|
|
60
|
+
request: MasteringRepairDenoiseClassicalRequest,
|
|
61
|
+
): Float32Array;
|
|
62
|
+
export function masteringRepairDenoiseClassical(
|
|
63
|
+
samples: Float32Array,
|
|
64
|
+
sampleRate: number,
|
|
65
|
+
options?: DenoiseClassicalOptions,
|
|
66
|
+
): Float32Array;
|
|
67
|
+
export function masteringRepairDenoiseClassical(
|
|
68
|
+
samples: Float32Array | MasteringRepairDenoiseClassicalRequest,
|
|
69
|
+
sampleRate?: number,
|
|
70
|
+
options: DenoiseClassicalOptions = {},
|
|
71
|
+
): Float32Array {
|
|
72
|
+
const request =
|
|
73
|
+
samples instanceof Float32Array
|
|
74
|
+
? { samples, sampleRate: sampleRate as number, ...options }
|
|
75
|
+
: samples;
|
|
76
|
+
return requireModule().masteringRepairDenoiseClassical(
|
|
77
|
+
request.samples,
|
|
78
|
+
request.sampleRate,
|
|
79
|
+
request,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Offline STFT-domain classical denoiser for a stereo pair, driven by one channel-linked
|
|
85
|
+
* gain mask.
|
|
86
|
+
*
|
|
87
|
+
* The mask is built from the channel-summed power and applied unchanged to both channels, so
|
|
88
|
+
* the pass cannot move an interchannel level or phase difference. That is also why the result
|
|
89
|
+
* carries a single `report` rather than one per channel: a pair would be two copies of one
|
|
90
|
+
* measurement and would read as though the two could differ.
|
|
91
|
+
*
|
|
92
|
+
* `report.detected` is therefore a *pair-level* measurement, and the only absolute one in the
|
|
93
|
+
* result. Its levels are dBFS on the channel-summed power, so two identical channels read
|
|
94
|
+
* `10*log10(2)` — about 3.01 dB — above the same material through
|
|
95
|
+
* {@link masteringRepairDenoiseClassical}. A stereo floor is comparable only against another
|
|
96
|
+
* stereo floor, never against a mono one.
|
|
97
|
+
*
|
|
98
|
+
* Needs at least `nFft` samples and REJECTS a shorter input, which is the opposite of
|
|
99
|
+
* {@link masteringRepairDereverbClassicalStereo} — that one pads.
|
|
100
|
+
*
|
|
101
|
+
* Which options are live depends on `mode`: `overSubtraction` and `spectralFloor` are read
|
|
102
|
+
* only by `spectralSubtraction`, and `speechPresenceGain` and `gainSmoothing` only by the
|
|
103
|
+
* other two, so at the default `logMmse` the first pair does nothing.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* const { left, right, report } = masteringRepairDenoiseClassicalStereo({
|
|
108
|
+
* left: leftSamples,
|
|
109
|
+
* right: rightSamples,
|
|
110
|
+
* sampleRate: 48000,
|
|
111
|
+
* reductionDb: 18,
|
|
112
|
+
* });
|
|
113
|
+
* console.log(report.detected.floorDbfs, report.meanReductionDb);
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export function masteringRepairDenoiseClassicalStereo(
|
|
117
|
+
request: MasteringRepairDenoiseClassicalStereoRequest,
|
|
118
|
+
): MasteringRepairDenoiseClassicalStereoResult;
|
|
119
|
+
export function masteringRepairDenoiseClassicalStereo(
|
|
120
|
+
left: Float32Array,
|
|
121
|
+
right: Float32Array,
|
|
122
|
+
sampleRate: number,
|
|
123
|
+
config?: DenoiseClassicalOptions,
|
|
124
|
+
): MasteringRepairDenoiseClassicalStereoResult;
|
|
125
|
+
export function masteringRepairDenoiseClassicalStereo(
|
|
126
|
+
left: Float32Array | MasteringRepairDenoiseClassicalStereoRequest,
|
|
127
|
+
right?: Float32Array,
|
|
128
|
+
sampleRate?: number,
|
|
129
|
+
config: DenoiseClassicalOptions = {},
|
|
130
|
+
): MasteringRepairDenoiseClassicalStereoResult {
|
|
131
|
+
const request: MasteringRepairDenoiseClassicalStereoRequest =
|
|
132
|
+
left instanceof Float32Array
|
|
133
|
+
? { left, right: right as Float32Array, sampleRate, ...config }
|
|
134
|
+
: left;
|
|
135
|
+
const { left: leftSamples, right: rightSamples, sampleRate: rate, ...options } = request;
|
|
136
|
+
return requireModule().masteringRepairDenoiseClassicalStereo(
|
|
137
|
+
leftSamples,
|
|
138
|
+
rightSamples,
|
|
139
|
+
rate ?? 22050,
|
|
140
|
+
options,
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Offline STFT-domain classical denoiser for any number of channels, driven by one
|
|
146
|
+
* channel-linked gain mask.
|
|
147
|
+
*
|
|
148
|
+
* The N-channel form of {@link masteringRepairDenoiseClassicalStereo}, carrying the same
|
|
149
|
+
* guarantee over the whole set: the mask is built from the channel-summed power and applied
|
|
150
|
+
* unchanged to every channel, so no interchannel level or phase difference moves however many
|
|
151
|
+
* channels there are. One `report` for the set, and one output per input channel in input order.
|
|
152
|
+
*
|
|
153
|
+
* A single channel reproduces {@link masteringRepairDenoiseClassical} bit for bit, and two
|
|
154
|
+
* reproduce {@link masteringRepairDenoiseClassicalStereo} plane for plane — `channels[0]` is the
|
|
155
|
+
* left plane and `channels[1]` the right.
|
|
156
|
+
*
|
|
157
|
+
* `report.detected` carries absolute levels and they are the SET's: the floor is referred to the
|
|
158
|
+
* summed mean square of every channel, so N identical channels read `10*log10(N)` above
|
|
159
|
+
* one of them — about 3.01 dB at two channels and 4.77 dB at three. Compare a floor only against
|
|
160
|
+
* one measured over the same number of channels. Every other field of the report is a fraction
|
|
161
|
+
* and does not move with the channel count.
|
|
162
|
+
*
|
|
163
|
+
* Needs at least `nFft` samples and REJECTS a shorter input, which is the opposite of
|
|
164
|
+
* {@link masteringRepairDereverbClassicalLinked} — that one pads.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* const { channels, report } = masteringRepairDenoiseClassicalLinked({
|
|
169
|
+
* channels: [frontLeft, frontRight, centre],
|
|
170
|
+
* sampleRate: 48000,
|
|
171
|
+
* reductionDb: 18,
|
|
172
|
+
* });
|
|
173
|
+
* console.log(channels.length, report.detected.floorDbfs);
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
export function masteringRepairDenoiseClassicalLinked(
|
|
177
|
+
request: MasteringRepairDenoiseClassicalLinkedRequest,
|
|
178
|
+
): MasteringRepairDenoiseClassicalLinkedResult;
|
|
179
|
+
export function masteringRepairDenoiseClassicalLinked(
|
|
180
|
+
channels: Float32Array[],
|
|
181
|
+
sampleRate: number,
|
|
182
|
+
config?: DenoiseClassicalOptions,
|
|
183
|
+
): MasteringRepairDenoiseClassicalLinkedResult;
|
|
184
|
+
export function masteringRepairDenoiseClassicalLinked(
|
|
185
|
+
channels: Float32Array[] | MasteringRepairDenoiseClassicalLinkedRequest,
|
|
186
|
+
sampleRate?: number,
|
|
187
|
+
config: DenoiseClassicalOptions = {},
|
|
188
|
+
): MasteringRepairDenoiseClassicalLinkedResult {
|
|
189
|
+
const request: MasteringRepairDenoiseClassicalLinkedRequest = Array.isArray(channels)
|
|
190
|
+
? { channels, sampleRate, ...config }
|
|
191
|
+
: channels;
|
|
192
|
+
const { channels: input, sampleRate: rate, ...options } = request;
|
|
193
|
+
return requireModule().masteringRepairDenoiseClassicalLinked(input, rate ?? 22050, options);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* How `masteringRepairDehum` removes the harmonic series.
|
|
198
|
+
*
|
|
199
|
+
* `subtract` tracks each harmonic's amplitude and phase and subtracts the tone they describe,
|
|
200
|
+
* so material sitting at the same frequency but uncorrelated with the tracked series survives.
|
|
201
|
+
* `notch` cascades one RBJ notch per harmonic and removes everything inside each notch's
|
|
202
|
+
* bandwidth, hum or programme alike.
|
|
203
|
+
*/
|
|
204
|
+
export type DehumMode = 'subtract' | 'notch';
|
|
205
|
+
|
|
206
|
+
/** Options for `masteringRepairDehum`. */
|
|
207
|
+
export interface DehumOptions {
|
|
208
|
+
fundamentalHz?: number;
|
|
209
|
+
harmonics?: number;
|
|
210
|
+
q?: number;
|
|
211
|
+
adaptive?: boolean;
|
|
212
|
+
searchRangeHz?: number;
|
|
213
|
+
adaptation?: number;
|
|
214
|
+
frameSize?: number;
|
|
215
|
+
pllBandwidth?: number;
|
|
216
|
+
/** Defaults to `'subtract'`. */
|
|
217
|
+
mode?: DehumMode;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export interface MasteringRepairDehumRequest extends DehumOptions {
|
|
221
|
+
samples: Float32Array;
|
|
222
|
+
sampleRate: number;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** Request form of `masteringRepairDehumStereo`. */
|
|
226
|
+
export interface MasteringRepairDehumStereoRequest extends DehumOptions {
|
|
227
|
+
left: Float32Array;
|
|
228
|
+
right: Float32Array;
|
|
229
|
+
sampleRate?: number;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** Offline mains-hum remover. */
|
|
233
|
+
export function masteringRepairDehum(request: MasteringRepairDehumRequest): Float32Array;
|
|
234
|
+
export function masteringRepairDehum(
|
|
235
|
+
samples: Float32Array,
|
|
236
|
+
sampleRate: number,
|
|
237
|
+
options?: DehumOptions,
|
|
238
|
+
): Float32Array;
|
|
239
|
+
export function masteringRepairDehum(
|
|
240
|
+
samples: Float32Array | MasteringRepairDehumRequest,
|
|
241
|
+
sampleRate?: number,
|
|
242
|
+
options: DehumOptions = {},
|
|
243
|
+
): Float32Array {
|
|
244
|
+
const request =
|
|
245
|
+
samples instanceof Float32Array
|
|
246
|
+
? { samples, sampleRate: sampleRate as number, ...options }
|
|
247
|
+
: samples;
|
|
248
|
+
return requireModule().masteringRepairDehum(request.samples, request.sampleRate, request);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Offline mains-hum remover for a stereo pair.
|
|
253
|
+
*
|
|
254
|
+
* With `adaptive` set, mains hum is one physical source, so the tracker reads the channel
|
|
255
|
+
* mean and both cascades follow the one frequency it finds: `appliedFundamentalHz` and
|
|
256
|
+
* `fundamentalDriftHz` come back identical in both reports by construction, while each
|
|
257
|
+
* report's `detected` still measures that channel's own input and each channel keeps its
|
|
258
|
+
* own filter state, so neither channel's transient rings through the other. With `adaptive`
|
|
259
|
+
* clear, which is the default, nothing is shared and the two channels are filtered
|
|
260
|
+
* independently at the configured frequency.
|
|
261
|
+
*/
|
|
262
|
+
export function masteringRepairDehumStereo(
|
|
263
|
+
request: MasteringRepairDehumStereoRequest,
|
|
264
|
+
): MasteringRepairDehumStereoResult;
|
|
265
|
+
export function masteringRepairDehumStereo(
|
|
266
|
+
left: Float32Array,
|
|
267
|
+
right: Float32Array,
|
|
268
|
+
sampleRate: number,
|
|
269
|
+
config?: DehumOptions,
|
|
270
|
+
): MasteringRepairDehumStereoResult;
|
|
271
|
+
export function masteringRepairDehumStereo(
|
|
272
|
+
left: Float32Array | MasteringRepairDehumStereoRequest,
|
|
273
|
+
right?: Float32Array,
|
|
274
|
+
sampleRate?: number,
|
|
275
|
+
config: DehumOptions = {},
|
|
276
|
+
): MasteringRepairDehumStereoResult {
|
|
277
|
+
const request: MasteringRepairDehumStereoRequest =
|
|
278
|
+
left instanceof Float32Array
|
|
279
|
+
? { left, right: right as Float32Array, sampleRate, ...config }
|
|
280
|
+
: left;
|
|
281
|
+
const { left: leftSamples, right: rightSamples, sampleRate: rate, ...options } = request;
|
|
282
|
+
return requireModule().masteringRepairDehumStereo(
|
|
283
|
+
leftSamples,
|
|
284
|
+
rightSamples,
|
|
285
|
+
rate ?? 22050,
|
|
286
|
+
options,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** Request form of `masteringRepairDetectNoiseFloor`. */
|
|
291
|
+
export interface MasteringRepairDetectNoiseFloorRequest extends DenoiseClassicalOptions {
|
|
292
|
+
samples: Float32Array;
|
|
293
|
+
sampleRate: number;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/** Request form of `masteringRepairNoiseBandBins`. */
|
|
297
|
+
export interface MasteringRepairNoiseBandBinsRequest {
|
|
298
|
+
nFft?: number;
|
|
299
|
+
sampleRate?: number;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/** Request form of `masteringRepairDetectHum`. */
|
|
303
|
+
export interface MasteringRepairDetectHumRequest extends DehumOptions {
|
|
304
|
+
samples: Float32Array;
|
|
305
|
+
sampleRate: number;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Measures the noise floor without denoising.
|
|
310
|
+
*
|
|
311
|
+
* Runs the STFT and the configured noise estimator — the two stages
|
|
312
|
+
* {@link masteringRepairDenoiseClassical} runs — and stops before the gain mask, which is why
|
|
313
|
+
* no attenuation figure appears here.
|
|
314
|
+
*
|
|
315
|
+
* Needs at least `nFft` samples and THROWS for a shorter buffer, the opposite of
|
|
316
|
+
* {@link masteringRepairDetectReverb}, which pads one.
|
|
317
|
+
*
|
|
318
|
+
* `floorDbfs` is an absolute level, so it is comparable only against another figure measured
|
|
319
|
+
* over the same channel count.
|
|
320
|
+
*/
|
|
321
|
+
export function masteringRepairDetectNoiseFloor(
|
|
322
|
+
request: MasteringRepairDetectNoiseFloorRequest,
|
|
323
|
+
): NoiseDetection;
|
|
324
|
+
export function masteringRepairDetectNoiseFloor(
|
|
325
|
+
samples: Float32Array,
|
|
326
|
+
sampleRate: number,
|
|
327
|
+
options?: DenoiseClassicalOptions,
|
|
328
|
+
): NoiseDetection;
|
|
329
|
+
export function masteringRepairDetectNoiseFloor(
|
|
330
|
+
samples: Float32Array | MasteringRepairDetectNoiseFloorRequest,
|
|
331
|
+
sampleRate?: number,
|
|
332
|
+
options: DenoiseClassicalOptions = {},
|
|
333
|
+
): NoiseDetection {
|
|
334
|
+
const request =
|
|
335
|
+
samples instanceof Float32Array
|
|
336
|
+
? { samples, sampleRate: sampleRate as number, ...options }
|
|
337
|
+
: samples;
|
|
338
|
+
return requireModule().masteringRepairDetectNoiseFloor(
|
|
339
|
+
request.samples,
|
|
340
|
+
request.sampleRate,
|
|
341
|
+
request,
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Bin boundaries of the grid {@link masteringRepairDetectNoiseFloor} reports `bandFloorDbfs` on.
|
|
347
|
+
*
|
|
348
|
+
* Band `k` covers the one-sided STFT bins `[bins[k], bins[k + 1])`, and bin `b` sits at
|
|
349
|
+
* `b * sampleRate / nFft` Hz.
|
|
350
|
+
*
|
|
351
|
+
* The geometric band edges are rounded to bins, so a band narrower than the bin spacing comes
|
|
352
|
+
* out EMPTY — `bins[k] === bins[k + 1]` — and its `bandFloorDbfs[k]` reads as the floor
|
|
353
|
+
* sentinel because no bin landed in it, NOT because that region was quiet. Telling those two
|
|
354
|
+
* apart is what this grid is for, and the rounding cannot be recovered from the band count
|
|
355
|
+
* alone.
|
|
356
|
+
*
|
|
357
|
+
* Nothing but the analysis geometry decides the grid, so no denoise config is taken: one call
|
|
358
|
+
* describes every floor measured at that `nFft` and `sampleRate`, whatever mode or estimator
|
|
359
|
+
* produced it.
|
|
360
|
+
*
|
|
361
|
+
* @param nFft - STFT size the bins belong to; a positive power of two, the same rule
|
|
362
|
+
* {@link masteringRepairDetectNoiseFloor} applies to its config, so every grid returned here
|
|
363
|
+
* is one that entry can report on. Defaults to 1024.
|
|
364
|
+
* @param sampleRate - Sample rate the bins belong to, in Hz; positive. Defaults to 22050.
|
|
365
|
+
* @returns 33 bin indices, low to high — one more than the 32 bands: the first bin of every
|
|
366
|
+
* band plus the one-past-the-end bin of the last, which is `nFft / 2 + 1`. Non-decreasing.
|
|
367
|
+
* @throws If `nFft` is not a positive power of two, or `sampleRate` is not positive.
|
|
368
|
+
*
|
|
369
|
+
* @example
|
|
370
|
+
* ```ts
|
|
371
|
+
* const bins = masteringRepairNoiseBandBins({ nFft: 1024, sampleRate: 48000 });
|
|
372
|
+
* const floor = masteringRepairDetectNoiseFloor({ samples, sampleRate: 48000, nFft: 1024 });
|
|
373
|
+
* floor.bandFloorDbfs.forEach((level, k) => {
|
|
374
|
+
* if (bins[k] === bins[k + 1]) return; // empty band: `level` is the sentinel, not a measurement
|
|
375
|
+
* console.log((bins[k] * 48000) / 1024, level);
|
|
376
|
+
* });
|
|
377
|
+
* ```
|
|
378
|
+
*/
|
|
379
|
+
export function masteringRepairNoiseBandBins(
|
|
380
|
+
request?: MasteringRepairNoiseBandBinsRequest,
|
|
381
|
+
): Int32Array;
|
|
382
|
+
export function masteringRepairNoiseBandBins(nFft?: number, sampleRate?: number): Int32Array;
|
|
383
|
+
export function masteringRepairNoiseBandBins(
|
|
384
|
+
nFft?: number | MasteringRepairNoiseBandBinsRequest,
|
|
385
|
+
sampleRate?: number,
|
|
386
|
+
): Int32Array {
|
|
387
|
+
// Both positional arguments are optional, so a default on `nFft` would swallow
|
|
388
|
+
// an explicit `undefined` and take the request branch with `sampleRate` in hand
|
|
389
|
+
// but unreachable. Discriminate on the value instead.
|
|
390
|
+
const request = typeof nFft === 'object' && nFft !== null ? nFft : { nFft, sampleRate };
|
|
391
|
+
return requireModule().masteringRepairNoiseBandBins(
|
|
392
|
+
request.nFft ?? 1024,
|
|
393
|
+
request.sampleRate ?? 22050,
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Measures hum without filtering.
|
|
399
|
+
*
|
|
400
|
+
* Always runs the estimation path, whatever `adaptive` says: the fixed path notches the
|
|
401
|
+
* configured frequency without ever looking for hum, so a detector following the flag would
|
|
402
|
+
* hand back its own input. `fundamentalProminence` is the winning candidate's projected energy
|
|
403
|
+
* over the median candidate, so `1.0` means no peak was found at all — it is not a lock flag.
|
|
404
|
+
*
|
|
405
|
+
* `harmonicDbfs` is measured at every `k*f0` the sample rate carries, not only the ones a
|
|
406
|
+
* cascade would notch; a `k*f0` at or past Nyquist reads the dB floor because nothing is there
|
|
407
|
+
* to measure.
|
|
408
|
+
*/
|
|
409
|
+
export function masteringRepairDetectHum(request: MasteringRepairDetectHumRequest): HumDetection;
|
|
410
|
+
export function masteringRepairDetectHum(
|
|
411
|
+
samples: Float32Array,
|
|
412
|
+
sampleRate: number,
|
|
413
|
+
options?: DehumOptions,
|
|
414
|
+
): HumDetection;
|
|
415
|
+
export function masteringRepairDetectHum(
|
|
416
|
+
samples: Float32Array | MasteringRepairDetectHumRequest,
|
|
417
|
+
sampleRate?: number,
|
|
418
|
+
options: DehumOptions = {},
|
|
419
|
+
): HumDetection {
|
|
420
|
+
const request =
|
|
421
|
+
samples instanceof Float32Array
|
|
422
|
+
? { samples, sampleRate: sampleRate as number, ...options }
|
|
423
|
+
: samples;
|
|
424
|
+
return requireModule().masteringRepairDetectHum(request.samples, request.sampleRate, request);
|
|
425
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Silence trimming, with the range detector it shares its geometry with.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { getSonareModule } from './module_state';
|
|
6
|
+
import type { MasteringRepairTrimSilenceStereoResult, TrimRange } from './public_types_repair';
|
|
7
|
+
|
|
8
|
+
function requireModule() {
|
|
9
|
+
return getSonareModule();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Trimming modes accepted by `masteringRepairTrimSilence`. */
|
|
13
|
+
export type TrimSilenceMode = 'peak' | 'lufsGated';
|
|
14
|
+
|
|
15
|
+
/** Options for `masteringRepairTrimSilence`. */
|
|
16
|
+
export interface TrimSilenceOptions {
|
|
17
|
+
threshold?: number;
|
|
18
|
+
paddingSamples?: number;
|
|
19
|
+
mode?: TrimSilenceMode;
|
|
20
|
+
gateLufs?: number;
|
|
21
|
+
windowMs?: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface MasteringRepairTrimSilenceRequest extends TrimSilenceOptions {
|
|
25
|
+
samples: Float32Array;
|
|
26
|
+
sampleRate: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Request form of `masteringRepairTrimSilenceStereo`. */
|
|
30
|
+
export interface MasteringRepairTrimSilenceStereoRequest extends TrimSilenceOptions {
|
|
31
|
+
left: Float32Array;
|
|
32
|
+
right: Float32Array;
|
|
33
|
+
sampleRate?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Offline silence trimmer (peak threshold or LUFS-gated). */
|
|
37
|
+
export function masteringRepairTrimSilence(
|
|
38
|
+
request: MasteringRepairTrimSilenceRequest,
|
|
39
|
+
): Float32Array;
|
|
40
|
+
export function masteringRepairTrimSilence(
|
|
41
|
+
samples: Float32Array,
|
|
42
|
+
sampleRate: number,
|
|
43
|
+
options?: TrimSilenceOptions,
|
|
44
|
+
): Float32Array;
|
|
45
|
+
export function masteringRepairTrimSilence(
|
|
46
|
+
samples: Float32Array | MasteringRepairTrimSilenceRequest,
|
|
47
|
+
sampleRate?: number,
|
|
48
|
+
options: TrimSilenceOptions = {},
|
|
49
|
+
): Float32Array {
|
|
50
|
+
const request =
|
|
51
|
+
samples instanceof Float32Array
|
|
52
|
+
? { samples, sampleRate: sampleRate as number, ...options }
|
|
53
|
+
: samples;
|
|
54
|
+
return requireModule().masteringRepairTrimSilence(request.samples, request.sampleRate, request);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Offline silence trimmer for a stereo pair, cutting both channels to one shared range.
|
|
59
|
+
*
|
|
60
|
+
* Each channel is scanned on its own and the two ranges are UNIONED, so the pair keeps
|
|
61
|
+
* whatever either channel calls signal and both outputs come back the same length. The scan
|
|
62
|
+
* never reads a downmix: `0.5 * (left + right)` halves material carried by one channel alone,
|
|
63
|
+
* which can drop it under the gate, and cancels an antiphase pair to exactly zero, which would
|
|
64
|
+
* read full-level audio in both channels as silence. Trimming is destructive, so the rule errs
|
|
65
|
+
* toward keeping.
|
|
66
|
+
*
|
|
67
|
+
* The only repair stereo entry that SHORTENS its input: `result.left.length` is the output
|
|
68
|
+
* length, and the input's says nothing about it. A pair in which neither channel carries signal
|
|
69
|
+
* returns two EMPTY arrays and succeeds — it does not throw and does not return null.
|
|
70
|
+
*
|
|
71
|
+
* `report.range` is the union that was applied to both channels. `leftRange` and `rightRange`
|
|
72
|
+
* are the per-channel scans it was formed from, so a caller can see which channel decided each
|
|
73
|
+
* edge; a channel carrying nothing reports an empty range and contributes nothing to the union.
|
|
74
|
+
* With nothing kept, `report.range` is `(inputLength, inputLength)`, so `removedHeadSamples` is
|
|
75
|
+
* the whole input and `removedTailSamples` is 0 — the two still sum to the input length and
|
|
76
|
+
* only the split between the ends is arbitrary.
|
|
77
|
+
*
|
|
78
|
+
* Which option is live depends on `mode`: `threshold` is read ONLY by `'peak'`, and `gateLufs`
|
|
79
|
+
* and `windowMs` ONLY by `'lufsGated'`. Changing an option the active mode does not read is
|
|
80
|
+
* silently inert rather than an error.
|
|
81
|
+
*
|
|
82
|
+
* That gated mode compares an UNWEIGHTED RMS over a window centred on each sample against
|
|
83
|
+
* `gateLufs`, so the figure it gates on is dBFS rather than a BS.1770 loudness, and `windowMs`
|
|
84
|
+
* sizes that window and does nothing else. The window is clipped at the buffer ends, so a
|
|
85
|
+
* sample near either edge is judged on a shorter one.
|
|
86
|
+
*
|
|
87
|
+
* `paddingSamples` widens the kept range in both directions and is clamped to the buffer, so it
|
|
88
|
+
* can never reach past either end; a pass that kept nothing is not padded. A NEGATIVE count is
|
|
89
|
+
* refused by name rather than absorbed into 0 or into the default — the underlying field is
|
|
90
|
+
* unsigned, and a negative one would arrive as an enormous count instead.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* const { left, right, report, leftRange, rightRange } = masteringRepairTrimSilenceStereo({
|
|
95
|
+
* left: leftSamples,
|
|
96
|
+
* right: rightSamples,
|
|
97
|
+
* sampleRate: 48000,
|
|
98
|
+
* mode: 'peak',
|
|
99
|
+
* threshold: 0.01,
|
|
100
|
+
* });
|
|
101
|
+
* console.log(left.length, report.removedHeadSamples, leftRange.first, rightRange.first);
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export function masteringRepairTrimSilenceStereo(
|
|
105
|
+
request: MasteringRepairTrimSilenceStereoRequest,
|
|
106
|
+
): MasteringRepairTrimSilenceStereoResult;
|
|
107
|
+
export function masteringRepairTrimSilenceStereo(
|
|
108
|
+
left: Float32Array,
|
|
109
|
+
right: Float32Array,
|
|
110
|
+
sampleRate: number,
|
|
111
|
+
config?: TrimSilenceOptions,
|
|
112
|
+
): MasteringRepairTrimSilenceStereoResult;
|
|
113
|
+
export function masteringRepairTrimSilenceStereo(
|
|
114
|
+
left: Float32Array | MasteringRepairTrimSilenceStereoRequest,
|
|
115
|
+
right?: Float32Array,
|
|
116
|
+
sampleRate?: number,
|
|
117
|
+
config: TrimSilenceOptions = {},
|
|
118
|
+
): MasteringRepairTrimSilenceStereoResult {
|
|
119
|
+
const request: MasteringRepairTrimSilenceStereoRequest =
|
|
120
|
+
left instanceof Float32Array
|
|
121
|
+
? { left, right: right as Float32Array, sampleRate, ...config }
|
|
122
|
+
: left;
|
|
123
|
+
const { left: leftSamples, right: rightSamples, sampleRate: rate, ...options } = request;
|
|
124
|
+
return requireModule().masteringRepairTrimSilenceStereo(
|
|
125
|
+
leftSamples,
|
|
126
|
+
rightSamples,
|
|
127
|
+
rate ?? 22050,
|
|
128
|
+
options,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Request form of `masteringRepairDetectTrimRange`. */
|
|
133
|
+
export interface MasteringRepairDetectTrimRangeRequest extends TrimSilenceOptions {
|
|
134
|
+
samples: Float32Array;
|
|
135
|
+
sampleRate: number;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Request form of `masteringRepairDetectTrimRangeStereo`. */
|
|
139
|
+
export interface MasteringRepairDetectTrimRangeStereoRequest extends TrimSilenceOptions {
|
|
140
|
+
left: Float32Array;
|
|
141
|
+
right: Float32Array;
|
|
142
|
+
sampleRate?: number;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Measures the range {@link masteringRepairTrimSilence} would keep, without trimming.
|
|
147
|
+
*
|
|
148
|
+
* The padding `paddingSamples` asks for is already INSIDE the returned range, so this is the
|
|
149
|
+
* range the repair would cut to rather than the detected extent of the signal. A buffer with
|
|
150
|
+
* nothing above the threshold reports `(length, length)`.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```ts
|
|
154
|
+
* const range = masteringRepairDetectTrimRange({ samples, sampleRate: 48000, threshold: 0.01 });
|
|
155
|
+
* const keptSeconds = (range.lastExclusive - range.first) / 48000;
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export function masteringRepairDetectTrimRange(
|
|
159
|
+
request: MasteringRepairDetectTrimRangeRequest,
|
|
160
|
+
): TrimRange;
|
|
161
|
+
export function masteringRepairDetectTrimRange(
|
|
162
|
+
samples: Float32Array,
|
|
163
|
+
sampleRate: number,
|
|
164
|
+
options?: TrimSilenceOptions,
|
|
165
|
+
): TrimRange;
|
|
166
|
+
export function masteringRepairDetectTrimRange(
|
|
167
|
+
samples: Float32Array | MasteringRepairDetectTrimRangeRequest,
|
|
168
|
+
sampleRate?: number,
|
|
169
|
+
options: TrimSilenceOptions = {},
|
|
170
|
+
): TrimRange {
|
|
171
|
+
const request =
|
|
172
|
+
samples instanceof Float32Array
|
|
173
|
+
? { samples, sampleRate: sampleRate as number, ...options }
|
|
174
|
+
: samples;
|
|
175
|
+
return requireModule().masteringRepairDetectTrimRange(
|
|
176
|
+
request.samples,
|
|
177
|
+
request.sampleRate,
|
|
178
|
+
request,
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Measures the one range a stereo trim pass would cut both channels to.
|
|
184
|
+
*
|
|
185
|
+
* Each channel is scanned on its own and the two ranges are UNIONED, so the pair keeps whatever
|
|
186
|
+
* either channel calls signal. A channel with nothing above the threshold contributes NO EDGE
|
|
187
|
+
* rather than an edge at the buffer's end: the union of a silent channel and an active one is
|
|
188
|
+
* the active channel's range exactly, where a naive `min`/`max` would push `lastExclusive` out
|
|
189
|
+
* to the buffer end and keep the whole tail.
|
|
190
|
+
*
|
|
191
|
+
* A downmix is not read: summing to mono halves material carried by one channel alone and
|
|
192
|
+
* cancels an antiphase pair outright, either of which would read full-level audio as silence.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```ts
|
|
196
|
+
* const range = masteringRepairDetectTrimRangeStereo({ left, right, sampleRate: 48000 });
|
|
197
|
+
* console.log(range.first, range.lastExclusive);
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
export function masteringRepairDetectTrimRangeStereo(
|
|
201
|
+
request: MasteringRepairDetectTrimRangeStereoRequest,
|
|
202
|
+
): TrimRange;
|
|
203
|
+
export function masteringRepairDetectTrimRangeStereo(
|
|
204
|
+
left: Float32Array,
|
|
205
|
+
right: Float32Array,
|
|
206
|
+
sampleRate: number,
|
|
207
|
+
config?: TrimSilenceOptions,
|
|
208
|
+
): TrimRange;
|
|
209
|
+
export function masteringRepairDetectTrimRangeStereo(
|
|
210
|
+
left: Float32Array | MasteringRepairDetectTrimRangeStereoRequest,
|
|
211
|
+
right?: Float32Array,
|
|
212
|
+
sampleRate?: number,
|
|
213
|
+
config: TrimSilenceOptions = {},
|
|
214
|
+
): TrimRange {
|
|
215
|
+
const request: MasteringRepairDetectTrimRangeStereoRequest =
|
|
216
|
+
left instanceof Float32Array
|
|
217
|
+
? { left, right: right as Float32Array, sampleRate, ...config }
|
|
218
|
+
: left;
|
|
219
|
+
const { left: leftSamples, right: rightSamples, sampleRate: rate, ...options } = request;
|
|
220
|
+
return requireModule().masteringRepairDetectTrimRangeStereo(
|
|
221
|
+
leftSamples,
|
|
222
|
+
rightSamples,
|
|
223
|
+
rate ?? 22050,
|
|
224
|
+
options,
|
|
225
|
+
);
|
|
226
|
+
}
|