@fluex/fluexgl-dsp 0.3.4 → 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.
- package/lib/dist/core/classes/AudioClip.d.ts +10 -28
- package/lib/dist/core/classes/AudioClip.d.ts.map +1 -1
- package/lib/dist/core/classes/AudioClip.js +56 -192
- package/lib/dist/core/classes/AudioClipPlayer.d.ts +15 -0
- package/lib/dist/core/classes/AudioClipPlayer.d.ts.map +1 -0
- package/lib/dist/core/classes/AudioClipPlayer.js +31 -0
- package/lib/dist/core/classes/AudioDevice.d.ts +2 -0
- package/lib/dist/core/classes/AudioDevice.d.ts.map +1 -1
- package/lib/dist/core/classes/AudioDevice.js +6 -2
- package/lib/dist/core/classes/Channel.d.ts +16 -34
- package/lib/dist/core/classes/Channel.d.ts.map +1 -1
- package/lib/dist/core/classes/Channel.js +95 -190
- package/lib/dist/core/classes/DpsPipeline.js +2 -2
- package/lib/dist/core/classes/Effector.d.ts.map +1 -1
- package/lib/dist/core/classes/Effector.js +0 -1
- package/lib/dist/core/classes/Master.d.ts +4 -4
- package/lib/dist/core/classes/Master.d.ts.map +1 -1
- package/lib/dist/core/classes/Master.js +11 -5
- package/lib/dist/core/exports.d.ts +1 -0
- package/lib/dist/core/exports.d.ts.map +1 -1
- package/lib/dist/core/exports.js +1 -0
- package/lib/dist/core/functions/rebuild-effect-chain.d.ts +3 -0
- package/lib/dist/core/functions/rebuild-effect-chain.d.ts.map +1 -0
- package/lib/dist/core/functions/rebuild-effect-chain.js +2 -0
- package/lib/dist/index.d.ts +2 -2
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +2 -2
- package/lib/dist/test/linkable-channels.d.ts +2 -0
- package/lib/dist/test/linkable-channels.d.ts.map +1 -0
- package/lib/dist/test/linkable-channels.js +16 -0
- package/lib/dist/utilities/helpers.d.ts +1 -2
- package/lib/dist/utilities/helpers.d.ts.map +1 -1
- package/lib/dist/utilities/helpers.js +5 -5
- package/lib/src/core/classes/AudioClip.ts +62 -236
- package/lib/src/core/classes/AudioClipPlayer.ts +45 -0
- package/lib/src/core/classes/AudioDevice.ts +12 -6
- package/lib/src/core/classes/Channel.ts +88 -221
- package/lib/src/core/classes/DpsPipeline.ts +2 -2
- package/lib/src/core/classes/Effector.ts +1 -3
- package/lib/src/core/classes/Master.ts +24 -12
- package/lib/src/core/exports.ts +2 -1
- package/lib/src/core/functions/rebuild-effect-chain.ts +5 -0
- package/lib/src/index.ts +3 -2
- package/lib/src/utilities/helpers.ts +5 -5
- package/package.json +2 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
16
|
-
|
|
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
|
-
|
|
37
|
-
Play(timestamp?: number, offset?: number):
|
|
38
|
-
Seek(seconds: number):
|
|
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
|
|
41
|
-
SetPanLevel(panLevel: number): AudioClip
|
|
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
|
-
|
|
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":"AAGA,OAAO,
|
|
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
|
-
|
|
17
|
-
|
|
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.
|
|
27
|
+
if (!this.context)
|
|
40
28
|
return null;
|
|
41
|
-
const context = this.
|
|
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.
|
|
58
|
-
Debug.Error("
|
|
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.
|
|
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
|
-
|
|
73
|
-
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
`
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
this.gainNode = new GainNode(
|
|
91
|
-
this.stereoPannerNode = new StereoPannerNode(
|
|
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.
|
|
99
|
-
Debug.Error("Could not play
|
|
100
|
-
"
|
|
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
|
-
|
|
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.
|
|
152
|
-
Debug.Error("Could not seek because the
|
|
153
|
-
`
|
|
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.
|
|
187
|
-
|
|
188
|
-
|
|
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
|
|
156
|
+
this.gainNode?.gain.setValueAtTime(volume, this.context?.currentTime ?? 0);
|
|
191
157
|
return this;
|
|
192
158
|
}
|
|
193
159
|
SetPanLevel(panLevel) {
|
|
194
|
-
if (!this.
|
|
195
|
-
|
|
196
|
-
|
|
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
|
-
|
|
200
|
-
|
|
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
|
|
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.
|
|
191
|
+
if (!this.context)
|
|
221
192
|
return false;
|
|
222
|
-
const contextCurrentTime = this.
|
|
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
|
-
|
|
264
|
-
if (!
|
|
265
|
-
Debug.Error("
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
-
|
|
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.
|
|
244
|
+
return (!this.isPlaying || !this.context)
|
|
381
245
|
? 0
|
|
382
|
-
: this.offsetAtStart + (this.
|
|
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;
|
|
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
|
-
|
|
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
|
-
|
|
9
|
-
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
constructor(
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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":"
|
|
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"}
|