@libraz/libsonare 1.5.5 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -20
- package/dist/analysis.d.ts +5809 -0
- package/dist/analysis.js +2574 -0
- package/dist/analysis.js.map +1 -0
- package/dist/index.d.ts +884 -55
- package/dist/index.js +1302 -292
- package/dist/index.js.map +1 -1
- package/dist/schemas/realtime-voice-changer-preset-pack.schema.json +27 -0
- package/dist/schemas/realtime-voice-changer-preset.schema.json +140 -0
- package/dist/sonare-analysis.js +2 -0
- package/dist/sonare-analysis.wasm +0 -0
- package/dist/sonare.js +1 -1
- package/dist/sonare.wasm +0 -0
- package/dist/worker.d.ts +65 -0
- package/dist/worker.js +734 -0
- package/dist/worker.js.map +1 -0
- package/dist/worklet.d.ts +628 -88
- package/dist/worklet.js +1816 -266
- package/dist/worklet.js.map +1 -1
- package/package.json +23 -11
- package/src/_chain_config.ts +5 -3
- package/src/analysis.ts +137 -0
- package/src/analysis_helpers.ts +40 -29
- package/src/audio.ts +7 -2
- package/src/clip_page_streamer.ts +62 -8
- package/src/codes.ts +87 -64
- package/src/effects_mastering.ts +1 -0
- package/src/effects_transform.ts +179 -10
- package/src/errors.ts +1 -0
- package/src/feature_core.ts +140 -2
- package/src/feature_music.ts +25 -3
- package/src/feature_pitch.ts +70 -1
- package/src/feature_spectral.ts +295 -7
- package/src/feature_spectrogram.ts +203 -3
- package/src/features.ts +16 -1
- package/src/index.ts +120 -8
- package/src/mastering_chain.ts +20 -8
- package/src/mastering_core.ts +5 -0
- package/src/mastering_dynamics.ts +7 -1
- package/src/metering.ts +6 -1
- package/src/mixer.ts +3 -3
- package/src/opfs_clip_pages.ts +26 -1
- package/src/project.ts +13 -0
- package/src/project_class.ts +204 -23
- package/src/project_internal.ts +38 -34
- package/src/project_types.ts +114 -11
- package/src/public_types.ts +68 -0
- package/src/public_types_mastering.ts +22 -0
- package/src/public_types_mixing.ts +27 -2
- package/src/public_types_music.ts +9 -0
- package/src/public_types_realtime.ts +23 -5
- package/src/public_types_spectral.ts +33 -0
- package/src/quick_analysis.ts +46 -10
- package/src/realtime_engine.ts +167 -6
- package/src/realtime_voice_changer.ts +51 -77
- package/src/sonare-analysis.js.d.ts +8 -0
- package/src/sonare.js.d.ts +340 -6
- package/src/stream_analyzer.ts +6 -1
- package/src/streaming_processors.ts +15 -0
- package/src/web_midi.ts +46 -11
- package/src/worker.ts +196 -0
- package/src/worker_client.ts +352 -0
- package/src/worker_protocol.ts +59 -0
- package/src/worklet/engine-automation.ts +2 -1
- package/src/worklet/engine-capture-facade.ts +13 -4
- package/src/worklet/engine-clips.ts +12 -3
- package/src/worklet/engine-node.ts +264 -21
- package/src/worklet/engine-offline.ts +7 -2
- package/src/worklet/engine-parameter-facade.ts +55 -5
- package/src/worklet/engine-processor.ts +435 -62
- package/src/worklet/engine-register.ts +9 -1
- package/src/worklet/engine-strips.ts +19 -3
- package/src/worklet/engine-sync.ts +2 -6
- package/src/worklet/engine-tempo-facade.ts +8 -6
- package/src/worklet/engine.ts +390 -13
- package/src/worklet/guards.ts +121 -8
- package/src/worklet/messages.ts +166 -8
- package/src/worklet/protocol.ts +305 -17
- package/src/worklet/voice-changer-processor.ts +12 -15
- package/src/worklet.ts +20 -1
package/src/project_class.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
assertProjectMidiEvents,
|
|
3
|
+
projectAutomationTargetKindValue,
|
|
3
4
|
projectLoopModeValue,
|
|
4
5
|
projectMidi1Event,
|
|
5
6
|
projectModule,
|
|
@@ -9,12 +10,17 @@ import {
|
|
|
9
10
|
} from './project_internal';
|
|
10
11
|
import type {
|
|
11
12
|
BuiltinSynthBinding,
|
|
13
|
+
ExternalSeparatedStemImportRequest,
|
|
14
|
+
ExternalSeparatedStemImportResult,
|
|
12
15
|
MidiCcLearnOptions,
|
|
13
16
|
ProjectAssistSidecar,
|
|
17
|
+
ProjectAssistSidecarInput,
|
|
14
18
|
ProjectAutomationLaneDesc,
|
|
15
19
|
ProjectAutomationPoint,
|
|
20
|
+
ProjectAutomationTargetKind,
|
|
16
21
|
ProjectBounceOptions,
|
|
17
22
|
ProjectChordSymbol,
|
|
23
|
+
ProjectClip,
|
|
18
24
|
ProjectClipCompSegment,
|
|
19
25
|
ProjectClipDesc,
|
|
20
26
|
ProjectClipFade,
|
|
@@ -32,9 +38,11 @@ import type {
|
|
|
32
38
|
ProjectMidiRouteConfig,
|
|
33
39
|
ProjectMidiRouteResult,
|
|
34
40
|
ProjectNotePairValidation,
|
|
41
|
+
ProjectSource,
|
|
35
42
|
ProjectTempoCandidate,
|
|
36
43
|
ProjectTempoSegment,
|
|
37
44
|
ProjectTimeSignatureSegment,
|
|
45
|
+
ProjectTrack,
|
|
38
46
|
ProjectTrackDesc,
|
|
39
47
|
ProjectTrackKind,
|
|
40
48
|
ProjectWarpMapDesc,
|
|
@@ -44,6 +52,41 @@ import type {
|
|
|
44
52
|
SynthPatch,
|
|
45
53
|
} from './project_types';
|
|
46
54
|
|
|
55
|
+
function validateAssistSidecarUint32(value: unknown, field: string): number {
|
|
56
|
+
if (
|
|
57
|
+
typeof value !== 'number' ||
|
|
58
|
+
!Number.isSafeInteger(value) ||
|
|
59
|
+
value < 0 ||
|
|
60
|
+
value > 0xffff_ffff
|
|
61
|
+
) {
|
|
62
|
+
throw new RangeError(`Project.setAssistSidecar: ${field} must be a uint32`);
|
|
63
|
+
}
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function validateAssistSidecarPpq(value: unknown, field: string): number {
|
|
68
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {
|
|
69
|
+
throw new RangeError(
|
|
70
|
+
`Project.setAssistSidecar: ${field} must be a finite, non-negative number`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function validateAssistSidecarPayload(value: unknown): Uint8Array {
|
|
77
|
+
if (!(value instanceof Uint8Array)) {
|
|
78
|
+
throw new TypeError('Project.setAssistSidecar: payload must be a Uint8Array');
|
|
79
|
+
}
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function validateAssistSidecarModuleId(value: unknown): string {
|
|
84
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
85
|
+
throw new TypeError('Project.setAssistSidecar: moduleId must be a non-empty string');
|
|
86
|
+
}
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
|
|
47
90
|
/**
|
|
48
91
|
* Headless DAW project (control-thread-only arrangement model).
|
|
49
92
|
*
|
|
@@ -77,6 +120,11 @@ export class Project {
|
|
|
77
120
|
this.native = new (projectModule().Project)();
|
|
78
121
|
}
|
|
79
122
|
|
|
123
|
+
/** Create a new empty project. */
|
|
124
|
+
static create(): Project {
|
|
125
|
+
return new Project();
|
|
126
|
+
}
|
|
127
|
+
|
|
80
128
|
/** Pack a MIDI 1.0 note-on event accepted by {@link setMidiEvents}. */
|
|
81
129
|
static midiNoteOn(
|
|
82
130
|
ppq: number,
|
|
@@ -337,6 +385,19 @@ export class Project {
|
|
|
337
385
|
return this.native.addClip(desc);
|
|
338
386
|
}
|
|
339
387
|
|
|
388
|
+
/** Import host-separated PCM through the normal audio-track/clip path. */
|
|
389
|
+
importExternalStems(
|
|
390
|
+
request: ExternalSeparatedStemImportRequest,
|
|
391
|
+
): ExternalSeparatedStemImportResult {
|
|
392
|
+
return this.native.importExternalStems({
|
|
393
|
+
...request,
|
|
394
|
+
stems: request.stems.map((stem) => ({
|
|
395
|
+
...stem,
|
|
396
|
+
layout: stem.layout === 'mono' ? 1 : stem.layout === 'stereo' ? 2 : stem.layout,
|
|
397
|
+
})),
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
|
|
340
401
|
/** Split captured loop-recording audio into takes and add one clip. */
|
|
341
402
|
addLoopRecordingTakes(desc: ProjectLoopRecordingDesc): ProjectLoopRecordingResult {
|
|
342
403
|
return this.native.addLoopRecordingTakes(desc);
|
|
@@ -391,7 +452,11 @@ export class Project {
|
|
|
391
452
|
* Route a track's MIDI to host-instrument `destinationId` (0 = default). The
|
|
392
453
|
* compiler stamps every MIDI clip on the track with this id so the engine
|
|
393
454
|
* dispatches its events to the instrument registered for that destination.
|
|
394
|
-
* Routes through an undoable edit command.
|
|
455
|
+
* Routes through an undoable edit command. Builtin, NativeSynth, and SF2
|
|
456
|
+
* instruments retain source-track provenance inside a shared destination
|
|
457
|
+
* voice pool. With only zero-latency instruments bound, live lanes and
|
|
458
|
+
* channel-strip bounces remain aligned. Configure one live lane per source
|
|
459
|
+
* track that needs strip processing.
|
|
395
460
|
*/
|
|
396
461
|
setTrackMidiDestination(trackId: number, destinationId: number): void {
|
|
397
462
|
this.native.setTrackMidiDestination(trackId, destinationId);
|
|
@@ -440,6 +505,19 @@ export class Project {
|
|
|
440
505
|
this.native.setMaxUndoDepth(depth);
|
|
441
506
|
}
|
|
442
507
|
|
|
508
|
+
/** Set the combined undo/redo history byte cap. Zero disables retention. */
|
|
509
|
+
setMaxHistoryBytes(bytes: number): void {
|
|
510
|
+
if (typeof bytes !== 'number') {
|
|
511
|
+
throw new TypeError('Project.setMaxHistoryBytes: bytes must be a number');
|
|
512
|
+
}
|
|
513
|
+
if (!Number.isFinite(bytes) || !Number.isInteger(bytes) || bytes < 0 || bytes > 0xffff_ffff) {
|
|
514
|
+
throw new RangeError(
|
|
515
|
+
'Project.setMaxHistoryBytes: bytes must be a finite integer in the uint32 range',
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
this.native.setMaxHistoryBytes(bytes);
|
|
519
|
+
}
|
|
520
|
+
|
|
443
521
|
/** Replace a MIDI clip's entire event list. */
|
|
444
522
|
setMidiEvents(
|
|
445
523
|
clipId: number,
|
|
@@ -603,8 +681,11 @@ export class Project {
|
|
|
603
681
|
* Karplus-Strong / modal / additive / percussion / extended-waveguide-piano
|
|
604
682
|
* engines plus the realism layer). Pass a {@link SynthPatch}, a preset-name
|
|
605
683
|
* string (`'saw-lead'` / `'va:saw-lead'`; see {@link synthPresetNames}), or
|
|
606
|
-
* an array of either; each object entry may carry
|
|
607
|
-
*
|
|
684
|
+
* an array of either; each object entry may carry `destinationId` (default
|
|
685
|
+
* 0) and `useGmPrograms` (default `false`) binding conveniences, neither of
|
|
686
|
+
* which is part of the NativeSynth patch itself. When enabled, MIDI program
|
|
687
|
+
* changes select the corresponding General MIDI voice while the patch remains
|
|
688
|
+
* the fallback.
|
|
608
689
|
* Because the parameter defaults to `{}`, omission and explicit `undefined`
|
|
609
690
|
* both create one default binding. Use an explicitly empty array `[]` (or
|
|
610
691
|
* runtime `null`) for zero bindings. Unknown preset names throw.
|
|
@@ -685,6 +766,26 @@ export class Project {
|
|
|
685
766
|
this.native.setClipFade(clipId, fadeIn, fadeOut);
|
|
686
767
|
}
|
|
687
768
|
|
|
769
|
+
/** Audio source ids that need decoded PCM after deserialization. */
|
|
770
|
+
unresolvedAudioSourceIds(): number[] {
|
|
771
|
+
return this.native.unresolvedAudioSourceIds();
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
/** Register decoded interleaved PCM for an existing audio source (undoable). */
|
|
775
|
+
setSourceAudio(
|
|
776
|
+
sourceId: number,
|
|
777
|
+
audio: Float32Array,
|
|
778
|
+
channels: number,
|
|
779
|
+
sampleRate: number,
|
|
780
|
+
): void {
|
|
781
|
+
this.native.setSourceAudio(sourceId, audio, channels, sampleRate);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/** Replace an audio source's metadata strings as one undoable edit. */
|
|
785
|
+
setAudioSourceMetadata(sourceId: number, contentHash: string, externalStemRole: string): void {
|
|
786
|
+
this.native.setAudioSourceMetadata(sourceId, contentHash, externalStemRole);
|
|
787
|
+
}
|
|
788
|
+
|
|
688
789
|
/** Replace a clip's take list and active take id (undoable). */
|
|
689
790
|
setClipTakes(clipId: number, takes: ReadonlyArray<ProjectClipTake>, activeTakeId = 0): void {
|
|
690
791
|
this.native.setClipTakes(clipId, takes, activeTakeId);
|
|
@@ -739,25 +840,41 @@ export class Project {
|
|
|
739
840
|
this.native.setTrackRoute(trackId, channelStripRef ?? '', outputTarget ?? '');
|
|
740
841
|
}
|
|
741
842
|
|
|
742
|
-
/** Append an automation lane
|
|
843
|
+
/** Append an automation lane; returns its stable target parameter id (undoable). */
|
|
743
844
|
addAutomationLane(trackId: number, desc: ProjectAutomationLaneDesc): number {
|
|
744
|
-
|
|
745
|
-
targetParamId
|
|
746
|
-
|
|
747
|
-
}
|
|
845
|
+
if (desc.targetParamId === 0) {
|
|
846
|
+
throw new RangeError('project automation lane targetParamId must be non-zero');
|
|
847
|
+
}
|
|
848
|
+
const nativeDesc: ProjectAutomationLaneDesc = { ...desc };
|
|
849
|
+
if (Object.keys(desc).includes('targetKind')) {
|
|
850
|
+
nativeDesc.targetKind = projectAutomationTargetKindValue(
|
|
851
|
+
desc.targetKind as ProjectAutomationTargetKind,
|
|
852
|
+
) as ProjectAutomationTargetKind;
|
|
853
|
+
}
|
|
854
|
+
return this.native.addAutomationLane(trackId, nativeDesc);
|
|
748
855
|
}
|
|
749
856
|
|
|
750
|
-
/** Replace
|
|
751
|
-
editAutomationLane(
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
857
|
+
/** Replace the lane identified by its stable target parameter id (undoable). */
|
|
858
|
+
editAutomationLane(
|
|
859
|
+
trackId: number,
|
|
860
|
+
targetParamId: number,
|
|
861
|
+
desc: ProjectAutomationLaneDesc,
|
|
862
|
+
): void {
|
|
863
|
+
if (desc.targetParamId === 0) {
|
|
864
|
+
throw new RangeError('project automation lane targetParamId must be non-zero');
|
|
865
|
+
}
|
|
866
|
+
const nativeDesc: ProjectAutomationLaneDesc = { ...desc };
|
|
867
|
+
if (Object.keys(desc).includes('targetKind')) {
|
|
868
|
+
nativeDesc.targetKind = projectAutomationTargetKindValue(
|
|
869
|
+
desc.targetKind as ProjectAutomationTargetKind,
|
|
870
|
+
) as ProjectAutomationTargetKind;
|
|
871
|
+
}
|
|
872
|
+
this.native.editAutomationLane(trackId, targetParamId, nativeDesc);
|
|
756
873
|
}
|
|
757
874
|
|
|
758
|
-
/** Remove
|
|
759
|
-
removeAutomationLane(trackId: number,
|
|
760
|
-
this.native.removeAutomationLane(trackId,
|
|
875
|
+
/** Remove the lane identified by its stable target parameter id (undoable). */
|
|
876
|
+
removeAutomationLane(trackId: number, targetParamId: number): void {
|
|
877
|
+
this.native.removeAutomationLane(trackId, targetParamId);
|
|
761
878
|
}
|
|
762
879
|
|
|
763
880
|
/** Replace the project's key annotation stream (undoable). */
|
|
@@ -770,7 +887,14 @@ export class Project {
|
|
|
770
887
|
this.native.annotateChords(chords);
|
|
771
888
|
}
|
|
772
889
|
|
|
773
|
-
/**
|
|
890
|
+
/**
|
|
891
|
+
* Add or update an opaque assist sidecar via an undoable edit.
|
|
892
|
+
*
|
|
893
|
+
* The descriptor form is the canonical API and matches the Node binding;
|
|
894
|
+
* the positional form remains available for compatibility with the original
|
|
895
|
+
* WASM facade.
|
|
896
|
+
*/
|
|
897
|
+
setAssistSidecar(sidecar: ProjectAssistSidecarInput): void;
|
|
774
898
|
setAssistSidecar(
|
|
775
899
|
moduleId: string,
|
|
776
900
|
schemaVersion: number,
|
|
@@ -778,14 +902,52 @@ export class Project {
|
|
|
778
902
|
regionStartPpq: number,
|
|
779
903
|
regionEndPpq: number,
|
|
780
904
|
payload: Uint8Array,
|
|
905
|
+
): void;
|
|
906
|
+
setAssistSidecar(
|
|
907
|
+
sidecarOrModuleId: ProjectAssistSidecarInput | string,
|
|
908
|
+
schemaVersion?: number,
|
|
909
|
+
targetTrackId?: number,
|
|
910
|
+
regionStartPpq?: number,
|
|
911
|
+
regionEndPpq?: number,
|
|
912
|
+
payload?: Uint8Array,
|
|
781
913
|
): void {
|
|
914
|
+
if (typeof sidecarOrModuleId === 'string') {
|
|
915
|
+
if (
|
|
916
|
+
schemaVersion === undefined ||
|
|
917
|
+
targetTrackId === undefined ||
|
|
918
|
+
regionStartPpq === undefined ||
|
|
919
|
+
regionEndPpq === undefined ||
|
|
920
|
+
payload === undefined
|
|
921
|
+
) {
|
|
922
|
+
throw new TypeError('Project.setAssistSidecar: positional form requires six arguments');
|
|
923
|
+
}
|
|
924
|
+
this.native.setAssistSidecar(
|
|
925
|
+
validateAssistSidecarModuleId(sidecarOrModuleId),
|
|
926
|
+
validateAssistSidecarUint32(schemaVersion, 'schemaVersion'),
|
|
927
|
+
validateAssistSidecarUint32(targetTrackId, 'targetTrackId'),
|
|
928
|
+
validateAssistSidecarPpq(regionStartPpq, 'regionStartPpq'),
|
|
929
|
+
validateAssistSidecarPpq(regionEndPpq, 'regionEndPpq'),
|
|
930
|
+
validateAssistSidecarPayload(payload),
|
|
931
|
+
);
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
if (
|
|
936
|
+
sidecarOrModuleId === null ||
|
|
937
|
+
typeof sidecarOrModuleId !== 'object' ||
|
|
938
|
+
Array.isArray(sidecarOrModuleId)
|
|
939
|
+
) {
|
|
940
|
+
throw new TypeError('Project.setAssistSidecar: expected a sidecar descriptor object');
|
|
941
|
+
}
|
|
942
|
+
const sidecar = sidecarOrModuleId;
|
|
943
|
+
const moduleId = validateAssistSidecarModuleId(sidecar.moduleId);
|
|
782
944
|
this.native.setAssistSidecar(
|
|
783
945
|
moduleId,
|
|
784
|
-
schemaVersion,
|
|
785
|
-
targetTrackId,
|
|
786
|
-
regionStartPpq,
|
|
787
|
-
regionEndPpq,
|
|
788
|
-
payload,
|
|
946
|
+
validateAssistSidecarUint32(sidecar.schemaVersion ?? 0, 'schemaVersion'),
|
|
947
|
+
validateAssistSidecarUint32(sidecar.targetTrackId ?? 0, 'targetTrackId'),
|
|
948
|
+
validateAssistSidecarPpq(sidecar.regionStartPpq ?? 0, 'regionStartPpq'),
|
|
949
|
+
validateAssistSidecarPpq(sidecar.regionEndPpq ?? 0, 'regionEndPpq'),
|
|
950
|
+
validateAssistSidecarPayload(sidecar.payload ?? new Uint8Array()),
|
|
789
951
|
);
|
|
790
952
|
}
|
|
791
953
|
|
|
@@ -799,6 +961,12 @@ export class Project {
|
|
|
799
961
|
return this.native.getAssistSidecar(index);
|
|
800
962
|
}
|
|
801
963
|
|
|
964
|
+
/** Read every stored assist sidecar in the same order as the index getter. */
|
|
965
|
+
assistSidecars(): ProjectAssistSidecar[] {
|
|
966
|
+
const count = this.assistSidecarCount();
|
|
967
|
+
return Array.from({ length: count }, (_, index) => this.getAssistSidecar(index));
|
|
968
|
+
}
|
|
969
|
+
|
|
802
970
|
/** Set the project's clip-overlap policy (SonareProjectOverlapPolicy ordinal). */
|
|
803
971
|
setOverlapPolicy(policy: number): void {
|
|
804
972
|
this.native.setOverlapPolicy(policy);
|
|
@@ -841,6 +1009,19 @@ export class Project {
|
|
|
841
1009
|
return this.native.markerByIndex(index);
|
|
842
1010
|
}
|
|
843
1011
|
|
|
1012
|
+
/** Read a stored project track by 0-based index. */
|
|
1013
|
+
trackByIndex(index: number): ProjectTrack {
|
|
1014
|
+
return this.native.trackByIndex(index);
|
|
1015
|
+
}
|
|
1016
|
+
/** Read a stored project clip by 0-based index. */
|
|
1017
|
+
clipByIndex(index: number): ProjectClip {
|
|
1018
|
+
return this.native.clipByIndex(index);
|
|
1019
|
+
}
|
|
1020
|
+
/** Read a stored project source by 0-based index. */
|
|
1021
|
+
sourceByIndex(index: number): ProjectSource {
|
|
1022
|
+
return this.native.sourceByIndex(index);
|
|
1023
|
+
}
|
|
1024
|
+
|
|
844
1025
|
/** Number of markers in the project. */
|
|
845
1026
|
markerCount(): number {
|
|
846
1027
|
return this.native.markerCount();
|
package/src/project_internal.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import { resolveEnumOrdinal } from './codes';
|
|
1
2
|
import { getSonareModule } from './module_state';
|
|
2
3
|
import type {
|
|
3
4
|
BuiltinSynthBinding,
|
|
4
5
|
ProjectAssistSidecar,
|
|
6
|
+
ProjectAutomationLaneDesc,
|
|
5
7
|
ProjectAutomationPoint,
|
|
8
|
+
ProjectAutomationTargetKind,
|
|
6
9
|
ProjectBounceOptions,
|
|
7
10
|
ProjectChordSymbol,
|
|
11
|
+
ProjectClip,
|
|
8
12
|
ProjectClipCompSegment,
|
|
9
13
|
ProjectClipDesc,
|
|
10
14
|
ProjectClipFade,
|
|
@@ -21,9 +25,11 @@ import type {
|
|
|
21
25
|
ProjectMidiRouteConfig,
|
|
22
26
|
ProjectMidiRouteResult,
|
|
23
27
|
ProjectNotePairValidation,
|
|
28
|
+
ProjectSource,
|
|
24
29
|
ProjectTempoCandidate,
|
|
25
30
|
ProjectTempoSegment,
|
|
26
31
|
ProjectTimeSignatureSegment,
|
|
32
|
+
ProjectTrack,
|
|
27
33
|
ProjectTrackKind,
|
|
28
34
|
ProjectWarpMapDesc,
|
|
29
35
|
ProjectWarpMode,
|
|
@@ -41,6 +47,7 @@ export interface WasmProject {
|
|
|
41
47
|
setSampleRate: (sampleRate: number) => void;
|
|
42
48
|
addTrack: (desc: { kind?: number | string; name?: string }) => number;
|
|
43
49
|
addClip: (desc: ProjectClipDesc) => number;
|
|
50
|
+
importExternalStems: (request: unknown) => { trackIds: number[]; clipIds: number[] };
|
|
44
51
|
addLoopRecordingTakes: (desc: ProjectLoopRecordingDesc) => ProjectLoopRecordingResult;
|
|
45
52
|
addMidiClip: (startPpq: number, lengthPpq: number) => ProjectMidiClipResult;
|
|
46
53
|
splitClip: (clipId: number, splitPpq: number) => number;
|
|
@@ -60,6 +67,7 @@ export interface WasmProject {
|
|
|
60
67
|
redo: () => void;
|
|
61
68
|
clearHistory: () => void;
|
|
62
69
|
setMaxUndoDepth: (depth: number) => void;
|
|
70
|
+
setMaxHistoryBytes: (bytes: number) => void;
|
|
63
71
|
setMidiEvents: (
|
|
64
72
|
clipId: number,
|
|
65
73
|
events: ReadonlyArray<ProjectMidiEvent | readonly [number, number, number]>,
|
|
@@ -108,6 +116,14 @@ export interface WasmProject {
|
|
|
108
116
|
removeClip: (clipId: number) => void;
|
|
109
117
|
setClipGain: (clipId: number, gain: number) => void;
|
|
110
118
|
setClipFade: (clipId: number, fadeIn: ProjectClipFade, fadeOut: ProjectClipFade) => void;
|
|
119
|
+
unresolvedAudioSourceIds: () => number[];
|
|
120
|
+
setSourceAudio: (
|
|
121
|
+
sourceId: number,
|
|
122
|
+
audio: Float32Array,
|
|
123
|
+
channels: number,
|
|
124
|
+
sampleRate: number,
|
|
125
|
+
) => void;
|
|
126
|
+
setAudioSourceMetadata: (sourceId: number, contentHash: string, externalStemRole: string) => void;
|
|
111
127
|
setClipTakes: (
|
|
112
128
|
clipId: number,
|
|
113
129
|
takes: ReadonlyArray<ProjectClipTake>,
|
|
@@ -125,16 +141,13 @@ export interface WasmProject {
|
|
|
125
141
|
removeTrack: (trackId: number) => void;
|
|
126
142
|
renameTrack: (trackId: number, name: string) => void;
|
|
127
143
|
setTrackRoute: (trackId: number, channelStripRef: string, outputTarget: string) => void;
|
|
128
|
-
addAutomationLane: (
|
|
129
|
-
trackId: number,
|
|
130
|
-
desc: { targetParamId: number; points: ReadonlyArray<ProjectAutomationPoint> },
|
|
131
|
-
) => number;
|
|
144
|
+
addAutomationLane: (trackId: number, desc: ProjectAutomationLaneDesc) => number;
|
|
132
145
|
editAutomationLane: (
|
|
133
146
|
trackId: number,
|
|
134
|
-
|
|
135
|
-
desc:
|
|
147
|
+
targetParamId: number,
|
|
148
|
+
desc: ProjectAutomationLaneDesc,
|
|
136
149
|
) => void;
|
|
137
|
-
removeAutomationLane: (trackId: number,
|
|
150
|
+
removeAutomationLane: (trackId: number, targetParamId: number) => void;
|
|
138
151
|
annotateKeys: (keys: ReadonlyArray<ProjectKeySegment>) => void;
|
|
139
152
|
annotateChords: (chords: ReadonlyArray<ProjectChordSymbol>) => void;
|
|
140
153
|
setAssistSidecar: (
|
|
@@ -154,6 +167,9 @@ export interface WasmProject {
|
|
|
154
167
|
setMarker: (markerId: number, ppq: number, name: string) => number;
|
|
155
168
|
setMarkerEx: (marker: ProjectMarker) => number;
|
|
156
169
|
markerByIndex: (index: number) => ProjectMarker;
|
|
170
|
+
trackByIndex: (index: number) => ProjectTrack;
|
|
171
|
+
clipByIndex: (index: number) => ProjectClip;
|
|
172
|
+
sourceByIndex: (index: number) => ProjectSource;
|
|
157
173
|
markerCount: () => number;
|
|
158
174
|
trackCount: () => number;
|
|
159
175
|
clipCount: () => number;
|
|
@@ -307,37 +323,25 @@ export function assertProjectMidiEvents(
|
|
|
307
323
|
}
|
|
308
324
|
|
|
309
325
|
export function projectTrackKindValue(kind: ProjectTrackKind | undefined): number {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
return kind;
|
|
326
|
+
return resolveEnumOrdinal(kind ?? 'audio', { audio: 0, midi: 1, aux: 2 }, 'project track kind');
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export function projectAutomationTargetKindValue(kind: ProjectAutomationTargetKind): number {
|
|
330
|
+
return resolveEnumOrdinal(
|
|
331
|
+
kind,
|
|
332
|
+
{ opaque: 0, 'track-fader-db': 1, 'track-pan': 2 },
|
|
333
|
+
'project automation target kind',
|
|
334
|
+
);
|
|
320
335
|
}
|
|
321
336
|
|
|
322
337
|
export function projectWarpModeValue(mode: ProjectWarpMode | undefined): number {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
if (mode === 'tempo-sync') {
|
|
330
|
-
return 2;
|
|
331
|
-
}
|
|
332
|
-
return mode;
|
|
338
|
+
return resolveEnumOrdinal(
|
|
339
|
+
mode ?? 'off',
|
|
340
|
+
{ off: 0, repitch: 1, 'tempo-sync': 2 },
|
|
341
|
+
'project warp mode',
|
|
342
|
+
);
|
|
333
343
|
}
|
|
334
344
|
|
|
335
345
|
export function projectLoopModeValue(mode: ProjectLoopMode | undefined): number {
|
|
336
|
-
|
|
337
|
-
return 0;
|
|
338
|
-
}
|
|
339
|
-
if (mode === 'loop') {
|
|
340
|
-
return 1;
|
|
341
|
-
}
|
|
342
|
-
return mode;
|
|
346
|
+
return resolveEnumOrdinal(mode ?? 'off', { off: 0, loop: 1 }, 'project loop mode');
|
|
343
347
|
}
|
package/src/project_types.ts
CHANGED
|
@@ -25,6 +25,29 @@ export interface ProjectBounceOptions {
|
|
|
25
25
|
instrumentLatencySamples?: number;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/** One decoded output from a host-owned source-separation model. */
|
|
29
|
+
export interface ExternalSeparatedStem {
|
|
30
|
+
name: string;
|
|
31
|
+
/** Optional host metadata; it does not change DSP. */
|
|
32
|
+
role?: string;
|
|
33
|
+
layout: 'mono' | 'stereo' | 1 | 2;
|
|
34
|
+
planarSamples: Float32Array[];
|
|
35
|
+
/** Absolute project-rate frame at which this stem begins. */
|
|
36
|
+
startFrame?: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Request for {@link Project.importExternalStems}. */
|
|
40
|
+
export interface ExternalSeparatedStemImportRequest {
|
|
41
|
+
sampleRate: number;
|
|
42
|
+
stems: ExternalSeparatedStem[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Ids of the normal tracks and clips created by the import. */
|
|
46
|
+
export interface ExternalSeparatedStemImportResult {
|
|
47
|
+
trackIds: number[];
|
|
48
|
+
clipIds: number[];
|
|
49
|
+
}
|
|
50
|
+
|
|
28
51
|
/**
|
|
29
52
|
* Marker kind ordinals. Mirrors `SonareMarkerKind` in `src/sonare_c_types.h`;
|
|
30
53
|
* the values are part of the ABI and must not be renumbered.
|
|
@@ -53,17 +76,51 @@ export interface ProjectMarker {
|
|
|
53
76
|
keyMinor?: boolean;
|
|
54
77
|
}
|
|
55
78
|
|
|
79
|
+
/** Read-only stored project track returned by {@link Project.trackByIndex}. */
|
|
80
|
+
export interface ProjectTrack {
|
|
81
|
+
id: number;
|
|
82
|
+
kind: number;
|
|
83
|
+
midiDestinationId: number;
|
|
84
|
+
gain: number;
|
|
85
|
+
pan: number;
|
|
86
|
+
mute: boolean;
|
|
87
|
+
solo: boolean;
|
|
88
|
+
name: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Read-only stored project clip returned by {@link Project.clipByIndex}. */
|
|
92
|
+
export interface ProjectClip {
|
|
93
|
+
id: number;
|
|
94
|
+
trackId: number;
|
|
95
|
+
sourceId: number;
|
|
96
|
+
sourceKind: number;
|
|
97
|
+
startPpq: number;
|
|
98
|
+
lengthPpq: number;
|
|
99
|
+
sourceOffsetPpq: number;
|
|
100
|
+
gain: number;
|
|
101
|
+
loopMode: number;
|
|
102
|
+
loopLengthPpq: number;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Read-only stored project source returned by {@link Project.sourceByIndex}. */
|
|
106
|
+
export interface ProjectSource {
|
|
107
|
+
id: number;
|
|
108
|
+
kind: number;
|
|
109
|
+
channelCount: number;
|
|
110
|
+
storageHandleId: number;
|
|
111
|
+
sampleRateHint: number;
|
|
112
|
+
nameOrUri: string;
|
|
113
|
+
/** Owning content hash for audio sources; empty for MIDI sources. */
|
|
114
|
+
contentHash: string;
|
|
115
|
+
/** External source-separation role for audio sources; empty for MIDI sources. */
|
|
116
|
+
externalStemRole: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Names accepted by the minimal built-in oscillator synth. */
|
|
120
|
+
export const BUILTIN_SYNTH_WAVEFORMS = ['sine', 'saw', 'sawtooth', 'square', 'triangle'] as const;
|
|
121
|
+
|
|
56
122
|
/** Oscillator waveform for the built-in synth. */
|
|
57
|
-
export type BuiltinSynthWaveform =
|
|
58
|
-
| 'sine'
|
|
59
|
-
| 'saw'
|
|
60
|
-
| 'sawtooth'
|
|
61
|
-
| 'square'
|
|
62
|
-
| 'triangle'
|
|
63
|
-
| 0
|
|
64
|
-
| 1
|
|
65
|
-
| 2
|
|
66
|
-
| 3;
|
|
123
|
+
export type BuiltinSynthWaveform = (typeof BUILTIN_SYNTH_WAVEFORMS)[number] | 0 | 1 | 2 | 3;
|
|
67
124
|
|
|
68
125
|
/**
|
|
69
126
|
* Built-in synth patch + MIDI routing for
|
|
@@ -111,6 +168,8 @@ export interface Sf2InstrumentConfig {
|
|
|
111
168
|
gain?: number;
|
|
112
169
|
/** Max simultaneous voices (0 => 48, clamped to [1, 64]). */
|
|
113
170
|
polyphony?: number;
|
|
171
|
+
/** Prefer dedicated physical models for covered melodic GM programs. Defaults to false; drums stay SF2-first. */
|
|
172
|
+
preferModelForModeledFamilies?: boolean;
|
|
114
173
|
}
|
|
115
174
|
|
|
116
175
|
/** Source backend a resolved MIDI program renders through. */
|
|
@@ -198,6 +257,7 @@ export const SYNTH_MOD_DESTINATIONS = [
|
|
|
198
257
|
export interface SynthEnumTables {
|
|
199
258
|
engineModes: string[];
|
|
200
259
|
waveforms: string[];
|
|
260
|
+
builtinWaveforms: string[];
|
|
201
261
|
filterModels: string[];
|
|
202
262
|
filterOutputs: string[];
|
|
203
263
|
bodyTypes: string[];
|
|
@@ -258,6 +318,8 @@ export interface SynthPatch {
|
|
|
258
318
|
* `(destination_id, patch)` bindings instead. Defaults to `0`.
|
|
259
319
|
*/
|
|
260
320
|
destinationId?: number;
|
|
321
|
+
/** Resolve MIDI channels from incoming GM bank/program changes; defaults to false. */
|
|
322
|
+
useGmPrograms?: boolean;
|
|
261
323
|
/** Base preset name (see {@link synthPresetNames}); omit for the init patch. */
|
|
262
324
|
preset?: string;
|
|
263
325
|
engineMode?: SynthEngineMode | number;
|
|
@@ -312,8 +374,11 @@ export type ProjectFadeCurve =
|
|
|
312
374
|
| 'equal-power'
|
|
313
375
|
| 'equal_power'
|
|
314
376
|
| 'equalPower'
|
|
377
|
+
| 'equalpower'
|
|
315
378
|
| 'exponential'
|
|
379
|
+
| 'exp'
|
|
316
380
|
| 'logarithmic'
|
|
381
|
+
| 'log'
|
|
317
382
|
| 0
|
|
318
383
|
| 1
|
|
319
384
|
| 2
|
|
@@ -389,12 +454,34 @@ export interface ProjectAutomationPoint {
|
|
|
389
454
|
curve?: ProjectAutomationCurve;
|
|
390
455
|
}
|
|
391
456
|
|
|
457
|
+
/**
|
|
458
|
+
* Persistent target classification for an automation lane.
|
|
459
|
+
*
|
|
460
|
+
* The numeric ordinals mirror `SonareAutomationTargetKind`; the string names
|
|
461
|
+
* are the public WASM spellings accepted by the project facade.
|
|
462
|
+
*/
|
|
463
|
+
export const AutomationTargetKind = {
|
|
464
|
+
opaque: 0,
|
|
465
|
+
trackFaderDb: 1,
|
|
466
|
+
trackPan: 2,
|
|
467
|
+
} as const;
|
|
468
|
+
|
|
469
|
+
/** Accepted automation target kind name or ABI ordinal. */
|
|
470
|
+
export type ProjectAutomationTargetKind = 'opaque' | 'track-fader-db' | 'track-pan' | 0 | 1 | 2;
|
|
471
|
+
|
|
472
|
+
/** Numeric aliases matching the C-ABI enum names. */
|
|
473
|
+
export const PROJECT_AUTOMATION_TARGET_OPAQUE = AutomationTargetKind.opaque;
|
|
474
|
+
export const PROJECT_AUTOMATION_TARGET_TRACK_FADER_DB = AutomationTargetKind.trackFaderDb;
|
|
475
|
+
export const PROJECT_AUTOMATION_TARGET_TRACK_PAN = AutomationTargetKind.trackPan;
|
|
476
|
+
|
|
392
477
|
/** Automation-lane descriptor for {@link Project.addAutomationLane}. */
|
|
393
478
|
export interface ProjectAutomationLaneDesc {
|
|
394
|
-
/** Host-defined id of the parameter the lane drives. */
|
|
479
|
+
/** Host-defined, non-zero id of the parameter the lane drives (zero is reserved). */
|
|
395
480
|
targetParamId: number;
|
|
396
481
|
/** Breakpoints (stored verbatim). */
|
|
397
482
|
points: ReadonlyArray<ProjectAutomationPoint>;
|
|
483
|
+
/** Optional persistent target classification; omission retains the legacy opaque route. */
|
|
484
|
+
targetKind?: ProjectAutomationTargetKind;
|
|
398
485
|
}
|
|
399
486
|
|
|
400
487
|
/** One tempo segment for {@link Project.setTempoSegments}. */
|
|
@@ -456,6 +543,22 @@ export interface ProjectChordSymbol {
|
|
|
456
543
|
modulationBoundary?: boolean;
|
|
457
544
|
}
|
|
458
545
|
|
|
546
|
+
/** Descriptor accepted by {@link Project.setAssistSidecar}. */
|
|
547
|
+
export interface ProjectAssistSidecarInput {
|
|
548
|
+
/** Non-empty module id key. */
|
|
549
|
+
moduleId: string;
|
|
550
|
+
/** Module-defined schema version. Defaults to `0`. */
|
|
551
|
+
schemaVersion?: number;
|
|
552
|
+
/** Target track id (`0` = project scope). Defaults to `0`. */
|
|
553
|
+
targetTrackId?: number;
|
|
554
|
+
/** Region start in PPQ. Defaults to `0`. */
|
|
555
|
+
regionStartPpq?: number;
|
|
556
|
+
/** Region end in PPQ. Defaults to `0`. */
|
|
557
|
+
regionEndPpq?: number;
|
|
558
|
+
/** Opaque module-owned payload bytes. Defaults to an empty payload. */
|
|
559
|
+
payload?: Uint8Array;
|
|
560
|
+
}
|
|
561
|
+
|
|
459
562
|
/** Assist sidecar snapshot returned by {@link Project.getAssistSidecar}. */
|
|
460
563
|
export interface ProjectAssistSidecar {
|
|
461
564
|
moduleId: string;
|