@blibliki/engine 0.3.5 → 0.3.7
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/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +205 -70
- package/dist/index.d.ts +205 -70
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/src/Engine.ts +10 -4
- package/src/core/IO/Collection.ts +4 -1
- package/src/core/index.ts +7 -2
- package/src/core/midi/MidiDevice.ts +1 -0
- package/src/core/midi/MidiEvent.ts +17 -1
- package/src/core/module/Module.ts +114 -23
- package/src/core/module/PolyModule.ts +27 -2
- package/src/core/module/VoiceScheduler.ts +3 -2
- package/src/core/module/index.ts +1 -1
- package/src/core/schema.ts +53 -8
- package/src/index.ts +10 -2
- package/src/modules/Constant.ts +10 -6
- package/src/modules/Envelope.ts +21 -38
- package/src/modules/Filter.ts +58 -39
- package/src/modules/Gain.ts +8 -6
- package/src/modules/Inspector.ts +16 -6
- package/src/modules/Master.ts +2 -3
- package/src/modules/MidiMapper.ts +292 -0
- package/src/modules/MidiSelector.ts +13 -8
- package/src/modules/Oscillator.ts +38 -21
- package/src/modules/Scale.ts +19 -10
- package/src/modules/StepSequencer.ts +2 -2
- package/src/modules/StereoPanner.ts +86 -0
- package/src/modules/VirtualMidi.ts +2 -2
- package/src/modules/index.ts +26 -15
- package/src/modules/BiquadFilter.ts +0 -162
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { IModule, Module, MidiOutput } from "@/core";
|
|
1
|
+
import { IModule, Module, MidiOutput, SetterHooks } from "@/core";
|
|
2
2
|
import MidiEvent from "@/core/midi/MidiEvent";
|
|
3
|
-
import {
|
|
3
|
+
import { ModulePropSchema } from "@/core/schema";
|
|
4
4
|
import { ICreateModule, ModuleType } from ".";
|
|
5
5
|
|
|
6
6
|
export type IMidiSelector = IModule<ModuleType.MidiSelector>;
|
|
@@ -8,7 +8,7 @@ export type IMidiSelectorProps = {
|
|
|
8
8
|
selectedId: string | undefined | null;
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
export const midiSelectorPropSchema:
|
|
11
|
+
export const midiSelectorPropSchema: ModulePropSchema<IMidiSelectorProps> = {
|
|
12
12
|
selectedId: {
|
|
13
13
|
kind: "string",
|
|
14
14
|
label: "Midi device ID",
|
|
@@ -17,7 +17,10 @@ export const midiSelectorPropSchema: PropSchema<IMidiSelectorProps> = {
|
|
|
17
17
|
|
|
18
18
|
const DEFAULT_PROPS: IMidiSelectorProps = { selectedId: undefined };
|
|
19
19
|
|
|
20
|
-
export default class MidiSelector
|
|
20
|
+
export default class MidiSelector
|
|
21
|
+
extends Module<ModuleType.MidiSelector>
|
|
22
|
+
implements Pick<SetterHooks<IMidiSelectorProps>, "onSetSelectedId">
|
|
23
|
+
{
|
|
21
24
|
declare audioNode: undefined;
|
|
22
25
|
midiOutput!: MidiOutput;
|
|
23
26
|
_forwardMidiEvent?: (midiEvent: MidiEvent) => void;
|
|
@@ -38,12 +41,14 @@ export default class MidiSelector extends Module<ModuleType.MidiSelector> {
|
|
|
38
41
|
this.registerOutputs();
|
|
39
42
|
}
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
onSetSelectedId: SetterHooks<IMidiSelectorProps>["onSetSelectedId"] = (
|
|
45
|
+
value,
|
|
46
|
+
) => {
|
|
44
47
|
this.removeEventListener();
|
|
45
48
|
this.addEventListener(value);
|
|
46
|
-
|
|
49
|
+
|
|
50
|
+
return value;
|
|
51
|
+
};
|
|
47
52
|
|
|
48
53
|
private get forwardMidiEvent() {
|
|
49
54
|
if (this._forwardMidiEvent) return this._forwardMidiEvent;
|
|
@@ -2,9 +2,9 @@ import { ContextTime } from "@blibliki/transport";
|
|
|
2
2
|
import { Context, dbToGain } from "@blibliki/utils";
|
|
3
3
|
import { IModule, Module } from "@/core";
|
|
4
4
|
import Note from "@/core/Note";
|
|
5
|
-
import { IModuleConstructor } from "@/core/module/Module";
|
|
5
|
+
import { IModuleConstructor, SetterHooks } from "@/core/module/Module";
|
|
6
6
|
import { IPolyModuleConstructor, PolyModule } from "@/core/module/PolyModule";
|
|
7
|
-
import {
|
|
7
|
+
import { EnumProp, ModulePropSchema } from "@/core/schema";
|
|
8
8
|
import { ICreateModule, ModuleType } from ".";
|
|
9
9
|
|
|
10
10
|
const LOW_GAIN = -18;
|
|
@@ -38,7 +38,12 @@ export type IOscillatorProps = {
|
|
|
38
38
|
lowGain: boolean;
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
export const oscillatorPropSchema:
|
|
41
|
+
export const oscillatorPropSchema: ModulePropSchema<
|
|
42
|
+
IOscillatorProps,
|
|
43
|
+
{
|
|
44
|
+
wave: EnumProp<OscillatorWave>;
|
|
45
|
+
}
|
|
46
|
+
> = {
|
|
42
47
|
wave: {
|
|
43
48
|
kind: "enum",
|
|
44
49
|
options: Object.values(OscillatorWave),
|
|
@@ -67,8 +72,8 @@ export const oscillatorPropSchema: PropSchema<IOscillatorProps> = {
|
|
|
67
72
|
},
|
|
68
73
|
octave: {
|
|
69
74
|
kind: "number",
|
|
70
|
-
min: -
|
|
71
|
-
max:
|
|
75
|
+
min: -1,
|
|
76
|
+
max: 2,
|
|
72
77
|
step: 1,
|
|
73
78
|
label: "Octave",
|
|
74
79
|
},
|
|
@@ -87,7 +92,20 @@ const DEFAULT_PROPS: IOscillatorProps = {
|
|
|
87
92
|
lowGain: false,
|
|
88
93
|
};
|
|
89
94
|
|
|
90
|
-
|
|
95
|
+
type OscillatorSetterHooks = Pick<
|
|
96
|
+
SetterHooks<IOscillatorProps>,
|
|
97
|
+
| "onAfterSetWave"
|
|
98
|
+
| "onAfterSetFrequency"
|
|
99
|
+
| "onAfterSetFine"
|
|
100
|
+
| "onAfterSetCoarse"
|
|
101
|
+
| "onAfterSetOctave"
|
|
102
|
+
| "onAfterSetLowGain"
|
|
103
|
+
>;
|
|
104
|
+
|
|
105
|
+
export class MonoOscillator
|
|
106
|
+
extends Module<ModuleType.Oscillator>
|
|
107
|
+
implements OscillatorSetterHooks
|
|
108
|
+
{
|
|
91
109
|
declare audioNode: OscillatorNode;
|
|
92
110
|
isStated = false;
|
|
93
111
|
lowOutputGain: GainNode;
|
|
@@ -114,31 +132,29 @@ export class MonoOscillator extends Module<ModuleType.Oscillator> {
|
|
|
114
132
|
this.registerOutputs();
|
|
115
133
|
}
|
|
116
134
|
|
|
117
|
-
|
|
135
|
+
onAfterSetWave: OscillatorSetterHooks["onAfterSetWave"] = (value) => {
|
|
118
136
|
this.audioNode.type = value;
|
|
119
|
-
}
|
|
137
|
+
};
|
|
120
138
|
|
|
121
|
-
|
|
139
|
+
onAfterSetFrequency: OscillatorSetterHooks["onAfterSetFrequency"] = () => {
|
|
122
140
|
this.updateFrequency();
|
|
123
|
-
}
|
|
141
|
+
};
|
|
124
142
|
|
|
125
|
-
|
|
143
|
+
onAfterSetFine: OscillatorSetterHooks["onAfterSetFine"] = () => {
|
|
126
144
|
this.updateFrequency();
|
|
127
|
-
}
|
|
145
|
+
};
|
|
128
146
|
|
|
129
|
-
|
|
147
|
+
onAfterSetCoarse: OscillatorSetterHooks["onAfterSetCoarse"] = () => {
|
|
130
148
|
this.updateFrequency();
|
|
131
|
-
}
|
|
149
|
+
};
|
|
132
150
|
|
|
133
|
-
|
|
151
|
+
onAfterSetOctave: OscillatorSetterHooks["onAfterSetOctave"] = () => {
|
|
134
152
|
this.updateFrequency();
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
protected onAfterSetLowGain() {
|
|
138
|
-
if (!this.superInitialized) return;
|
|
153
|
+
};
|
|
139
154
|
|
|
155
|
+
onAfterSetLowGain: OscillatorSetterHooks["onAfterSetLowGain"] = () => {
|
|
140
156
|
this.rePlugAll();
|
|
141
|
-
}
|
|
157
|
+
};
|
|
142
158
|
|
|
143
159
|
start(time: ContextTime) {
|
|
144
160
|
if (this.isStated) return;
|
|
@@ -148,6 +164,8 @@ export class MonoOscillator extends Module<ModuleType.Oscillator> {
|
|
|
148
164
|
}
|
|
149
165
|
|
|
150
166
|
stop(time: ContextTime) {
|
|
167
|
+
if (!this.isStated) return;
|
|
168
|
+
|
|
151
169
|
this.audioNode.stop(time);
|
|
152
170
|
this.rePlugAll(() => {
|
|
153
171
|
this.audioNode = new OscillatorNode(this.context.audioContext, {
|
|
@@ -183,7 +201,6 @@ export class MonoOscillator extends Module<ModuleType.Oscillator> {
|
|
|
183
201
|
|
|
184
202
|
private get finalFrequency(): number | undefined {
|
|
185
203
|
const { frequency, coarse, octave, fine } = this.props;
|
|
186
|
-
if (!this.superInitialized) return;
|
|
187
204
|
|
|
188
205
|
const transposed =
|
|
189
206
|
frequency * Math.pow(2, coarse / 12 + octave + fine / 12);
|
package/src/modules/Scale.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Context } from "@blibliki/utils";
|
|
2
|
-
import { IModule, Module } from "@/core";
|
|
3
|
-
import {
|
|
2
|
+
import { IModule, Module, SetterHooks } from "@/core";
|
|
3
|
+
import { ModulePropSchema } from "@/core/schema";
|
|
4
4
|
import { CustomWorklet, newAudioWorklet } from "@/processors";
|
|
5
5
|
import { ICreateModule, ModuleType } from ".";
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ export type IScaleProps = {
|
|
|
11
11
|
current: number;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
export const scalePropSchema:
|
|
14
|
+
export const scalePropSchema: ModulePropSchema<IScaleProps> = {
|
|
15
15
|
min: {
|
|
16
16
|
kind: "number",
|
|
17
17
|
min: -Infinity,
|
|
@@ -37,7 +37,14 @@ export const scalePropSchema: PropSchema<IScaleProps> = {
|
|
|
37
37
|
|
|
38
38
|
const DEFAULT_PROPS: IScaleProps = { min: 0, max: 1, current: 0.5 };
|
|
39
39
|
|
|
40
|
-
export default class Scale
|
|
40
|
+
export default class Scale
|
|
41
|
+
extends Module<ModuleType.Scale>
|
|
42
|
+
implements
|
|
43
|
+
Pick<
|
|
44
|
+
SetterHooks<IScaleProps>,
|
|
45
|
+
"onAfterSetMin" | "onAfterSetMax" | "onAfterSetCurrent"
|
|
46
|
+
>
|
|
47
|
+
{
|
|
41
48
|
declare audioNode: AudioWorkletNode;
|
|
42
49
|
|
|
43
50
|
constructor(engineId: string, params: ICreateModule<ModuleType.Scale>) {
|
|
@@ -66,15 +73,17 @@ export default class Scale extends Module<ModuleType.Scale> {
|
|
|
66
73
|
return this.audioNode.parameters.get("max")!;
|
|
67
74
|
}
|
|
68
75
|
|
|
69
|
-
|
|
76
|
+
onAfterSetMin: SetterHooks<IScaleProps>["onAfterSetMin"] = (value) => {
|
|
70
77
|
this.min.value = value;
|
|
71
|
-
}
|
|
78
|
+
};
|
|
72
79
|
|
|
73
|
-
|
|
80
|
+
onAfterSetMax: SetterHooks<IScaleProps>["onAfterSetMax"] = (value) => {
|
|
74
81
|
this.max.value = value;
|
|
75
|
-
}
|
|
82
|
+
};
|
|
76
83
|
|
|
77
|
-
|
|
84
|
+
onAfterSetCurrent: SetterHooks<IScaleProps>["onAfterSetCurrent"] = (
|
|
85
|
+
value,
|
|
86
|
+
) => {
|
|
78
87
|
this.current.value = value;
|
|
79
|
-
}
|
|
88
|
+
};
|
|
80
89
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { INote,
|
|
1
|
+
import { INote, Module, IModule, MidiOutput, ModulePropSchema } from "@/core";
|
|
2
2
|
import { ICreateModule, ModuleType } from ".";
|
|
3
3
|
|
|
4
4
|
export type IStepSequencer = IModule<ModuleType.StepSequencer>;
|
|
@@ -16,7 +16,7 @@ export type IStepSequencerProps = {
|
|
|
16
16
|
sequences: ISequence[][];
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
export const stepSequencerPropSchema:
|
|
19
|
+
export const stepSequencerPropSchema: ModulePropSchema<
|
|
20
20
|
Omit<IStepSequencerProps, "sequences">
|
|
21
21
|
> = {
|
|
22
22
|
steps: {
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Context } from "@blibliki/utils";
|
|
2
|
+
import { IModule, Module, ModulePropSchema } from "@/core";
|
|
3
|
+
import { IModuleConstructor, SetterHooks } from "@/core/module/Module";
|
|
4
|
+
import { IPolyModuleConstructor, PolyModule } from "@/core/module/PolyModule";
|
|
5
|
+
import { ICreateModule, ModuleType } from ".";
|
|
6
|
+
|
|
7
|
+
export type IStereoPanner = IModule<ModuleType.StereoPanner>;
|
|
8
|
+
export type IStereoPannerProps = {
|
|
9
|
+
pan: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const stereoPannerPropSchema: ModulePropSchema<IStereoPannerProps> = {
|
|
13
|
+
pan: {
|
|
14
|
+
kind: "number",
|
|
15
|
+
min: -1,
|
|
16
|
+
max: 1,
|
|
17
|
+
step: 0.01,
|
|
18
|
+
label: "Pan",
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const DEFAULT_PROPS: IStereoPannerProps = {
|
|
23
|
+
pan: 0,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export class MonoStereoPanner
|
|
27
|
+
extends Module<ModuleType.StereoPanner>
|
|
28
|
+
implements Pick<SetterHooks<IStereoPannerProps>, "onAfterSetPan">
|
|
29
|
+
{
|
|
30
|
+
declare audioNode: StereoPannerNode;
|
|
31
|
+
|
|
32
|
+
constructor(
|
|
33
|
+
engineId: string,
|
|
34
|
+
params: ICreateModule<ModuleType.StereoPanner>,
|
|
35
|
+
) {
|
|
36
|
+
const props = { ...DEFAULT_PROPS, ...params.props };
|
|
37
|
+
const audioNodeConstructor = (context: Context) =>
|
|
38
|
+
new StereoPannerNode(context.audioContext);
|
|
39
|
+
|
|
40
|
+
super(engineId, {
|
|
41
|
+
...params,
|
|
42
|
+
audioNodeConstructor,
|
|
43
|
+
props,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
this.registerDefaultIOs();
|
|
47
|
+
this.registerAdditionalInputs();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
onAfterSetPan: SetterHooks<IStereoPannerProps>["onAfterSetPan"] = (value) => {
|
|
51
|
+
this.audioNode.pan.value = value;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
private registerAdditionalInputs() {
|
|
55
|
+
this.registerAudioInput({
|
|
56
|
+
name: "pan",
|
|
57
|
+
getAudioNode: () => this.audioNode.pan,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export default class StereoPanner extends PolyModule<ModuleType.StereoPanner> {
|
|
63
|
+
constructor(
|
|
64
|
+
engineId: string,
|
|
65
|
+
params: IPolyModuleConstructor<ModuleType.StereoPanner>,
|
|
66
|
+
) {
|
|
67
|
+
const props = { ...DEFAULT_PROPS, ...params.props };
|
|
68
|
+
const monoModuleConstructor = (
|
|
69
|
+
engineId: string,
|
|
70
|
+
params: IModuleConstructor<ModuleType.StereoPanner>,
|
|
71
|
+
) => new MonoStereoPanner(engineId, params);
|
|
72
|
+
|
|
73
|
+
super(engineId, {
|
|
74
|
+
...params,
|
|
75
|
+
props,
|
|
76
|
+
monoModuleConstructor,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
this.registerAdditionalInputs();
|
|
80
|
+
this.registerDefaultIOs();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private registerAdditionalInputs() {
|
|
84
|
+
this.registerAudioInput({ name: "pan" });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ContextTime } from "@blibliki/transport";
|
|
2
|
-
import {
|
|
2
|
+
import { Module, IModule, MidiOutput, Note, ModulePropSchema } from "@/core";
|
|
3
3
|
import MidiEvent from "@/core/midi/MidiEvent";
|
|
4
4
|
import { ICreateModule, ModuleType } from ".";
|
|
5
5
|
|
|
@@ -8,7 +8,7 @@ export type IVirtualMidiProps = {
|
|
|
8
8
|
activeNotes: string[];
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
export const virtualMidiPropSchema:
|
|
11
|
+
export const virtualMidiPropSchema: ModulePropSchema<IVirtualMidiProps> = {
|
|
12
12
|
activeNotes: {
|
|
13
13
|
kind: "array",
|
|
14
14
|
label: "Active notes",
|
package/src/modules/index.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { assertNever } from "@blibliki/utils";
|
|
2
|
-
import { IModule, Module
|
|
2
|
+
import { IModule, Module } from "@/core";
|
|
3
3
|
import { IPolyModuleConstructor } from "@/core/module/PolyModule";
|
|
4
4
|
import VoiceScheduler, {
|
|
5
5
|
IVoiceSchedulerProps,
|
|
6
6
|
voiceSchedulerPropSchema,
|
|
7
7
|
} from "@/core/module/VoiceScheduler";
|
|
8
|
-
import BiquadFilter, {
|
|
9
|
-
biquadFilterPropSchema,
|
|
10
|
-
IBiquadFilterProps,
|
|
11
|
-
} from "./BiquadFilter";
|
|
12
8
|
import Constant, { constantPropSchema, IConstantProps } from "./Constant";
|
|
13
9
|
import Envelope, { envelopePropSchema, IEnvelopeProps } from "./Envelope";
|
|
14
10
|
import Filter, { filterPropSchema, IFilterProps } from "./Filter";
|
|
15
11
|
import Gain, { gainPropSchema, IGainProps } from "./Gain";
|
|
16
12
|
import Inspector, { IInspectorProps, inspectorPropSchema } from "./Inspector";
|
|
17
13
|
import Master, { IMasterProps, masterPropSchema } from "./Master";
|
|
14
|
+
import MidiMapper, {
|
|
15
|
+
IMidiMapperProps,
|
|
16
|
+
midiMapperPropSchema,
|
|
17
|
+
} from "./MidiMapper";
|
|
18
18
|
import MidiSelector, {
|
|
19
19
|
IMidiSelectorProps,
|
|
20
20
|
midiSelectorPropSchema,
|
|
@@ -28,6 +28,10 @@ import StepSequencer, {
|
|
|
28
28
|
IStepSequencerProps,
|
|
29
29
|
stepSequencerPropSchema,
|
|
30
30
|
} from "./StepSequencer";
|
|
31
|
+
import StereoPanner, {
|
|
32
|
+
IStereoPannerProps,
|
|
33
|
+
stereoPannerPropSchema,
|
|
34
|
+
} from "./StereoPanner";
|
|
31
35
|
import VirtualMidi, {
|
|
32
36
|
IVirtualMidiProps,
|
|
33
37
|
virtualMidiPropSchema,
|
|
@@ -40,10 +44,11 @@ export enum ModuleType {
|
|
|
40
44
|
MidiSelector = "MidiSelector",
|
|
41
45
|
Envelope = "Envelope",
|
|
42
46
|
Filter = "Filter",
|
|
43
|
-
BiquadFilter = "BiquadFilter",
|
|
44
47
|
Scale = "Scale",
|
|
48
|
+
StereoPanner = "StereoPanner",
|
|
45
49
|
Inspector = "Inspector",
|
|
46
50
|
Constant = "Constant",
|
|
51
|
+
MidiMapper = "MidiMapper",
|
|
47
52
|
VirtualMidi = "VirtualMidi",
|
|
48
53
|
StepSequencer = "StepSequencer",
|
|
49
54
|
VoiceScheduler = "VoiceScheduler",
|
|
@@ -56,10 +61,11 @@ export type ModuleTypeToPropsMapping = {
|
|
|
56
61
|
[ModuleType.MidiSelector]: IMidiSelectorProps;
|
|
57
62
|
[ModuleType.Envelope]: IEnvelopeProps;
|
|
58
63
|
[ModuleType.Filter]: IFilterProps;
|
|
59
|
-
[ModuleType.BiquadFilter]: IBiquadFilterProps;
|
|
60
64
|
[ModuleType.Scale]: IScaleProps;
|
|
65
|
+
[ModuleType.StereoPanner]: IStereoPannerProps;
|
|
61
66
|
[ModuleType.Inspector]: IInspectorProps;
|
|
62
67
|
[ModuleType.Constant]: IConstantProps;
|
|
68
|
+
[ModuleType.MidiMapper]: IMidiMapperProps;
|
|
63
69
|
[ModuleType.VirtualMidi]: IVirtualMidiProps;
|
|
64
70
|
[ModuleType.StepSequencer]: IStepSequencerProps;
|
|
65
71
|
[ModuleType.VoiceScheduler]: IVoiceSchedulerProps;
|
|
@@ -72,28 +78,28 @@ export type ModuleTypeToModuleMapping = {
|
|
|
72
78
|
[ModuleType.MidiSelector]: MidiSelector;
|
|
73
79
|
[ModuleType.Envelope]: Envelope;
|
|
74
80
|
[ModuleType.Filter]: Filter;
|
|
75
|
-
[ModuleType.BiquadFilter]: BiquadFilter;
|
|
76
81
|
[ModuleType.Scale]: Scale;
|
|
82
|
+
[ModuleType.StereoPanner]: StereoPanner;
|
|
77
83
|
[ModuleType.Inspector]: Inspector;
|
|
78
84
|
[ModuleType.Constant]: Constant;
|
|
85
|
+
[ModuleType.MidiMapper]: MidiMapper;
|
|
79
86
|
[ModuleType.VirtualMidi]: VirtualMidi;
|
|
80
87
|
[ModuleType.StepSequencer]: StepSequencer;
|
|
81
88
|
[ModuleType.VoiceScheduler]: VoiceScheduler;
|
|
82
89
|
};
|
|
83
90
|
|
|
84
|
-
export const moduleSchemas
|
|
85
|
-
[K in ModuleType]: PropSchema<Partial<ModuleTypeToPropsMapping[K]>>;
|
|
86
|
-
} = {
|
|
91
|
+
export const moduleSchemas = {
|
|
87
92
|
[ModuleType.Oscillator]: oscillatorPropSchema,
|
|
88
93
|
[ModuleType.Gain]: gainPropSchema,
|
|
89
94
|
[ModuleType.Master]: masterPropSchema,
|
|
90
95
|
[ModuleType.MidiSelector]: midiSelectorPropSchema,
|
|
91
96
|
[ModuleType.Envelope]: envelopePropSchema,
|
|
92
97
|
[ModuleType.Filter]: filterPropSchema,
|
|
93
|
-
[ModuleType.BiquadFilter]: biquadFilterPropSchema,
|
|
94
98
|
[ModuleType.Scale]: scalePropSchema,
|
|
99
|
+
[ModuleType.StereoPanner]: stereoPannerPropSchema,
|
|
95
100
|
[ModuleType.Inspector]: inspectorPropSchema,
|
|
96
101
|
[ModuleType.Constant]: constantPropSchema,
|
|
102
|
+
[ModuleType.MidiMapper]: midiMapperPropSchema,
|
|
97
103
|
[ModuleType.VirtualMidi]: virtualMidiPropSchema,
|
|
98
104
|
[ModuleType.StepSequencer]: stepSequencerPropSchema,
|
|
99
105
|
[ModuleType.VoiceScheduler]: voiceSchedulerPropSchema,
|
|
@@ -104,11 +110,14 @@ export { OscillatorWave } from "./Oscillator";
|
|
|
104
110
|
export type { IGain } from "./Gain";
|
|
105
111
|
export type { IMaster } from "./Master";
|
|
106
112
|
export type { IMidiSelector } from "./MidiSelector";
|
|
113
|
+
export type { IStereoPanner } from "./StereoPanner";
|
|
107
114
|
export type {
|
|
108
115
|
IStepSequencer,
|
|
109
116
|
IStepSequencerProps,
|
|
110
117
|
ISequence,
|
|
111
118
|
} from "./StepSequencer";
|
|
119
|
+
export type { IMidiMapper, IMidiMapperProps, MidiMapping } from "./MidiMapper";
|
|
120
|
+
export { MidiMappingMode } from "./MidiMapper";
|
|
112
121
|
|
|
113
122
|
export type AnyModule = Module<ModuleType>;
|
|
114
123
|
export type IAnyModule = IModule<ModuleType>;
|
|
@@ -126,7 +135,7 @@ export type ModuleParams = {
|
|
|
126
135
|
| ModuleType.Gain
|
|
127
136
|
| ModuleType.Envelope
|
|
128
137
|
| ModuleType.Filter
|
|
129
|
-
| ModuleType.
|
|
138
|
+
| ModuleType.StereoPanner
|
|
130
139
|
| ModuleType.VoiceScheduler
|
|
131
140
|
? IPolyModuleConstructor<K>
|
|
132
141
|
: ICreateModule<K>;
|
|
@@ -149,14 +158,16 @@ export function createModule(
|
|
|
149
158
|
return new Envelope(engineId, params);
|
|
150
159
|
case ModuleType.Filter:
|
|
151
160
|
return new Filter(engineId, params);
|
|
152
|
-
case ModuleType.BiquadFilter:
|
|
153
|
-
return new BiquadFilter(engineId, params);
|
|
154
161
|
case ModuleType.Scale:
|
|
155
162
|
return new Scale(engineId, params);
|
|
163
|
+
case ModuleType.StereoPanner:
|
|
164
|
+
return new StereoPanner(engineId, params);
|
|
156
165
|
case ModuleType.Inspector:
|
|
157
166
|
return new Inspector(engineId, params);
|
|
158
167
|
case ModuleType.Constant:
|
|
159
168
|
return new Constant(engineId, params);
|
|
169
|
+
case ModuleType.MidiMapper:
|
|
170
|
+
return new MidiMapper(engineId, params);
|
|
160
171
|
case ModuleType.VirtualMidi:
|
|
161
172
|
return new VirtualMidi(engineId, params);
|
|
162
173
|
case ModuleType.StepSequencer:
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import { Context } from "@blibliki/utils";
|
|
2
|
-
import { IModuleConstructor, Module } from "@/core/module/Module";
|
|
3
|
-
import { IPolyModuleConstructor, PolyModule } from "@/core/module/PolyModule";
|
|
4
|
-
import { PropSchema } from "@/core/schema";
|
|
5
|
-
import { createModule, ICreateModule, ModuleType } from ".";
|
|
6
|
-
import { MonoGain } from "./Gain";
|
|
7
|
-
import Scale from "./Scale";
|
|
8
|
-
|
|
9
|
-
export type IBiquadFilterProps = {
|
|
10
|
-
cutoff: number;
|
|
11
|
-
envelopeAmount: number;
|
|
12
|
-
type: BiquadFilterType;
|
|
13
|
-
Q: number;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const MIN_FREQ = 20;
|
|
17
|
-
const MAX_FREQ = 20000;
|
|
18
|
-
|
|
19
|
-
const DEFAULT_PROPS: IBiquadFilterProps = {
|
|
20
|
-
cutoff: MAX_FREQ,
|
|
21
|
-
envelopeAmount: 0,
|
|
22
|
-
type: "lowpass",
|
|
23
|
-
Q: 1,
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export const biquadFilterPropSchema: PropSchema<IBiquadFilterProps> = {
|
|
27
|
-
cutoff: {
|
|
28
|
-
kind: "number",
|
|
29
|
-
min: MIN_FREQ,
|
|
30
|
-
max: MAX_FREQ,
|
|
31
|
-
step: 1,
|
|
32
|
-
label: "Cutoff",
|
|
33
|
-
},
|
|
34
|
-
envelopeAmount: {
|
|
35
|
-
kind: "number",
|
|
36
|
-
min: -1,
|
|
37
|
-
max: 1,
|
|
38
|
-
step: 0.01,
|
|
39
|
-
label: "Envelope Amount",
|
|
40
|
-
},
|
|
41
|
-
type: {
|
|
42
|
-
kind: "enum",
|
|
43
|
-
options: ["lowpass", "highpass", "bandpass"] satisfies BiquadFilterType[],
|
|
44
|
-
label: "Type",
|
|
45
|
-
},
|
|
46
|
-
Q: {
|
|
47
|
-
kind: "number",
|
|
48
|
-
min: -100,
|
|
49
|
-
max: 100,
|
|
50
|
-
step: 0.1,
|
|
51
|
-
label: "Q",
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
class MonoBiquadFilter extends Module<ModuleType.BiquadFilter> {
|
|
56
|
-
declare audioNode: BiquadFilterNode;
|
|
57
|
-
private scale: Scale;
|
|
58
|
-
private amount: MonoGain;
|
|
59
|
-
|
|
60
|
-
constructor(
|
|
61
|
-
engineId: string,
|
|
62
|
-
params: ICreateModule<ModuleType.BiquadFilter>,
|
|
63
|
-
) {
|
|
64
|
-
const props = { ...DEFAULT_PROPS, ...params.props };
|
|
65
|
-
|
|
66
|
-
const audioNodeConstructor = (context: Context) =>
|
|
67
|
-
new BiquadFilterNode(context.audioContext, {
|
|
68
|
-
type: props.type,
|
|
69
|
-
frequency: props.cutoff,
|
|
70
|
-
Q: props.Q,
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
super(engineId, {
|
|
74
|
-
...params,
|
|
75
|
-
props,
|
|
76
|
-
audioNodeConstructor,
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
this.amount = new MonoGain(engineId, {
|
|
80
|
-
name: "amount",
|
|
81
|
-
moduleType: ModuleType.Gain,
|
|
82
|
-
props: { gain: props.envelopeAmount },
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
this.scale = createModule(engineId, {
|
|
86
|
-
name: "scale",
|
|
87
|
-
moduleType: ModuleType.Scale,
|
|
88
|
-
props: { min: MIN_FREQ, max: MAX_FREQ, current: this.props.cutoff },
|
|
89
|
-
}) as Scale;
|
|
90
|
-
|
|
91
|
-
this.amount.plug({ audioModule: this.scale, from: "out", to: "in" });
|
|
92
|
-
this.scale.audioNode.connect(this.audioNode.frequency);
|
|
93
|
-
|
|
94
|
-
this.registerDefaultIOs();
|
|
95
|
-
this.registerInputs();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
protected onSetType(value: IBiquadFilterProps["type"]) {
|
|
99
|
-
this.audioNode.type = value;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
protected onSetCutoff(value: IBiquadFilterProps["cutoff"]) {
|
|
103
|
-
if (!this.superInitialized) return;
|
|
104
|
-
|
|
105
|
-
this.scale.props = { current: value };
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
protected onSetQ(value: IBiquadFilterProps["Q"]) {
|
|
109
|
-
this.audioNode.Q.value = value;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
protected onSetEnvelopeAmount(value: IBiquadFilterProps["envelopeAmount"]) {
|
|
113
|
-
if (!this.superInitialized) return;
|
|
114
|
-
|
|
115
|
-
this.amount.props = { gain: value };
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
private registerInputs() {
|
|
119
|
-
this.registerAudioInput({
|
|
120
|
-
name: "cutoff",
|
|
121
|
-
getAudioNode: () => this.audioNode.frequency,
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
this.registerAudioInput({
|
|
125
|
-
name: "cutoffMod",
|
|
126
|
-
getAudioNode: () => this.amount.audioNode,
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
this.registerAudioInput({
|
|
130
|
-
name: "Q",
|
|
131
|
-
getAudioNode: () => this.audioNode.Q,
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export default class BiquadFilter extends PolyModule<ModuleType.BiquadFilter> {
|
|
137
|
-
constructor(
|
|
138
|
-
engineId: string,
|
|
139
|
-
params: IPolyModuleConstructor<ModuleType.BiquadFilter>,
|
|
140
|
-
) {
|
|
141
|
-
const props = { ...DEFAULT_PROPS, ...params.props };
|
|
142
|
-
const monoModuleConstructor = (
|
|
143
|
-
engineId: string,
|
|
144
|
-
params: IModuleConstructor<ModuleType.BiquadFilter>,
|
|
145
|
-
) => new MonoBiquadFilter(engineId, params);
|
|
146
|
-
|
|
147
|
-
super(engineId, {
|
|
148
|
-
...params,
|
|
149
|
-
props,
|
|
150
|
-
monoModuleConstructor,
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
this.registerInputs();
|
|
154
|
-
this.registerDefaultIOs();
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
private registerInputs() {
|
|
158
|
-
this.registerAudioInput({ name: "cutoff" });
|
|
159
|
-
this.registerAudioInput({ name: "cutoffMod" });
|
|
160
|
-
this.registerAudioInput({ name: "Q" });
|
|
161
|
-
}
|
|
162
|
-
}
|