@blibliki/engine 0.1.17 → 0.1.19
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/README.md +13 -1
- package/{build → dist/build}/Engine.d.ts +14 -22
- package/dist/build/core/IO/AudioNode.d.ts +35 -0
- package/dist/build/core/IO/Collection.d.ts +13 -0
- package/dist/build/core/IO/ForwardNode.d.ts +38 -0
- package/dist/build/core/IO/MidiNode.d.ts +30 -0
- package/dist/build/core/IO/Node.d.ts +36 -0
- package/dist/build/core/IO/index.d.ts +12 -0
- package/dist/build/core/Module/MonoModule.d.ts +67 -0
- package/dist/build/core/Module/PolyModule.d.ts +57 -0
- package/dist/build/core/Module/index.d.ts +6 -0
- package/{build → dist/build/core}/Note/index.d.ts +3 -0
- package/{build → dist/build/core/midi}/MidiDevice.d.ts +1 -1
- package/dist/build/core/midi/MidiEvent.d.ts +21 -0
- package/dist/build/core/midi/index.d.ts +5 -0
- package/dist/build/index.d.ts +9 -0
- package/{build/Module → dist/build/modules}/BitCrusher.d.ts +5 -1
- package/{build/Module → dist/build/modules}/Delay.d.ts +5 -1
- package/{build/Module → dist/build/modules}/Distortion.d.ts +5 -1
- package/{build/Module → dist/build/modules}/Effect.d.ts +7 -2
- package/{build/Module → dist/build/modules}/Envelope/AmpEnvelope.d.ts +10 -2
- package/{build/Module → dist/build/modules}/Envelope/Base.d.ts +30 -11
- package/{build/Module → dist/build/modules}/Envelope/FreqEnvelope.d.ts +10 -3
- package/{build/Module → dist/build/modules}/Filter.d.ts +13 -13
- package/{build/Module → dist/build/modules}/Master.d.ts +5 -2
- package/{build/Module → dist/build/modules}/MidiSelector.d.ts +9 -5
- package/{build/Module → dist/build/modules}/Oscillator.d.ts +15 -9
- package/{build/Module → dist/build/modules}/Reverb.d.ts +5 -1
- package/{build/Module → dist/build/modules}/Sequencer.d.ts +9 -5
- package/{build/Module → dist/build/modules}/VirtualMidi.d.ts +12 -8
- package/dist/build/modules/VoiceScheduler.d.ts +43 -0
- package/dist/build/modules/Volume.d.ts +26 -0
- package/dist/build/modules/index.d.ts +16 -0
- package/{build → dist/build}/routes.d.ts +6 -5
- package/dist/build/types.d.ts +5 -0
- package/dist/build/utils.d.ts +1 -0
- package/dist/main.cjs.js +33 -0
- package/dist/main.cjs.js.map +1 -0
- package/dist/main.esm.js +33 -0
- package/dist/main.esm.js.map +1 -0
- package/package.json +26 -22
- package/src/Engine.ts +27 -36
- package/src/core/IO/AudioNode.ts +77 -0
- package/src/core/IO/Collection.ts +76 -0
- package/src/core/IO/ForwardNode.ts +192 -0
- package/src/core/IO/MidiNode.ts +67 -0
- package/src/core/IO/Node.ts +117 -0
- package/src/core/IO/index.ts +47 -0
- package/src/core/Module/MonoModule.ts +219 -0
- package/src/core/Module/PolyModule.ts +206 -0
- package/src/core/Module/index.ts +15 -0
- package/src/{Note → core/Note}/index.ts +19 -4
- package/src/{MidiDeviceManager.ts → core/midi/MidiDeviceManager.ts} +20 -15
- package/src/core/midi/MidiEvent.ts +91 -0
- package/src/core/midi/index.ts +5 -0
- package/src/index.ts +8 -12
- package/src/{Module → modules}/BitCrusher.ts +15 -4
- package/src/{Module → modules}/Delay.ts +15 -4
- package/src/{Module → modules}/Distortion.ts +15 -4
- package/src/{Module → modules}/Effect.ts +10 -6
- package/src/modules/Envelope/AmpEnvelope.ts +23 -0
- package/src/{Module → modules}/Envelope/Base.ts +50 -31
- package/src/{Module → modules}/Envelope/FreqEnvelope.ts +18 -23
- package/src/{Module → modules}/Filter.ts +18 -46
- package/src/{Module → modules}/Master.ts +8 -2
- package/src/{Module → modules}/MidiSelector.ts +18 -14
- package/src/{Module → modules}/Oscillator.ts +27 -16
- package/src/{Module → modules}/Reverb.ts +15 -4
- package/src/{Module → modules}/Sequencer.ts +17 -13
- package/src/{Module → modules}/VirtualMidi.ts +16 -12
- package/src/modules/VoiceScheduler.ts +145 -0
- package/src/{Module → modules}/Volume.ts +23 -15
- package/src/{Module → modules}/index.ts +14 -21
- package/src/routes.ts +19 -18
- package/src/types.ts +3 -0
- package/src/utils.ts +18 -0
- package/build/Engine.js +0 -165
- package/build/Engine.js.map +0 -1
- package/build/MidiDevice.js +0 -45
- package/build/MidiDevice.js.map +0 -1
- package/build/MidiDeviceManager.js +0 -59
- package/build/MidiDeviceManager.js.map +0 -1
- package/build/MidiEvent.d.ts +0 -18
- package/build/MidiEvent.js +0 -64
- package/build/MidiEvent.js.map +0 -1
- package/build/Module/Base.d.ts +0 -63
- package/build/Module/Base.js +0 -138
- package/build/Module/Base.js.map +0 -1
- package/build/Module/BitCrusher.js +0 -22
- package/build/Module/BitCrusher.js.map +0 -1
- package/build/Module/DataSequencer.d.ts +0 -26
- package/build/Module/DataSequencer.js +0 -91
- package/build/Module/DataSequencer.js.map +0 -1
- package/build/Module/Delay.js +0 -30
- package/build/Module/Delay.js.map +0 -1
- package/build/Module/Distortion.js +0 -22
- package/build/Module/Distortion.js.map +0 -1
- package/build/Module/Effect.js +0 -22
- package/build/Module/Effect.js.map +0 -1
- package/build/Module/Envelope/AmpEnvelope.js +0 -14
- package/build/Module/Envelope/AmpEnvelope.js.map +0 -1
- package/build/Module/Envelope/Base.js +0 -106
- package/build/Module/Envelope/Base.js.map +0 -1
- package/build/Module/Envelope/FreqEnvelope.js +0 -50
- package/build/Module/Envelope/FreqEnvelope.js.map +0 -1
- package/build/Module/Envelope/index.js +0 -4
- package/build/Module/Envelope/index.js.map +0 -1
- package/build/Module/Filter.js +0 -100
- package/build/Module/Filter.js.map +0 -1
- package/build/Module/IO.d.ts +0 -39
- package/build/Module/IO.js +0 -59
- package/build/Module/IO.js.map +0 -1
- package/build/Module/Master.js +0 -12
- package/build/Module/Master.js.map +0 -1
- package/build/Module/MidiSelector.js +0 -50
- package/build/Module/MidiSelector.js.map +0 -1
- package/build/Module/Oscillator.js +0 -136
- package/build/Module/Oscillator.js.map +0 -1
- package/build/Module/PolyModule.d.ts +0 -49
- package/build/Module/PolyModule.js +0 -175
- package/build/Module/PolyModule.js.map +0 -1
- package/build/Module/Reverb.js +0 -30
- package/build/Module/Reverb.js.map +0 -1
- package/build/Module/Sequencer.js +0 -131
- package/build/Module/Sequencer.js.map +0 -1
- package/build/Module/VirtualMidi.js +0 -53
- package/build/Module/VirtualMidi.js.map +0 -1
- package/build/Module/VoiceScheduler.d.ts +0 -38
- package/build/Module/VoiceScheduler.js +0 -130
- package/build/Module/VoiceScheduler.js.map +0 -1
- package/build/Module/Volume.d.ts +0 -20
- package/build/Module/Volume.js +0 -48
- package/build/Module/Volume.js.map +0 -1
- package/build/Module/index.d.ts +0 -14
- package/build/Module/index.js +0 -66
- package/build/Module/index.js.map +0 -1
- package/build/Note/frequencyTable.js +0 -146
- package/build/Note/frequencyTable.js.map +0 -1
- package/build/Note/index.js +0 -81
- package/build/Note/index.js.map +0 -1
- package/build/index.d.ts +0 -8
- package/build/index.js +0 -5
- package/build/index.js.map +0 -1
- package/build/routes.js +0 -31
- package/build/routes.js.map +0 -1
- package/jest.config.js +0 -19
- package/src/MidiEvent.ts +0 -93
- package/src/Module/Base.ts +0 -223
- package/src/Module/DataSequencer.ts +0 -121
- package/src/Module/Envelope/AmpEnvelope.ts +0 -17
- package/src/Module/IO.ts +0 -85
- package/src/Module/PolyModule.ts +0 -234
- package/src/Module/VoiceScheduler.ts +0 -161
- package/test/Module/Oscillator.test.ts +0 -9
- package/tsconfig.json +0 -22
- /package/{build → dist/build/core}/Note/frequencyTable.d.ts +0 -0
- /package/{build → dist/build/core/midi}/MidiDeviceManager.d.ts +0 -0
- /package/{build/Module → dist/build/modules}/Envelope/index.d.ts +0 -0
- /package/src/{Note → core/Note}/frequencyTable.ts +0 -0
- /package/src/{MidiDevice.ts → core/midi/MidiDevice.ts} +0 -0
- /package/src/{Module → modules}/Envelope/index.ts +0 -0
package/package.json
CHANGED
|
@@ -1,42 +1,46 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blibliki/engine",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"main": "
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.19",
|
|
4
|
+
"main": "dist/main.cjs.js",
|
|
5
|
+
"module": "dist/main.esm.js",
|
|
6
|
+
"types": "dist/build/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"README.md",
|
|
9
|
+
"src",
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
6
12
|
"dependencies": {
|
|
7
13
|
"@types/lodash": "^4.14.186",
|
|
14
|
+
"crypto-js": "^4.2.0",
|
|
8
15
|
"lodash": "^4.17.21",
|
|
9
16
|
"tone": "^14.7.77",
|
|
10
17
|
"uuid": "^8.3.2"
|
|
11
18
|
},
|
|
12
19
|
"scripts": {
|
|
13
20
|
"start": "tsc -w -p tsconfig.json",
|
|
14
|
-
"build": "
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
},
|
|
19
|
-
"browserslist": {
|
|
20
|
-
"production": [
|
|
21
|
-
">0.2%",
|
|
22
|
-
"not dead",
|
|
23
|
-
"not op_mini all"
|
|
24
|
-
],
|
|
25
|
-
"development": [
|
|
26
|
-
"last 1 chrome version",
|
|
27
|
-
"last 1 firefox version",
|
|
28
|
-
"last 1 safari version"
|
|
29
|
-
]
|
|
21
|
+
"build": "rollup -c",
|
|
22
|
+
"lint": "eslint src",
|
|
23
|
+
"ts:check": "tsc --noEmit",
|
|
24
|
+
"test": "jest"
|
|
30
25
|
},
|
|
31
26
|
"devDependencies": {
|
|
27
|
+
"@rollup/plugin-commonjs": "^25.0.7",
|
|
28
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
29
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
30
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
31
|
+
"@types/crypto-js": "^4.2.2",
|
|
32
32
|
"@types/jest": "^29.2.0",
|
|
33
33
|
"@types/node": "^16.7.13",
|
|
34
34
|
"@types/uuid": "^8.3.4",
|
|
35
|
-
"eslint": "^
|
|
35
|
+
"@typescript-eslint/eslint-plugin": "^6.9.0",
|
|
36
|
+
"@typescript-eslint/parser": "^6.9.0",
|
|
37
|
+
"eslint": "^8.52.0",
|
|
36
38
|
"jest": "^29.2.2",
|
|
37
39
|
"prettier": "^2.7.1",
|
|
40
|
+
"rollup": "^4.10.0",
|
|
41
|
+
"rollup-plugin-dts": "^6.1.0",
|
|
38
42
|
"ts-jest": "^29.0.3",
|
|
39
|
-
"typescript": "^
|
|
40
|
-
"typescript-language-server": "^0.
|
|
43
|
+
"typescript": "^5.2.2",
|
|
44
|
+
"typescript-language-server": "^4.0.0"
|
|
41
45
|
}
|
|
42
46
|
}
|
package/src/Engine.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { Context, now, setContext } from "tone";
|
|
2
|
-
import MidiDeviceManager from "./
|
|
3
|
-
import MidiEvent, { EType } from "./MidiEvent";
|
|
2
|
+
import { MidiEvent, MidiDeviceManager } from "./core/midi";
|
|
4
3
|
|
|
5
|
-
import { AudioModule,
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import { applyRoutes, createRoute, RouteInterface, RouteProps } from "./routes";
|
|
4
|
+
import { AudioModule, Startable } from "./core/Module";
|
|
5
|
+
import { createModule, VirtualMidi, VoiceScheduler } from "./modules";
|
|
6
|
+
import { applyRoutes, createRoute, RouteInterface } from "./routes";
|
|
7
|
+
import { AnyObject, Optional } from "./types";
|
|
10
8
|
|
|
11
9
|
type LatencyHint = "interactive" | "playback" | "balanced";
|
|
12
10
|
|
|
@@ -22,10 +20,9 @@ interface InitializeInterface {
|
|
|
22
20
|
class Engine {
|
|
23
21
|
midiDeviceManager: MidiDeviceManager;
|
|
24
22
|
private static instance: Engine;
|
|
25
|
-
private _master: Master;
|
|
26
23
|
private context: Context;
|
|
27
|
-
private propsUpdateCallbacks: { (id: string, props:
|
|
28
|
-
private _isStarted
|
|
24
|
+
private propsUpdateCallbacks: { (id: string, props: AnyObject): void }[];
|
|
25
|
+
private _isStarted = false;
|
|
29
26
|
|
|
30
27
|
modules: {
|
|
31
28
|
[Identifier: string]: AudioModule;
|
|
@@ -51,7 +48,7 @@ class Engine {
|
|
|
51
48
|
|
|
52
49
|
initialize(props: InitializeInterface) {
|
|
53
50
|
return new Promise((resolve) => {
|
|
54
|
-
if (this.context) return resolve({
|
|
51
|
+
if (this.context) return resolve({});
|
|
55
52
|
|
|
56
53
|
this.context = new Context(props.context);
|
|
57
54
|
setContext(this.context);
|
|
@@ -60,15 +57,20 @@ class Engine {
|
|
|
60
57
|
this.midiDeviceManager = new MidiDeviceManager();
|
|
61
58
|
|
|
62
59
|
setTimeout(() => {
|
|
63
|
-
resolve({
|
|
60
|
+
resolve({});
|
|
64
61
|
}, 0);
|
|
65
62
|
});
|
|
66
63
|
}
|
|
67
64
|
|
|
68
|
-
addModule(params: {
|
|
69
|
-
|
|
65
|
+
addModule(params: {
|
|
66
|
+
id?: string;
|
|
67
|
+
name: string;
|
|
68
|
+
type: string;
|
|
69
|
+
props?: AnyObject;
|
|
70
|
+
}) {
|
|
71
|
+
const { id, name, type, props = {} } = params;
|
|
70
72
|
|
|
71
|
-
const audioModule = createModule(name, type, {});
|
|
73
|
+
const audioModule = createModule({ id, name, type, props: {} });
|
|
72
74
|
audioModule.props = props;
|
|
73
75
|
this.modules[audioModule.id] = audioModule;
|
|
74
76
|
|
|
@@ -95,15 +97,15 @@ class Engine {
|
|
|
95
97
|
return audioModule.serialize();
|
|
96
98
|
}
|
|
97
99
|
|
|
98
|
-
onPropsUpdate(callback: (id: string, props:
|
|
100
|
+
onPropsUpdate(callback: (id: string, props: AnyObject) => void) {
|
|
99
101
|
this.propsUpdateCallbacks.push(callback);
|
|
100
102
|
}
|
|
101
103
|
|
|
102
|
-
_triggerPropsUpdate(id: string, props:
|
|
104
|
+
_triggerPropsUpdate(id: string, props: AnyObject) {
|
|
103
105
|
this.propsUpdateCallbacks.forEach((callback) => callback(id, props));
|
|
104
106
|
}
|
|
105
107
|
|
|
106
|
-
updatePropsModule(id: string, props:
|
|
108
|
+
updatePropsModule(id: string, props: AnyObject) {
|
|
107
109
|
const audioModule = this.findById(id);
|
|
108
110
|
|
|
109
111
|
const applyRoutesRequired = this.applyRoutesRequired(audioModule, props);
|
|
@@ -113,7 +115,7 @@ class Engine {
|
|
|
113
115
|
return audioModule.serialize();
|
|
114
116
|
}
|
|
115
117
|
|
|
116
|
-
addRoute(props:
|
|
118
|
+
addRoute(props: Optional<RouteInterface, "id">) {
|
|
117
119
|
const route = createRoute(props);
|
|
118
120
|
const newRoutes = { ...this.routes, [route.id]: route };
|
|
119
121
|
|
|
@@ -128,29 +130,18 @@ class Engine {
|
|
|
128
130
|
this.updateRoutes();
|
|
129
131
|
}
|
|
130
132
|
|
|
131
|
-
|
|
132
|
-
if (this._master) return this._master.serialize();
|
|
133
|
-
|
|
134
|
-
const masterProps = this.addModule({ name: "Master", type: "Master" });
|
|
135
|
-
this._master = this.modules[masterProps.id] as Master;
|
|
136
|
-
|
|
137
|
-
return masterProps;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
triggerVirtualMidi(id: string, noteName: string, type: EType) {
|
|
133
|
+
triggerVirtualMidi(id: string, noteName: string, type: "noteOn" | "noteOff") {
|
|
141
134
|
const virtualMidi = this.findById(id) as VirtualMidi;
|
|
142
135
|
|
|
143
|
-
virtualMidi.sendMidi(MidiEvent.fromNote(noteName, type));
|
|
136
|
+
virtualMidi.sendMidi(MidiEvent.fromNote(noteName, type === "noteOn"));
|
|
144
137
|
}
|
|
145
138
|
|
|
146
139
|
dispose() {
|
|
147
140
|
Object.values(this.modules).forEach((m) => {
|
|
148
|
-
if (m instanceof Master) return;
|
|
149
|
-
|
|
150
141
|
m.dispose();
|
|
151
142
|
});
|
|
152
143
|
|
|
153
|
-
this.modules =
|
|
144
|
+
this.modules = {};
|
|
154
145
|
this.routes = {};
|
|
155
146
|
}
|
|
156
147
|
|
|
@@ -176,7 +167,7 @@ class Engine {
|
|
|
176
167
|
this.updateRoutes();
|
|
177
168
|
|
|
178
169
|
Object.values(this.modules).forEach((audioModule) => {
|
|
179
|
-
const am = audioModule as
|
|
170
|
+
const am = audioModule as unknown as Startable;
|
|
180
171
|
if (!am.start) return;
|
|
181
172
|
|
|
182
173
|
am.start(startTime);
|
|
@@ -186,7 +177,7 @@ class Engine {
|
|
|
186
177
|
stop() {
|
|
187
178
|
const startTime = now();
|
|
188
179
|
Object.values(this.modules).forEach((audioModule) => {
|
|
189
|
-
const am = audioModule as
|
|
180
|
+
const am = audioModule as unknown as Startable;
|
|
190
181
|
if (!am.stop) return;
|
|
191
182
|
|
|
192
183
|
am.stop(startTime);
|
|
@@ -207,7 +198,7 @@ class Engine {
|
|
|
207
198
|
applyRoutes(Object.values(this.routes));
|
|
208
199
|
}
|
|
209
200
|
|
|
210
|
-
private applyRoutesRequired(audioModule: AudioModule, props:
|
|
201
|
+
private applyRoutesRequired(audioModule: AudioModule, props: AnyObject) {
|
|
211
202
|
if (!props.polyNumber) return false;
|
|
212
203
|
if (!(audioModule instanceof VoiceScheduler)) return false;
|
|
213
204
|
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { InputNode } from "tone";
|
|
2
|
+
import IONode, { IOType, IIONode } from "./Node";
|
|
3
|
+
import MonoModule, { Connectable } from "../Module/index";
|
|
4
|
+
import { AnyObject } from "../../types";
|
|
5
|
+
import { ForwardInput, ForwardOutput } from "./ForwardNode";
|
|
6
|
+
|
|
7
|
+
export type AudioIO = AudioInput | AudioOutput;
|
|
8
|
+
|
|
9
|
+
export interface IAudioInput extends IIONode {
|
|
10
|
+
ioType: IOType.AudioInput;
|
|
11
|
+
internalModule: InputNode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface IAudioOutput extends IIONode {
|
|
15
|
+
ioType: IOType.AudioOutput;
|
|
16
|
+
internalModule: IInternalModule;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface IInternalModule extends Connectable {}
|
|
20
|
+
|
|
21
|
+
export class AudioInput extends IONode implements IAudioInput {
|
|
22
|
+
declare ioType: IOType.AudioInput;
|
|
23
|
+
internalModule!: InputNode;
|
|
24
|
+
declare connections: AudioOutput[];
|
|
25
|
+
|
|
26
|
+
constructor(
|
|
27
|
+
plugableModule: MonoModule<Connectable, AnyObject>,
|
|
28
|
+
props: IAudioInput
|
|
29
|
+
) {
|
|
30
|
+
super(plugableModule, props);
|
|
31
|
+
this.internalModule = props.internalModule;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
plug(io: AudioOutput | ForwardOutput, plugOther: boolean = true) {
|
|
35
|
+
super.plug(io, plugOther);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
unPlug(io: AudioOutput | ForwardOutput, plugOther: boolean = true) {
|
|
39
|
+
super.unPlug(io, plugOther);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
unPlugAll() {
|
|
43
|
+
IONode.unPlugAll(this);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class AudioOutput extends IONode implements IAudioOutput {
|
|
48
|
+
declare ioType: IOType.AudioOutput;
|
|
49
|
+
internalModule!: IInternalModule;
|
|
50
|
+
declare connections: AudioInput[];
|
|
51
|
+
|
|
52
|
+
constructor(
|
|
53
|
+
plugableModule: MonoModule<Connectable, AnyObject>,
|
|
54
|
+
props: IAudioOutput
|
|
55
|
+
) {
|
|
56
|
+
super(plugableModule, props);
|
|
57
|
+
this.internalModule = props.internalModule;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
plug(io: AudioInput | ForwardInput, plugOther: boolean = true) {
|
|
61
|
+
super.plug(io, plugOther);
|
|
62
|
+
if (io instanceof ForwardInput) return;
|
|
63
|
+
|
|
64
|
+
this.internalModule.connect(io.internalModule);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
unPlug(io: AudioInput | ForwardInput, plugOther: boolean = true) {
|
|
68
|
+
super.unPlug(io, plugOther);
|
|
69
|
+
if (io instanceof ForwardInput) return;
|
|
70
|
+
|
|
71
|
+
this.internalModule.disconnect(io.internalModule);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
unPlugAll() {
|
|
75
|
+
IONode.unPlugAll(this);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import MonoModule, { AudioModule, PolyModule } from "../Module";
|
|
2
|
+
import IO, { IOType } from "./Node";
|
|
3
|
+
import { AudioInput, AudioOutput } from "./AudioNode";
|
|
4
|
+
import { MidiInput, MidiOutput } from "./MidiNode";
|
|
5
|
+
import { IAnyIO } from ".";
|
|
6
|
+
import { ForwardInput, ForwardOutput } from "./ForwardNode";
|
|
7
|
+
|
|
8
|
+
export default class IOCollection<AnyIO extends IO> {
|
|
9
|
+
plugableModule: AudioModule;
|
|
10
|
+
collection: AnyIO[] = [];
|
|
11
|
+
|
|
12
|
+
constructor(plugableModule: AudioModule) {
|
|
13
|
+
this.plugableModule = plugableModule;
|
|
14
|
+
}
|
|
15
|
+
add<CurrentIO extends AnyIO>(props: IAnyIO): CurrentIO {
|
|
16
|
+
let io;
|
|
17
|
+
|
|
18
|
+
switch (props.ioType) {
|
|
19
|
+
case IOType.AudioInput:
|
|
20
|
+
if (this.plugableModule instanceof PolyModule) {
|
|
21
|
+
throw Error("PolyModule is not supported");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
io = new AudioInput(this.plugableModule, props);
|
|
25
|
+
break;
|
|
26
|
+
case IOType.AudioOutput:
|
|
27
|
+
if (this.plugableModule instanceof PolyModule) {
|
|
28
|
+
throw Error("PolyModule is not supported");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
io = new AudioOutput(this.plugableModule, props);
|
|
32
|
+
break;
|
|
33
|
+
case IOType.ForwardInput:
|
|
34
|
+
if (this.plugableModule instanceof MonoModule) {
|
|
35
|
+
throw Error("MonoModule is not supported");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
io = new ForwardInput(this.plugableModule, props);
|
|
39
|
+
break;
|
|
40
|
+
case IOType.ForwardOutput:
|
|
41
|
+
if (this.plugableModule instanceof MonoModule) {
|
|
42
|
+
throw Error("MonoModule is not supported");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
io = new ForwardOutput(this.plugableModule, props);
|
|
46
|
+
break;
|
|
47
|
+
case IOType.MidiInput:
|
|
48
|
+
io = new MidiInput(this.plugableModule, props);
|
|
49
|
+
break;
|
|
50
|
+
case IOType.MidiOutput:
|
|
51
|
+
io = new MidiOutput(this.plugableModule, props);
|
|
52
|
+
break;
|
|
53
|
+
default:
|
|
54
|
+
throw Error("Unknown IOType");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
this.collection.push(io as unknown as CurrentIO);
|
|
58
|
+
return io as unknown as CurrentIO;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
unPlugAll() {
|
|
62
|
+
this.collection.forEach((io) => io.unPlugAll());
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
find(id: string) {
|
|
66
|
+
return this.collection.find((io) => io.id === id);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
findByName(name: string) {
|
|
70
|
+
return this.collection.find((io) => io.name === name);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
serialize() {
|
|
74
|
+
return this.collection.map((io) => io.serialize());
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import IONode, {
|
|
2
|
+
IOType,
|
|
3
|
+
IIONode,
|
|
4
|
+
plugCompatibleIO,
|
|
5
|
+
unPlugCompatibleIO,
|
|
6
|
+
} from "./Node";
|
|
7
|
+
import Module, { Connectable, PolyModule } from "../Module";
|
|
8
|
+
import { AnyObject } from "../../types";
|
|
9
|
+
import { AnyInput, AnyOuput } from ".";
|
|
10
|
+
|
|
11
|
+
export interface IForwardInput extends IIONode {
|
|
12
|
+
ioType: IOType.ForwardInput;
|
|
13
|
+
}
|
|
14
|
+
export interface IForwardOutput extends IIONode {
|
|
15
|
+
ioType: IOType.ForwardOutput;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class ForwardInput extends IONode implements IForwardInput {
|
|
19
|
+
declare plugableModule: PolyModule<Module<Connectable, AnyObject>, AnyObject>;
|
|
20
|
+
declare ioType: IOType.ForwardInput;
|
|
21
|
+
declare connections: ForwardOutput[];
|
|
22
|
+
|
|
23
|
+
constructor(
|
|
24
|
+
plugableModule: PolyModule<Module<Connectable, AnyObject>, AnyObject>,
|
|
25
|
+
props: IForwardInput
|
|
26
|
+
) {
|
|
27
|
+
super(plugableModule, props);
|
|
28
|
+
this.checkNameValidity();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
get subInputs() {
|
|
32
|
+
return this.plugableModule.audioModules.map((am) => {
|
|
33
|
+
const input = am.inputs.findByName(this.name);
|
|
34
|
+
if (!input) throw Error(`Could not forward input ${this.name}`);
|
|
35
|
+
|
|
36
|
+
return input;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get subModules() {
|
|
41
|
+
return this.plugableModule.audioModules;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
subModule(voiceNo: number) {
|
|
45
|
+
const mod = this.subModules.find((m) => m.voiceNo === voiceNo);
|
|
46
|
+
if (!mod) throw Error(`Submodule with voiceNo ${voiceNo} not found`);
|
|
47
|
+
|
|
48
|
+
return mod;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
subInput(voiceNo: number) {
|
|
52
|
+
const input = this.subModule(voiceNo).inputs.findByName(this.name);
|
|
53
|
+
if (!input) throw Error(`Could not forward input ${this.name}`);
|
|
54
|
+
|
|
55
|
+
return input;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
plug(io: AnyOuput, plugOther: boolean = true) {
|
|
59
|
+
super.plug(io, plugOther);
|
|
60
|
+
if (!plugOther && io instanceof ForwardOutput) return;
|
|
61
|
+
|
|
62
|
+
if (io instanceof ForwardOutput) {
|
|
63
|
+
this.subModules.forEach((am) => {
|
|
64
|
+
const input = am.inputs.findByName(this.name);
|
|
65
|
+
if (!input) throw Error(`Could not forward input ${this.name}`);
|
|
66
|
+
|
|
67
|
+
const output = io.subOutput(am.voiceNo as number);
|
|
68
|
+
plugCompatibleIO(input, output);
|
|
69
|
+
});
|
|
70
|
+
} else {
|
|
71
|
+
this.subInputs.forEach((input) => plugCompatibleIO(input, io));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
unPlug(io: AnyOuput, plugOther: boolean = true) {
|
|
76
|
+
super.unPlug(io, plugOther);
|
|
77
|
+
if (!plugOther && io instanceof ForwardOutput) return;
|
|
78
|
+
|
|
79
|
+
if (io instanceof ForwardOutput) {
|
|
80
|
+
this.subModules.forEach((am) => {
|
|
81
|
+
const input = am.inputs.findByName(this.name);
|
|
82
|
+
if (!input) throw Error(`Could not forward input ${this.name}`);
|
|
83
|
+
|
|
84
|
+
const output = io.subOutput(am.voiceNo as number);
|
|
85
|
+
unPlugCompatibleIO(input, output);
|
|
86
|
+
});
|
|
87
|
+
} else {
|
|
88
|
+
this.subInputs.forEach((input) => unPlugCompatibleIO(input, io));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
unPlugAll() {
|
|
93
|
+
IONode.unPlugAll(this);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private checkNameValidity() {
|
|
97
|
+
const input = this.plugableModule.audioModules[0].inputs.findByName(
|
|
98
|
+
this.name
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
if (!input) throw Error("You should forward to existing input");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export class ForwardOutput extends IONode implements IForwardOutput {
|
|
106
|
+
declare plugableModule: PolyModule<Module<Connectable, AnyObject>, AnyObject>;
|
|
107
|
+
declare ioType: IOType.ForwardOutput;
|
|
108
|
+
declare connections: ForwardInput[];
|
|
109
|
+
|
|
110
|
+
constructor(
|
|
111
|
+
plugableModule: PolyModule<Module<Connectable, AnyObject>, AnyObject>,
|
|
112
|
+
props: IForwardOutput
|
|
113
|
+
) {
|
|
114
|
+
super(plugableModule, props);
|
|
115
|
+
this.checkNameValidity();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
get subOutputs() {
|
|
119
|
+
return this.subModules.map((am) => {
|
|
120
|
+
const output = am.outputs.findByName(this.name);
|
|
121
|
+
if (!output) throw Error(`Could not forward input ${this.name}`);
|
|
122
|
+
|
|
123
|
+
return output;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
get subModules() {
|
|
128
|
+
return this.plugableModule.audioModules;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
subModule(voiceNo: number) {
|
|
132
|
+
const mod = this.subModules.find((m) => m.voiceNo === voiceNo);
|
|
133
|
+
if (!mod) throw Error(`Submodule with voiceNo ${voiceNo} not found`);
|
|
134
|
+
|
|
135
|
+
return mod;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
subOutput(voiceNo: number) {
|
|
139
|
+
const output = this.subModule(voiceNo).outputs.findByName(this.name);
|
|
140
|
+
if (!output) throw Error(`Could not forward input ${this.name}`);
|
|
141
|
+
|
|
142
|
+
return output;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
plug(io: AnyInput, plugOther: boolean = true) {
|
|
146
|
+
super.plug(io, plugOther);
|
|
147
|
+
if (!plugOther && io instanceof ForwardInput) return;
|
|
148
|
+
|
|
149
|
+
if (io instanceof ForwardInput) {
|
|
150
|
+
this.subModules.forEach((am) => {
|
|
151
|
+
const output = am.outputs.findByName(this.name);
|
|
152
|
+
if (!output) throw Error(`Could not forward output ${this.name}`);
|
|
153
|
+
|
|
154
|
+
const input = io.subInput(am.voiceNo as number);
|
|
155
|
+
|
|
156
|
+
plugCompatibleIO(input, output);
|
|
157
|
+
});
|
|
158
|
+
} else {
|
|
159
|
+
this.subOutputs.forEach((output) => plugCompatibleIO(io, output));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
unPlug(io: AnyInput, plugOther: boolean = true) {
|
|
164
|
+
super.unPlug(io, plugOther);
|
|
165
|
+
if (!plugOther && io instanceof ForwardInput) return;
|
|
166
|
+
|
|
167
|
+
if (io instanceof ForwardInput) {
|
|
168
|
+
this.subModules.forEach((am) => {
|
|
169
|
+
const output = am.outputs.findByName(this.name);
|
|
170
|
+
if (!output) throw Error(`Could not forward output ${this.name}`);
|
|
171
|
+
|
|
172
|
+
const input = io.subInput(am.voiceNo as number);
|
|
173
|
+
|
|
174
|
+
unPlugCompatibleIO(input, output);
|
|
175
|
+
});
|
|
176
|
+
} else {
|
|
177
|
+
this.subOutputs.forEach((output) => unPlugCompatibleIO(io, output));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
unPlugAll() {
|
|
182
|
+
IONode.unPlugAll(this);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private checkNameValidity() {
|
|
186
|
+
const output = this.plugableModule.audioModules[0].outputs.findByName(
|
|
187
|
+
this.name
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
if (!output) throw Error("You should forward to existing output");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { AudioModule } from "../Module";
|
|
2
|
+
import { MidiEvent } from "../midi";
|
|
3
|
+
import { ForwardInput, ForwardOutput } from "./ForwardNode";
|
|
4
|
+
import IONode, { IOType, IIONode } from "./Node";
|
|
5
|
+
|
|
6
|
+
export interface IMidiInput extends IIONode {
|
|
7
|
+
ioType: IOType.MidiInput;
|
|
8
|
+
onMidiEvent: (event: MidiEvent) => void;
|
|
9
|
+
}
|
|
10
|
+
export interface IMidiOutput extends IIONode {
|
|
11
|
+
ioType: IOType.MidiOutput;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class MidiInput extends IONode implements IMidiInput {
|
|
15
|
+
declare ioType: IOType.MidiInput;
|
|
16
|
+
declare connections: MidiOutput[];
|
|
17
|
+
onMidiEvent: (event: MidiEvent) => void;
|
|
18
|
+
|
|
19
|
+
constructor(plugableModule: AudioModule, props: IMidiInput) {
|
|
20
|
+
super(plugableModule, props);
|
|
21
|
+
|
|
22
|
+
this.onMidiEvent = props.onMidiEvent;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
plug(io: MidiOutput | ForwardOutput, plugOther: boolean = true) {
|
|
26
|
+
super.plug(io, plugOther);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
unPlug(io: MidiOutput | ForwardOutput, plugOther: boolean = true) {
|
|
30
|
+
super.unPlug(io, plugOther);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
unPlugAll() {
|
|
34
|
+
IONode.unPlugAll(this);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class MidiOutput extends IONode implements IMidiOutput {
|
|
39
|
+
declare ioType: IOType.MidiOutput;
|
|
40
|
+
declare connections: MidiInput[];
|
|
41
|
+
|
|
42
|
+
constructor(plugableModule: AudioModule, props: IIONode) {
|
|
43
|
+
super(plugableModule, props);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
plug(io: MidiInput | ForwardInput, plugOther: boolean = true) {
|
|
47
|
+
super.plug(io, plugOther);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
unPlug(io: MidiInput | ForwardOutput, plugOther: boolean = true) {
|
|
51
|
+
super.unPlug(io, plugOther);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
unPlugAll() {
|
|
55
|
+
IONode.unPlugAll(this);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
onMidiEvent = (event: MidiEvent) => {
|
|
59
|
+
this.midiConnections.forEach((input) => {
|
|
60
|
+
input.onMidiEvent(event);
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
private get midiConnections() {
|
|
65
|
+
return this.connections.filter((input) => input instanceof MidiInput);
|
|
66
|
+
}
|
|
67
|
+
}
|