@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
|
@@ -12,29 +12,29 @@ import { ErrorCodes, WarningCodes } from "../console-codes";
|
|
|
12
12
|
* FluexGL DSP cannot be used without calling this function first.
|
|
13
13
|
* @returns
|
|
14
14
|
*/
|
|
15
|
-
export async function
|
|
16
|
-
Debug.
|
|
15
|
+
export async function initializeDspPipeline(options) {
|
|
16
|
+
Debug.log("Attempting to initialize DSP pipeline...");
|
|
17
17
|
const start = Date.now();
|
|
18
18
|
let initialized = true;
|
|
19
19
|
try {
|
|
20
20
|
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
21
|
-
Debug.
|
|
21
|
+
Debug.log(`Found ${stream.getTracks().length} media stream tracks.`);
|
|
22
22
|
stream.getTracks().forEach(function (track) {
|
|
23
23
|
track.stop();
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
catch (err) {
|
|
27
27
|
initialized = false;
|
|
28
|
-
Debug.
|
|
28
|
+
Debug.error("Permission to access media devices has not been granted.", [
|
|
29
29
|
"Make sure the user has granted FluentGL permission to access media devices."
|
|
30
30
|
], ErrorCodes.NO_CONTEXT_PERMISSION);
|
|
31
31
|
}
|
|
32
32
|
await LoadWebAssemblyModule(options.pathToWasm);
|
|
33
33
|
const workletFileRequest = await fetch(options.pathToWorklet);
|
|
34
34
|
const textContent = await workletFileRequest.text();
|
|
35
|
-
const blobUrl =
|
|
35
|
+
const blobUrl = constructProcessorWorklet(textContent);
|
|
36
36
|
const end = Date.now(), difference = end - start;
|
|
37
|
-
Debug.
|
|
37
|
+
Debug.success(`Succesfully initialized DSP pipeline within ${difference}ms.`);
|
|
38
38
|
return {
|
|
39
39
|
success: true,
|
|
40
40
|
workletBlobUrl: blobUrl
|
|
@@ -44,7 +44,7 @@ export async function InitializeDspPipeline(options) {
|
|
|
44
44
|
* Resolves a list of available audio output devices.
|
|
45
45
|
* @returns
|
|
46
46
|
*/
|
|
47
|
-
export async function
|
|
47
|
+
export async function resolveAudioOutputDevices() {
|
|
48
48
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
49
49
|
const audioDevices = [];
|
|
50
50
|
for (let device of devices)
|
|
@@ -55,7 +55,7 @@ export async function ResolveAudioOutputDevices() {
|
|
|
55
55
|
* Resolves a list of available audio input devices.
|
|
56
56
|
* @returns
|
|
57
57
|
*/
|
|
58
|
-
export async function
|
|
58
|
+
export async function resolveAudioInputDevices() {
|
|
59
59
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
60
60
|
const audioDevices = [];
|
|
61
61
|
for (let device of devices)
|
|
@@ -66,36 +66,36 @@ export async function ResolveAudioInputDevices() {
|
|
|
66
66
|
* Resolves the default audio output device.
|
|
67
67
|
* @returns
|
|
68
68
|
*/
|
|
69
|
-
export async function
|
|
70
|
-
Debug.
|
|
69
|
+
export async function resolveDefaultAudioOutputDevice(init) {
|
|
70
|
+
Debug.log("Attempting to resolve default audio output device...");
|
|
71
71
|
const audioDeviceInfos = [];
|
|
72
72
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
73
73
|
for (let device of devices)
|
|
74
74
|
(device.kind === "audiooutput" && device.deviceId == "default")
|
|
75
75
|
&& audioDeviceInfos.push(device);
|
|
76
|
-
devices.length === 0 && Debug.
|
|
76
|
+
devices.length === 0 && Debug.warn("No default audio device found.", [], WarningCodes.NO_DEFAULT_AUDIO_DEVICE_FOUND);
|
|
77
77
|
const defaultAudioDevice = devices.length === 0 ? null : new AudioDevice(audioDeviceInfos[0]);
|
|
78
78
|
if (!defaultAudioDevice)
|
|
79
79
|
return null;
|
|
80
|
-
await
|
|
80
|
+
await loadWorkletOnAudioDevice(defaultAudioDevice, init.workletBlobUrl);
|
|
81
81
|
return defaultAudioDevice;
|
|
82
82
|
}
|
|
83
83
|
/**
|
|
84
84
|
* Resolves the default audio input device.
|
|
85
85
|
* @returns
|
|
86
86
|
*/
|
|
87
|
-
export async function
|
|
88
|
-
Debug.
|
|
87
|
+
export async function resolveDefaultAudioInputDevice(init) {
|
|
88
|
+
Debug.log("Attempting to resolve default audio output device...");
|
|
89
89
|
const audioDeviceInfos = [];
|
|
90
90
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
91
91
|
for (let device of devices)
|
|
92
92
|
(device.kind === "audioinput" && device.deviceId == "default")
|
|
93
93
|
&& audioDeviceInfos.push(device);
|
|
94
|
-
devices.length === 0 && Debug.
|
|
94
|
+
devices.length === 0 && Debug.warn("No default audio device found.", [], WarningCodes.NO_DEFAULT_AUDIO_DEVICE_FOUND);
|
|
95
95
|
const defaultAudioDevice = devices.length === 0 ? null : new AudioDevice(audioDeviceInfos[0]);
|
|
96
96
|
if (!defaultAudioDevice)
|
|
97
97
|
return null;
|
|
98
|
-
await
|
|
98
|
+
await loadWorkletOnAudioDevice(defaultAudioDevice, init.workletBlobUrl);
|
|
99
99
|
return defaultAudioDevice;
|
|
100
100
|
}
|
|
101
101
|
/**
|
|
@@ -104,19 +104,19 @@ export async function ResolveDefaultAudioInputDevice(init) {
|
|
|
104
104
|
* @param options
|
|
105
105
|
* @returns
|
|
106
106
|
*/
|
|
107
|
-
export async function
|
|
107
|
+
export async function loadAudioSource(path, options = { allowForeignFileTypes: false }) {
|
|
108
108
|
const extension = mime.getType(path);
|
|
109
109
|
if (!extension && !options.allowForeignFileTypes) {
|
|
110
|
-
Debug.
|
|
110
|
+
Debug.error("The file type of the specified file could not be identified.", [
|
|
111
111
|
`Set allowForeignFileTypes to true in the properties to allow foreign or unknown file types.`
|
|
112
112
|
], ErrorCodes.NO_FILE_TYPE_FOUND);
|
|
113
113
|
return null;
|
|
114
114
|
}
|
|
115
115
|
if (!SUPPORTED_FILE_TYPES.includes(extension))
|
|
116
|
-
Debug.
|
|
116
|
+
Debug.warn("The file type of the specified file is unknown and possibly unknown, but will be used anyways.");
|
|
117
117
|
const file = await fetch(path, { method: "get" });
|
|
118
118
|
if (file.status !== 200) {
|
|
119
|
-
Debug.
|
|
119
|
+
Debug.error("The specified file could not be loaded.", [
|
|
120
120
|
`Received status code: ${file.status}.`
|
|
121
121
|
], ErrorCodes.PATH_TO_FILE_NOT_FOUND);
|
|
122
122
|
return null;
|
|
@@ -133,7 +133,7 @@ export async function LoadAudioSource(path, options = { allowForeignFileTypes: f
|
|
|
133
133
|
/**
|
|
134
134
|
* Loads an audio file from a blob.
|
|
135
135
|
*/
|
|
136
|
-
export async function
|
|
136
|
+
export async function loadAudioSourceFromBlob(blob) {
|
|
137
137
|
const tempContext = new AudioContext(), arrayBuffer = await blob.arrayBuffer();
|
|
138
138
|
const audioBuffer = await tempContext.decodeAudioData(arrayBuffer);
|
|
139
139
|
return {
|
|
@@ -142,27 +142,27 @@ export async function LoadAudioSourceFromBlob(blob) {
|
|
|
142
142
|
audioBuffer, arrayBuffer
|
|
143
143
|
};
|
|
144
144
|
}
|
|
145
|
-
export function
|
|
145
|
+
export function constructProcessorWorklet(code) {
|
|
146
146
|
const blob = new Blob([code], {
|
|
147
147
|
type: "application/javascript"
|
|
148
148
|
});
|
|
149
149
|
return URL.createObjectURL(blob);
|
|
150
150
|
}
|
|
151
|
-
export async function
|
|
152
|
-
Debug.
|
|
151
|
+
export async function loadWorkletOnAudioDevice(audioDevice, workletBlobUrl) {
|
|
152
|
+
Debug.log("Loading worklet modules on master channel...", [`Channel ID: ${audioDevice.id}`]);
|
|
153
153
|
const context = audioDevice.context, start = Date.now();
|
|
154
154
|
await context.audioWorklet.addModule(workletBlobUrl);
|
|
155
155
|
const end = Date.now(), difference = end - start;
|
|
156
|
-
Debug.
|
|
156
|
+
Debug.success("Succesfully loaded audio processor worklets into master channel.", [
|
|
157
157
|
`Executed in ${difference}ms.`,
|
|
158
158
|
]);
|
|
159
159
|
return true;
|
|
160
160
|
}
|
|
161
|
-
export function
|
|
161
|
+
export function sendMessageToWorklet(node, commandId, data) {
|
|
162
162
|
if (!node)
|
|
163
163
|
return false;
|
|
164
164
|
if (typeof data === "number" && !Number.isFinite(data)) {
|
|
165
|
-
Debug.
|
|
165
|
+
Debug.warn("Refusing to send non-finite numeric value to AudioWorkletNode.", [
|
|
166
166
|
`Command: ${String(commandId)}`,
|
|
167
167
|
`Value: ${String(data)}`
|
|
168
168
|
]);
|
|
@@ -171,39 +171,25 @@ export function SendMessageToWorklet(node, commandId, data) {
|
|
|
171
171
|
node.port.postMessage({ commandId, data });
|
|
172
172
|
return true;
|
|
173
173
|
}
|
|
174
|
-
export function
|
|
174
|
+
export function isFiniteNumber(value) {
|
|
175
175
|
return typeof value === "number" && Number.isFinite(value);
|
|
176
176
|
}
|
|
177
|
-
export function
|
|
178
|
-
return
|
|
177
|
+
export function coerceFiniteNumber(value, fallback) {
|
|
178
|
+
return isFiniteNumber(value) ? value : fallback;
|
|
179
179
|
}
|
|
180
|
-
export function
|
|
181
|
-
if (!compiledWebAssemblyModule)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
},
|
|
196
|
-
processorOptions: {
|
|
197
|
-
module: compiledWebAssemblyModule
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
catch (err) {
|
|
202
|
-
Debug.Error("Failed to create audio worklet node.", [
|
|
203
|
-
`Request audio worklet node: ${name}.`,
|
|
204
|
-
"Make sure you called InitializeDspPipeline/InitializeDpsPipeline and loaded the worklet module on the same AudioContext.",
|
|
205
|
-
String(err)
|
|
206
|
-
]);
|
|
207
|
-
return null;
|
|
208
|
-
}
|
|
180
|
+
export function createAudioWorkletNode(context, name, data) {
|
|
181
|
+
if (!compiledWebAssemblyModule)
|
|
182
|
+
throw new Error("Coult not create audio worklet node. WebAssembly has not been compiled yet.");
|
|
183
|
+
return new AudioWorkletNode(context, name, {
|
|
184
|
+
numberOfInputs: 1,
|
|
185
|
+
numberOfOutputs: 1,
|
|
186
|
+
outputChannelCount: [2],
|
|
187
|
+
parameterData: {
|
|
188
|
+
...data,
|
|
189
|
+
sampleRate: context.sampleRate
|
|
190
|
+
},
|
|
191
|
+
processorOptions: {
|
|
192
|
+
module: compiledWebAssemblyModule
|
|
193
|
+
}
|
|
194
|
+
});
|
|
209
195
|
}
|
|
@@ -8,7 +8,7 @@ export async function LoadWebAssemblyModule(path) {
|
|
|
8
8
|
compiledWebAssemblyModule = module;
|
|
9
9
|
resolve(module);
|
|
10
10
|
}).catch(function (error) {
|
|
11
|
-
Debug.
|
|
11
|
+
Debug.error("Failed to load WebAssembly module from path: " + path, [
|
|
12
12
|
"Make sure the path is correct and the server is serving the .wasm file with the correct MIME type (application/wasm).",
|
|
13
13
|
"Error details: " + error.message
|
|
14
14
|
], ErrorCodes.WASM_COMPILATION_ERROR);
|
package/lib/src/console-codes.ts
CHANGED
|
@@ -19,7 +19,8 @@ export 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
|
|
|
25
26
|
export enum WarningCodes {
|