Logo Search packages:      
Sourcecode: csound version File versions  Download package

sndloop.c

/*  sndloop.c sndloop flooper pvsarp pvsvoc

(c) Victor Lazzarini, 2004

This file is part of Csound.

The Csound Library is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

Csound is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with Csound; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA

SNDLOOP

asig, krec  sndloop  ain, kpitch, ktrig, idur, ifad

A sound looper with pitch control.

INIT

idur - loop duration in seconds
ifad - crossfade duration in seconds

PERFORMANCE

asig - output signal
krec - 'rec on' signal, 1 when recording, 0 otherwise
kpitch - pitch control (transposition ratio)
kon - on signal: when 0, processing is bypassed. When switched on (kon >= 1),
the opcode starts recording until the loop memory is full. It then plays
the looped sound until it is switched off again (kon = 0). Another recording
can start again with kon >= 1.

FLOOPER

asig flooper kamp, kpitch, istart, idur, ifad, ifn

Function-table crossfading looper.

INIT

istart - starting point of loop (in secs)
idur - loop duration (secs)
ifad - crossfade duration (secs)

PERFORMANCE

asig - output signal
kamp - amplitude scaling
kpitch - pitch control (transposition ratio)

FLOOPER2

asig flooper2 kamp, kpitch, kloopstart, kloopend, kcrossfade, ifn [, istart, imode, ifenv]

Function-table crossfading looper with variable loop parameters and
different looping modes.

INIT

ifn - sound source function table. Non-power-of-two and deferred allocation
tables are allowed.
istart - playback starting point in secs, only applicable to loop modes 0 & 2 [def:0]
imode - loop modes: 0 forward, 1 backward, 2 back-and-forth [def: 0]
ifenv - if non-zero, crossfade envelope shape table number. 0, the default, sets
the crossfade to linear.

PERFORMANCE

kamp - amplitude scaling
kpitch - playback pitch ratio (1 - normal, > 1 faster, < 1 slower). Negative
ratios are not allowed.
kloopstart - loop start point (secs). Note that although k-rate, loop parameters
such as this are only updated once per loop cycle.
kloopend - loop end point (secs), updated once per loop cycle.
kcrossfade - crossfade length (secs), updated once per loop cycle and limited to
loop length.


PVSARP

fsig pvsarp fin, kcf, kdepth, kgain

Spectral arpeggiator

PERFORMANCE

fin - input pv streaming signal
kcf - centre freq of arpeggiation (normalised 0 - 1.0,
corresponding to 0 - Nyquist)
kdepth - depth of attenuation of surrounding frequency bins
kgain - gain applied to the bin at the centre frequency

PVSVOC

fsig pvsvoc fenv,fexc,kdepth, kgain

Applies the spectral envelope of one sound to the frequencies (excitation) of
another.

PERFORMANCE

fenv - spectral envelope signal
fexc - excitation signal
kdepth - depth of effect (0-1)
kgain - signal gain

*/

#include "csdl.h"
#include "pstream.h"

typedef struct _sndloop {
  OPDS h;
  MYFLT *out, *recon;       /* output,record on */
  MYFLT *sig, *pitch, *on;  /* in, pitch, sound on */
  MYFLT *dur, *cfd;         /* duration, crossfade  */
  AUXCH buffer;             /* loop memory */
  long  wp;                 /* writer pointer */
  double rp;                /* read pointer  */
  long  cfds;               /* crossfade in samples */
  long durs;                /* duration in samples */
  int  rst;                 /* reset indicator */
  MYFLT inc;                /* fade in/out increment/decrement */
  MYFLT  a;                 /* fade amp */
} sndloop;

typedef struct _flooper {
  OPDS h;
  MYFLT *out;  /* output */
  MYFLT *amp, *pitch, *start, *dur, *cfd, *ifn;
  AUXCH buffer; /* loop memory */
  FUNC  *sfunc;  /* function table */
  long strts;   /* start in samples */
  long  durs;    /* duration in samples */
  double  ndx;    /* table lookup ndx */
  int   loop_off;
} flooper;


typedef struct _flooper2 {
  OPDS h;
  MYFLT *out;  /* output */
  MYFLT *amp, *pitch, *loop_start, *loop_end,
    *crossfade, *ifn, *start, *imode, *ifn2, *iskip;
  FUNC  *sfunc;  /* function table */
  FUNC *efunc;
  MYFLT count;
  int lstart, lend,cfade, mode;
  double  ndx[2];    /* table lookup ndx */
  int firsttime, init;
} flooper2;


