@fluex/fluexgl-dsp 0.4.4 → 0.4.6

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.
@@ -2,6 +2,7 @@ import { AudioClipPlayer } from "./AudioClipPlayer";
2
2
  import { AudioClip } from "./AudioClip";
3
3
  import { Master } from "./Master";
4
4
  import { Effector } from "./Effector";
5
+ import { ArrayPosition } from "../../typings";
5
6
  export declare class Channel {
6
7
  id: string;
7
8
  label: string;
@@ -16,13 +17,22 @@ export declare class Channel {
16
17
  audioClipPlayer: AudioClipPlayer | null;
17
18
  constructor(context: AudioContext, label?: string);
18
19
  private rebuildEffectChain;
19
- AddEffect(effect: Effector): void;
20
- AttachEffect(effect: Effector): void;
21
- RemoveEffect(effect: Effector): void;
22
- DetachEffect(effect: Effector): void;
23
20
  private disconnectAudioNodes;
24
21
  private isInitialized;
25
22
  private isReachable;
23
+ /**
24
+ * Public method to manually rebuild the effect chain.
25
+ * Can be useful when the automatic rebuilt did not
26
+ * work properly.
27
+ * @returns
28
+ */
29
+ RebuildEffectChain(): void;
30
+ AddEffect(effect: Effector): Channel;
31
+ AttachEffect(effect: Effector): Channel;
32
+ RemoveEffect(effect: Effector): void;
33
+ RemoveAllEffects(): void;
34
+ DetachEffect(effect: Effector): void;
35
+ DetachAllEffects(): void;
26
36
  Send(channel: Channel | Master): void;
27
37
  Unsend(channel: Channel | Master): void;
28
38
  HasAudioClipPlayer(): boolean;
@@ -30,5 +40,10 @@ export declare class Channel {
30
40
  AttachAudioClip(audioClip: AudioClip): Channel;
31
41
  Volume(volume?: number): number;
32
42
  Pan(pan?: number): number;
43
+ GetEffectsByLabel(label: string): Effector[];
44
+ GetFirstEffectByLabel(label: string): Effector | null;
45
+ GetEffectById(id: string): Effector[];
46
+ GetFirstEffectById(id: string): Effector | null;
47
+ MoveEffectToIndex(effect: Effector, index: number | ArrayPosition): void;
33
48
  }
34
49
  //# 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,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"}
1
+ {"version":3,"file":"Channel.d.ts","sourceRoot":"","sources":["../../../src/core/classes/Channel.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,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;IAsC1B,OAAO,CAAC,oBAAoB;IAqB5B,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,WAAW;IAwBnB;;;;;OAKG;IACI,kBAAkB;IAIlB,SAAS,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO;IAcpC,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO;IAIvC,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAqBpC,gBAAgB;IAMhB,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAIpC,gBAAgB;IAIhB,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAkC9B,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAehC,kBAAkB,IAAI,OAAO;IAI7B,mBAAmB;IAOnB,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;IASzB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE;IAI5C,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAMrD,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,EAAE;IAIrC,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAM/C,iBAAiB,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;CAmElF"}
@@ -58,42 +58,6 @@ export class Channel {
58
58
  }
59
59
  activeEffects[activeEffects.length - 1].audioWorkletNode.connect(this.stereoPannerNode);
60
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
- }
97
61
  disconnectAudioNodes(gc) {
98
62
  this.input?.disconnect();
99
63
  this.stereoPannerNode?.disconnect();
@@ -129,6 +93,54 @@ export class Channel {
129
93
  }
130
94
  return false;
131
95
  }
96
+ /**
97
+ * Public method to manually rebuild the effect chain.
98
+ * Can be useful when the automatic rebuilt did not
99
+ * work properly.
100
+ * @returns
101
+ */
102
+ RebuildEffectChain() {
103
+ return this.rebuildEffectChain();
104
+ }
105
+ AddEffect(effect) {
106
+ if (!this.context)
107
+ throw new Error(`Could not add effect (${effect.id}), to channel (${this.id}), because the channel's AudioContext is undefined.`);
108
+ if (this.effects.includes(effect))
109
+ throw new Error(`Could not add effect (${effect.id}), to channel (${this.id}), because it has already been added to the channel.`);
110
+ this.effects.push(effect);
111
+ effect.InitializeOnAttachment(this.context);
112
+ this.rebuildEffectChain();
113
+ return this;
114
+ }
115
+ AttachEffect(effect) {
116
+ return this.AddEffect(effect);
117
+ }
118
+ RemoveEffect(effect) {
119
+ if (!this.effects.includes(effect)) {
120
+ Debug.Error("Could not remove effect, because it is not part of this channel.", [
121
+ "Call .AddEffect([effect Effector]) before removing effect."
122
+ ], ErrorCodes.EFFECT_NOT_FOUND);
123
+ return;
124
+ }
125
+ const self = this;
126
+ this.effects.forEach(function (_effect, index) {
127
+ if (effect.id === _effect.id)
128
+ self.effects.splice(index, 1);
129
+ });
130
+ effect.audioWorkletNode?.disconnect();
131
+ this.rebuildEffectChain();
132
+ }
133
+ RemoveAllEffects() {
134
+ for (const effect of this.effects) {
135
+ this.RemoveEffect(effect);
136
+ }
137
+ }
138
+ DetachEffect(effect) {
139
+ return this.RemoveEffect(effect);
140
+ }
141
+ DetachAllEffects() {
142
+ return this.RemoveAllEffects();
143
+ }
132
144
  Send(channel) {
133
145
  if (channel instanceof Master)
134
146
  return channel.AttachChannel(this);
@@ -200,4 +212,69 @@ export class Channel {
200
212
  pan && this.stereoPannerNode.pan.setValueAtTime(pan, this.context.currentTime);
201
213
  return pan ?? this.stereoPannerNode.pan.value;
202
214
  }
215
+ GetEffectsByLabel(label) {
216
+ return this.effects.filter(effect => effect.label === label);
217
+ }
218
+ GetFirstEffectByLabel(label) {
219
+ const filteredEffects = this.effects.filter(effect => effect.label === label);
220
+ return filteredEffects.length !== 0 ? filteredEffects[0] : null;
221
+ }
222
+ GetEffectById(id) {
223
+ return this.effects.filter(effect => effect.id === id);
224
+ }
225
+ GetFirstEffectById(id) {
226
+ const filteredEffects = this.effects.filter(effect => effect.id === id);
227
+ return filteredEffects.length !== 0 ? filteredEffects[0] : null;
228
+ }
229
+ MoveEffectToIndex(effect, index) {
230
+ let fromIndex = -1, matches = 0, i = 0;
231
+ for (i = 0; i < this.effects.length; i++) {
232
+ if (this.effects[i].id === effect.id) {
233
+ if (fromIndex === -1)
234
+ fromIndex = i;
235
+ matches++;
236
+ }
237
+ }
238
+ if (matches === 0)
239
+ throw new Error("Effect '" + effect.id + "' (" + effect.label + ") could not be found. " +
240
+ "The effect ID may have changed, or the effect is not attached to this channel.");
241
+ if (matches > 1)
242
+ throw new Error("Multiple effects with the ID '" + effect.id + "' are attached to this channel. " +
243
+ "Make sure every effect has a unique ID.");
244
+ let toIndex;
245
+ if (typeof index === "number") {
246
+ toIndex = index;
247
+ }
248
+ else {
249
+ switch (index) {
250
+ case "start":
251
+ toIndex = 0;
252
+ break;
253
+ case "end":
254
+ toIndex = this.effects.length - 1;
255
+ break;
256
+ case "one-after-start":
257
+ toIndex = 1;
258
+ break;
259
+ case "one-before-end":
260
+ toIndex = this.effects.length - 2;
261
+ break;
262
+ default:
263
+ throw new Error("Invalid ArrayPosition: " + String(index));
264
+ }
265
+ }
266
+ if (toIndex < 0)
267
+ toIndex = 0;
268
+ if (toIndex >= this.effects.length)
269
+ toIndex = this.effects.length - 1;
270
+ if (fromIndex === toIndex)
271
+ return;
272
+ const item = this.effects.splice(fromIndex, 1)[0];
273
+ if (fromIndex < toIndex)
274
+ toIndex = toIndex - 1;
275
+ this.effects.splice(toIndex, 0, item);
276
+ // Initializing the effect is unnessecary because it should have been intialized already
277
+ // otherwise it could not been found. Rebuilding the effect chain is nessecary though.
278
+ this.rebuildEffectChain();
279
+ }
203
280
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Effector.d.ts","sourceRoot":"","sources":["../../../src/core/classes/Effector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGhH,8BAAsB,QAAQ;IAEnB,EAAE,EAAE,MAAM,CAAQ;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC5B,IAAI,EAAE,MAAM,CAAc;IAE1B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IACjD,OAAO,EAAE,YAAY,GAAG,IAAI,CAAQ;IAE3C,OAAO,CAAC,iCAAiC,CAAkB;IAE3D,OAAO,CAAC,MAAM,CAMb;IAED,OAAO,CAAC,sBAAsB;IAgB9B,SAAS,CAAC,4BAA4B,CAAC,IAAI,EAAE,gBAAgB;IAOtD,gBAAgB,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAOjG,IAAI,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAarF,mBAAmB,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,QAAQ;IAalG,mBAAmB,CAAC,KAAK,CAAC,EAAE,MAAM,gBAAgB,GAAG,QAAQ;aAWpD,sBAAsB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAC/E"}
1
+ {"version":3,"file":"Effector.d.ts","sourceRoot":"","sources":["../../../src/core/classes/Effector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiD,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGhG,8BAAsB,QAAQ;IAEnB,EAAE,EAAE,MAAM,CAAQ;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC5B,IAAI,EAAE,MAAM,CAAc;IAE1B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IACjD,OAAO,EAAE,YAAY,GAAG,IAAI,CAAQ;IAE3C,OAAO,CAAC,iCAAiC,CAAkB;IAE3D,OAAO,CAAC,MAAM,CAMb;IAED,OAAO,CAAC,sBAAsB;IAgB9B,SAAS,CAAC,4BAA4B,CAAC,IAAI,EAAE,gBAAgB;IAQtD,gBAAgB,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAOjG,IAAI,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAarF,mBAAmB,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,QAAQ;IAalG,mBAAmB,CAAC,KAAK,CAAC,EAAE,MAAM,gBAAgB,GAAG,QAAQ;aAWpD,sBAAsB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAC/E"}
@@ -30,6 +30,7 @@ export class Effector {
30
30
  registerMessageEventListener(node) {
31
31
  if (this.hasRegisteredMessageEventListener)
32
32
  return;
33
+ this.hasRegisteredMessageEventListener = true;
33
34
  node.port.onmessage = this.handleIncomingMessages.bind(this);
34
35
  Debug.Log(`Succesfully registered event listener on effector ${this.name} (${this.label}) [${this.id}]`);
35
36
  }
@@ -6,7 +6,7 @@ export declare class SoftClip extends Effector {
6
6
  drive: number;
7
7
  gain: number;
8
8
  strictMode: StrictMode;
9
- constructor({ drive, gain, strictMode }: Partial<SoftClipOptions>);
9
+ constructor({ drive, gain, strictMode }?: Partial<SoftClipOptions>);
10
10
  InitializeOnAttachment(context: AudioContext): Promise<void>;
11
11
  ReturnOptionsAsObject(): SoftClipOptions;
12
12
  SetDrive(drive: number): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"SoftClip.d.ts","sourceRoot":"","sources":["../../../../src/effects/classes/clips/SoftClip.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAwD,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAErH,qBAAa,QAAS,SAAQ,QAAQ;IAE3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAc;IAClC,IAAI,EAAE,MAAM,CAAc;IAE1B,KAAK,EAAE,MAAM,CAAK;IAClB,IAAI,EAAE,MAAM,CAAK;IACjB,UAAU,EAAE,UAAU,CAAuB;gBAExC,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,OAAO,CAAC,eAAe,CAAC;IAUpD,sBAAsB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlE,qBAAqB,IAAI,eAAe;IAQxC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAMhC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAKxC"}
1
+ {"version":3,"file":"SoftClip.d.ts","sourceRoot":"","sources":["../../../../src/effects/classes/clips/SoftClip.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAwD,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAErH,qBAAa,QAAS,SAAQ,QAAQ;IAE3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAc;IAClC,IAAI,EAAE,MAAM,CAAc;IAE1B,KAAK,EAAE,MAAM,CAAK;IAClB,IAAI,EAAE,MAAM,CAAK;IACjB,UAAU,EAAE,UAAU,CAAuB;gBAExC,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,GAAE,OAAO,CAAC,eAAe,CAAM;IAUzD,sBAAsB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IASlE,qBAAqB,IAAI,eAAe;IAQxC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAMhC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAKxC"}
@@ -7,7 +7,7 @@ export class SoftClip extends Effector {
7
7
  drive = 1;
8
8
  gain = 1;
9
9
  strictMode = StrictMode.Disabled;
10
- constructor({ drive, gain, strictMode }) {
10
+ constructor({ drive, gain, strictMode } = {}) {
11
11
  super();
12
12
  this.drive = Math.max(0, CoerceFiniteNumber(drive, this.drive));
13
13
  this.gain = Math.max(0, CoerceFiniteNumber(gain, this.gain));
@@ -15,8 +15,10 @@ export class SoftClip extends Effector {
15
15
  this.strictMode = mode === StrictMode.Enabled ? StrictMode.Enabled : StrictMode.Disabled;
16
16
  }
17
17
  async InitializeOnAttachment(context) {
18
- this.context = context;
19
- this.audioWorkletNode = CreateAudioWorkletNode(context, AudioWorkletProcessorNames.SoftClip, this.ReturnOptionsAsObject());
18
+ if (this.context === null)
19
+ this.context = context;
20
+ if (this.audioWorkletNode === null)
21
+ this.audioWorkletNode = CreateAudioWorkletNode(context, AudioWorkletProcessorNames.SoftClip, this.ReturnOptionsAsObject());
20
22
  }
21
23
  ReturnOptionsAsObject() {
22
24
  return {
@@ -9,6 +9,6 @@ export { AudioDevice, Channel, Effector, Master, AudioClip, DspPipeline, AudioCl
9
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
- export { StrictMode, ProcessorIdentificationCodes, HardClipMessageCommandId, SoftClipMessageCommandId, AudioWorkletProcessorNames, ChorusMessageCommandId, LowPassFilterMessageCommandId } from "./typings";
13
- export type { DspDebuggerOptions, DspOptions, LoadAudioSourceOptions, AudioSourceData, ChannelOptions, ChannelSpatialization, AudioClipEventMap, AudioClipEvents, AudioClipOnProgressEvent, AudioClipAnalyserProperty, AudioClipAnalyserType, DspPipelineInitializationOptions, DspPipelineInitializationState, ChorusEffectOptions, LowPassFilterOptions, SoftClipOptions, HardClipOptions, EffectorEventMap, IncomingMessageType, IncomingProcessorMessage, ProcessorData, EffectorEvents, } from "./typings";
12
+ export { StrictMode, ProcessorIdentificationCodes, HardClipMessageCommandId, SoftClipMessageCommandId, AudioWorkletProcessorNames, ChorusMessageCommandId, LowPassFilterMessageCommandId, } from "./typings";
13
+ export type { DspDebuggerOptions, DspOptions, LoadAudioSourceOptions, AudioSourceData, ChannelOptions, ChannelSpatialization, AudioClipEventMap, AudioClipEvents, AudioClipOnProgressEvent, AudioClipAnalyserProperty, AudioClipAnalyserType, DspPipelineInitializationOptions, DspPipelineInitializationState, ChorusEffectOptions, LowPassFilterOptions, SoftClipOptions, HardClipOptions, EffectorEventMap, IncomingMessageType, IncomingProcessorMessage, ProcessorData, EffectorEvents, ArrayPosition } from "./typings";
14
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,eAAO,MAAM,GAAG,EAAE,UAYjB,CAAA;AAED,OAAO,EACH,MAAM,EACN,QAAQ,EACR,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,OAAO,EACH,UAAU,EACV,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,6BAA6B,EAChC,MAAM,WAAW,CAAC;AAEnB,YAAY,EACR,kBAAkB,EAClB,UAAU,EACV,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,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EACxB,aAAa,EACb,cAAc,GACjB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,eAAO,MAAM,GAAG,EAAE,UAYjB,CAAA;AAED,OAAO,EACH,MAAM,EACN,QAAQ,EACR,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,OAAO,EACH,UAAU,EACV,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,6BAA6B,GAChC,MAAM,WAAW,CAAC;AAEnB,YAAY,EACR,kBAAkB,EAClB,UAAU,EACV,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,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EACxB,aAAa,EACb,cAAc,EACd,aAAa,EAChB,MAAM,WAAW,CAAC"}
package/lib/dist/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  export const DSP = {
6
6
  maxMasterChannels: 8,
7
7
  maxTotalChannels: 128,
8
- sampleRate: 44000,
8
+ sampleRate: 41000,
9
9
  spatialization: "stereo",
10
10
  overrideMaxAudioBufferNodes: false,
11
11
  debugger: {
@@ -20,4 +20,4 @@ export { AudioDevice, Channel, Effector, Master, AudioClip, DspPipeline, AudioCl
20
20
  export { InitializeDspPipeline, ResolveAudioOutputDevices, ResolveAudioInputDevices, ResolveDefaultAudioInputDevice, ResolveDefaultAudioOutputDevice, LoadAudioSource, LoadAudioSourceFromBlob, LoadWorkletOnAudioDevice, SendMessageToWorklet } from "./utilities/helpers";
21
21
  export { SUPPORTED_FILE_TYPES } from "./utilities/constants";
22
22
  export { hasInitializedWasm, } from "./utilities/web-assembly";
23
- export { StrictMode, ProcessorIdentificationCodes, HardClipMessageCommandId, SoftClipMessageCommandId, AudioWorkletProcessorNames, ChorusMessageCommandId, LowPassFilterMessageCommandId } from "./typings";
23
+ export { StrictMode, ProcessorIdentificationCodes, HardClipMessageCommandId, SoftClipMessageCommandId, AudioWorkletProcessorNames, ChorusMessageCommandId, LowPassFilterMessageCommandId, } from "./typings";
@@ -2,6 +2,7 @@ export type ChannelSpatialization = "mono" | "stereo" | "surround";
2
2
  export type AudioClipAnalyserType = "pre" | "post";
3
3
  export type AudioClipAnalyserProperty = "fftSize" | "minDecibels" | "maxDecibels" | "smoothingTimeConstant";
4
4
  export type IncomingMessageType = "message" | "error" | "warning" | "wasm-instantiated";
5
+ export type ArrayPosition = "start" | "middle" | "end" | "one-after-start" | "one-before-end";
5
6
  export type AudioClipEvents = {
6
7
  [K in keyof AudioClipEventMap]: AudioClipEventMap[K][];
7
8
  };
@@ -1 +1 @@
1
- {"version":3,"file":"typings.d.ts","sourceRoot":"","sources":["../src/typings.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;AACnE,MAAM,MAAM,qBAAqB,GAAG,KAAK,GAAG,MAAM,CAAC;AACnD,MAAM,MAAM,yBAAyB,GAAG,SAAS,GAAG,aAAa,GAAG,aAAa,GAAG,uBAAuB,CAAC;AAC5G,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,mBAAmB,CAAC;AAExF,MAAM,MAAM,eAAe,GAAG;KACzB,CAAC,IAAI,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,CAAC,CAAC,EAAE;CACzD,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;KACxB,CAAC,IAAI,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAC,EAAE;CACvD,CAAA;AAED,oBAAY,6BAA6B;IACrC,SAAS,IAAA;IACT,eAAe,IAAA;IACf,IAAI,IAAA;CACP;AAED,oBAAY,sBAAsB;IAC9B,cAAc,IAAA;IACd,UAAU,IAAA;IACV,SAAS,IAAA;IACT,MAAM,IAAA;IACN,WAAW,IAAA;CACd;AAED,oBAAY,wBAAwB;IAChC,QAAQ,IAAA;IACR,OAAO,IAAA;CACV;AAED,oBAAY,wBAAwB;IAChC,QAAQ,IAAA;IACR,OAAO,IAAA;CACV;AAED,oBAAY,0BAA0B;IAClC,UAAU,wBAAwB;IAClC,mBAAmB,iCAAiC;IACpD,aAAa,2BAA2B;IACxC,SAAS,uBAAuB;IAChC,aAAa,2BAA2B;IACxC,WAAW,yBAAyB;IACpC,aAAa,2BAA2B;IACxC,cAAc,4BAA4B;IAC1C,cAAc,4BAA4B;IAC1C,WAAW,yBAAyB;IACpC,MAAM,oBAAoB;IAC1B,OAAO,qBAAqB;IAC5B,MAAM,oBAAoB;IAC1B,MAAM,oBAAoB;IAC1B,QAAQ,sBAAsB;IAC9B,QAAQ,sBAAsB;CACjC;AAED,oBAAY,4BAA4B;IACpC,kBAAkB,yBAAyB;IAC3C,oBAAoB,2BAA2B;IAC/C,4BAA4B,oCAAoC;CACnE;AAED,oBAAY,UAAU;IAClB,QAAQ,IAAO;IACf,OAAO,IAAO;CACjB;AAED,MAAM,WAAW,kBAAkB;IAC/B,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,qBAAqB,CAAC;IACtC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,2BAA2B,EAAE,OAAO,CAAC;CACxC;AAED,MAAM,WAAW,sBAAsB;IACnC,qBAAqB,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC5B,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAC9B,UAAU,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAC;CACzD;AAED,MAAM,WAAW,gCAAgC;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,8BAA8B;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC7B,4BAA4B,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC1E,4BAA4B,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC1E,0BAA0B,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACxE,mCAAmC,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACjF,6BAA6B,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;CAC9E;AAED,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,GAAG,4BAA4B,CAAC,kBAAkB,CAAC;IAC7D,IAAI,EAAE,MAAM,GAAG,4BAA4B,CAAC,oBAAoB,CAAC;IACjE,SAAS,EAAE,MAAM,GAAG,4BAA4B,CAAC,4BAA4B,CAAC;CACjF;AAED,MAAM,WAAW,wBAAwB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,mBAAmB,CAAC;IAC1B,SAAS,EAAE,aAAa,CAAC;IACzB,cAAc,CAAC,EAAE,GAAG,CAAC;CACxB"}
1
+ {"version":3,"file":"typings.d.ts","sourceRoot":"","sources":["../src/typings.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;AACnE,MAAM,MAAM,qBAAqB,GAAG,KAAK,GAAG,MAAM,CAAC;AACnD,MAAM,MAAM,yBAAyB,GAAG,SAAS,GAAG,aAAa,GAAG,aAAa,GAAG,uBAAuB,CAAC;AAC5G,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,mBAAmB,CAAC;AACxF,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAG9F,MAAM,MAAM,eAAe,GAAG;KACzB,CAAC,IAAI,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,CAAC,CAAC,EAAE;CACzD,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;KACxB,CAAC,IAAI,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAC,EAAE;CACvD,CAAA;AAED,oBAAY,6BAA6B;IACrC,SAAS,IAAA;IACT,eAAe,IAAA;IACf,IAAI,IAAA;CACP;AAED,oBAAY,sBAAsB;IAC9B,cAAc,IAAA;IACd,UAAU,IAAA;IACV,SAAS,IAAA;IACT,MAAM,IAAA;IACN,WAAW,IAAA;CACd;AAED,oBAAY,wBAAwB;IAChC,QAAQ,IAAA;IACR,OAAO,IAAA;CACV;AAED,oBAAY,wBAAwB;IAChC,QAAQ,IAAA;IACR,OAAO,IAAA;CACV;AAED,oBAAY,0BAA0B;IAClC,UAAU,wBAAwB;IAClC,mBAAmB,iCAAiC;IACpD,aAAa,2BAA2B;IACxC,SAAS,uBAAuB;IAChC,aAAa,2BAA2B;IACxC,WAAW,yBAAyB;IACpC,aAAa,2BAA2B;IACxC,cAAc,4BAA4B;IAC1C,cAAc,4BAA4B;IAC1C,WAAW,yBAAyB;IACpC,MAAM,oBAAoB;IAC1B,OAAO,qBAAqB;IAC5B,MAAM,oBAAoB;IAC1B,MAAM,oBAAoB;IAC1B,QAAQ,sBAAsB;IAC9B,QAAQ,sBAAsB;CACjC;AAED,oBAAY,4BAA4B;IACpC,kBAAkB,yBAAyB;IAC3C,oBAAoB,2BAA2B;IAC/C,4BAA4B,oCAAoC;CACnE;AAED,oBAAY,UAAU;IAClB,QAAQ,IAAO;IACf,OAAO,IAAO;CACjB;AAED,MAAM,WAAW,kBAAkB;IAC/B,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,qBAAqB,CAAC;IACtC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,2BAA2B,EAAE,OAAO,CAAC;CACxC;AAED,MAAM,WAAW,sBAAsB;IACnC,qBAAqB,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC5B,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAC9B,UAAU,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAC;CACzD;AAED,MAAM,WAAW,gCAAgC;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,8BAA8B;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC7B,4BAA4B,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC1E,4BAA4B,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC1E,0BAA0B,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACxE,mCAAmC,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACjF,6BAA6B,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;CAC9E;AAED,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,GAAG,4BAA4B,CAAC,kBAAkB,CAAC;IAC7D,IAAI,EAAE,MAAM,GAAG,4BAA4B,CAAC,oBAAoB,CAAC;IACjE,SAAS,EAAE,MAAM,GAAG,4BAA4B,CAAC,4BAA4B,CAAC;CACjF;AAED,MAAM,WAAW,wBAAwB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,mBAAmB,CAAC;IAC1B,SAAS,EAAE,aAAa,CAAC;IACzB,cAAc,CAAC,EAAE,GAAG,CAAC;CACxB"}
@@ -1,10 +1,12 @@
1
1
  import { v4 } from "uuid";
2
+
2
3
  import { Debug } from "../../utilities/debugger";
3
4
  import { AudioClipPlayer } from "./AudioClipPlayer";
4
5
  import { AudioClip } from "./AudioClip";
5
6
  import { Master } from "./Master";
6
7
  import { Effector } from "./Effector";
7
8
  import { ErrorCodes } from "../../console-codes";
9
+ import { ArrayPosition } from "../../typings";
8
10
 
9
11
  export class Channel {
10
12
 
@@ -73,7 +75,7 @@ export class Channel {
73
75
  this.input.connect(activeEffects[0].audioWorkletNode as AudioNode);
74
76
 
75
77
  for (let i: number = 0; i < activeEffects.length - 1; i++) {
76
-
78
+
77
79
  const current = activeEffects[i].audioWorkletNode as AudioNode;
78
80
  const next = activeEffects[i + 1].audioWorkletNode as AudioNode;
79
81
 
@@ -83,54 +85,6 @@ export class Channel {
83
85
  (activeEffects[activeEffects.length - 1].audioWorkletNode as AudioNode).connect(this.stereoPannerNode);
84
86
  }
85
87
 
86
- public AddEffect(effect: Effector): void {
87
-
88
- if (!this.context) {
89
- Debug.Error("Could not add effect because this channel has no AudioContext.");
90
- return;
91
- }
92
-
93
- if (this.effects.includes(effect)) {
94
- Debug.Error("Could not add effect because it is already part of this channel", [
95
- "Call .RemoveEffect([effect Effector]) before adding effect."
96
- ], ErrorCodes.EFFECT_ALREADY_ATTACHED);
97
- return;
98
- }
99
-
100
- this.effects.push(effect);
101
- effect.InitializeOnAttachment(this.context);
102
- this.rebuildEffectChain();
103
- }
104
-
105
- public AttachEffect(effect: Effector): void {
106
- return this.AddEffect(effect);
107
- }
108
-
109
- public RemoveEffect(effect: Effector): void {
110
-
111
- if (!this.effects.includes(effect)) {
112
- Debug.Error("Could not remove effect, because it is not part of this channel.", [
113
- "Call .AddEffect([effect Effector]) before removing effect."
114
- ], ErrorCodes.EFFECT_NOT_FOUND);
115
- return;
116
- }
117
-
118
- const self: Channel = this;
119
-
120
- this.effects.forEach(function (_effect: Effector, index: number): void {
121
- if (effect.id === _effect.id)
122
- self.effects.splice(index, 1);
123
- });
124
-
125
- effect.audioWorkletNode?.disconnect();
126
-
127
- this.rebuildEffectChain();
128
- }
129
-
130
- public DetachEffect(effect: Effector): void {
131
- return this.RemoveEffect(effect);
132
- }
133
-
134
88
  private disconnectAudioNodes(gc?: boolean) {
135
89
 
136
90
  this.input?.disconnect();
@@ -180,6 +134,69 @@ export class Channel {
180
134
  return false;
181
135
  }
182
136
 
137
+ /**
138
+ * Public method to manually rebuild the effect chain.
139
+ * Can be useful when the automatic rebuilt did not
140
+ * work properly.
141
+ * @returns
142
+ */
143
+ public RebuildEffectChain() {
144
+ return this.rebuildEffectChain();
145
+ }
146
+
147
+ public AddEffect(effect: Effector): Channel {
148
+
149
+ if (!this.context)
150
+ throw new Error(`Could not add effect (${effect.id}), to channel (${this.id}), because the channel's AudioContext is undefined.`);
151
+
152
+ if (this.effects.includes(effect))
153
+ throw new Error(`Could not add effect (${effect.id}), to channel (${this.id}), because it has already been added to the channel.`);
154
+
155
+ this.effects.push(effect);
156
+ effect.InitializeOnAttachment(this.context);
157
+ this.rebuildEffectChain();
158
+ return this;
159
+ }
160
+
161
+ public AttachEffect(effect: Effector): Channel {
162
+ return this.AddEffect(effect);
163
+ }
164
+
165
+ public RemoveEffect(effect: Effector): void {
166
+
167
+ if (!this.effects.includes(effect)) {
168
+ Debug.Error("Could not remove effect, because it is not part of this channel.", [
169
+ "Call .AddEffect([effect Effector]) before removing effect."
170
+ ], ErrorCodes.EFFECT_NOT_FOUND);
171
+ return;
172
+ }
173
+
174
+ const self: Channel = this;
175
+
176
+ this.effects.forEach(function (_effect: Effector, index: number): void {
177
+ if (effect.id === _effect.id)
178
+ self.effects.splice(index, 1);
179
+ });
180
+
181
+ effect.audioWorkletNode?.disconnect();
182
+
183
+ this.rebuildEffectChain();
184
+ }
185
+
186
+ public RemoveAllEffects() {
187
+ for (const effect of this.effects) {
188
+ this.RemoveEffect(effect);
189
+ }
190
+ }
191
+
192
+ public DetachEffect(effect: Effector): void {
193
+ return this.RemoveEffect(effect);
194
+ }
195
+
196
+ public DetachAllEffects() {
197
+ return this.RemoveAllEffects();
198
+ }
199
+
183
200
  public Send(channel: Channel | Master) {
184
201
 
185
202
  if (channel instanceof Master)
@@ -234,7 +251,6 @@ export class Channel {
234
251
  }
235
252
 
236
253
  public UnsendToAllChannels() {
237
-
238
254
  for (var i: number = 0; i < this.sends.length; i++) {
239
255
  this.Unsend(this.sends[i]);
240
256
  i--;
@@ -251,19 +267,107 @@ export class Channel {
251
267
 
252
268
  public Volume(volume?: number): number {
253
269
 
254
- if(!this.context) throw new Error("Could not set volume on channel, because it's context is undefined.");
255
- if(!this.gainNode) throw new Error("Could not set volume on channel, because it's GainNode is undefined.")
270
+ if (!this.context) throw new Error("Could not set volume on channel, because it's context is undefined.");
271
+ if (!this.gainNode) throw new Error("Could not set volume on channel, because it's GainNode is undefined.")
256
272
 
257
273
  volume && this.gainNode.gain.setValueAtTime(volume, this.context.currentTime);
258
274
  return volume ?? this.gainNode.gain.value;
259
275
  }
260
276
 
261
277
  public Pan(pan?: number): number {
262
-
263
- if(!this.context) throw new Error("Could not set pan on channel, because it's context is undefined.");
264
- if(!this.stereoPannerNode) throw new Error("Cannot set pan on channel, because it's StereoPannerNode is undefined.");
278
+
279
+ if (!this.context) throw new Error("Could not set pan on channel, because it's context is undefined.");
280
+ if (!this.stereoPannerNode) throw new Error("Cannot set pan on channel, because it's StereoPannerNode is undefined.");
265
281
 
266
282
  pan && this.stereoPannerNode.pan.setValueAtTime(pan, this.context.currentTime);
267
283
  return pan ?? this.stereoPannerNode.pan.value;
268
284
  }
285
+
286
+ public GetEffectsByLabel(label: string): Effector[] {
287
+ return this.effects.filter(effect => effect.label === label);
288
+ }
289
+
290
+ public GetFirstEffectByLabel(label: string): Effector | null {
291
+
292
+ const filteredEffects: Effector[] = this.effects.filter(effect => effect.label === label);
293
+ return filteredEffects.length !== 0 ? filteredEffects[0] : null;
294
+ }
295
+
296
+ public GetEffectById(id: string): Effector[] {
297
+ return this.effects.filter(effect => effect.id === id);
298
+ }
299
+
300
+ public GetFirstEffectById(id: string): Effector | null {
301
+
302
+ const filteredEffects: Effector[] = this.effects.filter(effect => effect.id === id);
303
+ return filteredEffects.length !== 0 ? filteredEffects[0] : null;
304
+ }
305
+
306
+ public MoveEffectToIndex(effect: Effector, index: number | ArrayPosition): void {
307
+
308
+ let fromIndex: number = -1,
309
+ matches: number = 0,
310
+ i: number = 0;
311
+
312
+ for (i = 0; i < this.effects.length; i++) {
313
+ if (this.effects[i].id === effect.id) {
314
+ if (fromIndex === -1)
315
+ fromIndex = i;
316
+
317
+ matches++;
318
+ }
319
+ }
320
+
321
+ if (matches === 0) throw new Error(
322
+ "Effect '" + effect.id + "' (" + effect.label + ") could not be found. " +
323
+ "The effect ID may have changed, or the effect is not attached to this channel."
324
+ );
325
+
326
+ if (matches > 1) throw new Error(
327
+ "Multiple effects with the ID '" + effect.id + "' are attached to this channel. " +
328
+ "Make sure every effect has a unique ID."
329
+ );
330
+
331
+ let toIndex: number;
332
+
333
+ if (typeof index === "number") {
334
+ toIndex = index;
335
+ } else {
336
+ switch (index) {
337
+ case "start":
338
+ toIndex = 0;
339
+ break;
340
+ case "end":
341
+ toIndex = this.effects.length - 1;
342
+ break;
343
+ case "one-after-start":
344
+ toIndex = 1;
345
+ break;
346
+ case "one-before-end":
347
+ toIndex = this.effects.length - 2;
348
+ break;
349
+ default:
350
+ throw new Error("Invalid ArrayPosition: " + String(index));
351
+ }
352
+ }
353
+
354
+ if (toIndex < 0)
355
+ toIndex = 0;
356
+
357
+ if (toIndex >= this.effects.length)
358
+ toIndex = this.effects.length - 1;
359
+
360
+ if (fromIndex === toIndex) return;
361
+
362
+ const item: Effector = this.effects.splice(fromIndex, 1)[0];
363
+
364
+ if (fromIndex < toIndex)
365
+ toIndex = toIndex - 1;
366
+
367
+ this.effects.splice(toIndex, 0, item);
368
+
369
+ // Initializing the effect is unnessecary because it should have been intialized already
370
+ // otherwise it could not been found. Rebuilding the effect chain is nessecary though.
371
+ this.rebuildEffectChain();
372
+ }
269
373
  }
@@ -1,6 +1,6 @@
1
1
  import { v4 } from "uuid";
2
2
 
3
- import { IncomingProcessorMessage, IncomingMessageType, EffectorEvents, EffectorEventMap } from "../../typings";
3
+ import { IncomingProcessorMessage, type EffectorEvents, EffectorEventMap } from "../../typings";
4
4
  import { Debug } from "../../utilities/debugger";
5
5
 
6
6
  export abstract class Effector {
@@ -41,6 +41,7 @@ export abstract class Effector {
41
41
  protected registerMessageEventListener(node: AudioWorkletNode) {
42
42
  if (this.hasRegisteredMessageEventListener) return;
43
43
 
44
+ this.hasRegisteredMessageEventListener = true;
44
45
  node.port.onmessage = this.handleIncomingMessages.bind(this);
45
46
  Debug.Log(`Succesfully registered event listener on effector ${this.name} (${this.label}) [${this.id}]`);
46
47
  }
@@ -11,7 +11,7 @@ export class SoftClip extends Effector {
11
11
  public gain: number = 1;
12
12
  public strictMode: StrictMode = StrictMode.Disabled;
13
13
 
14
- constructor({ drive, gain, strictMode }: Partial<SoftClipOptions>) {
14
+ constructor({ drive, gain, strictMode }: Partial<SoftClipOptions> = {}) {
15
15
  super();
16
16
 
17
17
  this.drive = Math.max(0, CoerceFiniteNumber(drive, this.drive));
@@ -22,8 +22,12 @@ export class SoftClip extends Effector {
22
22
  }
23
23
 
24
24
  public async InitializeOnAttachment(context: AudioContext): Promise<void> {
25
- this.context = context;
26
- this.audioWorkletNode = CreateAudioWorkletNode<SoftClipOptions>(context, AudioWorkletProcessorNames.SoftClip, this.ReturnOptionsAsObject());
25
+
26
+ if(this.context === null)
27
+ this.context = context;
28
+
29
+ if(this.audioWorkletNode === null)
30
+ this.audioWorkletNode = CreateAudioWorkletNode<SoftClipOptions>(context, AudioWorkletProcessorNames.SoftClip, this.ReturnOptionsAsObject());
27
31
  }
28
32
 
29
33
  public ReturnOptionsAsObject(): SoftClipOptions {
package/lib/src/index.ts CHANGED
@@ -8,7 +8,7 @@ import { DspOptions } from "./typings";
8
8
  export const DSP: DspOptions = {
9
9
  maxMasterChannels: 8,
10
10
  maxTotalChannels: 128,
11
- sampleRate: 44000,
11
+ sampleRate: 41000,
12
12
  spatialization: "stereo",
13
13
  overrideMaxAudioBufferNodes: false,
14
14
  debugger: {
@@ -80,7 +80,7 @@ export {
80
80
  SoftClipMessageCommandId,
81
81
  AudioWorkletProcessorNames,
82
82
  ChorusMessageCommandId,
83
- LowPassFilterMessageCommandId
83
+ LowPassFilterMessageCommandId,
84
84
  } from "./typings";
85
85
 
86
86
  export type {
@@ -106,4 +106,5 @@ export type {
106
106
  IncomingProcessorMessage,
107
107
  ProcessorData,
108
108
  EffectorEvents,
109
- } from "./typings";
109
+ ArrayPosition
110
+ } from "./typings";
@@ -2,6 +2,8 @@ export type ChannelSpatialization = "mono" | "stereo" | "surround";
2
2
  export type AudioClipAnalyserType = "pre" | "post";
3
3
  export type AudioClipAnalyserProperty = "fftSize" | "minDecibels" | "maxDecibels" | "smoothingTimeConstant";
4
4
  export type IncomingMessageType = "message" | "error" | "warning" | "wasm-instantiated";
5
+ export type ArrayPosition = "start" | "middle" | "end" | "one-after-start" | "one-before-end";
6
+
5
7
 
6
8
  export type AudioClipEvents = {
7
9
  [K in keyof AudioClipEventMap]: AudioClipEventMap[K][];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluex/fluexgl-dsp",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "description": "An open-source, web-based DSP library developed alongside FluexGL, designed for creating and manipulating sounds in various contexts.",
5
5
  "main": "lib/dist/index.js",
6
6
  "types": "lib/dist/index.d.ts",