Csound Csound-dev Csound-tekno Search About

[Cs-dev] Infinite loop in Vosim Opcode

Date2008-09-25 05:16
From"Steven Yi"
Subject[Cs-dev] Infinite loop in Vosim Opcode
AttachmentsNone  

Date2008-09-26 00:21
Fromre@abc.se
SubjectRe: [Cs-dev] Infinite loop in Vosim Opcode
Apologies for this, esp with released code.
It's certainly a mess, no excuses.

I did a few changes to straighten out the while-loop
(now ar++ and --nsmps go together, that helps the logic a bit)

Below the entire file is pasted, I cleaned up some warnings as well.
It's sent without line breaks, hope it's readable.
If some other format is desired, just say.

	re

======== begin vosim.c ========

/* VOSIM.C: VOice SIMulation implementation
  * by rasmus ekman March 13, 2008, for Csound.
  * This code is released under the Csound license,
  * GNU Lesser General Public License version 2.1,
  * or (at your option) any later version.
  */

/* Programmer note:
  * Pre- and post-conditions are noted at function level.
  * These are essential for the code to work at all.
  * There are some complications because we accept weird user input:
  * (a) kfund < 0: This is forced to positive - no point in "backward" events.
  * (b) kform == 0: This leads to infinite length pulse, ie silence.
  * (c) kform < 0: Table is read backward.
  *     If table is symmetric, kform and -kform should produce identical outputs.
  */

#include "cs.h"
#include "vosim.h"
#include 
#include 

/* Post: unless skipping init, timrem == 0 */
void vosimset(VOSIM *p)
{
     if (*p->iskip)
         return;

     p->ftable = ftfind(p->iftab);
     if (p->ftable == NULL) {
         initerror("vosim: pulse table not found");
         return;
     }

     p->timrem = p->pulstogo = p->pulsephs = p->pulseinc = 0;
     p->pulseamp = p->ampdecay = p->lenfact = FL(0.0);
}


/* Pre: timrem == 0.
  * Post:
  *    IF kform >= 0, pulsephs >= FMAXLEN.
  *    ELSE pulsephs < 0.
  *    timrem > 0.
  */
void vosim_event(VOSIM *p)
{
     p->pulstogo = (long)*p->knofpulse + 1;     /* count of pulses, (+1 since decr at start of pulse) */
     if (*p->kfund == FL(0.0))                  /* infinitely long event */
         p->timrem = INT_MAX;
     else
         p->timrem = (long)(esr / fabs(*p->kfund));
     p->pulseinc = (long)(*p->kform * sicvt);
     p->pulsephs = (p->pulseinc >= 0)? MAXLEN : -1;   /* starts a new pulse */
     p->ampdecay = *p->kdamp;
     p->pulseamp = *p->amp + p->ampdecay;       /* increase initial amp, since it's reduced at pulse start */
     p->lenfact  = *p->kpulsemul;               /* if negative, table is read alternately back-/forward */
     if (p->lenfact != FL(0.0))                 /* reduce table rate, since it's increased at pulse start */
         p->pulseinc = (long)(p->pulseinc / p->lenfact);
}


/* Pre: pulsephs >= FMAXLEN OR pulsephs < 0.
  * Post:
  *    pulstogo is decremented or zero.
  *    0 <= pulsephs < FMAXLEN.
  */
void vosim_pulse(VOSIM *p)
{
     long pulselen;
     p->pulsephs &= PHMASK;
     p->pulseinc = (long)(p->pulseinc * p->lenfact);
     /* If pulse can't fit in remaining event time, skip and generate silence */
     pulselen = (p->pulseinc != FL(0.0))? (long)fabs(FMAXLEN / p->pulseinc) : INT_MAX;
     if (--p->pulstogo <= 0 || pulselen > p->timrem)
         p->pulstogo = 0;
     else
         p->pulseamp -= p->ampdecay;
}