typedef struct _flooper3 {
  OPDS h;
  MYFLT *out;  /* output */
  MYFLT *amp, *pitch, *loop_start, *loop_end,
    *crossfade, *ifn, *start, *imode, *ifn2, *iskip;
  FUNC  *sfunc;  /* function table */
  FUNC *efunc;
  long count;
  int lstart, lend,cfade, mode;
  long  ndx[2];    /* table lookup ndx */
  int firsttime, init;
  int lobits,lomask;
  MYFLT lodiv;
} flooper3;

typedef struct _pvsarp {
  OPDS h;
  PVSDAT  *fout;
  PVSDAT  *fin;
  MYFLT   *cf;
  MYFLT   *kdepth;
  MYFLT   *gain;
  unsigned long   lastframe;
}
  pvsarp;

typedef struct _pvsvoc {
  OPDS h;
  PVSDAT  *fout;
  PVSDAT  *fin;
  PVSDAT  *ffr;
  MYFLT   *kdepth;
  MYFLT   *gain;
  unsigned long   lastframe;
}
  pvsvoc;

static int sndloop_init(CSOUND *csound, sndloop *p)
{
    p->durs = (long) (*(p->dur)*csound->esr); /* dur in samps */
    p->cfds = (long) (*(p->cfd)*csound->esr); /* fade in samps */
    p->inc  = FL(1.0)/p->cfds;    /* inc/dec */
    p->a    = FL(0.0);
    p->wp   = 0;   /* intialise write pointer */
    p->rst  = 1;       /* reset the rec control */
    if(p->buffer.auxp==NULL ||
       p->buffer.size<p->durs*sizeof(MYFLT))   /* allocate memory if necessary */
      csound->AuxAlloc(csound, p->durs*sizeof(MYFLT), &p->buffer);
    return OK;
}

static int sndloop_process(CSOUND *csound, sndloop *p)
{
    int i, on = (int) *(p->on), recon, n = csound->ksmps;
    long durs = p->durs, cfds = p->cfds, wp = p->wp;
    double rp = p->rp;
    MYFLT a = p->a, inc = p->inc;
    MYFLT *out = p->out, *sig = p->sig, *buffer = p->buffer.auxp;
    MYFLT pitch = *(p->pitch);

    if (on) recon = p->rst; /* restart recording if switched on again */
    else recon = 0;  /* else do not record */

    for (i=0; i < n; i++) {
      if (recon) { /* if the recording is ON */
        /* fade in portion */
        if (wp < cfds) {
          buffer[wp] = sig[i]*a;
          a += inc;
        }
        else {
          if (wp >= durs) { /* fade out portion */
            buffer[wp-durs] += sig[i]*a;
            a -= inc;
          }
          else buffer[wp] = sig[i];  /* middle of loop */
        }
        /* while recording connect input to output directly */
        out[i] = sig[i];
        wp++; /* increment writer pointer */
        if (wp == durs+cfds) {  /* end of recording */
          recon = 0;  /* OFF */
          p->rst = 0; /* reset to 0 */
          p->rp = (MYFLT) wp; /* rp pointer to start from here */
        }
      }
      else {
        if (on) { /* if opcode is ON */
          out[i] = buffer[(int)rp]; /* output the looped sound */
          rp += pitch;        /* read pointer increment */
          while (rp >= durs) rp -= durs; /* wrap-around */
          while (rp < 0) rp += durs;
        }
        else {   /* if opocde is OFF */
          out[i] = sig[i]; /* copy input to the output */
          p->rst = 1;   /* reset: ready for new recording */
          wp = 0; /* zero write pointer */
        }
      }
    }
    p->rp = rp; /* keep the values */
    p->wp = wp;
    p->a = a;
    *(p->recon) = (MYFLT) recon; /* output 'rec on light' */

    return OK;
}

