@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.
Files changed (78) hide show
  1. package/README.md +16 -38
  2. package/lib/dist/core/classes/AudioClip.d.ts +3 -1
  3. package/lib/dist/core/classes/AudioClip.d.ts.map +1 -1
  4. package/lib/dist/core/classes/AudioClip.js +18 -5
  5. package/lib/dist/core/classes/AudioClipPlayer.d.ts +8 -2
  6. package/lib/dist/core/classes/AudioClipPlayer.d.ts.map +1 -1
  7. package/lib/dist/core/classes/AudioClipPlayer.js +48 -1
  8. package/lib/dist/core/classes/AudioDevice.d.ts +2 -0
  9. package/lib/dist/core/classes/AudioDevice.d.ts.map +1 -1
  10. package/lib/dist/core/classes/AudioDevice.js +4 -0
  11. package/lib/dist/core/classes/Channel.d.ts +10 -2
  12. package/lib/dist/core/classes/Channel.d.ts.map +1 -1
  13. package/lib/dist/core/classes/Channel.js +67 -0
  14. package/lib/dist/core/classes/DpsPipeline.d.ts +1 -1
  15. package/lib/dist/core/classes/DpsPipeline.d.ts.map +1 -1
  16. package/lib/dist/core/classes/DpsPipeline.js +7 -3
  17. package/lib/dist/core/classes/Effector.d.ts +2 -2
  18. package/lib/dist/core/classes/Effector.d.ts.map +1 -1
  19. package/lib/dist/core/classes/Effector.js +1 -1
  20. package/lib/dist/core/classes/Master.d.ts +12 -0
  21. package/lib/dist/core/classes/Master.d.ts.map +1 -1
  22. package/lib/dist/core/classes/Master.js +77 -7
  23. package/lib/dist/effects/classes/Analyser.d.ts +16 -0
  24. package/lib/dist/effects/classes/Analyser.d.ts.map +1 -0
  25. package/lib/dist/effects/classes/Analyser.js +62 -0
  26. package/lib/dist/effects/classes/Chorus.d.ts +4 -3
  27. package/lib/dist/effects/classes/Chorus.d.ts.map +1 -1
  28. package/lib/dist/effects/classes/Chorus.js +21 -12
  29. package/lib/dist/effects/classes/clips/HardClip.d.ts +4 -3
  30. package/lib/dist/effects/classes/clips/HardClip.d.ts.map +1 -1
  31. package/lib/dist/effects/classes/clips/HardClip.js +15 -9
  32. package/lib/dist/effects/classes/clips/SoftClip.d.ts +4 -3
  33. package/lib/dist/effects/classes/clips/SoftClip.d.ts.map +1 -1
  34. package/lib/dist/effects/classes/clips/SoftClip.js +15 -9
  35. package/lib/dist/effects/classes/filters/LowPassFilter.d.ts +4 -3
  36. package/lib/dist/effects/classes/filters/LowPassFilter.d.ts.map +1 -1
  37. package/lib/dist/effects/classes/filters/LowPassFilter.js +23 -14
  38. package/lib/dist/effects/exports.d.ts +1 -0
  39. package/lib/dist/effects/exports.d.ts.map +1 -1
  40. package/lib/dist/effects/exports.js +1 -0
  41. package/lib/dist/index.d.ts +5 -4
  42. package/lib/dist/index.d.ts.map +1 -1
  43. package/lib/dist/index.js +13 -18
  44. package/lib/dist/typings.d.ts +13 -11
  45. package/lib/dist/typings.d.ts.map +1 -1
  46. package/lib/dist/typings.js +5 -0
  47. package/lib/dist/utilities/debugger.js +6 -6
  48. package/lib/dist/utilities/helpers.d.ts +2 -0
  49. package/lib/dist/utilities/helpers.d.ts.map +1 -1
  50. package/lib/dist/utilities/helpers.js +35 -12
  51. package/lib/src/core/classes/AudioClip.ts +23 -7
  52. package/lib/src/core/classes/AudioClipPlayer.ts +67 -7
  53. package/lib/src/core/classes/AudioDevice.ts +5 -0
  54. package/lib/src/core/classes/Channel.ts +97 -4
  55. package/lib/src/core/classes/DpsPipeline.ts +7 -3
  56. package/lib/src/core/classes/Effector.ts +3 -2
  57. package/lib/src/core/classes/Master.ts +98 -11
  58. package/lib/src/effects/classes/Analyser.ts +84 -0
  59. package/lib/src/effects/classes/Chorus.ts +22 -13
  60. package/lib/src/effects/classes/clips/HardClip.ts +17 -10
  61. package/lib/src/effects/classes/clips/SoftClip.ts +17 -10
  62. package/lib/src/effects/classes/filters/LowPassFilter.ts +28 -15
  63. package/lib/src/effects/exports.ts +2 -1
  64. package/lib/src/index.ts +27 -29
  65. package/lib/src/typings.ts +14 -14
  66. package/lib/src/utilities/debugger.ts +6 -6
  67. package/lib/src/utilities/helpers.ts +38 -14
  68. package/package.json +1 -1
  69. package/lib/dist/effects/classes/Filter.d.ts +0 -3
  70. package/lib/dist/effects/classes/Filter.d.ts.map +0 -1
  71. package/lib/dist/effects/classes/Filter.js +0 -2
  72. package/lib/dist/effects/classes/SoftClip.d.ts +0 -10
  73. package/lib/dist/effects/classes/SoftClip.d.ts.map +0 -1
  74. package/lib/dist/effects/classes/SoftClip.js +0 -39
  75. package/lib/dist/test/linkable-channels.d.ts +0 -2
  76. package/lib/dist/test/linkable-channels.d.ts.map +0 -1
  77. package/lib/dist/test/linkable-channels.js +0 -16
  78. 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
