@blibliki/engine 0.5.2 → 0.9.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 (47) hide show
  1. package/README.md +22 -2
  2. package/dist/index.d.ts +501 -107
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/package.json +7 -7
  6. package/src/Engine.ts +46 -29
  7. package/src/core/index.ts +11 -2
  8. package/src/core/midi/BaseMidiDevice.ts +47 -0
  9. package/src/core/midi/ComputerKeyboardDevice.ts +2 -1
  10. package/src/core/midi/MidiDeviceManager.ts +125 -31
  11. package/src/core/midi/{MidiDevice.ts → MidiInputDevice.ts} +6 -30
  12. package/src/core/midi/MidiOutputDevice.ts +23 -0
  13. package/src/core/midi/adapters/NodeMidiAdapter.ts +99 -13
  14. package/src/core/midi/adapters/WebMidiAdapter.ts +68 -10
  15. package/src/core/midi/adapters/types.ts +13 -4
  16. package/src/core/midi/controllers/BaseController.ts +14 -0
  17. package/src/core/module/Module.ts +121 -13
  18. package/src/core/module/PolyModule.ts +36 -0
  19. package/src/core/module/VoiceScheduler.ts +150 -10
  20. package/src/core/module/index.ts +9 -4
  21. package/src/index.ts +27 -3
  22. package/src/modules/Chorus.ts +222 -0
  23. package/src/modules/Constant.ts +2 -2
  24. package/src/modules/Delay.ts +347 -0
  25. package/src/modules/Distortion.ts +182 -0
  26. package/src/modules/Envelope.ts +158 -92
  27. package/src/modules/Filter.ts +7 -7
  28. package/src/modules/Gain.ts +2 -2
  29. package/src/modules/LFO.ts +287 -0
  30. package/src/modules/LegacyEnvelope.ts +146 -0
  31. package/src/modules/{MidiSelector.ts → MidiInput.ts} +26 -19
  32. package/src/modules/MidiMapper.ts +59 -4
  33. package/src/modules/MidiOutput.ts +121 -0
  34. package/src/modules/Noise.ts +259 -0
  35. package/src/modules/Oscillator.ts +9 -3
  36. package/src/modules/Reverb.ts +379 -0
  37. package/src/modules/Scale.ts +49 -4
  38. package/src/modules/StepSequencer.ts +410 -22
  39. package/src/modules/StereoPanner.ts +1 -1
  40. package/src/modules/index.ts +142 -29
  41. package/src/processors/custom-envelope-processor.ts +125 -0
  42. package/src/processors/index.ts +10 -0
  43. package/src/processors/lfo-processor.ts +123 -0
  44. package/src/processors/scale-processor.ts +42 -5
  45. package/src/utils/WetDryMixer.ts +123 -0
  46. package/src/utils/expandPatternSequence.ts +18 -0
  47. package/src/utils/index.ts +2 -0