static int flooper_init(CSOUND *csound, flooper *p)
{
    MYFLT *tab, *buffer, a = (MYFLT) 0, inc;
    long cfds = (long) (*(p->cfd)*csound->esr);     /* fade in samps  */
    long starts = (long) (*(p->start)*csound->esr); /* start in samps */
    long durs = (long)  (*(p->dur)*csound->esr);    /* dur in samps   */
    long len, i;

    if (cfds > durs) {
      return csound->InitError(csound,
                               Str("crossfade longer than loop duration\n"));
    }

    inc =  FL(1.0)/cfds;    /* inc/dec */
    p->sfunc = csound->FTnp2Find(csound, p->ifn);  /* function table */
    if (p->sfunc==NULL) {
      return csound->InitError(csound,Str("function table not found\n"));
    }
    tab = p->sfunc->ftable,  /* func table pointer */
      len = p->sfunc->flen;    /* function table length */
    if (starts > len) {
      return csound->InitError(csound,Str("start time beyond end of table\n"));
    }

    if (starts+durs+cfds > len) {
      return csound->InitError(csound,Str("table not long enough for loop\n"));
    }

    if (p->buffer.auxp==NULL ||
        p->buffer.size<(durs+1)*sizeof(MYFLT))   /* allocate memory if necessary */
      csound->AuxAlloc(csound,(durs+1)*sizeof(MYFLT), &p->buffer);

    inc = (MYFLT)1/cfds;       /* fade envelope incr/decr */
    buffer = p->buffer.auxp;   /* loop memory */

    /* we now write the loop into memory */
    for (i=0; i < durs; i++) {
      if (i < cfds) {
        buffer[i] = a*tab[i+starts];
        a += inc;
      }
      else buffer[i] = tab[i+starts];;
    }
    /*  crossfade section */
    for (i=0; i  < cfds; i++) {
      buffer[i] += a*tab[i+starts+durs];
      a -= inc;
    }

    buffer[durs] = buffer[0]; /* for wrap-around interpolation */
    p->strts     = starts;
    p->durs      = durs;
    p->ndx       = FL(0.0);   /* lookup index */
    p->loop_off  = 1;
    return OK;
}

static int flooper_process(CSOUND *csound, flooper *p)
{
  int i, n = csound->ksmps;
  long end = p->strts+p->durs, durs = p->durs;
  MYFLT *out = p->out, *buffer = p->buffer.auxp;
  MYFLT amp = *(p->amp), pitch = *(p->pitch);
  MYFLT *tab = p->sfunc->ftable;
  double ndx = p->ndx;
  MYFLT  frac;
  int tndx, loop_off = p->loop_off;

  for (i=0; i < n; i++) {
    tndx = (int) ndx;
    frac = ndx - tndx;
    /* this is the start portion of the sound */
    if (ndx >= 0  && ndx < end && loop_off) {
      out[i] = amp*(tab[tndx] + frac*(tab[tndx+1] - tab[tndx]));
      ndx += pitch;
    }
    /* this is the loop section */
    else {
      if(loop_off) {
        ndx -= end;
        tndx -= end;
        /* wrap-around, if reading backwards */
        while (tndx < 0) tndx += durs;
      }
      loop_off = 0;
      out[i] = amp*(buffer[tndx] + frac*(buffer[tndx+1] - buffer[tndx]));
      ndx += pitch;
      while (ndx < 0) ndx += durs;
      while (ndx >= durs) ndx -= durs;

    }

  }
  p->ndx = ndx;
  p->loop_off = loop_off;
  return OK;
}

static int flooper2_init(CSOUND *csound, flooper2 *p)
{

  p->sfunc = csound->FTnp2Find(csound, p->ifn);  /* function table */
  if (p->sfunc==NULL) {
    return csound->InitError(csound,Str("function table not found\n"));
  }
  if(*p->ifn2 != 0) p->efunc = csound->FTFind(csound, p->ifn2);
  else p->efunc = NULL;

  if(*p->iskip == 0){
  p->mode = (int) *p->imode;
  if(p->mode == 0 || p->mode == 2){
    if((p->ndx[0] = *p->start*csound->GetSr(csound)) < 0)
      p->ndx[0] = 0;
    if(p->ndx[0] >= p->sfunc->flen)
      p->ndx[0] = (double) p->sfunc->flen - 1.;
    p->count = 0;
  }
  p->init = 1;
  p->firsttime = 1;
  }
  return OK;
}

