1 /*
2     ugens7.c:
3 
4     Copyright (C) 1995 J. Michael Clarke, based on ideas from CHANT (IRCAM),
5                        Barry Vercoe, John ffitch
6 
7     This file is part of Csound.
8 
9     The Csound Library is free software; you can redistribute it
10     and/or modify it under the terms of the GNU Lesser General Public
11     License as published by the Free Software Foundation; either
12     version 2.1 of the License, or (at your option) any later version.
13 
14     Csound is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU Lesser General Public License for more details.
18 
19     You should have received a copy of the GNU Lesser General Public
20     License along with Csound; if not, write to the Free Software
21     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22     02110-1301 USA
23 */
24 
25 #include "stdopcod.h"               /*                      UGENS7.C        */
26 #include "ugens7.h"
27 #include <math.h>
28 
29 /* loosely based on code of Michael Clarke, University of Huddersfield */
30 
31 static   int32_t    newpulse(CSOUND *, FOFS *, OVRLAP *, MYFLT *, MYFLT *, MYFLT *);
32 
fofset0(CSOUND * csound,FOFS * p,int32_t flag)33 static int32_t fofset0(CSOUND *csound, FOFS *p, int32_t flag)
34 {
35     int32_t skip = (*p->iskip != FL(0.0) && p->auxch.auxp != 0);
36     if (LIKELY((p->ftp1 = csound->FTFind(csound, p->ifna)) != NULL &&
37                (p->ftp2 = csound->FTFind(csound, p->ifnb)) != NULL)) {
38       OVRLAP *ovp, *nxtovp;
39       int32  olaps;
40       p->durtogo = (int32)(*p->itotdur * CS_ESR);
41       if (!skip) { /* legato: skip all memory management */
42         if (*p->iphs == FL(0.0))                /* if fundphs zero,  */
43           p->fundphs = MAXLEN;                  /*   trigger new FOF */
44         else p->fundphs = (int32)(*p->iphs * FMAXLEN) & PHMASK;
45         if (UNLIKELY((olaps = (int32)*p->iolaps) <= 0)) {
46           return csound->InitError(csound, Str("illegal value for iolaps"));
47         }
48         if (*p->iphs >= FL(0.0))
49           csound->AuxAlloc(csound, (size_t)olaps * sizeof(OVRLAP), &p->auxch);
50         ovp = &p->basovrlap;
51         nxtovp = (OVRLAP *) p->auxch.auxp;
52         do {
53           ovp->nxtact = NULL;
54           ovp->nxtfree = nxtovp;                /* link the ovlap spaces */
55           ovp = nxtovp++;
56         } while (--olaps);
57         ovp->nxtact = NULL;
58         ovp->nxtfree = NULL;
59         p->fofcount = -1;
60         p->prvband = FL(0.0);
61         p->expamp = FL(1.0);
62         p->prvsmps = (int32)0;
63         p->preamp = FL(1.0);
64       } /* end of legato code */
65       p->ampcod   = IS_ASIG_ARG(p->xamp) ? 1 : 0;
66       p->fundcod  = IS_ASIG_ARG(p->xfund) ? 1 : 0;
67       p->formcod  = IS_ASIG_ARG(p->xform) ? 1 : 0;
68       p->xincod   = p->ampcod || p->fundcod || p->formcod;
69       if (flag)
70         p->fmtmod = (*p->ifmode == FL(0.0)) ? 0 : 1;
71     }
72     else return NOTOK;
73     p->foftype = flag;
74     return OK;
75 }
76 
fofset(CSOUND * csound,FOFS * p)77 static int32_t fofset(CSOUND *csound, FOFS *p)
78 {
79     return fofset0(csound, p, 1);
80 }
81 
fofset2(CSOUND * csound,FOFS * p)82 static int32_t fofset2(CSOUND *csound, FOFS *p)
83 {
84     return fofset0(csound, p, 0);
85 }
86 
fof(CSOUND * csound,FOFS * p)87 static int32_t fof(CSOUND *csound, FOFS *p)
88 {
89     OVRLAP  *ovp;
90     FUNC    *ftp1,  *ftp2;
91     MYFLT   *ar, *amp, *fund, *form;
92     uint32_t offset = p->h.insdshead->ksmps_offset;
93     uint32_t early  = p->h.insdshead->ksmps_no_end;
94     uint32_t n, nsmps = CS_KSMPS;
95     int32   fund_inc, form_inc;
96     MYFLT   v1, fract ,*ftab;
97 
98     if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */
99     ar = p->ar;
100     amp = p->xamp;
101     fund = p->xfund;
102     form = p->xform;
103     ftp1 = p->ftp1;
104     ftp2 = p->ftp2;
105     fund_inc = (int32)(*fund * csound->sicvt);
106     if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT));
107     if (UNLIKELY(early)) {
108       nsmps -= early;
109       memset(&ar[nsmps], '\0', early*sizeof(MYFLT));
110     }
111     form_inc = (int32)(*form * csound->sicvt);
112     for (n=offset; n<nsmps; n++) {
113       if (p->fundphs & MAXLEN) {               /* if phs has wrapped */
114         p->fundphs &= PHMASK;
115         if ((ovp = p->basovrlap.nxtfree) == NULL) goto err2;
116         if (newpulse(csound, p, ovp, amp, fund, form)) {   /* init new fof */
117           ovp->nxtact = p->basovrlap.nxtact;     /* & link into  */
118           p->basovrlap.nxtact = ovp;             /*   actlist    */
119           p->basovrlap.nxtfree = ovp->nxtfree;
120         }
121       }
122       ar[n] = FL(0.0);
123       ovp = &p->basovrlap;
124       while (ovp->nxtact != NULL) {         /* perform cur actlist:  */
125         MYFLT  result;
126         OVRLAP *prvact = ovp;
127         ovp = ovp->nxtact;                   /*  formant waveform  */
128         fract = PFRAC1(ovp->formphs);        /* from JMC Fog*/
129         ftab = ftp1->ftable + (ovp->formphs >> ftp1->lobits);/*JMC Fog*/
130         v1 = *ftab++;                           /*JMC Fog*/
131         result = v1 + (*ftab - v1) * fract;     /*JMC Fog*/
132 /*              result = *(ftp1->ftable + (ovp->formphs >> ftp1->lobits) ); */
133         if (p->foftype) {
134           if (p->fmtmod)
135             ovp->formphs += form_inc;           /* inc phs on mode */
136           else ovp->formphs += ovp->forminc;
137         }
138         else {
139 #define kgliss ifmode
140           /* MYFLT ovp->glissbas = kgliss / grain length. ovp->sampct is
141              incremented each sample. We add glissbas * sampct to the
142              pitch of grain at each a-rate pass (ovp->formphs is the
143              index into ifna; ovp->forminc is the stepping factor that
144              decides pitch) */
145           ovp->formphs += (int32)(ovp->forminc + ovp->glissbas * ovp->sampct++);
146         }
147         ovp->formphs &= PHMASK;
148         if (ovp->risphs < MAXLEN) {             /*  formant ris envlp */
149           result *= *(ftp2->ftable + (ovp->risphs >> ftp2->lobits) );
150           ovp->risphs += ovp->risinc;
151         }
152         if (ovp->timrem <= ovp->dectim) {       /*  formant dec envlp */
153           result *= *(ftp2->ftable + (ovp->decphs >> ftp2->lobits) );
154           if ((ovp->decphs -= ovp->decinc) < 0)
155             ovp->decphs = 0;
156         }
157         ar[n] += (result * ovp->curamp);        /*  add wavfrm to out */
158         if (--ovp->timrem)                      /*  if fof not expird */
159           ovp->curamp *= ovp->expamp;           /*   apply bw exp dec */
160         else {
161           prvact->nxtact = ovp->nxtact;         /*  else rm frm activ */
162           ovp->nxtfree = p->basovrlap.nxtfree;  /*  & ret spc to free */
163           p->basovrlap.nxtfree = ovp;
164           ovp = prvact;
165         }
166       }
167       p->fundphs += fund_inc;
168       if (p->xincod) {
169         if (p->ampcod)    amp++;
170         if (p->fundcod)   fund_inc = (int32)(*++fund * csound->sicvt);
171         if (p->formcod)   form_inc = (int32)(*++form * csound->sicvt);
172       }
173       p->durtogo--;
174     }
175     return OK;
176  err1:
177     return csound->PerfError(csound, &(p->h),
178                              Str("fof: not initialised"));
179  err2:
180     return csound->PerfError(csound, &(p->h),
181                              Str("FOF needs more overlaps"));
182 }
183 
newpulse(CSOUND * csound,FOFS * p,OVRLAP * ovp,MYFLT * amp,MYFLT * fund,MYFLT * form)184 static int32_t newpulse(CSOUND *csound,
185                     FOFS *p, OVRLAP *ovp, MYFLT *amp, MYFLT *fund, MYFLT *form)
186 {
187     MYFLT   octamp = *amp, oct;
188     int32   rismps, newexp = 0;
189 
190     if ((ovp->timrem = (int32)(*p->kdur * CS_ESR)) > p->durtogo &&
191         (*p->iskip==FL(0.0))) /* ringtime */
192       return(0);
193     if ((oct = *p->koct) > FL(0.0)) {                   /* octaviation */
194       int64_t csnt = -1;
195       int32 ioct = (int32)oct, bitpat = ~(csnt << ioct);
196       if (bitpat & ++p->fofcount)
197         return(0);
198       if ((bitpat += 1) & p->fofcount)
199         octamp *= (FL(1.0) + ioct - oct);
200     }
201     if (*fund == FL(0.0))                               /* formant phs */
202       ovp->formphs = 0;
203     else ovp->formphs = (int32)(p->fundphs * *form / *fund) & PHMASK;
204     ovp->forminc = (int32)(*form * csound->sicvt);
205     if (*p->kband != p->prvband) {                    /* bw: exp dec */
206       p->prvband = *p->kband;
207       p->expamp =  EXP(*p->kband * csound->mpidsr);
208       newexp = 1;
209     }
210     /* Init grain rise ftable phase. Negative kform values make
211        the kris (ifnb) initial index go negative and crash csound.
212        So insert another if-test with compensating code. */
213     if (*p->kris >= csound->onedsr && *form != FL(0.0)) {   /* init fnb ris */
214       if (*form < FL(0.0) && ovp->formphs != 0)
215         ovp->risphs = (int32)((MAXLEN - ovp->formphs) / -*form / *p->kris);
216       else
217         ovp->risphs = (int32)(ovp->formphs / *form / *p->kris);
218       ovp->risinc = (int32)(csound->sicvt / *p->kris);
219       rismps = MAXLEN / ovp->risinc;
220     }
221     else {
222       ovp->risphs = MAXLEN;
223       rismps = 0;
224     }
225     if (newexp || rismps != p->prvsmps) {            /* if new params */
226       if ((p->prvsmps = rismps))                     /*   redo preamp */
227         p->preamp = csound->intpow(p->expamp, -rismps);
228       else p->preamp = FL(1.0);
229     }
230     ovp->curamp = octamp * p->preamp;                /* set startamp  */
231     ovp->expamp = p->expamp;
232     if ((ovp->dectim = (int32)(*p->kdec * CS_ESR)) > 0) /*  fnb dec  */
233       ovp->decinc = (int32)(csound->sicvt / *p->kdec);
234     ovp->decphs = PHMASK;
235     if (!p->foftype) {
236       /* Make fof take k-rate phase increment:
237          Add current iphs to initial form phase */
238       ovp->formphs += (int32)(*p->iphs * FMAXLEN);           /*  krate phs */
239       ovp->formphs &= PHMASK;
240       /* Set up grain gliss increment: ovp->glissbas will be added to
241          ovp->forminc at each pass in fof2. Thus glissbas must be
242          equal to kgliss / grain playing time. Also make it harmonic,
243          so integer kgliss can represent octaves (ie pow() call). */
244       ovp->glissbas = ovp->forminc * (MYFLT)pow(2.0, (double)*p->kgliss);
245       /* glissbas should be diff of start & end pitch*/
246       ovp->glissbas -= ovp->forminc;
247       ovp->glissbas /= ovp->timrem;
248       ovp->sampct = 0;   /* Must be reset in case ovp was used before  */
249     }
250     return(1);
251 }
252 
253 #if 0
254 static int32_t hrngflg=0;
255 #endif
256 
harmset(CSOUND * csound,HARMON * p)257 static int32_t harmset(CSOUND *csound, HARMON *p)
258 {
259     MYFLT minfrq = *p->ilowest;
260     if (UNLIKELY(minfrq < FL(64.0))) {
261       return csound->InitError(csound, Str("Minimum frequency too low"));
262     }
263     if (p->auxch.auxp == NULL || minfrq < p->minfrq) {
264       int32 nbufs = (int32)(CS_EKR * FL(3.0) / minfrq) + 1;
265       int32 nbufsmps = nbufs * CS_KSMPS;
266       int32 maxprd = (int32)(CS_ESR / minfrq);
267       int32 totalsiz = nbufsmps * 5 + maxprd; /* Surely 5! not 4 */
268       /* printf("init: nbufs = %d; nbufsmps = %d; maxprd = %d; totalsiz = %d\n", */
269       /*        nbufs, nbufsmps, maxprd, totalsiz);       */
270       csound->AuxAlloc(csound, (size_t)totalsiz * sizeof(MYFLT), &p->auxch);
271       p->bufp = (MYFLT *) p->auxch.auxp;
272       p->midp = p->bufp + nbufsmps;        /* each >= maxprd * 3 */
273       p->bufq = p->midp + nbufsmps;
274       p->midq = p->bufq + nbufsmps;
275       p->autobuf = p->midq + nbufsmps;     /* size of maxprd */
276       p->nbufsmps = nbufsmps;
277       p->n2bufsmps = nbufsmps * 2;
278       p->lomaxdist = maxprd;
279       p->minfrq = minfrq;
280     }
281     if ((p->autoktim = (int32_t)/*MYFLT2LONG*/(*p->iptrkprd * CS_EKR)) < 1)
282       p->autoktim = 1;
283     p->autokcnt = 1;              /* init for immediate autocorr attempt */
284     printf("ekr = %f iptrk = %f, autocnt = %d; autotim = %d\n",
285            CS_EKR, *p->iptrkprd, p->autokcnt, p->autoktim);
286     p->lsicvt = FL(65536.0) * csound->onedsr;
287     p->cpsmode = ((*p->icpsmode != FL(0.0)));
288     p->inp1 = p->bufp;
289     p->inp2 = p->midp;
290     p->inq1 = p->bufq;
291     p->inq2 = p->midq;
292     p->puls1 = NULL;
293     p->puls2 = NULL;
294     p->puls3 = NULL;
295     p->prvest = FL(0.0);
296     p->prvq = FL(0.0);
297     p->phase1 = 0;
298     p->phase2 = 0;
299 #if 0
300     hrngflg = 0;
301     p->period = -1;
302 #endif
303     return OK;
304 }
305 
306 #if 0
307 static int32_t cycle = 0;
308 #endif
harmon(CSOUND * csound,HARMON * p)309 static int32_t harmon(CSOUND *csound, HARMON *p)
310 {
311     MYFLT *src1, *src2, *src3, *inp1, *inp2, *outp;
312     MYFLT c1, c2, qval, *inq1, *inq2;
313     MYFLT sum, minval, *minqp = NULL, *minq1, *minq2, *endp;
314     MYFLT *pulstrt, lin1, lin2, lin3;
315     int32  cnt1, cnt2, cnt3;
316     int32  nn, phase1, phase2, phsinc1, phsinc2, period;
317     uint32_t offset = p->h.insdshead->ksmps_offset;
318     uint32_t early  = p->h.insdshead->ksmps_no_end;
319     uint32_t n, nsmps = CS_KSMPS;
320 
321     outp = p->ar;
322 #if 0
323     if (early || offset) printf("early=%d, offet=%d\n", early, offset);
324 #endif
325     if (UNLIKELY(offset)) memset(outp, '\0', offset*sizeof(MYFLT));
326     if (UNLIKELY(early)) {
327       nsmps -= early;
328       memset(&outp[nsmps], '\0', early*sizeof(MYFLT));
329     }
330     inp1 = p->inp1;
331     inp2 = p->inp2;
332     inq1 = p->inq1;
333     inq2 = p->inq2;
334     qval = p->prvq;
335     if (*p->kest != p->prvest &&
336         *p->kest != FL(0.0)) {    /* if new pitch estimate */
337       MYFLT estperiod = CS_ESR / *p->kest;
338       double b = 2.0 - cos((double)(*p->kest * csound->tpidsr));
339       p->c2 = (MYFLT)(b - sqrt(b*b - 1.0)); /*   recalc lopass coefs */
340       p->c1 = FL(1.0) - p->c2;
341       p->prvest = *p->kest;
342       p->estprd = estperiod;
343       p->prvar = FL(0.0);
344     }
345     if (*p->kvar != p->prvar) {
346       MYFLT oneplusvar = FL(1.0) + *p->kvar;
347       /* prd window is prd +/- var int32_t */
348       p->mindist = (int32)(p->estprd/oneplusvar);
349 /*       if (p->mindist==0) p->mindist=1; */
350       p->maxdist = (int32)(p->estprd*oneplusvar);
351       if (p->maxdist > p->lomaxdist)
352         p->maxdist = p->lomaxdist;
353       p->max2dist = p->maxdist * 2;
354       p->prvar = *p->kvar;
355     }
356     c1 = p->c1;
357     c2 = p->c2;
358     //printf("cycle %d\n", ++cycle);
359     for (src1 = p->asig, n = offset; n<nsmps; n++) {
360       *inp1++ = *inp2++ = src1[n];            /* dbl store the wavform */
361       //printf("src[%d] = %f\n", n, src1[n]);
362       if (src1[n] > FL(0.0))
363         qval = c1 * src1[n] + c2 * qval;      /*  & its half-wave rect */
364       else qval = c2 * qval;
365       *inq1++ = *inq2++ = qval;
366     }
367     if (!(--p->autokcnt)) {                   /* if time for new autocorr  */
368       MYFLT *mid1, *mid2, *src4;
369       MYFLT *autop, *maxp;
370       MYFLT dsum, dinv, win, windec, maxval;
371       int32  dist;
372       //printf("AUTOCORRELATE min/max = %d,%d\n",p->mindist, p->maxdist);
373       p->autokcnt = p->autoktim;
374       mid2 = inp2 - p->max2dist;
375       mid1 = mid2 - 1;
376       autop = p->autobuf;
377       for (dist = p->mindist; dist <= p->maxdist; dist++) {
378         dsum = FL(0.0);
379         dinv = FL(1.0) / dist;
380         src1 = mid1;  src3 = mid1 + dist;
381         src2 = mid2;  src4 = mid2 + dist;
382         for (win = FL(1.0), windec = dinv, nn = dist; nn--; ) {
383           dsum += win * (*src1 * *src3 + *src2 * *src4);
384           //printf("dsum = %f from %f %f %f %f\n", dsum, *src1, *src2, *src3, *src4);
385           src1--; src2++; src3--; src4++;
386           win -= windec;
387         }
388         *autop++ = dsum * dinv;
389       }
390       maxval = FL(0.0);
391       maxp = autop = p->autobuf;
392       endp = autop + p->maxdist - p->mindist;
393       while (autop < endp) {
394         //printf("newval, maxval = %f, %f\n", *autop, maxval);
395         if (*autop > maxval) {          /* max autocorr gives new period */
396           maxval = *autop;
397           maxp = autop;
398 #if 0
399           csound->Message(csound, "new maxval %f at %p\n", maxval, (int64_t)maxp);
400 #endif
401         }
402         autop++;
403       }
404       //printf("**** maxval = %f ****\n", maxval);
405       period = p->mindist + maxp - p->autobuf;
406       if (period != p->period) {
407 #if 0
408         csound->Message(csound, "New period %d %d\n", period, p->period);
409 #endif
410         p->period = period;
411         if (!p->cpsmode)
412           p->lsicvt = FL(65536.0) / period;
413         p->pnt1 = (int32)((MYFLT)period * FL(0.2));
414         p->pnt2 = (int32)((MYFLT)period * FL(0.8));
415         p->pnt3 = period;
416         p->inc1 = FL(1.0) / p->pnt1;
417         p->inc2 = FL(1.0) / (period - p->pnt2);
418       }
419     }
420     else period = p->period;
421 
422     minval = (MYFLT)HUGE_VAL;               /* Suitably large ! */
423     minq2 = inq2 - period;                  /* srch the qbuf for minima */
424     minq1 = minq2 - period;                 /* which are 1 period apart */
425     endp = inq2;                            /* move srch over 1 period  */
426     while (minq2 < endp) {
427       if ((sum = *minq1 + *minq2) < minval) {
428         minval = sum;
429         minqp = minq1;
430       }
431       minq1++; minq2++;
432     }
433     src1 = minqp - p->n2bufsmps;            /* get src equiv of 1st min  */
434     if (period==0) {
435       csound->Warning(csound, Str("Period zero\n"));
436       outp = p->ar;
437       memset(outp, 0, sizeof(MYFLT)*CS_KSMPS);
438       return OK;
439     }
440     while (src1 + CS_KSMPS > inp2)     /* if not enough smps presnt */
441       src1 -= period;                       /*      back up 1 prd        */
442     pulstrt = src1;                         /* curr available pulse beg  */
443 
444     src1 = p->puls1;                        /* insert pulses into output */
445     src2 = p->puls2;
446     src3 = p->puls3;
447     lin1 = p->lin1;
448     lin2 = p->lin2;
449     lin3 = p->lin3;
450     cnt1 = p->cnt1;
451     cnt2 = p->cnt2;
452     cnt3 = p->cnt3;
453     phase1 = p->phase1;
454     phase2 = p->phase2;
455     phsinc1 = (int32)(*p->kfrq1 * p->lsicvt);
456     phsinc2 = (int32)(*p->kfrq2 * p->lsicvt);
457     for (n=offset; n<nsmps; n++) {
458       MYFLT sum;
459       if (src1 != NULL) {
460         if (++cnt1 < p->pnt11) {
461           sum = *src1++ * lin1;
462           lin1 += p->inc11;
463         }
464         else if (cnt1 <= p->pnt12)
465           sum = *src1++;
466         else if (cnt1 <= p->pnt13) {
467           sum = *src1++ * lin1;
468           lin1 -= p->inc12;
469         }
470         else {
471           sum = FL(0.0);
472           src1 = NULL;
473         }
474       }
475       else sum = FL(0.0);
476       if (src2 != NULL) {
477         if (++cnt2 < p->pnt21) {
478           sum += *src2++ * lin2;
479           lin2 += p->inc21;
480         }
481         else if (cnt2 <= p->pnt22)
482           sum += *src2++;
483         else if (cnt2 <= p->pnt23) {
484           sum += *src2++ * lin2;
485           lin2 -= p->inc22;
486         }
487         else src2 = NULL;
488       }
489       if (src3 != NULL) {
490         if (++cnt3 < p->pnt31) {
491           sum += *src3++ * lin3;
492           lin3 += p->inc31;
493         }
494         else if (cnt3 <= p->pnt32)
495           sum += *src3++;
496         else if (cnt3 <= p->pnt33) {
497           sum += *src3++ * lin3;
498           lin3 -= p->inc32;
499         }
500         else src3 = NULL;
501       }
502       if ((phase1 += phsinc1) & (~0xFFFFL)) { /* 64bit safe! */
503         phase1 &= 0x0000FFFFL;
504         if (src1 == NULL) {
505           src1 = pulstrt;
506           cnt1 = 0;
507           lin1 = p->inc1;
508           p->inc11 = p->inc1;
509           p->inc12 = p->inc2;
510           p->pnt11 = p->pnt1;
511           p->pnt12 = p->pnt2;
512           p->pnt13 = p->pnt3;
513         }
514         else if (src2 == NULL) {
515           src2 = pulstrt;
516           cnt2 = 0;
517           lin2 = p->inc1;
518           p->inc21 = p->inc1;
519           p->inc22 = p->inc2;
520           p->pnt21 = p->pnt1;
521           p->pnt22 = p->pnt2;
522           p->pnt23 = p->pnt3;
523         }
524         else if (src3 == NULL) {
525           src3 = pulstrt;
526           cnt3 = 0;
527           lin3 = p->inc1;
528           p->inc31 = p->inc1;
529           p->inc32 = p->inc2;
530           p->pnt31 = p->pnt1;
531           p->pnt32 = p->pnt2;
532           p->pnt33 = p->pnt3;
533         }
534 #if 0
535         else if (UNLIKELY(++hrngflg > 200)) {
536           csound->Message(csound, Str("harmon out of range...\n"));
537           hrngflg = 0;
538         }
539 #endif
540       }
541       if ((phase2 += phsinc2) & (~0xFFFFL)) {
542         phase2 &= 0x0000FFFFL;
543         if (src1 == NULL) {
544           src1 = pulstrt;
545           cnt1 = 0;
546           lin1 = p->inc1;
547           p->inc11 = p->inc1;
548           p->inc12 = p->inc2;
549           p->pnt11 = p->pnt1;
550           p->pnt12 = p->pnt2;
551           p->pnt13 = p->pnt3;
552         }
553         else if (src2 == NULL) {
554           src2 = pulstrt;
555           cnt2 = 0;
556           lin2 = p->inc1;
557           p->inc21 = p->inc1;
558           p->inc22 = p->inc2;
559           p->pnt21 = p->pnt1;
560           p->pnt22 = p->pnt2;
561           p->pnt23 = p->pnt3;
562         }
563         else if (src3 == NULL) {
564           src3 = pulstrt;
565           cnt3 = 0;
566           lin3 = p->inc1;
567           p->inc31 = p->inc1;
568           p->inc32 = p->inc2;
569           p->pnt31 = p->pnt1;
570           p->pnt32 = p->pnt2;
571           p->pnt33 = p->pnt3;
572         }
573 #if 0
574         else if (UNLIKELY(++hrngflg > 200)) {
575           csound->Message(csound, Str("harmon out of range\n"));
576           hrngflg = 0;
577         }
578 #endif
579       }
580       outp[n] = sum;
581     }
582     if (inp1 >= p->midp) {
583       p->inp1 = p->bufp;
584       p->inp2 = p->midp;
585       p->inq1 = p->bufq;
586       p->inq2 = p->midq;
587       if (src1 != NULL)
588         src1 -= p->nbufsmps;
589       if (src2 != NULL)
590         src2 -= p->nbufsmps;
591       if (src3 != NULL)
592         src3 -= p->nbufsmps;
593     }
594     else {
595       p->inp1 = inp1;
596       p->inp2 = inp2;
597       p->inq1 = inq1;
598       p->inq2 = inq2;
599     }
600     p->puls1 = src1;
601     p->puls2 = src2;
602     p->puls3 = src3;
603     p->lin1 = lin1;
604     p->lin2 = lin2;
605     p->lin3 = lin3;
606     p->cnt1 = cnt1;
607     p->cnt2 = cnt2;
608     p->cnt3 = cnt3;
609     p->phase1 = phase1;
610     p->phase2 = phase2;
611     p->prvq = qval;
612     return OK;
613 }
614 
615 #define S(x)    sizeof(x)
616 
617 static OENTRY localops[] =
618   {
619    { "fof",    S(FOFS),   TR, 3, "a","xxxkkkkkiiiiooo",(SUBR)fofset,(SUBR)fof   },
620    { "fof2",   S(FOFS),   TR, 3, "a","xxxkkkkkiiiikko",(SUBR)fofset2,(SUBR)fof  },
621    { "harmon", S(HARMON), 0,3, "a",  "akkkkiii",(SUBR)harmset,  (SUBR)harmon  }
622 };
623 
ugens7_init_(CSOUND * csound)624 int32_t ugens7_init_(CSOUND *csound)
625 {
626     return csound->AppendOpcodes(csound, &(localops[0]),
627                                  (int32_t) (sizeof(localops) / sizeof(OENTRY)));
628 }
629 
630