aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/xsample/source/groove.cpp
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2009-04-01 21:13:09 +0000
committerThomas Grill <xovo@users.sourceforge.net>2009-04-01 21:13:09 +0000
commit0ed7a8b68dd73e2b0473b8127aeca99f3bac9061 (patch)
tree5c67818b38a5cc2f9caa5ca7f8640ca356adf02b /externals/grill/xsample/source/groove.cpp
parentbb4c7f6a245394d09dac9adfb2efb093d3d98452 (diff)
cleaned up grill externals - replaced with svn:externals to svn.grrrr.org/ext/trunk/
svn path=/trunk/; revision=10951
Diffstat (limited to 'externals/grill/xsample/source/groove.cpp')
-rw-r--r--externals/grill/xsample/source/groove.cpp810
1 files changed, 0 insertions, 810 deletions
diff --git a/externals/grill/xsample/source/groove.cpp b/externals/grill/xsample/source/groove.cpp
deleted file mode 100644
index c989156e..00000000
--- a/externals/grill/xsample/source/groove.cpp
+++ /dev/null
@@ -1,810 +0,0 @@
-/*
-xsample - extended sample objects for Max/MSP and pd (pure data)
-
-Copyright (c) 2001-2007 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.
-*/
-
-#ifdef _MSC_VER
-#define _USE_MATH_DEFINES
-#endif
-
-#include "main.h"
-#include <math.h>
-#include <stdio.h>
-
-#ifdef _MSC_VER
-#pragma warning (disable:4244)
-#endif
-
-#ifndef M_PI
-#define M_PI 3.141592653589793238462643383
-#endif
-
-#define XZONE_TABLE 512
-
-
-class xgroove:
- public xinter
-{
- FLEXT_HEADER_S(xgroove,xinter,setup)
-
-public:
- xgroove(int argc,const t_atom *argv);
- virtual ~xgroove();
-
- void m_pos(float pos)
- {
- setpos(LIKELY(s2u)?pos/s2u:0);
- Update(xsc_pos,true);
- }
-
- inline void m_posmod(float pos) { setposmod(LIKELY(pos)?pos/s2u:0); } // motivated by Tim Blechmann
-
- inline void mg_pos(float &v) const { v = curpos*s2u; }
-
-
- enum xs_fade {
- xsf_keeplooppos = 0,xsf_keeplooplen,xsf_keepfade,xsf_inside
- };
-
- enum xs_shape {
- xss_lin = 0,xss_qsine,xss_hsine
- };
-
-
- void ms_xfade(int xf)
- {
- if(xf < 0 || xf > xsf_inside) xf = xsf_keeplooppos;
- xfade = (xs_fade)xf;
- Update(xsc_fade,true);
- }
-
- void ms_xshape(int sh);
-
- void ms_xzone(float xz);
- void mg_xzone(float &xz) { xz = _xzone*s2u; }
-
- void m_loop(xs_loop lp)
- {
- loopmode = lp,bidir = 1;
- Update(xsc_loop,true);
- }
-
-protected:
-
- double curpos; // in samples
- float bidir; // +1 or -1
-
- float _xzone,xzone;
- long znsmin,znsmax;
- xs_fade xfade;
- int xshape;
- t_sample **znbuf;
- t_sample *znpos,*znmul,*znidx;
- int pblksz;
-
- inline void setpos(double pos)
- {
- if(UNLIKELY(pos < znsmin)) curpos = znsmin;
- else if(UNLIKELY(pos > znsmax)) curpos = znsmax;
- else curpos = pos;
- }
-
- inline void setposmod(double pos)
- {
- if(pos >= 0)
- curpos = znsmin+fmod(pos,znsmax-znsmin);
- else
- curpos = znsmax+fmod(pos,znsmax-znsmin);
- }
-
- virtual void DoReset();
- virtual void DoUpdate(unsigned int flags);
-
- virtual void CbSignal();
-
- virtual void m_help();
- virtual void m_print();
-
-private:
- static void setup(t_classid c);
-
- //! return true if something has changed
- bool do_xzone();
-
- DEFSIGFUN(s_pos_off);
- DEFSIGFUN(s_pos_once);
- DEFSIGFUN(s_pos_loop);
- DEFSIGFUN(s_pos_loopzn);
- DEFSIGFUN(s_pos_bidir);
-
- DEFSIGCALL(posfun);
- DEFSTCALL(zonefun);
-
- static t_sample fade_lin[],fade_qsine[],fade_hsine[];
-
- FLEXT_CALLBACK_F(m_pos)
- FLEXT_CALLBACK_F(m_posmod)
- FLEXT_CALLBACK_F(m_min)
- FLEXT_CALLBACK_F(m_max)
- FLEXT_CALLBACK(m_all)
-
- FLEXT_CALLSET_E(m_loop,xs_loop)
-
- 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_F(mg_pos,m_pos)
- FLEXT_CALLSET_F(m_min)
- FLEXT_CALLSET_F(m_max)
-};
-
-
-FLEXT_LIB_DSP_V("xgroove~",xgroove)
-
-
-t_sample xgroove::fade_lin[XZONE_TABLE+1];
-t_sample xgroove::fade_qsine[XZONE_TABLE+1];
-t_sample xgroove::fade_hsine[XZONE_TABLE+1];
-
-void xgroove::setup(t_classid c)
-{
- DefineHelp(c,"xgroove~");
-
- FLEXT_CADDMETHOD_(c,0,"all",m_all);
- FLEXT_CADDMETHOD(c,1,m_min);
- FLEXT_CADDMETHOD(c,2,m_max);
-
- FLEXT_CADDATTR_VAR(c,"min",mg_min,m_min);
- FLEXT_CADDATTR_VAR(c,"max",mg_max,m_max);
- FLEXT_CADDATTR_VAR(c,"pos",mg_pos,m_pos);
- FLEXT_CADDMETHOD_(c,0,"posmod",m_posmod);
-
- FLEXT_CADDATTR_VAR_E(c,"loop",loopmode,m_loop);
-
- FLEXT_CADDATTR_VAR(c,"xfade",xfade,ms_xfade);
- FLEXT_CADDATTR_VAR(c,"xzone",mg_xzone,ms_xzone);
- 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*(M_PI/2));
-
- // half sine wave
- fade_hsine[i] = (sin(x*M_PI-M_PI/2)+1.f)*0.5f;
- }
-}
-
-xgroove::xgroove(int argc,const t_atom *argv):
- curpos(0),bidir(1),
- _xzone(0),xzone(0),
- xfade(xsf_keeplooppos),xshape(xss_lin),
- znpos(NULL),znmul(NULL),znidx(NULL),
- pblksz(0)
-{
- int argi = 0;
-#if FLEXT_SYS == FLEXT_SYS_MAX
- if(argc > argi && CanbeInt(argv[argi])) {
- outchns = GetAInt(argv[argi]);
- argi++;
- }
-#endif
-
- if(argc > argi && IsSymbol(argv[argi])) {
-
- buf.Set(GetSymbol(argv[argi]),true);
- argi++;
-
-#if FLEXT_SYS == FLEXT_SYS_MAX
- // old-style command line?
- if(UNLIKELY(argi == 1 && argc == 2 && CanbeInt(argv[argi]))) {
- outchns = GetAInt(argv[argi]);
- argi++;
- post("%s: old style command line detected - please change to '%s [channels] [buffer]'",thisName(),thisName());
- }
-#endif
- }
-
- AddInSignal("Signal of playing speed"); // speed signal
- AddInFloat("Starting point"); // min play pos
- AddInFloat("Ending point"); // max play pos
- for(int ci = 0; ci < outchns; ++ci) {
- char tmp[30];
- STD::sprintf(tmp,"Audio signal channel %i",ci+1);
- AddOutSignal(tmp); // output
- }
- AddOutSignal("Position currently played"); // position
- AddOutFloat("Starting point (rounded to frame)"); // play min
- AddOutFloat("Ending point (rounded to frame)"); // play max
- AddOutBang("Bang on loop end/rollover"); // loop bang
-
- // don't know vector size yet -> wait for m_dsp
- znbuf = new t_sample *[outchns];
- for(int i = 0; i < outchns; ++i) znbuf[i] = NULL;
-
- // initialize crossfade shape
- ms_xshape(xshape);
-}
-
-xgroove::~xgroove()
-{
- if(znbuf) {
- for(int i = 0; i < outchns; ++i) if(znbuf[i]) FreeAligned(znbuf[i]);
- delete[] znbuf;
- }
-
- if(znpos) FreeAligned(znpos);
- if(znidx) FreeAligned(znidx);
-}
-
-void xgroove::DoReset()
-{
- xinter::DoReset();
- curpos = 0;
- bidir = 1;
-}
-
-void xgroove::ms_xzone(float xz)
-{
- ChkBuffer(true);
-
- _xzone = (UNLIKELY(xz < 0) || UNLIKELY(!s2u))?0:xz/s2u;
- Update(xsc_fade,true);
-}
-
-void xgroove::ms_xshape(int sh)
-{
- if(UNLIKELY(sh < 0) || UNLIKELY(sh > xss_hsine)) sh = xss_lin;
-
- xshape = (xs_shape)sh;
- switch(xshape) {
- 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;
- }
-
- // no need to recalc the fade zone here
-}
-
-
-void xgroove::s_pos_off(int n,t_sample *const *invecs,t_sample *const *outvecs)
-{
- t_sample *pos = outvecs[outchns];
-
- SetSamples(pos,n,curpos);
-
- playfun(n,&pos,outvecs);
-
- SetSamples(pos,n,scale(curpos));
-}
-
-void xgroove::s_pos_once(int n,t_sample *const *invecs,t_sample *const *outvecs)
-{
- const t_sample *speed = invecs[0];
- t_sample *pos = outvecs[outchns];
- bool lpbang = false;
-
- const double smin = curmin,smax = curmax,plen = smax-smin;
-
- if(LIKELY(plen > 0)) {
- register double o = curpos;
-
- for(int i = 0; i < n; ++i) {
- const t_sample spd = speed[i]; // must be first because the vector is reused for output!
-
- if(UNLIKELY(!(o < smax))) { o = smax; lpbang = true; }
- else if(UNLIKELY(o < smin)) { o = smin; lpbang = true; }
-
- pos[i] = o;
- o += spd;
- }
- // normalize and store current playing position
- setpos(o);
-
- playfun(n,&pos,outvecs);
-
- arrscale(n,pos,pos);
- }
- else
- s_pos_off(n,invecs,outvecs);
-
- if(UNLIKELY(lpbang)) {
- doplay = false;
- ToOutBang(outchns+3);
- }
-}
-
-void xgroove::s_pos_loop(int n,t_sample *const *invecs,t_sample *const *outvecs)
-{
- const t_sample *speed = invecs[0];
- t_sample *pos = outvecs[outchns];
- bool lpbang = false;
-
-#ifdef __VEC__
- // prefetch cache
- vec_dst(speed,GetPrefetchConstant(1,n>>2,0),0);
-#endif
-
- const double smin = curmin,smax = curmax,plen = smax-smin;
-
- if(LIKELY(plen > 0)) {
- register double o = curpos;
-
- if(wrap && UNLIKELY(smin < 0) && UNLIKELY(smax >= buf.Frames())) {
- for(int i = 0; i < n; ++i) {
- const t_sample spd = speed[i]; // must be first because the vector is reused for output!
-
- // normalize offset
- if(UNLIKELY(!(o < smax))) { // faster than o >= smax
- o = fmod(o-smin,plen)+smin;
- lpbang = true;
- }
- else if(UNLIKELY(o < smin)) {
- o = fmod(o-smin,plen)+smax;
- lpbang = true;
- }
-
- // TODO normalize to 0...buf.Frames()
- pos[i] = o;
- o += spd;
- }
- }
- else {
- ///////////////////////////////////
- // Most of the time is spent in here
- ///////////////////////////////////
- for(int i = 0; i < n; ++i) {
- const t_sample spd = speed[i]; // must be first because the vector is reused for output!
-
- // normalize offset
- if(UNLIKELY(!(o < smax))) { // faster than o >= smax
- o = fmod(o-smin,plen)+smin;
- lpbang = true;
- }
- else if(UNLIKELY(o < smin)) {
- o = fmod(o-smin,plen)+smax;
- lpbang = true;
- }
-
- pos[i] = o;
- o += spd;
- }
- }
-
- // normalize and store current playing position
- setpos(o);
-
- playfun(n,&pos,outvecs);
-
- arrscale(n,pos,pos);
- }
- else
- s_pos_off(n,invecs,outvecs);
-
-#ifdef __VEC__
- vec_dss(0);
-#endif
-
- if(UNLIKELY(lpbang)) ToOutBang(outchns+3);
-}
-
-void xgroove::s_pos_loopzn(int n,t_sample *const *invecs,t_sample *const *outvecs)
-{
- const t_sample *speed = invecs[0];
- t_sample *pos = outvecs[outchns];
- bool lpbang = false;
-
- FLEXT_ASSERT(xzone);
-
- const float xz = xzone,xf = (float)XZONE_TABLE/xz;
-
- // adapt the playing bounds to the current cross-fade zone
- const long smin = znsmin,smax = znsmax,plen = smax-smin;
-
- // temporary storage
- const long cmin = curmin,cmax = curmax;
- // hack -> set curmin/curmax to loop extremes so that sampling functions (playfun) don't get confused
- curmin = smin,curmax = smax;
-
- if(LIKELY(plen > 0)) {
- bool inzn = false;
- register double o = curpos;
-
- // calculate inner cross-fade boundaries
- const double lmin = smin+xz,lmax = smax-xz,lsh = lmax-lmin+xz;
- const double lmin2 = lmin-xz/2,lmax2 = lmax+xz/2;
-
- for(int i = 0; i < n; ++i) {
- // normalize offset
- if(UNLIKELY(o < smin)) {
- o = fmod(o-smin,plen)+smax;
- lpbang = true;
- }
- else if(UNLIKELY(!(o < smax))) {
- o = fmod(o-smin,plen)+smin;
- lpbang = true;
- }
-
- if(UNLIKELY(o < lmin)) {
- register float inp;
- if(o < lmin2) {
- // in first half of early cross-fade zone
- // this happens only once, then the offset is normalized to the end
- // of the loop (before mid of late crossfade)
-
- o += lsh;
- // now lmax <= o <= lmax2
- lpbang = true;
-
- inp = xz-(float)(o-lmax); // 0 <= inp < xz
- znpos[i] = lmin-inp;
- }
- else {
- // in second half of early cross-fade zone
-
- inp = xz+(float)(o-lmin); // 0 <= inp < xz
- znpos[i] = lmax+inp;
- }
- znidx[i] = inp*xf;
- inzn = true;
- }
- else if(UNLIKELY(!(o < lmax))) {
- register float inp;
- if(!(o < lmax2)) {
- // in second half of late cross-fade zone
- // this happens only once, then the offset is normalized to the beginning
- // of the loop (after mid of early crossfade)
- o -= lsh;
- // now lmin2 <= o <= lmin
- lpbang = true;
-
- inp = xz+(float)(o-lmin); // 0 <= inp < xz
- znpos[i] = lmax+inp;
- }
- else {
- // in first half of late cross-fade zone
- inp = xz-(float)(o-lmax); // 0 <= inp < xz
- znpos[i] = lmin-inp;
- }
- znidx[i] = inp*xf;
- inzn = true;
- }
- else
- znidx[i] = XZONE_TABLE,znpos[i] = 0;
-
- const t_sample spd = speed[i]; // must be first because the vector is reused for output!
- pos[i] = o;
- o += spd;
- }
-
- // normalize and store current playing position
- setpos(o);
-
- // calculate samples (1st voice)
- playfun(n,&pos,outvecs);
-
- // rescale position vector
- arrscale(n,pos,pos);
-
- if(UNLIKELY(inzn)) {
- // only if we have touched the cross-fade zone
-
- // calculate samples in loop zone (2nd voice)
- playfun(n,&znpos,znbuf);
-
- // calculate counterpart in loop fade
- arrscale(n,znidx,znpos,XZONE_TABLE,-1);
-
- // calculate fade coefficients by sampling from the fade curve
- zonefun(znmul,0,XZONE_TABLE+1,n,1,1,&znidx,&znidx,false);
- zonefun(znmul,0,XZONE_TABLE+1,n,1,1,&znpos,&znpos,false);
-
- // mix voices for all channels
- for(int o = 0; o < outchns; ++o) {
- MulSamples(outvecs[o],outvecs[o],znidx,n);
- MulSamples(znbuf[o],znbuf[o],znpos,n);
- AddSamples(outvecs[o],outvecs[o],znbuf[o],n);
- }
- }
- }
- else
- s_pos_off(n,invecs,outvecs);
-
- curmin = cmin,curmax = cmax;
-
- if(UNLIKELY(lpbang)) ToOutBang(outchns+3);
-}
-
-void xgroove::s_pos_bidir(int n,t_sample *const *invecs,t_sample *const *outvecs)
-{
- const t_sample *speed = invecs[0];
- t_sample *pos = outvecs[outchns];
- bool lpbang = false;
-
- const int smin = curmin,smax = curmax,plen = smax-smin;
-
- if(LIKELY(plen > 0)) {
- register double o = curpos;
- register float bd = bidir;
-
- for(int i = 0; i < n; ++i) {
- const t_sample spd = speed[i]; // must be first because the vector is reused for output!
-
- // normalize offset
- // \todo at the moment fmod doesn't take bidirectionality into account!!
- if(UNLIKELY(!(o < smax))) {
- o = smax-fmod(o-smax,plen); // mirror the position at smax
- bd = -bd;
- lpbang = true;
- }
- else if(UNLIKELY(o < smin)) {
- o = smin+fmod(smin-o,plen); // mirror the position at smin
- bd = -bd;
- lpbang = true;
- }
-
- pos[i] = o;
- o += spd*bd;
- }
- // normalize and store current playing position
- setpos(o);
-
- bidir = bd;
- playfun(n,&pos,outvecs);
-
- arrscale(n,pos,pos);
- }
- else
- s_pos_off(n,invecs,outvecs);
-
- if(UNLIKELY(lpbang)) ToOutBang(outchns+3);
-}
-
-void xgroove::CbSignal()
-{
- int ret = ChkBuffer(true);
-
- if(LIKELY(ret)) {
- FLEXT_ASSERT(buf.Valid());
-
- const lock_t l = Lock();
- posfun(Blocksize(),InSig(),OutSig());
- Unlock(l);
-
- Refresh();
- }
- else
- zerofun(Blocksize(),InSig(),OutSig());
-}
-
-
-void xgroove::DoUpdate(unsigned int flags)
-{
- xinter::DoUpdate(flags);
-
- if(flags&xsc_range) {
- // output new range
- ToOutFloat(outchns+1,curmin*s2u);
- ToOutFloat(outchns+2,curmax*s2u);
- }
-
- if(flags&(xsc_fade|xsc_range))
- if(do_xzone()) flags |= xsc_play;
-
- if(flags&(xsc_pos|xsc_range))
- // normalize position
- setpos(curpos);
-
- // loop zone must already be set
- if(flags&xsc_play) {
- if(doplay) {
- switch(loopmode) {
- case xsl_once:
- SETSIGFUN(posfun,SIGFUN(s_pos_once));
- break;
- case xsl_loop:
- if(xzone > 0) {
- const int blksz = Blocksize();
-
- if(pblksz != blksz) {
- for(int o = 0; o < outchns; ++o) {
- if(znbuf[o]) FreeAligned(znbuf[o]);
- znbuf[o] = (t_sample *)NewAligned(blksz*sizeof(t_sample));
- }
-
- if(znpos) FreeAligned(znpos);
- znpos = (t_sample *)NewAligned(blksz*sizeof(t_sample));
- if(znidx) FreeAligned(znidx);
- znidx = (t_sample *)NewAligned(blksz*sizeof(t_sample));
-
- pblksz = blksz;
- }
-
- SETSIGFUN(posfun,SIGFUN(s_pos_loopzn));
-
- // linear interpolation should be just ok for fade zone, no?
- switch(outchns) {
- case 1: SETSTFUN(zonefun,TMPLSTF(st_play2,1,1)); break;
- case 2: SETSTFUN(zonefun,TMPLSTF(st_play2,1,2)); break;
- case 4: SETSTFUN(zonefun,TMPLSTF(st_play2,1,4)); break;
- default: SETSTFUN(zonefun,TMPLSTF(st_play2,1,-1));
- }
- }
- else
- SETSIGFUN(posfun,SIGFUN(s_pos_loop));
- break;
- case xsl_bidir:
- SETSIGFUN(posfun,SIGFUN(s_pos_bidir));
- break;
- default: ; // just to prevent warning
- }
- }
- else
- SETSIGFUN(posfun,SIGFUN(s_pos_off));
- }
-}
-
-bool xgroove::do_xzone()
-{
- // \todo do we really need this?
- if(UNLIKELY(!s2u)) return false; // this can happen if DSP is off
-
- const long frames = buf.Frames();
- if(UNLIKELY(!frames)) return false;
-
- xzone = _xzone; // make a copy for changing it
-
- if(xfade == xsf_inside) {
- // fade zone goes inside the loop -> loop becomes shorter
-
- // \todo what about round-off?
- const long maxfd = (curmax-curmin)/2;
- if(xzone > maxfd) xzone = maxfd;
-
- znsmin = curmin,znsmax = curmax;
- }
- else if(xfade == xsf_keepfade) {
- // try to keep fade zone
- // change of loop bounds may happen
-
- // restrict xzone to half of buffer
- const long maxfd = frames/2;
- if(xzone > maxfd) xzone = maxfd;
-
- // \todo what about round-off?
- const long hzone = CASTINT<long>(xzone/2.f+0.5f);
- znsmin = curmin-hzone;
- znsmax = curmax+hzone;
-
- // widen loop if xzone doesn't fit into it
- // \todo check formula
- long lack = CASTINT<long>(ceil((xzone*2.f-(znsmax-znsmin))/2.f));
- if(lack > 0) znsmin -= lack,znsmax += lack;
-
- if(!wrap) {
- // check buffer limits and shift bounds if necessary
- if(znsmin < 0) {
- znsmax -= znsmin;
- znsmin = 0;
- }
- if(znsmax > frames)
- znsmax = frames;
- }
- }
- else if(xfade == xsf_keeplooplen) {
- // try to keep loop length
- // shifting of loop bounds may happen
-
- const long plen = curmax-curmin;
- if(xzone > plen) xzone = plen;
- const long maxfd = frames-plen;
- if(xzone > maxfd) xzone = maxfd;
-
- // \todo what about round-off?
- const long hzone = CASTINT<long>(xzone/2.f+0.5f);
- znsmin = curmin-hzone;
- znsmax = curmax+hzone;
-
- if(!wrap) {
- // check buffer limits and shift bounds if necessary
- // both cases can't happen because of xzone having been limited above
- if(znsmin < 0) {
- znsmax -= znsmin;
- znsmin = 0;
- }
- else if(znsmax > frames) {
- znsmin -= znsmax-frames;
- znsmax = frames;
- }
- }
- }
- else if(xfade == xsf_keeplooppos) {
- // try to keep loop position and length
-
- // restrict fade zone to maximum length
- const long plen = curmax-curmin;
- if(xzone > plen) xzone = plen;
-
- // \todo what about round-off?
- const long hzone = CASTINT<long>(xzone/2.f+0.5f);
- znsmin = curmin-hzone;
- znsmax = curmax+hzone;
-
- long ovr = znsmax-frames;
- if(-znsmin > ovr) ovr = -znsmin;
- if(ovr > 0) {
- znsmin += ovr;
- znsmax -= ovr;
- xzone -= ovr*2;
- }
- }
-
- FLEXT_ASSERT(znsmin <= znsmax && (znsmax-znsmin) >= xzone*2.f);
-
- return true;
-}
-
-
-void xgroove::m_help()
-{
- post("%s - part of xsample objects, version " XSAMPLE_VERSION,thisName());
- post("(C) Thomas Grill, 2001-2007");
-#if FLEXT_SYS == FLEXT_SYS_MAX
- post("Arguments: %s [channels=1] [buffer]",thisName());
-#else
- post("Arguments: %s [buffer]",thisName());
-#endif
- post("Inlets: 1:Messages/Speed signal, 2:Min position, 3:Max position");
- post("Outlets: 1:Audio signal, 2:Position signal, 3:Min position (rounded), 4:Max position (rounded)");
- post("Methods:");
- post("\thelp: shows this help");
- post("\tset [name] / @buffer [name]: set buffer or reinit");
- post("\tenable 0/1: turn dsp calculation off/on");
- post("\treset: reset min/max playing points and playing offset");
- post("\tprint: print current settings");
- post("\t@loop 0/1/2: sets looping to off/forward/bidirectional");
- post("\t@interp 0/1/2: set interpolation to off/4-point/linear");
- post("\t@min {unit}: set minimum playing point");
- post("\t@max {unit}: set maximum playing point");
- post("\tall: select entire buffer length");
- post("\tpos {unit}: set playing position (obeying the current scale mode)");
- post("\tposmod {unit}: set playing position (modulo into min/max range)");
- post("\tbang/start: start playing");
- post("\tstop: stop playing");
- post("\trefresh: checks buffer and refreshes outlets");
- 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@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("");
-}
-
-void xgroove::m_print()
-{
- static const char *sclmode_txt[] = {"units","units in loop","buffer","loop"};
- static const char *interp_txt[] = {"off","4-point","linear"};
- static const char *loop_txt[] = {"once","looping","bidir"};
-
- // print all current settings
- post("%s - current settings:",thisName());
- post("bufname = '%s', length = %.3f, channels = %i",buf.Name(),(float)(buf.Frames()*s2u),buf.Channels());
- post("out channels = %i, frames/unit = %.3f, scale mode = %s",outchns,(float)(1./s2u),sclmode_txt[sclmode]);
- post("loop = %s, interpolation = %s",loop_txt[(int)loopmode],interp_txt[interp >= xsi_none && interp <= xsi_lin?interp:xsi_none]);
- post("loop crossfade zone = %.3f",(float)(xzone*s2u));
- post("");
-}