@blibliki/engine 0.1.0

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 (91) hide show
  1. package/README.md +4 -0
  2. package/build/Engine.d.ts +114 -0
  3. package/build/Engine.js +81 -0
  4. package/build/Engine.js.map +1 -0
  5. package/build/MidiDevice.d.ts +25 -0
  6. package/build/MidiDevice.js +45 -0
  7. package/build/MidiDevice.js.map +1 -0
  8. package/build/MidiDeviceManager.d.ts +12 -0
  9. package/build/MidiDeviceManager.js +45 -0
  10. package/build/MidiDeviceManager.js.map +1 -0
  11. package/build/MidiEvent.d.ts +12 -0
  12. package/build/MidiEvent.js +37 -0
  13. package/build/MidiEvent.js.map +1 -0
  14. package/build/Module/Base.d.ts +72 -0
  15. package/build/Module/Base.js +139 -0
  16. package/build/Module/Base.js.map +1 -0
  17. package/build/Module/Envelope/AmpEnvelope.d.ts +8 -0
  18. package/build/Module/Envelope/AmpEnvelope.js +15 -0
  19. package/build/Module/Envelope/AmpEnvelope.js.map +1 -0
  20. package/build/Module/Envelope/Base.d.ts +45 -0
  21. package/build/Module/Envelope/Base.js +110 -0
  22. package/build/Module/Envelope/Base.js.map +1 -0
  23. package/build/Module/Envelope/FreqEnvelope.d.ts +17 -0
  24. package/build/Module/Envelope/FreqEnvelope.js +51 -0
  25. package/build/Module/Envelope/FreqEnvelope.js.map +1 -0
  26. package/build/Module/Envelope/index.d.ts +3 -0
  27. package/build/Module/Envelope/index.js +4 -0
  28. package/build/Module/Envelope/index.js.map +1 -0
  29. package/build/Module/Filter.d.ts +31 -0
  30. package/build/Module/Filter.js +83 -0
  31. package/build/Module/Filter.js.map +1 -0
  32. package/build/Module/IO.d.ts +39 -0
  33. package/build/Module/IO.js +59 -0
  34. package/build/Module/IO.js.map +1 -0
  35. package/build/Module/Master.d.ts +7 -0
  36. package/build/Module/Master.js +12 -0
  37. package/build/Module/Master.js.map +1 -0
  38. package/build/Module/MidiSelector.d.ts +16 -0
  39. package/build/Module/MidiSelector.js +44 -0
  40. package/build/Module/MidiSelector.js.map +1 -0
  41. package/build/Module/Oscillator.d.ts +42 -0
  42. package/build/Module/Oscillator.js +123 -0
  43. package/build/Module/Oscillator.js.map +1 -0
  44. package/build/Module/PolyModule.d.ts +57 -0
  45. package/build/Module/PolyModule.js +191 -0
  46. package/build/Module/PolyModule.js.map +1 -0
  47. package/build/Module/VoiceScheduler.d.ts +37 -0
  48. package/build/Module/VoiceScheduler.js +117 -0
  49. package/build/Module/VoiceScheduler.js.map +1 -0
  50. package/build/Module/Volume.d.ts +15 -0
  51. package/build/Module/Volume.js +34 -0
  52. package/build/Module/Volume.js.map +1 -0
  53. package/build/Module/index.d.ts +20 -0
  54. package/build/Module/index.js +60 -0
  55. package/build/Module/index.js.map +1 -0
  56. package/build/Note/frequencyTable.d.ts +4 -0
  57. package/build/Note/frequencyTable.js +146 -0
  58. package/build/Note/frequencyTable.js.map +1 -0
  59. package/build/Note/index.d.ts +13 -0
  60. package/build/Note/index.js +53 -0
  61. package/build/Note/index.js.map +1 -0
  62. package/build/index.d.ts +8 -0
  63. package/build/index.js +6 -0
  64. package/build/index.js.map +1 -0
  65. package/build/routes.d.ts +17 -0
  66. package/build/routes.js +23 -0
  67. package/build/routes.js.map +1 -0
  68. package/package.json +37 -0
  69. package/src/Engine.ts +129 -0
  70. package/src/MidiDevice.ts +67 -0
  71. package/src/MidiDeviceManager.ts +61 -0
  72. package/src/MidiEvent.ts +44 -0
  73. package/src/Module/Base.ts +200 -0
  74. package/src/Module/Envelope/AmpEnvelope.ts +17 -0
  75. package/src/Module/Envelope/Base.ts +159 -0
  76. package/src/Module/Envelope/FreqEnvelope.ts +69 -0
  77. package/src/Module/Envelope/index.ts +3 -0
  78. package/src/Module/Filter.ts +111 -0
  79. package/src/Module/IO.ts +85 -0
  80. package/src/Module/Master.ts +18 -0
  81. package/src/Module/MidiSelector.ts +64 -0
  82. package/src/Module/Oscillator.ts +166 -0
  83. package/src/Module/PolyModule.ts +243 -0
  84. package/src/Module/VoiceScheduler.ts +153 -0
  85. package/src/Module/Volume.ts +46 -0
  86. package/src/Module/index.ts +78 -0
  87. package/src/Note/frequencyTable.ts +146 -0
  88. package/src/Note/index.ts +65 -0
  89. package/src/index.ts +10 -0
  90. package/src/routes.ts +41 -0
  91. package/tsconfig.json +22 -0
