1 /*  Copyright (C) 2002-2004 Gabriel Maldonado */
2 /*                2016 John ffitch (array changed) */
3 
4 /*  The gab library is free software; you can redistribute it */
5 /*  and/or modify it under the terms of the GNU Lesser General Public */
6 /*  License as published by the Free Software Foundation; either */
7 /*  version 2.1 of the License, or (at your option) any later version. */
8 
9 /*  The gab library is distributed in the hope that it will be useful, */
10 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of */
11 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the */
12 /*  GNU Lesser General Public License for more details. */
13 
14 /*  You should have received a copy of the GNU Lesser General Public */
15 /*  License along with the gab library; if not, write to the Free Software */
16 /*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA */
17 /*  02110-1301 USA */
18 
19 /* Ported to csound5 by: Andres Cabrera */
20 /* This file includes the opcodes from newopcodes.c */
21 /* TODO: Check if the authors (Peter Neubaeker and Jens Groh) are correct */
22 
23 /*printi removed? I can't find the corresponding OENTRY- */
24 /*Left them commented out */
25 /*how should exitnow be safely implemented? */
26 /*Check the zak opcodes */
27 /*changed some comments to c-style */
28 /*Check csystem, exitnow */
29 /*Check other opcodes commented out in Oentry */
30 
31 
32 #include "stdopcod.h"
33 #include "gab.h"
34 #include <math.h>
35 #include "interlocks.h"
36 
37 #define FLT_MAX ((MYFLT)0x7fffffff)
38 
krsnsetx(CSOUND * csound,KRESONX * p)39 static int32_t krsnsetx(CSOUND *csound, KRESONX *p)
40   /* Gabriel Maldonado, modified for arb order  */
41 {
42     int32_t scale;
43     p->scale = scale = (int32_t) *p->iscl;
44     if (UNLIKELY((p->loop = MYFLT2LRND(*p->ord)) < 1))
45       p->loop = 4; /*default value*/
46     if (!*p->istor && (p->aux.auxp == NULL ||
47                        (uint32_t)(p->loop*2*sizeof(MYFLT)) > p->aux.size))
48       csound->AuxAlloc(csound, (int64_t)(p->loop*2*sizeof(MYFLT)), &p->aux);
49     p->yt1 = (MYFLT*)p->aux.auxp; p->yt2 = (MYFLT*)p->aux.auxp + p->loop;
50     if (UNLIKELY(scale && scale != 1 && scale != 2)) {
51       return csound->InitError(csound,Str("illegal reson iscl value, %f"),
52                                *p->iscl);
53     }
54     if (LIKELY(!(*p->istor))) {
55       memset(p->yt1, 0, p->loop*sizeof(MYFLT));
56       memset(p->yt2, 0, p->loop*sizeof(MYFLT));
57     }
58     p->prvcf = p->prvbw = -FL(100.0);
59     return OK;
60 }
61 
kresonx(CSOUND * csound,KRESONX * p)62 static int32_t kresonx(CSOUND *csound, KRESONX *p) /* Gabriel Maldonado, modified */
63 {
64     int32_t flag = 0, j;
65     MYFLT       *ar, *asig;
66     MYFLT       c3p1, c3t4, omc3, c2sqr;
67     MYFLT *yt1, *yt2, c1,c2,c3;
68 
69     if (*p->kcf != p->prvcf) {
70       p->prvcf = *p->kcf;
71       p->cosf = COS(*p->kcf * csound->tpidsr * CS_KSMPS);
72       flag = 1;
73     }
74     if (*p->kbw != p->prvbw) {
75       p->prvbw = *p->kbw;
76       p->c3 = EXP(*p->kbw * csound->mtpdsr * CS_KSMPS);
77       flag = 1;
78     }
79     if (flag) {
80       c3p1 = p->c3 + FL(1.0);
81       c3t4 = p->c3 * FL(4.0);
82       omc3 = FL(1.0)- p->c3;
83       p->c2 = c3t4 * p->cosf / c3p1;            /* -B, so + below */
84       c2sqr = p->c2 * p->c2;
85       if (p->scale == 1)
86         p->c1 = omc3 * SQRT(FL(1.0) - (c2sqr / c3t4));
87       else if (p->scale == 2)
88         p->c1 = SQRT((c3p1*c3p1-c2sqr) * omc3/c3p1);
89       else p->c1 = FL(1.0);
90     }
91     c1   = p->c1;
92     c2   = p->c2;
93     c3   = p->c3;
94     yt1  = p->yt1;
95     yt2  = p->yt2;
96     asig = p->asig;
97     ar   = p->ar;
98     for (j=0; j< p->loop; j++) {
99       *ar = c1 * *asig + c2 * yt1[j] - c3 * yt2[j];
100       yt2[j] = yt1[j];
101       yt1[j] = *ar;
102       asig= p->ar;
103     }
104     return OK;
105 }
106 
107 /* /////////////////////////////////////////// */
108 
fastab_set(CSOUND * csound,FASTAB * p)109 static int32_t fastab_set(CSOUND *csound, FASTAB *p)
110 {
111     FUNC *ftp;
112     if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) {
113       return csound->InitError(csound, Str("fastab: incorrect table number"));
114     }
115     p->table = ftp->ftable;
116     p->tablen = ftp->flen;
117     p->xmode = (int32_t) *p->ixmode;
118     if (p->xmode)
119       p->xbmul = (MYFLT) p->tablen /*- FL(0.001)*/;
120     else
121       p->xbmul = FL(1.0);
122     return OK;
123 }
124 
fastabw(CSOUND * csound,FASTAB * p)125 static int32_t fastabw(CSOUND *csound, FASTAB *p)
126 {
127     uint32_t offset = p->h.insdshead->ksmps_offset;
128     uint32_t early  = p->h.insdshead->ksmps_no_end;
129     uint32_t n, nsmps = CS_KSMPS;
130     FUNC *ftp = csound->FTnp2Finde(csound, p->xfn);
131     p->table = ftp->ftable;
132     MYFLT *tab = p->table;
133     MYFLT *rslt = p->rslt, *ndx = p->xndx;
134 
135 
136     if (UNLIKELY(early)) nsmps -= early;
137     if (p->xmode) {
138       MYFLT xbmul = p->xbmul;   /* load once */
139       int32_t len = p->tablen;
140       for (n=offset; n<nsmps; n++)  { /* for loops compile better */
141         int32_t i = (int32_t)MYFLT2LRND(ndx[n]*xbmul);
142         if (UNLIKELY(i > len || i<0)) {
143           csound->Message(csound, "ndx: %f\n", ndx[n]);
144           return csound->PerfError(csound, &(p->h), Str("tabw off end"));
145         }
146         tab[i] = rslt[n];
147       }
148     }
149     else {
150       int32_t len = p->tablen;
151       for (n=offset; n<nsmps; n++) {
152         int32_t i = MYFLT2LRND(ndx[n]);
153         if (UNLIKELY(i > len || i<0)) {
154           return csound->PerfError(csound, &(p->h), Str("tabw off end"));
155         }
156         tab[i] = rslt[n];
157       }
158     }
159     return OK;
160 }
161 
fastabk(CSOUND * csound,FASTAB * p)162 static int32_t fastabk(CSOUND *csound, FASTAB *p)
163 {
164     int32_t i;
165     if (p->xmode)
166       i = (int32_t) MYFLT2LRND(*p->xndx * p->xbmul);
167     else
168       i = (int32_t) MYFLT2LRND(*p->xndx);
169     if (UNLIKELY(i > p->tablen || i<0)) {
170       return csound->PerfError(csound, &(p->h), Str("tab off end %i"), i);
171     }
172     *p->rslt =  p->table[i];
173     return OK;
174 }
175 
fastabkw(CSOUND * csound,FASTAB * p)176 static int32_t fastabkw(CSOUND *csound, FASTAB *p)
177 {
178     int32_t i;
179     if (p->xmode)
180       i = (int32_t) MYFLT2LRND(*p->xndx * p->xbmul);
181     else
182       i = (int32_t) MYFLT2LRND(*p->xndx);
183     if (UNLIKELY(i > p->tablen || i<0)) {
184       return csound->PerfError(csound, &(p->h), Str("tabw off end"));
185     }
186     p->table[i] = *p->rslt;
187     return OK;
188 }
189 
fastabi(CSOUND * csound,FASTAB * p)190 static int32_t fastabi(CSOUND *csound, FASTAB *p)
191 {
192     FUNC *ftp;
193     int32 i;
194 
195     if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) {
196       return csound->InitError(csound, Str("tab_i: incorrect table number"));
197     }
198     if (*p->ixmode)
199       i = (int32) MYFLT2LRND(*p->xndx * ftp->flen);
200     else
201       i = (int32) MYFLT2LRND(*p->xndx);
202     if (UNLIKELY(i >= (int32)ftp->flen || i<0)) {
203       return csound->InitError(csound, Str("tab_i off end: table number: %d\n"),
204                                (int32_t) *p->xfn);
205     }
206     *p->rslt =  ftp->ftable[i];
207     return OK;
208 }
209 
fastabiw(CSOUND * csound,FASTAB * p)210 static int32_t fastabiw(CSOUND *csound, FASTAB *p)
211 {
212     FUNC *ftp;
213     int32 i;
214     /*ftp = csound->FTFind(p->xfn); */
215     if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) {
216       return csound->InitError(csound, Str("tabw_i: incorrect table number"));
217     }
218     if (*p->ixmode)
219       i = (int32) MYFLT2LRND(*p->xndx * ftp->flen);
220     else
221       i = (int32) MYFLT2LRND(*p->xndx);
222     if (UNLIKELY(i >= (int32)ftp->flen || i<0)) {
223       return csound->PerfError(csound, &(p->h), Str("tabw_i off end"));
224     }
225     ftp->ftable[i] = *p->rslt;
226     return OK;
227 }
228 
fastab(CSOUND * csound,FASTAB * p)229 static int32_t fastab(CSOUND *csound, FASTAB *p)
230 {
231     uint32_t offset = p->h.insdshead->ksmps_offset;
232     uint32_t early  = p->h.insdshead->ksmps_no_end;
233     uint32_t i, nsmps = CS_KSMPS;
234     FUNC *ftp = csound->FTnp2Finde(csound, p->xfn);
235     p->table = ftp->ftable;
236     MYFLT *tab = p->table;
237     MYFLT *rslt = p->rslt, *ndx = p->xndx;
238     if (UNLIKELY(offset)) memset(rslt, '\0', offset*sizeof(MYFLT));
239     if (UNLIKELY(early)) {
240       nsmps -= early;
241       memset(&rslt[nsmps], '\0', early*sizeof(MYFLT));
242     }
243     if (p->xmode) {
244       MYFLT xbmul = p->xbmul;
245       int32_t len = p->tablen;
246       for (i=offset; i<nsmps; i++) {
247         int32_t n = (int32_t) MYFLT2LRND(ndx[i] * xbmul);
248         if (UNLIKELY(n > len || n<0)) {
249           return csound->PerfError(csound, &(p->h), Str("tab off end %d"),n);
250         }
251         rslt[i] = tab[n];
252       }
253     }
254     else {
255       int32_t len = p->tablen;
256       for (i=offset; i<nsmps; i++) {
257         int32_t n = (int32_t) MYFLT2LRND(ndx[i]);
258         if (UNLIKELY(n > len || n<0)) {
259           return csound->PerfError(csound, &(p->h), Str("tab off end %d"),n);
260         }
261         rslt[i] = tab[n];
262       }
263     }
264     return OK;
265 }
266 
tab_init(CSOUND * csound,TB_INIT * p,int32_t ndx)267 static CS_NOINLINE int32_t tab_init(CSOUND *csound, TB_INIT *p, int32_t ndx)
268 {
269     MYFLT             *ft;
270     STDOPCOD_GLOBALS  *pp;
271     if (UNLIKELY(csoundGetTable(csound, &ft, MYFLT2LRND(*p->ifn)) < 0))
272       return csound->InitError(csound, Str("tab_init: incorrect table number"));
273     pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env;
274     pp->tb_ptrs[ndx] = ft;
275     return OK;
276 }
277 
tab_perf(CSOUND * csound,FASTB * p)278 static CS_NOINLINE int32_t tab_perf(CSOUND *csound, FASTB *p)
279 {
280      IGN(csound);
281      *p->r = (*p->tb_ptr)[(int32_t) MYFLT2LRND(*p->ndx)];
282     return OK;
283 }
284 
tab_i_tmp(CSOUND * csound,FASTB * p,int32_t ndx)285 static CS_NOINLINE int32_t tab_i_tmp(CSOUND *csound, FASTB *p, int32_t ndx)
286 {
287     STDOPCOD_GLOBALS  *pp;
288     pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env;
289     p->tb_ptr = &(pp->tb_ptrs[ndx]);
290     p->h.iopadr = (SUBR) tab_perf;
291     return tab_perf(csound, p);
292 }
293 
tab_k_tmp(CSOUND * csound,FASTB * p,int32_t ndx)294 static CS_NOINLINE int32_t tab_k_tmp(CSOUND *csound, FASTB *p, int32_t ndx)
295 {
296     STDOPCOD_GLOBALS  *pp;
297     pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env;
298     p->tb_ptr = &(pp->tb_ptrs[ndx]);
299     p->h.opadr = (SUBR) tab_perf;
300     return tab_perf(csound, p);
301 }
302 
303 #ifdef TAB_MACRO
304 #undef TAB_MACRO
305 #endif
306 
307 #define TAB_MACRO(W,X,Y,Z)                  \
308 static int32_t W(CSOUND *csound, TB_INIT *p)    \
309 {   return tab_init(csound, p, Z);  }       \
310 static int32_t X(CSOUND *csound, FASTB *p)      \
311 {   return tab_i_tmp(csound, p, Z); }       \
312 static int32_t Y(CSOUND *csound, FASTB *p)      \
313 {   return tab_k_tmp(csound, p, Z); }
314 
315 TAB_MACRO(tab0_init, tab0_i_tmp, tab0_k_tmp, 0)
316 TAB_MACRO(tab1_init, tab1_i_tmp, tab1_k_tmp, 1)
317 TAB_MACRO(tab2_init, tab2_i_tmp, tab2_k_tmp, 2)
318 TAB_MACRO(tab3_init, tab3_i_tmp, tab3_k_tmp, 3)
319 TAB_MACRO(tab4_init, tab4_i_tmp, tab4_k_tmp, 4)
320 TAB_MACRO(tab5_init, tab5_i_tmp, tab5_k_tmp, 5)
321 TAB_MACRO(tab6_init, tab6_i_tmp, tab6_k_tmp, 6)
322 TAB_MACRO(tab7_init, tab7_i_tmp, tab7_k_tmp, 7)
323 TAB_MACRO(tab8_init, tab8_i_tmp, tab8_k_tmp, 8)
324 TAB_MACRO(tab9_init, tab9_i_tmp, tab9_k_tmp, 9)
325 TAB_MACRO(tab10_init, tab10_i_tmp, tab10_k_tmp, 10)
326 TAB_MACRO(tab11_init, tab11_i_tmp, tab11_k_tmp, 11)
327 TAB_MACRO(tab12_init, tab12_i_tmp, tab12_k_tmp, 12)
328 TAB_MACRO(tab13_init, tab13_i_tmp, tab13_k_tmp, 13)
329 TAB_MACRO(tab14_init, tab14_i_tmp, tab14_k_tmp, 14)
330 TAB_MACRO(tab15_init, tab15_i_tmp, tab15_k_tmp, 15)
331 
332 /* ====================== */
333 /* opcodes from Jens Groh */
334 /* ====================== */
335 
nlalp_set(CSOUND * csound,NLALP * p)336 static int32_t nlalp_set(CSOUND *csound, NLALP *p)
337 {
338     IGN(csound);
339     if (LIKELY(!(*p->istor))) {
340       p->m0 = 0.0;
341       p->m1 = 0.0;
342     }
343     return OK;
344 }
345 
nlalp(CSOUND * csound,NLALP * p)346 static int32_t nlalp(CSOUND *csound, NLALP *p)
347 {
348     IGN(csound);
349     uint32_t offset = p->h.insdshead->ksmps_offset;
350     uint32_t early  = p->h.insdshead->ksmps_no_end;
351     uint32_t n, nsmps = CS_KSMPS;
352     MYFLT *rp;
353     MYFLT *ip;
354     double m0;
355     double m1;
356     double tm0;
357     double tm1;
358     double klfact;
359     double knfact;
360 
361     rp = p->aresult;
362     ip = p->ainsig;
363     klfact = (double)*p->klfact;
364     knfact = (double)*p->knfact;
365     tm0 = p->m0;
366     tm1 = p->m1;
367     if (UNLIKELY(offset)) memset(rp, '\0', offset*sizeof(MYFLT));
368      if (UNLIKELY(early)) {
369       nsmps -= early;
370       memset(&rp[nsmps], '\0', early*sizeof(MYFLT));
371     }
372    if (knfact == 0.0) { /* linear case */
373      if (UNLIKELY(klfact == 0.0)) { /* degenerated linear case */
374         m0 = (double)ip[0] - tm1;
375         rp[offset] = (MYFLT)(tm0);
376         for (n=offset+1; n<nsmps; n++) {
377           rp[n] = (MYFLT)(m0);
378           m0 = (double)ip[n];
379         }
380         tm1 = 0.0;
381         tm0 = m0;
382       }
383       else { /* normal linear case */
384         for (n=offset; n<nsmps; n++) {
385           m0 = (double)ip[n] - tm1;
386           m1 = m0 * klfact;
387           rp[n] = (MYFLT)(tm0 + m1);
388           tm1 = m1;
389           tm0 = m0;
390         }
391       }
392     } else { /* non-linear case */
393      if (UNLIKELY(klfact == 0.0)) { /* simplified non-linear case */
394         for (n=offset; n<nsmps; n++) {
395           m0 = (double)ip[n] - tm1;
396           m1 = fabs(m0) * knfact;
397           rp[n] = (MYFLT)(tm0 + m1);
398           tm1 = m1;
399           tm0 = m0;
400         }
401       } else { /* normal non-linear case */
402         for (n=offset; n<nsmps; n++) {
403           m0 = (double)ip[n] - tm1;
404           m1 = m0 * klfact + fabs(m0) * knfact;
405           rp[n] = (MYFLT)(tm0 + m1);
406           tm1 = m1;
407           tm0 = m0;
408         }
409       }
410     }
411     p->m0 = tm0;
412     p->m1 = tm1;
413     return OK;
414 }
415 
416 /* ----------------------------------------------- */
417 
adsynt2_set(CSOUND * csound,ADSYNT2 * p)418 static int32_t adsynt2_set(CSOUND *csound,ADSYNT2 *p)
419 {
420     FUNC    *ftp;
421     uint32_t count;
422     int32   *lphs;
423     MYFLT    iphs = *p->iphs;
424 
425     p->inerr = 0;
426 
427     if (LIKELY((ftp = csound->FTFind(csound, p->ifn)) != NULL)) {
428       p->ftp = ftp;
429     }
430     else {
431       p->inerr = 1;
432       return csound->InitError(csound, Str("adsynt2: wavetable not found!"));
433     }
434 
435     count = (uint32_t)*p->icnt;
436     if (UNLIKELY(count < 1)) count = 1;
437     p->count = count;
438 
439     if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifreqtbl)) != NULL)) {
440       p->freqtp = ftp;
441     }
442     else {
443       p->inerr = 1;
444       return csound->InitError(csound, Str("adsynt2: freqtable not found!"));
445     }
446     if (UNLIKELY(ftp->flen < count)) {
447       p->inerr = 1;
448       return csound->InitError(csound,
449                                Str("adsynt2: partial count is greater "
450                                    "than freqtable size!"));
451     }
452 
453     if (LIKELY((ftp = csound->FTnp2Find(csound, p->iamptbl)) != NULL)) {
454       p->amptp = ftp;
455     }
456     else {
457       p->inerr = 1;
458       return csound->InitError(csound, Str("adsynt2: amptable not found!"));
459     }
460     if (UNLIKELY(ftp->flen < count)) {
461       p->inerr = 1;
462       return csound->InitError(csound,
463                                Str("adsynt2: partial count is greater "
464                                    "than amptable size!"));
465     }
466 
467     if (p->lphs.auxp==NULL ||
468         p->lphs.size < sizeof(int32)*count)
469       csound->AuxAlloc(csound, sizeof(int32)*count, &p->lphs);
470     lphs = (int32*)p->lphs.auxp;
471 
472     if (iphs > 1) {
473       uint32_t c;
474       for (c=0; c<count; c++) {
475         lphs[c] = ((int32)
476                    ((MYFLT) ((double) (csound->Rand31(&(csound->randSeed1)) - 1)
477                              / 2147483645.0) * FMAXLEN)) & PHMASK;
478       }
479     }
480     else if (iphs >= 0) {
481       uint32_t c;
482       for (c=0; c<count; c++) {
483         lphs[c] = ((int32)(iphs * FMAXLEN)) & PHMASK;
484       }
485     }
486     if (p->pamp.auxp==NULL ||
487         p->pamp.size < (uint32_t)(sizeof(MYFLT)*p->count))
488       csound->AuxAlloc(csound, sizeof(MYFLT)*p->count, &p->pamp);
489     else  if (iphs >= 0)        /* AuxAlloc clear anyway */
490       memset(p->pamp.auxp, 0, sizeof(MYFLT)*p->count);
491     return OK;
492 }
493 
adsynt2(CSOUND * csound,ADSYNT2 * p)494 static int32_t adsynt2(CSOUND *csound,ADSYNT2 *p)
495 {
496     FUNC    *ftp, *freqtp, *amptp;
497     MYFLT   *ar, *ftbl, *freqtbl, *amptbl, *prevAmp;
498     MYFLT   amp0, amp, cps0, cps, ampIncr, amp2;
499     int32   phs, inc, lobits;
500     int32   *lphs;
501     int32_t     c, count;
502     uint32_t offset = p->h.insdshead->ksmps_offset;
503     uint32_t early  = p->h.insdshead->ksmps_no_end;
504     uint32_t n, nsmps = CS_KSMPS;
505 
506     /* I believe this can never happen as InitError will remove instance */
507     /* The check should be on p->amptp and p->freqtp  -- JPff            */
508     if (UNLIKELY(p->inerr || p->amptp==NULL || p->freqtp==NULL)) {
509       return csound->InitError(csound, Str("adsynt2: not initialised"));
510     }
511     ftp = p->ftp;
512     ftbl = ftp->ftable;
513     lobits = ftp->lobits;
514     freqtp = p->freqtp;
515     freqtbl = freqtp->ftable;
516     amptp = p->amptp;
517     amptbl = amptp->ftable;
518     lphs = (int32*)p->lphs.auxp;
519     prevAmp = (MYFLT*)p->pamp.auxp;
520 
521     cps0 = *p->kcps;
522     amp0 = *p->kamp;
523     count = p->count;
524 
525     ar = p->sr;
526     memset(ar, 0, nsmps*sizeof(MYFLT));
527     if (UNLIKELY(early)) {
528       nsmps -= early;
529       memset(&ar[nsmps], '\0', early*sizeof(MYFLT));
530     }
531 
532     for (c=0; c<count; c++) {
533       amp2 = prevAmp[c];
534       amp = amptbl[c] * amp0;
535       cps = freqtbl[c] * cps0;
536       inc = (int32) (cps * csound->sicvt);
537       phs = lphs[c];
538       ampIncr = (amp - amp2) * CS_ONEDKSMPS;
539       for (n=offset; n<nsmps; n++) {
540         ar[n] += *(ftbl + (phs >> lobits)) * amp2;
541         phs += inc;
542         phs &= PHMASK;
543         amp2 += ampIncr;
544       }
545       prevAmp[c] = amp;
546       lphs[c] = phs;
547     }
548     return OK;
549 }
550 
exitnow(CSOUND * csound,EXITNOW * p)551 static int32_t exitnow(CSOUND *csound, EXITNOW *p)
552 {
553     (void) p;
554     csound->LongJmp(csound, MYFLT2LRND(*p->retval));
555     return OK;  /* compiler only */
556 }
557 
tabrec_set(CSOUND * csound,TABREC * p)558 static int32_t tabrec_set(CSOUND *csound,TABREC *p)
559 {
560     IGN(csound);
561     p->recording = 0;
562     p->currtic = 0;
563     p->ndx = 0;
564     p->numins = p->INOCOUNT-4;
565     return OK;
566 }
567 
tabrec_k(CSOUND * csound,TABREC * p)568 static int32_t tabrec_k(CSOUND *csound,TABREC *p)
569 {
570     if (*p->ktrig_start) {
571       if (*p->kfn != p->old_fn) {
572         int32_t flen;
573         if (UNLIKELY((flen = csoundGetTable(csound,&(p->table),
574                                             (int32_t)*p->kfn)) < 0))
575           return csound->PerfError(csound, &(p->h),
576                                    Str("Invalid ftable no. %f"), *p->kfn);
577         p->tablen = (int64_t) flen;
578         *(p->table++) = *p->numtics;
579         p->old_fn = *p->kfn;
580       }
581       p->recording = 1;
582       p->ndx = 0;
583       p->currtic = 0;
584     }
585     if (*p->ktrig_stop) {
586 
587       if (p->currtic >= *p->numtics) {
588         p->recording = 0;
589         return OK;
590       }
591       p->currtic++;
592     }
593     if (p->recording) {
594       int32_t j, curr_frame = p->ndx * p->numins;
595 
596       MYFLT *table = p->table;
597       MYFLT **inargs = p->inargs;
598       if (curr_frame + p->numins < p->tablen) {
599         /* record only if table is not full */
600         for (j = 0; j < p->numins; j++)
601           table[curr_frame + j] = *inargs[j];
602       }
603       (p->ndx)++;
604     }
605     return OK;
606 }
607 /*-------------------------*/
tabplay_set(CSOUND * csound,TABPLAY * p)608 static int32_t tabplay_set(CSOUND *csound,TABPLAY *p)
609 {
610     /*   FUNC *ftp; */
611     /* if ((ftp = csound->FTFind(p->ifn)) == NULL) { */
612     /*   csound->InitError(csound, Str("tabplay: incorrect table number")); */
613     /*   return; */
614     /* } */
615     /*  p->table = ftp->ftable; */
616     /*  p->tablen = ftp->flen; */
617     IGN(csound);
618     p->playing = 0;
619     p->currtic = 0;
620     p->ndx = 0;
621     p->numouts = p->INOCOUNT-3;
622     return OK;
623 }
624 
tabplay_k(CSOUND * csound,TABPLAY * p)625 static int32_t tabplay_k(CSOUND *csound,TABPLAY *p)
626 {
627     if (*p->ktrig) {
628       if (*p->kfn != p->old_fn) {
629         int32_t flen;
630         if (UNLIKELY((flen = csoundGetTable(csound, &(p->table),
631                                             (int32_t)*p->kfn)) < 0))
632           return csound->PerfError(csound, &(p->h),
633                                    Str("Invalid ftable no. %f"), *p->kfn);
634         p->tablen = (int64_t) flen;
635         p->currtic = 0;
636         p->ndx = 0;
637         *(p->table++) = *p->numtics;
638         p->old_fn = *p->kfn;
639       }
640       p->playing = 1;
641       if (p->currtic == 0)
642         p->ndx = 0;
643       if (p->currtic >= *p->numtics) {
644         p->playing = 0;
645         return OK;
646       }
647       p->currtic++;
648       p->currtic %= (int64_t) *p->numtics;
649 
650     }
651     if (p->playing) {
652       int32_t j, curr_frame = p->ndx * p->numouts;
653       MYFLT *table = p->table;
654       MYFLT **outargs = p->outargs;
655       if (UNLIKELY(curr_frame + p->numouts < p->tablen)) {
656         /* play only if ndx is inside table */
657         for (j = 0; j < p->numouts; j++)
658           *outargs[j] = table[curr_frame+j];
659       }
660       (p->ndx)++;
661     }
662     return OK;
663 }
664 
isChanged_set(CSOUND * csound,ISCHANGED * p)665 static int32_t isChanged_set(CSOUND *csound,ISCHANGED *p)
666 {
667      IGN(csound);
668     p->numargs = p->INOCOUNT;
669     memset(p->old_inargs, 0, sizeof(MYFLT)*p->numargs); /* Initialise */
670     p->cnt = 1;
671     return OK;
672 }
673 
isChanged(CSOUND * csound,ISCHANGED * p)674 static int32_t isChanged(CSOUND *csound,ISCHANGED *p)
675 {
676     IGN(csound);
677     MYFLT **inargs = p->inargs;
678     MYFLT *old_inargs = p->old_inargs;
679     int32_t numargs = p->numargs, ktrig = 0, j;
680 
681     if (LIKELY(p->cnt))
682       for (j =0; j< numargs; j++) {
683         if (*inargs[j] != old_inargs[j]) {
684           ktrig = 1;
685           break;
686         }
687       }
688 
689     if (ktrig || p->cnt==0) {
690       for (j =0; j< numargs; j++) {
691         old_inargs[j] = *inargs[j];
692       }
693     }
694     *p->ktrig = (MYFLT) ktrig;
695     p->cnt++;
696     return OK;
697 }
698 
isChanged2_set(CSOUND * csound,ISCHANGED * p)699 static int32_t isChanged2_set(CSOUND *csound,ISCHANGED *p)
700 {
701     int32_t res = isChanged_set(csound,p);
702     p->cnt = 0;
703     return res;
704 }
705 
706 /* changed in array */
isAChanged_set(CSOUND * csound,ISACHANGED * p)707 static int32_t isAChanged_set(CSOUND *csound, ISACHANGED *p)
708 {
709     int32_t size = 0, i;
710     ARRAYDAT *arr = p->chk;
711     //char *tmp;
712     for (i=0; i<arr->dimensions; i++) size += arr->sizes[i];
713     size *= arr->arrayMemberSize;
714     csound->AuxAlloc(csound, size, &p->old_chk);
715     /* tmp = (char*)p->old_chk.auxp; */
716     /* for (i=0; i<size; i++) tmp[i]=rand()&0xff; */
717     /* memset(p->old_chk.auxp, '\0', size); */
718     p->size = size;
719     p->cnt = 0;
720     return OK;
721 }
722 
723 
isAChanged(CSOUND * csound,ISACHANGED * p)724 static int32_t isAChanged(CSOUND *csound,ISACHANGED *p)
725 {
726      IGN(csound);
727     ARRAYDAT *chk = p->chk;
728     void *old_chk = p->old_chk.auxp;
729     int32_t size = p->size;
730     int32_t ktrig = memcmp(chk->data, old_chk, size);
731     memcpy(old_chk, chk->data, size);
732     *p->ktrig = (p->cnt && ktrig)?FL(1.0):FL(0.0);
733     p->cnt++;
734     return OK;
735 }
736 
737 
738 /* ------------------------- */
739 
partial_maximum_set(CSOUND * csound,P_MAXIMUM * p)740 static int32_t partial_maximum_set(CSOUND *csound,P_MAXIMUM *p)
741 {
742      IGN(csound);
743     int32_t flag = (int32_t) *p->imaxflag;
744     switch (flag) {
745     case 1:
746       p->max = 0; break;
747     case 2:
748       p->max = -FLT_MAX; break;
749     case 3:
750       p->max = FLT_MAX; break;
751     case 4:
752       p->max = 0; break;
753     }
754     p->counter = 0;
755     return OK;
756 }
757 
partial_maximum(CSOUND * csound,P_MAXIMUM * p)758 static int32_t partial_maximum(CSOUND *csound,P_MAXIMUM *p)
759 {
760     uint32_t offset = p->h.insdshead->ksmps_offset;
761     uint32_t early  = p->h.insdshead->ksmps_no_end;
762     uint32_t n, nsmps = CS_KSMPS;
763     int32_t flag = (int32_t) *p->imaxflag;
764     MYFLT *a = p->asig;
765     MYFLT max = p->max;
766     if (UNLIKELY(early)) nsmps -= early;
767     switch(flag) {
768     case 1: /* absolute maximum */
769       for (n=offset; n<nsmps; n++) {
770         MYFLT temp;
771         if ((temp = FABS(a[n])) > max) max = temp;
772       }
773       if (max > p->max) p->max = max;
774       break;
775     case 2: /* actual maximum */
776       for (n=offset; n<nsmps; n++) {
777         if (a[n] > max) max = a[n];
778       }
779       if (max > p->max) p->max = max;
780       break;
781     case 3: /* actual minimum */
782       for (n=offset; n<nsmps; n++) {
783         if (a[n] < max) max = a[n];
784       }
785       if (max < p->max) p->max = max;
786       break;
787     case 4: { /* average */
788         MYFLT temp = FL(0.0);
789         p->counter += nsmps;
790         for (n=offset; n<nsmps; n++) {
791           temp += a[n];
792         }
793         p->max += temp;
794       }
795       break;
796     default:
797       return csound->PerfError(csound, &(p->h),
798                                Str("max_k: invalid imaxflag value"));
799     }
800     if (*p->ktrig) {
801       switch (flag) {
802       case 4:
803         *p->kout = p->max / (MYFLT) p->counter;
804         p->counter = 0;
805         p->max = FL(0.0);
806       break;
807       case 1:
808         *p->kout = p->max;
809         p->max = 0; break;
810       case 2:
811         *p->kout = p->max;
812         p->max = -FLT_MAX; break;
813       case 3:
814         *p->kout = p->max;
815         p->max = FLT_MAX; break;
816       }
817     }
818     return OK;
819 }
820 
821 /* From fractals.c */
822 /* mandelbrot set scanner  */
mandel_set(CSOUND * csound,MANDEL * p)823 static int32_t mandel_set(CSOUND *csound,MANDEL *p)
824 {
825      IGN(csound);
826     p->oldx=-99999; /*probably unused values  */
827     p->oldy=-99999;
828     p->oldCount = -1;
829     return OK;
830 }
831 
mandel(CSOUND * csound,MANDEL * p)832 static int32_t mandel(CSOUND *csound,MANDEL *p)
833 {
834      IGN(csound);
835     MYFLT px=*p->kx, py=*p->ky;
836     if (*p->ktrig && (px != p->oldx || py != p->oldy)) {
837       int32_t maxIter = (int32_t) *p->kmaxIter, j;
838       MYFLT x=FL(0.0), y=FL(0.0), newx, newy;
839       for (j=0; j<maxIter; j++) {
840         newx = x*x - y*y + px;
841         newy = FL(2.0)*x*y + py;
842         x=newx;
843         y=newy;
844         if (x*x+y*y >= FL(4.0)) break;
845       }
846       p->oldx = px;
847       p->oldy = py;
848       if (p->oldCount != j) *p->koutrig = FL(1.0);
849       else *p->koutrig = FL(0.0);
850       *p->kr = (MYFLT) (p->oldCount = j);
851     }
852     else {
853       *p->kr = (MYFLT) p->oldCount;
854       *p->koutrig = FL(0.0);
855     }
856     return OK;
857 }
858 
859 #define S(x)    sizeof(x)
860 
861 OENTRY gab_localops[] = {
862   {"resonxk", S(KRESONX),    0, 3,   "k",    "kkkooo",
863                             (SUBR) krsnsetx, (SUBR) kresonx, NULL },
864   { "tab_i",S(FASTAB),       TR, 1,   "i",    "iio", (SUBR) fastabi, NULL, NULL },
865   { "tab",S(FASTAB),         TR, 3,   "a",    "xio",
866                             (SUBR) fastab_set, (SUBR) fastab },
867   { "tab.k",S(FASTAB),       TR, 3,   "k",    "kio",
868                             (SUBR) fastab_set, (SUBR)fastabk, NULL },
869   { "tabw_i",S(FASTAB),      TW, 1,   "",    "iiio", (SUBR) fastabiw, NULL, NULL },
870   { "tabw",S(FASTAB),        TW, 3,   "",    "kkio",
871                             (SUBR)fastab_set, (SUBR)fastabkw          },
872   { "tabw",S(FASTAB),        TW, 3,   "",    "aaio",
873                             (SUBR)fastab_set, (SUBR)fastabw     },
874   { "tb0_init", S(TB_INIT),  _QQ, 1,   "",      "i",    (SUBR)tab0_init},
875   { "tb1_init", S(TB_INIT),  _QQ, 1,   "",      "i",    (SUBR)tab1_init},
876   { "tb2_init", S(TB_INIT),  _QQ, 1,   "",      "i",    (SUBR)tab2_init},
877   { "tb3_init", S(TB_INIT),  _QQ, 1,   "",      "i",    (SUBR)tab3_init},
878   { "tb4_init", S(TB_INIT),  _QQ, 1,   "",      "i",    (SUBR)tab4_init},
879   { "tb5_init", S(TB_INIT),  _QQ, 1,   "",      "i",    (SUBR)tab5_init},
880   { "tb6_init", S(TB_INIT),  _QQ, 1,   "",      "i",    (SUBR)tab6_init},
881   { "tb7_init", S(TB_INIT),  _QQ, 1,   "",      "i",    (SUBR)tab7_init},
882   { "tb8_init", S(TB_INIT),  _QQ, 1,   "",      "i",    (SUBR)tab8_init},
883   { "tb9_init", S(TB_INIT),  _QQ, 1,   "",      "i",    (SUBR)tab9_init},
884   { "tb10_init", S(TB_INIT), _QQ, 1,   "",      "i",    (SUBR)tab10_init},
885   { "tb11_init", S(TB_INIT), _QQ, 1,   "",      "i",    (SUBR)tab11_init},
886   { "tb12_init", S(TB_INIT), _QQ, 1,   "",      "i",    (SUBR)tab12_init},
887   { "tb13_init", S(TB_INIT), _QQ, 1,   "",      "i",    (SUBR)tab13_init},
888   { "tb14_init", S(TB_INIT), _QQ, 1,   "",      "i",    (SUBR)tab14_init},
889   { "tb15_init", S(TB_INIT), _QQ, 1,   "",      "i",    (SUBR)tab15_init},
890   /* tbx_t (t-rate version removed here) */
891   { "tb0.i",      S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab0_i_tmp    },
892   { "tb1.i",      S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab1_i_tmp    },
893   { "tb2.i",      S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab2_i_tmp    },
894   { "tb3.i",      S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab3_i_tmp    },
895   { "tb4.i",      S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab4_i_tmp    },
896   { "tb5.i",      S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab5_i_tmp    },
897   { "tb6.i",      S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab6_i_tmp    },
898   { "tb7.i",      S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab7_i_tmp    },
899   { "tb8.i",      S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab8_i_tmp    },
900   { "tb9.i",      S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab9_i_tmp    },
901   { "tb10.i",     S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab10_i_tmp   },
902   { "tb11.i",     S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab11_i_tmp   },
903   { "tb12.i",     S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab12_i_tmp   },
904   { "tb13.i",     S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab13_i_tmp   },
905   { "tb14.i",     S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab14_i_tmp   },
906   { "tb15.i",     S(FASTB), _QQ|TR, 1,    "i",     "i", (SUBR) tab15_i_tmp   },
907   { "tb0.k",  S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab0_k_tmp  },
908   { "tb1.k",  S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab1_k_tmp  },
909   { "tb2.k",  S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab2_k_tmp  },
910   { "tb3.k",  S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab3_k_tmp  },
911   { "tb4.k",  S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab4_k_tmp  },
912   { "tb5.k",  S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab5_k_tmp  },
913   { "tb6.k",  S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab6_k_tmp  },
914   { "tb7.k",  S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab7_k_tmp  },
915   { "tb8.k",  S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab8_k_tmp  },
916   { "tb9.k",  S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab9_k_tmp  },
917   { "tb10.k", S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab10_k_tmp  },
918   { "tb11.k", S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab11_k_tmp  },
919   { "tb12.k", S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab12_k_tmp  },
920   { "tb13.k", S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab13_k_tmp  },
921   { "tb14.k", S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab14_k_tmp  },
922   { "tb15.k", S(FASTB), _QQ|TR, 2,  "k",    "k",    NULL, (SUBR) tab15_k_tmp  },
923   { "nlalp",  S(NLALP), 0,  3,  "a",    "akkoo",
924                             (SUBR) nlalp_set, (SUBR) nlalp   },
925   { "adsynt2",S(ADSYNT2),TR, 3,    "a",     "kkiiiio",
926                             (SUBR) adsynt2_set, (SUBR)adsynt2 },
927   { "exitnow",S(EXITNOW),   0, 1,    "",  "o", (SUBR) exitnow, NULL, NULL },
928 /* { "zr_i",  S(ZKR),     0, 1,  "i",  "i",  (SUBR)zread, NULL, NULL}, */
929 /* { "zr_k",  S(ZKR),     0, 2,  "k",  "k",  NULL, (SUBR)zread, NULL}, */
930 /* { "zr_a",  S(ZAR),     0, 3,  "a",  "a",  (SUBR)zaset, (SUBR)zar}, */
931 /* { "k_i",   S(ASSIGN),  0, 1,  "k",  "i",  (SUBR)assign}, */
932 /* { "k_t",   S(ASSIGN),  0, 2,  "k",  "t",  NULL, (SUBR)assign}, */
933 /* { "a_k",   S(INDIFF),  0, 3,  "a",  "k",  (SUBR)a_k_set, (SUBR)interp }, */
934   { "tabrec",   S(TABREC),  TW, 3,     "",      "kkkkz",
935                             (SUBR) tabrec_set, (SUBR) tabrec_k, NULL },
936   { "tabplay",  S(TABPLAY), TR, 3,     "",      "kkkz",
937                             (SUBR) tabplay_set, (SUBR) tabplay_k, NULL },
938   { "changed.k", S(ISCHANGED),  0, 3,     "k",     "z",
939                             (SUBR) isChanged_set, (SUBR)isChanged, NULL },
940   { "changed2.k", S(ISCHANGED), 0, 3,     "k",     "z",
941                             (SUBR) isChanged2_set, (SUBR)isChanged, NULL },
942   { "changed2.A", S(ISACHANGED), 0, 3,     "k",     ".[]",
943                             (SUBR) isAChanged_set, (SUBR)isAChanged, NULL },
944   { "max_k",  S(P_MAXIMUM), 0, 3,      "k",    "aki",
945             (SUBR) partial_maximum_set, (SUBR) partial_maximum },
946   { "mandel",S(MANDEL),     0, 3,      "kk",    "kkkk",
947                             (SUBR) mandel_set, (SUBR) mandel, NULL }
948 };
949 
gab_gab_init_(CSOUND * csound)950 int32_t gab_gab_init_(CSOUND *csound)
951 {
952     return csound->AppendOpcodes(csound, &(gab_localops[0]),
953                                  (int32_t) (sizeof(gab_localops) / sizeof(OENTRY)));
954 }
955 
956