import { OggVorbisDecoderWebWorker } from '@wasm-audio-decoders/ogg-vorbis'; import { OggOpusDecoderWebWorker } from 'ogg-opus-decoder'; import { IAudioDecodeData, IAudioDecoder, IMotaAudioContext } from './types'; export class VorbisDecoder implements IAudioDecoder { decoder?: OggVorbisDecoderWebWorker; async create(): Promise { this.decoder = new OggVorbisDecoderWebWorker(); await this.decoder.ready; } async destroy(): Promise { if (!this.decoder) return; else return this.decoder.free(); } async decode(data: Uint8Array): Promise { if (!this.decoder) return Promise.resolve(null); else return this.decoder.decode(data) as Promise; } async decodeAll(data: Uint8Array): Promise { if (!this.decoder) return Promise.resolve(null); else return this.decoder.decodeFile(data) as Promise; } async flush(): Promise { if (!this.decoder) return Promise.resolve(null); else return this.decoder.flush() as Promise; } } export class OpusDecoder implements IAudioDecoder { decoder?: OggOpusDecoderWebWorker; async create(): Promise { this.decoder = new OggOpusDecoderWebWorker({ speechQualityEnhancement: 'none' }); await this.decoder.ready; } async destroy(): Promise { if (!this.decoder) return; else return this.decoder.free(); } async decode(data: Uint8Array): Promise { if (!this.decoder) return Promise.resolve(null); else return this.decoder.decode(data) as Promise; } async decodeAll(data: Uint8Array): Promise { if (!this.decoder) return Promise.resolve(null); else return this.decoder.decodeFile(data) as Promise; } async flush(): Promise { if (!this.decoder) return Promise.resolve(null); else return this.decoder.flush() as Promise; } } export class VanillaDecoder implements IAudioDecoder { constructor(readonly ac: IMotaAudioContext) {} create(): Promise { return Promise.resolve(); } destroy(): Promise { return Promise.resolve(); } private async decodeData( data: Uint8Array ): Promise { if (data.buffer instanceof ArrayBuffer) { const buffer = await this.ac.ac.decodeAudioData(data.buffer); const decodedData: Float32Array[] = []; for (let i = 0; i < buffer.numberOfChannels; i++) { const data = buffer.getChannelData(i); decodedData.push(data); } const sampled = decodedData[0].length; const sampleRate = buffer.sampleRate; return { errors: [], channelData: decodedData, samplesDecoded: sampled, sampleRate }; } else { return Promise.resolve(null); } } decode(data: Uint8Array): Promise { return this.decodeData(data); } decodeAll(data: Uint8Array): Promise { return this.decodeData(data); } flush(): Promise { return Promise.resolve(null); } }