react-native-audio-api
Version:
react-native-audio-api provides system for controlling audio in React Native environment compatible with Web Audio API specification
120 lines (100 loc) • 3.37 kB
text/typescript
import { NativeAudioAPIModule } from '../specs';
import type {
WorkletRuntime,
IAudioAPIModule,
IWorkletsModule,
} from './ModuleInterfaces';
import { AudioApiError } from '../errors';
import semverGte from 'semver/functions/gte';
class AudioAPIModule implements IAudioAPIModule {
#workletsModule_: IWorkletsModule | null = null;
#canUseWorklets_ = false;
#workletsVersion = 'unknown';
#workletsAvailable_ = false;
private static readonly MIN_WORKLETS_VERSION = '0.6.0';
constructor() {
// Important! Verify and import worklets first
// otherwise the native module installation might crash
// if react-native-worklets is not imported before audio-api
this.#verifyWorklets();
if (this.#verifyInstallation()) {
return;
}
if (!NativeAudioAPIModule) {
throw new AudioApiError(
`Failed to install react-native-audio-api: The native module could not be found.`
);
}
NativeAudioAPIModule.install();
}
#verifyWorklets(): boolean {
try {
const workletsPackage = require('react-native-worklets');
const workletsPackageJson = require('react-native-worklets/package.json');
this.#workletsVersion = workletsPackageJson.version;
this.#workletsAvailable_ = true;
this.#canUseWorklets_ = semverGte(
this.#workletsVersion,
AudioAPIModule.MIN_WORKLETS_VERSION
);
if (this.#canUseWorklets_) {
this.#workletsModule_ = workletsPackage;
}
return this.#canUseWorklets_;
} catch {
this.#canUseWorklets_ = false;
return false;
}
}
#verifyInstallation(): boolean {
return (
globalThis.createAudioContext != null &&
globalThis.createOfflineAudioContext != null &&
globalThis.createAudioRecorder != null &&
globalThis.createAudioBuffer != null &&
globalThis.createAudioDecoder != null &&
globalThis.createAudioFileUtils != null &&
globalThis.AudioEventEmitter != null
);
}
get workletsModule(): IWorkletsModule | null {
return this.#workletsModule_;
}
/**
* Indicates whether react-native-worklets are installed in matching version,
* for usage with react-native-audio-api.
*/
get canUseWorklets(): boolean {
return this.#canUseWorklets_;
}
/** Returns the installed worklets version or 'unknown'. */
get workletsVersion(): string {
return this.#workletsVersion;
}
/**
* Indicates whether react-native-worklets are installed, regardless of
* version support. Useful for asserting compatibility.
*/
get areWorkletsAvailable(): boolean {
return this.#workletsAvailable_;
}
/**
* Indicates whether the installed react-native-worklets version is supported.
* Useful for asserting compatibility.
*/
get isWorkletsVersionSupported(): boolean {
// Note: if areWorkletsAvailable is true, canUseWorklets is equivalent to version check
return this.#canUseWorklets_;
}
/** Returns the range of supported worklets versions. */
get supportedWorkletsVersion(): string[] {
return [`>=${AudioAPIModule.MIN_WORKLETS_VERSION}`];
}
public createAudioRuntime(): WorkletRuntime | null {
if (!this.#canUseWorklets_) {
return null;
}
return this.#workletsModule_!.createWorkletRuntime('AudioWorkletRuntime');
}
}
export default new AudioAPIModule();