[PD-cvs] externals/fftease README, NONE, 1.1 bthresher~.c, NONE, 1.1 burrow~.c, NONE, 1.1 cavoc27~.c, NONE, 1.1 cavoc~.c, NONE, 1.1 centerring~.c, NONE, 1.1 codepend~.c, NONE, 1.1 crossx~.c, NONE, 1.1 dentist~.c, NONE, 1.1 disarrain~.c, NONE, 1.1 disarray~.c, NONE, 1.1 drown~.c, NONE, 1.1 ether~.c, NONE, 1.1 leaker~.c, NONE, 1.1 mindwarp~.c, NONE, 1.1 morphine~.c, NONE, 1.1 multyq~.c, NONE, 1.1 presidency~.c, NONE, 1.1 pvcompand~.c, NONE, 1.1 pvgrain~.c, NONE, 1.1 pvharm~.c, NONE, 1.1 pvoc~.c, NONE, 1.1 pvtuner~.c, NONE, 1.1 pvwarp~.c, NONE, 1.1 reanimator~.c, NONE, 1.1 resent~.c, NONE, 1.1 residency_buffer~.c, NONE, 1.1 residency~.c, NONE, 1.1 scrape~.c, NONE, 1.1 shapee~.c, NONE, 1.1 swinger~.c, NONE, 1.1 taint~.c, NONE, 1.1 thresher~.c, NONE, 1.1 vacancy~.c, NONE, 1.1 xsyn~.c, NONE, 1.1

Hans-Christoph Steiner eighthave at users.sourceforge.net
Thu Feb 9 17:18:41 CET 2006


Update of /cvsroot/pure-data/externals/fftease
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13719

Added Files:
	README bthresher~.c burrow~.c cavoc27~.c cavoc~.c 
	centerring~.c codepend~.c crossx~.c dentist~.c disarrain~.c 
	disarray~.c drown~.c ether~.c leaker~.c mindwarp~.c 
	morphine~.c multyq~.c presidency~.c pvcompand~.c pvgrain~.c 
	pvharm~.c pvoc~.c pvtuner~.c pvwarp~.c reanimator~.c resent~.c 
	residency_buffer~.c residency~.c scrape~.c shapee~.c 
	swinger~.c taint~.c thresher~.c vacancy~.c xsyn~.c 
Log Message:
got everything building and working, including building single-object/single-file objects with a shared dylib.  Now got to get it integrated into the build system

--- NEW FILE: cavoc27~.c ---
#include "MSPd.h"

#include "fftease.h"

#if MSP
void *cavoc27_class;
#endif 

#if PD
static t_class *cavoc27_class;
#endif

#define OBJECT_NAME "cavoc27~"

/* NOTE THIS IS A MORE COMPLEX CA WITH 3 DIFFERENT STATES  */

typedef struct _cavoc27
{
#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 *ichannel; //for interpolation
  float *tmpchannel; // for spectrum capture
  float *output;
  float frame_duration;
  int max_bin;

  // for CAVOC2

  float fundamental;
  float *last_frame;
  short left;
  short right;
  short center;
  short *rule;
  float density;
  float start_breakpoint;
  int hold_frames;
  int frames_left;
  int set_count;
  short interpolate_flag;
  short capture_flag;
  short capture_lock;
  // FFT
  // for convert

  float *c_lastphase_in;
  float *c_lastphase_out;
  float c_fundamental;
  float c_factor_in;
  float c_factor_out;
  float mult; 
  float *trigland;
  int *bitshuffle;
  //
  void *list_outlet;
  t_atom *list_data;
  short mute;
  int winfac;//window factor
  int overlap;//overlap factor
  int vs;//vector size
  float hold_time;//hold time in seconds
} t_cavoc27;

void *cavoc27_new(t_symbol *s, int argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *cavoc27_perform(t_int *w);
void cavoc27_dsp(t_cavoc27 *x, t_signal **sp, short *count);
void cavoc27_assist(t_cavoc27 *x, void *b, long m, long a, char *s);
void cavoc27_free( t_cavoc27 *x);
int cavoc27_apply_rule( short left, short right, short center, short *rule);
float cavoc27_randf(float min, float max);
void cavoc27_rule (t_cavoc27 *x, t_symbol *msg, short argc, t_atom *argv);
void cavoc27_density (t_cavoc27 *x, t_floatarg density);
void cavoc27_hold_time (t_cavoc27 *x, t_floatarg hold_time);
void cavoc27_interpolate (t_cavoc27 *x, t_floatarg interpolate);
void cavoc27_capture_spectrum (t_cavoc27 *x, t_floatarg flag );
void cavoc27_capture_lock (t_cavoc27 *x, t_floatarg toggle );
void cavoc27_retune (t_cavoc27 *x, t_floatarg min, t_floatarg max);
void cavoc27_mute (t_cavoc27 *x, t_floatarg toggle);
void cavoc27_init(t_cavoc27 *x,short initialized);
void cavoc27_rand_set_spectrum(t_cavoc27 *x);
void cavoc27_rand_set_rule(t_cavoc27 *x);
void cavoc27_fftinfo(t_cavoc27 *x);
void cavoc27_overlap(t_cavoc27 *x, t_floatarg f);
void cavoc27_winfac(t_cavoc27 *x, t_floatarg f);

#if MSP
void main(void)
{
  setup((t_messlist **)&cavoc27_class, (method)cavoc27_new, (method)cavoc27_free, 
  (short)sizeof(t_cavoc27), 0, A_GIMME, 0);
  addmess((method)cavoc27_dsp, "dsp", A_CANT, 0);
  addmess((method)cavoc27_assist,"assist",A_CANT,0);
  addmess((method)cavoc27_rule,"rule",A_GIMME,0);
  addmess((method)cavoc27_density,"density",A_FLOAT,0);
  addmess((method)cavoc27_hold_time,"hold_time",A_FLOAT,0);
  addmess((method)cavoc27_interpolate,"interpolate",A_FLOAT,0);
  addmess((method)cavoc27_overlap,"overlap",A_FLOAT,0);
  addmess((method)cavoc27_winfac,"winfac",A_FLOAT,0);
  addmess((method)cavoc27_fftinfo,"fftinfo",0);
  addmess((method)cavoc27_retune,"retune",A_FLOAT,A_FLOAT,0);
  addmess((method)cavoc27_capture_spectrum,"capture_spectrum",A_FLOAT,0);
  addmess((method)cavoc27_mute,"mute",A_FLOAT,0);
  dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif
#if PD
/* Pd Initialization */
void cavoc27_tilde_setup(void)
{
  cavoc27_class = class_new(gensym("cavoc27~"), (t_newmethod)cavoc27_new, 
			 (t_method)cavoc27_free ,sizeof(t_cavoc27), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(cavoc27_class, t_cavoc27, x_f);
  class_addmethod(cavoc27_class, (t_method)cavoc27_dsp, gensym("dsp"), 0);
  class_addmethod(cavoc27_class, (t_method)cavoc27_mute, gensym("mute"), A_FLOAT,0);
  class_addmethod(cavoc27_class, (t_method)cavoc27_rule, gensym("rule"), A_GIMME,0);
  class_addmethod(cavoc27_class, (t_method)cavoc27_density, gensym("density"), A_DEFFLOAT,0);
  class_addmethod(cavoc27_class, (t_method)cavoc27_hold_time, gensym("hold_time"), A_DEFFLOAT,0);
  class_addmethod(cavoc27_class, (t_method)cavoc27_interpolate, gensym("interpolate"), A_DEFFLOAT, 0);
  class_addmethod(cavoc27_class, (t_method)cavoc27_capture_spectrum, gensym("capture_spectrum"), A_FLOAT, 0);
  class_addmethod(cavoc27_class, (t_method)cavoc27_retune, gensym("retune"), A_DEFFLOAT,A_DEFFLOAT,0);
  class_addmethod(cavoc27_class, (t_method)cavoc27_overlap, gensym("overlap"), A_FLOAT, 0);
  class_addmethod(cavoc27_class, (t_method)cavoc27_winfac, gensym("winfac"), A_FLOAT, 0);
  class_addmethod(cavoc27_class, (t_method)cavoc27_fftinfo, gensym("fftinfo"), 0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void cavoc27_rand_set_rule(t_cavoc27 *x)
{
int i;
float rval;
  for( i = 0; i < 27; i++ ){
    rval = cavoc27_randf(0.0,1.0);
    if( rval < .333 )
      x->rule[i] = 0;
    else if(rval < .666 )
      x->rule[i] = 1;
    else x->rule[i] = 2;
  }
}

void cavoc27_retune(t_cavoc27 *x, t_floatarg min, t_floatarg max)
{
  int i;

  if( max <= 0 || min <= 0 || min > max ){
    error("bad values for min and max multipliers");
    return;
  }
  if( min < .1 )
    min = 0.1;
  if( max > 2.0 )
    max = 2.0;
  for( i = 0; i < x->N2 + 1; i++ ){
    x->channel[ i * 2 + 1 ] = x->c_fundamental * (float) (i / 2) * cavoc27_randf(min, max);
  }

}

void cavoc27_density(t_cavoc27 *x, t_floatarg density)
{
  int i;
  if( density < 0.0001 ){
    density = .0001;
  } else if( density > .9999 ){
    density = 1.0;
  }
  x->density = density;
  x->start_breakpoint = 1.0 - x->density;
  for( i = 0; i < x->N2 + 1; i++ ){
    if( cavoc27_randf(0.0, 1.0) > x->start_breakpoint ){
      if( cavoc27_randf(0.0,1.0) > 0.5 ){
	x->channel[ i * 2 ] = 1;
      }
      else {
	x->channel[ i * 2 ] = 2;
      }
      ++(x->set_count);
    } else {
      x->channel[ i * 2 ] = 0;
    }
  }
  for( i = 0; i < x->N+2; i++ ){
    x->last_frame[i] = x->channel[i];
  }
}

void cavoc27_mute (t_cavoc27 *x, t_floatarg toggle)
{
	x->mute = (short)toggle;
}

void cavoc27_hold_time(t_cavoc27 *x, t_floatarg hold_time)
{

  if(hold_time <= 0){
  	post("illegal hold time %f",hold_time);
  	return;
  }
  x->hold_time = hold_time;
  if(! x->frame_duration){
	error("%s: zero frame duration",OBJECT_NAME);
	x->frame_duration = .15;
  }
  x->hold_frames = (int) ( (hold_time/1000.0) / x->frame_duration);
  if( x->hold_frames < 1 )
    x->hold_frames = 1;
  //  x->frames_left = x->hold_frames;

}

void cavoc27_interpolate(t_cavoc27 *x, t_floatarg flag)
{
  x->interpolate_flag = (short) flag;
}

void cavoc27_capture_spectrum(t_cavoc27 *x, t_floatarg flag )
{
// now identical to capture_lock
  x->capture_lock = (short)flag; 
}

void cavoc27_capture_lock(t_cavoc27 *x, t_floatarg flag )
{
  x->capture_lock = (short)flag; 
}

void cavoc27_rule (t_cavoc27 *x, t_symbol *msg, short argc, t_atom *argv)
{
  int i;
  short *rule = x->rule;
  if( argc != 27 ){
    error("the rule must be size 18");
    return;
  }
  
  for( i = 0; i < 27; i++ ){
    rule[i] = (short) atom_getfloatarg( i, argc, argv);
  }
}

void cavoc27_free( t_cavoc27 *x ){
#if MSP
  dsp_free( (t_pxobject *) x);
#endif
  free(x->trigland);
  free(x->bitshuffle);
  free(x->Wanal);
  free(x->Wsyn);
  free(x->input);
  free(x->Hwin);
  free(x->buffer);
  free(x->channel);
  free(x->ichannel);
  free(x->tmpchannel);
  free(x->last_frame);
  free(x->output);
  free(x->c_lastphase_out);
  free(x->rule);  
}

void cavoc27_assist (t_cavoc27 *x, void *b, long msg, long arg, char *dst)
{
  if (msg==1) {
    switch (arg) {
    case 0:
      sprintf(dst,"unused(signal)");
      break;
    }
  } else if (msg==2) {
    switch (arg) {
    case 0:
      sprintf(dst,"output(signal)"); break;
    }
  }
}

void *cavoc27_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
  t_cavoc27 *x = (t_cavoc27 *)newobject(cavoc27_class);
  dsp_setup((t_pxobject *)x,1);
  outlet_new((t_pxobject *)x, "signal");
#endif
#if PD
  int i;
  t_cavoc27 *x = (t_cavoc27 *)pd_new(cavoc27_class);
  outlet_new(&x->x_obj, gensym("signal"));
#endif

  x->overlap = 0;
  x->winfac=0;
  x->hold_time=0;
  x->density = 0;
  
  x->density = atom_getfloatarg(0,argc,argv);
  x->hold_time = atom_getfloatarg(1,argc,argv) * .001;// convert to seconds
  x->overlap = atom_getfloatarg(2,argc,argv);
  x->winfac = atom_getfloatarg(3,argc,argv);

  if(x->density <= 0)
  	x->density = .0001;
  if(x->density >= 1)
  	x->density = .9999;
  x->start_breakpoint = 1.0 - x->density;
  if(!x->hold_time)
  	x->hold_time = 0.15;
    	
  x->vs = sys_getblksize();
  x->R = sys_getsr();

  cavoc27_init(x,0);
  return (x);
}

void cavoc27_overlap(t_cavoc27 *x, t_floatarg f)
{
int i = (int) f;
  if(!power_of_two(i)){
    post("%f is not a power of two",f);
    return;
  }
	x->overlap = i;
	cavoc27_init(x,1);
}

void cavoc27_winfac(t_cavoc27 *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;
	cavoc27_init(x,2);
}

void cavoc27_fftinfo(t_cavoc27 *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 cavoc27_init(t_cavoc27 *x,short initialized)
{
int i;

  if(!power_of_two(x->overlap))
    x->overlap = 4;
  if(!power_of_two(x->winfac))
    x->winfac = 1;
//post("init with o %d and wf %d",x->overlap,x->winfac);
  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->N2 = (x->N)>>1;
  x->Nw2 = (x->Nw)>>1;
  x->inCount = -(x->Nw);  
  x->mult = 1. / (float) x->N;
  x->c_fundamental =  (float) x->R/( (x->N2)<<1 );
  x->c_factor_out = TWOPI * (float)  x->D / (float) x->R;
  x->c_factor_in =  (float) x->R/((float)x->D * TWOPI);
  x->frame_duration = (float)x->D/(float) x->R;
  x->hold_frames = (int) (x->hold_time/x->frame_duration);
  x->frames_left = x->hold_frames;
//  x->frames_left = 0;
  x->set_count = 0;

	if(!initialized){
	  srand(time(0));
	  x->interpolate_flag = 0;
	  x->capture_lock = 0;
	  
	  x->mute = 0;
	  x->Wanal = (float *) calloc(MAX_Nw, sizeof(float));	
	  x->Wsyn = (float *) calloc(MAX_Nw, sizeof(float));	
	  x->input = (float *) calloc(MAX_Nw, sizeof(float));	
	  x->Hwin = (float *) calloc(MAX_Nw, sizeof(float));
	  x->buffer = (float *) calloc(MAX_N, sizeof(float));
	  x->channel = (float *) calloc(MAX_N+2, sizeof(float));
	  x->ichannel = (float *) calloc(MAX_N+2, sizeof(float));
	  x->tmpchannel = (float *) calloc(MAX_N+2, sizeof(float));
	  x->rule = (short *) calloc(27, sizeof(short));
	  x->last_frame = (float *) calloc(MAX_N+2, sizeof(float));
	  x->output = (float *) calloc(MAX_Nw, sizeof(float));
	  x->bitshuffle = (int *) calloc(MAX_N * 2, sizeof(int));
	  x->trigland = (float *) calloc(MAX_N * 2, sizeof(float));
	  x->c_lastphase_in = (float *) calloc(MAX_N2+1, sizeof(float));
	  x->c_lastphase_out = (float *) calloc(MAX_N2+1, sizeof(float));

  
	} 
		memset((char *)x->input,0,x->Nw * sizeof(float));
		memset((char *)x->output,0,x->Nw * sizeof(float));
		memset((char *)x->buffer,0,x->N * 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));


  cavoc27_rand_set_rule(x); 
  init_rdft( x->N, x->bitshuffle, x->trigland);
  makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
  cavoc27_rand_set_spectrum(x);
  for( i = 0; i < x->N+2; i++ ){
    x->last_frame[i] = x->channel[i];
  }
}

void cavoc27_rand_set_spectrum(t_cavoc27 *x)
{
int i;
float rval;

  //set spectrum
  for( i = 0; i < x->N2 + 1; i++ ){
    if( cavoc27_randf(0.0, 1.0) > x->start_breakpoint){
      rval = cavoc27_randf(0.0, 1.0);
      if( rval < 0.5 ){
				x->channel[ i * 2 ] = 1;
			}
      else {
        x->channel[ i * 2 ] = 2;
      }
      ++(x->set_count);
    } else {
      x->channel[ i * 2 ] = 0;
    }
    x->channel[ i * 2 + 1 ] = x->c_fundamental * (float) (i / 2) * cavoc27_randf(.9,1.1);
  }
}

t_int *cavoc27_perform(t_int *w)
{
  int	i,j;
  float m1,m2;
  ////////////
  t_cavoc27 *x = (t_cavoc27 *) (w[1]);
	
  float *in = (t_float *)(w[2]);
  float *out = (t_float *)(w[3]);
  t_int n = w[4];

  int frames_left = x->frames_left;
  float *input = x->input;
  float *buffer = x->buffer;
  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 *output = x->output;
  float *channel = x->channel;
  float *tmpchannel = x->tmpchannel;
  float *ichannel = x->ichannel;
  float mult = x->mult ;
  int *bitshuffle = x->bitshuffle;
  float *trigland = x->trigland ;
  int hold_frames = x->hold_frames;
  short *rule = x->rule;
  short left = x->left;
  short right = x->right;
  short center = x->center;
  float *last_frame = x->last_frame;
  float *c_lastphase_out = x->c_lastphase_out;
  float *c_lastphase_in = x->c_lastphase_in;
  float c_fundamental = x->c_fundamental;
  float c_factor_out = x->c_factor_out;
  float c_factor_in = x->c_factor_in;
  short interpolate_flag = x->interpolate_flag;


  if( x->mute ){
    while( n-- ){
      *out++ = 0.0;
    }
    return (w+5);
  }

  x->inCount += D;  
  
  if( x->capture_flag || x->capture_lock ) {


    for ( j = 0 ; j < (Nw - D) ; j++ ){
      input[j] = input[j+D];
    }
    for ( j = (Nw-D), i = 0 ; j < Nw; j++, i++ ) {
      input[j] = *in++;
    }

    fold( input, Wanal, Nw, buffer, N, x->inCount );   
    rdft( N, 1, buffer, bitshuffle, trigland );
    convert( buffer, tmpchannel, N2, c_lastphase_in, c_fundamental, c_factor_in );

    // ONLY COPY PHASES
    for( i = 1; i < N+2; i += 2 ){
      channel[i] = tmpchannel[i];
      // last_frame[i] = channel[i] = tmpchannel[i];
    }

    if( x->capture_flag ){
   		 --(x->capture_flag);
   	}
    // on final frame - swap in channel (just phases though )

    
  }
  if( --frames_left <= 0){
    /* save composite frame for next time  (only amps) */
/*    for( i = 0; i < N+1; i++ ){
      last_frame[i] = channel[i];
    }*/

    for( i = 0; i < N+1; i += 2 ){
      last_frame[i] = channel[i];
    }

    frames_left = hold_frames;
    for( i = 2; i < N; i+=2 ){
      left = last_frame[ i - 2 ];
      center = last_frame[i] ;
      right = last_frame[i+2];
      channel[i] = cavoc27_apply_rule(left, right, center, rule );
    }
    /* boundary cases */
    center = last_frame[0];
    right = last_frame[2];
    left = last_frame[N];
    channel[0] = cavoc27_apply_rule(left, right, center, rule );

    center = last_frame[N];
    right = last_frame[0];
    left = last_frame[N - 2];
    channel[N] = cavoc27_apply_rule(left, right, center, rule );
  }
  if( interpolate_flag ){
    m1 = (float) frames_left / (float) hold_frames ;
    m2 = 1.0 - m1;
    for( i = 0; i <N+2; i += 2 ){
      ichannel[i] = m1 * last_frame[i] + m2 * channel[i];
      ichannel[i+1] = channel[i+1];
    }

    unconvert( ichannel, buffer, N2, c_lastphase_out, c_fundamental, c_factor_out  );
  } else {
    unconvert( channel, 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++ )
    *out++ = output[j] * mult;

  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
			
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;	

  /* restore state variables */
  x->inCount = inCount;
  x->frames_left = frames_left;
  return (w+5);
}		

int cavoc27_apply_rule( short left, short right, short center, short *rule){

  if( left == 0 && center == 0 && right == 0 )
    return rule[0];
  if( left == 1 && center == 0 && right == 1 )
    return rule[1];
  if( left == 1 && center == 0 && right == 0 )
    return rule[2];
  if( left == 0 && center == 0 && right == 1 )
    return rule[3];
  if( left == 2 && center == 0 && right == 2 )
    return rule[4];
  if( left == 2 && center == 0 && right == 0 )
    return rule[5];
  if( left == 0 && center == 0 && right == 2 )
    return rule[6];
  if( left == 2 && center == 0 && right == 1 )
    return rule[7];
  if( left == 1 && center == 0 && right == 2 )
    return rule[8];

  if( left == 0 && center == 1 && right == 0 )
    return rule[9];
  if( left == 1 && center == 1 && right == 1 )
    return rule[10];
  if( left == 1 && center == 1 && right == 0 )
    return rule[11];
  if( left == 0 && center == 1 && right == 1 )
    return rule[12];
  if( left == 2 && center == 1 && right == 2 )
    return rule[13];
  if( left == 2 && center == 1 && right == 0 )
    return rule[14];
  if( left == 0 && center == 1 && right == 2 )
    return rule[15];
  if( left == 2 && center == 1 && right == 1 )
    return rule[16];
  if( left == 1 && center == 1 && right == 2 )
    return rule[17];

  if( left == 0 && center == 2 && right == 0 )
    return rule[18];
  if( left == 1 && center == 2 && right == 1 )
    return rule[19];
  if( left == 1 && center == 2 && right == 0 )
    return rule[20];
  if( left == 0 && center == 2 && right == 1 )
    return rule[21];
  if( left == 2 && center == 2 && right == 2 )
    return rule[22];
  if( left == 2 && center == 2 && right == 0 )
    return rule[23];
  if( left == 0 && center == 2 && right == 2 )
    return rule[24];
  if( left == 2 && center == 2 && right == 1 )
    return rule[25];
  if( left == 1 && center == 2 && right == 2 )
    return rule[26];
  return 0; //should never happen  
}

float cavoc27_randf(float min, float max)
{
	float randv, retval;
	
	randv = (float) (rand() % 32768) / 32768.0 ;
	return (retval = min + (max-min) * randv)  ;
}
void cavoc27_dsp(t_cavoc27 *x, t_signal **sp, short *count)
{
  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;
  	cavoc27_init(x,1);
  }
  dsp_add(cavoc27_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec,  sp[0]->s_n);
}


--- NEW FILE: multyq~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *multyq_class;
#endif 

#if PD
static t_class *multyq_class;
#endif

#define OBJECT_NAME "multyq~"

typedef struct _multyq
{
#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 mult; 
  float *trigland;
  int *bitshuffle;

  // for multyQ
  float cf1;
  float gainfac1;
  float bw1;
  float cf2;
  float gainfac2;
  float bw2;
  float cf3;
  float gainfac3;
  float bw3;
  float cf4;
  float gainfac4;
  float bw4;

  float *rcos;
  float *filt;
  float *freqs;
  int rcoslen;
  //
  short in2_connected;
  short in3_connected;
  short in4_connected;
  short in5_connected;
  short in6_connected;
  short in7_connected;
  short in8_connected;
  short in9_connected;
  short in10_connected;
  short in11_connected;
  short in12_connected;
  short in13_connected;
  short please_update;
  short always_update;
  short mute;
  short bypass;
  int overlap;
  int winfac;
} t_multyq;

void *multyq_new(t_symbol *s, int argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *multyq_perform(t_int *w);
void multyq_dsp(t_multyq *x, t_signal **sp, short *count);
void multyq_assist(t_multyq *x, void *b, long m, long a, char *s);
void multyq_bypass(t_multyq *x, t_floatarg state);
void multyq_mute(t_multyq *x, t_floatarg state);
void update_filter_function(t_multyq *x);
void multyq_float(t_multyq *x, double f);
void filtyQ( float *S, float *C, float *filtfunc, int N2 );
void multyq_init(t_multyq *x, short initialized);
void multyq_free(t_multyq *x);
void multyq_fftinfo(t_multyq *x);
void multyq_overlap(t_multyq *x, t_floatarg f);
void multyq_winfac(t_multyq *x, t_floatarg f);

#if MSP
void main(void)
{
  setup((t_messlist **)&multyq_class, (method)multyq_new, (method)multyq_free, 
  (short)sizeof(t_multyq), 0, A_GIMME, 0);
  addmess((method)multyq_dsp, "dsp", A_CANT, 0);
  addmess((method)multyq_assist,"assist",A_CANT,0);
  addmess((method)multyq_bypass,"bypass",A_DEFFLOAT,0);
  addmess((method)multyq_mute,"mute",A_DEFFLOAT,0);
  addmess((method)multyq_overlap,"overlap",A_DEFFLOAT,0);
  addmess((method)multyq_winfac,"winfac",A_DEFFLOAT,0);
  addmess((method)multyq_fftinfo,"fftinfo",0);
  addfloat((method)multyq_float);
  dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif 

#if PD
void multyq_tilde_setup(void)
{
  multyq_class = class_new(gensym("multyq~"), (t_newmethod)multyq_new, 
			 (t_method)multyq_free ,sizeof(t_multyq), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(multyq_class, t_multyq, x_f);
  class_addmethod(multyq_class,(t_method)multyq_dsp,gensym("dsp"),0);
  class_addmethod(multyq_class,(t_method)multyq_mute,gensym("mute"),A_FLOAT,0);
  class_addmethod(multyq_class,(t_method)multyq_bypass,gensym("bypass"),A_FLOAT,0);
  class_addmethod(multyq_class,(t_method)multyq_overlap,gensym("overlap"),A_FLOAT,0);
  class_addmethod(multyq_class,(t_method)multyq_winfac,gensym("winfac"),A_FLOAT,0);
  class_addmethod(multyq_class,(t_method)multyq_fftinfo,gensym("fftinfo"),0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif


void multyq_free(t_multyq *x)
{
#if MSP
  dsp_free((t_pxobject *)x);
#endif
  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->output,0);
  freebytes(x->bitshuffle,0);
  freebytes(x->trigland,0);
  freebytes(x->rcos,0);
  freebytes(x->freqs,0);
  freebytes(x->filt,0);
}

void multyq_overlap(t_multyq *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;
	multyq_init(x,1);
}

void multyq_winfac(t_multyq *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;
	multyq_init(x,2);
}

void multyq_fftinfo(t_multyq *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 *multyq_new(t_symbol *s, int argc, t_atom *argv)
{
int i;
#if MSP
  t_multyq *x = (t_multyq *)newobject(multyq_class);
  dsp_setup((t_pxobject *)x,13);
  outlet_new((t_pxobject *)x, "signal");
  x->x_obj.z_misc |= Z_NO_INPLACE;
#endif

#if PD
  t_multyq *x = (t_multyq *)pd_new(multyq_class);
  for(i=0; i<12; i++){
    inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
  }
  outlet_new(&x->x_obj, gensym("signal"));
#endif
  
  x->overlap = atom_getfloatarg(0,argc,argv);
  x->winfac = atom_getfloatarg(1,argc,argv);
  if(!power_of_two(x->overlap))
    x->overlap = 4;
  if(!power_of_two(x->winfac))
    x->winfac = 2;

  x->D = sys_getblksize();
  x->R = sys_getsr();
  if(!x->R)
    x->R = 44100;
  if(!x->D)
    x->D = 256;
	  	    		

  multyq_init(x,0);

  return (x);
}

void multyq_init(t_multyq *x, short initialized)
{
	int i;
	float funda, base;
	
	x->N = x->D * x->overlap; 
	x->Nw = x->N * x->winfac;	
	limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
	x->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->mult = 1. / (float) x->N; 
	x->inCount = -(x->Nw);
	
	if(!initialized){
		x->please_update = 0;
		x->always_update = 0;
		x->rcoslen = 8192 ;		
		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->rcos = (float *) getbytes( x->rcoslen * sizeof( float ) );
		x->freqs = (float *) getbytes( MAX_N2 * sizeof( float ) );	
		x->filt = (float *) getbytes( (MAX_N2 + 1) * sizeof( float ) );	
		
		x->cf1  = 200.;
		x->gainfac1  = 0.0;
		x->bw1 = .15;
		
		x->cf2  = 700.;
		x->gainfac2  = 0.0;
		x->bw2  = .1; 
		
		x->cf3  = 3000.;
		x->gainfac3  = 0.0;
		x->bw3  = .15;
		
		x->cf4  = 12000.;
		x->gainfac4 = 0.0;
		x->bw4 = .15;
		
		x->mute = 0;
		x->bypass = 0;
		for (i = 0; i < x->rcoslen; i++){
			x->rcos[i] =  .5 - .5 * cos(((float)i/(float)x->rcoslen) * TWOPI);
		}	
		
	} 
		memset((char *)x->input,0,x->Nw * sizeof(float));
		memset((char *)x->output,0,x->Nw * sizeof(float));		

    init_rdft( x->N, x->bitshuffle, x->trigland);
    makehanning(x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
	funda = base = (float)x->R /(float)x->N ;
	for(i = 0; i < x->N2; i++){
		x->freqs[i] = base;
		base += funda;
	}
	update_filter_function(x);
	
}

t_int *multyq_perform(t_int *w)
{

  int i, j;
  t_multyq *x = (t_multyq *) (w[1]);
  short please_update = x->please_update;
  float	*inbuf = (t_float *)(w[2]);
  float	*in2 = (t_float *)(w[3]);
  float *in3 = (t_float *)(w[4]);
  float	*in4 = (t_float *)(w[5]);
  float	*in5 = (t_float *)(w[6]);
  float	*in6 = (t_float *)(w[7]);
  float	*in7 = (t_float *)(w[8]);
  float	*in8 = (t_float *)(w[9]);
  float	*in9 = (t_float *)(w[10]);
  float	*in10 = (t_float *)(w[11]);
  float	*in11 = (t_float *)(w[12]);
  float	*in12 = (t_float *)(w[13]);
  float	*in13 = (t_float *)(w[14]);
  float	*outbuf = (t_float *)(w[15]);
  t_int	n = w[16];
  int  inCount = x->inCount;
  float *Wanal = x->Wanal;
  float *Wsyn = x->Wsyn;
  float *input = x->input;
  float *Hwin = x->Hwin;
  float *buffer = x->buffer;
  float *channel = x->channel;
  float *output = x->output;
  int D = x->D;
  int I = D;
  int R = x->R;
  int Nw = x->Nw;
  int N = x->N ;
  int N2 = x-> N2;
  int Nw2 = x->Nw2;
  int *bitshuffle = x->bitshuffle;
  float *trigland = x->trigland;
  float *filt = x->filt;
  float mult = x->mult;
  int in = x->inCount ;  
  int on = in;
  
  if(x->mute) {
    while (n--){
      *outbuf++ = 0.;
    }
    return (w+17);
  }	
  if(x->bypass) {
    while (n--){
      *outbuf++ = *inbuf++;
    }
    return (w+17);
  }
#if MSP
  if( x->in2_connected ){
    x->cf1 = *in2++ ;
  }
  if( x->in3_connected ){
    x->bw1 = *in3++ ;
  }
  if( x->in4_connected ){
    x->gainfac1 = *in4++ ;
  }
  if( x->in5_connected ){
    x->cf2 = *in5++ ;
  }
  if( x->in6_connected ){
    x->bw2 = *in6++ ;
  }
  if( x->in7_connected ){
    x->gainfac2 = *in7++ ;
  }  
  if( x->in8_connected ){
    x->cf3 = *in8++ ;
  }
  if( x->in9_connected ){
    x->bw3 = *in9++ ;
  }
  if( x->in10_connected ){
    x->gainfac3 = *in10++ ;
  }  
  if( x->in11_connected ){
    x->cf4 = *in11++ ;
  }
  if( x->in12_connected ){
    x->bw4 = *in12++ ;
  }
  if( x->in13_connected ){
    x->gainfac4 = *in13++;
  }  
#endif

#if PD
    x->cf1 = *in2++;
    x->bw1 = *in3++;
    x->gainfac1 = *in4++;
    x->cf2 = *in5++;
    x->bw2 = *in6++;
    x->gainfac2 = *in7++;
    x->cf3 = *in8++;
    x->bw3 = *in9++;
    x->gainfac3 = *in10++;
    x->cf4 = *in11++;
    x->bw4 = *in12++;
    x->gainfac4 = *in13++;
#endif
  
  if(x->always_update) {
    update_filter_function(x);
  }
  else if(please_update) {
    update_filter_function(x);	
    please_update = 0;
  }

  in += D;
  on += I;

  for ( j = 0 ; j < (Nw - D) ; j++ ){
    input[j] = input[j+D];
  }
  for ( j = (Nw-D), i = 0 ; j < Nw; j++, i++ ) {
    input[j] = *inbuf++;
  }

  fold(input, Wanal, Nw, buffer, N, in);   
  rdft(N, 1, buffer, bitshuffle, trigland);

  filtyQ(buffer, channel,filt, N2);

  rdft(N, -1, buffer, bitshuffle, trigland);
  overlapadd( buffer, N, Wsyn, output, Nw, inCount);
    
   
  for (j = 0; j < D; j++){
    *outbuf++ = output[j] * mult;
  }
  for (j = 0; j < Nw - D; j++){
    output[j] = output[j+D];
  }

  for (j = Nw - D; j < Nw; j++){
    output[j] = 0.;
  }	

  x->inCount = in;
  x->please_update = please_update;
  
  return (w+17);
}		

void multyq_bypass(t_multyq *x, t_floatarg state)
{
  x->bypass = (short)state;	
}

void multyq_mute(t_multyq *x, t_floatarg state)
{
  x->mute = (short)state;	
}

void multyq_dsp(t_multyq *x, t_signal **sp, short *count)
{
  int i;

  if(x->R != sp[0]->s_sr||x->D != sp[0]->s_n){
    x->R = sp[0]->s_sr;
    x->D = sp[0]->s_n;
    multyq_init(x,1);
  }

#if MSP
  x->in2_connected = count[1];
  x->in3_connected = count[2];
  x->in4_connected = count[3];
  x->in5_connected = count[4];
  x->in6_connected = count[5];
  x->in7_connected = count[6];
  x->in8_connected = count[7];
  x->in9_connected = count[8];
  x->in10_connected = count[9];
  x->in11_connected = count[10];
  x->in12_connected = count[11];
  x->in13_connected = count[12];
  x->always_update = 0;
  for(i = 1; i < 13; i++) {
    x->always_update += count[i];
  }
#endif

#if PD
    x->always_update = 1;
#endif		

  dsp_add(multyq_perform, 16, x, 
	  sp[0]->s_vec,sp[1]->s_vec,sp[2]->s_vec,sp[3]->s_vec,sp[4]->s_vec,  
	  sp[5]->s_vec,sp[6]->s_vec,sp[7]->s_vec,sp[8]->s_vec,sp[9]->s_vec, 
	  sp[10]->s_vec,sp[11]->s_vec,sp[12]->s_vec,sp[13]->s_vec,sp[0]->s_n);
}


void update_filter_function(t_multyq *x) 
{
  float funda, curfreq, m1, m2;
  float lo, hi ;
  float ploc, gainer;
  int i;
  float nyquist = (float)x->R / 2.0;
  float *filt = x->filt;
  float *rcos = x->rcos;
  float *freqs = x->freqs;
  int rcoslen = x->rcoslen;
  
  // sanity
  if( x->cf1 < 0 ){
    x->cf1 = 0;
  } 
  else if( x->cf1 > nyquist){
    x->cf1 = nyquist ;
  } 
  if( x->bw1 <= .05 ){
    x->bw1 = .05;
  }
  else if( x->bw1 > 1. ){
    x->bw1 = 1.;
  }
  if( x->gainfac1 < -1. ){
    x->gainfac1 = -1;
  }
  if( x->cf2 < 0 ){
    x->cf2 = 0;
  } 
  else if( x->cf2> nyquist){
    x->cf2 = nyquist ;
  } 
  if( x->bw2 <= .05 ){
    x->bw2 = .05;
  }
  else if( x->bw2 > 1. ){
    x->bw2 = 1.;
  }
  if( x->gainfac2 < -1. ){
    x->gainfac2 = -1;
  }
  if( x->cf3 < 0 ){
    x->cf3 = 0;
  } 
  else if( x->cf3 > nyquist){
    x->cf3 = nyquist ;
  } 
  if( x->bw3 <= .05 ){
    x->bw3 = .05;
  }
  else if( x->bw3 > 1. ){
    x->bw3 = 1.;
  }
  if( x->gainfac3 < -1. ){
    x->gainfac3 = -1;
  }
  if( x->cf4 < 0 ){
    x->cf4 = 0;
  } 
  else if( x->cf4 > nyquist){
    x->cf4 = nyquist ;
  } 
  if( x->bw4 <= .05 ){
    x->bw4 = .05;
  }
  else if( x->bw4 > 1. ){
    x->bw4 = 1.;
  }
  if( x->gainfac4 < -1. ){
    x->gainfac4 = -1;
  }
  for( i = 0; i < x->N2; i++ ) {
    x->filt[i] = 1.0 ;
  }
  // filt 1
  lo = x->cf1 * (1.0 - x->bw1 );
  hi = x->cf1 * (1.0 + x->bw1 );
  for( i = 0; i < x->N2; i++ ) {
    if(freqs[i] >= lo && freqs[i] <= hi){
      ploc = (freqs[i] - lo) / (hi - lo);
      gainer = 1 + x->gainfac1 * rcos[ (int) (ploc * rcoslen) ] ;
      if( gainer < 0 ){
	gainer = 0;
      }
      filt[i] *= gainer ;
		
    }
  }
  // filt 2
  lo = x->cf2 * (1.0 - x->bw2 );
  hi = x->cf2 * (1.0 + x->bw2 );
  for( i = 0; i < x->N2; i++ ) {
    if( freqs[i] >= lo && freqs[i] <= hi){
      ploc = (freqs[i] - lo) / (hi - lo);
      gainer = 1 + x->gainfac2 * rcos[ (int) (ploc * rcoslen) ] ;
      if( gainer < 0 ){
	gainer = 0;
      }
      filt[i] *= gainer ;
		
    }
  }
  // filt 3
  lo = x->cf3 * (1.0 - x->bw3 );
  hi = x->cf3 * (1.0 + x->bw3 );
  for( i = 0; i < x->N2; i++ ) {
    if(freqs[i] >= lo && freqs[i] <= hi){
      ploc = (freqs[i] - lo) / (hi - lo);
      gainer = 1 + x->gainfac3 * rcos[ (int) (ploc * rcoslen) ] ;
      if( gainer < 0 ){
	gainer = 0;
      }
      filt[i] *= gainer ;
		
    }
  }
  // filt 4
  lo = x->cf4 * (1.0 - x->bw4 );
  hi = x->cf4 * (1.0 + x->bw4 );
  for( i = 0; i < x->N2; i++ ) {
    if(freqs[i] >= lo && freqs[i] <= hi){
      ploc = (freqs[i] - lo) / (hi - lo);
      gainer = 1 + x->gainfac4 * rcos[ (int) (ploc * rcoslen) ] ;
      if( gainer < 0 ){
	gainer = 0;
      }
      filt[i] *= gainer ;
		
    }
  }

}
#if MSP
void multyq_float(t_multyq *x, double f) // Look at floats at inlets
{
int inlet = x->x_obj.z_in;
	
  if (inlet == 1)
    {
      x->cf1 = f;
    }
  else if (inlet == 2)
    {
      x->bw1 = f;
    }
  else if (inlet == 3)
    {
      x->gainfac1 = f;
    }
  else if (inlet == 4)
    {
      x->cf2 = f;
    }
  else if (inlet == 5)
    {
      x->bw2 = f;
    }
  else if (inlet == 6)
    {
      x->gainfac2 = f;
    }
  else if (inlet == 7)
    {
      x->cf3 = f;
    }
  else if (inlet == 8)
    {
      x->bw3 = f;
    }
  else if (inlet == 9)
    {
      x->gainfac3 = f;
    }	
  else if (inlet == 10)
    {
      x->cf4 = f;
    }
  else if (inlet == 11)
    {
      x->bw4 = f;
    }
  else if (inlet == 12)
    {
      x->gainfac4 = f;
    }		
  x->please_update = 1;
}
#endif

void multyq_assist (t_multyq *x, void *b, long msg, long arg, char *dst)
{
  if (msg==1) {
    switch (arg) {
    case 0: sprintf(dst,"(signal) Input"); break;
    case 1: sprintf(dst,"(signal/float) Cf1");break;
    case 2: sprintf(dst,"(signal/float) Bw1"); break;
    case 3: sprintf(dst,"(signal/float) Gain1"); break;
    case 4: sprintf(dst,"(signal/float) Cf2"); break;
    case 5: sprintf(dst,"(signal/float) Bw2"); break;
    case 6: sprintf(dst,"(signal/float) Gain2"); break;
    case 7: sprintf(dst,"(signal/float) Cf3"); break;
    case 8: sprintf(dst,"(signal/float) Bw3"); break;
    case 9: sprintf(dst,"(signal/float) Gain3"); break;
    case 10: sprintf(dst,"(signal/float) Cf4"); break;
    case 11: sprintf(dst,"(signal/float) Bw4"); break;
    case 12: sprintf(dst,"(signal/float) Gain4"); break;
    }
  } else if (msg==2) {
    sprintf(dst,"(signal) Output");
  }
}


void filtyQ( float *S, float *C, float *filtfunc, int N2 )
{
  int real, imag, amp, phase;
  float a, b;
  int i;
  float maxamp = 1.;

  for ( i = 0; i <= N2; i++ ) {
    imag = phase = ( real = amp = i<<1 ) + 1;
    a = ( i == N2 ? S[1] : S[real] );
    b = ( i == 0 || i == N2 ? 0. : S[imag] );
    C[amp] = hypot( a, b );
    C[amp] *= filtfunc[ i ];
    C[phase] = -atan2( b, a );
  }

  for ( i = 0; i <= N2; i++ ) {
    imag = phase = ( real = amp = i<<1 ) + 1;
    S[real] = *(C+amp) * cos( *(C+phase) );
    if ( i != N2 )
      S[imag] = -*(C+amp) * sin( *(C+phase) );
  }
}

--- NEW FILE: crossx~.c ---
#include "MSPd.h"

#include "fftease.h"

#if MSP
void *crossx_class;
#endif 

#if PD
static t_class *crossx_class;
#endif

#define OBJECT_NAME "crossx~"

typedef struct _crossx
{
#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;
  float *input1;	
  float *buffer1;
  float *channel1;

  float *input2;	
  float *buffer2;
  float *channel2;
  float *last_channel;
  //
  int	inCount;
  float *Hwin;
  float *Wanal;	
  float *Wsyn;	
  float *output;
  /* crossx vars */

  float *c_lastphase_in1;
  float *c_lastphase_in2;
  float *c_lastphase_out;
  float c_fundamental;
  float c_factor_in;
  float c_factor_out;

  float threshie;
  short thresh_connected;
  // for fast fft
  float mult; 
  float *trigland;
  int *bitshuffle;
  int overlap;//overlap factor
  int winfac;//window factor
  int vs;//vector size
  short mute;//flag
  short autonorm;// for self gain regulation
} t_crossx;

void *crossx_new(t_symbol *s, int argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *crossx_perform(t_int *w);
void crossx_dsp(t_crossx *x, t_signal **sp, short *count);
void crossx_assist(t_crossx *x, void *b, long m, long a, char *s);
void crossx_float(t_crossx *x, double f);
void *crossx_new(t_symbol *s, int argc, t_atom *argv);
void crossx_init(t_crossx *x, short initialized);
void crossx_overlap(t_crossx *x, t_floatarg o);
void crossx_winfac(t_crossx *x, t_floatarg o);
void crossx_fftinfo(t_crossx *x);
void crossx_mute(t_crossx *x, t_floatarg toggle);
void crossx_autonorm(t_crossx *x, t_floatarg toggle);
void crossx_free(t_crossx *x);

#if MSP
void main(void)
{
  setup((t_messlist **)&crossx_class, (method)crossx_new, (method)dsp_free, 
  (short)sizeof(t_crossx), 0L, A_GIMME, 0);
  addmess((method)crossx_dsp, "dsp", A_CANT, 0);
  addmess((method)crossx_assist,"assist",A_CANT,0);
  addmess((method)crossx_mute,"mute",A_DEFFLOAT,0);
  addmess((method)crossx_overlap, "overlap",  A_DEFFLOAT, 0);
  addmess((method)crossx_winfac, "winfac",  A_DEFFLOAT, 0);
  addmess((method)crossx_fftinfo, "fftinfo", 0);
  addmess((method)crossx_autonorm, "autonorm",  A_DEFFLOAT, 0);
  addfloat((method)crossx_float);
  dsp_initclass();
   	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif
#if PD
void crossx_tilde_setup(void)
{
  crossx_class = class_new(gensym("crossx~"), (t_newmethod)crossx_new, 
			 (t_method)crossx_free ,sizeof(t_crossx), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(crossx_class, t_crossx, x_f);
  class_addmethod(crossx_class, (t_method)crossx_dsp, gensym("dsp"), 0);
  class_addmethod(crossx_class, (t_method)crossx_assist, gensym("assist"), 0);
  class_addmethod(crossx_class, (t_method)crossx_mute, gensym("mute"), A_DEFFLOAT,0);
  class_addmethod(crossx_class, (t_method)crossx_overlap, gensym("overlap"), A_DEFFLOAT,0);
  class_addmethod(crossx_class, (t_method)crossx_winfac, gensym("winfac"), A_DEFFLOAT,0);
  class_addmethod(crossx_class, (t_method)crossx_fftinfo, gensym("fftinfo"), 0);
  class_addmethod(crossx_class, (t_method)crossx_autonorm, gensym("autonorm"), A_DEFFLOAT,0);
   	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
post("padded memory");
}
#endif


void crossx_autonorm(t_crossx *x, t_floatarg toggle)
{
	x->autonorm = (short) toggle;
}
void crossx_assist (t_crossx *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) Filter Sound");
      break;
    case 2:
      sprintf(dst,"(float/signal) Cross Synthesis Threshold");
      break;

    }
  } else if (msg==2) {
    sprintf(dst,"(signal) Output");
  }
}

void crossx_overlap(t_crossx *x, t_floatarg o)
{
  if(!power_of_two((int)o)){
    error("%f is not a power of two",o);
    return;
  }
  x->overlap = (int)o;
  crossx_init(x,1);
}

void crossx_winfac(t_crossx *x, t_floatarg f)
{
  if(!power_of_two((int)f)){
    error("%f is not a power of two",f);
    return;
  }
  x->winfac = (int)f;
  crossx_init(x,1);
}

void crossx_fftinfo( t_crossx *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 crossx_mute(t_crossx *x, t_floatarg toggle)
{
  x->mute = (short)toggle;
}

void crossx_free(t_crossx *x)
{
#if MSP
  dsp_free((t_pxobject *) x);
#endif
  freebytes(x->trigland,0);
  freebytes(x->bitshuffle,0);
  freebytes(x->Wanal,0);
  freebytes(x->Wsyn,0);
  freebytes(x->input1,0);
  freebytes(x->input2,0);
  freebytes(x->Hwin,0);
  freebytes(x->buffer1,0);
  freebytes(x->buffer2,0);
  freebytes(x->channel1,0);
  freebytes(x->channel2,0);
  freebytes(x->output,0);
  /* these last are extra - kill if we clean up - upstairs
  free(x->c_lastphase_in1);
  free(x->c_lastphase_in2);
  free(x->c_lastphase_out);
  free(x->last_channel);*/
}

#if MSP
void crossx_float(t_crossx *x, double f) // Look at floats at inlets
{
int inlet = x->x_obj.z_in;
	
  if (inlet == 2)
    {
      x->threshie = f;
    }
}
#endif

void *crossx_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
  t_crossx *x = (t_crossx *)newobject(crossx_class);
  dsp_setup((t_pxobject *)x,3);
  outlet_new((t_pxobject *)x, "signal");
#endif
#if PD
  t_crossx *x = (t_crossx *)pd_new(crossx_class);
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
#endif


  x->overlap = atom_getfloatarg(0,argc,argv);
  x->winfac = atom_getfloatarg(1,argc,argv);
  if(x->overlap <= 0)
    x->overlap = 4;

  x->winfac = 1;
    
  x->R = sys_getsr();
  x->vs = sys_getblksize();

  crossx_init(x,0);
  return (x);
}

void crossx_init(t_crossx *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->N2 = (x->N)>>1;
  x->Nw2 = (x->Nw)>>1;
  x->inCount = -(x->Nw);
  x->mult = 1. / (float) x->N;

  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;
	if(!initialized){
      x->threshie = .001 ;
      x->autonorm = 0;
        x->mute = 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->output = (float *) getbytes((MAX_Nw) * sizeof(float));
	  x->bitshuffle = (int *) getbytes((MAX_N * 2)* sizeof(int));
	  x->trigland = (float *) getbytes((MAX_N * 2)* sizeof(float));

	  x->input1 = (float *) getbytes(MAX_Nw * sizeof(float));	
	  x->buffer1 = (float *) getbytes(MAX_N * sizeof(float));
	  x->channel1 = (float *) getbytes((MAX_N+2) * sizeof(float));
	  x->input2 = (float *) getbytes(MAX_Nw * sizeof(float));	
	  x->buffer2 = (float *) getbytes(MAX_N * sizeof(float));
	  x->channel2 = (float *) getbytes((MAX_N+2) * sizeof(float));
	  x->last_channel = (float *) getbytes((MAX_N+2) * sizeof(float));
	  x->c_lastphase_in1 = (float *) getbytes((MAX_N2+1) * sizeof(float));
	  x->c_lastphase_in2 = (float *) getbytes((MAX_N2+1) * sizeof(float));
	  x->c_lastphase_out = (float *) getbytes((MAX_N2+1) * sizeof(float));
	} 
		memset((char *)x->input1,0,x->Nw * sizeof(float));
		memset((char *)x->input2,0,x->Nw * sizeof(float));
		memset((char *)x->output,0,x->Nw * sizeof(float));
		memset((char *)x->buffer1,0,x->N * sizeof(float));
		memset((char *)x->buffer2,0,x->N * sizeof(float));
		memset((char *)x->channel1,0,(x->N+2) * sizeof(float));
		memset((char *)x->channel2,0,(x->N+2) * sizeof(float));
		memset((char *)x->c_lastphase_in1,0,(x->N2+1) * sizeof(float));
		memset((char *)x->c_lastphase_in2,0,(x->N2+1) * sizeof(float));
		memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float));
	
  init_rdft( x->N, x->bitshuffle, x->trigland);
  makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
}

t_int *crossx_perform(t_int *w)
{
	int i, j;

  float a1, a2, b1, b2;
  int even, odd;
  int amp, freq;
  float gainer, threshie;
  float ingain = 0;
  float outgain, rescale;
  float mymult;

  t_crossx *x = (t_crossx *) (w[1]);
  t_float *in1 = (t_float *)(w[2]);
  t_float *in2 = (t_float *)(w[3]);
  t_float *in3 = (t_float *)(w[4]);
  t_float *out = (t_float *)(w[5]);
  t_int n = w[6];
	
  /* dereference struncture  */	
  float *input1 = x->input1;
  float *input2 = x->input2;
  float *buffer1 = x->buffer1;
  float *buffer2 = x->buffer2;
  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 *output = x->output;
  float *channel1 = x->channel1;
  float *channel2 = x->channel2;
  float *last_channel = x->last_channel;
  int *bitshuffle = x->bitshuffle;
  float *trigland = x->trigland;
  float mult = x->mult;
  float *c_lastphase_in1 = x->c_lastphase_in1;
  float *c_lastphase_in2 = x->c_lastphase_in2;
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;
	short autonorm = x->autonorm;

  if(x->mute){
    while(n--){
      *out++ = 0;
    }
    return w+7;
  }
  
  if( x->thresh_connected ){	
  	threshie = *in3++;
  } else {
  	threshie = x->threshie;
  }
  
  inCount += D;

  for ( j = 0 ; j < Nw - D ; j++ ){
    input1[j] = input1[j+D];
    input2[j] = input2[j+D];
  }
  for ( j = Nw - D; j < Nw; j++ ) {
    input1[j] = *in1++;
    input2[j] = *in2++;
  }

  fold( input1, Wanal, Nw, buffer1, N, inCount );		
  fold( input2, Wanal, Nw, buffer2, N, inCount );	
  rdft( N, 1, buffer1, bitshuffle, trigland );
  rdft( N, 1, buffer2, bitshuffle, trigland );

/* changing algorithm for window flexibility */
  if(autonorm){
    ingain = 0;
  	for(i = 0; i < N; i+=2){
  		ingain += hypot(buffer1[i], buffer1[i+1]);
  	}
  }

  for ( i = 0; i <= N2; i++ ) {
    odd = ( even = i<<1 ) + 1;

    a1 = ( i == N2 ? *(buffer1+1) : *(buffer1+even) );
    b1 = ( i == 0 || i == N2 ? 0. : *(buffer1+odd) );
    a2 = ( i == N2 ? *(buffer2+1) : *(buffer2+even) );
    b2 = ( i == 0 || i == N2 ? 0. : *(buffer2+odd) );
    gainer = hypot(a2, b2);
    if( gainer > threshie ) 
    	*(channel1+even) = hypot( a1, b1 ) * gainer;
    *(channel1+odd) = -atan2( b1, a1 );
    *(buffer1+even) = *(channel1+even) * cos( *(channel1+odd) );
    if ( i != N2 )
      *(buffer1+odd) = -(*(channel1+even)) * sin( *(channel1+odd) );

  }
  if(autonorm){
    outgain = 0;
  	for(i = 0; i < N; i+=2){
  		outgain += hypot(buffer1[i], buffer1[i+1]);
  	}
	if(ingain <= .0000001){
  		// post("gain emergency!");
  		rescale = 1.0;
  	} else {
  		rescale = ingain / outgain;
  	} 
  	// post("ingain %f outgain %f rescale %f",ingain, outgain, rescale);
  	mymult = mult * rescale;
  }  else {
  	mymult = mult;
  }

  rdft( N, -1, buffer1, bitshuffle, trigland );
  overlapadd( buffer1, N, Wsyn, output, Nw, inCount);

  for ( j = 0; j < D; j++ )
    *out++ = output[j] * mymult;

  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
			
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;

	

  /* restore state variables */
  x->inCount = inCount % Nw;
  return (w+7);
}		

void crossx_dsp(t_crossx *x, t_signal **sp, short *count)
{
#if MSP
  x->thresh_connected = count[2];
#endif
#if PD
  x->thresh_connected = 1;
#endif

  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;
    crossx_init(x,1);
  }
  
  dsp_add(crossx_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, 
	  sp[3]->s_vec, sp[0]->s_n);
}


--- NEW FILE: taint~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *taint_class;
#endif
#if PD
static t_class *taint_class;
#endif

#define OBJECT_NAME "taint~"


/*
Adding -32dB pad for invert option. Also added latency mechanism in
 switching from normal to "invert" to avoid glitches from extreme
 amplitude disparities.
 
 Made all inlets of type signal (with float options).
 
 Threshold input is now linear, not dB (with Max doing the conversion
										if desired).
 
 -EL 10/1/2005
 
 */

typedef struct _taint
{
#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;
	int invert;
	int *bitshuffle;
    
	float threshold;
	float exponent;
	float *Wanal;	
	float *Wsyn;	
	float *inputOne;
	float *inputTwo;
	float *Hwin;
	float *bufferOne;
	float *bufferTwo;
	float *channelOne;
	float *channelTwo;
	float *output;
	float mult; 
	float *trigland;
	
	short connected[8];
	short mute;
	int overlap;//overlap factor
		int winfac;//window factor
			int vs;//vector size  
				int invert_countdown; // delay onset of invert effect to avoid loud glitches
				int invert_nextstate;// next state for invert   
					float invert_pad;   	
} t_taint;


/* msp function prototypes */

void *taint_new(t_symbol *s, int argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *taint_perform(t_int *w);
void taint_dsp(t_taint *x, t_signal **sp, short *count);
void taint_assist(t_taint *x, void *b, long m, long a, char *s);
void taint_dest(t_taint *x, double f);
void taint_invert(t_taint *x, t_floatarg toggle);
void taint_free(t_taint *x);
void taint_mute(t_taint *x, t_floatarg toggle);
void taint_fftinfo(t_taint *x);
void taint_tilde_setup(void);
void taint_overlap(t_taint *x, t_floatarg o);
void taint_winfac(t_taint *x, t_floatarg o);
void taint_init(t_taint *x, short initialized);
void taint_pad(t_taint *x, t_floatarg pad);


#if MSP
void main(void)
{
	setup( (struct messlist **) &taint_class, (void *) taint_new,
		   (method)dsp_free, (short) sizeof(t_taint),
		   0, A_GIMME, 0);
	
	addmess((method)taint_dsp, "dsp", A_CANT, 0);
	addmess((method)taint_assist,"assist",A_CANT,0);    
	addmess((method)taint_invert,"invert", A_FLOAT, 0);  
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
	
	addmess((method)taint_overlap,"overlap", A_FLOAT, 0);
	addmess((method)taint_winfac,"winfac", A_FLOAT, 0);
	addmess((method)taint_mute,"mute", A_FLOAT, 0);
	addmess((method)taint_pad,"pad", A_FLOAT, 0);
	addmess((method)taint_fftinfo,"fftinfo", 0);
	addfloat((method) taint_dest);
	dsp_initclass();
}

/* float input handling routine (MSP only)*/
void taint_dest(t_taint *x, double f)
{
	int inlet = x->x_obj.z_in;
	
	if ( inlet == 2 ) {
		x->exponent = f;	
	}
	
	if ( inlet == 3 ){
		/* x->threshold = (float) (pow( 10., (f * .05))); */
		x->threshold = f;
	}
}
#endif

#if PD
void taint_tilde_setup(void)
{
	taint_class = class_new(gensym("taint~"), (t_newmethod)taint_new, 
							(t_method)taint_free ,sizeof(t_taint), 0,A_GIMME,0);
	CLASS_MAINSIGNALIN(taint_class, t_taint, x_f);
	class_addmethod(taint_class, (t_method)taint_dsp, gensym("dsp"), 0);
	class_addmethod(taint_class, (t_method)taint_assist, gensym("assist"), 0);
	class_addmethod(taint_class, (t_method)taint_invert, gensym("invert"), A_FLOAT,0);
	class_addmethod(taint_class, (t_method)taint_overlap, gensym("overlap"), A_FLOAT,0);
	class_addmethod(taint_class, (t_method)taint_mute, gensym("mute"), A_FLOAT,0);
	class_addmethod(taint_class, (t_method)taint_pad, gensym("pad"), A_FLOAT,0);
	class_addmethod(taint_class, (t_method)taint_fftinfo, gensym("fftinfo"), A_CANT,0);
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif


void taint_mute(t_taint *x, t_floatarg toggle)
{
	x->mute = (short)toggle;
	//  post("mute set to %f, %d",toggle,x->mute);
}

void taint_overlap(t_taint *x, t_floatarg o)
{
	if(!power_of_two(o)){
		error("%f is not a power of two",o);
		return;
	}
	x->overlap = (int)o;
	taint_init(x,1);
}

void taint_winfac(t_taint *x, t_floatarg f)
{
	if(!power_of_two(f)){
		error("%f is not a power of two",f);
		return;
	}
	x->winfac = (int)f;
	taint_init(x,1);
}

void taint_fftinfo( t_taint *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 taint_free(t_taint *x)
{
#if MSP
	dsp_free((t_pxobject *) x);
#endif
	free(x->trigland);
	free(x->bitshuffle);
	free(x->Wanal);
	free(x->Wsyn);
	free(x->Hwin);
	free(x->inputOne);
	free(x->inputTwo);
	free(x->bufferOne);
	free(x->bufferTwo);
	free(x->channelOne);
	free(x->channelTwo);
	free(x->output);
}

void taint_pad(t_taint *x, t_floatarg pad)
{
	x->invert_pad = pad;
	taint_invert(x,x->invert);//resubmit to invert
}

void taint_invert(t_taint *x, t_floatarg toggle)
{
	
	x->invert_nextstate = toggle;
	x->invert_countdown = x->overlap; // delay effect for "overlap" vectors
	
	if(x->invert_nextstate){ // lower gain immediately; delay going to invert
		x->mult = (1. / (float) x->N) * x->invert_pad;
	} else {
		x->invert = 0; //immediately turn off invert; delay raising gain
	}
	
}

void taint_assist (t_taint *x, void *b, long msg, long arg, char *dst)
{
	
	if (msg == 1) {
		
		switch (arg) {
			case 0:		sprintf(dst,"(signal) Input One");break;
			case 1:		sprintf(dst,"(signal) Input Two"); break;
			case 2:		sprintf(dst,"(signal/float) Scaling Exponent"); break;
			case 3:		sprintf(dst,"(signal/float) Inverse Threshold"); break;
		}
	}
	
	else {
		
		if (msg == 2)
			sprintf(dst,"(signal) Output");
		
	}
}


void *taint_new(t_symbol *s, int argc, t_atom *argv)
{
	
#if MSP
	t_taint 	*x = (t_taint *) newobject(taint_class);
	dsp_setup((t_pxobject *)x,4);
	outlet_new((t_pxobject *)x, "signal");
	// x->x_obj.z_misc |= Z_NO_INPLACE; // probably not needed
#endif
#if PD
	t_taint *x = (t_taint *)pd_new(taint_class);
	/* add three additional signal inlets */
	inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
	inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
	inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
	outlet_new(&x->x_obj, gensym("signal"));
#endif
	
	
	/* optional arguments: scaling exponent, threshold (now linear), overlap, winfac */
	x->exponent = atom_getfloatarg(0,argc,argv);
	x->threshold = atom_getfloatarg(1,argc,argv);
	x->overlap = atom_getfloatarg(2,argc,argv);
	x->winfac = atom_getfloatarg(3,argc,argv);
	
	/*	
		x->threshold = (float) pow(10.0,(x->threshold * .05));
	*/
	/* sanity check */
	if(x->exponent < 0.25)
		x->exponent = 0.25;
	
	if(!power_of_two(x->overlap)){
		x->overlap = 4;
	}
	if(!power_of_two(x->winfac)){
		x->winfac = 1;
	}
  		
	x->vs = sys_getblksize();
	x->R = sys_getsr();
	
	taint_init(x,0);
	
	return (x);
}

void taint_init(t_taint *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->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->inCount = -(x->Nw);
	x->mult = 1. / (float) x->N;
	if(!initialized){
		x->invert_pad = 0.025; // -32 dB
		x->invert_countdown = 0;
		x->mute = 0;
		x->invert = 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->inputOne = (float *) getbytes( MAX_Nw * sizeof(float) );
		x->inputTwo = (float *) getbytes( MAX_Nw * sizeof(float) );	
		x->bufferOne = (float *) getbytes( MAX_N * sizeof(float) );
		x->bufferTwo = (float *) getbytes( MAX_N * sizeof(float) ); 
		x->channelOne = (float *) getbytes( (MAX_N+2) * sizeof(float) );
		x->channelTwo = (float *) getbytes( (MAX_N+2) * sizeof(float) );
		x->output = (float *) getbytes( MAX_Nw * sizeof(float) );
		x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) );
		x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) );
	} 
	if(x->invert){
		x->mult *= x->invert_pad;
    }
	memset((char *)x->inputOne,0,x->Nw * sizeof(float));
	memset((char *)x->inputTwo,0,x->Nw * sizeof(float));
	memset((char *)x->output,0,x->Nw * sizeof(float));
		
	init_rdft( x->N, x->bitshuffle, x->trigland);
	makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 1);
	
}


t_int *taint_perform(t_int *w)
{
	
	int		
    i,j,
    inCount,
    R,
    N,
    N2,
    D,
    Nw,
    invert = 0,
    even, odd,
    *bitshuffle;
	
	float		maxamp,	
		threshold = 1.,
		mult,
		exponent,
		a1, b1,
		a2, b2,
		*inputOne,
		*inputTwo,
		*bufferOne,
		*bufferTwo,
		*output,
		*Wanal,
		*Wsyn,
		*channelOne,
		*channelTwo,
		*trigland;
	
	
	
	/* get our inlets and outlets */
	
	t_taint *x = (t_taint *) (w[1]);
	t_float *inOne = (t_float *)(w[2]);
	t_float *inTwo = (t_float *)(w[3]);
	t_float *vec_exponent = (t_float *)(w[4]);
	t_float *vec_threshold = (t_float *)(w[5]);
	t_float *out = (t_float *)(w[6]);
	t_int n = w[7];
	
	short *connected = x->connected;
	/* dereference structure  */	
	if(connected[2])
		x->exponent = *vec_exponent;
	if(connected[3]){
		x->threshold = *vec_threshold;
		/*
		x->threshold = (float) (pow( 10., (x->threshold * .05)));
		 */
	}
	
	if(x->mute){
		while(n--)
			*out++ = 0.0;
		return w+8;
	}
	// do countdown
	if(x->invert_countdown > 0){
		
		if(x->invert) { // we 
		} else {
		}  
		--(x->invert_countdown);
		if(! x->invert_countdown){ // countdown just ended
			if(x->invert_nextstate){ // moving to invert (gain is already down)
				x->invert = x->invert_nextstate;
			} else { // invert is already off - now reset gain
				x->mult = 1. / (float) x->N;
			}
		}
	}
	
	inputOne = x->inputOne;
	inputTwo = x->inputTwo;
	bufferOne = x->bufferOne;
	bufferTwo = x->bufferTwo;
	inCount = x->inCount;
	R = x->R;
	N = x->N;
	N2 = x->N2;
	D = x->D;
	Nw = x->Nw;
	Wanal = x->Wanal;
	Wsyn = x->Wsyn;
	output = x->output;
	channelOne = x->channelOne;
	channelTwo = x->channelTwo;
	bitshuffle = x->bitshuffle;
	trigland = x->trigland;
	mult = x->mult;	
	invert = x->invert;
	exponent = x->exponent;
	
	if ( x->threshold != 0. )
		threshold = x->threshold;
	
	/* fill our retaining buffers */
	
	inCount += D;
	
	for ( j = 0 ; j < Nw - D ; j++ ) {
		inputOne[j] = inputOne[j+D];
		inputTwo[j] = inputTwo[j+D];
	}
	
	for ( j = Nw - D; j < Nw; j++ ) {
		inputOne[j] = *inOne++;
		inputTwo[j] = *inTwo++;
	}
	
	/* apply hamming window and fold our window buffer into the fft buffer */ 
	
	fold( inputOne, Wanal, Nw, bufferOne, N, inCount );
	fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount );
	
	/* do an fft */ 
	
	rdft( N, 1, bufferOne, bitshuffle, trigland );
	rdft( N, 1, bufferTwo, bitshuffle, trigland );
	
	/* convert to polar coordinates from complex values */
	
	if (invert) {
		
		for ( i = 0; i <= N2; i++ ) {
			
			float magnitude;	
			
			odd = ( even = i<<1 ) + 1;
			
			a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) );
			b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) );
			
			a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) );
			b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) );
			
			*(channelOne+even) = hypot( a1, b1 );
			*(channelOne+odd) = -atan2( b1, a1 );
			
			magnitude = *(channelTwo+even) = hypot( a2, b2 );
			*(channelTwo+odd) = -atan2( b2, a2 );
			
			/* use threshold for inverse filtering to avoid division by zero */
			
			if ( magnitude < threshold )
				magnitude = 0.;
			
			else  
				magnitude = 1. / magnitude;
			
			*(channelOne+even) *= magnitude;
			*(channelOne+even) = pow( *(channelOne+even), exponent );
		}
	}
	
	
	else {
		
		for ( i = 0; i <= N2; i++ ) {
			
			odd = ( even = i<<1 ) + 1;
			
			a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) );
			b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) );
			
			a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) );
			b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) );
			
			*(channelOne+even) = hypot( a1, b1 );
			*(channelOne+odd) = -atan2( b1, a1 );
			
			*(channelTwo+even) = hypot( a2, b2 );
			*(channelTwo+odd) = -atan2( b2, a2 );
			
			/* simple multiplication of magnitudes */
			
			*(channelOne+even) *= *(channelTwo+even);
			
			*(channelOne+even) = pow( *(channelOne+even), exponent );
		}
	}
	
	/* convert back to complex form, read for the inverse fft */
	
	for ( i = 0; i <= N2; i++ ) {
		
		odd = ( even = i<<1 ) + 1;
		
		*(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) );
		
		if ( i != N2 )
			*(bufferOne+odd) = -(*(channelOne+even)) * sin( *(channelOne+odd) );
	}
	
	
	/* do an inverse fft */
	
	rdft( N, -1, bufferOne, bitshuffle, trigland );
	
	/* use slow inverse fft */
	
	//  rfft( bufferOne, N2, INVERSE );
	
	/* dewindow our result */
	
	overlapadd( bufferOne, N, Wsyn, output, Nw, inCount);
	
	/* set our output and adjust our retaining output buffer */
	
	for ( j = 0; j < D; j++ )
		*out++ = output[j] * mult;
	
	for ( j = 0; j < Nw - D; j++ )
		output[j] = output[j+D];
	
	for ( j = Nw - D; j < Nw; j++ )
		output[j] = 0.;
	
	
	/* restore state variables */
	
	x->inCount = inCount % Nw;
	return (w+8);
}		


void taint_dsp(t_taint *x, t_signal **sp, short *count)
{
	long i;
	
#if MSP
	for( i = 0; i < 4; i++ ){
		x->connected[i] = count[i];
	}
#endif
	/* signal is always connected in Pd */
#if PD 
	for( i = 0; i < 4; i++ ){
		x->connected[i] = 1;
	}
#endif
	
	/* reinitialize if vector size or sampling rate has been changed */
	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;
		taint_init(x,1);
	}	
	
	dsp_add(taint_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);
}


--- NEW FILE: pvharm~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *pvharm_class;
#endif 

#if PD
static t_class *pvharm_class;
#endif

#define OBJECT_NAME "pvharm~"

typedef struct _pvharm
{
#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;
	// for convert
	float *c_lastphase_in;
	//  float *c_lastphase_out;
	float c_fundamental;
	float c_factor_in;
	float c_factor_out;
	
	float *table;
	int NP;
	
	int L;
	int first;
	float Iinv;
	
	float ffac;
	// for oscbank 1
	float *lastamp;
	float *lastfreq;
	float *index;
	int lo_bin;
	int hi_bin;
	float topfreq;
	float P;
	float myPInc;
	//
	// for oscbank 2
	float *lastamp2;
	float *lastfreq2;
	float *index2;
	int lo_bin2;
	int hi_bin2;
	float topfreq2;
	float P2;
	float myPInc2;
	//
	
	float synt;
	float myPI;
	float TWOmyPI;
	// for fast fft
	float mult; 
	float *trigland;
	int *bitshuffle;
	short pitch1_connected;
	short pitch2_connected;
	short synt_connected;
	short mute;
	int vs;//vector size
		int overlap;//overlap factor
			int winfac;//window size factor
				float hifreq;//highest frequency to synthesize
					float lofreq;//lowest frequency to synthesize
} t_pvharm;

void *pvharm_new(t_symbol *s, int argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *pvharm_perform(t_int *w);
void pvharm_dsp(t_pvharm *x, t_signal **sp, short *count);
void pvharm_assist(t_pvharm *x, void *b, long m, long a, char *s);
void pvharm_float(t_pvharm *x, double f);
void pvharm_mute(t_pvharm *x, t_floatarg f);
void pvharm_init(t_pvharm *x, short initialized);
void pvharm_lowfreq(t_pvharm *x, t_floatarg f);
void pvharm_highfreq(t_pvharm *x, t_floatarg f);
void pvharm_free(t_pvharm *x);
void pvharm_fftinfo(t_pvharm *x);
void pvharm_overlap(t_pvharm *x, t_floatarg f);
void pvharm_winfac(t_pvharm *x, t_floatarg f);

#if MSP
void main(void)
{
	setup((t_messlist **) &pvharm_class, (method) pvharm_new, (method)pvharm_free, 
		  (short)sizeof(t_pvharm), 0, A_GIMME, 0);
	addmess((method)pvharm_dsp, "dsp", A_CANT, 0);
	addmess((method)pvharm_assist,"assist",A_CANT,0);
	addmess((method)pvharm_mute,"mute",A_DEFFLOAT,0);
	
	addmess((method)pvharm_lowfreq,"lowfreq",A_FLOAT,0);
	addmess((method)pvharm_highfreq,"highfreq",A_FLOAT,0);
	addmess((method)pvharm_overlap,"overlap",A_DEFFLOAT,0);
	addmess((method)pvharm_winfac,"winfac",A_DEFFLOAT,0);
	addmess((method)pvharm_fftinfo,"fftinfo",0);  addfloat((method)pvharm_float);
	dsp_initclass();
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
void pvharm_tilde_setup(void)
{
	pvharm_class = class_new(gensym("pvharm~"), (t_newmethod)pvharm_new, 
							 (t_method)pvharm_free ,sizeof(t_pvharm), 0,A_GIMME,0);
	CLASS_MAINSIGNALIN(pvharm_class, t_pvharm, x_f);
	class_addmethod(pvharm_class, (t_method)pvharm_dsp, gensym("dsp"), 0);
	class_addmethod(pvharm_class, (t_method)pvharm_assist, gensym("assist"), 0);
	class_addmethod(pvharm_class, (t_method)pvharm_mute, gensym("mute"), A_DEFFLOAT,0);
	class_addmethod(pvharm_class, (t_method)pvharm_highfreq, gensym("highfreq"), A_DEFFLOAT,0);
	class_addmethod(pvharm_class, (t_method)pvharm_lowfreq, gensym("lowfreq"), A_DEFFLOAT,0);
	class_addmethod(pvharm_class,(t_method)pvharm_overlap,gensym("overlap"),A_FLOAT,0);
	class_addmethod(pvharm_class,(t_method)pvharm_winfac,gensym("winfac"),A_FLOAT,0);
	class_addmethod(pvharm_class,(t_method)pvharm_fftinfo,gensym("fftinfo"),0); 
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void pvharm_free(t_pvharm *x)
{
#if MSP
	dsp_free((t_pxobject *) x);
#endif
	freebytes(x->c_lastphase_in,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->output,0);
	freebytes(x->lastamp,0);
	freebytes(x->lastamp2,0);
	freebytes(x->lastfreq,0);
	freebytes(x->lastfreq2,0);
	freebytes(x->index,0);
	freebytes(x->index2,0);
	freebytes(x->table,0);
}

void pvharm_assist (t_pvharm *x, void *b, long msg, long arg, char *dst)
{
	if (msg==1) {
		switch (arg) {
			case 0: sprintf(dst,"(signal) Input"); break;
			case 1: sprintf(dst,"(signal/float) Pitch Multiplier 1"); break;
			case 2: sprintf(dst,"(signal/float) Pitch Multiplier 2"); break;
			case 3: sprintf(dst,"(signal/float) Synthesis Threshold"); break;
		}
	} else if (msg==2) {
		sprintf(dst,"(signal) Output");
	}
}

void pvharm_overlap(t_pvharm *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;
	pvharm_init(x,1);
}

void pvharm_winfac(t_pvharm *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;
	pvharm_init(x,2);
}

void pvharm_fftinfo(t_pvharm *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 pvharm_highfreq(t_pvharm *x, t_floatarg f)
{
	float curfreq;
	
	if(f < x->lofreq){
		error("current minimum is %f",x->lofreq);
		return;
	}
	if(f > x->R/2 ){
		f = x->R/2;
	}	
	x->hifreq = f;
	x->hi_bin = 1;  
	curfreq = 0;
	while(curfreq < x->hifreq) {
		++(x->hi_bin);
		curfreq += x->c_fundamental;
	}
}

void pvharm_lowfreq(t_pvharm *x, t_floatarg f)
{
	float curfreq;
	
	if(f > x->hifreq){
		error("current maximum is %f",x->lofreq);
		return;
	}
	if(f < 0 ){
		f = 0;
	}	
	x->lofreq = f;
	x->lo_bin = 0;  
	curfreq = 0;
	while( curfreq < x->lofreq ) {
		++(x->lo_bin);
		curfreq += x->c_fundamental ;
	}
}

void *pvharm_new(t_symbol *s, int argc, t_atom *argv)
{
	//  int i;
#if MSP
	t_pvharm *x = (t_pvharm *)newobject(pvharm_class);
	dsp_setup((t_pxobject *)x,4);
	outlet_new((t_pxobject *)x, "signal");
#endif
#if PD
	t_pvharm *x = (t_pvharm *)pd_new(pvharm_class);
	inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
	inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
	inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
	outlet_new(&x->x_obj, gensym("signal"));
#endif
	
	x->vs = sys_getblksize();
	x->R = sys_getsr();
	
	x->lofreq = atom_getfloatarg(0,argc,argv);
	x->hifreq = atom_getfloatarg(1,argc,argv);
	x->overlap = atom_getfloatarg(2,argc,argv);
	x->winfac = atom_getfloatarg(3,argc,argv);
	if(x->lofreq <0 || x->lofreq> 22050)
		x->lofreq = 0;
	if(x->hifreq <50 || x->hifreq> 22050)
		x->hifreq = 4000;
    
	if(!power_of_two(x->overlap))
		x->overlap = 4;
	if(!power_of_two(x->winfac))
		x->winfac = 2;
	
	pvharm_init(x,0);
	return (x);
}

void pvharm_init(t_pvharm *x, short initialized)
{
	int i;
	float curfreq;
	
	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->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->inCount = -(x->Nw);
	x->mult = 1. / (float) x->N;
	x->Iinv = 1./x->D;
	x->c_fundamental =  (float) x->R/(float)((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;
    
	if(!initialized){
		x->P = .5 ; // for testing purposes
		x->P2 = .6666666666 ; // for testing purposes
  		x->L = 8192 ;
  		x->synt = .00005;
  		x->mute = 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->lastamp = (float *) getbytes((MAX_N+1) * sizeof(float));
		x->lastfreq = (float *) getbytes((MAX_N+1) * sizeof(float));
		x->lastamp2 = (float *) getbytes((MAX_N+1) * sizeof(float));
		x->lastfreq2 = (float *) getbytes((MAX_N+1) * sizeof(float));
		x->index = (float *) getbytes((MAX_N+1) * sizeof(float));
		x->index2 = (float *) getbytes((MAX_N+1) * sizeof(float));
		x->table = (float *) getbytes(x->L * sizeof(float));
		x->c_lastphase_in = (float *) getbytes((MAX_N2+1) * sizeof(float));
	}
	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->lastamp,0,(x->N+1) * sizeof(float));
	memset((char *)x->lastfreq,0,(x->N+1) * sizeof(float));
	memset((char *)x->lastamp2,0,(x->N+1) * sizeof(float));
	memset((char *)x->lastfreq2,0,(x->N+1) * sizeof(float));
	memset((char *)x->index,0,(x->N+1) * sizeof(float));
	memset((char *)x->index2,0,(x->N+1) * sizeof(float));
	
	x->myPInc = x->P * x->L/x->R;
	x->myPInc2 = x->P2 * x->L/x->R;
	x->ffac = x->P * PI/x->N;
	if(x->hifreq < x->c_fundamental) {
		x->hifreq = 3000.0 ;
	}
	x->hi_bin = 1;  
	curfreq = 0;
	while(curfreq < x->hifreq) {
		++(x->hi_bin);
		curfreq += x->c_fundamental ;
	}
	if( x->hi_bin >= x->N2 ){
		x->hi_bin = x->N2 - 1;
	}
	x->lo_bin = 0;  
	curfreq = 0;
	while(curfreq < x->lofreq) {
		++(x->lo_bin);
		curfreq += x->c_fundamental ;
	}
	
	for (i = 0; i < x->L; i++) {
		x->table[i] = (float) x->N * cos((float)i * TWOPI / (float)x->L);
	}
	init_rdft( x->N, x->bitshuffle, x->trigland);
	makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
	
}

t_int *pvharm_perform(t_int *w)
{
	int i,j, in,on;
	int    amp,freq,chan;  
	int breaker = 0;
	float    a,ainc,f,finc,address;
	float tmpfreq;
	t_pvharm *x = (t_pvharm *) (w[1]);
	t_float *inbuf = (t_float *)(w[2]);
	t_float *in2 = (t_float *)(w[3]);
	t_float *in3 = (t_float *)(w[4]);
	t_float *in4 = (t_float *)(w[5]);
	t_float *outbuf = (t_float *)(w[6]);
	t_int n = w[7];
	
	int D = x->D;
	int I = D;
	int R = x->R;
	int Nw = x->Nw;
	int N = x->N ;
	int N2 = x-> N2;
	int Nw2 = x->Nw2;
	int L = x->L;
	float fundamental = x->c_fundamental;
	float factor_in =  x->c_factor_in;
	float factor_out = x->c_factor_out;
	int *bitshuffle = x->bitshuffle;
	float *trigland = x->trigland;
	float mult = x->mult;	  		
	float synt = x->synt;
	float P  = x->P; 
	float P2  = x->P2; 
	float Iinv = x->Iinv;
	float myPInc = x->myPInc;
	float myPInc2 = x->myPInc2;
	float *table = x->table;
	float *lastamp = x->lastamp;
	float *lastamp2 = x->lastamp2;
	float *lastfreq = x->lastfreq;
	float *lastfreq2 = x->lastfreq2;
	float *bindex = x->index;
	float *bindex2 = x->index2;
	float *lastphase_in = x->c_lastphase_in;
	//  float *lastphase_out = x->c_lastphase_out;
	float *Wanal = x->Wanal;
	float *Wsyn = x->Wsyn;
	float *input = x->input;
	float *Hwin = x->Hwin;
	float *buffer = x->buffer;
	float *channel = x->channel;
	float *output = x->output;
	int hi_bin = x->hi_bin;
	int lo_bin = x->lo_bin;
	in = on = x->inCount ;
	
	if( x->mute ){
		for ( j = 0; j < n; j++ ){
			*outbuf++ = 0.0;
		}
		return (w+8);
	}
	
	
	if( x->synt_connected ){
		synt = *in4++;
	}
	if( x->pitch1_connected) {
		P = *in2++;
		myPInc = P * x->L/x->R;
	}
	if( x->pitch2_connected) {
		P2 = *in3++;
		myPInc2 = P2 * x->L/x->R;
	}
	in += D;
	on += I;
	
	for ( j = 0 ; j < (Nw - D) ; j++ ){
		input[j] = input[j+D];
	}
	for ( j = (Nw-D), i = 0 ; j < Nw; j++, i++ ) {
		input[j] = *inbuf++;
	}
	
	fold( input, Wanal, Nw, buffer, N, in );
	rdft( N, 1, buffer, bitshuffle, trigland );
	convert( buffer, channel, N2, lastphase_in, fundamental, factor_in );
	
	
	for ( chan = lo_bin; chan < hi_bin; chan++ ) {
		
		freq = ( amp = ( chan << 1 ) ) + 1;
		if ( channel[amp] < synt ){ 
			breaker = 1;
		}
		if( breaker ) {
			breaker = 0 ;
		} else {
			tmpfreq = channel[freq] * myPInc;
			finc = ( tmpfreq - ( f = lastfreq[chan] ) )*Iinv;
			ainc = ( channel[amp] - ( a = lastamp[chan] ) )*Iinv;
			address = bindex[chan];
			for ( n = 0; n < I; n++ ) {
				output[n] += a*table[ (int) address ];
				address += f;
				while ( address >= L )
					address -= L;
				while ( address < 0 )
					address += L;
				a += ainc;
				f += finc;
			}
			lastfreq[chan] = tmpfreq;
			lastamp[chan] = channel[amp];
			bindex[chan] = address;
			// OSC BANK 2
			tmpfreq = channel[freq] * myPInc2;
			finc = ( tmpfreq - ( f = lastfreq2[chan] ) )*Iinv;
			ainc = ( channel[amp] - ( a = lastamp2[chan] ) )*Iinv;
			address = bindex2[chan];
			for ( n = 0; n < I; n++ ) {
				output[n] += a*table[ (int) address ];
				
				address += f;
				while ( address >= L )
					address -= L;
				while ( address < 0 )
					address += L;
				a += ainc;
				f += finc;
			}
			lastfreq2[chan] = tmpfreq;
			lastamp2[chan] = channel[amp];
			bindex2[chan] = address;
			
		}
	}
	
	for ( j = 0; j < D; j++ ){
		*outbuf++ = output[j] * mult;
	}
	for ( j = 0; j < Nw - D; j++ ){
		output[j] = output[j+D];
	}
	
	for ( j = Nw - D; j < Nw; j++ ){
		output[j] = 0.;
	}	
	
	x->P = P;
	x->P2 = P2;
	x->inCount = in;
	return (w+8);
}		

#if MSP
void pvharm_float(t_pvharm *x, double f) // Look at floats at inlets
{
	int inlet = x->x_obj.z_in;
	
	if (inlet == 1)
    {
		x->P = f;
		x->myPInc = x->P*x->L/x->R;
		
    }
	else if (inlet == 2)
    {
		x->P2 = f;
		x->myPInc2 = x->P2*x->L/x->R;
    }
	else if (inlet == 3)
    {
		x->synt = f;
    }
	
}
#endif

void pvharm_mute(t_pvharm *x, t_floatarg state)
{
	x->mute = (short)state;	
}

void pvharm_dsp(t_pvharm *x, t_signal **sp, short *count)
{
#if MSP
	x->pitch1_connected = count[1];
	x->pitch2_connected = count[2];
	x->synt_connected = count[3];
#endif
#if PD
	x->pitch1_connected = 1;
	x->pitch2_connected = 1;
	x->synt_connected = 1;
#endif
	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;
		pvharm_init(x,1);
	}
	//  post("pvharm: sampling rate is %f",sp[0]->s_sr );
	dsp_add(pvharm_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);
}


--- NEW FILE: pvoc~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *pvoc_class;
#endif 

#if PD
static t_class *pvoc_class;
#endif

#define OBJECT_NAME "pvoc~"

typedef struct _pvoc
{
#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;
	// for convert
	float *c_lastphase_in;
	float *c_lastphase_out;
	float c_fundamental;
	float c_factor_in;
	float c_factor_out;
	
	// for oscbank
	int NP;
	float P;
	int L;
	int first;
	float Iinv;
	float *lastamp;
	float *lastfreq;
	float *index;
	float *table;
	float myPInc;
	float ffac;
	//
	float lofreq;
	float hifreq;
	int lo_bin;
	int hi_bin;
	float topfreq;
	float synt;
	// for fast fft
	float mult; 
	float *trigland;
	int *bitshuffle;
	//
	int bypass_state;
	int pitch_connected;
	int synt_connected;
	int overlap;
	int winfac;
	short mute;
} t_pvoc;

void *pvoc_new(t_symbol *s, int argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *pvoc_perform(t_int *w);
void pvoc_dsp(t_pvoc *x, t_signal **sp, short *count);
void pvoc_assist(t_pvoc *x, void *b, long m, long a, char *s);
void pvoc_bypass(t_pvoc *x, t_floatarg state);//Pd does not accept A_LONG
void pvoc_float(t_pvoc *x, double f);
void pvoc_free(t_pvoc *x);
void pvoc_mute(t_pvoc *x, t_floatarg tog);
void pvoc_init(t_pvoc *x, short initialized);
void pvoc_lowfreq(t_pvoc *x, t_floatarg f);
void pvoc_highfreq(t_pvoc *x, t_floatarg f);
void pvoc_overlap(t_pvoc *x, t_floatarg o);
void pvoc_winfac(t_pvoc *x, t_floatarg f);
void pvoc_fftinfo(t_pvoc *x);;

#if PD
/* Pd Initialization */
void pvoc_tilde_setup(void)
{
	pvoc_class = class_new(gensym("pvoc~"), (t_newmethod)pvoc_new, 
						   (t_method)pvoc_free ,sizeof(t_pvoc), 0,A_GIMME,0);
	CLASS_MAINSIGNALIN(pvoc_class, t_pvoc, x_f);
	class_addmethod(pvoc_class, (t_method)pvoc_dsp, gensym("dsp"), 0);
	class_addmethod(pvoc_class, (t_method)pvoc_mute, gensym("mute"), A_DEFFLOAT,0);
	class_addmethod(pvoc_class, (t_method)pvoc_bypass, gensym("bypass"), A_DEFFLOAT,0);
	class_addmethod(pvoc_class, (t_method)pvoc_highfreq, gensym("highfreq"), A_DEFFLOAT,0);
	class_addmethod(pvoc_class, (t_method)pvoc_lowfreq, gensym("lowfreq"), A_DEFFLOAT,0);
	class_addmethod(pvoc_class, (t_method)pvoc_overlap, gensym("overlap"), A_DEFFLOAT,0);
	class_addmethod(pvoc_class, (t_method)pvoc_winfac, gensym("winfac"), A_DEFFLOAT,0);
	class_addmethod(pvoc_class, (t_method)pvoc_fftinfo, gensym("fftinfo"),0);
	class_addmethod(pvoc_class, (t_method)pvoc_assist, gensym("assist"), 0);
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if MSP
void main(void)
{
	setup((t_messlist **)&pvoc_class, (method)pvoc_new, (method)pvoc_free, (short)sizeof(t_pvoc), 0L, A_GIMME, 0);
	addmess((method)pvoc_dsp, "dsp", A_CANT, 0);
	addmess((method)pvoc_assist,"assist",A_CANT,0);
	addmess((method)pvoc_bypass,"bypass",A_DEFFLOAT,0);
	addmess((method)pvoc_mute,"mute",A_DEFFLOAT,0);
	addmess((method)pvoc_lowfreq,"lowfreq",A_DEFFLOAT,0);
	addmess((method)pvoc_highfreq,"highfreq",A_DEFFLOAT,0);
	addmess((method)pvoc_fftinfo,"fftinfo",0);
	addmess((method)pvoc_overlap, "overlap",  A_DEFFLOAT, 0);
	addmess((method)pvoc_winfac, "winfac",  A_DEFFLOAT, 0);
	addfloat((method)pvoc_float);
	dsp_initclass();
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void pvoc_mute(t_pvoc *x, t_floatarg tog)
{
	x->mute = (short)tog;
}

void pvoc_overlap(t_pvoc *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;
	pvoc_init(x,1);
}

void pvoc_winfac(t_pvoc *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;
	pvoc_init(x,2);
}

void pvoc_fftinfo(t_pvoc *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 pvoc_free(t_pvoc *x ){
#if MSP
	dsp_free((t_pxobject *) x);
#endif
	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->output,0);
	freebytes(x->lastamp,0);
	freebytes(x->lastfreq,0);
	freebytes(x->index,0);
	freebytes(x->table,0);
}

/*MSP only but Pd crashes without it 
maybe because of function definition???
*/
void pvoc_assist (t_pvoc *x, void *b, long msg, long arg, char *dst)
{
	if (msg==1) {
		switch (arg) {
			case 0: sprintf(dst,"(signal) Input"); break;
			case 1: sprintf(dst,"(signal/float) Pitch Modification Factor"); break;
			case 2: sprintf(dst,"(signal/float) Synthesis Threshold"); break;
		}
	} else if (msg==2) {
		sprintf(dst,"(signal) Output");
	}
}

void pvoc_highfreq(t_pvoc *x, t_floatarg f)
{
	float curfreq;
	
	if(f < x->lofreq){
		error("current minimum is %f",x->lofreq);
		return;
	}
	if(f > x->R/2 ){
		f = x->R/2;
	}	
	x->hifreq = f;
	x->hi_bin = 1;  
	curfreq = 0;
	while(curfreq < x->hifreq) {
		++(x->hi_bin);
		curfreq += x->c_fundamental;
	}
}

void pvoc_lowfreq(t_pvoc *x, t_floatarg f)
{
	float curfreq;
	
	if(f > x->hifreq){
		error("current maximum is %f",x->lofreq);
		return;
	}
	if(f < 0 ){
		f = 0;
	}	
	x->lofreq = f;
	x->lo_bin = 0;  
	curfreq = 0;
	while( curfreq < x->lofreq ) {
		++(x->lo_bin);
		curfreq += x->c_fundamental ;
	}
}


void pvoc_init(t_pvoc *x, short initialized)
{
	int i;
	float curfreq;
	
	if(!x->R)//temp init if MSP functions returned zero
		x->R = 44100;
	if(!x->D)
		x->D = 256;
	if(x->P <= 0)
		x->P = 1.0;
	if(!power_of_two(x->overlap))
		x->overlap = 4;
	if(!power_of_two(x->winfac))
		x->winfac = 2;
	x->N = x->D * x->overlap;
	x->Nw = x->N * x->winfac;
	limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
	x->N2 = x->N / 2;
	x->Nw2 = x->Nw / 2;
	x->inCount = -(x->Nw);
	x->bypass_state = 0;
	x->mult = 1. / (float) x->N;
	x->pitch_connected = 0;
	x->synt_connected = 0;
	x->mute = 0;
	x->synt = .000001;
	x->L = 8192 ;
	x->c_fundamental =  (float) x->R/(float)( (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;
	x->Iinv = 1./x->D;
	x->myPInc = x->P*x->L/x->R;
	x->ffac = x->P * PI/x->N;
	
	if(!initialized){
		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->lastamp = (float *) getbytes( (MAX_N+1) * sizeof(float) );
		x->lastfreq = (float *) getbytes( (MAX_N+1) * sizeof(float) );
		x->index = (float *) getbytes( (MAX_N+1) * sizeof(float) );
		x->table = (float *) getbytes( x->L * sizeof(float) );
		x->P = 1.0;
		x->ffac = x->P * PI/MAX_N;
	} 
	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));
	memset((char *)x->lastamp,0,(x->N+1) * sizeof(float));
	memset((char *)x->lastfreq,0,(x->N+1) * sizeof(float));
	memset((char *)x->index,0,(x->N+1) * sizeof(float));
		
	for ( i = 0; i < x->L; i++ ) {
		x->table[i] = (float) x->N * cos((float)i * TWOPI / (float)x->L);
	}
	init_rdft( x->N, x->bitshuffle, x->trigland);
	makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
	
	if( x->hifreq < x->c_fundamental ) {
		x->hifreq = 3000.0 ;
	}
	x->hi_bin = 1;  
	curfreq = 0;
	while( curfreq < x->hifreq ) {
		++(x->hi_bin);
		curfreq += x->c_fundamental ;
	}
	
	x->lo_bin = 0;  
	curfreq = 0;
	while( curfreq < x->lofreq ) {
		++(x->lo_bin);
		curfreq += x->c_fundamental ;
	}
	
}

void *pvoc_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
	t_pvoc *x = (t_pvoc *)newobject(pvoc_class);
	dsp_setup((t_pxobject *)x,3);
	outlet_new((t_pxobject *)x, "signal");
#endif
	
#if PD
	t_pvoc *x = (t_pvoc *)pd_new(pvoc_class);
	inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
	inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
	outlet_new(&x->x_obj, gensym("signal"));
#endif
	
	x->lofreq = atom_getfloatarg(0,argc,argv);
	x->hifreq = atom_getfloatarg(1,argc,argv);
	x->overlap = atom_getfloatarg(2,argc,argv);
	x->winfac = atom_getfloatarg(3,argc,argv);
	
	if(x->lofreq <0 || x->lofreq> 22050)
		x->lofreq = 0;
	if(x->hifreq <50 || x->hifreq> 22050)
		x->hifreq = 4000;
    
    
	if(!power_of_two(x->overlap)){
		x->overlap = 4;
	}
	if(!power_of_two(x->winfac)){
		x->winfac = 2;
	}
	x->R = sys_getsr();
	x->D = sys_getblksize();
	
	pvoc_init(x,0);
	
	return (x);
}

t_int *pvoc_perform(t_int *w)
{
	int 	i,j, in,on;
	int    amp,freq,chan,L = 8192;
	
	float    a,ainc,f,finc,address;
	int breaker = 0;
	t_pvoc *x = (t_pvoc *) (w[1]);
	t_float *inbuf = (t_float *)(w[2]);
	t_float *in2 = (t_float *)(w[3]);
	t_float *in3 = (t_float *)(w[4]);
	t_float *outbuf = (t_float *)(w[5]);
	t_int n = w[6];
	
	int D = x->D;
	int I = D;
	int R = x->R;
	int Nw = x->Nw;
	int N = x->N ;
	int N2 = x-> N2;
	int Nw2 = x->Nw2;
	float fundamental = x->c_fundamental;
	float factor_in =  x->c_factor_in;
	float factor_out = x->c_factor_out;
	int *bitshuffle = x->bitshuffle;
	float *trigland = x->trigland;
	float mult = x->mult;	
	float synt = x->synt;
	float P  = x->P; 
	float Iinv = 1./x->D;
	float myPInc = x->myPInc;
	float *table = x->table;
	float *lastamp = x->lastamp ;
	float *lastfreq = x->lastfreq ;
	float *bindex = x->index;
	float *lastphase_in = x->c_lastphase_in;
	float *lastphase_out = x->c_lastphase_out;
	
	float *Wanal = x->Wanal;
	float *Wsyn = x->Wsyn;
	float *input = x->input;
	float *Hwin = x->Hwin;
	float *buffer = x->buffer;
	float *channel = x->channel;
	float *output = x->output;
	int hi_bin = x->hi_bin;
	int lo_bin = x->lo_bin;
	in = on = x->inCount ;
	
	
	if(x->mute){
		while(n--){
			*outbuf++ = 0;
		}
		return w+7;
	}
#if MSP
	if(x->pitch_connected) {
		P  = *in2;
		myPInc = P * (float) x->L / (float)x->R;
	}
	
	if (x->synt_connected) {
		synt = *in3;
	}
#endif
	// Pd has superior float/signal inlet treatment
#if PD
	P = *in2; 
	synt = *in3;
	myPInc = P * (float) x->L / (float)x->R;
#endif
	
	if (x->bypass_state) {
		for( j = 0; j < D; j++ ) {
			*outbuf++ = *inbuf++;
		}
		return w+7;
	}
	
    in = on = x->inCount ;
	
    in += D;
    on += I;
	
    for ( j = 0 ; j < (Nw - D) ; j++ ){
		input[j] = input[j+D];
    }
    for ( j = (Nw-D), i = 0 ; j < Nw; j++, i++ ) {// unneeded loop variable
		input[j] = *inbuf++;
    }
	
    fold( input, Wanal, Nw, buffer, N, in );   
    rdft( N, 1, buffer, bitshuffle, trigland );
    convert( buffer, channel, N2, lastphase_in, fundamental, factor_in );
	
	
    // start osc bank 
	
    for ( chan = lo_bin; chan < hi_bin; chan++ ) {
		
		freq = ( amp = ( chan << 1 ) ) + 1;
		if ( channel[amp] < synt ){ 
			breaker = 1;
		}
		if( breaker ) {
			breaker = 0 ;
		} else {
			channel[freq] *= myPInc;
			finc = ( channel[freq] - ( f = lastfreq[chan] ) )*Iinv;
			ainc = ( channel[amp] - ( a = lastamp[chan] ) )*Iinv;
			address = bindex[chan];
			for ( n = 0; n < I; n++ ) {
				output[n] += a*table[ (int) address ];
				
				address += f;
				while ( address >= L )
					address -= L;
				while ( address < 0 )
					address += L;
				a += ainc;
				f += finc;
			}
			lastfreq[chan] = channel[freq];
			lastamp[chan] = channel[amp];
			bindex[chan] = address;
		}
    }
    
	
    for ( j = 0; j < D; j++ ){
		*outbuf++ = output[j] * mult;
    }
    for ( j = 0; j < Nw - D; j++ ){
		output[j] = output[j+D];
    }
	
    for ( j = Nw - D; j < Nw; j++ ){
		output[j] = 0.;
    }	
	
	
	
    // restore state variables
    x->inCount = in;
	return (w+7);
}	

void pvoc_bypass(t_pvoc *x, t_floatarg state)
{
	x->bypass_state = state;	
}

#if MSP
void pvoc_float(t_pvoc *x, double f) // Look at floats at inlets
{
	int inlet = x->x_obj.z_in;
	
	if (inlet == 1)
    {
		x->P = (float)f;
		x->myPInc = x->P*x->L/x->R;
    }
	else if (inlet == 2)
    {
		x->synt = (float)f;
    }
	
}
#endif


void pvoc_dsp(t_pvoc *x, t_signal **sp, short *count)
{
	
#if MSP // these blew up Pd
	x->pitch_connected = count[1];
	x->synt_connected = count[2];
#endif
	
	if(x->D != sp[0]->s_n || x->R != sp[0]->s_sr ){
		x->D = sp[0]->s_n;
		x->R = sp[0]->s_sr;
		pvoc_init(x,1);
	}
	
	dsp_add(pvoc_perform, 6, x, 
			sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, 
			sp[0]->s_n);
}


--- NEW FILE: reanimator~.c ---
#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);
}



--- NEW FILE: dentist~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *dentist_class;
#endif 

#if PD
static t_class *dentist_class;
#endif

#define OBJECT_NAME "dentist~"

typedef struct _dentist
{
#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;
  //
  short *bin_selection;
  short *last_bin_selection;
  int *active_bins;
  int tooth_count;
  int ramp_frames;
  int frames_left;
  float frame_duration;
  int max_bin;
  //
  float mult; 
  float *trigland;
  int *bitshuffle;
  int overlap;
  int winfac;
  float topfreq;
  float funda;
  //
  void *list_outlet;
  short direct_update;
  short mute;
  t_atom *list_data;
  short interpolate_singles;
  float sync;
} t_dentist;

void *dentist_new(t_symbol *msg, short argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *dentist_perform(t_int *w);
void dentist_dsp(t_dentist *x, t_signal **sp, short *count);
void dentist_assist(t_dentist *x, void *b, long m, long a, char *s);
void set_switch_bins (t_dentist *x, int i);
void reset_shuffle(t_dentist *x);
void dentist_showstate(t_dentist *x);
void dentist_direct_update(t_dentist *x, t_floatarg toggle);
void dentist_mute(t_dentist *x, t_floatarg toggle);
void dentist_setstate(t_dentist *x, t_symbol *msg, short argc, t_atom *argv);
void dentist_ramptime(t_dentist *x, t_floatarg ramp_ms);
int rand_index(int max);
void dentist_init(t_dentist *x, short initialized);
void dentist_bins_pd (t_dentist *x, t_floatarg i);
void dentist_topfreq(t_dentist *x, t_floatarg f);
void dentist_free(t_dentist *x);
void dentist_toothcount(t_dentist *x, t_floatarg newcount);
void dentist_scramble(t_dentist *x);
void dentist_activate_bins(t_dentist *x, t_floatarg f);
void dentist_interpolate_singles(t_dentist *x, t_floatarg f);
void dentist_overlap(t_dentist *x, t_floatarg o);
void dentist_winfac(t_dentist *x, t_floatarg o);
void dentist_fftinfo(t_dentist *x);
void dentist_mute(t_dentist *x, t_floatarg toggle);


#if MSP
void main(void)
{
  setup((t_messlist **)&dentist_class, (method)dentist_new, (method)dsp_free, 
  (short)sizeof(t_dentist), 0, A_GIMME, 0);
  addmess((method)dentist_dsp, "dsp", A_CANT, 0);
  addint((method)set_switch_bins);
//  addbang((method)reset_shuffle);
  addmess((method)dentist_showstate,"showstate",0);
//  addmess((method)dentist_direct_update,"direct_update",A_FLOAT, 0);
  addmess((method)dentist_mute,"mute",A_FLOAT, 0);
  addmess((method)dentist_setstate, "setstate", A_GIMME, 0);
  addmess((method)dentist_ramptime, "ramptime", A_FLOAT, 0);
  addmess((method)dentist_topfreq, "topfreq", A_FLOAT, 0);
  addmess((method)dentist_toothcount, "toothcount", A_FLOAT, 0);
//  addmess((method)dentist_activate_bins, "activate_bins", A_FLOAT, 0);
  addmess((method)dentist_interpolate_singles, "interpolate_singles", A_FLOAT, 0);
  addmess((method)dentist_scramble, "scramble", 0);
  addmess((method)dentist_assist,"assist",A_CANT,0);
  addmess((method)dentist_overlap, "overlap",  A_DEFFLOAT, 0);
  addmess((method)dentist_winfac, "winfac",  A_DEFFLOAT, 0);
  addmess((method)dentist_fftinfo, "fftinfo", 0);
  dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
void dentist_tilde_setup(void)
{
  dentist_class = class_new(gensym("dentist~"), (t_newmethod)dentist_new, 
			 (t_method)dentist_free ,sizeof(t_dentist), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(dentist_class, t_dentist, x_f);
  class_addmethod(dentist_class,(t_method)dentist_dsp,gensym("dsp"),0);
  class_addmethod(dentist_class,(t_method)dentist_mute,gensym("mute"),A_FLOAT,0);
  class_addmethod(dentist_class,(t_method)dentist_showstate,gensym("showstate"),0);
//  class_addmethod(dentist_class,(t_method)dentist_direct_update,gensym("direct_update"),A_FLOAT,0);
  class_addmethod(dentist_class,(t_method)dentist_setstate,gensym("setstate"),A_GIMME,0);
  class_addmethod(dentist_class,(t_method)dentist_ramptime,gensym("ramptime"),A_FLOAT,0);
//  class_addmethod(dentist_class,(t_method)dentist_bins_pd,gensym("dentist_bins"),A_FLOAT,0);
  class_addmethod(dentist_class,(t_method)dentist_topfreq,gensym("topfreq"),A_FLOAT,0);
  class_addmethod(dentist_class,(t_method)dentist_toothcount,gensym("toothcount"),A_FLOAT,0);
  class_addmethod(dentist_class,(t_method)dentist_interpolate_singles,gensym("interpolate_singles"),A_FLOAT, 0);
  class_addmethod(dentist_class,(t_method)dentist_scramble,gensym("scramble"),0);
//  class_addmethod(dentist_class,(t_method)dentist_activate_bins,gensym("activate_bins"),A_FLOAT,0);
  class_addmethod(dentist_class, (t_method)dentist_overlap, gensym("overlap"), A_DEFFLOAT,0);
  class_addmethod(dentist_class, (t_method)dentist_winfac, gensym("winfac"), A_DEFFLOAT,0);
  class_addmethod(dentist_class, (t_method)dentist_fftinfo, gensym("fftinfo"), 0);

  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void dentist_interpolate_singles(t_dentist *x, t_floatarg f)
{
    x->interpolate_singles = (short)f;
//    post("singles interp: %d",x->interpolate_singles);
}

void dentist_free(t_dentist *x)
{
/* Pd might be having difficulty freeing its memory */
#if MSP
    dsp_free((t_pxobject *)x);
#endif
    free(x->Wanal);
    free(x->Wsyn);
    free(x->input);
    free(x->Hwin);
    free(x->buffer);
    free(x->channel);
    free(x->output);
    free(x->bitshuffle);
    free(x->trigland);
    free(x->bin_selection);
    free(x->active_bins);
    free(x->last_bin_selection);
    free(x->list_data);

//post("avoiding freeing memory here");
}

void dentist_overlap(t_dentist *x, t_floatarg f)
{
int o = (int)f;
  if(!power_of_two(o)){
    error("%d is not a power of two",o);
    return;
  }
  x->overlap = o;
  dentist_init(x,1);
}

void dentist_winfac(t_dentist *x, t_floatarg f)
{
int w = (int)f;
  if(!power_of_two(w)){
    error("%d is not a power of two",w);
    return;
  }
  x->winfac = w;
  dentist_init(x,2);
}

void dentist_fftinfo( t_dentist *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 dentist_direct_update( t_dentist *x, t_floatarg toggle)
{
  x->direct_update = (short)toggle;
}

void dentist_mute( t_dentist *x, t_floatarg toggle )
{
  x->mute = (short)toggle;
}

void dentist_assist (t_dentist *x, void *b, long msg, long arg, char *dst)
{
  if (msg==1) {
    switch (arg) {
    case 0:
      sprintf(dst,"(signal) Input ");
      break;
    }
  } else if (msg==2) {
    switch (arg) {
    case 0: sprintf(dst,"(signal) Output"); break;
    case 1: sprintf(dst,"(signal) Interpolation Sync"); break;
    case 2: sprintf(dst,"(list) Current Selected Bins"); break;			
    }
  }
}

void *dentist_new(t_symbol *msg, short argc, t_atom *argv)
{
#if MSP
  t_dentist *x = (t_dentist *)newobject(dentist_class);
  x->list_outlet = listout((t_pxobject *)x);
  dsp_setup((t_pxobject *)x,1);
  outlet_new((t_pxobject *)x, "signal");
  outlet_new((t_pxobject *)x, "signal");
#endif

#if PD
  t_dentist *x = (t_dentist *)pd_new(dentist_class);
  outlet_new(&x->x_obj, gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
  x->list_outlet = outlet_new(&x->x_obj,gensym("list"));
#endif

  // INITIALIZATIONS
	
  x->D = sys_getblksize();
  x->R = sys_getsr(); 
  x->topfreq = atom_getfloatarg(0,argc,argv);
  x->overlap = atom_getfloatarg(1,argc,argv);
  x->winfac = atom_getfloatarg(2,argc,argv);
  if(!power_of_two(x->overlap))
  	x->overlap = 4;
  if(!power_of_two(x->winfac))
  	x->winfac = 1;
  
  dentist_init(x,0);
  return (x);
}

void dentist_topfreq(t_dentist *x, t_floatarg f)
{
float funda = x->funda;
float curfreq;

    if(f < 50 || f > x->R/2.0)
        return;
        
    x->topfreq = f;
    x->max_bin = 1;  
    curfreq = 0;
    while(curfreq < x->topfreq) {
        ++(x->max_bin);
        curfreq += funda ;
    }
}

void dentist_init(t_dentist *x, short initialized)
{
	
	float curfreq;
	int i;
	
    x->N = x->overlap * x->D;
    x->Nw = x->N * x->winfac;	
  limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
	
	x->N2 = (x->N)>>1;
    x->Nw2 = (x->Nw)>>1;
    x->inCount = -(x->Nw);
    
	if(!initialized){
		x->sync = 0;
		x->mute = 0;
		x->direct_update = 0;
		if(x->topfreq < 100)
			x->topfreq = 100.0;
		x->Wanal = (float *) calloc(MAX_Nw, sizeof(float));	
		x->Wsyn = (float *) calloc(MAX_Nw, sizeof(float));	
		x->input = (float *) calloc(MAX_Nw, sizeof(float));	
		x->Hwin = (float *) calloc(MAX_Nw, sizeof(float));
		x->buffer = (float *) calloc(MAX_N, sizeof(float));
		x->channel = (float *) calloc(MAX_N+2, sizeof(float));
		x->output = (float *) calloc(MAX_Nw, sizeof(float));
		x->bitshuffle = (int *) calloc(MAX_N * 2, sizeof(int));
		x->trigland = (float *) calloc(MAX_N * 2, sizeof(float));
		x->bin_selection = (short *) calloc( MAX_N2, sizeof(short));
		x->active_bins = (int *) calloc( MAX_N2, sizeof(int));
		x->last_bin_selection = (short *) calloc( MAX_N2, sizeof(short)) ;
		x->list_data = (t_atom *) calloc( MAX_N + 2, sizeof(t_atom));
		x->tooth_count = 0;
		x->interpolate_singles = 1;
		x->ramp_frames = 0;
		dentist_scramble(x);
	} 
	memset((char *)x->input,0,x->Nw * sizeof(float));
	memset((char *)x->output,0,x->Nw * sizeof(float));
	memset((char *)x->buffer,0,x->N * sizeof(float));
	memset((char *)x->channel,0,(x->N+2) * sizeof(float));

	
    x->mult = 1. / (float) x->N;
    x->frame_duration = (float) x->D / (float) x->R;
    x->frames_left = 0;
    x->funda = (float) x->R / (float) x->N;
    x->max_bin = 1;  
/*    curfreq = 0;
	
    while(curfreq < x->topfreq) {
        ++(x->max_bin);
        curfreq += x->funda;
    }*/
    if(!x->funda){
    	error("%s: zero sampling rate!",OBJECT_NAME);
    	return;
    }
    x->max_bin = (int) (x->topfreq / x->funda);
    if(x->max_bin < 1)
    	x->max_bin = 1;
    
	init_rdft( x->N, x->bitshuffle, x->trigland);
	makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
    
    for( i = 0; i < x->N2; i++) {
        x->last_bin_selection[i] = x->bin_selection[i];
    }
}

t_int *dentist_perform(t_int *w)
{
  int	i,j;
  float oldfrac,newfrac;
  int  tooth_count;

  t_dentist *x = (t_dentist *) (w[1]);
	
  t_float *in = (t_float *)(w[2]);
  t_float *out = (t_float *)(w[3]);
  t_float *sync_vec = (t_float *)(w[4]);
  t_int n = w[5];

  int frames_left = x->frames_left;
  int ramp_frames = x->ramp_frames;
  short *bin_selection = x->bin_selection;
  short *last_bin_selection = x->last_bin_selection;
  /* dereference struncture  */	
  float *input = x->input;
  float *buffer = x->buffer;
  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 *output = x->output;
  float *channel = x->channel;
  float mult = x->mult ;
  int *bitshuffle = x->bitshuffle;
  float *trigland = x->trigland ;
  float sync = x->sync;


  if( x->mute ){
    while( n-- ){
      *out++ = 0.0;
      *sync_vec++ = sync;
    }
    return (w+6);
  }
	
  inCount += D;

  for ( j = 0 ; j < Nw - D ; j++ ){
    input[j] = input[j+D];
  }
  for ( j = Nw - D; j < Nw; j++ ) {
    input[j] = *in++;
  }

  fold( input, Wanal, Nw, buffer, N, inCount );	
  rdft( N, 1, buffer, bitshuffle, trigland );
  leanconvert( buffer, channel, N2 );

  if(frames_left > 0 && ramp_frames > 0) {
    // INTERPOLATE ACCORDING TO POSITION IN RAMP
    oldfrac = (float) frames_left / (float) ramp_frames ;
    sync = newfrac = 1.0 - oldfrac;
    for( i = 0; i < N2 ; i++){
      if( (! bin_selection[i]) && (! last_bin_selection[i]) ){
		channel[i * 2]  = 0;
      } else if (bin_selection[i] && last_bin_selection[i]) {
		// channel[i * 2]  *= 1; NO ACTION
      } else if (bin_selection[i]) {
		channel[i * 2]  *= newfrac;
      } else if (last_bin_selection[i]) {
		channel[i * 2]  *= oldfrac;
      }
    }
    --frames_left;
    if( ! frames_left ){
      // Copy current to last
      for( i = 0; i < N2; i++) {
		last_bin_selection[i] = bin_selection[i];
      }
    }
  } else {
    for( i = 0; i < N2 ; i++){
      if( ! bin_selection[ i ] ){
		channel[ i * 2 ]  = 0;
      }
    }
    oldfrac = 0.0;
    sync = 1.0;
  }
  leanunconvert( channel, buffer,  N2 );
  rdft( N, -1, buffer, bitshuffle, trigland );
  overlapadd( buffer, N, Wsyn, output, Nw, inCount);

  for ( j = 0; j < D; j++ )
    *out++ = output[j] * mult;

  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
			
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;	

  /* restore state variables */
  for(i=0; i < n; i++){
  	sync_vec[i] = sync;
  }
  x->inCount = inCount % Nw;
  x->frames_left = frames_left;
  x->sync = sync;
  return (w+6);
}		


void set_switch_bins (t_dentist *x, int i)
{
  if( i < 0 ){
    i = 0;
  }
  if( i > x->N2 ) {
    i = x->N2;
  }
  x->tooth_count = i;
  if( x->direct_update ){
    reset_shuffle(x);
  }
  return;
}
//identical function for Pd
void dentist_bins_pd (t_dentist *x, t_floatarg i)
{
  if( i < 0 ){
    i = 0;
  }
  if( i > x->N2 ) {
    i = x->N2;
  }
  x->tooth_count = (int)i;
  if(x->direct_update){
    reset_shuffle(x);
  }
  return;
}

// experimental, not to be used
void dentist_activate_bins(t_dentist *x, t_floatarg f)
{
    if(f < 0 || f > x->max_bin){
#if PD
        post("* %d bin out of range",(int)f);
#endif        
        return;
    }
    x->tooth_count = (int)f;
}

void dentist_scramble(t_dentist *x)
{
short *last_bin_selection = x->last_bin_selection;
short *bin_selection = x->bin_selection;
int *active_bins = x->active_bins;
int N2 = x->N2;
int i,tmp,b1,b2;
int maxswap = x->max_bin;
int tooth_count = x->tooth_count;

  /* for(i = 0; i < x->N2; i++){
    last_bin_selection[i] = bin_selection[i];
  }*/
  for(i=0; i<N2; i++){
    bin_selection[i] = 0;
    active_bins[i] = i;
  }
  while(maxswap > 0){
    b1 = maxswap;
    b2 = rand_index(maxswap);
    tmp = active_bins[b1];
    active_bins[b1] = active_bins[b2];
    active_bins[b2] = tmp;
    --maxswap;
  }
  for( i = 0; i < x->tooth_count; i++ ) {
    x->bin_selection[active_bins[i]] = 1;
  }
  x->frames_left = x->ramp_frames;
  if(! x->ramp_frames) {
    for(i = 0; i < N2; i++){
      last_bin_selection[i] = bin_selection[i];
    }
  }    
}


void dentist_toothcount(t_dentist *x, t_floatarg newcount)
{
int i;
int nc = (int) newcount;
int max = x->max_bin;
int tooth_count = x->tooth_count;
int newbin;
int oldbin;

if(nc < 0 || nc > x->N2){
#if PD
    post("* %d out of range",nc);
#endif
#if MSP
    error("%d out of range",nc);
#endif
    return;
}
  /* for(i = 0; i < x->N2; i++){
    x->last_bin_selection[i] = x->bin_selection[i];
  }*/
  if(nc < x->tooth_count){
    for(i = nc; i < tooth_count; i++){
        x->bin_selection[x->active_bins[i]] = 0;
    }
  } else {
    for(i = tooth_count; i < nc; i++){
        x->bin_selection[x->active_bins[i]] = 1;
    }
  }
  // if immediate reset
  if(x->interpolate_singles){
//  post("setting frames left");
    x->frames_left = x->ramp_frames;
  }
  if(! x->ramp_frames) {
    for(i = 0; i < x->N2; i++){
      x->last_bin_selection[i] = x->bin_selection[i];
    }
  }
  x->tooth_count = nc;
}


void reset_shuffle (t_dentist *x)
{
  int i;
  int temp, p1, p2;
  int max;

  max = x->max_bin;
  for(i = 0; i < x->N2; i++){
    x->last_bin_selection[i] = x->bin_selection[i];
    x->bin_selection[i] = 0;
  }
  for(i = 0; i < x->max_bin; i++) {
    x->active_bins[i] = rand_index(max);
    x->bin_selection[x->active_bins[i]] = 1;
  }
  x->frames_left = x->ramp_frames;
  if(! x->ramp_frames) { // Ramp Off - Immediately set last to current
    for( i = 0; i < x->N2; i++ ){
      x->last_bin_selection[ i ] = x->bin_selection[ i ];
    }
  }
}

int rand_index(int max) {
  return (rand() % max);
}

void dentist_setstate (t_dentist *x, t_symbol *msg, short argc, t_atom *argv) {
  short i;
  int selex;
  
  short *last_bin_selection = x->last_bin_selection;
  short *bin_selection = x->bin_selection;
  int *active_bins = x->active_bins;
  x->tooth_count = argc;
  
  for(i = 0; i < x->N2; i++){
    last_bin_selection[i] = bin_selection[i]; // needed here
    bin_selection[i] = 0;
  }

  for (i=0; i < argc; i++) {
    selex = atom_getfloatarg(i,argc,argv);
    if (selex < x->N2 && selex >= 0 ) {
      active_bins[i] = selex;
      bin_selection[selex] = 1;
    } else {
      post ("%d out of range bin",selex);
    }		
  }


  x->frames_left = x->ramp_frames;
  if(! x->ramp_frames) { // Ramp Off - Immediately set last to current
    for(i = 0; i < x->N2; i++){
      last_bin_selection[i] = bin_selection[i];
    }
  }

  return;
}
void dentist_ramptime (t_dentist *x, t_floatarg ramp_ms) {
	
  if(ramp_ms <= 0){
    x->ramp_frames = 0;
    return;
  }
  
  x->frames_left = x->ramp_frames = (int)(ramp_ms * .001 / x->frame_duration);
  return;
}
// REPORT CURRENT SHUFFLE STATUS
void dentist_showstate (t_dentist *x) {

  t_atom *list_data = x->list_data;

  short i, count;
  float data;

  count = 0;
  for(i = 0; i < x->tooth_count; i++ ) {
    data = x->active_bins[i];
#if MSP
      SETLONG(list_data+count,x->active_bins[i]);
 #endif
 #if PD
        SETFLOAT(list_data+count,data);
 #endif
      ++count;
  }	
  outlet_list(x->list_outlet,0,x->tooth_count,list_data);

  return;
}
void dentist_dsp(t_dentist *x, t_signal **sp, short *count)
{
  long i;
  if(x->R != sp[0]->s_sr || x->D != sp[0]->s_n){
    x->R = sp[0]->s_sr;
    x->D = sp[0]->s_n;
    dentist_init(x,1);
  }
  dsp_add(dentist_perform, 5, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
}


--- NEW FILE: codepend~.c ---
#include "MSPd.h"

#include "fftease.h"

#if MSP
void *codepend_class;
#endif
#if PD
static t_class *codepend_class;
#endif

#define OBJECT_NAME "codepend~"


/*
  Adding -32dB pad for invert option. Also added latency mechanism in
  switching from normal to "invert" to avoid glitches from extreme
  amplitude disparities.

  Made all inlets of type signal (with float options).

  Threshold input is now linear, not dB (with Max doing the conversion
  if desired).

  -EL 10/1/2005

*/

typedef struct _codepend
{
#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;
  int invert;
  int *bitshuffle;
    
  float threshold;
  float exponent;
  float *Wanal;	
  float *Wsyn;	
  float *inputOne;
  float *inputTwo;
  float *Hwin;
  float *bufferOne;
  float *bufferTwo;
  float *channelOne;
  float *channelTwo;
  float *output;
  float mult; 
  float *trigland;

  short connected[8];
  short mute;
  int overlap;//overlap factor
  int winfac;//window factor
  int vs;//vector size  
  int invert_countdown; // delay onset of invert effect to avoid loud glitches
  int invert_nextstate;// next state for invert   
  float invert_pad;   	
} t_codepend;


/* msp function prototypes */

void *codepend_new(t_symbol *s, int argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *codepend_perform(t_int *w);
void codepend_dsp(t_codepend *x, t_signal **sp, short *count);
void codepend_assist(t_codepend *x, void *b, long m, long a, char *s);
void codepend_dest(t_codepend *x, double f);
void codepend_invert(t_codepend *x, t_floatarg toggle);
void codepend_free(t_codepend *x);
void codepend_mute(t_codepend *x, t_floatarg toggle);
void codepend_fftinfo(t_codepend *x);
void codepend_tilde_setup(void);
void codepend_winfac(t_codepend *x, t_floatarg o);
void codepend_overlap(t_codepend *x, t_floatarg o);
void codepend_init(t_codepend *x, short initialized);
void codepend_pad(t_codepend *x, t_floatarg pad);


#if MSP
void main(void)
{
  setup( (struct messlist **) &codepend_class, (void *) codepend_new,
	 (method)dsp_free, (short) sizeof(t_codepend),
	 0, A_GIMME, 0);
  
  addmess((method)codepend_dsp, "dsp", A_CANT, 0);
  addmess((method)codepend_assist,"assist",A_CANT,0);    
  addmess((method)codepend_invert,"invert", A_FLOAT, 0);  
  
  addmess((method)codepend_mute,"mute", A_FLOAT, 0);
  addmess((method)codepend_pad,"pad", A_FLOAT, 0);
  addmess((method)codepend_overlap,"overlap", A_FLOAT, 0);
  addmess((method)codepend_winfac,"winfac", A_FLOAT, 0);
  addmess((method)codepend_fftinfo,"fftinfo", 0);
  addfloat((method) codepend_dest);
  dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}

/* float input handling routine (MSP only)*/
void codepend_dest(t_codepend *x, double df)
{
float f = (float) df;
int inlet = x->x_obj.z_in;

  if ( inlet == 2 ) {
    x->exponent = f;	
  }
	
  if ( inlet == 3 ){
    /* x->threshold = (float) (pow( 10., (f * .05))); */
    x->threshold = f;
  }
}
#endif

#if PD
void codepend_tilde_setup(void)
{
  codepend_class = class_new(gensym("codepend~"), (t_newmethod)codepend_new, 
			     (t_method)codepend_free ,sizeof(t_codepend), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(codepend_class, t_codepend, x_f);
  class_addmethod(codepend_class, (t_method)codepend_dsp, gensym("dsp"), 0);
  class_addmethod(codepend_class, (t_method)codepend_assist, gensym("assist"), 0);
  class_addmethod(codepend_class, (t_method)codepend_invert, gensym("invert"), A_FLOAT,0);
  
  class_addmethod(codepend_class, (t_method)codepend_mute, gensym("mute"), A_FLOAT,0);
  class_addmethod(codepend_class, (t_method)codepend_pad, gensym("pad"), A_FLOAT,0);
  class_addmethod(codepend_class, (t_method)codepend_overlap, gensym("overlap"), A_FLOAT,0);
  class_addmethod(codepend_class, (t_method)codepend_winfac, gensym("winfac"), A_FLOAT,0);
  class_addmethod(codepend_class, (t_method)codepend_fftinfo, gensym("fftinfo"), A_CANT,0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif


void codepend_mute(t_codepend *x, t_floatarg toggle)
{
  x->mute = (short)toggle;
//  post("mute set to %f, %d",toggle,x->mute);
}

void codepend_overlap(t_codepend *x, t_floatarg o)
{
  if(!power_of_two((int)o)){
    error("%f is not a power of two",o);
    return;
  }
  x->overlap = (int)o;
  codepend_init(x,1);
}

void codepend_winfac(t_codepend *x, t_floatarg f)
{
  if(!power_of_two((int)f)){
    error("%f is not a power of two",f);
    return;
  }
  x->winfac = (int)f;
  codepend_init(x,1);
}

void codepend_fftinfo( t_codepend *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 codepend_free(t_codepend *x)
{
#if MSP
  dsp_free((t_pxobject *) x);
#endif
  free(x->trigland);
  free(x->bitshuffle);
  free(x->Wanal);
  free(x->Wsyn);
  free(x->Hwin);
  free(x->inputOne);
  free(x->inputTwo);
  free(x->bufferOne);
  free(x->bufferTwo);
  free(x->channelOne);
  free(x->channelTwo);
  free(x->output);
}

void codepend_pad(t_codepend *x, t_floatarg pad)
{
	x->invert_pad = pad;
	codepend_invert(x,x->invert);//resubmit to invert
}

void codepend_invert(t_codepend *x, t_floatarg toggle)
{

  x->invert_nextstate = (short)toggle;
  x->invert_countdown = x->overlap; // delay effect for "overlap" vectors
	
  if(x->invert_nextstate){ // lower gain immediately; delay going to invert
    x->mult = (1. / (float) x->N) * x->invert_pad;
  } else {
    x->invert = 0; //immediately turn off invert; delay raising gain
  }

}

void codepend_assist (t_codepend *x, void *b, long msg, long arg, char *dst)
{

  if (msg == 1) {

    switch (arg) {
    case 0:		sprintf(dst,"(signal) Input One");break;
    case 1:		sprintf(dst,"(signal) Input Two"); break;
    case 2:		sprintf(dst,"(signal/float) Scaling Exponent"); break;
    case 3:		sprintf(dst,"(signal/float) Inverse Threshold"); break;
    }
  }

  else {

    if (msg == 2)
      sprintf(dst,"(signal) Output");

  }
}


void *codepend_new(t_symbol *s, int argc, t_atom *argv)
{

#if MSP
  t_codepend 	*x = (t_codepend *) newobject(codepend_class);
  dsp_setup((t_pxobject *)x,4);
  outlet_new((t_pxobject *)x, "signal");
  // x->x_obj.z_misc |= Z_NO_INPLACE; // probably not needed
#endif
#if PD
  t_codepend *x = (t_codepend *)pd_new(codepend_class);
  /* add three additional signal inlets */
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
#endif


  /* optional arguments: scaling exponent, threshold (now linear), overlap, winfac */
  x->exponent = atom_getfloatarg(0,argc,argv);
  x->threshold = atom_getfloatarg(1,argc,argv);
  x->overlap = atom_getfloatarg(2,argc,argv);
  x->winfac = atom_getfloatarg(3,argc,argv);

  /*	
    x->threshold = (float) pow(10.0,(x->threshold * .05));
  */
  /* sanity check */
  if(x->exponent < 0.25)
    x->exponent = 0.25;

  if(!power_of_two(x->overlap)){
    x->overlap = 4;
  }
  if(!power_of_two(x->winfac)){
    x->winfac = 1;
  }
  		
  x->vs = sys_getblksize();
  x->R = sys_getsr();
 
  codepend_init(x,0);

  return (x);
}

void codepend_init(t_codepend *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->N2 = (x->N)>>1;
  x->Nw2 = (x->Nw)>>1;
  x->inCount = -(x->Nw);
  x->mult = 1. / (float) x->N;
  if(!initialized){
	x->invert_pad = 0.025; // -32 dB
    x->invert_countdown = 0;
    x->mute = 0;
    x->invert = 0;
    x->Wanal = (float *) calloc(MAX_Nw, sizeof(float));	
    x->Wsyn = (float *) calloc(MAX_Nw, sizeof(float));	
    x->Hwin = (float *) calloc(MAX_Nw, sizeof(float));
    x->inputOne = (float *) calloc(MAX_Nw, sizeof(float));	
    x->inputTwo = (float *) calloc(MAX_Nw, sizeof(float));
    x->bufferOne = (float *) calloc(MAX_N, sizeof(float));
    x->bufferTwo = (float *) calloc(MAX_N, sizeof(float));
    x->channelOne = (float *) calloc(MAX_N+2, sizeof(float));
    x->channelTwo = (float *) calloc(MAX_N+2, sizeof(float));
    x->output = (float *) calloc(MAX_Nw, sizeof(float));
    x->bitshuffle = (int *) calloc(MAX_N * 2, sizeof(int));
    x->trigland = (float *) calloc(MAX_N * 2, sizeof(float));
  }
		memset((char *)x->inputOne,0,x->Nw);
		memset((char *)x->inputTwo,0,x->Nw);
		memset((char *)x->output,0,x->Nw);
		memset((char *)x->bufferOne,0,x->N);
		memset((char *)x->bufferTwo,0,x->N);
		memset((char *)x->channelOne,0,(x->N+2));
		memset((char *)x->channelTwo,0,(x->N+2));
 
    if(x->invert){
      x->mult *= x->invert_pad;
    }
  init_rdft( x->N, x->bitshuffle, x->trigland);
  makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 1);
  
}


t_int *codepend_perform(t_int *w)
{

  int		
    i,j,
    inCount,
    R,
    N,
    N2,
    D,
    Nw,
    invert = 0,
    even, odd,
    *bitshuffle;

  float		maxamp,	
    threshold = 1.,
    mult,
    exponent,
    a1, b1,
    a2, b2,
    *inputOne,
    *inputTwo,
    *bufferOne,
    *bufferTwo,
    *output,
    *Wanal,
    *Wsyn,
    *channelOne,
    *channelTwo,
    *trigland;



  /* get our inlets and outlets */
	
  t_codepend *x = (t_codepend *) (w[1]);
  t_float *inOne = (t_float *)(w[2]);
  t_float *inTwo = (t_float *)(w[3]);
  t_float *vec_exponent = (t_float *)(w[4]);
  t_float *vec_threshold = (t_float *)(w[5]);
  t_float *out = (t_float *)(w[6]);
  t_int n = w[7];

  short *connected = x->connected;
  /* dereference structure  */	
  if(connected[2])
    x->exponent = *vec_exponent;
  if(connected[3]){
    x->threshold = *vec_threshold;
    /*
      x->threshold = (float) (pow( 10., (x->threshold * .05)));
    */
  }
  
  if(x->mute){
	while(n--)
		*out++ = 0.0;
	return w+8;
  }
  // do countdown
  if(x->invert_countdown > 0){
  
    if(x->invert) { // we 
    } else {
    }  
    --(x->invert_countdown);
    if(! x->invert_countdown){ // countdown just ended
      if(x->invert_nextstate){ // moving to invert (gain is already down)
		x->invert = x->invert_nextstate;
      } else { // invert is already off - now reset gain
		x->mult = 1. / (float) x->N;
      }
    }
  }

  inputOne = x->inputOne;
  inputTwo = x->inputTwo;
  bufferOne = x->bufferOne;
  bufferTwo = x->bufferTwo;
  inCount = x->inCount;
  R = x->R;
  N = x->N;
  N2 = x->N2;
  D = x->D;
  Nw = x->Nw;
  Wanal = x->Wanal;
  Wsyn = x->Wsyn;
  output = x->output;
  channelOne = x->channelOne;
  channelTwo = x->channelTwo;
  bitshuffle = x->bitshuffle;
  trigland = x->trigland;
  mult = x->mult;	
  invert = x->invert;
  exponent = x->exponent;
  
  if ( x->threshold != 0. )
    threshold = x->threshold;
  
  /* fill our retaining buffers */

  inCount += D;

  for ( j = 0 ; j < Nw - D ; j++ ) {
    inputOne[j] = inputOne[j+D];
    inputTwo[j] = inputTwo[j+D];
  }

  for ( j = Nw - D; j < Nw; j++ ) {
    inputOne[j] = *inOne++;
    inputTwo[j] = *inTwo++;
  }

  /* apply hamming window and fold our window buffer into the fft buffer */ 

  fold( inputOne, Wanal, Nw, bufferOne, N, inCount );
  fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount );

  /* do an fft */ 

  rdft( N, 1, bufferOne, bitshuffle, trigland );
  rdft( N, 1, bufferTwo, bitshuffle, trigland );

  /* convert to polar coordinates from complex values */
 
  if (invert) {
 
    for ( i = 0; i <= N2; i++ ) {
    
      float mag_1, mag_2;
    
      odd = ( even = i<<1 ) + 1;

      a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) );
      b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) );
    
      a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) );
      b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) );

      /* complex division */	

      mag_1 = hypot( a1, b1 );
      mag_2 = hypot( a2, b2 );

      if ( mag_2 > threshold )
      	*(channelOne+even) =  mag_1 / mag_2;
      
      else
      	*(channelOne+even) =  mag_1 / threshold;
      
      if ( mag_1 != 0. && mag_2 != 0. )
	*(channelOne+odd) = atan2( b2, a2 ) - atan2( b1, a1 );
      
      else 
        *(channelOne+odd) = 0.;

      /* raise resulting magnitude to a desired power */
    	  
      *(channelOne+even) = pow( *(channelOne+even), exponent );
    }  
  }


  else {
 
    for ( i = 0; i <= N2; i++ ) {
    
      float f_real, f_imag;
    
      odd = ( even = i<<1 ) + 1;

      a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) );
      b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) );
    
      a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) );
      b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) );

      /* complex multiply */

      f_real = (a1 * a2) - (b1 * b2);
      f_imag = (a1 * b2) + (b1 * a2);	

      *(channelOne+even) = hypot( f_real, f_imag );
      *(channelOne+odd) = -atan2( f_imag, f_real );

      /* raise resulting magnitude to a desired power */
    	  
      *(channelOne+even) = pow( *(channelOne+even), exponent );
    }
  }

  /* convert back to complex form, read for the inverse fft */

  for ( i = 0; i <= N2; i++ ) {

    odd = ( even = i<<1 ) + 1;

    *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) );

    if ( i != N2 )
      *(bufferOne+odd) = -(*(channelOne+even)) * sin( *(channelOne+odd) );
  }


  /* do an inverse fft */

  rdft( N, -1, bufferOne, bitshuffle, trigland );


  /* dewindow our result */

  overlapadd( bufferOne, N, Wsyn, output, Nw, inCount);

  /* set our output and adjust our retaining output buffer */

  for ( j = 0; j < D; j++ )
    *out++ = output[j] * mult;
	
  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
  
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;
		

  /* restore state variables */


  x->inCount = inCount % Nw;
  return (w+8);
}		


void codepend_dsp(t_codepend *x, t_signal **sp, short *count)
{
long i;

#if MSP
  for( i = 0; i < 4; i++ ){
    x->connected[i] = count[i];
  }
#endif
  /* signal is always connected in Pd */
#if PD 
  for( i = 0; i < 4; i++ ){
    x->connected[i] = 1;
  }
#endif

  /* reinitialize if vector size or sampling rate has been changed */
  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;
    codepend_init(x,1);
  }	
  
  dsp_add(codepend_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);
}


--- NEW FILE: thresher~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *thresher_class;
#endif 

#if PD
static t_class *thresher_class;
#endif

#define OBJECT_NAME "thresher~"

#define DEFAULT_HOLD (40.0)



typedef struct _thresher
{
#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	in_count;
	float *Wanal;	
	float *Wsyn;	
	float *input;	
	float *Hwin;
	//  float *winput;
	float *buffer;
	float *channel;
	float *output;
	/* thresher vars */
	float move_threshold;
	float *composite_frame ;
	int *frames_left;
	int max_hold_frames;
	float max_hold_time;
	int first_frame;
	float damping_factor ;
	short thresh_connected;
	short damping_connected;
	// for convert
	float *c_lastphase_in;
	float *c_lastphase_out;
	float c_fundamental;
	float c_factor_in;
	float c_factor_out;
	// for fast fft
	float mult; 
	float *trigland;
	int *bitshuffle;
	short mute;
	short bypass;
	int winfac;
	int overlap;
	float tadv;
} t_thresher;

void *thresher_new(t_symbol *s, int argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *thresher_perform(t_int *w);
void thresher_dsp(t_thresher *x, t_signal **sp, short *count);
void thresher_assist(t_thresher *x, void *b, long m, long a, char *s);
void thresher_float(t_thresher *x, double f);
void thresher_mute(t_thresher *x, t_floatarg f);
void thresher_bypass(t_thresher *x, t_floatarg f);
void thresher_free( t_thresher *x );
void thresher_overlap(t_thresher *x, t_floatarg f);
void thresher_winfac(t_thresher *x, t_floatarg f);
void thresher_fftinfo(t_thresher *x);
void thresher_init(t_thresher *x, short initialized);

#if MSP
void main(void)
{
	setup((t_messlist **)&thresher_class, (method)thresher_new, (method)thresher_free, 
		  (short)sizeof(t_thresher), 0L, A_GIMME, 0);
	addmess((method)thresher_dsp, "dsp", A_CANT, 0);
	addmess((method)thresher_assist,"assist",A_CANT,0);
	addmess((method)thresher_mute,"mute",A_FLOAT,0);
	addmess((method)thresher_bypass,"bypass",A_FLOAT,0);
	addmess((method)thresher_overlap,"overlap",A_DEFFLOAT,0);
	addmess((method)thresher_winfac,"winfac",A_DEFFLOAT,0);
	addmess((method)thresher_fftinfo,"fftinfo",0);
	addfloat((method)thresher_float);
	dsp_initclass();
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
	
}
#endif

#if PD
void thresher_tilde_setup(void)
{
	thresher_class = class_new(gensym("thresher~"), (t_newmethod)thresher_new, 
							   (t_method)thresher_free ,sizeof(t_thresher), 0,A_GIMME,0);
	
	CLASS_MAINSIGNALIN(thresher_class, t_thresher, x_f );
	class_addmethod(thresher_class, (t_method)thresher_dsp, gensym("dsp"), 0);
	class_addmethod(thresher_class, (t_method)thresher_mute, gensym("mute"), A_DEFFLOAT,0);
	class_addmethod(thresher_class, (t_method)thresher_bypass, gensym("bypass"), A_DEFFLOAT,0);
	class_addmethod(thresher_class, (t_method)thresher_assist, gensym("assist"), 0);
	class_addmethod(thresher_class,(t_method)thresher_overlap,gensym("overlap"),A_FLOAT,0);
	class_addmethod(thresher_class,(t_method)thresher_winfac,gensym("winfac"),A_FLOAT,0);
	class_addmethod(thresher_class,(t_method)thresher_fftinfo,gensym("fftinfo"),0);
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void thresher_overlap(t_thresher *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;
	thresher_init(x,1);
}

void thresher_winfac(t_thresher *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;
	thresher_init(x,2);
}

void thresher_fftinfo(t_thresher *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 thresher_free(t_thresher *x){
#if MSP
	dsp_free( (t_pxobject *) x);
#endif
	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->output,0);
	freebytes(x->composite_frame,0);
	freebytes(x->frames_left,0);
}
void thresher_mute(t_thresher *x, t_floatarg f){
	x->mute = (short)f;
}

void thresher_bypass(t_thresher *x, t_floatarg f){
	x->bypass = (short)f;
}

void thresher_assist (t_thresher *x, void *b, long msg, long arg, char *dst)
{
	if (msg==1) {
		switch (arg) {
			case 0:
				sprintf(dst,"(signal) Input");
				break;
			case 1:
				sprintf(dst,"(signal/float) Threshold");
				break;
			case 2:
				sprintf(dst,"(signal/float) Damping Factor");
				break;
		}
	} else if (msg==2) {
		sprintf(dst,"(signal) Output");
	}
}


void *thresher_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
	t_thresher *x = (t_thresher *)newobject(thresher_class);
	dsp_setup((t_pxobject *)x,3);
	outlet_new((t_pxobject *)x, "signal");
#endif
	
#if PD
    t_thresher *x = (t_thresher *)pd_new(thresher_class);
    inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
    inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
    outlet_new(&x->x_obj, gensym("signal"));
#endif
	
	
	x->move_threshold = atom_getfloatarg(0, argc, argv);
	x->damping_factor = atom_getfloatarg(1, argc, argv);
	x->overlap = atom_getfloatarg( 2, argc, argv );
	x->winfac = atom_getfloatarg( 3, argc, argv );
	
	x->D = sys_getblksize();
	x->R = sys_getsr();
	
	thresher_init(x,0);
	return (x);
}

void thresher_init(t_thresher *x, short initialized)
{
	int i;
	
	if(!x->D)
		x->D = 256;
	if(!x->R)
		x->R = 44100;
	if(!power_of_two(x->overlap))
		x->overlap = 4;
	if(!power_of_two(x->winfac))
		x->winfac = 1;
	x->N = x->D * x->overlap;
	x->Nw = x->N * x->winfac;
	limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
	x->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->in_count = -(x->Nw);
	x->mult = 1. / (float) x->N;
	x->tadv = (float) x->D / (float) x->R ;
	
	
	
	if(!initialized){
		x->mute = 0;
		x->bypass = 0;
		if(!x->damping_factor){
			x->damping_factor = .95;
		}
		x->first_frame = 1;
		x->move_threshold = .00001 ;
		x->max_hold_time = DEFAULT_HOLD ;
		x->max_hold_frames = x->max_hold_time / x->tadv;
		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;
		
		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->composite_frame = (float *) getbytes( (MAX_N+2) * sizeof(float) );
		x->frames_left = (int *) getbytes( (MAX_N+2) * sizeof(int) );
		
	}
	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));  
	memset((char *)x->frames_left,0,(x->N+2) * sizeof(float));
	
	init_rdft(x->N, x->bitshuffle, x->trigland);
	makehanning(x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
}

t_int *thresher_perform(t_int *w)
{
	float sample, outsamp ;
	int		    i,j;
	
	t_thresher *x = (t_thresher *) (w[1]);
	
	float *in = (t_float *)(w[2]);
	float *inthresh = (t_float *)(w[3]);
	float *damping = (t_float *)(w[4]);
	float *out = (t_float *)(w[5]);
	int n = (int)(w[6]);
	
	float	*input = x->input;
	float *output = x->output;
	float *buffer = x->buffer;
	float *Wanal = x->Wanal;
	float *Wsyn = x->Wsyn;
	float *channel = x->channel;
	float damping_factor = x->damping_factor;
	int max_hold_frames = x->max_hold_frames;
	int *frames_left = x->frames_left;
	float *composite_frame = x->composite_frame;
	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;
	int *bitshuffle = x->bitshuffle;
	float *trigland = x->trigland;
	float mult = x->mult;	
	int in_count = x->in_count;
	int R = x->R;
	int N = x->N;
	int N2 = x->N2;
	int D = x->D;
	int Nw = x->Nw;
	float move_threshold = x->move_threshold;
	
	
	if( x->mute ) {
		for( j = 0; j < D; j++) {
			*out++ = 0.0 ;
		}
		return (w+7);
	} 
	
	if ( x->bypass ) {
		for( j = 0; j < D; j++) {
			*out++ = *in++ ;
		}
		return (w+7);
	} 
	
	
	
	
    if( x->thresh_connected ) {
		move_threshold = *inthresh ;
    }
    if( x->damping_connected ) {
		damping_factor = *damping ;
    }
	
	in_count += D;
	
	for ( j = 0 ; j < Nw - D ; j++ )
		input[j] = input[j+D];
	
	for ( j = Nw - D; j < Nw; j++ ) {
		input[j] = *in++;
	}
	
	fold( input, Wanal, Nw, buffer, N, in_count );
	
	rdft( N, 1, buffer, bitshuffle, trigland );
	
	convert( buffer, channel, N2, c_lastphase_in, c_fundamental, c_factor_in  );
	
	if( x->first_frame ){
		for ( i = 0; i < N+2; i++ ){
			composite_frame[i] = channel[i];
			frames_left[i] = max_hold_frames;
		}
		x->first_frame = 0;
	} else {
		for( i = 0; i < N+2; i += 2 ){
			if(fabs( composite_frame[i] - channel[i] ) > move_threshold ||
			   frames_left[i] <= 0 ){
				composite_frame[i] = channel[i];
				composite_frame[i+1] = channel[i+1];
				frames_left[i] = max_hold_frames;
			} else {
				--(frames_left[i]);
				composite_frame[i] *= damping_factor;
			}
		}
	}
	
	
    unconvert( composite_frame, buffer, N2, c_lastphase_out, c_fundamental, c_factor_out  );
    rdft( N, -1, buffer, bitshuffle, trigland );
	
    overlapadd( buffer, N, Wsyn, output, Nw, in_count );
	
    for ( j = 0; j < D; j++ )
		*out++ = output[j] * mult;
	
    for ( j = 0; j < Nw - D; j++ )
		output[j] = output[j+D];
	
    for ( j = Nw - D; j < Nw; j++ )
		output[j] = 0.;
	
    x->in_count = in_count;
    x->damping_factor = damping_factor;
	
    return (w+7);
}

#if MSP
void thresher_float(t_thresher *x, double f) // Look at floats at inlets
{
	int inlet = x->x_obj.z_in;
	
	if (inlet == 1)
    {
		x->move_threshold = f;
    } else if (inlet == 2)  {
		x->damping_factor = f;
    }
}
#endif

void thresher_dsp(t_thresher *x, t_signal **sp, short *count)
{
#if MSP
	x->thresh_connected = count[1];
	x->damping_connected = count[2];
#endif
	
#if PD
	x->thresh_connected = 1;
	x->damping_connected = 1;
#endif
	
	if(sp[0]->s_n != x->D || x->R != sp[0]->s_sr){
		x->D = sp[0]->s_n;
		x->R = sp[0]->s_sr;
		thresher_init(x,1);
	}
	dsp_add(thresher_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec,
			sp[0]->s_n);
}


--- NEW FILE: README ---
This is source code for FFTease 2.5. It is up to you to link it into
your favorite compiler system. You are welcome to study, modify or do
anything else with it.

FFTease is copyright 2000-2005 Eric Lyon and Christopher Penrose.
--- NEW FILE: pvgrain~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *pvgrain_class;
#endif 

#if PD
static t_class *pvgrain_class;
#endif

#define OBJECT_NAME "pvgrain~"

typedef struct _pvgrain
{
#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;
  // for convert
  float *c_lastphase_in;
  float c_fundamental;
  float c_factor_in;
  float c_factor_out;
float synt;
  // for oscbank
  int NP;
  float P;
  int L;
  int first;
  float Iinv;
  float *lastamp;
  float *lastfreq;
  float *index;
  float *table;
  short *binsort;
  float myPInc;
  float ffac;
  //
  int lo_bin;
  int hi_bin;
  float topfreq;
  float bottomfreq;
  // for fast fft
  float mult; 
  float *trigland;
  int *bitshuffle;
  //
  int mute;
  float grain_probability;
  float sample_basefreq;
  int grains_per_frame ;
  void *list_outlet;
  float *listdata;
  short list_count;
  void *m_clock;
  int overlap;//overlap factor
  int winfac;//window factor
  int vs;//vector size

} t_pvgrain;

void *pvgrain_new(t_symbol *s, int argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *pvgrain_perform(t_int *w);
void pvgrain_dsp(t_pvgrain *x, t_signal **sp, short *count);
void pvgrain_assist(t_pvgrain *x, void *b, long m, long a, char *s);
void pvgrain_mute(t_pvgrain *x, t_floatarg state);
void pvgrain_float(t_pvgrain *x, double f);
void pvgrain_tick(t_pvgrain *x);
void pvgrain_printchan(t_pvgrain *x);
void pvgrain_probability (t_pvgrain *x, t_floatarg prob);
void pvgrain_framegrains (t_pvgrain *x, t_floatarg grains);
void pvgrain_topfreq (t_pvgrain *x, t_floatarg top);
void pvgrain_bottomfreq (t_pvgrain *x, t_floatarg f);
void pvgrain_basefreq (t_pvgrain *x, t_floatarg base);
float pvgrain_randf(float min, float max);
void pvgrain_init(t_pvgrain *x, short initialized);
void pvgrain_free(t_pvgrain *x);
void pvgrain_winfac(t_pvgrain *x, t_floatarg factor);
void pvgrain_overlap(t_pvgrain *x, t_floatarg o);
void pvgrain_fftinfo(t_pvgrain *x) ;

#if MSP
void main(void)
{
  setup((t_messlist **)&pvgrain_class, (method)pvgrain_new, (method)pvgrain_free, 
	(short)sizeof(t_pvgrain), 0, A_GIMME, 0);
  addmess((method)pvgrain_dsp, "dsp", A_CANT, 0);
  addmess((method)pvgrain_assist,"assist",A_CANT,0);
  addmess((method)pvgrain_mute,"mute",A_DEFFLOAT,0);
  addmess((method)pvgrain_printchan,"printchan",A_DEFFLOAT,0);
  addmess((method)pvgrain_probability,"probability",A_DEFFLOAT,0);
  addmess((method)pvgrain_framegrains,"framegrains",A_DEFFLOAT,0);
  addmess((method)pvgrain_topfreq,"topfreq",A_DEFFLOAT,0);
  addmess((method)pvgrain_basefreq,"basefreq",A_DEFFLOAT,0);
  addmess((method)pvgrain_overlap, "overlap",  A_DEFFLOAT, 0);
  addmess((method)pvgrain_winfac, "winfac",  A_DEFFLOAT, 0);
  addmess((method)pvgrain_fftinfo, "fftinfo", 0);
  dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);}
#endif
#if PD
void pvgrain_tilde_setup(void)
{
  pvgrain_class = class_new(gensym("pvgrain~"), (t_newmethod)pvgrain_new, 
			 (t_method)pvgrain_free ,sizeof(t_pvgrain), 0, A_GIMME, 0);
  CLASS_MAINSIGNALIN(pvgrain_class, t_pvgrain, x_f);
  class_addmethod(pvgrain_class, (t_method)pvgrain_dsp, gensym("dsp"), 0);
  class_addmethod(pvgrain_class, (t_method)pvgrain_mute, gensym("mute"), A_FLOAT, 0);
  class_addmethod(pvgrain_class, (t_method)pvgrain_topfreq, gensym("topfreq"), A_FLOAT, 0);
  class_addmethod(pvgrain_class, (t_method)pvgrain_bottomfreq, gensym("bottomfreq"), A_FLOAT, 0);
  class_addmethod(pvgrain_class, (t_method)pvgrain_printchan, gensym("printchan"), A_FLOAT, 0);
  class_addmethod(pvgrain_class, (t_method)pvgrain_probability, gensym("probability"), A_FLOAT, 0);
  class_addmethod(pvgrain_class, (t_method)pvgrain_framegrains, gensym("framegrains"), A_FLOAT, 0);
  class_addmethod(pvgrain_class, (t_method)pvgrain_basefreq, gensym("basefreq"), A_FLOAT, 0);
  class_addmethod(pvgrain_class, (t_method)pvgrain_overlap, gensym("overlap"), A_DEFFLOAT,0);
  class_addmethod(pvgrain_class, (t_method)pvgrain_winfac, gensym("winfac"), A_DEFFLOAT,0);
  class_addmethod(pvgrain_class, (t_method)pvgrain_fftinfo, gensym("fftinfo"), 0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void pvgrain_printchan(t_pvgrain *x)
{
  int i;
  post("***");
  for( i = 0 ; i < 30; i+= 2 ){
    post("amp %f freq %f", x->channel[i*2], x->channel[i*2 + 1]);
  }
  post("***");
}

void pvgrain_basefreq (t_pvgrain *x, t_floatarg base)
{
  if( base < 0.0 )
    base = 0. ;
  if( base > x->R / 2 )
    base = x->R / 2 ;
  x->sample_basefreq = base;
}

void pvgrain_topfreq (t_pvgrain *x, t_floatarg top)
{
  float curfreq ;
  if( top < 50. )
    top = 50.;
  if( top > x->R / 2 )
    top = x->R / 2;
  x->topfreq = top ;
  curfreq = 0;
  x->hi_bin = 0;
  while( curfreq < x->topfreq ) {
    ++(x->hi_bin);
    curfreq += x->c_fundamental ;
  }
}

void pvgrain_bottomfreq (t_pvgrain *x, t_floatarg f)
{
  float curfreq;
  if( f >= x->topfreq || f >= x->R/2){
	post("%f is too high a bottom freq",f);
	return;
  }

  x->bottomfreq = f;
  curfreq = 0;
  x->lo_bin = 0;
  while( curfreq < x->bottomfreq ) {
    ++(x->lo_bin);
    curfreq += x->c_fundamental ;
  }
//  post("low bin: %d high bin: %d",x->lo_bin,x->hi_bin);
}

void pvgrain_probability (t_pvgrain *x, t_floatarg prob)
{
	
  if( prob < 0. )
    prob = 0.;
  if( prob > 1. )
    prob = 1.;
  x->grain_probability = prob ;
}

void pvgrain_framegrains (t_pvgrain *x, t_floatarg grains)
{
	
  if( grains < 1 )
    grains = 1;
  if( grains > x->N2 - 1 )
    grains = x->N2 - 1;
  x->grains_per_frame = grains ;
	
}

void pvgrain_tick(t_pvgrain *x)
{
  t_atom myList[2];
  float *listdata = x->listdata;
  int i;

  for (i=0; i < 2; i++) {
    SETFLOAT(myList+i,listdata[i]); /* macro for setting a t_atom */
     
  }
  outlet_list(x->list_outlet,0L,2,myList);
  
}

void pvgrain_assist (t_pvgrain *x, void *b, long msg, long arg, char *dst)
{
  if (msg==1) {
    switch (arg) {
    case 0:
      sprintf(dst,"(signal) Input");
      break;

    }
  } else if (msg==2) {
    sprintf(dst,"(list) Amplitude/Frequency Pairs");
  }
}

void *pvgrain_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
  t_pvgrain *x = (t_pvgrain *)newobject(pvgrain_class);
  dsp_setup((t_pxobject *)x,1);
  x->list_outlet = listout(x);
#endif
#if PD
  t_pvgrain *x = (t_pvgrain *)pd_new(pvgrain_class);
  x->list_outlet = outlet_new(&x->x_obj,gensym("list"));
#endif
  x->vs = sys_getblksize();
  x->R = sys_getsr();
  
  x->grains_per_frame = atom_getfloatarg(0,argc,argv);
  x->grain_probability = atom_getfloatarg(1,argc,argv);
  x->topfreq = atom_getfloatarg(2,argc,argv);
  x->overlap = atom_getfloatarg(3,argc,argv);
  x->winfac = atom_getfloatarg(4,argc,argv);
  
  if(!x->grains_per_frame)
  	x->grains_per_frame = 4;
  if(!x->grain_probability)
  	x->grain_probability = .0001;
  if(!x->topfreq)
  	x->topfreq = 1000;
  if(!x->overlap)
  	x->overlap = 2;
  if(!x->winfac)
  	x->winfac = 4;
  	
  pvgrain_init(x,0);
  return (x);
}

void pvgrain_init(t_pvgrain *x, short initialized)
{
	float curfreq;
	
	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->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->inCount = -(x->Nw);
	x->mult = 1. / (float) x->N;
	x->Iinv = 1./x->D;
	x->myPInc = x->P*x->L/x->R;
	x->ffac = x->P * PI/x->N;
#if MSP
	x->m_clock = clock_new(x,(method)pvgrain_tick);
#endif
#if PD
	x->m_clock = clock_new(x,(void *)pvgrain_tick);
#endif
	x->c_fundamental =  (float) x->R/(float)( (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;
	
	
	if(!initialized){
		x->P = 1.0 ;
		x->sample_basefreq = 261.0;
		x->bottomfreq = 0.0;
		x->mute = 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->buffer = (float *) getbytes( MAX_N * sizeof(float) );
		x->channel = (float *) getbytes( (MAX_N+2) * sizeof(float) );
		x->output = (float *) getbytes( MAX_Nw * 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->binsort = (short *) getbytes((MAX_N2+1) * sizeof(short) );
		x->listdata = (float *) getbytes(40 * sizeof(float));
		
	} 
	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));
	init_rdft( x->N, x->bitshuffle, x->trigland);
	makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D);
	curfreq = 0;
	x->hi_bin = 0;
	x->lo_bin = 0;
	while( curfreq < x->topfreq ) {
		++(x->hi_bin);
		curfreq += x->c_fundamental ;
	}
	x->lo_bin = 0;  
	curfreq = 0;
	while( curfreq < x->bottomfreq ) {
		++(x->lo_bin);
		curfreq += x->c_fundamental ;
	}
	
}

void pvgrain_overlap(t_pvgrain *x, t_floatarg o)
{
  if(!power_of_two((int)o)){
    error("%f is not a power of two",o);
    return;
  }
  x->overlap = (int)o;
  pvgrain_init(x,1);
}

void pvgrain_winfac(t_pvgrain *x, t_floatarg f)
{
  if(!power_of_two((int)f)){
    error("%f is not a power of two",f);
    return;
  }
  x->winfac = (int)f;
  pvgrain_init(x,2);
}

void pvgrain_fftinfo( t_pvgrain *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 pvgrain_free(t_pvgrain *x)
{
#if MSP
  dsp_free((t_pxobject *) x);
#endif
  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->output,0);
  freebytes(x->c_lastphase_in,0);
  freebytes(x->binsort,0);
  freebytes(x->listdata,0);
}

t_int *pvgrain_perform(t_int *w)
{
  int 	i,j, in;
  float tmp, dice;
  short print_grain;

  t_pvgrain *x = (t_pvgrain *) (w[1]);
  t_float *inbuf = (t_float *)(w[2]);
  t_int n = w[3];
  
  short *binsort = x->binsort;
  int grains_per_frame = x->grains_per_frame ;
  int hi_bin = x->hi_bin;
  int lo_bin = x->lo_bin;
  int *bitshuffle = x->bitshuffle;
  float *trigland = x->trigland;
  float factor_in =  x->c_factor_in;
  int D = x->D;
  int I = D;
  int R = x->R;
  int Nw = x->Nw;
  int N = x->N ;
  int N2 = x-> N2;
  int Nw2 = x->Nw2;
  float fundamental = x->c_fundamental;
  float *lastphase_in = x->c_lastphase_in;
  float *Wanal = x->Wanal;
  float *Wsyn = x->Wsyn;
  float *input = x->input;
  float *Hwin = x->Hwin;
  float *buffer = x->buffer;
  float *channel = x->channel;
  float selection_probability = x->grain_probability;

  if (x->mute) { 	
    return (w+4);	
  }


  in = x->inCount ;
  x->list_count = 0;

  in += D;

  for ( j = 0 ; j < (Nw - D) ; j++ ){
    input[j] = input[j+D];
  }
  for ( j = (Nw-D), i = 0 ; j < Nw; j++, i++ ) {
    input[j] = *inbuf++;
  }

  fold( input, Wanal, Nw, buffer, N, in );   
  rdft( N, 1, buffer, bitshuffle, trigland );
  convert( buffer, channel, N2, lastphase_in, fundamental, factor_in );
  if( grains_per_frame > hi_bin - lo_bin )
    grains_per_frame = hi_bin - lo_bin;
//  binsort[0] = 0;
  for( i = 0; i < hi_bin; i++ ){// could be hi_bin - lo_bin
    binsort[i] = i + lo_bin;
  }
  for( i = lo_bin; i < hi_bin - 1; i++ ){
    for( j = i+1; j < hi_bin; j++ ){
      if(channel[binsort[j] * 2] > channel[binsort[i] * 2]) {
		tmp = binsort[j];
		binsort[j] = binsort[i];
		binsort[i] = tmp;
      }
    }
  }
  for( i = 0; i < grains_per_frame; i++ ){
    print_grain = 1;
    dice = pvgrain_randf(0.,1.);
    if( dice < 0.0 || dice > 1.0 ){
      error("dice %f out of range", dice);
    }
    if( selection_probability < 1.0 ){
      if( dice > selection_probability) {
		print_grain = 0;
      } 
    }
    if( print_grain ){
      x->listdata[ x->list_count * 2 ] = channel[ binsort[i]*2 ];
      x->listdata[ (x->list_count * 2) + 1 ] = channel[(binsort[i]*2) + 1] ;
      ++(x->list_count);
      clock_delay(x->m_clock,0); 
    }
  }
  x->inCount = in % Nw;
	
  return (w+4);
}	

float pvgrain_randf(float min, float max) {
  float guess;
  guess = (float) (rand() % RAND_MAX) / (float) RAND_MAX ;
  return ( min + guess * (max - min) );
}	

void pvgrain_mute(t_pvgrain *x, t_floatarg state)
{
  x->mute = (short)state;	
}

#if MSP
void pvgrain_float(t_pvgrain *x, double f) // Look at floats at inlets
{
int inlet = x->x_obj.z_in;
	
  if (inlet == 1)
    {
      x->P = f;
      //post("P set to %f",f);
    }
  else if (inlet == 2)
    {
      x->synt = f;
      //post("synt set to %f",f);
    }
}
#endif

void pvgrain_dsp(t_pvgrain *x, t_signal **sp, short *count)
{
  /*	long i;
	if( count[1] ){
	x->pitch_connected = 1;
	} else {
	x->pitch_connected = 0;
	}
	if( count[2] ){
	x->synt_connected = 1;
	} else {
	x->synt_connected = 0;
	}
  */
  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;
    pvgrain_init(x,1);
  }
  dsp_add(pvgrain_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
}


--- NEW FILE: residency_buffer~.c ---
#ifndef PD

#include "MSPd.h"
#include "fftease.h"
/* #include "buffer.h" */

/* Not ported to Pd due to array/buffer difference */
// #define FLEN 1024

#if MSP
void *resident_class;
#endif 

#if PD
static t_class *resident_class;
#endif

#define OBJECT_NAME "residency_buffer~"

typedef struct _resident
{
#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 current_frame;
	int framecount;
	//
	float frame_increment ;
	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 frames_read;
	int MAXFRAMES;
	short mute;
	short in2_connected;
	short in3_connected;
	int buffer_frame_count;
	// buffer
	t_symbol *l_sym;
	t_buffer *l_buf;
	short initialized;
	float *tmpframe;
	int hopsize;
	int overlap;
	int winfac;
	short playthrough;
	float sync;
	short buffer_is_hosed;
} t_resident;

void *resident_new(t_symbol *msg, short argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *resident_perform(t_int *w);
void resident_dsp(t_resident *x, t_signal **sp, short *count);
void resident_assist(t_resident *x, void *b, long m, long a, char *s);
void resident_bangname ( t_resident *x ) ;
void resident_meminfo( t_resident *x ) ;
void resident_float(t_resident *x, double f) ;
void resident_mute(t_resident *x, long toggle);
void resident_calcbuf(t_resident *x, double desired_duration);
void resident_dsp_free( t_resident *x );
void resident_fftinfo(t_resident *x);
void resident_winfac(t_resident *x, t_floatarg f);
void resident_playthrough(t_resident *x, t_floatarg f);
void resident_overlap(t_resident *x, t_floatarg f);
resident_init(t_resident *x, short initialized);


void main(void)
{
	setup((t_messlist **)&resident_class, (method)resident_new, (method)resident_dsp_free, (short)sizeof(t_resident), 0L, A_GIMME,0);
	addmess((method)resident_dsp, "dsp", A_CANT, 0);
	addmess((method)resident_assist,"assist",A_CANT,0);
	addfloat((method) resident_float);
	addbang( (method) resident_bangname );
	addmess ((method)resident_mute, "mute", A_LONG, 0);
	addmess ((method)resident_fftinfo, "meminfo", 0);
	addmess ((method)resident_calcbuf, "calcbuf", A_FLOAT, 0);
	addmess ((method)resident_winfac, "winfac", A_FLOAT, 0);
	addmess ((method)resident_overlap, "overlap", A_FLOAT, 0);
	addmess ((method)resident_playthrough, "playthrough", A_FLOAT, 0);
	addmess ((method)resident_fftinfo, "fftinfo", 0);
	dsp_initclass();
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}

void resident_meminfo( t_resident *x )
{
    post("%d frames in buffer", x->buffer_frame_count);
    post("frame_duration: %f, actual time in buffer: %f", x->tadv, (float)(x->buffer_frame_count) * x->tadv);
    post("actual time in buffer: %f", (float)(x->buffer_frame_count) * x->tadv);   
}



void resident_fftinfo(t_resident *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 resident_dsp_free( t_resident *x ){
	dsp_free( (t_pxobject *) x);
	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->output,0);
	freebytes(x->tmpframe,0);
	
}

void resident_calcbuf(t_resident *x, double desired_duration)
{
	float ms_calc;
	float frames_needed;
	float seconds;
	float frames;
	float samples;
	
	seconds = desired_duration / 1000.0;
	frames = seconds / x->tadv;
	samples = frames * (float) (x->N + 2);
	ms_calc = (samples / x->R) * 1000.0;
	post("you need %.0f milliseconds in buffer to get %.0f frames", ms_calc, frames);
	
}

void resident_assist (t_resident *x, void *b, long msg, long arg, char *dst)
{
	if (msg==1) {
		switch (arg) {
			case 0:
				sprintf(dst,"(signal/bang) Input, Sampling Trigger");
				break;
			case 1:
				sprintf(dst,"(signal/float) Frame Increment");
				break;
			case 2:
				sprintf(dst,"(signal/float) Frame Position [0-1]");
				break;
				
		}
	} else if (msg==2) {
		switch(arg) {
			case 1: sprintf(dst,"(signal) Output"); break;
			case 2: sprintf(dst,"(signal) Record Sync"); break;
		}
	}
}

void *resident_new(t_symbol *msg, short argc, t_atom *argv)
{
	t_resident *x = (t_resident *)newobject(resident_class);
	
	dsp_setup((t_pxobject *)x,3);
	outlet_new((t_pxobject *)x, "signal");
	outlet_new((t_pxobject *)x, "signal");
	
	x->D = sys_getblksize();
	x->R = sys_getsr();
	
	/* args: bufname, overlap, winfac */
	
	x->l_sym = atom_getsymarg(0, argc, argv);
	x->overlap = atom_getintarg(1, argc, argv);
	x->winfac = atom_getintarg(2, argc, argv);
	
//	post("argc is %d", argc); it is the number of arguments, not including name of external
	if(argc < 1){
		error("%s: you must provide the name of a valid buffer.",OBJECT_NAME);
		x->x_obj.z_disabled = 1;
		return 0; // kills object for good
	} else {
		x->x_obj.z_disabled = 0;
	}
	
	resident_init(x,0);  
	return (x);
}

resident_init(t_resident *x, short initialized)
{
	int i;
	if(!power_of_two(x->overlap))
		x->overlap = 4;
	if(!power_of_two(x->winfac))
		x->winfac = 1;
	
	x->N = x->D * x->overlap;
	x->Nw = x->N * x->winfac;
	limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
	x->hopsize = x->D;
	x->tadv = (float) x->D / (float) x->R;	
	x->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->inCount = -(x->Nw);
	x->mult = 1. / (float) x->N;
	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;
	
	if(!initialized){
		x->mute = 0;
		x->sync = 0;
		x->initialized = 1;
		x->current_frame = x->framecount = 0;
		x->frame_increment = 1.0 ;
		x->fpos = x->last_fpos = 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->tmpframe = (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) );
	}
	
	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));
	
	init_rdft( x->N, x->bitshuffle, x->trigland); 	
	makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D);
}

t_int *resident_perform(t_int *w)
{
	float sample, outsamp ;	
	int index_offset;
	int i, j;
	
	////////////////////////////////////////////// 
	t_resident *x = (t_resident *) (w[1]);
	t_float *in = (t_float *)(w[2]);
	t_float *increment = (t_float *)(w[3]);
	t_float *position = (t_float *)(w[4]);
	t_float *out = (t_float *)(w[5]);
	t_float *vec_sync = (t_float *)(w[6]);
	t_int n = 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 fframe = x->current_frame ;
	float fincr = x->frame_increment;
	float fpos = x->fpos;
	float last_fpos = x->last_fpos ;
	int framecount = x->framecount;
	float sync = x->sync;
	
	
	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 *tmpframe = x->tmpframe;
	
	t_buffer *l_buf = x->l_buf;
	
	int frames_read = x->frames_read;
	int buffer_frame_count = x->buffer_frame_count;
	
	if (x->in2_connected) {
		fincr = *increment++; 
	} 
	
	if (x->in3_connected) {
		fpos = *position++; 
	}
	
	inCount += D;

	if( (! x->initialized) || x->mute || x->x_obj.z_disabled ) {
	    for ( j = 0; j < D; j++ ){
      		*out++ = 0.0;
      		*vec_sync++ = sync;
		}
		return (w+8); // must be index of "n" + 1
	}
	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] = *in++;
		}
		
		fold( input, Wanal, Nw, buffer, N, inCount );	
		rdft( N, 1, buffer, bitshuffle, trigland );
		
		convert( buffer, tmpframe, N2, c_lastphase_in, c_fundamental, c_factor_in );
		
		index_offset = (N+2) * frames_read;
		
		for( i = index_offset, j = 0; i < index_offset + N + 2; i++, j++ ){
			l_buf->b_samples[i] = tmpframe[j];
		}
		
		++frames_read;
		// output empty buffers while reading
		sync = (float)frames_read/(float)(x->buffer_frame_count);
		
		if(x->playthrough){
			for ( i=0, j = Nw - D; j < Nw; j++, i++ ) {
				out[i] = input[j];
				vec_sync[j] = sync;
			}    	
		} else {
			for ( j = 0; j < D; j++ ){
				out[j] = 0.0;
				vec_sync[j] = sync;
			}
		}
		
		if( frames_read >= x->buffer_frame_count){
			x->read_me = 0;
			//     post("resident_buffer: data acquisition completed");
		} 
		
	} else if (x->mute ) {
		// Process Muted
		for ( j = 0; j < D; j++ ){
			out[j] = 0.0;
			vec_sync[j] = sync;
		}
	}
	else {
		
		if( fpos < 0 )
			fpos = 0;
		if( fpos > 1 )
			fpos = 1;
		if( fpos != last_fpos ){
			fframe =  fpos * (float) buffer_frame_count ;
			last_fpos = fpos;
		}
		
		
		fframe += fincr;
		while( fframe >= buffer_frame_count ) {
			fframe -= buffer_frame_count;
		} 
		while( fframe < 0. ) {
			fframe += buffer_frame_count ;
		}
		
		index_offset = (N+2) * (int) fframe;
		
		for( i = index_offset, j = 0; i < index_offset + N + 2; i++, j++ ){
			tmpframe[j] = l_buf->b_samples[i];
		}
		// REPLACE loveboat with buffer
		unconvert(  tmpframe, 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++ ){
			*out++ = output[j] * mult;
		}
		for ( j = 0; j < Nw - D; j++ ){
			output[j] = output[j+D];
		}
		
		for ( j = Nw - D; j < Nw; j++ ){
			output[j] = 0.;
			vec_sync[0] = sync;
		}
	}
	
	/* restore state variables */
	
	x->inCount = inCount % Nw;
	x->current_frame = fframe;
	x->frame_increment = fincr;
	x->fpos = fpos;
	x->last_fpos = last_fpos;
	x->frames_read = frames_read;
	x->sync = sync;
	
	return (w+8);
}		
void resident_float(t_resident *x, double f) // Look at floats at inlets
{
	//  int inlet = ((t_pxobject*)x)->z_in;
	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;
		
    }
}
void resident_bangname ( t_resident *x )
{
	// int i, j;
	
	x->read_me = 1;
	x->frames_read = 0;
	//  post("resident_buffer: beginning spectral data acquisition");
	return;
	
}

void resident_mute(t_resident *x, long toggle)
{
	x->mute = (short)toggle;	
}

void resident_playthrough(t_resident *x, t_floatarg toggle)
{
	x->playthrough = (short)toggle;	
}

void resident_winfac(t_resident *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;
	resident_init(x,2);
}

void resident_overlap(t_resident *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;
	resident_init(x,1);
}


void resident_dsp(t_resident *x, t_signal **sp, short *count)
{
	long i;
	int buffer_samples;
	t_buffer *b;
  	
	x->in2_connected = count[1];
	x->in3_connected = count[2];
	
	if(x->R != sp[0]->s_sr || x->D != sp[0]->s_n){
		x->R = sp[0]->s_sr;
		x->D = sp[0]->s_n;
		resident_init(x,1);
	}
  	/*	
  	post("value of disabled is: %d",x->x_obj.z_disabled);
  	post("value of initialized is: %d",x->initialized);
  	*/
/*  	if(x->l_sym->s_name == ""){
  		post("this buffer was not even dignified with a name");
  	} */
  	  	/*
  	if(!x->l_sym->s_thing){
  		error("residency_buffer~: not linked to a valid buffer");
  	} */
//	else if(!x->initialized){
		
		if ((b = (t_buffer *)(x->l_sym->s_thing)) && ob_sym(b) == gensym("buffer~")) {
			x->l_buf = b;
			x->initialized = 1;
			if( x->l_buf->b_nchans != 1 ){
				error("resident_buffer~: buffer \"%s\" must have 1 channel, not %d", x->l_sym->s_name, x->l_buf->b_nchans);
				x->x_obj.z_disabled = 1;
			}
		}	
		else {
			error("%s: buffer \"%s\" not found",OBJECT_NAME, x->l_sym->s_name);
			x->x_obj.z_disabled = 1;
		}	
	
		if( ! x->x_obj.z_disabled ){
			x->buffer_frame_count = (float) (x->l_buf->b_frames) / (float)(x->N + 2 );
		}
		
//	}
	
	
	dsp_add(resident_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);
			
}



#endif /* PD */

--- NEW FILE: centerring~.c ---
#include "MSPd.h"
#include "fftease.h"
#include "PenroseOscil.h"
#include "PenroseRand.h"

#define OBJECT_NAME "centerring~"
#define MAX_WARP 16.0

#if MSP
	void *centerring_class;
#endif
#if PD
	static t_class *centerring_class;
#endif

#define OBJECT_NAME "centerring~"

typedef struct _centerring
{
#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;
    int bufferLength;
    int recalc;
    int	seed;
    int *bitshuffle;
    
    float baseFreq;
    float constFreq;
    float bandFreq;
    float frameR;
    float *ringPhases;
    float *ringIncrements;
    float *sineBuffer;
    float *Wanal;	
    float *Wsyn;	
    float *inputOne;
    float *Hwin;
    float *bufferOne;
    float *channelOne;
    float *newChannel;
    float *newAmplitudes;
    float *output;
    float mult; 
    float *trigland;

	short connected[8];
	short mute;
	int overlap;//overlap factor
	int winfac;//window factor
	int vs;//vector size       	
} t_centerring;


/* msp function prototypes */

void *centerring_new(t_symbol *s, int argc, t_atom *argv);
t_int *centerring_perform(t_int *w);
void centerring_dsp(t_centerring *x, t_signal **sp, short *count);
void centerring_float(t_centerring *x, double myFloat);
void centerring_assist(t_centerring *x, void *b, long m, long a, char *s);
void centerring_dest(t_centerring *x, double f);
void centerring_messages(t_centerring *x, t_symbol *s, short argc, t_atom *argv);
void centerring_adjust( t_centerring *x );
void centerring_zerophases( t_centerring *x );
void centerring_randphases( t_centerring *x );
void centerring_free(t_centerring *x);
void centerring_init(t_centerring *x, short initialized);
void centerring_mute(t_centerring *x, t_floatarg toggle);
void centerring_overlap(t_centerring *x, t_floatarg o);
void centerring_fftinfo( t_centerring *x );
void centerring_winfac(t_centerring *x, t_floatarg f);


/* float input handling routine for shape width (MSP only) */
#if MSP
void centerring_float( t_centerring *x, t_floatarg df )
{
float myFloat = (float) df;
int inlet = x->x_obj.z_in;

	if ( inlet == 1 ) {
		x->baseFreq = myFloat;
		x->recalc = 1;
	}	
	if ( inlet == 2 ) {
		x->bandFreq = myFloat;
		x->recalc = 1;
	}
	if ( inlet == 3 ) {
		x->constFreq = myFloat;
		x->recalc = 1;
	}
}


void main(void)
{
    setup( (struct messlist **) &centerring_class, (method) centerring_new,
    		(method) centerring_free, (short) sizeof(t_centerring), 0,A_GIMME, 0);
    		
    addmess((method)centerring_dsp, "dsp", A_CANT, 0);
    addmess((method)centerring_assist,"assist",A_CANT,0);
	addmess((method)centerring_messages,"seed", A_GIMME, 0);    
	addmess((method)centerring_messages,"zerophases", A_GIMME, 0);
	addmess((method)centerring_messages,"randphases", A_GIMME, 0);
	addmess((method)centerring_mute,"mute", A_FLOAT, 0);
	addmess((method)centerring_overlap,"overlap", A_FLOAT, 0);
	addmess((method)centerring_winfac,"winfac", A_FLOAT, 0);
	addmess((method)centerring_fftinfo,"fftinfo", 0);
    addfloat((method)centerring_float);
    dsp_initclass();
    post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
void centerring_tilde_setup(void)
{
  centerring_class = class_new(gensym("centerring~"), (t_newmethod)centerring_new, 
			  (t_method)centerring_free ,sizeof(t_centerring), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(centerring_class, t_centerring, x_f);
  class_addmethod(centerring_class, (t_method)centerring_dsp, gensym("dsp"), 0);
  class_addmethod(centerring_class, (t_method)centerring_assist, gensym("assist"), 0);
  class_addmethod(centerring_class, (t_method)centerring_messages, gensym("seed"), A_GIMME,0);
  class_addmethod(centerring_class, (t_method)centerring_messages, gensym("zerophases"), A_GIMME,0);
  class_addmethod(centerring_class, (t_method)centerring_messages, gensym("randphases"), A_GIMME,0);
  class_addmethod(centerring_class, (t_method)centerring_overlap, gensym("overlap"), A_FLOAT,0);
  class_addmethod(centerring_class, (t_method)centerring_winfac, gensym("winfac"), A_FLOAT,0);
  class_addmethod(centerring_class, (t_method)centerring_mute, gensym("mute"), A_FLOAT,0);
  class_addmethod(centerring_class, (t_method)centerring_fftinfo, gensym("fftinfo"),0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void centerring_messages(t_centerring *x, t_symbol *s, short argc, t_atom *argv)
{	

	if (s == gensym("seed"))
		x->seed = (int) atom_getfloatarg(0,argc,argv);

	if (s == gensym("zerophases")) 
		centerring_zerophases( x );
		
	if (s == gensym("randphases"))
		centerring_randphases( x );
}



/* diagnostic messages for Max */

void centerring_assist (t_centerring *x, void *b, long msg, long arg, char *dst)
{

  if (msg == 1) {

    switch (arg) {

    	case 0:		sprintf(dst,"(signal) Input");
			break;

    	case 1:		sprintf(dst,"(signal/float) Base Modulation Frequency");
			break;
			
		case 2:		sprintf(dst,"(signal/float) Frequency Deviation Bandwidth");
			break;

		case 3:		sprintf(dst,"(signal/float) Frequency Deviation Constant");
			break;		
    }
  }

  else {

    if (msg == 2)
      sprintf(dst,"(signal) Output");

  }
}


void *centerring_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
  t_centerring 	*x = (t_centerring *) newobject(centerring_class);
  dsp_setup((t_pxobject *)x, 4);
  outlet_new((t_pxobject *)x, "signal");
#endif
#if PD
  t_centerring *x = (t_centerring *)pd_new(centerring_class);
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
#endif

  
  /* optional arguments: baseFreq, bandFreq, constFreq, seed, overlap, winfac */
  x->overlap = x->winfac = 0;
  x->baseFreq = atom_getfloatarg(0,argc,argv);
  x->bandFreq = atom_getfloatarg(1,argc,argv);
  x->constFreq = atom_getfloatarg(2,argc,argv);  
  x->seed = atom_getfloatarg(3,argc,argv);
  x->overlap = atom_getfloatarg(4,argc,argv);
  x->winfac = atom_getfloatarg(5,argc,argv);  

  if(!power_of_two(x->overlap)){
	x->overlap = 4;
  }
  if(!power_of_two(x->winfac)){
	x->winfac = 1;
  }  

if(x->baseFreq <= 0.0)
	x->baseFreq = 1.;
if(x->bandFreq <= 0.0)
	x->bandFreq = .2;
if(x->constFreq <= 0)
	x->constFreq = 1.;
		
  x->vs = sys_getblksize();
  x->R = sys_getsr();

  centerring_init(x,0);
  return(x);
}

void centerring_init(t_centerring *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->N2 = (x->N)>>1;
  x->Nw2 = (x->Nw)>>1;
  x->inCount = -(x->Nw);
  x->mult = 1. / (float) x->N;
  x->frameR = (float) x->R / (float) x->D;
  
  if(!initialized){
    x->mute = 0;
	x->bufferLength = 131072;
	x->recalc = 0;
    x->Wanal = (float *) calloc(MAX_Nw, sizeof(float));	
    x->Wsyn = (float *) calloc(MAX_Nw, sizeof(float));	
    x->Hwin = (float *) calloc(MAX_Nw, sizeof(float));
    x->inputOne = (float *) calloc(MAX_Nw, sizeof(float));	
    x->bufferOne = (float *) calloc(MAX_N, sizeof(float));
    x->channelOne = (float *) calloc((MAX_N+2), sizeof(float));
	x->newChannel = (float *) calloc(MAX_N+2, sizeof(float));
	x->newAmplitudes = (float *) calloc(((MAX_N2 + 1) * 16), sizeof(float) );
	x->ringPhases = (float *) calloc((MAX_N2 + 1), sizeof(float));
	x->ringIncrements = (float *) calloc((MAX_N2 + 1), sizeof(float));
	x->sineBuffer = (float *) calloc((x->bufferLength + 1), sizeof(float));
    x->output = (float *) calloc(MAX_Nw, sizeof(float));
    x->bitshuffle = (int *) calloc(MAX_N * 2, sizeof(int));
    x->trigland = (float *) calloc(MAX_N * 2, sizeof(float));
  } 
		memset((char *)x->inputOne,0,x->Nw);
		memset((char *)x->output,0,x->Nw);
		memset((char *)x->bufferOne,0,x->N);
		memset((char *)x->channelOne,0,x->N+2);
		memset((char *)x->newChannel,0,x->N+2);
		memset((char *)x->ringPhases,0,(x->N2+1));
		memset((char *)x->ringIncrements,0,(x->N2+1));
		memset((char *)x->newAmplitudes,0,(x->N2+1));
 
  init_rdft(x->N, x->bitshuffle, x->trigland);
  makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
  makeSineBuffer(x->sineBuffer, x->bufferLength);
  centerring_adjust(x);
  centerring_zerophases(x); 
}

void centerring_free(t_centerring *x)
{
#if MSP
  dsp_free((t_pxobject *) x);
#endif
  free(x->trigland);
  free(x->bitshuffle);
  free(x->Wanal);
  free(x->Wsyn);
  free(x->Hwin);
  free(x->inputOne);
  free(x->bufferOne);
  free(x->channelOne);
  free(x->output);
  free(x->newChannel);
  free(x->newAmplitudes);
  free(x->ringPhases);
  free(x->ringIncrements);
  free(x->sineBuffer);
}

void centerring_adjust( t_centerring *x ) {

	int		i;

	float	*ringIncrements = x->ringIncrements,
			*ringPhases = x->ringPhases;

/* initialize oscillator increments and phases */

    for (i=0; i < x->N2; i++) {

      *(ringIncrements+i) = frequencyToIncrement( x->frameR,
                                x->baseFreq *
                                ( (rrand(&(x->seed)) * x->bandFreq) + x->constFreq ),
                                x->bufferLength );
    }
}


void centerring_zerophases( t_centerring *x ) {

  int	i;

  for (i=0; i < x->N2; i++)
    *((x->ringPhases)+i) = 0.;
}


void centerring_randphases( t_centerring *x ) {

  int	i;

  for (i=0; i < x->N2; i++)
    *((x->ringPhases)+i) = prand(&(x->seed)) * (float) (x->bufferLength);

}



t_int *centerring_perform(t_int *w)
{

  int		
			i,j,
			bindex,
			inCount,
			R,
			N,
			N2,
			D,
			Nw,
  			newLength,
  			bufferLength,
   			even, odd,
  	 		*bitshuffle;

  float		mult,
  			bandFreq,
			constFreq,
			baseFreq,
			a1, b1,
			interpIncr,
			interpPhase,
  			*inputOne,
			*inputTwo,
			*bufferOne,
			*bufferTwo,
			*output,
			*Wanal,
			*Wsyn,
			*ringPhases,
            *ringIncrements,
            *sineBuffer,
			*channelOne,
			*newChannel,
			*newAmplitudes,
			*trigland;

	
  t_centerring *x = (t_centerring *) (w[1]);
  t_float *inOne = (t_float *) (w[2]);  
  t_float *vec_baseFreq = (t_float *) (w[3]);
  t_float *vec_bandFreq = (t_float *) (w[4]);
  t_float *vec_constFreq = (t_float *) (w[5]);
  t_float *out = (t_float *)(w[6]);
  t_int n = (int) (w[7]);
  short *connected = x->connected;
  
  if(connected[1]){
	x->recalc = 1;
	x->baseFreq = *vec_baseFreq;	
  }
  if(connected[2]){
	x->recalc = 1;
	x->bandFreq = *vec_bandFreq;	
  }
  if(connected[3]){
	x->recalc = 1;
	x->constFreq = *vec_constFreq;	
  }
  
  if(x->mute){
    while(n--)
      *out++ = 0.0;
    return (w+8);
  }
  	
/* dereference structure  */	

  inputOne = x->inputOne;
  bufferOne = x->bufferOne;
  inCount = x->inCount;
  R = x->R;
  N = x->N;
  N2 = x->N2;
  D = x->D;
  Nw = x->Nw;
  Wanal = x->Wanal;
  Wsyn = x->Wsyn;
  output = x->output;
  channelOne = x->channelOne;
  newChannel = x->newChannel;
  newAmplitudes = x->newAmplitudes;
  bitshuffle = x->bitshuffle;
  trigland = x->trigland; 
  mult = x->mult;
  
  bufferLength = x->bufferLength;
  
  ringPhases = x->ringPhases;
  ringIncrements = x->ringIncrements;
  sineBuffer = x->sineBuffer;

 /* recalculate our oscillator values if object inputs have been updated */

 if (x->recalc)
    centerring_adjust( x );
 
 x->recalc = 0;
  
/* fill our retaining buffers */

  inCount += D;

  for ( j = 0 ; j < Nw - D ; j++ )
    inputOne[j] = inputOne[j+D];

  for ( j = Nw - D; j < Nw; j++ )
    inputOne[j] = *inOne++;

/* apply hamming window and fold our window buffer into the fft buffer */ 

  fold( inputOne, Wanal, Nw, bufferOne, N, inCount );

/* do an fft */ 

  rdft( N, 1, bufferOne, bitshuffle, trigland );

/* convert to polar coordinates from complex values */ 

  for ( i = 0; i <= N2; i++ ) {
      odd = ( even = i<<1 ) + 1;

      a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) );
      b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) );
    
/* replace signal one's phases with those of signal two */

      *(channelOne+even) = hypot( a1, b1 );
      *(channelOne+odd) = -atan2( b1, a1 );      
  }
		
  
/* perform ring modulation on successive fft frames */

   for (i=0; i < N2; i++) {
	 even = i<<1;

     *(channelOne+even) *= bufferOscil( ringPhases+i,
                   *(ringIncrements+i), sineBuffer, bufferLength );
   }
		
/* convert from polar to cartesian */	

  for ( i = 0; i <= N2; i++ ) {

    odd = ( even = i<<1 ) + 1;
      
    *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) );

    if ( i != N2 )
      *(bufferOne+odd) = (*(channelOne+even)) * -sin( *(channelOne+odd) );
  }


/* do an inverse fft */

  rdft( N, -1, bufferOne, bitshuffle, trigland );

/* dewindow our result */

  overlapadd( bufferOne, N, Wsyn, output, Nw, inCount);

/* set our output and adjust our retaining output buffer */

  for ( j = 0; j < D; j++ )
    *out++ = output[j] * mult;
	
  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
  
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;
		

/* restore state variables */

  x->inCount = inCount % Nw;
  return (w+8);
}		



void centerring_mute(t_centerring *x, t_floatarg toggle)
{
  x->mute = (short)toggle;
}

void centerring_overlap(t_centerring *x, t_floatarg o)
{
  if(!power_of_two((int)o)){
	error("%f is not a power of two",o);
    return;
  }
  x->overlap = (int)o;
  centerring_init(x,1);
}

void centerring_winfac(t_centerring *x, t_floatarg f)
{
  if(!power_of_two((int)f)){
    error("%f is not a power of two",f);
    return;
  }
  x->winfac = (int)f;
	centerring_init(x,1);
}

void centerring_fftinfo( t_centerring *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 centerring_dsp(t_centerring *x, t_signal **sp, short *count)
{
	int i;

	#if MSP
	  for( i = 0; i < 4; i++ ){
		x->connected[i] = count[i];
	  }
	#endif

	#if PD 
	  for( i = 0; i < 4; i++ ){
		x->connected[i] = 1;
	  }
	#endif	
	
  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;
    centerring_init(x,1);
  }		

	dsp_add(centerring_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);
}


--- NEW FILE: mindwarp~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *mindwarp_class;
#endif
#if PD
static t_class *mindwarp_class;
#endif

#define OBJECT_NAME "mindwarp~"


#define MAX_WARP 16.0

/* 12.11.05 fixed divide-by-zero bug */

typedef struct _mindwarp
{
#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;
    int	warpConnected;
    int widthConnected;
    int *bitshuffle;
    
    float warpFactor;
    float shapeWidth;
    float *Wanal;	
    float *Wsyn;	
    float *inputOne;
    float *Hwin;
    float *bufferOne;
    float *channelOne;
    float *newChannel;
    float *newAmplitudes;
    float *output;
    float mult; 
    float *trigland;
  short connected[8];
  short mute;
  int overlap;//overlap factor
  int winfac;//window factor
  int vs;//vector size     	
} t_mindwarp;


/* msp function prototypes */

void *mindwarp_new(t_symbol *s, int argc, t_atom *argv);

t_int *mindwarp_perform(t_int *w);
void mindwarp_dsp(t_mindwarp *x, t_signal **sp, short *count);
void mindwarp_float(t_mindwarp *x, double myFloat);
void mindwarp_assist(t_mindwarp *x, void *b, long m, long a, char *s);
void mindwarp_dest(t_mindwarp *x, double f);
void mindwarp_init(t_mindwarp *x, short initialized);
void mindwarp_free(t_mindwarp *x);
void mindwarp_mute(t_mindwarp *x, t_floatarg toggle);
void mindwarp_fftinfo(t_mindwarp *x);
void mindwarp_overlap(t_mindwarp *x, t_floatarg o);
void mindwarp_winfac(t_mindwarp *x, t_floatarg o);
void mindwarp_tilde_setup(void);

#if MSP

void mindwarp_float( t_mindwarp *x, double df )
{
float myFloat = (float)df;

int inlet = x->x_obj.z_in;

//post("float input to mindwarp: %f",myFloat);

	if ( inlet == 1 ) {
	
		x->warpFactor = myFloat;
			
		if ( x->warpFactor > MAX_WARP )
			x->warpFactor = MAX_WARP;
				
		if ( x->warpFactor < (1. / MAX_WARP) )
			x->warpFactor = (1. / MAX_WARP);
	}	

	if ( inlet == 2 ) {

		if ( myFloat >= 1. && myFloat <= (double) x->N )
			x->shapeWidth = myFloat;
	}
	
}

void main(void)
{
    setup( (struct messlist **) &mindwarp_class, (method) mindwarp_new,
    		(method) mindwarp_free, (short) sizeof(t_mindwarp), 0, A_GIMME, 0);
    		
    addmess((method)mindwarp_dsp, "dsp", A_CANT, 0);
    addmess((method)mindwarp_assist,"assist",A_CANT,0);
    addmess((method)mindwarp_mute,"mute", A_FLOAT, 0);
     addmess((method)mindwarp_overlap,"overlap", A_FLOAT, 0);
     addmess((method)mindwarp_winfac,"winfac", A_FLOAT, 0);
     addmess((method)mindwarp_fftinfo,"fftinfo", 0);  
    addfloat((method)mindwarp_float);
    dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
void mindwarp_tilde_setup(void)
{
  mindwarp_class = class_new(gensym("mindwarp~"), (t_newmethod)mindwarp_new, 
			     (t_method)mindwarp_free ,sizeof(t_mindwarp), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(mindwarp_class, t_mindwarp, x_f);
  class_addmethod(mindwarp_class, (t_method)mindwarp_dsp, gensym("dsp"), 0);
  class_addmethod(mindwarp_class, (t_method)mindwarp_assist, gensym("assist"), 0);
  class_addmethod(mindwarp_class, (t_method)mindwarp_overlap, gensym("overlap"), A_FLOAT,0);
 class_addmethod(mindwarp_class, (t_method)mindwarp_winfac, gensym("winfac"), A_FLOAT,0);

  class_addmethod(mindwarp_class, (t_method)mindwarp_mute, gensym("mute"), A_FLOAT,0);
  class_addmethod(mindwarp_class, (t_method)mindwarp_fftinfo, gensym("fftinfo"), A_CANT,0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif



/* diagnostic messages for Max */

void mindwarp_assist (t_mindwarp *x, void *b, long msg, long arg, char *dst)
{

  if (msg == 1) {

    switch (arg) {

    	case 0:		sprintf(dst,"(signal) Formant Input");
			break;

    	case 1:		sprintf(dst,"(signal/float) Warp Factor");
			break;
			
		case 2:		sprintf(dst,"(signal/float) Shape Width");
			break;		
    }
  }

  else {

    if (msg == 2)
      sprintf(dst,"(signal) Mindwarp Output");

  }
}


void *mindwarp_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
  t_mindwarp 	*x = (t_mindwarp *) newobject(mindwarp_class);
  dsp_setup((t_pxobject *)x, 3);
  outlet_new((t_pxobject *)x, "signal");
#endif

#if PD
  t_mindwarp *x = (t_mindwarp *)pd_new(mindwarp_class);
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
#endif
  
  
/* args: warpfactor, shape width, overlap, window factor */


  x->warpFactor = atom_getfloatarg(0,argc,argv);
  x->shapeWidth = atom_getfloatarg(1,argc,argv);
  x->overlap = atom_getfloatarg(2,argc,argv);
  x->winfac = atom_getfloatarg(3,argc,argv);

  if(!power_of_two(x->overlap)){
    x->overlap = 4;
  }
  if(!power_of_two(x->winfac)){
    x->winfac = 1;
  }
  
  if(x->warpFactor <= 0 || x->warpFactor > 100.0)
  	x->warpFactor = 1.0;
  if(x->shapeWidth <= 0 || x->shapeWidth > 64)
  	x->shapeWidth = 3.0;
  
  x->vs = sys_getblksize();
  x->R = sys_getsr();
  mindwarp_init(x,0);

  return (x);

}

void mindwarp_init(t_mindwarp *x, short initialized)
{
	
	
	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->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->inCount = -(x->Nw);
	x->mult = 1. / (float) x->N;
	
	
	if(!initialized){
		x->mute = 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->inputOne = (float *)  getbytes (MAX_Nw * sizeof(float));
		x->bufferOne = (float *)  getbytes (MAX_N * sizeof(float));
		x->channelOne = (float *)  getbytes (MAX_N+2 * sizeof(float));
		x->newAmplitudes = (float *)  getbytes (((MAX_N2 + 1) * 16) * sizeof(float));
		x->newChannel = (float *)  getbytes ((MAX_N + 1) * sizeof(float));
		x->output = (float *)  getbytes (MAX_Nw * sizeof(float));
		x->bitshuffle = (int *)  getbytes (MAX_N * 2 * sizeof(int));
		x->trigland = (float *)  getbytes (MAX_N * 2 * sizeof(float));
	} 
	memset((char *)x->inputOne,0,x->Nw * sizeof(float));
	memset((char *)x->output,0,x->Nw * sizeof(float));
	
	
	init_rdft( x->N, x->bitshuffle, x->trigland);
	makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 1);
	
}

void mindwarp_free(t_mindwarp *x)
{
#if MSP
  dsp_free((t_pxobject *) x);
#endif
  freebytes(x->trigland,0);
  freebytes(x->bitshuffle,0);
  freebytes(x->Wanal,0);
  freebytes(x->Wsyn,0);
  freebytes(x->Hwin,0);
  freebytes(x->inputOne,0);
  freebytes(x->bufferOne,0);
  freebytes(x->channelOne,0);
  freebytes(x->newAmplitudes,0);
  freebytes(x->newChannel,0);
  freebytes(x->output,0);
}



t_int *mindwarp_perform(t_int *w)
{

  int		
			i,j,
			bindex,
			inCount,
			R,
			N,
			N2,
			D,
			Nw,
			invert = 1,
  			shapeWidth,
  			remainingWidth,
  			newLength,
  			even, odd,
  	 		*bitshuffle;

  float		maxamp,	
  			threshMult = 1.,
  			warpFactor,
			mult,
			cutoff,
			filterMult,
			a1, b1,
			interpIncr,
			interpPhase,
  			*inputOne,
			*inputTwo,
			*bufferOne,
			*bufferTwo,
			*output,
			*Wanal,
			*Wsyn,
			*channelOne,
			*newChannel,
			*newAmplitudes,
			*trigland;

/* get our inlets and outlets */
	
  t_mindwarp *x = (t_mindwarp *) (w[1]);
  t_float *inOne = (t_float *) (w[2]);
  t_float *vec_warpFactor = (t_float *) (w[3]);
  t_float *vec_shapeWidth = (t_float *) (w[4]);
  t_float *out = (t_float *)(w[5]);
  t_int n = w[6];
  
  short *connected = x->connected;

  if(x->mute){
	while(n--)
		*out++ = 0.0;
	return w+7;
  }
  
  warpFactor = connected[1] ? *vec_warpFactor : x->warpFactor;
  shapeWidth = connected[2] ? (int) (*vec_shapeWidth) : (int) x->shapeWidth;

  if(warpFactor <= 0.0){
  	warpFactor = 0.1;
  	error("zero warp factor reported");
  }

	  

/* dereference structure  */	

  inputOne = x->inputOne;
  bufferOne = x->bufferOne;
  inCount = x->inCount;
  R = x->R;
  N = x->N;
  N2 = x->N2;
  D = x->D;
  Nw = x->Nw;
  Wanal = x->Wanal;
  Wsyn = x->Wsyn;
  output = x->output;
  channelOne = x->channelOne;
  newChannel = x->newChannel;
  newAmplitudes = x->newAmplitudes;
  bitshuffle = x->bitshuffle;
  trigland = x->trigland;
  mult = x->mult;	
  
  cutoff = (float) N2 * .9;
  filterMult = .00001;
    


	
	
/* fill our retaining buffers */

  inCount += D;

  for ( j = 0 ; j < Nw - D ; j++ )
    inputOne[j] = inputOne[j+D];

  for ( j = Nw - D; j < Nw; j++ )
    inputOne[j] = *inOne++;

/* apply hamming window and fold our window buffer into the fft buffer */ 

  fold( inputOne, Wanal, Nw, bufferOne, N, inCount );


/* do an fft */ 

  rdft( N, 1, bufferOne, bitshuffle, trigland );

/* convert to polar coordinates from complex values */ 

  for ( i = 0; i <= N2; i++ ) {
      odd = ( even = i<<1 ) + 1;

      a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) );
      b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) );
    
/* replace signal one's phases with those of signal two */

      *(channelOne+even) = hypot( a1, b1 );
      *(channelOne+odd) = -atan2( b1, a1 );      
  }


  
  /* set the number of expected new amplitudes */
  if(warpFactor <= 0){
  	error("bad warp, resetting");
  	warpFactor = 1.0;
  }

  newLength = (int) ((float) N2 / warpFactor);
   
  if(newLength <= 0){
  	error("bad length: resetting");
  	newLength = 1.0;
  }

  interpIncr = (float) N2 / (float) newLength;

  interpPhase = 0.;


  /* do simple linear interpolation on magnitudes */

  for ( bindex=0; bindex < newLength; bindex++ ) {

	int		localbindex = ((int) interpPhase) << 1;

	float	lower = *(channelOne + localbindex),
			upper = *(channelOne + localbindex + 2),
			diff = interpPhase - ( (float) ( (int) interpPhase ) );

	*(newAmplitudes+bindex) = lower + ( ( upper - lower ) * diff );

	interpPhase += interpIncr;
  }


  
/* replace magnitudes with warped values */

  if (warpFactor > 1.) {

	  int	until = (int) ( cutoff / warpFactor );

	  for ( bindex=0; bindex < until; bindex++ ) {
	    register int	amp = bindex<<1;

	    *(newChannel+amp) = *(newAmplitudes+bindex);
	  }


	  /* filter remaining spectrum as spectral envelope has shrunk */

	  for ( bindex=until; bindex < N2; bindex++ ) {
	    register int	amp = bindex<<1;

	    *(newChannel+amp) *= filterMult;
	  }
  }


//OK
  
  /* spectral envelope has enlarged, no post filtering is necessary */
  
  else {

	for ( bindex=0; bindex <= N2; bindex++ ) {
	    register int	amp = bindex<<1;

	    *(newChannel+amp) = *(newAmplitudes+bindex);
	}
  }


  
/* constrain our shapeWidth value */

  if ( shapeWidth > N2 )
  	shapeWidth = N2;
  	
  if ( shapeWidth < 1 )
  	shapeWidth = 1;

/* lets just shape the entire signal by the shape width */


  for ( i=0; i < N; i += shapeWidth << 1 ) {
	  
	float       amplSum = 0.,
    		    freqSum = 0.,
          		factor = 1.0;

	for ( j = 0; j < shapeWidth << 1; j += 2 ) {

  		amplSum += *(newChannel+i+j);
  		freqSum += *(channelOne+i+j);
	}

	if (amplSum < 0.000000001)
		factor = 0.000000001;	
	
	/* this can happen, crashing external; now fixed.*/
		
	if( freqSum <= 0 ){
//		error("bad freq sum, resetting");
		freqSum = 1.0;
	}
	else	
		factor = amplSum / freqSum;

	for ( j = 0; j < shapeWidth << 1; j += 2 )
  		*(channelOne+i+j) *= factor;
  }

/* copy remaining magnitudes (fixed shadowed variable warning by renaming bindex)*/

  if ( (remainingWidth = N2 % shapeWidth) ) {

	int			lbindex = (N2 - remainingWidth) << 1;


	float       amplSum = 0.,
    		    freqSum = 0.,
          		factor;

	for ( j = 0; j < remainingWidth << 1; j += 2 ) {

  		amplSum += *(newChannel+lbindex+j);
  		freqSum += *(channelOne+lbindex+j);
	}

	if (amplSum < 0.000000001)
		factor = 0.000000001;	
		
	else	
		factor = amplSum / freqSum;

	for ( j = 0; j < remainingWidth << 1; j += 2 )
  		*(channelOne+bindex+j) *= factor;
  }
		

/* convert from polar to cartesian */	

  for ( i = 0; i <= N2; i++ ) {

    odd = ( even = i<<1 ) + 1;
      
    *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) );

    if ( i != N2 )
      *(bufferOne+odd) = (*(channelOne+even)) * -sin( *(channelOne+odd) );
  }


/* do an inverse fft */

  rdft( N, -1, bufferOne, bitshuffle, trigland );

/* dewindow our result */

  overlapadd( bufferOne, N, Wsyn, output, Nw, inCount);

/* set our output and adjust our retaining output buffer */

  for ( j = 0; j < D; j++ )
    *out++ = output[j] * mult;
	
  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
  
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;
		

/* restore state variables */

  x->inCount = inCount % Nw;
  return (w+7);
}		

void mindwarp_mute(t_mindwarp *x, t_floatarg toggle)
{
  x->mute = (short)toggle;
}

void mindwarp_overlap(t_mindwarp *x, t_floatarg o)
{
  if(!power_of_two((int)o)){
    error("%f is not a power of two",o);
    return;
  }
  x->overlap = (int)o;
  mindwarp_init(x,1);
}

void mindwarp_winfac(t_mindwarp *x, t_floatarg f)
{
  if(!power_of_two((int)f)){
    error("%f is not a power of two",f);
    return;
  }
  x->winfac = (int)f;
  mindwarp_init(x,1);
}

void mindwarp_fftinfo( t_mindwarp *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 mindwarp_dsp(t_mindwarp *x, t_signal **sp, short *count)
{
long i;
#if MSP
  for( i = 0; i < 3; i++ ){
    x->connected[i] = count[i];
  }
#endif
  /* signal is always connected in Pd */
#if PD 
  for( i = 0; i < 3; i++ ){
    x->connected[i] = 1;
  }
#endif

  /* reinitialize if vector size or sampling rate has been changed */
  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;
    mindwarp_init(x,1);
  }		
  
  dsp_add(mindwarp_perform, 6, x,
		sp[0]->s_vec,
		sp[1]->s_vec,
		sp[2]->s_vec,
		sp[3]->s_vec,
		sp[0]->s_n);
}


--- NEW FILE: cavoc~.c ---
#include "MSPd.h"

#include "fftease.h"

#if MSP
void *cavoc_class;
#endif 

#if PD
static t_class *cavoc_class;
#endif

#define OBJECT_NAME "cavoc~"

typedef struct _cavoc
{
#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	in_count;
  float *Wanal;	
  float *Wsyn;	
  float *input;	
  float *Hwin;
  float *buffer;
  float *channel;
  float *output;

  float frame_duration;
  int max_bin;

  float fundamental;
  float *last_frame;
  short left;
  short right;
  short center;
  short *rule;
  float density;
  float start_breakpoint;
  int hold_frames;
  int frames_left;
  int set_count;
  // FFT
  float *c_lastphase_out;
  float c_fundamental;
  float c_factor_out;
  float mult; 
  float *trigland;
  int *bitshuffle;
  //
  void *list_outlet;
  t_atom *list_data;
  short mute;
  int overlap;
  int winfac;
  short external_trigger;
  float hold_time;
} t_cavoc;

void *cavoc_new(t_symbol *msg, short argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *cavoc_perform(t_int *w);
void cavoc_dsp(t_cavoc *x, t_signal **sp, short *count);
void cavoc_assist(t_cavoc *x, void *b, long m, long a, char *s);
void cavoc_free( t_cavoc *x );
int cavoc_apply_rule( short left, short right, short center, short *rule);
float cavoc_randf(float min, float max);
void cavoc_rule (t_cavoc *x, t_symbol *msg, short argc, t_atom *argv);
void cavoc_density (t_cavoc *x, t_floatarg density);
void cavoc_hold_time (t_cavoc *x, t_floatarg hold_time);
void cavoc_retune (t_cavoc *x, t_floatarg min, t_floatarg max);
void cavoc_mute (t_cavoc *x, t_floatarg toggle);
void cavoc_external_trigger(t_cavoc *x, t_floatarg toggle);
void cavoc_init(t_cavoc *x,short initialized);
void cavoc_overlap(t_cavoc *x, t_floatarg f);
void cavoc_winfac(t_cavoc *x, t_floatarg f);
void cavoc_fftinfo(t_cavoc *x);

#if MSP
void main(void)
{
  setup((t_messlist **)&cavoc_class, (method)cavoc_new, (method)cavoc_free, 
  	(short)sizeof(t_cavoc), 0, A_GIMME, 0);
  addmess((method)cavoc_dsp, "dsp", A_CANT, 0);
  addmess((method)cavoc_assist,"assist",A_CANT,0);
  addmess((method)cavoc_rule,"rule",A_GIMME,0);
  addmess((method)cavoc_density,"density",A_FLOAT,0);
  addmess((method)cavoc_hold_time,"hold_time",A_FLOAT,0);
  addmess((method)cavoc_mute,"mute",A_FLOAT,0);
  addmess((method)cavoc_external_trigger,"external_trigger",A_FLOAT,0);
  addmess((method)cavoc_retune,"retune",A_FLOAT,A_FLOAT,0);
  addmess((method)cavoc_overlap,"overlap",A_FLOAT,0);
  addmess((method)cavoc_winfac,"winfac",A_FLOAT,0);
  addmess((method)cavoc_fftinfo,"fftinfo",0);
  dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
void cavoc_tilde_setup(void){
  cavoc_class = class_new(gensym("cavoc~"), (t_newmethod)cavoc_new, 
      (t_method)cavoc_free ,sizeof(t_cavoc), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(cavoc_class, t_cavoc, x_f);
  class_addmethod(cavoc_class,(t_method)cavoc_dsp,gensym("dsp"),0);
  class_addmethod(cavoc_class,(t_method)cavoc_mute,gensym("mute"),A_FLOAT,0);
  class_addmethod(cavoc_class,(t_method)cavoc_overlap,gensym("overlap"),A_FLOAT,0);
  class_addmethod(cavoc_class,(t_method)cavoc_winfac,gensym("winfac"),A_FLOAT,0);
  class_addmethod(cavoc_class,(t_method)cavoc_rule,gensym("rule"),A_GIMME,0);
	class_addmethod(cavoc_class,(t_method)cavoc_density,gensym("density"),A_FLOAT,0);
	class_addmethod(cavoc_class,(t_method)cavoc_hold_time,gensym("hold_time"),A_FLOAT,0);
	class_addmethod(cavoc_class,(t_method)cavoc_external_trigger,gensym("external_trigger"),A_FLOAT,0);
	class_addmethod(cavoc_class,(t_method)cavoc_retune,gensym("retune"),A_FLOAT,A_FLOAT,0);
  class_addmethod(cavoc_class,(t_method)cavoc_winfac,gensym("winfac"),A_FLOAT,0);
  class_addmethod(cavoc_class,(t_method)cavoc_overlap,gensym("overlap"),A_FLOAT,0);
  class_addmethod(cavoc_class,(t_method)cavoc_fftinfo,gensym("fftinfo"),0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void cavoc_fftinfo( t_cavoc *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 cavoc_overlap(t_cavoc *x, t_floatarg f)
{
  if(!power_of_two(f)){
    error("%f is not a power of two",f);
    return;
  }
	x->overlap = (int)f;
	cavoc_init(x,1);
}

void cavoc_winfac(t_cavoc *x, t_floatarg f)
{
	  if(!power_of_two(f)){
	    error("%f is not a power of two",f);
	    return;
	  }
	x->winfac = (int)f;
	cavoc_init(x,1);
}

void cavoc_external_trigger(t_cavoc *x, t_floatarg toggle)
{
	x->external_trigger = toggle;
}

void cavoc_mute (t_cavoc *x, t_floatarg toggle)
{
	x->mute = toggle;
}

void cavoc_retune(t_cavoc *x, t_floatarg min, t_floatarg max)
{
  int i;

  if( max <= 0 || min <= 0 || min > max ){
    error("bad values for min and max multipliers");
    return;
  }
  if( min < .1 )
    min = 0.1;
  if( max > 2.0 )
    max = 2.0;
  for( i = 0; i < x->N2 + 1; i++ ){
    x->channel[ i * 2 + 1 ] = x->c_fundamental * (float) (i / 2) * cavoc_randf(min, max);
  }

}

void cavoc_density(t_cavoc *x, t_floatarg density)
{
  int i;
  if( density < 0.0001 ){
    density = .0001;
  } else if( density > .9999 ){
    density = 1.0;
  }
  x->density = density;
  x->start_breakpoint = 1.0 - x->density;
  for( i = 0; i < x->N2 + 1; i++ ){
    if( cavoc_randf(0.0, 1.0) > x->start_breakpoint ){
      x->channel[ i * 2 ] = 1;
      ++(x->set_count);
    } else {
      x->channel[ i * 2 ] = 0;
    }
  }
  for( i = 0; i < x->N+2; i++ ){
    x->last_frame[i] = x->channel[i];
  }
}

void cavoc_hold_time(t_cavoc *x, t_floatarg f)
{

	if(f <= 0){
		error("negative or zero hold time.");
		return;
	}
	x->hold_time = f;
  x->hold_frames = (int) ((x->hold_time/1000.0) / x->frame_duration);
  if( x->hold_frames < 1 )
    x->hold_frames = 1;
  x->frames_left = x->hold_frames;

}

void cavoc_rule (t_cavoc *x, t_symbol *msg, short argc, t_atom *argv)
{
  int i;
  short *rule = x->rule;
  if( argc != 8 ){
    error("the rule must be size 8");
    return;
  }
  
  for( i = 0; i < 8; i++ ){
    rule[i] = (short) atom_getfloatarg(i, argc, argv);
//    post("%d",rule[i]);
  }
}

void cavoc_free( t_cavoc *x ){
#if MSP
  dsp_free((t_pxobject *) x);
#endif
  free(x->trigland);
  free(x->bitshuffle);
  free(x->Wanal);
  free(x->Wsyn);
  free(x->input);
  free(x->Hwin);
  free(x->buffer);
  free(x->channel);
  free(x->last_frame);
  free(x->output);
  free(x->c_lastphase_out);
  free(x->rule);  
}

void cavoc_assist (t_cavoc *x, void *b, long msg, long arg, char *dst)
{
  if (msg==1) {
    switch (arg) {
   	 case 0: sprintf(dst,"(signal) Trigger");break;
    }
  } else if (msg==2) {
    switch (arg) {
  	  case 0:sprintf(dst,"(signal) Output"); break;
    }
  }
}

void *cavoc_new(t_symbol *msg, short argc, t_atom *argv)
{
#if MSP
  t_cavoc *x = (t_cavoc *)newobject(cavoc_class);
  dsp_setup((t_pxobject *)x,1);
  outlet_new((t_pxobject *)x, "signal");
 #endif

#if PD
	t_cavoc *x = (t_cavoc *)pd_new(cavoc_class);
  outlet_new(&x->x_obj, gensym("signal"));
#endif

  x->D = sys_getblksize();
  x->R = sys_getsr();

  x->density = atom_getfloatarg(0,argc,argv);
  x->hold_time = atom_getintarg(1,argc,argv);
  x->overlap = atom_getintarg(2,argc,argv);
  x->winfac = atom_getintarg(3,argc,argv);

  
	cavoc_init(x,0);
  return (x);
}

void cavoc_init(t_cavoc *x,short initialized)
{
int i;

  if(!x->D)
    x->D = 256;
  if(!x->R)
    x->R = 44100;
  if(!power_of_two(x->overlap))
    x->overlap = 4;
  if(!power_of_two(x->winfac))
    x->winfac = 1;
  x->N = x->D * x->overlap;
  x->Nw = x->N * x->winfac;
limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
  x->mult = 1. / (float) x->N;
  x->N2 = (x->N)>>1;
  x->Nw2 = (x->Nw)>>1;
  x->in_count = -(x->Nw);
  x->c_fundamental =  (float) x->R/(float)((x->N2)<<1);
  x->frame_duration = (float)x->D/(float) x->R;
  if(x->hold_time <= 100) /* in milliseconds */
  	x->hold_time = 100;


  cavoc_hold_time(x, x->hold_time);  	

	if(!initialized){
	  
	  srand(time(0));
	  x->mute = 0;
	  x->set_count = 0;
	  x->external_trigger = 0;
	  if( x->density < 0.0 ){
	    x->density = 0;
	  } else if( x->density > 1.0 ){
	    x->density = 1.0;
	  }
	  x->start_breakpoint = 1.0 - x->density;
	  
	  x->Wanal = (float *) calloc( MAX_Nw, sizeof(float) );	
	  x->Wsyn = (float *) calloc( MAX_Nw, sizeof(float) );	
	  x->input = (float *) calloc( MAX_Nw, sizeof(float) );	
	  x->Hwin = (float *) calloc( MAX_Nw, sizeof(float) );
	  x->buffer = (float *) calloc( MAX_N, sizeof(float) );
	  x->channel = (float *) calloc( MAX_N+2, sizeof(float) );
	  x->last_frame = (float *) calloc(MAX_N+2, sizeof(float));
	  x->output = (float *) calloc( MAX_Nw, sizeof(float) );
	  x->bitshuffle = (int *) calloc( MAX_N * 2, sizeof( int ) );
	  x->trigland = (float *) calloc( MAX_N * 2, sizeof( float ) );
	  x->c_lastphase_out = (float *) calloc( MAX_N2+1, sizeof(float) );
	  
	  x->c_factor_out = TWOPI * (float)  x->D / (float) x->R;
	  x->rule = (short *)  calloc(8, sizeof(short));

	  x->rule[2] = x->rule[3] = x->rule[5] = x->rule[6] = 1;
	  x->rule[0] = x->rule[1] = x->rule[4] = x->rule[7] = 0;

	} 
		memset((char *)x->input,0,x->Nw * sizeof(float));
		memset((char *)x->output,0,x->Nw * sizeof(float));
		memset((char *)x->buffer,0,x->N * sizeof(float));
		memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float));
		memset((char *)x->last_frame,0,(x->N+2) * sizeof(float));

  init_rdft( x->N, x->bitshuffle, x->trigland);
  makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);

  for(i = 0; i < x->N2 + 1; i++){
    if(cavoc_randf(0.0, 1.0) > x->start_breakpoint){
      x->channel[ i * 2 ] = 1;
      ++(x->set_count);
    } else {
      x->channel[i * 2] = 0;
    }
    x->channel[i * 2 + 1] = x->c_fundamental * (float) (i / 2) * cavoc_randf(.9,1.1);
  }

//  post("turned on %d of a possible %d bins", x->set_count, x->N2+1 );
  
  for( i = 0; i < x->N+2; i++ ){
    x->last_frame[i] = x->channel[i];
  }
//  post("cavoc~ FFT size: %d",x->N);
}

t_int *cavoc_perform(t_int *w)
{
  int	i,j;
  float oldfrac,newfrac;
  t_cavoc *x = (t_cavoc *)(w[1]);
  float *trigger_vec = (t_float *)(w[2]);
  float *out = (t_float *)(w[3]);
  t_int n = w[4];

  int frames_left = x->frames_left;
  float *input = x->input;
  float *buffer = x->buffer;
  int in_count = x->in_count;
  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 *output = x->output;
  float *channel = x->channel;
  float mult = x->mult ;
  int *bitshuffle = x->bitshuffle;
  float *trigland = x->trigland ;
  int hold_frames = x->hold_frames;
  short *rule = x->rule;
  short left = x->left;
  short right = x->right;
  short center = x->center;
  float *last_frame = x->last_frame;
  float *c_lastphase_out = x->c_lastphase_out;
  float c_fundamental = x->c_fundamental;
  float c_factor_out = x->c_factor_out;
  short external_trigger = x->external_trigger;
  short new_event = 0;
  
  in_count += D;

  if( x->mute ){
    while( n-- ){
      *out++ = 0.0;
    }
    return (w+5);
  }
  if(external_trigger){// only accurate to within a vector because of FFT
  	for(i=0;i<n;i++){
  		if(trigger_vec[i]){
  			new_event = 1;
  			break;
  		}
  	}
  } else if(!--frames_left){
    frames_left = hold_frames;
  	new_event = 1;
  }
  
  if(new_event){
    for( i = 2; i < N; i+=2 ){
      left = last_frame[ i - 2];
      center = last_frame[i] ;
      right = last_frame[i+2];
      channel[i] = cavoc_apply_rule(left, right, center, rule );
    }
    /* boundary cases */
    center = last_frame[0];
    right = last_frame[2];
    left = last_frame[N];
    channel[0] = cavoc_apply_rule(left, right, center, rule );

    center = last_frame[N];
    right = last_frame[0];
    left = last_frame[N - 2];
    channel[N] = cavoc_apply_rule(left, right, center, rule );


    /* save composite frame for next time */
    for( i = 0; i < N+1; i++ ){
      last_frame[i] = channel[i];
    }
  }
  unconvert( channel, buffer, N2, c_lastphase_out, c_fundamental, c_factor_out  );
  rdft( N, -1, buffer, bitshuffle, trigland );
  overlapadd( buffer, N, Wsyn, output, Nw, in_count);

  for ( j = 0; j < D; j++ )
    *out++ = output[j] * mult;

  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
			
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;	

  /* restore state variables */
  x->in_count = in_count % Nw;
  x->frames_left = frames_left;
  return (w+5);
}		

int cavoc_apply_rule(short left, short right, short center, short *rule){

  if( ! center ){
    if( ! left && ! right){
      return  rule[0];
    } else if ( ! left && right ){ 
      return rule[1];
    } else if ( left && ! right ) {
      return rule[2];
    } else if (left && right) {
      return rule[3];
    }
  } else {
    if( ! left && ! right){
      return rule[4];
    } else if ( ! left && right ){ 
      return rule[5];
    } else if ( left && ! right ) {
      return rule[6];
    } else if (left && right) {
      return rule[7];
    }
  }
  return 0;// never happens
}

float cavoc_randf(float min, float max)
{
	float randv;
	
	randv = (float) (rand() % 32768) / 32768.0 ;
	
	return (min + ((max-min) * randv))  ;
}
void cavoc_dsp(t_cavoc *x, t_signal **sp, short *count)
{
  if(sp[0]->s_n != x->D || x->R != sp[0]->s_sr){
    x->D = sp[0]->s_n;
    x->R = sp[0]->s_sr;
    cavoc_init(x,1);
  }

  dsp_add(cavoc_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec,  sp[0]->s_n);
}


--- NEW FILE: burrow~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
	void *burrow_class;
#endif
#if PD
	static t_class *burrow_class;
#endif

#define OBJECT_NAME "burrow~"

/* after adding fixes, window factors > 1 are defective. Is there
a remaining bug, or is this a problem for FFT-only processors? */

/* A few changes:

Threshold and Multiplier now have their own
inlets, which accept (signal/float). The input
is now linear, rather than in dB. Reasons for this:

1) Linear input is the Max/MSP convention
2) It is easy to convert from linear to dB in Max
3) (My favorite) This cuts down on programmer overhead.
 
 */

typedef struct _burrow
{
#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;
    int invert;
    int *bitshuffle;
    
    float threshold;
    float multiplier;
    float mult;
    float *Wanal;	
    float *Wsyn;	
    float *inputOne;
    float *inputTwo;
    float *Hwin;
    float *bufferOne;
    float *bufferTwo;
    float *channelOne;
 	float *channelTwo;
    float *output;
    float *trigland;

	short connected[8];
	short mute;
	int overlap;//overlap factor
	int winfac;//window factor
	int vs;//vector size    	
} t_burrow;


/* msp function prototypes */

void *burrow_new(t_symbol *s, int argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *burrow_perform(t_int *w);
void burrow_dsp(t_burrow *x, t_signal **sp, short *count);
void burrow_assist(t_burrow *x, void *b, long m, long a, char *s);
void burrow_float(t_burrow *x, t_floatarg myFloat);
void burrow_init(t_burrow *x, short initialized);
void burrow_free(t_burrow *x);
void burrow_invert(t_burrow *x, t_floatarg toggle);
void burrow_mute(t_burrow *x, t_floatarg toggle);
void burrow_fftinfo(t_burrow *x);
void burrow_tilde_setup(void);
void burrow_overlap(t_burrow *x, t_floatarg o);
void burrow_winfac(t_burrow *x, t_floatarg f);


#if MSP
void main(void)
{
    setup((t_messlist **)&burrow_class,(method) burrow_new, 
(method)burrow_free, (short) sizeof(t_burrow),0, A_GIMME, 0);
    addmess((method)burrow_dsp, "dsp", A_CANT, 0);
    addmess((method)burrow_assist,"assist",A_CANT,0);    
    addmess((method)burrow_invert,"invert", A_FLOAT, 0);
	addmess((method)burrow_overlap,"overlap", A_FLOAT, 0);
	addmess((method)burrow_mute,"mute", A_FLOAT, 0);
    addmess((method)burrow_winfac,"winfac",A_FLOAT,0);
	addmess((method)burrow_fftinfo,"fftinfo", 0);
    addfloat((method)burrow_float);
    dsp_initclass();
    post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}

/* float input handling routines (MSP only) */

void burrow_float(t_burrow *x, t_floatarg myFloat)
{
int inlet = ((t_pxobject*)x)->z_in;
	if ( inlet == 2 ) // added two outlets so position is moved over
		x->threshold = myFloat; 

	if ( inlet == 3 )
		x->multiplier = myFloat;
}
#endif
#if PD
void burrow_tilde_setup(void)
{
  burrow_class = class_new(gensym("burrow~"), (t_newmethod)burrow_new, 
			  (t_method)burrow_free ,sizeof(t_burrow), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(burrow_class, t_burrow, x_f);
  class_addmethod(burrow_class, (t_method)burrow_dsp, gensym("dsp"), 0);
  class_addmethod(burrow_class, (t_method)burrow_assist, gensym("assist"), 0);
  class_addmethod(burrow_class, (t_method)burrow_invert, gensym("invert"), A_FLOAT,0);
  class_addmethod(burrow_class, (t_method)burrow_overlap, gensym("overlap"), A_FLOAT,0);
  class_addmethod(burrow_class, (t_method)burrow_mute, gensym("mute"), A_FLOAT,0);
  class_addmethod(burrow_class, (t_method)burrow_fftinfo, gensym("fftinfo"), A_CANT,0);
  class_addmethod(burrow_class,(t_method)burrow_winfac,gensym("winfac"),A_FLOAT,0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void burrow_free(t_burrow *x)
{
#if MSP
  dsp_free((t_pxobject *) x);
#endif
  free(x->trigland);
  free(x->bitshuffle);
  free(x->Wanal);
  free(x->Wsyn);
  free(x->Hwin);
  free(x->inputOne);
  free(x->inputTwo);
  free(x->bufferOne);
  free(x->bufferTwo);
  free(x->channelOne);
  free(x->channelTwo);
  free(x->output);

}


void burrow_invert(t_burrow *x, t_floatarg toggle)
{
	x->invert = toggle;
}

void burrow_mute(t_burrow *x, t_floatarg toggle)
{
  x->mute = toggle;
}

void burrow_overlap(t_burrow *x, t_floatarg o)
{
  if(!power_of_two(o)){
	error("%f is not a power of two",o);
    return;
  }
  x->overlap = o;
  burrow_init(x,1);
}

void burrow_winfac(t_burrow *x, t_floatarg f)
{
  if(!power_of_two(f)){
    error("%f is not a power of two",f);
    return;
  }
  x->winfac = (int)f;
  burrow_init(x,1);
}

void burrow_fftinfo( t_burrow *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);
}



/* diagnostic messages for Max */

void burrow_assist (t_burrow *x, void *b, long msg, long arg, char *dst)
{

  if (msg == 1) {

    switch (arg) {
    	case 0: sprintf(dst,"(signal) Source Sound"); break;
		case 1: sprintf(dst,"(signal) Burrow Filtering Sound"); break;
		case 2: sprintf(dst,"(signal/float) Filter Threshold"); break;
		case 3: sprintf(dst,"(signal/float) Filter Multiplier"); break;
    }
  }

  else {
    if (msg == 2)
      sprintf(dst,"(signal) Output");
  }
}

void burrow_init(t_burrow *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->N2 = (x->N)>>1;
  x->Nw2 = (x->Nw)>>1;
  x->inCount = -(x->Nw);
  x->mult = 1. / (float) x->N;
  if(!initialized){
    x->mute = 0;
    x->invert = 0;
    x->inputOne = (float *) calloc(MAX_Nw, sizeof(float));	
    x->inputTwo = (float *) calloc(MAX_Nw, sizeof(float));
    x->bufferOne = (float *) calloc(MAX_N, sizeof(float));
    x->bufferTwo = (float *) calloc(MAX_N, sizeof(float));
    x->channelOne = (float *) calloc((MAX_N+2), sizeof(float));
    x->channelTwo = (float *) calloc((MAX_N+2), sizeof(float));
    x->Wanal = (float *) calloc(MAX_Nw, sizeof(float));	
    x->Wsyn = (float *) calloc(MAX_Nw, sizeof(float));	
    x->Hwin = (float *) calloc(MAX_Nw, sizeof(float));
    x->output = (float *) calloc(MAX_Nw, sizeof(float));
    x->bitshuffle = (int *) calloc(MAX_N * 2, sizeof(int));
    x->trigland = (float *) calloc(MAX_N * 2, sizeof(float));
  } 
	memset((char *)x->inputOne,0,x->Nw * sizeof(float));
	memset((char *)x->inputTwo,0,x->Nw * sizeof(float));
	memset((char *)x->output,0,x->Nw * sizeof(float));
	memset((char *)x->bufferOne,0,x->N * sizeof(float));
	memset((char *)x->bufferTwo,0,x->N * sizeof(float));
  
  makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
  init_rdft( x->N, x->bitshuffle, x->trigland);
}

void *burrow_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
  t_burrow 	*x = (t_burrow *) newobject(burrow_class);
  dsp_setup((t_pxobject *)x,4);
  outlet_new((t_pxobject *)x, "signal");
#endif
#if PD
  t_burrow *x = (t_burrow *)pd_new(burrow_class);
  /* add three additional signal inlets */
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
#endif

/* optional arguments: threshold, multiplier, overlap, winfac */

  x->threshold = atom_getfloatarg(0,argc,argv);
  x->multiplier = atom_getfloatarg(1,argc,argv);
  x->overlap = atom_getfloatarg(2,argc,argv);
  x->winfac = atom_getfloatarg(3,argc,argv);
  
  if(!power_of_two(x->overlap)){
	x->overlap = 4;
  }
  if(!power_of_two(x->winfac)){
	x->winfac = 1;
  }
  if(x->threshold > 1.0 || x->threshold < 0.0){
	x->threshold = 0;
  }
  if(x->multiplier > 1.0 || x->multiplier < 0.0){
	x->multiplier = .01;
  }

 x->vs = sys_getblksize();
 x->R = sys_getsr();
 
 burrow_init(x,0);
 return(x);
 
}


t_int *burrow_perform(t_int *w)
{
/* get our inlets and outlets */
	
  t_burrow *x = (t_burrow *) (w[1]);
  t_float *inOne = (t_float *)(w[2]);
  t_float *inTwo = (t_float *)(w[3]);
  t_float *flt_threshold = (t_float *)(w[4]);
  t_float *flt_multiplier = (t_float *)(w[5]);
  t_float *out = (t_float *)(w[6]);
  t_int n = w[7];

  short *connected = x->connected;
  
  int	
			i,j,
			inCount,
			R,
			N,
			N2,
			D,
			Nw,
			invert = 0,
  			even, odd,
  	 		*bitshuffle;

  float		maxamp,	
  			threshold = 1.,
  			multiplier = 1.,
			mult,
			a1, b1,
  			a2, b2,
  			*inputOne,
			*inputTwo,
			*bufferOne,
			*bufferTwo,
			*output,
			*Wanal,
			*Wsyn,
			*channelOne,
			*channelTwo,
			*trigland;
	
/* dereference structure  */	

  inputOne = x->inputOne;
  inputTwo = x->inputTwo;
  bufferOne = x->bufferOne;
  bufferTwo = x->bufferTwo;
  inCount = x->inCount;
  
  R = x->R;
  N = x->N;
  N2 = x->N2;
  D = x->D;
  Nw = x->Nw;
  Wanal = x->Wanal;
  Wsyn = x->Wsyn;
  output = x->output;
  
  channelOne = x->channelOne;
  channelTwo = x->channelTwo;
  bitshuffle = x->bitshuffle;
  trigland = x->trigland;
  multiplier = x->multiplier;	
  threshold = x->threshold;
  mult = x->mult;
  invert = x->invert;
  
  if(connected[2]){
	threshold = *flt_threshold;
  } else {
	threshold = x->threshold;
  }
  
  if(connected[3]){
	multiplier = *flt_multiplier;
  } else {
	multiplier = x->multiplier;
  }

/* save some CPUs if muted */
  if(x->mute){
    while(n--)
      *out++ = 0.0;
    return (w+8);
  }
    
/* fill our retaining buffers */

  inCount += D;

  for ( j = 0 ; j < Nw - D ; j++ ) {
    inputOne[j] = inputOne[j+D];
    inputTwo[j] = inputTwo[j+D];
  }

  for ( j = Nw-D; j < Nw; j++ ) {
    inputOne[j] = *inOne++;
    inputTwo[j] = *inTwo++;
  }

/* apply hamming window and fold our window buffer into the fft buffer */ 

  fold( inputOne, Wanal, Nw, bufferOne, N, inCount );
  fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount );


/* do an fft */ 

  rdft( N, 1, bufferOne, bitshuffle, trigland );
  rdft( N, 1, bufferTwo, bitshuffle, trigland );

/* use redundant coding for speed, even though moving the invert variable
   comparison outside of the for loop will give us only a minimal performance
   increase (hypot and atan2 are the most intensive portions of this code).
   consider adding a table lookup for atan2 instead.
*/


if (invert) {

/* convert to polar coordinates from complex values */
 
    for ( i = 0; i <= N2; i++ ) {
    
      odd = ( even = i<<1 ) + 1;

      a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) );
      b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) );
    
      a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) );
      b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) );

      *(channelOne+even) = hypot( a1, b1 );
      *(channelOne+odd) = -atan2( b1, a1 );
    
      *(channelTwo+even) = hypot( a2, b2 );

	/* use simple threshold from second signal to trigger filtering */
      
      if ( *(channelTwo+even) < threshold )
      	*(channelOne+even) *= multiplier;
      
/*      *(channelTwo+odd) = -atan2( b2, a2 );  */

    }  
}

else {

/* convert to polar coordinates from complex values */
 
    for ( i = 0; i <= N2; i++ ) {
    
      odd = ( even = i<<1 ) + 1;

      a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) );
      b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) );
    
      a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) );
      b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) );

      *(channelOne+even) = hypot( a1, b1 );
      *(channelOne+odd) = -atan2( b1, a1 );
    
      *(channelTwo+even) = hypot( a2, b2 );

	/* use simple threshold from second signal to trigger filtering */
      
      if ( *(channelTwo+even) > threshold )
      	*(channelOne+even) *= multiplier;
      
/*      *(channelTwo+odd) = -atan2( b2, a2 );  */

    }  
}

/* convert back to complex form, read for the inverse fft */

  for ( i = 0; i <= N2; i++ ) {

    odd = ( even = i<<1 ) + 1;

    *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) );

    if ( i != N2 )
      *(bufferOne+odd) = -(*(channelOne+even)) * sin( *(channelOne+odd) );
  }


/* do an inverse fft */

  rdft( N, -1, bufferOne, bitshuffle, trigland );

/* dewindow our result */

  overlapadd( bufferOne, N, Wsyn, output, Nw, inCount);

/* set our output and adjust our retaining output buffer */

  for ( j = 0; j < D; j++ )
    *out++ = output[j] * mult;
	
  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
  
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;
		

/* restore state variables */

  x->inCount = inCount % Nw;
  return (w+8);
}		

void burrow_dsp(t_burrow *x, t_signal **sp, short *count)
{
	long i;
	#if MSP
	  for( i = 0; i < 4; i++ ){
		x->connected[i] = count[i];
	  }
	#endif
	/* signal is always connected in Pd */
	#if PD 
	  for( i = 0; i < 4; i++ ){
		x->connected[i] = 1;
	  }
	#endif
  /* reinitialize if vector size or sampling rate has been changed */
  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;
    burrow_init(x,1);
  }	
	dsp_add(burrow_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);
}


--- NEW FILE: pvwarp~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *pvwarp_class;
#endif 

#if PD
static t_class *pvwarp_class;
#endif

#define OBJECT_NAME "pvwarp~"

typedef struct _pvwarp
{
#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;
	// for convert
	float *c_lastphase_in;
	float *c_lastphase_out;
	float c_fundamental;
	float c_factor_in;
	float c_factor_out;
	float P;
	int L;
	int first;
	float Iinv;
	float *lastamp;
	float *lastfreq;
	float *windex;
	float *table;
	float myPInc;
	float ffac;
	//
	int lo_bin;
	int hi_bin;
	float lofreq;//user speficied lowest synthfreq
		float hifreq;// user specified highest synthfreq
			float topfreq;
			float synt;
			float myPI;
			float TWOmyPI;
			// for fast fft
			float mult; 
			float *trigland;
			int *bitshuffle;
			//
			short *connections;
			short mute;
			short bypass;
			int pitch_connected;
			int synt_connected;
			float *warpfunc ;
			short please_update;
			short always_update;
			float cf1;
			float bw1;
			float warpfac1;
			float cf2;
			float bw2;
			float warpfac2;
			int funcoff;
			short verbose;
			short automate;
			int overlap;//overlap factor
				int winfac;// window factor
					int vs;//last measurement of vector size
} t_pvwarp;

void *pvwarp_new(t_symbol *s, int argc, t_atom *argv);
//t_int *offset_perform(t_int *w);
t_int *pvwarp_perform(t_int *w);
void pvwarp_dsp(t_pvwarp *x, t_signal **sp, short *count);
void pvwarp_assist(t_pvwarp *x, void *b, long m, long a, char *s);
void pvwarp_bypass(t_pvwarp *x, t_floatarg state);
void pvwarp_mute(t_pvwarp *x, t_floatarg state);
void pvwarp_verbose(t_pvwarp *x, t_floatarg state);
void pvwarp_overlap(t_pvwarp *x, t_floatarg o);
void pvwarp_automate(t_pvwarp *x, t_floatarg state);
void pvwarp_autofunc(t_pvwarp *x, t_floatarg minval, t_floatarg maxval);
void pvwarp_float(t_pvwarp *x, t_float f);
void pvwarp_dsp_free( t_pvwarp *x );
void pvwarp_fftinfo( t_pvwarp *x );
float myrand( float min, float max );
float closestf(float test, float *arr) ;
int freq_to_bin( float target, float fundamental );
void update_warp_function( t_pvwarp *x ) ;
void pvwarp_init(t_pvwarp *x, short initialized);
void pvwarp_bottomfreq(t_pvwarp *x, t_floatarg f);
void pvwarp_topfreq(t_pvwarp *x, t_floatarg f);
void pvwarp_fftinfo(t_pvwarp *x);
void pvwarp_overlap(t_pvwarp *x, t_floatarg f);
void pvwarp_winfac(t_pvwarp *x, t_floatarg f);;

#if MSP
void main(void)
{
	setup((t_messlist **)&pvwarp_class, (method)pvwarp_new, (method)pvwarp_dsp_free, (short)sizeof(t_pvwarp), 
		  0, A_GIMME, 0);
	addmess((method)pvwarp_dsp, "dsp", A_CANT, 0);
	addmess((method)pvwarp_assist,"assist",A_CANT,0);
	addmess((method)pvwarp_bypass,"bypass",A_DEFFLOAT,0);
	addmess((method)pvwarp_mute,"mute",A_DEFFLOAT,0);
	addmess((method)pvwarp_verbose,"verbose",A_DEFFLOAT,0);
	addmess((method)pvwarp_overlap,"overlap",A_FLOAT,0);
	addmess((method)pvwarp_bottomfreq,"bottomfreq",A_FLOAT,0);
	addmess((method)pvwarp_topfreq,"topfreq",A_FLOAT,0);
	addmess((method)pvwarp_fftinfo,"fftinfo",0);
	addmess((method)pvwarp_autofunc,"autofunc",A_DEFFLOAT, A_DEFFLOAT,0);
	addmess((method)pvwarp_overlap,"overlap",A_DEFFLOAT,0);
	addmess((method)pvwarp_winfac,"winfac",A_DEFFLOAT,0);
	addmess((method)pvwarp_fftinfo,"fftinfo",0);
	addfloat((method)pvwarp_float);
	dsp_initclass();
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
/* Pd Initialization */
void pvwarp_tilde_setup(void)
{
	pvwarp_class = class_new(gensym("pvwarp~"), (t_newmethod)pvwarp_new, 
							 (t_method)pvwarp_dsp_free ,sizeof(t_pvwarp), 0,A_GIMME,0);
	CLASS_MAINSIGNALIN(pvwarp_class, t_pvwarp, x_f);
	class_addmethod(pvwarp_class, (t_method)pvwarp_dsp, gensym("dsp"), 0);
	class_addmethod(pvwarp_class, (t_method)pvwarp_mute, gensym("mute"), A_DEFFLOAT,0);
	class_addmethod(pvwarp_class, (t_method)pvwarp_bypass, gensym("bypass"), A_DEFFLOAT,0);
	class_addmethod(pvwarp_class, (t_method)pvwarp_overlap, gensym("overlap"), A_DEFFLOAT,0);
	class_addmethod(pvwarp_class, (t_method)pvwarp_bottomfreq, gensym("bottomfreq"), A_DEFFLOAT,0);
	class_addmethod(pvwarp_class, (t_method)pvwarp_topfreq, gensym("topfreq"), A_DEFFLOAT, 0);
	class_addmethod(pvwarp_class, (t_method)pvwarp_automate, gensym("automate"), A_DEFFLOAT, 0);
	class_addmethod(pvwarp_class, (t_method)pvwarp_autofunc, gensym("autofunc"), A_DEFFLOAT,A_DEFFLOAT,0);
	class_addmethod(pvwarp_class,(t_method)pvwarp_overlap,gensym("overlap"),A_FLOAT,0);
	class_addmethod(pvwarp_class,(t_method)pvwarp_winfac,gensym("winfac"),A_FLOAT,0);
	class_addmethod(pvwarp_class,(t_method)pvwarp_fftinfo,gensym("fftinfo"),0);
	//  addfloat((method)pvwarp_float);
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void pvwarp_automate(t_pvwarp *x, t_floatarg state)
{
	x->automate = state;
}
void pvwarp_overlap(t_pvwarp *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;
	pvwarp_init(x,1);
}

void pvwarp_winfac(t_pvwarp *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;
	pvwarp_init(x,2);
}

void pvwarp_fftinfo(t_pvwarp *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);
}

float myrand ( float min, float max )
{
	return (min + (max-min) * ((float) (rand() % 32768) / (float) 32768.0));
}
void update_warp_function( t_pvwarp *x ) 
{
	int i,j;
	int N2 = x->N2;
	float *warpfunc = x->warpfunc;
	float warpfac1 = x->warpfac1;
	float warpfac2 = x->warpfac2;
	
	float cf1 = x->cf1;
	float cf2 = x->cf2;
	float bw1 = x->bw1;
	float bw2 = x->bw2;
	float c_fundamental = x->c_fundamental;
	float deviation;
	float diff;
	int midbin, lobin, hibin ;
	float hif, lof;
	int bin_extent;
	short verbose = x->verbose;
	
	for( i = 0; i < N2; i++ ){
		warpfunc[i] = 1.0;
	}
	hif = cf1 * (1. + bw1);
	lof = cf1 * (1. - bw1);
	midbin = freq_to_bin( cf1, c_fundamental );
	hibin = freq_to_bin( hif, c_fundamental );
	lobin = freq_to_bin( lof, c_fundamental );
	if( hibin >= N2 - 1 ){
		hibin = N2 - 1;
	}
	if( lobin < 0 ){
		lobin = 0;
	} 
	if( verbose )
		post("bump1: hi %d mid %d lo %d",hibin,midbin,lobin);
	
	warpfunc[midbin] = warpfac1;
	diff = warpfac1 - 1.0 ;
	bin_extent = hibin - midbin ;
	for( i = midbin, j = 0; i < hibin; i++, j++ ){
		deviation = diff * ((float)(bin_extent - j) / (float) bin_extent );
		warpfunc[ i ] += deviation ;
	}
	bin_extent = midbin - lobin ;
	for( i = midbin, j = 0; i > lobin; i--, j++ ){
		deviation = diff * ((float)(bin_extent - j) / (float) bin_extent );
		warpfunc[ i ] += deviation ;
	}
	
	// NOW DO SECOND BUMP
	hif = cf2 * (1. + bw2);
	lof = cf2 * (1. - bw2);
	midbin = freq_to_bin( cf2, c_fundamental );
	hibin = freq_to_bin( hif, c_fundamental );
	lobin = freq_to_bin( lof, c_fundamental );
	if( hibin >= N2 - 1 ){
		hibin = N2 - 1;
	}
	if( lobin < 0 ){
		lobin = 0;
	} 
	if( verbose )
		post("bump2: hi %d mid %d lo %d",hibin,midbin,lobin);
	warpfunc[midbin] = warpfac2;
	diff = warpfac2 - 1.0 ;
	bin_extent = hibin - midbin ;
	for( i = midbin, j = 0; i < hibin; i++, j++ ){
		deviation = diff * ((float)(bin_extent - j) / (float) bin_extent );
		warpfunc[ i ] += deviation ;
	}
	bin_extent = midbin - lobin ;
	for( i = midbin, j = 0; i > lobin; i--, j++ ){
		deviation = diff * ((float)(bin_extent - j) / (float) bin_extent );
		warpfunc[ i ] += deviation ;
	}
	
	x->please_update = 0;
	//	return( x );
	
}
void pvwarp_verbose(t_pvwarp *x, t_floatarg state)
{
	x->verbose = state;	
}

void pvwarp_autofunc(t_pvwarp *x, t_floatarg minval, t_floatarg maxval)
{
	int minpoints, maxpoints, segpoints, i;
	int pointcount = 0;
	float target, lastval;
	float m1, m2;
	int N2 = x->N2;
	float *warpfunc = x->warpfunc;
	/////
	
	minpoints = 0.05 * (float) N2;
	maxpoints = 0.25 * (float) N2;
	if( minval > 1000.0 || minval < .001 ){
		minval = 0.5;
	}
	if( maxval < 0.01 || maxval > 1000.0 ){
		minval = 2.0;
	}
	
	lastval = myrand(minval, maxval);
	// post("automate: min %d max %d",minpoints, maxpoints);
	while( pointcount < N2 ){
		target = myrand(minval, maxval);
		segpoints = minpoints + (rand() % (maxpoints-minpoints));
		if( pointcount + segpoints > N2 ){
			segpoints = N2 - pointcount;
		}
		for( i = 0; i < segpoints; i++ ){
			m2 = (float)i / (float) segpoints ;
			m1 = 1.0 - m2;
			warpfunc[ pointcount + i ] = m1 * lastval + m2 * target;
		}
		lastval = target;
		pointcount += segpoints;
	}
}

void pvwarp_bypass(t_pvwarp *x, t_floatarg state)
{
	x->bypass = state;	
}
void pvwarp_mute(t_pvwarp *x, t_floatarg state)
{
	x->mute = state;	
}

void pvwarp_dsp_free( t_pvwarp *x ){
#if MSP
	dsp_free( (t_pxobject *) x);
#endif
	free(x->c_lastphase_in);
	free(x->c_lastphase_out);
	free(x->trigland);
	free(x->bitshuffle);
	free(x->Wanal);
	free(x->Wsyn);
	free(x->input);
	free(x->Hwin);
	free(x->buffer);
	free(x->channel);
	free(x->output);
	free(x->lastamp);
	free(x->lastfreq);
	free(x->windex);
	free(x->table);
	free(x->warpfunc);
	free(x->connections);
}

void pvwarp_assist (t_pvwarp *x, void *b, long msg, long arg, char *dst)
{
	if (msg==1) {
		switch (arg) {
			case 0:
				sprintf(dst,"(signal) Input ");
				break;
			case 1:
				sprintf(dst,"(signal/float) Center Frequency 1");
				break;
			case 2:
				sprintf(dst,"(signal/float) Bandwidth Factor 1");
				break;
			case 3:
				sprintf(dst,"(signal/float) Warp Factor 1");
				break;
			case 4:
				sprintf(dst,"(signal/float) Center Frequency 2");
				break;
			case 5:
				sprintf(dst,"(signal/float) Bandwidth Factor 2");
				break;
			case 6:
				sprintf(dst,"(signal/float) Warp Factor 2");
				break;
			case 7:
				sprintf(dst,"(signal/float) Function Offset (0.0-1.0) ");
				break;
			case 8:
				sprintf(dst,"(signal/float) Pitch Factor");
				break;
			case 9:
				sprintf(dst,"(signal/float) Synthesis Gate Value");
				break;
				
		}
	} else if (msg==2) {
		sprintf(dst,"(signal) Output");
	}
}

void *pvwarp_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
	t_pvwarp *x = (t_pvwarp *)newobject(pvwarp_class);
	dsp_setup((t_pxobject *)x,10);
	outlet_new((t_pxobject *)x, "signal");
#endif
#if PD
	int i;
	t_pvwarp *x = (t_pvwarp *)pd_new(pvwarp_class);
	for(i=0;i<9;i++)
		inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
	outlet_new(&x->x_obj, gensym("signal"));
#endif
	
	x->lofreq = atom_getfloatarg(0,argc,argv);
	x->hifreq = atom_getfloatarg(1,argc,argv);
	x->overlap = atom_getfloatarg(2,argc,argv);
	x->winfac = atom_getfloatarg(3,argc,argv);
	if(!x->overlap)
		x->overlap = 4;
	if(!x->winfac)
		x->winfac = 2;
	x->D = sys_getblksize();  
	x->R = sys_getsr();	
	pvwarp_init(x,0);
	
	return (x);
}

void pvwarp_init(t_pvwarp *x, short initialized)
{
	int i, j;
	float funda, curfreq;
	x->N = x->D * x->overlap;
	x->Nw = x->N * x->winfac;
	limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
	x->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->c_fundamental =  (float) x->R/(float)( (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;
	x->inCount = -(x->Nw);
	x->mult = 1. / (float) x->N;
	x->Iinv = 1./x->D;
	x->myPInc = x->P*x->L/x->R;// really needed
		x->ffac = x->P * PI/x->N;  
	  	    
		if(!initialized){
			srand(clock());
			x->L = 8192;
			x->P = 1.0 ; //initialization only
			
			x->please_update = 0;
			x->verbose = 0;
			x->bypass = 0;
			x->mute = 0;
			x->topfreq = 3000. ;
			x->always_update = 0;
			x->automate = 0;
			x->warpfac1 = 1.0;
			x->warpfac2 = 1.0;
			x->funcoff = 0;
			x->cf1 = 500.;
			x->cf2 = 3000.;
			x->bw1 = 0.2;
			x->bw2 = 0.2;
			x->synt = .000001;
			
			x->connections = (short *) calloc(16, sizeof(short));	
			x->Wanal = (float *) calloc(MAX_Nw, sizeof(float));	
			x->Wsyn = (float *) calloc(MAX_Nw, sizeof(float));	
			x->input = (float *) calloc(MAX_Nw, sizeof(float));	
			x->Hwin = (float *) calloc(MAX_Nw, sizeof(float));
			x->buffer = (float *) calloc(MAX_N, sizeof(float));
			x->channel = (float *) calloc(MAX_N+2, sizeof(float));
			x->output = (float *) calloc(MAX_Nw, sizeof(float));
			x->bitshuffle = (int *) calloc(MAX_N * 2, sizeof(int));
			x->trigland = (float *) calloc(MAX_N * 2, sizeof(float));
			x->warpfunc = (float *) calloc(MAX_N2, sizeof(float));
			x->lastamp = (float *) calloc(MAX_N+1, sizeof(float));
			x->lastfreq = (float *) calloc(MAX_N+1, sizeof(float));
			x->windex = (float *) calloc(MAX_N+1, sizeof(float));
			x->table = (float *) calloc(x->L, sizeof(float));
			x->c_lastphase_in = (float *) calloc(MAX_N2+1, sizeof(float));
			x->c_lastphase_out = (float *) calloc(MAX_N2+1, sizeof(float));
			
		}
		for (i = 0; i < x->L; i++) {
			x->table[i] = (float) x->N * cos((float)i * TWOPI / (float)x->L);
		}
		
		memset((char *)x->input,0,x->Nw * sizeof(float));
		memset((char *)x->output,0,x->Nw * sizeof(float));
		memset((char *)x->buffer,0,x->N * sizeof(float));
		memset((char *)x->channel,0,(x->N+2) * sizeof(float));
		memset((char *)x->lastfreq,0,(x->N+1) * sizeof(float));
		memset((char *)x->lastamp,0,(x->N+1) * sizeof(float));
		// added
		memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float));
		memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float));
		memset((char *)x->windex,0,(x->N+1) * sizeof(float));
		
		if( x->hifreq < x->c_fundamental ) {
			x->hifreq = 1000.0;// arbitrary
		}
		x->hi_bin = 1;  
		curfreq = 0;
		while( curfreq < x->hifreq ) {
			++(x->hi_bin);
			curfreq += x->c_fundamental ;
		}
		if( x->hi_bin >= x->N2 )
			x->hi_bin = x->N2 - 1;
		x->lo_bin = 0;  
		curfreq = 0;
		while( curfreq < x->lofreq ) {
			++(x->lo_bin);
			curfreq += x->c_fundamental ;
		}	
		update_warp_function(x);
		init_rdft(x->N, x->bitshuffle, x->trigland);
		makehanning(x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
		//  post("FFT size: %d",x->N);
}



void pvwarp_bottomfreq(t_pvwarp *x, t_floatarg f)
{
	int tbin;
	float curfreq;
	float fundamental = x->c_fundamental;
	tbin = 1;  
	curfreq = 0;
	
	if( f < 0 || f > x->R / 2.0 ){
		error("frequency %f out of range", f);
		return;
	}
	
	while( curfreq < f ) {
		++tbin;
		curfreq += fundamental ;
	}
	
	if( tbin < x->hi_bin && tbin >= 0 ){
		x->lo_bin = tbin;
		x->lofreq = f;
	} else {
		error("bin %d out of range", tbin);
	}
	
}

void pvwarp_topfreq(t_pvwarp *x, t_floatarg f)
{
	int tbin;
	float curfreq;
	float fundamental = x->c_fundamental;
	tbin = 1;  
	curfreq = 0;
	
	if( f < 0 || f > x->R / 2.0 ){
		error("frequency %f out of range", f);
		return;
	}
	
	while( curfreq < f ) {
		++tbin;
		curfreq += fundamental ;
	}
	
	if( tbin > x->lo_bin && tbin < x->N2 - 1 ){
		x->hi_bin = tbin;
		x->hifreq = f;
	} else {
		error("bin %d out of range", tbin);
	}
	
}

t_int *pvwarp_perform(t_int *w)
{
	int 	i,j, in,on;
	int    amp,freq,chan,NP,L = 8192;
	
	float    a,ainc,f,finc,address;
	int breaker = 0;
	t_pvwarp *x = (t_pvwarp *) (w[1]);
	
	t_float *inbuf = (t_float *)(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 *in4 = (t_float *)(w[6]);
	t_float *in5 = (t_float *)(w[7]);
	t_float *in6 = (t_float *)(w[8]);
	t_float *in7 = (t_float *)(w[9]);
	t_float *in8 = (t_float *)(w[10]);
	t_float *in9 = (t_float *)(w[11]);
	t_float *outbuf = (t_float *)(w[12]);
	t_int n = w[13];
	
	int D = x->D;
	int I = D;
	int R = x->R;
	int Nw = x->Nw;
	int N = x->N ;
	int N2 = x-> N2;
	int Nw2 = x->Nw2;
	float fundamental = x->c_fundamental;
	float factor_in =  x->c_factor_in;
	float factor_out = x->c_factor_out;
	int *bitshuffle = x->bitshuffle;
	float *trigland = x->trigland;
	float mult = x->mult;	
	float warpfac1 = x->warpfac1;
	float warpfac2 = x->warpfac2;
	int funcoff;
	float P;
	float synt;	
	
	float Iinv = 1./x->D;
	float myPInc = x->myPInc;
	
	/* assign pointers */
	
	float *table = x->table;
	float *lastamp = x->lastamp ;
	float *lastfreq = x->lastfreq ;
	float *windex = x->windex;
	float *lastphase_in = x->c_lastphase_in;
	float *lastphase_out = x->c_lastphase_out;
	
	float *Wanal = x->Wanal;
	float *Wsyn = x->Wsyn;
	float *input = x->input;
	float *Hwin = x->Hwin;
	float *buffer = x->buffer;
	float *channel = x->channel;
	float *output = x->output;
	short *connections = x->connections;
	float *warpfunc;
	
	int hi_bin = x->hi_bin;
	int lo_bin = x->lo_bin;
	
	if(!x->automate) {
		if( connections[0] ) {
			x->cf1  = *in1 ; 
		}
		if ( connections[1] ) {
			x->bw1 = *in2 ;
		}
		if ( connections[2] ) {
			x->warpfac1 = *in3 ;
		}
		if( connections[3] ) {
			x->cf2  = *in4 ; 
		}
		if ( connections[4] ) {
			x->bw2 = *in5 ;
		}
		if ( connections[5] ) {
			x->warpfac2 = *in6 ;
		}
	}  
	
	if( connections[6] ) {
		f  = *in7 ; 
		if( f < 0 ) {
			f = 0.0;
		} else if (f > 1.0 ){
			f = 1.0;
		}
		x->funcoff = f * (float) (N2 - 1);
	}
	if ( connections[7] ) {
		x->P = *in8 ;
		x->myPInc = x->P*x->L/x->R;
	}
	if ( connections[8] ) {
		x->synt = *in9 ;
	}
	P= x->P;
	synt = x->synt;
	funcoff = x->funcoff;  	
	
	
	if( (x->please_update || x->always_update)  && ! x->automate){
		update_warp_function(x);
	}
	warpfunc = x->warpfunc;
	
	in = on = x->inCount ;
	if( x->mute) {
		for ( j = 0; j < n; j++ ){
			outbuf[j] = 0.;
		}
		return (w+14);
	}	
	else if( x->bypass ) {
		for ( j = 0; j < n; j++ ){
			outbuf[j] = *inbuf++;
		}
		return (w+14);
	} else {
		
		in = on = x->inCount ;
		
		
		in += D;
		on += I;
		
		for ( j = 0 ; j < (Nw - D) ; j++ ){
			input[j] = input[j+D];
		}
		for ( j = (Nw-D), i = 0 ; j < Nw; j++, i++ ) {
			input[j] = *inbuf++;
		}
		
		fold( input, Wanal, Nw, buffer, N, in );   
		rdft( N, 1, buffer, bitshuffle, trigland );
		convert( buffer, channel, N2, lastphase_in, fundamental, factor_in );
		
		
		// start osc bank 
		
		for ( chan = lo_bin; chan < hi_bin; chan++ ) {
			
			freq = ( amp = ( chan << 1 ) ) + 1;
			if ( channel[amp] < synt ){ 
				breaker = 1;
			}
			if( breaker ) {
				breaker = 0 ;
			} else {
				
				/* HERE IS WHERE WE WARP THE SPECTRUM */
				channel[freq] *= myPInc * warpfunc[(chan + funcoff) % N2];
				finc = ( channel[freq] - ( f = lastfreq[chan] ) )*Iinv;
				ainc = ( channel[amp] - ( a = lastamp[chan] ) )*Iinv;
				address = windex[chan];
				for ( n = 0; n < I; n++ ) {
					output[n] += a*table[ (int) address ];
				    
					address += f;
					while ( address >= L )
						address -= L;
					while ( address < 0 )
						address += L;
					a += ainc;
					f += finc;
				}
				lastfreq[chan] = channel[freq];
				lastamp[chan] = channel[amp];
				windex[chan] = address;
			}
		}
		
		
		for ( j = 0; j < D; j++ ){
			*outbuf++ = output[j] * mult;
		}
		for ( j = 0; j < Nw - D; j++ ){
			output[j] = output[j+D];
		}
		
		for ( j = Nw - D; j < Nw; j++ ){
			output[j] = 0.;
		}	
		
		
		
		/* restore state variables */
		x->inCount = in % Nw;
		return (w+14);
	}
	
}		


int freq_to_bin( float target, float fundamental ){
	float lastf = 0.0;
	float testf = 0.0;
	int thebin = 0;
	while( testf < target ){
		++thebin;
		lastf = testf;
		testf += fundamental;
	}
	
	if(fabs(target - testf) < fabs(target - lastf) ){
		return thebin;
	} else {
		return (thebin - 1);
	}
}
#if MSP
void pvwarp_float(t_pvwarp *x, t_float f) // Look at floats at inlets
{
	int inlet = ((t_pxobject*)x)->z_in;
	int N2 = x->N2;
	if (inlet == 1){
		x->cf1 = f;
		x->please_update = 1;
	} else if (inlet == 2) {
		x->bw1 = f;
		x->please_update = 1;
	} else if (inlet == 3) {
		x->warpfac1 = f;
		x->please_update = 1;
	} else if (inlet == 4) {
		x->cf2 = f;
		x->please_update = 1;
		
	} else if (inlet == 5) {
		x->bw2 = f;
		x->please_update = 1;
		
	} else if (inlet == 6) {
		x->warpfac2 = f;
		x->please_update = 1;
	} else if (inlet == 7) {
		if( f < 0 ) {
			f = 0.0;
		} else if (f > 1.0 ){
			f = 1.0;
		}
		x->funcoff = f * (float) (x->N2 - 1);
	} else if (inlet == 8) {
		x->P = f;
		x->myPInc = x->P*x->L/x->R;
		
	} else if (inlet == 9)
    {
		x->synt = f;
    }
}
#endif

void pvwarp_dsp(t_pvwarp *x, t_signal **sp, short *count)
{
	long i;
	x->always_update = 0;
#if MSP
	for( i = 1; i < 10; i++ ){
		// only the first 6 inlets alter warp function
		if( i < 6 ){
			x->always_update += count[i];
		}
		x->connections[i-1] = count[i];
		// post("connection %d: %d", i-1, count[i]);
	}
#endif
#if PD
	x->always_update = 1;
	for(i=0;i<10;i++){
		x->connections[i] = 1;
	}
#endif
	
	if(x->D != sp[0]->s_n || x->R != sp[0]->s_sr){
		x->D = sp[0]->s_n;
		x->R = sp[0]->s_sr;
		pvwarp_init(x,1);
	}
	dsp_add(pvwarp_perform, 13, x, 
			sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, 
			sp[4]->s_vec, sp[5]->s_vec, sp[6]->s_vec, sp[7]->s_vec, 
			sp[8]->s_vec, sp[9]->s_vec, sp[10]->s_vec,
			sp[0]->s_n);
}

--- NEW FILE: ether~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *ether_class;
#endif
#if PD
static t_class *ether_class;
#endif

#define OBJECT_NAME "ether~"


/* Added a new inlet for the composite index */

typedef struct _ether
{
#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;
    int invert;
    int *bitshuffle;
    
    float threshMult;
    float *Wanal;	
    float *Wsyn;	
    float *inputOne;
    float *inputTwo;
    float *Hwin;
    float *bufferOne;
    float *bufferTwo;
    float *channelOne;
 	float *channelTwo;
    float *output;
    float mult; 
    float *trigland;
  short connected[8];
  short mute;
  int overlap;//overlap factor
  int winfac;//window factor
  int vs;//vector size  
    	
} t_ether;


void *ether_new(t_symbol *s, int argc, t_atom *argv);
t_int *ether_perform(t_int *w);
void ether_dsp(t_ether *x, t_signal **sp, short *count);
void ether_assist(t_ether *x, void *b, long m, long a, char *s);
void ether_dest(t_ether *x, double f);
void ether_invert(t_ether *x, t_floatarg toggle);
void ether_init(t_ether *x, short initialized);
void ether_free(t_ether *x);
void ether_mute(t_ether *x, t_floatarg toggle);
void ether_fftinfo(t_ether *x);
void ether_winfac(t_ether *x, t_floatarg f);
void ether_overlap(t_ether *x, t_floatarg o);
void ether_tilde_setup(void);


#if MSP
void main(void)
{
    setup((t_messlist **)&ether_class, (method) ether_new, (method)ether_free, (short) sizeof(t_ether),
    		0, A_GIMME, 0);
  
    addmess((method)ether_dsp, "dsp", A_CANT, 0);
    addmess((method)ether_assist,"assist",A_CANT,0);    
    addfloat((method)ether_dest);
    addmess((method)ether_invert,"invert", A_FLOAT, 0);
    addmess((method)ether_mute,"mute", A_FLOAT, 0);
     addmess((method)ether_overlap,"overlap", A_FLOAT, 0);   
     addmess((method)ether_winfac,"winfac", A_FLOAT, 0);
     addmess((method)ether_fftinfo,"fftinfo",  0);
    dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);

}

void ether_dest(t_ether *x, double f)
{
	x->threshMult = (float) f;	
}
#endif

#if PD
void ether_tilde_setup(void)
{
  ether_class = class_new(gensym("ether~"), (t_newmethod)ether_new, 
			     (t_method)ether_free ,sizeof(t_ether), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(ether_class, t_ether, x_f);
  class_addmethod(ether_class, (t_method)ether_dsp, gensym("dsp"), 0);
  class_addmethod(ether_class, (t_method)ether_assist, gensym("assist"), 0);
  class_addmethod(ether_class, (t_method)ether_invert, gensym("invert"), A_FLOAT,0);
  class_addmethod(ether_class, (t_method)ether_overlap, gensym("overlap"), A_FLOAT,0);
  class_addmethod(ether_class, (t_method)ether_mute, gensym("mute"), A_FLOAT,0);
  class_addmethod(ether_class, (t_method)ether_winfac, gensym("winfac"), A_FLOAT,0);
  class_addmethod(ether_class, (t_method)ether_fftinfo, gensym("fftinfo"), A_CANT,0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif



/* diagnostic messages for Max */


void ether_assist (t_ether *x, void *b, long msg, long arg, char *dst)
{

  if (msg == 1) {

    switch (arg) {

    	case 0:		sprintf(dst,"(signal) Input One");break;
    	case 1:		sprintf(dst,"(signal) Input Two"); break;
    	case 2:		sprintf(dst,"(signal) Composite Index"); break;
    }
  }

  else {

    if (msg == 2)
      sprintf(dst,"(signal) Output");

  }
}

void ether_free(t_ether *x)
{
#if MSP
  dsp_free((t_pxobject *) x);
#endif
  freebytes(x->trigland,0);
  freebytes(x->bitshuffle,0);
  freebytes(x->Wanal,0);
  freebytes(x->Wsyn,0);
  freebytes(x->Hwin,0);
  freebytes(x->inputOne,0);
  freebytes(x->inputTwo,0);
  freebytes(x->bufferOne,0);
  freebytes(x->bufferTwo,0);
  freebytes(x->channelOne,0);
  freebytes(x->channelTwo,0);
  freebytes(x->output,0);
}

void ether_overlap(t_ether *x, t_floatarg df)
{
int o = (int)df;
  if(!power_of_two(o)){
    error("%d is not a power of two",o);
    return;
  }
  x->overlap = o;
  ether_init(x,1);
}

void ether_winfac(t_ether *x, t_floatarg f)
{
int wf = (int)f;
  if(!power_of_two(wf)){
    error("%f is not a power of two",f);
    return;
  }
  x->winfac = wf;
  ether_init(x,1);
}

void ether_fftinfo( t_ether *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 *ether_new(t_symbol *s, int argc, t_atom *argv)
{

#if MSP
  t_ether 	*x = (t_ether *) newobject(ether_class);
  dsp_setup((t_pxobject *)x,3);
  outlet_new((t_pxobject *)x, "signal");
#endif
#if PD
  t_ether *x = (t_ether *)pd_new(ether_class);
  /* add two additional signal inlets */
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
#endif

/* optional arguments: overlap winfac */
	
  x->overlap = atom_getfloatarg(0,argc,argv);
  x->winfac = atom_getfloatarg(1,argc,argv);
  if(!power_of_two(x->overlap)){
    x->overlap = 4;
  }
  if(!power_of_two(x->winfac)){
    x->winfac = 1;
  }
  x->vs = sys_getblksize();
  x->R = sys_getsr();
  ether_init(x,0);
  
  return (x);
}

void ether_init(t_ether *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->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->inCount = -(x->Nw);
	x->mult = 1. / (float) x->N;
	if(!initialized){
		x->mute = 0;
		x->invert = 0;
		x->threshMult = 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->inputOne = (float *) getbytes(MAX_Nw * sizeof(float));	
		x->inputTwo = (float *) getbytes(MAX_Nw  * sizeof(float));
		x->bufferOne = (float *) getbytes(MAX_N  * sizeof(float));
		x->bufferTwo = (float *) getbytes(MAX_N  * sizeof(float));
		x->channelOne = (float *) getbytes(MAX_N+2  * sizeof(float));
		x->channelTwo = (float *) getbytes(MAX_N+2  * sizeof(float));
		x->output = (float *) getbytes(MAX_Nw * sizeof(float));
		x->bitshuffle = (int *) getbytes(MAX_N * 2 * sizeof(int));
		x->trigland = (float *) getbytes(MAX_N * 2 * sizeof(float));
	} 
		memset((char *)x->inputOne,0,x->Nw * sizeof(float));
		memset((char *)x->inputTwo,0,x->Nw * sizeof(float));
		memset((char *)x->output,0,x->Nw * sizeof(float));

	init_rdft( x->N, x->bitshuffle, x->trigland);
	makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 1);
	
}


t_int *ether_perform(t_int *w)
{

  int		i,j,
			inCount,
			R,
			N,
			N2,
			D,
			Nw,
			invert = 1,
  			even, odd,
  	 		*bitshuffle;

  float		maxamp,	
  			threshMult = 1.,
			mult,
			a1, b1,
  			a2, b2,
  			*inputOne,
			*inputTwo,
			*bufferOne,
			*bufferTwo,
			*output,
			*Wanal,
			*Wsyn,
			*channelOne,
			*channelTwo,
			*trigland;

  
/* get our inlets and outlets */
	
  t_ether *x = (t_ether *) (w[1]);
  t_float *inOne = (t_float *)(w[2]);
  t_float *inTwo = (t_float *)(w[3]);
  t_float *vec_threshMult = (t_float *)(w[4]);
  t_float *out = (t_float *)(w[5]);
  t_int n = w[6];
	
  short *connected = x->connected;
  
/* dereference structure  */	

  inputOne = x->inputOne;
  inputTwo = x->inputTwo;
  bufferOne = x->bufferOne;
  bufferTwo = x->bufferTwo;
  inCount = x->inCount;
  R = x->R;
  N = x->N;
  N2 = x->N2;
  D = x->D;
  Nw = x->Nw;
  Wanal = x->Wanal;
  Wsyn = x->Wsyn;
  output = x->output;
  channelOne = x->channelOne;
  channelTwo = x->channelTwo;
  bitshuffle = x->bitshuffle;
  trigland = x->trigland;
  mult = x->mult;	
  invert = x->invert;
  
  if(connected[2]){
  	threshMult = *vec_threshMult;
  }
  else if ( x->threshMult != 0. ){
  	threshMult = x->threshMult;
  }
  else { 
	threshMult = 1.0;
  }
  
  if(x->mute){
	while(n--)
		*out++ = 0.0;
	return w+7;
  }

/* fill our retaining buffers */

  inCount += D;

  for ( j = 0 ; j < Nw - D ; j++ ) {
    inputOne[j] = inputOne[j+D];
    inputTwo[j] = inputTwo[j+D];
  }

  for ( j = Nw - D; j < Nw; j++ ) {
    inputOne[j] = *inOne++;
    inputTwo[j] = *inTwo++;
  }

/* apply hamming window and fold our window buffer into the fft buffer */ 

  fold( inputOne, Wanal, Nw, bufferOne, N, inCount );
  fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount );


/* do an fft */ 

  rdft( N, 1, bufferOne, bitshuffle, trigland );
  rdft( N, 1, bufferTwo, bitshuffle, trigland );

/* use slow fft */


/* use redundant coding for speed, even though moving the invert variable
   comparison outside of the for loop will give us only a minimal performance
   increase (hypot and atan2 are the most intensive portions of this code).
   consider adding a table lookup for atan2 instead.
*/

  if (invert) {	
 
/* convert to polar coordinates from complex values */
 
    for ( i = 0; i <= N2; i++ ) {
      odd = ( even = i<<1 ) + 1;

      a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) );
      b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) );
    
      a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) );
      b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) );

      *(channelOne+even) = hypot( a1, b1 );
      *(channelOne+odd) = -atan2( b1, a1 );
    
      *(channelTwo+even) = hypot( a2, b2 );
      *(channelTwo+odd) = -atan2( b2, a2 );

/* use simple threshold for inverse compositing */
    
      if ( *(channelOne+even) > *(channelTwo+even) * threshMult )
      	*(channelOne+even) = *(channelTwo+even);
    	
      if ( *(channelOne+odd) == 0. )
    	*(channelOne+odd) = *(channelTwo+odd);	 
    }
  }

  else {

/* convert to polar coordinates from complex values */
 
    for ( i = 0; i <= N2; i++ ) {
    
      odd = ( even = i<<1 ) + 1;

      a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) );
      b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) );
    
      a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) );
      b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) );

      *(channelOne+even) = hypot( a1, b1 );
      *(channelOne+odd) = -atan2( b1, a1 );
    
      *(channelTwo+even) = hypot( a2, b2 );
      *(channelTwo+odd) = -atan2( b2, a2 );

/* use simple threshold for compositing */
    
      if ( *(channelOne+even) < *(channelTwo+even) * threshMult )
      	*(channelOne+even) = *(channelTwo+even);
    	
      if ( *(channelOne+odd) == 0. )
    	*(channelOne+odd) = *(channelTwo+odd);	 
    }  
  }

/* convert back to complex form, read for the inverse fft */

  for ( i = 0; i <= N2; i++ ) {

    odd = ( even = i<<1 ) + 1;

    *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) );

    if ( i != N2 )
      *(bufferOne+odd) = -(*(channelOne+even)) * sin( *(channelOne+odd) );
  }


/* do an inverse fft */

  rdft( N, -1, bufferOne, bitshuffle, trigland );


/* dewindow our result */

  overlapadd( bufferOne, N, Wsyn, output, Nw, inCount);

/* set our output and adjust our retaining output buffer */

  for ( j = 0; j < D; j++ )
    *out++ = output[j] * mult;
	
  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
  
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;
		

/* restore state variables */

  x->inCount = inCount % Nw;
  return (w+7);
}		

void ether_mute(t_ether *x, t_floatarg toggle)
{
  x->mute = (short)toggle;
}

void ether_invert(t_ether *x, t_floatarg toggle)
{
  x->invert = (int)toggle;
}

void ether_dsp(t_ether *x, t_signal **sp, short *count)
{
	long i;
#if MSP
  for( i = 0; i < 3; i++ ){
    x->connected[i] = count[i];
  }
#endif
  /* signal is always connected in Pd */
#if PD 
  for( i = 0; i < 3; i++ ){
    x->connected[i] = 1;
  }
#endif
  /* reinitialize if vector size or sampling rate has been changed */
  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;
    ether_init(x,1);
  }	
	dsp_add(ether_perform, 6, x,
		sp[0]->s_vec,
		sp[1]->s_vec,
		sp[2]->s_vec,
		sp[3]->s_vec,
		sp[0]->s_n);
}


--- NEW FILE: swinger~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *swinger_class;
#endif 

#if PD
static t_class *swinger_class;
#endif

#define OBJECT_NAME "swinger~"

typedef struct _swinger
{
#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;
    int *bitshuffle;
    
    float *Wanal;	
    float *Wsyn;	
    float *inputOne;
    float *inputTwo;
    float *Hwin;
    float *bufferOne;
    float *bufferTwo;
    float *channelOne;
 	float *channelTwo;
    float *output;
    float mult; 
    float *trigland;
	int overlap;//overlap factor
		int winfac;// window factor
			int vs;//last measurement of vector size
				short mute;
				
} t_swinger;


/* msp function prototypes */

void *swinger_new(t_symbol *s, int argc, t_atom *argv);
t_int *swinger_perform(t_int *w);
void swinger_dsp(t_swinger *x, t_signal **sp, short *count);
void swinger_assist(t_swinger *x, void *b, long m, long a, char *s);
void swinger_mute(t_swinger *x, t_floatarg state);
void swinger_init(t_swinger *x, short initialized);
void swinger_dsp_free(t_swinger *x);
void swinger_overlap(t_swinger *x, t_floatarg o);
void swinger_winfac(t_swinger *x, t_floatarg o);
//int power_of_two(int p);
void swinger_fftinfo(t_swinger *x);

#if MSP

void main(void)
{
    setup((t_messlist **)&swinger_class, (method) swinger_new, (method)dsp_free, (short)sizeof(t_swinger),
		  0L, A_GIMME, 0);
	
    addmess((method)swinger_dsp, "dsp", A_CANT, 0);
    addmess((method)swinger_assist,"assist",A_CANT,0);
    addmess((method)swinger_mute,"mute",A_FLOAT,0);
	addmess((method)swinger_overlap,"overlap",A_FLOAT,0);
	addmess((method)swinger_winfac,"winfac",A_FLOAT,0);
	addmess((method)swinger_fftinfo,"fftinfo",0);
    dsp_initclass();
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif
#if PD
/* Pd Initialization */
void swinger_tilde_setup(void)
{
	swinger_class = class_new(gensym("swinger~"), (t_newmethod)swinger_new, 
							  (t_method)swinger_dsp_free ,sizeof(t_swinger), 0,A_GIMME,0);
	CLASS_MAINSIGNALIN(swinger_class, t_swinger, x_f);
	class_addmethod(swinger_class, (t_method)swinger_dsp, gensym("dsp"), 0);
	class_addmethod(swinger_class, (t_method)swinger_mute, gensym("mute"), A_DEFFLOAT,0);
	class_addmethod(swinger_class, (t_method)swinger_overlap, gensym("overlap"), A_DEFFLOAT,0);
	class_addmethod(swinger_class, (t_method)swinger_winfac, gensym("winfac"), A_DEFFLOAT,0);
	class_addmethod(swinger_class, (t_method)swinger_fftinfo, gensym("fftinfo"),0);
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

/* diagnostic messages for Max */
void swinger_fftinfo(t_swinger *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 swinger_mute(t_swinger *x, t_floatarg state)
{
	x->mute = state;	
}

void swinger_assist (t_swinger *x, void *b, long msg, long arg, char *dst)
{
	
	if (msg == 1) {
		
		switch (arg) {
			
			case 0:		sprintf(dst,"(signal) Signal to be Phase Replaced ");
				break;
				
			case 1:		sprintf(dst,"(signal) Signal to Supply Phase Information ");
				break;
		}
	}
	
	else {
		
		if (msg == 2)
			sprintf(dst,"(signal) Swinger Output");
		
	}
}


void *swinger_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
	t_swinger 	*x = (t_swinger *) newobject(swinger_class);
	dsp_setup((t_pxobject *)x,2);
	outlet_new((t_pxobject *)x, "signal");
	/* make sure that signal inlets and outlets have their own memory */
	x->x_obj.z_misc |= Z_NO_INPLACE;
#endif
#if PD
	t_swinger *x = (t_swinger *)pd_new(swinger_class);
	inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
	outlet_new(&x->x_obj, gensym("signal"));
#endif
	
	/* INITIALIZATIONS */
	x->overlap = atom_getfloatarg(0,argc,argv);
	x->winfac = atom_getfloatarg(1,argc,argv);
	if(!x->winfac)	
		x->winfac = 1;
	if(!x->overlap)
		x->overlap = 4;
	x->vs = sys_getblksize();
	x->R = sys_getsr();
	swinger_init(x,0); 
	return (x);
}

void swinger_overlap(t_swinger *x, t_floatarg o)
{
	if(!power_of_two(o)){
		post("%f is not a power of two",o);
		return;
	}
	x->overlap = o;
	swinger_init(x,1);
}

void swinger_winfac(t_swinger *x, t_floatarg f)
{
	if(!power_of_two(f)){
	    error("%f is not a power of two",f);
	    return;
	}
	x->winfac = (int)f;
	swinger_init(x,1);
}

void swinger_init(t_swinger *x, short initialized)
{
	int i;
	x->D = x->vs;
	x->N = x->vs * x->overlap;
	x->Nw = x->N * x->winfac;
	limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
	x->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->inCount = -(x->Nw);
	x->mult = 1. / (float) x->N;
	
	if(!initialized){
		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->inputOne = (float *) getbytes( MAX_Nw * sizeof(float) );
		x->inputTwo = (float *) getbytes( MAX_Nw * sizeof(float) );	
		x->bufferOne = (float *) getbytes( MAX_N * sizeof(float) );
		x->bufferTwo = (float *) getbytes( MAX_N * sizeof(float) ); 
		x->channelOne = (float *) getbytes( (MAX_N+2) * sizeof(float) );
		x->channelTwo = (float *) getbytes( (MAX_N+2) * sizeof(float) );
		x->output = (float *) getbytes( MAX_Nw * sizeof(float) );
		x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) );
		x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) );
	}
	memset((char *)x->inputOne,0,x->Nw * sizeof(float));
	memset((char *)x->inputTwo,0,x->Nw * sizeof(float));
	memset((char *)x->output,0,x->Nw * sizeof(float));
	
	init_rdft(x->N, x->bitshuffle, x->trigland);
	makehanning(x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 1);// wants an ODD window
		
}

t_int *swinger_perform(t_int *w)
{
	
	int		n,
	i,j,
	inCount,
	R,
	N,
	N2,
	D,
	Nw,
	invert = 1,
	even, odd,
	*bitshuffle;
	
	float		maxamp,	
		threshMult = 1.,
		mult,
		a1, b1,
		a2, b2,
		*inputOne,
		*inputTwo,
		*bufferOne,
		*bufferTwo,
		*output,
		*Wanal,
		*Wsyn,
		*channelOne,
		*channelTwo,
		*trigland;
	t_float 	*inOne,
		*inTwo,	
		*out;
	
	/* get our inlets and outlets */
	
	t_swinger *x = (t_swinger *) (w[1]);
	inOne = (t_float *)(w[2]);
	inTwo = (t_float *)(w[3]);
	
	out = (t_float *)(w[4]);
	n = (int)(w[5]);
	
	/* dereference structure  */	
	
	inputOne = x->inputOne;
	inputTwo = x->inputTwo;
	bufferOne = x->bufferOne;
	bufferTwo = x->bufferTwo;
	inCount = x->inCount;
	R = x->R;
	N = x->N;
	N2 = x->N2;
	D = x->D;
	Nw = x->Nw;
	Wanal = x->Wanal;
	Wsyn = x->Wsyn;
	output = x->output;
	channelOne = x->channelOne;
	channelTwo = x->channelTwo;
	bitshuffle = x->bitshuffle;
	trigland = x->trigland;
	mult = x->mult;	
	
	/* no computation if muted */
	
	if(x->mute){
		while(n--) 
			*out++ = 0.0;
		return w+6;
	}
	
	inCount += D;
	
	for ( j = 0 ; j < Nw - D ; j++ ) {
		inputOne[j] = inputOne[j+D];
		inputTwo[j] = inputTwo[j+D];
	}
	
	for ( j = Nw-D; j < Nw; j++ ) {
		inputOne[j] = *inOne++;
		inputTwo[j] = *inTwo++;
	}
	
	/* apply hamming window and fold our window buffer into the fft buffer */ 
	
	fold( inputOne, Wanal, Nw, bufferOne, N, inCount );
	fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount );
	
	/* do an fft */ 
	
	rdft( N, 1, bufferOne, bitshuffle, trigland );
	rdft( N, 1, bufferTwo, bitshuffle, trigland );
	
	/* use redundant coding for speed, even though moving the invert variable
		comparison outside of the for loop will give us only a minimal performance
		increase (hypot and atan2 are the most intensive portions of this code).
		consider adding a table lookup for atan2 instead.
		*/
	
	/* convert to polar coordinates from complex values */
	
	for ( i = 0; i <= N2; i++ ) {
		odd = ( even = i<<1 ) + 1;
		
		a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) );
		b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) );
		
		a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) );
		b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) );
		
		/* replace signal one's phases with those of signal two */
		
		*(channelOne+even) = hypot( a1, b1 );
		*(channelOne+odd) = -atan2( b2, a2 );        
	}
	
	for ( i = 0; i <= N2; i++ ) {
		
		odd = ( even = i<<1 ) + 1;
		
		*(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) );
		
		if ( i != N2 )
			*(bufferOne+odd) = -(*(channelOne+even)) * sin( *(channelOne+odd) );
	}
	
	
	/* do an inverse fft */
	
	rdft( N, -1, bufferOne, bitshuffle, trigland );
	
	
	
	/* dewindow our result */
	
	overlapadd( bufferOne, N, Wsyn, output, Nw, inCount);
	
	/* set our output and adjust our retaining output buffer */
	
	for ( j = 0; j < D; j++ )
		*out++ = output[j] * mult;
	
	for ( j = 0; j < Nw - D; j++ )
		output[j] = output[j+D];
	
	for ( j = Nw - D; j < Nw; j++ )
		output[j] = 0.;
	
	
	/* restore state variables */
	
	x->inCount = inCount % Nw;
	return (w+6);
}	

void swinger_dsp_free( t_swinger *x )
{
#if MSP
	dsp_free((t_pxobject *) x);
#endif
	freebytes(x->trigland,0);
	freebytes(x->bitshuffle,0);
	freebytes(x->Wanal,0);
	freebytes(x->Wsyn,0);
	freebytes(x->Hwin,0);
	freebytes(x->inputOne,0);
	freebytes(x->inputTwo,0);
	freebytes(x->bufferOne,0);
	freebytes(x->bufferTwo,0);
	freebytes(x->channelOne,0);
	freebytes(x->channelTwo,0);
	freebytes(x->output,0);
}

void swinger_dsp(t_swinger *x, t_signal **sp, short *count)
{
	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;
		swinger_init(x,1);
	}
	dsp_add(swinger_perform, 5, x,
			sp[0]->s_vec,sp[1]->s_vec,sp[2]->s_vec,sp[0]->s_n);
}


--- NEW FILE: leaker~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *leaker_class;
#endif 

#if PD
static t_class *leaker_class;
#endif

#define OBJECT_NAME "leaker~"


typedef struct _leaker
{
#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;
  float *input1;	
  float *buffer1;
  float *channel1;


  float *input2;	
  float *buffer2;
  float *channel2;

  int *sieve ;
  //
  int	inCount;
  float *Hwin;
  float *Wanal;	
  float *Wsyn;	
  float *output;
  /* leaker vars */

  float *c_lastphase_in1;
  float *c_lastphase_in2;
  float *c_lastphase_out;
  float c_fundamental;
  float c_factor_in;
  float c_factor_out;

  float mult; 
  float *trigland;
  int *bitshuffle;
  short mute;
  short bypass;
  short fade_connected;
  float fade_value;
  int overlap;
  int winfac;
} t_leaker;

static void leaker_free(t_leaker *x);
void *leaker_new(t_symbol *msg, short argc, t_atom *argv);
//t_int *offset_perform(t_int *w);
t_int *leaker_perform(t_int *w);
void leaker_dsp(t_leaker *x, t_signal **sp, short *count);
void leaker_assist(t_leaker *x, void *b, long m, long a, char *s);
void leaker_upsieve(t_leaker *x) ;
void leaker_downsieve(t_leaker *x) ;
void leaker_randsieve(t_leaker *x) ;
void leaker_bypass(t_leaker *x, t_floatarg state);
void leaker_mute(t_leaker *x, t_floatarg state);
void leaker_float(t_leaker *x, double f);
void leaker_init(t_leaker *x, short initialized);
void leaker_overlap(t_leaker *x, t_floatarg f);
void leaker_winfac(t_leaker *x, t_floatarg f);
void leaker_fftinfo(t_leaker *x);

#if MSP
void main(void)
{
  setup((t_messlist **)&leaker_class, (method)leaker_new, (method)leaker_free, 
	(short)sizeof(t_leaker), 0, A_GIMME, 0);
  addmess((method)leaker_dsp, "dsp", A_CANT, 0);
  addmess((method)leaker_assist,"assist",A_CANT,0);
  addmess((method)leaker_upsieve, "upsieve", 0);
  addmess((method)leaker_downsieve, "downsieve", 0);
  addmess((method)leaker_randsieve, "randsieve", 0);
  addmess((method)leaker_bypass,"bypass",A_DEFFLOAT,0);
  addmess((method)leaker_mute,"mute",A_DEFFLOAT,0);
  addmess((method)leaker_overlap,"overlap",A_DEFFLOAT,0);
  addmess((method)leaker_winfac,"winfac",A_DEFFLOAT,0);
  addmess((method)leaker_fftinfo,"fftinfo",0);
  addfloat((method)leaker_float);
  dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
void leaker_tilde_setup(void)
{
  leaker_class = class_new(gensym("leaker~"), (t_newmethod)leaker_new, 
    (t_method)leaker_free ,sizeof(t_leaker), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(leaker_class, t_leaker, x_f);
  class_addmethod(leaker_class, (t_method)leaker_dsp, gensym("dsp"), 0);
  class_addmethod(leaker_class, (t_method)leaker_mute, gensym("mute"), A_DEFFLOAT,0);
  class_addmethod(leaker_class, (t_method)leaker_bypass, gensym("bypass"), A_DEFFLOAT,0);
  class_addmethod(leaker_class, (t_method)leaker_mute, gensym("mute"), A_DEFFLOAT,0);
  class_addmethod(leaker_class, (t_method)leaker_overlap, gensym("overlap"), A_DEFFLOAT,0);
  class_addmethod(leaker_class, (t_method)leaker_winfac, gensym("winfac"), A_DEFFLOAT,0);
  class_addmethod(leaker_class, (t_method)leaker_fftinfo, gensym("fftinfo"),0);
  class_addmethod(leaker_class, (t_method)leaker_upsieve, gensym("upsieve"), 0);
  class_addmethod(leaker_class, (t_method)leaker_downsieve, gensym("downsieve"),0);
  class_addmethod(leaker_class, (t_method)leaker_randsieve, gensym("randsieve"),0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void leaker_overlap(t_leaker *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;
	leaker_init(x,1);
}

void leaker_winfac(t_leaker *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;
	leaker_init(x,2);
}

void leaker_fftinfo(t_leaker *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 leaker_free( t_leaker *x ){
#if MSP
  dsp_free((t_pxobject *)x);
#endif
  freebytes(x->c_lastphase_in1,0); 
  freebytes(x->c_lastphase_in2,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->input1,0);
  freebytes(x->input2,0);
  freebytes(x->Hwin,0);
  freebytes(x->buffer1,0);
  freebytes(x->buffer2,0);
  freebytes(x->channel1,0);
  freebytes(x->channel2,0);
  freebytes(x->output,0);
  freebytes(x->sieve,0);
}

void leaker_upsieve(t_leaker *x) {
  int i;
  for( i = 0; i < x->N2; i++ ){
    x->sieve[i] = i + 1;
  }
}

void leaker_downsieve(t_leaker *x) {
  int i;
  for( i = 0; i < x->N2; i++ ){
    x->sieve[i] = x->N2  - i;
  }
}

void leaker_randsieve(t_leaker *x) {
  int i,j;
  int NSwitch = 100000 ;
  int temp ;
  int pos1, pos2;

  // use better algorithm

  for( i = 0; i < x->N2; i++ ){
    x->sieve[i] = i + 1;
  }
  for( i = 0; i < NSwitch; i++ ){
    pos1 = rand() % x->N2;
    pos2 = rand() % x->N2;
    temp = x->sieve[pos2];
    x->sieve[pos2] = x->sieve[pos1];
    x->sieve[pos1] = temp ;
  }
}

void leaker_bypass(t_leaker *x, t_floatarg state)
{
  x->bypass = (short)state;	
}
void leaker_mute(t_leaker *x, t_floatarg state)
{
  x->mute = (short)state;	
}


void leaker_assist (t_leaker *x, void *b, long msg, long arg, char *dst)
{
  if (msg==1) {
    switch (arg) {
    case 0: sprintf(dst,"(signal) Input 1");break;
    case 1: sprintf(dst,"(signal) Input 2");break;
    case 2: sprintf(dst,"(signal/float) Crossfade Position (0.0 - 1.0)");break;
    }
  } else if (msg==2) {
    sprintf(dst,"(signal) Output ");
  }
}

void *leaker_new(t_symbol *msg, short argc, t_atom *argv)
{
#if MSP
  t_leaker *x = (t_leaker *)newobject(leaker_class);
  dsp_setup((t_pxobject *)x,3);
  outlet_new((t_pxobject *)x, "signal");
#endif

#if PD
  t_leaker *x = (t_leaker *)pd_new(leaker_class);
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
#endif

  x->D = sys_getblksize();
  x->R = sys_getsr();
  if(!x->D)
    x->D = 256;
  if(!x->R)
    x->R = 44100;

  x->overlap = atom_getfloatarg(0,argc,argv);
  x->winfac = atom_getfloatarg(1,argc,argv);
  if(!x->overlap)
    x->overlap = 4;
  if(!x->winfac)
    x->winfac = 1;

  leaker_init(x,0);	
  return (x);
}

void leaker_init(t_leaker *x, short initialized)
{
	int i;
	if(!power_of_two(x->overlap))
		x->overlap = 4;
	if(!power_of_two(x->winfac))
		x->winfac = 2;
	x->N = x->D * x->overlap;
	x->Nw = x->N * x->winfac;
	limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
	x->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->inCount = -(x->Nw);
	x->mult = 1. / (float) x->N;
	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;
	
	if(!initialized) {
		x->mute = 0;
		x->bypass = 0;
		x->fade_connected = 0;
		x->fade_value = 0;
		
		x->input1 = (float *) getbytes(MAX_Nw * sizeof(float));	
		x->buffer1 = (float *) getbytes(MAX_N * sizeof(float));
		x->channel1 = (float *) getbytes((MAX_N+2) * sizeof(float));
		x->input2 = (float *) getbytes(MAX_Nw * sizeof(float));	
		x->buffer2 = (float *) getbytes(MAX_N * sizeof(float));
		x->channel2 = (float *) getbytes((MAX_N+2) * sizeof(float));
		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->output = (float *) getbytes(MAX_Nw * sizeof(float));
		x->bitshuffle = (int *) getbytes (MAX_N * 2 * sizeof( int ));
		x->trigland = (float *) getbytes(MAX_N * 2 * sizeof( float ));	  
		x->sieve = (int *) getbytes((MAX_N2 + 1) * sizeof(int));
		x->c_lastphase_in1 = (float *) getbytes((MAX_N2+1) * sizeof(float));
		x->c_lastphase_in2 = (float *) getbytes((MAX_N2+1) * sizeof(float));
		x->c_lastphase_out = (float *) getbytes((MAX_N2+1) * sizeof(float));
		
	}  

		memset((char *)x->input1,0,x->Nw);
		memset((char *)x->input2,0,x->Nw);
		memset((char *)x->output,0,x->Nw);
		memset((char *)x->c_lastphase_in1,0,(x->N2+1) * sizeof(float));
		memset((char *)x->c_lastphase_in2,0,(x->N2+1) * sizeof(float));
		memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float));

	init_rdft(x->N, x->bitshuffle, x->trigland);
	makehanning(x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
	if(initialized != 2){
		for(i = 0; i < x->N2; i++){
			x->sieve[i] = i;
		}
	}
}

t_int *leaker_perform(t_int *w)
{
  int i,j,odd,even;
  float a1,a2,b1,b2;

  t_leaker *x = (t_leaker *) (w[1]);
  t_float *in1 = (t_float *)(w[2]);
  t_float *in2 = (t_float *)(w[3]);
  t_float *in3 = (t_float *)(w[4]);
  t_float *out = (t_float *)(w[5]);
  t_int n = w[6];

  float fade_value = x->fade_value;	
  float *input1 = x->input1;
  float *input2 = x->input2;
  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 *output = x->output;
  float *buffer1 = x->buffer1;
  float *buffer2 = x->buffer2;
  float *channel1 = x->channel1;
  float *channel2 = x->channel2;
  int *sieve = x->sieve;
  int *bitshuffle = x->bitshuffle;
  float *trigland = x->trigland;
  float mult = x->mult;	

  /* dereference struncture  */	
  if( x->mute) {
    while(n--){
      *out++ = 0.;
    }
    return (w+7);
  }	
  if( x->bypass ) {
    while(n--){
      *out++ = *in1++;
    }
    return (w+7);
  } 

#if MSP
  if(x->fade_connected)
    fade_value = *in3++ * (float) N2;
#endif

#if PD
    fade_value = *in3++ * (float) N2;
#endif

  inCount += D;

  for ( j = 0 ; j < Nw - D ; j++ ){
    input1[j] = input1[j+D];
    input2[j] = input2[j+D];
  }
  for ( j = Nw - D; j < Nw; j++ ) {
    input1[j] = *in1++;
    input2[j] = *in2++;
  }

  fold(input1, Wanal, Nw, buffer1, N, inCount);		
  fold(input2, Wanal, Nw, buffer2, N, inCount);	
  rdft(N, 1, buffer1, bitshuffle, trigland);
  rdft(N, 1, buffer2, bitshuffle, trigland);


  for ( i = 0; i <= N2; i++ ) {
    odd = ( even = i<<1 ) + 1;
    if( fade_value <= 0 || fade_value < sieve[i]  ){
      a1 = ( i == N2 ? *(buffer1+1) : *(buffer1+even) );
      b1 = ( i == 0 || i == N2 ? 0. : *(buffer1+odd) );

      *(channel1+even) = hypot( a1, b1 ) ;
      *(channel1+odd) = -atan2( b1, a1 );
      *(buffer1+even) = *(channel1+even) * cos(*(channel1+odd));
      if ( i != N2 ){
	*(buffer1+odd) = -(*(channel1+even)) * sin(*(channel1+odd));
      }
    } else {
      a2 = ( i == N2 ? *(buffer2+1) : *(buffer2+even) );
      b2 = ( i == 0 || i == N2 ? 0. : *(buffer2+odd) );
      *(channel1+even) = hypot( a2, b2 ) ;
      *(channel1+odd) = -atan2( b2, a2 );
      *(buffer1+even) = *(channel1+even) * cos(*(channel1+odd) );
      if ( i != N2 ){
	*(buffer1+odd) = -(*(channel1+even)) * sin( *(channel1+odd) );
      }
    }
  }

  rdft( N, -1, buffer1, bitshuffle, trigland );
  overlapadd( buffer1, N, Wsyn, output, Nw, inCount);

  for ( j = 0; j < D; j++ )
    *out++ = output[j] * mult;

  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];

  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;

  x->inCount = inCount % Nw;
  
  return (w+7);
}		

void leaker_dsp(t_leaker *x, t_signal **sp, short *count)
{
  long i;
#if MSP
  x->fade_connected = count[2];
#endif
  if(x->R != sp[0]->s_sr || x->D != sp[0]->s_n){
    x->R = sp[0]->s_sr;
    x->D = sp[0]->s_n;
    leaker_init(x,1);
  }
  
  dsp_add(leaker_perform, 6, x, 
	  sp[0]->s_vec,sp[1]->s_vec,sp[2]->s_vec,sp[3]->s_vec,sp[0]->s_n);
}
#if MSP
void leaker_float(t_leaker *x, double f)
{
  int inlet = x->x_obj.z_in;
  if( inlet == 2 && f >= 0 && f <= 1){
    x->fade_value = f * (float) x->N2;
  }
}
#endif


--- NEW FILE: scrape~.c ---
#include "MSPd.h"
#include "fftease.h"


#if MSP
void *scrape_class;
#endif 

#if PD
static t_class *scrape_class;
#endif

#define OBJECT_NAME "scrape~"

typedef struct _scrape
{
#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 knee;
	float cutoff;
	float scrape_mult;
	float thresh1;
	float thresh2;
	float *threshfunc;
	short connected[8];
	short mute;
	short bypass;
	//
	float mult; 
	float *trigland;
	int *bitshuffle;
	int overlap;//overlap factor
		int winfac;//window factor
			int vs;//vector size
} t_scrape;

void *scrape_new(t_symbol *msg, short argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *scrape_perform(t_int *w);
void scrape_dsp(t_scrape *x, t_signal **sp, short *count);
void scrape_assist(t_scrape *x, void *b, long m, long a, char *s);
void scrape_float(t_scrape *x, double f) ;
void update_thresh_function( t_scrape *x );
void scrape_frowned( float *S, float *C, float *threshfunc, float fmult, int N2 );
void scrape_mute(t_scrape *x, t_floatarg toggle);
void scrape_bypass(t_scrape *x, t_floatarg toggle);
void scrape_dsp_free( t_scrape *x );
void update_thresh_function( t_scrape *x );
void scrape_init(t_scrape *x, short initialized);
void scrape_fftinfo(t_scrape *x);
void scrape_overlap(t_scrape *x, t_floatarg f);
void scrape_winfac(t_scrape *x, t_floatarg f);

#if MSP
void main(void)
{
	setup((t_messlist **) &scrape_class, (method)scrape_new, (method)scrape_dsp_free, 
		  (short)sizeof(t_scrape), 0, A_GIMME, 0);
	addmess((method)scrape_dsp, "dsp", A_CANT, 0);
	addmess((method)scrape_assist,"assist",A_CANT,0);
	addmess ((method)scrape_mute, "mute", A_FLOAT, 0);
	addmess ((method)scrape_bypass, "bypass", A_FLOAT, 0);
	addmess((method)scrape_overlap,"overlap",A_DEFFLOAT,0);
	addmess((method)scrape_winfac,"winfac",A_DEFFLOAT,0);
	addmess((method)scrape_fftinfo,"fftinfo",0);  addfloat((method) scrape_float);
	dsp_initclass();
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
void scrape_tilde_setup(void)
{
	scrape_class = class_new(gensym("scrape~"), (t_newmethod)scrape_new, 
							 (t_method)scrape_dsp_free ,sizeof(t_scrape), 0,A_GIMME,0);
	CLASS_MAINSIGNALIN(scrape_class, t_scrape, x_f);
	class_addmethod(scrape_class, (t_method)scrape_dsp, gensym("dsp"), 0);
	class_addmethod(scrape_class, (t_method)scrape_assist, gensym("assist"), 0);
	class_addmethod(scrape_class, (t_method)scrape_mute, gensym("mute"), A_DEFFLOAT,0);
	class_addmethod(scrape_class, (t_method)scrape_bypass, gensym("bypass"), A_DEFFLOAT,0);
	class_addmethod(scrape_class, (t_method)scrape_overlap, gensym("overlap"), A_DEFFLOAT,0);
	class_addmethod(scrape_class,(t_method)scrape_winfac,gensym("winfac"),A_FLOAT,0);
	class_addmethod(scrape_class,(t_method)scrape_fftinfo,gensym("fftinfo"),0);
	
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif


void scrape_dsp_free( t_scrape *x )
{
#if MSP
	dsp_free( (t_pxobject *) x);
#endif
	
	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->output,0);
	freebytes(x->threshfunc,0);
}

void scrape_assist (t_scrape *x, void *b, long msg, long arg, char *dst)
{
	if (msg==1) {
		switch (arg) {
			case 0: sprintf(dst,"(signal) Input ");break;
			case 1: sprintf(dst,"(float/signal) Knee Frequency"); break;
			case 2: sprintf(dst,"(float/signal) Cutoff Frequency"); break;
			case 3: sprintf(dst,"(float/signal) Knee Threshold"); break;
			case 4: sprintf(dst,"(float/signal) Cutoff Threshold"); break;
			case 5: sprintf(dst,"(float/signal) Multiplier For Weak Bins"); break;
		}
	} else if (msg==2) {
		sprintf(dst,"(signal) Output");
	}
}

void *scrape_new(t_symbol *msg, short argc, t_atom *argv)
{
#if MSP
	t_scrape *x = (t_scrape *)newobject(scrape_class);
	dsp_setup((t_pxobject *)x,6);
	outlet_new((t_pxobject *)x, "signal");
#endif
#if PD
	int i;
	t_scrape *x = (t_scrape *)pd_new(scrape_class);
	for(i=0;i<5;i++)
		inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
	outlet_new(&x->x_obj, gensym("signal"));
#endif
	x->knee = atom_getfloatarg(0, argc, argv);
	x->cutoff = atom_getfloatarg(1, argc, argv);
	x->thresh1 = atom_getfloatarg(2, argc, argv);
	x->thresh2 = atom_getfloatarg(3, argc, argv);
	x->scrape_mult = atom_getfloatarg(4, argc, argv);  
	x->overlap = atom_getfloatarg(5, argc, argv); 
	x->winfac = atom_getfloatarg(6, argc, argv);  
	if(x->knee <= 0)
		x->knee = 1000.0;
	if(x->cutoff <= 0)
		x->cutoff = 4000.0;
	if(x->thresh1 <= 0)
		x->thresh1 = .0001 ;
	if(x->thresh2 <= 0)
		x->thresh2 = .09 ;
	if( x->scrape_mult < 0 || x->scrape_mult > 10 ){
		x->scrape_mult = 0.1;
	}
	if(!power_of_two(x->overlap))
		x->overlap = 4;
	if(!power_of_two(x->winfac))
		x->winfac = 1;
	
	x->vs = sys_getblksize();
	x->R = sys_getsr();
	scrape_init(x,0);
	return (x);
}

void scrape_init(t_scrape *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->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->inCount = -(x->Nw);
	x->mult = 1. / (float) x->N;
	
	if(!initialized){
		x->mute = 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->threshfunc = (float *) getbytes(MAX_N2 * sizeof(float));
	}
	memset((char *)x->input,0,x->Nw * sizeof(float));
	memset((char *)x->output,0,x->Nw * sizeof(float));  
	makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
	init_rdft( x->N, x->bitshuffle, x->trigland);
	if(initialized != 2)
		update_thresh_function(x);
}

void scrape_overlap(t_scrape *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;
	scrape_init(x,1);
}

void scrape_winfac(t_scrape *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;
	scrape_init(x,2);
}

void scrape_fftinfo(t_scrape *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);
}

#if MSP
void scrape_float(t_scrape *x, double f) // Look at floats at inlets
{
	int inlet = x->x_obj.z_in;
	
	if (inlet == 1)
    {
		if( f> 50  && f < 18000) {
			x->knee = f ;
			update_thresh_function( x );	
		}	
		
    }
	else if (inlet == 2)
    {
		if( (f > x->knee)  && (f < 20000) ) {
			x->cutoff = f ;
			update_thresh_function( x );	
		}
    }
	else if (inlet == 3)
    {
		x->thresh1 = f;
		update_thresh_function( x );
    }
	else if (inlet == 4)
    {
		x->thresh2 = f;
		update_thresh_function( x );
    }
	else if (inlet == 5)
    {
		if( f > 0 ) {
			x->scrape_mult = f;
		}
    }
} 
#endif
void update_thresh_function( t_scrape *x ) 
{
	float funda, curfreq, m1, m2;
	int i;
	
	funda = (float)  x->R / ((float)x->N * 2.0 );
	curfreq = funda ;
	for( i = 0; i < x->N2; i++ ) {
		if( curfreq  < x->knee ){
			x->threshfunc[i] = 0.0 ;
		} else if( curfreq >= x->knee && curfreq < x->cutoff ) {
			m2 = (x->knee - curfreq) / (x->cutoff - x->knee) ;
			m1 = 1.0 - m2 ;
			x->threshfunc[i] = m1 * x->thresh1 + m2 * x->thresh2 ;
		} else {
			x->threshfunc[i] = x->thresh2;
		}
		curfreq += funda ;
	}
}

void scrape_mute(t_scrape *x, t_floatarg toggle)
{
	x->mute = (short)toggle;	
}

void scrape_bypass(t_scrape *x, t_floatarg toggle)
{
	x->bypass = (short)toggle;	
}


t_int *scrape_perform(t_int *w)
{
	float sample, outsamp ;
	
	
	
	int	i,j;
	float tmp ;	
	
	short update = 0;
	
	t_scrape *x = (t_scrape *) (w[1]);
	t_float *in = (t_float *)(w[2]);
	t_float *knee_freq = (t_float *)(w[3]);
	t_float *cut_freq = (t_float *)(w[4]);
	t_float *thresh1 = (t_float *)(w[5]);
	t_float *thresh2 = (t_float *)(w[6]);
	t_float *scrape_mult = (t_float *)(w[7]);
	t_float *out = (t_float *)(w[8]);
	t_int n = w[9];
	
	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 mult = x->mult ;
	int *bitshuffle = x->bitshuffle;
	float *trigland = x->trigland ;      
	float *threshfunc = x->threshfunc ;
	short *connected = x->connected;
	
	if( x->mute ){
		while( n-- ){
			*out++ = 0.0;
		}
		return (w+10); // always what dsp_add says + 1
	}
	if( x->bypass ){
		while( n-- ){
			*out++ = *in++ * 0.5; // gain compensation
		}
		return (w+10); // always what dsp_add says + 1
	}
	if( connected[1] ){
		tmp = *knee_freq++;
		if( tmp > 50 && tmp < 20000 ){
			x->knee = tmp;
			update = 1;
		}
	}
	if( connected[2] ){
		tmp = *cut_freq++;
		if( tmp > x->knee && tmp < 20000 ){
			x->cutoff = *cut_freq++;
			update = 1;
		}
	}
	if( connected[3] ){
		x->thresh1 = *thresh1++ ;
		update = 1;
	}
	if( connected[4] ){
		x->thresh2 = *thresh2++ ;
		update = 1;
	}
	if( connected[5] ){
		x->scrape_mult = *scrape_mult++ ;
	}
	
	if( update ){
		update_thresh_function( x );	
	}
	
	x->inCount += D;
	
	for ( j = 0 ; j < Nw - D ; j++ ){
		input[j] = input[j+D];
	}
	for ( j = Nw - D; j < Nw; j++ ) {
		input[j] = *in++;
	}
	
	fold( input, Wanal, Nw, buffer, N, inCount );	
	rdft( N, 1, buffer, bitshuffle, trigland );
	
	scrape_frowned( buffer, channel, threshfunc, x->scrape_mult, N2 );
	
	rdft( N, -1, buffer, bitshuffle, trigland );
	overlapadd( buffer, N, Wsyn, output, Nw, inCount);
	
	for ( j = 0; j < D; j++ )
		*out++ = output[j] * mult;
	
	for ( j = 0; j < Nw - D; j++ )
		output[j] = output[j+D];
	
	for ( j = Nw - D; j < Nw; j++ )
		output[j] = 0.;
	
	return (w+10); // always what dsp_add says + 1
}		



void scrape_frowned( float *S, float *C, float *threshfunc, float fmult, int N2 )

{
	int real, imag, amp, phase;
	float a, b;
	int i;
	float maxamp = 1.;
	
	for( i = 0; i <= N2; i++ ){
		amp = i<<1;
		if( maxamp < C[amp] ){
			maxamp = C[amp];
		}
	}
	
	for ( i = 0; i <= N2; i++ ) {
		imag = phase = ( real = amp = i<<1 ) + 1;
		a = ( i == N2 ? S[1] : S[real] );
		b = ( i == 0 || i == N2 ? 0. : S[imag] );
		C[amp] = hypot( a, b );
		
		if ( (C[amp]) < threshfunc[i] * maxamp ){
			C[amp] *= fmult;
		}
		C[phase] = -atan2( b, a );
	}
	
	for ( i = 0; i <= N2; i++ ) {
		imag = phase = ( real = amp = i<<1 ) + 1;
		S[real] = *(C+amp) * cos( *(C+phase) );
		if ( i != N2 )
			S[imag] = -*(C+amp) * sin( *(C+phase) );
	}
}

void scrape_dsp(t_scrape *x, t_signal **sp, short *count)
{
	long i;
#if MSP
	for( i = 0; i < 6; i++ ){
		x->connected[i] = count[i];
	}
#endif
#if PD
	for( i = 0; i < 6; i++ ){
		x->connected[i] = 1;
	}
#endif
	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;
		scrape_init(x,1);
	}
	dsp_add(scrape_perform, 9, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec,  sp[3]->s_vec, 
			sp[4]->s_vec, sp[5]->s_vec, 
			sp[6]->s_vec, sp[0]->s_n);
}


--- NEW FILE: drown~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *drown_class;
#endif 

#if PD
static t_class *drown_class;
#endif

#define OBJECT_NAME "drown~"

typedef struct _drown
{
#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 drownmult;
  // float threshgen;
  short mute;
  float threshold;
  // faster FFT
  float mult; 
  float *trigland;
  int *bitshuffle;
      
  short connected[8];
  int overlap;//overlap factor
  int winfac;//window factor
  int vs;//vector size
  
  short peakflag;// means threshold is relative to peak amp
  //
} t_drown;

void *drown_new(t_symbol *s, int argc, t_atom *argv);
void drown_mute(t_drown *x, t_floatarg toggle);
void drown_rel2peak(t_drown *x, t_floatarg toggle);
//t_int *offset_perform(t_int *w);
t_int *drown_perform(t_int *w);
void drown_dsp(t_drown *x, t_signal **sp, short *count);
void drown_assist(t_drown *x, void *b, long m, long a, char *s);
void nudist( float *S, float *C, float threshold, float fmult, int N2 );
void drown_float(t_drown *x, double f);
void drown_overlap(t_drown *x, t_floatarg o);
void drown_free(t_drown *x);
void drown_init(t_drown *x, short initialized);
void drown_overlap(t_drown *x, t_floatarg f);
void drown_winfac(t_drown *x, t_floatarg f);
void drown_fftinfo(t_drown *x);

#if MSP
void main(void)
{
  setup((t_messlist **)&drown_class, (method)drown_new, (method)drown_free, 
	(short)sizeof(t_drown), 0, A_GIMME, 0);
  addmess((method)drown_dsp, "dsp", A_CANT, 0);
  addmess((method)drown_assist,"assist",A_CANT,0);
  addmess((method)drown_mute,"mute",A_FLOAT,0);
  addmess((method)drown_rel2peak,"rel2peak",A_FLOAT,0);
  addmess((method)drown_overlap,"overlap",A_FLOAT,0);
  addmess((method)drown_winfac,"winfac",A_FLOAT,0);
  addmess((method)drown_fftinfo,"fftinfo",0);
  addfloat((method)drown_float);
  dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if MSP
void drown_float(t_drown *x, double f) // Look at floats at inlets
{

  int inlet = x->x_obj.z_in;
//  post("drown: incoming float: %f",f);
//  post("inlet %d",inlet);
  if (inlet == 1)
    {
      x->threshold = f;
    }
  if (inlet == 2)
    {
      x->drownmult = f;
    }
}
#endif
#if PD
void drown_tilde_setup(void)
{
  drown_class = class_new(gensym("drown~"), (t_newmethod)drown_new, 
			  (t_method)drown_free ,sizeof(t_drown), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(drown_class, t_drown, x_f);
  class_addmethod(drown_class, (t_method)drown_dsp, gensym("dsp"), 0);
  class_addmethod(drown_class, (t_method)drown_assist, gensym("assist"), 0);
  class_addmethod(drown_class, (t_method)drown_mute, gensym("mute"), A_FLOAT,0);
  class_addmethod(drown_class, (t_method)drown_overlap, gensym("overlap"), A_FLOAT,0);
  class_addmethod(drown_class, (t_method)drown_rel2peak, gensym("rel2peak"), A_FLOAT,0);
  class_addmethod(drown_class, (t_method)drown_overlap, gensym("overlap"), A_FLOAT,0);
  class_addmethod(drown_class, (t_method)drown_winfac, gensym("winfac"), A_FLOAT,0);
  class_addmethod(drown_class, (t_method)drown_fftinfo, gensym("fftinfo"), 0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif



void drown_overlap(t_drown *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;
	drown_init(x,1);
}

void drown_winfac(t_drown *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;
	drown_init(x,2);
}

void drown_fftinfo(t_drown *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 drown_rel2peak(t_drown *x, t_floatarg toggle)
{
  x->peakflag = (short)toggle;
}

void drown_mute(t_drown *x, t_floatarg toggle)
{
  x->mute = (short)toggle;
}

void drown_assist (t_drown *x, void *b, long msg, long arg, char *dst)
{
  if (msg==1) {
    switch (arg) {
    case 0: sprintf(dst,"(signal) Input"); break;
    case 1: sprintf(dst,"(signal/float) Threshold Generator"); break;
    case 2: sprintf(dst,"(signal/float) Multiplier for Weak Bins"); break;
    }
  } else if (msg==2) {
    sprintf(dst,"(signal) Output");
  }
}

void *drown_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
  t_drown *x = (t_drown *)newobject(drown_class);
  dsp_setup((t_pxobject *)x,3);
  outlet_new((t_pxobject *)x, "signal");
#endif
#if PD
  t_drown *x = (t_drown *)pd_new(drown_class);
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
#endif

  x->threshold = atom_getfloatarg(0,argc,argv);
  x->drownmult = atom_getfloatarg(1,argc,argv);
  x->overlap = atom_getfloatarg(2,argc,argv);
  x->winfac = atom_getfloatarg(3,argc,argv);

  if(x->threshold <= 0)
    x->threshold = .0001;
  if(x->drownmult <= 0)
    x->drownmult = 0.1;
  if(!power_of_two(x->overlap))
    x->overlap = 4;
  if(!power_of_two(x->winfac))
    x->winfac = 1;
  	
  x->vs = sys_getblksize();
  x->R = sys_getsr();
  
  drown_init(x,0);
  return (x);
}

void drown_init(t_drown *x, short initialized)
{
	int i;
	int mem;
	
	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->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->inCount = -(x->Nw);
	x->mult = 1. / (float) x->N;
	
	if(!initialized){
		x->mute = 0;
		x->peakflag = 0;
		mem = (MAX_Nw) * sizeof(float);
		x->input = (float *) getbytes(mem);	
		x->output = (float *) getbytes(mem);
		x->Wanal = (float *) getbytes(mem);	
		x->Wsyn = (float *) getbytes(mem);	
		x->Hwin = (float *) getbytes(mem);
		mem = (MAX_N) * sizeof(float);
		x->buffer = (float *) getbytes(mem); 
		mem = (MAX_N+2) * sizeof(float);
		x->channel = (float *) getbytes(mem);
		mem = (MAX_N) * sizeof(int);
		x->bitshuffle = (int *) getbytes(mem);
		mem = (MAX_N) * sizeof(float);
		x->trigland = (float *) getbytes(mem);
	} 
		memset((char *)x->input,0,x->Nw * sizeof(float));
		memset((char *)x->output,0,x->Nw * sizeof(float));

	makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
	init_rdft( x->N, x->bitshuffle, x->trigland);
}

void drown_free(t_drown *x)
{
#if MSP
  dsp_free((t_pxobject *) x);
#endif
  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->output,0);
}

t_int *drown_perform(t_int *w)
{
  int	i,j;
  float frame_peak = 0.0;
  float local_thresh;
	
  t_drown *x = (t_drown *) (w[1]);
  t_float *in = (t_float *)(w[2]);
  t_float *in2 = (t_float *)(w[3]);
  t_float *in3 = (t_float *)(w[4]);
  t_float *out = (t_float *)(w[5]);
  t_int n = w[6];

  float *Wanal = x->Wanal;
  float *Wsyn = x->Wsyn;
  float *input = x->input;
  float *Hwin = x->Hwin;
  float *buffer = x->buffer;
  float *channel = x->channel;
  float *output = x->output;

  int D = x->D;
  int I = D;
  int R = x->R;
  int Nw = x->Nw;
  int N = x->N ;
  int N2 = x-> N2;
  int Nw2 = x->Nw2;
  int *bitshuffle = x->bitshuffle;
  float *trigland = x->trigland;
  float mult = x->mult;
  int inCount = x->inCount ;  
  int on = inCount;
  float threshold = x->threshold;
  float drownmult = x->drownmult;
  short *connected = x->connected;
  // get multiplier from sig inlet

  /* dereference struncture  */	
	
	
  if( x->mute ){
    while( n-- ){
      *out++ = 0.0;
    }
    return (w+7);
  }
	
  if( connected[1] )
    threshold = *in2++ ;
		
  if( connected[2] )
    drownmult = *in3++ ;
	
  inCount += D;


  for ( j = 0 ; j < Nw - D ; j++ ){
    input[j] = input[j+D];
  }
  for ( j = Nw - D; j < Nw; j++ ) {
    input[j] = *in++;
  }

  fold( input, Wanal, Nw, buffer, N, inCount );	

  rdft(N, 1, buffer, bitshuffle, trigland);
  
  if( x->peakflag ){
  	leanconvert( buffer, channel, N2);
  	for(i = 0; i <N; i+= 2){	
  		if(frame_peak < channel[i])
  			frame_peak = channel[i];
  	}
  	local_thresh = frame_peak * threshold;
  	for(i = 0; i <N; i+= 2){	
  		if(channel[i] < local_thresh)
  			channel[i]  *= drownmult;
  	}  	
  	leanunconvert( channel, buffer, N2);
  } else {
 	 nudist( buffer, channel, threshold, drownmult, N2 );
  }
  rdft( N, -1, buffer, bitshuffle, trigland );

  overlapadd( buffer, N, Wsyn, output, Nw, inCount);

  for ( j = 0; j < D; j++ )
    *out++ = output[j] * mult;

  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
			
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;

	

  /* restore state variables */
  x->inCount = inCount % Nw;
  return (w+7);
}		

void nudist( float *S, float *C, float threshold, float fmult, int N2 )

{
  int real, imag, amp, phase;
  float a, b;
  int i;
  float maxamp = 1.;
  for ( i = 0; i <= N2; i++ ) {
    imag = phase = ( real = amp = i<<1 ) + 1;
    a = ( i == N2 ? S[1] : S[real] );
    b = ( i == 0 || i == N2 ? 0. : S[imag] );
    C[amp] = hypot( a, b );

    if ( (C[amp]) < threshold  ){
      C[amp] *= fmult;
    }
    C[phase] = -atan2( b, a );
  }

  for ( i = 0; i <= N2; i++ ) {
    imag = phase = ( real = amp = i<<1 ) + 1;
    S[real] = *(C+amp) * cos( *(C+phase) );
    if ( i != N2 )
      S[imag] = -*(C+amp) * sin( *(C+phase) );
  }
}

void drown_dsp(t_drown *x, t_signal **sp, short *count)
{
  long i;
#if MSP
  for( i = 0; i < 4; i++ ){
    x->connected[i] = count[i];
  }
#endif
#if PD
  for( i = 0; i < 4; i++ ){
    x->connected[i] = 1;
  }
#endif

  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;
    drown_init(x,1);
  }
  dsp_add(drown_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, 
	  sp[3]->s_vec, sp[0]->s_n);
}


--- NEW FILE: disarray~.c ---
#include "MSPd.h"
#include "fftease.h"

#define MEMPAD (1024)

#if MSP
void *disarray_class;
#endif 

#if PD
static t_class *disarray_class;
#endif

#define OBJECT_NAME "disarray~"


typedef struct _disarray
{
#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;
    //
    int *shuffle_in;
    int *shuffle_out;
    int shuffle_count;
    int max_bin;
   //
    float mult; 
    float *trigland;
    int *bitshuffle;
    //
    float top_frequency;
    int overlap;
    int winfac;
    float c_fundamental;

    //
	void *list_outlet;
	t_atom *list_data;
	short mute;
	short bypass;
	short lock;
} t_disarray;

void *disarray_new(t_symbol *msg, short argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *disarray_perform(t_int *w);
void disarray_dsp(t_disarray *x, t_signal **sp, short *count);
void disarray_assist(t_disarray *x, void *b, long m, long a, char *s);
void switch_count (t_disarray *x, t_floatarg i);
void iswitch_count (t_disarray *x, t_int i);
void disarray_topfreq (t_disarray *x, t_floatarg freq);
void reset_shuffle( t_disarray *x );
void disarray_showstate( t_disarray *x );
void disarray_list (t_disarray *x, t_symbol *msg, short argc, t_atom *argv);
void disarray_setstate (t_disarray *x, t_symbol *msg, short argc, t_atom *argv);
int rand_index( int max);
void disarray_mute(t_disarray *x, t_floatarg toggle);
void disarray_bypass(t_disarray *x, t_floatarg toggle);
void disarray_tilde_setup(void);
void disarray_free(t_disarray *x);

void disarray_overlap(t_disarray *x, t_floatarg o);
void disarray_winfac(t_disarray *x, t_floatarg o);
void disarray_fftinfo(t_disarray *x);
void disarray_init(t_disarray *x, short initialized);

#if MSP
void main(void)
{
    setup((t_messlist **)&disarray_class, (method)disarray_new, 
    (method)disarray_free, (short)sizeof(t_disarray), 0, A_GIMME, 0);
    addmess((method)disarray_dsp, "dsp", A_CANT, 0);
    addint((method)iswitch_count);
    addbang((method)reset_shuffle);
    addmess((method)disarray_showstate,"showstate",0);
    addmess ((method)disarray_list, "list", A_GIMME, 0);
    addmess ((method)disarray_setstate, "setstate", A_GIMME, 0);
    addmess((method)disarray_assist,"assist",A_CANT,0);
    addmess ((method)disarray_mute, "mute", A_FLOAT, 0);
    addmess ((method)disarray_topfreq, "topfreq", A_FLOAT, 0);
    addmess ((method)disarray_bypass, "bypass", A_LONG, 0);
    addmess((method)disarray_overlap, "overlap",  A_DEFFLOAT, 0);
    addmess((method)disarray_winfac, "winfac",  A_DEFFLOAT, 0);
    addmess((method)switch_count, "switch_count",  A_DEFFLOAT, 0);
    addmess((method)disarray_fftinfo, "fftinfo", 0);
  
    dsp_initclass();
	  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
void disarray_tilde_setup(void)
{
  disarray_class = class_new(gensym("disarray~"), (t_newmethod)disarray_new, 
			 (t_method)disarray_free ,sizeof(t_disarray), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(disarray_class, t_disarray, x_f);
  class_addmethod(disarray_class, (t_method)disarray_dsp, gensym("dsp"), 0);
  class_addmethod(disarray_class, (t_method)disarray_showstate, gensym("showstate"), 0);
  class_addmethod(disarray_class, (t_method)disarray_list, gensym("list"), A_GIMME, 0);
  class_addmethod(disarray_class, (t_method)disarray_mute, gensym("mute"), A_FLOAT, 0);
  class_addmethod(disarray_class, (t_method)disarray_topfreq, gensym("topfreq"), A_FLOAT, 0);
  class_addmethod(disarray_class, (t_method)switch_count, gensym("switch_count"), A_FLOAT, 0);
  class_addmethod(disarray_class, (t_method)reset_shuffle, gensym("bang"),  0);
  class_addmethod(disarray_class, (t_method)disarray_overlap, gensym("overlap"), A_DEFFLOAT,0);
  class_addmethod(disarray_class, (t_method)disarray_winfac, gensym("winfac"), A_DEFFLOAT,0);
  class_addmethod(disarray_class, (t_method)disarray_fftinfo, gensym("fftinfo"), 0);
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void disarray_free(t_disarray *x)
{
#if MSP
    dsp_free((t_pxobject *) x);
#endif
     free(x->Wanal);	
     free(x->Wsyn);	
     free(x->input);	
     free(x->Hwin);
     free(x->buffer);
     free(x->channel);
     free(x->output);
     free(x->bitshuffle);
     free(x->trigland);
     free(x->list_data) ;
}


void disarray_overlap(t_disarray *x, t_floatarg o)
{
  if(!power_of_two(o)){
    error("%f is not a power of two",o);
    return;
  }
  x->overlap = (int)o;
  disarray_init(x,1);
}

void disarray_winfac(t_disarray *x, t_floatarg f)
{
  if(!power_of_two(f)){
    error("%f is not a power of two",f);
    return;
  }
  x->winfac = (int)f;
  disarray_init(x,2); /* calling lighter reinit routine */
}

void disarray_fftinfo( t_disarray *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 disarray_topfreq (t_disarray *x, t_floatarg freq)
{
 float funda = (float) x->R / (2. * (float) x->N) ;
 float curfreq;
 
   
  if( freq < funda || freq > 20000) {
  	freq = 1000.0 ;
  }
  x->max_bin = 1;  
  curfreq = 0;
  while( curfreq < freq ) {
   	 ++(x->max_bin);
    curfreq += funda ;
 }

}

void disarray_assist (t_disarray *x, void *b, long msg, long arg, char *dst)
{
	if (msg==1) {
		switch (arg) {
			case 0: sprintf(dst,"(signal) Input "); break;
		}
	} else if (msg==2) {
		switch (arg) {
			case 0: sprintf(dst,"(signal) Output "); break;
			case 1: sprintf(dst,"(list) Current State "); break;
		}
	}
}

void *disarray_new(t_symbol *msg, short argc, t_atom *argv)
{
#if MSP
   t_disarray *x = (t_disarray *)newobject(disarray_class);
  	x->list_outlet = listout((t_pxobject *)x);
    dsp_setup((t_pxobject *)x,1);
    outlet_new((t_pxobject *)x, "signal");
#endif

#if PD
  t_disarray *x = (t_disarray *)pd_new(disarray_class);
  outlet_new(&x->x_obj, gensym("signal"));
  x->list_outlet = outlet_new(&x->x_obj,gensym("list"));
#endif

// INITIALIZATIONS

  	
   	srand( time( 0 ) );

  x->D = sys_getblksize();
  x->R = sys_getsr(); 
  x->top_frequency = atom_getfloatarg(0,argc,argv);
  x->overlap = atom_getintarg(1,argc,argv);
  x->winfac = atom_getintarg(2,argc,argv);
  
  if(!power_of_two(x->overlap))
  	x->overlap = 4;
  if(!power_of_two(x->winfac))
  	x->winfac = 1; 
  disarray_init(x,0);
    return (x);
}


void disarray_init(t_disarray *x, short initialized)
{
	int i;
	float curfreq;
	
	
	if(!power_of_two(x->winfac)){
		x->winfac = 1;
	}
	if(!power_of_two(x->overlap)){
		x->overlap = 4;
	}	
	
	x->N = x->D * x->overlap;
	x->Nw = x->N * x->winfac;	
    limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
	x->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->inCount = -(x->Nw);
	
	x->c_fundamental =  (float) x->R/(float)( (x->N2)<<1 );
	x->mult = 1. / (float) x->N;
	
	x->lock = 1; 
	
	if(initialized == 0){
		x->Wanal = (float *) calloc( (MAX_Nw) , sizeof(float));	
		x->Wsyn = (float *) calloc( (MAX_Nw), sizeof(float));	
		x->input = (float *) calloc( (MAX_Nw), sizeof(float));	
		x->Hwin = (float *) calloc( (MAX_Nw), sizeof(float));
		x->output = (float *) calloc( (MAX_Nw) , sizeof(float));
		x->buffer = (float *) calloc( (MAX_N), sizeof(float));
		x->channel = (float *) calloc( ((MAX_N+2)) , sizeof(float));
		x->bitshuffle = (int *) calloc( ((MAX_N * 2)) , sizeof(int));
		x->trigland = (float *) calloc( ((MAX_N * 2)) , sizeof(float));
		x->shuffle_in = (int *) calloc( (MAX_N2), sizeof(int) ) ;
		x->shuffle_out = (int *) calloc( (MAX_N2), sizeof(int) ) ;
		x->list_data = (t_atom *) calloc( ((MAX_N+2)) , sizeof(t_atom) ) ;
		x->mute = 0;
		x->bypass = 0;
		x->shuffle_count = 0;
		
	} else {
		memset((char *)x->input,0,x->Nw * sizeof(float));
		memset((char *)x->output,0,x->Nw * sizeof(float));
		memset((char *)x->buffer,0,x->N * sizeof(float));
		memset((char *)x->channel,0,(x->N+2) * sizeof(float));
	}
	
	
	init_rdft( x->N, x->bitshuffle, x->trigland);
	makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D);
	
	
	if(initialized != 2){
		if( x->top_frequency < x->c_fundamental || x->top_frequency > 20000) {
			x->top_frequency = 1000.0 ;
		}
		x->max_bin = 1;  
		curfreq = 0;
		while( curfreq < x->top_frequency ) {
			++(x->max_bin);
			curfreq += x->c_fundamental ;
		}
		
		reset_shuffle(x); // set shuffle lookup
		x->shuffle_count = 0;
	}
	x->lock = 0;
}


void disarray_mute(t_disarray *x, t_floatarg toggle)
{
  x->mute = (short)toggle;
//  post("muted: %d", x->mute);	
}

void disarray_bypass(t_disarray *x, t_floatarg toggle)
{
  x->bypass = (short)toggle;	
}


t_int *disarray_perform(t_int *w)
{
  t_disarray *x = (t_disarray *) (w[1]);
  t_float *in = (t_float *)(w[2]);
  t_float *out = (t_float *)(w[3]);
  int n = w[4];
  
  int R = x->R;
  int Nw = x->Nw;
  int N = x->N ;
  int N2 = x-> N2;
  int Nw2 = x->Nw2;
  float *Wanal = x->Wanal;
  float *Wsyn = x->Wsyn;
  float *Hwin = x->Hwin;
  	
  float *input = x->input; 
  float *output = x->output;
  float *buffer = x->buffer;
  float *channel = x->channel;
  int		i,j;
  int inCount = x->inCount;
				
  int	D = x->D;
  float tmp;

  int shuffle_count = x->shuffle_count;

  float mult = x->mult ;
  int *bitshuffle = x->bitshuffle;
  float *trigland = x->trigland ;
  int *shuffle_in = x->shuffle_in;
  int *shuffle_out = x->shuffle_out;
  
  if( x->mute || x->lock ){
    while( n-- ){
      *out++ = 0.0;
    }
    return (w+5); 
  }
  
  if( x->bypass ){
    while( n-- ){
      *out++ = *in++ * 0.5; // gain compensation
    }
    return (w+5);
  }

  inCount += D;

  for ( j = 0 ; j < Nw - D ; j++ ){
    input[j] = input[j+D];
  }
  for ( j = Nw - D; j < Nw; j++ ) {
    input[j] = *in++;
  }

  fold(input, Wanal, Nw, buffer, N, inCount);	
  rdft(N, 1, buffer, bitshuffle, trigland);
    
  leanconvert(buffer, channel, N2);

	for( i = 0; i < shuffle_count ; i++){
		tmp = channel[ shuffle_in[ i ] * 2 ];
		channel[ shuffle_in[ i ] * 2]  = channel[ shuffle_out[ i ] * 2];
		channel[ shuffle_out[ i ] * 2]  = tmp;
	}
	
  leanunconvert( channel, buffer,  N2 );

  rdft( N, -1, buffer, bitshuffle, trigland );
  overlapadd( buffer, N, Wsyn, output, Nw, inCount);

  for ( j = 0; j < D; j++ )
    *out++ = output[j] * mult;

  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
			
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;

  /* restore state variables */
  x->inCount = inCount % Nw;

  return (w+5);
}		

void iswitch_count(t_disarray *x, t_int i)
{
	switch_count(x,(t_floatarg)i);
}

void switch_count (t_disarray *x, t_floatarg i)
{
	if( i < 0 ){
		 i = 0;
	}
	if( i > x->N2 ) {
		i = x->N2;
	}
	x->shuffle_count = i;
}

void reset_shuffle (t_disarray *x)
{
int i;
int temp, p1, p2;
int max;

//post("max bin %d",x->max_bin);
max = x->max_bin;
	for( i = 0; i < x->N2; i++ ) {
		x->shuffle_out[i] = x->shuffle_in[i] = i ;
	}
	
	for( i = 0; i < 10000; i++ ) {
		p1 = x->shuffle_out[ rand_index( max ) ];
		p2 = x->shuffle_out[ rand_index( max ) ];
		temp = x->shuffle_out[ p1 ];
		x->shuffle_out[ p1 ] = x->shuffle_out[ p2 ];
		x->shuffle_out[ p2 ] = temp;
	}
	
}

int rand_index( int max) {
	return ( rand() % max );
}

void disarray_dsp(t_disarray *x, t_signal **sp, short *count)
{

  if(x->D != sp[0]->s_n ||x->D != sp[0]->s_n ) {
    x->R = sp[0]->s_sr;
    x->D = sp[0]->s_n;
    disarray_init(x,1);
  }
		dsp_add(disarray_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec,  sp[0]->s_n);
}

// ENTER STORED SHUFFLE
void disarray_list (t_disarray *x, t_symbol *msg, short argc, t_atom *argv) {
	short i;
	int ival;
	x->shuffle_count = argc;
	for (i=0; i < argc; i++) {

    ival = (int)atom_getfloatarg(i,argc,argv);


		if ( ival < x->N2 ) {
			x->shuffle_out[ i ] = ival;
		} else {
			post ("%d out of range",ival);
		}
	}
	return;
}

void disarray_setstate (t_disarray *x, t_symbol *msg, short argc, t_atom *argv) {
  short i;
  int ival;
  
  x->shuffle_count = argc;
  for (i=0; i < argc; i++) {
	  ival = atom_getfloatarg(i,argc,argv);

    if ( ival < x->N2 && ival >= 0) {
      x->shuffle_out[ i ] = ival;
    } else {
    	error("%s: %d is out of range",OBJECT_NAME, ival);
    }
  }
  return;
}

// REPORT CURRENT SHUFFLE STATUS
void disarray_showstate (t_disarray *x ) {

  t_atom *list_data = x->list_data;

  short i;
#if MSP
  for( i = 0; i < x->shuffle_count; i++ ) {
    SETLONG(list_data+i,x->shuffle_out[i]);
  }
#endif

#if PD
  for( i = 0; i < x->shuffle_count; i++ ) {
    SETFLOAT(list_data+i,(float)x->shuffle_out[i]);
  }
#endif	
  outlet_list(x->list_outlet,0,x->shuffle_count,list_data);

  return;
}

--- NEW FILE: morphine~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *morphine_class;
#endif
#if PD
static t_class *morphine_class;
#endif

#define OBJECT_NAME "morphine~"

/*

Added additional inlet for morphine index

-EL 

*/

typedef struct _pickme {

  int		bin;
  float		value;

} pickme;


typedef struct _morphine
{
#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;
    int *bitshuffle;
    float morphIndex;
    float exponScale;
    float *Wanal;	
    float *Wsyn;	
    float *inputOne;
    float *inputTwo;
    float *Hwin;
    float *bufferOne;
    float *bufferTwo;
    float *channelOne;
 	float *channelTwo;
    float *output;
    float mult; 
    float *trigland;
    pickme *picks;
    pickme *mirror;

  short connected[8];
  short mute;
  int overlap;//overlap factor
  int winfac;//window factor
  int vs;//vector size  

} t_morphine;


/* msp function prototypes */

void *morphine_new(t_symbol *s, int argc, t_atom *argv);
//t_int *offset_perform(t_int *w);
t_int *morphine_perform(t_int *w);
void morphine_dsp(t_morphine *x, t_signal **sp, short *count);
void morphine_assist(t_morphine *x, void *b, long m, long a, char *s);
void morphine_dest(t_morphine *x, double f);

int sortIncreasing( const void *a, const void *b );
//int qsortE (char *base_ptr, int total_elems, int size, int (*cmp)());
// avoid warning with legal function pointer prototype
int qsortE (char *base_ptr, int total_elems, int size, int (*cmp)(const void *a, const void *b));
void morphine_transition(t_morphine *x, t_floatarg f);
void morphine_free(t_morphine *x);
void morphine_mute(t_morphine *x, t_floatarg toggle);
void morphine_fftinfo(t_morphine *x);
void morphine_tilde_setup(void);
void morphine_overlap(t_morphine *x, t_floatarg o);
void morphine_winfac(t_morphine *x, t_floatarg o);
void morphine_init(t_morphine *x, short initialized);

int sortIncreasing( const void *a, const void *b )
{

  if ( ((pickme *) a)->value > ((pickme *) b)->value )
    return 1;

  if ( ((pickme *) a)->value < ((pickme *) b)->value )
    return -1;

  return 0;
}

#if MSP
void main(void)
{
    setup( (struct messlist **) &morphine_class, (void *) morphine_new, (method)morphine_free,
    		 (short) sizeof(t_morphine), 0, A_GIMME, 0);
  
    addmess((method)morphine_dsp, "dsp", A_CANT, 0);
    addmess((method)morphine_assist,"assist",A_CANT,0);    
    
    addmess((method)morphine_transition,"transition", A_FLOAT, 0);
  addmess((method)morphine_overlap,"overlap", A_FLOAT, 0);
  addmess((method)morphine_mute,"mute", A_FLOAT, 0);
  addmess((method)morphine_fftinfo,"fftinfo", 0);
  addmess((method)morphine_winfac,"winfac",A_FLOAT, 0);
  addfloat((method)morphine_dest);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
    dsp_initclass();
}

void morphine_dest(t_morphine *x, double f)
{
int inlet = x->x_obj.z_in;

	if(inlet == 2)
		x->morphIndex = f;
//	post("index now %f", x->morphIndex);
}
#endif

#if PD
void morphine_tilde_setup(void)
{
  morphine_class = class_new(gensym("morphine~"), (t_newmethod)morphine_new, 
			     (t_method)morphine_free ,sizeof(t_morphine), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(morphine_class, t_morphine, x_f);
  class_addmethod(morphine_class, (t_method)morphine_dsp, gensym("dsp"), 0);
  class_addmethod(morphine_class, (t_method)morphine_assist, gensym("assist"), 0);
  class_addmethod(morphine_class, (t_method)morphine_overlap, gensym("overlap"), A_FLOAT,0);
  class_addmethod(morphine_class, (t_method)morphine_winfac, gensym("winfac"), A_FLOAT,0);
  class_addmethod(morphine_class, (t_method)morphine_mute, gensym("mute"), A_FLOAT,0);
  class_addmethod(morphine_class, (t_method)morphine_transition, gensym("transition"), A_FLOAT,0);
  class_addmethod(morphine_class, (t_method)morphine_fftinfo, gensym("fftinfo"), A_CANT,0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

/* diagnostic messages for Max */

void morphine_assist (t_morphine *x, void *b, long msg, long arg, char *dst)
{

  if (msg == 1) {

    switch (arg) {

    	case 0:		sprintf(dst,"(signal) Input One"); break;
    	case 1:		sprintf(dst,"(signal) Input Two"); break;
    	case 2:		sprintf(dst,"(signal/float) Morph Index"); break;
    }
  }

  else {

    if (msg == 2)
      sprintf(dst,"(signal) output");

  }
}

void morphine_transition(t_morphine *x, t_floatarg f)
{	
	x->exponScale = (float)f;
}


void *morphine_new(t_symbol *s, int argc, t_atom *argv)
{

#if MSP
  t_morphine 	*x = (t_morphine *) newobject(morphine_class);
  dsp_setup((t_pxobject *)x,3);
  outlet_new((t_pxobject *)x, "signal");
#endif

#if PD
  t_morphine *x = (t_morphine *)pd_new(morphine_class);
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
#endif

/* optional arguments: exponent scale, overlap, window factor */

  x->exponScale = atom_getfloatarg(0,argc,argv);
  x->overlap = atom_getfloatarg(1,argc,argv);
  x->winfac = atom_getfloatarg(2,argc,argv);

  if(!power_of_two(x->overlap)){
    x->overlap = 4;
  }
  if(!power_of_two(x->winfac)){
    x->winfac = 1;
  }
  		
  x->vs = sys_getblksize();
  x->R = sys_getsr();
 
  morphine_init(x,0);

  return (x);
}

void morphine_init(t_morphine *x, short initialized)
{
  int i;
int BIGGIE = 32768;
  
  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->N2 = (x->N)>>1;
  x->Nw2 = (x->Nw)>>1;
  x->inCount = -(x->Nw);
  x->mult = 1. / (float) x->N;
  if(!initialized){
    x->morphIndex = 0.;
    x->mute = 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->inputOne = (float *) getbytes(MAX_Nw * sizeof(float));	
    x->inputTwo = (float *) getbytes(MAX_Nw * sizeof(float));
    x->bufferOne = (float *) getbytes(MAX_N * sizeof(float));
    x->bufferTwo = (float *) getbytes(MAX_N * sizeof(float));
    x->channelOne = (float *) getbytes(MAX_N+2 * sizeof(float));
    x->channelTwo = (float *) getbytes(MAX_N+2 * sizeof(float));
    x->output = (float *) getbytes(MAX_Nw * sizeof(float));
    x->bitshuffle = (int *) getbytes(MAX_N * 2 * sizeof(int));
    x->trigland = (float *) getbytes(MAX_N * 2 * sizeof(float));
    x->picks = (pickme *) getbytes(((MAX_N2)+1) * sizeof(pickme));
    x->mirror = (pickme *) getbytes(((MAX_N2)+1) * sizeof(pickme));

  } 
		memset((char *)x->inputOne,0,x->Nw * sizeof(float));
		memset((char *)x->inputTwo,0,x->Nw * sizeof(float));
		memset((char *)x->output,0,x->Nw * sizeof(float));
 
  init_rdft( x->N, x->bitshuffle, x->trigland);
  makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
  
}

t_int *morphine_perform(t_int *w)
{

  int		
			i,j,
			inCount,
			R,
			N,
			N2,
			D,
			Nw,
			lookupIndex,
  			even, odd,
  	 		*bitshuffle;

  float		maxamp,	
  			threshMult = 1.,
			mult,
			morphIndex,
			exponScale,
			a1, b1,
  			a2, b2,
  			*inputOne,
			*inputTwo,
			*bufferOne,
			*bufferTwo,
			*output,
			*Wanal,
			*Wsyn,
			*channelOne,
			*channelTwo,
			*trigland;

  pickme	*picks,
  			*mirror;

/* get our inlets and outlets */
	
  t_morphine *x = (t_morphine *) (w[1]);
  t_float *inOne = (t_float *)(w[2]);
  t_float *inTwo = (t_float *)(w[3]);
  t_float *vec_morphIndex = (t_float *)(w[4]);
  t_float *out = (t_float *)(w[5]);
  t_int n = w[6];

  short *connected = x->connected;
  	
  if(x->mute){
	while(n--)
		*out++ = 0.0;
	return w+7;
  }

/* dereference structure  */	

  inputOne = x->inputOne;
  inputTwo = x->inputTwo;
  bufferOne = x->bufferOne;
  bufferTwo = x->bufferTwo;
  inCount = x->inCount;
  R = x->R;
  N = x->N;
  N2 = x->N2;
  D = x->D;
  Nw = x->Nw;
  Wanal = x->Wanal;
  Wsyn = x->Wsyn;
  output = x->output;
  channelOne = x->channelOne;
  channelTwo = x->channelTwo;
  bitshuffle = x->bitshuffle;
  trigland = x->trigland;
  mult = x->mult;	
  picks = x->picks;
  mirror = x->mirror;
  morphIndex = x->morphIndex;
  exponScale = x->exponScale;
  
  morphIndex = connected[2] ? *vec_morphIndex : x->morphIndex;
//  post("connected %d index %f stored index %f",connected[2],morphIndex, x->morphIndex);
  if ( morphIndex < 0 )
  	morphIndex = 0.;
  else {
    if ( morphIndex > 1. )
    	morphIndex = 1.;
  }
  
  
/* fill our retaining buffers */

  inCount += D;

  for ( j = 0 ; j < Nw - D ; j++ ) {
    inputOne[j] = inputOne[j+D];
    inputTwo[j] = inputTwo[j+D];
  }

  for ( j = Nw - D; j < Nw; j++ ) {
    inputOne[j] = *inOne++;
    inputTwo[j] = *inTwo++;
  }


/* apply hamming window and fold our window buffer into the fft buffer */ 

  fold( inputOne, Wanal, Nw, bufferOne, N, inCount );
  fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount );

/* do an fft */ 

  rdft( N, 1, bufferOne, bitshuffle, trigland );
  rdft( N, 1, bufferTwo, bitshuffle, trigland );

/* convert to polar coordinates from complex values */

    for ( i = 0; i <= N2; i++ ) {
      odd = ( even = i<<1 ) + 1;

      a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) );
      b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) );
    
      a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) );
      b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) );

      *(channelOne+even) = hypot( a1, b1 );
      *(channelOne+odd) = -atan2( b1, a1 );
    
      *(channelTwo+even) = hypot( a2, b2 );
      *(channelTwo+odd) = -atan2( b2, a2 );


/* find amplitude differences between home and visitors */

	  (picks+i)->value = fabs( *(channelOne+even) - 
	  						*(channelTwo+even) );
	  (picks+i)->bin = i;  
    }

/* sort our differences in ascending order */


	qsortE( (char *) picks, (int) N2+1, (int) sizeof(pickme),
		 sortIncreasing );

      /* now we create an effective mirror of the sorted distribution.
         we will assure that the initial transition will be made from
         small spectral differences (when the sort behavior is increasing)
         and the ending transition will also be made from small spectral
         differences */

      for ( i=0; i <= N2; i += 2 ) {
        (mirror+(i/2))->bin = (picks+i)->bin;
        (mirror+(i/2))->value = (picks+i)->value;
      }

      for ( i=1; i <= N2; i += 2 ) {
        (mirror+(N2-(i/2)))->bin = (picks+i)->bin;
        (mirror+(N2-(i/2)))->value = (picks+i)->value;
      }


/* calculate our morphIndex from an exponential function based on exponScale */
      
     if (exponScale == 0.) 
       lookupIndex = (int) (( (float) N2 ) * morphIndex);
       
     else {
     
     	if ( morphIndex < .5 ) {
     
          lookupIndex = (int) ( ((float) N2) * ((
          			 (1. - exp( exponScale * morphIndex * 2. )) /
    				 (1. - exp( exponScale )) ) * .5) );
    	}
    				 
    	else {
    	
    	  lookupIndex = (int) ( ((float) N2) * ( .5 +  
          			 (( (1. - exp( -exponScale * (morphIndex - .5) * 2. )) /
    				 (1. - exp( -exponScale )) ) * .5) ) );
    	}			 
    				 
      }
      
      
//      post("%d", lookupIndex);
      
/* choose the bins that are least different first */

    for ( i=0; i <= lookupIndex; i++ ) {

	  even = ((mirror+i)->bin)<<1,
	  odd = (((mirror+i)->bin)<<1) + 1;	

	  *(channelOne+even) = *(channelTwo+even);
	  *(channelOne+odd) = *(channelTwo+odd);
    }

/* convert back to complex form, read for the inverse fft */

  for ( i = 0; i <= N2; i++ ) {

    odd = ( even = i<<1 ) + 1;

    *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) );

    if ( i != N2 )
      *(bufferOne+odd) = -(*(channelOne+even)) * sin( *(channelOne+odd) );
  }

/* do an inverse fft */

  rdft( N, -1, bufferOne, bitshuffle, trigland );


/* dewindow our result */

  overlapadd( bufferOne, N, Wsyn, output, Nw, inCount);


/* set our output and adjust our retaining output buffer */

  for ( j = 0; j < D; j++ )
   *out++ = output[j] * mult;
	
  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
  
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;
		
/* restore state variables */

  x->inCount = inCount % Nw;
    
  return (w+7);
}		
void morphine_free(t_morphine *x)
{
#if MSP
  dsp_free((t_pxobject *) x);
#endif
  freebytes(x->trigland,0);
  freebytes(x->bitshuffle,0);
  freebytes(x->Wanal,0);
  freebytes(x->Wsyn,0);
  freebytes(x->Hwin,0);
  freebytes(x->inputOne,0);
  freebytes(x->inputTwo,0);
  freebytes(x->bufferOne,0);
  freebytes(x->bufferTwo,0);
  freebytes(x->channelOne,0);
  freebytes(x->channelTwo,0);
  freebytes(x->picks,0);
  freebytes(x->mirror,0);
  freebytes(x->output,0);
}

void morphine_fftinfo( t_morphine *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 morphine_overlap(t_morphine *x, t_floatarg df)
{
int o = (int)df;

  if(!power_of_two(o)){
    error("%d is not a power of two",o);
    return;
  }
  x->overlap = (int)o;
  morphine_init(x,1);
}

void morphine_winfac(t_morphine *x, t_floatarg df)
{
int wf = (int) df;
  if(!power_of_two(wf)){
    error("%d is not a power of two",wf);
    return;
  }
  x->winfac = wf;
  morphine_init(x,1);
}

void morphine_mute(t_morphine *x, t_floatarg toggle)
{
  x->mute = (short)toggle;
}

void morphine_dsp(t_morphine *x, t_signal **sp, short *count)
{
long i;

#if MSP
  for( i = 0; i < 3; i++ ){
    x->connected[i] = count[i];
  }
#endif
  /* signal is always connected in Pd */
#if PD 
  for( i = 0; i < 3; i++ ){
    x->connected[i] = 1;
  }
#endif

  /* reinitialize if vector size or sampling rate has been changed */
  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;
    morphine_init(x,1);
  }	

	dsp_add(morphine_perform, 6, x,
		sp[0]->s_vec,
		sp[1]->s_vec,
		sp[2]->s_vec,
		sp[3]->s_vec,
		sp[0]->s_n);
}




--- NEW FILE: resent~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *resent_class;
#endif 

#if PD
static t_class *resent_class;
#endif

#define OBJECT_NAME "resent~"

typedef struct _resent
{
#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 *frame_incr;
  float *store_incr;
  float *frame_phase;
  float frameloc;
  float **loveboat;
  float current_frame;
  int framecount;
  //
  float frame_increment ;
  float *composite_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 frames_read;
//  int MAXFRAMES;
  short mute;
  void *m_clock;
  void *m_bang;
  short playthrough;
  int hopsize;
  int overlap;
  int winfac;
  short lock;
  float duration;
  short verbose;
  float sync;
} t_resent;

void *resent_new(t_symbol *msg, short argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *resent_perform(t_int *w);
void resent_dsp(t_resent *x, t_signal **sp, short *count);
void resent_assist(t_resent *x, void *b, long m, long a, char *s);
void resent_acquire_sample (t_resent *x) ;
void resent_mute(t_resent *x, t_floatarg tog);
void resent_bin(t_resent *x, t_floatarg fbin, t_floatarg speed);
void resent_setphase(t_resent *x, t_floatarg phase);
void resent_addphase(t_resent *x, t_floatarg phase);
void resent_setspeed( t_resent *x,  t_floatarg speed );
void resent_addspeed( t_resent *x,  t_floatarg speed );
void resent_size( t_resent *x,  t_floatarg size_ms );
void resent_free( t_resent *x );
void resent_store_incr( t_resent *x );
void resent_setspeed_and_phase( t_resent *x,  t_floatarg speed, t_floatarg phase );
void resent_tick(t_resent *x);
void resent_fftinfo(t_resent *x);
void resent_init(t_resent *x, short flag);
void resent_linephase(t_resent *x, t_symbol *msg, short argc, t_atom *argv);
void resent_linespeed(t_resent *x, t_symbol *msg, short argc, t_atom *argv);
void resent_randphase(t_resent *x, t_symbol *msg, short argc, t_atom *argv);
void resent_randspeed(t_resent *x, t_symbol *msg, short argc, t_atom *argv);
void resent_playthrough(t_resent *x, t_floatarg state);
float resent_randf(float min, float max);
void resent_winfac(t_resent *x, t_floatarg factor);

void resent_verbose(t_resent *x, t_floatarg t);
void resent_fftinfo(t_resent *x);
void resent_overlap(t_resent *x, t_floatarg f);
void resent_winfac(t_resent *x, t_floatarg f);

#if MSP
void main(void)
{
  setup((t_messlist **)&resent_class, (method)resent_new, 
  (method)resent_free, (short)sizeof(t_resent), 0L,A_GIMME,0);
  addmess((method)resent_dsp, "dsp", A_CANT, 0);
  addmess((method)resent_assist,"assist",A_CANT,0);
  addbang((method)resent_acquire_sample);
  addmess((method)resent_mute, "mute", A_FLOAT, 0);
  addmess((method)resent_linespeed, "linespeed", A_GIMME, 0);
  addmess((method)resent_linephase, "linephase", A_GIMME, 0);
  addmess((method)resent_randspeed, "randspeed", A_GIMME, 0);
  addmess((method)resent_randphase, "randphase", A_GIMME, 0);
  addmess((method)resent_bin, "bin", A_DEFFLOAT, A_DEFFLOAT, 0);
  addmess((method)resent_setphase, "setphase",  A_DEFFLOAT, 0);
  addmess((method)resent_addphase, "addphase",  A_DEFFLOAT, 0);
  addmess((method)resent_setspeed, "setspeed",  A_DEFFLOAT, 0);
  addmess((method)resent_addspeed, "addspeed",  A_DEFFLOAT, 0);
  addmess((method)resent_playthrough, "playthrough",  A_DEFFLOAT, 0);
  addmess((method)resent_store_incr, "store_incr",0);
  addmess((method)resent_fftinfo, "fftinfo",0);
  addmess((method)resent_overlap, "overlap",A_FLOAT,0);
  addmess((method)resent_winfac, "winfac",A_FLOAT,0);
  addmess((method)resent_setspeed_and_phase, "setspeed_and_phase",  A_DEFFLOAT, A_DEFFLOAT, 0);
  addmess((method)resent_size, "size", A_FLOAT,0);
//  addmess((method)resent_verbose, "verbose", A_FLOAT,0);
  addmess((method)resent_overlap,"overlap",A_DEFFLOAT,0);
  addmess((method)resent_winfac,"winfac",A_DEFFLOAT,0);
  addmess((method)resent_fftinfo,"fftinfo",0);
  dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
void resent_tilde_setup(void)
{
  resent_class = class_new(gensym("resent~"), (t_newmethod)resent_new, 
			 (t_method)resent_free ,sizeof(t_resent), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(resent_class, t_resent, x_f);
  class_addmethod(resent_class,(t_method)resent_dsp,gensym("dsp"),0);
  class_addmethod(resent_class,(t_method)resent_mute,gensym("mute"),A_FLOAT,0);
  class_addmethod(resent_class,(t_method)resent_linespeed,gensym("linespeed"),A_GIMME,0);
  class_addmethod(resent_class,(t_method)resent_linephase,gensym("linephase"),A_GIMME,0);
  class_addmethod(resent_class,(t_method)resent_randspeed,gensym("randspeed"),A_GIMME,0);
  class_addmethod(resent_class,(t_method)resent_randphase,gensym("randphase"),A_GIMME,0);
  class_addmethod(resent_class,(t_method)resent_bin,gensym("bin"),A_DEFFLOAT, A_DEFFLOAT,0);
// Pd may still have parser bug for similar starting strings
  class_addmethod(resent_class,(t_method)resent_setspeed_and_phase,gensym("ssap"),A_DEFFLOAT, A_DEFFLOAT,0);
  class_addmethod(resent_class,(t_method)resent_setphase,gensym("setphase"),A_DEFFLOAT,0);
  class_addmethod(resent_class,(t_method)resent_addphase,gensym("addphase"),A_DEFFLOAT,0);
  class_addmethod(resent_class,(t_method)resent_setspeed,gensym("setspeed"),A_DEFFLOAT,0);
  class_addmethod(resent_class,(t_method)resent_addspeed,gensym("addspeed"),A_DEFFLOAT,0);
  class_addmethod(resent_class,(t_method)resent_fftinfo,gensym("fftinfo"),0);
class_addmethod(resent_class,(t_method)resent_store_incr,gensym("store_incr"),0);
  class_addmethod(resent_class,(t_method)resent_playthrough,gensym("playthrough"),A_FLOAT,0); 
  class_addmethod(resent_class,(t_method)resent_size,gensym("size"),A_FLOAT,0);
  class_addmethod(resent_class,(t_method)resent_overlap,gensym("overlap"),A_FLOAT,0); 
  class_addmethod(resent_class,(t_method)resent_winfac,gensym("winfac"),A_FLOAT,0);  
  class_addmethod(resent_class,(t_method)resent_verbose,gensym("verbose"),A_FLOAT,0);
  class_addmethod(resent_class,(t_method)resent_acquire_sample,gensym("acquire_sample"),0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif



void resent_verbose(t_resent *x, t_floatarg t)
{
  x->verbose = (short)t;
}


void resent_overlap(t_resent *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;
	resent_init(x,1);
}

void resent_winfac(t_resent *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;
	resent_init(x,2);
}

void resent_fftinfo(t_resent *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 resent_size(t_resent *x, t_floatarg size)
{
  x->duration = size/1000.0;
  resent_init(x,1);
}

void resent_store_incr(t_resent *x)
{
  int i;
  float *store_incr = x->store_incr;
  float *frame_incr = x->frame_incr;
	
  for(i = 0; i < x->N2; i++){
    store_incr[i] = frame_incr[i];
  }
}
	
void resent_free(t_resent *x){
  int i ;
#if MSP
  dsp_free((t_pxobject *) x);
#endif
  for(i = 0; i < x->framecount; i++){
    freebytes(x->loveboat[i],0) ;
  }	
  freebytes(x->frame_phase,0);
  freebytes(x->composite_frame,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->output,0);
  freebytes(x->frame_incr,0);
  freebytes(x->store_incr,0);
}

void resent_bin(t_resent *x, t_floatarg fbin, t_floatarg speed)
{
int bin_num = (int) fbin;

  if(bin_num >= 0 && bin_num < x->N2){
    x->frame_incr[bin_num] = speed ;
  } else {
    post("resent~: bin %d is out of range", bin_num);
  }
}

void resent_setphase( t_resent *x,  t_floatarg phase)
{
  float scaled_phase ;
  int i;
	
  if( phase < 0. )
    phase = 0. ;
  if( phase > 1. )
    phase = 1.;
  scaled_phase = phase * (float) x->framecount ;
  for( i = 0; i < x->N2; i++ ){
    x->frame_phase[i] = scaled_phase ;
  }
		
}

void resent_addphase( t_resent *x,  t_floatarg phase )
{
  float scaled_phase ;
  float *frame_phase = x->frame_phase;
  int framecount =  x->framecount;
  int i;
	
		
  if( phase < 0. )
    phase = 0. ;
  if( phase > 1. )
    phase = 1.;
  scaled_phase = phase * (float) framecount ;
  for( i = 0; i < x->N2; i++ ){
    frame_phase[i] += scaled_phase ;
    while( frame_phase[i] < 0 )
      frame_phase[i] += framecount;
    while( frame_phase[i] > framecount - 1 )
      frame_phase[i] -= framecount ;
  }

		
}

void resent_setspeed( t_resent *x,  t_floatarg speed )
{
  int i;
	
  for( i = 0; i < x->N2; i++ ){
	
    x->frame_incr[i] = speed ;
  }
  // post("speed reset to %f",speed);
		
}

void resent_addspeed( t_resent *x,  t_floatarg speed )
{
  int i;
  float *store_incr = x->store_incr;
  float *frame_incr = x->frame_incr;
		
  for( i = 0; i < x->N2; i++ ){	
    frame_incr[i] = store_incr[i] + speed ;
  }
	
		
}
void resent_setspeed_and_phase( t_resent *x,  t_floatarg speed, t_floatarg phase )
{
  float scaled_phase ;
  int i;
  if( phase < 0. )
    phase = 0. ;
  if( phase > 1. )
    phase = 1.;
	
  scaled_phase = phase * (float) x->framecount ;
  for( i = 0; i < x->N2; i++ ){
    x->frame_phase[i] = scaled_phase ;
    x->frame_incr[i] = speed ;
  }
//  post("ssap: speed reset to %f, phase reset to %f",speed,phase);
		
}

void resent_assist (t_resent *x, void *b, long msg, long arg, char *dst)
{
  if (msg==1) {
    switch (arg) {
    case 0:
      sprintf(dst,"(signal/bang) Input, Sample Trigger");
      break;
    }
  } else if (msg==2) {
    switch( arg){
    case 0: 
      sprintf(dst,"(signal) Output ");
      break;
    case 1:
      sprintf(dst,"(signal) Recording Sync");
      break;
    }
		
  }
}

void resent_tick(t_resent *x) {
  outlet_bang(x->m_bang);
}

void resent_init(t_resent *x,short initialized)
{
  int i;
  int last_framecount = x->framecount;

  x->lock = 1;
  
  if(!x->D)
    x->D = 256;
  if(!x->R)
    x->R = 44100;
  if(!power_of_two(x->winfac))
    x->winfac = 1;
  if(!power_of_two(x->overlap))
    x->overlap = 1;

  x->verbose = 0; // testing only
  
  x->N = x->D * x->overlap;
  x->Nw = x->N * x->winfac;
  limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
  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->tadv = (float)x->D/(float)x->R;
  x->mult = 1. / (float) x->N;
  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;
  if(x->duration < .005){
    x->duration = 1.0;
  }
  x->framecount =  x->duration/x->tadv ;
  x->read_me = 0;

  if(!initialized){
    x->frame_increment = 1.0 ;  
    x->mute = 0;
    x->playthrough = 0;
    x->sync = 0;
    x->frames_read = 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->composite_frame = (float *) getbytes( (MAX_N+2) * sizeof(float) );
    x->frame_incr = (float *) getbytes( MAX_N2 * sizeof(float) );
    x->store_incr = (float *) getbytes( MAX_N2 * sizeof(float) );
    x->frame_phase = (float *) getbytes( MAX_N2 * sizeof(float) );
    x->loveboat = (float **) getbytes(x->framecount * sizeof(float *));

    for(i=0;i<x->framecount;i++){
      x->loveboat[i] = (float *) getbytes((x->N+2) * sizeof(float));
      if(x->loveboat[i] == NULL){
				error("Insufficient Memory!");
				return;
      }
      memset((char *)x->loveboat[i],0,(x->N+2) * sizeof(float));
    }
  } else if(initialized == 1){
    for(i = 0; i < last_framecount; i++){
      freebytes(x->loveboat[i],0) ;
    }
    freebytes(x->loveboat,0);
    x->loveboat = (float **) getbytes(x->framecount * sizeof(float *));
    for(i=0;i<x->framecount;i++){
      x->loveboat[i] = (float *) getbytes((x->N+2) *sizeof(float));
      if(x->loveboat[i] == NULL){
				error("Insufficient Memory!");
				return;
      }
      memset((char *)x->loveboat[i],0,(x->N+2) * sizeof(float));
    }
  }
	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));
	memset((char *)x->frame_incr,0,(x->N2)* sizeof(float));
	memset((char *)x->store_incr,0,(x->N2) * sizeof(float));
	memset((char *)x->frame_phase,0,(x->N2) * sizeof(float));

	
  init_rdft( x->N, x->bitshuffle, x->trigland);
  x->hopsize = x->N / x->overlap;	
  makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D);

  
  x->lock = 0;
}

void *resent_new(t_symbol *msg, short argc, t_atom *argv)
{
#if MSP
  t_resent *x = (t_resent *)newobject(resent_class);
//  x->m_bang = bangout((t_pxobject *)x);
//  x->m_clock = clock_new(x,(method)resent_tick);
  dsp_setup((t_pxobject *)x,1);
  outlet_new((t_pxobject *)x, "signal");
  outlet_new((t_pxobject *)x, "signal");
#endif

#if PD
  t_resent *x = (t_resent *)pd_new(resent_class);
  outlet_new(&x->x_obj, gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
//  x->m_bang = outlet_new(&x->x_obj,gensym("bang"));
//  x->m_clock = clock_new(x,(void *)resent_tick);
#endif

  srand(clock());

  x->duration = atom_getfloatarg(0, argc, argv)/1000.0;
  x->overlap = atom_getfloatarg(1, argc, argv);
  x->winfac = atom_getfloatarg(2, argc, argv);
  x->D = sys_getblksize();
  x->R = sys_getsr();

  resent_init(x,0);

  return (x);
}

t_int *resent_perform(t_int *w)
{

  int iphase, amp, freq, i, j;
  float fincr;	
  float fpos;
  ////////////////////////////////////////////// 
  t_resent *x = (t_resent *) (w[1]);
  float *frame_incr = x->frame_incr ;
  float *frame_phase = x->frame_phase ;
  float *composite_frame = x->composite_frame ;
  float in_sample;
  t_float *in = (t_float *)(w[2]);
  t_float *out = (t_float *)(w[3]);
  t_float *sync_vec = (t_float *)(w[4]);
  t_int n = w[5];
	
  /* 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 fframe = x->current_frame ;
  float last_fpos = x->last_fpos ;
  int framecount = x->framecount;
  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 sync = x->sync;
  
  sync = (float)x->frames_read / (float)x->framecount;
  
  if(x->mute || x->lock){
	while(n--){
	  *out++ = 0.0;
	  *sync_vec++ = sync;
	}
	return (w+6);
  }
  
  inCount += D;


  
  if(x->read_me){
    for ( j = 0 ; j < Nw - D ; j++ ){
      input[j] = input[j+D];
    }
    if(x->playthrough){
      for (j = Nw - D; j < Nw; j++) {
				in_sample = input[j] = *in++;
				*out++ = in_sample * 0.5; // scale down
				*sync_vec++ = sync;
		  }
    } else{
      for (j = Nw - D; j < Nw; j++) {
				input[j] = *in++;
				*out++ = 0.0;
				*sync_vec++ = sync;
      }
    }

    fold( input, Wanal, Nw, buffer, N, inCount );	
    rdft( N, 1, buffer, bitshuffle, trigland );

    convert( buffer, x->loveboat[(x->frames_read)++], N2, c_lastphase_in, c_fundamental, c_factor_in );
    if(x->frames_read >= x->framecount){
      x->read_me = 0;
    } 	
  } 
  else {
    for( i = 0 ; i < N2; i++ ){
      amp = i<<1;
      freq = amp + 1 ;
      iphase = frame_phase[i]  ;
      if( iphase < 0 )
		iphase = 0;
      if( iphase > framecount - 1 )
		iphase = framecount - 1;
      composite_frame[amp] = x->loveboat[iphase][amp];
      composite_frame[freq] = x->loveboat[iphase][freq];
      frame_phase[i] += frame_incr[i] ;
      while( frame_phase[i] > framecount - 1)
		frame_phase[i] -= framecount ;
      while( frame_phase[i] < 0. )
		frame_phase[i] += framecount ;
    }

    unconvert(composite_frame, 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++){
      *out++ = output[j] * mult;
      *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.;
    }
  }
	
  /* restore state variables */

  x->inCount = inCount %Nw;
  x->current_frame = fframe;
  x->last_fpos = last_fpos;
  x->sync = sync;


  return (w+6);
}
	


void resent_acquire_sample(t_resent *x)
{
  x->read_me = 1;
  x->frames_read = 0;

  return;
}

void resent_mute(t_resent *x, t_floatarg tog)
{
  x->mute = tog;	
}

void resent_playthrough(t_resent *x, t_floatarg state)
{
  x->playthrough = state;
}

void resent_linephase(t_resent *x, t_symbol *msg, short argc, t_atom *argv)
{
  int bin1, bin2;
  float phase1, phase2, bindiff;
  int i;
  float m1, m2;

  bin1 = (int) atom_getfloatarg(0, argc, argv);
  phase1 = atom_getfloatarg(1, argc, argv) * x->framecount;
  bin2 = (int) atom_getfloatarg(2, argc, argv);
  phase2 = atom_getfloatarg(3, argc, argv) * x->framecount;

  if( bin1 > x->N2 || bin2 > x->N2 ){
    error("too high bin number");
    return;
  }
  bindiff = bin2 - bin1;
  if( bindiff < 1 ){
    error("make bin2 higher than bin 1, bye now");
    return;
  }
  for( i = bin1; i < bin2; i++ ){
    m2 = (float) i / bindiff;
    m1 = 1. - m2;
    x->frame_phase[i] = m1 * phase1 + m2 * phase2;
  }
}

void resent_randphase(t_resent *x, t_symbol *msg, short argc, t_atom *argv)
{

  float minphase, maxphase;
  int i;
  int framecount = x->framecount;
  
  minphase = atom_getfloatarg(0, argc, argv);
  maxphase = atom_getfloatarg(1, argc, argv);
	
//  post("minphase %f maxphase %f",minphase, maxphase);
  if(minphase < 0.0)
    minphase = 0.0;
  if( maxphase > 1.0 )
    maxphase = 1.0;
  	
  for( i = 0; i < x->N2; i++ ){
    x->frame_phase[i] = (int) (resent_randf( minphase, maxphase ) * (float) (framecount - 1) ) ;	
  } 
}

void resent_randspeed(t_resent *x, t_symbol *msg, short argc, t_atom *argv)
{

  float minspeed, maxspeed;
  int i;


  minspeed = atom_getfloatarg(0, argc, argv);
  maxspeed = atom_getfloatarg(1, argc, argv);

  for( i = 0; i < x->N2; i++ ){
    x->frame_incr[i] = resent_randf(minspeed, maxspeed);
  } 
}

void resent_linespeed(t_resent *x, t_symbol *msg, short argc, t_atom *argv)
{
  int bin1, bin2;
  float speed1, speed2, bindiff;
  int i;
  float m1, m2;

  bin1 = (int) atom_getfloatarg(0, argc, argv);
  speed1 = atom_getfloatarg(1, argc, argv);
  bin2 = (int) atom_getfloatarg(2, argc, argv);
  speed2 = atom_getfloatarg(3, argc, argv);

  if( bin1 > x->N2 || bin2 > x->N2 ){
    error("too high bin number");
    return;
  }
  bindiff = bin2 - bin1;
  if( bindiff < 1 ){
    error("make bin2 higher than bin 1, bye now");
    return;
  }
  for( i = bin1; i < bin2; i++ ){
    m2 = (float) i / bindiff;
    m1 = 1. - m2;
    x->frame_incr[i] = m1 * speed1 + m2 * speed2;
  }
}
void resent_dsp(t_resent *x, t_signal **sp, short *count)
{
  if(x->R != sp[0]->s_sr || x->D != sp[0]->s_n){
    x->R = sp[0]->s_sr;
    x->D = sp[0]->s_n;
    if(x->verbose)
      post("new vector size: %d, new sampling rate:%d",x->D,x->R);
    resent_init(x,1);
  }		
  dsp_add(resent_perform, 5, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
}

float resent_randf(float min,float max)
{
  float rval;
  rval = (float) (rand() % RAND_MAX) / (float) RAND_MAX;
  return ( min + (max-min) * rval );	
}

--- NEW FILE: xsyn~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *xsyn_class;
#endif 

#if PD
static t_class *xsyn_class;
#endif

#define OBJECT_NAME "xsyn~"

typedef struct _xsyn
{
#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;
	float *input1;	
	float *buffer1;
	float *channel1;
	
	
	float *input2;	
	float *buffer2;
	float *channel2;
	//
	int	inCount;
	float *Hwin;
	float *Wanal;	
	float *Wsyn;	
	float *output;
	/* xsyn vars */
	
	float *c_lastphase_in1;
	float *c_lastphase_in2;
	float *c_lastphase_out;
	float c_fundamental;
	float c_factor_in;
	float c_factor_out;
	
	//	float *filter ;
	// for fast fft
	float mult; 
	float *trigland;
	int *bitshuffle;
	int overlap;//overlap factor
		int winfac;//window factor
			int vs;//vector size
				short mute;//flag
} t_xsyn;

void *xsyn_new(t_symbol *s, int argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *xsyn_perform(t_int *w);
void xsyn_dsp(t_xsyn *x, t_signal **sp, short *count);
void xsyn_assist(t_xsyn *x, void *b, long m, long a, char *s);
void xsyn_dsp_free( t_xsyn *x );
void xsyn_init(t_xsyn *x, short initialized);
void xsyn_mute(t_xsyn *x, t_floatarg toggle);
void xsyn_fftinfo(t_xsyn *x);
void xsyn_overlap(t_xsyn *x, t_floatarg f);
void xsyn_winfac(t_xsyn *x, t_floatarg f);

void xsyn_dsp_free( t_xsyn *x )
{
#if MSP
	dsp_free( (t_pxobject *) x);
#endif
	freebytes(x->c_lastphase_in1,0); 
	freebytes(x->c_lastphase_in2,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->Hwin,0);
	freebytes(x->input1,0);
	freebytes(x->buffer1,0);
	freebytes(x->channel1,0);
	freebytes(x->input2,0);
	freebytes(x->buffer2,0);
	freebytes(x->channel2,0);
	freebytes(x->output,0);
}

#if MSP
void main(void)
{
	setup((t_messlist **)&xsyn_class, (method) xsyn_new, (method)xsyn_dsp_free, 
		  (short)sizeof(t_xsyn), 0, A_GIMME, 0);
	addmess((method)xsyn_dsp, "dsp", A_CANT, 0);
	addmess((method)xsyn_assist,"assist",A_CANT,0);
	addmess((method)xsyn_mute,"mute",A_FLOAT,0);
	addmess((method)xsyn_overlap,"overlap",A_FLOAT,0);
	addmess((method)xsyn_winfac,"winfac",A_DEFFLOAT,0);
	addmess((method)xsyn_fftinfo,"fftinfo",0);
	dsp_initclass();
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
void xsyn_tilde_setup(void)
{
	xsyn_class = class_new(gensym("xsyn~"), (t_newmethod)xsyn_new, 
						   (t_method)xsyn_dsp_free ,sizeof(t_xsyn), 0,A_GIMME,0);
	CLASS_MAINSIGNALIN(xsyn_class, t_xsyn, x_f);
	class_addmethod(xsyn_class, (t_method)xsyn_dsp, gensym("dsp"), 0);
	class_addmethod(xsyn_class, (t_method)xsyn_assist, gensym("assist"), 0);
	class_addmethod(xsyn_class, (t_method)xsyn_mute, gensym("mute"), A_DEFFLOAT,0);
	class_addmethod(xsyn_class, (t_method)xsyn_overlap, gensym("overlap"), A_DEFFLOAT,0);
	class_addmethod(xsyn_class,(t_method)xsyn_winfac,gensym("winfac"),A_FLOAT,0);
	class_addmethod(xsyn_class,(t_method)xsyn_fftinfo,gensym("fftinfo"),0);
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void xsyn_mute(t_xsyn *x, t_floatarg toggle)
{
	x->mute = (short)toggle;
}

void xsyn_overlap(t_xsyn *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;
	xsyn_init(x,1);
}

void xsyn_winfac(t_xsyn *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;
	xsyn_init(x,2);
}

void xsyn_fftinfo(t_xsyn *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 xsyn_assist (t_xsyn *x, void *b, long msg, long arg, char *dst)
{
	if (msg==1) {
		switch (arg) {
			case 0:
				sprintf(dst,"(signal) Input 1 ");
				break;
			case 1:
				sprintf(dst,"(signal) Input 2 ");
				break;
		}
	} else if (msg==2) {
		sprintf(dst,"(signal) Output ");
	}
}

void *xsyn_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
	t_xsyn *x = (t_xsyn *)newobject(xsyn_class);
	dsp_setup((t_pxobject *)x,2);
	outlet_new((t_pxobject *)x, "signal");
#endif
#if PD
	t_xsyn *x = (t_xsyn *)pd_new(xsyn_class);
	inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
	outlet_new(&x->x_obj, gensym("signal"));
#endif
	x->overlap = atom_getfloatarg(0,argc,argv);
	x->winfac = atom_getfloatarg(1,argc,argv);
	if(!power_of_two(x->overlap))
		x->overlap = 4;
	if(!power_of_two(x->winfac))
		x->winfac = 1;
	
	x->R = sys_getsr();
	x->vs = sys_getblksize();
	
	xsyn_init(x,0);
	return (x);
}

void xsyn_init(t_xsyn *x, short initialized)
{
	
	
	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->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->inCount = -(x->Nw);
	x->mult = 1. / (float) x->N;
	
	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;
	if(!initialized){
		x->mute = 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->input1 = (float *) getbytes(MAX_Nw * sizeof(float));	
		x->buffer1 = (float *) getbytes(MAX_N  * sizeof(float));
		x->channel1 = (float *) getbytes((MAX_N+2)  * sizeof(float));
		x->input2 = (float *) getbytes(MAX_Nw * sizeof(float));	
		x->buffer2 = (float *) getbytes(MAX_N  * sizeof(float));
		x->channel2 = (float *) getbytes((MAX_N+2)  * sizeof(float));
		x->output = (float *) getbytes(MAX_Nw * sizeof(float));
		x->bitshuffle = (int *) getbytes(MAX_N * 2 * sizeof(int));
		x->trigland = (float *) getbytes(MAX_N * 2 * sizeof(float));
		x->c_lastphase_in1 = (float *) getbytes((MAX_N2+1) * sizeof(float));
		x->c_lastphase_in2 = (float *) getbytes((MAX_N2+1) * sizeof(float));
		x->c_lastphase_out = (float *) getbytes((MAX_N2+1) * sizeof(float));
	} 
	memset((char *)x->input1,0,x->Nw * sizeof(float));
	memset((char *)x->input2,0,x->Nw * sizeof(float));
	memset((char *)x->output,0,x->Nw * sizeof(float));
	memset((char *)x->c_lastphase_in1,0,(x->N2+1) * sizeof(float));
	memset((char *)x->c_lastphase_in2,0,(x->N2+1) * sizeof(float));
	memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float));
		
	init_rdft( x->N, x->bitshuffle, x->trigland);
	makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
}

t_int *xsyn_perform(t_int *w)
{
	t_float *in1,*out, *in2;
	
	float sample, outsamp ;
	
	float	*input1, *input2,
		*output,
		*buffer1, *buffer2,
		*Wanal,
		*Wsyn,
		*channel1, *channel2;
	
	int		n,
		i,j,
		inCount,
		R,
		N,
		N2,
		D,
		Nw;
	float maxamp ;	
	int	*bitshuffle;	
	float *trigland;	
	float mult;
	float a1, a2, b1, b2;
	int even, odd;
	
	
	
	t_xsyn *x = (t_xsyn *) (w[1]);
	in1 = (t_float *)(w[2]);
	in2 = (t_float *)(w[3]);
	out = (t_float *)(w[4]);
	n = (int)(w[5]);
	
	/* dereference struncture  */	
	input1 = x->input1;
	input2 = x->input2;
	buffer1 = x->buffer1;
	buffer2 = x->buffer2;
	inCount = x->inCount;
	R = x->R;
	N = x->N;
	N2 = x->N2;
	D = x->D;
	Nw = x->Nw;
	Wanal = x->Wanal;
	Wsyn = x->Wsyn;
	output = x->output;
	buffer1 = x->buffer1;
	buffer2 = x->buffer2;
	channel1 = x->channel1;
	channel2 = x->channel2;
	bitshuffle = x->bitshuffle;
	trigland = x->trigland;
	mult = x->mult;	
	
	if(x->mute){
		while(n--){
			*out++ = 0.0;
		}
		return (w+6);
	}
	x->inCount += D;
	
	for ( j = 0 ; j < Nw - D ; j++ ){
		input1[j] = input1[j+D];
		input2[j] = input2[j+D];
	}
	for ( j = Nw - D; j < Nw; j++ ) {
		input1[j] = *in1++;
		input2[j] = *in2++;
	}
	
	fold( input1, Wanal, Nw, buffer1, N, inCount );		
	fold( input2, Wanal, Nw, buffer2, N, inCount );	
	rdft( N, 1, buffer1, bitshuffle, trigland );
	rdft( N, 1, buffer2, bitshuffle, trigland );
	leanconvert( buffer1, channel1, N2 );
	leanconvert( buffer2, channel2, N2 );
	maxamp = 0 ;
	for( i = 0; i < N; i+= 2 ) {
		if( channel2[i] > maxamp ) {
			maxamp = channel2[i];
		}
	}
	if( maxamp == 0.0 )
		maxamp = 1.0 ;
	for( i = 0; i < N; i+= 2 ) {
		channel1[i] *= (channel2[i] / maxamp );
	}
	
	leanunconvert( channel1, buffer1,  N2 );
	
	rdft( N, -1, buffer1, bitshuffle, trigland );
	
	overlapadd( buffer1, N, Wsyn, output, Nw, inCount);
	
	for ( j = 0; j < D; j++ )
		*out++ = output[j] * mult;
	
	for ( j = 0; j < Nw - D; j++ )
		output[j] = output[j+D];
	
	for ( j = Nw - D; j < Nw; j++ )
		output[j] = 0.;
	
	
	
	/* restore state variables */
	x->inCount = inCount;
	return (w+6);
}		

void xsyn_dsp(t_xsyn *x, t_signal **sp, short *count)
{
	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;
		xsyn_init(x,1);
	}
	
	dsp_add(xsyn_perform, 5, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec,  sp[0]->s_n);
}


--- NEW FILE: bthresher~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *bthresher_class;
#endif 

#if PD
static t_class *bthresher_class;
#endif

#define OBJECT_NAME "bthresher~"

typedef struct _bthresher
{
#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	in_count;
  float *Wanal;	
  float *Wsyn;	
  float *input;	
  float *Hwin;
  float *buffer;
  float *channel;
  float *output;
  /* bthresher vars */
  float *move_threshold;
  float *composite_frame ;
  int *frames_left;
  int max_hold_frames;
  float max_hold_time;
  int first_frame;
  float *damping_factor ;
  float thresh_scalar;
  float damp_scalar;
  short thresh_connected;
  short damping_connected;
  void *list_outlet;
  void *misc_outlet;
  t_atom *list_data;

  // for convert
  float *c_lastphase_in;
  float *c_lastphase_out;
  float c_fundamental;
  float c_factor_in;
  float c_factor_out;
  // for fast fft
  float mult; 
  float *trigland;
  int *bitshuffle;
  short mute;
  short bypass;
  float init_thresh;
  float init_damping;
  int overlap;
  int winfac;
  float tadv;
  short inf_hold;
} t_bthresher;

  
void *bthresher_new(t_symbol *s, int argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *bthresher_perform(t_int *w);
void bthresher_dsp(t_bthresher *x, t_signal **sp, short *count);
void bthresher_assist(t_bthresher *x, void *b, long m, long a, char *s);
void bthresher_float(t_bthresher *x, double f);
void bthresher_mute(t_bthresher *x, t_floatarg f);
void bthresher_bypass(t_bthresher *x, t_floatarg f);
void bthresher_overlap(t_bthresher *x, t_floatarg f);
void bthresher_winfac(t_bthresher *x, t_floatarg f);
void bthresher_fftinfo(t_bthresher *x);
void bthresher_free(t_bthresher *x);
void bthresher_bin(t_bthresher *x, t_floatarg bin_num, t_floatarg threshold, t_floatarg damper);
void bthresher_rdamper(t_bthresher *x, t_floatarg min, t_floatarg max );
void bthresher_rthreshold(t_bthresher *x, t_floatarg min, t_floatarg max);
void bthresher_dump(t_bthresher *x );
void bthresher_list (t_bthresher *x, t_symbol *msg, short argc, t_atom *argv);
void bthresher_init(t_bthresher *x, short initialized);
float bthresher_boundrand(float min, float max);
void bthresher_allthresh(t_bthresher *x, t_floatarg f);
void bthresher_alldamp(t_bthresher *x, t_floatarg f);
void bthresher_inf_hold(t_bthresher *x, t_floatarg f);
void bthresher_max_hold(t_bthresher *x, t_floatarg f);

#if MSP
void main(void)
{
  setup((t_messlist **)&bthresher_class, (method)bthresher_new, (method)bthresher_free, 
  	(short)sizeof(t_bthresher), 0, A_GIMME, 0);
  addmess((method)bthresher_dsp, "dsp", A_CANT, 0);
  addmess((method)bthresher_assist,"assist",A_CANT,0);
  addmess((method)bthresher_mute,"mute",A_FLOAT,0);
  addmess((method)bthresher_bypass,"bypass",A_FLOAT,0);
  addmess((method)bthresher_overlap,"overlap",A_FLOAT,0);
  addmess((method)bthresher_winfac,"winfac",A_FLOAT,0);
  addmess((method)bthresher_fftinfo,"fftinfo",0);
  addmess ((method)bthresher_bin, "bin", A_FLOAT, A_FLOAT, A_FLOAT, 0);
  addmess ((method)bthresher_rdamper, "rdamper", A_DEFFLOAT, A_DEFFLOAT, 0);
  addmess ((method)bthresher_rthreshold, "rthreshold", A_DEFFLOAT, A_DEFFLOAT, 0);
  addmess((method)bthresher_dump,"dump",0);
  addmess((method)bthresher_list,"list",A_GIMME,0);
  addmess((method)bthresher_alldamp,"alldamp",A_FLOAT,0);
  addmess((method)bthresher_allthresh,"allthresh",A_FLOAT,0);
  addmess((method)bthresher_inf_hold,"inf_hold",A_FLOAT,0);
  addmess((method)bthresher_max_hold,"max_hold",A_FLOAT,0);
  addfloat((method)bthresher_float);
  dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif
#if PD
void bthresher_tilde_setup(void){
  bthresher_class = class_new(gensym("bthresher~"), (t_newmethod)bthresher_new, 
      (t_method)bthresher_free ,sizeof(t_bthresher), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(bthresher_class, t_bthresher, x_f);
  class_addmethod(bthresher_class,(t_method)bthresher_dsp,gensym("dsp"),0);
  class_addmethod(bthresher_class,(t_method)bthresher_mute,gensym("mute"),A_FLOAT,0);
  class_addmethod(bthresher_class,(t_method)bthresher_bypass,gensym("bypass"),A_FLOAT,0);
  class_addmethod(bthresher_class,(t_method)bthresher_overlap,gensym("overlap"),A_FLOAT,0);
  class_addmethod(bthresher_class,(t_method)bthresher_winfac,gensym("winfac"),A_FLOAT,0);
  class_addmethod(bthresher_class,(t_method)bthresher_fftinfo,gensym("fftinfo"),0);
  class_addmethod(bthresher_class,(t_method)bthresher_rdamper,gensym("rdamper"),A_FLOAT,A_FLOAT,0);
  class_addmethod(bthresher_class,(t_method)bthresher_rthreshold,gensym("rthreshold"),A_FLOAT,A_FLOAT,0);
  class_addmethod(bthresher_class,(t_method)bthresher_dump,gensym("dump"),0);
  class_addmethod(bthresher_class,(t_method)bthresher_list,gensym("list"),A_GIMME,0);
  class_addmethod(bthresher_class,(t_method)bthresher_alldamp,gensym("alldamp"),A_FLOAT,0);
  class_addmethod(bthresher_class,(t_method)bthresher_allthresh,gensym("allthresh"),A_FLOAT,0);
  class_addmethod(bthresher_class,(t_method)bthresher_inf_hold,gensym("inf_hold"),A_FLOAT,0);
  class_addmethod(bthresher_class,(t_method)bthresher_max_hold,gensym("max_hold"),A_FLOAT,0); 
  class_addmethod(bthresher_class,(t_method)bthresher_bin,gensym("bin"),A_FLOAT,A_FLOAT,A_FLOAT,0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void bthresher_fftinfo( t_bthresher *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 bthresher_free( t_bthresher *x ){
#if MSP
  dsp_free( (t_pxobject *) x);
#endif


  freebytes(x->Wanal,0); 
  freebytes(x->Wsyn,0);
  freebytes(x->Hwin,0);
  freebytes(x->buffer,0);
  freebytes(x->channel,0);
  freebytes(x->input,0);
  freebytes(x->output,0);
  freebytes(x->trigland,0); 
  freebytes(x->bitshuffle,0); 
  /* full phase vocoder */
  freebytes(x->c_lastphase_in,0); 
  freebytes(x->c_lastphase_out,0); 
  /* external-specific memory */
  freebytes(x->composite_frame,0);
  freebytes(x->frames_left,0);
  freebytes(x->move_threshold,0);
  freebytes(x->damping_factor,0);
  freebytes(x->list_data,0);
}

void bthresher_max_hold(t_bthresher *x, t_floatarg f)
{
	if(f<=0)
		return;
	x->max_hold_time = f * .001;
	x->max_hold_frames = x->max_hold_time / x->tadv;
}

void bthresher_inf_hold(t_bthresher *x, t_floatarg f)
{
	x->inf_hold = (int)f;
}

void bthresher_allthresh(t_bthresher *x, t_floatarg f)
{
int i;
//post("thresh %f",f);
	for(i=0;i<x->N2+1;i++)
		x->move_threshold[i] = f;
}

void bthresher_alldamp(t_bthresher *x, t_floatarg f)
{
int i;
//post("damp %f",f);
	for(i=0;i<x->N2+1;i++)
		x->damping_factor[i] = f;
}

void bthresher_overlap(t_bthresher *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;
	bthresher_init(x,1);
}

void bthresher_winfac(t_bthresher *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;
	bthresher_init(x,2);
}

void bthresher_mute(t_bthresher *x, t_floatarg f){
  x->mute = f;
}
void bthresher_bypass(t_bthresher *x, t_floatarg f){
  x->bypass = f;
}

void bthresher_assist (t_bthresher *x, void *b, long msg, long arg, char *dst)
{
  if (msg==1) {
    switch (arg) {
    case 0:sprintf(dst,"(signal) Input");break;
    case 1:sprintf(dst,"(signal/float) Threshold Scalar");break;
    case 2:sprintf(dst,"(signal/float) Damping Factor Scalar");break;
    }
  } else if (msg==2) {
    switch (arg) {
    case 0:sprintf(dst,"(signal) Output");break;
    case 1:sprintf(dst,"(list) Current State");break;
    }
  }
}

void bthresher_list (t_bthresher *x, t_symbol *msg, short argc, t_atom *argv) {
  int i, bin, idiv;
  float fdiv;
  float *damping_factor = x->damping_factor;
  float *move_threshold = x->move_threshold;

  //	post("reading %d elements", argc);
  idiv = fdiv = (float) argc / 3.0 ;
  if( fdiv - idiv > 0.0 ) {
    post("list must be in triplets");
    return;
  }
/*  for( i = 0; i < x->N2+1; i++) {
    move_threshold[i] = 0.0 ;
  }*/

  for( i = 0; i < argc; i += 3 ) {
    bin = atom_getintarg(i,argc,argv);
    damping_factor[bin] = atom_getfloatarg(i+1,argc,argv);
    move_threshold[bin] = atom_getfloatarg(i+2,argc,argv);
/*    bin = argv[i].a_w.w_long ;
    damping_factor[bin] = argv[i + 1].a_w.w_float;
    move_threshold[bin] = argv[i + 2].a_w.w_float;*/
  }
}

void bthresher_dump (t_bthresher *x) {

  t_atom *list_data = x->list_data;
  float *damping_factor = x->damping_factor;
  float *move_threshold = x->move_threshold;

  int i,j, count;
#if MSP
  for( i = 0, j = 0; i < x->N2 * 3 ; i += 3, j++ ) {
    SETLONG(list_data+i,j);
    SETFLOAT(list_data+(i+1),damping_factor[j]);
    SETFLOAT(list_data+(i+2),move_threshold[j]);		
  }	
#endif

#if PD
  for( i = 0, j = 0; i < x->N2 * 3 ; i += 3, j++ ) {
    SETFLOAT(list_data+i,(float)j);
    SETFLOAT(list_data+(i+1),damping_factor[j]);
    SETFLOAT(list_data+(i+2),move_threshold[j]);		
  }
#endif

  count = x->N2 * 3;
  outlet_list(x->list_outlet,0,count,list_data);

  return;
}

void *bthresher_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
  t_bthresher *x = (t_bthresher *)newobject(bthresher_class);
  x->list_outlet = listout((t_pxobject *)x);
  dsp_setup((t_pxobject *)x,3);
  outlet_new((t_pxobject *)x, "signal");
#endif

#if PD
    t_bthresher *x = (t_bthresher *)pd_new(bthresher_class);
    inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
    inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
    outlet_new(&x->x_obj, gensym("signal"));
    x->list_outlet = outlet_new(&x->x_obj,gensym("list"));
#endif


  x->D = sys_getblksize();
  x->R = sys_getsr();
  
  x->init_thresh = atom_getfloatarg(0,argc,argv);
  x->init_damping = atom_getfloatarg(1,argc,argv);
  x->overlap = atom_getintarg(2,argc,argv);
  x->winfac = atom_getintarg(3,argc,argv);
  
  bthresher_init(x,0);
  


  return (x);
}

void bthresher_init(t_bthresher *x, short initialized)
{
int i; 

  if(!x->D)
    x->D = 256;
  if(!x->R)
    x->R = 44100;
  if(!power_of_two(x->overlap))
    x->overlap = 4;
  if(!power_of_two(x->winfac))
    x->winfac = 1;

  x->N = x->D * x->overlap;
  x->Nw = x->N * x->winfac;
    
limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);

  x->mult = 1. / (float) x->N;
  x->N2 = (x->N)>>1;
  x->Nw2 = (x->Nw)>>1;
  x->in_count = -(x->Nw);
  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;
	      
	if(!initialized){
	  x->first_frame = 1;
	  x->max_hold_time = 60.0 ;
	  x->thresh_connected = 0;
	  x->damping_connected = 0;
	  x->thresh_scalar = 1;
	  x->damp_scalar = 1;
	  x->mute = 0;
	  x->bypass = 0;
	  x->inf_hold = 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->buffer = (float *) getbytes((MAX_N) * sizeof(float));
	  x->channel = (float *) getbytes(((MAX_N+2)) * sizeof(float));
	  x->output = (float *) getbytes((MAX_Nw) * 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->composite_frame = (float *) getbytes( (MAX_N+2)* sizeof(float));
	  x->frames_left = (int *) getbytes((MAX_N+2)* sizeof(int));

	  // TRIPLETS OF bin# damp_factor threshold
	  x->list_data = (t_atom *) getbytes((MAX_N2 + 1) * 3 * sizeof(t_atom));

	  x->move_threshold = (float *) getbytes((MAX_N2+1)* sizeof(float));
	  x->damping_factor = (float *) getbytes((MAX_N2+1)* sizeof(float));
	  

	} 
  if(initialized == 0 || initialized == 1){
	  for(i = 0; i < x->N2+1; i++) {
	    x->move_threshold[i] = x->init_thresh;
	    x->damping_factor[i] = x->init_damping;
	  }
  }

	memset((char *)x->input,0,x->Nw * sizeof(float));
	memset((char *)x->output,0,x->Nw * sizeof(float));
	memset((char *)x->buffer,0,x->N * 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->tadv = (float) x->D / (float) x->R;
  x->max_hold_frames = x->max_hold_time / x->tadv;
  init_rdft(x->N, x->bitshuffle, x->trigland);
  makehanning(x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
}

void bthresher_rdamper(t_bthresher *x,  t_floatarg min, t_floatarg max)
{
  int i;	

  for( i = 0; i < x->N2; i++ ) {
    x->damping_factor[i] = bthresher_boundrand(min, max);
  }
}

void bthresher_rthreshold( t_bthresher *x,  t_floatarg min, t_floatarg max )
{
  int i;
  for( i = 0; i < x->N2; i++ ) {
    x->move_threshold[i] = bthresher_boundrand(min, max);
  }
}


void bthresher_bin(t_bthresher *x, t_floatarg bin_num, t_floatarg damper, t_floatarg threshold)
{
int bn = (int) bin_num;
  if( bn >= 0 && bn < x->N2 ){
//    post("setting %d to %f %f",bn,threshold,damper);
    x->move_threshold[bn] = threshold;
    x->damping_factor[bn] = damper;
  } else {
    post("bthresher~: %d is out of range", bn);
  }
}


t_int *bthresher_perform(t_int *w)
{
	
  float sample, outsamp ;
  int	i, j, on;
  t_bthresher *x = (t_bthresher *) (w[1]);
  float *in = (t_float *)(w[2]);
  float *inthresh = (t_float *)(w[3]);
  float *damping = (t_float *)(w[4]);
  float *out = (t_float *)(w[5]);
  t_int n = w[6];
	

  int *bitshuffle = x->bitshuffle;
  float *trigland = x->trigland;
  float mult = x->mult;	

  int in_count = x->in_count;
  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 *damping_factor = x->damping_factor;
  float *move_threshold = x->move_threshold;
  float *input = x->input;
  float *output = x->output;
  float *buffer = x->buffer;
  float *channel = x->channel;
  float *composite_frame = x->composite_frame;
  int max_hold_frames = x->max_hold_frames;
  int *frames_left = x->frames_left;
  float thresh_scalar = x->thresh_scalar;
  float damp_scalar = x->damp_scalar;
  short inf_hold = x->inf_hold;
  
  if( x->mute ) {
    for( j = 0; j < D; j++) {
      *out++ = 0.0 ;
    }
  } else if ( x->bypass ) {
    for( j = 0; j < D; j++) {
      *out++ = *in++ * 0.5;
    }
  } else {
#if MSP
    if( x->thresh_connected ) {
      thresh_scalar = *inthresh++;
    }
    if( x->damping_connected ) {
      damp_scalar = *damping++;
    }
#endif

#if PD
      thresh_scalar = *inthresh++;
      damp_scalar = *damping++;
#endif	

    in_count += D;


    for ( j = 0 ; j < Nw - D ; j++ )
      input[j] = input[j+D];

    for ( j = Nw-D; j < Nw; j++ ) {
      input[j] = *in++;
    }

    fold( input, Wanal, Nw, buffer, N, in_count );
    rdft( N, 1, buffer, bitshuffle, trigland );
    convert( buffer, channel, N2, x->c_lastphase_in, x->c_fundamental, x->c_factor_in  );
	
    if( x->first_frame ){
      for ( i = 0; i < N+2; i++ ){
        composite_frame[i] = channel[i];
        x->frames_left[i] = max_hold_frames;
      }
      x->first_frame = 0;
    } else {
      if( thresh_scalar < .999 || thresh_scalar > 1.001 || damp_scalar < .999 || damp_scalar > 1.001 ) {
				for(i = 0, j = 0; i < N+2; i += 2, j++ ){
				  if( fabs( composite_frame[i] - channel[i] ) > move_threshold[j] * thresh_scalar|| frames_left[j] <= 0 ){
				    composite_frame[i] = channel[i];
				    composite_frame[i+1] = channel[i+1];
				    frames_left[j] = max_hold_frames;
				  } else {
				    if(!inf_hold){
				      --(frames_left[j]);
				    }
				    composite_frame[i] *= damping_factor[j] * damp_scalar;
				  }
				}

      } else {
				for( i = 0, j = 0; i < N+2; i += 2, j++ ){
				  if( fabs( composite_frame[i] - channel[i] ) > move_threshold[j] || frames_left[j] <= 0 ){
				    composite_frame[i] = channel[i];
				    composite_frame[i+1] = channel[i+1];
				    frames_left[j] = max_hold_frames;
				  } else {
				    if(!inf_hold){
				      --(frames_left[j]);
				    }
				    composite_frame[i] *= damping_factor[j];
				  }
				}
      }
    }

    unconvert(x->composite_frame, buffer, N2, x->c_lastphase_out, x->c_fundamental, x->c_factor_out);
    rdft(N, -1, buffer, bitshuffle, trigland);

    overlapadd(buffer, N, Wsyn, output, Nw, in_count);

    for ( j = 0; j < D; j++ )
      *out++ = output[j] * mult;

    for ( j = 0; j < Nw - D; j++ )
      output[j] = output[j+D];
			
    for ( j = Nw - D; j < Nw; j++ )
      output[j] = 0.;
  }
  x->in_count = in_count % Nw;
  x->thresh_scalar = thresh_scalar;
  x->damp_scalar = damp_scalar;
	
  return (w+7);
}		

#if MSP
void bthresher_float(t_bthresher *x, double f) // Look at floats at inlets
{
  int inlet = x->x_obj.z_in;
  int i;	
  if (inlet == 1)
    {
      x->thresh_scalar = f;
    } else if (inlet == 2)  {
      x->damp_scalar = f;
    }
}
#endif

void bthresher_dsp(t_bthresher *x, t_signal **sp, short *count)
{
#if MSP
  x->thresh_connected = count[1];
  x->damping_connected = count[2];
#endif
  if(sp[0]->s_n != x->D || x->R != sp[0]->s_sr){
    x->D = sp[0]->s_n;
    x->R = sp[0]->s_sr;
    bthresher_init(x,1);
  }
  dsp_add(bthresher_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec,
	  sp[0]->s_n);
}

float bthresher_boundrand( float min, float max) {
  float frand;
  frand = (float) (rand() % 32768)/ 32768.0;
  return (min + frand * (max-min) );
}


--- NEW FILE: disarrain~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *disarrain_class;
#endif 

#if PD
static t_class *disarrain_class;
#endif

#define OBJECT_NAME "disarrain~"


typedef struct _disarrain
{
#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 *last_channel;
  float *composite_channel;
  float *output;
  int overlap;
  int winfac;
  //

  int *shuffle_mapping;
  int *last_shuffle_mapping;
  int *shuffle_tmp; // work space for making a new distribution
  int shuffle_count;// number of bins to swap
  int last_shuffle_count;// ditto from last shuffle mapping
  int max_bin;
  //
  float mult; 
  float *trigland;
  int *bitshuffle;
  //
  void *list_outlet;
  t_atom *list_data;
  short mute;
  short bypass;
  float frame_duration; // duration in seconds of a single frame
  float interpolation_duration; // duration in seconds of interpolation
  int interpolation_frames; // number of frames to interpolate
  int frame_countdown; // keep track of position in interpolation
  int overlap_factor;// determines window size, etc.
  float top_frequency;// for remapping spectrum
  int perform_method;// 0 for lean, 1 for full conversion
  // for convert
//  float *c_lastphase_in;
//  float *c_lastphase_out;
  float c_fundamental;
  float c_factor_in;
  float c_factor_out;
  // check switching algorithm
  short lock;// lock for switching mapping arrays, but not used now
  short force_fade; // new fadetime set regardless of situation
  short force_switch;// binds new distribution to change of bin count
} t_disarrain;

void *disarrain_new(t_symbol *msg, short argc, t_atom *argv);

t_int *disarrain_perform_lean(t_int *w);
t_int *disarrain_perform_full(t_int *w);
void disarrain_dsp(t_disarrain *x, t_signal **sp, short *count);
void disarrain_assist(t_disarrain *x, void *b, long m, long a, char *s);
void disarrain_switch_count (t_disarrain *x, t_floatarg i);
void disarrain_topfreq (t_disarrain *x, t_floatarg freq);
void disarrain_fadetime (t_disarrain *x, t_floatarg f);
void reset_shuffle( t_disarrain *x );
void disarrain_showstate( t_disarrain *x );
void disarrain_list (t_disarrain *x, t_symbol *msg, short argc, t_atom *argv);
void disarrain_setstate (t_disarrain *x, t_symbol *msg, short argc, t_atom *argv);
void disarrain_isetstate (t_disarrain *x, t_symbol *msg, short argc, t_atom *argv);
int rand_index(int max);
void disarrain_mute(t_disarrain *x, t_floatarg toggle);
void disarrain_bypass(t_disarrain *x, t_floatarg toggle);
void copy_shuffle_array(t_disarrain *x);
void interpolate_frames_to_channel(t_disarrain *x);
void disarrain_killfade(t_disarrain *x);
void disarrain_forcefade(t_disarrain *x, t_floatarg toggle);
void disarrain_init(t_disarrain *x, short initialized);
void disarrain_free(t_disarrain *x);
void disarrain_overlap(t_disarrain *x, t_floatarg o);
void disarrain_winfac(t_disarrain *x, t_floatarg o);
void disarrain_fftinfo(t_disarrain *x);
void disarrain_force_switch(t_disarrain *x, t_floatarg toggle);


#if MSP
void main(void)
{
  setup((t_messlist **)&disarrain_class, (method)disarrain_new, (method)disarrain_free, 
  (short)sizeof(t_disarrain), 0, A_GIMME, 0);
  addmess((method)disarrain_dsp, "dsp", A_CANT, 0);
  addint((method)disarrain_switch_count);
  addbang((method)reset_shuffle);
  addmess((method)disarrain_showstate,"showstate",0);
  addmess ((method)disarrain_list, "list", A_GIMME, 0);
  addmess ((method)disarrain_setstate, "setstate", A_GIMME, 0);
  addmess ((method)disarrain_isetstate, "isetstate", A_GIMME, 0);
  addmess((method)disarrain_assist,"assist",A_CANT,0);
  addmess ((method)disarrain_mute, "mute", A_FLOAT, 0);
  addmess ((method)disarrain_topfreq, "topfreq", A_FLOAT, 0);
  addmess ((method)disarrain_fadetime, "fadetime", A_FLOAT, 0);
  addmess ((method)disarrain_bypass, "bypass", A_FLOAT, 0);
  addmess ((method)disarrain_forcefade, "forcefade", A_FLOAT, 0);
  addmess ((method)disarrain_force_switch, "force_switch", A_FLOAT, 0);
  addmess ((method)disarrain_switch_count, "switch_count", A_FLOAT, 0);
  addmess ((method)disarrain_killfade, "killfade", 0);
  addmess ((method)reset_shuffle, "reset_shuffle", 0);
  
  addmess((method)disarrain_overlap, "overlap",  A_DEFFLOAT, 0);
  addmess((method)disarrain_winfac, "winfac",  A_DEFFLOAT, 0);
  addmess((method)disarrain_fftinfo, "fftinfo", 0);
  dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
void disarrain_tilde_setup(void)
{
  disarrain_class = class_new(gensym("disarrain~"), (t_newmethod)disarrain_new, 
			 (t_method)disarrain_free ,sizeof(t_disarrain), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(disarrain_class, t_disarrain, x_f);
  class_addmethod(disarrain_class, (t_method)disarrain_dsp, gensym("dsp"), 0);
  class_addmethod(disarrain_class, (t_method)disarrain_showstate, gensym("showstate"), 0);
  class_addmethod(disarrain_class, (t_method)disarrain_list, gensym("list"), A_GIMME, 0);
  class_addmethod(disarrain_class, (t_method)disarrain_setstate, gensym("setstate"), A_GIMME, 0);
  class_addmethod(disarrain_class, (t_method)disarrain_isetstate, gensym("isetstate"), A_GIMME, 0);

  class_addmethod(disarrain_class, (t_method)disarrain_mute, gensym("mute"), A_FLOAT, 0);
  class_addmethod(disarrain_class, (t_method)disarrain_topfreq, gensym("topfreq"), A_FLOAT, 0);
  class_addmethod(disarrain_class, (t_method)disarrain_fadetime, gensym("fadetime"), A_FLOAT, 0);
  class_addmethod(disarrain_class, (t_method)disarrain_bypass, gensym("bypass"), A_FLOAT, 0);
  class_addmethod(disarrain_class, (t_method)disarrain_forcefade, gensym("forcefade"), A_FLOAT, 0);
class_addmethod(disarrain_class, (t_method)disarrain_force_switch, gensym("force_switch"), A_FLOAT, 0);


//  class_addmethod(disarrain_class, (t_method)disarrain_killfade, gensym("reset"), A_FLOAT, 0);
  class_addmethod(disarrain_class, (t_method)reset_shuffle, gensym("bang"),  0);
  class_addmethod(disarrain_class, (t_method)reset_shuffle, gensym("reset_shuffle"),  0);
  class_addmethod(disarrain_class, (t_method)disarrain_switch_count, gensym("switch_count"), A_FLOAT, 0);
  
  class_addmethod(disarrain_class, (t_method)disarrain_overlap, gensym("overlap"), A_DEFFLOAT,0);
  class_addmethod(disarrain_class, (t_method)disarrain_winfac, gensym("winfac"), A_DEFFLOAT,0);
  class_addmethod(disarrain_class, (t_method)disarrain_fftinfo, gensym("fftinfo"), 0);
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void disarrain_free(t_disarrain *x)
{
#if MSP
    dsp_free((t_pxobject *) x);
#endif
     freebytes(x->Wanal, x->Nw * sizeof(float));	
     freebytes(x->Wsyn, x->Nw * sizeof(float));	
     freebytes(x->input, x->Nw * sizeof(float));	
     freebytes(x->Hwin, x->Nw * sizeof(float));
     freebytes(x->buffer, x->N * sizeof(float));
     freebytes(x->channel, (x->N+2) * sizeof(float));
     freebytes(x->last_channel, (x->N+2) * sizeof(float));
     freebytes(x->composite_channel, x->N+2 * sizeof(float));
     freebytes(x->output, x->Nw * sizeof(float));
     freebytes(x->bitshuffle, (x->N * 2) * sizeof(int));
     freebytes(x->trigland, x->N * 2 * sizeof(float));
     freebytes(x->shuffle_mapping, x->N2 * sizeof(int)) ;
     freebytes(x->last_shuffle_mapping, x->N2 * sizeof(int)) ;
     freebytes(x->shuffle_tmp, x->N2 * sizeof(int)) ;
     freebytes(x->list_data,(x->N+2) * sizeof(t_atom)) ;
//     freebytes(x->c_lastphase_in, (x->N2+1)*sizeof(float));
//     freebytes(x->c_lastphase_out,(x->N2+1)* sizeof(float));
}



void disarrain_init(t_disarrain *x, short initialized)
{
  int i;
  float curfreq;

  if(!power_of_two(x->winfac)){
    x->winfac = 1;
  }
  if(!power_of_two(x->overlap)){
    x->overlap = 4;
  }	
  x->N = x->D * x->overlap;
  x->Nw = x->N * x->winfac;	
  limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
  x->c_fundamental =  (float) x->R/(float)( (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;

  x->N2 = (x->N)>>1;
  x->Nw2 = (x->Nw)>>1;
  x->inCount = -(x->Nw);
  x->mult = 1. / (float) x->N;
  
  x->lock = 1; // not good enough
  
  if(initialized == 0){
    x->Wanal = (float *) calloc(MAX_Nw , sizeof(float));	
    x->Wsyn = (float *) calloc(MAX_Nw , sizeof(float));	
    x->input = (float *) calloc(MAX_Nw , sizeof(float));	
    x->Hwin = (float *) calloc(MAX_Nw , sizeof(float));
    x->buffer = (float *) calloc(MAX_N , sizeof(float));
    x->channel = (float *) calloc(MAX_N+2 , sizeof(float));
    x->last_channel = (float *) calloc(MAX_N+2 , sizeof(float));
    x->composite_channel = (float *) calloc(MAX_N+2 , sizeof(float));
    x->output = (float *) calloc(MAX_Nw , sizeof(float));
    x->bitshuffle = (int *) calloc((MAX_N * 2) , sizeof(int));
    x->trigland = (float *) calloc(MAX_N * 2 , sizeof(float));
    x->shuffle_mapping = (int *) calloc( MAX_N2 , sizeof(int) ) ;
    x->last_shuffle_mapping = (int *) calloc( MAX_N2 , sizeof(int) ) ;
    x->shuffle_tmp = (int *) calloc( MAX_N2 , sizeof(int) ) ;
    x->list_data = (t_atom *) calloc((MAX_N+2) , sizeof(t_atom) ) ;
    x->mute = 0;
    x->bypass = 0;
    x->force_fade = 0;
    x->interpolation_duration = 0.1; //seconds
  } 
		memset((char *)x->input,0,x->Nw * sizeof(float));
		memset((char *)x->output,0,x->Nw * sizeof(float));
		memset((char *)x->buffer,0,x->N * sizeof(float));
		memset((char *)x->channel,0,(x->N+2) * sizeof(float));
		memset((char *)x->last_channel,0,(x->N+2) * sizeof(float));


  init_rdft( x->N, x->bitshuffle, x->trigland);
  makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D);
 
  
  if(initialized != 2){
	  if( x->top_frequency < x->c_fundamental || x->top_frequency > 20000) {
	    x->top_frequency = 1000.0 ;
	  }
	  x->max_bin = 1;  
	  curfreq = 0;
	  while( curfreq < x->top_frequency ) {
	    ++(x->max_bin);
	    curfreq += x->c_fundamental ;
	  }
	  for( i = 0; i < x->N2; i++ ) {
	    x->shuffle_mapping[i] = x->last_shuffle_mapping[i] = i*2;
	  }
	  reset_shuffle(x); // set shuffle lookup
	  copy_shuffle_array(x);// copy it to the last lookup (for interpolation)
	  x->frame_duration = (float) x->D / (float) x->R;
	  x->interpolation_frames = x->interpolation_duration / x->frame_duration;
	  x->frame_countdown = 0;
	  x->shuffle_count = 0;
	  x->last_shuffle_count = 0;
  }
  x->lock = 0;
 }


void disarrain_force_switch(t_disarrain *x, t_floatarg f)
{
	x->force_switch = (short)f;
}

void disarrain_fadetime (t_disarrain *x, t_floatarg f)
{
  int frames;
  float duration;
  
  // forcefade allows forcing new fadetime at any time
  if(! x->force_fade) {
#if MSP
    if(!sys_getdspstate()){
      return; // DSP is inactive
    }
#endif
    if(x->frame_countdown) {
      error("disarrain: fade in progress, fadetime reset blocked");
      return;
    }
  }
  
  duration = f * .001;
  frames = duration / x->frame_duration;
  if( frames <= 1){
    error("%s: too short fade",OBJECT_NAME);
    return;
  }
  x->interpolation_duration = f * .001;
  x->interpolation_frames = frames;

}

void disarrain_killfade(t_disarrain *x)
{
  x->frame_countdown = 0;

}

void disarrain_topfreq (t_disarrain *x, t_floatarg freq)
{
  float funda = (float) x->R / (2. * (float) x->N) ;
  float curfreq;
 
  if( freq < funda || freq > 20000) {
    freq = 1000.0 ;
  }
  x->max_bin = 1;  
  curfreq = 0;
  while( curfreq < freq ) {
    ++(x->max_bin);
    curfreq += funda ;
  }
}

void disarrain_assist (t_disarrain *x, void *b, long msg, long arg, char *dst)
{
  if (msg==1) {
    switch (arg) {
    case 0: sprintf(dst,"(signal) Input"); break;
    }
  } else if (msg==2) {
    switch (arg) {
    case 0:	sprintf(dst,"(signal) Output"); break;
    case 1: sprintf(dst,"(signal) Interpolation Sync"); break;
    case 2: sprintf(dst,"(list) Current State"); break;
    }
  }
}

void *disarrain_new(t_symbol *msg, short argc, t_atom *argv)
{

#if MSP
  t_disarrain *x = (t_disarrain *)newobject(disarrain_class);
  x->list_outlet = listout((t_pxobject *)x);
  dsp_setup((t_pxobject *)x,1);
  outlet_new((t_pxobject *)x, "signal");
  outlet_new((t_pxobject *)x, "signal");
#endif

#if PD
  t_disarrain *x = (t_disarrain *)pd_new(disarrain_class);
  outlet_new(&x->x_obj, gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
  x->list_outlet = outlet_new(&x->x_obj,gensym("list"));
#endif

  srand(time(0));

  x->D = sys_getblksize();
  x->R = sys_getsr(); 
  x->top_frequency = atom_getfloatarg(0,argc,argv);
  x->overlap_factor = atom_getintarg(1,argc,argv);
  x->winfac = atom_getintarg(2,argc,argv);

  disarrain_init(x,0);
  return (x);
}

void disarrain_forcefade(t_disarrain *x, t_floatarg toggle)
{
  x->force_fade = (short)toggle;	
}

void disarrain_mute(t_disarrain *x, t_floatarg toggle)
{
  x->mute = (short)toggle;	
}

void disarrain_bypass(t_disarrain *x, t_floatarg toggle)
{
  x->bypass = (short)toggle;	
}

void disarrain_overlap(t_disarrain *x, t_floatarg df)
{
int o = (int)df;
  if(!power_of_two(o)){
    error("%d is not a power of two",o);
    return;
  }
  x->overlap = (int)o;
  disarrain_init(x,1);
}

void disarrain_winfac(t_disarrain *x, t_floatarg f)
{
int wf = (int)f;
  if(!power_of_two(wf)){
    error("%f is not a power of two",wf);
    return;
  }
  x->winfac = wf;
  disarrain_init(x,2); /* calling lighter reinit routine */
}

void disarrain_fftinfo( t_disarrain *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);
}


// lean convert perform method
t_int *disarrain_perform_lean(t_int *w)
{
  t_disarrain *x = (t_disarrain *) (w[1]);
  t_float *in = (t_float *)(w[2]);
  t_float *out = (t_float *)(w[3]);
  t_float *vec_sync = (t_float *)(w[4]);
  int n = w[5];
  int R = x->R;
  int Nw = x->Nw;
  int N = x->N ;
  int N2 = x-> N2;
  int Nw2 = x->Nw2;
  float *Wanal = x->Wanal;
  float *Wsyn = x->Wsyn;
  float *Hwin = x->Hwin;
  	
  float *input = x->input; 
  float *output = x->output;
  float *buffer = x->buffer;
  float *channel = x->channel;
  float *last_channel = x->last_channel;
  int		i,j;
  int inCount = x->inCount;
				
  int	D = x->D;
  float tmp;
  float ival = 0.0;
  int *shuffle_mapping = x->shuffle_mapping;
  int shuffle_count = x->shuffle_count;
  int *last_shuffle_mapping = x->last_shuffle_mapping;
  int last_shuffle_count = x->last_shuffle_count;	
  float mult = x->mult ;
  int *bitshuffle = x->bitshuffle;
  float *trigland = x->trigland ;
  int frame_countdown = x->frame_countdown; // will read from variable
  int interpolation_frames = x->interpolation_frames;
  if( x->mute || x->lock ){
    while( n-- ){
      *out++ = 0.0;
    }
    return (w+6); 
  }
  if( x->bypass ){
    while( n-- ){
      *out++ = *in++ * 0.5; // gain compensation
    }
    return (w+6);
  }

  inCount += D;

  for ( j = 0 ; j < Nw - D ; j++ ){
    input[j] = input[j+D];
  }
  for ( j = Nw - D; j < Nw; j++ ) {
    input[j] = *in++;
  }

  fold(input, Wanal, Nw, buffer, N, inCount);	
  rdft(N, 1, buffer, bitshuffle, trigland);
    
  leanconvert(buffer, channel, N2);

  // first time for interpolation, just do last frame 

  if(frame_countdown == interpolation_frames){

    for( i = 0, j = 0; i < last_shuffle_count ; i++, j+=2){
      tmp = channel[j];
      channel[j] = channel[last_shuffle_mapping[i]];
      channel[last_shuffle_mapping[i]] = tmp;
    }
    --frame_countdown;
  } 
  else if( frame_countdown > 0 ){
    ival = (float)frame_countdown/(float)interpolation_frames;
    // copy current frame to lastframe
    for(j = 0; j < N; j+=2){
      last_channel[j] = channel[j];
    }	
    // make last frame swap
    for(i = 0, j = 0; i < last_shuffle_count ; i++, j+=2){
      tmp = last_channel[j];
      last_channel[j] = last_channel[last_shuffle_mapping[i]];
      last_channel[last_shuffle_mapping[i]] = tmp;

    }	
    // make current frame swap
    for( i = 0, j = 0; i < shuffle_count ; i++, j+=2){
      tmp = channel[j];
      channel[j]  = channel[shuffle_mapping[i]];
      channel[shuffle_mapping[i]]  = tmp;

    }
    // now interpolate between the two

    for(j = 0; j < N; j+=2){
      channel[j] = channel[j] + ival * (last_channel[j] - channel[j]);
    }
		
    --frame_countdown;
    if(frame_countdown <= 0){
      copy_shuffle_array(x);
    }
  } else {
    // otherwise straight swapping
    for( i = 0, j = 0; i < shuffle_count ; i++, j+=2){
      tmp = channel[j];
      channel[j]  = channel[ shuffle_mapping[i]];
      channel[shuffle_mapping[i]] = tmp;     
    }
  }
  leanunconvert( channel, buffer,  N2 );

  rdft( N, -1, buffer, bitshuffle, trigland );
  overlapadd( buffer, N, Wsyn, output, Nw, inCount);

  for ( j = 0; j < D; j++ )
    *out++ = output[j] * mult;

  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
			
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;
/* send out sync signal */
  for(j = 0; j < n; j++){
  	vec_sync[j] = ival;
  }
  /* restore state variables */
  x->inCount = inCount % Nw;
  x->frame_countdown = frame_countdown;
  return (w+6);
}		


void interpolate_frames_to_channel(t_disarrain *x)
{
  float ival;
  float tmp;
  int i,j;
  int frame_countdown = x->frame_countdown;
  int interpolation_frames = x->interpolation_frames;
  float *channel = x->channel;
  float *last_channel = x->last_channel;
  int *shuffle_mapping = x->shuffle_mapping;
  int shuffle_count = x->shuffle_count;
  int *last_shuffle_mapping = x->shuffle_mapping;
  int last_shuffle_count = x->shuffle_count;	
  int local_max_bins;
  int N = x->N;
	
  ival = (float)frame_countdown/(float)interpolation_frames;

//  post("interpolation:%f",ival);
  local_max_bins = (shuffle_count > last_shuffle_count)? shuffle_count : last_shuffle_count;
  // copy channel (only amplitudes)
  for(j = 0; j < N; j+=2){
    last_channel[j] = channel[j];
  }
  // make last frame
  for( i = 0, j = 0; i < last_shuffle_count ; i++, j+=2){
    tmp = last_channel[j];
    last_channel[j] = last_channel[last_shuffle_mapping[i]];
    last_channel[last_shuffle_mapping[i]] = tmp;
  }
  // make current frame
  for( i = 0, j = 0; i < shuffle_count ; i++, j+=2){
    tmp = channel[j];
    channel[j]  = channel[shuffle_mapping[i]];
    channel[shuffle_mapping[i]]  = tmp;
  }
  // now interpolate between the two

  for(j = 0; j < N; j+=2){
    // channel[j] = channel[j] + ival * (last_channel[j] - channel[j]);
		
    // or better?
    channel[j] += ival * (last_channel[j] - channel[j]);
  }
}


void disarrain_switch_count (t_disarrain *x, t_floatarg f)
{
int i = f;
/*
#if MSP
  if(! sys_getdspstate()){
    return; // DSP is inactive
  }
#endif
*/
  if( x->frame_countdown && !x->force_fade){
    error("%s: fade in progress, no action taken",OBJECT_NAME);
    return;
  }
  if( i < 0 ){
    i = 0;
  }
  if( i > x->N2 ) {
    i = x->N2;
  }
  copy_shuffle_array(x);
  x->last_shuffle_count = x->shuffle_count;
  x->shuffle_count = i;
  x->frame_countdown = x->interpolation_frames; // force interpolation
}


void reset_shuffle (t_disarrain *x)
{
  int i;
  int temp, p1, p2;
  int max = x->max_bin;
  int  N2 = x->N2;
  
  int *shuffle_tmp = x->shuffle_tmp;
  int *shuffle_mapping = x->shuffle_mapping;

  
  copy_shuffle_array(x);

  for( i = 0; i < N2; i++ ) {
    shuffle_tmp[i] = i;
  }
  // improve this algorithm
		
  for( i = 0; i < max; i++ ) {
    p1 = shuffle_tmp[ rand_index( max ) ];
    p2 = shuffle_tmp[ rand_index( max ) ];
    temp = shuffle_tmp[p1];
    shuffle_tmp[ p1 ] = shuffle_tmp[ p2 ];
    shuffle_tmp[ p2 ] = temp;
  }
	
	
	
  // now map to amplitude channels
  for( i = 0; i < N2; i++ ) {
    shuffle_tmp[i] *= 2;
  }
	
  // force interpolation
  x->frame_countdown = x->interpolation_frames;	
  
  x->lock = 1;
  for( i = 0; i < N2; i++ ) {
    shuffle_mapping[i] = shuffle_tmp[i];
  }

  x->lock = 0;
}

void copy_shuffle_array(t_disarrain *x)
{
  int i;
  int N2 = x->N2;
  int *shuffle_mapping = x->shuffle_mapping;
  int *last_shuffle_mapping = x->last_shuffle_mapping;	


  for(i = 0; i<N2; i++){
    last_shuffle_mapping[i] = shuffle_mapping[i];
  }
  x->last_shuffle_count = x->shuffle_count;

}

int rand_index(int max) {

  return (rand() % max);
}

void disarrain_dsp(t_disarrain *x, t_signal **sp, short *count)
{
  long i;

  if(x->D != sp[0]->s_n ||x->D != sp[0]->s_n ) {
    x->R = sp[0]->s_sr;
    x->D = sp[0]->s_n;
    disarrain_init(x,1);
  }

  dsp_add(disarrain_perform_lean, 5, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);

}

// ENTER STORED SHUFFLE
void disarrain_list (t_disarrain *x, t_symbol *msg, short argc, t_atom *argv) {
  short i;
  int ival;
//  post("list message called");
  x->shuffle_count = argc;
//  post("list: count now %d",x->shuffle_count );
  for (i=0; i < argc; i++) {
  #if MSP
    ival = argv[i].a_w.w_long;
  #endif
  
  #if PD
    ival = atom_getfloatarg(i,argc,argv);
  #endif
    if (ival < x->N2) {
      x->shuffle_mapping[i] = ival;
//      post("set %d to %d",i, x->shuffle_mapping[ i ]);
    } else {
//      post ("%d out of range",ival);
    }
		
  }
//  post("last val is %d", x->shuffle_mapping[argc - 1]);
  return;
}


void disarrain_isetstate (t_disarrain *x, t_symbol *msg, short argc, t_atom *argv) {
  short i;
  int ival;
  
//  x->last_shuffle_count = x->shuffle_count;
  
  copy_shuffle_array(x);
  x->shuffle_count = argc;
  
  
//  x->lock = 1;
    
  for (i=0; i < argc; i++) {
    ival = 2 * atom_getfloatarg(i,argc,argv);

    if ( ival < x->N2 && ival >= 0) {
      x->shuffle_mapping[ i ] = ival;
    }else {
    	error("%s: %d is out of range",OBJECT_NAME, ival);
    }
  }

//  x->lock = 0;
  x->frame_countdown = x->interpolation_frames;
  
  return;
}

void disarrain_setstate (t_disarrain *x, t_symbol *msg, short argc, t_atom *argv) {
  short i;
  int ival;
  
  x->shuffle_count = argc;
  for (i=0; i < argc; i++) {
	  ival = 2 *atom_getfloatarg(i,argc,argv);

    if ( ival < x->N2 && ival >= 0) {
      x->shuffle_mapping[ i ] = ival;
    } else {
    	error("%s: %d is out of range",OBJECT_NAME, ival);
    }
  }
  return;
}

// REPORT CURRENT SHUFFLE STATUS
void disarrain_showstate (t_disarrain *x ) {

  t_atom *list_data = x->list_data;

  short i;
#if MSP
  for( i = 0; i < x->shuffle_count; i++ ) {
    SETLONG(list_data+i,x->shuffle_mapping[i]/2);
  }
#endif

#if PD
  for( i = 0; i < x->shuffle_count; i++ ) {
    SETFLOAT(list_data+i,(float)x->shuffle_mapping[i]/2);
  }
#endif	
  outlet_list(x->list_outlet,0,x->shuffle_count,list_data);

  return;
}


--- NEW FILE: presidency~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *presidency_class;
#endif 

#if PD
static t_class *presidency_class;
#endif

#define OBJECT_NAME "presidency~"

typedef struct _presidency
{
#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 **loveboat;
  float current_frame;
  float *local_frame; // needs mem allocation in init
  int framecount;
  float lo_freq;
  float hi_freq;
  float topfreq;
  float curfreq;
  float P;
  int lo_bin;
  int hi_bin;
  float i_vector_size;
  float vector_size;
  float synthesis_threshold;
  float pitch_increment;
  // oscillator
  float *table;
  float *bindex;
  float *lastamp;// stores last amplitudes for each bin
  float *lastfreq;// stores last frequencies
  float table_si;
  int table_length;
  //
  float frame_increment ;
  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 frames_read;
  //  int MAXFRAMES;
  short mute;
  short virgin;
  short playthrough;
  short in2_connected;
  short in3_connected;
  short in4_connected;
  int overlap;
  int winfac;
  int hopsize;
  float duration;
  short lock;
  short verbose;
  short override;
  float sync;
} t_presidency;

void *presidency_new(t_symbol *s, int argc, t_atom *argv);
t_int *presidency_perform(t_int *w);
void presidency_dsp(t_presidency *x, t_signal **sp, short *count);
void presidency_assist(t_presidency *x, void *b, long m, long a, char *s);
void presidency_bangname(t_presidency *x) ;

void presidency_playthrough( t_presidency *x, t_floatarg tog) ;
void presidency_float(t_presidency *x, double f) ;
void presidency_int(t_presidency *x, long i);
void presidency_mute(t_presidency *x, t_floatarg tog);
void presidency_free(t_presidency *x);
void presidency_init(t_presidency *x, short initialized);
void presidency_size(t_presidency *x, t_floatarg newsize);
void presidency_winfac(t_presidency *x, t_floatarg factor);
void presidency_overlap(t_presidency *x, t_floatarg o);
void presidency_fftinfo(t_presidency *x) ;
void presidency_verbose(t_presidency *x, t_floatarg t);
void presidency_acquire_sample(t_presidency *x);
void presidency_low_freq(t_presidency *x, t_floatarg f);
void presidency_high_freq(t_presidency *x, t_floatarg f);
void presidency_calc_bins_from_freqs(t_presidency *x);
void presidency_abs_thresh(t_presidency *x, t_floatarg t);

#if MSP
void main(void)
{
  setup((t_messlist **)&presidency_class, (method)presidency_new, (method)presidency_free, 
	(short)sizeof(t_presidency), 0, A_GIMME,0);
  addmess((method)presidency_dsp, "dsp", A_CANT, 0);
  addmess((method)presidency_assist,"assist",A_CANT,0);
  addfloat((method)presidency_float);
  addint((method)presidency_int);
  addbang((method)presidency_bangname);
  addmess((method)presidency_mute, "mute", A_FLOAT, 0);
  addmess((method)presidency_fftinfo, "fftinfo",  0);
  addmess((method)presidency_playthrough, "playthrough", A_DEFFLOAT, 0);
  addmess((method)presidency_size, "size", A_DEFFLOAT, 0);
  addmess((method)presidency_overlap, "overlap", A_DEFFLOAT, 0);
  addmess((method)presidency_winfac, "winfac", A_DEFFLOAT, 0);
  addmess((method)presidency_verbose, "verbose", A_DEFFLOAT, 0);
  addmess((method)presidency_low_freq, "low_freq", A_DEFFLOAT, 0);
  addmess((method)presidency_high_freq, "high_freq", A_DEFFLOAT, 0);
  addmess((method)presidency_acquire_sample, "acquire_sample", 0);
  addmess((method)presidency_abs_thresh, "abs_thresh", A_FLOAT, 0);
  dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
void presidency_tilde_setup(void)
{
  presidency_class = class_new(gensym("presidency~"), (t_newmethod)presidency_new, 
			 (t_method)presidency_free ,sizeof(t_presidency), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(presidency_class, t_presidency, x_f);
  class_addmethod(presidency_class,(t_method)presidency_dsp,gensym("dsp"),0);
  class_addmethod(presidency_class,(t_method)presidency_mute,gensym("mute"),A_FLOAT,0);
  class_addmethod(presidency_class,(t_method)presidency_fftinfo,gensym("fftinfo"),0);
  class_addmethod(presidency_class,(t_method)presidency_playthrough,gensym("playthrough"),A_FLOAT,0); 
  class_addmethod(presidency_class,(t_method)presidency_size,gensym("size"),A_FLOAT,0);
  class_addmethod(presidency_class,(t_method)presidency_overlap,gensym("overlap"),A_FLOAT,0); 
  class_addmethod(presidency_class,(t_method)presidency_winfac,gensym("winfac"),A_FLOAT,0);  
  class_addmethod(presidency_class,(t_method)presidency_verbose,gensym("verbose"),A_FLOAT,0);
  class_addmethod(presidency_class,(t_method)presidency_acquire_sample,gensym("acquire_sample"),0);
  class_addmethod(presidency_class,(t_method)presidency_low_freq,gensym("low_freq"),A_FLOAT,0);
  class_addmethod(presidency_class,(t_method)presidency_high_freq,gensym("high_freq"),A_FLOAT,0);
  class_addmethod(presidency_class,(t_method)presidency_abs_thresh,gensym("abs_thresh"),A_FLOAT,0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void presidency_abs_thresh(t_presidency *x, t_floatarg f)
{
	if(f < 0){
		error("illegal value for threshold");
		return;
	}
	x->synthesis_threshold = f;
}

void presidency_low_freq(t_presidency *x, t_floatarg f)
{
	if(f > x->hi_freq || f < 0){
		error("illegal value for low freq");
		return;
	}
	x->lo_freq = f;
	presidency_calc_bins_from_freqs(x);
}

void presidency_high_freq(t_presidency *x, t_floatarg f)
{
	if(f < x->lo_freq || f > x->R/2.0){
		error("illegal value for high freq");
		return;
	}
	x->hi_freq = f;
	presidency_calc_bins_from_freqs(x);
}

void presidency_calc_bins_from_freqs(t_presidency *x)
{
  x->hi_bin = 1;  
  x->curfreq = 0;
  
  if( x->c_fundamental <= 0){
	error("we're not yet fully initialized. Try turning on DACs first");
	return;
  }
  
  while( x->curfreq < x->hi_freq ) {
    ++(x->hi_bin);
    x->curfreq += x->c_fundamental ;
  }

  x->lo_bin = 0;  
  x->curfreq = 0;
  while( x->curfreq < x->lo_freq ) {
    ++(x->lo_bin);
    x->curfreq += x->c_fundamental ;
  }

  if( x->hi_bin > x->N2)
    x->hi_bin = x->N2 ;
  if(x->lo_bin > x->hi_bin)
	x->lo_bin = x->hi_bin;
//  post("hibin: %d lobin %d",x->hi_bin, x->lo_bin);
}


void presidency_overlap(t_presidency *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;
	presidency_init(x,1);
}

void presidency_winfac(t_presidency *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;
	presidency_init(x,2);
}

void presidency_fftinfo(t_presidency *x)
{
  if( ! x->overlap ){
    post("zero overlap!");
    return;
  }
  post("%s: FFT size %d, hopsize %d, winfac %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw);
}

void presidency_verbose(t_presidency *x, t_floatarg t)
{
  x->verbose = t;
}

void presidency_size(t_presidency *x, t_floatarg newsize)
{
//protect with DACs off?

  if(newsize > 0.0){//could be horrendous size, but that's the user's problem
  	x->duration = newsize/1000.0;
	presidency_init(x,1);  	
  }
}

void presidency_playthrough (t_presidency *x, t_floatarg tog)
{
  x->playthrough = tog;
}

void presidency_free(t_presidency *x){
  int i ;
#if MSP
  dsp_free((t_pxobject *)x);
#endif
  for(i = 0; i < x->framecount; i++){
    freebytes(x->loveboat[i],0) ;
  }
  freebytes(x->loveboat,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->output,0);
  freebytes(x->local_frame,0);
}



void presidency_init(t_presidency *x, short initialized)
{
	int i;
	long oldsize,newsize;
	int oldN = x->N;
	int oldN2 = x->N2;
	int oldNw = x->Nw;
	int last_framecount = x->framecount;
	x->lock = 1;
	x->virgin = 1;
	
	if(!power_of_two(x->winfac))
		x->winfac = 1;
	if(!power_of_two(x->overlap))
		x->overlap = 4;
	if(!x->R)
		x->R = 44100;
	if(!x->D){
		x->D = 256;
		x->vector_size = x->D;
	}
	x->N = x->D * x->overlap;
	x->Nw = x->N * x->winfac;
	limit_fftsize(&x->N, &x->Nw, OBJECT_NAME);
	
	x->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->inCount = -(x->Nw);
	x->mult = 1. / (float) x->N;
//	post("mult %f N %d",x->mult,x->N);
	x->current_frame = 0;
	x->fpos = x->last_fpos = 0;
	x->tadv = (float)x->D/(float)x->R;
	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;
	x->table_length = 8192;
	x->table_si = (float) x->table_length / (float) x->R;
	x->pitch_increment = 1.0 * x->table_si;
	
	if( x->duration <= 0 ){
		x->duration = 1.0;
	}
	
	x->framecount =  x->duration / x->tadv ;
	x->hopsize = (float)x->N / x->overlap;
	x->read_me = 0;
	
	if(!initialized){
		x->mute = 0;
		x->in2_connected = 0;
		x->in3_connected = 0;
		x->sync = 0;
		x->playthrough = 0;
		x->frame_increment = 1.0;
		x->verbose = 0;
		x->table = (float *) getbytes(x->table_length * sizeof(float));
		x->Wanal = (float *) getbytes(MAX_Nw*sizeof(float));	
		x->Wsyn = (float *) getbytes(MAX_Nw*sizeof(float));	
		x->input = (float *) getbytes(MAX_Nw*sizeof(float));	
		x->Hwin = (float *) getbytes(MAX_Nw*sizeof(float));
		x->bindex = (float *) getbytes( (MAX_N+1) * sizeof(float) );
		x->buffer = (float *) getbytes(MAX_N*sizeof(float));
		x->channel = (float *) getbytes((MAX_N+2)*sizeof(float));
		x->output = (float *) getbytes(MAX_Nw*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->lastamp = (float *) getbytes((MAX_N+1) * sizeof(float));
		x->lastfreq = (float *) getbytes((MAX_N+1) * sizeof(float));
		x->local_frame = (float *) getbytes((MAX_N+2)*sizeof(float));
		x->loveboat = (float **) getbytes(x->framecount*sizeof(float *));
		

		/* here we stay with old reallocation approach and pray */
		for(i=0;i<x->framecount;i++){
			x->loveboat[i] = (float *) getbytes(((x->N)+2)*sizeof(float));
			if(x->loveboat[i] == NULL){
				error("memory error");
				return;
			}
			memset((char *)x->loveboat[i],0,(x->N+2)*sizeof(float));
		}
	} else if(initialized == 1) {
		//free and allocate
		oldsize = (oldN+2)*sizeof(float);
		for(i = 0; i < last_framecount; i++){
			freebytes(x->loveboat[i],oldsize) ;
		}
		oldsize = last_framecount*sizeof(float *);
		freebytes(x->loveboat,oldsize);
		x->loveboat = (float **) getbytes(x->framecount*sizeof(float *));  
		for(i=0;i<x->framecount;i++){
			x->loveboat[i] = (float *) getbytes((x->N+2)*sizeof(float));
			if(x->loveboat[i] == NULL){
				error("memory error");
				return;
			}
			memset((char *)x->loveboat[i],0,(x->N+2)*sizeof(float));
		}
	}  
	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->lastamp,0,(x->N+1)*sizeof(float));
	memset((char *)x->lastfreq,0,(x->N+1)*sizeof(float));
	memset((char *)x->bindex,0,(x->N+1)*sizeof(float));
	memset((char *)x->buffer,0,x->N * sizeof(float));
	if(!x->vector_size){
		post("zero vector size - something is really screwed up here!");
		return;
	}
	for ( i = 0; i < x->table_length; i++ ) {
		x->table[i] = (float) x->N * cos((float)i * TWOPI / (float)x->table_length);
	}	
	x->c_fundamental =  (float) x->R/(float)x->N ;
	x->c_factor_in =  (float) x->R/((float)x->vector_size * TWOPI);
	
	if( x->hi_freq < x->c_fundamental ) {
		x->hi_freq = x->topfreq ;
	}
	x->hi_bin = 1;  
	x->curfreq = 0;
	while( x->curfreq < x->hi_freq ) {
		++(x->hi_bin);
		x->curfreq += x->c_fundamental ;
	}
	
	x->lo_bin = 0;  
	x->curfreq = 0;
	while( x->curfreq < x->lo_freq ) {
		++(x->lo_bin);
		x->curfreq += x->c_fundamental ;
	}
	
	if( x->hi_bin > x->N2)
		x->hi_bin = x->N2 ;
	if(x->lo_bin > x->hi_bin)
		x->lo_bin = x->hi_bin;
	
	x->i_vector_size = 1.0/x->vector_size;
	x->pitch_increment = x->P*x->table_length/x->R;
	
	makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D);
	init_rdft( x->N, x->bitshuffle, x->trigland);

		  
	x->lock = 0;
}

void *presidency_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
  t_presidency *x = (t_presidency *)newobject(presidency_class);
  dsp_setup((t_pxobject *)x,4);
  outlet_new((t_pxobject *)x, "signal");
  outlet_new((t_pxobject *)x, "signal");
#endif

#if PD
  t_presidency *x = (t_presidency *)pd_new(presidency_class);
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
#endif

  x->duration = atom_getfloatarg(0,argc,argv)/1000.0;
  x->lo_freq = atom_getfloatarg(1,argc,argv);
  x->hi_freq = atom_getfloatarg(2,argc,argv);
  x->overlap = atom_getfloatarg(3,argc,argv);
  x->winfac = atom_getfloatarg(4,argc,argv);

  x->D = sys_getblksize();
  x->R = sys_getsr();
  x->vector_size = x->D;

  x->topfreq = 3000.; // default top freq
  if(!x->lo_freq){
	x->lo_freq = 0;
  }
  if(!x->hi_freq)
	x->hi_freq = 4000.0;
	
  presidency_init(x,0);

  return (x);
}

t_int *presidency_perform(t_int *w)
{	
  int i, j;
  float sample;

  ////////////////////////////////////////////// 
  t_presidency *x = (t_presidency *) (w[1]);
  t_float *in = (t_float *)(w[2]);
  t_float *speed = (t_float *)(w[3]);
  t_float *position = (t_float *)(w[4]);
  t_float *pinc = (t_float *)(w[5]);
  t_float *out = (t_float *)(w[6]);
  t_float *sync_vec = (t_float *)(w[7]);
  t_int n = w[8];
	
  int inCount = x->inCount;
  int R = x->R;
  int N = x->N;
  int N2 = x->N2;
  int D = x->D;
  int vector_size = 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 *local_frame = x->local_frame;
  float fframe = x->current_frame ;
  float last_fpos = x->last_fpos ;
  int framecount = x->framecount;
  float fincr = x->frame_increment;
  float fpos = x->fpos;
  float pitch_increment = x->pitch_increment;
  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 table_si = x->table_si;
  int lo_bin = x->lo_bin;
  int hi_bin = x->hi_bin;
  float i_vector_size = x->i_vector_size;
  float synthesis_threshold = x->synthesis_threshold;
  float *lastfreq = x->lastfreq;
  float *lastamp = x->lastamp;
  float *bindex = x->bindex;
  float *table = x->table;
  int table_length = x->table_length;
  float sync = x->sync;


  if(x->lock || x->mute){
  	while(n--){
  	  *out++ = 0.0;
  	  *sync_vec++ = sync;
  	}
  	return (w+9);
  }
  
#if MSP
  if (x->in2_connected) {
    fincr = *speed; 
  } 
  if (x->in3_connected) {
    fpos = *position; 
  } 
  if (x->in4_connected) {
    pitch_increment = *pinc * table_si; 
  } 
#endif

#if PD
  fincr = *speed;
  fpos = *position;
  pitch_increment = *pinc * table_si;
#endif

  inCount += D;

  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] = *in++;
    }

    if( x->playthrough ){
      for ( j = N-D; j < N; j++ ) {
	    *out++ = input[j] * 0.5;
      }
    }
    else { 
      for ( j = 0; j < D; j++ ){
	    *out++ = 0.0;
      }
    }

    fold(input, Wanal, Nw, buffer, N, inCount);	
    rdft(N, 1, buffer, bitshuffle, trigland);
    sync = (float) x->frames_read / (float) framecount;
    if(x->frames_read >= framecount){
      sync = 1.0;
      x->read_me = 0;
      if(x->verbose){
      	post("presidency: data acquisition completed");
      }
    } else {
      convert(buffer, x->loveboat[(x->frames_read)++], N2, c_lastphase_in, c_fundamental, c_factor_in);
    }
    x->virgin = 0;
    for ( j = 0; j < D; j++ ){
	    *sync_vec++ = sync;
    }

  } 
  else if(x->playthrough && x->virgin){
      while(n--){
	  	 sample = *in++ * 0.5;
		   *out++ = sample;
		   *sync_vec++ = sync;
      }
  }
  /* synthesis section */
  else {
    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 ;
    }
	// copy stored frame to local for possible modifications
    for(i = 0; i < N; i++){
		local_frame[i] = x->loveboat[(int) fframe ][i];
	}

	for( i = lo_bin * 2 + 1; i < hi_bin * 2 + 1; i += 2 ){
	  local_frame[i] *= pitch_increment;
    }

  bloscbank(local_frame, output, D, i_vector_size, lastfreq, lastamp, 
  	bindex, table, table_length, synthesis_threshold, lo_bin, hi_bin);

    for ( j = 0; j < D; j++ ){
      *out++ = output[j] * mult;
      *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.;
    }
  }
	
  /* restore state variables */

  x->inCount = inCount % Nw;
  x->current_frame = fframe;
  x->frame_increment = fincr;
  x->fpos = fpos;
  x->last_fpos = last_fpos;
  x->pitch_increment = pitch_increment;
  x->sync = sync;
  return (w+9);
}		

#if MSP
void presidency_int(t_presidency *x, long i)
{
	presidency_float(x,(float)i);
}

void presidency_float(t_presidency *x, double f) // Look at floats at inlets
{
  int inlet = ((t_pxobject*)x)->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;
  } 
  else if( inlet == 3 ){
  	  x->pitch_increment = f * x->table_si;
  }
}
#endif

void presidency_acquire_sample(t_presidency *x)
{
  x->read_me = 1;
  x->frames_read = 0;
  if(x->verbose)
	post("%: beginning spectral data acquisition",OBJECT_NAME);
}

void presidency_bangname (t_presidency *x)
{
  x->read_me = 1;
  x->frames_read = 0;
  if(x->verbose)
  	post("%s: beginning spectral data acquisition",OBJECT_NAME);
}

void presidency_mute(t_presidency *x, t_floatarg tog)
{
  x->mute = (short)tog;	
}

void presidency_dsp(t_presidency *x, t_signal **sp, short *count)
{
#if MSP
  x->in2_connected = count[1];
  x->in3_connected = count[2];
  x->in4_connected = count[3];
#endif
		
  if(x->R != sp[0]->s_sr || x->D != sp[0]->s_n){
    x->R = sp[0]->s_sr;
    x->D = sp[0]->s_n;
  	x->vector_size = x->D;
    if(x->verbose)
      post("new vsize: %d, new SR:%d",x->D,x->R);
    presidency_init(x,1);
  }
  
  dsp_add(presidency_perform, 8, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec,  
	  sp[3]->s_vec, sp[4]->s_vec, sp[5]->s_vec, sp[0]->s_n);
}

void presidency_assist(t_presidency *x, void *b, long msg, long arg, char *dst)
{
  if (msg==1) {
    switch (arg) {
    case 0: sprintf(dst,"(signal) Input"); break;
    case 1: sprintf(dst,"(signal/float) Frame Increment"); break;
    case 2: sprintf(dst,"(signal/float) Frame Position [0-1]"); break;
	  case 3: sprintf(dst,"(signal/float) Transposition Factor"); break;
    }
  } else if (msg==2) {
    switch (arg) {
    case 0: sprintf(dst,"(signal) Output"); break;
    case 1: sprintf(dst,"(signal/float) Record Sync"); break;
    }
  }
}

--- NEW FILE: vacancy~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *vacancy_class;
#endif
#if PD
static t_class *vacancy_class;
#endif

#define OBJECT_NAME "vacancy~"

/*
Added inlet for compositing threshold, which is now
given linearly, not in dB (since Max can do that).

-EL 02.10.2005

*/
typedef struct _vacancy
{
#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;
    int invert;
    int useRms;
    int swapPhase;
    int *bitshuffle;
    
    float threshold;
    float *Wanal;	
    float *Wsyn;	
    float *inputOne;
    float *inputTwo;
    float *Hwin;
    float *bufferOne;
    float *bufferTwo;
    float *channelOne;
 	float *channelTwo;
    float *output;
    float mult; 
    float *trigland;
  short connected[8];
  short mute;
  int overlap;//overlap factor
  int winfac;//window factor
  int vs;//vector size  
    	
} t_vacancy;


/* msp function prototypes */

void *vacancy_new(t_symbol *s, int argc, t_atom *argv);
t_int *vacancy_perform(t_int *w);
void vacancy_dsp(t_vacancy *x, t_signal **sp, short *count);
void vacancy_assist(t_vacancy *x, void *b, long m, long a, char *s);
void vacancy_dest(t_vacancy *x, double f);

void vacancy_rms(t_vacancy *x, t_floatarg f);
void vacancy_invert(t_vacancy *x, t_floatarg f);
void vacancy_swapphase(t_vacancy *x, t_floatarg f);

void vacancy_free(t_vacancy *x);
void vacancy_mute(t_vacancy *x, t_floatarg toggle);
void vacancy_fftinfo(t_vacancy *x);
void vacancy_tilde_setup(void);
void vacancy_overlap(t_vacancy *x, t_floatarg o);
void vacancy_winfac(t_vacancy *x, t_floatarg o);
void vacancy_init(t_vacancy *x, short initialized);

#if MSP
void main(void)
{
    setup((t_messlist **)&vacancy_class, (method)vacancy_new, (method)vacancy_free, 
    (short) sizeof(t_vacancy), 0, A_GIMME, 0);
  
    addmess((method)vacancy_dsp, "dsp", A_CANT, 0);
    addmess((method)vacancy_assist,"assist",A_CANT,0);    
    addmess((method)vacancy_rms,"rms", A_FLOAT, 0);
    addmess((method)vacancy_invert,"invert", A_FLOAT, 0);
	addmess((method)vacancy_swapphase,"swapphase", A_FLOAT, 0);
	addmess((method)vacancy_mute,"mute", A_FLOAT, 0);
	addmess((method)vacancy_overlap,"overlap", A_FLOAT, 0);
	addmess((method)vacancy_winfac,"winfac", A_FLOAT, 0);
	addmess((method)vacancy_fftinfo,"fftinfo", 0);
	addfloat((method)vacancy_dest);
    dsp_initclass();
    post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}

void vacancy_dest(t_vacancy *x, double f)
{
int inlet = x->x_obj.z_in;

	if(inlet == 2)
		x->threshold = (float) f;
}
#endif

#if PD
void vacancy_tilde_setup(void)
{
  vacancy_class = class_new(gensym("vacancy~"), (t_newmethod)vacancy_new, 
			     (t_method)vacancy_free ,sizeof(t_vacancy), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(vacancy_class, t_vacancy, x_f);
  class_addmethod(vacancy_class, (t_method)vacancy_dsp, gensym("dsp"), 0);
  class_addmethod(vacancy_class, (t_method)vacancy_assist, gensym("assist"), 0);
  class_addmethod(vacancy_class, (t_method)vacancy_invert, gensym("invert"), A_FLOAT,0);
  class_addmethod(vacancy_class, (t_method)vacancy_swapphase, gensym("swapphase"), A_FLOAT,0);
  class_addmethod(vacancy_class, (t_method)vacancy_overlap, gensym("overlap"), A_FLOAT,0);
  class_addmethod(vacancy_class, (t_method)vacancy_winfac, gensym("winfac"), A_FLOAT,0);
  class_addmethod(vacancy_class, (t_method)vacancy_mute, gensym("mute"), A_FLOAT,0);
  class_addmethod(vacancy_class, (t_method)vacancy_fftinfo, gensym("fftinfo"), A_CANT,0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}

#endif


void vacancy_rms(t_vacancy *x, t_floatarg f)
{
	x->useRms = (int) f;
}

void vacancy_invert(t_vacancy *x, t_floatarg f)
{
	x->invert = (int) f;
}

void vacancy_swapphase(t_vacancy *x, t_floatarg f)
{
	x->swapPhase = (int) f;
}


void vacancy_assist (t_vacancy *x, void *b, long msg, long arg, char *dst)
{

  if (msg == 1) {

    switch (arg) {

    	case 0:		sprintf(dst,"(signal) Input One"); break;
    	case 1:		sprintf(dst,"(signal) Input Two"); break;
    	case 2:		sprintf(dst,"(signal) Mixing Threshold"); break;
    }
  }

  else {

    if (msg == 2)
      sprintf(dst,"(signal) Output");

  }
}

void vacancy_fftinfo( t_vacancy *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 vacancy_mute(t_vacancy *x, t_floatarg toggle)
{
  x->mute = (short)toggle;
}

void vacancy_overlap(t_vacancy *x, t_floatarg o)
{
  if(!power_of_two(o)){
    error("%f is not a power of two",o);
    return;
  }
  x->overlap = (int)o;
  vacancy_init(x,1);
}

void vacancy_winfac(t_vacancy *x, t_floatarg f)
{
  if(!power_of_two(f)){
    error("%f is not a power of two",f);
    return;
  }
  x->winfac = (int)f;
  vacancy_init(x,1);
}

void *vacancy_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
  t_vacancy 	*x = (t_vacancy *) newobject(vacancy_class);
  dsp_setup((t_pxobject *)x,3);
  outlet_new((t_pxobject *)x, "signal");
#endif

#if PD
  t_vacancy *x = (t_vacancy *)pd_new(vacancy_class);
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
#endif



/* optional arguments: overlap, window factor */

  x->overlap = atom_getfloatarg(0,argc,argv);
  x->winfac = atom_getfloatarg(1,argc,argv);

  if(!power_of_two(x->overlap)){
    x->overlap = 4;
  }
  if(!power_of_two(x->winfac)){
    x->winfac = 1;
  }
  		
  x->vs = sys_getblksize();
  x->R = sys_getsr();
 
  vacancy_init(x,0);

  return (x);
}

void vacancy_init(t_vacancy *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->N2 = (x->N)>>1;
  x->Nw2 = (x->Nw)>>1;
  x->inCount = -(x->Nw);
  x->mult = 1. / (float) x->N;
  if(!initialized){
    x->mute = 0;
    x->invert = 0;
    x->threshold = 0.;
    x->useRms = 1;
    x->swapPhase = 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->inputOne = (float *) getbytes( MAX_Nw * sizeof(float) );
	  x->inputTwo = (float *) getbytes( MAX_Nw * sizeof(float) );	
	  x->bufferOne = (float *) getbytes( MAX_N * sizeof(float) );
	  x->bufferTwo = (float *) getbytes( MAX_N * sizeof(float) ); 
	  x->channelOne = (float *) getbytes( (MAX_N+2)  * sizeof(float) );
	  x->channelTwo = (float *) getbytes( (MAX_N+2)  * sizeof(float) );
	  x->output = (float *) getbytes( MAX_Nw * sizeof(float) );
	  x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) );
	  x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) );
  }
	memset((char *)x->inputOne,0,x->Nw * sizeof(float));
	memset((char *)x->inputTwo,0,x->Nw * sizeof(float));
	memset((char *)x->output,0,x->Nw * sizeof(float));
	
  init_rdft( x->N, x->bitshuffle, x->trigland);
  makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0);
  
}

void vacancy_free(t_vacancy *x)
{
#if MSP
  dsp_free((t_pxobject *) x);
#endif
  freebytes(x->trigland,0);
  freebytes(x->bitshuffle,0);
  freebytes(x->Wanal,0);
  freebytes(x->Wsyn,0);
  freebytes(x->Hwin,0);
  freebytes(x->inputOne,0);
  freebytes(x->inputTwo,0);
  freebytes(x->bufferOne,0);
  freebytes(x->bufferTwo,0);
  freebytes(x->channelOne,0);
  freebytes(x->channelTwo,0);
  freebytes(x->output,0);
}

t_int *vacancy_perform(t_int *w)
{

  int	
			i,j,
			inCount,
			R,
			N,
			N2,
			D,
			Nw,
			invert = 0,
			useRms = 1,
			swapPhase = 0,
  			even, odd,
  	 		*bitshuffle;

  float		maxamp,	
  			threshold = .001,
			mult,
			useme,
			rms = 0.,
			a1, b1,
  			a2, b2,
  			*inputOne,
			*inputTwo,
			*bufferOne,
			*bufferTwo,
			*output,
			*Wanal,
			*Wsyn,
			*channelOne,
			*channelTwo,
			*trigland;



/* get our inlets and outlets */
	
  t_vacancy *x = (t_vacancy *) (w[1]);
  t_float *inOne = (t_float *)(w[2]);
  t_float *inTwo = (t_float *)(w[3]);
  t_float *vec_threshold = (t_float *)(w[4]);
  t_float *out = (t_float *)(w[5]);
  t_int n = (t_int)(w[6]);
	
  short *connected = x->connected;

  if(x->mute){
	while(n--)
		*out++ = 0.0;
	return w+7;
  }

/* dereference structure  */	

  inputOne = x->inputOne;
  inputTwo = x->inputTwo;
  bufferOne = x->bufferOne;
  bufferTwo = x->bufferTwo;
  inCount = x->inCount;
  R = x->R;
  N = x->N;
  N2 = x->N2;
  D = x->D;
  Nw = x->Nw;
  Wanal = x->Wanal;
  Wsyn = x->Wsyn;
  output = x->output;
  channelOne = x->channelOne;
  channelTwo = x->channelTwo;
  bitshuffle = x->bitshuffle;
  trigland = x->trigland;
  mult = x->mult;
  invert = x->invert;
  useRms = x->useRms;
  swapPhase = x->swapPhase;
  
  threshold = connected[2] ? *vec_threshold : x->threshold;
  
 /*
  a bug?? Threshold could be -90 to 90 (dB)
  
  if ( x->threshold > 0. )
  	threshold = x->threshold;
  */
  
  
/* fill our retaining buffers */

  inCount += D;

  for ( j = 0 ; j < Nw - D ; j++ ) {
    inputOne[j] = inputOne[j+D];
    inputTwo[j] = inputTwo[j+D];
  }

  for ( j = Nw - D; j < Nw; j++ ) {
    inputOne[j] = *inOne++;
    inputTwo[j] = *inTwo++;
  }

  if (useRms) {

    rms = 0.;

	for ( i=0; i < Nw; i++ )
	  rms += *(inputOne+i) * *(inputOne+i);

	rms = sqrt( rms / Nw );

	useme = rms * threshold;
  }
  
  else
  	useme = threshold;


/* apply hamming window and fold our window buffer into the fft buffer */ 

  fold( inputOne, Wanal, Nw, bufferOne, N, inCount );
  fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount );


/* do an fft */ 

  rdft( N, 1, bufferOne, bitshuffle, trigland );
  rdft( N, 1, bufferTwo, bitshuffle, trigland );

/* use slow fft */

//  rfft( bufferOne, N2, FORWARD );
//  rfft( bufferTwo, N2, FORWARD );


/* convert to polar coordinates from complex values */
 
  for ( i = 0; i <= N2; i++ ) {
    
      odd = ( even = i<<1 ) + 1;

      a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) );
      b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) );
    
      a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) );
      b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) );

      *(channelOne+even) = hypot( a1, b1 );
      *(channelOne+odd) = -atan2( b1, a1 );
    
      *(channelTwo+even) = hypot( a2, b2 );
      *(channelTwo+odd) = -atan2( b2, a2 ); 
  }
  
  
  /* composite here please */

  if (invert) {

    if (swapPhase) {

      for ( i=0; i < N2; i+=2 ) {
		if ( *(channelOne+i) > useme && *(channelTwo+i) < *(channelOne+i) ) {
		  *(channelOne+i) = *(channelTwo+i);
		  *(channelOne+i+1) = *(channelTwo+i+1);
		}
      }
    }

    else {

      for ( i=0; i < N2; i+=2 ) {
		if ( *(channelOne+i) > useme && *(channelTwo+i) < *(channelOne+i) ) {
		  *(channelOne+i) = *(channelTwo+i);
		  
		  if ( *(channelOne+i+1) == 0. )
		    *(channelOne+i+1) = *(channelTwo+i+1);
		}
      }
    }
  }

  else {

    if (swapPhase) {

      for ( i=0; i < N2; i+=2 ) {
		if ( *(channelOne+i) < useme && *(channelTwo+i) > *(channelOne+i) ) {
		  *(channelOne+i) = *(channelTwo+i);
		  *(channelOne+i+1) = *(channelTwo+i+1);
		}
      }
    }

    else {

      for ( i=0; i < N2; i+=2 ) {

		if ( *(channelOne+i) < useme && *(channelTwo+i) > *(channelOne+i) ) {
		  *(channelOne+i) = *(channelTwo+i);
		  
		  if ( *(channelOne+i+1) == 0. )
		    *(channelOne+i+1) = *(channelTwo+i+1);
		}
      }
    }
  }
  

/* convert back to complex form, read for the inverse fft */

  for ( i = 0; i <= N2; i++ ) {

    odd = ( even = i<<1 ) + 1;

    *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) );

    if ( i != N2 )
      *(bufferOne+odd) = -(*(channelOne+even)) * sin( *(channelOne+odd) );
  }


/* do an inverse fft */

  rdft( N, -1, bufferOne, bitshuffle, trigland );

/* dewindow our result */

  overlapadd( bufferOne, N, Wsyn, output, Nw, inCount);

/* set our output and adjust our retaining output buffer */

  for ( j = 0; j < D; j++ )
    *out++ = output[j] * mult;
	
  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
  
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;
		

/* restore state variables */

  x->inCount = inCount % Nw;
  return (w+7);
}		





void vacancy_dsp(t_vacancy *x, t_signal **sp, short *count)
{
long i;

#if MSP
  for( i = 0; i < 3; i++ ){
    x->connected[i] = count[i];
  }
#endif
  /* signal is always connected in Pd */
#if PD 
  for( i = 0; i < 3; i++ ){
    x->connected[i] = 1;
  }
#endif

  /* reinitialize if vector size or sampling rate has been changed */
  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;
    vacancy_init(x,1);
  }	

	dsp_add(vacancy_perform, 6, x,
		sp[0]->s_vec,
		sp[1]->s_vec,
		sp[2]->s_vec,
		sp[3]->s_vec,
		sp[0]->s_n);
}


--- NEW FILE: shapee~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *shapee_class;
#endif 

#if PD
static t_class *shapee_class;
#endif

#define OBJECT_NAME "shapee~"

typedef struct _shapee
{
#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;
    int widthConnected;
    int *bitshuffle;
    
    float shapeWidth;
    float *Wanal;	
    float *Wsyn;	
    float *inputOne;
    float *inputTwo;
    float *Hwin;
    float *bufferOne;
    float *bufferTwo;
    float *channelOne;
    float *channelTwo;
    float *output;
    float mult; 
    float *trigland;
  int overlap;//overlap factor
  int winfac;// window factor
  int vs;//last measurement of vector size
  short mute;   	
} t_shapee;


/* msp function prototypes */

void *shapee_new(t_symbol *s, int argc, t_atom *argv);
t_int *shapee_perform(t_int *w);
void shapee_dsp(t_shapee *x, t_signal **sp, short *count);
void shapee_float(t_shapee *x, double myFloat);
void shapee_assist(t_shapee *x, void *b, long m, long a, char *s);
void shapee_init(t_shapee *x, short initialized);
void shapee_mute(t_shapee *x, t_floatarg state);
void shapee_free(t_shapee *x);
void shapee_overlap(t_shapee *x, t_floatarg o);
void shapee_winfac(t_shapee *x, t_floatarg wf);
void shapee_fftinfo(t_shapee *x);

/* first calling */

/* float input handling routine for shape width */
#if MSP
void shapee_float( t_shapee *x, double myFloat )
{

	if ( x->x_obj.z_in == 2 ) {

		if ( myFloat >= 1. && myFloat <= (double) x->N )
			x->shapeWidth = (float)myFloat;
	}	
}

void main(void)
{
    setup( (t_messlist **) &shapee_class, (method) shapee_new,
    		(method) shapee_free, (short) sizeof(t_shapee), 0, A_GIMME, 0);
    		
    addmess((method)shapee_dsp, "dsp", A_CANT, 0);
    addmess((method)shapee_assist,"assist",A_CANT,0);
    addfloat((method)shapee_float);	
    addmess((method)shapee_mute,"mute",A_FLOAT,0);
	addmess((method)shapee_overlap,"overlap",A_FLOAT,0);
	addmess((method)shapee_winfac,"winfac",A_FLOAT,0);
	addmess((method)shapee_fftinfo,"fftinfo",0);
    dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
  }
#endif

#if PD
void shapee_tilde_setup(void)
{
  shapee_class = class_new(gensym("shapee~"), (t_newmethod)shapee_new, 
			 (t_method)shapee_free ,sizeof(t_shapee), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(shapee_class, t_shapee, x_f);
  class_addmethod(shapee_class, (t_method)shapee_dsp, gensym("dsp"), 0);
  class_addmethod(shapee_class, (t_method)shapee_mute, gensym("mute"), A_DEFFLOAT,0);
  class_addmethod(shapee_class, (t_method)shapee_overlap, gensym("overlap"), A_DEFFLOAT,0);
  class_addmethod(shapee_class, (t_method)shapee_winfac, gensym("winfac"), A_DEFFLOAT,0);
  class_addmethod(shapee_class, (t_method)shapee_fftinfo, gensym("fftinfo"),0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif



/* diagnostic messages for Max */

void shapee_assist (t_shapee *x, void *b, long msg, long arg, char *dst)
{

  if (msg == 1) {
    switch (arg) {
    	case 0:		sprintf(dst,"(signal) Frequency Reference");break;
    	case 1:		sprintf(dst,"(signal) Amplitude Reference");break;
	  	case 2:		sprintf(dst,"(signal/float) Shape Width"); break;		
    }
  }

  else {

    if (msg == 2)
      sprintf(dst,"(signal) Output");
  }
}


void *shapee_new(t_symbol *s, int argc, t_atom *argv)
{
			
#if MSP
  t_shapee 	*x = (t_shapee *) newobject(shapee_class);
  dsp_setup((t_pxobject *)x, 3);
  outlet_new((t_pxobject *)x, "signal");
#endif
#if PD
  t_shapee *x = (t_shapee *)pd_new(shapee_class);
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
  outlet_new(&x->x_obj, gensym("signal"));
#endif

/* INITIALIZATIONS */
  x->overlap = atom_getfloatarg(0,argc,argv);
  x->winfac = atom_getfloatarg(1,argc,argv);
  if(!x->winfac)	
	x->winfac = 1;
  if(!x->overlap)
	x->overlap = 4;
  x->vs = sys_getblksize();
  x->R = sys_getsr();
  shapee_init(x,0); 

  return (x);
}

void shapee_init(t_shapee *x, short initialized)
{
  int i;
  x->D = x->vs;
  x->N = x->vs * x->overlap;
  x->Nw = x->N * x->winfac;
  limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
  x->N2 = (x->N)>>1;
  x->Nw2 = (x->Nw)>>1;
  x->inCount = -(x->Nw);
  x->mult = 1. / (float) x->N;
  
	if(!initialized){
	  x->mute = 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->inputOne = (float *) getbytes( MAX_Nw * sizeof(float) );
	  x->inputTwo = (float *) getbytes( MAX_Nw * sizeof(float) );	
	  x->bufferOne = (float *) getbytes( MAX_N  * sizeof(float) );
	  x->bufferTwo = (float *) getbytes( MAX_N  * sizeof(float) ); 
	  x->channelOne = (float *) getbytes(  (MAX_N+2) * sizeof(float) );
	  x->channelTwo = (float *) getbytes(  (MAX_N+2) * sizeof(float) );
	  x->output = (float *) getbytes( MAX_Nw * sizeof(float) );
	  x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) );
	  x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) );
	}
	memset((char *)x->inputOne,0,x->Nw * sizeof(float));
	memset((char *)x->inputTwo,0,x->Nw * sizeof(float));
	memset((char *)x->output,0,x->Nw * sizeof(float));

  init_rdft(x->N, x->bitshuffle, x->trigland);
  makehanning(x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 1);// wants an ODD window
}

void shapee_fftinfo(t_shapee *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 shapee_mute(t_shapee *x, t_floatarg state)
{
	x->mute = (short)state;
}

void shapee_overlap(t_shapee *x, t_floatarg o)
{
int test = (int) o;
	if(!power_of_two(test)){
		post("%d is not a power of two",test);
		return;
	}
	x->overlap = test;
	shapee_init(x,1);
}

void shapee_winfac(t_shapee *x, t_floatarg wf)
{
int test = (int) wf;
if(!power_of_two(test)){
		post("%d is not a power of two",test);
		return;
}
x->winfac = test;
shapee_init(x,1);

}

t_int *shapee_perform(t_int *w)
{

  int		n,
			i,j,
			inCount,
			R,
			N,
			N2,
			D,
			Nw,
			invert = 1,
  			shapeWidth,
  			remainingWidth,
  			even, odd,
  	 		*bitshuffle;

  float		maxamp,	
  			threshMult = 1.,
			mult,
			a1, b1,
  			a2, b2,
  			*inputOne,
			*inputTwo,
			*bufferOne,
			*bufferTwo,
			*output,
			*Wanal,
			*Wsyn,
			*channelOne,
			*channelTwo,
			*trigland;

  t_float 	*inOne,
  			*inTwo,	
			*inShape,
			*out;


/* get our inlets and outlets */
	
  t_shapee *x = (t_shapee *) (w[1]);
  inOne = (t_float *) (w[2]);
  inTwo = (t_float *) (w[3]);
  inShape = (t_float *) (w[4]);
  out = (t_float *)(w[5]);
  n = (t_int) (w[6]);

/* get our shapeWidth -- from either a signal our float input */
#if MSP
  shapeWidth = x->widthConnected ? (int) *inShape : (int) x->shapeWidth;
#endif
#if PD
  shapeWidth = (int) *inShape;
#endif	

/* dereference structure  */	
if(x->mute){
	while(n--) *out++ = 0.0;
	return w+7;
}

  inputOne = x->inputOne;
  inputTwo = x->inputTwo;
  bufferOne = x->bufferOne;
  bufferTwo = x->bufferTwo;
  inCount = x->inCount;
  R = x->R;
  N = x->N;
  N2 = x->N2;
  D = x->D;
  Nw = x->Nw;
  Wanal = x->Wanal;
  Wsyn = x->Wsyn;
  output = x->output;
  channelOne = x->channelOne;
  channelTwo = x->channelTwo;
  bitshuffle = x->bitshuffle;
  trigland = x->trigland;
  mult = x->mult;	
  
    

  if(shapeWidth < 1 || shapeWidth > N2)
	shapeWidth = 1;
	
  inCount += D;

  for ( j = 0 ; j < Nw - D ; j++ ) {
    inputOne[j] = inputOne[j+D];
    inputTwo[j] = inputTwo[j+D];
  }

  for ( j = Nw - D; j < Nw; j++ ) {
    inputOne[j] = *inOne++;
    inputTwo[j] = *inTwo++;
  }

/* apply hamming window and fold our window buffer into the fft buffer */ 

  fold( inputOne, Wanal, Nw, bufferOne, N, inCount );
  fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount );

/* do an fft */ 

  rdft( N, 1, bufferOne, bitshuffle, trigland );
  rdft( N, 1, bufferTwo, bitshuffle, trigland );

/* convert to polar coordinates from complex values */ 

  for ( i = 0; i <= N2; i++ ) {
      odd = ( even = i<<1 ) + 1;

      a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) );
      b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) );
    
      a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) );
      b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) );

/* replace signal one's phases with those of signal two */

      *(channelOne+even) = hypot( a1, b1 );
      *(channelOne+odd) = -atan2( b1, a1 );
    
      *(channelTwo+even) = hypot( a2, b2 );
      *(channelTwo+odd) = -atan2( b2, a2 );       
  }

/* constrain our shapeWidth value */

  if ( shapeWidth > N2 )
  	shapeWidth = N2;
  	
  if ( shapeWidth < 1 )
  	shapeWidth = 1;


/* lets just shape the entire signal by the shape width */

  for ( i=0; i < N; i += shapeWidth << 1 ) {
	  
	float       amplSum = 0.,
    		    freqSum = 0.,
          		factor;

	for ( j = 0; j < shapeWidth << 1; j += 2 ) {

  		amplSum += *(channelTwo+i+j);
  		freqSum += *(channelOne+i+j);
	}
		if(freqSum <= 0.001){
			freqSum = 1.0;
		}
	if (amplSum < 0.000000001)
		factor = 0.000000001;	
		
	else	
		factor = amplSum / freqSum;

	for ( j = 0; j < shapeWidth * 2; j += 2 )
  		*(channelOne+i+j) *= factor;
  }

/* copy remaining magnitudes */

  if ( (remainingWidth = N2 % shapeWidth) ) {

		int			bindex = (N2 - remainingWidth) << 1;


		float       amplSum = 0.,
	    		    freqSum = 0.,
	          		factor;

		for ( j = 0; j < remainingWidth * 2; j += 2 ) {

	  		amplSum += *(channelTwo+bindex+j);
	  		freqSum += *(channelOne+bindex+j);
		}
		if(freqSum <= 0.00001){
			freqSum = 1.0;
		}
		if (amplSum < 0.000000001)
			factor = 0.000000001;	
			
		else	
			factor = amplSum / freqSum;

		for ( j = 0; j < remainingWidth * 2; j += 2 )
	  		*(channelOne+bindex+j) *= factor;
		}
		

/* convert from polar to cartesian */	

  for ( i = 0; i <= N2; i++ ) {

    odd = ( even = i<<1 ) + 1;
      
    *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) );

    if ( i != N2 )
      *(bufferOne+odd) = (*(channelOne+even)) * -sin( *(channelOne+odd) );
  }


/* do an inverse fft */

  rdft( N, -1, bufferOne, bitshuffle, trigland );

/* dewindow our result */

  overlapadd( bufferOne, N, Wsyn, output, Nw, inCount);

/* set our output and adjust our retaining output buffer */

  for ( j = 0; j < D; j++ )
    *out++ = output[j] * mult;
	
  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
  
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;
		

/* restore state variables */

  x->inCount = inCount % Nw;
  return (w+7);
}		
void shapee_free( t_shapee *x )
{
#if MSP
  dsp_free( (t_pxobject *) x);
#endif
  freebytes(x->trigland,0);
  freebytes(x->bitshuffle,0);
  freebytes(x->Wanal,0);
  freebytes(x->Wsyn,0);
  freebytes(x->Hwin,0);
  freebytes(x->inputOne,0);
  freebytes(x->inputTwo,0);
  freebytes(x->bufferOne,0);
  freebytes(x->bufferTwo,0);
  freebytes(x->channelOne,0);
  freebytes(x->channelTwo,0);
  freebytes(x->output,0);
}

void shapee_dsp(t_shapee *x, t_signal **sp, short *count)
{
#if MSP	
	x->widthConnected = count[2];
#endif
	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;
		shapee_init(x,1);
	}
	dsp_add(shapee_perform, 6, x,
		sp[0]->s_vec,
		sp[1]->s_vec,
		sp[2]->s_vec,
		sp[3]->s_vec,
		sp[0]->s_n);
}


--- NEW FILE: pvcompand~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *pvcompand_class;
#endif 

#if PD
static t_class *pvcompand_class;
#endif

#define OBJECT_NAME "pvcompand~"

#define MAX_N (16384)
#define MAX_Nw (MAX_N * 4)

typedef struct _pvcompand
{
#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 mult; 
  float *trigland;
  int *bitshuffle;
  //
  float *curthresh ;
  float *atten;
  float *thresh ;
  int count;
  float thresh_interval;
  float max_atten; 
  float  atten_interval ; 
  float tstep;
  float gstep;
  float last_max_atten;
  short norml;
  short mute;
  short bypass;
  short connected[2];
  int overlap;
  int winfac;
} t_pvcompand;

void *pvcompand_new(t_symbol *s, int argc, t_atom *argv);
t_int *offset_perform(t_int *w);
t_int *pvcompand_perform(t_int *w);
void pvcompand_dsp(t_pvcompand *x, t_signal **sp, short *count);
void pvcompand_assist(t_pvcompand *x, void *b, long m, long a, char *s);
void update_thresholds(t_pvcompand *x);
void pvcompand_normalize(t_pvcompand *x, t_floatarg val);
void pvcompand_float(t_pvcompand *x, double f);
void pvcompand_free(t_pvcompand *x);
float pvcompand_ampdb(float db);
void pvcompand_init(t_pvcompand *x,short initialized);
void pvcompand_fftinfo(t_pvcompand *x);
void pvcompand_overlap(t_pvcompand *x, t_floatarg f);
void pvcompand_winfac(t_pvcompand *x, t_floatarg f);
void pvcompand_bypass(t_pvcompand *x, t_floatarg f);
void pvcompand_mute(t_pvcompand *x, t_floatarg f);

#if MSP
void main(void)
{
  setup((t_messlist **)&pvcompand_class, (method)pvcompand_new, 
  (method)pvcompand_free, (short)sizeof(t_pvcompand), 0, A_GIMME, 0);
  addmess((method)pvcompand_dsp, "dsp", A_CANT, 0);
  addmess((method)pvcompand_normalize, "normalize", A_LONG, 0);
  addmess((method)pvcompand_winfac,"winfac", A_FLOAT, 0);
  addmess((method)pvcompand_overlap,"overlap", A_FLOAT, 0);
  addmess((method)pvcompand_fftinfo,"fftinfo", 0);
  addmess((method)pvcompand_bypass,"bypass", A_FLOAT, 0);
  addmess((method)pvcompand_mute,"mute", A_FLOAT, 0);
  addmess((method)pvcompand_assist,"assist",A_CANT,0);
  addfloat((method)pvcompand_float);
  dsp_initclass();
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
void pvcompand_tilde_setup(void)
{
  pvcompand_class = class_new(gensym("pvcompand~"), (t_newmethod)pvcompand_new, 
			 (t_method)pvcompand_free ,sizeof(t_pvcompand), 0,A_GIMME,0);
  CLASS_MAINSIGNALIN(pvcompand_class, t_pvcompand, x_f);
  class_addmethod(pvcompand_class,(t_method)pvcompand_dsp,gensym("dsp"),0);
  class_addmethod(pvcompand_class,(t_method)pvcompand_mute,gensym("mute"),A_FLOAT,0);
  class_addmethod(pvcompand_class,(t_method)pvcompand_bypass,gensym("bypass"),A_FLOAT,0);
  class_addmethod(pvcompand_class,(t_method)pvcompand_overlap,gensym("overlap"),A_FLOAT,0);
  class_addmethod(pvcompand_class,(t_method)pvcompand_winfac,gensym("winfac"),A_FLOAT,0);
  class_addmethod(pvcompand_class,(t_method)pvcompand_fftinfo,gensym("fftinfo"),0);
  class_addmethod(pvcompand_class,(t_method)pvcompand_normalize,gensym("normalize"),A_FLOAT,0);
  post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}

#endif

void pvcompand_bypass(t_pvcompand *x, t_floatarg f)
{
	x->bypass = (short)f;
}

void pvcompand_mute(t_pvcompand *x, t_floatarg f)
{
	x->mute = (short)f;
}


void pvcompand_free( t_pvcompand *x ){
#if MSP
	dsp_free( (t_pxobject *) x);
#endif
	freebytes(x->curthresh,0);
	freebytes(x->atten,0);
	freebytes(x->thresh,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->output,0);
}

void pvcompand_assist (t_pvcompand *x, void *b, long msg, long arg, char *dst)
{
  if (msg==1) {
    switch (arg) {
    case 0:
      sprintf(dst,"(signal) Input");
      break;
    case 1:
      sprintf(dst,"(float/signal) Threshold");
      break;

    }
  } else if (msg==2) {
    sprintf(dst,"(signal) Output");
  }
}

#if MSP
void pvcompand_float(t_pvcompand *x, double f) // Look at floats at inlets
{
int inlet = x->x_obj.z_in;
	
    if (inlet == 1)
	{
		x->last_max_atten = x->max_atten = f;
		update_thresholds(x);	
		
	}
}
#endif
  
void *pvcompand_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
  t_pvcompand *x = (t_pvcompand *)newobject(pvcompand_class);
  dsp_setup((t_pxobject *)x,2);
  outlet_new((t_pxobject *)x, "signal");
#endif

#if PD
    t_pvcompand *x = (t_pvcompand *)pd_new(pvcompand_class);
    inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
    outlet_new(&x->x_obj, gensym("signal"));
#endif

  // INITIALIZATIONS
  x->D  = sys_getblksize();
  x->R = sys_getsr();
  x->max_atten = atom_getfloatarg(0,argc,argv);
  x->overlap = atom_getfloatarg(1,argc,argv);
  x->winfac = atom_getfloatarg(2,argc,argv);
  if(!x->max_atten)
  	x->max_atten = -6;

  if(x->D <= 0)
  	x->D = 256;
  if(x->R <= 0)
  	x->R = 44100;

   pvcompand_init(x,0);
  return (x);
}

void pvcompand_init(t_pvcompand *x,short initialized)
{
int i;

  if(!power_of_two(x->overlap))
  	x->overlap = 4;
  if(!power_of_two(x->winfac))
  	x->winfac = 1;
  	
  x->N = x->D * x->overlap;
  x->Nw = x->N * x->winfac;	
  limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
  x->N2 = (x->N)>>1;
  x->Nw2 = (x->Nw)>>1;
  x->inCount = -(x->Nw);
  x->mult = 1. / (float) x->N;

	if(!initialized){
	  x->norml = 0;
	  x->mute = 0;
	  x->bypass = 0;
	  x->thresh_interval = 1.0;
	  x->last_max_atten =  x->max_atten; 
	  x->atten_interval = 2.0 ; 
	  x->tstep = 1.0 ;
	  x->gstep = 2.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->buffer = (float *) getbytes(MAX_N * sizeof(float) );
    x->channel = (float *) getbytes( (MAX_N+2) * sizeof(float) );
    x->output = (float *) getbytes(MAX_N * sizeof(float) );
    x->bitshuffle = (int *) getbytes(MAX_N * 2 * sizeof( int ) );
    x->trigland = (float *) getbytes(MAX_N * 2 * sizeof( float ) );
    x->thresh = (float *) getbytes(MAX_N * sizeof(float) );
	  x->atten = (float *) getbytes(MAX_N * sizeof(float) );
	  x->curthresh = (float *) getbytes(MAX_N * sizeof(float) );
	} 
		
		memset((char *)x->input,0,x->Nw * sizeof(float));
		memset((char *)x->output,0,x->Nw * sizeof(float));

	  init_rdft( x->N, x->bitshuffle, x->trigland);
	  makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D);
	  update_thresholds(x); 

}

void update_thresholds( t_pvcompand *x ) {
  int i;

  float nowamp = x->max_atten ;
  float nowthresh = 0.0 ;

  x->count = 0;
  if( nowamp < 0.0 ) 
    while( nowamp < 0.0 ){
      x->atten[x->count] = pvcompand_ampdb( nowamp );
      nowamp += x->gstep ;
      ++(x->count);
 	if(x->count >= x->N){
		error("count exceeds %d",x->N);
		x->count = x->N - 1;
		break;
	}
    }
  else if( nowamp > 0.0 ) 
    while( nowamp > 0.0 ){
      x->atten[x->count] = pvcompand_ampdb( nowamp );
      nowamp -= x->gstep ;
      ++(x->count);
 	if(x->count >= x->N){
		error("count exceeds %d",x->N);
		x->count = x->N - 1;
		break;
	}
    }

  for( i = 0; i < x->count; i++){
    x->thresh[i] = pvcompand_ampdb( nowthresh );
    nowthresh -= x->tstep ;
  }
  /*   
       for( i = 0; i < count; i++)
       fprintf(stderr,"thresh %f gain %f\n",thresh[i], atten[i]);
  */
}

void pvcompand_normalize(t_pvcompand *x, t_floatarg val) 
{
  x->norml = val;
}

t_int *pvcompand_perform(t_int *w)
{
  float sample, outsamp ;	
  int i,j;	
  float maxamp ;	
  float fmult;
  float cutoff;
  float avr, new_avr, rescale;

  t_pvcompand *x = (t_pvcompand *) (w[1]);
  t_float *in = (t_float *)(w[2]);
  t_float *in2 = (t_float *)(w[3]);
  t_float *out = (t_float *)(w[4]);
  int n = (int)(w[5]);

  int  inCount = x->inCount;
  float *Wanal = x->Wanal;
  float *Wsyn = x->Wsyn;
  float *input = x->input;
  float *Hwin = x->Hwin;
  float *buffer = x->buffer;
  float *channel = x->channel;
  float *output = x->output;
  	
  int D = x->D;
  int I = D;
  int R = x->R;
  int Nw = x->Nw;
  int N = x->N ;
  int N2 = x-> N2;
  int Nw2 = x->Nw2;
  int *bitshuffle = x->bitshuffle;
  float *trigland = x->trigland;
  float mult = x->mult;
  int count = x->count;
  float *atten = x->atten;
  float *curthresh = x->curthresh;
  float *thresh = x->thresh;
  float max_atten = x->max_atten;		

if( x->mute ){
	while( n-- ){
		*out++ = 0.0;
	}
	return (w+6); 
}
if( x->bypass ){
	while( n-- ){
		*out++ = *in++ * 0.5; // gain compensation
	}
	return (w+6); 
}

#if MSP
  if( x->connected[1] ){
	  max_atten = *in2++ ;
	  if(max_atten != x->last_max_atten) {
	    x->last_max_atten = x->max_atten = max_atten;
	    update_thresholds(x);
	  }
  } 
#endif

#if PD
  max_atten = *in2++ ;
  if(max_atten != x->last_max_atten) {
    x->last_max_atten = x->max_atten = max_atten;
    update_thresholds(x);
  }
#endif

  inCount += D;

  for ( j = 0 ; j < Nw - D ; j++ ){
    input[j] = input[j+D];
  }
  for ( j = Nw - D; j < Nw; j++ ) {
    input[j] = *in++;
  }

  fold( input, Wanal, Nw, buffer, N, inCount );	
  rdft( N, 1, buffer, bitshuffle, trigland );

  leanconvert(buffer, channel, N2);

  maxamp = 0.;
  avr = 0;
  for( i = 0; i < N; i+= 2 ){
    avr += channel[i];
    if( maxamp < channel[i] ){
      maxamp = channel[i] ;
    }
  }
   if(count <= 1){
	//	post("count too low!"); 
		count = 1;
	}
  for( i = 0; i < count; i++ ){
    curthresh[i] = thresh[i]*maxamp ;
  }
  cutoff = curthresh[count-1];
  new_avr = 0;
  for( i = 0; i < N; i += 2){
    if( channel[i] > cutoff ){
      j = count-1;
      while( channel[i] > curthresh[j] ){
				j--;
				if( j < 0 ){
				  j = 0;
				  break;
				}
      }
      channel[i] *= atten[j];
    }
    new_avr += channel[i] ;
  }

  leanunconvert( channel,buffer, N2);

  rdft( N, -1, buffer, bitshuffle, trigland );

  overlapadd( buffer, N, Wsyn, output, Nw, inCount);
  if( x->norml ) {
    if( new_avr <= 0 ){
      new_avr = .0001;
    }
    rescale =  avr / new_avr ;
    mult *= rescale ;

  } else {
    mult *= pvcompand_ampdb( max_atten * -.5); ;
  }

  for ( j = 0; j < D; j++ ){
    *out++ = output[j] * mult;

  }
  for ( j = 0; j < Nw - D; j++ )
    output[j] = output[j+D];
			
  for ( j = Nw - D; j < Nw; j++ )
    output[j] = 0.;

	

  /* restore state variables */
  x->inCount = inCount % Nw;
  return (w+6);
}	
	
float pvcompand_ampdb(float db) 
{
  float amp;
  amp = pow((double)10.0, (double)(db/20.0)) ;
  return(amp);
}

void pvcompand_overlap(t_pvcompand *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;
	pvcompand_init(x,1);
}

void pvcompand_winfac(t_pvcompand *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;
	pvcompand_init(x,2);
}

void pvcompand_fftinfo(t_pvcompand *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 pvcompand_dsp(t_pvcompand *x, t_signal **sp, short *count)
{
  long i;

#if MSP
  x->connected[1] = count[1];
#endif

  if(x->D != sp[0]->s_n || x->R != sp[0]->s_sr ){
  	x->D = sp[0]->s_n;
  	x->R = sp[0]->s_sr;
    pvcompand_init(x,1);
  }
  
  dsp_add(pvcompand_perform, 5,x,sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
}


--- NEW FILE: pvtuner~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *pvtuner_class;
#endif 

#if PD
static t_class *pvtuner_class;
#endif

#define OBJECT_NAME "pvtuner~"

#define MAXTONES (1024)
#define BASE_FREQ (27.5)	/* low A  */
#define DIATONIC 0
#define EASTERN 1
#define MINOR 2
#define EQ12 3
[...1193 lines suppressed...]
	class_addmethod(pvtuner_class, (t_method)pvtuner_minor_seventh_chord,gensym("minor_seventh_chord"),0);
	class_addmethod(pvtuner_class, (t_method)pvtuner_dominant_seventh_chord,gensym("dominant_seventh_chord"),0);
	class_addmethod(pvtuner_class, (t_method)pvtuner_eq8,gensym("eq8"),0);               
	class_addmethod(pvtuner_class, (t_method)pvtuner_pentaclust,gensym("pentaclust"),0);
	class_addmethod(pvtuner_class, (t_method)pvtuner_quarterclust,gensym("quarterclust"),0);   
	class_addmethod(pvtuner_class, (t_method)pvtuner_eq5,gensym("eq5"),0); 
	class_addmethod(pvtuner_class, (t_method)pvtuner_slendro,gensym("slendro"),0);
	class_addmethod(pvtuner_class, (t_method)pvtuner_pelog,gensym("pelog"),0);       
	class_addmethod(pvtuner_class, (t_method)pvtuner_import_scale,gensym("import_scale"),A_DEFSYM,0);
	class_addmethod(pvtuner_class, (t_method)pvtuner_toptune,gensym("toptune"),A_FLOAT, 0);
	class_addmethod(pvtuner_class, (t_method)pvtuner_topfreq,gensym("topfreq"),A_FLOAT, 0);
	class_addmethod(pvtuner_class, (t_method)pvtuner_list,gensym("list"),A_GIMME, 0);
	class_addmethod(pvtuner_class, (t_method)pvtuner_frequency_range,gensym("frequency_range"),A_FLOAT,A_FLOAT, 0);
	class_addmethod(pvtuner_class, (t_method)pvtuner_overlap,gensym("overlap"),A_FLOAT, 0);
	class_addmethod(pvtuner_class, (t_method)pvtuner_winfac,gensym("winfac"),A_FLOAT, 0);
	class_addmethod(pvtuner_class, (t_method)pvtuner_fftinfo,gensym("fftinfo"), 0);
	class_addmethod(pvtuner_class, (t_method)pvtuner_binfo,gensym("binfo"), 0);
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

--- NEW FILE: residency~.c ---
#include "MSPd.h"
#include "fftease.h"

#if MSP
void *residency_class;
#endif 

#if PD
static t_class *residency_class;
#endif

#define OBJECT_NAME "residency~"

typedef struct _residency
{
#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 **loveboat;
	float current_frame;
	int framecount;
	//
	float frame_increment ;
	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 frames_read;
	//  int MAXFRAMES;
	short mute;
	short virgin;
	short playthrough;
	short in2_connected;
	short in3_connected;
	int overlap;
	int winfac;
	int hopsize;
	// int windowsize;
	float duration;
	short lock;
	short verbose;
	short override;
	float *input_vec;
	float sync;
} t_residency;

void *residency_new(t_symbol *s, int argc, t_atom *argv);
t_int *residency_perform(t_int *w);
void residency_dsp(t_residency *x, t_signal **sp, short *count);
void residency_assist(t_residency *x, void *b, long m, long a, char *s);
void residency_bangname(t_residency *x) ;
void residency_fftinfo(t_residency *x) ;
void residency_playthrough( t_residency *x, t_floatarg tog) ;
void residency_float(t_residency *x, double f) ;
void residency_mute(t_residency *x, t_floatarg tog);
void residency_free(t_residency *x);
void residency_init(t_residency *x, short initialized);
void residency_size(t_residency *x, t_floatarg newsize);
void residency_winfac(t_residency *x, t_floatarg factor);
void residency_overlap(t_residency *x, t_floatarg o);
void residency_verbose(t_residency *x, t_floatarg t);
void residency_acquire_sample(t_residency *x);
void residency_meminfo( t_residency *x );

#if MSP
void main(void)
{
	setup((t_messlist **)&residency_class, (method)residency_new, (method)residency_free, 
		  (short)sizeof(t_residency), 0L, A_GIMME,0);
	addmess((method)residency_dsp, "dsp", A_CANT, 0);
	addmess((method)residency_assist,"assist",A_CANT,0);
	addfloat((method)residency_float);
	addbang((method)residency_bangname);
	addmess((method)residency_mute, "mute", A_FLOAT, 0);
	addmess((method)residency_fftinfo, "fftinfo",  0);
	addmess((method)residency_meminfo, "meminfo",  0);
	addmess((method)residency_playthrough, "playthrough", A_DEFFLOAT, 0);
	addmess((method)residency_size, "size", A_DEFFLOAT, 0);
	addmess((method)residency_overlap, "overlap", A_DEFFLOAT, 0);
	addmess((method)residency_winfac, "winfac", A_DEFFLOAT, 0);
	addmess((method)residency_verbose, "verbose", A_DEFFLOAT, 0);
	dsp_initclass();
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

#if PD
void residency_tilde_setup(void)
{
	residency_class = class_new(gensym("residency~"), (t_newmethod)residency_new, 
								(t_method)residency_free ,sizeof(t_residency), 0,A_GIMME,0);
	CLASS_MAINSIGNALIN(residency_class, t_residency, x_f);
	class_addmethod(residency_class,(t_method)residency_dsp,gensym("dsp"),0);
	class_addmethod(residency_class,(t_method)residency_mute,gensym("mute"),A_FLOAT,0);
	class_addmethod(residency_class,(t_method)residency_fftinfo,gensym("fftinfo"),0);
	class_addmethod(residency_class,(t_method)residency_meminfo,gensym("meminfo"),0);
	class_addmethod(residency_class,(t_method)residency_playthrough,gensym("playthrough"),A_FLOAT,0); 
	class_addmethod(residency_class,(t_method)residency_size,gensym("size"),A_FLOAT,0);
	class_addmethod(residency_class,(t_method)residency_overlap,gensym("overlap"),A_FLOAT,0); 
	class_addmethod(residency_class,(t_method)residency_winfac,gensym("winfac"),A_FLOAT,0);  
	class_addmethod(residency_class,(t_method)residency_verbose,gensym("verbose"),A_FLOAT,0);
	class_addmethod(residency_class,(t_method)residency_acquire_sample,gensym("acquire_sample"),0);
	post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);
}
#endif

void residency_meminfo( t_residency *x )
{
    post("%d frames in buffer", x->framecount);
    post("frame_duration: %f, actual time in buffer: %f", x->tadv, (float)(x->framecount) * x->tadv);
	
}

void residency_overlap(t_residency *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;
	residency_init(x,1);
}

void residency_winfac(t_residency *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;
	//  post("called winfac");
	residency_init(x,2);
}

void residency_fftinfo(t_residency *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 residency_verbose(t_residency *x, t_floatarg t)
{
	x->verbose = t;
}

void residency_size(t_residency *x, t_floatarg newsize)
{
	//protect with DACs off?
	
	if(newsize > 0.0){//could be horrendous size, but that's the user's problem
		x->duration = newsize/1000.0;
		residency_init(x,1);  	
	}
}

void residency_playthrough (t_residency *x, t_floatarg tog)
{
	x->playthrough = tog;
}

void residency_free(t_residency *x){
	int i ;
#if MSP
	dsp_free((t_pxobject *)x);
#endif
	for(i = 0; i < x->framecount; i++){
		freebytes(x->loveboat[i],0) ;
	}
	freebytes(x->loveboat,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->output,0);
}



void residency_init(t_residency *x, short initialized)
{
	int i;
	
	int last_framecount = x->framecount;
	x->lock = 1;
	x->virgin = 1;
	
	if(!x->winfac)
		x->winfac = 1;
	if(!x->overlap)
		x->overlap = 4;
	if(!x->R)
		x->R = 44100;
	if(!x->D)
		x->D = 256;
	x->N = x->D * x->overlap;
	x->Nw = x->N * x->winfac;
	limit_fftsize(&x->N,&x->Nw,OBJECT_NAME);
	x->N2 = (x->N)>>1;
	x->Nw2 = (x->Nw)>>1;
	x->inCount = -(x->Nw);
	x->mult = 1. / (float) x->N;
	x->current_frame = 0;
	x->fpos = x->last_fpos = 0;
	x->tadv = (float)x->D/(float)x->R;
	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;
	
	if( x->duration <= 0 ){
		x->duration = 1.0;
	}
	
	x->framecount =  x->duration / x->tadv ;
	x->hopsize = x->N / x->overlap;
	x->read_me = 0;
	
	if(!initialized){
		x->sync = 0;
		x->mute = 0;
		x->in2_connected = 0;
		x->in3_connected = 0;
		x->playthrough = 0;
		x->frame_increment = 1.0;
		x->verbose = 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->input_vec = (float *) getbytes(8192  * sizeof(float));
		x->loveboat = (float **) getbytes(x->framecount * sizeof(float *));
		for(i=0;i<x->framecount;i++){
			x->loveboat[i] = (float *) getbytes(((x->N)+2) * sizeof(float));
			if(x->loveboat[i] == NULL){
				error("memory error");
				return;
			}
			memset((char *)x->loveboat[i],0,(x->N+2)*sizeof(float));
		}
	} else if(initialized == 1){
		
		for(i = 0; i < last_framecount; i++){
			freebytes(x->loveboat[i],0) ;
		}
		freebytes(x->loveboat,0);
		x->loveboat = (float **) getbytes(x->framecount * sizeof(float *));  
		for(i=0;i<x->framecount;i++){
			x->loveboat[i] = (float *) getbytes((x->N+2) * sizeof(float));
			if(x->loveboat[i] == NULL){
				error("memory error");
				return;
			}
			memset((char *)x->loveboat[i],0,(x->N+2)*sizeof(float));
		}
	} 
	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));
	
	makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D);
	init_rdft( x->N, x->bitshuffle, x->trigland);
	
	x->lock = 0;
}

void *residency_new(t_symbol *s, int argc, t_atom *argv)
{
#if MSP
	t_residency *x = (t_residency *)newobject(residency_class);
	dsp_setup((t_pxobject *)x,3);
	outlet_new((t_pxobject *)x, "signal");
	outlet_new((t_pxobject *)x, "signal");
#endif
	
#if PD
	t_residency *x = (t_residency *)pd_new(residency_class);
	inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
	inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal"));
	outlet_new(&x->x_obj, gensym("signal"));
	outlet_new(&x->x_obj, gensym("signal"));
#endif
	//  x->x_obj.z_misc |= Z_NO_INPLACE; 
	x->duration = atom_getfloatarg(0,argc,argv)/1000.0;
	x->overlap = atom_getfloatarg(1,argc,argv);
	x->winfac = atom_getfloatarg(2,argc,argv);
	
	x->D = sys_getblksize();
	x->R = sys_getsr();
	
	residency_init(x,0);
	
	return (x);
}

t_int *residency_perform(t_int *w)
{	
	int i, j;
	float sample;
	
	////////////////////////////////////////////// 
	t_residency *x = (t_residency *) (w[1]);
	t_float *in = (t_float *)(w[2]);
	t_float *increment = (t_float *)(w[3]);
	t_float *position = (t_float *)(w[4]);
	t_float *out = (t_float *)(w[5]);
	t_float *vec_sync = (t_float *) (w[6]);
	t_int n = w[7];
	
	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 *input_vec = x->input_vec;
	float fframe = x->current_frame ;
	float last_fpos = x->last_fpos ;
	int framecount = x->framecount;
	float fincr = x->frame_increment;
	float fpos = x->fpos;
	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 sync = x->sync;
	
	if(x->lock || x->mute){
		while(n--){
			*out++ = 0.0;
			*vec_sync++ = sync;
		}
		return (w+8);
	}
	
#if MSP
	if (x->in2_connected) {
		fincr = *increment; 
	} 
	if (x->in3_connected) {
		fpos = *position; 
	} 
#endif
	
#if PD
	fincr = *increment;
	fpos = *position;
#endif
	
	inCount += D;
	
	for(i = 0; i < D; i++){
		input_vec[i] = in[i];
	}
	if(x->read_me) {
		for ( j = 0 ; j < Nw - D ; j++ ){
			input[j] = input[j+D];
		}
		for (i = 0,j = Nw - D; j < Nw; j++, i++) {
			input[j] = input_vec[i];
		}
		if(framecount > 0)
			sync = (float)x->frames_read/(float)framecount;
		
		
		if( x->playthrough ){
			for ( i = 0, j = Nw - D; j < Nw; j++, i++ ) {
				out[i] = input_vec[i] * 0.5;
				vec_sync[i] = sync;
			}
		}
		else { 
			for ( j = 0; j < D; j++ ){
				out[j] = 0.0;
				vec_sync[j] = sync;
			}
		}
		
		fold(input, Wanal, Nw, buffer, N, inCount);	
		rdft(N, 1, buffer, bitshuffle, trigland);
		
		
		if(x->frames_read >= framecount){
			x->read_me = 0;
			if(x->verbose){
				post("residency: data acquisition completed");
			}
		} else {
			convert(buffer, x->loveboat[(x->frames_read)++], N2, c_lastphase_in, c_fundamental, c_factor_in);
		}
		x->virgin = 0;
	} 
	else if(x->playthrough && x->virgin){
		for(i=0;i<D;i++){
			sync = 0;
			sample = input_vec[i] * 0.5;
			out[i] = sample;
			vec_sync[i] = sync;
		}
	}
	else {
		//sync = 1.0;
		
		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(x->loveboat[(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(i = 0; i < D; i++){
			vec_sync[i] = sync;
		}
		for ( j = 0; j < D; j++ ){
			out[j] = output[j] * mult;
		}
		for ( j = 0; j < Nw - D; j++ ){
			output[j] = output[j+D];
		}
		
		for ( j = Nw - D; j < Nw; j++ ){
			output[j] = 0.;
		}
		
	}
	
	/* restore state variables */
	
	x->inCount = inCount % Nw;
	x->current_frame = fframe;
	x->frame_increment = fincr;
	x->fpos = fpos;
	x->last_fpos = last_fpos;
	x->sync = sync;
	return (w+8);
}		

#if MSP
void residency_float(t_residency *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 residency_acquire_sample(t_residency *x)
{
	x->read_me = 1;
	x->frames_read = 0;
	post("beginning spectral data acquisition");
	return;
}

void residency_bangname (t_residency *x)
{
	x->read_me = 1;
	x->frames_read = 0;
	if(x->verbose)
		post("beginning spectral data acquisition");
	return;
}

void residency_mute(t_residency *x, t_floatarg tog)
{
	x->mute = tog;	
}

void residency_dsp(t_residency *x, t_signal **sp, short *count)
{
#if MSP
	x->in2_connected = count[1];
	x->in3_connected = count[2];
#endif
	
	if(x->R != sp[0]->s_sr || x->D != sp[0]->s_n){
		x->R = sp[0]->s_sr;
		x->D = sp[0]->s_n;
		if(x->verbose)
			post("new vsize: %d, new SR:%d",x->D,x->R);
		residency_init(x,1);
	}
	
	dsp_add(residency_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);
}

void residency_assist(t_residency *x, void *b, long msg, long arg, char *dst)
{
	if (msg==1) {
		switch (arg) {
			case 0: sprintf(dst,"(signal/bang) Input, Sampling Trigger"); break;
			case 1: sprintf(dst,"(signal/float) Frame Increment");break;
			case 2:sprintf(dst,"(signal/float) Frame Position [0-1]");break;
				
		}
	} else if (msg==2) {
		switch(arg){
			case 0: sprintf(dst,"(signal) Output"); break;
			case 1: sprintf(dst,"(signal) Recording Sync"); break;
		}
	}
}





More information about the Pd-cvs mailing list