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.05k stars 168 forks source link

Biquad: Possibility to set the filters coefficients and not just Q/freq/gain #323

Closed narnau closed 9 years ago

narnau commented 10 years ago

Currently it is only possible to design a filter by using the Q/freq/gain parameters. It seems that the solution would be to show the setNormalizedCoefficients function of the biquad node on the API.

void Biquad::setNormalizedCoefficients(double b0, double b1, double b2, double a0, double a1, double a2) -> http://dxr.mozilla.org/mozilla-central/source/content/media/webaudio/blink/Biquad.cpp

rtoy commented 10 years ago

What exactly is the problem you want to solve? You want to set the coefficients to arbitrary values?

narnau commented 10 years ago

Yes, I want to set the 6 coefficients without using the cookbook formulas for Q/freq/gain. i.e. have direct access to the coefficients.

padenot commented 10 years ago

Could you be more precise about your use case?

On Fri, May 16, 2014, at 08:07 PM, narnau wrote:

Yes, I want to set the 5 coefficients without using the cookbook formulas for Q/freq/gain. i.e. have direct access to the coefficients.


Reply to this email directly or view it on GitHub: https://github.com/WebAudio/web-audio-api/issues/323#issuecomment-43361774

rtoy commented 10 years ago

One possible use case: you want to implement a higher order filter and you've decomposed it into a bunch of biquads. In this case, you probably have the coefficients for each biquad and don't want to have to convert to Q/freq/gain.

I guess this also allows one to implement a first order filter; I don't think that's possible with the current filter types.

padenot commented 10 years ago

fwiw, a way to do first order filters have been requested to me on twitter this weekend.

This seems like a change that is easy to implement, and that can certainly be very useful.

This is also quite easy to spec, once we have the equations from the cook book copied and integrated to the spec (and not merely referencing them).

narnau commented 10 years ago

Yes, as Raymond told, I think that it could be very useful to implement higher order filters with a series of biquads.

Another point would be to have the option to execute this bunch of biquads as a cascade of biquads. (all the biquad equations inside the same iteration). It could be really simple to implement and it would have a positive affect in the CPU load.

narnau commented 10 years ago

Hello, Although the cookbook formulas are useful for the 90% of use cases, it only cover a very small subset of what a biquad is able to do. I expose three user cases where the cookbook formulas are not enough:

Our current use case is as follows : we have some FIR filters; for CPU considerations, we model these FIR filters into a series of biquads filters. The modeling operation produces a list of coefficients and these coefficients are not compatible with the cookbook formulas.

Another (similar) use case : one can design high-order filters (e.g. using butterworth mapping) in order to obtain lowpass/highpass filters which are steeper than the standard (2nd order) lowpass biquad; with such filter design you obtain a set of coefficients that cannot be represented with the cookbook.

Another use case : the cookbook formulas allow to design either highshelf and lowshelf filter but I have elaborated my own cookbook formula that allows to design a biquad which performs both highshelf and lowshelf at the same time (so 2x more efficient in CPU). Such very useful filter cannot currently be implemented in the Web Audio API.

rtoy commented 10 years ago

Can you give a few short examples?

For an FIR filter, can't you use the convolver node to implement them? That should efficient.

For higher order filters, I think the biquads from decomposing the higher order filter should be expressible with biquads. The issue is that you probably have to convert the coefficients into the form that biquad node wants.

narnau commented 10 years ago

The issue is that you probably have to convert the coefficients into the form that biquad node wants.

This conversion is not always possible. On one hand you have 5 (or 6) coefficients, on the other hand you have 3 parameters (Q/freq/gain). The mapping between these two forms is not a bijective function.

For an FIR filter, can't you use the convolver node to implement them? That should efficient.

When we model the FIR filters with IIR filters we transform a 512-tap FIR filter with a 30 coefficients IIR filter, so the IIR filter is more efficient. Also, it's useful to reduce the bandwidth network when downloading the filters.

rtoy commented 10 years ago

I think for a general biquad (b0+b1/z+b2/z^2)/A(z), where A(z) = 1 + a1/z + a2/z^2, you decompose into 3 biquads: b0/A(z) + b1/z/A(z) + b2/z^2/A(z) which are representable as a lowpass, bandpass, and highpass filter.

But I agree, it is useful to be able to set the coefficients directly.

jussi-kalliokoski commented 10 years ago

