murmuraba
Version:
Real-time audio noise reduction with advanced chunked processing for web applications
75 lines (74 loc) • 2.49 kB
JavaScript
import { getEngine } from '../api';
/**
* Apply gain to WAV audio buffer
*/
function applyGainToBuffer(arrayBuffer, gain) {
const view = new DataView(arrayBuffer);
const newBuffer = new ArrayBuffer(arrayBuffer.byteLength);
const newView = new DataView(newBuffer);
// Copy WAV header (first 44 bytes)
for (let i = 0; i < 44; i++) {
newView.setUint8(i, view.getUint8(i));
}
// Apply gain to audio samples (16-bit PCM)
for (let i = 44; i < arrayBuffer.byteLength - 1; i += 2) {
const sample = view.getInt16(i, true);
const amplified = Math.max(-32768, Math.min(32767, sample * gain));
newView.setInt16(i, amplified, true);
}
return newBuffer;
}
/**
* Process audio file and capture VAD metrics frame by frame
*/
export async function processFileWithMetrics(arrayBuffer, onFrameProcessed, outputGain = 2.5 // Apply 2.5x gain to processed audio for balanced louder output
) {
const engine = getEngine();
const metrics = [];
let frameCount = 0;
let totalVad = 0;
// Hook into the engine's frame processing
const originalProcessFrame = engine['processFrame'].bind(engine);
engine['processFrame'] = function (frame) {
const result = originalProcessFrame(frame);
// Calculate RMS
let sum = 0;
for (let i = 0; i < frame.length; i++) {
sum += frame[i] * frame[i];
}
const rms = Math.sqrt(sum / frame.length);
const metric = {
vad: result.vad,
frame: frameCount++,
timestamp: Date.now(),
rms
};
metrics.push(metric);
totalVad += result.vad;
if (onFrameProcessed) {
onFrameProcessed(metric);
}
return result;
};
try {
// Process the file
let processedBuffer = await engine.processFile(arrayBuffer);
// Apply output gain to make audio louder
if (outputGain !== 1.0) {
processedBuffer = applyGainToBuffer(processedBuffer, outputGain);
}
// Restore original method
engine['processFrame'] = originalProcessFrame;
const averageVad = metrics.length > 0 ? totalVad / metrics.length : 0;
return {
processedBuffer,
metrics,
averageVad
};
}
catch (error) {
// Restore original method on error
engine['processFrame'] = originalProcessFrame;
throw error;
}
}