Logo Search packages:      
Sourcecode: csound version File versions

sndwarp.c

/*
    sndwarp.c:

    Copyright (C) 1997 Richard Karpen, John ffitch

    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
*/

/**************************************************************/
/*************sndwarp******************************************/
/*** By Richard Karpen - 1992, 1995, 1997 *********************/
/**************************************************************/
/*This is a version that uses table lookup instead of reading */
/*from soundfiles.                                            */
/**************************************************************/

#include "csdl.h"
#include "sndwarp.h"

#define unirand(x) ((MYFLT) (x->Rand31(&(x->randSeed1)) - 1) / FL(2147483645.0))

static int sndwarpgetset(CSOUND *csound, SNDWARP *p)
{
    int         i;
    int         nsections;
    FUNC        *ftpWind, *ftpSamp;
    WARPSECTION *exp;
    char        *auxp;
    MYFLT       iwsize;

    nsections = (int)*p->ioverlap;
    if ((auxp = p->auxch.auxp) == NULL || nsections != p->nsections) {
      if (nsections != p->nsections)
        auxp = p->auxch.auxp=NULL;
      csound->AuxAlloc(csound, (size_t)nsections*sizeof(WARPSECTION), &p->auxch);
      auxp = p->auxch.auxp;
      p->nsections = nsections;
    }
    p->exp = (WARPSECTION *)auxp;

    if (UNLIKELY((ftpSamp = csound->FTFind(csound, p->isampfun)) == NULL)) return NOTOK;
    p->ftpSamp  = ftpSamp;
    p->sampflen = ftpSamp->flen;

    if (UNLIKELY((ftpWind = csound->FTFind(csound, p->ifn)) == NULL)) return NOTOK;
    p->ftpWind = ftpWind;
    p->flen    = ftpWind->flen;

    p->maxFr   = -1 + ftpSamp->flen;
    p->prFlg   = 1;    /* true */
    p->begin   = (int)(*p->ibegin * csound->esr);

    exp        = p->exp;
    iwsize = *p->iwsize;
    for (i=0; i< *p->ioverlap; i++) {
      if (i==0) {
        exp[i].wsize = (int)iwsize;
        exp[1].cnt = 0;
        exp[i].ampphs = FL(0.0);
      }
      else {
        exp[i].wsize = (int) (iwsize + (unirand(csound) * (*p->irandw)));
        exp[i].cnt=(int)(exp[i].wsize*((MYFLT)i/(*p->ioverlap)));
        exp[i].ampphs = p->flen*((MYFLT)i/(*p->ioverlap));
      }
      exp[i].offset = (MYFLT)p->begin;
      exp[i].ampincr = (MYFLT)p->flen/(exp[i].wsize-1);
      /* exp[i].section = i+1;  *//* section number just used for debugging! */

    }
    p->ampcode = (XINARG1) ? 1 : 0;
    p->timewarpcode = (XINARG2) ? 1 : 0;
    p->resamplecode = (XINARG3) ? 1 : 0;
    return OK;
}

