@libraz/libsonare 1.5.3 → 1.5.4
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 +69 -740
- package/dist/index.d.ts +15 -9
- package/dist/index.js +114 -10
- package/dist/index.js.map +1 -1
- package/dist/sonare.wasm +0 -0
- package/dist/worklet.js +82 -5
- package/dist/worklet.js.map +1 -1
- package/package.json +14 -3
- package/src/codes.ts +27 -4
- package/src/effects_transform.ts +20 -14
- package/src/feature_music.ts +14 -4
- package/src/metering.ts +4 -2
- package/src/project_class.ts +13 -0
- package/src/project_internal.ts +2 -0
- package/src/realtime_voice_changer.ts +79 -3
- package/src/sonare.js.d.ts +4 -0
package/dist/index.d.ts
CHANGED
|
@@ -1176,12 +1176,12 @@ interface PercussiveRequest extends ValidateOptions {
|
|
|
1176
1176
|
}
|
|
1177
1177
|
interface TimeStretchRequest extends ValidateOptions {
|
|
1178
1178
|
samples: Float32Array;
|
|
1179
|
-
sampleRate
|
|
1179
|
+
sampleRate?: number;
|
|
1180
1180
|
rate: number;
|
|
1181
1181
|
}
|
|
1182
1182
|
interface PitchShiftRequest extends ValidateOptions {
|
|
1183
1183
|
samples: Float32Array;
|
|
1184
|
-
sampleRate
|
|
1184
|
+
sampleRate?: number;
|
|
1185
1185
|
semitones: number;
|
|
1186
1186
|
}
|
|
1187
1187
|
interface PitchCorrectToMidiRequest extends ValidateOptions {
|
|
@@ -1215,7 +1215,7 @@ interface NoteMoveRequest extends NoteMoveOptions, ValidateOptions {
|
|
|
1215
1215
|
}
|
|
1216
1216
|
interface NormalizeRequest extends ValidateOptions {
|
|
1217
1217
|
samples: Float32Array;
|
|
1218
|
-
sampleRate
|
|
1218
|
+
sampleRate?: number;
|
|
1219
1219
|
targetDb?: number;
|
|
1220
1220
|
}
|
|
1221
1221
|
interface SpectralEditRequest extends SpectralEditOptions, ValidateOptions {
|
|
@@ -1256,7 +1256,7 @@ declare function percussive(samples: Float32Array, sampleRate?: number, options?
|
|
|
1256
1256
|
* Time-stretch audio without changing pitch.
|
|
1257
1257
|
*
|
|
1258
1258
|
* @param samples - Audio samples (mono, float32)
|
|
1259
|
-
* @param sampleRate - Sample rate in Hz
|
|
1259
|
+
* @param sampleRate - Sample rate in Hz (default: 22050)
|
|
1260
1260
|
* @param rate - Time stretch rate (0.5 = double duration, 2.0 = half duration)
|
|
1261
1261
|
* @returns Time-stretched audio
|
|
1262
1262
|
*/
|
|
@@ -1266,7 +1266,7 @@ declare function timeStretch(samples: Float32Array, sampleRate: number, rate: nu
|
|
|
1266
1266
|
* Pitch-shift audio without changing duration.
|
|
1267
1267
|
*
|
|
1268
1268
|
* @param samples - Audio samples (mono, float32)
|
|
1269
|
-
* @param sampleRate - Sample rate in Hz
|
|
1269
|
+
* @param sampleRate - Sample rate in Hz (default: 22050)
|
|
1270
1270
|
* @param semitones - Pitch shift in semitones (+12 = one octave up, -12 = one octave down)
|
|
1271
1271
|
* @returns Pitch-shifted audio
|
|
1272
1272
|
*/
|
|
@@ -1340,7 +1340,7 @@ declare function noteMove(samples: Float32Array, sampleRate?: number, options?:
|
|
|
1340
1340
|
* Normalize audio to target peak level.
|
|
1341
1341
|
*
|
|
1342
1342
|
* @param samples - Audio samples (mono, float32)
|
|
1343
|
-
* @param sampleRate - Sample rate in Hz
|
|
1343
|
+
* @param sampleRate - Sample rate in Hz (default: 22050)
|
|
1344
1344
|
* @param targetDb - Target peak level in dB (default: 0 dB = full scale)
|
|
1345
1345
|
* @returns Normalized audio
|
|
1346
1346
|
*/
|
|
@@ -2645,6 +2645,10 @@ declare class Project {
|
|
|
2645
2645
|
undo(): void;
|
|
2646
2646
|
/** Redo the most recently undone edit. */
|
|
2647
2647
|
redo(): void;
|
|
2648
|
+
/** Clear the undo/redo history without changing the current project state. */
|
|
2649
|
+
clearHistory(): void;
|
|
2650
|
+
/** Cap the undo history depth (clamped to >= 1); evicts oldest entries beyond the cap. */
|
|
2651
|
+
setMaxUndoDepth(depth: number): void;
|
|
2648
2652
|
/** Replace a MIDI clip's entire event list. */
|
|
2649
2653
|
setMidiEvents(clipId: number, events: ReadonlyArray<ProjectMidiEvent | readonly [number, number, number]>): void;
|
|
2650
2654
|
/** Import an in-memory SMF buffer; returns the first added clip id. */
|
|
@@ -5079,8 +5083,10 @@ interface WaveformPeaksReport {
|
|
|
5079
5083
|
declare function meteringStereoCorrelation(request: MeteringStereoRequest): number;
|
|
5080
5084
|
declare function meteringStereoCorrelation(left: Float32Array, right: Float32Array, sampleRate?: number, options?: ValidateOptions): number;
|
|
5081
5085
|
/**
|
|
5082
|
-
* Side / mid energy ratio
|
|
5083
|
-
*
|
|
5086
|
+
* Side / mid energy ratio in `[0, +Infinity)`: 0 = pure mono, ~1 = wide stereo,
|
|
5087
|
+
* larger = increasingly decorrelated / out-of-phase. The value is unbounded and
|
|
5088
|
+
* returns `Infinity` when the mid channel is silent (a mono-collapsed / fully
|
|
5089
|
+
* out-of-phase signal).
|
|
5084
5090
|
*/
|
|
5085
5091
|
declare function meteringStereoWidth(request: MeteringStereoRequest): number;
|
|
5086
5092
|
declare function meteringStereoWidth(left: Float32Array, right: Float32Array, sampleRate?: number, options?: ValidateOptions): number;
|
|
@@ -6022,7 +6028,7 @@ declare class RealtimeVoiceChanger {
|
|
|
6022
6028
|
constructor(config?: RealtimeVoiceChangerConfigInput);
|
|
6023
6029
|
prepare(sampleRate: number, maxBlockSize?: number, channels?: number): void;
|
|
6024
6030
|
reset(): void;
|
|
6025
|
-
setConfig(config: RealtimeVoiceChangerConfigInput): void;
|
|
6031
|
+
setConfig(config: RealtimeVoiceChangerConfigInput | RealtimeVoiceChangerPodConfig): void;
|
|
6026
6032
|
configJson(): string;
|
|
6027
6033
|
latencySamples(): number;
|
|
6028
6034
|
processMono(samples: Float32Array): Float32Array;
|
package/dist/index.js
CHANGED
|
@@ -244,12 +244,16 @@ function percussive(samples, sampleRate = 22050, options = {}) {
|
|
|
244
244
|
function timeStretch(samples, sampleRate, rate, options = {}) {
|
|
245
245
|
const request = samples instanceof Float32Array ? { samples, sampleRate, rate, ...options } : samples;
|
|
246
246
|
assertSamples("timeStretch", request.samples, request.validate !== false);
|
|
247
|
-
return requireModule().timeStretch(request.samples, request.sampleRate, request.rate);
|
|
247
|
+
return requireModule().timeStretch(request.samples, request.sampleRate ?? 22050, request.rate);
|
|
248
248
|
}
|
|
249
249
|
function pitchShift(samples, sampleRate, semitones, options = {}) {
|
|
250
250
|
const request = samples instanceof Float32Array ? { samples, sampleRate, semitones, ...options } : samples;
|
|
251
251
|
assertSamples("pitchShift", request.samples, request.validate !== false);
|
|
252
|
-
return requireModule().pitchShift(
|
|
252
|
+
return requireModule().pitchShift(
|
|
253
|
+
request.samples,
|
|
254
|
+
request.sampleRate ?? 22050,
|
|
255
|
+
request.semitones
|
|
256
|
+
);
|
|
253
257
|
}
|
|
254
258
|
function pitchCorrectToMidi(samples, sampleRate = 22050, currentMidi = 69, targetMidi = 69, options = {}) {
|
|
255
259
|
const request = samples instanceof Float32Array ? { samples, sampleRate, currentMidi, targetMidi, ...options } : samples;
|
|
@@ -336,7 +340,11 @@ function noteMove(samples, sampleRate = 22050, options = {}) {
|
|
|
336
340
|
function normalize(samples, sampleRate, targetDb = 0, options = {}) {
|
|
337
341
|
const request = samples instanceof Float32Array ? { samples, sampleRate, targetDb, ...options } : samples;
|
|
338
342
|
assertSamples("normalize", request.samples, request.validate !== false);
|
|
339
|
-
return requireModule().normalize(
|
|
343
|
+
return requireModule().normalize(
|
|
344
|
+
request.samples,
|
|
345
|
+
request.sampleRate ?? 22050,
|
|
346
|
+
request.targetDb ?? 0
|
|
347
|
+
);
|
|
340
348
|
}
|
|
341
349
|
function spectralEdit(samples, sampleRate, ops = [], options = {}) {
|
|
342
350
|
const request = samples instanceof Float32Array ? { samples, sampleRate, ops, ...options } : samples;
|
|
@@ -1257,7 +1265,11 @@ function analyzeMelody(samples, sampleRate = 22050, options = {}) {
|
|
|
1257
1265
|
const fmax = options.fmax ?? 2093;
|
|
1258
1266
|
validateFrequencyBounds("analyzeMelody", fmin, fmax);
|
|
1259
1267
|
if (fmin <= 0) {
|
|
1260
|
-
throw new
|
|
1268
|
+
throw new SonareError(
|
|
1269
|
+
4 /* InvalidParameter */,
|
|
1270
|
+
"InvalidParameter",
|
|
1271
|
+
"analyzeMelody: fmin must be positive"
|
|
1272
|
+
);
|
|
1261
1273
|
}
|
|
1262
1274
|
validatePositiveIntegers("analyzeMelody", {
|
|
1263
1275
|
frameLength: options.frameLength ?? 2048,
|
|
@@ -1266,7 +1278,11 @@ function analyzeMelody(samples, sampleRate = 22050, options = {}) {
|
|
|
1266
1278
|
const threshold = options.threshold ?? 0.1;
|
|
1267
1279
|
assertFiniteScalar("analyzeMelody", threshold, "threshold");
|
|
1268
1280
|
if (threshold <= 0) {
|
|
1269
|
-
throw new
|
|
1281
|
+
throw new SonareError(
|
|
1282
|
+
4 /* InvalidParameter */,
|
|
1283
|
+
"InvalidParameter",
|
|
1284
|
+
"analyzeMelody: threshold must be positive"
|
|
1285
|
+
);
|
|
1270
1286
|
}
|
|
1271
1287
|
return requireModule9().analyzeMelody(
|
|
1272
1288
|
samples,
|
|
@@ -3555,6 +3571,17 @@ var Project = class _Project {
|
|
|
3555
3571
|
redo() {
|
|
3556
3572
|
this.native.redo();
|
|
3557
3573
|
}
|
|
3574
|
+
/** Clear the undo/redo history without changing the current project state. */
|
|
3575
|
+
clearHistory() {
|
|
3576
|
+
this.native.clearHistory();
|
|
3577
|
+
}
|
|
3578
|
+
/** Cap the undo history depth (clamped to >= 1); evicts oldest entries beyond the cap. */
|
|
3579
|
+
setMaxUndoDepth(depth) {
|
|
3580
|
+
if (!Number.isInteger(depth) || depth < 1) {
|
|
3581
|
+
throw new RangeError("Project.setMaxUndoDepth: depth must be an integer >= 1");
|
|
3582
|
+
}
|
|
3583
|
+
this.native.setMaxUndoDepth(depth);
|
|
3584
|
+
}
|
|
3558
3585
|
/** Replace a MIDI clip's entire event list. */
|
|
3559
3586
|
setMidiEvents(clipId, events) {
|
|
3560
3587
|
assertProjectMidiEvents("Project.setMidiEvents", events);
|
|
@@ -4021,6 +4048,8 @@ function panLawCode(panLaw) {
|
|
|
4021
4048
|
return panLaw;
|
|
4022
4049
|
}
|
|
4023
4050
|
switch (panLaw) {
|
|
4051
|
+
case "const3dB":
|
|
4052
|
+
return 0;
|
|
4024
4053
|
case "const4.5dB":
|
|
4025
4054
|
return 1;
|
|
4026
4055
|
case "const6dB":
|
|
@@ -4028,7 +4057,7 @@ function panLawCode(panLaw) {
|
|
|
4028
4057
|
case "linear0dB":
|
|
4029
4058
|
return 3;
|
|
4030
4059
|
default:
|
|
4031
|
-
|
|
4060
|
+
throw new Error(`Invalid pan law: ${panLaw}`);
|
|
4032
4061
|
}
|
|
4033
4062
|
}
|
|
4034
4063
|
function panModeCode(panMode) {
|
|
@@ -4036,6 +4065,8 @@ function panModeCode(panMode) {
|
|
|
4036
4065
|
return panMode;
|
|
4037
4066
|
}
|
|
4038
4067
|
switch (panMode) {
|
|
4068
|
+
case "balance":
|
|
4069
|
+
return 0;
|
|
4039
4070
|
case "stereoPan":
|
|
4040
4071
|
case "stereo-pan":
|
|
4041
4072
|
return 1;
|
|
@@ -4043,17 +4074,34 @@ function panModeCode(panMode) {
|
|
|
4043
4074
|
case "dual-pan":
|
|
4044
4075
|
return 2;
|
|
4045
4076
|
default:
|
|
4046
|
-
|
|
4077
|
+
throw new Error(`Invalid pan mode: ${panMode}`);
|
|
4047
4078
|
}
|
|
4048
4079
|
}
|
|
4049
4080
|
function meterTapCode(tap) {
|
|
4050
|
-
|
|
4081
|
+
if (typeof tap === "number") {
|
|
4082
|
+
return tap;
|
|
4083
|
+
}
|
|
4084
|
+
switch (tap) {
|
|
4085
|
+
case "preFader":
|
|
4086
|
+
return 0;
|
|
4087
|
+
case "postFader":
|
|
4088
|
+
return 1;
|
|
4089
|
+
default:
|
|
4090
|
+
throw new Error(`Invalid meter tap: ${tap}`);
|
|
4091
|
+
}
|
|
4051
4092
|
}
|
|
4052
4093
|
function sendTimingCode(timing) {
|
|
4053
4094
|
if (typeof timing === "number") {
|
|
4054
4095
|
return timing;
|
|
4055
4096
|
}
|
|
4056
|
-
|
|
4097
|
+
switch (timing) {
|
|
4098
|
+
case "postFader":
|
|
4099
|
+
return 0;
|
|
4100
|
+
case "preFader":
|
|
4101
|
+
return 1;
|
|
4102
|
+
default:
|
|
4103
|
+
throw new Error(`Invalid send timing: ${timing}`);
|
|
4104
|
+
}
|
|
4057
4105
|
}
|
|
4058
4106
|
|
|
4059
4107
|
// src/realtime_engine.ts
|
|
@@ -5330,6 +5378,61 @@ var Mixer = class _Mixer {
|
|
|
5330
5378
|
};
|
|
5331
5379
|
|
|
5332
5380
|
// src/realtime_voice_changer.ts
|
|
5381
|
+
function isFlatVoiceChangerPod(config) {
|
|
5382
|
+
return typeof config === "object" && config !== null && "retuneSemitones" in config;
|
|
5383
|
+
}
|
|
5384
|
+
function flatVoiceChangerPodToNested(pod) {
|
|
5385
|
+
return {
|
|
5386
|
+
inputGainDb: pod.inputGainDb,
|
|
5387
|
+
outputGainDb: pod.outputGainDb,
|
|
5388
|
+
wetMix: pod.wetMix,
|
|
5389
|
+
retune: { semitones: pod.retuneSemitones, mix: pod.retuneMix, grainSize: pod.retuneGrainSize },
|
|
5390
|
+
formant: {
|
|
5391
|
+
factor: pod.formantFactor,
|
|
5392
|
+
amount: pod.formantAmount,
|
|
5393
|
+
body: pod.formantBody,
|
|
5394
|
+
brightness: pod.formantBrightness,
|
|
5395
|
+
nasal: pod.formantNasal
|
|
5396
|
+
},
|
|
5397
|
+
eq: {
|
|
5398
|
+
highpassHz: pod.eqHighpassHz,
|
|
5399
|
+
bodyDb: pod.eqBodyDb,
|
|
5400
|
+
presenceDb: pod.eqPresenceDb,
|
|
5401
|
+
airDb: pod.eqAirDb
|
|
5402
|
+
},
|
|
5403
|
+
gate: {
|
|
5404
|
+
thresholdDb: pod.gateThresholdDb,
|
|
5405
|
+
attackMs: pod.gateAttackMs,
|
|
5406
|
+
releaseMs: pod.gateReleaseMs,
|
|
5407
|
+
rangeDb: pod.gateRangeDb
|
|
5408
|
+
},
|
|
5409
|
+
compressor: {
|
|
5410
|
+
thresholdDb: pod.compressorThresholdDb,
|
|
5411
|
+
ratio: pod.compressorRatio,
|
|
5412
|
+
attackMs: pod.compressorAttackMs,
|
|
5413
|
+
releaseMs: pod.compressorReleaseMs,
|
|
5414
|
+
makeupGainDb: pod.compressorMakeupGainDb
|
|
5415
|
+
},
|
|
5416
|
+
deesser: {
|
|
5417
|
+
frequencyHz: pod.deesserFrequencyHz,
|
|
5418
|
+
thresholdDb: pod.deesserThresholdDb,
|
|
5419
|
+
ratio: pod.deesserRatio,
|
|
5420
|
+
rangeDb: pod.deesserRangeDb
|
|
5421
|
+
},
|
|
5422
|
+
reverb: {
|
|
5423
|
+
mix: pod.reverbMix,
|
|
5424
|
+
timeMs: pod.reverbTimeMs,
|
|
5425
|
+
damping: pod.reverbDamping,
|
|
5426
|
+
seed: pod.reverbSeed
|
|
5427
|
+
},
|
|
5428
|
+
limiter: {
|
|
5429
|
+
ceilingDb: pod.limiterCeilingDb,
|
|
5430
|
+
releaseMs: pod.limiterReleaseMs,
|
|
5431
|
+
enableIspLimiter: pod.limiterEnableIspLimiter,
|
|
5432
|
+
ispCeilingDbtp: pod.limiterIspCeilingDbtp
|
|
5433
|
+
}
|
|
5434
|
+
};
|
|
5435
|
+
}
|
|
5333
5436
|
var RealtimeVoiceChanger = class {
|
|
5334
5437
|
constructor(config = "neutral-monitor") {
|
|
5335
5438
|
const module2 = getSonareModule();
|
|
@@ -5342,7 +5445,8 @@ var RealtimeVoiceChanger = class {
|
|
|
5342
5445
|
this.changer.reset();
|
|
5343
5446
|
}
|
|
5344
5447
|
setConfig(config) {
|
|
5345
|
-
|
|
5448
|
+
const resolved = isFlatVoiceChangerPod(config) ? flatVoiceChangerPodToNested(config) : config;
|
|
5449
|
+
this.changer.setConfig(resolved);
|
|
5346
5450
|
}
|
|
5347
5451
|
configJson() {
|
|
5348
5452
|
return this.changer.configJson();
|