[SCM] calf/master: Multiband limiter: ASC fixes.
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:40:52 UTC 2013
The following commit has been merged in the master branch:
commit a6ff6573bdb24b42eb8301b8340980d2b2c56f37
Author: Markus Schmidt <schmidt at boomshop.net>
Date: Fri Feb 10 00:29:00 2012 +0000
Multiband limiter: ASC fixes.
diff --git a/src/audio_fx.cpp b/src/audio_fx.cpp
index a5695be..139c090 100644
--- a/src/audio_fx.cpp
+++ b/src/audio_fx.cpp
@@ -633,6 +633,26 @@ void lookahead_limiter::reset_asc() {
asc_changed = true;
}
+float lookahead_limiter::get_rdelta(float peak, float _limit, float _att, bool _asc) {
+
+ // calc the att for average input to walk to if we use asc (att of average signal)
+ float _a_att = (limit * weight) / (asc_coeff * asc) * (float)asc_c;
+
+ // calc a release delta from this attenuation
+ float _rdelta = (1.0 - _att) / (srate * release);
+ if(_asc and auto_release and asc_c > 0 and _a_att > _att) {
+ // check if releasing to average level of peaks is steeper than
+ // releasing to 1.f
+ float _delta = std::max((_a_att - _att) / (srate * release), _rdelta / 10);
+ if(_delta < _rdelta) {
+ asc_active = true;
+ _asc_used = true;
+ _rdelta = _delta;
+ }
+ }
+ return _rdelta;
+}
+
void lookahead_limiter::process(float &left, float &right, float * multi_buffer)
{
// PROTIP: harming paying customers enough to make them develop a competing
@@ -648,15 +668,15 @@ void lookahead_limiter::process(float &left, float &right, float * multi_buffer)
buffer[pos] = left;
buffer[pos + 1] = right;
}
-
+
// are we using multiband? get the multiband coefficient or use 1.f
float multi_coeff = (use_multi) ? multi_buffer[pos] : 1.f;
-
- // input peak - impact higher in left or right channel?
- peak = fabs(left) > fabs(right) ? fabs(left) : fabs(right);
-
+
// calc the real limit including weight and multi coeff
float _limit = limit * multi_coeff * weight;
+
+ // input peak - impact higher in left or right channel?
+ peak = fabs(left) > fabs(right) ? fabs(left) : fabs(right);
// add an eventually appearing peak to the asc fake buffer if asc active
if(auto_release and peak > _limit) {
@@ -667,22 +687,11 @@ void lookahead_limiter::process(float &left, float &right, float * multi_buffer)
if(peak > _limit or multi_coeff < 1.0) {
float _multi_coeff = 1.f;
float _peak;
-
+
// calc the attenuation needed to reduce incoming peak
float _att = std::min(_limit / peak, 1.f);
-
-
- // calc a release delta from this attenuation
- float _rdelta = (1.0 - _att) / (srate * release);
- if(auto_release and asc_c > 0) {
- // check if releasing to average level of peaks is steeper than
- // releasing to 1.f
- float _delta = std::max((limit * weight) / (asc_coeff * asc) * (float)asc_c - _att, 0.000001f) / (srate * release);
- if(_delta < _rdelta) {
- asc_active = true;
- _rdelta = _delta;
- }
- }
+ // calc release without any asc to keep all relevant peaks
+ float _rdelta = get_rdelta(peak, _limit, _att, false);
// calc the delta for walking to incoming peak attenuation
float _delta = (_limit / peak - att) / buffer_size * channels;
@@ -764,12 +773,32 @@ void lookahead_limiter::process(float &left, float &right, float * multi_buffer)
// ...and calculate outpout from it
left *= att;
right *= att;
-
+
if((pos + channels) % buffer_size == nextpos[nextiter]) {
// if we reach a buffered position, change the actual delta and erase
// this (the first) element from nextpos and nextdelta buffer
- delta = nextdelta[nextiter];
- nextlen = (nextlen - 1) % buffer_size;
+ if(auto_release) {
+ // set delta to asc influenced release delta
+ delta = get_rdelta(_peak, (limit * weight * _multi_coeff), att);
+ if(nextlen > 1) {
+ // if there are more positions to walk to, calc delta to next
+ // position in buffer and compare it to release delta (keep
+ // changes between peaks below asc steepness)
+ int _nextpos = nextpos[(nextiter + 1) % buffer_size];
+ float __peak = fabs(buffer[_nextpos]) > fabs(buffer[_nextpos + 1]) ? fabs(buffer[_nextpos]) : fabs(buffer[_nextpos + 1]);
+ float __multi_coeff = (use_multi) ? multi_buffer[_nextpos] : 1.f;
+ float __delta = ((limit * __multi_coeff * weight) / __peak - att) / (((buffer_size + _nextpos - ((pos + channels) % buffer_size)) % buffer_size) / channels);
+ if(__delta < delta) {
+ delta = __delta;
+ }
+ }
+ } else {
+ // if no asc set delta from nextdelta buffer and fix the attenuation
+ delta = nextdelta[nextiter];
+ att = (limit * weight * _multi_coeff) / _peak;
+ }
+ // remove first element from circular nextpos buffer
+ nextlen -= 1;
nextpos[nextiter] = -1;
nextiter = (nextiter + 1) % buffer_size;
}
@@ -778,6 +807,9 @@ void lookahead_limiter::process(float &left, float &right, float * multi_buffer)
// release time seems over, reset attenuation and delta
att = 1.0f;
delta = 0.0f;
+ nextiter = 0;
+ nextlen = 0;
+ nextpos[0] = -1;
}
// main limiting party is over, let's cleanup the puke
diff --git a/src/calf/audio_fx.h b/src/calf/audio_fx.h
index b4db50f..e2032e2 100644
--- a/src/calf/audio_fx.h
+++ b/src/calf/audio_fx.h
@@ -574,9 +574,9 @@ public:
uint32_t srate;
float att; // a coefficient the output is multiplied with
float att_max; // a memory for the highest attenuation - used for display
- unsigned int pos; // where we are actually in our sample buffer
- unsigned int buffer_size;
- unsigned int overall_buffer_size;
+ int pos; // where we are actually in our sample buffer
+ int buffer_size;
+ int overall_buffer_size;
bool is_active;
bool debug;
bool auto_release;
@@ -600,10 +600,12 @@ public:
int asc_pos;
bool asc_changed;
float asc_coeff;
+ bool _asc_used;
static inline void denormal(volatile float *f) {
*f += 1e-18;
*f -= 1e-18;
}
+ inline float get_rdelta(float peak, float _limit, float _att, bool _asc = true);
void reset();
void reset_asc();
bool get_asc();
diff --git a/src/calf/modules_limit.h b/src/calf/modules_limit.h
index d5d4b9a..29a61ba 100644
--- a/src/calf/modules_limit.h
+++ b/src/calf/modules_limit.h
@@ -66,7 +66,7 @@ private:
float meter_inL, meter_inR, meter_outL, meter_outR;
dsp::lookahead_limiter strip[strips];
dsp::lookahead_limiter broadband;
- dsp::biquad_d2<float> lpL[strips - 1][3], lpR[strips - 1][3], hpL[strips - 1][3], hpR[strips - 1][3];
+ dsp::biquad_d2<float> lpL[strips - 1][strips - 1], lpR[strips - 1][strips - 1], hpL[strips - 1][strips - 1], hpR[strips - 1][strips - 1];
float freq_old[strips - 1], sep_old[strips - 1], q_old[strips - 1];
unsigned int pos;
unsigned int buffer_size;
diff --git a/src/modules_limit.cpp b/src/modules_limit.cpp
index f7fb6fc..e8a4666 100644
--- a/src/modules_limit.cpp
+++ b/src/modules_limit.cpp
@@ -354,12 +354,12 @@ void multibandlimiter_audio_module::params_changed()
rel = *params[param_release] * pow(0.25, *params[param_release0] * -1);
rel = (*params[param_minrel] > 0.5) ? std::max(2500 * (1.f / 30), rel) : rel;
weight[0] = pow(0.25, *params[param_weight0] * -1);
- strip[0].set_params(*params[param_limit], *params[param_attack], rel, weight[0], *params[param_asc], pow(0.5, (*params[param_asc_coeff] - 0.5) * 2 * -1), true);
+ strip[0].set_params(*params[param_limit], *params[param_attack], rel, weight[0], *params[param_asc], pow(0.5, (*params[param_asc_coeff] - 0.5) * 2 * -1));
*params[param_effrelease0] = rel;
rel = *params[param_release] * pow(0.25, *params[param_release1] * -1);
rel = (*params[param_minrel] > 0.5) ? std::max(2500 * (1.f / *params[param_freq0]), rel) : rel;
weight[1] = pow(0.25, *params[param_weight1] * -1);
- strip[1].set_params(*params[param_limit], *params[param_attack], rel, weight[1], *params[param_asc], pow(0.5, (*params[param_asc_coeff] - 0.5) * 2 * -1));
+ strip[1].set_params(*params[param_limit], *params[param_attack], rel, weight[1], *params[param_asc], pow(0.5, (*params[param_asc_coeff] - 0.5) * 2 * -1), true);
*params[param_effrelease1] = rel;
rel = *params[param_release] * pow(0.25, *params[param_release2] * -1);
rel = (*params[param_minrel] > 0.5) ? std::max(2500 * (1.f / *params[param_freq1]), rel) : rel;
@@ -421,6 +421,7 @@ void multibandlimiter_audio_module::set_sample_rate(uint32_t sr)
if(params[param_att##index] != NULL) \
*params[param_att##index] = strip[index].get_attenuation(); \
+
uint32_t multibandlimiter_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
{
bool bypass = *params[param_bypass] > 0.5f;
@@ -656,22 +657,14 @@ bool multibandlimiter_audio_module::get_graph(int index, int subindex, float *da
break;
}
for(int j = 0; j <= j1; j ++) {
- switch(subindex) {
- case 0:
- ret *= lpL[0][j].freq_gain(freq, (float)srate);
- break;
- case 1:
- ret *= hpL[0][j].freq_gain(freq, (float)srate);
- ret *= lpL[1][j].freq_gain(freq, (float)srate);
- break;
- case 2:
- ret *= hpL[1][j].freq_gain(freq, (float)srate);
- ret *= lpL[2][j].freq_gain(freq, (float)srate);
- break;
- case 3:
- ret *= hpL[2][j].freq_gain(freq, (float)srate);
- break;
+ if(subindex == 0)
+ ret *= lpL[0][j].freq_gain(freq, (float)srate);
+ if(subindex > 0 and subindex < strips - 1) {
+ ret *= hpL[subindex - 1][j].freq_gain(freq, (float)srate);
+ ret *= lpL[subindex][j].freq_gain(freq, (float)srate);
}
+ if(subindex == strips - 1)
+ ret *= hpL[2][j].freq_gain(freq, (float)srate);
}
data[i] = dB_grid(ret);
}
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list