@opendaw/studio-adapters 0.0.106 → 0.0.108
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/EngineProcessorAttachment.d.ts +13 -5
- package/dist/EngineProcessorAttachment.d.ts.map +1 -1
- package/dist/EngineProcessorAttachment.js +15 -10
- package/dist/devices/audio-effects/GateDeviceBoxAdapter.js +1 -1
- package/dist/editing/UserEditing.d.ts +1 -0
- package/dist/editing/UserEditing.d.ts.map +1 -1
- package/dist/editing/UserEditing.js +5 -0
- package/dist/factories/InstrumentFactories.d.ts.map +1 -1
- package/dist/factories/InstrumentFactories.js +12 -33
- package/dist/offline-renderer.d.ts +2 -2
- package/dist/offline-renderer.d.ts.map +1 -1
- package/dist/preset/PresetDecoder.d.ts +6 -2
- package/dist/preset/PresetDecoder.d.ts.map +1 -1
- package/dist/preset/PresetDecoder.js +193 -41
- package/dist/preset/PresetEncoder.d.ts +7 -1
- package/dist/preset/PresetEncoder.d.ts.map +1 -1
- package/dist/preset/PresetEncoder.js +91 -5
- package/dist/preset/PresetHeader.d.ts +4 -0
- package/dist/preset/PresetHeader.d.ts.map +1 -1
- package/dist/preset/PresetHeader.js +5 -0
- package/dist/selection/VertexSelection.d.ts.map +1 -1
- package/dist/selection/VertexSelection.js +3 -0
- package/dist/transfer/TransferUtils.js +4 -4
- package/package.json +11 -11
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { int, Option } from "@opendaw/lib-std";
|
|
2
|
+
import { ppqn } from "@opendaw/lib-dsp";
|
|
2
3
|
export type ProcessorOptions = {};
|
|
3
4
|
export type EngineProcessorAttachment = {
|
|
4
5
|
syncStreamBuffer: SharedArrayBuffer;
|
|
5
6
|
controlFlagsBuffer: SharedArrayBuffer;
|
|
6
7
|
hrClockBuffer: SharedArrayBuffer;
|
|
7
8
|
project: ArrayBufferLike;
|
|
8
|
-
exportConfiguration?:
|
|
9
|
+
exportConfiguration?: ExportConfiguration;
|
|
9
10
|
options?: ProcessorOptions;
|
|
10
11
|
};
|
|
11
12
|
export type ExportStemConfiguration = {
|
|
@@ -15,10 +16,17 @@ export type ExportStemConfiguration = {
|
|
|
15
16
|
skipChannelStrip?: boolean;
|
|
16
17
|
fileName: string;
|
|
17
18
|
};
|
|
18
|
-
export type
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
export type ExportRange = "full" | {
|
|
20
|
+
start: ppqn;
|
|
21
|
+
end: ppqn;
|
|
22
|
+
};
|
|
23
|
+
export type ExportConfiguration = {
|
|
24
|
+
stems?: Record<string, ExportStemConfiguration>;
|
|
25
|
+
range?: ExportRange;
|
|
26
|
+
};
|
|
27
|
+
export declare namespace ExportConfiguration {
|
|
28
|
+
const countStems: (config: Option<ExportConfiguration>) => int;
|
|
21
29
|
const sanitizeFileName: (name: string) => string;
|
|
22
|
-
const sanitizeExportNamesInPlace: (configuration:
|
|
30
|
+
const sanitizeExportNamesInPlace: (configuration: ExportConfiguration) => void;
|
|
23
31
|
}
|
|
24
32
|
//# sourceMappingURL=EngineProcessorAttachment.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EngineProcessorAttachment.d.ts","sourceRoot":"","sources":["../src/EngineProcessorAttachment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,
|
|
1
|
+
{"version":3,"file":"EngineProcessorAttachment.d.ts","sourceRoot":"","sources":["../src/EngineProcessorAttachment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAa,MAAM,EAAC,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAErC,MAAM,MAAM,gBAAgB,GAAG,EAAE,CAAA;AAGjC,MAAM,MAAM,yBAAyB,GAAG;IACpC,gBAAgB,EAAE,iBAAiB,CAAA;IACnC,kBAAkB,EAAE,iBAAiB,CAAA;IACrC,aAAa,EAAE,iBAAiB,CAAA;IAChC,OAAO,EAAE,eAAe,CAAA;IACxB,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC,OAAO,CAAC,EAAE,gBAAgB,CAAA;CAC7B,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IAClC,mBAAmB,EAAE,OAAO,CAAA;IAC5B,YAAY,EAAE,OAAO,CAAA;IACrB,mBAAmB,EAAE,OAAO,CAAA;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,QAAQ,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,CAAA;AAE7D,MAAM,MAAM,mBAAmB,GAAG;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAA;IAC/C,KAAK,CAAC,EAAE,WAAW,CAAA;CACtB,CAAA;AAED,yBAAiB,mBAAmB,CAAC;IAC1B,MAAM,UAAU,GAAI,QAAQ,MAAM,CAAC,mBAAmB,CAAC,KAAG,GAI3D,CAAA;IAEC,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,MAA4D,CAAA;IAErG,MAAM,0BAA0B,GAAI,eAAe,mBAAmB,KAAG,IAmB/E,CAAA;CACJ"}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { isDefined } from "@opendaw/lib-std";
|
|
2
|
+
export var ExportConfiguration;
|
|
3
|
+
(function (ExportConfiguration) {
|
|
4
|
+
ExportConfiguration.countStems = (config) => config.match({
|
|
4
5
|
none: () => 1,
|
|
5
|
-
some: (
|
|
6
|
+
some: cfg => isDefined(cfg.stems) ? Object.keys(cfg.stems).length : 1
|
|
6
7
|
});
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
ExportConfiguration.sanitizeFileName = (name) => name.replace(/[<>:"/\\|?*\x00-\x1F]/g, "_").trim();
|
|
9
|
+
ExportConfiguration.sanitizeExportNamesInPlace = (configuration) => {
|
|
10
|
+
if (!isDefined(configuration.stems)) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const stems = configuration.stems;
|
|
9
14
|
const sanitizedNames = new Map();
|
|
10
15
|
const getUniqueName = (baseName) => {
|
|
11
16
|
let count = sanitizedNames.get(baseName) ?? 0;
|
|
@@ -18,9 +23,9 @@ export var ExportStemsConfiguration;
|
|
|
18
23
|
sanitizedNames.set(newName, 1);
|
|
19
24
|
return newName;
|
|
20
25
|
};
|
|
21
|
-
Object.keys(
|
|
22
|
-
const entry =
|
|
23
|
-
entry.fileName = getUniqueName(
|
|
26
|
+
Object.keys(stems).forEach((key) => {
|
|
27
|
+
const entry = stems[key];
|
|
28
|
+
entry.fileName = getUniqueName(ExportConfiguration.sanitizeFileName(entry.fileName));
|
|
24
29
|
});
|
|
25
30
|
};
|
|
26
|
-
})(
|
|
31
|
+
})(ExportConfiguration || (ExportConfiguration = {}));
|
|
@@ -54,7 +54,7 @@ _GateDeviceBoxAdapter_context = new WeakMap(), _GateDeviceBoxAdapter_box = new W
|
|
|
54
54
|
inverse: __classPrivateFieldGet(this, _GateDeviceBoxAdapter_parametric, "f").createParameter(box.inverse, ValueMapping.bool, StringMapping.bool, "Inverse"),
|
|
55
55
|
threshold: __classPrivateFieldGet(this, _GateDeviceBoxAdapter_parametric, "f").createParameter(box.threshold, ValueMapping.linear(-80.0, 0.0), StringMapping.decible, "Threshold"),
|
|
56
56
|
return: __classPrivateFieldGet(this, _GateDeviceBoxAdapter_parametric, "f").createParameter(box.return, ValueMapping.linear(0.0, 24.0), StringMapping.decible, "Return"),
|
|
57
|
-
attack: __classPrivateFieldGet(this, _GateDeviceBoxAdapter_parametric, "f").createParameter(box.attack, ValueMapping.linear(0.0,
|
|
57
|
+
attack: __classPrivateFieldGet(this, _GateDeviceBoxAdapter_parametric, "f").createParameter(box.attack, ValueMapping.linear(0.0, 1000.0), StringMapping.numeric({ unit: "ms", fractionDigits: 1 }), "Attack"),
|
|
58
58
|
hold: __classPrivateFieldGet(this, _GateDeviceBoxAdapter_parametric, "f").createParameter(box.hold, ValueMapping.linear(0.0, 500.0), StringMapping.numeric({ unit: "ms", fractionDigits: 1 }), "Hold"),
|
|
59
59
|
release: __classPrivateFieldGet(this, _GateDeviceBoxAdapter_parametric, "f").createParameter(box.release, ValueMapping.linear(1.0, 2000.0), StringMapping.numeric({ unit: "ms", fractionDigits: 1 }), "Release"),
|
|
60
60
|
floor: __classPrivateFieldGet(this, _GateDeviceBoxAdapter_parametric, "f").createParameter(box.floor, ValueMapping.decibel(-72.0, -12.0, 0.0), StringMapping.decible, "Floor")
|
|
@@ -7,6 +7,7 @@ export declare class UserEditing implements Terminable {
|
|
|
7
7
|
catchupAndSubscribe(observer: Observer<Option<Vertex>>): Subscription;
|
|
8
8
|
follow(pointer: PointerField<Pointers.Editing>): void;
|
|
9
9
|
edit(target: Vertex<Pointers.Editing | Pointers>): void;
|
|
10
|
+
editIfDifferent(target: Vertex<Pointers.Editing | Pointers>): void;
|
|
10
11
|
isEditing(vertex: Vertex<Pointers.Editing | Pointers>): boolean;
|
|
11
12
|
get(): Option<Vertex>;
|
|
12
13
|
clear(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserEditing.d.ts","sourceRoot":"","sources":["../../src/editing/UserEditing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAY,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAC,MAAM,kBAAkB,CAAA;AAC9F,OAAO,EAAC,YAAY,EAAE,MAAM,EAAC,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAA;AAE9C,qBAAa,WAAY,YAAW,UAAU;;gBAO9B,OAAO,EAAE,OAAO;IAK5B,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,YAAY;IAKrE,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,IAAI;IAOrD,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,GAAG,IAAI;IAIvD,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,GAAG,OAAO;IAO/D,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC;IAErB,KAAK,IAAI,IAAI;IAEb,SAAS,IAAI,IAAI;CAOpB"}
|
|
1
|
+
{"version":3,"file":"UserEditing.d.ts","sourceRoot":"","sources":["../../src/editing/UserEditing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAY,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAC,MAAM,kBAAkB,CAAA;AAC9F,OAAO,EAAC,YAAY,EAAE,MAAM,EAAC,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAA;AAE9C,qBAAa,WAAY,YAAW,UAAU;;gBAO9B,OAAO,EAAE,OAAO;IAK5B,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,YAAY;IAKrE,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,IAAI;IAOrD,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,GAAG,IAAI;IAIvD,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,GAAG,IAAI;IAIlE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,GAAG,OAAO;IAO/D,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC;IAErB,KAAK,IAAI,IAAI;IAEb,SAAS,IAAI,IAAI;CAOpB"}
|
|
@@ -33,6 +33,11 @@ export class UserEditing {
|
|
|
33
33
|
edit(target) {
|
|
34
34
|
__classPrivateFieldGet(this, _UserEditing_pointer, "f").ifSome(pointer => __classPrivateFieldGet(this, _UserEditing_editing, "f").modify(() => pointer.refer(target), false));
|
|
35
35
|
}
|
|
36
|
+
editIfDifferent(target) {
|
|
37
|
+
if (!this.isEditing(target)) {
|
|
38
|
+
this.edit(target);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
36
41
|
isEditing(vertex) {
|
|
37
42
|
return __classPrivateFieldGet(this, _UserEditing_pointer, "f").match({
|
|
38
43
|
none: () => false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstrumentFactories.d.ts","sourceRoot":"","sources":["../../src/factories/InstrumentFactories.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,gBAAgB,EAChB,YAAY,EAEZ,mBAAmB,EACnB,aAAa,EACb,kBAAkB,EAElB,kBAAkB,EAElB,aAAa,EACb,qBAAqB,EACxB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAC,IAAI,EAAa,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAKtD,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAA;AAGrD,yBAAiB,mBAAmB,CAAC;IAC1B,MAAM,IAAI,EAAE,iBAAiB,CAAC,IAAI,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"InstrumentFactories.d.ts","sourceRoot":"","sources":["../../src/factories/InstrumentFactories.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,gBAAgB,EAChB,YAAY,EAEZ,mBAAmB,EACnB,aAAa,EACb,kBAAkB,EAElB,kBAAkB,EAElB,aAAa,EACb,qBAAqB,EACxB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAC,IAAI,EAAa,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAKtD,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAA;AAGrD,yBAAiB,mBAAmB,CAAC;IAC1B,MAAM,IAAI,EAAE,iBAAiB,CAAC,IAAI,EAAE,aAAa,CAoBvD,CAAA;IAEM,MAAM,IAAI,EAAE,iBAAiB,CAAC,YAAY,EAAE,aAAa,CAiB/D,CAAA;IAED,KAAY,mBAAmB,GAAG,aAAa,CAAC;QAC5C,IAAI,EAAE,IAAI,CAAA;QACV,IAAI,EAAE,IAAI,CAAC,KAAK,CAAA;QAChB,IAAI,EAAE,MAAM,CAAA;QACZ,iBAAiB,EAAE,MAAM,CAAA;QACzB,OAAO,EAAE,OAAO,CAAA;KACnB,CAAC,CAAA;IAEK,MAAM,SAAS,EAAE,iBAAiB,CAAC,mBAAmB,EAAE,kBAAkB,CA8BhF,CAAA;IAEM,MAAM,YAAY,EAAE,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,CA8BvE,CAAA;IAEM,MAAM,UAAU,EAAE,iBAAiB,CAAC,IAAI,EAAE,mBAAmB,CAiBnE,CAAA;IAEM,MAAM,SAAS,EAAE,iBAAiB,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,kBAAkB,CAehG,CAAA;IAEM,MAAM,OAAO,EAAE,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,CAe7D,CAAA;IAEM,MAAM,KAAK;;;;;;kBAlCgC,IAAI,CAAC,MAAM;kBAAQ,MAAM;;;;KAkCe,CAAA;IAC1F,KAAY,IAAI,GAAG,MAAM,OAAO,KAAK,CAAA;CAYxC"}
|
|
@@ -30,27 +30,14 @@ export var InstrumentFactories;
|
|
|
30
30
|
description: "Simple sampler",
|
|
31
31
|
manualPage: DeviceManualUrls.Nano,
|
|
32
32
|
trackType: TrackType.Notes,
|
|
33
|
-
create: (boxGraph, host, name, icon, attachment) => {
|
|
34
|
-
|
|
33
|
+
create: (boxGraph, host, name, icon, attachment) => NanoDeviceBox.create(boxGraph, UUID.generate(), box => {
|
|
34
|
+
box.label.setValue(name);
|
|
35
|
+
box.icon.setValue(IconSymbol.toName(icon));
|
|
35
36
|
if (isDefined(attachment)) {
|
|
36
|
-
|
|
37
|
+
box.file.refer(attachment);
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const fileDuration = 5.340;
|
|
41
|
-
audioFileBox = boxGraph.findBox(fileUUID)
|
|
42
|
-
.unwrapOrElse(() => AudioFileBox.create(boxGraph, fileUUID, box => {
|
|
43
|
-
box.fileName.setValue("Rhode");
|
|
44
|
-
box.endInSeconds.setValue(fileDuration);
|
|
45
|
-
}));
|
|
46
|
-
}
|
|
47
|
-
return NanoDeviceBox.create(boxGraph, UUID.generate(), box => {
|
|
48
|
-
box.label.setValue(name);
|
|
49
|
-
box.icon.setValue(IconSymbol.toName(icon));
|
|
50
|
-
box.file.refer(audioFileBox);
|
|
51
|
-
box.host.refer(host);
|
|
52
|
-
});
|
|
53
|
-
}
|
|
39
|
+
box.host.refer(host);
|
|
40
|
+
})
|
|
54
41
|
};
|
|
55
42
|
InstrumentFactories.Playfield = {
|
|
56
43
|
defaultName: "Playfield",
|
|
@@ -89,7 +76,6 @@ export var InstrumentFactories;
|
|
|
89
76
|
create: (boxGraph, host, name, icon, _attachment) => VaporisateurDeviceBox.create(boxGraph, UUID.generate(), box => {
|
|
90
77
|
box.label.setValue(name);
|
|
91
78
|
box.icon.setValue(IconSymbol.toName(icon));
|
|
92
|
-
box.tune.setInitValue(0.0);
|
|
93
79
|
box.cutoff.setInitValue(8000.0);
|
|
94
80
|
box.resonance.setInitValue(0.1);
|
|
95
81
|
box.attack.setInitValue(0.005);
|
|
@@ -126,18 +112,11 @@ export var InstrumentFactories;
|
|
|
126
112
|
description: "Soundfont Player",
|
|
127
113
|
manualPage: DeviceManualUrls.Soundfont,
|
|
128
114
|
trackType: TrackType.Notes,
|
|
129
|
-
create: (boxGraph, host, name, icon,
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return SoundfontDeviceBox.create(boxGraph, UUID.generate(), box => {
|
|
135
|
-
box.label.setValue(name);
|
|
136
|
-
box.icon.setValue(IconSymbol.toName(icon));
|
|
137
|
-
box.host.refer(host);
|
|
138
|
-
box.file.refer(soundfontBox);
|
|
139
|
-
});
|
|
140
|
-
}
|
|
115
|
+
create: (boxGraph, host, name, icon) => SoundfontDeviceBox.create(boxGraph, UUID.generate(), box => {
|
|
116
|
+
box.label.setValue(name);
|
|
117
|
+
box.icon.setValue(IconSymbol.toName(icon));
|
|
118
|
+
box.host.refer(host);
|
|
119
|
+
})
|
|
141
120
|
};
|
|
142
121
|
InstrumentFactories.Apparat = {
|
|
143
122
|
defaultName: "Apparat",
|
|
@@ -146,7 +125,7 @@ export var InstrumentFactories;
|
|
|
146
125
|
description: "User-scripted instrument",
|
|
147
126
|
manualPage: DeviceManualUrls.Apparat,
|
|
148
127
|
trackType: TrackType.Notes,
|
|
149
|
-
create: (boxGraph, host, name, icon
|
|
128
|
+
create: (boxGraph, host, name, icon) => ApparatDeviceBox.create(boxGraph, UUID.generate(), box => {
|
|
150
129
|
box.label.setValue(name);
|
|
151
130
|
box.icon.setValue(IconSymbol.toName(icon));
|
|
152
131
|
box.host.refer(host);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExportConfiguration } from "./EngineProcessorAttachment";
|
|
2
2
|
export interface OfflineEngineInitializeConfig {
|
|
3
3
|
sampleRate: number;
|
|
4
4
|
numberOfChannels: number;
|
|
@@ -6,7 +6,7 @@ export interface OfflineEngineInitializeConfig {
|
|
|
6
6
|
syncStreamBuffer: SharedArrayBuffer;
|
|
7
7
|
controlFlagsBuffer: SharedArrayBuffer;
|
|
8
8
|
project: ArrayBufferLike;
|
|
9
|
-
exportConfiguration?:
|
|
9
|
+
exportConfiguration?: ExportConfiguration;
|
|
10
10
|
}
|
|
11
11
|
export interface OfflineEngineRenderConfig {
|
|
12
12
|
silenceThresholdDb?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"offline-renderer.d.ts","sourceRoot":"","sources":["../src/offline-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"offline-renderer.d.ts","sourceRoot":"","sources":["../src/offline-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,mBAAmB,EAAC,MAAM,6BAA6B,CAAA;AAE/D,MAAM,WAAW,6BAA6B;IAC1C,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,MAAM,CAAA;IACxB,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,iBAAiB,CAAA;IACnC,kBAAkB,EAAE,iBAAiB,CAAA;IACrC,OAAO,EAAE,eAAe,CAAA;IACxB,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;CAC5C;AAED,MAAM,WAAW,yBAAyB;IACtC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED,MAAM,WAAW,qBAAqB;IAClC,UAAU,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACzF,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtC,MAAM,CAAC,MAAM,EAAE,yBAAyB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAA;IAClE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAA;IAC9C,IAAI,IAAI,IAAI,CAAA;CACf"}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { Attempt } from "@opendaw/lib-std";
|
|
1
|
+
import { Attempt, int } from "@opendaw/lib-std";
|
|
2
2
|
import { AudioUnitBox } from "@opendaw/studio-boxes";
|
|
3
3
|
import { ProjectSkeleton } from "../project/ProjectSkeleton";
|
|
4
|
+
import { PresetHeader } from "./PresetHeader";
|
|
4
5
|
export declare namespace PresetDecoder {
|
|
5
|
-
const decode: (bytes: ArrayBufferLike, target: ProjectSkeleton) =>
|
|
6
|
+
const decode: (bytes: ArrayBufferLike, target: ProjectSkeleton) => ReadonlyArray<AudioUnitBox>;
|
|
7
|
+
const peekHasTimeline: (arrayBuffer: ArrayBuffer) => boolean;
|
|
6
8
|
const replaceAudioUnit: (arrayBuffer: ArrayBuffer, targetAudioUnitBox: AudioUnitBox, options?: {
|
|
7
9
|
keepMIDIEffects?: boolean;
|
|
8
10
|
keepAudioEffects?: boolean;
|
|
11
|
+
keepTimeline?: boolean;
|
|
9
12
|
}) => Attempt<void, string>;
|
|
13
|
+
const insertEffectChain: (bytes: ArrayBufferLike, targetAudioUnit: AudioUnitBox, insertIndex: int, kind: PresetHeader.ChainKind) => Attempt<void, string>;
|
|
10
14
|
}
|
|
11
15
|
//# sourceMappingURL=PresetDecoder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PresetDecoder.d.ts","sourceRoot":"","sources":["../../src/preset/PresetDecoder.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"PresetDecoder.d.ts","sourceRoot":"","sources":["../../src/preset/PresetDecoder.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,OAAO,EAGP,GAAG,EAQN,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAEH,YAAY,EAOf,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAC,eAAe,EAAC,MAAM,4BAA4B,CAAA;AAE1D,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAG3C,yBAAiB,aAAa,CAAC;IACpB,MAAM,MAAM,GAAI,OAAO,eAAe,EAAE,QAAQ,eAAe,KAAG,aAAa,CAAC,YAAY,CA4ElG,CAAA;IAEM,MAAM,eAAe,GAAI,aAAa,WAAW,KAAG,OAY1D,CAAA;IAEM,MAAM,gBAAgB,GAAI,aAAa,WAAW,EAAE,oBAAoB,YAAY,EAAE,UAAU;QACnG,eAAe,CAAC,EAAE,OAAO,CAAA;QACzB,gBAAgB,CAAC,EAAE,OAAO,CAAA;QAC1B,YAAY,CAAC,EAAE,OAAO,CAAA;KACzB,KAAG,OAAO,CAAC,IAAI,EAAE,MAAM,CAsHvB,CAAA;IAEM,MAAM,iBAAiB,GAC1B,OAAO,eAAe,EACtB,iBAAiB,YAAY,EAC7B,aAAa,GAAG,EAChB,MAAM,YAAY,CAAC,SAAS,KAC7B,OAAO,CAAC,IAAI,EAAE,MAAM,CA+FtB,CAAA;CACJ"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { asDefined, asInstanceOf, Attempts, ByteArrayInput, isAbsent, isDefined, isInstanceOf, Option, RuntimeNotifier, UUID } from "@opendaw/lib-std";
|
|
2
|
-
import { BoxGraph, PointerField } from "@opendaw/lib-box";
|
|
3
|
-
import { AudioUnitType } from "@opendaw/studio-enums";
|
|
1
|
+
import { asDefined, asInstanceOf, Attempts, ByteArrayInput, isAbsent, isDefined, isInstanceOf, Option, RuntimeNotifier, tryCatch, UUID } from "@opendaw/lib-std";
|
|
2
|
+
import { BoxGraph, IndexedBox, PointerField } from "@opendaw/lib-box";
|
|
3
|
+
import { AudioUnitType, Pointers } from "@opendaw/studio-enums";
|
|
4
4
|
import { AudioFileBox, AudioUnitBox, BoxIO, CaptureAudioBox, CaptureMidiBox, SoundfontFileBox, TrackBox } from "@opendaw/studio-boxes";
|
|
5
5
|
import { ProjectSkeleton } from "../project/ProjectSkeleton";
|
|
6
6
|
import { TransferUtils } from "../transfer";
|
|
@@ -15,14 +15,15 @@ export var PresetDecoder;
|
|
|
15
15
|
headline: "Could Not Import Preset",
|
|
16
16
|
message: "Invalid preset file"
|
|
17
17
|
}).then();
|
|
18
|
-
return;
|
|
18
|
+
return [];
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
const version = header.readInt();
|
|
21
|
+
if (version !== PresetHeader.FORMAT_VERSION) {
|
|
21
22
|
RuntimeNotifier.info({
|
|
22
23
|
headline: "Could Not Import Preset",
|
|
23
|
-
message:
|
|
24
|
+
message: `Unsupported preset version ${version} (this build supports ${PresetHeader.FORMAT_VERSION}).`
|
|
24
25
|
}).then();
|
|
25
|
-
return;
|
|
26
|
+
return [];
|
|
26
27
|
}
|
|
27
28
|
const sourceBoxGraph = new BoxGraph(Option.wrap(BoxIO.create));
|
|
28
29
|
try {
|
|
@@ -33,12 +34,17 @@ export var PresetDecoder;
|
|
|
33
34
|
headline: "Could Not Import Preset",
|
|
34
35
|
message: String(reason)
|
|
35
36
|
}).then();
|
|
36
|
-
return;
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
const summary = {};
|
|
40
|
+
for (const box of sourceBoxGraph.boxes()) {
|
|
41
|
+
summary[box.name] = (summary[box.name] ?? 0) + 1;
|
|
37
42
|
}
|
|
43
|
+
console.info(`PresetDecoder.decode: source graph boxes`, summary);
|
|
38
44
|
const sourceAudioUnitBoxes = sourceBoxGraph.boxes()
|
|
39
45
|
.filter(box => isInstanceOf(box, AudioUnitBox))
|
|
40
46
|
.filter(box => box.type.getValue() !== AudioUnitType.Output);
|
|
41
|
-
const excludeBox = (box) => TransferUtils.shouldExclude(box)
|
|
47
|
+
const excludeBox = (box) => TransferUtils.shouldExclude(box);
|
|
42
48
|
const dependencies = Array.from(sourceBoxGraph.dependenciesOf(sourceAudioUnitBoxes, {
|
|
43
49
|
alwaysFollowMandatory: true,
|
|
44
50
|
stopAtResources: true,
|
|
@@ -48,34 +54,64 @@ export var PresetDecoder;
|
|
|
48
54
|
const uuidMap = TransferUtils.generateMap(sourceAudioUnitBoxes, dependencies, rootBox.audioUnits.address.uuid, primaryAudioBusBox.address.uuid);
|
|
49
55
|
TransferUtils.copyBoxes(uuidMap, target.boxGraph, sourceAudioUnitBoxes, dependencies);
|
|
50
56
|
TransferUtils.reorderAudioUnits(uuidMap, sourceAudioUnitBoxes, rootBox);
|
|
51
|
-
sourceAudioUnitBoxes
|
|
57
|
+
const importedAudioUnits = sourceAudioUnitBoxes
|
|
52
58
|
.map(source => asInstanceOf(rootBox.graph
|
|
53
59
|
.findBox(uuidMap.get(source.address.uuid).target)
|
|
54
60
|
.unwrap("Target AudioUnit has not been copied"), AudioUnitBox))
|
|
55
|
-
.filter(box => box.type.getValue() !== AudioUnitType.Output)
|
|
56
|
-
|
|
61
|
+
.filter(box => box.type.getValue() !== AudioUnitType.Output);
|
|
62
|
+
importedAudioUnits.forEach((audioUnitBox) => {
|
|
57
63
|
const inputBox = audioUnitBox.input.pointerHub.incoming().at(0)?.box;
|
|
58
|
-
if (isDefined(inputBox)) {
|
|
59
|
-
|
|
60
|
-
if (captureBox instanceof CaptureMidiBox) {
|
|
61
|
-
TrackBox.create(target.boxGraph, UUID.generate(), box => {
|
|
62
|
-
box.index.setValue(0);
|
|
63
|
-
box.type.setValue(TrackType.Notes);
|
|
64
|
-
box.target.refer(audioUnitBox);
|
|
65
|
-
box.tracks.refer(audioUnitBox.tracks);
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
else if (captureBox instanceof CaptureAudioBox) {
|
|
69
|
-
TrackBox.create(target.boxGraph, UUID.generate(), box => {
|
|
70
|
-
box.index.setValue(0);
|
|
71
|
-
box.type.setValue(TrackType.Audio);
|
|
72
|
-
box.target.refer(audioUnitBox);
|
|
73
|
-
box.tracks.refer(audioUnitBox.tracks);
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
});
|
|
64
|
+
if (!isDefined(inputBox)) {
|
|
65
|
+
return;
|
|
77
66
|
}
|
|
67
|
+
const existingTrackCount = audioUnitBox.tracks.pointerHub.incoming().length;
|
|
68
|
+
console.info(`PresetDecoder.decode: AudioUnit ${UUID.toString(audioUnitBox.address.uuid)} has ${existingTrackCount} pre-copied track(s)`);
|
|
69
|
+
if (existingTrackCount > 0) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
audioUnitBox.capture.targetVertex.ifSome(({ box: captureBox }) => {
|
|
73
|
+
if (captureBox instanceof CaptureMidiBox) {
|
|
74
|
+
TrackBox.create(target.boxGraph, UUID.generate(), box => {
|
|
75
|
+
box.index.setValue(0);
|
|
76
|
+
box.type.setValue(TrackType.Notes);
|
|
77
|
+
box.target.refer(audioUnitBox);
|
|
78
|
+
box.tracks.refer(audioUnitBox.tracks);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
else if (captureBox instanceof CaptureAudioBox) {
|
|
82
|
+
TrackBox.create(target.boxGraph, UUID.generate(), box => {
|
|
83
|
+
box.index.setValue(0);
|
|
84
|
+
box.type.setValue(TrackType.Audio);
|
|
85
|
+
box.target.refer(audioUnitBox);
|
|
86
|
+
box.tracks.refer(audioUnitBox.tracks);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
});
|
|
78
90
|
});
|
|
91
|
+
return importedAudioUnits;
|
|
92
|
+
};
|
|
93
|
+
PresetDecoder.peekHasTimeline = (arrayBuffer) => {
|
|
94
|
+
if (arrayBuffer.byteLength < 8) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
const header = new ByteArrayInput(arrayBuffer.slice(0, 8));
|
|
98
|
+
if (header.readInt() !== PresetHeader.MAGIC_HEADER_OPEN) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
if (header.readInt() !== PresetHeader.FORMAT_VERSION) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
const sourceBoxGraph = new BoxGraph(Option.wrap(BoxIO.create));
|
|
105
|
+
const decoded = tryCatch(() => sourceBoxGraph.fromArrayBuffer(arrayBuffer.slice(8), false));
|
|
106
|
+
if (decoded.status === "failure") {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
for (const box of sourceBoxGraph.boxes()) {
|
|
110
|
+
if (isInstanceOf(box, TrackBox)) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return false;
|
|
79
115
|
};
|
|
80
116
|
PresetDecoder.replaceAudioUnit = (arrayBuffer, targetAudioUnitBox, options) => {
|
|
81
117
|
console.debug("ReplaceAudioUnit with preset...");
|
|
@@ -101,8 +137,10 @@ export var PresetDecoder;
|
|
|
101
137
|
}
|
|
102
138
|
const replaceMIDIEffects = options?.keepMIDIEffects !== true;
|
|
103
139
|
const replaceAudioEffects = options?.keepAudioEffects !== true;
|
|
140
|
+
const replaceTimeline = options?.keepTimeline !== true;
|
|
104
141
|
console.debug("replaceMIDIEffects", replaceMIDIEffects);
|
|
105
142
|
console.debug("replaceAudioEffects", replaceAudioEffects);
|
|
143
|
+
console.debug("replaceTimeline", replaceTimeline);
|
|
106
144
|
asDefined(targetAudioUnitBox.input.pointerHub.incoming().at(0)?.box, "Target has no input").delete();
|
|
107
145
|
if (replaceMIDIEffects) {
|
|
108
146
|
targetAudioUnitBox.midiEffects.pointerHub.incoming().forEach(({ box }) => box.delete());
|
|
@@ -120,16 +158,30 @@ export var PresetDecoder;
|
|
|
120
158
|
sourceAudioUnitBox.audioEffects.pointerHub.incoming().forEach(({ box }) => box.delete());
|
|
121
159
|
sourceBoxGraph.endTransaction();
|
|
122
160
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
161
|
+
const sourceHasTracks = sourceAudioUnitBox.tracks.pointerHub.incoming().length > 0;
|
|
162
|
+
if (sourceHasTracks && replaceTimeline) {
|
|
163
|
+
targetAudioUnitBox.tracks.pointerHub.incoming().forEach(({ box }) => box.delete());
|
|
164
|
+
}
|
|
165
|
+
// Capture boxes live on the target's AudioUnit already and must not be duplicated.
|
|
166
|
+
// When the caller wants to keep the target's existing timeline, also exclude TrackBox
|
|
167
|
+
// (and everything reached through it) so source tracks aren't copied in.
|
|
168
|
+
const excludeBox = (box) => {
|
|
169
|
+
if (box.accept({
|
|
170
|
+
visitCaptureMidiBox: (_box) => true,
|
|
171
|
+
visitCaptureAudioBox: (_box) => true
|
|
172
|
+
}) === true) {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
if (!replaceTimeline && TransferUtils.excludeTimelinePredicate(box)) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
return false;
|
|
179
|
+
};
|
|
129
180
|
const uuidMap = UUID.newSet(({ source }) => source);
|
|
130
181
|
const dependencies = Array.from(sourceBoxGraph.dependenciesOf(sourceAudioUnitBox, {
|
|
131
182
|
excludeBox,
|
|
132
|
-
alwaysFollowMandatory:
|
|
183
|
+
alwaysFollowMandatory: true,
|
|
184
|
+
stopAtResources: true
|
|
133
185
|
}).boxes);
|
|
134
186
|
uuidMap.addMany([
|
|
135
187
|
{
|
|
@@ -154,9 +206,9 @@ export var PresetDecoder;
|
|
|
154
206
|
}
|
|
155
207
|
});
|
|
156
208
|
PointerField.decodeWith({
|
|
157
|
-
map: (_pointer, newAddress) => newAddress.
|
|
158
|
-
|
|
159
|
-
|
|
209
|
+
map: (_pointer, newAddress) => newAddress.flatMap(address => uuidMap.opt(address.uuid).match({
|
|
210
|
+
some: ({ target }) => Option.wrap(address.moveTo(target)),
|
|
211
|
+
none: () => targetBoxGraph.findBox(address.uuid).nonEmpty() ? Option.wrap(address) : Option.None
|
|
160
212
|
}))
|
|
161
213
|
}, () => {
|
|
162
214
|
dependencies
|
|
@@ -175,4 +227,104 @@ export var PresetDecoder;
|
|
|
175
227
|
});
|
|
176
228
|
return Attempts.Ok;
|
|
177
229
|
};
|
|
230
|
+
PresetDecoder.insertEffectChain = (bytes, targetAudioUnit, insertIndex, kind) => {
|
|
231
|
+
const headerInput = new ByteArrayInput(bytes.slice(0, 8));
|
|
232
|
+
if (headerInput.readInt() !== PresetHeader.MAGIC_HEADER_OPEN) {
|
|
233
|
+
return Attempts.err("Invalid preset header");
|
|
234
|
+
}
|
|
235
|
+
const version = headerInput.readInt();
|
|
236
|
+
if (version !== PresetHeader.FORMAT_VERSION) {
|
|
237
|
+
return Attempts.err(`Unsupported preset version ${version} (this build supports ${PresetHeader.FORMAT_VERSION}).`);
|
|
238
|
+
}
|
|
239
|
+
const sourceGraph = new BoxGraph(Option.wrap(BoxIO.create));
|
|
240
|
+
const loaded = tryCatch(() => sourceGraph.fromArrayBuffer(bytes.slice(8), false));
|
|
241
|
+
if (loaded.status === "failure") {
|
|
242
|
+
return Attempts.err(`Failed to decode preset: ${String(loaded.error)}`);
|
|
243
|
+
}
|
|
244
|
+
const sourceAudioUnit = sourceGraph.boxes()
|
|
245
|
+
.filter(box => isInstanceOf(box, AudioUnitBox))
|
|
246
|
+
.map(box => asInstanceOf(box, AudioUnitBox))
|
|
247
|
+
.find(box => box.type.getValue() !== AudioUnitType.Output);
|
|
248
|
+
if (isAbsent(sourceAudioUnit)) {
|
|
249
|
+
return Attempts.err("Preset contains no audio unit");
|
|
250
|
+
}
|
|
251
|
+
const sourceField = kind === PresetHeader.ChainKind.Audio
|
|
252
|
+
? sourceAudioUnit.audioEffects
|
|
253
|
+
: sourceAudioUnit.midiEffects;
|
|
254
|
+
const effects = IndexedBox.collectIndexedBoxes(sourceField);
|
|
255
|
+
if (effects.length === 0) {
|
|
256
|
+
return Attempts.err("Preset contains no effects of the requested kind");
|
|
257
|
+
}
|
|
258
|
+
const targetField = kind === PresetHeader.ChainKind.Audio
|
|
259
|
+
? targetAudioUnit.audioEffects
|
|
260
|
+
: targetAudioUnit.midiEffects;
|
|
261
|
+
const targetFieldAddress = targetField.address;
|
|
262
|
+
const hostPointerType = kind === PresetHeader.ChainKind.Audio
|
|
263
|
+
? Pointers.AudioEffectHost
|
|
264
|
+
: Pointers.MIDIEffectHost;
|
|
265
|
+
const targetGraph = targetAudioUnit.graph;
|
|
266
|
+
const count = effects.length;
|
|
267
|
+
const existing = IndexedBox.collectIndexedBoxes(targetField);
|
|
268
|
+
for (let i = existing.length - 1; i >= 0; i--) {
|
|
269
|
+
const box = existing[i];
|
|
270
|
+
const current = box.index.getValue();
|
|
271
|
+
if (current >= insertIndex) {
|
|
272
|
+
box.index.setValue(current + count);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
const excludeBox = (box) => TransferUtils.shouldExclude(box)
|
|
276
|
+
|| TransferUtils.excludeTimelinePredicate(box)
|
|
277
|
+
|| box instanceof AudioUnitBox;
|
|
278
|
+
const effectSet = new Set(effects);
|
|
279
|
+
const dependencies = Array.from(sourceGraph.dependenciesOf(effects, {
|
|
280
|
+
alwaysFollowMandatory: true,
|
|
281
|
+
stopAtResources: true,
|
|
282
|
+
excludeBox
|
|
283
|
+
}).boxes).filter(box => !effectSet.has(box));
|
|
284
|
+
const existingPreservedUuids = UUID.newSet(uuid => uuid);
|
|
285
|
+
dependencies.forEach(source => {
|
|
286
|
+
if (source.resource === "preserved" && targetGraph.findBox(source.address.uuid).nonEmpty()) {
|
|
287
|
+
existingPreservedUuids.add(source.address.uuid);
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
const uuidMap = UUID.newSet(({ source }) => source);
|
|
291
|
+
uuidMap.addMany([
|
|
292
|
+
...effects.map(box => ({ source: box.address.uuid, target: UUID.generate() })),
|
|
293
|
+
...dependencies.map(box => ({
|
|
294
|
+
source: box.address.uuid,
|
|
295
|
+
target: box.resource === "preserved" ? box.address.uuid : UUID.generate()
|
|
296
|
+
}))
|
|
297
|
+
]);
|
|
298
|
+
PointerField.decodeWith({
|
|
299
|
+
map: (pointer, address) => {
|
|
300
|
+
if (pointer.pointerType === hostPointerType) {
|
|
301
|
+
return Option.wrap(targetFieldAddress);
|
|
302
|
+
}
|
|
303
|
+
return address.flatMap(addr => uuidMap.opt(addr.uuid).match({
|
|
304
|
+
some: ({ target }) => Option.wrap(addr.moveTo(target)),
|
|
305
|
+
none: () => targetGraph.findBox(addr.uuid).nonEmpty() ? Option.wrap(addr) : Option.None
|
|
306
|
+
}));
|
|
307
|
+
}
|
|
308
|
+
}, () => {
|
|
309
|
+
effects.forEach((source, i) => {
|
|
310
|
+
const input = new ByteArrayInput(source.toArrayBuffer());
|
|
311
|
+
const uuid = uuidMap.get(source.address.uuid).target;
|
|
312
|
+
targetGraph.createBox(source.name, uuid, box => {
|
|
313
|
+
box.read(input);
|
|
314
|
+
if (IndexedBox.isIndexedBox(box)) {
|
|
315
|
+
box.index.setValue(insertIndex + i);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
dependencies.forEach(source => {
|
|
320
|
+
if (existingPreservedUuids.hasKey(source.address.uuid)) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
const input = new ByteArrayInput(source.toArrayBuffer());
|
|
324
|
+
const uuid = uuidMap.get(source.address.uuid).target;
|
|
325
|
+
targetGraph.createBox(source.name, uuid, box => box.read(input));
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
return Attempts.Ok;
|
|
329
|
+
};
|
|
178
330
|
})(PresetDecoder || (PresetDecoder = {}));
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
import { Box } from "@opendaw/lib-box";
|
|
1
2
|
import { AudioUnitBox } from "@opendaw/studio-boxes";
|
|
3
|
+
import { PresetHeader } from "./PresetHeader";
|
|
2
4
|
export declare namespace PresetEncoder {
|
|
3
|
-
const encode: (audioUnitBox: AudioUnitBox
|
|
5
|
+
const encode: (audioUnitBox: AudioUnitBox, options?: {
|
|
6
|
+
excludeEffect?: (box: Box) => boolean;
|
|
7
|
+
includeTimeline?: boolean;
|
|
8
|
+
}) => ArrayBufferLike;
|
|
9
|
+
const encodeEffects: (effects: ReadonlyArray<Box>, kind: PresetHeader.ChainKind) => ArrayBufferLike;
|
|
4
10
|
}
|
|
5
11
|
//# sourceMappingURL=PresetEncoder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PresetEncoder.d.ts","sourceRoot":"","sources":["../../src/preset/PresetEncoder.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PresetEncoder.d.ts","sourceRoot":"","sources":["../../src/preset/PresetEncoder.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,GAAG,EAA2B,MAAM,kBAAkB,CAAA;AAC9D,OAAO,EAAC,YAAY,EAA4D,MAAM,uBAAuB,CAAA;AAI7G,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAE3C,yBAAiB,aAAa,CAAC;IACpB,MAAM,MAAM,GAAI,cAAc,YAAY,EAC1B,UAAS;QACL,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;QACtC,eAAe,CAAC,EAAE,OAAO,CAAA;KACvB,KAAG,eA+B/B,CAAA;IAEM,MAAM,aAAa,GACtB,SAAS,aAAa,CAAC,GAAG,CAAC,EAC3B,MAAM,YAAY,CAAC,SAAS,KAC7B,eA0EF,CAAA;CACJ"}
|
|
@@ -1,29 +1,115 @@
|
|
|
1
|
-
import { Arrays, ByteArrayOutput } from "@opendaw/lib-std";
|
|
1
|
+
import { Arrays, ByteArrayInput, ByteArrayOutput, Option, UUID } from "@opendaw/lib-std";
|
|
2
|
+
import { IndexedBox, PointerField } from "@opendaw/lib-box";
|
|
3
|
+
import { AudioUnitBox, CaptureAudioBox, CaptureMidiBox, NoopInstrumentBox } from "@opendaw/studio-boxes";
|
|
4
|
+
import { AudioUnitType, Pointers } from "@opendaw/studio-enums";
|
|
2
5
|
import { ProjectSkeleton } from "../project/ProjectSkeleton";
|
|
3
6
|
import { TransferUtils } from "../transfer";
|
|
4
7
|
import { PresetHeader } from "./PresetHeader";
|
|
5
8
|
export var PresetEncoder;
|
|
6
9
|
(function (PresetEncoder) {
|
|
7
|
-
PresetEncoder.encode = (audioUnitBox) => {
|
|
10
|
+
PresetEncoder.encode = (audioUnitBox, options = {}) => {
|
|
8
11
|
const header = ByteArrayOutput.create();
|
|
9
12
|
header.writeInt(PresetHeader.MAGIC_HEADER_OPEN);
|
|
10
13
|
header.writeInt(PresetHeader.FORMAT_VERSION);
|
|
11
14
|
const preset = ProjectSkeleton.empty({ createOutputMaximizer: false, createDefaultUser: false });
|
|
12
15
|
const { boxGraph, mandatoryBoxes: { rootBox, primaryAudioBusBox } } = preset;
|
|
13
16
|
const audioUnitBoxes = [audioUnitBox];
|
|
14
|
-
const
|
|
17
|
+
const excludeEffect = options.excludeEffect ?? (() => false);
|
|
18
|
+
const includeTimeline = options.includeTimeline === true;
|
|
19
|
+
const excludeBox = (box) => TransferUtils.shouldExclude(box)
|
|
20
|
+
|| (!includeTimeline && TransferUtils.excludeTimelinePredicate(box))
|
|
21
|
+
|| excludeEffect(box);
|
|
15
22
|
boxGraph.beginTransaction();
|
|
16
23
|
const dependencies = Array.from(audioUnitBox.graph.dependenciesOf(audioUnitBoxes, {
|
|
17
24
|
alwaysFollowMandatory: true,
|
|
18
25
|
stopAtResources: true,
|
|
19
26
|
excludeBox
|
|
20
27
|
}).boxes);
|
|
28
|
+
const summary = {};
|
|
29
|
+
for (const dep of dependencies) {
|
|
30
|
+
summary[dep.name] = (summary[dep.name] ?? 0) + 1;
|
|
31
|
+
}
|
|
32
|
+
console.info(`PresetEncoder.encode: includeTimeline=${includeTimeline}, deps=${dependencies.length}`, summary);
|
|
21
33
|
const uuidMap = TransferUtils.generateMap(audioUnitBoxes, dependencies, rootBox.audioUnits.address.uuid, primaryAudioBusBox.address.uuid);
|
|
22
34
|
TransferUtils.copyBoxes(uuidMap, boxGraph, audioUnitBoxes, dependencies);
|
|
23
35
|
TransferUtils.reorderAudioUnits(uuidMap, audioUnitBoxes, rootBox);
|
|
24
36
|
boxGraph.endTransaction();
|
|
25
|
-
|
|
26
|
-
|
|
37
|
+
return Arrays.concatArrayBuffers(header.toArrayBuffer(), boxGraph.toArrayBuffer());
|
|
38
|
+
};
|
|
39
|
+
PresetEncoder.encodeEffects = (effects, kind) => {
|
|
40
|
+
const header = ByteArrayOutput.create();
|
|
41
|
+
header.writeInt(PresetHeader.MAGIC_HEADER_OPEN);
|
|
42
|
+
header.writeInt(PresetHeader.FORMAT_VERSION);
|
|
43
|
+
const preset = ProjectSkeleton.empty({ createOutputMaximizer: false, createDefaultUser: false });
|
|
44
|
+
const { boxGraph, mandatoryBoxes: { rootBox, primaryAudioBusBox } } = preset;
|
|
45
|
+
boxGraph.beginTransaction();
|
|
46
|
+
const captureBox = kind === PresetHeader.ChainKind.Audio
|
|
47
|
+
? CaptureAudioBox.create(boxGraph, UUID.generate())
|
|
48
|
+
: CaptureMidiBox.create(boxGraph, UUID.generate());
|
|
49
|
+
const wrapperAudioUnit = AudioUnitBox.create(boxGraph, UUID.generate(), box => {
|
|
50
|
+
box.collection.refer(rootBox.audioUnits);
|
|
51
|
+
box.output.refer(primaryAudioBusBox.input);
|
|
52
|
+
box.index.setValue(0);
|
|
53
|
+
box.type.setValue(AudioUnitType.Instrument);
|
|
54
|
+
box.capture.refer(captureBox);
|
|
55
|
+
});
|
|
56
|
+
NoopInstrumentBox.create(boxGraph, UUID.generate(), box => {
|
|
57
|
+
box.host.refer(wrapperAudioUnit.input);
|
|
58
|
+
});
|
|
59
|
+
if (effects.length > 0) {
|
|
60
|
+
const sourceGraph = effects[0].graph;
|
|
61
|
+
const excludeBox = (box) => TransferUtils.shouldExclude(box)
|
|
62
|
+
|| TransferUtils.excludeTimelinePredicate(box)
|
|
63
|
+
|| box instanceof AudioUnitBox;
|
|
64
|
+
const effectSet = new Set(effects);
|
|
65
|
+
const dependencies = Array.from(sourceGraph.dependenciesOf(effects, {
|
|
66
|
+
alwaysFollowMandatory: true,
|
|
67
|
+
stopAtResources: true,
|
|
68
|
+
excludeBox
|
|
69
|
+
}).boxes).filter(box => !effectSet.has(box));
|
|
70
|
+
const uuidMap = UUID.newSet(({ source }) => source);
|
|
71
|
+
uuidMap.addMany([
|
|
72
|
+
...effects.map(box => ({ source: box.address.uuid, target: UUID.generate() })),
|
|
73
|
+
...dependencies.map(box => ({
|
|
74
|
+
source: box.address.uuid,
|
|
75
|
+
target: box.resource === "preserved" ? box.address.uuid : UUID.generate()
|
|
76
|
+
}))
|
|
77
|
+
]);
|
|
78
|
+
const targetField = kind === PresetHeader.ChainKind.Audio
|
|
79
|
+
? wrapperAudioUnit.audioEffects
|
|
80
|
+
: wrapperAudioUnit.midiEffects;
|
|
81
|
+
const hostPointerType = kind === PresetHeader.ChainKind.Audio
|
|
82
|
+
? Pointers.AudioEffectHost
|
|
83
|
+
: Pointers.MIDIEffectHost;
|
|
84
|
+
PointerField.decodeWith({
|
|
85
|
+
map: (pointer, address) => {
|
|
86
|
+
if (pointer.pointerType === hostPointerType) {
|
|
87
|
+
return Option.wrap(targetField.address);
|
|
88
|
+
}
|
|
89
|
+
return address.flatMap(addr => uuidMap.opt(addr.uuid).match({
|
|
90
|
+
some: ({ target }) => Option.wrap(addr.moveTo(target)),
|
|
91
|
+
none: () => boxGraph.findBox(addr.uuid).nonEmpty() ? Option.wrap(addr) : Option.None
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
}, () => {
|
|
95
|
+
effects.forEach((source, i) => {
|
|
96
|
+
const input = new ByteArrayInput(source.toArrayBuffer());
|
|
97
|
+
const uuid = uuidMap.get(source.address.uuid).target;
|
|
98
|
+
boxGraph.createBox(source.name, uuid, box => {
|
|
99
|
+
box.read(input);
|
|
100
|
+
if (IndexedBox.isIndexedBox(box)) {
|
|
101
|
+
box.index.setValue(i);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
dependencies.forEach(source => {
|
|
106
|
+
const input = new ByteArrayInput(source.toArrayBuffer());
|
|
107
|
+
const uuid = uuidMap.get(source.address.uuid).target;
|
|
108
|
+
boxGraph.createBox(source.name, uuid, box => box.read(input));
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
boxGraph.endTransaction();
|
|
27
113
|
return Arrays.concatArrayBuffers(header.toArrayBuffer(), boxGraph.toArrayBuffer());
|
|
28
114
|
};
|
|
29
115
|
})(PresetEncoder || (PresetEncoder = {}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PresetHeader.d.ts","sourceRoot":"","sources":["../../src/preset/PresetHeader.ts"],"names":[],"mappings":"AAAA,yBAAiB,YAAY,CAAC;IACnB,MAAM,iBAAiB,aAAa,CAAA;IACpC,MAAM,cAAc,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"PresetHeader.d.ts","sourceRoot":"","sources":["../../src/preset/PresetHeader.ts"],"names":[],"mappings":"AAAA,yBAAiB,YAAY,CAAC;IACnB,MAAM,iBAAiB,aAAa,CAAA;IACpC,MAAM,cAAc,IAAI,CAAA;IAE/B,KAAY,SAAS;QAAE,IAAI,IAAI;QAAE,KAAK,IAAI;KAAC;CAC9C"}
|
|
@@ -2,4 +2,9 @@ export var PresetHeader;
|
|
|
2
2
|
(function (PresetHeader) {
|
|
3
3
|
PresetHeader.MAGIC_HEADER_OPEN = 0x4F505245; // OPRE
|
|
4
4
|
PresetHeader.FORMAT_VERSION = 1;
|
|
5
|
+
let ChainKind;
|
|
6
|
+
(function (ChainKind) {
|
|
7
|
+
ChainKind[ChainKind["Midi"] = 0] = "Midi";
|
|
8
|
+
ChainKind[ChainKind["Audio"] = 1] = "Audio";
|
|
9
|
+
})(ChainKind = PresetHeader.ChainKind || (PresetHeader.ChainKind = {}));
|
|
5
10
|
})(PresetHeader || (PresetHeader = {}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VertexSelection.d.ts","sourceRoot":"","sources":["../../src/selection/VertexSelection.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,SAAS,EACT,OAAO,EACP,GAAG,EAGH,SAAS,EACT,SAAS,EACT,iBAAiB,EAEjB,YAAY,EAGf,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAU,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAe,MAAM,kBAAkB,CAAA;AACpF,OAAO,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAA;AAE9C,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AAEnD,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAA;AAErD;;;GAGG;AACH,qBAAa,eAAgB,YAAW,SAAS,CAAC,gBAAgB,CAAC;;IAQnD,QAAQ,CAAC,OAAO,EAAE,OAAO;IAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ;gBAA7C,OAAO,EAAE,OAAO,EAAW,QAAQ,EAAE,QAAQ;IAOlE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,IAAI;IAQ/C,OAAO,IAAI,IAAI;IASf,uBAAuB,CAAC,CAAC,SAAS,WAAW,EAAE,SAAS,EAAE,SAAS,CAAC,gBAAgB,CAAC,EACtC,GAAG,EAAE,SAAS,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC;IAIzG,MAAM,CAAC,GAAG,WAAW,EAAE,aAAa,CAAC,gBAAgB,CAAC,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"VertexSelection.d.ts","sourceRoot":"","sources":["../../src/selection/VertexSelection.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,SAAS,EACT,OAAO,EACP,GAAG,EAGH,SAAS,EACT,SAAS,EACT,iBAAiB,EAEjB,YAAY,EAGf,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAU,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAe,MAAM,kBAAkB,CAAA;AACpF,OAAO,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAA;AAE9C,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AAEnD,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAA;AAErD;;;GAGG;AACH,qBAAa,eAAgB,YAAW,SAAS,CAAC,gBAAgB,CAAC;;IAQnD,QAAQ,CAAC,OAAO,EAAE,OAAO;IAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ;gBAA7C,OAAO,EAAE,OAAO,EAAW,QAAQ,EAAE,QAAQ;IAOlE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,IAAI;IAQ/C,OAAO,IAAI,IAAI;IASf,uBAAuB,CAAC,CAAC,SAAS,WAAW,EAAE,SAAS,EAAE,SAAS,CAAC,gBAAgB,CAAC,EACtC,GAAG,EAAE,SAAS,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC;IAIzG,MAAM,CAAC,GAAG,WAAW,EAAE,aAAa,CAAC,gBAAgB,CAAC,GAAG,IAAI;IAoB7D,QAAQ,CAAC,GAAG,WAAW,EAAE,aAAa,CAAC,gBAAgB,CAAC,GAAG,IAAI;IAW/D,WAAW,IAAI,IAAI;IAInB,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,aAAa,CAAC,gBAAgB,CAAC;IAQhF,OAAO,IAAI,OAAO;IAClB,QAAQ,IAAI,OAAO;IAEnB,KAAK,IAAI,GAAG;IAEZ,UAAU,CAAC,UAAU,EAAE,gBAAgB,GAAG,OAAO;IAEjD,QAAQ,IAAI,aAAa,CAAC,gBAAgB,CAAC;IAE3C,SAAS,CAAC,QAAQ,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAEtE,mBAAmB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,GAAG,YAAY;CA4BnF"}
|
|
@@ -65,6 +65,9 @@ export class VertexSelection {
|
|
|
65
65
|
this.editing.modify(() => {
|
|
66
66
|
const selection = __classPrivateFieldGet(this, _VertexSelection_target, "f").unwrap();
|
|
67
67
|
for (const selectable of selectables) {
|
|
68
|
+
if (!selectable.isAttached()) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
68
71
|
if (!__classPrivateFieldGet(this, _VertexSelection_selectableMap, "f").hasKey(selectable.address)) {
|
|
69
72
|
SelectionBox.create(this.boxGraph, UUID.generate(), box => {
|
|
70
73
|
box.selectable.refer(selectable);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Arrays, asInstanceOf, assert, ByteArrayInput, clamp, isDefined, isInstanceOf, SetMultimap, UUID } from "@opendaw/lib-std";
|
|
1
|
+
import { Arrays, asInstanceOf, assert, ByteArrayInput, clamp, isDefined, isInstanceOf, Option, SetMultimap, UUID } from "@opendaw/lib-std";
|
|
2
2
|
import { AudioUnitBox, AuxSendBox, TrackBox } from "@opendaw/studio-boxes";
|
|
3
3
|
import { IndexedBox, PointerField } from "@opendaw/lib-box";
|
|
4
4
|
import { UnionBoxTypes } from "../unions";
|
|
@@ -54,9 +54,9 @@ export var TransferUtils;
|
|
|
54
54
|
return false;
|
|
55
55
|
};
|
|
56
56
|
PointerField.decodeWith({
|
|
57
|
-
map: (_pointer, address) => address.
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
map: (_pointer, address) => address.flatMap(addr => uuidMap.opt(addr.uuid).match({
|
|
58
|
+
some: ({ target }) => Option.wrap(addr.moveTo(target)),
|
|
59
|
+
none: () => targetBoxGraph.findBox(addr.uuid).nonEmpty() ? Option.wrap(addr) : Option.None
|
|
60
60
|
}))
|
|
61
61
|
}, () => {
|
|
62
62
|
audioUnitBoxes.forEach((source) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opendaw/studio-adapters",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.108",
|
|
4
4
|
"license": "LGPL-3.0-or-later",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -23,18 +23,18 @@
|
|
|
23
23
|
"test": "echo \"No tests to run\""
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@opendaw/lib-box": "^0.0.
|
|
27
|
-
"@opendaw/lib-dsp": "^0.0.
|
|
28
|
-
"@opendaw/lib-fusion": "^0.0.
|
|
29
|
-
"@opendaw/lib-runtime": "^0.0.
|
|
30
|
-
"@opendaw/lib-std": "^0.0.
|
|
31
|
-
"@opendaw/studio-boxes": "^0.0.
|
|
32
|
-
"@opendaw/studio-enums": "^0.0.
|
|
26
|
+
"@opendaw/lib-box": "^0.0.85",
|
|
27
|
+
"@opendaw/lib-dsp": "^0.0.83",
|
|
28
|
+
"@opendaw/lib-fusion": "^0.0.92",
|
|
29
|
+
"@opendaw/lib-runtime": "^0.0.78",
|
|
30
|
+
"@opendaw/lib-std": "^0.0.77",
|
|
31
|
+
"@opendaw/studio-boxes": "^0.0.90",
|
|
32
|
+
"@opendaw/studio-enums": "^0.0.74",
|
|
33
33
|
"soundfont2": "^0.5.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@opendaw/eslint-config": "^0.0.
|
|
37
|
-
"@opendaw/typescript-config": "^0.0.
|
|
36
|
+
"@opendaw/eslint-config": "^0.0.28",
|
|
37
|
+
"@opendaw/typescript-config": "^0.0.31"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "df20edf139f65d8d3146ae44e0e800054550bf12"
|
|
40
40
|
}
|