If we expose the coefficients, I don't think it makes much sense to limit that to biquad - just exposing a general purpose Filter node with arbitrary size IIR and FIR coefficients would solve this as well as other use cases. There's some overlap with the ConvolverNode, in that ConvolverNode would just be subset (FIR) of this node.

rtoy commented 10 years ago

I think for FIR, we should just teach people how to implement an FIR filter with a ConvolverNode..

Direct implementation of IIR filters can suffer from significant roundoff. I think it's almost always better to decompose into biquads. The decomposition could be done in the node itself, but that is also problematic because solving high order polynomials accurately is hard. And after getting all of the polse and zeroes, it's not clear which poles should go with which zeroes to form a biquad.

cwilso commented 10 years ago

This would be a very powerful addition. I think it needs to be a separate CustomBiquadFilterNode, though.

svgeesus commented 10 years ago

There are two ways to do this - allow direct setting of 6 biquad filter coeeficients as well as Q/frequency/gain, and make two separate nodes (one 6 coeffs only, one Q/freq/gain only as @cwilso suggests). The advantage of the second method is that you don't have to solve the issue of setting them one way and reading them back a different way; ordocumenting what happens when someone sets, say, Q, a2, and b1. CustomBiquadFilterNode should be easy to spec for v1 since it is just setting the coefficients directly.

rtoy commented 10 years ago

One small issue is having to explain the difference between BiquadFilterNode and CustomBiquadFilterNode to a user.

I think CustomBiquadFilterNode should only take 5 coefficients, probably as AudioParams. We would also need to specify what happens if someone creates an unstable filter. Is that allowed? Checking for stability is straightforward, but could be problematic if the coefficients are AudioParams.

svgeesus commented 10 years ago

The documentation for CustomBiquadFilterNode should include a few simple examples that do what cookbook Q/freq/gain does not; like 6dB/oct filters as mentioned above, band-reject filters, allpass filters, steep anti-aliasing filters (to use when previous steps have not been carefully bandlimited).

svgeesus commented 10 years ago

@rtoy agree its not a free lunch and explaining why there are two nodes that do similar things is needed. It still seems cleaner than the alternative with one tricky node that can be used in one of two ways, though.

rtoy commented 10 years ago

The current BiquadFilterNode already has band-reject (notch) filters and allpass filters. Were you thinking of something else?

I didn't follow what you wanted with steep anti-aliasing filters. Biquads can only give 12dB/octave, so are you suggesting cascading them for steeper filters?

svgeesus commented 10 years ago

My understanding (and correct me if I am wrong) is that by direct manipulation of the coefficients its possible to get filters which have a steeper initial cutoff in the transition region. (The eventual slope is still 12bB/oct once it settles down).

And thus, its a use case not covered by cookbook filters. Is that right?

