// sigpack // for // pure-data // by weiss // www.weiss-archiv.de #include "m_pd.h" #include #include #ifdef _MSC_VER #pragma warning( disable : 4244 ) #pragma warning( disable : 4305 ) #endif #define BUFFER_SIZE 10240 #define SSTAB 0.00001f #define ASTAB 0.02f //Truncate-to-zero modulo (ANSI C doesn`t specify) will only work //if -m < v < 2m #define MOD(v,m) (v<0?v+m:(v>=m?v-m:v)) // ------------------------ transient~ ----------------------------- // transient mangler // code from swh_plugins by steve harris www.plugin.org.uk static t_class *transient_tilde_class; typedef struct _transient_tilde { t_object x_obj; t_sample x_attack;//-1 - 1 t_sample x_sustain;//-1 - 1 float *x_buffer; int x_buffer_pos; long x_count; float x_fast_buffer_sum; float x_fast_track; float x_medi_buffer_sum; float x_medi_track; int x_sample_rate; float x_slow_buffer_sum; float x_slow_track; float x_f; } t_transient_tilde; static void *transient_tilde_new(t_floatarg attack, t_floatarg sustain) { t_transient_tilde *x = (t_transient_tilde *)pd_new(transient_tilde_class); x->x_attack = attack; x->x_sustain = sustain; outlet_new(&x->x_obj, gensym("signal")); floatinlet_new(&x->x_obj, &x->x_attack); floatinlet_new(&x->x_obj, &x->x_sustain); //memset(x->x_buffer, '/0', BUFFER_SIZE * sizeof(float)); x->x_buffer = getbytes(BUFFER_SIZE * sizeof(float)); x->x_fast_buffer_sum = 0.1; x->x_medi_buffer_sum = 0.1; x->x_slow_buffer_sum = 0.1; x->x_buffer_pos = 0; x->x_fast_track = 0.0; x->x_medi_track = 0.0; x->x_slow_track = 0.0; x->x_count = 0; x->x_sample_rate = sys_getsr(); x->x_f = 0; if (attack) x->x_attack = attack; else x->x_attack = 0.0; if (sustain) x->x_sustain = sustain; else x->x_sustain = 0.0; return (x); } static t_int *transient_tilde_perform(t_int *w) { t_transient_tilde *x = (t_transient_tilde *)(w[1]); t_float *in = (t_float *)(w[2]); t_float *out = (t_float *)(w[3]); int n = (int)(w[4]); float f; const int fast_sum_size = (2 * x->x_sample_rate) / 1000; const int medi_sum_size = (25 * x->x_sample_rate) / 1000; const int slow_sum_size = (100 * x->x_sample_rate) / 1000; const float fast_track_lag = 1.5f / fast_sum_size; const float medi_track_lag = 1.0f / medi_sum_size; const float slow_track_lag = 1.3f / slow_sum_size; float ratio; while (n--) { f = *in++; x->x_buffer[x->x_buffer_pos] = fabs(f); x->x_fast_buffer_sum += x->x_buffer[x->x_buffer_pos]; x->x_medi_buffer_sum += x->x_buffer[x->x_buffer_pos]; x->x_slow_buffer_sum += x->x_buffer[x->x_buffer_pos]; x->x_fast_buffer_sum -= x->x_buffer[MOD(x->x_buffer_pos - fast_sum_size, BUFFER_SIZE)]; x->x_medi_buffer_sum -= x->x_buffer[MOD(x->x_buffer_pos - medi_sum_size, BUFFER_SIZE)]; x->x_slow_buffer_sum -= x->x_buffer[MOD(x->x_buffer_pos - slow_sum_size, BUFFER_SIZE)]; if(x->x_count++ > slow_sum_size) { x->x_fast_track += (x->x_fast_buffer_sum/fast_sum_size - x->x_fast_track) * fast_track_lag; x->x_medi_track += (x->x_medi_buffer_sum/medi_sum_size - x->x_medi_track) * medi_track_lag; x->x_slow_track += (x->x_slow_buffer_sum/slow_sum_size - x->x_slow_track) * slow_track_lag; } //Attack ratio = (x->x_fast_track + ASTAB) / (x->x_medi_track + ASTAB); if (ratio * x->x_attack > 1.0f) { f *= ratio * x->x_attack; } else if (ratio * x->x_attack < 1.0f) { f /= ratio * -x->x_attack; } //Sustain ratio = (x->x_slow_track + SSTAB) / (x->x_medi_track + SSTAB); if (ratio * x->x_sustain > 1.0f) { f *= ratio * x->x_sustain; } else if (ratio * x->x_sustain < -1.0f) { f /= ratio * x->x_sustain; } *out++ = f; x->x_buffer_pos = (x->x_buffer_pos +1) % BUFFER_SIZE; } return (w+5); } static void transient_tilde_dsp(t_transient_tilde *x, t_signal **sp) { dsp_add(transient_tilde_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); } void transient_tilde_setup(void) { transient_tilde_class = class_new(gensym("transient~"), (t_newmethod)transient_tilde_new, 0, sizeof(t_transient_tilde), 0, A_DEFFLOAT, A_DEFFLOAT, 0); CLASS_MAINSIGNALIN(transient_tilde_class, t_transient_tilde, x_f); class_addmethod(transient_tilde_class, (t_method)transient_tilde_dsp, gensym("dsp"), 0); }