summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Mueller <github@johannes-mueller.org>2017-07-13 21:28:17 +0200
committerRobin Gareus <robin@gareus.org>2017-07-31 21:31:22 +0200
commit59775df9be375a249b3c4cbdc7e825eee27c393e (patch)
treed2e42258d00936405ceaee29f3f6bcf996c92db7
parent24cbb1b153ad2b380c3e5d5f51913fd93ff0a4fb (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.
-rw-r--r--libs/plugins/a-comp.lv2/a-comp.c148
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);