@libraz/libsonare 1.7.1 → 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 -170
- 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 -5837
- 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 -7329
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3816 -1359
- 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 -2142
- package/dist/worklet.d.ts.map +1 -0
- package/dist/worklet.js +2889 -466
- 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 +285 -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 +64 -24
- package/src/project_class.ts +502 -29
- package/src/project_internal.ts +151 -42
- package/src/project_synth.ts +67 -1
- package/src/project_types.ts +302 -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 +750 -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 +1125 -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 +212 -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 +85 -28
- package/src/worklet/engine-offline.ts +14 -8
- package/src/worklet/engine-parameter-facade.ts +21 -0
- package/src/worklet/engine-processor.ts +307 -71
- 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 +239 -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 +22 -0
- package/src/effects_transform.ts +0 -718
- package/src/mastering_repair.ts +0 -273
package/src/project_class.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BuiltinSynthBinding,
|
|
3
|
+
Sf2InstrumentConfig,
|
|
4
|
+
Sf2ProgramStatus,
|
|
5
|
+
SynthPatch,
|
|
6
|
+
} from './instrument_types';
|
|
1
7
|
import {
|
|
2
8
|
assertProjectMidiEvents,
|
|
9
|
+
normalizeSynthInstrument,
|
|
10
|
+
projectAutomationPointValue,
|
|
3
11
|
projectAutomationTargetKindValue,
|
|
4
12
|
projectLoopModeValue,
|
|
5
13
|
projectMidi1Event,
|
|
@@ -9,7 +17,6 @@ import {
|
|
|
9
17
|
type WasmProject,
|
|
10
18
|
} from './project_internal';
|
|
11
19
|
import type {
|
|
12
|
-
BuiltinSynthBinding,
|
|
13
20
|
ExternalSeparatedStemImportRequest,
|
|
14
21
|
ExternalSeparatedStemImportResult,
|
|
15
22
|
MidiCcLearnOptions,
|
|
@@ -35,22 +42,53 @@ import type {
|
|
|
35
42
|
ProjectMidiCcBinding,
|
|
36
43
|
ProjectMidiClipResult,
|
|
37
44
|
ProjectMidiEvent,
|
|
45
|
+
ProjectMidiFxBakeRequest,
|
|
46
|
+
ProjectMidiFxBakeResult,
|
|
47
|
+
ProjectMidiFxPreviewRequest,
|
|
38
48
|
ProjectMidiRouteConfig,
|
|
39
49
|
ProjectMidiRouteResult,
|
|
40
50
|
ProjectNotePairValidation,
|
|
41
51
|
ProjectSource,
|
|
42
52
|
ProjectTempoCandidate,
|
|
53
|
+
ProjectTempoOptions,
|
|
43
54
|
ProjectTempoSegment,
|
|
44
55
|
ProjectTimeSignatureSegment,
|
|
45
56
|
ProjectTrack,
|
|
46
57
|
ProjectTrackDesc,
|
|
47
58
|
ProjectTrackKind,
|
|
59
|
+
ProjectTranscribeRequest,
|
|
48
60
|
ProjectWarpMapDesc,
|
|
49
61
|
ProjectWarpMode,
|
|
50
|
-
Sf2InstrumentConfig,
|
|
51
|
-
Sf2ProgramStatus,
|
|
52
|
-
SynthPatch,
|
|
53
62
|
} from './project_types';
|
|
63
|
+
import {
|
|
64
|
+
assertBoundedInteger,
|
|
65
|
+
assertNibble,
|
|
66
|
+
assertSampleRate,
|
|
67
|
+
assertSamples,
|
|
68
|
+
assertU7,
|
|
69
|
+
} from './validation';
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Folds the positional and request call forms of `bakeMidiFx` into one shape,
|
|
73
|
+
* so defaults, validation and errors cannot diverge between them.
|
|
74
|
+
*/
|
|
75
|
+
function normalizeMidiFxBakeRequest(
|
|
76
|
+
clipIdOrRequest: number | ProjectMidiFxBakeRequest,
|
|
77
|
+
configJson?: string,
|
|
78
|
+
): Required<ProjectMidiFxBakeRequest> {
|
|
79
|
+
if (typeof clipIdOrRequest === 'number') {
|
|
80
|
+
return {
|
|
81
|
+
clipId: clipIdOrRequest,
|
|
82
|
+
configJson: configJson ?? '',
|
|
83
|
+
withSourceIndex: false,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
clipId: clipIdOrRequest.clipId,
|
|
88
|
+
configJson: clipIdOrRequest.configJson,
|
|
89
|
+
withSourceIndex: clipIdOrRequest.withSourceIndex ?? false,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
54
92
|
|
|
55
93
|
function validateAssistSidecarUint32(value: unknown, field: string): number {
|
|
56
94
|
if (
|
|
@@ -87,6 +125,52 @@ function validateAssistSidecarModuleId(value: unknown): string {
|
|
|
87
125
|
return value;
|
|
88
126
|
}
|
|
89
127
|
|
|
128
|
+
const MIDI2_U16_MAX = 0xffff;
|
|
129
|
+
const MIDI2_U32_MAX = 0xffffffff;
|
|
130
|
+
|
|
131
|
+
// UMP MIDI-2.0 channel-voice packet (message type 0x4). Canonical layout is
|
|
132
|
+
// sonare::midi::make_midi2_* (C-ABI sonare_midi2_*); the golden vectors in
|
|
133
|
+
// midi2-ump.test.ts lock this copy against it.
|
|
134
|
+
function midi2Event(
|
|
135
|
+
fnName: string,
|
|
136
|
+
ppq: number,
|
|
137
|
+
group: number,
|
|
138
|
+
opcode: number,
|
|
139
|
+
channel: number,
|
|
140
|
+
byte2: number,
|
|
141
|
+
byte3: number,
|
|
142
|
+
word1: number,
|
|
143
|
+
): ProjectMidiEvent {
|
|
144
|
+
if (!Number.isFinite(ppq) || ppq < 0) {
|
|
145
|
+
throw new RangeError(`${fnName}: ppq must be a non-negative finite number`);
|
|
146
|
+
}
|
|
147
|
+
const g = assertNibble(fnName, group, 'group');
|
|
148
|
+
const ch = assertNibble(fnName, channel, 'channel');
|
|
149
|
+
const word0 =
|
|
150
|
+
((0x4 << 28) | (g << 24) | (opcode << 20) | (ch << 16) | (byte2 << 8) | byte3) >>> 0;
|
|
151
|
+
return { ppq, data0: word0, data1: word1 >>> 0 };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function midi2U32(fnName: string, value: number, argName: string): number {
|
|
155
|
+
assertBoundedInteger(fnName, value, argName, 0, MIDI2_U32_MAX);
|
|
156
|
+
return value;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function midi2U16(fnName: string, value: number, argName: string): number {
|
|
160
|
+
assertBoundedInteger(fnName, value, argName, 0, MIDI2_U16_MAX);
|
|
161
|
+
return value;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function midi2I32(fnName: string, value: number, argName: string): number {
|
|
165
|
+
assertBoundedInteger(fnName, value, argName, -0x80000000, 0x7fffffff);
|
|
166
|
+
return value;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function midi2Byte(fnName: string, value: number, argName: string): number {
|
|
170
|
+
assertBoundedInteger(fnName, value, argName, 0, 0xff);
|
|
171
|
+
return value;
|
|
172
|
+
}
|
|
173
|
+
|
|
90
174
|
/**
|
|
91
175
|
* Headless DAW project (control-thread-only arrangement model).
|
|
92
176
|
*
|
|
@@ -115,6 +199,7 @@ function validateAssistSidecarModuleId(value: unknown): string {
|
|
|
115
199
|
*/
|
|
116
200
|
export class Project {
|
|
117
201
|
private native: WasmProject;
|
|
202
|
+
private released = false;
|
|
118
203
|
|
|
119
204
|
constructor() {
|
|
120
205
|
this.native = new (projectModule().Project)();
|
|
@@ -179,6 +264,233 @@ export class Project {
|
|
|
179
264
|
return projectMidi1Event('Project.midiProgram', ppq, group, 0xc, channel, program, 0);
|
|
180
265
|
}
|
|
181
266
|
|
|
267
|
+
/**
|
|
268
|
+
* Pack a MIDI 2.0 note-on event accepted by {@link setMidiEvents}.
|
|
269
|
+
* `velocity16` is the full 16-bit velocity (0 is a sounding note-on);
|
|
270
|
+
* `attributeType` 0 is none, 3 is pitch 7.9.
|
|
271
|
+
*/
|
|
272
|
+
static midi2NoteOn(
|
|
273
|
+
ppq: number,
|
|
274
|
+
group: number,
|
|
275
|
+
channel: number,
|
|
276
|
+
note: number,
|
|
277
|
+
velocity16: number,
|
|
278
|
+
attributeType = 0,
|
|
279
|
+
attributeData = 0,
|
|
280
|
+
): ProjectMidiEvent {
|
|
281
|
+
const fn = 'Project.midi2NoteOn';
|
|
282
|
+
const n = assertU7(fn, note, 'note');
|
|
283
|
+
const vel = midi2U16(fn, velocity16, 'velocity16');
|
|
284
|
+
const type = midi2Byte(fn, attributeType, 'attributeType');
|
|
285
|
+
const data = midi2U16(fn, attributeData, 'attributeData');
|
|
286
|
+
return midi2Event(fn, ppq, group, 0x9, channel, n, type, ((vel << 16) | data) >>> 0);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** Pack a MIDI 2.0 note-off event (`velocity16` is the full 16-bit release velocity). */
|
|
290
|
+
static midi2NoteOff(
|
|
291
|
+
ppq: number,
|
|
292
|
+
group: number,
|
|
293
|
+
channel: number,
|
|
294
|
+
note: number,
|
|
295
|
+
velocity16 = 0,
|
|
296
|
+
): ProjectMidiEvent {
|
|
297
|
+
const fn = 'Project.midi2NoteOff';
|
|
298
|
+
const n = assertU7(fn, note, 'note');
|
|
299
|
+
const vel = midi2U16(fn, velocity16, 'velocity16');
|
|
300
|
+
return midi2Event(fn, ppq, group, 0x8, channel, n, 0, (vel << 16) >>> 0);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/** Pack a MIDI 2.0 control-change event (`value32` is the full 32-bit value). */
|
|
304
|
+
static midi2Cc(
|
|
305
|
+
ppq: number,
|
|
306
|
+
group: number,
|
|
307
|
+
channel: number,
|
|
308
|
+
controller: number,
|
|
309
|
+
value32: number,
|
|
310
|
+
): ProjectMidiEvent {
|
|
311
|
+
const fn = 'Project.midi2Cc';
|
|
312
|
+
const c = assertU7(fn, controller, 'controller');
|
|
313
|
+
return midi2Event(fn, ppq, group, 0xb, channel, c, 0, midi2U32(fn, value32, 'value32'));
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/** Pack a MIDI 2.0 poly-pressure event (`pressure32` is the full 32-bit pressure). */
|
|
317
|
+
static midi2PolyPressure(
|
|
318
|
+
ppq: number,
|
|
319
|
+
group: number,
|
|
320
|
+
channel: number,
|
|
321
|
+
note: number,
|
|
322
|
+
pressure32: number,
|
|
323
|
+
): ProjectMidiEvent {
|
|
324
|
+
const fn = 'Project.midi2PolyPressure';
|
|
325
|
+
const n = assertU7(fn, note, 'note');
|
|
326
|
+
return midi2Event(fn, ppq, group, 0xa, channel, n, 0, midi2U32(fn, pressure32, 'pressure32'));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/** Pack a MIDI 2.0 channel-pressure event (`pressure32` is the full 32-bit pressure). */
|
|
330
|
+
static midi2ChannelPressure(
|
|
331
|
+
ppq: number,
|
|
332
|
+
group: number,
|
|
333
|
+
channel: number,
|
|
334
|
+
pressure32: number,
|
|
335
|
+
): ProjectMidiEvent {
|
|
336
|
+
const fn = 'Project.midi2ChannelPressure';
|
|
337
|
+
return midi2Event(fn, ppq, group, 0xd, channel, 0, 0, midi2U32(fn, pressure32, 'pressure32'));
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/** Pack a MIDI 2.0 pitch-bend event (`bend32` is unsigned 32-bit, center = 0x80000000). */
|
|
341
|
+
static midi2PitchBend(
|
|
342
|
+
ppq: number,
|
|
343
|
+
group: number,
|
|
344
|
+
channel: number,
|
|
345
|
+
bend32: number,
|
|
346
|
+
): ProjectMidiEvent {
|
|
347
|
+
const fn = 'Project.midi2PitchBend';
|
|
348
|
+
return midi2Event(fn, ppq, group, 0xe, channel, 0, 0, midi2U32(fn, bend32, 'bend32'));
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Pack a MIDI 2.0 program-change event. The bank travels in the same message
|
|
353
|
+
* and is applied only when `bankValid` is true.
|
|
354
|
+
*/
|
|
355
|
+
static midi2Program(
|
|
356
|
+
ppq: number,
|
|
357
|
+
group: number,
|
|
358
|
+
channel: number,
|
|
359
|
+
program: number,
|
|
360
|
+
bankValid = false,
|
|
361
|
+
bankMsb = 0,
|
|
362
|
+
bankLsb = 0,
|
|
363
|
+
): ProjectMidiEvent {
|
|
364
|
+
const fn = 'Project.midi2Program';
|
|
365
|
+
const p = assertU7(fn, program, 'program');
|
|
366
|
+
const msb = assertU7(fn, bankMsb, 'bankMsb');
|
|
367
|
+
const lsb = assertU7(fn, bankLsb, 'bankLsb');
|
|
368
|
+
const word1 = ((p << 24) | (msb << 8) | lsb) >>> 0;
|
|
369
|
+
return midi2Event(fn, ppq, group, 0xc, channel, 0, bankValid ? 1 : 0, word1);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** Pack a MIDI 2.0 registered controller (RPN) event. */
|
|
373
|
+
static midi2RegisteredController(
|
|
374
|
+
ppq: number,
|
|
375
|
+
group: number,
|
|
376
|
+
channel: number,
|
|
377
|
+
bank: number,
|
|
378
|
+
index: number,
|
|
379
|
+
value32: number,
|
|
380
|
+
): ProjectMidiEvent {
|
|
381
|
+
const fn = 'Project.midi2RegisteredController';
|
|
382
|
+
const b = assertU7(fn, bank, 'bank');
|
|
383
|
+
const i = assertU7(fn, index, 'index');
|
|
384
|
+
return midi2Event(fn, ppq, group, 0x2, channel, b, i, midi2U32(fn, value32, 'value32'));
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/** Pack a MIDI 2.0 assignable controller (NRPN) event. */
|
|
388
|
+
static midi2AssignableController(
|
|
389
|
+
ppq: number,
|
|
390
|
+
group: number,
|
|
391
|
+
channel: number,
|
|
392
|
+
bank: number,
|
|
393
|
+
index: number,
|
|
394
|
+
value32: number,
|
|
395
|
+
): ProjectMidiEvent {
|
|
396
|
+
const fn = 'Project.midi2AssignableController';
|
|
397
|
+
const b = assertU7(fn, bank, 'bank');
|
|
398
|
+
const i = assertU7(fn, index, 'index');
|
|
399
|
+
return midi2Event(fn, ppq, group, 0x3, channel, b, i, midi2U32(fn, value32, 'value32'));
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/** Pack a MIDI 2.0 relative registered controller event (`delta32` is a signed change). */
|
|
403
|
+
static midi2RelativeRegisteredController(
|
|
404
|
+
ppq: number,
|
|
405
|
+
group: number,
|
|
406
|
+
channel: number,
|
|
407
|
+
bank: number,
|
|
408
|
+
index: number,
|
|
409
|
+
delta32: number,
|
|
410
|
+
): ProjectMidiEvent {
|
|
411
|
+
const fn = 'Project.midi2RelativeRegisteredController';
|
|
412
|
+
const b = assertU7(fn, bank, 'bank');
|
|
413
|
+
const i = assertU7(fn, index, 'index');
|
|
414
|
+
return midi2Event(fn, ppq, group, 0x4, channel, b, i, midi2I32(fn, delta32, 'delta32'));
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/** Pack a MIDI 2.0 relative assignable controller event (`delta32` is a signed change). */
|
|
418
|
+
static midi2RelativeAssignableController(
|
|
419
|
+
ppq: number,
|
|
420
|
+
group: number,
|
|
421
|
+
channel: number,
|
|
422
|
+
bank: number,
|
|
423
|
+
index: number,
|
|
424
|
+
delta32: number,
|
|
425
|
+
): ProjectMidiEvent {
|
|
426
|
+
const fn = 'Project.midi2RelativeAssignableController';
|
|
427
|
+
const b = assertU7(fn, bank, 'bank');
|
|
428
|
+
const i = assertU7(fn, index, 'index');
|
|
429
|
+
return midi2Event(fn, ppq, group, 0x5, channel, b, i, midi2I32(fn, delta32, 'delta32'));
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/** Pack a MIDI 2.0 registered per-note controller event (`index` is 0..255). */
|
|
433
|
+
static midi2RegisteredPerNoteController(
|
|
434
|
+
ppq: number,
|
|
435
|
+
group: number,
|
|
436
|
+
channel: number,
|
|
437
|
+
note: number,
|
|
438
|
+
index: number,
|
|
439
|
+
value32: number,
|
|
440
|
+
): ProjectMidiEvent {
|
|
441
|
+
const fn = 'Project.midi2RegisteredPerNoteController';
|
|
442
|
+
const n = assertU7(fn, note, 'note');
|
|
443
|
+
const i = midi2Byte(fn, index, 'index');
|
|
444
|
+
return midi2Event(fn, ppq, group, 0x0, channel, n, i, midi2U32(fn, value32, 'value32'));
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/** Pack a MIDI 2.0 assignable per-note controller event (`index` is 0..255). */
|
|
448
|
+
static midi2AssignablePerNoteController(
|
|
449
|
+
ppq: number,
|
|
450
|
+
group: number,
|
|
451
|
+
channel: number,
|
|
452
|
+
note: number,
|
|
453
|
+
index: number,
|
|
454
|
+
value32: number,
|
|
455
|
+
): ProjectMidiEvent {
|
|
456
|
+
const fn = 'Project.midi2AssignablePerNoteController';
|
|
457
|
+
const n = assertU7(fn, note, 'note');
|
|
458
|
+
const i = midi2Byte(fn, index, 'index');
|
|
459
|
+
return midi2Event(fn, ppq, group, 0x1, channel, n, i, midi2U32(fn, value32, 'value32'));
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/** Pack a MIDI 2.0 per-note pitch-bend event (`bend32` is unsigned 32-bit, center = 0x80000000). */
|
|
463
|
+
static midi2PerNotePitchBend(
|
|
464
|
+
ppq: number,
|
|
465
|
+
group: number,
|
|
466
|
+
channel: number,
|
|
467
|
+
note: number,
|
|
468
|
+
bend32: number,
|
|
469
|
+
): ProjectMidiEvent {
|
|
470
|
+
const fn = 'Project.midi2PerNotePitchBend';
|
|
471
|
+
const n = assertU7(fn, note, 'note');
|
|
472
|
+
return midi2Event(fn, ppq, group, 0x6, channel, n, 0, midi2U32(fn, bend32, 'bend32'));
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Pack a MIDI 2.0 per-note management event. `detach` sets the D flag
|
|
477
|
+
* (detach per-note controllers from voices already sounding on `note`);
|
|
478
|
+
* `reset` sets the S flag (reset the note's per-note controllers).
|
|
479
|
+
*/
|
|
480
|
+
static midi2PerNoteManagement(
|
|
481
|
+
ppq: number,
|
|
482
|
+
group: number,
|
|
483
|
+
channel: number,
|
|
484
|
+
note: number,
|
|
485
|
+
detach = false,
|
|
486
|
+
reset = false,
|
|
487
|
+
): ProjectMidiEvent {
|
|
488
|
+
const fn = 'Project.midi2PerNoteManagement';
|
|
489
|
+
const n = assertU7(fn, note, 'note');
|
|
490
|
+
const flags = (detach ? 0x02 : 0) | (reset ? 0x01 : 0);
|
|
491
|
+
return midi2Event(fn, ppq, group, 0xf, channel, n, flags, 0);
|
|
492
|
+
}
|
|
493
|
+
|
|
182
494
|
/** Return the General MIDI instrument name for `program`, or `null` when out of range. */
|
|
183
495
|
static gmInstrumentName(program: number): string | null {
|
|
184
496
|
return projectModule().midiGmInstrumentName(program);
|
|
@@ -310,9 +622,7 @@ export class Project {
|
|
|
310
622
|
channel: number,
|
|
311
623
|
bend: number,
|
|
312
624
|
): ProjectMidiEvent {
|
|
313
|
-
|
|
314
|
-
throw new RangeError('Project.midiPitchBend: bend must be an integer in [0, 16383]');
|
|
315
|
-
}
|
|
625
|
+
assertBoundedInteger('Project.midiPitchBend', bend, 'bend', 0, 0x3fff);
|
|
316
626
|
return projectMidi1Event(
|
|
317
627
|
'Project.midiPitchBend',
|
|
318
628
|
ppq,
|
|
@@ -370,7 +680,11 @@ export class Project {
|
|
|
370
680
|
return this.native.toJson();
|
|
371
681
|
}
|
|
372
682
|
|
|
373
|
-
/**
|
|
683
|
+
/**
|
|
684
|
+
* Set the project sample rate in Hz. Must be in `[8000, 384000]`; anything
|
|
685
|
+
* outside that range throws. Applied through the edit history, so it is
|
|
686
|
+
* undoable.
|
|
687
|
+
*/
|
|
374
688
|
setSampleRate(sampleRate: number): void {
|
|
375
689
|
this.native.setSampleRate(sampleRate);
|
|
376
690
|
}
|
|
@@ -462,7 +776,24 @@ export class Project {
|
|
|
462
776
|
this.native.setTrackMidiDestination(trackId, destinationId);
|
|
463
777
|
}
|
|
464
778
|
|
|
465
|
-
/**
|
|
779
|
+
/**
|
|
780
|
+
* Set a track's linear playback gain (1.0 = unity; >= 0) via an undoable edit.
|
|
781
|
+
*
|
|
782
|
+
* The value reaches the track's audio and MIDI alike, but the stage it lands
|
|
783
|
+
* on follows the track's channel strip. A strip bound by this track alone
|
|
784
|
+
* (including one synthesized for an unbound track) carries the controls on its
|
|
785
|
+
* own fader and panner. A strip several tracks share processes their sum and
|
|
786
|
+
* carries none of them; each track applies its controls upstream instead — on
|
|
787
|
+
* its own clip schedules for audio, on its track lane for MIDI.
|
|
788
|
+
*
|
|
789
|
+
* A MIDI track's gain/pan on a shared strip ride the track lane, which is fed
|
|
790
|
+
* per source track only by an instrument that preserves source-track identity
|
|
791
|
+
* (see {@link setTrackMidiDestination}). An opaque host-callback instrument, or
|
|
792
|
+
* one reporting non-zero latency, renders one buffer per destination and has no
|
|
793
|
+
* per-track stage on a shared strip, so its gain/pan do not reach the bounce
|
|
794
|
+
* there; bind such an instrument to a track with an exclusive strip. Mute and
|
|
795
|
+
* solo are unaffected: a silenced MIDI track schedules no events at all.
|
|
796
|
+
*/
|
|
466
797
|
setTrackGain(trackId: number, gain: number): void {
|
|
467
798
|
this.native.setTrackGain(trackId, gain);
|
|
468
799
|
}
|
|
@@ -477,7 +808,17 @@ export class Project {
|
|
|
477
808
|
this.native.setTrackSolo(trackId, solo);
|
|
478
809
|
}
|
|
479
810
|
|
|
480
|
-
/**
|
|
811
|
+
/**
|
|
812
|
+
* Set a track's stereo balance in [-1, +1] (0 = center) via an undoable edit.
|
|
813
|
+
*
|
|
814
|
+
* See {@link setTrackGain} for which stage a track's controls land on. The pan
|
|
815
|
+
* law that shapes the balance belongs to that stage: the strip's configured law
|
|
816
|
+
* on a channel strip and on the clips of an audio track sharing a strip, and
|
|
817
|
+
* the track lane's law for a MIDI track sharing a strip (the law of whatever
|
|
818
|
+
* strip the host bound to that lane, or a linear balance when none is bound).
|
|
819
|
+
* Every law is normalized so a centered track stays at unity and only the away
|
|
820
|
+
* channel is attenuated, so the difference is a taper, not a level offset.
|
|
821
|
+
*/
|
|
481
822
|
setTrackPan(trackId: number, pan: number): void {
|
|
482
823
|
this.native.setTrackPan(trackId, pan);
|
|
483
824
|
}
|
|
@@ -518,7 +859,18 @@ export class Project {
|
|
|
518
859
|
this.native.setMaxHistoryBytes(bytes);
|
|
519
860
|
}
|
|
520
861
|
|
|
521
|
-
/**
|
|
862
|
+
/**
|
|
863
|
+
* Replace a MIDI clip's entire event list.
|
|
864
|
+
*
|
|
865
|
+
* @remarks
|
|
866
|
+
* Drops the clip's SysEx, which {@link importSmf} and {@link exportSmf} both
|
|
867
|
+
* keep. A clip's SysEx payloads sit beside the event list and are reached by
|
|
868
|
+
* a handle {@link ProjectMidiEvent} does not carry, so replacing the list
|
|
869
|
+
* leaves nothing referring to them: a GS setup block that survives an import
|
|
870
|
+
* and an export byte for byte is gone after one call here. Nothing reads the
|
|
871
|
+
* handles back either, so a caller that must keep the setup edits the
|
|
872
|
+
* exported file rather than the event list.
|
|
873
|
+
*/
|
|
522
874
|
setMidiEvents(
|
|
523
875
|
clipId: number,
|
|
524
876
|
events: ReadonlyArray<ProjectMidiEvent | readonly [number, number, number]>,
|
|
@@ -536,8 +888,15 @@ export class Project {
|
|
|
536
888
|
return this.native.importSmf(data);
|
|
537
889
|
}
|
|
538
890
|
|
|
539
|
-
/**
|
|
540
|
-
|
|
891
|
+
/**
|
|
892
|
+
* Export the project's tempo map + MIDI clips to an SMF byte buffer.
|
|
893
|
+
*
|
|
894
|
+
* @remarks
|
|
895
|
+
* The buffer owns a plain `ArrayBuffer`, which is what the `Blob` / `File`
|
|
896
|
+
* constructors accept — so `new Blob([project.exportSmf()])` compiles without
|
|
897
|
+
* a copy through `new Uint8Array(...)` first.
|
|
898
|
+
*/
|
|
899
|
+
exportSmf(): Uint8Array<ArrayBuffer> {
|
|
541
900
|
return this.native.exportSmf();
|
|
542
901
|
}
|
|
543
902
|
|
|
@@ -555,8 +914,12 @@ export class Project {
|
|
|
555
914
|
* Export the project's tempo map + MIDI clips to a MIDI 2.0 Clip File
|
|
556
915
|
* (`SMF2CLIP`) byte buffer. MIDI 2.0-only events are written without loss —
|
|
557
916
|
* prefer this over {@link exportSmf} when MIDI 2.0 fidelity matters.
|
|
917
|
+
*
|
|
918
|
+
* @remarks
|
|
919
|
+
* As with {@link exportSmf}, the buffer owns a plain `ArrayBuffer` and goes
|
|
920
|
+
* straight into a `Blob`.
|
|
558
921
|
*/
|
|
559
|
-
exportClipFile(): Uint8Array {
|
|
922
|
+
exportClipFile(): Uint8Array<ArrayBuffer> {
|
|
560
923
|
return this.native.exportClipFile();
|
|
561
924
|
}
|
|
562
925
|
|
|
@@ -584,8 +947,33 @@ export class Project {
|
|
|
584
947
|
* Destructively bake a MIDI-FX chain into all stored events. Large clips are
|
|
585
948
|
* drained without truncation; failure leaves the original clip unchanged.
|
|
586
949
|
*/
|
|
587
|
-
bakeMidiFx(clipId: number, configJson: string): void
|
|
588
|
-
|
|
950
|
+
bakeMidiFx(clipId: number, configJson: string): void;
|
|
951
|
+
/**
|
|
952
|
+
* Request form. Setting `withSourceIndex` also returns per-event provenance,
|
|
953
|
+
* so a selection or an editorial annotation can be carried across the bake.
|
|
954
|
+
*/
|
|
955
|
+
bakeMidiFx(request: ProjectMidiFxBakeRequest): ProjectMidiFxBakeResult;
|
|
956
|
+
bakeMidiFx(
|
|
957
|
+
clipIdOrRequest: number | ProjectMidiFxBakeRequest,
|
|
958
|
+
configJson?: string,
|
|
959
|
+
): ProjectMidiFxBakeResult {
|
|
960
|
+
const request = normalizeMidiFxBakeRequest(clipIdOrRequest, configJson);
|
|
961
|
+
if (!request.withSourceIndex) {
|
|
962
|
+
this.native.bakeMidiFx(request.clipId, request.configJson);
|
|
963
|
+
return {};
|
|
964
|
+
}
|
|
965
|
+
return {
|
|
966
|
+
sourceIndex: this.native.bakeMidiFxWithSourceIndex(request.clipId, request.configJson),
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/**
|
|
971
|
+
* Count the events {@link bakeMidiFx} would produce for this clip and
|
|
972
|
+
* configuration, without mutating the project. The transform is
|
|
973
|
+
* deterministic, so the count matches what the bake goes on to produce.
|
|
974
|
+
*/
|
|
975
|
+
previewMidiFxCount(request: ProjectMidiFxPreviewRequest): number {
|
|
976
|
+
return this.native.previewMidiFxCount(request.clipId, request.configJson);
|
|
589
977
|
}
|
|
590
978
|
|
|
591
979
|
/** Backward alias for {@link bakeMidiFx}. */
|
|
@@ -603,19 +991,62 @@ export class Project {
|
|
|
603
991
|
return this.native.validateMidiNotes(clipId);
|
|
604
992
|
}
|
|
605
993
|
|
|
994
|
+
/**
|
|
995
|
+
* Transcribe mono audio straight into a MIDI clip's event list, **replacing**
|
|
996
|
+
* whatever it held — exactly as {@link setMidiEvents} does.
|
|
997
|
+
*
|
|
998
|
+
* The PPQ grid is this project's own tempo map, which is why there is no
|
|
999
|
+
* `tempoBpm` field: a project whose tempo was installed by {@link autoTempo}
|
|
1000
|
+
* transcribes onto that map rather than onto a second, separately detected
|
|
1001
|
+
* tempo. Use the standalone `transcribe` when you want events without a
|
|
1002
|
+
* project.
|
|
1003
|
+
*
|
|
1004
|
+
* Quantizing, tempo detection and key/chord annotation are not done here —
|
|
1005
|
+
* see `transcribe` for what each belongs to.
|
|
1006
|
+
*
|
|
1007
|
+
* @returns the number of notes written (half the events)
|
|
1008
|
+
* @throws {RangeError} on empty `samples`, a non-finite sample, or a
|
|
1009
|
+
* `sampleRate` outside `[8000, 384000]`
|
|
1010
|
+
* @throws {SonareError} `InvalidParameter` when `clipId` is unknown or not a
|
|
1011
|
+
* MIDI clip, or on an option outside its domain; `NotSupported` when the
|
|
1012
|
+
* library was built without the pitch editor
|
|
1013
|
+
*/
|
|
1014
|
+
transcribeToClip(request: ProjectTranscribeRequest): number {
|
|
1015
|
+
assertSamples('Project.transcribeToClip', request.samples, true);
|
|
1016
|
+
assertSampleRate('Project.transcribeToClip', request.sampleRate);
|
|
1017
|
+
return this.native.transcribeToClip(
|
|
1018
|
+
request.clipId,
|
|
1019
|
+
request.samples,
|
|
1020
|
+
request.sampleRate,
|
|
1021
|
+
request,
|
|
1022
|
+
);
|
|
1023
|
+
}
|
|
1024
|
+
|
|
606
1025
|
/** Return ranked tempo-octave and detected-meter candidates without editing. */
|
|
607
|
-
analyzeTempo(
|
|
608
|
-
|
|
1026
|
+
analyzeTempo(
|
|
1027
|
+
audio: Float32Array,
|
|
1028
|
+
sampleRate: number,
|
|
1029
|
+
options?: ProjectTempoOptions,
|
|
1030
|
+
): ProjectTempoCandidate[] {
|
|
1031
|
+
return this.native.analyzeTempo(audio, sampleRate, options);
|
|
609
1032
|
}
|
|
610
1033
|
|
|
611
|
-
/**
|
|
1034
|
+
/**
|
|
1035
|
+
* Detect and install a ranked tempo candidate; optionally apply detected meter.
|
|
1036
|
+
*
|
|
1037
|
+
* @remarks
|
|
1038
|
+
* `candidateIndex` indexes the ranking {@link analyzeTempo} produced, so pair
|
|
1039
|
+
* the two on the same `options`. Read the installed map back with
|
|
1040
|
+
* {@link tempoSegmentCount} and {@link tempoSegmentByIndex}.
|
|
1041
|
+
*/
|
|
612
1042
|
autoTempo(
|
|
613
1043
|
audio: Float32Array,
|
|
614
1044
|
sampleRate: number,
|
|
615
1045
|
candidateIndex = 0,
|
|
616
1046
|
applyTimeSignatures = false,
|
|
1047
|
+
options?: ProjectTempoOptions,
|
|
617
1048
|
): number {
|
|
618
|
-
return this.native.autoTempo(audio, sampleRate, candidateIndex, applyTimeSignatures);
|
|
1049
|
+
return this.native.autoTempo(audio, sampleRate, candidateIndex, applyTimeSignatures, options);
|
|
619
1050
|
}
|
|
620
1051
|
|
|
621
1052
|
/** Snap to a bar (`division=0`), beat (`1`), or beat subdivision (`2+`). */
|
|
@@ -677,9 +1108,9 @@ export class Project {
|
|
|
677
1108
|
|
|
678
1109
|
/**
|
|
679
1110
|
* Compile + render the project offline, routing MIDI tracks through the
|
|
680
|
-
* patch-driven NativeSynth — the full synthesizer (
|
|
681
|
-
*
|
|
682
|
-
*
|
|
1111
|
+
* patch-driven NativeSynth — the full synthesizer (every
|
|
1112
|
+
* {@link SynthEngineMode} engine plus the realism layer; the modes are
|
|
1113
|
+
* enumerated by {@link SYNTH_ENGINE_MODES}). Pass a {@link SynthPatch}, a preset-name
|
|
683
1114
|
* string (`'saw-lead'` / `'va:saw-lead'`; see {@link synthPresetNames}), or
|
|
684
1115
|
* an array of either; each object entry may carry `destinationId` (default
|
|
685
1116
|
* 0) and `useGmPrograms` (default `false`) binding conveniences, neither of
|
|
@@ -690,12 +1121,19 @@ export class Project {
|
|
|
690
1121
|
* both create one default binding. Use an explicitly empty array `[]` (or
|
|
691
1122
|
* runtime `null`) for zero bindings. Unknown preset names throw.
|
|
692
1123
|
* Deterministic for a fixed project + options + patch.
|
|
1124
|
+
*
|
|
1125
|
+
* An `engineMode: 'sample'` patch reads its PCM from the {@link SampleBank}
|
|
1126
|
+
* passed as `sampleBank`; the bank must still be alive when the bounce runs,
|
|
1127
|
+
* and one bound without a bank renders silence.
|
|
693
1128
|
*/
|
|
694
1129
|
bounceWithSynthInstrument(
|
|
695
1130
|
instrument: SynthPatch | string | ReadonlyArray<SynthPatch | string> = {},
|
|
696
1131
|
options: ProjectBounceOptions = {},
|
|
697
1132
|
): Float32Array {
|
|
698
|
-
|
|
1133
|
+
const normalized = Array.isArray(instrument)
|
|
1134
|
+
? instrument.map((entry) => normalizeSynthInstrument(entry))
|
|
1135
|
+
: normalizeSynthInstrument(instrument);
|
|
1136
|
+
return this.native.bounceWithSynthInstrument(normalized, options);
|
|
699
1137
|
}
|
|
700
1138
|
|
|
701
1139
|
/**
|
|
@@ -845,7 +1283,10 @@ export class Project {
|
|
|
845
1283
|
if (desc.targetParamId === 0) {
|
|
846
1284
|
throw new RangeError('project automation lane targetParamId must be non-zero');
|
|
847
1285
|
}
|
|
848
|
-
const nativeDesc: ProjectAutomationLaneDesc = {
|
|
1286
|
+
const nativeDesc: ProjectAutomationLaneDesc = {
|
|
1287
|
+
...desc,
|
|
1288
|
+
points: desc.points.map(projectAutomationPointValue),
|
|
1289
|
+
};
|
|
849
1290
|
if (Object.keys(desc).includes('targetKind')) {
|
|
850
1291
|
nativeDesc.targetKind = projectAutomationTargetKindValue(
|
|
851
1292
|
desc.targetKind as ProjectAutomationTargetKind,
|
|
@@ -863,7 +1304,10 @@ export class Project {
|
|
|
863
1304
|
if (desc.targetParamId === 0) {
|
|
864
1305
|
throw new RangeError('project automation lane targetParamId must be non-zero');
|
|
865
1306
|
}
|
|
866
|
-
const nativeDesc: ProjectAutomationLaneDesc = {
|
|
1307
|
+
const nativeDesc: ProjectAutomationLaneDesc = {
|
|
1308
|
+
...desc,
|
|
1309
|
+
points: desc.points.map(projectAutomationPointValue),
|
|
1310
|
+
};
|
|
867
1311
|
if (Object.keys(desc).includes('targetKind')) {
|
|
868
1312
|
nativeDesc.targetKind = projectAutomationTargetKindValue(
|
|
869
1313
|
desc.targetKind as ProjectAutomationTargetKind,
|
|
@@ -1047,6 +1491,28 @@ export class Project {
|
|
|
1047
1491
|
return this.native.tempoSegmentCount();
|
|
1048
1492
|
}
|
|
1049
1493
|
|
|
1494
|
+
/**
|
|
1495
|
+
* Reads a tempo segment by index, in stored order.
|
|
1496
|
+
*
|
|
1497
|
+
* @param index - Zero-based index below {@link tempoSegmentCount}
|
|
1498
|
+
* @returns The segment, in the shape {@link setTempoSegments} accepts
|
|
1499
|
+
* @throws When the index is at or past the count
|
|
1500
|
+
*/
|
|
1501
|
+
tempoSegmentByIndex(index: number): ProjectTempoSegment {
|
|
1502
|
+
return this.native.tempoSegmentByIndex(index);
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
/**
|
|
1506
|
+
* Reads a time-signature segment by index, in stored order.
|
|
1507
|
+
*
|
|
1508
|
+
* @param index - Zero-based index below {@link timeSignatureCount}
|
|
1509
|
+
* @returns The segment, in the shape {@link setTimeSignatures} accepts
|
|
1510
|
+
* @throws When the index is at or past the count
|
|
1511
|
+
*/
|
|
1512
|
+
timeSignatureByIndex(index: number): ProjectTimeSignatureSegment {
|
|
1513
|
+
return this.native.timeSignatureByIndex(index);
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1050
1516
|
/** Number of time-signature segments on the project. */
|
|
1051
1517
|
timeSignatureCount(): number {
|
|
1052
1518
|
return this.native.timeSignatureCount();
|
|
@@ -1064,15 +1530,22 @@ export class Project {
|
|
|
1064
1530
|
|
|
1065
1531
|
/**
|
|
1066
1532
|
* Compile diagnostics produced by the most recent bounce on this project
|
|
1067
|
-
* (e.g. MIDI clips rendering silently without a bound instrument).
|
|
1068
|
-
* bounce has run, the result is empty
|
|
1533
|
+
* (e.g. MIDI clips rendering silently without a bound instrument). On a
|
|
1534
|
+
* project no bounce has ever run on, the result is empty in full:
|
|
1535
|
+
* `hasTimeline` is `false` and `diagnostics` is empty. A failed bounce is
|
|
1536
|
+
* distinguishable from that state, because a bounce only loses its timeline
|
|
1537
|
+
* through an error diagnostic and so always reports at least one.
|
|
1069
1538
|
*/
|
|
1070
1539
|
lastBounceCompileResult(): ProjectCompileResult {
|
|
1071
1540
|
return this.native.lastBounceCompileResult();
|
|
1072
1541
|
}
|
|
1073
1542
|
|
|
1074
|
-
/** Release the underlying WASM object.
|
|
1543
|
+
/** Release the underlying WASM object. Idempotent, as the Node facade is. */
|
|
1075
1544
|
delete(): void {
|
|
1545
|
+
if (this.released) {
|
|
1546
|
+
return;
|
|
1547
|
+
}
|
|
1548
|
+
this.released = true;
|
|
1076
1549
|
this.native.delete();
|
|
1077
1550
|
}
|
|
1078
1551
|
|