@opendaw/studio-core 0.0.43 → 0.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AssetService.d.ts +12 -2
- package/dist/AssetService.d.ts.map +1 -1
- package/dist/AssetService.js +46 -1
- package/dist/AudioOfflineRenderer.d.ts +1 -2
- package/dist/AudioOfflineRenderer.d.ts.map +1 -1
- package/dist/AudioOfflineRenderer.js +10 -3
- package/dist/EffectBox.d.ts +2 -2
- package/dist/EffectBox.d.ts.map +1 -1
- package/dist/EffectFactories.d.ts +6 -0
- package/dist/EffectFactories.d.ts.map +1 -1
- package/dist/EffectFactories.js +29 -24
- package/dist/EffectFactory.d.ts +1 -1
- package/dist/EffectFactory.d.ts.map +1 -1
- package/dist/EffectParameterDefaults.d.ts +5 -0
- package/dist/EffectParameterDefaults.d.ts.map +1 -0
- package/dist/EffectParameterDefaults.js +27 -0
- package/dist/Engine.d.ts +1 -1
- package/dist/Engine.d.ts.map +1 -1
- package/dist/EngineFacade.d.ts +1 -1
- package/dist/EngineFacade.d.ts.map +1 -1
- package/dist/EngineFacade.js +1 -1
- package/dist/EngineWorklet.d.ts +2 -2
- package/dist/EngineWorklet.d.ts.map +1 -1
- package/dist/EngineWorklet.js +3 -2
- package/dist/Preferences.d.ts +20 -0
- package/dist/Preferences.d.ts.map +1 -0
- package/dist/Preferences.js +46 -0
- package/dist/capture/CaptureDevices.js +3 -3
- package/dist/capture/RecordTrack.d.ts +2 -2
- package/dist/capture/RecordTrack.d.ts.map +1 -1
- package/dist/capture/Recording.d.ts +1 -1
- package/dist/capture/Recording.d.ts.map +1 -1
- package/dist/capture/Recording.js +1 -1
- package/dist/cloud/CloudAuthManager.d.ts +6 -2
- package/dist/cloud/CloudAuthManager.d.ts.map +1 -1
- package/dist/cloud/CloudAuthManager.js +12 -12
- package/dist/cloud/CloudBackup.js +1 -1
- package/dist/cloud/{CloudBackupSoundfont.d.ts → CloudBackupSoundfonts.d.ts} +1 -1
- package/dist/cloud/CloudBackupSoundfonts.d.ts.map +1 -0
- package/dist/cloud/{CloudBackupSoundfont.js → CloudBackupSoundfonts.js} +1 -1
- package/dist/dawproject/BuiltinDevices.d.ts.map +1 -1
- package/dist/dawproject/BuiltinDevices.js +3 -2
- package/dist/dawproject/{DawProjectImport.d.ts → DawProjectImporter.d.ts} +1 -1
- package/dist/dawproject/DawProjectImporter.d.ts.map +1 -0
- package/dist/dawproject/{DawProjectImport.js → DawProjectImporter.js} +17 -5
- package/dist/dawproject/DawProjectImporter.test.d.ts +2 -0
- package/dist/dawproject/DawProjectImporter.test.d.ts.map +1 -0
- package/dist/dawproject/{DawProjectImport.test.js → DawProjectImporter.test.js} +1 -1
- package/dist/dawproject/DawProjectService.js +1 -1
- package/dist/dawproject/index.d.ts +1 -1
- package/dist/dawproject/index.d.ts.map +1 -1
- package/dist/dawproject/index.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/midi/MIDILearning.d.ts +1 -1
- package/dist/midi/MIDILearning.d.ts.map +1 -1
- package/dist/midi/MIDILearning.js +22 -3
- package/dist/processors.js +27 -5
- package/dist/processors.js.map +4 -4
- package/dist/project/Project.d.ts +12 -8
- package/dist/project/Project.d.ts.map +1 -1
- package/dist/project/Project.js +45 -33
- package/dist/project/ProjectMigration.d.ts.map +1 -1
- package/dist/project/ProjectMigration.js +10 -1
- package/dist/project/Recovery.d.ts +9 -0
- package/dist/project/Recovery.d.ts.map +1 -0
- package/dist/project/Recovery.js +49 -0
- package/dist/project/index.d.ts +1 -0
- package/dist/project/index.d.ts.map +1 -1
- package/dist/project/index.js +1 -0
- package/dist/samples/OpenSampleAPI.d.ts.map +1 -1
- package/dist/samples/OpenSampleAPI.js +5 -3
- package/dist/samples/SampleService.d.ts +5 -2
- package/dist/samples/SampleService.d.ts.map +1 -1
- package/dist/samples/SampleService.js +12 -4
- package/dist/samples/SampleStorage.d.ts +1 -1
- package/dist/samples/SampleStorage.d.ts.map +1 -1
- package/dist/samples/SampleStorage.js +1 -1
- package/dist/soundfont/DefaultSoundfontLoader.d.ts +2 -1
- package/dist/soundfont/DefaultSoundfontLoader.d.ts.map +1 -1
- package/dist/soundfont/DefaultSoundfontLoader.js +14 -4
- package/dist/soundfont/DefaultSoundfontLoaderManager.d.ts +2 -1
- package/dist/soundfont/DefaultSoundfontLoaderManager.d.ts.map +1 -1
- package/dist/soundfont/DefaultSoundfontLoaderManager.js +1 -0
- package/dist/soundfont/OpenSoundfontAPI.d.ts.map +1 -1
- package/dist/soundfont/OpenSoundfontAPI.js +6 -4
- package/dist/soundfont/SoundfontService.d.ts +5 -2
- package/dist/soundfont/SoundfontService.d.ts.map +1 -1
- package/dist/soundfont/SoundfontService.js +18 -8
- package/dist/workers-main.js +2 -2
- package/dist/workers-main.js.map +4 -4
- package/dist/ysync/YService.d.ts.map +1 -1
- package/dist/ysync/YService.js +4 -2
- package/dist/ysync/YSync.d.ts.map +1 -1
- package/dist/ysync/YSync.js +79 -51
- package/package.json +49 -48
- package/dist/cloud/CloudBackupSoundfont.d.ts.map +0 -1
- package/dist/dawproject/DawProjectImport.d.ts.map +0 -1
- package/dist/dawproject/DawProjectImport.test.d.ts +0 -2
- package/dist/dawproject/DawProjectImport.test.d.ts.map +0 -1
- package/dist/env.d.ts +0 -6
- package/dist/env.d.ts.map +0 -1
- package/dist/env.js +0 -9
|
@@ -1,33 +1,36 @@
|
|
|
1
|
-
import { Procedure, Terminable, TerminableOwner, Terminator } from "@opendaw/lib-std";
|
|
2
|
-
import {
|
|
1
|
+
import { Func, Procedure, Terminable, TerminableOwner, Terminator } from "@opendaw/lib-std";
|
|
2
|
+
import { BoxEditing, BoxGraph } from "@opendaw/lib-box";
|
|
3
3
|
import { AudioBusBox, AudioUnitBox, BoxIO, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
|
|
4
4
|
import { BoxAdapters, BoxAdaptersContext, ClipSequencing, ParameterFieldAdapters, ProcessorOptions, ProjectSkeleton, RootBoxAdapter, SampleLoaderManager, SoundfontLoaderManager, TimelineBoxAdapter, UserEditingManager, VertexSelection } from "@opendaw/studio-adapters";
|
|
5
5
|
import { LiveStreamBroadcaster, LiveStreamReceiver } from "@opendaw/lib-fusion";
|
|
6
6
|
import { ProjectEnv } from "./ProjectEnv";
|
|
7
7
|
import { Mixer } from "../Mixer";
|
|
8
8
|
import { ProjectApi } from "./ProjectApi";
|
|
9
|
-
import { CaptureDevices } from "../capture
|
|
9
|
+
import { CaptureDevices } from "../capture";
|
|
10
10
|
import { EngineFacade } from "../EngineFacade";
|
|
11
11
|
import { EngineWorklet } from "../EngineWorklet";
|
|
12
|
-
import { MIDILearning } from "../midi
|
|
12
|
+
import { MIDILearning } from "../midi";
|
|
13
13
|
export type RestartWorklet = {
|
|
14
|
-
unload:
|
|
14
|
+
unload: Func<unknown, Promise<unknown>>;
|
|
15
15
|
load: Procedure<EngineWorklet>;
|
|
16
16
|
};
|
|
17
|
+
export type ProjectCreateOptions = {
|
|
18
|
+
noDefaultUser?: boolean;
|
|
19
|
+
};
|
|
17
20
|
export declare class Project implements BoxAdaptersContext, Terminable, TerminableOwner {
|
|
18
21
|
#private;
|
|
19
|
-
static new(env: ProjectEnv): Project;
|
|
22
|
+
static new(env: ProjectEnv, options?: ProjectCreateOptions): Project;
|
|
20
23
|
static load(env: ProjectEnv, arrayBuffer: ArrayBuffer): Project;
|
|
21
24
|
static skeleton(env: ProjectEnv, skeleton: ProjectSkeleton): Project;
|
|
22
25
|
readonly boxGraph: BoxGraph<BoxIO.TypeMap>;
|
|
23
26
|
readonly rootBox: RootBox;
|
|
24
|
-
readonly
|
|
27
|
+
readonly userInterfaceBoxes: ReadonlyArray<UserInterfaceBox>;
|
|
25
28
|
readonly masterBusBox: AudioBusBox;
|
|
26
29
|
readonly masterAudioUnit: AudioUnitBox;
|
|
27
30
|
readonly timelineBox: TimelineBox;
|
|
28
31
|
readonly api: ProjectApi;
|
|
29
32
|
readonly captureDevices: CaptureDevices;
|
|
30
|
-
readonly editing:
|
|
33
|
+
readonly editing: BoxEditing;
|
|
31
34
|
readonly selection: VertexSelection;
|
|
32
35
|
readonly boxAdapters: BoxAdapters;
|
|
33
36
|
readonly userEditingManager: UserEditingManager;
|
|
@@ -39,6 +42,7 @@ export declare class Project implements BoxAdaptersContext, Terminable, Terminab
|
|
|
39
42
|
private constructor();
|
|
40
43
|
startAudioWorklet(restart?: RestartWorklet, options?: ProcessorOptions): EngineWorklet;
|
|
41
44
|
startRecording(countIn?: boolean): void;
|
|
45
|
+
follow(box: UserInterfaceBox): void;
|
|
42
46
|
own<T extends Terminable>(terminable: T): T;
|
|
43
47
|
ownAll<T extends Terminable>(...terminables: Array<T>): void;
|
|
44
48
|
spawn(): Terminator;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Project.d.ts","sourceRoot":"","sources":["../../src/project/Project.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"Project.d.ts","sourceRoot":"","sources":["../../src/project/Project.ts"],"names":[],"mappings":"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"}
|
package/dist/project/Project.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { Arrays, ByteArrayOutput, Option, panic, safeExecute, Terminator, UUID } from "@opendaw/lib-std";
|
|
2
|
-
import {
|
|
3
|
-
import { AudioBusBox, AudioUnitBox, BoxIO, GrooveShuffleBox, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
|
|
2
|
+
import { BoxEditing, BoxGraph } from "@opendaw/lib-box";
|
|
3
|
+
import { AudioBusBox, AudioUnitBox, BoxIO, CompressorDeviceBox, GrooveShuffleBox, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
|
|
4
4
|
import { BoxAdapters, IconSymbol, ParameterFieldAdapters, ProjectDecoder, RootBoxAdapter, TimelineBoxAdapter, UnionBoxTypes, UserEditingManager, VertexSelection } from "@opendaw/studio-adapters";
|
|
5
5
|
import { LiveStreamReceiver } from "@opendaw/lib-fusion";
|
|
6
6
|
import { AudioUnitType } from "@opendaw/studio-enums";
|
|
7
7
|
import { Mixer } from "../Mixer";
|
|
8
8
|
import { ProjectApi } from "./ProjectApi";
|
|
9
9
|
import { ProjectMigration } from "./ProjectMigration";
|
|
10
|
-
import { CaptureDevices } from "../capture
|
|
10
|
+
import { CaptureDevices, Recording } from "../capture";
|
|
11
11
|
import { EngineFacade } from "../EngineFacade";
|
|
12
|
-
import {
|
|
13
|
-
import { MIDILearning } from "../midi/MIDILearning";
|
|
12
|
+
import { MIDILearning } from "../midi";
|
|
14
13
|
import { ProjectValidation } from "./ProjectValidation";
|
|
14
|
+
import { Preferences } from "../Preferences";
|
|
15
15
|
// Main Entry Point for a Project
|
|
16
16
|
export class Project {
|
|
17
|
-
static new(env) {
|
|
17
|
+
static new(env, options) {
|
|
18
18
|
const boxGraph = new BoxGraph(Option.wrap(BoxIO.create));
|
|
19
19
|
const isoString = new Date().toISOString();
|
|
20
20
|
console.debug(`New Project created on ${isoString}`);
|
|
@@ -26,29 +26,42 @@ export class Project {
|
|
|
26
26
|
box.groove.refer(grooveShuffleBox);
|
|
27
27
|
box.created.setValue(isoString);
|
|
28
28
|
});
|
|
29
|
-
const
|
|
30
|
-
const masterBusBox = AudioBusBox.create(boxGraph, UUID.generate(), box => {
|
|
29
|
+
const primaryAudioBus = AudioBusBox.create(boxGraph, UUID.generate(), box => {
|
|
31
30
|
box.collection.refer(rootBox.audioBusses);
|
|
32
31
|
box.label.setValue("Output");
|
|
33
32
|
box.icon.setValue(IconSymbol.toName(IconSymbol.SpeakerHeadphone));
|
|
34
33
|
box.color.setValue(/*Colors.blue*/ "hsl(189, 100%, 65%)"); // TODO
|
|
35
34
|
});
|
|
36
|
-
const
|
|
35
|
+
const primaryAudioOutputUnit = AudioUnitBox.create(boxGraph, UUID.generate(), box => {
|
|
37
36
|
box.type.setValue(AudioUnitType.Output);
|
|
38
37
|
box.collection.refer(rootBox.audioUnits);
|
|
39
38
|
box.output.refer(rootBox.outputDevice);
|
|
40
39
|
box.index.setValue(0);
|
|
41
40
|
});
|
|
41
|
+
if (Preferences.values["auto-create-output-compressor"]) {
|
|
42
|
+
CompressorDeviceBox.create(boxGraph, UUID.generate(), box => {
|
|
43
|
+
box.label.setValue("Compressor");
|
|
44
|
+
box.index.setValue(0);
|
|
45
|
+
box.host.refer(primaryAudioOutputUnit.audioEffects);
|
|
46
|
+
box.threshold.setValue(0);
|
|
47
|
+
box.ratio.setValue(24);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
42
50
|
const timelineBox = TimelineBox.create(boxGraph, UUID.generate());
|
|
43
51
|
rootBox.timeline.refer(timelineBox.root);
|
|
44
|
-
|
|
45
|
-
|
|
52
|
+
primaryAudioBus.output.refer(primaryAudioOutputUnit.input);
|
|
53
|
+
const userInterfaceBoxes = [];
|
|
54
|
+
if (options?.noDefaultUser !== true) {
|
|
55
|
+
const userInterfaceBox = UserInterfaceBox.create(boxGraph, UUID.generate());
|
|
56
|
+
userInterfaceBox.root.refer(rootBox.users);
|
|
57
|
+
userInterfaceBoxes.push(userInterfaceBox);
|
|
58
|
+
}
|
|
46
59
|
boxGraph.endTransaction();
|
|
47
60
|
return new Project(env, boxGraph, {
|
|
48
61
|
rootBox,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
primaryAudioBus,
|
|
63
|
+
primaryAudioOutputUnit,
|
|
64
|
+
userInterfaceBoxes,
|
|
52
65
|
timelineBox
|
|
53
66
|
});
|
|
54
67
|
}
|
|
@@ -64,7 +77,7 @@ export class Project {
|
|
|
64
77
|
#env;
|
|
65
78
|
boxGraph;
|
|
66
79
|
rootBox;
|
|
67
|
-
|
|
80
|
+
userInterfaceBoxes;
|
|
68
81
|
masterBusBox;
|
|
69
82
|
masterAudioUnit;
|
|
70
83
|
timelineBox;
|
|
@@ -79,26 +92,28 @@ export class Project {
|
|
|
79
92
|
midiLearning;
|
|
80
93
|
mixer;
|
|
81
94
|
engine = new EngineFacade();
|
|
82
|
-
constructor(env, boxGraph, { rootBox,
|
|
95
|
+
constructor(env, boxGraph, { rootBox, userInterfaceBoxes, primaryAudioBus, primaryAudioOutputUnit, timelineBox }) {
|
|
83
96
|
this.#env = env;
|
|
84
97
|
this.boxGraph = boxGraph;
|
|
85
98
|
this.rootBox = rootBox;
|
|
86
|
-
this.
|
|
87
|
-
this.masterBusBox =
|
|
88
|
-
this.masterAudioUnit =
|
|
99
|
+
this.userInterfaceBoxes = userInterfaceBoxes;
|
|
100
|
+
this.masterBusBox = primaryAudioBus;
|
|
101
|
+
this.masterAudioUnit = primaryAudioOutputUnit;
|
|
89
102
|
this.timelineBox = timelineBox;
|
|
90
103
|
this.api = new ProjectApi(this);
|
|
91
|
-
this.editing = new
|
|
104
|
+
this.editing = new BoxEditing(this.boxGraph);
|
|
92
105
|
this.selection = new VertexSelection(this.editing, this.boxGraph);
|
|
93
106
|
this.parameterFieldAdapters = new ParameterFieldAdapters();
|
|
94
107
|
this.boxAdapters = this.#terminator.own(new BoxAdapters(this));
|
|
95
108
|
this.userEditingManager = new UserEditingManager(this.editing);
|
|
96
|
-
this.userEditingManager.follow(this.userInterfaceBox);
|
|
97
|
-
this.selection.switch(this.userInterfaceBox.selection);
|
|
98
109
|
this.liveStreamReceiver = this.#terminator.own(new LiveStreamReceiver());
|
|
99
110
|
this.midiLearning = this.#terminator.own(new MIDILearning(this));
|
|
100
111
|
this.captureDevices = this.#terminator.own(new CaptureDevices(this));
|
|
101
112
|
this.mixer = new Mixer(this.rootBoxAdapter.audioUnits);
|
|
113
|
+
// TODO We are probably doing that from the outside
|
|
114
|
+
if (this.userInterfaceBoxes.length > 0) {
|
|
115
|
+
this.follow(this.userInterfaceBoxes[0]);
|
|
116
|
+
}
|
|
102
117
|
console.debug(`Project was created on ${this.rootBoxAdapter.created.toString()}`);
|
|
103
118
|
}
|
|
104
119
|
startAudioWorklet(restart, options) {
|
|
@@ -110,8 +125,8 @@ export class Project {
|
|
|
110
125
|
// we will only accept the first error
|
|
111
126
|
engine.removeEventListener("error", handler);
|
|
112
127
|
engine.removeEventListener("processorerror", handler);
|
|
113
|
-
safeExecute(restart?.unload, event);
|
|
114
128
|
lifecycle.terminate();
|
|
129
|
+
await safeExecute(restart?.unload, event);
|
|
115
130
|
safeExecute(restart?.load, this.startAudioWorklet(restart));
|
|
116
131
|
};
|
|
117
132
|
engine.addEventListener("error", handler);
|
|
@@ -127,6 +142,10 @@ export class Project {
|
|
|
127
142
|
}
|
|
128
143
|
Recording.start(this, countIn).finally();
|
|
129
144
|
}
|
|
145
|
+
follow(box) {
|
|
146
|
+
this.userEditingManager.follow(box);
|
|
147
|
+
this.selection.switch(box.selection);
|
|
148
|
+
}
|
|
130
149
|
own(terminable) { return this.#terminator.own(terminable); }
|
|
131
150
|
ownAll(...terminables) { return this.#terminator.ownAll(...terminables); }
|
|
132
151
|
spawn() { return this.#terminator.spawn(); }
|
|
@@ -146,9 +165,9 @@ export class Project {
|
|
|
146
165
|
mandatoryBoxes: {
|
|
147
166
|
rootBox: this.rootBox,
|
|
148
167
|
timelineBox: this.timelineBox,
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
168
|
+
primaryAudioBus: this.masterBusBox,
|
|
169
|
+
primaryAudioOutputUnit: this.masterAudioUnit,
|
|
170
|
+
userInterfaceBoxes: this.userInterfaceBoxes
|
|
152
171
|
}
|
|
153
172
|
};
|
|
154
173
|
}
|
|
@@ -156,16 +175,9 @@ export class Project {
|
|
|
156
175
|
const output = ByteArrayOutput.create();
|
|
157
176
|
output.writeInt(ProjectDecoder.MAGIC_HEADER_OPEN);
|
|
158
177
|
output.writeInt(ProjectDecoder.FORMAT_VERSION);
|
|
159
|
-
// store all boxes
|
|
160
178
|
const boxGraphChunk = this.boxGraph.toArrayBuffer();
|
|
161
179
|
output.writeInt(boxGraphChunk.byteLength);
|
|
162
180
|
output.writeBytes(new Int8Array(boxGraphChunk));
|
|
163
|
-
// store mandatory boxes' addresses
|
|
164
|
-
UUID.toDataOutput(output, this.rootBox.address.uuid);
|
|
165
|
-
UUID.toDataOutput(output, this.userInterfaceBox.address.uuid);
|
|
166
|
-
UUID.toDataOutput(output, this.masterBusBox.address.uuid);
|
|
167
|
-
UUID.toDataOutput(output, this.masterAudioUnit.address.uuid);
|
|
168
|
-
UUID.toDataOutput(output, this.timelineBox.address.uuid);
|
|
169
181
|
return output.toArrayBuffer();
|
|
170
182
|
}
|
|
171
183
|
copy(env) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectMigration.d.ts","sourceRoot":"","sources":["../../src/project/ProjectMigration.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProjectMigration.d.ts","sourceRoot":"","sources":["../../src/project/ProjectMigration.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,eAAe,EAAC,MAAM,0BAA0B,CAAA;AAExD,qBAAa,gBAAgB;IACzB,MAAM,CAAC,OAAO,CAAC,EAAC,QAAQ,EAAE,cAAc,EAAC,EAAE,eAAe,GAAG,IAAI;CA4EpE"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CaptureAudioBox, CaptureMidiBox, GrooveShuffleBox, ValueEventCurveBox } from "@opendaw/studio-boxes";
|
|
2
|
-
import { asDefined, asInstanceOf, UUID } from "@opendaw/lib-std";
|
|
2
|
+
import { asDefined, asInstanceOf, clamp, UUID } from "@opendaw/lib-std";
|
|
3
3
|
import { AudioUnitType } from "@opendaw/studio-enums";
|
|
4
4
|
export class ProjectMigration {
|
|
5
5
|
static migrate({ boxGraph, mandatoryBoxes }) {
|
|
@@ -70,6 +70,15 @@ export class ProjectMigration {
|
|
|
70
70
|
}));
|
|
71
71
|
box.capture.refer(captureBox);
|
|
72
72
|
boxGraph.endTransaction();
|
|
73
|
+
},
|
|
74
|
+
visitRevampDeviceBox: (box) => {
|
|
75
|
+
// Clamp order in RevampDeviceBox to 0-3
|
|
76
|
+
// The older version stored the actual order,
|
|
77
|
+
// but the new version only stores indices, so 4 is not valid anymore
|
|
78
|
+
boxGraph.beginTransaction();
|
|
79
|
+
box.lowPass.order.setValue(clamp(box.lowPass.order.getValue(), 0, 3));
|
|
80
|
+
box.highPass.order.setValue(clamp(box.highPass.order.getValue(), 0, 3));
|
|
81
|
+
boxGraph.endTransaction();
|
|
73
82
|
}
|
|
74
83
|
}));
|
|
75
84
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Option, Provider } from "@opendaw/lib-std";
|
|
2
|
+
import { ProjectEnv, ProjectProfile } from "../";
|
|
3
|
+
export declare class Recovery {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(projectProfileService: Provider<Option<ProjectProfile>>, env: ProjectEnv);
|
|
6
|
+
restoreProfile(): Promise<Option<ProjectProfile>>;
|
|
7
|
+
createBackupCommand(): Option<Provider<Promise<void>>>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=Recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Recovery.d.ts","sourceRoot":"","sources":["../../src/project/Recovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,QAAQ,EAAO,MAAM,kBAAkB,CAAA;AAEvD,OAAO,EAAU,UAAU,EAAe,cAAc,EAAU,MAAM,KAAK,CAAA;AAE7E,qBAAa,QAAQ;;gBAML,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU;IAK9E,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAsBvD,mBAAmB,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;CAgBzD"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Option, UUID } from "@opendaw/lib-std";
|
|
2
|
+
import { Promises } from "@opendaw/lib-runtime";
|
|
3
|
+
import { Project, ProjectProfile, Workers } from "../";
|
|
4
|
+
export class Recovery {
|
|
5
|
+
static #RESTORE_FILE_PATH = ".backup";
|
|
6
|
+
#projectProfileProvider;
|
|
7
|
+
#env;
|
|
8
|
+
constructor(projectProfileService, env) {
|
|
9
|
+
this.#projectProfileProvider = projectProfileService;
|
|
10
|
+
this.#env = env;
|
|
11
|
+
}
|
|
12
|
+
async restoreProfile() {
|
|
13
|
+
const backupResult = await Promises.tryCatch(Workers.Opfs.list(Recovery.#RESTORE_FILE_PATH));
|
|
14
|
+
if (backupResult.status === "rejected" || backupResult.value.length === 0) {
|
|
15
|
+
return Option.None;
|
|
16
|
+
}
|
|
17
|
+
const readResult = await Promises.tryCatch(Promise.all([
|
|
18
|
+
Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/uuid`)
|
|
19
|
+
.then(x => UUID.validateBytes(x)),
|
|
20
|
+
Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/project.od`)
|
|
21
|
+
.then(x => Project.load(this.#env, x.buffer)),
|
|
22
|
+
Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/meta.json`)
|
|
23
|
+
.then(x => JSON.parse(new TextDecoder().decode(x.buffer))),
|
|
24
|
+
Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/saved`)
|
|
25
|
+
.then(x => x.at(0) === 1)
|
|
26
|
+
]));
|
|
27
|
+
const deleteResult = await Promises.tryCatch(Workers.Opfs.delete(Recovery.#RESTORE_FILE_PATH));
|
|
28
|
+
console.debug(`delete backup: "${deleteResult.status}"`);
|
|
29
|
+
if (readResult.status === "rejected") {
|
|
30
|
+
return Option.None;
|
|
31
|
+
}
|
|
32
|
+
const [uuid, project, meta, saved] = readResult.value;
|
|
33
|
+
const profile = new ProjectProfile(uuid, project, meta, Option.None, saved);
|
|
34
|
+
console.debug(`restore ${profile}, saved: ${saved}`);
|
|
35
|
+
return Option.wrap(profile);
|
|
36
|
+
}
|
|
37
|
+
createBackupCommand() {
|
|
38
|
+
return this.#projectProfileProvider().map((profile) => async () => {
|
|
39
|
+
console.debug("backup project");
|
|
40
|
+
const { project, meta, uuid } = profile;
|
|
41
|
+
return Promises.tryCatch(Promise.all([
|
|
42
|
+
Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/uuid`, uuid),
|
|
43
|
+
Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/project.od`, new Uint8Array(project.toArrayBuffer())),
|
|
44
|
+
Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/meta.json`, new TextEncoder().encode(JSON.stringify(meta))),
|
|
45
|
+
Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/saved`, new Uint8Array([profile.saved() ? 1 : 0]))
|
|
46
|
+
])).then(result => console.debug(`backup result: ${result.status}`));
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
package/dist/project/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/project/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/project/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,YAAY,CAAA"}
|
package/dist/project/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenSampleAPI.d.ts","sourceRoot":"","sources":["../../src/samples/OpenSampleAPI.ts"],"names":[],"mappings":"AAAA,OAAO,EAMH,SAAS,EAGT,SAAS,EACT,IAAI,EACP,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"OpenSampleAPI.d.ts","sourceRoot":"","sources":["../../src/samples/OpenSampleAPI.ts"],"names":[],"mappings":"AAAA,OAAO,EAMH,SAAS,EAGT,SAAS,EACT,IAAI,EACP,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAA;AAK9C,qBAAa,aAAc,YAAW,SAAS;IAC3C,MAAM,CAAC,QAAQ,CAAC,OAAO,wCAAuC;IAC9D,MAAM,CAAC,QAAQ,CAAC,QAAQ,2CAA0C;IAGlE,MAAM,CAAC,GAAG,IAAI,aAAa;IAE3B,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS;IAStD,OAAO;IAED,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAKrC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;IAQtC,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAmC3G,MAAM,CAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAoC/E,YAAY,IAAI,OAAO;CAC1B"}
|
|
@@ -9,7 +9,9 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
9
9
|
};
|
|
10
10
|
import { Arrays, asDefined, DefaultObservableValue, Lazy, panic, RuntimeNotifier, tryCatch, UUID } from "@opendaw/lib-std";
|
|
11
11
|
import { network, Promises } from "@opendaw/lib-runtime";
|
|
12
|
+
import { Sample } from "@opendaw/studio-adapters";
|
|
12
13
|
import { base64Credentials, OpenDAWHeaders } from "../OpenDAWHeaders";
|
|
14
|
+
import { z } from "zod";
|
|
13
15
|
// Standard openDAW samples (considered to be non-removable)
|
|
14
16
|
export class OpenSampleAPI {
|
|
15
17
|
static ApiRoot = "https://api.opendaw.studio/samples";
|
|
@@ -25,13 +27,13 @@ export class OpenSampleAPI {
|
|
|
25
27
|
}
|
|
26
28
|
constructor() { }
|
|
27
29
|
async all() {
|
|
28
|
-
return Promises.
|
|
29
|
-
.then(x => x.json(), () => []));
|
|
30
|
+
return Promises.guardedRetry(() => fetch(`${OpenSampleAPI.ApiRoot}/list.php`, OpenDAWHeaders)
|
|
31
|
+
.then(x => x.json().then(x => z.array(Sample).parse(x)), () => []), (_error, count) => count < 10);
|
|
30
32
|
}
|
|
31
33
|
async get(uuid) {
|
|
32
34
|
const url = `${OpenSampleAPI.ApiRoot}/get.php?uuid=${UUID.toString(uuid)}`;
|
|
33
35
|
const sample = await Promises.retry(() => network.limitFetch(url, OpenDAWHeaders)
|
|
34
|
-
.then(x => x.json()))
|
|
36
|
+
.then(x => x.json().then(x => Sample.parse(x))))
|
|
35
37
|
.then(x => { if ("error" in x) {
|
|
36
38
|
return panic(x.error);
|
|
37
39
|
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { Procedure } from "@opendaw/lib-std";
|
|
1
|
+
import { Class, Procedure } from "@opendaw/lib-std";
|
|
2
|
+
import { Box } from "@opendaw/lib-box";
|
|
2
3
|
import { Sample } from "@opendaw/studio-adapters";
|
|
3
4
|
import { AssetService } from "../AssetService";
|
|
4
5
|
export declare class SampleService extends AssetService<Sample> {
|
|
5
6
|
readonly audioContext: AudioContext;
|
|
6
7
|
protected readonly namePlural: string;
|
|
7
8
|
protected readonly nameSingular: string;
|
|
9
|
+
protected readonly boxType: Class<Box>;
|
|
10
|
+
protected readonly filePickerOptions: FilePickerOptions;
|
|
8
11
|
constructor(audioContext: AudioContext, onUpdate: Procedure<Sample>);
|
|
9
|
-
browse(multiple: boolean): Promise<ReadonlyArray<Sample>>;
|
|
10
12
|
importFile({ uuid, name, arrayBuffer, progressHandler }: AssetService.ImportArgs): Promise<Sample>;
|
|
13
|
+
protected collectAllFiles(): Promise<ReadonlyArray<Sample>>;
|
|
11
14
|
}
|
|
12
15
|
//# sourceMappingURL=SampleService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SampleService.d.ts","sourceRoot":"","sources":["../../src/samples/SampleService.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"SampleService.d.ts","sourceRoot":"","sources":["../../src/samples/SampleService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,EAAe,SAAS,EAAiB,MAAM,kBAAkB,CAAA;AACtF,OAAO,EAAC,GAAG,EAAC,MAAM,kBAAkB,CAAA;AAKpC,OAAO,EAAY,MAAM,EAAiB,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAC,YAAY,EAAC,MAAM,iBAAiB,CAAA;AAM5C,qBAAa,aAAc,SAAQ,YAAY,CAAC,MAAM,CAAC;IAMvC,QAAQ,CAAC,YAAY,EAAE,YAAY;IAL/C,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAY;IACjD,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAW;IAClD,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAe;IACrD,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAiC;gBAEnE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC;IAItE,UAAU,CAAC,EAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,eAAgC,EAAC,EACzD,YAAY,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;cAqC5C,eAAe,IAAI,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;CAKpE"}
|
|
@@ -2,19 +2,22 @@ import { Arrays, isUndefined, Progress, UUID } from "@opendaw/lib-std";
|
|
|
2
2
|
import { estimateBpm } from "@opendaw/lib-dsp";
|
|
3
3
|
import { Promises } from "@opendaw/lib-runtime";
|
|
4
4
|
import { SamplePeaks } from "@opendaw/lib-fusion";
|
|
5
|
-
import {
|
|
5
|
+
import { AudioFileBox } from "@opendaw/studio-boxes";
|
|
6
6
|
import { AssetService } from "../AssetService";
|
|
7
|
+
import { FilePickerAcceptTypes } from "../FilePickerAcceptTypes";
|
|
8
|
+
import { Workers } from "../Workers";
|
|
9
|
+
import { SampleStorage } from "./SampleStorage";
|
|
10
|
+
import { OpenSampleAPI } from "./OpenSampleAPI";
|
|
7
11
|
export class SampleService extends AssetService {
|
|
8
12
|
audioContext;
|
|
9
13
|
namePlural = "Samples";
|
|
10
14
|
nameSingular = "Sample";
|
|
15
|
+
boxType = AudioFileBox;
|
|
16
|
+
filePickerOptions = FilePickerAcceptTypes.WavFiles;
|
|
11
17
|
constructor(audioContext, onUpdate) {
|
|
12
18
|
super(onUpdate);
|
|
13
19
|
this.audioContext = audioContext;
|
|
14
20
|
}
|
|
15
|
-
async browse(multiple) {
|
|
16
|
-
return this.browseFiles(multiple, FilePickerAcceptTypes.WavFiles);
|
|
17
|
-
}
|
|
18
21
|
async importFile({ uuid, name, arrayBuffer, progressHandler = Progress.Empty }) {
|
|
19
22
|
console.debug(`importSample '${name}' (${arrayBuffer.byteLength >> 10}kb)`);
|
|
20
23
|
console.time("UUID.sha256");
|
|
@@ -48,4 +51,9 @@ export class SampleService extends AssetService {
|
|
|
48
51
|
this.onUpdate(sample);
|
|
49
52
|
return sample;
|
|
50
53
|
}
|
|
54
|
+
async collectAllFiles() {
|
|
55
|
+
const stock = await OpenSampleAPI.get().all();
|
|
56
|
+
const local = await SampleStorage.get().list();
|
|
57
|
+
return Arrays.merge(stock, local, (sample, { uuid }) => sample.uuid === uuid);
|
|
58
|
+
}
|
|
51
59
|
}
|
|
@@ -13,7 +13,7 @@ export declare namespace SampleStorage {
|
|
|
13
13
|
export declare class SampleStorage extends Storage<Sample, SampleMetaData, SampleStorage.NewSample, [AudioData, Peaks, SampleMetaData]> {
|
|
14
14
|
static readonly Folder = "samples/v2";
|
|
15
15
|
static get(): SampleStorage;
|
|
16
|
-
static
|
|
16
|
+
static cleanDeprecated(): Promise<void>;
|
|
17
17
|
private constructor();
|
|
18
18
|
save({ uuid, audio, peaks, meta }: SampleStorage.NewSample): Promise<void>;
|
|
19
19
|
updateSampleMeta(uuid: UUID.Bytes, meta: SampleMetaData): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SampleStorage.d.ts","sourceRoot":"","sources":["../../src/samples/SampleStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACtE,OAAO,EAAC,KAAK,EAAc,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAG1E,OAAO,EAAC,OAAO,EAAC,MAAM,YAAY,CAAA;AAElC,yBAAiB,aAAa,CAAC;IAC3B,KAAY,SAAS,GAAG;QACpB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC;QACjB,KAAK,EAAE,SAAS,CAAC;QACjB,KAAK,EAAE,WAAW,CAAC;QACnB,IAAI,EAAE,cAAc,CAAA;KACvB,CAAA;CACJ;AAED,qBAAa,aAAc,SAAQ,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,aAAa,CAAC,SAAS,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;IAC3H,MAAM,CAAC,QAAQ,CAAC,MAAM,gBAAe;IAGrC,MAAM,CAAC,GAAG,IAAI,aAAa;WAEd,
|
|
1
|
+
{"version":3,"file":"SampleStorage.d.ts","sourceRoot":"","sources":["../../src/samples/SampleStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACtE,OAAO,EAAC,KAAK,EAAc,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAG1E,OAAO,EAAC,OAAO,EAAC,MAAM,YAAY,CAAA;AAElC,yBAAiB,aAAa,CAAC;IAC3B,KAAY,SAAS,GAAG;QACpB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC;QACjB,KAAK,EAAE,SAAS,CAAC;QACjB,KAAK,EAAE,WAAW,CAAC;QACnB,IAAI,EAAE,cAAc,CAAA;KACvB,CAAA;CACJ;AAED,qBAAa,aAAc,SAAQ,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,aAAa,CAAC,SAAS,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;IAC3H,MAAM,CAAC,QAAQ,CAAC,MAAM,gBAAe;IAGrC,MAAM,CAAC,GAAG,IAAI,aAAa;WAEd,eAAe;IAE5B,OAAO;IAED,IAAI,CAAC,EAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAC,EAAE,aAAa,CAAC,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAexE,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;CAgB5E"}
|
|
@@ -15,7 +15,7 @@ import { Storage } from "../Storage";
|
|
|
15
15
|
export class SampleStorage extends Storage {
|
|
16
16
|
static Folder = "samples/v2";
|
|
17
17
|
static get() { return new SampleStorage(); }
|
|
18
|
-
static async
|
|
18
|
+
static async cleanDeprecated() { Workers.Opfs.delete("samples/v1").catch(EmptyExec); }
|
|
19
19
|
constructor() { super(SampleStorage.Folder); }
|
|
20
20
|
async save({ uuid, audio, peaks, meta }) {
|
|
21
21
|
const path = `${this.folder}/${UUID.toString(uuid)}`;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Observer, Option, Subscription, UUID } from "@opendaw/lib-std";
|
|
2
2
|
import { SoundfontLoader, SoundfontLoaderState, SoundfontMetaData } from "@opendaw/studio-adapters";
|
|
3
3
|
import { DefaultSoundfontLoaderManager } from "./DefaultSoundfontLoaderManager";
|
|
4
|
-
import { SoundFont2 } from "soundfont2";
|
|
4
|
+
import type { SoundFont2 } from "soundfont2";
|
|
5
5
|
export declare class DefaultSoundfontLoader implements SoundfontLoader {
|
|
6
6
|
#private;
|
|
7
7
|
constructor(manager: DefaultSoundfontLoaderManager, uuid: UUID.Bytes);
|
|
8
8
|
subscribe(observer: Observer<SoundfontLoaderState>): Subscription;
|
|
9
|
+
invalidate(): void;
|
|
9
10
|
get uuid(): UUID.Bytes;
|
|
10
11
|
get soundfont(): Option<SoundFont2>;
|
|
11
12
|
get meta(): Option<SoundfontMetaData>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultSoundfontLoader.d.ts","sourceRoot":"","sources":["../../src/soundfont/DefaultSoundfontLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,QAAQ,EAAE,MAAM,EAAY,YAAY,EAAc,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAErG,OAAO,EAAC,eAAe,EAAE,oBAAoB,EAAE,iBAAiB,EAAC,MAAM,0BAA0B,CAAA;AACjG,OAAO,EAAC,6BAA6B,EAAC,MAAM,iCAAiC,CAAA;AAE7E,OAAO,EAAC,UAAU,EAAC,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"DefaultSoundfontLoader.d.ts","sourceRoot":"","sources":["../../src/soundfont/DefaultSoundfontLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,QAAQ,EAAE,MAAM,EAAY,YAAY,EAAc,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAErG,OAAO,EAAC,eAAe,EAAE,oBAAoB,EAAE,iBAAiB,EAAC,MAAM,0BAA0B,CAAA;AACjG,OAAO,EAAC,6BAA6B,EAAC,MAAM,iCAAiC,CAAA;AAE7E,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,YAAY,CAAA;AAE1C,qBAAa,sBAAuB,YAAW,eAAe;;gBAY9C,OAAO,EAAE,6BAA6B,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK;IAQpE,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,YAAY;IAQjE,UAAU,IAAI,IAAI;IAOlB,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,CAAoB;IAC1C,IAAI,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC,CAAyB;IAC5D,IAAI,IAAI,IAAI,MAAM,CAAC,iBAAiB,CAAC,CAAoB;IACzD,IAAI,KAAK,IAAI,oBAAoB,CAAqB;IAEtD,QAAQ,IAAI,MAAM;CA+CrB"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Notifier, Option, Terminable, UUID } from "@opendaw/lib-std";
|
|
2
2
|
import { Promises } from "@opendaw/lib-runtime";
|
|
3
3
|
import { SoundfontStorage } from "./SoundfontStorage";
|
|
4
|
-
import { SoundFont2 } from "soundfont2";
|
|
5
4
|
export class DefaultSoundfontLoader {
|
|
6
5
|
#manager;
|
|
7
6
|
#uuid;
|
|
8
7
|
#notifier;
|
|
8
|
+
#soundFont2 = Promises.memoizeAsync(() => import("soundfont2"));
|
|
9
9
|
#meta = Option.None;
|
|
10
10
|
#soundfont = Option.None;
|
|
11
11
|
#state = { type: "progress", progress: 0.0 };
|
|
@@ -22,6 +22,12 @@ export class DefaultSoundfontLoader {
|
|
|
22
22
|
}
|
|
23
23
|
return this.#notifier.subscribe(observer);
|
|
24
24
|
}
|
|
25
|
+
invalidate() {
|
|
26
|
+
this.#state = { type: "progress", progress: 0.0 };
|
|
27
|
+
this.#meta = Option.None;
|
|
28
|
+
this.#soundfont = Option.None;
|
|
29
|
+
this.#get();
|
|
30
|
+
}
|
|
25
31
|
get uuid() { return this.#uuid; }
|
|
26
32
|
get soundfont() { return this.#soundfont; }
|
|
27
33
|
get meta() { return this.#meta; }
|
|
@@ -32,8 +38,8 @@ export class DefaultSoundfontLoader {
|
|
|
32
38
|
this.#notifier.notify(this.#state);
|
|
33
39
|
}
|
|
34
40
|
#get() {
|
|
35
|
-
SoundfontStorage.get().load(this.#uuid).then(([file, meta]) => {
|
|
36
|
-
this.#soundfont = Option.wrap(
|
|
41
|
+
SoundfontStorage.get().load(this.#uuid).then(async ([file, meta]) => {
|
|
42
|
+
this.#soundfont = Option.wrap(await this.#createSoundFont2(file));
|
|
37
43
|
this.#meta = Option.wrap(meta);
|
|
38
44
|
this.#setState({ type: "loaded" });
|
|
39
45
|
}, (error) => {
|
|
@@ -57,7 +63,7 @@ export class DefaultSoundfontLoader {
|
|
|
57
63
|
const [file, meta] = fetchResult.value;
|
|
58
64
|
const storeResult = await Promises.tryCatch(SoundfontStorage.get().save({ uuid: this.#uuid, file, meta }));
|
|
59
65
|
if (storeResult.status === "resolved") {
|
|
60
|
-
this.#soundfont = Option.wrap(
|
|
66
|
+
this.#soundfont = Option.wrap(await this.#createSoundFont2(file));
|
|
61
67
|
this.#meta = Option.wrap(meta);
|
|
62
68
|
this.#setState({ type: "loaded" });
|
|
63
69
|
}
|
|
@@ -66,4 +72,8 @@ export class DefaultSoundfontLoader {
|
|
|
66
72
|
this.#setState({ type: "error", reason: "N/A" });
|
|
67
73
|
}
|
|
68
74
|
}
|
|
75
|
+
async #createSoundFont2(buffer) {
|
|
76
|
+
const { SoundFont2 } = await this.#soundFont2();
|
|
77
|
+
return new SoundFont2(new Uint8Array(buffer));
|
|
78
|
+
}
|
|
69
79
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Progress, UUID } from "@opendaw/lib-std";
|
|
2
|
-
import { SoundfontProvider } from "./SoundfontProvider";
|
|
3
2
|
import { SoundfontLoader, SoundfontLoaderManager, SoundfontMetaData } from "@opendaw/studio-adapters";
|
|
3
|
+
import { SoundfontProvider } from "./SoundfontProvider";
|
|
4
4
|
export declare class DefaultSoundfontLoaderManager implements SoundfontLoaderManager, SoundfontProvider {
|
|
5
5
|
#private;
|
|
6
6
|
constructor(provider: SoundfontProvider);
|
|
7
7
|
fetch(uuid: UUID.Bytes, progress: Progress.Handler): Promise<[ArrayBuffer, SoundfontMetaData]>;
|
|
8
8
|
remove(uuid: UUID.Bytes): void;
|
|
9
9
|
getOrCreate(uuid: UUID.Bytes): SoundfontLoader;
|
|
10
|
+
invalidate(uuid: UUID.Bytes): void;
|
|
10
11
|
}
|
|
11
12
|
//# sourceMappingURL=DefaultSoundfontLoaderManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultSoundfontLoaderManager.d.ts","sourceRoot":"","sources":["../../src/soundfont/DefaultSoundfontLoaderManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAa,IAAI,EAAC,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"DefaultSoundfontLoaderManager.d.ts","sourceRoot":"","sources":["../../src/soundfont/DefaultSoundfontLoaderManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAa,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAC1D,OAAO,EAAC,eAAe,EAAE,sBAAsB,EAAE,iBAAiB,EAAC,MAAM,0BAA0B,CAAA;AAEnG,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAA;AAErD,qBAAa,6BAA8B,YAAW,sBAAsB,EAAE,iBAAiB;;gBAI/E,QAAQ,EAAE,iBAAiB;IAKvC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;IAI9F,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK;IAEvB,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,eAAe;IAI9C,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK;CAC9B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenSoundfontAPI.d.ts","sourceRoot":"","sources":["../../src/soundfont/OpenSoundfontAPI.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,SAAS,EAAmB,SAAS,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAC7F,OAAO,EAAC,SAAS,EAAE,iBAAiB,EAAC,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"OpenSoundfontAPI.d.ts","sourceRoot":"","sources":["../../src/soundfont/OpenSoundfontAPI.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,SAAS,EAAmB,SAAS,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAC7F,OAAO,EAAC,SAAS,EAAE,iBAAiB,EAAC,MAAM,0BAA0B,CAAA;AAKrE,qBAAa,gBAAgB;;IACzB,MAAM,CAAC,QAAQ,CAAC,OAAO,2CAA0C;IACjE,MAAM,CAAC,QAAQ,CAAC,QAAQ,8CAA6C;IAGrE,MAAM,CAAC,GAAG,IAAI,gBAAgB;IAW9B,OAAO;IAED,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAExC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC;IAMzC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;CAyB1G"}
|