@fluex/fluexgl-dsp 0.4.6 → 0.4.8
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/README.md +7 -7
- package/lib/dist/console-codes.d.ts +2 -1
- package/lib/dist/console-codes.d.ts.map +1 -1
- package/lib/dist/console-codes.js +1 -0
- package/lib/dist/core/classes/AudioClip.d.ts +27 -16
- package/lib/dist/core/classes/AudioClip.d.ts.map +1 -1
- package/lib/dist/core/classes/AudioClip.js +133 -48
- package/lib/dist/core/classes/AudioClipPlayer.d.ts +8 -8
- package/lib/dist/core/classes/AudioClipPlayer.d.ts.map +1 -1
- package/lib/dist/core/classes/AudioClipPlayer.js +22 -24
- package/lib/dist/core/classes/AudioDevice.d.ts +46 -5
- package/lib/dist/core/classes/AudioDevice.d.ts.map +1 -1
- package/lib/dist/core/classes/AudioDevice.js +47 -6
- package/lib/dist/core/classes/Channel.d.ts +20 -20
- package/lib/dist/core/classes/Channel.d.ts.map +1 -1
- package/lib/dist/core/classes/Channel.js +42 -42
- package/lib/dist/core/classes/DpsPipeline.d.ts +6 -6
- package/lib/dist/core/classes/DpsPipeline.d.ts.map +1 -1
- package/lib/dist/core/classes/DpsPipeline.js +18 -18
- package/lib/dist/core/classes/Effector.d.ts +5 -5
- package/lib/dist/core/classes/Effector.d.ts.map +1 -1
- package/lib/dist/core/classes/Effector.js +8 -8
- package/lib/dist/core/classes/Master.d.ts +6 -6
- package/lib/dist/core/classes/Master.d.ts.map +1 -1
- package/lib/dist/core/classes/Master.js +18 -18
- package/lib/dist/effects/classes/Analyser.d.ts +10 -6
- package/lib/dist/effects/classes/Analyser.d.ts.map +1 -1
- package/lib/dist/effects/classes/Analyser.js +29 -13
- package/lib/dist/effects/classes/Chorus.d.ts +7 -7
- package/lib/dist/effects/classes/Chorus.d.ts.map +1 -1
- package/lib/dist/effects/classes/Chorus.js +25 -25
- package/lib/dist/effects/classes/Distortion.d.ts +1 -1
- package/lib/dist/effects/classes/Distortion.d.ts.map +1 -1
- package/lib/dist/effects/classes/Distortion.js +1 -1
- package/lib/dist/effects/classes/Reverb.d.ts +32 -0
- package/lib/dist/effects/classes/Reverb.d.ts.map +1 -0
- package/lib/dist/effects/classes/Reverb.js +61 -0
- package/lib/dist/effects/classes/clips/HardClip.d.ts +5 -5
- package/lib/dist/effects/classes/clips/HardClip.d.ts.map +1 -1
- package/lib/dist/effects/classes/clips/HardClip.js +14 -14
- package/lib/dist/effects/classes/clips/SoftClip.d.ts +4 -4
- package/lib/dist/effects/classes/clips/SoftClip.d.ts.map +1 -1
- package/lib/dist/effects/classes/clips/SoftClip.js +13 -13
- package/lib/dist/effects/classes/filters/HighPassFilter.d.ts +18 -0
- package/lib/dist/effects/classes/filters/HighPassFilter.d.ts.map +1 -0
- package/lib/dist/effects/classes/filters/HighPassFilter.js +59 -0
- package/lib/dist/effects/classes/filters/LowPassFilter.d.ts +5 -5
- package/lib/dist/effects/classes/filters/LowPassFilter.d.ts.map +1 -1
- package/lib/dist/effects/classes/filters/LowPassFilter.js +17 -17
- package/lib/dist/effects/classes/filters/NotchFilter.d.ts +18 -0
- package/lib/dist/effects/classes/filters/NotchFilter.d.ts.map +1 -0
- package/lib/dist/effects/classes/filters/NotchFilter.js +59 -0
- package/lib/dist/effects/exports.d.ts +2 -5
- package/lib/dist/effects/exports.d.ts.map +1 -1
- package/lib/dist/effects/exports.js +2 -5
- package/lib/dist/index.d.ts +4 -4
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +3 -3
- package/lib/dist/typings.d.ts +33 -0
- package/lib/dist/typings.d.ts.map +1 -1
- package/lib/dist/typings.js +12 -0
- package/lib/dist/utilities/constants.d.ts +1 -0
- package/lib/dist/utilities/constants.d.ts.map +1 -1
- package/lib/dist/utilities/constants.js +1 -0
- package/lib/dist/utilities/debugger.d.ts +4 -4
- package/lib/dist/utilities/debugger.js +8 -8
- package/lib/dist/utilities/helpers.d.ts +13 -13
- package/lib/dist/utilities/helpers.d.ts.map +1 -1
- package/lib/dist/utilities/helpers.js +45 -59
- package/lib/dist/utilities/web-assembly.js +1 -1
- package/lib/src/console-codes.ts +2 -1
- package/lib/src/core/classes/AudioClip.ts +166 -55
- package/lib/src/core/classes/AudioClipPlayer.ts +22 -24
- package/lib/src/core/classes/AudioDevice.ts +49 -6
- package/lib/src/core/classes/Channel.ts +42 -42
- package/lib/src/core/classes/DpsPipeline.ts +19 -19
- package/lib/src/core/classes/Effector.ts +9 -9
- package/lib/src/core/classes/Master.ts +18 -18
- package/lib/src/effects/classes/Analyser.ts +33 -13
- package/lib/src/effects/classes/Chorus.ts +25 -25
- package/lib/src/effects/classes/Distortion.ts +1 -1
- package/lib/src/effects/classes/Reverb.ts +81 -0
- package/lib/src/effects/classes/clips/HardClip.ts +14 -14
- package/lib/src/effects/classes/clips/SoftClip.ts +13 -13
- package/lib/src/effects/classes/filters/HighPassFilter.ts +81 -0
- package/lib/src/effects/classes/filters/LowPassFilter.ts +17 -17
- package/lib/src/effects/classes/filters/NotchFilter.ts +81 -0
- package/lib/src/effects/exports.ts +2 -6
- package/lib/src/index.ts +15 -17
- package/lib/src/typings.ts +39 -1
- package/lib/src/utilities/constants.ts +3 -1
- package/lib/src/utilities/debugger.ts +4 -4
- package/lib/src/utilities/helpers.ts +47 -60
- package/lib/src/utilities/web-assembly.ts +1 -1
- package/package.json +3 -2
- package/lib/src/effects/classes/reverbs/ChamberReverb.ts +0 -1
- package/lib/src/effects/classes/reverbs/ConvolverReverb.ts +0 -1
- package/lib/src/effects/classes/reverbs/GenericReverb.ts +0 -1
- package/lib/src/effects/classes/reverbs/HallReverb.ts +0 -1
- package/lib/src/effects/classes/reverbs/RoomReverb.ts +0 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Effector } from "../../core/exports";
|
|
2
|
+
import { AudioWorkletProcessorNames, StrictMode } from "../../typings";
|
|
3
|
+
import { coerceFiniteNumber, createAudioWorkletNode, sendMessageToWorklet } from "../../utilities/helpers";
|
|
4
|
+
|
|
5
|
+
export interface ReverbOptions {
|
|
6
|
+
roomSize: number;
|
|
7
|
+
damping: number;
|
|
8
|
+
mix: number;
|
|
9
|
+
stereoSpreadMs: number;
|
|
10
|
+
strictMode: StrictMode;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export enum ReverbMessageCommandId {
|
|
14
|
+
SetRoomSize,
|
|
15
|
+
SetDamping,
|
|
16
|
+
SetMix,
|
|
17
|
+
SetStereoSpreadMs
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class Reverb extends Effector {
|
|
21
|
+
|
|
22
|
+
public label: string | null = "Reverb";
|
|
23
|
+
public name: string = "Reverb";
|
|
24
|
+
|
|
25
|
+
public roomSize: number = 0.3;
|
|
26
|
+
public damping: number = 0.5;
|
|
27
|
+
public mix: number = 0.3;
|
|
28
|
+
public stereoSpreadMs: number = 0;
|
|
29
|
+
public strictMode: StrictMode = StrictMode.Disabled;
|
|
30
|
+
|
|
31
|
+
constructor(options?: Partial<ReverbOptions>) {
|
|
32
|
+
super();
|
|
33
|
+
|
|
34
|
+
this.roomSize = Math.max(0, coerceFiniteNumber(options?.roomSize ?? this.roomSize, this.roomSize));
|
|
35
|
+
this.damping = Math.max(0, coerceFiniteNumber(options?.damping ?? this.damping, this.damping));
|
|
36
|
+
this.mix = Math.max(0, coerceFiniteNumber(options?.mix ?? this.mix, this.mix));
|
|
37
|
+
this.stereoSpreadMs = Math.max(0, coerceFiniteNumber(options?.stereoSpreadMs ?? this.stereoSpreadMs, this.stereoSpreadMs));
|
|
38
|
+
|
|
39
|
+
const mode = coerceFiniteNumber(options?.strictMode ?? this.strictMode, this.strictMode);
|
|
40
|
+
this.strictMode = mode === StrictMode.Enabled ? StrictMode.Enabled : StrictMode.Disabled;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public async initializeOnAttachment(context: AudioContext): Promise<void> {
|
|
44
|
+
this.context = context;
|
|
45
|
+
this.audioWorkletNode = createAudioWorkletNode<ReverbOptions>(context, AudioWorkletProcessorNames.Reverb, this.returnOptionsAsObject());
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public returnOptionsAsObject(): ReverbOptions {
|
|
49
|
+
return {
|
|
50
|
+
roomSize: this.roomSize,
|
|
51
|
+
damping: this.damping,
|
|
52
|
+
mix: this.mix,
|
|
53
|
+
stereoSpreadMs: this.stereoSpreadMs,
|
|
54
|
+
strictMode: this.strictMode
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public setRoomSize(roomSize: number): boolean {
|
|
59
|
+
roomSize = Math.max(0, coerceFiniteNumber(roomSize ?? this.roomSize, this.roomSize));
|
|
60
|
+
this.roomSize = roomSize;
|
|
61
|
+
return sendMessageToWorklet<ReverbMessageCommandId, number>(this.audioWorkletNode, ReverbMessageCommandId.SetRoomSize, roomSize);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public setDamping(damping: number): boolean {
|
|
65
|
+
damping = Math.max(0, coerceFiniteNumber(damping ?? this.damping, this.damping));
|
|
66
|
+
this.damping = damping;
|
|
67
|
+
return sendMessageToWorklet<ReverbMessageCommandId, number>(this.audioWorkletNode, ReverbMessageCommandId.SetDamping, damping);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public setMix(mix: number): boolean {
|
|
71
|
+
mix = Math.max(0, coerceFiniteNumber(mix ?? this.mix, this.mix));
|
|
72
|
+
this.mix = mix;
|
|
73
|
+
return sendMessageToWorklet<ReverbMessageCommandId, number>(this.audioWorkletNode, ReverbMessageCommandId.SetMix, mix);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public setStereoSpreadMs(stereoSpreadMs: number) {
|
|
77
|
+
stereoSpreadMs = Math.max(0, coerceFiniteNumber(stereoSpreadMs ?? this.stereoSpreadMs, this.stereoSpreadMs));
|
|
78
|
+
this.stereoSpreadMs = stereoSpreadMs;
|
|
79
|
+
return sendMessageToWorklet<ReverbMessageCommandId, number>(this.audioWorkletNode, ReverbMessageCommandId.SetStereoSpreadMs, stereoSpreadMs);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effector } from "../../../core/classes/Effector";
|
|
2
|
-
import {
|
|
2
|
+
import { coerceFiniteNumber, createAudioWorkletNode, sendMessageToWorklet } from "../../../utilities/helpers";
|
|
3
3
|
import { HardClipMessageCommandId, AudioWorkletProcessorNames, HardClipOptions, StrictMode } from "../../../typings";
|
|
4
4
|
|
|
5
5
|
export class HardClip extends Effector {
|
|
@@ -11,22 +11,22 @@ export class HardClip extends Effector {
|
|
|
11
11
|
public gain: number = 1;
|
|
12
12
|
public strictMode: StrictMode = StrictMode.Disabled;
|
|
13
13
|
|
|
14
|
-
constructor(
|
|
14
|
+
constructor(options?: HardClipOptions) {
|
|
15
15
|
super();
|
|
16
16
|
|
|
17
|
-
this.drive = Math.max(0,
|
|
18
|
-
this.gain = Math.max(0,
|
|
17
|
+
this.drive = Math.max(0, coerceFiniteNumber(options?.drive ?? this.drive, this.drive));
|
|
18
|
+
this.gain = Math.max(0, coerceFiniteNumber(options?.gain ?? this.gain, this.gain));
|
|
19
19
|
|
|
20
|
-
const mode =
|
|
20
|
+
const mode = coerceFiniteNumber(options?.strictMode ?? this.strictMode, this.strictMode);
|
|
21
21
|
this.strictMode = mode === StrictMode.Enabled ? StrictMode.Enabled : StrictMode.Disabled;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
public async
|
|
24
|
+
public async initializeOnAttachment(context: AudioContext): Promise<void> {
|
|
25
25
|
this.context = context;
|
|
26
|
-
this.audioWorkletNode =
|
|
26
|
+
this.audioWorkletNode = createAudioWorkletNode<HardClipOptions>(context, AudioWorkletProcessorNames.HardClip, this.returnOptionsAsObject());
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
public
|
|
29
|
+
public returnOptionsAsObject(): HardClipOptions {
|
|
30
30
|
return {
|
|
31
31
|
drive: this.drive,
|
|
32
32
|
gain: this.gain,
|
|
@@ -34,15 +34,15 @@ export class HardClip extends Effector {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
public
|
|
38
|
-
drive = Math.max(0,
|
|
37
|
+
public setDrive(drive: number): boolean {
|
|
38
|
+
drive = Math.max(0, coerceFiniteNumber(drive, this.drive));
|
|
39
39
|
this.drive = drive;
|
|
40
|
-
return
|
|
40
|
+
return sendMessageToWorklet<HardClipMessageCommandId, number>(this.audioWorkletNode, HardClipMessageCommandId.SetDrive, drive);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
public
|
|
44
|
-
gain = Math.max(0,
|
|
43
|
+
public setGain(gain: number): boolean{
|
|
44
|
+
gain = Math.max(0, coerceFiniteNumber(gain, this.gain));
|
|
45
45
|
this.gain = gain;
|
|
46
|
-
return
|
|
46
|
+
return sendMessageToWorklet<HardClipMessageCommandId, number>(this.audioWorkletNode, HardClipMessageCommandId.SetGain, gain);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { coerceFiniteNumber, createAudioWorkletNode, sendMessageToWorklet } from "../../../utilities/helpers";
|
|
2
2
|
import { Effector } from "../../../core/classes/Effector";
|
|
3
3
|
import { SoftClipOptions, AudioWorkletProcessorNames, SoftClipMessageCommandId, StrictMode } from "../../../typings";
|
|
4
4
|
|
|
@@ -14,23 +14,23 @@ export class SoftClip extends Effector {
|
|
|
14
14
|
constructor({ drive, gain, strictMode }: Partial<SoftClipOptions> = {}) {
|
|
15
15
|
super();
|
|
16
16
|
|
|
17
|
-
this.drive = Math.max(0,
|
|
18
|
-
this.gain = Math.max(0,
|
|
17
|
+
this.drive = Math.max(0, coerceFiniteNumber(drive, this.drive));
|
|
18
|
+
this.gain = Math.max(0, coerceFiniteNumber(gain, this.gain));
|
|
19
19
|
|
|
20
|
-
const mode =
|
|
20
|
+
const mode = coerceFiniteNumber(strictMode, this.strictMode);
|
|
21
21
|
this.strictMode = mode === StrictMode.Enabled ? StrictMode.Enabled : StrictMode.Disabled;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
public async
|
|
24
|
+
public async initializeOnAttachment(context: AudioContext): Promise<void> {
|
|
25
25
|
|
|
26
26
|
if(this.context === null)
|
|
27
27
|
this.context = context;
|
|
28
28
|
|
|
29
29
|
if(this.audioWorkletNode === null)
|
|
30
|
-
this.audioWorkletNode =
|
|
30
|
+
this.audioWorkletNode = createAudioWorkletNode<SoftClipOptions>(context, AudioWorkletProcessorNames.SoftClip, this.returnOptionsAsObject());
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
public
|
|
33
|
+
public returnOptionsAsObject(): SoftClipOptions {
|
|
34
34
|
return {
|
|
35
35
|
drive: this.drive,
|
|
36
36
|
gain: this.gain,
|
|
@@ -38,15 +38,15 @@ export class SoftClip extends Effector {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
public
|
|
42
|
-
drive = Math.max(0,
|
|
41
|
+
public setDrive(drive: number): boolean {
|
|
42
|
+
drive = Math.max(0, coerceFiniteNumber(drive, this.drive));
|
|
43
43
|
this.drive = drive;
|
|
44
|
-
return
|
|
44
|
+
return sendMessageToWorklet<SoftClipMessageCommandId, number>(this.audioWorkletNode, SoftClipMessageCommandId.SetDrive, drive);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
public
|
|
48
|
-
gain = Math.max(0,
|
|
47
|
+
public setGain(gain: number): boolean{
|
|
48
|
+
gain = Math.max(0, coerceFiniteNumber(gain, this.gain));
|
|
49
49
|
this.gain = gain;
|
|
50
|
-
return
|
|
50
|
+
return sendMessageToWorklet<SoftClipMessageCommandId, number>(this.audioWorkletNode, SoftClipMessageCommandId.SetGain, gain);
|
|
51
51
|
}
|
|
52
52
|
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { coerceFiniteNumber, createAudioWorkletNode, sendMessageToWorklet } from "../../../utilities/helpers";
|
|
2
|
+
import { Effector } from "../../../core/classes/Effector";
|
|
3
|
+
import { AudioWorkletProcessorNames, HighPassFilterMessageCommandId, HighPassFilterOptions, StrictMode } from "../../../typings";
|
|
4
|
+
import { DEFAULT_SAMPLE_RATE } from "../../../utilities/constants";
|
|
5
|
+
|
|
6
|
+
export class HighPassFilter extends Effector {
|
|
7
|
+
|
|
8
|
+
public name: string = "HighPassFilter";
|
|
9
|
+
public label: string | null = "HighPassFilter";
|
|
10
|
+
|
|
11
|
+
public cutoff: number = 1000;
|
|
12
|
+
public q: number = 0.7;
|
|
13
|
+
public strictMode: StrictMode = StrictMode.Disabled;
|
|
14
|
+
public maxFrequency: number = DEFAULT_SAMPLE_RATE * 0.5;
|
|
15
|
+
|
|
16
|
+
private contextSampleRate: number = DEFAULT_SAMPLE_RATE;
|
|
17
|
+
|
|
18
|
+
constructor({ cutoff, q, strictMode }: Partial<HighPassFilterOptions> = {}) {
|
|
19
|
+
super();
|
|
20
|
+
|
|
21
|
+
this.cutoff = coerceFiniteNumber(cutoff, this.cutoff);
|
|
22
|
+
this.q = coerceFiniteNumber(q, this.q);
|
|
23
|
+
|
|
24
|
+
const mode = coerceFiniteNumber(strictMode, this.strictMode);
|
|
25
|
+
this.strictMode = mode === StrictMode.Enabled ? StrictMode.Enabled : StrictMode.Disabled;
|
|
26
|
+
this.audioWorkletNode && this.registerMessageEventListener(this.audioWorkletNode);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public async initializeOnAttachment(context: AudioContext): Promise<void> {
|
|
30
|
+
|
|
31
|
+
this.context = context;
|
|
32
|
+
this.contextSampleRate = context.sampleRate;
|
|
33
|
+
this.audioWorkletNode = createAudioWorkletNode(context, AudioWorkletProcessorNames.HighPassFilter, this.returnOptionsAsObject());
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public returnOptionsAsObject(): HighPassFilterOptions {
|
|
37
|
+
return {
|
|
38
|
+
cutoff: this.cutoff,
|
|
39
|
+
q: this.q,
|
|
40
|
+
strictMode: this.strictMode,
|
|
41
|
+
maxFrequency: this.maxFrequency
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public setCutoff(cutoff: number = 1000): boolean {
|
|
46
|
+
|
|
47
|
+
if (!this.context) return false;
|
|
48
|
+
|
|
49
|
+
cutoff = coerceFiniteNumber(cutoff, this.cutoff);
|
|
50
|
+
cutoff = Math.min(this.maxFrequency, cutoff);
|
|
51
|
+
|
|
52
|
+
if (cutoff >= this.context.sampleRate)
|
|
53
|
+
cutoff = this.context.sampleRate;
|
|
54
|
+
|
|
55
|
+
this.cutoff = cutoff;
|
|
56
|
+
return sendMessageToWorklet<HighPassFilterMessageCommandId, number>(this.audioWorkletNode, HighPassFilterMessageCommandId.SetCutoff, cutoff);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public setMaxFrequency(maxFrequency: number = this.maxFrequency) {
|
|
60
|
+
|
|
61
|
+
maxFrequency = coerceFiniteNumber(maxFrequency, this.maxFrequency);
|
|
62
|
+
|
|
63
|
+
if(maxFrequency > (this.contextSampleRate * 0.5))
|
|
64
|
+
throw new Error("Could not set the max frequency, because the value is over the sample rate.");
|
|
65
|
+
|
|
66
|
+
this.maxFrequency = maxFrequency;
|
|
67
|
+
return sendMessageToWorklet<HighPassFilterMessageCommandId.SetMaxFrequency, number>(this.audioWorkletNode, HighPassFilterMessageCommandId.SetMaxFrequency, maxFrequency);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public setQ(q: number = 0.7): boolean {
|
|
71
|
+
|
|
72
|
+
q = coerceFiniteNumber(q, this.q);
|
|
73
|
+
q = Math.max(0.0001, q);
|
|
74
|
+
|
|
75
|
+
if (q > 4)
|
|
76
|
+
q = 4;
|
|
77
|
+
|
|
78
|
+
this.q = q;
|
|
79
|
+
return sendMessageToWorklet<HighPassFilterMessageCommandId, number>(this.audioWorkletNode, HighPassFilterMessageCommandId.SetQ, q);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effector } from "../../../core/classes/Effector";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { coerceFiniteNumber, sendMessageToWorklet, createAudioWorkletNode } from "../../../utilities/helpers";
|
|
4
4
|
|
|
5
5
|
import { LowPassFilterOptions, LowPassFilterMessageCommandId, AudioWorkletProcessorNames, StrictMode } from "../../../typings";
|
|
6
6
|
|
|
@@ -17,22 +17,22 @@ export class LowPassFilter extends Effector {
|
|
|
17
17
|
constructor({ cutoff, minFrequency, q, strictMode }: Partial<LowPassFilterOptions>) {
|
|
18
18
|
super();
|
|
19
19
|
|
|
20
|
-
this.cutoff =
|
|
21
|
-
this.minFrequency =
|
|
22
|
-
this.q =
|
|
20
|
+
this.cutoff = coerceFiniteNumber(cutoff, this.cutoff);
|
|
21
|
+
this.minFrequency = coerceFiniteNumber(minFrequency, this.minFrequency);
|
|
22
|
+
this.q = coerceFiniteNumber(q, this.q);
|
|
23
23
|
|
|
24
|
-
const mode =
|
|
24
|
+
const mode = coerceFiniteNumber(strictMode, this.strictMode);
|
|
25
25
|
this.strictMode = mode === StrictMode.Enabled ? StrictMode.Enabled : StrictMode.Disabled;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
public async
|
|
28
|
+
public async initializeOnAttachment(context: AudioContext): Promise<void> {
|
|
29
29
|
|
|
30
30
|
this.context = context;
|
|
31
|
-
this.audioWorkletNode =
|
|
31
|
+
this.audioWorkletNode = createAudioWorkletNode(context, AudioWorkletProcessorNames.LowPassFilter, this.returnOptionsAsObject());
|
|
32
32
|
this.audioWorkletNode && this.registerMessageEventListener(this.audioWorkletNode);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
public
|
|
35
|
+
public returnOptionsAsObject(): LowPassFilterOptions {
|
|
36
36
|
return {
|
|
37
37
|
cutoff: this.cutoff,
|
|
38
38
|
minFrequency: this.minFrequency,
|
|
@@ -41,40 +41,40 @@ export class LowPassFilter extends Effector {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
public
|
|
44
|
+
public setCutoff(cutoff: number = 1000): boolean {
|
|
45
45
|
|
|
46
46
|
if (!this.context) return false;
|
|
47
47
|
|
|
48
|
-
cutoff =
|
|
48
|
+
cutoff = coerceFiniteNumber(cutoff, this.cutoff);
|
|
49
49
|
cutoff = Math.max(this.minFrequency, cutoff);
|
|
50
50
|
|
|
51
51
|
if (cutoff >= this.context.sampleRate)
|
|
52
52
|
cutoff = this.context.sampleRate;
|
|
53
53
|
|
|
54
54
|
this.cutoff = cutoff;
|
|
55
|
-
return
|
|
55
|
+
return sendMessageToWorklet<LowPassFilterMessageCommandId, number>(this.audioWorkletNode, LowPassFilterMessageCommandId.SetCutoff, cutoff);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
public
|
|
58
|
+
public setMinFrequency(minFrequency: number = 10): boolean {
|
|
59
59
|
|
|
60
|
-
minFrequency =
|
|
60
|
+
minFrequency = coerceFiniteNumber(minFrequency, this.minFrequency);
|
|
61
61
|
|
|
62
62
|
if (minFrequency < 10)
|
|
63
63
|
minFrequency = 10;
|
|
64
64
|
|
|
65
65
|
this.minFrequency = minFrequency;
|
|
66
|
-
return
|
|
66
|
+
return sendMessageToWorklet<LowPassFilterMessageCommandId, number>(this.audioWorkletNode, LowPassFilterMessageCommandId.SetMinFrequency, minFrequency);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
public
|
|
69
|
+
public setQ(q: number = 0.7): boolean {
|
|
70
70
|
|
|
71
|
-
q =
|
|
71
|
+
q = coerceFiniteNumber(q, this.q);
|
|
72
72
|
q = Math.max(0.0001, q);
|
|
73
73
|
|
|
74
74
|
if(q > 4)
|
|
75
75
|
q = 4;
|
|
76
76
|
|
|
77
77
|
this.q = q;
|
|
78
|
-
return
|
|
78
|
+
return sendMessageToWorklet<LowPassFilterMessageCommandId, number>(this.audioWorkletNode, LowPassFilterMessageCommandId.SetQ, q);
|
|
79
79
|
}
|
|
80
80
|
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { AudioWorkletProcessorNames, NotchFilterMessageCommandId, NotchFilterOptions, StrictMode } from "../../../typings";
|
|
2
|
+
import { Effector } from "../../../core/classes/Effector";
|
|
3
|
+
import { DEFAULT_SAMPLE_RATE } from "../../../utilities/constants";
|
|
4
|
+
import { coerceFiniteNumber, createAudioWorkletNode, sendMessageToWorklet } from "../../../utilities/helpers";
|
|
5
|
+
|
|
6
|
+
export default class NotchFilter extends Effector {
|
|
7
|
+
|
|
8
|
+
public name: string = "NotchFilter";
|
|
9
|
+
public label: string | null = "NotchFilter";
|
|
10
|
+
|
|
11
|
+
public cutoff: number = 1000;
|
|
12
|
+
public minFrequency: number = 10;
|
|
13
|
+
public q: number = 0.7;
|
|
14
|
+
|
|
15
|
+
private contextSampleRate: number = DEFAULT_SAMPLE_RATE;
|
|
16
|
+
private strictMode: StrictMode = StrictMode.Disabled;
|
|
17
|
+
|
|
18
|
+
constructor({ cutoff, q, minFrequency, strictMode }: Partial<NotchFilterOptions> = {}) {
|
|
19
|
+
super();
|
|
20
|
+
|
|
21
|
+
this.cutoff = coerceFiniteNumber(cutoff, this.cutoff);
|
|
22
|
+
this.q = coerceFiniteNumber(q, this.q);
|
|
23
|
+
|
|
24
|
+
const mode = coerceFiniteNumber(strictMode, this.strictMode);
|
|
25
|
+
this.strictMode = mode === StrictMode.Enabled ? StrictMode.Enabled : StrictMode.Disabled;
|
|
26
|
+
this.audioWorkletNode && this.registerMessageEventListener(this.audioWorkletNode);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public async initializeOnAttachment(context: AudioContext): Promise<void> {
|
|
30
|
+
|
|
31
|
+
this.context = context;
|
|
32
|
+
this.contextSampleRate = context.sampleRate;
|
|
33
|
+
this.audioWorkletNode = createAudioWorkletNode(context, AudioWorkletProcessorNames.NotchFilter, this.returnOptionsAsObject());
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public returnOptionsAsObject(): NotchFilterOptions {
|
|
37
|
+
return {
|
|
38
|
+
cutoff: this.cutoff,
|
|
39
|
+
q: this.q,
|
|
40
|
+
strictMode: this.strictMode,
|
|
41
|
+
minFrequency: this.minFrequency
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public setCutoff(cutoff: number = 1000): boolean {
|
|
46
|
+
|
|
47
|
+
if (!this.context) return false;
|
|
48
|
+
|
|
49
|
+
cutoff = coerceFiniteNumber(cutoff, this.cutoff);
|
|
50
|
+
cutoff = Math.min(this.minFrequency, cutoff);
|
|
51
|
+
|
|
52
|
+
if (cutoff >= this.context.sampleRate)
|
|
53
|
+
cutoff = this.context.sampleRate;
|
|
54
|
+
|
|
55
|
+
this.cutoff = cutoff;
|
|
56
|
+
return sendMessageToWorklet<NotchFilterMessageCommandId, number>(this.audioWorkletNode, NotchFilterMessageCommandId.SetCutoff, cutoff);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public setMinFrequency(minFrequency: number = this.minFrequency) {
|
|
60
|
+
|
|
61
|
+
minFrequency = coerceFiniteNumber(minFrequency, this.minFrequency);
|
|
62
|
+
|
|
63
|
+
if(minFrequency < 10)
|
|
64
|
+
minFrequency = 10;
|
|
65
|
+
|
|
66
|
+
this.minFrequency = minFrequency;
|
|
67
|
+
return sendMessageToWorklet<NotchFilterMessageCommandId.SetMinFrequency, number>(this.audioWorkletNode, NotchFilterMessageCommandId.SetMinFrequency, minFrequency);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public setQ(q: number = 0.7): boolean {
|
|
71
|
+
|
|
72
|
+
q = coerceFiniteNumber(q, this.q);
|
|
73
|
+
q = Math.max(0.0001, q);
|
|
74
|
+
|
|
75
|
+
if (q > 4)
|
|
76
|
+
q = 4;
|
|
77
|
+
|
|
78
|
+
this.q = q;
|
|
79
|
+
return sendMessageToWorklet<NotchFilterMessageCommandId, number>(this.audioWorkletNode, NotchFilterMessageCommandId.SetQ, q);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -7,6 +7,7 @@ export { Saturation } from "./classes/Saturation";
|
|
|
7
7
|
export { StereoPanner } from "./classes/StereoPanner";
|
|
8
8
|
export { SoftClip } from "./classes/clips/SoftClip";
|
|
9
9
|
export { HardClip } from "./classes/clips/HardClip";
|
|
10
|
+
export { Reverb, type ReverbOptions } from "./classes/Reverb";
|
|
10
11
|
|
|
11
12
|
export { Compressor } from "./classes/compressors/Compressor";
|
|
12
13
|
export { MultibandCompressor } from "./classes/compressors/MultibandCompressor";
|
|
@@ -16,10 +17,5 @@ export { MonoDelay } from "./classes/delays/MonoDelay";
|
|
|
16
17
|
export { PingPongDelay } from "./classes/delays/PingPongDelay";
|
|
17
18
|
export { StereoDelay } from "./classes/delays/StereoDelay";
|
|
18
19
|
|
|
19
|
-
export { ChamberReverb } from "./classes/reverbs/ChamberReverb";
|
|
20
|
-
export { ConvolverReverb } from "./classes/reverbs/ConvolverReverb";
|
|
21
|
-
export { GenericReverb } from "./classes/reverbs/GenericReverb";
|
|
22
|
-
export { HallReverb } from "./classes/reverbs/HallReverb";
|
|
23
|
-
export { RoomReverb } from "./classes/reverbs/RoomReverb";
|
|
24
|
-
|
|
25
20
|
export { LowPassFilter } from "./classes/filters/LowPassFilter";
|
|
21
|
+
export { HighPassFilter } from "./classes/filters/HighPassFilter";
|
package/lib/src/index.ts
CHANGED
|
@@ -33,14 +33,11 @@ export {
|
|
|
33
33
|
MonoDelay,
|
|
34
34
|
PingPongDelay,
|
|
35
35
|
StereoDelay,
|
|
36
|
-
ChamberReverb,
|
|
37
|
-
ConvolverReverb,
|
|
38
|
-
GenericReverb,
|
|
39
|
-
HallReverb,
|
|
40
|
-
RoomReverb,
|
|
41
36
|
SoftClip,
|
|
42
37
|
LowPassFilter,
|
|
43
|
-
HardClip
|
|
38
|
+
HardClip,
|
|
39
|
+
HighPassFilter,
|
|
40
|
+
Reverb, type ReverbOptions
|
|
44
41
|
} from "./effects/exports";
|
|
45
42
|
|
|
46
43
|
export {
|
|
@@ -54,19 +51,20 @@ export {
|
|
|
54
51
|
} from "./core/exports";
|
|
55
52
|
|
|
56
53
|
export {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
54
|
+
initializeDspPipeline,
|
|
55
|
+
resolveAudioOutputDevices,
|
|
56
|
+
resolveAudioInputDevices,
|
|
57
|
+
resolveDefaultAudioInputDevice,
|
|
58
|
+
resolveDefaultAudioOutputDevice,
|
|
59
|
+
loadAudioSource,
|
|
60
|
+
loadAudioSourceFromBlob,
|
|
61
|
+
loadWorkletOnAudioDevice,
|
|
62
|
+
sendMessageToWorklet
|
|
66
63
|
} from "./utilities/helpers";
|
|
67
64
|
|
|
68
65
|
export {
|
|
69
|
-
SUPPORTED_FILE_TYPES
|
|
66
|
+
SUPPORTED_FILE_TYPES,
|
|
67
|
+
DEFAULT_SAMPLE_RATE
|
|
70
68
|
} from "./utilities/constants";
|
|
71
69
|
|
|
72
70
|
export {
|
|
@@ -106,5 +104,5 @@ export type {
|
|
|
106
104
|
IncomingProcessorMessage,
|
|
107
105
|
ProcessorData,
|
|
108
106
|
EffectorEvents,
|
|
109
|
-
ArrayPosition
|
|
107
|
+
ArrayPosition,
|
|
110
108
|
} from "./typings";
|
package/lib/src/typings.ts
CHANGED
|
@@ -4,7 +4,6 @@ export type AudioClipAnalyserProperty = "fftSize" | "minDecibels" | "maxDecibels
|
|
|
4
4
|
export type IncomingMessageType = "message" | "error" | "warning" | "wasm-instantiated";
|
|
5
5
|
export type ArrayPosition = "start" | "middle" | "end" | "one-after-start" | "one-before-end";
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
export type AudioClipEvents = {
|
|
9
8
|
[K in keyof AudioClipEventMap]: AudioClipEventMap[K][];
|
|
10
9
|
}
|
|
@@ -19,6 +18,18 @@ export enum LowPassFilterMessageCommandId {
|
|
|
19
18
|
SetQ
|
|
20
19
|
}
|
|
21
20
|
|
|
21
|
+
export enum HighPassFilterMessageCommandId {
|
|
22
|
+
SetCutoff,
|
|
23
|
+
SetMaxFrequency,
|
|
24
|
+
SetQ
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export enum NotchFilterMessageCommandId {
|
|
28
|
+
SetCutoff,
|
|
29
|
+
SetMinFrequency,
|
|
30
|
+
SetQ
|
|
31
|
+
}
|
|
32
|
+
|
|
22
33
|
export enum ChorusMessageCommandId {
|
|
23
34
|
SetBaseDelayMs,
|
|
24
35
|
SetDepthMs,
|
|
@@ -108,8 +119,21 @@ export interface AudioClipOnProgressEvent {
|
|
|
108
119
|
formatted: string;
|
|
109
120
|
}
|
|
110
121
|
|
|
122
|
+
export interface AudioClipOnInitializeEvent {
|
|
123
|
+
durationOfInitialization: number;
|
|
124
|
+
context: AudioContext | null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface AudioClipOnPlayEvent {
|
|
128
|
+
timestamp: number;
|
|
129
|
+
audioBufferSourceNodes: AudioBufferSourceNode[];
|
|
130
|
+
context: AudioContext;
|
|
131
|
+
}
|
|
132
|
+
|
|
111
133
|
export interface AudioClipEventMap {
|
|
112
134
|
"progress": (event: AudioClipOnProgressEvent) => void;
|
|
135
|
+
"initialize": (event: AudioClipOnInitializeEvent) => void;
|
|
136
|
+
"play": (event: AudioClipOnPlayEvent) => void;
|
|
113
137
|
}
|
|
114
138
|
|
|
115
139
|
export interface DspPipelineInitializationOptions {
|
|
@@ -139,6 +163,20 @@ export interface LowPassFilterOptions {
|
|
|
139
163
|
strictMode: StrictMode;
|
|
140
164
|
}
|
|
141
165
|
|
|
166
|
+
export interface HighPassFilterOptions {
|
|
167
|
+
cutoff: number;
|
|
168
|
+
q: number;
|
|
169
|
+
maxFrequency: number;
|
|
170
|
+
strictMode: StrictMode;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export interface NotchFilterOptions {
|
|
174
|
+
cutoff: number;
|
|
175
|
+
q: number;
|
|
176
|
+
minFrequency: number;
|
|
177
|
+
strictMode: StrictMode;
|
|
178
|
+
}
|
|
179
|
+
|
|
142
180
|
export interface SoftClipOptions {
|
|
143
181
|
drive: number;
|
|
144
182
|
gain: number;
|
|
@@ -4,7 +4,7 @@ import { DSP } from "../index";
|
|
|
4
4
|
|
|
5
5
|
export namespace Debug {
|
|
6
6
|
|
|
7
|
-
export function
|
|
7
|
+
export function log(message: string, additionalDetails?: string[]) {
|
|
8
8
|
|
|
9
9
|
if (!DSP.debugger.showInfo) return;
|
|
10
10
|
|
|
@@ -17,7 +17,7 @@ export namespace Debug {
|
|
|
17
17
|
return console.log(outputString, "color: white;", "color: gray", "color: gray");
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export function
|
|
20
|
+
export function success(message: string, additionalDetails?: string[]) {
|
|
21
21
|
|
|
22
22
|
if (!DSP.debugger.showInfo) return;
|
|
23
23
|
|
|
@@ -30,7 +30,7 @@ export namespace Debug {
|
|
|
30
30
|
return console.log(outputString, "color: lime;", "color: white", "color: gray");
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export function
|
|
33
|
+
export function warn(message: string, additionalDetails?: string[], warningCode?: WarningCodes) {
|
|
34
34
|
|
|
35
35
|
if (!DSP.debugger.showWarnings) return;
|
|
36
36
|
|
|
@@ -43,7 +43,7 @@ export namespace Debug {
|
|
|
43
43
|
return console.log(outputString, "color: gray", "color: yellow;", "color: white", "color: white; font-style: italic;");
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export function
|
|
46
|
+
export function error(message: string, additionalDetails?: string[], errorCode?: ErrorCodes) {
|
|
47
47
|
|
|
48
48
|
if (!DSP.debugger.showErrors) return;
|
|
49
49
|
|