diff options
Diffstat (limited to 'pvwarp~.c')
-rw-r--r-- | pvwarp~.c | 873 |
1 files changed, 872 insertions, 1 deletions
@@ -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); +} + |