If so, it can be used as one stage in a multi-stage AA filter to cut frequencies just past the cuttoff frequency more steeply. (I don't know if you get passband ripple in consequence).

(about notch and all-pass: yes, so they do, please ignore that part of the comment.)

rtoy commented 10 years ago

On Tue, Nov 11, 2014 at 2:02 PM, Nantonos notifications@github.com wrote:

My understanding (and correct me if I am wrong) is that by direct manipulation of the coefficients its possible to get filters which have a steeper ''initial'' cutoff in the transition region. (The eventual slope is still 12bB/oct once it settles down).

​I guess that's possible, but I have no experience with that.​

​​

And thus, its a use case not covered by cookbook filters. Is that right?

If so, it can be used as one stage in a multi-stage AA filter to cut frequencies just past the cuttoff frequency more steeply. (I don't know if you get passband ripple in consequence).

​Once you get to multiple stages, I think you can design the filter to have (or not) any kind of passband or stopband ripple that you want by choosing the appropriate kind of filter (Butterworth, Bessel, Chebyshev, Elliptical, etc.)​

(about notch and all-pass: yes, so they do, please ignore that part of the comment.)

— Reply to this email directly or view it on GitHub https://github.com/WebAudio/web-audio-api/issues/323#issuecomment-62630124 .

Ray

notthetup commented 10 years ago

Am I right that the main utility of having an abstracted BiquadFilerNode that exposes freq/Q/gain Parameters is to enable Parameter automation methods on work on those with sample accuracy.

Otherwise we could essentially have a CustomFilterNode that exposes the 5 biquad coefficients and have 3rd party JS libraries do the transformation based on whatever formulae/technique they choose.

cwilso commented 10 years ago

Am I right that the main utility of having an abstracted BiquadFilerNode that exposes freq/Q/gain Parameters is to enable Parameter automation methods on work on those with sample accuracy.

No, actually. In fact, the freq/Q/gain/detune are k-rate, not a-rate. The point of having a BiquadFilterNode that exposes these parameters and a type is convenience and intuition; the average developer will be able to instantly utilize a lowpass filter with high Q, but would have to look up the formula (and manually automate) for it if we only offered the decomposed custom filter.

joeberkovitz commented 10 years ago

Proposal: new filter node with raw coefficients exposed as AudioParams (k-rate)

rtoy commented 9 years ago

After thinking this over a bit, I think I like Jussi's proposal https://github.com/WebAudio/web-audio-api/issues/323#issuecomment-60533393 about just making a general IIR filter node where you can specify any set of a and b coefficients. No automation allowed.

joeberkovitz commented 9 years ago

@rtoy Can you please explain why you want to remove the automation? We had already agreed to make a new filter node type with the general coefficients, but with automation.

rtoy commented 9 years ago

I just don't really see a use case for automating random coefficients for a general IIR filter. But if you really want automation, then ok. I find it quite messy even for a general biquad.

joeberkovitz commented 9 years ago

I don't care a lot about automation in this case. But others might, so I just wanted a statement on record as to why you wanted to remove it, in case they care. It sounds as though the reason is "unlikely use case" and "implementation complexity".

rtoy commented 9 years ago

Oh, I didn't think about implementation complexity, but that does bring up a good point in how to design such a filter. Will there be a set of attributes like a1,a2,a3,..., b0, b1, b2,... that represent the coefficients? Then we have to specify some arbitrary but fixed number of coefficients. I was thinking more along the lines of createIIRFIlter(, ). Not sure how to do automation in this case.

joeberkovitz commented 9 years ago

Yes, that was exactly the idea (a1, a2... with explicit and fixed number of names), except the original thought was that they would be AudioParams for consistency with the old biquad. I think it would be a more consistent API if they are AudioParams, whether that seems likely or not. If we're going to change that decision then we should run it by everyone again.

rtoy commented 9 years ago

I'm fine with AudioParams.

padenot commented 9 years ago

Since this would essentially be a custom biquad, we could just have an type that would be "custom" on the biquad, and the 6 new AudioParams that would only work when the type is "custom", like there is for the OscillatorNode.

People from IRCAM told me they would also need a way to set the internal filter state, essentially setFilterMemory(x0,x1,y0,y1).

rtoy commented 9 years ago

A BiquadFilterNode with type "custom" is acceptable to me. Except there should be 5 audioparams, not 6: b0, b1, b2, a1, a2. a0 is implicit and is always 1. If I set a filter type of "lowpass", can I read the coefficient attributes to get the current filter coefficients for the lowpass filter? Kind of useful, but perhaps problematic if the filter has automation.

setFilterMemory is ok too as long as users know it won't be sample accurate and could cause glitches.

Finally, are you saying we should not support a general IIR filter node as proposed by Jussi and just support the custom BiquadFilterNode?

padenot commented 9 years ago

Yes, 5 AudioParam. I'd say you could read out the values, but that would mean to solve the issues about read back of AudioParams first (I don't know the issue number # offhand, sorry).

Yes, setFilterMemory would have a note saying that it is expected that authors call it while nothing is flowing through the BiquadFilter.

I think we can go a long way with a Biquad with custom coefficient, but I'm certainly not opposed to having a generic IIR filter node, we'd need to discuss that.

rtoy commented 9 years ago

This works for me.

I would prefer that if we add a generic IIR filter node, then the Biquad filter node is unchanged (no custom coefficients). Or don't add an IIR node and the Biquad node allows custom coefficients.

joeberkovitz commented 9 years ago

The previously accepted proposal envisioned a new node interface with a new name and factory method, and we had agreed at the F2F to leave the existing BiquadFilter alone (without adding a new filter type of "custom").

To avoid going around on this again and possibly surprising members who previously agreed to leaving the old class alone, I'd ask if one of the following choices is acceptable:

1) [previously agreed on] Add a new biquad filter node with custom coefficients 2) Add a new IIR filter node

In both cases, the old Biquad filter would stick around unchanged.

rtoy commented 9 years ago

I prefer option 2. If we're adding a new node, might as well go all the way with a fairly general IIR filter node.

svgeesus commented 9 years ago

