@fluex/fluexgl-dsp 0.4.1 → 0.4.3

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 (85) hide show
  1. package/README.md +16 -38
  2. package/lib/dist/console-codes.d.ts +22 -7
  3. package/lib/dist/console-codes.d.ts.map +1 -1
  4. package/lib/dist/console-codes.js +22 -7
  5. package/lib/dist/core/classes/AudioClip.d.ts +3 -1
  6. package/lib/dist/core/classes/AudioClip.d.ts.map +1 -1
  7. package/lib/dist/core/classes/AudioClip.js +23 -17
  8. package/lib/dist/core/classes/AudioClipPlayer.d.ts +10 -2
  9. package/lib/dist/core/classes/AudioClipPlayer.d.ts.map +1 -1
  10. package/lib/dist/core/classes/AudioClipPlayer.js +56 -2
  11. package/lib/dist/core/classes/AudioDevice.d.ts +2 -0
  12. package/lib/dist/core/classes/AudioDevice.d.ts.map +1 -1
  13. package/lib/dist/core/classes/AudioDevice.js +5 -0
  14. package/lib/dist/core/classes/Channel.d.ts +14 -4
  15. package/lib/dist/core/classes/Channel.d.ts.map +1 -1
  16. package/lib/dist/core/classes/Channel.js +93 -7
  17. package/lib/dist/core/classes/DpsPipeline.d.ts +1 -1
  18. package/lib/dist/core/classes/DpsPipeline.d.ts.map +1 -1
  19. package/lib/dist/core/classes/DpsPipeline.js +7 -3
  20. package/lib/dist/core/classes/Effector.d.ts +2 -2
  21. package/lib/dist/core/classes/Effector.d.ts.map +1 -1
  22. package/lib/dist/core/classes/Effector.js +1 -1
  23. package/lib/dist/core/classes/Master.d.ts +12 -0
  24. package/lib/dist/core/classes/Master.d.ts.map +1 -1
  25. package/lib/dist/core/classes/Master.js +80 -9
  26. package/lib/dist/effects/classes/Analyser.d.ts +16 -0
  27. package/lib/dist/effects/classes/Analyser.d.ts.map +1 -0
  28. package/lib/dist/effects/classes/Analyser.js +62 -0
  29. package/lib/dist/effects/classes/Chorus.d.ts +4 -3
  30. package/lib/dist/effects/classes/Chorus.d.ts.map +1 -1
  31. package/lib/dist/effects/classes/Chorus.js +21 -12
  32. package/lib/dist/effects/classes/clips/HardClip.d.ts +4 -3
  33. package/lib/dist/effects/classes/clips/HardClip.d.ts.map +1 -1
  34. package/lib/dist/effects/classes/clips/HardClip.js +15 -9
  35. package/lib/dist/effects/classes/clips/SoftClip.d.ts +4 -3
  36. package/lib/dist/effects/classes/clips/SoftClip.d.ts.map +1 -1
  37. package/lib/dist/effects/classes/clips/SoftClip.js +15 -9
  38. package/lib/dist/effects/classes/filters/LowPassFilter.d.ts +4 -3
  39. package/lib/dist/effects/classes/filters/LowPassFilter.d.ts.map +1 -1
  40. package/lib/dist/effects/classes/filters/LowPassFilter.js +23 -14
  41. package/lib/dist/effects/exports.d.ts +1 -0
  42. package/lib/dist/effects/exports.d.ts.map +1 -1
  43. package/lib/dist/effects/exports.js +1 -0
  44. package/lib/dist/index.d.ts +5 -4
  45. package/lib/dist/index.d.ts.map +1 -1
  46. package/lib/dist/index.js +13 -18
  47. package/lib/dist/typings.d.ts +13 -11
  48. package/lib/dist/typings.d.ts.map +1 -1
  49. package/lib/dist/typings.js +5 -0
  50. package/lib/dist/utilities/debugger.js +6 -6
  51. package/lib/dist/utilities/helpers.d.ts +2 -0
  52. package/lib/dist/utilities/helpers.d.ts.map +1 -1
  53. package/lib/dist/utilities/helpers.js +35 -12
  54. package/lib/dist/utilities/web-assembly.d.ts.map +1 -1
  55. package/lib/dist/utilities/web-assembly.js +6 -0
  56. package/lib/src/console-codes.ts +22 -7
  57. package/lib/src/core/classes/AudioClip.ts +28 -19
  58. package/lib/src/core/classes/AudioClipPlayer.ts +77 -8
  59. package/lib/src/core/classes/AudioDevice.ts +6 -1
  60. package/lib/src/core/classes/Channel.ts +126 -13
  61. package/lib/src/core/classes/DpsPipeline.ts +7 -3
  62. package/lib/src/core/classes/Effector.ts +3 -2
  63. package/lib/src/core/classes/Master.ts +101 -13
  64. package/lib/src/effects/classes/Analyser.ts +84 -0
  65. package/lib/src/effects/classes/Chorus.ts +22 -13
  66. package/lib/src/effects/classes/clips/HardClip.ts +17 -10
  67. package/lib/src/effects/classes/clips/SoftClip.ts +17 -10
  68. package/lib/src/effects/classes/filters/LowPassFilter.ts +28 -15
  69. package/lib/src/effects/exports.ts +2 -1
  70. package/lib/src/index.ts +27 -29
  71. package/lib/src/typings.ts +14 -14
  72. package/lib/src/utilities/debugger.ts +6 -6
  73. package/lib/src/utilities/helpers.ts +39 -15
  74. package/lib/src/utilities/web-assembly.ts +8 -0
  75. package/package.json +1 -1
  76. package/lib/dist/effects/classes/Filter.d.ts +0 -3
  77. package/lib/dist/effects/classes/Filter.d.ts.map +0 -1
  78. package/lib/dist/effects/classes/Filter.js +0 -2
  79. package/lib/dist/effects/classes/SoftClip.d.ts +0 -10
  80. package/lib/dist/effects/classes/SoftClip.d.ts.map +0 -1
  81. package/lib/dist/effects/classes/SoftClip.js +0 -39
  82. package/lib/dist/test/linkable-channels.d.ts +0 -2
  83. package/lib/dist/test/linkable-channels.d.ts.map +0 -1
  84. package/lib/dist/test/linkable-channels.js +0 -16
  85. 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,13 +1,28 @@