@@ -0,0 +1,123 @@
1
+ import { Context } from "@blibliki/utils";
2
+
3
+ /**
4
+ * WetDryMixer - Reusable wet/dry signal mixer for audio effects
5
+ *
6
+ * Provides equal-power crossfading between dry (unprocessed) and wet (processed) signals.
7
+ * Used by effects modules to blend the original signal with the effect output.
8
+ *
9
+ * Audio Graph:
10
+ * ```
11
+ * INPUT
12
+ * |
13
+ * +------------+------------+
14
+ * | |
15
+ * [DryGainNode] [WetGainNode]
16
+ * (cos(mix*π/2)) (sin(mix*π/2))
17
+ * | |
18
+ * +------------+------------+
19
+ * |
20
+ * [OutputNode]
21
+ * ```
22
+ *
23
+ * Usage:
24
+ * ```typescript
25
+ * const mixer = new WetDryMixer(context);
26
+ *
27
+ * // Connect input to mixer
28
+ * mixer.connectInput(sourceNode);
29
+ *
30
+ * // Get wet input node and connect effect chain
31
+ * const wetInput = mixer.getWetInput();
32
+ * sourceNode.connect(effectNode);
33
+ * effectNode.connect(wetInput);
34
+ *
35
+ * // Set mix amount
36
+ * mixer.setMix(0.5); // 50/50 blend
37
+ *
38
+ * // Connect output
39
+ * const output = mixer.getOutput();
40
+ * output.connect(destination);
41
+ * ```
42
+ */
43
+ export class WetDryMixer {
44
+ private dryGainNode: GainNode;
45
+ private wetGainNode: GainNode;
46
+ private outputNode: GainNode;
47
+
48
+ constructor(context: Context) {
49
+ const audioContext = context.audioContext;
50
+
51
+ // Create nodes
52
+ this.dryGainNode = audioContext.createGain();
53
+ this.wetGainNode = audioContext.createGain();
54
+ this.outputNode = audioContext.createGain();
55
+
56
+ // Initialize gains
57
+ this.dryGainNode.gain.value = 1; // Full dry initially
58
+ this.wetGainNode.gain.value = 0; // No wet initially
59
+ this.outputNode.gain.value = 1; // Unity output
60
+
61
+ // Connect to output
62
+ this.dryGainNode.connect(this.outputNode);
63
+ this.wetGainNode.connect(this.outputNode);
64
+ }
65
+
66
+ /**
67
+ * Connect an audio source to the dry path.
68
+ * The source should also be connected separately to the wet path processing.
69
+ */
70
+ connectInput(source: AudioNode): void {
71
+ source.connect(this.dryGainNode);
72
+ }
73
+
74
+ /**
75
+ * Get the wet input node to connect your effect chain to.
76
+ * Connect your effect output to this node.
77
+ */
78
+ getWetInput(): GainNode {
79
+ return this.wetGainNode;
80
+ }
81
+
82
+ /**
83
+ * Get the dry input node (for special routing needs).
84
+ */
85
+ getDryInput(): GainNode {
86
+ return this.dryGainNode;
87
+ }
88
+
89
+ /**
90
+ * Get the output node to connect to destination.
91
+ */
92
+ getOutput(): GainNode {
93
+ return this.outputNode;
94
+ }
95
+
96
+ /**
97
+ * Set the mix amount between dry and wet signals.
98
+ * Uses equal-power crossfade to maintain constant perceived loudness.
99
+ *
100
+ * @param mix - Mix amount (0-1)
101
+ * - 0 = 100% dry (no effect)
102
+ * - 0.5 = 50/50 blend
103
+ * - 1 = 100% wet (full effect)
104
+ */
105
+ setMix(mix: number): void {
106
+ // Equal-power crossfade
107
+ // This maintains constant perceived loudness across all mix values
108
+ const dryGain = Math.cos((mix * Math.PI) / 2);
109
+ const wetGain = Math.sin((mix * Math.PI) / 2);
110
+
111
+ this.dryGainNode.gain.value = dryGain;
112
+ this.wetGainNode.gain.value = wetGain;
113
+ }
114
+
115
+ /**
116
+ * Disconnect all nodes (cleanup).
117
+ */
118
+ disconnect(): void {
119
+ this.dryGainNode.disconnect();
120
+ this.wetGainNode.disconnect();
121
+ this.outputNode.disconnect();
122
+ }
123
+ }
@@ -0,0 +1,18 @@
1
+ export function expandPatternSequence(input: string): string[] {
2
+ const result: string[] = [];
3
+ let num = "";
4
+
5
+ for (const ch of input) {
6
+ if (ch >= "0" && ch <= "9") {
7
+ num += ch;
8
+ } else {
9
+ const count = Number(num);
10
+ for (let i = 0; i < count; i++) {
11
+ result.push(ch);
12
+ }
13
+ num = "";
14
+ }
15
+ }
16
+
17
+ return result.map((v) => v.toUpperCase());
18
+ }
@@ -0,0 +1,2 @@
1
+ export { WetDryMixer } from "./WetDryMixer";
2
+ export { expandPatternSequence } from "./expandPatternSequence";