static int flooper2_process(CSOUND *csound, flooper2 *p)
{
    int i, n = csound->ksmps;
    MYFLT *out = p->out, sr = csound->GetSr(csound);
    MYFLT amp = *(p->amp), pitch = *(p->pitch);
    MYFLT *tab = p->sfunc->ftable;
    double *ndx = p->ndx;
    MYFLT frac0, frac1, *etab;
    int loop_end = p->lend, loop_start = p->lstart,
        crossfade = p->cfade, len = p->sfunc->flen;
    MYFLT count = p->count,fadein, fadeout;
    int *firsttime = &p->firsttime, elen, mode=p->mode, init = p->init;
    unsigned long tndx0, tndx1;

    if (p->efunc != NULL) {
      etab = p->efunc->ftable;
      elen = p->efunc->flen;
    }
    else {
      etab = NULL;
      elen = 0;
    }

    /* loop parameters & check */
    if (pitch < FL(0.0)) pitch = FL(0.0);

    if (*firsttime) {
      int loopsize;
      loop_start = (int) (*p->loop_start*sr);
      loop_end =   (int) (*p->loop_end*sr);
      p->lstart = loop_start = loop_start < 0 ? 0 : loop_start;
      p->lend = loop_end =   loop_end > len ? len :
        (loop_end < loop_start ? loop_start : loop_end);
      loopsize = loop_end - loop_start;
      crossfade = (int) (*p->crossfade*sr);

      if (mode == 1) {
        ndx[0] = (double) loop_end;
        ndx[1] = (double) loop_end;
        count = (MYFLT) crossfade;
        p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade;
      }
      else if (mode == 2) {
        ndx[1] = (double) loop_start - FL(1.0);
        p->cfade = crossfade = crossfade > loopsize/2 ? loopsize/2-1 : crossfade;
      }
      else {
     ndx[1] = (double) loop_start;
     p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade;
      }
      *firsttime = 0;
    }
    for (i=0; i < n; i++) {
      if (mode == 1){ /* backwards */
        tndx0 = (int) ndx[0];
        frac0 = ndx[0] - tndx0;
        if (ndx[0] > crossfade + loop_start)
          out[i] = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]));
        else {
          tndx1 = (int) ndx[1];
          frac1 = ndx[1] - tndx1;
          if (etab==NULL){
            fadeout = count/crossfade;
            fadein = FL(1.0) - fadeout;
          }
          else {
            fadeout = elen*count/crossfade;
            fadein = etab[elen - (int)fadeout];
            fadeout = etab[(int)fadeout];
          }
          out[i] = amp*(fadeout*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]))
                        + fadein*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1])));
          ndx[1]-=pitch;
          count-=pitch;
        }
        ndx[0]-=pitch;

        if (ndx[0] <= loop_start) {
          int loopsize;
          loop_start = (int) (*p->loop_start*sr);
          loop_end =   (int) (*p->loop_end*sr);
          p->lstart = loop_start = loop_start < 0 ? 0 : loop_start;
          p->lend = loop_end =   loop_end > len ? len :
            (loop_end < loop_start ? loop_start : loop_end);
          loopsize = loop_end - loop_start;
          crossfade = (int) (*p->crossfade*sr);
          p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade;
          ndx[0] = ndx[1];
          ndx[1] =  (double)loop_end;
          count=(MYFLT)crossfade;
        }
      }
      else if (mode==2) { /* back and forth */
        out[i] = 0;
        /* this is the forward reader */
        if (init && ndx[0] < loop_start + crossfade) {
          tndx0 = (int) ndx[0];
          frac0 = ndx[0] - tndx0;
          out[i] = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]));
          ndx[0] += pitch;
        }
        else if (ndx[0] < loop_start + crossfade) {
          if (etab==NULL) fadein = count/crossfade;
          else fadein = etab[(int)(elen*count/crossfade)];
          tndx0 = (int) ndx[0];
          frac0 = ndx[0] - tndx0;
          out[i] += amp*fadein*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]));
          ndx[0] += pitch;
          count  += pitch;
        }
        else if(ndx[0] < loop_end - crossfade) {
          tndx0 = (int) ndx[0];
          frac0 = ndx[0] - tndx0;
          out[i] = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]));
          ndx[0] += pitch;
          init = 0;
          if (ndx[0] >= loop_end - crossfade) {
            ndx[1] = (double) loop_end;
            count = 0;
          }
        }
        else if (ndx[0] < loop_end) {
          if(etab==NULL) fadeout = FL(1.0) - count/crossfade;
          else  fadeout = etab[(int)(elen*(1.0 - count/crossfade))];
          tndx0 = (int) ndx[0];
          frac0 = ndx[0] - tndx0;
          out[i] += amp*fadeout*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]));
          ndx[0] += pitch;
          count  += pitch;
        }
        /* this is the backward reader */
        if (ndx[1] > loop_end - crossfade) {
          if (etab==NULL) fadein = count/crossfade;
          else fadein = etab[(int)(elen*count/crossfade)];
          tndx1 = (int) ndx[1];
          frac1 = ndx[1] - tndx1;
          out[i] += amp*fadein*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1]));
          ndx[1] -= pitch;
        }
        else if(ndx[1] > loop_start + crossfade) {
          tndx1 = (int) ndx[1];
          frac1 = ndx[1] - tndx1;
          out[i] = amp*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1]));
          ndx[1] -= pitch;
          if (ndx[1] <= loop_start + crossfade) {
            ndx[0] = (double) loop_start;
            count = 0;
          }
        }
        else if (ndx[1] > loop_start) {
          if(etab==NULL) fadeout = FL(1.0) - count/crossfade;
          else fadeout = etab[(int)(elen*(1.0 - count/crossfade))];
          tndx1 = (int) ndx[1];
          frac1 = ndx[1] - tndx1;
          out[i] += amp*fadeout*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1]));
          ndx[1] -= pitch;
          if (ndx[1] <= loop_start) {
            int loopsize;
            loop_start = (int) (*p->loop_start*sr);
            loop_end =   (int) (*p->loop_end*sr);
            p->lstart = loop_start = loop_start < 0 ? 0 : loop_start;
            p->lend = loop_end =   loop_end > len ? len :
              (loop_end < loop_start ? loop_start : loop_end);
            loopsize = loop_end - loop_start;
            crossfade = (int) (*p->crossfade*sr);
            p->cfade = crossfade = crossfade > loopsize/2 ? loopsize/2-1 : crossfade;
          }
        }
      }
      else {  /* normal */
        out[i] = 0;
        tndx0 = (unsigned long) ndx[0];
        frac0 = ndx[0] - tndx0;
        if (ndx[0] < loop_end-crossfade)
          out[i] = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]));
        else {
          tndx1 = (int) ndx[1];
          frac1 = ndx[1] - tndx1;
          if (etab==NULL) {
            fadein = count/crossfade;
            fadeout = FL(1.0) - fadein;
          }
          else {
            fadein = elen*count/crossfade;
            fadeout = etab[elen - (int)fadein];
            fadein = etab[(int)fadein];
          }
          out[i] = amp*(fadeout*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]))
                        + fadein*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1])));
          ndx[1]+=pitch;
          count+=pitch;
        }
        ndx[0]+=pitch;
        if (ndx[0] >= loop_end) {
          int loopsize;
          loop_start = (int) (*p->loop_start*sr);
          loop_end =   (int) (*p->loop_end*sr);
          p->lstart = loop_start = loop_start < 0 ? 0 : loop_start;
          p->lend = loop_end =   loop_end > len ? len :
            (loop_end < loop_start ? loop_start : loop_end);
          loopsize = loop_end - loop_start;
          crossfade = (int) (*p->crossfade*sr);
          p->cfade = crossfade = crossfade > loopsize ? loopsize-1 : crossfade;
          ndx[0] = ndx[1];
          ndx[1] = (double)loop_start;
          count=0;
        }
      }
    }

    p->count = count;
    p->cfade = crossfade;
    p->lend = loop_end;
    p->lstart = loop_start;
    p->init = init;
    return OK;
}