static int sndwarp(CSOUND *csound, SNDWARP *p)
{
    int         n, nsmps = csound->ksmps;
    MYFLT       frm0,frm1;
    int32       base, longphase;
    MYFLT       frac, frIndx;
    MYFLT       *r1, *r2, *amp, *timewarpby, *resample;
    WARPSECTION *exp;
    FUNC        *ftpWind, *ftpSamp;
    int         i;
    MYFLT       v1, v2, windowamp, fract;
    MYFLT       flen = (MYFLT)p->flen;
    MYFLT       iwsize = *p->iwsize;
    int         overlap = *p->ioverlap;

    if (UNLIKELY(p->auxch.auxp==NULL)) goto err1;
    r1 = p->r1;
    r2 = p->r2;
    memset(r1, 0, nsmps*sizeof(MYFLT));
    if (p->OUTOCOUNT >1) memset(r2, 0, nsmps*sizeof(MYFLT));
/*     for (i=0; i<nsmps; i++) { */
/*       *r1++ = FL(0.0); */
/*       if (p->OUTOCOUNT >1) *r2++ = FL(0.0); */
/*     } */
    exp = p->exp;
    ftpWind = p->ftpWind;
    ftpSamp = p->ftpSamp;

    for (i=0; i<overlap; i++) {
/*       nsmps = csound->ksmps; */
/*       r1 = p->r1; */
/*       if (p->OUTOCOUNT >1)  r2 = p->r2; */
      resample = p->xresample;
      timewarpby = p->xtimewarp;
      amp = p->xamp;

      for (n=0; n<nsmps;n++) {
        if (exp[i].cnt < exp[i].wsize) goto skipover;

        if (*p->itimemode!=0)
          exp[i].offset=(csound->esr * *timewarpby)+p->begin;
        else
          exp[i].offset += (MYFLT)exp[i].wsize/(*timewarpby);

        exp[i].cnt=0;
        exp[i].wsize = (int) (iwsize + (unirand(csound) * (*p->irandw)));
        exp[i].ampphs = FL(0.0);
        exp[i].ampincr = flen/(exp[i].wsize-1);

      skipover:

        frIndx =(MYFLT)((exp[i].cnt * *resample)  + exp[i].offset);
        exp[i].cnt += 1;
        if (frIndx > (MYFLT)p->maxFr) { /* not past last one */
          frIndx = (MYFLT)p->maxFr;
          if (p->prFlg) {
            p->prFlg = 0;   /* false */
            csound->Warning(csound, Str("SNDWARP at last sample frame"));
          }
        }
        longphase = (int32)exp[i].ampphs;
        if (longphase > p->flen-1) longphase = p->flen-1;
        v1 = *(ftpWind->ftable + longphase);
        v2 = *(ftpWind->ftable + longphase + 1);
        fract = (MYFLT)(exp[i].ampphs - (int32)exp[i].ampphs);
        windowamp = v1 + (v2 - v1)*fract;
        exp[i].ampphs += exp[i].ampincr;

        base = (int32)frIndx;    /* index of basis frame of interpolation */
        frac = ((MYFLT)(frIndx - (MYFLT)base));
        frm0 = *(ftpSamp->ftable + base);
        frm1 = *(ftpSamp->ftable + (base+1));
        if (frac != FL(0.0)) {
          r1[n] += ((frm0 + frac*(frm1-frm0)) * windowamp) * *amp;
          if (i==0)
           if (p->OUTOCOUNT > 1)
             r2[n] += (frm0 + frac*(frm1-frm0)) * *amp;
        }
        else {
          r1[n] += (frm0 * windowamp) * *amp;
          if (i==0)
            if (p->OUTOCOUNT > 1)
              r2[n] += frm0 * *amp;
        }
        if (p->ampcode) amp++;
        if (p->timewarpcode) timewarpby++;
        if (p->resamplecode) resample++;
      }
    }
    return OK;
 err1:
    return csound->PerfError(csound, Str("sndwarp: not initialised"));
}

/****************************************************************/
/**************STEREO VERSION OF SNDWARP*************************/
/****************************************************************/

static int sndwarpstgetset(CSOUND *csound, SNDWARPST *p)
{
    int         i;
    int         nsections;
    FUNC        *ftpWind, *ftpSamp;
    WARPSECTION *exp;
    char        *auxp;
    MYFLT       iwsize;

    if (UNLIKELY(p->OUTOCOUNT > 2 && p->OUTOCOUNT < 4)) {
      return csound->InitError(csound, Str("Wrong number of outputs "
                                           "in sndwarpst; must be 2 or 4"));
    }
    nsections = (int)*p->ioverlap;
    if ((auxp = p->auxch.auxp) == NULL || nsections != p->nsections) {
      if (nsections != p->nsections)
        auxp=p->auxch.auxp=NULL;
      csound->AuxAlloc(csound, (size_t)nsections*sizeof(WARPSECTION), &p->auxch);
      auxp = p->auxch.auxp;
      p->nsections = nsections;
    }
    p->exp = (WARPSECTION *)auxp;

    if (UNLIKELY((ftpSamp = csound->FTFind(csound, p->isampfun)) == NULL))
      return NOTOK;
    p->ftpSamp = ftpSamp;
    p->sampflen=ftpSamp->flen;

    if (UNLIKELY((ftpWind = csound->FTFind(csound, p->ifn)) == NULL))
      return NOTOK;
    p->ftpWind = ftpWind;
    p->flen=ftpWind->flen;

    p->maxFr  = -1L + (int32)(ftpSamp->flen*FL(0.5));
    p->prFlg = 1;    /* true */
    p->begin = (int)(*p->ibegin * csound->esr);
    iwsize = *p->iwsize;
    exp = p->exp;
    for (i=0; i< nsections; i++) {
      if (i==0) {
        exp[i].wsize = (int)iwsize;
        exp[i].cnt=0;
        exp[i].ampphs = FL(0.0);
      }
      else {
        exp[i].wsize = (int) (iwsize + (unirand(csound) * (*p->irandw)));
        exp[i].cnt=(int)(exp[i].wsize*((MYFLT)i/(*p->ioverlap)));
        exp[i].ampphs = p->flen*(i/(*p->ioverlap));
      }
      exp[i].offset = (MYFLT)p->begin;
      exp[i].ampincr = (MYFLT)p->flen/(exp[i].wsize-1);
      /* exp[i].section = i+1;  *//* section number just used for debugging! */

    }
    p->ampcode = (XINARG1) ? 1 : 0;
    p->timewarpcode = (XINARG2) ? 1 : 0;
    p->resamplecode = (XINARG3) ? 1 : 0;
    return OK;
}

static int sndwarpstset(CSOUND *csound, SNDWARPST *p)
{
    return sndwarpstgetset(csound,p);
}

