@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,212 +1,117 @@
1
1
  import { v4 } from "uuid";
2
2
  import { Debug } from "../../utilities/debugger";
3
+ import { AudioClipPlayer } from "./AudioClipPlayer";
4
+ import { Master } from "./Master";
3
5
  export class Channel {
4
- options;
5
6
  id = v4();
6
- effects = [];
7
- label;
8
- parentialContext = null;
9
- parentialMasterChannel = null;
10
- audioClips = [];
11
- gainNode = null;
7
+ label = "Channel";
8
+ input = null;
12
9
  stereoPannerNode = null;
13
10
  analyserNode = null;
14
- channelSplitterNode = null;
15
- analyserFloatArrayBuffer = new Float32Array();
16
- analyserByteArrayBuffer = new Uint8Array();
17
- audioClipsInputGainNode = null;
18
- analyserOptions = { fftSize: 32 };
19
- constructor(options = { maxAudioNodes: 8, maxEffects: 8 }) {
20
- this.options = options;
21
- this.label = options.label ?? null;
22
- }
23
- rebuildEffectChain() {
24
- Debug.Log("Attempting to rebuild effect chain.");
25
- if (!this.audioClipsInputGainNode || !this.stereoPannerNode) {
26
- return Debug.Error("Could not rebuild effect chain, because one or more nodes on this channel are undefined.", [
27
- `Channel id: ${this.id}.`,
28
- `Current amount of effects: ${this.effects.length}.`
29
- ]);
30
- }
31
- this.audioClipsInputGainNode.disconnect();
32
- for (const effect of this.effects) {
33
- effect.audioWorkletNode?.disconnect();
34
- }
35
- const activeEffects = this.effects.filter(function (e) {
36
- return !!e.audioWorkletNode;
37
- });
38
- if (activeEffects.length === 0) {
39
- this.audioClipsInputGainNode.connect(this.stereoPannerNode);
40
- }
41
- else {
42
- this.audioClipsInputGainNode.connect(activeEffects[0].audioWorkletNode);
43
- for (let i = 0; i < activeEffects.length - 1; i++) {
44
- const current = activeEffects[i].audioWorkletNode;
45
- const next = activeEffects[i + 1].audioWorkletNode;
46
- current.connect(next);
47
- }
48
- const lastEffectNode = activeEffects[activeEffects.length - 1].audioWorkletNode;
49
- lastEffectNode.connect(this.stereoPannerNode);
11
+ gainNode = null;
12
+ output = null;
13
+ context = null;
14
+ sends = [];
15
+ audioClipPlayer = null;
16
+ constructor(context) {
17
+ this.context = context;
18
+ this.disconnectAudioNodes(true);
19
+ this.input = new GainNode(context);
20
+ this.stereoPannerNode = new StereoPannerNode(context);
21
+ this.analyserNode = new AnalyserNode(context);
22
+ this.gainNode = new GainNode(context);
23
+ this.output = new GainNode(context);
24
+ this.audioClipPlayer = new AudioClipPlayer(context);
25
+ this.input.connect(this.stereoPannerNode);
26
+ this.stereoPannerNode.connect(this.analyserNode);
27
+ this.analyserNode.connect(this.gainNode);
28
+ this.gainNode.connect(this.output);
29
+ this.audioClipPlayer.Send(this);
30
+ }
31
+ disconnectAudioNodes(gc) {
32
+ this.input?.disconnect();
33
+ this.stereoPannerNode?.disconnect();
34
+ this.analyserNode?.disconnect();
35
+ this.gainNode?.disconnect();
36
+ this.output?.disconnect();
37
+ if (gc) {
38
+ this.input = null;
39
+ this.stereoPannerNode = null;
40
+ this.analyserNode = null;
41
+ this.gainNode = null;
42
+ this.output = null;
50
43
  }
51
- Debug.Success("Successfully rebuilt effect chain.", [
52
- `Channel id: ${this.id}.`,
53
- `Current amount of effects: ${this.effects.length}`
54
- ]);
55
44
  }
56
- InitializeChannelOnMasterAttachment(master) {
57
- this.parentialMasterChannel = master;
58
- this.parentialContext = master.context;
59
- this.gainNode = new GainNode(this.parentialContext);
60
- this.stereoPannerNode = new StereoPannerNode(this.parentialContext);
61
- this.analyserNode = new AnalyserNode(this.parentialContext, this.analyserOptions);
62
- this.analyserFloatArrayBuffer = new Float32Array(this.analyserNode.fftSize);
63
- this.analyserByteArrayBuffer = new Uint8Array(this.analyserNode.fftSize);
64
- this.audioClipsInputGainNode = new GainNode(this.parentialContext);
65
- this.audioClipsInputGainNode.connect(this.stereoPannerNode);
66
- this.stereoPannerNode.connect(this.gainNode);
67
- this.gainNode.connect(this.analyserNode);
68
- this.analyserNode.connect(this.parentialMasterChannel.gainNode);
45
+ isInitialized() {
46
+ return !!(this.context && this.input && this.output);
69
47
  }
70
- SetLabel(label) {
71
- this.options.label = label;
72
- this.label = label;
73
- }
74
- ClearLabel() {
75
- this.options.label = "";
76
- this.label = null;
77
- }
78
- AttachAudioClip(clip) {
79
- if (this.audioClips.includes(clip))
80
- return Debug.Error("Could not attach audio clip because it is already part of this channel", [
81
- "Call .DetachAudioClip([clip AudioClip]) before attaching audio clip."
82
- ]);
83
- clip.InitializeAudioClipOnAttaching(this);
84
- this.audioClips.push(clip);
85
- }
86
- DetachAudioClip(clip) {
87
- if (!this.audioClips.includes(clip))
88
- return Debug.Error("Could not detach audio clip, because it is not part of this channel.", [
89
- "Call .AttachAudioClip([clip AudioClip]) before deattaching audio clip."
90
- ]);
91
- const self = this;
92
- clip.parentialAudioContext = null;
93
- clip.parentialChannel = null;
94
- clip.hasAttachedToChannel = false;
95
- clip.stereoPannerNode?.disconnect();
96
- clip.gainNode?.disconnect();
97
- clip.DisconnectAllAudioBufferSourceNodes();
98
- this.audioClips.forEach(function (_clip, index) {
99
- if (clip.id === _clip.id)
100
- return self.audioClips.splice(index, 1);
101
- });
102
- }
103
- HasAudioClip(clip) {
104
- for (let _clip of this.audioClips) {
105
- if (_clip.id === clip.id)
48
+ isReachable(target) {
49
+ const visited = new Set();
50
+ const stack = [this];
51
+ while (stack.length > 0) {
52
+ const current = stack.pop();
53
+ if (current.id === target.id)
106
54
  return true;
55
+ if (visited.has(current.id))
56
+ continue;
57
+ visited.add(current.id);
58
+ for (let i = 0; i < current.sends.length; i++)
59
+ stack.push(current.sends[i]);
107
60
  }
108
61
  return false;
109
62
  }
110
- SetVolume(volume) {
111
- if (!this.gainNode)
112
- return Debug.Error("Could not set channel volume because the channel is not attached to a master channel.", [
113
- "Attach the channel to a master channel before setting the volume."
63
+ Send(channel) {
64
+ if (channel instanceof Master)
65
+ return channel.AttachChannel(this);
66
+ if (channel.id === this.id)
67
+ return Debug.Error("Could not link channel to itself.", [
68
+ `This channel id: ${this.id}`
114
69
  ]);
115
- this.gainNode.gain.setValueAtTime(volume, this.parentialContext.currentTime);
116
- }
117
- SetPanLevel(pan) {
118
- if (!this.stereoPannerNode)
119
- return Debug.Error("Could not set channel pan level because the channel is not attached to a master channel.", [
120
- "Attach the channel to a master channel before setting the pan level."
70
+ if (!this.isInitialized() || !channel.isInitialized())
71
+ return Debug.Error("Could not link channels because one (or both) channels are not initialized.", [
72
+ `This channel id: ${this.id} initialized: ${this.isInitialized()}`,
73
+ `Target channel id: ${channel.id} initialized: ${channel.isInitialized()}`
121
74
  ]);
122
- this.stereoPannerNode.pan.setValueAtTime(pan, this.parentialContext.currentTime);
123
- }
124
- AddEffect(effect) {
125
- if (!this.parentialContext)
126
- return Debug.Error("Could not add effect on channel, because the parential context is undefined.", [
127
- `Channel ID: ${this.id}`,
128
- `Effect ID: ${effect.id}`,
129
- `Effect name: ${effect.constructor.name}`
75
+ if (this.context !== channel.context)
76
+ return Debug.Error("Could not link channels because they do not share the same AudioContext.", [
77
+ `This channel context: ${this.context ? "set" : "null"}`,
78
+ `Target channel context: ${channel.context ? "set" : "null"}`
130
79
  ]);
131
- if (this.effects.includes(effect))
132
- return Debug.Error("Could not add effect because it is already part of this channel", [
133
- "Call .RemoveEffect([effect Effector]) before adding effect."
80
+ if (this.sends.includes(channel))
81
+ return Debug.Error("Could not link channels, because the given channel is already linked with this one.", [
82
+ `This channel id: ${this.id}`,
83
+ `Target channel id: ${channel.id}`
134
84
  ]);
135
- effect.InitializeOnAttachment(this.parentialContext);
136
- this.effects.push(effect);
137
- this.rebuildEffectChain();
138
- }
139
- AttachEffect(effect) {
140
- return this.AddEffect(effect);
141
- }
142
- RemoveEffect(effect) {
143
- if (!this.effects.includes(effect))
144
- return Debug.Error("Could not remove effect, because it is not part of this channel.", [
145
- "Call .AddEffect([effect Effector]) before removing effect."
85
+ if (channel.isReachable(this))
86
+ return Debug.Error("Could not link channels because it would create a feedback loop.", [
87
+ `This channel id: ${this.id}`,
88
+ `Target channel id: ${channel.id}`
146
89
  ]);
147
- const self = this;
148
- this.effects.forEach(function (_effect, index) {
149
- if (effect.id === _effect.id)
150
- return self.effects.splice(index, 1);
151
- });
152
- this.rebuildEffectChain();
153
- }
154
- DetachEffect(effect) {
155
- return this.RemoveEffect(effect);
156
- }
157
- SetAnalyserFftSize(value) {
158
- if (!this.analyserNode) {
159
- Debug.Error("Could not set FFT size on analyser because the analyser has not been defined.");
160
- return null;
161
- }
162
- this.analyserNode.fftSize = value;
163
- this.analyserFloatArrayBuffer = new Float32Array(this.analyserNode.fftSize);
164
- this.analyserByteArrayBuffer = new Uint8Array(this.analyserNode.fftSize);
165
- return this.analyserNode.fftSize;
166
- }
167
- GetWaveformFloatData() {
168
- if (!this.analyserNode) {
169
- Debug.Error("Could not get waveform float data, because the analyser has not been defined.");
170
- return null;
90
+ this.output.connect(channel.input);
91
+ this.sends.push(channel);
92
+ }
93
+ Unsend(channel) {
94
+ if (channel instanceof Master)
95
+ return channel.DetachChannel(this);
96
+ const idx = this.sends.indexOf(channel);
97
+ if (idx === -1)
98
+ return;
99
+ if (this.output && channel.input)
100
+ this.output.disconnect(channel.input);
101
+ this.sends.splice(idx, 1);
102
+ }
103
+ HasAudioClipPlayer() {
104
+ return !!this.audioClipPlayer;
105
+ }
106
+ UnsendToAllChannels() {
107
+ for (var i = 0; i < this.sends.length; i++) {
108
+ this.Unsend(this.sends[i]);
109
+ i--;
171
110
  }
172
- if (this.analyserFloatArrayBuffer.length !== this.analyserNode.fftSize) {
173
- this.analyserFloatArrayBuffer = new Float32Array(this.analyserNode.fftSize);
174
- }
175
- this.analyserNode.getFloatTimeDomainData(this.analyserFloatArrayBuffer);
176
- return this.analyserFloatArrayBuffer;
177
- }
178
- GetWaveformByteData() {
179
- if (!this.analyserNode) {
180
- Debug.Error("Could not get waveform byte data, because the analyser has not been defined.");
181
- return null;
182
- }
183
- if (this.analyserByteArrayBuffer.length !== this.analyserNode.fftSize) {
184
- this.analyserByteArrayBuffer = new Uint8Array(this.analyserNode.fftSize);
185
- }
186
- this.analyserNode.getByteTimeDomainData(this.analyserByteArrayBuffer);
187
- return this.analyserByteArrayBuffer;
188
- }
189
- SetAnalyserOptions(options) {
190
- this.analyserOptions = { ...options };
191
- if (!this.analyserNode)
192
- return null;
193
- this.analyserNode.minDecibels = options.minDecibels ?? this.analyserNode.minDecibels;
194
- this.analyserNode.maxDecibels = options.maxDecibels ?? this.analyserNode.maxDecibels;
195
- this.analyserNode.fftSize = options.fftSize ?? 32;
196
- this.analyserNode.smoothingTimeConstant = options.smoothingTimeConstant ?? this.analyserNode.smoothingTimeConstant;
197
- this.analyserByteArrayBuffer = new Uint8Array(this.analyserNode.fftSize);
198
- this.analyserFloatArrayBuffer = new Float32Array(this.analyserNode.fftSize);
199
- return this;
200
- }
201
- // Public getters and setters
202
- get volume() {
203
- if (!this.gainNode)
204
- return null;
205
- return this.gainNode.gain.value;
206
111
  }
207
- get panLevel() {
208
- if (!this.stereoPannerNode)
209
- return null;
210
- return this.stereoPannerNode.pan.value;
112
+ AttachAudioClip(audioClip) {
113
+ if (!this.audioClipPlayer)
114
+ return Debug.Error("Cannot not link AudioClip to this channel because this channel's AudioClipPlayer is undefined.");
115
+ this.audioClipPlayer.AttachAudioClip(audioClip);
211
116
  }
212
117
  }
@@ -2,7 +2,7 @@ import { v4 } from "uuid";
2
2
  import { AudioDevice } from "./AudioDevice";
3
3
  import { Debug } from "../../utilities/debugger";
4
4
  import { LoadWebAssemblyModule } from "../../utilities/web-assembly";
5
- import { ConstructProcessorWorklet, LoadWorkletOnMasterChannel } from "../../utilities/helpers";
5
+ import { ConstructProcessorWorklet, LoadWorkletOnAudioDevice } from "../../utilities/helpers";
6
6
  import { ErrorCodes, WarningCodes } from "../../console-codes";
7
7
  /**
8
8
  * Represents the digital signal processing (DSP) pipeline responsible for initializing
@@ -106,7 +106,7 @@ export class DspPipeline {
106
106
  const defaultAudioDevice = devices.length === 0 ? null : new AudioDevice(audioDeviceInfos[0]);
107
107
  if (!defaultAudioDevice)
108
108
  return null;
109
- await LoadWorkletOnMasterChannel(defaultAudioDevice.masterChannel, this.blobUrl);
109
+ await LoadWorkletOnAudioDevice(defaultAudioDevice, this.blobUrl);
110
110
  return defaultAudioDevice;
111
111
  }
112
112
  TellMeWhatTheFuckThisWholeLibraryActuallyDoes() {
@@ -2,10 +2,10 @@ import { Channel } from "./Channel";
2
2
  export declare class Master {
3
3
  id: string;
4
4
  channels: Channel[];
5
- context: AudioContext;
6
- gainNode: GainNode;
7
- analyserNode: AnalyserNode;
8
- constructor();
5
+ gainNode: GainNode | null;
6
+ analyserNode: AnalyserNode | null;
7
+ context: AudioContext | null;
8
+ constructor(context: AudioContext);
9
9
  AttachChannel(channel: Channel): void;
10
10
  DetachChannel(channel: Channel): void;
11
11
  }
@@ -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;AAIpC,qBAAa,MAAM;IAER,EAAE,EAAE,MAAM,CAAQ;IAClB,QAAQ,EAAE,OAAO,EAAE,CAAM;IACzB,OAAO,EAAE,YAAY,CAAsB;IAE3C,QAAQ,EAAE,QAAQ,CAA6B;IAC/C,YAAY,EAAE,YAAY,CAAiC;;IAQ3D,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAYrC,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAgB/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;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"}
@@ -3,10 +3,13 @@ import { Debug } from "../../utilities/debugger";
3
3
  export class Master {
4
4
  id = v4();
5
5
  channels = [];
6
- context = new AudioContext();
7
- gainNode = this.context.createGain();
8
- analyserNode = this.context.createAnalyser();
9
- constructor() {
6
+ gainNode = null;
7
+ analyserNode = null;
8
+ context = null;
9
+ constructor(context) {
10
+ this.context = context;
11
+ this.gainNode = new GainNode(context);
12
+ this.analyserNode = new AnalyserNode(context);
10
13
  this.gainNode.connect(this.analyserNode);
11
14
  this.analyserNode.connect(this.context.destination);
12
15
  }
@@ -15,8 +18,9 @@ export class Master {
15
18
  return Debug.Error("Could not attach the channel because it is already part of this master channel.", [
16
19
  "Call .DetachChannel([channel Channel]) before attaching the channel."
17
20
  ]);
18
- channel.InitializeChannelOnMasterAttachment(this);
19
21
  this.channels.push(channel);
22
+ if (channel.output && this.gainNode)
23
+ channel.output.connect(this.gainNode);
20
24
  return;
21
25
  }
22
26
  DetachChannel(channel) {
@@ -24,6 +28,8 @@ export class Master {
24
28
  return Debug.Error("Could not detach the channel because it is not part of this master channel.", [
25
29
  "Call .AttachChannel([channel Channel]) before detaching the channel."
26
30
  ]);
31
+ if (channel.output && this.gainNode)
32
+ channel.output.disconnect(this.gainNode);
27
33
  const self = this;
28
34
  this.channels.forEach(function (_channel, index) {
29
35
  if (channel.id === _channel.id) {
@@ -4,4 +4,5 @@ export { Effector } from "./classes/Effector";
4
4
  export { Master } from "./classes/Master";
5
5
  export { AudioClip } from "./classes/AudioClip";
6
6
  export { DspPipeline } from "./classes/DpsPipeline";
7
+ export { AudioClipPlayer } from "./classes/AudioClipPlayer";
7
8
  //# sourceMappingURL=exports.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../../src/core/exports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../../src/core/exports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC"}
@@ -4,3 +4,4 @@ export { Effector } from "./classes/Effector";
4
4
  export { Master } from "./classes/Master";
5
5
  export { AudioClip } from "./classes/AudioClip";
6
6
  export { DspPipeline } from "./classes/DpsPipeline";
7
+ export { AudioClipPlayer } from "./classes/AudioClipPlayer";
@@ -0,0 +1,3 @@
1
+ import { Channel } from "../classes/Channel";
2
+ export declare function rebuildEffectChain(channel: Channel): void;
3
+ //# sourceMappingURL=rebuild-effect-chain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rebuild-effect-chain.d.ts","sourceRoot":"","sources":["../../../src/core/functions/rebuild-effect-chain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,QAElD"}
@@ -0,0 +1,2 @@
1
+ export function rebuildEffectChain(channel) {
2
+ }
@@ -5,8 +5,8 @@
5
5
  import { FluexGLAudioDescriptor } from "./typings";
6
6
  export declare const FluexGLAudio: FluexGLAudioDescriptor;
7
7
  export { Chorus, Distortion, Equalizer, Limiter, Saturation, StereoPanner, Compressor, MultibandCompressor, AdvancedDelay, MonoDelay, PingPongDelay, StereoDelay, ChamberReverb, ConvolverReverb, GenericReverb, HallReverb, RoomReverb, SoftClip, LowPassFilter, HardClip } from "./effects/exports";
8
- export { AudioDevice, Channel, Effector, Master, AudioClip, DspPipeline } from "./core/exports";
9
- export { InitializeDspPipeline, ResolveAudioOutputDevices, ResolveAudioInputDevices, ResolveDefaultAudioInputDevice, ResolveDefaultAudioOutputDevice, LoadAudioSource, LoadAudioSourceFromBlob, LoadWorkletOnMasterChannel, SendMessageToWorklet } from "./utilities/helpers";
8
+ export { AudioDevice, Channel, Effector, Master, AudioClip, DspPipeline, AudioClipPlayer } from "./core/exports";
9
+ export { InitializeDspPipeline, ResolveAudioOutputDevices, ResolveAudioInputDevices, ResolveDefaultAudioInputDevice, ResolveDefaultAudioOutputDevice, LoadAudioSource, LoadAudioSourceFromBlob, LoadWorkletOnAudioDevice, SendMessageToWorklet } from "./utilities/helpers";
10
10
  export { SUPPORTED_FILE_TYPES } from "./utilities/constants";
11
11
  export { hasInitializedWasm, } from "./utilities/web-assembly";
12
12
  export type { FluexGLAudioDescriptor, FluexGLAudioDebuggerOptions, FluexGLAudioOptions, LoadAudioSourceOptions, AudioSourceData, ChannelOptions, ChannelSpatialization, AudioClipEventMap, AudioClipEvents, AudioClipOnProgressEvent, AudioClipAnalyserProperty, AudioClipAnalyserType, DspPipelineInitializationOptions, DspPipelineInitializationState, ChorusEffectOptions, LowPassFilterOptions, LowPassFilterMessageCommandId, ChorusMessageCommandId, AudioWorkletProcessorNames, SoftClipMessageCommandId, SoftClipOptions, HardClipMessageCommandId, HardClipOptions, EffectorEventMap, IncomingMessageType, IncomingProcessorMessage, ProcessorData, ProcessorIdentificationCodes, EffectorEvents } from "./typings";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAEnD,eAAO,MAAM,YAAY,EAAE,sBAkB1B,CAAA;AAED,OAAO,EACH,MAAM,EACN,UAAU,EACV,SAAS,EACT,OAAO,EACP,UAAU,EACV,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,aAAa,EACb,WAAW,EACX,aAAa,EACb,eAAe,EACf,aAAa,EACb,UAAU,EACV,UAAU,EACV,QAAQ,EACR,aAAa,EACb,QAAQ,EACX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACH,WAAW,EACX,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAS,EACT,WAAW,EACd,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACH,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,EACxB,8BAA8B,EAC9B,+BAA+B,EAC/B,eAAe,EACf,uBAAuB,EACvB,0BAA0B,EAC1B,oBAAoB,EACvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACH,oBAAoB,EACvB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACH,kBAAkB,GACrB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EACR,sBAAsB,EACtB,2BAA2B,EAC3B,mBAAmB,EACnB,sBAAsB,EACtB,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,wBAAwB,EACxB,yBAAyB,EACzB,qBAAqB,EACrB,gCAAgC,EAChC,8BAA8B,EAC9B,mBAAmB,EACnB,oBAAoB,EACpB,6BAA6B,EAC7B,sBAAsB,EACtB,0BAA0B,EAC1B,wBAAwB,EACxB,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EACxB,aAAa,EACb,4BAA4B,EAC5B,cAAc,EACjB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAEnD,eAAO,MAAM,YAAY,EAAE,sBAkB1B,CAAA;AAED,OAAO,EACH,MAAM,EACN,UAAU,EACV,SAAS,EACT,OAAO,EACP,UAAU,EACV,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,aAAa,EACb,WAAW,EACX,aAAa,EACb,eAAe,EACf,aAAa,EACb,UAAU,EACV,UAAU,EACV,QAAQ,EACR,aAAa,EACb,QAAQ,EACX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACH,WAAW,EACX,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAS,EACT,WAAW,EACX,eAAe,EAClB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACH,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,EACxB,8BAA8B,EAC9B,+BAA+B,EAC/B,eAAe,EACf,uBAAuB,EACvB,wBAAwB,EACxB,oBAAoB,EACvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACH,oBAAoB,EACvB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACH,kBAAkB,GACrB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EACR,sBAAsB,EACtB,2BAA2B,EAC3B,mBAAmB,EACnB,sBAAsB,EACtB,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,wBAAwB,EACxB,yBAAyB,EACzB,qBAAqB,EACrB,gCAAgC,EAChC,8BAA8B,EAC9B,mBAAmB,EACnB,oBAAoB,EACpB,6BAA6B,EAC7B,sBAAsB,EACtB,0BAA0B,EAC1B,wBAAwB,EACxB,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EACxB,aAAa,EACb,4BAA4B,EAC5B,cAAc,EACjB,MAAM,WAAW,CAAC"}
package/lib/dist/index.js CHANGED
@@ -22,7 +22,7 @@ export const FluexGLAudio = {
22
22
  }
23
23
  };
24
24
  export { Chorus, Distortion, Equalizer, Limiter, Saturation, StereoPanner, Compressor, MultibandCompressor, AdvancedDelay, MonoDelay, PingPongDelay, StereoDelay, ChamberReverb, ConvolverReverb, GenericReverb, HallReverb, RoomReverb, SoftClip, LowPassFilter, HardClip } from "./effects/exports";
25
- export { AudioDevice, Channel, Effector, Master, AudioClip, DspPipeline } from "./core/exports";
26
- export { InitializeDspPipeline, ResolveAudioOutputDevices, ResolveAudioInputDevices, ResolveDefaultAudioInputDevice, ResolveDefaultAudioOutputDevice, LoadAudioSource, LoadAudioSourceFromBlob, LoadWorkletOnMasterChannel, SendMessageToWorklet } from "./utilities/helpers";
25
+ export { AudioDevice, Channel, Effector, Master, AudioClip, DspPipeline, AudioClipPlayer } from "./core/exports";
26
+ export { InitializeDspPipeline, ResolveAudioOutputDevices, ResolveAudioInputDevices, ResolveDefaultAudioInputDevice, ResolveDefaultAudioOutputDevice, LoadAudioSource, LoadAudioSourceFromBlob, LoadWorkletOnAudioDevice, SendMessageToWorklet } from "./utilities/helpers";
27
27
  export { SUPPORTED_FILE_TYPES } from "./utilities/constants";
28
28
  export { hasInitializedWasm, } from "./utilities/web-assembly";
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=linkable-channels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linkable-channels.d.ts","sourceRoot":"","sources":["../../src/test/linkable-channels.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ import { DspPipeline, Channel } from "../index";
2
+ (async function () {
3
+ const pipeline = new DspPipeline({
4
+ pathToWasm: "",
5
+ pathToWorklet: ""
6
+ });
7
+ const hasInitialized = await pipeline.Init();
8
+ if (!hasInitialized)
9
+ return;
10
+ const audioDevice = await pipeline.ResolveDefaultAudioOutputDevice();
11
+ if (!audioDevice)
12
+ return;
13
+ const master = audioDevice.GetMasterChannel();
14
+ const channel1 = new Channel();
15
+ const channel2 = new Channel();
16
+ })();
@@ -1,5 +1,4 @@
1
1
  import { AudioDevice } from "../core/classes/AudioDevice";
2
- import { Master } from "../core/classes/Master";
3
2
  import { LoadAudioSourceOptions, AudioSourceData, DspPipelineInitializationOptions, DspPipelineInitializationState, AudioWorkletProcessorNames } from "../typings";
4
3
  /**
5
4
  * Initializes the DSP pipeline by requesting audio permissions and initializing the WASM module.
@@ -41,7 +40,7 @@ export declare function LoadAudioSource(path: string, options?: Partial<LoadAudi
41
40
  */
42
41
  export declare function LoadAudioSourceFromBlob(blob: Blob): Promise<AudioSourceData | null>;
43
42
  export declare function ConstructProcessorWorklet(code: string): string;
44
- export declare function LoadWorkletOnMasterChannel(master: Master, workletBlobUrl: string): Promise<boolean>;
43
+ export declare function LoadWorkletOnAudioDevice(audioDevice: AudioDevice, workletBlobUrl: string): Promise<boolean>;
45
44
  export declare function SendMessageToWorklet<T, K = any>(node: AudioWorkletNode | null, commandId: T, data: K): boolean;
46
45
  export declare function CreateAudioWorkletNode<T = any>(context: AudioContext, name: AudioWorkletProcessorNames | string, data: T): AudioWorkletNode | null;
47
46
  //# sourceMappingURL=helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utilities/helpers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAQhD,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,gCAAgC,EAAE,8BAA8B,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAEnK;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,gCAAgC,GAAG,OAAO,CAAC,8BAA8B,GAAG,IAAI,CAAC,CAwCrI;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAUxE;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAUvE;AAED;;;GAGG;AACH,wBAAsB,+BAA+B,CAAC,IAAI,EAAE,8BAA8B,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAmBvH;AAED;;;GAGG;AACH,wBAAsB,8BAA8B,CAAC,IAAI,EAAE,8BAA8B,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAmBtH;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,OAAO,CAAC,sBAAsB,CAAoC,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAoChK;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAYzF;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO9D;AAED,wBAAsB,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,oBAgBtF;AAED,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,WAOpG;AAED,wBAAgB,sBAAsB,CAAC,CAAC,GAAG,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,0BAA0B,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC,2BAsBxH"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utilities/helpers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAS1D,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,gCAAgC,EAAE,8BAA8B,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAEnK;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,gCAAgC,GAAG,OAAO,CAAC,8BAA8B,GAAG,IAAI,CAAC,CAwCrI;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAUxE;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAUvE;AAED;;;GAGG;AACH,wBAAsB,+BAA+B,CAAC,IAAI,EAAE,8BAA8B,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAmBvH;AAED;;;GAGG;AACH,wBAAsB,8BAA8B,CAAC,IAAI,EAAE,8BAA8B,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAmBtH;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,OAAO,CAAC,sBAAsB,CAAoC,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAoChK;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAYzF;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO9D;AAED,wBAAsB,wBAAwB,CAAC,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAgB9F;AAED,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,WAOpG;AAED,wBAAgB,sBAAsB,CAAC,CAAC,GAAG,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,0BAA0B,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC,2BAsBxH"}
@@ -77,7 +77,7 @@ export async function ResolveDefaultAudioOutputDevice(init) {
77
77
  const defaultAudioDevice = devices.length === 0 ? null : new AudioDevice(audioDeviceInfos[0]);
78
78
  if (!defaultAudioDevice)
79
79
  return null;
80
- await LoadWorkletOnMasterChannel(defaultAudioDevice.masterChannel, init.workletBlobUrl);
80
+ await LoadWorkletOnAudioDevice(defaultAudioDevice, init.workletBlobUrl);
81
81
  return defaultAudioDevice;
82
82
  }
83
83
  /**
@@ -95,7 +95,7 @@ export async function ResolveDefaultAudioInputDevice(init) {
95
95
  const defaultAudioDevice = devices.length === 0 ? null : new AudioDevice(audioDeviceInfos[0]);
96
96
  if (!defaultAudioDevice)
97
97
  return null;
98
- await LoadWorkletOnMasterChannel(defaultAudioDevice.masterChannel, init.workletBlobUrl);
98
+ await LoadWorkletOnAudioDevice(defaultAudioDevice, init.workletBlobUrl);
99
99
  return defaultAudioDevice;
100
100
  }
101
101
  /**
@@ -148,9 +148,9 @@ export function ConstructProcessorWorklet(code) {
148
148
  });
149
149
  return URL.createObjectURL(blob);
150
150
  }
151
- export async function LoadWorkletOnMasterChannel(master, workletBlobUrl) {
152
- Debug.Log("Loading worklet modules on master channel...", [`Channel ID: ${master.id}`]);
153
- const context = master.context, start = Date.now();
151
+ export async function LoadWorkletOnAudioDevice(audioDevice, workletBlobUrl) {
152
+ Debug.Log("Loading worklet modules on master channel...", [`Channel ID: ${audioDevice.id}`]);
153
+ const context = audioDevice.context, start = Date.now();
154
154
  await context.audioWorklet.addModule(workletBlobUrl);
155
155
  const end = Date.now(), difference = end - start;
156
156
  Debug.Success("Succesfully loaded audio processor worklets into master channel.", [