diff options
-rw-r--r-- | libs/plugins/a-comp.lv2/a-comp.c | 135 |
1 files changed, 71 insertions, 64 deletions
diff --git a/libs/plugins/a-comp.lv2/a-comp.c b/libs/plugins/a-comp.lv2/a-comp.c index 89bd5c9270..a77893782b 100644 --- a/libs/plugins/a-comp.lv2/a-comp.c +++ b/libs/plugins/a-comp.lv2/a-comp.c @@ -78,9 +78,8 @@ typedef struct { float* output1; float srate; - float old_yl; - float old_y1; - float old_yg; + + float old_in_peak_db; float makeup_gain; @@ -100,8 +99,6 @@ typedef struct { float v_thresdb; float v_gainr; float v_makeup; - float v_lvl; - float v_lv1; float v_lvl_in; float v_lvl_out; #endif @@ -124,7 +121,6 @@ instantiate(const LV2_Descriptor* descriptor, } acomp->srate = rate; - acomp->old_yl=acomp->old_y1=acomp->old_yg=0.f; acomp->makeup_gain = 1.f; #ifdef LV2_EXTENDED acomp->need_expose = true; @@ -134,7 +130,6 @@ instantiate(const LV2_Descriptor* descriptor, return (LV2_Handle)acomp; } - static void connect_port(LV2_Handle instance, uint32_t port, @@ -256,7 +251,7 @@ activate(LV2_Handle instance) *(acomp->gainr) = 0.0f; *(acomp->outlevel) = -45.0f; - acomp->old_yl=acomp->old_y1=acomp->old_yg=0.f; + acomp->old_in_peak_db = -160.0f; } static void @@ -270,14 +265,16 @@ run_mono(LV2_Handle instance, uint32_t n_samples) float srate = acomp->srate; float width = (6.f * *(acomp->knee)) + 0.01; - float cdb=0.f; float attack_coeff = exp(-1000.f/(*(acomp->attack) * srate)); float release_coeff = exp(-1000.f/(*(acomp->release) * srate)); float max = 0.f; float lgaininp = 0.f; float Lgain = 1.f; - float Lxg, Lxl, Lyg, Lyl, Ly1; + float Lxg, Lyg; + float current_gainr; + float old_gainr = *acomp->gainr; + int usesidechain = (*(acomp->sidechain) <= 0.f) ? 0 : 1; uint32_t i; float ingain; @@ -333,7 +330,6 @@ run_mono(LV2_Handle instance, uint32_t n_samples) Lxg = (ingain==0.f) ? -160.f : to_dB(ingain); Lxg = sanitize_denormal(Lxg); - if (2.f*(Lxg-thresdb) < -width) { Lyg = Lxg; } else if (2.f*(Lxg-thresdb) > width) { @@ -343,21 +339,23 @@ run_mono(LV2_Handle instance, uint32_t n_samples) Lyg = Lxg + (1.f/ratio-1.f)*(Lxg-thresdb+width/2.f)*(Lxg-thresdb+width/2.f)/(2.f*width); } - Lxl = Lxg - Lyg; + current_gainr = Lxg - Lyg; + + if (current_gainr < old_gainr) { + current_gainr = release_coeff*old_gainr + (1.f-release_coeff)*current_gainr; + } else if (current_gainr > old_gainr) { + current_gainr = attack_coeff*old_gainr + (1.f-attack_coeff)*current_gainr; + } + + current_gainr = sanitize_denormal(current_gainr); - acomp->old_y1 = sanitize_denormal(acomp->old_y1); - acomp->old_yl = sanitize_denormal(acomp->old_yl); - Ly1 = fmaxf(Lxl, release_coeff * acomp->old_y1+(1.f-release_coeff)*Lxl); - Lyl = attack_coeff * acomp->old_yl+(1.f-attack_coeff)*Ly1; - Ly1 = sanitize_denormal(Ly1); - Lyl = sanitize_denormal(Lyl); + Lgain = from_dB(-current_gainr); - cdb = -Lyl; - Lgain = from_dB(cdb); + old_gainr = current_gainr; - *(acomp->gainr) = Lyl; - if (Lyl > max_gainr) { - max_gainr = Lyl; + *(acomp->gainr) = current_gainr; + if (current_gainr > max_gainr) { + max_gainr = current_gainr; } lgaininp = in0 * Lgain; @@ -365,12 +363,6 @@ run_mono(LV2_Handle instance, uint32_t n_samples) output[i] = lgaininp * makeup_gain; max = (fabsf(output[i]) > max) ? fabsf(output[i]) : sanitize_denormal(max); - - // TODO re-use local variables on stack - // store values back to acomp at the end of the inner-loop - acomp->old_yl = Lyl; - acomp->old_y1 = Ly1; - acomp->old_yg = Lyg; } if ( fabsf(makeup_target - makeup_gain) < 1e-6 ) { @@ -385,17 +377,25 @@ run_mono(LV2_Handle instance, uint32_t n_samples) #ifdef LV2_EXTENDED acomp->v_gainr = max_gainr; - const float old_v_lv1 = acomp->v_lv1; - const float old_v_lvl = acomp->v_lvl; + float in_peak_db = to_dB(in_peak); + + if (!isfinite_local (in_peak_db)) { + in_peak_db = -160.0f; + } const float tot_rel_c = exp(-1000.f/(*(acomp->release) * srate) * n_samples); const float tot_atk_c = exp(-1000.f/(*(acomp->attack) * srate) * n_samples); - acomp->v_lv1 = fmaxf (in_peak, tot_rel_c*old_v_lv1 + (1.f-tot_rel_c)*in_peak); - acomp->v_lvl = tot_atk_c*old_v_lvl + (1.f-tot_atk_c)*acomp->v_lv1; - if (!isfinite_local (acomp->v_lvl)) { - acomp->v_lvl = 0.f; + const float old_in_peak_db = acomp->old_in_peak_db; + + if (in_peak_db < old_in_peak_db && in_peak_db < thresdb) { + in_peak_db = tot_rel_c*old_in_peak_db + (1.f-tot_rel_c)*in_peak_db; + } else if (in_peak_db > acomp->old_in_peak_db && in_peak_db > thresdb) { + in_peak_db = tot_atk_c*old_in_peak_db+ (1.f*tot_atk_c)*in_peak_db; } - const float v_lvl_in = (acomp->v_lvl < 0.001f) ? -60.f : to_dB(acomp->v_lvl); + + acomp->old_in_peak_db = in_peak_db; + + const float v_lvl_in = in_peak_db; const float v_lvl_out = (max < 0.001f) ? -60.f : to_dB(max); if (fabsf (acomp->v_lvl_out - v_lvl_out) >= 1 || fabsf (acomp->v_lvl_in - v_lvl_in) >= 1) { // >= 1dB difference @@ -424,7 +424,6 @@ run_stereo(LV2_Handle instance, uint32_t n_samples) float srate = acomp->srate; float width = (6.f * *(acomp->knee)) + 0.01; - float cdb=0.f; float attack_coeff = exp(-1000.f/(*(acomp->attack) * srate)); float release_coeff = exp(-1000.f/(*(acomp->release) * srate)); @@ -432,7 +431,10 @@ run_stereo(LV2_Handle instance, uint32_t n_samples) float lgaininp = 0.f; float rgaininp = 0.f; float Lgain = 1.f; - float Lxg, Lxl, Lyg, Lyl, Ly1; + float Lxg, Lyg; + float current_gainr; + float old_gainr = *acomp->gainr; + int usesidechain = (*(acomp->sidechain) <= 0.f) ? 0 : 1; uint32_t i; float ingain; @@ -492,7 +494,6 @@ run_stereo(LV2_Handle instance, uint32_t n_samples) Lxg = (ingain==0.f) ? -160.f : to_dB(ingain); Lxg = sanitize_denormal(Lxg); - if (2.f*(Lxg-thresdb) < -width) { Lyg = Lxg; } else if (2.f*(Lxg-thresdb) > width) { @@ -502,21 +503,23 @@ run_stereo(LV2_Handle instance, uint32_t n_samples) Lyg = Lxg + (1.f/ratio-1.f)*(Lxg-thresdb+width/2.f)*(Lxg-thresdb+width/2.f)/(2.f*width); } - Lxl = Lxg - Lyg; + current_gainr = Lxg - Lyg; + + if (current_gainr < old_gainr) { + current_gainr = release_coeff*old_gainr + (1.f-release_coeff)*current_gainr; + } else if (current_gainr > old_gainr) { + current_gainr = attack_coeff*old_gainr + (1.f-attack_coeff)*current_gainr; + } - acomp->old_y1 = sanitize_denormal(acomp->old_y1); - acomp->old_yl = sanitize_denormal(acomp->old_yl); - Ly1 = fmaxf(Lxl, release_coeff * acomp->old_y1+(1.f-release_coeff)*Lxl); - Lyl = attack_coeff * acomp->old_yl+(1.f-attack_coeff)*Ly1; - Ly1 = sanitize_denormal(Ly1); - Lyl = sanitize_denormal(Lyl); + current_gainr = sanitize_denormal(current_gainr); - cdb = -Lyl; - Lgain = from_dB(cdb); + Lgain = from_dB(-current_gainr); - *(acomp->gainr) = Lyl; - if (Lyl > max_gainr) { - max_gainr = Lyl; + old_gainr = current_gainr; + + *(acomp->gainr) = current_gainr; + if (current_gainr > max_gainr) { + max_gainr = current_gainr; } lgaininp = in0 * Lgain; @@ -526,12 +529,6 @@ run_stereo(LV2_Handle instance, uint32_t n_samples) output1[i] = rgaininp * makeup_gain; max = (fmaxf(fabs(output0[i]), fabs(output1[i])) > max) ? fmaxf(fabs(output0[i]), fabs(output1[i])) : sanitize_denormal(max); - - // TODO re-use local variables on stack - // store values back to acomp at the end of the inner-loop - acomp->old_yl = Lyl; - acomp->old_y1 = Ly1; - acomp->old_yg = Lyg; } if ( fabsf(makeup_target - makeup_gain) < 1e-6 ) { @@ -546,16 +543,26 @@ run_stereo(LV2_Handle instance, uint32_t n_samples) #ifdef LV2_EXTENDED acomp->v_gainr = max_gainr; - const float old_v_lv1 = acomp->v_lv1; - const float old_v_lvl = acomp->v_lvl; + float in_peak_db = to_dB(in_peak); + + if (!isfinite_local (in_peak_db)) { + in_peak_db = -160.0f; + } + const float tot_rel_c = exp(-1000.f/(*(acomp->release) * srate) * n_samples); const float tot_atk_c = exp(-1000.f/(*(acomp->attack) * srate) * n_samples); - acomp->v_lv1 = fmaxf (in_peak, tot_rel_c*old_v_lv1 + (1.f-tot_rel_c)*in_peak); - acomp->v_lvl = tot_atk_c*old_v_lvl + (1.f-tot_atk_c)*acomp->v_lv1; - if (!isfinite_local (acomp->v_lvl)) { - acomp->v_lvl = 0.f; + + const float old_in_peak_db = acomp->old_in_peak_db; + + if (in_peak_db < old_in_peak_db && in_peak_db < thresdb) { + in_peak_db = tot_rel_c*old_in_peak_db + (1.f-tot_rel_c)*in_peak_db; + } else if (in_peak_db > acomp->old_in_peak_db && in_peak_db > thresdb) { + in_peak_db = tot_atk_c*old_in_peak_db+ (1.f*tot_atk_c)*in_peak_db; } - const float v_lvl_in = (acomp->v_lvl < 0.001f) ? -60.f : to_dB(acomp->v_lvl); + + acomp->old_in_peak_db = in_peak_db; + + const float v_lvl_in = in_peak_db; const float v_lvl_out = (max < 0.001f) ? -60.f : to_dB(max); if (fabsf (acomp->v_lvl_out - v_lvl_out) >= 1 || fabsf (acomp->v_lvl_in - v_lvl_in) >= 1) { // >= 1dB difference |