1
1
  export declare enum ErrorCodes {
2
- NO_CONTEXT_PERMISSION = "FLUEXGL@AUDIO_ERROR_0001",
3
- NO_FILE_TYPE_FOUND = "FLUEXGL@AUDIO_ERROR_0002",
4
- PATH_TO_FILE_NOT_FOUND = "FLUEXGL@AUDIO_ERROR_0003",
5
- SAME_MASTER_CHANNEL = "FLUEXGL@AUDIO_ERROR_0004",
6
- WASM_MODULE_INITIALIZATION_FAILED = "FLUEXGL@AUDIO_ERROR_0005",
7
- PATH_TO_WASM_FILE_NOT_FOUND = "FLUEXGL@AUDIO_ERROR_0006"
2
+ NO_CONTEXT_PERMISSION = "ERROR:FLUEXGL-DSP@0001",
3
+ NO_FILE_TYPE_FOUND = "ERROR:FLUEXGL-DSP@0002",
4
+ PATH_TO_FILE_NOT_FOUND = "ERROR:FLUEXGL-DSP@0003",
5
+ SAME_MASTER_CHANNEL = "ERROR:FLUEXGL-DSP@0004",
6
+ WASM_MODULE_INITIALIZATION_FAILED = "ERROR:FLUEXGL-DSP@0005",
7
+ PATH_TO_WASM_FILE_NOT_FOUND = "ERROR:FLUEXGL-DSP@0006",
8
+ WASM_COMPILATION_ERROR = "ERROR:FLUEXGL-DSP@0007",
9
+ WORKLET_NO_WASM_MODULE_INSTANTIATED = "ERROR:FLUEXGL-DSP@0008",
10
+ EFFECT_ALREADY_ATTACHED = "ERROR:FLUEXGL-DSP@0009",
11
+ EFFECT_NOT_FOUND = "ERROR:FLUEXGL-DSP@0010",
12
+ CHANNEL_ALREADY_ATTACHED = "ERROR:FLUEXGL-DSP@0011",
13
+ CHANNEL_NOT_FOUND = "ERROR:FLUEXGL-DSP@0012",
14
+ CHANNEL_CANNOT_LINK_TO_ITSELF = "ERROR:FLUEXGL-DSP@0013",
15
+ CHANNEL_NOT_INITIALIZED = "ERROR:FLUEXGL-DSP@0014",
16
+ CHANNEL_NOT_SAME_AUDIO_CONTEXT = "ERROR:FLUEXGL-DSP@0015",
17
+ CHANNEL_ALREADY_LINKED = "ERROR:FLUEXGL-DSP@0016",
18
+ CHANNEL_POSSIBLE_FEEDBACK_LOOP = "ERROR:FLUEXGL-DSP@0017",
19
+ AUDIO_CLIP_ALREADY_ATTACHED = "ERROR:FLUEXGL-DSP@0018",
20
+ AUDIO_CLIP_NOT_FOUND = "ERROR:FLUEXGL-DSP@0019",
21
+ AUDIO_CLIP_PLAYER_NO_CONTEXT = "ERROR:FLUEXGL-DSP@0020",
22
+ PANNING_OUT_OF_RANGE = "ERROR:FLUEXGL-DSP@0021"
8
23
  }
