aboutsummaryrefslogtreecommitdiff
path: root/reanimator~.c
diff options
context:
space:
mode:
Diffstat (limited to 'reanimator~.c')
-rw-r--r--reanimator~.c698
1 files changed, 698 insertions, 0 deletions
diff --git a/reanimator~.c b/reanimator~.c
new file mode 100644
index 0000000..8afec93
--- /dev/null
+++ b/reanimator~.c
@@ -0,0 +1,698 @@
+#include "MSPd.h"
+#include "fftease.h"
+
+
+#define THRESHOLD_MIN (.000001)
+
+#if MSP
+void *reanimator_class;
+#endif
+
+#if PD
+static t_class *reanimator_class;
+#endif
+
+
+#define OBJECT_NAME "reanimator~"
+
+typedef struct _reanimator
+{
+#if MSP
+ t_pxobject x_obj;
+#endif
+#if PD
+ t_object x_obj;
+ float x_f;
+#endif
+ int R;
+ int N;
+ int N2;
+ int Nw;
+ int Nw2;
+ int D;
+ int i;
+ int inCount;
+ float *Wanal;
+ float *Wsyn;
+ float *input;
+ float *Hwin;
+ float *buffer;
+ float *channel;
+ float *output;
+ float **framebank;
+ float *normalized_frame;
+ float current_frame;
+ int framecount;
+ //
+ float frame_increment ;
+ float last_frame ;
+
+ float fpos;
+ float last_fpos;
+ float tadv;
+ // for convert
+ float *c_lastphase_in;
+ float *c_lastphase_out;
+ float c_fundamental;
+ float c_factor_in;
+ float c_factor_out;
+ // faster fft
+ float mult;
+ float *trigland;
+ int *bitshuffle;
+ int read_me;
+
+ int total_frames;
+ short mute;
+ short initialized;
+ float threshold;
+ short inverse;
+ int top_comparator_bin;
+ short residency_mode;
+ int vs;// vector size
+ int winfac;//window factor
+ int overlap;//overlap factor
+ float sample_len;//duration of texture sample
+ float sync;
+ int megs;
+} t_reanimator;
+
+void *reanimator_new(t_symbol *msg, short argc, t_atom *argv);
+// t_int *offset_perform(t_int *w);
+t_int *reanimator_perform(t_int *w);
+void reanimator_dsp(t_reanimator *x, t_signal **sp, short *count);
+void reanimator_assist(t_reanimator *x, void *b, long m, long a, char *s);
+void reanimator_analyze (t_reanimator *x);
+void reanimator_float(t_reanimator *x, double f) ;
+void reanimator_mute(t_reanimator *x, t_floatarg flag);
+void reanimator_inverse(t_reanimator *x, t_floatarg toggle);
+void reanimator_topbin(t_reanimator *x, t_floatarg bin);
+void reanimator_startframe(t_reanimator *x, t_floatarg start);
+void reanimator_endframe(t_reanimator *x, t_floatarg end);
+void reanimator_framerange(t_reanimator *x, t_floatarg start, t_floatarg end);
+void reanimator_inverse(t_reanimator *x, t_floatarg toggle);
+void reanimator_size(t_reanimator *x, t_floatarg size_ms);
+void reanimator_freeze_and_march(t_reanimator *x, t_floatarg f);
+void reanimator_resume( t_reanimator *x );
+void reanimator_threshold(t_reanimator *x, t_floatarg threshold);
+void reanimator_dsp_free( t_reanimator *x );
+void reanimator_framecount ( t_reanimator *x );
+void reanimator_init(t_reanimator *x, short initialized);
+void reanimator_fftinfo(t_reanimator *x);
+void reanimator_overlap(t_reanimator *x, t_floatarg f);
+void reanimator_winfac(t_reanimator *x, t_floatarg f);
+void reanimator_meminfo(t_reanimator *x);
+
+#if MSP
+void main(void)
+{
+ setup((t_messlist **)&reanimator_class, (method)reanimator_new,
+ (method)reanimator_dsp_free, (short)sizeof(t_reanimator), 0L, A_GIMME,0);
+ addmess((method)reanimator_dsp, "dsp", A_CANT, 0);
+ addmess((method)reanimator_assist,"assist",A_CANT,0);
+ addfloat((method)reanimator_float);
+ addmess ((method)reanimator_mute, "mute", A_FLOAT, 0);
+ addmess ((method)reanimator_inverse, "inverse", A_FLOAT, 0);
+ addmess ((method)reanimator_topbin, "topbin", A_FLOAT, 0);
+ addmess ((method)reanimator_threshold, "threshold", A_FLOAT, 0);
+ addmess ((method)reanimator_analyze, "analyze", 0);
+ addmess ((method)reanimator_framecount, "framecount", 0);
+ addmess ((method)reanimator_freeze_and_march, "freeze_and_march", A_FLOAT, 0);
+ addmess ((method)reanimator_resume, "resume", 0);
+ addmess((method)reanimator_overlap,"overlap",A_DEFFLOAT,0);
+ addmess((method)reanimator_winfac,"winfac",A_DEFFLOAT,0);
+ addmess((method)reanimator_fftinfo,"fftinfo",0);
+ addmess((method)reanimator_meminfo,"meminfo",0);
+ dsp_initclass();
+ post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
+}
+#endif
+#if PD
+/* Pd Initialization */
+void reanimator_tilde_setup(void)
+{
+ reanimator_class = class_new(gensym("reanimator~"), (t_newmethod)reanimator_new,
+ (t_method)reanimator_dsp_free ,sizeof(t_reanimator), 0,A_GIMME,0);
+ CLASS_MAINSIGNALIN(reanimator_class, t_reanimator, x_f);
+ class_addmethod(reanimator_class, (t_method)reanimator_dsp, gensym("dsp"), 0);
+ class_addmethod(reanimator_class, (t_method)reanimator_mute, gensym("mute"), A_FLOAT,0);
+ class_addmethod(reanimator_class, (t_method)reanimator_inverse, gensym("inverse"), A_FLOAT,0);
+ class_addmethod(reanimator_class, (t_method)reanimator_topbin, gensym("topbin"), A_FLOAT,0);
+ class_addmethod(reanimator_class, (t_method)reanimator_threshold, gensym("threshold"), A_FLOAT,0);
+
+ class_addmethod(reanimator_class, (t_method)reanimator_freeze_and_march, gensym("freeze_and_march"), A_FLOAT, 0);
+ class_addmethod(reanimator_class, (t_method)reanimator_analyze, gensym("analyze"), 0);
+ class_addmethod(reanimator_class, (t_method)reanimator_framecount, gensym("framecount"), 0);
+ class_addmethod(reanimator_class, (t_method)reanimator_overlap, gensym("overlap"), A_FLOAT, 0);
+ class_addmethod(reanimator_class, (t_method)reanimator_winfac, gensym("winfac"), A_FLOAT, 0);
+ class_addmethod(reanimator_class, (t_method)reanimator_fftinfo, gensym("fftinfo"), 0);
+ class_addmethod(reanimator_class, (t_method)reanimator_meminfo, gensym("meminfo"), 0);
+ post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
+}
+#endif
+
+void reanimator_overlap(t_reanimator *x, t_floatarg f)
+{
+ int i = (int) f;
+ if(!power_of_two(i)){
+ error("%f is not a power of two",f);
+ return;
+ }
+ x->overlap = i;
+ reanimator_init(x,1);
+}
+
+void reanimator_winfac(t_reanimator *x, t_floatarg f)
+{
+ int i = (int)f;
+
+ if(!power_of_two(i)){
+ error("%f is not a power of two",f);
+ return;
+ }
+ x->winfac = i;
+ reanimator_init(x,2);
+}
+
+void reanimator_meminfo(t_reanimator *x)
+{
+ post("%s currently stores %d FFT Frames, duration: %f sec., size: %.2f MB",
+ OBJECT_NAME, x->framecount, x->tadv * x->framecount, (float)x->megs/1000000.0);
+}
+
+void reanimator_fftinfo(t_reanimator *x)
+{
+ if( ! x->overlap ){
+ post("zero overlap!");
+ return;
+ }
+ post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw);
+}
+
+void reanimator_framecount ( t_reanimator *x )
+{
+ post("%d frames stored", x->total_frames);
+}
+
+void reanimator_freeze_and_march(t_reanimator *x, t_floatarg f)
+{
+ x->frame_increment = f;
+ x->residency_mode = 1;
+}
+
+void reanimator_resume( t_reanimator *x )
+{
+ x->residency_mode = 0;
+}
+
+void reanimator_dsp_free( t_reanimator *x ){
+ int i ;
+#if MSP
+ dsp_free( (t_pxobject *) x);
+#endif
+ for( i = 0; i < x->framecount; i++ ){
+ freebytes(x->framebank[i],0) ;
+ }
+
+ freebytes(x->c_lastphase_in,0);
+ freebytes(x->c_lastphase_out,0);
+ freebytes(x->trigland,0);
+ freebytes(x->bitshuffle,0);
+ freebytes(x->Wanal,0);
+ freebytes(x->Wsyn,0);
+ freebytes(x->input,0);
+ freebytes(x->Hwin,0);
+ freebytes(x->buffer,0);
+ freebytes(x->channel,0);
+ freebytes(x->normalized_frame,0);
+ freebytes(x->output,0);
+}
+
+
+void reanimator_assist (t_reanimator *x, void *b, long msg, long arg, char *dst)
+{
+ if (msg==1) {
+ switch (arg) {
+ case 0:
+ sprintf(dst,"(signal) Driver Sound ");
+ break;
+ case 1:
+ sprintf(dst,"(signal) Texture Sound");
+ break;
+
+ }
+ } else if (msg==2) {
+ switch (arg) {
+ case 0:
+ sprintf(dst,"(signal) Output");
+ break;
+ case 1:
+ sprintf(dst,"(signal) Matched Frame");
+ break;
+ case 2:
+ sprintf(dst,"(signal) Sync");
+ break;
+
+ }
+ }
+}
+
+
+void *reanimator_new(t_symbol *msg, short argc, t_atom *argv)
+{
+#if MSP
+ t_reanimator *x = (t_reanimator *)newobject(reanimator_class);
+ dsp_setup((t_pxobject *)x,2);
+ outlet_new((t_pxobject *)x, "signal");
+ outlet_new((t_pxobject *)x, "signal");
+ outlet_new((t_pxobject *)x, "signal");
+#endif
+#if PD
+ int i;
+ t_reanimator *x = (t_reanimator *)pd_new(reanimator_class);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
+ for(i=0;i<3;i++)
+ outlet_new(&x->x_obj, gensym("signal"));
+#endif
+
+ x->vs = sys_getblksize();
+ x->R = sys_getsr();
+
+ x->sample_len = atom_getfloatarg(0,argc,argv) * .001;// convert to seconds
+ x->overlap = atom_getintarg(1,argc,argv);
+ x->winfac = atom_getintarg(2,argc,argv);
+
+ if(!x->overlap)
+ x->overlap = 4;
+ if(!x->winfac)
+ x->winfac = 1;
+ if(x->sample_len <= .05){
+ x->sample_len = 1.0;
+ post("%s: sample length set to default 1000 ms.",OBJECT_NAME);
+ }
+
+ reanimator_init(x,0);
+ return (x);
+}
+
+void reanimator_init(t_reanimator *x, short initialized)
+{
+ int i;
+ x->D = x->vs;
+ x->N = x->D * x->overlap;
+ x->Nw = x->N * x->winfac;
+ limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
+ x->tadv = (float)x->D/(float)x->R;
+ x->mult = 1. / (float) x->N;
+ x->N2 = (x->N)>>1;
+ x->Nw2 = (x->Nw)>>1;
+ x->inCount = -(x->Nw);
+ x->current_frame = x->framecount = 0;
+ x->fpos = x->last_fpos = 0;
+ x->framecount = 0;
+ x->total_frames = x->sample_len / x->tadv;
+
+ if(!initialized){
+ x->sync = 0.0;
+ x->inverse = 0;
+ x->initialized = 0;
+ x->threshold = .0001;
+ x->top_comparator_bin = 10 ;
+ x->residency_mode = 0;
+ x->frame_increment = 1.0 ;
+ x->mute = 0;
+ x->read_me = 0;
+ x->framecount = 0;
+ x->Wanal = (float *) getbytes( (MAX_Nw) * sizeof(float));
+ x->Wsyn = (float *) getbytes( (MAX_Nw) * sizeof(float));
+ x->Hwin = (float *) getbytes( (MAX_Nw) * sizeof(float));
+ x->input = (float *) getbytes( MAX_Nw * sizeof(float) );
+ x->output = (float *) getbytes( MAX_Nw * sizeof(float) );
+ x->buffer = (float *) getbytes( MAX_N * sizeof(float) );
+ x->channel = (float *) getbytes( (MAX_N+2) * sizeof(float) );
+ x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) );
+ x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) );
+ x->c_lastphase_in = (float *) getbytes( (MAX_N2+1) * sizeof(float) );
+ x->c_lastphase_out = (float *) getbytes( (MAX_N2+1) * sizeof(float) );
+
+ x->total_frames = x->sample_len / x->tadv;
+ x->normalized_frame = (float *) getbytes( (MAX_N+2) * sizeof(float));
+ x->framebank = (float **) getbytes(x->total_frames * sizeof(float *));
+ /* taking a risk here */
+ while(x->framecount < x->total_frames ){
+ x->framebank[(x->framecount)] = (float *) getbytes((x->N+2) * sizeof(float));
+ memset((char *)x->framebank[(x->framecount)],0,(x->N+2) * sizeof(float));
+ ++(x->framecount);
+ }
+
+ } else {
+ while(x->framecount < x->total_frames ){
+ x->framebank[x->framecount] =
+ (float *) resizebytes((char *)x->framebank[x->framecount],0,(x->N+2) * sizeof(float));
+ memset((char *)x->framebank[(x->framecount)],0,(x->N+2) * sizeof(float));
+ ++(x->framecount);
+ }
+ }
+ memset((char *)x->input,0,x->Nw * sizeof(float));
+ memset((char *)x->output,0,x->Nw * sizeof(float));
+ memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float));
+ memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float));
+
+
+ x->c_fundamental = (float) x->R/( (x->N2)<<1 );
+ x->c_factor_in = (float) x->R/((float)x->D * TWOPI);
+ x->c_factor_out =TWOPI * (float) x->D / (float) x->R;
+ init_rdft(x->N, x->bitshuffle, x->trigland);
+ makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D);
+
+ x->megs = sizeof(float) * x->framecount * (x->N+2);
+}
+
+t_int *reanimator_perform(t_int *w)
+{
+ float sample, outsamp ;
+ float ampsum, new_ampsum, rescale;
+ float min_difsum, difsum;
+ int
+ i,j, match_frame=0;
+
+
+ //////////////////////////////////////////////
+ t_reanimator *x = (t_reanimator *) (w[1]);
+ t_float *driver = (t_float *)(w[2]);
+ t_float *texture = (t_float *)(w[3]);
+ t_float *soundout = (t_float *)(w[4]);
+ t_float *matchout = (t_float *)(w[5]);
+ t_float *sync_vec = (t_float *)(w[6]);
+ int n = (int)(w[7]);
+
+ /* dereference structure */
+
+ int inCount = x->inCount;
+ int R = x->R;
+ int N = x->N;
+ int N2 = x->N2;
+ int D = x->D;
+ int Nw = x->Nw;
+ float *Wanal = x->Wanal;
+ float *Wsyn = x->Wsyn;
+ float *input = x->input;
+ float *output = x->output;
+ float *buffer = x->buffer;
+ float *channel = x->channel;
+ float *normalized_frame = x->normalized_frame;
+ int framecount = x->framecount;
+ int total_frames = x->total_frames;
+
+ float threshold = x->threshold;
+ int top_comparator_bin = x->top_comparator_bin ;
+
+ float mult = x->mult ;
+ int *bitshuffle = x->bitshuffle;
+ float *trigland = x->trigland ;
+
+ float *c_lastphase_in = x->c_lastphase_in;
+ float *c_lastphase_out = x->c_lastphase_out;
+ float c_fundamental = x->c_fundamental;
+ float c_factor_in = x->c_factor_in;
+ float c_factor_out = x->c_factor_out;
+ float **framebank = x->framebank;
+ // for residency mode
+ float fframe = x->current_frame ;
+ float last_fpos = x->last_fpos ;
+ float fincr = x->frame_increment;
+ float fpos = x->fpos ;
+ float sync = x->sync;
+ /***********************************/
+ inCount += D;
+
+ /* SAMPLE MODE */
+ if( x->read_me ) {
+ for ( j = 0 ; j < Nw - D ; j++ ){
+ input[j] = input[j+D];
+ }
+ for ( j = Nw - D; j < Nw; j++ ) {
+ input[j] = *texture++;
+ }
+
+ fold( input, Wanal, Nw, buffer, N, inCount );
+ rdft( N, 1, buffer, bitshuffle, trigland );
+
+ sync = (float) framecount / (float) total_frames;
+ for ( j = 0; j < n; j++ ){
+ *sync_vec++ = sync;
+ *matchout++ = 0.0;
+ *soundout++ = 0.0;
+ }
+ convert( buffer, framebank[framecount], N2, c_lastphase_in, c_fundamental, c_factor_in );
+
+ new_ampsum = ampsum = 0;
+ for( j = 0; j < N; j+= 2 ){
+ ampsum += framebank[framecount][j];
+ }
+
+ if( ampsum > .00000001 ){
+ rescale = 1.0 / ampsum ;
+ for( i = 0; i < N; i+= 2 ){
+ framebank[framecount][i] *= rescale;
+ }
+
+ ++framecount;
+
+ } else {
+ post("amplitude for frame %d is too low\n", framecount);
+ }
+
+ // output empty buffers while reading
+
+
+ if( framecount >= total_frames ){
+ sync = 1.0;
+ x->read_me = 0;
+ // post("reanimator~: data acquisition completed");
+ x->initialized = 1;
+ // clear input buffer
+ for( i = 0; i < Nw; i++ )
+ input[i] = 0.0;
+ }
+
+ } else if (x->mute || ! x->initialized) {
+ for ( j = 0; j < D; j++ ){
+ *soundout++ = 0.0;
+ *matchout++ = 0.0;
+ *sync_vec++ = sync;
+ }
+ }
+ /* RESIDENCY RESYNTHESIS */
+ else if( x->residency_mode ) {
+ if( fpos < 0 )
+ fpos = 0;
+ if( fpos > 1 )
+ fpos = 1;
+ if( fpos != last_fpos ){
+ fframe = fpos * (float) framecount ;
+ last_fpos = fpos;
+ }
+
+
+ fframe += fincr;
+ while( fframe >= framecount ) {
+ fframe -= framecount;
+ }
+ while( fframe < 0. ) {
+ fframe += framecount ;
+ }
+
+ unconvert(framebank[(int) fframe ], buffer, N2, c_lastphase_out, c_fundamental, c_factor_out );
+
+ rdft( N, -1, buffer, bitshuffle, trigland );
+ overlapadd( buffer, N, Wsyn, output, Nw, inCount );
+
+ for ( j = 0; j < D; j++ ){
+ *soundout++ = output[j] * mult;
+ *matchout++ = (int) fframe;
+ *sync_vec++ = sync;
+ }
+ for ( j = 0; j < Nw - D; j++ ){
+ output[j] = output[j+D];
+ }
+
+ for ( j = Nw - D; j < Nw; j++ ){
+ output[j] = 0.;
+ }
+ x->current_frame = fframe;
+ x->frame_increment = fincr;
+ x->fpos = fpos;
+ x->sync = sync;
+ }
+ /* REANIMATION HERE */
+ else {
+ for ( j = 0 ; j < Nw - D ; j++ ){
+ input[j] = input[j+D];
+ }
+ for ( j = Nw - D; j < Nw; j++ ) {
+ input[j] = *driver++;
+ }
+
+ fold( input, Wanal, Nw, buffer, N, inCount );
+ rdft( N, 1, buffer, bitshuffle, trigland );
+ convert( buffer, channel, N2, c_lastphase_in, c_fundamental, c_factor_in );
+ ampsum = 0;
+ // NORMALIZE INPUT FRAME
+ for( i = 0; i < N+2; i += 2 ){
+ ampsum += channel[i];
+ }
+
+ if( ampsum > threshold ){
+ rescale = 1.0 / ampsum;
+ for( i = 0; i < N; i += 2 ){
+ channel[i] *= rescale;
+ }
+ } else {
+ // AMPLITUDE OF INPUT WAS TOO LOW - OUTPUT SILENCE AND RETURN
+ for ( j = 0; j < D; j++ ){
+ *soundout++ = 0.0;
+ *matchout++ = 0.0;
+ *sync_vec++ = sync;
+
+ }
+ x->inCount = inCount;
+ x->sync = sync;
+ return (w+8);
+
+ }
+ // NOW COMPARE TO STORED FRAMES
+ if( x->inverse ){ // INVERSE CASE
+ min_difsum = 0.0 ;
+
+ for( j = 0; j < framecount; j++ ){
+ difsum = 0;
+ for( i = 0; i < top_comparator_bin * 2; i += 2 ){
+ difsum += fabs( channel[i] - framebank[j][i] );
+ }
+ // fprintf(stderr,"bin 20: in %f compare %f\n", channel[40], frames[j][40]);
+ if( difsum > min_difsum ){
+ match_frame = j;
+ min_difsum = difsum;
+ }
+ }
+ } else { // NORMAL CASE
+ min_difsum = 1000000.0 ;
+
+ for( j = 0; j < framecount; j++ ){
+ difsum = 0;
+ for( i = 0; i < top_comparator_bin * 2; i += 2 ){
+ difsum += fabs( channel[i] - framebank[j][i] );
+ }
+ // fprintf(stderr,"bin 20: in %f compare %f\n", channel[40], frames[j][40]);
+ if( difsum < min_difsum ){
+ match_frame = j;
+ min_difsum = difsum;
+ }
+ }
+ }
+
+ unconvert( framebank[match_frame], buffer, N2, c_lastphase_out, c_fundamental, c_factor_out );
+
+ rdft( N, -1, buffer, bitshuffle, trigland );
+ overlapadd( buffer, N, Wsyn, output, Nw, inCount );
+
+ // scale back to match
+ for ( j = 0; j < D; j++ ){
+ *soundout++ = output[j] * (mult / rescale);
+ *matchout++ = (float) match_frame;
+ *sync_vec++ = sync;
+ }
+ for ( j = 0; j < Nw - D; j++ ){
+ output[j] = output[j+D];
+ }
+
+ for ( j = Nw - D; j < Nw; j++ ){
+ output[j] = 0.;
+ }
+ x->current_frame = match_frame; // for residency
+ x->sync = sync;
+ }
+
+ /* restore state variables */
+ x->framecount = framecount;
+ x->inCount = inCount % Nw;
+ x->sync = sync;
+
+ return (w+8);
+}
+
+#if MSP
+void reanimator_float(t_reanimator *x, double f) // Look at floats at inlets
+{
+ int inlet = x->x_obj.z_in;
+
+ if (inlet == 1)
+ {
+ x->frame_increment = f;
+ }
+ else if (inlet == 2)
+ {
+ if (f < 0 ){
+ f = 0;
+ } else if(f > 1) {
+ f = 1.;
+ }
+ x->fpos = f;
+
+ }
+}
+#endif
+
+void reanimator_analyze ( t_reanimator *x )
+{
+ // int i, j;
+
+ x->read_me = 1;
+ x->framecount = 0;
+ // post("reanimator: beginning spectral data acquisition");
+ return;
+
+}
+
+void reanimator_mute(t_reanimator *x, t_floatarg flag)
+{
+ x->mute = flag;
+ // post ("mute set to %d", flag);
+}
+
+void reanimator_topbin(t_reanimator *x, t_floatarg bin)
+{
+ if( bin > 1 && bin < x->N2 )
+ x->top_comparator_bin = bin;
+}
+
+
+void reanimator_inverse(t_reanimator *x, t_floatarg toggle)
+{
+ x->inverse = toggle;
+ // post ("inverse set to %d", toggle);
+}
+
+void reanimator_threshold(t_reanimator *x, t_floatarg threshold)
+{
+ if( threshold > THRESHOLD_MIN )
+ x->threshold = threshold;
+ else
+ x->threshold = THRESHOLD_MIN;
+}
+
+void reanimator_dsp(t_reanimator *x, t_signal **sp, short *count)
+{
+ // long i;
+
+ if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){
+ x->vs = sp[0]->s_n;
+ x->R = sp[0]->s_sr;
+ reanimator_init(x,1);
+ }
+ dsp_add(reanimator_perform, 7, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec,
+ sp[3]->s_vec, sp[4]->s_vec, sp[0]->s_n);
+}
+
+