Add off_db (deadband) to GtkDial for quiet signals

Add an optional deadband at the bottom of the GtkDial so that very
quiet signals can be squashed into the first 1% of the dial. This will
be used to make the level meters more realistic.
This commit is contained in:
Geoffrey D. Bennett
2024-02-02 19:14:45 +10:30
parent 17b39efee0
commit 1cc6c64c04
2 changed files with 54 additions and 12 deletions

View File

@@ -87,6 +87,7 @@ enum {
PROP_ADJUSTMENT, PROP_ADJUSTMENT,
PROP_ROUND_DIGITS, PROP_ROUND_DIGITS,
PROP_ZERO_DB, PROP_ZERO_DB,
PROP_OFF_DB,
PROP_TAPER, PROP_TAPER,
PROP_CAN_CONTROL, PROP_CAN_CONTROL,
LAST_PROP LAST_PROP
@@ -113,6 +114,7 @@ struct _GtkDial {
int round_digits; int round_digits;
double zero_db; double zero_db;
double off_db;
int taper; int taper;
gboolean can_control; gboolean can_control;
@@ -188,6 +190,23 @@ static double taper_log(double val) {
} }
static double calc_taper(GtkDial *dial, double val) { static double calc_taper(GtkDial *dial, double val) {
double mn = gtk_adjustment_get_lower(dial->adj);
double mx = gtk_adjustment_get_upper(dial->adj);
double off_db = gtk_dial_get_off_db(dial);
// if off_db is set, then values below it are considered as
// almost-silence, so we clamp them to 0.01
if (off_db > mn) {
if (val == mn)
val = 0;
else if (val <= off_db)
val = 0.01;
else
val = calc_valp(val, off_db, mx) * 0.99 + 0.01;
} else {
val = calc_valp(val, mn, mx);
}
if (dial->taper == GTK_DIAL_TAPER_LINEAR) if (dial->taper == GTK_DIAL_TAPER_LINEAR)
return taper_linear( return taper_linear(
val, val,
@@ -266,10 +285,7 @@ static void get_dial_properties(
props->slider_thickness = 16; props->slider_thickness = 16;
double mn = dial->adj ? gtk_adjustment_get_lower(dial->adj) : 0; props->valp = calc_taper(dial, gtk_adjustment_get_value(dial->adj));
double mx = dial->adj ? gtk_adjustment_get_upper(dial->adj) : 1;
double value = dial->adj ? gtk_adjustment_get_value(dial->adj) : 0.25;
props->valp = calc_taper(dial, calc_valp(value, mn, mx));
props->angle = calc_val(props->valp, ANGLE_START, ANGLE_END); props->angle = calc_val(props->valp, ANGLE_START, ANGLE_END);
double slider_radius = props->radius - props->slider_thickness / 2; double slider_radius = props->radius - props->slider_thickness / 2;
@@ -359,6 +375,22 @@ static void gtk_dial_class_init(GtkDialClass *klass) {
G_PARAM_READWRITE | G_PARAM_CONSTRUCT G_PARAM_READWRITE | G_PARAM_CONSTRUCT
); );
/**
* GtkDial:off_db: (attributes org.gtk.Method.get=gtk_dial_get_off_db org.gtk.Method.set=gtk_dial_set_off_db)
*
* Values above the lower value of the adjustment up to this value
* will be considered as the minimum value + 1 (so will display as
* just-above-zero).
*/
properties[PROP_OFF_DB] = g_param_spec_double(
"off_db",
"OffdB",
"Values up to this value will be considered as almost-silence",
-G_MAXDOUBLE, G_MAXDOUBLE,
-G_MAXDOUBLE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT
);
/** /**
* GtkDial:taper: (attributes org.gtk.Method.get=gtk_dial_get_taper org.gtk.Method.set=gtk_dial_set_taper) * GtkDial:taper: (attributes org.gtk.Method.get=gtk_dial_get_taper org.gtk.Method.set=gtk_dial_set_taper)
* *
@@ -594,14 +626,7 @@ static void dial_snapshot(GtkWidget *widget, GtkSnapshot *snapshot) {
// draw line to zero db // draw line to zero db
double zero_db = gtk_dial_get_zero_db(dial); double zero_db = gtk_dial_get_zero_db(dial);
if (zero_db != 0.0) { if (zero_db != 0.0) {
double zero_db_valp = calc_taper( double zero_db_valp = calc_taper(dial, zero_db);
dial,
calc_valp(
zero_db,
gtk_adjustment_get_lower(dial->adj),
gtk_adjustment_get_upper(dial->adj)
)
);
double zero_db_angle = calc_val(zero_db_valp, ANGLE_START, ANGLE_END); double zero_db_angle = calc_val(zero_db_valp, ANGLE_START, ANGLE_END);
double zero_db_x = cos(zero_db_angle) * slider_radius + p.cx; double zero_db_x = cos(zero_db_angle) * slider_radius + p.cx;
@@ -735,6 +760,9 @@ static void gtk_dial_set_property(
case PROP_ZERO_DB: case PROP_ZERO_DB:
gtk_dial_set_zero_db(dial, g_value_get_double(value)); gtk_dial_set_zero_db(dial, g_value_get_double(value));
break; break;
case PROP_OFF_DB:
gtk_dial_set_off_db(dial, g_value_get_double(value));
break;
case PROP_TAPER: case PROP_TAPER:
gtk_dial_set_taper(dial, g_value_get_int(value)); gtk_dial_set_taper(dial, g_value_get_int(value));
break; break;
@@ -765,6 +793,9 @@ static void gtk_dial_get_property(
case PROP_ZERO_DB: case PROP_ZERO_DB:
g_value_set_double(value, dial->zero_db); g_value_set_double(value, dial->zero_db);
break; break;
case PROP_OFF_DB:
g_value_set_double(value, dial->off_db);
break;
case PROP_TAPER: case PROP_TAPER:
g_value_set_int(value, dial->taper); g_value_set_int(value, dial->taper);
break; break;
@@ -803,6 +834,14 @@ double gtk_dial_get_zero_db(GtkDial *dial) {
return dial->zero_db; return dial->zero_db;
} }
void gtk_dial_set_off_db(GtkDial *dial, double off_db) {
dial->off_db = off_db;
}
double gtk_dial_get_off_db(GtkDial *dial) {
return dial->off_db;
}
void gtk_dial_set_taper(GtkDial *dial, int taper) { void gtk_dial_set_taper(GtkDial *dial, int taper) {
dial->taper = taper; dial->taper = taper;
} }

View File

@@ -65,6 +65,9 @@ int gtk_dial_get_round_digits(GtkDial *dial);
void gtk_dial_set_zero_db(GtkDial *dial, double zero_db); void gtk_dial_set_zero_db(GtkDial *dial, double zero_db);
double gtk_dial_get_zero_db(GtkDial *dial); double gtk_dial_get_zero_db(GtkDial *dial);
void gtk_dial_set_off_db(GtkDial *dial, double off_db);
double gtk_dial_get_off_db(GtkDial *dial);
// taper functions // taper functions
enum { enum {
GTK_DIAL_TAPER_LINEAR, GTK_DIAL_TAPER_LINEAR,