9
24
  export declare enum WarningCodes {
10
- NO_DEFAULT_AUDIO_DEVICE_FOUND = "FLUEXGL@AUDIO_WARNING_0001"
25
+ NO_DEFAULT_AUDIO_DEVICE_FOUND = "WARNING:FLUEXGL-DSP@0001"
11
26
  }
12
27
  export declare enum SuccessCodes {
13
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"console-codes.d.ts","sourceRoot":"","sources":["../src/console-codes.ts"],"names":[],"mappings":"AAAA,oBAAY,UAAU;IAClB,qBAAqB,6BAA6B;IAClD,kBAAkB,6BAA6B;IAC/C,sBAAsB,6BAA6B;IACnD,mBAAmB,6BAA6B;IAChD,iCAAiC,6BAA6B;IAC9D,2BAA2B,6BAA6B;CAC3D;AAED,oBAAY,YAAY;IACpB,6BAA6B,+BAA+B;CAC/D;AAED,oBAAY,YAAY;CAEvB"}
1
+ {"version":3,"file":"console-codes.d.ts","sourceRoot":"","sources":["../src/console-codes.ts"],"names":[],"mappings":"AAAA,oBAAY,UAAU;IAClB,qBAAqB,2BAA2B;IAChD,kBAAkB,2BAA2B;IAC7C,sBAAsB,2BAA2B;IACjD,mBAAmB,2BAA2B;IAC9C,iCAAiC,2BAA2B;IAC5D,2BAA2B,2BAA2B;IACtD,sBAAsB,2BAA2B;IACjD,mCAAmC,2BAA2B;IAC9D,uBAAuB,2BAA2B;IAClD,gBAAgB,2BAA2B;IAC3C,wBAAwB,2BAA2B;IACnD,iBAAiB,2BAA2B;IAC5C,6BAA6B,2BAA2B;IACxD,uBAAuB,2BAA2B;IAClD,8BAA8B,2BAA2B;IACzD,sBAAsB,2BAA2B;IACjD,8BAA8B,2BAA2B;IACzD,2BAA2B,2BAA2B;IACtD,oBAAoB,2BAA2B;IAC/C,4BAA4B,2BAA2B;IACvD,oBAAoB,2BAA2B;CAClD;AAED,oBAAY,YAAY;IACpB,6BAA6B,6BAA6B;CAC7D;AAED,oBAAY,YAAY;CAEvB"}
@@ -1,15 +1,30 @@
1
1
  export var ErrorCodes;
