Konstantin Kuznetsov
Konstantin Kuznetsov

Reputation: 903

Filtering web audio frequencies

I'm playing mp3 file via Tone.js's Player and I need to play only certain range of frequencies from this file. This range is dynamically selected by the user, and the user should be able to change it without stopping playback. Simultaneously Tone.js plays synthesized notes. Currently, I'm using bandpass/lowpass/highpass filters, but as far as I understand, they do not strictly cut frequencies outside of selected range, but instead smoothly reduce their gain, as illustrated by the red line in the graph below that I've found in some tutorial. Here is my piece of code:

function applyLimits([min,max]) {
    minFreq = min > max ? Number.NEGATIVE_INFINITY : min;
    maxFreq = min > max ? Number.POSITIVE_INFINITY : max;
    if (mp3Player) {
        if (minFreq == Number.NEGATIVE_INFINITY && maxFreq == Number.POSITIVE_INFINITY) {
            if (mp3Filter) {
                mp3Filter.dispose();
                mp3Player.toMaster();
                mp3Filter = null;
            }
        }
        else {
            if (!mp3Filter) {
                mp3Player.disconnect();
                mp3Filter = new Tone.Filter();
                mp3Player.chain(mp3Filter, Tone.Master);
            }
            if (minFreq != Number.NEGATIVE_INFINITY && maxFreq != Number.POSITIVE_INFINITY) {
                let centerFrequency = Math.sqrt(maxFreq * minFreq);
                let q = centerFrequency / (maxFreq - minFreq);
                mp3Filter.set({frequency: centerFrequency, Q: q, type: 'bandpass', rolloff: -96});
            }
            else if (minFreq != Number.NEGATIVE_INFINITY) {
                mp3Filter.set({frequency: minFreq, Q: 1, type: 'highpass', rolloff: -96});
            }
            else {
                mp3Filter.set({frequency: maxFreq, Q: 1, type: 'lowpass', rolloff: -96});
            }
        }
    }
}

What I need is illustrated by the green line. Looking at Tone.js sources, I can see that Tone.js uses cascading biquadfilters. But using even 10 cascading filters will result in a curve, not precise cut. Besides, according to this graph, frequencies within the range are affected too.

The graph

How is it possible to achieve such effect using Tone.js, Web Audio API or any other js library?

Upvotes: 2

Views: 541

Answers (1)

Raymond Toy
Raymond Toy

Reputation: 6048

The green line, if it is truly vertical, is physically unrealizable. The best you can do is to cascade a bunch of biquads together (carefully) to produce an approximation. Or use the IIRFilterNode (if available) to do the filtering.

Upvotes: 1

Related Questions