react-native-audio-api
Version:
react-native-audio-api provides system for controlling audio in React Native environment compatible with Web Audio API specification
155 lines (130 loc) • 4.52 kB
text/typescript
import { IBaseAudioContext } from '../interfaces';
import {
ContextState,
PeriodicWaveConstraints,
AudioBufferSourceNodeOptions,
} from '../types';
import AudioDestinationNode from './AudioDestinationNode';
import OscillatorNode from './OscillatorNode';
import GainNode from './GainNode';
import StereoPannerNode from './StereoPannerNode';
import BiquadFilterNode from './BiquadFilterNode';
import AudioBufferSourceNode from './AudioBufferSourceNode';
import AudioBuffer from './AudioBuffer';
import PeriodicWave from './PeriodicWave';
import AnalyserNode from './AnalyserNode';
import AudioBufferQueueSourceNode from './AudioBufferQueueSourceNode';
import { InvalidAccessError, NotSupportedError } from '../errors';
import RecorderAdapterNode from './RecorderAdapterNode';
export default class BaseAudioContext {
readonly destination: AudioDestinationNode;
readonly sampleRate: number;
readonly context: IBaseAudioContext;
constructor(context: IBaseAudioContext) {
this.context = context;
this.destination = new AudioDestinationNode(this, context.destination);
this.sampleRate = context.sampleRate;
}
public get currentTime(): number {
return this.context.currentTime;
}
public get state(): ContextState {
return this.context.state;
}
createRecorderAdapter(): RecorderAdapterNode {
return new RecorderAdapterNode(this, this.context.createRecorderAdapter());
}
createOscillator(): OscillatorNode {
return new OscillatorNode(this, this.context.createOscillator());
}
createGain(): GainNode {
return new GainNode(this, this.context.createGain());
}
createStereoPanner(): StereoPannerNode {
return new StereoPannerNode(this, this.context.createStereoPanner());
}
createBiquadFilter(): BiquadFilterNode {
return new BiquadFilterNode(this, this.context.createBiquadFilter());
}
createBufferSource(
options?: AudioBufferSourceNodeOptions
): AudioBufferSourceNode {
const pitchCorrection = options?.pitchCorrection ?? false;
return new AudioBufferSourceNode(
this,
this.context.createBufferSource(pitchCorrection)
);
}
createBufferQueueSource(): AudioBufferQueueSourceNode {
return new AudioBufferQueueSourceNode(
this,
this.context.createBufferQueueSource()
);
}
createBuffer(
numOfChannels: number,
length: number,
sampleRate: number
): AudioBuffer {
if (numOfChannels < 1 || numOfChannels >= 32) {
throw new NotSupportedError(
`The number of channels provided (${numOfChannels}) is outside the range [1, 32]`
);
}
if (length <= 0) {
throw new NotSupportedError(
`The number of frames provided (${length}) is less than or equal to the minimum bound (0)`
);
}
if (sampleRate < 8000 || sampleRate > 96000) {
throw new NotSupportedError(
`The sample rate provided (${sampleRate}) is outside the range [8000, 96000]`
);
}
return new AudioBuffer(
this.context.createBuffer(numOfChannels, length, sampleRate)
);
}
createPeriodicWave(
real: Float32Array,
imag: Float32Array,
constraints?: PeriodicWaveConstraints
): PeriodicWave {
if (real.length !== imag.length) {
throw new InvalidAccessError(
`The lengths of the real (${real.length}) and imaginary (${imag.length}) arrays must match.`
);
}
const disableNormalization = constraints?.disableNormalization ?? false;
return new PeriodicWave(
this.context.createPeriodicWave(real, imag, disableNormalization)
);
}
createAnalyser(): AnalyserNode {
return new AnalyserNode(this, this.context.createAnalyser());
}
/** Decodes audio data from a local file path. */
async decodeAudioDataSource(sourcePath: string): Promise<AudioBuffer> {
// Remove the file:// prefix if it exists
if (sourcePath.startsWith('file://')) {
sourcePath = sourcePath.replace('file://', '');
}
return new AudioBuffer(
await this.context.decodeAudioDataSource(sourcePath)
);
}
/** Decodes audio data from an ArrayBuffer. */
async decodeAudioData(data: ArrayBuffer): Promise<AudioBuffer> {
return new AudioBuffer(
await this.context.decodeAudioData(new Uint8Array(data))
);
}
async decodePCMInBase64Data(
base64: string,
playbackRate: number = 1.0
): Promise<AudioBuffer> {
return new AudioBuffer(
await this.context.decodePCMAudioDataInBase64(base64, playbackRate)
);
}
}