@fluex/fluexgl-dsp 0.4.6 → 0.4.8
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/README.md +7 -7
- package/lib/dist/console-codes.d.ts +2 -1
- package/lib/dist/console-codes.d.ts.map +1 -1
- package/lib/dist/console-codes.js +1 -0
- package/lib/dist/core/classes/AudioClip.d.ts +27 -16
- package/lib/dist/core/classes/AudioClip.d.ts.map +1 -1
- package/lib/dist/core/classes/AudioClip.js +133 -48
- package/lib/dist/core/classes/AudioClipPlayer.d.ts +8 -8
- package/lib/dist/core/classes/AudioClipPlayer.d.ts.map +1 -1
- package/lib/dist/core/classes/AudioClipPlayer.js +22 -24
- package/lib/dist/core/classes/AudioDevice.d.ts +46 -5
- package/lib/dist/core/classes/AudioDevice.d.ts.map +1 -1
- package/lib/dist/core/classes/AudioDevice.js +47 -6
- package/lib/dist/core/classes/Channel.d.ts +20 -20
- package/lib/dist/core/classes/Channel.d.ts.map +1 -1
- package/lib/dist/core/classes/Channel.js +42 -42
- package/lib/dist/core/classes/DpsPipeline.d.ts +6 -6
- package/lib/dist/core/classes/DpsPipeline.d.ts.map +1 -1
- package/lib/dist/core/classes/DpsPipeline.js +18 -18
- package/lib/dist/core/classes/Effector.d.ts +5 -5
- package/lib/dist/core/classes/Effector.d.ts.map +1 -1
- package/lib/dist/core/classes/Effector.js +8 -8
- package/lib/dist/core/classes/Master.d.ts +6 -6
- package/lib/dist/core/classes/Master.d.ts.map +1 -1
- package/lib/dist/core/classes/Master.js +18 -18
- package/lib/dist/effects/classes/Analyser.d.ts +10 -6
- package/lib/dist/effects/classes/Analyser.d.ts.map +1 -1
- package/lib/dist/effects/classes/Analyser.js +29 -13
- package/lib/dist/effects/classes/Chorus.d.ts +7 -7
- package/lib/dist/effects/classes/Chorus.d.ts.map +1 -1
- package/lib/dist/effects/classes/Chorus.js +25 -25
- package/lib/dist/effects/classes/Distortion.d.ts +1 -1
- package/lib/dist/effects/classes/Distortion.d.ts.map +1 -1
- package/lib/dist/effects/classes/Distortion.js +1 -1
- package/lib/dist/effects/classes/Reverb.d.ts +32 -0
- package/lib/dist/effects/classes/Reverb.d.ts.map +1 -0
- package/lib/dist/effects/classes/Reverb.js +61 -0
- package/lib/dist/effects/classes/clips/HardClip.d.ts +5 -5
- package/lib/dist/effects/classes/clips/HardClip.d.ts.map +1 -1
- package/lib/dist/effects/classes/clips/HardClip.js +14 -14
- package/lib/dist/effects/classes/clips/SoftClip.d.ts +4 -4
- package/lib/dist/effects/classes/clips/SoftClip.d.ts.map +1 -1
- package/lib/dist/effects/classes/clips/SoftClip.js +13 -13
- package/lib/dist/effects/classes/filters/HighPassFilter.d.ts +18 -0
- package/lib/dist/effects/classes/filters/HighPassFilter.d.ts.map +1 -0
- package/lib/dist/effects/classes/filters/HighPassFilter.js +59 -0
- package/lib/dist/effects/classes/filters/LowPassFilter.d.ts +5 -5
- package/lib/dist/effects/classes/filters/LowPassFilter.d.ts.map +1 -1
- package/lib/dist/effects/classes/filters/LowPassFilter.js +17 -17
- package/lib/dist/effects/classes/filters/NotchFilter.d.ts +18 -0
- package/lib/dist/effects/classes/filters/NotchFilter.d.ts.map +1 -0
- package/lib/dist/effects/classes/filters/NotchFilter.js +59 -0
- package/lib/dist/effects/exports.d.ts +2 -5
- package/lib/dist/effects/exports.d.ts.map +1 -1
- package/lib/dist/effects/exports.js +2 -5
- package/lib/dist/index.d.ts +4 -4
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +3 -3
- package/lib/dist/typings.d.ts +33 -0
- package/lib/dist/typings.d.ts.map +1 -1
- package/lib/dist/typings.js +12 -0
- package/lib/dist/utilities/constants.d.ts +1 -0
- package/lib/dist/utilities/constants.d.ts.map +1 -1
- package/lib/dist/utilities/constants.js +1 -0
- package/lib/dist/utilities/debugger.d.ts +4 -4
- package/lib/dist/utilities/debugger.js +8 -8
- package/lib/dist/utilities/helpers.d.ts +13 -13
- package/lib/dist/utilities/helpers.d.ts.map +1 -1
- package/lib/dist/utilities/helpers.js +45 -59
- package/lib/dist/utilities/web-assembly.js +1 -1
- package/lib/src/console-codes.ts +2 -1
- package/lib/src/core/classes/AudioClip.ts +166 -55
- package/lib/src/core/classes/AudioClipPlayer.ts +22 -24
- package/lib/src/core/classes/AudioDevice.ts +49 -6
- package/lib/src/core/classes/Channel.ts +42 -42
- package/lib/src/core/classes/DpsPipeline.ts +19 -19
- package/lib/src/core/classes/Effector.ts +9 -9
- package/lib/src/core/classes/Master.ts +18 -18
- package/lib/src/effects/classes/Analyser.ts +33 -13
- package/lib/src/effects/classes/Chorus.ts +25 -25
- package/lib/src/effects/classes/Distortion.ts +1 -1
- package/lib/src/effects/classes/Reverb.ts +81 -0
- package/lib/src/effects/classes/clips/HardClip.ts +14 -14
- package/lib/src/effects/classes/clips/SoftClip.ts +13 -13
- package/lib/src/effects/classes/filters/HighPassFilter.ts +81 -0
- package/lib/src/effects/classes/filters/LowPassFilter.ts +17 -17
- package/lib/src/effects/classes/filters/NotchFilter.ts +81 -0
- package/lib/src/effects/exports.ts +2 -6
- package/lib/src/index.ts +15 -17
- package/lib/src/typings.ts +39 -1
- package/lib/src/utilities/constants.ts +3 -1
- package/lib/src/utilities/debugger.ts +4 -4
- package/lib/src/utilities/helpers.ts +47 -60
- package/lib/src/utilities/web-assembly.ts +1 -1
- package/package.json +3 -2
- package/lib/src/effects/classes/reverbs/ChamberReverb.ts +0 -1
- package/lib/src/effects/classes/reverbs/ConvolverReverb.ts +0 -1
- package/lib/src/effects/classes/reverbs/GenericReverb.ts +0 -1
- package/lib/src/effects/classes/reverbs/HallReverb.ts +0 -1
- package/lib/src/effects/classes/reverbs/RoomReverb.ts +0 -1
package/README.md
CHANGED
|
@@ -30,14 +30,14 @@ import { DspPipeline, Channel, LoadAudioSource, AudioClip } from "@fluex/fluexgl
|
|
|
30
30
|
pathToWorklet: "/data/fluexgl-dsp-processor.worklet"
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
await pipeline.
|
|
33
|
+
await pipeline.initializeDpsPipeline();
|
|
34
34
|
|
|
35
|
-
const audioDevice = await pipeline.
|
|
35
|
+
const audioDevice = await pipeline.resolveDefaultAudioOutputDevice();
|
|
36
36
|
|
|
37
37
|
if(!audioDevice) return;
|
|
38
38
|
|
|
39
|
-
const master = audioDevice.
|
|
40
|
-
const context = audioDevice.
|
|
39
|
+
const master = audioDevice.getMasterChannel();
|
|
40
|
+
const context = audioDevice.getContext();
|
|
41
41
|
|
|
42
42
|
const audioSource = await LoadAudioSource("/music.mp3");
|
|
43
43
|
|
|
@@ -46,11 +46,11 @@ import { DspPipeline, Channel, LoadAudioSource, AudioClip } from "@fluex/fluexgl
|
|
|
46
46
|
const audioClip = new AudioClip(audioSource);
|
|
47
47
|
const channel = new Channel(context);
|
|
48
48
|
|
|
49
|
-
channel.
|
|
50
|
-
audioClip.
|
|
49
|
+
channel.send(master);
|
|
50
|
+
audioClip.send(channel);
|
|
51
51
|
|
|
52
52
|
button.addEventListener("click", function() {
|
|
53
|
-
audioClip.
|
|
53
|
+
audioClip.play();
|
|
54
54
|
});
|
|
55
55
|
})();
|
|
56
56
|
```
|
|
@@ -19,7 +19,8 @@ export declare enum ErrorCodes {
|
|
|
19
19
|
AUDIO_CLIP_ALREADY_ATTACHED = "ERROR:FLUEXGL-DSP@0018",
|
|
20
20
|
AUDIO_CLIP_NOT_FOUND = "ERROR:FLUEXGL-DSP@0019",
|
|
21
21
|
AUDIO_CLIP_PLAYER_NO_CONTEXT = "ERROR:FLUEXGL-DSP@0020",
|
|
22
|
-
PANNING_OUT_OF_RANGE = "ERROR:FLUEXGL-DSP@0021"
|
|
22
|
+
PANNING_OUT_OF_RANGE = "ERROR:FLUEXGL-DSP@0021",
|
|
23
|
+
PITCH_OUT_OF_RANGE = "ERROR:FLUEXGL-DSP@0022"
|
|
23
24
|
}
|
|
24
25
|
export declare enum WarningCodes {
|
|
25
26
|
NO_DEFAULT_AUDIO_DEVICE_FOUND = "WARNING:FLUEXGL-DSP@0001"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console-codes.d.ts","sourceRoot":"","sources":["../src/console-codes.ts"],"names":[],"mappings":"AAAA,oBAAY,UAAU;IAClB,qBAAqB,2BAA2B;IAChD,kBAAkB,2BAA2B;IAC7C,sBAAsB,2BAA2B;IACjD,mBAAmB,2BAA2B;IAC9C,iCAAiC,2BAA2B;IAC5D,2BAA2B,2BAA2B;IACtD,sBAAsB,2BAA2B;IACjD,mCAAmC,2BAA2B;IAC9D,uBAAuB,2BAA2B;IAClD,gBAAgB,2BAA2B;IAC3C,wBAAwB,2BAA2B;IACnD,iBAAiB,2BAA2B;IAC5C,6BAA6B,2BAA2B;IACxD,uBAAuB,2BAA2B;IAClD,8BAA8B,2BAA2B;IACzD,sBAAsB,2BAA2B;IACjD,8BAA8B,2BAA2B;IACzD,2BAA2B,2BAA2B;IACtD,oBAAoB,2BAA2B;IAC/C,4BAA4B,2BAA2B;IACvD,oBAAoB,2BAA2B;
|
|
1
|
+
{"version":3,"file":"console-codes.d.ts","sourceRoot":"","sources":["../src/console-codes.ts"],"names":[],"mappings":"AAAA,oBAAY,UAAU;IAClB,qBAAqB,2BAA2B;IAChD,kBAAkB,2BAA2B;IAC7C,sBAAsB,2BAA2B;IACjD,mBAAmB,2BAA2B;IAC9C,iCAAiC,2BAA2B;IAC5D,2BAA2B,2BAA2B;IACtD,sBAAsB,2BAA2B;IACjD,mCAAmC,2BAA2B;IAC9D,uBAAuB,2BAA2B;IAClD,gBAAgB,2BAA2B;IAC3C,wBAAwB,2BAA2B;IACnD,iBAAiB,2BAA2B;IAC5C,6BAA6B,2BAA2B;IACxD,uBAAuB,2BAA2B;IAClD,8BAA8B,2BAA2B;IACzD,sBAAsB,2BAA2B;IACjD,8BAA8B,2BAA2B;IACzD,2BAA2B,2BAA2B;IACtD,oBAAoB,2BAA2B;IAC/C,4BAA4B,2BAA2B;IACvD,oBAAoB,2BAA2B;IAC/C,kBAAkB,2BAA2B;CAChD;AAED,oBAAY,YAAY;IACpB,6BAA6B,6BAA6B;CAC7D;AAED,oBAAY,YAAY;CAEvB"}
|
|
@@ -21,6 +21,7 @@ export var ErrorCodes;
|
|
|
21
21
|
ErrorCodes["AUDIO_CLIP_NOT_FOUND"] = "ERROR:FLUEXGL-DSP@0019";
|
|
22
22
|
ErrorCodes["AUDIO_CLIP_PLAYER_NO_CONTEXT"] = "ERROR:FLUEXGL-DSP@0020";
|
|
23
23
|
ErrorCodes["PANNING_OUT_OF_RANGE"] = "ERROR:FLUEXGL-DSP@0021";
|
|
24
|
+
ErrorCodes["PITCH_OUT_OF_RANGE"] = "ERROR:FLUEXGL-DSP@0022";
|
|
24
25
|
})(ErrorCodes || (ErrorCodes = {}));
|
|
25
26
|
export var WarningCodes;
|
|
26
27
|
(function (WarningCodes) {
|
|
@@ -10,6 +10,10 @@ export declare class AudioClip {
|
|
|
10
10
|
isPlaying: boolean;
|
|
11
11
|
startTime: number;
|
|
12
12
|
offsetAtStart: number;
|
|
13
|
+
playbackRate: number;
|
|
14
|
+
pitch: number;
|
|
15
|
+
minPitchSemitones: number;
|
|
16
|
+
maxPitchSemitones: number;
|
|
13
17
|
progressUpdateSpeed: number;
|
|
14
18
|
gainNode: GainNode | null;
|
|
15
19
|
stereoPannerNode: StereoPannerNode | null;
|
|
@@ -17,29 +21,36 @@ export declare class AudioClip {
|
|
|
17
21
|
audioClipPlayer: AudioClipPlayer | null;
|
|
18
22
|
private audioBufferSourceNodes;
|
|
19
23
|
private maxAudioBufferSourceNodes;
|
|
24
|
+
private audioClipPlayers;
|
|
20
25
|
private progressInterval;
|
|
21
26
|
private events;
|
|
22
27
|
constructor(data: AudioSourceData);
|
|
23
28
|
private createBufferSource;
|
|
24
29
|
private connectSourcesTo;
|
|
25
30
|
private safeDisconnect;
|
|
31
|
+
private getOutputNodes;
|
|
26
32
|
private rebuildNodeChain;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
initialize(audioClipPlayer: AudioClipPlayer): void;
|
|
34
|
+
play(timestamp?: number, offset?: number): void | this | null;
|
|
35
|
+
seek(seconds: number): void | this;
|
|
36
|
+
stop(): AudioClip | null;
|
|
37
|
+
setVolume(volume: number): AudioClip;
|
|
38
|
+
setPanLevel(panLevel: number): AudioClip;
|
|
39
|
+
setLoop(loop?: boolean): AudioClip;
|
|
40
|
+
setMaxAudioBufferSourceNodes(value: number): AudioClip;
|
|
41
|
+
disconnectAllAudioBufferSourceNodes(): boolean;
|
|
42
|
+
addEventListener<K extends keyof AudioClipEventMap>(event: K, cb: AudioClipEventMap[K]): () => void;
|
|
43
|
+
once<K extends keyof AudioClipEventMap>(event: K, cb: AudioClipEventMap[K]): () => void;
|
|
44
|
+
removeEventListener<K extends keyof AudioClipEventMap>(event: K, cb: AudioClipEventMap[K]): AudioClip;
|
|
45
|
+
clearEventListeners(event?: keyof AudioClipEventMap): AudioClip;
|
|
46
|
+
getChannelData(channel?: number): Float32Array;
|
|
47
|
+
send(channel: Channel | Master): void;
|
|
48
|
+
unsend(channel: Channel | Master): void;
|
|
49
|
+
detachFromAudioClipPlayer(audioClipPlayer: AudioClipPlayer): void;
|
|
50
|
+
setPitch(semitones: number): AudioClip;
|
|
51
|
+
resetPitch(): AudioClip;
|
|
52
|
+
/** @deprecated Use {@link setPitch} instead. */
|
|
53
|
+
setPlaybackRateInSemitones(semitones: number): AudioClip;
|
|
43
54
|
get currentPlaybackTime(): number;
|
|
44
55
|
get duration(): number;
|
|
45
56
|
get volume(): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioClip.d.ts","sourceRoot":"","sources":["../../../src/core/classes/AudioClip.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"AudioClip.d.ts","sourceRoot":"","sources":["../../../src/core/classes/AudioClip.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,10 @@ export class AudioClip {
|
|
|
11
11
|
isPlaying = false;
|
|
12
12
|
startTime = 0;
|
|
13
13
|
offsetAtStart = 0;
|
|
14
|
+
playbackRate = 1;
|
|
15
|
+
pitch = 0;
|
|
16
|
+
minPitchSemitones = -24;
|
|
17
|
+
maxPitchSemitones = 24;
|
|
14
18
|
progressUpdateSpeed = 20;
|
|
15
19
|
gainNode = null;
|
|
16
20
|
stereoPannerNode = null;
|
|
@@ -18,9 +22,12 @@ export class AudioClip {
|
|
|
18
22
|
audioClipPlayer = null;
|
|
19
23
|
audioBufferSourceNodes = [];
|
|
20
24
|
maxAudioBufferSourceNodes = 1;
|
|
25
|
+
audioClipPlayers = [];
|
|
21
26
|
progressInterval = 0;
|
|
22
27
|
events = {
|
|
23
|
-
"progress": []
|
|
28
|
+
"progress": [],
|
|
29
|
+
"initialize": [],
|
|
30
|
+
"play": []
|
|
24
31
|
};
|
|
25
32
|
constructor(data) {
|
|
26
33
|
this.data = data;
|
|
@@ -32,6 +39,7 @@ export class AudioClip {
|
|
|
32
39
|
const bufferSource = context.createBufferSource();
|
|
33
40
|
bufferSource.buffer = this.data.audioBuffer;
|
|
34
41
|
bufferSource.loop = this.loop;
|
|
42
|
+
bufferSource.playbackRate.setValueAtTime(this.playbackRate, this.context.currentTime);
|
|
35
43
|
return bufferSource;
|
|
36
44
|
}
|
|
37
45
|
connectSourcesTo(target) {
|
|
@@ -43,42 +51,74 @@ export class AudioClip {
|
|
|
43
51
|
safeDisconnect(node) {
|
|
44
52
|
node?.disconnect();
|
|
45
53
|
}
|
|
54
|
+
getOutputNodes() {
|
|
55
|
+
const nodes = [];
|
|
56
|
+
for (const player of this.audioClipPlayers) {
|
|
57
|
+
if (player.outputGainNode && !nodes.includes(player.outputGainNode))
|
|
58
|
+
nodes.push(player.outputGainNode);
|
|
59
|
+
}
|
|
60
|
+
return nodes;
|
|
61
|
+
}
|
|
46
62
|
rebuildNodeChain() {
|
|
47
|
-
if (!this.context || !this.gainNode || !this.stereoPannerNode
|
|
48
|
-
Debug.
|
|
63
|
+
if (!this.context || !this.gainNode || !this.stereoPannerNode) {
|
|
64
|
+
Debug.error("Failed to rebuild node chain, because some of the core AudioNodes are missing.");
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
const destinations = this.getOutputNodes();
|
|
68
|
+
if (destinations.length === 0) {
|
|
69
|
+
Debug.error("Failed to rebuild node chain, because no output destinations are available.");
|
|
49
70
|
return false;
|
|
50
71
|
}
|
|
51
|
-
const destination = this.audioClipPlayer.outputGainNode;
|
|
52
72
|
this.safeDisconnect(this.gainNode);
|
|
53
73
|
this.safeDisconnect(this.stereoPannerNode);
|
|
54
74
|
this.gainNode.connect(this.stereoPannerNode);
|
|
55
|
-
|
|
75
|
+
for (const destination of destinations) {
|
|
76
|
+
this.stereoPannerNode.connect(destination);
|
|
77
|
+
}
|
|
56
78
|
this.connectSourcesTo(this.gainNode);
|
|
57
79
|
return true;
|
|
58
80
|
}
|
|
59
|
-
|
|
81
|
+
initialize(audioClipPlayer) {
|
|
82
|
+
const startTimestamp = Date.now(), self = this;
|
|
60
83
|
if (!audioClipPlayer.context)
|
|
61
|
-
return Debug.
|
|
84
|
+
return Debug.error("Could not initialize AudioClip, because the AudioClipPlayer somehow has no audio context.", [
|
|
85
|
+
`AudioClipPlayer id: ${audioClipPlayer.id}`,
|
|
86
|
+
`AudioClip id: ${this.id}`
|
|
87
|
+
], ErrorCodes.AUDIO_CLIP_PLAYER_NO_CONTEXT);
|
|
88
|
+
if (this.context && this.context !== audioClipPlayer.context) {
|
|
89
|
+
return Debug.error("Could not initialize AudioClip, because the AudioClipPlayer does not share the same AudioContext.", [
|
|
62
90
|
`AudioClipPlayer id: ${audioClipPlayer.id}`,
|
|
63
91
|
`AudioClip id: ${this.id}`
|
|
64
92
|
], ErrorCodes.AUDIO_CLIP_PLAYER_NO_CONTEXT);
|
|
93
|
+
}
|
|
65
94
|
this.audioClipPlayer = audioClipPlayer;
|
|
66
95
|
this.context = audioClipPlayer.context;
|
|
67
|
-
|
|
68
|
-
|
|
96
|
+
if (!this.gainNode)
|
|
97
|
+
this.gainNode = new GainNode(this.context);
|
|
98
|
+
if (!this.stereoPannerNode)
|
|
99
|
+
this.stereoPannerNode = new StereoPannerNode(this.context);
|
|
100
|
+
if (!this.audioClipPlayers.includes(audioClipPlayer))
|
|
101
|
+
this.audioClipPlayers.push(audioClipPlayer);
|
|
102
|
+
const endTimestamp = Date.now(), difference = endTimestamp - startTimestamp;
|
|
103
|
+
this.events.initialize.forEach(function (cb) {
|
|
104
|
+
cb({
|
|
105
|
+
durationOfInitialization: difference,
|
|
106
|
+
context: self.context
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
this.rebuildNodeChain();
|
|
69
110
|
}
|
|
70
|
-
|
|
111
|
+
play(timestamp, offset) {
|
|
71
112
|
if (!this.context)
|
|
72
|
-
return Debug.
|
|
73
|
-
"Make sure to attach this AudioClip to an AudioClipPlayer instance, before calling .
|
|
113
|
+
return Debug.error("Could not play audio clip, because context (AudioContext) is undefined.", [
|
|
114
|
+
"Make sure to attach this AudioClip to an AudioClipPlayer instance, before calling .play on this AudioClip."
|
|
74
115
|
]);
|
|
75
|
-
const context = this.context;
|
|
76
|
-
const self = this;
|
|
116
|
+
const context = this.context, self = this;
|
|
77
117
|
if (this.audioBufferSourceNodes.length > this.maxAudioBufferSourceNodes - 1)
|
|
78
118
|
return null;
|
|
79
119
|
const bufferSource = this.createBufferSource();
|
|
80
120
|
if (!bufferSource) {
|
|
81
|
-
Debug.
|
|
121
|
+
Debug.error("Something went wrong.");
|
|
82
122
|
return null;
|
|
83
123
|
}
|
|
84
124
|
const actualOffset = offset ?? this.offsetAtStart ?? 0;
|
|
@@ -86,9 +126,9 @@ export class AudioClip {
|
|
|
86
126
|
this.offsetAtStart = actualOffset;
|
|
87
127
|
this.isPlaying = true;
|
|
88
128
|
if (this.progressInterval)
|
|
89
|
-
clearInterval(this.progressInterval);
|
|
129
|
+
window.clearInterval(this.progressInterval);
|
|
90
130
|
if (this.isPlaying)
|
|
91
|
-
this.progressInterval = setInterval(function () {
|
|
131
|
+
this.progressInterval = window.setInterval(function () {
|
|
92
132
|
if (!self.isPlaying)
|
|
93
133
|
return;
|
|
94
134
|
const current = self.offsetAtStart + (context.currentTime - self.startTime);
|
|
@@ -116,12 +156,19 @@ export class AudioClip {
|
|
|
116
156
|
this.audioBufferSourceNodes.push(bufferSource);
|
|
117
157
|
this.rebuildNodeChain();
|
|
118
158
|
bufferSource.start(timestamp ?? this.startTime, actualOffset);
|
|
159
|
+
this.events.play.forEach(function (cb) {
|
|
160
|
+
cb({
|
|
161
|
+
timestamp: Date.now(),
|
|
162
|
+
audioBufferSourceNodes: self.audioBufferSourceNodes,
|
|
163
|
+
context: context,
|
|
164
|
+
});
|
|
165
|
+
});
|
|
119
166
|
return this;
|
|
120
167
|
}
|
|
121
|
-
|
|
168
|
+
seek(seconds) {
|
|
122
169
|
if (!this.context)
|
|
123
|
-
return Debug.
|
|
124
|
-
`Make sure to attach this AudioClip to an AudioClipPlayer instance before calling .
|
|
170
|
+
return Debug.error("Could not seek because the context (AudioContext) of this AudioClip is undefined.", [
|
|
171
|
+
`Make sure to attach this AudioClip to an AudioClipPlayer instance before calling .seek on this AudioClip.`,
|
|
125
172
|
`AudioClip id: ${this.id}`
|
|
126
173
|
]);
|
|
127
174
|
const clamped = Math.max(0, Math.min(seconds, this.duration));
|
|
@@ -129,11 +176,11 @@ export class AudioClip {
|
|
|
129
176
|
this.offsetAtStart = clamped;
|
|
130
177
|
return this;
|
|
131
178
|
}
|
|
132
|
-
this.
|
|
133
|
-
this.
|
|
179
|
+
this.stop();
|
|
180
|
+
this.play(undefined, clamped);
|
|
134
181
|
return this;
|
|
135
182
|
}
|
|
136
|
-
|
|
183
|
+
stop() {
|
|
137
184
|
this.audioBufferSourceNodes.forEach(function (node) {
|
|
138
185
|
node.stop();
|
|
139
186
|
node.disconnect();
|
|
@@ -146,37 +193,37 @@ export class AudioClip {
|
|
|
146
193
|
}
|
|
147
194
|
return this;
|
|
148
195
|
}
|
|
149
|
-
|
|
196
|
+
setVolume(volume) {
|
|
150
197
|
if (!this.context)
|
|
151
|
-
Debug.
|
|
152
|
-
"Make sure to attach this AudioClip to an AudioClipPlayer instance before calling .
|
|
198
|
+
Debug.error("Could not set volume because the context (AudioContext) of this AudioClip is undefined.", [
|
|
199
|
+
"Make sure to attach this AudioClip to an AudioClipPlayer instance before calling .setVolume() on this AudioClip.",
|
|
153
200
|
], ErrorCodes.AUDIO_CLIP_PLAYER_NO_CONTEXT);
|
|
154
201
|
this.gainNode?.gain.setValueAtTime(volume, this.context?.currentTime ?? 0);
|
|
155
202
|
return this;
|
|
156
203
|
}
|
|
157
|
-
|
|
204
|
+
setPanLevel(panLevel) {
|
|
158
205
|
if (!this.context)
|
|
159
|
-
Debug.
|
|
160
|
-
"Make sure to attach this AudioClip to an AudioClipPlayer instance before calling .
|
|
206
|
+
Debug.error("Could not set volume because the context (AudioContext) of this AudioClip is undefined.", [
|
|
207
|
+
"Make sure to attach this AudioClip to an AudioClipPlayer instance before calling .setPanLevel() on this AudioClip.",
|
|
161
208
|
], ErrorCodes.AUDIO_CLIP_PLAYER_NO_CONTEXT);
|
|
162
209
|
if (panLevel < -1 || panLevel > 1)
|
|
163
|
-
Debug.
|
|
210
|
+
Debug.error("Could not set the pan level because it is not between -1 and 1.", [
|
|
164
211
|
`Given value: ${panLevel}.`,
|
|
165
212
|
`Accepts a value between -1 and 1. Can be a floating number.`
|
|
166
213
|
], ErrorCodes.PANNING_OUT_OF_RANGE);
|
|
167
214
|
this.stereoPannerNode?.pan.setValueAtTime(panLevel, this.context?.currentTime ?? 0);
|
|
168
215
|
return this;
|
|
169
216
|
}
|
|
170
|
-
|
|
217
|
+
setLoop(loop) {
|
|
171
218
|
this.audioBufferSourceNodes.forEach(function (node) {
|
|
172
219
|
node.loop = loop ?? true;
|
|
173
220
|
});
|
|
174
221
|
this.loop = loop ?? true;
|
|
175
222
|
return this;
|
|
176
223
|
}
|
|
177
|
-
|
|
224
|
+
setMaxAudioBufferSourceNodes(value) {
|
|
178
225
|
if (!DSP.overrideMaxAudioBufferNodes) {
|
|
179
|
-
Debug.
|
|
226
|
+
Debug.warn("Cannot set maxAudioBufferSourceNodes because the option to override the current maximum value is disabled.", [
|
|
180
227
|
"Set overrideMaxAudioBufferNodes on DSP to true, in order to override the maximum audio buffer source nodes."
|
|
181
228
|
]);
|
|
182
229
|
return this;
|
|
@@ -184,7 +231,7 @@ export class AudioClip {
|
|
|
184
231
|
this.maxAudioBufferSourceNodes = value;
|
|
185
232
|
return this;
|
|
186
233
|
}
|
|
187
|
-
|
|
234
|
+
disconnectAllAudioBufferSourceNodes() {
|
|
188
235
|
if (!this.context)
|
|
189
236
|
return false;
|
|
190
237
|
const contextCurrentTime = this.context?.currentTime;
|
|
@@ -194,19 +241,19 @@ export class AudioClip {
|
|
|
194
241
|
});
|
|
195
242
|
return true;
|
|
196
243
|
}
|
|
197
|
-
|
|
244
|
+
addEventListener(event, cb) {
|
|
198
245
|
this.events[event].push(cb);
|
|
199
|
-
return () => this.
|
|
246
|
+
return () => this.removeEventListener(event, cb);
|
|
200
247
|
}
|
|
201
|
-
|
|
248
|
+
once(event, cb) {
|
|
202
249
|
const wrapper = ((...args) => {
|
|
203
250
|
// @ts-ignore
|
|
204
251
|
cb(...args);
|
|
205
|
-
this.
|
|
252
|
+
this.removeEventListener(event, wrapper);
|
|
206
253
|
});
|
|
207
|
-
return this.
|
|
254
|
+
return this.addEventListener(event, wrapper);
|
|
208
255
|
}
|
|
209
|
-
|
|
256
|
+
removeEventListener(event, cb) {
|
|
210
257
|
const arr = this.events[event];
|
|
211
258
|
for (let i = 0; i < arr.length; i++) {
|
|
212
259
|
if (arr[i] === cb) {
|
|
@@ -216,7 +263,7 @@ export class AudioClip {
|
|
|
216
263
|
}
|
|
217
264
|
return this;
|
|
218
265
|
}
|
|
219
|
-
|
|
266
|
+
clearEventListeners(event) {
|
|
220
267
|
if (event) {
|
|
221
268
|
this.events[event].length = 0;
|
|
222
269
|
}
|
|
@@ -225,26 +272,64 @@ export class AudioClip {
|
|
|
225
272
|
}
|
|
226
273
|
return this;
|
|
227
274
|
}
|
|
228
|
-
|
|
275
|
+
getChannelData(channel = 0) {
|
|
229
276
|
return this.data.audioBuffer.getChannelData(channel);
|
|
230
277
|
}
|
|
231
|
-
|
|
278
|
+
send(channel) {
|
|
232
279
|
if (!channel.audioClipPlayer)
|
|
233
|
-
return Debug.
|
|
280
|
+
return Debug.error("Could not send AudioClip signal to channel, because the channel's AudioClipPlayer is undefined.", [
|
|
234
281
|
"Make sure to initialize the Channel.",
|
|
235
282
|
`Channel id: ${channel.id}.`,
|
|
236
283
|
`AudioClip id: ${this.id}.`
|
|
237
284
|
]);
|
|
238
|
-
channel.audioClipPlayer.
|
|
285
|
+
channel.audioClipPlayer.attachAudioClip(this);
|
|
239
286
|
}
|
|
240
|
-
|
|
287
|
+
unsend(channel) {
|
|
241
288
|
if (!channel.audioClipPlayer)
|
|
242
|
-
return Debug.
|
|
289
|
+
return Debug.error("Could not unsend AudioClip signal to channel, because the channel's AudioClipPlayer is undefined.", [
|
|
243
290
|
"Make sure to initialize the Channel.",
|
|
244
291
|
`Channel id: ${channel.id}.`,
|
|
245
292
|
`AudioClip id: ${this.id}.`
|
|
246
293
|
]);
|
|
247
|
-
channel.audioClipPlayer.
|
|
294
|
+
channel.audioClipPlayer.detachAudioClip(this);
|
|
295
|
+
}
|
|
296
|
+
detachFromAudioClipPlayer(audioClipPlayer) {
|
|
297
|
+
const idx = this.audioClipPlayers.indexOf(audioClipPlayer);
|
|
298
|
+
if (idx === -1)
|
|
299
|
+
return;
|
|
300
|
+
this.audioClipPlayers.splice(idx, 1);
|
|
301
|
+
if (this.audioClipPlayer === audioClipPlayer) {
|
|
302
|
+
this.audioClipPlayer = this.audioClipPlayers[0] ?? null;
|
|
303
|
+
}
|
|
304
|
+
if (this.audioClipPlayers.length === 0) {
|
|
305
|
+
this.stop();
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
this.rebuildNodeChain();
|
|
309
|
+
}
|
|
310
|
+
setPitch(semitones) {
|
|
311
|
+
if (!this.context)
|
|
312
|
+
Debug.error("Could not set pitch because the context (AudioContext) of this AudioClip is undefined.", [
|
|
313
|
+
"Make sure to attach this AudioClip to an AudioClipPlayer instance before calling .setPitch() on this AudioClip.",
|
|
314
|
+
], ErrorCodes.AUDIO_CLIP_PLAYER_NO_CONTEXT);
|
|
315
|
+
if (semitones < this.minPitchSemitones || semitones > this.maxPitchSemitones)
|
|
316
|
+
Debug.error("Could not set the pitch because it is not within the allowed semitone range.", [
|
|
317
|
+
`Given value: ${semitones}.`,
|
|
318
|
+
`Accepts a value between ${this.minPitchSemitones} and ${this.maxPitchSemitones} semitones.`
|
|
319
|
+
], ErrorCodes.PITCH_OUT_OF_RANGE);
|
|
320
|
+
const calculatedPlaybackRate = Math.pow(2, semitones / 12);
|
|
321
|
+
for (const buffer of this.audioBufferSourceNodes)
|
|
322
|
+
buffer.playbackRate.setValueAtTime(calculatedPlaybackRate, this.context?.currentTime ?? 0);
|
|
323
|
+
this.pitch = semitones;
|
|
324
|
+
this.playbackRate = calculatedPlaybackRate;
|
|
325
|
+
return this;
|
|
326
|
+
}
|
|
327
|
+
resetPitch() {
|
|
328
|
+
return this.setPitch(0);
|
|
329
|
+
}
|
|
330
|
+
/** @deprecated Use {@link setPitch} instead. */
|
|
331
|
+
setPlaybackRateInSemitones(semitones) {
|
|
332
|
+
return this.setPitch(semitones);
|
|
248
333
|
}
|
|
249
334
|
get currentPlaybackTime() {
|
|
250
335
|
return (!this.isPlaying || !this.context)
|
|
@@ -9,14 +9,14 @@ export declare class AudioClipPlayer {
|
|
|
9
9
|
context: AudioContext | null;
|
|
10
10
|
channel: Channel | Master | null;
|
|
11
11
|
constructor(context: AudioContext);
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
attachAudioClip(audioClip: AudioClip): void;
|
|
13
|
+
detachAudioClip(clip: AudioClip): void;
|
|
14
|
+
send(channel: Channel | Master): void;
|
|
15
|
+
unsend(): void;
|
|
16
|
+
setVolume(value: number): void;
|
|
17
|
+
stopAll(): void;
|
|
18
|
+
dispose(): void;
|
|
19
|
+
setLabel(label: string): void;
|
|
20
20
|
get length(): number;
|
|
21
21
|
get volume(): number;
|
|
22
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioClipPlayer.d.ts","sourceRoot":"","sources":["../../../src/core/classes/AudioClipPlayer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,qBAAa,eAAe;IAEjB,KAAK,EAAE,MAAM,CAAqB;IAClC,EAAE,EAAE,MAAM,CAAQ;IAElB,UAAU,EAAE,SAAS,EAAE,CAAM;IAC7B,cAAc,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAEvC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAQ;IACpC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAQ;
|
|
1
|
+
{"version":3,"file":"AudioClipPlayer.d.ts","sourceRoot":"","sources":["../../../src/core/classes/AudioClipPlayer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,qBAAa,eAAe;IAEjB,KAAK,EAAE,MAAM,CAAqB;IAClC,EAAE,EAAE,MAAM,CAAQ;IAElB,UAAU,EAAE,SAAS,EAAE,CAAM;IAC7B,cAAc,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAEvC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAQ;IACpC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAQ;IAE/C,YAAY,OAAO,EAAE,YAAY,EAGhC;IAEM,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAQjD;IAEM,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,CAY5C;IAEM,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAQ3C;IAEM,MAAM,IAAI,IAAI,CAWpB;IAEM,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAQpC;IAEM,OAAO,IAAI,IAAI,CAKrB;IAEM,OAAO,IAAI,IAAI,CAUrB;IAEM,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEnC;IAED,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED,IAAW,MAAM,IAAI,MAAM,CAE1B;CACJ"}
|
|
@@ -12,34 +12,32 @@ export class AudioClipPlayer {
|
|
|
12
12
|
this.context = context;
|
|
13
13
|
this.outputGainNode = new GainNode(context);
|
|
14
14
|
}
|
|
15
|
-
|
|
15
|
+
attachAudioClip(audioClip) {
|
|
16
16
|
if (this.audioClips.includes(audioClip))
|
|
17
|
-
return Debug.
|
|
18
|
-
"Call .
|
|
17
|
+
return Debug.error("Could not attach audio clip because it is already part of this channel", [
|
|
18
|
+
"Call .detachAudioClip([clip AudioClip]) before attaching audio clip."
|
|
19
19
|
], ErrorCodes.AUDIO_CLIP_ALREADY_ATTACHED);
|
|
20
|
-
audioClip.
|
|
20
|
+
audioClip.initialize(this);
|
|
21
21
|
this.audioClips.push(audioClip);
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
detachAudioClip(clip) {
|
|
24
24
|
if (!this.audioClips.includes(clip))
|
|
25
|
-
return Debug.
|
|
26
|
-
"Call .
|
|
25
|
+
return Debug.error("Could not detach audio clip because it is not part of this channel", [
|
|
26
|
+
"Call .attachAudioClip([clip AudioClip]) before detaching audio clip."
|
|
27
27
|
], ErrorCodes.AUDIO_CLIP_NOT_FOUND);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return self.audioClips.splice(index, 1);
|
|
33
|
-
});
|
|
28
|
+
const idx = this.audioClips.indexOf(clip);
|
|
29
|
+
if (idx >= 0)
|
|
30
|
+
this.audioClips.splice(idx, 1);
|
|
31
|
+
clip.detachFromAudioClipPlayer(this);
|
|
34
32
|
}
|
|
35
|
-
|
|
33
|
+
send(channel) {
|
|
36
34
|
if (!this.outputGainNode || !channel.input)
|
|
37
|
-
return Debug.
|
|
38
|
-
this.
|
|
35
|
+
return Debug.error("Could not send AudioClipPlayer signal to a channel/master.");
|
|
36
|
+
this.unsend();
|
|
39
37
|
this.channel = channel;
|
|
40
38
|
this.outputGainNode.connect(channel.input);
|
|
41
39
|
}
|
|
42
|
-
|
|
40
|
+
unsend() {
|
|
43
41
|
if (!this.outputGainNode)
|
|
44
42
|
return;
|
|
45
43
|
if (this.channel && this.channel.input) {
|
|
@@ -50,7 +48,7 @@ export class AudioClipPlayer {
|
|
|
50
48
|
}
|
|
51
49
|
this.channel = null;
|
|
52
50
|
}
|
|
53
|
-
|
|
51
|
+
setVolume(value) {
|
|
54
52
|
if (!this.outputGainNode)
|
|
55
53
|
return;
|
|
56
54
|
if (value < 0)
|
|
@@ -59,21 +57,21 @@ export class AudioClipPlayer {
|
|
|
59
57
|
value = 1;
|
|
60
58
|
this.outputGainNode.gain.value = value;
|
|
61
59
|
}
|
|
62
|
-
|
|
60
|
+
stopAll() {
|
|
63
61
|
this.audioClips.forEach(function (clip) {
|
|
64
|
-
clip.
|
|
62
|
+
clip.stop();
|
|
65
63
|
});
|
|
66
64
|
}
|
|
67
|
-
|
|
68
|
-
this.
|
|
69
|
-
this.
|
|
65
|
+
dispose() {
|
|
66
|
+
this.stopAll();
|
|
67
|
+
this.unsend();
|
|
70
68
|
this.outputGainNode?.disconnect();
|
|
71
69
|
this.audioClips = [];
|
|
72
70
|
this.outputGainNode = null;
|
|
73
71
|
this.channel = null;
|
|
74
72
|
this.context = null;
|
|
75
73
|
}
|
|
76
|
-
|
|
74
|
+
setLabel(label) {
|
|
77
75
|
this.label = label;
|
|
78
76
|
}
|
|
79
77
|
get length() {
|
|
@@ -7,11 +7,52 @@ export declare class AudioDevice {
|
|
|
7
7
|
context: AudioContext;
|
|
8
8
|
masterChannel: Master;
|
|
9
9
|
masterChannels: Master[];
|
|
10
|
+
readonly sampleRate: number;
|
|
11
|
+
readonly baseLatency: number;
|
|
12
|
+
readonly outputLatency: number;
|
|
13
|
+
readonly state: AudioContextState;
|
|
14
|
+
readonly currentTime: number;
|
|
15
|
+
readonly maximumFrequency: number;
|
|
10
16
|
constructor(deviceInfo: MediaDeviceInfo);
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Returns the master channel associated with this audio device.
|
|
19
|
+
* The master channel is the main output channel for this audio device, and is used to control the overall volume and other properties of the audio output.
|
|
20
|
+
* @returns
|
|
21
|
+
*/
|
|
22
|
+
getMasterChannel(): Master;
|
|
23
|
+
/**
|
|
24
|
+
* Sets the master channel for this audio device.
|
|
25
|
+
* The master channel is normally automatically created when the audio device is initialized, but this method allows for the master channel to be changed if needed.
|
|
26
|
+
* @param channel
|
|
27
|
+
* @returns
|
|
28
|
+
*/
|
|
29
|
+
setMasterChannel(channel: Master): void;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new master channel based on the this audio device's audio context, and adds it to the master channels array.
|
|
32
|
+
* Normally, an audio device should only have one master channel, but this method allows for multiple master channels to be created and used if needed.
|
|
33
|
+
* @returns
|
|
34
|
+
*/
|
|
35
|
+
createMasterChannel(): Master;
|
|
36
|
+
/**
|
|
37
|
+
* Returns the audio context associated with this audio device.
|
|
38
|
+
* This method is provided for ease of use, and is a wrapper for the context property.
|
|
39
|
+
*
|
|
40
|
+
* The audio context can vary between audio devices, and is used to create channels and master channels that are associated with this audio device.
|
|
41
|
+
*/
|
|
42
|
+
getContext(): AudioContext;
|
|
43
|
+
/**
|
|
44
|
+
* Creates a new channel based on the this audio device's audio context.
|
|
45
|
+
* This method is a wrapper for the Channel constructor, and is provided for ease of use.
|
|
46
|
+
* In case you want to create a channel with a different audio context, you can use the Channel constructor directly.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```
|
|
50
|
+
* const myChannel: Channel = audioDevice.createChannel("My Channel");
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @param label
|
|
54
|
+
* @returns
|
|
55
|
+
*/
|
|
56
|
+
createChannel(label?: string): Channel;
|
|
16
57
|
}
|
|
17
58
|
//# sourceMappingURL=AudioDevice.d.ts.map
|