@@ -0,0 +1,44 @@
1
+ import { now } from "tone";
2
+ import Note from "./Note";
3
+
4
+ const EvenType: { [key: number]: string } = {
5
+ 8: "noteOff",
6
+ 9: "noteOn",
7
+ };
8
+
9
+ export default class MidiEvent {
10
+ note?: Note;
11
+ triggeredAt: number;
12
+ private data: Uint8Array;
13
+ private _type: string;
14
+ private _event: MIDIMessageEvent;
15
+
16
+ constructor(event: MIDIMessageEvent) {
17
+ this._event = event;
18
+ this.triggeredAt = now();
19
+ this.data = event.data;
20
+ this.defineNote();
21
+ }
22
+
23
+ get type() {
24
+ if (this._type) return this._type;
25
+
26
+ let type = EvenType[this.data[0] >> 4];
27
+
28
+ if (type === "noteOn" && this.data[2] === 0) {
29
+ type = "noteOff";
30
+ }
31
+
32
+ return (this._type = type);
33
+ }
34
+
35
+ get isNote() {
36
+ return this.type === "noteOn" || this.type === "noteOff";
37
+ }
38
+
39
+ defineNote() {
40
+ if (!this.isNote) return;
41
+
42
+ this.note = new Note(this._event);
43
+ }
44
+ }
@@ -0,0 +1,200 @@
1
+ import { v4 as uuidv4 } from "uuid";
2
+ import { InputNode } from "tone";
3
+
4
+ import { Input, Output, IOInterface } from "./IO";
5
+ import MidiEvent from "../MidiEvent";
6
+ import { AudioModule, PolyModule } from "../Module";
7
+
8
+ export enum ModuleType {
9
+ Oscillator = "monoOscillator",
10
+ Envelope = "monoEnvelope",
11
+ AmpEnvelope = "monoAmpEnvelope",
12
+ FreqEnvelope = "monoFreqEnvelope",
13
+ Filter = "monoFilter",
14
+ Master = "master",
15
+ Voice = "voice",
16
+ MidiSelector = "midiSelector",
17
+ Volume = "monoVolume",
18
+ }
19
+
20
+ export interface Connectable {
21
+ connect: (inputNode: InputNode) => void;
22
+ disconnect: (inputNode?: InputNode) => void;
23
+ dispose: () => void;
24
+ }
25
+
26
+ export interface Triggerable {
27
+ triggerAttack: Function;
28
+ triggerRelease: Function;
29
+ }
30
+
31
+ export interface ModuleInterface {
32
+ name: string;
33
+ type: ModuleType;
34
+ props?: { [key: string]: any };
35
+ voiceNo?: number;
36
+ }
37
+
38
+ export class DummnyInternalModule implements Connectable {
39
+ connect(inputNode: InputNode) {
40
+ throw Error("This module is not connectable");
41
+ }
42
+
43
+ disconnect(inputNode?: InputNode) {}
44
+
45
+ dispose() {}
46
+ }
47
+
48
+ class Module<InternalModule extends Connectable, PropsInterface>
49
+ implements ModuleInterface
50
+ {
51
+ internalModule: InternalModule;
52
+
53
+ readonly id: string;
54
+ name: string;
55
+ inputs: Input[] = [];
56
+ outputs: Output[] = [];
57
+ type: ModuleType;
58
+ readonly voiceNo?: number;
59
+ updatedAt: Date;
60
+ _props: PropsInterface;
61
+
62
+ constructor(internalModule: InternalModule, props: Partial<ModuleInterface>) {
63
+ this.internalModule = internalModule;
64
+ this.id = uuidv4();
65
+
66
+ Object.assign(this, props);
67
+ }
68
+
69
+ set props(value: PropsInterface) {
70
+ if (!value) return;
71
+ if (!this._props) this._props = value;
72
+
73
+ this.updatedAt = new Date();
74
+
75
+ Object.assign(this, value);
76
+ }
77
+
78
+ get props() {
79
+ return this._props;
80
+ }
81
+
82
+ plug(audioModule: AudioModule, from: string, to: string) {
83
+ const output = this.outputs.find((i) => i.name === from);
84
+ if (!output) throw Error(`Output ${from} not exist`);
85
+
86
+ console.log(`${this.name}:${from} => ${audioModule.name}:${to}`);
87
+
88
+ const input = audioModule.inputs.find((i) => i.name === to);
89
+ if (!input)
90
+ throw Error(`Input ${to} in module ${audioModule.name} not exist`);
91
+
92
+ output.plug(input);
93
+ }
94
+
95
+ unplugAll() {
96
+ this.outputs.forEach((o) => o.unPlugAll());
97
+ }
98
+
99
+ connect = (
100
+ inputAudioModule: AudioModule,
101
+ attribute: string = "internalModule"
102
+ ) => {
103
+ if (inputAudioModule instanceof PolyModule) {
104
+ inputAudioModule.audioModules.forEach((m) => {
105
+ this.internalModule.connect((m as any)[attribute] as InputNode);
106
+ });
107
+ return;
108
+ }
109
+
110
+ this.internalModule.connect(
111
+ (inputAudioModule as any)[attribute] as InputNode
112
+ );
113
+ };
114
+
115
+ disconnect = (
116
+ inputAudioModule: AudioModule,
117
+ attribute: string = "internalModule"
118
+ ) => {
119
+ if (inputAudioModule instanceof PolyModule) {
120
+ inputAudioModule.audioModules.forEach((m) => {
121
+ this.internalModule.disconnect((m as any)[attribute] as InputNode);
122
+ });
123
+ return;
124
+ }
125
+
126
+ this.internalModule.disconnect(
127
+ (inputAudioModule as any)[attribute] as InputNode
128
+ );
129
+ };
130
+
131
+ dispose() {
132
+ this.internalModule.dispose();
133
+ }
134
+
135
+ triggerAttack(midiEvent: MidiEvent) {
136
+ throw Error("triggerAttack not implemented");
137
+ }
138
+
139
+ triggerRelease(midiEvent: MidiEvent) {
140
+ throw Error("triggerRelease not implemented");
141
+ }
142
+
143
+ midiTriggered = (midiEvent: MidiEvent) => {
144
+ switch (midiEvent.type) {
145
+ case "noteOn":
146
+ this.triggerAttack(midiEvent);
147
+ break;
148
+ case "noteOff":
149
+ this.triggerRelease(midiEvent);
150
+ break;
151
+ default:
152
+ throw Error("This type is not a note");
153
+ }
154
+ };
155
+
156
+ serialize() {
157
+ return {
158
+ id: this.id,
159
+ name: this.name,
160
+ type: this.type,
161
+ props: this.props,
162
+ inputs: this.inputs.map((i) => i.serialize()),
163
+ outputs: this.outputs.map((i) => i.serialize()),
164
+ };
165
+ }
166
+
167
+ protected registerInput(props: IOInterface): Input {
168
+ const input = new Input(this, props);
169
+ this.inputs.push(input);
170
+
171
+ return input;
172
+ }
173
+
174
+ protected registerOutput(props: IOInterface): Output {
175
+ const output = new Output(this, props);
176
+ this.outputs.push(output);
177
+
178
+ return output;
179
+ }
180
+
181
+ protected registerBasicOutputs() {
182
+ this.registerOutput({
183
+ name: "output",
184
+ onPlug: (output: Output) => {
185
+ this.connect(output.audioModule);
186
+ },
187
+ onUnPlug: (output: Output) => {
188
+ this.disconnect(output.audioModule);
189
+ },
190
+ });
191
+ }
192
+
193
+ protected registerBasicInputs() {
194
+ this.registerInput({
195
+ name: "input",
196
+ });
197
+ }
198
+ }
199
+
200
+ export default Module;
@@ -0,0 +1,17 @@
1
+ import { AmplitudeEnvelope } from "tone";
2
+
3
+ import { ModuleType } from "../index";
4
+ import Base, { EnvelopeInterface, PolyBase } from "./Base";
5
+ import { PolyModuleType } from "../PolyModule";
6
+
7
+ export default class AmpEnvelope extends Base<AmplitudeEnvelope> {
8
+ constructor(name: string, props: EnvelopeInterface) {
9
+ super(name, ModuleType.AmpEnvelope, new AmplitudeEnvelope(), props);
10
+ }
11
+ }
12
+
13
+ export class PolyAmpEnvelope extends PolyBase<AmpEnvelope> {
14
+ constructor(name: string, props: Partial<EnvelopeInterface>) {
15
+ super(name, ModuleType.AmpEnvelope, PolyModuleType.AmpEnvelope, props);
16
+ }
17
+ }
@@ -0,0 +1,159 @@
1
+ import { Envelope as Env } from "tone";
2
+
3
+ import Module, { ModuleType, Connectable, Triggerable } from "../index";
4
+ import PolyModule, { PolyModuleType } from "../PolyModule";
5
+ import MidiEvent from "../../MidiEvent";
6
+
7
+ export const enum EnvelopeStages {
8
+ Attack = "attack",
9
+ Decay = "decay",
10
+ Sustain = "sustain",
11
+ Release = "release",
12
+ }
13
+
14
+ const MAX_TIME = 2;
15
+ const MIN_TIME = 0.01;
16
+ const SUSTAIN_MAX_VALUE = 1;
17
+ const SUSTAIN_MIN_VALUE = 0;
18
+
19
+ export interface EnvelopeInterface {
20
+ attack: number;
21
+ decay: number;
22
+ sustain: number;
23
+ release: number;
24
+ voiceNo?: number;
25
+ }
26
+
27
+ const InitialProps: EnvelopeInterface = {
28
+ attack: MIN_TIME,
29
+ decay: MIN_TIME,
30
+ sustain: SUSTAIN_MAX_VALUE,
31
+ release: MIN_TIME,
32
+ };
33
+
34
+ export default abstract class EnvelopeModule<EnvelopeLike extends Env>
35
+ extends Module<EnvelopeLike, EnvelopeInterface>
36
+ implements Triggerable
37
+ {
38
+ activeNote?: string;
39
+ triggeredAt: number;
40
+
41
+ constructor(
42
+ name: string,
43
+ type: ModuleType,
44
+ internalModule: EnvelopeLike,
45
+ props: EnvelopeInterface
46
+ ) {
47
+ super(internalModule, {
48
+ name,
49
+ type,
50
+ props: { ...InitialProps, ...props },
51
+ });
52
+ }
53
+
54
+ get attack() {
55
+ return this._props["attack"];
56
+ }
57
+
58
+ set attack(value: number) {
59
+ this.setStage(EnvelopeStages.Attack, value);
60
+ }
61
+
62
+ get decay() {
63
+ return this._props["decay"];
64
+ }
65
+
66
+ set decay(value: number) {
67
+ this.setStage(EnvelopeStages.Decay, value);
68
+ }
69
+
70
+ get sustain() {
71
+ return this._props["sustain"];
72
+ }
73
+
74
+ set sustain(value: number) {
75
+ this.setStage(EnvelopeStages.Sustain, value);
76
+ }
77
+
78
+ get release() {
79
+ return this._props["release"];
80
+ }
81
+
82
+ set release(value: number) {
83
+ this.setStage(EnvelopeStages.Release, value);
84
+ }
85
+
86
+ setStage(stage: EnvelopeStages, value: number) {
87
+ const calculatedValue =
88
+ value === 0 ? this.minTime(stage) : this.maxTime(stage) * value;
89
+ this._props = { ...this.props, [stage]: value };
90
+ this.internalModule[stage] = calculatedValue;
91
+ }
92
+
93
+ triggerAttack(midiEvent: MidiEvent) {
94
+ const { note, triggeredAt } = midiEvent;
95
+
96
+ this.activeNote = note?.fullName;
97
+ this.triggeredAt = triggeredAt;
98
+ this.internalModule.triggerAttack(triggeredAt);
99
+ }
100
+
101
+ triggerRelease(midiEvent: MidiEvent) {
102
+ const { note, triggeredAt } = midiEvent;
103
+
104
+ if (this.activeNote && this.activeNote !== note?.fullName) return;
105
+
106
+ this.internalModule.triggerRelease(triggeredAt);
107
+ }
108
+
109
+ private maxTime(stage: EnvelopeStages): number {
110
+ return stage === EnvelopeStages.Sustain ? SUSTAIN_MAX_VALUE : MAX_TIME;
111
+ }
112
+
113
+ private minTime(stage: EnvelopeStages): number {
114
+ return stage === EnvelopeStages.Sustain ? SUSTAIN_MIN_VALUE : MIN_TIME;
115
+ }
116
+ }
117
+
118
+ export abstract class PolyBase<
119
+ EnvelopeModule extends Module<Connectable, any>
120
+ > extends PolyModule<EnvelopeModule, EnvelopeInterface> {
121
+ constructor(
122
+ name: string,
123
+ type: ModuleType,
124
+ polyType: PolyModuleType,
125
+ props: Partial<EnvelopeInterface>
126
+ ) {
127
+ super(polyType, {
128
+ name,
129
+ type,
130
+ props: { ...InitialProps, ...props },
131
+ });
132
+
133
+ this.registerBasicInputs();
134
+ this.registerBasicOutputs();
135
+ this.registerInputs();
136
+ }
137
+
138
+ private registerInputs() {
139
+ this.registerInput({
140
+ name: "midi in",
141
+ pluggable: this.midiTriggered,
142
+ });
143
+ }
144
+ }
145
+
146
+ export class Envelope extends EnvelopeModule<Env> {
147
+ constructor(name: string, props: EnvelopeInterface) {
148
+ super(name, ModuleType.Envelope, new Env(), props);
149
+ }
150
+ }
151
+
152
+ export class PolyEnvelope extends PolyBase<Envelope> {
153
+ constructor(name: string, props: Partial<EnvelopeInterface>) {
154
+ super(name, ModuleType.Envelope, PolyModuleType.Envelope, {
155
+ ...InitialProps,
156
+ ...props,
157
+ });
158
+ }
159
+ }
@@ -0,0 +1,69 @@
1
+ import { FrequencyEnvelope } from "tone";
2
+
3
+ import { ModuleType } from "../Base";
4
+ import Filter from "../Filter";
5
+ import { Output } from "../IO";
6
+ import { PolyModuleType } from "../PolyModule";
7
+
8
+ import Base, { EnvelopeInterface, PolyBase } from "./Base";
9
+
10
+ interface FreqEnvelopeInterface extends Partial<EnvelopeInterface> {
11
+ amount?: number;
12
+ }
13
+
14
+ const InitialProps: FreqEnvelopeInterface = {
15
+ amount: 0,
16
+ };
17
+
18
+ export default class FreqEnvelope extends Base<FrequencyEnvelope> {
19
+ private _frequency: number;
20
+ private _amount: number;
21
+ filter: Filter;
22
+
23
+ constructor(name: string, props: EnvelopeInterface) {
24
+ super(name, ModuleType.FreqEnvelope, new FrequencyEnvelope(), {
25
+ ...InitialProps,
26
+ ...props,
27
+ });
28
+ }
29
+
30
+ get frequency() {
31
+ return this._frequency;
32
+ }
33
+
34
+ set frequency(value: number) {
35
+ this._frequency = value;
36
+ this.internalModule.baseFrequency = value;
37
+ }
38
+
39
+ get amount() {
40
+ return this._amount;
41
+ }
42
+
43
+ set amount(value: number) {
44
+ this._amount = value;
45
+
46
+ this.internalModule.octaves = value;
47
+ }
48
+ }
49
+
50
+ export class PolyFreqEnvelope extends PolyBase<FreqEnvelope> {
51
+ constructor(name: string, props: Partial<EnvelopeInterface>) {
52
+ super(name, ModuleType.FreqEnvelope, PolyModuleType.FreqEnvelope, props);
53
+
54
+ this.registerOutputs();
55
+ }
56
+
57
+ protected registerOutputs() {
58
+ this.registerOutput({
59
+ name: "frequency",
60
+ pluggable: this,
61
+ onPlug: (output: Output) => {
62
+ this.connect(output.audioModule, output.pluggable);
63
+ },
64
+ onUnPlug: (output: Output) => {
65
+ this.disconnect(output.audioModule, output.pluggable);
66
+ },
67
+ });
68
+ }
69
+ }
@@ -0,0 +1,3 @@
1
+ export { default, Envelope, EnvelopeStages } from "./Base";
2
+ export { default as AmpEnvelope } from "./AmpEnvelope";
3
+ export { default as FreqEnvelope } from "./FreqEnvelope";
@@ -0,0 +1,111 @@
1
+ import { Filter as InternalFilter } from "tone";
2
+
3
+ import { FreqEnvelope } from "./Envelope";
4
+ import Module, { ModuleType } from "./Base";
5
+ import PolyModule, { PolyModuleType } from "./PolyModule";
6
+ import { PolyFreqEnvelope } from "./Envelope/FreqEnvelope";
7
+
8
+ interface FilterInterface {
9
+ cutoff: number;
10
+ resonance: number;
11
+ envelopeAmount: number;
12
+ voiceNo?: number;
13
+ }
14
+
15
+ interface FilterProps extends Partial<FilterInterface> {}
16
+
17
+ const InitialProps: FilterInterface = {
18
+ cutoff: 20000,
19
+ resonance: 0,
20
+ envelopeAmount: 0,
21
+ };
22
+
23
+ export default class Filter extends Module<InternalFilter, FilterInterface> {
24
+ private _envelope: FreqEnvelope;
25
+
26
+ constructor(name: string, props: FilterProps) {
27
+ super(new InternalFilter({ type: "lowpass" }), {
28
+ name,
29
+ props: { ...InitialProps, ...props },
30
+ type: ModuleType.Filter,
31
+ });
32
+ }
33
+
34
+ get cutoff() {
35
+ return this._props["cutoff"];
36
+ }
37
+
38
+ set cutoff(value: number) {
39
+ this._props = { ...this.props, cutoff: value };
40
+
41
+ if (this._envelope) {
42
+ this._envelope.frequency = value;
43
+ } else {
44
+ this.internalModule.frequency.value = value;
45
+ }
46
+ }
47
+
48
+ get frequency() {
49
+ return this.internalModule.frequency;
50
+ }
51
+
52
+ get resonance() {
53
+ return this._props["resonance"];
54
+ }
55
+
56
+ set resonance(value: number) {
57
+ this._props = { ...this.props, resonance: value };
58
+
59
+ this.internalModule.Q.value = value;
60
+ }
61
+
62
+ get envelopeAmount() {
63
+ return this._props["envelopeAmount"];
64
+ }
65
+
66
+ set envelopeAmount(value: number) {
67
+ this._props = { ...this.props, envelopeAmount: value };
68
+
69
+ if (!this._envelope) return;
70
+
71
+ this._envelope.amount = value;
72
+ }
73
+
74
+ conntectedEnvelope(envelope: FreqEnvelope) {
75
+ this._envelope = envelope;
76
+ this._envelope.frequency = this.cutoff;
77
+ }
78
+ }
79
+
80
+ export class PolyFilter extends PolyModule<Filter, FilterInterface> {
81
+ constructor(name: string, props: Partial<FilterInterface>) {
82
+ super(PolyModuleType.Filter, {
83
+ name,
84
+ props: { ...InitialProps, ...props },
85
+ type: ModuleType.Filter,
86
+ });
87
+
88
+ this.registerBasicInputs();
89
+ this.registerBasicOutputs();
90
+ this.registerInputs();
91
+ }
92
+
93
+ private registerInputs() {
94
+ this.registerInput({
95
+ name: "frequency",
96
+ pluggable: "frequency",
97
+ onPlug: (output) => {
98
+ this.conntectedEnvelope(output.audioModule as PolyFreqEnvelope);
99
+ },
100
+ });
101
+ }
102
+
103
+ conntectedEnvelope(polyFreqEnvelope: PolyFreqEnvelope) {
104
+ polyFreqEnvelope.audioModules.forEach((envelope) => {
105
+ if (envelope.voiceNo === undefined) return;
106
+
107
+ const filter = this.findVoice(envelope.voiceNo);
108
+ filter?.conntectedEnvelope(envelope);
109
+ });
110
+ }
111
+ }
@@ -0,0 +1,85 @@
1
+ import { v4 as uuidv4 } from "uuid";
2
+ import { AudioModule } from "../Module";
3
+
4
+ export interface IOInterface {
5
+ name: string;
6
+ pluggable?: any;
7
+ onPlug?: (io: IO) => void;
8
+ onUnPlug?: (io: IO) => void;
9
+ }
10
+
11
+ export interface SerializeInterface {
12
+ id: string;
13
+ name: string;
14
+ moduleId: string;
15
+ moduleName: string;
16
+ }
17
+
18
+ enum IOType {
19
+ Input = "input",
20
+ Output = "output",
21
+ }
22
+
23
+ abstract class IO {
24
+ id: string;
25
+ ioType: IOType;
26
+ name: string;
27
+ audioModule: AudioModule;
28
+ pluggable: any;
29
+ onPlug: (io: IO) => void;
30
+ onUnPlug: (io: IO) => void;
31
+ connections: Input[] | Output[] = [];
32
+
33
+ constructor(ioType: IOType, audioModule: AudioModule, props: IOInterface) {
34
+ this.id = uuidv4();
35
+ this.ioType = ioType;
36
+ this.audioModule = audioModule;
37
+
38
+ Object.assign(this, props);
39
+ }
40
+
41
+ plug(io: IO) {
42
+ if (this.onPlug) this.onPlug(io);
43
+
44
+ if (this.ioType === IOType.Output) io.plug(this);
45
+
46
+ this.connections.push(io);
47
+ }
48
+
49
+ unPlug(io: IO) {
50
+ if (this.onUnPlug) this.onUnPlug(io);
51
+
52
+ if (this.ioType === IOType.Output) {
53
+ io.unPlug(this);
54
+ }
55
+
56
+ this.connections = this.connections.filter(
57
+ (current_io) => current_io.id !== io.id
58
+ );
59
+ }
60
+
61
+ unPlugAll() {
62
+ this.connections.forEach((c) => this.unPlug(c));
63
+ }
64
+
65
+ serialize(): SerializeInterface {
66
+ return {
67
+ id: this.id,
68
+ name: this.name,
69
+ moduleId: this.audioModule.id,
70
+ moduleName: this.audioModule.name,
71
+ };
72
+ }
73
+ }
74
+
75
+ export class Input extends IO {
76
+ constructor(audioModule: AudioModule, props: IOInterface) {
77
+ super(IOType.Input, audioModule, props);
78
+ }
79
+ }
80
+
81
+ export class Output extends IO {
82
+ constructor(audioModule: AudioModule, props: IOInterface) {
83
+ super(IOType.Output, audioModule, props);
84
+ }
85
+ }
@@ -0,0 +1,18 @@
1
+ import { Destination, getDestination } from "tone";
2
+ import Module, { ModuleType } from "../Module";
3
+
4
+ export interface MasterInterface {}
5
+
6
+ export default class Master extends Module<
7
+ typeof Destination,
8
+ MasterInterface
9
+ > {
10
+ constructor() {
11
+ super(getDestination(), {
12
+ name: "Master",
13
+ type: ModuleType.Master,
14
+ });
15
+
16
+ this.registerBasicInputs();
17
+ }
18
+ }