void vosim(VOSIM *p)
{
     long nsmps = ksmps;
     MYFLT *ar = p->ar;
     MYFLT *ftdata;
     long  lobits;

     FUNC *ftp = p->ftable;
     if (ftp == NULL) {
         perferror("vosim: not initialised");
         return;
     }
     ftdata = ftp->ftable;
     lobits = ftp->lobits;

     while (nsmps)
     {
         /* new event? */
         if (p->timrem == 0)
             vosim_event(p);

         /* new pulse? */
         if (p->pulsephs >= MAXLEN || p->pulsephs < 0)
             vosim_pulse(p);

         /* silence after last pulse in burst? */
         if (p->pulstogo == 0)
         {
             /* bypass regular synthesis and fill output with zeros */
             while (p->timrem && nsmps) {
                 *ar++ = FL(0.0);
                 --p->timrem;
                 --nsmps;
             }
         }
         else
         {
             /* produce one sample */
             p->pulsephs &= PHMASK;
             *ar++ = *(ftdata + (p->pulsephs >> lobits)) * p->pulseamp;
             --p->timrem;
             --nsmps;
             p->pulsephs += p->pulseinc;
         }
     }
}

======== end  vosim.c ========


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Csound-devel mailing list
Csound-devel@lists.sourceforge.net

Date2008-09-26 02:48
Fromre@abc.se
SubjectRe: [Cs-dev] Infinite loop in Vosim Opcode
Since my previous post stupidly used Csound 4.x style code,
here's an adapted version which seems to compile with cs5.
Continues to end of post (remove list footer).

	re

============== begin vosim.c ===============

/* VOSIM.C: VOice SIMulation implementation
  * by rasmus ekman March 13, 2008, for Csound.
  * This code is released under the Csound license,
  * GNU Lesser General Public License version 2.1,
  * or (at your option) any later version.
  */

/* Programmer note:
  * Pre- and post-conditions are noted at function level.
  * These are essential for the code to work at all.
  * There are some complications because we accept weird user input:
  * (a) kfund < 0: This is forced to positive - no point in "backward" events.
  * (b) kform == 0: This leads to infinite length pulse, ie silence.
  * (c) kform < 0: Table is read backward.
  *     If table is symmetric, kform and -kform should give bit-identical outputs.
  *
  * Don't fiddle with the code unless you understand how the table read
  * params pulsephs and pulseinc are used both to read table and to indicate that
  * a new pulse should start, and that pulseinc can be negative.
  */

#include "csdl.h"
#include 
#include 

typedef struct {
         OPDS h;
         MYFLT *ar, *amp, *kfund, *kform, *kdamp, *knofpulse, *kpulsemul,
               *iftab, *iskip;
         FUNC *ftable;
         int32  timrem;    /* samples left of event */
         int32  pulstogo;  /* count of pulses to produce in burst */
         int32  pulsephs;  /* index into table of this pulse (= MAXLEN / kform) */
         int32  pulseinc;  /* increment in table of pulse */
         MYFLT pulseamp;  /* amp of current pulse */
         MYFLT ampdecay;  /* subtract from amp on new pulse */
         MYFLT lenfact;   /* increase length of next pulse */
} VOSIM;


/* Post: unless skipping init, timrem == 0 */
int vosimset(CSOUND* csound, VOSIM *p)
{
     if (*p->iskip)
       return OK;

     p->ftable = csound->FTFind(csound, p->iftab);
     if (p->ftable == NULL) {
       csound->InitError(csound, Str("vosim: pulse table not found"));
       return NOTOK;
     }

     p->timrem = p->pulstogo = p->pulsephs = p->pulseinc = 0;
     p->pulseamp = p->ampdecay = p->lenfact = FL(0.0);
     return OK;
}


/* Pre: timrem == 0.
  * Post:
  *    IF kform >= 0, pulsephs >= FMAXLEN.
  *    ELSE pulsephs < 0.
  *    timrem > 0.
  */
void vosim_event(CSOUND* csound, VOSIM *p)
{
     /* count of pulses, (+1 since decr at start of pulse) */
     p->pulstogo = (int32)*p->knofpulse + 1;
     if (*p->kfund == FL(0.0))         /* infinitely long event */
       p->timrem = INT_MAX;
     else
       p->timrem = (int32)(csound->esr / fabs(*p->kfund));
     p->pulseinc = (int32)(*p->kform * csound->sicvt);
     p->pulsephs = (p->pulseinc >= 0)? MAXLEN : -1;   /* starts a new pulse */
     p->ampdecay = *p->kdamp;
     /* increase initial amp, since it's reduced at pulse start */
     p->pulseamp = *p->amp + p->ampdecay;
     /* if negative, table is read alternately back-/forward */
     p->lenfact  = *p->kpulsemul;
     /* reduce table rate, since it's increased at pulse start */
     if (p->lenfact != FL(0.0))
       p->pulseinc = (int32)(p->pulseinc / p->lenfact);
}


