Creating a 10-Band Equalizer Using Web Audio API
Asked Answered
A

3

17

I'm trying to wrap my head around using the Web Audio API to recreate something like
Winamp's 10-band equalizer.

Winamp's 10-band equalizer
(source: head-fi.org)

From what I can gather, I have to create 10 Biquad Filters, set their type to 2 (for a Bandpass filter) and set their frequency to [60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000] respectively. Once I have done that (and here's where I'm getting a little confused) I would then create a separate Gain Node for each frequency "band" and bind its value to a slider.

<input id="someFreqBand" type="range" min="-12" max="12" step="0.1" value="0" onchange="slide()"/>

Assuming all of that is correct, then the only remaining step is to connect all 10 gain nodes to the Audio Context destination (which I imagine will take all 10 frequency "bands" and mix/sync them back together). Is this the right way to go about creating a Web Audio 10-band equalizer?

The major thing I'm confused about is how I go about "connecting" the source to the 10 frequency band filters (+ associated gain node) since all the nodes only have a single input or output (including the destination).

Addison answered 5/10, 2012 at 0:48 Comment(0)
T
10

As Matt D said, there should be no problem connecting the filters to the same destination.

I would however say that you probably want to use filters with type 5 (peaking), which lets all frequencies through and only amplifies/reduce at the frequency at which you've set the respective filter.frequency.value. That lets you connect the filters in series so you don't need 10 separate audio paths. You could also consider using a low-shelf filter as the first filter, and a hi-shelf filter as the tenth, which is rather common in equalizers. I can't remember if that's what winamp does, though.

Finally, if you go with the peaking filters in series, you don't need a separate gain node for each frequency, you just set the filter.gain.value for the specific filters.

Tyndareus answered 10/10, 2012 at 12:29 Comment(4)
Unless I'm mistaken, all graphic equalizers use the bandpass filter. See here on page 4: rs6.eporia.com/company_38/techpaper106.pdf It does seem odd that the low-shelf/high-shelf/peaking filter allows you to adjust the gain directly on the filter node, but not the bandpass filter...Addison
I'm not sure if all graphic equalizers use bandpass filters, but I'm sure that using peaking filters in series would be the easier way to get the behaviour you're after.Tyndareus
filters should be connected in series, as Jagi mentioned.Upandcoming
Yes, as did I. :)Tyndareus
W
15

By connecting every filter with the destination you are creating 5 paths (routes) so you will hear quintupling amplification of the source sound. It's not the correct way. You have to connect each filter in one line.

source.connect(filter1);
filter1.connect(filter2);
filter2.connect(filter3);
filter3.connect(filter4);
filter4.connect(filter5);
filter5.connect(context.destination);
Weimaraner answered 9/4, 2013 at 6:36 Comment(0)
T
10

As Matt D said, there should be no problem connecting the filters to the same destination.

I would however say that you probably want to use filters with type 5 (peaking), which lets all frequencies through and only amplifies/reduce at the frequency at which you've set the respective filter.frequency.value. That lets you connect the filters in series so you don't need 10 separate audio paths. You could also consider using a low-shelf filter as the first filter, and a hi-shelf filter as the tenth, which is rather common in equalizers. I can't remember if that's what winamp does, though.

Finally, if you go with the peaking filters in series, you don't need a separate gain node for each frequency, you just set the filter.gain.value for the specific filters.

Tyndareus answered 10/10, 2012 at 12:29 Comment(4)
Unless I'm mistaken, all graphic equalizers use the bandpass filter. See here on page 4: rs6.eporia.com/company_38/techpaper106.pdf It does seem odd that the low-shelf/high-shelf/peaking filter allows you to adjust the gain directly on the filter node, but not the bandpass filter...Addison
I'm not sure if all graphic equalizers use bandpass filters, but I'm sure that using peaking filters in series would be the easier way to get the behaviour you're after.Tyndareus
filters should be connected in series, as Jagi mentioned.Upandcoming
Yes, as did I. :)Tyndareus
A
2

The major thing I'm confused about is how I go about "connecting" the source to the 10 frequency band filters (+ associated gain node) since all the nodes only have a single input or output (including the destination).

This is true, but don't think about it like a physical output that can only be connected to another physical input. A single output of a Web Audio node can be connected to multiple nodes, and a node can also receive multiple inputs. For example, let's say you wanted to chain an input node through 5 filters in parallel and then join them back together. You could do something like this:

source.connect(filter1);
source.connect(filter2);
source.connect(filter3);
source.connect(filter4);
source.connect(filter5);

filter1.connect(context.destination);
filter2.connect(context.destination);
filter3.connect(context.destination);
filter4.connect(context.destination);
filter5.connect(context.destination);

The key insight here is that calling .connect multiple times will not switch the output to a different node, but will simply add additional output connections. In other words, it's a "fan out/fan in" system.

Apron answered 9/10, 2012 at 19:47 Comment(2)
It seems like poor documentation when the spec says: numberOfInputs: 1. numberOfOutputs: 1. When by 1 they mean many.Addison
I admit it could be clearer, but that documentation is still correct. One output can connect to multiple inputs. Think about it more like the number of output ports rather than outputs.Apron

© 2022 - 2024 — McMap. All rights reserved.