static int flooper3_init(CSOUND *csound, flooper3 *p)
{
  int len,i,p2s,lomod;
  p->sfunc = csound->FTnp2Find(csound, p->ifn);  /* function table */
  if (p->sfunc==NULL) {
    return csound->InitError(csound,Str("function table not found\n"));
  }
  if(*p->ifn2 != 0) p->efunc = csound->FTFind(csound, p->ifn2);
  else p->efunc = NULL;

  len = p->sfunc->flen;
  p->lobits = 0;
  for(i=1; i < len; i<<=1);
  p2s = i;
  for(;(i & MAXLEN)==0; p->lobits++, i<<=1);
  lomod = MAXLEN/p2s;
  p->lomask = lomod - 1;
  p->lodiv = 1.0/lomod;

  if(*p->iskip == 0){
    p->mode = (int) *p->imode;
    if(p->mode == 0 || p->mode == 2){
      if((p->ndx[0] = *p->start*csound->GetSr(csound)) < 0)
        p->ndx[0] = 0;
      if(p->ndx[0] >= p->sfunc->flen)
        p->ndx[0] = p->sfunc->flen - 1.;
      p->count = 0;
    }
    p->init = 1;
    p->firsttime = 1;
    p->ndx[0] <<= p->lobits;

  }
  return OK;
}

