summaryrefslogtreecommitdiff
path: root/libs/plugins/a-comp.lv2/a-comp.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/plugins/a-comp.lv2/a-comp.c')
-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);