aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/xsample/source
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2004-04-08 04:01:44 +0000
committerThomas Grill <xovo@users.sourceforge.net>2004-04-08 04:01:44 +0000
commit3b55ea164662d73b5850bab344a413d1fd5264c1 (patch)
treefe6b9a9054f8237f2575e469f66b3c5125148d52 /externals/grill/xsample/source
parent7fb76f925e1bbb37df0ed0b548bcf6ce7670c835 (diff)
""
svn path=/trunk/; revision=1575
Diffstat (limited to 'externals/grill/xsample/source')
-rw-r--r--externals/grill/xsample/source/groove.cpp235
-rw-r--r--externals/grill/xsample/source/main.h4
2 files changed, 133 insertions, 106 deletions
diff --git a/externals/grill/xsample/source/groove.cpp b/externals/grill/xsample/source/groove.cpp
index 0da9087c..f96b33bb 100644
--- a/externals/grill/xsample/source/groove.cpp
+++ b/externals/grill/xsample/source/groove.cpp
@@ -17,7 +17,7 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#endif
-#define XZONE_TABLE 512
+#define XZONE_TABLE 64
class xgroove:
@@ -45,14 +45,11 @@ public:
virtual V m_max(F mx);
V ms_xfade(I xf);
+ V ms_xshape(I sh);
V ms_xzone(F xz);
V mg_xzone(F &xz) { xz = _xzone*s2u; }
- V m_xshape(I argc = 0,const t_atom *argv = NULL);
- inline V ms_xshape(const AtomList &ret) { m_xshape(ret.Count(),ret.Atoms()); }
- V mg_xshape(AtomList &ret) const;
-
enum xs_loop {
xsl__ = -1, // don't change
xsl_once = 0,xsl_loop,xsl_bidir
@@ -63,6 +60,11 @@ public:
xsf_keeplooppos = 0,xsf_keeplooplen,xsf_keepfade,xsf_inside
};
+ enum xs_shape {
+ xss__ = -1, // don't change
+ xss_lin = 0,xss_qsine,xss_hsine
+ };
+
V m_loop(xs_loop lp = xsl__);
protected:
@@ -75,8 +77,6 @@ protected:
L znsmin,znsmax;
xs_fade xfade;
I xshape;
- F xshparam;
- D znmin,znmax;
S **znbuf;
S *znpos,*znmul,*znidx;
I pblksz;
@@ -129,6 +129,8 @@ private:
zerofun(n,in,out);
}
+ static S fade_lin[],fade_qsine[],fade_hsine[];
+
FLEXT_CALLBACK_F(m_pos)
FLEXT_CALLBACK_F(m_posmod)
FLEXT_CALLBACK_F(m_min)
@@ -137,9 +139,10 @@ private:
FLEXT_CALLSET_I(ms_xfade)
FLEXT_ATTRGET_I(xfade)
+ FLEXT_CALLSET_I(ms_xshape)
+ FLEXT_ATTRGET_I(xshape)
FLEXT_CALLSET_F(ms_xzone)
FLEXT_CALLGET_F(mg_xzone)
- FLEXT_CALLVAR_V(mg_xshape,ms_xshape)
FLEXT_CALLVAR_F(mg_pos,m_pos)
FLEXT_CALLSET_F(m_min)
@@ -152,6 +155,14 @@ private:
FLEXT_LIB_DSP_V("xgroove~",xgroove)
+S xgroove::fade_lin[XZONE_TABLE+1];
+S xgroove::fade_qsine[XZONE_TABLE+1];
+S xgroove::fade_hsine[XZONE_TABLE+1];
+
+#ifndef PI
+#define PI 3.14159265358979f
+#endif
+
V xgroove::setup(t_classid c)
{
DefineHelp(c,"xgroove~");
@@ -169,14 +180,27 @@ V xgroove::setup(t_classid c)
FLEXT_CADDATTR_VAR(c,"xfade",xfade,ms_xfade);
FLEXT_CADDATTR_VAR(c,"xzone",mg_xzone,ms_xzone);
- FLEXT_CADDATTR_VAR(c,"xshape",mg_xshape,ms_xshape);
+ FLEXT_CADDATTR_VAR(c,"xshape",xshape,ms_xshape);
+
+ // initialize fade tables
+ for(int i = 0; i <= XZONE_TABLE; ++i) {
+ const float x = i*(1.f/XZONE_TABLE);
+ // linear
+ fade_lin[i] = x;
+
+ // quarter sine wave
+ fade_qsine[i] = sin(x*(PI/2));
+
+ // half sine wave
+ fade_hsine[i] = (sin(x*PI-PI/2)+1.f)*0.5f;
+ }
}
xgroove::xgroove(I argc,const t_atom *argv):
loopmode(xsl_loop),curpos(0),
_xzone(0),xzone(0),pblksz(0),
- xfade(xsf_keeplooppos),xshape(0),xshparam(1),
- znbuf(NULL),znmul(NULL),znidx(NULL),znpos(NULL),
+ xfade(xsf_keeplooppos),xshape(xss_lin),
+ znidx(NULL),znpos(NULL),
bidir(1)
{
I argi = 0;
@@ -195,7 +219,7 @@ xgroove::xgroove(I argc,const t_atom *argv):
argi++;
#if FLEXT_SYS == FLEXT_SYS_MAX
- // oldstyle command line?
+ // old-style command line?
if(argi == 1 && argc == 2 && CanbeInt(argv[argi])) {
outchns = GetAInt(argv[argi]);
argi++;
@@ -222,23 +246,19 @@ xgroove::xgroove(I argc,const t_atom *argv):
// don't know vector size yet -> wait for m_dsp
znbuf = new S *[outchns];
for(I i = 0; i < outchns; ++i) znbuf[i] = NULL;
- znpos = NULL;
- znidx = NULL;
- znmul = new S[XZONE_TABLE+1];
- m_xshape();
+ ms_xshape(xshape);
}
xgroove::~xgroove()
{
if(znbuf) {
- for(I i = 0; i < outchns; ++i) if(znbuf[i]) delete[] znbuf[i];
+ for(I i = 0; i < outchns; ++i) if(znbuf[i]) FreeAligned(znbuf[i]);
delete[] znbuf;
}
- if(znpos) delete[] znpos;
- if(znidx) delete[] znidx;
- delete[] znmul;
+ if(znpos) FreeAligned(znpos);
+ if(znidx) FreeAligned(znidx);
}
BL xgroove::Init()
@@ -314,56 +334,32 @@ V xgroove::ms_xzone(F xz)
s_dsp();
}
-V xgroove::m_xshape(I argc,const t_atom *argv)
+V xgroove::ms_xshape(I sh)
{
- const F pi = 3.14159265358979f;
- xshape = 0;
- xshparam = 1;
- if(argc >= 1 && CanbeInt(argv[0])) xshape = GetAInt(argv[0]);
- if(argc >= 2 && CanbeFloat(argv[1])) {
- xshparam = GetAFloat(argv[1]);
-/*
- // clip to 0..1
- if(xshparam < 0) xshparam = 0;
- else if(xshparam > 1) xshparam = 1;
-*/
- }
-
- I i;
+ xshape = (xs_shape)sh;
switch(xshape) {
- case 1:
- // sine half wave
- for(i = 0; i <= XZONE_TABLE; ++i)
- znmul[i] = sin(i*pi/(XZONE_TABLE*2))*xshparam+i*(1.f/XZONE_TABLE)*(1.f-xshparam);
- break;
- case 2:
- // sine full wave
- for(i = 0; i <= XZONE_TABLE; ++i)
- znmul[i] = ((sin(i*(pi/XZONE_TABLE)-pi*0.5f)+1.f)*0.5f)*xshparam+i*(1.f/XZONE_TABLE)*(1.f-xshparam);
- break;
- case 0:
- default:
- // linear
- for(i = 0; i <= XZONE_TABLE; ++i)
- znmul[i] = i*(1.f/XZONE_TABLE);
+ case xss_qsine: znmul = fade_qsine; break;
+ case xss_hsine: znmul = fade_hsine; break;
+ default:
+ post("%s - shape parameter invalid, set to linear",thisName());
+ case xss_lin:
+ znmul = fade_lin; break;
}
-}
-V xgroove::mg_xshape(AtomList &ret) const
-{
- ret(2);
- SetInt(ret[0],xshape);
- SetFloat(ret[1],xshparam);
+ // no need to recalc the fade zone here
}
-
V xgroove::do_xzone()
{
- if(!s2u) return; // this can happen if DSP is off
+ // \todo do we really need this?
+ if(!s2u) return; // this can happen if DSP is off
xzone = _xzone; // make a copy for changing it
- if(xfade == xsf_inside) { // fade zone goes inside the loop -> loop gets shorter
+ if(xfade == xsf_inside) {
+ // fade zone goes inside the loop -> loop becomes shorter
+
+ // \todo what about round-off?
const L maxfd = (curmax-curmin)/2;
if(xzone > maxfd) xzone = maxfd;
@@ -371,14 +367,20 @@ V xgroove::do_xzone()
}
else if(xfade == xsf_keepfade) {
// try to keep fade zone
- // shifting of loop bounds may happen
+ // change of loop bounds may happen
// restrict xzone to half of buffer
const L maxfd = buf->Frames()/2;
if(xzone > maxfd) xzone = maxfd;
- znsmin = curmin-xzone/2;
- znsmax = curmax+xzone/2;
+ // \todo what about round-off?
+ znsmin = curmin-(L)(xzone/2);
+ znsmax = curmax+(L)(xzone/2);
+
+ // widen loop if xzone doesn't fit into it
+ // \todo check formula
+ L lack = (L)ceil((xzone*2-(znsmax-znsmin))/2);
+ if(lack > 0) znsmin -= lack,znsmax += lack;
// check buffer limits and shift bounds if necessary
if(znsmin < 0) {
@@ -392,11 +394,14 @@ V xgroove::do_xzone()
// try to keep loop length
// shifting of loop bounds may happen
- const L maxfd = buf->Frames()-(curmax-curmin);
+ const L plen = curmax-curmin;
+ if(xzone > plen) xzone = plen;
+ const L maxfd = buf->Frames()-plen;
if(xzone > maxfd) xzone = maxfd;
- znsmin = curmin-xzone/2;
- znsmax = curmax+xzone/2;
+ // \todo what about round-off?
+ znsmin = curmin-(L)(xzone/2);
+ znsmax = curmax+(L)(xzone/2);
// check buffer limits and shift bounds if necessary
// both cases can't happen because of xzone having been limited above
@@ -412,8 +417,13 @@ V xgroove::do_xzone()
else if(xfade == xsf_keeplooppos) {
// try to keep loop position and length
- znsmin = curmin-xzone/2;
- znsmax = curmax+xzone/2;
+ // restrict fade zone to maximum length
+ const L plen = curmax-curmin;
+ if(xzone > plen) xzone = plen;
+
+ // \todo what about round-off?
+ znsmin = curmin-(L)(xzone/2);
+ znsmax = curmax+(L)(xzone/2);
L ovr = znsmax-buf->Frames();
if(-znsmin > ovr) ovr = -znsmin;
@@ -424,9 +434,6 @@ V xgroove::do_xzone()
}
}
- znmin = znsmin+xzone;
- znmax = znsmax-xzone;
-
FLEXT_ASSERT(znsmin <= znsmax && (znsmax-znsmin) >= xzone*2);
}
@@ -631,7 +638,6 @@ V xgroove::s_pos_loopzn(I n,S *const *invecs,S *const *outvecs)
FLEXT_ASSERT(xzone);
const F xz = xzone,xf = (F)XZONE_TABLE/xz;
- const D lmin = znmin,lmax = znmax,lsh = lmax-lmin+xz;
// adapt the playing bounds to the current cross-fade zone
const L smin = znsmin,smax = znsmax,plen = smax-smin;
@@ -640,30 +646,53 @@ V xgroove::s_pos_loopzn(I n,S *const *invecs,S *const *outvecs)
BL inzn = false;
register D o = curpos;
+ // calculate inner cross-fade boundaries
+ const D lmin = smin+xz,lmax = smax-xz,lsh = lmax-lmin+xz;
+ const D lmin2 = lmin-xz/2,lmax2 = lmax+xz/2;
+
for(I i = 0; i < n; ++i) {
- // \TODO: exploit relationships: smin <= lmin, smax >= lmax
-
// normalize offset
- if(!(o < smax)) {
- o = fmod(o-smin,plen)+smin;
- lpbang = true;
- }
- else if(o < smin) {
+ if(o < smin) {
o = fmod(o-smin,plen)+smax;
lpbang = true;
}
-
- if(o >= lmax) {
- // in late cross-fade zone
- o -= lsh;
+ else if(!(o < smax)) {
+ o = fmod(o-smin,plen)+smin;
+ lpbang = true;
}
- // now: smin <= o < smax
if(o < lmin) {
- // in early cross-fade zone
- register F inp = xz+(F)(o-lmin); // 0 <= inp < xz
+ register F inp;
+ if(o < lmin2) {
+ o += lsh;
+ lpbang = true;
+ // now lmax <= o <= lmax2
+
+ inp = xz-(F)(o-lmax); // 0 <= inp < xz
+ znpos[i] = lmin-inp;
+ }
+ else { // in early cross-fade zone
+ inp = xz+(F)(o-lmin); // 0 <= inp < xz
+ znpos[i] = lmax+inp;
+ }
+ znidx[i] = inp*xf;
+ inzn = true;
+ }
+ else if(!(o < lmax)) {
+ register F inp;
+ if(!(o < lmax2)) {
+ o -= lsh;
+ lpbang = true;
+ // now lmin2 <= o <= lmin
+
+ inp = xz+(F)(o-lmin); // 0 <= inp < xz
+ znpos[i] = lmax+inp;
+ }
+ else { // in late cross-fade zone
+ inp = xz-(F)(o-lmax); // 0 <= inp < xz
+ znpos[i] = lmin-inp;
+ }
znidx[i] = inp*xf;
- znpos[i] = lmax+inp;
inzn = true;
}
else
@@ -675,14 +704,16 @@ V xgroove::s_pos_loopzn(I n,S *const *invecs,S *const *outvecs)
}
// normalize and store current playing position
- if(o < znsmin) o += plen;
setpos(o);
// calculate samples (1st voice)
playfun(n,&pos,outvecs);
+ // rescale position vector
+ arrscale(n,pos,pos);
+
if(inzn) {
- // only if we are in cross-fade zone
+ // only if we have touched the cross-fade zone
// calculate samples in loop zone (2nd voice)
playfun(n,&znpos,znbuf);
@@ -690,20 +721,17 @@ V xgroove::s_pos_loopzn(I n,S *const *invecs,S *const *outvecs)
// calculate counterpart in loop fade
arrscale(n,znidx,znpos,XZONE_TABLE,-1);
- // calculate fade coefficients
+ // calculate fade coefficients by sampling from the fade curve
zonefun(znmul,0,XZONE_TABLE+1,n,1,1,&znidx,&znidx);
zonefun(znmul,0,XZONE_TABLE+1,n,1,1,&znpos,&znpos);
// mix voices for all channels
for(I o = 0; o < outchns; ++o) {
- F *ov = outvecs[o],*ob = znbuf[o];
- for(I i = 0; i < n; ++i,ov++,ob++)
- *ov = (*ov)*znidx[i]+(*ob)*znpos[i];
+ MulSamples(outvecs[o],outvecs[o],znidx,n);
+ MulSamples(znbuf[o],znbuf[o],znpos,n);
+ AddSamples(outvecs[o],outvecs[o],znbuf[o],n);
}
}
-
- // rescale position vector
- arrscale(n,pos,pos);
}
else
s_pos_off(n,invecs,outvecs);
@@ -770,14 +798,14 @@ V xgroove::s_dsp()
if(pblksz != blksz) {
for(I o = 0; o < outchns; ++o) {
- if(znbuf[o]) delete[] znbuf[o];
- znbuf[o] = new S[blksz];
+ if(znbuf[o]) FreeAligned(znbuf[o]);
+ znbuf[o] = (S *)NewAligned(blksz*sizeof(S));
}
- if(znpos) delete[] znpos;
- znpos = new S[blksz];
- if(znidx) delete[] znidx;
- znidx = new S[blksz];
+ if(znpos) FreeAligned(znpos);
+ znpos = (S *)NewAligned(blksz*sizeof(S));
+ if(znidx) FreeAligned(znidx);
+ znidx = (S *)NewAligned(blksz*sizeof(S));
pblksz = blksz;
}
@@ -838,9 +866,8 @@ V xgroove::m_help()
post("\t@units 0/1/2/3: set units to frames/buffer size/ms/s");
post("\t@sclmode 0/1/2/3: set range of position to units/units in loop/buffer/loop");
post("\t@xzone {unit}: length of loop crossfade zone");
- post("\t@xsymm -1,0...1: symmetry of crossfade zone inside/outside point");
- post("\t@xshape 0/1 [param 0...1]: shape of crossfading (linear/trig)");
- post("\t@xkeep 0/1: try to preserve xzone/loop length");
+ post("\t@xfade 0/1/2/3: fade mode (keep loop/keep loop length/keep fade/inside loop)");
+ post("\t@xshape 0/1/2: shape of crossfade (linear/quarter sine/half sine)");
post("");
}
diff --git a/externals/grill/xsample/source/main.h b/externals/grill/xsample/source/main.h
index f19dce45..056550b9 100644
--- a/externals/grill/xsample/source/main.h
+++ b/externals/grill/xsample/source/main.h
@@ -12,7 +12,7 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#define __XSAMPLE_H
-#define XSAMPLE_VERSION "0.3.0pre19"
+#define XSAMPLE_VERSION "0.3.0pre20"
#define FLEXT_ATTRIBUTES 1
@@ -113,7 +113,7 @@ public:
enum xs_intp {
xsi__ = -1, // don't change
- xsi_none = 0,xsi_lin,xsi_4p
+ xsi_none = 0,xsi_4p,xsi_lin
};
enum xs_sclmd {