2
2
  (function (ErrorCodes) {
3
- ErrorCodes["NO_CONTEXT_PERMISSION"] = "FLUEXGL@AUDIO_ERROR_0001";
4
- ErrorCodes["NO_FILE_TYPE_FOUND"] = "FLUEXGL@AUDIO_ERROR_0002";
5
- ErrorCodes["PATH_TO_FILE_NOT_FOUND"] = "FLUEXGL@AUDIO_ERROR_0003";
6
- ErrorCodes["SAME_MASTER_CHANNEL"] = "FLUEXGL@AUDIO_ERROR_0004";
7
- ErrorCodes["WASM_MODULE_INITIALIZATION_FAILED"] = "FLUEXGL@AUDIO_ERROR_0005";
8
- ErrorCodes["PATH_TO_WASM_FILE_NOT_FOUND"] = "FLUEXGL@AUDIO_ERROR_0006";
3
+ ErrorCodes["NO_CONTEXT_PERMISSION"] = "ERROR:FLUEXGL-DSP@0001";
4
+ ErrorCodes["NO_FILE_TYPE_FOUND"] = "ERROR:FLUEXGL-DSP@0002";
5
+ ErrorCodes["PATH_TO_FILE_NOT_FOUND"] = "ERROR:FLUEXGL-DSP@0003";
6
+ ErrorCodes["SAME_MASTER_CHANNEL"] = "ERROR:FLUEXGL-DSP@0004";
7
+ ErrorCodes["WASM_MODULE_INITIALIZATION_FAILED"] = "ERROR:FLUEXGL-DSP@0005";
8
+ ErrorCodes["PATH_TO_WASM_FILE_NOT_FOUND"] = "ERROR:FLUEXGL-DSP@0006";
9
+ ErrorCodes["WASM_COMPILATION_ERROR"] = "ERROR:FLUEXGL-DSP@0007";
10
+ ErrorCodes["WORKLET_NO_WASM_MODULE_INSTANTIATED"] = "ERROR:FLUEXGL-DSP@0008";
11
+ ErrorCodes["EFFECT_ALREADY_ATTACHED"] = "ERROR:FLUEXGL-DSP@0009";
12
+ ErrorCodes["EFFECT_NOT_FOUND"] = "ERROR:FLUEXGL-DSP@0010";
13
+ ErrorCodes["CHANNEL_ALREADY_ATTACHED"] = "ERROR:FLUEXGL-DSP@0011";
14
+ ErrorCodes["CHANNEL_NOT_FOUND"] = "ERROR:FLUEXGL-DSP@0012";
15
+ ErrorCodes["CHANNEL_CANNOT_LINK_TO_ITSELF"] = "ERROR:FLUEXGL-DSP@0013";
16
+ ErrorCodes["CHANNEL_NOT_INITIALIZED"] = "ERROR:FLUEXGL-DSP@0014";
17
+ ErrorCodes["CHANNEL_NOT_SAME_AUDIO_CONTEXT"] = "ERROR:FLUEXGL-DSP@0015";
18
+ ErrorCodes["CHANNEL_ALREADY_LINKED"] = "ERROR:FLUEXGL-DSP@0016";
19
+ ErrorCodes["CHANNEL_POSSIBLE_FEEDBACK_LOOP"] = "ERROR:FLUEXGL-DSP@0017";
20
+ ErrorCodes["AUDIO_CLIP_ALREADY_ATTACHED"] = "ERROR:FLUEXGL-DSP@0018";
21
+ ErrorCodes["AUDIO_CLIP_NOT_FOUND"] = "ERROR:FLUEXGL-DSP@0019";
22
+ ErrorCodes["AUDIO_CLIP_PLAYER_NO_CONTEXT"] = "ERROR:FLUEXGL-DSP@0020";
23
+ ErrorCodes["PANNING_OUT_OF_RANGE"] = "ERROR:FLUEXGL-DSP@0021";
9
24
  })(ErrorCodes || (ErrorCodes = {}));
10
25
  export var WarningCodes;
11
26
  (function (WarningCodes) {
12
- WarningCodes["NO_DEFAULT_AUDIO_DEVICE_FOUND"] = "FLUEXGL@AUDIO_WARNING_0001";
27
+ WarningCodes["NO_DEFAULT_AUDIO_DEVICE_FOUND"] = "WARNING:FLUEXGL-DSP@0001";
13
28
  })(WarningCodes || (WarningCodes = {}));
14
29
  export var SuccessCodes;
