From dd12428b1cbfd67d3c144367e94e40988cb86609 Mon Sep 17 00:00:00 2001 From: porres Date: Tue, 13 Aug 2024 13:56:30 -0300 Subject: [PATCH] pimp multichannel --- Code_source/Compiled/audio/pimp~.c | 335 ++++++++++++------------- Documentation/Help-files/del~-help.pd | 6 +- Documentation/Help-files/pimp~-help.pd | 232 +++++++++-------- 3 files changed, 297 insertions(+), 276 deletions(-) diff --git a/Code_source/Compiled/audio/pimp~.c b/Code_source/Compiled/audio/pimp~.c index 0be805c95..4e5808346 100644 --- a/Code_source/Compiled/audio/pimp~.c +++ b/Code_source/Compiled/audio/pimp~.c @@ -1,236 +1,235 @@ -// Porres 2016 - 2023 +// Porres 2017-2023 #include "m_pd.h" -#include "math.h" #include "magic.h" -static t_class *pimp_class; +#include +#include + +#define MAXLEN 1024 typedef struct _pimp{ t_object x_obj; - double x_phase; - double x_last_phase_offset; - t_int midi; - t_int soft; - t_float x_freq; + double *x_phase; + int x_nchans; + t_int x_n; + t_int x_sig1; + t_int x_sig2; + t_int x_ch2; + t_int x_ch3; + t_int x_midi; + t_int x_soft; + t_int *x_dir; + float *x_freq_list; + t_int x_list_size; t_inlet *x_inlet_phase; t_inlet *x_inlet_sync; - t_outlet *x_outlet_dsp_0; - t_outlet *x_outlet_dsp_1; - t_float x_sr; + t_outlet *x_out_0; + t_outlet *x_out_1; + double x_sr_rec; // MAGIC: - int x_posfreq; // positive frequency flag t_glist *x_glist; // object list t_float *x_signalscalar; // right inlet's float field - int x_hasfeeders; // right inlet connection flag t_float x_phase_sync_float; // float from magic }t_pimp; -static t_int *pimp_perform_magic(t_int *w){ - t_pimp *x = (t_pimp *)(w[1]); - int nblock = (t_int)(w[2]); - t_float *in1 = (t_float *)(w[3]); // freq - t_float *in3 = (t_float *)(w[5]); // phase - t_float *out1 = (t_float *)(w[6]); - t_float *out2 = (t_float *)(w[7]); - int posfreq = x->x_posfreq; -// Magic Start - t_float *scalar = x->x_signalscalar; - if(!else_magic_isnan(*x->x_signalscalar)){ - t_float input_phase = fmod(*scalar, 1); - if(input_phase < 0) - input_phase += 1; -/* if(input_phase == 0 && x->x_posfreq) - input_phase = 1;*/ - x->x_phase = input_phase; - else_magic_setnan(x->x_signalscalar); - } -// Magic End - double phase = x->x_phase; - double last_phase_offset = x->x_last_phase_offset; - double sr = x->x_sr; - while(nblock--){ - double hz = *in1++; - if(x->midi) - hz = pow(2, (hz - 69)/12) * 440; - posfreq = hz >= 0; - double phase_offset = *in3++; - double phase_step = hz / sr; // phase_step - phase_step = phase_step > 1 ? 1. : phase_step < -1 ? -1 : phase_step; // clipped phase_step - double phase_dev = phase_offset - last_phase_offset; - if(phase_dev >= 1 || phase_dev <= -1) - phase_dev = fmod(phase_dev, 1); // fmod(phase_dev) - if(hz >= 0){ - phase = phase + phase_dev; - if(phase_dev != 0 && phase <= 0){ - phase = phase + 1.; // wrap deviated phase - } - *out2++ = phase >= 1.; - if(phase >= 1.) - phase = phase - 1; // wrapped phase - } - else{ // hz < 0 - phase = phase + phase_dev; - if(phase >= 1) - phase = phase - 1.; // wrap deviated phase - *out2++ = phase <= 0.; - if(phase <= 0.) - phase = phase + 1.; // wrapped phase - } - *out1++ = phase; // wrapped phase - phase += phase_step; // next phase - last_phase_offset = phase_offset; // last phase offset - } - x->x_posfreq = posfreq; - x->x_phase = phase; - x->x_last_phase_offset = last_phase_offset; - return(w+8); +static t_class *pimp_class; + +double pimp_wrap_phase(double phase){ + while(phase >= 1) + phase -= 1.; + while(phase < 0) + phase += 1.; + return(phase); } static t_int *pimp_perform(t_int *w){ t_pimp *x = (t_pimp *)(w[1]); - int nblock = (t_int)(w[2]); - t_float *in1 = (t_float *)(w[3]); // freq - t_float *in2 = (t_float *)(w[4]); // sync - t_float *in3 = (t_float *)(w[5]); // phase - t_float *out1 = (t_float *)(w[6]); - t_float *out2 = (t_float *)(w[7]); - double phase = x->x_phase; - double last_phase_offset = x->x_last_phase_offset; - double sr = x->x_sr; - while(nblock--){ - double hz = *in1++; - if(x->midi) - hz = pow(2, (hz - 69)/12) * 440; - double trig = *in2++; - double phase_offset = *in3++; - double phase_step = hz / sr; // phase_step - phase_step = phase_step > 1 ? 1. : phase_step < -1 ? -1 : phase_step; // clipped phase_step - double phase_dev = phase_offset - last_phase_offset; - if(phase_dev >= 1 || phase_dev <= -1) - phase_dev = fmod(phase_dev, 1); // fmod(phase_dev) - if(x->soft) - phase_step *= (x->soft); - if(hz >= 0){ - if(trig > 0 && trig <= 1){ - if(x->soft) - x->soft = x->soft == 1 ? -1 : 1; - else - phase = trig; - } - else{ - phase = phase + phase_dev; - if(phase_dev != 0 && phase <= 0) - phase = phase + 1.; // wrap deviated phase - } - *out2++ = phase >= 1.; - if(phase >= 1.) - phase = phase - 1; // wrapped phase + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *in3 = (t_float *)(w[4]); + t_float *out1 = (t_float *)(w[5]); + t_float *out2 = (t_float *)(w[6]); + t_int *dir = x->x_dir; + double *phase = x->x_phase; +// Magic Start + if(!x->x_sig2){ + t_float *scalar = x->x_signalscalar; + if(!else_magic_isnan(*x->x_signalscalar)){ + t_float input_phase = fmod(*scalar, 1); + if(input_phase < 0) + input_phase += 1; + for(int j = 0; j < x->x_nchans; j++) + x->x_phase[j] = input_phase; + else_magic_setnan(x->x_signalscalar); } - else{ // hz < 0 - if(trig > 0 && trig < 1){ - if(x->soft) - x->soft = x->soft == 1 ? -1 : 1; - else - phase = trig; - } - else if(trig == 1){ - if(x->soft) - x->soft = x->soft == 1 ? -1 : 1; - else - phase = 0; - } - else{ - phase = phase + phase_dev; - if(phase >= 1) - phase = phase - 1.; // wrap deviated phase + } +// Magic End + for(int j = 0; j < x->x_nchans; j++){ + for(int i = 0, n = x->x_n; i < n; i++){ + double hz = x->x_sig1 ? in1[j*n + i] : x->x_freq_list[j]; + if(x->x_midi) + hz = hz <= 0 ? 0 : pow(2, (hz - 69)/12) * 440; + double step = hz * x->x_sr_rec; // phase step + step = step > 1.0 ? 1.0 : step < -1.0 ? -1.0 : step; + if(x->x_sig2){ + if(x->x_soft){ + if(dir[j] == 0) + dir[j] = 1; + step *= (dir[j]); + } + t_float trig = x->x_ch2 == 1 ? in2[i] : in2[j*n + i]; + if(trig > 0 && trig <= 1){ + if(x->x_soft) + dir[j] = dir[j] == 1 ? -1 : 1; + else + phase[j] = trig; + } } - *out2++ = phase <= 0.; - if(phase <= 0.) - phase = phase + 1.; // wrapped phase + double phase_offset = x->x_ch3 == 1 ? in3[i] : in3[j*n + i]; + out1[j*n + i] = pimp_wrap_phase(phase[j] + phase_offset); + out2[j*n + i] = phase[j] >= 1 || phase[j] < 0;; + phase[j] = pimp_wrap_phase(phase[j]); + phase[j] += step; } - *out1++ = phase; // wrapped phase - phase += phase_step; // next phase - last_phase_offset = phase_offset; // last phase offset } x->x_phase = phase; - x->x_last_phase_offset = last_phase_offset; - return(w+8); + x->x_dir = dir; + return(w+7); } static void pimp_dsp(t_pimp *x, t_signal **sp){ - x->x_hasfeeders = else_magic_inlet_connection((t_object *)x, x->x_glist, 1, &s_signal); // magic feeder flag - x->x_sr = sp[0]->s_sr; - if(x->x_hasfeeders){ - dsp_add(pimp_perform, 7, x, sp[0]->s_n, - sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec); + x->x_n = sp[0]->s_n, x->x_sr_rec = 1.0 / (double)sp[0]->s_sr; + x->x_ch2 = sp[1]->s_nchans, x->x_ch3 = sp[2]->s_nchans; + x->x_sig1 = else_magic_inlet_connection((t_object *)x, x->x_glist, 0, &s_signal); + x->x_sig2 = else_magic_inlet_connection((t_object *)x, x->x_glist, 1, &s_signal); + int chs = x->x_sig1 ? sp[0]->s_nchans : x->x_list_size; + if(x->x_nchans != chs){ + x->x_phase = (double *)resizebytes(x->x_phase, + x->x_nchans * sizeof(double), chs * sizeof(double)); + x->x_dir = (t_int *)resizebytes(x->x_dir, + x->x_nchans * sizeof(double), chs * sizeof(double)); + x->x_nchans = chs; } - else{ - dsp_add(pimp_perform_magic, 7, x, sp[0]->s_n, - sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec); + signal_setmultiout(&sp[3], x->x_nchans); + signal_setmultiout(&sp[4], x->x_nchans); + if((x->x_ch2 > 1 && x->x_ch2 != x->x_nchans) + || (x->x_ch3 > 1 && x->x_ch3 != x->x_nchans)){ + dsp_add_zero(sp[3]->s_vec, x->x_nchans*x->x_n); + pd_error(x, "[pimp~]: channel sizes mismatch"); + return; } + dsp_add(pimp_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, + sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec); } static void pimp_midi(t_pimp *x, t_floatarg f){ - x->midi = (int)(f != 0); + x->x_midi = (int)(f != 0); +} + +static void pimp_set(t_pimp *x, t_symbol *s, int ac, t_atom *av){ + s = NULL; + if(ac != 2) + return; + int i = atom_getint(av); + float f = atom_getint(av+1); + if(i >= x->x_list_size) + i = x->x_list_size; + if(i <= 0) + i = 1; + i--; + x->x_freq_list[i] = f; +} + +static void pimp_list(t_pimp *x, t_symbol *s, int ac, t_atom * av){ + s = NULL; + if(ac == 0) + return; + if(x->x_list_size != ac){ + x->x_list_size = ac; + canvas_update_dsp(); + } + for(int i = 0; i < ac; i++) + x->x_freq_list[i] = atom_getfloat(av+i); } static void pimp_soft(t_pimp *x, t_floatarg f){ - x->soft = (int)(f != 0); + x->x_soft = (int)(f != 0); } static void *pimp_free(t_pimp *x){ inlet_free(x->x_inlet_sync); inlet_free(x->x_inlet_phase); - outlet_free(x->x_outlet_dsp_0); - outlet_free(x->x_outlet_dsp_1); + outlet_free(x->x_out_0); + outlet_free(x->x_out_1); + freebytes(x->x_phase, x->x_nchans * sizeof(*x->x_phase)); + freebytes(x->x_dir, x->x_nchans * sizeof(*x->x_dir)); + free(x->x_freq_list); return(void *)x; } static void *pimp_new(t_symbol *s, int ac, t_atom *av){ s = NULL; t_pimp *x = (t_pimp *)pd_new(pimp_class); - x->midi = 0; - t_float init_freq = 0, init_phase = 0; + x->x_midi = x->x_soft = 0; + x->x_dir = (t_int *)getbytes(sizeof(*x->x_dir)); + x->x_phase = (double *)getbytes(sizeof(*x->x_phase)); + x->x_freq_list = (float*)malloc(MAXLEN * sizeof(float)); + x->x_freq_list[0] = x->x_phase[0] = 0; + x->x_list_size = 1; while(ac && av->a_type == A_SYMBOL){ - if(atom_getsymbol(av) == gensym("-midi")) - x->midi = 1; - else if(atom_getsymbol(av) == gensym("-soft")) - x->soft = 1; - ac--, av++; + if(atom_getsymbol(av) == gensym("-midi")){ + x->x_midi = 1; + ac--, av++; + } + else if(atom_getsymbol(av) == gensym("-soft")){ + x->x_soft = 1; + ac--, av++; + } + else if(atom_getsymbol(av) == gensym("-mc")){ + ac--, av++; + if(!ac || av->a_type != A_FLOAT) + goto errstate; + int n = 0; + while(ac && av->a_type == A_FLOAT){ + x->x_freq_list[n] = atom_getfloat(av); + ac--, av++, n++; + } + x->x_list_size = n; + } + else + goto errstate; } if(ac && av->a_type == A_FLOAT){ - init_freq = av->a_w.w_float; + x->x_freq_list[0] = av->a_w.w_float; ac--, av++; if(ac && av->a_type == A_FLOAT){ - init_phase = av->a_w.w_float; + x->x_phase[0] = av->a_w.w_float; ac--, av++; } } - init_phase = init_phase < 0 ? 0 : init_phase >= 1 ? 0 : init_phase; // clipping phase input - if(init_freq >= 0) - x->x_posfreq = 1; - x->x_phase = init_phase; - x->x_last_phase_offset = 0; - x->x_freq = init_freq; - x->x_sr = sys_getsr(); // sample rate x->x_inlet_sync = inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); pd_float((t_pd *)x->x_inlet_sync, 0); x->x_inlet_phase = inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); - pd_float((t_pd *)x->x_inlet_phase, init_phase); - x->x_outlet_dsp_0 = outlet_new(&x->x_obj, &s_signal); + pd_float((t_pd *)x->x_inlet_phase, x->x_phase[0]); + x->x_out_0 = outlet_new(&x->x_obj, &s_signal); + x->x_out_1 = outlet_new(&x->x_obj, &s_signal); // Magic x->x_glist = canvas_getcurrent(); x->x_signalscalar = obj_findsignalscalar((t_object *)x, 1); - x->x_outlet_dsp_1 = outlet_new(&x->x_obj, &s_signal); return(x); +errstate: + post("[pimp~]: improper args"); + return(NULL); } void pimp_tilde_setup(void){ pimp_class = class_new(gensym("pimp~"), (t_newmethod)pimp_new, (t_method)pimp_free, - sizeof(t_pimp), CLASS_DEFAULT, A_GIMME, 0); - CLASS_MAINSIGNALIN(pimp_class, t_pimp, x_freq); + sizeof(t_pimp), CLASS_MULTICHANNEL, A_GIMME, 0); + class_addmethod(pimp_class, nullfn, gensym("signal"), 0); + class_addmethod(pimp_class, (t_method)pimp_dsp, gensym("dsp"), A_CANT, 0); + class_addlist(pimp_class, pimp_list); class_addmethod(pimp_class, (t_method)pimp_soft, gensym("soft"), A_DEFFLOAT, 0); class_addmethod(pimp_class, (t_method)pimp_midi, gensym("midi"), A_DEFFLOAT, 0); - class_addmethod(pimp_class, (t_method)pimp_dsp, gensym("dsp"), A_CANT, 0); + class_addmethod(pimp_class, (t_method)pimp_set, gensym("set"), A_GIMME, 0); } diff --git a/Documentation/Help-files/del~-help.pd b/Documentation/Help-files/del~-help.pd index aa2605d18..5a9f33840 100755 --- a/Documentation/Help-files/del~-help.pd +++ b/Documentation/Help-files/del~-help.pd @@ -1,4 +1,4 @@ -#N canvas 577 34 560 469 10; +#N canvas 577 38 560 469 10; #X obj 2 4 cnv 15 301 42 empty empty del~ 20 20 2 37 #e0e0e0 #000000 0; #N canvas 0 22 450 278 (subpatch) 0; #X coords 0 1 100 -1 302 42 1; @@ -21,7 +21,7 @@ #X floatatom 322 164 6 0 0 0 - - - 0; #X obj 322 193 else/f2s~ 200; #X obj 61 149 else/player~ bubul.wav 1 1; -#N canvas 466 23 561 610 del~ 0; +#N canvas 466 38 561 610 del~ 0; #X obj 4 378 cnv 3 550 3 empty empty inlets 8 12 0 13 #dcdcdc #000000 0; #X obj 4 454 cnv 3 550 3 empty empty outlets 8 12 0 13 #dcdcdc #000000 0; #X obj 3 520 cnv 3 550 3 empty empty arguments 8 12 0 13 #dcdcdc #000000 0; @@ -164,9 +164,9 @@ #X obj 96 214 else/del~ out -samps \$0-y 44100; #X text 34 457 2) float; #X text 28 441 1) symbol; -#X text 91 456 - delay size in ms or samples (default 1 sample); #X text 91 441 - sets delay line name (optional: default internal name relative to patch), f 74; #X text 77 86 Read from a delay line. It uses a cubic (4 point) interpolation called spline and considers the buffer to be circular (so index 0 to table size is accepted)., f 70; +#X text 91 456 - delay time in ms or samples (default 0); #X connect 25 0 26 0; #X connect 26 0 27 0; #X connect 27 0 35 0; diff --git a/Documentation/Help-files/pimp~-help.pd b/Documentation/Help-files/pimp~-help.pd index 7d9080e54..d25d03736 100644 --- a/Documentation/Help-files/pimp~-help.pd +++ b/Documentation/Help-files/pimp~-help.pd @@ -1,12 +1,12 @@ -#N canvas 480 58 561 605 10; -#X obj 3 420 cnv 3 550 3 empty empty outlets 8 12 0 13 #dcdcdc #000000 0; -#X obj 3 523 cnv 3 550 3 empty empty arguments 8 12 0 13 #dcdcdc #000000 0; -#X obj 104 429 cnv 17 3 17 empty empty 0 5 9 0 16 #dcdcdc #9c9c9c 0; -#X obj 3 574 cnv 15 552 21 empty empty empty 20 12 0 14 #e0e0e0 #202020 0; +#N canvas 493 38 562 616 10; +#X obj 3 424 cnv 3 550 3 empty empty outlets 8 12 0 13 #dcdcdc #000000 0; +#X obj 3 543 cnv 3 550 3 empty empty arguments 8 12 0 13 #dcdcdc #000000 0; +#X obj 102 433 cnv 17 3 17 empty empty 0 5 9 0 16 #dcdcdc #9c9c9c 0; +#X obj 3 589 cnv 15 552 21 empty empty empty 20 12 0 14 #e0e0e0 #202020 0; #X obj 23 42 cnv 4 4 4 empty empty Phasor~ 0 28 2 18 #e0e0e0 #000000 0; #X obj 90 42 cnv 4 4 4 empty empty + 0 28 2 18 #e0e0e0 #000000 0; #N canvas 207 34 366 264 (subpatch) 0; -#X obj 51 101 tgl 42 0 \$0-tgl-s \$0-tgl-r empty 1 8 1 9 #dcdcdc #7c7c7c #fcfcfc 0 1; +#X obj 51 101 tgl 42 0 \$0-tgl-s \$0-tgl-r empty 1 8 1 9 #4a4f51 #cde5c3 #fcfcfc 0 1; #X obj 215 68 route dsp; #X obj 215 37 receive pd; #N canvas 977 77 379 291 set_color 0; @@ -75,7 +75,7 @@ #X restore 215 165 pd set_color; #X obj 135 122 r \$0-tgl-s; #N canvas 121 482 450 300 (subpatch) 0; -#X obj 101 101 cnv 25 40 25 empty \$0-cnv DSP 3 13 0 20 #dcdcdc #7c7c7c 0; +#X obj 101 101 cnv 25 40 25 empty \$0-cnv DSP 3 13 0 20 #4a4f51 #cde5c3 0; #X coords 0 -1 1 1 42 27 1 100 100; #X restore 51 144 pd; #X obj 226 139 s \$0-tgl-r; @@ -106,13 +106,12 @@ #X connect 9 0 0 0; #X coords 0 -1 1 1 44 72 2 50 100; #X restore 505 71 pd; -#X text 188 429 signal -; -#X obj 104 450 cnv 17 3 17 empty empty 1 5 9 0 16 #dcdcdc #9c9c9c 0; -#X text 188 450 signal -; -#X text 249 429 phase signal; -#X text 171 532 1) float; -#X text 239 532 - frequency in hertz; -#X text 171 552 2) float; +#X text 188 433 signal -; +#X obj 102 454 cnv 17 3 17 empty empty 1 5 9 0 16 #dcdcdc #9c9c9c 0; +#X text 188 454 signal -; +#X text 249 433 phase signal; +#X text 171 551 1) float; +#X text 171 567 2) float; #N canvas 483 104 832 590 sync 0; #X obj 137 320 cnv 15 198 118 empty empty empty 20 12 0 14 #e0e0e0 #404040 0; #N canvas 0 22 450 278 (subpatch) 0; @@ -127,7 +126,7 @@ #X connect 0 0 2 0; #X connect 1 0 2 0; #X connect 3 0 1 0; -#X restore 282 233 pd graph; +#X restore 272 233 pd graph; #X text 489 62 An impulse oscillator as the input forces hard sync to the phase output., f 51; #X text 735 217 Master; #X text 660 266 Slave; @@ -137,53 +136,51 @@ #X obj 563 265 else/pimp~ 200; #X obj 636 216 else/pimp~ 110; #X text 486 427 NOTE:; -#X msg 41 134 0; -#X msg 72 133 0.25; -#X msg 144 133 0.75; -#X msg 184 133 1; -#X msg 112 133 0.5; -#X text 215 132 <= reset =>; +#X msg 41 128 0; +#X msg 72 128 0.25; +#X msg 144 128 0.75; +#X msg 184 128 1; +#X msg 112 128 0.5; #X obj 130 215 else/out~; #X obj 61 180 else/pimp~ 1; -#X obj 282 198 else/pimp~ 2; +#X obj 272 198 else/pimp~ 2; #X text 33 13 The second inlet resets the phase ands behaves in the same way as in [phasor~]. A number input resets the oscillator and restarts the cycle with an initial phase that corresponds to the input number \, so the internal phase is synced to the given value. The phase values are from 0 to 1 and values beyond that are wrapped within this range.; #X text 34 473 Additionally \, you can reset the oscillator with an impulse signal. Inputs that are > 0 and <= 1 reset the phase Pdexpects an impulse signal for syncing. The impulse values need to be > 0 and <= 1 (otherwise ignored). Because phase is cyclical \, the value of 1 represents the "phase 0" of the cycle \, where the impulse occurs. Send it impulses above and check the result. Use a multiplier to reset to another phase value.; -#X msg 422 131 0.25; -#X msg 348 130 0.75; -#X msg 316 130 1; -#X msg 388 130 0.5; -#X obj 316 162 else/impseq~; +#X msg 412 128 0.25; +#X msg 338 128 0.75; +#X msg 306 128 1; +#X msg 378 128 0.5; +#X obj 306 162 else/impseq~; #X text 510 454 The "phase sync" inlet is quite different from the "phase offset" inlet. This means that the are completely independent., f 44; #X msg 563 218 soft \$1; #X obj 563 187 tgl 16 0 empty empty empty 0 -8 0 10 #dfdfdf #000000 #000000 0 1; #X text 489 98 Soft sync is also possible with the '-soft' flag or the "soft" message \, where it alternates between positive and negative frequencies and sounds less harsh., f 51; +#X text 215 127 <-- reset -->; #X connect 6 0 7 0; #X connect 8 0 10 0; #X connect 9 0 6 0; #X connect 10 1 9 1; -#X connect 12 0 19 1; -#X connect 13 0 19 1; -#X connect 14 0 19 1; -#X connect 15 0 19 1; -#X connect 16 0 19 1; -#X connect 19 1 18 0; -#X connect 20 0 2 0; -#X connect 23 0 27 0; -#X connect 24 0 27 0; -#X connect 25 0 27 0; -#X connect 26 0 27 0; -#X connect 27 0 20 1; -#X connect 29 0 9 0; -#X connect 30 0 29 0; -#X restore 498 253 pd sync; -#X obj 210 169 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10 #dcdcdc #000000 #000000 0 256; -#X obj 210 197 else/pimp~ 1, f 17; -#X obj 309 245 else/out~; -#X obj 210 257 nbx 8 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10 #dcdcdc #000000 #000000 0 256; -#X obj 171 190 vsl 20 90 0 1 0 0 dsfsk sfg empty 0 -9 0 10 #dcdcdc #000000 #000000 0 1; +#X connect 12 0 18 1; +#X connect 13 0 18 1; +#X connect 14 0 18 1; +#X connect 15 0 18 1; +#X connect 16 0 18 1; +#X connect 18 1 17 0; +#X connect 19 0 2 0; +#X connect 22 0 26 0; +#X connect 23 0 26 0; +#X connect 24 0 26 0; +#X connect 25 0 26 0; +#X connect 26 0 19 1; +#X connect 28 0 9 0; +#X connect 29 0 28 0; +#X restore 498 225 pd sync; +#X obj 210 164 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10 #dcdcdc #000000 #000000 0 256; +#X obj 210 192 else/pimp~ 1, f 17; +#X obj 309 240 else/out~; +#X obj 210 252 nbx 8 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10 #dcdcdc #000000 #000000 0 256; +#X obj 171 185 vsl 20 90 0 1 0 0 dsfsk sfg empty 0 -9 0 10 #dcdcdc #000000 #000000 0 1; #X obj 110 42 cnv 4 4 4 empty empty imp~ 0 28 2 18 #e0e0e0 #000000 0; -#X text 322 217 <= impulse; -#X text 111 225 phase =>; #X obj 3 4 cnv 15 301 42 empty empty pimp~ 20 20 2 37 #e0e0e0 #000000 0; #X obj 306 4 cnv 15 250 40 empty empty empty 12 13 0 18 #7c7c7c #e0e4dc 0; #N canvas 0 22 450 278 (subpatch) 0; @@ -238,36 +235,22 @@ #X connect 20 0 22 2; #X connect 21 0 15 0; #X connect 22 0 15 1; -#X restore 450 277 pd phase offset; -#X text 239 552 - initial phase offset; -#X text 160 268 0; -#X text 160 186 1; -#X text 249 450 impulse signal (at period transitions); +#X restore 450 249 pd phase offset; +#X text 160 263 0; +#X text 160 181 1; +#X text 249 454 impulse signal (at period transitions); #X text 63 89 [pimp~] is a combination of [phasor~] and [else/imp~] (alias of [else/impulse~]). It's [imp~] with an extra phase output (left outlet). The impulse happens at every phase period start (in both negative or positive frequencies/directions). It also has inlets for phase sync and phase modulation like [imp~].; -#X obj 3 311 cnv 3 550 3 empty empty inlets 8 12 0 13 #dcdcdc #000000 0; -#X text 147 320 float/signal -; -#X text 240 320 frequency in hz; -#X obj 104 372 cnv 17 3 17 empty empty 1 5 9 0 16 #dcdcdc #9c9c9c 0; -#X text 147 393 float/signal -; -#X obj 104 392 cnv 17 3 17 empty empty 2 5 9 0 16 #dcdcdc #9c9c9c 0; -#X text 252 393 phase offset (modulation input); -#X text 252 373 phase sync (resets internal phase); -#X text 147 373 float/signal -; -#N canvas 461 182 707 329 example 0; +#X obj 3 306 cnv 3 550 3 empty empty inlets 8 12 0 13 #dcdcdc #000000 0; +#X text 240 314 frequency in hz, f 47; +#X obj 102 379 cnv 17 3 17 empty empty 1 5 9 0 16 #dcdcdc #9c9c9c 0; +#X text 147 400 float/signal -; +#X obj 102 399 cnv 17 3 17 empty empty 2 5 9 0 16 #dcdcdc #9c9c9c 0; +#X text 240 400 phase offset (modulation input), f 47; +#X text 240 380 phase sync (resets internal phase), f 47; +#X text 147 380 float/signal -; +#N canvas 612 179 707 329 example 0; #X obj 309 201 else/sh~; #X obj 309 146 noise~; -#X obj 309 274 nbx 8 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10 #dcdcdc #000000 #000000 0 256; -#N canvas 1046 306 123 217 snapshot~ 0; -#X obj 29 107 snapshot~; -#X obj 46 79 metro 100; -#X obj 46 53 loadbang; -#X obj 29 146 outlet; -#X obj 29 25 inlet~; -#X connect 0 0 3 0; -#X connect 1 0 0 0; -#X connect 2 0 1 0; -#X connect 4 0 0 0; -#X restore 309 244 pd snapshot~; #X obj 123 123 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10 #dcdcdc #000000 #000000 0 256; #X obj 126 98 hsl 128 15 -1 1 0 0 empty empty empty -2 -8 0 10 #dcdcdc #000000 #000000 0 1; #X obj 432 145 cnv 15 198 138 empty empty empty 20 12 0 14 #e0e0e0 #404040 0; @@ -278,29 +261,29 @@ #X text 637 274 0; #X text 635 137 1; #X obj 49 226 metro 100; -#X obj 49 201 tgl 15 0 empty empty empty 17 7 0 10 #dcdcdc #000000 #000000 0 1; -#X obj 49 177 loadbang; +#X obj 49 197 tgl 19 0 empty empty empty 17 7 0 10 #dcdcdc #000000 #000000 0 1; +#X obj 49 173 loadbang; #X obj 123 273 tabwrite~ \$0-phase; #X text 151 97 frequency; #X obj 192 202 else/out~; #X obj 123 150 else/pimp~ 1; #X text 14 15 [pimp~] is very convenient for both driving a process with its phase output (such as reading a sample or envelope) and also triggering at period transitions other objects or processes (such as with [sh~] below)., f 54; #X text 357 15 Since it deals with negative frequencies \, the impulse is only sent when leaping from one phase cycle to the next (in either direction). Try smoothly changing the frequency from positive to negative in the slider to the left \, pay close attention to the phase output below and litsen to when the impulse happens., f 53; -#X connect 0 0 3 0; +#X obj 309 244 else/numbox~ 6 10 100 #C0C0C4 #440008 10 0 0 0; +#X connect 0 0 17 0; #X connect 1 0 0 0; +#X connect 2 0 14 0; #X connect 3 0 2 0; -#X connect 4 0 16 0; -#X connect 5 0 4 0; -#X connect 10 0 13 0; -#X connect 11 0 10 0; -#X connect 12 0 11 0; -#X connect 16 0 13 0; -#X connect 16 1 15 0; -#X connect 16 1 0 1; -#X restore 480 208 pd example; -#X obj 210 228 else/s2f~; -#X text 18 260 see also:; -#X obj 18 279 else/pimpmul~; +#X connect 8 0 11 0; +#X connect 9 0 8 0; +#X connect 10 0 9 0; +#X connect 14 0 11 0; +#X connect 14 1 13 0; +#X connect 14 1 0 1; +#X restore 480 203 pd example; +#X obj 210 223 else/s2f~; +#X text 18 255 see also:; +#X obj 18 274 else/pimpmul~; #N canvas 767 116 434 354 midi 0; #X msg 150 150 midi \$1; #X obj 150 121 tgl 19 0 empty empty empty 0 -8 0 10 #dfdfdf #000000 #000000 0 1; @@ -312,17 +295,56 @@ #X connect 1 0 0 0; #X connect 2 0 4 0; #X connect 4 0 3 0; -#X restore 498 230 pd midi; -#X obj 3 477 cnv 3 550 3 empty empty flags 8 12 0 13 #dcdcdc #000000 0; -#X text 133 498 -soft: sets to soft sync mode (default hard); -#X obj 105 321 cnv 17 3 45 empty empty 0 5 9 0 16 #dcdcdc #9c9c9c 0; -#X text 147 336 midi -; -#X text 240 336 non zero sets to frequency input in MIDI pitch; -#X text 147 352 soft -; -#X text 240 352 non zero sets to soft sync mode; -#X text 133 483 -midi: sets frequency input in MIDI pitch (default hertz); -#X connect 15 0 16 0; -#X connect 16 0 49 0; -#X connect 16 1 17 0; -#X connect 18 0 19 0; -#X connect 49 0 18 0; +#X restore 448 225 pd midi; +#X obj 3 480 cnv 3 550 3 empty empty flags 8 12 0 13 #dcdcdc #000000 0; +#X text 133 519 -soft: sets to soft sync mode (default hard), f 58; +#X obj 103 315 cnv 17 3 57 empty empty 0 5 9 0 16 #dcdcdc #9c9c9c 0; +#X text 147 328 midi -; +#X text 240 328 non zero sets to frequency input in MIDI pitch, f 47; +#X text 147 356 soft -; +#X text 240 356 non zero sets to soft sync mode, f 47; +#X text 133 504 -midi: sets frequency input in MIDI pitch (default hertz), f 58; +#X text 322 212 <-- impulse; +#X text 239 551 - frequency in hertz (default 0), f 34; +#X text 239 567 - initial phase offset (default 0); +#X text 106 220 phase -->; +#N canvas 640 164 534 476 multichannel 0; +#X obj 39 354 else/out.mc~; +#X obj 117 273 else/sine~; +#X obj 117 244 *~ 0.75; +#X obj 110 179 *~ 2; +#X obj 236 368 else/out~; +#X floatatom 236 186 5 0 0 0 - - - 12; +#X msg 249 217 400 600; +#X msg 262 247 400 600 700; +#X obj 39 145 else/sigs~ 333 444; +#X obj 110 205 else/impulse~; +#X msg 279 290 set 1 555; +#X text 349 283 the set message sets a single frequency channel, f 24; +#X obj 39 303 else/pimp~; +#X obj 236 337 else/pimp~ -mc 440 660; +#X text 33 14 If [pimp~] has a multichannel left input \, it outputs the same number of channels. If the secondary inlets have a signal with a single channel for sync and phase modulation \, the single value is applied to all channels. If a secondary inlet is also a multichhanel signal \, then each channel gets its sync or phase deviation value. Note \, however \, that the number of multichannels in secondary inlets need to match the same number of channels from the left input., f 76; +#X text 195 109 You can initialize the object with multichannel if you give it a list of frequencies with the -mc flag (you can't set phases though). A list input also works if no signal is connected to set it to multichannel with a list of frequencies input., f 49; +#X connect 1 0 12 2; +#X connect 2 0 1 0; +#X connect 3 0 9 0; +#X connect 5 0 13 0; +#X connect 6 0 13 0; +#X connect 7 0 13 0; +#X connect 8 0 2 0; +#X connect 8 0 3 0; +#X connect 8 0 12 0; +#X connect 9 0 12 1; +#X connect 10 0 13 0; +#X connect 12 0 0 0; +#X connect 13 0 4 0; +#X restore 450 273 pd multichannel; +#X text 153 314 list/signal -; +#X text 111 342 set -; +#X text 240 342 set a single frequency channel, f 47; +#X text 103 489 -mc : sets multichannel output with a list of frequencies, f 63; +#X connect 14 0 15 0; +#X connect 15 0 44 0; +#X connect 15 1 16 0; +#X connect 17 0 18 0; +#X connect 44 0 17 0;