@opendaw/studio-core 0.0.101 → 0.0.103

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.
Files changed (75) hide show
  1. package/dist/AssetService.js +2 -2
  2. package/dist/EffectFactories.d.ts +2 -0
  3. package/dist/EffectFactories.d.ts.map +1 -1
  4. package/dist/EffectFactories.js +5 -0
  5. package/dist/Engine.d.ts +3 -0
  6. package/dist/Engine.d.ts.map +1 -1
  7. package/dist/EngineFacade.d.ts +3 -0
  8. package/dist/EngineFacade.d.ts.map +1 -1
  9. package/dist/EngineFacade.js +20 -2
  10. package/dist/EngineWorklet.d.ts +3 -0
  11. package/dist/EngineWorklet.d.ts.map +1 -1
  12. package/dist/EngineWorklet.js +97 -9
  13. package/dist/OfflineEngineRenderer.d.ts +3 -1
  14. package/dist/OfflineEngineRenderer.d.ts.map +1 -1
  15. package/dist/OfflineEngineRenderer.js +11 -2
  16. package/dist/StudioPreferences.d.ts +1 -0
  17. package/dist/StudioPreferences.d.ts.map +1 -1
  18. package/dist/StudioSettings.d.ts +1 -0
  19. package/dist/StudioSettings.d.ts.map +1 -1
  20. package/dist/StudioSettings.js +4 -2
  21. package/dist/capture/CaptureAudio.d.ts +3 -1
  22. package/dist/capture/CaptureAudio.d.ts.map +1 -1
  23. package/dist/capture/CaptureAudio.js +43 -18
  24. package/dist/capture/CaptureMidi.js +1 -1
  25. package/dist/capture/MonitoringMode.d.ts +2 -0
  26. package/dist/capture/MonitoringMode.d.ts.map +1 -0
  27. package/dist/capture/MonitoringMode.js +1 -0
  28. package/dist/capture/RecordAutomation.d.ts +6 -0
  29. package/dist/capture/RecordAutomation.d.ts.map +1 -0
  30. package/dist/capture/RecordAutomation.js +139 -0
  31. package/dist/capture/Recording.d.ts +3 -0
  32. package/dist/capture/Recording.d.ts.map +1 -1
  33. package/dist/capture/Recording.js +16 -36
  34. package/dist/capture/index.d.ts +2 -0
  35. package/dist/capture/index.d.ts.map +1 -1
  36. package/dist/capture/index.js +2 -0
  37. package/dist/dawproject/DawProjectImporter.d.ts.map +1 -1
  38. package/dist/dawproject/DawProjectImporter.js +4 -0
  39. package/dist/offline-engine.js +1 -1
  40. package/dist/offline-engine.js.map +4 -4
  41. package/dist/processors.js +9 -9
  42. package/dist/processors.js.map +4 -4
  43. package/dist/project/Project.d.ts +2 -0
  44. package/dist/project/Project.d.ts.map +1 -1
  45. package/dist/project/Project.js +32 -12
  46. package/dist/project/ProjectApi.d.ts +3 -1
  47. package/dist/project/ProjectApi.d.ts.map +1 -1
  48. package/dist/project/ProjectApi.js +30 -17
  49. package/dist/project/ProjectMigration.d.ts.map +1 -1
  50. package/dist/project/ProjectMigration.js +3 -2
  51. package/dist/project/migration/MigrateNeuralAmpDeviceBox.d.ts +4 -0
  52. package/dist/project/migration/MigrateNeuralAmpDeviceBox.d.ts.map +1 -0
  53. package/dist/project/migration/MigrateNeuralAmpDeviceBox.js +29 -0
  54. package/dist/project/migration/index.d.ts +1 -0
  55. package/dist/project/migration/index.d.ts.map +1 -1
  56. package/dist/project/migration/index.js +1 -0
  57. package/dist/ui/clipboard/ClipboardManager.d.ts.map +1 -1
  58. package/dist/ui/clipboard/ClipboardManager.js +54 -8
  59. package/dist/ui/clipboard/ClipboardUtils.js +3 -3
  60. package/dist/ui/clipboard/types/AudioUnitsClipboardHandler.d.ts.map +1 -1
  61. package/dist/ui/clipboard/types/AudioUnitsClipboardHandler.js +6 -0
  62. package/dist/ui/clipboard/types/DevicesClipboardHandler.js +1 -1
  63. package/dist/ui/clipboard/types/RegionsClipboardHandler.d.ts.map +1 -1
  64. package/dist/ui/clipboard/types/RegionsClipboardHandler.js +4 -0
  65. package/dist/ui/menu/MenuItems.d.ts +2 -2
  66. package/dist/ui/menu/MenuItems.d.ts.map +1 -1
  67. package/dist/ui/timeline/RegionClipResolver.d.ts +2 -2
  68. package/dist/ui/timeline/RegionClipResolver.d.ts.map +1 -1
  69. package/dist/ui/timeline/RegionClipResolver.js +40 -37
  70. package/dist/ui/timeline/RegionClipResolver.test.js +400 -0
  71. package/dist/workers-main.js +1 -1
  72. package/dist/workers-main.js.map +3 -3
  73. package/dist/ysync/YService.d.ts.map +1 -1
  74. package/dist/ysync/YService.js +1 -2
  75. package/package.json +15 -15
