From eba585829684fcf54a0c8614709d2c10c75032b4 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Sat, 8 Jan 2005 04:59:44 +0000 Subject: merge in branch "20041229-unify" - some small cleanups os x fixes minor updates improved buffer handling simplify updates Mac adaptations - made xcode project preparing xsample 0.3.0 release updated for build system some optimizations - fixed loop record bug Completion of attribute functionality, revisited and updated help files svn path=/trunk/; revision=2477 --- externals/grill/xsample/source/inter.h | 511 +++++++++++++++++++++++---------- 1 file changed, 353 insertions(+), 158 deletions(-) (limited to 'externals/grill/xsample/source/inter.h') diff --git a/externals/grill/xsample/source/inter.h b/externals/grill/xsample/source/inter.h index e3bdd5c8..d0ab3994 100755 --- a/externals/grill/xsample/source/inter.h +++ b/externals/grill/xsample/source/inter.h @@ -1,225 +1,420 @@ /* - xsample - extended sample objects for Max/MSP and pd (pure data) -Copyright (c) 2001-2004 Thomas Grill (xovo@gmx.net) +Copyright (c) 2001-2005 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. - */ #ifndef __INTER_H #define __INTER_H -TMPLDEF V xinter::st_play0(const S *,const I ,const I ,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) +TMPLDEF void xinter::st_play0(const t_sample *,const int ,const int ,const int n,const int inchns,const int outchns,t_sample *const *invecs,t_sample *const *outvecs,bool looped) { // stopped/invalid buffer -> output zero - for(I ci = 0; ci < outchns; ++ci) ZeroSamples(outvecs[ci],n); + for(int ci = 0; ci < outchns; ++ci) ZeroSamples(outvecs[ci],n); } -TMPLDEF V xinter::st_play1(const S *bdt,const I smin,const I smax,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) +TMPLDEF void xinter::st_play1(const t_sample *bdt,const int smin,const int smax,const int n,const int inchns,const int outchns,t_sample *const *invecs,t_sample *const *outvecs,bool looped) { SIGCHNS(BCHNS,inchns,OCHNS,outchns); // position info are frame units - const S *pos = invecs[0]; - S *const *sig = outvecs; - register I si = 0; + const t_sample *pos = invecs[0]; + t_sample *const *sig = outvecs; // no interpolation // ---------------- - - for(I i = 0; i < n; ++i,++si) { - register const I oint = (I)(*(pos++)); - register const S *fp; - - if(oint >= smin) - if(oint < smax) { - // normal - fp = bdt+oint*BCHNS; - } - else { - // position > last sample ... take only last sample - fp = bdt+(smin == smax?smin:smax-1)*BCHNS; - } - else { - // position < 0 ... take only 0th sample - fp = bdt+smin*BCHNS; - } - - for(I ci = 0; ci < OCHNS; ++ci) - sig[ci][si] = fp[ci]; - } - // clear rest of output channels (if buffer has less channels) - for(I ci = OCHNS; ci < outchns; ++ci) ZeroSamples(sig[ci],n); + if(smin == smax) { + // zero loop length -> assume that smin is a valid sample position... + + int ci; + for(ci = 0; ci < OCHNS; ++ci) SetSamples(sig[ci],n,bdt[smin*BCHNS]); + // clear rest of output channels (if buffer has less channels) + for(; ci < outchns; ++ci) ZeroSamples(sig[ci],n); + } + else if(OCHNS == 1) { + t_sample *sig0 = sig[0]; + for(int i = 0; i < n; ++i) { + register long oint = CASTINT(*(pos++)); + + // for xplay oint can be out of bounds -> check + if(oint >= smin) + if(oint < smax) { + // normal + *(sig0++) = bdt[oint*BCHNS]; + } + else { + // position > last sample ... take only last sample + *(sig0++) = bdt[(smax-1)*BCHNS]; + } + else { + // position < 0 ... take only 0th sample + *(sig0++) = bdt[smin*BCHNS]; + } + } + } + else { + for(int i = 0,si = 0; i < n; ++i,++si) { + register long oint = CASTINT(*(pos++)); + register const t_sample *fp; + + // for xplay oint can be out of bounds -> check + if(oint >= smin) + if(oint < smax) { + // normal + fp = bdt+oint*BCHNS; + } + else { + // position > last sample ... take only last sample + fp = bdt+(smax-1)*BCHNS; + } + else { + // position < 0 ... take only 0th sample + fp = bdt+smin*BCHNS; + } + + for(int ci = 0; ci < OCHNS; ++ci) + sig[ci][si] = fp[ci]; + } + + // clear rest of output channels (if buffer has less channels) + for(int ci = OCHNS; ci < outchns; ++ci) ZeroSamples(sig[ci],n); + } } -TMPLDEF V xinter::st_play2(const S *bdt,const I smin,const I smax,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) +TMPLDEF void xinter::st_play2(const t_sample *bdt,const int smin,const int smax,const int n,const int inchns,const int outchns,t_sample *const *invecs,t_sample *const *outvecs,bool looped) { - const I plen = smax-smin; //curlen; + const int plen = smax-smin; if(plen < 2) { - st_play1 TMPLCALL (bdt,smin,smax,n,inchns,outchns,invecs,outvecs); + st_play1 TMPLCALL (bdt,smin,smax,n,inchns,outchns,invecs,outvecs,looped); return; } SIGCHNS(BCHNS,inchns,OCHNS,outchns); // position info are frame units - const S *pos = invecs[0]; - S *const *sig = outvecs; - register I si = 0; + const t_sample *pos = invecs[0]; + t_sample *const *sig = outvecs; // linear interpolation // -------------------- - const I maxo = smax-1; // last sample in buffer - - for(I i = 0; i < n; ++i,++si) { - const F o = *(pos++); - register const I oint = (I)o; - - if(oint >= smin) - if(oint < maxo) { - // normal interpolation - register const F frac = o-oint; - register const S *const fp0 = bdt+oint*BCHNS; - register const S *const fp1 = fp0+BCHNS; - for(I ci = 0; ci < OCHNS; ++ci) - sig[ci][si] = fp0[ci]+frac*(fp1[ci]-fp0[ci]); - } - else { - // position is past last sample -> take the last sample - register const S *const fp = bdt+maxo*BCHNS; - for(I ci = 0; ci < OCHNS; ++ci) - sig[ci][si] = fp[ci]; - } - else { - // position is before first sample -> take the first sample - register const S *const fp = bdt+smin*BCHNS; - for(I ci = 0; ci < OCHNS; ++ci) - sig[ci][si] = fp[ci]; - } - } + const int maxo = smax-1; // last sample in buffer + + if(OCHNS == 1) { + t_sample *sig0 = sig[0]; + for(int i = 0; i < n; ++i) { + const float o = *(pos++); + register long oint = CASTINT(o); + const float frac = o-oint; + t_sample fp0,fp1; + + if(oint >= smin) + if(oint < maxo) { + // normal interpolation + fp0 = bdt[oint*BCHNS]; + fp1 = bdt[(oint+1)*BCHNS]; + } + else { + // position is past last sample + if(looped) { + oint = smin+(oint-smin)%plen; + fp0 = bdt[oint*BCHNS]; + fp1 = oint >= maxo?bdt[smin]:fp0; + } + else + fp0 = fp1 = bdt[maxo*BCHNS]; + } + else { + // position is before first sample + if(looped) { + oint = smax-(smin-oint)%plen; + fp0 = bdt[oint*BCHNS]; + fp1 = oint >= maxo?bdt[smin]:fp0; + } + else + fp0 = fp1 = bdt[smin*BCHNS]; + } + + *(sig0++) = fp0+frac*(fp1-fp0); + } + } + else { + for(int i = 0,si = 0; i < n; ++i,++si) { + const float o = *(pos++); + register long oint = CASTINT(o); + const t_sample *fp0,*fp1; + const float frac = o-oint; + + if(oint >= smin) + if(oint < maxo) { + // normal interpolation + fp0 = bdt+oint*BCHNS; + fp1 = fp0+BCHNS; + } + else { + // position is past last sample + if(looped) { + oint = smin+(oint-smin)%plen; + fp0 = bdt+oint*BCHNS; + fp1 = oint >= maxo?bdt+smin:fp0; + } + else + fp0 = fp1 = bdt+maxo*BCHNS; + } + else { + // position is before first sample + if(looped) { + oint = smax-(smin-oint)%plen; + fp0 = bdt+oint*BCHNS; + fp1 = oint >= maxo?bdt+smin:fp0; + } + else + fp0 = fp1 = bdt+smin*BCHNS; + } - // clear rest of output channels (if buffer has less channels) - for(I ci = OCHNS; ci < outchns; ++ci) ZeroSamples(sig[ci],n); + for(int ci = 0; ci < OCHNS; ++ci) + sig[ci][si] = fp0[ci]+frac*(fp1[ci]-fp0[ci]); + } + + // clear rest of output channels (if buffer has less channels) + for(int ci = OCHNS; ci < outchns; ++ci) ZeroSamples(sig[ci],n); + } } -TMPLDEF V xinter::st_play4(const S *bdt,const I smin,const I smax,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) +TMPLDEF void xinter::st_play4(const t_sample *bdt,const int smin,const int smax,const int n,const int inchns,const int outchns,t_sample *const *invecs,t_sample *const *outvecs,bool looped) { - const I plen = smax-smin; //curlen; + const int plen = smax-smin; //curlen; if(plen < 4) { - if(plen < 2) st_play1 TMPLCALL (bdt,smin,smax,n,inchns,outchns,invecs,outvecs); - else st_play2 TMPLCALL (bdt,smin,smax,n,inchns,outchns,invecs,outvecs); + if(plen < 2) st_play1 TMPLCALL (bdt,smin,smax,n,inchns,outchns,invecs,outvecs,looped); + else st_play2 TMPLCALL (bdt,smin,smax,n,inchns,outchns,invecs,outvecs,looped); return; } SIGCHNS(BCHNS,inchns,OCHNS,outchns); // position info are frame units - const S *pos = invecs[0]; - -#ifdef __VEC__ - // prefetch cache - vec_dst(pos,GetPrefetchConstant(1,n>>2,0),0); - const int pf = GetPrefetchConstant(BCHNS,1,16*BCHNS); -#endif - - S *const *sig = outvecs; - register I si = 0; + const t_sample *pos = invecs[0]; + t_sample *const *sig = outvecs; // 4-point interpolation // --------------------- - const I maxo = smax-1; // last sample in play region - const S *maxp = bdt+maxo*BCHNS; // pointer to last sample - - for(I i = 0; i < n; ++i,++si) { - F o = *(pos++); - register I oint = (I)o; - register F frac; - register const S *fa,*fb,*fc,*fd; - - if(oint > smin) - if(oint < maxo-2) { - // normal case - - fa = bdt+oint*BCHNS-BCHNS; - frac = o-oint; - fb = fa+BCHNS; - #ifdef __VEC__ - vec_dst(fa,pf,0); - #endif - fc = fb+BCHNS; - fd = fc+BCHNS; - } - else { - // after the end - - if(oint > maxo) oint = maxo,o = (float)smax; - frac = o-oint; - - fb = bdt+oint*BCHNS; - fa = fb-BCHNS; - - // \TODO what about wraparound (in loop/palindrome mode) ? - fc = fb >= maxp?maxp:fb+BCHNS; - fd = fc >= maxp?maxp:fc+BCHNS; - } - else { - // before the beginning - - // if oint < first sample set it to first sample - // \TODO what about wraparound (in loop/palindrome mode) ? - if(oint < smin) oint = smin,o = (float)smin; - - // position is first sample - fa = bdt+smin*BCHNS; - - fb = bdt+oint*BCHNS; - frac = o-oint; - fc = fb+BCHNS; - fd = fc+BCHNS; - } - - register F f1 = 0.5f*(frac-1.0f); - register F f3 = frac*3.0f-1.0f; - - for(I ci = 0; ci < OCHNS; ++ci) { - const F amdf = (fa[ci]-fd[ci])*frac; - const F cmb = fc[ci]-fb[ci]; - const F bma = fb[ci]-fa[ci]; - sig[ci][si] = fb[ci] + frac*( cmb - f1 * ( amdf+bma+cmb*f3 ) ); - } - } - -#ifdef __VEC__ - vec_dss(0); -#endif + const int maxo = smax-1; // last sample in play region + + if(OCHNS == 1) { + t_sample *sig0 = sig[0]; + for(int i = 0; i < n; ++i) { + float o = *(pos++); + register long oint = CASTINT(o); + register t_sample fa,fb,fc,fd; + const float frac = o-oint; + register const t_sample *ptr = bdt+oint*BCHNS; + + if(oint > smin) { + if(oint < maxo-2) { + // normal case + fa = ptr[-BCHNS]; + fb = ptr[0]; + fc = ptr[BCHNS]; + fd = ptr[BCHNS*2]; + } + else { + // not enough space at the end + + if(looped) { + // normalize position + oint = smin+(oint-smin)%plen; + goto looped1; + } + else { + // last sample is outside in any case + fd = bdt[maxo*BCHNS]; + + if(oint-1 >= maxo) + // if first is outside, all are outside + fa = fb = fc = fd; + else { + fa = ptr[-BCHNS]; + if(oint >= maxo) + fb = fc = fd; + else { + fb = ptr[0]; + fc = oint+1 < maxo?ptr[BCHNS]:fd; + } + } + } + } + } + else { + // not enough space at the beginning + + if(looped) { + // normalize position + oint = smax-(smin-oint)%plen; +looped1: + ptr = bdt+oint*BCHNS; + + // inside in any case + fb = ptr[0]; + + if(oint < maxo-1) { + fa = oint > smin?ptr[-BCHNS]:bdt[maxo*BCHNS]; + fc = ptr[BCHNS]; + fd = ptr[BCHNS*2]; + } + else { + fa = ptr[-BCHNS]; + fc = oint < maxo?ptr[BCHNS]:ptr[(1-plen)*BCHNS]; + fd = ptr[(2-plen)*BCHNS]; + } + } + else { + // first sample is outside in any case + fa = bdt[smin*BCHNS]; + + if(oint+2 < smin) + // if last is outside, all are outside + fb = fc = fd = fa; + else { + fd = ptr[BCHNS*2]; + if(oint+1 < smin) + fb = fc = fa; + else { + fc = ptr[BCHNS]; + fb = oint < smin?fa:ptr[0]; + } + } + } + } + + const float f1 = 0.5f*(frac-1.0f); + const float f3 = frac*3.0f-1.0f; + + const float amdf = (fa-fd)*frac; + const float cmb = fc-fb; + const float bma = fb-fa; + *(sig0++) = fb + frac*( cmb - f1 * ( amdf+bma+cmb*f3 ) ); + } + } + else { + for(int i = 0,si = 0; i < n; ++i,++si) { + float o = *(pos++); + register long oint = CASTINT(o); + const float frac = o-oint; + register const t_sample *ptr = bdt+oint*BCHNS; + register const t_sample *fa,*fb,*fc,*fd; + + if(oint > smin) + if(oint < maxo-2) { + // normal case + fb = ptr; + fa = fb-BCHNS; + fc = fb+BCHNS; + fd = fc+BCHNS; + } + else { + // not enough space at the end + + if(looped) { + // normalize position + oint = smin+(oint-smin)%plen; + goto looped2; + } + else { + // last sample is outside in any case + fd = bdt+maxo*BCHNS; + + if(oint-1 >= maxo) + // if first is outside, all are outside + fa = fb = fc = fd; + else { + fa = ptr-BCHNS; + if(oint >= maxo) + fb = fc = fd; + else { + fb = ptr; + fc = oint+1 < maxo?ptr+BCHNS:fd; + } + } + } + } + else { + // not enough space at the beginning + + if(looped) { + // normalize position + oint = smax-(smin-oint)%plen; +looped2: + // inside in any case + fb = bdt+oint*BCHNS; + + if(oint < maxo-1) { + fa = oint > smin?fb-BCHNS:bdt+maxo*BCHNS; + fc = fb+BCHNS; + fd = fc+BCHNS; + } + else { + fa = fb-BCHNS; + fc = oint < maxo?fb+BCHNS:bdt+(oint-plen+1)*BCHNS; + fd = bdt+(oint-plen+2)*BCHNS; + } + } + else { + // first sample is outside in any case + fa = bdt+smin*BCHNS; + + if(oint+2 < smin) + // if last is outside, all are outside + fb = fc = fd = fa; + else { + fd = ptr+BCHNS*2; + if(oint+1 < smin) + fb = fc = fa; + else { + fc = ptr+BCHNS; + fb = oint < smin?fa:ptr; + } + } + } + } + + const float f1 = 0.5f*(frac-1.0f); + const float f3 = frac*3.0f-1.0f; + + for(int ci = 0; ci < OCHNS; ++ci) { + const float amdf = (fa[ci]-fd[ci])*frac; + const float cmb = fc[ci]-fb[ci]; + const float bma = fb[ci]-fa[ci]; + sig[ci][si] = fb[ci] + frac*( cmb - f1 * ( amdf+bma+cmb*f3 ) ); + } + } - // clear rest of output channels (if buffer has less channels) - for(I ci = OCHNS; ci < outchns; ++ci) ZeroSamples(sig[ci],n); + // clear rest of output channels (if buffer has less channels) + for(int ci = OCHNS; ci < outchns; ++ci) ZeroSamples(sig[ci],n); + } } -TMPLDEF inline V xinter::s_play0(I n,S *const *invecs,S *const *outvecs) +TMPLDEF inline void xinter::s_play0(int n,t_sample *const *invecs,t_sample *const *outvecs) { - st_play0 TMPLCALL (buf->Data(),curmin,curmax,n,buf->Channels(),outchns,invecs,outvecs); + st_play0 TMPLCALL (buf.Data(),curmin,curmax,n,buf.Channels(),outchns,invecs,outvecs,loopmode == xsl_loop); } -TMPLDEF inline V xinter::s_play1(I n,S *const *invecs,S *const *outvecs) +TMPLDEF inline void xinter::s_play1(int n,t_sample *const *invecs,t_sample *const *outvecs) { - st_play1 TMPLCALL (buf->Data(),curmin,curmax,n,buf->Channels(),outchns,invecs,outvecs); + st_play1 TMPLCALL (buf.Data(),curmin,curmax,n,buf.Channels(),outchns,invecs,outvecs,loopmode == xsl_loop); } -TMPLDEF inline V xinter::s_play2(I n,S *const *invecs,S *const *outvecs) +TMPLDEF inline void xinter::s_play2(int n,t_sample *const *invecs,t_sample *const *outvecs) { - st_play2 TMPLCALL (buf->Data(),curmin,curmax,n,buf->Channels(),outchns,invecs,outvecs); + st_play2 TMPLCALL (buf.Data(),curmin,curmax,n,buf.Channels(),outchns,invecs,outvecs,loopmode == xsl_loop); } -TMPLDEF inline V xinter::s_play4(I n,S *const *invecs,S *const *outvecs) +TMPLDEF inline void xinter::s_play4(int n,t_sample *const *invecs,t_sample *const *outvecs) { - st_play4 TMPLCALL (buf->Data(),curmin,curmax,n,buf->Channels(),outchns,invecs,outvecs); + st_play4 TMPLCALL (buf.Data(),curmin,curmax,n,buf.Channels(),outchns,invecs,outvecs,loopmode == xsl_loop); } #endif -- cgit v1.2.1