static int sndwarpst(CSOUND *csound, SNDWARPST *p)
{
    int         n, nsmps = csound->ksmps;
    MYFLT       frm10,frm11, frm20, frm21;
    int32        base, longphase;
    MYFLT       frac, frIndx;
    MYFLT       *r1, *r2,*r3, *r4, *amp, *timewarpby, *resample;
    WARPSECTION *exp;
    FUNC        *ftpWind, *ftpSamp;
    int         i;
    MYFLT       v1, v2, windowamp, fract;
    MYFLT       flen = (MYFLT)p->flen;
    MYFLT       iwsize = *p->iwsize;

    if (UNLIKELY(p->auxch.auxp==NULL)) goto err1;  /* RWD fix */
    r1 = p->r1;
    r2 = p->r2;
    r3 = p->r3;
    r4 = p->r4;
    memset(r1, 0,nsmps*sizeof(MYFLT));
    memset(r2, 0,nsmps*sizeof(MYFLT));
    if (p->OUTOCOUNT >2) {
      memset(r3, 0,nsmps*sizeof(MYFLT));
      memset(r4, 0,nsmps*sizeof(MYFLT));
    }
    exp = p->exp;
    ftpWind = p->ftpWind;
    ftpSamp = p->ftpSamp;

    for (i=0; i<*p->ioverlap; i++) {
      resample = p->xresample;
      timewarpby = p->xtimewarp;
      amp = p->xamp;

      for (n=0; n<nsmps;n++) {
        if (exp[i].cnt < exp[i].wsize) goto skipover;

        if (*p->itimemode!=0)
          exp[i].offset=(csound->esr * *timewarpby)+p->begin;
        else
          exp[i].offset += (MYFLT)exp[i].wsize/(*timewarpby);

        exp[i].cnt=0;
        exp[i].wsize = (int) (iwsize + (unirand(csound) * (*p->irandw)));
        exp[i].ampphs = FL(0.0);
        exp[i].ampincr = flen/(exp[i].wsize-1);

      skipover:
        frIndx =(MYFLT)(exp[i].cnt * *resample)  + (MYFLT)exp[i].offset;
        exp[i].cnt += 1;
        if (frIndx > (MYFLT)p->maxFr) {  /* not past last one */
          frIndx = (MYFLT)p->maxFr;
          if (p->prFlg) {
            p->prFlg = 0;   /* false */
            csound->Warning(csound, Str("SNDWARP at last sample frame"));
          }
        }
        longphase = (int32)exp[i].ampphs;
        if (longphase > p->flen-1) longphase = p->flen-1;
        v1 = *(ftpWind->ftable + longphase);
        v2 = *(ftpWind->ftable + longphase + 1);
        fract = (MYFLT)(exp[i].ampphs - (int32)exp[i].ampphs);
        windowamp = v1 + (v2 - v1)*fract;
        exp[i].ampphs += exp[i].ampincr;

        base = (int32)frIndx;    /* index of basis frame of interpolation */
        frac = ((MYFLT)(frIndx - (MYFLT)base));

        frm10 = *(ftpSamp->ftable + (base * 2));
        frm11 = *(ftpSamp->ftable + ((base+1)*2));
        frm20 = *(ftpSamp->ftable + (base*2)+1);
        frm21 = *(ftpSamp->ftable + (((base+1)*2)+1));
        if (frac != FL(0.0)) {
          r1[n] += ((frm10 + frac*(frm11-frm10)) * windowamp) * *amp;
          r2[n] += ((frm20 + frac*(frm21-frm20)) * windowamp) * *amp;
          if (i==0)
            if (p->OUTOCOUNT > 2) {
              r3[n] += (frm10 + frac*(frm11-frm10)) * *amp;
              r4[n] += (frm20 + frac*(frm21-frm20)) * *amp;
            }
        }
        else {
          r1[n] += (frm10 * windowamp) * *amp;
          r2[n] += (frm20 * windowamp) * *amp;
          if (i==0)
            if (p->OUTOCOUNT > 2) {
              r3[n] += frm10 * *amp;
              r4[n] += frm20 * *amp;
            }
        }
        if (p->ampcode) amp++;
        if (p->timewarpcode) timewarpby++;
        if (p->resamplecode) resample++;
      }
    }
    return OK;
 err1:
    return csound->PerfError(csound, Str("sndwarpst: not initialised"));
}

#define S(x)    sizeof(x)

static OENTRY localops[] = {
  { "sndwarp", S(SNDWARP), 5, "mm", "xxxiiiiiii",
    (SUBR)sndwarpgetset, NULL, (SUBR)sndwarp},
  { "sndwarpst", S(SNDWARPST), 5, "mmmm","xxxiiiiiii",
    (SUBR)sndwarpstset,NULL,(SUBR)sndwarpst}
};

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


Generated by  Doxygen 1.6.0   Back to index