- // Make sure that FluexGL can access audio devices.
37
- const hasInitialized = await InitializeDspPipeline();
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
- if(!audioDevice) return;
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
- // Label the channel as 'BackgroundMusic'.
55
- channel.SetLabel("BackgroundMusic");
35
+ const audioDevice = await pipeline.ResolveDefaultAudioOutputDevice();
56
36
 
57
- // Attach the 'BackgroundMusic' channel, to the device's master channel.
58
- masterChannel.AttachChannel(channel);
37
+ if(!audioDevice) return;
59
38
 
60
- // Load the data from the audio source.
61
- const audioSourceData: AudioSourceData | null = await LoadAudioSource("/assets/data/bruh.mp3");
39
+ const master = audioDevice.GetMasterChannel();
40
+ const context = audioDevice.GetContext();
62
41
 
63
- if(!audioSourceData) return;
42
+ const audioSource = await LoadAudioSource("/music.mp3");
64
43
 
65
- // Create a audio node based on the data.
66
- const audioClip = new AudioClip(audioSourceData);
44
+ if(!audioSource) return;
67
45
 
68
- // Attach the audio node to the channel.
69
- channel.AttachAudioClip(audioClip);
46
+ const audioClip = new AudioClip(audioSource);
47
+ const channel = new Channel(context);
70
48
 
71
- // Click event listener on window.
72
- window.addEventListener("click", function() {
49
+ channel.Send(master);
50
+ audioClip.Send(channel);
73
51
 
74
- // Play the audio clip
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,EAAoD,iBAAiB,EAAmB,eAAe,EAAE,MAAM,eAAe,CAAC;AAEtI,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIpD,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;IAUtD,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;IAW5B,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
+ {"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
- Debug.Warn("Changing the amount of buffer source nodes may cause some properties of this class instance to work inproperly.", [
185
- "The default value is 1."
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.HasAudioClipPlayer())
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
- Send(channel: Channel): void;
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;AAGxC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,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,IAAI,CAAQ;gBAE1B,OAAO,EAAE,YAAY;IAK1B,eAAe,CAAC,SAAS,EAAE,SAAS;IAUpC,IAAI,CAAC,OAAO,EAAE,OAAO;IAQrB,QAAQ,CAAC,KAAK,EAAE,MAAM;CAGhC"}
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;AAKlC,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;CAGpC"}
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
- private sends;
13
- private audioClipPlayer;
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":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,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,YAAY,GAAG,IAAI,CAAQ;IAE3C,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,eAAe,CAAgC;gBAE3C,OAAO,EAAE,YAAY;IAqBjC,OAAO,CAAC,oBAAoB;IAiB5B,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,WAAW;IAwBZ,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAiC9B,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAehC,kBAAkB,IAAI,OAAO;IAI7B,mBAAmB;IASnB,eAAe,CAAC,SAAS,EAAE,SAAS;CAM9C"}
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;AAEjE;;;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,OAAO,EAAE,gCAAgC;IAKrD;;;;;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"}
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 = options.pathToWasm;
40
- this.pathToWorklet = options.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
- parentialContext: AudioContext | null;
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(parentialContext: AudioContext): Promise<void>;
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;IAC1B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IACjD,gBAAgB,EAAE,YAAY,GAAG,IAAI,CAAQ;IAEpD,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,gBAAgB,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CACxF"}
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"}
@@ -5,7 +5,7 @@ export class Effector {
5
5
  label = null;
6
6
  name = "Effector";
7
7
  audioWorkletNode = null;
8
- parentialContext = null;
8
+ context = null;
9
9
  hasRegisteredMessageEventListener = false;
10
10
  events = {
11
11
  "incoming-processor-error": [],
@@ -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;AAKpC,qBAAa,MAAM;IAER,EAAE,EAAE,MAAM,CAAQ;IAClB,QAAQ,EAAE,OAAO,EAAE,CAAM;IAEzB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IACjC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IAEzC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAQ;gBAE/B,OAAO,EAAE,YAAY;IAW1B,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAcrC,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAmB/C"}
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.gainNode)
23
- channel.output.connect(this.gainNode);
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.gainNode)
32
- channel.output.disconnect(this.gainNode);
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 === _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"}