@opendaw/studio-core 0.0.130 → 0.0.131
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.d.ts.map +1 -1
- package/dist/AssetService.js +11 -2
- package/dist/AudioOfflineRenderer.js +1 -1
- package/dist/Engine.d.ts +1 -1
- package/dist/Engine.d.ts.map +1 -1
- package/dist/EngineFacade.d.ts +1 -1
- package/dist/EngineFacade.d.ts.map +1 -1
- package/dist/EngineFacade.js +2 -2
- package/dist/EngineWorklet.d.ts +1 -1
- package/dist/EngineWorklet.d.ts.map +1 -1
- package/dist/EngineWorklet.js +9 -46
- package/dist/MonitoringRouter.d.ts +10 -0
- package/dist/MonitoringRouter.d.ts.map +1 -0
- package/dist/MonitoringRouter.js +89 -0
- package/dist/capture/CaptureAudio.d.ts +10 -0
- package/dist/capture/CaptureAudio.d.ts.map +1 -1
- package/dist/capture/CaptureAudio.js +105 -30
- package/dist/capture/RecordAudio.d.ts.map +1 -1
- package/dist/capture/RecordAudio.js +10 -2
- package/dist/capture/Recording.js +1 -1
- package/dist/processors.js +22 -22
- package/dist/processors.js.map +4 -4
- package/dist/project/AudioWavExport.d.ts +6 -0
- package/dist/project/AudioWavExport.d.ts.map +1 -0
- package/dist/project/AudioWavExport.js +15 -0
- package/dist/project/NoteMidiExport.d.ts +9 -0
- package/dist/project/NoteMidiExport.d.ts.map +1 -0
- package/dist/project/NoteMidiExport.js +27 -0
- package/dist/project/Project.d.ts.map +1 -1
- package/dist/project/Project.js +1 -2
- package/dist/project/ProjectApi.d.ts +3 -1
- package/dist/project/ProjectApi.d.ts.map +1 -1
- package/dist/project/ProjectApi.js +8 -0
- package/dist/project/ProjectStorage.d.ts.map +1 -1
- package/dist/project/ProjectStorage.js +1 -0
- package/dist/project/index.d.ts +2 -0
- package/dist/project/index.d.ts.map +1 -1
- package/dist/project/index.js +2 -0
- package/dist/project/migration/MigrateValueEventCollection.test.js +3 -3
- package/dist/samples/OpenSampleAPI.d.ts +1 -0
- package/dist/samples/OpenSampleAPI.d.ts.map +1 -1
- package/dist/samples/OpenSampleAPI.js +1 -0
- package/dist/samples/SampleService.js +1 -1
- package/dist/soundfont/DefaultSoundfontLoader.d.ts.map +1 -1
- package/dist/soundfont/DefaultSoundfontLoader.js +3 -0
- package/dist/soundfont/OpenSoundfontAPI.d.ts +1 -0
- package/dist/soundfont/OpenSoundfontAPI.d.ts.map +1 -1
- package/dist/soundfont/OpenSoundfontAPI.js +1 -0
- package/dist/soundfont/SoundfontService.js +1 -1
- package/dist/sync-log/SyncLogWriter.d.ts.map +1 -1
- package/dist/sync-log/SyncLogWriter.js +3 -2
- package/dist/ui/clipboard/ClipboardUtils.js +1 -1
- package/dist/ysync/YService.d.ts.map +1 -1
- package/dist/ysync/YService.js +0 -5
- package/dist/ysync/YSync.d.ts +1 -0
- package/dist/ysync/YSync.d.ts.map +1 -1
- package/dist/ysync/YSync.js +45 -48
- package/package.json +16 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetService.d.ts","sourceRoot":"","sources":["../src/AssetService.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,EAKL,QAAQ,EACR,QAAQ,
|
|
1
|
+
{"version":3,"file":"AssetService.d.ts","sourceRoot":"","sources":["../src/AssetService.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,EAKL,QAAQ,EACR,QAAQ,EACR,QAAQ,EAER,YAAY,EACZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAC,QAAQ,EAAC,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAC,MAAM,EAAE,SAAS,EAAC,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAAC,YAAY,EAAE,gBAAgB,EAAC,MAAM,uBAAuB,CAAA;AAEpE,yBAAiB,YAAY,CAAC;IAC1B,KAAY,UAAU,GAAG;QACrB,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAA;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,WAAW,CAAC;QACzB,eAAe,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC;QACnC,MAAM,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAA;KAClC,CAAA;CACJ;AAED,8BAAsB,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EAAE,GAAG,GAAG,IAAI;IACvE,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAChD,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC9C,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,YAAY,GAAG,gBAAgB,CAAC,CAAA;IAC3E,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAA;IAEhE,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAA2B;IAE1E,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,YAAY;IAE/C,MAAM,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAI1D,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,YAAY,CAAC,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC;IAExD,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE;QAAE,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,KAAK,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;cAkDjG,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAuChH,SAAS,CAAC,QAAQ,CAAC,eAAe,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;CAClE"}
|
package/dist/AssetService.js
CHANGED
|
@@ -48,10 +48,19 @@ export class AssetService {
|
|
|
48
48
|
});
|
|
49
49
|
continue;
|
|
50
50
|
}
|
|
51
|
-
const
|
|
51
|
+
const importResult = await Promises.tryCatch(this.importFile({
|
|
52
|
+
uuid, name: files[0].name, arrayBuffer: readResult.value, progressHandler: Progress.Empty
|
|
53
|
+
}));
|
|
54
|
+
if (importResult.status === "rejected") {
|
|
55
|
+
await RuntimeNotifier.info({
|
|
56
|
+
headline: `${this.nameSingular} Import Failed`,
|
|
57
|
+
message: `'${files[0].name}' could not be imported: ${String(importResult.error)}`
|
|
58
|
+
});
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
52
61
|
await RuntimeNotifier.info({
|
|
53
62
|
headline: "Replaced Asset",
|
|
54
|
-
message: `${
|
|
63
|
+
message: `${importResult.value.name} has been replaced`
|
|
55
64
|
});
|
|
56
65
|
manager.invalidate(uuid);
|
|
57
66
|
}
|
|
@@ -28,7 +28,7 @@ export var AudioOfflineRenderer;
|
|
|
28
28
|
exportConfiguration: optExportConfiguration.unwrapOrUndefined()
|
|
29
29
|
});
|
|
30
30
|
engineWorklet.play();
|
|
31
|
-
engineWorklet.connect(context.destination);
|
|
31
|
+
engineWorklet.connect(context.destination, 0);
|
|
32
32
|
await engineWorklet.isReady();
|
|
33
33
|
while (!await engineWorklet.queryLoadingComplete()) {
|
|
34
34
|
await Wait.timeSpan(TimeSpan.seconds(1));
|
package/dist/Engine.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export interface Engine extends Terminable {
|
|
|
25
25
|
scheduleClipStop(trackIds: ReadonlyArray<UUID.Bytes>): void;
|
|
26
26
|
subscribeClipNotification(observer: Observer<ClipNotification>): Subscription;
|
|
27
27
|
subscribeDeviceMessage(uuid: string, listener: Procedure<string>): Subscription;
|
|
28
|
-
registerMonitoringSource(uuid: UUID.Bytes, node: AudioNode, numChannels: 1 | 2): void;
|
|
28
|
+
registerMonitoringSource(uuid: UUID.Bytes, node: AudioNode, numChannels: 1 | 2, destinationNode: AudioNode): void;
|
|
29
29
|
unregisterMonitoringSource(uuid: UUID.Bytes): void;
|
|
30
30
|
get position(): ObservableValue<ppqn>;
|
|
31
31
|
get bpm(): ObservableValue<bpm>;
|
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,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACpH,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,gBAAgB;IAChB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IAC7C,gBAAgB;IAChB,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,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,IAAI,CAAA;IACtE,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,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,YAAY,CAAA;IAC/E,wBAAwB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,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,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACpH,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,gBAAgB;IAChB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IAC7C,gBAAgB;IAChB,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,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,IAAI,CAAA;IACtE,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,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,YAAY,CAAA;IAC/E,wBAAwB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,GAAG,CAAC,EAAE,eAAe,EAAE,SAAS,GAAG,IAAI,CAAA;IACjH,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
|
@@ -43,7 +43,7 @@ export declare class EngineFacade implements Engine {
|
|
|
43
43
|
scheduleClipPlay(clipIds: ReadonlyArray<UUID.Bytes>): void;
|
|
44
44
|
scheduleClipStop(trackIds: ReadonlyArray<UUID.Bytes>): void;
|
|
45
45
|
subscribeDeviceMessage(uuid: string, listener: Procedure<string>): Subscription;
|
|
46
|
-
registerMonitoringSource(uuid: UUID.Bytes, node: AudioNode, numChannels: 1 | 2): void;
|
|
46
|
+
registerMonitoringSource(uuid: UUID.Bytes, node: AudioNode, numChannels: 1 | 2, destinationNode: AudioNode): void;
|
|
47
47
|
unregisterMonitoringSource(uuid: UUID.Bytes): void;
|
|
48
48
|
terminate(): void;
|
|
49
49
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EngineFacade.d.ts","sourceRoot":"","sources":["../src/EngineFacade.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"EngineFacade.d.ts","sourceRoot":"","sources":["../src/EngineFacade.ts"],"names":[],"mappings":"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"}
|
package/dist/EngineFacade.js
CHANGED
|
@@ -94,8 +94,8 @@ export class EngineFacade {
|
|
|
94
94
|
subscribeDeviceMessage(uuid, listener) {
|
|
95
95
|
return this.#worklet.unwrap("No worklet to subscribeDeviceMessage").subscribeDeviceMessage(uuid, listener);
|
|
96
96
|
}
|
|
97
|
-
registerMonitoringSource(uuid, node, numChannels) {
|
|
98
|
-
this.#worklet.ifSome(worklet => worklet.registerMonitoringSource(uuid, node, numChannels));
|
|
97
|
+
registerMonitoringSource(uuid, node, numChannels, destinationNode) {
|
|
98
|
+
this.#worklet.ifSome(worklet => worklet.registerMonitoringSource(uuid, node, numChannels, destinationNode));
|
|
99
99
|
}
|
|
100
100
|
unregisterMonitoringSource(uuid) {
|
|
101
101
|
this.#worklet.ifSome(worklet => worklet.unregisterMonitoringSource(uuid));
|
package/dist/EngineWorklet.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export declare class EngineWorklet extends AudioWorkletNode implements Engine {
|
|
|
40
40
|
scheduleClipStop(trackIds: ReadonlyArray<UUID.Bytes>): void;
|
|
41
41
|
subscribeClipNotification(observer: Observer<ClipNotification>): Subscription;
|
|
42
42
|
subscribeDeviceMessage(uuid: string, listener: Procedure<string>): Subscription;
|
|
43
|
-
registerMonitoringSource(uuid: UUID.Bytes, node: AudioNode, numChannels: 1 | 2): void;
|
|
43
|
+
registerMonitoringSource(uuid: UUID.Bytes, node: AudioNode, numChannels: 1 | 2, destinationNode: AudioNode): void;
|
|
44
44
|
unregisterMonitoringSource(uuid: UUID.Bytes): void;
|
|
45
45
|
terminate(): void;
|
|
46
46
|
}
|
|
@@ -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":"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"}
|
package/dist/EngineWorklet.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Arrays, DefaultObservableValue,
|
|
1
|
+
import { Arrays, DefaultObservableValue, Notifier, Option, SetMultimap, SyncStream, Terminator, UUID } from "@opendaw/lib-std";
|
|
2
2
|
import { RenderQuantum } from "@opendaw/lib-dsp";
|
|
3
3
|
import { Communicator, Messenger } from "@opendaw/lib-runtime";
|
|
4
4
|
import { EngineSettingsSchema, EngineStateSchema, ExportStemsConfiguration, PERF_BUFFER_SIZE, PreferencesHost } from "@opendaw/studio-adapters";
|
|
5
5
|
import { SyncSource } from "@opendaw/lib-box";
|
|
6
6
|
import { AnimationFrame } from "@opendaw/lib-dom";
|
|
7
|
+
import { MonitoringRouter } from "./MonitoringRouter";
|
|
7
8
|
import { MIDIReceiver } from "./midi";
|
|
8
9
|
import { HRClockWorker } from "./HRClockWorker";
|
|
9
10
|
export class EngineWorklet extends AudioWorkletNode {
|
|
@@ -34,8 +35,7 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
|
34
35
|
#consecutiveOverloadCount = 0;
|
|
35
36
|
#lastCpuLoadUpdate = 0;
|
|
36
37
|
#maxMsSinceLastUpdate = 0;
|
|
37
|
-
#
|
|
38
|
-
#monitoringSources = new Map();
|
|
38
|
+
#monitoringRouter = null;
|
|
39
39
|
constructor(context, project, exportConfiguration, options) {
|
|
40
40
|
const numberOfChannels = ExportStemsConfiguration.countStems(Option.wrap(exportConfiguration)) * 2;
|
|
41
41
|
const budgetMs = (RenderQuantum / context.sampleRate) * 1000;
|
|
@@ -54,8 +54,8 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
|
54
54
|
const controlFlagsSAB = new SharedArrayBuffer(4); // 4 bytes minimum
|
|
55
55
|
super(context, "engine-processor", {
|
|
56
56
|
numberOfInputs: 1,
|
|
57
|
-
numberOfOutputs:
|
|
58
|
-
outputChannelCount: [numberOfChannels],
|
|
57
|
+
numberOfOutputs: 2,
|
|
58
|
+
outputChannelCount: [numberOfChannels, 8],
|
|
59
59
|
processorOptions: {
|
|
60
60
|
syncStreamBuffer: reader.buffer,
|
|
61
61
|
controlFlagsBuffer: controlFlagsSAB,
|
|
@@ -111,6 +111,7 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
|
111
111
|
}
|
|
112
112
|
terminate() { dispatcher.dispatchAndForget(this.terminate); }
|
|
113
113
|
}));
|
|
114
|
+
this.#monitoringRouter = this.#terminator.own(new MonitoringRouter(this, this.#commands));
|
|
114
115
|
const { port, sab } = this.#terminator.own(MIDIReceiver.create(() => context instanceof AudioContext ? context.outputLatency * 1000 : 20, (deviceId, data, relativeTimeInMs) => this.#project.receivedMIDIFromEngine(deviceId, data, relativeTimeInMs)));
|
|
115
116
|
this.#commands.setupMIDI(port, sab);
|
|
116
117
|
Communicator.executor(messenger.channel("engine-to-client"), {
|
|
@@ -230,49 +231,11 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
|
230
231
|
this.#deviceMessageListeners.add(uuid, listener);
|
|
231
232
|
return { terminate: () => this.#deviceMessageListeners.remove(uuid, listener) };
|
|
232
233
|
}
|
|
233
|
-
registerMonitoringSource(uuid, node, numChannels) {
|
|
234
|
-
this.#
|
|
235
|
-
this.#rebuildMonitoringMerger();
|
|
234
|
+
registerMonitoringSource(uuid, node, numChannels, destinationNode) {
|
|
235
|
+
this.#monitoringRouter.registerSource(uuid, node, numChannels, destinationNode);
|
|
236
236
|
}
|
|
237
237
|
unregisterMonitoringSource(uuid) {
|
|
238
|
-
|
|
239
|
-
const entry = this.#monitoringSources.get(key);
|
|
240
|
-
if (isDefined(entry)) {
|
|
241
|
-
entry.node.disconnect();
|
|
242
|
-
this.#monitoringSources.delete(key);
|
|
243
|
-
}
|
|
244
|
-
this.#rebuildMonitoringMerger();
|
|
245
|
-
}
|
|
246
|
-
#rebuildMonitoringMerger() {
|
|
247
|
-
if (isDefined(this.#channelMerger)) {
|
|
248
|
-
this.#channelMerger.disconnect();
|
|
249
|
-
this.#channelMerger = null;
|
|
250
|
-
}
|
|
251
|
-
if (this.#monitoringSources.size === 0) {
|
|
252
|
-
this.#commands.updateMonitoringMap([]);
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
let totalChannels = 0;
|
|
256
|
-
for (const { numChannels } of this.#monitoringSources.values()) {
|
|
257
|
-
totalChannels += numChannels;
|
|
258
|
-
}
|
|
259
|
-
this.#channelMerger = this.context.createChannelMerger(totalChannels);
|
|
260
|
-
this.#channelMerger.connect(this);
|
|
261
|
-
const map = [];
|
|
262
|
-
let channel = 0;
|
|
263
|
-
for (const [uuidString, { node, numChannels }] of this.#monitoringSources) {
|
|
264
|
-
const uuid = UUID.parse(uuidString);
|
|
265
|
-
const splitter = this.context.createChannelSplitter(numChannels);
|
|
266
|
-
node.connect(splitter);
|
|
267
|
-
const channels = [];
|
|
268
|
-
for (let i = 0; i < numChannels; i++) {
|
|
269
|
-
splitter.connect(this.#channelMerger, i, channel);
|
|
270
|
-
channels.push(channel);
|
|
271
|
-
channel++;
|
|
272
|
-
}
|
|
273
|
-
map.push({ uuid, channels });
|
|
274
|
-
}
|
|
275
|
-
this.#commands.updateMonitoringMap(map);
|
|
238
|
+
this.#monitoringRouter.unregisterSource(uuid);
|
|
276
239
|
}
|
|
277
240
|
#updateCpuLoad(budgetMs, project) {
|
|
278
241
|
while (this.#lastPerfReadIndex !== this.#perfIndex) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Terminable, UUID } from "@opendaw/lib-std";
|
|
2
|
+
import { EngineCommands } from "@opendaw/studio-adapters";
|
|
3
|
+
export declare class MonitoringRouter implements Terminable {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(worklet: AudioWorkletNode, commands: EngineCommands);
|
|
6
|
+
registerSource(uuid: UUID.Bytes, sourceNode: AudioNode, numChannels: 1 | 2, destinationNode: AudioNode): void;
|
|
7
|
+
unregisterSource(uuid: UUID.Bytes): void;
|
|
8
|
+
terminate(): void;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=MonitoringRouter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MonitoringRouter.d.ts","sourceRoot":"","sources":["../src/MonitoringRouter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,UAAU,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACtF,OAAO,EAAqB,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAW3E,qBAAa,gBAAiB,YAAW,UAAU;;gBAUnC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,cAAc;IAQ/D,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,GAAG,CAAC,EAAE,eAAe,EAAE,SAAS,GAAG,IAAI;IAK7G,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI;IAuDxC,SAAS,IAAI,IAAI;CAWpB"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { isDefined, UUID } from "@opendaw/lib-std";
|
|
2
|
+
const MAX_MONITORING_CHANNELS = 8;
|
|
3
|
+
export class MonitoringRouter {
|
|
4
|
+
#context;
|
|
5
|
+
#worklet;
|
|
6
|
+
#commands;
|
|
7
|
+
#splitter;
|
|
8
|
+
#sources = UUID.newSet(entry => entry.uuid);
|
|
9
|
+
#inputMerger = null;
|
|
10
|
+
#outputMergers = [];
|
|
11
|
+
constructor(worklet, commands) {
|
|
12
|
+
this.#context = worklet.context;
|
|
13
|
+
this.#worklet = worklet;
|
|
14
|
+
this.#commands = commands;
|
|
15
|
+
this.#splitter = this.#context.createChannelSplitter(MAX_MONITORING_CHANNELS);
|
|
16
|
+
worklet.connect(this.#splitter, 1);
|
|
17
|
+
}
|
|
18
|
+
registerSource(uuid, sourceNode, numChannels, destinationNode) {
|
|
19
|
+
this.#sources.add({ uuid, sourceNode, numChannels, destinationNode }, true);
|
|
20
|
+
this.#rebuild();
|
|
21
|
+
}
|
|
22
|
+
unregisterSource(uuid) {
|
|
23
|
+
this.#sources.removeByKeyIfExist(uuid);
|
|
24
|
+
this.#rebuild();
|
|
25
|
+
}
|
|
26
|
+
#rebuild() {
|
|
27
|
+
if (isDefined(this.#inputMerger)) {
|
|
28
|
+
this.#inputMerger.disconnect();
|
|
29
|
+
this.#inputMerger = null;
|
|
30
|
+
}
|
|
31
|
+
for (const merger of this.#outputMergers) {
|
|
32
|
+
merger.disconnect();
|
|
33
|
+
}
|
|
34
|
+
this.#outputMergers = [];
|
|
35
|
+
if (this.#sources.isEmpty()) {
|
|
36
|
+
this.#commands.updateMonitoringMap([]);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
let totalChannels = 0;
|
|
40
|
+
for (const { numChannels } of this.#sources) {
|
|
41
|
+
totalChannels += numChannels;
|
|
42
|
+
}
|
|
43
|
+
if (totalChannels > MAX_MONITORING_CHANNELS) {
|
|
44
|
+
console.warn(`MonitoringRouter: ${totalChannels} channels requested, max is ${MAX_MONITORING_CHANNELS}. Some sources will not receive effects monitoring.`);
|
|
45
|
+
}
|
|
46
|
+
const usedChannels = Math.min(totalChannels, MAX_MONITORING_CHANNELS);
|
|
47
|
+
this.#inputMerger = this.#context.createChannelMerger(usedChannels);
|
|
48
|
+
this.#inputMerger.connect(this.#worklet);
|
|
49
|
+
const map = [];
|
|
50
|
+
let channel = 0;
|
|
51
|
+
for (const { uuid, sourceNode, numChannels, destinationNode } of this.#sources) {
|
|
52
|
+
if (channel + numChannels > MAX_MONITORING_CHANNELS) {
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
const inputSplitter = this.#context.createChannelSplitter(numChannels);
|
|
56
|
+
sourceNode.connect(inputSplitter);
|
|
57
|
+
const channels = [];
|
|
58
|
+
for (let i = 0; i < numChannels; i++) {
|
|
59
|
+
inputSplitter.connect(this.#inputMerger, i, channel);
|
|
60
|
+
channels.push(channel);
|
|
61
|
+
channel++;
|
|
62
|
+
}
|
|
63
|
+
map.push({ uuid, channels });
|
|
64
|
+
const outputMerger = this.#context.createChannelMerger(2);
|
|
65
|
+
if (numChannels === 2) {
|
|
66
|
+
this.#splitter.connect(outputMerger, channels[0], 0);
|
|
67
|
+
this.#splitter.connect(outputMerger, channels[1], 1);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
this.#splitter.connect(outputMerger, channels[0], 0);
|
|
71
|
+
this.#splitter.connect(outputMerger, channels[0], 1);
|
|
72
|
+
}
|
|
73
|
+
outputMerger.connect(destinationNode);
|
|
74
|
+
this.#outputMergers.push(outputMerger);
|
|
75
|
+
}
|
|
76
|
+
this.#commands.updateMonitoringMap(map);
|
|
77
|
+
}
|
|
78
|
+
terminate() {
|
|
79
|
+
if (isDefined(this.#inputMerger)) {
|
|
80
|
+
this.#inputMerger.disconnect();
|
|
81
|
+
this.#inputMerger = null;
|
|
82
|
+
}
|
|
83
|
+
for (const merger of this.#outputMergers) {
|
|
84
|
+
merger.disconnect();
|
|
85
|
+
}
|
|
86
|
+
this.#outputMergers = [];
|
|
87
|
+
this.#sources.clear();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -19,6 +19,16 @@ export declare class CaptureAudio extends Capture<CaptureAudioBox> {
|
|
|
19
19
|
get streamMediaTrack(): Option<MediaStreamTrack>;
|
|
20
20
|
get outputNode(): Option<AudioNode>;
|
|
21
21
|
get effectiveChannelCount(): number;
|
|
22
|
+
get monitorGainNode(): GainNode;
|
|
23
|
+
get monitorPanNode(): StereoPannerNode;
|
|
24
|
+
get monitorVolumeDb(): number;
|
|
25
|
+
set monitorVolumeDb(value: number);
|
|
26
|
+
get monitorPan(): number;
|
|
27
|
+
set monitorPan(value: number);
|
|
28
|
+
get monitorMuted(): boolean;
|
|
29
|
+
set monitorMuted(value: boolean);
|
|
30
|
+
get monitorOutputDeviceId(): Option<string>;
|
|
31
|
+
setMonitorOutputDevice(deviceId: Option<string>): Promise<void>;
|
|
22
32
|
prepareRecording(): Promise<void>;
|
|
23
33
|
startRecording(): Terminable;
|
|
24
34
|
}
|
|
@@ -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;AAK/C,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAE/C,qBAAa,YAAa,SAAQ,OAAO,CAAC,eAAe,CAAC;;
|
|
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;;gBAsB1C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe;IA+CjG,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,CAAuD;IAC1F,IAAI,qBAAqB,IAAI,MAAM,CAA6C;IAChF,IAAI,eAAe,IAAI,QAAQ,CAA+B;IAC9D,IAAI,cAAc,IAAI,gBAAgB,CAA8B;IACpE,IAAI,eAAe,IAAI,MAAM,CAA+B;IAC5D,IAAI,eAAe,CAAC,KAAK,EAAE,MAAM,EAGhC;IACD,IAAI,UAAU,IAAI,MAAM,CAA0B;IAClD,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,EAG3B;IACD,IAAI,YAAY,IAAI,OAAO,CAA4B;IACvD,IAAI,YAAY,CAAC,KAAK,EAAE,OAAO,EAG9B;IACD,IAAI,qBAAqB,IAAI,MAAM,CAAC,MAAM,CAAC,CAAqC;IAE1E,sBAAsB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAoC/D,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IA4BvC,cAAc,IAAI,UAAU;CA6H/B"}
|
|
@@ -8,29 +8,45 @@ import { RenderQuantum } from "../RenderQuantum";
|
|
|
8
8
|
export class CaptureAudio extends Capture {
|
|
9
9
|
#stream;
|
|
10
10
|
#streamGenerator;
|
|
11
|
+
#monitorGainNode;
|
|
12
|
+
#monitorPanNode;
|
|
11
13
|
#monitoringMode = "off";
|
|
12
14
|
#requestChannels = Option.None;
|
|
13
15
|
#gainDb = 0.0;
|
|
16
|
+
#monitorVolumeDb = 0.0;
|
|
17
|
+
#monitorPan = 0.0;
|
|
18
|
+
#monitorMuted = false;
|
|
14
19
|
#audioChain = null;
|
|
15
20
|
#preparedWorklet = null;
|
|
21
|
+
#monitorOutputDeviceId = Option.None;
|
|
22
|
+
#monitorAudioElement = null;
|
|
23
|
+
#monitorStreamDest = null;
|
|
16
24
|
constructor(manager, audioUnitBox, captureAudioBox) {
|
|
17
25
|
super(manager, audioUnitBox, captureAudioBox);
|
|
26
|
+
const { audioContext } = this.manager.project.env;
|
|
27
|
+
this.#monitorGainNode = audioContext.createGain();
|
|
28
|
+
this.#monitorGainNode.gain.value = dbToGain(this.#monitorVolumeDb);
|
|
29
|
+
this.#monitorPanNode = audioContext.createStereoPanner();
|
|
30
|
+
this.#monitorPanNode.pan.value = this.#monitorPan;
|
|
31
|
+
this.#monitorGainNode.connect(this.#monitorPanNode);
|
|
18
32
|
this.#stream = new MutableObservableOption();
|
|
19
33
|
this.#streamGenerator = Promises.sequentialize(() => this.#updateStream());
|
|
20
|
-
this.ownAll(
|
|
34
|
+
this.ownAll(Terminable.create(() => {
|
|
35
|
+
this.#disconnectMonitoring();
|
|
36
|
+
if (isDefined(this.#monitorAudioElement)) {
|
|
37
|
+
this.#monitorAudioElement.pause();
|
|
38
|
+
this.#monitorAudioElement.srcObject = null;
|
|
39
|
+
}
|
|
40
|
+
this.#monitorGainNode.disconnect();
|
|
41
|
+
this.#monitorPanNode.disconnect();
|
|
42
|
+
}), captureAudioBox.requestChannels.catchupAndSubscribe(owner => {
|
|
21
43
|
const channels = owner.getValue();
|
|
22
44
|
this.#requestChannels = channels === 1 || channels === 2 ? Option.wrap(channels) : Option.None;
|
|
23
45
|
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
|
-
}
|
|
30
46
|
}), captureAudioBox.gainDb.catchupAndSubscribe(owner => {
|
|
31
47
|
this.#gainDb = owner.getValue();
|
|
32
48
|
if (isDefined(this.#audioChain)) {
|
|
33
|
-
this.#audioChain.
|
|
49
|
+
this.#audioChain.recordGainNode.gain.value = dbToGain(this.#gainDb);
|
|
34
50
|
}
|
|
35
51
|
}), captureAudioBox.deviceId.catchupAndSubscribe(async () => {
|
|
36
52
|
if (this.armed.getValue()) {
|
|
@@ -71,8 +87,62 @@ export class CaptureAudio extends Capture {
|
|
|
71
87
|
get streamMediaTrack() {
|
|
72
88
|
return this.#stream.flatMap(stream => Option.wrap(stream.getAudioTracks().at(0)));
|
|
73
89
|
}
|
|
74
|
-
get outputNode() { return Option.wrap(this.#audioChain?.
|
|
90
|
+
get outputNode() { return Option.wrap(this.#audioChain?.recordGainNode); }
|
|
75
91
|
get effectiveChannelCount() { return this.#audioChain?.channelCount ?? 1; }
|
|
92
|
+
get monitorGainNode() { return this.#monitorGainNode; }
|
|
93
|
+
get monitorPanNode() { return this.#monitorPanNode; }
|
|
94
|
+
get monitorVolumeDb() { return this.#monitorVolumeDb; }
|
|
95
|
+
set monitorVolumeDb(value) {
|
|
96
|
+
this.#monitorVolumeDb = value;
|
|
97
|
+
this.#monitorGainNode.gain.value = this.#monitorMuted ? 0 : dbToGain(this.#monitorVolumeDb);
|
|
98
|
+
}
|
|
99
|
+
get monitorPan() { return this.#monitorPan; }
|
|
100
|
+
set monitorPan(value) {
|
|
101
|
+
this.#monitorPan = value;
|
|
102
|
+
this.#monitorPanNode.pan.value = value;
|
|
103
|
+
}
|
|
104
|
+
get monitorMuted() { return this.#monitorMuted; }
|
|
105
|
+
set monitorMuted(value) {
|
|
106
|
+
this.#monitorMuted = value;
|
|
107
|
+
this.#monitorGainNode.gain.value = value ? 0 : dbToGain(this.#monitorVolumeDb);
|
|
108
|
+
}
|
|
109
|
+
get monitorOutputDeviceId() { return this.#monitorOutputDeviceId; }
|
|
110
|
+
async setMonitorOutputDevice(deviceId) {
|
|
111
|
+
const oldDestination = this.#monitorDestination();
|
|
112
|
+
this.#monitorOutputDeviceId = deviceId;
|
|
113
|
+
if (isDefined(this.#monitorAudioElement)) {
|
|
114
|
+
this.#monitorAudioElement.pause();
|
|
115
|
+
this.#monitorAudioElement.srcObject = null;
|
|
116
|
+
this.#monitorAudioElement = null;
|
|
117
|
+
}
|
|
118
|
+
if (isDefined(this.#monitorStreamDest)) {
|
|
119
|
+
this.#monitorStreamDest.disconnect();
|
|
120
|
+
this.#monitorStreamDest = null;
|
|
121
|
+
}
|
|
122
|
+
if (deviceId.nonEmpty()) {
|
|
123
|
+
const { audioContext } = this.manager.project.env;
|
|
124
|
+
this.#monitorStreamDest = audioContext.createMediaStreamDestination();
|
|
125
|
+
const audio = new Audio();
|
|
126
|
+
audio.srcObject = this.#monitorStreamDest.stream;
|
|
127
|
+
try {
|
|
128
|
+
await audio.setSinkId(deviceId.unwrap());
|
|
129
|
+
await audio.play();
|
|
130
|
+
this.#monitorAudioElement = audio;
|
|
131
|
+
}
|
|
132
|
+
catch (reason) {
|
|
133
|
+
audio.srcObject = null;
|
|
134
|
+
this.#monitorStreamDest.disconnect();
|
|
135
|
+
this.#monitorStreamDest = null;
|
|
136
|
+
this.#monitorOutputDeviceId = Option.None;
|
|
137
|
+
RuntimeNotifier.info({ headline: "Output Device Error", message: `${reason}` });
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (this.#monitoringMode !== "off" && isDefined(this.#audioChain)) {
|
|
142
|
+
this.#monitorPanNode.disconnect(oldDestination);
|
|
143
|
+
this.#monitorPanNode.connect(this.#monitorDestination());
|
|
144
|
+
}
|
|
145
|
+
}
|
|
76
146
|
async prepareRecording() {
|
|
77
147
|
const { project } = this.manager;
|
|
78
148
|
const { env: { audioContext, audioWorklets, sampleManager, sampleService } } = project;
|
|
@@ -92,12 +162,12 @@ export class CaptureAudio extends Capture {
|
|
|
92
162
|
if (!isDefined(audioChain)) {
|
|
93
163
|
return Promise.reject("No audio chain available for recording.");
|
|
94
164
|
}
|
|
95
|
-
const {
|
|
165
|
+
const { recordGainNode, channelCount } = audioChain;
|
|
96
166
|
const recordingWorklet = audioWorklets.createRecording(channelCount, RenderQuantum);
|
|
97
167
|
recordingWorklet.bpm = project.timelineBox.bpm.getValue();
|
|
98
168
|
recordingWorklet.sampleService = sampleService;
|
|
99
169
|
sampleManager.record(recordingWorklet);
|
|
100
|
-
|
|
170
|
+
recordGainNode.connect(recordingWorklet);
|
|
101
171
|
this.#preparedWorklet = recordingWorklet;
|
|
102
172
|
}
|
|
103
173
|
startRecording() {
|
|
@@ -110,10 +180,10 @@ export class CaptureAudio extends Capture {
|
|
|
110
180
|
return Terminable.Empty;
|
|
111
181
|
}
|
|
112
182
|
this.#preparedWorklet = null;
|
|
113
|
-
const {
|
|
183
|
+
const { recordGainNode } = audioChain;
|
|
114
184
|
return RecordAudio.start({
|
|
115
185
|
recordingWorklet,
|
|
116
|
-
sourceNode:
|
|
186
|
+
sourceNode: recordGainNode,
|
|
117
187
|
sampleManager,
|
|
118
188
|
project,
|
|
119
189
|
capture: this,
|
|
@@ -157,47 +227,51 @@ export class CaptureAudio extends Capture {
|
|
|
157
227
|
});
|
|
158
228
|
}
|
|
159
229
|
#stopStream() {
|
|
230
|
+
this.#disconnectMonitoring();
|
|
160
231
|
this.#destroyAudioChain();
|
|
161
232
|
this.#stream.clear(stream => stream.getAudioTracks().forEach(track => track.stop()));
|
|
162
233
|
}
|
|
163
234
|
#rebuildAudioChain(stream) {
|
|
164
|
-
|
|
235
|
+
this.#disconnectMonitoring();
|
|
165
236
|
this.#destroyAudioChain();
|
|
166
237
|
const { audioContext } = this.manager.project.env;
|
|
167
238
|
const sourceNode = audioContext.createMediaStreamSource(stream);
|
|
168
|
-
const
|
|
169
|
-
|
|
239
|
+
const recordGainNode = audioContext.createGain();
|
|
240
|
+
recordGainNode.gain.value = dbToGain(this.#gainDb);
|
|
170
241
|
const streamChannelCount = Math.min(stream.getAudioTracks().at(0)?.getSettings().channelCount ?? 2, 2);
|
|
171
242
|
const channelCount = this.#requestChannels.unwrapOrElse(streamChannelCount);
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
sourceNode.connect(
|
|
175
|
-
this.#audioChain = { sourceNode,
|
|
176
|
-
|
|
177
|
-
this.#connectMonitoring();
|
|
178
|
-
}
|
|
243
|
+
recordGainNode.channelCount = channelCount;
|
|
244
|
+
recordGainNode.channelCountMode = "explicit";
|
|
245
|
+
sourceNode.connect(recordGainNode);
|
|
246
|
+
this.#audioChain = { sourceNode, recordGainNode, channelCount };
|
|
247
|
+
this.#connectMonitoring();
|
|
179
248
|
}
|
|
180
249
|
#destroyAudioChain() {
|
|
181
250
|
if (isDefined(this.#audioChain)) {
|
|
182
|
-
const { sourceNode,
|
|
251
|
+
const { sourceNode, recordGainNode } = this.#audioChain;
|
|
183
252
|
sourceNode.disconnect();
|
|
184
|
-
|
|
253
|
+
recordGainNode.disconnect();
|
|
185
254
|
this.#audioChain = null;
|
|
186
255
|
}
|
|
187
256
|
}
|
|
257
|
+
#monitorDestination() {
|
|
258
|
+
return this.#monitorStreamDest ?? this.manager.project.env.audioContext.destination;
|
|
259
|
+
}
|
|
188
260
|
#connectMonitoring() {
|
|
189
261
|
if (!isDefined(this.#audioChain)) {
|
|
190
262
|
return;
|
|
191
263
|
}
|
|
264
|
+
const { sourceNode, channelCount } = this.#audioChain;
|
|
192
265
|
switch (this.#monitoringMode) {
|
|
193
266
|
case "off":
|
|
194
267
|
break;
|
|
195
268
|
case "direct":
|
|
196
|
-
|
|
269
|
+
sourceNode.connect(this.#monitorGainNode);
|
|
270
|
+
this.#monitorPanNode.connect(this.#monitorDestination());
|
|
197
271
|
break;
|
|
198
272
|
case "effects":
|
|
199
|
-
|
|
200
|
-
|
|
273
|
+
this.manager.project.engine.registerMonitoringSource(this.audioUnitBox.address.uuid, sourceNode, channelCount, this.#monitorGainNode);
|
|
274
|
+
this.#monitorPanNode.connect(this.#monitorDestination());
|
|
201
275
|
break;
|
|
202
276
|
}
|
|
203
277
|
}
|
|
@@ -209,11 +283,12 @@ export class CaptureAudio extends Capture {
|
|
|
209
283
|
case "off":
|
|
210
284
|
break;
|
|
211
285
|
case "direct":
|
|
212
|
-
this.#audioChain.
|
|
286
|
+
this.#audioChain.sourceNode.disconnect(this.#monitorGainNode);
|
|
287
|
+
this.#monitorPanNode.disconnect(this.#monitorDestination());
|
|
213
288
|
break;
|
|
214
289
|
case "effects":
|
|
215
|
-
this.#audioChain.gainNode.disconnect();
|
|
216
290
|
this.manager.project.engine.unregisterMonitoringSource(this.audioUnitBox.address.uuid);
|
|
291
|
+
this.#monitorPanNode.disconnect(this.#monitorDestination());
|
|
217
292
|
break;
|
|
218
293
|
}
|
|
219
294
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecordAudio.d.ts","sourceRoot":"","sources":["../../src/capture/RecordAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAMH,UAAU,EAIb,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAa,mBAAmB,EAA2B,MAAM,0BAA0B,CAAA;AAClG,OAAO,EAAC,OAAO,EAAC,MAAM,YAAY,CAAA;AAClC,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAIjC,yBAAiB,WAAW,CAAC;IACzB,KAAK,kBAAkB,GAAG;QACtB,gBAAgB,EAAE,gBAAgB,CAAA;QAClC,UAAU,EAAE,SAAS,CAAA;QACrB,aAAa,EAAE,mBAAmB,CAAA;QAClC,OAAO,EAAE,OAAO,CAAA;QAChB,OAAO,EAAE,OAAO,CAAA;QAChB,aAAa,EAAE,MAAM,CAAA;KACxB,CAAA;IAOD,MAAM,CAAC,MAAM,KAAK,GACd,kFAAgF,kBAAkB,KAChG,
|
|
1
|
+
{"version":3,"file":"RecordAudio.d.ts","sourceRoot":"","sources":["../../src/capture/RecordAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAMH,UAAU,EAIb,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAa,mBAAmB,EAA2B,MAAM,0BAA0B,CAAA;AAClG,OAAO,EAAC,OAAO,EAAC,MAAM,YAAY,CAAA;AAClC,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAIjC,yBAAiB,WAAW,CAAC;IACzB,KAAK,kBAAkB,GAAG;QACtB,gBAAgB,EAAE,gBAAgB,CAAA;QAClC,UAAU,EAAE,SAAS,CAAA;QACrB,aAAa,EAAE,mBAAmB,CAAA;QAClC,OAAO,EAAE,OAAO,CAAA;QAChB,OAAO,EAAE,OAAO,CAAA;QAChB,aAAa,EAAE,MAAM,CAAA;KACxB,CAAA;IAOD,MAAM,CAAC,MAAM,KAAK,GACd,kFAAgF,kBAAkB,KAChG,UAsNL,CAAA;;CACJ"}
|
|
@@ -124,8 +124,9 @@ export var RecordAudio;
|
|
|
124
124
|
pointer.refer(newFileBox.transientMarkers);
|
|
125
125
|
}
|
|
126
126
|
oldFileBox.delete();
|
|
127
|
-
});
|
|
127
|
+
}, false);
|
|
128
128
|
});
|
|
129
|
+
editing.mark();
|
|
129
130
|
};
|
|
130
131
|
terminator.ownAll(Terminable.create(() => {
|
|
131
132
|
tryCatch(() => sourceNode.disconnect(recordingWorklet));
|
|
@@ -178,10 +179,17 @@ export var RecordAudio;
|
|
|
178
179
|
editing.modify(() => {
|
|
179
180
|
currentTake.ifSome(take => {
|
|
180
181
|
const actualDurationInSeconds = take.regionBox.duration.getValue();
|
|
182
|
+
if (actualDurationInSeconds <= 0) {
|
|
183
|
+
take.regionBox.delete();
|
|
184
|
+
currentTake = Option.None;
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
181
187
|
finalizeTake(take, actualDurationInSeconds);
|
|
182
188
|
currentWaveformOffset += actualDurationInSeconds;
|
|
183
189
|
});
|
|
184
|
-
|
|
190
|
+
if (currentTake.nonEmpty()) {
|
|
191
|
+
startNewTake(loopFrom);
|
|
192
|
+
}
|
|
185
193
|
}, false);
|
|
186
194
|
}
|
|
187
195
|
lastPosition = currentPosition;
|
|
@@ -37,7 +37,7 @@ export class Recording {
|
|
|
37
37
|
if (isRecording.getValue() || isCountingIn.getValue()) {
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
|
-
editing.modify(() => terminator.terminate()); // finalizes recording
|
|
40
|
+
editing.modify(() => terminator.terminate(), false); // finalizes recording
|
|
41
41
|
this.#isRecording = false;
|
|
42
42
|
};
|
|
43
43
|
terminator.ownAll(engine.isRecording.subscribe(stop), engine.isCountingIn.subscribe(stop), Terminable.create(() => Recording.#instance = Option.None));
|