@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.
Files changed (47) hide show
  1. package/build/Engine.d.ts +5 -0
  2. package/build/Engine.js +30 -2
  3. package/build/Engine.js.map +1 -1
  4. package/build/MidiEvent.d.ts +2 -0
  5. package/build/MidiEvent.js +8 -0
  6. package/build/MidiEvent.js.map +1 -1
  7. package/build/Module/Base.d.ts +0 -2
  8. package/build/Module/Base.js +9 -7
  9. package/build/Module/Base.js.map +1 -1
  10. package/build/Module/DataSequencer.d.ts +24 -0
  11. package/build/Module/DataSequencer.js +64 -0
  12. package/build/Module/DataSequencer.js.map +1 -0
  13. package/build/Module/Envelope/Base.d.ts +0 -1
  14. package/build/Module/Envelope/Base.js +1 -10
  15. package/build/Module/Envelope/Base.js.map +1 -1
  16. package/build/Module/Oscillator.d.ts +5 -2
  17. package/build/Module/Oscillator.js +26 -11
  18. package/build/Module/Oscillator.js.map +1 -1
  19. package/build/Module/PolyModule.d.ts +1 -1
  20. package/build/Module/PolyModule.js +1 -1
  21. package/build/Module/PolyModule.js.map +1 -1
  22. package/build/Module/Sequencer.d.ts +5 -2
  23. package/build/Module/Sequencer.js +31 -21
  24. package/build/Module/Sequencer.js.map +1 -1
  25. package/build/Module/Volume.d.ts +4 -0
  26. package/build/Module/Volume.js +15 -1
  27. package/build/Module/Volume.js.map +1 -1
  28. package/build/Module/index.d.ts +2 -0
  29. package/build/Module/index.js +4 -0
  30. package/build/Module/index.js.map +1 -1
  31. package/build/Note/index.d.ts +5 -2
  32. package/build/Note/index.js +12 -2
  33. package/build/Note/index.js.map +1 -1
  34. package/build/index.d.ts +1 -1
  35. package/package.json +1 -1
  36. package/src/Engine.ts +36 -2
  37. package/src/MidiEvent.ts +14 -0
  38. package/src/Module/Base.ts +19 -10
  39. package/src/Module/DataSequencer.ts +92 -0
  40. package/src/Module/Envelope/Base.ts +1 -10
  41. package/src/Module/Oscillator.ts +28 -12
  42. package/src/Module/PolyModule.ts +1 -1
  43. package/src/Module/Sequencer.ts +35 -21
  44. package/src/Module/Volume.ts +19 -1
  45. package/src/Module/index.ts +5 -0
  46. package/src/Note/index.ts +17 -5
  47. package/src/index.ts +6 -1
@@ -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.note = new Note("C3");
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.start();
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.frequency(this.range, this.coarse);
136
+ const freq = this.note.adjustFrequency(this.range, this.coarse);
127
137
 
128
138
  if (time) {
129
- this.internalModule.restart(time);
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",
@@ -92,7 +92,7 @@ export default abstract class PolyModule<
92
92
 
93
93
  midiTriggered = (
94
94
  midiEvent: MidiEvent,
95
- voiceNo: number,
95
+ voiceNo: number = 0,
96
96
  noteIndex?: number
97
97
  ) => {
98
98
  const audioModule = this.findVoice(voiceNo);
@@ -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.start();
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 adjustNumberOfSequences(bar = 0) {
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.adjustNumberOfSequences(bar + 1);
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.adjustNumberOfSequences(bar);
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() {
@@ -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: -100,
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
  }
@@ -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
- constructor(eventOrString: Partial<INote> | MIDIMessageEvent | string) {
21
- if (typeof eventOrString === "string") {
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
- frequency(range: number = 0, coarse: number = 0) {
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 { ModuleInterface, AudioModule, ISequence } from "./Module";
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";