1 /*
2     gens1.c:
3 
4     Copyright (C) 1991 Barry Vercoe, John ffitch
5 
6     This file is part of Csound.
7 
8     The Csound Library is free software; you can redistribute it
9     and/or modify it under the terms of the GNU Lesser General Public
10     License as published by the Free Software Foundation; either
11     version 2.1 of the License, or (at your option) any later version.
12 
13     Csound is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU Lesser General Public License for more details.
17 
18     You should have received a copy of the GNU Lesser General Public
19     License along with Csound; if not, write to the Free Software
20     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21     02110-1301 USA
22 */
23 
24 #include "csoundCore.h"         /*                      UGENS1.C        */
25 #include "ugens1.h"
26 #include <math.h>
27 
28 #define FHUND (FL(100.0))
29 
30 
linset(CSOUND * csound,LINE * p)31 int32_t linset(CSOUND *csound, LINE *p)
32 {
33     double       dur;
34     if (LIKELY((dur = *p->idur) > FL(0.0))) {
35       p->incr = (*p->ib - *p->ia) / dur * csound->onedsr;
36       p->kincr = p->incr*CS_KSMPS;
37       p->val = *p->ia;
38     }
39     return OK;
40 }
41 
kline(CSOUND * csound,LINE * p)42 int32_t kline(CSOUND *csound, LINE *p)
43 {
44     IGN(csound);
45     *p->xr = p->val;            /* rslt = val   */
46     p->val += p->kincr;          /* val += incr  */
47     return OK;
48 }
49 
aline(CSOUND * csound,LINE * p)50 int32_t aline(CSOUND *csound, LINE *p)
51 {
52     IGN(csound);
53     double val, inc;
54     MYFLT *ar;
55     uint32_t offset = p->h.insdshead->ksmps_offset;
56     uint32_t early  = p->h.insdshead->ksmps_no_end;
57     uint32_t n, nsmps = CS_KSMPS;
58     ar = p->xr;
59     val = p->val;
60     inc = p->incr;
61 
62     if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT));
63     if (UNLIKELY(early)) {
64       nsmps -= early;
65       memset(&ar[nsmps], '\0', early*sizeof(MYFLT));
66     }
67 
68     //p->val += inc;/* nxtval = val + inc */
69     //inc /= (nsmps - offset);
70     for (n=offset; n<nsmps; n++) {
71       ar[n] = (MYFLT)val;
72       val += inc;       /* interp val for ksmps */
73     }
74     p->val = val;
75     return OK;
76 }
77 
expset(CSOUND * csound,EXPON * p)78 int32_t expset(CSOUND *csound, EXPON *p)
79 {
80     double       dur, a, b;
81     //printf("kr = %f , 1/kr = %f \n",CS_EKR, CS_ONEDKR);
82     if (LIKELY((dur = *p->idur) > FL(0.0) )) {
83       a = *p->ia;
84       b = *p->ib;
85       if (LIKELY((a * b) > FL(0.0))) {
86         p->mlt = POWER(b/a, csound->onedsr/dur);
87         p->kmlt = POWER(b/a, CS_ONEDKR/dur);
88         p->val = a;
89       }
90       else if (a == FL(0.0))
91         return csound->InitError(csound, Str("arg1 is zero"));
92       else if (b == FL(0.0))
93         return csound->InitError(csound, Str("arg2 is zero"));
94       else return csound->InitError(csound, Str("unlike signs"));
95     }
96     return OK;
97 }
98 
kexpon(CSOUND * csound,EXPON * p)99 int32_t kexpon(CSOUND *csound, EXPON *p)
100 {
101    IGN(csound);
102     *p->xr = p->val;            /* rslt = val   */
103     p->val *= p->kmlt;           /* val *= mlt  */
104     return OK;
105 }
106 
expon(CSOUND * csound,EXPON * p)107 int32_t expon(CSOUND *csound, EXPON *p)
108 {
109     IGN(csound);
110     double val, mlt;//, inc;//, nxtval;
111     MYFLT *ar;
112     uint32_t offset = p->h.insdshead->ksmps_offset;
113     uint32_t early  = p->h.insdshead->ksmps_no_end;
114     uint32_t n, nsmps = CS_KSMPS;
115 
116     val = p->val;
117     mlt = p->mlt;
118     // nxtval = val * mlt;
119     ar = p->xr;
120     if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT));
121     if (UNLIKELY(early)) {
122       nsmps -= early;
123       memset(&ar[nsmps], '\0', early*sizeof(MYFLT));
124     }
125     //inc = nxtval - val;
126     //inc /= (nsmps - offset);   /* increment per sample */
127     for (n=offset; n<nsmps; n++) {
128       ar[n] = (MYFLT)val;
129       val *= mlt;               /* interp val for ksmps */
130     }
131     // p->val = nxtval;            /* store next value */
132     p->val = val;
133     return OK;
134 }
135 
lsgset(CSOUND * csound,LINSEG * p)136 int32_t lsgset(CSOUND *csound, LINSEG *p)
137 {
138     SEG *segp;
139     int32_t nsegs;
140     MYFLT       **argp;
141     double val;
142 
143     if (UNLIKELY(!(p->INCOUNT & 1))) {
144       return csound->InitError(csound, Str("incomplete number of input arguments"));
145     }
146 
147     /* count segs & alloc if nec */
148     nsegs = (p->INOCOUNT - (!(p->INOCOUNT & 1))) >> 1;
149     /* VL: 29.05.17 allocating one extra empty segment
150        so that the breakpoint version of this opcode
151        can work properly without a fencepost bug */
152     if (UNLIKELY((p->cursegp = (SEG *) p->auxch.auxp) == NULL ||
153                  (nsegs+1)*sizeof(SEG) < (uint32_t)p->auxch.size)) {
154       csound->AuxAlloc(csound, (int32_t)(nsegs+1)*sizeof(SEG), &p->auxch);
155       p->cursegp = (SEG *) p->auxch.auxp;
156       segp = p->cursegp + 1; /* point to first seg */
157       p->cursegp->cnt = 0;   /* zero duration of segment 0  */
158       segp[nsegs-1].cnt = MAXPOS; /* set endcount for safety */
159     } else segp = p->cursegp + 1; /* point to first seg */
160     argp = p->argums;
161     val = (double)**argp++;
162     if (UNLIKELY(**argp <= FL(0.0)))  return OK;    /* if idur1 <= 0, skip init  */
163     p->curval = val;
164     p->curcnt = 0;
165     /* VL: 29.05.17 this was causing a fencepost error in
166        the breakpoint version (linsegb) */
167     //p->cursegp = segp - 1;          /* else setup null seg0 */
168     p->segsrem = nsegs + 1;
169     do {                                /* init each seg ..  */
170       double dur = (double)**argp++;
171       segp->nxtpt = (double)**argp++;
172       if (UNLIKELY((segp->cnt = (int32_t)(dur * CS_EKR + FL(0.5))) < 0))
173         segp->cnt = 0;
174       if (UNLIKELY((segp->acnt = (int32_t)(dur * csound->esr + FL(0.5))) < 0))
175         segp->acnt = 0;
176       segp++;
177     } while (--nsegs);
178     p->xtra = -1;
179 
180     return OK;
181 
182 }
183 
lsgset_bkpt(CSOUND * csound,LINSEG * p)184 int32_t lsgset_bkpt(CSOUND *csound, LINSEG *p)
185 {
186     int32_t cnt = 0, bkpt = 0;
187     int32_t nsegs;
188     int32_t n;
189     SEG *segp;
190     n = lsgset(csound, p);
191     if (UNLIKELY(n!=0)) return n;
192     nsegs = p->segsrem;
193     segp = p->cursegp;
194     do {
195       if (UNLIKELY(cnt > segp->cnt))
196         return csound->InitError(csound, Str("Breakpoint %d not valid"), bkpt);
197       segp->cnt -= cnt;
198       cnt += segp->cnt;
199       segp++;
200       bkpt++;
201     } while (--nsegs);
202     return OK;
203 }
204 
205 
klnseg(CSOUND * csound,LINSEG * p)206 int32_t klnseg(CSOUND *csound, LINSEG *p)
207 {
208     IGN(csound);
209     *p->rslt = p->curval;               /* put the cur value    */
210     if (UNLIKELY(p->auxch.auxp==NULL)) goto err1;          /* RWD fix */
211     if (UNLIKELY(p->segsrem)) {                   /* done if no more segs */
212       if (--p->curcnt <= 0) {           /* if done cur segment  */
213         SEG *segp = p->cursegp;
214         if (UNLIKELY(!(--p->segsrem)))  {
215           p->curval = segp->nxtpt;      /* advance the cur val  */
216           return OK;
217         }
218         p->cursegp = ++segp;            /*   find the next      */
219         if (UNLIKELY(!(p->curcnt = segp->cnt))) { /*   nonlen = discontin */
220           p->curval = segp->nxtpt;      /*   poslen = new slope */
221           /*          p->curval += p->curinc;  ??????? */
222           return OK;
223         }
224         else {
225           p->curinc = (segp->nxtpt - p->curval) / segp->cnt;
226           p->curval += p->curinc;
227           return OK;
228         }
229       }
230       if (p->curcnt<10)         /* This is a fiddle to get rounding right!  */
231         p->curinc = (p->cursegp->nxtpt - p->curval) / p->curcnt; /* recalc */
232       p->curval += p->curinc;           /* advance the cur val  */
233     }
234     return OK;
235  err1:
236     return csound->InitError(csound, Str("linseg not initialised (krate)\n"));
237 }
238 
linseg(CSOUND * csound,LINSEG * p)239 int32_t linseg(CSOUND *csound, LINSEG *p)
240 {
241     double val, ainc;
242     MYFLT *rs = p->rslt;
243     uint32_t offset = p->h.insdshead->ksmps_offset;
244     uint32_t early  = p->h.insdshead->ksmps_no_end;
245     uint32_t n, nsmps = CS_KSMPS;
246 
247     if (UNLIKELY(p->auxch.auxp==NULL)) goto err1;  /* RWD fix */
248 
249     val = p->curval;                      /* sav the cur value    */
250     if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT));
251     if (UNLIKELY(early)) {
252       nsmps -= early;
253       memset(&rs[nsmps], '\0', early*sizeof(MYFLT));
254     }
255 
256     for (n=offset; n<nsmps; n++) {
257       if (LIKELY(p->segsrem)) {             /* if no more segs putk */
258         if (--p->curcnt <= 0) {             /*  if done cur segment */
259           SEG *segp = p->cursegp;
260         chk1:
261           if (UNLIKELY(!--p->segsrem)) {    /*   if none left       */
262             val = p->curval = segp->nxtpt;
263             goto putk;                      /*      put endval      */
264           }
265           p->cursegp = ++segp;              /*   else find the next */
266           //printf("newseg: nxtpt=%f acnt=%d\n", segp->nxtpt, segp->acnt);
267           if (UNLIKELY(!(p->curcnt = segp->acnt))) {
268             val = p->curval = segp->nxtpt;  /* nonlen = discontin */
269             goto chk1;
270           }                                 /*   poslen = new slope */
271           p->curainc = (segp->nxtpt - val) / segp->acnt;
272           // p->curainc = p->curinc * CS_ONEDKSMPS;
273         }
274         // p->curval = val + p->curinc;        /* advance the cur val  */
275         if (UNLIKELY((ainc = p->curainc) == FL(0.0)))
276           goto putk;
277         rs[n] = (MYFLT)val;
278         val += ainc;
279       }
280       else {                      /* no more segments */
281       putk:
282         rs[n] = (MYFLT)val;
283       }
284     }
285     p->curval = val;
286     return OK;
287  err1:
288 
289     return csound->PerfError(csound, &(p->h),
290                              Str("linseg: not initialised (arate)\n"));
291 }
292 
293 /* **** ADSR is just a construction and use of linseg */
294 
295 #define MAXSEGDUR (INT_MAX/CS_ESR)
296 
adsrset1(CSOUND * csound,LINSEG * p,int32_t midip)297 static int32_t adsrset1(CSOUND *csound, LINSEG *p, int32_t midip)
298 {
299     SEG         *segp;
300     int32_t     nsegs;
301     MYFLT       **argp = p->argums;
302     double      dur;
303     MYFLT       len = csound->curip->p3.value;
304     MYFLT       release = *argp[3];
305     int32_t     relestim;
306 
307     //printf("len = %f\n", len);
308     if (UNLIKELY(len<=FL(0.0)))
309       len = (int32_t) MAXSEGDUR;// FL(10000.0); /* MIDI case set int32_t */
310     nsegs = 6;          /* DADSR */
311     if ((segp = (SEG *) p->auxch.auxp) == NULL ||
312         nsegs*sizeof(SEG) < (uint32_t)p->auxch.size) {
313       csoundAuxAlloc(csound, (size_t) nsegs * sizeof(SEG), &p->auxch);
314       p->cursegp = segp = (SEG *) p->auxch.auxp;
315       segp[nsegs-1].cnt = MAXPOS; /* set endcount for safety */
316     }
317     else if (**argp > FL(0.0))
318       memset(p->auxch.auxp, 0, (size_t)nsegs*sizeof(SEG));
319     if (**argp <= FL(0.0))  return OK;       /* if idur1 <= 0, skip init  */
320     p->curval = 0.0;
321     p->curcnt = 0;
322     p->cursegp = segp - 1;      /* else setup null seg0 */
323     p->segsrem = nsegs;
324     //printf("args: %f %f %f %f %f\n",
325     //       *argp[0], *argp[1], *argp[2], *argp[3],* argp[4]);
326                                 /* Delay */
327     dur = (double)*argp[4];
328     segp->nxtpt = FL(0.0);
329     segp->cnt = (int32_t)(dur * CS_EKR + FL(0.5));
330     //printf("delay: dur=%f cnt=%d\n", dur, segp->cnt);
331     segp++;
332                                 /* Attack */
333     dur = (double)*argp[0];
334     segp->nxtpt = FL(1.0);
335     segp->cnt = (int32_t)(dur * CS_EKR + FL(0.5));
336     if (UNLIKELY((segp->acnt = (int32_t)(dur * csound->esr + FL(0.5))) < 0))
337         segp->acnt = 0;
338     //printf("attack: dur=%f cnt=%d acnt=%d nxt=%f\n",
339     //       dur, segp->cnt, segp->acnt, segp->nxtpt);
340     segp++;
341                                 /* Decay */
342     dur = *argp[1];
343     segp->nxtpt = *argp[2];
344     segp->cnt = (int32_t)(dur * CS_EKR + FL(0.5));
345     if (UNLIKELY((segp->acnt = (int32_t)(dur * csound->esr + FL(0.5))) < 0))
346       segp->acnt = 0;
347     //printf("decay: dur=%f cnt=%d acnt=%d nxt=%f\n",
348     //       dur, segp->cnt, segp->acnt, segp->nxtpt);
349     segp++;
350                                 /* Sustain */
351     /* Should use p3 from score, but how.... */
352     dur = len - *argp[4] - *argp[0] - *argp[1] - *argp[3];
353     if (!midip && dur <0.0)
354       csound->Warning(csound, Str("length of ADSR note too short"));
355     segp->nxtpt = *argp[2];
356     segp->cnt = (int32_t)(dur * CS_EKR + FL(0.5));
357     if (UNLIKELY((segp->acnt = (int32_t)(dur * csound->esr + FL(0.5))) < 0))
358       segp->acnt = 0;
359     //printf("sustain: dur=%f cnt=%d acnt=%d nxt=%f\n",
360     //       dur, segp->cnt, segp->acnt, segp->nxtpt);
361     segp++;
362                                 /* Release */
363     dur = *argp[3];
364     segp->nxtpt = FL(0.0);
365     segp->cnt = (int32_t)(release * CS_EKR + FL(0.5));
366     if (UNLIKELY((segp->acnt = (int32_t)(release * csound->esr + FL(0.5))) < 0))
367       segp->acnt = 0;
368     //printf("release: dur=%f cnt=%d acnt=%d nxt=%f\n",
369     //       dur, segp->cnt, segp->acnt, segp->nxtpt);
370     if (midip) {
371       relestim = (p->cursegp + p->segsrem - 1)->cnt;
372       p->xtra = relestim;
373           /*  VL 4-1-2011 was (int32_t)(*argp[5] * CS_EKR + FL(0.5));
374               this seems to fix it */
375       if (relestim > p->h.insdshead->xtratim)
376         p->h.insdshead->xtratim = (int32_t)relestim;
377     }
378     else
379       p->xtra = 0L;
380     return OK;
381 }
382 
adsrset(CSOUND * csound,LINSEG * p)383 int32_t adsrset(CSOUND *csound, LINSEG *p)
384 {
385     return adsrset1(csound, p, 0);
386 }
387 
madsrset(CSOUND * csound,LINSEG * p)388 int32_t madsrset(CSOUND *csound, LINSEG *p)
389 {
390     return adsrset1(csound, p, 1);
391 }
392 
393 /* End of ADSR */
394 
lsgrset(CSOUND * csound,LINSEG * p)395 int32_t lsgrset(CSOUND *csound, LINSEG *p)
396 {
397     int32_t relestim;
398     if (lsgset(csound,p) == OK){
399     relestim = (p->cursegp + p->segsrem - 1)->cnt;
400     p->xtra = relestim;
401     /* VL 4-1-2011 was -1, making all linsegr
402                             releases in an instr => xtratim
403                             set to relestim seems to fix this */
404     if (relestim > p->h.insdshead->xtratim)
405       p->h.insdshead->xtratim = (int32_t)relestim;
406     return OK;
407     }
408     else return NOTOK;
409 }
410 
klnsegr(CSOUND * csound,LINSEG * p)411 int32_t klnsegr(CSOUND *csound, LINSEG *p)
412 {
413     IGN(csound);
414     *p->rslt = p->curval;                   /* put the cur value    */
415     if (p->segsrem) {                       /* done if no more segs */
416       SEG *segp;
417       if (p->h.insdshead->relesing && p->segsrem > 1) {
418         while (p->segsrem > 1) {           /* reles flag new:      */
419           segp = ++p->cursegp;             /*   go to last segment */
420           p->segsrem--;
421         }                                  /*   get univ relestim  */
422         segp->cnt = p->xtra>= 0 ? p->xtra : p->h.insdshead->xtratim;
423         goto newi;                         /*   and set new curinc */
424       }
425       if (--p->curcnt <= 0) {              /* if done cur seg      */
426       chk2:
427         if (p->segsrem == 2) return OK;    /*   seg Y rpts lastval */
428         if (!(--p->segsrem)) return OK;    /*   seg Z now done all */
429         segp = ++p->cursegp;               /*   else find nextseg  */
430       newi:
431         if (!(p->curcnt = segp->cnt)) {    /*   nonlen = discontin */
432           p->curval = segp->nxtpt;         /*     reload & rechk   */
433           goto chk2;
434         }                                  /*   else get new slope */
435         p->curinc = (segp->nxtpt - p->curval) / segp->cnt;
436       }
437       p->curval += p->curinc;              /* advance the cur val  */
438     }
439     return OK;
440 }
441 
linsegr(CSOUND * csound,LINSEG * p)442 int32_t linsegr(CSOUND *csound, LINSEG *p)
443 {
444     IGN(csound);
445     MYFLT  val, ainc, *rs = p->rslt;
446     uint32_t offset = p->h.insdshead->ksmps_offset;
447     uint32_t early  = p->h.insdshead->ksmps_no_end;
448     uint32_t n, nsmps = CS_KSMPS;
449 
450     if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT));
451     if (UNLIKELY(early)) {
452       nsmps -= early;
453       memset(&rs[nsmps], '\0', early*sizeof(MYFLT));
454     }
455     val = p->curval;                          /* sav the cur value    */
456     for (n=offset; n<nsmps; n++) {
457       if (LIKELY(p->segsrem)) {               /* if no more segs putk */
458         SEG *segp;
459         if (p->h.insdshead->relesing && p->segsrem > 1) {
460           while (p->segsrem > 1) {            /* release flag new:    */
461             segp = ++p->cursegp;              /*   go to last segment */
462             p->segsrem--;
463           }                                   /*   get univ relestim  */
464           segp->acnt = (p->xtra >=0 ? p->xtra : p->h.insdshead->xtratim)*CS_KSMPS;
465           goto newi;                          /*   and set new curinc */
466         }
467         if (--p->curcnt <= 0) {               /* if done cur seg      */
468         chk2:
469           if (p->segsrem == 2) goto putk;     /*   seg Y rpts lastval */
470           if (!(--p->segsrem)) goto putk;     /*   seg Z now done all */
471           segp = ++p->cursegp;                /*   else find nextseg  */
472         newi:
473           if (!(p->curcnt = segp->acnt)) {    /*   nonlen = discontin */
474             val = p->curval = segp->nxtpt;    /*   reload & rechk  */
475             goto chk2;
476           }                                   /*   else get new slope */
477           p->curainc = (segp->nxtpt - val) / segp->acnt;
478           // p->curainc = p->curinc * CS_ONEDKSMPS;
479         }
480         //p->curval = val + p->curainc*CS_KSMPS;    /* advance the cur val  */
481         if ((ainc = p->curainc) == FL(0.0))
482           goto putk;
483 
484         rs[n] = val;
485         val += ainc;
486       }
487       else {
488       putk:
489         rs[n] = val;
490       }
491     }
492     p->curval = val;
493     return OK;
494 }
495 
xsgset(CSOUND * csound,EXXPSEG * p)496 int32_t xsgset(CSOUND *csound, EXXPSEG *p)
497 {
498     XSEG        *segp;
499     int32_t         nsegs;
500     MYFLT       d, **argp, val, dur, nxtval;
501     int32_t         n=0;
502 
503     if (!(p->INCOUNT & 1)) {
504       return csound->InitError(csound, Str("incomplete number of input arguments"));
505     }
506 
507     /* count segs & alloc if nec */
508     nsegs = (p->INOCOUNT - (!(p->INOCOUNT & 1))) >> 1;
509     if ((segp = (XSEG *) p->auxch.auxp) == NULL ||
510         nsegs*sizeof(XSEG) < (uint32_t)p->auxch.size) {
511       csound->AuxAlloc(csound, (int32_t)nsegs*sizeof(XSEG), &p->auxch);
512       p->cursegp = segp = (XSEG *) p->auxch.auxp;
513       (segp+nsegs-1)->cnt = MAXPOS;   /* set endcount for safety */
514     }
515     argp = p->argums;
516     nxtval = **argp++;
517     if (**argp <= FL(0.0))  return OK;          /* if idur1 <= 0, skip init  */
518     p->cursegp = segp;                          /* else proceed from 1st seg */
519     segp--;
520     p->segsrem = nsegs;
521     do {
522       segp++;           /* init each seg ..  */
523       val = nxtval;
524       dur = **argp++;
525       nxtval = **argp++;
526       if (UNLIKELY(val * nxtval <= FL(0.0)))
527         goto experr;
528       d = dur * CS_EKR;
529       segp->val = val;
530       segp->mlt = (MYFLT) pow((double)(nxtval / val), (1.0/(double)d));
531       segp->cnt = (int32_t) (d + FL(0.5));
532       d = dur * csound->esr;
533       segp->amlt = (MYFLT) pow((double)(nxtval / val), (1.0/(double)d));
534       segp->acnt = (int32_t) (d + FL(0.5));
535     } while (--nsegs);
536     segp->cnt = MAXPOS;         /* set last cntr to infin */
537     segp->acnt = MAXPOS;         /* set last cntr to infin */
538     return OK;
539 
540  experr:
541     n = segp - p->cursegp + 1;
542     if (val == FL(0.0))
543       return csound->InitError(csound, Str("ival%d is zero"), n);
544     else if (nxtval == FL(0.0))
545       return csound->InitError(csound, Str("ival%d is zero"), n+1);
546     return csound->InitError(csound, Str("ival%d sign conflict"), n+1);
547 }
548 
xsgset_bkpt(CSOUND * csound,EXXPSEG * p)549 int32_t xsgset_bkpt(CSOUND *csound, EXXPSEG *p)
550 {
551    XSEG        *segp;
552     int32_t         nsegs;
553     MYFLT       d, **argp, val, dur, dursum = FL(0.0), bkpt, nxtval;
554     int32_t         n=0;
555 
556 
557     if (!(p->INCOUNT & 1)){
558       return csound->InitError(csound, Str("incomplete number of input arguments"));
559     }
560 
561     /* count segs & alloc if nec */
562     nsegs = (p->INOCOUNT - (!(p->INOCOUNT & 1))) >> 1;
563     if ((segp = (XSEG *) p->auxch.auxp) == NULL ||
564         nsegs*sizeof(XSEG) < (uint32_t)p->auxch.size) {
565       csound->AuxAlloc(csound, (int32_t)nsegs*sizeof(XSEG), &p->auxch);
566       p->cursegp = segp = (XSEG *) p->auxch.auxp;
567       (segp+nsegs-1)->cnt = MAXPOS;   /* set endcount for safety */
568     }
569     argp = p->argums;
570     nxtval = **argp++;
571     if (**argp <= FL(0.0))  return OK;          /* if idur1 <= 0, skip init  */
572     p->cursegp = segp;                          /* else proceed from 1st seg */
573     segp--;
574     p->segsrem = nsegs;
575     do {
576       segp++;           /* init each seg ..  */
577       val = nxtval;
578       bkpt = **argp++;
579       if (UNLIKELY(bkpt < dursum))
580           return csound->InitError(csound,
581                                    Str("Breakpoint time %f not valid"), bkpt);
582       dur = bkpt - dursum;
583       dursum += dur;
584       nxtval = **argp++;
585       if (UNLIKELY(val * nxtval <= FL(0.0)))
586         goto experr;
587       d = dur * CS_EKR;
588       segp->val = val;
589       segp->mlt = (MYFLT) pow((double)(nxtval / val), (1.0/(double)d));
590       segp->cnt = (int32_t) (d + FL(0.5));
591       d = dur * csound->esr;
592       segp->amlt = (MYFLT) pow((double)(nxtval / val), (1.0/(double)d));
593       segp->acnt = (int32_t) (d + FL(0.5));
594     } while (--nsegs);
595     segp->cnt = MAXPOS;         /* set last cntr to infin */
596     segp->acnt = MAXPOS;
597     return OK;
598 
599  experr:
600     n = segp - p->cursegp + 1;
601     if (val == FL(0.0))
602       return csound->InitError(csound, Str("ival%d is zero"), n);
603     else if (nxtval == FL(0.0))
604       return csound->InitError(csound, Str("ival%d is zero"), n+1);
605     return csound->InitError(csound, Str("ival%d sign conflict"), n+1);
606 }
607 
608 
xsgset2b(CSOUND * csound,EXPSEG2 * p)609 int32_t xsgset2b(CSOUND *csound, EXPSEG2 *p)
610 {
611     XSEG        *segp;
612     int32_t         nsegs;
613     MYFLT       d, **argp, val, dur, dursum = FL(0.0), bkpt, nxtval;
614     int32_t         n;
615 
616 
617     if (!(p->INCOUNT & 1)){
618       return csound->InitError(csound, Str("incomplete number of input arguments"));
619     }
620 
621     /* count segs & alloc if nec */
622     nsegs = (p->INOCOUNT - (!(p->INOCOUNT & 1))) >> 1;
623     if ((segp = (XSEG*) p->auxch.auxp) == NULL ||
624         (uint32_t)nsegs*sizeof(XSEG) > (uint32_t)p->auxch.size) {
625       csound->AuxAlloc(csound, (int32_t)nsegs*sizeof(XSEG), &p->auxch);
626       p->cursegp = segp = (XSEG *) p->auxch.auxp;
627       (segp+nsegs-1)->cnt = MAXPOS;   /* set endcount for safety */
628     }
629     argp = p->argums;
630     nxtval = **argp++;
631     if (**argp <= FL(0.0))  return OK;        /* if idur1 <= 0, skip init  */
632     p->cursegp = segp;                      /* else proceed from 1st seg */
633     segp--;
634     do {
635       segp++;           /* init each seg ..  */
636       val = nxtval;
637       bkpt = **argp++;
638       if (UNLIKELY(bkpt < dursum))
639           return csound->InitError(csound,
640                                    Str("Breakpoint time %f not valid"), bkpt);
641       dur = bkpt - dursum;
642       dursum += dur;
643       nxtval = **argp++;
644 /*       if (dur > FL(0.0)) { */
645       if (UNLIKELY(val * nxtval <= FL(0.0)))
646           goto experr;
647         d = dur * csound->esr;
648         segp->val = val;
649         segp->mlt = POWER((nxtval / val), FL(1.0)/d);
650         segp->cnt = (int32_t) (d + FL(0.5));
651          d = dur * csound->esr;
652          segp->amlt = (MYFLT) pow((double)(nxtval / val), (1.0/(double)d));
653          segp->acnt = (int32_t) (d + FL(0.5));
654 /*       } */
655 /*       else break;               /\*  .. til 0 dur or done *\/ */
656     } while (--nsegs);
657     segp->cnt = MAXPOS;         /* set last cntr to infin */
658      segp->acnt = MAXPOS;
659     return OK;
660 
661  experr:
662     n = segp - p->cursegp + 1;
663     if (val == FL(0.0))
664       return csound->InitError(csound, Str("ival%d is zero"), n);
665     else if (nxtval == FL(0.0))
666       return csound->InitError(csound, Str("ival%d is zero"), n+1);
667     return csound->InitError(csound, Str("ival%d sign conflict"), n+1);
668 }
669 
xsgset2(CSOUND * csound,EXPSEG2 * p)670 int32_t xsgset2(CSOUND *csound, EXPSEG2 *p)   /*gab-A1 (G.Maldonado) */
671 {
672     XSEG        *segp;
673     int32_t         nsegs;
674     MYFLT       d, **argp, val, dur, nxtval;
675     int32_t         n;
676 
677 
678     if (!(p->INCOUNT & 1)){
679       return csound->InitError(csound, Str("incomplete number of input arguments"));
680     }
681 
682     /* count segs & alloc if nec */
683     nsegs = (p->INOCOUNT - (!(p->INOCOUNT & 1))) >> 1;
684     if ((segp = (XSEG*) p->auxch.auxp) == NULL ||
685         (uint32_t)nsegs*sizeof(XSEG) > (uint32_t)p->auxch.size) {
686       csound->AuxAlloc(csound, (int32_t)nsegs*sizeof(XSEG), &p->auxch);
687       p->cursegp = segp = (XSEG *) p->auxch.auxp;
688       (segp+nsegs-1)->cnt = MAXPOS;   /* set endcount for safety */
689     }
690     argp = p->argums;
691     nxtval = **argp++;
692     if (**argp <= FL(0.0))  return OK;        /* if idur1 <= 0, skip init  */
693     p->cursegp = segp;                      /* else proceed from 1st seg */
694     segp--;
695     do {
696       segp++;           /* init each seg ..  */
697       val = nxtval;
698       dur = **argp++;
699       nxtval = **argp++;
700 /*       if (dur > FL(0.0)) { */
701       if (UNLIKELY(val * nxtval <= FL(0.0)))
702           goto experr;
703         d = dur * csound->esr;
704         segp->val = val;
705         segp->mlt = POWER((nxtval / val), FL(1.0)/d);
706         segp->cnt = (int32_t) (d + FL(0.5));
707         d = dur * csound->esr;
708         segp->amlt = (MYFLT) pow((double)(nxtval / val), (1.0/(double)d));
709         segp->acnt = (int32_t) (d + FL(0.5));
710 /*       } */
711 /*       else break;               /\*  .. til 0 dur or done *\/ */
712     } while (--nsegs);
713     segp->cnt = MAXPOS;         /* set last cntr to infin */
714     segp->acnt = MAXPOS;
715     return OK;
716 
717  experr:
718     n = segp - p->cursegp + 1;
719     if (val == FL(0.0))
720       return csound->InitError(csound, Str("ival%d is zero"), n);
721     else if (nxtval == FL(0.0))
722       return csound->InitError(csound, Str("ival%d is zero"), n+1);
723     return csound->InitError(csound, Str("ival%d sign conflict"), n+1);
724 }
725 
726 /***************************************/
727 
expseg2(CSOUND * csound,EXPSEG2 * p)728 int32_t expseg2(CSOUND *csound, EXPSEG2 *p)             /* gab-A1 (G.Maldonado) */
729 {
730     IGN(csound);
731     XSEG        *segp;
732     uint32_t offset = p->h.insdshead->ksmps_offset;
733     uint32_t early  = p->h.insdshead->ksmps_no_end;
734     uint32_t n, nsmps = CS_KSMPS;
735     MYFLT       val, *rs;
736     segp = p->cursegp;
737     val  = segp->val;
738     rs   = p->rslt;
739     if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT));
740     if (UNLIKELY(early)) {
741       nsmps -= early;
742       memset(&rs[nsmps], '\0', early*sizeof(MYFLT));
743     }
744     for (n=offset; n<nsmps; n++) {
745       while (--segp->cnt < 0)   {
746         p->cursegp = ++segp;
747         val = segp->val;
748       }
749       rs[n] = val;
750       val *=  segp->mlt;
751     }
752     segp->val = val;
753     return OK;
754 }
755 
756 /* **** XDSR is just a construction and use of expseg */
757 
xdsrset(CSOUND * csound,EXXPSEG * p)758 int32_t xdsrset(CSOUND *csound, EXXPSEG *p)
759 {
760     XSEG    *segp;
761     int32_t     nsegs;
762     MYFLT   **argp = p->argums;
763     MYFLT   len = csound->curip->p3.value;
764     MYFLT   delay = *argp[4], attack = *argp[0], decay = *argp[1];
765     MYFLT   sus, dur;
766     MYFLT   release = *argp[3];
767 
768     if (UNLIKELY(len<FL(0.0))) len = FL(100000.0); /* MIDI case set long */
769     if (csound->curip->p3.value-delay-attack-decay<FL(0.0))
770       csound->Warning(csound, Str("length of XADSR note too short"));
771     len -= release;                      /* len is time remaining */
772     if (UNLIKELY(len<FL(0.0))) { /* Odd case of release time greater than dur */
773       release = csound->curip->p3.value; len = FL(0.0);
774     }
775     nsegs = 5;          /* DXDSR */
776     if ((segp = (XSEG *) p->auxch.auxp) == NULL ||
777         nsegs*sizeof(XSEG) < (uint32_t)p->auxch.size) {
778       csound->AuxAlloc(csound, (int32_t)nsegs*sizeof(XSEG), &p->auxch);
779       segp = (XSEG *) p->auxch.auxp;
780     }
781     segp[nsegs-1].cnt = MAXPOS;         /* set endcount for safety */
782     if (**argp <= FL(0.0))  return OK;  /* if idur1 <= 0, skip init  */
783     p->cursegp = segp;                  /* else setup null seg0 */
784     p->segsrem = nsegs;
785     delay += FL(0.001);
786     if (delay > len) {delay = len; len -= delay;}
787     attack -= FL(0.001);
788     if (attack > len) {attack = len; len -= attack;}
789     if (decay > len) {decay = len; len -= decay;}
790     sus = len;
791     segp[0].val = FL(0.0001);   /* Like zero start, but exponential */
792     segp[0].mlt = FL(1.0);
793     segp[0].cnt = (int32_t) (delay*CS_EKR + FL(0.5));
794     segp[0].amlt =  FL(1.0);
795     segp[0].acnt = (int32_t) (delay*CS_ESR + FL(0.5));
796     dur = attack*CS_EKR;
797     segp[1].val = FL(0.0001);
798     segp[1].mlt = POWER(FL(1000.0), FL(1.0)/dur);
799     segp[1].cnt = (int32_t) (dur + FL(0.5));
800     dur = attack*CS_ESR;
801     segp[1].amlt = POWER(FL(1000.0), FL(1.0)/dur);
802     segp[1].acnt = (int32_t) (dur + FL(0.5));
803     //printf("attack: %f %f %d / %f %d\n",
804     //       segp[1].val,segp[1].mlt,segp[1].cnt,segp[1].amlt, segp[1].acnt);
805     dur = decay*CS_EKR;
806     segp[2].val = FL(1.0);
807     segp[2].mlt = POWER(*argp[2], FL(1.0)/dur);
808     segp[2].cnt = (int32_t) (dur + FL(0.5));
809     dur = decay*CS_ESR;
810     segp[2].amlt = POWER(*argp[2], FL(1.0)/dur);
811     segp[2].acnt = (int32_t) (dur + FL(0.5));
812     //printf("decay: %f %f %d %f %d\n",
813     //       segp[2].val,segp[2].mlt,segp[2].cnt,segp[2].amlt, segp[2].acnt);
814     segp[3].val = *argp[2];
815     segp[3].mlt = FL(1.0);
816     segp[3].cnt = (int32_t) (sus*CS_EKR + FL(0.5));
817 
818     segp[3].amlt = FL(1.0);
819     segp[3].acnt = (int32_t) (sus*CS_ESR + FL(0.5));
820     //printf("sustain: %f %f %d %f %d\n",
821     //       segp[3].val,segp[3].mlt,segp[3].cnt,segp[3].amlt, segp[3].acnt);
822     dur = release*CS_EKR;
823     segp[4].val = *argp[2];
824     segp[4].mlt = POWER(FL(0.001)/(*argp[2]), FL(1.0)/dur);
825     segp[4].cnt = MAXPOS; /*(int32_t) (dur + FL(0.5)); */
826 
827     dur = release*CS_ESR;
828     segp[4].amlt = POWER(FL(0.001)/(*argp[2]), FL(1.0)/dur);
829     segp[4].acnt = MAXPOS; /*(int32_t) (dur + FL(0.5)); */
830     //printf("releaase: %f %f %d %f %d\n",
831     //       segp[4].val,segp[4].mlt,segp[4].cnt,segp[4].amlt, segp[4].acnt);
832     return OK;
833 }
834 
835 /* end of XDSR */
836 
kxpseg(CSOUND * csound,EXXPSEG * p)837 int32_t kxpseg(CSOUND *csound, EXXPSEG *p)
838 {
839     XSEG        *segp;
840 
841 
842     segp = p->cursegp;
843     if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */
844     while (--segp->cnt < 0)
845       p->cursegp = ++segp;
846     *p->rslt = segp->val;
847     segp->val *= segp->mlt;
848     return OK;
849  err1:
850     return csound->PerfError(csound, &(p->h),
851                              Str("expseg (krate): not initialised"));
852 }
853 
854 
expseg(CSOUND * csound,EXXPSEG * p)855 int32_t expseg(CSOUND *csound, EXXPSEG *p)
856 {
857     XSEG        *segp;
858     uint32_t offset = p->h.insdshead->ksmps_offset;
859     uint32_t early  = p->h.insdshead->ksmps_no_end;
860     uint32_t n, nsmps = CS_KSMPS;
861     MYFLT       *rs = p->rslt;
862 
863 
864 
865     if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT));
866     if (UNLIKELY(early)) {
867       nsmps -= early;
868       memset(&rs[nsmps], '\0', early*sizeof(MYFLT));
869     }
870     for (n=offset; n<nsmps; n++) {
871       segp = p->cursegp;
872       if (UNLIKELY(p->auxch.auxp==NULL)) goto err1;
873       while (--segp->acnt < 0) {
874         //printf("seg: val=%f amlt=%f\n", segp->val,segp->amlt );
875         p->cursegp = ++segp;
876         //printf("nxtseg: val=%f amlt=%f acnt=%d\n",
877         //       segp->val,segp->amlt,segp->acnt);
878       }
879       rs[n] = segp->val;
880       segp->val *= segp->amlt;
881     }
882     return OK;
883   err1:
884     return csound->PerfError(csound, &(p->h),
885                              Str("expseg (arate): not initialised"));
886 }
887 
xsgrset(CSOUND * csound,EXPSEG * p)888 int32_t xsgrset(CSOUND *csound, EXPSEG *p)
889 {
890     int32_t     relestim;
891     SEG     *segp;
892     int32_t     nsegs, n = 0;
893     MYFLT   **argp, prvpt;
894 
895 
896     if (!(p->INCOUNT & 1)){
897       return csound->InitError(csound, Str("incomplete number of input arguments"));
898     }
899 
900     //p->xtra = -1;
901     /* count segs & alloc if nec */
902     nsegs = (p->INOCOUNT - (!(p->INOCOUNT & 1))) >> 1;
903     if ((segp = (SEG *) p->auxch.auxp) == NULL ||
904         (uint32_t)nsegs*sizeof(SEG) > (uint32_t)p->auxch.size) {
905       csound->AuxAlloc(csound, (int32_t)nsegs*sizeof(SEG), &p->auxch);
906       p->cursegp = segp = (SEG *) p->auxch.auxp;
907     }
908     argp = p->argums;
909     prvpt = **argp++;
910     if (**argp < FL(0.0))  return OK; /* if idur1 < 0, skip init      */
911     p->curval  = prvpt;
912     p->curcnt  = 0;                   /* else setup null seg0         */
913     p->cursegp = segp - 1;
914     p->segsrem = nsegs + 1;
915     do {                              /* init & chk each real seg ..  */
916       MYFLT dur = **argp++;
917       segp->nxtpt = **argp++;
918       if ((segp->cnt = (int32_t)(dur * CS_EKR + FL(0.5))) <= 0)
919         segp->cnt = 0;
920       else if (segp->nxtpt * prvpt <= FL(0.0))
921         goto experr;
922       if ((segp->acnt = (int32_t)(dur * CS_ESR )) <= 0)
923         segp->acnt = 0;
924       prvpt = segp->nxtpt;
925       segp++;
926     } while (--nsegs);
927     relestim = (int32_t)(p->cursegp + p->segsrem - 1)->cnt;
928     p->xtra = relestim;
929     if (relestim > p->h.insdshead->xtratim)
930       p->h.insdshead->xtratim = relestim;
931     return OK;
932 
933  experr:
934     n = segp - p->cursegp;// + 2;
935     if (prvpt == FL(0.0))
936       return csound->InitError(csound, Str("ival%d is zero"), n);
937     else if (segp->nxtpt == FL(0.0))
938       return csound->InitError(csound, Str("ival%d is zero"), n+1);
939     return csound->InitError(csound, Str("ival%d sign conflict"), n+1);
940 }
941 
942 /* **** MXDSR is just a construction and use of expseg */
943 
mxdsrset(CSOUND * csound,EXPSEG * p)944 int32_t mxdsrset(CSOUND *csound, EXPSEG *p)
945 {
946     int32_t         relestim;
947     SEG         *segp;
948     int32_t         nsegs;
949     MYFLT       **argp = p->argums;
950     MYFLT       delay = *argp[4], attack = *argp[0], decay = *argp[1];
951     MYFLT       rel = *argp[3];
952 
953     nsegs = 4;          /* DXDSR */
954     if ((segp = (SEG *) p->auxch.auxp) == NULL ||
955         nsegs*sizeof(SEG) < (uint32_t)p->auxch.size) {
956       csound->AuxAlloc(csound, (int32_t)nsegs*sizeof(SEG), &p->auxch);
957       segp = (SEG *) p->auxch.auxp;
958     }
959     if (**argp <= FL(0.0))  return OK;  /* if idur1 <= 0, skip init  */
960     p->cursegp = segp-1;                /* else setup null seg0 */
961     p->segsrem = nsegs+1;
962     p->curval = FL(0.001);
963     p->curcnt = 0;                      /* else setup null seg0 */
964     delay += FL(0.001);
965     attack -= FL(0.001);
966     segp[0].nxtpt = FL(0.001);
967     segp[0].cnt = (int32_t) (delay*CS_EKR + FL(0.5));
968     segp[0].acnt = (int32_t) (delay*CS_ESR + FL(0.5));
969     segp[1].nxtpt = FL(1.0);
970     segp[1].cnt = (int32_t) (attack*CS_EKR + FL(0.5));
971     segp[1].acnt = (int32_t) (attack*CS_ESR + FL(0.5));
972     segp[2].nxtpt = *argp[2];
973     segp[2].cnt = (int32_t) (decay*CS_EKR + FL(0.5));
974     segp[2].acnt = (int32_t) (decay*CS_ESR + FL(0.5));
975     segp[3].nxtpt = FL(0.001);
976     segp[3].cnt = (int32_t) (rel*CS_EKR + FL(0.5));
977     segp[3].acnt = (int32_t) (rel*CS_ESR + FL(0.5));
978     relestim = (int32_t)(p->cursegp + p->segsrem - 1)->cnt;
979     p->xtra = relestim;//(int32_t)(*argp[5] * CS_EKR + FL(0.5)); /* Release time?? */
980     if (relestim > p->h.insdshead->xtratim)
981       p->h.insdshead->xtratim = relestim;
982     return OK;
983 }
984 
985 /* end of MXDSR */
986 
kxpsegr(CSOUND * csound,EXPSEG * p)987 int32_t kxpsegr(CSOUND *csound, EXPSEG *p)
988 {
989     IGN(csound);
990     *p->rslt = p->curval;               /* put the cur value    */
991     if (p->segsrem) {                   /* done if no more segs */
992       SEG *segp;
993       if (p->h.insdshead->relesing && p->segsrem > 1) {
994         while (p->segsrem > 1) {        /* reles flag new:      */
995           segp = ++p->cursegp;          /*   go to last segment */
996           p->segsrem--;
997         }                               /*   get univ relestim  */
998         segp->cnt = p->xtra>=0 ? p->xtra : p->h.insdshead->xtratim;
999         goto newm;                      /*   and set new curmlt */
1000       }
1001       if (--p->curcnt <= 0) {           /* if done cur seg      */
1002       chk2:
1003         if (p->segsrem == 2) return OK; /*   seg Y rpts lastval */
1004         if (!(--p->segsrem)) return OK; /*   seg Z now done all */
1005         segp = ++p->cursegp;            /*   else find nextseg  */
1006       newm:
1007         if (!(p->curcnt = segp->cnt)) { /*   nonlen = discontin */
1008           p->curval = segp->nxtpt;      /*     reload & rechk   */
1009           goto chk2;
1010         }
1011         if (segp->nxtpt == p->curval)   /*   else get new mlt   */
1012           p->curmlt = FL(1.0);
1013         else p->curmlt = (MYFLT) pow(segp->nxtpt/p->curval, 1.0/segp->cnt);
1014       }
1015       p->curval *= p->curmlt;           /* advance the cur val  */
1016     }
1017     return OK;
1018 }
1019 
expsegr(CSOUND * csound,EXPSEG * p)1020 int32_t expsegr(CSOUND *csound, EXPSEG *p)
1021 {
1022     IGN(csound);
1023     MYFLT  val, amlt, *rs = p->rslt;
1024     uint32_t offset = p->h.insdshead->ksmps_offset;
1025     uint32_t early  = p->h.insdshead->ksmps_no_end;
1026     uint32_t n, nsmps = CS_KSMPS;
1027 
1028 
1029     if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT));
1030     if (UNLIKELY(early)) {
1031       nsmps -= early;
1032       memset(&rs[nsmps], '\0', early*sizeof(MYFLT));
1033     }
1034                       /* sav the cur value    */
1035     val = p->curval;
1036     for (n=offset; n<nsmps; n++) {
1037 
1038       if (p->segsrem) {                   /* if no more segs putk */
1039         SEG *segp;
1040         if (p->h.insdshead->relesing && p->segsrem > 1) {
1041           while (p->segsrem > 1) {        /* if reles flag new    */
1042             segp = ++p->cursegp;          /*   go to last segment */
1043             p->segsrem--;
1044           }                               /*   get univ relestim  */
1045           segp->acnt = (p->xtra>=0 ? p->xtra : p->h.insdshead->xtratim)*CS_KSMPS;
1046           goto newm;                      /*   and set new curmlt */
1047         }
1048         if (--p->curcnt <= 0) {           /* if done cur seg      */
1049         chk2:
1050           if (p->segsrem == 2) goto putk; /*   seg Y rpts lastval */
1051           if (!(--p->segsrem)) goto putk; /*   seg Z now done all */
1052           segp = ++p->cursegp;            /*   else find nextseg  */
1053         newm:
1054           if (!(p->curcnt = segp->acnt)) { /*   nonlen = discontin */
1055             val = p->curval = segp->nxtpt; /*   reload & rechk  */
1056             goto chk2;
1057           }                               /*   else get new mlts  */
1058           if (segp->nxtpt == val) {
1059             p->curmlt = p->curamlt = FL(1.0);
1060             p->curval = val;
1061             goto putk;
1062           }
1063           else {
1064             p->curmlt = POWER((segp->nxtpt/val), FL(1.0)/segp->cnt);
1065             // VL: this line introduces a bug
1066             //p->curamlt = POWER(p->curmlt, FL(1.0)/(MYFLT)(nsmps-offset));
1067             // VL: this line fixes it but does not take account of offset
1068             p->curamlt = POWER((segp->nxtpt/val), FL(1.0)/segp->acnt);
1069           }
1070         }
1071         if ((amlt = p->curamlt) == FL(1.0)) goto putk;
1072         rs[n] = val;
1073         val *= amlt;
1074       }
1075       else {
1076       putk:
1077         rs[n] =  val;
1078       }
1079     }
1080     p->curval = val;
1081     return OK;
1082 }
1083 
lnnset(CSOUND * csound,LINEN * p)1084 int32_t lnnset(CSOUND *csound, LINEN *p)
1085 {
1086     MYFLT a,b,dur;
1087     MYFLT len = csound->curip->p3.value;
1088 
1089     if ((dur = *p->idur) > FL(0.0)) {
1090       MYFLT iris = *p->iris, idec = *p->idec;
1091       if (len<(iris<idec?idec:iris))
1092         csound->Warning(csound, Str("p3 too short in linen"));
1093 
1094       p->cnt1 = (int32_t)(iris * CS_EKR + FL(0.5));
1095       if (p->cnt1 > (int32_t)0) {
1096         p->inc1 = FL(1.0) / (MYFLT) p->cnt1;
1097       }
1098       else p->inc1 = FL(1.0);
1099       a = dur * CS_EKR + FL(0.5);
1100       b = idec * CS_EKR + FL(0.5);
1101       if ((int32_t) b > 0) {
1102         p->cnt2 = (int32_t) (a - b);
1103         p->inc2 = FL(1.0) /  b;
1104       }
1105       else {
1106         p->inc2 = FL(1.0);
1107         p->cnt2 = (int32_t) a;
1108       }
1109       p->lin1 = FL(0.0);
1110       p->lin2 = FL(1.0);
1111     }
1112     return OK;
1113 }
1114 
alnnset(CSOUND * csound,LINEN * p)1115 int32_t alnnset(CSOUND *csound, LINEN *p)
1116 {
1117     MYFLT a,b,dur;
1118     MYFLT len = csound->curip->p3.value;
1119 
1120     if ((dur = *p->idur) > FL(0.0)) {
1121       MYFLT iris = *p->iris, idec = *p->idec;
1122       if (len<(iris<idec?idec:iris))
1123         csound->Warning(csound, Str("p3 too short in linen"));
1124       p->cnt1 = (int64_t)(*p->iris * CS_ESR + FL(0.5));
1125       if (p->cnt1 > 0) {
1126         p->inc1 = FL(1.0) / (MYFLT) p->cnt1;
1127       }
1128       else p->inc1 = FL(1.0);
1129       a = dur * CS_ESR + FL(0.5);
1130       b = *p->idec * CS_ESR + FL(0.5);
1131       if ((int64_t) b > 0) {
1132         p->cnt2 = (int64_t) (a - b);
1133         p->inc2 = FL(1.0) /  b;
1134       }
1135       else {
1136         p->inc2 = FL(1.0);
1137         p->cnt2 = (int64_t) a;
1138       }
1139       p->lin1 = FL(0.0);
1140       p->lin2 = FL(1.0);
1141     }
1142     return OK;
1143 }
1144 
klinen(CSOUND * csound,LINEN * p)1145 int32_t klinen(CSOUND *csound, LINEN *p)
1146 {
1147     IGN(csound);
1148     MYFLT fact = FL(1.0);
1149 
1150     if (p->cnt1 > 0) {
1151       fact = p->lin1;
1152       p->lin1 += p->inc1;
1153       p->cnt1--;
1154     }
1155     if (p->cnt2 > 0)
1156       p->cnt2--;
1157     else {
1158       fact *= p->lin2;
1159       p->lin2 -= p->inc2;
1160     }
1161     *p->rslt = *p->sig * fact;
1162     return OK;
1163 }
1164 
linen(CSOUND * csound,LINEN * p)1165 int32_t linen(CSOUND *csound, LINEN *p)
1166 {
1167     IGN(csound);
1168     uint32_t offset = p->h.insdshead->ksmps_offset;
1169     uint32_t early  = p->h.insdshead->ksmps_no_end;
1170     uint32_t flag=0, n, nsmps = CS_KSMPS;
1171     MYFLT *rs,*sg,val;
1172     int32_t    asgsg = IS_ASIG_ARG(p->sig);
1173     int64_t cnt2 = p->cnt2;
1174     int64_t cnt1 = p->cnt1;
1175     MYFLT lin1 = p->lin1;
1176     MYFLT lin2 = p->lin2;
1177 
1178     rs = p->rslt;
1179     sg = p->sig;
1180 
1181     if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT));
1182     if (UNLIKELY(early)) {
1183       nsmps -= early;
1184       memset(&rs[nsmps], '\0', early*sizeof(MYFLT));
1185     }
1186 
1187     for (n=offset; n<nsmps; n++) {
1188     val = FL(1.0);
1189     if (cnt1 > 0) {
1190       flag = 1;
1191       val = lin1;
1192       lin1 += p->inc1;
1193       cnt1--;
1194     }
1195 
1196     if (cnt2 > 0){
1197       cnt2--;
1198     }
1199     else {
1200       val *= lin2;
1201       lin2 -= p->inc2;
1202       flag = 1;
1203     }
1204 
1205     if (flag) {
1206       if (asgsg)
1207           rs[n] = sg[n] * val;
1208       else
1209           rs[n] = *sg * val;
1210       }
1211     else {
1212      if (asgsg)
1213         rs[n] = sg[n];
1214      else rs[n] = *sg;
1215      }
1216     flag = 0;
1217     }
1218     p->cnt2 = cnt2;
1219     p->cnt1 = cnt1;
1220     p->lin1 = lin1;
1221     p->lin2 = lin2;
1222     return OK;
1223 }
1224 
1225 
1226 
lnrset(CSOUND * csound,LINENR * p)1227 int32_t lnrset(CSOUND *csound, LINENR *p)
1228 {
1229     p->cnt1 = (int32_t)(*p->iris * CS_EKR + FL(0.5));
1230     if (p->cnt1 > 0L) {
1231       p->inc1 = FL(1.0) / (MYFLT)p->cnt1;
1232       p->val = FL(0.0);
1233     }
1234     else p->inc1 = p->val = FL(1.0);
1235     if (*p->idec > FL(0.0)) {
1236       int32_t relestim = (int32_t)(*p->idec * CS_EKR + FL(0.5));
1237 
1238       if (relestim > p->h.insdshead->xtratim)
1239         p->h.insdshead->xtratim = relestim;
1240       if (UNLIKELY(*p->iatdec <= FL(0.0))) {
1241         return csound->InitError(csound, Str("non-positive iatdec"));
1242       }
1243       else p->mlt2 = POWER(*p->iatdec, CS_ONEDKR / *p->idec);
1244     }
1245     else p->mlt2 = FL(1.0);
1246     p->lin1 = FL(0.0);
1247     p->val2 = FL(1.0);
1248     return OK;
1249 }
1250 
alnrset(CSOUND * csound,LINENR * p)1251 int32_t alnrset(CSOUND *csound, LINENR *p)
1252 {
1253     p->cnt1 = (int32_t)(*p->iris * CS_ESR);
1254     if (p->cnt1 > 0L) {
1255       p->inc1 = FL(1.0) / (MYFLT)p->cnt1;
1256       p->val = FL(0.0);
1257     }
1258     else p->inc1 = p->val = FL(1.0);
1259     if (*p->idec > FL(0.0)) {
1260       int32_t relestim = (int32_t)(*p->idec * CS_EKR + FL(0.5));
1261       if (relestim > p->h.insdshead->xtratim)
1262         p->h.insdshead->xtratim = relestim;
1263       if (UNLIKELY(*p->iatdec <= FL(0.0))) {
1264         return csound->InitError(csound, Str("non-positive iatdec"));
1265       }
1266       else p->mlt2 = POWER(*p->iatdec, csound->onedsr / *p->idec);
1267     }
1268     else p->mlt2 = FL(1.0);
1269     p->lin1 = FL(0.0);
1270     p->val2 = FL(1.0);
1271     return OK;
1272 }
1273 
1274 
klinenr(CSOUND * csound,LINENR * p)1275 int32_t klinenr(CSOUND *csound, LINENR *p)
1276 {
1277    IGN(csound);
1278     MYFLT fact = FL(1.0);
1279 
1280     if (p->cnt1 > 0L) {
1281       fact = p->lin1;
1282       p->lin1 += p->inc1;
1283       p->cnt1--;
1284     }
1285     if (p->h.insdshead->relesing) {
1286       fact *= p->val2;
1287       p->val2 *= p->mlt2;
1288     }
1289     *p->rslt = *p->sig * fact;
1290     return OK;
1291 }
1292 
linenr(CSOUND * csound,LINENR * p)1293 int32_t linenr(CSOUND *csound, LINENR *p)
1294 {
1295     IGN(csound);
1296     uint32_t offset = p->h.insdshead->ksmps_offset;
1297     uint32_t early  = p->h.insdshead->ksmps_no_end;
1298     uint32_t flag=0, n, nsmps = CS_KSMPS;
1299     MYFLT *rs,*sg,val,val2 = p->val2;
1300     int32_t    asgsg = IS_ASIG_ARG(p->sig);
1301     val = p->val;
1302     rs = p->rslt;
1303     sg = p->sig;
1304     if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT));
1305     if (UNLIKELY(early)) {
1306        nsmps -= early;
1307        memset(&rs[nsmps], '\0', early*sizeof(MYFLT));
1308     }
1309     for (n=offset; n<nsmps; n++) {
1310       if (p->cnt1 > 0L) {
1311         flag = 1;
1312         val = p->lin1;
1313         p->lin1 += p->inc1;
1314         p->cnt1--;
1315       }
1316       if (p->h.insdshead->relesing) {
1317         flag = 1;
1318         val = p->cnt1==0L ? val2 :val*val2;
1319         //val *= val2;              /* If val = val2 jumps */
1320         val2 *= p->mlt2;
1321       }
1322       if (flag) {
1323         if (asgsg)
1324           rs[n] = sg[n] * val;
1325         else
1326           rs[n] = *sg * val;
1327       }
1328       else {
1329         if (asgsg) rs[n] = sg[n];
1330         else rs[n] = *sg;
1331       }
1332     }
1333     p->val = val;
1334     p->val2 = val2;
1335     return OK;
1336 }
1337 
evxset(CSOUND * csound,ENVLPX * p)1338 int32_t evxset(CSOUND *csound, ENVLPX *p)
1339 {
1340     FUNC        *ftp;
1341     MYFLT       ixmod, iatss, idur, prod, diff, asym, nk, denom, irise;
1342     int32_t       cnt1;
1343     MYFLT       len = csound->curip->p3.value;
1344 
1345     if ((ftp = csound->FTFind(csound, p->ifn)) == NULL)
1346       return NOTOK;
1347     p->ftp = ftp;
1348     if ((idur = *p->idur) > FL(0.0)) {
1349       if (UNLIKELY((iatss = FABS(*p->iatss)) == FL(0.0))) {
1350         return csound->InitError(csound, "iatss = 0");
1351       }
1352       if (iatss != FL(1.0) && (ixmod = *p->ixmod) != FL(0.0)) {
1353         if (UNLIKELY(FABS(ixmod) > FL(0.95))) {
1354           return csound->InitError(csound, Str("ixmod out of range."));
1355         }
1356         ixmod = -SIN(SIN(ixmod));
1357         prod = ixmod * iatss;
1358         diff = ixmod - iatss;
1359         denom = diff + prod + FL(1.0);
1360         if (denom == FL(0.0))
1361           asym = FHUND;
1362         else {
1363           asym = FL(2.0) * prod / denom;
1364           if (FABS(asym) > FHUND)
1365             asym = FHUND;
1366         }
1367         iatss = (iatss - asym) / (FL(1.0) - asym);
1368         asym = asym* *(ftp->ftable + ftp->flen); /* +1 */
1369       }
1370       else asym = FL(0.0);
1371       if ((irise = *p->irise) > FL(0.0)) {
1372         if (irise + *p->idec > len)
1373           csound->Warning(csound, Str("p3 too short in envlpx"));
1374         p->phs = 0;
1375         p->ki = (int32_t) (CS_KICVT / irise);
1376         p->val = *ftp->ftable;
1377       }
1378       else {
1379         p->phs = -1;
1380         p->val = *(ftp->ftable + ftp->flen)-asym;
1381         irise = FL(0.0);  /* in case irise < 0 */
1382       }
1383       if (UNLIKELY(!(*(ftp->ftable + ftp->flen)))) {
1384         return csound->InitError(csound, Str("rise func ends with zero"));
1385       }
1386       cnt1 = (int32_t) ((idur - irise - *p->idec) * CS_EKR + FL(0.5));
1387       if (cnt1 < 0L) {
1388         cnt1 = 0;
1389         nk = CS_EKR;
1390       }
1391       else {
1392         if (*p->iatss < FL(0.0) || cnt1 <= 4L)
1393           nk = CS_EKR;
1394         else nk = (MYFLT) cnt1;
1395       }
1396       p->mlt1 = POWER(iatss, (FL(1.0)/nk));
1397       if (*p->idec > FL(0.0)) {
1398         if (UNLIKELY(*p->iatdec <= FL(0.0))) {
1399           return csound->InitError(csound, Str("non-positive iatdec"));
1400         }
1401         p->mlt2 = POWER(*p->iatdec, (CS_ONEDKR / *p->idec));
1402       }
1403       p->cnt1 = cnt1;
1404       p->asym = asym;
1405     }
1406     return OK;
1407 }
1408 
knvlpx(CSOUND * csound,ENVLPX * p)1409 int32_t knvlpx(CSOUND *csound, ENVLPX *p)
1410 {
1411     FUNC        *ftp;
1412     int32_t       phs;
1413     MYFLT       fact, v1, fract, *ftab;
1414 
1415     ftp = p->ftp;
1416     if (UNLIKELY(ftp==NULL)) goto err1;        /* RWD fix */
1417 
1418     if ((phs = p->phs) >= 0) {
1419       fract = (MYFLT) PFRAC(phs);
1420       ftab = ftp->ftable + (phs >> ftp->lobits);
1421       v1 = *ftab++;
1422       fact = (v1 + (*ftab - v1) * fract);
1423       phs += p->ki;
1424       if (phs >= MAXLEN) {  /* check that 2**N+1th pnt is good */
1425         p->val = *(ftp->ftable + ftp->flen );
1426         if (UNLIKELY(!p->val)) {
1427           return csound->PerfError(csound, &(p->h),
1428                                    Str("envlpx rise func ends with zero"));
1429         }
1430         p->val -= p->asym;
1431         phs = -1L;
1432       }
1433       p->phs = phs;
1434     }
1435     else {
1436       fact = p->val;
1437       if (p->cnt1 > 0L) {
1438         p->val *= p->mlt1;
1439         fact += p->asym;
1440         p->cnt1--;
1441         if (p->cnt1 == 0L)
1442           p->val += p->asym;
1443       }
1444       else p->val *= p->mlt2;
1445     }
1446     *p->rslt = *p->xamp * fact;
1447     return OK;
1448  err1:
1449     return csound->PerfError(csound, &(p->h),
1450                              Str("envlpx(krate): not initialised"));
1451 }
1452 
aevxset(CSOUND * csound,ENVLPX * p)1453 int32_t aevxset(CSOUND *csound, ENVLPX *p)
1454 {
1455     FUNC        *ftp;
1456     MYFLT       ixmod, iatss, idur, prod, diff, asym, nk, denom, irise;
1457     int32_t       cnt1;
1458     MYFLT       len = csound->curip->p3.value;
1459 
1460     if ((ftp = csound->FTFind(csound, p->ifn)) == NULL)
1461       return NOTOK;
1462     p->ftp = ftp;
1463     if ((idur = *p->idur) > FL(0.0)) {
1464       if (UNLIKELY((iatss = FABS(*p->iatss)) == FL(0.0))) {
1465         return csound->InitError(csound, "iatss = 0");
1466       }
1467       if (iatss != FL(1.0) && (ixmod = *p->ixmod) != FL(0.0)) {
1468         if (UNLIKELY(FABS(ixmod) > FL(0.95))) {
1469           return csound->InitError(csound, Str("ixmod out of range."));
1470         }
1471         ixmod = -SIN(SIN(ixmod));
1472         prod = ixmod * iatss;
1473         diff = ixmod - iatss;
1474         denom = diff + prod + FL(1.0);
1475         if (denom == FL(0.0))
1476           asym = FHUND;
1477         else {
1478           asym = FL(2.0) * prod / denom;
1479           if (FABS(asym) > FHUND)
1480             asym = FHUND;
1481         }
1482         iatss = (iatss - asym) / (FL(1.0) - asym);
1483         asym = asym* *(ftp->ftable + ftp->flen); /* +1 */
1484       }
1485       else asym = FL(0.0);
1486 
1487       if ((irise = *p->irise) > FL(0.0)) {
1488         if (irise + *p->idec > len)
1489           csound->Warning(csound, Str("p3 too short in envlpx"));
1490         p->phs = 0;
1491         p->ki = (int32_t) ((FMAXLEN / CS_ESR )/ irise);
1492         p->val = *ftp->ftable;
1493       }
1494       else {
1495         p->phs = -1;
1496         p->val = *(ftp->ftable + ftp->flen)-asym;
1497         irise = FL(0.0);  /* in case irise < 0 */
1498       }
1499       if (UNLIKELY(!(*(ftp->ftable + ftp->flen)))) {
1500         return csound->InitError(csound, Str("rise func ends with zero"));
1501       }
1502       cnt1 = (int32_t) ((idur - irise - *p->idec) * CS_ESR);
1503       if (cnt1 < 0L) {
1504         cnt1 = 0;
1505         nk = CS_ESR;
1506       }
1507       else {
1508         if (*p->iatss < FL(0.0) || cnt1 <= 4L)
1509           nk = CS_ESR;
1510         else nk = (MYFLT) cnt1;
1511       }
1512       p->mlt1 = POWER(iatss, (FL(1.0)/nk));
1513       if (*p->idec > FL(0.0)) {
1514         if (UNLIKELY(*p->iatdec <= FL(0.0))) {
1515           return csound->InitError(csound, Str("non-positive iatdec"));
1516         }
1517         p->mlt2 = POWER(*p->iatdec, (csound->onedsr / *p->idec));
1518       }
1519       p->cnt1 = cnt1;
1520       p->asym = asym;
1521     }
1522     return OK;
1523 }
1524 
1525 
envlpx(CSOUND * csound,ENVLPX * p)1526 int32_t envlpx(CSOUND *csound, ENVLPX *p)
1527 {
1528     int32_t       phs;
1529     uint32_t offset = p->h.insdshead->ksmps_offset;
1530     uint32_t early  = p->h.insdshead->ksmps_no_end;
1531     uint32_t n, nsmps = CS_KSMPS;
1532     int64_t pos, lobits, lomask;
1533     MYFLT      fact, *xamp, *rslt, val, asym, mlt, mlt2, v1, fract, *ftab, lodiv;
1534     int32_t        asgsg = IS_ASIG_ARG(p->xamp);
1535     xamp = p->xamp;
1536     rslt = p->rslt;
1537     val  = p->val;
1538     mlt = p->mlt1;
1539     mlt2 = p->mlt2;
1540     asym = p->asym;
1541 
1542     if (UNLIKELY(p->ftp==NULL))
1543       return csound->PerfError(csound, &(p->h),
1544                              Str("envlpx(krate): not initialised"));
1545     ftab = p->ftp->ftable;
1546     lobits = p->ftp->lobits;
1547     lomask = p->ftp->lomask;
1548     lodiv  = p->ftp->lodiv;
1549     if (UNLIKELY(ftab[p->ftp->flen] == 0.0))
1550       return csound->PerfError(csound, &(p->h),
1551                              Str("envlpx rise func ends with zero"));
1552 
1553     if (UNLIKELY(offset)) memset(rslt, '\0', offset*sizeof(MYFLT));
1554     if (UNLIKELY(early)) {
1555       nsmps -= early;
1556       memset(&rslt[nsmps], '\0', early*sizeof(MYFLT));
1557     }
1558 
1559 
1560     for (n=offset; n<nsmps;n++) {
1561 
1562      if ((phs = p->phs) >= 0L) {
1563        fract = ((phs) & lomask) * lodiv;
1564        pos = (int64_t) (phs >> lobits);
1565        v1 = ftab[pos+1];
1566        fact = (v1 + (ftab[pos] - v1) * fract);
1567        phs += p->ki;
1568        if (phs >= MAXLEN) {
1569         val = ftab[p->ftp->flen];
1570         val -= p->asym;
1571         phs = -1;
1572       }
1573       p->phs = phs;
1574     }
1575     else {
1576       fact = val;
1577       if (p->cnt1 > 0L) {
1578         val *= mlt;
1579         fact += asym;
1580         p->cnt1--;
1581         if (p->cnt1 == 0L)
1582           val += asym;
1583       }
1584       else val *= mlt2;
1585     }
1586     if (asgsg)
1587         rslt[n] = xamp[n] * fact;
1588     else
1589         rslt[n] = *xamp * fact;
1590     }
1591     p->val = val;
1592     return OK;
1593 }
1594 
evrset(CSOUND * csound,ENVLPR * p)1595 int32_t evrset(CSOUND *csound, ENVLPR *p)
1596 {
1597     FUNC        *ftp;
1598     MYFLT       ixmod, iatss, prod, diff, asym, denom, irise;
1599 
1600     if ((ftp = csound->FTFind(csound, p->ifn)) == NULL)
1601       return NOTOK;
1602     p->ftp = ftp;
1603     if (UNLIKELY((iatss = FABS(*p->iatss)) == FL(0.0))) {
1604       return csound->InitError(csound, "iatss = 0");
1605     }
1606     if (iatss != FL(1.0) && (ixmod = *p->ixmod) != FL(0.0)) {
1607       if (UNLIKELY(FABS(ixmod) > FL(0.95))) {
1608         return csound->InitError(csound, Str("ixmod out of range."));
1609       }
1610       ixmod = -SIN(SIN(ixmod));
1611       prod  = ixmod * iatss;
1612       diff  = ixmod - iatss;
1613       denom = diff + prod + FL(1.0);
1614       if (denom == FL(0.0))
1615         asym = FHUND;
1616       else {
1617         asym = FL(2.0) * prod / denom;
1618         if (FABS(asym) > FHUND)
1619           asym = FHUND;
1620       }
1621       iatss = (iatss - asym) / (FL(1.0) - asym);
1622       asym = asym * *(ftp->ftable + ftp->flen); /* +1 */
1623     }
1624     else asym = FL(0.0);
1625     if ((irise = *p->irise) > FL(0.0)) {
1626       p->phs = 0;
1627       p->ki = (int32_t) (CS_KICVT / irise);
1628       p->val = *ftp->ftable;
1629     }
1630     else {
1631       p->phs = -1;
1632       p->val = *(ftp->ftable + ftp->flen)-asym;
1633       /* irise = FL(0.0); */          /* in case irise < 0 */
1634     }
1635     if (UNLIKELY(!(*(ftp->ftable + ftp->flen)))) {
1636       return csound->InitError(csound, Str("rise func ends with zero"));
1637     }
1638     p->mlt1 = POWER(iatss, CS_ONEDKR);
1639     if (*p->idec > FL(0.0)) {
1640       int32_t rlscnt = (int32_t)(*p->idec * CS_EKR + FL(0.5));
1641       if ((p->rindep = (int32_t)*p->irind))
1642         p->rlscnt = rlscnt;
1643       else if (rlscnt > p->h.insdshead->xtratim)
1644         p->h.insdshead->xtratim = (int32_t)rlscnt;
1645       if (UNLIKELY((p->atdec = *p->iatdec) <= FL(0.0) )) {
1646         return csound->InitError(csound, Str("non-positive iatdec"));
1647       }
1648     }
1649     p->asym = asym;
1650     p->rlsing = 0;
1651     return OK;
1652 }
1653 
aevrset(CSOUND * csound,ENVLPR * p)1654 int32_t aevrset(CSOUND *csound, ENVLPR *p)
1655 {
1656     FUNC        *ftp;
1657     MYFLT       ixmod, iatss, prod, diff, asym, denom, irise;
1658 
1659     if ((ftp = csound->FTFind(csound, p->ifn)) == NULL)
1660       return NOTOK;
1661     p->ftp = ftp;
1662     if (UNLIKELY((iatss = FABS(*p->iatss)) == FL(0.0))) {
1663       return csound->InitError(csound, "iatss = 0");
1664     }
1665     if (iatss != FL(1.0) && (ixmod = *p->ixmod) != FL(0.0)) {
1666       if (UNLIKELY(FABS(ixmod) > FL(0.95))) {
1667         return csound->InitError(csound, Str("ixmod out of range."));
1668       }
1669       ixmod = -SIN(SIN(ixmod));
1670       prod  = ixmod * iatss;
1671       diff  = ixmod - iatss;
1672       denom = diff + prod + FL(1.0);
1673       if (denom == FL(0.0))
1674         asym = FHUND;
1675       else {
1676         asym = FL(2.0) * prod / denom;
1677         if (FABS(asym) > FHUND)
1678           asym = FHUND;
1679       }
1680       iatss = (iatss - asym) / (FL(1.0) - asym);
1681       asym = asym * *(ftp->ftable + ftp->flen); /* +1 */
1682     }
1683     else asym = FL(0.0);
1684     if ((irise = *p->irise) > FL(0.0)) {
1685       p->phs = 0;
1686       p->ki = (int32_t) ((FMAXLEN / CS_ESR)/ irise);
1687       p->val = *ftp->ftable;
1688     }
1689     else {
1690       p->phs = -1;
1691       p->val = *(ftp->ftable + ftp->flen)-asym;
1692       /* irise = FL(0.0); */          /* in case irise < 0 */
1693     }
1694     if (UNLIKELY(!(*(ftp->ftable + ftp->flen)))) {
1695       return csound->InitError(csound, Str("rise func ends with zero"));
1696     }
1697     p->mlt1 = POWER(iatss, csound->onedsr);
1698     if (*p->idec > FL(0.0)) {
1699       int32_t rlscnt = (int32_t)(*p->idec * CS_EKR + FL(0.5));
1700       if ((p->rindep = (int32_t)*p->irind))
1701         p->rlscnt = rlscnt;
1702       else if (rlscnt > p->h.insdshead->xtratim)
1703         p->h.insdshead->xtratim = (int32_t)rlscnt;
1704       if (UNLIKELY((p->atdec = *p->iatdec) <= FL(0.0) )) {
1705         return csound->InitError(csound, Str("non-positive iatdec"));
1706       }
1707     }
1708     p->asym = asym;
1709     p->rlsing = 0;
1710     return OK;
1711 }
1712 
1713 
knvlpxr(CSOUND * csound,ENVLPR * p)1714 int32_t knvlpxr(CSOUND *csound, ENVLPR *p)
1715 {
1716     IGN(csound);
1717     MYFLT  fact;
1718     int32_t  rlscnt;
1719 
1720     if (!p->rlsing) {                   /* if not in reles seg  */
1721       if (p->h.insdshead->relesing) {
1722         p->rlsing = 1;                  /*   if new flag, set mlt2 */
1723         rlscnt = (p->rindep) ? p->rlscnt : p->h.insdshead->xtratim;
1724         if (rlscnt)
1725           p->mlt2 = POWER(p->atdec, FL(1.0)/rlscnt);
1726         else p->mlt2 = FL(1.0);
1727       }
1728       if (p->phs >= 0) {                /* do fn rise for seg 1 */
1729         FUNC *ftp = p->ftp;
1730         int32_t phs = p->phs;
1731         MYFLT fract = PFRAC(phs);
1732         MYFLT *ftab = ftp->ftable + (phs >> ftp->lobits);
1733         MYFLT v1 = *ftab++;
1734         fact = (v1 + (*ftab - v1) * fract);
1735         phs += p->ki;
1736         if (phs < MAXLEN || p->rlsing)  /* if more fn or beg rls */
1737           p->val = fact;                /*      save cur val     */
1738         else {                          /* else prep for seg 2  */
1739           p->val = *(ftp->ftable + ftp->flen) - p->asym;
1740           phs = -1L;
1741         }
1742         p->phs = phs;
1743       }
1744       else {
1745         fact = p->val + p->asym;        /* do seg 2 with asym */
1746         p->val *= p->mlt1;
1747         if (p->rlsing)                  /* if ending, rm asym */
1748           p->val += p->asym;
1749       }
1750     }
1751     else fact = p->val *= p->mlt2;      /* else do seg 3 decay */
1752     *p->rslt = *p->xamp * fact;
1753     return OK;
1754 }
1755 
envlpxr(CSOUND * csound,ENVLPR * p)1756 int32_t envlpxr(CSOUND *csound, ENVLPR *p)
1757 {
1758     uint32_t offset = p->h.insdshead->ksmps_offset;
1759     uint32_t early  = p->h.insdshead->ksmps_no_end;
1760     uint32_t n, nsmps = CS_KSMPS;
1761     int32_t  rlscnt;
1762     int64_t lobits, lomask, pos, phs = p->phs;
1763     MYFLT fact, *xamp, *rslt, val, asym, mlt, v1, fract, *ftab, lodiv;
1764     int32_t    asgsg = IS_ASIG_ARG(p->xamp);
1765 
1766     xamp = p->xamp;
1767     rslt = p->rslt;
1768     val  = p->val;
1769     mlt = p->mlt1;
1770     //mlt2 = p->mlt2;
1771     asym = p->asym;
1772 
1773     if (UNLIKELY(p->ftp==NULL))
1774       return csound->PerfError(csound, &(p->h),
1775                              Str("envlpx(krate): not initialised"));
1776     ftab = p->ftp->ftable;
1777     lobits = p->ftp->lobits;
1778     lomask = p->ftp->lomask;
1779     lodiv  = p->ftp->lodiv;
1780     if (UNLIKELY(ftab[p->ftp->flen] == 0.0))
1781       return csound->PerfError(csound, &(p->h),
1782                              Str("envlpx rise func ends with zero"));
1783 
1784     if (UNLIKELY(offset)) memset(rslt, '\0', offset*sizeof(MYFLT));
1785     if (UNLIKELY(early)) {
1786       nsmps -= early;
1787       memset(&rslt[nsmps], '\0', early*sizeof(MYFLT));
1788     }
1789 
1790     for (n=offset; n<nsmps; n++) {
1791 
1792       if (!p->rlsing) {                   /* if not in reles seg  */
1793         if (p->h.insdshead->relesing) {
1794           p->rlsing = 1;                  /*   if new flag, set mlt2 */
1795           rlscnt = (p->rindep) ? p->rlscnt : p->h.insdshead->xtratim;
1796           rlscnt *= CS_KSMPS;
1797           if (rlscnt)
1798             p->mlt2 = POWER(p->atdec, FL(1.0)/rlscnt);
1799           else p->mlt2 = FL(1.0);
1800         }
1801         if (p->phs >= 0) {                /* do fn rise for seg 1 */
1802           fract = ((phs) & lomask) * lodiv;
1803           pos = (int64_t) (phs >> lobits);
1804           v1 = ftab[pos+1];
1805           fact = (v1 + (ftab[pos] - v1) * fract);
1806           phs += p->ki;
1807           if (phs >= MAXLEN) {
1808             val = ftab[p->ftp->flen];
1809             val -= p->asym;
1810             phs = -1;
1811           }
1812           else val = fact;      /* JPff: in case very early release */
1813           p->phs = phs;
1814         }
1815         else {
1816           fact = val + asym;
1817           val *= mlt;
1818           if (p->rlsing)
1819             val += asym;
1820         }
1821       }
1822       else
1823         fact = val *= p->mlt2;     /* else do seg 3 decay  */
1824 
1825       if (asgsg)
1826         rslt[n] = xamp[n] * fact;
1827       else
1828         rslt[n] = *xamp * fact;
1829     }
1830     p->val = val;
1831     return OK;
1832 }
1833 
csgset(CSOUND * csound,COSSEG * p)1834 int32_t csgset(CSOUND *csound, COSSEG *p)
1835 {
1836     SEG *segp, *sp;
1837     int32_t nsegs;
1838     MYFLT       **argp;
1839     double val, y1, y2;
1840 
1841 
1842     if (!(p->INCOUNT & 1)) {
1843       return csound->InitError(csound, Str("incomplete number of input arguments"));
1844     }
1845 
1846     /* count segs & alloc if nec */
1847     nsegs = (p->INOCOUNT - (!(p->INOCOUNT & 1))) >> 1;
1848     //printf("****nsegs = %d\n", nsegs);
1849     if ((segp = (SEG *) p->auxch.auxp) == NULL ||
1850         nsegs*sizeof(SEG) < (uint32_t)p->auxch.size) {
1851       csound->AuxAlloc(csound, (int32_t)(1+nsegs)*sizeof(SEG), &p->auxch);
1852       p->cursegp = 1+(segp = (SEG *) p->auxch.auxp);
1853       segp[nsegs-1].cnt = MAXPOS; /* set endcount for safety */
1854       segp[nsegs-1].acnt = MAXPOS;
1855     }
1856     sp = segp;
1857     argp = p->argums;
1858     y1 = val = (double)**argp++;
1859     if (UNLIKELY(**argp <= FL(0.0)))  return OK;    /* if idur1 <= 0, skip init  */
1860     p->curcnt = 0;
1861     p->cursegp = segp+1;          /* else setup first seg */
1862     p->segsrem = nsegs;
1863     //printf("****current seg = %p segp = %p\n", p->cursegp, segp);
1864     do {                                /* init each seg ..  */
1865       double dur = (double)**argp++;
1866       segp->nxtpt = (double)**argp++;
1867       if (UNLIKELY((segp->cnt = (int32_t)(dur * CS_EKR + FL(0.5))) < 0))
1868         segp->cnt = 0;
1869       if (UNLIKELY((segp->acnt = (int32_t)(dur * CS_ESR)) < 0))
1870         segp->acnt = 0;
1871 
1872       //printf("****i: %d(%p): cnt=%d nxtpt=%f\n",
1873       //       p->segsrem-nsegs, segp, segp->cnt, segp->nxtpt);
1874       segp++;
1875     } while (--nsegs);
1876     p->y1 = y1;
1877     p->y2 = y2 = sp->nxtpt;
1878     p->x = 0.0;
1879     if (IS_ASIG_ARG(p->rslt)) {
1880       p->inc = (y2!=y1 ? 1.0/(sp->acnt) : 0.0);
1881       p->curcnt = sp->acnt;
1882     }
1883     else {
1884       p->inc = (y2!=y1 ? 1.0/(sp->cnt) : 0.0);
1885       p->curcnt = sp->cnt;
1886     }
1887     //printf("****incx, y1,y2 = %g, %f, %f\n", p->inc, p->y1, p->y2);
1888     p->val = p->y1;
1889     return OK;
1890 }
1891 
csgset_bkpt(CSOUND * csound,COSSEG * p)1892 int32_t csgset_bkpt(CSOUND *csound, COSSEG *p)
1893 {
1894     int32_t cnt, bkpt = 0;
1895     int32_t nsegs;
1896     int32_t n;
1897     SEG *segp;
1898     n = csgset(csound, p);
1899     if (UNLIKELY(n!=0)) return n;
1900     cnt = p->curcnt;
1901     nsegs = p->segsrem-1;
1902     segp = p->cursegp;
1903     if (IS_ASIG_ARG(p->rslt))
1904     do {
1905       if (UNLIKELY(cnt > segp->acnt))
1906         return csound->InitError(csound, Str("Breakpoint %d not valid"), bkpt);
1907       segp->acnt -= cnt;
1908       cnt += segp->acnt;
1909       segp++;
1910       bkpt++;
1911     } while (--nsegs);
1912     else
1913     do {
1914       //csound->Message(csound, "%d/ %d: %d, %d ", nsegs, bkpt, cnt, segp->cnt);
1915       if (UNLIKELY(cnt > segp->cnt))
1916         return csound->InitError(csound, Str("Breakpoint %d not valid"), bkpt);
1917       segp->cnt -= cnt;
1918       cnt += segp->cnt;
1919       //csound->Message(csound, "-> %d, %d %f\n", cnt, segp->cnt, segp->nxtpt);
1920       segp++;
1921       bkpt++;
1922     } while (--nsegs);
1923 
1924     return OK;
1925 }
1926 
csgrset(CSOUND * csound,COSSEG * p)1927 int32_t csgrset(CSOUND *csound, COSSEG *p)
1928 {
1929     int32_t relestim;
1930     if (csgset(csound,p) != 0) return NOTOK;
1931     relestim = (p->cursegp + p->segsrem-2)->cnt;
1932     p->xtra = relestim;
1933     if (relestim > p->h.insdshead->xtratim)
1934       p->h.insdshead->xtratim = (int32_t)relestim;
1935     return OK;
1936 }
1937 
kosseg(CSOUND * csound,COSSEG * p)1938 int32_t kosseg(CSOUND *csound, COSSEG *p)
1939 {
1940     double val1 = p->y1, val2 = p->y2, x = p->x;
1941     double inc = p->inc;
1942 
1943     if (UNLIKELY(p->auxch.auxp==NULL)) goto err1;          /* RWD fix */
1944 
1945     if (LIKELY(p->segsrem)) {             /* if no more segs putk */
1946       if (--p->curcnt <= 0) {             /*  if done cur segment */
1947         SEG *segp = p->cursegp;
1948       chk1:
1949         p->y1 = val1 = val2;
1950         if (UNLIKELY(!--p->segsrem)) {    /*   if none left       */
1951           p->y2 = val2 = segp->nxtpt;
1952           goto putk;                      /*      put endval      */
1953         }
1954         //printf("new seg: %d %f\n", segp->cnt, segp->nxtpt);
1955         val2 = p->y2 = segp->nxtpt;          /* Base of next segment */
1956         inc = p->inc = (segp->cnt ? 1.0/(segp->cnt) : 0.0);
1957         x = 0.0;
1958         p->cursegp = segp+1;              /*   else find the next */
1959         if (UNLIKELY(!(p->curcnt = segp->cnt))) {
1960           val2 = p->y2 = segp->nxtpt;  /* nonlen = discontin */
1961           inc = p->inc = (segp->cnt ? 1.0/(segp->cnt) : 0.0);
1962           goto chk1;
1963         }                                 /*   poslen = new slope */
1964       }
1965       {
1966         double mu2 = (1.0-cos(x*PI))*0.5;
1967         *p->rslt = (MYFLT)(val1*(1.0-mu2)+val2*mu2);
1968         x += inc;
1969       }
1970     }
1971     else {
1972     putk:
1973       *p->rslt = (MYFLT)val1;
1974     }
1975     p->x = x;
1976     return OK;
1977  err1:
1978     return csound->InitError(csound, Str("cosseg not initialised (krate)\n"));
1979 }
1980 
cosseg(CSOUND * csound,COSSEG * p)1981 int32_t cosseg(CSOUND *csound, COSSEG *p)
1982 {
1983     double val1 = p->y1, val2 = p->y2, x = p->x;
1984     MYFLT *rs = p->rslt;
1985     uint32_t offset = p->h.insdshead->ksmps_offset;
1986     uint32_t early  = p->h.insdshead->ksmps_no_end;
1987     uint32_t n, nsmps = CS_KSMPS;
1988     double inc = p->inc;///(nsmps-offset);
1989 
1990     if (UNLIKELY(p->auxch.auxp==NULL)) goto err1;
1991 
1992     if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT));
1993     if (UNLIKELY(early)) {
1994       nsmps -= early;
1995       memset(&rs[nsmps], '\0', early*sizeof(MYFLT));
1996     }
1997 
1998     for (n=offset; n<nsmps; n++) {
1999       double mu2;
2000       if (LIKELY(p->segsrem)) {             /* if no more segs putk */
2001         if (--p->curcnt <= 0) {             /*  if done cur segment */
2002           SEG *segp = p->cursegp;
2003         chk1:
2004           p->y1 = val1 = val2;
2005           if (UNLIKELY(!--p->segsrem)) {    /*   if none left       */
2006             p->y2 = val2 = segp->nxtpt;
2007             goto putk;                      /*      put endval      */
2008           }
2009           val2 = p->y2 = segp->nxtpt;          /* Base of next segment */
2010           inc = (segp->acnt ? 1.0/(segp->acnt) : 0.0);
2011           x = 0.0;
2012           //printf("****new seg val1.val2=%f,%f inc=%f\n", val1,val2, inc);
2013           p->cursegp = segp+1;              /*   else find the next */
2014           if (UNLIKELY(!(p->curcnt = segp->acnt))) {
2015             val2 = p->y2 = segp->nxtpt;  /* nonlen = discontin */
2016             inc = (segp->acnt ? 1.0/(segp->acnt) : 0.0);
2017             //printf("****val1,val2=%f,%f inc=%f\n", val1, val2, inc);
2018             goto chk1;
2019           }                                 /*   poslen = new slope */
2020         }
2021         mu2 = (1.0-cos(x*PI))*0.5;
2022         //printf("****x=%f inc=%f mu2=%f\n", x, inc, mu2);
2023         rs[n] = (MYFLT)(val1*(1.0-mu2)+val2*mu2);
2024         x += inc;
2025       }
2026       else {
2027       putk:
2028         rs[n] = (MYFLT)val1;
2029 
2030       }
2031     }
2032     p->inc = inc;
2033     p->x = x;
2034     return OK;
2035  err1:
2036     return csound->PerfError(csound, &(p->h),
2037                              Str("cosseg: not initialised (arate)\n"));
2038 }
2039 
cossegr(CSOUND * csound,COSSEG * p)2040 int32_t cossegr(CSOUND *csound, COSSEG *p)
2041 {
2042     double val1 = p->y1, val2 = p->y2, x = p->x, val = p->val;
2043     MYFLT *rs = p->rslt;
2044     uint32_t offset = p->h.insdshead->ksmps_offset;
2045     uint32_t n, nsmps = CS_KSMPS;
2046     double inc = p->inc;
2047 
2048     memset(rs, '\0', offset*sizeof(MYFLT));
2049     if (UNLIKELY(p->auxch.auxp==NULL)) goto err1;
2050 
2051     for (n=offset; n<nsmps; n++) {
2052       if (LIKELY(p->segsrem)) {             /* if no more segs putk */
2053         SEG *segp = p->cursegp;
2054         if (p->h.insdshead->relesing && p->segsrem > 1) {
2055           while (p->segsrem > 1) {            /* release flag new:    */
2056             segp = ++p->cursegp;              /*   go to last segment */
2057             p->segsrem--;
2058           }
2059           segp--;                                 /*   get univ relestim  */
2060           segp->acnt = (p->xtra >=0 ? p->xtra : p->h.insdshead->xtratim)*CS_KSMPS;
2061           //p->y1 = val1 = val2;
2062           p->y1 = val1 = val;
2063           //printf("%d(%p): cnt=%d strt= %f nxtpt=%f\n",
2064           //      p->segsrem, segp, segp->cnt,val1, segp->nxtpt);
2065           goto newi;                          /*   and set new curinc */
2066         }
2067         if (p->segsrem == 1 && !p->h.insdshead->relesing) {
2068           goto putk;
2069         }
2070         if (--p->curcnt <= 0) {             /*  if done cur segment */
2071         chk1:
2072           p->y1 = val1 = val2;
2073           if (UNLIKELY(!--p->segsrem)) {    /*   if none left       */
2074             p->y2 = val2 = segp->nxtpt;
2075             goto putk;                      /*      put endval      */
2076           }
2077         newi:
2078           //printf("new seg: %d %f\n", segp->cnt, segp->nxtpt);
2079           val2 = p->y2 = segp->nxtpt;          /* Base of next segment */
2080           inc =p->inc = (segp->acnt ? 1.0/(segp->acnt) : 0.0);
2081           x = 0.0;
2082           p->cursegp = segp+1;              /*   else find the next */
2083           if (UNLIKELY(!(p->curcnt = segp->acnt))) {
2084             val2 = p->y2 = segp->nxtpt;  /* nonlen = discontin */
2085             inc = p->inc = (segp->acnt ? 1.0/(segp->acnt) : 0.0);
2086             goto chk1;
2087           }                                 /*   poslen = new slope */
2088           //printf("New segment incx, y1,y2 = %g, %f, %f\n", inc, val1, val2);
2089         }
2090         {
2091           double mu2 = (1.0-cos(x*PI))*0.5;
2092           val = rs[n] = (MYFLT)(val1*(1.0-mu2)+val2*mu2);
2093           x += inc;
2094           //if (x>1 || x<0) printf("x=%f out of range\n", x);
2095         }
2096       }
2097       else {
2098       putk:
2099         rs[n] = (MYFLT)val1;
2100       }
2101     }
2102     p->inc = inc;
2103     p->x = x;
2104     p->val = val;
2105     return OK;
2106  err1:
2107     return csound->PerfError(csound, &(p->h),
2108                              Str("cossegr: not initialised (arate)\n"));
2109 }
2110 
2111 
2112 #if 0
2113 int32_t cossegr(CSOUND *csound, COSSEG *p)
2114 {
2115     double val1 = p->y1, val2 = p->y2, x = p->x;
2116     MYFLT *rs = p->rslt;
2117     uint32_t offset = p->h.insdshead->ksmps_offset;
2118     uint32_t n, nsmps = CS_KSMPS;
2119     double inc = p->inc/(nsmps-offset);
2120 
2121     memset(rs, '\0', offset*sizeof(MYFLT));
2122     if (UNLIKELY(p->auxch.auxp==NULL)) goto err1;
2123 
2124     if (LIKELY(p->segsrem)) {             /* if no more segs putk */
2125       SEG *segp = p->cursegp;
2126       if (p->h.insdshead->relesing && p->segsrem > 1) {
2127         while (p->segsrem > 1) {            /* release flag new:    */
2128           segp = ++p->cursegp;              /*   go to last segment */
2129           p->segsrem--;
2130         }                                   /*   get univ relestim  */
2131         segp->cnt = p->xtra >=0 ? p->xtra : p->h.insdshead->xtratim;
2132         goto newi;                          /*   and set new curinc */
2133       }
2134       if (--p->curcnt <= 0) {             /*  if done cur segment */
2135       chk1:
2136         p->y1 = val1 = val2;
2137         if (UNLIKELY(!--p->segsrem)) {    /*   if none left       */
2138           p->y2 = val2 = segp->nxtpt;
2139           goto putk;                      /*      put endval      */
2140         }
2141       newi:
2142         //printf("new seg: %d %f\n", segp->cnt, segp->nxtpt);
2143         val2 = p->y2 = segp->nxtpt;          /* Base of next segment */
2144         p->inc = (segp->cnt ? 1.0/(segp->cnt) : 0.0);
2145         inc /= nsmps;
2146         x = 0.0;
2147         p->cursegp = segp+1;              /*   else find the next */
2148         if (UNLIKELY(!(p->curcnt = segp->cnt))) {
2149           val2 = p->y2 = segp->nxtpt;  /* nonlen = discontin */
2150           p->inc = (segp->cnt ? 1.0/(segp->cnt) : 0.0);
2151           inc /= nsmps;
2152           //printf("zero length: incx, y1,y2 = %f, %f, %f\n", inc, val1, val2);
2153           goto chk1;
2154         }                                 /*   poslen = new slope */
2155         //printf("New segment incx, y1,y2 = %g, %f, %f\n", inc, val1, val2);
2156       }
2157       for (n=offset; n<nsmps; n++) {
2158         double mu2 = (1.0-cos(x*PI))*0.5;
2159         rs[n] = (MYFLT)(val1*(1.0-mu2)+val2*mu2);
2160         x += inc;
2161         //if (x>1 || x<0) printf("x=%f out of range\n", x);
2162       }
2163     }
2164     else {
2165     putk:
2166       //printf("ending at %f\n", val1);
2167       for (n=offset; n<nsmps; n++) {
2168         rs[n] = (MYFLT)val1;
2169       }
2170     }
2171     p->x = x;
2172     return OK;
2173  err1:
2174     return csound->PerfError(csound, &(p->h),
2175                              Str("cossegr: not initialised (arate)\n"));
2176 }
2177 #endif
2178 
kcssegr(CSOUND * csound,COSSEG * p)2179 int32_t kcssegr(CSOUND *csound, COSSEG *p)
2180 {
2181     double val1 = p->y1, val2 = p->y2, x = p->x, val = p->val;
2182     double inc = p->inc;
2183 
2184     if (UNLIKELY(p->auxch.auxp==NULL)) goto err1;          /* RWD fix */
2185 
2186     if (LIKELY(p->segsrem)) {             /* if no more segs putk */
2187       SEG *segp = p->cursegp;
2188       if (p->h.insdshead->relesing && p->segsrem > 1) {
2189         while (p->segsrem > 1) {           /* reles flag new:      */
2190           segp = ++p->cursegp;             /*   go to last segment */
2191           p->segsrem--;
2192         }
2193         segp--;                             /*   get univ relestim  */
2194         segp->cnt = p->xtra>= 0 ? p->xtra : p->h.insdshead->xtratim;
2195         p->y1 = val1 = val;
2196         goto newi;                         /*   and set new curinc */
2197       }
2198       if (p->segsrem == 1 && !p->h.insdshead->relesing) {
2199        goto putk;
2200       }
2201       if (--p->curcnt <= 0) {             /*  if done cur segment */
2202       chk1:
2203         p->y1 = val1 = val2;
2204         if (UNLIKELY(!--p->segsrem)) {    /*   if none left       */
2205           p->y2 = val2 = segp->nxtpt;
2206           goto putk;                      /*      put endval      */
2207         }
2208       newi:
2209         val2 = p->y2 = segp->nxtpt;          /* Base of next segment */
2210         inc = p->inc = (segp->cnt ? 1.0/(segp->cnt) : 0.0);
2211         x = 0.0;
2212         p->cursegp = segp+1;              /*   else find the next */
2213         if (UNLIKELY(!(p->curcnt = segp->cnt))) {
2214           val2 = p->y2 = segp->nxtpt;  /* nonlen = discontin */
2215           inc = p->inc = (segp->cnt ? 1.0/(segp->cnt) : 0.0);
2216           goto chk1;
2217         }                                 /*   poslen = new slope */
2218       }
2219       {
2220         double mu2 = (1.0-cos(x*PI))*0.5;
2221         val = *p->rslt = (MYFLT)(val1*(1.0-mu2)+val2*mu2);
2222         x += inc;
2223       }
2224     }
2225     else {
2226     putk:
2227         *p->rslt = (MYFLT)val1;
2228     }
2229     p->x = x;
2230     p->val = val;
2231     return OK;
2232  err1:
2233     return csound->InitError(csound, Str("cosseg not initialised (krate)\n"));
2234 }
2235