Beispiel #1
0
void draw_knob(t_gain *x, t_object *view, t_rect *rect)
{
    float ratio;
	t_elayer *g = ebox_start_layer((t_ebox *)x, gensym("knob_layer"), rect->width, rect->height);
    
	if (g)
	{
        float value = (x->f_value + 90.) / 108.;
        egraphics_set_color_rgba(g, &x->f_color_knob);
        if(x->f_direction)
        {
            ratio = pd_clip_minmax(rect->width * 0.05, 4., 12.);
            egraphics_set_line_width(g, ratio);
            egraphics_line_fast(g, value * rect->width, -2, value * rect->width, rect->height+4);
        }
        else
        {
            ratio = pd_clip_minmax(rect->height * 0.05, 4., 12.);
            egraphics_set_line_width(g, ratio);
            egraphics_line_fast(g, -2, (1. - value) * rect->height, rect->width+4, (1. - value) * rect->height);
        }
        ebox_end_layer((t_ebox*)x, gensym("knob_layer"));
	}
	ebox_paint_layer((t_ebox *)x, gensym("knob_layer"), 0., 0.);
}
Beispiel #2
0
void gain_mousedown(t_gain *x, t_object *patcherview, t_pt pt, long modifiers)
{
    float value;
    if(x->f_mode)
    {
        x->f_value_last = x->f_value;
        if(x->f_direction)
        {
            x->f_value_ref = pd_clip_minmax(pt.x / x->j_box.b_rect.width * 108. - 90., -90., 18.);
        }
        else
        {
            x->f_value_ref = pd_clip_minmax((x->j_box.b_rect.height - pt.y) / x->j_box.b_rect.height * 108. - 90., -90., 18.);
        }
    }
    else
    {
        if(x->f_direction)
        {
            value = pd_clip_minmax(pt.x / x->j_box.b_rect.width * 108. - 90., -90., 18.);
        }
        else
        {
            value = pd_clip_minmax((x->j_box.b_rect.height - pt.y) / x->j_box.b_rect.height * 108. - 90., -90., 18.);
        }
        gain_float(x, value);
    }
}
Beispiel #3
0
void gain_mousedrag(t_gain *x, t_object *patcherview, t_pt pt, long modifiers)
{
    float newvalue, value;
    if(x->f_mode)
    {
        if(x->f_direction)
        {
            newvalue = pt.x / x->j_box.b_rect.width * 108. - 90.;
        }
        else
        {
            newvalue = (x->j_box.b_rect.height - pt.y) / x->j_box.b_rect.height * 108. - 90.;
        }
        value = pd_clip_minmax(x->f_value_last + newvalue - x->f_value_ref, -90., 18.);
        
        if(value == -90. || value == 18.)
        {
            x->f_value_last = value;
            x->f_value_ref  = newvalue;
        }
    }
    else
    {
        if(x->f_direction)
        {
            value = pd_clip_minmax(pt.x / x->j_box.b_rect.width * 108. - 90., -90., 18.);
        }
        else
        {
            value = pd_clip_minmax((x->j_box.b_rect.height - pt.y) / x->j_box.b_rect.height * 108. - 90., -90., 18.);
        }
    }
    
    gain_float(x, value);
}
Beispiel #4
0
void knob_paint(t_knob *x, t_object *view)
{
	t_rect rect;
    if(x->f_endless)
    {
        if(x->f_min < x->f_max)
        {
            x->f_value = fmodf(x->f_value + x->f_max - x->f_min, x->f_max - x->f_min);
        }
        else
        {
            x->f_value = fmodf(x->f_value + x->f_min - x->f_max, x->f_min - x->f_max);
        }
    }
    else
    {
        if(x->f_min < x->f_max)
            x->f_value = pd_clip_minmax(x->f_value, x->f_min, x->f_max);
        else
            x->f_value = pd_clip_minmax(x->f_value, x->f_max, x->f_min);
    }
    
	ebox_get_rect_for_view((t_ebox *)x, &rect);
    draw_background(x, view, &rect);
    draw_needle(x, view, &rect);
}
Beispiel #5
0
t_rgb rgb_addContrast(t_rgb color, float contrast)
{
    t_rgb new_color = color;
    new_color.red = (float)pd_clip_minmax(new_color.red += contrast, 0., 1.);
    new_color.green = (float)pd_clip_minmax(new_color.green += contrast, 0., 1.);
    new_color.blue = (float)pd_clip_minmax(new_color.blue += contrast, 0., 1.);
    return new_color;
}
Beispiel #6
0
void matrixctrl_mousedown(t_matrixctrl *x, t_object *patcherview, t_pt pt, long modifiers)
{
    x->f_selected.x = (int)pd_clip_minmax((int)(pt.x / (x->j_box.b_rect.width / (float)x->f_size.x)), 0, x->f_size.x-1);
    x->f_selected.y = (int)pd_clip_minmax((int)(pt.y / (x->j_box.b_rect.height / (float)x->f_size.y)), 0, x->f_size.y-1);
    if(x->f_selected.x >= 0 && x->f_selected.x < x->f_size.x && x->f_selected.y >= 0 && x->f_selected.y < x->f_size.y)
    {
        x->f_values[(long)x->f_selected.y * (long)x->f_size.x + (long)x->f_selected.x] = !x->f_values[(long)x->f_selected.y * (long)x->f_size.x + (long)x->f_selected.x];
        ebox_invalidate_layer((t_ebox *)x, cream_sym_background_layer);
        ebox_redraw((t_ebox *)x);
        matrixctrl_output(x, x->f_selected.x, x->f_selected.y);
    }
}
Beispiel #7
0
t_pd_err filterview_type_set(t_filterview *x, t_object *attr, long ac, t_atom *av)
{
    if(ac && av)
    {
        if(atom_gettype(av) == A_FLOAT)
        {
            x->f_type = pd_clip_minmax(atom_getfloat(av), 0, 8);
        }
        else if(atom_gettype(av) == A_SYM)
        {
            if(atom_getsym(av) == gensym("lowpass"))
                x->f_type = Lowpass;
            else if(atom_getsym(av) == gensym("highpass"))
                x->f_type = Highpass;
            else if(atom_getsym(av) == gensym("bandpass"))
                x->f_type = Bandpass;
            else if(atom_getsym(av) == gensym("notch"))
                x->f_type = Notch;
            else if(atom_getsym(av) == gensym("peak"))
                x->f_type = Peak;
            else if(atom_getsym(av) == gensym("lowshelf"))
                x->f_type = Lowshelf;
            else if(atom_getsym(av) == gensym("highshelf"))
                x->f_type = Highshelf;/*
            else if(atom_getsym(av) == gensym("allpass"))
                x->f_type = Allpass;
            else if(atom_getsym(av) == gensym("resonante"))
                x->f_type = Resonante;*/
        }
        filterview_compute(x);
    }
    return 0;
}
t_pd_err channels_set(t_hoa_meter *x, void *attr, long argc, t_atom *argv)
{
    t_atom* av;
    if(argc && argv)
    {
        if(atom_gettype(argv) == A_FLOAT)
        {
            long d = pd_clip_minmax(atom_getfloat(argv), 1, MAX_SPEAKER);
            if(d != x->f_meter->getNumberOfChannels())
            {
                int dspState = canvas_suspend_dsp();
                delete x->f_meter;
                x->f_meter = new Meter(d);
                delete x->f_vector;
                x->f_vector = new Vector(d);
                
                av = new t_atom[x->f_meter->getNumberOfChannels()];
                for(int i = 0; i < x->f_meter->getNumberOfChannels(); i++)
                {
                    atom_setfloat(av+i, x->f_meter->getChannelAzimuth(i) / HOA_2PI * 360.);
                    x->f_over_leds[i] = 0;
                }
                angles_set(x, NULL, x->f_meter->getNumberOfChannels(), av);
                
                eobj_resize_inputs((t_ebox *)x, x->f_meter->getNumberOfChannels());
                
                canvas_resume_dsp(dspState);
            }
        }
    }
    return NULL;
}
Beispiel #9
0
t_pd_err radio_mode_set(t_radio *x, t_object *attr, long ac, t_atom *av)
{
	int i;
    if(ac && av && atom_gettype(av) == A_FLOAT)
    {
        if(pd_clip_minmax(atom_getfloat(av), 0, 1) != x->f_mode)
        {
            x->f_mode = pd_clip_minmax(atom_getfloat(av), 0, 1);
            for(i = 0; i < x->f_nitems; i++)
                x->f_items[i] = 0;
            ebox_invalidate_layer((t_ebox *)x, gensym("background_layer"));
            ebox_invalidate_layer((t_ebox *)x, gensym("items_layer"));
            ebox_redraw((t_ebox *)x);
        }
    }
    return 0;
}
Beispiel #10
0
void gain_set(t_gain *x, float f)
{
    x->f_value = pd_clip_minmax(f, -90., 18.);
    x->f_amp_old = x->f_amp;
    x->f_amp = powf(10., x->f_value * 0.05);
    x->f_amp_step = (float)(x->f_amp - x->f_amp_old) / (float)x->f_ramp_sample;
    x->f_counter  = 0;
    ebox_invalidate_layer((t_ebox *)x, gensym("knob_layer"));
    ebox_redraw((t_ebox *)x);
}
float breakpoints_interpolation(t_breakpoints *x, float f)
{
    f = pd_clip_minmax(f, x->f_range_abscissa[0], x->f_range_abscissa[1]);
    if(x->f_outline_mode == 0)
        return breakpoints_linear(x, f);
    else if(x->f_outline_mode == 1 || x->f_number_of_points == 2)
        return breakpoints_cosine(x, f);
    else
        return breakpoints_cubic(x, f);
}
void breakpoints_move(t_breakpoints *x, t_symbol* s, int argc, t_atom* argv)
{
    int index;
    float abs, ord;
    if(x->f_number_of_points == MAXPOINTS)
        return;

    if(argc && argv)
    {
        if(argc == 3 && atom_gettype(argv) == A_FLOAT && atom_gettype(argv+1) == A_FLOAT && atom_gettype(argv+2) == A_FLOAT)
        {
            index = atom_getfloat(argv);
            abs = atom_getfloat(argv+1);
            ord = pd_clip_minmax(atom_getfloat(argv+2), x->f_range_ordinate[0], x->f_range_ordinate[1]);
            if(index >= x->f_number_of_points || index < 0)
            {
                return;
            }
            else if(index == 0)
            {
                if(x->f_number_of_points > 1)
                    x->f_point_abscissa[0] = pd_clip_minmax(abs, x->f_range_abscissa[0], x->f_point_abscissa[1]);
                else
                    x->f_point_abscissa[0] = pd_clip_minmax(abs, x->f_range_abscissa[0], x->f_range_abscissa[1]);
                x->f_point_ordinate[0] = ord;
            }
            else if(index == x->f_number_of_points-1)
            {
                x->f_point_abscissa[index] = pd_clip_minmax(abs, x->f_point_abscissa[index-1], x->f_range_abscissa[1]);
                x->f_point_ordinate[index] = ord;
            }
            else
            {
                x->f_point_abscissa[index] = pd_clip_minmax(abs, x->f_point_abscissa[index-1], x->f_point_abscissa[index+1]);
                x->f_point_ordinate[index] = ord;
            }

            ebox_invalidate_layer((t_ebox *)x, gensym("points_layer"));
            ebox_redraw((t_ebox *)x);
        }
    }
}
Beispiel #13
0
void gain_linear(t_gain *x, float f)
{
    f = pd_clip_minmax(f, 0.00001, 8.);
    f = (20.f * log10f(f));
    
    if(f < -90)
    {
        f  = -90.;
    }
    gain_float(x, f);
}
Beispiel #14
0
t_pd_err radio_nitems_set(t_radio *x, t_object *attr, long ac, t_atom *av)
{
	int i;
    t_atom argv[2];
    if(ac && av && atom_gettype(av) == A_FLOAT)
    {
        if(pd_clip_minmax(atom_getfloat(av), 1, 256) != x->f_nitems)
        {
            x->f_nitems = pd_clip_minmax(atom_getfloat(av), 1, 256);
            for(i = 0; i < x->f_nitems; i++)
                x->f_items[i] = 0;
            
            ebox_invalidate_layer((t_ebox *)x, gensym("background_layer"));
            ebox_invalidate_layer((t_ebox *)x, gensym("items_layer"));
            atom_setfloat(argv, x->j_box.b_rect.width);
            atom_setfloat(argv+1, x->j_box.b_rect.height);
            object_attr_setvalueof((t_object *)x, gensym("size"), 2, argv);
        }
    }
    return 0;
}
Beispiel #15
0
void draw_background(t_gain *x, t_object *view, t_rect *rect)
{
    float ratio;
	t_elayer *g = ebox_start_layer((t_ebox *)x, gensym("background_layer"), rect->width, rect->height);
    
	if (g)
	{
        if(x->f_direction)
        {
            ratio = 90. / 108.;
            egraphics_set_line_width(g, pd_clip_minmax(rect->height * 0.1, 2., 4.));
            
            egraphics_set_color_rgba(g, &x->f_color_border);
            egraphics_line_fast(g, rect->width * ratio, 0, rect->width * ratio, rect->height);
            
            egraphics_set_color_rgba(g, &x->f_color_background);
            egraphics_line_fast(g, rect->width * ratio, pd_clip_min(rect->height * 0.1, 2), rect->width * ratio, rect->height - pd_clip_min(rect->height * 0.1, 2));
            
            egraphics_set_color_rgba(g, &x->f_color_border);
            egraphics_line_fast(g, pd_clip_min(rect->height * 0.1, 2), rect->height * 0.5, rect->width-pd_clip_min(rect->height * 0.1, 2), rect->height * 0.5);
        }
        else
        {
            ratio = 1. - 90. / 108.;
            egraphics_set_line_width(g, pd_clip_minmax(rect->width * 0.1, 2., 4.));
            
            egraphics_set_color_rgba(g, &x->f_color_border);
            egraphics_line_fast(g, 0, rect->height * ratio, rect->width, rect->height * ratio);
            
            egraphics_set_color_rgba(g, &x->f_color_background);
            egraphics_line_fast(g, pd_clip_min(rect->width * 0.1, 2), rect->height * ratio, rect->width - pd_clip_min(rect->width * 0.1, 2), rect->height * ratio);
            
            egraphics_set_color_rgba(g, &x->f_color_border);
            egraphics_line_fast(g, rect->width * 0.5, pd_clip_min(rect->width * 0.1, 2), rect->width * 0.5, rect->height -pd_clip_min(rect->width * 0.1, 2));
            
        }
        ebox_end_layer((t_ebox*)x, gensym("background_layer"));
	}
	ebox_paint_layer((t_ebox *)x, gensym("background_layer"), 0., 0.);
}
Beispiel #16
0
void plane_set(t_plane *x, t_symbol *s, long ac, t_atom *av)
{
    if(ac && av)
    {
        if(ac >= 1)
        {
            if(x->f_boundaries.x < x->f_boundaries.width)
                x->f_position.x = pd_clip_minmax(atom_getfloat(av), x->f_boundaries.x, x->f_boundaries.width);
            else
                x->f_position.x = pd_clip_minmax(atom_getfloat(av), x->f_boundaries.width, x->f_boundaries.x);
        }
        if(ac >= 2)
        {
            if(x->f_boundaries.y < x->f_boundaries.height)
                x->f_position.y = pd_clip_minmax(atom_getfloat(av+1), x->f_boundaries.y, x->f_boundaries.height);
            else
                x->f_position.y = pd_clip_minmax(atom_getfloat(av+1), x->f_boundaries.height, x->f_boundaries.y);
        }
        ebox_invalidate_layer((t_ebox *)x, gensym("point_layer"));
        ebox_redraw((t_ebox *)x);
    }
}
void breakpoints_add(t_breakpoints *x, t_symbol* s, int argc, t_atom* argv)
{
    int index, i;
    float abs, ord;
    if(x->f_number_of_points == MAXPOINTS)
        return;

    if(argc && argv)
    {
        if(argc == 2 && atom_gettype(argv) == A_FLOAT && atom_gettype(argv+1) == A_FLOAT)
        {
            abs = atom_getfloat(argv);
            ord = pd_clip_minmax(atom_getfloat(argv+1), x->f_range_ordinate[0], x->f_range_ordinate[1]);

            if(abs < x->f_range_abscissa[0] || abs > x->f_range_abscissa[1])
                return;

            if(x->f_number_of_points == 0)
            {
                index  = 0;
            }
            else if(abs >= x->f_point_abscissa[x->f_number_of_points-1])
            {
                index = x->f_number_of_points;
            }
            else
            {
                index = 0;
                for(i = 0; i < x->f_number_of_points-1; i++)
                {
                    if(abs > x->f_point_abscissa[i])
                        index = i+1;
                }

                for(i = x->f_number_of_points-1; i >= index; i--)
                {
                    x->f_point_abscissa[i+1] = x->f_point_abscissa[i];
                    x->f_point_ordinate[i+1] = x->f_point_ordinate[i];
                }
            }
            x->f_point_abscissa[index] = abs;
            x->f_point_ordinate[index] = ord;
            x->f_number_of_points++;
            x->f_point_last_created = index;

            ebox_invalidate_layer((t_ebox *)x, gensym("points_layer"));
            ebox_redraw((t_ebox *)x);

        }
    }
}
void draw_text(t_breakpoints *x, t_object *view, t_rect *rect)
{
    char number[512];
    t_elayer *g = ebox_start_layer((t_ebox *)x, cream_sym_text_layer, rect->width, rect->height);
    t_etext *jtl = etext_layout_create();
	if(g && jtl)
	{
        float height = sys_fontheight(ebox_getfontsize((t_ebox *)x)) + 1;
        if (x->f_point_selected != -1)
        {
            sprintf(number, "x : %.2f y : %.2f", x->f_point_abscissa[x->f_point_selected], x->f_point_ordinate[x->f_point_selected]);
        }
        else if(x->f_mouse.x != -666666 && x->f_mouse.y != -666666)
        {
            x->f_mouse.x = pd_clip_minmax(x->f_mouse.x, x->f_range_abscissa[0], x->f_range_abscissa[1]);
            x->f_mouse.y = pd_clip_minmax(x->f_mouse.y, x->f_range_ordinate[0], x->f_range_ordinate[1]);
            sprintf(number, "x : %.2f y : %.2f", x->f_mouse.x, x->f_mouse.y);
        }
        else
        {
            ebox_end_layer((t_ebox*)x, cream_sym_text_layer);
            ebox_paint_layer((t_ebox *)x, cream_sym_text_layer, 0., 0.);
            return;
        }
        etext_layout_set(jtl, number, &x->j_box.b_font, 5, height * 0.5, rect->width, 0, ETEXT_LEFT, ETEXT_JLEFT, ETEXT_NOWRAP);
        etext_layout_settextcolor(jtl, &x->f_color_text);
        etext_layout_draw(jtl, g);

        ebox_end_layer((t_ebox*)x, cream_sym_text_layer);
	}
    if(jtl)
    {
       etext_layout_destroy(jtl);
    }
	ebox_paint_layer((t_ebox *)x, cream_sym_text_layer, 0., 0.);
}
Beispiel #19
0
void knob_set(t_knob *x, float f)
{
    if(x->f_endless)
    {
        if(x->f_min < x->f_max)
        {
            x->f_value = fmodf(f + x->f_max - x->f_min, x->f_max - x->f_min);
        }
        else
        {
            x->f_value = fmodf(f + x->f_min - x->f_max, x->f_min - x->f_max);
        }
    }
    else
    {
        if(x->f_min < x->f_max)
            x->f_value = pd_clip_minmax(f, x->f_min, x->f_max);
        else
            x->f_value = pd_clip_minmax(f, x->f_max, x->f_min);
    }
    
    ebox_invalidate_layer((t_ebox *)x, gensym("needle_layer"));
    ebox_redraw((t_ebox *)x);
}
Beispiel #20
0
static void blackboard_fill(t_blackboard *x, float f)
{
    x->f_fill = pd_clip_minmax(f, 0, 1);
}
t_pd_err breakpoints_notify(t_breakpoints *x, t_symbol *s, t_symbol *msg, void *sender, void *data)
{
    int i, j;
    float max;
	if (msg == cream_sym_attr_modified)
	{
		if(s == cream_sym_bgcolor || s == cream_sym_bdcolor || s == gensym("ptcolor") || s == gensym("licolor") || s == gensym("textcolor") || s == gensym("fontsize") || s == gensym("fontname") || s == gensym("fontweight") || s == gensym("fontslant"))
		{
			ebox_invalidate_layer((t_ebox *)x, gensym("points_layer"));
            ebox_invalidate_layer((t_ebox *)x, cream_sym_text_layer);
		}
        if(s == gensym("absrange") || s == gensym("ordrange"))
        {
            if(x->f_range_abscissa[0] > x->f_range_abscissa[1])
            {
                max = x->f_range_abscissa[0];
                x->f_range_abscissa[0] = x->f_range_abscissa[1];
                x->f_range_abscissa[1] = max;
            }
            if(x->f_range_ordinate[0] > x->f_range_ordinate[1])
            {
                max = x->f_range_ordinate[0];
                x->f_range_ordinate[0] = x->f_range_ordinate[1];
                x->f_range_ordinate[1] = max;
            }

            for(i = 0; i < x->f_number_of_points; i++)
            {
                if(x->f_point_abscissa[i] < x->f_range_abscissa[0] || x->f_point_abscissa[i] > x->f_range_abscissa[1])
                {
                    for(j = i; j < x->f_number_of_points; j++)
                    {
                        x->f_point_abscissa[j] = x->f_point_abscissa[j+1];
                        x->f_point_ordinate[j] = x->f_point_ordinate[j+1];
                    }
                    x->f_number_of_points--;
                    i--;
                }
                x->f_point_ordinate[i] = pd_clip_minmax(x->f_point_ordinate[i], x->f_range_ordinate[0], x->f_range_ordinate[1]);
            }
            ebox_invalidate_layer((t_ebox *)x, gensym("points_layer"));
        }
        if(s == gensym("outline"))
        {
            if(x->f_outline == gensym("Cosine"))
            {
                x->f_outline_mode = 1;
            }
            else if(x->f_outline == gensym("Cubic"))
            {
                x->f_outline_mode = 2;
            }
            else
            {
                x->f_outline = gensym("Linear");
                x->f_outline_mode = 0;
            }
            ebox_invalidate_layer((t_ebox *)x, gensym("points_layer"));
        }
        ebox_redraw((t_ebox *)x);
	}
	return 0;
}
Beispiel #22
0
void knob_mousedrag(t_knob *x, t_object *patcherview, t_pt pt, long modifiers)
{
    float angle = pd_angle(pt.x - x->j_box.b_rect.width * 0.5, (x->j_box.b_rect.height * 0.5 - pt.y)) / EPD_2PI;
    if(x->f_mode)
    {
        if(x->f_endless)
        {
            if(x->f_min < x->f_max)
            {
                angle = -angle;
                angle -= 0.25;
                while (angle < 0.)
                    angle += 1.;
                while (angle > 1.)
                    angle -= 1.;
                x->f_value = angle * (x->f_max - x->f_min) + x->f_min;
            }
            else
            {
                angle += 0.25;
                while (angle < 0.)
                    angle += 1.;
                while (angle > 1.)
                    angle -= 1.;
                x->f_value = angle * (x->f_min - x->f_max) + x->f_max;
            }
        }
        else
        {
            if(x->f_min < x->f_max)
            {
                angle = -angle;
                angle -= 0.25;
                while (angle < 0.)
                    angle += 1.;
                while (angle > 1.)
                    angle -= 1.;
                angle = pd_clip_minmax(angle, 0.125, 0.875);
                angle -= 0.125;
                angle *= 1. / 0.75;
                x->f_value = angle * (x->f_max - x->f_min) + x->f_min;
            }
        
            else
            {
                angle += 0.25;
                while (angle < 0.)
                    angle += 1.;
                while (angle > 1.)
                    angle -= 1.;
                angle = pd_clip_minmax(angle, 0.125, 0.875);
                angle -= 0.125;
                angle *= 1. / 0.75;
                x->f_value = angle * (x->f_min - x->f_max) + x->f_max;
            }
        }
    }
    else
    {
        float diff = x->f_ref_y - pt.y;
        if(diff == 0xffffffff)
            return;
        if(x->f_min < x->f_max)
        {
            if(x->f_endless)
            {
                x->f_value = fmodf(diff / 50. * (x->f_max - x->f_min) + x->f_ref_value + x->f_max - x->f_min, x->f_max - x->f_min);
            }
            else
                x->f_value = pd_clip_minmax(diff / 50. * (x->f_max - x->f_min) + x->f_ref_value, x->f_min, x->f_max);
        }
        else
        {
            if(x->f_endless)
            {
                x->f_value = fmodf(diff / 50. * (x->f_min - x->f_max) + x->f_ref_value + x->f_min - x->f_max, x->f_min - x->f_max);
            }
            else
                x->f_value = pd_clip_minmax(diff / 50. * (x->f_min - x->f_max) + x->f_ref_value, x->f_max, x->f_min);
        }
    }
    ebox_invalidate_layer((t_ebox *)x, gensym("needle_layer"));
    ebox_redraw((t_ebox *)x);
    knob_output(x);
}