@opendaw/studio-core 0.0.101 → 0.0.102
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/dist/AssetService.js +2 -2
- package/dist/EffectFactories.d.ts +2 -0
- package/dist/EffectFactories.d.ts.map +1 -1
- package/dist/EffectFactories.js +5 -0
- package/dist/Engine.d.ts +3 -0
- package/dist/Engine.d.ts.map +1 -1
- package/dist/EngineFacade.d.ts +3 -0
- package/dist/EngineFacade.d.ts.map +1 -1
- package/dist/EngineFacade.js +20 -2
- package/dist/EngineWorklet.d.ts +3 -0
- package/dist/EngineWorklet.d.ts.map +1 -1
- package/dist/EngineWorklet.js +97 -9
- package/dist/OfflineEngineRenderer.d.ts.map +1 -1
- package/dist/OfflineEngineRenderer.js +1 -0
- package/dist/StudioPreferences.d.ts +1 -0
- package/dist/StudioPreferences.d.ts.map +1 -1
- package/dist/StudioSettings.d.ts +1 -0
- package/dist/StudioSettings.d.ts.map +1 -1
- package/dist/StudioSettings.js +4 -2
- package/dist/capture/CaptureAudio.d.ts +3 -1
- package/dist/capture/CaptureAudio.d.ts.map +1 -1
- package/dist/capture/CaptureAudio.js +43 -18
- package/dist/capture/MonitoringMode.d.ts +2 -0
- package/dist/capture/MonitoringMode.d.ts.map +1 -0
- package/dist/capture/MonitoringMode.js +1 -0
- package/dist/capture/index.d.ts +1 -0
- package/dist/capture/index.d.ts.map +1 -1
- package/dist/capture/index.js +1 -0
- package/dist/dawproject/DawProjectImporter.d.ts.map +1 -1
- package/dist/dawproject/DawProjectImporter.js +4 -0
- package/dist/processors.js +9 -9
- package/dist/processors.js.map +4 -4
- package/dist/project/Project.d.ts +1 -0
- package/dist/project/Project.d.ts.map +1 -1
- package/dist/project/Project.js +25 -7
- package/dist/project/ProjectApi.d.ts +1 -1
- package/dist/project/ProjectApi.d.ts.map +1 -1
- package/dist/project/ProjectApi.js +5 -2
- package/dist/project/ProjectMigration.d.ts.map +1 -1
- package/dist/project/ProjectMigration.js +3 -2
- package/dist/project/migration/MigrateNeuralAmpDeviceBox.d.ts +4 -0
- package/dist/project/migration/MigrateNeuralAmpDeviceBox.d.ts.map +1 -0
- package/dist/project/migration/MigrateNeuralAmpDeviceBox.js +29 -0
- package/dist/project/migration/index.d.ts +1 -0
- package/dist/project/migration/index.d.ts.map +1 -1
- package/dist/project/migration/index.js +1 -0
- package/dist/ui/clipboard/ClipboardManager.d.ts.map +1 -1
- package/dist/ui/clipboard/ClipboardManager.js +20 -6
- package/dist/ui/clipboard/ClipboardUtils.js +3 -3
- package/dist/ui/clipboard/types/DevicesClipboardHandler.js +1 -1
- package/dist/workers-main.js +1 -1
- package/dist/workers-main.js.map +3 -3
- package/package.json +15 -15
package/dist/AssetService.js
CHANGED
|
@@ -32,7 +32,7 @@ export class AssetService {
|
|
|
32
32
|
}
|
|
33
33
|
const { error, status, value: files } = await Promises.tryCatch(Files.open({ ...this.filePickerOptions, multiple: false }));
|
|
34
34
|
if (status === "rejected") {
|
|
35
|
-
if (Errors.isAbort(error)) {
|
|
35
|
+
if (Errors.isAbort(error) || Errors.isNotAllowed(error)) {
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
38
|
else {
|
|
@@ -54,7 +54,7 @@ export class AssetService {
|
|
|
54
54
|
async browseFiles(multiple, filePickerSettings) {
|
|
55
55
|
const { error, status, value: files } = await Promises.tryCatch(Files.open({ ...filePickerSettings, multiple }));
|
|
56
56
|
if (status === "rejected") {
|
|
57
|
-
if (Errors.isAbort(error)) {
|
|
57
|
+
if (Errors.isAbort(error) || Errors.isNotAllowed(error)) {
|
|
58
58
|
return [];
|
|
59
59
|
}
|
|
60
60
|
else {
|
|
@@ -34,6 +34,7 @@ export declare namespace EffectFactories {
|
|
|
34
34
|
Crusher: EffectFactory;
|
|
35
35
|
Fold: EffectFactory;
|
|
36
36
|
Tidal: EffectFactory;
|
|
37
|
+
NeuralAmp: EffectFactory;
|
|
37
38
|
Maximizer: EffectFactory;
|
|
38
39
|
};
|
|
39
40
|
const MidiList: ReadonlyArray<Readonly<EffectFactory>>;
|
|
@@ -49,6 +50,7 @@ export declare namespace EffectFactories {
|
|
|
49
50
|
Crusher: EffectFactory;
|
|
50
51
|
Fold: EffectFactory;
|
|
51
52
|
Tidal: EffectFactory;
|
|
53
|
+
NeuralAmp: EffectFactory;
|
|
52
54
|
Maximizer: EffectFactory;
|
|
53
55
|
Arpeggio: EffectFactory;
|
|
54
56
|
Pitch: EffectFactory;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EffectFactories.d.ts","sourceRoot":"","sources":["../src/EffectFactories.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAG7C,yBAAiB,eAAe,CAAC;IACtB,MAAM,QAAQ,EAAE,aAatB,CAAA;IAEM,MAAM,KAAK,EAAE,aAanB,CAAA;IAEM,MAAM,QAAQ,EAAE,aAatB,CAAA;IAEM,MAAM,SAAS,EAAE,aA8BvB,CAAA;IAEM,MAAM,UAAU,EAAE,aAcxB,CAAA;IAEM,MAAM,KAAK,EAAE,aAcnB,CAAA;IAEM,MAAM,cAAc,EAAE,aAc5B,CAAA;IAEM,MAAM,SAAS,EAAE,aAavB,CAAA;IAEM,MAAM,UAAU,EAAE,aAcxB,CAAA;IAEM,MAAM,IAAI,EAAE,aAalB,CAAA;IAEM,MAAM,MAAM,EAAE,aAcpB,CAAA;IAEM,MAAM,OAAO,EAAE,aAarB,CAAA;IAEM,MAAM,IAAI,EAAE,aAalB,CAAA;IAEM,MAAM,KAAK,EAAE,aAcnB,CAAA;IAEM,MAAM,MAAM,EAAE,aAapB,CAAA;IAEM,MAAM,SAAS,EAAE,aAavB,CAAA;IAEM,MAAM,OAAO,EAAE,aAqDrB,CAAA;IAEM,MAAM,SAAS;;;;;KAKrB,CAAA;
|
|
1
|
+
{"version":3,"file":"EffectFactories.d.ts","sourceRoot":"","sources":["../src/EffectFactories.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAG7C,yBAAiB,eAAe,CAAC;IACtB,MAAM,QAAQ,EAAE,aAatB,CAAA;IAEM,MAAM,KAAK,EAAE,aAanB,CAAA;IAEM,MAAM,QAAQ,EAAE,aAatB,CAAA;IAEM,MAAM,SAAS,EAAE,aA8BvB,CAAA;IAEM,MAAM,UAAU,EAAE,aAcxB,CAAA;IAEM,MAAM,KAAK,EAAE,aAcnB,CAAA;IAEM,MAAM,cAAc,EAAE,aAc5B,CAAA;IAEM,MAAM,SAAS,EAAE,aAavB,CAAA;IAEM,MAAM,UAAU,EAAE,aAcxB,CAAA;IAEM,MAAM,IAAI,EAAE,aAalB,CAAA;IAEM,MAAM,MAAM,EAAE,aAcpB,CAAA;IAEM,MAAM,OAAO,EAAE,aAarB,CAAA;IAEM,MAAM,IAAI,EAAE,aAalB,CAAA;IAEM,MAAM,KAAK,EAAE,aAcnB,CAAA;IAEM,MAAM,MAAM,EAAE,aAapB,CAAA;IAEM,MAAM,SAAS,EAAE,aAavB,CAAA;IAEM,MAAM,OAAO,EAAE,aAqDrB,CAAA;IAEM,MAAM,SAAS;;;;;KAKrB,CAAA;IAIM,MAAM,UAAU;;;;;;;;;;;;;KAatB,CAAA;IAIM,MAAM,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC,aAAa,CAAC,CAChC,CAAA;IACrB,MAAM,SAAS,EAAE,aAAa,CAAC,QAAQ,CAAC,aAAa,CAAC,CAChC,CAAA;IACtB,MAAM,WAAW;;;;;;;;;;;;;;;;;KAAgC,CAAA;IACxD,KAAY,cAAc,GAAG,MAAM,OAAO,SAAS,CAAA;IACnD,KAAY,eAAe,GAAG,MAAM,OAAO,UAAU,CAAA;CACxD"}
|
package/dist/EffectFactories.js
CHANGED
|
@@ -270,6 +270,7 @@ export var EffectFactories;
|
|
|
270
270
|
Velocity: EffectFactories.Velocity,
|
|
271
271
|
Zeitgeist: EffectFactories.Zeitgeist
|
|
272
272
|
};
|
|
273
|
+
const includeNeuralAmp = false;
|
|
273
274
|
EffectFactories.AudioNamed = {
|
|
274
275
|
StereoTool: EffectFactories.StereoTool,
|
|
275
276
|
Compressor: EffectFactories.Compressor,
|
|
@@ -281,8 +282,12 @@ export var EffectFactories;
|
|
|
281
282
|
Crusher: EffectFactories.Crusher,
|
|
282
283
|
Fold: EffectFactories.Fold,
|
|
283
284
|
Tidal: EffectFactories.Tidal,
|
|
285
|
+
NeuralAmp: EffectFactories.NeuralAmp,
|
|
284
286
|
Maximizer: EffectFactories.Maximizer
|
|
285
287
|
};
|
|
288
|
+
if (!includeNeuralAmp) {
|
|
289
|
+
delete EffectFactories.AudioNamed.NeuralAmp;
|
|
290
|
+
}
|
|
286
291
|
EffectFactories.MidiList = Object.values(EffectFactories.MidiNamed);
|
|
287
292
|
EffectFactories.AudioList = Object.values(EffectFactories.AudioNamed);
|
|
288
293
|
EffectFactories.MergedNamed = { ...EffectFactories.MidiNamed, ...EffectFactories.AudioNamed };
|
package/dist/Engine.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export interface Engine extends Terminable {
|
|
|
21
21
|
scheduleClipPlay(clipIds: ReadonlyArray<UUID.Bytes>): void;
|
|
22
22
|
scheduleClipStop(trackIds: ReadonlyArray<UUID.Bytes>): void;
|
|
23
23
|
subscribeClipNotification(observer: Observer<ClipNotification>): Subscription;
|
|
24
|
+
registerMonitoringSource(uuid: UUID.Bytes, node: AudioNode, numChannels: 1 | 2): void;
|
|
25
|
+
unregisterMonitoringSource(uuid: UUID.Bytes): void;
|
|
24
26
|
get position(): ObservableValue<ppqn>;
|
|
25
27
|
get bpm(): ObservableValue<bpm>;
|
|
26
28
|
get isPlaying(): ObservableValue<boolean>;
|
|
@@ -29,6 +31,7 @@ export interface Engine extends Terminable {
|
|
|
29
31
|
get playbackTimestamp(): ObservableValue<ppqn>;
|
|
30
32
|
get countInBeatsRemaining(): ObservableValue<number>;
|
|
31
33
|
get markerState(): ObservableValue<Nullable<[UUID.Bytes, int]>>;
|
|
34
|
+
get cpuLoad(): ObservableValue<number>;
|
|
32
35
|
get project(): Project;
|
|
33
36
|
get preferences(): EnginePreferences;
|
|
34
37
|
get perfBuffer(): Float32Array;
|
package/dist/Engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../src/Engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACzG,OAAO,EAAC,SAAS,EAAE,GAAG,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAC,gBAAgB,EAAE,iBAAiB,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACxF,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAEjC,MAAM,WAAW,MAAO,SAAQ,UAAU;IACtC,IAAI,IAAI,IAAI,CAAA;IACZ,IAAI,IAAI,IAAI,CAAA;IACZ,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAA;IACjC,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IAC7C,aAAa,IAAI,IAAI,CAAA;IACrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACxC,IAAI,IAAI,IAAI,CAAA;IACZ,KAAK,IAAI,IAAI,CAAA;IACb,KAAK,IAAI,IAAI,CAAA;IACb,IAAI,IAAI,IAAI,CAAA;IACZ,cAAc,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAAA;IACnD,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;IACpC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY,CAAA;IAC5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IACxC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IAC1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IAC3D,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../src/Engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACzG,OAAO,EAAC,SAAS,EAAE,GAAG,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAC,gBAAgB,EAAE,iBAAiB,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACxF,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAEjC,MAAM,WAAW,MAAO,SAAQ,UAAU;IACtC,IAAI,IAAI,IAAI,CAAA;IACZ,IAAI,IAAI,IAAI,CAAA;IACZ,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAA;IACjC,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IAC7C,aAAa,IAAI,IAAI,CAAA;IACrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACxC,IAAI,IAAI,IAAI,CAAA;IACZ,KAAK,IAAI,IAAI,CAAA;IACb,KAAK,IAAI,IAAI,CAAA;IACb,IAAI,IAAI,IAAI,CAAA;IACZ,cAAc,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAAA;IACnD,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;IACpC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY,CAAA;IAC5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IACxC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IAC1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IAC3D,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY,CAAA;IAC7E,wBAAwB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;IACrF,0BAA0B,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IAElD,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAA;IACrC,IAAI,GAAG,IAAI,eAAe,CAAC,GAAG,CAAC,CAAA;IAC/B,IAAI,SAAS,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IACzC,IAAI,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IAC3C,IAAI,YAAY,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IAC5C,IAAI,iBAAiB,IAAI,eAAe,CAAC,IAAI,CAAC,CAAA;IAC9C,IAAI,qBAAqB,IAAI,eAAe,CAAC,MAAM,CAAC,CAAA;IACpD,IAAI,WAAW,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;IAC/D,IAAI,OAAO,IAAI,eAAe,CAAC,MAAM,CAAC,CAAA;IACtC,IAAI,OAAO,IAAI,OAAO,CAAA;IACtB,IAAI,WAAW,IAAI,iBAAiB,CAAA;IACpC,IAAI,UAAU,IAAI,YAAY,CAAA;IAC9B,IAAI,SAAS,IAAI,MAAM,CAAA;CAC1B"}
|
package/dist/EngineFacade.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export declare class EngineFacade implements Engine {
|
|
|
23
23
|
get playbackTimestamp(): ObservableValue<ppqn>;
|
|
24
24
|
get countInBeatsRemaining(): ObservableValue<int>;
|
|
25
25
|
get markerState(): DefaultObservableValue<Nullable<[UUID.Bytes, int]>>;
|
|
26
|
+
get cpuLoad(): ObservableValue<number>;
|
|
26
27
|
get project(): Project;
|
|
27
28
|
get sampleRate(): number;
|
|
28
29
|
get preferences(): EnginePreferences;
|
|
@@ -40,6 +41,8 @@ export declare class EngineFacade implements Engine {
|
|
|
40
41
|
noteSignal(signal: NoteSignal): void;
|
|
41
42
|
scheduleClipPlay(clipIds: ReadonlyArray<UUID.Bytes>): void;
|
|
42
43
|
scheduleClipStop(trackIds: ReadonlyArray<UUID.Bytes>): void;
|
|
44
|
+
registerMonitoringSource(uuid: UUID.Bytes, node: AudioNode, numChannels: 1 | 2): void;
|
|
45
|
+
unregisterMonitoringSource(uuid: UUID.Bytes): void;
|
|
43
46
|
terminate(): void;
|
|
44
47
|
}
|
|
45
48
|
//# sourceMappingURL=EngineFacade.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EngineFacade.d.ts","sourceRoot":"","sources":["../src/EngineFacade.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,sBAAsB,EACtB,GAAG,EACH,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAEZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,SAAS,EAAE,GAAG,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrD,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EAGjB,UAAU,EAEb,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAGjC,qBAAa,YAAa,YAAW,MAAM;;;
|
|
1
|
+
{"version":3,"file":"EngineFacade.d.ts","sourceRoot":"","sources":["../src/EngineFacade.ts"],"names":[],"mappings":"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"}
|
package/dist/EngineFacade.js
CHANGED
|
@@ -12,6 +12,7 @@ export class EngineFacade {
|
|
|
12
12
|
#isRecording = new DefaultObservableValue(false);
|
|
13
13
|
#isCountingIn = new DefaultObservableValue(false);
|
|
14
14
|
#markerState = new DefaultObservableValue(null);
|
|
15
|
+
#cpuLoad = new DefaultObservableValue(0);
|
|
15
16
|
#preferencesFacade;
|
|
16
17
|
#worklet = Option.None;
|
|
17
18
|
constructor() {
|
|
@@ -21,7 +22,7 @@ export class EngineFacade {
|
|
|
21
22
|
this.#worklet = Option.wrap(worklet);
|
|
22
23
|
this.#preferencesFacade.setHost(worklet.preferences);
|
|
23
24
|
this.#lifecycle.terminate();
|
|
24
|
-
this.#lifecycle.ownAll(worklet.playbackTimestamp.catchupAndSubscribe(owner => this.#playbackTimestamp.setValue(owner.getValue())), worklet.countInBeatsRemaining.catchupAndSubscribe(owner => this.#countInBeatsRemaining.setValue(owner.getValue())), worklet.position.catchupAndSubscribe(owner => this.#position.setValue(owner.getValue())), worklet.bpm.catchupAndSubscribe(owner => this.#bpm.setValue(owner.getValue())), worklet.isPlaying.catchupAndSubscribe(owner => this.#isPlaying.setValue(owner.getValue())), worklet.isRecording.catchupAndSubscribe(owner => this.#isRecording.setValue(owner.getValue())), worklet.isCountingIn.catchupAndSubscribe(owner => this.#isCountingIn.setValue(owner.getValue())), worklet.markerState.catchupAndSubscribe(owner => this.#markerState.setValue(owner.getValue())));
|
|
25
|
+
this.#lifecycle.ownAll(worklet.playbackTimestamp.catchupAndSubscribe(owner => this.#playbackTimestamp.setValue(owner.getValue())), worklet.countInBeatsRemaining.catchupAndSubscribe(owner => this.#countInBeatsRemaining.setValue(owner.getValue())), worklet.position.catchupAndSubscribe(owner => this.#position.setValue(owner.getValue())), worklet.bpm.catchupAndSubscribe(owner => this.#bpm.setValue(owner.getValue())), worklet.isPlaying.catchupAndSubscribe(owner => this.#isPlaying.setValue(owner.getValue())), worklet.isRecording.catchupAndSubscribe(owner => this.#isRecording.setValue(owner.getValue())), worklet.isCountingIn.catchupAndSubscribe(owner => this.#isCountingIn.setValue(owner.getValue())), worklet.markerState.catchupAndSubscribe(owner => this.#markerState.setValue(owner.getValue())), worklet.cpuLoad.catchupAndSubscribe(owner => this.#cpuLoad.setValue(owner.getValue())));
|
|
25
26
|
}
|
|
26
27
|
assertWorklet() { this.#worklet.unwrap("No worklet available"); }
|
|
27
28
|
releaseWorklet() {
|
|
@@ -30,7 +31,17 @@ export class EngineFacade {
|
|
|
30
31
|
this.#lifecycle.terminate();
|
|
31
32
|
this.#worklet = Option.None;
|
|
32
33
|
}
|
|
33
|
-
play() {
|
|
34
|
+
play() {
|
|
35
|
+
this.#worklet.ifSome(worklet => {
|
|
36
|
+
const context = worklet.context;
|
|
37
|
+
if (context.state === "suspended") {
|
|
38
|
+
context.resume().then(() => worklet.play());
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
worklet.play();
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
34
45
|
stop(reset = false) { this.#worklet.ifSome(worklet => worklet.stop(reset)); }
|
|
35
46
|
setPosition(position) { this.#worklet.ifSome(worklet => worklet.setPosition(position)); }
|
|
36
47
|
prepareRecordingState(countIn) { this.#worklet.ifSome(worklet => worklet.prepareRecordingState(countIn)); }
|
|
@@ -43,6 +54,7 @@ export class EngineFacade {
|
|
|
43
54
|
get playbackTimestamp() { return this.#playbackTimestamp; }
|
|
44
55
|
get countInBeatsRemaining() { return this.#countInBeatsRemaining; }
|
|
45
56
|
get markerState() { return this.#markerState; }
|
|
57
|
+
get cpuLoad() { return this.#cpuLoad; }
|
|
46
58
|
get project() { return this.#worklet.unwrap("No worklet to get project").project; }
|
|
47
59
|
get sampleRate() { return this.#worklet.isEmpty() ? 44_100 : this.#worklet.unwrap().context.sampleRate; }
|
|
48
60
|
get preferences() { return this.#preferencesFacade; }
|
|
@@ -76,6 +88,12 @@ export class EngineFacade {
|
|
|
76
88
|
scheduleClipStop(trackIds) {
|
|
77
89
|
this.#worklet.unwrap("No worklet to scheduleClipStop").scheduleClipStop(trackIds);
|
|
78
90
|
}
|
|
91
|
+
registerMonitoringSource(uuid, node, numChannels) {
|
|
92
|
+
this.#worklet.ifSome(worklet => worklet.registerMonitoringSource(uuid, node, numChannels));
|
|
93
|
+
}
|
|
94
|
+
unregisterMonitoringSource(uuid) {
|
|
95
|
+
this.#worklet.ifSome(worklet => worklet.unregisterMonitoringSource(uuid));
|
|
96
|
+
}
|
|
79
97
|
terminate() {
|
|
80
98
|
this.releaseWorklet();
|
|
81
99
|
this.#terminator.terminate();
|
package/dist/EngineWorklet.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export declare class EngineWorklet extends AudioWorkletNode implements Engine {
|
|
|
27
27
|
get markerState(): ObservableValue<Nullable<[UUID.Bytes, int]>>;
|
|
28
28
|
get project(): Project;
|
|
29
29
|
get preferences(): PreferencesHost<EngineSettings>;
|
|
30
|
+
get cpuLoad(): ObservableValue<number>;
|
|
30
31
|
get perfBuffer(): Float32Array;
|
|
31
32
|
get perfIndex(): number;
|
|
32
33
|
isReady(): Promise<void>;
|
|
@@ -37,6 +38,8 @@ export declare class EngineWorklet extends AudioWorkletNode implements Engine {
|
|
|
37
38
|
scheduleClipPlay(clipIds: ReadonlyArray<UUID.Bytes>): void;
|
|
38
39
|
scheduleClipStop(trackIds: ReadonlyArray<UUID.Bytes>): void;
|
|
39
40
|
subscribeClipNotification(observer: Observer<ClipNotification>): Subscription;
|
|
41
|
+
registerMonitoringSource(uuid: UUID.Bytes, node: AudioNode, numChannels: 1 | 2): void;
|
|
42
|
+
unregisterMonitoringSource(uuid: UUID.Bytes): void;
|
|
40
43
|
terminate(): void;
|
|
41
44
|
}
|
|
42
45
|
//# sourceMappingURL=EngineWorklet.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EngineWorklet.d.ts","sourceRoot":"","sources":["../src/EngineWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,GAAG,
|
|
1
|
+
{"version":3,"file":"EngineWorklet.d.ts","sourceRoot":"","sources":["../src/EngineWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,GAAG,EAEH,sBAAsB,EAEtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAGZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,SAAS,EAAE,GAAG,EAAE,IAAI,EAAgB,MAAM,kBAAkB,CAAA;AAEpE,OAAO,EACH,gBAAgB,EAIhB,cAAc,EAKd,wBAAwB,EAExB,UAAU,EAEV,eAAe,EACf,gBAAgB,EACnB,MAAM,0BAA0B,CAAA;AAIjC,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAKjC,qBAAa,aAAc,SAAQ,gBAAiB,YAAW,MAAM;;IACjE,MAAM,CAAC,EAAE,EAAE,GAAG,CAAQ;IAEtB,QAAQ,CAAC,EAAE,SAAqB;gBAgCpB,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,OAAO,EAChB,mBAAmB,CAAC,EAAE,wBAAwB,EAC9C,OAAO,CAAC,EAAE,gBAAgB;IAkJtC,IAAI,IAAI,IAAI;IAIZ,IAAI,CAAC,KAAK,GAAE,OAAe,GAAG,IAAI;IAIlC,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IACjC,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAC7C,aAAa,IAAI,IAAI;IACrB,KAAK,IAAI,IAAI;IACb,KAAK,IAAI,IAAI;IAKb,IAAI,IAAI,IAAI;IACZ,cAAc,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAEnD,IAAI,SAAS,IAAI,eAAe,CAAC,OAAO,CAAC,CAAyB;IAClE,IAAI,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,CAA2B;IACtE,IAAI,YAAY,IAAI,eAAe,CAAC,OAAO,CAAC,CAA4B;IACxE,IAAI,qBAAqB,IAAI,eAAe,CAAC,MAAM,CAAC,CAAqC;IACzF,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAwB;IAC7D,IAAI,GAAG,IAAI,eAAe,CAAC,GAAG,CAAC,CAAmB;IAClD,IAAI,iBAAiB,IAAI,sBAAsB,CAAC,MAAM,CAAC,CAAiC;IACxF,IAAI,WAAW,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAA2B;IAC1F,IAAI,OAAO,IAAI,OAAO,CAAuB;IAC7C,IAAI,WAAW,IAAI,eAAe,CAAC,cAAc,CAAC,CAA2B;IAC7E,IAAI,OAAO,IAAI,eAAe,CAAC,MAAM,CAAC,CAAuB;IAC7D,IAAI,UAAU,IAAI,YAAY,CAA0B;IACxD,IAAI,SAAS,IAAI,MAAM,CAAyB;IAEhD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IACxC,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IACpC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IAC5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI;IACxC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAI1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAG3D,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAQ7E,wBAAwB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI;IAKrF,0BAA0B,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI;IAiElD,SAAS,IAAI,IAAI;CAKpB"}
|
package/dist/EngineWorklet.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Arrays, DefaultObservableValue, Notifier, Option, SyncStream, Terminator, UUID } from "@opendaw/lib-std";
|
|
1
|
+
import { Arrays, DefaultObservableValue, isDefined, Notifier, Option, SyncStream, Terminator, UUID } from "@opendaw/lib-std";
|
|
2
|
+
import { RenderQuantum } from "@opendaw/lib-dsp";
|
|
3
|
+
import { Communicator, Messenger } from "@opendaw/lib-runtime";
|
|
4
|
+
import { EngineSettingsSchema, EngineStateSchema, ExportStemsConfiguration, PERF_BUFFER_SIZE, PreferencesHost } from "@opendaw/studio-adapters";
|
|
2
5
|
import { SyncSource } from "@opendaw/lib-box";
|
|
3
6
|
import { AnimationFrame } from "@opendaw/lib-dom";
|
|
4
|
-
import { Communicator, Messenger } from "@opendaw/lib-runtime";
|
|
5
|
-
import { EngineSettingsSchema, EngineStateSchema, ExportStemsConfiguration, PreferencesHost } from "@opendaw/studio-adapters";
|
|
6
7
|
import { MIDIReceiver } from "./midi";
|
|
7
8
|
import { HRClockWorker } from "./HRClockWorker";
|
|
8
9
|
export class EngineWorklet extends AudioWorkletNode {
|
|
@@ -19,6 +20,7 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
|
19
20
|
#countInBeatsRemaining = new DefaultObservableValue(0);
|
|
20
21
|
#preferences;
|
|
21
22
|
#markerState = new DefaultObservableValue(null);
|
|
23
|
+
#cpuLoad = new DefaultObservableValue(0);
|
|
22
24
|
#controlFlags;
|
|
23
25
|
#notifyClipNotification;
|
|
24
26
|
#notifyNoteSignals;
|
|
@@ -27,8 +29,15 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
|
27
29
|
#isReady;
|
|
28
30
|
#perfBuffer = new Float32Array(0);
|
|
29
31
|
#perfIndex = 0;
|
|
32
|
+
#lastPerfReadIndex = 0;
|
|
33
|
+
#consecutiveOverloadCount = 0;
|
|
34
|
+
#lastCpuLoadUpdate = 0;
|
|
35
|
+
#maxMsSinceLastUpdate = 0;
|
|
36
|
+
#channelMerger = null;
|
|
37
|
+
#monitoringSources = new Map();
|
|
30
38
|
constructor(context, project, exportConfiguration, options) {
|
|
31
39
|
const numberOfChannels = ExportStemsConfiguration.countStems(Option.wrap(exportConfiguration)) * 2;
|
|
40
|
+
const budgetMs = (RenderQuantum / context.sampleRate) * 1000;
|
|
32
41
|
const reader = SyncStream.reader(EngineStateSchema(), state => {
|
|
33
42
|
this.#isPlaying.setValue(state.isPlaying);
|
|
34
43
|
this.#isRecording.setValue(state.isRecording);
|
|
@@ -38,11 +47,12 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
|
38
47
|
this.#bpm.setValue(state.bpm);
|
|
39
48
|
this.#perfBuffer = state.perfBuffer;
|
|
40
49
|
this.#perfIndex = state.perfIndex;
|
|
50
|
+
this.#updateCpuLoad(budgetMs, project);
|
|
41
51
|
this.#position.setValue(state.position); // This must be the last to handle the state values before
|
|
42
52
|
});
|
|
43
53
|
const controlFlagsSAB = new SharedArrayBuffer(4); // 4 bytes minimum
|
|
44
54
|
super(context, "engine-processor", {
|
|
45
|
-
numberOfInputs:
|
|
55
|
+
numberOfInputs: 1,
|
|
46
56
|
numberOfOutputs: 1,
|
|
47
57
|
outputChannelCount: [numberOfChannels],
|
|
48
58
|
processorOptions: {
|
|
@@ -92,6 +102,9 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
|
92
102
|
setupMIDI(port, buffer) {
|
|
93
103
|
dispatcher.dispatchAndForget(this.setupMIDI, port, buffer);
|
|
94
104
|
}
|
|
105
|
+
updateMonitoringMap(map) {
|
|
106
|
+
dispatcher.dispatchAndForget(this.updateMonitoringMap, map);
|
|
107
|
+
}
|
|
95
108
|
terminate() { dispatcher.dispatchAndForget(this.terminate); }
|
|
96
109
|
}));
|
|
97
110
|
const { port, sab } = this.#terminator.own(MIDIReceiver.create(() => context instanceof AudioContext ? context.outputLatency * 1000 : 20, (deviceId, data, relativeTimeInMs) => this.#project.receivedMIDIFromEngine(deviceId, data, relativeTimeInMs)));
|
|
@@ -152,20 +165,25 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
|
152
165
|
this.#preferences = this.#terminator.own(new PreferencesHost(EngineSettingsSchema.parse({})));
|
|
153
166
|
this.#terminator.ownAll(AnimationFrame.add(() => reader.tryRead()), project.liveStreamReceiver.connect(messenger.channel("engine-live-data")), this.#preferences.syncWith(messenger.channel("engine-preferences")), new SyncSource(project.boxGraph, messenger.channel("engine-sync"), false));
|
|
154
167
|
}
|
|
155
|
-
play() {
|
|
156
|
-
|
|
168
|
+
play() {
|
|
169
|
+
this.wake();
|
|
170
|
+
this.#commands.play();
|
|
171
|
+
}
|
|
172
|
+
stop(reset = false) {
|
|
173
|
+
this.#isPlaying.setValue(false);
|
|
174
|
+
this.#commands.stop(reset);
|
|
175
|
+
}
|
|
157
176
|
setPosition(position) { this.#commands.setPosition(position); }
|
|
158
177
|
prepareRecordingState(countIn) { this.#commands.prepareRecordingState(countIn); }
|
|
159
178
|
stopRecording() { this.#commands.stopRecording(); }
|
|
160
179
|
panic() { this.#commands.panic(); }
|
|
161
180
|
sleep() {
|
|
162
181
|
Atomics.store(this.#controlFlags, 0, 1);
|
|
182
|
+
this.#isPlaying.setValue(false);
|
|
163
183
|
this.#commands.stop(true);
|
|
164
184
|
}
|
|
165
185
|
wake() { Atomics.store(this.#controlFlags, 0, 0); }
|
|
166
|
-
loadClickSound(index, data) {
|
|
167
|
-
this.#commands.loadClickSound(index, data);
|
|
168
|
-
}
|
|
186
|
+
loadClickSound(index, data) { this.#commands.loadClickSound(index, data); }
|
|
169
187
|
get isPlaying() { return this.#isPlaying; }
|
|
170
188
|
get isRecording() { return this.#isRecording; }
|
|
171
189
|
get isCountingIn() { return this.#isCountingIn; }
|
|
@@ -176,6 +194,7 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
|
176
194
|
get markerState() { return this.#markerState; }
|
|
177
195
|
get project() { return this.#project; }
|
|
178
196
|
get preferences() { return this.#preferences; }
|
|
197
|
+
get cpuLoad() { return this.#cpuLoad; }
|
|
179
198
|
get perfBuffer() { return this.#perfBuffer; }
|
|
180
199
|
get perfIndex() { return this.#perfIndex; }
|
|
181
200
|
isReady() { return this.#isReady; }
|
|
@@ -197,6 +216,75 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
|
197
216
|
});
|
|
198
217
|
return this.#notifyClipNotification.subscribe(observer);
|
|
199
218
|
}
|
|
219
|
+
registerMonitoringSource(uuid, node, numChannels) {
|
|
220
|
+
this.#monitoringSources.set(UUID.toString(uuid), { node, numChannels });
|
|
221
|
+
this.#rebuildMonitoringMerger();
|
|
222
|
+
}
|
|
223
|
+
unregisterMonitoringSource(uuid) {
|
|
224
|
+
const key = UUID.toString(uuid);
|
|
225
|
+
const entry = this.#monitoringSources.get(key);
|
|
226
|
+
if (isDefined(entry)) {
|
|
227
|
+
entry.node.disconnect();
|
|
228
|
+
this.#monitoringSources.delete(key);
|
|
229
|
+
}
|
|
230
|
+
this.#rebuildMonitoringMerger();
|
|
231
|
+
}
|
|
232
|
+
#rebuildMonitoringMerger() {
|
|
233
|
+
if (isDefined(this.#channelMerger)) {
|
|
234
|
+
this.#channelMerger.disconnect();
|
|
235
|
+
this.#channelMerger = null;
|
|
236
|
+
}
|
|
237
|
+
if (this.#monitoringSources.size === 0) {
|
|
238
|
+
this.#commands.updateMonitoringMap([]);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
let totalChannels = 0;
|
|
242
|
+
for (const { numChannels } of this.#monitoringSources.values()) {
|
|
243
|
+
totalChannels += numChannels;
|
|
244
|
+
}
|
|
245
|
+
this.#channelMerger = this.context.createChannelMerger(totalChannels);
|
|
246
|
+
this.#channelMerger.connect(this);
|
|
247
|
+
const map = [];
|
|
248
|
+
let channel = 0;
|
|
249
|
+
for (const [uuidString, { node, numChannels }] of this.#monitoringSources) {
|
|
250
|
+
const uuid = UUID.parse(uuidString);
|
|
251
|
+
const splitter = this.context.createChannelSplitter(numChannels);
|
|
252
|
+
node.connect(splitter);
|
|
253
|
+
const channels = [];
|
|
254
|
+
for (let i = 0; i < numChannels; i++) {
|
|
255
|
+
splitter.connect(this.#channelMerger, i, channel);
|
|
256
|
+
channels.push(channel);
|
|
257
|
+
channel++;
|
|
258
|
+
}
|
|
259
|
+
map.push({ uuid, channels });
|
|
260
|
+
}
|
|
261
|
+
this.#commands.updateMonitoringMap(map);
|
|
262
|
+
}
|
|
263
|
+
#updateCpuLoad(budgetMs, project) {
|
|
264
|
+
while (this.#lastPerfReadIndex !== this.#perfIndex) {
|
|
265
|
+
const ms = this.#perfBuffer[this.#lastPerfReadIndex];
|
|
266
|
+
if (ms > this.#maxMsSinceLastUpdate) {
|
|
267
|
+
this.#maxMsSinceLastUpdate = ms;
|
|
268
|
+
}
|
|
269
|
+
if (ms >= budgetMs) {
|
|
270
|
+
this.#consecutiveOverloadCount++;
|
|
271
|
+
if (this.#consecutiveOverloadCount >= 30) {
|
|
272
|
+
project.handleCpuOverload();
|
|
273
|
+
this.#consecutiveOverloadCount = 0;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
this.#consecutiveOverloadCount = 0;
|
|
278
|
+
}
|
|
279
|
+
this.#lastPerfReadIndex = (this.#lastPerfReadIndex + 1) % PERF_BUFFER_SIZE;
|
|
280
|
+
}
|
|
281
|
+
const now = performance.now();
|
|
282
|
+
if (now - this.#lastCpuLoadUpdate >= 1000) {
|
|
283
|
+
this.#cpuLoad.setValue(Math.round((this.#maxMsSinceLastUpdate / budgetMs) * 100));
|
|
284
|
+
this.#maxMsSinceLastUpdate = 0;
|
|
285
|
+
this.#lastCpuLoadUpdate = now;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
200
288
|
terminate() {
|
|
201
289
|
this.#commands.terminate();
|
|
202
290
|
this.#terminator.terminate();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OfflineEngineRenderer.d.ts","sourceRoot":"","sources":["../src/OfflineEngineRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,GAAG,EAAa,MAAM,EAAS,QAAQ,EAA6B,MAAM,kBAAkB,CAAA;AAC5G,OAAO,EAAC,SAAS,EAAO,MAAM,kBAAkB,CAAA;AAEhD,OAAO,EAGH,wBAAwB,
|
|
1
|
+
{"version":3,"file":"OfflineEngineRenderer.d.ts","sourceRoot":"","sources":["../src/OfflineEngineRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,GAAG,EAAa,MAAM,EAAS,QAAQ,EAA6B,MAAM,kBAAkB,CAAA;AAC5G,OAAO,EAAC,SAAS,EAAO,MAAM,kBAAkB,CAAA;AAEhD,OAAO,EAGH,wBAAwB,EAKxB,yBAAyB,EAC5B,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAOjC,qBAAa,qBAAqB;;IAC9B,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKjC,MAAM,CAAC,YAAY,IAAI,MAAM;WAIhB,MAAM,CAAC,MAAM,EAAE,OAAO,EACf,sBAAsB,EAAE,MAAM,CAAC,wBAAwB,CAAC,EACxD,UAAU,GAAE,GAAY,GACzC,OAAO,CAAC,qBAAqB,CAAC;WAoHpB,KAAK,CAAC,MAAM,EAAE,OAAO,EACf,sBAAsB,EAAE,MAAM,CAAC,wBAAwB,CAAC,EACxD,QAAQ,EAAE,QAAQ,CAAC,OAAO,EAC1B,WAAW,CAAC,EAAE,WAAW,EACzB,UAAU,GAAE,GAAY,GACxC,OAAO,CAAC,SAAS,CAAC;IAwBrB,OAAO;IAkBP,IAAI,UAAU,IAAI,GAAG,CAA0B;IAC/C,IAAI,gBAAgB,IAAI,GAAG,CAAgC;IAC3D,IAAI,WAAW,IAAI,GAAG,CAA2B;IAEjD,IAAI,IAAI,IAAI;IAIZ,IAAI,IAAI,IAAI;IAKZ,SAAS,IAAI,IAAI;IAKX,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAM3C,MAAM,CACR,MAAM,EAAE,yBAAyB,EACjC,QAAQ,EAAE,QAAQ,CAAC,OAAO,EAC1B,WAAW,CAAC,EAAE,WAAW,GAC1B,OAAO,CAAC,SAAS,CAAC;CAqCxB"}
|
|
@@ -90,6 +90,7 @@ export class OfflineEngineRenderer {
|
|
|
90
90
|
scheduleClipPlay(clipIds) { dispatcher.dispatchAndForget(this.scheduleClipPlay, clipIds); }
|
|
91
91
|
scheduleClipStop(trackIds) { dispatcher.dispatchAndForget(this.scheduleClipStop, trackIds); }
|
|
92
92
|
setupMIDI(port, buffer) { dispatcher.dispatchAndForget(this.setupMIDI, port, buffer); }
|
|
93
|
+
updateMonitoringMap(map) { dispatcher.dispatchAndForget(this.updateMonitoringMap, map); }
|
|
93
94
|
loadClickSound(index, data) { dispatcher.dispatchAndForget(this.loadClickSound, index, data); }
|
|
94
95
|
terminate() { dispatcher.dispatchAndForget(this.terminate); }
|
|
95
96
|
});
|
|
@@ -14,6 +14,7 @@ export declare const StudioPreferences: import("@opendaw/lib-fusion").Preference
|
|
|
14
14
|
engine: {
|
|
15
15
|
"note-audition-while-editing": boolean;
|
|
16
16
|
"auto-create-output-compressor": boolean;
|
|
17
|
+
"stop-playback-when-overloading": boolean;
|
|
17
18
|
};
|
|
18
19
|
pointer: {
|
|
19
20
|
"dragging-use-pointer-lock": boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StudioPreferences.d.ts","sourceRoot":"","sources":["../src/StudioPreferences.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB
|
|
1
|
+
{"version":3,"file":"StudioPreferences.d.ts","sourceRoot":"","sources":["../src/StudioPreferences.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAwD,CAAA"}
|
package/dist/StudioSettings.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export declare const StudioSettingsSchema: z.ZodObject<{
|
|
|
17
17
|
engine: z.ZodDefault<z.ZodObject<{
|
|
18
18
|
"note-audition-while-editing": z.ZodBoolean;
|
|
19
19
|
"auto-create-output-compressor": z.ZodBoolean;
|
|
20
|
+
"stop-playback-when-overloading": z.ZodBoolean;
|
|
20
21
|
}, z.core.$strip>>;
|
|
21
22
|
pointer: z.ZodDefault<z.ZodObject<{
|
|
22
23
|
"dragging-use-pointer-lock": z.ZodBoolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StudioSettings.d.ts","sourceRoot":"","sources":["../src/StudioSettings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAA;AAGrB,eAAO,MAAM,UAAU,8BAA+B,CAAA;AACtD,eAAO,MAAM,kCAAkC,qDAAsD,CAAA;AAErG,eAAO,MAAM,oBAAoB
|
|
1
|
+
{"version":3,"file":"StudioSettings.d.ts","sourceRoot":"","sources":["../src/StudioSettings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAA;AAGrB,eAAO,MAAM,UAAU,8BAA+B,CAAA;AACtD,eAAO,MAAM,kCAAkC,qDAAsD,CAAA;AAErG,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+D/B,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA"}
|
package/dist/StudioSettings.js
CHANGED
|
@@ -22,10 +22,12 @@ export const StudioSettingsSchema = z.object({
|
|
|
22
22
|
}).default({ musical: true, absolute: false, details: false, fps: 25 }),
|
|
23
23
|
"engine": z.object({
|
|
24
24
|
"note-audition-while-editing": z.boolean(),
|
|
25
|
-
"auto-create-output-compressor": z.boolean()
|
|
25
|
+
"auto-create-output-compressor": z.boolean(),
|
|
26
|
+
"stop-playback-when-overloading": z.boolean()
|
|
26
27
|
}).default({
|
|
27
28
|
"note-audition-while-editing": true,
|
|
28
|
-
"auto-create-output-compressor": true
|
|
29
|
+
"auto-create-output-compressor": true,
|
|
30
|
+
"stop-playback-when-overloading": true
|
|
29
31
|
}),
|
|
30
32
|
"pointer": z.object({
|
|
31
33
|
"dragging-use-pointer-lock": z.boolean(),
|
|
@@ -2,11 +2,13 @@ import { MutableObservableOption, Option, Terminable } from "@opendaw/lib-std";
|
|
|
2
2
|
import { AudioUnitBox, CaptureAudioBox } from "@opendaw/studio-boxes";
|
|
3
3
|
import { Capture } from "./Capture";
|
|
4
4
|
import { CaptureDevices } from "./CaptureDevices";
|
|
5
|
+
import { MonitoringMode } from "./MonitoringMode";
|
|
5
6
|
export declare class CaptureAudio extends Capture<CaptureAudioBox> {
|
|
6
7
|
#private;
|
|
7
8
|
constructor(manager: CaptureDevices, audioUnitBox: AudioUnitBox, captureAudioBox: CaptureAudioBox);
|
|
8
9
|
get isMonitoring(): boolean;
|
|
9
|
-
|
|
10
|
+
get monitoringMode(): MonitoringMode;
|
|
11
|
+
set monitoringMode(value: MonitoringMode);
|
|
10
12
|
get gainDb(): number;
|
|
11
13
|
get requestChannels(): Option<1 | 2>;
|
|
12
14
|
set requestChannels(value: 1 | 2);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CaptureAudio.d.ts","sourceRoot":"","sources":["../../src/capture/CaptureAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,uBAAuB,EAEvB,MAAM,EAEN,UAAU,EACb,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAC,YAAY,EAAE,eAAe,EAAC,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AACjC,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"CaptureAudio.d.ts","sourceRoot":"","sources":["../../src/capture/CaptureAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,uBAAuB,EAEvB,MAAM,EAEN,UAAU,EACb,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAC,YAAY,EAAE,eAAe,EAAC,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AACjC,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAK/C,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAE/C,qBAAa,YAAa,SAAQ,OAAO,CAAC,eAAe,CAAC;;gBAe1C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe;IAwCjG,IAAI,YAAY,IAAI,OAAO,CAAwC;IACnE,IAAI,cAAc,IAAI,cAAc,CAA8B;IAClE,IAAI,cAAc,CAAC,KAAK,EAAE,cAAc,EAQvC;IACD,IAAI,MAAM,IAAI,MAAM,CAAsB;IAC1C,IAAI,eAAe,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAA+B;IACnE,IAAI,eAAe,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,EAAmD;IACnF,IAAI,MAAM,IAAI,uBAAuB,CAAC,WAAW,CAAC,CAAsB;IACxE,IAAI,cAAc,IAAI,MAAM,CAAC,MAAM,CAAC,CAEnC;IACD,IAAI,KAAK,IAAI,MAAM,CAAsE;IACzF,IAAI,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,CAA+D;IAChG,IAAI,gBAAgB,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAE/C;IACD,IAAI,UAAU,IAAI,MAAM,CAAC,SAAS,CAAC,CAAiD;IACpF,IAAI,qBAAqB,IAAI,MAAM,CAA6C;IAE1E,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BvC,cAAc,IAAI,UAAU;CAsH/B"}
|
|
@@ -8,7 +8,7 @@ import { RenderQuantum } from "../RenderQuantum";
|
|
|
8
8
|
export class CaptureAudio extends Capture {
|
|
9
9
|
#stream;
|
|
10
10
|
#streamGenerator;
|
|
11
|
-
#
|
|
11
|
+
#monitoringMode = "off";
|
|
12
12
|
#requestChannels = Option.None;
|
|
13
13
|
#gainDb = 0.0;
|
|
14
14
|
#audioChain = null;
|
|
@@ -21,6 +21,12 @@ export class CaptureAudio extends Capture {
|
|
|
21
21
|
const channels = owner.getValue();
|
|
22
22
|
this.#requestChannels = channels === 1 || channels === 2 ? Option.wrap(channels) : Option.None;
|
|
23
23
|
this.#stream.ifSome(stream => this.#rebuildAudioChain(stream));
|
|
24
|
+
// Re-register monitoring if in effects mode (channel count may have changed)
|
|
25
|
+
if (this.#monitoringMode === "effects" && isDefined(this.#audioChain)) {
|
|
26
|
+
const engine = this.manager.project.engine;
|
|
27
|
+
engine.unregisterMonitoringSource(this.audioUnitBox.address.uuid);
|
|
28
|
+
engine.registerMonitoringSource(this.audioUnitBox.address.uuid, this.#audioChain.gainNode, this.#audioChain.channelCount);
|
|
29
|
+
}
|
|
24
30
|
}), captureAudioBox.gainDb.catchupAndSubscribe(owner => {
|
|
25
31
|
this.#gainDb = owner.getValue();
|
|
26
32
|
if (isDefined(this.#audioChain)) {
|
|
@@ -40,19 +46,18 @@ export class CaptureAudio extends Capture {
|
|
|
40
46
|
}
|
|
41
47
|
}));
|
|
42
48
|
}
|
|
43
|
-
get isMonitoring() { return this.#
|
|
44
|
-
|
|
45
|
-
|
|
49
|
+
get isMonitoring() { return this.#monitoringMode !== "off"; }
|
|
50
|
+
get monitoringMode() { return this.#monitoringMode; }
|
|
51
|
+
set monitoringMode(value) {
|
|
52
|
+
if (this.#monitoringMode === value) {
|
|
46
53
|
return;
|
|
47
54
|
}
|
|
48
|
-
this.#
|
|
49
|
-
|
|
55
|
+
this.#disconnectMonitoring();
|
|
56
|
+
this.#monitoringMode = value;
|
|
57
|
+
if (this.#monitoringMode !== "off") {
|
|
50
58
|
this.armed.setValue(true);
|
|
51
|
-
this.#connectMonitoring();
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
this.#disconnectMonitoring();
|
|
55
59
|
}
|
|
60
|
+
this.#connectMonitoring();
|
|
56
61
|
}
|
|
57
62
|
get gainDb() { return this.#gainDb; }
|
|
58
63
|
get requestChannels() { return this.#requestChannels; }
|
|
@@ -154,7 +159,7 @@ export class CaptureAudio extends Capture {
|
|
|
154
159
|
this.#stream.clear(stream => stream.getAudioTracks().forEach(track => track.stop()));
|
|
155
160
|
}
|
|
156
161
|
#rebuildAudioChain(stream) {
|
|
157
|
-
const
|
|
162
|
+
const wasMonitoringMode = this.#monitoringMode !== "off" && isDefined(this.#audioChain) ? this.#monitoringMode : "off";
|
|
158
163
|
this.#destroyAudioChain();
|
|
159
164
|
const { audioContext } = this.manager.project.env;
|
|
160
165
|
const sourceNode = audioContext.createMediaStreamSource(stream);
|
|
@@ -166,7 +171,7 @@ export class CaptureAudio extends Capture {
|
|
|
166
171
|
gainNode.channelCountMode = "explicit";
|
|
167
172
|
sourceNode.connect(gainNode);
|
|
168
173
|
this.#audioChain = { sourceNode, gainNode, channelCount };
|
|
169
|
-
if (
|
|
174
|
+
if (wasMonitoringMode !== "off" || this.#monitoringMode !== "off") {
|
|
170
175
|
this.#connectMonitoring();
|
|
171
176
|
}
|
|
172
177
|
}
|
|
@@ -179,15 +184,35 @@ export class CaptureAudio extends Capture {
|
|
|
179
184
|
}
|
|
180
185
|
}
|
|
181
186
|
#connectMonitoring() {
|
|
182
|
-
if (isDefined(this.#audioChain)) {
|
|
183
|
-
|
|
184
|
-
|
|
187
|
+
if (!isDefined(this.#audioChain)) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
switch (this.#monitoringMode) {
|
|
191
|
+
case "off":
|
|
192
|
+
break;
|
|
193
|
+
case "direct":
|
|
194
|
+
this.#audioChain.gainNode.connect(this.manager.project.env.audioContext.destination);
|
|
195
|
+
break;
|
|
196
|
+
case "effects":
|
|
197
|
+
const engine = this.manager.project.engine;
|
|
198
|
+
engine.registerMonitoringSource(this.audioUnitBox.address.uuid, this.#audioChain.gainNode, this.#audioChain.channelCount);
|
|
199
|
+
break;
|
|
185
200
|
}
|
|
186
201
|
}
|
|
187
202
|
#disconnectMonitoring() {
|
|
188
|
-
if (isDefined(this.#audioChain)) {
|
|
189
|
-
|
|
190
|
-
|
|
203
|
+
if (!isDefined(this.#audioChain)) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
switch (this.#monitoringMode) {
|
|
207
|
+
case "off":
|
|
208
|
+
break;
|
|
209
|
+
case "direct":
|
|
210
|
+
this.#audioChain.gainNode.disconnect(this.manager.project.env.audioContext.destination);
|
|
211
|
+
break;
|
|
212
|
+
case "effects":
|
|
213
|
+
this.#audioChain.gainNode.disconnect();
|
|
214
|
+
this.manager.project.engine.unregisterMonitoringSource(this.audioUnitBox.address.uuid);
|
|
215
|
+
break;
|
|
191
216
|
}
|
|
192
217
|
}
|
|
193
218
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MonitoringMode.d.ts","sourceRoot":"","sources":["../../src/capture/MonitoringMode.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/capture/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/capture/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/capture/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA"}
|
package/dist/capture/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DawProjectImporter.d.ts","sourceRoot":"","sources":["../../src/dawproject/DawProjectImporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAiBH,IAAI,EAEP,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAcH,aAAa,EAUhB,MAAM,yBAAyB,CAAA;AA2BhC,OAAO,EAOH,eAAe,EAElB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAA;AAIvC,yBAAiB,gBAAgB,CAAC;IAW9B,KAAY,MAAM,GAAG;QACjB,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpC,QAAQ,EAAE,eAAe,CAAA;KAC5B,CAAA;IAOM,MAAM,IAAI,GAAU,QAAQ,aAAa,EAAE,WAAW,UAAU,CAAC,gBAAgB,KAAG,OAAO,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"DawProjectImporter.d.ts","sourceRoot":"","sources":["../../src/dawproject/DawProjectImporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAiBH,IAAI,EAEP,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAcH,aAAa,EAUhB,MAAM,yBAAyB,CAAA;AA2BhC,OAAO,EAOH,eAAe,EAElB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAA;AAIvC,yBAAiB,gBAAgB,CAAC;IAW9B,KAAY,MAAM,GAAG;QACjB,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpC,QAAQ,EAAE,eAAe,CAAA;KAC5B,CAAA;IAOM,MAAM,IAAI,GAAU,QAAQ,aAAa,EAAE,WAAW,UAAU,CAAC,gBAAgB,KAAG,OAAO,CAAC,MAAM,CA6cxG,CAAA;CAaJ"}
|
|
@@ -328,6 +328,10 @@ export var DawProjectImport;
|
|
|
328
328
|
const loopDuration = clip.loopEnd ?? warpDistance;
|
|
329
329
|
const durationInPulses = duration * PPQN.Quarter;
|
|
330
330
|
const loopDurationInPulses = loopDuration * PPQN.Quarter;
|
|
331
|
+
if (loopDurationInPulses < 1) {
|
|
332
|
+
console.warn(`Skipping clip '${clip.name}': loop duration too small (${loopDurationInPulses} ppqn)`);
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
331
335
|
const collectionBox = ValueEventCollectionBox.create(boxGraph, UUID.generate());
|
|
332
336
|
const pitchStretch = AudioPitchStretchBox.create(boxGraph, UUID.generate());
|
|
333
337
|
AudioContentHelpers.addDefaultWarpMarkers(boxGraph, pitchStretch, loopDurationInPulses, audioFileBox.endInSeconds.getValue());
|