@blibliki/engine 0.1.11 → 0.1.13
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 +5 -0
- package/build/Engine.js +30 -2
- package/build/Engine.js.map +1 -1
- package/build/MidiEvent.d.ts +2 -0
- package/build/MidiEvent.js +8 -0
- package/build/MidiEvent.js.map +1 -1
- package/build/Module/Base.d.ts +0 -2
- package/build/Module/Base.js +9 -7
- package/build/Module/Base.js.map +1 -1
- package/build/Module/DataSequencer.d.ts +24 -0
- package/build/Module/DataSequencer.js +64 -0
- package/build/Module/DataSequencer.js.map +1 -0
- package/build/Module/Envelope/Base.d.ts +0 -1
- package/build/Module/Envelope/Base.js +1 -10
- package/build/Module/Envelope/Base.js.map +1 -1
- package/build/Module/Oscillator.d.ts +5 -2
- package/build/Module/Oscillator.js +26 -11
- package/build/Module/Oscillator.js.map +1 -1
- package/build/Module/PolyModule.d.ts +1 -1
- package/build/Module/PolyModule.js +1 -1
- package/build/Module/PolyModule.js.map +1 -1
- package/build/Module/Sequencer.d.ts +5 -2
- package/build/Module/Sequencer.js +31 -21
- package/build/Module/Sequencer.js.map +1 -1
- package/build/Module/Volume.d.ts +4 -0
- package/build/Module/Volume.js +15 -1
- package/build/Module/Volume.js.map +1 -1
- package/build/Module/index.d.ts +2 -0
- package/build/Module/index.js +4 -0
- package/build/Module/index.js.map +1 -1
- package/build/Note/index.d.ts +5 -2
- package/build/Note/index.js +12 -2
- package/build/Note/index.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/Engine.ts +36 -2
- package/src/MidiEvent.ts +14 -0
- package/src/Module/Base.ts +19 -10
- package/src/Module/DataSequencer.ts +92 -0
- package/src/Module/Envelope/Base.ts +1 -10
- package/src/Module/Oscillator.ts +28 -12
- package/src/Module/PolyModule.ts +1 -1
- package/src/Module/Sequencer.ts +35 -21
- package/src/Module/Volume.ts +19 -1
- package/src/Module/index.ts +5 -0
- package/src/Note/index.ts +17 -5
- package/src/index.ts +6 -1
package/src/Module/Oscillator.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import MidiEvent from "../MidiEvent";
|
|
2
1
|
import { now, Oscillator as Osc, ToneOscillatorType } from "tone";
|
|
3
2
|
|
|
4
3
|
import Note from "../Note";
|
|
@@ -32,10 +31,7 @@ class MonoOscillator extends Module<Osc, OscillatorInterface> {
|
|
|
32
31
|
props: { ...InitialProps, ...props },
|
|
33
32
|
});
|
|
34
33
|
|
|
35
|
-
this.
|
|
36
|
-
|
|
37
|
-
this.internalModule.sync();
|
|
38
|
-
this.internalModule.start();
|
|
34
|
+
this.start(now());
|
|
39
35
|
}
|
|
40
36
|
|
|
41
37
|
get note(): Note {
|
|
@@ -108,28 +104,40 @@ class MonoOscillator extends Module<Osc, OscillatorInterface> {
|
|
|
108
104
|
this.updateFrequency();
|
|
109
105
|
}
|
|
110
106
|
|
|
111
|
-
start() {
|
|
112
|
-
this.internalModule.
|
|
107
|
+
start(time: number) {
|
|
108
|
+
const state = this.internalModule.context.transport.state;
|
|
109
|
+
if (state !== "started") return;
|
|
110
|
+
|
|
111
|
+
const oscState = this.internalModule.state;
|
|
112
|
+
|
|
113
|
+
if (oscState === "started") {
|
|
114
|
+
this.internalModule.restart(time);
|
|
115
|
+
} else {
|
|
116
|
+
this.internalModule.start(time);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
stop(time?: number) {
|
|
121
|
+
this.internalModule.stop(time);
|
|
113
122
|
}
|
|
114
123
|
|
|
115
124
|
triggerAttack = (note: Note, triggeredAt: number) => {
|
|
116
125
|
this.setNoteAt(note, triggeredAt);
|
|
126
|
+
this.start(triggeredAt);
|
|
117
127
|
};
|
|
118
128
|
|
|
119
|
-
triggerRelease = (note: Note) => {
|
|
129
|
+
triggerRelease = (note: Note, triggeredAt: number) => {
|
|
120
130
|
// Do nothing
|
|
121
131
|
};
|
|
122
132
|
|
|
123
133
|
private updateFrequency(time?: number) {
|
|
124
134
|
if (!this.note) return;
|
|
125
135
|
|
|
126
|
-
const freq = this.note.
|
|
136
|
+
const freq = this.note.adjustFrequency(this.range, this.coarse);
|
|
127
137
|
|
|
128
138
|
if (time) {
|
|
129
|
-
this.internalModule.
|
|
130
|
-
this.internalModule.frequency.setValueAtTime(freq, time);
|
|
139
|
+
this.internalModule.frequency.linearRampToValueAtTime(freq, time);
|
|
131
140
|
} else {
|
|
132
|
-
this.internalModule.restart();
|
|
133
141
|
this.internalModule.frequency.value = freq;
|
|
134
142
|
}
|
|
135
143
|
}
|
|
@@ -156,6 +164,14 @@ export default class Oscillator extends PolyModule<
|
|
|
156
164
|
this.registerInputs();
|
|
157
165
|
}
|
|
158
166
|
|
|
167
|
+
start(time: number) {
|
|
168
|
+
this.audioModules.forEach((audioModule) => audioModule.start(time));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
stop(time?: number) {
|
|
172
|
+
this.audioModules.forEach((audioModule) => audioModule.stop(time));
|
|
173
|
+
}
|
|
174
|
+
|
|
159
175
|
private registerInputs() {
|
|
160
176
|
this.registerInput({
|
|
161
177
|
name: "midi in",
|
package/src/Module/PolyModule.ts
CHANGED
package/src/Module/Sequencer.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Part, Time } from "tone";
|
|
1
|
+
import { now, Part, Time } from "tone";
|
|
2
2
|
import Module, { DummnyInternalModule } from "./Base";
|
|
3
3
|
import { INote } from "../Note";
|
|
4
4
|
import { Output } from "./IO";
|
|
@@ -37,18 +37,27 @@ export default class Sequencer extends Module<
|
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
this.initializePart();
|
|
40
|
-
this.start();
|
|
40
|
+
this.start(now());
|
|
41
41
|
this.registerOutputs();
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
get props() {
|
|
45
|
+
return super.props;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
set props(value: ISequencer) {
|
|
49
|
+
if (!this.sequences) this._props["sequences"] = [];
|
|
50
|
+
|
|
51
|
+
super.props = { ...this.props, ...value };
|
|
52
|
+
this.adjust();
|
|
53
|
+
}
|
|
54
|
+
|
|
44
55
|
get steps() {
|
|
45
56
|
return this._props["steps"];
|
|
46
57
|
}
|
|
47
58
|
|
|
48
59
|
set steps(value: number) {
|
|
49
60
|
this._props = { ...this.props, steps: value };
|
|
50
|
-
this.adjustNumberOfSequences();
|
|
51
|
-
this.updateBarParts();
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
get bars() {
|
|
@@ -57,9 +66,6 @@ export default class Sequencer extends Module<
|
|
|
57
66
|
|
|
58
67
|
set bars(value: number) {
|
|
59
68
|
this._props = { ...this.props, bars: value };
|
|
60
|
-
this.adjustNumberOfBars();
|
|
61
|
-
this.adjustNumberOfSequences();
|
|
62
|
-
this.updateBarParts();
|
|
63
69
|
}
|
|
64
70
|
|
|
65
71
|
get sequences() {
|
|
@@ -69,11 +75,13 @@ export default class Sequencer extends Module<
|
|
|
69
75
|
set sequences(value: ISequence[][]) {
|
|
70
76
|
const sequences = value;
|
|
71
77
|
this._props = { ...this.props, sequences };
|
|
72
|
-
this.updateBarParts();
|
|
73
78
|
}
|
|
74
79
|
|
|
75
|
-
start() {
|
|
76
|
-
this.part.
|
|
80
|
+
start(time: number) {
|
|
81
|
+
const state = this.part.context.transport.state;
|
|
82
|
+
if (state !== "started") return;
|
|
83
|
+
|
|
84
|
+
this.part.start(time);
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
stop() {
|
|
@@ -94,6 +102,14 @@ export default class Sequencer extends Module<
|
|
|
94
102
|
});
|
|
95
103
|
}
|
|
96
104
|
|
|
105
|
+
private adjust() {
|
|
106
|
+
if (!this.part) return;
|
|
107
|
+
|
|
108
|
+
this.adjustNumberOfBars();
|
|
109
|
+
this.adjustNumberOfSteps();
|
|
110
|
+
this.updateBarParts();
|
|
111
|
+
}
|
|
112
|
+
|
|
97
113
|
private adjustNumberOfBars() {
|
|
98
114
|
const currentBar = this.sequences.length;
|
|
99
115
|
const num = currentBar - this.bars;
|
|
@@ -102,16 +118,8 @@ export default class Sequencer extends Module<
|
|
|
102
118
|
if (num === 0) return;
|
|
103
119
|
|
|
104
120
|
if (num > 0) {
|
|
105
|
-
if (this.part) {
|
|
106
|
-
this.part.remove(`${currentBar}:0:0`);
|
|
107
|
-
this.part.loopEnd = this.loopEnd;
|
|
108
|
-
}
|
|
109
121
|
sequences.pop();
|
|
110
122
|
} else {
|
|
111
|
-
if (this.part) {
|
|
112
|
-
this.part.add(`${currentBar}:0:0`, currentBar);
|
|
113
|
-
this.part.loopEnd = this.loopEnd;
|
|
114
|
-
}
|
|
115
123
|
sequences.push([]);
|
|
116
124
|
}
|
|
117
125
|
|
|
@@ -119,7 +127,7 @@ export default class Sequencer extends Module<
|
|
|
119
127
|
this.adjustNumberOfBars();
|
|
120
128
|
}
|
|
121
129
|
|
|
122
|
-
private
|
|
130
|
+
private adjustNumberOfSteps(bar = 0) {
|
|
123
131
|
if (!this.bars) return;
|
|
124
132
|
|
|
125
133
|
const allSequences = [...this.sequences];
|
|
@@ -129,7 +137,7 @@ export default class Sequencer extends Module<
|
|
|
129
137
|
if (num === 0) {
|
|
130
138
|
if (bar === this.bars - 1) return;
|
|
131
139
|
|
|
132
|
-
this.
|
|
140
|
+
this.adjustNumberOfSteps(bar + 1);
|
|
133
141
|
return;
|
|
134
142
|
}
|
|
135
143
|
|
|
@@ -142,7 +150,7 @@ export default class Sequencer extends Module<
|
|
|
142
150
|
allSequences[bar] = sequences;
|
|
143
151
|
this.sequences = allSequences;
|
|
144
152
|
|
|
145
|
-
this.
|
|
153
|
+
this.adjustNumberOfSteps(bar);
|
|
146
154
|
}
|
|
147
155
|
|
|
148
156
|
private updateBarParts() {
|
|
@@ -152,6 +160,12 @@ export default class Sequencer extends Module<
|
|
|
152
160
|
|
|
153
161
|
return part;
|
|
154
162
|
});
|
|
163
|
+
|
|
164
|
+
this.part.clear();
|
|
165
|
+
this.barParts.forEach((_, bar) => {
|
|
166
|
+
this.part.add(`${bar}:0:0`, bar);
|
|
167
|
+
});
|
|
168
|
+
this.part.loopEnd = this.loopEnd;
|
|
155
169
|
}
|
|
156
170
|
|
|
157
171
|
private get loopEnd() {
|
package/src/Module/Volume.ts
CHANGED
|
@@ -2,13 +2,14 @@ import { Volume as Vol } from "tone";
|
|
|
2
2
|
|
|
3
3
|
import Module, { Voicable } from "./Base";
|
|
4
4
|
import PolyModule from "./PolyModule";
|
|
5
|
+
import Note from "../Note";
|
|
5
6
|
|
|
6
7
|
export interface VolumeInterface extends Voicable {
|
|
7
8
|
volume: number;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
const InitialProps: VolumeInterface = {
|
|
11
|
-
volume: -
|
|
12
|
+
volume: -Infinity,
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
class MonoVolume extends Module<Vol, VolumeInterface> {
|
|
@@ -28,6 +29,15 @@ class MonoVolume extends Module<Vol, VolumeInterface> {
|
|
|
28
29
|
|
|
29
30
|
this.internalModule.volume.value = this.volume;
|
|
30
31
|
}
|
|
32
|
+
|
|
33
|
+
triggerAttack = (note: Note, triggeredAt: number) => {
|
|
34
|
+
const db = 20 * Math.log10(note.velocity);
|
|
35
|
+
this.internalModule.volume.exponentialRampToValueAtTime(db, triggeredAt);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
triggerRelease = (note: Note, triggeredAt: number) => {
|
|
39
|
+
// Do nothing
|
|
40
|
+
};
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
export default class Volume extends PolyModule<MonoVolume, VolumeInterface> {
|
|
@@ -42,5 +52,13 @@ export default class Volume extends PolyModule<MonoVolume, VolumeInterface> {
|
|
|
42
52
|
|
|
43
53
|
this.registerBasicInputs();
|
|
44
54
|
this.registerBasicOutputs();
|
|
55
|
+
this.registerInputs();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private registerInputs() {
|
|
59
|
+
this.registerInput({
|
|
60
|
+
name: "midi in",
|
|
61
|
+
pluggable: this.midiTriggered,
|
|
62
|
+
});
|
|
45
63
|
}
|
|
46
64
|
}
|
package/src/Module/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ import Delay from "./Delay";
|
|
|
14
14
|
import Distortion from "./Distortion";
|
|
15
15
|
import BitCrusher from "./BitCrusher";
|
|
16
16
|
import Sequencer from "./Sequencer";
|
|
17
|
+
import DataSequencer from "./DataSequencer";
|
|
17
18
|
|
|
18
19
|
export { default } from "./Base";
|
|
19
20
|
export { default as PolyModule } from "./PolyModule";
|
|
@@ -22,7 +23,9 @@ export type { ModuleInterface, Connectable, Triggerable } from "./Base";
|
|
|
22
23
|
export { default as Filter } from "./Filter";
|
|
23
24
|
export { default as Oscillator } from "./Oscillator";
|
|
24
25
|
export { default as Sequencer } from "./Sequencer";
|
|
26
|
+
export { default as DataSequencer } from "./DataSequencer";
|
|
25
27
|
export type { ISequence } from "./Sequencer";
|
|
28
|
+
export type { IDataSequence } from "./DataSequencer";
|
|
26
29
|
|
|
27
30
|
export {
|
|
28
31
|
Envelope,
|
|
@@ -79,6 +82,8 @@ function moduleClassFromType(type: string) {
|
|
|
79
82
|
return BitCrusher;
|
|
80
83
|
case Sequencer.moduleName:
|
|
81
84
|
return Sequencer;
|
|
85
|
+
case DataSequencer.moduleName:
|
|
86
|
+
return DataSequencer;
|
|
82
87
|
default:
|
|
83
88
|
throw Error(`Unknown module type ${type}`);
|
|
84
89
|
}
|
package/src/Note/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ const NotesLength = Notes.length;
|
|
|
6
6
|
|
|
7
7
|
export interface INote {
|
|
8
8
|
note: string;
|
|
9
|
+
frequency: number;
|
|
9
10
|
duration: string;
|
|
10
11
|
velocity?: number;
|
|
11
12
|
}
|
|
@@ -16,9 +17,14 @@ export default class Note {
|
|
|
16
17
|
octave: number;
|
|
17
18
|
velocity: number = 1;
|
|
18
19
|
duration: string;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
frequency: number;
|
|
21
|
+
|
|
22
|
+
constructor(
|
|
23
|
+
eventOrString: Partial<INote> | MIDIMessageEvent | string | number
|
|
24
|
+
) {
|
|
25
|
+
if (typeof eventOrString === "number") {
|
|
26
|
+
this.fromFrequency(eventOrString);
|
|
27
|
+
} else if (typeof eventOrString === "string") {
|
|
22
28
|
this.fromString(eventOrString);
|
|
23
29
|
} else if (eventOrString instanceof MIDIMessageEvent) {
|
|
24
30
|
this.fromEvent(eventOrString);
|
|
@@ -39,7 +45,9 @@ export default class Note {
|
|
|
39
45
|
return `${this.name}${this.octave}`;
|
|
40
46
|
}
|
|
41
47
|
|
|
42
|
-
|
|
48
|
+
adjustFrequency(range: number = 0, coarse: number = 0) {
|
|
49
|
+
if (this.frequency) return this.frequency;
|
|
50
|
+
|
|
43
51
|
let newOctave = this.octave + range;
|
|
44
52
|
let coarseIndex = Notes.indexOf(this.name) + coarse;
|
|
45
53
|
let nameIndex = coarseIndex;
|
|
@@ -51,7 +59,6 @@ export default class Note {
|
|
|
51
59
|
newOctave--;
|
|
52
60
|
nameIndex = NotesLength + nameIndex;
|
|
53
61
|
}
|
|
54
|
-
|
|
55
62
|
const newName = Notes[nameIndex];
|
|
56
63
|
|
|
57
64
|
return frequencyTable[`${newName}${newOctave}`];
|
|
@@ -64,11 +71,16 @@ export default class Note {
|
|
|
64
71
|
serialize(): INote {
|
|
65
72
|
return {
|
|
66
73
|
note: this.fullName,
|
|
74
|
+
frequency: this.frequency,
|
|
67
75
|
velocity: this.velocity,
|
|
68
76
|
duration: this.duration,
|
|
69
77
|
};
|
|
70
78
|
}
|
|
71
79
|
|
|
80
|
+
private fromFrequency(frequency: number) {
|
|
81
|
+
this.frequency = frequency;
|
|
82
|
+
}
|
|
83
|
+
|
|
72
84
|
private fromString(string: string) {
|
|
73
85
|
const matches = string.match(/(\w#?)(\d)?/) || [];
|
|
74
86
|
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,11 @@ export { default as Note } from "./Note";
|
|
|
5
5
|
|
|
6
6
|
export type { INote } from "./Note";
|
|
7
7
|
export type { MidiDeviceInterface } from "./MidiDevice";
|
|
8
|
-
export type {
|
|
8
|
+
export type {
|
|
9
|
+
ModuleInterface,
|
|
10
|
+
AudioModule,
|
|
11
|
+
ISequence,
|
|
12
|
+
IDataSequence,
|
|
13
|
+
} from "./Module";
|
|
9
14
|
|
|
10
15
|
export type { SerializeInterface as IOProps } from "./Module/IO";
|