static int flooper3_process(CSOUND *csound, flooper3 *p)
{
  int i, n = csound->ksmps, lobits = p->lobits,si,ei;
  MYFLT *out = p->out, sr = csound->GetSr(csound);
  MYFLT amp = *(p->amp), pitch = *(p->pitch);
  MYFLT *tab = p->sfunc->ftable, cvt;
  long *ndx = p->ndx, lomask = p->lomask, pos;
  MYFLT frac0, frac1, *etab, lodiv = p->lodiv;
  int loop_end = p->lend, loop_start = p->lstart, mode = p->mode,
    crossfade = p->cfade, len = p->sfunc->flen, count = p->count;
  MYFLT fadein, fadeout;
  int *firsttime = &p->firsttime, elen, init = p->init;
  unsigned long tndx0, tndx1;

  /* loop parameters & check */
  if (pitch < FL(0.0)) pitch = FL(0.0);
  if (*firsttime) {
    int loopsize;
    loop_start = MYFLT2LRND(*p->loop_start*sr);
    loop_end =   MYFLT2LRND (*p->loop_end*sr);
    p->lstart = loop_start = (loop_start < 0 ? 0 : loop_start);
    p->lend = loop_end =   (loop_end > len ? len :
                            (loop_end < loop_start ? loop_start : loop_end));
    loopsize = loop_end - loop_start;
    crossfade = MYFLT2LRND(*p->crossfade*sr);

    if (mode == 1) {
      ndx[0] = loop_end<<lobits;
      ndx[1] = loop_end<<lobits;
      count = crossfade<<lobits;
      p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade;
    }
    else if (mode == 2) {
      ndx[1] = (loop_start-1)<<lobits;
      p->cfade = crossfade = crossfade > loopsize/2 ? loopsize/2-1 : crossfade;
    }
    else {
      ndx[1] = loop_start<<lobits;
      p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade;
    }
    *firsttime = 0;
  }

  if (p->efunc != NULL) {
    etab = p->efunc->ftable;
    elen = p->efunc->flen;
  }
  else {
    etab = NULL;
    elen = 1;
  }
  cvt = (MYFLT )elen/p->cfade;
  si = MYFLT2LRND(pitch*(lomask));
  ei = MYFLT2LRND(pitch*(lomask));

  for (i=0; i < n; i++) {
    if(mode == 0){
      tndx0 = ndx[0]>>lobits;
      frac0 = (ndx[0] & lomask)*lodiv;
      if (tndx0 < loop_end-crossfade)
        out[i] = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]));
      else {
        tndx1 = ndx[1]>>lobits;
        frac1 = (ndx[1] & lomask)*lodiv;
        if (etab==NULL) {
          fadein = (count>>lobits)*cvt;
          fadeout = FL(1.0) - fadein;
        }
        else {
          pos = MYFLT2LRND((count>>lobits)*cvt);
          fadein = etab[pos];
          fadeout = etab[elen - pos];
        }
        out[i] = amp*(fadeout*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]))
                      + fadein*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1])));

        ndx[1]+=si;
        count+=ei;
      }
      ndx[0]+=si;
      if (tndx0 >= loop_end) {
        int loopsize;
        loop_start = MYFLT2LRND(*p->loop_start*sr);
        loop_end =   MYFLT2LRND(*p->loop_end*sr);
        p->lstart = loop_start = (loop_start < 0 ? 0 : loop_start);
        p->lend = loop_end =   (loop_end > len ? len :
                                (loop_end < loop_start ? loop_start : loop_end));
        loopsize = (loop_end - loop_start);
        crossfade =  MYFLT2LRND(*p->crossfade*sr);
        p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade;
        ndx[0] = ndx[1];
        ndx[1] = loop_start<<lobits;
        count=0;
        cvt = (MYFLT)elen/p->cfade;
      }
    }
    else if (mode == 1) {
      tndx0 = ndx[0]>>lobits;
      frac0 = (ndx[0] & lomask)*lodiv;
      if (tndx0 > crossfade + loop_start)
        out[i] = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]));
      else {
        tndx1 = ndx[1]>>lobits;
        frac1 = (ndx[1] & lomask)*lodiv;
        if (etab==NULL) {
          fadeout = (count>>lobits)*cvt;
          fadein = FL(1.0) - fadeout;
        }
        else {
          pos = MYFLT2LRND((count>>lobits)*cvt);
          fadeout = etab[pos];
          fadein = etab[elen - pos];
        }
        out[i] = amp*(fadeout*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]))
                      + fadein*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1])));

        ndx[1]-=si;
        count-=ei;
      }
      ndx[0]-=si;

      if (tndx0 <= loop_start) {
        int loopsize;
        loop_start = MYFLT2LRND(*p->loop_start*sr);
        loop_end =   MYFLT2LRND(*p->loop_end*sr);
        p->lstart = loop_start = (loop_start < 0 ? 0 : loop_start);
        p->lend = loop_end =   (loop_end > len ? len :
                                (loop_end < loop_start ? loop_start : loop_end));
        loopsize = (loop_end - loop_start);
        crossfade =  MYFLT2LRND(*p->crossfade*sr);
        p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade;
        ndx[0] = ndx[1];
        ndx[1] = loop_end<<lobits;
        count=crossfade<<lobits;
        cvt = (MYFLT)elen/p->cfade;
      }
    }
    else if (mode == 2){
      out[i] = 0;
      /* this is the forward reader */
      tndx0 = ndx[0]>>lobits;
      frac0 = (ndx[0] & lomask)*lodiv;
      if (init && tndx0 < loop_start + crossfade) {
        out[i] = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]));
        ndx[0] += si;
      }
      else if (tndx0 < loop_start + crossfade) {
        if (etab==NULL) fadein = (count>>lobits)*cvt;
        else {
          pos = MYFLT2LRND((count>>lobits)*cvt);
          fadein = etab[pos];
        }
        out[i] += amp*fadein*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]));
        ndx[0] += si;
        count  += ei;
      }
      else if(tndx0 < loop_end - crossfade) {
        out[i] = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]));
        ndx[0] += si;
        init = 0;
        tndx0 = ndx[0]>>lobits;
        if (tndx0 >= loop_end - crossfade) {
          ndx[1] = loop_end<<lobits;
          count = 0;
        }
      }
      else if (tndx0 < loop_end) {
        if (etab==NULL) fadeout = FL(1.0) - (count>>lobits)*cvt;
        else {
          pos = MYFLT2LRND((count>>lobits)*cvt);
          fadeout = etab[elen - pos];
        }
        out[i] += amp*fadeout*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0]));
        ndx[0] += si;
        count  += ei;
      }

      /* this is the backward reader */
      tndx1 = ndx[1]>>lobits;
      frac1 = (ndx[1] & lomask)*lodiv;
      if (tndx1 > loop_end - crossfade) {
        if (etab==NULL) fadein = (count>>lobits)*cvt;
        else {
          pos = MYFLT2LRND((count>>lobits)*cvt);
          fadein = etab[pos];
        }
        out[i] += amp*fadein*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1]));
        ndx[1] -= si;
      }
      else if(tndx1 > loop_start + crossfade) {
        out[i] = amp*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1]));
        ndx[1] -= si;
        tndx1 = ndx[1]>>lobits;
        if (tndx1 <= loop_start + crossfade) {
          ndx[0] = loop_start<<lobits;
          count = 0;
        }
      }
      else if (tndx1 > loop_start) {
        if (etab==NULL) fadeout = FL(1.0) - (count>>lobits)*cvt;
        else {
          pos = MYFLT2LRND((count>>lobits)*cvt);
          fadeout = etab[elen - pos];
        }
        out[i] += amp*fadeout*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1]));
        ndx[1] -= si;
        tndx1 = ndx[1]>>lobits;
        if (tndx1 <= loop_start) {
          int loopsize;
          loop_start = MYFLT2LRND(*p->loop_start*sr);
          loop_end =   MYFLT2LRND(*p->loop_end*sr);
          p->lstart = loop_start = (loop_start < 0 ? 0 : loop_start);
          p->lend = loop_end =   (loop_end > len ? len :
                                  (loop_end < loop_start ? loop_start : loop_end));
          loopsize = (loop_end - loop_start);
          crossfade =  MYFLT2LRND(*p->crossfade*sr);
          p->cfade = crossfade = crossfade > loopsize/2 ? loopsize/2-1 : crossfade;
          cvt = (MYFLT)elen/p->cfade;
        }
      }
    }
  }

  p->count = count;
  p->cfade = crossfade;
  p->lend = loop_end;
  p->lstart = loop_start;
  p->init = init;
  return OK;
}


