Skip to content

Instantly share code, notes, and snippets.

@chebum
Last active February 3, 2020 13:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chebum/1f901ebcdb2b55489065a90267ce5fc6 to your computer and use it in GitHub Desktop.
Save chebum/1f901ebcdb2b55489065a90267ce5fc6 to your computer and use it in GitHub Desktop.
Web Audio API - Find combined amplitude gain of biquad filters
/**
* Calculates maximum gain for a set of biquad filters. The function will calculate
* frequency response in steps specified by precisionHz
*
* @param {BiquadFilterNode[]} filters The array of biquad filters,
* @param {number} precisionHz A resolution in hertz of the calculation - smaller value means higher precision. Default value: 20.
* @return {number} Gain of the filters in dB.
*/
function maxGain(filters, precisionHz) {
if (!filters || filters.length === 0)
return 0;
precisionHz = Math.max(1, precisionHz || 20);
const maxFrequency = filters[0].context.sampleRate;
const steps = Math.ceil(maxFrequency / precisionHz);
// Generate input array for getFrequencyResponse method
const frequencies = new Float32Array(steps);
for (let i = 0; i < steps; i++) {
frequencies[i] = (i + 1) * precisionHz;
}
// Here we will store combined amplitude response
const totalAmplitudeResp = new Float32Array(steps);
for (let i = 0; i < steps; i++) {
totalAmplitudeResp[i] = 1;
}
// Temporary container for every filter response
const amplitudeResp = new Float32Array(steps), phaseResp = new Float32Array(steps);
for (let i = filters.length - 1; i >= 0; i--) {
const filter = filters[i];
// Get filter response and convolve it with existing response
filter.getFrequencyResponse(frequencies, amplitudeResp, phaseResp);
for (let j = 0; j < steps; j++) {
totalAmplitudeResp[j] *= amplitudeResp[j];
}
}
// Find max gain
let maxGain = -10000000;
for (let i = 0; i < steps; i++) {
const gain = totalAmplitudeResp[i];
if (gain > maxGain)
maxGain = gain;
}
// Convert gain to dB
filterGain = maxGain > 1.0 ? 20 * Math.log10(maxGain) : 0;
return filterGain;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment