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