From 3e124704b07e35827f46457d8a0640d67a2c052e Mon Sep 17 00:00:00 2001 From: Johannes Mueller Date: Fri, 4 Aug 2017 11:07:33 +0200 Subject: [PATCH] GR-based visualization in a-comp --- libs/plugins/a-comp.lv2/a-comp.c | 109 ++++++++++++++++--------------- 1 file changed, 55 insertions(+), 54 deletions(-) diff --git a/libs/plugins/a-comp.lv2/a-comp.c b/libs/plugins/a-comp.lv2/a-comp.c index a77893782b..cabbd8cbde 100644 --- a/libs/plugins/a-comp.lv2/a-comp.c +++ b/libs/plugins/a-comp.lv2/a-comp.c @@ -79,8 +79,6 @@ typedef struct { float srate; - float old_in_peak_db; - float makeup_gain; #ifdef LV2_EXTENDED @@ -101,6 +99,7 @@ typedef struct { float v_makeup; float v_lvl_in; float v_lvl_out; + float v_state_x; #endif } AComp; @@ -251,7 +250,6 @@ activate(LV2_Handle instance) *(acomp->gainr) = 0.0f; *(acomp->outlevel) = -45.0f; - acomp->old_in_peak_db = -160.0f; } static void @@ -318,18 +316,21 @@ run_mono(LV2_Handle instance, uint32_t n_samples) } #endif - float in_peak = 0.f; + float in_peak_db = -160.f; float max_gainr = 0.f; for (i = 0; i < n_samples; i++) { in0 = input[i]; sc0 = sc[i]; ingain = usesidechain ? fabs(sc0) : fabs(in0); - in_peak = fmaxf (in_peak, ingain); Lyg = 0.f; Lxg = (ingain==0.f) ? -160.f : to_dB(ingain); Lxg = sanitize_denormal(Lxg); + if (Lxg > in_peak_db) { + in_peak_db = Lxg; + } + if (2.f*(Lxg-thresdb) < -width) { Lyg = Lxg; } else if (2.f*(Lxg-thresdb) > width) { @@ -377,32 +378,27 @@ run_mono(LV2_Handle instance, uint32_t n_samples) #ifdef LV2_EXTENDED acomp->v_gainr = max_gainr; - 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); - - 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; - } - - 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 + const float v_lvl_out = *acomp->outlevel; + + float state_x; + + const float knee_lim_gr = (1.f - 1.f/ratio) * width/2.f; + + if (acomp->v_gainr > knee_lim_gr) { + state_x = acomp->v_gainr / (1.f - 1.f/ratio) + thresdb; + } else { + state_x = sqrt ( (2.f*width*acomp->v_gainr) / (1.f-1.f/ratio) ) + thresdb - width/2.f; + } + + if (fabsf (acomp->v_lvl_out - v_lvl_out) >= .1f || + fabsf (acomp->v_lvl_in - v_lvl_in) >= .1f || + fabsf (acomp->v_state_x - state_x) >= .1f ) { + // >= 0.1dB difference acomp->need_expose = true; acomp->v_lvl_in = v_lvl_in; - const float relax_coef = exp(-(float)n_samples/srate); - acomp->v_lvl_out = fmaxf (v_lvl_out, relax_coef*acomp->v_lvl_out + (1.f-relax_coef)*v_lvl_out); + acomp->v_lvl_out = v_lvl_out; + acomp->v_state_x = state_x; } if (acomp->need_expose && acomp->queue_draw) { acomp->need_expose = false; @@ -480,7 +476,7 @@ run_stereo(LV2_Handle instance, uint32_t n_samples) } #endif - float in_peak = 0.f; + float in_peak_db = -160.f; float max_gainr = 0.f; for (i = 0; i < n_samples; i++) { @@ -489,10 +485,12 @@ run_stereo(LV2_Handle instance, uint32_t n_samples) sc0 = sc[i]; maxabslr = fmaxf(fabs(in0), fabs(in1)); ingain = usesidechain ? fabs(sc0) : maxabslr; - in_peak = fmaxf (in_peak, ingain); Lyg = 0.f; Lxg = (ingain==0.f) ? -160.f : to_dB(ingain); Lxg = sanitize_denormal(Lxg); + if (Lxg > in_peak_db) { + in_peak_db = Lxg; + } if (2.f*(Lxg-thresdb) < -width) { Lyg = Lxg; @@ -543,33 +541,27 @@ run_stereo(LV2_Handle instance, uint32_t n_samples) #ifdef LV2_EXTENDED acomp->v_gainr = max_gainr; - 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); - - 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; - } - - 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 + const float v_lvl_out = *acomp->outlevel; + + float state_x; + + const float knee_lim_gr = (1.f - 1.f/ratio) * width/2.f; + + if (acomp->v_gainr > knee_lim_gr) { + state_x = acomp->v_gainr / (1.f - 1.f/ratio) + thresdb; + } else { + state_x = sqrt ( (2.f*width*acomp->v_gainr) / (1.f-1.f/ratio) ) + thresdb - width/2.f; + } + + if (fabsf (acomp->v_lvl_out - v_lvl_out) >= .1f || + fabsf (acomp->v_lvl_in - v_lvl_in) >= .1f || + fabsf (acomp->v_state_x - state_x) >= .1f ) { + // >= 0.1dB difference acomp->need_expose = true; acomp->v_lvl_in = v_lvl_in; - const float relax_coef = exp(-2.0*n_samples/srate); - acomp->v_lvl_out = fmaxf (v_lvl_out, relax_coef*acomp->v_lvl_out + (1.f-relax_coef)*v_lvl_out); + acomp->v_lvl_out = v_lvl_out; + acomp->v_state_x = state_x; } if (acomp->need_expose && acomp->queue_draw) { acomp->need_expose = false; @@ -705,6 +697,15 @@ render_inline_full (cairo_t* cr, const AComp* self) cairo_stroke (cr); } + // draw state + cairo_set_source_rgba (cr, .8, .8, .8, 1.0); + + const float state_x = w * (1.f - (10.f-self->v_state_x)/70.f); + const float state_y = h * (comp_curve (self, self->v_state_x) - 10.f) / -70.f; + + cairo_arc (cr, state_x, state_y, 3.f, 0.f, 2.f*M_PI); + cairo_fill (cr); + // draw curve cairo_set_source_rgba (cr, .8, .8, .8, 1.0); cairo_move_to (cr, 0, h);