wwmm / easyeffects

Limiter, compressor, convolver, equalizer and auto volume and many other plugins for PipeWire applications
GNU General Public License v3.0
6.56k stars 270 forks source link

LSP Limiter #1054

Closed v-fox closed 3 years ago

v-fox commented 3 years ago

Same as #1031 - would be nice to use LSP limiter with ALR and avoid https://github.com/calf-studio-gear/calf/issues/217

The only deficiency in LSP limiter now is that it's not multiband. Hopefully, this will be alleviated with https://github.com/sadko4u/lsp-plugins/issues/140 And then also https://github.com/sadko4u/lsp-plugins/issues/196

wwmm commented 3 years ago

I did not consider that Calf's limiter was also affected by the crossover issue. I thought that only the multiband plugins were affected.

v-fox commented 3 years ago

I did not consider that Calf's limiter was also affected by the crossover issue. I thought that only the multiband plugins were affected.

I just noticed that you're not using multiband Calf limiter which gives much better results, thanks to differentiated release time and weights, than single-band, the crossover issue notwithstanding. Naturally, when it's implemented in LSP, it will be the superior limiter implementation.

I would like to try to migrate my standalone setup of https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/698 but LSP limiter is the most important part of it. I would need to figure out per-output equalizer configuration with shared configuration among several outputs for the rest of plugins.

Digitalone1 commented 3 years ago

I'm working on porting LSP multiband compressor. If LSP limiter is needed, it has to be introduced in the same release the new mbc is implemented, otherwise too much changes for the user will be made in different releases breaking existing presets.

Digitalone1 commented 3 years ago

Tomorrow I'm starting the port of this plugin which I hope it can be introduced in the next release (that is quite big since the new mbc and other changes, I think it deserves 6.1 tag).

Digitalone1 commented 3 years ago

@wwmm The LSP Limiter has a Dither option. If enabled, it goes from 7 to 24 bit.

As I read here:

When to add dither is a subject of some confusion and even controversy. The simplest way to look at it is that you should always dither when going down in bit-depth. So, if you’re going from 24-bit to 16-bit, you should dither. If you’re going from 32-bit fixed point (not floating point) to 24- or 16-bit, you should dither.

Since all the pipeline is handled at 32 bit, I think it's not needed to expose it in the UI, right?

v-fox commented 3 years ago

Since all the pipeline is handled at 32 bit, I think it's not needed to expose it in the UI, right?

I don't think that on principle you shouldn't cut features that already present.

In this case, I'm not sure how useful dithering is BUT note that limiter is usually the last processing stage before offloading to hardware. And most modern DACs use 24-bit integer PCM (rarely, there is also 32-bit integer PCM) put into 24 or 32 bit integer "words". Meaning that 32-bit float is downsampled into 24-bit integer at that point. It's unclear how well things are dithered in PipeWire during this conversion, so pre-dithering at that point may or may not decrease conversion distortion.

To be honest, I'm not sure what it could mean to "go from 32-bit fixed point (not floating point) to 24- or 16-bit" because I newer heard about integer formats being used for software processing of audio streams, especially in LV2 plugins that run atop of JACK API. Maybe it's intended to be used when using 24i input with 16i output, despite 32f stream in between ?

Moreover, for some inexplicable reason, setting dither=none in LSP limiter leads to endless stream of errors (in pw-top and pipewire daemon log) for me in all JACK nodes during silence.

Digitalone1 commented 3 years ago

I don't think that on principle you shouldn't cut features that already present.

I don't want to do it, but take in consideration that plugins are built to be run in Ardour or on Jack. EE is a specific software and maybe some options are useless since it has its own pipeline. In our case the last plugin is not really the last processing stage, the stream has to go also over spectrum and output level meter, even if they are only analysing the signal.

If the option is useless in our context, it's not needed to be added. For that reason I'm asking.

v-fox commented 3 years ago

In our case the last plugin is not really the last processing stage,

That's what limiter with compression / automatic gain control is for. Otherwise its job of preventing clipping may be negated.

the stream has to go also over spectrum and output level meter, even if they are only analysing the signal.

Which is why it may as well be the last. Analyzer should not influence signal.

If the option is useless in our context, it's not needed to be added. For that reason I'm asking.

If anything, it should be defaulted to "24-bit" setting until the reason for massive errors under PW during silence is found. In my particular case, combination of multiband compressor and limiter may exacerbate the situation in comparison to only having limiter, so you may need to put MBC beforehand to reproduce (check for errors with pw-top and journalctl --no-hostname -b0 -e --user -u pipewire).

Digitalone1 commented 3 years ago

To be honest, I'm not sure what it could mean to "go from 32-bit fixed point (not floating point) to 24- or 16-bit" because I newer heard about integer formats being used for software processing of audio streams, especially in LV2 plugins that run atop of JACK API. Maybe it's intended to be used when using 24i input with 16i output, despite 32f stream in between ?

The page I cited has the following tip:

You don’t need to dither when going from 32-bit floating point to 24-bit 
(because 32-bit floating point doesn’t have a higher bit depth), 
but you do from 32-bit fixed point to any lower bit depth.

If anything, it should be defaulted to "24-bit" setting until the reason for massive errors under PW during silence is found.

