From 7389e47cdb55abecc03afa68a6854a1c8bdb1961 Mon Sep 17 00:00:00 2001 From: Maciej Makowski Date: Thu, 14 Nov 2024 19:16:44 +0100 Subject: [PATCH] feat: updated interfaces --- .../src/core/BaseAudioContext.ts | 18 +++++++++++++++++- .../src/core/OscillatorNode.ts | 12 ++++++++++++ .../src/core/PeriodicWave.ts | 10 ++++++++++ .../react-native-audio-api/src/core/types.ts | 11 ++++++++++- .../react-native-audio-api/src/interfaces.ts | 14 ++++++++++++++ 5 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 packages/react-native-audio-api/src/core/PeriodicWave.ts diff --git a/packages/react-native-audio-api/src/core/BaseAudioContext.ts b/packages/react-native-audio-api/src/core/BaseAudioContext.ts index 78c86f8e..524b05e8 100644 --- a/packages/react-native-audio-api/src/core/BaseAudioContext.ts +++ b/packages/react-native-audio-api/src/core/BaseAudioContext.ts @@ -1,5 +1,5 @@ import { IBaseAudioContext } from '../interfaces'; -import { ContextState } from './types'; +import { ContextState, PeriodicWaveConstraints } from './types'; import AudioDestinationNode from './AudioDestinationNode'; import OscillatorNode from './OscillatorNode'; import GainNode from './GainNode'; @@ -75,4 +75,20 @@ export default class BaseAudioContext { this.context.createBuffer(numOfChannels, length, sampleRate) ); } + + createPeriodicWave( + real: number[], + imag: number[], + constraints?: PeriodicWaveConstraints + ): PeriodicWave { + if (real.length !== imag.length) { + throw new RangeError( + `The lengths of the real (${real.length}) and imaginary (${imag.length}) arrays are different` + ); + } + + const disableNormalization = constraints?.disableNormalization ?? false; + + return this.context.createPeriodicWave(real, imag, disableNormalization); + } } diff --git a/packages/react-native-audio-api/src/core/OscillatorNode.ts b/packages/react-native-audio-api/src/core/OscillatorNode.ts index f74fbb2b..e53e6b4f 100644 --- a/packages/react-native-audio-api/src/core/OscillatorNode.ts +++ b/packages/react-native-audio-api/src/core/OscillatorNode.ts @@ -3,6 +3,8 @@ import { OscillatorType } from './types'; import AudioScheduledSourceNode from './AudioScheduledSourceNode'; import AudioParam from './AudioParam'; import BaseAudioContext from './BaseAudioContext'; +import PeriodicWave from './PeriodicWave'; +import { InvalidStateError } from '../errors'; export default class OscillatorNode extends AudioScheduledSourceNode { readonly frequency: AudioParam; @@ -20,6 +22,16 @@ export default class OscillatorNode extends AudioScheduledSourceNode { } public set type(value: OscillatorType) { + if (value === 'custom') { + throw new InvalidStateError( + "The type can't be set to custom. You need to call setPeriodicWave() instead in order to define a custom waveform." + ); + } + (this.node as IOscillatorNode).type = value; } + + public setPeriodicWave(wave: PeriodicWave): void { + (this.node as IOscillatorNode).setPeriodicWave(wave.periodicWave); + } } diff --git a/packages/react-native-audio-api/src/core/PeriodicWave.ts b/packages/react-native-audio-api/src/core/PeriodicWave.ts new file mode 100644 index 00000000..b00c4505 --- /dev/null +++ b/packages/react-native-audio-api/src/core/PeriodicWave.ts @@ -0,0 +1,10 @@ +import { IPeriodicWave } from '../interfaces'; + +export default class PeriodicWave { + /** @internal */ + public readonly periodicWave: IPeriodicWave; + + constructor(periodicWave: IPeriodicWave) { + this.periodicWave = periodicWave; + } +} diff --git a/packages/react-native-audio-api/src/core/types.ts b/packages/react-native-audio-api/src/core/types.ts index bfa4dbaa..40be56f4 100644 --- a/packages/react-native-audio-api/src/core/types.ts +++ b/packages/react-native-audio-api/src/core/types.ts @@ -14,4 +14,13 @@ export type BiquadFilterType = export type ContextState = 'running' | 'closed'; -export type OscillatorType = 'sine' | 'square' | 'sawtooth' | 'triangle'; +export type OscillatorType = + | 'sine' + | 'square' + | 'sawtooth' + | 'triangle' + | 'custom'; + +export interface PeriodicWaveConstraints { + disableNormalization: boolean; +} diff --git a/packages/react-native-audio-api/src/interfaces.ts b/packages/react-native-audio-api/src/interfaces.ts index f1511038..366f0e29 100644 --- a/packages/react-native-audio-api/src/interfaces.ts +++ b/packages/react-native-audio-api/src/interfaces.ts @@ -11,6 +11,7 @@ export interface IBaseAudioContext { readonly state: ContextState; readonly sampleRate: number; readonly currentTime: number; + createOscillator(): IOscillatorNode; createGain(): IGainNode; createStereoPanner(): IStereoPannerNode; @@ -21,6 +22,11 @@ export interface IBaseAudioContext { length: number, sampleRate: number ) => IAudioBuffer; + createPeriodicWave: ( + real: number[], + imag: number[], + disableNormalization: boolean + ) => IPeriodicWave; } export interface IAudioContext extends IBaseAudioContext { @@ -34,6 +40,7 @@ export interface IAudioNode { readonly channelCount: number; readonly channelCountMode: ChannelCountMode; readonly channelInterpretation: ChannelInterpretation; + connect: (node: IAudioNode) => void; disconnect: (node: IAudioNode) => void; } @@ -52,6 +59,7 @@ export interface IBiquadFilterNode extends IAudioNode { readonly Q: AudioParam; readonly gain: AudioParam; type: BiquadFilterType; + getFrequencyResponse( frequencyArray: number[], magResponseOutput: number[], @@ -70,6 +78,8 @@ export interface IOscillatorNode extends IAudioScheduledSourceNode { readonly frequency: IAudioParam; readonly detune: IAudioParam; type: OscillatorType; + + setPeriodicWave(periodicWave: IPeriodicWave): void; } export interface IAudioBufferSourceNode extends IAudioScheduledSourceNode { @@ -82,6 +92,7 @@ export interface IAudioBuffer { readonly duration: number; readonly sampleRate: number; readonly numberOfChannels: number; + getChannelData(channel: number): number[]; copyFromChannel( destination: number[], @@ -100,7 +111,10 @@ export interface IAudioParam { defaultValue: number; minValue: number; maxValue: number; + setValueAtTime: (value: number, startTime: number) => void; linearRampToValueAtTime: (value: number, endTime: number) => void; exponentialRampToValueAtTime: (value: number, endTime: number) => void; } + +export interface IPeriodicWave {}