static int pvsarp_init(CSOUND *csound, pvsarp *p)
{
  long N = p->fin->N;

  if (p->fout->frame.auxp==NULL || p->fout->frame.size<(N+2)*sizeof(float))
    csound->AuxAlloc(csound,(N+2)*sizeof(float),&p->fout->frame);
  p->fout->N =  N;
  p->fout->overlap = p->fin->overlap;
  p->fout->winsize = p->fin->winsize;
  p->fout->wintype = p->fin->wintype;
  p->fout->format = p->fin->format;
  p->fout->framecount = 1;
  p->lastframe = 0;

  if (!(p->fout->format==PVS_AMP_FREQ) || (p->fout->format==PVS_AMP_PHASE)){
    return csound->InitError(csound,
                             Str("pvsarp: signal format must be amp-phase "
                             "or amp-freq.\n"));
  }

  return OK;
}

static int pvsarp_process(CSOUND *csound, pvsarp *p)
{
  long i,j,N = p->fout->N, bins = N/2 + 1;
  float g = (float) *p->gain;
  MYFLT kdepth = (MYFLT) *(p->kdepth), cf = (MYFLT) *(p->cf);
  float *fin = (float *) p->fin->frame.auxp;
  float *fout = (float *) p->fout->frame.auxp;

  if (fout==NULL)
    return csound->PerfError(csound,Str("pvsarp: not initialised\n"));

  if (p->lastframe < p->fin->framecount) {
    cf = cf >= 0 ? (cf < bins ? cf*bins : bins-1) : 0;
    kdepth = kdepth >= 0 ? (kdepth <= 1 ? kdepth : FL(1.0)): FL(0.0);
    for (i=j=0;i < N+2;i+=2, j++) {
      if (j == (int) cf) fout[i] = fin[i]*g;
      else fout[i] = (float)(fin[i]*(1-kdepth));
      fout[i+1] = fin[i+1];
    }
    p->fout->framecount = p->lastframe = p->fin->framecount;
  }

  return OK;
}

