1 /*
2     ugens3.c:
3 
4     Copyright (C) 1991 Barry Vercoe, John ffitch
5 
6     This file is part of Csound.
7 
8     The Csound Library is free software; you can redistribute it
9     and/or modify it under the terms of the GNU Lesser General Public
10     License as published by the Free Software Foundation; either
11     version 2.1 of the License, or (at your option) any later version.
12 
13     Csound is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU Lesser General Public License for more details.
17 
18     You should have received a copy of the GNU Lesser General Public
19     License along with Csound; if not, write to the Free Software
20     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21     02110-1301 USA
22 */
23 
24 #include "csoundCore.h"         /*                              UGENS3.C    */
25 #include "ugens3.h"
26 #include <math.h>
27 
foscset(CSOUND * csound,FOSC * p)28 int32_t foscset(CSOUND *csound, FOSC *p)
29 {
30     FUNC    *ftp;
31 
32     if (LIKELY((ftp = csound->FTFind(csound, p->ifn)) != NULL)) {
33       p->ftp = ftp;
34       if (*p->iphs >= 0)
35         p->cphs = p->mphs = (int32_t)(*p->iphs * FMAXLEN);
36       p->ampcod = IS_ASIG_ARG(p->xamp) ? 1 : 0;
37       p->carcod = IS_ASIG_ARG(p->xcar) ? 1 : 0;
38       p->modcod = IS_ASIG_ARG(p->xmod) ? 1 : 0;
39       return OK;
40     }
41     return NOTOK;
42 }
43 
foscil(CSOUND * csound,FOSC * p)44 int32_t foscil(CSOUND *csound, FOSC *p)
45 {
46     FUNC    *ftp;
47     MYFLT   *ar, *ampp, *modp, cps, amp;
48     MYFLT   xcar, xmod, *carp, car, fmod, cfreq, mod, ndx, *ftab;
49     int32_t    mphs, cphs, minc, cinc, lobits;
50     uint32_t offset = p->h.insdshead->ksmps_offset;
51     uint32_t early  = p->h.insdshead->ksmps_no_end;
52     uint32_t n, nsmps = CS_KSMPS;
53     MYFLT   sicvt = csound->sicvt;
54 
55     ar = p->rslt;
56     ftp = p->ftp;
57     if (UNLIKELY(ftp == NULL)) goto err1;
58     ftab = ftp->ftable;
59     lobits = ftp->lobits;
60     mphs = p->mphs;
61     cphs = p->cphs;
62     ampp = p->xamp;
63     cps  = *p->kcps;
64     carp = p->xcar;
65     modp = p->xmod;
66     amp  = *ampp;
67     xcar = *carp;
68     xmod = *modp;
69     if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT));
70     if (UNLIKELY(early)) {
71       nsmps -= early;
72       memset(&ar[nsmps], '\0', early*sizeof(MYFLT));
73     }
74 
75     if (p->ampcod || p->carcod || p->modcod) {
76       for (n=offset;n<nsmps;n++) {
77         if (p->ampcod) amp = ampp[n];
78         if (p->carcod) xcar = carp[n];
79         if (p->modcod) xmod = modp[n];
80         car = cps * xcar;
81         mod = cps * xmod;
82         ndx = *p->kndx * mod;
83         minc = (int32_t)(mod * sicvt);
84         mphs &= PHMASK;
85         fmod = *(ftab + (mphs >>lobits)) * ndx;
86         mphs += minc;
87         cfreq = car + fmod;
88         cinc = (int32_t)(cfreq * sicvt);
89         cphs &= PHMASK;
90         ar[n] = *(ftab + (cphs >>lobits)) * amp;
91         cphs += cinc;
92       }
93     }
94     else {
95       MYFLT amp = *ampp;
96       cps = *p->kcps;
97       car = cps * *carp;
98       mod = cps * *modp;
99       ndx = *p->kndx * mod;
100       minc = (int32_t)(mod * sicvt);
101       for (n=offset;n<nsmps;n++) {
102         mphs &= PHMASK;
103         fmod = *(ftab + (mphs >>lobits)) * ndx;
104         mphs += minc;
105         cfreq = car + fmod;
106         cinc = (int32_t)(cfreq * sicvt);
107         cphs &= PHMASK;
108         ar[n] = *(ftab + (cphs >>lobits)) * amp;
109         cphs += cinc;
110       }
111     }
112     p->mphs = mphs;
113     p->cphs = cphs;
114 
115     return OK;
116  err1:
117     return csound->PerfError(csound, &(p->h),
118                              Str("foscil: not initialised"));
119 }
120 
foscili(CSOUND * csound,FOSC * p)121 int32_t foscili(CSOUND *csound, FOSC *p)
122 {
123     FUNC   *ftp;
124     MYFLT  *ar, *ampp, amp, cps, fract, v1, car, fmod, cfreq, mod;
125     MYFLT  *carp, *modp, xcar, xmod, ndx, *ftab;
126     int32_t  mphs, cphs, minc, cinc, lobits;
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     MYFLT  sicvt = csound->sicvt;
131     MYFLT  *ft;
132 
133     ar = p->rslt;
134     ftp = p->ftp;
135     if (UNLIKELY(ftp == NULL)) goto err1;        /* RWD fix */
136     ft = ftp->ftable;
137     lobits = ftp->lobits;
138     mphs = p->mphs;
139     cphs = p->cphs;
140     ampp = p->xamp;
141     cps  = *p->kcps;
142     carp = p->xcar;
143     modp = p->xmod;
144     amp  = *ampp;
145     xcar = *carp;
146     xmod = *modp;
147     if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT));
148     if (UNLIKELY(early)) {
149       nsmps -= early;
150       memset(&ar[nsmps], '\0', early*sizeof(MYFLT));
151     }
152     if (p->ampcod || p->carcod || p->modcod) {
153       for (n=offset;n<nsmps;n++) {
154         if (p->ampcod)  amp = ampp[n];
155         if (p->carcod)  xcar = carp[n];
156         if (p->modcod)  xmod = modp[n];
157         car = cps * xcar;
158         mod = cps * xmod;
159         ndx = *p->kndx * mod;
160         minc = (int32_t)(mod * sicvt);
161         mphs &= PHMASK;
162         fract = PFRAC(mphs);
163         ftab = ft + (mphs >>lobits);
164         v1 = *ftab++;
165         fmod = (v1 + (*ftab - v1) * fract) * ndx;
166         mphs += minc;
167         cfreq = car + fmod;
168         cinc = (int32_t)(cfreq * sicvt);
169         cphs &= PHMASK;
170         fract = PFRAC(cphs);
171         ftab = ft + (cphs >>lobits);
172         v1 = *ftab++;
173         ar[n] = (v1 + (*ftab - v1) * fract) * amp;
174         cphs += cinc;
175       }
176     }
177     else {
178       cps = *p->kcps;
179       car = cps * *carp;
180       mod = cps * *modp;
181       ndx = *p->kndx * mod;
182       minc = (int32_t)(mod * sicvt);
183       for (n=offset;n<nsmps;n++) {
184         mphs &= PHMASK;
185         fract = PFRAC(mphs);
186         ftab = ft + (mphs >>lobits);
187         v1 = *ftab++;
188         fmod = (v1 + (*ftab - v1) * fract) * ndx;
189         mphs += minc;
190         cfreq = car + fmod;
191         cinc = (int32_t)(cfreq * sicvt);
192         cphs &= PHMASK;
193         fract = PFRAC(cphs);
194         ftab = ft + (cphs >>lobits);
195         v1 = *ftab++;
196         ar[n] = (v1 + (*ftab - v1) * fract) * amp;
197         cphs += cinc;
198       }
199     }
200     p->mphs = mphs;
201     p->cphs = cphs;
202 
203     return OK;
204  err1:
205     return csound->PerfError(csound, &(p->h),
206                              Str("foscili: not initialised"));
207 }
208 
209 
losset(CSOUND * csound,LOSC * p)210 int32_t losset(CSOUND *csound, LOSC *p)
211 {
212     FUNC    *ftp;
213     if ((ftp = csound->FTnp2Finde(csound,p->ifn)) != NULL) {
214       uint32 maxphs = ftp->flenfrms;
215       //printf("****maxphs = %d (%x)\n", maxphs, maxphs);
216       //printf("****ftp cvtbas = %g ibas = %g\n", ftp->cvtbas, *p->ibas);
217       p->ftp = ftp;
218       if (*p->ibas != FL(0.0))
219         p->cpscvt = (ftp->cvtbas / *p->ibas)/LOFACT;
220       else if (UNLIKELY((p->cpscvt = ftp->cpscvt) == FL(0.0))) {
221         p->cpscvt = FL(1.0) /FL(261.62556530059862592); /* Middle C */
222         csound->Warning(csound, Str("no legal base frequency"));
223       }
224       else p->cpscvt /= LOFACT;
225       //printf("****cpscvt = %g\n", p->cpscvt);
226       if ((p->mod1 = (int16) *p->imod1) < 0) {
227         if (UNLIKELY((p->mod1 = ftp->loopmode1) == 0)) {
228           csound->Warning(csound, Str("loscil: sustain defers to "
229                                       "non-looping source"));
230         }
231         p->beg1 = ftp->begin1;
232         p->end1 = ftp->end1;
233       }
234       else if (UNLIKELY(p->mod1 < 0 || p->mod1 > 3))
235         goto lerr2;
236       else {
237         p->beg1 = *p->ibeg1;
238         p->end1 = *p->iend1;
239         if (!p->beg1 && !p->end1)
240           /* default to looping the whole sample */
241           p->end1 =            /* These are the same!! */
242             (p->mod1 ? (MYFLT)maxphs : (MYFLT)ftp->flenfrms);
243         else if (UNLIKELY(p->beg1 < 0 ||
244                           p->end1 > maxphs ||
245                           p->beg1 >= p->end1)) {
246           csound->Message(csound, "beg: %g, end = %g, maxphs = %d\n",
247                           p->beg1, p->end1, maxphs);
248           goto lerr2;
249         }
250       }
251       if ((p->mod2 = (int16) *p->imod2) < 0) {
252         p->mod2 = ftp->loopmode2;
253         p->beg2 = ftp->begin2;
254         p->end2 = ftp->end2;
255       }
256       else {
257         p->beg2 = *p->ibeg2;
258         p->end2 = *p->iend2;
259         if (UNLIKELY(p->mod2 < 0 || p->mod2 > 3 ||
260                      p->beg2 < 0 || p->end2 > (int32_t)maxphs ||
261                      p->beg2 >= p->end2)) {
262           goto lerr3;
263         }
264       }
265       p->beg1 = (p->beg1 >= 0L ? p->beg1 : 0L);
266       p->end1 = (p->end1 < (int32_t)maxphs ? p->end1 : (int32_t)maxphs);
267       if (UNLIKELY(p->beg1 >= p->end1)) {
268         p->mod1 = 0;
269         p->beg1 = 0L;
270         p->end1 = maxphs;
271       }
272       p->beg2 = (p->beg2 >= 0L ? p->beg2 : 0L);
273       p->end2 = (p->end2 < (int32_t)maxphs ? p->end2 : (int32_t)maxphs);
274       if (UNLIKELY(p->beg2 >= p->end2)) {
275         p->mod2 = 0;
276         p->beg2 = 0L;
277       }
278       if (!p->mod2 && !p->end2)       /* if no release looping */
279         p->end2 = maxphs;             /*   set a reading limit */
280       p->lphs = 0;
281       p->seg1 = 1;
282       if ((p->curmod = p->mod1))
283         p->looping = 1;
284       else p->looping = 0;
285       if (p->OUTOCOUNT == 1) {
286         p->stereo = 0;
287         if (UNLIKELY(ftp->nchanls != 1))
288           return csound->InitError(csound, Str(
289                                "mono loscil cannot read from stereo ftable"));
290       }
291       else {
292         p->stereo = 1;
293         if (UNLIKELY(ftp->nchanls != 2))
294           return csound->InitError(csound, Str(
295                                "stereo loscil cannot read from mono ftable"));
296       }
297       return OK;
298     }
299     return NOTOK;
300 
301  lerr2:
302     return csound->InitError(csound, Str("illegal sustain loop data"));
303  lerr3:
304     return csound->InitError(csound, Str("illegal release loop data"));
305 }
306 
losset_phs(CSOUND * csound,LOSCPHS * p)307 int32_t losset_phs(CSOUND *csound, LOSCPHS *p)
308 {
309     FUNC    *ftp;
310     if ((ftp = csound->FTnp2Finde(csound,p->ifn)) != NULL) {
311       uint32 maxphs = ftp->flenfrms;
312       //printf("****maxphs = %d (%x)\n", maxphs, maxphs);
313       p->ftp = ftp;
314       if (*p->ibas != FL(0.0))
315         p->cpscvt = (ftp->cvtbas / *p->ibas)/LOFACT;
316       else if (UNLIKELY((p->cpscvt = ftp->cpscvt) == FL(0.0))) {
317         p->cpscvt = FL(1.0) /FL(261.62556530059862592); /* Middle C */
318         csound->Warning(csound, Str("no legal base frequency"));
319       }
320       else p->cpscvt /= LOFACT;
321       //printf("****cpscvt = %g\n", p->cpscvt);
322       if ((p->mod1 = (int16) *p->imod1) < 0) {
323         if (UNLIKELY((p->mod1 = ftp->loopmode1) == 0)) {
324           csound->Warning(csound, Str("loscil: sustain defers to "
325                                       "non-looping source"));
326         }
327         p->beg1 = ftp->begin1;
328         p->end1 = ftp->end1;
329       }
330       else if (UNLIKELY(p->mod1 < 0 || p->mod1 > 3))
331         goto lerr2;
332       else {
333         p->beg1 = *p->ibeg1;
334         p->end1 = *p->iend1;
335         if (!p->beg1 && !p->end1)
336           /* default to looping the whole sample */
337           p->end1 =            /* These are the same!! */
338             (p->mod1 ? (MYFLT)maxphs : (MYFLT)ftp->flenfrms);
339         else if (UNLIKELY(p->beg1 < 0 ||
340                           p->end1 > maxphs ||
341                           p->beg1 >= p->end1)) {
342           csound->Message(csound, "beg: %g, end = %g, maxphs = %d\n",
343                           p->beg1, p->end1, maxphs);
344           goto lerr2;
345         }
346       }
347       if ((p->mod2 = (int16) *p->imod2) < 0) {
348         p->mod2 = ftp->loopmode2;
349         p->beg2 = ftp->begin2;
350         p->end2 = ftp->end2;
351       }
352       else {
353         p->beg2 = *p->ibeg2;
354         p->end2 = *p->iend2;
355         if (UNLIKELY(p->mod2 < 0 || p->mod2 > 3 ||
356                      p->beg2 < 0 || p->end2 > (int32_t)maxphs ||
357                      p->beg2 >= p->end2)) {
358           goto lerr3;
359         }
360       }
361       p->beg1 = (p->beg1 >= 0L ? p->beg1 : 0L);
362       p->end1 = (p->end1 < (int32_t)maxphs ? p->end1 : (int32_t)maxphs);
363       if (UNLIKELY(p->beg1 >= p->end1)) {
364         p->mod1 = 0;
365         p->beg1 = 0L;
366         p->end1 = maxphs;
367       }
368       p->beg2 = (p->beg2 >= 0L ? p->beg2 : 0L);
369       p->end2 = (p->end2 < (int32_t)maxphs ? p->end2 : (int32_t)maxphs);
370       if (UNLIKELY(p->beg2 >= p->end2)) {
371         p->mod2 = 0;
372         p->beg2 = 0L;
373       }
374       if (!p->mod2 && !p->end2)       /* if no release looping */
375         p->end2 = maxphs;             /*   set a reading limit */
376       p->lphs = 0;
377       p->seg1 = 1;
378       if ((p->curmod = p->mod1))
379         p->looping = 1;
380       else p->looping = 0;
381       if (p->OUTOCOUNT == 2) {
382         p->stereo = 0;
383         if (UNLIKELY(ftp->nchanls != 1))
384           return csound->InitError(csound, Str(
385                                "mono loscilphs cannot read from stereo ftable"));
386       }
387       else if (p->OUTOCOUNT == 3)
388         {
389           p->stereo = 1;
390           if (UNLIKELY(ftp->nchanls != 2))
391             return csound->InitError(csound, Str(
392                                "stereo loscilphs cannot read from mono ftable"));
393         }
394       else {
395         return csound->InitError(csound, Str(
396                                "loscilphs: insufficient outputs"));
397       }
398       return OK;
399     }
400     return NOTOK;
401 
402  lerr2:
403     return csound->InitError(csound, Str("illegal sustain loop data"));
404  lerr3:
405     return csound->InitError(csound, Str("illegal release loop data"));
406 }
407 
loscil_linear_interp_mono(MYFLT * ar,MYFLT * ftbl,MYFLT phs,int32_t flen)408 static inline void loscil_linear_interp_mono(MYFLT *ar,
409                                              MYFLT *ftbl, MYFLT phs, int32_t flen)
410 {
411     MYFLT   fract, tmp;
412     int32_t   x;
413 
414     fract = MODF(phs, &tmp);
415     x = (int32_t) tmp;
416     //printf("phs=%d+%f\n",x, fract);
417     tmp = ftbl[x];
418     x = (x < flen ? (x + 1) : flen);
419     *ar = tmp + ((ftbl[x] - tmp) * fract);
420 }
421 
loscil_linear_interp_stereo(MYFLT * arL,MYFLT * arR,MYFLT * ftbl,MYFLT phs,int32_t flen)422 static inline void loscil_linear_interp_stereo(MYFLT *arL, MYFLT *arR,
423                                                MYFLT *ftbl, MYFLT phs, int32_t flen)
424 {
425     MYFLT   fract, tmpL, tmpR;
426     int     x;
427 
428     fract = MODF(phs, &tmpL);
429     x = (int32_t) 2*tmpL;
430     //printf("phs=%d+%f\n",x, fract);
431     tmpL = ftbl[x];
432     tmpR = ftbl[x + 1];
433     x = (x < ((int32_t) flen - 1) ? (x + 2) : ((int32_t) flen - 1));
434     *arL = tmpL + ((ftbl[x] - tmpL) * fract);
435     *arR = tmpR + ((ftbl[x + 1] - tmpR) * fract);
436 }
437 
loscil_cubic_interp_mono(MYFLT * ar,MYFLT * ftbl,MYFLT phs,int32_t flen)438 static inline void loscil_cubic_interp_mono(MYFLT *ar,
439                                             MYFLT *ftbl, MYFLT phs, int32_t flen)
440 {
441     MYFLT   fract, tmp, a0, a1, a2, a3;
442     int32_t     x;
443 
444     fract = MODF(phs, &tmp);
445     x = (int32_t) tmp;
446     //printf("phs=%d+%f\n",x, fract);
447     a3 = fract * fract; a3 -= FL(1.0); a3 *= (FL(1.0) / FL(6.0));
448     a2 = fract; a2 += FL(1.0); a0 = (a2 *= FL(0.5)); a0 -= FL(1.0);
449     a1 = FL(3.0) * a3; a2 -= a1; a0 -= a3; a1 -= fract;
450     a0 *= fract; a1 *= fract; a2 *= fract; a3 *= fract; a1 += FL(1.0);
451     tmp = ftbl[(x >= 0 ? x : 0)] * a0;
452     tmp += ftbl[++x] * a1;
453     x++;
454     tmp += ftbl[(x < (int32_t) flen ? x : (int32_t) flen)] * a2;
455     x++;
456     tmp += ftbl[(x < (int32_t) flen ? x : (int32_t) flen)] * a3;
457     *ar = tmp;
458 }
459 
460 static CS_NOINLINE void
loscil_cubic_interp_stereo(MYFLT * arL,MYFLT * arR,MYFLT * ftbl,MYFLT phs,int32_t flen)461     loscil_cubic_interp_stereo(MYFLT *arL, MYFLT *arR,
462                                MYFLT *ftbl, MYFLT phs, int32_t flen)
463 {
464     MYFLT   fract, tmpL, tmpR, a0, a1, a2, a3;
465     int32_t     x;
466 
467     fract = MODF(phs, &tmpL);
468     x = (int32_t) 2*tmpL;
469     //printf("phs=%d+%f\n",x, fract);
470     a3 = fract * fract; a3 -= FL(1.0); a3 *= (FL(1.0) / FL(6.0));
471     a2 = fract; a2 += FL(1.0); a0 = (a2 *= FL(0.5)); a0 -= FL(1.0);
472     a1 = FL(3.0) * a3; a2 -= a1; a0 -= a3; a1 -= fract;
473     a0 *= fract; a1 *= fract; a2 *= fract; a3 *= fract; a1 += FL(1.0);
474     tmpL = ftbl[(x >= 0 ? x : 0)] * a0;
475     tmpR = ftbl[(x >= 0 ? (x + 1) : 1)] * a0;
476     x += 2;
477     tmpL += ftbl[x] * a1;
478     tmpR += ftbl[x + 1] * a1;
479     x = (x < ((int32_t) flen - 1) ? (x + 2) : ((int32_t) flen - 1));
480     tmpL += ftbl[x] * a2;
481     tmpR += ftbl[x + 1] * a2;
482     x = (x < ((int32_t) flen - 1) ? (x + 2) : ((int32_t) flen - 1));
483     tmpL += ftbl[x] * a3;
484     tmpR += ftbl[x + 1] * a3;
485     *arL = tmpL;
486     *arR = tmpR;
487 }
488 
489 /* *********************** needs total rewrite **************** */
loscil(CSOUND * csound,LOSC * p)490 int32_t loscil(CSOUND *csound, LOSC *p)
491 {
492     IGN(csound);
493     FUNC    *ftp;
494     MYFLT   *ar1, *ar2, *ftbl, *xamp;
495     MYFLT    phs;
496     MYFLT    inc, beg, end;
497     uint32_t n = p->h.insdshead->ksmps_offset;
498     uint32_t early  = p->h.insdshead->ksmps_no_end;
499     uint32_t nsmps = CS_KSMPS;
500     int32_t      aamp;
501     MYFLT    xx;
502 
503     ftp = p->ftp;
504     ftbl = ftp->ftable;
505     if ((inc = (*p->kcps * p->cpscvt)) < 0)
506       inc = -inc;
507     //printf("inc: %lf * %lf = %lf\n", *p->kcps, p->cpscvt, inc);
508     xamp = p->xamp;
509     xx = *xamp;
510     aamp = IS_ASIG_ARG(p->xamp) ? 1 : 0;
511     if (p->seg1) {                      /* if still segment 1  */
512       beg = p->beg1;
513       end = p->end1;
514       if (UNLIKELY(p->h.insdshead->relesing))     /*    sense note_off   */
515         p->looping = 0;
516     }
517     else {
518       beg = p->beg2;
519       end = p->end2;
520     }
521     phs = p->lphs;
522     ar1 = p->ar1;
523     if (UNLIKELY(n)) memset(ar1, '\0', n*sizeof(MYFLT));
524     if (UNLIKELY(early)) {
525       nsmps -= early;
526       memset(&ar1[nsmps], '\0', early*sizeof(MYFLT));
527     }
528     if (p->stereo) {
529       ar2 = p->ar2;
530       if (UNLIKELY(n)) memset(ar2, '\0', n*sizeof(MYFLT));
531       if (UNLIKELY(early)) memset(&ar2[nsmps], '\0', early*sizeof(MYFLT));
532       goto phsck2;
533     }
534  phschk:
535     if (phs >= end && p->curmod != 3) {
536       //printf("****phs = %f end = %f\n", phs,end);
537       goto put0;
538     }
539     switch (p->curmod) {
540     case 0:
541       for (; n<nsmps; n++) {                    /* NO LOOPING  */
542         loscil_linear_interp_mono(&ar1[n], ftbl, phs, ftp->flen);
543         if (aamp) xx = xamp[n];
544         ar1[n] *= xx;
545         if ((phs += inc) >= end) {
546           //printf("****phs, end = %f, %f\n", phs, end);
547           goto nxtseg;
548         }
549       }
550       break;
551     case 1:
552       for (; n<nsmps; n++) {                    /* NORMAL LOOPING */
553         loscil_linear_interp_mono(&ar1[n], ftbl, phs, ftp->flen);
554         if (aamp) xx = xamp[n];
555         ar1[n] *= xx;
556         if (UNLIKELY((phs += inc) >= end)) {
557           if (!(p->looping)) goto nxtseg;
558           phs -= end - beg;
559         }
560       }
561       break;
562     case 2:
563     case2:
564       for (; n<nsmps; n++) {                    /* BIDIR FORW, EVEN */
565         loscil_linear_interp_mono(&ar1[n], ftbl, phs, ftp->flen);
566         if (aamp) xx = xamp[n];
567         ar1[n] *= xx;
568         if ((phs += inc) >= end) {
569           if (!(p->looping)) goto nxtseg;
570           phs -= (phs - end) * 2;
571           p->curmod = 3;
572           if (++n<nsmps) goto case3;
573           else break;
574         }
575       }
576       break;
577     case 3:
578     case3:
579       for (; n<nsmps; n++) {                    /* BIDIR BACK, EVEN */
580         loscil_linear_interp_mono(&ar1[n], ftbl, phs, ftp->flen);
581         if (aamp) xx = xamp[n];
582         ar1[n] *= xx;
583         if (UNLIKELY((phs -= inc) < beg)) {
584           phs += (beg - phs) * 2;
585           p->curmod = 2;
586           if (++n<nsmps) goto case2;
587           else break;
588         }
589       }
590       break;
591 
592     nxtseg:
593       if (p->seg1) {
594         p->seg1 = 0;
595         if ((p->curmod = p->mod2) != 0)
596           p->looping = 1;
597         if (++n>nsmps) {
598           beg = p->beg2;
599           end = p->end2;
600           p->lphs = phs;
601           goto phschk;
602         }
603         break;
604       }
605       if (LIKELY(++n<nsmps)) goto phsout;
606       break;
607     }
608     p->lphs = phs;
609     return OK;
610 
611  phsout:
612     p->lphs = phs;
613 put0:
614     //printf("****put0\n");
615     memset(&ar1[n], '\0', sizeof(MYFLT)*(nsmps-n));
616     return OK;
617 
618  phsck2:
619     /*VL increment for stereo */
620     if (phs >= end && p->curmod != 3)
621       goto put0s;                               /* for STEREO:  */
622     switch (p->curmod) {
623     case 0:
624       for (; n<nsmps; n++) {                    /* NO LOOPING  */
625         loscil_linear_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
626         if (aamp) xx = xamp[n];
627         ar1[n] *= xx;
628         ar2[n] *= xx;
629         if (UNLIKELY((phs += inc) >= end))
630           goto nxtseg2;
631       }
632       break;
633     case 1:
634       for (; n<nsmps; n++) {                    /* NORMAL LOOPING */
635         loscil_linear_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
636         if (aamp) xx = xamp[n];
637         ar1[n] *= xx;
638         ar2[n] *= xx;
639         if (UNLIKELY((phs += inc) >= end)) {
640           if (!(p->looping)) goto nxtseg2;
641           phs -= end - beg;
642         }
643       }
644       break;
645     case 2:
646     case2s:
647       for (; n<nsmps; n++) {                    /* BIDIR FORW, EVEN */
648         loscil_linear_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
649         if (aamp) xx = xamp[n];
650         ar1[n] *= xx;
651         ar2[n] *= xx;
652         if (UNLIKELY((phs += inc) >= end)) {
653           if (!(p->looping)) goto nxtseg2;
654           phs -= (phs - end) * 2;
655           p->curmod = 3;
656           if (++n<nsmps) goto case3s;
657           else break;
658         }
659       }
660       break;
661     case 3:
662     case3s:
663       for (; n<nsmps; n++) {                    /* BIDIR BACK, EVEN */
664        loscil_linear_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
665         if (aamp) xx = xamp[n];
666         ar1[n] *= xx;
667         ar2[n] *= xx;
668         if (UNLIKELY((phs -= inc) < beg)) {
669           phs += (beg - phs) * 2;
670           p->curmod = 2;
671           if (++n<nsmps) goto case2s;
672           else break;
673         }
674       }
675       break;
676 
677     nxtseg2:
678       if (p->seg1) {
679         p->seg1 = 0;
680         if ((p->curmod = p->mod2) != 0)
681           p->looping = 1;
682         if (++n<nsmps) {
683           beg = p->beg2;
684           end = p->end2;
685           p->lphs = phs;
686           goto phsck2;
687         }
688         break;
689       }
690       if (LIKELY(++n<nsmps)) goto phsout2;
691       break;
692     }
693     p->lphs = phs;
694     return OK;
695 
696  phsout2:
697     p->lphs = phs;
698  put0s:
699     memset(&ar1[n], '\0', sizeof(MYFLT)*(nsmps-n));
700     memset(&ar2[n], '\0', sizeof(MYFLT)*(nsmps-n));
701     return OK;
702 }
703 
704 
loscil_phs(CSOUND * csound,LOSCPHS * p)705 int32_t loscil_phs(CSOUND *csound, LOSCPHS *p)
706 {
707     IGN(csound);
708     FUNC    *ftp;
709     MYFLT   *ar1, *ar2, *ftbl, *xamp, *sphs;
710     MYFLT    phs;
711     MYFLT    inc, beg, end;
712     uint32_t n = p->h.insdshead->ksmps_offset;
713     uint32_t early  = p->h.insdshead->ksmps_no_end;
714     uint32_t nsmps = CS_KSMPS;
715     int32_t      aamp;
716     MYFLT    xx;
717 
718     ftp = p->ftp;
719     ftbl = ftp->ftable;
720     if ((inc = (*p->kcps * p->cpscvt)) < 0)
721       inc = -inc;
722     xamp = p->xamp;
723     xx = *xamp;
724     aamp = IS_ASIG_ARG(p->xamp) ? 1 : 0;
725     if (p->seg1) {                      /* if still segment 1  */
726       beg = p->beg1;
727       end = p->end1;
728       if (UNLIKELY(p->h.insdshead->relesing))     /*    sense note_off   */
729         p->looping = 0;
730     }
731     else {
732       beg = p->beg2;
733       end = p->end2;
734     }
735     phs = p->lphs;
736     ar1 = p->ar1;
737     sphs = p->sphs;
738     if (UNLIKELY(n)) memset(ar1, '\0', n*sizeof(MYFLT));
739     if (UNLIKELY(early)) {
740       nsmps -= early;
741       memset(&ar1[nsmps], '\0', early*sizeof(MYFLT));
742       memset(&sphs[nsmps], '\0', early*sizeof(MYFLT));
743     }
744     if (p->stereo) {
745       ar2 = p->ar2;
746       if (UNLIKELY(n)) memset(ar2, '\0', n*sizeof(MYFLT));
747       if (UNLIKELY(early)) memset(&ar2[nsmps], '\0', early*sizeof(MYFLT));
748       goto phsck2;
749     }
750  phschk:
751     if (phs >= end && p->curmod != 3) {
752       //printf("****phs = %f end = %d\n", phs,end);
753       goto put0;
754     }
755     switch (p->curmod) {
756     case 0:
757       for (; n<nsmps; n++) {                    /* NO LOOPING  */
758         loscil_linear_interp_mono(&ar1[n], ftbl, phs, ftp->flen);
759         if (aamp) xx = xamp[n];
760         ar1[n] *= xx;
761         sphs[n] = phs/ftp->flen;
762         if ((phs += inc) >= end) {
763           //printf("****phs, end = %f, %d\n", phs, end);
764           goto nxtseg;
765         }
766       }
767       break;
768     case 1:
769       for (; n<nsmps; n++) {                    /* NORMAL LOOPING */
770         loscil_linear_interp_mono(&ar1[n], ftbl, phs, ftp->flen);
771         if (aamp) xx = xamp[n];
772         ar1[n] *= xx;
773         sphs[n] = phs/ftp->flen;
774         if (UNLIKELY((phs += inc) >= end)) {
775           if (!(p->looping)) goto nxtseg;
776           phs -= end - beg;
777         }
778       }
779       break;
780     case 2:
781     case2:
782       for (; n<nsmps; n++) {                    /* BIDIR FORW, EVEN */
783         loscil_linear_interp_mono(&ar1[n], ftbl, phs, ftp->flen);
784         if (aamp) xx = xamp[n];
785         ar1[n] *= xx;
786         sphs[n] = phs/ftp->flen;
787         if ((phs += inc) >= end) {
788           if (!(p->looping)) goto nxtseg;
789           phs -= (phs - end) * 2;
790           p->curmod = 3;
791           if (++n<nsmps) goto case3;
792           else break;
793         }
794       }
795       break;
796     case 3:
797     case3:
798       for (; n<nsmps; n++) {                    /* BIDIR BACK, EVEN */
799         loscil_linear_interp_mono(&ar1[n], ftbl, phs, ftp->flen);
800         if (aamp) xx = xamp[n];
801         ar1[n] *= xx;
802         sphs[n] = phs/ftp->flen;
803         if (UNLIKELY((phs -= inc) < beg)) {
804           phs += (beg - phs) * 2;
805           p->curmod = 2;
806           if (++n<nsmps) goto case2;
807           else break;
808         }
809       }
810       break;
811 
812     nxtseg:
813       if (p->seg1) {
814         p->seg1 = 0;
815         if ((p->curmod = p->mod2) != 0)
816           p->looping = 1;
817         if (++n>nsmps) {
818           beg = p->beg2;
819           end = p->end2;
820           p->lphs = phs;
821           goto phschk;
822         }
823         break;
824       }
825       if (LIKELY(++n<nsmps)) goto phsout;
826       break;
827     }
828     p->lphs = phs;
829     return OK;
830 
831  phsout:
832     p->lphs = phs;
833 put0:
834     //printf("****put0\n");
835     memset(&ar1[n], '\0', sizeof(MYFLT)*(nsmps-n));
836     return OK;
837 
838  phsck2:
839     if (phs >= end && p->curmod != 3)
840       goto put0s;                               /* for STEREO:  */
841     switch (p->curmod) {
842     case 0:
843       for (; n<nsmps; n++) {                    /* NO LOOPING  */
844         loscil_linear_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
845         if (aamp) xx = xamp[n];
846         ar1[n] *= xx;
847         ar2[n] *= xx;
848         sphs[n] = phs/ftp->flen;
849         if (UNLIKELY((phs += inc) >= end))
850           goto nxtseg2;
851       }
852       break;
853     case 1:
854       for (; n<nsmps; n++) {                    /* NORMAL LOOPING */
855         loscil_linear_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
856         if (aamp) xx = xamp[n];
857         ar1[n] *= xx;
858         ar2[n] *= xx;
859         sphs[n] = phs/ftp->flen;
860         if (UNLIKELY((phs += inc) >= end)) {
861           if (!(p->looping)) goto nxtseg2;
862           phs -= end - beg;
863         }
864       }
865       break;
866     case 2:
867     case2s:
868       for (; n<nsmps; n++) {                    /* BIDIR FORW, EVEN */
869         loscil_linear_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
870         if (aamp) xx = xamp[n];
871         ar1[n] *= xx;
872         ar2[n] *= xx;
873         sphs[n] = phs/ftp->flen;
874         if (UNLIKELY((phs += inc) >= end)) {
875           if (!(p->looping)) goto nxtseg2;
876           phs -= (phs - end) * 2;
877           p->curmod = 3;
878           if (++n<nsmps) goto case3s;
879           else break;
880         }
881       }
882       break;
883     case 3:
884     case3s:
885       for (; n<nsmps; n++) {                    /* BIDIR BACK, EVEN */
886        loscil_linear_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
887         if (aamp) xx = xamp[n];
888         ar1[n] *= xx;
889         ar2[n] *= xx;
890         sphs[n] = phs/ftp->flen;
891         if (UNLIKELY((phs -= inc) < beg)) {
892           phs += (beg - phs) * 2;
893           p->curmod = 2;
894           if (++n<nsmps) goto case2s;
895           else break;
896         }
897       }
898       break;
899 
900     nxtseg2:
901       if (p->seg1) {
902         p->seg1 = 0;
903         if ((p->curmod = p->mod2) != 0)
904           p->looping = 1;
905         if (++n<nsmps) {
906           beg = p->beg2;
907           end = p->end2;
908           p->lphs = phs;
909           goto phsck2;
910         }
911         break;
912       }
913       if (LIKELY(++n<nsmps)) goto phsout2;
914       break;
915     }
916     p->lphs = phs;
917     return OK;
918 
919  phsout2:
920     p->lphs = phs;
921  put0s:
922     memset(&ar1[n], '\0', sizeof(MYFLT)*(nsmps-n));
923     memset(&ar2[n], '\0', sizeof(MYFLT)*(nsmps-n));
924     return OK;
925 }
926 
927 
928 
loscil3_phs(CSOUND * csound,LOSCPHS * p)929 int32_t loscil3_phs(CSOUND *csound, LOSCPHS *p)
930 {
931     IGN(csound);
932     FUNC    *ftp;
933     MYFLT   *ar1, *ar2, *ftbl, *xamp, *sphs;
934     MYFLT    phs;
935     MYFLT    inc, beg, end;
936     uint32_t n = p->h.insdshead->ksmps_offset;
937     uint32_t early  = p->h.insdshead->ksmps_no_end;
938     uint32_t nsmps = CS_KSMPS;
939     int32_t     aamp;
940     MYFLT   xx;
941 
942     ftp = p->ftp;
943     ftbl = ftp->ftable;
944     if ((inc = (*p->kcps * p->cpscvt)) < 0)
945       inc = -inc;
946     xamp = p->xamp;
947     xx = *xamp;
948     aamp = IS_ASIG_ARG(p->xamp) ? 1 : 0;
949     if (p->seg1) {                      /* if still segment 1  */
950       beg = p->beg1;
951       end = p->end1;
952       if (p->h.insdshead->relesing)   /*    sense note_off   */
953         p->looping = 0;
954     }
955     else {
956       beg = p->beg2;
957       end = p->end2;
958     }
959     phs = p->lphs;
960     ar1 = p->ar1;
961     sphs = p->sphs;
962     if (UNLIKELY(n)) memset(ar1, '\0', n*sizeof(MYFLT));
963     if (UNLIKELY(early)) {
964       nsmps -= early;
965       memset(&ar1[nsmps], '\0', early*sizeof(MYFLT));
966       memset(&sphs[nsmps], '\0', early*sizeof(MYFLT));
967     }
968     if (p->stereo) {
969       ar2 = p->ar2;
970       if (UNLIKELY(n)) memset(ar1, '\0', n*sizeof(MYFLT));
971       if (UNLIKELY(early)) memset(&ar2[nsmps], '\0', early*sizeof(MYFLT));
972       goto phsck2;
973     }
974  phschk:
975     if (UNLIKELY(phs >= end && p->curmod != 3))
976       goto put0;
977     switch (p->curmod) {
978     case 0:
979       for (; n<nsmps; n++) {                    /* NO LOOPING  */
980         loscil_cubic_interp_mono(&ar1[n], ftbl, phs, ftp->flen);
981         if (aamp) xx = xamp[n];
982         ar1[n] *= xx;
983         sphs[n] = phs/ftp->flen;
984         if (UNLIKELY((phs += inc) >= end))
985           goto nxtseg;
986       }
987       break;
988     case 1:
989       for (; n<nsmps; n++) {                    /* NORMAL LOOPING */
990         loscil_cubic_interp_mono(&ar1[n], ftbl, phs, ftp->flen);
991         if (aamp) xx = xamp[n];
992         ar1[n] *= xx;
993         sphs[n] = phs/ftp->flen;
994         if (UNLIKELY((phs += inc) >= end)) {
995           if (!(p->looping)) goto nxtseg;
996           phs -= end - beg;
997         }
998       }
999       break;
1000     case 2:
1001     case2:
1002       for (; n<nsmps; n++) {                    /* BIDIR FORW, EVEN */
1003         loscil_cubic_interp_mono(&ar1[n], ftbl, phs, ftp->flen);
1004         if (aamp) xx = xamp[n];
1005         ar1[n] *= xx;
1006         sphs[n] = phs/ftp->flen;
1007         if (UNLIKELY((phs += inc) >= end)) {
1008           if (!(p->looping)) goto nxtseg;
1009           phs -= (phs - end) * 2;
1010           p->curmod = 3;
1011           if (++n<nsmps) goto case3;
1012           else break;
1013         }
1014       }
1015       break;
1016     case 3:
1017     case3:
1018       for (; n<nsmps; n++) {                    /* BIDIR BACK, EVEN */
1019         loscil_cubic_interp_mono(&ar1[n], ftbl, phs, ftp->flen);;
1020         if (aamp) xx = xamp[n];
1021         ar1[n] *= xx;
1022         sphs[n] = phs/ftp->flen;
1023         if (UNLIKELY((phs -= inc) < beg)) {
1024           phs += (beg - phs) * 2;
1025           p->curmod = 2;
1026           if (++n<nsmps) goto case2;
1027           else break;
1028         }
1029       }
1030       break;
1031 
1032     nxtseg:
1033       if (p->seg1) {
1034         p->seg1 = 0;
1035         if ((p->curmod = p->mod2) != 0)
1036           p->looping = 1;
1037         if (--nsmps) {
1038           beg = p->beg2;
1039           end = p->end2;
1040           p->lphs = phs;
1041           goto phschk;
1042         }
1043         break;
1044       }
1045       if (LIKELY(++n<nsmps)) goto phsout;
1046       break;
1047     }
1048     p->lphs = phs;
1049     return OK;
1050 
1051  phsout:
1052     p->lphs = phs;
1053  put0:
1054     memset(&ar1[n], 0, sizeof(MYFLT)*(nsmps-n));
1055     /* do { */
1056     /*   *ar1++ = FL(0.0); */
1057     /* } while (--nsmps); */
1058     return OK;
1059 
1060  phsck2:
1061     if (UNLIKELY(phs >= end && p->curmod != 3))
1062       goto put0s;                               /* for STEREO:  */
1063     switch (p->curmod) {
1064     case 0:
1065       for (; n<nsmps; n++) {                    /* NO LOOPING  */
1066         loscil_cubic_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
1067         if (aamp) xx = xamp[n];
1068         ar1[n] *= xx;
1069         ar2[n] *= xx;
1070         sphs[n] = phs/ftp->flen;
1071         if (UNLIKELY((phs += inc) >= end))
1072           goto nxtseg2;
1073       }
1074       break;
1075     case 1:
1076       for (; n<nsmps; n++) {                    /* NORMAL LOOPING */
1077         loscil_cubic_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
1078         if (aamp) xx = xamp[n];
1079         ar1[n] *= xx;
1080         ar2[n] *= xx;
1081         sphs[n] = phs/ftp->flen;
1082         if (UNLIKELY((phs += inc) >= end)) {
1083           if (!(p->looping)) goto nxtseg2;
1084           phs -= end - beg;
1085         }
1086       }
1087       break;
1088     case 2:
1089     case2s:
1090       for (; n<nsmps; n++) {                    /* BIDIR FORW, EVEN */
1091         loscil_cubic_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
1092         if (aamp) xx = xamp[n];
1093         ar1[n] *= xx;
1094         ar2[n] *= xx;
1095         if (UNLIKELY((phs += inc) >= end)) {
1096           if (!(p->looping)) goto nxtseg2;
1097           phs -= (phs - end) * 2;
1098           p->curmod = 3;
1099           if (++n<nsmps) goto case3s;
1100           else break;
1101         }
1102       }
1103       break;
1104     case 3:
1105     case3s:
1106       for (; n<nsmps; n++) {                    /* BIDIR BACK, EVEN */
1107         loscil_cubic_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
1108         if (aamp) xx = xamp[n];
1109         ar1[n] *= xx;
1110         ar2[n] *= xx;
1111         sphs[n] = phs/ftp->flen;
1112         if (UNLIKELY((phs -= inc) < beg)) {
1113           phs += (beg - phs) * 2;
1114           p->curmod = 2;
1115           if (++n<nsmps) goto case2s;
1116           else break;
1117         }
1118       }
1119       break;
1120 
1121     nxtseg2:
1122       if (p->seg1) {
1123         p->seg1 = 0;
1124         if ((p->curmod = p->mod2) != 0)
1125           p->looping = 1;
1126         if (++n<nsmps) {
1127           beg = p->beg2;
1128           end = p->end2;
1129           p->lphs = phs;
1130           goto phsck2;
1131         }
1132         break;
1133       }
1134       if (LIKELY(++n<nsmps)) goto phsout2;
1135       break;
1136     }
1137     p->lphs = phs;
1138     return OK;
1139 
1140  phsout2:
1141     p->lphs = phs;
1142  put0s:
1143     memset(&ar1[n], '\0', sizeof(MYFLT)*(nsmps-n));
1144     memset(&ar2[n], '\0', sizeof(MYFLT)*(nsmps-n));
1145     return OK;
1146 }
1147 
1148 
loscil3(CSOUND * csound,LOSC * p)1149 int32_t loscil3(CSOUND *csound, LOSC *p)
1150 {
1151     IGN(csound);
1152     FUNC    *ftp;
1153     MYFLT   *ar1, *ar2, *ftbl, *xamp;
1154     MYFLT    phs;
1155     MYFLT    inc, beg, end;
1156     uint32_t n = p->h.insdshead->ksmps_offset;
1157     uint32_t early  = p->h.insdshead->ksmps_no_end;
1158     uint32_t nsmps = CS_KSMPS;
1159     int32_t     aamp;
1160     MYFLT   xx;
1161 
1162     ftp = p->ftp;
1163     ftbl = ftp->ftable;
1164     if ((inc = (*p->kcps * p->cpscvt)) < 0)
1165       inc = -inc;
1166     xamp = p->xamp;
1167     xx = *xamp;
1168     aamp = IS_ASIG_ARG(p->xamp) ? 1 : 0;
1169     if (p->seg1) {                      /* if still segment 1  */
1170       beg = p->beg1;
1171       end = p->end1;
1172       if (p->h.insdshead->relesing)   /*    sense note_off   */
1173         p->looping = 0;
1174     }
1175     else {
1176       beg = p->beg2;
1177       end = p->end2;
1178     }
1179     phs = p->lphs;
1180     ar1 = p->ar1;
1181     if (UNLIKELY(n)) memset(ar1, '\0', n*sizeof(MYFLT));
1182     if (UNLIKELY(early)) {
1183       nsmps -= early;
1184       memset(&ar1[nsmps], '\0', early*sizeof(MYFLT));
1185     }
1186     if (p->stereo) {
1187       ar2 = p->ar2;
1188       if (UNLIKELY(n)) memset(ar1, '\0', n*sizeof(MYFLT));
1189       if (UNLIKELY(early)) memset(&ar2[nsmps], '\0', early*sizeof(MYFLT));
1190       goto phsck2;
1191     }
1192  phschk:
1193     if (UNLIKELY(phs >= end && p->curmod != 3))
1194       goto put0;
1195     switch (p->curmod) {
1196     case 0:
1197       for (; n<nsmps; n++) {                    /* NO LOOPING  */
1198         loscil_cubic_interp_mono(&ar1[n], ftbl, phs, ftp->flen);
1199         if (aamp) xx = xamp[n];
1200         ar1[n] *= xx;
1201         if (UNLIKELY((phs += inc) >= end))
1202           goto nxtseg;
1203       }
1204       break;
1205     case 1:
1206       for (; n<nsmps; n++) {                    /* NORMAL LOOPING */
1207         loscil_cubic_interp_mono(&ar1[n], ftbl, phs, ftp->flen);
1208         if (aamp) xx = xamp[n];
1209         ar1[n] *= xx;
1210         if (UNLIKELY((phs += inc) >= end)) {
1211           if (!(p->looping)) goto nxtseg;
1212           phs -= end - beg;
1213         }
1214       }
1215       break;
1216     case 2:
1217     case2:
1218       for (; n<nsmps; n++) {                    /* BIDIR FORW, EVEN */
1219         loscil_cubic_interp_mono(&ar1[n], ftbl, phs, ftp->flen);
1220         if (aamp) xx = xamp[n];
1221         ar1[n] *= xx;
1222         if (UNLIKELY((phs += inc) >= end)) {
1223           if (!(p->looping)) goto nxtseg;
1224           phs -= (phs - end) * 2;
1225           p->curmod = 3;
1226           if (++n<nsmps) goto case3;
1227           else break;
1228         }
1229       }
1230       break;
1231     case 3:
1232     case3:
1233       for (; n<nsmps; n++) {                    /* BIDIR BACK, EVEN */
1234         loscil_cubic_interp_mono(&ar1[n], ftbl, phs, ftp->flen);;
1235         if (aamp) xx = xamp[n];
1236         ar1[n] *= xx;
1237         if (UNLIKELY((phs -= inc) < beg)) {
1238           phs += (beg - phs) * 2;
1239           p->curmod = 2;
1240           if (++n<nsmps) goto case2;
1241           else break;
1242         }
1243       }
1244       break;
1245 
1246     nxtseg:
1247       if (p->seg1) {
1248         p->seg1 = 0;
1249         if ((p->curmod = p->mod2) != 0)
1250           p->looping = 1;
1251         if (--nsmps) {
1252           beg = p->beg2;
1253           end = p->end2;
1254           p->lphs = phs;
1255           goto phschk;
1256         }
1257         break;
1258       }
1259       if (LIKELY(++n<nsmps)) goto phsout;
1260       break;
1261     }
1262     p->lphs = phs;
1263     return OK;
1264 
1265  phsout:
1266     p->lphs = phs;
1267  put0:
1268     memset(&ar1[n], 0, sizeof(MYFLT)*(nsmps-n));
1269     /* do { */
1270     /*   *ar1++ = FL(0.0); */
1271     /* } while (--nsmps); */
1272     return OK;
1273 
1274  phsck2:
1275     if (UNLIKELY(phs >= end && p->curmod != 3))
1276       goto put0s;                               /* for STEREO:  */
1277     switch (p->curmod) {
1278     case 0:
1279       for (; n<nsmps; n++) {                    /* NO LOOPING  */
1280         loscil_cubic_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
1281         if (aamp) xx = xamp[n];
1282         ar1[n] *= xx;
1283         ar2[n] *= xx;
1284         if (UNLIKELY((phs += inc) >= end))
1285           goto nxtseg2;
1286       }
1287       break;
1288     case 1:
1289       for (; n<nsmps; n++) {                    /* NORMAL LOOPING */
1290         loscil_cubic_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
1291         if (aamp) xx = xamp[n];
1292         ar1[n] *= xx;
1293         ar2[n] *= xx;
1294         if (UNLIKELY((phs += inc) >= end)) {
1295           if (!(p->looping)) goto nxtseg2;
1296           phs -= end - beg;
1297         }
1298       }
1299       break;
1300     case 2:
1301     case2s:
1302       for (; n<nsmps; n++) {                    /* BIDIR FORW, EVEN */
1303         loscil_cubic_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
1304         if (aamp) xx = xamp[n];
1305         ar1[n] *= xx;
1306         ar2[n] *= xx;
1307         if (UNLIKELY((phs += inc) >= end)) {
1308           if (!(p->looping)) goto nxtseg2;
1309           phs -= (phs - end) * 2;
1310           p->curmod = 3;
1311           if (++n<nsmps) goto case3s;
1312           else break;
1313         }
1314       }
1315       break;
1316     case 3:
1317     case3s:
1318       for (; n<nsmps; n++) {                    /* BIDIR BACK, EVEN */
1319         loscil_cubic_interp_stereo(&ar1[n], &ar2[n], ftbl, phs, ftp->flen);
1320         if (aamp) xx = xamp[n];
1321         ar1[n] *= xx;
1322         ar2[n] *= xx;
1323         if (UNLIKELY((phs -= inc) < beg)) {
1324           phs += (beg - phs) * 2;
1325           p->curmod = 2;
1326           if (++n<nsmps) goto case2s;
1327           else break;
1328         }
1329       }
1330       break;
1331 
1332     nxtseg2:
1333       if (p->seg1) {
1334         p->seg1 = 0;
1335         if ((p->curmod = p->mod2) != 0)
1336           p->looping = 1;
1337         if (++n<nsmps) {
1338           beg = p->beg2;
1339           end = p->end2;
1340           p->lphs = phs;
1341           goto phsck2;
1342         }
1343         break;
1344       }
1345       if (LIKELY(++n<nsmps)) goto phsout2;
1346       break;
1347     }
1348     p->lphs = phs;
1349     return OK;
1350 
1351  phsout2:
1352     p->lphs = phs;
1353  put0s:
1354     memset(&ar1[n], '\0', sizeof(MYFLT)*(nsmps-n));
1355     memset(&ar2[n], '\0', sizeof(MYFLT)*(nsmps-n));
1356     return OK;
1357 }
1358 
1359 
1360 
1361 #define ISINSIZ 32768L
1362 #define ADMASK  32767L
1363 
adset_(CSOUND * csound,ADSYN * p,int32_t stringname)1364 static int32_t adset_(CSOUND *csound, ADSYN *p, int32_t stringname)
1365 {
1366     int32_t    n;
1367     char    filnam[MAXNAME];
1368     MEMFIL  *mfp;
1369     int16   *adp, *endata, val;
1370     PTLPTR  *ptlap, *ptlfp, *ptlim;
1371     int32_t     size;
1372 
1373     if (csound->isintab == NULL) {  /* if no sin table yet, make one */
1374       int16 *ip;
1375       csound->isintab = ip =
1376         (int16*) csound->Malloc(csound, ISINSIZ * sizeof(int16));
1377       for (n = 0; n < ISINSIZ; n++)
1378         *ip++ = (int16) (sin(TWOPI * n / ISINSIZ) * 32767.0);
1379     }
1380     if (stringname) strNcpy(filnam, ((STRINGDAT*)p->ifilcod)->data, MAXNAME-1);
1381     else if (csound->ISSTRCOD(*p->ifilcod))
1382       strNcpy(filnam, get_arg_string(csound, *p->ifilcod), MAXNAME-1);
1383     else csound->strarg2name(csound, filnam, p->ifilcod, "adsyn.", 0);
1384 
1385 
1386     if ((mfp = p->mfp) == NULL || strcmp(mfp->filename,filnam) != 0) {
1387       /* readfile if reqd */
1388       if (UNLIKELY((mfp = ldmemfile2withCB(csound, filnam,
1389                                            CSFTYPE_HETRO, NULL)) == NULL)) {
1390         return csound->InitError(csound, Str("ADSYN cannot load %s"), filnam);
1391       }
1392       p->mfp = mfp;                         /*   & record         */
1393     }
1394 
1395     adp = (int16 *) mfp->beginp;            /* align on file data */
1396     endata = (int16 *) mfp->endp;
1397     size = 1+(*adp == -1 ? MAXPTLS : *adp++); /* Old no header -> MAXPIL */
1398     if (p->aux.auxp==NULL || p->aux.size < (uint32_t)sizeof(PTLPTR)*size)
1399       csound->AuxAlloc(csound, sizeof(PTLPTR)*size, &p->aux);
1400 
1401     ptlap = ptlfp = (PTLPTR*)p->aux.auxp;   /* find base ptl blk */
1402     ptlim = ptlap + size;
1403     do {
1404       if ((val = *adp++) < 0) {             /* then for each brkpt set,   */
1405         switch (val) {
1406         case -1:
1407           ptlap->nxtp = ptlap + 1;       /* chain the ptl blks */
1408           if (UNLIKELY((ptlap = ptlap->nxtp) >= ptlim)) goto adsful;
1409           ptlap->ap = (DUPLE *) adp;     /*  record start amp  */
1410           ptlap->amp = ptlap->ap->val;
1411           break;
1412         case -2:
1413           if (UNLIKELY((ptlfp += 1) >= ptlim)) goto adsful;
1414           ptlfp->fp = (DUPLE *) adp;     /*  record start frq  */
1415           ptlfp->frq = ptlfp->fp->val;
1416           ptlfp->phs = 0;                /*  and clr the phase */
1417           break;
1418         default:
1419           return csound->InitError(csound, Str("illegal code %d encountered"), val);
1420         }
1421       }
1422     } while (adp < endata);
1423     if (UNLIKELY(ptlap != ptlfp)) {
1424       return csound->InitError(csound, Str("%d amp tracks, %d freq tracks"),
1425                                (int32_t) (ptlap - (PTLPTR*)p->aux.auxp) - 1,
1426                                (int32_t) (ptlfp - (PTLPTR*)p->aux.auxp) - 1);
1427     }
1428     ptlap->nxtp = NULL;   /* terminate the chain */
1429     p->mksecs = 0;
1430 
1431     return OK;
1432 
1433  adsful:
1434     return csound->InitError(csound, Str("partial count exceeds MAXPTLS"));
1435 }
1436 
adset(CSOUND * csound,ADSYN * p)1437 int32_t adset(CSOUND *csound, ADSYN *p){
1438   return adset_(csound,p,0);
1439 }
1440 
adset_S(CSOUND * csound,ADSYN * p)1441 int32_t adset_S(CSOUND *csound, ADSYN *p){
1442   return adset_(csound,p,1);
1443 }
1444 
1445 #define ADSYN_MAXLONG FL(2147483647.0)
1446 
adsyn(CSOUND * csound,ADSYN * p)1447 int32_t adsyn(CSOUND *csound, ADSYN *p)
1448 {
1449     PTLPTR  *curp, *prvp;
1450     DUPLE   *ap, *fp;
1451     int16   curtim, diff, ktogo;
1452     int32_t   phs, sinc, amp;
1453     uint32_t offset = p->h.insdshead->ksmps_offset;
1454     uint32_t early  = p->h.insdshead->ksmps_no_end;
1455     uint32_t n, nsmps = CS_KSMPS;
1456     MYFLT   *ar = p->rslt;
1457     MYFLT   ampscale, frqscale;
1458     int32_t   timkincr, nxtim;
1459 
1460     if (UNLIKELY(csound->isintab == NULL)) {      /* RWD fix */
1461       return csound->PerfError(csound, &(p->h),
1462                                Str("adsyn: not initialised"));
1463     }
1464     /* IV - Jul 11 2002 */
1465     ampscale = *p->kamod * csound->e0dbfs;      /* since 15-bit sine table */
1466     frqscale = *p->kfmod * ISINSIZ * csound->onedsr;
1467     /* 1024 * msecs of analysis */
1468     memset(p->rslt,0,sizeof(MYFLT)*nsmps);
1469     if (UNLIKELY(early)) nsmps -= early;
1470     timkincr = (int32)(*p->ksmod*FL(1024000.0)*CS_ONEDKR);
1471     curtim = (int16)(p->mksecs >> 10);          /* cvt mksecs to msecs */
1472     curp = (PTLPTR*)p->aux.auxp;                /* now for each partial:    */
1473     while ((prvp = curp) && (curp = curp->nxtp) != NULL ) {
1474       ap = curp->ap;
1475       fp = curp->fp;
1476       while (curtim >= (ap+1)->tim)       /* timealign ap, fp */
1477         curp->ap = ap += 1;
1478       while (curtim >= (fp+1)->tim)
1479         curp->fp = fp += 1;
1480       if ((amp = curp->amp)) {            /* for non-zero amp   */
1481         sinc = (int32)(curp->frq * frqscale);
1482         phs = curp->phs;
1483         /*   addin a sinusoid */
1484         for (n=offset; n<nsmps; n++) {
1485           ar[n] += (ampscale*(MYFLT)csound->isintab[phs]*(MYFLT)amp)/ADSYN_MAXLONG;
1486           phs += sinc;
1487           phs &= ADMASK;
1488         }
1489         curp->phs = phs;
1490       }
1491       if ((nxtim = (ap+1)->tim) == 32767) {   /* if last amp this partial */
1492         prvp->nxtp = curp->nxtp;            /*   remov from activ chain */
1493         curp = prvp;
1494       }
1495       else {                                 /* else interp towds nxt amp */
1496         if ((diff = (int16)((ap+1)->val - amp))) {
1497           ktogo = (int16)(((nxtim<<10) - p->mksecs + timkincr - 1) / timkincr);
1498           if (ktogo == 0) curp->amp += diff;
1499           else            curp->amp += diff / ktogo;
1500         }
1501         if ((nxtim = (fp+1)->tim) != 32767            /*      & nxt frq */
1502             && (diff = (fp+1)->val - curp->frq)) {
1503           ktogo = (int16)(((nxtim<<10) - p->mksecs + timkincr - 1) / timkincr);
1504           if (ktogo == 0) curp->frq += diff;
1505           else            curp->frq += diff / ktogo;
1506         }
1507       }
1508     }
1509     p->mksecs += timkincr;                  /* advance the time */
1510     return OK;
1511 }
1512