15
30
  (function (SuccessCodes) {
@@ -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;AAMlC,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;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;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,8 @@
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";
5
+ import { ErrorCodes } from "lib/src/console-codes";
4
6
  export class AudioClip {
5
7
  data;
6
8
  id = v4();
@@ -59,7 +61,7 @@ export class AudioClip {
59
61
  return Debug.Error("Could not initialize AudioClip, because the AudioClipPlayer somehow has no audio context.", [
60
62
  `AudioClipPlayer id: ${audioClipPlayer.id}`,
61
63
  `AudioClip id: ${this.id}`
62
- ]);
64
+ ], ErrorCodes.AUDIO_CLIP_PLAYER_NO_CONTEXT);
63
65
  this.audioClipPlayer = audioClipPlayer;
64
66
  this.context = audioClipPlayer.context;
65
67
  this.gainNode = new GainNode(this.context);
@@ -148,11 +150,7 @@ export class AudioClip {
148
150
  if (!this.context)
149
151
  Debug.Error("Could not set volume because the context (AudioContext) of this AudioClip is undefined.", [
150
152
  "Make sure to attach this AudioClip to an AudioClipPlayer instance before calling .SetVolume() on this AudioClip.",
151
- ]);
152
- if (!this.gainNode)
153
- Debug.Error("Could not set volume because the gainNode (GainNode) of this AudioClip is undefined.", [
154
- "Make sure to attach this AudioClip to an AudioClipPlayer instance before calling .SetVolume() on this AudioClip.",
155
- ]);
153
+ ], ErrorCodes.AUDIO_CLIP_PLAYER_NO_CONTEXT);
156
154
  this.gainNode?.gain.setValueAtTime(volume, this.context?.currentTime ?? 0);
157
155
  return this;
158
156
  }
@@ -160,16 +158,12 @@ export class AudioClip {
160
158
  if (!this.context)
161
159
  Debug.Error("Could not set volume because the context (AudioContext) of this AudioClip is undefined.", [
162
160
  "Make sure to attach this AudioClip to an AudioClipPlayer instance before calling .SetPanLevel() on this AudioClip.",
163
- ]);
164
- if (!this.stereoPannerNode)
165
- Debug.Error("Could not set volume because the stereoPannerNode (StereoPannerNode) of this AudioClip is undefined.", [
166
- "Make sure to attach this AudioClip to an AudioClipPlayer instance before calling .SetPanLevel() on this AudioClip.",
167
- ]);
161
+ ], ErrorCodes.AUDIO_CLIP_PLAYER_NO_CONTEXT);
168
162
  if (panLevel < -1 || panLevel > 1)
169
163
  Debug.Error("Could not set the pan level because it is not between -1 and 1.", [
170
164
  `Given value: ${panLevel}.`,
171
165
  `Accepts a value between -1 and 1. Can be a floating number.`
172
- ]);
166
+ ], ErrorCodes.PANNING_OUT_OF_RANGE);
173
167
  this.stereoPannerNode?.pan.setValueAtTime(panLevel, this.context?.currentTime ?? 0);
174
168
  return this;
175
169
  }
@@ -181,9 +175,12 @@ export class AudioClip {
181
175
  return this;
182
176
  }
183
177
  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
- ]);
178
+ if (!DSP.overrideMaxAudioBufferNodes) {
179
+ Debug.Warn("Cannot set maxAudioBufferSourceNodes because the option to override the current maximum value is disabled.", [
180
+ "Set overrideMaxAudioBufferNodes on DSP to true, in order to override the maximum audio buffer source nodes."
181
+ ]);
182
+ return this;
183
+ }
187
184
  this.maxAudioBufferSourceNodes = value;
188
185
  return this;
189
186
  }
@@ -232,13 +229,22 @@ export class AudioClip {
232
229
  return this.data.audioBuffer.getChannelData(channel);
233
230
  }
234
231
  Send(channel) {
235
- if (!channel.HasAudioClipPlayer())
232
+ if (!channel.audioClipPlayer)
236
233
  return Debug.Error("Could not send AudioClip signal to channel, because the channel's AudioClipPlayer is undefined.", [
237
234
  "Make sure to initialize the Channel.",
238
235
  `Channel id: ${channel.id}.`,
239
236
  `AudioClip id: ${this.id}.`
240
237
  ]);
241
- channel.AttachAudioClip(this);
238
+ channel.audioClipPlayer.AttachAudioClip(this);
239
+ }
240
+ Unsend(channel) {
241
+ if (!channel.audioClipPlayer)
242
+ return Debug.Error("Could not unsend AudioClip signal to channel, because the channel's AudioClipPlayer is undefined.", [
243
+ "Make sure to initialize the Channel.",
244
+ `Channel id: ${channel.id}.`,
245
+ `AudioClip id: ${this.id}.`
246
+ ]);
247
+ channel.audioClipPlayer.DetachAudioClip(this);
242
248
  }
243
249
  get currentPlaybackTime() {
244
250
  return (!this.isPlaying || !this.context)
@@ -1,15 +1,23 @@
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;
20
+ get length(): number;
21
+ get volume(): number;
14
22
  }
