diff options
author | Johannes Mueller <github@johannes-mueller.org> | 2017-07-13 21:28:17 +0200 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2017-07-31 21:31:22 +0200 |
commit | 59775df9be375a249b3c4cbdc7e825eee27c393e (patch) | |
tree | d2e42258d00936405ceaee29f3f6bcf996c92db7 /libs | |
parent | 24cbb1b153ad2b380c3e5d5f51913fd93ff0a4fb (diff) |
Simplified inline display if the channel strip is not wide enough
If the width of the display area is below 200 px, we switch from the graph
display to displaying only two bars, one for output level and one for gain
reduction. In the bar mode we also visualize threshold and ratio.
Diffstat (limited to 'libs')
-rw-r--r-- | libs/plugins/a-comp.lv2/a-comp.c | 148 |
1 files changed, 131 insertions, 17 deletions
diff --git a/libs/plugins/a-comp.lv2/a-comp.c b/libs/plugins/a-comp.lv2/a-comp.c index bb282f962c..80985715e7 100644 --- a/libs/plugins/a-comp.lv2/a-comp.c +++ b/libs/plugins/a-comp.lv2/a-comp.c @@ -129,6 +129,7 @@ instantiate(const LV2_Descriptor* descriptor, acomp->tau = (1.0 - exp (-2.f * M_PI * 25.f / acomp->srate)); #ifdef LV2_EXTENDED acomp->need_expose = true; + acomp->v_lvl_out = -70.f; #endif return (LV2_Handle)acomp; @@ -394,7 +395,8 @@ run_mono(LV2_Handle instance, uint32_t n_samples) // >= 1dB difference acomp->need_expose = true; acomp->v_lvl_in = v_lvl_in; - acomp->v_lvl_out = v_lvl_out - to_dB(makeup_gain); + 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); } if (acomp->need_expose && acomp->queue_draw) { acomp->need_expose = false; @@ -547,7 +549,8 @@ run_stereo(LV2_Handle instance, uint32_t n_samples) // >= 1dB difference acomp->need_expose = true; acomp->v_lvl_in = v_lvl_in; - acomp->v_lvl_out = v_lvl_out - to_dB(makeup_gain); + 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); } if (acomp->need_expose && acomp->queue_draw) { acomp->need_expose = false; @@ -582,7 +585,7 @@ cleanup(LV2_Handle instance) #ifdef LV2_EXTENDED static float -comp_curve (AComp* self, float xg) { +comp_curve (const AComp* self, float xg) { const float knee = self->v_knee; const float ratio = self->v_ratio; const float thresdb = self->v_thresdb; @@ -604,23 +607,14 @@ comp_curve (AComp* self, float xg) { return yg; } -static LV2_Inline_Display_Image_Surface * -render_inline (LV2_Handle instance, uint32_t w, uint32_t max_h) +static void +render_inline_full (cairo_t* cr, const AComp* self) { - AComp* self = (AComp*)instance; - uint32_t h = MIN (w, max_h); + const float w = self->w; + const float h = self->h; const float makeup_thres = self->v_thresdb + self->v_makeup; - if (!self->display || self->w != w || self->h != h) { - if (self->display) cairo_surface_destroy(self->display); - self->display = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h); - self->w = w; - self->h = h; - } - - cairo_t* cr = cairo_create (self->display); - // clear background cairo_rectangle (cr, 0, 0, w, h); cairo_set_source_rgba (cr, .2, .2, .2, 1.0); @@ -737,10 +731,130 @@ render_inline (LV2_Handle instance, uint32_t w, uint32_t max_h) cairo_fill (cr); cairo_pattern_destroy (pat); // TODO cache pattern +} + +static void +render_inline_only_bars (cairo_t* cr, const AComp* self) +{ + const float w = self->w; + const float h = self->h; + + cairo_rectangle (cr, 0, 0, w, h); + cairo_set_source_rgba (cr, .2, .2, .2, 1.0); + cairo_fill (cr); + + cairo_set_line_width (cr, 1.0); + + cairo_save (cr); + + const float ht = 0.333f * h; + + const float x1 = w*0.05; + const float wd = w - 2.0f*x1; + + const float y1 = 0.1*h; + const float y2 = h - y1 - ht; + + cairo_set_source_rgba (cr, 0.5, 0.5, 0.5, 0.5); + + cairo_rectangle (cr, x1, y1, wd, ht); + cairo_fill (cr); + + cairo_rectangle (cr, x1, y2, wd, ht); + cairo_fill (cr); + + cairo_set_source_rgba (cr, 0.75, 0.0, 0.0, 1.0); + const float w_gr = (self->v_gainr > 60.f) ? wd : wd * self->v_gainr * (1.f/60.f); + cairo_rectangle (cr, x1+wd-w_gr, y2, w_gr, ht); + cairo_fill (cr); + + if (self->v_lvl_out > -60.f) { + if (self->v_lvl_out > 10.f) { + cairo_set_source_rgba (cr, 0.75, 0.0, 0.0, 1.0); + } else if (self->v_lvl_out > 0.f) { + cairo_set_source_rgba (cr, 0.66, 0.66, 0.0, 1.0); + } else { + cairo_set_source_rgba (cr, 0.0, 0.66, 0.0, 1.0); + } + const float w_g = (self->v_lvl_out > 10.f) ? wd : wd * (60.f+self->v_lvl_out) / 70.f; + cairo_rectangle (cr, x1, y1, w_g, ht); + cairo_fill (cr); + } + + cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0); + + const float tck = 0.25*ht; + + for (uint32_t d = 1; d < 7; ++d) { + const float x = x1 + (d * wd * (10.f / 70.f)); + + cairo_move_to (cr, x, y1); + cairo_line_to (cr, x, y1+tck); + + cairo_move_to (cr, x, y1+ht); + cairo_line_to (cr, x, y1+ht-tck); + + cairo_move_to (cr, x, y2); + cairo_line_to (cr, x, y2+tck); + + cairo_move_to (cr, x, y2+ht); + cairo_line_to (cr, x, y2+ht-tck); + } + + cairo_set_line_width (cr, 2.0); + + const float x_0dB = x1 + wd*(60.f/70.f); + + cairo_move_to (cr, x_0dB, y1); + cairo_line_to (cr, x_0dB, y1+ht); + + cairo_rectangle (cr, x1, y1, wd, ht); + cairo_rectangle (cr, x1, y2, wd, ht); + cairo_stroke (cr); + + // visualize threshold + const float tr = x1 + wd * (60.f+self->v_thresdb) / 70.f; + cairo_set_source_rgba (cr, 0.95, 0.95, 0.0, 1.0); + cairo_move_to (cr, tr, y1); + cairo_line_to (cr, tr, y1+ht); + cairo_stroke (cr); + + // visualize ratio + const float reduced_0dB = self->v_thresdb * (1.f - 1.f/self->v_ratio); + const float rt = x1 + wd * (60.f+reduced_0dB) / 70.f; + cairo_set_source_rgba (cr, 0.95, 0.0, 0.0, 1.0); + cairo_move_to (cr, rt, y1); + cairo_line_to (cr, rt, y1+ht); + cairo_stroke (cr); +} +static LV2_Inline_Display_Image_Surface * +render_inline (LV2_Handle instance, uint32_t w, uint32_t max_h) +{ + AComp* self = (AComp*)instance; + + uint32_t h = MIN (w, max_h); + if (w < 200) { + h = 40; + } + + if (!self->display || self->w != w || self->h != h) { + if (self->display) cairo_surface_destroy(self->display); + self->display = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h); + self->w = w; + self->h = h; + } + + cairo_t* cr = cairo_create (self->display); + + if (w >= 200) { + render_inline_full (cr, self); + } else { + render_inline_only_bars (cr, self); + } - // create RGBA surface cairo_destroy (cr); + cairo_surface_flush (self->display); self->surf.width = cairo_image_surface_get_width (self->display); self->surf.height = cairo_image_surface_get_height (self->display); |