trummerschlunk / master_me

automatic mastering plugin for live streaming, podcasts and internet radio.
GNU General Public License v3.0
546 stars 22 forks source link

Multiband compressor introduces phase smearing #26

Closed x42 closed 2 years ago

x42 commented 2 years ago

I did a few listening tests, and the confirmed this by measurement. The LR4 cross-over network used by the mscomp adds a 180 deg phase-shift where bands overlap:

mscomp-phase-smearing

A multiband compressor is commonly implemented:

I've whipped up some FAUST code for this which should be straight forward to integrate here.

https://gist.github.com/eeb2aa9f9cc4a9083fb2cf2d86645c9a

@magnetophon Since you have significantly contributed to FAUST's compressor lib, you may be interested in this as well.

magnetophon commented 2 years ago

@x42 Thanks a lot for making this! We should definitely use this approach, imho.

@dariosanfilippo Since you wrote the crossover we are using atm, you may be interested in this as well. Probably nothing you didn't know already, but still.

I know that crossovers smear the phase, but I didn't know that MB-compressors where commonly implemented with shelving filters. Therefore, I naively thought I was somewhat original when I made https://github.com/magnetophon/shelfMultiBand ¯\_(ツ)_/¯

@x42 I have a hard time reading compcalc. Could you explain what you mean by:

 * This is similar to `(co).peak_compression_gain_mono_db`, except
 * signal power is used, and there is a fixed exponential knee.

By signal power, you mean the x*x here, correct? What does that do, why is it better? Is it similar to an RMS compressor?

What do you mean by exponential, when you say it has an exponential knee? Can the knee also be variable, using this algo?

In general, what does this do different from mine? Should we try to include it in the faust libraries?

magnetophon commented 2 years ago

@x42 IIUC, you compressor's release time is dependent on the attack, correct? If yes, do you prefer that? If yes, why do you prefer it?

x42 commented 2 years ago

What does that do, why is it better?

It's not better just different, and yes averaged x^2 is RMS. I'm yet to implement some gain hold logic to prevent excessive gain and "pumping". If there is interest to add it to the faust libs I'll re-license it then to ISC or MIT when it's done.

x42 commented 2 years ago

Therefore, I naively thought I was somewhat original when I made https://github.com/magnetophon/shelfMultiBand ¯_(ツ)_/¯

heh. well, harrison's XT-MC pre-dates that by at least half a decade, and other pro-audio plugins (iZotope, FabFilter) use this as well or have an option to pick the filter for the signal-stream and key-analysis.

I have a hard time reading compcalc

The feeling is mutual :) I thought tour code is rather complicated, but reading it I learned a nice trick how you use *Group at the top, to re-use subsets!

BTW. I really like the UI for XT-MC. This is also where I stole the idea of matched meter and threshold control range, that klaus picked up on in https://github.com/trummerschlunk/soundsgood/issues/23#issuecomment-1217878672 image

x42 commented 2 years ago

you compressor's release time is dependent on the attack, correct?

No. they're separate. Attack is applied to the input level (using a 1st order LPF) and release is applied to result (using a 2nd order LPF), IFF unless the signal exceeds the threshold. the ba.if clause is used for that. zr2 is effectively a filtered (square) of the input-level relative to the threshold. The effective gain is then (zr2) ^ (-ratio). Here with a ratio of [0, -.5] since it applies to signal power.

As for the transfer curve it is similar to darc.lv2, except it doesn't have auto-gain and a fixed point at -10dB/RMS. There is a constant reduction, even well below the threshold (due to the exponential relationship ^(-ratio). The FAUST code currrently differs from darc.lv2 and uses sqrt(2 * zr2) to map it against arbitrary, cases without the auto-gain.

image

Another nice feature is that the "Hold" is not time-dependent, but level dependent. So if the level drops rapidly, no additional gain is added. This is great for vocals. where there can be some silence that is longer than the release time and other compressor will open up and make the noise floor audible. It fees the release time to do actual release while there is a signal.

Anyway, for the case at hand you probably only want the top 10 lines of gist and re-use the shelving filters.

