[pulseaudio-discuss] R: New equalizer module (module-eqpro-sink), some questions

Georg Chini georg at chini.tk
Sat Apr 20 00:54:49 UTC 2019

On 20.04.19 01:02, Alexander E. Patrakov wrote:
> сб, 20 апр. 2019 г. в 00:15, Georg Chini <georg at chini.tk>:
>> On 19.04.19 18:23, Alexander E. Patrakov wrote:
>>> пт, 19 апр. 2019 г. в 14:13, Tanu Kaskinen <tanuk at iki.fi>:
>>>> If the plugin gets the number of bands during the
>>>> initialization, it can create the appropriate number of non-array
>>>> control ports. Interleaved audio ports aren't needed either, because
>>>> PulseAudio can do the deinterleaving before passing the audio to the
>>>> plugin (like module-ladspa-sink already does). If one's going to write
>>>> an LV2 plugin, it's best to use standard port types so that all hosts
>>>> will be able to use the plugin.
>>> In addition, I think that "if the plugin gets the number of bands [at
>>> runtime]" is a very big "if" for an IIR-based equalizer. So big that I
>>> would rather hard-code it, or treat equalizers with a different number
>>> of bands as completely different plugins. The reason is that the
>>> required slope of inter-band transition (i.e., effectively, the filter
>>> order) is a function of the width of each band. Implement a filter
>>> with a too-low order, and it won't be able to isolate (and thus
>>> control thegain of) a frequency band selectively enough. Implement a
>>> filter with a too-high order, and its frequency response will be too
>>> steppy.
>> My understanding is that Andrea's equalizer algorithm supports
>> an arbitrary number of bands (certainly within some sane limits).
>> Please correct me if I am wrong.
> It supports arbitrary amount of bands, but not arbitrary filter order
> for a band. Just to reiterate, the whole filter is a cascade of some
> per-band filters of the same order. Each filter in the cascade is
> implemented, according to the dissertation, as a cut-and-boost filter,
> which is based on a band-pass filter, which is in turn based on a
> shelving Butterworth filter of order 2M. Hopefully I haven't missed
> any order-doubling here. I have not thoroughly checked whether the
> implementation actually follows the dissertation - this is complicated
> by the Italian language that I don't know, and cryptic variable names.
> The majority of the dissertation does contain formulas for an
> arbitrary even order (2M), but on page 41, it starts talking about
> filters of order 8 only. And, if I understand correctly, it doesn't
> match the code, which is hard-coded to implement only filters of order
> 4, and it is not only a matter of increasing M and M2 in the file,
> because then xn[i] must be set in eq_filter() for i >= 4. Another sign
> of this mismatch between the dissertation and the code is the
> different length of the "c" array - 10 in the code and 21 in algorithm
> 6.2 on page 43 (page numbers here are presented as printed at the
> bottom, not as displayed in PDF viewers' left pane).
> Because of the fixed order, there are indeed limits on the useful
> number of bands. E.g., given that the minimum and maximum supported
> gains in the band are -12 and 12 dB (at least this is what's mentioned
> in the dissertation), it means that the gain must increase by 24 dB
> between the centers of the neighboring bands. With the default 10-band
> filter, i.e. with one octave per band, this means that 24 dB per
> octave is the maximum supported slope, which is roughly right for a
> 4th order filter. In other words, more than 10 bands cannot be useful
> with 4th order filters and 24 dB of gain difference between the
> neighboring bands. I understand that it is odd to set the gain in two
> neighboring octaves to differ by that much.
> For a 5-band equalizer with the same gain limits, filters of 2nd order
> would be sufficient and preferable. Also, the order of the filter
> could be lowered if the gain limits are set lower.

I can't really comment on this, my knowledge is not sufficient.
But what you are basically saying is that the equalizer does
not hold what Andrea claims it can do and that it is only useful
as a 10-band equalizer. I wonder why her work was then
accepted as a master thesis.

>>> Besides, consumer electronic devices (TVs, HDMI receivers, Hi-Fi
>>> amplifiers) just do not have equalizers with a variable number of
>>> bands, for usability reasons. I don't see a reason for PulseAudio to
>>> be different.
>> You can't add sliders on the fly on a consumer electronic
>> device but you can do so in software. Why should we be guided
>> by a behavior that is governed by physical limits? If the algorithm
>> supports it, I see no reason why it should not be implemented.
>> (As said above naturally within some sane limits, you are right
>> that it would make no sense to have for example 50 bands.)
> Sliders in a consumer electronics device such as a TV are just virtual
> widgets on the screen, i.e. software, not physical knobs. Again, their
> number is fixed because of usable and "intuitive" UI.
I guess there are enough people who would wish for more
>> Surely you could go for several different plugins, but I do not
>> see the reason why the code should be duplicated a couple
>> of times. The goal is to have one plugin and not a collection.
>> I just don't like the idea that you have to duplicate things only
>> because of the limitation of the surrounding framework.
>> That's why I am looking for a way to dynamically adapt the
>> number of control ports or - which seems to be supported
>> by LV2 - use a control port that is an array.
> And my point is exactly that there is a reason, filter order, not
> related to any framework limitations, for different code for different
> number of bands.
>> Another example where an array would be useful as a control
>> port is the virtual-surround-sink. The HRIR data used by the filter
>> is an array of floats which could vary in size.
> I also disagree here. Yes, it can vary in size, but should not be
> treated as a control port at all. There is no way to usefully control
> it for a user, that's why. It should therefore be either hard-coded
> (as done in Windows) or loaded through a file.

If you load it through a file like pulseaudio does, how do
you pass the values to the filter? Or should the plugin itself
load the file?

> In summary, there is no use case presented so far that actually
> requires the number of user-controllable (i.e. exposed) controls to be
> a non-constant, and one of the reasons is that this won't fly past UI
> guidelines. Anyway, if LV2 supports this use case, and we settle on
> LV2 as the preferred plugin format, then we should support this
> feature, too, despite the UI-design-related objection above.
There is a way to communicate such changes to a UI. And
there are surely other filter setups where it would at least
be convenient to have a flexible number of controls (and
a flexible number of audio channels).
>> The focus of this mail thread is no longer the equalizer, even
>> though the subject may suggest that and it is often used as an
>> example. The starting point of the discussion was that I did a
>> consolidation of the virtual sinks we have in pulseaudio (see
>> !88) and the result shows that many of the filters we have
>> could be further consolidated to a single plugin sink. The
>> question then was which kind of plugin format we should use?
>> Naturally it would be better to use some standard API instead
>> of inventing our own. And if we move to a plugin-sink, the
>> plugin API should also support the features of the new
>> equalizer, so that this can be integrated as well if Andrea
>> is willing to contribute to a plugin.
>> Tanu suggested the LV2 standard, so I took a look into it. My
>> understanding is, that the CVPort is the type of control structure
>> I have been looking for, though Tanu says otherwise.
> I do agree that we should use some standard API if it fits, and don't
> see it a big problem if there are cases like echo-cancellation that
> don't fit.
> I have no my own objections to LV2, but we have discussed the idea of
> module-lv2-sink with David Henningsson in 2013 on LinuxCon Europe, and
> he did object - if I remember correctly, it was something related to
> GUI libraries used in LV2 plugins.
Yes, LV2 plugins can bring their own GUI. But that is an extension.
A module-lv2-sink would indeed be difficult to implement because
there are many LV2 extensions and features. But we could start
with implementing something basic and extend when needed.
>> There is however another limitation I see with the LV2 standard,
>> which is that it does not support interleaved audio channels.
>> This is not fatal, but at least inconvenient. It looks like massive
>> overhead to me if you have to de-interlace the audio data, then
>> run multiple instances of the filter and finally have to interleave
>> the data again. I think a plugin standard for pulseaudio should
>> be able to handle interleaved data.
> Pro audio world (which is the native habitat of various LADSPA and LV2
> plugins) is dominated by JACK, which supports non-interleaved audio
> samples only.
I do not say that it should support only interleaved audio, but
it should also support interleaved audio. It would be rather
easy to tag an audio port as interleaved and have an additional
variable which holds the number of channels. I don't understand
why this is not supported out of the box. If you don't want to use
the feature, you could still run those plugins non-interleaved.

All in all it looks to me like implementing an LV2 sink would have no
benefit, so probably I just leave things as they are.

More information about the pulseaudio-discuss mailing list