@fluex/fluexgl-dsp 0.3.5 → 0.4.0

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 (42) hide show
  1. package/lib/dist/core/classes/AudioClip.d.ts +10 -28
  2. package/lib/dist/core/classes/AudioClip.d.ts.map +1 -1
  3. package/lib/dist/core/classes/AudioClip.js +56 -192
  4. package/lib/dist/core/classes/AudioClipPlayer.d.ts +15 -0
  5. package/lib/dist/core/classes/AudioClipPlayer.d.ts.map +1 -0
  6. package/lib/dist/core/classes/AudioClipPlayer.js +31 -0
  7. package/lib/dist/core/classes/AudioDevice.d.ts +2 -0
  8. package/lib/dist/core/classes/AudioDevice.d.ts.map +1 -1
  9. package/lib/dist/core/classes/AudioDevice.js +6 -2
  10. package/lib/dist/core/classes/Channel.d.ts +16 -34
  11. package/lib/dist/core/classes/Channel.d.ts.map +1 -1
  12. package/lib/dist/core/classes/Channel.js +95 -190
  13. package/lib/dist/core/classes/DpsPipeline.js +2 -2
  14. package/lib/dist/core/classes/Master.d.ts +4 -4
  15. package/lib/dist/core/classes/Master.d.ts.map +1 -1
  16. package/lib/dist/core/classes/Master.js +11 -5
  17. package/lib/dist/core/exports.d.ts +1 -0
  18. package/lib/dist/core/exports.d.ts.map +1 -1
  19. package/lib/dist/core/exports.js +1 -0
  20. package/lib/dist/core/functions/rebuild-effect-chain.d.ts +3 -0
  21. package/lib/dist/core/functions/rebuild-effect-chain.d.ts.map +1 -0
  22. package/lib/dist/core/functions/rebuild-effect-chain.js +2 -0
  23. package/lib/dist/index.d.ts +2 -2
  24. package/lib/dist/index.d.ts.map +1 -1
  25. package/lib/dist/index.js +2 -2
  26. package/lib/dist/test/linkable-channels.d.ts +2 -0
  27. package/lib/dist/test/linkable-channels.d.ts.map +1 -0
  28. package/lib/dist/test/linkable-channels.js +16 -0
  29. package/lib/dist/utilities/helpers.d.ts +1 -2
  30. package/lib/dist/utilities/helpers.d.ts.map +1 -1
  31. package/lib/dist/utilities/helpers.js +5 -5
  32. package/lib/src/core/classes/AudioClip.ts +62 -236
  33. package/lib/src/core/classes/AudioClipPlayer.ts +45 -0
  34. package/lib/src/core/classes/AudioDevice.ts +12 -6
  35. package/lib/src/core/classes/Channel.ts +88 -221
  36. package/lib/src/core/classes/DpsPipeline.ts +2 -2
  37. package/lib/src/core/classes/Master.ts +24 -12
  38. package/lib/src/core/exports.ts +2 -1
  39. package/lib/src/core/functions/rebuild-effect-chain.ts +5 -0
  40. package/lib/src/index.ts +3 -2
  41. package/lib/src/utilities/helpers.ts +5 -5
  42. package/package.json +2 -1
@@ -1,9 +1,9 @@
1
- import { AudioClipAnalyserProperty, AudioClipAnalyserType, AudioClipEventMap, AudioSourceData } from "../../typings";
1
+ import { AudioClipEventMap, AudioSourceData } from "../../typings";
2
2
  import { Channel } from "./Channel";