15
23
  //# 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;AAGlC,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;IAIpC,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED,IAAW,MAAM,IAAI,MAAM,CAE1B;CACJ"}
@@ -1,5 +1,6 @@
1
1
  import { v4 } from "uuid";
2
2
  import { Debug } from "../../utilities/debugger";
3
+ import { ErrorCodes } from "lib/src/console-codes";
3
4
  export class AudioClipPlayer {
4
5
  label = "AudioClipPlayer";
5
6
  id = v4();
@@ -15,17 +16,70 @@ export class AudioClipPlayer {
15
16
  if (this.audioClips.includes(audioClip))
16
17
  return Debug.Error("Could not attach audio clip because it is already part of this channel", [
17
18
  "Call .DetachAudioClip([clip AudioClip]) before attaching audio clip."
18
- ]);
19
+ ], ErrorCodes.AUDIO_CLIP_ALREADY_ATTACHED);
19
20
  audioClip.Initialize(this);
20
21
  this.audioClips.push(audioClip);
21
22
  }
23
+ DetachAudioClip(clip) {
24
+ if (!this.audioClips.includes(clip))
25
+ return Debug.Error("Could not detach audio clip because it is not part of this channel", [
26
+ "Call .AttachAudioClip([clip AudioClip]) before detaching audio clip."
27
+ ], ErrorCodes.AUDIO_CLIP_NOT_FOUND);
28
+ clip.Stop();
29
+ const self = this;
30
+ this.audioClips.forEach(function (_clip, index) {
31
+ if (clip.id === _clip.id)
32
+ return self.audioClips.splice(index, 1);
33
+ });
34
+ }
22
35
  Send(channel) {
23
36
  if (!this.outputGainNode || !channel.input)
24
- return Debug.Error("Could not send AudioClipPlayer signal to a channel.");
37
+ return Debug.Error("Could not send AudioClipPlayer signal to a channel/master.");
38
+ this.Unsend();
25
39
  this.channel = channel;
26
40
  this.outputGainNode.connect(channel.input);
27
41
  }
42
+ Unsend() {
43
+ if (!this.outputGainNode)
44
+ return;
45
+ if (this.channel && this.channel.input) {
46
+ this.outputGainNode.disconnect(this.channel.input);
47
+ }
48
+ else {
49
+ this.outputGainNode.disconnect();
50
+ }
51
+ this.channel = null;
52
+ }
53
+ SetVolume(value) {
54
+ if (!this.outputGainNode)
55
+ return;
56
+ if (value < 0)
57
+ value = 0;
58
+ if (value > 1)
59
+ value = 1;
60
+ this.outputGainNode.gain.value = value;
61
+ }
62
+ StopAll() {
63
+ this.audioClips.forEach(function (clip) {
64
+ clip.Stop();
65
+ });
66
+ }
67
+ Dispose() {
68
+ this.StopAll();
69
+ this.Unsend();
70
+ this.outputGainNode?.disconnect();
71
+ this.audioClips = [];
72
+ this.outputGainNode = null;
73
+ this.channel = null;
74
+ this.context = null;
75
+ }
28
76
  SetLabel(label) {
29
77
  this.label = label;
30
78
  }
79
+ get length() {
80
+ return this.audioClips.length;
81
+ }
82
+ get volume() {
83
+ return this.outputGainNode?.gain.value ?? 0;
84
+ }
31
85
  }