/* Pre: pulsephs >= FMAXLEN OR pulsephs < 0.
  * Post:
  *    pulstogo is decremented or zero.
  *    0 <= pulsephs < FMAXLEN.
  */
void vosim_pulse(CSOUND* csound, VOSIM *p)
{
     int32 pulselen;
     p->pulsephs &= PHMASK;
     p->pulseinc = (int32)(p->pulseinc * p->lenfact);
     /* If pulse can't fit in remaining event time, skip and generate silence */
     pulselen = (p->pulseinc != FL(0.0))? (int32)fabs(FMAXLEN / p->pulseinc) : INT_MAX;
     if (--p->pulstogo <= 0 || pulselen > p->timrem) {
       p->pulstogo = 0;
       return;
     }
     p->pulseamp -= p->ampdecay;
}


int vosim(CSOUND* csound, VOSIM *p)
{
     int32 nsmps = csound->ksmps;
     MYFLT *ar = p->ar;
     MYFLT *ftdata;
     int32  lobits;

     FUNC *ftp = p->ftable;
     if (ftp == NULL) {
       csound->PerfError(csound, Str("vosim: not initialised"));
       return NOTOK;
     }
     ftdata = ftp->ftable;
     lobits = ftp->lobits;

     while (nsmps > 0)
     {
         /* new event? */
         if (p->timrem == 0)
             vosim_event(csound, p);

         /* new pulse? */
         if (p->pulsephs >= MAXLEN || p->pulsephs < 0)
             vosim_pulse(csound, p);

         if (p->pulstogo > 0)
         {
             /* produce one sample */
             p->pulsephs &= PHMASK;
             *ar++ = *(ftdata + (p->pulsephs >> lobits)) * p->pulseamp;
             --p->timrem;
             --nsmps;
             p->pulsephs += p->pulseinc;
         }
         else
         {
		    /* silence after last pulse in burst: */
             /* bypass regular synthesis and fill output with zeros */
             while (p->timrem && nsmps) {
                 *ar++ = FL(0.0);
                 --p->timrem;
                 --nsmps;
             }
         }
     }
     return OK;
}

/* ar   vosim   kamp, kFund, kForm, kDamp, kPulseCount, kPulseFactor,
                 ifn [, iskip] */

#define S(x)    sizeof(x)

static OENTRY localops[] = {
   { "vosim", S(VOSIM), 5, "a", "kkkkkkio", (SUBR)vosimset, NULL, (SUBR)vosim }
};


LINKAGE

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Csound-devel mailing list
Csound-devel@lists.sourceforge.net

Date2008-09-26 08:09
Fromre@abc.se
SubjectRe: [Cs-dev] Infinite loop in Vosim Opcode
Since my previous post stupidly used Csound 4.x style code,
here's an adapted version which seems to compile with cs5.
Continues to end of post (remove list footer).

	re

============== begin vosim.c ===============

/* VOSIM.C: VOice SIMulation implementation
  * by rasmus ekman March 13, 2008, for Csound.
  * This code is released under the Csound license,
  * GNU Lesser General Public License version 2.1,
  * or (at your option) any later version.
  */

/* Programmer note:
  * Pre- and post-conditions are noted at function level.
  * These are essential for the code to work at all.
  * There are some complications because we accept weird user input:
  * (a) kfund < 0: This is forced to positive - no point in "backward" events.
  * (b) kform == 0: This leads to infinite length pulse, ie silence.
  * (c) kform < 0: Table is read backward.
  *     If table is symmetric, kform and -kform should give bit-identical outputs.
  *
  * Don't fiddle with the code unless you understand how the table read
  * params pulsephs and pulseinc are used both to read table and to indicate that
  * a new pulse should start, and that pulseinc can be negative.
  */

#include "csdl.h"
#include 
#include 

typedef struct {
         OPDS h;
         MYFLT *ar, *amp, *kfund, *kform, *kdamp, *knofpulse, *kpulsemul,
               *iftab, *iskip;
         FUNC *ftable;
         int32  timrem;    /* samples left of event */
         int32  pulstogo;  /* count of pulses to produce in burst */
         int32  pulsephs;  /* index into table of this pulse (= MAXLEN / kform) */
         int32  pulseinc;  /* increment in table of pulse */
         MYFLT pulseamp;  /* amp of current pulse */
         MYFLT ampdecay;  /* subtract from amp on new pulse */
         MYFLT lenfact;   /* increase length of next pulse */
} VOSIM;