I thought the reason to have a new node was to avoid the case where the coefficients are set indirectly (but cutoff frequency, Q, etc) and then read back or modified individually at the individual coefficient level. Automation of individual coefficients is not harmful but equally is not very useful as they don't correspond to physical concepts. I could imagine code that precomputes a set of five automations though. A more general IIR node might be be useful; is it a strict superset of FIR (he said hazily)?

rtoy commented 9 years ago

The general IIR node would be a (limited) strict superset of FIR. Given Joe's suggestion on what it would look like, there would be some max limit on the number of FIR (and IIR) coefficients, so you could implement fairly short FIR with it instead of using a convolver node.

From an implementation viewpoint, it might be beneficial to have additional attributes to tell how many of the a and b coefficients are in use.

rtoy commented 9 years ago

From the 2015/03/19 teleconf, a general IIR filter is desired. The coefficients will not be audioparams. Details to be worked out.

joeberkovitz commented 9 years ago

@rtoy Given the agreement on a general IIR node, is that proposal now ready for editing as a resolution for this issue?

gyltefors commented 8 years ago

Hmm, why have a biquad node in the first place if one can't set the parameters (a0,a1,a2,b1,b2), but is restricted to a few predefined filters only?

rtoy commented 8 years ago

First, as explained above, any biquad filter can be created using the predefined filters. Second, the predefined filters allow you to do useful automations that aren't easily possible by automating the individual coefficients. Third, if you really want to set the coefficients, use IIRFilterNode.

Finally, this bug is closed. Please open a new bug.

gyltefors commented 8 years ago

Well, what we have now is a node called "biquad" that can't implement MOST biquad filters (*). While filter sweeps are FUN, I doubt many people would need that in any serious application. So, yes, there is definitely a need to open a few new tickets to address the overall design decisions concerning Web Audio.

rtoy commented 8 years ago

Any biquad filter can decomposed into a combination of the builtin biquad filters, so you are not limited in any way. The only difficulty is deciding how to decompose the general biquad into one of the predefined ones.

gyltefors commented 8 years ago

So you say that to implement ONE biquad, I have to use SEVERAL biquad nodes, using in your words "difficult" math? It doesn't sound like a good design decision to me.

rtoy commented 8 years ago

So, use the IIRFilterNode.

gyltefors commented 8 years ago

It is not available in the current version of Chrome, so I'll have to use a custom node. In the end, none of the predefined nodes, biquad, compressor etc. are useful in a real application, and you have to use custom nodes for everything. Reading through this thread, there seem to be many people with an audio engineering background giving valuable comments, that are mostly ignored with remarks like, "why would we need that?" etc. And we end up with a framework that does a lot a cool stuff, but not really the things that an audio engineer needs to be able to implement his designs.

notthetup commented 8 years ago

@gyltefors This is how the W3C spec process works. The discussions here are about the WebAudio specification. Whatever is discussed and decided becomes a part of the WebAudio spec. The browser (UA) manufacturers are then free to implement the spec based on their own priority and schedule.

So you might see things here (like you noticed with the IIRFilterNode) which are in the spec (most often added recently, https://github.com/WebAudio/web-audio-api/pull/556 ) but not yet implemented in your favourite browsers. Give the browser vendors a little time. They will get implemented in due time. :)

As for the decision between what the WebAudio framework should do natively and what should be left for libraries and other applications to implement on the top is a continuous discussion that happens in the spec. Depending on factors like performance, expandability and abstraction, the Audio Working Group chooses between the various approaches.

Specifically for the IIRFilterNode, I would expect to see a bunch of OpenSource libraries for implementing common filter designs with the IIRFilterNode soon, once the browsers start supporting that node.

gyltefors commented 8 years ago

@notthetup Thanks, I am new to this process. What is best approach to push for changes that I feel are important for WebAudio to be useful for application developers?

notthetup commented 8 years ago
  1. Check the latest version of WebAudio Spec for reference.
  2. Search the issues to see if there already a discussion on that topic/node/aspect. People interested in certain issues would be subscribed to them so they'll get notified.
  3. If there isn't one, then raise a new issue and explain in detail what you'd want to see in the WebAudio Specification. If the Audio Working Group needs more information or examples, feel free implement some tests or examples to help the discussion.
  4. Once the suggestion gets accepted by the W3C Audio Working Group, it will get added to the WebAudio Specification. After that you'll have to wait for the browser vendors to implement it and for all the updates to go out so all your users can also have the new functionality. This may take time. We have to be patient. :)
  5. Also, look at the various open source libraries, frameworks and tools available on top of WebAudio. Tons of great functionality is available that way, and ready to be used.