From 68383146f9dee06321a899af047e127f0327eb69 Mon Sep 17 00:00:00 2001 From: porres Date: Sat, 5 Aug 2023 17:36:13 -0300 Subject: [PATCH] glide2~ --- Code_source/Compiled/signal/glide2~.c | 214 ++++++++++++++--------- Documentation/Help-files/glide2~-help.pd | 134 +++++++------- 2 files changed, 203 insertions(+), 145 deletions(-) diff --git a/Code_source/Compiled/signal/glide2~.c b/Code_source/Compiled/signal/glide2~.c index af9a051f5..3bf3c7b2e 100644 --- a/Code_source/Compiled/signal/glide2~.c +++ b/Code_source/Compiled/signal/glide2~.c @@ -4,21 +4,21 @@ #include "math.h" typedef struct _glide2{ - t_object x_obj; + t_object x_obj; t_inlet *x_inlet_ms_up; t_inlet *x_inlet_ms_down; - t_float x_in; - int x_n_up; - int x_nleft_up; - int x_n_down; - int x_nleft_down; - int x_reset; - float x_last_in; - float x_last_out; - float x_sr_khz; - float x_delta; - float x_start; - float x_exp; + int *x_n_up; + int *x_nleft_up; + int *x_n_down; + int *x_nleft_down; + int x_reset; + int x_nchans; + float *x_last_in; + float *x_last_out; + float *x_start; + float *x_delta; + float x_sr_khz; + float x_exp; }t_glide2; static t_class *glide2_class; @@ -31,17 +31,17 @@ static void glide2_reset(t_glide2 *x){ x->x_reset = 1; } -static float glide2_get_step(t_glide2 *x, int n, int nleft){ +static float glide2_get_step(t_glide2 *x, int n, int nleft, int j){ float step = (float)(n-nleft)/(float)n; if(fabs(x->x_exp) != 1){ // EXPONENTIAL if(x->x_exp >= 0){ // positive exponential - if(x->x_delta > 0) + if(x->x_delta[j] > 0) step = pow(step, x->x_exp); else step = 1-pow(1-step, x->x_exp); } else{ // negative exponential - if(x->x_delta > 0) + if(x->x_delta[j] > 0) step = 1-pow(1-step, -x->x_exp); else step = pow(step, -x->x_exp); @@ -53,91 +53,141 @@ static float glide2_get_step(t_glide2 *x, int n, int nleft){ static t_int *glide2_perform(t_int *w){ t_glide2 *x = (t_glide2 *)(w[1]); int n = (int)(w[2]); - t_float *in1 = (t_float *)(w[3]); - t_float *in2 = (t_float *)(w[4]); - t_float *in3 = (t_float *)(w[5]); - t_float *out = (t_float *)(w[6]); - float last_in = x->x_last_in; - float last_out = x->x_last_out; - float start = x->x_start; - while(n--){ - t_float in = *in1++; - t_float ms_up = *in2++; - t_float ms_down = *in3++; - if(ms_up <= 0) - ms_up = 0; - if(ms_down <= 0) - ms_down = 0; - x->x_n_up = (int)roundf(ms_up * x->x_sr_khz) + 1; // n samples - x->x_n_down = (int)roundf(ms_down * x->x_sr_khz) + 1; // n samples - if(x->x_reset){ // reset - x->x_nleft_up = x->x_nleft_down = 0; - x->x_reset = 0; - *out++ = last_out = last_in = in; - } - else if(in != last_in){ // input change, update - start = last_out; - x->x_delta = (in - last_out); - if(x->x_delta > 0){ - x->x_nleft_up = x->x_n_up - 1; - float step = glide2_get_step(x, x->x_n_up, x->x_nleft_up); - float inc = step * x->x_delta; - *out++ = last_out = (last_out + inc); - last_in = in; - } - else{ - x->x_nleft_down = x->x_n_down - 1; - float step = glide2_get_step(x, x->x_n_down, x->x_nleft_down); - float inc = step * x->x_delta; - *out++ = last_out = (last_out + inc); - last_in = in; + int ch2 = (int)(w[3]); + int ch3 = (int)(w[4]); + t_float *in1 = (t_float *)(w[5]); + t_float *in2 = (t_float *)(w[6]); + t_float *in3 = (t_float *)(w[7]); + t_float *out = (t_float *)(w[8]); + float *last_in = x->x_last_in; + float *last_out = x->x_last_out; + float *start = x->x_start; + for(int j = 0; j < x->x_nchans; j++){ + for(int i = 0; i < n; i++){ + t_float in = in1[j*n + i]; + t_float ms_up = ch2 == 1 ? in2[i] : in2[j*n + i]; + t_float ms_down = ch3 == 1 ? in3[i] : in3[j*n + i]; + if(ms_up <= 0) + ms_up = 0; + if(ms_down <= 0) + ms_down = 0; + x->x_n_up[j] = (int)roundf(ms_up * x->x_sr_khz) + 1; // n samples + x->x_n_down[j] = (int)roundf(ms_down * x->x_sr_khz) + 1; // n samples + if(x->x_reset){ // reset + x->x_nleft_up[j] = x->x_nleft_down[j] = 0; + out[j*n + i] = last_out[j] = last_in[j] = in; + if(j == (x->x_nchans - 1)) + x->x_reset = 0; } - } - else{ - if(x->x_delta > 0){ - if(x->x_nleft_up > 0){ - x->x_nleft_up--; - float step = glide2_get_step(x, x->x_n_up, x->x_nleft_up); - float inc = step * x->x_delta; - *out++ = last_out = (start + inc); + else if(in != last_in[j]){ // input change, update + start[j] = last_out[j]; + x->x_delta[j] = (in - last_out[j]); + if(x->x_delta[j] > 0){ + x->x_nleft_up[j] = x->x_n_up[j] - 1; + float step = glide2_get_step(x, x->x_n_up[j], x->x_nleft_up[j], j); + float inc = step * x->x_delta[j]; + out[j*n + i] = last_out[j] = (last_out[j] + inc); + last_in[j] = in; + } + else{ + x->x_nleft_down[j] = x->x_n_down[j] - 1; + float step = glide2_get_step(x, x->x_n_down[j], x->x_nleft_down[j], j); + float inc = step * x->x_delta[j]; + out[j*n + i] = last_out[j] = (last_out[j] + inc); + last_in[j] = in; } - else - *out++ = last_out = last_in = in; } else{ - if(x->x_nleft_down > 0){ - x->x_nleft_down--; - float step = glide2_get_step(x, x->x_n_down, x->x_nleft_down); - float inc = step * x->x_delta; - *out++ = last_out = (start + inc); + if(x->x_delta[j] > 0){ + if(x->x_nleft_up[j] > 0){ + x->x_nleft_up[j]--; + float step = glide2_get_step(x, x->x_n_up[j], x->x_nleft_up[j], j); + float inc = step * x->x_delta[j]; + out[j*n + i] = last_out[j] = (start[j] + inc); + } + else + out[j*n + i] = last_out[j] = last_in[j] = in; + } + else{ + if(x->x_nleft_down[j] > 0){ + x->x_nleft_down[j]--; + float step = glide2_get_step(x, x->x_n_down[j], x->x_nleft_down[j], j); + float inc = step * x->x_delta[j]; + out[j*n + i] = last_out[j] = (start[j] + inc); + } + else + out[j*n + i] = last_out[j] = last_in[j] = in; } - else - *out++ = last_out = last_in = in; } - } - + }; }; x->x_start = start; x->x_last_in = last_in; x->x_last_out = last_out; - return(w+7); + return(w+9); } static void glide2_dsp(t_glide2 *x, t_signal **sp){ x->x_sr_khz = sp[0]->s_sr * 0.001; - dsp_add(glide2_perform, 6, x, sp[0]->s_n, sp[0]->s_vec, + int chs = sp[0]->s_nchans, ch2 = sp[1]->s_nchans, ch3 = sp[2]->s_nchans, n = sp[0]->s_n; + signal_setmultiout(&sp[3], chs); + if(x->x_nchans != chs){ + x->x_n_up = (int *)resizebytes(x->x_n_up, + x->x_nchans * sizeof(int), chs * sizeof(int)); + x->x_n_down = (int *)resizebytes(x->x_n_down, + x->x_nchans * sizeof(int), chs * sizeof(int)); + x->x_nleft_up = (int *)resizebytes(x->x_nleft_up, + x->x_nchans * sizeof(int), chs * sizeof(int)); + x->x_nleft_down = (int *)resizebytes(x->x_nleft_down, + x->x_nchans * sizeof(int), chs * sizeof(int)); + x->x_last_in = (t_float *)resizebytes(x->x_last_in, + x->x_nchans * sizeof(t_float), chs * sizeof(t_float)); + x->x_last_out = (t_float *)resizebytes(x->x_last_out, + x->x_nchans * sizeof(t_float), chs * sizeof(t_float)); + x->x_start = (t_float *)resizebytes(x->x_start, + x->x_nchans * sizeof(t_float), chs * sizeof(t_float)); + x->x_delta = (t_float *)resizebytes(x->x_delta, + x->x_nchans * sizeof(t_float), chs * sizeof(t_float)); + x->x_nchans = chs; + } + if((ch2 > 1 && ch2 != x->x_nchans) || (ch3 > 1 && ch3 != x->x_nchans)){ + dsp_add_zero(sp[3]->s_vec, chs*n); + pd_error(x, "[glide2~]: channel sizes mismatch"); + } + else + dsp_add(glide2_perform, 8, x, n, ch2, ch3, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec); } +static void *glide2_free(t_glide2 *x){ + inlet_free(x->x_inlet_ms_up); + inlet_free(x->x_inlet_ms_down); + freebytes(x->x_n_up, x->x_nchans * sizeof(*x->x_n_up)); + freebytes(x->x_n_down, x->x_nchans * sizeof(*x->x_n_down)); + freebytes(x->x_nleft_up, x->x_nchans * sizeof(*x->x_nleft_up)); + freebytes(x->x_nleft_down, x->x_nchans * sizeof(*x->x_nleft_down)); + freebytes(x->x_last_in, x->x_nchans * sizeof(*x->x_last_in)); + freebytes(x->x_last_out, x->x_nchans * sizeof(*x->x_last_out)); + freebytes(x->x_start, x->x_nchans * sizeof(*x->x_start)); + freebytes(x->x_delta, x->x_nchans * sizeof(*x->x_delta)); + return(void *)x; +} + static void *glide2_new(t_symbol *s, int ac, t_atom *av){ t_glide2 *x = (t_glide2 *)pd_new(glide2_class); s = NULL; - float ms_up = 0; - float ms_down = 0; + x->x_n_up = (int *)getbytes(sizeof(*x->x_n_up)); + x->x_n_down = (int *)getbytes(sizeof(*x->x_n_down)); + x->x_nleft_up = (int *)getbytes(sizeof(*x->x_nleft_up)); + x->x_nleft_down = (int *)getbytes(sizeof(*x->x_nleft_down)); + x->x_last_in = (t_float *)getbytes(sizeof(*x->x_last_in)); + x->x_last_out = (t_float *)getbytes(sizeof(*x->x_last_out)); + x->x_start = (t_float *)getbytes(sizeof(*x->x_start)); + x->x_delta = (t_float *)getbytes(sizeof(*x->x_delta)); x->x_sr_khz = sys_getsr() * 0.001; - x->x_last_in = 0.; - x->x_reset = x->x_nleft_up = 0; + x->x_reset = 0; x->x_exp = 1.; + float ms_up = 0, ms_down = 0.; int argnum = 0; while(ac > 0){ if(av->a_type == A_FLOAT){ @@ -183,9 +233,9 @@ static void *glide2_new(t_symbol *s, int ac, t_atom *av){ } void glide2_tilde_setup(void){ - glide2_class = class_new(gensym("glide2~"), (t_newmethod)glide2_new, 0, - sizeof(t_glide2), 0, A_GIMME, 0); - CLASS_MAINSIGNALIN(glide2_class, t_glide2, x_in); + glide2_class = class_new(gensym("glide2~"), (t_newmethod)glide2_new, + (t_method)glide2_free, sizeof(t_glide2), CLASS_MULTICHANNEL, A_GIMME, 0); + class_addmethod(glide2_class, nullfn, gensym("signal"), 0); class_addmethod(glide2_class, (t_method) glide2_dsp, gensym("dsp"), A_CANT, 0); class_addmethod(glide2_class, (t_method)glide2_reset, gensym("reset"), 0); class_addmethod(glide2_class, (t_method)glide2_exp, gensym("exp"), A_FLOAT, 0); diff --git a/Documentation/Help-files/glide2~-help.pd b/Documentation/Help-files/glide2~-help.pd index e25ae38ea..04455f39b 100644 --- a/Documentation/Help-files/glide2~-help.pd +++ b/Documentation/Help-files/glide2~-help.pd @@ -1,45 +1,26 @@ -#N canvas 497 23 565 615 10; -#X obj 305 5 cnv 15 250 40 empty empty empty 12 13 0 18 #7c7c7c #e0e4dc -0; +#N canvas 453 44 565 615 10; +#X obj 305 5 cnv 15 250 40 empty empty empty 12 13 0 18 #7c7c7c #e0e4dc 0; #N canvas 382 141 749 319 (subpatch) 0; #X coords 0 -1 1 1 252 42 2 100 100; #X restore 304 4 pd; -#X obj 344 12 cnv 10 10 10 empty empty ELSE 0 15 2 30 #7c7c7c #e0e4dc -0; -#X obj 457 12 cnv 10 10 10 empty empty EL 0 6 2 13 #7c7c7c #e0e4dc -0; -#X obj 477 12 cnv 10 10 10 empty empty Locus 0 6 2 13 #7c7c7c #e0e4dc -0; -#X obj 514 12 cnv 10 10 10 empty empty Solus' 0 6 2 13 #7c7c7c #e0e4dc -0; -#X obj 463 27 cnv 10 10 10 empty empty ELSE 0 6 2 13 #7c7c7c #e0e4dc -0; -#X obj 501 27 cnv 10 10 10 empty empty library 0 6 2 13 #7c7c7c #e0e4dc -0; -#X obj 3 584 cnv 15 552 21 empty empty empty 20 12 0 14 #e0e0e0 #202020 -0; -#X obj 6 343 cnv 3 550 3 empty empty inlets 8 12 0 13 #dcdcdc #000000 -0; -#X obj 6 459 cnv 3 550 3 empty empty outlets 8 12 0 13 #dcdcdc #000000 -0; -#X obj 6 529 cnv 3 550 3 empty empty arguments 8 12 0 13 #dcdcdc #000000 -0; -#X obj 97 352 cnv 17 3 48 empty empty 0 5 9 0 16 #dcdcdc #9c9c9c 0 -; -#X obj 97 469 cnv 17 3 17 empty empty 0 5 9 0 16 #dcdcdc #9c9c9c 0 -; -#X text 182 352 signal; +#X obj 344 12 cnv 10 10 10 empty empty ELSE 0 15 2 30 #7c7c7c #e0e4dc 0; +#X obj 457 12 cnv 10 10 10 empty empty EL 0 6 2 13 #7c7c7c #e0e4dc 0; +#X obj 477 12 cnv 10 10 10 empty empty Locus 0 6 2 13 #7c7c7c #e0e4dc 0; +#X obj 514 12 cnv 10 10 10 empty empty Solus' 0 6 2 13 #7c7c7c #e0e4dc 0; +#X obj 463 27 cnv 10 10 10 empty empty ELSE 0 6 2 13 #7c7c7c #e0e4dc 0; +#X obj 501 27 cnv 10 10 10 empty empty library 0 6 2 13 #7c7c7c #e0e4dc 0; +#X obj 3 584 cnv 15 552 21 empty empty empty 20 12 0 14 #e0e0e0 #202020 0; +#X obj 6 343 cnv 3 550 3 empty empty inlets 8 12 0 13 #dcdcdc #000000 0; +#X obj 6 459 cnv 3 550 3 empty empty outlets 8 12 0 13 #dcdcdc #000000 0; +#X obj 6 529 cnv 3 550 3 empty empty arguments 8 12 0 13 #dcdcdc #000000 0; +#X obj 97 352 cnv 17 3 48 empty empty 0 5 9 0 16 #dcdcdc #9c9c9c 0; +#X obj 97 469 cnv 17 3 17 empty empty 0 5 9 0 16 #dcdcdc #9c9c9c 0; #X text 237 352 - incoming signal to smooth out; -#X text 180 468 signal; #X text 169 538 1) float; #X text 169 559 2) float; -#X obj 97 408 cnv 17 3 17 empty empty 1 5 9 0 16 #dcdcdc #9c9c9c 0 -; -#X obj 97 432 cnv 17 3 17 empty empty 2 5 9 0 16 #dcdcdc #9c9c9c 0 -; -#X text 187 407 float; +#X obj 97 408 cnv 17 3 17 empty empty 1 5 9 0 16 #dcdcdc #9c9c9c 0; +#X obj 97 432 cnv 17 3 17 empty empty 2 5 9 0 16 #dcdcdc #9c9c9c 0; #X text 237 468 - smoothed out/filtered signal; -#X text 187 431 float; #X obj 25 255 else/glide~; #X text 23 234 see also:; #X obj 491 69 else/setdsp~; @@ -50,27 +31,20 @@ #X obj 155 266 else/out~; #X obj 155 222 *~; #X obj 116 149 else/brown~; -#X obj 275 219 vsl 18 100 0 1 0 0 ewtwet wefwert empty 0 -9 0 10 #dcdcdc -#000000 #000000 0 1; +#X obj 275 219 vsl 18 100 0 1 0 0 ewtwet wefwert empty 0 -9 0 10 #dcdcdc #000000 #000000 0 1; #X obj 275 191 else/sig2float~; #X text 298 312 0; #X text 298 213 1; #X obj 213 132 else/pulse~ 0.5; -#X text 60 91 [glide2~] is just like [glide~] but has distinct ramp -times for both up and down.; -#X obj 23 40 cnv 4 4 4 empty empty Signal 0 28 2 18 #e0e0e0 #000000 -0; -#X obj 80 40 cnv 4 4 4 empty empty glide/portamento 0 28 2 18 #e0e0e0 -#000000 0; -#X obj 2 4 cnv 15 301 42 empty empty glide2~ 20 20 2 37 #e0e0e0 #000000 -0; +#X text 60 91 [glide2~] is just like [glide~] but has distinct ramp times for both up and down.; +#X obj 23 40 cnv 4 4 4 empty empty Signal 0 28 2 18 #e0e0e0 #000000 0; +#X obj 80 40 cnv 4 4 4 empty empty glide/portamento 0 28 2 18 #e0e0e0 #000000 0; +#X obj 2 4 cnv 15 301 42 empty empty glide2~ 20 20 2 37 #e0e0e0 #000000 0; #N canvas 0 22 450 278 (subpatch) 0; #X coords 0 1 100 -1 302 42 1 0 0; #X restore 2 4 graph; -#X obj 6 496 cnv 3 550 3 empty empty flags 8 12 0 13 #dcdcdc #000000 -0; -#X text 90 503 -exp : sets exponential factor (default '1' \, -linear); +#X obj 6 496 cnv 3 550 3 empty empty flags 8 12 0 13 #dcdcdc #000000 0; +#X text 90 503 -exp : sets exponential factor (default '1' \, linear); #X text 188 368 reset; #X text 238 368 - resets glide to input value; #X text 152 384 exp ; @@ -88,16 +62,14 @@ linear); #X connect 3 0 6 0; #X connect 6 0 7 0; #X connect 7 0 0 0; -#X restore 473 281 pd example; +#X restore 473 261 pd example; #N canvas 561 138 532 514 exponential 0; -#X obj 86 323 cnv 15 398 138 empty empty empty 20 12 0 14 #e0e0e0 #404040 -0; +#X obj 86 323 cnv 15 398 138 empty empty empty 20 12 0 14 #e0e0e0 #404040 0; #N canvas 0 22 450 278 (subpatch) 0; #X array \$0-exp 441 float 0; #X coords 0 1 440 0 400 140 1 0 0; #X restore 85 322 graph; -#X obj 74 38 bng 20 250 50 1 empty empty empty 17 7 0 10 #dcdcdc #000000 -#000000; +#X obj 74 38 bng 20 250 50 1 empty empty empty 17 7 0 10 #dcdcdc #000000 #000000; #X obj 75 257 tabwrite~ \$0-exp; #X msg 111 124 4; #X msg 141 124 -4; @@ -108,8 +80,7 @@ linear); #X obj 90 83 else/timed.gate~ 7; #X msg 141 176 exp \$1; #X obj 385 39 else/setdsp~; -#X text 287 142 You can set exponential factors \, much like as in -[rescale~]. Check it out as well., f 33; +#X text 287 142 You can set exponential factors \, much like as in [rescale~]. Check it out as well., f 33; #X obj 90 206 else/glide2~ -exp 4 7 3; #X connect 2 0 3 0; #X connect 2 0 10 0; @@ -121,13 +92,50 @@ linear); #X connect 10 0 14 0; #X connect 11 0 14 0; #X connect 14 0 3 0; -#X restore 450 304 pd exponential; +#X restore 450 284 pd exponential; #X obj 213 160 else/glide2~ 1000 500; #X obj 25 277 else/lag2~; #X obj 25 297 else/slew2~; -#X connect 32 0 31 0; -#X connect 33 0 32 0; -#X connect 35 0 34 0; -#X connect 38 0 52 0; -#X connect 52 0 32 1; -#X connect 52 0 35 0; +#N canvas 589 113 507 509 multichannel 0; +#X obj 81 289 else/s2f~; +#X obj 81 122 bng 25 250 50 0 empty empty empty 0 -8 0 10 #dfdfdf #000000 #000000; +#X obj 353 297 setdsp~; +#X obj 81 320 unpack; +#X obj 81 351 vsl 18 120 0 1 0 0 empty empty empty 0 -9 0 10 #dfdfdf #000000 #000000 0 1; +#X obj 114 351 vsl 18 120 0 1 0 0 empty empty empty 0 -9 0 10 #dfdfdf #000000 #000000 0 1; +#X obj 81 161 else/impseq~; +#X obj 81 203 else/rand.f~ -ch 2 0 1; +#X obj 231 279 else/s2f~; +#X obj 231 324 unpack; +#X obj 231 355 vsl 18 120 0 1 0 0 empty empty empty 0 -9 0 10 #dfdfdf #000000 #000000 0 1; +#X obj 264 355 vsl 18 120 0 1 0 0 empty empty empty 0 -9 0 10 #dfdfdf #000000 #000000 0 1; +#X obj 300 217 else/sigs~ 1500 2500; +#X obj 265 185 else/sigs~ 500 1000; +#X text 45 21 If [glide2~] has a multichannel left input \, it outputs the same number of channels. If the secondary inlets have a single channel for the up/down glide times \, the single value is applied to all channels. If a secondary inlet is also a multichhanel signal \, then each channel gets its own glide time value. Note \, however \, that the number of multichannels in secondary inlets need to match the same number of channels from the left input., f 65; +#X obj 81 260 else/glide2~ 500 1500; +#X obj 231 250 else/glide2~; +#X connect 0 0 3 0; +#X connect 1 0 6 0; +#X connect 3 0 4 0; +#X connect 3 1 5 0; +#X connect 6 0 7 0; +#X connect 7 0 15 0; +#X connect 7 0 16 0; +#X connect 8 0 9 0; +#X connect 9 0 10 0; +#X connect 9 1 11 0; +#X connect 12 0 16 2; +#X connect 13 0 16 1; +#X connect 15 0 0 0; +#X connect 16 0 8 0; +#X restore 446 309 pd multichannel; +#X text 164 352 signal(s); +#X text 163 468 signal(s); +#X text 164 407 signal(s); +#X text 164 431 signal(s); +#X connect 28 0 27 0; +#X connect 29 0 28 0; +#X connect 31 0 30 0; +#X connect 34 0 48 0; +#X connect 48 0 28 1; +#X connect 48 0 31 0;