@opendaw/studio-core 0.0.10 → 0.0.12

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.
Files changed (46) hide show
  1. package/dist/EffectFactories.d.ts +38 -0
  2. package/dist/EffectFactories.d.ts.map +1 -0
  3. package/dist/EffectFactories.js +163 -0
  4. package/dist/EffectFactory.d.ts +13 -0
  5. package/dist/EffectFactory.d.ts.map +1 -0
  6. package/dist/EffectFactory.js +1 -0
  7. package/dist/InstrumentBox.d.ts +3 -0
  8. package/dist/InstrumentBox.d.ts.map +1 -0
  9. package/dist/InstrumentBox.js +1 -0
  10. package/dist/InstrumentFactories.d.ts +15 -0
  11. package/dist/InstrumentFactories.d.ts.map +1 -0
  12. package/dist/{Instruments.js → InstrumentFactories.js} +31 -69
  13. package/dist/InstrumentFactory.d.ts +11 -0
  14. package/dist/InstrumentFactory.d.ts.map +1 -0
  15. package/dist/InstrumentFactory.js +1 -0
  16. package/dist/InstrumentOptions.d.ts +8 -0
  17. package/dist/InstrumentOptions.d.ts.map +1 -0
  18. package/dist/InstrumentOptions.js +1 -0
  19. package/dist/InstrumentProduct.d.ts +8 -0
  20. package/dist/InstrumentProduct.d.ts.map +1 -0
  21. package/dist/InstrumentProduct.js +1 -0
  22. package/dist/Project.d.ts +3 -1
  23. package/dist/Project.d.ts.map +1 -1
  24. package/dist/Project.js +7 -59
  25. package/dist/ProjectApi.d.ts +44 -0
  26. package/dist/ProjectApi.d.ts.map +1 -0
  27. package/dist/ProjectApi.js +217 -0
  28. package/dist/ProjectMigration.d.ts +5 -0
  29. package/dist/ProjectMigration.d.ts.map +1 -0
  30. package/dist/ProjectMigration.js +60 -0
  31. package/dist/index.d.ts +8 -3
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +8 -3
  34. package/dist/processors.js +2 -2
  35. package/dist/processors.js.map +3 -3
  36. package/dist/workers.js +2 -2
  37. package/dist/workers.js.map +4 -4
  38. package/package.json +16 -16
  39. package/dist/Effects.d.ts +0 -154
  40. package/dist/Effects.d.ts.map +0 -1
  41. package/dist/Effects.js +0 -166
  42. package/dist/Instruments.d.ts +0 -35
  43. package/dist/Instruments.d.ts.map +0 -1
  44. package/dist/Modifier.d.ts +0 -21
  45. package/dist/Modifier.d.ts.map +0 -1
  46. package/dist/Modifier.js +0 -168
