From 84231a000a4f06e34efa0d3700377dd3cc447e0b Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 4 Oct 2012 22:24:37 +0000 Subject: took FFTease2.5_Pd_OSX.zip and unpacked it into a Library Template layout original source: http://www.somasa.qub.ac.uk/~elyon/LyonSoftware/MaxMSP/FFTease/FFTease2.5_Pd_OSX.zip svn path=/trunk/externals/fftease/; revision=16331 --- pvwarp~.c | 873 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 872 insertions(+), 1 deletion(-) (limited to 'pvwarp~.c') diff --git a/pvwarp~.c b/pvwarp~.c index 63a97db..3aa4209 100644 --- a/pvwarp~.c +++ b/pvwarp~.c @@ -1 +1,872 @@ -#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); } \ No newline at end of file +#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(!fftease_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(!fftease_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); +} + -- cgit v1.2.1