@opendaw/studio-core 0.0.39 → 0.0.41
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/InstrumentFactories.d.ts.map +1 -1
- package/dist/InstrumentFactories.js +15 -12
- package/dist/capture/CaptureMidi.d.ts.map +1 -1
- package/dist/capture/CaptureMidi.js +8 -15
- package/dist/capture/RecordAudio.d.ts.map +1 -1
- package/dist/capture/RecordAudio.js +2 -1
- package/dist/capture/Recording.d.ts.map +1 -1
- package/dist/capture/Recording.js +1 -2
- package/dist/clouds/CloudAuthManager.js +2 -2
- package/dist/dawproject/DawProjectImport.d.ts +2 -2
- package/dist/dawproject/DawProjectImport.d.ts.map +1 -1
- package/dist/dawproject/DawProjectImport.js +4 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/midi/MidiDevices.d.ts +1 -1
- package/dist/midi/MidiDevices.d.ts.map +1 -1
- package/dist/midi/MidiDevices.js +3 -3
- package/dist/midi/SoftwareMIDIInput.d.ts.map +1 -1
- package/dist/midi/SoftwareMIDIInput.js +5 -1
- package/dist/processors.js +3 -3
- package/dist/processors.js.map +4 -4
- package/dist/project/Project.d.ts +3 -3
- package/dist/project/Project.d.ts.map +1 -1
- package/dist/project/Project.js +5 -4
- package/dist/project/ProjectMigration.d.ts +2 -2
- package/dist/project/ProjectMigration.d.ts.map +1 -1
- package/dist/project/ProjectMigration.js +0 -1
- package/dist/project/ProjectValidation.d.ts +5 -0
- package/dist/project/ProjectValidation.d.ts.map +1 -0
- package/dist/project/ProjectValidation.js +50 -0
- package/dist/samples/index.d.ts +0 -1
- package/dist/samples/index.d.ts.map +1 -1
- package/dist/samples/index.js +0 -1
- package/dist/ui/TimelineRange.d.ts +3 -1
- package/dist/ui/TimelineRange.d.ts.map +1 -1
- package/dist/ui/TimelineRange.js +7 -5
- package/dist/utils/AutofitUtils.d.ts +7 -0
- package/dist/utils/AutofitUtils.d.ts.map +1 -0
- package/dist/utils/AutofitUtils.js +78 -0
- package/dist/workers-main.js +2 -2
- package/dist/workers-main.js.map +3 -3
- package/dist/yjs/YMapper.d.ts +9 -0
- package/dist/yjs/YMapper.d.ts.map +1 -0
- package/dist/yjs/YMapper.js +45 -0
- package/dist/yjs/YService.d.ts +7 -0
- package/dist/yjs/YService.d.ts.map +1 -0
- package/dist/yjs/YService.js +69 -0
- package/dist/yjs/YSync.d.ts +17 -0
- package/dist/yjs/YSync.d.ts.map +1 -0
- package/dist/yjs/YSync.js +195 -0
- package/package.json +16 -16
- package/dist/samples/P2PSampleProvider.d.ts +0 -13
- package/dist/samples/P2PSampleProvider.d.ts.map +0 -1
- package/dist/samples/P2PSampleProvider.js +0 -350
@@ -1,7 +1,7 @@
|
|
1
1
|
import { Procedure, Terminable, TerminableOwner, Terminator } from "@opendaw/lib-std";
|
2
2
|
import { BoxGraph, Editing } from "@opendaw/lib-box";
|
3
3
|
import { AudioBusBox, AudioUnitBox, BoxIO, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
|
4
|
-
import { BoxAdapters, BoxAdaptersContext, ClipSequencing, ParameterFieldAdapters, ProcessorOptions,
|
4
|
+
import { BoxAdapters, BoxAdaptersContext, ClipSequencing, ParameterFieldAdapters, ProcessorOptions, ProjectSkeleton, RootBoxAdapter, SampleLoaderManager, 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";
|
@@ -18,7 +18,7 @@ export declare class Project implements BoxAdaptersContext, Terminable, Terminab
|
|
18
18
|
#private;
|
19
19
|
static new(env: ProjectEnv): Project;
|
20
20
|
static load(env: ProjectEnv, arrayBuffer: ArrayBuffer): Project;
|
21
|
-
static skeleton(env: ProjectEnv, skeleton:
|
21
|
+
static skeleton(env: ProjectEnv, skeleton: ProjectSkeleton): Project;
|
22
22
|
readonly boxGraph: BoxGraph<BoxIO.TypeMap>;
|
23
23
|
readonly rootBox: RootBox;
|
24
24
|
readonly userInterfaceBox: UserInterfaceBox;
|
@@ -51,7 +51,7 @@ export declare class Project implements BoxAdaptersContext, Terminable, Terminab
|
|
51
51
|
get isAudioContext(): boolean;
|
52
52
|
get isMainThread(): boolean;
|
53
53
|
get liveStreamBroadcaster(): LiveStreamBroadcaster;
|
54
|
-
get skeleton():
|
54
|
+
get skeleton(): ProjectSkeleton;
|
55
55
|
toArrayBuffer(): ArrayBufferLike;
|
56
56
|
copy(env?: Partial<ProjectEnv>): Project;
|
57
57
|
invalid(): boolean;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Project.d.ts","sourceRoot":"","sources":["../../src/project/Project.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,SAAS,EAET,UAAU,EACV,eAAe,EACf,UAAU,EAEb,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,QAAQ,EAAE,OAAO,EAAC,MAAM,kBAAkB,CAAA;AAClD,OAAO,EACH,WAAW,EACX,YAAY,EACZ,KAAK,EAGL,OAAO,EACP,WAAW,EAEX,gBAAgB,EACnB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,WAAW,EACX,kBAAkB,EAClB,cAAc,
|
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
@@ -11,6 +11,7 @@ import { CaptureDevices } from "../capture/CaptureDevices";
|
|
11
11
|
import { EngineFacade } from "../EngineFacade";
|
12
12
|
import { Recording } from "../capture/Recording";
|
13
13
|
import { MIDILearning } from "../midi/MIDILearning";
|
14
|
+
import { ProjectValidation } from "./ProjectValidation";
|
14
15
|
// Main Entry Point for a Project
|
15
16
|
export class Project {
|
16
17
|
static new(env) {
|
@@ -52,12 +53,11 @@ export class Project {
|
|
52
53
|
});
|
53
54
|
}
|
54
55
|
static load(env, arrayBuffer) {
|
55
|
-
|
56
|
-
ProjectMigration.migrate(skeleton);
|
57
|
-
return new Project(env, skeleton.boxGraph, skeleton.mandatoryBoxes);
|
56
|
+
return this.skeleton(env, ProjectDecoder.decode(arrayBuffer));
|
58
57
|
}
|
59
58
|
static skeleton(env, skeleton) {
|
60
59
|
ProjectMigration.migrate(skeleton);
|
60
|
+
ProjectValidation.validate(skeleton);
|
61
61
|
return new Project(env, skeleton.boxGraph, skeleton.mandatoryBoxes);
|
62
62
|
}
|
63
63
|
#terminator = new Terminator();
|
@@ -171,9 +171,10 @@ export class Project {
|
|
171
171
|
return Project.load({ ...this.#env, ...env }, this.toArrayBuffer());
|
172
172
|
}
|
173
173
|
invalid() {
|
174
|
+
// TODO Optimise. Flag changes somewhere.
|
174
175
|
return this.boxGraph.boxes().some(box => box.accept({
|
175
176
|
visitTrackBox: (box) => {
|
176
|
-
for (const
|
177
|
+
for (const [current, next] of Arrays.iterateAdjacent(box.regions.pointerHub.incoming()
|
177
178
|
.map(({ box }) => UnionBoxTypes.asRegionBox(box))
|
178
179
|
.sort(({ position: a }, { position: b }) => a.getValue() - b.getValue()))) {
|
179
180
|
if (current.position.getValue() + current.duration.getValue() > next.position.getValue()) {
|
@@ -1,5 +1,5 @@
|
|
1
|
-
import {
|
1
|
+
import { ProjectSkeleton } from "@opendaw/studio-adapters";
|
2
2
|
export declare class ProjectMigration {
|
3
|
-
static migrate({ boxGraph, mandatoryBoxes }:
|
3
|
+
static migrate({ boxGraph, mandatoryBoxes }: ProjectSkeleton): void;
|
4
4
|
}
|
5
5
|
//# sourceMappingURL=ProjectMigration.d.ts.map
|
@@ -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":"AAYA,OAAO,EAAC,eAAe,EAAC,MAAM,0BAA0B,CAAA;AAExD,qBAAa,gBAAgB;IACzB,MAAM,CAAC,OAAO,CAAC,EAAC,QAAQ,EAAE,cAAc,EAAC,EAAE,eAAe,GAAG,IAAI;CAmEpE"}
|
@@ -16,7 +16,6 @@ export class ProjectMigration {
|
|
16
16
|
globalShuffle.setValue("Groove Shuffle");
|
17
17
|
boxGraph.endTransaction();
|
18
18
|
}
|
19
|
-
// TODO We can remove this when we delete all not-migrated, local(!) project files from my machine
|
20
19
|
// We need to run on a copy, because we might add more boxes during the migration
|
21
20
|
boxGraph.boxes().slice().forEach(box => box.accept({
|
22
21
|
visitZeitgeistDeviceBox: (box) => {
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ProjectValidation.d.ts","sourceRoot":"","sources":["../../src/project/ProjectValidation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,eAAe,EAAC,MAAM,0BAA0B,CAAA;AAGxD,yBAAiB,iBAAiB,CAAC;IACxB,MAAM,QAAQ,GAAI,UAAU,eAAe,KAAG,IA2CpD,CAAA;CACJ"}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import { Arrays, asDefined, EmptyExec, RuntimeNotifier } from "@opendaw/lib-std";
|
2
|
+
export var ProjectValidation;
|
3
|
+
(function (ProjectValidation) {
|
4
|
+
ProjectValidation.validate = (skeleton) => {
|
5
|
+
const { boxGraph } = skeleton;
|
6
|
+
const invalidBoxes = new Set();
|
7
|
+
const validateRegion = (box) => {
|
8
|
+
if (box.position.getValue() < 0) {
|
9
|
+
console.warn(box, "must have a position greater equal 0");
|
10
|
+
invalidBoxes.add(box);
|
11
|
+
}
|
12
|
+
if (box.duration.getValue() <= 0) {
|
13
|
+
console.warn(box, "must have a duration greater than 0");
|
14
|
+
invalidBoxes.add(box);
|
15
|
+
}
|
16
|
+
};
|
17
|
+
boxGraph.boxes().forEach(box => box.accept({
|
18
|
+
visitNoteRegionBox: (box) => validateRegion(box),
|
19
|
+
visitValueRegionBox: (box) => validateRegion(box),
|
20
|
+
visitAudioRegionBox: (box) => validateRegion(box),
|
21
|
+
visitTrackBox: (box) => Arrays.iterateAdjacent(box.regions.pointerHub.incoming()
|
22
|
+
.map(({ box }) => asDefined(box.accept({
|
23
|
+
visitNoteRegionBox: (box) => box,
|
24
|
+
visitValueRegionBox: (box) => box,
|
25
|
+
visitAudioRegionBox: (box) => box
|
26
|
+
}), "Box must be a NoteRegionBox, ValueRegionBox or AudioRegionBox"))
|
27
|
+
.sort((a, b) => a.position.getValue() - b.position.getValue()))
|
28
|
+
.forEach(([left, right]) => {
|
29
|
+
if (right.position.getValue() < left.position.getValue() + left.duration.getValue()) {
|
30
|
+
console.warn(left, right, "Overlapping regions");
|
31
|
+
invalidBoxes.add(left);
|
32
|
+
invalidBoxes.add(right);
|
33
|
+
}
|
34
|
+
})
|
35
|
+
}));
|
36
|
+
if (invalidBoxes.size === 0) {
|
37
|
+
return;
|
38
|
+
}
|
39
|
+
console.warn(`Deleting ${invalidBoxes.size} invalid boxes:`);
|
40
|
+
boxGraph.beginTransaction();
|
41
|
+
invalidBoxes.forEach(box => box.delete());
|
42
|
+
boxGraph.endTransaction();
|
43
|
+
RuntimeNotifier.info({
|
44
|
+
headline: "Some data is corrupt",
|
45
|
+
message: `The project contains ${invalidBoxes.size} invalid boxes.
|
46
|
+
We fixed them as good as possible. This probably happend because there was a bug that we hopefully fixed.
|
47
|
+
Please send this file to the developers.`
|
48
|
+
}).then(EmptyExec, EmptyExec);
|
49
|
+
};
|
50
|
+
})(ProjectValidation || (ProjectValidation = {}));
|
package/dist/samples/index.d.ts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/samples/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,iBAAiB,CAAA;AAC/B,cAAc,
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/samples/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,iBAAiB,CAAA"}
|
package/dist/samples/index.js
CHANGED
@@ -7,6 +7,8 @@ export declare class TimelineRange implements Terminable {
|
|
7
7
|
set minUnits(_: number);
|
8
8
|
get maxUnits(): number;
|
9
9
|
set maxUnits(value: number);
|
10
|
+
get unitCenter(): number;
|
11
|
+
set unitCenter(value: number);
|
10
12
|
get width(): number;
|
11
13
|
set width(value: number);
|
12
14
|
get minimum(): number;
|
@@ -19,7 +21,7 @@ export declare class TimelineRange implements Terminable {
|
|
19
21
|
get unitRange(): number;
|
20
22
|
get valueAxis(): ValueAxis;
|
21
23
|
normalize(value: number): unitValue;
|
22
|
-
|
24
|
+
toUnits(value: number): unitValue;
|
23
25
|
unitToX(unit: number): number;
|
24
26
|
xToUnit(x: number): number;
|
25
27
|
moveToUnit(value: number): void;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"TimelineRange.d.ts","sourceRoot":"","sources":["../../src/ui/TimelineRange.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,QAAQ,EAGR,YAAY,EACZ,YAAY,EACZ,UAAU,EAEV,SAAS,EACT,SAAS,EACZ,MAAM,kBAAkB,CAAA;AAEzB,qBAAa,aAAc,YAAW,UAAU;;gBAShC,OAAO,CAAC,EAAE,YAAY;IAYlC,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,YAAY;IAE1D,IAAI,QAAQ,IAAI,MAAM,CAAW;IACjC,IAAI,QAAQ,CAAC,CAAC,EAAE,MAAM,EAErB;IAED,IAAI,QAAQ,IAAI,MAAM,CAAwB;IAC9C,IAAI,QAAQ,CAAC,KAAK,EAAE,MAAM,EAIzB;IAED,IAAI,KAAK,IAAI,MAAM,CAA2B;IAC9C,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAA6B;IAGpD,IAAI,OAAO,IAAI,MAAM,CAAuB;IAC5C,IAAI,OAAO,CAAC,KAAK,EAAE,MAAM,EAAyB;IAElD,IAAI,OAAO,IAAI,MAAM,
|
1
|
+
{"version":3,"file":"TimelineRange.d.ts","sourceRoot":"","sources":["../../src/ui/TimelineRange.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,QAAQ,EAGR,YAAY,EACZ,YAAY,EACZ,UAAU,EAEV,SAAS,EACT,SAAS,EACZ,MAAM,kBAAkB,CAAA;AAEzB,qBAAa,aAAc,YAAW,UAAU;;gBAShC,OAAO,CAAC,EAAE,YAAY;IAYlC,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,YAAY;IAE1D,IAAI,QAAQ,IAAI,MAAM,CAAW;IACjC,IAAI,QAAQ,CAAC,CAAC,EAAE,MAAM,EAErB;IAED,IAAI,QAAQ,IAAI,MAAM,CAAwB;IAC9C,IAAI,QAAQ,CAAC,KAAK,EAAE,MAAM,EAIzB;IAED,IAAI,UAAU,IAAI,MAAM,CAA0C;IAClE,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,EAA8C;IAE1E,IAAI,KAAK,IAAI,MAAM,CAA2B;IAC9C,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAA6B;IAGpD,IAAI,OAAO,IAAI,MAAM,CAAuB;IAC5C,IAAI,OAAO,CAAC,KAAK,EAAE,MAAM,EAAyB;IAElD,IAAI,OAAO,IAAI,MAAM,CAAuC;IAC5D,IAAI,OAAO,CAAC,KAAK,EAAE,MAAM,EAA2C;IACpE,IAAI,OAAO,IAAI,MAAM,CAAuC;IAC5D,IAAI,OAAO,CAAC,KAAK,EAAE,MAAM,EAA2C;IACpE,IAAI,aAAa,IAAI,MAAM,CAAkD;IAC7E,IAAI,SAAS,IAAI,MAAM,CAAqC;IAC5D,IAAI,SAAS,IAAI,SAAS,CAAyB;IACnD,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS;IACnC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS;IACjC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAC7B,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAC1B,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAC/B,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAC/C,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAChD,OAAO,IAAI,IAAI;IACf,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW,GAAG,IAAI;IAa/D,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAC/B,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAC/B,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,GAAG,IAAI;IACrD,IAAI,WAAW,IAAI,MAAM,CAAkD;IAC3E,IAAI,GAAG,IAAI,SAAS,CAAyB;IAC7C,IAAI,GAAG,CAAC,KAAK,EAAE,SAAS,EAA2B;IACnD,IAAI,GAAG,IAAI,SAAS,CAAyB;IAC7C,IAAI,GAAG,CAAC,KAAK,EAAE,SAAS,EAA2B;IACnD,IAAI,MAAM,IAAI,SAAS,CAA4B;IACnD,IAAI,MAAM,CAAC,KAAK,EAAE,SAAS,EAA8B;IACzD,IAAI,MAAM,IAAI,SAAS,CAA4B;IACnD,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAC9B,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAC9B,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,GAAG,IAAI;IACjD,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS;IAC9B,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;IAElD,SAAS,IAAI,IAAI;CACpB"}
|
package/dist/ui/TimelineRange.js
CHANGED
@@ -29,22 +29,24 @@ export class TimelineRange {
|
|
29
29
|
this.#maxUnits = value;
|
30
30
|
this.#range.minimum = this.normalize(this.#minimum);
|
31
31
|
}
|
32
|
+
get unitCenter() { return this.toUnits(this.#range.center); }
|
33
|
+
set unitCenter(value) { this.#range.center = this.normalize(value); }
|
32
34
|
get width() { return this.#range.width; }
|
33
35
|
set width(value) { this.#range.width = value; }
|
34
36
|
// minimum interval
|
35
37
|
get minimum() { return this.#minimum; }
|
36
38
|
set minimum(value) { this.#minimum = value; }
|
37
|
-
get unitMin() { return this.
|
39
|
+
get unitMin() { return this.toUnits(this.#range.min); }
|
38
40
|
set unitMin(value) { this.#range.min = this.normalize(value); }
|
39
|
-
get unitMax() { return this.
|
41
|
+
get unitMax() { return this.toUnits(this.#range.max); }
|
40
42
|
set unitMax(value) { this.#range.max = this.normalize(value); }
|
41
|
-
get unitsPerPixel() { return this.
|
43
|
+
get unitsPerPixel() { return this.toUnits(this.#range.valuesPerPixel); }
|
42
44
|
get unitRange() { return this.unitMax - this.unitMin; }
|
43
45
|
get valueAxis() { return this.#valueAxis; }
|
44
46
|
normalize(value) { return value / this.maxUnits; }
|
45
|
-
|
47
|
+
toUnits(value) { return value * this.maxUnits; }
|
46
48
|
unitToX(unit) { return this.valueToX(this.normalize(unit)); }
|
47
|
-
xToUnit(x) { return this.
|
49
|
+
xToUnit(x) { return this.toUnits(this.xToValue(x)); }
|
48
50
|
moveToUnit(value) { this.#range.moveTo(this.normalize(value)); }
|
49
51
|
unitOverlaps(min, max) { return this.#range.overlaps(this.normalize(min), this.normalize(max)); }
|
50
52
|
showUnitInterval(min, max) { this.#range.set(this.normalize(min), this.normalize(max)); }
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import { Project } from "../index";
|
2
|
+
import { AudioRegionBoxAdapter } from "@opendaw/studio-adapters";
|
3
|
+
export declare namespace AutofitUtils {
|
4
|
+
const changeBpm: (project: Project, newBpm: number, mark: boolean) => void;
|
5
|
+
const regionsToAutofit: (project: Project, regions: ReadonlyArray<AudioRegionBoxAdapter>) => void;
|
6
|
+
}
|
7
|
+
//# sourceMappingURL=AutofitUtils.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"AutofitUtils.d.ts","sourceRoot":"","sources":["../../src/utils/AutofitUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAC,MAAM,UAAU,CAAA;AAChC,OAAO,EAAsB,qBAAqB,EAAkB,MAAM,0BAA0B,CAAA;AAKpG,yBAAiB,YAAY,CAAC;IAGnB,MAAM,SAAS,GAAI,SAAS,OAAO,EAAE,QAAQ,MAAM,EAAE,MAAM,OAAO,KAAG,IAsC3E,CAAA;IAEM,MAAM,gBAAgB,GAAI,SAAS,OAAO,EAAE,SAAS,aAAa,CAAC,qBAAqB,CAAC,SAgC/F,CAAA;CACJ"}
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import { AudioPlayback } from "@opendaw/studio-enums";
|
2
|
+
import { PPQN } from "@opendaw/lib-dsp";
|
3
|
+
import { ArrayMultimap, isNull, Iterables } from "@opendaw/lib-std";
|
4
|
+
export var AutofitUtils;
|
5
|
+
(function (AutofitUtils) {
|
6
|
+
// Since we do not have an unsynchronized playback, we are going to change the region that has 'autofit' enabled.
|
7
|
+
// This will cause resizing the regions to always play at absolute time (no adaption to tempo change).
|
8
|
+
AutofitUtils.changeBpm = (project, newBpm, mark) => {
|
9
|
+
const { editing, timelineBox: { bpm: bpmField }, rootBoxAdapter } = project;
|
10
|
+
const autofitRegions = rootBoxAdapter.audioUnits.adapters()
|
11
|
+
.flatMap(audioUnitBoxAdapter => audioUnitBoxAdapter.tracks.values()
|
12
|
+
.map(trackBoxAdapter => trackBoxAdapter.regions.collection.asArray()
|
13
|
+
.filter((regionBoxAdapter) => regionBoxAdapter.accept({
|
14
|
+
visitAudioRegionBoxAdapter: (_region) => true
|
15
|
+
}) ?? false)));
|
16
|
+
const oldBpm = bpmField.getValue();
|
17
|
+
const scale = newBpm / oldBpm;
|
18
|
+
editing.modify(() => {
|
19
|
+
autofitRegions.forEach(regions => {
|
20
|
+
for (const [region, next] of Iterables.pairWise(regions)) {
|
21
|
+
// we cannot filter them upfront because the next region would be missing as a limit
|
22
|
+
if (region.box.playback.getValue() !== AudioPlayback.AudioFit) {
|
23
|
+
continue;
|
24
|
+
}
|
25
|
+
let durationInSeconds = region.file.endInSeconds - region.file.startInSeconds;
|
26
|
+
if (durationInSeconds === 0) {
|
27
|
+
console.warn("AutofitUtils.changeBpm: durationInSeconds is 0. Try to access file.");
|
28
|
+
const { numberOfFrames, sampleRate } = region.file.getOrCreateLoader().data
|
29
|
+
.unwrap("AutofitUtils.changeBpm: durationInSeconds is 0 and audio is not loaded yet.");
|
30
|
+
durationInSeconds = numberOfFrames / sampleRate;
|
31
|
+
}
|
32
|
+
const max = isNull(next) ? Number.POSITIVE_INFINITY : next.position;
|
33
|
+
const durationInPulses = Math.min(max, PPQN.secondsToPulses(durationInSeconds, newBpm));
|
34
|
+
const oldDuration = region.box.duration.getValue();
|
35
|
+
const oldLoopOffset = region.box.loopOffset.getValue();
|
36
|
+
const oldLoopDuration = region.box.loopDuration.getValue();
|
37
|
+
const repeat = oldDuration / oldLoopDuration;
|
38
|
+
region.box.duration.setValue(durationInPulses * repeat);
|
39
|
+
region.box.loopDuration.setValue(durationInPulses);
|
40
|
+
region.box.loopOffset.setValue(oldLoopOffset * scale);
|
41
|
+
}
|
42
|
+
});
|
43
|
+
bpmField.setValue(newBpm);
|
44
|
+
}, mark);
|
45
|
+
};
|
46
|
+
AutofitUtils.regionsToAutofit = (project, regions) => {
|
47
|
+
if (regions.length === 0)
|
48
|
+
return;
|
49
|
+
const map = new ArrayMultimap();
|
50
|
+
regions.forEach(region => map.add(region.trackBoxAdapter
|
51
|
+
.unwrap("AutofitUtils.regionsToAutofit: Could not unwrap trackBoxAdapter"), region));
|
52
|
+
const { editing, timelineBox: { bpm: bpmField } } = project;
|
53
|
+
const bpm = bpmField.getValue();
|
54
|
+
editing.modify(() => map.forEach((trackBoxAdapter, regions) => {
|
55
|
+
for (const region of regions) {
|
56
|
+
const next = trackBoxAdapter.regions.collection.greaterEqual(region.complete + 1);
|
57
|
+
const max = isNull(next) ? Number.POSITIVE_INFINITY : next.position;
|
58
|
+
let durationInSeconds = region.file.endInSeconds - region.file.startInSeconds;
|
59
|
+
if (durationInSeconds === 0) {
|
60
|
+
console.warn("AutofitUtils.regionsToAutofit: durationInSeconds is 0. Try to access file.");
|
61
|
+
const { numberOfFrames, sampleRate } = region.file.getOrCreateLoader().data
|
62
|
+
.unwrap("AutofitUtils.regionsToAutofit: durationInSeconds is 0 and audio is not loaded yet.");
|
63
|
+
durationInSeconds = numberOfFrames / sampleRate;
|
64
|
+
}
|
65
|
+
const durationInPulses = Math.min(max, PPQN.secondsToPulses(durationInSeconds, bpm));
|
66
|
+
const oldDuration = region.box.duration.getValue();
|
67
|
+
const oldLoopOffset = region.box.loopOffset.getValue();
|
68
|
+
const oldLoopDuration = region.box.loopDuration.getValue();
|
69
|
+
const repeat = oldDuration / oldLoopDuration;
|
70
|
+
const scale = durationInPulses / oldLoopDuration;
|
71
|
+
region.box.playback.setValue(AudioPlayback.AudioFit);
|
72
|
+
region.box.duration.setValue(durationInPulses * repeat);
|
73
|
+
region.box.loopDuration.setValue(durationInPulses);
|
74
|
+
region.box.loopOffset.setValue(oldLoopOffset * scale);
|
75
|
+
}
|
76
|
+
}));
|
77
|
+
};
|
78
|
+
})(AutofitUtils || (AutofitUtils = {}));
|