@@ -0,0 +1,217 @@
1
+ import { assert, Option, panic, Strings, UUID } from "@opendaw/lib-std";
2
+ import { AudioUnitType } from "@opendaw/studio-enums";
3
+ import { AudioBusBox, AudioUnitBox, NoteClipBox, NoteEventBox, NoteEventCollectionBox, NoteRegionBox, TrackBox, ValueClipBox, ValueEventCollectionBox, ValueRegionBox } from "@opendaw/studio-boxes";
4
+ import { AudioUnitBoxAdapter, IconSymbol, NoteEventBoxAdapter, TrackType } from "@opendaw/studio-adapters";
5
+ import { ColorCodes } from "./ColorCodes";
6
+ import { PPQN } from "@opendaw/lib-dsp";
7
+ export class ProjectApi {
8
+ static AudioUnitOrdering = {
9
+ [AudioUnitType.Instrument]: 0,
10
+ [AudioUnitType.Aux]: 1,
11
+ [AudioUnitType.Bus]: 2,
12
+ [AudioUnitType.Output]: 3
13
+ };
14
+ #project;
15
+ constructor(project) { this.#project = project; }
16
+ createInstrument({ create, defaultIcon, defaultName, trackType }, { name, icon, index } = {}) {
17
+ const { boxGraph, boxAdapters, rootBoxAdapter, userEditingManager } = this.#project;
18
+ const existingNames = rootBoxAdapter.audioUnits.adapters()
19
+ .map(adapter => adapter.input.getValue().match({
20
+ none: () => "Untitled",
21
+ some: adapter => adapter.labelField.getValue()
22
+ }));
23
+ const audioUnitBox = this.#createAudioUnit(AudioUnitType.Instrument, index);
24
+ const audioUnitBoxAdapter = boxAdapters.adapterFor(audioUnitBox, AudioUnitBoxAdapter);
25
+ const uniqueName = Strings.getUniqueName(existingNames, name ?? defaultName);
26
+ const iconSymbol = icon ?? defaultIcon;
27
+ const instrumentBox = create(boxGraph, audioUnitBoxAdapter, uniqueName, iconSymbol);
28
+ const trackBox = TrackBox.create(boxGraph, UUID.generate(), box => {
29
+ box.index.setValue(0);
30
+ box.type.setValue(trackType);
31
+ box.tracks.refer(audioUnitBoxAdapter.tracksField);
32
+ box.target.refer(audioUnitBoxAdapter.audioUnitBoxAdapter().box);
33
+ });
34
+ userEditingManager.audioUnit.edit(audioUnitBox.editing);
35
+ return { audioUnitBox, instrumentBox, trackBox };
36
+ }
37
+ createEffect(host, factory, newIndex) {
38
+ let chain;
39
+ let field;
40
+ if (factory.type === "audio") {
41
+ chain = host.audioEffects.adapters();
42
+ field = host.audioEffects.field();
43
+ }
44
+ else if (factory.type === "midi") {
45
+ chain = host.midiEffects.adapters();
46
+ field = host.midiEffects.field();
47
+ }
48
+ else {
49
+ return panic(`Unknown factory type: ${factory.type}`);
50
+ }
51
+ const box = factory.create(this.#project, field, newIndex);
52
+ for (let index = newIndex; index < chain.length; index++) {
53
+ chain[index].indexField.setValue(index + 1);
54
+ }
55
+ return box;
56
+ }
57
+ createAudioBus(name, icon, type, color) {
58
+ console.debug(`createAudioBus '${name}', type: ${type}, color: ${color}`);
59
+ const { rootBox, boxGraph } = this.#project;
60
+ assert(rootBox.audioBusses.isAttached(), "rootBox not attached");
61
+ const uuid = UUID.generate();
62
+ const audioBusBox = AudioBusBox.create(boxGraph, uuid, box => {
63
+ box.collection.refer(rootBox.audioBusses);
64
+ box.label.setValue(name);
65
+ box.icon.setValue(IconSymbol.toName(icon));
66
+ box.color.setValue(color);
67
+ });
68
+ const audioUnitBox = this.#createAudioUnit(type);
69
+ TrackBox.create(boxGraph, UUID.generate(), box => {
70
+ box.tracks.refer(audioUnitBox.tracks);
71
+ box.target.refer(audioUnitBox);
72
+ box.index.setValue(0);
73
+ box.type.setValue(TrackType.Undefined);
74
+ });
75
+ audioBusBox.output.refer(audioUnitBox.input);
76
+ return audioBusBox;
77
+ }
78
+ createNoteTrack(adapter, index = 0) {
79
+ return this.#createTrack(adapter, TrackType.Notes, index);
80
+ }
81
+ createAudioTrack(adapter, index = 0) {
82
+ return this.#createTrack(adapter, TrackType.Audio, index);
83
+ }
84
+ createAutomationTrack(adapter, index = 0) {
85
+ return this.#createTrack(adapter, TrackType.Value, index);
86
+ }
87
+ createClip(trackBox, clipIndex, { name, hue } = {}) {
88
+ const { boxGraph } = this.#project;
89
+ const type = trackBox.type.getValue();
90
+ switch (type) {
91
+ case TrackType.Notes: {
92
+ const events = NoteEventCollectionBox.create(boxGraph, UUID.generate());
93
+ return Option.wrap(NoteClipBox.create(boxGraph, UUID.generate(), box => {
94
+ box.index.setValue(clipIndex);
95
+ box.label.setValue(name ?? "Notes");
96
+ box.hue.setValue(hue ?? ColorCodes.forTrackType(type));
97
+ box.mute.setValue(false);
98
+ box.duration.setValue(PPQN.Bar);
99
+ box.clips.refer(trackBox.clips);
100
+ box.events.refer(events.owners);
101
+ }));
102
+ }
103
+ case TrackType.Value: {
104
+ const events = ValueEventCollectionBox.create(boxGraph, UUID.generate());
105
+ return Option.wrap(ValueClipBox.create(boxGraph, UUID.generate(), box => {
106
+ box.index.setValue(clipIndex);
107
+ box.label.setValue(name ?? "CV");
108
+ box.hue.setValue(hue ?? ColorCodes.forTrackType(type));
109
+ box.mute.setValue(false);
110
+ box.duration.setValue(PPQN.Bar);
111
+ box.events.refer(events.owners);
112
+ box.clips.refer(trackBox.clips);
113
+ }));
114
+ }
115
+ }
116
+ return Option.None;
117
+ }
118
+ createRegion(trackBox, position, duration, { name, hue } = {}) {
119
+ const { boxGraph } = this.#project;
120
+ const type = trackBox.type.getValue();
121
+ switch (type) {
122
+ case TrackType.Notes: {
123
+ const events = NoteEventCollectionBox.create(boxGraph, UUID.generate());
124
+ return Option.wrap(NoteRegionBox.create(boxGraph, UUID.generate(), box => {
125
+ box.position.setValue(Math.max(position, 0));
126
+ box.label.setValue(name ?? "Notes");
127
+ box.hue.setValue(hue ?? ColorCodes.forTrackType(type));
128
+ box.mute.setValue(false);
129
+ box.duration.setValue(duration);
130
+ box.loopDuration.setValue(PPQN.Bar);
131
+ box.events.refer(events.owners);
132
+ box.regions.refer(trackBox.regions);
133
+ }));
134
+ }
135
+ case TrackType.Value: {
136
+ const events = ValueEventCollectionBox.create(boxGraph, UUID.generate());
137
+ return Option.wrap(ValueRegionBox.create(boxGraph, UUID.generate(), box => {
138
+ box.position.setValue(Math.max(position, 0));
139
+ box.label.setValue(name ?? "Automation");
140
+ box.hue.setValue(hue ?? ColorCodes.forTrackType(type));
141
+ box.mute.setValue(false);
142
+ box.duration.setValue(duration);
143
+ box.loopDuration.setValue(PPQN.Bar);
144
+ box.events.refer(events.owners);
145
+ box.regions.refer(trackBox.regions);
146
+ }));
147
+ }
148
+ }
149
+ return Option.None;
150
+ }
151
+ createNoteEvent({ owner, position, duration, velocity, pitch, chance, cent }) {
152
+ const { boxAdapters, boxGraph } = this.#project;
153
+ return boxAdapters.adapterFor(NoteEventBox.create(boxGraph, UUID.generate(), box => {
154
+ box.position.setValue(position);
155
+ box.duration.setValue(duration);
156
+ box.velocity.setValue(velocity ?? 1.0);
157
+ box.pitch.setValue(pitch);
158
+ box.chance.setValue(chance ?? 100.0);
159
+ box.cent.setValue(cent ?? 0.0);
160
+ box.events.refer(owner.events.targetVertex
161
+ .unwrap("Owner has no event-collection").box
162
+ .asBox(NoteEventCollectionBox).events);
163
+ }), NoteEventBoxAdapter);
164
+ }
165
+ deleteAudioUnit(adapter) {
166
+ const { rootBoxAdapter } = this.#project;
167
+ const adapters = rootBoxAdapter.audioUnits.adapters();
168
+ const boxIndex = adapter.indexField.getValue();
169
+ const deleteIndex = adapters.indexOf(adapter);
170
+ console.debug(`deleteAudioUnit adapter: ${adapter.toString()}, deleteIndex: ${deleteIndex}, indexField: ${boxIndex}`);
171
+ if (deleteIndex === -1) {
172
+ return panic(`Cannot delete ${adapter}. Does not exist.`);
173
+ }
174
+ if (deleteIndex !== boxIndex) {
175
+ console.debug("indices", adapters.map(x => x.box.index.getValue()).join(", "));
176
+ return panic(`Cannot delete ${adapter}. Wrong index.`);
177
+ }
178
+ for (let index = deleteIndex + 1; index < adapters.length; index++) {
179
+ adapters[index].indexField.setValue(index - 1);
180
+ }
181
+ adapter.box.delete();
182
+ }
183
+ #createAudioUnit(type, index) {
184
+ const { boxGraph, rootBox, rootBoxAdapter, masterBusBox } = this.#project;
185
+ const insertIndex = index ?? this.#pushAudioUnitsIndices(rootBoxAdapter, type, 1);
186
+ console.debug(`createAudioUnit type: ${type}, insertIndex: ${insertIndex}`);
187
+ return AudioUnitBox.create(boxGraph, UUID.generate(), box => {
188
+ box.collection.refer(rootBox.audioUnits);
189
+ box.output.refer(masterBusBox.input);
190
+ box.index.setValue(insertIndex);
191
+ box.type.setValue(type);
192
+ });
193
+ }
194
+ #createTrack(adapter, trackType, index = 0) {
195
+ return TrackBox.create(this.#project.boxGraph, UUID.generate(), box => {
196
+ box.index.setValue(index);
197
+ box.type.setValue(trackType);
198
+ box.tracks.refer(adapter.tracksField);
199
+ box.target.refer(adapter.audioUnitBoxAdapter().box);
200
+ });
201
+ }
202
+ #pushAudioUnitsIndices(rootBoxAdapter, type, count = 1) {
203
+ const adapters = rootBoxAdapter.audioUnits.adapters();
204
+ const order = ProjectApi.AudioUnitOrdering[type];
205
+ let index = 0 | 0;
206
+ for (; index < adapters.length; index++) {
207
+ if (ProjectApi.AudioUnitOrdering[adapters[index].type] > order) {
208
+ break;
209
+ }
210
+ }
211
+ const insertIndex = index;
212
+ while (index < adapters.length) {
213
+ adapters[index].indexField.setValue(count + index++);
214
+ }
215
+ return insertIndex;
216
+ }
217
+ }
@@ -0,0 +1,5 @@
1
+ import { ProjectDecoder } from "@opendaw/studio-adapters";
2
+ export declare class ProjectMigration {
3
+ static migrate({ boxGraph, mandatoryBoxes }: ProjectDecoder.Skeleton): void;
4
+ }
5
+ //# sourceMappingURL=ProjectMigration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProjectMigration.d.ts","sourceRoot":"","sources":["../src/ProjectMigration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAUvD,qBAAa,gBAAgB;IACzB,MAAM,CAAC,OAAO,CAAC,EAAC,QAAQ,EAAE,cAAc,EAAC,EAAE,cAAc,CAAC,QAAQ,GAAG,IAAI;CAoD5E"}
@@ -0,0 +1,60 @@
1
+ import { GrooveShuffleBox, ValueEventCurveBox } from "@opendaw/studio-boxes";
2
+ import { asInstanceOf, UUID } from "@opendaw/lib-std";
3
+ export class ProjectMigration {
4
+ static migrate({ boxGraph, mandatoryBoxes }) {
5
+ const { rootBox } = mandatoryBoxes;
6
+ if (rootBox.groove.targetAddress.isEmpty()) {
7
+ console.debug("Migrate to global GrooveShuffleBox");
8
+ boxGraph.beginTransaction();
9
+ rootBox.groove.refer(GrooveShuffleBox.create(boxGraph, UUID.generate()));
10
+ boxGraph.endTransaction();
11
+ }
12
+ const globalShuffle = asInstanceOf(rootBox.groove.targetVertex.unwrap(), GrooveShuffleBox).label;
13
+ if (globalShuffle.getValue() !== "Groove Shuffle") {
14
+ boxGraph.beginTransaction();
15
+ globalShuffle.setValue("Groove Shuffle");
16
+ boxGraph.endTransaction();
17
+ }
18
+ // TODO We can remove this when we delete all not-migrated, local(!) project files from my machine
19
+ boxGraph.boxes().forEach(box => box.accept({
20
+ visitZeitgeistDeviceBox: (box) => {
21
+ if (box.groove.targetAddress.isEmpty()) {
22
+ console.debug("Migrate 'ZeitgeistDeviceBox' to GrooveShuffleBox");
23
+ boxGraph.beginTransaction();
24
+ box.groove.refer(rootBox.groove.targetVertex.unwrap());
25
+ boxGraph.endTransaction();
26
+ }
27
+ },
28
+ visitValueEventBox: (eventBox) => {
29
+ const slope = eventBox.slope.getValue();
30
+ if (isNaN(slope)) {
31
+ return;
32
+ } // already migrated, nothing to do
33
+ if (slope === 0.0) { // never set
34
+ console.debug("Migrate 'ValueEventBox'");
35
+ boxGraph.beginTransaction();
36
+ eventBox.slope.setValue(NaN);
37
+ boxGraph.endTransaction();
38
+ }
39
+ else if (eventBox.interpolation.getValue() === 1) { // linear
40
+ if (slope === 0.5) {
41
+ console.debug("Migrate 'ValueEventBox' to linear");
42
+ boxGraph.beginTransaction();
43
+ eventBox.slope.setValue(NaN);
44
+ boxGraph.endTransaction();
45
+ }
46
+ else {
47
+ console.debug("Migrate 'ValueEventBox' to new ValueEventCurveBox");
48
+ boxGraph.beginTransaction();
49
+ ValueEventCurveBox.create(boxGraph, UUID.generate(), box => {
50
+ box.event.refer(eventBox.interpolation);
51
+ box.slope.setValue(slope);
52
+ });
53
+ eventBox.slope.setValue(NaN);
54
+ boxGraph.endTransaction();
55
+ }
56
+ }
57
+ }
58
+ }));
59
+ }
60
+ }
package/dist/index.d.ts CHANGED
@@ -8,14 +8,19 @@ export * from "./samples/MainThreadSampleManager";
8
8
  export * from "./samples/SampleProvider";
