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.
This commit is contained in:
committed by
Robin Gareus
parent
24cbb1b153
commit
59775df9be
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user