@opendaw/studio-core 0.0.20 → 0.0.21
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/AudioDevices.d.ts +8 -0
- package/dist/AudioDevices.d.ts.map +1 -0
- package/dist/AudioDevices.js +34 -0
- package/dist/MidiDevices.d.ts +12 -0
- package/dist/MidiDevices.d.ts.map +1 -0
- package/dist/MidiDevices.js +92 -0
- package/dist/Project.d.ts +10 -1
- package/dist/Project.d.ts.map +1 -1
- package/dist/Project.js +21 -1
- package/dist/ProjectEnv.d.ts +0 -1
- package/dist/ProjectEnv.d.ts.map +1 -1
- package/dist/capture/Capture.d.ts +1 -1
- package/dist/capture/Capture.d.ts.map +1 -1
- package/dist/capture/CaptureAudio.d.ts +5 -5
- package/dist/capture/CaptureAudio.d.ts.map +1 -1
- package/dist/capture/CaptureAudio.js +14 -14
- package/dist/capture/CaptureMidi.d.ts +2 -2
- package/dist/capture/CaptureMidi.d.ts.map +1 -1
- package/dist/capture/CaptureMidi.js +86 -30
- package/dist/capture/RecordAudio.d.ts +1 -3
- package/dist/capture/RecordAudio.d.ts.map +1 -1
- package/dist/capture/RecordAudio.js +2 -2
- package/dist/capture/RecordMidi.d.ts +1 -3
- package/dist/capture/RecordMidi.d.ts.map +1 -1
- package/dist/capture/RecordMidi.js +4 -4
- package/dist/capture/Recording.js +2 -2
- package/dist/capture/RecordingContext.d.ts +0 -4
- package/dist/capture/RecordingContext.d.ts.map +1 -1
- package/dist/dawproject/DawProject.d.ts.map +1 -1
- package/dist/dawproject/DawProject.js +4 -5
- package/dist/dawproject/DawProjectExporter.test.js +1 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/processors.js +2 -2
- package/dist/processors.js.map +4 -4
- package/dist/workers.js +2 -2
- package/dist/workers.js.map +4 -4
- package/package.json +14 -14
- package/dist/AudioInputDevices.d.ts +0 -8
- package/dist/AudioInputDevices.d.ts.map +0 -1
- package/dist/AudioInputDevices.js +0 -30
@@ -0,0 +1,8 @@
|
|
1
|
+
export declare class AudioDevices {
|
2
|
+
#private;
|
3
|
+
static requestPermission(): Promise<undefined>;
|
4
|
+
static requestStream(constraints: MediaTrackConstraints): Promise<MediaStream>;
|
5
|
+
static updateInputList(): Promise<undefined>;
|
6
|
+
static get inputs(): ReadonlyArray<MediaDeviceInfo>;
|
7
|
+
}
|
8
|
+
//# sourceMappingURL=AudioDevices.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"AudioDevices.d.ts","sourceRoot":"","sources":["../src/AudioDevices.ts"],"names":[],"mappings":"AAIA,qBAAa,YAAY;;WACR,iBAAiB;WAQjB,aAAa,CAAC,WAAW,EAAE,qBAAqB,GAAG,OAAO,CAAC,WAAW,CAAC;WAavE,eAAe;IAY5B,MAAM,KAAK,MAAM,IAAI,aAAa,CAAC,eAAe,CAAC,CAAsB;CAC5E"}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import { Promises } from "@opendaw/lib-runtime";
|
2
|
+
import { Arrays, isInstanceOf, warn } from "@opendaw/lib-std";
|
3
|
+
import { ConstrainDOM } from "@opendaw/lib-dom";
|
4
|
+
export class AudioDevices {
|
5
|
+
static async requestPermission() {
|
6
|
+
const { status, value: stream } = await Promises.tryCatch(navigator.mediaDevices.getUserMedia({ audio: true }));
|
7
|
+
if (status === "rejected") {
|
8
|
+
return warn("Could not request permission.");
|
9
|
+
}
|
10
|
+
stream.getTracks().forEach(track => track.stop());
|
11
|
+
await this.updateInputList();
|
12
|
+
}
|
13
|
+
static async requestStream(constraints) {
|
14
|
+
const { status, value: stream, error } = await Promises.tryCatch(navigator.mediaDevices.getUserMedia({ audio: constraints }));
|
15
|
+
if (status === "rejected") {
|
16
|
+
return warn(isInstanceOf(error, OverconstrainedError) ?
|
17
|
+
error.constraint === "deviceId"
|
18
|
+
? `Could not find device with id: '${ConstrainDOM.resolveString(constraints.deviceId)}'`
|
19
|
+
: error.constraint
|
20
|
+
: String(error));
|
21
|
+
}
|
22
|
+
return stream;
|
23
|
+
}
|
24
|
+
static async updateInputList() {
|
25
|
+
this.#inputs = Arrays.empty();
|
26
|
+
const { status, value: devices } = await Promises.tryCatch(navigator.mediaDevices.enumerateDevices());
|
27
|
+
if (status === "rejected") {
|
28
|
+
return warn("Could not enumerate devices.");
|
29
|
+
}
|
30
|
+
this.#inputs = devices.filter(device => device.kind === "audioinput" && device.deviceId !== "" && device.groupId !== "");
|
31
|
+
}
|
32
|
+
static #inputs = Arrays.empty();
|
33
|
+
static get inputs() { return this.#inputs; }
|
34
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import { MutableObservableValue, ObservableOption, Option } from "@opendaw/lib-std";
|
2
|
+
export declare class MidiDevices {
|
3
|
+
#private;
|
4
|
+
static canRequestMidiAccess(): boolean;
|
5
|
+
static requestPermission(): Promise<undefined>;
|
6
|
+
static get(): ObservableOption<MIDIAccess>;
|
7
|
+
static inputs(): Option<ReadonlyArray<MIDIInput>>;
|
8
|
+
static outputs(): Option<ReadonlyArray<MIDIOutput>>;
|
9
|
+
static panic(): void;
|
10
|
+
static available(): MutableObservableValue<boolean>;
|
11
|
+
}
|
12
|
+
//# sourceMappingURL=MidiDevices.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"MidiDevices.d.ts","sourceRoot":"","sources":["../src/MidiDevices.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,sBAAsB,EAEtB,gBAAgB,EAGhB,MAAM,EAGT,MAAM,kBAAkB,CAAA;AAIzB,qBAAa,WAAW;;IACpB,MAAM,CAAC,oBAAoB,IAAI,OAAO;WAEzB,iBAAiB;IAiB9B,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC,UAAU,CAAC;IAE1C,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAIjD,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAInD,MAAM,CAAC,KAAK,IAAI,IAAI;IAkBpB,MAAM,CAAC,SAAS,IAAI,sBAAsB,CAAC,OAAO,CAAC;CAqCtD"}
|
@@ -0,0 +1,92 @@
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
6
|
+
};
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
9
|
+
};
|
10
|
+
import { Lazy, MutableObservableOption, MutableObservableValue, Notifier, warn } from "@opendaw/lib-std";
|
11
|
+
import { MidiData } from "@opendaw/lib-midi";
|
12
|
+
import { Promises } from "@opendaw/lib-runtime";
|
13
|
+
export class MidiDevices {
|
14
|
+
static canRequestMidiAccess() { return "requestMIDIAccess" in navigator; }
|
15
|
+
static async requestPermission() {
|
16
|
+
if (this.canRequestMidiAccess()) {
|
17
|
+
const { status, value: midiAccess, error } = await Promises.tryCatch(navigator.requestMIDIAccess({ sysex: false }));
|
18
|
+
if (status === "rejected") {
|
19
|
+
console.warn(error);
|
20
|
+
return warn("Could not request MIDI");
|
21
|
+
}
|
22
|
+
const numberOfInputs = midiAccess.inputs.size;
|
23
|
+
const numberOfOutputs = midiAccess.outputs.size;
|
24
|
+
console.debug(`MIDI access granted: ${numberOfInputs} inputs, ${numberOfOutputs} outputs`);
|
25
|
+
this.#midiAccess.wrap(midiAccess);
|
26
|
+
}
|
27
|
+
else {
|
28
|
+
return warn("This browser does not support MIDI");
|
29
|
+
}
|
30
|
+
}
|
31
|
+
static get() { return this.#midiAccess; }
|
32
|
+
static inputs() {
|
33
|
+
return this.get().map(({ inputs }) => Array.from(inputs.values()));
|
34
|
+
}
|
35
|
+
static outputs() {
|
36
|
+
return this.get().map(({ outputs }) => Array.from(outputs.values()));
|
37
|
+
}
|
38
|
+
static panic() {
|
39
|
+
this.get().ifSome((midiAccess) => {
|
40
|
+
for (let note = 0; note < 128; note++) {
|
41
|
+
for (let channel = 0; channel < 16; channel++) {
|
42
|
+
const data = MidiData.noteOff(channel, note);
|
43
|
+
const event = new MessageEvent("midimessage", { data });
|
44
|
+
for (let input of midiAccess.inputs.values()) {
|
45
|
+
input.dispatchEvent(event);
|
46
|
+
}
|
47
|
+
for (let output of midiAccess.outputs.values()) {
|
48
|
+
output.send(data);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
});
|
53
|
+
}
|
54
|
+
static available() {
|
55
|
+
const scope = this;
|
56
|
+
return new class {
|
57
|
+
#notifier = new Notifier();
|
58
|
+
constructor() {
|
59
|
+
const subscription = scope.get().subscribe(option => {
|
60
|
+
if (option.nonEmpty()) {
|
61
|
+
subscription.terminate();
|
62
|
+
this.#notifier.notify(this);
|
63
|
+
} // MIDIAccess cannot be turned off
|
64
|
+
});
|
65
|
+
}
|
66
|
+
setValue(value) {
|
67
|
+
if (!value || scope.#midiAccess.nonEmpty() || scope.#isRequesting) {
|
68
|
+
return;
|
69
|
+
}
|
70
|
+
console.debug("Request MIDI access");
|
71
|
+
scope.#isRequesting = true;
|
72
|
+
scope.requestPermission().finally(() => scope.#isRequesting = false);
|
73
|
+
}
|
74
|
+
getValue() { return scope.#midiAccess.nonEmpty(); }
|
75
|
+
catchupAndSubscribe(observer) {
|
76
|
+
observer(this);
|
77
|
+
return this.#notifier.subscribe(observer);
|
78
|
+
}
|
79
|
+
subscribe(observer) {
|
80
|
+
return this.#notifier.subscribe(observer);
|
81
|
+
}
|
82
|
+
};
|
83
|
+
}
|
84
|
+
static #isRequesting = false;
|
85
|
+
static #midiAccess = new MutableObservableOption();
|
86
|
+
}
|
87
|
+
__decorate([
|
88
|
+
Lazy,
|
89
|
+
__metadata("design:type", Function),
|
90
|
+
__metadata("design:paramtypes", []),
|
91
|
+
__metadata("design:returntype", Object)
|
92
|
+
], MidiDevices, "available", null);
|
package/dist/Project.d.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Terminable, TerminableOwner, Terminator } from "@opendaw/lib-std";
|
1
|
+
import { Procedure, Terminable, TerminableOwner, Terminator } from "@opendaw/lib-std";
|
2
2
|
import { BoxGraph, Editing } from "@opendaw/lib-box";
|
3
3
|
import { AudioBusBox, AudioUnitBox, BoxIO, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
|
4
4
|
import { BoxAdapters, BoxAdaptersContext, ClipSequencing, ParameterFieldAdapters, ProjectDecoder, RootBoxAdapter, SampleManager, TimelineBoxAdapter, UserEditingManager, VertexSelection } from "@opendaw/studio-adapters";
|
@@ -7,6 +7,13 @@ import { ProjectEnv } from "./ProjectEnv";
|
|
7
7
|
import { Mixer } from "./Mixer";
|
8
8
|
import { ProjectApi } from "./ProjectApi";
|
9
9
|
import { CaptureManager } from "./capture/CaptureManager";
|
10
|
+
import { EngineFacade } from "./EngineFacade";
|
11
|
+
import { EngineWorklet } from "./EngineWorklet";
|
12
|
+
import { Worklets } from "./Worklets";
|
13
|
+
export type RestartWorklet = {
|
14
|
+
unload: Procedure<unknown>;
|
15
|
+
load: Procedure<EngineWorklet>;
|
16
|
+
};
|
10
17
|
export declare class Project implements BoxAdaptersContext, Terminable, TerminableOwner {
|
11
18
|
#private;
|
12
19
|
static new(env: ProjectEnv): Project;
|
@@ -27,7 +34,9 @@ export declare class Project implements BoxAdaptersContext, Terminable, Terminab
|
|
27
34
|
readonly parameterFieldAdapters: ParameterFieldAdapters;
|
28
35
|
readonly liveStreamReceiver: LiveStreamReceiver;
|
29
36
|
readonly mixer: Mixer;
|
37
|
+
readonly engine: EngineFacade;
|
30
38
|
private constructor();
|
39
|
+
startAudioWorklet(worklets: Worklets, restart: RestartWorklet): EngineWorklet;
|
31
40
|
own<T extends Terminable>(terminable: T): T;
|
32
41
|
ownAll<T extends Terminable>(...terminables: Array<T>): void;
|
33
42
|
spawn(): Terminator;
|
package/dist/Project.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Project.d.ts","sourceRoot":"","sources":["../src/Project.ts"],"names":[],"mappings":"AAAA,OAAO,
|
1
|
+
{"version":3,"file":"Project.d.ts","sourceRoot":"","sources":["../src/Project.ts"],"names":[],"mappings":"AAAA,OAAO,EAIH,SAAS,EACT,UAAU,EACV,eAAe,EACf,UAAU,EAEb,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,QAAQ,EAAE,OAAO,EAAC,MAAM,kBAAkB,CAAA;AAClD,OAAO,EACH,WAAW,EACX,YAAY,EACZ,KAAK,EAEL,OAAO,EACP,WAAW,EACX,gBAAgB,EACnB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,WAAW,EACX,kBAAkB,EAClB,cAAc,EAGd,sBAAsB,EACtB,cAAc,EACd,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EAClB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAC,qBAAqB,EAAE,kBAAkB,EAAC,MAAM,qBAAqB,CAAA;AAE7E,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAA;AACvC,OAAO,EAAC,KAAK,EAAC,MAAM,SAAS,CAAA;AAC7B,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAC,cAAc,EAAC,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAA;AAEnC,MAAM,MAAM,cAAc,GAAG;IAAE,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC,aAAa,CAAC,CAAA;CAAE,CAAA;AAG3F,qBAAa,OAAQ,YAAW,kBAAkB,EAAE,UAAU,EAAE,eAAe;;IAC3E,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO;IAuCpC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO;IAM/D,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,CAAC,QAAQ,GAAG,OAAO;IAQ5E,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAE1C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAA;IAC3C,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAA;IAClC,QAAQ,CAAC,eAAe,EAAE,YAAY,CAAA;IACtC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IAEjC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAA;IACxB,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAA;IACvC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAA;IACnC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAA;IAC/C,QAAQ,CAAC,sBAAsB,EAAE,sBAAsB,CAAA;IACvD,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAA;IAC/C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,MAAM,eAAqB;IAEpC,OAAO;IA8BP,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,GAAG,aAAa;IAoB7E,GAAG,CAAC,CAAC,SAAS,UAAU,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC;IAC3C,MAAM,CAAC,CAAC,SAAS,UAAU,EAAE,GAAG,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI;IAC5D,KAAK,IAAI,UAAU;IAEnB,IAAI,GAAG,IAAI,UAAU,CAAmB;IACxC,IAAI,GAAG,IAAI,MAAM,CAAyC;IAC1D,IAAI,cAAc,IAAI,cAAc,CAAmE;IACvG,IAAI,kBAAkB,IAAI,kBAAkB,CAA2E;IACvH,IAAI,aAAa,IAAI,aAAa,CAAiC;IACnE,IAAI,cAAc,IAAI,cAAc,CAAkD;IACtF,IAAI,cAAc,IAAI,OAAO,CAAe;IAC5C,IAAI,YAAY,IAAI,OAAO,CAAc;IACzC,IAAI,qBAAqB,IAAI,qBAAqB,CAAkD;IAEpG,IAAI,QAAQ,IAAI,cAAc,CAAC,QAAQ,CAWtC;IAED,aAAa,IAAI,eAAe;IAiBhC,IAAI,IAAI,OAAO;IAEf,SAAS,IAAI,IAAI;CACpB"}
|
package/dist/Project.js
CHANGED
@@ -8,8 +8,8 @@ import { Mixer } from "./Mixer";
|
|
8
8
|
import { ProjectApi } from "./ProjectApi";
|
9
9
|
import { ProjectMigration } from "./ProjectMigration";
|
10
10
|
import { CaptureManager } from "./capture/CaptureManager";
|
11
|
+
import { EngineFacade } from "./EngineFacade";
|
11
12
|
// Main Entry Point for a Project
|
12
|
-
//
|
13
13
|
export class Project {
|
14
14
|
static new(env) {
|
15
15
|
const boxGraph = new BoxGraph(Option.wrap(BoxIO.create));
|
@@ -75,6 +75,7 @@ export class Project {
|
|
75
75
|
parameterFieldAdapters;
|
76
76
|
liveStreamReceiver;
|
77
77
|
mixer;
|
78
|
+
engine = new EngineFacade();
|
78
79
|
constructor(env, boxGraph, { rootBox, userInterfaceBox, masterBusBox, masterAudioUnit, timelineBox }) {
|
79
80
|
this.#env = env;
|
80
81
|
this.boxGraph = boxGraph;
|
@@ -96,6 +97,25 @@ export class Project {
|
|
96
97
|
this.mixer = new Mixer(this.rootBoxAdapter.audioUnits);
|
97
98
|
console.debug(`Project was created on ${this.rootBoxAdapter.created.toString()}`);
|
98
99
|
}
|
100
|
+
startAudioWorklet(worklets, restart) {
|
101
|
+
console.debug(`start AudioWorklet`);
|
102
|
+
const lifecycle = this.#terminator.spawn();
|
103
|
+
const engine = lifecycle.own(worklets.createEngine(this));
|
104
|
+
const handler = async (event) => {
|
105
|
+
console.warn(event);
|
106
|
+
// we will only accept the first error
|
107
|
+
engine.removeEventListener("error", handler);
|
108
|
+
engine.removeEventListener("processorerror", handler);
|
109
|
+
restart.unload(event);
|
110
|
+
lifecycle.terminate();
|
111
|
+
restart.load(this.startAudioWorklet(worklets, restart));
|
112
|
+
};
|
113
|
+
engine.addEventListener("error", handler);
|
114
|
+
engine.addEventListener("processorerror", handler);
|
115
|
+
engine.connect(engine.context.destination);
|
116
|
+
this.engine.setClient(engine);
|
117
|
+
return engine;
|
118
|
+
}
|
99
119
|
own(terminable) { return this.#terminator.own(terminable); }
|
100
120
|
ownAll(...terminables) { return this.#terminator.ownAll(...terminables); }
|
101
121
|
spawn() { return this.#terminator.spawn(); }
|
package/dist/ProjectEnv.d.ts
CHANGED
package/dist/ProjectEnv.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ProjectEnv.d.ts","sourceRoot":"","sources":["../src/ProjectEnv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,0BAA0B,CAAA;AAEtD,MAAM,WAAW,UAAU;IACvB,
|
1
|
+
{"version":3,"file":"ProjectEnv.d.ts","sourceRoot":"","sources":["../src/ProjectEnv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,0BAA0B,CAAA;AAEtD,MAAM,WAAW,UAAU;IACvB,aAAa,EAAE,aAAa,CAAA;CAC/B"}
|
@@ -6,9 +6,9 @@ import { CaptureManager } from "./CaptureManager";
|
|
6
6
|
export declare abstract class Capture<BOX extends CaptureBox = CaptureBox> implements Terminable {
|
7
7
|
#private;
|
8
8
|
protected constructor(manager: CaptureManager, audioUnitBox: AudioUnitBox, captureBox: BOX);
|
9
|
+
abstract get deviceLabel(): Option<string>;
|
9
10
|
abstract prepareRecording(context: RecordingContext): Promise<void>;
|
10
11
|
abstract startRecording(context: RecordingContext): Terminable;
|
11
|
-
abstract get deviceLabel(): Option<string>;
|
12
12
|
get uuid(): UUID.Format;
|
13
13
|
get manager(): CaptureManager;
|
14
14
|
get audioUnitBox(): AudioUnitBox;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Capture.d.ts","sourceRoot":"","sources":["../../src/capture/Capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,sBAAsB,EACtB,MAAM,EACN,UAAU,EAEV,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAA;AAEnD,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAE/C,8BAAsB,OAAO,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU,CAAE,YAAW,UAAU;;IAUpF,SAAS,aAAa,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG;IAmB1F,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IACnE,QAAQ,CAAC,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,UAAU;
|
1
|
+
{"version":3,"file":"Capture.d.ts","sourceRoot":"","sources":["../../src/capture/Capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,sBAAsB,EACtB,MAAM,EACN,UAAU,EAEV,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAA;AAEnD,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAE/C,8BAAsB,OAAO,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU,CAAE,YAAW,UAAU;;IAUpF,SAAS,aAAa,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG;IAmB1F,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,CAAA;IAC1C,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IACnE,QAAQ,CAAC,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,UAAU;IAE9D,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,CAAyC;IAChE,IAAI,OAAO,IAAI,cAAc,CAAuB;IACpD,IAAI,YAAY,IAAI,YAAY,CAA4B;IAC5D,IAAI,UAAU,IAAI,GAAG,CAA0B;IAC/C,IAAI,KAAK,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAqB;IACjE,IAAI,QAAQ,IAAI,sBAAsB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAwB;IAE9E,GAAG,CAAC,CAAC,SAAS,UAAU,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC;IAC3C,MAAM,CAAC,CAAC,SAAS,UAAU,EAAE,GAAG,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI;IACpE,SAAS,IAAI,IAAI;CACpB"}
|
@@ -1,17 +1,17 @@
|
|
1
|
-
import {
|
1
|
+
import { MutableObservableOption, Option, Terminable } from "@opendaw/lib-std";
|
2
2
|
import { AudioUnitBox, CaptureAudioBox } from "@opendaw/studio-boxes";
|
3
3
|
import { Capture } from "./Capture";
|
4
|
-
import { RecordingContext } from "./RecordingContext";
|
5
4
|
import { CaptureManager } from "./CaptureManager";
|
5
|
+
import { RecordingContext } from "./RecordingContext";
|
6
6
|
export declare class CaptureAudio extends Capture<CaptureAudioBox> {
|
7
7
|
#private;
|
8
|
-
constructor(manager: CaptureManager, audioUnitBox: AudioUnitBox,
|
8
|
+
constructor(manager: CaptureManager, audioUnitBox: AudioUnitBox, captureAudioBox: CaptureAudioBox);
|
9
9
|
get gainDb(): number;
|
10
|
-
get stream():
|
10
|
+
get stream(): MutableObservableOption<MediaStream>;
|
11
11
|
get streamDeviceId(): Option<string>;
|
12
12
|
get deviceLabel(): Option<string>;
|
13
13
|
get streamMediaTrack(): Option<MediaStreamTrack>;
|
14
14
|
prepareRecording({}: RecordingContext): Promise<void>;
|
15
|
-
startRecording({ audioContext, worklets, project,
|
15
|
+
startRecording({ audioContext, worklets, project, sampleManager }: RecordingContext): Terminable;
|
16
16
|
}
|
17
17
|
//# sourceMappingURL=CaptureAudio.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"CaptureAudio.d.ts","sourceRoot":"","sources":["../../src/capture/CaptureAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,
|
1
|
+
{"version":3,"file":"CaptureAudio.d.ts","sourceRoot":"","sources":["../../src/capture/CaptureAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,uBAAuB,EAAE,MAAM,EAAE,UAAU,EAAO,MAAM,kBAAkB,CAAA;AAExH,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;AAE/C,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AAGnD,qBAAa,YAAa,SAAQ,OAAO,CAAC,eAAe,CAAC;;gBAQ1C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe;IA4BjG,IAAI,MAAM,IAAI,MAAM,CAAsB;IAE1C,IAAI,MAAM,IAAI,uBAAuB,CAAC,WAAW,CAAC,CAAsB;IAExE,IAAI,cAAc,IAAI,MAAM,CAAC,MAAM,CAAC,CAEnC;IAED,IAAI,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,CAEhC;IAED,IAAI,gBAAgB,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAE/C;IAEK,gBAAgB,CAAC,EAAE,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3D,cAAc,CAAC,EAAC,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAC,EAAE,gBAAgB,GAAG,UAAU;CA6DjG"}
|
@@ -1,21 +1,21 @@
|
|
1
|
-
import { assert, isDefined, isUndefined,
|
1
|
+
import { assert, isDefined, isUndefined, MutableObservableOption, Option, warn } from "@opendaw/lib-std";
|
2
|
+
import { Promises } from "@opendaw/lib-runtime";
|
2
3
|
import { Capture } from "./Capture";
|
3
4
|
import { RecordAudio } from "./RecordAudio";
|
4
|
-
import {
|
5
|
-
import { Promises } from "@opendaw/lib-runtime";
|
5
|
+
import { AudioDevices } from "../AudioDevices";
|
6
6
|
export class CaptureAudio extends Capture {
|
7
7
|
#stream;
|
8
8
|
#streamGenerator;
|
9
9
|
#requestChannels = Option.None;
|
10
10
|
#gainDb = 0.0;
|
11
|
-
constructor(manager, audioUnitBox,
|
12
|
-
super(manager, audioUnitBox,
|
13
|
-
this.#stream = new
|
11
|
+
constructor(manager, audioUnitBox, captureAudioBox) {
|
12
|
+
super(manager, audioUnitBox, captureAudioBox);
|
13
|
+
this.#stream = new MutableObservableOption();
|
14
14
|
this.#streamGenerator = Promises.sequential(() => this.#updateStream());
|
15
|
-
this.ownAll(
|
15
|
+
this.ownAll(captureAudioBox.requestChannels.catchupAndSubscribe(owner => {
|
16
16
|
const channels = owner.getValue();
|
17
17
|
this.#requestChannels = channels === 1 || channels === 2 ? Option.wrap(channels) : Option.None;
|
18
|
-
}),
|
18
|
+
}), captureAudioBox.gainDb.catchupAndSubscribe(owner => this.#gainDb = owner.getValue()), captureAudioBox.deviceId.catchupAndSubscribe(async () => {
|
19
19
|
if (this.armed.getValue()) {
|
20
20
|
await this.#streamGenerator();
|
21
21
|
}
|
@@ -43,18 +43,18 @@ export class CaptureAudio extends Capture {
|
|
43
43
|
async prepareRecording({}) {
|
44
44
|
return this.#streamGenerator();
|
45
45
|
}
|
46
|
-
startRecording({ audioContext, worklets, project,
|
46
|
+
startRecording({ audioContext, worklets, project, sampleManager }) {
|
47
47
|
const streamOption = this.#stream;
|
48
48
|
assert(streamOption.nonEmpty(), "Stream not prepared.");
|
49
49
|
const mediaStream = streamOption.unwrap();
|
50
50
|
const channelCount = mediaStream.getAudioTracks().at(0)?.getSettings().channelCount ?? 1;
|
51
51
|
const numChunks = 128;
|
52
|
+
const recordingWorklet = worklets.createRecording(channelCount, numChunks, audioContext.outputLatency);
|
52
53
|
return RecordAudio.start({
|
53
|
-
recordingWorklet
|
54
|
+
recordingWorklet,
|
54
55
|
mediaStream,
|
55
56
|
sampleManager,
|
56
57
|
audioContext,
|
57
|
-
engine,
|
58
58
|
project,
|
59
59
|
capture: this,
|
60
60
|
gainDb: this.#gainDb
|
@@ -78,14 +78,14 @@ export class CaptureAudio extends Capture {
|
|
78
78
|
this.#stopStream();
|
79
79
|
const deviceId = this.deviceId.getValue().unwrapOrUndefined();
|
80
80
|
const channelCount = this.#requestChannels.unwrapOrElse(1); // as of today, browsers cap MediaStream audio to stereo.
|
81
|
-
return
|
81
|
+
return AudioDevices.requestStream({
|
82
82
|
deviceId: { exact: deviceId },
|
83
|
-
sampleRate: this.manager.project.
|
83
|
+
sampleRate: this.manager.project.engine.sampleRate(),
|
84
84
|
sampleSize: 32,
|
85
85
|
echoCancellation: false,
|
86
86
|
noiseSuppression: false,
|
87
87
|
autoGainControl: false,
|
88
|
-
channelCount
|
88
|
+
channelCount
|
89
89
|
}).then(stream => {
|
90
90
|
const tracks = stream.getAudioTracks();
|
91
91
|
const settings = tracks.at(0)?.getSettings();
|
@@ -6,8 +6,8 @@ import { CaptureManager } from "./CaptureManager";
|
|
6
6
|
export declare class CaptureMidi extends Capture<CaptureMidiBox> {
|
7
7
|
#private;
|
8
8
|
constructor(manager: CaptureManager, audioUnitBox: AudioUnitBox, captureMidiBox: CaptureMidiBox);
|
9
|
-
prepareRecording({ requestMIDIAccess }: RecordingContext): Promise<void>;
|
10
|
-
startRecording({ project, engine }: RecordingContext): Terminable;
|
11
9
|
get deviceLabel(): Option<string>;
|
10
|
+
prepareRecording({}: RecordingContext): Promise<void>;
|
11
|
+
startRecording({ project }: RecordingContext): Terminable;
|
12
12
|
}
|
13
13
|
//# sourceMappingURL=CaptureMidi.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"CaptureMidi.d.ts","sourceRoot":"","sources":["../../src/capture/CaptureMidi.ts"],"names":[],"mappings":"AAAA,OAAO,
|
1
|
+
{"version":3,"file":"CaptureMidi.d.ts","sourceRoot":"","sources":["../../src/capture/CaptureMidi.ts"],"names":[],"mappings":"AAAA,OAAO,EAQH,MAAM,EAEN,UAAU,EAEb,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAC,YAAY,EAAE,cAAc,EAAC,MAAM,uBAAuB,CAAA;AAClE,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAEjC,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAI/C,qBAAa,WAAY,SAAQ,OAAO,CAAC,cAAc,CAAC;;gBAQxC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc;IAsC/F,IAAI,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,CAA0C;IAErE,gBAAgB,CAAC,EAAE,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB3D,cAAc,CAAC,EAAC,OAAO,EAAC,EAAE,gBAAgB,GAAG,UAAU;CA8C1D"}
|
@@ -1,50 +1,106 @@
|
|
1
|
-
import { assert, isDefined, isUndefined, Notifier, Option,
|
1
|
+
import { asDefined, assert, isDefined, isUndefined, Notifier, Option, Terminable, warn } from "@opendaw/lib-std";
|
2
2
|
import { Events } from "@opendaw/lib-dom";
|
3
3
|
import { MidiData } from "@opendaw/lib-midi";
|
4
4
|
import { Capture } from "./Capture";
|
5
5
|
import { RecordMidi } from "./RecordMidi";
|
6
|
+
import { MidiDevices } from "../MidiDevices";
|
7
|
+
import { Promises } from "@opendaw/lib-runtime";
|
6
8
|
export class CaptureMidi extends Capture {
|
7
|
-
#
|
9
|
+
#streamGenerator;
|
10
|
+
#notifier = new Notifier();
|
8
11
|
#filterChannel = Option.None;
|
12
|
+
#streaming = Option.None;
|
9
13
|
constructor(manager, audioUnitBox, captureMidiBox) {
|
10
14
|
super(manager, audioUnitBox, captureMidiBox);
|
11
|
-
this.
|
15
|
+
this.#streamGenerator = Promises.sequential(() => this.#updateStream());
|
16
|
+
this.ownAll(captureMidiBox.channel.subscribe(async (owner) => {
|
12
17
|
const channel = owner.getValue();
|
13
18
|
this.#filterChannel = channel >= 0 ? Option.wrap(channel) : Option.None;
|
19
|
+
await this.#streamGenerator();
|
20
|
+
}), captureMidiBox.deviceId.catchupAndSubscribe(async () => {
|
21
|
+
if (this.armed.getValue()) {
|
22
|
+
await this.#streamGenerator();
|
23
|
+
}
|
24
|
+
}), this.armed.catchupAndSubscribe(async (owner) => {
|
25
|
+
const armed = owner.getValue();
|
26
|
+
if (armed) {
|
27
|
+
await this.#streamGenerator();
|
28
|
+
}
|
29
|
+
else {
|
30
|
+
this.#stopStream();
|
31
|
+
}
|
32
|
+
}), this.#notifier.subscribe(event => {
|
33
|
+
console.debug(MidiData.debug(event.data));
|
34
|
+
const data = asDefined(event.data);
|
35
|
+
const engine = manager.project.engine;
|
36
|
+
const isNoteOn = MidiData.isNoteOn(data);
|
37
|
+
if (MidiData.isNoteOff(data) || (isNoteOn && MidiData.readVelocity(data) === 0)) {
|
38
|
+
engine.noteOff(this.uuid, MidiData.readPitch(data));
|
39
|
+
}
|
40
|
+
else if (isNoteOn) {
|
41
|
+
engine.noteOn(this.uuid, MidiData.readPitch(data), MidiData.readVelocity(data));
|
42
|
+
}
|
14
43
|
}));
|
15
44
|
}
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
45
|
+
get deviceLabel() { return Option.wrap("MIDI coming soon."); }
|
46
|
+
async prepareRecording({}) {
|
47
|
+
const availableMidiDevices = MidiDevices.get();
|
48
|
+
if (availableMidiDevices.isEmpty()) {
|
49
|
+
return Promise.reject("MIDI is not available");
|
50
|
+
}
|
51
|
+
const option = this.deviceId.getValue();
|
52
|
+
if (option.nonEmpty()) {
|
53
|
+
const { inputs } = availableMidiDevices.unwrap();
|
54
|
+
const captureDevices = Array.from(inputs.values());
|
55
|
+
const deviceId = option.unwrap();
|
56
|
+
if (isUndefined(captureDevices.find(device => deviceId === device.id))) {
|
57
|
+
return warn(`Could not find MIDI device with id: '${deviceId}'`);
|
26
58
|
}
|
27
|
-
|
28
|
-
|
59
|
+
}
|
60
|
+
}
|
61
|
+
startRecording({ project }) {
|
62
|
+
const availableMidiDevices = MidiDevices.inputs();
|
63
|
+
assert(availableMidiDevices.nonEmpty(), "No MIDI input devices found");
|
64
|
+
return RecordMidi.start({ notifier: this.#notifier, project, capture: this });
|
29
65
|
}
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
66
|
+
async #updateStream() {
|
67
|
+
// TODO Check if the requirements have been changed (are different than the current stream setup)
|
68
|
+
if (MidiDevices.get().isEmpty()) {
|
69
|
+
await MidiDevices.requestPermission();
|
70
|
+
}
|
71
|
+
const availableMidiDevices = MidiDevices.inputs();
|
72
|
+
const inputs = availableMidiDevices.unwrap();
|
73
|
+
const captureDevices = this.deviceId.getValue().match({
|
74
|
+
none: () => inputs,
|
75
|
+
some: id => inputs.filter(device => id === device.id)
|
76
|
+
});
|
77
|
+
const activeNotes = new Int8Array(128);
|
78
|
+
this.#streaming.ifSome(terminable => terminable.terminate());
|
79
|
+
this.#streaming = Option.wrap(Terminable.many(...captureDevices.map(input => Events.subscribe(input, "midimessage", (event) => {
|
37
80
|
const data = event.data;
|
38
81
|
if (isDefined(data) &&
|
39
82
|
this.#filterChannel.mapOr(channel => MidiData.readChannel(data) === channel, true)) {
|
40
|
-
|
83
|
+
if (MidiData.isNoteOn(data)) {
|
84
|
+
activeNotes[MidiData.readPitch(data)]++;
|
85
|
+
this.#notifier.notify(event);
|
86
|
+
}
|
87
|
+
else if (MidiData.isNoteOff(data)) {
|
88
|
+
activeNotes[MidiData.readPitch(data)]--;
|
89
|
+
this.#notifier.notify(event);
|
90
|
+
}
|
41
91
|
}
|
42
|
-
}))
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
92
|
+
})), Terminable.create(() => activeNotes.forEach((count, index) => {
|
93
|
+
if (count > 0) {
|
94
|
+
// TODO respect channel!
|
95
|
+
const event = new MessageEvent("midimessage", { data: MidiData.noteOff(index, count) });
|
96
|
+
for (let i = 0; i < count; i++) {
|
97
|
+
this.#notifier.notify(event);
|
98
|
+
}
|
99
|
+
}
|
100
|
+
}))));
|
101
|
+
}
|
102
|
+
#stopStream() {
|
103
|
+
this.#streaming.ifSome(terminable => terminable.terminate());
|
104
|
+
this.#streaming = Option.None;
|
48
105
|
}
|
49
|
-
get deviceLabel() { return Option.None; }
|
50
106
|
}
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import { Terminable } from "@opendaw/lib-std";
|
2
2
|
import { SampleManager } from "@opendaw/studio-adapters";
|
3
|
-
import { Engine } from "../Engine";
|
4
3
|
import { Project } from "../Project";
|
5
4
|
import { Capture } from "./Capture";
|
6
5
|
import { RecordingWorklet } from "../RecordingWorklet";
|
@@ -10,12 +9,11 @@ export declare namespace RecordAudio {
|
|
10
9
|
mediaStream: MediaStream;
|
11
10
|
sampleManager: SampleManager;
|
12
11
|
audioContext: AudioContext;
|
13
|
-
engine: Engine;
|
14
12
|
project: Project;
|
15
13
|
capture: Capture;
|
16
14
|
gainDb: number;
|
17
15
|
};
|
18
|
-
export const start: ({ recordingWorklet, mediaStream, sampleManager, audioContext,
|
16
|
+
export const start: ({ recordingWorklet, mediaStream, sampleManager, audioContext, project, capture, gainDb }: RecordAudioContext) => Terminable;
|
19
17
|
export {};
|
20
18
|
}
|
21
19
|
//# sourceMappingURL=RecordAudio.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"RecordAudio.d.ts","sourceRoot":"","sources":["../../src/capture/RecordAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,UAAU,EAAmB,MAAM,kBAAkB,CAAA;AAGpF,OAAO,EAAC,aAAa,EAAY,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAC,
|
1
|
+
{"version":3,"file":"RecordAudio.d.ts","sourceRoot":"","sources":["../../src/capture/RecordAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,UAAU,EAAmB,MAAM,kBAAkB,CAAA;AAGpF,OAAO,EAAC,aAAa,EAAY,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAC,OAAO,EAAC,MAAM,YAAY,CAAA;AAClC,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAEjC,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAA;AAGpD,yBAAiB,WAAW,CAAC;IACzB,KAAK,kBAAkB,GAAG;QACtB,gBAAgB,EAAE,gBAAgB,CAAA;QAClC,WAAW,EAAE,WAAW,CAAA;QACxB,aAAa,EAAE,aAAa,CAAA;QAC5B,YAAY,EAAE,YAAY,CAAA;QAC1B,OAAO,EAAE,OAAO,CAAA;QAChB,OAAO,EAAE,OAAO,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;KACjB,CAAA;IAED,MAAM,CAAC,MAAM,KAAK,GACd,0FAEG,kBAAkB,KAAG,UA2D3B,CAAA;;CACJ"}
|
@@ -6,10 +6,10 @@ import { RecordTrack } from "./RecordTrack";
|
|
6
6
|
import { ColorCodes } from "../ColorCodes";
|
7
7
|
export var RecordAudio;
|
8
8
|
(function (RecordAudio) {
|
9
|
-
RecordAudio.start = ({ recordingWorklet, mediaStream, sampleManager, audioContext,
|
9
|
+
RecordAudio.start = ({ recordingWorklet, mediaStream, sampleManager, audioContext, project, capture, gainDb }) => {
|
10
10
|
const terminator = new Terminator();
|
11
11
|
const beats = PPQN.fromSignature(1, project.timelineBox.signature.denominator.getValue());
|
12
|
-
const { editing, boxGraph } = project;
|
12
|
+
const { editing, engine, boxGraph } = project;
|
13
13
|
const trackBox = RecordTrack.findOrCreate(editing, capture.audioUnitBox, TrackType.Audio);
|
14
14
|
const uuid = recordingWorklet.uuid;
|
15
15
|
sampleManager.record(recordingWorklet);
|
@@ -1,15 +1,13 @@
|
|
1
1
|
import { Notifier, Terminable } from "@opendaw/lib-std";
|
2
|
-
import { Engine } from "../Engine";
|
3
2
|
import { Project } from "../Project";
|
4
3
|
import { Capture } from "./Capture";
|
5
4
|
export declare namespace RecordMidi {
|
6
5
|
type RecordMidiContext = {
|
7
6
|
notifier: Notifier<MIDIMessageEvent>;
|
8
|
-
engine: Engine;
|
9
7
|
project: Project;
|
10
8
|
capture: Capture;
|
11
9
|
};
|
12
|
-
export const start: ({ notifier,
|
10
|
+
export const start: ({ notifier, project, capture }: RecordMidiContext) => Terminable;
|
13
11
|
export {};
|
14
12
|
}
|
15
13
|
//# sourceMappingURL=RecordMidi.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"RecordMidi.d.ts","sourceRoot":"","sources":["../../src/capture/RecordMidi.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,QAAQ,EAIR,UAAU,EAGb,MAAM,kBAAkB,CAAA;AAKzB,OAAO,EAAC,
|
1
|
+
{"version":3,"file":"RecordMidi.d.ts","sourceRoot":"","sources":["../../src/capture/RecordMidi.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,QAAQ,EAIR,UAAU,EAGb,MAAM,kBAAkB,CAAA;AAKzB,OAAO,EAAC,OAAO,EAAC,MAAM,YAAY,CAAA;AAClC,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAIjC,yBAAiB,UAAU,CAAC;IACxB,KAAK,iBAAiB,GAAG;QACrB,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QACrC,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,OAAO,CAAA;KACnB,CAAA;IAED,MAAM,CAAC,MAAM,KAAK,GAAI,gCAA8B,iBAAiB,KAAG,UAiEvE,CAAA;;CACJ"}
|