1 /*
2 ugensa.c:
3
4 Copyright (C) 1997 J. Michael Clarke, based on ideas from CHANT (IRCAM)
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 "stdopcod.h" /* UGENSA.C */
25 #include "ugensa.h"
26 #include "ugens7.h"
27 #include <math.h>
28
29 /* FOG generator */
30
31 static int32_t newpulse(CSOUND *, FOGS *, OVERLAP *, MYFLT *, MYFLT *, MYFLT *);
32
fogset(CSOUND * csound,FOGS * p)33 static int32_t fogset(CSOUND *csound, FOGS *p)
34 {
35 /* legato test, not sure if the last bit (auxch) is correct? */
36 int32_t skip = (*p->iskip != FL(0.0) && p->auxch.auxp != 0);
37 if (LIKELY((p->ftp1 = csound->FTFind(csound, p->ifna)) != NULL &&
38 (p->ftp2 = csound->FTFind(csound, p->ifnb)) != NULL)) {
39 OVERLAP *ovp, *nxtovp;
40 int32 olaps;
41 p->fogcvt = FMAXLEN/(p->ftp1)->flen; /*JMC for FOG*/
42 p->durtogo = (int32)(*p->itotdur * CS_ESR);
43 if (!skip) { /* legato: skip all memory management */
44 p->spdphs = 0L; /*JMC for FOG*/
45 if (*p->iphs == FL(0.0)) /* if fundphs zero, */
46 p->fundphs = MAXLEN; /* trigger new FOF */
47 else p->fundphs = (int32)(*p->iphs * FMAXLEN) & PHMASK;
48 if (UNLIKELY((olaps = (int32)*p->iolaps) <= 0)) {
49 return csound->InitError(csound, Str("illegal value for iolaps"));
50 }
51 if (*p->iphs>=FL(0.0))
52 csound->AuxAlloc(csound, (size_t)olaps * sizeof(OVERLAP), &p->auxch);
53 ovp = &p->basovrlap;
54 nxtovp = (OVERLAP *) p->auxch.auxp;
55 do {
56 ovp->nxtact = NULL;
57 ovp->nxtfree = nxtovp; /* link the ovlap spaces */
58 ovp = nxtovp++;
59 } while (--olaps);
60 ovp->nxtact = NULL;
61 ovp->nxtfree = NULL;
62 p->fofcount = -1;
63 p->prvband = FL(0.0);
64 p->expamp = FL(1.0);
65 p->prvsmps = 0;
66 p->preamp = FL(1.0);
67 }
68 p->ampcod = IS_ASIG_ARG(p->xamp) ? 1 : 0;
69 p->fundcod = IS_ASIG_ARG(p->xdens) ? 1 : 0;
70 p->formcod = IS_ASIG_ARG(p->xtrans) ? 1 : 0;
71 p->xincod = p->ampcod || p->fundcod || p->formcod;
72 /* p->speedcod = (p->XINCODE & 0x8) ? 1 : 0; */ /*out for phs version of fog*/
73 p->fmtmod = (*p->itmode == 0.0) ? 0 : 1;
74 }
75 else return NOTOK;
76 return OK;
77 }
78
fog(CSOUND * csound,FOGS * p)79 static int32_t fog(CSOUND *csound, FOGS *p)
80 {
81 OVERLAP *ovp;
82 FUNC *ftp1, *ftp2;
83 MYFLT *ar, *amp, *fund, *ptch, *speed;
84 MYFLT v1, fract ,*ftab, fogcvt = p->fogcvt; /*JMC added for FOG*/
85 uint32_t offset = p->h.insdshead->ksmps_offset;
86 uint32_t early = p->h.insdshead->ksmps_no_end;
87 uint32_t n, nsmps = CS_KSMPS;
88 int32 fund_inc, form_inc;
89 /* int64_t speed_inc; */ /*JMC added last--out for phs version*/
90
91 ar = p->ar;
92 amp = p->xamp;
93 fund = p->xdens;
94 ptch = p->xtrans;
95 speed = p->xspd;
96 ftp1 = p->ftp1;
97 ftp2 = p->ftp2;
98 fund_inc = (int32)(*fund * csound->sicvt);
99 form_inc = (int32)(*ptch * fogcvt); /*form_inc = *form * csound->sicvt;*/
100 /* speed_inc = *speed * fogcvt; */ /*JMC for FOG--out for phs version*/
101 if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT));
102 if (UNLIKELY(early)) {
103 nsmps -= early;
104 memset(&ar[nsmps], '\0', early*sizeof(MYFLT));
105 }
106 for (n=offset;n<nsmps;n++) {
107 if (p->fundphs & MAXLEN) { /* if phs has wrapped */
108 p->fundphs &= PHMASK;
109 if (UNLIKELY((ovp = p->basovrlap.nxtfree) == NULL)) goto err1;
110 if (newpulse(csound, p, ovp, amp, fund, ptch)) { /* init new fof */
111 ovp->nxtact = p->basovrlap.nxtact; /* & link into */
112 p->basovrlap.nxtact = ovp; /* actlist */
113 p->basovrlap.nxtfree = ovp->nxtfree;
114 }
115 }
116 ar[n] = FL(0.0);
117 ovp = &p->basovrlap;
118 while (ovp->nxtact != NULL) { /* perform cur actlist: */
119 MYFLT result;
120 OVERLAP *prvact = ovp;
121 ovp = ovp->nxtact; /* formant waveform */
122 fract = PFRAC1(ovp->formphs); /*JMC Fog*/
123 ftab = ftp1->ftable + (ovp->formphs >> ftp1->lobits);/*JMC Fog*/
124 v1 = *ftab++; /*JMC Fog*/
125 result = v1 + (*ftab - v1) * fract; /*JMC Fog*/
126 /* result = *(ftp1->ftable + (ovp->formphs >> ftp1->lobits) ); FOF version*/
127 if (p->fmtmod)
128 ovp->formphs += form_inc; /* inc phs on mode */
129 else ovp->formphs += ovp->forminc;
130 ovp->formphs &= PHMASK;
131 if (ovp->risphs < MAXLEN) { /* formant ris envlp */
132 result *= *(ftp2->ftable + (ovp->risphs >> ftp2->lobits) );
133 ovp->risphs += ovp->risinc;
134 }
135 if (ovp->timrem <= ovp->dectim) { /* formant dec envlp */
136 result *= *(ftp2->ftable + (ovp->decphs >> ftp2->lobits) );
137 if ((ovp->decphs -= ovp->decinc) < 0)
138 ovp->decphs = 0;
139 }
140 ar[n] += (result * ovp->curamp); /* add wavfrm to out */
141 if (--ovp->timrem) /* if fof not expird */
142 ovp->curamp *= ovp->expamp; /* apply bw exp dec */
143 else {
144 prvact->nxtact = ovp->nxtact; /* else rm frm activ */
145 ovp->nxtfree = p->basovrlap.nxtfree;/* & ret spc to free */
146 p->basovrlap.nxtfree = ovp;
147 ovp = prvact;
148 }
149 }
150 p->fundphs += fund_inc;
151 /* p->spdphs += speed_inc; */ /*JMC for FOG*/
152 p->spdphs = (int32)(speed[n] * FMAXLEN); /*for phs version of FOG*/
153 p->spdphs &= PHMASK; /*JMC for FOG*/
154 if (p->xincod) {
155 if (p->ampcod) amp++;
156 if (p->fundcod) fund_inc = (int32)(*++fund * csound->sicvt);
157 if (p->formcod) form_inc = (int32)(*++ptch * fogcvt);
158 /*form_inc = *++form * csound->sicvt;*/
159 /* if (p->speedcod) speed_inc = *++speed * fogcvt; */ /*JMC for FOG*/
160 }
161 p->durtogo--;
162 }
163 return OK;
164 err1:
165 return csound->PerfError(csound, &(p->h),
166 Str("FOF needs more overlaps"));
167 }
168
newpulse(CSOUND * csound,FOGS * p,OVERLAP * ovp,MYFLT * amp,MYFLT * fund,MYFLT * ptch)169 static int32_t newpulse(CSOUND *csound, FOGS *p, OVERLAP *ovp, MYFLT *amp,
170 MYFLT *fund, MYFLT *ptch)
171 {
172 MYFLT octamp = *amp, oct;
173 MYFLT form = *ptch / csound->sicvt, fogcvt = p->fogcvt;
174 int32 rismps, newexp = 0;
175 if ((ovp->timrem = (int32)(*p->kdur * CS_ESR)) > p->durtogo &&
176 (*p->iskip==FL(0.0))) /* ringtime */
177 return(0);
178 if ((oct = *p->koct) > 0.0) { /* octaviation */
179 int64_t cnst = -1L;
180 int32 ioct = (int32)oct, bitpat = ~(cnst << ioct);
181 if (bitpat & ++p->fofcount)
182 return(0);
183 if ((bitpat += 1) & p->fofcount)
184 octamp *= (FL(1.0) + ioct - oct);
185 }
186 if (*fund == 0.0) /* formant phs */
187 ovp->formphs = 0;
188 /* else
189 ovp->formphs = (int32)((p->fundphs * form / *fund) + p->spdphs) & PHMASK; */
190 else ovp->formphs = (int32)(p->fundphs * form / *fund) & PHMASK;
191 ovp->forminc = (int32)(*ptch * fogcvt);/*JMC for FOG*/
192 /*ovp->forminc = *form * csound->sicvt;*/
193 if (*p->kband != p->prvband) { /* bw: exp dec */
194 p->prvband = *p->kband;
195 p->expamp = EXP(*p->kband * csound->mpidsr);
196 newexp = 1;
197 }
198 if (*p->kris >= csound->onedsr && form != 0.0) { /* init fnb ris */
199 ovp->risphs = (uint32)(ovp->formphs / (fabs(form))
200 / *p->kris); /* JPff fix */
201 ovp->risinc = (int32)(csound->sicvt / *p->kris);
202 rismps = MAXLEN / ovp->risinc;
203 }
204 else {
205 ovp->risphs = MAXLEN;
206 rismps = 0;
207 }
208
209 /* p->spdphs (soundfile ftable index) must be added to
210 ovp->formphs (sound ftable reading rate)
211 AFTER ovp-risphs is calculated */
212 ovp->formphs = (ovp->formphs + p->spdphs) & PHMASK;
213
214 if (newexp || rismps != p->prvsmps) { /* if new params */
215 if ((p->prvsmps = rismps)) /* redo preamp */
216 p->preamp = csound->intpow(p->expamp, -rismps);
217 else p->preamp = FL(1.0);
218 }
219 ovp->curamp = octamp * p->preamp; /* set startamp */
220 ovp->expamp = p->expamp;
221 if ((ovp->dectim = (int32)(*p->kdec * CS_ESR)) > 0) /* fnb dec */
222 ovp->decinc = (int32)(csound->sicvt / *p->kdec);
223 ovp->decphs = PHMASK;
224 return(1);
225 }
226
227 /* JMC test additional UG */
228 #define S(x) sizeof(x)
229
230 static OENTRY localops[] = {
231 { "fog", S(FOGS), TR, 3, "a","xxxakkkkkiiiiooo",(SUBR)fogset,(SUBR)fog}
232 };
233
ugensa_init_(CSOUND * csound)234 int32_t ugensa_init_(CSOUND *csound)
235 {
236 return csound->AppendOpcodes(csound, &(localops[0]),
237 (int32_t) (sizeof(localops) / sizeof(OENTRY)));
238 }
239
240