aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/xsample/source/inter.ci
diff options
context:
space:
mode:
Diffstat (limited to 'externals/grill/xsample/source/inter.ci')
-rw-r--r--externals/grill/xsample/source/inter.ci355
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