@fluex/fluexgl-dsp 0.1.3 → 0.2.1
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 +86 -86
- package/lib/dist/console-codes.d.ts +13 -13
- package/lib/dist/console-codes.js +16 -16
- package/lib/dist/core/classes/AudioClip.d.ts +67 -62
- package/lib/dist/core/classes/AudioClip.d.ts.map +1 -1
- package/lib/dist/core/classes/AudioClip.js +406 -386
- package/lib/dist/core/classes/AudioDevice.d.ts +12 -12
- package/lib/dist/core/classes/AudioDevice.js +30 -30
- package/lib/dist/core/classes/Channel.d.ts +41 -29
- package/lib/dist/core/classes/Channel.d.ts.map +1 -1
- package/lib/dist/core/classes/Channel.js +210 -144
- package/lib/dist/core/classes/DpsPipeline.d.ts +59 -59
- package/lib/dist/core/classes/DpsPipeline.js +115 -115
- package/lib/dist/core/classes/Effector.d.ts +8 -11
- package/lib/dist/core/classes/Effector.d.ts.map +1 -1
- package/lib/dist/core/classes/Effector.js +8 -20
- package/lib/dist/core/classes/Master.d.ts +11 -11
- package/lib/dist/core/classes/Master.js +35 -35
- package/lib/dist/core/exports.d.ts +6 -6
- package/lib/dist/core/exports.js +6 -6
- package/lib/dist/effects/classes/Chorus.d.ts +20 -2
- package/lib/dist/effects/classes/Chorus.d.ts.map +1 -1
- package/lib/dist/effects/classes/Chorus.js +85 -2
- package/lib/dist/effects/classes/Distortion.d.ts +6 -2
- package/lib/dist/effects/classes/Distortion.d.ts.map +1 -1
- package/lib/dist/effects/classes/Distortion.js +9 -2
- package/lib/dist/effects/classes/Equalizer.d.ts +2 -2
- package/lib/dist/effects/classes/Equalizer.js +2 -2
- package/lib/dist/effects/classes/Filter.d.ts +2 -2
- package/lib/dist/effects/classes/Filter.js +2 -2
- package/lib/dist/effects/classes/Limiter.d.ts +2 -2
- package/lib/dist/effects/classes/Limiter.js +2 -2
- package/lib/dist/effects/classes/Saturation.d.ts +2 -2
- package/lib/dist/effects/classes/Saturation.d.ts.map +1 -1
- package/lib/dist/effects/classes/Saturation.js +2 -2
- package/lib/dist/effects/classes/SoftClip.d.ts +9 -7
- package/lib/dist/effects/classes/SoftClip.d.ts.map +1 -1
- package/lib/dist/effects/classes/SoftClip.js +39 -38
- package/lib/dist/effects/classes/StereoPanner.d.ts +3 -2
- package/lib/dist/effects/classes/StereoPanner.d.ts.map +1 -1
- package/lib/dist/effects/classes/StereoPanner.js +3 -2
- package/lib/dist/effects/classes/compressors/Compressor.d.ts +2 -2
- package/lib/dist/effects/classes/compressors/Compressor.js +2 -2
- package/lib/dist/effects/classes/compressors/MultibandCompressor.d.ts +2 -2
- package/lib/dist/effects/classes/compressors/MultibandCompressor.js +2 -2
- package/lib/dist/effects/classes/delays/AdvancedDelay.d.ts +2 -2
- package/lib/dist/effects/classes/delays/AdvancedDelay.js +2 -2
- package/lib/dist/effects/classes/delays/MonoDelay.d.ts +2 -2
- package/lib/dist/effects/classes/delays/MonoDelay.js +2 -2
- package/lib/dist/effects/classes/delays/PingPongDelay.d.ts +2 -2
- package/lib/dist/effects/classes/delays/PingPongDelay.js +2 -2
- package/lib/dist/effects/classes/delays/StereoDelay.d.ts +2 -2
- package/lib/dist/effects/classes/delays/StereoDelay.js +2 -2
- package/lib/dist/effects/classes/reverbs/ChamberReverb.d.ts +2 -2
- package/lib/dist/effects/classes/reverbs/ChamberReverb.js +2 -2
- package/lib/dist/effects/classes/reverbs/ConvolverReverb.d.ts +2 -2
- package/lib/dist/effects/classes/reverbs/ConvolverReverb.js +2 -2
- package/lib/dist/effects/classes/reverbs/GenericReverb.d.ts +2 -2
- package/lib/dist/effects/classes/reverbs/GenericReverb.js +2 -2
- package/lib/dist/effects/classes/reverbs/HallReverb.d.ts +2 -2
- package/lib/dist/effects/classes/reverbs/HallReverb.js +2 -2
- package/lib/dist/effects/classes/reverbs/RoomReverb.d.ts +2 -2
- package/lib/dist/effects/classes/reverbs/RoomReverb.js +2 -2
- package/lib/dist/effects/exports.d.ts +19 -19
- package/lib/dist/effects/exports.js +19 -19
- package/lib/dist/index.d.ts +12 -12
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +28 -28
- package/lib/dist/typings.d.ts +66 -59
- package/lib/dist/typings.d.ts.map +1 -1
- package/lib/dist/typings.js +1 -1
- package/lib/dist/utilities/constants.d.ts +1 -1
- package/lib/dist/utilities/constants.js +9 -9
- package/lib/dist/utilities/debugger.d.ts +7 -7
- package/lib/dist/utilities/debugger.js +49 -49
- package/lib/dist/utilities/helpers.d.ts +44 -40
- package/lib/dist/utilities/helpers.d.ts.map +1 -1
- package/lib/dist/utilities/helpers.js +160 -143
- package/lib/dist/utilities/web-assembly.d.ts +3 -3
- package/lib/dist/utilities/web-assembly.d.ts.map +1 -1
- package/lib/dist/utilities/web-assembly.js +12 -12
- package/lib/src/console-codes.ts +15 -15
- package/lib/src/core/classes/AudioClip.ts +539 -539
- package/lib/src/core/classes/AudioDevice.ts +38 -38
- package/lib/src/core/classes/Channel.ts +288 -288
- package/lib/src/core/classes/DpsPipeline.ts +152 -152
- package/lib/src/core/classes/Effector.ts +11 -12
- package/lib/src/core/classes/Master.ts +49 -49
- package/lib/src/core/exports.ts +5 -5
- package/lib/src/effects/classes/Chorus.ts +111 -111
- package/lib/src/effects/classes/Distortion.ts +13 -13
- package/lib/src/effects/classes/Saturation.ts +2 -2
- package/lib/src/effects/classes/SoftClip.ts +44 -44
- package/lib/src/effects/classes/StereoPanner.ts +2 -2
- package/lib/src/effects/exports.ts +22 -22
- package/lib/src/index.ts +93 -93
- package/lib/src/typings.ts +78 -78
- package/lib/src/utilities/constants.ts +8 -8
- package/lib/src/utilities/debugger.ts +65 -65
- package/lib/src/utilities/helpers.ts +237 -237
- package/lib/src/utilities/web-assembly.ts +12 -12
- package/package.json +51 -50
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import { FluexGLAudio } from "../index";
|
|
2
|
-
export var Debug;
|
|
3
|
-
(function (Debug) {
|
|
4
|
-
function Log(message, additionalDetails) {
|
|
5
|
-
if (!FluexGLAudio.options.debugger.showInfo)
|
|
6
|
-
return;
|
|
7
|
-
let outputString = `%c[INFO]: %c${message} %c`;
|
|
8
|
-
additionalDetails && additionalDetails.forEach(function (detail) {
|
|
9
|
-
outputString += `\n\u0009 > ${detail}`;
|
|
10
|
-
});
|
|
11
|
-
return console.log(outputString, "color: white;", "color: gray", "color: gray");
|
|
12
|
-
}
|
|
13
|
-
Debug.Log = Log;
|
|
14
|
-
function Success(message, additionalDetails) {
|
|
15
|
-
if (!FluexGLAudio.options.debugger.showInfo)
|
|
16
|
-
return;
|
|
17
|
-
let outputString = `%c[SUCCESS]: %c${message} %c`;
|
|
18
|
-
additionalDetails && additionalDetails.forEach(function (detail) {
|
|
19
|
-
outputString += `\n\u0009 > ${detail}`;
|
|
20
|
-
});
|
|
21
|
-
return console.log(outputString, "color: lime;", "color: white", "color: gray");
|
|
22
|
-
}
|
|
23
|
-
Debug.Success = Success;
|
|
24
|
-
function Warn(message, additionalDetails, warningCode) {
|
|
25
|
-
if (!FluexGLAudio.options.debugger.showWarnings)
|
|
26
|
-
return;
|
|
27
|
-
let outputString = `%c(${warningCode ? warningCode : "Unknown".toUpperCase()}) %c[WARNING]: %c${message} %c`;
|
|
28
|
-
(additionalDetails && additionalDetails !== null) && additionalDetails.forEach(function (detail) {
|
|
29
|
-
outputString += `\n\u0009 > ${detail}`;
|
|
30
|
-
});
|
|
31
|
-
return console.log(outputString, "color: gray", "color: yellow;", "color: white", "color: white; font-style: italic;");
|
|
32
|
-
}
|
|
33
|
-
Debug.Warn = Warn;
|
|
34
|
-
function Error(message, additionalDetails, errorCode) {
|
|
35
|
-
if (!FluexGLAudio.options.debugger.showErrors)
|
|
36
|
-
return;
|
|
37
|
-
let outputString = `%c(${errorCode ? errorCode : "Unknown".toUpperCase()}) %c[ERROR]: %c${message} %c`;
|
|
38
|
-
(additionalDetails && additionalDetails !== null) && additionalDetails.forEach(function (detail) {
|
|
39
|
-
outputString += `\n\u0009 > ${detail}`;
|
|
40
|
-
});
|
|
41
|
-
console.log(outputString, "color: red", "color: red;", "color: white", "color: white; font-style: italic;");
|
|
42
|
-
if (FluexGLAudio.options.debugger.breakOnError) {
|
|
43
|
-
for (let char of message)
|
|
44
|
-
outputString = outputString.replace("%c", "");
|
|
45
|
-
throw new window.Error(outputString);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
Debug.Error = Error;
|
|
49
|
-
})(Debug || (Debug = {}));
|
|
1
|
+
import { FluexGLAudio } from "../index";
|
|
2
|
+
export var Debug;
|
|
3
|
+
(function (Debug) {
|
|
4
|
+
function Log(message, additionalDetails) {
|
|
5
|
+
if (!FluexGLAudio.options.debugger.showInfo)
|
|
6
|
+
return;
|
|
7
|
+
let outputString = `%c[INFO]: %c${message} %c`;
|
|
8
|
+
additionalDetails && additionalDetails.forEach(function (detail) {
|
|
9
|
+
outputString += `\n\u0009 > ${detail}`;
|
|
10
|
+
});
|
|
11
|
+
return console.log(outputString, "color: white;", "color: gray", "color: gray");
|
|
12
|
+
}
|
|
13
|
+
Debug.Log = Log;
|
|
14
|
+
function Success(message, additionalDetails) {
|
|
15
|
+
if (!FluexGLAudio.options.debugger.showInfo)
|
|
16
|
+
return;
|
|
17
|
+
let outputString = `%c[SUCCESS]: %c${message} %c`;
|
|
18
|
+
additionalDetails && additionalDetails.forEach(function (detail) {
|
|
19
|
+
outputString += `\n\u0009 > ${detail}`;
|
|
20
|
+
});
|
|
21
|
+
return console.log(outputString, "color: lime;", "color: white", "color: gray");
|
|
22
|
+
}
|
|
23
|
+
Debug.Success = Success;
|
|
24
|
+
function Warn(message, additionalDetails, warningCode) {
|
|
25
|
+
if (!FluexGLAudio.options.debugger.showWarnings)
|
|
26
|
+
return;
|
|
27
|
+
let outputString = `%c(${warningCode ? warningCode : "Unknown".toUpperCase()}) %c[WARNING]: %c${message} %c`;
|
|
28
|
+
(additionalDetails && additionalDetails !== null) && additionalDetails.forEach(function (detail) {
|
|
29
|
+
outputString += `\n\u0009 > ${detail}`;
|
|
30
|
+
});
|
|
31
|
+
return console.log(outputString, "color: gray", "color: yellow;", "color: white", "color: white; font-style: italic;");
|
|
32
|
+
}
|
|
33
|
+
Debug.Warn = Warn;
|
|
34
|
+
function Error(message, additionalDetails, errorCode) {
|
|
35
|
+
if (!FluexGLAudio.options.debugger.showErrors)
|
|
36
|
+
return;
|
|
37
|
+
let outputString = `%c(${errorCode ? errorCode : "Unknown".toUpperCase()}) %c[ERROR]: %c${message} %c`;
|
|
38
|
+
(additionalDetails && additionalDetails !== null) && additionalDetails.forEach(function (detail) {
|
|
39
|
+
outputString += `\n\u0009 > ${detail}`;
|
|
40
|
+
});
|
|
41
|
+
console.log(outputString, "color: red", "color: red;", "color: white", "color: white; font-style: italic;");
|
|
42
|
+
if (FluexGLAudio.options.debugger.breakOnError) {
|
|
43
|
+
for (let char of message)
|
|
44
|
+
outputString = outputString.replace("%c", "");
|
|
45
|
+
throw new window.Error(outputString);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
Debug.Error = Error;
|
|
49
|
+
})(Debug || (Debug = {}));
|
|
@@ -1,41 +1,45 @@
|
|
|
1
|
-
import { AudioDevice } from "../core/classes/AudioDevice";
|
|
2
|
-
import { Master } from "../core/classes/Master";
|
|
3
|
-
import { LoadAudioSourceOptions, AudioSourceData, DspPipelineInitializationOptions, DspPipelineInitializationState } from "../typings";
|
|
4
|
-
/**
|
|
5
|
-
* Initializes the DSP pipeline by requesting audio permissions and initializing the WASM module.
|
|
6
|
-
* Very important to call this function and wait for it to complete before using any audio features.
|
|
7
|
-
*
|
|
8
|
-
* FluexGL DSP cannot be used without calling this function first.
|
|
9
|
-
* @returns
|
|
10
|
-
*/
|
|
11
|
-
export declare function InitializeDspPipeline(options: DspPipelineInitializationOptions): Promise<DspPipelineInitializationState | null>;
|
|
12
|
-
/**
|
|
13
|
-
* Resolves a list of available audio output devices.
|
|
14
|
-
* @returns
|
|
15
|
-
*/
|
|
16
|
-
export declare function ResolveAudioOutputDevices(): Promise<AudioDevice[]>;
|
|
17
|
-
/**
|
|
18
|
-
* Resolves a list of available audio input devices.
|
|
19
|
-
* @returns
|
|
20
|
-
*/
|
|
21
|
-
export declare function ResolveAudioInputDevices(): Promise<AudioDevice[]>;
|
|
22
|
-
/**
|
|
23
|
-
* Resolves the default audio output device.
|
|
24
|
-
* @returns
|
|
25
|
-
*/
|
|
26
|
-
export declare function ResolveDefaultAudioOutputDevice(init: DspPipelineInitializationState): Promise<AudioDevice | null>;
|
|
27
|
-
/**
|
|
28
|
-
* Resolves the default audio input device.
|
|
29
|
-
* @returns
|
|
30
|
-
*/
|
|
31
|
-
export declare function ResolveDefaultAudioInputDevice(): Promise<AudioDevice | null>;
|
|
32
|
-
/**
|
|
33
|
-
* Loads an audio source from a specified path.
|
|
34
|
-
* @param path
|
|
35
|
-
* @param options
|
|
36
|
-
* @returns
|
|
37
|
-
*/
|
|
38
|
-
export declare function LoadAudioSource(path: string, options?: Partial<LoadAudioSourceOptions>): Promise<AudioSourceData | null>;
|
|
39
|
-
|
|
40
|
-
|
|
1
|
+
import { AudioDevice } from "../core/classes/AudioDevice";
|
|
2
|
+
import { Master } from "../core/classes/Master";
|
|
3
|
+
import { LoadAudioSourceOptions, AudioSourceData, DspPipelineInitializationOptions, DspPipelineInitializationState } from "../typings";
|
|
4
|
+
/**
|
|
5
|
+
* Initializes the DSP pipeline by requesting audio permissions and initializing the WASM module.
|
|
6
|
+
* Very important to call this function and wait for it to complete before using any audio features.
|
|
7
|
+
*
|
|
8
|
+
* FluexGL DSP cannot be used without calling this function first.
|
|
9
|
+
* @returns
|
|
10
|
+
*/
|
|
11
|
+
export declare function InitializeDspPipeline(options: DspPipelineInitializationOptions): Promise<DspPipelineInitializationState | null>;
|
|
12
|
+
/**
|
|
13
|
+
* Resolves a list of available audio output devices.
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
export declare function ResolveAudioOutputDevices(): Promise<AudioDevice[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Resolves a list of available audio input devices.
|
|
19
|
+
* @returns
|
|
20
|
+
*/
|
|
21
|
+
export declare function ResolveAudioInputDevices(): Promise<AudioDevice[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Resolves the default audio output device.
|
|
24
|
+
* @returns
|
|
25
|
+
*/
|
|
26
|
+
export declare function ResolveDefaultAudioOutputDevice(init: DspPipelineInitializationState): Promise<AudioDevice | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Resolves the default audio input device.
|
|
29
|
+
* @returns
|
|
30
|
+
*/
|
|
31
|
+
export declare function ResolveDefaultAudioInputDevice(init: DspPipelineInitializationState): Promise<AudioDevice | null>;
|
|
32
|
+
/**
|
|
33
|
+
* Loads an audio source from a specified path.
|
|
34
|
+
* @param path
|
|
35
|
+
* @param options
|
|
36
|
+
* @returns
|
|
37
|
+
*/
|
|
38
|
+
export declare function LoadAudioSource(path: string, options?: Partial<LoadAudioSourceOptions>): Promise<AudioSourceData | null>;
|
|
39
|
+
/**
|
|
40
|
+
* Loads an audio file from a blob.
|
|
41
|
+
*/
|
|
42
|
+
export declare function LoadAudioSourceFromBlob(blob: Blob): Promise<AudioSourceData | null>;
|
|
43
|
+
export declare function ConstructProcessorWorklet(code: string): string;
|
|
44
|
+
export declare function LoadWorkletOnMasterChannel(master: Master, workletBlobUrl: string): Promise<boolean>;
|
|
41
45
|
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utilities/helpers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utilities/helpers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAahD,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,gCAAgC,EAAE,8BAA8B,EAAE,MAAM,YAAY,CAAC;AAEvI;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,gCAAgC,GAAG,OAAO,CAAC,8BAA8B,GAAG,IAAI,CAAC,CAwCrI;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAUxE;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAUvE;AAED;;;GAGG;AACH,wBAAsB,+BAA+B,CAAC,IAAI,EAAE,8BAA8B,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAmBvH;AAED;;;GAGG;AACH,wBAAsB,8BAA8B,CAAC,IAAI,EAAE,8BAA8B,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAmBtH;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,OAAO,CAAC,sBAAsB,CAAoC,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAoChK;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAYzF;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO9D;AAED,wBAAsB,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,oBAgBtF"}
|
|
@@ -1,143 +1,160 @@
|
|
|
1
|
-
import mime from "mime";
|
|
2
|
-
import { v4 } from "uuid";
|
|
3
|
-
import { AudioDevice } from "../core/classes/AudioDevice";
|
|
4
|
-
import { Debug } from "./debugger";
|
|
5
|
-
import { SUPPORTED_FILE_TYPES } from "./constants";
|
|
6
|
-
import { LoadWebAssemblyModule } from "./web-assembly";
|
|
7
|
-
import { ErrorCodes, WarningCodes } from "../console-codes";
|
|
8
|
-
/**
|
|
9
|
-
* Initializes the DSP pipeline by requesting audio permissions and initializing the WASM module.
|
|
10
|
-
* Very important to call this function and wait for it to complete before using any audio features.
|
|
11
|
-
*
|
|
12
|
-
* FluexGL DSP cannot be used without calling this function first.
|
|
13
|
-
* @returns
|
|
14
|
-
*/
|
|
15
|
-
export async function InitializeDspPipeline(options) {
|
|
16
|
-
Debug.Log("Attempting to initialize DSP pipeline...");
|
|
17
|
-
const start = Date.now();
|
|
18
|
-
let initialized = true;
|
|
19
|
-
try {
|
|
20
|
-
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
21
|
-
Debug.Log(`Found ${stream.getTracks().length} media stream tracks.`);
|
|
22
|
-
stream.getTracks().forEach(function (track) {
|
|
23
|
-
track.stop();
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
catch (err) {
|
|
27
|
-
initialized = false;
|
|
28
|
-
Debug.Error("Permission to access media devices has not been granted.", [
|
|
29
|
-
"Make sure the user has granted FluentGL permission to access media devices."
|
|
30
|
-
], ErrorCodes.NO_CONTEXT_PERMISSION);
|
|
31
|
-
}
|
|
32
|
-
await LoadWebAssemblyModule(options.pathToWasm);
|
|
33
|
-
const workletFileRequest = await fetch(options.pathToWorklet);
|
|
34
|
-
const textContent = await workletFileRequest.text();
|
|
35
|
-
const blobUrl = ConstructProcessorWorklet(textContent);
|
|
36
|
-
const end = Date.now(), difference = end - start;
|
|
37
|
-
Debug.Success(`Succesfully initialized DSP pipeline within ${difference}ms.`);
|
|
38
|
-
return {
|
|
39
|
-
success: true,
|
|
40
|
-
workletBlobUrl: blobUrl
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Resolves a list of available audio output devices.
|
|
45
|
-
* @returns
|
|
46
|
-
*/
|
|
47
|
-
export async function ResolveAudioOutputDevices() {
|
|
48
|
-
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
49
|
-
const audioDevices = [];
|
|
50
|
-
for (let device of devices)
|
|
51
|
-
device.kind === "audiooutput" && audioDevices.push(new AudioDevice(device));
|
|
52
|
-
return audioDevices;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Resolves a list of available audio input devices.
|
|
56
|
-
* @returns
|
|
57
|
-
*/
|
|
58
|
-
export async function ResolveAudioInputDevices() {
|
|
59
|
-
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
60
|
-
const audioDevices = [];
|
|
61
|
-
for (let device of devices)
|
|
62
|
-
device.kind === "audioinput" && audioDevices.push(new AudioDevice(device));
|
|
63
|
-
return audioDevices;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Resolves the default audio output device.
|
|
67
|
-
* @returns
|
|
68
|
-
*/
|
|
69
|
-
export async function ResolveDefaultAudioOutputDevice(init) {
|
|
70
|
-
Debug.Log("Attempting to resolve default audio output device...");
|
|
71
|
-
const audioDeviceInfos = [];
|
|
72
|
-
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
73
|
-
for (let device of devices)
|
|
74
|
-
(device.kind === "audiooutput" && device.deviceId == "default")
|
|
75
|
-
&& audioDeviceInfos.push(device);
|
|
76
|
-
devices.length === 0 && Debug.Warn("No default audio device found.", [], WarningCodes.NO_DEFAULT_AUDIO_DEVICE_FOUND);
|
|
77
|
-
const defaultAudioDevice = devices.length === 0 ? null : new AudioDevice(audioDeviceInfos[0]);
|
|
78
|
-
if (!defaultAudioDevice)
|
|
79
|
-
return null;
|
|
80
|
-
await LoadWorkletOnMasterChannel(defaultAudioDevice.masterChannel, init.workletBlobUrl);
|
|
81
|
-
return defaultAudioDevice;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Resolves the default audio input device.
|
|
85
|
-
* @returns
|
|
86
|
-
*/
|
|
87
|
-
export async function ResolveDefaultAudioInputDevice() {
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
await
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
1
|
+
import mime from "mime";
|
|
2
|
+
import { v4 } from "uuid";
|
|
3
|
+
import { AudioDevice } from "../core/classes/AudioDevice";
|
|
4
|
+
import { Debug } from "./debugger";
|
|
5
|
+
import { SUPPORTED_FILE_TYPES } from "./constants";
|
|
6
|
+
import { LoadWebAssemblyModule } from "./web-assembly";
|
|
7
|
+
import { ErrorCodes, WarningCodes } from "../console-codes";
|
|
8
|
+
/**
|
|
9
|
+
* Initializes the DSP pipeline by requesting audio permissions and initializing the WASM module.
|
|
10
|
+
* Very important to call this function and wait for it to complete before using any audio features.
|
|
11
|
+
*
|
|
12
|
+
* FluexGL DSP cannot be used without calling this function first.
|
|
13
|
+
* @returns
|
|
14
|
+
*/
|
|
15
|
+
export async function InitializeDspPipeline(options) {
|
|
16
|
+
Debug.Log("Attempting to initialize DSP pipeline...");
|
|
17
|
+
const start = Date.now();
|
|
18
|
+
let initialized = true;
|
|
19
|
+
try {
|
|
20
|
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
21
|
+
Debug.Log(`Found ${stream.getTracks().length} media stream tracks.`);
|
|
22
|
+
stream.getTracks().forEach(function (track) {
|
|
23
|
+
track.stop();
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
initialized = false;
|
|
28
|
+
Debug.Error("Permission to access media devices has not been granted.", [
|
|
29
|
+
"Make sure the user has granted FluentGL permission to access media devices."
|
|
30
|
+
], ErrorCodes.NO_CONTEXT_PERMISSION);
|
|
31
|
+
}
|
|
32
|
+
await LoadWebAssemblyModule(options.pathToWasm);
|
|
33
|
+
const workletFileRequest = await fetch(options.pathToWorklet);
|
|
34
|
+
const textContent = await workletFileRequest.text();
|
|
35
|
+
const blobUrl = ConstructProcessorWorklet(textContent);
|
|
36
|
+
const end = Date.now(), difference = end - start;
|
|
37
|
+
Debug.Success(`Succesfully initialized DSP pipeline within ${difference}ms.`);
|
|
38
|
+
return {
|
|
39
|
+
success: true,
|
|
40
|
+
workletBlobUrl: blobUrl
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Resolves a list of available audio output devices.
|
|
45
|
+
* @returns
|
|
46
|
+
*/
|
|
47
|
+
export async function ResolveAudioOutputDevices() {
|
|
48
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
49
|
+
const audioDevices = [];
|
|
50
|
+
for (let device of devices)
|
|
51
|
+
device.kind === "audiooutput" && audioDevices.push(new AudioDevice(device));
|
|
52
|
+
return audioDevices;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolves a list of available audio input devices.
|
|
56
|
+
* @returns
|
|
57
|
+
*/
|
|
58
|
+
export async function ResolveAudioInputDevices() {
|
|
59
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
60
|
+
const audioDevices = [];
|
|
61
|
+
for (let device of devices)
|
|
62
|
+
device.kind === "audioinput" && audioDevices.push(new AudioDevice(device));
|
|
63
|
+
return audioDevices;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Resolves the default audio output device.
|
|
67
|
+
* @returns
|
|
68
|
+
*/
|
|
69
|
+
export async function ResolveDefaultAudioOutputDevice(init) {
|
|
70
|
+
Debug.Log("Attempting to resolve default audio output device...");
|
|
71
|
+
const audioDeviceInfos = [];
|
|
72
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
73
|
+
for (let device of devices)
|
|
74
|
+
(device.kind === "audiooutput" && device.deviceId == "default")
|
|
75
|
+
&& audioDeviceInfos.push(device);
|
|
76
|
+
devices.length === 0 && Debug.Warn("No default audio device found.", [], WarningCodes.NO_DEFAULT_AUDIO_DEVICE_FOUND);
|
|
77
|
+
const defaultAudioDevice = devices.length === 0 ? null : new AudioDevice(audioDeviceInfos[0]);
|
|
78
|
+
if (!defaultAudioDevice)
|
|
79
|
+
return null;
|
|
80
|
+
await LoadWorkletOnMasterChannel(defaultAudioDevice.masterChannel, init.workletBlobUrl);
|
|
81
|
+
return defaultAudioDevice;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Resolves the default audio input device.
|
|
85
|
+
* @returns
|
|
86
|
+
*/
|
|
87
|
+
export async function ResolveDefaultAudioInputDevice(init) {
|
|
88
|
+
Debug.Log("Attempting to resolve default audio output device...");
|
|
89
|
+
const audioDeviceInfos = [];
|
|
90
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
91
|
+
for (let device of devices)
|
|
92
|
+
(device.kind === "audioinput" && device.deviceId == "default")
|
|
93
|
+
&& audioDeviceInfos.push(device);
|
|
94
|
+
devices.length === 0 && Debug.Warn("No default audio device found.", [], WarningCodes.NO_DEFAULT_AUDIO_DEVICE_FOUND);
|
|
95
|
+
const defaultAudioDevice = devices.length === 0 ? null : new AudioDevice(audioDeviceInfos[0]);
|
|
96
|
+
if (!defaultAudioDevice)
|
|
97
|
+
return null;
|
|
98
|
+
await LoadWorkletOnMasterChannel(defaultAudioDevice.masterChannel, init.workletBlobUrl);
|
|
99
|
+
return defaultAudioDevice;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Loads an audio source from a specified path.
|
|
103
|
+
* @param path
|
|
104
|
+
* @param options
|
|
105
|
+
* @returns
|
|
106
|
+
*/
|
|
107
|
+
export async function LoadAudioSource(path, options = { allowForeignFileTypes: false }) {
|
|
108
|
+
const extension = mime.getType(path);
|
|
109
|
+
if (!extension && !options.allowForeignFileTypes) {
|
|
110
|
+
Debug.Error("The file type of the specified file could not be identified.", [
|
|
111
|
+
`Set allowForeignFileTypes to true in the properties to allow foreign or unknown file types.`
|
|
112
|
+
], ErrorCodes.NO_FILE_TYPE_FOUND);
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
if (!SUPPORTED_FILE_TYPES.includes(extension))
|
|
116
|
+
Debug.Warn("The file type of the specified file is unknown and possibly unknown, but will be used anyways.");
|
|
117
|
+
const file = await fetch(path, { method: "get" });
|
|
118
|
+
if (file.status !== 200) {
|
|
119
|
+
Debug.Error("The specified file could not be loaded.", [
|
|
120
|
+
`Received status code: ${file.status}.`
|
|
121
|
+
], ErrorCodes.PATH_TO_FILE_NOT_FOUND);
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const tempContext = new AudioContext(), arrayBuffer = await file.arrayBuffer(), audioBuffer = await tempContext.decodeAudioData(arrayBuffer);
|
|
125
|
+
// IMPORTANT!
|
|
126
|
+
tempContext.close();
|
|
127
|
+
return {
|
|
128
|
+
arrayBuffer, audioBuffer,
|
|
129
|
+
id: v4(),
|
|
130
|
+
timestamp: Date.now()
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Loads an audio file from a blob.
|
|
135
|
+
*/
|
|
136
|
+
export async function LoadAudioSourceFromBlob(blob) {
|
|
137
|
+
const tempContext = new AudioContext(), arrayBuffer = await blob.arrayBuffer();
|
|
138
|
+
const audioBuffer = await tempContext.decodeAudioData(arrayBuffer);
|
|
139
|
+
return {
|
|
140
|
+
id: v4(),
|
|
141
|
+
timestamp: Date.now(),
|
|
142
|
+
audioBuffer, arrayBuffer
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
export function ConstructProcessorWorklet(code) {
|
|
146
|
+
const blob = new Blob([code], {
|
|
147
|
+
type: "application/javascript"
|
|
148
|
+
});
|
|
149
|
+
return URL.createObjectURL(blob);
|
|
150
|
+
}
|
|
151
|
+
export async function LoadWorkletOnMasterChannel(master, workletBlobUrl) {
|
|
152
|
+
Debug.Log("Loading worklet modules on master channel...", [`Channel ID: ${master.id}`]);
|
|
153
|
+
const context = master.context, start = Date.now();
|
|
154
|
+
await context.audioWorklet.addModule(workletBlobUrl);
|
|
155
|
+
const end = Date.now(), difference = end - start;
|
|
156
|
+
Debug.Success("Succesfully loaded audio processor worklets into master channel.", [
|
|
157
|
+
`Executed in ${difference}ms.`,
|
|
158
|
+
]);
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare let hasInitializedWasm: boolean;
|
|
2
|
-
export declare let compiledWebAssemblyModule: WebAssembly.Module | null;
|
|
3
|
-
export declare function LoadWebAssemblyModule(path: string): Promise<WebAssembly.Module>;
|
|
1
|
+
export declare let hasInitializedWasm: boolean;
|
|
2
|
+
export declare let compiledWebAssemblyModule: WebAssembly.Module | null;
|
|
3
|
+
export declare function LoadWebAssemblyModule(path: string): Promise<WebAssembly.Module>;
|
|
4
4
|
//# sourceMappingURL=web-assembly.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-assembly.d.ts","sourceRoot":"","sources":["../../src/utilities/web-assembly.ts"],"names":[],"mappings":"AAAA,eAAO,IAAI,kBAAkB,EAAE,OAAe,CAAC;AAC/C,eAAO,IAAI,yBAAyB,EAAE,WAAW,CAAC,MAAM,GAAG,IAAW,CAAC;AAEvE,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"web-assembly.d.ts","sourceRoot":"","sources":["../../src/utilities/web-assembly.ts"],"names":[],"mappings":"AAAA,eAAO,IAAI,kBAAkB,EAAE,OAAe,CAAC;AAC/C,eAAO,IAAI,yBAAyB,EAAE,WAAW,CAAC,MAAM,GAAG,IAAW,CAAC;AAEvE,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CASrF"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
export let hasInitializedWasm = false;
|
|
2
|
-
export let compiledWebAssemblyModule = null;
|
|
3
|
-
export async function LoadWebAssemblyModule(path) {
|
|
4
|
-
return new Promise(function (resolve, reject) {
|
|
5
|
-
WebAssembly.compileStreaming(fetch(path)).then(function (module) {
|
|
6
|
-
compiledWebAssemblyModule = module;
|
|
7
|
-
resolve(module);
|
|
8
|
-
}).catch(function (error) {
|
|
9
|
-
reject(error);
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
}
|
|
1
|
+
export let hasInitializedWasm = false;
|
|
2
|
+
export let compiledWebAssemblyModule = null;
|
|
3
|
+
export async function LoadWebAssemblyModule(path) {
|
|
4
|
+
return new Promise(function (resolve, reject) {
|
|
5
|
+
WebAssembly.compileStreaming(fetch(path)).then(function (module) {
|
|
6
|
+
compiledWebAssemblyModule = module;
|
|
7
|
+
resolve(module);
|
|
8
|
+
}).catch(function (error) {
|
|
9
|
+
reject(error);
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
}
|
package/lib/src/console-codes.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
export enum ErrorCodes {
|
|
2
|
-
NO_CONTEXT_PERMISSION = "FLUEXGL@AUDIO_ERROR_0001",
|
|
3
|
-
NO_FILE_TYPE_FOUND = "FLUEXGL@AUDIO_ERROR_0002",
|
|
4
|
-
PATH_TO_FILE_NOT_FOUND = "FLUEXGL@AUDIO_ERROR_0003",
|
|
5
|
-
SAME_MASTER_CHANNEL = "FLUEXGL@AUDIO_ERROR_0004",
|
|
6
|
-
WASM_MODULE_INITIALIZATION_FAILED = "FLUEXGL@AUDIO_ERROR_0005",
|
|
7
|
-
PATH_TO_WASM_FILE_NOT_FOUND = "FLUEXGL@AUDIO_ERROR_0006"
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export enum WarningCodes {
|
|
11
|
-
NO_DEFAULT_AUDIO_DEVICE_FOUND = "FLUEXGL@AUDIO_WARNING_0001"
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export enum SuccessCodes {
|
|
15
|
-
|
|
1
|
+
export enum ErrorCodes {
|
|
2
|
+
NO_CONTEXT_PERMISSION = "FLUEXGL@AUDIO_ERROR_0001",
|
|
3
|
+
NO_FILE_TYPE_FOUND = "FLUEXGL@AUDIO_ERROR_0002",
|
|
4
|
+
PATH_TO_FILE_NOT_FOUND = "FLUEXGL@AUDIO_ERROR_0003",
|
|
5
|
+
SAME_MASTER_CHANNEL = "FLUEXGL@AUDIO_ERROR_0004",
|
|
6
|
+
WASM_MODULE_INITIALIZATION_FAILED = "FLUEXGL@AUDIO_ERROR_0005",
|
|
7
|
+
PATH_TO_WASM_FILE_NOT_FOUND = "FLUEXGL@AUDIO_ERROR_0006"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export enum WarningCodes {
|
|
11
|
+
NO_DEFAULT_AUDIO_DEVICE_FOUND = "FLUEXGL@AUDIO_WARNING_0001"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export enum SuccessCodes {
|
|
15
|
+
|
|
16
16
|
}
|