@@ -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(label?: string): 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,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO;CAGhD"}
@@ -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 {
@@ -12,6 +13,7 @@ export class AudioDevice {
12
13
  constructor(deviceInfo) {
13
14
  this.deviceInfo = deviceInfo;
14
15
  }
16
+ ;
15
17
  GetMasterChannel() {
16
18
  return this.masterChannel;
17
19
  }
@@ -31,4 +33,7 @@ export class AudioDevice {
31
33
  GetContext() {
32
34
  return this.context;
33
35
  }
36
+ CreateChannel(label) {
37
+ return new Channel(this.context, label);
38
+ }
34
39
  }
@@ -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;
14
- constructor(context: AudioContext);
15
+ sends: Channel[];
16
+ audioClipPlayer: AudioClipPlayer | null;
17
+ constructor(context: AudioContext, label?: string);
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;
@@ -19,6 +27,8 @@ export declare class Channel {
19
27
  Unsend(channel: Channel | Master): void;
20
28
  HasAudioClipPlayer(): boolean;
21
29
  UnsendToAllChannels(): void;
22
- AttachAudioClip(audioClip: AudioClip): void;
30
+ AttachAudioClip(audioClip: AudioClip): Channel;
31
+ Volume(volume?: number): number;
32
+ Pan(pan?: number): number;
23
33
  }
24
34
  //# sourceMappingURL=Channel.d.ts.map
@@ -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;AAGtC,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,EAAE,KAAK,CAAC,EAAE,MAAM;IAsBjD,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;IAQnB,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO;IAQ9C,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM;IAS/B,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM;CAQnC"}
@@ -2,6 +2,7 @@ import { v4 } from "uuid";
2
2
  import { Debug } from "../../utilities/debugger";
3
3
  import { AudioClipPlayer } from "./AudioClipPlayer";
4
4
  import { Master } from "./Master";
5
+ import { ErrorCodes } from "../../console-codes";
5
6
  export class Channel {
6
7
  id = v4();
7
8
  label = "Channel";
@@ -10,11 +11,13 @@ export class Channel {
10
11
  analyserNode = null;
11
12
  gainNode = null;
12
13
  output = null;
14
+ effects = [];
13
15
  context = null;
14
16
  sends = [];
15
17
  audioClipPlayer = null;
16
- constructor(context) {
18
+ constructor(context, label) {
17
19
  this.context = context;
20
+ this.label = label ?? this.label;
18
21
  this.disconnectAudioNodes(true);
19
22
  this.input = new GainNode(context);
20
23
  this.stereoPannerNode = new StereoPannerNode(context);
@@ -28,12 +31,78 @@ export class Channel {
28
31
  this.gainNode.connect(this.output);
29
32
  this.audioClipPlayer.Send(this);
30
33
  }
34
+ rebuildEffectChain() {
35
+ if (!this.input || !this.stereoPannerNode) {
36
+ Debug.Error("Could not rebuild effect chain because one or more required audio nodes are undefined.", [
37
+ `Channel id: ${this.id}.`,
38
+ `Input defined: ${!!this.input}.`,
39
+ `StereoPannerNode defined: ${!!this.stereoPannerNode}.`
40
+ ]);
41
+ return;
42
+ }
43
+ this.input.disconnect();
44
+ for (const effect of this.effects)
45
+ effect.audioWorkletNode?.disconnect();
46
+ const activeEffects = this.effects.filter(function (e) {
47
+ return !!e.audioWorkletNode;
48
+ });
49
+ if (activeEffects.length === 0) {
50
+ this.input.connect(this.stereoPannerNode);
51
+ return;
52
+ }
53
+ this.input.connect(activeEffects[0].audioWorkletNode);
54
+ for (let i = 0; i < activeEffects.length - 1; i++) {
55
+ const current = activeEffects[i].audioWorkletNode;
56
+ const next = activeEffects[i + 1].audioWorkletNode;
57
+ current.connect(next);
58
+ }
59
+ activeEffects[activeEffects.length - 1].audioWorkletNode.connect(this.stereoPannerNode);
60
+ }
61
+ AddEffect(effect) {
62
+ if (!this.context) {
63
+ Debug.Error("Could not add effect because this channel has no AudioContext.");
64
+ return;
65
+ }
66
+ if (this.effects.includes(effect)) {
67
+ Debug.Error("Could not add effect because it is already part of this channel", [
68
+ "Call .RemoveEffect([effect Effector]) before adding effect."
69
+ ], ErrorCodes.EFFECT_ALREADY_ATTACHED);
70
+ return;
71
+ }
72
+ this.effects.push(effect);
73
+ effect.InitializeOnAttachment(this.context);
74
+ this.rebuildEffectChain();
75
+ }
76
+ AttachEffect(effect) {
77
+ return this.AddEffect(effect);
78
+ }
79
+ RemoveEffect(effect) {
80
+ if (!this.effects.includes(effect)) {
81
+ Debug.Error("Could not remove effect, because it is not part of this channel.", [
82
+ "Call .AddEffect([effect Effector]) before removing effect."
83
+ ], ErrorCodes.EFFECT_NOT_FOUND);
84
+ return;
85
+ }
86
+ const self = this;
87
+ this.effects.forEach(function (_effect, index) {
88
+ if (effect.id === _effect.id)
89
+ self.effects.splice(index, 1);
90
+ });
91
+ effect.audioWorkletNode?.disconnect();
92
+ this.rebuildEffectChain();
93
+ }
94
+ DetachEffect(effect) {
95
+ return this.RemoveEffect(effect);
96
+ }
31
97
  disconnectAudioNodes(gc) {
32
98
  this.input?.disconnect();
33
99
  this.stereoPannerNode?.disconnect();
34
100
  this.analyserNode?.disconnect();
35
101
  this.gainNode?.disconnect();
36
102
  this.output?.disconnect();
103
+ for (const effect of this.effects) {
104
+ effect.audioWorkletNode?.disconnect();
105
+ }
37
106
  if (gc) {
38
107
  this.input = null;
39
108
  this.stereoPannerNode = null;
@@ -66,27 +135,27 @@ export class Channel {
66
135
  if (channel.id === this.id)
67
136
  return Debug.Error("Could not link channel to itself.", [
68
137
  `This channel id: ${this.id}`
69
- ]);
138
+ ], ErrorCodes.CHANNEL_CANNOT_LINK_TO_ITSELF);
70
139
  if (!this.isInitialized() || !channel.isInitialized())
71
140
  return Debug.Error("Could not link channels because one (or both) channels are not initialized.", [
72
141
  `This channel id: ${this.id} initialized: ${this.isInitialized()}`,
73
142
  `Target channel id: ${channel.id} initialized: ${channel.isInitialized()}`
74
- ]);
143
+ ], ErrorCodes.CHANNEL_NOT_INITIALIZED);
75
144
  if (this.context !== channel.context)
76
145
  return Debug.Error("Could not link channels because they do not share the same AudioContext.", [
77
146
  `This channel context: ${this.context ? "set" : "null"}`,
78
147
  `Target channel context: ${channel.context ? "set" : "null"}`
79
- ]);
148
+ ], ErrorCodes.CHANNEL_NOT_SAME_AUDIO_CONTEXT);
80
149
  if (this.sends.includes(channel))
81
150
  return Debug.Error("Could not link channels, because the given channel is already linked with this one.", [
82
151
  `This channel id: ${this.id}`,
83
152
  `Target channel id: ${channel.id}`
84
- ]);
153
+ ], ErrorCodes.CHANNEL_ALREADY_LINKED);
85
154
  if (channel.isReachable(this))
86
155
  return Debug.Error("Could not link channels because it would create a feedback loop.", [
87
156
  `This channel id: ${this.id}`,
88
157
  `Target channel id: ${channel.id}`
89
- ]);
158
+ ], ErrorCodes.CHANNEL_POSSIBLE_FEEDBACK_LOOP);
90
159
  this.output.connect(channel.input);