dariosanfilippo commented 2 years ago

Dear Robin, thank you so much for pointing this out.

I did a few listening tests, and the confirmed this by measurement. The LR4 cross-over network used by the mscomp adds a 180 deg phase-shift where bands overlap:

Could you please tell me what is the exact setup that you have for your tests? I.e., how many bands in your crossover and what frequency cutoffs?

Is the problem the dip in the mag response that I see in your image? I checked the crossover networks with a few other people and it seemed that the phase corrections were correct, also based on what Zavalishin suggests in his book, but I'll investigate the issue.

Cheers, Dario

mscomp-phase-smearing

A multiband compressor is commonly implemented:

  • Band-split the key signal (x-over network of LR4 is fine here)
  • Analyze each freq band, calculate compression gain
  • Use shelving filters to apply the gain to the signal

I've whipped up some FAUST code for this which should be straight forward to integrate here.

https://gist.github.com/eeb2aa9f9cc4a9083fb2cf2d86645c9a

@magnetophon Since you have significantly contributed to FAUST's compressor lib, you may be interested in this as well.

x42 commented 2 years ago

Could you please tell me what is the exact setup that you have for your tests?

It is this project compiled using Faust-2.41 to a LV2 plugin and the using Ardour's plugin-analysis tool to plot magnitude and phase response, using a sample-rate of 48kHz. For the plot all stages other than the multi-band compressor were bypassed.

So this is effecively just measuring the fi.crossover8LR4 filters for the multiband compressor https://github.com/trummerschlunk/soundsgood/blob/95afee16e87d9cbcbbc1e31505b4ca9bdf7b5923/soundsgood.dsp#L243

There is a 180 deg phase shift at each transition point. The red line in the plot (Y axis labels on the right in the plot).

Magnitude is fine (give or take the slight dip, which may be the compressor kicking in, in response to to the measurement, sending a delta impulse though it).

how many bands in your crossover and what frequency cutoffs?

In this case there are 8 filters. When I measured it, the filters freq. were hardcoded: https://github.com/trummerschlunk/soundsgood/blob/4e69588c6913b9aca97e5de08a7e6ca06b350c95/soundsgood.dsp#L262

Anyway just a simple process = fi.crossover2LR4 (f) : + also show this.

dariosanfilippo commented 2 years ago

Hi, @x42.

Thanks for the information.

I see, so the problem is the phase shift in the final signal, which I'd expect due to the two cascaded SVF filters in the networks. I guess that the technique using shelving filters avoids that, which I will study as I am not familiar with it.

Thanks again for this.

Dario

x42 commented 2 years ago

@dariosanfilippo alternatively you could use 1st order filters.

This is what Zam Multicomp does -- note the code incorrectly has a LR4 label, but correctly cites https://cytomic.com/files/dsp/SvfInputMixing.pdf -- but zamaudio uses a 3 band filter only; 6dB likely has too much overlap for a 8 freq split.

--

Edit: re-reading zamulticomp's source and looking at the transfer function. the low and high -filters are also shelves.

I've just started reading "The Design of Active Crossovers" by Douglas Self and it seems that LR4 is acceptable for a single crossover: "The conclusion we can draw is that a crossover whose summed phase response is that of a 1st-order or 2nd-order allpass filter is wholly acceptable." (page 59, 2nd edition).

The case at hand however has multiple such phase shifts.

magnetophon commented 2 years ago

@x42:

you compressor's release time is dependent on the attack, correct?

No. they're separate.

Thanks for the explanation.

Another nice feature is that the "Hold" is not time-dependent, but level dependent.

Could you talk about how this works behind te scenes? I always want to learn more about auto-release tactics, as I think they can greatly improve the sound.

Anyway, for the case at hand you probably only want the top 10 lines of gist and re-use the shelving filters.

Agreed, but the auto-hold might be interesting. I haven't taken the time to do listening test yet, though, sorry.

x42 commented 2 years ago

Could you talk about how this works behind the scenes?

I've just added it to the gist. tl;dr freeze the current gain level when the signal falls below a given threshold.