9
9
  export * from "./ColorCodes";
10
10
  export * from "./Colors";
11
- export * from "./Effects";
11
+ export * from "./EffectFactory";
12
+ export * from "./EffectFactories";
12
13
  export * from "./Engine";
13
14
  export * from "./EngineFacade";
14
15
  export * from "./EngineWorklet";
15
- export * from "./Instruments";
16
+ export * from "./InstrumentBox";
17
+ export * from "./InstrumentFactories";
18
+ export * from "./InstrumentFactory";
19
+ export * from "./InstrumentOptions";
20
+ export * from "./InstrumentProduct";
16
21
  export * from "./Mixer";
17
- export * from "./Modifier";
18
22
  export * from "./Project";
23
+ export * from "./ProjectApi";
19
24
  export * from "./ProjectEnv";
20
25
  export * from "./Wav";
21
26
  export * from "./WorkerAgents";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,0BAA0B,CAAA;AAExC,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,SAAS,CAAA;AACvB,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,OAAO,CAAA;AACrB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,0BAA0B,CAAA;AAExC,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,mBAAmB,CAAA;AACjC,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,OAAO,CAAA;AACrB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA"}
package/dist/index.js CHANGED
@@ -8,14 +8,19 @@ export * from "./samples/MainThreadSampleManager";
8
8
  export * from "./samples/SampleProvider";
9
9
  export * from "./ColorCodes";
10
10
  export * from "./Colors";
11
- export * from "./Effects";
11
+ export * from "./EffectFactory";
12
+ export * from "./EffectFactories";
12
13
  export * from "./Engine";
13
14
  export * from "./EngineFacade";
14
15
  export * from "./EngineWorklet";
15
- export * from "./Instruments";
16
+ export * from "./InstrumentBox";
17
+ export * from "./InstrumentFactories";
18
+ export * from "./InstrumentFactory";
19
+ export * from "./InstrumentOptions";
20
+ export * from "./InstrumentProduct";
16
21
  export * from "./Mixer";
17
- export * from "./Modifier";
18
22
  export * from "./Project";
23
+ export * from "./ProjectApi";
19
24
  export * from "./ProjectEnv";
20
25
  export * from "./Wav";
21
26
  export * from "./WorkerAgents";