/* Post: unless skipping init, timrem == 0 */
int vosimset(CSOUND* csound, VOSIM *p)
{
     if (*p->iskip)
       return OK;

     p->ftable = csound->FTFind(csound, p->iftab);
     if (p->ftable == NULL) {
       csound->InitError(csound, Str("vosim: pulse table not found"));
       return NOTOK;
     }

     p->timrem = p->pulstogo = p->pulsephs = p->pulseinc = 0;
     p->pulseamp = p->ampdecay = p->lenfact = FL(0.0);
     return OK;
}


/* Pre: timrem == 0.
  * Post:
  *    IF kform >= 0, pulsephs >= FMAXLEN.
  *    ELSE pulsephs < 0.
  *    timrem > 0.
  */
void vosim_event(CSOUND* csound, VOSIM *p)
{
     /* count of pulses, (+1 since decr at start of pulse) */
     p->pulstogo = (int32)*p->knofpulse + 1;
     if (*p->kfund == FL(0.0))         /* infinitely long event */
       p->timrem = INT_MAX;
     else
       p->timrem = (int32)(csound->esr / fabs(*p->kfund));
     p->pulseinc = (int32)(*p->kform * csound->sicvt);
     p->pulsephs = (p->pulseinc >= 0)? MAXLEN : -1;   /* starts a new pulse */
     p->ampdecay = *p->kdamp;
     /* increase initial amp, since it's reduced at pulse start */
     p->pulseamp = *p->amp + p->ampdecay;
     /* if negative, table is read alternately back-/forward */
     p->lenfact  = *p->kpulsemul;
     /* reduce table rate, since it's increased at pulse start */
     if (p->lenfact != FL(0.0))
       p->pulseinc = (int32)(p->pulseinc / p->lenfact);
}


/* Pre: pulsephs >= FMAXLEN OR pulsephs < 0.
  * Post:
  *    pulstogo is decremented or zero.
  *    0 <= pulsephs < FMAXLEN.
  */
void vosim_pulse(CSOUND* csound, VOSIM *p)
{
     int32 pulselen;
     p->pulsephs &= PHMASK;
     p->pulseinc = (int32)(p->pulseinc * p->lenfact);
     /* If pulse can't fit in remaining event time, skip and generate silence */
     pulselen = (p->pulseinc != FL(0.0))? (int32)fabs(FMAXLEN / p->pulseinc) : INT_MAX;
     if (--p->pulstogo <= 0 || pulselen > p->timrem) {
       p->pulstogo = 0;
       return;
     }
     p->pulseamp -= p->ampdecay;
}


int vosim(CSOUND* csound, VOSIM *p)
{
     int32 nsmps = csound->ksmps;
     MYFLT *ar = p->ar;
     MYFLT *ftdata;
     int32  lobits;

     FUNC *ftp = p->ftable;
     if (ftp == NULL) {
       csound->PerfError(csound, Str("vosim: not initialised"));
       return NOTOK;
     }
     ftdata = ftp->ftable;
     lobits = ftp->lobits;

     while (nsmps > 0)
     {
         /* new event? */
         if (p->timrem == 0)
             vosim_event(csound, p);

         /* new pulse? */
         if (p->pulsephs >= MAXLEN || p->pulsephs < 0)
             vosim_pulse(csound, p);

         if (p->pulstogo > 0)
         {
             /* produce one sample */
             p->pulsephs &= PHMASK;
             *ar++ = *(ftdata + (p->pulsephs >> lobits)) * p->pulseamp;
             --p->timrem;
             --nsmps;
             p->pulsephs += p->pulseinc;
         }
         else
         {
		    /* silence after last pulse in burst: */
             /* bypass regular synthesis and fill output with zeros */
             while (p->timrem && nsmps) {
                 *ar++ = FL(0.0);
                 --p->timrem;
                 --nsmps;
             }
         }
     }
     return OK;
}

/* ar   vosim   kamp, kFund, kForm, kDamp, kPulseCount, kPulseFactor,
                 ifn [, iskip] */

#define S(x)    sizeof(x)

static OENTRY localops[] = {
   { "vosim", S(VOSIM), 5, "a", "kkkkkkio", (SUBR)vosimset, NULL, (SUBR)vosim }
};


LINKAGE


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Csound-devel mailing list
Csound-devel@lists.sourceforge.net