diff options
Diffstat (limited to 'externals/grill/xsample/source/inter.ci')
-rw-r--r-- | externals/grill/xsample/source/inter.ci | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/externals/grill/xsample/source/inter.ci b/externals/grill/xsample/source/inter.ci new file mode 100644 index 00000000..2902c386 --- /dev/null +++ b/externals/grill/xsample/source/inter.ci @@ -0,0 +1,355 @@ +#ifndef __INTER_H +#define __INTER_H + +TMPLDEF V xinter::st_play0(const S *bdt,const I smin,const I smax,const F s2u,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) +{ + // stopped + SIGCHNS(BCHNS,inchns,OCHNS,outchns); + + const S *pos = invecs[0]; + S *const *sig = outvecs; + + for(I ci = 0; ci < outchns; ++ci) + for(I si = 0; si < n; ++si) sig[ci][si] = 0; +} + +TMPLDEF V xinter::st_play1(const S *bdt,const I smin,const I smax,const F s2u,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) +{ + SIGCHNS(BCHNS,inchns,OCHNS,outchns); + + const S *pos = invecs[0]; + S *const *sig = outvecs; + register I si = 0; + + // no interpolation + // ---------------- + + for(I i = 0; i < n; ++i,++si) { + register const I oint = (I)(*(pos++)/s2u); + register const S *fp; + if(oint < smin) { + // position < 0 ... take only 0th sample + fp = bdt+smin*BCHNS; + } + else if(oint >= smax) { + // position > last sample ... take only last sample + fp = bdt+(smax-1)*BCHNS; + } + else { + // normal + fp = bdt+oint*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) + for(si = 0; si < n; ++si) sig[ci][si] = 0; +} + +TMPLDEF V xinter::st_play2(const S *bdt,const I smin,const I smax,const F s2u,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) +{ + const I plen = smax-smin; //curlen; + if(plen < 2) { + st_play1 TMPLCALL (bdt,smin,smax,s2u,n,inchns,outchns,invecs,outvecs); + return; + } + + SIGCHNS(BCHNS,inchns,OCHNS,outchns); + + const S *pos = invecs[0]; + S *const *sig = outvecs; + register I si = 0; + + // linear interpolation + // -------------------- + + const I maxo = smax-1; // last sample in buffer + + for(I i = 0; i < n; ++i,++si) { + const F o = *(pos++)/s2u; + register const I oint = (I)o; + + if(oint < smin) { + // 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]; + } + else if(oint >= maxo) { + // 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 { + // 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]); + } + } + + // clear rest of output channels (if buffer has less channels) + for(I ci = OCHNS; ci < outchns; ++ci) + for(si = 0; si < n; ++si) sig[ci][si] = 0; +} + +TMPLDEF V xinter::st_play4(const S *bdt,const I smin,const I smax,const F s2u,const I n,const I inchns,const I outchns,S *const *invecs,S *const *outvecs) +{ + const I plen = smax-smin; //curlen; + if(plen < 4) { + if(plen < 2) st_play1 TMPLCALL (bdt,smin,smax,s2u,n,inchns,outchns,invecs,outvecs); + else st_play2 TMPLCALL (bdt,smin,smax,s2u,n,inchns,outchns,invecs,outvecs); + return; + } + + SIGCHNS(BCHNS,inchns,OCHNS,outchns); + + const S *pos = invecs[0]; + S *const *sig = outvecs; + register I si = 0; + + // 4-point interpolation + // --------------------- + const I maxo = smax-1; // last sample in play region + + for(I i = 0; i < n; ++i,++si) { + F o = *(pos++)/s2u; + register I oint = (I)o,ointm,oint1,oint2; + + if(oint <= smin) { + if(oint < smin) oint = smin,o = smin; + // position is first simple + ointm = smin; // first sample + oint1 = oint+1; + oint2 = oint1+1; + } + else if(oint >= maxo-2) { + if(oint > maxo) oint = maxo,o = smax; + ointm = oint-1; + oint1 = oint >= maxo?maxo:oint+1; + oint2 = oint1 >= maxo?maxo:oint1+1; + } + else { + ointm = oint-1; + oint1 = oint+1; + oint2 = oint1+1; + } + + register F frac = o-oint; + + register const S *fa = bdt+ointm*BCHNS; + register const S *fb = bdt+oint*BCHNS; + register const S *fc = bdt+oint1*BCHNS; + register const S *fd = bdt+oint2*BCHNS; + + for(I ci = 0; ci < OCHNS; ++ci) { + const F cmb = fc[ci]-fb[ci]; + sig[ci][si] = fb[ci] + frac*( + cmb - 0.5f*(frac-1.) * ((fa[ci]-fd[ci]+3.0f*cmb)*frac + (fb[ci]-fa[ci]-cmb)) + ); + } + } + + // clear rest of output channels (if buffer has less channels) + for(I ci = OCHNS; ci < outchns; ++ci) + for(si = 0; si < n; ++si) sig[ci][si] = 0; +} + +#if 0 + +TMPLDEF V xinter::s_play0(I n,S *const *invecs,S *const *outvecs) +{ + // stopped + SIGCHNS(BCHNS,buf->Channels(),OCHNS,outchns); + + const S *pos = invecs[0]; + S *const *sig = outvecs; + + for(I ci = 0; ci < outchns; ++ci) + for(I si = 0; si < n; ++si) sig[ci][si] = 0; +} + +TMPLDEF V xinter::s_play4(I n,S *const *invecs,S *const *outvecs) +{ + const I smin = curmin,smax = curmax,plen = smax-smin; //curlen; + if(plen < 4) { + if(plen < 2) s_play1 TMPLCALL (n,invecs,outvecs); + else s_play2 TMPLCALL (n,invecs,outvecs); + return; + } + + SIGCHNS(BCHNS,buf->Channels(),OCHNS,outchns); + + const S *pos = invecs[0]; + S *const *sig = outvecs; + register I si = 0; + const S *bdt = buf->Data(); + + // 4-point interpolation + // --------------------- + const I maxo = smax-1; // last sample in play region + + for(I i = 0; i < n; ++i,++si) { + F o = *(pos++)/s2u; + register I oint = (I)o,ointm,oint1,oint2; + + if(oint <= smin) { + if(oint < smin) oint = smin,o = smin; + // position is first simple + ointm = smin; // first sample + oint1 = oint+1; + oint2 = oint1+1; + } + else if(oint >= maxo-2) { + if(oint > maxo) oint = maxo,o = smax; + ointm = oint-1; + oint1 = oint >= maxo?maxo:oint+1; + oint2 = oint1 >= maxo?maxo:oint1+1; + } + else { + ointm = oint-1; + oint1 = oint+1; + oint2 = oint1+1; + } + + register F frac = o-oint; + + register const S *fa = bdt+ointm*BCHNS; + register const S *fb = bdt+oint*BCHNS; + register const S *fc = bdt+oint1*BCHNS; + register const S *fd = bdt+oint2*BCHNS; + + for(I ci = 0; ci < OCHNS; ++ci) { + const F cmb = fc[ci]-fb[ci]; + sig[ci][si] = fb[ci] + frac*( + cmb - 0.5f*(frac-1.) * ((fa[ci]-fd[ci]+3.0f*cmb)*frac + (fb[ci]-fa[ci]-cmb)) + ); + } + } + + // clear rest of output channels (if buffer has less channels) + for(I ci = OCHNS; ci < outchns; ++ci) + for(si = 0; si < n; ++si) sig[ci][si] = 0; +} + +TMPLDEF V xinter::s_play2(I n,S *const *invecs,S *const *outvecs) +{ + const I smin = curmin,smax = curmax,plen = smax-smin; //curlen; + if(plen < 2) { + s_play1 TMPLCALL (n,invecs,outvecs); + return; + } + + SIGCHNS(BCHNS,buf->Channels(),OCHNS,outchns); + + const S *pos = invecs[0]; + S *const *sig = outvecs; + register I si = 0; + + // linear interpolation + // -------------------- + + const I maxo = smax-1; // last sample in buffer + const S *bdt = buf->Data(); + + for(I i = 0; i < n; ++i,++si) { + const F o = *(pos++)/s2u; + register const I oint = (I)o; + + if(oint < smin) { + // 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]; + } + else if(oint >= maxo) { + // 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 { + // 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]); + } + } + + // clear rest of output channels (if buffer has less channels) + for(I ci = OCHNS; ci < outchns; ++ci) + for(si = 0; si < n; ++si) sig[ci][si] = 0; +} + +TMPLDEF V xinter::s_play1(I n,S *const *invecs,S *const *outvecs) +{ + SIGCHNS(BCHNS,buf->Channels(),OCHNS,outchns); + + const S *pos = invecs[0]; + S *const *sig = outvecs; + register I si = 0; + const I smin = curmin,smax = curmax; + const S *bdt = buf->Data(); + + // no interpolation + // ---------------- + + for(I i = 0; i < n; ++i,++si) { + register const I oint = (I)(*(pos++)/s2u); + register const S *fp; + if(oint < smin) { + // position < 0 ... take only 0th sample + fp = bdt+smin*BCHNS; + } + else if(oint >= smax) { + // position > last sample ... take only last sample + fp = bdt+(smax-1)*BCHNS; + } + else { + // normal + fp = bdt+oint*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) + for(si = 0; si < n; ++si) sig[ci][si] = 0; +} + +#else + +TMPLDEF V xinter::s_play0(I n,S *const *invecs,S *const *outvecs) +{ + st_play0 TMPLCALL (buf->Data(),curmin,curmax,s2u,n,buf->Channels(),outchns,invecs,outvecs); +} + +TMPLDEF V xinter::s_play1(I n,S *const *invecs,S *const *outvecs) +{ + st_play1 TMPLCALL (buf->Data(),curmin,curmax,s2u,n,buf->Channels(),outchns,invecs,outvecs); +} + +TMPLDEF V xinter::s_play2(I n,S *const *invecs,S *const *outvecs) +{ + st_play2 TMPLCALL (buf->Data(),curmin,curmax,s2u,n,buf->Channels(),outchns,invecs,outvecs); +} + +TMPLDEF V xinter::s_play4(I n,S *const *invecs,S *const *outvecs) +{ + st_play4 TMPLCALL (buf->Data(),curmin,curmax,s2u,n,buf->Channels(),outchns,invecs,outvecs); +} + +#endif + + +#endif |