sensorium / Mozzi

sound synthesis library for Arduino

Home Page:https://sensorium.github.io/Mozzi/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

StateVariable centre frequency depends on Q

tomcombriat opened this issue · comments

Hi,
Playing a bit with all the filters I found out a few limitations.
The StateVariable in mozzi is good fun, it actually is able to display quite high resonance (way bigger than LowPassFilter at high frequencies) and, for low resonance (Q=255) is quite spot on on the desired cutoff frequency as long as one does not push to far toward Nyquist (not a problem in my opinion).

However, when pushing the resonance, the effective centre_frequency of the filter decreases. Here is an example with a set centre_frequency of 1000 Hz:

Q Effective centre frequency
255 1000
128 846
64 702
32 591
16 498
8 416
4 355
2 292
1 248

By fiddling around a bit, I found that one can renormalise the centre_frequency to achieve the correct output:
centre_frequency = 4* centre_frequency / (Q^(1/4))

However correcting this is not completely trivial: it implies recalculating the centre_frequency every time the resonance is changed (just like the LowPassFilter is doing). Also the normalisation factor is not trivial to compute. So I am asking for opinions:

  • Would it be worth to fight a bit to correct this?
  • In that case, maybe a lookup table, calculated at compile time could be used?
  • Should the original behavior kept (switch using a template argument between LEGACY and ACCURATE for instance?

On the other end, I also found that the LowPassFilter can also be used as a statevariable using:

//return buf1;    // LP
 //return in-buf0;  // HP
 return buf0 - buf1;  // BP 
 //return in - buf0 + buf1; // notch

And this filter is not impeded by the shift with Q (and is slightly faster).
As it is not as resonant as StateVariable, and not scaled, I think it is worth keeping both, and adding the other outputs to LowPassFilter to make it "another" StateVariable.
What would be the best strategy then?

  • Adding a template argument for the filter type? What would be a good name then (StateVariable2 does not sound right).
  • Making separated HighPassFilter etc, all actually falling back on the code of LowPassFilter (hidden template argument).

Let me know your opinions!
Cheers,
Tom

Regarding the StateVariable filter, I guess it will be a good idea to keep old code working as before. Arguably, the center frequency shift is a bug, but there may well be existing code where the frequency shift is not an issue, while additional computation might be. Suggested procedure: Create a new StateVariableFilter which will have two well-documented functions: setResonance() and setResonanceQuick() (or something). StateVariable could become deprecated with a note on the available choice.

As for a more generic LowPassFilter, FrequencyFilter or ResonantFilter might be suitable names for a template?

This can be closed, right?

Well, this is not resolved, but I guess it won't be as this would change the behavior of all existing sketches using the stateVariable. Additionnally, the ResonantFilter class offers filters with stable Q. So I would say yes.