@blibliki/engine 0.1.1 → 0.1.3
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/build/Engine.d.ts +7 -1
- package/build/Engine.js +25 -4
- package/build/Engine.js.map +1 -1
- package/build/MidiDevice.d.ts +1 -1
- package/build/MidiDevice.js +3 -3
- package/build/MidiDevice.js.map +1 -1
- package/build/MidiDeviceManager.d.ts +11 -10
- package/build/MidiDeviceManager.js +47 -33
- package/build/MidiDeviceManager.js.map +1 -1
- package/build/MidiEvent.d.ts +4 -3
- package/build/MidiEvent.js +12 -6
- package/build/MidiEvent.js.map +1 -1
- package/build/Module/Base.d.ts +1 -0
- package/build/Module/Base.js +1 -0
- package/build/Module/Base.js.map +1 -1
- package/build/Module/MidiSelector.d.ts +2 -4
- package/build/Module/MidiSelector.js +13 -14
- package/build/Module/MidiSelector.js.map +1 -1
- package/build/Module/VirtualMidi.d.ts +26 -0
- package/build/Module/VirtualMidi.js +58 -0
- package/build/Module/VirtualMidi.js.map +1 -0
- package/build/Module/index.d.ts +2 -1
- package/build/Module/index.js +3 -0
- package/build/Module/index.js.map +1 -1
- package/package.json +1 -1
- package/src/Engine.ts +29 -6
- package/src/MidiDevice.ts +3 -3
- package/src/MidiDeviceManager.ts +48 -39
- package/src/MidiEvent.ts +17 -7
- package/src/Module/Base.ts +1 -0
- package/src/Module/MidiSelector.ts +13 -15
- package/src/Module/VirtualMidi.ts +80 -0
- package/src/Module/index.ts +3 -0
package/build/Engine.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import MidiDeviceManager from "./MidiDeviceManager";
|
|
1
2
|
import { ModuleType } from "./Module";
|
|
2
3
|
import { AudioModule } from "./Module";
|
|
3
4
|
import { RouteInterface, RouteProps } from "./routes";
|
|
@@ -10,9 +11,11 @@ interface InitializeInterface {
|
|
|
10
11
|
context?: Partial<ContextInterface>;
|
|
11
12
|
}
|
|
12
13
|
declare class Engine {
|
|
14
|
+
midiDeviceManager: MidiDeviceManager;
|
|
13
15
|
private static instance;
|
|
14
16
|
private _master;
|
|
15
17
|
private context;
|
|
18
|
+
private propsUpdateCallbacks;
|
|
16
19
|
modules: {
|
|
17
20
|
[Identifier: string]: AudioModule;
|
|
18
21
|
};
|
|
@@ -68,6 +71,8 @@ declare class Engine {
|
|
|
68
71
|
name: string;
|
|
69
72
|
props: any;
|
|
70
73
|
};
|
|
74
|
+
onPropsUpdate(callback: (id: string, props: any) => void): void;
|
|
75
|
+
_triggerPropsUpdate(id: string, props: any): void;
|
|
71
76
|
updatePropsModule(id: string, props: any): {
|
|
72
77
|
id: string;
|
|
73
78
|
name: string;
|
|
@@ -106,9 +111,10 @@ declare class Engine {
|
|
|
106
111
|
name: string;
|
|
107
112
|
props: any;
|
|
108
113
|
};
|
|
109
|
-
|
|
114
|
+
triggerVirtualMidi(id: string, noteName: string, type: string): void;
|
|
110
115
|
dispose(): void;
|
|
111
116
|
findById(id: string): AudioModule;
|
|
117
|
+
private applyRoutesRequired;
|
|
112
118
|
}
|
|
113
119
|
declare const _default: Engine;
|
|
114
120
|
export default _default;
|
package/build/Engine.js
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { Context, setContext } from "tone";
|
|
2
|
+
import MidiDeviceManager from "./MidiDeviceManager";
|
|
3
|
+
import MidiEvent from "./MidiEvent";
|
|
2
4
|
import { ModuleType } from "./Module";
|
|
3
5
|
import { createModule } from "./Module";
|
|
4
6
|
import VoiceScheduler from "./Module/VoiceScheduler";
|
|
5
7
|
import { applyRoutes, createRoute } from "./routes";
|
|
6
8
|
class Engine {
|
|
9
|
+
midiDeviceManager;
|
|
7
10
|
static instance;
|
|
8
11
|
_master;
|
|
9
12
|
context;
|
|
13
|
+
propsUpdateCallbacks;
|
|
10
14
|
modules;
|
|
11
15
|
routes;
|
|
12
16
|
constructor() {
|
|
13
17
|
this.modules = {};
|
|
14
18
|
this.routes = {};
|
|
19
|
+
this.propsUpdateCallbacks = [];
|
|
15
20
|
}
|
|
16
21
|
static getInstance() {
|
|
17
22
|
if (!Engine.instance) {
|
|
@@ -23,6 +28,7 @@ class Engine {
|
|
|
23
28
|
this.context = new Context(props.context);
|
|
24
29
|
setContext(this.context);
|
|
25
30
|
this.context.transport.start();
|
|
31
|
+
this.midiDeviceManager = new MidiDeviceManager();
|
|
26
32
|
return {
|
|
27
33
|
master: this.master,
|
|
28
34
|
};
|
|
@@ -38,12 +44,17 @@ class Engine {
|
|
|
38
44
|
audioModule.name = name;
|
|
39
45
|
return audioModule.serialize();
|
|
40
46
|
}
|
|
47
|
+
onPropsUpdate(callback) {
|
|
48
|
+
this.propsUpdateCallbacks.push(callback);
|
|
49
|
+
}
|
|
50
|
+
_triggerPropsUpdate(id, props) {
|
|
51
|
+
this.propsUpdateCallbacks.forEach((callback) => callback(id, props));
|
|
52
|
+
}
|
|
41
53
|
updatePropsModule(id, props) {
|
|
42
54
|
const audioModule = this.findById(id);
|
|
43
|
-
const
|
|
55
|
+
const applyRoutesRequired = this.applyRoutesRequired(audioModule, props);
|
|
44
56
|
audioModule.props = props;
|
|
45
|
-
|
|
46
|
-
if (polyNumber !== newPolyNumber)
|
|
57
|
+
if (applyRoutesRequired)
|
|
47
58
|
applyRoutes(Object.values(this.routes));
|
|
48
59
|
return audioModule.serialize();
|
|
49
60
|
}
|
|
@@ -65,7 +76,10 @@ class Engine {
|
|
|
65
76
|
this._master = this.modules[masterProps.id];
|
|
66
77
|
return masterProps;
|
|
67
78
|
}
|
|
68
|
-
|
|
79
|
+
triggerVirtualMidi(id, noteName, type) {
|
|
80
|
+
const virtualMidi = this.findById(id);
|
|
81
|
+
virtualMidi.sendMidi(MidiEvent.fromNote(noteName, type));
|
|
82
|
+
}
|
|
69
83
|
dispose() {
|
|
70
84
|
Object.values(this.modules).forEach((m) => {
|
|
71
85
|
if (m.type === "master")
|
|
@@ -81,6 +95,13 @@ class Engine {
|
|
|
81
95
|
throw Error(`Audio module with id ${id} not exists`);
|
|
82
96
|
return audioModule;
|
|
83
97
|
}
|
|
98
|
+
applyRoutesRequired(audioModule, props) {
|
|
99
|
+
if (!props.polyNumber)
|
|
100
|
+
return false;
|
|
101
|
+
if (!(audioModule instanceof VoiceScheduler))
|
|
102
|
+
return false;
|
|
103
|
+
return props.polyNumber !== audioModule.polyNumber;
|
|
104
|
+
}
|
|
84
105
|
}
|
|
85
106
|
export default Engine.getInstance();
|
|
86
107
|
//# sourceMappingURL=Engine.js.map
|
package/build/Engine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Engine.js","sourceRoot":"","sources":["../src/Engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"Engine.js","sourceRoot":"","sources":["../src/Engine.ts"],"names":[],"mappings":"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"}
|
package/build/MidiDevice.d.ts
CHANGED
package/build/MidiDevice.js
CHANGED
|
@@ -17,7 +17,7 @@ export default class MidiDevice {
|
|
|
17
17
|
const isMidiEvent = e instanceof MIDIMessageEvent;
|
|
18
18
|
if (!isMidiEvent)
|
|
19
19
|
return;
|
|
20
|
-
this.
|
|
20
|
+
this.processEvent(e);
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
disconnect() {
|
|
@@ -31,9 +31,9 @@ export default class MidiDevice {
|
|
|
31
31
|
this.eventListerCallbacks.push(callback);
|
|
32
32
|
}
|
|
33
33
|
removeEventListener(callback) {
|
|
34
|
-
this.eventListerCallbacks = this.eventListerCallbacks.filter((c) => c
|
|
34
|
+
this.eventListerCallbacks = this.eventListerCallbacks.filter((c) => c !== callback);
|
|
35
35
|
}
|
|
36
|
-
|
|
36
|
+
processEvent(e) {
|
|
37
37
|
const event = new MidiEvent(e);
|
|
38
38
|
switch (event.type) {
|
|
39
39
|
case "noteOn":
|
package/build/MidiDevice.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MidiDevice.js","sourceRoot":"","sources":["../src/MidiDevice.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,aAAa,CAAC;AAUpC,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B,EAAE,CAAS;IACX,IAAI,CAAS;IACb,KAAK,CAAS;IACd,oBAAoB,GAA0B,EAAE,CAAC;IAEzC,KAAK,CAAY;IAEzB,YAAY,IAAe;QACzB,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,UAAU,IAAI,CAAC,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAElB,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,OAAO;QACL,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC,CAAC,EAAE,EAAE;YAC/B,MAAM,WAAW,GAAG,CAAC,YAAY,gBAAgB,CAAC;YAElD,IAAI,CAAC,WAAW;gBAAE,OAAO;YAEzB,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"MidiDevice.js","sourceRoot":"","sources":["../src/MidiDevice.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,aAAa,CAAC;AAUpC,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B,EAAE,CAAS;IACX,IAAI,CAAS;IACb,KAAK,CAAS;IACd,oBAAoB,GAA0B,EAAE,CAAC;IAEzC,KAAK,CAAY;IAEzB,YAAY,IAAe;QACzB,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,UAAU,IAAI,CAAC,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAElB,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,OAAO;QACL,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC,CAAC,EAAE,EAAE;YAC/B,MAAM,WAAW,GAAG,CAAC,YAAY,gBAAgB,CAAC;YAElD,IAAI,CAAC,WAAW;gBAAE,OAAO;YAEzB,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC,CAAC;IACJ,CAAC;IAED,UAAU;QACR,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;IAClC,CAAC;IAED,SAAS;QACP,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;QAEjC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED,gBAAgB,CAAC,QAA6B;QAC5C,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED,mBAAmB,CAAC,QAA6B;QAC/C,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAC1D,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CACtB,CAAC;IACJ,CAAC;IAEO,YAAY,CAAC,CAAmB;QACtC,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC;QAE/B,QAAQ,KAAK,CAAC,IAAI,EAAE;YAClB,KAAK,QAAQ,CAAC;YACd,KAAK,SAAS;gBACZ,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;SACpE;IACH,CAAC;CACF"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import MidiDevice from "./MidiDevice";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
onStateChange(callback:
|
|
2
|
+
export default class MidiDeviceManager {
|
|
3
|
+
devices: {
|
|
4
|
+
[Key: string]: MidiDevice;
|
|
5
|
+
};
|
|
6
|
+
private initialized;
|
|
7
|
+
constructor();
|
|
8
|
+
find(id: string): MidiDevice | null;
|
|
9
|
+
onStateChange(callback: (device: MidiDevice) => void): void;
|
|
10
|
+
private listenChanges;
|
|
11
|
+
private initializeDevices;
|
|
12
|
+
private inputs;
|
|
10
13
|
}
|
|
11
|
-
declare const _default: MidiDeviceManager;
|
|
12
|
-
export default _default;
|
|
@@ -1,45 +1,59 @@
|
|
|
1
1
|
import MidiDevice from "./MidiDevice";
|
|
2
|
-
class MidiDeviceManager {
|
|
3
|
-
devices;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
export default class MidiDeviceManager {
|
|
3
|
+
devices = {};
|
|
4
|
+
initialized = false;
|
|
5
|
+
constructor() {
|
|
6
|
+
this.initializeDevices().then(() => {
|
|
7
|
+
this.listenChanges();
|
|
8
|
+
this.initialized = true;
|
|
9
|
+
});
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return this.devices;
|
|
14
|
-
this.devices = (await this._inputs()).map((input) => new MidiDevice(input));
|
|
15
|
-
return this.devices;
|
|
16
|
-
}
|
|
17
|
-
async find(id) {
|
|
18
|
-
const device = (await this.fetchDevices()).find((dev) => dev.id === id);
|
|
11
|
+
find(id) {
|
|
12
|
+
const device = this.devices[id];
|
|
19
13
|
if (!device)
|
|
20
|
-
|
|
14
|
+
return null;
|
|
21
15
|
return device;
|
|
22
16
|
}
|
|
23
|
-
|
|
17
|
+
onStateChange(callback) {
|
|
18
|
+
navigator.requestMIDIAccess().then((access) => {
|
|
19
|
+
access.onstatechange = (e) => {
|
|
20
|
+
const isMidiEvent = e instanceof MIDIConnectionEvent;
|
|
21
|
+
if (!isMidiEvent)
|
|
22
|
+
return;
|
|
23
|
+
if (e.port instanceof MIDIOutput)
|
|
24
|
+
return;
|
|
25
|
+
const input = e.port;
|
|
26
|
+
const midi = new MidiDevice(input);
|
|
27
|
+
callback(midi);
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
listenChanges() {
|
|
32
|
+
this.onStateChange((device) => {
|
|
33
|
+
if (device.state === "disconnected") {
|
|
34
|
+
device.disconnect();
|
|
35
|
+
delete this.devices[device.id];
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
this.devices[device.id] = device;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async initializeDevices() {
|
|
43
|
+
if (this.initialized)
|
|
44
|
+
return Object.values(this.devices);
|
|
45
|
+
(await this.inputs()).forEach((input) => {
|
|
46
|
+
if (this.devices[input.id])
|
|
47
|
+
return;
|
|
48
|
+
this.devices[input.id] = new MidiDevice(input);
|
|
49
|
+
});
|
|
50
|
+
return Object.values(this.devices);
|
|
51
|
+
}
|
|
52
|
+
async inputs() {
|
|
24
53
|
const inputs = [];
|
|
25
54
|
const access = await navigator.requestMIDIAccess();
|
|
26
55
|
access.inputs.forEach((input) => inputs.push(input));
|
|
27
56
|
return inputs;
|
|
28
57
|
}
|
|
29
|
-
async onStateChange(callback) {
|
|
30
|
-
const access = await navigator.requestMIDIAccess();
|
|
31
|
-
await this.fetchDevices();
|
|
32
|
-
access.onstatechange = (e) => {
|
|
33
|
-
const isMidiEvent = e instanceof MIDIConnectionEvent;
|
|
34
|
-
if (!isMidiEvent)
|
|
35
|
-
return;
|
|
36
|
-
if (e.port instanceof MIDIOutput)
|
|
37
|
-
return;
|
|
38
|
-
const input = e.port;
|
|
39
|
-
const midi = new MidiDevice(input);
|
|
40
|
-
callback(midi);
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
58
|
}
|
|
44
|
-
export default MidiDeviceManager.getInstance();
|
|
45
59
|
//# sourceMappingURL=MidiDeviceManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MidiDeviceManager.js","sourceRoot":"","sources":["../src/MidiDeviceManager.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,cAAc,CAAC;AAEtC,MAAM,iBAAiB;
|
|
1
|
+
{"version":3,"file":"MidiDeviceManager.js","sourceRoot":"","sources":["../src/MidiDeviceManager.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,cAAc,CAAC;AAEtC,MAAM,CAAC,OAAO,OAAO,iBAAiB;IACpC,OAAO,GAAkC,EAAE,CAAC;IACpC,WAAW,GAAY,KAAK,CAAC;IAErC;QACE,IAAI,CAAC,iBAAiB,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;YACjC,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,EAAU;QACb,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAEhC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAEzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,aAAa,CAAC,QAAsC;QAClD,SAAS,CAAC,iBAAiB,EAAE,CAAC,IAAI,CAAC,CAAC,MAAkB,EAAE,EAAE;YACxD,MAAM,CAAC,aAAa,GAAG,CAAC,CAAC,EAAE,EAAE;gBAC3B,MAAM,WAAW,GAAG,CAAC,YAAY,mBAAmB,CAAC;gBAErD,IAAI,CAAC,WAAW;oBAAE,OAAO;gBACzB,IAAI,CAAC,CAAC,IAAI,YAAY,UAAU;oBAAE,OAAO;gBAEzC,MAAM,KAAK,GAAG,CAAC,CAAC,IAAiB,CAAC;gBAElC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;gBAEnC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACjB,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,aAAa;QACnB,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,EAAE,EAAE;YAC5B,IAAI,MAAM,CAAC,KAAK,KAAK,cAAc,EAAE;gBACnC,MAAM,CAAC,UAAU,EAAE,CAAC;gBACpB,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;aAChC;iBAAM;gBACL,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC;aAClC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,iBAAiB;QAC7B,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEzD,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;YACtC,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBAAE,OAAO;YAEnC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAEO,KAAK,CAAC,MAAM;QAClB,MAAM,MAAM,GAAqB,EAAE,CAAC;QAEpC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,iBAAiB,EAAE,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAErD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
|
package/build/MidiEvent.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import Note from "./Note";
|
|
2
2
|
export default class MidiEvent {
|
|
3
3
|
note?: Note;
|
|
4
|
-
triggeredAt: number;
|
|
4
|
+
readonly triggeredAt: number;
|
|
5
|
+
_type: string;
|
|
5
6
|
private data;
|
|
6
|
-
private
|
|
7
|
-
|
|
7
|
+
private event;
|
|
8
|
+
static fromNote(noteName: string, type: string): MidiEvent;
|
|
8
9
|
constructor(event: MIDIMessageEvent);
|
|
9
10
|
get type(): string;
|
|
10
11
|
get isNote(): boolean;
|
package/build/MidiEvent.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { now } from "tone";
|
|
2
2
|
import Note from "./Note";
|
|
3
|
-
const
|
|
3
|
+
const EventType = {
|
|
4
4
|
8: "noteOff",
|
|
5
5
|
9: "noteOn",
|
|
6
6
|
};
|
|
7
7
|
export default class MidiEvent {
|
|
8
8
|
note;
|
|
9
9
|
triggeredAt;
|
|
10
|
-
data;
|
|
11
10
|
_type;
|
|
12
|
-
|
|
11
|
+
data;
|
|
12
|
+
event;
|
|
13
|
+
static fromNote(noteName, type) {
|
|
14
|
+
const event = new MidiEvent(new MIDIMessageEvent("", { data: new Uint8Array([0, 0, 0]) }));
|
|
15
|
+
event.note = new Note(noteName);
|
|
16
|
+
event._type = type;
|
|
17
|
+
return event;
|
|
18
|
+
}
|
|
13
19
|
constructor(event) {
|
|
14
|
-
this.
|
|
20
|
+
this.event = event;
|
|
15
21
|
this.triggeredAt = now();
|
|
16
22
|
this.data = event.data;
|
|
17
23
|
this.defineNote();
|
|
@@ -19,7 +25,7 @@ export default class MidiEvent {
|
|
|
19
25
|
get type() {
|
|
20
26
|
if (this._type)
|
|
21
27
|
return this._type;
|
|
22
|
-
let type =
|
|
28
|
+
let type = EventType[this.data[0] >> 4];
|
|
23
29
|
if (type === "noteOn" && this.data[2] === 0) {
|
|
24
30
|
type = "noteOff";
|
|
25
31
|
}
|
|
@@ -31,7 +37,7 @@ export default class MidiEvent {
|
|
|
31
37
|
defineNote() {
|
|
32
38
|
if (!this.isNote)
|
|
33
39
|
return;
|
|
34
|
-
this.note = new Note(this.
|
|
40
|
+
this.note = new Note(this.event);
|
|
35
41
|
}
|
|
36
42
|
}
|
|
37
43
|
//# sourceMappingURL=MidiEvent.js.map
|
package/build/MidiEvent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MidiEvent.js","sourceRoot":"","sources":["../src/MidiEvent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAC3B,OAAO,IAAI,MAAM,QAAQ,CAAC;AAE1B,MAAM,
|
|
1
|
+
{"version":3,"file":"MidiEvent.js","sourceRoot":"","sources":["../src/MidiEvent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAC3B,OAAO,IAAI,MAAM,QAAQ,CAAC;AAE1B,MAAM,SAAS,GAA8B;IAC3C,CAAC,EAAE,SAAS;IACZ,CAAC,EAAE,QAAQ;CACZ,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,SAAS;IAC5B,IAAI,CAAQ;IACH,WAAW,CAAS;IAC7B,KAAK,CAAS;IACN,IAAI,CAAa;IACjB,KAAK,CAAmB;IAEhC,MAAM,CAAC,QAAQ,CAAC,QAAgB,EAAE,IAAY;QAC5C,MAAM,KAAK,GAAG,IAAI,SAAS,CACzB,IAAI,gBAAgB,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC9D,CAAC;QACF,KAAK,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;QAEnB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,YAAY,KAAuB;QACjC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,WAAW,GAAG,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACvB,IAAI,CAAC,UAAU,EAAE,CAAC;IACpB,CAAC;IAED,IAAI,IAAI;QACN,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC;QAElC,IAAI,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAExC,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE;YAC3C,IAAI,GAAG,SAAS,CAAC;SAClB;QAED,OAAO,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC;IAC3D,CAAC;IAED,UAAU;QACR,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QAEzB,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;CACF"}
|
package/build/Module/Base.d.ts
CHANGED
package/build/Module/Base.js
CHANGED
|
@@ -11,6 +11,7 @@ export var ModuleType;
|
|
|
11
11
|
ModuleType["Master"] = "master";
|
|
12
12
|
ModuleType["Voice"] = "voice";
|
|
13
13
|
ModuleType["MidiSelector"] = "midiSelector";
|
|
14
|
+
ModuleType["VirtualMidi"] = "virtualMidi";
|
|
14
15
|
ModuleType["Volume"] = "monoVolume";
|
|
15
16
|
})(ModuleType || (ModuleType = {}));
|
|
16
17
|
export class DummnyInternalModule {
|
package/build/Module/Base.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Base.js","sourceRoot":"","sources":["../../src/Module/Base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AAGpC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAe,MAAM,MAAM,CAAC;AAElD,OAAO,EAAe,UAAU,EAAE,MAAM,WAAW,CAAC;AAEpD,MAAM,CAAN,IAAY,
|
|
1
|
+
{"version":3,"file":"Base.js","sourceRoot":"","sources":["../../src/Module/Base.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import MidiDevice from "../MidiDevice";
|
|
2
|
-
import MidiEvent from "../MidiEvent";
|
|
3
1
|
import Module, { DummnyInternalModule } from "./Base";
|
|
4
2
|
import { Output } from "./IO";
|
|
5
3
|
export interface MidiSelectorInterface {
|
|
@@ -10,7 +8,7 @@ export default class MidiSelector extends Module<DummnyInternalModule, MidiSelec
|
|
|
10
8
|
constructor(name: string, props: Partial<MidiSelectorInterface>);
|
|
11
9
|
get selectedId(): string | null;
|
|
12
10
|
set selectedId(value: string | null);
|
|
13
|
-
onMidiEvent: (midiEvent: MidiEvent) => void;
|
|
14
|
-
availableDevices(): Promise<MidiDevice[]>;
|
|
15
11
|
private registerOutputs;
|
|
12
|
+
private onMidiEvent;
|
|
13
|
+
private addEventListener;
|
|
16
14
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Engine from "../Engine";
|
|
2
2
|
import Module, { ModuleType, DummnyInternalModule } from "./Base";
|
|
3
3
|
const InitialProps = {
|
|
4
4
|
selectedId: null,
|
|
@@ -12,33 +12,32 @@ export default class MidiSelector extends Module {
|
|
|
12
12
|
type: ModuleType.MidiSelector,
|
|
13
13
|
});
|
|
14
14
|
this.registerOutputs();
|
|
15
|
+
this.addEventListener(this.selectedId);
|
|
15
16
|
}
|
|
16
17
|
get selectedId() {
|
|
17
18
|
return this._props["selectedId"];
|
|
18
19
|
}
|
|
19
20
|
set selectedId(value) {
|
|
20
21
|
if (this.selectedId) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
});
|
|
22
|
+
const prevMidiDevice = Engine.midiDeviceManager.find(this.selectedId);
|
|
23
|
+
prevMidiDevice?.removeEventListener(this.onMidiEvent);
|
|
24
24
|
}
|
|
25
25
|
this._props = { ...this.props, selectedId: value };
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
});
|
|
26
|
+
this.addEventListener(value);
|
|
27
|
+
}
|
|
28
|
+
registerOutputs() {
|
|
29
|
+
this.midiOutput = this.registerOutput({ name: "midi out" });
|
|
31
30
|
}
|
|
32
31
|
onMidiEvent = (midiEvent) => {
|
|
33
32
|
this.midiOutput.connections.forEach((input) => {
|
|
34
33
|
input.pluggable(midiEvent);
|
|
35
34
|
});
|
|
36
35
|
};
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
this.
|
|
36
|
+
addEventListener(midiId) {
|
|
37
|
+
if (!this.onMidiEvent || !midiId)
|
|
38
|
+
return; // Ugly hack because of weird super bug
|
|
39
|
+
const midiDevice = Engine.midiDeviceManager.find(midiId);
|
|
40
|
+
midiDevice?.addEventListener(this.onMidiEvent);
|
|
42
41
|
}
|
|
43
42
|
}
|
|
44
43
|
//# sourceMappingURL=MidiSelector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MidiSelector.js","sourceRoot":"","sources":["../../src/Module/MidiSelector.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MidiSelector.js","sourceRoot":"","sources":["../../src/Module/MidiSelector.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,WAAW,CAAC;AAE/B,OAAO,MAAM,EAAE,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAOlE,MAAM,YAAY,GAA0B;IAC1C,UAAU,EAAE,IAAI;CACjB,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,MAGzC;IACC,UAAU,CAAS;IAEnB,YAAY,IAAY,EAAE,KAAqC;QAC7D,KAAK,CAAC,IAAI,oBAAoB,EAAE,EAAE;YAChC,IAAI;YACJ,KAAK,EAAE,EAAE,GAAG,YAAY,EAAE,GAAG,KAAK,EAAE;YACpC,IAAI,EAAE,UAAU,CAAC,YAAY;SAC9B,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,UAAU,CAAC,KAAoB;QACjC,IAAI,IAAI,CAAC,UAAU,EAAE;YACnB,MAAM,cAAc,GAAG,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACtE,cAAc,EAAE,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;SACvD;QAED,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QAEnD,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAEO,eAAe;QACrB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAC9D,CAAC;IAEO,WAAW,GAAG,CAAC,SAAoB,EAAE,EAAE;QAC7C,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;YAC5C,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEM,gBAAgB,CAAC,MAAqB;QAC5C,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,uCAAuC;QAEjF,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzD,UAAU,EAAE,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACjD,CAAC;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import MidiEvent from "../MidiEvent";
|
|
2
|
+
import Module, { ModuleType, DummnyInternalModule } from "./Base";
|
|
3
|
+
import { Output } from "./IO";
|
|
4
|
+
export interface VirtualMidiInterface {
|
|
5
|
+
activeNotes: string[];
|
|
6
|
+
}
|
|
7
|
+
export default class VirtualMidi extends Module<DummnyInternalModule, VirtualMidiInterface> {
|
|
8
|
+
midiOutput: Output;
|
|
9
|
+
constructor(name: string, props: VirtualMidiInterface);
|
|
10
|
+
get activeNotes(): string[];
|
|
11
|
+
set activeNotes(value: string[]);
|
|
12
|
+
sendMidi(midiEvent: MidiEvent): void;
|
|
13
|
+
triggerAttack(midiEvent: MidiEvent): void;
|
|
14
|
+
triggerRelease(midiEvent: MidiEvent): void;
|
|
15
|
+
serialize(): {
|
|
16
|
+
activeNotes: string[];
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
type: ModuleType;
|
|
20
|
+
props: VirtualMidiInterface;
|
|
21
|
+
inputs: import("./IO").SerializeInterface[];
|
|
22
|
+
outputs: import("./IO").SerializeInterface[];
|
|
23
|
+
};
|
|
24
|
+
private registerInputs;
|
|
25
|
+
private registerOutputs;
|
|
26
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import Engine from "../Engine";
|
|
2
|
+
import Module, { ModuleType, DummnyInternalModule } from "./Base";
|
|
3
|
+
const InitialProps = {
|
|
4
|
+
activeNotes: [],
|
|
5
|
+
};
|
|
6
|
+
export default class VirtualMidi extends Module {
|
|
7
|
+
midiOutput;
|
|
8
|
+
constructor(name, props) {
|
|
9
|
+
super(new DummnyInternalModule(), {
|
|
10
|
+
name,
|
|
11
|
+
props: { ...InitialProps, ...props },
|
|
12
|
+
type: ModuleType.VirtualMidi,
|
|
13
|
+
});
|
|
14
|
+
this.registerInputs();
|
|
15
|
+
this.registerOutputs();
|
|
16
|
+
}
|
|
17
|
+
get activeNotes() {
|
|
18
|
+
return this._props["activeNotes"];
|
|
19
|
+
}
|
|
20
|
+
// can't set externaly
|
|
21
|
+
set activeNotes(value) {
|
|
22
|
+
this._props = { ...this.props, activeNotes: value };
|
|
23
|
+
}
|
|
24
|
+
sendMidi(midiEvent) {
|
|
25
|
+
this.midiTriggered(midiEvent);
|
|
26
|
+
this.midiOutput.connections.forEach((input) => {
|
|
27
|
+
input.pluggable(midiEvent);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
triggerAttack(midiEvent) {
|
|
31
|
+
if (!midiEvent.note)
|
|
32
|
+
return;
|
|
33
|
+
this.activeNotes = [...this.activeNotes, midiEvent.note.fullName];
|
|
34
|
+
Engine._triggerPropsUpdate(this.id, this.props);
|
|
35
|
+
}
|
|
36
|
+
triggerRelease(midiEvent) {
|
|
37
|
+
if (!midiEvent.note)
|
|
38
|
+
return;
|
|
39
|
+
this.activeNotes = this.activeNotes.filter((name) => name !== midiEvent.note.fullName);
|
|
40
|
+
Engine._triggerPropsUpdate(this.id, this.props);
|
|
41
|
+
}
|
|
42
|
+
serialize() {
|
|
43
|
+
return {
|
|
44
|
+
...super.serialize(),
|
|
45
|
+
activeNotes: this.activeNotes,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
registerInputs() {
|
|
49
|
+
this.registerInput({
|
|
50
|
+
name: "midi in",
|
|
51
|
+
pluggable: this.midiTriggered,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
registerOutputs() {
|
|
55
|
+
this.midiOutput = this.registerOutput({ name: "midi out" });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=VirtualMidi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VirtualMidi.js","sourceRoot":"","sources":["../../src/Module/VirtualMidi.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,WAAW,CAAC;AAE/B,OAAO,MAAM,EAAE,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAOlE,MAAM,YAAY,GAAyB;IACzC,WAAW,EAAE,EAAE;CAChB,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,MAGxC;IACC,UAAU,CAAS;IAEnB,YAAY,IAAY,EAAE,KAA2B;QACnD,KAAK,CAAC,IAAI,oBAAoB,EAAE,EAAE;YAChC,IAAI;YACJ,KAAK,EAAE,EAAE,GAAG,YAAY,EAAE,GAAG,KAAK,EAAE;YACpC,IAAI,EAAE,UAAU,CAAC,WAAW;SAC7B,CAAC,CAAC;QAEH,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACpC,CAAC;IAED,sBAAsB;IACtB,IAAI,WAAW,CAAC,KAAe;QAC7B,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;IACtD,CAAC;IAED,QAAQ,CAAC,SAAoB;QAC3B,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QAC9B,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;YAC5C,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,aAAa,CAAC,SAAoB;QAChC,IAAI,CAAC,SAAS,CAAC,IAAI;YAAE,OAAO;QAE5B,IAAI,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClE,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC;IAED,cAAc,CAAC,SAAoB;QACjC,IAAI,CAAC,SAAS,CAAC,IAAI;YAAE,OAAO;QAE5B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CACxC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC,IAAK,CAAC,QAAQ,CAC5C,CAAC;QACF,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC;IAED,SAAS;QACP,OAAO;YACL,GAAG,KAAK,CAAC,SAAS,EAAE;YACpB,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC;IACJ,CAAC;IAEO,cAAc;QACpB,IAAI,CAAC,aAAa,CAAC;YACjB,IAAI,EAAE,SAAS;YACf,SAAS,EAAE,IAAI,CAAC,aAAa;SAC9B,CAAC,CAAC;IACL,CAAC;IAEO,eAAe;QACrB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAC9D,CAAC;CACF"}
|
package/build/Module/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import MidiSelector from "./MidiSelector";
|
|
|
9
9
|
import { PolyAmpEnvelope } from "./Envelope/AmpEnvelope";
|
|
10
10
|
import { PolyEnvelope } from "./Envelope/Base";
|
|
11
11
|
import Volume, { PolyVolume } from "./Volume";
|
|
12
|
+
import VirtualMidi from "./VirtualMidi";
|
|
12
13
|
export { default, ModuleType } from "./Base";
|
|
13
14
|
export { default as PolyModule, PolyModuleType } from "./PolyModule";
|
|
14
15
|
export type { ModuleInterface, Connectable, Triggerable } from "./Base";
|
|
@@ -17,4 +18,4 @@ export { default as Oscillator } from "./Oscillator";
|
|
|
17
18
|
export { Envelope, AmpEnvelope, FreqEnvelope, EnvelopeStages, } from "./Envelope";
|
|
18
19
|
export declare type AudioModule = Module<Connectable, any> | PolyModule<Module<Connectable, any>, any>;
|
|
19
20
|
export declare function createModule(name: string, type: string, props: any): AudioModule;
|
|
20
|
-
export declare function moduleClassFromType(type: string): typeof Oscillator | typeof PolyOscillator | typeof Envelope | typeof PolyEnvelope | typeof AmpEnvelope | typeof PolyAmpEnvelope | typeof Filter | typeof PolyFilter | typeof Master | typeof VoiceScheduler | typeof Voice | typeof MidiSelector | typeof Volume | typeof PolyVolume;
|
|
21
|
+
export declare function moduleClassFromType(type: string): typeof Oscillator | typeof PolyOscillator | typeof Envelope | typeof PolyEnvelope | typeof AmpEnvelope | typeof PolyAmpEnvelope | typeof Filter | typeof PolyFilter | typeof Master | typeof VoiceScheduler | typeof Voice | typeof MidiSelector | typeof Volume | typeof PolyVolume | typeof VirtualMidi;
|
package/build/Module/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import { PolyAmpEnvelope } from "./Envelope/AmpEnvelope";
|
|
|
10
10
|
import { PolyFreqEnvelope } from "./Envelope/FreqEnvelope";
|
|
11
11
|
import { PolyEnvelope } from "./Envelope/Base";
|
|
12
12
|
import Volume, { PolyVolume } from "./Volume";
|
|
13
|
+
import VirtualMidi from "./VirtualMidi";
|
|
13
14
|
export { default, ModuleType } from "./Base";
|
|
14
15
|
export { default as PolyModule, PolyModuleType } from "./PolyModule";
|
|
15
16
|
export { default as Filter } from "./Filter";
|
|
@@ -53,6 +54,8 @@ export function moduleClassFromType(type) {
|
|
|
53
54
|
return VoiceScheduler;
|
|
54
55
|
case ModuleType.MidiSelector:
|
|
55
56
|
return MidiSelector;
|
|
57
|
+
case ModuleType.VirtualMidi:
|
|
58
|
+
return VirtualMidi;
|
|
56
59
|
default:
|
|
57
60
|
throw Error("Unknown module type");
|
|
58
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/Module/index.ts"],"names":[],"mappings":"AAAA,OAAe,EAAe,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,UAAU,EAAE,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,MAAM,MAAM,UAAU,CAAC;AAC9B,OAAO,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/Module/index.ts"],"names":[],"mappings":"AAAA,OAAe,EAAe,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,UAAU,EAAE,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,MAAM,MAAM,UAAU,CAAC;AAC9B,OAAO,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,WAAW,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGrE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,cAAc,GACf,MAAM,YAAY,CAAC;AAMpB,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,IAAY,EACZ,KAAU;IAEV,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAExC,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,QAAQ,IAAI,EAAE;QACZ,KAAK,UAAU,CAAC,UAAU;YACxB,OAAO,UAAU,CAAC;QACpB,KAAK,UAAU,CAAC,QAAQ;YACtB,OAAO,QAAQ,CAAC;QAClB,KAAK,UAAU,CAAC,WAAW;YACzB,OAAO,WAAW,CAAC;QACrB,KAAK,UAAU,CAAC,YAAY;YAC1B,OAAO,YAAY,CAAC;QACtB,KAAK,UAAU,CAAC,MAAM;YACpB,OAAO,MAAM,CAAC;QAChB,KAAK,UAAU,CAAC,MAAM;YACpB,OAAO,MAAM,CAAC;QAChB,KAAK,cAAc,CAAC,UAAU;YAC5B,OAAO,cAAc,CAAC;QACxB,KAAK,cAAc,CAAC,QAAQ;YAC1B,OAAO,YAAY,CAAC;QACtB,KAAK,cAAc,CAAC,WAAW;YAC7B,OAAO,eAAe,CAAC;QACzB,KAAK,cAAc,CAAC,YAAY;YAC9B,OAAO,gBAAgB,CAAC;QAC1B,KAAK,cAAc,CAAC,MAAM;YACxB,OAAO,UAAU,CAAC;QACpB,KAAK,cAAc,CAAC,MAAM;YACxB,OAAO,UAAU,CAAC;QACpB,KAAK,UAAU,CAAC,MAAM;YACpB,OAAO,MAAM,CAAC;QAChB,KAAK,UAAU,CAAC,KAAK;YACnB,OAAO,KAAK,CAAC;QACf,KAAK,cAAc,CAAC,cAAc;YAChC,OAAO,cAAc,CAAC;QACxB,KAAK,UAAU,CAAC,YAAY;YAC1B,OAAO,YAAY,CAAC;QACtB,KAAK,UAAU,CAAC,WAAW;YACzB,OAAO,WAAW,CAAC;QACrB;YACE,MAAM,KAAK,CAAC,qBAAqB,CAAC,CAAC;KACtC;AACH,CAAC"}
|
package/package.json
CHANGED
package/src/Engine.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { Context, setContext } from "tone";
|
|
2
|
+
import MidiDeviceManager from "./MidiDeviceManager";
|
|
3
|
+
import MidiEvent from "./MidiEvent";
|
|
2
4
|
|
|
3
5
|
import { ModuleType } from "./Module";
|
|
4
6
|
import { AudioModule, createModule } from "./Module";
|
|
5
7
|
import Master from "./Module/Master";
|
|
8
|
+
import VirtualMidi from "./Module/VirtualMidi";
|
|
6
9
|
import VoiceScheduler from "./Module/VoiceScheduler";
|
|
7
10
|
import { applyRoutes, createRoute, RouteInterface, RouteProps } from "./routes";
|
|
8
11
|
|
|
@@ -18,9 +21,11 @@ interface InitializeInterface {
|
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
class Engine {
|
|
24
|
+
midiDeviceManager: MidiDeviceManager;
|
|
21
25
|
private static instance: Engine;
|
|
22
26
|
private _master: Master;
|
|
23
27
|
private context: Context;
|
|
28
|
+
private propsUpdateCallbacks: { (id: string, props: any): void }[];
|
|
24
29
|
|
|
25
30
|
modules: {
|
|
26
31
|
[Identifier: string]: AudioModule;
|
|
@@ -33,6 +38,7 @@ class Engine {
|
|
|
33
38
|
private constructor() {
|
|
34
39
|
this.modules = {};
|
|
35
40
|
this.routes = {};
|
|
41
|
+
this.propsUpdateCallbacks = [];
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
public static getInstance(): Engine {
|
|
@@ -47,6 +53,7 @@ class Engine {
|
|
|
47
53
|
this.context = new Context(props.context);
|
|
48
54
|
setContext(this.context);
|
|
49
55
|
this.context.transport.start();
|
|
56
|
+
this.midiDeviceManager = new MidiDeviceManager();
|
|
50
57
|
|
|
51
58
|
return {
|
|
52
59
|
master: this.master,
|
|
@@ -69,15 +76,20 @@ class Engine {
|
|
|
69
76
|
return audioModule.serialize();
|
|
70
77
|
}
|
|
71
78
|
|
|
79
|
+
onPropsUpdate(callback: (id: string, props: any) => void) {
|
|
80
|
+
this.propsUpdateCallbacks.push(callback);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
_triggerPropsUpdate(id: string, props: any) {
|
|
84
|
+
this.propsUpdateCallbacks.forEach((callback) => callback(id, props));
|
|
85
|
+
}
|
|
86
|
+
|
|
72
87
|
updatePropsModule(id: string, props: any) {
|
|
73
88
|
const audioModule = this.findById(id);
|
|
74
89
|
|
|
75
|
-
const
|
|
76
|
-
audioModule instanceof VoiceScheduler && audioModule.polyNumber;
|
|
90
|
+
const applyRoutesRequired = this.applyRoutesRequired(audioModule, props);
|
|
77
91
|
audioModule.props = props;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (polyNumber !== newPolyNumber) applyRoutes(Object.values(this.routes));
|
|
92
|
+
if (applyRoutesRequired) applyRoutes(Object.values(this.routes));
|
|
81
93
|
|
|
82
94
|
return audioModule.serialize();
|
|
83
95
|
}
|
|
@@ -110,7 +122,11 @@ class Engine {
|
|
|
110
122
|
return masterProps;
|
|
111
123
|
}
|
|
112
124
|
|
|
113
|
-
|
|
125
|
+
triggerVirtualMidi(id: string, noteName: string, type: string) {
|
|
126
|
+
const virtualMidi = this.findById(id) as VirtualMidi;
|
|
127
|
+
|
|
128
|
+
virtualMidi.sendMidi(MidiEvent.fromNote(noteName, type));
|
|
129
|
+
}
|
|
114
130
|
|
|
115
131
|
dispose() {
|
|
116
132
|
Object.values(this.modules).forEach((m) => {
|
|
@@ -130,6 +146,13 @@ class Engine {
|
|
|
130
146
|
|
|
131
147
|
return audioModule;
|
|
132
148
|
}
|
|
149
|
+
|
|
150
|
+
private applyRoutesRequired(audioModule: AudioModule, props: any) {
|
|
151
|
+
if (!props.polyNumber) return false;
|
|
152
|
+
if (!(audioModule instanceof VoiceScheduler)) return false;
|
|
153
|
+
|
|
154
|
+
return props.polyNumber !== audioModule.polyNumber;
|
|
155
|
+
}
|
|
133
156
|
}
|
|
134
157
|
|
|
135
158
|
export default Engine.getInstance();
|
package/src/MidiDevice.ts
CHANGED
|
@@ -31,7 +31,7 @@ export default class MidiDevice implements MidiDeviceInterface {
|
|
|
31
31
|
|
|
32
32
|
if (!isMidiEvent) return;
|
|
33
33
|
|
|
34
|
-
this.
|
|
34
|
+
this.processEvent(e);
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -51,11 +51,11 @@ export default class MidiDevice implements MidiDeviceInterface {
|
|
|
51
51
|
|
|
52
52
|
removeEventListener(callback: EventListerCallback) {
|
|
53
53
|
this.eventListerCallbacks = this.eventListerCallbacks.filter(
|
|
54
|
-
(c) => c
|
|
54
|
+
(c) => c !== callback
|
|
55
55
|
);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
private processEvent(e: MIDIMessageEvent) {
|
|
59
59
|
const event = new MidiEvent(e);
|
|
60
60
|
|
|
61
61
|
switch (event.type) {
|
package/src/MidiDeviceManager.ts
CHANGED
|
@@ -1,61 +1,70 @@
|
|
|
1
1
|
import MidiDevice from "./MidiDevice";
|
|
2
2
|
|
|
3
|
-
class MidiDeviceManager {
|
|
4
|
-
|
|
5
|
-
private
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return MidiDeviceManager.instance;
|
|
3
|
+
export default class MidiDeviceManager {
|
|
4
|
+
devices: { [Key: string]: MidiDevice } = {};
|
|
5
|
+
private initialized: boolean = false;
|
|
6
|
+
|
|
7
|
+
constructor() {
|
|
8
|
+
this.initializeDevices().then(() => {
|
|
9
|
+
this.listenChanges();
|
|
10
|
+
this.initialized = true;
|
|
11
|
+
});
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
find(id: string): MidiDevice | null {
|
|
15
|
+
const device = this.devices[id];
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
if (!device) return null;
|
|
19
18
|
|
|
20
|
-
return
|
|
19
|
+
return device;
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
(
|
|
26
|
-
|
|
22
|
+
onStateChange(callback: (device: MidiDevice) => void) {
|
|
23
|
+
navigator.requestMIDIAccess().then((access: MIDIAccess) => {
|
|
24
|
+
access.onstatechange = (e) => {
|
|
25
|
+
const isMidiEvent = e instanceof MIDIConnectionEvent;
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
if (!isMidiEvent) return;
|
|
28
|
+
if (e.port instanceof MIDIOutput) return;
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
}
|
|
30
|
+
const input = e.port as MIDIInput;
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
const inputs: Array<MIDIInput> = [];
|
|
32
|
+
const midi = new MidiDevice(input);
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
callback(midi);
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
private listenChanges() {
|
|
40
|
+
this.onStateChange((device) => {
|
|
41
|
+
if (device.state === "disconnected") {
|
|
42
|
+
device.disconnect();
|
|
43
|
+
delete this.devices[device.id];
|
|
44
|
+
} else {
|
|
45
|
+
this.devices[device.id] = device;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
40
48
|
}
|
|
41
49
|
|
|
42
|
-
async
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
private async initializeDevices() {
|
|
51
|
+
if (this.initialized) return Object.values(this.devices);
|
|
52
|
+
|
|
53
|
+
(await this.inputs()).forEach((input) => {
|
|
54
|
+
if (this.devices[input.id]) return;
|
|
45
55
|
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
this.devices[input.id] = new MidiDevice(input);
|
|
57
|
+
});
|
|
48
58
|
|
|
49
|
-
|
|
50
|
-
|
|
59
|
+
return Object.values(this.devices);
|
|
60
|
+
}
|
|
51
61
|
|
|
52
|
-
|
|
62
|
+
private async inputs() {
|
|
63
|
+
const inputs: Array<MIDIInput> = [];
|
|
53
64
|
|
|
54
|
-
|
|
65
|
+
const access = await navigator.requestMIDIAccess();
|
|
66
|
+
access.inputs.forEach((input) => inputs.push(input));
|
|
55
67
|
|
|
56
|
-
|
|
57
|
-
};
|
|
68
|
+
return inputs;
|
|
58
69
|
}
|
|
59
70
|
}
|
|
60
|
-
|
|
61
|
-
export default MidiDeviceManager.getInstance();
|
package/src/MidiEvent.ts
CHANGED
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
import { now } from "tone";
|
|
2
2
|
import Note from "./Note";
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const EventType: { [key: number]: string } = {
|
|
5
5
|
8: "noteOff",
|
|
6
6
|
9: "noteOn",
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
export default class MidiEvent {
|
|
10
10
|
note?: Note;
|
|
11
|
-
triggeredAt: number;
|
|
11
|
+
readonly triggeredAt: number;
|
|
12
|
+
_type: string;
|
|
12
13
|
private data: Uint8Array;
|
|
13
|
-
private
|
|
14
|
-
|
|
14
|
+
private event: MIDIMessageEvent;
|
|
15
|
+
|
|
16
|
+
static fromNote(noteName: string, type: string) {
|
|
17
|
+
const event = new MidiEvent(
|
|
18
|
+
new MIDIMessageEvent("", { data: new Uint8Array([0, 0, 0]) })
|
|
19
|
+
);
|
|
20
|
+
event.note = new Note(noteName);
|
|
21
|
+
event._type = type;
|
|
22
|
+
|
|
23
|
+
return event;
|
|
24
|
+
}
|
|
15
25
|
|
|
16
26
|
constructor(event: MIDIMessageEvent) {
|
|
17
|
-
this.
|
|
27
|
+
this.event = event;
|
|
18
28
|
this.triggeredAt = now();
|
|
19
29
|
this.data = event.data;
|
|
20
30
|
this.defineNote();
|
|
@@ -23,7 +33,7 @@ export default class MidiEvent {
|
|
|
23
33
|
get type() {
|
|
24
34
|
if (this._type) return this._type;
|
|
25
35
|
|
|
26
|
-
let type =
|
|
36
|
+
let type = EventType[this.data[0] >> 4];
|
|
27
37
|
|
|
28
38
|
if (type === "noteOn" && this.data[2] === 0) {
|
|
29
39
|
type = "noteOff";
|
|
@@ -39,6 +49,6 @@ export default class MidiEvent {
|
|
|
39
49
|
defineNote() {
|
|
40
50
|
if (!this.isNote) return;
|
|
41
51
|
|
|
42
|
-
this.note = new Note(this.
|
|
52
|
+
this.note = new Note(this.event);
|
|
43
53
|
}
|
|
44
54
|
}
|
package/src/Module/Base.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import MidiDeviceManager from "../MidiDeviceManager";
|
|
1
|
+
import Engine from "../Engine";
|
|
3
2
|
import MidiEvent from "../MidiEvent";
|
|
4
3
|
import Module, { ModuleType, DummnyInternalModule } from "./Base";
|
|
5
4
|
import { Output } from "./IO";
|
|
@@ -26,6 +25,7 @@ export default class MidiSelector extends Module<
|
|
|
26
25
|
});
|
|
27
26
|
|
|
28
27
|
this.registerOutputs();
|
|
28
|
+
this.addEventListener(this.selectedId);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
get selectedId() {
|
|
@@ -34,31 +34,29 @@ export default class MidiSelector extends Module<
|
|
|
34
34
|
|
|
35
35
|
set selectedId(value: string | null) {
|
|
36
36
|
if (this.selectedId) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
});
|
|
37
|
+
const prevMidiDevice = Engine.midiDeviceManager.find(this.selectedId);
|
|
38
|
+
prevMidiDevice?.removeEventListener(this.onMidiEvent);
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
this._props = { ...this.props, selectedId: value };
|
|
43
42
|
|
|
44
|
-
|
|
43
|
+
this.addEventListener(value);
|
|
44
|
+
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
});
|
|
46
|
+
private registerOutputs() {
|
|
47
|
+
this.midiOutput = this.registerOutput({ name: "midi out" });
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
onMidiEvent = (midiEvent: MidiEvent) => {
|
|
50
|
+
private onMidiEvent = (midiEvent: MidiEvent) => {
|
|
52
51
|
this.midiOutput.connections.forEach((input) => {
|
|
53
52
|
input.pluggable(midiEvent);
|
|
54
53
|
});
|
|
55
54
|
};
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
56
|
+
private addEventListener(midiId: string | null) {
|
|
57
|
+
if (!this.onMidiEvent || !midiId) return; // Ugly hack because of weird super bug
|
|
60
58
|
|
|
61
|
-
|
|
62
|
-
this.
|
|
59
|
+
const midiDevice = Engine.midiDeviceManager.find(midiId);
|
|
60
|
+
midiDevice?.addEventListener(this.onMidiEvent);
|
|
63
61
|
}
|
|
64
62
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import Engine from "../Engine";
|
|
2
|
+
import MidiEvent from "../MidiEvent";
|
|
3
|
+
import Module, { ModuleType, DummnyInternalModule } from "./Base";
|
|
4
|
+
import { Output } from "./IO";
|
|
5
|
+
|
|
6
|
+
export interface VirtualMidiInterface {
|
|
7
|
+
activeNotes: string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const InitialProps: VirtualMidiInterface = {
|
|
11
|
+
activeNotes: [],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default class VirtualMidi extends Module<
|
|
15
|
+
DummnyInternalModule,
|
|
16
|
+
VirtualMidiInterface
|
|
17
|
+
> {
|
|
18
|
+
midiOutput: Output;
|
|
19
|
+
|
|
20
|
+
constructor(name: string, props: VirtualMidiInterface) {
|
|
21
|
+
super(new DummnyInternalModule(), {
|
|
22
|
+
name,
|
|
23
|
+
props: { ...InitialProps, ...props },
|
|
24
|
+
type: ModuleType.VirtualMidi,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
this.registerInputs();
|
|
28
|
+
this.registerOutputs();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
get activeNotes() {
|
|
32
|
+
return this._props["activeNotes"];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// can't set externaly
|
|
36
|
+
set activeNotes(value: string[]) {
|
|
37
|
+
this._props = { ...this.props, activeNotes: value };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
sendMidi(midiEvent: MidiEvent) {
|
|
41
|
+
this.midiTriggered(midiEvent);
|
|
42
|
+
this.midiOutput.connections.forEach((input) => {
|
|
43
|
+
input.pluggable(midiEvent);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
triggerAttack(midiEvent: MidiEvent) {
|
|
48
|
+
if (!midiEvent.note) return;
|
|
49
|
+
|
|
50
|
+
this.activeNotes = [...this.activeNotes, midiEvent.note.fullName];
|
|
51
|
+
Engine._triggerPropsUpdate(this.id, this.props);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
triggerRelease(midiEvent: MidiEvent) {
|
|
55
|
+
if (!midiEvent.note) return;
|
|
56
|
+
|
|
57
|
+
this.activeNotes = this.activeNotes.filter(
|
|
58
|
+
(name) => name !== midiEvent.note!.fullName
|
|
59
|
+
);
|
|
60
|
+
Engine._triggerPropsUpdate(this.id, this.props);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
serialize() {
|
|
64
|
+
return {
|
|
65
|
+
...super.serialize(),
|
|
66
|
+
activeNotes: this.activeNotes,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private registerInputs() {
|
|
71
|
+
this.registerInput({
|
|
72
|
+
name: "midi in",
|
|
73
|
+
pluggable: this.midiTriggered,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private registerOutputs() {
|
|
78
|
+
this.midiOutput = this.registerOutput({ name: "midi out" });
|
|
79
|
+
}
|
|
80
|
+
}
|
package/src/Module/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { PolyAmpEnvelope } from "./Envelope/AmpEnvelope";
|
|
|
10
10
|
import { PolyFreqEnvelope } from "./Envelope/FreqEnvelope";
|
|
11
11
|
import { PolyEnvelope } from "./Envelope/Base";
|
|
12
12
|
import Volume, { PolyVolume } from "./Volume";
|
|
13
|
+
import VirtualMidi from "./VirtualMidi";
|
|
13
14
|
|
|
14
15
|
export { default, ModuleType } from "./Base";
|
|
15
16
|
export { default as PolyModule, PolyModuleType } from "./PolyModule";
|
|
@@ -72,6 +73,8 @@ export function moduleClassFromType(type: string) {
|
|
|
72
73
|
return VoiceScheduler;
|
|
73
74
|
case ModuleType.MidiSelector:
|
|
74
75
|
return MidiSelector;
|
|
76
|
+
case ModuleType.VirtualMidi:
|
|
77
|
+
return VirtualMidi;
|
|
75
78
|
default:
|
|
76
79
|
throw Error("Unknown module type");
|
|
77
80
|
}
|