@@ -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;IAEM,MAAM,UAAU;;;;;;;;;;;;KAYtB,CAAA;IACM,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"}
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"}
@@ -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;
@@ -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;IAE7E,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,OAAO,CAAA;IACtB,IAAI,WAAW,IAAI,iBAAiB,CAAA;IACpC,IAAI,UAAU,IAAI,YAAY,CAAA;IAC9B,IAAI,SAAS,IAAI,MAAM,CAAA;CAC1B"}
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"}
@@ -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;;;IAoBvC,UAAU,CAAC,OAAO,EAAE,aAAa;IAgBjC,aAAa,IAAI,IAAI;IAErB,cAAc,IAAI,IAAI;IAOtB,IAAI,IAAI,IAAI;IACZ,IAAI,CAAC,KAAK,GAAE,OAAe,GAAG,IAAI;IAClC,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IACjC,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAC7C,aAAa,IAAI,IAAI;IAErB,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAwB;IAC7D,IAAI,GAAG,IAAI,eAAe,CAAC,GAAG,CAAC,CAAmB;IAClD,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,iBAAiB,IAAI,eAAe,CAAC,IAAI,CAAC,CAAiC;IAC/E,IAAI,qBAAqB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAqC;IACtF,IAAI,WAAW,IAAI,sBAAsB,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAA2B;IACjG,IAAI,OAAO,IAAI,OAAO,CAAmE;IACzF,IAAI,UAAU,IAAI,MAAM,CAAsF;IAC9G,IAAI,WAAW,IAAI,iBAAiB,CAAiC;IACrE,IAAI,UAAU,IAAI,YAAY,CAAiF;IAC/G,IAAI,SAAS,IAAI,MAAM,CAA8D;IAErF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IAGxC,KAAK,IAAI,IAAI;IACb,KAAK,IAAI,IAAI;IACb,IAAI,IAAI,IAAI;IACZ,cAAc,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAGnD,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAG7E,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IAG5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI;IAGxC,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAGpC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAG1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAI3D,SAAS,IAAI,IAAI;CAIpB"}
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;;;IAqBvC,UAAU,CAAC,OAAO,EAAE,aAAa;IAiBjC,aAAa,IAAI,IAAI;IAErB,cAAc,IAAI,IAAI;IAOtB,IAAI,IAAI,IAAI;IAUZ,IAAI,CAAC,KAAK,GAAE,OAAe,GAAG,IAAI;IAClC,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IACjC,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAC7C,aAAa,IAAI,IAAI;IAErB,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAwB;IAC7D,IAAI,GAAG,IAAI,eAAe,CAAC,GAAG,CAAC,CAAmB;IAClD,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,iBAAiB,IAAI,eAAe,CAAC,IAAI,CAAC,CAAiC;IAC/E,IAAI,qBAAqB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAqC;IACtF,IAAI,WAAW,IAAI,sBAAsB,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAA2B;IACjG,IAAI,OAAO,IAAI,eAAe,CAAC,MAAM,CAAC,CAAuB;IAC7D,IAAI,OAAO,IAAI,OAAO,CAAmE;IACzF,IAAI,UAAU,IAAI,MAAM,CAAsF;IAC9G,IAAI,WAAW,IAAI,iBAAiB,CAAiC;IACrE,IAAI,UAAU,IAAI,YAAY,CAAiF;IAC/G,IAAI,SAAS,IAAI,MAAM,CAA8D;IAErF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IAGxC,KAAK,IAAI,IAAI;IACb,KAAK,IAAI,IAAI;IACb,IAAI,IAAI,IAAI;IACZ,cAAc,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAGnD,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAG7E,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IAG5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI;IAGxC,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAGpC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAG1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAG3D,wBAAwB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI;IAGrF,0BAA0B,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI;IAIlD,SAAS,IAAI,IAAI;CAIpB"}
@@ -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() { this.#worklet.ifSome(worklet => worklet.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();
@@ -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,EACH,sBAAsB,EAEtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAGZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,SAAS,EAAE,GAAG,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAIrD,OAAO,EACH,gBAAgB,EAIhB,cAAc,EAKd,wBAAwB,EACxB,UAAU,EACV,eAAe,EACf,gBAAgB,EACnB,MAAM,0BAA0B,CAAA;AAEjC,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;gBAyBpB,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,OAAO,EAChB,mBAAmB,CAAC,EAAE,wBAAwB,EAC9C,OAAO,CAAC,EAAE,gBAAgB;IA6ItC,IAAI,IAAI,IAAI;IACZ,IAAI,CAAC,KAAK,GAAE,OAAe,GAAG,IAAI;IAClC,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;IAIb,IAAI,IAAI,IAAI;IACZ,cAAc,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAInD,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,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,SAAS,IAAI,IAAI;CAKpB"}
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"}
@@ -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: 0,
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() { this.#commands.play(); }
156
- stop(reset = false) { this.#commands.stop(reset); }
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,5 +1,5 @@
1
1
  import { int, Option, Progress } from "@opendaw/lib-std";
2
- import { AudioData } from "@opendaw/lib-dsp";
2
+ import { AudioData, ppqn } from "@opendaw/lib-dsp";
3
3
  import { ExportStemsConfiguration, OfflineEngineRenderConfig } from "@opendaw/studio-adapters";
4
4
  import { Project } from "./project";
5
5
  export declare class OfflineEngineRenderer {
@@ -14,6 +14,8 @@ export declare class OfflineEngineRenderer {
14
14
  get totalFrames(): int;
15
15
  play(): void;
16
16
  stop(): void;
17
+ setPosition(position: ppqn): void;
18
+ waitForLoading(): Promise<void>;
17
19
  terminate(): void;
18
20
  step(samples: int): Promise<Float32Array[]>;
19
21
  render(config: OfflineEngineRenderConfig, progress: Progress.Handler, abortSignal?: AbortSignal): Promise<AudioData>;
@@ -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,EAIxB,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;WAmHpB,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"}
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,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAEhD,OAAO,EAIH,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,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IAI3B,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAMrC,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"}
@@ -1,7 +1,7 @@
1
1
  import { Errors, isDefined, Option, panic, Terminator, TimeSpan } from "@opendaw/lib-std";
2
2
  import { AudioData } from "@opendaw/lib-dsp";
3
3
  import { Communicator, Messenger, Wait } from "@opendaw/lib-runtime";
4
- import { ExportStemsConfiguration } from "@opendaw/studio-adapters";
4
+ import { EngineStateSchema, ExportStemsConfiguration } from "@opendaw/studio-adapters";
5
5
  import { AudioWorklets } from "./AudioWorklets";
6
6
  import { MIDIReceiver } from "./midi";
7
7
  let workerUrl = Option.None;
@@ -35,7 +35,7 @@ export class OfflineEngineRenderer {
35
35
  });
36
36
  const channel = new MessageChannel();
37
37
  const progressChannel = new MessageChannel();
38
- const syncStreamBuffer = new SharedArrayBuffer(1024);
38
+ const syncStreamBuffer = new SharedArrayBuffer(EngineStateSchema().bytesTotal + 1);
39
39
  const controlFlagsBuffer = new SharedArrayBuffer(4);
40
40
  const terminator = new Terminator();
41
41
  const engineMessenger = Messenger.for(channel.port2);
@@ -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
  });
@@ -149,6 +150,14 @@ export class OfflineEngineRenderer {
149
150
  this.#engineCommands.stop(true);
150
151
  this.#protocol.stop();
151
152
  }
153
+ setPosition(position) {
154
+ this.#engineCommands.setPosition(position);
155
+ }
156
+ async waitForLoading() {
157
+ while (!await this.#engineCommands.queryLoadingComplete()) {
158
+ await Wait.timeSpan(TimeSpan.millis(100));
159
+ }
160
+ }
152
161
  terminate() {
153
162
  this.#terminator.terminate();
154
163
  this.#worker.terminate();
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAwD,CAAA"}
1
+ {"version":3,"file":"StudioPreferences.d.ts","sourceRoot":"","sources":["../src/StudioPreferences.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAwD,CAAA"}
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6D/B,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA"}
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"}
@@ -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
- set isMonitoring(value: boolean);
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;AAM/C,qBAAa,YAAa,SAAQ,OAAO,CAAC,eAAe,CAAC;;gBAe1C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe;IAkCjG,IAAI,YAAY,IAAI,OAAO,CAA4B;IACvD,IAAI,YAAY,CAAC,KAAK,EAAE,OAAO,EAS9B;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;CAsG/B"}
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
- #isMonitoring = false;
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.#isMonitoring; }
44
- set isMonitoring(value) {
45
- if (this.#isMonitoring === value) {
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.#isMonitoring = value;
49
- if (this.#isMonitoring) {
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 wasMonitoring = this.#isMonitoring && isDefined(this.#audioChain);
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 (wasMonitoring || this.#isMonitoring) {
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
- const { audioContext } = this.manager.project.env;
184
- this.#audioChain.gainNode.connect(audioContext.destination);
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
- const { audioContext } = this.manager.project.env;
190
- this.#audioChain.gainNode.disconnect(audioContext.destination);
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
  }