Skip to content
Permalink
main
Go to file
 
 
Cannot retrieve contributors at this time
1797 lines (1685 sloc) 89.9 KB
/**
@file
rez~ - a looper thang
@ingroup MSP
*/
#include "ext.h"
#include "z_dsp.h"
#include "math.h"
#include "ext_buffer.h"
#include "ext_atomic.h"
#include "ext_obex.h"
#include "ext_obex_util.h"
#ifdef MAC_VERSION
#define FRCNLN inline __attribute__((always_inline))
#endif
#ifdef WIN_VERSION
#define FRCNLN __forceinline
#endif
typedef struct _rez {
t_pxobject obj;
t_buffer_ref *buf;
t_symbol *bufname;
t_symbol *mode;
t_ptr_int chan;
t_ptr_int bchan;
t_ptr_int bframes;
t_ptr_int pstart;
t_ptr_int pend;
t_ptr_int rstart;
t_ptr_int rend;
t_ptr_int nstart;
t_ptr_int nend;
t_ptr_int nrstart;
t_ptr_int nrend;
t_ptr_int fade;
t_ptr_int pfad;
t_ptr_int rfad;
t_ptr_int rxfad;
t_ptr_int xfad;
t_ptr_int rspprev;
t_ptr_int oneshot;
t_double rphprev;
t_double dpos;
t_double xpos;
t_double rpos;
t_double rxpos;
t_double phprev;
t_double spprev;
t_double sr;
t_double srscale;
t_bool wr;
t_bool rwr;
t_bool pparamchange;
t_bool rparamchange;
t_bool inOderAus;
t_bool rinOderAus;
t_bool buf_modd;
t_bool wram;
t_bool nshot;
t_bool rnshot;
} t_rez;
void *rez_new(t_symbol *s, long argc, t_atom *argv);
void rez_free(t_rez *x);
t_max_err rez_notify(t_rez *x, t_symbol *s, t_symbol *msg, void *sender, void *data);
t_max_err rez_attrfad_get(t_rez *x, t_object *attr, long *argc, t_atom **argv);
t_max_err rez_attrfad_set(t_rez *x, t_object *attr, long argc, t_atom *argv);
t_max_err rez_attr1shot_get(t_rez *x, t_object *attr, long *argc, t_atom **argv);
t_max_err rez_attr1shot_set(t_rez *x, t_object *attr, long argc, t_atom *argv);
void rez_assist(t_rez *x, void *b, long m, long a, char *s);
void rez_fade(t_rez *x, t_ptr_int fd);
void rez_limits(t_rez *x);
void rez_set(t_rez *x, t_symbol *s, long ac, t_atom *av);
void rez_doset(t_rez *x, t_symbol *s, long ac, t_atom *av);
void rez_pstart(t_rez *x, t_double ps);
void rez_pend(t_rez *x, t_double pe);
void rez_rstart(t_rez *x, t_double rs);
void rez_rend(t_rez *x, t_double re);
void rez_dblclick(t_rez *x);
void rez_sperform64(t_rez *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam);
void rez_psperform64(t_rez *x, t_object *d64, double **is, long numis, double **os, long numos, long smps, long flgs, void *usrp);
void rez_rsperform64(t_rez *x, t_object *d64, double **is, long numis, double **os, long numos, long smps, long flgs, void *usrp);
void rez_mperform64(t_rez *x, t_object *d64, double **is, long numis, double **os, long numos, long smps, long flgs, void *usrp);
void rez_pmperform64(t_rez *x, t_object *d64, double **is, long numis, double **os, long numos, long smps, long flgs, void *usrp);
void rez_rmperform64(t_rez *x, t_object *d64, double **is, long numis, double **os, long numos, long smps, long flgs, void *usrp);
void rez_dsp64(t_rez *x, t_object *d64, short *count, double sr, long maxvecsize, long flgs);
static t_class *s_rez_class;
static t_symbol *ps_buffer_modified, *ps_mode_a, *ps_mode_b, *ps_nada;
//easing function(fade/crossfade)
static FRCNLN double eas_func_up(double y1, double ramp, long fad)
{ return y1*(0.5*(1.0-cos((1.0-(((double)fad)/ramp))*PI))); }
static FRCNLN double eas_func_dwn(double y1, double ramp, long fad)
{ return y1*(0.5*(1.0-cos((((double)fad)/ramp)*PI))); }
static FRCNLN double eas_rec_up(double y1, double rmp, double odb, long fad)
{ return y1*(1.0-((odb*0.5)*(1.0-cos((1.0-((double)fad/rmp))*PI)))); }
static FRCNLN double eas_rec_dwn(double y1, double rmp, double odb, long fad)
{ return y1*(1.0-((odb*0.5)*(1.0-cos(((double)fad/rmp)*PI)))); }
static FRCNLN void interp_index(t_ptr_int p, t_ptr_int *ndxz,t_ptr_int *ndxb,t_ptr_int *ndxc, t_double spd,t_ptr_int frms)
{
t_ptr_int dr = (spd>=0)?1:-1;
*ndxz = p - dr; frms -= 1; //index-calc for cubic interpolation
if(*ndxz < 0) *ndxz = frms + *ndxz; else if(*ndxz > frms) *ndxz = *ndxz - frms;
*ndxb = p + dr;
if(*ndxb < 0) *ndxb = frms + *ndxb; else if(*ndxb > frms) *ndxb = *ndxb - frms;
*ndxc = *ndxb + dr;
if(*ndxc < 0) *ndxc = frms + *ndxc; else if(*ndxc > frms) *ndxc = *ndxc - frms;
return;
}
static FRCNLN double interp(double f, double z, double a, double b, double c)
{ return (!f) ? a : ((((0.5*(c-z) + 1.5*(a-b))*f + (z - 2.5*a + b + b - 0.5*c))*f + (0.5*(b-z)))*f + a); }
void ext_main(void *r)
{
t_class *c = class_new("rez~", (method)rez_new, (method)rez_free, sizeof(t_rez), NULL, A_GIMME, 0);
class_addmethod(c, (method)rez_dsp64, "dsp64", A_CANT, 0);
class_addmethod(c, (method)rez_assist, "assist", A_CANT, 0);
class_addmethod(c, (method)rez_dblclick,"dblclick", A_CANT, 0);
class_addmethod(c, (method)rez_notify, "notify", A_CANT, 0);
class_addmethod(c, (method)rez_pstart, "in", A_FLOAT, 0);
class_addmethod(c, (method)rez_pend, "aus", A_FLOAT, 0);
class_addmethod(c, (method)rez_rstart, "rin", A_FLOAT, 0);
class_addmethod(c, (method)rez_rend, "raus", A_FLOAT, 0);
class_addmethod(c, (method)rez_set, "set", A_GIMME, 0);
CLASS_ATTR_LONG(c, "fade", 0, t_rez, fade);
CLASS_ATTR_SAVE(c, "fade", 0);
CLASS_ATTR_ACCESSORS(c, "fade", (method)rez_attrfad_get, (method)rez_attrfad_set);
CLASS_ATTR_CHAR(c, "oneshot", 0, t_rez, oneshot);
CLASS_ATTR_SAVE(c, "oneshot", 0);
CLASS_ATTR_ACCESSORS(c, "oneshot", (method)rez_attr1shot_get, (method)rez_attr1shot_set);
class_dspinit(c); class_register(CLASS_BOX, c); s_rez_class = c;
ps_buffer_modified = gensym("buffer_modified"); ps_nada = gensym("");
ps_mode_a = gensym("play"); ps_mode_b = gensym("rec");
}
void *rez_new(t_symbol *s, long argc, t_atom *argv)
{
t_rez *x = (t_rez *)object_alloc(s_rez_class);
if(x)
{
t_symbol *bufname=0; t_symbol *mode=0; t_ptr_int chan=2;
bufname = atom_getsymarg(0,argc,argv);
chan = atom_getintarg(1,argc,argv); if(!chan)chan=2;
mode = atom_getsymarg(2,argc,argv);
if(mode == ps_mode_a){ dsp_setup((t_pxobject *)x,2); }else if(mode == ps_mode_b)
{ if(chan>1) dsp_setup((t_pxobject *)x,5); else dsp_setup((t_pxobject *)x,4); }
else{ if(chan>1) dsp_setup((t_pxobject *)x,7); else dsp_setup((t_pxobject *)x,6); }
x->mode=mode; x->bufname=bufname; x->chan=chan; x->fade=128;
x->rparamchange=x->pparamchange=x->rinOderAus=x->inOderAus=1;
x->rxfad=x->xfad=x->pfad=x->rfad=-1; x->wram=x->rspprev=x->buf_modd=x->rnshot=0;
x->nshot=x->nstart=x->nrstart=x->rstart=x->pstart=x->rwr=x->wr=x->oneshot=0;
x->rphprev=x->rpos=x->rxpos=x->xpos=x->dpos=x->spprev=x->phprev=0.;
if(mode!=ps_mode_b)
{
if(chan>1)outlet_new((t_object *)x, "signal"); // audio outlet
outlet_new((t_object *)x, "signal"); // audio outlet
}
if(mode==ps_nada){ outlet_new((t_object *)x, "signal"); }
outlet_new((t_object *)x, "signal"); // phase outlet
// create new buffer reference, initially a buffer with provided-name
x->buf = buffer_ref_new((t_object *)x, bufname); x->obj.z_misc |= Z_NO_INPLACE;
attr_args_process(x, argc, argv);
}
return (x);
}
// add object to dsp-chain(and call appropriate perform method; setup according to buffer~)
void rez_dsp64(t_rez *x, t_object *d64, short *count, double sr, long maxvecsize, long flgs)
{
x->sr = sr;
t_atom iav[2];
atom_setsym(iav, x->bufname);
atom_setlong(iav+1, x->chan);
rez_set(x, x->bufname, 2, iav);
if(x->chan>1)
{
if(x->mode==ps_mode_a)
object_method(d64, gensym("dsp_add64"), x, rez_psperform64, 0, NULL);
else if(x->mode==ps_mode_b)
object_method(d64, gensym("dsp_add64"), x, rez_rsperform64, 0, NULL);
else
object_method(d64, gensym("dsp_add64"), x, rez_sperform64, 0, NULL);
}
else
{
if(x->mode==ps_mode_a)
object_method(d64, gensym("dsp_add64"), x, rez_pmperform64, 0, NULL);
else if(x->mode==ps_mode_b)
object_method(d64, gensym("dsp_add64"), x, rez_rmperform64, 0, NULL);
else
object_method(d64, gensym("dsp_add64"), x, rez_mperform64, 0, NULL);
}
}
// free buffer~ memory, and object from dsp-chain
void rez_free(t_rez *x){ dsp_free((t_pxobject *)x); object_free(x->buf); }
// handles necessary notifications for when buffer appears/disappears/is-modded.
t_max_err rez_notify(t_rez *x, t_symbol *s, t_symbol *msg, void *sender, void *data)
{
if (msg == ps_buffer_modified) x->buf_modd = true;
return buffer_ref_notify(x->buf, s, msg, sender, data);
}
void rez_assist(t_rez *x, void *b, long m, long a, char *s)
{
t_symbol *mode = x->mode; t_ptr_int chan= x->chan;
if (m == ASSIST_INLET) // inlets
{
if(mode == ps_mode_a)
{
switch (a)
{
case 0: snprintf_zero(s,256,"(signal)starting-phase(from 0. to 1.)"); break;
case 1: snprintf_zero(s, 256,"(signal)playback speed(from -∞. to +∞.)"); break;
}
}
else if(mode == ps_mode_b)
{
if(chan>1)
{
switch (a)
{
case 0: snprintf_zero(s,256,"(signal)starting-rec-phase(from 0. to 1.)"); break;
case 1: snprintf_zero(s, 256,"(signal)recording-speed(-1.,0.,or +1. only)"); break;
case 2: snprintf_zero(s, 256, "(signal)overdub-amount(0. to 1.)"); break;
case 3: snprintf_zero(s, 256, "(signal)left-recording-input"); break;
case 4: snprintf_zero(s, 256, "(signal)right-recording-input"); break;
}
}
else
{
switch (a)
{
case 0: snprintf_zero(s,256,"(signal)starting-rec-phase(from 0. to 1.)"); break;
case 1: snprintf_zero(s, 256,"(signal)recording-speed(-1.,0.,or +1. only)"); break;
case 2: snprintf_zero(s, 256, "(signal)overdub-amount(0. to 1.)"); break;
case 3: snprintf_zero(s, 256, "(signal)left-recording-input"); break;
}
}
}
else
{
if(chan>1)
{
switch (a)
{
case 0: snprintf_zero(s,256,"(signal)starting-phase(from 0. to 1.)"); break;
case 1: snprintf_zero(s, 256,"(signal)playback speed(from -∞. to +∞.)"); break;
case 2: snprintf_zero(s,256,"(signal)starting-rec-phase(from 0. to 1.)"); break;
case 3: snprintf_zero(s, 256,"(signal)recording-speed(-1.,0.,or +1. only)"); break;
case 4: snprintf_zero(s, 256,"(signal)overdub-amount(0. to 1.)"); break;
case 5: snprintf_zero(s, 256,"(signal)left-recording-input"); break;
case 6: snprintf_zero(s, 256,"(signal)right-recording-input"); break;
}
}
else
{
switch (a)
{
case 0: snprintf_zero(s,256,"(signal)starting-phase(from 0. to 1.)"); break;
case 1: snprintf_zero(s, 256,"(signal)playback speed(from -∞. to +∞.)"); break;
case 2: snprintf_zero(s,256,"(signal)starting-rec-phase(from 0. to 1.)"); break;
case 3: snprintf_zero(s, 256,"(signal)recording-speed(-1.,0.,or +1. only)"); break;
case 4: snprintf_zero(s, 256,"(signal)overdub-amount(0. to 1.)"); break;
case 5: snprintf_zero(s, 256,"(signal)left-recording-input"); break;
}
}
}
}
else
{
if(mode == ps_mode_a)
{
if(chan>1)
{
switch (a)
{
case 0: snprintf_zero(s,256,"(signal)left-output"); break;
case 1: snprintf_zero(s, 256,"(signal)right-output"); break;
case 2: snprintf_zero(s, 256,"(signal)playback-phase(0. to 1.)"); break;
}
}
else
{
switch (a)
{
case 0: snprintf_zero(s,256,"(signal)left-output"); break;
case 1: snprintf_zero(s, 256,"(signal)playback-phase(0. to 1.)"); break;
}
}
}
else if(mode == ps_nada)
{
if(chan>1)
{
switch (a)
{
case 0: snprintf_zero(s,256,"(signal)left-output"); break;
case 1: snprintf_zero(s, 256,"(signal)right-output"); break;
case 2: snprintf_zero(s, 256,"(signal)playback-phase(0. to 1.)"); break;
case 3: snprintf_zero(s, 256,"(signal)recording-phase(0. to 1.)"); break;
}
}
else
{
switch (a)
{
case 0: snprintf_zero(s,256,"(signal)left-output"); break;
case 1: snprintf_zero(s, 256,"(signal)playback-phase(0. to 1.)"); break;
case 2: snprintf_zero(s, 256,"(signal)recording-phase(0. to 1.)"); break;
}
}
}else{ switch(a){ case 0: snprintf_zero(s, 256,"(signal)recording-phase(0. to 1.)"); } }
}
}
t_max_err rez_attrfad_set(t_rez *x, t_object *attr, long argc, t_atom *argv)
{ t_ptr_int fade = atom_getlong(argv); x->fade = (fade<0)?0:((fade>65536)?65536:fade); return 0; }
t_max_err rez_attrfad_get(t_rez *x, t_object *attr, long *argc, t_atom **argv)
{
char alloc; t_ptr_int fade = x->fade;
atom_alloc(argc, argv, &alloc); atom_setlong(*argv, fade); return 0;
}
t_max_err rez_attr1shot_set(t_rez *x, t_object *attr, long argc, t_atom *argv)
{ t_bool oneshot = atom_getlong(argv); x->oneshot = oneshot; return 0; }
t_max_err rez_attr1shot_get(t_rez *x, t_object *attr, long *argc, t_atom **argv)
{
char alloc; t_bool oneshot = x->oneshot;
atom_alloc(argc, argv, &alloc); atom_setlong(*argv, oneshot); return 0;
}
void rez_limits(t_rez *x)
{
t_double sr = x->sr;
t_buffer_obj *b = buffer_ref_getobject(x->buf); // get the actual buffer object from our ref
if (b)
{
x->bchan=buffer_getchannelcount(b); // buffer~'s number of chans
x->srscale=buffer_getsamplerate(b)/sr;
x->bframes=buffer_getframecount(b); // buffer~-length of 1 channel
}
}
void rez_doset(t_rez *x, t_symbol *s, long ac, t_atom *av)
{
t_symbol *name; name = (ac) ? atom_getsym(av) : gensym("");
buffer_ref_set(x->buf, name); rez_limits(x);
}
// calls setting buffer ref be on main thread only
void rez_set(t_rez *x,t_symbol *s,long ac,t_atom *av){ defer(x,(method)rez_doset,s,ac,av); }
//___________LOOP_BOUNDARY_SETUP FOR PLAYBACK AND RECORDING___________
//.."wr"/"rwr" = wraparound flag is on if "in"(pstart)/"rin"(rstart) > "aus"(pend)/"raus"(rend)...
//..With wraparound, playback plays through end-to-start of buffer~ to reach "aus"(pend)/"raus"(rend)
//_____"pparamchange"/"rparamchange" are flags to tell the perform method to register changes...
//.....(once safely within distance for proper observance of loop-boundaries/crossfades/fades,..
//..perform-meth writes to "pparamchange"/"rparamchange" tracking internal registration of changes)
void rez_pstart(t_rez *x, t_double ps)
{
ps = (ps>1.0)?1.0:((ps<0.0)?0.0:ps); x->pstart = ps*(x->bframes-1);
if(x->pstart > x->pend) x->wr=1; else x->wr=0; x->pparamchange = 1;
}
void rez_pend(t_rez *x, t_double pe)
{
pe = (pe>1.0)?1.0:((pe<0.0)?0.0:pe); x->pend = pe*(x->bframes-1);
if(x->pstart > x->pend) x->wr=1; else x->wr=0; x->pparamchange = 1;
}
void rez_rstart(t_rez *x, t_double rs)
{
rs = (rs>1.0)?1.0:((rs<0.0)?0.0:rs); x->rstart = rs*(x->bframes-1);
if(x->rstart > x->rend) x->rwr=1; else x->rwr=0; x->rparamchange = 1;
}
void rez_rend(t_rez *x, t_double re)
{
re = (re>1.0)?1.0:((re<0.0)?0.0:re); x->rend = re*(x->bframes-1);
if(x->rstart > x->rend) x->rwr=1; else x->rwr=0; x->rparamchange = 1;
}
void rez_dblclick(t_rez *x) { buffer_view(buffer_ref_getobject(x->buf)); }
void rez_sperform64(t_rez *x, t_object *d64, double **is, long numis, double **os, long numos, long smps, long flgs, void *usrp)
{
t_double *ph = is[0];
t_double *spd = is[1];
t_double *rph = is[2];
t_double *rspd = is[3];
t_double *ovdb = is[4];
t_double *rinL = is[5];
t_double *rinR = is[6];
t_double *outL = os[0];
t_double *outR = os[1];
t_double *outPh = os[2];
t_double *outRPh = os[3];
long n=smps; float *b;
t_double phprev,inpos,dpos,sp,rcL,rcR,frac,dfrnc,rpos,rxpos,rsp;
t_double spprev,oL,oR,oPh,oRPh,xL,xR,xpos,scldsr,odb,rphprev,rinpos;
t_ptr_int rndx,rxdx,bnc,bframes,pstart,pend,rstart,rend,nstart,nend,nrstart,nrend;
t_ptr_int indx,indxz,indxb,indxc,xfad,pfad,rfad,rxfad,fade,rs,rspprev;
t_bool wr,rwr,pparamch,rparamch,inOderAus,rinOderAus,wram,oneshot,nshot,rnshot;
t_buffer_obj *buffer=buffer_ref_getobject(x->buf);
b = buffer_locksamples(buffer); if(!b||x->obj.z_disabled) goto zero;
if(x->buf_modd){ x->buf_modd=false; rez_limits(x); } oneshot=x->oneshot; nshot=x->nshot;
bnc=x->bchan; bframes=x->bframes-1; pstart=x->pstart; pend=x->pend; inOderAus=x->inOderAus;
pparamch=x->pparamchange; pfad=x->pfad; xfad=x->xfad; fade=x->fade; xpos=x->xpos;
rpos=x->rpos; wr=x->wr; rparamch=x->rparamchange; rfad=x->rfad;
rstart=x->rstart; rend=x->rend; rnshot=x->rnshot; phprev=x->phprev; rphprev=x->rphprev;
spprev=x->spprev; dpos=x->dpos; wram=x->wram; scldsr=x->srscale;
nend=x->nend; nstart=x->nstart; nrend=x->nrend; nrstart=x->nrstart;
rxfad=x->rxfad; rxpos=x->rxpos; rspprev=x->rspprev; rwr=x->rwr; rinOderAus=x->rinOderAus;
while(n--)
{
inpos=*ph++; sp=*spd++; rinpos=*rph++; rsp=*rspd++; odb=*ovdb++; rcL=*rinL++; rcR=*rinR++;
inpos=(inpos<0.0)?0.0:((inpos>1.0)?1.0:inpos); inpos*=bframes; sp*=scldsr;
rinpos=(rinpos<0.0)?0.0:((rinpos>1.0)?1.0:rinpos); rinpos*=bframes;
if(rsp>0.0) rs=1; else if(rsp<0.0) rs=-1; else rs=0;
//inOderAus(from SachaBaronCohen's "Bruno" skit)-flag indicates if position is 'in'/'out' of a loop..
//..if 'in' loop-boundary,save messages(pstart/pend/rstart/rend) internally(nstart/nend/nrstart/nrend)
if(oneshot)//ONESHOT_SECTION
{ //..........................ONESHOT-RECORDING
if((rspprev==0)&&(rs!=0))//on speed-change for 'on',check position from loop bounds..
{ //..setup fade-in/fade-out,internal one-shot flag(nshot),& pos/speed changes
rpos=rinpos; rfad=fade-1; wram=1; rnshot=1; rspprev=rs;
if(rwr)
{
if((rpos>(rend-fade))&&(rpos<(rstart+fade))){ rinOderAus=0; }
else { rinOderAus=1; nrstart=rstart; nrend=rend; }
}
else
{
if((rpos>(rend-fade))||(rpos<(rstart+fade))){ rinOderAus=0; }
else { rinOderAus=1; nrstart=rstart; nrend=rend; }
}
}
else if(((rspprev!=0)&&(rs==0)) && rnshot){ rfad=fade-1; rnshot=0; }
if(rnshot)//rnshot flag determines if the state is fading-in-recording/recording-regular..
{
if(rwr)
{
if((rpos<(rend-fade))||(rpos>(rstart+fade)))
{ rinOderAus=1; nrstart=rstart; nrend=rend; }
}
else
{
if((rpos<(rend-fade))&&(rpos>(rstart+fade)))
{ rinOderAus=1; nrstart=rstart; nrend=rend; }
}
if(rinOderAus)
{
if(rwr)
{ if((rpos>=(nrend-fade))&&(rpos<=(nrstart+fade))){ rfad=fade-1; rnshot=0; } }
else
{ if((rpos>=(nrend-fade))||(rpos<=(nrstart+fade))){ rfad=fade-1; rnshot=0; } }
}
//buffer~-boundary constraint, and positional-increment
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=rpos; rpos+=rs;
if(rfad>=0)//Fade-In
{
b[rndx*bnc]=eas_func_up(rcL,fade,rfad)+eas_rec_up(b[rndx*bnc],fade,1-odb,rfad);
b[rndx*bnc+1]=eas_func_up(rcR,fade,rfad)+eas_rec_up(b[rndx*bnc+1],fade,1-odb,rfad);
rfad--;
}else{ b[rndx*bnc]=rcL+(b[rndx*bnc]*odb); b[rndx*bnc+1]=rcR+(b[rndx*bnc+1]*odb); };
}
else //..or(when rnshot is 0, the state is) fading-out-recording/stopped-recording
{
if(rfad>=0)
{ //....buffer~-boundary constraint, and positional-increment
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=rpos; rpos+=rspprev;
b[rndx*bnc]=eas_func_dwn(rcL,fade,rfad)+eas_rec_dwn(b[rndx*bnc],fade,1-odb,rfad);
b[rndx*bnc+1]=eas_func_dwn(rcR,fade,rfad)+eas_rec_dwn(b[rndx*bnc+1],fade,1-odb,rfad);
rfad--; if(rfad<0) { wram=0; rspprev=rs; }
} else { rspprev=rs; }
}
//......................................ONESHOT-PLAYBACK
if((spprev==0.0)&&(sp!=0.0))//on speed-change for 'on',check position from loop bounds..
{ //..setup fade-in/fade-out,internal one-shot flag(nshot),& position/speed changes
dpos=inpos; pfad=fade-1; nshot=1; spprev=sp;
if(wr)
{
if((dpos>(pend-fade))&&(dpos<(pstart+fade))){ inOderAus=0; }
else { inOderAus=1; nstart=pstart; nend=pend; }
}
else{ if((dpos>(pend-fade))||(dpos<(pstart+fade)))
{ inOderAus=0; }else{ inOderAus=1; nstart=pstart; nend=pend; } }
}
else if(((spprev!=0.0)&&(sp==0.0)) && nshot){ pfad=fade-1; nshot=0; }
if(nshot) //nshot flag determines if the state is fading-in/playing-back-regular..
{
if(wr)
{
if((dpos<(pend-fade))||(dpos>(pstart+fade)))
{ inOderAus=1; nstart=pstart; nend=pend; }
}
else
{
if((dpos<(pend-fade))&&(dpos>(pstart+fade)))
{ inOderAus=1; nstart=pstart; nend=pend; }
}
if(inOderAus)
{
if(wr){ if((dpos>=(nend-fade))&&(dpos<=(nstart+fade))){ pfad=fade-1; nshot=0; } }
else{ if((dpos>=(nend-fade))||(dpos<=(nstart+fade))){ pfad=fade-1; nshot=0; } }
}
//buffer~-boundary constraint, positional-increment, and bicubic interpolation
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(sp>0){frac=dpos-indx;}else if(sp<0){frac=1.0-(dpos-indx);}else frac=0.0; dpos+=sp;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
xR = interp(frac, b[indxz*bnc+1], b[indx*bnc+1], b[indxb*bnc+1], b[indxc*bnc+1]);
//fade-in
if(pfad>=0){ oL=eas_func_up(xL,fade,pfad); oR=eas_func_up(xR,fade,pfad); pfad--; }
else{ oL=xL; oR=xR; }
}
else //..or(when nshot is 0, the state is) fading-out/silenced
{//fade-Out
if(pfad>=0)
{ //buffer~-boundary constraint, positional-increment, and bicubic interpolation
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(spd>0){frac=dpos-indx;}else if(spd<0){frac=1.0-(dpos-indx);}else frac=0.0;
dpos+=spprev;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
xR = interp(frac, b[indxz*bnc+1], b[indx*bnc+1], b[indxb*bnc+1], b[indxc*bnc+1]);
oL = eas_func_dwn(xL, fade, pfad); oR = eas_func_dwn(xR, fade, pfad);
pfad--; if(pfad<0)spprev=sp;
}else{ oL = oR = 0.; spprev=sp; } //.........<-Everything Off
}
}
else//LOOPER_(not_oneshot)_SECTION
{ //................................LOOPER-RECORDING
if((rs!=rspprev)&&(rfad<0))
{
if(((rspprev==0)&&(rs!=0))&&(rfad<0)){ rfad=fade-1; wram=1; rspprev=rs; }
else if (((rspprev!=0)&&(rs==0))&&(rfad<0)){ rfad=fade-1; }
else if(((rspprev<0)&&(rs>0))||((rspprev>0)&&(rs<0))){ rxfad=fade; rxpos=rpos; }
}
if(rs!=0)
{
if((rinpos!=rphprev)&&(rxfad<0))
{ //crossfade positional changes
if(rwr){ if((rinpos>nrend)&&(rinpos<nrstart))rinOderAus=0; else rinOderAus=1; }
else{ if((rinpos>nrend)||(rinpos<nrstart))rinOderAus=0; else rinOderAus=1; }
if(rfad<0){rxfad=fade; rxpos=rpos;} rphprev=rpos=rinpos;
}
if(rparamch)
{ //window changes
if(rwr){
if(((rpos>rend)&&(rpos<rstart))&&((rend>nrend)||(rstart<nrstart)))
rinOderAus=0; else rinOderAus=1;
}else{
if(((rpos>rend)||(rpos<rstart))&&((rend>nrend)||(rstart<nrstart)))
rinOderAus=0; else rinOderAus=1;
}
}
//recording-crossfade at loop boundaries
if((rinOderAus)&&(rxfad<0))
{ //rparamch = flag to notify when there's incoming..
if(rparamch){ rparamch=0; nrend=rend; nrstart=rstart; }//..message-set loop-bounds
if(rwr){
if((rpos>nrend)&&(rpos<nrstart))
{
rxfad=fade;
if(rs>0){ rpos=nrstart; rxpos=nrend; }else{ rpos=nrend; rxpos=nrstart;}
}
}else{
if((rpos>nrend)||(rpos<nrstart))
{
rxfad=fade;
if(rs>0){ rpos=nrstart; rxpos=nrend; }else{ rpos=nrend; rxpos=nrstart;}
}
}
}
else //if starting off outside of loop-boundaries, record until within...
{ //..and once within, save messages(rstart/rend) internally(nrstart/nrend)
if(rwr)
{if((rpos<=rend)||(rpos>=rstart))
{rparamch=0; rinOderAus=1; nrend=rend; nrstart=rstart;}}
else
{if((rpos<=rend)&&(rpos>=rstart))
{rparamch=0; rinOderAus=1; nrend=rend; nrstart=rstart;}}
}
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=trunc(rpos); rpos+=rs;
if(rxfad>=0) //....Crossfades(happen at loop-points and phase changes)
{ //crossfade-point buffer~-boundary constraint and increment
if(rxpos>bframes)rxpos=0; if(rxpos<0)rxpos=bframes; rxdx=trunc(rxpos); rxpos+=rs;
b[rxdx*bnc]=eas_func_dwn(rcL,fade,rxfad)+eas_rec_dwn(b[rxdx*bnc],fade,1-odb,rxfad);
b[rxdx*bnc+1]=eas_func_dwn(rcR,fade,rxfad)+eas_rec_dwn(b[rxdx*bnc+1],fade,1-odb,rxfad);
b[rndx*bnc]=eas_func_up(rcL,fade,rxfad)+eas_rec_up(b[rndx*bnc],fade,1-odb,rxfad);
b[rndx*bnc+1]=eas_func_up(rcR,fade,rxfad)+eas_rec_up(b[rndx*bnc+1],fade,1-odb,rxfad);
rxfad--;
}
else if(rfad>=0) //...................Fade-In
{
b[rndx*bnc]=eas_func_up(rcL,fade,rfad)+eas_rec_up(b[rndx*bnc],fade,1-odb,rfad);
b[rndx*bnc+1]=eas_func_up(rcR,fade,rfad)+eas_rec_up(b[rndx*bnc+1],fade,1-odb,rfad);rfad--;
} else { b[rndx*bnc]=rcL+(b[rndx*bnc]*odb); b[rndx*bnc+1]=rcR+(b[rndx*bnc+1]*odb); }
}
else
{ //...................................Fade-Out
if(rfad>=0)
{
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=trunc(rpos); rpos+=rspprev;
b[rndx*bnc]=eas_func_dwn(rcL,fade,rfad)+eas_rec_dwn(b[rndx*bnc],fade,1-odb,rfad);
b[rndx*bnc+1]=eas_func_dwn(rcR,fade,rfad)+eas_rec_dwn(b[rndx*bnc+1],fade,1-odb,rfad);
rfad--; if(rfad<0) { wram=0; rspprev=rs; }
}else{ rspprev=rs; }
}
//.....................................LOOPER-PLAYBACK
if((sp!=spprev)&&(xfad<0))
{if((((spprev==0.0)&&(sp!=0.0))||((spprev!=0.0)&&(sp==0.0)))&&(pfad<0)){pfad=fade;}//onoff
else if(((spprev<0)&&(sp>0))||((spprev>0)&&(sp<0))){xfad=fade;xpos=dpos;}}//xfad neg<->pos
if(sp!=0.0)
{
if((inpos!=phprev)&&(xfad<0))
{ //crossfade positional changes
if(wr){ if((inpos>nend)&&(inpos<nstart))inOderAus=0; else inOderAus=1; }
else{ if((inpos>nend)||(inpos<nstart))inOderAus=0; else inOderAus=1; }
if(pfad<0){xfad=fade; xpos=dpos;} phprev=dpos=inpos;
}
if(pparamch)
{ //window changes
if(wr){
if(((dpos>pend)&&(dpos<pstart))&&((pend>nend)||(pstart<nstart)))
inOderAus=0; else inOderAus=1;
}else{
if(((dpos>pend)||(dpos<pstart))&&((pend>nend)||(pstart<nstart)))
inOderAus=0; else inOderAus=1;
}
}
//crossfade at playback-loop boundaries
if((inOderAus)&&(xfad<0))
{
if(pparamch){ pparamch=0; nend=pend; nstart=pstart; }
if(wr){
if((dpos>nend)&&(dpos<nstart))
{
xfad=fade; xpos=dpos;
if(sp>0.0) dpos=(dpos-nend)+nstart; else dpos=nend-(nstart-dpos);
}
}else{
if((dpos>nend)||(dpos<nstart))
{
xfad=fade; xpos=dpos;
if(sp>0.0) dpos=(dpos-nend)+nstart; else dpos=nend-(nstart-dpos);
}
}
}
else //if starting off outside of loop-boundaries, play until within...
{ //..and once within, save messages(pstart/pend) internally(nstart/nend)
if(wr)
{if((dpos<=pend)||(dpos>=pstart)){pparamch=0; inOderAus=1; nend=pend; nstart=pstart;}}
else
{if((dpos<=pend)&&(dpos>=pstart)){pparamch=0; inOderAus=1; nend=pend; nstart=pstart;}}
}
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(sp>0){ frac=dpos-indx; }else if(sp<0){ frac=1.0-(dpos-indx); }else frac=0.0; dpos+=sp;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
xR = interp(frac, b[indxz*bnc+1], b[indx*bnc+1], b[indxb*bnc+1], b[indxc*bnc+1]);
if(pfad>=0) //.......................Fade-In
{ oL=eas_func_up(xL,fade,pfad); oR=eas_func_up(xR,fade,pfad); pfad--; }
else if(xfad>=0)//..Crossfades(happen at loop-points,phase-changes,and abrupt pos/neg)
{
if(xpos>bframes)xpos-=(bframes+1); if(xpos<0)xpos+=(bframes+1); indx=trunc(xpos);
if(sp>0){frac=xpos-indx;}else if(sp<0){frac=1.0-(xpos-indx);}else frac=0.0;
xpos+=sp;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
oL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
oR = interp(frac, b[indxz*bnc+1], b[indx*bnc+1], b[indxb*bnc+1], b[indxc*bnc+1]);
oL = eas_func_up(xL, fade, xfad) + eas_func_dwn(oL, fade, xfad);
oR = eas_func_up(xR, fade, xfad) + eas_func_dwn(oR, fade, xfad); xfad--;
}else{ oL=xL; oR=xR; } //..<-Regular Playback
spprev=sp;
}
else
{ //......................................Fade-Out
if(pfad>=0)
{
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(spd>0){frac=dpos-indx;}else if(spd<0){frac=1.0-(dpos-indx);}else frac=0.0;
dpos+=spprev;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
xR = interp(frac, b[indxz*bnc+1], b[indx*bnc+1], b[indxb*bnc+1], b[indxc*bnc+1]);
oL = eas_func_dwn(xL, fade, pfad); oR = eas_func_dwn(xR, fade, pfad); pfad--;
if(pfad<0)spprev=sp;
}else{ oL = oR = 0.; spprev=sp; } //<-Everything Off
}
if(wram) //..calculate abs-difference between playhead and recordhead..
{ //..if difference is within fade time, use difference to drive ducking of playhead
if(sp!=(double)rs)
{
dfrnc = fabs(rpos-dpos);
if(dfrnc<(fade*2.7489))
{ oL=eas_func_dwn(oL,(fade*2.7489),dfrnc); oR=eas_func_dwn(oR,(fade*2.7489),dfrnc); }
}
}
}
oPh=dpos/bframes; oRPh=rpos/bframes;//<-convert samp-index 2 phase
*outL++ = oL; *outR++ = oR; *outPh++ = oPh; *outRPh++ = oRPh;
}
if(wram)buffer_setdirty(buffer); buffer_unlocksamples(buffer); x->nshot=nshot; x->rnshot=rnshot;
x->pparamchange=pparamch; x->rparamchange=rparamch; x->xfad=xfad; x->pfad=pfad; x->xpos=xpos;
x->phprev=phprev; x->rphprev=rphprev; x->spprev=spprev; x->rspprev=rspprev; x->rxpos=rxpos;
x->dpos=dpos; x->rpos=rpos; x->inOderAus=inOderAus; x->rinOderAus=rinOderAus; x->rfad=rfad;
x->nend=nend; x->nstart=nstart; x->nrend=nrend; x->nrstart=nrstart; x->rxfad=rxfad; x->wram=wram;
return;
zero: while(n--){ *outL++=0.; *outR++=0.; *outPh++=0.; *outRPh++=0.; }
}
void rez_psperform64(t_rez *x, t_object *d64, double **is, long numis, double **os, long numos, long smps, long flgs, void *usrp)
{
t_double *ph = is[0];
t_double *spd = is[1];
t_double *outL = os[0];
t_double *outR = os[1];
t_double *outPh = os[2];
long n=smps; float *b;
t_double phprev,inpos,dpos,sp,frac;
t_double spprev,oL,oR,oPh,xL,xR,xpos,scldsr;
t_ptr_int bnc,bframes,pstart,pend,nstart,nend;
t_ptr_int indx,indxz,indxb,indxc,xfad,pfad,fade;
t_bool wr,pparamch,inOderAus,oneshot,nshot;
t_buffer_obj *buffer=buffer_ref_getobject(x->buf);
b = buffer_locksamples(buffer); if(!b||x->obj.z_disabled) goto zero;
if(x->buf_modd){ x->buf_modd=false; rez_limits(x); } oneshot=x->oneshot; nshot=x->nshot;
bnc=x->bchan; bframes=x->bframes-1; pstart=x->pstart; pend=x->pend; inOderAus=x->inOderAus;
pparamch=x->pparamchange; pfad=x->pfad; xfad=x->xfad; fade=x->fade; xpos=x->xpos; wr=x->wr;
phprev=x->phprev; spprev=x->spprev; dpos=x->dpos; scldsr=x->srscale;
nend=x->nend; nstart=x->nstart;
while(n--)
{
inpos=*ph++; sp=*spd++;
inpos=(inpos<0.0)?0.0:((inpos>1.0)?1.0:inpos); inpos*=bframes; sp*=scldsr;
//inOderAus(from SachaBaronCohen's "Bruno" skit)-flag indicates if position is 'in'/'out' of a loop..
//..if 'in' loop-boundary,save messages(pstart/pend) internally(nstart/nend)
if(oneshot)//ONESHOT_SECTION
{
//......................................ONESHOT-PLAYBACK
if((spprev==0.0)&&(sp!=0.0))//on speed-change for 'on',check position from loop bounds..
{ //..setup fade-in/fade-out,internal one-shot flag(nshot),& position/speed changes
dpos=inpos; pfad=fade-1; nshot=1; spprev=sp;
if(wr)
{
if((dpos>(pend-fade))&&(dpos<(pstart+fade))){ inOderAus=0; }
else { inOderAus=1; nstart=pstart; nend=pend; }
}
else{ if((dpos>(pend-fade))||(dpos<(pstart+fade)))
{ inOderAus=0; }else{ inOderAus=1; nstart=pstart; nend=pend; } }
}
else if(((spprev!=0.0)&&(sp==0.0)) && nshot){ pfad=fade-1; nshot=0; }
if(nshot) //nshot flag determines if the state is fading-in/playing-back-regular..
{
if(wr)
{
if((dpos<(pend-fade))||(dpos>(pstart+fade)))
{ inOderAus=1; nstart=pstart; nend=pend; }
}
else
{
if((dpos<(pend-fade))&&(dpos>(pstart+fade)))
{ inOderAus=1; nstart=pstart; nend=pend; }
}
if(inOderAus)
{
if(wr){ if((dpos>=(nend-fade))&&(dpos<=(nstart+fade))){ pfad=fade-1; nshot=0; } }
else{ if((dpos>=(nend-fade))||(dpos<=(nstart+fade))){ pfad=fade-1; nshot=0; } }
}
//buffer~-boundary constraint, positional-increment, and bicubic interpolation
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(sp>0){frac=dpos-indx;}else if(sp<0){frac=1.0-(dpos-indx);}else frac=0.0; dpos+=sp;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
xR = interp(frac, b[indxz*bnc+1], b[indx*bnc+1], b[indxb*bnc+1], b[indxc*bnc+1]);
//fade-in
if(pfad>=0){ oL=eas_func_up(xL,fade,pfad); oR=eas_func_up(xR,fade,pfad); pfad--; }
else{ oL=xL; oR=xR; }
}
else //..or(when nshot is 0, the state is) fading-out/silenced
{//fade-Out
if(pfad>=0)
{ //buffer~-boundary constraint, positional-increment, and bicubic interpolation
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(spd>0){frac=dpos-indx;}else if(spd<0){frac=1.0-(dpos-indx);}else frac=0.0;
dpos+=spprev;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
xR = interp(frac, b[indxz*bnc+1], b[indx*bnc+1], b[indxb*bnc+1], b[indxc*bnc+1]);
oL = eas_func_dwn(xL, fade, pfad); oR = eas_func_dwn(xR, fade, pfad);
pfad--; if(pfad<0)spprev=sp;
}else{ oL = oR = 0.; spprev=sp; } //.........<-Everything Off
}
}
else//LOOPER_(not_oneshot)_SECTION
{ //.....................................LOOPER-PLAYBACK
if((sp!=spprev)&&(xfad<0))
{if((((spprev==0.0)&&(sp!=0.0))||((spprev!=0.0)&&(sp==0.0)))&&(pfad<0)){pfad=fade;}//onoff
else if(((spprev<0)&&(sp>0))||((spprev>0)&&(sp<0))){xfad=fade;xpos=dpos;}}//xfad neg<->pos
if(sp!=0.0)
{
if((inpos!=phprev)&&(xfad<0))
{ //crossfade positional changes
if(wr){ if((inpos>nend)&&(inpos<nstart))inOderAus=0; else inOderAus=1; }
else{ if((inpos>nend)||(inpos<nstart))inOderAus=0; else inOderAus=1; }
if(pfad<0){xfad=fade; xpos=dpos;} phprev=dpos=inpos;
}
if(pparamch)
{ //window changes
if(wr){
if(((dpos>pend)&&(dpos<pstart))&&((pend>nend)||(pstart<nstart)))
inOderAus=0; else inOderAus=1;
}else{
if(((dpos>pend)||(dpos<pstart))&&((pend>nend)||(pstart<nstart)))
inOderAus=0; else inOderAus=1;
}
}
//crossfade at playback-loop boundaries
if((inOderAus)&&(xfad<0))
{
if(pparamch){ pparamch=0; nend=pend; nstart=pstart; }
if(wr){
if((dpos>nend)&&(dpos<nstart))
{
xfad=fade; xpos=dpos;
if(sp>0.0) dpos=(dpos-nend)+nstart; else dpos=nend-(nstart-dpos);
}
}else{
if((dpos>nend)||(dpos<nstart))
{
xfad=fade; xpos=dpos;
if(sp>0.0) dpos=(dpos-nend)+nstart; else dpos=nend-(nstart-dpos);
}
}
}
else //if starting off outside of loop-boundaries, play until within...
{ //..and once within, save messages(pstart/pend) internally(nstart/nend)
if(wr)
{if((dpos<=pend)||(dpos>=pstart)){pparamch=0; inOderAus=1; nend=pend; nstart=pstart;}}
else
{if((dpos<=pend)&&(dpos>=pstart)){pparamch=0; inOderAus=1; nend=pend; nstart=pstart;}}
}
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(sp>0){ frac=dpos-indx; }else if(sp<0){ frac=1.0-(dpos-indx); }else frac=0.0; dpos+=sp;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
xR = interp(frac, b[indxz*bnc+1], b[indx*bnc+1], b[indxb*bnc+1], b[indxc*bnc+1]);
if(pfad>=0) //.......................Fade-In
{ oL=eas_func_up(xL,fade,pfad); oR=eas_func_up(xR,fade,pfad); pfad--; }
else if(xfad>=0)//..Crossfades(happen at loop-points,phase-changes,and abrupt pos/neg)
{
if(xpos>bframes)xpos-=(bframes+1); if(xpos<0)xpos+=(bframes+1); indx=trunc(xpos);
if(sp>0){frac=xpos-indx;}else if(sp<0){frac=1.0-(xpos-indx);}else frac=0.0;
xpos+=sp;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
oL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
oR = interp(frac, b[indxz*bnc+1], b[indx*bnc+1], b[indxb*bnc+1], b[indxc*bnc+1]);
oL = eas_func_up(xL, fade, xfad) + eas_func_dwn(oL, fade, xfad);
oR = eas_func_up(xR, fade, xfad) + eas_func_dwn(oR, fade, xfad); xfad--;
}else{ oL=xL; oR=xR; } //..<-Regular Playback
spprev=sp;
}
else
{ //......................................Fade-Out
if(pfad>=0)
{
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(spd>0){frac=dpos-indx;}else if(spd<0){frac=1.0-(dpos-indx);}else frac=0.0;
dpos+=spprev;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
xR = interp(frac, b[indxz*bnc+1], b[indx*bnc+1], b[indxb*bnc+1], b[indxc*bnc+1]);
oL = eas_func_dwn(xL, fade, pfad); oR = eas_func_dwn(xR, fade, pfad); pfad--;
if(pfad<0)spprev=sp;
}else{ oL = oR = 0.; spprev=sp; } //<-Everything Off
}
}
oPh=dpos/bframes; //<-convert samp-index 2 phase
*outL++ = oL; *outR++ = oR; *outPh++ = oPh;
}
buffer_unlocksamples(buffer); x->nshot=nshot; x->phprev=phprev; x->spprev=spprev;
x->pparamchange=pparamch; x->xfad=xfad; x->pfad=pfad; x->xpos=xpos;
x->dpos=dpos; x->inOderAus=inOderAus; x->nend=nend; x->nstart=nstart;
return;
zero: while(n--){ *outL++=0.; *outR++=0.; *outPh++=0.; }
}
void rez_rsperform64(t_rez *x, t_object *d64, double **is, long numis, double **os, long numos, long smps, long flgs, void *usrp)
{
t_double *rph = is[0];
t_double *rspd = is[1];
t_double *ovdb = is[2];
t_double *rinL = is[3];
t_double *rinR = is[4];
t_double *outRPh = os[0];
long n=smps; float *b;
t_double rcL,rcR,rpos,rxpos,rsp;
t_double oRPh,odb,rphprev,rinpos;
t_ptr_int rndx,rxdx,bnc,bframes,rstart,rend,nrstart,nrend,rfad,rxfad,fade,rs,rspprev;
t_bool rwr,rparamch,rinOderAus,wram,oneshot,rnshot;
t_buffer_obj *buffer=buffer_ref_getobject(x->buf);
b = buffer_locksamples(buffer); if(!b||x->obj.z_disabled) goto zero;
if(x->buf_modd){ x->buf_modd=false; rez_limits(x); } oneshot=x->oneshot;
bnc=x->bchan; bframes=x->bframes-1; fade=x->fade;
rpos=x->rpos; rparamch=x->rparamchange; rfad=x->rfad; rstart=x->rstart; rend=x->rend;
rnshot=x->rnshot; rphprev=x->rphprev; wram=x->wram; nrend=x->nrend; nrstart=x->nrstart;
rxfad=x->rxfad; rxpos=x->rxpos; rspprev=x->rspprev; rwr=x->rwr; rinOderAus=x->rinOderAus;
while(n--)
{
rinpos=*rph++; rsp=*rspd++; odb=*ovdb++; rcL=*rinL++; rcR=*rinR++;
rinpos=(rinpos<0.0)?0.0:((rinpos>1.0)?1.0:rinpos); rinpos*=bframes;
if(rsp>0.0) rs=1; else if(rsp<0.0) rs=-1; else rs=0;
//inOderAus(from SachaBaronCohen's "Bruno" skit)-flag indicates if position is 'in'/'out' of a loop..
//..if 'in' loop-boundary,save messages(pstart/pend/rstart/rend) internally(nstart/nend/nrstart/nrend)
if(oneshot)//ONESHOT_SECTION
{ //..........................ONESHOT-RECORDING
if((rspprev==0)&&(rs!=0))//on speed-change for 'on',check position from loop bounds..
{ //..setup fade-in/fade-out,internal one-shot flag(nshot),& pos/speed changes
rpos=rinpos; rfad=fade-1; wram=1; rnshot=1; rspprev=rs;
if(rwr)
{
if((rpos>(rend-fade))&&(rpos<(rstart+fade))){ rinOderAus=0; }
else { rinOderAus=1; nrstart=rstart; nrend=rend; }
}
else
{
if((rpos>(rend-fade))||(rpos<(rstart+fade))){ rinOderAus=0; }
else { rinOderAus=1; nrstart=rstart; nrend=rend; }
}
}
else if(((rspprev!=0)&&(rs==0)) && rnshot){ rfad=fade-1; rnshot=0; }
if(rnshot)//rnshot flag determines if the state is fading-in-recording/recording-regular..
{
if(rwr)
{
if((rpos<(rend-fade))||(rpos>(rstart+fade)))
{ rinOderAus=1; nrstart=rstart; nrend=rend; }
}
else
{
if((rpos<(rend-fade))&&(rpos>(rstart+fade)))
{ rinOderAus=1; nrstart=rstart; nrend=rend; }
}
if(rinOderAus)
{
if(rwr)
{ if((rpos>=(nrend-fade))&&(rpos<=(nrstart+fade))){ rfad=fade-1; rnshot=0; } }
else
{ if((rpos>=(nrend-fade))||(rpos<=(nrstart+fade))){ rfad=fade-1; rnshot=0; } }
}
//buffer~-boundary constraint, and positional-increment
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=rpos; rpos+=rs;
if(rfad>=0)//Fade-In
{
b[rndx*bnc]=eas_func_up(rcL,fade,rfad)+eas_rec_up(b[rndx*bnc],fade,1-odb,rfad);
b[rndx*bnc+1]=eas_func_up(rcR,fade,rfad)+eas_rec_up(b[rndx*bnc+1],fade,1-odb,rfad);
rfad--;
}else{ b[rndx*bnc]=rcL+(b[rndx*bnc]*odb); b[rndx*bnc+1]=rcR+(b[rndx*bnc+1]*odb); };
}
else //..or(when rnshot is 0, the state is) fading-out-recording/stopped-recording
{
if(rfad>=0)
{ //....buffer~-boundary constraint, and positional-increment
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=rpos; rpos+=rspprev;
b[rndx*bnc]=eas_func_dwn(rcL,fade,rfad)+eas_rec_dwn(b[rndx*bnc],fade,1-odb,rfad);
b[rndx*bnc+1]=eas_func_dwn(rcR,fade,rfad)+eas_rec_dwn(b[rndx*bnc+1],fade,1-odb,rfad);
rfad--; if(rfad<0) { wram=0; rspprev=rs; }
} else { rspprev=rs; }
}
}
else//LOOPER_(not_oneshot)_SECTION
{ //................................LOOPER-RECORDING
if((rs!=rspprev)&&(rfad<0))
{
if(((rspprev==0)&&(rs!=0))&&(rfad<0)){ rfad=fade-1; wram=1; rspprev=rs; }
else if (((rspprev!=0)&&(rs==0))&&(rfad<0)){ rfad=fade-1; }
else if(((rspprev<0)&&(rs>0))||((rspprev>0)&&(rs<0))){ rxfad=fade; rxpos=rpos; }
}
if(rs!=0)
{
if((rinpos!=rphprev)&&(rxfad<0))
{ //crossfade positional changes
if(rwr){ if((rinpos>nrend)&&(rinpos<nrstart))rinOderAus=0; else rinOderAus=1; }
else{ if((rinpos>nrend)||(rinpos<nrstart))rinOderAus=0; else rinOderAus=1; }
if(rfad<0){rxfad=fade; rxpos=rpos;} rphprev=rpos=rinpos;
}
if(rparamch)
{ //window changes
if(rwr){
if(((rpos>rend)&&(rpos<rstart))&&((rend>nrend)||(rstart<nrstart)))
rinOderAus=0; else rinOderAus=1;
}else{
if(((rpos>rend)||(rpos<rstart))&&((rend>nrend)||(rstart<nrstart)))
rinOderAus=0; else rinOderAus=1;
}
}
//recording-crossfade at loop boundaries
if((rinOderAus)&&(rxfad<0))
{ //rparamch = flag to notify when there's incoming..
if(rparamch){ rparamch=0; nrend=rend; nrstart=rstart; }//..message-set loop-bounds
if(rwr){
if((rpos>nrend)&&(rpos<nrstart))
{
rxfad=fade;
if(rs>0){ rpos=nrstart; rxpos=nrend; }else{ rpos=nrend; rxpos=nrstart;}
}
}else{
if((rpos>nrend)||(rpos<nrstart))
{
rxfad=fade;
if(rs>0){ rpos=nrstart; rxpos=nrend; }else{ rpos=nrend; rxpos=nrstart;}
}
}
}
else //if starting off outside of loop-boundaries, record until within...
{ //..and once within, save messages(rstart/rend) internally(nrstart/nrend)
if(rwr)
{if((rpos<=rend)||(rpos>=rstart))
{rparamch=0; rinOderAus=1; nrend=rend; nrstart=rstart;}}
else
{if((rpos<=rend)&&(rpos>=rstart))
{rparamch=0; rinOderAus=1; nrend=rend; nrstart=rstart;}}
}
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=trunc(rpos); rpos+=rs;
if(rxfad>=0) //....Crossfades(happen at loop-points and phase changes)
{ //crossfade-point buffer~-boundary constraint and increment
if(rxpos>bframes)rxpos=0; if(rxpos<0)rxpos=bframes; rxdx=trunc(rxpos); rxpos+=rs;
b[rxdx*bnc]=eas_func_dwn(rcL,fade,rxfad)+eas_rec_dwn(b[rxdx*bnc],fade,1-odb,rxfad);
b[rxdx*bnc+1]=eas_func_dwn(rcR,fade,rxfad)+eas_rec_dwn(b[rxdx*bnc+1],fade,1-odb,rxfad);
b[rndx*bnc]=eas_func_up(rcL,fade,rxfad)+eas_rec_up(b[rndx*bnc],fade,1-odb,rxfad);
b[rndx*bnc+1]=eas_func_up(rcR,fade,rxfad)+eas_rec_up(b[rndx*bnc+1],fade,1-odb,rxfad);
rxfad--;
}
else if(rfad>=0) //...................Fade-In
{
b[rndx*bnc]=eas_func_up(rcL,fade,rfad)+eas_rec_up(b[rndx*bnc],fade,1-odb,rfad);
b[rndx*bnc+1]=eas_func_up(rcR,fade,rfad)+eas_rec_up(b[rndx*bnc+1],fade,1-odb,rfad);rfad--;
} else { b[rndx*bnc]=rcL+(b[rndx*bnc]*odb); b[rndx*bnc+1]=rcR+(b[rndx*bnc+1]*odb); }
}
else
{ //...................................Fade-Out
if(rfad>=0)
{
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=trunc(rpos); rpos+=rspprev;
b[rndx*bnc]=eas_func_dwn(rcL,fade,rfad)+eas_rec_dwn(b[rndx*bnc],fade,1-odb,rfad);
b[rndx*bnc+1]=eas_func_dwn(rcR,fade,rfad)+eas_rec_dwn(b[rndx*bnc+1],fade,1-odb,rfad);
rfad--; if(rfad<0) { wram=0; rspprev=rs; }
}else{ rspprev=rs; }
}
}
oRPh=rpos/bframes;//<-convert samp-index 2 phase
*outRPh++ = oRPh;
}
if(wram)buffer_setdirty(buffer); buffer_unlocksamples(buffer); x->rnshot=rnshot; x->wram=wram;
x->rparamchange=rparamch; x->rphprev=rphprev; x->rspprev=rspprev; x->rxpos=rxpos; x->rxfad=rxfad;
x->rpos=rpos; x->rinOderAus=rinOderAus; x->rfad=rfad; x->nrend=nrend; x->nrstart=nrstart;
return;
zero: while(n--){ *outRPh++=0.; }
}
void rez_mperform64(t_rez *x, t_object *d64, double **is, long numis, double **os, long numos, long smps, long flgs, void *usrp)
{
t_double *ph = is[0];
t_double *spd = is[1];
t_double *rph = is[2];
t_double *rspd = is[3];
t_double *ovdb = is[4];
t_double *rinL = is[5];
t_double *outL = os[0];
t_double *outPh = os[1];
t_double *outRPh = os[2];
long n=smps; float *b;
t_double phprev,inpos,dpos,sp,rcL,frac,dfrnc,rpos,rxpos,rsp;
t_double spprev,oL,oPh,oRPh,xL,xpos,scldsr,odb,rphprev,rinpos;
t_ptr_int rndx,rxdx,bnc,bframes,pstart,pend,rstart,rend,nstart,nend,nrstart,nrend;
t_ptr_int indx,indxz,indxb,indxc,xfad,pfad,rfad,rxfad,fade,rs,rspprev;
t_bool wr,rwr,pparamch,rparamch,inOderAus,rinOderAus,wram,oneshot,nshot,rnshot;
t_buffer_obj *buffer=buffer_ref_getobject(x->buf);
b = buffer_locksamples(buffer); if(!b||x->obj.z_disabled) goto zero;
if(x->buf_modd){ x->buf_modd=false; rez_limits(x); } oneshot=x->oneshot; nshot=x->nshot;
bnc=x->bchan; bframes=x->bframes-1; pstart=x->pstart; pend=x->pend; inOderAus=x->inOderAus;
pparamch=x->pparamchange; pfad=x->pfad; xfad=x->xfad; fade=x->fade; xpos=x->xpos;
rpos=x->rpos; wr=x->wr; rparamch=x->rparamchange; rfad=x->rfad;
rstart=x->rstart; rend=x->rend; rnshot=x->rnshot; phprev=x->phprev; rphprev=x->rphprev;
spprev=x->spprev; dpos=x->dpos; wram=x->wram; scldsr=x->srscale;
nend=x->nend; nstart=x->nstart; nrend=x->nrend; nrstart=x->nrstart;
rxfad=x->rxfad; rxpos=x->rxpos; rspprev=x->rspprev; rwr=x->rwr; rinOderAus=x->rinOderAus;
while(n--)
{
inpos=*ph++; sp=*spd++; rinpos=*rph++; rsp=*rspd++; odb=*ovdb++; rcL=*rinL++;
inpos=(inpos<0.0)?0.0:((inpos>1.0)?1.0:inpos); inpos*=bframes; sp*=scldsr;
rinpos=(rinpos<0.0)?0.0:((rinpos>1.0)?1.0:rinpos); rinpos*=bframes;
if(rsp>0.0) rs=1; else if(rsp<0.0) rs=-1; else rs=0;
//inOderAus(from SachaBaronCohen's "Bruno" skit)-flag indicates if position is 'in'/'out' of a loop..
//..if 'in' loop-boundary,save messages(pstart/pend/rstart/rend) internally(nstart/nend/nrstart/nrend)
if(oneshot)//ONESHOT_SECTION
{ //..........................ONESHOT-RECORDING
if((rspprev==0)&&(rs!=0))//on speed-change for 'on',check position from loop bounds..
{ //..setup fade-in/fade-out,internal one-shot flag(nshot),& pos/speed changes
rpos=rinpos; rfad=fade-1; wram=1; rnshot=1; rspprev=rs;
if(rwr)
{
if((rpos>(rend-fade))&&(rpos<(rstart+fade))){ rinOderAus=0; }
else { rinOderAus=1; nrstart=rstart; nrend=rend; }
}
else
{
if((rpos>(rend-fade))||(rpos<(rstart+fade))){ rinOderAus=0; }
else { rinOderAus=1; nrstart=rstart; nrend=rend; }
}
}
else if(((rspprev!=0)&&(rs==0)) && rnshot){ rfad=fade-1; rnshot=0; }
if(rnshot)//rnshot flag determines if the state is fading-in-recording/recording-regular..
{
if(rwr)
{
if((rpos<(rend-fade))||(rpos>(rstart+fade)))
{ rinOderAus=1; nrstart=rstart; nrend=rend; }
}
else
{
if((rpos<(rend-fade))&&(rpos>(rstart+fade)))
{ rinOderAus=1; nrstart=rstart; nrend=rend; }
}
if(rinOderAus)
{
if(rwr)
{ if((rpos>=(nrend-fade))&&(rpos<=(nrstart+fade))){ rfad=fade-1; rnshot=0; } }
else
{ if((rpos>=(nrend-fade))||(rpos<=(nrstart+fade))){ rfad=fade-1; rnshot=0; } }
}
//buffer~-boundary constraint, and positional-increment
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=rpos; rpos+=rs;
if(rfad>=0)//Fade-In
{
b[rndx*bnc]=eas_func_up(rcL,fade,rfad)+eas_rec_up(b[rndx*bnc],fade,1-odb,rfad);
rfad--;
}else{ b[rndx*bnc]=rcL+(b[rndx*bnc]*odb); };
}
else //..or(when rnshot is 0, the state is) fading-out-recording/stopped-recording
{
if(rfad>=0)
{ //....buffer~-boundary constraint, and positional-increment
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=rpos; rpos+=rspprev;
b[rndx*bnc]=eas_func_dwn(rcL,fade,rfad)+eas_rec_dwn(b[rndx*bnc],fade,1-odb,rfad);
rfad--; if(rfad<0) { wram=0; rspprev=rs; }
} else { rspprev=rs; }
}
//......................................ONESHOT-PLAYBACK
if((spprev==0.0)&&(sp!=0.0))//on speed-change for 'on',check position from loop bounds..
{ //..setup fade-in/fade-out,internal one-shot flag(nshot),& position/speed changes
dpos=inpos; pfad=fade-1; nshot=1; spprev=sp;
if(wr)
{
if((dpos>(pend-fade))&&(dpos<(pstart+fade))){ inOderAus=0; }
else { inOderAus=1; nstart=pstart; nend=pend; }
}
else{ if((dpos>(pend-fade))||(dpos<(pstart+fade)))
{ inOderAus=0; }else{ inOderAus=1; nstart=pstart; nend=pend; } }
}
else if(((spprev!=0.0)&&(sp==0.0)) && nshot){ pfad=fade-1; nshot=0; }
if(nshot) //nshot flag determines if the state is fading-in/playing-back-regular..
{
if(wr)
{
if((dpos<(pend-fade))||(dpos>(pstart+fade)))
{ inOderAus=1; nstart=pstart; nend=pend; }
}
else
{
if((dpos<(pend-fade))&&(dpos>(pstart+fade)))
{ inOderAus=1; nstart=pstart; nend=pend; }
}
if(inOderAus)
{
if(wr){ if((dpos>=(nend-fade))&&(dpos<=(nstart+fade))){ pfad=fade-1; nshot=0; } }
else{ if((dpos>=(nend-fade))||(dpos<=(nstart+fade))){ pfad=fade-1; nshot=0; } }
}
//buffer~-boundary constraint, positional-increment, and bicubic interpolation
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(sp>0){frac=dpos-indx;}else if(sp<0){frac=1.0-(dpos-indx);}else frac=0.0; dpos+=sp;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
//fade-in
if(pfad>=0){ oL=eas_func_up(xL,fade,pfad); pfad--; }
else{ oL=xL; }
}
else //..or(when nshot is 0, the state is) fading-out/silenced
{//fade-Out
if(pfad>=0)
{ //buffer~-boundary constraint, positional-increment, and bicubic interpolation
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(spd>0){frac=dpos-indx;}else if(spd<0){frac=1.0-(dpos-indx);}else frac=0.0;
dpos+=spprev;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
oL = eas_func_dwn(xL, fade, pfad);
pfad--; if(pfad<0)spprev=sp;
}else{ oL = 0.; spprev=sp; } //.........<-Everything Off
}
}
else//LOOPER_(not_oneshot)_SECTION
{ //................................LOOPER-RECORDING
if((rs!=rspprev)&&(rfad<0))
{
if(((rspprev==0)&&(rs!=0))&&(rfad<0)){ rfad=fade-1; wram=1; rspprev=rs; }
else if (((rspprev!=0)&&(rs==0))&&(rfad<0)){ rfad=fade-1; }
else if(((rspprev<0)&&(rs>0))||((rspprev>0)&&(rs<0))){ rxfad=fade; rxpos=rpos; }
}
if(rs!=0)
{
if((rinpos!=rphprev)&&(rxfad<0))
{ //crossfade positional changes
if(rwr){ if((rinpos>nrend)&&(rinpos<nrstart))rinOderAus=0; else rinOderAus=1; }
else{ if((rinpos>nrend)||(rinpos<nrstart))rinOderAus=0; else rinOderAus=1; }
if(rfad<0){rxfad=fade; rxpos=rpos;} rphprev=rpos=rinpos;
}
if(rparamch)
{ //window changes
if(rwr){
if(((rpos>rend)&&(rpos<rstart))&&((rend>nrend)||(rstart<nrstart)))
rinOderAus=0; else rinOderAus=1;
}else{
if(((rpos>rend)||(rpos<rstart))&&((rend>nrend)||(rstart<nrstart)))
rinOderAus=0; else rinOderAus=1;
}
}
//recording-crossfade at loop boundaries
if((rinOderAus)&&(rxfad<0))
{ //rparamch = flag to notify when there's incoming..
if(rparamch){ rparamch=0; nrend=rend; nrstart=rstart; }//..message-set loop-bounds
if(rwr){
if((rpos>nrend)&&(rpos<nrstart))
{
rxfad=fade;
if(rs>0){ rpos=nrstart; rxpos=nrend; }else{ rpos=nrend; rxpos=nrstart;}
}
}else{
if((rpos>nrend)||(rpos<nrstart))
{
rxfad=fade;
if(rs>0){ rpos=nrstart; rxpos=nrend; }else{ rpos=nrend; rxpos=nrstart;}
}
}
}
else //if starting off outside of loop-boundaries, record until within...
{ //..and once within, save messages(rstart/rend) internally(nrstart/nrend)
if(rwr)
{if((rpos<=rend)||(rpos>=rstart))
{rparamch=0; rinOderAus=1; nrend=rend; nrstart=rstart;}}
else
{if((rpos<=rend)&&(rpos>=rstart))
{rparamch=0; rinOderAus=1; nrend=rend; nrstart=rstart;}}
}
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=trunc(rpos); rpos+=rs;
if(rxfad>=0) //....Crossfades(happen at loop-points and phase changes)
{ //crossfade-point buffer~-boundary constraint and increment
if(rxpos>bframes)rxpos=0; if(rxpos<0)rxpos=bframes; rxdx=trunc(rxpos); rxpos+=rs;
b[rxdx*bnc]=eas_func_dwn(rcL,fade,rxfad)+eas_rec_dwn(b[rxdx*bnc],fade,1-odb,rxfad);
b[rndx*bnc]=eas_func_up(rcL,fade,rxfad)+eas_rec_up(b[rndx*bnc],fade,1-odb,rxfad);
rxfad--;
}
else if(rfad>=0) //...................Fade-In
{
b[rndx*bnc]=eas_func_up(rcL,fade,rfad)+eas_rec_up(b[rndx*bnc],fade,1-odb,rfad);
rfad--;
} else { b[rndx*bnc]=rcL+(b[rndx*bnc]*odb); }
}
else
{ //...................................Fade-Out
if(rfad>=0)
{
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=trunc(rpos); rpos+=rspprev;
b[rndx*bnc]=eas_func_dwn(rcL,fade,rfad)+eas_rec_dwn(b[rndx*bnc],fade,1-odb,rfad);
rfad--; if(rfad<0) { wram=0; rspprev=rs; }
}else{ rspprev=rs; }
}
//.....................................LOOPER-PLAYBACK
if((sp!=spprev)&&(xfad<0))
{if((((spprev==0.0)&&(sp!=0.0))||((spprev!=0.0)&&(sp==0.0)))&&(pfad<0)){pfad=fade;}//onoff
else if(((spprev<0)&&(sp>0))||((spprev>0)&&(sp<0))){xfad=fade;xpos=dpos;}}//xfad neg<->pos
if(sp!=0.0)
{
if((inpos!=phprev)&&(xfad<0))
{ //crossfade positional changes
if(wr){ if((inpos>nend)&&(inpos<nstart))inOderAus=0; else inOderAus=1; }
else{ if((inpos>nend)||(inpos<nstart))inOderAus=0; else inOderAus=1; }
if(pfad<0){xfad=fade; xpos=dpos;} phprev=dpos=inpos;
}
if(pparamch)
{ //window changes
if(wr){
if(((dpos>pend)&&(dpos<pstart))&&((pend>nend)||(pstart<nstart)))
inOderAus=0; else inOderAus=1;
}else{
if(((dpos>pend)||(dpos<pstart))&&((pend>nend)||(pstart<nstart)))
inOderAus=0; else inOderAus=1;
}
}
//crossfade at playback-loop boundaries
if((inOderAus)&&(xfad<0))
{
if(pparamch){ pparamch=0; nend=pend; nstart=pstart; }
if(wr){
if((dpos>nend)&&(dpos<nstart))
{
xfad=fade; xpos=dpos;
if(sp>0.0) dpos=(dpos-nend)+nstart; else dpos=nend-(nstart-dpos);
}
}else{
if((dpos>nend)||(dpos<nstart))
{
xfad=fade; xpos=dpos;
if(sp>0.0) dpos=(dpos-nend)+nstart; else dpos=nend-(nstart-dpos);
}
}
}
else //if starting off outside of loop-boundaries, play until within...
{ //..and once within, save messages(pstart/pend) internally(nstart/nend)
if(wr)
{if((dpos<=pend)||(dpos>=pstart)){pparamch=0; inOderAus=1; nend=pend; nstart=pstart;}}
else
{if((dpos<=pend)&&(dpos>=pstart)){pparamch=0; inOderAus=1; nend=pend; nstart=pstart;}}
}
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(sp>0){ frac=dpos-indx; }else if(sp<0){ frac=1.0-(dpos-indx); }else frac=0.0; dpos+=sp;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
if(pfad>=0) //.......................Fade-In
{ oL=eas_func_up(xL,fade,pfad); pfad--; }
else if(xfad>=0)//..Crossfades(happen at loop-points,phase-changes,and abrupt pos/neg)
{
if(xpos>bframes)xpos-=(bframes+1); if(xpos<0)xpos+=(bframes+1); indx=trunc(xpos);
if(sp>0){frac=xpos-indx;}else if(sp<0){frac=1.0-(xpos-indx);}else frac=0.0;
xpos+=sp;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
oL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
oL = eas_func_up(xL, fade, xfad) + eas_func_dwn(oL, fade, xfad); xfad--;
}else{ oL=xL; } //..<-Regular Playback
spprev=sp;
}
else
{ //......................................Fade-Out
if(pfad>=0)
{
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(spd>0){frac=dpos-indx;}else if(spd<0){frac=1.0-(dpos-indx);}else frac=0.0;
dpos+=spprev;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
oL = eas_func_dwn(xL, fade, pfad); pfad--;
if(pfad<0)spprev=sp;
}else{ oL = 0.; spprev=sp; } //<-Everything Off
}
if(wram) //..calculate abs-difference between playhead and recordhead..
{ //..if difference is within fade time, use difference to drive ducking of playhead
if(sp!=(double)rs)
{
dfrnc = fabs(rpos-dpos);
if(dfrnc<(fade*2.7489)){ oL=eas_func_dwn(oL,(fade*2.7489),dfrnc); }
}
}
}
oPh=dpos/bframes; oRPh=rpos/bframes;//<-convert samp-index 2 phase
*outL++ = oL; *outPh++ = oPh; *outRPh++ = oRPh;
}
if(wram)buffer_setdirty(buffer); buffer_unlocksamples(buffer); x->nshot=nshot; x->rnshot=rnshot;
x->pparamchange=pparamch; x->rparamchange=rparamch; x->xfad=xfad; x->pfad=pfad; x->xpos=xpos;
x->phprev=phprev; x->rphprev=rphprev; x->spprev=spprev; x->rspprev=rspprev; x->rxpos=rxpos;
x->dpos=dpos; x->rpos=rpos; x->inOderAus=inOderAus; x->rinOderAus=rinOderAus; x->rfad=rfad;
x->nend=nend; x->nstart=nstart; x->nrend=nrend; x->nrstart=nrstart; x->rxfad=rxfad; x->wram=wram;
return;
zero: while(n--){ *outL++=0.; *outPh++=0.; *outRPh++=0.; }
}
void rez_pmperform64(t_rez *x, t_object *d64, double **is, long numis, double **os, long numos, long smps, long flgs, void *usrp)
{
t_double *ph = is[0];
t_double *spd = is[1];
t_double *outL = os[0];
t_double *outPh = os[1];
long n=smps; float *b;
t_double phprev,inpos,dpos,sp,frac,spprev,oL,oPh,xL,xpos,scldsr;
t_ptr_int bnc,bframes,pstart,pend,nstart,nend,indx,indxz,indxb,indxc,xfad,pfad,fade;
t_bool wr,pparamch,inOderAus,oneshot,nshot;
t_buffer_obj *buffer=buffer_ref_getobject(x->buf);
b = buffer_locksamples(buffer); if(!b||x->obj.z_disabled) goto zero;
if(x->buf_modd){ x->buf_modd=false; rez_limits(x); } oneshot=x->oneshot; nshot=x->nshot; wr=x->wr;
bnc=x->bchan; bframes=x->bframes-1; pstart=x->pstart; pend=x->pend; inOderAus=x->inOderAus;
pparamch=x->pparamchange; pfad=x->pfad; xfad=x->xfad; fade=x->fade; xpos=x->xpos; nstart=x->nstart;
phprev=x->phprev; spprev=x->spprev; dpos=x->dpos; scldsr=x->srscale; nend=x->nend;
while(n--)
{
inpos=*ph++; sp=*spd++;
inpos=(inpos<0.0)?0.0:((inpos>1.0)?1.0:inpos); inpos*=bframes; sp*=scldsr;
//inOderAus(from SachaBaronCohen's "Bruno" skit)-flag indicates if position is 'in'/'out' of a loop..
//..if 'in' loop-boundary,save messages(pstart/pend) internally(nstart/nend)
if(oneshot)//ONESHOT_SECTION
{ //......................................ONESHOT-PLAYBACK
if((spprev==0.0)&&(sp!=0.0))//on speed-change for 'on',check position from loop bounds..
{ //..setup fade-in/fade-out,internal one-shot flag(nshot),& position/speed changes
dpos=inpos; pfad=fade-1; nshot=1; spprev=sp;
if(wr)
{
if((dpos>(pend-fade))&&(dpos<(pstart+fade))){ inOderAus=0; }
else { inOderAus=1; nstart=pstart; nend=pend; }
}
else{ if((dpos>(pend-fade))||(dpos<(pstart+fade)))
{ inOderAus=0; }else{ inOderAus=1; nstart=pstart; nend=pend; } }
}
else if(((spprev!=0.0)&&(sp==0.0)) && nshot){ pfad=fade-1; nshot=0; }
if(nshot) //nshot flag determines if the state is fading-in/playing-back-regular..
{
if(wr)
{
if((dpos<(pend-fade))||(dpos>(pstart+fade)))
{ inOderAus=1; nstart=pstart; nend=pend; }
}
else
{
if((dpos<(pend-fade))&&(dpos>(pstart+fade)))
{ inOderAus=1; nstart=pstart; nend=pend; }
}
if(inOderAus)
{
if(wr){ if((dpos>=(nend-fade))&&(dpos<=(nstart+fade))){ pfad=fade-1; nshot=0; } }
else{ if((dpos>=(nend-fade))||(dpos<=(nstart+fade))){ pfad=fade-1; nshot=0; } }
}
//buffer~-boundary constraint, positional-increment, and bicubic interpolation
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(sp>0){frac=dpos-indx;}else if(sp<0){frac=1.0-(dpos-indx);}else frac=0.0; dpos+=sp;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
//fade-in
if(pfad>=0){ oL=eas_func_up(xL,fade,pfad); pfad--; }
else{ oL=xL; }
}
else //..or(when nshot is 0, the state is) fading-out/silenced
{//fade-Out
if(pfad>=0)
{ //buffer~-boundary constraint, positional-increment, and bicubic interpolation
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(spd>0){frac=dpos-indx;}else if(spd<0){frac=1.0-(dpos-indx);}else frac=0.0;
dpos+=spprev;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
oL = eas_func_dwn(xL, fade, pfad);
pfad--; if(pfad<0)spprev=sp;
}else{ oL = 0.; spprev=sp; } //.........<-Everything Off
}
}
else//LOOPER_(not_oneshot)_SECTION
{ //.....................................LOOPER-PLAYBACK
if((sp!=spprev)&&(xfad<0))
{if((((spprev==0.0)&&(sp!=0.0))||((spprev!=0.0)&&(sp==0.0)))&&(pfad<0)){pfad=fade;}//onoff
else if(((spprev<0)&&(sp>0))||((spprev>0)&&(sp<0))){xfad=fade;xpos=dpos;}}//xfad neg<->pos
if(sp!=0.0)
{
if((inpos!=phprev)&&(xfad<0))
{ //crossfade positional changes
if(wr){ if((inpos>nend)&&(inpos<nstart))inOderAus=0; else inOderAus=1; }
else{ if((inpos>nend)||(inpos<nstart))inOderAus=0; else inOderAus=1; }
if(pfad<0){xfad=fade; xpos=dpos;} phprev=dpos=inpos;
}
if(pparamch)
{ //window changes
if(wr){
if(((dpos>pend)&&(dpos<pstart))&&((pend>nend)||(pstart<nstart)))
inOderAus=0; else inOderAus=1;
}else{
if(((dpos>pend)||(dpos<pstart))&&((pend>nend)||(pstart<nstart)))
inOderAus=0; else inOderAus=1;
}
}
//crossfade at playback-loop boundaries
if((inOderAus)&&(xfad<0))
{
if(pparamch){ pparamch=0; nend=pend; nstart=pstart; }
if(wr){
if((dpos>nend)&&(dpos<nstart))
{
xfad=fade; xpos=dpos;
if(sp>0.0) dpos=(dpos-nend)+nstart; else dpos=nend-(nstart-dpos);
}
}else{
if((dpos>nend)||(dpos<nstart))
{
xfad=fade; xpos=dpos;
if(sp>0.0) dpos=(dpos-nend)+nstart; else dpos=nend-(nstart-dpos);
}
}
}
else //if starting off outside of loop-boundaries, play until within...
{ //..and once within, save messages(pstart/pend) internally(nstart/nend)
if(wr)
{if((dpos<=pend)||(dpos>=pstart)){pparamch=0; inOderAus=1; nend=pend; nstart=pstart;}}
else
{if((dpos<=pend)&&(dpos>=pstart)){pparamch=0; inOderAus=1; nend=pend; nstart=pstart;}}
}
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(sp>0){ frac=dpos-indx; }else if(sp<0){ frac=1.0-(dpos-indx); }else frac=0.0; dpos+=sp;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
if(pfad>=0) //.......................Fade-In
{ oL=eas_func_up(xL,fade,pfad); pfad--; }
else if(xfad>=0)//..Crossfades(happen at loop-points,phase-changes,and abrupt pos/neg)
{
if(xpos>bframes)xpos-=(bframes+1); if(xpos<0)xpos+=(bframes+1); indx=trunc(xpos);
if(sp>0){frac=xpos-indx;}else if(sp<0){frac=1.0-(xpos-indx);}else frac=0.0;
xpos+=sp;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
oL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
oL = eas_func_up(xL, fade, xfad) + eas_func_dwn(oL, fade, xfad); xfad--;
}else{ oL=xL; } //..<-Regular Playback
spprev=sp;
}
else
{ //......................................Fade-Out
if(pfad>=0)
{
if(dpos>bframes)dpos-=(bframes+1); if(dpos<0)dpos+=(bframes+1); indx=trunc(dpos);
if(spd>0){frac=dpos-indx;}else if(spd<0){frac=1.0-(dpos-indx);}else frac=0.0;
dpos+=spprev;
interp_index(indx,&indxz,&indxb,&indxc,sp,bframes);
xL = interp(frac, b[indxz*bnc], b[indx*bnc], b[indxb*bnc], b[indxc*bnc]);
oL = eas_func_dwn(xL, fade, pfad); pfad--;
if(pfad<0)spprev=sp;
}else{ oL = 0.; spprev=sp; } //<-Everything Off
}
}
oPh=dpos/bframes; //<-convert samp-index 2 phase
*outL++ = oL; *outPh++ = oPh;
}
buffer_unlocksamples(buffer); x->nshot=nshot; x->pparamchange=pparamch; x->xfad=xfad;
x->pfad=pfad; x->xpos=xpos; x->phprev=phprev; x->spprev=spprev; x->dpos=dpos;
x->inOderAus=inOderAus; x->nend=nend; x->nstart=nstart;
return;
zero: while(n--){ *outL++=0.; *outPh++=0.; }
}
void rez_rmperform64(t_rez *x, t_object *d64, double **is, long numis, double **os, long numos, long smps, long flgs, void *usrp)
{
t_double *rph = is[0];
t_double *rspd = is[1];
t_double *ovdb = is[2];
t_double *rinL = is[3];
t_double *outRPh = os[0];
long n=smps; float *b;
t_double rcL,rpos,rxpos,rsp,oRPh,odb,rphprev,rinpos;
t_ptr_int rndx,rxdx,bnc,bframes,rstart,rend,nrstart,nrend,rfad,rxfad,fade,rs,rspprev;
t_bool rwr,rparamch,rinOderAus,wram,oneshot,rnshot;
t_buffer_obj *buffer=buffer_ref_getobject(x->buf);
b = buffer_locksamples(buffer); if(!b||x->obj.z_disabled) goto zero;
if(x->buf_modd){ x->buf_modd=false; rez_limits(x); } oneshot=x->oneshot;
bnc=x->bchan; bframes=x->bframes-1; fade=x->fade; rpos=x->rpos; rparamch=x->rparamchange;
rfad=x->rfad; rstart=x->rstart; rend=x->rend; rnshot=x->rnshot; rphprev=x->rphprev;
wram=x->wram; nrend=x->nrend; nrstart=x->nrstart; rxfad=x->rxfad; rxpos=x->rxpos;
rspprev=x->rspprev; rwr=x->rwr; rinOderAus=x->rinOderAus;
while(n--)
{
rinpos=*rph++; rsp=*rspd++; odb=*ovdb++; rcL=*rinL++;
rinpos=(rinpos<0.0)?0.0:((rinpos>1.0)?1.0:rinpos); rinpos*=bframes;
if(rsp>0.0) rs=1; else if(rsp<0.0) rs=-1; else rs=0;
//inOderAus(from SachaBaronCohen's "Bruno" skit)-flag indicates if position is 'in'/'out' of a loop..
//..if 'in' loop-boundary,save messages(pstart/pend/rstart/rend) internally(nstart/nend/nrstart/nrend)
if(oneshot)//ONESHOT_SECTION
{ //..........................ONESHOT-RECORDING
if((rspprev==0)&&(rs!=0))//on speed-change for 'on',check position from loop bounds..
{ //..setup fade-in/fade-out,internal one-shot flag(nshot),& pos/speed changes
rpos=rinpos; rfad=fade-1; wram=1; rnshot=1; rspprev=rs;
if(rwr)
{
if((rpos>(rend-fade))&&(rpos<(rstart+fade))){ rinOderAus=0; }
else { rinOderAus=1; nrstart=rstart; nrend=rend; }
}
else
{
if((rpos>(rend-fade))||(rpos<(rstart+fade))){ rinOderAus=0; }
else { rinOderAus=1; nrstart=rstart; nrend=rend; }
}
}
else if(((rspprev!=0)&&(rs==0)) && rnshot){ rfad=fade-1; rnshot=0; }
if(rnshot)//rnshot flag determines if the state is fading-in-recording/recording-regular..
{
if(rwr)
{
if((rpos<(rend-fade))||(rpos>(rstart+fade)))
{ rinOderAus=1; nrstart=rstart; nrend=rend; }
}
else
{
if((rpos<(rend-fade))&&(rpos>(rstart+fade)))
{ rinOderAus=1; nrstart=rstart; nrend=rend; }
}
if(rinOderAus)
{
if(rwr)
{ if((rpos>=(nrend-fade))&&(rpos<=(nrstart+fade))){ rfad=fade-1; rnshot=0; } }
else
{ if((rpos>=(nrend-fade))||(rpos<=(nrstart+fade))){ rfad=fade-1; rnshot=0; } }
}
//buffer~-boundary constraint, and positional-increment
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=rpos; rpos+=rs;
if(rfad>=0)//Fade-In
{
b[rndx*bnc]=eas_func_up(rcL,fade,rfad)+eas_rec_up(b[rndx*bnc],fade,1-odb,rfad);
rfad--;
}else{ b[rndx*bnc]=rcL+(b[rndx*bnc]*odb); };
}
else //..or(when rnshot is 0, the state is) fading-out-recording/stopped-recording
{
if(rfad>=0)
{ //....buffer~-boundary constraint, and positional-increment
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=rpos; rpos+=rspprev;
b[rndx*bnc]=eas_func_dwn(rcL,fade,rfad)+eas_rec_dwn(b[rndx*bnc],fade,1-odb,rfad);
rfad--; if(rfad<0) { wram=0; rspprev=rs; }
} else { rspprev=rs; }
}
}
else//LOOPER_(not_oneshot)_SECTION
{ //................................LOOPER-RECORDING
if((rs!=rspprev)&&(rfad<0))
{
if(((rspprev==0)&&(rs!=0))&&(rfad<0)){ rfad=fade-1; wram=1; rspprev=rs; }
else if (((rspprev!=0)&&(rs==0))&&(rfad<0)){ rfad=fade-1; }
else if(((rspprev<0)&&(rs>0))||((rspprev>0)&&(rs<0))){ rxfad=fade; rxpos=rpos; }
}
if(rs!=0)
{
if((rinpos!=rphprev)&&(rxfad<0))
{ //crossfade positional changes
if(rwr){ if((rinpos>nrend)&&(rinpos<nrstart))rinOderAus=0; else rinOderAus=1; }
else{ if((rinpos>nrend)||(rinpos<nrstart))rinOderAus=0; else rinOderAus=1; }
if(rfad<0){rxfad=fade; rxpos=rpos;} rphprev=rpos=rinpos;
}
if(rparamch)
{ //window changes
if(rwr){
if(((rpos>rend)&&(rpos<rstart))&&((rend>nrend)||(rstart<nrstart)))
rinOderAus=0; else rinOderAus=1;
}else{
if(((rpos>rend)||(rpos<rstart))&&((rend>nrend)||(rstart<nrstart)))
rinOderAus=0; else rinOderAus=1;
}
}
//recording-crossfade at loop boundaries
if((rinOderAus)&&(rxfad<0))
{ //rparamch = flag to notify when there's incoming..
if(rparamch){ rparamch=0; nrend=rend; nrstart=rstart; }//..message-set loop-bounds
if(rwr){
if((rpos>nrend)&&(rpos<nrstart))
{
rxfad=fade;
if(rs>0){ rpos=nrstart; rxpos=nrend; }else{ rpos=nrend; rxpos=nrstart;}
}
}else{
if((rpos>nrend)||(rpos<nrstart))
{
rxfad=fade;
if(rs>0){ rpos=nrstart; rxpos=nrend; }else{ rpos=nrend; rxpos=nrstart;}
}
}
}
else //if starting off outside of loop-boundaries, record until within...
{ //..and once within, save messages(rstart/rend) internally(nrstart/nrend)
if(rwr)
{if((rpos<=rend)||(rpos>=rstart))
{rparamch=0; rinOderAus=1; nrend=rend; nrstart=rstart;}}
else
{if((rpos<=rend)&&(rpos>=rstart))
{rparamch=0; rinOderAus=1; nrend=rend; nrstart=rstart;}}
}
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=trunc(rpos); rpos+=rs;
if(rxfad>=0) //....Crossfades(happen at loop-points and phase changes)
{ //crossfade-point buffer~-boundary constraint and increment
if(rxpos>bframes)rxpos=0; if(rxpos<0)rxpos=bframes; rxdx=trunc(rxpos); rxpos+=rs;
b[rxdx*bnc]=eas_func_dwn(rcL,fade,rxfad)+eas_rec_dwn(b[rxdx*bnc],fade,1-odb,rxfad);
b[rndx*bnc]=eas_func_up(rcL,fade,rxfad)+eas_rec_up(b[rndx*bnc],fade,1-odb,rxfad);
rxfad--;
}
else if(rfad>=0) //...................Fade-In
{
b[rndx*bnc]=eas_func_up(rcL,fade,rfad)+eas_rec_up(b[rndx*bnc],fade,1-odb,rfad);
rfad--;
} else { b[rndx*bnc]=rcL+(b[rndx*bnc]*odb); }
}
else
{ //...................................Fade-Out
if(rfad>=0)
{
if(rpos>bframes)rpos=0; if(rpos<0)rpos=bframes; rndx=trunc(rpos); rpos+=rspprev;
b[rndx*bnc]=eas_func_dwn(rcL,fade,rfad)+eas_rec_dwn(b[rndx*bnc],fade,1-odb,rfad);
rfad--; if(rfad<0) { wram=0; rspprev=rs; }
}else{ rspprev=rs; }
}
}
oRPh=rpos/bframes;//<-convert samp-index 2 phase
*outRPh++ = oRPh;
}
if(wram)buffer_setdirty(buffer); buffer_unlocksamples(buffer); x->rnshot=rnshot; x->wram=wram;
x->rparamchange=rparamch; x->rphprev=rphprev; x->rspprev=rspprev; x->rxpos=rxpos; x->rfad=rfad;
x->rpos=rpos; x->rinOderAus=rinOderAus; x->nrend=nrend; x->nrstart=nrstart; x->rxfad=rxfad;
return;
zero: while(n--){ *outRPh++=0.; }
}