91
160
  this.sends.push(channel);
92
161
  }
@@ -111,7 +180,24 @@ export class Channel {
111
180
  }
112
181
  AttachAudioClip(audioClip) {
113
182
  if (!this.audioClipPlayer)
114
- return Debug.Error("Cannot not link AudioClip to this channel because this channel's AudioClipPlayer is undefined.");
183
+ throw Error("Cannot not link AudioClip to this channel because this channel's AudioClipPlayer is undefined.");
115
184
  this.audioClipPlayer.AttachAudioClip(audioClip);
185
+ return this;
186
+ }
187
+ Volume(volume) {
188
+ if (!this.context)
189
+ throw new Error("Could not set volume on channel, because it's context is undefined.");
190
+ if (!this.gainNode)
191
+ throw new Error("Could not set volume on channel, because it's GainNode is undefined.");
192
+ volume && this.gainNode.gain.setValueAtTime(volume, this.context.currentTime);
193
+ return volume ?? this.gainNode.gain.value;
194
+ }
195
+ Pan(pan) {
196
+ if (!this.context)
197
+ throw new Error("Could not set pan on channel, because it's context is undefined.");
198
+ if (!this.stereoPannerNode)
199
+ throw new Error("Cannot set pan on channel, because it's StereoPannerNode is undefined.");
200
+ pan && this.stereoPannerNode.pan.setValueAtTime(pan, this.context.currentTime);
201
+ return pan ?? this.stereoPannerNode.pan.value;
116
202
  }
117
203
  }
@@ -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}.