TeaWeb/web/app/voice/AudioResampler.ts
2020-09-01 12:53:42 +02:00

55 lines
No EOL
1.8 KiB
TypeScript

import {LogCategory, logWarn} from "tc-shared/log";
const OfflineAudioContext = window.webkitOfflineAudioContext || window.OfflineAudioContext;
export class AudioResampler {
private readonly targetSampleRate: number;
private readonly isPromiseResponse: boolean;
constructor(targetSampleRate: number){
this.targetSampleRate = targetSampleRate;
this.isPromiseResponse = navigator.browserSpecs.name != 'Safari';
if(this.targetSampleRate < 3000 || this.targetSampleRate > 384000) {
throw tr("The target sample rate is outside the range [3000, 384000].");
}
}
getTargetSampleRate() : number {
return this.targetSampleRate;
}
async resample(buffer: AudioBuffer) : Promise<AudioBuffer> {
if(!buffer) {
logWarn(LogCategory.AUDIO, tr("Received empty buffer as input! Returning empty output!"));
return buffer;
}
if(buffer.sampleRate == this.targetSampleRate) {
return buffer;
}
const context = new OfflineAudioContext(
buffer.numberOfChannels,
Math.ceil(buffer.length * this.targetSampleRate / buffer.sampleRate),
this.targetSampleRate
);
let source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.start(0);
if(this.isPromiseResponse) {
return await context.startRendering();
} else {
return await new Promise<AudioBuffer>((resolve, reject) => {
context.oncomplete = event => resolve(event.renderedBuffer);
try {
context.startRendering();
} catch (ex) {
reject(ex);
}
});
}
}
}