@opendaw/studio-core 0.0.32 → 0.0.34
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/AudioWorklets.d.ts +1 -0
- package/dist/AudioWorklets.d.ts.map +1 -1
- package/dist/AudioWorklets.js +7 -3
- package/dist/RecordingWorklet.js +2 -2
- package/dist/{WorkerAgents.d.ts → Workers.d.ts} +5 -3
- package/dist/Workers.d.ts.map +1 -0
- package/dist/{WorkerAgents.js → Workers.js} +12 -8
- package/dist/clouds/CloudBackupProjects.js +4 -4
- package/dist/clouds/CloudBackupSamples.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/project/ProjectBundle.js +5 -5
- package/dist/project/ProjectProfile.js +4 -4
- package/dist/project/ProjectStorage.js +11 -11
- package/dist/samples/MainThreadSampleLoader.js +2 -2
- package/dist/samples/SampleStorage.d.ts.map +1 -1
- package/dist/samples/SampleStorage.js +14 -14
- package/dist/{workers.js → workers-main.js} +2 -2
- package/dist/{workers.js.map → workers-main.js.map} +3 -3
- package/package.json +6 -6
- package/dist/WorkerAgents.d.ts.map +0 -1
- package/dist/asset-urls.d.ts +0 -3
- package/dist/asset-urls.d.ts.map +0 -1
- package/dist/asset-urls.js +0 -2
package/dist/AudioWorklets.d.ts
CHANGED
@@ -6,6 +6,7 @@ import { MeterWorklet } from "./MeterWorklet";
|
|
6
6
|
import { RecordingWorklet } from "./RecordingWorklet";
|
7
7
|
export declare class AudioWorklets {
|
8
8
|
#private;
|
9
|
+
static setWorkletUrl(url: string): void;
|
9
10
|
static install(context: BaseAudioContext): Promise<AudioWorklets>;
|
10
11
|
static get(context: BaseAudioContext): AudioWorklets;
|
11
12
|
constructor(context: BaseAudioContext);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"AudioWorklets.d.ts","sourceRoot":"","sources":["../src/AudioWorklets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,GAAG,
|
1
|
+
{"version":3,"file":"AudioWorklets.d.ts","sourceRoot":"","sources":["../src/AudioWorklets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,GAAG,EAAS,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAC,wBAAwB,EAAa,MAAM,0BAA0B,CAAA;AAC7E,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AAGnD,qBAAa,aAAa;;IACtB,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;WAO1B,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,CAAC;IAQvE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,aAAa;gBAMxC,OAAO,EAAE,gBAAgB;IAErC,IAAI,OAAO,IAAI,gBAAgB,CAAuB;IAEtD,WAAW,CAAC,gBAAgB,EAAE,GAAG,GAAG,YAAY;IAIhD,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,mBAAmB,CAAC,EAAE,wBAAwB,GAAG,aAAa;IAI7F,eAAe,CAAC,gBAAgB,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,GAAG,gBAAgB;CAOlG"}
|
package/dist/AudioWorklets.js
CHANGED
@@ -1,12 +1,16 @@
|
|
1
|
-
import { asDefined } from "@opendaw/lib-std";
|
1
|
+
import { asDefined, Option } from "@opendaw/lib-std";
|
2
2
|
import { EngineWorklet } from "./EngineWorklet";
|
3
3
|
import { MeterWorklet } from "./MeterWorklet";
|
4
4
|
import { RecordingWorklet } from "./RecordingWorklet";
|
5
5
|
import { RenderQuantum } from "./RenderQuantum";
|
6
|
-
import { WorkletsUrl } from "./asset-urls";
|
7
6
|
export class AudioWorklets {
|
7
|
+
static setWorkletUrl(url) {
|
8
|
+
console.debug(`setWorkletUrl: '${url}'`);
|
9
|
+
this.#workletUrl = Option.wrap(url);
|
10
|
+
}
|
11
|
+
static #workletUrl = Option.None;
|
8
12
|
static async install(context) {
|
9
|
-
return context.audioWorklet.addModule(
|
13
|
+
return context.audioWorklet.addModule(this.#workletUrl.unwrap("WorkletUrl is missing")).then(() => {
|
10
14
|
const worklets = new AudioWorklets(context);
|
11
15
|
this.#map.set(context, worklets);
|
12
16
|
return worklets;
|
package/dist/RecordingWorklet.js
CHANGED
@@ -4,7 +4,7 @@ import { SamplePeaks } from "@opendaw/lib-fusion";
|
|
4
4
|
import { mergeChunkPlanes, RingBuffer } from "@opendaw/studio-adapters";
|
5
5
|
import { SampleStorage } from "./samples/SampleStorage";
|
6
6
|
import { RenderQuantum } from "./RenderQuantum";
|
7
|
-
import {
|
7
|
+
import { Workers } from "./Workers";
|
8
8
|
import { PeaksWriter } from "./PeaksWriter";
|
9
9
|
export class RecordingWorklet extends AudioWorkletNode {
|
10
10
|
#terminator = new Terminator();
|
@@ -83,7 +83,7 @@ export class RecordingWorklet extends AudioWorkletNode {
|
|
83
83
|
};
|
84
84
|
this.#data = Option.wrap(audioData);
|
85
85
|
const shifts = SamplePeaks.findBestFit(totalSamples);
|
86
|
-
const peaks = await
|
86
|
+
const peaks = await Workers
|
87
87
|
.Peak.generateAsync(Progress.Empty, shifts, frames, totalSamples, numberOfChannels);
|
88
88
|
this.#peaks = Option.wrap(SamplePeaks.from(new ByteArrayInput(peaks)));
|
89
89
|
const bpm = BPMTools.detect(frames[0], sample_rate);
|
@@ -1,10 +1,12 @@
|
|
1
1
|
import { Option } from "@opendaw/lib-std";
|
2
|
-
import type { OpfsProtocol, SamplePeakProtocol } from "@opendaw/lib-fusion";
|
3
2
|
import { Messenger } from "@opendaw/lib-runtime";
|
4
|
-
|
3
|
+
import type { OpfsProtocol, SamplePeakProtocol } from "@opendaw/lib-fusion";
|
4
|
+
export declare class Workers {
|
5
|
+
#private;
|
6
|
+
static setWorkerUrl(url: string): void;
|
5
7
|
static install(): Promise<void>;
|
6
8
|
static messenger: Option<Messenger>;
|
7
9
|
static get Peak(): SamplePeakProtocol;
|
8
10
|
static get Opfs(): OpfsProtocol;
|
9
11
|
}
|
10
|
-
//# sourceMappingURL=
|
12
|
+
//# sourceMappingURL=Workers.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"Workers.d.ts","sourceRoot":"","sources":["../src/Workers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,MAAM,EAAY,MAAM,kBAAkB,CAAA;AACjF,OAAO,EAAe,SAAS,EAAC,MAAM,sBAAsB,CAAA;AAC5D,OAAO,KAAK,EAAC,YAAY,EAAE,kBAAkB,EAAC,MAAM,qBAAqB,CAAA;AAEzE,qBAAa,OAAO;;IAChB,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;WAOzB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBrC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,CAAc;IAGjD,MAAM,KAAK,IAAI,IAAI,kBAAkB,CAapC;IAGD,MAAM,KAAK,IAAI,IAAI,YAAY,CAS9B;CACJ"}
|
@@ -9,17 +9,21 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
9
|
};
|
10
10
|
import { assert, Lazy, Option } from "@opendaw/lib-std";
|
11
11
|
import { Communicator, Messenger } from "@opendaw/lib-runtime";
|
12
|
-
|
13
|
-
|
12
|
+
export class Workers {
|
13
|
+
static setWorkerUrl(url) {
|
14
|
+
console.debug(`setWorkerUrl: '${url}'`);
|
15
|
+
this.#workerUrl = Option.wrap(url);
|
16
|
+
}
|
17
|
+
static #workerUrl = Option.None;
|
14
18
|
static async install() {
|
15
|
-
|
16
|
-
|
17
|
-
const message = Messenger.for(new Worker(
|
19
|
+
console.debug("install Workers");
|
20
|
+
assert(this.messenger.isEmpty(), "Workers are already installed");
|
21
|
+
const message = Messenger.for(new Worker(this.#workerUrl.unwrap("workerUrl is missing"), { type: "module" }));
|
18
22
|
this.messenger = Option.wrap(message);
|
19
23
|
const { resolve, promise } = Promise.withResolvers();
|
20
24
|
const subscription = message.channel("initialize").subscribe(data => {
|
21
25
|
if (data === "ready") {
|
22
|
-
console.debug("
|
26
|
+
console.debug("Workers ready");
|
23
27
|
resolve();
|
24
28
|
subscription.terminate();
|
25
29
|
}
|
@@ -49,9 +53,9 @@ __decorate([
|
|
49
53
|
Lazy,
|
50
54
|
__metadata("design:type", Object),
|
51
55
|
__metadata("design:paramtypes", [])
|
52
|
-
],
|
56
|
+
], Workers, "Peak", null);
|
53
57
|
__decorate([
|
54
58
|
Lazy,
|
55
59
|
__metadata("design:type", Object),
|
56
60
|
__metadata("design:paramtypes", [])
|
57
|
-
],
|
61
|
+
], Workers, "Opfs", null);
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { Arrays, Errors, isAbsent, Objects, panic, Progress, RuntimeNotifier, TimeSpan, UUID } from "@opendaw/lib-std";
|
2
2
|
import { network, Promises } from "@opendaw/lib-runtime";
|
3
3
|
import { ProjectStorage } from "../project/ProjectStorage";
|
4
|
-
import {
|
4
|
+
import { Workers } from "../Workers";
|
5
5
|
import { ProjectPaths } from "../project/ProjectPaths";
|
6
6
|
// these get indexed in the cloud with the uuid in the cloud's catalog
|
7
7
|
const catalogFields = ["name", "modified", "created", "tags", "description"];
|
@@ -146,12 +146,12 @@ export class CloudBackupProjects {
|
|
146
146
|
const coverPath = `${path}/image.bin`;
|
147
147
|
const projectArrayBuffer = await Promises.guardedRetry(() => this.#cloudHandler.download(projectPath), network.DefaultRetry);
|
148
148
|
const metaArrayBuffer = await Promises.guardedRetry(() => this.#cloudHandler.download(metaPath), network.DefaultRetry);
|
149
|
-
await
|
150
|
-
await
|
149
|
+
await Workers.Opfs.write(ProjectPaths.projectFile(uuid), new Uint8Array(projectArrayBuffer));
|
150
|
+
await Workers.Opfs.write(ProjectPaths.projectMeta(uuid), new Uint8Array(metaArrayBuffer));
|
151
151
|
const hasCover = files.some(file => file.endsWith("image.bin"));
|
152
152
|
if (hasCover) {
|
153
153
|
const arrayBuffer = await Promises.guardedRetry(() => this.#cloudHandler.download(coverPath), network.DefaultRetry);
|
154
|
-
await
|
154
|
+
await Workers.Opfs.write(ProjectPaths.projectCover(uuid), new Uint8Array(arrayBuffer));
|
155
155
|
}
|
156
156
|
return uuidAsString;
|
157
157
|
}));
|
@@ -3,7 +3,7 @@ import { network, Promises } from "@opendaw/lib-runtime";
|
|
3
3
|
import { SamplePeaks } from "@opendaw/lib-fusion";
|
4
4
|
import { OpenSampleAPI } from "../samples/OpenSampleAPI";
|
5
5
|
import { SampleStorage } from "../samples/SampleStorage";
|
6
|
-
import {
|
6
|
+
import { Workers } from "../Workers";
|
7
7
|
import { WavFile } from "../WavFile";
|
8
8
|
export class CloudBackupSamples {
|
9
9
|
static RemotePath = "samples";
|
@@ -113,7 +113,7 @@ export class CloudBackupSamples {
|
|
113
113
|
frames: waveAudio.channels
|
114
114
|
};
|
115
115
|
const shifts = SamplePeaks.findBestFit(audioData.numberOfFrames);
|
116
|
-
const peaks = await
|
116
|
+
const peaks = await Workers.Peak.generateAsync(Progress.Empty, shifts, audioData.frames, audioData.numberOfFrames, audioData.numberOfChannels);
|
117
117
|
await SampleStorage.saveSample(UUID.parse(sample.uuid), audioData, peaks, sample);
|
118
118
|
return sample;
|
119
119
|
}));
|
package/dist/index.d.ts
CHANGED
@@ -53,6 +53,6 @@ export * from "./Mixer";
|
|
53
53
|
export * from "./PeaksWriter";
|
54
54
|
export * from "./RenderQuantum";
|
55
55
|
export * from "./WavFile";
|
56
|
-
export * from "./
|
56
|
+
export * from "./Workers";
|
57
57
|
export * from "./AudioWorklets";
|
58
58
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AAEnC,cAAc,yBAAyB,CAAA;AACvC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAE7C,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AAEnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,sBAAsB,CAAA;AAEpC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,mBAAmB,CAAA;AACjC,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,yBAAyB,CAAA;AACvC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,WAAW,CAAA;AACzB,cAAc,
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AAEnC,cAAc,yBAAyB,CAAA;AACvC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAE7C,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AAEnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,sBAAsB,CAAA;AAEpC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,mBAAmB,CAAA;AACjC,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,yBAAyB,CAAA;AACvC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,iBAAiB,CAAA"}
|
package/dist/index.js
CHANGED
@@ -3,7 +3,7 @@ import { AudioFileBox } from "@opendaw/studio-boxes";
|
|
3
3
|
import { Project } from "./Project";
|
4
4
|
import { ProjectPaths } from "./ProjectPaths";
|
5
5
|
import { ProjectProfile } from "./ProjectProfile";
|
6
|
-
import {
|
6
|
+
import { Workers } from "../Workers";
|
7
7
|
import { SampleStorage } from "../samples/SampleStorage";
|
8
8
|
export var ProjectBundle;
|
9
9
|
(function (ProjectBundle) {
|
@@ -50,7 +50,7 @@ export var ProjectBundle;
|
|
50
50
|
return;
|
51
51
|
}
|
52
52
|
promises.push(file.async("arraybuffer")
|
53
|
-
.then(arrayBuffer =>
|
53
|
+
.then(arrayBuffer => Workers.Opfs
|
54
54
|
.write(`${SampleStorage.Folder}/${path}`, new Uint8Array(arrayBuffer))));
|
55
55
|
});
|
56
56
|
await Promise.all(promises);
|
@@ -63,9 +63,9 @@ export var ProjectBundle;
|
|
63
63
|
const pipeSampleLoaderInto = async (loader, zip) => {
|
64
64
|
const exec = async () => {
|
65
65
|
const path = `${SampleStorage.Folder}/${UUID.toString(loader.uuid)}`;
|
66
|
-
zip.file("audio.wav", await
|
67
|
-
zip.file("peaks.bin", await
|
68
|
-
zip.file("meta.json", await
|
66
|
+
zip.file("audio.wav", await Workers.Opfs.read(`${path}/audio.wav`), { binary: true });
|
67
|
+
zip.file("peaks.bin", await Workers.Opfs.read(`${path}/peaks.bin`), { binary: true });
|
68
|
+
zip.file("meta.json", await Workers.Opfs.read(`${path}/meta.json`));
|
69
69
|
};
|
70
70
|
if (loader.state.type === "loaded") {
|
71
71
|
return exec();
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { EmptyExec, Notifier, Option, UUID } from "@opendaw/lib-std";
|
2
2
|
import { ProjectMeta } from "./ProjectMeta";
|
3
|
-
import {
|
3
|
+
import { Workers } from "../Workers";
|
4
4
|
import { ProjectPaths } from "./ProjectPaths";
|
5
5
|
export class ProjectProfile {
|
6
6
|
#uuid;
|
@@ -72,11 +72,11 @@ export class ProjectProfile {
|
|
72
72
|
}
|
73
73
|
static async #writeFiles({ uuid, project, meta, cover }) {
|
74
74
|
return Promise.all([
|
75
|
-
|
76
|
-
|
75
|
+
Workers.Opfs.write(ProjectPaths.projectFile(uuid), new Uint8Array(project.toArrayBuffer())),
|
76
|
+
Workers.Opfs.write(ProjectPaths.projectMeta(uuid), new TextEncoder().encode(JSON.stringify(meta))),
|
77
77
|
cover.match({
|
78
78
|
none: () => Promise.resolve(),
|
79
|
-
some: x =>
|
79
|
+
some: x => Workers.Opfs.write(ProjectPaths.projectCover(uuid), new Uint8Array(x))
|
80
80
|
})
|
81
81
|
]).then(EmptyExec);
|
82
82
|
}
|
@@ -2,17 +2,17 @@ import { Option, safeExecute, tryCatch, UUID } from "@opendaw/lib-std";
|
|
2
2
|
import { AudioFileBox } from "@opendaw/studio-boxes";
|
3
3
|
import { ProjectDecoder } from "@opendaw/studio-adapters";
|
4
4
|
import { Promises } from "@opendaw/lib-runtime";
|
5
|
-
import {
|
5
|
+
import { Workers } from "../Workers";
|
6
6
|
import { ProjectPaths } from "./ProjectPaths";
|
7
7
|
export var ProjectStorage;
|
8
8
|
(function (ProjectStorage) {
|
9
9
|
ProjectStorage.listProjects = async ({ includeCover, includeProject, progress } = {}) => {
|
10
|
-
return
|
10
|
+
return Workers.Opfs.list(ProjectPaths.Folder)
|
11
11
|
.then(files => Promise.all(files.filter(file => file.kind === "directory")
|
12
12
|
.map(async ({ name }, index, { length }) => {
|
13
13
|
safeExecute(progress, (index + 1) / length);
|
14
14
|
const uuid = UUID.parse(name);
|
15
|
-
const array = await
|
15
|
+
const array = await Workers.Opfs.read(ProjectPaths.projectMeta(uuid));
|
16
16
|
return {
|
17
17
|
uuid,
|
18
18
|
meta: JSON.parse(new TextDecoder().decode(array)),
|
@@ -22,20 +22,20 @@ export var ProjectStorage;
|
|
22
22
|
})));
|
23
23
|
};
|
24
24
|
ProjectStorage.loadProject = async (uuid) => {
|
25
|
-
return
|
25
|
+
return Workers.Opfs.read(ProjectPaths.projectFile(uuid)).then(array => array.buffer);
|
26
26
|
};
|
27
27
|
ProjectStorage.loadMeta = async (uuid) => {
|
28
|
-
return
|
28
|
+
return Workers.Opfs.read(ProjectPaths.projectMeta(uuid)).then(array => array.buffer);
|
29
29
|
};
|
30
30
|
ProjectStorage.loadCover = async (uuid) => {
|
31
|
-
return
|
31
|
+
return Workers.Opfs.read(ProjectPaths.projectCover(uuid))
|
32
32
|
.then(array => Option.wrap(array.buffer), () => Option.None);
|
33
33
|
};
|
34
34
|
ProjectStorage.listUsedSamples = async () => {
|
35
35
|
const uuids = [];
|
36
|
-
const files = await
|
36
|
+
const files = await Workers.Opfs.list(ProjectPaths.Folder);
|
37
37
|
for (const { name } of files.filter(file => file.kind === "directory")) {
|
38
|
-
const result = await
|
38
|
+
const result = await Workers.Opfs.read(ProjectPaths.projectFile(UUID.parse(name)));
|
39
39
|
tryCatch(() => {
|
40
40
|
const { boxGraph } = ProjectDecoder.decode(result.buffer);
|
41
41
|
uuids.push(...boxGraph.boxes()
|
@@ -49,11 +49,11 @@ export var ProjectStorage;
|
|
49
49
|
const array = await ProjectStorage.loadTrashedIds();
|
50
50
|
array.push(UUID.toString(uuid));
|
51
51
|
const trash = new TextEncoder().encode(JSON.stringify(array));
|
52
|
-
await
|
53
|
-
await
|
52
|
+
await Workers.Opfs.write(`${ProjectPaths.Folder}/trash.json`, trash);
|
53
|
+
await Workers.Opfs.delete(ProjectPaths.projectFolder(uuid));
|
54
54
|
};
|
55
55
|
ProjectStorage.loadTrashedIds = async () => {
|
56
|
-
const { status, value } = await Promises.tryCatch(
|
56
|
+
const { status, value } = await Promises.tryCatch(Workers.Opfs.read(`${ProjectPaths.Folder}/trash.json`));
|
57
57
|
return status === "rejected" ? [] : JSON.parse(new TextDecoder().decode(value));
|
58
58
|
};
|
59
59
|
})(ProjectStorage || (ProjectStorage = {}));
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { ByteArrayInput, Notifier, Option, Progress, Terminable, UUID } from "@opendaw/lib-std";
|
2
2
|
import { Promises } from "@opendaw/lib-runtime";
|
3
3
|
import { SamplePeaks } from "@opendaw/lib-fusion";
|
4
|
-
import {
|
4
|
+
import { Workers } from "../Workers";
|
5
5
|
import { SampleStorage } from "./SampleStorage";
|
6
6
|
export class MainThreadSampleLoader {
|
7
7
|
#manager;
|
@@ -81,7 +81,7 @@ export class MainThreadSampleLoader {
|
|
81
81
|
}
|
82
82
|
const [audio, meta] = fetchResult.value;
|
83
83
|
const shifts = SamplePeaks.findBestFit(audio.numberOfFrames);
|
84
|
-
const peaks = await
|
84
|
+
const peaks = await Workers.Peak.generateAsync(peakProgress, shifts, audio.frames, audio.numberOfFrames, audio.numberOfChannels);
|
85
85
|
const storeResult = await Promises.tryCatch(SampleStorage.saveSample(this.#uuid, audio, peaks, meta));
|
86
86
|
if (this.#version !== version) {
|
87
87
|
return;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"SampleStorage.d.ts","sourceRoot":"","sources":["../../src/samples/SampleStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAEhE,OAAO,EAAC,KAAK,EAAc,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAI1E,yBAAiB,aAAa,CAAC;IACpB,MAAM,KAAK,
|
1
|
+
{"version":3,"file":"SampleStorage.d.ts","sourceRoot":"","sources":["../../src/samples/SampleStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAEhE,OAAO,EAAC,KAAK,EAAc,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAI1E,yBAAiB,aAAa,CAAC;IACpB,MAAM,KAAK,qBAA2D,CAAA;IAEtE,MAAM,MAAM,eAAe,CAAA;IAE3B,MAAM,UAAU,GAAU,MAAM,IAAI,CAAC,KAAK,EAChB,OAAO,SAAS,EAChB,OAAO,WAAW,EAClB,MAAM,cAAc,KAAG,OAAO,CAAC,IAAI,CAanE,CAAA;IAEM,MAAM,gBAAgB,GAAU,MAAM,IAAI,CAAC,KAAK,EAAE,MAAM,cAAc,KAAG,OAAO,CAAC,IAAI,CAG3F,CAAA;IAEM,MAAM,UAAU,GAAU,MAAM,IAAI,CAAC,KAAK,KAAG,OAAO,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,CAAC,CAe7F,CAAA;IAEM,MAAM,YAAY,GAAU,MAAM,IAAI,CAAC,KAAK,KAAG,OAAO,CAAC,IAAI,CAMjE,CAAA;IAEM,MAAM,cAAc,QAAa,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAGjE,CAAA;IAEM,MAAM,cAAc,GAAU,KAAK,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,KAAG,OAAO,CAAC,IAAI,CAGlF,CAAA;IAEM,MAAM,WAAW,QAAa,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAOjE,CAAA;CACJ"}
|
@@ -1,11 +1,11 @@
|
|
1
1
|
import { ByteArrayInput, EmptyExec, UUID } from "@opendaw/lib-std";
|
2
2
|
import { Promises } from "@opendaw/lib-runtime";
|
3
3
|
import { SamplePeaks } from "@opendaw/lib-fusion";
|
4
|
-
import {
|
4
|
+
import { Workers } from "../Workers";
|
5
5
|
import { WavFile } from "../WavFile";
|
6
6
|
export var SampleStorage;
|
7
7
|
(function (SampleStorage) {
|
8
|
-
SampleStorage.clean = () =>
|
8
|
+
SampleStorage.clean = () => Workers.Opfs.delete("samples/v1").catch(EmptyExec);
|
9
9
|
SampleStorage.Folder = "samples/v2";
|
10
10
|
SampleStorage.saveSample = async (uuid, audio, peaks, meta) => {
|
11
11
|
const path = `${SampleStorage.Folder}/${UUID.toString(uuid)}`;
|
@@ -16,23 +16,23 @@ export var SampleStorage;
|
|
16
16
|
}));
|
17
17
|
console.debug(`save sample '${path}'`);
|
18
18
|
return Promise.all([
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
Workers.Opfs.write(`${path}/audio.wav`, data),
|
20
|
+
Workers.Opfs.write(`${path}/peaks.bin`, new Uint8Array(peaks)),
|
21
|
+
Workers.Opfs.write(`${path}/meta.json`, new TextEncoder().encode(JSON.stringify(meta)))
|
22
22
|
]).then(EmptyExec);
|
23
23
|
};
|
24
24
|
SampleStorage.updateSampleMeta = async (uuid, meta) => {
|
25
25
|
const path = `${SampleStorage.Folder}/${UUID.toString(uuid)}`;
|
26
|
-
return
|
26
|
+
return Workers.Opfs.write(`${path}/meta.json`, new TextEncoder().encode(JSON.stringify(meta)));
|
27
27
|
};
|
28
28
|
SampleStorage.loadSample = async (uuid) => {
|
29
29
|
const path = `${SampleStorage.Folder}/${UUID.toString(uuid)}`;
|
30
30
|
return Promise.all([
|
31
|
-
|
31
|
+
Workers.Opfs.read(`${path}/audio.wav`)
|
32
32
|
.then(bytes => WavFile.decodeFloats(bytes.buffer)),
|
33
|
-
|
33
|
+
Workers.Opfs.read(`${path}/peaks.bin`)
|
34
34
|
.then(bytes => SamplePeaks.from(new ByteArrayInput(bytes.buffer))),
|
35
|
-
|
35
|
+
Workers.Opfs.read(`${path}/meta.json`)
|
36
36
|
.then(bytes => JSON.parse(new TextDecoder().decode(bytes)))
|
37
37
|
]).then(([buffer, peaks, meta]) => [{
|
38
38
|
sampleRate: buffer.sampleRate,
|
@@ -46,21 +46,21 @@ export var SampleStorage;
|
|
46
46
|
const uuids = await SampleStorage.loadTrashedIds();
|
47
47
|
uuids.push(UUID.toString(uuid));
|
48
48
|
await SampleStorage.saveTrashedIds(uuids);
|
49
|
-
await
|
49
|
+
await Workers.Opfs.delete(`${path}`);
|
50
50
|
};
|
51
51
|
SampleStorage.loadTrashedIds = async () => {
|
52
|
-
const { status, value } = await Promises.tryCatch(
|
52
|
+
const { status, value } = await Promises.tryCatch(Workers.Opfs.read(`${SampleStorage.Folder}/trash.json`));
|
53
53
|
return status === "rejected" ? [] : JSON.parse(new TextDecoder().decode(value));
|
54
54
|
};
|
55
55
|
SampleStorage.saveTrashedIds = async (ids) => {
|
56
56
|
const trash = new TextEncoder().encode(JSON.stringify(ids));
|
57
|
-
await
|
57
|
+
await Workers.Opfs.write(`${SampleStorage.Folder}/trash.json`, trash);
|
58
58
|
};
|
59
59
|
SampleStorage.listSamples = async () => {
|
60
|
-
return
|
60
|
+
return Workers.Opfs.list(SampleStorage.Folder)
|
61
61
|
.then(files => Promise.all(files.filter(file => file.kind === "directory")
|
62
62
|
.map(async ({ name }) => {
|
63
|
-
const array = await
|
63
|
+
const array = await Workers.Opfs.read(`${SampleStorage.Folder}/${name}/meta.json`);
|
64
64
|
return ({ uuid: name, ...JSON.parse(new TextDecoder().decode(array)) });
|
65
65
|
})), () => []);
|
66
66
|
};
|