LMMS / lmms

Cross-platform music production software
https://lmms.io
GNU General Public License v2.0
7.97k stars 994 forks source link

Crossover Equalizer - Glitch on transients #3421

Open zonkmachine opened 7 years ago

zonkmachine commented 7 years ago

The Crossover Equalizer could use some interpolation. It's riddled with glitches on suddenly increased values of the crossover frequency knobs. Interestingly the glitches seem only to be present on increase and not decrease of the knob value. crossoverequalizerglitch.mmp.zip

See earlier issue https://github.com/LMMS/lmms/issues/3339 and its fix https://github.com/LMMS/lmms/pull/3343

PaulBatchelor commented 7 years ago

@zonkmachine best way to do that is with a 1-pole smoothing filter. If there isn't a class for this, one should exist (I can make this)

michaelgregorius commented 7 years ago

Here you can find some code for a smoothing filter: http://www.musicdsp.org/archive.php?classid=3#257

PhysSong commented 4 years ago

For example, Calf Filter has a control called "Intertia" for that purpose. https://calf-studio-gear.org/doc/Filter.html

PaulBatchelor commented 4 years ago

The code for sp_port can be used as a smoothing filter:

https://github.com/PaulBatchelor/Soundpipe/blob/master/modules/port.c

The frequency knob value is read at the beginning of a render block (a control-rate signal), then passed into the smoothing filter as an input signal. The smoothing filter works inside the render block at audio rate.

"inertia" is the smoothing amount. Usually this is represented as a tau coefficient, which can be roughly thought of as smoothing time. In sp_port this is the htime variable.

PaulBatchelor commented 4 years ago

Did some digging.

The crossover EQ filter is made up of a few instances of StereoLinkWitzRiley filters, which is a basic filter type used all over LMMS. It only calculates things on a per-sample basis, and there is no support for block-rate parameter smoothing.

It actually turns out in the same file where the StereoLinkWitzRiley filters are defined (BasicFilters, there is also perfectly suitable code for a onepole smoother. I would build a class on top of this called ParameterSmoother or something that elegantly handles the parameter updates and block-rate to audio-rate signal conversion + smoothing.

The way to update LinkWitzRiley filter is with the setLowpass and setHighpass methods. This would need to be called at audio-rate any time the audio-rate output from ParameterSmoother changes. There should definitely be audio-rate parameter caching of some sort so that these methods don't get called every time... it looks like the filter does a full bilinear transform in order to calculate the coefficients.