static int pvsvoc_init(CSOUND *csound, pvsvoc *p)
{
  long N = p->fin->N;

  if (p->fout->frame.auxp==NULL || p->fout->frame.size<(N+2)*sizeof(float))
    csound->AuxAlloc(csound,(N+2)*sizeof(float),&p->fout->frame);
  p->fout->N =  N;
  p->fout->overlap = p->fin->overlap;
  p->fout->winsize = p->fin->winsize;
  p->fout->wintype = p->fin->wintype;
  p->fout->format = p->fin->format;
  p->fout->framecount = 1;
  p->lastframe = 0;

  if (!(p->fout->format==PVS_AMP_FREQ) || (p->fout->format==PVS_AMP_PHASE)){
    return csound->InitError(csound,
                             Str("signal format must be amp-phase "
                                 "or amp-freq.\n"));
  }

  return OK;
}

static int pvsvoc_process(CSOUND *csound, pvsvoc *p)
{
  long i,N = p->fout->N;
  float g = (float) *p->gain;
  MYFLT kdepth = (MYFLT) *(p->kdepth);
  float *fin = (float *) p->fin->frame.auxp;
  float *ffr = (float *) p->ffr->frame.auxp;
  float *fout = (float *) p->fout->frame.auxp;

  if (fout==NULL)
    return csound->PerfError(csound,Str("pvsvoc: not initialised\n"));

  if (p->lastframe < p->fin->framecount) {

    kdepth = kdepth >= 0 ? (kdepth <= 1 ? kdepth : FL(1.0)): FL(0.0);
    for(i=0;i < N+2;i+=2) {
      fout[i] = fin[i]*g;
      fout[i+1] = ffr[i+1]*(kdepth) + fin[i+1]*(FL(1.0)-kdepth);
    }
    p->fout->framecount = p->lastframe = p->fin->framecount;
  }

  return OK;
}

static int pvsmorph_process(CSOUND *csound, pvsvoc *p)
{
  long i,N = p->fout->N;
  float frint = (float) *p->gain;
  float amint = (float) *(p->kdepth);
  float *fi1 = (float *) p->fin->frame.auxp;
  float *fi2 = (float *) p->ffr->frame.auxp;
  float *fout = (float *) p->fout->frame.auxp;

  if (fout==NULL)
    return csound->PerfError(csound,Str("pvsmorph: not initialised\n"));

  if (p->lastframe < p->fin->framecount) {

   amint = amint >= 0 ? (amint <= 1 ? amint : FL(1.0)): FL(0.0);
   frint = frint >= 0 ? (frint <= 1 ? frint : FL(1.0)): FL(0.0);
    for(i=0;i < N+2;i+=2) {
      fout[i] = fi1[i]*(1.0-amint) + fi2[i]*(amint);
      fout[i+1] = fi2[i+1]*(1.0-frint) + fi2[i+1]*(frint);
    }
    p->fout->framecount = p->lastframe = p->fin->framecount;
  }

  return OK;
}

static OENTRY localops[] = {
  {"sndloop", sizeof(sndloop), 5,
   "ak", "akkii", (SUBR)sndloop_init, NULL, (SUBR)sndloop_process},
  {"flooper", sizeof(flooper), 5,
   "a", "kkiiii", (SUBR)flooper_init, NULL, (SUBR)flooper_process},
  {"pvsarp", sizeof(pvsarp), 3,
   "f", "fkkk", (SUBR)pvsarp_init, (SUBR)pvsarp_process},
  {"pvsvoc", sizeof(pvsvoc), 3,
   "f", "ffkk", (SUBR)pvsvoc_init, (SUBR)pvsvoc_process},
  {"flooper2", sizeof(flooper2), 5,
   "a", "kkkkkioooo", (SUBR)flooper2_init, NULL, (SUBR)flooper2_process},
 {"flooper3", sizeof(flooper3), 5,
  "a", "kkkkkioooo", (SUBR)flooper3_init, NULL, (SUBR)flooper3_process},
 {"pvsmorph", sizeof(pvsvoc), 3,
   "f", "ffkk", (SUBR)pvsvoc_init, (SUBR)pvsmorph_process}
};

int sndloop_init_(CSOUND *csound)
{
  return csound->AppendOpcodes(csound, &(localops[0]),
                               (int) (sizeof(localops) / sizeof(OENTRY)));
}


Generated by  Doxygen 1.6.0   Back to index