1 /*
2     fgens.c:
3 
4     Copyright (C) 1991, 1994, 1995, 1998, 2000, 2004
5                   Barry Vercoe, John ffitch, Paris Smaragdis,
6                   Gabriel Maldonado, Richard Karpen, Greg Sullivan,
7                   Pete Moss, Istvan Varga, Victor Lazzarini
8 
9     This file is part of Csound.
10 
11     The Csound Library is free software; you can redistribute it
12     and/or modify it under the terms of the GNU Lesser General Public
13     License as published by the Free Software Foundation; either
14     version 2.1 of the License, or (at your option) any later version.
15 
16     Csound is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU Lesser General Public License for more details.
20 
21     You should have received a copy of the GNU Lesser General Public
22     License along with Csound; if not, write to the Free Software
23     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24     02110-1301 USA
25 */
26 
27 #include "csoundCore.h"         /*                      FGENS.C         */
28 #include <ctype.h>
29 #include "soundio.h"
30 #include "cwindow.h"
31 #include "cmath.h"
32 #include "fgens.h"
33 #include "pstream.h"
34 #include "pvfileio.h"
35 #include <stdlib.h>
36 /* #undef ISSTRCOD */
37 
38 
isstrcod(MYFLT xx)39 int isstrcod(MYFLT xx)
40 {
41 #ifdef USE_DOUBLE
42     union {
43       double d;
44       int32_t i[2];
45     } z;
46     z.d = xx;
47     return ((z.i[1]&0x7ff00000)==0x7ff00000);
48 #else
49     union {
50       float f;
51       int32_t i;
52     } z;
53     z.f = xx;
54     return ((z.i&0x7f800000) == 0x7f800000);
55 #endif
56 }
57 
58 extern double besseli(double);
59 FUNC *csoundFTnp2Findint(CSOUND *csound, MYFLT *argp, int verbose);static int gen01raw(FGDATA *, FUNC *);
60 static int gen01(FGDATA *, FUNC *), gen02(FGDATA *, FUNC *);
61 static int gen03(FGDATA *, FUNC *), gen04(FGDATA *, FUNC *);
62 static int gen05(FGDATA *, FUNC *), gen06(FGDATA *, FUNC *);
63 static int gen07(FGDATA *, FUNC *), gen08(FGDATA *, FUNC *);
64 static int gen09(FGDATA *, FUNC *), gen10(FGDATA *, FUNC *);
65 static int gen11(FGDATA *, FUNC *), gen12(FGDATA *, FUNC *);
66 static int gen13(FGDATA *, FUNC *), gen14(FGDATA *, FUNC *);
67 static int gen15(FGDATA *, FUNC *), gen17(FGDATA *, FUNC *);
68 static int gen18(FGDATA *, FUNC *), gen19(FGDATA *, FUNC *);
69 static int gen20(FGDATA *, FUNC *), gen21(FGDATA *, FUNC *);
70 static int gen23(FGDATA *, FUNC *), gen24(FGDATA *, FUNC *);
71 static int gen16(FGDATA *, FUNC *), gen25(FGDATA *, FUNC *);
72 static int gen27(FGDATA *, FUNC *), gen28(FGDATA *, FUNC *);
73 static int gen30(FGDATA *, FUNC *), gen31(FGDATA *, FUNC *);
74 static int gen32(FGDATA *, FUNC *), gen33(FGDATA *, FUNC *);
75 static int gen34(FGDATA *, FUNC *), gen40(FGDATA *, FUNC *);
76 static int gen41(FGDATA *, FUNC *), gen42(FGDATA *, FUNC *);
77 static int gen43(FGDATA *, FUNC *);
78 static int gn1314(FGDATA *, FUNC *, MYFLT, MYFLT);
79 static int gen51(FGDATA *, FUNC *), gen52(FGDATA *, FUNC *);
80 static int gen53(FGDATA *, FUNC *);
81 static int GENUL(FGDATA *, FUNC *);
82 #ifndef NACL
83 static int gen49(FGDATA *, FUNC *);
84 #endif
85 
86 static const GEN or_sub[GENMAX + 1] = {
87     GENUL,
88     gen01, gen02, gen03, gen04, gen05, gen06, gen07, gen08, gen09, gen10,
89     gen11, gen12, gen13, gen14, gen15, gen16, gen17, gen18, gen19, gen20,
90     gen21, GENUL, gen23, gen24, gen25, GENUL, gen27, gen28, GENUL, gen30,
91     gen31, gen32, gen33, gen34, GENUL, GENUL, GENUL, GENUL, GENUL, gen40,
92     gen41, gen42, gen43, GENUL, GENUL, GENUL, GENUL, GENUL,
93 #ifndef NACL
94     gen49,
95 #else
96     GENUL,
97 #endif
98     GENUL,
99     gen51, gen52, gen53, GENUL, GENUL, GENUL, GENUL, GENUL, GENUL, GENUL
100 };
101 
102 typedef struct namedgen {
103     char    *name;
104     int     genum;
105     struct namedgen *next;
106 } NAMEDGEN;
107 
108 #define tpd360  (FL(0.0174532925199433))
109 
110 #define FTAB_SEARCH_BASE (100)
111 
112 CS_NOINLINE int  fterror(const FGDATA *, const char *, ...);
113 static CS_NOINLINE void ftresdisp(const FGDATA *, FUNC *);
114 static CS_NOINLINE FUNC *ftalloc(const FGDATA *);
115 
GENUL(FGDATA * ff,FUNC * ftp)116 static int GENUL(FGDATA *ff, FUNC *ftp)
117 {
118     (void) ftp;
119     return fterror(ff, Str("unknown GEN number"));
120 }
121 
isPowerOfTwo(unsigned int x)122 static inline unsigned int isPowerOfTwo (unsigned int x) {
123   return (x > 0) && !(x & (x - 1)) ? 1 : 0;
124 }
125 
126 /**
127  * Create ftable using evtblk data, and store pointer to new table in *ftpp.
128  * If mode is zero, a zero table number is ignored, otherwise a new table
129  * number is automatically assigned.
130  * Returns zero on success.
131  */
132 
hfgens(CSOUND * csound,FUNC ** ftpp,const EVTBLK * evtblkp,int mode)133 int hfgens(CSOUND *csound, FUNC **ftpp, const EVTBLK *evtblkp, int mode)
134 {
135     int32    genum, ltest;
136     int     lobits, msg_enabled, i;
137     FUNC    *ftp;
138     FGDATA  ff;
139     int nonpowof2_flag=0; /* gab: fixed for non-powoftwo function tables*/
140 
141     *ftpp = NULL;
142     if (UNLIKELY(csound->gensub == NULL)) {
143       csound->gensub = (GEN*) csound->Malloc(csound, sizeof(GEN) * (GENMAX + 1));
144       memcpy(csound->gensub, or_sub, sizeof(GEN) * (GENMAX + 1));
145       csound->genmax = GENMAX + 1;
146     }
147     msg_enabled = csound->oparms->msglevel & 7;
148     memset(&ff, '\0', sizeof(ff)); /* for Valgrind */
149     ff.csound = csound;
150     memcpy((char*) &(ff.e), (char*) evtblkp,
151            (size_t) ((char*) &(evtblkp->p[2]) - (char*) evtblkp));
152     ff.fno = (int) MYFLT2LRND(ff.e.p[1]);
153     if (!ff.fno) {
154       if (!mode)
155         return 0;                               /*  fno = 0: return,        */
156       ff.fno = FTAB_SEARCH_BASE;
157       do {                                      /*      or automatic number */
158         ++ff.fno;
159       } while (ff.fno <= csound->maxfnum && csound->flist[ff.fno] != NULL);
160       ff.e.p[1] = (MYFLT) (ff.fno);
161     }
162     else if (ff.fno < 0) {                      /*  fno < 0: remove         */
163       ff.fno = -(ff.fno);
164       if (UNLIKELY(ff.fno > csound->maxfnum ||
165                    (ftp = csound->flist[ff.fno]) == NULL)) {
166         return fterror(&ff, Str("ftable does not exist"));
167       }
168       csound->flist[ff.fno] = NULL;
169       csound->Free(csound, (void*) ftp);
170       if (UNLIKELY(msg_enabled))
171         csoundMessage(csound, Str("ftable %d now deleted\n"), ff.fno);
172       return 0;
173     }
174     if (UNLIKELY(ff.fno > csound->maxfnum)) {   /* extend list if necessary */
175       FUNC  **nn;
176       int   size;
177       for (size = csound->maxfnum; size < ff.fno; size += MAXFNUM)
178         ;
179       nn = (FUNC**) csound->ReAlloc(csound,
180                                     csound->flist, (size + 1) * sizeof(FUNC*));
181       csound->flist = nn;
182       for (i = csound->maxfnum + 1; i <= size; i++)
183         csound->flist[i] = NULL;                /*  Clear new section       */
184       csound->maxfnum = size;
185     }
186     if (UNLIKELY(ff.e.pcnt <= 4)) {             /*  chk minimum arg count   */
187       return fterror(&ff, Str("insufficient gen arguments"));
188     }
189     if (UNLIKELY(ff.e.pcnt>PMAX)) {
190       //#ifdef BETA
191       csound->DebugMsg(csound, "T%d/%d(%d): x=%p memcpy from %p to %p length %zu\n",
192               (int)evtblkp->p[1], (int)evtblkp->p[4], ff.e.pcnt, evtblkp->c.extra,
193               &(ff.e.p[2]), &(evtblkp->p[2]), sizeof(MYFLT) * PMAX);
194       //#endif
195       memcpy(&(ff.e.p[2]), &(evtblkp->p[2]), sizeof(MYFLT) * (PMAX-2));
196       ff.e.c.extra =
197         (MYFLT*)csound->Malloc(csound,sizeof(MYFLT) * (evtblkp->c.extra[0]+1));
198       memcpy(ff.e.c.extra, evtblkp->c.extra,
199              sizeof(MYFLT) * (evtblkp->c.extra[0]+1));
200     }
201     else
202       memcpy(&(ff.e.p[2]), &(evtblkp->p[2]),
203              sizeof(MYFLT) * ((int) ff.e.pcnt - 1));
204     if (isstrcod(ff.e.p[4])) {
205       /* A named gen given so search the list of extra gens */
206       NAMEDGEN *n = (NAMEDGEN*) csound->namedgen;
207       while (n) {
208         if (strcmp(n->name, ff.e.strarg) == 0) {    /* Look up by name */
209           ff.e.p[4] = genum = n->genum;
210           break;
211         }
212         n = n->next;                            /*  and round again         */
213       }
214       if (UNLIKELY(n == NULL)) {
215         return fterror(&ff, Str("Named gen \"%s\" not defined"), ff.e.strarg);
216       }
217     }
218     else {
219       genum = (int32) MYFLT2LRND(ff.e.p[4]);
220       if (genum < 0)
221         genum = -genum;
222       if (UNLIKELY(!genum || genum > csound->genmax)) { /*   & legal gen number x*/
223         return fterror(&ff, Str("illegal gen number"));
224       }
225     }
226     ff.flen = (int32) MYFLT2LRND(ff.e.p[3]);
227     if (!ff.flen) {
228       /* defer alloc to gen01|gen23|gen28 */
229       ff.guardreq = 1;
230       if (UNLIKELY(genum != 1 && genum != 2 && genum != 23 &&
231                    genum != 28 && genum != 49 && genum<=GENMAX)) {
232         return fterror(&ff, Str("deferred size for GENs 1, 2, 23, 28 or 49 only"));
233       }
234       if (UNLIKELY(msg_enabled))
235         csoundMessage(csound, Str("ftable %d:\n"), ff.fno);
236       i = (*csound->gensub[genum])(&ff, NULL);
237       ftp = csound->flist[ff.fno];
238       if (i != 0) {
239         csound->flist[ff.fno] = NULL;
240         csound->Free(csound, ftp);
241         return -1;
242       }
243       *ftpp = ftp;
244       return 0;
245     }
246     /* if user flen given */
247     if (ff.flen < 0L || !isPowerOfTwo(ff.flen&~1)) {
248       /* gab for non-pow-of-two-length    */
249       ff.guardreq = 1;
250       if (ff.flen<0) ff.flen = -(ff.flen);             /* gab: fixed */
251       if (!(ff.flen & (ff.flen - 1L)) || ff.flen > MAXLEN)
252         goto powOfTwoLen;
253       lobits = 0;                       /* Hope this is not needed! */
254       nonpowof2_flag = 1; /* gab: fixed for non-powoftwo function tables*/
255     }
256     else {
257       ff.guardreq = ff.flen & 01;       /*  set guard request flg   */
258       ff.flen &= -2L;                   /*  flen now w/o guardpt    */
259  powOfTwoLen:
260       if (UNLIKELY(ff.flen <= 0L || ff.flen > MAXLEN)) {
261         return fterror(&ff, Str("illegal table length"));
262       }
263       for (ltest = ff.flen, lobits = 0;
264            (ltest & MAXLEN) == 0L;
265            lobits++, ltest <<= 1)
266         ;
267       if (UNLIKELY(ltest != MAXLEN)) {  /*  flen is not power-of-2 */
268         // return fterror(&ff, Str("illegal table length"));
269         //csound->Warning(csound, Str("table %d size not power of two"), ff.fno);
270         lobits = 0;
271         nonpowof2_flag = 1;
272         ff.guardreq = 1;
273       }
274     }
275     ftp = ftalloc(&ff);                 /*  alloc ftable space now  */
276     ftp->lenmask  = ((ff.flen & (ff.flen - 1L)) ?
277                      0L : (ff.flen - 1L));      /*  init hdr w powof2 data  */
278     ftp->lobits   = lobits;
279     i = (1 << lobits);
280     ftp->lomask   = (int32) (i - 1);
281     ftp->lodiv    = FL(1.0) / (MYFLT) i;        /*    & other useful vals   */
282     ftp->nchanls  = 1;                          /*    presume mono for now  */
283     ftp->gen01args.sample_rate = csound->esr;  /* set table SR to esr */
284     ftp->flenfrms = ff.flen;
285     if (nonpowof2_flag)
286       ftp->lenmask = 0xFFFFFFFF; /* gab: fixed for non-powoftwo function tables */
287 
288     if (UNLIKELY(msg_enabled))
289       csoundMessage(csound, Str("ftable %d:\n"), ff.fno);
290     if ((*csound->gensub[genum])(&ff, ftp) != 0) {
291       csound->flist[ff.fno] = NULL;
292       csound->Free(csound, ftp);
293       return -1;
294     }
295     /* VL 11.01.05 for deferred GEN01, it's called in gen01raw */
296     ftresdisp(&ff, ftp);                        /* rescale and display      */
297     *ftpp = ftp;
298     /* keep original arguments, from GEN number  */
299     ftp->argcnt = ff.e.pcnt - 3;
300     {  /* Note this does not handle extended args -- JPff */
301       int size=ftp->argcnt;
302       if (UNLIKELY(size>PMAX-4)) size=PMAX-4;
303       /* printf("size = %d -> %d ftp->args = %p\n", */
304       /*        size, sizeof(MYFLT)*size, ftp->args); */
305       memcpy(ftp->args, &(ff.e.p[4]), sizeof(MYFLT)*size); /* is this right? */
306       /*for (k=0; k < size; k++)
307         csound->Message(csound, "%f\n", ftp->args[k]);*/
308     }
309     return 0;
310 }
311 
312 /**
313  * Allocates space for 'tableNum' with a length (not including the guard
314  * point) of 'len' samples. The table data is not cleared to zero.
315  * Return value is zero on success.
316  */
317 
csoundFTAlloc(CSOUND * csound,int tableNum,int len)318 int csoundFTAlloc(CSOUND *csound, int tableNum, int len)
319 {
320     int   i, size;
321     FUNC  **nn, *ftp;
322 
323     if (UNLIKELY(tableNum <= 0 || len <= 0 || len > (int) MAXLEN))
324       return -1;
325     if (UNLIKELY(tableNum > csound->maxfnum)) { /* extend list if necessary     */
326       for (size = csound->maxfnum; size < tableNum; size += MAXFNUM)
327         ;
328       nn = (FUNC**) csound->ReAlloc(csound,
329                                     csound->flist, (size + 1) * sizeof(FUNC*));
330       csound->flist = nn;
331       for (i = csound->maxfnum + 1; i <= size; i++)
332         csound->flist[i] = NULL;            /* Clear new section            */
333       csound->maxfnum = size;
334     }
335     /* allocate space for table */
336     size = (int) (len * (int) sizeof(MYFLT));
337     ftp = csound->flist[tableNum];
338     if (ftp == NULL) {
339       csound->flist[tableNum] = (FUNC*) csound->Malloc(csound, sizeof(FUNC));
340       csound->flist[tableNum]->ftable =
341         (MYFLT*)csound->Malloc(csound, sizeof(MYFLT)*(len+1));
342     }
343     else if (len != (int) ftp->flen) {
344       if (UNLIKELY(csound->actanchor.nxtact != NULL)) { /*   & chk for danger    */
345         /* return */  /* VL: changed this into a Warning */
346           csound->Warning(csound, Str("ftable %d relocating due to size change"
347                                         "\n         currently active instruments "
348                                         "may find this disturbing"), tableNum);
349       }
350       csound->flist[tableNum] = NULL;
351       csound->Free(csound, ftp);
352       csound->flist[tableNum] = (FUNC*) csound->Malloc(csound, (size_t) size);
353     }
354     /* initialise table header */
355     ftp = csound->flist[tableNum];
356     //memset((void*) ftp, 0, (size_t) ((char*) &(ftp->ftable) - (char*) ftp));
357     ftp->flen = (int32) len;
358     if (!(len & (len - 1))) {
359       /* for power of two length: */
360       ftp->lenmask = (int32) (len - 1);
361       for (i = len, ftp->lobits = 0L; i < (int) MAXLEN; ftp->lobits++, i <<= 1)
362         ;
363       i = (int) MAXLEN / len;
364       ftp->lomask = (int32) (i - 1);
365       ftp->lodiv = FL(1.0) / (MYFLT) i;
366     }
367     ftp->flenfrms = (int32) len;
368     ftp->nchanls = 1L;
369     ftp->fno = (int32) tableNum;
370 
371     return 0;
372 }
373 
374 /**
375  * Deletes a function table.
376  * Return value is zero on success.
377  */
378 
csoundFTDelete(CSOUND * csound,int tableNum)379 int csoundFTDelete(CSOUND *csound, int tableNum)
380 {
381     FUNC  *ftp;
382 
383     if (UNLIKELY((unsigned int) (tableNum - 1) >= (unsigned int) csound->maxfnum))
384       return -1;
385     ftp = csound->flist[tableNum];
386     if (UNLIKELY(ftp == NULL))
387       return -1;
388     csound->flist[tableNum] = NULL;
389     csound->Free(csound, ftp);
390 
391     return 0;
392 }
393 
394 /* read ftable values directly from p-args */
395 
gen02(FGDATA * ff,FUNC * ftp)396 static int gen02(FGDATA *ff, FUNC *ftp)
397 {
398     MYFLT   *fp, *pp = &(ff->e.p[5]);
399     int     nvals = ff->e.pcnt - 4;
400     int nsw = 1;
401     CSOUND  *csound = ff->csound;
402 
403     if (UNLIKELY(ff->e.pcnt>=PMAX))
404       csound->Warning(csound, Str("using extended arguments\n"));
405     if (ff->flen==0) {
406       ff->flen = nvals;
407       ftp = ftalloc(ff);
408     }
409     else if (nvals >= (int) ff->flen)
410       nvals = (int) ff->flen + 1;               /* for all vals up to flen+1 */
411     fp = ftp->ftable;
412     while (nvals--) {
413       *fp++ = *pp++;                            /*   copy into ftable   */
414       if (UNLIKELY(nsw && pp>&ff->e.p[PMAX])) {
415 #ifdef BETA
416         csound->DebugMsg(csound, "Switch to extra args\n");
417 #endif
418         nsw = 0;                /* only switch once */
419         pp = &(ff->e.c.extra[1]);
420       }
421     }
422     return OK;
423 }
424 
gen03(FGDATA * ff,FUNC * ftp)425 static int gen03(FGDATA *ff, FUNC *ftp)
426 {
427     int     ncoefs, nargs = ff->e.pcnt - 4;
428     MYFLT   xintvl, xscale;
429     int     xloc, nlocs;
430     MYFLT   *fp = ftp->ftable, x, sum, *coefp, *coef0, *coeflim;
431 
432     if (UNLIKELY((ncoefs = nargs - 2) <= 0)) {
433       return fterror(ff, Str("no coefs present"));
434     }
435     coef0 = &ff->e.p[7];
436     coeflim = coef0 + ncoefs;
437     if (UNLIKELY((xintvl = ff->e.p[6] - ff->e.p[5]) <= 0)) {
438       return fterror(ff, Str("illegal x interval"));
439     }
440     xscale = xintvl / (MYFLT)ff->flen;
441     xloc = (int) (ff->e.p[5] / xscale);        /* initial xloc */
442     nlocs = (int) ff->flen + 1;
443     do {                                       /* for each loc:        */
444       x     = xloc++ * xscale;
445       coefp = coeflim;
446       sum   = *--coefp;                        /* init sum to coef(n)  */
447       while (coefp > coef0) {
448         sum *= x;                              /*  & accum by Horner's rule */
449         sum += *--coefp;
450       }
451       *fp++ = sum;
452     } while (--nlocs);
453 
454     return OK;
455 }
456 
gen04(FGDATA * ff,FUNC * ftp)457 static int gen04(FGDATA *ff, FUNC *ftp)
458 {
459     CSOUND  *csound = ff->csound;
460     MYFLT   *valp, *rvalp, *fp = ftp->ftable;
461     int     n, r;
462     FUNC    *srcftp;
463     MYFLT   val, max, maxinv;
464     int     srcno, srcpts, ptratio;
465 
466     if (UNLIKELY(ff->e.pcnt < 6)) {
467       return fterror(ff, Str("insufficient arguments"));
468     }
469     if (UNLIKELY((srcno = (int)ff->e.p[5]) <= 0 || srcno > csound->maxfnum ||
470                  (srcftp = csound->flist[srcno]) == NULL)) {
471       return fterror(ff, Str("unknown srctable number"));
472     }
473     if (!ff->e.p[6]) {
474       srcpts = srcftp->flen;
475       valp   = srcftp->ftable;
476       rvalp  = NULL;
477     }
478     else {
479       srcpts = srcftp->flen >>1;
480       valp   = &srcftp->ftable[srcpts];
481       rvalp  = valp - 1;
482     }
483     if (UNLIKELY((ptratio = srcpts / ff->flen) < 1)) {
484       return fterror(ff, Str("table size too large"));
485     }
486     if ((val = *valp++)) {
487       if (val < FL(0.0))      val = -val;
488       max = val;
489       maxinv = FL(1.0) / max;
490     }
491     else {
492       max = FL(0.0);
493       maxinv = FL(1.0);
494     }
495     *fp++ = maxinv;
496     for (n = ff->flen; n--; ) {
497       for (r = ptratio; r--; ) {
498         if ((val = *valp++)) {
499           if (val < FL(0.0)) val = -val;
500           if (val > max) {
501             max = val;
502             maxinv = FL(1.0) / max;
503           }
504         }
505         if (rvalp != NULL && (val = *rvalp--)) {
506           if (val < 0.)   val = -val;
507           if (val > max) {
508             max = val;
509             maxinv = FL(1.0) / max;
510           }
511         }
512       }
513       *fp++ = maxinv;
514     }
515     ff->guardreq = 1;                  /* disable new guard point */
516     ff->e.p[4] = -FL(4.0);             /*   and rescaling         */
517 
518     return OK;
519 }
520 
gen05(FGDATA * ff,FUNC * ftp)521 static int gen05(FGDATA *ff, FUNC *ftp)
522 {
523     int     nsegs, seglen;
524     MYFLT   *valp, *fp, *finp;
525     MYFLT   amp1, mult;
526     int nsw = 1;
527     CSOUND  *csound = ff->csound;
528 
529     if (UNLIKELY(ff->e.pcnt>=PMAX))
530       csound->Warning(csound, Str("using extended arguments\n"));
531     if ((nsegs = (ff->e.pcnt-5) >> 1) <= 0)    /* nsegs = nargs-1 /2 */
532       return OK;
533     valp = &ff->e.p[5];
534     fp = ftp->ftable;
535     finp = fp + ff->flen;
536     if (UNLIKELY(*valp == 0)) goto gn5er2;
537     do {
538       amp1 = *valp++;
539       if (UNLIKELY(nsw && valp>&ff->e.p[PMAX])) {
540         valp = &(ff->e.c.extra[1]);
541         nsw  = 0;
542       }
543       if (!(seglen = (int)*valp++)) {
544         if (UNLIKELY(nsw && valp>&ff->e.p[PMAX])) {
545           valp = &(ff->e.c.extra[1]);
546           nsw  = 0;
547         }
548         continue;
549       }
550       if (UNLIKELY(nsw && valp>&ff->e.p[PMAX])) {
551         valp = &(ff->e.c.extra[1]);
552         nsw  = 0;
553       }
554       if (UNLIKELY(seglen < 0)) goto gn5er1;
555       if (UNLIKELY((mult = *valp/amp1) <= 0)) goto gn5er2;
556       mult = POWER(mult, FL(1.0)/seglen);
557       while (seglen--) {
558         *fp++ = amp1;
559         amp1 *= mult;
560         if (fp > finp)
561           return OK;
562       }
563     } while (--nsegs);
564     if (fp == finp)                 /* if 2**n pnts, add guardpt */
565       *fp = amp1;
566     return OK;
567 
568  gn5er1:
569     return fterror(ff, Str("gen call has negative segment size:"));
570  gn5er2:
571     return fterror(ff, Str("illegal input vals for gen call, beginning:"));
572 }
573 
gen07(FGDATA * ff,FUNC * ftp)574 static int gen07(FGDATA *ff, FUNC *ftp)
575 {
576     int     nsegs, seglen;
577     MYFLT   *valp, *fp, *finp;
578     MYFLT   amp1, incr;
579 
580     if ((nsegs = (ff->e.pcnt-5) >> 1) <= 0)         /* nsegs = nargs-1 /2 */
581       return OK;
582     valp = &ff->e.p[5];
583     fp = ftp->ftable;
584     finp = fp + ff->flen;
585     do {
586       amp1 = *valp++;
587       if (!(seglen = (int)*valp++)) continue;
588       if (UNLIKELY(seglen < 0)) goto gn7err;
589       incr = (*valp - amp1) / seglen;
590       while (seglen--) {
591         *fp++ = amp1;
592         amp1 += incr;
593         if (fp > finp)
594           return OK;
595       }
596     } while (--nsegs);
597     if (fp == finp)                 /* if 2**n pnts, add guardpt */
598       *fp = amp1;
599     return OK;
600 
601  gn7err:
602     return fterror(ff, Str("gen call has negative segment size:"));
603 }
604 
gen06(FGDATA * ff,FUNC * ftp)605 static int gen06(FGDATA *ff, FUNC *ftp)
606 {
607     MYFLT   *segp, *extremp, *inflexp, *segptsp, *fp, *finp;
608     MYFLT   y, diff2;
609     int     pntno, pntinc, nsegs, npts;
610     int nsw = 1;
611     CSOUND  *csound = ff->csound;
612 
613     if (UNLIKELY(ff->e.pcnt>=PMAX))
614       csound->Warning(csound, Str("using extended arguments\n"));
615     if (UNLIKELY((nsegs = ((ff->e.pcnt - 5) >> 1)) < 1)) {
616       return fterror(ff, Str("insufficient arguments"));
617     }
618     fp = ftp->ftable;
619     finp = fp + ff->flen;
620     pntinc = 1;
621     for (segp = &ff->e.p[3], segptsp = &ff->e.p[4]; nsegs > 0; nsegs--) {
622       segp += 1;
623       if (UNLIKELY(nsw && segp>&ff->e.p[PMAX])) {
624           segp = &(ff->e.c.extra[1]);
625           nsw  = 0;
626         }
627       segp += 1;
628       if (UNLIKELY(nsw && segp>&ff->e.p[PMAX])) {
629           segp = &(ff->e.c.extra[1]);
630           nsw  = 0;
631         }
632       segptsp = segp + 1;
633       if (UNLIKELY(nsw && segptsp>&ff->e.p[PMAX])) {
634           segptsp = &(ff->e.c.extra[1]);
635         }
636       if (UNLIKELY((npts = (int)*segptsp) < 0)) {
637         return fterror(ff, Str("negative segsiz"));
638       }
639       if (pntinc > 0) {
640         pntno   = 0;
641         inflexp = segp + 1;
642         if (UNLIKELY(nsw && inflexp>&ff->e.p[PMAX])) {
643           inflexp = &(ff->e.c.extra[1]);
644         }
645         inflexp++;
646         if (UNLIKELY(nsw && inflexp>&ff->e.p[PMAX])) {
647           inflexp = &(ff->e.c.extra[1]);
648         }
649         extremp = segp;
650       }
651       else {
652         pntno   = npts;
653         inflexp = segp;
654         extremp = segp + 1;
655         if (UNLIKELY(nsw && extremp>&ff->e.p[PMAX])) {
656           extremp = &(ff->e.c.extra[1]);
657         }
658         extremp++;
659         if (UNLIKELY(nsw && extremp>&ff->e.p[PMAX])) {
660           extremp = &(ff->e.c.extra[1]);
661         }
662       }
663       diff2 = (*inflexp - *extremp) * FL(0.5);
664       for ( ; npts > 0 && fp < finp; pntno += pntinc, npts--) {
665         y = (MYFLT)pntno / *segptsp;
666         *fp++ = (FL(3.0)-y) * y * y * diff2 + *extremp;
667       }
668       pntinc = -pntinc;
669     }
670     segp += 1;
671     if (UNLIKELY(nsw && segp>&ff->e.p[PMAX])) {
672       segp = &(ff->e.c.extra[1]);
673       nsw  = 0;
674     }
675     segp += 1;
676     if (UNLIKELY(nsw && segp>&ff->e.p[PMAX])) {
677       segp = &(ff->e.c.extra[1]);
678       nsw  = 0;
679     }
680     *fp = *(segp);                      /* write last target point */
681 
682     return OK;
683 }
684 
gen08(FGDATA * ff,FUNC * ftp)685 static int gen08(FGDATA *ff, FUNC *ftp)
686 {
687     MYFLT   R, x, c3, c2, c1, c0, *fp, *fplim, *valp;
688     MYFLT   f2 = FL(0.0), f1, f0, df1, df0, dx01, dx12 = FL(0.0), curx;
689     MYFLT   slope, resd1, resd0;
690     int     nsegs, npts;
691     CSOUND  *csound = ff->csound;
692     int nsw = 1;
693 
694     if (UNLIKELY(ff->e.pcnt>=PMAX))
695       csound->Warning(csound, Str("using extended arguments\n"));
696     if (UNLIKELY((nsegs = (ff->e.pcnt - 5) >> 1) <= 0)) {
697       return fterror(ff, Str("insufficient arguments"));
698     }
699     valp = &ff->e.p[5];
700     fp = ftp->ftable;
701     fplim = fp + ff->flen;
702     f0 = *valp++;                    /* 1st 3 params give vals at x0, x1 */
703     if (UNLIKELY((dx01 = *valp++) <= FL(0.0))) {      /* and dist between*/
704       return fterror(ff, Str("illegal x interval"));
705     }
706     f1 = *valp++;
707     curx = df0 = FL(0.0);           /* init x to origin; slope at x0 = 0 */
708     do {                            /* for each spline segmnt (x0 to x1) */
709       if (nsegs > 1) {                      /* if another seg to follow  */
710         MYFLT dx02;
711         if (UNLIKELY((dx12 = *valp++) <= FL(0.0))) {  /*  read its distance  */
712           return fterror(ff, Str("illegal x interval"));
713         }
714         f2 = *valp++;                       /*    and the value at x2    */
715         if (UNLIKELY(UNLIKELY(nsw && valp>&ff->e.p[PMAX]))) {
716 #ifdef BETA
717           csound->DebugMsg(csound, "Switch to extra args\n");
718 #endif
719           nsw = 0;                /* only switch once */
720           valp = &(ff->e.c.extra[1]);
721         }
722         dx02 = dx01 + dx12;
723         df1 = ( f2*dx01*dx01 + f1*(dx12-dx01)*dx02 - f0*dx12*dx12 )
724           / (dx01*dx02*dx12);
725       }                                /* df1 is slope of parabola at x1 */
726       else df1 = FL(0.0);
727       if ((npts = (int) (dx01 - curx)) > fplim - fp)
728         npts = fplim - fp;
729       if (npts > 0) {                       /* for non-trivial segment: */
730         slope = (f1 - f0) / dx01;           /*   get slope x0 to x1     */
731         resd0 = df0 - slope;                /*   then residual slope    */
732         resd1 = df1 - slope;                /*     at x0 and x1         */
733         c3 = (resd0 + resd1) / (dx01*dx01);
734         c2 = - (resd1 + FL(2.0)*resd0) / dx01;
735         c1 = df0;                           /*   and calc cubic coefs   */
736         c0 = f0;
737         for (x = curx; npts>0; --npts, x += FL(1.0)) {
738           R     = c3;
739           R    *= x;
740           R    += c2;            /* f(x) = ((c3 x + c2) x + c1) x + c0  */
741           R    *= x;
742           R    += c1;
743           R    *= x;
744           R    += c0;
745           *fp++ = R;                        /* store n pts for this seg */
746         }
747         curx = x;
748       }
749       curx -= dx01;                 /* back up x by length last segment */
750       dx01  = dx12;                     /* relocate to the next segment */
751       f0    = f1;                       /*   by assuming its parameters */
752       f1    = f2;
753       df0   = df1;
754     } while (--nsegs && fp<fplim);      /* loop for remaining segments  */
755     while (fp <= fplim)
756       *fp++ = f0;                       /* & repeat the last value      */
757     return OK;
758 }
759 
gen09(FGDATA * ff,FUNC * ftp)760 static int gen09(FGDATA *ff, FUNC *ftp)
761 {
762     int     hcnt;
763     MYFLT   *valp, *fp, *finp;
764     double  phs, inc, amp;
765     double  tpdlen = TWOPI / (double) ff->flen;
766     CSOUND  *csound = ff->csound;
767     int nsw = 1;
768 
769     if (UNLIKELY(ff->e.pcnt>=PMAX))
770       csound->Warning(csound, Str("using extended arguments\n"));
771     if ((hcnt = (ff->e.pcnt - 4) / 3) <= 0)         /* hcnt = nargs / 3 */
772       return OK;
773     valp = &ff->e.p[5];
774     finp = &ftp->ftable[ff->flen];
775     do {
776       inc = *(valp++) * tpdlen;
777       if (UNLIKELY(nsw && valp>&ff->e.p[PMAX])) {
778 #ifdef BETA
779         csound->DebugMsg(csound, "Switch to extra args\n");
780 #endif
781         nsw = 0;                /* only switch once */
782         valp = &(ff->e.c.extra[1]);
783       }
784       amp = *(valp++);
785       if (UNLIKELY(nsw && valp>&ff->e.p[PMAX])) {
786 #ifdef BETA
787         csound->DebugMsg(csound, "Switch to extra args\n");
788 #endif
789         nsw = 0;                /* only switch once */
790         valp = &(ff->e.c.extra[1]);
791       }
792       phs = *(valp++) * tpd360;
793       if (UNLIKELY(nsw && valp>&ff->e.p[PMAX])) {
794 #ifdef BETA
795         csound->DebugMsg(csound, "Switch to extra args\n");
796 #endif
797         nsw = 0;                /* only switch once */
798         valp = &(ff->e.c.extra[1]);
799       }
800       for (fp = ftp->ftable; fp <= finp; fp++) {
801         *fp += (MYFLT) (sin(phs) * amp);
802         if (UNLIKELY((phs += inc) >= TWOPI))
803           phs -= TWOPI;
804       }
805     } while (--hcnt);
806 
807     return OK;
808 }
809 
gen10(FGDATA * ff,FUNC * ftp)810 static int gen10(FGDATA *ff, FUNC *ftp)
811 {
812     int32   phs, hcnt;
813     MYFLT   amp, *fp, *finp;
814     int32   flen = ff->flen;
815     double  tpdlen = TWOPI / (double) flen;
816     CSOUND  *csound = ff->csound;
817 
818     if (UNLIKELY(ff->e.pcnt>=PMAX))
819       csound->Warning(csound, Str("using extended arguments\n"));
820     hcnt = ff->e.pcnt - 4;                              /* hcnt is nargs    */
821     finp = &ftp->ftable[flen];
822     do {
823       MYFLT *valp = (hcnt+4>=PMAX ? &ff->e.c.extra[hcnt+5-PMAX] :
824                                     &ff->e.p[hcnt + 4]);
825       if ((amp = *valp) != FL(0.0))         /* for non-0 amps,  */
826         for (phs = 0, fp = ftp->ftable; fp <= finp; fp++) {
827           *fp += (MYFLT) sin(phs * tpdlen) * amp;         /* accum sin pts    */
828           phs += hcnt;                                    /* phsinc is hno    */
829           phs %= flen;
830         }
831     } while (--hcnt);
832 
833     return OK;
834 }
835 
gen11(FGDATA * ff,FUNC * ftp)836 static int gen11(FGDATA *ff, FUNC *ftp)
837 {
838     MYFLT   *fp, *finp;
839     int32    phs;
840     double  x;
841     MYFLT   denom, r, scale;
842     int     n, k;
843     int     nargs = ff->e.pcnt - 4;
844 
845     if (UNLIKELY((n = (int) ff->e.p[5]) < 1)) {
846       return fterror(ff, Str("nh partials < 1"));
847     }
848     k = 1;
849     r = FL(1.0);
850     if (ff->e.pcnt > 5)
851       k = (int) ff->e.p[6];
852     if (nargs > 2)
853       r = ff->e.p[7];
854     fp = ftp->ftable;
855     finp = fp + ff->flen;
856     if (ff->e.pcnt == 5 || (k == 1 && r == FL(1.0))) {  /* simple "buzz" case */
857       int tnp1;
858       MYFLT pdlen;
859 
860       tnp1  = (n << 1) + 1;
861       scale = FL(0.5) / n;
862       pdlen = PI_F / (MYFLT) ff->flen;
863       for (phs = 0; fp <= finp; phs++) {
864         x = phs * pdlen;
865         denom = sin(x);
866         if (fabs(denom)<1.0e-10) //(!(denom = (MYFLT) sin(x)))
867           *fp++ = FL(1.0);
868         else *fp++ = ((MYFLT) sin(tnp1 * x) / denom - FL(1.0)) * scale;
869       }
870     }
871     else {                                   /* complex "gbuzz" case */
872       double  tpdlen = TWOPI / (double) ff->flen;
873       MYFLT   numer, twor, rsqp1, rtn, rtnp1, absr;
874       int     km1, kpn, kpnm1;
875 
876       km1   = k - 1;
877       kpn   = k + n;
878       kpnm1 = kpn - 1;
879       twor  = r * FL(2.0);
880       rsqp1 = r * r + FL(1.0);
881       rtn   = intpow(r, (int32) n);
882       rtnp1 = rtn * r;
883       if ((absr =  FABS(r)) > FL(0.999) && absr < FL(1.001))
884         scale = FL(1.0) / n;
885       else scale = (FL(1.0) - absr) / (FL(1.0) - FABS(rtn));
886       for (phs = 0; fp <= finp; phs++) {
887         x = (double) phs * tpdlen;
888         numer = (MYFLT)cos(x*k) - r * (MYFLT)cos(x*km1) - rtn*(MYFLT)cos(x*kpn)
889                 + rtnp1 * (MYFLT)cos(x*kpnm1);
890         if ((denom = rsqp1 - twor * (MYFLT) cos(x)) > FL(0.0001)
891             || denom < -FL(0.0001))
892           *fp++ = numer / denom * scale;
893         else *fp++ = FL(1.0);
894       }
895     }
896     return OK;
897 }
898 
gen12(FGDATA * ff,FUNC * ftp)899 static int gen12(FGDATA *ff, FUNC *ftp)
900 {
901     static const double coefs[] = { 3.5156229, 3.0899424, 1.2067492,
902                                     0.2659732, 0.0360768, 0.0045813 };
903     const double *coefp, *cplim = coefs + 6;
904     double  sum, tsquare, evenpowr;
905     int     n;
906     MYFLT   *fp;
907     double  xscale;
908 
909     xscale = (double) ff->e.p[5] / ff->flen / 3.75;
910     for (n = 0, fp = ftp->ftable; n <= ff->flen; n++) {
911       tsquare  = (double) n * xscale;
912       tsquare *= tsquare;
913       for (sum = evenpowr = 1.0, coefp = coefs; coefp < cplim; coefp++) {
914         evenpowr *= tsquare;
915         sum += *coefp * evenpowr;
916       }
917       *fp++ = (MYFLT) log(sum);
918     }
919     return OK;
920 }
921 
gen13(FGDATA * ff,FUNC * ftp)922 static int gen13(FGDATA *ff, FUNC *ftp)
923 {
924     return gn1314(ff, ftp, FL(2.0), FL(0.5));
925 }
926 
gen14(FGDATA * ff,FUNC * ftp)927 static int gen14(FGDATA *ff, FUNC *ftp)
928 {
929     return gn1314(ff, ftp, FL(1.0), FL(1.0));
930 }
931 
gn1314(FGDATA * ff,FUNC * ftp,MYFLT mxval,MYFLT mxscal)932 static int gn1314(FGDATA *ff, FUNC *ftp, MYFLT mxval, MYFLT mxscal)
933 {
934     CSOUND  *csound = ff->csound;
935     int32    nh, nn;
936     MYFLT   *mp, *mspace, *hp, *oddhp;
937     MYFLT   xamp, xintvl, scalfac, sum, prvm;
938     int nsw = 1;
939 
940     if (UNLIKELY(ff->e.pcnt>=PMAX))
941       csound->Warning(csound, Str("using extended arguments\n"));
942     if (UNLIKELY((nh = ff->e.pcnt - 6) <= 0)) {
943       return fterror(ff, Str("insufficient arguments"));
944     }
945     if (UNLIKELY((xintvl = ff->e.p[5]) <= 0)) {
946       return fterror(ff, Str("illegal xint value"));
947     }
948     if (UNLIKELY((xamp = ff->e.p[6]) <= 0)) {
949       return fterror(ff, Str("illegal xamp value"));
950     }
951     ff->e.p[5] = -xintvl;
952     ff->e.p[6] = xintvl;
953     nn = nh * sizeof(MYFLT) / 2;              /* alloc spc for terms 3,5,7,..*/
954     mp = mspace =
955       (MYFLT *) csound->Calloc(csound, nn);     /* of 1st row of matrix, and */
956     for (nn = (nh + 1) >>1; --nn; )             /* form array of non-0 terms */
957       *mp++ = mxval = -mxval;                   /*  -val, val, -val, val ... */
958     scalfac = 2 / xamp;
959     hp = &ff->e.p[7];                           /* beginning with given h0,  */
960     do {
961       mp = mspace;
962       oddhp = hp;
963       sum = *oddhp++;                           /* sum = diag(=1) * this h   */
964       if (UNLIKELY(nsw && oddhp>&ff->e.p[PMAX])) {
965 #ifdef BETA
966         csound->DebugMsg(csound, "Switch to extra args\n");
967 #endif
968         nsw = 0;                /* only switch once */
969         oddhp = &(ff->e.c.extra[1]);
970       }
971       for (nn = (nh+1) >>1; --nn; ) {
972         int nnsw = nsw;
973         oddhp++;                                /*  + odd terms * h+2,h+4,.. */
974         if (UNLIKELY(nnsw && oddhp>&ff->e.p[PMAX])) {
975 #ifdef BETA
976           csound->DebugMsg(csound, "Switch to extra args\n");
977 #endif
978           nnsw = 0;                /* only switch once */
979           oddhp = &(ff->e.c.extra[1]);
980         }
981         sum += *mp++ * *oddhp++;
982         if (UNLIKELY(nnsw && oddhp>&ff->e.p[PMAX])) {
983 #ifdef BETA
984           csound->DebugMsg(csound, "Switch to extra args\n");
985 #endif
986           nnsw = 0;                /* only switch once */
987           oddhp = &(ff->e.c.extra[1]);
988         }
989       }
990       *hp++ = sum * mxscal;                     /* repl this h w. coef (sum) */
991       if (UNLIKELY(nsw && hp>&ff->e.p[PMAX])) {
992 #ifdef BETA
993         csound->DebugMsg(csound, "Switch to extra args\n");
994 #endif
995         nsw = 0;                /* only switch once */
996         hp = &(ff->e.c.extra[1]);
997       }
998       mp    = mspace;
999       prvm  = FL(1.0);
1000       for (nn = nh>>1; --nn > 0; mp++)          /* calc nxt row matrix terms */
1001         *mp = prvm = *mp - prvm;
1002       mxscal *= scalfac;
1003     } while (--nh);                             /* loop til all h's replaced */
1004     csound->Free(csound,mspace);
1005     return gen03(ff, ftp);                      /* then call gen03 to write */
1006 }
1007 
gen15(FGDATA * ff,FUNC * ftp)1008 static int gen15(FGDATA *ff, FUNC *ftp)
1009 {
1010     MYFLT   xint, xamp, *hsin, h, angle;
1011     MYFLT   *fp, *cosp, *sinp;
1012     int     n, nh;
1013     void    *lp13;
1014     int     nargs = ff->e.pcnt - 4;
1015     CSOUND  *csound = ff->csound;
1016     int nsw = 1;
1017 
1018     if (UNLIKELY(ff->e.pcnt>=PMAX))
1019       csound->Warning(csound, Str("using extended arguments\n"));
1020     if (UNLIKELY(nargs & 01)) {
1021       return fterror(ff, Str("uneven number of args"));
1022     }
1023     hsin = (MYFLT*)csound->Malloc(csound,sizeof(MYFLT)*((1+ff->e.pcnt)/2));
1024     nh = (nargs - 2) >>1;
1025     fp   = &ff->e.p[5];                         /* save p5, p6  */
1026     xint = *fp++;
1027     xamp = *fp++;
1028     for (n = nh, cosp = fp, sinp = hsin; n > 0; n--) {
1029       h = *fp++;                                /* rpl h,angle pairs */
1030       if (UNLIKELY(nsw && fp>&ff->e.p[PMAX])) {
1031 #ifdef BETA
1032         csound->DebugMsg(csound, "Switch to extra args\n");
1033 #endif
1034         nsw = 0;                /* only switch once */
1035         fp = &(ff->e.c.extra[1]);
1036       }
1037       angle = (MYFLT) (*fp++ * tpd360);
1038       *cosp++ = h * COS(angle);  /* with h cos angle */
1039       *sinp++ = h * SIN(angle);  /* and save the sine */
1040     }
1041     nargs -= nh;
1042     ff->e.pcnt = (int16)(nargs + 4);            /* added by F. Pinot 16-01-2012 */
1043     if (UNLIKELY(gen13(ff, ftp) != OK)) {       /* call gen13   */
1044       csound->Free(csound,hsin);
1045       return NOTOK;
1046     }
1047     lp13 = (void*) ftp;
1048     ff->fno++;                                  /* alloc eq. space for fno+1 */
1049     ftp = ftalloc(ff);                          /* & copy header */
1050     memcpy((void*) ftp, lp13, (size_t) sizeof(FUNC)-sizeof(MYFLT*));
1051     ftp->fno = (int32) ff->fno;
1052     fp    = &ff->e.p[5];
1053     nsw = 1;
1054     *fp++ = xint;                               /* restore p5, p6,   */
1055     *fp++ = xamp;
1056     for (n = nh-1, sinp = hsin+1; n > 0; n--) { /* then skip h0*sin  */
1057       *fp++ = *sinp++;                          /* & copy rem hn*sin */
1058       if (UNLIKELY(nsw && fp>&ff->e.p[PMAX])) {
1059 #ifdef BETA
1060         csound->DebugMsg(csound, "Switch to extra args\n");
1061 #endif
1062         nsw = 0;                /* only switch once */
1063         fp = &(ff->e.c.extra[1]);
1064       }
1065     }
1066     nargs--;
1067     ff->e.pcnt = (int16)(nargs + 4); /* added by F. Pinot 16-01-2012 */
1068     csound->Free(csound,hsin);
1069     n = gen14(ff, ftp);       /* now draw ftable   */
1070     ftresdisp(ff, ftp);       /* added by F. Pinot 16-01-2012 */
1071     ff->fno--;                /* F. Pinot, the first function table */
1072                               /* is scaled and displayed by hfgens */
1073     return n;
1074 }
1075 
gen16(FGDATA * ff,FUNC * ftp)1076 static int gen16(FGDATA *ff, FUNC *ftp)
1077 {
1078     MYFLT   *fp, *valp, val;
1079     int     nargs = ff->e.pcnt - 4;
1080     int     nseg = nargs / 3;
1081     int remaining;
1082 
1083     fp = ftp->ftable;
1084     remaining = ff->e.p[3];
1085     valp = &ff->e.p[5];
1086     *fp++ = val = *valp++;
1087     while (nseg-- > 0) {
1088       MYFLT dur    = *valp++;
1089       MYFLT alpha  = *valp++;
1090       MYFLT nxtval = *valp++;
1091       int32 cnt = (int32) (dur + FL(0.5));
1092       if (alpha == FL(0.0)) {
1093         MYFLT c1 = (nxtval-val)/dur;
1094         while (cnt-- > 0) {
1095           if (--remaining<=0) break;
1096           *fp++ = val = val + c1;
1097         }
1098       }
1099       else {
1100         MYFLT c1 = (nxtval - val)/(FL(1.0) - EXP(alpha));
1101         MYFLT x;
1102         alpha /= dur;
1103         x = alpha;
1104         while (cnt-->0) {
1105           if (--remaining<=0) break;
1106           *fp++ = val + c1 * (FL(1.0) - EXP(x));
1107           x += alpha;
1108         }
1109         val = *(fp-1);
1110       }
1111     }
1112     return OK;
1113 }
1114 
gen17(FGDATA * ff,FUNC * ftp)1115 static int gen17(FGDATA *ff, FUNC *ftp)
1116 {
1117     int     nsegs, ndx, nxtndx;
1118     MYFLT   *valp, *fp, *finp;
1119     MYFLT   val;
1120     int     nargs = ff->e.pcnt - 4;
1121     CSOUND  *csound = ff->csound;
1122     int nsw = 1;
1123 
1124     if (UNLIKELY(ff->e.pcnt>=PMAX))
1125       csound->Warning(csound, Str("using extended arguments\n"));
1126     if ((nsegs = nargs >> 1) <= 0)       /* nsegs = nargs /2 */
1127       goto gn17err;
1128     valp = &ff->e.p[5];
1129     fp = ftp->ftable;
1130     finp = fp + ff->flen;
1131     if (UNLIKELY((ndx = (int)*valp++) != 0))
1132       goto gn17err;
1133     while (--nsegs) {
1134       val = *valp++;
1135       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
1136         nsw =0, valp = &(ff->e.c.extra[1]);
1137       if (UNLIKELY((nxtndx = (int)*valp++) <= ndx))
1138         goto gn17err;
1139       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
1140         nsw =0, valp = &(ff->e.c.extra[1]);
1141       do {
1142         *fp++ = val;
1143         if (fp > finp)
1144           return OK;
1145       } while (++ndx < nxtndx);
1146     }
1147     val = *valp;
1148     while (fp <= finp)                    /* include 2**n + 1 guardpt */
1149       *fp++ = val;
1150     return OK;
1151 
1152  gn17err:
1153     return fterror(ff, Str("gen call has illegal x-ordinate values:"));
1154 }
1155 
1156 /* by pete moss (petemoss@petemoss.org), jan 2002 */
1157 
gen18(FGDATA * ff,FUNC * ftp)1158 static int gen18(FGDATA *ff, FUNC *ftp)
1159 {
1160     CSOUND  *csound = ff->csound;
1161     int     cnt, start, finish, fnlen, j;
1162     MYFLT   *pp = &ff->e.p[5], fn, amp, *fp, *fp18 = ftp->ftable, range, f;
1163     double  i;
1164     FUNC    *fnp;
1165     int     nargs = ff->e.pcnt - 4;
1166     int nsw = 1;
1167 
1168     if (UNLIKELY(ff->e.pcnt>=PMAX))
1169       csound->Warning(csound, Str("using extended arguments\n"));
1170     if (UNLIKELY((cnt = nargs >> 2) <= 0)) {
1171       return fterror(ff, Str("wrong number of args"));
1172     }
1173     while (cnt--) {
1174       fn=*pp++;
1175       if (UNLIKELY(nsw && pp>=&ff->e.p[PMAX-1])) nsw =0, pp = &(ff->e.c.extra[1]);
1176       amp=*pp++;
1177       if (UNLIKELY(nsw && pp>=&ff->e.p[PMAX-1])) nsw =0, pp = &(ff->e.c.extra[1]);
1178       start=(int)*pp++;
1179       if (UNLIKELY(nsw && pp>=&ff->e.p[PMAX-1])) nsw =0, pp = &(ff->e.c.extra[1]);
1180       finish=(int)*pp++;
1181       if (UNLIKELY(nsw && pp>=&ff->e.p[PMAX-1])) nsw =0, pp = &(ff->e.c.extra[1]);
1182 
1183       if (UNLIKELY((start>ff->flen) || (finish>=ff->flen))) {
1184         /* make sure start and finish < flen */
1185         return fterror(ff, Str("a range given exceeds table length"));
1186       }
1187 
1188       if (LIKELY((fnp=csoundFTFind(csound,&fn))!=NULL)) { /* make sure fn exists */
1189         fp = fnp->ftable, fnlen = fnp->flen-1;        /* and set it up */
1190       }
1191       else {
1192         return fterror(ff, Str("an input function does not exist"));
1193       }
1194 
1195       range = (MYFLT) (finish - start), j = start;
1196       while (j <= finish) {                      /* write the table */
1197         unsigned int ii;
1198         f = (MYFLT)modf((fnlen*(j - start)/range), &i);
1199         ii = (unsigned int)i;
1200         //printf("***ii=%d f=%g\n", ii, f);
1201         if (ii==fnp->flen)
1202           fp18[j++] += amp * fp[ii];
1203         else
1204           fp18[j++] += amp * ((f * (fp[ii+1] - fp[ii])) + fp[ii]);
1205       }
1206     }
1207     return OK;
1208 }
1209 
gen19(FGDATA * ff,FUNC * ftp)1210 static int gen19(FGDATA *ff, FUNC *ftp)
1211 {
1212     int     hcnt;
1213     MYFLT   *valp, *fp, *finp;
1214     double  phs, inc, amp, dc, tpdlen = TWOPI / (double) ff->flen;
1215     int     nargs = ff->e.pcnt - 4;
1216     CSOUND  *csound = ff->csound;
1217     int nsw = 1;
1218 
1219     if (UNLIKELY(ff->e.pcnt>=PMAX))
1220       csound->Warning(csound, Str("using extended arguments\n"));
1221     if ((hcnt = nargs / 4) <= 0)                /* hcnt = nargs / 4 */
1222       return OK;
1223     valp = &ff->e.p[5];
1224     finp = &ftp->ftable[ff->flen];
1225     do {
1226       inc = *(valp++) * tpdlen;
1227       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
1228         nsw =0, valp = &(ff->e.c.extra[1]);
1229       amp = *(valp++);
1230       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
1231         nsw =0, valp = &(ff->e.c.extra[1]);
1232       phs = *(valp++) * tpd360;
1233       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
1234         nsw =0, valp = &(ff->e.c.extra[1]);
1235       dc = *(valp++);
1236       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
1237         nsw =0, valp = &(ff->e.c.extra[1]);
1238       for (fp = ftp->ftable; fp <= finp; fp++) {
1239         *fp += (MYFLT) (sin(phs) * amp + dc);   /* dc after str scale */
1240         if ((phs += inc) >= TWOPI)
1241           phs -= TWOPI;
1242       }
1243     } while (--hcnt);
1244 
1245     return OK;
1246 }
1247 
1248 /*  GEN20 and GEN21 by Paris Smaragdis 1994 B.C.M. Csound development team  */
1249 
gen20(FGDATA * ff,FUNC * ftp)1250 static int gen20(FGDATA *ff, FUNC *ftp)
1251 {
1252     MYFLT   cf[4], *ft;
1253     double  arg, x, xarg, beta = 0.0,varian = 1.0;
1254     int     i, nargs = ff->e.pcnt - 4;
1255 
1256     ft = ftp->ftable;
1257     xarg = 1.0;
1258 
1259     if (ff->e.p[4] < FL(0.0)) {
1260       xarg = ff->e.p[6];
1261       if ( nargs < 2 ) xarg = 1.0;
1262     }
1263 
1264     if (nargs > 2) {
1265       beta = (double) ff->e.p[7];
1266       varian = (double) ff->e.p[7];
1267     }
1268 
1269     switch ((int) ff->e.p[5])  {
1270     case 1:                     /* Hamming */
1271         cf[0] = FL(0.54);
1272         cf[1] = FL(0.46);
1273         cf[2] = cf[3] = FL(0.0);
1274         break;
1275     case 2:                     /* Hanning */
1276         cf[0] = cf[1] = FL(0.5);
1277         cf[2] = cf[3] = FL(0.0);
1278         break;
1279     case 3:                     /* Bartlett */
1280         arg = 2.0/ff->flen;
1281         for (i = 0, x = 0.0 ; i < ((int) ff->flen >> 1) ; i++, x++)
1282             ft[i] = (MYFLT) (x * arg * xarg);
1283         for ( ; i < (int) ff->flen ; i++, x++)
1284             ft[i] = (MYFLT) ((2.0 - x * arg) * xarg);
1285         return OK;
1286     case 4:                     /* Blackman */
1287         cf[0] = FL(0.42);
1288         cf[1] = FL(0.5);
1289         cf[2] = FL(0.08);
1290         cf[3] = FL(0.0);
1291         break;
1292     case 5:                     /* Blackman-Harris */
1293         cf[0] = FL(0.35878);
1294         cf[1] = FL(0.48829);
1295         cf[2] = FL(0.14128);
1296         cf[3] = FL(0.01168);
1297         break;
1298     case 6:                     /* Gaussian */
1299         arg = 12.0 / ff->flen;
1300         for (i = 0, x = -6.0 ; i < ((int) ff->flen >> 1) ; i++, x += arg)
1301           ft[i] = (MYFLT)(xarg * (pow(2.718281828459,-(x*x)/(2.0*varian*varian))));
1302         for (x = 0.0 ; i <= (int) ff->flen ; i++, x += arg)
1303           ft[i] = (MYFLT)(xarg * (pow(2.718281828459,-(x*x)/(2.0*varian*varian))));
1304         return OK;
1305     case 7:                     /* Kaiser */
1306       {
1307         double flen2 = 4.0 / ((double) ff->flen * (double) ff->flen);
1308         double besbeta = 1.0 / besseli(beta);
1309         x = (double) ff->flen * (-0.5) + 1.0;
1310         ft[0] = ft[ff->flen] = (MYFLT) (xarg * besbeta);
1311         for (i = 1 ; i < (int) ff->flen ; i++, x += 1.0)
1312           ft[i] = (MYFLT) (xarg * besseli(beta * sqrt(1.0 - x * x * flen2))
1313                                 * besbeta);
1314         return OK;
1315       }
1316     case 8:                     /* Rectangular */
1317         for (i = 0; i <= (int) ff->flen ; i++)
1318           ft[i] = FL(xarg);
1319         return OK;
1320     case 9:                     /* Sinc */
1321         arg = TWOPI * varian / ff->flen;
1322         for (i = 0, x = -PI * varian; i < ((int) ff->flen >> 1) ; i++, x += arg)
1323           ft[i] = (MYFLT) (xarg * sin(x) / x);
1324         ft[i++] = (MYFLT) xarg;
1325         for (x = arg ; i <= (int) ff->flen ; i++, x += arg)
1326           ft[i] = (MYFLT) (xarg * sin(x) / x);
1327         return OK;
1328     default:
1329         return fterror(ff, Str("No such window type!"));
1330     }
1331 
1332     arg = TWOPI / ff->flen;
1333 
1334     for (i = 0, x = 0.0 ; i <= (int) ff->flen ; i++, x += arg)
1335       ft[i] = (MYFLT) (xarg * (cf[0] - cf[1]*cos(x) + cf[2]*cos(2.0 * x)
1336                                      - cf[3]*cos(3.0 * x)));
1337 
1338     return OK;
1339 }
1340 
gen21(FGDATA * ff,FUNC * ftp)1341 static int gen21(FGDATA *ff, FUNC *ftp)
1342 {
1343     int     retval = gen21_rand(ff, ftp);
1344 
1345     switch (retval) {
1346       case 0:   break;
1347       case -1:  return fterror(ff, Str("Wrong number of input arguments"));
1348       case -2:  return fterror(ff, Str("unknown distribution"));
1349       default:  return NOTOK;
1350     }
1351     return OK;
1352 }
1353 
nextval(FILE * f)1354 static MYFLT nextval(FILE *f)
1355 {
1356     /* Read the next character; suppress multiple space and comments to a
1357        single space */
1358     int c;
1359  top:
1360     c = getc(f);
1361  top1:
1362     if (UNLIKELY(feof(f))) return NAN; /* Hope value is ignored */
1363     if (isdigit(c) || c=='e' || c=='E' || c=='+' || c=='-' || c=='.') {
1364       double d;                           /* A number starts */
1365       char buff[128];
1366       int j = 0;
1367       do {                                /* Fill buffer */
1368         buff[j++] = c;
1369         c = getc(f);
1370       } while (isdigit(c) || c=='e' || c=='E' || c=='+' || c=='-' || c=='.');
1371       buff[j]='\0';
1372       d = atof(buff);
1373       if (c==';' || c=='#') {             /* If exended with comment clear it now */
1374         while ((c = getc(f)) != '\n');
1375       }
1376       return (MYFLT)d;
1377     }
1378     //else .... allow expressions in [] ?
1379     while (isspace(c) || c == ',') c = getc(f);       /* Whitespace */
1380     if (c==';' || c=='#' || c=='<') {     /* Comment and tag*/
1381       while ((c = getc(f)) != '\n');
1382     }
1383     if (isdigit(c) || c=='e' || c=='E' || c=='+' || c=='-' || c=='.') goto top1;
1384     goto top;
1385 }
1386 
gen23(FGDATA * ff,FUNC * ftp)1387 static int gen23(FGDATA *ff, FUNC *ftp)
1388                                 /* ASCII file table read Gab 17-feb-98*/
1389                                 /* Modified after Paris Smaragdis by JPff */
1390 {                               /* And further hacked 2009 by JPff */
1391     CSOUND  *csound = ff->csound;
1392     MYFLT   *fp;
1393     FILE    *infile;
1394     void    *fd;
1395     int     j;
1396     MYFLT   tmp;
1397 
1398     fd = csound->FileOpen2(csound, &infile, CSFILE_STD, ff->e.strarg, "r",
1399                            "SFDIR;SSDIR;INCDIR", CSFTYPE_FLOATS_TEXT, 0);
1400     if (UNLIKELY(fd == NULL)) {
1401       return fterror(ff, Str("error opening ASCII file"));
1402     }
1403     if (ftp == NULL) {
1404       /* Start counting elements */
1405       ff->flen = 0;
1406       do {
1407         ff->flen++;
1408         nextval(infile);
1409       } while (!feof(infile));
1410       ff->flen--; // overshoots by 1
1411       csoundMessage(csound, Str("%ld elements in %s\n"),
1412                     (long) ff->flen, ff->e.strarg);
1413       rewind(infile);
1414       /* Allocate memory and read them in now */
1415   /*  ff->flen      = ff->flen + 2;        ??? */
1416       ftp           = ftalloc(ff);
1417       ftp->lenmask  = 0xFFFFFFFF; /* avoid the error in csoundFTFind */
1418     }
1419     fp = ftp->ftable;
1420     j = 0;
1421     while (!feof(infile) && j < ff->flen) fp[j++] = nextval(infile);
1422     tmp = nextval(infile); // overshot value
1423     if (UNLIKELY(!feof(infile)))
1424       csound->Warning(csound,
1425                       Str("Number(s) after table full in GEN23, starting %f"), tmp);
1426     csound->FileClose(csound, fd);
1427     // if (def)
1428     {
1429       MYFLT *tab = ftp->ftable;
1430       tab[ff->flen] = tab[0];  /* guard point */
1431       //ftp->flen -= 1;  /* exclude guard point */
1432       ftresdisp(ff, ftp);       /* VL: 11.01.05  for deferred alloc tables */
1433     }
1434 
1435 
1436     return OK;
1437 }
1438 
gen24(FGDATA * ff,FUNC * ftp)1439 static int gen24(FGDATA *ff, FUNC *ftp)
1440 {
1441     CSOUND  *csound = ff->csound;
1442     MYFLT   *fp = ftp->ftable, *fp_source;
1443     FUNC    *srcftp;
1444     int     srcno, srcpts, j;
1445     MYFLT   max, min, new_max, new_min, source_amp, target_amp, amp_ratio;
1446     int     nargs = ff->e.pcnt - 4;
1447 
1448     if (UNLIKELY(nargs < 3)) {
1449       return fterror(ff, Str("insufficient arguments"));
1450     }
1451     if (UNLIKELY((srcno = (int) ff->e.p[5]) <= 0 ||
1452         srcno > csound->maxfnum         ||
1453                  (srcftp = csound->flist[srcno]) == NULL)) {
1454       return fterror(ff, Str("unknown srctable number"));
1455     }
1456     fp_source = srcftp->ftable;
1457 
1458     new_min = ff->e.p[6];
1459     new_max = ff->e.p[7];
1460     srcpts = srcftp->flen;
1461     if (UNLIKELY(srcpts!= ff->flen)) {
1462       return fterror(ff, Str("table size must be the same of source table"));
1463     }
1464     max = min = fp_source[0];
1465     for (j = 0; j < srcpts; j++) {
1466       if (fp_source[j] > max ) max = fp_source[j];
1467       if (fp_source[j] < min ) min = fp_source[j];
1468     }
1469 
1470     source_amp = max - min;
1471     target_amp = new_max - new_min;
1472     amp_ratio = target_amp/source_amp;
1473 
1474     for (j = 0; j < srcpts; j++) {
1475       fp[j] = (fp_source[j]-min) * amp_ratio + new_min;
1476     }
1477     fp[j] = fp[j-1];
1478 
1479     return OK;
1480 }
1481 
gen25(FGDATA * ff,FUNC * ftp)1482 static int gen25(FGDATA *ff, FUNC *ftp)
1483 {
1484     int     nsegs,  seglen;
1485     MYFLT   *valp, *fp, *finp;
1486     MYFLT   x1, x2, y1, y2, mult;
1487     int     nargs = ff->e.pcnt - 4;
1488     CSOUND  *csound = ff->csound;
1489     int nsw = 1;
1490 
1491     if (UNLIKELY(ff->e.pcnt>=PMAX))
1492       csound->Warning(csound, Str("using extended arguments\n"));
1493     if ((nsegs = ((nargs / 2) - 1)) <= 0)
1494       return OK;
1495     valp = &ff->e.p[5];
1496     fp = ftp->ftable;
1497     finp = fp + ff->flen;
1498     do {
1499       x1 = *valp++;
1500       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
1501         nsw =0, valp = &(ff->e.c.extra[1]);
1502       y1 =  *valp++;
1503       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
1504         nsw =0, valp = &(ff->e.c.extra[1]);
1505       x2 = *valp++;
1506       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
1507         nsw =0, valp = &(ff->e.c.extra[1]);
1508       if (LIKELY(nsegs > 1)) {
1509         y2 =  *valp++;
1510         if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
1511           nsw =0, valp = &(ff->e.c.extra[1]);
1512       }
1513       else
1514         y2 = *valp;
1515       if (UNLIKELY(x2 < x1)) goto gn25err;
1516       if (UNLIKELY(x1 > ff->flen || x2 > ff->flen)) goto gn25err2;
1517       seglen = (int)(x2-x1);
1518       if (UNLIKELY(y1 <= 0 || y2 <= 0)) goto gn25err3;
1519       mult = y2/y1;
1520       mult = POWER(mult, FL(1.0)/seglen);
1521       while (seglen--) {
1522         *fp++ = y1;
1523         y1 *= mult;
1524         if (fp > finp)
1525           return OK;
1526       }
1527       valp -= 2;
1528     } while (--nsegs);
1529     if (fp == finp)                     /* if 2**n pnts, add guardpt */
1530       *fp = y1;
1531     return OK;
1532 
1533  gn25err:
1534     return fterror(ff, Str("x coordinates must all be in increasing order:"));
1535 
1536  gn25err2:
1537     return fterror(ff, Str("x coordinate greater than function size:"));
1538 
1539  gn25err3:
1540     return fterror(ff,
1541                    Str("illegal input val (y <= 0) for gen call, beginning:"));
1542 }
1543 
gen27(FGDATA * ff,FUNC * ftp)1544 static int gen27(FGDATA *ff, FUNC *ftp)
1545 {
1546     int     nsegs;
1547     MYFLT   *valp, *fp, *finp;
1548     MYFLT   x1, x2, y1, y2, yy, seglen, incr;
1549     int     nargs = ff->e.pcnt - 4;
1550     CSOUND  *csound = ff->csound;
1551     int nsw = 1;
1552 
1553     if (UNLIKELY(ff->e.pcnt>=PMAX))
1554       csound->Warning(csound, Str("using extended arguments\n"));
1555     if ((nsegs = ((nargs / 2) - 1)) <= 0)
1556       return OK;
1557     valp = &ff->e.p[5];
1558     fp = ftp->ftable;
1559     finp = fp + ff->flen;
1560     //printf("valp=%p end=%p extra=%p\n",
1561     //       valp, &ff->e.p[PMAX-1], &(ff->e.c.extra[1]));
1562     x2 = *valp++; y2 = *valp++;
1563     do {
1564       x1 = x2; y1 = y2;
1565       x2 = *valp++;
1566       if (UNLIKELY(nsw && valp>&ff->e.p[PMAX-1])) {
1567         //printf("extend: valp=%p extra=%p\n", valp, &(ff->e.c.extra[1]));
1568         nsw =0, valp = &(ff->e.c.extra[1]);
1569         //printf("extendx2: valp=%p\n", valp);
1570       }
1571       //if (nsw==0) printf("extend: valp=%p\n", valp);
1572       if (LIKELY(nsegs > 1)) {
1573         y2 =  *valp++;
1574         if (UNLIKELY(nsw && valp>&ff->e.p[PMAX-1])) {
1575           //printf("extendy2: valp=%p extra=%p\n", valp, &(ff->e.c.extra[1]));
1576           nsw =0, valp = &(ff->e.c.extra[1]);
1577           //printf("extend: valp=%p\n", valp);
1578         }
1579       }
1580       else {
1581         y2 = *valp;
1582         //printf("end of list: valp = %p x1,y1,x2,y2 = %f,%f,%f,%f\n",
1583         //       valp, x1, y1, x2, y2);
1584       }
1585       if (UNLIKELY(x2 < x1)) goto gn27err;
1586       if (UNLIKELY(x1 > ff->flen || x2 > ff->flen)) goto gn27err2;
1587       seglen = x2-x1;
1588       incr = (y2 - y1) / seglen;
1589       yy = y1;
1590       while (seglen--) {
1591         *fp++ = yy;
1592         yy += incr;
1593         if (fp > finp)
1594           return OK;
1595       }
1596     } while (--nsegs);
1597     if (fp == finp)                     /* if 2**n pnts, add guardpt */
1598       *fp = y1;
1599     return OK;
1600 
1601  gn27err:
1602     printf("nsegs=%d x1,y1 = %f,%f x2,y2 = %f,%f\n", nsegs, x1, y1, x2, y2);
1603     return fterror(ff, Str("x coordinates must all be in increasing order:"));
1604  gn27err2:
1605     return fterror(ff, Str("x coordinate greater than function size:"));
1606 }
1607 
1608 /* read X Y values directly from ascii file */
1609 
gen28(FGDATA * ff,FUNC * ftp)1610 static int gen28(FGDATA *ff, FUNC *ftp)
1611 {
1612     CSOUND  *csound = ff->csound;
1613     MYFLT   *fp, *finp;
1614     int     seglen, resolution = 100;
1615     FILE    *filp;
1616     void    *fd;
1617     int     i=0, j=0;
1618     MYFLT   *x, *y, *z;
1619     int     arraysize = 1000;
1620     MYFLT   x1, y1, z1, x2, y2, z2, incrx, incry;
1621 
1622     if (UNLIKELY(ff->flen))
1623       return fterror(ff, Str("GEN28 requires zero table length"));
1624     fd = csound->FileOpen2(csound, &filp, CSFILE_STD, ff->e.strarg, "r",
1625                           "SFDIR;SSDIR;INCDIR", CSFTYPE_FLOATS_TEXT, 0);
1626     if (UNLIKELY(fd == NULL))
1627       goto gen28err1;
1628 
1629     x = (MYFLT*)csound->Calloc(csound,arraysize*sizeof(MYFLT));
1630     y = (MYFLT*)csound->Calloc(csound,arraysize*sizeof(MYFLT));
1631     z = (MYFLT*)csound->Calloc(csound,arraysize*sizeof(MYFLT));
1632 #if defined(USE_DOUBLE)
1633     while (fscanf( filp, "%lf%lf%lf", &z[i], &x[i], &y[i])!= EOF)
1634 #else
1635     while (fscanf( filp, "%f%f%f", &z[i], &x[i], &y[i])!= EOF)
1636 #endif
1637       {
1638         i++;
1639         if (UNLIKELY(i>=arraysize)) {
1640           MYFLT* newx, *newy, *newz;
1641           arraysize += 1000;
1642           newx = (MYFLT*)realloc(x, arraysize*sizeof(MYFLT));
1643           newy = (MYFLT*)realloc(y, arraysize*sizeof(MYFLT));
1644           newz = (MYFLT*)realloc(z, arraysize*sizeof(MYFLT));
1645           if (UNLIKELY(!newx || !newy || !newz)) {
1646             fprintf(stderr, Str("Out of Memory\n"));
1647             exit(7);
1648           }
1649           x = newx; y = newy; z = newz;
1650         }
1651       }
1652     --i;
1653 
1654     ff->flen      = (int32) (z[i] * resolution * 2);
1655     ff->flen      = ff->flen + 2;       /* ??? */
1656     ftp           = ftalloc(ff);
1657     fp            = ftp->ftable;
1658     finp          = fp + ff->flen;
1659 
1660     do {
1661       x1 = x[j];
1662       y1 = y[j];
1663       x2 = x[j+1];
1664       y2 = y[j+1];
1665       z1 = z[j];
1666       z2 = z[j+1];
1667 
1668       if (UNLIKELY(z2 < z1)) goto gen28err2;
1669       seglen = (int)((z2-z1) * resolution);
1670       incrx = (x2 - x1) / (MYFLT)seglen;
1671       incry = (y2 - y1) / (MYFLT)seglen;
1672       while (seglen--) {
1673         *fp++ = x1;
1674         x1   += incrx;
1675         *fp++ = y1;
1676         y1   += incry;
1677       }
1678 
1679       j++;
1680     } while (--i);
1681     do {
1682       *fp++ = x[j];
1683       *fp++ = y[j+1];
1684     } while (fp < finp);
1685 
1686     csound->Free(csound,x); csound->Free(csound,y); csound->Free(csound,z);
1687     csound->FileClose(csound, fd);
1688 
1689     return OK;
1690 
1691  gen28err1:
1692     return fterror(ff, Str("could not open space file"));
1693  gen28err2:
1694     csound->Free(csound,x); csound->Free(csound,y); csound->Free(csound,z);
1695     return fterror(ff, Str("Time values must be in increasing order"));
1696 }
1697 
1698 /* gen30: extract a range of harmonic partials from source table */
1699 
gen30(FGDATA * ff,FUNC * ftp)1700 static int gen30(FGDATA *ff, FUNC *ftp)
1701 {
1702     CSOUND  *csound = ff->csound;
1703     MYFLT   *x, *f1, *f2;
1704     int     l1, l2, minh = 0, maxh = 0, i;
1705     MYFLT   xsr, minfrac, maxfrac;
1706     int     nargs = ff->e.pcnt - 4;
1707 
1708     if (UNLIKELY(nargs < 3)) {
1709       return fterror(ff, Str("insufficient gen arguments"));
1710     }
1711     xsr = FL(1.0);
1712     if ((nargs > 3) && (ff->e.p[8] > FL(0.0)))
1713       xsr = csound->esr / ff->e.p[8];
1714     l2 = csoundGetTable(csound, &f2, (int) ff->e.p[5]);
1715     if (UNLIKELY(l2 < 0)) {
1716       return fterror(ff, Str("GEN30: source ftable not found"));
1717     }
1718     f1 = ftp->ftable;
1719     l1 = (int) ftp->flen;
1720     minfrac = ff->e.p[6];           /* lowest harmonic partial number */
1721     maxfrac = ff->e.p[7] * xsr;     /* highest harmonic partial number */
1722     i = (l1 < l2 ? l1 : l2) >> 1;   /* sr/2 limit */
1723     /* limit to 0 - sr/2 range */
1724     if ((maxfrac < FL(0.0)) || (minfrac > (MYFLT) i))
1725       return OK;
1726     if (maxfrac > (MYFLT) i)
1727       maxfrac = (MYFLT) i;
1728     if (minfrac < FL(0.0))
1729       minfrac = FL(0.0);
1730     if ((nargs > 4) && (ff->e.p[9] != FL(0.0))) {
1731       minh     = (int) minfrac;     /* "interpolation" mode */
1732       minfrac -= (MYFLT) minh;
1733       minfrac  = FL(1.0) - minfrac;
1734       maxh     = (int) maxfrac;
1735       maxfrac -= (MYFLT) (maxh++);
1736       if (maxh > i) {
1737         maxh = i; maxfrac = FL(1.0);
1738       }
1739     }
1740     else {
1741       minh = (int) ((double) minfrac + (i < 10000 ? 0.99 : 0.9));
1742       maxh = (int) ((double) maxfrac + (i < 10000 ? 0.01 : 0.1));
1743       minfrac = maxfrac = FL(1.0);
1744     }
1745     if (minh > maxh)
1746       return OK;
1747     i = (l1 > l2 ? l1 : l2) + 2;
1748     x = (MYFLT*) csound->Malloc(csound,sizeof(MYFLT) * i);
1749     /* read src table with amplitude scale */
1750     xsr = csound->GetInverseRealFFTScale(csound, l1) * (MYFLT) l1 / (MYFLT) l2;
1751     for (i = 0; i < l2; i++)
1752       x[i] = xsr * f2[i];
1753     /* filter */
1754     csound->RealFFT(csound, x, l2);
1755     x[l2] = x[1];
1756     x[1] = x[l2 + 1] = FL(0.0);
1757     for (i = 0; i < (minh << 1); i++)
1758       x[i] = FL(0.0);
1759     x[i++] *= minfrac;
1760     x[i] *= minfrac;
1761     i = maxh << 1;
1762     x[i++] *= maxfrac;
1763     x[i++] *= maxfrac;
1764     for ( ; i < (l1 + 2); i++)
1765       x[i] = FL(0.0);
1766     x[1] = x[l1];
1767     x[l1] = x[l1 + 1] = FL(0.0);
1768     csound->InverseRealFFT(csound, x, l1);
1769     /* write dest. table */
1770     /* memcpy(f1, x, l1*sizeof(MYFLT)); */
1771     for (i = 0; i < l1; i++)
1772       f1[i] = x[i];
1773     f1[l1] = f1[0];     /* write guard point */
1774     csound->Free(csound,x);
1775 
1776     return OK;
1777 }
1778 
1779 /* gen31: transpose, phase shift, and mix source table */
1780 
gen31(FGDATA * ff,FUNC * ftp)1781 static int gen31(FGDATA *ff, FUNC *ftp)
1782 {
1783     CSOUND  *csound = ff->csound;
1784     MYFLT   *x, *y, *f1, *f2;
1785     MYFLT   a, p;
1786     double  d_re, d_im, p_re, p_im, ptmp;
1787     int     i, j, k, n, l1, l2;
1788     int     nargs = ff->e.pcnt - 4;
1789     MYFLT   *valp = &ff->e.p[6];
1790     int nsw = 1;
1791 
1792     if (UNLIKELY(ff->e.pcnt>=PMAX))
1793       csound->Warning(csound, Str("using extended arguments\n"));
1794     if (UNLIKELY(nargs < 4)) {
1795       return fterror(ff, Str("insufficient gen arguments"));
1796     }
1797     l2 = csoundGetTable(csound, &f2, (int) ff->e.p[5]);
1798     if (UNLIKELY(l2 < 0)) {
1799       return fterror(ff, Str("GEN31: source ftable not found"));
1800     }
1801     f1 = ftp->ftable;
1802     l1 = (int) ftp->flen;
1803 
1804     x = (MYFLT*) csound->Calloc(csound, (l2 + 2)*sizeof(MYFLT));
1805     y = (MYFLT*) csound->Calloc(csound, (l1 + 2)*sizeof(MYFLT));
1806     /* read and analyze src table, apply amplitude scale */
1807     a = csound->GetInverseRealFFTScale(csound, l1) * (MYFLT) l1 / (MYFLT) l2;
1808     for (i = 0; i < l2; i++)
1809       x[i] = a * f2[i];
1810     csound->RealFFT(csound, x, l2);
1811     x[l2] = x[1];
1812     x[1] = x[l2 + 1] = FL(0.0);
1813 
1814     for (j = 6; j < (nargs + 3); j+=3) {
1815       n = (int) (FL(0.5) + *valp++); if (n < 1) n = 1; /* frequency */
1816       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
1817         nsw =0, valp = &(ff->e.c.extra[1]);
1818       a = *valp++;                                     /* amplitude */
1819       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
1820         nsw =0, valp = &(ff->e.c.extra[1]);
1821       p = *valp++;                                       /* phase     */
1822       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
1823         nsw =0, valp = &(ff->e.c.extra[1]);
1824       //p -= (MYFLT) ((int) p);
1825       { MYFLT dummy = FL(0.0);
1826         p = MODF(p, &dummy);
1827       }
1828       if (UNLIKELY(p < FL(0.0))) p += FL(1.0);
1829       p *= TWOPI_F;
1830       d_re = cos((double) p); d_im = sin((double) p);
1831       p_re = 1.0; p_im = 0.0;   /* init. phase */
1832       for (i = k = 0; (i < l1 && k <l2); i += (n << 1), k += 2) {
1833         /* mix to table */
1834         y[i + 0] += a * (x[k + 0] * (MYFLT) p_re - x[k + 1] * (MYFLT) p_im);
1835         y[i + 1] += a * (x[k + 1] * (MYFLT) p_re + x[k + 0] * (MYFLT) p_im);
1836         /* update phase */
1837         ptmp = p_re * d_re - p_im * d_im;
1838         p_im = p_im * d_re + p_re * d_im;
1839         p_re = ptmp;
1840       }
1841     }
1842 
1843     /* write dest. table */
1844     y[1] = y[l1];
1845     y[l1] = y[l1 + 1] = FL(0.0);
1846     csound->InverseRealFFT(csound, y, l1);
1847     /* memcpy(f1, y, l1*sizeof(MYFLT)); */
1848     for (i = 0; i < l1; i++)
1849       f1[i] = y[i];
1850     f1[l1] = f1[0];     /* write guard point */
1851 
1852     csound->Free(csound,x);
1853     csound->Free(csound,y);
1854 
1855     return OK;
1856 }
1857 
1858 /* gen32: transpose, phase shift, and mix source tables */
1859 
paccess(FGDATA * ff,int i)1860 static inline MYFLT paccess(FGDATA *ff, int i)
1861 {
1862     if (LIKELY(i<PMAX)) return ff->e.p[i];
1863     else return ff->e.c.extra[i-PMAX+1];
1864 }
1865 
gen32(FGDATA * ff,FUNC * ftp)1866 static int gen32(FGDATA *ff, FUNC *ftp)
1867 {
1868     CSOUND  *csound = ff->csound;
1869     MYFLT   *x, *y, *f1, *f2;
1870     MYFLT   a, p;
1871     double  d_re, d_im, p_re, p_im, ptmp;
1872     int     i, j, k, n, l1, l2, ntabl, *pnum, ft;
1873     int     nargs = ff->e.pcnt - 4;
1874 
1875     if (UNLIKELY(ff->e.pcnt>=PMAX)) {
1876       csound->Warning(csound, Str("using extended arguments\n"));
1877     }
1878     if (UNLIKELY(nargs < 4)) {
1879       return fterror(ff, Str("insufficient gen arguments"));
1880     }
1881 
1882     ntabl = nargs >> 2;         /* number of waves to mix */
1883     pnum  = (int*) csound->Malloc(csound,sizeof(int) * ntabl);
1884     for (i = 0; i < ntabl; i++)
1885       pnum[i] = (i << 2) + 5;   /* p-field numbers */
1886     do {
1887       i = k = 0;                        /* sort by table number */
1888       while (i < (ntabl - 1)) {
1889         if (paccess(ff,pnum[i]) > paccess(ff,pnum[i + 1])) {
1890           j = pnum[i]; pnum[i] = pnum[i + 1]; pnum[i + 1] = j;
1891           k = 1;
1892         }
1893         i++;
1894       }
1895     } while (k);
1896 
1897     f1 = ftp->ftable;
1898     l1 = (int) ftp->flen;
1899     memset(f1, 0, l1*sizeof(MYFLT));
1900     /* for (i = 0; i <= l1; i++) */
1901     /*   f1[i] = FL(0.0); */
1902     x = y = NULL;
1903 
1904     ft = 0x7FFFFFFF;            /* last table number */
1905     j  = -1;                    /* current wave number */
1906 
1907     while (++j < ntabl) {
1908       p = paccess(ff,pnum[j]);                /* table number */
1909       i = (int) MYFLT2LRND(p);
1910       l2 = csoundGetTable(csound, &f2, abs(i));
1911       if (UNLIKELY(l2 < 0)) {
1912         fterror(ff, Str("GEN32: source ftable %d not found"), abs(i));
1913         if (x != NULL) csound->Free(csound,x);
1914         if (y != NULL) csound->Free(csound,y);
1915         csound->Free(csound,pnum);
1916         return NOTOK;
1917       }
1918       if (i < 0) {              /* use linear interpolation */
1919         ft = i;
1920         p_re  = (double) paccess(ff,pnum[j] + 3);     /* start phase */
1921         p_re -= (double) ((int) p_re); if (p_re < 0.0) p_re++;
1922         p_re *= (double) l2;
1923         d_re  = (double) paccess(ff,pnum[j] + 1);     /* frequency */
1924         d_re *= (double) l2 / (double) l1;
1925         a     = paccess(ff,pnum[j] + 2);              /* amplitude */
1926         for (i = 0; i <= l1; i++) {
1927           k = (int) p_re; p = (MYFLT) (p_re - (double) k);
1928           if (k >= l2) k -= l2;
1929           f1[i] += f2[k++] * a * (FL(1.0) - p);
1930           f1[i] += f2[k] * a * p;
1931           p_re += d_re;
1932           while (p_re < 0.0) p_re += (double) l2;
1933           while (p_re >= (double) l2) p_re -= (double) l2;
1934         }
1935       }
1936       else {                    /* use FFT */
1937         if (i != ft) {
1938           ft = i;               /* new table */
1939           if (y == NULL)
1940             y = (MYFLT*) csound->Calloc(csound,(l1 + 2)*sizeof (MYFLT));
1941           if (x != NULL) csound->Free(csound,x);
1942           x = (MYFLT*) csound->Calloc(csound,(l2 + 2)*sizeof (MYFLT));
1943           /* read and analyze src table */
1944           for (i = 0; i < l2; i++)
1945             x[i] = f2[i];
1946           csound->RealFFT(csound, x, l2);
1947           x[l2] = x[1];
1948           x[1] = x[l2 + 1] = FL(0.0);
1949         }
1950         n = (int) (FL(0.5) + paccess(ff,pnum[j] + 1));         /* frequency */
1951         if (n < 1) n = 1;
1952         a = paccess(ff,pnum[j] + 2) * (MYFLT) l1 / (MYFLT) l2; /* amplitude */
1953         a *= csound->GetInverseRealFFTScale(csound, (int) l1);
1954         p = paccess(ff,pnum[j] + 3);                           /* phase */
1955         p -= (MYFLT) ((int) p); if (p < FL(0.0)) p += FL(1.0); p *= TWOPI_F;
1956         d_re = cos ((double) p); d_im = sin ((double) p);
1957         p_re = 1.0; p_im = 0.0;         /* init. phase */
1958         if (y != NULL)
1959           for (i = k = 0; (i <= l1 && k <= l2); i += (n << 1), k += 2) {
1960             /* mix to table */
1961             y[i + 0] += a * (x[k + 0] * (MYFLT) p_re - x[k + 1] * (MYFLT) p_im);
1962             y[i + 1] += a * (x[k + 1] * (MYFLT) p_re + x[k + 0] * (MYFLT) p_im);
1963             /* update phase */
1964             ptmp = p_re * d_re - p_im * d_im;
1965             p_im = p_im * d_re + p_re * d_im;
1966             p_re = ptmp;
1967           }
1968       }
1969     }
1970     /* write dest. table */
1971     if (y != NULL) {
1972       y[1] = y[l1]; y[l1] = y[l1 + 1] = FL(0.0);
1973       csound->InverseRealFFT(csound, y, l1);
1974       for (i = 0; i < l1; i++)
1975         f1[i] += y[i];
1976       f1[l1] += y[0];           /* write guard point */
1977       csound->Free(csound,x);         /* free tmp memory */
1978       csound->Free(csound,y);
1979     }
1980     csound->Free(csound,pnum);
1981 
1982     return OK;
1983 }
1984 
1985 /* GEN33 by Istvan Varga */
1986 
gen33(FGDATA * ff,FUNC * ftp)1987 static int gen33(FGDATA *ff, FUNC *ftp)
1988 {
1989     CSOUND  *csound = ff->csound;
1990     MYFLT   fmode, *ft, *srcft, scl, amp, phs;
1991     MYFLT   *x;
1992     int     nh, flen, srclen, i, pnum, maxp;
1993     int     nargs = ff->e.pcnt - 4;
1994 
1995     if (UNLIKELY(nargs < 3)) {
1996       return fterror(ff, Str("insufficient gen arguments"));
1997     }
1998     if (nargs > 3)      /* check optional argument */
1999       fmode = ff->e.p[8];
2000     else
2001       fmode = FL(0.0);
2002     /* table length and data */
2003     ft = ftp->ftable; flen = (int) ftp->flen;
2004     /* source table */
2005     srclen = csoundGetTable(csound, &srcft, (int) ff->e.p[5]);
2006     if (UNLIKELY(srclen < 0)) {
2007       return fterror(ff, Str("GEN33: source ftable not found"));
2008     }
2009     /* number of partials */
2010     nh = (int) (ff->e.p[6] + FL(0.5));
2011     if (UNLIKELY(nh > (srclen / 3))) nh = srclen / 3;
2012     if (UNLIKELY(nh < 0)) nh = 0;
2013     /* amplitude scale */
2014     scl = FL(0.5) * (MYFLT) flen * ff->e.p[7];
2015     scl *= csound->GetInverseRealFFTScale(csound, flen);
2016     /* frequency mode */
2017     if (fmode < FL(0.0)) {
2018       fmode = (MYFLT) flen / (csound->esr * -fmode);  /* frequency in Hz */
2019     }
2020     else if (fmode > FL(0.0)) {
2021       fmode = (MYFLT) flen / fmode;             /* ref. sample rate */
2022     }
2023     else {
2024       fmode = FL(1.0);                          /* partial number */
2025     }
2026 
2027     /* allocate memory for tmp data */
2028     x = (MYFLT*) csound->Calloc(csound,(flen + 2)*sizeof(MYFLT));
2029 
2030     maxp = flen >> 1;           /* max. partial number */
2031     i = nh;
2032     while (i--) {
2033       /* amplitude */
2034       amp = scl * *(srcft++);
2035       /* partial number */
2036       pnum = (int) MYFLT2LRND(fmode * *srcft);
2037       srcft++;
2038       if (UNLIKELY(pnum < (-maxp) || pnum > maxp)) {
2039         srcft++; continue;      /* skip partial with too high frequency */
2040       }
2041       /* initial phase */
2042       phs = TWOPI_F * *(srcft++);
2043       if (UNLIKELY(pnum < 0)) {
2044         phs = PI_F - phs; pnum = -pnum;         /* negative frequency */
2045       }
2046       /* mix to FFT data */
2047       x[pnum << 1] += amp * SIN(phs);
2048       x[(pnum << 1) + 1] -= amp * COS(phs);
2049     }
2050 
2051     csound->InverseRealFFT(csound, x, flen);    /* iFFT */
2052 
2053 
2054     memcpy(ft, x, flen*sizeof(MYFLT));
2055     /* for (i = 0; i < flen; i++)  /\* copy to output table *\/ */
2056     /*   ft[i] = x[i]; */
2057     ft[flen] = x[0];            /* write guard point */
2058 
2059     /* free tmp memory */
2060     csound->Free(csound,x);
2061 
2062     return OK;
2063 }
2064 
2065 /* GEN34 by Istvan Varga */
2066 
gen34(FGDATA * ff,FUNC * ftp)2067 static int gen34(FGDATA *ff, FUNC *ftp)
2068 {
2069     CSOUND  *csound = ff->csound;
2070     MYFLT   fmode, *ft, *srcft, scl;
2071     double  y0, y1, x, c, v, *xn, *cn, *vn, *tmp, amp, frq, phs;
2072     int32    nh, flen, srclen, i, j, k, l, bs;
2073     FUNC    *src;
2074     int     nargs = ff->e.pcnt - 4;
2075 
2076     if (UNLIKELY(nargs < 3)) {
2077       return fterror(ff, Str("insufficient gen arguments"));
2078     }
2079     if (nargs > 3)      /* check optional argument */
2080       fmode = ff->e.p[8];
2081     else
2082       fmode = FL(0.0);
2083     /* table length and data */
2084     ft = ftp->ftable; flen = (int32) ftp->flen;
2085     /* source table */
2086     if (UNLIKELY((src = csoundFTnp2Findint(csound, &(ff->e.p[5]), 1)) == NULL))
2087       return NOTOK;
2088     srcft = src->ftable; srclen = (int32) src->flen;
2089     /* number of partials */
2090     nh = (int32) (ff->e.p[6] + FL(0.5));
2091     if (UNLIKELY(nh > (srclen / 3L))) nh = srclen / 3L;
2092     if (UNLIKELY(nh < 0L)) nh = 0L;
2093     /* amplitude scale */
2094     scl = ff->e.p[7];
2095     /* frequency mode */
2096     if (fmode < FL(0.0)) {
2097       fmode = TWOPI_F / (csound->esr * -fmode); /* frequency in Hz */
2098     }
2099     else if (fmode > FL(0.0)) {
2100       fmode = TWOPI_F / fmode;          /* ref. sample rate */
2101     }
2102     else {
2103       fmode = TWOPI_F / (MYFLT) flen;   /* partial number */
2104     }
2105 
2106     /* use blocks of 256 samples (2048 bytes) for speed */
2107     bs = 256L;
2108     /* allocate memory for tmp data */
2109     tmp = (double*) csound->Malloc(csound, sizeof(double) * bs);
2110     xn  = (double*) csound->Malloc(csound, sizeof(double) * (nh + 1L));
2111     cn  = (double*) csound->Malloc(csound, sizeof(double) * (nh + 1L));
2112     vn  = (double*) csound->Malloc(csound, sizeof(double) * (nh + 1L));
2113     /* initialise oscillators */
2114     i = -1L;
2115     while (++i < nh) {
2116       amp = (double) scl * (double) *(srcft++);         /* amplitude */
2117       frq = (double) fmode * (double) *(srcft++);       /* frequency */
2118       if (UNLIKELY(fabs (frq) > PI)) {
2119         xn[i] = cn[i] = vn[i] = 0.0;
2120         srcft++; continue;      /* skip partial with too high frequency */
2121       }
2122       phs = TWOPI * (double) *(srcft++);                /* phase */
2123       /* calculate coeffs for fast sine oscillator */
2124       y0 = sin(phs);           /* sample 0 */
2125       y1 = sin(phs + frq);     /* sample 1 */
2126       xn[i] = y0;
2127       cn[i] = 2.0 * cos(frq) - 2.0;
2128       vn[i] = y1 - cn[i] * y0 - y0;
2129       /* amp. scale */
2130       xn[i] *= amp; vn[i] *= amp;
2131     }
2132 
2133     /* render output */
2134     j = flen + 1L;      /* include guard point */
2135     do {
2136       k = (j > bs ? bs : j);    /* block size */
2137       /* clear buffer */
2138       memset(tmp, 0, k*sizeof(double));
2139       /* for (i = 0L; i < k; i++) tmp[i] = 0.0; */
2140       /* fast sine oscillator */
2141       i = -1L;
2142       while (++i < nh) {
2143         x = xn[i]; c = cn[i]; v = vn[i];
2144         l = k;
2145         do {
2146           *(tmp++) += x;
2147           v += c * x;
2148           x += v;
2149         } while (--l);
2150         tmp -= k;               /* restore pointer */
2151         xn[i] = x; vn[i] = v;   /* save oscillator state */
2152       }
2153       /* write to output table */
2154       for (i = 0L; i < k; i++) *(ft++) = (MYFLT) tmp[i];
2155       j -= k;
2156     } while (j);
2157 
2158     /* free tmp buffers */
2159     csound->Free(csound,tmp); csound->Free(csound,xn);
2160     csound->Free(csound,cn); csound->Free(csound,vn);
2161 
2162     return OK;
2163 }
2164 
gen40(FGDATA * ff,FUNC * ftp)2165 static int gen40(FGDATA *ff, FUNC *ftp)               /*gab d5*/
2166 {
2167     CSOUND  *csound = ff->csound;
2168     MYFLT   *fp = ftp->ftable, *fp_source, *fp_temp;
2169     FUNC    *srcftp;
2170     int     srcno, srcpts, j, k;
2171     MYFLT   last_value = FL(0.0), lenratio;
2172 
2173     if (UNLIKELY((srcno = (int) ff->e.p[5]) <= 0 ||
2174                  srcno > csound->maxfnum         ||
2175                  (srcftp = csound->flist[srcno]) == NULL)) {
2176       return fterror(ff, Str("unknown source table number"));
2177     }
2178     fp_source = srcftp->ftable;
2179     srcpts = srcftp->flen;
2180     fp_temp = (MYFLT *) csound->Calloc(csound,srcpts*sizeof(MYFLT));
2181     for (j = 0; j < srcpts; j++) {
2182       last_value += fp_source[j];
2183       fp_temp[j] = last_value;
2184     }
2185     lenratio = (ff->flen-1)/last_value;
2186 
2187     for (j = 0; j < ff->flen; j++) {
2188       k=0;
2189       while ( k++ < srcpts && fp_temp[k] * lenratio < j) ;
2190       k--;
2191       fp[j] = (MYFLT) k;
2192     }
2193     fp[j] = fp[j-1];
2194     csound->Free(csound,fp_temp);
2195 
2196     return OK;
2197 }
2198 
gen41(FGDATA * ff,FUNC * ftp)2199 static int gen41(FGDATA *ff, FUNC *ftp)   /*gab d5*/
2200 {
2201     MYFLT   *fp = ftp->ftable, *pp = &ff->e.p[5];
2202     int     i, j, k, width;
2203     MYFLT    tot_prob = FL(0.0);
2204     int     nargs = ff->e.pcnt - 4;
2205 
2206     for (j=0; j < nargs; j+=2) {
2207       if (UNLIKELY(pp[j+1]<0))
2208         return fterror(ff, Str("Gen41: negative probability not allowed"));
2209       tot_prob += pp[j+1];
2210     }
2211     //printf("total prob = %g\n", tot_prob);
2212     for (i=0, j=0; j< nargs; j+=2) {
2213       width = (int) ((pp[j+1]/tot_prob) * ff->flen +.5);
2214       for ( k=0; k < width; k++,i++) {
2215         fp[i] = pp[j];
2216       }
2217     }
2218     //printf("GEN41: i=%d le=%d\n", i, ff->flen);
2219     if (UNLIKELY(i<=ff->flen))
2220       fp[i] = pp[j-1]; /* conditional is attempt to stop error */
2221 
2222     return OK;
2223 }
2224 
gen42(FGDATA * ff,FUNC * ftp)2225 static int gen42(FGDATA *ff, FUNC *ftp) /*gab d5*/
2226 {
2227     MYFLT   *fp = ftp->ftable, inc;
2228     int     j, k, width;
2229     MYFLT    tot_prob = FL(0.0);
2230     int     nargs = ff->e.pcnt - 4;
2231     CSOUND  *csound = ff->csound;
2232     int nsw = 1;
2233     MYFLT   *valp = &ff->e.p[5];
2234 
2235     if (UNLIKELY(ff->e.pcnt>=PMAX))
2236       csound->Warning(csound, Str("using extended arguments\n"));
2237     for (j=0; j < nargs; j+=3) {
2238       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
2239         nsw =0, valp = &(ff->e.c.extra[1]);
2240       valp++;
2241       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
2242         nsw =0, valp = &(ff->e.c.extra[1]);
2243       valp++;
2244       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
2245         nsw =0, valp = &(ff->e.c.extra[1]);
2246       tot_prob += *valp++;
2247     }
2248     nsw = 1; valp = &ff->e.p[5];
2249     for (j=0; j< nargs; j+=3) {
2250       MYFLT p1, p2, p3;
2251       p1 = *valp++;
2252       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
2253         nsw =0, valp = &(ff->e.c.extra[1]);
2254       p2 = *valp++;
2255       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
2256         nsw =0, valp = &(ff->e.c.extra[1]);
2257       p3 = *valp++;
2258       if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1]))
2259         nsw =0, valp = &(ff->e.c.extra[1]);
2260       width = (int) ((p3/tot_prob) * ff->flen +FL(0.5));
2261       inc = (p2-p1) / (MYFLT) (width-1);
2262       for ( k=0; k < width; k++) {
2263         *fp++ = p1+(inc*k);
2264       }
2265     }
2266     *fp = *(fp-1);
2267 
2268     return OK;
2269 }
2270 
fterror(const FGDATA * ff,const char * s,...)2271 CS_NOINLINE int fterror(const FGDATA *ff, const char *s, ...)
2272 {
2273     CSOUND  *csound = ff->csound;
2274     char    buf[64];
2275     va_list args;
2276 
2277     snprintf(buf, 64, Str("ftable %d: "), ff->fno);
2278     va_start(args, s);
2279     csound->ErrMsgV(csound, buf, s, args);
2280     va_end(args);
2281     csoundMessage(csound, "f%3.0f %8.2f %8.2f ",
2282                             ff->e.p[1], ff->e.p2orig, ff->e.p3orig);
2283     if (isstrcod(ff->e.p[4]))
2284       csoundMessage(csound,"%s ", ff->e.strarg);
2285     else
2286       csoundMessage(csound, "%8.2f", ff->e.p[4]);
2287     if (isstrcod(ff->e.p[5]))
2288       csoundMessage(csound, "  \"%s\" ...\n", ff->e.strarg);
2289     else
2290       csoundMessage(csound, "%8.2f ...\n", ff->e.p[5]);
2291 
2292     return -1;
2293 }
2294 
2295 /* set guardpt, rescale the function, and display it */
2296 
ftresdisp(const FGDATA * ff,FUNC * ftp)2297 static CS_NOINLINE void ftresdisp(const FGDATA *ff, FUNC *ftp)
2298 {
2299     CSOUND  *csound = ff->csound;
2300     MYFLT   *fp, *finp = &ftp->ftable[ff->flen];
2301     MYFLT   abs, maxval;
2302     WINDAT  dwindow;
2303     char    strmsg[64];
2304 
2305     if (!ff->guardreq)                      /* if no guardpt yet, do it */
2306       ftp->ftable[ff->flen] = ftp->ftable[0];
2307     if (ff->e.p[4] > FL(0.0)) {             /* if genum positve, rescale */
2308       for (fp=ftp->ftable, maxval = FL(0.0); fp<=finp; ) {
2309         if ((abs = *fp++) < FL(0.0))
2310           abs = -abs;
2311         if (abs > maxval)
2312           maxval = abs;
2313       }
2314       if (maxval != FL(0.0) && maxval != FL(1.0))
2315         for (fp=ftp->ftable; fp<=finp; fp++)
2316           *fp /= maxval;
2317     }
2318     if (!csound->oparms->displays)
2319       return;
2320     memset(&dwindow, 0, sizeof(WINDAT));
2321     snprintf(strmsg, 64, Str("ftable %d:"), (int) ff->fno);
2322     if (csound->csoundMakeGraphCallback_ == NULL) dispinit(csound);
2323     dispset(csound, &dwindow, ftp->ftable, (int32) (ff->flen),
2324               strmsg, 0, "ftable");
2325     display(csound, &dwindow);
2326 }
2327 
generate_sine_tab(CSOUND * csound)2328 static void generate_sine_tab(CSOUND *csound)
2329 {                               /* Assume power of 2 length */
2330     int flen = csound->sinelength;
2331     FUNC    *ftp = (FUNC*) csound->Calloc(csound, sizeof(FUNC));
2332     ftp->ftable = (MYFLT*) csound->Calloc(csound, sizeof(MYFLT)*(flen+1));
2333     double  tpdlen = TWOPI / (double) flen;
2334     MYFLT *ftable = ftp->ftable;
2335     unsigned int i;
2336     int ltest, lobits;
2337     for (ltest = flen, lobits = 0;
2338            (ltest & MAXLEN) == 0L;
2339            lobits++, ltest <<= 1)
2340         ;
2341     ftp->lobits   = lobits;
2342     i = (1 << lobits);
2343     ftp->lomask   = (int32) (i - 1);
2344     ftp->lodiv    = FL(1.0) / (MYFLT) i;        /*    & other useful vals   */
2345     ftp->flen = ftp->flenfrms = flen;
2346     ftp->fno = -1;
2347     ftp->lenmask = flen - 1;
2348     ftp->nchanls = 1;
2349     for (i = 1; i<ftp->flen; i++)
2350       ftable[i] = (MYFLT) sin(i*tpdlen);
2351     ftable[0] = ftable[ftp->flen] = FL(0.0);
2352     csound->sinetable = ftp;
2353     return;
2354 }
2355 
2356 /* alloc ftable space for fno (or replace one) */
2357 /*  set ftp to point to that structure         */
2358 
ftalloc(const FGDATA * ff)2359 static CS_NOINLINE FUNC *ftalloc(const FGDATA *ff)
2360 {
2361     CSOUND  *csound = ff->csound;
2362     FUNC    *ftp = csound->flist[ff->fno];
2363 
2364     if (UNLIKELY(ftp != NULL)) {
2365       csound->Warning(csound, Str("replacing previous ftable %d"), ff->fno);
2366       if (ff->flen != (int32)ftp->flen) {       /* if redraw & diff len, */
2367         csound->Free(csound, ftp->ftable);
2368         csound->Free(csound, (void*) ftp);             /*   release old space   */
2369         csound->flist[ff->fno] = ftp = NULL;
2370         if (UNLIKELY(csound->actanchor.nxtact != NULL)) { /*   & chk for danger */
2371           csound->Warning(csound, Str("ftable %d relocating due to size change"
2372                                       "\n         currently active instruments "
2373                                       "may find this disturbing"), ff->fno);
2374         }
2375       }
2376       else {
2377                                     /* else clear it to zero */
2378         MYFLT *tmp = ftp->ftable;
2379         memset((void*) ftp->ftable, 0, sizeof(MYFLT)*(ff->flen+1));
2380         memset((void*) ftp, 0, sizeof(FUNC));
2381         ftp->ftable = tmp; /* restore table pointer */
2382       }
2383     }
2384     if (ftp == NULL) {                      /*   alloc space as reqd */
2385       csound->flist[ff->fno] = ftp = (FUNC*) csound->Calloc(csound, sizeof(FUNC));
2386       ftp->ftable = (MYFLT*) csound->Calloc(csound, (1+ff->flen) * sizeof(MYFLT));
2387     }
2388     ftp->fno = (int32) ff->fno;
2389     ftp->flen = ff->flen;
2390     return ftp;
2391 }
2392 
2393 /* find the ptr to an existing ftable structure */
2394 /*   called by oscils, etc at init time         */
2395 
csoundFTFind(CSOUND * csound,MYFLT * argp)2396 FUNC *csoundFTFind(CSOUND *csound, MYFLT *argp)
2397 {
2398     FUNC    *ftp;
2399     int     fno;
2400 
2401     fno = MYFLT2LONG(*argp);
2402     if (UNLIKELY(fno == -1)) {
2403       if (UNLIKELY(csound->sinetable==NULL)) generate_sine_tab(csound);
2404       return csound->sinetable;
2405     }
2406     if (UNLIKELY(fno <= 0                    ||
2407                  fno > csound->maxfnum       ||
2408                  (ftp = csound->flist[fno]) == NULL)) {
2409       csoundInitError(csound, Str("Invalid ftable no. %f"), *argp);
2410       return NULL;
2411     }
2412     else if (UNLIKELY(ftp->lenmask == -1)) {
2413       csoundInitError(csound, Str("illegal table length"));
2414       return NULL;
2415     }
2416     else if (UNLIKELY(!ftp->lenmask)) {
2417       csoundInitError(csound,
2418                       Str("deferred-size ftable %f illegal here"), *argp);
2419       return NULL;
2420     }
2421     return ftp;
2422 }
2423 
2424 /* find the ptr to an existing ftable structure */
2425 /*   called by oscils, etc at init time         */
2426 /* does not throw an error when a non-pow of two size table is found */
2427 
csoundFTFind2(CSOUND * csound,MYFLT * argp)2428 FUNC *csoundFTFind2(CSOUND *csound, MYFLT *argp)
2429 {
2430     FUNC    *ftp;
2431     int     fno;
2432 
2433     fno = MYFLT2LONG(*argp);
2434     if (UNLIKELY(fno == -1)) {
2435       if (UNLIKELY(csound->sinetable==NULL)) generate_sine_tab(csound);
2436       return csound->sinetable;
2437     }
2438     if (UNLIKELY(fno <= 0                    ||
2439                  fno > csound->maxfnum       ||
2440                  (ftp = csound->flist[fno]) == NULL)) {
2441       return NULL;
2442     }
2443     else if (UNLIKELY(ftp->lenmask == -1)) {
2444       return NULL;
2445     }
2446     else if (UNLIKELY(!ftp->lenmask)) {
2447       return NULL;
2448     }
2449     return ftp;
2450 }
2451 
2452 static FUNC *gen01_defer_load(CSOUND *csound, int fno);
csoundGetTable(CSOUND * csound,MYFLT ** tablePtr,int tableNum)2453 PUBLIC int csoundGetTable(CSOUND *csound, MYFLT **tablePtr, int tableNum)
2454 {
2455     FUNC    *ftp;
2456 
2457     if (UNLIKELY((unsigned int) (tableNum - 1) >= (unsigned int) csound->maxfnum))
2458       goto err_return;
2459     ftp = csound->flist[tableNum];
2460     if (UNLIKELY(ftp == NULL))
2461       goto err_return;
2462     if (!ftp->flen) {
2463       ftp = gen01_defer_load(csound, tableNum);
2464       if (UNLIKELY(ftp == NULL))
2465         goto err_return;
2466     }
2467     *tablePtr = ftp->ftable;
2468     return (int) ftp->flen;
2469  err_return:
2470     *tablePtr = (MYFLT*) NULL;
2471     return -1;
2472 }
2473 
2474 
2475 
csoundGetTableArgs(CSOUND * csound,MYFLT ** argsPtr,int tableNum)2476 PUBLIC int csoundGetTableArgs(CSOUND *csound, MYFLT **argsPtr, int tableNum)
2477 {
2478     FUNC    *ftp;
2479     if (UNLIKELY((unsigned int) (tableNum - 1) >= (unsigned int) csound->maxfnum))
2480       goto err_return;
2481     ftp = csound->flist[tableNum];
2482     if (UNLIKELY(ftp == NULL))
2483       goto err_return;
2484     *argsPtr = ftp->args;
2485     return (int) ftp->argcnt;
2486 
2487  err_return:
2488     *argsPtr = (MYFLT*) NULL;
2489     return -1;
2490 }
2491 
2492 /**************************************
2493  * csoundFTFindP()
2494  *
2495  * New function to find a function table at performance time.  Based
2496  * on csoundFTFind() which is intended to run at init time only.
2497  *
2498  * This function can be called from other modules - such as ugrw1.c.
2499  *
2500  * It returns a pointer to a FUNC data structure which contains all
2501  * the details of the desired table.  0 is returned if it cannot be
2502  * found.
2503  *
2504  * This does not handle deferred function table loads (gen01).
2505  *
2506  * Maybe this could be achieved, but some exploration would be
2507  * required to see that this is feasible at performance time.
2508  */
csoundFTFindP(CSOUND * csound,MYFLT * argp)2509 FUNC *csoundFTFindP(CSOUND *csound, MYFLT *argp)
2510 {
2511     FUNC    *ftp;
2512     int     fno;
2513 
2514     /* Check limits, and then index  directly into the flist[] which
2515      * contains pointers to FUNC data structures for each table.
2516      */
2517     fno = MYFLT2LONG(*argp);
2518     if (UNLIKELY(fno == -1)) {
2519       if (UNLIKELY(csound->sinetable==NULL)) generate_sine_tab(csound);
2520       return csound->sinetable;
2521     }
2522     if (UNLIKELY(fno <= 0                 ||
2523                  fno > csound->maxfnum    ||
2524                  (ftp = csound->flist[fno]) == NULL)) {
2525       csound->ErrorMsg(csound, Str("Invalid ftable no. %f"), *argp);
2526       return NULL;
2527     }
2528     else if (UNLIKELY(!ftp->lenmask)) {
2529       /* Now check that the table has a length > 0.  This should only
2530        * occur for tables which have not been loaded yet.  */
2531       csound->ErrorMsg(csound, Str("Deferred-size ftable %f load "
2532                                   "not available at perf time."), *argp);
2533       return NULL;
2534     }
2535     return ftp;
2536 }
2537 
2538 /* find ptr to a deferred-size ftable structure */
2539 /*   called by loscil at init time, and ftlen   */
2540 
csoundFTnp2Findint(CSOUND * csound,MYFLT * argp,int verbose)2541 FUNC *csoundFTnp2Findint(CSOUND *csound, MYFLT *argp, int verbose)
2542 {
2543     FUNC    *ftp;
2544     int     fno = MYFLT2LONG(*argp);
2545 
2546     if (UNLIKELY(fno == -1)) {
2547       if (UNLIKELY(csound->sinetable==NULL)) generate_sine_tab(csound);
2548       return csound->sinetable;
2549     }
2550     if (UNLIKELY(fno <= 0 ||
2551                  fno > csound->maxfnum    ||
2552                  (ftp = csound->flist[fno]) == NULL)) {
2553       if (verbose) csound->ErrorMsg(csound, Str("Invalid ftable no. %f"), *argp);
2554       return NULL;
2555     }
2556     if (ftp->flen == 0) {
2557      if (LIKELY(csound->oparms->gen01defer))
2558        ftp = gen01_defer_load(csound, fno);
2559        else {
2560          if (verbose) csound->ErrorMsg(csound, Str("Invalid ftable no. %f"), *argp);
2561         return NULL;
2562     }
2563       if (UNLIKELY(ftp == NULL))
2564       csound->inerrcnt++;
2565     }
2566     return ftp;
2567 }
2568 
csoundFTnp2Find(CSOUND * csound,MYFLT * argp)2569 FUNC *csoundFTnp2Find(CSOUND *csound, MYFLT *argp)
2570 {
2571     return csoundFTnp2Findint(csound, argp, 0);
2572 }
csoundFTnp2Finde(CSOUND * csound,MYFLT * argp)2573 FUNC *csoundFTnp2Finde(CSOUND *csound, MYFLT *argp)
2574 {
2575     return csoundFTnp2Findint(csound, argp, 1);
2576 }
2577 
2578 /* read ftable values from a sound file */
2579 /* stops reading when table is full     */
2580 
gen01(FGDATA * ff,FUNC * ftp)2581 static int gen01(FGDATA *ff, FUNC *ftp)
2582 {
2583     if (UNLIKELY(ff->e.pcnt < 8)) {
2584       return fterror(ff, Str("insufficient arguments"));
2585     }
2586     if (ff->csound->oparms->gen01defer) {
2587       /* We're deferring the soundfile load until performance time,
2588          so allocate the function table descriptor, save the arguments,
2589          and get out */
2590       ftp = ftalloc(ff);
2591       ftp->gen01args.gen01 = ff->e.p[4];
2592       ftp->gen01args.ifilno = ff->e.p[5];
2593       ftp->gen01args.iskptim = ff->e.p[6];
2594       ftp->gen01args.iformat = ff->e.p[7];
2595       ftp->gen01args.channel = ff->e.p[8];
2596       strNcpy(ftp->gen01args.strarg, ff->e.strarg, SSTRSIZ);
2597       return OK;
2598     }
2599     return gen01raw(ff, ftp);
2600 }
2601 
needsiz(CSOUND * csound,FGDATA * ff,int32 maxend)2602 static void needsiz(CSOUND *csound, FGDATA *ff, int32 maxend)
2603 {
2604     int32 nxtpow;
2605     maxend -= 1; nxtpow = 2;
2606     while (maxend >>= 1)
2607       nxtpow <<= 1;
2608     csoundMessage(csound, Str("non-deferred ftable %d needs size %d\n"),
2609                             (int) ff->fno, nxtpow);
2610 }
2611 
2612 static const int gen01_format_table[10] = {
2613     0,
2614     AE_CHAR,    AE_ALAW,    AE_ULAW,    AE_SHORT,    AE_LONG,
2615     AE_FLOAT,   AE_UNCH,    AE_24INT,   AE_DOUBLE
2616 };
2617 
2618 /* read ftable values from a sound file */
2619 /* stops reading when table is full     */
2620 
gen01raw(FGDATA * ff,FUNC * ftp)2621 static int gen01raw(FGDATA *ff, FUNC *ftp)
2622 {
2623     CSOUND  *csound = ff->csound;
2624     SOUNDIN *p;
2625     SOUNDIN tmpspace;
2626     SNDFILE *fd;
2627     int     truncmsg = 0;
2628     int32   inlocs = 0;
2629     int     def = 0, table_length = ff->flen + 1;
2630 
2631     p = &tmpspace;
2632     memset(p, 0, sizeof(SOUNDIN));
2633     {
2634       int32 filno = (int32) MYFLT2LRND(ff->e.p[5]);
2635       int   fmt = (int) MYFLT2LRND(ff->e.p[7]);
2636       /* union { */
2637       /*   MYFLT d; */
2638       /*   int32_t i[2]; */
2639       /* } xx; */
2640       /* xx.d = ff->e.p[5]; */
2641       /* printf("****line %d: ff->e.p[5] %f %.8x %.8x\n", __LINE__, */
2642       /*        ff->e.p[5], xx.i[1], xx.i[0]); */
2643       /* printf("****line %d: isstrcod=%d %d file %s\n", __LINE__, */
2644       /*        isstrcod(ff->e.p[5]), isnan(ff->e.p[5]), ff->e.strarg); */
2645       if (isstrcod(ff->e.p[5])) {
2646         /* printf("****line %d\n" , __LINE__); */
2647         if (ff->e.strarg[0] == '"') {
2648           int len = (int) strlen(ff->e.strarg) - 2;
2649           /* printf("****line %d\n" , __LINE__); */
2650           strNcpy(p->sfname, ff->e.strarg + 1, 512);
2651           if (len >= 0 && p->sfname[len] == '"')
2652             p->sfname[len] = '\0';
2653         }
2654         else {
2655           /* printf("****line %d\n" , __LINE__); */
2656           strNcpy(p->sfname, ff->e.strarg, 512);
2657         }
2658       }
2659       else if (filno >= 0 && filno <= csound->strsmax &&
2660                csound->strsets && csound->strsets[filno]) {
2661         /* printf("****line %d\n" , __LINE__); */
2662         strNcpy(p->sfname, csound->strsets[filno], 512);
2663       }
2664       else {
2665         /* printf("****line %d\n" , __LINE__); */
2666         snprintf(p->sfname, 512, "soundin.%d", filno);   /* soundin.filno */
2667       }
2668       //printf("****line %d: sfname=%s\n" , __LINE__, p->sfname);
2669       if (UNLIKELY(fmt < -9 || fmt > 9))
2670         return fterror(ff, Str("invalid sample format: %d"), fmt);
2671       if (fmt<0)
2672         p->format = -gen01_format_table[-fmt];
2673       else p->format = 0;
2674     }
2675     p->skiptime = ff->e.p[6];
2676     p->channel  = (int) MYFLT2LRND(ff->e.p[8]);
2677     p->do_floatscaling = 0;
2678     if (UNLIKELY(p->channel < 0 /* || p->channel > ALLCHNLS-1 */)) {
2679       return fterror(ff, Str("channel %d illegal"), (int) p->channel);
2680     }
2681     if (p->channel == 0)                      /* snd is chan 1,2,..8 or all */
2682       p->channel = ALLCHNLS;
2683     p->analonly = 0;
2684     if (UNLIKELY(ff->flen == 0 && (csound->oparms->msglevel & 7))) {
2685       csoundMessage(csound, Str("deferred alloc for %s\n"), p->sfname);
2686     }
2687     if (UNLIKELY((fd = sndgetset(csound, p))==NULL)) {
2688       /* sndinset to open the file  */
2689       return fterror(ff, Str("Failed to open file %s"), p->sfname);
2690     }
2691     if (ff->flen == 0) {                      /* deferred ftalloc requestd: */
2692       if (UNLIKELY((ff->flen = p->framesrem + 1) <= 0)) {
2693         /*   get minsize from soundin */
2694         return fterror(ff, Str("deferred size, but filesize unknown"));
2695       }
2696       if (UNLIKELY(csound->oparms->msglevel & 7))
2697         csoundMessage(csound, Str("  defer length %d\n"), ff->flen - 1);
2698        if (p->channel == ALLCHNLS)
2699          ff->flen *= p->nchanls;
2700       ff->guardreq  = 1;                      /* presum this includes guard */
2701 /*ff->flen     -= 1;*/ /* VL: this was causing tables to exclude last point */
2702       ftp           = ftalloc(ff);            /*   alloc now, and           */
2703       ftp->lenmask  = 0L;                     /*   mark hdr partly filled   */
2704       /*if (p->channel==ALLCHNLS) ftp->nchanls  = p->nchanls;
2705       else ftp->nchanls  = 1;
2706       ftp->flenfrms = ff->flen / p->nchanls; */ /* ?????????? */
2707       def           = 1;
2708       ff->flen -= 1;
2709       table_length = ff->flen;
2710     }
2711     if (p->channel==ALLCHNLS) {
2712       //ff->flen *= p->nchanls;
2713       ftp->nchanls  = p->nchanls;
2714     }
2715     else ftp->nchanls  = 1;
2716     ftp->flenfrms = ff->flen / ftp->nchanls;  /* VL fixed 8/10/19: using table nchnls */
2717     ftp->gen01args.sample_rate = (MYFLT) p->sr;
2718     ftp->cvtbas = LOFACT * p->sr * csound->onedsr;
2719     {
2720       SF_INSTRUMENT lpd;
2721       int ans = sf_command(fd, SFC_GET_INSTRUMENT, &lpd, sizeof(SF_INSTRUMENT));
2722       if (ans) {
2723         double natcps;
2724 #ifdef BETA
2725         if ((csound->oparms_.msglevel & 7) == 7) {
2726           csoundMessage(csound,
2727                   "Base Note : %u\tDetune    : %u\n"
2728                   "Low  Note : %u\tHigh Note : %u\n"
2729                   "Low  Vel. : %u\tHigh Vel. : %u\n"
2730                   "Gain      : %d\tCount     : %d\n"
2731                   "mode      : %d\n"
2732                   "start     : %d\tend       : %d\tcount  :%d\n"
2733                   "mode      : %d\n"
2734                   "start     : %d\tend       : %d\tcount  :%d\n\n",
2735                   lpd.basenote, 0U, lpd.key_lo, lpd.key_hi,
2736                   lpd.velocity_lo, lpd.velocity_hi, lpd.gain, lpd.loop_count,
2737                   lpd.loops[0].mode, lpd.loops[0].start, lpd.loops[0].end,
2738                   lpd.loops[0].count, lpd.loops[1].mode, lpd.loops[1].start,
2739                   lpd.loops[1].end, lpd.loops[1].count);
2740         }
2741 #endif
2742         natcps = pow(2.0, ((double) ((int) lpd.basenote - 69)
2743                            + (double) lpd.detune * 0.01) / 12.0) * csound->A4;
2744         /* As far as I can tell this gainfac value is never used! */
2745         //gainfac = exp((double) lpd.gain * LOG10D20);
2746      /* if (lpd.basenote == 0)
2747           lpd.basenote = ftp->cvtbas; */
2748         ftp->cpscvt = ftp->cvtbas / natcps;
2749         ftp->loopmode1 = (lpd.loops[0].mode == SF_LOOP_NONE ? 0 :
2750                           lpd.loops[0].mode == SF_LOOP_FORWARD ? 1 :
2751                           2);
2752         ftp->loopmode2 = (lpd.loops[1].mode == SF_LOOP_NONE ? 0 :
2753                           lpd.loops[1].mode == SF_LOOP_FORWARD ? 1 :
2754                           2);
2755          ftp->begin1 = lpd.loops[0].start;
2756         ftp->begin2 = lpd.loops[1].start;
2757         if (ftp->loopmode1)             /* Greg Sullivan */
2758           ftp->end1 = lpd.loops[0].end;
2759         else
2760           ftp->end1 = ftp->flenfrms;    /* Greg Sullivan */
2761         ftp->end2 = lpd.loops[1].end;
2762         if (UNLIKELY(ftp->end1 > ff->flen || ftp->end2 > ff->flen)) {
2763           int32 maxend;
2764           csound->Warning(csound,
2765                           Str("GEN1: input file truncated by ftable size"));
2766           if ((maxend = ftp->end1) < ftp->end2)
2767             maxend = ftp->end2;
2768           csoundMessage(csound,
2769                           Str("\tlooping endpoint %d exceeds ftsize %d\n"),
2770                           maxend, ff->flen);
2771           needsiz(csound, ff, maxend);
2772           truncmsg = 1;
2773         }
2774       }
2775       else {
2776         ftp->cpscvt = FL(0.0);          /* else no looping possible   */
2777         ftp->loopmode1 = 0;
2778         ftp->loopmode2 = 0;
2779         ftp->end1 = ftp->flenfrms;      /* Greg Sullivan */
2780       }
2781     }
2782     /* read sound with opt gain */
2783 
2784     if (UNLIKELY((inlocs=getsndin(csound, fd, ftp->ftable, table_length, p)) < 0)) {
2785       return fterror(ff, Str("GEN1 read error"));
2786     }
2787 
2788     if (UNLIKELY(p->audrem > 0 && !truncmsg && p->framesrem > ff->flen)) {
2789       /* Reduce msg */
2790       csound->Warning(csound, Str("GEN1: file truncated by ftable size"));
2791       csound->Warning(csound, Str("\taudio samps %d exceeds ftsize %d"),
2792                               (int32) p->framesrem, (int32) ff->flen);
2793       needsiz(csound, ff, p->framesrem);     /* ????????????  */
2794     }
2795     ftp->soundend = inlocs / ftp->nchanls;   /* record end of sound samps */
2796     csound->FileClose(csound, p->fd);
2797     if (def) {
2798       MYFLT *tab = ftp->ftable;
2799       ftresdisp(ff, ftp);       /* VL: 11.01.05  for deferred alloc tables */
2800       tab[ff->flen] = tab[0];  /* guard point */
2801       ftp->flen -= 1;  /* exclude guard point */
2802     }
2803     /* save arguments */
2804     ftp->argcnt = ff->e.pcnt - 3;
2805     {  /* Note this does not handle extened args -- JPff */
2806       int size=ftp->argcnt;
2807       //if (size>=PMAX) size=PMAX; // Coverity 96615 says this overflows
2808       memcpy(ftp->args, &(ff->e.p[4]), sizeof(MYFLT)*size);
2809       /* for (k=0; k < size; k++)
2810          csound->Message(csound, "%f\n", ftp->args[k]);*/
2811     }
2812     return OK;
2813 }
2814 
2815 /* GEN 43 (c) Victor Lazzarini, 2004 */
2816 
2817 typedef struct _pvstabledat {
2818     int32    fftsize;
2819     int32    overlap;
2820     int32    winsize;
2821     int     wintype;
2822     int     chans;
2823     int32    format;
2824     int32    blockalign;
2825     uint32 frames;
2826 } PVSTABLEDAT;
2827 
gen43(FGDATA * ff,FUNC * ftp)2828 static int gen43(FGDATA *ff, FUNC *ftp)
2829 {
2830     CSOUND          *csound = ff->csound;
2831     MYFLT           *fp = ftp->ftable;
2832     MYFLT           *filno;
2833     int             nvals = ff->e.pcnt - 4;
2834     MYFLT           *channel;
2835     char            filename[MAXNAME];
2836     PVOCEX_MEMFILE  pp;
2837     PVSTABLEDAT     p;
2838     uint32          framesize, blockalign, bins;
2839     uint32          frames, i, j;
2840     float           *framep, *startp;
2841     double          accum = 0.0;
2842 
2843     if (UNLIKELY(nvals != 2)) {
2844       return fterror(ff, Str("wrong number of ftable arguments"));
2845     }
2846 
2847     filno = &ff->e.p[5];
2848     if (isstrcod(ff->e.p[5]))
2849       strNcpy(filename, (char *)(&ff->e.strarg[0]), MAXNAME);
2850     else
2851       csound->strarg2name(csound, filename, filno, "pvoc.", 0);
2852 
2853     if (UNLIKELY(PVOCEX_LoadFile(csound, filename, &pp) != 0))
2854       return fterror(ff, Str("Failed to load PVOC-EX file"));
2855     //csoundDie(csound, Str("Failed to load PVOC-EX file"));
2856     p.fftsize  = pp.fftsize;
2857     p.overlap  = pp.overlap;
2858     p.winsize  = pp.winsize;
2859     p.wintype  = pp.wintype;
2860     p.chans    = pp.chans;
2861     p.format   = pp.format;
2862     p.frames   = pp.nframes;
2863 
2864     channel = &ff->e.p[6];
2865     if (UNLIKELY(*channel > p.chans))
2866       return fterror(ff, Str("illegal channel number"));
2867 
2868     framesize = p.fftsize+1;
2869     bins = framesize/2;
2870     frames = p.frames;
2871 
2872     if (*channel > 0) {
2873       startp = (float *) pp.data + (p.fftsize + 2) * ((int) *channel - 1);
2874       blockalign = (p.fftsize+2) * p.chans; /* only read one channel */
2875     }
2876     else {
2877       startp = (float *) pp.data;
2878       blockalign = (p.fftsize+2);           /* read all channels */
2879     }
2880 
2881     framep = startp;
2882 
2883     if (UNLIKELY(bins > (uint32) (ftp->flen+1))) {
2884       return fterror(ff, Str("ftable size too small"));
2885     }
2886 
2887     for (i=0; i<framesize; i+=2) {
2888       for (j=0; j < frames; j++, framep += blockalign) {
2889         accum += framep[i];
2890       }
2891       fp[i/2] = (MYFLT)accum/frames;
2892       framep = startp;
2893       accum = 0.0;
2894     }
2895     return OK;
2896 }
2897 #ifndef NACL
2898 #include "mp3dec.h"
2899 
gen49raw(FGDATA * ff,FUNC * ftp)2900 static int gen49raw(FGDATA *ff, FUNC *ftp)
2901 {
2902     CSOUND  *csound        = ff->csound;
2903     MYFLT   *fp           = ftp == NULL ? NULL: ftp->ftable;
2904     mp3dec_t mpa           = NULL;
2905     mpadec_config_t config = { MPADEC_CONFIG_FULL_QUALITY, MPADEC_CONFIG_AUTO,
2906                                MPADEC_CONFIG_16BIT, MPADEC_CONFIG_LITTLE_ENDIAN,
2907                                MPADEC_CONFIG_REPLAYGAIN_NONE, TRUE, TRUE, TRUE,
2908                                0.0 };
2909     int     skip              = 0, chan = 0, r, fd;
2910     int p                     = 0;
2911     char    sfname[1024];
2912     mpadec_info_t mpainfo;
2913     uint32_t bufsize, bufused = 0;
2914     uint8_t *buffer;
2915     int size = 0x1000;
2916     int flen, nchanls, def = 0;
2917 
2918     if (UNLIKELY(ff->e.pcnt < 7)) {
2919       return fterror(ff, Str("insufficient arguments"));
2920     }
2921     /* memset(&mpainfo, 0, sizeof(mpadec_info_t)); */ /* Is this necessary? */
2922     {
2923       int32 filno = (int32) MYFLT2LRND(ff->e.p[5]);
2924       if (isstrcod(ff->e.p[5])) {
2925         if (ff->e.strarg[0] == '"') {
2926           int len = (int) strlen(ff->e.strarg) - 2;
2927           strNcpy(sfname, ff->e.strarg + 1, 1024);
2928           if (len >= 0 && sfname[len] == '"')
2929             sfname[len] = '\0';
2930         }
2931         else
2932           strNcpy(sfname, ff->e.strarg, 1024);
2933       }
2934       else if ((filno= (int32) MYFLT2LRND(ff->e.p[5])) >= 0 &&
2935                filno <= csound->strsmax &&
2936                csound->strsets && csound->strsets[filno])
2937         strNcpy(sfname, csound->strsets[filno], 1024);
2938       else
2939         snprintf(sfname, 1024, "soundin.%d", filno);   /* soundin.filno */
2940     }
2941     chan  = (int) MYFLT2LRND(ff->e.p[7]);
2942     if (UNLIKELY(chan < 0)) {
2943       return fterror(ff, Str("channel %d illegal"), (int) chan);
2944     }
2945     switch (chan) {
2946     case 0:
2947       config.mode = MPADEC_CONFIG_AUTO; break;
2948     case 1:
2949       config.mode = MPADEC_CONFIG_MONO; break;
2950     case 2:
2951       config.mode = MPADEC_CONFIG_STEREO; break;
2952     case 3:
2953       config.mode = MPADEC_CONFIG_CHANNEL1; break;
2954     case 4:
2955       config.mode = MPADEC_CONFIG_CHANNEL2; break;
2956     }
2957     mpa = mp3dec_init();
2958     if (UNLIKELY(!mpa)) {
2959       return fterror(ff, Str("Not enough memory\n"));
2960     }
2961     if (UNLIKELY((r = mp3dec_configure(mpa, &config)) != MP3DEC_RETCODE_OK)) {
2962       mp3dec_uninit(mpa);
2963       return fterror(ff, mp3dec_error(r));
2964     }
2965     (void)csound->FileOpen2(csound, &fd, CSFILE_FD_R,
2966                                      sfname, NULL, "SFDIR;SSDIR",
2967                                      CSFTYPE_UNKNOWN_AUDIO, 0);
2968     //    fd = open(sfname, O_RDONLY); /* search paths */
2969     if (UNLIKELY(fd < 0)) {
2970       mp3dec_uninit(mpa);
2971       return fterror(ff, "sfname");
2972     }
2973     if (UNLIKELY((r = mp3dec_init_file(mpa, fd, 0, FALSE)) != MP3DEC_RETCODE_OK)) {
2974       mp3dec_uninit(mpa);
2975       return fterror(ff, mp3dec_error(r));
2976     }
2977     if (UNLIKELY((r = mp3dec_get_info(mpa, &mpainfo, MPADEC_INFO_STREAM)) !=
2978                  MP3DEC_RETCODE_OK)) {
2979       mp3dec_uninit(mpa);
2980       return fterror(ff, mp3dec_error(r));
2981     }
2982     /* maxsize = mpainfo.decoded_sample_size */
2983     /*   *mpainfo.decoded_frame_samples */
2984     /*   *mpainfo.frames; */
2985     {
2986       char temp[80];
2987       if (mpainfo.frequency < 16000) strcpy(temp, "MPEG-2.5 ");
2988       else if (mpainfo.frequency < 32000) strcpy(temp, "MPEG-2 ");
2989       else strcpy(temp, "MPEG-1 ");
2990       if (mpainfo.layer == 1) strcat(temp, "Layer I");
2991       else if (mpainfo.layer == 2) strcat(temp, "Layer II");
2992       else strcat(temp, "Layer III");
2993       csound->DebugMsg(csound, "Input:  %s, %s, %d kbps, %d Hz  (%d:%02d)\n",
2994               temp, ((mpainfo.channels > 1) ? "stereo" : "mono"),
2995               mpainfo.bitrate, mpainfo.frequency, mpainfo.duration/60,
2996               mpainfo.duration%60);
2997     }
2998     buffer = (uint8_t *)csound->Malloc(csound,size);
2999     bufsize = size/mpainfo.decoded_sample_size;
3000     skip = (int)(ff->e.p[6] * mpainfo.frequency);
3001     while (skip > 0) {
3002       uint32_t xx = skip;
3003       if ((uint32_t)xx > bufsize) xx = bufsize;
3004       //      printf("gen49: skipping xx\n", xx);
3005       skip -=xx;
3006       mp3dec_decode(mpa, buffer, mpainfo.decoded_sample_size*xx, &bufused);
3007     }
3008     //bufsize *= mpainfo.decoded_sample_size;
3009     r = mp3dec_decode(mpa, buffer, size, &bufused);
3010     nchanls = (chan == 2 && mpainfo.channels == 2 ? 2 : 1);
3011     if (ff->flen == 0) {    /* deferred ftalloc */
3012       int fsize, frames;
3013       frames = mpainfo.frames * mpainfo.decoded_frame_samples;
3014       fsize  = frames * nchanls;
3015       if (UNLIKELY((ff->flen = fsize) <= 0))
3016         return fterror(ff, Str("deferred size, but filesize unknown"));
3017       if (UNLIKELY(ff->flen > MAXLEN))
3018         return fterror(ff, Str("illegal table length"));
3019       if (UNLIKELY(csound->oparms->msglevel & 7))
3020         csoundMessage(csound, Str("  defer length %d\n"), ff->flen);
3021       ftp = ftalloc(ff);
3022       ftp->lenmask  = 0L;
3023       ftp->flenfrms = frames;
3024       ftp->nchanls  = nchanls;
3025       fp = ftp->ftable;
3026       def = 1;
3027     }
3028     ftp->gen01args.sample_rate = mpainfo.frequency;
3029     ftp->cvtbas = LOFACT * mpainfo.frequency * csound->onedsr;
3030     flen = ftp->flen;
3031     //printf("gen49: flen=%d size=%d bufsize=%d\n", flen, size, bufsize);
3032     while ((r == MP3DEC_RETCODE_OK) && bufused) {
3033       unsigned int i;
3034       short *bb = (short*)buffer;
3035       //printf("gen49: p=%d bufused=%d\n", p, bufused);
3036       for (i=0; i<bufused*nchanls/mpainfo.decoded_sample_size; i++)  {
3037         if (UNLIKELY(p>=flen)) {
3038           csound->Free(csound,buffer);
3039           //printf("gen49: i=%d p=%d exit as at end of table\n", i, p);
3040           return ((mp3dec_uninit(mpa) == MP3DEC_RETCODE_OK) ? OK : NOTOK);
3041         }
3042         fp[p] = ((MYFLT)bb[i]/(MYFLT)0x7fff) * csound->e0dbfs;
3043         //printf("%d: %f %d\n", p, fp[p], bb[i]);
3044         p++;
3045        }
3046       if (i <= 0) break;
3047       //printf("gen49: new buffer\n");
3048       r = mp3dec_decode(mpa, buffer, size, &bufused);
3049     }
3050 
3051     csound->Free(csound, buffer);
3052     r |= mp3dec_uninit(mpa);
3053     if (def) ftresdisp(ff, ftp);
3054     return ((r == MP3DEC_RETCODE_OK) ? OK : NOTOK);
3055 }
3056 
gen49(FGDATA * ff,FUNC * ftp)3057 static int gen49(FGDATA *ff, FUNC *ftp)
3058 {
3059     if (UNLIKELY(ff->e.pcnt < 7)) {
3060       return fterror(ff, Str("insufficient arguments"));
3061     }
3062     if (ff->csound->oparms->gen01defer) {
3063       /* We're deferring the soundfile load until performance time,
3064          so allocate the function table descriptor, save the arguments,
3065          and get out */
3066       ftp = ftalloc(ff);
3067       ftp->gen01args.gen01 = ff->e.p[4];
3068       ftp->gen01args.ifilno = ff->e.p[5];
3069       ftp->gen01args.iskptim = ff->e.p[6];
3070       ftp->gen01args.iformat = ff->e.p[7];
3071       ftp->gen01args.channel = ff->e.p[8];
3072       strNcpy(ftp->gen01args.strarg, ff->e.strarg, SSTRSIZ);
3073       return OK;
3074     }
3075     return gen49raw(ff, ftp);
3076 }
3077 #endif
3078 
gen51(FGDATA * ff,FUNC * ftp)3079 static int gen51(FGDATA *ff, FUNC *ftp)    /* Gab 1/3/2005 */
3080 {
3081     int     j, notenum, grade, numgrades, basekeymidi, nvals;
3082     MYFLT   basefreq, factor, interval;
3083     MYFLT   *fp = ftp->ftable, *pp;
3084     CSOUND  *csound = ff->csound;
3085 
3086     if (UNLIKELY(ff->e.pcnt>=PMAX)) {
3087       csound->Warning(csound, Str("using extended arguments\n"));
3088     }
3089     nvals       = ff->flen;
3090     pp          = &(ff->e.p[5]);
3091     numgrades   = (int) *pp++;
3092     interval    = *pp++;
3093     basefreq    = *pp++;
3094     basekeymidi = (int) *pp++;
3095     if (UNLIKELY((ff->e.pcnt - 8) < numgrades)) { /* gab fixed */
3096       return fterror(ff,
3097                      Str("GEN51: invalid number of p-fields (too few grades)"));
3098     }
3099 
3100     for (j = 0; j < nvals; j++) {
3101       MYFLT x;
3102       notenum = j;
3103       if (notenum < basekeymidi) {
3104         notenum = basekeymidi - notenum;
3105         grade  = (numgrades - (notenum % numgrades)) % numgrades;
3106         factor = -((MYFLT) ((int) ((notenum + numgrades - 1) / numgrades)));
3107       }
3108       else {
3109         notenum = notenum - basekeymidi;
3110         grade  = notenum % numgrades;
3111         factor = (MYFLT) ((int) (notenum / numgrades));
3112       }
3113       factor = POWER(interval, factor);
3114       if (LIKELY(grade<PMAX-10)) x = pp[grade];
3115       else x = ff->e.c.extra[grade-PMAX+11];
3116       fp[j] = x * factor * basefreq;
3117     }
3118     return OK;
3119 }
3120 
gen52(FGDATA * ff,FUNC * ftp)3121 static int gen52(FGDATA *ff, FUNC *ftp)
3122 {
3123     CSOUND  *csound = ff->csound;
3124     MYFLT   *src, *dst;
3125     FUNC    *f;
3126     int     nchn, len, len2, i, j, k, n;
3127     int     nargs = (int) ff->e.pcnt - 4;
3128 
3129     if (UNLIKELY(ff->e.pcnt>=PMAX)) {
3130       csound->Warning(csound, Str("using extended arguments\n"));
3131     }
3132     if (UNLIKELY(nargs < 4)) {
3133       return fterror(ff, Str("insufficient gen arguments"));
3134     }
3135     nchn = MYFLT2LRND(ff->e.p[5]);
3136     if (UNLIKELY(((nchn * 3) + 1) != nargs)) {
3137       return fterror(ff, Str("number of channels "
3138                              "inconsistent with number of args"));
3139     }
3140     len = ((int) ftp->flen / nchn) * nchn;
3141     dst = ftp->ftable;
3142     memset(dst, 0, ftp->flen*sizeof(MYFLT));
3143     /* for (i = len; i <= (int) ftp->flen; i++) */
3144     /*   dst[i] = FL(0.0); */
3145     for (n = 0; n < nchn; n++) {
3146       MYFLT *pp;
3147       if (LIKELY((n * 3) + 6<PMAX-1)) pp = &(ff->e.p[(n * 3) + 6]);
3148       else pp = &(ff->e.c.extra[(n * 3) + 6-PMAX]);
3149       f = csoundFTFind(csound, pp);
3150       if (UNLIKELY(f == NULL))
3151         return NOTOK;
3152       len2 = (int) f->flen;
3153       src = f->ftable;
3154       i = n;
3155       if (LIKELY((n * 3) + 7<PMAX-1)) j = MYFLT2LRND(ff->e.p[(n * 3) + 7]);
3156       else j = MYFLT2LRND(ff->e.c.extra[(n * 3) + 7-PMAX]);
3157       if (LIKELY((n * 3) + 8<PMAX-1)) k = MYFLT2LRND(ff->e.p[(n * 3) + 8]);
3158       else k = MYFLT2LRND(ff->e.c.extra[(n * 3) + 8-PMAX]);
3159       while (i < len) {
3160         if (j >= 0 && j < len2)
3161           dst[i] = src[j];
3162         else
3163           dst[i] = FL(0.0);
3164         i += nchn;
3165         j += k;
3166       }
3167     }
3168     return OK;
3169 }
3170 
gen53_apply_window(MYFLT * buf,MYFLT * w,int npts,int wpts,int minphase)3171 static void gen53_apply_window(MYFLT *buf, MYFLT *w,
3172                                int npts, int wpts, int minphase)
3173 {
3174     int64_t ph, ph_inc;
3175     int     i, j;
3176     MYFLT   pfrac;
3177 
3178     for (i = 1, j = 0; i < npts; i <<= 1, j++)
3179       ;
3180     if (!minphase) {
3181       ph = (int64_t) 0;
3182       ph_inc = ((int64_t) wpts << 32) >> j;
3183     }
3184     else {
3185       ph = (int64_t) wpts << 31;
3186       ph_inc = ((int64_t) wpts << 31) >> j;
3187     }
3188     for (i = 0; i <= npts; i++) {
3189       j = (int) (ph >> 32);
3190       pfrac = (MYFLT) ((int) (((uint32_t) ph) >> 1));
3191       if (j >= wpts) {
3192         buf[i] *= w[wpts];
3193       }
3194       else {
3195         pfrac *= (FL(0.5) / (MYFLT) 0x40000000);
3196         buf[i] *= (w[j] + ((w[j + 1] - w[j]) * pfrac));
3197       }
3198       ph += ph_inc;
3199     }
3200 }
3201 
gen53_freq_response_to_ir(CSOUND * csound,MYFLT * obuf,MYFLT * ibuf,MYFLT * wbuf,int npts,int wpts,int mode)3202 static void gen53_freq_response_to_ir(CSOUND *csound,
3203                                       MYFLT *obuf, MYFLT *ibuf, MYFLT *wbuf,
3204                                       int npts, int wpts, int mode)
3205 {
3206     MYFLT   *buf1, *buf2;
3207     double  tmp;
3208     MYFLT   scaleFac;
3209     int     i, j, npts2 = (npts << 1);
3210 
3211     scaleFac = csound->GetInverseRealFFTScale(csound, npts);
3212     /* ---- linear phase impulse response ---- */
3213     i = j = 0;
3214     do {
3215       obuf[i++] = (FABS(ibuf[j])) * scaleFac; j++;
3216       obuf[i++] = FL(0.0);
3217       obuf[i++] = -(FABS(ibuf[j]) * scaleFac); j++;
3218       obuf[i++] = FL(0.0);
3219     } while (i < npts);
3220     obuf[1] = ibuf[j] * scaleFac;
3221     csound->InverseRealFFT(csound, obuf, npts);
3222     obuf[npts] = FL(0.0);               /* clear guard point */
3223     if (wbuf != NULL && !(mode & 4))    /* apply window if requested */
3224       gen53_apply_window(obuf, wbuf, npts, wpts, 0);
3225     if (!(mode & 1)) {
3226       csound->Message(csound, "linear-phase output\n");
3227       return;
3228     }
3229     /* ---- minimum phase impulse response ---- */
3230     scaleFac = csound->GetInverseRealFFTScale(csound, npts2);
3231     buf1 = (MYFLT*) csound->Malloc(csound, sizeof(MYFLT) * (size_t) npts2);
3232     buf2 = (MYFLT*) csound->Malloc(csound, sizeof(MYFLT) * (size_t) npts2);
3233     /* upsample magnitude response by a factor of 2, */
3234     /* and store result in obuf[0]...obuf[npts]      */
3235     for (j = 0; j < (npts >> 1); j++)
3236       buf1[j] = FL(0.0);
3237     for (i = 0; i < npts; i++, j++)
3238       buf1[j] = obuf[i];
3239     for ( ; j < npts2; j++)
3240       buf1[j] = FL(0.0);
3241     csound->RealFFT(csound, buf1, npts2);
3242     for (i = j = 0; i < npts; i++, j += 2) {
3243       tmp = (double) buf1[j];
3244       tmp = sqrt(tmp * tmp + 1.0e-20);
3245       obuf[i] = (MYFLT) tmp;
3246     }
3247     tmp = (double) buf1[1];
3248     tmp = sqrt(tmp * tmp + 1.0e-20);
3249     obuf[i] = (MYFLT) tmp;
3250     /* calculate logarithm of magnitude response, */
3251     for (i = 0; i <= npts; i++) {
3252       buf1[i] = LOG(obuf[i]);
3253     }
3254     for (j = i - 2; i < npts2; i++, j--)    /* need full spectrum,     */
3255       buf1[i] = buf1[j];                    /* not just the lower half */
3256     csound->RealFFT(csound, buf1, npts2);
3257     /* and convolve with 1/tan(x) impulse response */
3258     buf2[0] = FL(0.0);
3259     buf2[1] = FL(0.0);
3260     for (i = 2; i < npts2; i += 2) {
3261       buf2[i] = FL(0.0);
3262       buf2[i + 1] = (MYFLT) (npts2 - i) / (MYFLT) npts2;
3263     }
3264     csound->RealFFTMult(csound, buf1, buf1, buf2, npts2, scaleFac);
3265     /* store unwrapped phase response in buf1 */
3266     csound->InverseRealFFT(csound, buf1, npts2);
3267     /* convert from magnitude/phase format to real/imaginary */
3268     for (i = 2; i < npts2; i += 2) {
3269       double  ph;
3270       ph = (double) buf1[i >> 1] / TWOPI;
3271       ph = TWOPI * modf(ph, &tmp);
3272       ph = (ph < 0.0 ? ph + PI : ph - PI);
3273       tmp = -((double) scaleFac * (double) obuf[i >> 1]);
3274       buf2[i] = (MYFLT) (tmp * cos(ph));
3275       buf2[i + 1] = (MYFLT) (tmp * sin(ph));
3276     }
3277     buf2[0] = scaleFac * obuf[0];
3278     buf2[1] = scaleFac * obuf[npts];
3279     /* perform inverse FFT to get impulse response */
3280     csound->InverseRealFFT(csound, buf2, npts2);
3281     /* copy output, truncating to table length + guard point */
3282     for (i = 0; i <= npts; i++)
3283       obuf[i] = buf2[i];
3284     csound->Free(csound, buf2);
3285     csound->Free(csound, buf1);
3286      csound->Message(csound, "minimum-phase output\n");
3287     if (wbuf != NULL && !(mode & 8))    /* apply window if requested */
3288       gen53_apply_window(obuf, wbuf, npts, wpts, 1);
3289 }
3290 
gen53(FGDATA * ff,FUNC * ftp)3291 static int gen53(FGDATA *ff, FUNC *ftp)
3292 {
3293     CSOUND  *csound = ff->csound;
3294     MYFLT   *srcftp, *dstftp, *winftp = NULL;
3295     int     nargs = ff->e.pcnt - 4;
3296     int     mode = 0, srcftno, winftno = 0, srcflen, dstflen, winflen = 0;
3297 
3298     if (UNLIKELY(nargs < 1 || nargs > 3)) {
3299       return fterror(ff, Str("GEN53: invalid number of gen arguments"));
3300     }
3301     srcftno = (int) MYFLT2LRND(ff->e.p[5]);
3302     if (nargs > 1)
3303       mode = (int) MYFLT2LRND(ff->e.p[6]);
3304     if (nargs > 2)
3305       winftno = (int) MYFLT2LRND(ff->e.p[7]);
3306 
3307     dstftp = ftp->ftable; dstflen = (int) ftp->flen;
3308     if (UNLIKELY(dstflen < 8 || (dstflen & (dstflen - 1)))) {
3309       return fterror(ff, Str("GEN53: invalid table length"));
3310     }
3311     srcflen = csoundGetTable(csound, &srcftp, srcftno);
3312     if (UNLIKELY(srcflen < 0)) {
3313       return fterror(ff, Str("GEN53: invalid source table number"));
3314     }
3315     if (UNLIKELY(mode & (~15))) {
3316       return fterror(ff, Str("GEN53: mode must be in the range 0 to 15"));
3317     }
3318     if (UNLIKELY((!(mode & 2) && srcflen != (dstflen >> 1)) ||
3319                  ((mode & 2) && srcflen != dstflen))) {
3320       return fterror(ff, Str("GEN53: invalid source table length:"));
3321     }
3322     if (winftno) {
3323       winflen = csoundGetTable(csound, &winftp, winftno);
3324       if (UNLIKELY(winflen <= 0 || (winflen & (winflen - 1)))) {
3325         return fterror(ff, Str("GEN53: invalid window table"));
3326       }
3327     }
3328     if (mode & 2) {     /* if input data is impulse response: */
3329       MYFLT *tmpft;
3330       int   i, j;
3331       tmpft = (MYFLT*) csound->Calloc(csound, sizeof(MYFLT)
3332                                               * (size_t) ((dstflen >> 1) + 1));
3333       memcpy(dstftp, srcftp, sizeof(MYFLT) * (size_t) dstflen);
3334       csound->RealFFT(csound, dstftp, dstflen);
3335       tmpft[0] = dstftp[0];
3336       for (i = 2, j = 1; i < dstflen; i += 2, j++)
3337         tmpft[j] = HYPOT(dstftp[i], dstftp[i + 1]);
3338       tmpft[j] = dstftp[1];
3339       csound->Message(csound,Str("GEN 53: impulse response input, "));
3340       gen53_freq_response_to_ir(csound, dstftp, tmpft, winftp,
3341                                         dstflen, winflen, mode);
3342       csound->Free(csound, tmpft);
3343     }
3344     else  {              /* input is frequency response: */
3345       csound->Message(csound, Str("GEN 53: frequency response input, "));
3346       gen53_freq_response_to_ir(csound, dstftp, srcftp, winftp,
3347                                         dstflen, winflen, mode);
3348     }
3349     return OK;
3350 }
3351 
allocgen(CSOUND * csound,char * s,GEN fn)3352 int allocgen(CSOUND *csound, char *s, GEN fn)
3353 {
3354     NAMEDGEN *n = (NAMEDGEN*) csound->namedgen;
3355 
3356     while (n != NULL) {
3357       if (strcmp(s, n->name) == 0)
3358         return n->genum;
3359       n = n->next;
3360     }
3361     /* Need to allocate */
3362     n = (NAMEDGEN*) csound->Malloc(csound, sizeof(NAMEDGEN));
3363     n->genum = csound->genmax++;
3364     n->next = (NAMEDGEN*) csound->namedgen;
3365     n->name = csound->Malloc(csound, strlen(s) + 1);
3366     strcpy(n->name, s);
3367     csound->namedgen = (void*) n;
3368     if (LIKELY(csound->gensub == NULL)) {
3369       csound->gensub = (GEN*) csound->Malloc(csound, csound->genmax * sizeof(GEN));
3370       memcpy(csound->gensub, or_sub, sizeof(or_sub));
3371     }
3372     else
3373       csound->gensub = (GEN*) csound->ReAlloc(csound, csound->gensub,
3374                                                csound->genmax * sizeof(GEN));
3375     csound->gensub[csound->genmax-1] = fn;
3376     return csound->genmax-1;
3377 }
3378 
3379 
csoundIsNamedGEN(CSOUND * csound,int num)3380 int csoundIsNamedGEN(CSOUND *csound, int num) {
3381     NAMEDGEN *n = (NAMEDGEN*) csound->namedgen;
3382     while (n != NULL) {
3383       if (n->genum == abs(num))
3384         return strlen(n->name);
3385       n = n->next;
3386     }
3387     return 0;
3388 }
3389 
3390 /* ODDITY:  does not stop when num found but continues to end; also not used!
3391    But has API use
3392  */
csoundGetNamedGEN(CSOUND * csound,int num,char * name,int len)3393 void csoundGetNamedGEN(CSOUND *csound, int num, char *name, int len) {
3394     NAMEDGEN *n = (NAMEDGEN*) csound->namedgen;
3395     while (n != NULL) {
3396       if (n->genum == abs(num)) {
3397         strNcpy(name,n->name,len+1);
3398         return;
3399       }
3400       n = n->next;
3401     }
3402 }
3403 
3404 
3405 #include "resize.h"
3406 
3407 static int warned = 0;          /* Thread Safe */
resize_table(CSOUND * csound,RESIZE * p)3408 int resize_table(CSOUND *csound, RESIZE *p)
3409 {
3410     unsigned int fsize  = (unsigned int) MYFLT2LRND(*p->nsize);
3411     int fno  = (int) MYFLT2LRND(*p->fn);
3412     FUNC *ftp;
3413 
3414     if (UNLIKELY(warned==0)) {
3415       printf("WARNING: EXPERIMENTAL CODE\n");
3416       warned = 1;
3417     }
3418     if (UNLIKELY((ftp = csound->FTFind(csound, p->fn)) == NULL))
3419       return NOTOK;
3420     if (ftp->flen<fsize)
3421       ftp->ftable = (MYFLT *) csound->ReAlloc(csound, ftp->ftable,
3422                                               sizeof(MYFLT)*(fsize+1));
3423     ftp->flen = fsize+1;
3424     csound->flist[fno] = ftp;
3425     return OK;
3426 }
3427 
gen01_defer_load(CSOUND * csound,int fno)3428 static CS_NOINLINE FUNC *gen01_defer_load(CSOUND *csound, int fno)
3429 {
3430     FGDATA  ff;
3431     char    *strarg;
3432     FUNC    *ftp = csound->flist[fno];
3433 
3434     /* The soundfile hasn't been loaded yet, so call GEN01 */
3435     strarg = csound->Malloc(csound, strlen(ftp->gen01args.strarg)+1);
3436     strcpy(strarg, ftp->gen01args.strarg);
3437     memset(&ff, 0, sizeof(FGDATA));
3438     ff.csound = csound;
3439     ff.fno = fno;
3440     ff.e.strarg = strarg;
3441     ff.e.opcod = 'f';
3442     ff.e.pcnt = 8;
3443     ff.e.p[1] = (MYFLT) fno;
3444     ff.e.p[4] = ftp->gen01args.gen01;
3445     ff.e.p[5] = ftp->gen01args.ifilno;
3446     ff.e.p[6] = ftp->gen01args.iskptim;
3447     ff.e.p[7] = ftp->gen01args.iformat;
3448     ff.e.p[8] = ftp->gen01args.channel;
3449     if (UNLIKELY(gen01raw(&ff, ftp) != 0)) {
3450       csoundErrorMsg(csound, Str("Deferred load of '%s' failed"), strarg);
3451       return NULL;
3452     }
3453     return csound->flist[fno];
3454 }
3455