@fluex/fluexgl-dsp 0.4.0 → 0.4.2
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 +16 -38
- package/lib/dist/core/classes/AudioClip.d.ts +3 -1
- package/lib/dist/core/classes/AudioClip.d.ts.map +1 -1
- package/lib/dist/core/classes/AudioClip.js +18 -5
- package/lib/dist/core/classes/AudioClipPlayer.d.ts +8 -2
- package/lib/dist/core/classes/AudioClipPlayer.d.ts.map +1 -1
- package/lib/dist/core/classes/AudioClipPlayer.js +48 -1
- package/lib/dist/core/classes/AudioDevice.d.ts +2 -0
- package/lib/dist/core/classes/AudioDevice.d.ts.map +1 -1
- package/lib/dist/core/classes/AudioDevice.js +4 -0
- package/lib/dist/core/classes/Channel.d.ts +10 -2
- package/lib/dist/core/classes/Channel.d.ts.map +1 -1
- package/lib/dist/core/classes/Channel.js +67 -0
- package/lib/dist/core/classes/DpsPipeline.d.ts +1 -1
- package/lib/dist/core/classes/DpsPipeline.d.ts.map +1 -1
- package/lib/dist/core/classes/DpsPipeline.js +7 -3
- package/lib/dist/core/classes/Effector.d.ts +2 -2
- package/lib/dist/core/classes/Effector.d.ts.map +1 -1
- package/lib/dist/core/classes/Effector.js +1 -1
- package/lib/dist/core/classes/Master.d.ts +12 -0
- package/lib/dist/core/classes/Master.d.ts.map +1 -1
- package/lib/dist/core/classes/Master.js +77 -7
- package/lib/dist/effects/classes/Analyser.d.ts +16 -0
- package/lib/dist/effects/classes/Analyser.d.ts.map +1 -0
- package/lib/dist/effects/classes/Analyser.js +62 -0
- package/lib/dist/effects/classes/Chorus.d.ts +4 -3
- package/lib/dist/effects/classes/Chorus.d.ts.map +1 -1
- package/lib/dist/effects/classes/Chorus.js +21 -12
- package/lib/dist/effects/classes/clips/HardClip.d.ts +4 -3
- package/lib/dist/effects/classes/clips/HardClip.d.ts.map +1 -1
- package/lib/dist/effects/classes/clips/HardClip.js +15 -9
- package/lib/dist/effects/classes/clips/SoftClip.d.ts +4 -3
- package/lib/dist/effects/classes/clips/SoftClip.d.ts.map +1 -1
- package/lib/dist/effects/classes/clips/SoftClip.js +15 -9
- package/lib/dist/effects/classes/filters/LowPassFilter.d.ts +4 -3
- package/lib/dist/effects/classes/filters/LowPassFilter.d.ts.map +1 -1
- package/lib/dist/effects/classes/filters/LowPassFilter.js +23 -14
- 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 +5 -4
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +13 -18
- package/lib/dist/typings.d.ts +13 -11
- package/lib/dist/typings.d.ts.map +1 -1
- package/lib/dist/typings.js +5 -0
- package/lib/dist/utilities/debugger.js +6 -6
- package/lib/dist/utilities/helpers.d.ts +2 -0
- package/lib/dist/utilities/helpers.d.ts.map +1 -1
- package/lib/dist/utilities/helpers.js +35 -12
- package/lib/src/core/classes/AudioClip.ts +23 -7
- package/lib/src/core/classes/AudioClipPlayer.ts +67 -7
- package/lib/src/core/classes/AudioDevice.ts +5 -0
- package/lib/src/core/classes/Channel.ts +97 -4
- package/lib/src/core/classes/DpsPipeline.ts +7 -3
- package/lib/src/core/classes/Effector.ts +3 -2
- package/lib/src/core/classes/Master.ts +98 -11
- package/lib/src/effects/classes/Analyser.ts +84 -0
- package/lib/src/effects/classes/Chorus.ts +22 -13
- package/lib/src/effects/classes/clips/HardClip.ts +17 -10
- package/lib/src/effects/classes/clips/SoftClip.ts +17 -10
- package/lib/src/effects/classes/filters/LowPassFilter.ts +28 -15
- package/lib/src/effects/exports.ts +2 -1
- package/lib/src/index.ts +27 -29
- package/lib/src/typings.ts +14 -14
- package/lib/src/utilities/debugger.ts +6 -6
- package/lib/src/utilities/helpers.ts +38 -14
- package/package.json +1 -1
- package/lib/dist/effects/classes/Filter.d.ts +0 -3
- package/lib/dist/effects/classes/Filter.d.ts.map +0 -1
- package/lib/dist/effects/classes/Filter.js +0 -2
- package/lib/dist/effects/classes/SoftClip.d.ts +0 -10
- package/lib/dist/effects/classes/SoftClip.d.ts.map +0 -1
- package/lib/dist/effects/classes/SoftClip.js +0 -39
- package/lib/dist/test/linkable-channels.d.ts +0 -2
- package/lib/dist/test/linkable-channels.d.ts.map +0 -1
- package/lib/dist/test/linkable-channels.js +0 -16
- package/lib/src/core/functions/rebuild-effect-chain.ts +0 -5
package/README.md
CHANGED
|
@@ -21,57 +21,35 @@ $ npm i @fluex/fluexgl-dsp
|
|
|
21
21
|
## ⚡ Quick start
|
|
22
22
|
|
|
23
23
|
```ts
|
|
24
|
-
import {
|
|
25
|
-
AudioDevice,
|
|
26
|
-
InitializeDspPipeline,
|
|
27
|
-
LoadAudioSource,
|
|
28
|
-
ResolveDefaultAudioOutputDevice,
|
|
29
|
-
Channel,
|
|
30
|
-
AudioSourceData,
|
|
31
|
-
AudioClip
|
|
32
|
-
} from "@fluexgl/dsp";
|
|
24
|
+
import { DspPipeline, Channel, LoadAudioSource, AudioClip } from "@fluex/fluexgl-dsp";
|
|
33
25
|
|
|
34
26
|
(async function() {
|
|
35
27
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if(!hasInitialized) return null;
|
|
40
|
-
|
|
41
|
-
// Resolves the default audio output device.
|
|
42
|
-
const audioDevice: AudioDevice | null = await ResolveDefaultAudioOutputDevice({
|
|
43
|
-
pathToWasm: "/wasm/fluexgl-dsp-wasm_bg.wasm"
|
|
28
|
+
const pipeline = new DspPipeline({
|
|
29
|
+
pathToWasm: "/data/fluexgl-dsp-wasm_bg.wasm",
|
|
30
|
+
pathToWorklet: "/data/fluexgl-dsp-processor.worklet"
|
|
44
31
|
});
|
|
45
32
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// Get the master channel from the default audio output device.
|
|
49
|
-
const masterChannel = audioDevice.GetMasterChannel();
|
|
50
|
-
|
|
51
|
-
// Create a new empty channel.
|
|
52
|
-
const channel = new Channel();
|
|
33
|
+
await pipeline.InitializeDpsPipeline();
|
|
53
34
|
|
|
54
|
-
|
|
55
|
-
channel.SetLabel("BackgroundMusic");
|
|
35
|
+
const audioDevice = await pipeline.ResolveDefaultAudioOutputDevice();
|
|
56
36
|
|
|
57
|
-
|
|
58
|
-
masterChannel.AttachChannel(channel);
|
|
37
|
+
if(!audioDevice) return;
|
|
59
38
|
|
|
60
|
-
|
|
61
|
-
const
|
|
39
|
+
const master = audioDevice.GetMasterChannel();
|
|
40
|
+
const context = audioDevice.GetContext();
|
|
62
41
|
|
|
63
|
-
|
|
42
|
+
const audioSource = await LoadAudioSource("/music.mp3");
|
|
64
43
|
|
|
65
|
-
|
|
66
|
-
const audioClip = new AudioClip(audioSourceData);
|
|
44
|
+
if(!audioSource) return;
|
|
67
45
|
|
|
68
|
-
|
|
69
|
-
channel
|
|
46
|
+
const audioClip = new AudioClip(audioSource);
|
|
47
|
+
const channel = new Channel(context);
|
|
70
48
|
|
|
71
|
-
|
|
72
|
-
|
|
49
|
+
channel.Send(master);
|
|
50
|
+
audioClip.Send(channel);
|
|
73
51
|
|
|
74
|
-
|
|
52
|
+
button.addEventListener("click", function() {
|
|
75
53
|
audioClip.Play();
|
|
76
54
|
});
|
|
77
55
|
})();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AudioClipEventMap, AudioSourceData } from "../../typings";
|
|
2
2
|
import { Channel } from "./Channel";
|
|
3
3
|
import { AudioClipPlayer } from "./AudioClipPlayer";
|
|
4
|
+
import { Master } from "./Master";
|
|
4
5
|
export declare class AudioClip {
|
|
5
6
|
data: AudioSourceData;
|
|
6
7
|
id: string;
|
|
@@ -37,7 +38,8 @@ export declare class AudioClip {
|
|
|
37
38
|
RemoveEventListener<K extends keyof AudioClipEventMap>(event: K, cb: AudioClipEventMap[K]): AudioClip;
|
|
38
39
|
ClearEventListeners(event?: keyof AudioClipEventMap): AudioClip;
|
|
39
40
|
GetChannelData(channel?: number): Float32Array;
|
|
40
|
-
Send(channel: Channel): void;
|
|
41
|
+
Send(channel: Channel | Master): void;
|
|
42
|
+
Unsend(channel: Channel | Master): void;
|
|
41
43
|
get currentPlaybackTime(): number;
|
|
42
44
|
get duration(): number;
|
|
43
45
|
get volume(): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioClip.d.ts","sourceRoot":"","sources":["../../../src/core/classes/AudioClip.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
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;AAKlC,qBAAa,SAAS;IA2BC,IAAI,EAAE,eAAe;IAzBjC,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;IAE1B,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;IAa1B,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;IAcpC,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS;IAmBxC,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;IAWvC,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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { v4 } from "uuid";
|
|
2
2
|
import { format } from "date-fns";
|
|
3
3
|
import { Debug } from "../../utilities/debugger";
|
|
4
|
+
import { DSP } from "../../index";
|
|
4
5
|
export class AudioClip {
|
|
5
6
|
data;
|
|
6
7
|
id = v4();
|
|
@@ -181,9 +182,12 @@ export class AudioClip {
|
|
|
181
182
|
return this;
|
|
182
183
|
}
|
|
183
184
|
SetMaxAudioBufferSourceNodes(value) {
|
|
184
|
-
|
|
185
|
-
"
|
|
186
|
-
|
|
185
|
+
if (!DSP.overrideMaxAudioBufferNodes) {
|
|
186
|
+
Debug.Warn("Cannot set maxAudioBufferSourceNodes because the option to override the current maximum value is disabled.", [
|
|
187
|
+
"Set overrideMaxAudioBufferNodes on DSP to true, in order to override the maximum audio buffer source nodes."
|
|
188
|
+
]);
|
|
189
|
+
return this;
|
|
190
|
+
}
|
|
187
191
|
this.maxAudioBufferSourceNodes = value;
|
|
188
192
|
return this;
|
|
189
193
|
}
|
|
@@ -232,13 +236,22 @@ export class AudioClip {
|
|
|
232
236
|
return this.data.audioBuffer.getChannelData(channel);
|
|
233
237
|
}
|
|
234
238
|
Send(channel) {
|
|
235
|
-
if (!channel.
|
|
239
|
+
if (!channel.audioClipPlayer)
|
|
236
240
|
return Debug.Error("Could not send AudioClip signal to channel, because the channel's AudioClipPlayer is undefined.", [
|
|
237
241
|
"Make sure to initialize the Channel.",
|
|
238
242
|
`Channel id: ${channel.id}.`,
|
|
239
243
|
`AudioClip id: ${this.id}.`
|
|
240
244
|
]);
|
|
241
|
-
channel.AttachAudioClip(this);
|
|
245
|
+
channel.audioClipPlayer.AttachAudioClip(this);
|
|
246
|
+
}
|
|
247
|
+
Unsend(channel) {
|
|
248
|
+
if (!channel.audioClipPlayer)
|
|
249
|
+
return Debug.Error("Could not unsend AudioClip signal to channel, because the channel's AudioClipPlayer is undefined.", [
|
|
250
|
+
"Make sure to initialize the Channel.",
|
|
251
|
+
`Channel id: ${channel.id}.`,
|
|
252
|
+
`AudioClip id: ${this.id}.`
|
|
253
|
+
]);
|
|
254
|
+
channel.audioClipPlayer.DetachAudioClip(this);
|
|
242
255
|
}
|
|
243
256
|
get currentPlaybackTime() {
|
|
244
257
|
return (!this.isPlaying || !this.context)
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { AudioClip } from "./AudioClip";
|
|
2
2
|
import { Channel } from "./Channel";
|
|
3
|
+
import { Master } from "./Master";
|
|
3
4
|
export declare class AudioClipPlayer {
|
|
4
5
|
label: string;
|
|
5
6
|
id: string;
|
|
6
7
|
audioClips: AudioClip[];
|
|
7
8
|
outputGainNode: GainNode | null;
|
|
8
9
|
context: AudioContext | null;
|
|
9
|
-
channel: Channel | null;
|
|
10
|
+
channel: Channel | Master | null;
|
|
10
11
|
constructor(context: AudioContext);
|
|
11
12
|
AttachAudioClip(audioClip: AudioClip): void;
|
|
12
|
-
|
|
13
|
+
DetachAudioClip(clip: AudioClip): void;
|
|
14
|
+
Send(channel: Channel | Master): void;
|
|
15
|
+
Unsend(): void;
|
|
16
|
+
SetVolume(value: number): void;
|
|
17
|
+
StopAll(): void;
|
|
18
|
+
Dispose(): void;
|
|
13
19
|
SetLabel(label: string): void;
|
|
14
20
|
}
|
|
15
21
|
//# sourceMappingURL=AudioClipPlayer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioClipPlayer.d.ts","sourceRoot":"","sources":["../../../src/core/classes/AudioClipPlayer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"AudioClipPlayer.d.ts","sourceRoot":"","sources":["../../../src/core/classes/AudioClipPlayer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,qBAAa,eAAe;IAEjB,KAAK,EAAE,MAAM,CAAqB;IAClC,EAAE,EAAE,MAAM,CAAQ;IAElB,UAAU,EAAE,SAAS,EAAE,CAAM;IAC7B,cAAc,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAEvC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAQ;IACpC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAQ;gBAEnC,OAAO,EAAE,YAAY;IAK1B,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAU3C,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAgBtC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI;IAUrC,MAAM,IAAI,IAAI;IAad,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAU9B,OAAO,IAAI,IAAI;IAOf,OAAO,IAAI,IAAI;IAYf,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAGvC"}
|
|
@@ -19,12 +19,59 @@ export class AudioClipPlayer {
|
|
|
19
19
|
audioClip.Initialize(this);
|
|
20
20
|
this.audioClips.push(audioClip);
|
|
21
21
|
}
|
|
22
|
+
DetachAudioClip(clip) {
|
|
23
|
+
if (!this.audioClips.includes(clip))
|
|
24
|
+
return Debug.Error("Could not detach audio clip because it is not part of this channel", [
|
|
25
|
+
"Call .AttachAudioClip([clip AudioClip]) before detaching audio clip."
|
|
26
|
+
]);
|
|
27
|
+
clip.Stop();
|
|
28
|
+
const self = this;
|
|
29
|
+
this.audioClips.forEach(function (_clip, index) {
|
|
30
|
+
if (clip.id === _clip.id)
|
|
31
|
+
return self.audioClips.splice(index, 1);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
22
34
|
Send(channel) {
|
|
23
35
|
if (!this.outputGainNode || !channel.input)
|
|
24
|
-
return Debug.Error("Could not send AudioClipPlayer signal to a channel.");
|
|
36
|
+
return Debug.Error("Could not send AudioClipPlayer signal to a channel/master.");
|
|
37
|
+
this.Unsend();
|
|
25
38
|
this.channel = channel;
|
|
26
39
|
this.outputGainNode.connect(channel.input);
|
|
27
40
|
}
|
|
41
|
+
Unsend() {
|
|
42
|
+
if (!this.outputGainNode)
|
|
43
|
+
return;
|
|
44
|
+
if (this.channel && this.channel.input) {
|
|
45
|
+
this.outputGainNode.disconnect(this.channel.input);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
this.outputGainNode.disconnect();
|
|
49
|
+
}
|
|
50
|
+
this.channel = null;
|
|
51
|
+
}
|
|
52
|
+
SetVolume(value) {
|
|
53
|
+
if (!this.outputGainNode)
|
|
54
|
+
return;
|
|
55
|
+
if (value < 0)
|
|
56
|
+
value = 0;
|
|
57
|
+
if (value > 1)
|
|
58
|
+
value = 1;
|
|
59
|
+
this.outputGainNode.gain.value = value;
|
|
60
|
+
}
|
|
61
|
+
StopAll() {
|
|
62
|
+
this.audioClips.forEach(function (clip) {
|
|
63
|
+
clip.Stop();
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
Dispose() {
|
|
67
|
+
this.StopAll();
|
|
68
|
+
this.Unsend();
|
|
69
|
+
this.outputGainNode?.disconnect();
|
|
70
|
+
this.audioClips = [];
|
|
71
|
+
this.outputGainNode = null;
|
|
72
|
+
this.channel = null;
|
|
73
|
+
this.context = null;
|
|
74
|
+
}
|
|
28
75
|
SetLabel(label) {
|
|
29
76
|
this.label = label;
|
|
30
77
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Master } from "./Master";
|
|
2
|
+
import { Channel } from "./Channel";
|
|
2
3
|
export declare class AudioDevice {
|
|
3
4
|
deviceInfo: MediaDeviceInfo;
|
|
4
5
|
id: string;
|
|
@@ -11,5 +12,6 @@ export declare class AudioDevice {
|
|
|
11
12
|
SetMasterChannel(channel: Master): void;
|
|
12
13
|
CreateMasterChannel(): Master;
|
|
13
14
|
GetContext(): AudioContext;
|
|
15
|
+
CreateChannel(): Channel;
|
|
14
16
|
}
|
|
15
17
|
//# sourceMappingURL=AudioDevice.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioDevice.d.ts","sourceRoot":"","sources":["../../../src/core/classes/AudioDevice.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"AudioDevice.d.ts","sourceRoot":"","sources":["../../../src/core/classes/AudioDevice.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,qBAAa,WAAW;IAUD,UAAU,EAAE,eAAe;IARvC,EAAE,EAAE,MAAM,CAAQ;IAClB,SAAS,EAAE,MAAM,CAAc;IAE/B,OAAO,EAAE,YAAY,CAAsB;IAE3C,aAAa,EAAE,MAAM,CAA4B;IACjD,cAAc,EAAE,MAAM,EAAE,CAAM;gBAElB,UAAU,EAAE,eAAe;IAEvC,gBAAgB,IAAI,MAAM;IAI1B,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAUvC,mBAAmB,IAAI,MAAM;IAQ7B,UAAU,IAAI,YAAY;IAI1B,aAAa,IAAI,OAAO;CAGlC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { v4 } from "uuid";
|
|
2
2
|
import { Master } from "./Master";
|
|
3
|
+
import { Channel } from "./Channel";
|
|
3
4
|
import { ErrorCodes } from "../../console-codes";
|
|
4
5
|
import { Debug } from "../../utilities/debugger";
|
|
5
6
|
export class AudioDevice {
|
|
@@ -31,4 +32,7 @@ export class AudioDevice {
|
|
|
31
32
|
GetContext() {
|
|
32
33
|
return this.context;
|
|
33
34
|
}
|
|
35
|
+
CreateChannel() {
|
|
36
|
+
return new Channel(this.context);
|
|
37
|
+
}
|
|
34
38
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { AudioClipPlayer } from "./AudioClipPlayer";
|
|
1
2
|
import { AudioClip } from "./AudioClip";
|
|
2
3
|
import { Master } from "./Master";
|
|
4
|
+
import { Effector } from "./Effector";
|
|
3
5
|
export declare class Channel {
|
|
4
6
|
id: string;
|
|
5
7
|
label: string;
|
|
@@ -8,10 +10,16 @@ export declare class Channel {
|
|
|
8
10
|
analyserNode: AnalyserNode | null;
|
|
9
11
|
gainNode: GainNode | null;
|
|
10
12
|
output: AudioNode | null;
|
|
13
|
+
effects: Effector[];
|
|
11
14
|
context: AudioContext | null;
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
sends: Channel[];
|
|
16
|
+
audioClipPlayer: AudioClipPlayer | null;
|
|
14
17
|
constructor(context: AudioContext);
|
|
18
|
+
private rebuildEffectChain;
|
|
19
|
+
AddEffect(effect: Effector): void;
|
|
20
|
+
AttachEffect(effect: Effector): void;
|
|
21
|
+
RemoveEffect(effect: Effector): void;
|
|
22
|
+
DetachEffect(effect: Effector): void;
|
|
15
23
|
private disconnectAudioNodes;
|
|
16
24
|
private isInitialized;
|
|
17
25
|
private isReachable;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Channel.d.ts","sourceRoot":"","sources":["../../../src/core/classes/Channel.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Channel.d.ts","sourceRoot":"","sources":["../../../src/core/classes/Channel.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,qBAAa,OAAO;IAET,EAAE,EAAE,MAAM,CAAQ;IAClB,KAAK,EAAE,MAAM,CAAa;IAE1B,KAAK,EAAE,SAAS,GAAG,IAAI,CAAQ;IAC/B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IACjD,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IACzC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IACjC,MAAM,EAAE,SAAS,GAAG,IAAI,CAAQ;IAEhC,OAAO,EAAE,QAAQ,EAAE,CAAM;IACzB,OAAO,EAAE,YAAY,GAAG,IAAI,CAAQ;IAEpC,KAAK,EAAE,OAAO,EAAE,CAAM;IACtB,eAAe,EAAE,eAAe,GAAG,IAAI,CAAQ;gBAE1C,OAAO,EAAE,YAAY;IAqBjC,OAAO,CAAC,kBAAkB;IAsCnB,SAAS,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAmBjC,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAIpC,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAqBpC,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAI3C,OAAO,CAAC,oBAAoB;IAqB5B,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,WAAW;IAwBZ,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAkC9B,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAehC,kBAAkB,IAAI,OAAO;IAI7B,mBAAmB;IASnB,eAAe,CAAC,SAAS,EAAE,SAAS;CAM9C"}
|
|
@@ -10,6 +10,7 @@ export class Channel {
|
|
|
10
10
|
analyserNode = null;
|
|
11
11
|
gainNode = null;
|
|
12
12
|
output = null;
|
|
13
|
+
effects = [];
|
|
13
14
|
context = null;
|
|
14
15
|
sends = [];
|
|
15
16
|
audioClipPlayer = null;
|
|
@@ -28,12 +29,78 @@ export class Channel {
|
|
|
28
29
|
this.gainNode.connect(this.output);
|
|
29
30
|
this.audioClipPlayer.Send(this);
|
|
30
31
|
}
|
|
32
|
+
rebuildEffectChain() {
|
|
33
|
+
if (!this.input || !this.stereoPannerNode) {
|
|
34
|
+
Debug.Error("Could not rebuild effect chain because one or more required audio nodes are undefined.", [
|
|
35
|
+
`Channel id: ${this.id}.`,
|
|
36
|
+
`Input defined: ${!!this.input}.`,
|
|
37
|
+
`StereoPannerNode defined: ${!!this.stereoPannerNode}.`
|
|
38
|
+
]);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
this.input.disconnect();
|
|
42
|
+
for (const effect of this.effects)
|
|
43
|
+
effect.audioWorkletNode?.disconnect();
|
|
44
|
+
const activeEffects = this.effects.filter(function (e) {
|
|
45
|
+
return !!e.audioWorkletNode;
|
|
46
|
+
});
|
|
47
|
+
if (activeEffects.length === 0) {
|
|
48
|
+
this.input.connect(this.stereoPannerNode);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
this.input.connect(activeEffects[0].audioWorkletNode);
|
|
52
|
+
for (let i = 0; i < activeEffects.length - 1; i++) {
|
|
53
|
+
const current = activeEffects[i].audioWorkletNode;
|
|
54
|
+
const next = activeEffects[i + 1].audioWorkletNode;
|
|
55
|
+
current.connect(next);
|
|
56
|
+
}
|
|
57
|
+
activeEffects[activeEffects.length - 1].audioWorkletNode.connect(this.stereoPannerNode);
|
|
58
|
+
}
|
|
59
|
+
AddEffect(effect) {
|
|
60
|
+
if (!this.context) {
|
|
61
|
+
Debug.Error("Could not add effect because this channel has no AudioContext.");
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (this.effects.includes(effect)) {
|
|
65
|
+
Debug.Error("Could not add effect because it is already part of this channel", [
|
|
66
|
+
"Call .RemoveEffect([effect Effector]) before adding effect."
|
|
67
|
+
]);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
this.effects.push(effect);
|
|
71
|
+
effect.InitializeOnAttachment(this.context);
|
|
72
|
+
this.rebuildEffectChain();
|
|
73
|
+
}
|
|
74
|
+
AttachEffect(effect) {
|
|
75
|
+
return this.AddEffect(effect);
|
|
76
|
+
}
|
|
77
|
+
RemoveEffect(effect) {
|
|
78
|
+
if (!this.effects.includes(effect)) {
|
|
79
|
+
Debug.Error("Could not remove effect, because it is not part of this channel.", [
|
|
80
|
+
"Call .AddEffect([effect Effector]) before removing effect."
|
|
81
|
+
]);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const self = this;
|
|
85
|
+
this.effects.forEach(function (_effect, index) {
|
|
86
|
+
if (effect.id === _effect.id)
|
|
87
|
+
self.effects.splice(index, 1);
|
|
88
|
+
});
|
|
89
|
+
effect.audioWorkletNode?.disconnect();
|
|
90
|
+
this.rebuildEffectChain();
|
|
91
|
+
}
|
|
92
|
+
DetachEffect(effect) {
|
|
93
|
+
return this.RemoveEffect(effect);
|
|
94
|
+
}
|
|
31
95
|
disconnectAudioNodes(gc) {
|
|
32
96
|
this.input?.disconnect();
|
|
33
97
|
this.stereoPannerNode?.disconnect();
|
|
34
98
|
this.analyserNode?.disconnect();
|
|
35
99
|
this.gainNode?.disconnect();
|
|
36
100
|
this.output?.disconnect();
|
|
101
|
+
for (const effect of this.effects) {
|
|
102
|
+
effect.audioWorkletNode?.disconnect();
|
|
103
|
+
}
|
|
37
104
|
if (gc) {
|
|
38
105
|
this.input = null;
|
|
39
106
|
this.stereoPannerNode = null;
|
|
@@ -31,7 +31,7 @@ export declare class DspPipeline {
|
|
|
31
31
|
* @param options - Initialization options for the DSP pipeline.
|
|
32
32
|
* Must include valid paths to the WebAssembly and AudioWorklet files.
|
|
33
33
|
*/
|
|
34
|
-
constructor(options: DspPipelineInitializationOptions);
|
|
34
|
+
constructor({ pathToWasm, pathToWorklet, options }: DspPipelineInitializationOptions);
|
|
35
35
|
/**
|
|
36
36
|
* Initializes the DSP pipeline.
|
|
37
37
|
* This is a convenience wrapper around {@link InitializeDpsPipeline}.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DpsPipeline.d.ts","sourceRoot":"","sources":["../../../src/core/classes/DpsPipeline.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAM5C,OAAO,EAAE,gCAAgC,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"DpsPipeline.d.ts","sourceRoot":"","sources":["../../../src/core/classes/DpsPipeline.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAM5C,OAAO,EAAE,gCAAgC,EAAE,MAAM,eAAe,CAAC;AAGjE;;;GAGG;AACH,qBAAa,WAAW;IAEpB;;OAEG;IACI,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAExC;;OAEG;IACI,aAAa,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE3C;;OAEG;IACI,EAAE,EAAE,MAAM,CAAQ;IAEzB;;OAEG;IACI,cAAc,EAAE,OAAO,CAAS;IAEvC;;OAEG;IACH,OAAO,CAAC,OAAO,CAAuB;IAEtC;;;;;OAKG;gBACS,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE,gCAAgC;IAQpF;;;;;OAKG;IACU,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;;;;;OAMG;IACU,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC;IA0CtD;;;;;;OAMG;IACU,+BAA+B;IA+BrC,6CAA6C;CAGvD"}
|
|
@@ -4,6 +4,7 @@ import { Debug } from "../../utilities/debugger";
|
|
|
4
4
|
import { LoadWebAssemblyModule } from "../../utilities/web-assembly";
|
|
5
5
|
import { ConstructProcessorWorklet, LoadWorkletOnAudioDevice } from "../../utilities/helpers";
|
|
6
6
|
import { ErrorCodes, WarningCodes } from "../../console-codes";
|
|
7
|
+
import { DSP } from "../../index";
|
|
7
8
|
/**
|
|
8
9
|
* Represents the digital signal processing (DSP) pipeline responsible for initializing
|
|
9
10
|
* WebAssembly modules, AudioWorklet processors, and resolving audio output devices.
|
|
@@ -35,9 +36,12 @@ export class DspPipeline {
|
|
|
35
36
|
* @param options - Initialization options for the DSP pipeline.
|
|
36
37
|
* Must include valid paths to the WebAssembly and AudioWorklet files.
|
|
37
38
|
*/
|
|
38
|
-
constructor(options) {
|
|
39
|
-
this.pathToWasm =
|
|
40
|
-
this.pathToWorklet =
|
|
39
|
+
constructor({ pathToWasm, pathToWorklet, options }) {
|
|
40
|
+
this.pathToWasm = pathToWasm;
|
|
41
|
+
this.pathToWorklet = pathToWorklet;
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
for (const key in options)
|
|
44
|
+
DSP[key] = options[key];
|
|
41
45
|
}
|
|
42
46
|
/**
|
|
43
47
|
* Initializes the DSP pipeline.
|
|
@@ -4,7 +4,7 @@ export declare abstract class Effector {
|
|
|
4
4
|
label: string | null;
|
|
5
5
|
name: string;
|
|
6
6
|
audioWorkletNode: AudioWorkletNode | null;
|
|
7
|
-
|
|
7
|
+
context: AudioContext | null;
|
|
8
8
|
private hasRegisteredMessageEventListener;
|
|
9
9
|
private events;
|
|
10
10
|
private handleIncomingMessages;
|
|
@@ -13,6 +13,6 @@ export declare abstract class Effector {
|
|
|
13
13
|
Once<K extends keyof EffectorEventMap>(event: K, cb: EffectorEventMap[K]): () => void;
|
|
14
14
|
RemoveEventListener<K extends keyof EffectorEventMap>(event: K, cb: EffectorEventMap[K]): Effector;
|
|
15
15
|
ClearEventListeners(event?: keyof EffectorEventMap): Effector;
|
|
16
|
-
abstract InitializeOnAttachment(
|
|
16
|
+
abstract InitializeOnAttachment(context: AudioContext): Promise<void>;
|
|
17
17
|
}
|
|
18
18
|
//# sourceMappingURL=Effector.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Effector.d.ts","sourceRoot":"","sources":["../../../src/core/classes/Effector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGhH,8BAAsB,QAAQ;IAEnB,EAAE,EAAE,MAAM,CAAQ;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC5B,IAAI,EAAE,MAAM,CAAc;
|
|
1
|
+
{"version":3,"file":"Effector.d.ts","sourceRoot":"","sources":["../../../src/core/classes/Effector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGhH,8BAAsB,QAAQ;IAEnB,EAAE,EAAE,MAAM,CAAQ;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC5B,IAAI,EAAE,MAAM,CAAc;IAE1B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IACjD,OAAO,EAAE,YAAY,GAAG,IAAI,CAAQ;IAE3C,OAAO,CAAC,iCAAiC,CAAkB;IAE3D,OAAO,CAAC,MAAM,CAMb;IAED,OAAO,CAAC,sBAAsB;IAgB9B,SAAS,CAAC,4BAA4B,CAAC,IAAI,EAAE,gBAAgB;IAOtD,gBAAgB,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAOjG,IAAI,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAarF,mBAAmB,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,QAAQ;IAalG,mBAAmB,CAAC,KAAK,CAAC,EAAE,MAAM,gBAAgB,GAAG,QAAQ;aAWpD,sBAAsB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAC/E"}
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
import { Channel } from "./Channel";
|
|
2
|
+
import { Effector } from "./Effector";
|
|
3
|
+
import { AudioClipPlayer } from "./AudioClipPlayer";
|
|
4
|
+
import { AudioClip } from "./AudioClip";
|
|
2
5
|
export declare class Master {
|
|
3
6
|
id: string;
|
|
4
7
|
channels: Channel[];
|
|
8
|
+
effects: Effector[];
|
|
9
|
+
input: GainNode | null;
|
|
5
10
|
gainNode: GainNode | null;
|
|
6
11
|
analyserNode: AnalyserNode | null;
|
|
7
12
|
context: AudioContext | null;
|
|
13
|
+
audioClipPlayer: AudioClipPlayer | null;
|
|
8
14
|
constructor(context: AudioContext);
|
|
15
|
+
private disconnectAudioNodes;
|
|
16
|
+
private rebuildEffectChain;
|
|
17
|
+
AttachEffect(effect: Effector): void;
|
|
18
|
+
DetachEffect(effect: Effector): void;
|
|
9
19
|
AttachChannel(channel: Channel): void;
|
|
10
20
|
DetachChannel(channel: Channel): void;
|
|
21
|
+
HasAudioClipPlayer(): boolean;
|
|
22
|
+
AttachAudioClip(audioClip: AudioClip): void;
|
|
11
23
|
}
|
|
12
24
|
//# sourceMappingURL=Master.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Master.d.ts","sourceRoot":"","sources":["../../../src/core/classes/Master.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"Master.d.ts","sourceRoot":"","sources":["../../../src/core/classes/Master.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,qBAAa,MAAM;IAER,EAAE,EAAE,MAAM,CAAQ;IAElB,QAAQ,EAAE,OAAO,EAAE,CAAM;IACzB,OAAO,EAAE,QAAQ,EAAE,CAAM;IAEzB,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAC9B,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IACjC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IACzC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAQ;IACpC,eAAe,EAAE,eAAe,GAAG,IAAI,CAAQ;gBAE1C,OAAO,EAAE,YAAY;IAmBjC,OAAO,CAAC,oBAAoB;IAY5B,OAAO,CAAC,kBAAkB;IAuBnB,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAapC,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAkBpC,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAcrC,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAkBrC,kBAAkB,IAAI,OAAO;IAI7B,eAAe,CAAC,SAAS,EAAE,SAAS;CAM9C"}
|
|
@@ -1,17 +1,80 @@
|
|
|
1
1
|
import { v4 } from "uuid";
|
|
2
2
|
import { Debug } from "../../utilities/debugger";
|
|
3
|
+
import { AudioClipPlayer } from "./AudioClipPlayer";
|
|
3
4
|
export class Master {
|
|
4
5
|
id = v4();
|
|
5
6
|
channels = [];
|
|
7
|
+
effects = [];
|
|
8
|
+
input = null;
|
|
6
9
|
gainNode = null;
|
|
7
10
|
analyserNode = null;
|
|
8
11
|
context = null;
|
|
12
|
+
audioClipPlayer = null;
|
|
9
13
|
constructor(context) {
|
|
10
14
|
this.context = context;
|
|
15
|
+
this.disconnectAudioNodes();
|
|
16
|
+
this.audioClipPlayer = new AudioClipPlayer(context);
|
|
17
|
+
this.input = new GainNode(context);
|
|
11
18
|
this.gainNode = new GainNode(context);
|
|
12
19
|
this.analyserNode = new AnalyserNode(context);
|
|
20
|
+
this.input.connect(this.gainNode);
|
|
13
21
|
this.gainNode.connect(this.analyserNode);
|
|
14
22
|
this.analyserNode.connect(this.context.destination);
|
|
23
|
+
this.audioClipPlayer.Send(this);
|
|
24
|
+
}
|
|
25
|
+
disconnectAudioNodes() {
|
|
26
|
+
if (this.input)
|
|
27
|
+
this.input.disconnect();
|
|
28
|
+
if (this.gainNode)
|
|
29
|
+
this.gainNode.disconnect();
|
|
30
|
+
if (this.analyserNode)
|
|
31
|
+
this.analyserNode.disconnect();
|
|
32
|
+
this.effects.forEach(function (effect) {
|
|
33
|
+
if (effect.audioWorkletNode)
|
|
34
|
+
effect.audioWorkletNode.disconnect();
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
rebuildEffectChain() {
|
|
38
|
+
if (!this.context)
|
|
39
|
+
return;
|
|
40
|
+
if (!this.input || !this.gainNode || !this.analyserNode)
|
|
41
|
+
return;
|
|
42
|
+
this.disconnectAudioNodes();
|
|
43
|
+
let currentNode = this.input;
|
|
44
|
+
this.effects.forEach(function (effect) {
|
|
45
|
+
if (!effect.audioWorkletNode)
|
|
46
|
+
return;
|
|
47
|
+
currentNode.connect(effect.audioWorkletNode);
|
|
48
|
+
currentNode = effect.audioWorkletNode;
|
|
49
|
+
});
|
|
50
|
+
currentNode.connect(this.gainNode);
|
|
51
|
+
this.gainNode.connect(this.analyserNode);
|
|
52
|
+
this.analyserNode.connect(this.context.destination);
|
|
53
|
+
}
|
|
54
|
+
AttachEffect(effect) {
|
|
55
|
+
if (this.effects.includes(effect))
|
|
56
|
+
return Debug.Error("Could not attach the effect because it is already part of this master channel.", [
|
|
57
|
+
"Call .DetachEffect([effect Effector]) before attaching the effect."
|
|
58
|
+
]);
|
|
59
|
+
if (!this.context)
|
|
60
|
+
return this.rebuildEffectChain();
|
|
61
|
+
this.effects.push(effect);
|
|
62
|
+
effect.InitializeOnAttachment(this.context);
|
|
63
|
+
this.rebuildEffectChain();
|
|
64
|
+
}
|
|
65
|
+
DetachEffect(effect) {
|
|
66
|
+
if (!this.effects.includes(effect))
|
|
67
|
+
return Debug.Error("Could not detach the effect because it is not part of this master channel.", [
|
|
68
|
+
"Call .AttachEffect([effect Effector]) before detaching the effect."
|
|
69
|
+
]);
|
|
70
|
+
const self = this;
|
|
71
|
+
this.effects.forEach(function (_effect, index) {
|
|
72
|
+
if (effect.id === _effect.id) {
|
|
73
|
+
self.effects.splice(index, 1);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
this.rebuildEffectChain();
|
|
15
78
|
}
|
|
16
79
|
AttachChannel(channel) {
|
|
17
80
|
if (this.channels.includes(channel))
|
|
@@ -19,8 +82,8 @@ export class Master {
|
|
|
19
82
|
"Call .DetachChannel([channel Channel]) before attaching the channel."
|
|
20
83
|
]);
|
|
21
84
|
this.channels.push(channel);
|
|
22
|
-
if (channel.output && this.
|
|
23
|
-
channel.output.connect(this.
|
|
85
|
+
if (channel.output && this.input)
|
|
86
|
+
channel.output.connect(this.input);
|
|
24
87
|
return;
|
|
25
88
|
}
|
|
26
89
|
DetachChannel(channel) {
|
|
@@ -28,14 +91,21 @@ export class Master {
|
|
|
28
91
|
return Debug.Error("Could not detach the channel because it is not part of this master channel.", [
|
|
29
92
|
"Call .AttachChannel([channel Channel]) before detaching the channel."
|
|
30
93
|
]);
|
|
31
|
-
if (channel.output && this.
|
|
32
|
-
channel.output.disconnect(this.
|
|
94
|
+
if (channel.output && this.input)
|
|
95
|
+
channel.output.disconnect(this.input);
|
|
33
96
|
const self = this;
|
|
34
97
|
this.channels.forEach(function (_channel, index) {
|
|
35
|
-
if (channel.id
|
|
36
|
-
self.channels.splice(index, 1);
|
|
98
|
+
if (channel.id !== _channel.id)
|
|
37
99
|
return;
|
|
38
|
-
|
|
100
|
+
self.channels.splice(index, 1);
|
|
39
101
|
});
|
|
40
102
|
}
|
|
103
|
+
HasAudioClipPlayer() {
|
|
104
|
+
return !!this.audioClipPlayer;
|
|
105
|
+
}
|
|
106
|
+
AttachAudioClip(audioClip) {
|
|
107
|
+
if (!this.audioClipPlayer)
|
|
108
|
+
return Debug.Error("Cannot not link AudioClip to this channel because this channel's AudioClipPlayer is undefined.");
|
|
109
|
+
this.audioClipPlayer.AttachAudioClip(audioClip);
|
|
110
|
+
}
|
|
41
111
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Effector } from "../../core/exports";
|
|
2
|
+
export declare class Analyser extends Effector {
|
|
3
|
+
label: string | null;
|
|
4
|
+
name: string;
|
|
5
|
+
analyserNode: AnalyserNode | null;
|
|
6
|
+
float32ArrayBuffer: Float32Array<ArrayBuffer>;
|
|
7
|
+
uint8ArrayBuffer: Uint8Array<ArrayBuffer>;
|
|
8
|
+
private options;
|
|
9
|
+
constructor(options?: Partial<AnalyserOptions>);
|
|
10
|
+
InitializeOnAttachment(context: AudioContext): Promise<void>;
|
|
11
|
+
SetOptions(options: Partial<AnalyserOptions>): void;
|
|
12
|
+
GetWaveformFloatData(): Float32Array | null;
|
|
13
|
+
GetWaveformByteData(): Uint8Array | null;
|
|
14
|
+
private allocateBuffers;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=Analyser.d.ts.map
|
|
@@ -0,0 +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,kBAAkB,4BAAsB;IACxC,gBAAgB,0BAAoB;IAE3C,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;IAQ/C,OAAO,CAAC,eAAe;CAO1B"}
|