@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
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { now, Oscillator as Osc, ToneOscillatorType } from "tone";
|
|
2
2
|
import Engine from "../Engine";
|
|
3
3
|
|
|
4
|
-
import Note from "../Note";
|
|
5
|
-
import Module, {
|
|
6
|
-
import PolyModule from "./PolyModule";
|
|
4
|
+
import Note from "../core/Note";
|
|
5
|
+
import Module, { PolyModule, Startable } from "../core/Module";
|
|
7
6
|
|
|
8
|
-
export interface OscillatorInterface
|
|
7
|
+
export interface OscillatorInterface {
|
|
9
8
|
noteName: string;
|
|
10
9
|
fine: number;
|
|
11
10
|
coarse: number;
|
|
@@ -23,15 +22,27 @@ const InitialProps: OscillatorInterface = {
|
|
|
23
22
|
volume: 0,
|
|
24
23
|
};
|
|
25
24
|
|
|
26
|
-
class MonoOscillator
|
|
25
|
+
class MonoOscillator
|
|
26
|
+
extends Module<Osc, OscillatorInterface>
|
|
27
|
+
implements Startable
|
|
28
|
+
{
|
|
27
29
|
private _note: Note;
|
|
28
30
|
|
|
29
|
-
constructor(
|
|
31
|
+
constructor(params: {
|
|
32
|
+
id?: string;
|
|
33
|
+
name: string;
|
|
34
|
+
props: Partial<OscillatorInterface>;
|
|
35
|
+
}) {
|
|
36
|
+
const { id, name, props } = params;
|
|
37
|
+
|
|
30
38
|
super(new Osc(), {
|
|
39
|
+
id,
|
|
31
40
|
name,
|
|
32
41
|
props: { ...InitialProps, ...props },
|
|
33
42
|
});
|
|
34
43
|
|
|
44
|
+
this.registerBasicOutputs();
|
|
45
|
+
this.registerDefaultMidiInput();
|
|
35
46
|
this.start(now());
|
|
36
47
|
}
|
|
37
48
|
|
|
@@ -126,7 +137,7 @@ class MonoOscillator extends Module<Osc, OscillatorInterface> {
|
|
|
126
137
|
this.start(triggeredAt);
|
|
127
138
|
};
|
|
128
139
|
|
|
129
|
-
triggerRelease = (
|
|
140
|
+
triggerRelease = () => {
|
|
130
141
|
// Do nothing
|
|
131
142
|
};
|
|
132
143
|
|
|
@@ -153,15 +164,22 @@ export default class Oscillator extends PolyModule<
|
|
|
153
164
|
> {
|
|
154
165
|
static moduleName = "Oscillator";
|
|
155
166
|
|
|
156
|
-
constructor(
|
|
167
|
+
constructor(params: {
|
|
168
|
+
id?: string;
|
|
169
|
+
name: string;
|
|
170
|
+
props: Partial<OscillatorInterface>;
|
|
171
|
+
}) {
|
|
172
|
+
const { id, name, props } = params;
|
|
173
|
+
|
|
157
174
|
super({
|
|
175
|
+
id,
|
|
158
176
|
name,
|
|
159
177
|
child: MonoOscillator,
|
|
160
178
|
props: { ...InitialProps, ...props },
|
|
161
179
|
});
|
|
162
180
|
|
|
163
181
|
this.registerBasicOutputs();
|
|
164
|
-
this.
|
|
182
|
+
this.registerInput({ name: "midi in" });
|
|
165
183
|
}
|
|
166
184
|
|
|
167
185
|
start(time: number) {
|
|
@@ -171,11 +189,4 @@ export default class Oscillator extends PolyModule<
|
|
|
171
189
|
stop(time?: number) {
|
|
172
190
|
this.audioModules.forEach((audioModule) => audioModule.stop(time));
|
|
173
191
|
}
|
|
174
|
-
|
|
175
|
-
private registerInputs() {
|
|
176
|
-
this.registerInput({
|
|
177
|
-
name: "midi in",
|
|
178
|
-
pluggable: this.midiTriggered,
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
192
|
}
|
|
@@ -15,10 +15,21 @@ const InitialProps: Partial<ReverbInterface> = {
|
|
|
15
15
|
export default class Reverb extends Effect<InternalReverb, ReverbInterface> {
|
|
16
16
|
static moduleName = "Reverb";
|
|
17
17
|
|
|
18
|
-
constructor(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
constructor(params: {
|
|
19
|
+
id?: string;
|
|
20
|
+
name: string;
|
|
21
|
+
props: Partial<ReverbInterface>;
|
|
22
|
+
}) {
|
|
23
|
+
const { id, name, props } = params;
|
|
24
|
+
|
|
25
|
+
super({
|
|
26
|
+
id,
|
|
27
|
+
name,
|
|
28
|
+
internalModule: new InternalReverb(),
|
|
29
|
+
props: {
|
|
30
|
+
...InitialProps,
|
|
31
|
+
...props,
|
|
32
|
+
},
|
|
22
33
|
});
|
|
23
34
|
}
|
|
24
35
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { now, Part
|
|
2
|
-
import Module, { DummnyInternalModule } from "
|
|
3
|
-
import { INote } from "../Note";
|
|
4
|
-
import {
|
|
5
|
-
import MidiEvent from "../
|
|
1
|
+
import { now, Part } from "tone";
|
|
2
|
+
import Module, { DummnyInternalModule } from "../core/Module";
|
|
3
|
+
import { INote } from "../core/Note";
|
|
4
|
+
import { MidiOutput } from "../core/IO";
|
|
5
|
+
import { MidiEvent } from "../core/midi";
|
|
6
6
|
import Engine from "../Engine";
|
|
7
7
|
|
|
8
8
|
export interface ISequence {
|
|
@@ -27,11 +27,17 @@ export default class Sequencer extends Module<
|
|
|
27
27
|
ISequencer
|
|
28
28
|
> {
|
|
29
29
|
static moduleName = "Sequencer";
|
|
30
|
-
midiOutput:
|
|
30
|
+
midiOutput: MidiOutput;
|
|
31
31
|
private part: Part<ISequence>;
|
|
32
32
|
|
|
33
|
-
constructor(
|
|
33
|
+
constructor(params: {
|
|
34
|
+
id?: string;
|
|
35
|
+
name: string;
|
|
36
|
+
props: Partial<ISequencer>;
|
|
37
|
+
}) {
|
|
38
|
+
const { id, name, props } = params;
|
|
34
39
|
super(new DummnyInternalModule(), {
|
|
40
|
+
id,
|
|
35
41
|
name,
|
|
36
42
|
props: { ...InitialProps(), ...props },
|
|
37
43
|
});
|
|
@@ -88,7 +94,7 @@ export default class Sequencer extends Module<
|
|
|
88
94
|
}
|
|
89
95
|
|
|
90
96
|
private registerOutputs() {
|
|
91
|
-
this.midiOutput = this.
|
|
97
|
+
this.midiOutput = this.registerMidiOutput({ name: "midi out" });
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
private initializePart() {
|
|
@@ -151,7 +157,7 @@ export default class Sequencer extends Module<
|
|
|
151
157
|
private updateBarParts() {
|
|
152
158
|
this.part.clear();
|
|
153
159
|
|
|
154
|
-
this.sequences.forEach((barSeqs
|
|
160
|
+
this.sequences.forEach((barSeqs) => {
|
|
155
161
|
barSeqs.forEach((seq) => this.part.add(seq.time, seq));
|
|
156
162
|
});
|
|
157
163
|
|
|
@@ -165,10 +171,8 @@ export default class Sequencer extends Module<
|
|
|
165
171
|
private onPartEvent = (time: number, sequence: ISequence) => {
|
|
166
172
|
if (!sequence.active) return;
|
|
167
173
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
this.midiOutput.connections.forEach((input) => {
|
|
171
|
-
input.pluggable(event);
|
|
174
|
+
MidiEvent.fromSequence(sequence, time).forEach((event) => {
|
|
175
|
+
this.midiOutput.onMidiEvent(event);
|
|
172
176
|
});
|
|
173
177
|
};
|
|
174
178
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import Engine from "../Engine";
|
|
2
|
-
import MidiEvent from "../
|
|
3
|
-
import Note from "../Note";
|
|
4
|
-
import Module, { DummnyInternalModule } from "
|
|
5
|
-
import {
|
|
2
|
+
import { MidiEvent } from "../core/midi";
|
|
3
|
+
import Note from "../core/Note";
|
|
4
|
+
import Module, { DummnyInternalModule } from "../core/Module";
|
|
5
|
+
import { MidiOutput } from "../core/IO";
|
|
6
6
|
|
|
7
7
|
export interface VirtualMidiInterface {
|
|
8
8
|
activeNotes: string[];
|
|
@@ -17,10 +17,16 @@ export default class VirtualMidi extends Module<
|
|
|
17
17
|
VirtualMidiInterface
|
|
18
18
|
> {
|
|
19
19
|
static moduleName = "VirtualMidi";
|
|
20
|
-
midiOutput:
|
|
20
|
+
midiOutput: MidiOutput;
|
|
21
21
|
|
|
22
|
-
constructor(
|
|
22
|
+
constructor(params: {
|
|
23
|
+
id?: string;
|
|
24
|
+
name: string;
|
|
25
|
+
props: VirtualMidiInterface;
|
|
26
|
+
}) {
|
|
27
|
+
const { id, name, props } = params;
|
|
23
28
|
super(new DummnyInternalModule(), {
|
|
29
|
+
id,
|
|
24
30
|
name,
|
|
25
31
|
props: { ...InitialProps, ...props },
|
|
26
32
|
});
|
|
@@ -39,9 +45,7 @@ export default class VirtualMidi extends Module<
|
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
sendMidi(midiEvent: MidiEvent) {
|
|
42
|
-
this.midiOutput.
|
|
43
|
-
input.pluggable(midiEvent);
|
|
44
|
-
});
|
|
48
|
+
this.midiOutput.onMidiEvent(midiEvent);
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
triggerAttack = (note: Note) => {
|
|
@@ -64,13 +68,13 @@ export default class VirtualMidi extends Module<
|
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
private registerInputs() {
|
|
67
|
-
this.
|
|
71
|
+
this.registerMidiInput({
|
|
68
72
|
name: "midi in",
|
|
69
|
-
|
|
73
|
+
onMidiEvent: this.onMidiEvent,
|
|
70
74
|
});
|
|
71
75
|
}
|
|
72
76
|
|
|
73
77
|
private registerOutputs() {
|
|
74
|
-
this.midiOutput = this.
|
|
78
|
+
this.midiOutput = this.registerMidiOutput({ name: "midi out" });
|
|
75
79
|
}
|
|
76
80
|
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { MidiEvent } from "../core/midi";
|
|
2
|
+
import Module, { PolyModule, DummnyInternalModule } from "../core/Module";
|
|
3
|
+
import { MidiOutput } from "../core/IO";
|
|
4
|
+
|
|
5
|
+
export interface VoiceSchedulerInterface {
|
|
6
|
+
polyNumber: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default class VoiceScheduler extends PolyModule<
|
|
10
|
+
Voice,
|
|
11
|
+
VoiceSchedulerInterface
|
|
12
|
+
> {
|
|
13
|
+
static moduleName = "VoiceScheduler";
|
|
14
|
+
midiOutput: MidiOutput;
|
|
15
|
+
|
|
16
|
+
constructor(params: {
|
|
17
|
+
id?: string;
|
|
18
|
+
name: string;
|
|
19
|
+
props: VoiceSchedulerInterface;
|
|
20
|
+
}) {
|
|
21
|
+
const { id, name, props } = params;
|
|
22
|
+
|
|
23
|
+
super({
|
|
24
|
+
id,
|
|
25
|
+
name,
|
|
26
|
+
child: Voice,
|
|
27
|
+
props,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
this.registerInputs();
|
|
31
|
+
this.registerOutputs();
|
|
32
|
+
this.polyNumber = this.numberOfVoices;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
set polyNumber(value: number) {
|
|
36
|
+
super.numberOfVoices = value;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get polyNumber() {
|
|
40
|
+
return this.numberOfVoices;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
onMidiEvent = (midiEvent: MidiEvent) => {
|
|
44
|
+
let voice: Voice | undefined;
|
|
45
|
+
|
|
46
|
+
switch (midiEvent.type) {
|
|
47
|
+
case "noteOn":
|
|
48
|
+
voice = this.findFreeVoice();
|
|
49
|
+
|
|
50
|
+
break;
|
|
51
|
+
case "noteOff":
|
|
52
|
+
voice = this.audioModules.find(
|
|
53
|
+
(v) => v.activeNote === midiEvent.note.fullName
|
|
54
|
+
);
|
|
55
|
+
break;
|
|
56
|
+
default:
|
|
57
|
+
throw Error("This type is not a note");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!voice) return;
|
|
61
|
+
|
|
62
|
+
voice.midiTriggered(midiEvent);
|
|
63
|
+
midiEvent.voiceNo = voice.voiceNo;
|
|
64
|
+
this.midiOutput.onMidiEvent(midiEvent);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
serialize() {
|
|
68
|
+
const serialize = super.serialize();
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
...serialize,
|
|
72
|
+
props: { ...serialize.props, polyNumber: this.polyNumber },
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private findFreeVoice(): Voice {
|
|
77
|
+
let voice = this.audioModules.find((v) => !v.activeNote);
|
|
78
|
+
|
|
79
|
+
// If no available voice, get the one with the lowest triggeredAt
|
|
80
|
+
if (!voice) {
|
|
81
|
+
voice = this.audioModules.sort((a, b) => {
|
|
82
|
+
if (!a || !b) return 0;
|
|
83
|
+
|
|
84
|
+
return a.triggeredAt - b.triggeredAt;
|
|
85
|
+
})[0];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return voice;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private registerInputs() {
|
|
92
|
+
this.registerMidiInput({
|
|
93
|
+
name: "midi in",
|
|
94
|
+
onMidiEvent: this.onMidiEvent,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private registerOutputs() {
|
|
99
|
+
this.midiOutput = this.registerMidiOutput({ name: "midi out" });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
class Voice extends Module<DummnyInternalModule, VoiceSchedulerInterface> {
|
|
104
|
+
midiEvent: MidiEvent | null;
|
|
105
|
+
activeNote: string | null;
|
|
106
|
+
triggeredAt: number;
|
|
107
|
+
|
|
108
|
+
constructor(params: {
|
|
109
|
+
id?: string;
|
|
110
|
+
name: string;
|
|
111
|
+
props: VoiceSchedulerInterface;
|
|
112
|
+
}) {
|
|
113
|
+
const { id, name, props } = params;
|
|
114
|
+
|
|
115
|
+
super(new DummnyInternalModule(), {
|
|
116
|
+
id,
|
|
117
|
+
name,
|
|
118
|
+
props,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
midiTriggered = (midiEvent: MidiEvent) => {
|
|
123
|
+
if (this.voiceNo === undefined) throw Error("Voice without voiceNo");
|
|
124
|
+
|
|
125
|
+
const { triggeredAt, note, type } = midiEvent;
|
|
126
|
+
|
|
127
|
+
if (!note) return;
|
|
128
|
+
const noteName = note.fullName;
|
|
129
|
+
|
|
130
|
+
switch (type) {
|
|
131
|
+
case "noteOn":
|
|
132
|
+
this.activeNote = noteName;
|
|
133
|
+
this.triggeredAt = triggeredAt;
|
|
134
|
+
this.midiEvent = midiEvent;
|
|
135
|
+
|
|
136
|
+
break;
|
|
137
|
+
case "noteOff":
|
|
138
|
+
this.activeNote = null;
|
|
139
|
+
this.midiEvent = null;
|
|
140
|
+
break;
|
|
141
|
+
default:
|
|
142
|
+
throw Error("This type is not a note");
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Volume as Vol } from "tone";
|
|
2
2
|
|
|
3
|
-
import Module, {
|
|
4
|
-
import
|
|
5
|
-
import Note from "../Note";
|
|
3
|
+
import Module, { PolyModule } from "../core/Module";
|
|
4
|
+
import Note from "../core/Note";
|
|
6
5
|
|
|
7
|
-
export interface VolumeInterface
|
|
6
|
+
export interface VolumeInterface {
|
|
8
7
|
volume: number;
|
|
9
8
|
}
|
|
10
9
|
|
|
@@ -13,11 +12,21 @@ const InitialProps: VolumeInterface = {
|
|
|
13
12
|
};
|
|
14
13
|
|
|
15
14
|
class MonoVolume extends Module<Vol, VolumeInterface> {
|
|
16
|
-
constructor(
|
|
15
|
+
constructor(params: {
|
|
16
|
+
id?: string;
|
|
17
|
+
name: string;
|
|
18
|
+
props: Partial<VolumeInterface>;
|
|
19
|
+
}) {
|
|
20
|
+
const { id, name, props } = params;
|
|
21
|
+
|
|
17
22
|
super(new Vol(), {
|
|
23
|
+
id,
|
|
18
24
|
name,
|
|
19
25
|
props: { ...InitialProps, ...props },
|
|
20
26
|
});
|
|
27
|
+
|
|
28
|
+
this.registerBasicInputs();
|
|
29
|
+
this.registerBasicOutputs();
|
|
21
30
|
}
|
|
22
31
|
|
|
23
32
|
get volume() {
|
|
@@ -35,7 +44,7 @@ class MonoVolume extends Module<Vol, VolumeInterface> {
|
|
|
35
44
|
this.internalModule.volume.exponentialRampToValueAtTime(db, triggeredAt);
|
|
36
45
|
};
|
|
37
46
|
|
|
38
|
-
triggerRelease = (
|
|
47
|
+
triggerRelease = () => {
|
|
39
48
|
// Do nothing
|
|
40
49
|
};
|
|
41
50
|
}
|
|
@@ -43,8 +52,15 @@ class MonoVolume extends Module<Vol, VolumeInterface> {
|
|
|
43
52
|
export default class Volume extends PolyModule<MonoVolume, VolumeInterface> {
|
|
44
53
|
static moduleName = "Volume";
|
|
45
54
|
|
|
46
|
-
constructor(
|
|
55
|
+
constructor(params: {
|
|
56
|
+
id?: string;
|
|
57
|
+
name: string;
|
|
58
|
+
props: Partial<VolumeInterface>;
|
|
59
|
+
}) {
|
|
60
|
+
const { id, name, props } = params;
|
|
61
|
+
|
|
47
62
|
super({
|
|
63
|
+
id,
|
|
48
64
|
name,
|
|
49
65
|
child: MonoVolume,
|
|
50
66
|
props: { ...InitialProps, ...props },
|
|
@@ -52,13 +68,5 @@ export default class Volume extends PolyModule<MonoVolume, VolumeInterface> {
|
|
|
52
68
|
|
|
53
69
|
this.registerBasicInputs();
|
|
54
70
|
this.registerBasicOutputs();
|
|
55
|
-
this.registerInputs();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
private registerInputs() {
|
|
59
|
-
this.registerInput({
|
|
60
|
-
name: "midi in",
|
|
61
|
-
pluggable: this.midiTriggered,
|
|
62
|
-
});
|
|
63
71
|
}
|
|
64
72
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { camelCase, upperFirst } from "lodash";
|
|
2
|
-
import Module, { Connectable } from "./Base";
|
|
3
|
-
import PolyModule from "./PolyModule";
|
|
4
|
-
import Oscillator from "./Oscillator";
|
|
5
2
|
import { Envelope, AmpEnvelope, FreqEnvelope } from "./Envelope";
|
|
3
|
+
import Oscillator from "./Oscillator";
|
|
6
4
|
import Filter from "./Filter";
|
|
7
5
|
import Master from "./Master";
|
|
8
6
|
import VoiceScheduler from "./VoiceScheduler";
|
|
@@ -14,18 +12,15 @@ import Delay from "./Delay";
|
|
|
14
12
|
import Distortion from "./Distortion";
|
|
15
13
|
import BitCrusher from "./BitCrusher";
|
|
16
14
|
import Sequencer from "./Sequencer";
|
|
17
|
-
import
|
|
18
|
-
|
|
19
|
-
export { default } from "./Base";
|
|
20
|
-
export { default as PolyModule } from "./PolyModule";
|
|
21
|
-
export type { ModuleInterface, Connectable, Triggerable } from "./Base";
|
|
15
|
+
import { AudioModule } from "../core/Module";
|
|
22
16
|
|
|
17
|
+
export { default as Master } from "./Master";
|
|
23
18
|
export { default as Filter } from "./Filter";
|
|
24
19
|
export { default as Oscillator } from "./Oscillator";
|
|
20
|
+
export { default as VirtualMidi } from "./VirtualMidi";
|
|
21
|
+
export { default as VoiceScheduler } from "./VoiceScheduler";
|
|
25
22
|
export { default as Sequencer } from "./Sequencer";
|
|
26
|
-
export { default as DataSequencer } from "./DataSequencer";
|
|
27
23
|
export type { ISequence } from "./Sequencer";
|
|
28
|
-
export type { IDataSequence } from "./DataSequencer";
|
|
29
24
|
|
|
30
25
|
export {
|
|
31
26
|
Envelope,
|
|
@@ -34,18 +29,18 @@ export {
|
|
|
34
29
|
EnvelopeStages,
|
|
35
30
|
} from "./Envelope";
|
|
36
31
|
|
|
37
|
-
export
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
export interface ICreateModule {
|
|
33
|
+
id?: string;
|
|
34
|
+
name: string;
|
|
35
|
+
type: string;
|
|
36
|
+
props: any;
|
|
37
|
+
}
|
|
40
38
|
|
|
41
|
-
export function createModule(
|
|
42
|
-
name
|
|
43
|
-
type: string,
|
|
44
|
-
props: any
|
|
45
|
-
): AudioModule {
|
|
39
|
+
export function createModule(params: ICreateModule): AudioModule {
|
|
40
|
+
const { id, type, name, props } = params;
|
|
46
41
|
const klass = moduleClassFromType(type);
|
|
47
42
|
|
|
48
|
-
return new klass(name, props);
|
|
43
|
+
return new klass({ id, name, props });
|
|
49
44
|
}
|
|
50
45
|
|
|
51
46
|
function moduleClassFromType(type: string) {
|
|
@@ -82,8 +77,6 @@ function moduleClassFromType(type: string) {
|
|
|
82
77
|
return BitCrusher;
|
|
83
78
|
case Sequencer.moduleName:
|
|
84
79
|
return Sequencer;
|
|
85
|
-
case DataSequencer.moduleName:
|
|
86
|
-
return DataSequencer;
|
|
87
80
|
default:
|
|
88
81
|
throw Error(`Unknown module type ${type}`);
|
|
89
82
|
}
|
package/src/routes.ts
CHANGED
|
@@ -1,44 +1,45 @@
|
|
|
1
1
|
import { v4 as uuidv4 } from "uuid";
|
|
2
2
|
|
|
3
3
|
import Engine from "./";
|
|
4
|
+
import { plugCompatibleIO } from "./core/IO/Node";
|
|
5
|
+
import { Optional } from "./types";
|
|
4
6
|
|
|
5
7
|
export interface RouteProps {
|
|
6
8
|
sourceId: string;
|
|
7
|
-
|
|
9
|
+
sourceIOId: string;
|
|
8
10
|
destinationId: string;
|
|
9
|
-
|
|
11
|
+
destinationIOId: string;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export interface RouteInterface extends RouteProps {
|
|
13
15
|
id: string;
|
|
14
16
|
}
|
|
15
17
|
|
|
16
|
-
export function createRoute(props:
|
|
17
|
-
const id = uuidv4();
|
|
18
|
+
export function createRoute(props: Optional<RouteInterface, "id">) {
|
|
19
|
+
const id = props.id || uuidv4();
|
|
18
20
|
|
|
19
21
|
return { ...props, id };
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export function applyRoutes(routes: RouteInterface[]) {
|
|
23
|
-
Object.values(Engine.modules).forEach((m) =>
|
|
25
|
+
Object.values(Engine.modules).forEach((m) => {
|
|
26
|
+
m.unPlugAll();
|
|
27
|
+
});
|
|
24
28
|
|
|
25
|
-
const succesedConnections = routes
|
|
26
|
-
|
|
27
|
-
if (r1.outputName === "number of voices") return -1;
|
|
28
|
-
if (r2.outputName === "number of voices") return 1;
|
|
29
|
+
const succesedConnections = routes.map((route) => {
|
|
30
|
+
const { sourceId, sourceIOId, destinationId, destinationIOId } = route;
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
.map((route) => {
|
|
33
|
-
const { sourceId, outputName, destinationId, inputName } = route;
|
|
32
|
+
const source = Engine.findById(sourceId);
|
|
33
|
+
const destination = Engine.findById(destinationId);
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const output = source.outputs.find(sourceIOId);
|
|
36
|
+
const input = destination.inputs.find(destinationIOId);
|
|
37
|
+
if (!input || !output) throw Error("IO not found");
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
plugCompatibleIO(input, output);
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
return true;
|
|
42
|
+
});
|
|
42
43
|
|
|
43
44
|
if (succesedConnections.every((v) => v)) {
|
|
44
45
|
console.log("######## Routes succesfully applied");
|
package/src/types.ts
ADDED
package/src/utils.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import CryptoJS from "crypto-js";
|
|
2
|
+
|
|
3
|
+
export function deterministicId(
|
|
4
|
+
originalId: string,
|
|
5
|
+
additionalString: string
|
|
6
|
+
): string {
|
|
7
|
+
const combinedString = `${originalId}:${additionalString}`;
|
|
8
|
+
const hash = CryptoJS.SHA256(combinedString).toString(CryptoJS.enc.Hex);
|
|
9
|
+
|
|
10
|
+
const newId = `${hash.substring(0, 8)}-${hash.substring(
|
|
11
|
+
8,
|
|
12
|
+
12
|
|
13
|
+
)}-4${hash.substring(13, 16)}-${
|
|
14
|
+
"89AB"[parseInt(hash.substring(17, 18), 16) % 4]
|
|
15
|
+
}${hash.substring(18, 21)}-${hash.substring(21, 33)}`;
|
|
16
|
+
|
|
17
|
+
return newId;
|
|
18
|
+
}
|