I think we have to default to something useful, not to something else to prevent LSP bugs.

At last I think we could keep the option, even if it's use would be very useless.

wwmm commented 3 years ago

Although I really doubt that option will be useful for the majority of our users it is not a big problem to keep it there. Based on what I read on wikipedia https://en.wikipedia.org/wiki/Dither dithering in audio samples would be more useful when saving the processed audio to 16 bits media. Maybe that is what LSP author had in mind when he added this feature to the limiter. As I can not guarantee that none of our users will ever need to do something like that it is better to keep the option.

I think we have to default to something useful, not to something else to prevent LSP bugs.

Ideally our default should be to have dithering disabled. Dithering adds noise in order to remove quantization errors. If such errors are of no concern it does not make sense to add noise for nothing.

wwmm commented 3 years ago

Which is why it may as well be the last. Analyzer should not influence signal.

That is right. They are just analysing the data in passthrough mode. No change to the audio content is done.

v-fox commented 3 years ago

The page I cited has the following tip: …

That's great but we aren't talking here about some generic dithering. LSP is intended to work in JACK API that only has 32-bit float format, so you would have to ask its author what was his intention. Not sure if LV2 plugins can even use anything else. So only "saving" would be dumping or redirecting 32f stream.

I think we have to default to something useful, not to something else to prevent LSP bugs.

I'm pretty sure that not dropping thousands errors per minute and degrading expensive SSDs by stream of useless journald logs by default is useful. Not sure if it's LSP bug or PW bug.

Ideally our default should be to have dithering disabled. Dithering adds noise in order to remove quantization errors. If such errors are of no concern it does not make sense to add noise for nothing.

As I've said, DACs take integers, so float is always down-converted and precision is lost. The question is: how "concerning" that should be ? When you do such conversion from 16f image into 8i display format without dithering, you get super-ugly ringing artefacts. I assume that similar thing could happen in "bad" down-conversion of audio. I don't know what would be reasoning for stating that 32f and 24i somehow equal and have no loss when down-sampling with simple averaging without dithering.

But the bigger concern is behaviour with it off. I inclined to believe that it's more of PW bug than LSP due to https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/698 as it also likes to drop errors when "heavy" plugins like MBC and Calf's Exciter/Enhancer are active, regardless of CPU usage or buffer size. Except that in this case it drops errors only on silence.

wwmm commented 3 years ago

Not sure if LV2 plugins can even use anything else

Even if it does my wrapper based on PipeWire filters is forcing PipeWire to send us float 32.

marcan commented 2 years ago

The page I cited has the following tip:

You don’t need to dither when going from 32-bit floating point to 24-bit 
(because 32-bit floating point doesn’t have a higher bit depth), 
but you do from 32-bit fixed point to any lower bit depth.

This is not correct. 32-bit floating point has the same bit depth as 24-bit when your signal is at full range. Unless you are dithering something this loud, your 24-bit output will have less than 24 bits of resolution when the signal is quieter, while the 32-bit output will retain 24 bits of resolution throughout the entire dynamic range of the track, even the quietest sections. In other words, the 24 bit output will have ~-144 dBFS of quantization noise throughout, while the 32-bit output will have quantization noise that is 144 dB below the signal level at all times, whatever that may be (well, at least down to -700dBFS or so, which is where you run into denormals or FTZ).

That said, quantization noise at 24 bits is so utterly negligible that, in practice, nobody will ever be able to tell whether you dithered or not, unless you're massively boosting the gain of the output at a later point.

Dither options in limiter plug-ins are designed to be used in DAWs when exporting to 24-bit or 16-bit formats, where the DAW does not do proper dithering itself. It's a hack, you end up with a 32f output that is always rounded to the nearest 24i or 16i sample value, and hopefully the DAW turns it into that same value when exporting in the actual integer format.

sadko4u commented 10 months ago

@v-fox

Moreover, for some inexplicable reason, setting dither=none in LSP limiter leads to endless stream of errors (in pw-top and pipewire daemon log) for me in all JACK nodes during silence.

This may be the reason how PipeWire handles very small (denormalized) floating-point numbers. Dithering eliminates denormalized values, and this may be the case your system is working well. Denormalized values ARE VERY HEAVY at computation and give SIGNIFICANT PERFORMANCE PENALTY on modern CPUs (both Intel and AMD are affected). This may cause performance degradation, freezes and stutters in real-time audio.

I think it is a good reason to ask PipeWire developers to enable FTZ and DAZ before launching any audio processing chain.

v-fox commented 10 months ago

@sadko4u

This may be the reason how PipeWire handles very small (denormalized) floating-point numbers. Dithering eliminates denormalized values, and this may be the case your system is working well. Denormalized values ARE VERY HEAVY at computation and give SIGNIFICANT PERFORMANCE PENALTY on modern CPUs (both Intel and AMD are affected). This may cause performance degradation, freezes and stutters in real-time audio.

I think it is a good reason to ask PipeWire developers to enable FTZ and DAZ before launching any audio processing chain.

At some point it got cpu.zero.denormals option in pipewire.conf but, I think, it still defaults to false. I use it with true for my setup but I also left dithering to 24 bits since it doesn't seem to noticeably affect performance.