3
+ import { AudioClipPlayer } from "./AudioClipPlayer";
3
4
  export declare class AudioClip {
4
5
  data: AudioSourceData;
5
6
  id: string;
6
- hasAttachedToChannel: boolean;
7
7
  label: string | null;
8
8
  loop: boolean;
9
9
  isPlaying: boolean;
@@ -12,18 +12,8 @@ export declare class AudioClip {
12
12
  progressUpdateSpeed: number;
13
13
  gainNode: GainNode | null;
14
14
  stereoPannerNode: StereoPannerNode | null;
15
- parentialAudioContext: AudioContext | null;
16
- parentialChannel: Channel | null;
17
- preAnalyser: AnalyserNode | null;
18
- postAnalyser: AnalyserNode | null;
19
- preAnalyserEnabled: boolean;
20
- postAnalyserEnabled: boolean;
21
- preAnalyserOptions: AnalyserOptions;
22
- postAnalyserOptions: AnalyserOptions;
23
- preAnalyserFloatArrayBuffer: Float32Array<ArrayBuffer>;
24
- postAnalyserFloatArrayBuffer: Float32Array<ArrayBuffer>;
25
- preAnalyserByteArrayBuffer: Uint8Array<ArrayBuffer>;
26
- postAnalyserByteArrayBuffer: Uint8Array<ArrayBuffer>;
15
+ context: AudioContext | null;
16
+ audioClipPlayer: AudioClipPlayer | null;
27
17
  private audioBufferSourceNodes;
28
18
  private maxAudioBufferSourceNodes;
29
19
  private progressInterval;
@@ -33,12 +23,12 @@ export declare class AudioClip {
33
23
  private connectSourcesTo;
34
24
  private safeDisconnect;
35
25
  private rebuildNodeChain;
36
- InitializeAudioClipOnAttaching(channel: Channel): AudioClip | null;
37
- Play(timestamp?: number, offset?: number): AudioClip | null;
38
- Seek(seconds: number): AudioClip | null;
26
+ Initialize(audioClipPlayer: AudioClipPlayer): void;
27
+ Play(timestamp?: number, offset?: number): void | this | null;
28
+ Seek(seconds: number): void | this;
39
29
  Stop(): AudioClip | null;
40
- SetVolume(volume: number): AudioClip | void;
41
- SetPanLevel(panLevel: number): AudioClip | void;
30
+ SetVolume(volume: number): AudioClip;
31
+ SetPanLevel(panLevel: number): AudioClip;
42
32
  Loop(loop?: boolean): AudioClip;
43
33
  SetMaxAudioBufferSourceNodes(value: number): AudioClip;
44
34
  DisconnectAllAudioBufferSourceNodes(): boolean;
@@ -47,15 +37,7 @@ export declare class AudioClip {
47
37
  RemoveEventListener<K extends keyof AudioClipEventMap>(event: K, cb: AudioClipEventMap[K]): AudioClip;
48
38
  ClearEventListeners(event?: keyof AudioClipEventMap): AudioClip;
49
39
  GetChannelData(channel?: number): Float32Array;
50
- EnablePreAnalyser(): boolean;
51
- DisablePreAnalyser(): boolean;
52
- EnablePostAnalyser(): boolean;
53
- DisablePostAnalyser(): boolean;
54
- SetPreAnalyserOptions(options: AnalyserOptions): void;
55
- SetPostAnalyserOptions(options: AnalyserOptions): void;
56
- SetAnalyserOption(analyserType: AudioClipAnalyserType, property: AudioClipAnalyserProperty, value: number): boolean;
57
- GetWaveformFloatData(analyserType: AudioClipAnalyserType): Float32Array | null;
58
- GetWaveformByteData(analyserType: AudioClipAnalyserType): Uint8Array | null;
40
+ Send(channel: Channel): void;
59
41
  get currentPlaybackTime(): number;
60
42
  get duration(): number;
61
43
  get volume(): number;
@@ -1 +1 @@
1
- {"version":3,"file":"AudioClip.d.ts","sourceRoot":"","sources":["../../../src/core/classes/AudioClip.ts"],"names":[],"mappings":"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"}
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"}
@@ -4,7 +4,6 @@ import { Debug } from "../../utilities/debugger";
4
4
  export class AudioClip {
5
5
  data;
6
6
  id = v4();
7
- hasAttachedToChannel = false;
8
7
  label = null;
9
8
  loop = false;
10
9
  isPlaying = false;
@@ -13,18 +12,8 @@ export class AudioClip {
13
12
  progressUpdateSpeed = 20;
14
13
  gainNode = null;
15
14
  stereoPannerNode = null;
16
- parentialAudioContext = null;
17
- parentialChannel = null;
18
- preAnalyser = null;
19
- postAnalyser = null;
20
- preAnalyserEnabled = false;
21
- postAnalyserEnabled = false;
22
- preAnalyserOptions = {};
23
- postAnalyserOptions = {};
24
- preAnalyserFloatArrayBuffer = new Float32Array();
25
- postAnalyserFloatArrayBuffer = new Float32Array();
26
- preAnalyserByteArrayBuffer = new Uint8Array();
27
- postAnalyserByteArrayBuffer = new Uint8Array();
15
+ context = null;
16
+ audioClipPlayer = null;
28
17
  audioBufferSourceNodes = [];
29
18
  maxAudioBufferSourceNodes = 1;
30
19
  progressInterval = 0;
@@ -34,11 +23,10 @@ export class AudioClip {
34
23
  constructor(data) {
35
24
  this.data = data;
36
25
  }
37
- // Private methods.
38
26
  createBufferSource() {
39
- if (!this.parentialAudioContext)
27
+ if (!this.context)
40
28
  return null;
41
- const context = this.parentialAudioContext;
29
+ const context = this.context;
42
30
  const bufferSource = context.createBufferSource();
43
31
  bufferSource.buffer = this.data.audioBuffer;
44
32
  bufferSource.loop = this.loop;
@@ -54,54 +42,35 @@ export class AudioClip {
54
42
  node?.disconnect();
55
43
  }
56
44
  rebuildNodeChain() {
57
- if (!this.parentialAudioContext || !this.gainNode || !this.stereoPannerNode || !this.parentialChannel || !this.parentialChannel.audioClipsInputGainNode) {
58
- Debug.Error("rebuildNodeChain: missing context or core nodes (gain/panner).");
45
+ if (!this.context || !this.gainNode || !this.stereoPannerNode || !this.audioClipPlayer || !this.audioClipPlayer.outputGainNode) {
46
+ Debug.Error("Failed to rebuild node chain, because some of the core AudioNodes are missing.");
59
47
  return false;
60
48
  }
61
- const destination = this.parentialChannel.audioClipsInputGainNode;
49
+ const destination = this.audioClipPlayer.outputGainNode;
62
50
  this.safeDisconnect(this.gainNode);
63
51
  this.safeDisconnect(this.stereoPannerNode);
64
- this.safeDisconnect(this.preAnalyser);
65
- this.safeDisconnect(this.postAnalyser);
66
- let entry = this.gainNode;
67
- if (this.preAnalyserEnabled && this.preAnalyser) {
68
- entry = this.preAnalyser;
69
- this.preAnalyser.connect(this.gainNode);
70
- }
71
52
  this.gainNode.connect(this.stereoPannerNode);
72
- if (this.postAnalyserEnabled && this.postAnalyser) {
73
- this.stereoPannerNode.connect(this.postAnalyser);
74
- this.postAnalyser.connect(destination);
75
- }
76
- else {
77
- this.stereoPannerNode.connect(destination);
78
- }
79
- this.connectSourcesTo(entry);
53
+ this.stereoPannerNode.connect(destination);
54
+ this.connectSourcesTo(this.gainNode);
80
55
  return true;
81
56
  }
82
- // Public methods
83
- InitializeAudioClipOnAttaching(channel) {
84
- if (!channel.parentialContext || !channel.audioClipsInputGainNode) {
85
- Debug.Error("Could not initialize audio clip on channel attachment, because channel it's master channel has not been defined.", [
86
- `Call .AttachChannel([channel<"${channel.id}"> Channel]) on the master channel.`
57
+ Initialize(audioClipPlayer) {
58
+ if (!audioClipPlayer.context)
59
+ return Debug.Error("Could not initialize AudioClip, because the AudioClipPlayer somehow has no audio context.", [
60
+ `AudioClipPlayer id: ${audioClipPlayer.id}`,
61
+ `AudioClip id: ${this.id}`
87
62
  ]);
88
- return null;
89
- }
90
- this.gainNode = new GainNode(channel.parentialContext);
91
- this.stereoPannerNode = new StereoPannerNode(channel.parentialContext);
92
- this.parentialAudioContext = channel.parentialContext;
93
- this.parentialChannel = channel;
94
- this.hasAttachedToChannel = true;
95
- return this;
63
+ this.audioClipPlayer = audioClipPlayer;
64
+ this.context = audioClipPlayer.context;
65
+ this.gainNode = new GainNode(this.context);
66
+ this.stereoPannerNode = new StereoPannerNode(this.context);
96
67
  }
97
68
  Play(timestamp, offset) {
98
- if (!this.hasAttachedToChannel || !this.parentialAudioContext || !this.parentialChannel) {
99
- Debug.Error("Could not play the audio node because it is not attached to a channel", [
100
- "Call 'AttachAudioClip([clip AudioClip])' on a channel, before playing this audio node."
69
+ if (!this.context)
70
+ return Debug.Error("Could not play audio clip, because context (AudioContext) is undefined.", [
71
+ "Make sure to attach this AudioClip to an AudioClipPlayer instance, before calling .Play on this AudioClip."
101
72
  ]);
102
- return this;
103
- }
104
- const context = this.parentialAudioContext;
73
+ const context = this.context;
105
74
  const self = this;
106
75
  if (this.audioBufferSourceNodes.length > this.maxAudioBufferSourceNodes - 1)
107
76
  return null;
@@ -148,12 +117,11 @@ export class AudioClip {
148
117
  return this;
149
118
  }
150
119
  Seek(seconds) {
151
- if (!this.parentialAudioContext || !this.hasAttachedToChannel) {
152
- Debug.Error("Could not seek because the clip is not attached to a channel.", [
153
- `Clip ID: ${this.id}`
120
+ if (!this.context)
121
+ return Debug.Error("Could not seek because the context (AudioContext) of this AudioClip is undefined.", [
122
+ `Make sure to attach this AudioClip to an AudioClipPlayer instance before calling .Seek on this AudioClip.`,
123
+ `AudioClip id: ${this.id}`
154
124
  ]);
155
- return null;
156
- }
157
125
  const clamped = Math.max(0, Math.min(seconds, this.duration));
158
126
  if (!this.isPlaying) {
159
127
  this.offsetAtStart = clamped;
@@ -164,12 +132,6 @@ export class AudioClip {
164
132
  return this;
165
133
  }
166
134
  Stop() {
167
- if (!this.hasAttachedToChannel || !this.parentialAudioContext) {
168
- Debug.Error("Could not stop the audio node because it is not attached to a channel", [
169
- "Call 'AttachAudioClip([node AudioNode])' on a channel, before stopping this audio node."
170
- ]);
171
- return null;
172
- }
173
135
  this.audioBufferSourceNodes.forEach(function (node) {
174
136
  node.stop();
175
137
  node.disconnect();
@@ -183,23 +145,32 @@ export class AudioClip {
183
145
  return this;
184
146
  }
185
147
  SetVolume(volume) {
186
- if (!this.gainNode || !this.parentialAudioContext)
187
- return Debug.Error("Something went wrong while setting the volume.", [
188
- `Gain node on audio clip '${this.id}' is undefined.`
148
+ if (!this.context)
149
+ Debug.Error("Could not set volume because the context (AudioContext) of this AudioClip is undefined.", [
150
+ "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.",
189
155
  ]);
190
- this.gainNode.gain.setValueAtTime(volume, this.parentialAudioContext.currentTime);
156
+ this.gainNode?.gain.setValueAtTime(volume, this.context?.currentTime ?? 0);
191
157
  return this;
192
158
  }
193
159
  SetPanLevel(panLevel) {
194
- if (!this.stereoPannerNode || !this.parentialAudioContext)
195
- return Debug.Error("Something went wrong while setting the pan level", [
196
- `Stereo panner node on audio clip '${this.id}' is undefined`
160
+ if (!this.context)
161
+ Debug.Error("Could not set volume because the context (AudioContext) of this AudioClip is undefined.", [
162
+ "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.",
197
167
  ]);
198
168
  if (panLevel < -1 || panLevel > 1)
199
- return Debug.Error("Could not set the pan level because it is not between -1 and 1.", [
200
- "Provide this method with a value between -1 and 1"
169
+ Debug.Error("Could not set the pan level because it is not between -1 and 1.", [
170
+ `Given value: ${panLevel}.`,
171
+ `Accepts a value between -1 and 1. Can be a floating number.`
201
172
  ]);
202
- this.stereoPannerNode.pan.setValueAtTime(panLevel, this.parentialAudioContext.currentTime);
173
+ this.stereoPannerNode?.pan.setValueAtTime(panLevel, this.context?.currentTime ?? 0);
203
174
  return this;
204
175
  }
205
176
  Loop(loop) {
@@ -217,9 +188,9 @@ export class AudioClip {
217
188
  return this;
218
189
  }
219
190
  DisconnectAllAudioBufferSourceNodes() {
220
- if (!this.parentialAudioContext)
191
+ if (!this.context)
221
192
  return false;
222
- const contextCurrentTime = this.parentialAudioContext?.currentTime;
193
+ const contextCurrentTime = this.context?.currentTime;
223
194
  this.audioBufferSourceNodes.forEach(function (node) {
224
195
  node.stop(contextCurrentTime);
225
196
  node.disconnect();
@@ -260,126 +231,19 @@ export class AudioClip {
260
231
  GetChannelData(channel = 0) {
261
232
  return this.data.audioBuffer.getChannelData(channel);
262
233
  }
263
- EnablePreAnalyser() {
264
- if (!this.parentialAudioContext || !this.parentialChannel || !this.hasAttachedToChannel) {
265
- Debug.Error("EnablePreAnalyser: clip niet aan channel gekoppeld.");
266
- return false;
267
- }
268
- if (!this.preAnalyser)
269
- this.preAnalyser = new AnalyserNode(this.parentialAudioContext, this.preAnalyserOptions);
270
- this.preAnalyserFloatArrayBuffer = new Float32Array(this.preAnalyser.fftSize);
271
- this.preAnalyserByteArrayBuffer = new Uint8Array(this.preAnalyser.fftSize);
272
- this.preAnalyserEnabled = true;
273
- return this.rebuildNodeChain();
274
- }
275
- DisablePreAnalyser() {
276
- this.preAnalyserEnabled = false;
277
- return this.rebuildNodeChain();
278
- }
279
- EnablePostAnalyser() {
280
- if (!this.parentialAudioContext || !this.parentialChannel || !this.hasAttachedToChannel) {
281
- Debug.Error("EnablePostAnalyser: clip niet aan channel gekoppeld.");
282
- return false;
283
- }
284
- if (!this.postAnalyser)
285
- this.postAnalyser = new AnalyserNode(this.parentialAudioContext, this.postAnalyserOptions);
286
- this.postAnalyserFloatArrayBuffer = new Float32Array(this.postAnalyser.fftSize);
287
- this.postAnalyserByteArrayBuffer = new Uint8Array(this.postAnalyser.fftSize);
288
- this.postAnalyserEnabled = true;
289
- return this.rebuildNodeChain();
290
- }
291
- DisablePostAnalyser() {
292
- this.postAnalyserEnabled = false;
293
- return this.rebuildNodeChain();
294
- }
295
- SetPreAnalyserOptions(options) {
296
- this.preAnalyserOptions = { ...options };
297
- if (!this.preAnalyser)
298
- return;
299
- this.preAnalyser.fftSize = options.fftSize ?? this.preAnalyser.fftSize;
300
- this.preAnalyser.minDecibels = options.minDecibels ?? this.preAnalyser.minDecibels;
301
- this.preAnalyser.maxDecibels = options.maxDecibels ?? this.preAnalyser.maxDecibels;
302
- this.preAnalyser.smoothingTimeConstant = options.smoothingTimeConstant ?? this.preAnalyser.smoothingTimeConstant;
303
- }
304
- SetPostAnalyserOptions(options) {
305
- this.postAnalyserOptions = { ...options };
306
- if (!this.postAnalyser)
307
- return;
308
- this.postAnalyser.fftSize = options.fftSize ?? this.postAnalyser.fftSize;
309
- this.postAnalyser.minDecibels = options.minDecibels ?? this.postAnalyser.minDecibels;
310
- this.postAnalyser.maxDecibels = options.maxDecibels ?? this.postAnalyser.maxDecibels;
311
- this.postAnalyser.smoothingTimeConstant = options.smoothingTimeConstant ?? this.postAnalyser.smoothingTimeConstant;
312
- }
313
- SetAnalyserOption(analyserType, property, value) {
314
- const node = analyserType === "pre" ? this.preAnalyser : this.postAnalyser;
315
- if (node)
316
- switch (property) {
317
- case "fftSize":
318
- node.fftSize = value;
319
- break;
320
- case "minDecibels":
321
- node.minDecibels = value;
322
- break;
323
- case "maxDecibels":
324
- node.maxDecibels = value;
325
- break;
326
- case "smoothingTimeConstant":
327
- node.smoothingTimeConstant = value;
328
- break;
329
- default: return false;
330
- }
331
- const opts = analyserType === "pre" ? this.preAnalyserOptions : this.postAnalyserOptions;
332
- switch (property) {
333
- case "fftSize":
334
- opts.fftSize = value;
335
- break;
336
- case "minDecibels":
337
- opts.minDecibels = value;
338
- break;
339
- case "maxDecibels":
340
- opts.maxDecibels = value;
341
- break;
342
- case "smoothingTimeConstant":
343
- opts.smoothingTimeConstant = value;
344
- break;
345
- default: return false;
346
- }
347
- return true;
348
- }
349
- GetWaveformFloatData(analyserType) {
350
- if (analyserType === "pre" && this.preAnalyser) {
351
- this.preAnalyser.getFloatTimeDomainData(this.preAnalyserFloatArrayBuffer);
352
- return this.preAnalyserFloatArrayBuffer;
353
- }
354
- else if (analyserType === "post" && this.postAnalyser) {
355
- this.postAnalyser.getFloatTimeDomainData(this.postAnalyserFloatArrayBuffer);
356
- return this.postAnalyserFloatArrayBuffer;
357
- }
358
- return null;
359
- }
360
- GetWaveformByteData(analyserType) {
361
- if (!this.preAnalyser || !this.postAnalyser) {
362
- Debug.Error("Could not get byte waveform data because the pre analyser or post analyser has not been enabled.", [
363
- "Call .EnablePreAnalyser() or .EnablePostAnalyser() before getting waveform data."
234
+ Send(channel) {
235
+ if (!channel.HasAudioClipPlayer())
236
+ return Debug.Error("Could not send AudioClip signal to channel, because the channel's AudioClipPlayer is undefined.", [
237
+ "Make sure to initialize the Channel.",
238
+ `Channel id: ${channel.id}.`,
239
+ `AudioClip id: ${this.id}.`
364
240
  ]);
365
- return null;
366
- }
367
- switch (analyserType) {
368
- case "pre":
369
- this.preAnalyser.getByteTimeDomainData(this.preAnalyserByteArrayBuffer);
370
- return this.preAnalyserByteArrayBuffer;
371
- case "post":
372
- this.postAnalyser.getByteTimeDomainData(this.postAnalyserByteArrayBuffer);
373
- return this.postAnalyserByteArrayBuffer;
374
- default:
375
- return null;
376
- }
241
+ channel.AttachAudioClip(this);
377
242
  }
378
- // Public getters and setters
379
243
  get currentPlaybackTime() {
380
- return (!this.isPlaying || !this.parentialAudioContext)
244
+ return (!this.isPlaying || !this.context)
381
245
  ? 0
382
- : this.offsetAtStart + (this.parentialAudioContext.currentTime - this.startTime);
246
+ : this.offsetAtStart + (this.context.currentTime - this.startTime);
383
247
  }
384
248
  get duration() {
385
249
  return this.data.audioBuffer.duration;
@@ -0,0 +1,15 @@
1
+ import { AudioClip } from "./AudioClip";
2
+ import { Channel } from "./Channel";
3
+ export declare class AudioClipPlayer {
4
+ label: string;
5
+ id: string;
6
+ audioClips: AudioClip[];
7
+ outputGainNode: GainNode | null;
8
+ context: AudioContext | null;
9
+ channel: Channel | null;
10
+ constructor(context: AudioContext);
11
+ AttachAudioClip(audioClip: AudioClip): void;
12
+ Send(channel: Channel): void;
13
+ SetLabel(label: string): void;
14
+ }
15
+ //# sourceMappingURL=AudioClipPlayer.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,31 @@
1
+ import { v4 } from "uuid";
2
+ import { Debug } from "../../utilities/debugger";
3
+ export class AudioClipPlayer {
4
+ label = "AudioClipPlayer";
5
+ id = v4();
6
+ audioClips = [];
7
+ outputGainNode = null;
8
+ context = null;
9
+ channel = null;
10
+ constructor(context) {
11
+ this.context = context;
12
+ this.outputGainNode = new GainNode(context);
13
+ }
14
+ AttachAudioClip(audioClip) {
15
+ if (this.audioClips.includes(audioClip))
16
+ return Debug.Error("Could not attach audio clip because it is already part of this channel", [
17
+ "Call .DetachAudioClip([clip AudioClip]) before attaching audio clip."
18
+ ]);
19
+ audioClip.Initialize(this);
20
+ this.audioClips.push(audioClip);
21
+ }
22
+ Send(channel) {
23
+ if (!this.outputGainNode || !channel.input)
24
+ return Debug.Error("Could not send AudioClipPlayer signal to a channel.");
25
+ this.channel = channel;
26
+ this.outputGainNode.connect(channel.input);
27
+ }
28
+ SetLabel(label) {
29
+ this.label = label;
30
+ }
31
+ }
@@ -3,11 +3,13 @@ export declare class AudioDevice {
3
3
  deviceInfo: MediaDeviceInfo;
4
4
  id: string;
5
5
  timestamp: number;
6
+ context: AudioContext;
6
7
  masterChannel: Master;
7
8
  masterChannels: Master[];
8
9
  constructor(deviceInfo: MediaDeviceInfo);
9
10
  GetMasterChannel(): Master;
10
11
  SetMasterChannel(channel: Master): void;
11
12
  CreateMasterChannel(): Master;
13
+ GetContext(): AudioContext;
12
14
  }
13
15
  //# 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;IAQD,UAAU,EAAE,eAAe;IANvC,EAAE,EAAE,MAAM,CAAQ;IAClB,SAAS,EAAE,MAAM,CAAc;IAE/B,aAAa,EAAE,MAAM,CAAgB;IACrC,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;CAOvC"}
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"}
@@ -6,7 +6,8 @@ export class AudioDevice {
6
6
  deviceInfo;
7
7
  id = v4();
8
8
  timestamp = Date.now();
9
- masterChannel = new Master();
9
+ context = new AudioContext();
10
+ masterChannel = new Master(this.context);
10
11
  masterChannels = [];
11
12
  constructor(deviceInfo) {
12
13
  this.deviceInfo = deviceInfo;
@@ -23,8 +24,11 @@ export class AudioDevice {
23
24
  this.masterChannel = channel;
24
25
  }
25
26
  CreateMasterChannel() {
26
- const master = new Master();
27
+ const master = new Master(this.context);
27
28
  this.masterChannels.push(master);
28
29
  return master;
29
30
  }
31
+ GetContext() {
32
+ return this.context;
33
+ }
30
34
  }
@@ -1,42 +1,24 @@
1
- import { Effector } from "./Effector";
2
1
  import { AudioClip } from "./AudioClip";
3
2
  import { Master } from "./Master";
4
- import { ChannelOptions } from "../../typings";
5
3
  export declare class Channel {
6
- options: Partial<ChannelOptions>;
7
4
  id: string;
8
- effects: Effector[];
9
- label: string | null;
10
- parentialContext: AudioContext | null;
11
- parentialMasterChannel: Master | null;
12
- audioClips: AudioClip[];
13
- gainNode: GainNode | null;
5
+ label: string;
6
+ input: AudioNode | null;
14
7
  stereoPannerNode: StereoPannerNode | null;
15
8
  analyserNode: AnalyserNode | null;
16
- channelSplitterNode: ChannelSplitterNode | null;
17
- analyserFloatArrayBuffer: Float32Array<ArrayBuffer>;
18
- analyserByteArrayBuffer: Uint8Array<ArrayBuffer>;
19
- audioClipsInputGainNode: GainNode | null;
20
- analyserOptions: AnalyserOptions;
21
- constructor(options?: Partial<ChannelOptions>);
22
- private rebuildEffectChain;
23
- InitializeChannelOnMasterAttachment(master: Master): void;
24
- SetLabel(label: string): void;
25
- ClearLabel(): void;
26
- AttachAudioClip(clip: AudioClip): void;
27
- DetachAudioClip(clip: AudioClip): void;
28
- HasAudioClip(clip: AudioClip): boolean;
29
- SetVolume(volume: number): void;
30
- SetPanLevel(pan: number): void;
31
- AddEffect(effect: Effector): void;
32
- AttachEffect(effect: Effector): void;
33
- RemoveEffect(effect: Effector): void;
34
- DetachEffect(effect: Effector): void;
35
- SetAnalyserFftSize(value: number): number | null;
36
- GetWaveformFloatData(): Float32Array | null;
37
- GetWaveformByteData(): Uint8Array | null;
38
- SetAnalyserOptions(options: AnalyserOptions): Channel | null;
39
- get volume(): number | null;
40
- get panLevel(): number | null;
9
+ gainNode: GainNode | null;
10
+ output: AudioNode | null;
11
+ context: AudioContext | null;
12
+ private sends;
13
+ private audioClipPlayer;
14
+ constructor(context: AudioContext);
15
+ private disconnectAudioNodes;
16
+ private isInitialized;
17
+ private isReachable;
18
+ Send(channel: Channel | Master): void;
19
+ Unsend(channel: Channel | Master): void;
20
+ HasAudioClipPlayer(): boolean;
21
+ UnsendToAllChannels(): void;
22
+ AttachAudioClip(audioClip: AudioClip): void;
41
23
  }
42
24
  //# sourceMappingURL=Channel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Channel.d.ts","sourceRoot":"","sources":["../../../src/core/classes/Channel.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,qBAAa,OAAO;IAuBG,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC;IArB5C,EAAE,EAAE,MAAM,CAAQ;IAClB,OAAO,EAAE,QAAQ,EAAE,CAAM;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAErB,gBAAgB,EAAE,YAAY,GAAG,IAAI,CAAQ;IAC7C,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE7C,UAAU,EAAE,SAAS,EAAE,CAAM;IAE7B,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IACjC,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IACjD,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IACzC,mBAAmB,EAAE,mBAAmB,GAAG,IAAI,CAAQ;IAEvD,wBAAwB,4BAAsB;IAC9C,uBAAuB,0BAAoB;IAE3C,uBAAuB,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAEhD,eAAe,EAAE,eAAe,CAAmB;gBAEvC,OAAO,GAAE,OAAO,CAAC,cAAc,CAAuC;IAIzF,OAAO,CAAC,kBAAkB;IA2CnB,mCAAmC,CAAC,MAAM,EAAE,MAAM;IAoBlD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM7B,UAAU,IAAI,IAAI;IAMlB,eAAe,CAAC,IAAI,EAAE,SAAS;IAU/B,eAAe,CAAC,IAAI,EAAE,SAAS;IAuB/B,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO;IAStC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAS/B,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAS9B,SAAS,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAkBjC,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAIpC,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAgBpC,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAIpC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAehD,oBAAoB,IAAI,YAAY,GAAG,IAAI;IAe3C,mBAAmB,IAAI,UAAU,GAAG,IAAI;IAexC,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,GAAG,IAAI;IAmBnE,IAAW,MAAM,IAAI,MAAM,GAAG,IAAI,CAIjC;IAED,IAAW,QAAQ,IAAI,MAAM,GAAG,IAAI,CAInC;CACJ"}
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"}