@blibliki/engine 0.1.17 → 0.1.18
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/.eslintrc.js +14 -0
- package/.parcerc +6 -0
- package/README.md +13 -1
- package/dist/main.cjs.js +33 -0
- package/package.json +21 -22
- package/rollup.config.mjs +21 -0
- 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/test/MockingModules.ts +27 -0
- package/test/Module/Oscillator.test.ts +1 -1
- package/test/core/IO.test.ts +172 -0
- package/build/Engine.d.ts +0 -89
- package/build/Engine.js +0 -165
- package/build/Engine.js.map +0 -1
- package/build/MidiDevice.d.ts +0 -25
- package/build/MidiDevice.js +0 -45
- package/build/MidiDevice.js.map +0 -1
- package/build/MidiDeviceManager.d.ts +0 -13
- 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.d.ts +0 -12
- 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.d.ts +0 -15
- package/build/Module/Delay.js +0 -30
- package/build/Module/Delay.js.map +0 -1
- package/build/Module/Distortion.d.ts +0 -12
- package/build/Module/Distortion.js +0 -22
- package/build/Module/Distortion.js.map +0 -1
- package/build/Module/Effect.d.ts +0 -14
- package/build/Module/Effect.js +0 -22
- package/build/Module/Effect.js.map +0 -1
- package/build/Module/Envelope/AmpEnvelope.d.ts +0 -10
- package/build/Module/Envelope/AmpEnvelope.js +0 -14
- package/build/Module/Envelope/AmpEnvelope.js.map +0 -1
- package/build/Module/Envelope/Base.d.ts +0 -47
- package/build/Module/Envelope/Base.js +0 -106
- package/build/Module/Envelope/Base.js.map +0 -1
- package/build/Module/Envelope/FreqEnvelope.d.ts +0 -18
- package/build/Module/Envelope/FreqEnvelope.js +0 -50
- package/build/Module/Envelope/FreqEnvelope.js.map +0 -1
- package/build/Module/Envelope/index.d.ts +0 -3
- package/build/Module/Envelope/index.js +0 -4
- package/build/Module/Envelope/index.js.map +0 -1
- package/build/Module/Filter.d.ts +0 -37
- 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.d.ts +0 -8
- package/build/Module/Master.js +0 -12
- package/build/Module/Master.js.map +0 -1
- package/build/Module/MidiSelector.d.ts +0 -17
- package/build/Module/MidiSelector.js +0 -50
- package/build/Module/MidiSelector.js.map +0 -1
- package/build/Module/Oscillator.d.ts +0 -45
- 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.d.ts +0 -15
- package/build/Module/Reverb.js +0 -30
- package/build/Module/Reverb.js.map +0 -1
- package/build/Module/Sequencer.d.ts +0 -38
- package/build/Module/Sequencer.js +0 -131
- package/build/Module/Sequencer.js.map +0 -1
- package/build/Module/VirtualMidi.d.ts +0 -28
- 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.d.ts +0 -4
- package/build/Note/frequencyTable.js +0 -146
- package/build/Note/frequencyTable.js.map +0 -1
- package/build/Note/index.d.ts +0 -25
- 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.d.ts +0 -17
- package/build/routes.js +0 -31
- package/build/routes.js.map +0 -1
- 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/src/{Note → core/Note}/frequencyTable.ts +0 -0
- /package/src/{MidiDevice.ts → core/midi/MidiDevice.ts} +0 -0
- /package/src/{Module → modules}/Envelope/index.ts +0 -0
package/build/index.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export { default } from "./Engine";
|
|
2
|
-
export { default as MidiDevice } from "./MidiDevice";
|
|
3
|
-
export { default as MidiDeviceManager } from "./MidiDeviceManager";
|
|
4
|
-
export { default as Note } from "./Note";
|
|
5
|
-
export type { INote } from "./Note";
|
|
6
|
-
export type { MidiDeviceInterface } from "./MidiDevice";
|
|
7
|
-
export type { ModuleInterface, AudioModule, ISequence, IDataSequence, } from "./Module";
|
|
8
|
-
export type { SerializeInterface as IOProps } from "./Module/IO";
|
package/build/index.js
DELETED
package/build/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAC"}
|
package/build/routes.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export interface RouteProps {
|
|
2
|
-
sourceId: string;
|
|
3
|
-
outputName: string;
|
|
4
|
-
destinationId: string;
|
|
5
|
-
inputName: string;
|
|
6
|
-
}
|
|
7
|
-
export interface RouteInterface extends RouteProps {
|
|
8
|
-
id: string;
|
|
9
|
-
}
|
|
10
|
-
export declare function createRoute(props: RouteProps): {
|
|
11
|
-
id: string;
|
|
12
|
-
sourceId: string;
|
|
13
|
-
outputName: string;
|
|
14
|
-
destinationId: string;
|
|
15
|
-
inputName: string;
|
|
16
|
-
};
|
|
17
|
-
export declare function applyRoutes(routes: RouteInterface[]): void;
|
package/build/routes.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { v4 as uuidv4 } from "uuid";
|
|
2
|
-
import Engine from "./";
|
|
3
|
-
export function createRoute(props) {
|
|
4
|
-
const id = uuidv4();
|
|
5
|
-
return { ...props, id };
|
|
6
|
-
}
|
|
7
|
-
export function applyRoutes(routes) {
|
|
8
|
-
Object.values(Engine.modules).forEach((m) => m.unplugAll());
|
|
9
|
-
const succesedConnections = routes
|
|
10
|
-
.sort((r1, r2) => {
|
|
11
|
-
if (r1.outputName === "number of voices")
|
|
12
|
-
return -1;
|
|
13
|
-
if (r2.outputName === "number of voices")
|
|
14
|
-
return 1;
|
|
15
|
-
return 0;
|
|
16
|
-
})
|
|
17
|
-
.map((route) => {
|
|
18
|
-
const { sourceId, outputName, destinationId, inputName } = route;
|
|
19
|
-
const source = Engine.findById(sourceId);
|
|
20
|
-
const destination = Engine.findById(destinationId);
|
|
21
|
-
source.plug(destination, outputName, inputName);
|
|
22
|
-
return true;
|
|
23
|
-
});
|
|
24
|
-
if (succesedConnections.every((v) => v)) {
|
|
25
|
-
console.log("######## Routes succesfully applied");
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
console.log("######## Routes partialy applied");
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
//# sourceMappingURL=routes.js.map
|
package/build/routes.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,MAAM,MAAM,IAAI,CAAC;AAaxB,MAAM,UAAU,WAAW,CAAC,KAAiB;IAC3C,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IAEpB,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAwB;IAClD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IAE5D,MAAM,mBAAmB,GAAG,MAAM;SAC/B,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;QACf,IAAI,EAAE,CAAC,UAAU,KAAK,kBAAkB;YAAE,OAAO,CAAC,CAAC,CAAC;QACpD,IAAI,EAAE,CAAC,UAAU,KAAK,kBAAkB;YAAE,OAAO,CAAC,CAAC;QAEnD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;QAEjE,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAEnD,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;QAEhD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEL,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE;QACvC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;KACpD;SAAM;QACL,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;KACjD;AACH,CAAC"}
|
package/src/MidiEvent.ts
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { now } from "tone";
|
|
2
|
-
import { ISequence } from "./Module/Sequencer";
|
|
3
|
-
import { IDataSequence } from "./Module/DataSequencer";
|
|
4
|
-
import Note, { INote } from "./Note";
|
|
5
|
-
|
|
6
|
-
const EventType: { [key: number]: EType } = {
|
|
7
|
-
8: "noteOff",
|
|
8
|
-
9: "noteOn",
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export type EType = "noteOn" | "noteOff";
|
|
12
|
-
|
|
13
|
-
export default class MidiEvent {
|
|
14
|
-
notes: Note[];
|
|
15
|
-
readonly triggeredAt: number;
|
|
16
|
-
_type: EType;
|
|
17
|
-
private data: Uint8Array;
|
|
18
|
-
private event: MIDIMessageEvent;
|
|
19
|
-
|
|
20
|
-
static fromDataSequence(sequence: IDataSequence, triggeredAt: number) {
|
|
21
|
-
const event = new MidiEvent(
|
|
22
|
-
new MIDIMessageEvent("", { data: new Uint8Array([0, 0, 0]) }),
|
|
23
|
-
triggeredAt
|
|
24
|
-
);
|
|
25
|
-
event._type = "noteOn";
|
|
26
|
-
const note = new Note(sequence.frequency);
|
|
27
|
-
note.velocity = sequence.amplitude;
|
|
28
|
-
event.notes = [note];
|
|
29
|
-
|
|
30
|
-
return event;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
static fromSequence(sequence: ISequence, triggeredAt: number) {
|
|
34
|
-
const event = new MidiEvent(
|
|
35
|
-
new MIDIMessageEvent("", { data: new Uint8Array([0, 0, 0]) }),
|
|
36
|
-
triggeredAt
|
|
37
|
-
);
|
|
38
|
-
event._type = "noteOn";
|
|
39
|
-
event.notes = sequence.notes.map((n) => new Note(n));
|
|
40
|
-
|
|
41
|
-
return event;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
static fromNote(
|
|
45
|
-
noteName: string | Note | INote,
|
|
46
|
-
type: EType,
|
|
47
|
-
triggeredAt?: number
|
|
48
|
-
) {
|
|
49
|
-
const event = new MidiEvent(
|
|
50
|
-
new MIDIMessageEvent("", { data: new Uint8Array([0, 0, 0]) }),
|
|
51
|
-
triggeredAt
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
if (noteName instanceof Note) {
|
|
55
|
-
event.notes = [noteName];
|
|
56
|
-
} else {
|
|
57
|
-
event.notes = [new Note(noteName)];
|
|
58
|
-
}
|
|
59
|
-
event._type = type;
|
|
60
|
-
|
|
61
|
-
return event;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
constructor(event: MIDIMessageEvent, triggeredAt?: number) {
|
|
65
|
-
this.event = event;
|
|
66
|
-
this.triggeredAt = triggeredAt || now();
|
|
67
|
-
this.data = event.data;
|
|
68
|
-
this.defineNotes();
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
get type() {
|
|
72
|
-
if (this._type) return this._type;
|
|
73
|
-
|
|
74
|
-
let type = EventType[this.data[0] >> 4];
|
|
75
|
-
|
|
76
|
-
if (type === "noteOn" && this.data[2] === 0) {
|
|
77
|
-
type = "noteOff";
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return (this._type = type);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
get isNote() {
|
|
84
|
-
return this.type === "noteOn" || this.type === "noteOff";
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
defineNotes() {
|
|
88
|
-
if (!this.isNote) return;
|
|
89
|
-
if (this.notes) return;
|
|
90
|
-
|
|
91
|
-
this.notes = [new Note(this.event)];
|
|
92
|
-
}
|
|
93
|
-
}
|
package/src/Module/Base.ts
DELETED
|
@@ -1,223 +0,0 @@
|
|
|
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
|
-
import Note from "../Note";
|
|
8
|
-
|
|
9
|
-
export interface Connectable {
|
|
10
|
-
connect: (inputNode: InputNode) => void;
|
|
11
|
-
disconnect: (inputNode?: InputNode) => void;
|
|
12
|
-
dispose: () => void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface Triggerable {
|
|
16
|
-
triggerAttack: Function;
|
|
17
|
-
triggerRelease: Function;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface Voicable {
|
|
21
|
-
voiceNo?: number;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface ModuleInterface<PropsInterface> {
|
|
25
|
-
name: string;
|
|
26
|
-
props: PropsInterface;
|
|
27
|
-
voiceNo?: number;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export class DummnyInternalModule implements Connectable {
|
|
31
|
-
connect(inputNode: InputNode) {
|
|
32
|
-
throw Error("This module is not connectable");
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
disconnect(inputNode?: InputNode) {}
|
|
36
|
-
|
|
37
|
-
dispose() {}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
class Module<InternalModule extends Connectable, PropsInterface>
|
|
41
|
-
implements ModuleInterface<PropsInterface>
|
|
42
|
-
{
|
|
43
|
-
static readonly moduleName: string;
|
|
44
|
-
|
|
45
|
-
readonly id: string;
|
|
46
|
-
name: string;
|
|
47
|
-
internalModule: InternalModule;
|
|
48
|
-
inputs: Input[] = [];
|
|
49
|
-
outputs: Output[] = [];
|
|
50
|
-
readonly voiceNo?: number;
|
|
51
|
-
updatedAt: Date;
|
|
52
|
-
_props: PropsInterface = {} as PropsInterface;
|
|
53
|
-
|
|
54
|
-
constructor(
|
|
55
|
-
internalModule: InternalModule,
|
|
56
|
-
props: Partial<ModuleInterface<PropsInterface>>
|
|
57
|
-
) {
|
|
58
|
-
this.internalModule = internalModule;
|
|
59
|
-
this.id = uuidv4();
|
|
60
|
-
|
|
61
|
-
Object.assign(this, props);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
set props(value: PropsInterface) {
|
|
65
|
-
if (!value) return;
|
|
66
|
-
|
|
67
|
-
this.updatedAt = new Date();
|
|
68
|
-
|
|
69
|
-
Object.assign(this, value);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
get props() {
|
|
73
|
-
return this._props;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
plug(audioModule: AudioModule, from: string, to: string) {
|
|
77
|
-
const output = this.outputs.find((i) => i.name === from);
|
|
78
|
-
if (!output) throw Error(`Output ${from} not exist`);
|
|
79
|
-
|
|
80
|
-
const input = audioModule.inputs.find((i) => i.name === to);
|
|
81
|
-
if (!input)
|
|
82
|
-
throw Error(`Input ${to} in module ${audioModule.name} not exist`);
|
|
83
|
-
|
|
84
|
-
output.plug(input);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
unplugAll() {
|
|
88
|
-
this.outputs.forEach((o) => o.unPlugAll());
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
connect = (
|
|
92
|
-
inputAudioModule: AudioModule,
|
|
93
|
-
attribute: string = "internalModule"
|
|
94
|
-
) => {
|
|
95
|
-
if (inputAudioModule instanceof PolyModule) {
|
|
96
|
-
inputAudioModule.audioModules.forEach((m) => {
|
|
97
|
-
this.internalModule.connect((m as any)[attribute] as InputNode);
|
|
98
|
-
});
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
this.internalModule.connect(
|
|
103
|
-
(inputAudioModule as any)[attribute] as InputNode
|
|
104
|
-
);
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
disconnect = (
|
|
108
|
-
inputAudioModule: AudioModule,
|
|
109
|
-
attribute: string = "internalModule"
|
|
110
|
-
) => {
|
|
111
|
-
if (inputAudioModule instanceof PolyModule) {
|
|
112
|
-
inputAudioModule.audioModules.forEach((m) => {
|
|
113
|
-
this.internalModule.disconnect((m as any)[attribute] as InputNode);
|
|
114
|
-
});
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
this.internalModule.disconnect(
|
|
119
|
-
(inputAudioModule as any)[attribute] as InputNode
|
|
120
|
-
);
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
dispose() {
|
|
124
|
-
this.internalModule.dispose();
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
triggerAttack(note: Note, triggeredAt: number) {
|
|
128
|
-
throw Error("triggerAttack not implemented");
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
triggerRelease(note: Note, triggeredAt: number) {
|
|
132
|
-
throw Error("triggerRelease not implemented");
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
midiTriggered = (midiEvent: MidiEvent, noteIndex?: number) => {
|
|
136
|
-
const { notes, triggeredAt } = midiEvent;
|
|
137
|
-
|
|
138
|
-
switch (midiEvent.type) {
|
|
139
|
-
case "noteOn":
|
|
140
|
-
const { duration } = notes[0];
|
|
141
|
-
|
|
142
|
-
this.triggerer(this.triggerAttack, notes, triggeredAt, noteIndex);
|
|
143
|
-
|
|
144
|
-
if (duration) {
|
|
145
|
-
const releaseTriggeredAt =
|
|
146
|
-
triggeredAt + (this.internalModule as any).toSeconds(duration);
|
|
147
|
-
this.triggerer(
|
|
148
|
-
this.triggerRelease,
|
|
149
|
-
notes,
|
|
150
|
-
releaseTriggeredAt,
|
|
151
|
-
noteIndex
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
break;
|
|
155
|
-
case "noteOff":
|
|
156
|
-
this.triggerer(this.triggerRelease, notes, triggeredAt, noteIndex);
|
|
157
|
-
break;
|
|
158
|
-
default:
|
|
159
|
-
throw Error("This type is not a note");
|
|
160
|
-
}
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
private triggerer(
|
|
164
|
-
trigger: Function,
|
|
165
|
-
notes: Note[],
|
|
166
|
-
triggeredAt: number,
|
|
167
|
-
noteIndex?: number
|
|
168
|
-
) {
|
|
169
|
-
if (noteIndex !== undefined && this.voiceNo !== undefined) {
|
|
170
|
-
trigger(notes[noteIndex], triggeredAt);
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
notes.forEach((note) => trigger(note, triggeredAt));
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
serialize() {
|
|
178
|
-
const klass = this.constructor as typeof Module;
|
|
179
|
-
|
|
180
|
-
return {
|
|
181
|
-
id: this.id,
|
|
182
|
-
name: this.name,
|
|
183
|
-
type: klass.moduleName,
|
|
184
|
-
props: this.props,
|
|
185
|
-
inputs: this.inputs.map((i) => i.serialize()),
|
|
186
|
-
outputs: this.outputs.map((i) => i.serialize()),
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
protected registerInput(props: IOInterface): Input {
|
|
191
|
-
const input = new Input(this, props);
|
|
192
|
-
this.inputs.push(input);
|
|
193
|
-
|
|
194
|
-
return input;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
protected registerOutput(props: IOInterface): Output {
|
|
198
|
-
const output = new Output(this, props);
|
|
199
|
-
this.outputs.push(output);
|
|
200
|
-
|
|
201
|
-
return output;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
protected registerBasicOutputs() {
|
|
205
|
-
this.registerOutput({
|
|
206
|
-
name: "output",
|
|
207
|
-
onPlug: (output: Output) => {
|
|
208
|
-
this.connect(output.audioModule);
|
|
209
|
-
},
|
|
210
|
-
onUnPlug: (output: Output) => {
|
|
211
|
-
this.disconnect(output.audioModule);
|
|
212
|
-
},
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
protected registerBasicInputs() {
|
|
217
|
-
this.registerInput({
|
|
218
|
-
name: "input",
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export default Module;
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { Loop, now } from "tone";
|
|
2
|
-
|
|
3
|
-
import Module, { DummnyInternalModule } from "./Base";
|
|
4
|
-
import { Output } from "./IO";
|
|
5
|
-
import MidiEvent from "../MidiEvent";
|
|
6
|
-
import { sortBy, uniq } from "lodash";
|
|
7
|
-
import Engine from "../Engine";
|
|
8
|
-
|
|
9
|
-
interface IDataSequencer {
|
|
10
|
-
sequences: IDataSequence[];
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface IDataSequence {
|
|
14
|
-
voiceNo: number;
|
|
15
|
-
time: number;
|
|
16
|
-
frequency: number;
|
|
17
|
-
amplitude: number;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const InitialProps = () => ({
|
|
21
|
-
sequences: [],
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
export default class DataSequencer extends Module<
|
|
25
|
-
DummnyInternalModule,
|
|
26
|
-
IDataSequencer
|
|
27
|
-
> {
|
|
28
|
-
static moduleName = "DataSequencer";
|
|
29
|
-
private midiOutput: Output;
|
|
30
|
-
private prevNumberOfVoices: number;
|
|
31
|
-
private loop: Loop;
|
|
32
|
-
|
|
33
|
-
constructor(name: string, props: Partial<IDataSequence>) {
|
|
34
|
-
super(new DummnyInternalModule(), {
|
|
35
|
-
name,
|
|
36
|
-
props: { ...InitialProps(), ...props },
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
this.start(now());
|
|
40
|
-
this.registerOutputs();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
get sequences() {
|
|
44
|
-
return this._props["sequences"];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
set sequences(value: IDataSequence[]) {
|
|
48
|
-
const sequences = sortBy(value, (seq) => -seq.time);
|
|
49
|
-
this._props = { ...this.props, sequences };
|
|
50
|
-
this.updateNumberOfVoices();
|
|
51
|
-
this.start(now());
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
start(time: number) {
|
|
55
|
-
if (!Engine.isStarted) return;
|
|
56
|
-
Engine.updateRoutes();
|
|
57
|
-
|
|
58
|
-
const loopLength = 0.1;
|
|
59
|
-
const tempSequences = [...this.sequences];
|
|
60
|
-
const iterate = (maxTime: number) => {
|
|
61
|
-
const sequence = tempSequences.pop();
|
|
62
|
-
if (!sequence) return;
|
|
63
|
-
|
|
64
|
-
const seqTime = time + sequence.time;
|
|
65
|
-
this.onPartEvent(seqTime, sequence);
|
|
66
|
-
if (seqTime > maxTime) return;
|
|
67
|
-
|
|
68
|
-
iterate(maxTime);
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
this.loop = new Loop((t) => {
|
|
72
|
-
iterate(time + t + loopLength);
|
|
73
|
-
}, loopLength).start(time);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
stop() {
|
|
77
|
-
if (!this.loop) return;
|
|
78
|
-
|
|
79
|
-
this.loop.stop();
|
|
80
|
-
this.loop.dispose();
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
private onPartEvent = (time: number, sequence: IDataSequence) => {
|
|
84
|
-
const { voiceNo } = sequence;
|
|
85
|
-
const event = MidiEvent.fromDataSequence(sequence, time);
|
|
86
|
-
|
|
87
|
-
this.midiOutput.connections.forEach((input) => {
|
|
88
|
-
input.pluggable(event, voiceNo);
|
|
89
|
-
});
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
private get numberOfVoices() {
|
|
93
|
-
return uniq(this.sequences.map((sequence) => sequence.voiceNo)).length;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
private updateNumberOfVoices() {
|
|
97
|
-
if (!this.midiOutput) return;
|
|
98
|
-
|
|
99
|
-
this.midiOutput.connections.forEach((input) => {
|
|
100
|
-
if (input.audioModule instanceof Module) return;
|
|
101
|
-
|
|
102
|
-
input.audioModule.numberOfVoices = this.numberOfVoices;
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
if (this.prevNumberOfVoices !== this.numberOfVoices) {
|
|
106
|
-
Engine.updateRoutes();
|
|
107
|
-
}
|
|
108
|
-
this.prevNumberOfVoices = this.numberOfVoices;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
private registerOutputs() {
|
|
112
|
-
this.midiOutput = this.registerOutput({
|
|
113
|
-
name: "midi out",
|
|
114
|
-
onPlug: (input) => {
|
|
115
|
-
if (input.audioModule instanceof Module) return;
|
|
116
|
-
|
|
117
|
-
input.audioModule.numberOfVoices = this.numberOfVoices;
|
|
118
|
-
},
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { AmplitudeEnvelope } from "tone";
|
|
2
|
-
|
|
3
|
-
import Base, { EnvelopeInterface, PolyBase } from "./Base";
|
|
4
|
-
|
|
5
|
-
class MonoAmpEnvelope extends Base<AmplitudeEnvelope> {
|
|
6
|
-
constructor(name: string, props: EnvelopeInterface) {
|
|
7
|
-
super(name, new AmplitudeEnvelope(), props);
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export default class AmpEnvelope extends PolyBase<MonoAmpEnvelope> {
|
|
12
|
-
static moduleName = "AmpEnvelope";
|
|
13
|
-
|
|
14
|
-
constructor(name: string, props: Partial<EnvelopeInterface>) {
|
|
15
|
-
super(name, MonoAmpEnvelope, props);
|
|
16
|
-
}
|
|
17
|
-
}
|
package/src/Module/IO.ts
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
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
|
-
this.connections.push(io);
|
|
43
|
-
|
|
44
|
-
if (this.onPlug) this.onPlug(io);
|
|
45
|
-
|
|
46
|
-
if (this.ioType === IOType.Output) io.plug(this);
|
|
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
|
-
}
|