web-audio-peak-meter
Version:
A customizable peak meter using the web audio API
56 lines (52 loc) • 1.76 kB
text/typescript
export function calculateLPFCoefficients(numCoefficients:number, upsampleFactor: number):number[] {
const retCoefs = [];
const fcRel = 1.0 / (4.0 * upsampleFactor);
const minCoefN = 1 - Math.ceil(numCoefficients / 2);
const maxCoefN = Math.floor(numCoefficients / 2);
for (let n = minCoefN; n <= maxCoefN; n++) {
const wn = 0.54 + 0.46 * Math.cos(2.0 * Math.PI * n / numCoefficients);
let hn = 0.0;
if (n == 0) {
hn = 2.0 * fcRel;
}
else {
hn = Math.sin(2.0 * Math.PI * fcRel * n) / (Math.PI * n);
}
//Adapt windows & upsampler factor
hn = (wn * hn) * upsampleFactor;
retCoefs.push(hn);
};
return retCoefs;
}
export function filterSample(lpfBuffer:number[], lpfCoefficients: number[], upsampleFactor: number): number[]{
const upsampled = [];
for (let nA = 0; nA < upsampleFactor; nA += 1) {
let nT = 0;
let retVal = 0;
for (let nc = nA; nc < lpfCoefficients.length; nc += upsampleFactor) {
retVal += (lpfCoefficients[nc] * lpfBuffer[lpfBuffer.length - 1 - nT]);
nT += 1;
}
upsampled.push(retVal);
}
return upsampled;
}
export function truePeakValues(input:Float32Array[], lpfBuffers:number[][], lpfCoefficients: number[], upsampleFactor: number): number[] {
return input.map((channel, i) => {
const lpfBuffer = lpfBuffers[i];
let max = 0;
for (let s = 0; s < channel.length; s++) {
const sample = channel[s];
lpfBuffer.push(sample);
lpfBuffer.shift();
const upSampled = filterSample(lpfBuffer, lpfCoefficients, upsampleFactor);
for (let u = 0; u < upSampled.length; u++) {
const uAbs = Math.abs(upSampled[u]);
if (uAbs > max) {
max = uAbs;
}
}
}
return max;
});
}