react-native-audio-api
Version:
react-native-audio-api provides system for controlling audio in React Native environment compatible with Web Audio API specification
185 lines (148 loc) • 4.91 kB
text/typescript
import { AutomationEventData, AutomationEventType } from '../types';
import { InvalidStateError, NotSupportedError, RangeError } from '../errors';
import { IAudioParam } from '../jsi-interfaces';
import type BaseAudioContext from './BaseAudioContext';
export default class AudioParam {
public readonly defaultValue: number;
public readonly minValue: number;
public readonly maxValue: number;
constructor(
public readonly audioParam: IAudioParam,
public readonly context: BaseAudioContext
) {
this.value = audioParam.value;
this.defaultValue = audioParam.defaultValue;
this.minValue = audioParam.minValue;
this.maxValue = audioParam.maxValue;
}
public get value(): number {
return this.audioParam.value;
}
public set value(value: number) {
this.audioParam.value = value;
}
public setValueAtTime(value: number, startTime: number): AudioParam {
if (startTime < 0) {
throw new RangeError(
`startTime must be a finite non-negative number: ${startTime}`
);
}
this.checkCurveExclusion({
type: AutomationEventType.SET_VALUE,
automationTime: startTime,
});
const clampedTime = Math.max(startTime, this.context.currentTime);
this.audioParam.setValueAtTime(value, clampedTime);
return this;
}
public linearRampToValueAtTime(value: number, endTime: number): AudioParam {
if (endTime < 0) {
throw new RangeError(
`endTime must be a finite non-negative number: ${endTime}`
);
}
this.checkCurveExclusion({
type: AutomationEventType.LINEAR_RAMP,
automationTime: endTime,
});
const clampedTime = Math.max(endTime, this.context.currentTime);
this.audioParam.linearRampToValueAtTime(value, clampedTime);
return this;
}
public exponentialRampToValueAtTime(
value: number,
endTime: number
): AudioParam {
if (value === 0) {
throw new RangeError(`value must be a non-zero number: ${value}`);
}
if (endTime <= 0) {
throw new RangeError(
`endTime must be a finite non-negative number: ${endTime}`
);
}
this.checkCurveExclusion({
type: AutomationEventType.EXPONENTIAL_RAMP,
automationTime: endTime,
});
const clampedTime = Math.max(endTime, this.context.currentTime);
this.audioParam.exponentialRampToValueAtTime(value, clampedTime);
return this;
}
public setTargetAtTime(
target: number,
startTime: number,
timeConstant: number
): AudioParam {
if (startTime < 0) {
throw new RangeError(
`startTime must be a finite non-negative number: ${startTime}`
);
}
if (timeConstant < 0) {
throw new RangeError(
`timeConstant must be a finite non-negative number: ${timeConstant}`
);
}
this.checkCurveExclusion({
type: AutomationEventType.SET_TARGET,
automationTime: startTime,
});
const clampedTime = Math.max(startTime, this.context.currentTime);
this.audioParam.setTargetAtTime(target, clampedTime, timeConstant);
return this;
}
public setValueCurveAtTime(
values: Float32Array,
startTime: number,
duration: number
): AudioParam {
if (startTime < 0) {
throw new RangeError(
`startTime must be a finite non-negative number: ${startTime}`
);
}
if (duration <= 0) {
throw new RangeError(
`duration must be a finite strictly-positive number: ${duration}`
);
}
if (values.length < 2) {
throw new InvalidStateError(`values must contain at least two values`);
}
const clampedTime = Math.max(startTime, this.context.currentTime);
this.checkCurveExclusion({
type: AutomationEventType.SET_VALUE_CURVE,
automationTime: clampedTime,
duration,
});
this.audioParam.setValueCurveAtTime(values, clampedTime, duration);
return this;
}
public cancelScheduledValues(cancelTime: number): AudioParam {
if (cancelTime < 0) {
throw new RangeError(
`cancelTime must be a finite non-negative number: ${cancelTime}`
);
}
const clampedTime = Math.max(cancelTime, this.context.currentTime);
this.audioParam.cancelScheduledValues(clampedTime);
return this;
}
public cancelAndHoldAtTime(cancelTime: number): AudioParam {
if (cancelTime < 0) {
throw new RangeError(
`cancelTime must be a finite non-negative number: ${cancelTime}`
);
}
const clampedTime = Math.max(cancelTime, this.context.currentTime);
this.audioParam.cancelAndHoldAtTime(clampedTime);
return this;
}
private checkCurveExclusion(eventData: AutomationEventData): void {
const checkExclusionResult = this.audioParam.checkCurveExclusion(eventData);
if (checkExclusionResult.status === 'error') {
throw new NotSupportedError(checkExclusionResult.message);
}
}
}