WebAudio / web-audio-api

The Web Audio API v1.0, developed by the W3C Audio WG
https://webaudio.github.io/web-audio-api/
Other
1.04k stars 166 forks source link

Support Q and S for shelf filters #2428

Open rtoy opened 4 years ago

rtoy commented 4 years ago

Describe the issue From a message by Angus Turnbull:

Referring to: https://webaudio.github.io/web-audio-api/#BiquadFilterNode-attributes

The phrase "This is not used for lowshelf or highshelf filters." is repeated twice.

However, I think both should be deleted and Q values for shelf filters should be supported or at least specified.

I equalise my headphones on my desktop with: https://github.com/bmc0/dsp#effects and its configuration it supports a lot more than the Web Audio API:

lowshelf f0[k] width[q|s|d|o|h|k] gain Double-pole lowshelf filter. highshelf f0[k] width[q|s|d|o|h|k] gain Double-pole highshelf filter. Reference: q Q-factor (default). s Slope (shelving filters only). d Slope in dB/octave (shelving filters only). Also changes the definition of f0 from center frequency to corner frequency (like Room EQ Wizard and the Behringer DCX2496). o Bandwidth in octaves. h Bandwidth in Hz. k Bandwidth in kHz.

Another popular piece of Windows software is Equalizer APO which also supports both Q and DB per octave: https://sourceforge.net/p/equalizerapo/wiki/Configuration%20reference/

Pulse Effects is Linux app, second screenshot shows adjustable shelves: https://github.com/wwmm/pulseeffects

And see the cross-platform app Room EQ Wizard docs for speaker users: https://www.roomeqwizard.com/help/help_en-GB/html/eqfilters.html#top

All allow specifying at least 6db or 12db shelf filters and optionally customising it too. There's more EQ software out there I'm sure from the music world. We shouldn't leave the web behind :).

It would be sensible to: 1) Remove one or both references to lowshelf/highshelf not supporting Q. 2) Specify that it uses a default Q or Db/octave. The spec only mentions Q 1.0 but you might want 0.7071 for a 12db/octave default? 3) Allow users to customise the Q, please :). 4) Optionally support conversion between Q and Db-per-octave for shelves

Thanks, Angus Turnbull

rtoy commented 4 years ago

I noticed there might be some inconsistency between the lowshelf and highshelf filter equations defined in the spec and the corresponding equations from the Audio EQ Cookbook. (Plus, it looks like there might be a typo in the cookbook.)

The slope parameter is explicitly fixed in WebAudio, but maybe we can add that as a feature (for v2). Requires adding another AudioParam.

rtoy commented 4 years ago

See also WebAudio/web-audio-api-v2#64

rtoy commented 4 years ago

From eq. 10 in https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html, there is a relationship between Q and A and S for the shelving and peaking filters. For WebAudio S=1 always, so Q is only a function of A.

If we allow S to be modified, then we have a complicated relationship between Q and A (gain) for the filter type. If we allow Q and A to be modified independently, then S is changed. This not exposed in the API so the effect would be in the response. It would be hard to make this backward compatible since currently the only parameter that is changeable is A which implies a value for Q because S = 1.

rtoy commented 4 years ago

For the record, in https://github.com/WebAudio/web-audio-api-v2/issues/67#issuecomment-581507905, I mentioned an inconsistency. I was wrong. First use the correct link for the cookbook and if alpha_s in the spec is interpreted to be the same as alpha in the cookbook corresponding to equation 7, then everything is consistent.

rtoy commented 4 years ago

After looking at the equations for a lowshelf filter, I think we can make it all work and maintain backward compatibility (sort of). The default value for the gain attribute is 0. For a lowshelf, this is in dB, so the A=1 in the formula. For any value of alpha, A=1 causes the lowshelf filter to be identical to 1. That's good.

However, changing gain will produce different filter responses from before if we allow Q to have an effect. We can't make the new filter compatible with the old.

Perhaps the way forward is to create a new filter type, say, "lowshelfQ" and "highShelfQ" for this feature.

padenot commented 4 years ago

Virtual F2F:

rtoy commented 4 years ago

See eq. 10 in https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html. This gives a relationship between Q, S, and A. From the spec, [sec.1.13.5(https://webaudio.github.io/web-audio-api/#filters-characteristics), we have an expression for alpha_s where we explicitly set S = 1.

The shelf filters don't currently use Q. If we updated the filters to use Q, that would imply a value for S (because A is related to the gain audio param). This S would go into computing alpha_s. When Q = 1, it's pretty clear that S is not 1. Then alpha_s will change, which changes the lowshelf/highshelf filters.

If we want to support Q, we'll need to define new sholf filters..The definitions and implementation are pretty straightforward.

Given A (gain audioparam) and Q, compute S. Then compute alpha_s, and the existing lowshelf and highself formulas will work to define new filters.

rtoy commented 4 years ago

I've chatted with Robert Bristow-Johnson on this and he agrees that we should support Q for the shelf filters.

For the shelving filters, the most important equation is (11) in https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html. Currently for shelf filters, S = 1 so eqn 11 becomes 2*sqrt(A)*alpha = sin(w0)*(A+1), and that's independent of Q, obviously.

If support Q, I think that means S is now variable according to eqn 10. Solve that for S and plug it into eqn 11 and we get 2*sqrt(A)*alpha = sin(w0)*sqrt(A)/Q (eqn. 5).

The current default values for Q is 1 and for A is 1 (because the gain parameter is 0 from the relationship between A and dBGain). These values give two different values for 2*sqrt(A)*alpha: 2*sin(w0) and sin(w0). So, basically, they're not mathematically the same with the default values.

rtoy commented 4 years ago

Hacked an old demo I had to draw filter responses and then added support for shelf filters with Q. As expected, with the default values, the shelf filters produce the same response. But once the gain value changes, the frequency response is quite a bit different.

I think the only way to proceed here is to add two new filter types.

rtoy commented 4 years ago

Proposal: Add two new filter types named "lowshelfQ" and "highshelfQ" (TBD).

The formulas are basically the same except where we have 2*alpha_s*sqrt(A) replace alpha_s with alpha_q. (We really need equation numbers in the spec.)

rtoy commented 4 years ago

To be a bit clearer, use equations 29 and 31 from the AudioEQCookbook and the alpha term there is eqn 7.

This follows from eqn 13 and solve eqn 12 for S and substitute that into eqn 13.

rtoy commented 3 years ago

TPAC 2020:

Yes, we should add two new types of filters. Just need to pick appropriate names and add the correct equations for this.

rtoy commented 3 years ago

Virtual F2F 2021: https://github.com/WebAudio/web-audio-api-v2/issues/67#issuecomment-713754085 still holds. We just need to pick the names and add the appropriate text.