@fluex/fluexgl-dsp 0.4.6 → 0.4.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/lib/dist/core/classes/AudioClip.d.ts +2 -0
- package/lib/dist/core/classes/AudioClip.d.ts.map +1 -1
- package/lib/dist/core/classes/AudioClip.js +14 -2
- package/lib/dist/effects/classes/Analyser.d.ts +6 -2
- package/lib/dist/effects/classes/Analyser.d.ts.map +1 -1
- package/lib/dist/effects/classes/Analyser.js +24 -8
- 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/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 +1 -0
- package/lib/dist/effects/exports.d.ts.map +1 -1
- package/lib/dist/effects/exports.js +1 -0
- package/lib/dist/index.d.ts +3 -3
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +2 -2
- package/lib/dist/typings.d.ts +22 -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/src/core/classes/AudioClip.ts +19 -2
- package/lib/src/effects/classes/Analyser.ts +28 -8
- package/lib/src/effects/classes/filters/HighPassFilter.ts +81 -0
- package/lib/src/effects/classes/filters/NotchFilter.ts +81 -0
- package/lib/src/effects/exports.ts +1 -0
- package/lib/src/index.ts +5 -3
- package/lib/src/typings.ts +26 -1
- package/lib/src/utilities/constants.ts +3 -1
- package/package.json +1 -1
|
@@ -10,6 +10,7 @@ export declare class AudioClip {
|
|
|
10
10
|
isPlaying: boolean;
|
|
11
11
|
startTime: number;
|
|
12
12
|
offsetAtStart: number;
|
|
13
|
+
playbackRate: number;
|
|
13
14
|
progressUpdateSpeed: number;
|
|
14
15
|
gainNode: GainNode | null;
|
|
15
16
|
stereoPannerNode: StereoPannerNode | null;
|
|
@@ -40,6 +41,7 @@ export declare class AudioClip {
|
|
|
40
41
|
GetChannelData(channel?: number): Float32Array;
|
|
41
42
|
Send(channel: Channel | Master): void;
|
|
42
43
|
Unsend(channel: Channel | Master): void;
|
|
44
|
+
SetPlaybackRateInSemitones(semitones: number): AudioClip;
|
|
43
45
|
get currentPlaybackTime(): number;
|
|
44
46
|
get duration(): number;
|
|
45
47
|
get volume(): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioClip.d.ts","sourceRoot":"","sources":["../../../src/core/classes/AudioClip.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAmB,eAAe,EAAE,MAAM,eAAe,CAAC;AAEpF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAMlC,qBAAa,SAAS;
|
|
1
|
+
{"version":3,"file":"AudioClip.d.ts","sourceRoot":"","sources":["../../../src/core/classes/AudioClip.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAmB,eAAe,EAAE,MAAM,eAAe,CAAC;AAEpF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAMlC,qBAAa,SAAS;IA4BC,IAAI,EAAE,eAAe;IA1BjC,EAAE,EAAE,MAAM,CAAQ;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE5B,IAAI,EAAE,OAAO,CAAS;IACtB,SAAS,EAAE,OAAO,CAAS;IAC3B,SAAS,EAAE,MAAM,CAAK;IACtB,aAAa,EAAE,MAAM,CAAK;IAC1B,YAAY,EAAE,MAAM,CAAK;IAEzB,mBAAmB,EAAE,MAAM,CAAM;IAEjC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IACjC,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IAEjD,OAAO,EAAE,YAAY,GAAG,IAAI,CAAQ;IACpC,eAAe,EAAE,eAAe,GAAG,IAAI,CAAQ;IAEtD,OAAO,CAAC,sBAAsB,CAA+B;IAC7D,OAAO,CAAC,yBAAyB,CAAa;IAE9C,OAAO,CAAC,gBAAgB,CAAoB;IAE5C,OAAO,CAAC,MAAM,CAEb;gBAEkB,IAAI,EAAE,eAAe;IAExC,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,gBAAgB;IAmBjB,UAAU,CAAC,eAAe,EAAE,eAAe;IAc3C,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAqExC,IAAI,CAAC,OAAO,EAAE,MAAM;IAsBpB,IAAI,IAAI,SAAS,GAAG,IAAI;IAkBxB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAUpC,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS;IAexC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS;IAU/B,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS;IAatD,mCAAmC,IAAI,OAAO;IAc9C,gBAAgB,CAAC,CAAC,SAAS,MAAM,iBAAiB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAMnG,IAAI,CAAC,CAAC,SAAS,MAAM,iBAAiB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAYvF,mBAAmB,CAAC,CAAC,SAAS,MAAM,iBAAiB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,SAAS;IAarG,mBAAmB,CAAC,KAAK,CAAC,EAAE,MAAM,iBAAiB,GAAG,SAAS;IAW/D,cAAc,CAAC,OAAO,GAAE,MAAU,GAAG,YAAY;IAIjD,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAW9B,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAWhC,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;IAe/D,IAAW,mBAAmB,IAAI,MAAM,CAIvC;IAED,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAED,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED,IAAW,aAAa,IAAI,MAAM,CAEjC;IAED,IAAW,iBAAiB,IAAI,MAAM,CAKrC;IAED,IAAW,UAAU,IAAI,MAAM,CAE9B;IAED,IAAW,gBAAgB,IAAI,MAAM,CAEpC;IAED,IAAW,UAAU,IAAI,MAAM,CAE9B;CACJ"}
|
|
@@ -11,6 +11,7 @@ export class AudioClip {
|
|
|
11
11
|
isPlaying = false;
|
|
12
12
|
startTime = 0;
|
|
13
13
|
offsetAtStart = 0;
|
|
14
|
+
playbackRate = 1;
|
|
14
15
|
progressUpdateSpeed = 20;
|
|
15
16
|
gainNode = null;
|
|
16
17
|
stereoPannerNode = null;
|
|
@@ -32,6 +33,7 @@ export class AudioClip {
|
|
|
32
33
|
const bufferSource = context.createBufferSource();
|
|
33
34
|
bufferSource.buffer = this.data.audioBuffer;
|
|
34
35
|
bufferSource.loop = this.loop;
|
|
36
|
+
bufferSource.playbackRate.setValueAtTime(this.playbackRate, this.context.currentTime);
|
|
35
37
|
return bufferSource;
|
|
36
38
|
}
|
|
37
39
|
connectSourcesTo(target) {
|
|
@@ -86,9 +88,9 @@ export class AudioClip {
|
|
|
86
88
|
this.offsetAtStart = actualOffset;
|
|
87
89
|
this.isPlaying = true;
|
|
88
90
|
if (this.progressInterval)
|
|
89
|
-
clearInterval(this.progressInterval);
|
|
91
|
+
window.clearInterval(this.progressInterval);
|
|
90
92
|
if (this.isPlaying)
|
|
91
|
-
this.progressInterval = setInterval(function () {
|
|
93
|
+
this.progressInterval = window.setInterval(function () {
|
|
92
94
|
if (!self.isPlaying)
|
|
93
95
|
return;
|
|
94
96
|
const current = self.offsetAtStart + (context.currentTime - self.startTime);
|
|
@@ -246,6 +248,16 @@ export class AudioClip {
|
|
|
246
248
|
]);
|
|
247
249
|
channel.audioClipPlayer.DetachAudioClip(this);
|
|
248
250
|
}
|
|
251
|
+
SetPlaybackRateInSemitones(semitones) {
|
|
252
|
+
if (!this.context)
|
|
253
|
+
throw new Error("Could not set playback rate because the AudioContext is not defined.");
|
|
254
|
+
const calculatedPlaybackRate = Math.pow(2, semitones / 12);
|
|
255
|
+
for (const buffer of this.audioBufferSourceNodes) {
|
|
256
|
+
buffer.playbackRate.setValueAtTime(calculatedPlaybackRate, this.context?.currentTime);
|
|
257
|
+
}
|
|
258
|
+
this.playbackRate = calculatedPlaybackRate;
|
|
259
|
+
return this;
|
|
260
|
+
}
|
|
249
261
|
get currentPlaybackTime() {
|
|
250
262
|
return (!this.isPlaying || !this.context)
|
|
251
263
|
? 0
|
|
@@ -3,14 +3,18 @@ export declare class Analyser extends Effector {
|
|
|
3
3
|
label: string | null;
|
|
4
4
|
name: string;
|
|
5
5
|
analyserNode: AnalyserNode | null;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
waveformFloat32ArrayBuffer: Float32Array<ArrayBuffer>;
|
|
7
|
+
waveformUint8ArrayBuffer: Uint8Array<ArrayBuffer>;
|
|
8
|
+
frequencyFloat32ArrayBuffer: Float32Array<ArrayBuffer>;
|
|
9
|
+
frequencyUint8ArrayBuffer: Uint8Array<ArrayBuffer>;
|
|
8
10
|
private options;
|
|
9
11
|
constructor(options?: Partial<AnalyserOptions>);
|
|
10
12
|
InitializeOnAttachment(context: AudioContext): Promise<void>;
|
|
11
13
|
SetOptions(options: Partial<AnalyserOptions>): void;
|
|
12
14
|
GetWaveformFloatData(): Float32Array | null;
|
|
13
15
|
GetWaveformByteData(): Uint8Array | null;
|
|
16
|
+
GetFrequencyFloatData(): Float32Array | null;
|
|
17
|
+
GetFrequencyByteData(): Uint8Array | null;
|
|
14
18
|
private allocateBuffers;
|
|
15
19
|
}
|
|
16
20
|
//# sourceMappingURL=Analyser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Analyser.d.ts","sourceRoot":"","sources":["../../../src/effects/classes/Analyser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAI9C,qBAAa,QAAS,SAAQ,QAAQ;IAE3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAc;IAClC,IAAI,EAAE,MAAM,CAAc;IAE1B,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IAEzC,
|
|
1
|
+
{"version":3,"file":"Analyser.d.ts","sourceRoot":"","sources":["../../../src/effects/classes/Analyser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAI9C,qBAAa,QAAS,SAAQ,QAAQ;IAE3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAc;IAClC,IAAI,EAAE,MAAM,CAAc;IAE1B,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IAEzC,0BAA0B,4BAAsB;IAChD,wBAAwB,0BAAoB;IAC5C,2BAA2B,4BAAsB;IACjD,yBAAyB,0BAAoB;IAEpD,OAAO,CAAC,OAAO,CAKb;gBAEU,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;IAMjC,sBAAsB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IASlE,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IAwBnD,oBAAoB,IAAI,YAAY,GAAG,IAAI;IAQ3C,mBAAmB,IAAI,UAAU,GAAG,IAAI;IAQxC,qBAAqB,IAAI,YAAY,GAAG,IAAI;IAQ5C,oBAAoB,IAAI,UAAU,GAAG,IAAI;IAQhD,OAAO,CAAC,eAAe;CAS1B"}
|
|
@@ -3,8 +3,10 @@ export class Analyser extends Effector {
|
|
|
3
3
|
label = "Analyser";
|
|
4
4
|
name = "Analyser";
|
|
5
5
|
analyserNode = null;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
waveformFloat32ArrayBuffer = new Float32Array();
|
|
7
|
+
waveformUint8ArrayBuffer = new Uint8Array();
|
|
8
|
+
frequencyFloat32ArrayBuffer = new Float32Array();
|
|
9
|
+
frequencyUint8ArrayBuffer = new Uint8Array();
|
|
8
10
|
options = {
|
|
9
11
|
fftSize: 32,
|
|
10
12
|
smoothingTimeConstant: 0.8,
|
|
@@ -44,19 +46,33 @@ export class Analyser extends Effector {
|
|
|
44
46
|
GetWaveformFloatData() {
|
|
45
47
|
if (!this.analyserNode)
|
|
46
48
|
return null;
|
|
47
|
-
this.analyserNode.getFloatTimeDomainData(this.
|
|
48
|
-
return this.
|
|
49
|
+
this.analyserNode.getFloatTimeDomainData(this.waveformFloat32ArrayBuffer);
|
|
50
|
+
return this.waveformFloat32ArrayBuffer;
|
|
49
51
|
}
|
|
50
52
|
GetWaveformByteData() {
|
|
51
53
|
if (!this.analyserNode)
|
|
52
54
|
return null;
|
|
53
|
-
this.analyserNode.getByteTimeDomainData(this.
|
|
54
|
-
return this.
|
|
55
|
+
this.analyserNode.getByteTimeDomainData(this.waveformUint8ArrayBuffer);
|
|
56
|
+
return this.waveformUint8ArrayBuffer;
|
|
57
|
+
}
|
|
58
|
+
GetFrequencyFloatData() {
|
|
59
|
+
if (!this.analyserNode)
|
|
60
|
+
return null;
|
|
61
|
+
this.analyserNode.getFloatFrequencyData(this.frequencyFloat32ArrayBuffer);
|
|
62
|
+
return this.frequencyFloat32ArrayBuffer;
|
|
63
|
+
}
|
|
64
|
+
GetFrequencyByteData() {
|
|
65
|
+
if (!this.analyserNode)
|
|
66
|
+
return null;
|
|
67
|
+
this.analyserNode.getByteFrequencyData(this.frequencyUint8ArrayBuffer);
|
|
68
|
+
return this.frequencyUint8ArrayBuffer;
|
|
55
69
|
}
|
|
56
70
|
allocateBuffers() {
|
|
57
71
|
if (!this.analyserNode)
|
|
58
72
|
return;
|
|
59
|
-
this.
|
|
60
|
-
this.
|
|
73
|
+
this.waveformFloat32ArrayBuffer = new Float32Array(this.analyserNode.fftSize);
|
|
74
|
+
this.waveformUint8ArrayBuffer = new Uint8Array(this.analyserNode.fftSize);
|
|
75
|
+
this.frequencyFloat32ArrayBuffer = new Float32Array(this.analyserNode.fftSize);
|
|
76
|
+
this.frequencyUint8ArrayBuffer = new Uint8Array(this.analyserNode.fftSize);
|
|
61
77
|
}
|
|
62
78
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Effector } from "../../../core/classes/Effector";
|
|
2
|
+
import { HighPassFilterOptions, StrictMode } from "../../../typings";
|
|
3
|
+
export declare class HighPassFilter extends Effector {
|
|
4
|
+
name: string;
|
|
5
|
+
label: string | null;
|
|
6
|
+
cutoff: number;
|
|
7
|
+
q: number;
|
|
8
|
+
strictMode: StrictMode;
|
|
9
|
+
maxFrequency: number;
|
|
10
|
+
private contextSampleRate;
|
|
11
|
+
constructor({ cutoff, q, strictMode }?: Partial<HighPassFilterOptions>);
|
|
12
|
+
InitializeOnAttachment(context: AudioContext): Promise<void>;
|
|
13
|
+
ReturnOptionsAsObject(): HighPassFilterOptions;
|
|
14
|
+
SetCutoff(cutoff?: number): boolean;
|
|
15
|
+
SetMaxFrequency(maxFrequency?: number): boolean;
|
|
16
|
+
SetQ(q?: number): boolean;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=HighPassFilter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HighPassFilter.d.ts","sourceRoot":"","sources":["../../../../src/effects/classes/filters/HighPassFilter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAA8D,qBAAqB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGjI,qBAAa,cAAe,SAAQ,QAAQ;IAEjC,IAAI,EAAE,MAAM,CAAoB;IAChC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAoB;IAExC,MAAM,EAAE,MAAM,CAAQ;IACtB,CAAC,EAAE,MAAM,CAAO;IAChB,UAAU,EAAE,UAAU,CAAuB;IAC7C,YAAY,EAAE,MAAM,CAA6B;IAExD,OAAO,CAAC,iBAAiB,CAA+B;gBAE5C,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,GAAE,OAAO,CAAC,qBAAqB,CAAM;IAW7D,sBAAsB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlE,qBAAqB,IAAI,qBAAqB;IAS9C,SAAS,CAAC,MAAM,GAAE,MAAa,GAAG,OAAO;IAczC,eAAe,CAAC,YAAY,GAAE,MAA0B;IAWxD,IAAI,CAAC,CAAC,GAAE,MAAY,GAAG,OAAO;CAWxC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { CoerceFiniteNumber, CreateAudioWorkletNode, SendMessageToWorklet } from "../../../utilities/helpers";
|
|
2
|
+
import { Effector } from "../../../core/classes/Effector";
|
|
3
|
+
import { AudioWorkletProcessorNames, HighPassFilterMessageCommandId, StrictMode } from "../../../typings";
|
|
4
|
+
import { DEFAULT_SAMPLE_RATE } from "../../../utilities/constants";
|
|
5
|
+
export class HighPassFilter extends Effector {
|
|
6
|
+
name = "HighPassFilter";
|
|
7
|
+
label = "HighPassFilter";
|
|
8
|
+
cutoff = 1000;
|
|
9
|
+
q = 0.7;
|
|
10
|
+
strictMode = StrictMode.Disabled;
|
|
11
|
+
maxFrequency = DEFAULT_SAMPLE_RATE * 0.5;
|
|
12
|
+
contextSampleRate = DEFAULT_SAMPLE_RATE;
|
|
13
|
+
constructor({ cutoff, q, strictMode } = {}) {
|
|
14
|
+
super();
|
|
15
|
+
this.cutoff = CoerceFiniteNumber(cutoff, this.cutoff);
|
|
16
|
+
this.q = CoerceFiniteNumber(q, this.q);
|
|
17
|
+
const mode = CoerceFiniteNumber(strictMode, this.strictMode);
|
|
18
|
+
this.strictMode = mode === StrictMode.Enabled ? StrictMode.Enabled : StrictMode.Disabled;
|
|
19
|
+
this.audioWorkletNode && this.registerMessageEventListener(this.audioWorkletNode);
|
|
20
|
+
}
|
|
21
|
+
async InitializeOnAttachment(context) {
|
|
22
|
+
this.context = context;
|
|
23
|
+
this.contextSampleRate = context.sampleRate;
|
|
24
|
+
this.audioWorkletNode = CreateAudioWorkletNode(context, AudioWorkletProcessorNames.HighPassFilter, this.ReturnOptionsAsObject());
|
|
25
|
+
}
|
|
26
|
+
ReturnOptionsAsObject() {
|
|
27
|
+
return {
|
|
28
|
+
cutoff: this.cutoff,
|
|
29
|
+
q: this.q,
|
|
30
|
+
strictMode: this.strictMode,
|
|
31
|
+
maxFrequency: this.maxFrequency
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
SetCutoff(cutoff = 1000) {
|
|
35
|
+
if (!this.context)
|
|
36
|
+
return false;
|
|
37
|
+
cutoff = CoerceFiniteNumber(cutoff, this.cutoff);
|
|
38
|
+
cutoff = Math.min(this.maxFrequency, cutoff);
|
|
39
|
+
if (cutoff >= this.context.sampleRate)
|
|
40
|
+
cutoff = this.context.sampleRate;
|
|
41
|
+
this.cutoff = cutoff;
|
|
42
|
+
return SendMessageToWorklet(this.audioWorkletNode, HighPassFilterMessageCommandId.SetCutoff, cutoff);
|
|
43
|
+
}
|
|
44
|
+
SetMaxFrequency(maxFrequency = this.maxFrequency) {
|
|
45
|
+
maxFrequency = CoerceFiniteNumber(maxFrequency, this.maxFrequency);
|
|
46
|
+
if (maxFrequency > (this.contextSampleRate * 0.5))
|
|
47
|
+
throw new Error("Could not set the max frequency, because the value is over the sample rate.");
|
|
48
|
+
this.maxFrequency = maxFrequency;
|
|
49
|
+
return SendMessageToWorklet(this.audioWorkletNode, HighPassFilterMessageCommandId.SetMaxFrequency, maxFrequency);
|
|
50
|
+
}
|
|
51
|
+
SetQ(q = 0.7) {
|
|
52
|
+
q = CoerceFiniteNumber(q, this.q);
|
|
53
|
+
q = Math.max(0.0001, q);
|
|
54
|
+
if (q > 4)
|
|
55
|
+
q = 4;
|
|
56
|
+
this.q = q;
|
|
57
|
+
return SendMessageToWorklet(this.audioWorkletNode, HighPassFilterMessageCommandId.SetQ, q);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NotchFilterOptions } from "../../../typings";
|
|
2
|
+
import { Effector } from "../../../core/classes/Effector";
|
|
3
|
+
export default class NotchFilter extends Effector {
|
|
4
|
+
name: string;
|
|
5
|
+
label: string | null;
|
|
6
|
+
cutoff: number;
|
|
7
|
+
minFrequency: number;
|
|
8
|
+
q: number;
|
|
9
|
+
private contextSampleRate;
|
|
10
|
+
private strictMode;
|
|
11
|
+
constructor({ cutoff, q, minFrequency, strictMode }?: Partial<NotchFilterOptions>);
|
|
12
|
+
InitializeOnAttachment(context: AudioContext): Promise<void>;
|
|
13
|
+
ReturnOptionsAsObject(): NotchFilterOptions;
|
|
14
|
+
SetCutoff(cutoff?: number): boolean;
|
|
15
|
+
SetMinFrequency(minFrequency?: number): boolean;
|
|
16
|
+
SetQ(q?: number): boolean;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=NotchFilter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NotchFilter.d.ts","sourceRoot":"","sources":["../../../../src/effects/classes/filters/NotchFilter.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2D,kBAAkB,EAAc,MAAM,kBAAkB,CAAC;AAC3H,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAI1D,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,QAAQ;IAEtC,IAAI,EAAE,MAAM,CAAiB;IAC7B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAiB;IAErC,MAAM,EAAE,MAAM,CAAQ;IACtB,YAAY,EAAE,MAAM,CAAM;IAC1B,CAAC,EAAE,MAAM,CAAO;IAEvB,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,UAAU,CAAmC;gBAEzC,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,GAAE,OAAO,CAAC,kBAAkB,CAAM;IAWxE,sBAAsB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlE,qBAAqB,IAAI,kBAAkB;IAS3C,SAAS,CAAC,MAAM,GAAE,MAAa,GAAG,OAAO;IAczC,eAAe,CAAC,YAAY,GAAE,MAA0B;IAWxD,IAAI,CAAC,CAAC,GAAE,MAAY,GAAG,OAAO;CAWxC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { AudioWorkletProcessorNames, NotchFilterMessageCommandId, 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
|
+
export default class NotchFilter extends Effector {
|
|
6
|
+
name = "NotchFilter";
|
|
7
|
+
label = "NotchFilter";
|
|
8
|
+
cutoff = 1000;
|
|
9
|
+
minFrequency = 10;
|
|
10
|
+
q = 0.7;
|
|
11
|
+
contextSampleRate = DEFAULT_SAMPLE_RATE;
|
|
12
|
+
strictMode = StrictMode.Disabled;
|
|
13
|
+
constructor({ cutoff, q, minFrequency, strictMode } = {}) {
|
|
14
|
+
super();
|
|
15
|
+
this.cutoff = CoerceFiniteNumber(cutoff, this.cutoff);
|
|
16
|
+
this.q = CoerceFiniteNumber(q, this.q);
|
|
17
|
+
const mode = CoerceFiniteNumber(strictMode, this.strictMode);
|
|
18
|
+
this.strictMode = mode === StrictMode.Enabled ? StrictMode.Enabled : StrictMode.Disabled;
|
|
19
|
+
this.audioWorkletNode && this.registerMessageEventListener(this.audioWorkletNode);
|
|
20
|
+
}
|
|
21
|
+
async InitializeOnAttachment(context) {
|
|
22
|
+
this.context = context;
|
|
23
|
+
this.contextSampleRate = context.sampleRate;
|
|
24
|
+
this.audioWorkletNode = CreateAudioWorkletNode(context, AudioWorkletProcessorNames.NotchFilter, this.ReturnOptionsAsObject());
|
|
25
|
+
}
|
|
26
|
+
ReturnOptionsAsObject() {
|
|
27
|
+
return {
|
|
28
|
+
cutoff: this.cutoff,
|
|
29
|
+
q: this.q,
|
|
30
|
+
strictMode: this.strictMode,
|
|
31
|
+
minFrequency: this.minFrequency
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
SetCutoff(cutoff = 1000) {
|
|
35
|
+
if (!this.context)
|
|
36
|
+
return false;
|
|
37
|
+
cutoff = CoerceFiniteNumber(cutoff, this.cutoff);
|
|
38
|
+
cutoff = Math.min(this.minFrequency, cutoff);
|
|
39
|
+
if (cutoff >= this.context.sampleRate)
|
|
40
|
+
cutoff = this.context.sampleRate;
|
|
41
|
+
this.cutoff = cutoff;
|
|
42
|
+
return SendMessageToWorklet(this.audioWorkletNode, NotchFilterMessageCommandId.SetCutoff, cutoff);
|
|
43
|
+
}
|
|
44
|
+
SetMinFrequency(minFrequency = this.minFrequency) {
|
|
45
|
+
minFrequency = CoerceFiniteNumber(minFrequency, this.minFrequency);
|
|
46
|
+
if (minFrequency < 10)
|
|
47
|
+
minFrequency = 10;
|
|
48
|
+
this.minFrequency = minFrequency;
|
|
49
|
+
return SendMessageToWorklet(this.audioWorkletNode, NotchFilterMessageCommandId.SetMinFrequency, minFrequency);
|
|
50
|
+
}
|
|
51
|
+
SetQ(q = 0.7) {
|
|
52
|
+
q = CoerceFiniteNumber(q, this.q);
|
|
53
|
+
q = Math.max(0.0001, q);
|
|
54
|
+
if (q > 4)
|
|
55
|
+
q = 4;
|
|
56
|
+
this.q = q;
|
|
57
|
+
return SendMessageToWorklet(this.audioWorkletNode, NotchFilterMessageCommandId.SetQ, q);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -19,4 +19,5 @@ export { GenericReverb } from "./classes/reverbs/GenericReverb";
|
|
|
19
19
|
export { HallReverb } from "./classes/reverbs/HallReverb";
|
|
20
20
|
export { RoomReverb } from "./classes/reverbs/RoomReverb";
|
|
21
21
|
export { LowPassFilter } from "./classes/filters/LowPassFilter";
|
|
22
|
+
export { HighPassFilter } from "./classes/filters/HighPassFilter";
|
|
22
23
|
//# sourceMappingURL=exports.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../../src/effects/exports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE1D,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC"}
|
|
1
|
+
{"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../../src/effects/exports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE1D,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC"}
|
|
@@ -19,3 +19,4 @@ export { GenericReverb } from "./classes/reverbs/GenericReverb";
|
|
|
19
19
|
export { HallReverb } from "./classes/reverbs/HallReverb";
|
|
20
20
|
export { RoomReverb } from "./classes/reverbs/RoomReverb";
|
|
21
21
|
export { LowPassFilter } from "./classes/filters/LowPassFilter";
|
|
22
|
+
export { HighPassFilter } from "./classes/filters/HighPassFilter";
|
package/lib/dist/index.d.ts
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { DspOptions } from "./typings";
|
|
6
6
|
export declare const DSP: DspOptions;
|
|
7
|
-
export { Chorus, Analyser, Distortion, Equalizer, Limiter, Saturation, StereoPanner, Compressor, MultibandCompressor, AdvancedDelay, MonoDelay, PingPongDelay, StereoDelay, ChamberReverb, ConvolverReverb, GenericReverb, HallReverb, RoomReverb, SoftClip, LowPassFilter, HardClip } from "./effects/exports";
|
|
7
|
+
export { Chorus, Analyser, Distortion, Equalizer, Limiter, Saturation, StereoPanner, Compressor, MultibandCompressor, AdvancedDelay, MonoDelay, PingPongDelay, StereoDelay, ChamberReverb, ConvolverReverb, GenericReverb, HallReverb, RoomReverb, SoftClip, LowPassFilter, HardClip, HighPassFilter } from "./effects/exports";
|
|
8
8
|
export { AudioDevice, Channel, Effector, Master, AudioClip, DspPipeline, AudioClipPlayer } from "./core/exports";
|
|
9
9
|
export { InitializeDspPipeline, ResolveAudioOutputDevices, ResolveAudioInputDevices, ResolveDefaultAudioInputDevice, ResolveDefaultAudioOutputDevice, LoadAudioSource, LoadAudioSourceFromBlob, LoadWorkletOnAudioDevice, SendMessageToWorklet } from "./utilities/helpers";
|
|
10
|
-
export { SUPPORTED_FILE_TYPES } from "./utilities/constants";
|
|
10
|
+
export { SUPPORTED_FILE_TYPES, DEFAULT_SAMPLE_RATE } from "./utilities/constants";
|
|
11
11
|
export { hasInitializedWasm, } from "./utilities/web-assembly";
|
|
12
12
|
export { StrictMode, ProcessorIdentificationCodes, HardClipMessageCommandId, SoftClipMessageCommandId, AudioWorkletProcessorNames, ChorusMessageCommandId, LowPassFilterMessageCommandId, } from "./typings";
|
|
13
|
-
export type { DspDebuggerOptions, DspOptions, LoadAudioSourceOptions, AudioSourceData, ChannelOptions, ChannelSpatialization, AudioClipEventMap, AudioClipEvents, AudioClipOnProgressEvent, AudioClipAnalyserProperty, AudioClipAnalyserType, DspPipelineInitializationOptions, DspPipelineInitializationState, ChorusEffectOptions, LowPassFilterOptions, SoftClipOptions, HardClipOptions, EffectorEventMap, IncomingMessageType, IncomingProcessorMessage, ProcessorData, EffectorEvents, ArrayPosition } from "./typings";
|
|
13
|
+
export type { DspDebuggerOptions, DspOptions, LoadAudioSourceOptions, AudioSourceData, ChannelOptions, ChannelSpatialization, AudioClipEventMap, AudioClipEvents, AudioClipOnProgressEvent, AudioClipAnalyserProperty, AudioClipAnalyserType, DspPipelineInitializationOptions, DspPipelineInitializationState, ChorusEffectOptions, LowPassFilterOptions, SoftClipOptions, HardClipOptions, EffectorEventMap, IncomingMessageType, IncomingProcessorMessage, ProcessorData, EffectorEvents, ArrayPosition, } from "./typings";
|
|
14
14
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,eAAO,MAAM,GAAG,EAAE,UAYjB,CAAA;AAED,OAAO,EACH,MAAM,EACN,QAAQ,EACR,UAAU,EACV,SAAS,EACT,OAAO,EACP,UAAU,EACV,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,aAAa,EACb,WAAW,EACX,aAAa,EACb,eAAe,EACf,aAAa,EACb,UAAU,EACV,UAAU,EACV,QAAQ,EACR,aAAa,EACb,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,eAAO,MAAM,GAAG,EAAE,UAYjB,CAAA;AAED,OAAO,EACH,MAAM,EACN,QAAQ,EACR,UAAU,EACV,SAAS,EACT,OAAO,EACP,UAAU,EACV,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,aAAa,EACb,WAAW,EACX,aAAa,EACb,eAAe,EACf,aAAa,EACb,UAAU,EACV,UAAU,EACV,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,cAAc,EACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACH,WAAW,EACX,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAS,EACT,WAAW,EACX,eAAe,EAClB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACH,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,EACxB,8BAA8B,EAC9B,+BAA+B,EAC/B,eAAe,EACf,uBAAuB,EACvB,wBAAwB,EACxB,oBAAoB,EACvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACH,oBAAoB,EACpB,mBAAmB,EACtB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACH,kBAAkB,GACrB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACH,UAAU,EACV,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,6BAA6B,GAChC,MAAM,WAAW,CAAC;AAEnB,YAAY,EACR,kBAAkB,EAClB,UAAU,EACV,sBAAsB,EACtB,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,wBAAwB,EACxB,yBAAyB,EACzB,qBAAqB,EACrB,gCAAgC,EAChC,8BAA8B,EAC9B,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EACxB,aAAa,EACb,cAAc,EACd,aAAa,GAChB,MAAM,WAAW,CAAC"}
|
package/lib/dist/index.js
CHANGED
|
@@ -15,9 +15,9 @@ export const DSP = {
|
|
|
15
15
|
breakOnError: true
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
|
-
export { Chorus, Analyser, Distortion, Equalizer, Limiter, Saturation, StereoPanner, Compressor, MultibandCompressor, AdvancedDelay, MonoDelay, PingPongDelay, StereoDelay, ChamberReverb, ConvolverReverb, GenericReverb, HallReverb, RoomReverb, SoftClip, LowPassFilter, HardClip } from "./effects/exports";
|
|
18
|
+
export { Chorus, Analyser, Distortion, Equalizer, Limiter, Saturation, StereoPanner, Compressor, MultibandCompressor, AdvancedDelay, MonoDelay, PingPongDelay, StereoDelay, ChamberReverb, ConvolverReverb, GenericReverb, HallReverb, RoomReverb, SoftClip, LowPassFilter, HardClip, HighPassFilter } from "./effects/exports";
|
|
19
19
|
export { AudioDevice, Channel, Effector, Master, AudioClip, DspPipeline, AudioClipPlayer } from "./core/exports";
|
|
20
20
|
export { InitializeDspPipeline, ResolveAudioOutputDevices, ResolveAudioInputDevices, ResolveDefaultAudioInputDevice, ResolveDefaultAudioOutputDevice, LoadAudioSource, LoadAudioSourceFromBlob, LoadWorkletOnAudioDevice, SendMessageToWorklet } from "./utilities/helpers";
|
|
21
|
-
export { SUPPORTED_FILE_TYPES } from "./utilities/constants";
|
|
21
|
+
export { SUPPORTED_FILE_TYPES, DEFAULT_SAMPLE_RATE } from "./utilities/constants";
|
|
22
22
|
export { hasInitializedWasm, } from "./utilities/web-assembly";
|
|
23
23
|
export { StrictMode, ProcessorIdentificationCodes, HardClipMessageCommandId, SoftClipMessageCommandId, AudioWorkletProcessorNames, ChorusMessageCommandId, LowPassFilterMessageCommandId, } from "./typings";
|
package/lib/dist/typings.d.ts
CHANGED
|
@@ -14,6 +14,16 @@ export declare enum LowPassFilterMessageCommandId {
|
|
|
14
14
|
SetMinFrequency = 1,
|
|
15
15
|
SetQ = 2
|
|
16
16
|
}
|
|
17
|
+
export declare enum HighPassFilterMessageCommandId {
|
|
18
|
+
SetCutoff = 0,
|
|
19
|
+
SetMaxFrequency = 1,
|
|
20
|
+
SetQ = 2
|
|
21
|
+
}
|
|
22
|
+
export declare enum NotchFilterMessageCommandId {
|
|
23
|
+
SetCutoff = 0,
|
|
24
|
+
SetMinFrequency = 1,
|
|
25
|
+
SetQ = 2
|
|
26
|
+
}
|
|
17
27
|
export declare enum ChorusMessageCommandId {
|
|
18
28
|
SetBaseDelayMs = 0,
|
|
19
29
|
SetDepthMs = 1,
|
|
@@ -117,6 +127,18 @@ export interface LowPassFilterOptions {
|
|
|
117
127
|
q: number;
|
|
118
128
|
strictMode: StrictMode;
|
|
119
129
|
}
|
|
130
|
+
export interface HighPassFilterOptions {
|
|
131
|
+
cutoff: number;
|
|
132
|
+
q: number;
|
|
133
|
+
maxFrequency: number;
|
|
134
|
+
strictMode: StrictMode;
|
|
135
|
+
}
|
|
136
|
+
export interface NotchFilterOptions {
|
|
137
|
+
cutoff: number;
|
|
138
|
+
q: number;
|
|
139
|
+
minFrequency: number;
|
|
140
|
+
strictMode: StrictMode;
|
|
141
|
+
}
|
|
120
142
|
export interface SoftClipOptions {
|
|
121
143
|
drive: number;
|
|
122
144
|
gain: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typings.d.ts","sourceRoot":"","sources":["../src/typings.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;AACnE,MAAM,MAAM,qBAAqB,GAAG,KAAK,GAAG,MAAM,CAAC;AACnD,MAAM,MAAM,yBAAyB,GAAG,SAAS,GAAG,aAAa,GAAG,aAAa,GAAG,uBAAuB,CAAC;AAC5G,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,mBAAmB,CAAC;AACxF,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"typings.d.ts","sourceRoot":"","sources":["../src/typings.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;AACnE,MAAM,MAAM,qBAAqB,GAAG,KAAK,GAAG,MAAM,CAAC;AACnD,MAAM,MAAM,yBAAyB,GAAG,SAAS,GAAG,aAAa,GAAG,aAAa,GAAG,uBAAuB,CAAC;AAC5G,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,mBAAmB,CAAC;AACxF,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAE9F,MAAM,MAAM,eAAe,GAAG;KACzB,CAAC,IAAI,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,CAAC,CAAC,EAAE;CACzD,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;KACxB,CAAC,IAAI,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAC,EAAE;CACvD,CAAA;AAED,oBAAY,6BAA6B;IACrC,SAAS,IAAA;IACT,eAAe,IAAA;IACf,IAAI,IAAA;CACP;AAED,oBAAY,8BAA8B;IACtC,SAAS,IAAA;IACT,eAAe,IAAA;IACf,IAAI,IAAA;CACP;AAED,oBAAY,2BAA2B;IACnC,SAAS,IAAA;IACT,eAAe,IAAA;IACf,IAAI,IAAA;CACP;AAED,oBAAY,sBAAsB;IAC9B,cAAc,IAAA;IACd,UAAU,IAAA;IACV,SAAS,IAAA;IACT,MAAM,IAAA;IACN,WAAW,IAAA;CACd;AAED,oBAAY,wBAAwB;IAChC,QAAQ,IAAA;IACR,OAAO,IAAA;CACV;AAED,oBAAY,wBAAwB;IAChC,QAAQ,IAAA;IACR,OAAO,IAAA;CACV;AAED,oBAAY,0BAA0B;IAClC,UAAU,wBAAwB;IAClC,mBAAmB,iCAAiC;IACpD,aAAa,2BAA2B;IACxC,SAAS,uBAAuB;IAChC,aAAa,2BAA2B;IACxC,WAAW,yBAAyB;IACpC,aAAa,2BAA2B;IACxC,cAAc,4BAA4B;IAC1C,cAAc,4BAA4B;IAC1C,WAAW,yBAAyB;IACpC,MAAM,oBAAoB;IAC1B,OAAO,qBAAqB;IAC5B,MAAM,oBAAoB;IAC1B,MAAM,oBAAoB;IAC1B,QAAQ,sBAAsB;IAC9B,QAAQ,sBAAsB;CACjC;AAED,oBAAY,4BAA4B;IACpC,kBAAkB,yBAAyB;IAC3C,oBAAoB,2BAA2B;IAC/C,4BAA4B,oCAAoC;CACnE;AAED,oBAAY,UAAU;IAClB,QAAQ,IAAO;IACf,OAAO,IAAO;CACjB;AAED,MAAM,WAAW,kBAAkB;IAC/B,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,qBAAqB,CAAC;IACtC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,2BAA2B,EAAE,OAAO,CAAC;CACxC;AAED,MAAM,WAAW,sBAAsB;IACnC,qBAAqB,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC5B,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAC9B,UAAU,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAC;CACzD;AAED,MAAM,WAAW,gCAAgC;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,8BAA8B;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,qBAAqB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,EAAE,MAAM,CAAC;IACV,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,EAAE,MAAM,CAAC;IACV,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC7B,4BAA4B,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC1E,4BAA4B,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC1E,0BAA0B,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACxE,mCAAmC,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACjF,6BAA6B,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;CAC9E;AAED,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,GAAG,4BAA4B,CAAC,kBAAkB,CAAC;IAC7D,IAAI,EAAE,MAAM,GAAG,4BAA4B,CAAC,oBAAoB,CAAC;IACjE,SAAS,EAAE,MAAM,GAAG,4BAA4B,CAAC,4BAA4B,CAAC;CACjF;AAED,MAAM,WAAW,wBAAwB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,mBAAmB,CAAC;IAC1B,SAAS,EAAE,aAAa,CAAC;IACzB,cAAc,CAAC,EAAE,GAAG,CAAC;CACxB"}
|
package/lib/dist/typings.js
CHANGED
|
@@ -4,6 +4,18 @@ export var LowPassFilterMessageCommandId;
|
|
|
4
4
|
LowPassFilterMessageCommandId[LowPassFilterMessageCommandId["SetMinFrequency"] = 1] = "SetMinFrequency";
|
|
5
5
|
LowPassFilterMessageCommandId[LowPassFilterMessageCommandId["SetQ"] = 2] = "SetQ";
|
|
6
6
|
})(LowPassFilterMessageCommandId || (LowPassFilterMessageCommandId = {}));
|
|
7
|
+
export var HighPassFilterMessageCommandId;
|
|
8
|
+
(function (HighPassFilterMessageCommandId) {
|
|
9
|
+
HighPassFilterMessageCommandId[HighPassFilterMessageCommandId["SetCutoff"] = 0] = "SetCutoff";
|
|
10
|
+
HighPassFilterMessageCommandId[HighPassFilterMessageCommandId["SetMaxFrequency"] = 1] = "SetMaxFrequency";
|
|
11
|
+
HighPassFilterMessageCommandId[HighPassFilterMessageCommandId["SetQ"] = 2] = "SetQ";
|
|
12
|
+
})(HighPassFilterMessageCommandId || (HighPassFilterMessageCommandId = {}));
|
|
13
|
+
export var NotchFilterMessageCommandId;
|
|
14
|
+
(function (NotchFilterMessageCommandId) {
|
|
15
|
+
NotchFilterMessageCommandId[NotchFilterMessageCommandId["SetCutoff"] = 0] = "SetCutoff";
|
|
16
|
+
NotchFilterMessageCommandId[NotchFilterMessageCommandId["SetMinFrequency"] = 1] = "SetMinFrequency";
|
|
17
|
+
NotchFilterMessageCommandId[NotchFilterMessageCommandId["SetQ"] = 2] = "SetQ";
|
|
18
|
+
})(NotchFilterMessageCommandId || (NotchFilterMessageCommandId = {}));
|
|
7
19
|
export var ChorusMessageCommandId;
|
|
8
20
|
(function (ChorusMessageCommandId) {
|
|
9
21
|
ChorusMessageCommandId[ChorusMessageCommandId["SetBaseDelayMs"] = 0] = "SetBaseDelayMs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utilities/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,EAAE,MAAM,EAQxC,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utilities/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,EAAE,MAAM,EAQxC,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,MAAc,CAAC"}
|
|
@@ -20,6 +20,7 @@ export class AudioClip {
|
|
|
20
20
|
public isPlaying: boolean = false;
|
|
21
21
|
public startTime: number = 0;
|
|
22
22
|
public offsetAtStart: number = 0;
|
|
23
|
+
public playbackRate: number = 1;
|
|
23
24
|
|
|
24
25
|
public progressUpdateSpeed: number = 20;
|
|
25
26
|
|
|
@@ -49,6 +50,7 @@ export class AudioClip {
|
|
|
49
50
|
const bufferSource = context.createBufferSource();
|
|
50
51
|
bufferSource.buffer = this.data.audioBuffer;
|
|
51
52
|
bufferSource.loop = this.loop;
|
|
53
|
+
bufferSource.playbackRate.setValueAtTime(this.playbackRate, this.context.currentTime);
|
|
52
54
|
|
|
53
55
|
return bufferSource;
|
|
54
56
|
}
|
|
@@ -121,9 +123,9 @@ export class AudioClip {
|
|
|
121
123
|
this.offsetAtStart = actualOffset;
|
|
122
124
|
this.isPlaying = true;
|
|
123
125
|
|
|
124
|
-
if (this.progressInterval) clearInterval(this.progressInterval);
|
|
126
|
+
if (this.progressInterval) window.clearInterval(this.progressInterval);
|
|
125
127
|
|
|
126
|
-
if (this.isPlaying) this.progressInterval = setInterval(function () {
|
|
128
|
+
if (this.isPlaying) this.progressInterval = window.setInterval(function () {
|
|
127
129
|
|
|
128
130
|
if (!self.isPlaying) return;
|
|
129
131
|
|
|
@@ -336,6 +338,21 @@ export class AudioClip {
|
|
|
336
338
|
channel.audioClipPlayer.DetachAudioClip(this);
|
|
337
339
|
}
|
|
338
340
|
|
|
341
|
+
public SetPlaybackRateInSemitones(semitones: number): AudioClip {
|
|
342
|
+
|
|
343
|
+
if(!this.context)
|
|
344
|
+
throw new Error("Could not set playback rate because the AudioContext is not defined.");
|
|
345
|
+
|
|
346
|
+
const calculatedPlaybackRate: number = Math.pow(2, semitones / 12);
|
|
347
|
+
|
|
348
|
+
for(const buffer of this.audioBufferSourceNodes) {
|
|
349
|
+
buffer.playbackRate.setValueAtTime(calculatedPlaybackRate, this.context?.currentTime);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
this.playbackRate = calculatedPlaybackRate;
|
|
353
|
+
return this;
|
|
354
|
+
}
|
|
355
|
+
|
|
339
356
|
public get currentPlaybackTime(): number {
|
|
340
357
|
return (!this.isPlaying || !this.context)
|
|
341
358
|
? 0
|
|
@@ -9,8 +9,10 @@ export class Analyser extends Effector {
|
|
|
9
9
|
|
|
10
10
|
public analyserNode: AnalyserNode | null = null;
|
|
11
11
|
|
|
12
|
-
public
|
|
13
|
-
public
|
|
12
|
+
public waveformFloat32ArrayBuffer = new Float32Array();
|
|
13
|
+
public waveformUint8ArrayBuffer = new Uint8Array();
|
|
14
|
+
public frequencyFloat32ArrayBuffer = new Float32Array();
|
|
15
|
+
public frequencyUint8ArrayBuffer = new Uint8Array();
|
|
14
16
|
|
|
15
17
|
private options: AnalyserOptions = {
|
|
16
18
|
fftSize: 32,
|
|
@@ -62,23 +64,41 @@ export class Analyser extends Effector {
|
|
|
62
64
|
|
|
63
65
|
if (!this.analyserNode) return null;
|
|
64
66
|
|
|
65
|
-
this.analyserNode.getFloatTimeDomainData(this.
|
|
66
|
-
return this.
|
|
67
|
+
this.analyserNode.getFloatTimeDomainData(this.waveformFloat32ArrayBuffer);
|
|
68
|
+
return this.waveformFloat32ArrayBuffer;
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
public GetWaveformByteData(): Uint8Array | null {
|
|
70
72
|
|
|
71
73
|
if (!this.analyserNode) return null;
|
|
72
74
|
|
|
73
|
-
this.analyserNode.getByteTimeDomainData(this.
|
|
74
|
-
return this.
|
|
75
|
+
this.analyserNode.getByteTimeDomainData(this.waveformUint8ArrayBuffer);
|
|
76
|
+
return this.waveformUint8ArrayBuffer;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public GetFrequencyFloatData(): Float32Array | null {
|
|
80
|
+
|
|
81
|
+
if(!this.analyserNode) return null;
|
|
82
|
+
|
|
83
|
+
this.analyserNode.getFloatFrequencyData(this.frequencyFloat32ArrayBuffer);
|
|
84
|
+
return this.frequencyFloat32ArrayBuffer;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public GetFrequencyByteData(): Uint8Array | null {
|
|
88
|
+
|
|
89
|
+
if(!this.analyserNode) return null;
|
|
90
|
+
|
|
91
|
+
this.analyserNode.getByteFrequencyData(this.frequencyUint8ArrayBuffer);
|
|
92
|
+
return this.frequencyUint8ArrayBuffer;
|
|
75
93
|
}
|
|
76
94
|
|
|
77
95
|
private allocateBuffers(): void {
|
|
78
96
|
|
|
79
97
|
if (!this.analyserNode) return;
|
|
80
98
|
|
|
81
|
-
this.
|
|
82
|
-
this.
|
|
99
|
+
this.waveformFloat32ArrayBuffer = new Float32Array(this.analyserNode.fftSize);
|
|
100
|
+
this.waveformUint8ArrayBuffer = new Uint8Array(this.analyserNode.fftSize);
|
|
101
|
+
this.frequencyFloat32ArrayBuffer = new Float32Array(this.analyserNode.fftSize);
|
|
102
|
+
this.frequencyUint8ArrayBuffer = new Uint8Array(this.analyserNode.fftSize);
|
|
83
103
|
}
|
|
84
104
|
}
|
|
@@ -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
|
+
}
|
|
@@ -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
|
+
}
|
package/lib/src/index.ts
CHANGED
|
@@ -40,7 +40,8 @@ export {
|
|
|
40
40
|
RoomReverb,
|
|
41
41
|
SoftClip,
|
|
42
42
|
LowPassFilter,
|
|
43
|
-
HardClip
|
|
43
|
+
HardClip,
|
|
44
|
+
HighPassFilter
|
|
44
45
|
} from "./effects/exports";
|
|
45
46
|
|
|
46
47
|
export {
|
|
@@ -66,7 +67,8 @@ export {
|
|
|
66
67
|
} from "./utilities/helpers";
|
|
67
68
|
|
|
68
69
|
export {
|
|
69
|
-
SUPPORTED_FILE_TYPES
|
|
70
|
+
SUPPORTED_FILE_TYPES,
|
|
71
|
+
DEFAULT_SAMPLE_RATE
|
|
70
72
|
} from "./utilities/constants";
|
|
71
73
|
|
|
72
74
|
export {
|
|
@@ -106,5 +108,5 @@ export type {
|
|
|
106
108
|
IncomingProcessorMessage,
|
|
107
109
|
ProcessorData,
|
|
108
110
|
EffectorEvents,
|
|
109
|
-
ArrayPosition
|
|
111
|
+
ArrayPosition,
|
|
110
112
|
} 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,
|
|
@@ -139,6 +150,20 @@ export interface LowPassFilterOptions {
|
|
|
139
150
|
strictMode: StrictMode;
|
|
140
151
|
}
|
|
141
152
|
|
|
153
|
+
export interface HighPassFilterOptions {
|
|
154
|
+
cutoff: number;
|
|
155
|
+
q: number;
|
|
156
|
+
maxFrequency: number;
|
|
157
|
+
strictMode: StrictMode;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface NotchFilterOptions {
|
|
161
|
+
cutoff: number;
|
|
162
|
+
q: number;
|
|
163
|
+
minFrequency: number;
|
|
164
|
+
strictMode: StrictMode;
|
|
165
|
+
}
|
|
166
|
+
|
|
142
167
|
export interface SoftClipOptions {
|
|
143
168
|
drive: number;
|
|
144
169
|
gain: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluex/fluexgl-dsp",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.7",
|
|
4
4
|
"description": "An open-source, web-based DSP library developed alongside FluexGL, designed for creating and manipulating sounds in various contexts.",
|
|
5
5
|
"main": "lib/dist/index.js",
|
|
6
6
|
"types": "lib/dist/index.d.ts",
|