Unified · Split
Binary file not shown.
Binary file not shown.
| @@ -1,11 +0,0 @@ | ||
| 1 | −*.DS_Store | |
| 2 | −*.app | |
| 3 | −*.a | |
| 4 | −*.appex | |
| 5 | −*.vst | |
| 6 | −*.vst3 | |
| 7 | −*.component | |
| 8 | −*.xcuserstate | |
| 9 | −*.zip | |
| 10 | −*.swp | |
| 11 | −*/Builds | |
Binary file not shown.
| @@ -1,423 +0,0 @@ | ||
| 1 | −/* | |
| 2 | −** FFT and FHT routines | |
| 3 | −** Copyright 1988, 1993; Ron Mayer | |
| 4 | −** | |
| 5 | −** mayer_fht(fz,n); | |
| 6 | −** Does a hartley transform of "n" points in the array "fz". | |
| 7 | −** mayer_fft(n,real,imag) | |
| 8 | −** Does a fourier transform of "n" points of the "real" and | |
| 9 | −** "imag" arrays. | |
| 10 | −** mayer_ifft(n,real,imag) | |
| 11 | −** Does an inverse fourier transform of "n" points of the "real" | |
| 12 | −** and "imag" arrays. | |
| 13 | −** mayer_realfft(n,real) | |
| 14 | −** Does a real-valued fourier transform of "n" points of the | |
| 15 | −** "real" array. The real part of the transform ends | |
| 16 | −** up in the first half of the array and the imaginary part of the | |
| 17 | −** transform ends up in the second half of the array. | |
| 18 | −** mayer_realifft(n,real) | |
| 19 | −** The inverse of the realfft() routine above. | |
| 20 | −** | |
| 21 | −** | |
| 22 | −** NOTE: This routine uses at least 2 patented algorithms, and may be | |
| 23 | −** under the restrictions of a bunch of different organizations. | |
| 24 | −** Although I wrote it completely myself, it is kind of a derivative | |
| 25 | −** of a routine I once authored and released under the GPL, so it | |
| 26 | −** may fall under the free software foundation's restrictions; | |
| 27 | −** it was worked on as a Stanford Univ project, so they claim | |
| 28 | −** some rights to it; it was further optimized at work here, so | |
| 29 | −** I think this company claims parts of it. The patents are | |
| 30 | −** held by R. Bracewell (the FHT algorithm) and O. Buneman (the | |
| 31 | −** trig generator), both at Stanford Univ. | |
| 32 | −** If it were up to me, I'd say go do whatever you want with it; | |
| 33 | −** but it would be polite to give credit to the following people | |
| 34 | −** if you use this anywhere: | |
| 35 | −** Euler - probable inventor of the fourier transform. | |
| 36 | −** Gauss - probable inventor of the FFT. | |
| 37 | −** Hartley - probable inventor of the hartley transform. | |
| 38 | −** Buneman - for a really cool trig generator | |
| 39 | −** Mayer(me) - for authoring this particular version and | |
| 40 | −** including all the optimizations in one package. | |
| 41 | −** Thanks, | |
| 42 | −** Ron Mayer; mayer@acuson.com | |
| 43 | −** | |
| 44 | −*/ | |
| 45 | − | |
| 46 | −/* This is a slightly modified version of Mayer's contribution; write | |
| 47 | −* msp@ucsd.edu for the original code. Kudos to Mayer for a fine piece | |
| 48 | −* of work. -msp | |
| 49 | −*/ | |
| 50 | − | |
| 51 | −/* These pragmas are only used for MSVC, not MinGW or Cygwin <hans@at.or.at> */ | |
| 52 | −#ifdef _MSC_VER | |
| 53 | −#pragma warning( disable : 4305 ) /* uncast const double to float */ | |
| 54 | −#pragma warning( disable : 4244 ) /* uncast double to float */ | |
| 55 | −#pragma warning( disable : 4101 ) /* unused local variables */ | |
| 56 | −#endif | |
| 57 | − | |
| 58 | −/* the following is needed only to declare pd_fft() as exportable in MSW */ | |
| 59 | −#define t_sample float | |
| 60 | − | |
| 61 | −#define REAL t_sample | |
| 62 | −#define GOOD_TRIG | |
| 63 | − | |
| 64 | −#ifdef GOOD_TRIG | |
| 65 | −#else | |
| 66 | −#define FAST_TRIG | |
| 67 | −#endif | |
| 68 | − | |
| 69 | −#if defined(GOOD_TRIG) | |
| 70 | −#define FHT_SWAP(a,b,t) {(t)=(a);(a)=(b);(b)=(t);} | |
| 71 | −#define TRIG_VARS \ | |
| 72 | − int t_lam=0; | |
| 73 | −#define TRIG_INIT(k,c,s) \ | |
| 74 | − { \ | |
| 75 | − int i; \ | |
| 76 | − for (i=2 ; i<=k ; i++) \ | |
| 77 | − {coswrk[i]=costab[i];sinwrk[i]=sintab[i];} \ | |
| 78 | − t_lam = 0; \ | |
| 79 | − c = 1; \ | |
| 80 | − s = 0; \ | |
| 81 | − } | |
| 82 | −#define TRIG_NEXT(k,c,s) \ | |
| 83 | − { \ | |
| 84 | − int i,j; \ | |
| 85 | − (t_lam)++; \ | |
| 86 | − for (i=0 ; !((1<<i)&t_lam) ; i++); \ | |
| 87 | − i = k-i; \ | |
| 88 | − s = sinwrk[i]; \ | |
| 89 | − c = coswrk[i]; \ | |
| 90 | − if (i>1) \ | |
| 91 | − { \ | |
| 92 | − for (j=k-i+2 ; (1<<j)&t_lam ; j++); \ | |
| 93 | − j = k - j; \ | |
| 94 | − sinwrk[i] = halsec[i] * (sinwrk[i-1] + sinwrk[j]); \ | |
| 95 | − coswrk[i] = halsec[i] * (coswrk[i-1] + coswrk[j]); \ | |
| 96 | − } \ | |
| 97 | − } | |
| 98 | −#define TRIG_RESET(k,c,s) | |
| 99 | −#endif | |
| 100 | − | |
| 101 | −#if defined(FAST_TRIG) | |
| 102 | −#define TRIG_VARS \ | |
| 103 | − REAL t_c,t_s; | |
| 104 | −#define TRIG_INIT(k,c,s) \ | |
| 105 | − { \ | |
| 106 | − t_c = costab[k]; \ | |
| 107 | − t_s = sintab[k]; \ | |
| 108 | − c = 1; \ | |
| 109 | − s = 0; \ | |
| 110 | − } | |
| 111 | −#define TRIG_NEXT(k,c,s) \ | |
| 112 | − { \ | |
| 113 | − REAL t = c; \ | |
| 114 | − c = t*t_c - s*t_s; \ | |
| 115 | − s = t*t_s + s*t_c; \ | |
| 116 | − } | |
| 117 | −#define TRIG_RESET(k,c,s) | |
| 118 | −#endif | |
| 119 | − | |
| 120 | −static REAL halsec[20]= | |
| 121 | − { | |
| 122 | − 0, | |
| 123 | − 0, | |
| 124 | − .54119610014619698439972320536638942006107206337801, | |
| 125 | − .50979557910415916894193980398784391368261849190893, | |
| 126 | − .50241928618815570551167011928012092247859337193963, | |
| 127 | − .50060299823519630134550410676638239611758632599591, | |
| 128 | − .50015063602065098821477101271097658495974913010340, | |
| 129 | − .50003765191554772296778139077905492847503165398345, | |
| 130 | − .50000941253588775676512870469186533538523133757983, | |
| 131 | − .50000235310628608051401267171204408939326297376426, | |
| 132 | − .50000058827484117879868526730916804925780637276181, | |
| 133 | − .50000014706860214875463798283871198206179118093251, | |
| 134 | − .50000003676714377807315864400643020315103490883972, | |
| 135 | − .50000000919178552207366560348853455333939112569380, | |
| 136 | − .50000000229794635411562887767906868558991922348920, | |
| 137 | − .50000000057448658687873302235147272458812263401372 | |
| 138 | − }; | |
| 139 | −static REAL costab[20]= | |
| 140 | − { | |
| 141 | − .00000000000000000000000000000000000000000000000000, | |
| 142 | − .70710678118654752440084436210484903928483593768847, | |
| 143 | − .92387953251128675612818318939678828682241662586364, | |
| 144 | − .98078528040323044912618223613423903697393373089333, | |
| 145 | − .99518472667219688624483695310947992157547486872985, | |
| 146 | − .99879545620517239271477160475910069444320361470461, | |
| 147 | − .99969881869620422011576564966617219685006108125772, | |
| 148 | − .99992470183914454092164649119638322435060646880221, | |
| 149 | − .99998117528260114265699043772856771617391725094433, | |
| 150 | − .99999529380957617151158012570011989955298763362218, | |
| 151 | − .99999882345170190992902571017152601904826792288976, | |
| 152 | − .99999970586288221916022821773876567711626389934930, | |
| 153 | − .99999992646571785114473148070738785694820115568892, | |
| 154 | − .99999998161642929380834691540290971450507605124278, | |
| 155 | − .99999999540410731289097193313960614895889430318945, | |
| 156 | − .99999999885102682756267330779455410840053741619428 | |
| 157 | − }; | |
| 158 | −static REAL sintab[20]= | |
| 159 | − { | |
| 160 | − 1.0000000000000000000000000000000000000000000000000, | |
| 161 | − .70710678118654752440084436210484903928483593768846, | |
| 162 | − .38268343236508977172845998403039886676134456248561, | |
| 163 | − .19509032201612826784828486847702224092769161775195, | |
| 164 | − .09801714032956060199419556388864184586113667316749, | |
| 165 | − .04906767432741801425495497694268265831474536302574, | |
| 166 | − .02454122852291228803173452945928292506546611923944, | |
| 167 | − .01227153828571992607940826195100321214037231959176, | |
| 168 | − .00613588464915447535964023459037258091705788631738, | |
| 169 | − .00306795676296597627014536549091984251894461021344, | |
| 170 | − .00153398018628476561230369715026407907995486457522, | |
| 171 | − .00076699031874270452693856835794857664314091945205, | |
| 172 | − .00038349518757139558907246168118138126339502603495, | |
| 173 | − .00019174759731070330743990956198900093346887403385, | |
| 174 | − .00009587379909597734587051721097647635118706561284, | |
| 175 | − .00004793689960306688454900399049465887274686668768 | |
| 176 | − }; | |
| 177 | −static REAL coswrk[20]= | |
| 178 | − { | |
| 179 | − .00000000000000000000000000000000000000000000000000, | |
| 180 | − .70710678118654752440084436210484903928483593768847, | |
| 181 | − .92387953251128675612818318939678828682241662586364, | |
| 182 | − .98078528040323044912618223613423903697393373089333, | |
| 183 | − .99518472667219688624483695310947992157547486872985, | |
| 184 | − .99879545620517239271477160475910069444320361470461, | |
| 185 | − .99969881869620422011576564966617219685006108125772, | |
| 186 | − .99992470183914454092164649119638322435060646880221, | |
| 187 | − .99998117528260114265699043772856771617391725094433, | |
| 188 | − .99999529380957617151158012570011989955298763362218, | |
| 189 | − .99999882345170190992902571017152601904826792288976, | |
| 190 | − .99999970586288221916022821773876567711626389934930, | |
| 191 | − .99999992646571785114473148070738785694820115568892, | |
| 192 | − .99999998161642929380834691540290971450507605124278, | |
| 193 | − .99999999540410731289097193313960614895889430318945, | |
| 194 | − .99999999885102682756267330779455410840053741619428 | |
| 195 | − }; | |
| 196 | −static REAL sinwrk[20]= | |
| 197 | − { | |
| 198 | − 1.0000000000000000000000000000000000000000000000000, | |
| 199 | − .70710678118654752440084436210484903928483593768846, | |
| 200 | − .38268343236508977172845998403039886676134456248561, | |
| 201 | − .19509032201612826784828486847702224092769161775195, | |
| 202 | − .09801714032956060199419556388864184586113667316749, | |
| 203 | − .04906767432741801425495497694268265831474536302574, | |
| 204 | − .02454122852291228803173452945928292506546611923944, | |
| 205 | − .01227153828571992607940826195100321214037231959176, | |
| 206 | − .00613588464915447535964023459037258091705788631738, | |
| 207 | − .00306795676296597627014536549091984251894461021344, | |
| 208 | − .00153398018628476561230369715026407907995486457522, | |
| 209 | − .00076699031874270452693856835794857664314091945205, | |
| 210 | − .00038349518757139558907246168118138126339502603495, | |
| 211 | − .00019174759731070330743990956198900093346887403385, | |
| 212 | − .00009587379909597734587051721097647635118706561284, | |
| 213 | − .00004793689960306688454900399049465887274686668768 | |
| 214 | − }; | |
| 215 | − | |
| 216 | − | |
| 217 | −#define SQRT2_2 0.70710678118654752440084436210484 | |
| 218 | −#define SQRT2 2*0.70710678118654752440084436210484 | |
| 219 | − | |
| 220 | −void mayer_fht(REAL *fz, int n) | |
| 221 | −{ | |
| 222 | −/* REAL a,b; | |
| 223 | −REAL c1,s1,s2,c2,s3,c3,s4,c4; | |
| 224 | − REAL f0,g0,f1,g1,f2,g2,f3,g3; */ | |
| 225 | − int k,k1,k2,k3,k4,kx; | |
| 226 | − REAL *fi,*fn,*gi; | |
| 227 | − TRIG_VARS; | |
| 228 | − | |
| 229 | − for (k1=1,k2=0;k1<n;k1++) | |
| 230 | − { | |
| 231 | − REAL aa; | |
| 232 | − for (k=n>>1; (!((k2^=k)&k)); k>>=1); | |
| 233 | − if (k1>k2) | |
| 234 | − { | |
| 235 | − aa=fz[k1];fz[k1]=fz[k2];fz[k2]=aa; | |
| 236 | − } | |
| 237 | − } | |
| 238 | − for ( k=0 ; (1<<k)<n ; k++ ); | |
| 239 | − k &= 1; | |
| 240 | − if (k==0) | |
| 241 | − { | |
| 242 | − for (fi=fz,fn=fz+n;fi<fn;fi+=4) | |
| 243 | − { | |
| 244 | − REAL f0,f1,f2,f3; | |
| 245 | − f1 = fi[0 ]-fi[1 ]; | |
| 246 | − f0 = fi[0 ]+fi[1 ]; | |
| 247 | − f3 = fi[2 ]-fi[3 ]; | |
| 248 | − f2 = fi[2 ]+fi[3 ]; | |
| 249 | − fi[2 ] = (f0-f2); | |
| 250 | − fi[0 ] = (f0+f2); | |
| 251 | − fi[3 ] = (f1-f3); | |
| 252 | − fi[1 ] = (f1+f3); | |
| 253 | − } | |
| 254 | − } | |
| 255 | − else | |
| 256 | − { | |
| 257 | − for (fi=fz,fn=fz+n,gi=fi+1;fi<fn;fi+=8,gi+=8) | |
| 258 | − { | |
| 259 | − REAL bs1,bc1,bs2,bc2,bs3,bc3,bs4,bc4, | |
| 260 | − bg0,bf0,bf1,bg1,bf2,bg2,bf3,bg3; | |
| 261 | − bc1 = fi[0 ] - gi[0 ]; | |
| 262 | − bs1 = fi[0 ] + gi[0 ]; | |
| 263 | − bc2 = fi[2 ] - gi[2 ]; | |
| 264 | − bs2 = fi[2 ] + gi[2 ]; | |
| 265 | − bc3 = fi[4 ] - gi[4 ]; | |
| 266 | − bs3 = fi[4 ] + gi[4 ]; | |
| 267 | − bc4 = fi[6 ] - gi[6 ]; | |
| 268 | − bs4 = fi[6 ] + gi[6 ]; | |
| 269 | − bf1 = (bs1 - bs2); | |
| 270 | − bf0 = (bs1 + bs2); | |
| 271 | − bg1 = (bc1 - bc2); | |
| 272 | − bg0 = (bc1 + bc2); | |
| 273 | − bf3 = (bs3 - bs4); | |
| 274 | − bf2 = (bs3 + bs4); | |
| 275 | − bg3 = SQRT2*bc4; | |
| 276 | − bg2 = SQRT2*bc3; | |
| 277 | − fi[4 ] = bf0 - bf2; | |
| 278 | − fi[0 ] = bf0 + bf2; | |
| 279 | − fi[6 ] = bf1 - bf3; | |
| 280 | − fi[2 ] = bf1 + bf3; | |
| 281 | − gi[4 ] = bg0 - bg2; | |
| 282 | − gi[0 ] = bg0 + bg2; | |
| 283 | − gi[6 ] = bg1 - bg3; | |
| 284 | − gi[2 ] = bg1 + bg3; | |
| 285 | − } | |
| 286 | − } | |
| 287 | − if (n<16) return; | |
| 288 | − | |
| 289 | − do | |
| 290 | − { | |
| 291 | − REAL s1,c1; | |
| 292 | − int ii; | |
| 293 | − k += 2; | |
| 294 | − k1 = 1 << k; | |
| 295 | − k2 = k1 << 1; | |
| 296 | − k4 = k2 << 1; | |
| 297 | − k3 = k2 + k1; | |
| 298 | − kx = k1 >> 1; | |
| 299 | − fi = fz; | |
| 300 | − gi = fi + kx; | |
| 301 | − fn = fz + n; | |
| 302 | − do | |
| 303 | − { | |
| 304 | − REAL g0,f0,f1,g1,f2,g2,f3,g3; | |
| 305 | − f1 = fi[0 ] - fi[k1]; | |
| 306 | − f0 = fi[0 ] + fi[k1]; | |
| 307 | − f3 = fi[k2] - fi[k3]; | |
| 308 | − f2 = fi[k2] + fi[k3]; | |
| 309 | − fi[k2] = f0 - f2; | |
| 310 | − fi[0 ] = f0 + f2; | |
| 311 | − fi[k3] = f1 - f3; | |
| 312 | − fi[k1] = f1 + f3; | |
| 313 | − g1 = gi[0 ] - gi[k1]; | |
| 314 | − g0 = gi[0 ] + gi[k1]; | |
| 315 | − g3 = SQRT2 * gi[k3]; | |
| 316 | − g2 = SQRT2 * gi[k2]; | |
| 317 | − gi[k2] = g0 - g2; | |
| 318 | − gi[0 ] = g0 + g2; | |
| 319 | − gi[k3] = g1 - g3; | |
| 320 | − gi[k1] = g1 + g3; | |
| 321 | − gi += k4; | |
| 322 | − fi += k4; | |
| 323 | − } while (fi<fn); | |
| 324 | − TRIG_INIT(k,c1,s1); | |
| 325 | − for (ii=1;ii<kx;ii++) | |
| 326 | − { | |
| 327 | − REAL c2,s2; | |
| 328 | − TRIG_NEXT(k,c1,s1); | |
| 329 | − c2 = c1*c1 - s1*s1; | |
| 330 | − s2 = 2*(c1*s1); | |
| 331 | − fn = fz + n; | |
| 332 | − fi = fz +ii; | |
| 333 | − gi = fz +k1-ii; | |
| 334 | − do | |
| 335 | − { | |
| 336 | − REAL a,b,g0,f0,f1,g1,f2,g2,f3,g3; | |
| 337 | − b = s2*fi[k1] - c2*gi[k1]; | |
| 338 | − a = c2*fi[k1] + s2*gi[k1]; | |
| 339 | − f1 = fi[0 ] - a; | |
| 340 | − f0 = fi[0 ] + a; | |
| 341 | − g1 = gi[0 ] - b; | |
| 342 | − g0 = gi[0 ] + b; | |
| 343 | − b = s2*fi[k3] - c2*gi[k3]; | |
| 344 | − a = c2*fi[k3] + s2*gi[k3]; | |
| 345 | − f3 = fi[k2] - a; | |
| 346 | − f2 = fi[k2] + a; | |
| 347 | − g3 = gi[k2] - b; | |
| 348 | − g2 = gi[k2] + b; | |
| 349 | − b = s1*f2 - c1*g3; | |
| 350 | − a = c1*f2 + s1*g3; | |
| 351 | − fi[k2] = f0 - a; | |
| 352 | − fi[0 ] = f0 + a; | |
| 353 | − gi[k3] = g1 - b; | |
| 354 | − gi[k1] = g1 + b; | |
| 355 | − b = c1*g2 - s1*f3; | |
| 356 | − a = s1*g2 + c1*f3; | |
| 357 | − gi[k2] = g0 - a; | |
| 358 | − gi[0 ] = g0 + a; | |
| 359 | − fi[k3] = f1 - b; | |
| 360 | − fi[k1] = f1 + b; | |
| 361 | − gi += k4; | |
| 362 | − fi += k4; | |
| 363 | − } while (fi<fn); | |
| 364 | − } | |
| 365 | − TRIG_RESET(k,c1,s1); | |
| 366 | − } while (k4<n); | |
| 367 | −} | |
| 368 | − | |
| 369 | −void mayer_fft(int n, REAL *real, REAL *imag) | |
| 370 | −{ | |
| 371 | − REAL a,b,c,d; | |
| 372 | − REAL q,r,s,t; | |
| 373 | − int i,j,k; | |
| 374 | − for (i=1,j=n-1,k=n/2;i<k;i++,j--) { | |
| 375 | − a = real[i]; b = real[j]; q=a+b; r=a-b; | |
| 376 | − c = imag[i]; d = imag[j]; s=c+d; t=c-d; | |
| 377 | − real[i] = (q+t)*.5; real[j] = (q-t)*.5; | |
| 378 | − imag[i] = (s-r)*.5; imag[j] = (s+r)*.5; | |
| 379 | − } | |
| 380 | − mayer_fht(real,n); | |
| 381 | − mayer_fht(imag,n); | |
| 382 | −} | |
| 383 | − | |
| 384 | −void mayer_ifft(int n, REAL *real, REAL *imag) | |
| 385 | −{ | |
| 386 | − REAL a,b,c,d; | |
| 387 | − REAL q,r,s,t; | |
| 388 | − int i,j,k; | |
| 389 | − mayer_fht(real,n); | |
| 390 | − mayer_fht(imag,n); | |
| 391 | − for (i=1,j=n-1,k=n/2;i<k;i++,j--) { | |
| 392 | − a = real[i]; b = real[j]; q=a+b; r=a-b; | |
| 393 | − c = imag[i]; d = imag[j]; s=c+d; t=c-d; | |
| 394 | − imag[i] = (s+r)*0.5; imag[j] = (s-r)*0.5; | |
| 395 | − real[i] = (q-t)*0.5; real[j] = (q+t)*0.5; | |
| 396 | − } | |
| 397 | −} | |
| 398 | − | |
| 399 | −void mayer_realfft(int n, REAL *real) | |
| 400 | −{ | |
| 401 | − REAL a,b; | |
| 402 | − int i,j,k; | |
| 403 | − mayer_fht(real,n); | |
| 404 | − for (i=1,j=n-1,k=n/2;i<k;i++,j--) { | |
| 405 | − a = real[i]; | |
| 406 | − b = real[j]; | |
| 407 | − real[j] = (a-b)*0.5; | |
| 408 | − real[i] = (a+b)*0.5; | |
| 409 | − } | |
| 410 | −} | |
| 411 | − | |
| 412 | −void mayer_realifft(int n, REAL *real) | |
| 413 | −{ | |
| 414 | − REAL a,b; | |
| 415 | − int i,j,k; | |
| 416 | − for (i=1,j=n-1,k=n/2;i<k;i++,j--) { | |
| 417 | − a = real[i]; | |
| 418 | − b = real[j]; | |
| 419 | − real[j] = (a-b); | |
| 420 | − real[i] = (a+b); | |
| 421 | − } | |
| 422 | − mayer_fht(real,n); | |
| 423 | −} | |
| @@ -1,31 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * d_fft_mayer.h | |
| 3 | − * | |
| 4 | − * Created: 5/4/2017 10:33:59 PM | |
| 5 | − * Author: Kenny | |
| 6 | − */ | |
| 7 | − | |
| 8 | − | |
| 9 | −#ifndef D_FFT_MAYER_H_ | |
| 10 | −#define D_FFT_MAYER_H_ | |
| 11 | − | |
| 12 | −#ifdef __cplusplus | |
| 13 | −extern "C" { | |
| 14 | −#endif | |
| 15 | − | |
| 16 | −typedef float t_sample; /* a float type at most the same size */ | |
| 17 | − | |
| 18 | −#define REAL t_sample | |
| 19 | − | |
| 20 | −void mayer_fht(REAL *fz, int n); | |
| 21 | −void mayer_fft(int n, REAL *real, REAL *imag); | |
| 22 | −void mayer_ifft(int n, REAL *real, REAL *imag); | |
| 23 | −void mayer_realfft(int n, REAL *real); | |
| 24 | −void mayer_realifft(int n, REAL *real); | |
| 25 | − | |
| 26 | − | |
| 27 | −#ifdef __cplusplus | |
| 28 | −} | |
| 29 | −#endif | |
| 30 | − | |
| 31 | −#endif /* D_FFT_MAYER_H_ */ | |
| @@ -1,173 +0,0 @@ | ||
| 1 | − | |
| 2 | −/* | |
| 3 | −** Please only distribute this with it's associated FHT routine. | |
| 4 | −** This algorithm is apparently patented(!) and the code copyrighted. | |
| 5 | −** See the comment with the fht routine for more info. | |
| 6 | −** -Thanks, | |
| 7 | −** Ron Mayer | |
| 8 | −*/ | |
| 9 | − | |
| 10 | −#ifdef __cplusplus | |
| 11 | −extern "C" { | |
| 12 | −#endif | |
| 13 | − | |
| 14 | −#ifdef REAL | |
| 15 | −#else | |
| 16 | −#define REAL double | |
| 17 | −#endif | |
| 18 | − | |
| 19 | −#ifdef GOOD_TRIG | |
| 20 | −#else | |
| 21 | −#define FAST_TRIG | |
| 22 | −#endif | |
| 23 | − | |
| 24 | −#if defined(GOOD_TRIG) | |
| 25 | −#define FHT_SWAP(a,b,t) {(t)=(a);(a)=(b);(b)=(t);} | |
| 26 | −#define TRIG_VARS \ | |
| 27 | − int t_lam=0; | |
| 28 | −#define TRIG_INIT(k,c,s) \ | |
| 29 | − { \ | |
| 30 | − int i; \ | |
| 31 | − for (i=2 ; i<=k ; i++) \ | |
| 32 | − {coswrk[i]=costab[i];sinwrk[i]=sintab[i];} \ | |
| 33 | − t_lam = 0; \ | |
| 34 | − c = 1; \ | |
| 35 | − s = 0; \ | |
| 36 | − } | |
| 37 | −#define TRIG_NEXT(k,c,s) \ | |
| 38 | − { \ | |
| 39 | − int i,j; \ | |
| 40 | − (t_lam)++; \ | |
| 41 | − for (i=0 ; !((1<<i)&t_lam) ; i++); \ | |
| 42 | − i = k-i; \ | |
| 43 | − s = sinwrk[i]; \ | |
| 44 | − c = coswrk[i]; \ | |
| 45 | − if (i>1) \ | |
| 46 | − { \ | |
| 47 | − for (j=k-i+2 ; (1<<j)&t_lam ; j++); \ | |
| 48 | − j = k - j; \ | |
| 49 | − sinwrk[i] = halsec[i] * (sinwrk[i-1] + sinwrk[j]); \ | |
| 50 | − coswrk[i] = halsec[i] * (coswrk[i-1] + coswrk[j]); \ | |
| 51 | − } \ | |
| 52 | − } | |
| 53 | −#define TRIG_RESET(k,c,s) | |
| 54 | −#endif | |
| 55 | − | |
| 56 | −#if defined(FAST_TRIG) | |
| 57 | −#define TRIG_VARS \ | |
| 58 | − REAL t_c,t_s; | |
| 59 | −#define TRIG_INIT(k,c,s) \ | |
| 60 | − { \ | |
| 61 | − t_c = costab[k]; \ | |
| 62 | − t_s = sintab[k]; \ | |
| 63 | − c = 1; \ | |
| 64 | − s = 0; \ | |
| 65 | − } | |
| 66 | −#define TRIG_NEXT(k,c,s) \ | |
| 67 | − { \ | |
| 68 | − REAL t = c; \ | |
| 69 | − c = t*t_c - s*t_s; \ | |
| 70 | − s = t*t_s + s*t_c; \ | |
| 71 | − } | |
| 72 | −#define TRIG_RESET(k,c,s) | |
| 73 | −#endif | |
| 74 | − | |
| 75 | −static REAL halsec[20]= | |
| 76 | − { | |
| 77 | − 0, | |
| 78 | − 0, | |
| 79 | − .54119610014619698439972320536638942006107206337801, | |
| 80 | − .50979557910415916894193980398784391368261849190893, | |
| 81 | − .50241928618815570551167011928012092247859337193963, | |
| 82 | − .50060299823519630134550410676638239611758632599591, | |
| 83 | − .50015063602065098821477101271097658495974913010340, | |
| 84 | − .50003765191554772296778139077905492847503165398345, | |
| 85 | − .50000941253588775676512870469186533538523133757983, | |
| 86 | − .50000235310628608051401267171204408939326297376426, | |
| 87 | − .50000058827484117879868526730916804925780637276181, | |
| 88 | − .50000014706860214875463798283871198206179118093251, | |
| 89 | − .50000003676714377807315864400643020315103490883972, | |
| 90 | − .50000000919178552207366560348853455333939112569380, | |
| 91 | − .50000000229794635411562887767906868558991922348920, | |
| 92 | − .50000000057448658687873302235147272458812263401372 | |
| 93 | − }; | |
| 94 | −static REAL costab[20]= | |
| 95 | − { | |
| 96 | − .00000000000000000000000000000000000000000000000000, | |
| 97 | − .70710678118654752440084436210484903928483593768847, | |
| 98 | − .92387953251128675612818318939678828682241662586364, | |
| 99 | − .98078528040323044912618223613423903697393373089333, | |
| 100 | − .99518472667219688624483695310947992157547486872985, | |
| 101 | − .99879545620517239271477160475910069444320361470461, | |
| 102 | − .99969881869620422011576564966617219685006108125772, | |
| 103 | − .99992470183914454092164649119638322435060646880221, | |
| 104 | − .99998117528260114265699043772856771617391725094433, | |
| 105 | − .99999529380957617151158012570011989955298763362218, | |
| 106 | − .99999882345170190992902571017152601904826792288976, | |
| 107 | − .99999970586288221916022821773876567711626389934930, | |
| 108 | − .99999992646571785114473148070738785694820115568892, | |
| 109 | − .99999998161642929380834691540290971450507605124278, | |
| 110 | − .99999999540410731289097193313960614895889430318945, | |
| 111 | − .99999999885102682756267330779455410840053741619428 | |
| 112 | − }; | |
| 113 | −static REAL sintab[20]= | |
| 114 | − { | |
| 115 | − 1.0000000000000000000000000000000000000000000000000, | |
| 116 | − .70710678118654752440084436210484903928483593768846, | |
| 117 | − .38268343236508977172845998403039886676134456248561, | |
| 118 | − .19509032201612826784828486847702224092769161775195, | |
| 119 | − .09801714032956060199419556388864184586113667316749, | |
| 120 | − .04906767432741801425495497694268265831474536302574, | |
| 121 | − .02454122852291228803173452945928292506546611923944, | |
| 122 | − .01227153828571992607940826195100321214037231959176, | |
| 123 | − .00613588464915447535964023459037258091705788631738, | |
| 124 | − .00306795676296597627014536549091984251894461021344, | |
| 125 | − .00153398018628476561230369715026407907995486457522, | |
| 126 | − .00076699031874270452693856835794857664314091945205, | |
| 127 | − .00038349518757139558907246168118138126339502603495, | |
| 128 | − .00019174759731070330743990956198900093346887403385, | |
| 129 | − .00009587379909597734587051721097647635118706561284, | |
| 130 | − .00004793689960306688454900399049465887274686668768 | |
| 131 | − }; | |
| 132 | −static REAL coswrk[20]= | |
| 133 | − { | |
| 134 | − .00000000000000000000000000000000000000000000000000, | |
| 135 | − .70710678118654752440084436210484903928483593768847, | |
| 136 | − .92387953251128675612818318939678828682241662586364, | |
| 137 | − .98078528040323044912618223613423903697393373089333, | |
| 138 | − .99518472667219688624483695310947992157547486872985, | |
| 139 | − .99879545620517239271477160475910069444320361470461, | |
| 140 | − .99969881869620422011576564966617219685006108125772, | |
| 141 | − .99992470183914454092164649119638322435060646880221, | |
| 142 | − .99998117528260114265699043772856771617391725094433, | |
| 143 | − .99999529380957617151158012570011989955298763362218, | |
| 144 | − .99999882345170190992902571017152601904826792288976, | |
| 145 | − .99999970586288221916022821773876567711626389934930, | |
| 146 | − .99999992646571785114473148070738785694820115568892, | |
| 147 | − .99999998161642929380834691540290971450507605124278, | |
| 148 | − .99999999540410731289097193313960614895889430318945, | |
| 149 | − .99999999885102682756267330779455410840053741619428 | |
| 150 | − }; | |
| 151 | −static REAL sinwrk[20]= | |
| 152 | − { | |
| 153 | − 1.0000000000000000000000000000000000000000000000000, | |
| 154 | − .70710678118654752440084436210484903928483593768846, | |
| 155 | − .38268343236508977172845998403039886676134456248561, | |
| 156 | − .19509032201612826784828486847702224092769161775195, | |
| 157 | − .09801714032956060199419556388864184586113667316749, | |
| 158 | − .04906767432741801425495497694268265831474536302574, | |
| 159 | − .02454122852291228803173452945928292506546611923944, | |
| 160 | − .01227153828571992607940826195100321214037231959176, | |
| 161 | − .00613588464915447535964023459037258091705788631738, | |
| 162 | − .00306795676296597627014536549091984251894461021344, | |
| 163 | − .00153398018628476561230369715026407907995486457522, | |
| 164 | − .00076699031874270452693856835794857664314091945205, | |
| 165 | − .00038349518757139558907246168118138126339502603495, | |
| 166 | − .00019174759731070330743990956198900093346887403385, | |
| 167 | − .00009587379909597734587051721097647635118706561284, | |
| 168 | − .00004793689960306688454900399049465887274686668768 | |
| 169 | − }; | |
| 170 | − | |
| 171 | −#ifdef __cplusplus | |
| 172 | −} | |
| 173 | −#endif | |
| @@ -1,296 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-analysis.h | |
| 4 | − Created: 25 Oct 2019 10:30:52am | |
| 5 | − Author: Matthew Wang | |
| 6 | − | |
| 7 | − ==============================================================================*/ | |
| 8 | − | |
| 9 | −#ifndef LEAF_ANALYSIS_H_INCLUDED | |
| 10 | −#define LEAF_ANALYSIS_H_INCLUDED | |
| 11 | − | |
| 12 | −#ifdef __cplusplus | |
| 13 | −extern "C" { | |
| 14 | −#endif | |
| 15 | − | |
| 16 | − //============================================================================== | |
| 17 | − | |
| 18 | −#include "leaf-global.h" | |
| 19 | −#include "leaf-mempool.h" | |
| 20 | −#include "leaf-math.h" | |
| 21 | −#include "leaf-filters.h" | |
| 22 | −#include "leaf-envelopes.h" | |
| 23 | − | |
| 24 | − /*! | |
| 25 | − * @internal | |
| 26 | − * Header. | |
| 27 | − * @include basic-oscillators.h | |
| 28 | − * @example basic-oscillators.c | |
| 29 | − * An example. | |
| 30 | − */ | |
| 31 | − | |
| 32 | − //============================================================================== | |
| 33 | − | |
| 34 | − /* Envelope Follower */ | |
| 35 | − typedef struct _tEnvelopeFollower | |
| 36 | − { | |
| 37 | − float y; | |
| 38 | − float a_thresh; | |
| 39 | − float d_coeff; | |
| 40 | − | |
| 41 | − } _tEnvelopeFollower; | |
| 42 | − | |
| 43 | − typedef _tEnvelopeFollower* tEnvelopeFollower; | |
| 44 | − | |
| 45 | − void tEnvelopeFollower_init (tEnvelopeFollower* const, float attackThreshold, float decayCoeff); | |
| 46 | − void tEnvelopeFollower_free (tEnvelopeFollower* const); | |
| 47 | − void tEnvelopeFollower_initToPool (tEnvelopeFollower* const, float attackThreshold, float decayCoeff, tMempool* const); | |
| 48 | − void tEnvelopeFollower_freeFromPool (tEnvelopeFollower* const, tMempool* const); | |
| 49 | − | |
| 50 | − float tEnvelopeFollower_tick (tEnvelopeFollower* const, float x); | |
| 51 | − int tEnvelopeFollower_decayCoeff (tEnvelopeFollower* const, float decayCoeff); | |
| 52 | − int tEnvelopeFollower_attackThresh (tEnvelopeFollower* const, float attackThresh); | |
| 53 | − | |
| 54 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 55 | − | |
| 56 | − /* Zero Crossing Detector */ | |
| 57 | − typedef struct _tZeroCrossing { | |
| 58 | − int count; | |
| 59 | − int maxWindowSize; | |
| 60 | − int currentWindowSize; | |
| 61 | − float invCurrentWindowSize; | |
| 62 | − float* inBuffer; | |
| 63 | − uint16_t* countBuffer; | |
| 64 | − int prevPosition; | |
| 65 | − int position; | |
| 66 | − } _tZeroCrossing; | |
| 67 | − | |
| 68 | − typedef _tZeroCrossing* tZeroCrossing; | |
| 69 | − | |
| 70 | − void tZeroCrossing_init (tZeroCrossing* const, int maxWindowSize); | |
| 71 | − void tZeroCrossing_free (tZeroCrossing* const); | |
| 72 | − void tZeroCrossing_initToPool (tZeroCrossing* const, int maxWindowSize, tMempool* const); | |
| 73 | − void tZeroCrossing_freeFromPool (tZeroCrossing* const, tMempool* const); | |
| 74 | − | |
| 75 | − float tZeroCrossing_tick (tZeroCrossing* const, float input); | |
| 76 | − void tZeroCrossing_setWindow (tZeroCrossing* const, float windowSize); | |
| 77 | − | |
| 78 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 79 | − | |
| 80 | − /* PowerEnvelopeFollower */ | |
| 81 | − typedef struct _tPowerFollower { | |
| 82 | − float factor, oneminusfactor; | |
| 83 | − float curr; | |
| 84 | − | |
| 85 | − } _tPowerFollower; | |
| 86 | − | |
| 87 | − typedef _tPowerFollower* tPowerFollower; | |
| 88 | − | |
| 89 | − void tPowerFollower_init (tPowerFollower* const, float factor); | |
| 90 | − void tPowerFollower_free (tPowerFollower* const); | |
| 91 | − void tPowerFollower_initToPool (tPowerFollower* const, float factor, tMempool* const); | |
| 92 | − void tPowerFollower_freeFromPool (tPowerFollower* const, tMempool* const); | |
| 93 | − | |
| 94 | − float tPowerFollower_tick (tPowerFollower* const, float input); | |
| 95 | − float tPowerFollower_sample (tPowerFollower* const); | |
| 96 | − int tPowerFollower_setFactor (tPowerFollower* const, float factor); | |
| 97 | − | |
| 98 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 99 | − | |
| 100 | − // ENV~ from PD, modified for LEAF | |
| 101 | −#define MAXOVERLAP 32 | |
| 102 | −#define INITVSTAKEN 64 | |
| 103 | −#define ENV_WINDOW_SIZE 1024 | |
| 104 | −#define ENV_HOP_SIZE 256 | |
| 105 | − | |
| 106 | − typedef struct _tEnvPD | |
| 107 | − { | |
| 108 | − float buf[ENV_WINDOW_SIZE + INITVSTAKEN]; | |
| 109 | − uint16_t x_phase; /* number of points since last output */ | |
| 110 | − uint16_t x_period; /* requested period of output */ | |
| 111 | − uint16_t x_realperiod; /* period rounded up to vecsize multiple */ | |
| 112 | − uint16_t x_npoints; /* analysis window size in samples */ | |
| 113 | − float x_result; /* result to output */ | |
| 114 | − float x_sumbuf[MAXOVERLAP]; /* summing buffer */ | |
| 115 | − float x_f; | |
| 116 | − uint16_t windowSize, hopSize, blockSize; | |
| 117 | − uint16_t x_allocforvs; /* extra buffer for DSP vector size */ | |
| 118 | − } _tEnvPD; | |
| 119 | − | |
| 120 | − typedef _tEnvPD* tEnvPD; | |
| 121 | − | |
| 122 | − void tEnvPD_init (tEnvPD* const, int windowSize, int hopSize, int blockSize); | |
| 123 | − void tEnvPD_free (tEnvPD* const); | |
| 124 | − void tEnvPD_initToPool (tEnvPD* const, int windowSize, int hopSize, int blockSize, tMempool* const); | |
| 125 | − void tEnvPD_freeFromPool (tEnvPD* const, tMempool* const); | |
| 126 | − | |
| 127 | − float tEnvPD_tick (tEnvPD* const); | |
| 128 | − void tEnvPD_processBlock (tEnvPD* const, float* in); | |
| 129 | − | |
| 130 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 131 | − | |
| 132 | − /* tAttackDetection */ | |
| 133 | −#define DEFBLOCKSIZE 1024 | |
| 134 | −#define DEFTHRESHOLD 6 | |
| 135 | −#define DEFATTACK 10 | |
| 136 | −#define DEFRELEASE 10 | |
| 137 | − | |
| 138 | − typedef struct _tAttackDetection | |
| 139 | − { | |
| 140 | − float env; | |
| 141 | − | |
| 142 | − //Attack & Release times in msec | |
| 143 | − int atk; | |
| 144 | − int rel; | |
| 145 | − | |
| 146 | − //Attack & Release coefficients based on times | |
| 147 | − float atk_coeff; | |
| 148 | − float rel_coeff; | |
| 149 | − | |
| 150 | − int blocksize; | |
| 151 | − int samplerate; | |
| 152 | − | |
| 153 | − //RMS amplitude of previous block - used to decide if attack is present | |
| 154 | − float prevAmp; | |
| 155 | − | |
| 156 | − float threshold; | |
| 157 | − } _tAttackDetection; | |
| 158 | − | |
| 159 | − typedef _tAttackDetection* tAttackDetection; | |
| 160 | − | |
| 161 | − void tAttackDetection_init (tAttackDetection* const, int blocksize, int atk, int rel); | |
| 162 | − void tAttackDetection_free (tAttackDetection* const); | |
| 163 | − void tAttackDetection_initToPool (tAttackDetection* const, int blocksize, int atk, int rel, tMempool* const); | |
| 164 | − void tAttackDetection_freeFromPool (tAttackDetection* const, tMempool* const); | |
| 165 | − | |
| 166 | − // set expected input blocksize | |
| 167 | − void tAttackDetection_setBlocksize (tAttackDetection* const, int size); | |
| 168 | − | |
| 169 | − // change atkDetector sample rate | |
| 170 | − void tAttackDetection_setSamplerate (tAttackDetection* const, int inRate); | |
| 171 | − | |
| 172 | − // set attack time and coeff | |
| 173 | − void tAttackDetection_setAttack (tAttackDetection* const, int inAtk); | |
| 174 | − | |
| 175 | − // set release time and coeff | |
| 176 | − void tAttackDetection_setRelease (tAttackDetection* const, int inRel); | |
| 177 | − | |
| 178 | − // set level above which values are identified as attacks | |
| 179 | − void tAttackDetection_setThreshold (tAttackDetection* const, float thres); | |
| 180 | − | |
| 181 | − // find largest transient in input block, return index of attack | |
| 182 | − int tAttackDetection_detect (tAttackDetection* const, float *in); | |
| 183 | − | |
| 184 | − //============================================================================== | |
| 185 | − | |
| 186 | − // tSNAC: period detector | |
| 187 | − // from Katja Vetters http://www.katjaas.nl/helmholtz/helmholtz.html | |
| 188 | −#define SNAC_FRAME_SIZE 1024 // default analysis framesize // should be the same as (or smaller than?) PS_FRAME_SIZE | |
| 189 | −#define DEFOVERLAP 1 // default overlap | |
| 190 | −#define DEFBIAS 0.2f // default bias | |
| 191 | −#define DEFMINRMS 0.003f // default minimum RMS | |
| 192 | −#define SEEK 0.85f // seek-length as ratio of framesize | |
| 193 | − | |
| 194 | − typedef struct _tSNAC | |
| 195 | − { | |
| 196 | − float* inputbuf; | |
| 197 | − float* processbuf; | |
| 198 | − float* spectrumbuf; | |
| 199 | − float* biasbuf; | |
| 200 | − uint16_t timeindex; | |
| 201 | − uint16_t framesize; | |
| 202 | − uint16_t overlap; | |
| 203 | − uint16_t periodindex; | |
| 204 | − | |
| 205 | − float periodlength; | |
| 206 | − float fidelity; | |
| 207 | − float biasfactor; | |
| 208 | − float minrms; | |
| 209 | − | |
| 210 | − } _tSNAC; | |
| 211 | − | |
| 212 | − typedef _tSNAC* tSNAC; | |
| 213 | − | |
| 214 | − void tSNAC_init (tSNAC* const, int overlaparg); | |
| 215 | − void tSNAC_free (tSNAC* const); | |
| 216 | − void tSNAC_initToPool (tSNAC* const, int overlaparg, tMempool* const); | |
| 217 | − void tSNAC_freeFromPool (tSNAC* const, tMempool* const); | |
| 218 | − | |
| 219 | − void tSNAC_ioSamples (tSNAC *s, float *in, float *out, int size); | |
| 220 | − void tSNAC_setOverlap (tSNAC *s, int lap); | |
| 221 | − void tSNAC_setBias (tSNAC *s, float bias); | |
| 222 | − void tSNAC_setMinRMS (tSNAC *s, float rms); | |
| 223 | − | |
| 224 | − /*To get freq, perform SAMPLE_RATE/snac_getperiod() */ | |
| 225 | − float tSNAC_getPeriod (tSNAC *s); | |
| 226 | − float tSNAC_getFidelity (tSNAC *s); | |
| 227 | − | |
| 228 | −#define DEFPITCHRATIO 2.0f | |
| 229 | −#define DEFTIMECONSTANT 100.0f | |
| 230 | −#define DEFHOPSIZE 64 | |
| 231 | −#define DEFWINDOWSIZE 64 | |
| 232 | −#define FBA 20 | |
| 233 | −#define HPFREQ 40.0f | |
| 234 | − | |
| 235 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 236 | − // Period detection | |
| 237 | − typedef struct _tPeriodDetection | |
| 238 | − { | |
| 239 | − tEnvPD env; | |
| 240 | − tSNAC snac; | |
| 241 | − float* inBuffer; | |
| 242 | − float* outBuffer; | |
| 243 | − int frameSize; | |
| 244 | − int bufSize; | |
| 245 | − int framesPerBuffer; | |
| 246 | − int curBlock; | |
| 247 | − int lastBlock; | |
| 248 | − int i; | |
| 249 | − int indexstore; | |
| 250 | − int iLast; | |
| 251 | − int index; | |
| 252 | − float period; | |
| 253 | − | |
| 254 | − uint16_t hopSize; | |
| 255 | − uint16_t windowSize; | |
| 256 | − uint8_t fba; | |
| 257 | − | |
| 258 | − float timeConstant; | |
| 259 | − float radius; | |
| 260 | − float max; | |
| 261 | − float lastmax; | |
| 262 | − float deltamax; | |
| 263 | − | |
| 264 | − float fidelityThreshold; | |
| 265 | − | |
| 266 | − float history; | |
| 267 | − float alpha; | |
| 268 | − float tolerance; | |
| 269 | − | |
| 270 | − } _tPeriodDetection; | |
| 271 | − | |
| 272 | − typedef _tPeriodDetection* tPeriodDetection; | |
| 273 | − | |
| 274 | − void tPeriodDetection_init (tPeriodDetection* const, float* in, float* out, int bufSize, int frameSize); | |
| 275 | − void tPeriodDetection_free (tPeriodDetection* const); | |
| 276 | − void tPeriodDetection_initToPool (tPeriodDetection* const, float* in, float* out, int bufSize, int frameSize, tMempool* const); | |
| 277 | − void tPeriodDetection_freeFromPool (tPeriodDetection* const, tMempool* const); | |
| 278 | − | |
| 279 | − float tPeriodDetection_tick (tPeriodDetection* const, float sample); | |
| 280 | − float tPeriodDetection_getPeriod (tPeriodDetection* const); | |
| 281 | − void tPeriodDetection_setHopSize (tPeriodDetection* const, int hs); | |
| 282 | − void tPeriodDetection_setWindowSize (tPeriodDetection* const, int ws); | |
| 283 | − void tPeriodDetection_setFidelityThreshold(tPeriodDetection* const, float threshold); | |
| 284 | − void tPeriodDetection_setAlpha (tPeriodDetection* const, float alpha); | |
| 285 | − void tPeriodDetection_setTolerance (tPeriodDetection* const, float tolerance); | |
| 286 | − | |
| 287 | − //============================================================================== | |
| 288 | − | |
| 289 | −#ifdef __cplusplus | |
| 290 | −} | |
| 291 | −#endif | |
| 292 | − | |
| 293 | −#endif // LEAF_ANALYSIS_H_INCLUDED | |
| 294 | − | |
| 295 | −//============================================================================== | |
| 296 | − | |
| @@ -1,229 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-delay.h | |
| 4 | − Created: 20 Jan 2017 12:01:24pm | |
| 5 | − Author: Michael R Mulshine | |
| 6 | − | |
| 7 | − ==============================================================================*/ | |
| 8 | − | |
| 9 | −#ifndef LEAF_DELAY_H_INCLUDED | |
| 10 | −#define LEAF_DELAY_H_INCLUDED | |
| 11 | − | |
| 12 | −#ifdef __cplusplus | |
| 13 | −extern "C" { | |
| 14 | −#endif | |
| 15 | − | |
| 16 | − //============================================================================== | |
| 17 | − | |
| 18 | −#include "leaf-math.h" | |
| 19 | −#include "leaf-mempool.h" | |
| 20 | − | |
| 21 | − /*! | |
| 22 | − * @internal | |
| 23 | − * Header. | |
| 24 | − * @include basic-oscillators.h | |
| 25 | − * @example basic-oscillators.c | |
| 26 | − * An example. | |
| 27 | − */ | |
| 28 | − | |
| 29 | − //============================================================================== | |
| 30 | − | |
| 31 | − /* Non-interpolating delay, reimplemented from STK (Cook and Scavone). */ | |
| 32 | − typedef struct _tDelay | |
| 33 | − { | |
| 34 | − float gain; | |
| 35 | − float* buff; | |
| 36 | − | |
| 37 | − float lastOut, lastIn; | |
| 38 | − | |
| 39 | − uint32_t inPoint, outPoint; | |
| 40 | − | |
| 41 | − uint32_t delay, maxDelay; | |
| 42 | − | |
| 43 | − } _tDelay; | |
| 44 | − | |
| 45 | − typedef _tDelay* tDelay; | |
| 46 | − | |
| 47 | − void tDelay_init (tDelay* const, uint32_t delay, uint32_t maxDelay); | |
| 48 | − void tDelay_free (tDelay* const); | |
| 49 | − void tDelay_initToPool (tDelay* const, uint32_t delay, uint32_t maxDelay, tMempool* const); | |
| 50 | − void tDelay_freeFromPool (tDelay* const, tMempool* const); | |
| 51 | − | |
| 52 | − void tDelay_clear (tDelay* const); | |
| 53 | − int tDelay_setDelay (tDelay* const, uint32_t delay); | |
| 54 | − uint32_t tDelay_getDelay (tDelay* const); | |
| 55 | − void tDelay_tapIn (tDelay* const, float in, uint32_t tapDelay); | |
| 56 | − float tDelay_tapOut (tDelay* const, uint32_t tapDelay); | |
| 57 | − float tDelay_addTo (tDelay* const, float value, uint32_t tapDelay); | |
| 58 | − float tDelay_tick (tDelay* const, float sample); | |
| 59 | − float tDelay_getLastOut (tDelay* const); | |
| 60 | − float tDelay_getLastIn (tDelay* const); | |
| 61 | − | |
| 62 | − //============================================================================== | |
| 63 | − | |
| 64 | − /* Linearly-interpolating delay, reimplemented from STK (Cook and Scavone). */ | |
| 65 | − typedef struct _tLinearDelay | |
| 66 | − { | |
| 67 | − float gain; | |
| 68 | − float* buff; | |
| 69 | − | |
| 70 | − float lastOut, lastIn; | |
| 71 | − | |
| 72 | − uint32_t inPoint, outPoint; | |
| 73 | − | |
| 74 | − uint32_t maxDelay; | |
| 75 | − | |
| 76 | − float delay; | |
| 77 | − | |
| 78 | − float alpha, omAlpha; | |
| 79 | − | |
| 80 | − } _tLinearDelay; | |
| 81 | − | |
| 82 | − typedef _tLinearDelay* tLinearDelay; | |
| 83 | − | |
| 84 | − void tLinearDelay_init (tLinearDelay* const, float delay, uint32_t maxDelay); | |
| 85 | − void tLinearDelay_free (tLinearDelay* const); | |
| 86 | − void tLinearDelay_initToPool (tLinearDelay* const, float delay, uint32_t maxDelay, tMempool* const); | |
| 87 | − void tLinearDelay_freeFromPool(tLinearDelay* const, tMempool* const); | |
| 88 | − void tLinearDelay_clear (tLinearDelay* const dl); | |
| 89 | − int tLinearDelay_setDelay (tLinearDelay* const, float delay); | |
| 90 | − float tLinearDelay_getDelay (tLinearDelay* const); | |
| 91 | − void tLinearDelay_tapIn (tLinearDelay* const, float in, uint32_t tapDelay); | |
| 92 | − float tLinearDelay_tapOut (tLinearDelay* const, uint32_t tapDelay); | |
| 93 | − float tLinearDelay_addTo (tLinearDelay* const, float value, uint32_t tapDelay); | |
| 94 | − float tLinearDelay_tick (tLinearDelay* const, float sample); | |
| 95 | − void tLinearDelay_tickIn (tLinearDelay* const, float input); | |
| 96 | − float tLinearDelay_tickOut (tLinearDelay* const); | |
| 97 | − float tLinearDelay_getLastOut (tLinearDelay* const); | |
| 98 | − float tLinearDelay_getLastIn (tLinearDelay* const); | |
| 99 | − | |
| 100 | − | |
| 101 | − | |
| 102 | − //============================================================================== | |
| 103 | − | |
| 104 | − /* Hermite-interpolating delay, created by adapting STK linear delay with Hermite interpolation */ | |
| 105 | − typedef struct _tHermiteDelay | |
| 106 | − { | |
| 107 | − float gain; | |
| 108 | − float* buff; | |
| 109 | − | |
| 110 | − float lastOut, lastIn; | |
| 111 | − | |
| 112 | − uint32_t inPoint, outPoint; | |
| 113 | − | |
| 114 | − uint32_t maxDelay; | |
| 115 | − | |
| 116 | − float delay; | |
| 117 | − | |
| 118 | − float alpha, omAlpha; | |
| 119 | − | |
| 120 | − } _tHermiteDelay; | |
| 121 | − | |
| 122 | − typedef _tHermiteDelay* tHermiteDelay; | |
| 123 | − | |
| 124 | − void tHermiteDelay_init (tHermiteDelay* const dl, float delay, uint32_t maxDelay); | |
| 125 | − void tHermiteDelay_free (tHermiteDelay* const dl); | |
| 126 | − void tHermiteDelay_initToPool (tHermiteDelay* const dl, float delay, uint32_t maxDelay, tMempool* const mp); | |
| 127 | − void tHermiteDelay_freeFromPool (tHermiteDelay* const dl, tMempool* const mp); | |
| 128 | − void tHermiteDelay_clear (tHermiteDelay* const dl); | |
| 129 | − float tHermiteDelay_tick (tHermiteDelay* const dl, float input); | |
| 130 | − void tHermiteDelay_tickIn (tHermiteDelay* const dl, float input); | |
| 131 | − float tHermiteDelay_tickOut (tHermiteDelay* const dl); | |
| 132 | − int tHermiteDelay_setDelay (tHermiteDelay* const dl, float delay); | |
| 133 | − float tHermiteDelay_tapOut (tHermiteDelay* const dl, uint32_t tapDelay); | |
| 134 | − void tHermiteDelay_tapIn (tHermiteDelay* const dl, float value, uint32_t tapDelay); | |
| 135 | − float tHermiteDelay_addTo (tHermiteDelay* const dl, float value, uint32_t tapDelay); | |
| 136 | − float tHermiteDelay_getDelay (tHermiteDelay* const dl); | |
| 137 | − float tHermiteDelay_getLastOut (tHermiteDelay* const dl); | |
| 138 | − float tHermiteDelay_getLastIn (tHermiteDelay* const dl); | |
| 139 | − void tHermiteDelay_setGain (tHermiteDelay* const dl, float gain); | |
| 140 | − float tHermiteDelay_getGain (tHermiteDelay* const dl); | |
| 141 | − | |
| 142 | − | |
| 143 | − //============================================================================== | |
| 144 | − | |
| 145 | − /* Allpass-interpolating delay, reimplemented from STK (Cook and Scavone). */ | |
| 146 | − typedef struct _tAllpassDelay | |
| 147 | − { | |
| 148 | − float gain; | |
| 149 | − float* buff; | |
| 150 | − | |
| 151 | − float lastOut, lastIn; | |
| 152 | − | |
| 153 | − uint32_t inPoint, outPoint; | |
| 154 | − | |
| 155 | − uint32_t maxDelay; | |
| 156 | − | |
| 157 | − float delay; | |
| 158 | − | |
| 159 | − float alpha, omAlpha, coeff; | |
| 160 | − | |
| 161 | − float apInput; | |
| 162 | − | |
| 163 | − } _tAllpassDelay; | |
| 164 | − | |
| 165 | − typedef _tAllpassDelay* tAllpassDelay; | |
| 166 | − | |
| 167 | − void tAllpassDelay_init (tAllpassDelay* const, float delay, uint32_t maxDelay); | |
| 168 | − void tAllpassDelay_free (tAllpassDelay* const); | |
| 169 | − void tAllpassDelay_initToPool (tAllpassDelay* const, float delay, uint32_t maxDelay, tMempool* const); | |
| 170 | − void tAllpassDelay_freeFromPool(tAllpassDelay* const, tMempool* const); | |
| 171 | − | |
| 172 | − void tAllpassDelay_clear (tAllpassDelay* const); | |
| 173 | − int tAllpassDelay_setDelay (tAllpassDelay* const, float delay); | |
| 174 | − float tAllpassDelay_getDelay (tAllpassDelay* const); | |
| 175 | − void tAllpassDelay_tapIn (tAllpassDelay* const, float in, uint32_t tapDelay); | |
| 176 | − float tAllpassDelay_tapOut (tAllpassDelay* const, uint32_t tapDelay); | |
| 177 | − float tAllpassDelay_addTo (tAllpassDelay* const, float value, uint32_t tapDelay); | |
| 178 | − float tAllpassDelay_tick (tAllpassDelay* const, float sample); | |
| 179 | − float tAllpassDelay_getLastOut (tAllpassDelay* const); | |
| 180 | − float tAllpassDelay_getLastIn (tAllpassDelay* const); | |
| 181 | − | |
| 182 | − //============================================================================== | |
| 183 | − | |
| 184 | − /* Linear interpolating delay with fixed read and write pointers, variable rate. */ | |
| 185 | − typedef struct _tTapeDelay | |
| 186 | − { | |
| 187 | − float gain; | |
| 188 | − float* buff; | |
| 189 | − | |
| 190 | − float lastOut, lastIn; | |
| 191 | − | |
| 192 | − uint32_t inPoint; | |
| 193 | − | |
| 194 | − uint32_t maxDelay; | |
| 195 | − | |
| 196 | − float delay, inc, idx; | |
| 197 | − | |
| 198 | − float apInput; | |
| 199 | − | |
| 200 | − } _tTapeDelay; | |
| 201 | − | |
| 202 | − typedef _tTapeDelay* tTapeDelay; | |
| 203 | − | |
| 204 | − void tTapeDelay_init (tTapeDelay* const, float delay, uint32_t maxDelay); | |
| 205 | − void tTapeDelay_free (tTapeDelay* const); | |
| 206 | − void tTapeDelay_initToPool (tTapeDelay* const, float delay, uint32_t maxDelay, tMempool* const); | |
| 207 | − void tTapeDelay_freeFromPool(tTapeDelay* const, tMempool* const); | |
| 208 | − | |
| 209 | − void tTapeDelay_clear (tTapeDelay* const); | |
| 210 | − void tTapeDelay_setDelay (tTapeDelay* const, float delay); | |
| 211 | − float tTapeDelay_getDelay (tTapeDelay* const); | |
| 212 | − void tTapeDelay_tapIn (tTapeDelay* const, float in, uint32_t tapDelay); | |
| 213 | − float tTapeDelay_tapOut (tTapeDelay* const d, float tapDelay); | |
| 214 | − float tTapeDelay_addTo (tTapeDelay* const, float value, uint32_t tapDelay); | |
| 215 | − float tTapeDelay_tick (tTapeDelay* const, float sample); | |
| 216 | − void tTapeDelay_incrementInPoint(tTapeDelay* const dl); | |
| 217 | − float tTapeDelay_getLastOut (tTapeDelay* const); | |
| 218 | − float tTapeDelay_getLastIn (tTapeDelay* const); | |
| 219 | − | |
| 220 | − //============================================================================== | |
| 221 | − | |
| 222 | −#ifdef __cplusplus | |
| 223 | −} | |
| 224 | −#endif | |
| 225 | − | |
| 226 | −#endif // LEAF_DELAY_H_INCLUDED | |
| 227 | − | |
| 228 | −//============================================================================== | |
| 229 | − | |
| @@ -1,164 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-distortion.h | |
| 4 | − Created: 25 Oct 2019 10:23:28am | |
| 5 | − Author: Matthew Wang | |
| 6 | − | |
| 7 | − ==============================================================================*/ | |
| 8 | − | |
| 9 | −#ifndef LEAF_DISTORTION_H_INCLUDED | |
| 10 | −#define LEAF_DISTORTION_H_INCLUDED | |
| 11 | − | |
| 12 | −#ifdef __cplusplus | |
| 13 | −extern "C" { | |
| 14 | −#endif | |
| 15 | − | |
| 16 | − //============================================================================== | |
| 17 | − | |
| 18 | −#include "leaf-global.h" | |
| 19 | −#include "leaf-mempool.h" | |
| 20 | −#include "leaf-math.h" | |
| 21 | − | |
| 22 | − /*! | |
| 23 | − * @internal | |
| 24 | − * Header. | |
| 25 | − * @include basic-oscillators.h | |
| 26 | − * @example basic-oscillators.c | |
| 27 | − * An example. | |
| 28 | − */ | |
| 29 | − | |
| 30 | − //============================================================================== | |
| 31 | − | |
| 32 | − typedef struct _tSampleReducer | |
| 33 | − { | |
| 34 | − float invRatio; | |
| 35 | − float hold; | |
| 36 | − uint32_t count; | |
| 37 | − } _tSampleReducer; | |
| 38 | − | |
| 39 | − typedef _tSampleReducer* tSampleReducer; | |
| 40 | − | |
| 41 | − void tSampleReducer_init (tSampleReducer* const); | |
| 42 | − void tSampleReducer_free (tSampleReducer* const); | |
| 43 | − void tSampleReducer_initToPool (tSampleReducer* const, tMempool* const); | |
| 44 | − void tSampleReducer_freeFromPool (tSampleReducer* const, tMempool* const); | |
| 45 | − | |
| 46 | − float tSampleReducer_tick (tSampleReducer* const, float input); | |
| 47 | − | |
| 48 | − // sampling ratio | |
| 49 | − void tSampleReducer_setRatio (tSampleReducer* const, float ratio); | |
| 50 | − | |
| 51 | − //============================================================================== | |
| 52 | − | |
| 53 | − typedef struct _tOversampler | |
| 54 | − { | |
| 55 | − int ratio; | |
| 56 | − float* pCoeffs; | |
| 57 | − float* upState; | |
| 58 | − float* downState; | |
| 59 | − int numTaps; | |
| 60 | − int phaseLength; | |
| 61 | − } _tOversampler; | |
| 62 | − | |
| 63 | − typedef _tOversampler* tOversampler; | |
| 64 | − | |
| 65 | − void tOversampler_init (tOversampler* const, int order, oBool extraQuality); | |
| 66 | − void tOversampler_free (tOversampler* const); | |
| 67 | − void tOversampler_initToPool (tOversampler* const, int order, oBool extraQuality, tMempool* const); | |
| 68 | − void tOversampler_freeFromPool (tOversampler* const, tMempool* const); | |
| 69 | − | |
| 70 | − void tOversampler_upsample (tOversampler* const, float input, float* output); | |
| 71 | − float tOversampler_downsample (tOversampler* const os, float* input); | |
| 72 | − float tOversampler_tick (tOversampler* const, float input, float (*effectTick)(float)); | |
| 73 | − int tOversampler_getLatency (tOversampler* const os); | |
| 74 | − | |
| 75 | − //============================================================================== | |
| 76 | − | |
| 77 | − /* tLockhartWavefolder */ | |
| 78 | − | |
| 79 | − typedef struct _tLockhartWavefolder | |
| 80 | − { | |
| 81 | − double Ln1; | |
| 82 | − double Fn1; | |
| 83 | − double xn1; | |
| 84 | − | |
| 85 | − double RL; | |
| 86 | − double R; | |
| 87 | − double VT; | |
| 88 | − double Is; | |
| 89 | − | |
| 90 | − double a; | |
| 91 | − double b; | |
| 92 | − double d; | |
| 93 | − | |
| 94 | − // Antialiasing error threshold | |
| 95 | − double AAthresh; | |
| 96 | − double half_a; | |
| 97 | − double longthing; | |
| 98 | − | |
| 99 | − double LambertThresh, w, expw, p, r, s, myerr; | |
| 100 | − double l; | |
| 101 | − double u, Ln, Fn; | |
| 102 | − double tempsDenom; | |
| 103 | − double tempErrDenom; | |
| 104 | − double tempOutDenom; | |
| 105 | − | |
| 106 | − } _tLockhartWavefolder; | |
| 107 | − | |
| 108 | − typedef _tLockhartWavefolder* tLockhartWavefolder; | |
| 109 | − | |
| 110 | − void tLockhartWavefolder_init (tLockhartWavefolder* const); | |
| 111 | − void tLockhartWavefolder_free (tLockhartWavefolder* const); | |
| 112 | − void tLockhartWavefolder_initToPool (tLockhartWavefolder* const, tMempool* const); | |
| 113 | − void tLockhartWavefolder_freeFromPool (tLockhartWavefolder* const, tMempool* const); | |
| 114 | − | |
| 115 | − float tLockhartWavefolder_tick (tLockhartWavefolder* const, float samp); | |
| 116 | − | |
| 117 | − //============================================================================== | |
| 118 | − | |
| 119 | − typedef struct _tCrusher | |
| 120 | − { | |
| 121 | − float srr; | |
| 122 | − float mult, div; | |
| 123 | − float rnd; | |
| 124 | − | |
| 125 | − uint32_t op; //which bitwise operation (0-7) | |
| 126 | − | |
| 127 | − float gain; | |
| 128 | − tSampleReducer sReducer; | |
| 129 | − | |
| 130 | − } _tCrusher; | |
| 131 | − | |
| 132 | − typedef _tCrusher* tCrusher; | |
| 133 | − | |
| 134 | − void tCrusher_init (tCrusher* const); | |
| 135 | − void tCrusher_free (tCrusher* const); | |
| 136 | − void tCrusher_initToPool (tCrusher* const, tMempool* const); | |
| 137 | − void tCrusher_freeFromPool (tCrusher* const, tMempool* const); | |
| 138 | − | |
| 139 | − float tCrusher_tick (tCrusher* const, float input); | |
| 140 | − | |
| 141 | − // 0.0 - 1.0 | |
| 142 | − void tCrusher_setOperation (tCrusher* const, float op); | |
| 143 | − | |
| 144 | − // 0.0 - 1.0 | |
| 145 | − void tCrusher_setQuality (tCrusher* const, float val); | |
| 146 | − | |
| 147 | − // what division to round to | |
| 148 | − void tCrusher_setRound (tCrusher* const, float rnd); | |
| 149 | − | |
| 150 | − // sampling ratio | |
| 151 | − void tCrusher_setSamplingRatio (tCrusher* const, float ratio); | |
| 152 | − | |
| 153 | − //============================================================================== | |
| 154 | − | |
| 155 | − | |
| 156 | −#ifdef __cplusplus | |
| 157 | −} | |
| 158 | −#endif | |
| 159 | − | |
| 160 | −#endif // LEAF_DISTORTION_H_INCLUDED | |
| 161 | − | |
| 162 | −//============================================================================== | |
| 163 | − | |
| 164 | − | |
| @@ -1,122 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-dynamics.h | |
| 4 | − Created: 30 Nov 2018 11:57:05am | |
| 5 | − Author: airship | |
| 6 | − | |
| 7 | − ==============================================================================*/ | |
| 8 | − | |
| 9 | −#ifndef LEAF_DYNAMICS_H_INCLUDED | |
| 10 | −#define LEAF_DYNAMICS_H_INCLUDED | |
| 11 | − | |
| 12 | − | |
| 13 | −#ifdef __cplusplus | |
| 14 | −extern "C" { | |
| 15 | −#endif | |
| 16 | − | |
| 17 | − //============================================================================== | |
| 18 | − | |
| 19 | −#include "leaf-global.h" | |
| 20 | −#include "leaf-math.h" | |
| 21 | −#include "leaf-mempool.h" | |
| 22 | −#include "leaf-analysis.h" | |
| 23 | − | |
| 24 | − /*! | |
| 25 | − * @internal | |
| 26 | − * Header. | |
| 27 | − * @include basic-oscillators.h | |
| 28 | − * @example basic-oscillators.c | |
| 29 | − * An example. | |
| 30 | − */ | |
| 31 | − | |
| 32 | − //============================================================================== | |
| 33 | − | |
| 34 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 35 | − | |
| 36 | − /* Compressor */ | |
| 37 | − typedef struct _tCompressor | |
| 38 | − { | |
| 39 | − float tauAttack, tauRelease; | |
| 40 | − float T, R, W, M; // Threshold, compression Ratio, decibel Width of knee transition, decibel Make-up gain | |
| 41 | − | |
| 42 | − float x_G[2], y_G[2], x_T[2], y_T[2]; | |
| 43 | − | |
| 44 | − oBool isActive; | |
| 45 | − | |
| 46 | − } _tCompressor; | |
| 47 | − | |
| 48 | − typedef _tCompressor* tCompressor; | |
| 49 | − | |
| 50 | − void tCompressor_init (tCompressor* const); | |
| 51 | − void tCompressor_free (tCompressor* const); | |
| 52 | − void tCompressor_initToPool (tCompressor* const, tMempool* const); | |
| 53 | − void tCompressor_freeFromPool(tCompressor* const, tMempool* const); | |
| 54 | − | |
| 55 | − float tCompressor_tick (tCompressor* const, float input); | |
| 56 | − | |
| 57 | − /// | |
| 58 | − /* Feedback leveller */ | |
| 59 | − // An auto VCA that you put into a feedback circuit to make it stay at the same level. | |
| 60 | − // It can enforce level bidirectionally (amplifying and attenuating as needed) or | |
| 61 | − // just attenutating. The former option allows for infinite sustain strings, for example, while | |
| 62 | − // The latter option allows for decaying strings, which can never exceed | |
| 63 | − // a specific level. | |
| 64 | − | |
| 65 | − typedef struct _tFeedbackLeveler { | |
| 66 | − float targetLevel; // target power level | |
| 67 | − float strength; // how strongly level difference affects the VCA | |
| 68 | − int mode; // 0 for upwards limiting only, 1 for biderctional limiting | |
| 69 | − float curr; | |
| 70 | − tPowerFollower pwrFlw; // internal power follower needed for level tracking | |
| 71 | − | |
| 72 | − } _tFeedbackLeveler; | |
| 73 | − | |
| 74 | − typedef _tFeedbackLeveler* tFeedbackLeveler; | |
| 75 | − | |
| 76 | − void tFeedbackLeveler_init (tFeedbackLeveler* const, float targetLevel, float factor, float strength, int mode); | |
| 77 | − void tFeedbackLeveler_free (tFeedbackLeveler* const); | |
| 78 | − void tFeedbackLeveler_initToPool (tFeedbackLeveler* const, float targetLevel, float factor, float strength, int mode, tMempool* const); | |
| 79 | − void tFeedbackLeveler_freeFromPool (tFeedbackLeveler* const, tMempool* const); | |
| 80 | − | |
| 81 | − float tFeedbackLeveler_tick (tFeedbackLeveler* const, float input); | |
| 82 | − float tFeedbackLeveler_sample (tFeedbackLeveler* const); | |
| 83 | − void tFeedbackLeveler_setTargetLevel (tFeedbackLeveler* const, float TargetLevel); | |
| 84 | − void tFeedbackLeveler_setFactor (tFeedbackLeveler* const, float factor); | |
| 85 | − void tFeedbackLeveler_setMode (tFeedbackLeveler* const, int mode); // 0 for upwards limiting only, 1 for biderctional limiting | |
| 86 | − void tFeedbackLeveler_setStrength (tFeedbackLeveler* const, float strength); | |
| 87 | − | |
| 88 | − | |
| 89 | − //============================================================================== | |
| 90 | − | |
| 91 | − | |
| 92 | − //Threshold with hysteresis (like Max/MSP thresh~ object) | |
| 93 | − | |
| 94 | − typedef struct _tThreshold { | |
| 95 | − float highThresh, lowThresh; | |
| 96 | − int currentValue; | |
| 97 | − | |
| 98 | − } _tThreshold; | |
| 99 | − | |
| 100 | − typedef _tThreshold* tThreshold; | |
| 101 | − | |
| 102 | − void tThreshold_init (tThreshold* const, float low, float high); | |
| 103 | − void tThreshold_free (tThreshold* const); | |
| 104 | − void tThreshold_initToPool (tThreshold* const, float low, float high, tMempool* const); | |
| 105 | − void tThreshold_freeFromPool(tThreshold* const, tMempool* const); | |
| 106 | − | |
| 107 | − int tThreshold_tick (tThreshold* const, float input); | |
| 108 | − void tThreshold_setLow (tThreshold* const, float low); | |
| 109 | − void tThreshold_setHigh (tThreshold* const, float high); | |
| 110 | − | |
| 111 | − | |
| 112 | − | |
| 113 | − //////====================================================================== | |
| 114 | − | |
| 115 | −#ifdef __cplusplus | |
| 116 | −} | |
| 117 | −#endif | |
| 118 | − | |
| 119 | −#endif // LEAF_DYNAMICS_H_INCLUDED | |
| 120 | − | |
| 121 | −//============================================================================== | |
| 122 | − | |
| @@ -1,360 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-effects.h | |
| 4 | − Created: 20 Jan 2017 12:01:54pm | |
| 5 | − Author: Michael R Mulshine | |
| 6 | − | |
| 7 | − ==============================================================================*/ | |
| 8 | − | |
| 9 | −#ifndef LEAF_EFFECTS_H_INCLUDED | |
| 10 | −#define LEAF_EFFECTS_H_INCLUDED | |
| 11 | − | |
| 12 | −#ifdef __cplusplus | |
| 13 | −extern "C" { | |
| 14 | −#endif | |
| 15 | − | |
| 16 | − //============================================================================== | |
| 17 | −#include "leaf-global.h" | |
| 18 | −#include "leaf-math.h" | |
| 19 | −#include "leaf-mempool.h" | |
| 20 | −#include "leaf-dynamics.h" | |
| 21 | −#include "leaf-analysis.h" | |
| 22 | −#include "leaf-envelopes.h" | |
| 23 | − | |
| 24 | − /*! | |
| 25 | − * @internal | |
| 26 | − * Header. | |
| 27 | − * @include basic-oscillators.h | |
| 28 | − * @example basic-oscillators.c | |
| 29 | − * An example. | |
| 30 | − */ | |
| 31 | − | |
| 32 | − //============================================================================== | |
| 33 | − | |
| 34 | − /* tTalkbox */ | |
| 35 | −#define NUM_TALKBOX_PARAM 4 | |
| 36 | − | |
| 37 | − typedef struct _tTalkbox | |
| 38 | − { | |
| 39 | − float param[NUM_TALKBOX_PARAM]; | |
| 40 | − | |
| 41 | − int bufsize; | |
| 42 | − float* car0; | |
| 43 | − float* car1; | |
| 44 | − float* window; | |
| 45 | − float* buf0; | |
| 46 | − float* buf1; | |
| 47 | − | |
| 48 | − float warpFactor; | |
| 49 | − int32_t warpOn; | |
| 50 | − | |
| 51 | − float emphasis; | |
| 52 | − int32_t K, N, O, pos; | |
| 53 | − float wet, dry, FX; | |
| 54 | − float d0, d1, d2, d3, d4; | |
| 55 | − float u0, u1, u2, u3, u4; | |
| 56 | − | |
| 57 | − | |
| 58 | − } _tTalkbox; | |
| 59 | − | |
| 60 | − typedef _tTalkbox* tTalkbox; | |
| 61 | − | |
| 62 | − void tTalkbox_init (tTalkbox* const, int bufsize); | |
| 63 | − void tTalkbox_free (tTalkbox* const); | |
| 64 | − void tTalkbox_initToPool (tTalkbox* const, int bufsize, tMempool* const); | |
| 65 | − void tTalkbox_freeFromPool (tTalkbox* const, tMempool* const); | |
| 66 | − | |
| 67 | − float tTalkbox_tick (tTalkbox* const, float synth, float voice); | |
| 68 | − void tTalkbox_update (tTalkbox* const); | |
| 69 | − void tTalkbox_suspend (tTalkbox* const); | |
| 70 | − void tTalkbox_lpcDurbin (float *r, int p, float *k, float *g); | |
| 71 | − void tTalkbox_lpc (float *buf, float *car, int32_t n, int32_t o, float warp, int warpOn); | |
| 72 | − void tTalkbox_setQuality (tTalkbox* const, float quality); | |
| 73 | − void tTalkbox_setWarpFactor (tTalkbox* const voc, float warp); | |
| 74 | − void tTalkbox_setWarpOn (tTalkbox* const voc, float warpOn); | |
| 75 | − void tTalkbox_warpedAutocorrelate (float * x, unsigned int L, float * R, unsigned int P, float lambda); | |
| 76 | − //============================================================================== | |
| 77 | − | |
| 78 | − /* tVocoder */ | |
| 79 | −#define NUM_VOCODER_PARAM 8 | |
| 80 | −#define NBANDS 16 | |
| 81 | − | |
| 82 | − typedef struct _tVocoder | |
| 83 | − { | |
| 84 | − float param[NUM_VOCODER_PARAM]; | |
| 85 | − | |
| 86 | − float gain; //output level | |
| 87 | − float thru, high; //hf thru | |
| 88 | − float kout; //downsampled output | |
| 89 | − int32_t kval; //downsample counter | |
| 90 | − int32_t nbnd; //number of bands | |
| 91 | − | |
| 92 | − //filter coeffs and buffers - seems it's faster to leave this global than make local copy | |
| 93 | − float f[NBANDS][13]; //[0-8][0 1 2 | 0 1 2 3 | 0 1 2 3 | val rate] | |
| 94 | − | |
| 95 | − } _tVocoder; | |
| 96 | − | |
| 97 | − typedef _tVocoder* tVocoder; | |
| 98 | − | |
| 99 | − void tVocoder_init (tVocoder* const); | |
| 100 | − void tVocoder_free (tVocoder* const); | |
| 101 | − void tVocoder_initToPool (tVocoder* const, tMempool* const); | |
| 102 | − void tVocoder_freeFromPool (tVocoder* const, tMempool* const); | |
| 103 | − | |
| 104 | − float tVocoder_tick (tVocoder* const, float synth, float voice); | |
| 105 | − void tVocoder_update (tVocoder* const); | |
| 106 | − void tVocoder_suspend (tVocoder* const); | |
| 107 | − | |
| 108 | − //============================================================================== | |
| 109 | − | |
| 110 | − // tRosenbergGlottalPulse | |
| 111 | − | |
| 112 | − typedef struct _tRosenbergGlottalPulse | |
| 113 | − { | |
| 114 | − | |
| 115 | − float phase; | |
| 116 | − float openLength; | |
| 117 | − float pulseLength; | |
| 118 | − float freq; | |
| 119 | − float inc; | |
| 120 | − | |
| 121 | − | |
| 122 | − } _tRosenbergGlottalPulse; | |
| 123 | − | |
| 124 | − typedef _tRosenbergGlottalPulse* tRosenbergGlottalPulse; | |
| 125 | − | |
| 126 | − void tRosenbergGlottalPulse_init (tRosenbergGlottalPulse* const); | |
| 127 | − void tRosenbergGlottalPulse_free (tRosenbergGlottalPulse* const); | |
| 128 | − void tRosenbergGlottalPulse_initToPool (tRosenbergGlottalPulse* const, tMempool* const); | |
| 129 | − void tRosenbergGlottalPulse_freeFromPool (tRosenbergGlottalPulse* const, tMempool* const); | |
| 130 | − | |
| 131 | − float tRosenbergGlottalPulse_tick (tRosenbergGlottalPulse* const); | |
| 132 | − | |
| 133 | − void tRosenbergGlottalPulse_setFreq (tRosenbergGlottalPulse* const, float freq); | |
| 134 | − | |
| 135 | − void tRosenbergGlottalPulse_setOpenLength (tRosenbergGlottalPulse* const, float openLength); | |
| 136 | − | |
| 137 | − void tRosenbergGlottalPulse_setPulseLength (tRosenbergGlottalPulse* const, float pulseLength); | |
| 138 | − | |
| 139 | − //============================================================================== | |
| 140 | − | |
| 141 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 142 | − | |
| 143 | − /* tSOLAD : pitch shifting algorithm that underlies tRetune etc */ | |
| 144 | − // from Katja Vetters http://www.katjaas.nl/pitchshiftlowlatency/pitchshiftlowlatency.html | |
| 145 | −#define LOOPSIZE (2048*2) // (4096*2) // loop size must be power of two | |
| 146 | −#define LOOPMASK (LOOPSIZE - 1) | |
| 147 | −#define PITCHFACTORDEFAULT 1.0f | |
| 148 | −#define INITPERIOD 64.0f | |
| 149 | −#define MAXPERIOD (float)((LOOPSIZE - w->blocksize) * 0.8f) | |
| 150 | −#define MINPERIOD 8.0f | |
| 151 | − | |
| 152 | − typedef struct _tSOLAD | |
| 153 | − { | |
| 154 | − uint16_t timeindex; // current reference time, write index | |
| 155 | − uint16_t blocksize; // signal input / output block size | |
| 156 | − float pitchfactor; // pitch factor between 0.25 and 4 | |
| 157 | − float readlag; // read pointer's lag behind write pointer | |
| 158 | − float period; // period length in input signal | |
| 159 | − float jump; // read pointer jump length and direction | |
| 160 | − float xfadelength; // crossfade length expressed at input sample rate | |
| 161 | − float xfadevalue; // crossfade phase and value | |
| 162 | − | |
| 163 | − float* delaybuf; | |
| 164 | − | |
| 165 | − } _tSOLAD; | |
| 166 | − | |
| 167 | − typedef _tSOLAD* tSOLAD; | |
| 168 | − | |
| 169 | − void tSOLAD_init (tSOLAD* const); | |
| 170 | − void tSOLAD_free (tSOLAD* const); | |
| 171 | − void tSOLAD_initToPool (tSOLAD* const, tMempool* const); | |
| 172 | − void tSOLAD_freeFromPool (tSOLAD* const, tMempool* const); | |
| 173 | − | |
| 174 | − // send one block of input samples, receive one block of output samples | |
| 175 | − void tSOLAD_ioSamples (tSOLAD *w, float* in, float* out, int blocksize); | |
| 176 | − // set periodicity analysis data | |
| 177 | − void tSOLAD_setPeriod (tSOLAD *w, float period); | |
| 178 | − // set pitch factor between 0.25 and 4 | |
| 179 | − void tSOLAD_setPitchFactor (tSOLAD *w, float pitchfactor); | |
| 180 | − // force readpointer lag | |
| 181 | − void tSOLAD_setReadLag (tSOLAD *w, float readlag); | |
| 182 | − // reset state variables | |
| 183 | − void tSOLAD_resetState (tSOLAD *w); | |
| 184 | − | |
| 185 | − // Pitch shift | |
| 186 | − typedef struct _tPitchShift | |
| 187 | − { | |
| 188 | − tSOLAD sola; | |
| 189 | − tHighpass hp; | |
| 190 | − tPeriodDetection* p; | |
| 191 | − | |
| 192 | − float* outBuffer; | |
| 193 | − int frameSize; | |
| 194 | − int bufSize; | |
| 195 | − | |
| 196 | − int framesPerBuffer; | |
| 197 | − int curBlock; | |
| 198 | − int lastBlock; | |
| 199 | − int index; | |
| 200 | − | |
| 201 | − float pitchFactor; | |
| 202 | − float timeConstant; | |
| 203 | − float radius; | |
| 204 | − } _tPitchShift; | |
| 205 | − | |
| 206 | − typedef _tPitchShift* tPitchShift; | |
| 207 | − | |
| 208 | − void tPitchShift_init (tPitchShift* const, tPeriodDetection* const, float* out, int bufSize); | |
| 209 | − void tPitchShift_free (tPitchShift* const); | |
| 210 | − void tPitchShift_initToPool (tPitchShift* const, tPeriodDetection* const, float* out, int bufSize, tMempool* const); | |
| 211 | − void tPitchShift_freeFromPool (tPitchShift* const, tMempool* const); | |
| 212 | − | |
| 213 | − float tPitchShift_shift (tPitchShift* const); | |
| 214 | − float tPitchShift_shiftToFunc (tPitchShift* const, float (*fun)(float)); | |
| 215 | − float tPitchShift_shiftToFreq (tPitchShift* const, float freq); | |
| 216 | − void tPitchShift_setPitchFactor (tPitchShift* const, float pf); | |
| 217 | − | |
| 218 | − // Retune | |
| 219 | − typedef struct _tRetune | |
| 220 | − { | |
| 221 | − tPeriodDetection pd; | |
| 222 | − tPitchShift* ps; | |
| 223 | − | |
| 224 | − float* inBuffer; | |
| 225 | − float** outBuffers; | |
| 226 | − float* tickOutput; | |
| 227 | − int frameSize; | |
| 228 | − int bufSize; | |
| 229 | − | |
| 230 | − uint16_t hopSize; | |
| 231 | − uint16_t windowSize; | |
| 232 | − uint8_t fba; | |
| 233 | − | |
| 234 | − float* pitchFactor; | |
| 235 | − float timeConstant; | |
| 236 | − float radius; | |
| 237 | − | |
| 238 | − float inputPeriod; | |
| 239 | − | |
| 240 | − int numVoices; | |
| 241 | − } _tRetune; | |
| 242 | − | |
| 243 | − typedef _tRetune* tRetune; | |
| 244 | − | |
| 245 | − void tRetune_init (tRetune* const, int numVoices, int bufSize, int frameSize); | |
| 246 | − void tRetune_free (tRetune* const); | |
| 247 | − void tRetune_initToPool (tRetune* const, int numVoices, int bufSize, int frameSize, tMempool* const); | |
| 248 | − void tRetune_freeFromPool (tRetune* const, tMempool* const); | |
| 249 | − | |
| 250 | − float* tRetune_tick (tRetune* const, float sample); | |
| 251 | − void tRetune_setNumVoices (tRetune* const, int numVoices); | |
| 252 | − void tRetune_setPitchFactors (tRetune* const, float pf); | |
| 253 | − void tRetune_setPitchFactor (tRetune* const, float pf, int voice); | |
| 254 | − void tRetune_setTimeConstant (tRetune* const, float tc); | |
| 255 | − void tRetune_setHopSize (tRetune* const, int hs); | |
| 256 | − void tRetune_setWindowSize (tRetune* const, int ws); | |
| 257 | − void tRetune_setFidelityThreshold(tRetune* const, float threshold); | |
| 258 | − float tRetune_getInputPeriod (tRetune* const); | |
| 259 | − float tRetune_getInputFreq (tRetune* const); | |
| 260 | − | |
| 261 | − // Autotune | |
| 262 | − typedef struct _tAutotune | |
| 263 | − { | |
| 264 | − tPeriodDetection pd; | |
| 265 | − tPitchShift* ps; | |
| 266 | − | |
| 267 | − float* inBuffer; | |
| 268 | − float** outBuffers; | |
| 269 | − float* tickOutput; | |
| 270 | − int frameSize; | |
| 271 | − int bufSize; | |
| 272 | − | |
| 273 | − uint16_t hopSize; | |
| 274 | − uint16_t windowSize; | |
| 275 | − uint8_t fba; | |
| 276 | − | |
| 277 | − float* freq; | |
| 278 | − float timeConstant; | |
| 279 | − float radius; | |
| 280 | − | |
| 281 | − float inputPeriod; | |
| 282 | − | |
| 283 | − int numVoices; | |
| 284 | − } _tAutotune; | |
| 285 | − | |
| 286 | − typedef _tAutotune* tAutotune; | |
| 287 | − | |
| 288 | − void tAutotune_init (tAutotune* const, int numVoices, int bufSize, int frameSize); | |
| 289 | − void tAutotune_free (tAutotune* const); | |
| 290 | − void tAutotune_initToPool (tAutotune* const, int numVoices, int bufSize, int frameSize, tMempool* const); | |
| 291 | − void tAutotune_freeFromPool (tAutotune* const, tMempool* const); | |
| 292 | − | |
| 293 | − float* tAutotune_tick (tAutotune* const, float sample); | |
| 294 | − void tAutotune_setNumVoices (tAutotune* const, int numVoices); | |
| 295 | − void tAutotune_setFreqs (tAutotune* const, float f); | |
| 296 | − void tAutotune_setFreq (tAutotune* const, float f, int voice); | |
| 297 | − void tAutotune_setTimeConstant (tAutotune* const, float tc); | |
| 298 | − void tAutotune_setHopSize (tAutotune* const, int hs); | |
| 299 | − void tAutotune_setWindowSize (tAutotune* const, int ws); | |
| 300 | − void tAutotune_setFidelityThreshold (tAutotune* const, float threshold); | |
| 301 | − void tAutotune_setAlpha (tAutotune* const, float alpha); | |
| 302 | − void tAutotune_setTolerance (tAutotune* const, float tolerance); | |
| 303 | − float tAutotune_getInputPeriod (tAutotune* const); | |
| 304 | − float tAutotune_getInputFreq (tAutotune* const); | |
| 305 | − | |
| 306 | − //============================================================================== | |
| 307 | − | |
| 308 | − | |
| 309 | − typedef struct _tFormantShifter | |
| 310 | − { | |
| 311 | − int ford; | |
| 312 | − float falph; | |
| 313 | − float flamb; | |
| 314 | − float* fk; | |
| 315 | − float* fb; | |
| 316 | − float* fc; | |
| 317 | − float* frb; | |
| 318 | − float* frc; | |
| 319 | − float* fsig; | |
| 320 | − float* fsmooth; | |
| 321 | − float fhp; | |
| 322 | − float flp; | |
| 323 | − float flpa; | |
| 324 | − float* fbuff; | |
| 325 | − float* ftvec; | |
| 326 | − float fmute; | |
| 327 | − float fmutealph; | |
| 328 | − unsigned int cbi; | |
| 329 | − float shiftFactor; | |
| 330 | − float intensity, invIntensity; | |
| 331 | − tHighpass hp; | |
| 332 | − tHighpass hp2; | |
| 333 | − tFeedbackLeveler fbl1; | |
| 334 | − tFeedbackLeveler fbl2; | |
| 335 | − | |
| 336 | − } _tFormantShifter; | |
| 337 | − | |
| 338 | − typedef _tFormantShifter* tFormantShifter; | |
| 339 | − | |
| 340 | − void tFormantShifter_init (tFormantShifter* const, int order); | |
| 341 | − void tFormantShifter_free (tFormantShifter* const); | |
| 342 | − void tFormantShifter_initToPool (tFormantShifter* const, int order, tMempool* const); | |
| 343 | − void tFormantShifter_freeFromPool (tFormantShifter* const, tMempool* const); | |
| 344 | − | |
| 345 | − float tFormantShifter_tick (tFormantShifter* const, float input); | |
| 346 | − float tFormantShifter_remove (tFormantShifter* const, float input); | |
| 347 | − float tFormantShifter_add (tFormantShifter* const, float input); | |
| 348 | − void tFormantShifter_ioSamples (tFormantShifter* const, float* in, float* out, int size, float fwarp); | |
| 349 | − void tFormantShifter_setShiftFactor (tFormantShifter* const, float shiftFactor); | |
| 350 | − void tFormantShifter_setIntensity (tFormantShifter* const, float intensity); | |
| 351 | − | |
| 352 | − //============================================================================== | |
| 353 | − | |
| 354 | −#ifdef __cplusplus | |
| 355 | −} | |
| 356 | −#endif | |
| 357 | − | |
| 358 | −#endif // LEAF_EFFECTS_H_INCLUDED | |
| 359 | − | |
| 360 | −//============================================================================== | |
| @@ -1,103 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * leaf-electrical.h | |
| 3 | − * | |
| 4 | − * Created on: Sep 25, 2019 | |
| 5 | − * Author: jeffsnyder | |
| 6 | − */ | |
| 7 | − | |
| 8 | −#ifndef LEAF_INC_LEAF_ELECTRICAL_H_ | |
| 9 | −#define LEAF_INC_LEAF_ELECTRICAL_H_ | |
| 10 | − | |
| 11 | −#ifdef __cplusplus | |
| 12 | −extern "C" { | |
| 13 | −#endif | |
| 14 | − | |
| 15 | − //============================================================================== | |
| 16 | − | |
| 17 | −#include "leaf-global.h" | |
| 18 | −#include "leaf-math.h" | |
| 19 | −#include "leaf-mempool.h" | |
| 20 | − | |
| 21 | − /*! | |
| 22 | − * @internal | |
| 23 | − * Header. | |
| 24 | − * @include basic-oscillators.h | |
| 25 | − * @example basic-oscillators.c | |
| 26 | − * An example. | |
| 27 | − */ | |
| 28 | − | |
| 29 | − //============================================================================== | |
| 30 | − | |
| 31 | − typedef enum WDFComponentType | |
| 32 | − { | |
| 33 | − SeriesAdaptor = 0, | |
| 34 | − ParallelAdaptor, | |
| 35 | − Resistor, | |
| 36 | − Capacitor, | |
| 37 | − Inductor, | |
| 38 | − Inverter, | |
| 39 | − ResistiveSource, | |
| 40 | − IdealSource, | |
| 41 | − Diode, | |
| 42 | − DiodePair, | |
| 43 | − RootNil, | |
| 44 | − WDFComponentNil | |
| 45 | − } WDFComponentType; | |
| 46 | − | |
| 47 | − typedef struct _tWDF _tWDF; // needed to allow tWDF pointers in struct | |
| 48 | − typedef _tWDF* tWDF; | |
| 49 | − struct _tWDF | |
| 50 | − { | |
| 51 | − WDFComponentType type; | |
| 52 | − float port_resistance_up; | |
| 53 | − float port_resistance_left; | |
| 54 | − float port_resistance_right; | |
| 55 | − float port_conductance_up; | |
| 56 | − float port_conductance_left; | |
| 57 | − float port_conductance_right; | |
| 58 | − float incident_wave_up; | |
| 59 | − float incident_wave_left; | |
| 60 | − float incident_wave_right; | |
| 61 | − float reflected_wave_up; | |
| 62 | − float reflected_wave_left; | |
| 63 | − float reflected_wave_right; | |
| 64 | − float gamma_zero; | |
| 65 | − float sample_rate; | |
| 66 | − float value; | |
| 67 | − tWDF* child_left; | |
| 68 | − tWDF* child_right; | |
| 69 | − float (*get_port_resistance)(tWDF* const); | |
| 70 | − float (*get_reflected_wave_up)(tWDF* const, float); | |
| 71 | − float (*get_reflected_wave_down)(tWDF* const, float, float); | |
| 72 | − void (*set_incident_wave)(tWDF* const, float, float); | |
| 73 | − }; | |
| 74 | − | |
| 75 | − //WDF Linear Components | |
| 76 | − void tWDF_init (tWDF* const, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR); | |
| 77 | − void tWDF_free (tWDF* const); | |
| 78 | − void tWDF_initToPool (tWDF* const, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR, tMempool* const); | |
| 79 | − void tWDF_freeFromPool (tWDF* const, tMempool* const); | |
| 80 | − | |
| 81 | − float tWDF_tick (tWDF* const, float sample, tWDF* const outputPoint, uint8_t paramsChanged); | |
| 82 | − | |
| 83 | − void tWDF_setValue (tWDF* const, float value); | |
| 84 | − void tWDF_setSampleRate (tWDF* const, float sample_rate); | |
| 85 | − uint8_t tWDF_isLeaf (tWDF* const); | |
| 86 | − | |
| 87 | − float tWDF_getPortResistance (tWDF* const); | |
| 88 | − float tWDF_getReflectedWaveUp (tWDF* const, float input); //for tree, only uses input for resistive source | |
| 89 | − float tWDF_getReflectedWaveDown (tWDF* const, float input, float incident_wave); //for roots | |
| 90 | − void tWDF_setIncidentWave (tWDF* const, float incident_wave, float input); | |
| 91 | − | |
| 92 | − float tWDF_getVoltage (tWDF* const); | |
| 93 | − float tWDF_getCurrent (tWDF* const); | |
| 94 | − | |
| 95 | − | |
| 96 | − //============================================================================== | |
| 97 | − | |
| 98 | −#ifdef __cplusplus | |
| 99 | −} | |
| 100 | −#endif | |
| 101 | − | |
| 102 | −#endif /* LEAF_INC_LEAF_ELECTRICAL_H_ */ | |
| 103 | − | |
| @@ -1,366 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − ============================================================================== | |
| 3 | − | |
| 4 | − leaf-envelopes.h | |
| 5 | − Created: 20 Jan 2017 12:02:17pm | |
| 6 | − Author: Michael R Mulshine | |
| 7 | − | |
| 8 | − ============================================================================== | |
| 9 | − */ | |
| 10 | − | |
| 11 | −#ifndef LEAF_ENVELOPES_H_INCLUDED | |
| 12 | −#define LEAF_ENVELOPES_H_INCLUDED | |
| 13 | − | |
| 14 | −#ifdef __cplusplus | |
| 15 | −extern "C" { | |
| 16 | −#endif | |
| 17 | − | |
| 18 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 19 | − | |
| 20 | −#include "leaf-math.h" | |
| 21 | −#include "leaf-mempool.h" | |
| 22 | −#include "leaf-filters.h" | |
| 23 | −#include "leaf-delay.h" | |
| 24 | −#include "leaf-analysis.h" | |
| 25 | −#include "leaf-envelopes.h" | |
| 26 | − | |
| 27 | − /*! | |
| 28 | − * @internal | |
| 29 | − * Header. | |
| 30 | − * @include basic-oscillators.h | |
| 31 | − * @example basic-oscillators.c | |
| 32 | − * An example. | |
| 33 | − */ | |
| 34 | − | |
| 35 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 36 | − | |
| 37 | − /* Attack-Decay envelope */ | |
| 38 | − typedef struct _tEnvelope { | |
| 39 | − | |
| 40 | − const float *exp_buff; | |
| 41 | − const float *inc_buff; | |
| 42 | − uint32_t buff_size; | |
| 43 | − | |
| 44 | − float next; | |
| 45 | − | |
| 46 | − float attackInc, decayInc, rampInc; | |
| 47 | − | |
| 48 | − int inAttack, inDecay, inRamp; | |
| 49 | − | |
| 50 | − int loop; | |
| 51 | − | |
| 52 | − float gain, rampPeak; | |
| 53 | − | |
| 54 | − float attackPhase, decayPhase, rampPhase; | |
| 55 | − | |
| 56 | − } _tEnvelope; | |
| 57 | − | |
| 58 | − typedef _tEnvelope* tEnvelope; | |
| 59 | − | |
| 60 | − void tEnvelope_init (tEnvelope* const, float attack, float decay, int loop); | |
| 61 | − void tEnvelope_free (tEnvelope* const); | |
| 62 | − void tEnvelope_initToPool (tEnvelope* const, float attack, float decay, int loop, tMempool* const); | |
| 63 | − void tEnvelope_freeFromPool (tEnvelope* const, tMempool* const); | |
| 64 | − | |
| 65 | − float tEnvelope_tick (tEnvelope* const); | |
| 66 | − void tEnvelope_setAttack (tEnvelope* const, float attack); | |
| 67 | − void tEnvelope_setDecay (tEnvelope* const, float decay); | |
| 68 | − void tEnvelope_loop (tEnvelope* const, int loop); | |
| 69 | − void tEnvelope_on (tEnvelope* const, float velocity); | |
| 70 | − | |
| 71 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 72 | − | |
| 73 | − | |
| 74 | − | |
| 75 | − /* Exponential Smoother */ | |
| 76 | − typedef struct _tExpSmooth { | |
| 77 | − float factor, oneminusfactor; | |
| 78 | − float curr,dest; | |
| 79 | − | |
| 80 | − } _tExpSmooth; | |
| 81 | − | |
| 82 | − typedef _tExpSmooth* tExpSmooth; | |
| 83 | − | |
| 84 | − void tExpSmooth_init (tExpSmooth* const, float val, float factor); | |
| 85 | − void tExpSmooth_free (tExpSmooth* const); | |
| 86 | − void tExpSmooth_initToPool (tExpSmooth* const, float val, float factor, tMempool* const); | |
| 87 | − void tExpSmooth_freeFromPool (tExpSmooth* const, tMempool* const); | |
| 88 | − | |
| 89 | − float tExpSmooth_tick (tExpSmooth* const); | |
| 90 | − float tExpSmooth_sample (tExpSmooth* const); | |
| 91 | − void tExpSmooth_setFactor (tExpSmooth* const, float factor); | |
| 92 | − void tExpSmooth_setDest (tExpSmooth* const, float dest); | |
| 93 | − void tExpSmooth_setVal (tExpSmooth* const, float val); | |
| 94 | − void tExpSmooth_setValAndDest(tExpSmooth* const expsmooth, float val); | |
| 95 | − | |
| 96 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 97 | − | |
| 98 | − | |
| 99 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 100 | − | |
| 101 | − | |
| 102 | − /* ADSR */ | |
| 103 | − typedef struct _tADSR | |
| 104 | − { | |
| 105 | − const float *exp_buff; | |
| 106 | − const float *inc_buff; | |
| 107 | − uint32_t buff_size; | |
| 108 | − | |
| 109 | − float next; | |
| 110 | − | |
| 111 | − float attackInc, decayInc, releaseInc, rampInc; | |
| 112 | − | |
| 113 | − oBool inAttack, inDecay, inSustain, inRelease, inRamp; | |
| 114 | − | |
| 115 | − float sustain, gain, rampPeak, releasePeak; | |
| 116 | − | |
| 117 | − float attackPhase, decayPhase, releasePhase, rampPhase; | |
| 118 | − | |
| 119 | − float leakFactor; | |
| 120 | − | |
| 121 | − | |
| 122 | − } _tADSR; | |
| 123 | − | |
| 124 | − typedef _tADSR* tADSR; | |
| 125 | − | |
| 126 | − void tADSR_init (tADSR* const adsrenv, float attack, float decay, float sustain, float release); | |
| 127 | − void tADSR_free (tADSR* const); | |
| 128 | − void tADSR_initToPool (tADSR* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp); | |
| 129 | − void tADSR_freeFromPool (tADSR* const, tMempool* const); | |
| 130 | − | |
| 131 | − float tADSR_tick (tADSR* const); | |
| 132 | − void tADSR_setAttack (tADSR* const, float attack); | |
| 133 | − void tADSR_setDecay (tADSR* const, float decay); | |
| 134 | − void tADSR_setSustain (tADSR* const, float sustain); | |
| 135 | − void tADSR_setRelease (tADSR* const, float release); | |
| 136 | − void tADSR_setLeakFactor (tADSR* const, float leakFactor); | |
| 137 | − void tADSR_on (tADSR* const, float velocity); | |
| 138 | − void tADSR_off (tADSR* const); | |
| 139 | − | |
| 140 | − | |
| 141 | − | |
| 142 | − | |
| 143 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 144 | − | |
| 145 | − | |
| 146 | − | |
| 147 | − /* ADSR2 */ | |
| 148 | − typedef struct _tADSR2 | |
| 149 | − { | |
| 150 | − float sampleRateInMs; | |
| 151 | − float attack; | |
| 152 | − float decay; | |
| 153 | − float release; | |
| 154 | − float attackLambda; | |
| 155 | − float decayLambda; | |
| 156 | − float releaseLambda; | |
| 157 | − float sustain; | |
| 158 | − float leakGain; | |
| 159 | − float leakFactor; | |
| 160 | − float targetGainSquared; | |
| 161 | − float factor; | |
| 162 | − float oneMinusFactor; | |
| 163 | − float gain; | |
| 164 | − uint8_t attacking; | |
| 165 | − uint8_t gate; | |
| 166 | − float env; | |
| 167 | − float envTarget; | |
| 168 | − } _tADSR2; | |
| 169 | − | |
| 170 | − typedef _tADSR2* tADSR2; | |
| 171 | − | |
| 172 | − void tADSR2_init (tADSR2* const, float attack, float decay, float sustain, float release); | |
| 173 | − void tADSR2_free (tADSR2* const); | |
| 174 | − void tADSR2_initToPool (tADSR2* const, float attack, float decay, float sustain, float release, tMempool* const); | |
| 175 | − void tADSR2_freeFromPool (tADSR2* const, tMempool* const); | |
| 176 | − | |
| 177 | − float tADSR2_tick (tADSR2* const); | |
| 178 | − void tADSR2_setAttack (tADSR2* const, float attack); | |
| 179 | − void tADSR2_setDecay (tADSR2* const, float decay); | |
| 180 | − void tADSR2_setSustain (tADSR2* const, float sustain); | |
| 181 | − void tADSR2_setRelease (tADSR2* const, float release); | |
| 182 | − void tADSR2_setLeakFactor (tADSR2* const, float leakFactor); | |
| 183 | − void tADSR2_on (tADSR2* const, float velocity); | |
| 184 | − void tADSR2_off (tADSR2* const); | |
| 185 | − | |
| 186 | − | |
| 187 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 188 | − | |
| 189 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 190 | − enum envState { | |
| 191 | − env_idle = 0, | |
| 192 | − env_attack, | |
| 193 | − env_decay, | |
| 194 | − env_sustain, | |
| 195 | − env_release, | |
| 196 | − env_ramp | |
| 197 | − }; | |
| 198 | − | |
| 199 | − /* ADSR3 */ | |
| 200 | − typedef struct _tADSR3 | |
| 201 | − { | |
| 202 | − float sampleRateInMs; | |
| 203 | − int state; | |
| 204 | − float output; | |
| 205 | − float attackRate; | |
| 206 | − float decayRate; | |
| 207 | − float releaseRate; | |
| 208 | − float attackCoef; | |
| 209 | − float decayCoef; | |
| 210 | − float releaseCoef; | |
| 211 | − float sustainLevel; | |
| 212 | − float targetRatioA; | |
| 213 | − float targetRatioDR; | |
| 214 | − float attackBase; | |
| 215 | − float decayBase; | |
| 216 | − float releaseBase; | |
| 217 | − float leakFactor; | |
| 218 | − float targetGainSquared; | |
| 219 | − float factor; | |
| 220 | − float oneMinusFactor; | |
| 221 | − float gain; | |
| 222 | − | |
| 223 | − } _tADSR3; | |
| 224 | − | |
| 225 | − typedef _tADSR3* tADSR3; | |
| 226 | − | |
| 227 | − void tADSR3_init (tADSR3* const, float attack, float decay, float sustain, float release); | |
| 228 | − void tADSR3_free (tADSR3* const); | |
| 229 | − void tADSR3_initToPool (tADSR3* const, float attack, float decay, float sustain, float release, tMempool* const); | |
| 230 | − void tADSR3_freeFromPool (tADSR3* const, tMempool* const); | |
| 231 | − | |
| 232 | − float tADSR3_tick (tADSR3* const); | |
| 233 | − void tADSR3_setAttack (tADSR3* const, float attack); | |
| 234 | − void tADSR3_setDecay (tADSR3* const, float decay); | |
| 235 | − void tADSR3_setSustain (tADSR3* const, float sustain); | |
| 236 | − void tADSR3_setRelease (tADSR3* const, float release); | |
| 237 | − void tADSR3_setLeakFactor (tADSR3* const, float leakFactor); | |
| 238 | − void tADSR3_on (tADSR3* const, float velocity); | |
| 239 | − void tADSR3_off (tADSR3* const); | |
| 240 | − | |
| 241 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 242 | − | |
| 243 | − //ADSR4 | |
| 244 | − | |
| 245 | − | |
| 246 | − typedef struct _tADSR4 | |
| 247 | − { | |
| 248 | − const float *exp_buff; | |
| 249 | − uint32_t buff_size; | |
| 250 | − uint32_t buff_sizeMinusOne; | |
| 251 | − float bufferSizeDividedBySampleRateInMs; | |
| 252 | − float next; | |
| 253 | − | |
| 254 | − float attackInc, decayInc, releaseInc, rampInc; | |
| 255 | − | |
| 256 | − uint32_t whichStage; | |
| 257 | − | |
| 258 | − float sustain, gain, rampPeak, releasePeak; | |
| 259 | − | |
| 260 | − float attackPhase, decayPhase, releasePhase, rampPhase; | |
| 261 | − | |
| 262 | − float leakFactor; | |
| 263 | − | |
| 264 | − | |
| 265 | − } _tADSR4; | |
| 266 | − | |
| 267 | − typedef _tADSR4* tADSR4; | |
| 268 | − | |
| 269 | − void tADSR4_init (tADSR4* const, float attack, float decay, float sustain, float release, float* expBuffer, int bufferSize); | |
| 270 | − void tADSR4_free (tADSR4* const); | |
| 271 | − void tADSR4_initToPool (tADSR4* const, float attack, float decay, float sustain, float release, float* expBuffer, int bufferSize, tMempool* const); | |
| 272 | − void tADSR4_freeFromPool (tADSR4* const, tMempool* const); | |
| 273 | − | |
| 274 | − float tADSR4_tick (tADSR4* const); | |
| 275 | − float tADSR4_tickNoInterp (tADSR4* const adsrenv); | |
| 276 | − void tADSR4_setAttack (tADSR4* const, float attack); | |
| 277 | − void tADSR4_setDecay (tADSR4* const, float decay); | |
| 278 | − void tADSR4_setSustain (tADSR4* const, float sustain); | |
| 279 | − void tADSR4_setRelease (tADSR4* const, float release); | |
| 280 | − void tADSR4_setLeakFactor (tADSR4* const, float leakFactor); | |
| 281 | − void tADSR4_on (tADSR4* const, float velocity); | |
| 282 | − void tADSR4_off (tADSR4* const); | |
| 283 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 284 | − | |
| 285 | − /* Ramp */ | |
| 286 | − typedef struct _tRamp { | |
| 287 | − float inc; | |
| 288 | − float inv_sr_ms; | |
| 289 | − float minimum_time; | |
| 290 | − float curr,dest; | |
| 291 | − float time; | |
| 292 | − float factor; | |
| 293 | − int samples_per_tick; | |
| 294 | − | |
| 295 | − } _tRamp; | |
| 296 | − | |
| 297 | − typedef _tRamp* tRamp; | |
| 298 | − | |
| 299 | − void tRamp_init (tRamp* const, float time, int samplesPerTick); | |
| 300 | − void tRamp_free (tRamp* const); | |
| 301 | − void tRamp_initToPool (tRamp* const, float time, int samplesPerTick, tMempool* const); | |
| 302 | − void tRamp_freeFromPool (tRamp* const, tMempool* const); | |
| 303 | − | |
| 304 | − float tRamp_tick (tRamp* const); | |
| 305 | − float tRamp_sample (tRamp* const); | |
| 306 | − void tRamp_setTime (tRamp* const, float time); | |
| 307 | − void tRamp_setDest (tRamp* const, float dest); | |
| 308 | − void tRamp_setVal (tRamp* const, float val); | |
| 309 | − | |
| 310 | − ///============= | |
| 311 | − /* Ramp Updown*/ | |
| 312 | − typedef struct _tRampUpDown { | |
| 313 | − float upInc; | |
| 314 | − float downInc; | |
| 315 | − float inv_sr_ms; | |
| 316 | − float minimum_time; | |
| 317 | − float curr,dest; | |
| 318 | − float upTime; | |
| 319 | − float downTime; | |
| 320 | − int samples_per_tick; | |
| 321 | − | |
| 322 | − } _tRampUpDown; | |
| 323 | − | |
| 324 | − typedef _tRampUpDown* tRampUpDown; | |
| 325 | − | |
| 326 | − void tRampUpDown_init (tRampUpDown* const, float upTime, float downTime, int samplesPerTick); | |
| 327 | − void tRampUpDown_free (tRampUpDown* const); | |
| 328 | − void tRampUpDown_initToPool (tRampUpDown* const, float upTime, float downTime, int samplesPerTick, tMempool* const); | |
| 329 | − void tRampUpDown_freeFromPool (tRampUpDown* const, tMempool* const); | |
| 330 | − | |
| 331 | − float tRampUpDown_tick (tRampUpDown* const); | |
| 332 | − float tRampUpDown_sample (tRampUpDown* const); | |
| 333 | − void tRampUpDown_setUpTime (tRampUpDown* const, float upTime); | |
| 334 | − void tRampUpDown_setDownTime (tRampUpDown* const, float downTime); | |
| 335 | − void tRampUpDown_setDest (tRampUpDown* const, float dest); | |
| 336 | − void tRampUpDown_setVal (tRampUpDown* const, float val); | |
| 337 | − | |
| 338 | − | |
| 339 | − ///========================= | |
| 340 | − //Slide (based on Max/MSP's slide~) | |
| 341 | − typedef struct _tSlide { | |
| 342 | − float prevOut; | |
| 343 | − float currentOut; | |
| 344 | − float prevIn; | |
| 345 | − float invUpSlide; | |
| 346 | − float invDownSlide; | |
| 347 | − | |
| 348 | − } _tSlide; | |
| 349 | − | |
| 350 | − typedef _tSlide* tSlide; | |
| 351 | − | |
| 352 | − void tSlide_init (tSlide* const, float upSlide, float downSlide); | |
| 353 | − void tSlide_free (tSlide* const); | |
| 354 | − void tSlide_initToPool (tSlide* const, float upSlide, float downSlide, tMempool* const); | |
| 355 | − void tSlide_freeFromPool (tSlide* const, tMempool* const); | |
| 356 | − | |
| 357 | − float tSlide_tick (tSlide* const, float in); | |
| 358 | − | |
| 359 | −#ifdef __cplusplus | |
| 360 | −} | |
| 361 | −#endif | |
| 362 | − | |
| 363 | −#endif // LEAF_ENVELOPES_H_INCLUDED | |
| 364 | − | |
| 365 | − | |
| 366 | − | |
| @@ -1,486 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-filters.h | |
| 4 | − Created: 20 Jan 2017 12:01:10pm | |
| 5 | − Author: Michael R Mulshine | |
| 6 | − | |
| 7 | − ==============================================================================*/ | |
| 8 | − | |
| 9 | −#ifndef LEAF_FILTERS_H_INCLUDED | |
| 10 | −#define LEAF_FILTERS_H_INCLUDED | |
| 11 | − | |
| 12 | −#ifdef __cplusplus | |
| 13 | −extern "C" { | |
| 14 | −#endif | |
| 15 | − | |
| 16 | − //============================================================================== | |
| 17 | − | |
| 18 | −#include "leaf-math.h" | |
| 19 | −#include "leaf-mempool.h" | |
| 20 | −#include "leaf-delay.h" | |
| 21 | −#include "leaf-tables.h" | |
| 22 | − | |
| 23 | − /*! | |
| 24 | − * @internal | |
| 25 | − * Header. | |
| 26 | − * @include basic-oscillators.h | |
| 27 | − * @example basic-oscillators.c | |
| 28 | − * An example. | |
| 29 | − */ | |
| 30 | − | |
| 31 | − //============================================================================== | |
| 32 | − | |
| 33 | − /* tAllpass: Schroeder allpass. Comb-filter with feedforward and feedback. */ | |
| 34 | − typedef struct _tAllpass | |
| 35 | − { | |
| 36 | − float gain; | |
| 37 | − | |
| 38 | − tLinearDelay delay; | |
| 39 | − | |
| 40 | − float lastOut; | |
| 41 | − | |
| 42 | − } _tAllpass; | |
| 43 | − | |
| 44 | − typedef _tAllpass* tAllpass; | |
| 45 | − | |
| 46 | − void tAllpass_init (tAllpass* const, float initDelay, uint32_t maxDelay); | |
| 47 | − void tAllpass_free (tAllpass* const); | |
| 48 | − void tAllpass_initToPool (tAllpass* const, float initDelay, uint32_t maxDelay, tMempool* const); | |
| 49 | − void tAllpass_freeFromPool (tAllpass* const, tMempool* const); | |
| 50 | − | |
| 51 | − float tAllpass_tick (tAllpass* const, float input); | |
| 52 | − void tAllpass_setGain (tAllpass* const, float gain); | |
| 53 | − void tAllpass_setDelay (tAllpass* const, float delay); | |
| 54 | − | |
| 55 | − | |
| 56 | − //============================================================================== | |
| 57 | − | |
| 58 | − /* tOnePole: OnePole filter, reimplemented from STK (Cook and Scavone). */ | |
| 59 | − typedef struct _tOnePole | |
| 60 | − { | |
| 61 | − float gain; | |
| 62 | − float a0,a1; | |
| 63 | − float b0,b1; | |
| 64 | − float lastIn, lastOut; | |
| 65 | − | |
| 66 | − | |
| 67 | − } _tOnePole; | |
| 68 | − | |
| 69 | − typedef _tOnePole* tOnePole; | |
| 70 | − | |
| 71 | − void tOnePole_init (tOnePole* const, float thePole); | |
| 72 | − void tOnePole_free (tOnePole* const); | |
| 73 | − void tOnePole_initToPool (tOnePole* const, float thePole, tMempool* const); | |
| 74 | − void tOnePole_freeFromPool (tOnePole* const, tMempool* const); | |
| 75 | − | |
| 76 | − float tOnePole_tick (tOnePole* const, float input); | |
| 77 | − void tOnePole_setB0 (tOnePole* const, float b0); | |
| 78 | − void tOnePole_setA1 (tOnePole* const, float a1); | |
| 79 | − void tOnePole_setPole (tOnePole* const, float thePole); | |
| 80 | − void tOnePole_setFreq (tOnePole* const, float freq); | |
| 81 | − void tOnePole_setCoefficients(tOnePole* const, float b0, float a1); | |
| 82 | − void tOnePole_setGain (tOnePole* const, float gain); | |
| 83 | − | |
| 84 | − //============================================================================== | |
| 85 | − | |
| 86 | − /* TwoPole filter, reimplemented from STK (Cook and Scavone). */ | |
| 87 | − typedef struct _tTwoPole | |
| 88 | − { | |
| 89 | − float gain; | |
| 90 | − float a0, a1, a2; | |
| 91 | − float b0; | |
| 92 | − | |
| 93 | − float radius, frequency; | |
| 94 | − oBool normalize; | |
| 95 | − | |
| 96 | − float lastOut[2]; | |
| 97 | − | |
| 98 | − } _tTwoPole; | |
| 99 | − | |
| 100 | − typedef _tTwoPole* tTwoPole; | |
| 101 | − | |
| 102 | − void tTwoPole_init (tTwoPole* const); | |
| 103 | − void tTwoPole_free (tTwoPole* const); | |
| 104 | − void tTwoPole_initToPool (tTwoPole* const, tMempool* const); | |
| 105 | − void tTwoPole_freeFromPool (tTwoPole* const, tMempool* const); | |
| 106 | − | |
| 107 | − float tTwoPole_tick (tTwoPole* const, float input); | |
| 108 | − void tTwoPole_setB0 (tTwoPole* const, float b0); | |
| 109 | − void tTwoPole_setA1 (tTwoPole* const, float a1); | |
| 110 | − void tTwoPole_setA2 (tTwoPole* const, float a2); | |
| 111 | − void tTwoPole_setResonance (tTwoPole* const, float freq, float radius, oBool normalize); | |
| 112 | − void tTwoPole_setCoefficients(tTwoPole* const, float b0, float a1, float a2); | |
| 113 | − void tTwoPole_setGain (tTwoPole* const, float gain); | |
| 114 | − | |
| 115 | − //============================================================================== | |
| 116 | − | |
| 117 | − /* OneZero filter, reimplemented from STK (Cook and Scavone). */ | |
| 118 | − typedef struct _tOneZero | |
| 119 | − { | |
| 120 | − float gain; | |
| 121 | − float b0,b1; | |
| 122 | − float lastIn, lastOut, frequency; | |
| 123 | − | |
| 124 | − } _tOneZero; | |
| 125 | − | |
| 126 | − typedef _tOneZero* tOneZero; | |
| 127 | − | |
| 128 | − void tOneZero_init (tOneZero* const, float theZero); | |
| 129 | − void tOneZero_free (tOneZero* const); | |
| 130 | − void tOneZero_initToPool (tOneZero* const, float theZero, tMempool* const); | |
| 131 | − void tOneZero_freeFromPool (tOneZero* const, tMempool* const); | |
| 132 | − | |
| 133 | − float tOneZero_tick (tOneZero* const, float input); | |
| 134 | − void tOneZero_setB0 (tOneZero* const, float b0); | |
| 135 | − void tOneZero_setB1 (tOneZero* const, float b1); | |
| 136 | − void tOneZero_setZero (tOneZero* const, float theZero); | |
| 137 | − void tOneZero_setCoefficients(tOneZero* const, float b0, float b1); | |
| 138 | − void tOneZero_setGain (tOneZero* const, float gain); | |
| 139 | − float tOneZero_getPhaseDelay (tOneZero *f, float frequency ); | |
| 140 | − | |
| 141 | − //============================================================================== | |
| 142 | − | |
| 143 | − /* TwoZero filter, reimplemented from STK (Cook and Scavone). */ | |
| 144 | − typedef struct _tTwoZero | |
| 145 | − { | |
| 146 | − float gain; | |
| 147 | − float b0, b1, b2; | |
| 148 | − | |
| 149 | − float frequency, radius; | |
| 150 | − | |
| 151 | − float lastIn[2]; | |
| 152 | − | |
| 153 | − } _tTwoZero; | |
| 154 | − | |
| 155 | − typedef _tTwoZero* tTwoZero; | |
| 156 | − | |
| 157 | − void tTwoZero_init (tTwoZero* const); | |
| 158 | − void tTwoZero_free (tTwoZero* const); | |
| 159 | − void tTwoZero_initToPool (tTwoZero* const, tMempool* const); | |
| 160 | − void tTwoZero_freeFromPool (tTwoZero* const, tMempool* const); | |
| 161 | − | |
| 162 | − float tTwoZero_tick (tTwoZero* const, float input); | |
| 163 | − void tTwoZero_setB0 (tTwoZero* const, float b0); | |
| 164 | − void tTwoZero_setB1 (tTwoZero* const, float b1); | |
| 165 | − void tTwoZero_setB2 (tTwoZero* const, float b2); | |
| 166 | − void tTwoZero_setNotch (tTwoZero* const, float frequency, float radius); | |
| 167 | − void tTwoZero_setCoefficients(tTwoZero* const, float b0, float b1, float b2); | |
| 168 | − void tTwoZero_setGain (tTwoZero* const, float gain); | |
| 169 | − | |
| 170 | − //============================================================================== | |
| 171 | − | |
| 172 | − /* PoleZero filter, reimplemented from STK (Cook and Scavone). */ | |
| 173 | − typedef struct _tPoleZero | |
| 174 | − { | |
| 175 | − float gain; | |
| 176 | − float a0,a1; | |
| 177 | − float b0,b1; | |
| 178 | − | |
| 179 | − float lastIn, lastOut; | |
| 180 | − | |
| 181 | − } _tPoleZero; | |
| 182 | − | |
| 183 | − typedef _tPoleZero* tPoleZero; | |
| 184 | − | |
| 185 | − void tPoleZero_init (tPoleZero* const); | |
| 186 | − void tPoleZero_free (tPoleZero* const); | |
| 187 | − void tPoleZero_initToPool (tPoleZero* const, tMempool* const); | |
| 188 | − void tPoleZero_freeFromPool (tPoleZero* const, tMempool* const); | |
| 189 | − | |
| 190 | − float tPoleZero_tick (tPoleZero* const, float input); | |
| 191 | − void tPoleZero_setB0 (tPoleZero* const, float b0); | |
| 192 | − void tPoleZero_setB1 (tPoleZero* const, float b1); | |
| 193 | − void tPoleZero_setA1 (tPoleZero* const, float a1); | |
| 194 | − void tPoleZero_setCoefficients (tPoleZero* const, float b0, float b1, float a1); | |
| 195 | − void tPoleZero_setAllpass (tPoleZero* const, float coeff); | |
| 196 | − void tPoleZero_setBlockZero (tPoleZero* const, float thePole); | |
| 197 | − void tPoleZero_setGain (tPoleZero* const, float gain); | |
| 198 | − | |
| 199 | − //============================================================================== | |
| 200 | − | |
| 201 | − /* BiQuad filter, reimplemented from STK (Cook and Scavone). */ | |
| 202 | − typedef struct _tBiQuad | |
| 203 | − { | |
| 204 | − float gain; | |
| 205 | − float a0, a1, a2; | |
| 206 | − float b0, b1, b2; | |
| 207 | − | |
| 208 | − float lastIn[2]; | |
| 209 | − float lastOut[2]; | |
| 210 | − | |
| 211 | − float frequency, radius; | |
| 212 | − oBool normalize; | |
| 213 | − } _tBiQuad; | |
| 214 | − | |
| 215 | − typedef _tBiQuad* tBiQuad; | |
| 216 | − | |
| 217 | − void tBiQuad_init (tBiQuad* const); | |
| 218 | − void tBiQuad_free (tBiQuad* const); | |
| 219 | − void tBiQuad_initToPool (tBiQuad* const, tMempool* const); | |
| 220 | − void tBiQuad_freeFromPool (tBiQuad* const, tMempool* const); | |
| 221 | − | |
| 222 | − float tBiQuad_tick (tBiQuad* const, float input); | |
| 223 | − void tBiQuad_setB0 (tBiQuad* const, float b0); | |
| 224 | − void tBiQuad_setB1 (tBiQuad* const, float b1); | |
| 225 | − void tBiQuad_setB2 (tBiQuad* const, float b2); | |
| 226 | − void tBiQuad_setA1 (tBiQuad* const, float a1); | |
| 227 | − void tBiQuad_setA2 (tBiQuad* const, float a2); | |
| 228 | − void tBiQuad_setNotch (tBiQuad* const, float freq, float radius); | |
| 229 | − void tBiQuad_setResonance (tBiQuad* const, float freq, float radius, oBool normalize); | |
| 230 | − void tBiQuad_setCoefficients(tBiQuad* const, float b0, float b1, float b2, float a1, float a2); | |
| 231 | − void tBiQuad_setGain (tBiQuad* const, float gain); | |
| 232 | − | |
| 233 | − //============================================================================== | |
| 234 | − | |
| 235 | −/* State Variable Filter, algorithm from Andy Simper. */ | |
| 236 | − typedef enum SVFType | |
| 237 | − { | |
| 238 | − SVFTypeHighpass = 0, | |
| 239 | − SVFTypeLowpass, | |
| 240 | − SVFTypeBandpass, | |
| 241 | − SVFTypeNotch, | |
| 242 | − SVFTypePeak, | |
| 243 | − SVFTypeLowShelf, | |
| 244 | − SVFTypeHighShelf | |
| 245 | − } SVFType; | |
| 246 | − | |
| 247 | − typedef struct _tSVF | |
| 248 | − { | |
| 249 | − SVFType type; | |
| 250 | − float cutoff, Q; | |
| 251 | − float ic1eq,ic2eq; | |
| 252 | − float g,k,a1,a2,a3,cH,cB,cL,cBK; | |
| 253 | − | |
| 254 | − | |
| 255 | − } _tSVF; | |
| 256 | − | |
| 257 | − typedef _tSVF* tSVF; | |
| 258 | − | |
| 259 | − void tSVF_init (tSVF* const, SVFType type, float freq, float Q); | |
| 260 | − void tSVF_free (tSVF* const); | |
| 261 | − void tSVF_initToPool (tSVF* const, SVFType type, float freq, float Q, tMempool* const); | |
| 262 | − void tSVF_freeFromPool (tSVF* const, tMempool* const); | |
| 263 | − | |
| 264 | − float tSVF_tick (tSVF* const, float v0); | |
| 265 | − void tSVF_setFreq (tSVF* const, float freq); | |
| 266 | − void tSVF_setQ (tSVF* const, float Q); | |
| 267 | − void tSVF_setFreqAndQ (tSVF* const svff, float freq, float Q); | |
| 268 | − //============================================================================== | |
| 269 | − | |
| 270 | − /* Efficient State Variable Filter for 14-bit control input, [0, 4096). */ | |
| 271 | − typedef struct _tEfficientSVF | |
| 272 | − { | |
| 273 | − SVFType type; | |
| 274 | − float cutoff, Q; | |
| 275 | − float ic1eq,ic2eq; | |
| 276 | − float g,k,a1,a2,a3; | |
| 277 | − | |
| 278 | − } _tEfficientSVF; | |
| 279 | − | |
| 280 | − typedef _tEfficientSVF* tEfficientSVF; | |
| 281 | − | |
| 282 | − void tEfficientSVF_init (tEfficientSVF* const, SVFType type, uint16_t input, float Q); | |
| 283 | − void tEfficientSVF_free (tEfficientSVF* const); | |
| 284 | − void tEfficientSVF_initToPool (tEfficientSVF* const, SVFType type, uint16_t input, float Q, tMempool* const); | |
| 285 | − void tEfficientSVF_freeFromPool (tEfficientSVF* const, tMempool* const); | |
| 286 | − | |
| 287 | − float tEfficientSVF_tick (tEfficientSVF* const, float v0); | |
| 288 | − void tEfficientSVF_setFreq (tEfficientSVF* const, uint16_t controlFreq); | |
| 289 | − void tEfficientSVF_setQ (tEfficientSVF* const, float Q); | |
| 290 | − | |
| 291 | − //============================================================================== | |
| 292 | − | |
| 293 | − /* Simple Highpass filter. */ | |
| 294 | − typedef struct _tHighpass | |
| 295 | − { | |
| 296 | − float xs, ys, R; | |
| 297 | − float frequency; | |
| 298 | − | |
| 299 | − } _tHighpass; | |
| 300 | − | |
| 301 | − typedef _tHighpass* tHighpass; | |
| 302 | − | |
| 303 | − void tHighpass_init (tHighpass* const, float freq); | |
| 304 | − void tHighpass_free (tHighpass* const); | |
| 305 | − void tHighpass_initToPool (tHighpass* const, float freq, tMempool* const); | |
| 306 | − void tHighpass_freeFromPool (tHighpass* const, tMempool* const); | |
| 307 | − | |
| 308 | − float tHighpass_tick (tHighpass* const, float x); | |
| 309 | − void tHighpass_setFreq (tHighpass* const, float freq); | |
| 310 | − float tHighpass_getFreq (tHighpass* const); | |
| 311 | − | |
| 312 | − //============================================================================== | |
| 313 | − | |
| 314 | − // Butterworth Filter | |
| 315 | −#define NUM_SVF_BW 16 | |
| 316 | − typedef struct _tButterworth | |
| 317 | − { | |
| 318 | − float gain; | |
| 319 | − | |
| 320 | − int N; | |
| 321 | − | |
| 322 | − tSVF low[NUM_SVF_BW]; | |
| 323 | − tSVF high[NUM_SVF_BW]; | |
| 324 | − | |
| 325 | − float f1,f2; | |
| 326 | − | |
| 327 | − } _tButterworth; | |
| 328 | − | |
| 329 | − typedef _tButterworth* tButterworth; | |
| 330 | − | |
| 331 | − void tButterworth_init (tButterworth* const, int N, float f1, float f2); | |
| 332 | − void tButterworth_free (tButterworth* const); | |
| 333 | − void tButterworth_initToPool (tButterworth* const, int N, float f1, float f2, tMempool* const); | |
| 334 | − void tButterworth_freeFromPool (tButterworth* const, tMempool* const); | |
| 335 | − | |
| 336 | − float tButterworth_tick (tButterworth* const, float input); | |
| 337 | − void tButterworth_setF1 (tButterworth* const, float in); | |
| 338 | − void tButterworth_setF2 (tButterworth* const, float in); | |
| 339 | − void tButterworth_setFreqs (tButterworth* const, float f1, float f2); | |
| 340 | − | |
| 341 | − //============================================================================== | |
| 342 | − | |
| 343 | − typedef struct _tFIR | |
| 344 | − { | |
| 345 | − float* past; | |
| 346 | − float* coeff; | |
| 347 | − int numTaps; | |
| 348 | − } _tFIR; | |
| 349 | − | |
| 350 | − typedef _tFIR* tFIR; | |
| 351 | − | |
| 352 | − void tFIR_init (tFIR* const, float* coeffs, int numTaps); | |
| 353 | − void tFIR_free (tFIR* const); | |
| 354 | − void tFIR_initToPool (tFIR* const, float* coeffs, int numTaps, tMempool* const); | |
| 355 | − void tFIR_freeFromPool (tFIR* const, tMempool* const); | |
| 356 | − | |
| 357 | − float tFIR_tick (tFIR* const, float input); | |
| 358 | − | |
| 359 | − | |
| 360 | − //============================================================================== | |
| 361 | − | |
| 362 | − | |
| 363 | − typedef struct _tMedianFilter | |
| 364 | − { | |
| 365 | − float* val; | |
| 366 | − int* age; | |
| 367 | − int m; | |
| 368 | − int size; | |
| 369 | − int middlePosition; | |
| 370 | − int last; | |
| 371 | − int pos; | |
| 372 | − } _tMedianFilter; | |
| 373 | − | |
| 374 | − typedef _tMedianFilter* tMedianFilter; | |
| 375 | − | |
| 376 | − void tMedianFilter_init (tMedianFilter* const, int size); | |
| 377 | − void tMedianFilter_free (tMedianFilter* const); | |
| 378 | − void tMedianFilter_initToPool (tMedianFilter* const, int size, tMempool* const); | |
| 379 | − void tMedianFilter_freeFromPool (tMedianFilter* const, tMempool* const); | |
| 380 | − | |
| 381 | − float tMedianFilter_tick (tMedianFilter* const, float input); | |
| 382 | − | |
| 383 | − | |
| 384 | − | |
| 385 | − | |
| 386 | − | |
| 387 | − //Vadim Zavalishin style from VA book (from implementation in RSlib posted to kvr forum) | |
| 388 | − | |
| 389 | − typedef enum VZFilterType | |
| 390 | − { | |
| 391 | − Highpass = 0, | |
| 392 | − Lowpass, | |
| 393 | − BandpassSkirt, | |
| 394 | − BandpassPeak, | |
| 395 | − BandReject, | |
| 396 | − Bell, | |
| 397 | − Lowshelf, | |
| 398 | − Highshelf, | |
| 399 | − Morph, | |
| 400 | − Bypass, | |
| 401 | − Allpass | |
| 402 | − } VZFilterType; | |
| 403 | − | |
| 404 | − | |
| 405 | − typedef struct _tVZFilter | |
| 406 | − { | |
| 407 | − VZFilterType type; | |
| 408 | − // state: | |
| 409 | − float s1, s2; | |
| 410 | − | |
| 411 | − // filter coefficients: | |
| 412 | − float g; // embedded integrator gain | |
| 413 | − float R2; // twice the damping coefficient (R2 == 2*R == 1/Q) | |
| 414 | − float h; // factor for feedback (== 1/(1+2*R*g+g*g)) | |
| 415 | − float cL, cB, cH; // coefficients for low-, band-, and highpass signals | |
| 416 | − | |
| 417 | − // parameters: | |
| 418 | − float fs; // sample-rate | |
| 419 | − float fc; // characteristic frequency | |
| 420 | − float G; // gain | |
| 421 | − float invG; //1/gain | |
| 422 | − float B; // bandwidth (in octaves) | |
| 423 | − float m; // morph parameter (0...1) | |
| 424 | − | |
| 425 | − float sr; //local sampling rate of filter (may be different from leaf sr if oversampled) | |
| 426 | − float inv_sr; | |
| 427 | − | |
| 428 | − } _tVZFilter; | |
| 429 | − | |
| 430 | − typedef _tVZFilter* tVZFilter; | |
| 431 | − | |
| 432 | − void tVZFilter_init (tVZFilter* const, VZFilterType type, float freq, float Q); | |
| 433 | − void tVZFilter_free (tVZFilter* const); | |
| 434 | − void tVZFilter_initToPool (tVZFilter* const, VZFilterType type, float freq, float Q, tMempool* const); | |
| 435 | − void tVZFilter_freeFromPool (tVZFilter* const, tMempool* const); | |
| 436 | − void tVZFilter_setSampleRate (tVZFilter* const, float sampleRate); | |
| 437 | − float tVZFilter_tick (tVZFilter* const, float input); | |
| 438 | − float tVZFilter_tickEfficient (tVZFilter* const vf, float in); | |
| 439 | − void tVZFilter_calcCoeffs (tVZFilter* const); | |
| 440 | − void tVZFilter_setBandwidth (tVZFilter* const, float bandWidth); | |
| 441 | − void tVZFilter_setFreq (tVZFilter* const, float freq); | |
| 442 | − void tVZFilter_setFreqAndBandwidth (tVZFilter* const vf, float freq, float bw); | |
| 443 | − void tVZFilter_setGain (tVZFilter* const, float gain); | |
| 444 | − void tVZFilter_setType (tVZFilter* const, VZFilterType type); | |
| 445 | − float tVZFilter_BandwidthToR (tVZFilter* const vf, float B); | |
| 446 | − | |
| 447 | − | |
| 448 | − | |
| 449 | − | |
| 450 | − //diode ladder filter | |
| 451 | − typedef struct _tDiodeFilter | |
| 452 | − { | |
| 453 | − | |
| 454 | − float f; | |
| 455 | − float r; | |
| 456 | − float Vt; | |
| 457 | − float n; | |
| 458 | − float gamma; | |
| 459 | − float zi; | |
| 460 | − float g0inv; | |
| 461 | − float g1inv; | |
| 462 | − float g2inv; | |
| 463 | − float s0, s1, s2, s3; | |
| 464 | − | |
| 465 | − } _tDiodeFilter; | |
| 466 | − | |
| 467 | − typedef _tDiodeFilter* tDiodeFilter; | |
| 468 | − | |
| 469 | − void tDiodeFilter_init (tDiodeFilter* const, float freq, float Q); | |
| 470 | − void tDiodeFilter_free (tDiodeFilter* const); | |
| 471 | − void tDiodeFilter_initToPool (tDiodeFilter* const, float freq, float Q, tMempool* const); | |
| 472 | − void tDiodeFilter_freeFromPool (tDiodeFilter* const, tMempool* const); | |
| 473 | − | |
| 474 | − float tDiodeFilter_tick (tDiodeFilter* const, float input); | |
| 475 | − void tDiodeFilter_setFreq (tDiodeFilter* const vf, float cutoff); | |
| 476 | − void tDiodeFilter_setQ (tDiodeFilter* const vf, float resonance); | |
| 477 | − | |
| 478 | − | |
| 479 | −#ifdef __cplusplus | |
| 480 | −} | |
| 481 | −#endif | |
| 482 | − | |
| 483 | −#endif // LEAF_FILTERS_H_INCLUDED | |
| 484 | − | |
| 485 | −//============================================================================== | |
| 486 | − | |
| @@ -1,52 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − ============================================================================== | |
| 3 | − | |
| 4 | − leaf-global.h | |
| 5 | − Created: 24 Oct 2019 2:24:38pm | |
| 6 | − Author: Matthew Wang | |
| 7 | − | |
| 8 | − ============================================================================== | |
| 9 | − */ | |
| 10 | − | |
| 11 | −#ifndef LEAF_GLOBAL_H_INCLUDED | |
| 12 | −#define LEAF_GLOBAL_H_INCLUDED | |
| 13 | − | |
| 14 | −#ifdef __cplusplus | |
| 15 | −extern "C" { | |
| 16 | −#endif | |
| 17 | − | |
| 18 | −#include "leaf-mempool.h" | |
| 19 | − | |
| 20 | − /*! | |
| 21 | − * @ingroup leaf | |
| 22 | − * @brief The struct of the global LEAF instance `leaf`. Contains global variables and settings. | |
| 23 | − */ | |
| 24 | − struct LEAF | |
| 25 | − { | |
| 26 | − ///@{ | |
| 27 | − float sampleRate; //!< The current audio sample rate. Set with LEAF_setSampleRate(). | |
| 28 | − float invSampleRate; //!< The inverse of the current sample rate. | |
| 29 | − int blockSize; //!< The audio block size. | |
| 30 | − float twoPiTimesInvSampleRate; //!< Two-pi times the inverse of the current sample rate. | |
| 31 | − float (*random)(void); //!< A pointer to the random() function provided on initialization. | |
| 32 | − int clearOnAllocation; //!< A flag that determines whether memory allocated from the LEAF memory pool will be cleared. | |
| 33 | − tMempool mempool; //!< The default LEAF mempool object. | |
| 34 | − _tMempool _mempool; | |
| 35 | − size_t header_size; //!< The size in bytes of memory region headers within mempools. | |
| 36 | − ///@} | |
| 37 | − }; | |
| 38 | − typedef struct LEAF LEAF; | |
| 39 | − | |
| 40 | − extern LEAF leaf; | |
| 41 | − | |
| 42 | − //============================================================================== | |
| 43 | − | |
| 44 | −#ifdef __cplusplus | |
| 45 | −} | |
| 46 | −#endif | |
| 47 | − | |
| 48 | −#endif // LEAF_GLOBAL_H_INCLUDED | |
| 49 | − | |
| 50 | −//============================================================================== | |
| 51 | − | |
| 52 | − | |
| @@ -1,209 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-instruments.h | |
| 4 | − Created: 30 Nov 2018 10:24:44am | |
| 5 | − Author: airship | |
| 6 | − | |
| 7 | − ==============================================================================*/ | |
| 8 | − | |
| 9 | −#ifndef LEAF_INSTRUMENTS_H_INCLUDED | |
| 10 | −#define LEAF_INSTRUMENTS_H_INCLUDED | |
| 11 | − | |
| 12 | −#ifdef __cplusplus | |
| 13 | −extern "C" { | |
| 14 | −#endif | |
| 15 | − | |
| 16 | − //============================================================================== | |
| 17 | − | |
| 18 | −#include "leaf-math.h" | |
| 19 | −#include "leaf-mempool.h" | |
| 20 | −#include "leaf-oscillators.h" | |
| 21 | −#include "leaf-filters.h" | |
| 22 | −#include "leaf-envelopes.h" | |
| 23 | − | |
| 24 | − /*! | |
| 25 | − * @internal | |
| 26 | − * Header. | |
| 27 | − * @include basic-oscillators.h | |
| 28 | − * @example basic-oscillators.c | |
| 29 | − * An example. | |
| 30 | − */ | |
| 31 | − | |
| 32 | − //============================================================================== | |
| 33 | − | |
| 34 | − // 808 Cowbell | |
| 35 | − typedef struct _t808Cowbell { | |
| 36 | − | |
| 37 | − tSquare p[2]; | |
| 38 | − tNoise stick; | |
| 39 | − tSVF bandpassOsc; | |
| 40 | − tSVF bandpassStick; | |
| 41 | − tEnvelope envGain; | |
| 42 | − tEnvelope envStick; | |
| 43 | − tEnvelope envFilter; | |
| 44 | − tHighpass highpass; | |
| 45 | − float oscMix; | |
| 46 | − float filterCutoff; | |
| 47 | − uint8_t useStick; | |
| 48 | − | |
| 49 | − } _t808Cowbell; | |
| 50 | − | |
| 51 | − typedef _t808Cowbell* t808Cowbell; | |
| 52 | − | |
| 53 | − void t808Cowbell_init (t808Cowbell* const, int useStick); | |
| 54 | − void t808Cowbell_free (t808Cowbell* const); | |
| 55 | − void t808Cowbell_initToPool (t808Cowbell* const, int useStick, tMempool* const); | |
| 56 | − void t808Cowbell_freeFromPool (t808Cowbell* const, tMempool* const); | |
| 57 | − | |
| 58 | − float t808Cowbell_tick (t808Cowbell* const); | |
| 59 | − void t808Cowbell_on (t808Cowbell* const, float vel); | |
| 60 | − void t808Cowbell_setDecay (t808Cowbell* const, float decay); | |
| 61 | − void t808Cowbell_setHighpassFreq (t808Cowbell* const, float freq); | |
| 62 | − void t808Cowbell_setBandpassFreq (t808Cowbell* const, float freq); | |
| 63 | − void t808Cowbell_setFreq (t808Cowbell* const, float freq); | |
| 64 | − void t808Cowbell_setOscMix (t808Cowbell* const, float oscMix); | |
| 65 | − void t808Cowbell_setStick (t808Cowbell* const, int useStick); | |
| 66 | − | |
| 67 | − //============================================================================== | |
| 68 | − | |
| 69 | − // 808 Hihat | |
| 70 | − typedef struct _t808Hihat { | |
| 71 | − | |
| 72 | − // 6 Square waves | |
| 73 | − tSquare p[6]; | |
| 74 | − tNoise n; | |
| 75 | − tSVF bandpassOsc; | |
| 76 | − tSVF bandpassStick; | |
| 77 | − tEnvelope envGain; | |
| 78 | − tEnvelope envStick; | |
| 79 | − tEnvelope noiseFMGain; | |
| 80 | − tHighpass highpass; | |
| 81 | − tNoise stick; | |
| 82 | − | |
| 83 | − float freq; | |
| 84 | − float stretch; | |
| 85 | − float FM_amount; | |
| 86 | − float oscNoiseMix; | |
| 87 | − | |
| 88 | − } _t808Hihat; | |
| 89 | − | |
| 90 | − typedef _t808Hihat* t808Hihat; | |
| 91 | − | |
| 92 | − void t808Hihat_init (t808Hihat* const); | |
| 93 | − void t808Hihat_free (t808Hihat* const); | |
| 94 | − void t808Hihat_initToPool (t808Hihat* const, tMempool* const); | |
| 95 | − void t808Hihat_freeFromPool (t808Hihat* const, tMempool* const); | |
| 96 | − | |
| 97 | − float t808Hihat_tick (t808Hihat* const); | |
| 98 | − void t808Hihat_on (t808Hihat* const, float vel); | |
| 99 | − void t808Hihat_setOscNoiseMix (t808Hihat* const, float oscNoiseMix); | |
| 100 | − void t808Hihat_setDecay (t808Hihat* const, float decay); | |
| 101 | − void t808Hihat_setHighpassFreq (t808Hihat* const, float freq); | |
| 102 | − void t808Hihat_setOscBandpassFreq (t808Hihat* const, float freq); | |
| 103 | − void t808Hihat_setOscBandpassQ (t808Hihat* const hihat, float Q); | |
| 104 | − void t808Hihat_setStickBandPassFreq (t808Hihat* const, float freq); | |
| 105 | − void t808Hihat_setStickBandPassQ (t808Hihat* const hihat, float Q); | |
| 106 | − void t808Hihat_setOscFreq (t808Hihat* const, float freq); | |
| 107 | − void t808Hihat_setStretch (t808Hihat* const hihat, float stretch); | |
| 108 | − void t808Hihat_setFM (t808Hihat* const hihat, float FM_amount); | |
| 109 | − | |
| 110 | − //============================================================================== | |
| 111 | − | |
| 112 | − // 808 Snare | |
| 113 | − typedef struct _t808Snare { | |
| 114 | − | |
| 115 | − // Tone 1, Tone 2, Noise | |
| 116 | − tTriangle tone[2]; // Tri (not yet antialiased or wavetabled) | |
| 117 | − tNoise noiseOsc; | |
| 118 | − tSVF toneLowpass[2]; | |
| 119 | − tSVF noiseLowpass; // Lowpass from SVF filter | |
| 120 | − tEnvelope toneEnvOsc[2]; | |
| 121 | − tEnvelope toneEnvGain[2]; | |
| 122 | − tEnvelope noiseEnvGain; | |
| 123 | − tEnvelope toneEnvFilter[2]; | |
| 124 | − tEnvelope noiseEnvFilter; | |
| 125 | − | |
| 126 | − float toneGain[2]; | |
| 127 | − float noiseGain; | |
| 128 | − | |
| 129 | − float toneNoiseMix; | |
| 130 | − | |
| 131 | − float tone1Freq, tone2Freq; | |
| 132 | − | |
| 133 | − float noiseFilterFreq; | |
| 134 | − | |
| 135 | − } _t808Snare; | |
| 136 | − | |
| 137 | − typedef _t808Snare* t808Snare; | |
| 138 | − | |
| 139 | − void t808Snare_init (t808Snare* const); | |
| 140 | − void t808Snare_free (t808Snare* const); | |
| 141 | − void t808Snare_initToPool (t808Snare* const, tMempool* const); | |
| 142 | − void t808Snare_freeFromPool (t808Snare* const, tMempool* const); | |
| 143 | − | |
| 144 | − float t808Snare_tick (t808Snare* const); | |
| 145 | − void t808Snare_on (t808Snare* const, float vel); | |
| 146 | − void t808Snare_setTone1Freq (t808Snare* const, float freq); | |
| 147 | − void t808Snare_setTone2Freq (t808Snare* const, float freq); | |
| 148 | − void t808Snare_setTone1Decay (t808Snare* const, float decay); | |
| 149 | − void t808Snare_setTone2Decay (t808Snare* const, float decay); | |
| 150 | − void t808Snare_setNoiseDecay (t808Snare* const, float decay); | |
| 151 | − void t808Snare_setToneNoiseMix (t808Snare* const, float toneNoiseMix); | |
| 152 | − void t808Snare_setNoiseFilterFreq (t808Snare* const, float noiseFilterFreq); | |
| 153 | − void t808Snare_setNoiseFilterQ (t808Snare* const, float noiseFilterQ); | |
| 154 | − | |
| 155 | − //============================================================================== | |
| 156 | − | |
| 157 | − // 808 Kick | |
| 158 | − typedef struct _t808Kick { | |
| 159 | − | |
| 160 | − | |
| 161 | − tCycle tone; // Tri | |
| 162 | − tNoise noiseOsc; | |
| 163 | − tSVF toneLowpass; | |
| 164 | − tEnvelope toneEnvOscChirp; | |
| 165 | − tEnvelope toneEnvOscSigh; | |
| 166 | − tEnvelope toneEnvGain; | |
| 167 | − tEnvelope noiseEnvGain; | |
| 168 | − tEnvelope toneEnvFilter; | |
| 169 | − | |
| 170 | − float toneGain; | |
| 171 | − float noiseGain; | |
| 172 | − | |
| 173 | − float toneInitialFreq; | |
| 174 | − float sighAmountInHz; | |
| 175 | − float chirpRatioMinusOne; | |
| 176 | − float noiseFilterFreq; | |
| 177 | − | |
| 178 | − } _t808Kick; | |
| 179 | − | |
| 180 | − typedef _t808Kick* t808Kick; | |
| 181 | − | |
| 182 | − void t808Kick_init (t808Kick* const); | |
| 183 | − void t808Kick_free (t808Kick* const); | |
| 184 | − void t808Kick_initToPool (t808Kick* const, tMempool* const); | |
| 185 | − void t808Kick_freeFromPool (t808Kick* const, tMempool* const); | |
| 186 | − | |
| 187 | − float t808Kick_tick (t808Kick* const); | |
| 188 | − void t808Kick_on (t808Kick* const, float vel); | |
| 189 | − void t808Kick_setToneFreq (t808Kick* const, float freq); | |
| 190 | − void t808Kick_setToneDecay (t808Kick* const, float decay); | |
| 191 | − void t808Kick_setNoiseDecay (t808Kick* const, float decay); | |
| 192 | − void t808Kick_setSighAmount (t808Kick* const, float sigh); | |
| 193 | − void t808Kick_setChirpAmount (t808Kick* const, float chirp); | |
| 194 | − void t808Kick_setToneNoiseMix (t808Kick* const, float toneNoiseMix); | |
| 195 | − void t808Kick_setNoiseFilterFreq (t808Kick* const, float noiseFilterFreq); | |
| 196 | − void t808Kick_setNoiseFilterQ (t808Kick* const, float noiseFilterQ); | |
| 197 | − | |
| 198 | − //============================================================================== | |
| 199 | − | |
| 200 | −#ifdef __cplusplus | |
| 201 | −} | |
| 202 | −#endif | |
| 203 | − | |
| 204 | −#endif // LEAF_INSTRUMENTS_H_INCLUDED | |
| 205 | − | |
| 206 | −//============================================================================== | |
| 207 | − | |
| 208 | − | |
| 209 | − | |
| @@ -1,212 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-math.h | |
| 4 | − Created: 22 Jan 2017 7:02:56pm | |
| 5 | − Author: Michael R Mulshine | |
| 6 | − | |
| 7 | − ==============================================================================*/ | |
| 8 | − | |
| 9 | −#ifndef LEAF_MATH_H_INCLUDED | |
| 10 | −#define LEAF_MATH_H_INCLUDED | |
| 11 | − | |
| 12 | −#ifdef __cplusplus | |
| 13 | −extern "C" { | |
| 14 | −#endif | |
| 15 | − | |
| 16 | −#include "leaf-global.h" | |
| 17 | −#include "math.h" | |
| 18 | −#include "stdint.h" | |
| 19 | −#include "stdlib.h" | |
| 20 | − | |
| 21 | − //============================================================================== | |
| 22 | − | |
| 23 | − //============================================================================== | |
| 24 | − | |
| 25 | − typedef enum oBool | |
| 26 | − { | |
| 27 | − OTRUE = 1, | |
| 28 | − OFALSE = 0 | |
| 29 | − }oBool; | |
| 30 | − | |
| 31 | − // Allows for bitwise operations on floats | |
| 32 | − union unholy_t { /* a union between a float and an integer */ | |
| 33 | − float f; | |
| 34 | − int i; | |
| 35 | − }; | |
| 36 | − | |
| 37 | −#define SQRT8 2.82842712475f | |
| 38 | −#define WSCALE 1.30612244898f | |
| 39 | −#define PI (3.14159265358979f) | |
| 40 | −#define TWO_PI (6.28318530717958f) | |
| 41 | −#define HALF_PI (1.570796326794897f) | |
| 42 | − | |
| 43 | −#define VSF 1.0e-38f | |
| 44 | − | |
| 45 | −#define MAX_DELAY 8192 | |
| 46 | −#define INV_128 0.0078125f | |
| 47 | − | |
| 48 | −#define INV_20 0.05f | |
| 49 | −#define INV_40 0.025f | |
| 50 | −#define INV_80 0.0125f | |
| 51 | −#define INV_160 0.00625f | |
| 52 | −#define INV_320 0.003125f | |
| 53 | −#define INV_640 0.0015625f | |
| 54 | −#define INV_1280 0.00078125f | |
| 55 | −#define INV_2560 0.000390625f | |
| 56 | −#define INV_5120 0.0001953125f | |
| 57 | −#define INV_10240 0.00009765625f | |
| 58 | −#define INV_20480 0.000048828125f | |
| 59 | − | |
| 60 | − | |
| 61 | −#define INV_TWELVE 0.0833333333f | |
| 62 | −#define INV_440 0.0022727273f | |
| 63 | − | |
| 64 | −#define LOG2 0.3010299957f | |
| 65 | −#define INV_LOG2 3.321928095f | |
| 66 | − | |
| 67 | −#define SOS_M 343.0f | |
| 68 | −#define TWO_TO_5 32.0f | |
| 69 | −#define INV_TWO_TO_5 0.03125f | |
| 70 | −#define TWO_TO_7 128.f | |
| 71 | −#define INV_TWO_TO_7 0.0078125f | |
| 72 | −#define TWO_TO_8 256.f | |
| 73 | −#define INV_TWO_TO_8 0.00390625f | |
| 74 | −#define TWO_TO_9 512.f | |
| 75 | −#define INV_TWO_TO_9 0.001953125f | |
| 76 | −#define TWO_TO_10 1024.f | |
| 77 | −#define INV_TWO_TO_10 0.0009765625f | |
| 78 | −#define TWO_TO_11 2048.f | |
| 79 | −#define INV_TWO_TO_11 0.00048828125f | |
| 80 | −#define TWO_TO_12 4096.f | |
| 81 | −#define INV_TWO_TO_12 0.00024414062f | |
| 82 | −#define TWO_TO_15 32768.f | |
| 83 | −#define TWO_TO_16 65536.f | |
| 84 | −#define INV_TWO_TO_15 0.00003051757f | |
| 85 | −#define INV_TWO_TO_16 0.00001525878f | |
| 86 | −#define TWO_TO_16_MINUS_ONE 65535.0f | |
| 87 | −#define TWO_TO_23 8388608.0f | |
| 88 | −#define INV_TWO_TO_23 0.00000011920929f | |
| 89 | −#define TWO_TO_31 2147483648.0f | |
| 90 | −#define INV_TWO_TO_31 0.000000000465661f | |
| 91 | −#define TWO_TO_32 4294967296.0f | |
| 92 | −#define INV_TWO_TO_32 0.000000000232831f | |
| 93 | − | |
| 94 | −#define ONE_OVER_SQRT2 0.707106781186548f | |
| 95 | − | |
| 96 | −#define LOGTEN 2.302585092994 | |
| 97 | − | |
| 98 | − // Jones shaper | |
| 99 | − float LEAF_shaper (float input, float m_drive); | |
| 100 | − float LEAF_reedTable (float input, float offset, float slope); | |
| 101 | − | |
| 102 | − float LEAF_reduct (float input, float ratio); | |
| 103 | − float LEAF_round (float input, float rnd); | |
| 104 | − float LEAF_bitwise_xor(float input, uint32_t op); | |
| 105 | − | |
| 106 | − float LEAF_reduct (float input, float ratio); | |
| 107 | − float LEAF_round (float input, float rnd); | |
| 108 | − float LEAF_bitwise_xor(float input, uint32_t op); | |
| 109 | − | |
| 110 | − float LEAF_clip (float min, float val, float max); | |
| 111 | − int LEAF_clipInt (int min, int val, int max); | |
| 112 | − float LEAF_softClip (float val, float thresh); | |
| 113 | − oBool LEAF_isPrime (uint64_t number ); | |
| 114 | − | |
| 115 | − float LEAF_midiToFrequency (float f); | |
| 116 | − float LEAF_frequencyToMidi(float f); | |
| 117 | − | |
| 118 | − void LEAF_generate_sine (float* buffer, int size); | |
| 119 | − void LEAF_generate_sawtooth (float* buffer, float basefreq, int size); | |
| 120 | − void LEAF_generate_triangle (float* buffer, float basefreq, int size); | |
| 121 | − void LEAF_generate_square (float* buffer, float basefreq, int size); | |
| 122 | − | |
| 123 | − // dope af | |
| 124 | − float LEAF_chebyshevT(float in, int n); | |
| 125 | − float LEAF_CompoundChebyshevT(float in, int n, float* amps); | |
| 126 | − | |
| 127 | − // Hermite interpolation | |
| 128 | − float LEAF_interpolate_hermite (float A, float B, float C, float D, float t); | |
| 129 | − float LEAF_interpolate_hermite_x(float yy0, float yy1, float yy2, float yy3, float xx); | |
| 130 | − float LEAF_interpolation_linear (float A, float B, float t); | |
| 131 | − | |
| 132 | − float interpolate3max(float *buf, const int peakindex); | |
| 133 | − float interpolate3phase(float *buf, const int peakindex); | |
| 134 | − | |
| 135 | − // alternative implementation for abs() | |
| 136 | − // REQUIRES: 32 bit integers | |
| 137 | − int fastabs_int(int in); | |
| 138 | − | |
| 139 | − // alternative implementation for abs() | |
| 140 | − // REQUIRES: 32 bit floats | |
| 141 | − float fastabsf(float f); | |
| 142 | − | |
| 143 | − float fastexp2f(float f); | |
| 144 | − | |
| 145 | − float fastPowf(float a, float b) ; | |
| 146 | − double fastPow(double a, double b); | |
| 147 | − | |
| 148 | − | |
| 149 | − void LEAF_crossfade(float fade, float* volumes); | |
| 150 | − | |
| 151 | − | |
| 152 | − float LEAF_tanh(float x); | |
| 153 | − void LEAF_generate_sine(float* buffer, int size); | |
| 154 | − void LEAF_generate_sawtooth(float* buffer, float basefreq, int size); | |
| 155 | − void LEAF_generate_triangle(float* buffer, float basefreq, int size); | |
| 156 | − void LEAF_generate_square(float* buffer, float basefreq, int size); | |
| 157 | − | |
| 158 | − //0.001 base gives a good curve that goes from 1 to near zero | |
| 159 | − //1000 gives a good curve from -1.0 to 0.0 | |
| 160 | − void LEAF_generate_exp(float* buffer, float base, float start, float end, float offset, int size); | |
| 161 | − | |
| 162 | − float LEAF_poly_blep(float t, float dt); | |
| 163 | − float LEAF_midiToFrequency(float f); | |
| 164 | − | |
| 165 | − | |
| 166 | − float fast_mtof(float f); | |
| 167 | − | |
| 168 | − double fastexp(double x); | |
| 169 | − | |
| 170 | − float fastexpf(float x); | |
| 171 | − | |
| 172 | − double fasterexp(double x); | |
| 173 | − | |
| 174 | − float fasterexpf(float x); | |
| 175 | − | |
| 176 | − float mtof(float f); | |
| 177 | − | |
| 178 | − float fast_mtof(float f); | |
| 179 | − | |
| 180 | − float faster_mtof(float f); | |
| 181 | − | |
| 182 | − float ftom(float f); | |
| 183 | − | |
| 184 | − float powtodb(float f); | |
| 185 | − | |
| 186 | − float rmstodb(float f); | |
| 187 | − | |
| 188 | − float dbtopow(float f); | |
| 189 | − | |
| 190 | − float dbtorms(float f); | |
| 191 | − | |
| 192 | − float atodb(float a); | |
| 193 | − | |
| 194 | − float dbtoa(float db); | |
| 195 | − | |
| 196 | − float fastdbtoa(float db); | |
| 197 | − | |
| 198 | − float maximum (float num1, float num2); | |
| 199 | − | |
| 200 | − float minimum (float num1, float num2); | |
| 201 | − | |
| 202 | − | |
| 203 | − //============================================================================== | |
| 204 | − | |
| 205 | −#ifdef __cplusplus | |
| 206 | −} | |
| 207 | −#endif | |
| 208 | − | |
| 209 | −#endif // LEAF_MATH_H_INCLUDED | |
| 210 | − | |
| 211 | −//============================================================================== | |
| 212 | − | |
| @@ -1,159 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − In short, mpool is distributed under so called "BSD license", | |
| 4 | − | |
| 5 | − Copyright (c) 2009-2010 Tatsuhiko Kubo <cubicdaiya@gmail.com> | |
| 6 | − All rights reserved. | |
| 7 | − | |
| 8 | − Redistribution and use in source and binary forms, with or without modification, | |
| 9 | − are permitted provided that the following conditions are met: | |
| 10 | − | |
| 11 | − * Redistributions of source code must retain the above copyright notice, | |
| 12 | − this list of conditions and the following disclaimer. | |
| 13 | − | |
| 14 | − * Redistributions in binary form must reproduce the above copyright notice, | |
| 15 | − this list of conditions and the following disclaimer in the documentation | |
| 16 | − and/or other materials provided with the distribution. | |
| 17 | − | |
| 18 | − * Neither the name of the authors nor the names of its contributors | |
| 19 | − may be used to endorse or promote products derived from this software | |
| 20 | − without specific prior written permission. | |
| 21 | − | |
| 22 | − THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 23 | − "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 24 | − LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 25 | − A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 26 | − OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 27 | − SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
| 28 | − TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 29 | − PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 30 | − LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 31 | − NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 32 | − SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 33 | − | |
| 34 | − written by C99 style | |
| 35 | − ==============================================================================*/ | |
| 36 | − | |
| 37 | −#ifndef LEAF_MPOOL_H_INCLUDED | |
| 38 | −#define LEAF_MPOOL_H_INCLUDED | |
| 39 | − | |
| 40 | −#ifdef __cplusplus | |
| 41 | −extern "C" { | |
| 42 | −#endif | |
| 43 | − | |
| 44 | − //============================================================================== | |
| 45 | − | |
| 46 | −#include <stdio.h> | |
| 47 | −#include <stdlib.h> | |
| 48 | −#include <string.h> | |
| 49 | −#include <stdbool.h> | |
| 50 | − | |
| 51 | − //============================================================================== | |
| 52 | − | |
| 53 | −#define MPOOL_ALIGN_SIZE (8) | |
| 54 | − | |
| 55 | − //#define size_t unsigned long | |
| 56 | − | |
| 57 | − /*! | |
| 58 | − * @defgroup tmempool tMempool | |
| 59 | − * @ingroup mempool | |
| 60 | − * An object that can contain an additional mempool for the allocation of LEAF objects. | |
| 61 | − * @{ | |
| 62 | − */ | |
| 63 | − | |
| 64 | − // node of free list | |
| 65 | − typedef struct mpool_node_t { | |
| 66 | − char *pool; // memory pool field | |
| 67 | − struct mpool_node_t *next; // next node pointer | |
| 68 | − struct mpool_node_t *prev; // prev node pointer | |
| 69 | − size_t size; | |
| 70 | − } mpool_node_t; | |
| 71 | − | |
| 72 | − typedef struct _tMempool | |
| 73 | − { | |
| 74 | − char* mpool; // start of the mpool | |
| 75 | − size_t usize; // used size of the pool | |
| 76 | − size_t msize; // max size of the pool | |
| 77 | − mpool_node_t* head; // first node of memory pool free list | |
| 78 | − } _tMempool; | |
| 79 | − | |
| 80 | − typedef _tMempool* tMempool; | |
| 81 | − | |
| 82 | − //! Initialize a tMempool for a given memory location and size to the default LEAF mempool. | |
| 83 | − /*! | |
| 84 | − @param pool A pointer to the tMempool to be initialized. | |
| 85 | − @param memory A pointer to the chunk of memory to be used as a mempool. | |
| 86 | − @param size The size of the chunk of memory to be used as a mempool. | |
| 87 | − */ | |
| 88 | − void tMempool_init (tMempool* const pool, char* memory, size_t size); | |
| 89 | − | |
| 90 | − | |
| 91 | − //! Free a tMempool from the default LEAF mempool. | |
| 92 | − /*! | |
| 93 | − @param pool A pointer to the tMempool to be freed. | |
| 94 | − */ | |
| 95 | − void tMempool_free (tMempool* const pool); | |
| 96 | − | |
| 97 | − | |
| 98 | − //! Initialize a tMempool for a given memory location and size to a specified mempool. | |
| 99 | − /*! | |
| 100 | − @param pool A pointer to the tMempool to be initialized. | |
| 101 | − @param memory A pointer to the chunk of memory to be used as a mempool. | |
| 102 | − @param size The size of the chuck of memory to be used as a mempool. | |
| 103 | − @param poolTo A pointer to the tMempool to which a tMempool should be initialized. | |
| 104 | − */ | |
| 105 | − void tMempool_initToPool (tMempool* const pool, char* memory, size_t size, tMempool* const poolTo); | |
| 106 | − | |
| 107 | − | |
| 108 | − //! Free a tMempool from a specified mempool. | |
| 109 | − /*! | |
| 110 | − @param pool A pointer to the tMempool to be freed from the default LEAF mempool. | |
| 111 | − @param poolFrom A pointer to the tMempool from which a tMempool should be freed. | |
| 112 | − */ | |
| 113 | − void tMempool_freeFromPool (tMempool* const pool, tMempool* const poolFrom); | |
| 114 | − | |
| 115 | − /*! @} */ | |
| 116 | − | |
| 117 | − //============================================================================== | |
| 118 | − | |
| 119 | − // typedef struct mpool_t { | |
| 120 | − // char* mpool; // start of the mpool | |
| 121 | − // size_t usize; // used size of the pool | |
| 122 | − // size_t msize; // max size of the pool | |
| 123 | − // mpool_node_t* head; // first node of memory pool free list | |
| 124 | − // } mpool_t; | |
| 125 | − | |
| 126 | − void mpool_create (char* memory, size_t size, _tMempool* pool); | |
| 127 | − | |
| 128 | − char* mpool_alloc(size_t size, _tMempool* pool); | |
| 129 | − char* mpool_calloc(size_t asize, _tMempool* pool); | |
| 130 | − | |
| 131 | − void mpool_free(char* ptr, _tMempool* pool); | |
| 132 | − | |
| 133 | − size_t mpool_get_size(_tMempool* pool); | |
| 134 | − size_t mpool_get_used(_tMempool* pool); | |
| 135 | − | |
| 136 | − void leaf_pool_init(char* memory, size_t size); | |
| 137 | − | |
| 138 | − char* leaf_alloc(size_t size); | |
| 139 | − char* leaf_calloc(size_t size); | |
| 140 | − | |
| 141 | − void leaf_free(char* ptr); | |
| 142 | − | |
| 143 | − size_t leaf_pool_get_size(void); | |
| 144 | − size_t leaf_pool_get_used(void); | |
| 145 | − | |
| 146 | − char* leaf_pool_get_pool(void); | |
| 147 | − | |
| 148 | − void leaf_mempool_overrun(void); | |
| 149 | − | |
| 150 | −#ifdef __cplusplus | |
| 151 | −} | |
| 152 | −#endif | |
| 153 | − | |
| 154 | −#endif // LEAF_MPOOL_H | |
| 155 | − | |
| 156 | −//============================================================================== | |
| 157 | − | |
| 158 | − | |
| 159 | − | |
| @@ -1,510 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-midi.h | |
| 4 | − Created: 30 Nov 2018 11:29:26am | |
| 5 | − Author: airship | |
| 6 | − | |
| 7 | − ==============================================================================*/ | |
| 8 | − | |
| 9 | −#ifndef LEAF_MIDI_H_INCLUDED | |
| 10 | −#define LEAF_MIDI_H_INCLUDED | |
| 11 | − | |
| 12 | −#ifdef __cplusplus | |
| 13 | −extern "C" { | |
| 14 | −#endif | |
| 15 | − | |
| 16 | − //============================================================================== | |
| 17 | − | |
| 18 | −#include "leaf-global.h" | |
| 19 | −#include "leaf-mempool.h" | |
| 20 | −#include "leaf-math.h" | |
| 21 | −#include "leaf-envelopes.h" | |
| 22 | − | |
| 23 | − /*! | |
| 24 | − * @internal | |
| 25 | − * Header. | |
| 26 | − * @include basic-oscillators.h | |
| 27 | − * @example basic-oscillators.c | |
| 28 | − * An example. | |
| 29 | − */ | |
| 30 | − | |
| 31 | − //============================================================================== | |
| 32 | − | |
| 33 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 34 | − | |
| 35 | − /*! | |
| 36 | − * @defgroup tstack tStack | |
| 37 | − * @ingroup midi | |
| 38 | − * @brief A basic stack of integers with a fixed max size of 128, used by tPoly to keep track of MIDI notes. | |
| 39 | − * @{ | |
| 40 | − */ | |
| 41 | − | |
| 42 | − // STACK implementation (fixed size) | |
| 43 | −#define STACK_SIZE 128 | |
| 44 | − typedef struct _tStack | |
| 45 | − { | |
| 46 | − int data[STACK_SIZE]; | |
| 47 | − uint16_t pos; | |
| 48 | − uint16_t size; | |
| 49 | − uint16_t capacity; | |
| 50 | − oBool ordered; | |
| 51 | − | |
| 52 | − } _tStack; | |
| 53 | − | |
| 54 | − typedef _tStack* tStack; | |
| 55 | − | |
| 56 | − //! Initialize a tStack to the default LEAF mempool. | |
| 57 | − /*! | |
| 58 | − @param stack A pointer to the tStack to be initialized. | |
| 59 | − */ | |
| 60 | − void tStack_init (tStack* const stack); | |
| 61 | − | |
| 62 | − | |
| 63 | − //! Free a tStack from the default LEAF mempool. | |
| 64 | − /*! | |
| 65 | − @param stack A pointer to the tStack to be freed. | |
| 66 | − */ | |
| 67 | − void tStack_free (tStack* const stack); | |
| 68 | − | |
| 69 | − | |
| 70 | − //! Initialize a tStack to a specified mempool. | |
| 71 | − /*! | |
| 72 | − @param stack A pointer to the tStack to be initialized. | |
| 73 | − @param pool A pointer to the tMempool to which the tStack should be initialized. | |
| 74 | − */ | |
| 75 | − void tStack_initToPool (tStack* const stack, tMempool* const pool); | |
| 76 | − | |
| 77 | − | |
| 78 | − //! Free a tStack from a specified mempool. | |
| 79 | − /*! | |
| 80 | − @param stack A pointer to the tStack to be freed. | |
| 81 | − @param pool A pointer to the tMempool from which the tStack should be freed. | |
| 82 | − */ | |
| 83 | − void tStack_freeFromPool (tStack* const stack, tMempool* const pool); | |
| 84 | − | |
| 85 | − //! Set the capacity of the stack. | |
| 86 | − /*! | |
| 87 | − @param stack A pointer to the relevant tStack. | |
| 88 | − @param cap The new capacity. | |
| 89 | − */ | |
| 90 | − void tStack_setCapacity (tStack* const stack, uint16_t cap); | |
| 91 | − | |
| 92 | − | |
| 93 | − //! Add a value to the stack only if that value is not already in the stack. | |
| 94 | − /*! | |
| 95 | − @param stack A pointer to the relevant tStack. | |
| 96 | − @param item The value to be added. | |
| 97 | − */ | |
| 98 | − int tStack_addIfNotAlreadyThere (tStack* const stack, uint16_t item); | |
| 99 | − | |
| 100 | − | |
| 101 | − //! Add a value to the stack. | |
| 102 | − /*! | |
| 103 | − @param stack A pointer to the relevant tStack. | |
| 104 | − @param item The value to be added. | |
| 105 | − */ | |
| 106 | − void tStack_add (tStack* const stack, uint16_t item); | |
| 107 | − | |
| 108 | − | |
| 109 | − //! Remove a single instance of a value from the stack. | |
| 110 | − /*! | |
| 111 | − @param stack A pointer to the relevant tStack. | |
| 112 | − @param item The value to be removed. | |
| 113 | − */ | |
| 114 | − int tStack_remove (tStack* const stack, uint16_t item); | |
| 115 | − | |
| 116 | − | |
| 117 | − //! Clear the stack. | |
| 118 | − /*! | |
| 119 | − @param stack A pointer to the relevant tStack. | |
| 120 | − */ | |
| 121 | − void tStack_clear (tStack* const stack); | |
| 122 | − | |
| 123 | − | |
| 124 | − //! Get the first value in the stack. | |
| 125 | − /*! | |
| 126 | − @param stack A pointer to the relevant tStack. | |
| 127 | − @return The first value in the stack. | |
| 128 | − */ | |
| 129 | − int tStack_first (tStack* const stack); | |
| 130 | − | |
| 131 | − | |
| 132 | − //! Get the current size of the stack. | |
| 133 | − /*! | |
| 134 | − @param stack A pointer to the relevant tStack. | |
| 135 | − @return The current size of the stack. | |
| 136 | − */ | |
| 137 | − int tStack_getSize (tStack* const stack); | |
| 138 | − | |
| 139 | − //! Check if the stack contains a value, and if it does, get the index of that value. | |
| 140 | − /*! | |
| 141 | − @param stack A pointer to the relevant tStack. | |
| 142 | − @param item The value to check against the stack. | |
| 143 | − @return The index of the value or -1 if the stack does not contain the value. | |
| 144 | − */ | |
| 145 | − int tStack_contains (tStack* const stack, uint16_t item); | |
| 146 | − | |
| 147 | − //! Get the next value in the stack, starting from the earliest added values. | |
| 148 | − /*! | |
| 149 | − @param stack A pointer to the relevant tStack. | |
| 150 | − @return The next value in the stack or -1 if there are no values in the stack. | |
| 151 | − */ | |
| 152 | − int tStack_next (tStack* const stack); | |
| 153 | − | |
| 154 | − //! Get the value at a given index of the stack. | |
| 155 | − /*! | |
| 156 | − @param stack A pointer to the relevant tStack. | |
| 157 | − @param index The index of the stack from which to get a value. | |
| 158 | − @return The value at the given index. | |
| 159 | − */ | |
| 160 | − int tStack_get (tStack* const stack, int index); | |
| 161 | − | |
| 162 | − /*! @} */ | |
| 163 | − | |
| 164 | − /*! | |
| 165 | − * @defgroup tpoly tPoly | |
| 166 | − * @ingroup midi | |
| 167 | − * @brief An object for polyphonic handling. | |
| 168 | − * @{ | |
| 169 | − */ | |
| 170 | − | |
| 171 | − /* tPoly */ | |
| 172 | − typedef struct _tPoly | |
| 173 | − { | |
| 174 | − tStack stack; | |
| 175 | − tStack orderStack; | |
| 176 | − | |
| 177 | − tRamp* ramps; | |
| 178 | − float* rampVals; | |
| 179 | − oBool* firstReceived; | |
| 180 | − float glideTime; | |
| 181 | − oBool pitchGlideIsActive; | |
| 182 | − | |
| 183 | − int numVoices; | |
| 184 | − int maxNumVoices; | |
| 185 | − | |
| 186 | − //int voices[POLY_NUM_MAX_VOICES][2]; | |
| 187 | − int** voices; | |
| 188 | − | |
| 189 | − int notes[128][2]; | |
| 190 | − | |
| 191 | − int CCs[128]; | |
| 192 | − | |
| 193 | − uint8_t CCsRaw[128]; | |
| 194 | − | |
| 195 | − int lastVoiceToChange; | |
| 196 | − | |
| 197 | − float pitchBend; | |
| 198 | − tRamp pitchBendRamp; | |
| 199 | − | |
| 200 | − int currentNote; | |
| 201 | − int currentVoice; | |
| 202 | − int currentVelocity; | |
| 203 | − int maxLength; | |
| 204 | − | |
| 205 | − } _tPoly; | |
| 206 | − | |
| 207 | − typedef _tPoly* tPoly; | |
| 208 | − | |
| 209 | − /* MPoly*/ | |
| 210 | − //! Initialize a tPoly to the default LEAF mempool. | |
| 211 | − /*! | |
| 212 | − @param poly A pointer to the tPoly to be initialized. | |
| 213 | − @param maxNumVoices The maximum number of voices this tPoly can handle at once. | |
| 214 | − */ | |
| 215 | − void tPoly_init (tPoly* const poly, int maxNumVoices); | |
| 216 | − | |
| 217 | − | |
| 218 | − //! Free a tPoly from the default LEAF mempool. | |
| 219 | − /*! | |
| 220 | − @param poly A pointer to the tPoly to be freed. | |
| 221 | − */ | |
| 222 | − void tPoly_free (tPoly* const poly); | |
| 223 | − | |
| 224 | − | |
| 225 | − //! Initialize a tPoly to a specified mempool. | |
| 226 | − /*! | |
| 227 | − @param poly A pointer to the tPoly to be initialized. | |
| 228 | − @param pool A pointer to the tMempool to which the tPoly should be initialized. | |
| 229 | − */ | |
| 230 | − void tPoly_initToPool (tPoly* const poly, int maxNumVoices, tMempool* const pool); | |
| 231 | − | |
| 232 | − | |
| 233 | − //! Free a tPoly from a specified mempool. | |
| 234 | − /*! | |
| 235 | − @param poly A pointer to the tPoly to be freed. | |
| 236 | − @param pool A pointer to the tMempool from which the tPoly should be freed. | |
| 237 | − */ | |
| 238 | − void tPoly_freeFromPool (tPoly* const poly, tMempool* const pool); | |
| 239 | − | |
| 240 | − //! Add a note with a given velocity to the poly handler. | |
| 241 | − /*! | |
| 242 | − @param poly A pointer to the relevant tPoly. | |
| 243 | − @param note The MIDI note number to add. | |
| 244 | − @param vel The MIDI velocity of the note to add. | |
| 245 | − @return The voice that will play the note. | |
| 246 | − */ | |
| 247 | − int tPoly_noteOn (tPoly* const poly, int note, uint8_t vel); | |
| 248 | − | |
| 249 | − | |
| 250 | − //! Remove a note from the poly handler. | |
| 251 | − /*! | |
| 252 | − @param poly A pointer to the relevant tPoly. | |
| 253 | − @param note The MIDI note number to remove. | |
| 254 | − @return The voice that was playing the removed note. | |
| 255 | − */ | |
| 256 | − int tPoly_noteOff (tPoly* const poly, uint8_t note); | |
| 257 | − | |
| 258 | − void tPoly_orderedAddToStack (tPoly* const poly, uint8_t note); | |
| 259 | − | |
| 260 | − | |
| 261 | − //! Set the number of voices available to play notes. | |
| 262 | − /*! | |
| 263 | − @param poly A pointer to the relevant tPoly. | |
| 264 | − @param numVoices The new number of available voices. Cannot be greater than the max number voices given in tPoly_init(). | |
| 265 | − */ | |
| 266 | − void tPoly_setNumVoices (tPoly* const poly, uint8_t numVoices); | |
| 267 | − | |
| 268 | − //! Set whether pitch glide over note changes in voices is active. | |
| 269 | − /*! | |
| 270 | − @param poly A pointer to the relevant tPoly. | |
| 271 | − @param isActive Whether pitch glide should be active or not. | |
| 272 | − */ | |
| 273 | − void tPoly_setPitchGlideActive (tPoly* const poly, oBool isActive); | |
| 274 | − | |
| 275 | − //! Set how long pitch glide over note changes in voices takes. | |
| 276 | − /*! | |
| 277 | − @param poly A pointer to the relevant tPoly. | |
| 278 | − @param t The time to glide in milliseconds. | |
| 279 | − */ | |
| 280 | − void tPoly_setPitchGlideTime (tPoly* const poly, float t); | |
| 281 | − | |
| 282 | − //! Set the amount of pitch bend | |
| 283 | − /*! | |
| 284 | − @param poly A pointer to the relevant tPoly. | |
| 285 | − @param pitchBend The new amount of pitch bend. | |
| 286 | − */ | |
| 287 | − void tPoly_setPitchBend (tPoly* const poly, float pitchBend); | |
| 288 | − void tPoly_setBendGlideTime (tPoly* const poly, float t); | |
| 289 | − void tPoly_setBendSamplesPerTick (tPoly* const poly, float t); | |
| 290 | − | |
| 291 | − | |
| 292 | − //! Execute all tick-rate changes in the poly handler's pitch, including glide and bend. | |
| 293 | − /*! | |
| 294 | − @param poly A pointer to the relevant tPoly. | |
| 295 | − */ | |
| 296 | − void tPoly_tickPitch (tPoly* const poly); | |
| 297 | − | |
| 298 | − | |
| 299 | − //! Execute the tick-rate change of the poly handler's pitch glide. | |
| 300 | − /*! | |
| 301 | − @param poly A pointer to the relevant tPoly. | |
| 302 | − */ | |
| 303 | − void tPoly_tickPitchGlide (tPoly* const poly); | |
| 304 | − | |
| 305 | − | |
| 306 | − //! Execute the tick-rate change of the poly handler's pitch bend. | |
| 307 | − /*! | |
| 308 | − @param poly A pointer to the relevant tPoly. | |
| 309 | − */ | |
| 310 | − void tPoly_tickPitchBend (tPoly* const poly); | |
| 311 | − | |
| 312 | − | |
| 313 | − //! Get the current number of voices available to play notes. | |
| 314 | − /*! | |
| 315 | − @param poly A pointer to the relevant tPoly. | |
| 316 | − @return The current number of voices available to play notes. | |
| 317 | − */ | |
| 318 | − int tPoly_getNumVoices (tPoly* const poly); | |
| 319 | − | |
| 320 | − //! Get the number of voices currently playing notes. | |
| 321 | − /*! | |
| 322 | − @param poly A pointer to the relevant tPoly. | |
| 323 | − @return The number of voices currently playing notes. | |
| 324 | − */ | |
| 325 | − int tPoly_getNumActiveVoices (tPoly* const poly); | |
| 326 | − | |
| 327 | − //! Get the current pitch of a given voice. | |
| 328 | − /*! | |
| 329 | − @param poly A pointer to the relevant tPoly. | |
| 330 | − @param voice The voice to get the pitch of. | |
| 331 | − @return The current pitch of the given voice as a fractional MIDI note number. | |
| 332 | − */ | |
| 333 | − float tPoly_getPitch (tPoly* const poly, uint8_t voice); | |
| 334 | − | |
| 335 | − | |
| 336 | − //! Get the current MIDI note number of a given voice. | |
| 337 | − /*! | |
| 338 | − @param poly A pointer to the relevant tPoly. | |
| 339 | − @param voice The voice to get the MIDI note number of. | |
| 340 | − @return The MIDI note number of the given voice. | |
| 341 | − */ | |
| 342 | − int tPoly_getKey (tPoly* const poly, uint8_t voice); | |
| 343 | − | |
| 344 | − | |
| 345 | − //! Get the current MIDI velocity of a given voice. | |
| 346 | − /*! | |
| 347 | − @param poly A pointer to the relevant tPoly. | |
| 348 | − @param voice The voice to get the MIDI velocity of. | |
| 349 | − @return The current MIDI velocity of the given voice. | |
| 350 | − */ | |
| 351 | − int tPoly_getVelocity (tPoly* const poly, uint8_t voice); | |
| 352 | − | |
| 353 | − | |
| 354 | − //! Get the current play state of a given voice. | |
| 355 | − /*! | |
| 356 | − @param poly A pointer to the relevant tPoly. | |
| 357 | − @param voice The voice to get the state of. | |
| 358 | − @return The current play state of the given voice. | |
| 359 | − */ | |
| 360 | − int tPoly_isOn (tPoly* const poly, uint8_t voice); | |
| 361 | − | |
| 362 | − /*! @} */ | |
| 363 | − | |
| 364 | − //============================================================================== | |
| 365 | − | |
| 366 | − | |
| 367 | − /* tPoly */ | |
| 368 | − typedef struct _tSimplePoly | |
| 369 | − { | |
| 370 | − tStack stack; | |
| 371 | − | |
| 372 | − int numVoices; | |
| 373 | − int maxNumVoices; | |
| 374 | − int** voices; | |
| 375 | − int stealing_on; | |
| 376 | − int recover_stolen; | |
| 377 | − | |
| 378 | − int notes[128][2]; | |
| 379 | − } _tSimplePoly; | |
| 380 | − | |
| 381 | − typedef _tSimplePoly* tSimplePoly; | |
| 382 | − | |
| 383 | − //! Initialize a tPoly to the default LEAF mempool. | |
| 384 | − /*! | |
| 385 | − @param poly A pointer to the tPoly to be initialized. | |
| 386 | − @param maxNumVoices The maximum number of voices this tPoly can handle at once. | |
| 387 | − */ | |
| 388 | − void tSimplePoly_init (tSimplePoly* const poly, int maxNumVoices); | |
| 389 | − | |
| 390 | − | |
| 391 | − //! Free a tPoly from the default LEAF mempool. | |
| 392 | − /*! | |
| 393 | − @param poly A pointer to the tPoly to be freed. | |
| 394 | − */ | |
| 395 | − void tSimplePoly_free (tSimplePoly* const poly); | |
| 396 | − | |
| 397 | − | |
| 398 | − //! Initialize a tPoly to a specified mempool. | |
| 399 | − /*! | |
| 400 | − @param poly A pointer to the tPoly to be initialized. | |
| 401 | − @param pool A pointer to the tMempool to which the tPoly should be initialized. | |
| 402 | − */ | |
| 403 | − void tSimplePoly_initToPool (tSimplePoly* const poly, int maxNumVoices, tMempool* const pool); | |
| 404 | − | |
| 405 | − | |
| 406 | − //! Free a tPoly from a specified mempool. | |
| 407 | − /*! | |
| 408 | − @param poly A pointer to the tPoly to be freed. | |
| 409 | − @param pool A pointer to the tMempool from which the tPoly should be freed. | |
| 410 | − */ | |
| 411 | − void tSimplePoly_freeFromPool (tSimplePoly* const poly, tMempool* const pool); | |
| 412 | − | |
| 413 | − //! Add a note with a given velocity to the poly handler. | |
| 414 | − /*! | |
| 415 | − @param poly A pointer to the relevant tPoly. | |
| 416 | − @param note The MIDI note number to add. | |
| 417 | − @param vel The MIDI velocity of the note to add. | |
| 418 | − @return The voice that will play the note. | |
| 419 | − */ | |
| 420 | − int tSimplePoly_noteOn (tSimplePoly* const poly, int note, uint8_t vel); | |
| 421 | − | |
| 422 | − | |
| 423 | − //! Remove a note from the poly handler. | |
| 424 | − /*! | |
| 425 | − @param poly A pointer to the relevant tPoly. | |
| 426 | − @param note The MIDI note number to remove. | |
| 427 | − @return The voice that was playing the removed note. | |
| 428 | − */ | |
| 429 | − int tSimplePoly_noteOff (tSimplePoly* const poly, uint8_t note); | |
| 430 | − | |
| 431 | − | |
| 432 | − | |
| 433 | − void tSimplePoly_deactivateVoice(tSimplePoly* const polyh, uint8_t voice); | |
| 434 | − | |
| 435 | − int tSimplePoly_markPendingNoteOff(tSimplePoly* const polyh, uint8_t note); | |
| 436 | − | |
| 437 | − | |
| 438 | − //find if there is a voice with that note -- useful for note offs where you want to wait to remove it from the poly until the release phase of the envelope is finished | |
| 439 | − int tSimplePoly_findVoiceAssignedToNote(tSimplePoly* const polyh, uint8_t note); | |
| 440 | − | |
| 441 | − //! Set the number of voices available to play notes. | |
| 442 | − /*! | |
| 443 | − @param poly A pointer to the relevant tPoly. | |
| 444 | − @param numVoices The new number of available voices. Cannot be greater than the max number voices given in tPoly_init(). | |
| 445 | − */ | |
| 446 | − void tSimplePoly_setNumVoices (tSimplePoly* const poly, uint8_t numVoices); | |
| 447 | − | |
| 448 | − //! Set whether pitch glide over note changes in voices is active. | |
| 449 | − /*! | |
| 450 | − @param poly A pointer to the relevant tPoly. | |
| 451 | − @param isActive Whether pitch glide should be active or not. | |
| 452 | − */ | |
| 453 | − | |
| 454 | − //! Get the current number of voices available to play notes. | |
| 455 | − /*! | |
| 456 | − @param poly A pointer to the relevant tPoly. | |
| 457 | − @return The current number of voices available to play notes. | |
| 458 | − */ | |
| 459 | − int tSimplePoly_getNumVoices (tSimplePoly* const poly); | |
| 460 | − | |
| 461 | − //! Get the number of voices currently playing notes. | |
| 462 | − /*! | |
| 463 | − @param poly A pointer to the relevant tPoly. | |
| 464 | − @return The number of voices currently playing notes. | |
| 465 | − */ | |
| 466 | − int tSimplePoly_getNumActiveVoices (tSimplePoly* const poly); | |
| 467 | − | |
| 468 | − //! Get the current MIDI note number of a given voice. | |
| 469 | − /*! | |
| 470 | − @param poly A pointer to the relevant tPoly. | |
| 471 | − @param voice The voice to get the MIDI note number of. | |
| 472 | − @return The MIDI note number of the given voice. | |
| 473 | − */ | |
| 474 | − | |
| 475 | − int tSimplePoly_getPitch (tSimplePoly* const poly, uint8_t voice); | |
| 476 | − | |
| 477 | − | |
| 478 | − //this one returns negative one if the voice is inactive | |
| 479 | − int tSimplePoly_getPitchAndCheckActive(tSimplePoly* const polyh, uint8_t voice); | |
| 480 | − | |
| 481 | − | |
| 482 | − //! Get the current MIDI velocity of a given voice. | |
| 483 | − /*! | |
| 484 | − @param poly A pointer to the relevant tPoly. | |
| 485 | − @param voice The voice to get the MIDI velocity of. | |
| 486 | − @return The current MIDI velocity of the given voice. | |
| 487 | − */ | |
| 488 | − int tSimplePoly_getVelocity (tSimplePoly* const poly, uint8_t voice); | |
| 489 | − | |
| 490 | − | |
| 491 | − //! Get the current play state of a given voice. | |
| 492 | − /*! | |
| 493 | − @param poly A pointer to the relevant tPoly. | |
| 494 | − @param voice The voice to get the state of. | |
| 495 | − @return The current play state of the given voice. | |
| 496 | − */ | |
| 497 | − int tSimplePoly_isOn (tSimplePoly* const poly, uint8_t voice); | |
| 498 | − | |
| 499 | − /*! @} */ | |
| 500 | − //============================================================================== | |
| 501 | − | |
| 502 | −#ifdef __cplusplus | |
| 503 | −} | |
| 504 | −#endif | |
| 505 | − | |
| 506 | −#endif // LEAF_MIDI_H_INCLUDED | |
| 507 | − | |
| 508 | −//============================================================================== | |
| 509 | − | |
| 510 | − | |
| @@ -1,1143 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − leaf-oscillators.h | |
| 3 | − Created: 20 Jan 2017 12:00:58pm | |
| 4 | − Author: Michael R Mulshine | |
| 5 | − ==============================================================================*/ | |
| 6 | − | |
| 7 | −#ifndef LEAF_OSCILLATORS_H_INCLUDED | |
| 8 | −#define LEAF_OSCILLATORS_H_INCLUDED | |
| 9 | − | |
| 10 | −#ifdef __cplusplus | |
| 11 | −extern "C" { | |
| 12 | −#endif | |
| 13 | − | |
| 14 | − //============================================================================== | |
| 15 | − | |
| 16 | −#include "leaf-math.h" | |
| 17 | −#include "leaf-mempool.h" | |
| 18 | −#include "leaf-tables.h" | |
| 19 | −#include "leaf-filters.h" | |
| 20 | − | |
| 21 | − /*! | |
| 22 | − * Header. | |
| 23 | − * @include basic-oscillators.h | |
| 24 | − * @example basic-oscillators.c | |
| 25 | − * An example. | |
| 26 | − */ | |
| 27 | − | |
| 28 | − //============================================================================== | |
| 29 | − | |
| 30 | − typedef struct _tCycle | |
| 31 | − { | |
| 32 | − // Underlying phasor | |
| 33 | − float phase; | |
| 34 | − float inc,freq; | |
| 35 | − } _tCycle; | |
| 36 | − | |
| 37 | − typedef _tCycle* tCycle; | |
| 38 | − | |
| 39 | − /*! | |
| 40 | − * @defgroup tcycle tCycle | |
| 41 | − * @ingroup oscillators | |
| 42 | − * @brief A cycle/sine waveform oscillator. Uses wavetable synthesis. | |
| 43 | − * @{ | |
| 44 | − */ | |
| 45 | − | |
| 46 | − //! Initialize a tCycle to the default LEAF mempool. | |
| 47 | − /*! | |
| 48 | − @param osc A pointer to the tCycle to be initialized. | |
| 49 | − */ | |
| 50 | − void tCycle_init (tCycle* const osc); | |
| 51 | − | |
| 52 | − | |
| 53 | − //! Free a tCycle from the default LEAF mempool. | |
| 54 | − /*! | |
| 55 | − @param osc A pointer to the tCycle to be freed. | |
| 56 | − */ | |
| 57 | − void tCycle_free (tCycle* const osc); | |
| 58 | − | |
| 59 | − | |
| 60 | − //! Initialize a tCycle to a specified mempool. | |
| 61 | − /*! | |
| 62 | − @param osc A pointer to the tCycle to be initialized. | |
| 63 | − @param pool A pointer to the tMempool to which the tCycle should be initialized. | |
| 64 | − */ | |
| 65 | − void tCycle_initToPool (tCycle* const osc, tMempool* const pool); | |
| 66 | − | |
| 67 | − | |
| 68 | − //! Free a tCycle from a specified mempool. | |
| 69 | − /*! | |
| 70 | − @param osc A pointer to the tCycle to be freed. | |
| 71 | − @param pool A pointer to the tMempool from which the tCycle should be freed. | |
| 72 | − */ | |
| 73 | − void tCycle_freeFromPool (tCycle* const osc, tMempool* const pool); | |
| 74 | − | |
| 75 | − | |
| 76 | − //! Tick a tCycle oscillator. | |
| 77 | − /*! | |
| 78 | − @param osc A pointer to the relevant tCycle. | |
| 79 | − @return The ticked sample as a float from -1 to 1. | |
| 80 | − */ | |
| 81 | − float tCycle_tick (tCycle* const osc); | |
| 82 | − | |
| 83 | − | |
| 84 | − //! Set the frequency of a tCycle oscillator. | |
| 85 | − /*! | |
| 86 | − @param osc A pointer to the relevant tCycle. | |
| 87 | − @param freq The frequency to set the oscillator to. | |
| 88 | − */ | |
| 89 | − void tCycle_setFreq (tCycle* const osc, float freq); | |
| 90 | − | |
| 91 | − /*! @} */ | |
| 92 | − | |
| 93 | − //============================================================================== | |
| 94 | − | |
| 95 | − /* tTriangle: Anti-aliased Triangle waveform using wavetable interpolation. Wavetables constructed from sine components. */ | |
| 96 | − typedef struct _tTriangle | |
| 97 | − { | |
| 98 | − // Underlying phasor | |
| 99 | − float phase; | |
| 100 | − float inc,freq; | |
| 101 | − int oct; | |
| 102 | − float w; | |
| 103 | − } _tTriangle; | |
| 104 | − | |
| 105 | − typedef _tTriangle* tTriangle; | |
| 106 | − | |
| 107 | − /*! | |
| 108 | − * @defgroup ttriangle tTriangle | |
| 109 | − * @ingroup oscillators | |
| 110 | − * @brief An anti-aliased triangle waveform oscillator. Uses wavetable synthesis. | |
| 111 | − * @{ | |
| 112 | − */ | |
| 113 | − | |
| 114 | − //! Initialize a tTriangle to the default LEAF mempool. | |
| 115 | − /*! | |
| 116 | − @param osc A pointer to the tTriangle to be initialized. | |
| 117 | − */ | |
| 118 | − void tTriangle_init (tTriangle* const osc); | |
| 119 | − | |
| 120 | − | |
| 121 | − //! Free a tTriangle from the default LEAF mempool. | |
| 122 | − /*! | |
| 123 | − @param osc A pointer to the tTriangle to be freed. | |
| 124 | − */ | |
| 125 | − void tTriangle_free (tTriangle* const osc); | |
| 126 | − | |
| 127 | − | |
| 128 | − //! Initialize a tTriangle to a specified mempool. | |
| 129 | − /*! | |
| 130 | − @param osc A pointer to the tTriangle to be initialized. | |
| 131 | − @param pool A pointer to the tMempool to which the tTriangle should be initialized. | |
| 132 | − */ | |
| 133 | − void tTriangle_initToPool (tTriangle* const osc, tMempool* const pool); | |
| 134 | − | |
| 135 | − | |
| 136 | − //! Free a tTriangle from a specified mempool. | |
| 137 | − /*! | |
| 138 | − @param osc A pointer to the tTriangle to be freed. | |
| 139 | − @param pool A pointer to the tMempool from which the tTriangle should be freed. | |
| 140 | − */ | |
| 141 | − void tTriangle_freeFromPool (tTriangle* const osc, tMempool* const pool); | |
| 142 | − | |
| 143 | − | |
| 144 | − //! Tick a tTriangle oscillator. | |
| 145 | − /*! | |
| 146 | − @param osc A pointer to the relevant tTriangle. | |
| 147 | − @return The ticked sample as a float from -1 to 1. | |
| 148 | − */ | |
| 149 | − float tTriangle_tick (tTriangle* const osc); | |
| 150 | − | |
| 151 | − | |
| 152 | − //! Set the frequency of a tTriangle oscillator. | |
| 153 | − /*! | |
| 154 | − @param osc A pointer to the relevant tTriangle. | |
| 155 | − @param freq The frequency to set the oscillator to. | |
| 156 | − */ | |
| 157 | − void tTriangle_setFreq (tTriangle* const osc, float freq); | |
| 158 | − | |
| 159 | − /*! @} */ | |
| 160 | − | |
| 161 | − //============================================================================== | |
| 162 | − | |
| 163 | − /* tSquare: Anti-aliased Square waveform using wavetable interpolation. Wavetables constructed from sine components. */ | |
| 164 | − typedef struct _tSquare | |
| 165 | − { | |
| 166 | − // Underlying phasor | |
| 167 | − float phase; | |
| 168 | − float inc,freq; | |
| 169 | − int oct; | |
| 170 | − float w; | |
| 171 | − } _tSquare; | |
| 172 | − | |
| 173 | − typedef _tSquare* tSquare; | |
| 174 | − | |
| 175 | − /*! | |
| 176 | − * @defgroup tsquare tSquare | |
| 177 | − * @ingroup oscillators | |
| 178 | − * @brief An anti-aliased square waveform oscillator. Uses wavetable synthesis. | |
| 179 | − * @{ | |
| 180 | − */ | |
| 181 | − | |
| 182 | − //! Initialize a tSquare to the default LEAF mempool. | |
| 183 | − /*! | |
| 184 | − @param osc A pointer to the tSquare to be initialized. | |
| 185 | − */ | |
| 186 | − void tSquare_init (tSquare* const osc); | |
| 187 | − | |
| 188 | − | |
| 189 | − //! Free a tSquare from the default LEAF mempool. | |
| 190 | − /*! | |
| 191 | − @param osc A pointer to the tSquare to be freed. | |
| 192 | − */ | |
| 193 | − void tSquare_free (tSquare* const osc); | |
| 194 | − | |
| 195 | − | |
| 196 | − //! Initialize a tSquare to a specified mempool. | |
| 197 | − /*! | |
| 198 | − @param osc A pointer to the tSquare to be initialized. | |
| 199 | − @param pool A pointer to the tMempool to which the tSquare should be initialized. | |
| 200 | − */ | |
| 201 | − void tSquare_initToPool (tSquare* const osc, tMempool* const); | |
| 202 | − | |
| 203 | − | |
| 204 | − //! Free a tSquare from a specified mempool. | |
| 205 | − /*! | |
| 206 | − @param osc A pointer to the tSquare to be freed. | |
| 207 | − @param pool A pointer to the tMempool from which the tSquare should be freed. | |
| 208 | − */ | |
| 209 | − void tSquare_freeFromPool(tSquare* const osc, tMempool* const); | |
| 210 | − | |
| 211 | − | |
| 212 | − //! Tick a tSquare oscillator. | |
| 213 | − /*! | |
| 214 | − @param osc A pointer to the relevant tSquare. | |
| 215 | − @return The ticked sample as a float from -1 to 1. | |
| 216 | − */ | |
| 217 | − float tSquare_tick (tSquare* const osc); | |
| 218 | − | |
| 219 | − | |
| 220 | − //! Set the frequency of a tSquare oscillator. | |
| 221 | − /*! | |
| 222 | − @param osc A pointer to the relevant tSquare. | |
| 223 | − @param freq The frequency to set the oscillator to. | |
| 224 | − */ | |
| 225 | − void tSquare_setFreq (tSquare* const osc, float freq); | |
| 226 | − | |
| 227 | − /*! @} */ | |
| 228 | − | |
| 229 | − //============================================================================== | |
| 230 | − | |
| 231 | − /* tSawtooth: Anti-aliased Sawtooth waveform using wavetable interpolation. Wavetables constructed from sine components. */ | |
| 232 | − typedef struct _tSawtooth | |
| 233 | − { | |
| 234 | − // Underlying phasor | |
| 235 | − float phase; | |
| 236 | − float inc,freq; | |
| 237 | − int oct; | |
| 238 | − float w; | |
| 239 | − } _tSawtooth; | |
| 240 | − | |
| 241 | − typedef _tSawtooth* tSawtooth; | |
| 242 | − | |
| 243 | − /*! | |
| 244 | − * @defgroup tsawtooth tSawtooth | |
| 245 | − * @ingroup oscillators | |
| 246 | − * @brief An anti-aliased sawtooth waveform oscillator. Uses wavetable synthesis. | |
| 247 | − * @{ | |
| 248 | − */ | |
| 249 | − | |
| 250 | − //! Initialize a tSawtooth to the default LEAF mempool. | |
| 251 | − /*! | |
| 252 | − @param osc A pointer to the tSawtooth to be initialized. | |
| 253 | − */ | |
| 254 | − void tSawtooth_init (tSawtooth* const osc); | |
| 255 | − | |
| 256 | − | |
| 257 | − //! Free a tSawtooth from the default LEAF mempool. | |
| 258 | − /*! | |
| 259 | − @param osc A pointer to the tSawtooth to be freed. | |
| 260 | − */ | |
| 261 | − void tSawtooth_free (tSawtooth* const osc); | |
| 262 | − | |
| 263 | − | |
| 264 | − //! Initialize a tSawtooth to a specified mempool. | |
| 265 | − /*! | |
| 266 | − @param osc A pointer to the tSawtooth to be initialized. | |
| 267 | − @param pool A pointer to the tMempool to which the tSawtooth should be initialized. | |
| 268 | − */ | |
| 269 | − void tSawtooth_initToPool (tSawtooth* const osc, tMempool* const pool); | |
| 270 | − | |
| 271 | − | |
| 272 | − //! Free a tSawtooth from a specified mempool. | |
| 273 | − /*! | |
| 274 | − @param osc A pointer to the tSawtooth to be freed. | |
| 275 | − @param pool A pointer to the tMempool from which the tSawtooth should be freed. | |
| 276 | − */ | |
| 277 | − void tSawtooth_freeFromPool (tSawtooth* const osc, tMempool* const pool); | |
| 278 | − | |
| 279 | − | |
| 280 | − //! Tick a tSawtooth oscillator. | |
| 281 | − /*! | |
| 282 | − @param osc A pointer to the relevant tSawtooth. | |
| 283 | − @return The ticked sample as a float from -1 to 1. | |
| 284 | − */ | |
| 285 | − float tSawtooth_tick (tSawtooth* const osc); | |
| 286 | − | |
| 287 | − | |
| 288 | − //! Set the frequency of a tSawtooth oscillator. | |
| 289 | − /*! | |
| 290 | − @param osc A pointer to the relevant tSawtooth. | |
| 291 | − @param freq The frequency to set the oscillator to. | |
| 292 | − */ | |
| 293 | − void tSawtooth_setFreq (tSawtooth* const osc, float freq); | |
| 294 | − | |
| 295 | − /*! @} */ | |
| 296 | − | |
| 297 | − //============================================================================== | |
| 298 | − | |
| 299 | − typedef struct _tSine | |
| 300 | − { | |
| 301 | − float* sine; | |
| 302 | − int size; | |
| 303 | − float phase; | |
| 304 | − float inc,freq; | |
| 305 | − } _tSine; | |
| 306 | − | |
| 307 | − typedef _tSine* tSine; | |
| 308 | − | |
| 309 | − /*! | |
| 310 | − * @defgroup tsine tSine | |
| 311 | − * @ingroup oscillators | |
| 312 | − * @brief A cycle/sine waveform oscillator. | |
| 313 | − * @{ | |
| 314 | − */ | |
| 315 | − | |
| 316 | − //! Initialize a tSine to the default LEAF mempool. | |
| 317 | − /*! | |
| 318 | − @param osc A pointer to the tSine to be initialized. | |
| 319 | − */ | |
| 320 | − void tSine_init (tSine* const osc, int size); | |
| 321 | − | |
| 322 | − | |
| 323 | − //! Free a tSine from the default LEAF mempool. | |
| 324 | − /*! | |
| 325 | − @param osc A pointer to the tSine to be freed. | |
| 326 | − */ | |
| 327 | − void tSine_free (tSine* const osc); | |
| 328 | − | |
| 329 | − | |
| 330 | − //! Initialize a tSine to a specified mempool. | |
| 331 | − /*! | |
| 332 | − @param osc A pointer to the tSine to be initialized. | |
| 333 | − @param pool A pointer to the tMempool to which the tSine should be initialized. | |
| 334 | − */ | |
| 335 | − void tSine_initToPool (tSine* const osc, int size, tMempool* const pool); | |
| 336 | − | |
| 337 | − | |
| 338 | − //! Free a tSine from a specified mempool. | |
| 339 | − /*! | |
| 340 | − @param osc A pointer to the tSine to be freed. | |
| 341 | − @param pool A pointer to the tMempool from which the tSine should be freed. | |
| 342 | − */ | |
| 343 | − void tSine_freeFromPool (tSine* const osc, tMempool* const pool); | |
| 344 | − | |
| 345 | − | |
| 346 | − //! Tick a tSine oscillator. | |
| 347 | − /*! | |
| 348 | − @param osc A pointer to the relevant tSine. | |
| 349 | − @return The ticked sample as a float from -1 to 1. | |
| 350 | − */ | |
| 351 | − float tSine_tick (tSine* const osc); | |
| 352 | − | |
| 353 | − | |
| 354 | − //! Set the frequency of a tSine oscillator. | |
| 355 | − /*! | |
| 356 | − @param osc A pointer to the relevant tSine. | |
| 357 | − @param freq The frequency to set the oscillator to. | |
| 358 | − */ | |
| 359 | − void tSine_setFreq (tSine* const osc, float freq); | |
| 360 | − | |
| 361 | − /*! @} */ | |
| 362 | − | |
| 363 | − //============================================================================== | |
| 364 | − | |
| 365 | − /* tTri: Anti-aliased Triangle waveform using wavetable interpolation. */ | |
| 366 | − typedef struct _tTri | |
| 367 | − { | |
| 368 | − float phase; | |
| 369 | − float inc,freq; | |
| 370 | − float skew; | |
| 371 | − float lastOut; | |
| 372 | − } _tTri; | |
| 373 | − | |
| 374 | − typedef _tTri* tTri; | |
| 375 | − | |
| 376 | − /*! | |
| 377 | − * @defgroup tTri tTri | |
| 378 | − * @ingroup oscillators | |
| 379 | − * @brief An anti-aliased triangle waveform oscillator. | |
| 380 | − * @{ | |
| 381 | − */ | |
| 382 | − | |
| 383 | − //! Initialize a tTri to the default LEAF mempool. | |
| 384 | − /*! | |
| 385 | − @param osc A pointer to the tTri to be initialized. | |
| 386 | − */ | |
| 387 | − void tTri_init (tTri* const osc); | |
| 388 | − | |
| 389 | − | |
| 390 | − //! Free a tTri from the default LEAF mempool. | |
| 391 | − /*! | |
| 392 | − @param osc A pointer to the tTri to be freed. | |
| 393 | − */ | |
| 394 | − void tTri_free (tTri* const osc); | |
| 395 | − | |
| 396 | − | |
| 397 | − //! Initialize a tTri to a specified mempool. | |
| 398 | − /*! | |
| 399 | − @param osc A pointer to the tTri to be initialized. | |
| 400 | − @param pool A pointer to the tMempool to which the tTri should be initialized. | |
| 401 | − */ | |
| 402 | − void tTri_initToPool (tTri* const osc, tMempool* const pool); | |
| 403 | − | |
| 404 | − | |
| 405 | − //! Free a tTri from a specified mempool. | |
| 406 | − /*! | |
| 407 | − @param osc A pointer to the tTri to be freed. | |
| 408 | − @param pool A pointer to the tMempool from which the tTri should be freed. | |
| 409 | − */ | |
| 410 | − void tTri_freeFromPool (tTri* const osc, tMempool* const pool); | |
| 411 | − | |
| 412 | − | |
| 413 | − //! Tick a tTri oscillator. | |
| 414 | − /*! | |
| 415 | − @param osc A pointer to the relevant tTri. | |
| 416 | − @return The ticked sample as a float from -1 to 1. | |
| 417 | − */ | |
| 418 | − float tTri_tick (tTri* const osc); | |
| 419 | − | |
| 420 | − | |
| 421 | − //! Set the frequency of a tTri oscillator. | |
| 422 | − /*! | |
| 423 | − @param osc A pointer to the relevant tTriangle. | |
| 424 | − @param freq The frequency to set the oscillator to. | |
| 425 | − */ | |
| 426 | − void tTri_setFreq (tTri* const osc, float freq); | |
| 427 | − | |
| 428 | − void tTri_setSkew (tTri* const osc, float skew); | |
| 429 | − | |
| 430 | − /*! @} */ | |
| 431 | − | |
| 432 | − //============================================================================== | |
| 433 | − | |
| 434 | − /* tPulse: Anti-aliased Square waveform. */ | |
| 435 | − typedef struct _tPulse | |
| 436 | − { | |
| 437 | − float phase; | |
| 438 | − float inc,freq; | |
| 439 | − float width; | |
| 440 | − } _tPulse; | |
| 441 | − | |
| 442 | − typedef _tPulse* tPulse; | |
| 443 | − | |
| 444 | − /*! | |
| 445 | − * @defgroup tPulse tPulse | |
| 446 | − * @ingroup oscillators | |
| 447 | − * @brief An anti-aliased pulse waveform oscillator with changeable pulse width. | |
| 448 | − * @{ | |
| 449 | − */ | |
| 450 | − | |
| 451 | − //! Initialize a tPulse to the default LEAF mempool. | |
| 452 | − /*! | |
| 453 | − @param osc A pointer to the tPulse to be initialized. | |
| 454 | − */ | |
| 455 | − void tPulse_init (tPulse* const osc); | |
| 456 | − | |
| 457 | − | |
| 458 | − //! Free a tPulse from the default LEAF mempool. | |
| 459 | − /*! | |
| 460 | − @param osc A pointer to the tPulse to be freed. | |
| 461 | − */ | |
| 462 | − void tPulse_free (tPulse* const osc); | |
| 463 | − | |
| 464 | − | |
| 465 | − //! Initialize a tPulse to a specified mempool. | |
| 466 | − /*! | |
| 467 | − @param osc A pointer to the tPulse to be initialized. | |
| 468 | − @param pool A pointer to the tMempool to which the tPulse should be initialized. | |
| 469 | − */ | |
| 470 | − void tPulse_initToPool (tPulse* const osc, tMempool* const); | |
| 471 | − | |
| 472 | − | |
| 473 | − //! Free a tPulse from a specified mempool. | |
| 474 | − /*! | |
| 475 | − @param osc A pointer to the tPulse to be freed. | |
| 476 | − @param pool A pointer to the tMempool from which the tPulse should be freed. | |
| 477 | − */ | |
| 478 | − void tPulse_freeFromPool(tPulse* const osc, tMempool* const); | |
| 479 | − | |
| 480 | − | |
| 481 | − //! Tick a tPulse oscillator. | |
| 482 | − /*! | |
| 483 | − @param osc A pointer to the relevant tPulse. | |
| 484 | − @return The ticked sample as a float from -1 to 1. | |
| 485 | − */ | |
| 486 | − float tPulse_tick (tPulse* const osc); | |
| 487 | − | |
| 488 | − | |
| 489 | − //! Set the frequency of a tPulse oscillator. | |
| 490 | − /*! | |
| 491 | − @param osc A pointer to the relevant tPulse. | |
| 492 | − @param freq The frequency to set the oscillator to. | |
| 493 | − */ | |
| 494 | − void tPulse_setFreq (tPulse* const osc, float freq); | |
| 495 | − | |
| 496 | − void tPulse_setWidth (tPulse* const osc, float width); | |
| 497 | − | |
| 498 | − /*! @} */ | |
| 499 | − | |
| 500 | − //============================================================================== | |
| 501 | − | |
| 502 | − /* tSawtooth: Anti-aliased Sawtooth waveform. */ | |
| 503 | − typedef struct _tSaw | |
| 504 | − { | |
| 505 | − float phase; | |
| 506 | − float inc,freq; | |
| 507 | − } _tSaw; | |
| 508 | − | |
| 509 | − typedef _tSaw* tSaw; | |
| 510 | − | |
| 511 | − /*! | |
| 512 | − * @defgroup tsaw tSaw | |
| 513 | − * @ingroup oscillators | |
| 514 | − * @brief An anti-aliased sawtooth waveform oscillator. Uses wavetable synthesis. | |
| 515 | − * @{ | |
| 516 | − */ | |
| 517 | − | |
| 518 | − //! Initialize a tSaw to the default LEAF mempool. | |
| 519 | − /*! | |
| 520 | − @param osc A pointer to the tSaw to be initialized. | |
| 521 | − */ | |
| 522 | − void tSaw_init (tSaw* const osc); | |
| 523 | − | |
| 524 | − | |
| 525 | − //! Free a tSaw from the default LEAF mempool. | |
| 526 | − /*! | |
| 527 | − @param osc A pointer to the tSaw to be freed. | |
| 528 | − */ | |
| 529 | − void tSaw_free (tSaw* const osc); | |
| 530 | − | |
| 531 | − | |
| 532 | − //! Initialize a tSaw to a specified mempool. | |
| 533 | − /*! | |
| 534 | − @param osc A pointer to the tSaw to be initialized. | |
| 535 | − @param pool A pointer to the tMempool to which the tSaw should be initialized. | |
| 536 | − */ | |
| 537 | − void tSaw_initToPool (tSaw* const osc, tMempool* const pool); | |
| 538 | − | |
| 539 | − | |
| 540 | − //! Free a tSaw from a specified mempool. | |
| 541 | − /*! | |
| 542 | − @param osc A pointer to the tSaw to be freed. | |
| 543 | − @param pool A pointer to the tMempool from which the tSaw should be freed. | |
| 544 | − */ | |
| 545 | − void tSaw_freeFromPool (tSaw* const osc, tMempool* const pool); | |
| 546 | − | |
| 547 | − | |
| 548 | − //! Tick a tSaw oscillator. | |
| 549 | − /*! | |
| 550 | − @param osc A pointer to the relevant tSaw. | |
| 551 | − @return The ticked sample as a float from -1 to 1. | |
| 552 | − */ | |
| 553 | − float tSaw_tick (tSaw* const osc); | |
| 554 | − | |
| 555 | − | |
| 556 | − //! Set the frequency of a tSaw oscillator. | |
| 557 | − /*! | |
| 558 | − @param osc A pointer to the relevant tSaw. | |
| 559 | − @param freq The frequency to set the oscillator to. | |
| 560 | − */ | |
| 561 | − void tSaw_setFreq (tSaw* const osc, float freq); | |
| 562 | − | |
| 563 | − /*! @} */ | |
| 564 | − | |
| 565 | − //============================================================================== | |
| 566 | − | |
| 567 | − /* tPhasor: Aliasing phasor [0.0, 1.0) */ | |
| 568 | − typedef struct _tPhasor | |
| 569 | − { | |
| 570 | − float phase; | |
| 571 | − float inc,freq; | |
| 572 | − uint8_t phaseDidReset; | |
| 573 | − | |
| 574 | − } _tPhasor; | |
| 575 | − | |
| 576 | − typedef _tPhasor* tPhasor; | |
| 577 | − | |
| 578 | − /*! | |
| 579 | − * @defgroup tphasor Phasor | |
| 580 | − * @ingroup oscillators | |
| 581 | − * @brief An aliasing phasor. | |
| 582 | − * @{ | |
| 583 | − */ | |
| 584 | − | |
| 585 | − //! Initialize a tPhasor to the default LEAF mempool. | |
| 586 | − /*! | |
| 587 | − @param osc A pointer to the tPhasor to be initialized. | |
| 588 | − */ | |
| 589 | − void tPhasor_init (tPhasor* const osc); | |
| 590 | − | |
| 591 | − | |
| 592 | − //! Free a tPhasor from the default LEAF mempool. | |
| 593 | − /*! | |
| 594 | − @param osc A pointer to the tPhasor to be freed. | |
| 595 | − */ | |
| 596 | − void tPhasor_free (tPhasor* const osc); | |
| 597 | − | |
| 598 | − | |
| 599 | − //! Initialize a tPhasor to a specified mempool. | |
| 600 | − /*! | |
| 601 | − @param osc A pointer to the tPhasor to be initialized. | |
| 602 | − @param pool A pointer to the tMempool to which the tPhasor should be initialized. | |
| 603 | − */ | |
| 604 | − void tPhasor_initToPool (tPhasor* const osc, tMempool* const); | |
| 605 | − | |
| 606 | − | |
| 607 | − //! Free a tPhasor from a specified mempool. | |
| 608 | − /*! | |
| 609 | − @param osc A pointer to the tPhasor to be freed. | |
| 610 | − @param pool A pointer to the tMempool from which the tPhasor should be freed. | |
| 611 | − */ | |
| 612 | − void tPhasor_freeFromPool(tPhasor* const osc, tMempool* const); | |
| 613 | − | |
| 614 | − | |
| 615 | − //! Tick a tPhasor oscillator. | |
| 616 | − /*! | |
| 617 | − @param osc A pointer to the relevant tPhasor. | |
| 618 | − @return The ticked sample as a float from 0 to 1. | |
| 619 | − */ | |
| 620 | − float tPhasor_tick (tPhasor* const osc); | |
| 621 | − | |
| 622 | − | |
| 623 | − //! Set the frequency of a tPhasor oscillator. | |
| 624 | − /*! | |
| 625 | − @param osc A pointer to the relevant tPhasor. | |
| 626 | − @param freq The frequency to set the oscillator to. | |
| 627 | − */ | |
| 628 | − void tPhasor_setFreq (tPhasor* const osc, float freq); | |
| 629 | − | |
| 630 | − /*! @} */ | |
| 631 | − | |
| 632 | − //============================================================================== | |
| 633 | − | |
| 634 | − /*! | |
| 635 | − * @defgroup tnoise tNoise | |
| 636 | − * @ingroup oscillators | |
| 637 | − * @brief A noise generator. | |
| 638 | − * @{ | |
| 639 | − */ | |
| 640 | − | |
| 641 | − /* tNoise. WhiteNoise, PinkNoise. */ | |
| 642 | − /*! | |
| 643 | − * Noise types | |
| 644 | − */ | |
| 645 | − enum NoiseType | |
| 646 | − { | |
| 647 | − WhiteNoise, //!< White noise. Full spectrum. | |
| 648 | − PinkNoise, //!< Pink noise. Inverse frequency-proportional spectrum. | |
| 649 | − NoiseTypeNil, | |
| 650 | − }; | |
| 651 | − | |
| 652 | − typedef enum NoiseType NoiseType; | |
| 653 | − | |
| 654 | − typedef struct _tNoise | |
| 655 | − { | |
| 656 | − NoiseType type; | |
| 657 | − float pinkb0, pinkb1, pinkb2; | |
| 658 | − float(*rand)(void); | |
| 659 | − | |
| 660 | − } _tNoise; | |
| 661 | − | |
| 662 | − typedef _tNoise* tNoise; | |
| 663 | − | |
| 664 | − //! Initialize a tNoise to the default LEAF mempool. | |
| 665 | − /*! | |
| 666 | − @param osc A pointer to the tNoise to be initialized. | |
| 667 | − */ | |
| 668 | − void tNoise_init (tNoise* const noise, NoiseType type); | |
| 669 | − | |
| 670 | − | |
| 671 | − //! Free a tNoise from the default LEAF mempool. | |
| 672 | − /*! | |
| 673 | − @param osc A pointer to the tNoise to be freed. | |
| 674 | − */ | |
| 675 | − void tNoise_free (tNoise* const noise); | |
| 676 | − | |
| 677 | − | |
| 678 | − //! Initialize a tNoise to a specified mempool. | |
| 679 | − /*! | |
| 680 | − @param osc A pointer to the tNoise to be initialized. | |
| 681 | − @param pool A pointer to the tMempool to which the tNoise should be initialized. | |
| 682 | − */ | |
| 683 | − void tNoise_initToPool (tNoise* const noise, NoiseType type, tMempool* const); | |
| 684 | − | |
| 685 | − | |
| 686 | − //! Free a tNoise from a specified mempool. | |
| 687 | − /*! | |
| 688 | − @param osc A pointer to the tNoise to be freed. | |
| 689 | − @param pool A pointer to the tMempool from which the tNoise should be freed. | |
| 690 | − */ | |
| 691 | − void tNoise_freeFromPool (tNoise* const noise, tMempool* const); | |
| 692 | − | |
| 693 | − | |
| 694 | − //! Tick a tNoise oscillator. | |
| 695 | − /*! | |
| 696 | − @param osc A pointer to the relevant tNoise. | |
| 697 | − @return The ticked sample as a float from -1 to 1. | |
| 698 | − */ | |
| 699 | − float tNoise_tick (tNoise* const noise); | |
| 700 | − | |
| 701 | − /*! @} */ | |
| 702 | − | |
| 703 | − //============================================================================== | |
| 704 | − | |
| 705 | − /*! | |
| 706 | − * @defgroup tneuron tNeuron | |
| 707 | − * @ingroup oscillators | |
| 708 | − * @brief A model of a neuron, adapted to act as an oscillator. | |
| 709 | − * @{ | |
| 710 | − */ | |
| 711 | − | |
| 712 | − /*! | |
| 713 | − * Neuron modes | |
| 714 | − */ | |
| 715 | − enum NeuronMode | |
| 716 | − { | |
| 717 | − NeuronNormal, //!< Normal operation | |
| 718 | − NeuronTanh, //!< Tanh voltage shaping | |
| 719 | − NeuronAaltoShaper, //!< Aalto voltage shaping | |
| 720 | − NeuronModeNil | |
| 721 | − }; | |
| 722 | − typedef enum NeuronMode NeuronMode; | |
| 723 | − | |
| 724 | − typedef struct _tNeuron | |
| 725 | − { | |
| 726 | − tPoleZero f; | |
| 727 | − | |
| 728 | − NeuronMode mode; | |
| 729 | − | |
| 730 | − float voltage, current; | |
| 731 | − float timeStep; | |
| 732 | − | |
| 733 | − float alpha[3]; | |
| 734 | − float beta[3]; | |
| 735 | − float rate[3]; | |
| 736 | − float V[3]; | |
| 737 | − float P[3]; | |
| 738 | − float gK, gN, gL, C; | |
| 739 | − } _tNeuron; | |
| 740 | − | |
| 741 | − typedef _tNeuron* tNeuron; | |
| 742 | − | |
| 743 | − //! Initialize a tNeuron to the default LEAF mempool. | |
| 744 | − /*! | |
| 745 | − @param neuron A pointer to the tNeuron to be initialized. | |
| 746 | − */ | |
| 747 | − void tNeuron_init (tNeuron* const neuron); | |
| 748 | − | |
| 749 | − | |
| 750 | − //! Free a tNeuron from the default LEAF mempool. | |
| 751 | − /*! | |
| 752 | − @param neuron A pointer to the tNeuron to be freed. | |
| 753 | − */ | |
| 754 | − void tNeuron_free (tNeuron* const neuron); | |
| 755 | − | |
| 756 | − | |
| 757 | − //! Initialize a tNeuron to a specified mempool. | |
| 758 | − /*! | |
| 759 | − @param neuron A pointer to the tNeuron to be initialized. | |
| 760 | − @param pool A pointer to the tMempool to which the tNeuron should be initialized. | |
| 761 | − */ | |
| 762 | − void tNeuron_initToPool (tNeuron* const neuron, tMempool* const pool); | |
| 763 | − | |
| 764 | − | |
| 765 | − //! Free a tNeuron from a specified mempool. | |
| 766 | − /*! | |
| 767 | − @param neuron A pointer to the tNeuron to be freed. | |
| 768 | − @param pool A pointer to the tMempool from which the tNeuron should be freed. | |
| 769 | − */ | |
| 770 | − void tNeuron_freeFromPool(tNeuron* const neuron, tMempool* const pool); | |
| 771 | − | |
| 772 | − | |
| 773 | − //! Reset the neuron model. | |
| 774 | − /*! | |
| 775 | − @param neuron A pointer to the relevant tNeuron. | |
| 776 | − */ | |
| 777 | − void tNeuron_reset (tNeuron* const neuron); | |
| 778 | − | |
| 779 | − | |
| 780 | − //! Tick a tNeuron oscillator. | |
| 781 | − /*! | |
| 782 | − @param neuron A pointer to the relevant tNeuron. | |
| 783 | − @return The ticked sample as a float from -1 to 1. | |
| 784 | − */ | |
| 785 | − float tNeuron_tick (tNeuron* const neuron); | |
| 786 | − | |
| 787 | − | |
| 788 | − //! Set the tNeuron shaping mode. | |
| 789 | − /*! | |
| 790 | − @param neuron A pointer to the relevant tNeuron. | |
| 791 | − @param mode The mode to set the tNeuron to. | |
| 792 | − */ | |
| 793 | − void tNeuron_setMode (tNeuron* const neuron, NeuronMode mode); | |
| 794 | − | |
| 795 | − | |
| 796 | − //! Set the current. | |
| 797 | − /*! | |
| 798 | − @param neuron A pointer to the relevant tNeuron. | |
| 799 | − @param current The new current. | |
| 800 | − */ | |
| 801 | − void tNeuron_setCurrent (tNeuron* const neuron, float current); | |
| 802 | − | |
| 803 | − | |
| 804 | − //! Set the potassium value. | |
| 805 | − /*! | |
| 806 | − @param neuron A pointer to the relevant tNeuron. | |
| 807 | − @param K The new potassium. | |
| 808 | − */ | |
| 809 | − void tNeuron_setK (tNeuron* const neuron, float K); | |
| 810 | − | |
| 811 | − | |
| 812 | − //! Set the chloride value. | |
| 813 | − /*! | |
| 814 | − @param neuron A pointer to the relevant tNeuron. | |
| 815 | − @param L The new chloride value. | |
| 816 | − */ | |
| 817 | − void tNeuron_setL (tNeuron* const neuron, float L); | |
| 818 | − | |
| 819 | − | |
| 820 | − //! Set the sodium value. | |
| 821 | − /*! | |
| 822 | − @param neuron A pointer to the relevant tNeuron. | |
| 823 | − @param N The new sodium value. | |
| 824 | − */ | |
| 825 | − void tNeuron_setN (tNeuron* const neuron, float N); | |
| 826 | − | |
| 827 | − | |
| 828 | − //! Set the calcium value. | |
| 829 | − /*! | |
| 830 | − @param neuron A pointer to the relevant tNeuron. | |
| 831 | − @param C The new calcium. | |
| 832 | − */ | |
| 833 | − void tNeuron_setC (tNeuron* const neuron, float C); | |
| 834 | − | |
| 835 | − | |
| 836 | − //! Set the V1 value. | |
| 837 | − /*! | |
| 838 | − @param neuron A pointer to the relevant tNeuron. | |
| 839 | − @param V1 The new V1. | |
| 840 | − */ | |
| 841 | − void tNeuron_setV1 (tNeuron* const neuron, float V1); | |
| 842 | − | |
| 843 | − | |
| 844 | − //! Set the V2 value. | |
| 845 | − /*! | |
| 846 | − @param neuron A pointer to the relevant tNeuron. | |
| 847 | − @param V2 The new V2. | |
| 848 | − */ | |
| 849 | − void tNeuron_setV2 (tNeuron* const neuron, float V2); | |
| 850 | − | |
| 851 | − | |
| 852 | − //! Set the V3 value. | |
| 853 | − /*! | |
| 854 | − @param neuron A pointer to the relevant tNeuron. | |
| 855 | − @param V3 The new V3. | |
| 856 | − */ | |
| 857 | − void tNeuron_setV3 (tNeuron* const neuron, float V3); | |
| 858 | − | |
| 859 | − | |
| 860 | − //! Set the time step. | |
| 861 | − /*! | |
| 862 | − @param neuron A pointer to the relevant tNeuron. | |
| 863 | − @param timestep The new time step | |
| 864 | − */ | |
| 865 | − void tNeuron_setTimeStep (tNeuron* const neuron, float timestep); | |
| 866 | − | |
| 867 | − /*! @} */ | |
| 868 | − | |
| 869 | − //============================================================================== | |
| 870 | − | |
| 871 | − typedef struct _tMinBLEP | |
| 872 | − { | |
| 873 | − float coeffs[6]; | |
| 874 | − | |
| 875 | − // FilterState | |
| 876 | − float* x1, x2, y1, y2; | |
| 877 | − | |
| 878 | − float ratio, lastRatio; | |
| 879 | − | |
| 880 | − float overSamplingRatio; | |
| 881 | − int zeroCrossings; | |
| 882 | − | |
| 883 | − float lastValue; | |
| 884 | − float lastDelta; // previous derivative ... | |
| 885 | − | |
| 886 | − // Tweaking the Blep F | |
| 887 | − float proportionalBlepFreq; | |
| 888 | − uint8_t returnDerivative; // set this to return the FIRST DERIVATIVE of the blep (for first der. discontinuities) | |
| 889 | − | |
| 890 | − int blepIndex; | |
| 891 | − int numActiveBleps; | |
| 892 | − //currentActiveBlepOffsets; | |
| 893 | − float* offset; | |
| 894 | − float* freqMultiple; | |
| 895 | − float* pos_change_magnitude; | |
| 896 | − float* vel_change_magnitude; | |
| 897 | − | |
| 898 | − int minBlepSize; | |
| 899 | − float* minBlepArray; | |
| 900 | − float* minBlepDerivArray; | |
| 901 | − } _tMinBLEP; | |
| 902 | − | |
| 903 | − typedef _tMinBLEP* tMinBLEP; | |
| 904 | − | |
| 905 | − void tMinBLEP_init (tMinBLEP* const minblep, int zeroCrossings, int oversamplerRatio); | |
| 906 | − void tMinBLEP_free (tMinBLEP* const minblep); | |
| 907 | − void tMinBLEP_initToPool (tMinBLEP* const minblep, int zeroCrossings, int oversamplerRatio, tMempool* const pool); | |
| 908 | − void tMinBLEP_freeFromPool (tMinBLEP* const minblep, tMempool* const pool); | |
| 909 | − | |
| 910 | − // pass in audio, identify discontinuities and return the audio with minbleps inserted | |
| 911 | − float tMinBLEP_tick (tMinBLEP* const minblep, float input); | |
| 912 | − void tMinBLEP_buildBLEP (tMinBLEP* const minblep); | |
| 913 | − void tMinBLEP_addBLEP (tMinBLEP* const minblep, float offset, float posChange, float velChange); | |
| 914 | − | |
| 915 | − void tMinBLEP_setOversamplingRatio (tMinBLEP* const minblep, float ratio); | |
| 916 | − void tMinBLEP_setNumZeroCrossings (tMinBLEP* const minblep, int numCrossings); | |
| 917 | − | |
| 918 | − //============================================================================== | |
| 919 | − | |
| 920 | − /* tMBTriangle: Anti-aliased Triangle waveform using wavetable interpolation. */ | |
| 921 | − typedef struct _tMBTriangle | |
| 922 | − { | |
| 923 | − float phase; | |
| 924 | − float inc,freq; | |
| 925 | − float skew; | |
| 926 | − float lastOut; | |
| 927 | − | |
| 928 | − tMinBLEP minBlep; | |
| 929 | − tHighpass dcBlock; | |
| 930 | − } _tMBTriangle; | |
| 931 | − | |
| 932 | − typedef _tMBTriangle* tMBTriangle; | |
| 933 | − | |
| 934 | − /*! | |
| 935 | − * @defgroup tMBTriangle tMBTriangle | |
| 936 | − * @ingroup oscillators | |
| 937 | − * @brief An anti-aliased triangle waveform oscillator. | |
| 938 | − * @{ | |
| 939 | − */ | |
| 940 | − | |
| 941 | − //! Initialize a tMBTriangle to the default LEAF mempool. | |
| 942 | − /*! | |
| 943 | − @param osc A pointer to the tMBTriangle to be initialized. | |
| 944 | − */ | |
| 945 | − void tMBTriangle_init (tMBTriangle* const osc); | |
| 946 | − | |
| 947 | − | |
| 948 | − //! Free a tMBTriangle from the default LEAF mempool. | |
| 949 | − /*! | |
| 950 | − @param osc A pointer to the tMBTriangle to be freed. | |
| 951 | − */ | |
| 952 | − void tMBTriangle_free (tMBTriangle* const osc); | |
| 953 | − | |
| 954 | − | |
| 955 | − //! Initialize a tMBTriangle to a specified mempool. | |
| 956 | − /*! | |
| 957 | − @param osc A pointer to the tMBTriangle to be initialized. | |
| 958 | − @param pool A pointer to the tMempool to which the tMBTriangle should be initialized. | |
| 959 | − */ | |
| 960 | − void tMBTriangle_initToPool (tMBTriangle* const osc, tMempool* const pool); | |
| 961 | − | |
| 962 | − | |
| 963 | − //! Free a tMBTriangle from a specified mempool. | |
| 964 | − /*! | |
| 965 | − @param osc A pointer to the tMBTriangle to be freed. | |
| 966 | − @param pool A pointer to the tMempool from which the tMBTriangle should be freed. | |
| 967 | − */ | |
| 968 | − void tMBTriangle_freeFromPool (tMBTriangle* const osc, tMempool* const pool); | |
| 969 | − | |
| 970 | − | |
| 971 | − //! Tick a tMBTriangle oscillator. | |
| 972 | − /*! | |
| 973 | − @param osc A pointer to the relevant tMBTriangle. | |
| 974 | − @return The ticked sample as a float from -1 to 1. | |
| 975 | − */ | |
| 976 | − float tMBTriangle_tick (tMBTriangle* const osc); | |
| 977 | − | |
| 978 | − | |
| 979 | − //! Set the frequency of a tMBTriangle oscillator. | |
| 980 | − /*! | |
| 981 | − @param osc A pointer to the relevant tMBTriangleangle. | |
| 982 | − @param freq The frequency to set the oscillator to. | |
| 983 | − */ | |
| 984 | − void tMBTriangle_setFreq (tMBTriangle* const osc, float freq); | |
| 985 | − | |
| 986 | − void tMBTriangle_setSkew (tMBTriangle* const osc, float skew); | |
| 987 | − | |
| 988 | − void tMBTriangle_sync (tMBTriangle* const osc, float phase); | |
| 989 | − | |
| 990 | − /*! @} */ | |
| 991 | − | |
| 992 | − //============================================================================== | |
| 993 | − | |
| 994 | − /* tMBPulse: Anti-aliased Square waveform. */ | |
| 995 | − typedef struct _tMBPulse | |
| 996 | − { | |
| 997 | − float phase; | |
| 998 | − float inc,freq; | |
| 999 | − float width; | |
| 1000 | − | |
| 1001 | − tMinBLEP minBlep; | |
| 1002 | − tHighpass dcBlock; | |
| 1003 | − } _tMBPulse; | |
| 1004 | − | |
| 1005 | − typedef _tMBPulse* tMBPulse; | |
| 1006 | − | |
| 1007 | − /*! | |
| 1008 | − * @defgroup tMBPulse tMBPulse | |
| 1009 | − * @ingroup oscillators | |
| 1010 | − * @brief An anti-aliased pulse waveform oscillator with changeable pulse width. | |
| 1011 | − * @{ | |
| 1012 | − */ | |
| 1013 | − | |
| 1014 | − //! Initialize a tMBPulse to the default LEAF mempool. | |
| 1015 | − /*! | |
| 1016 | − @param osc A pointer to the tMBPulse to be initialized. | |
| 1017 | − */ | |
| 1018 | − void tMBPulse_init (tMBPulse* const osc); | |
| 1019 | − | |
| 1020 | − | |
| 1021 | − //! Free a tMBPulse from the default LEAF mempool. | |
| 1022 | − /*! | |
| 1023 | − @param osc A pointer to the tMBPulse to be freed. | |
| 1024 | − */ | |
| 1025 | − void tMBPulse_free (tMBPulse* const osc); | |
| 1026 | − | |
| 1027 | − | |
| 1028 | − //! Initialize a tMBPulse to a specified mempool. | |
| 1029 | − /*! | |
| 1030 | − @param osc A pointer to the tMBPulse to be initialized. | |
| 1031 | − @param pool A pointer to the tMempool to which the tMBPulse should be initialized. | |
| 1032 | − */ | |
| 1033 | − void tMBPulse_initToPool (tMBPulse* const osc, tMempool* const); | |
| 1034 | − | |
| 1035 | − | |
| 1036 | − //! Free a tMBPulse from a specified mempool. | |
| 1037 | − /*! | |
| 1038 | − @param osc A pointer to the tMBPulse to be freed. | |
| 1039 | − @param pool A pointer to the tMempool from which the tMBPulse should be freed. | |
| 1040 | − */ | |
| 1041 | − void tMBPulse_freeFromPool(tMBPulse* const osc, tMempool* const); | |
| 1042 | − | |
| 1043 | − | |
| 1044 | − //! Tick a tMBPulse oscillator. | |
| 1045 | − /*! | |
| 1046 | − @param osc A pointer to the relevant tMBPulse. | |
| 1047 | − @return The ticked sample as a float from -1 to 1. | |
| 1048 | − */ | |
| 1049 | − float tMBPulse_tick (tMBPulse* const osc); | |
| 1050 | − | |
| 1051 | − | |
| 1052 | − //! Set the frequency of a tMBPulse oscillator. | |
| 1053 | − /*! | |
| 1054 | − @param osc A pointer to the relevant tMBPulse. | |
| 1055 | − @param freq The frequency to set the oscillator to. | |
| 1056 | − */ | |
| 1057 | − void tMBPulse_setFreq (tMBPulse* const osc, float freq); | |
| 1058 | − | |
| 1059 | − void tMBPulse_setWidth (tMBPulse* const osc, float width); | |
| 1060 | − | |
| 1061 | − void tMBPulse_sync (tMBPulse* const osc, float phase); | |
| 1062 | − | |
| 1063 | − | |
| 1064 | − /*! @} */ | |
| 1065 | − | |
| 1066 | − //============================================================================== | |
| 1067 | − | |
| 1068 | − /* tMBSawtooth: Anti-aliased Sawtooth waveform. */ | |
| 1069 | − typedef struct _tMBSaw | |
| 1070 | − { | |
| 1071 | − float phase; | |
| 1072 | − float inc,freq; | |
| 1073 | − | |
| 1074 | − tMinBLEP minBlep; | |
| 1075 | − tHighpass dcBlock; | |
| 1076 | − } _tMBSaw; | |
| 1077 | − | |
| 1078 | − typedef _tMBSaw* tMBSaw; | |
| 1079 | − | |
| 1080 | − /*! | |
| 1081 | − * @defgroup tMBSaw tMBSaw | |
| 1082 | − * @ingroup oscillators | |
| 1083 | − * @brief An anti-aliased sawtooth waveform oscillator. Uses wavetable synthesis. | |
| 1084 | − * @{ | |
| 1085 | − */ | |
| 1086 | − | |
| 1087 | − //! Initialize a tMBSaw to the default LEAF mempool. | |
| 1088 | − /*! | |
| 1089 | − @param osc A pointer to the tMBSaw to be initialized. | |
| 1090 | − */ | |
| 1091 | − void tMBSaw_init (tMBSaw* const osc); | |
| 1092 | − | |
| 1093 | − | |
| 1094 | − //! Free a tMBSaw from the default LEAF mempool. | |
| 1095 | − /*! | |
| 1096 | − @param osc A pointer to the tMBSaw to be freed. | |
| 1097 | − */ | |
| 1098 | − void tMBSaw_free (tMBSaw* const osc); | |
| 1099 | − | |
| 1100 | − | |
| 1101 | − //! Initialize a tMBSaw to a specified mempool. | |
| 1102 | − /*! | |
| 1103 | − @param osc A pointer to the tMBSaw to be initialized. | |
| 1104 | − @param pool A pointer to the tMempool to which the tMBSaw should be initialized. | |
| 1105 | − */ | |
| 1106 | − void tMBSaw_initToPool (tMBSaw* const osc, tMempool* const pool); | |
| 1107 | − | |
| 1108 | − | |
| 1109 | − //! Free a tMBSaw from a specified mempool. | |
| 1110 | − /*! | |
| 1111 | − @param osc A pointer to the tMBSaw to be freed. | |
| 1112 | − @param pool A pointer to the tMempool from which the tMBSaw should be freed. | |
| 1113 | − */ | |
| 1114 | − void tMBSaw_freeFromPool (tMBSaw* const osc, tMempool* const pool); | |
| 1115 | − | |
| 1116 | − | |
| 1117 | − //! Tick a tMBSaw oscillator. | |
| 1118 | − /*! | |
| 1119 | − @param osc A pointer to the relevant tMBSaw. | |
| 1120 | − @return The ticked sample as a float from -1 to 1. | |
| 1121 | − */ | |
| 1122 | − float tMBSaw_tick (tMBSaw* const osc); | |
| 1123 | − | |
| 1124 | − | |
| 1125 | − //! Set the frequency of a tMBSaw oscillator. | |
| 1126 | − /*! | |
| 1127 | − @param osc A pointer to the relevant tMBSaw. | |
| 1128 | − @param freq The frequency to set the oscillator to. | |
| 1129 | − */ | |
| 1130 | − void tMBSaw_setFreq (tMBSaw* const osc, float freq); | |
| 1131 | − | |
| 1132 | − void tMBSaw_sync (tMBSaw* const osc, float phase); | |
| 1133 | − | |
| 1134 | − /*! @} */ | |
| 1135 | − | |
| 1136 | −#ifdef __cplusplus | |
| 1137 | −} | |
| 1138 | −#endif | |
| 1139 | − | |
| 1140 | −#endif // LEAF_OSCILLATORS_H_INCLUDED | |
| 1141 | − | |
| 1142 | −//============================================================================== | |
| 1143 | − | |
| @@ -1,259 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − ============================================================================== | |
| 3 | − | |
| 4 | − leaf-physical.h | |
| 5 | − Created: 30 Nov 2018 10:41:55am | |
| 6 | − Author: airship | |
| 7 | − | |
| 8 | − ============================================================================== | |
| 9 | − */ | |
| 10 | − | |
| 11 | −#ifndef LEAF_PHYSICAL_H_INCLUDED | |
| 12 | −#define LEAF_PHYSICAL_H_INCLUDED | |
| 13 | − | |
| 14 | −#ifdef __cplusplus | |
| 15 | −extern "C" { | |
| 16 | −#endif | |
| 17 | − | |
| 18 | − //============================================================================== | |
| 19 | − | |
| 20 | −#include "leaf-global.h" | |
| 21 | −#include "leaf-math.h" | |
| 22 | −#include "leaf-mempool.h" | |
| 23 | −#include "leaf-delay.h" | |
| 24 | −#include "leaf-filters.h" | |
| 25 | −#include "leaf-oscillators.h" | |
| 26 | −#include "leaf-envelopes.h" | |
| 27 | −#include "leaf-dynamics.h" | |
| 28 | − | |
| 29 | − /*! | |
| 30 | − * @internal | |
| 31 | − * Header. | |
| 32 | − * @include basic-oscillators.h | |
| 33 | − * @example basic-oscillators.c | |
| 34 | − * An example. | |
| 35 | − */ | |
| 36 | − | |
| 37 | − //============================================================================== | |
| 38 | − | |
| 39 | − /* Karplus Strong model */ | |
| 40 | − typedef struct _tPluck | |
| 41 | − { | |
| 42 | − tAllpassDelay delayLine; // Allpass or Linear?? big difference... | |
| 43 | − tOneZero loopFilter; | |
| 44 | − tOnePole pickFilter; | |
| 45 | − tNoise noise; | |
| 46 | − | |
| 47 | − float lastOut; | |
| 48 | − float loopGain; | |
| 49 | − float lastFreq; | |
| 50 | − | |
| 51 | − float sr; | |
| 52 | − | |
| 53 | − } _tPluck; | |
| 54 | − | |
| 55 | − typedef _tPluck* tPluck; | |
| 56 | − | |
| 57 | − void tPluck_init (tPluck* const, float lowestFrequency); //float delayBuff[DELAY_LENGTH]); | |
| 58 | − void tPluck_free (tPluck* const); | |
| 59 | − void tPluck_initToPool (tPluck* const, float lowestFrequency, tMempool* const); | |
| 60 | − void tPluck_freeFromPool (tPluck* const, tMempool* const); | |
| 61 | − | |
| 62 | − float tPluck_tick (tPluck* const); | |
| 63 | − | |
| 64 | − // Pluck the string. | |
| 65 | − void tPluck_pluck (tPluck* const, float amplitude); | |
| 66 | − | |
| 67 | − // Start a note with the given frequency and amplitude.; | |
| 68 | − void tPluck_noteOn (tPluck* const, float frequency, float amplitude ); | |
| 69 | − | |
| 70 | − // Stop a note with the given amplitude (speed of decay). | |
| 71 | − void tPluck_noteOff (tPluck* const, float amplitude ); | |
| 72 | − | |
| 73 | − // Set instrument parameters for a particular frequency. | |
| 74 | − void tPluck_setFrequency (tPluck* const, float frequency ); | |
| 75 | − | |
| 76 | − // Perform the control change specified by \e number and \e value (0.0 - 128.0). | |
| 77 | − void tPluck_controlChange (tPluck* const, int number, float value); | |
| 78 | − | |
| 79 | − // tPluck Utilities. | |
| 80 | − float tPluck_getLastOut (tPluck* const); | |
| 81 | − | |
| 82 | − //============================================================================== | |
| 83 | − | |
| 84 | − typedef enum SKControlType | |
| 85 | − { | |
| 86 | − SKPickPosition = 0, | |
| 87 | − SKStringDamping, | |
| 88 | − SKDetune, | |
| 89 | − SKControlTypeNil | |
| 90 | − } SKControlType; | |
| 91 | − | |
| 92 | − /* Stif Karplus Strong model */ | |
| 93 | − typedef struct _tKarplusStrong | |
| 94 | − { | |
| 95 | − tAllpassDelay delayLine; | |
| 96 | − tLinearDelay combDelay; | |
| 97 | − tOneZero filter; | |
| 98 | − tNoise noise; | |
| 99 | − tBiQuad biquad[4]; | |
| 100 | − | |
| 101 | − uint32_t length; | |
| 102 | − float loopGain; | |
| 103 | − float baseLoopGain; | |
| 104 | − float lastFrequency; | |
| 105 | − float lastLength; | |
| 106 | − float stretching; | |
| 107 | − float pluckAmplitude; | |
| 108 | − float pickupPosition; | |
| 109 | − | |
| 110 | − float lastOut; | |
| 111 | − | |
| 112 | − } _tKarplusStrong; | |
| 113 | − | |
| 114 | − typedef _tKarplusStrong* tKarplusStrong; | |
| 115 | − | |
| 116 | − void tKarplusStrong_init (tKarplusStrong* const, float lowestFrequency); // float delayBuff[2][DELAY_LENGTH]); | |
| 117 | − void tKarplusStrong_free (tKarplusStrong* const); | |
| 118 | − void tKarplusStrong_initToPool (tKarplusStrong* const, float lowestFrequency, tMempool* const); | |
| 119 | − void tKarplusStrong_freeFromPool (tKarplusStrong* const, tMempool* const); | |
| 120 | − | |
| 121 | − float tKarplusStrong_tick (tKarplusStrong* const); | |
| 122 | − | |
| 123 | − // Pluck the string. | |
| 124 | − void tKarplusStrong_pluck (tKarplusStrong* const, float amplitude); | |
| 125 | − | |
| 126 | − // Start a note with the given frequency and amplitude.; | |
| 127 | − void tKarplusStrong_noteOn (tKarplusStrong* const, float frequency, float amplitude ); | |
| 128 | − | |
| 129 | − // Stop a note with the given amplitude (speed of decay). | |
| 130 | − void tKarplusStrong_noteOff (tKarplusStrong* const, float amplitude ); | |
| 131 | − | |
| 132 | − // Set instrument parameters for a particular frequency. | |
| 133 | − void tKarplusStrong_setFrequency (tKarplusStrong* const, float frequency ); | |
| 134 | − | |
| 135 | − // Perform the control change specified by \e number and \e value (0.0 - 128.0). | |
| 136 | − // Use SKPickPosition, SKStringDamping, or SKDetune for type. | |
| 137 | − void tKarplusStrong_controlChange (tKarplusStrong* const, SKControlType type, float value); | |
| 138 | − | |
| 139 | − // Set the stretch "factor" of the string (0.0 - 1.0). | |
| 140 | − void tKarplusStrong_setStretch (tKarplusStrong* const, float stretch ); | |
| 141 | − | |
| 142 | − // Set the pluck or "excitation" position along the string (0.0 - 1.0). | |
| 143 | − void tKarplusStrong_setPickupPosition (tKarplusStrong* const, float position ); | |
| 144 | − | |
| 145 | − // Set the base loop gain. | |
| 146 | − void tKarplusStrong_setBaseLoopGain (tKarplusStrong* const, float aGain ); | |
| 147 | − | |
| 148 | − // tKarplusStrong utilities. | |
| 149 | − float tKarplusStrong_getLastOut (tKarplusStrong* const); | |
| 150 | − | |
| 151 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 152 | − | |
| 153 | − /* Simple Living String */ | |
| 154 | − typedef struct _tSimpleLivingString { | |
| 155 | − float freq, waveLengthInSamples; // the frequency of the string, determining delay length | |
| 156 | − float dampFreq; // frequency for the bridge LP filter, in Hz | |
| 157 | − float decay; // amplitude damping factor for the string (only active in mode 0) | |
| 158 | − float levMode; | |
| 159 | − float curr; | |
| 160 | − tLinearDelay delayLine; | |
| 161 | − tOnePole bridgeFilter; | |
| 162 | − tHighpass DCblocker; | |
| 163 | − tFeedbackLeveler fbLev; | |
| 164 | − tExpSmooth wlSmooth; | |
| 165 | − } _tSimpleLivingString; | |
| 166 | − | |
| 167 | − typedef _tSimpleLivingString* tSimpleLivingString; | |
| 168 | − | |
| 169 | − void tSimpleLivingString_init (tSimpleLivingString* const, float freq, float dampFreq, | |
| 170 | − float decay, float targetLev, float levSmoothFactor, | |
| 171 | − float levStrength, int levMode); | |
| 172 | − void tSimpleLivingString_free (tSimpleLivingString* const); | |
| 173 | − void tSimpleLivingString_initToPool (tSimpleLivingString* const, float freq, float dampFreq, | |
| 174 | − float decay, float targetLev, float levSmoothFactor, | |
| 175 | − float levStrength, int levMode, tMempool* const); | |
| 176 | − void tSimpleLivingString_freeFromPool (tSimpleLivingString* const, tMempool* const); | |
| 177 | − | |
| 178 | − float tSimpleLivingString_tick (tSimpleLivingString* const, float input); | |
| 179 | − float tSimpleLivingString_sample (tSimpleLivingString* const); | |
| 180 | − void tSimpleLivingString_setFreq (tSimpleLivingString* const, float freq); | |
| 181 | − void tSimpleLivingString_setWaveLength (tSimpleLivingString* const, float waveLength); // in samples | |
| 182 | − void tSimpleLivingString_setDampFreq (tSimpleLivingString* const, float dampFreq); | |
| 183 | − void tSimpleLivingString_setDecay (tSimpleLivingString* const, float decay); // should be near 1.0 | |
| 184 | − void tSimpleLivingString_setTargetLev (tSimpleLivingString* const, float targetLev); | |
| 185 | − void tSimpleLivingString_setLevSmoothFactor (tSimpleLivingString* const, float levSmoothFactor); | |
| 186 | − void tSimpleLivingString_setLevStrength (tSimpleLivingString* const, float levStrength); | |
| 187 | − void tSimpleLivingString_setLevMode (tSimpleLivingString* const, int levMode); | |
| 188 | − | |
| 189 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 190 | − | |
| 191 | − /* Living String */ | |
| 192 | − typedef struct _tLivingString { | |
| 193 | − float freq, waveLengthInSamples; // the frequency of the whole string, determining delay length | |
| 194 | − float pickPos; // the pick position, dividing the string in two, in ratio | |
| 195 | − float prepIndex; // the amount of pressure on the pickpoint of the string (near 0=soft obj, near 1=hard obj) | |
| 196 | − float dampFreq; // frequency for the bridge LP filter, in Hz | |
| 197 | − float decay; // amplitude damping factor for the string (only active in mode 0) | |
| 198 | − float levMode; | |
| 199 | − float curr; | |
| 200 | − tLinearDelay delLF,delUF,delUB,delLB; // delay for lower/upper/forward/backward part of the waveguide model | |
| 201 | − tOnePole bridgeFilter, nutFilter, prepFilterU, prepFilterL; | |
| 202 | − tHighpass DCblockerL, DCblockerU; | |
| 203 | − tFeedbackLeveler fbLevU, fbLevL; | |
| 204 | − tExpSmooth wlSmooth, ppSmooth; | |
| 205 | − } _tLivingString; | |
| 206 | − | |
| 207 | − typedef _tLivingString* tLivingString; | |
| 208 | − | |
| 209 | − void tLivingString_init (tLivingString* const, float freq, float pickPos, float prepIndex, | |
| 210 | − float dampFreq, float decay, float targetLev, float levSmoothFactor, | |
| 211 | − float levStrength, int levMode); | |
| 212 | − void tLivingString_free (tLivingString* const); | |
| 213 | − void tLivingString_initToPool (tLivingString* const, float freq, float pickPos, float prepIndex, | |
| 214 | − float dampFreq, float decay, float targetLev, float levSmoothFactor, | |
| 215 | − float levStrength, int levMode, tMempool* const); | |
| 216 | − void tLivingString_freeFromPool (tLivingString* const, tMempool* const); | |
| 217 | − | |
| 218 | − float tLivingString_tick (tLivingString* const, float input); | |
| 219 | − float tLivingString_sample (tLivingString* const); | |
| 220 | − void tLivingString_setFreq (tLivingString* const, float freq); | |
| 221 | − void tLivingString_setWaveLength (tLivingString* const, float waveLength); // in samples | |
| 222 | − void tLivingString_setPickPos (tLivingString* const, float pickPos); | |
| 223 | − void tLivingString_setPrepIndex (tLivingString* const, float prepIndex); | |
| 224 | − void tLivingString_setDampFreq (tLivingString* const, float dampFreq); | |
| 225 | − void tLivingString_setDecay (tLivingString* const, float decay); // should be near 1.0 | |
| 226 | − void tLivingString_setTargetLev (tLivingString* const, float targetLev); | |
| 227 | − void tLivingString_setLevSmoothFactor (tLivingString* const, float levSmoothFactor); | |
| 228 | − void tLivingString_setLevStrength (tLivingString* const, float levStrength); | |
| 229 | − void tLivingString_setLevMode (tLivingString* const, int levMode); | |
| 230 | − | |
| 231 | − // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 232 | − | |
| 233 | − //Reed Table - borrowed from STK | |
| 234 | − typedef struct _tReedTable { | |
| 235 | − float offset, slope; | |
| 236 | − } _tReedTable; | |
| 237 | − | |
| 238 | − typedef _tReedTable* tReedTable; | |
| 239 | − | |
| 240 | − void tReedTable_init (tReedTable* const, float offset, float slope); | |
| 241 | − void tReedTable_free (tReedTable* const); | |
| 242 | − void tReedTable_initToPool (tReedTable* const, float offset, float slope, tMempool* const); | |
| 243 | − void tReedTable_freeFromPool (tReedTable* const, tMempool* const); | |
| 244 | − | |
| 245 | − float tReedTable_tick (tReedTable* const, float input); | |
| 246 | − float tReedTable_tanh_tick (tReedTable* const, float input); //tanh softclip version of reed table - replacing the hard clip in original stk code | |
| 247 | − void tReedTable_setOffset (tReedTable* const, float offset); | |
| 248 | − void tReedTable_setSlope (tReedTable* const, float slope); | |
| 249 | − | |
| 250 | − //============================================================================== | |
| 251 | − | |
| 252 | −#ifdef __cplusplus | |
| 253 | −} | |
| 254 | −#endif | |
| 255 | − | |
| 256 | −#endif // LEAF_PHYSICAL_H_INCLUDED | |
| 257 | − | |
| 258 | −//============================================================================== | |
| 259 | − | |
| @@ -1,175 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-reverb.h | |
| 4 | − Created: 20 Jan 2017 12:02:04pm | |
| 5 | − Author: Michael R Mulshine | |
| 6 | − | |
| 7 | − ==============================================================================*/ | |
| 8 | − | |
| 9 | −#ifndef LEAF_REVERB_H_INCLUDED | |
| 10 | −#define LEAF_REVERB_H_INCLUDED | |
| 11 | − | |
| 12 | −#ifdef __cplusplus | |
| 13 | −extern "C" { | |
| 14 | −#endif | |
| 15 | − | |
| 16 | − //============================================================================== | |
| 17 | − | |
| 18 | −#include "leaf-global.h" | |
| 19 | −#include "leaf-math.h" | |
| 20 | −#include "leaf-mempool.h" | |
| 21 | −#include "leaf-delay.h" | |
| 22 | −#include "leaf-filters.h" | |
| 23 | −#include "leaf-oscillators.h" | |
| 24 | − | |
| 25 | − /*! | |
| 26 | − * @internal | |
| 27 | − * Header. | |
| 28 | − * @include basic-oscillators.h | |
| 29 | − * @example basic-oscillators.c | |
| 30 | − * An example. | |
| 31 | − */ | |
| 32 | − | |
| 33 | − //============================================================================== | |
| 34 | − | |
| 35 | − /* PRCReverb: Reverb, reimplemented from STK (Cook and Scavone). */ | |
| 36 | − typedef struct _tPRCReverb | |
| 37 | − { | |
| 38 | − float mix, t60; | |
| 39 | − | |
| 40 | − float inv_441; | |
| 41 | − | |
| 42 | − tDelay allpassDelays[2]; | |
| 43 | − tDelay combDelay; | |
| 44 | − float allpassCoeff; | |
| 45 | − float combCoeff; | |
| 46 | − | |
| 47 | − float lastIn, lastOut; | |
| 48 | − | |
| 49 | − } _tPRCReverb; | |
| 50 | − | |
| 51 | − typedef _tPRCReverb* tPRCReverb; | |
| 52 | − | |
| 53 | − void tPRCReverb_init (tPRCReverb* const, float t60); | |
| 54 | − void tPRCReverb_free (tPRCReverb* const); | |
| 55 | − void tPRCReverb_initToPool (tPRCReverb* const, float t60, tMempool* const); | |
| 56 | − void tPRCReverb_freeFromPool (tPRCReverb* const, tMempool* const); | |
| 57 | − | |
| 58 | − void tPRCReverb_clear (tPRCReverb* const); | |
| 59 | − float tPRCReverb_tick (tPRCReverb* const, float input); | |
| 60 | − | |
| 61 | − // Set reverb time in seconds. | |
| 62 | − void tPRCReverb_setT60 (tPRCReverb* const, float t60); | |
| 63 | − | |
| 64 | − // Set mix between dry input and wet output signal. | |
| 65 | − void tPRCReverb_setMix (tPRCReverb* const, float mix); | |
| 66 | − | |
| 67 | − //============================================================================== | |
| 68 | − | |
| 69 | − /* NReverb: Reverb, reimplemented from STK (Cook and Scavone). */ | |
| 70 | − typedef struct _tNReverb | |
| 71 | − { | |
| 72 | − float mix, t60; | |
| 73 | − | |
| 74 | − float inv_sr, inv_441; | |
| 75 | − | |
| 76 | − tLinearDelay allpassDelays[8]; | |
| 77 | − tLinearDelay combDelays[6]; | |
| 78 | − float allpassCoeff; | |
| 79 | − float combCoeffs[6]; | |
| 80 | − float lowpassState; | |
| 81 | − | |
| 82 | − float lastIn, lastOut; | |
| 83 | − | |
| 84 | − } _tNReverb; | |
| 85 | − | |
| 86 | − typedef _tNReverb* tNReverb; | |
| 87 | − | |
| 88 | − void tNReverb_init (tNReverb* const, float t60); | |
| 89 | − void tNReverb_free (tNReverb* const); | |
| 90 | − void tNReverb_initToPool (tNReverb* const, float t60, tMempool* const); | |
| 91 | − void tNReverb_freeFromPool (tNReverb* const, tMempool* const); | |
| 92 | − | |
| 93 | − void tNReverb_clear (tNReverb* const); | |
| 94 | − float tNReverb_tick (tNReverb* const, float input); | |
| 95 | − void tNReverb_tickStereo (tNReverb* const rev, float input, float* output); | |
| 96 | − | |
| 97 | − // Set reverb time in seconds. | |
| 98 | − void tNReverb_setT60 (tNReverb* const, float t60); | |
| 99 | − | |
| 100 | − // Set mix between dry input and wet output signal. | |
| 101 | − void tNReverb_setMix (tNReverb* const, float mix); | |
| 102 | − | |
| 103 | − //============================================================================== | |
| 104 | − | |
| 105 | − typedef struct _tDattorroReverb | |
| 106 | − { | |
| 107 | − float predelay; | |
| 108 | − float input_filter; | |
| 109 | − float feedback_filter; | |
| 110 | − float feedback_gain; | |
| 111 | − float mix; | |
| 112 | − uint32_t frozen; | |
| 113 | − | |
| 114 | − float size, size_max, t; | |
| 115 | − | |
| 116 | − float f1_delay_2_last, | |
| 117 | − f2_delay_2_last; | |
| 118 | − | |
| 119 | − float f1_last, | |
| 120 | − f2_last; | |
| 121 | − | |
| 122 | − // INPUT | |
| 123 | − tTapeDelay in_delay; | |
| 124 | − tOnePole in_filter; | |
| 125 | − tAllpass in_allpass[4]; | |
| 126 | − | |
| 127 | − // FEEDBACK 1 | |
| 128 | − tAllpass f1_allpass; | |
| 129 | − tTapeDelay f1_delay_1; | |
| 130 | − tOnePole f1_filter; | |
| 131 | − tTapeDelay f1_delay_2; | |
| 132 | − tTapeDelay f1_delay_3; | |
| 133 | − tHighpass f1_hp; | |
| 134 | − | |
| 135 | − tCycle f1_lfo; | |
| 136 | − | |
| 137 | − // FEEDBACK 2 | |
| 138 | − tAllpass f2_allpass; | |
| 139 | − tTapeDelay f2_delay_1; | |
| 140 | − tOnePole f2_filter; | |
| 141 | − tTapeDelay f2_delay_2; | |
| 142 | − tTapeDelay f2_delay_3; | |
| 143 | − tHighpass f2_hp; | |
| 144 | − | |
| 145 | − tCycle f2_lfo; | |
| 146 | − | |
| 147 | − } _tDattorroReverb; | |
| 148 | − | |
| 149 | − typedef _tDattorroReverb* tDattorroReverb; | |
| 150 | − | |
| 151 | − void tDattorroReverb_init (tDattorroReverb* const); | |
| 152 | − void tDattorroReverb_free (tDattorroReverb* const); | |
| 153 | − void tDattorroReverb_initToPool (tDattorroReverb* const, tMempool* const); | |
| 154 | − void tDattorroReverb_freeFromPool (tDattorroReverb* const, tMempool* const); | |
| 155 | − | |
| 156 | − void tDattorroReverb_clear (tDattorroReverb* const); | |
| 157 | − float tDattorroReverb_tick (tDattorroReverb* const, float input); | |
| 158 | − void tDattorroReverb_tickStereo (tDattorroReverb* const rev, float input, float* output); | |
| 159 | − void tDattorroReverb_setMix (tDattorroReverb* const, float mix); | |
| 160 | − void tDattorroReverb_setFreeze (tDattorroReverb* const rev, uint32_t freeze); | |
| 161 | − void tDattorroReverb_setHP (tDattorroReverb* const, float freq); | |
| 162 | − void tDattorroReverb_setSize (tDattorroReverb* const, float size); | |
| 163 | − void tDattorroReverb_setInputDelay (tDattorroReverb* const, float preDelay); | |
| 164 | − void tDattorroReverb_setInputFilter (tDattorroReverb* const, float freq); | |
| 165 | − void tDattorroReverb_setFeedbackFilter (tDattorroReverb* const, float freq); | |
| 166 | − void tDattorroReverb_setFeedbackGain (tDattorroReverb* const, float gain); | |
| 167 | − | |
| 168 | −#ifdef __cplusplus | |
| 169 | −} | |
| 170 | −#endif | |
| 171 | − | |
| 172 | −#endif // LEAF_REVERB_H_INCLUDED | |
| 173 | − | |
| 174 | −//============================================================================== | |
| 175 | − | |
| @@ -1,188 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-sampling.h | |
| 4 | − Created: 23 Jan 2019 11:22:09am | |
| 5 | − Author: Mike Mulshine | |
| 6 | − | |
| 7 | − ==============================================================================*/ | |
| 8 | − | |
| 9 | − | |
| 10 | −#ifndef LEAF_SAMPLING_H_INCLUDED | |
| 11 | −#define LEAF_SAMPLING_H_INCLUDED | |
| 12 | − | |
| 13 | −#ifdef __cplusplus | |
| 14 | −extern "C" { | |
| 15 | −#endif | |
| 16 | − | |
| 17 | − //============================================================================== | |
| 18 | − | |
| 19 | −#include "leaf-global.h" | |
| 20 | −#include "leaf-math.h" | |
| 21 | −#include "leaf-mempool.h" | |
| 22 | −#include "leaf-envelopes.h" | |
| 23 | −#include "leaf-mempool.h" | |
| 24 | −#include "leaf-analysis.h" | |
| 25 | − | |
| 26 | − /*! | |
| 27 | − * @internal | |
| 28 | − * Header. | |
| 29 | − * @include basic-oscillators.h | |
| 30 | − * @example basic-oscillators.c | |
| 31 | − * An example. | |
| 32 | − */ | |
| 33 | − | |
| 34 | − //============================================================================== | |
| 35 | − | |
| 36 | − typedef enum RecordMode | |
| 37 | − { | |
| 38 | − RecordOneShot = 0, | |
| 39 | − RecordLoop, | |
| 40 | − RecordModeNil | |
| 41 | − } RecordMode; | |
| 42 | − | |
| 43 | − typedef struct _tBuffer | |
| 44 | − { | |
| 45 | − float* buff; | |
| 46 | − | |
| 47 | − uint32_t idx; | |
| 48 | − uint32_t bufferLength; | |
| 49 | − uint32_t recordedLength; | |
| 50 | − RecordMode mode; | |
| 51 | − | |
| 52 | − int active; | |
| 53 | − | |
| 54 | − } _tBuffer; | |
| 55 | − | |
| 56 | − typedef _tBuffer* tBuffer; | |
| 57 | − | |
| 58 | − void tBuffer_init (tBuffer* const, uint32_t length); | |
| 59 | − void tBuffer_free (tBuffer* const); | |
| 60 | − void tBuffer_initToPool (tBuffer* const, uint32_t length, tMempool* const); | |
| 61 | − void tBuffer_freeFromPool (tBuffer* const, tMempool* const); | |
| 62 | − | |
| 63 | − void tBuffer_tick (tBuffer* const, float sample); | |
| 64 | − | |
| 65 | − void tBuffer_read (tBuffer* const, float* buff, uint32_t len); | |
| 66 | − | |
| 67 | − float tBuffer_get (tBuffer* const, int idx); | |
| 68 | − | |
| 69 | − void tBuffer_record (tBuffer* const); | |
| 70 | − void tBuffer_stop (tBuffer* const); | |
| 71 | − int tBuffer_getRecordPosition (tBuffer* const); | |
| 72 | − | |
| 73 | − void tBuffer_setRecordMode (tBuffer* const, RecordMode mode); | |
| 74 | − | |
| 75 | − void tBuffer_clear (tBuffer* const); | |
| 76 | − | |
| 77 | − uint32_t tBuffer_getBufferLength (tBuffer* const); | |
| 78 | − uint32_t tBuffer_getRecordedLength (tBuffer* const sb); | |
| 79 | − | |
| 80 | − //============================================================================== | |
| 81 | − | |
| 82 | − typedef enum PlayMode | |
| 83 | − { | |
| 84 | − PlayNormal, | |
| 85 | − PlayLoop, | |
| 86 | − PlayBackAndForth, | |
| 87 | − PlayModeNil | |
| 88 | − } PlayMode; | |
| 89 | − | |
| 90 | − typedef struct _tSampler | |
| 91 | − { | |
| 92 | − tBuffer samp; | |
| 93 | − | |
| 94 | − tRamp gain; | |
| 95 | − | |
| 96 | − float idx; | |
| 97 | − float inc; | |
| 98 | − float last; | |
| 99 | − float iinc; | |
| 100 | − int8_t dir; | |
| 101 | − int8_t flip; | |
| 102 | − int8_t bnf; | |
| 103 | − | |
| 104 | − int32_t start, targetstart; | |
| 105 | − int32_t end, targetend; | |
| 106 | − | |
| 107 | − uint32_t len; | |
| 108 | − uint32_t cfxlen; | |
| 109 | − float numticks; | |
| 110 | − PlayMode mode; | |
| 111 | − int retrigger; | |
| 112 | − | |
| 113 | − int active; | |
| 114 | − | |
| 115 | − uint8_t inCrossfade; | |
| 116 | − | |
| 117 | − float flipStart; | |
| 118 | − float flipIdx; | |
| 119 | − | |
| 120 | − } _tSampler; | |
| 121 | − | |
| 122 | − typedef _tSampler* tSampler; | |
| 123 | − | |
| 124 | − void tSampler_init (tSampler* const, tBuffer* const); | |
| 125 | − void tSampler_free (tSampler* const); | |
| 126 | − void tSampler_initToPool (tSampler* const, tBuffer* const, tMempool* const); | |
| 127 | − void tSampler_freeFromPool (tSampler* const, tMempool* const); | |
| 128 | − | |
| 129 | − float tSampler_tick (tSampler* const); | |
| 130 | − | |
| 131 | − void tSampler_setSample (tSampler* const, tBuffer* const); | |
| 132 | − | |
| 133 | − void tSampler_setMode (tSampler* const, PlayMode mode); | |
| 134 | − | |
| 135 | − void tSampler_play (tSampler* const); | |
| 136 | − void tSampler_stop (tSampler* const); | |
| 137 | − | |
| 138 | − void tSampler_setStart (tSampler* const, int32_t start); | |
| 139 | − void tSampler_setEnd (tSampler* const, int32_t end); | |
| 140 | − void tSampler_setLength (tSampler* const, int32_t length); | |
| 141 | − | |
| 142 | − void tSampler_setCrossfadeLength (tSampler* const sp, uint32_t length); | |
| 143 | − | |
| 144 | − void tSampler_setRate (tSampler* const, float rate); | |
| 145 | − | |
| 146 | − //============================================================================== | |
| 147 | − | |
| 148 | − typedef struct _tAutoSampler | |
| 149 | − { | |
| 150 | − tSampler sampler; | |
| 151 | − tEnvelopeFollower ef; | |
| 152 | − uint32_t windowSize; | |
| 153 | − float threshold; | |
| 154 | − float previousPower; | |
| 155 | − uint32_t sampleCounter; | |
| 156 | − uint32_t powerCounter; | |
| 157 | − uint8_t sampleTriggered; | |
| 158 | − } _tAutoSampler; | |
| 159 | − | |
| 160 | − typedef _tAutoSampler* tAutoSampler; | |
| 161 | − | |
| 162 | − void tAutoSampler_init (tAutoSampler* const, tBuffer* const); | |
| 163 | − void tAutoSampler_free (tAutoSampler* const); | |
| 164 | − void tAutoSampler_initToPool (tAutoSampler* const, tBuffer* const, tMempool* const); | |
| 165 | − void tAutoSampler_freeFromPool (tAutoSampler* const, tMempool* const); | |
| 166 | − | |
| 167 | − float tAutoSampler_tick (tAutoSampler* const, float input); | |
| 168 | − | |
| 169 | − void tAutoSampler_setBuffer (tAutoSampler* const, tBuffer* const); | |
| 170 | − | |
| 171 | − void tAutoSampler_setMode (tAutoSampler* const, PlayMode mode); | |
| 172 | − | |
| 173 | − void tAutoSampler_play (tAutoSampler* const); | |
| 174 | − void tAutoSampler_stop (tAutoSampler* const); | |
| 175 | − | |
| 176 | − void tAutoSampler_setThreshold (tAutoSampler* const, float thresh); | |
| 177 | − void tAutoSampler_setWindowSize (tAutoSampler* const, uint32_t size); | |
| 178 | − void tAutoSampler_setCrossfadeLength (tAutoSampler* const, uint32_t length); | |
| 179 | − | |
| 180 | − void tAutoSampler_setRate (tAutoSampler* const, float rate); | |
| 181 | − | |
| 182 | −#ifdef __cplusplus | |
| 183 | −} | |
| 184 | −#endif | |
| 185 | − | |
| 186 | −#endif // LEAF_SAMPLING_H_INCLUDED | |
| 187 | − | |
| 188 | −//============================================================================== | |
| @@ -1,104 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-tables.h | |
| 4 | − Created: 4 Dec 2016 9:42:41pm | |
| 5 | − Author: Michael R Mulshine | |
| 6 | − | |
| 7 | −==============================================================================*/ | |
| 8 | − | |
| 9 | −#ifndef LEAF_TABLES_H_INCLUDED | |
| 10 | −#define LEAF_TABLES_H_INCLUDED | |
| 11 | − | |
| 12 | −#ifdef __cplusplus | |
| 13 | −extern "C" { | |
| 14 | −#endif | |
| 15 | − | |
| 16 | −//============================================================================== | |
| 17 | − | |
| 18 | −#include "leaf-math.h" | |
| 19 | − | |
| 20 | −//============================================================================== | |
| 21 | − | |
| 22 | −#define USE_SAWTOOTH_TABLE 1 | |
| 23 | −#define USE_SQUARE_TABLE 1 | |
| 24 | −#define USE_TRIANGLE_TABLE 1 | |
| 25 | −#define USE_SHAPER_TABLE 1 | |
| 26 | − | |
| 27 | −#define SINE_TABLE_SIZE 2048 | |
| 28 | −#define SAW_TABLE_SIZE 2048 | |
| 29 | −#define SQR_TABLE_SIZE 2048 | |
| 30 | −#define TRI_TABLE_SIZE 2048 | |
| 31 | −#define EXP_DECAY_TABLE_SIZE 65536 | |
| 32 | −#define ATTACK_DECAY_INC_TABLE_SIZE 65536 | |
| 33 | −#define TANH1_TABLE_SIZE 65536 | |
| 34 | −#define DECAY_COEFF_TABLE_SIZE 4096 | |
| 35 | −#define MTOF1_TABLE_SIZE 4096 | |
| 36 | −#define FILTERTAN_TABLE_SIZE 4096 | |
| 37 | − | |
| 38 | −#define SHAPER1_TABLE_SIZE 65536 | |
| 39 | −extern const float __leaf_table_shaper1[SHAPER1_TABLE_SIZE]; | |
| 40 | − | |
| 41 | −#define COEFFS_SIZE 32 | |
| 42 | −extern const float* __leaf_tableref_firCoeffs[COEFFS_SIZE]; | |
| 43 | −extern const float __leaf_tablesize_firNumTaps[COEFFS_SIZE]; | |
| 44 | −extern const float __leaf_table_fir2XLow[32]; | |
| 45 | −extern const float __leaf_table_fir4XLow[64]; | |
| 46 | −extern const float __leaf_table_fir8XLow[64]; | |
| 47 | −extern const float __leaf_table_fir16XLow[128]; | |
| 48 | −extern const float __leaf_table_fir32XLow[256]; | |
| 49 | −extern const float __leaf_table_fir64XLow[256]; | |
| 50 | −extern const float __leaf_table_fir2XHigh[128]; | |
| 51 | −extern const float __leaf_table_fir4XHigh[256]; | |
| 52 | −extern const float __leaf_table_fir8XHigh[256]; | |
| 53 | −extern const float __leaf_table_fir16XHigh[512]; | |
| 54 | −extern const float __leaf_table_fir32XHigh[512]; | |
| 55 | −extern const float __leaf_table_fir64XHigh[1024]; | |
| 56 | − | |
| 57 | −typedef enum TableName | |
| 58 | −{ | |
| 59 | − T20 = 0, | |
| 60 | − T40, | |
| 61 | − T80, | |
| 62 | − T160, | |
| 63 | − T320, | |
| 64 | − T640, | |
| 65 | − T1280, | |
| 66 | − T2560, | |
| 67 | − T5120, | |
| 68 | − T10240, | |
| 69 | − T20480, | |
| 70 | − TableNameNil | |
| 71 | −} TableName; | |
| 72 | − | |
| 73 | −// mtof lookup table based on input range [0.0,1.0) in 4096 increments - midi frequency values scaled between m25 and m134 (from the Snyderphonics DrumBox code) | |
| 74 | − | |
| 75 | −extern const float __leaf_table_exp_decay[EXP_DECAY_TABLE_SIZE]; | |
| 76 | −extern const float __leaf_table_attack_decay_inc[ATTACK_DECAY_INC_TABLE_SIZE]; | |
| 77 | − | |
| 78 | −extern const float __leaf_table_filtertan[FILTERTAN_TABLE_SIZE]; | |
| 79 | − | |
| 80 | −extern const float __leaf_table_mtof1[MTOF1_TABLE_SIZE]; | |
| 81 | −extern const float __leaf_table_decayCoeffTable[DECAY_COEFF_TABLE_SIZE]; | |
| 82 | − | |
| 83 | −extern const float __leaf_table_tanh1[TANH1_TABLE_SIZE]; | |
| 84 | − | |
| 85 | −//============================================================================== | |
| 86 | − | |
| 87 | −/* Sine wave table ripped from http://aquaticus.info/pwm-sine-wave. */ | |
| 88 | −extern const float __leaf_table_sinewave[SINE_TABLE_SIZE]; | |
| 89 | − | |
| 90 | −extern const float __leaf_table_sawtooth[11][SAW_TABLE_SIZE]; | |
| 91 | − | |
| 92 | −extern const float __leaf_table_triangle[11][TRI_TABLE_SIZE]; | |
| 93 | − | |
| 94 | −extern const float __leaf_table_squarewave[11][SQR_TABLE_SIZE]; | |
| 95 | − | |
| 96 | −//============================================================================== | |
| 97 | − | |
| 98 | −#ifdef __cplusplus | |
| 99 | −} | |
| 100 | −#endif | |
| 101 | − | |
| 102 | −#endif // LEAF_TABLES_H_INCLUDED | |
| 103 | − | |
| 104 | −//============================================================================== | |
| @@ -1,1054 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-analysis.c | |
| 4 | − Created: 30 Nov 2018 11:56:49am | |
| 5 | − Author: airship | |
| 6 | − | |
| 7 | −==============================================================================*/ | |
| 8 | − | |
| 9 | −#if _WIN32 || _WIN64 | |
| 10 | − | |
| 11 | −#include "..\Inc\leaf-analysis.h" | |
| 12 | −#include "..\Externals\d_fft_mayer.h" | |
| 13 | − | |
| 14 | −#else | |
| 15 | − | |
| 16 | −#include "../Inc/leaf-analysis.h" | |
| 17 | −#include "../Externals/d_fft_mayer.h" | |
| 18 | − | |
| 19 | −#endif | |
| 20 | − | |
| 21 | −//=========================================================================== | |
| 22 | −/* Envelope Follower */ | |
| 23 | −//=========================================================================== | |
| 24 | − | |
| 25 | −void tEnvelopeFollower_init(tEnvelopeFollower* const ef, float attackThreshold, float decayCoeff) | |
| 26 | −{ | |
| 27 | − _tEnvelopeFollower* e = *ef = (_tEnvelopeFollower*) leaf_alloc(sizeof(_tEnvelopeFollower)); | |
| 28 | − | |
| 29 | − e->y = 0.0f; | |
| 30 | − e->a_thresh = attackThreshold; | |
| 31 | − e->d_coeff = decayCoeff; | |
| 32 | −} | |
| 33 | − | |
| 34 | −void tEnvelopeFollower_free(tEnvelopeFollower* const ef) | |
| 35 | −{ | |
| 36 | − _tEnvelopeFollower* e = *ef; | |
| 37 | − | |
| 38 | − leaf_free((char*)e); | |
| 39 | −} | |
| 40 | − | |
| 41 | −void tEnvelopeFollower_initToPool (tEnvelopeFollower* const ef, float attackThreshold, float decayCoeff, tMempool* const mp) | |
| 42 | −{ | |
| 43 | − _tMempool* m = *mp; | |
| 44 | − _tEnvelopeFollower* e = *ef = (_tEnvelopeFollower*) mpool_alloc(sizeof(_tEnvelopeFollower), m); | |
| 45 | − | |
| 46 | − e->y = 0.0f; | |
| 47 | − e->a_thresh = attackThreshold; | |
| 48 | − e->d_coeff = decayCoeff; | |
| 49 | −} | |
| 50 | − | |
| 51 | −void tEnvelopeFollower_freeFromPool (tEnvelopeFollower* const ef, tMempool* const mp) | |
| 52 | −{ | |
| 53 | − _tMempool* m = *mp; | |
| 54 | − _tEnvelopeFollower* e = *ef; | |
| 55 | − | |
| 56 | − mpool_free((char*)e, m); | |
| 57 | −} | |
| 58 | − | |
| 59 | −float tEnvelopeFollower_tick(tEnvelopeFollower* const ef, float x) | |
| 60 | −{ | |
| 61 | − _tEnvelopeFollower* e = *ef; | |
| 62 | − | |
| 63 | − if (x < 0.0f ) x = -x; /* Absolute value. */ | |
| 64 | − | |
| 65 | − if ((x >= e->y) && (x > e->a_thresh)) e->y = x; /* If we hit a peak, ride the peak to the top. */ | |
| 66 | − else e->y = e->y * e->d_coeff; /* Else, exponential decay of output. */ | |
| 67 | − | |
| 68 | − //ef->y = envelope_pow[(uint16_t)(ef->y * (float)UINT16_MAX)] * ef->d_coeff; //not quite the right behavior - too much loss of precision? | |
| 69 | − //ef->y = powf(ef->y, 1.000009f) * ef->d_coeff; // too expensive | |
| 70 | − | |
| 71 | − if( e->y < VSF) e->y = 0.0f; | |
| 72 | − | |
| 73 | − return e->y; | |
| 74 | −} | |
| 75 | − | |
| 76 | −int tEnvelopeFollower_decayCoeff(tEnvelopeFollower* const ef, float decayCoeff) | |
| 77 | −{ | |
| 78 | − _tEnvelopeFollower* e = *ef; | |
| 79 | − return e->d_coeff = decayCoeff; | |
| 80 | −} | |
| 81 | − | |
| 82 | −int tEnvelopeFollower_attackThresh(tEnvelopeFollower* const ef, float attackThresh) | |
| 83 | −{ | |
| 84 | − _tEnvelopeFollower* e = *ef; | |
| 85 | − return e->a_thresh = attackThresh; | |
| 86 | −} | |
| 87 | − | |
| 88 | − | |
| 89 | − | |
| 90 | − | |
| 91 | − | |
| 92 | −// zero crossing detector | |
| 93 | − | |
| 94 | −void tZeroCrossing_init (tZeroCrossing* const zc, int maxWindowSize) | |
| 95 | −{ | |
| 96 | − tZeroCrossing_initToPool (zc, maxWindowSize, &leaf.mempool); | |
| 97 | −} | |
| 98 | −void tZeroCrossing_free (tZeroCrossing* const zc) | |
| 99 | −{ | |
| 100 | − tZeroCrossing_freeFromPool (zc, &leaf.mempool); | |
| 101 | −} | |
| 102 | −void tZeroCrossing_initToPool (tZeroCrossing* const zc, int maxWindowSize, tMempool* const mp) | |
| 103 | −{ | |
| 104 | − _tMempool* m = *mp; | |
| 105 | − _tZeroCrossing* z = *zc = (_tZeroCrossing*) mpool_alloc(sizeof(_tZeroCrossing), m); | |
| 106 | − | |
| 107 | − z->count = 0; | |
| 108 | − z->maxWindowSize = maxWindowSize; | |
| 109 | − z->currentWindowSize = maxWindowSize; | |
| 110 | − z->invCurrentWindowSize = 1.0f / maxWindowSize; | |
| 111 | − z->position = 0; | |
| 112 | − z->prevPosition = maxWindowSize; | |
| 113 | − z->inBuffer = (float*) mpool_calloc(sizeof(float) * maxWindowSize, m); | |
| 114 | − z->countBuffer = (uint16_t*) mpool_calloc(sizeof(uint16_t) * maxWindowSize, m); | |
| 115 | −} | |
| 116 | − | |
| 117 | −void tZeroCrossing_freeFromPool (tZeroCrossing* const zc, tMempool* const mp) | |
| 118 | −{ | |
| 119 | − _tMempool* m = *mp; | |
| 120 | − _tZeroCrossing* z = *zc; | |
| 121 | − mpool_free((char*)z->inBuffer, m); | |
| 122 | − mpool_free((char*)z->countBuffer, m); | |
| 123 | − mpool_free((char*)z, m); | |
| 124 | −} | |
| 125 | − | |
| 126 | −//returns proportion of zero crossings within window size (0.0 would be none in window, 1.0 would be all zero crossings) | |
| 127 | −float tZeroCrossing_tick (tZeroCrossing* const zc, float input) | |
| 128 | −{ | |
| 129 | − _tZeroCrossing* z = *zc; | |
| 130 | − | |
| 131 | − z->inBuffer[z->position] = input; | |
| 132 | − int futurePosition = ((z->position + 1) % z->currentWindowSize); | |
| 133 | − float output = 0.0f; | |
| 134 | − | |
| 135 | − //add new value to count | |
| 136 | − if ((z->inBuffer[z->position] * z->inBuffer[z->prevPosition]) < 0.0f) | |
| 137 | − { | |
| 138 | − //zero crossing happened, add it to the count array | |
| 139 | − z->countBuffer[z->position] = 1; | |
| 140 | − z->count++; | |
| 141 | − } | |
| 142 | − else | |
| 143 | − { | |
| 144 | − z->countBuffer[z->position] = 0; | |
| 145 | − } | |
| 146 | − | |
| 147 | − //remove oldest value from count | |
| 148 | − if (z->countBuffer[futurePosition] > 0) | |
| 149 | − { | |
| 150 | − z->count--; | |
| 151 | − if (z->count < 0) | |
| 152 | − { | |
| 153 | − z->count = 0; | |
| 154 | − } | |
| 155 | − } | |
| 156 | − | |
| 157 | − z->prevPosition = z->position; | |
| 158 | − z->position = futurePosition; | |
| 159 | − | |
| 160 | − output = z->count * z->invCurrentWindowSize; | |
| 161 | − | |
| 162 | − return output; | |
| 163 | −} | |
| 164 | − | |
| 165 | − | |
| 166 | −void tZeroCrossing_setWindow (tZeroCrossing* const zc, float windowSize) | |
| 167 | −{ | |
| 168 | − _tZeroCrossing* z = *zc; | |
| 169 | − if (windowSize <= z->maxWindowSize) | |
| 170 | − { | |
| 171 | − z->currentWindowSize = windowSize; | |
| 172 | − } | |
| 173 | − else | |
| 174 | − { | |
| 175 | − z->currentWindowSize = z->maxWindowSize; | |
| 176 | − } | |
| 177 | − z->invCurrentWindowSize = 1.0f / z->currentWindowSize; | |
| 178 | −} | |
| 179 | − | |
| 180 | − | |
| 181 | − | |
| 182 | − | |
| 183 | − | |
| 184 | −//=========================================================================== | |
| 185 | −/* Power Follower */ | |
| 186 | −//=========================================================================== | |
| 187 | −void tPowerFollower_init(tPowerFollower* const pf, float factor) | |
| 188 | −{ | |
| 189 | − _tPowerFollower* p = *pf = (_tPowerFollower*) leaf_alloc(sizeof(_tPowerFollower)); | |
| 190 | − | |
| 191 | − p->curr=0.0f; | |
| 192 | − p->factor=factor; | |
| 193 | − p->oneminusfactor=1.0f-factor; | |
| 194 | −} | |
| 195 | − | |
| 196 | −void tPowerFollower_free(tPowerFollower* const pf) | |
| 197 | −{ | |
| 198 | − _tPowerFollower* p = *pf; | |
| 199 | − | |
| 200 | − leaf_free((char*)p); | |
| 201 | −} | |
| 202 | − | |
| 203 | −void tPowerFollower_initToPool (tPowerFollower* const pf, float factor, tMempool* const mp) | |
| 204 | −{ | |
| 205 | − _tMempool* m = *mp; | |
| 206 | − _tPowerFollower* p = *pf = (_tPowerFollower*) mpool_alloc(sizeof(_tPowerFollower), m); | |
| 207 | − | |
| 208 | − p->curr=0.0f; | |
| 209 | − p->factor=factor; | |
| 210 | − p->oneminusfactor=1.0f-factor; | |
| 211 | −} | |
| 212 | − | |
| 213 | −void tPowerFollower_freeFromPool (tPowerFollower* const pf, tMempool* const mp) | |
| 214 | −{ | |
| 215 | − _tMempool* m = *mp; | |
| 216 | − _tPowerFollower* p = *pf; | |
| 217 | − | |
| 218 | − mpool_free((char*)p, m); | |
| 219 | −} | |
| 220 | − | |
| 221 | −int tPowerFollower_setFactor(tPowerFollower* const pf, float factor) | |
| 222 | −{ | |
| 223 | − _tPowerFollower* p = *pf; | |
| 224 | − | |
| 225 | − if (factor<0) factor=0; | |
| 226 | − if (factor>1) factor=1; | |
| 227 | − p->factor=factor; | |
| 228 | − p->oneminusfactor=1.0f-factor; | |
| 229 | − return 0; | |
| 230 | −} | |
| 231 | − | |
| 232 | −float tPowerFollower_tick(tPowerFollower* const pf, float input) | |
| 233 | −{ | |
| 234 | − _tPowerFollower* p = *pf; | |
| 235 | − p->curr = p->factor*input*input+p->oneminusfactor*p->curr; | |
| 236 | − return p->curr; | |
| 237 | −} | |
| 238 | − | |
| 239 | −float tPowerFollower_sample(tPowerFollower* const pf) | |
| 240 | −{ | |
| 241 | − _tPowerFollower* p = *pf; | |
| 242 | − return p->curr; | |
| 243 | −} | |
| 244 | − | |
| 245 | − | |
| 246 | − | |
| 247 | − | |
| 248 | −//=========================================================================== | |
| 249 | −/* ---------------- env~ - simple envelope follower. ----------------- */ | |
| 250 | −//=========================================================================== | |
| 251 | − | |
| 252 | −void tEnvPD_init(tEnvPD* const xpd, int ws, int hs, int bs) | |
| 253 | −{ | |
| 254 | − _tEnvPD* x = *xpd = (_tEnvPD*) leaf_calloc(sizeof(_tEnvPD)); | |
| 255 | − | |
| 256 | − int period = hs, npoints = ws; | |
| 257 | − | |
| 258 | − int i; | |
| 259 | − | |
| 260 | − if (npoints < 1) npoints = 1024; | |
| 261 | − if (period < 1) period = npoints/2; | |
| 262 | − if (period < npoints / MAXOVERLAP + 1) | |
| 263 | − period = npoints / MAXOVERLAP + 1; | |
| 264 | − | |
| 265 | − x->x_npoints = npoints; | |
| 266 | − x->x_phase = 0; | |
| 267 | − x->x_period = period; | |
| 268 | − | |
| 269 | − x->windowSize = npoints; | |
| 270 | − x->hopSize = period; | |
| 271 | − x->blockSize = bs; | |
| 272 | − | |
| 273 | − for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0.0f; | |
| 274 | − for (i = 0; i < npoints; i++) | |
| 275 | − x->buf[i] = (1.0f - cosf((TWO_PI * i) / npoints))/npoints; | |
| 276 | − for (; i < npoints+INITVSTAKEN; i++) x->buf[i] = 0.0f; | |
| 277 | − | |
| 278 | − x->x_f = 0.0f; | |
| 279 | − | |
| 280 | − x->x_allocforvs = INITVSTAKEN; | |
| 281 | − | |
| 282 | − // ~ ~ ~ dsp ~ ~ ~ | |
| 283 | − if (x->x_period % x->blockSize) | |
| 284 | − { | |
| 285 | − x->x_realperiod = x->x_period + x->blockSize - (x->x_period % x->blockSize); | |
| 286 | − } | |
| 287 | − else | |
| 288 | − { | |
| 289 | − x->x_realperiod = x->x_period; | |
| 290 | − } | |
| 291 | − // ~ ~ ~ ~ ~ ~ ~ ~ | |
| 292 | −} | |
| 293 | − | |
| 294 | −void tEnvPD_free (tEnvPD* const xpd) | |
| 295 | −{ | |
| 296 | − _tEnvPD* x = *xpd; | |
| 297 | − | |
| 298 | − leaf_free((char*)x); | |
| 299 | −} | |
| 300 | − | |
| 301 | −void tEnvPD_initToPool (tEnvPD* const xpd, int ws, int hs, int bs, tMempool* const mp) | |
| 302 | −{ | |
| 303 | − _tMempool* m = *mp; | |
| 304 | − _tEnvPD* x = *xpd = (_tEnvPD*) mpool_calloc(sizeof(_tEnvPD), m); | |
| 305 | − | |
| 306 | − int period = hs, npoints = ws; | |
| 307 | − | |
| 308 | − int i; | |
| 309 | − | |
| 310 | − if (npoints < 1) npoints = 1024; | |
| 311 | − if (period < 1) period = npoints/2; | |
| 312 | − if (period < npoints / MAXOVERLAP + 1) | |
| 313 | − period = npoints / MAXOVERLAP + 1; | |
| 314 | − | |
| 315 | − x->x_npoints = npoints; | |
| 316 | − x->x_phase = 0; | |
| 317 | − x->x_period = period; | |
| 318 | − | |
| 319 | − x->windowSize = npoints; | |
| 320 | − x->hopSize = period; | |
| 321 | − x->blockSize = bs; | |
| 322 | − | |
| 323 | − for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0; | |
| 324 | − for (i = 0; i < npoints; i++) | |
| 325 | − x->buf[i] = (1.0f - cosf((2 * PI * i) / npoints))/npoints; | |
| 326 | − for (; i < npoints+INITVSTAKEN; i++) x->buf[i] = 0; | |
| 327 | − | |
| 328 | − x->x_f = 0; | |
| 329 | − | |
| 330 | − x->x_allocforvs = INITVSTAKEN; | |
| 331 | − | |
| 332 | − // ~ ~ ~ dsp ~ ~ ~ | |
| 333 | − if (x->x_period % x->blockSize) | |
| 334 | − { | |
| 335 | − x->x_realperiod = x->x_period + x->blockSize - (x->x_period % x->blockSize); | |
| 336 | − } | |
| 337 | − else | |
| 338 | − { | |
| 339 | − x->x_realperiod = x->x_period; | |
| 340 | − } | |
| 341 | − // ~ ~ ~ ~ ~ ~ ~ ~ | |
| 342 | −} | |
| 343 | − | |
| 344 | −void tEnvPD_freeFromPool (tEnvPD* const xpd, tMempool* const mp) | |
| 345 | −{ | |
| 346 | − _tMempool* m = *mp; | |
| 347 | − _tEnvPD* x = *xpd; | |
| 348 | − | |
| 349 | − mpool_free((char*)x, m); | |
| 350 | −} | |
| 351 | − | |
| 352 | −float tEnvPD_tick (tEnvPD* const xpd) | |
| 353 | −{ | |
| 354 | − _tEnvPD* x = *xpd; | |
| 355 | − return powtodb(x->x_result); | |
| 356 | −} | |
| 357 | − | |
| 358 | −void tEnvPD_processBlock(tEnvPD* const xpd, float* in) | |
| 359 | −{ | |
| 360 | − _tEnvPD* x = *xpd; | |
| 361 | − | |
| 362 | − int n = x->blockSize; | |
| 363 | − | |
| 364 | − int count; | |
| 365 | − t_sample *sump; | |
| 366 | − in += n; | |
| 367 | − for (count = x->x_phase, sump = x->x_sumbuf; | |
| 368 | − count < x->x_npoints; count += x->x_realperiod, sump++) | |
| 369 | − { | |
| 370 | − t_sample *hp = x->buf + count; | |
| 371 | − t_sample *fp = in; | |
| 372 | − t_sample sum = *sump; | |
| 373 | − int i; | |
| 374 | − | |
| 375 | − for (i = 0; i < n; i++) | |
| 376 | − { | |
| 377 | − fp--; | |
| 378 | − sum += *hp++ * (*fp * *fp); | |
| 379 | − } | |
| 380 | − *sump = sum; | |
| 381 | − } | |
| 382 | − sump[0] = 0; | |
| 383 | − x->x_phase -= n; | |
| 384 | − if (x->x_phase < 0) | |
| 385 | − { | |
| 386 | − x->x_result = x->x_sumbuf[0]; | |
| 387 | − for (count = x->x_realperiod, sump = x->x_sumbuf; | |
| 388 | − count < x->x_npoints; count += x->x_realperiod, sump++) | |
| 389 | − sump[0] = sump[1]; | |
| 390 | − sump[0] = 0; | |
| 391 | − x->x_phase = x->x_realperiod - n; | |
| 392 | − } | |
| 393 | −} | |
| 394 | − | |
| 395 | −//=========================================================================== | |
| 396 | −// ATTACKDETECTION | |
| 397 | −//=========================================================================== | |
| 398 | −/********Private function prototypes**********/ | |
| 399 | −static void atkdtk_init(tAttackDetection* const a, int blocksize, int atk, int rel); | |
| 400 | −static void atkdtk_envelope(tAttackDetection* const a, float *in); | |
| 401 | − | |
| 402 | −/********Constructor/Destructor***************/ | |
| 403 | − | |
| 404 | −void tAttackDetection_init(tAttackDetection* const ad, int blocksize, int atk, int rel) | |
| 405 | −{ | |
| 406 | − *ad = (_tAttackDetection*) leaf_alloc(sizeof(_tAttackDetection)); | |
| 407 | − | |
| 408 | − atkdtk_init(ad, blocksize, atk, rel); | |
| 409 | −} | |
| 410 | − | |
| 411 | −void tAttackDetection_free(tAttackDetection* const ad) | |
| 412 | −{ | |
| 413 | − _tAttackDetection* a = *ad; | |
| 414 | − | |
| 415 | − leaf_free((char*)a); | |
| 416 | −} | |
| 417 | − | |
| 418 | −void tAttackDetection_initToPool (tAttackDetection* const ad, int blocksize, int atk, int rel, tMempool* const mp) | |
| 419 | −{ | |
| 420 | − _tMempool* m = *mp; | |
| 421 | − *ad = (_tAttackDetection*) mpool_alloc(sizeof(_tAttackDetection), m); | |
| 422 | − | |
| 423 | − atkdtk_init(ad, blocksize, atk, rel); | |
| 424 | −} | |
| 425 | − | |
| 426 | −void tAttackDetection_freeFromPool (tAttackDetection* const ad, tMempool* const mp) | |
| 427 | −{ | |
| 428 | − _tMempool* m = *mp; | |
| 429 | − _tAttackDetection* a = *ad; | |
| 430 | − | |
| 431 | − mpool_free((char*)a, m); | |
| 432 | −} | |
| 433 | − | |
| 434 | −/*******Public Functions***********/ | |
| 435 | − | |
| 436 | − | |
| 437 | −void tAttackDetection_setBlocksize(tAttackDetection* const ad, int size) | |
| 438 | −{ | |
| 439 | − _tAttackDetection* a = *ad; | |
| 440 | − | |
| 441 | − if(!((size==64)|(size==128)|(size==256)|(size==512)|(size==1024)|(size==2048))) | |
| 442 | − size = DEFBLOCKSIZE; | |
| 443 | − a->blocksize = size; | |
| 444 | − | |
| 445 | − return; | |
| 446 | − | |
| 447 | −} | |
| 448 | − | |
| 449 | −void tAttackDetection_setSamplerate(tAttackDetection* const ad, int inRate) | |
| 450 | −{ | |
| 451 | − _tAttackDetection* a = *ad; | |
| 452 | − | |
| 453 | − a->samplerate = inRate; | |
| 454 | − | |
| 455 | − //Reset atk and rel to recalculate coeff | |
| 456 | − tAttackDetection_setAttack(ad, a->atk); | |
| 457 | − tAttackDetection_setRelease(ad, a->rel); | |
| 458 | −} | |
| 459 | − | |
| 460 | −void tAttackDetection_setThreshold(tAttackDetection* const ad, float thres) | |
| 461 | −{ | |
| 462 | − _tAttackDetection* a = *ad; | |
| 463 | − a->threshold = thres; | |
| 464 | −} | |
| 465 | − | |
| 466 | −void tAttackDetection_setAttack(tAttackDetection* const ad, int inAtk) | |
| 467 | −{ | |
| 468 | − _tAttackDetection* a = *ad; | |
| 469 | − a->atk = inAtk; | |
| 470 | − a->atk_coeff = pow(0.01, 1.0/(a->atk * a->samplerate * 0.001)); | |
| 471 | −} | |
| 472 | − | |
| 473 | −void tAttackDetection_setRelease(tAttackDetection* const ad, int inRel) | |
| 474 | −{ | |
| 475 | − _tAttackDetection* a = *ad; | |
| 476 | − a->rel = inRel; | |
| 477 | − a->rel_coeff = pow(0.01, 1.0/(a->rel * a->samplerate * 0.001)); | |
| 478 | −} | |
| 479 | − | |
| 480 | − | |
| 481 | −int tAttackDetection_detect(tAttackDetection* const ad, float *in) | |
| 482 | −{ | |
| 483 | − _tAttackDetection* a = *ad; | |
| 484 | − | |
| 485 | − int result; | |
| 486 | − | |
| 487 | − atkdtk_envelope(ad, in); | |
| 488 | − | |
| 489 | − if(a->env >= a->prevAmp*2) //2 times greater = 6dB increase | |
| 490 | − result = 1; | |
| 491 | − else | |
| 492 | − result = 0; | |
| 493 | − | |
| 494 | − a->prevAmp = a->env; | |
| 495 | − | |
| 496 | − return result; | |
| 497 | −} | |
| 498 | − | |
| 499 | −/*******Private Functions**********/ | |
| 500 | − | |
| 501 | −static void atkdtk_init(tAttackDetection* const ad, int blocksize, int atk, int rel) | |
| 502 | −{ | |
| 503 | − _tAttackDetection* a = *ad; | |
| 504 | − | |
| 505 | − a->env = 0; | |
| 506 | − a->blocksize = blocksize; | |
| 507 | − a->threshold = DEFTHRESHOLD; | |
| 508 | − a->samplerate = leaf.sampleRate; | |
| 509 | − a->prevAmp = 0; | |
| 510 | − | |
| 511 | − a->env = 0; | |
| 512 | − | |
| 513 | − tAttackDetection_setAttack(ad, atk); | |
| 514 | − tAttackDetection_setRelease(ad, rel); | |
| 515 | −} | |
| 516 | − | |
| 517 | −static void atkdtk_envelope(tAttackDetection* const ad, float *in) | |
| 518 | −{ | |
| 519 | − _tAttackDetection* a = *ad; | |
| 520 | − | |
| 521 | − int i = 0; | |
| 522 | − float tmp; | |
| 523 | − for(i = 0; i < a->blocksize; ++i){ | |
| 524 | − tmp = fastabsf(in[i]); | |
| 525 | − | |
| 526 | − if(tmp > a->env) | |
| 527 | − a->env = a->atk_coeff * (a->env - tmp) + tmp; | |
| 528 | − else | |
| 529 | − a->env = a->rel_coeff * (a->env - tmp) + tmp; | |
| 530 | − } | |
| 531 | − | |
| 532 | −} | |
| 533 | − | |
| 534 | −//=========================================================================== | |
| 535 | −// SNAC | |
| 536 | −//=========================================================================== | |
| 537 | −/******************************************************************************/ | |
| 538 | −/***************************** private procedures *****************************/ | |
| 539 | −/******************************************************************************/ | |
| 540 | − | |
| 541 | −#define REALFFT mayer_realfft | |
| 542 | −#define REALIFFT mayer_realifft | |
| 543 | − | |
| 544 | −static void snac_analyzeframe(tSNAC* const s); | |
| 545 | −static void snac_autocorrelation(tSNAC* const s); | |
| 546 | −static void snac_normalize(tSNAC* const s); | |
| 547 | −static void snac_pickpeak(tSNAC* const s); | |
| 548 | −static void snac_periodandfidelity(tSNAC* const s); | |
| 549 | −static void snac_biasbuf(tSNAC* const s); | |
| 550 | −static float snac_spectralpeak(tSNAC* const s, float periodlength); | |
| 551 | − | |
| 552 | − | |
| 553 | −/******************************************************************************/ | |
| 554 | −/******************************** constructor, destructor *********************/ | |
| 555 | −/******************************************************************************/ | |
| 556 | − | |
| 557 | − | |
| 558 | −void tSNAC_init(tSNAC* const snac, int overlaparg) | |
| 559 | −{ | |
| 560 | − _tSNAC* s = *snac = (_tSNAC*) leaf_calloc(sizeof(_tSNAC)); | |
| 561 | − | |
| 562 | − s->biasfactor = DEFBIAS; | |
| 563 | − s->timeindex = 0; | |
| 564 | − s->periodindex = 0; | |
| 565 | − s->periodlength = 0.; | |
| 566 | − s->fidelity = 0.; | |
| 567 | − s->minrms = DEFMINRMS; | |
| 568 | − s->framesize = SNAC_FRAME_SIZE; | |
| 569 | − | |
| 570 | − s->inputbuf = (float*) leaf_calloc(sizeof(float) * SNAC_FRAME_SIZE); | |
| 571 | − s->processbuf = (float*) leaf_calloc(sizeof(float) * (SNAC_FRAME_SIZE * 2)); | |
| 572 | − s->spectrumbuf = (float*) leaf_calloc(sizeof(float) * (SNAC_FRAME_SIZE / 2)); | |
| 573 | − s->biasbuf = (float*) leaf_calloc(sizeof(float) * SNAC_FRAME_SIZE); | |
| 574 | − | |
| 575 | − snac_biasbuf(snac); | |
| 576 | − tSNAC_setOverlap(snac, overlaparg); | |
| 577 | −} | |
| 578 | − | |
| 579 | −void tSNAC_free(tSNAC* const snac) | |
| 580 | −{ | |
| 581 | − _tSNAC* s = *snac; | |
| 582 | − | |
| 583 | − leaf_free((char*)s->inputbuf); | |
| 584 | − leaf_free((char*)s->processbuf); | |
| 585 | − leaf_free((char*)s->spectrumbuf); | |
| 586 | − leaf_free((char*)s->biasbuf); | |
| 587 | − leaf_free((char*)s); | |
| 588 | −} | |
| 589 | − | |
| 590 | −void tSNAC_initToPool (tSNAC* const snac, int overlaparg, tMempool* const mp) | |
| 591 | −{ | |
| 592 | − _tMempool* m = *mp; | |
| 593 | − _tSNAC* s = *snac = (_tSNAC*) mpool_alloc(sizeof(_tSNAC), m); | |
| 594 | − | |
| 595 | − s->biasfactor = DEFBIAS; | |
| 596 | − s->timeindex = 0; | |
| 597 | − s->periodindex = 0; | |
| 598 | − s->periodlength = 0.; | |
| 599 | − s->fidelity = 0.; | |
| 600 | − s->minrms = DEFMINRMS; | |
| 601 | − s->framesize = SNAC_FRAME_SIZE; | |
| 602 | − | |
| 603 | − s->inputbuf = (float*) mpool_calloc(sizeof(float) * SNAC_FRAME_SIZE, m); | |
| 604 | − s->processbuf = (float*) mpool_calloc(sizeof(float) * (SNAC_FRAME_SIZE * 2), m); | |
| 605 | − s->spectrumbuf = (float*) mpool_calloc(sizeof(float) * (SNAC_FRAME_SIZE / 2), m); | |
| 606 | − s->biasbuf = (float*) mpool_calloc(sizeof(float) * SNAC_FRAME_SIZE, m); | |
| 607 | − | |
| 608 | − snac_biasbuf(snac); | |
| 609 | − tSNAC_setOverlap(snac, overlaparg); | |
| 610 | −} | |
| 611 | − | |
| 612 | −void tSNAC_freeFromPool (tSNAC* const snac, tMempool* const mp) | |
| 613 | −{ | |
| 614 | − _tMempool* m = *mp; | |
| 615 | − _tSNAC* s = *snac; | |
| 616 | − | |
| 617 | − mpool_free((char*)s->inputbuf, m); | |
| 618 | − mpool_free((char*)s->processbuf, m); | |
| 619 | − mpool_free((char*)s->spectrumbuf, m); | |
| 620 | − mpool_free((char*)s->biasbuf, m); | |
| 621 | − mpool_free((char*)s, m); | |
| 622 | −} | |
| 623 | − | |
| 624 | −/******************************************************************************/ | |
| 625 | −/************************** public access functions****************************/ | |
| 626 | −/******************************************************************************/ | |
| 627 | − | |
| 628 | − | |
| 629 | −void tSNAC_ioSamples(tSNAC* const snac, float *in, float *out, int size) | |
| 630 | −{ | |
| 631 | − _tSNAC* s = *snac; | |
| 632 | − | |
| 633 | − int timeindex = s->timeindex; | |
| 634 | − int mask = s->framesize - 1; | |
| 635 | − int outindex = 0; | |
| 636 | − float *inputbuf = s->inputbuf; | |
| 637 | − float *processbuf = s->processbuf; | |
| 638 | − | |
| 639 | − // call analysis function when it is time | |
| 640 | − if(!(timeindex & (s->framesize / s->overlap - 1))) snac_analyzeframe(snac); | |
| 641 | − | |
| 642 | − while(size--) | |
| 643 | − { | |
| 644 | − inputbuf[timeindex] = *in++; | |
| 645 | − out[outindex++] = processbuf[timeindex++]; | |
| 646 | − timeindex &= mask; | |
| 647 | − } | |
| 648 | − s->timeindex = timeindex; | |
| 649 | −} | |
| 650 | − | |
| 651 | −void tSNAC_setOverlap(tSNAC* const snac, int lap) | |
| 652 | −{ | |
| 653 | − _tSNAC* s = *snac; | |
| 654 | − if(!((lap==1)|(lap==2)|(lap==4)|(lap==8))) lap = DEFOVERLAP; | |
| 655 | − s->overlap = lap; | |
| 656 | −} | |
| 657 | − | |
| 658 | − | |
| 659 | −void tSNAC_setBias(tSNAC* const snac, float bias) | |
| 660 | −{ | |
| 661 | − _tSNAC* s = *snac; | |
| 662 | − if(bias > 1.) bias = 1.; | |
| 663 | − if(bias < 0.) bias = 0.; | |
| 664 | − s->biasfactor = bias; | |
| 665 | − snac_biasbuf(snac); | |
| 666 | − return; | |
| 667 | −} | |
| 668 | − | |
| 669 | − | |
| 670 | −void tSNAC_setMinRMS(tSNAC* const snac, float rms) | |
| 671 | −{ | |
| 672 | − _tSNAC* s = *snac; | |
| 673 | − if(rms > 1.) rms = 1.; | |
| 674 | − if(rms < 0.) rms = 0.; | |
| 675 | − s->minrms = rms; | |
| 676 | − return; | |
| 677 | −} | |
| 678 | − | |
| 679 | − | |
| 680 | −float tSNAC_getPeriod(tSNAC* const snac) | |
| 681 | −{ | |
| 682 | − _tSNAC* s = *snac; | |
| 683 | − return(s->periodlength); | |
| 684 | −} | |
| 685 | − | |
| 686 | − | |
| 687 | −float tSNAC_getFidelity(tSNAC* const snac) | |
| 688 | −{ | |
| 689 | − _tSNAC* s = *snac; | |
| 690 | − return(s->fidelity); | |
| 691 | −} | |
| 692 | − | |
| 693 | − | |
| 694 | −/******************************************************************************/ | |
| 695 | −/***************************** private procedures *****************************/ | |
| 696 | −/******************************************************************************/ | |
| 697 | − | |
| 698 | − | |
| 699 | −// main analysis function | |
| 700 | −static void snac_analyzeframe(tSNAC* const snac) | |
| 701 | −{ | |
| 702 | − _tSNAC* s = *snac; | |
| 703 | − | |
| 704 | − int n, tindex = s->timeindex; | |
| 705 | − int framesize = s->framesize; | |
| 706 | − int mask = framesize - 1; | |
| 707 | − float norm = 1. / sqrt((float)(framesize * 2)); | |
| 708 | − | |
| 709 | − float *inputbuf = s->inputbuf; | |
| 710 | − float *processbuf = s->processbuf; | |
| 711 | − | |
| 712 | − // copy input to processing buffers | |
| 713 | − for(n=0; n<framesize; n++) | |
| 714 | − { | |
| 715 | − processbuf[n] = inputbuf[tindex] * norm; | |
| 716 | − tindex++; | |
| 717 | − tindex &= mask; | |
| 718 | − } | |
| 719 | − | |
| 720 | − // zeropadding | |
| 721 | − for(n=framesize; n<(framesize<<1); n++) processbuf[n] = 0.; | |
| 722 | − | |
| 723 | − // call analysis procedures | |
| 724 | − snac_autocorrelation(snac); | |
| 725 | − snac_normalize(snac); | |
| 726 | − snac_pickpeak(snac); | |
| 727 | − snac_periodandfidelity(snac); | |
| 728 | −} | |
| 729 | − | |
| 730 | − | |
| 731 | −static void snac_autocorrelation(tSNAC* const snac) | |
| 732 | −{ | |
| 733 | − _tSNAC* s = *snac; | |
| 734 | − | |
| 735 | − int n, m; | |
| 736 | − int framesize = s->framesize; | |
| 737 | − int fftsize = framesize * 2; | |
| 738 | − float *processbuf = s->processbuf; | |
| 739 | − float *spectrumbuf = s->spectrumbuf; | |
| 740 | − | |
| 741 | − REALFFT(fftsize, processbuf); | |
| 742 | − | |
| 743 | − // compute power spectrum | |
| 744 | − processbuf[0] *= processbuf[0]; // DC | |
| 745 | − processbuf[framesize] *= processbuf[framesize]; // Nyquist | |
| 746 | − | |
| 747 | − for(n=1; n<framesize; n++) | |
| 748 | − { | |
| 749 | − processbuf[n] = processbuf[n] * processbuf[n] | |
| 750 | − + processbuf[fftsize-n] * processbuf[fftsize-n]; // imag coefficients appear reversed | |
| 751 | − processbuf[fftsize-n] = 0.; | |
| 752 | − } | |
| 753 | − | |
| 754 | − // store power spectrum up to SR/4 for possible later use | |
| 755 | − for(m=0; m<(framesize>>1); m++) | |
| 756 | − { | |
| 757 | − spectrumbuf[m] = processbuf[m]; | |
| 758 | − } | |
| 759 | − | |
| 760 | − // transform power spectrum to autocorrelation function | |
| 761 | − REALIFFT(fftsize, processbuf); | |
| 762 | − return; | |
| 763 | −} | |
| 764 | − | |
| 765 | − | |
| 766 | −static void snac_normalize(tSNAC* const snac) | |
| 767 | −{ | |
| 768 | − _tSNAC* s = *snac; | |
| 769 | − | |
| 770 | − int framesize = s->framesize; | |
| 771 | − int framesizeplustimeindex = s->framesize + s->timeindex; | |
| 772 | − int timeindexminusone = s->timeindex - 1; | |
| 773 | − int n, m; | |
| 774 | − int mask = framesize - 1; | |
| 775 | − int seek = framesize * SEEK; | |
| 776 | − float *inputbuf = s->inputbuf; | |
| 777 | − float *processbuf= s->processbuf; | |
| 778 | − float signal1, signal2; | |
| 779 | − | |
| 780 | − // minimum RMS implemented as minimum autocorrelation at index 0 | |
| 781 | − // functionally equivalent to white noise floor | |
| 782 | − float rms = s->minrms / sqrt(1.0f / (float)framesize); | |
| 783 | − float minrzero = rms * rms; | |
| 784 | − float rzero = processbuf[0]; | |
| 785 | − if(rzero < minrzero) rzero = minrzero; | |
| 786 | − double normintegral = (double)rzero * 2.; | |
| 787 | − | |
| 788 | − // normalize biased autocorrelation function | |
| 789 | − // inputbuf is circular buffer: timeindex may be non-zero when overlap > 1 | |
| 790 | − processbuf[0] = 1; | |
| 791 | − for(n=1, m=s->timeindex+1; n<seek; n++, m++) | |
| 792 | − { | |
| 793 | − signal1 = inputbuf[(n + timeindexminusone)&mask]; | |
| 794 | − signal2 = inputbuf[(framesizeplustimeindex - n)&mask]; | |
| 795 | − normintegral -= (double)(signal1 * signal1 + signal2 * signal2); | |
| 796 | − processbuf[n] /= (float)normintegral * 0.5f; | |
| 797 | − } | |
| 798 | − | |
| 799 | − // flush instable function tail | |
| 800 | − for(n = seek; n<framesize; n++) processbuf[n] = 0.; | |
| 801 | − return; | |
| 802 | −} | |
| 803 | − | |
| 804 | − | |
| 805 | −static void snac_periodandfidelity(tSNAC* const snac) | |
| 806 | −{ | |
| 807 | − _tSNAC* s = *snac; | |
| 808 | − | |
| 809 | − float periodlength; | |
| 810 | − | |
| 811 | − if(s->periodindex) | |
| 812 | − { | |
| 813 | − periodlength = (float)s->periodindex + | |
| 814 | − interpolate3phase(s->processbuf, s->periodindex); | |
| 815 | − if(periodlength < 8) periodlength = snac_spectralpeak(snac, periodlength); | |
| 816 | − s->periodlength = periodlength; | |
| 817 | − s->fidelity = interpolate3max(s->processbuf, s->periodindex); | |
| 818 | − } | |
| 819 | − return; | |
| 820 | −} | |
| 821 | − | |
| 822 | −// select the peak which most probably represents period length | |
| 823 | −static void snac_pickpeak(tSNAC* const snac) | |
| 824 | −{ | |
| 825 | − _tSNAC* s = *snac; | |
| 826 | − | |
| 827 | − int n, peakindex=0; | |
| 828 | − int seek = s->framesize * SEEK; | |
| 829 | − float *processbuf= s->processbuf; | |
| 830 | − float maxvalue = 0.; | |
| 831 | − float biasedpeak; | |
| 832 | − float *biasbuf = s->biasbuf; | |
| 833 | − | |
| 834 | − // skip main lobe | |
| 835 | − for(n=1; n<seek; n++) | |
| 836 | − { | |
| 837 | − if(processbuf[n] < 0.) break; | |
| 838 | − } | |
| 839 | − | |
| 840 | − // find interpolated / biased maximum in SNAC function | |
| 841 | − // interpolation finds the 'real maximum' | |
| 842 | − // biasing favours the first candidate | |
| 843 | − for(; n<seek-1; n++) | |
| 844 | − { | |
| 845 | − if(processbuf[n] >= processbuf[n-1]) | |
| 846 | − { | |
| 847 | − if(processbuf[n] > processbuf[n+1]) // we have a local peak | |
| 848 | − { | |
| 849 | − biasedpeak = interpolate3max(processbuf, n) * biasbuf[n]; | |
| 850 | − | |
| 851 | − if(biasedpeak > maxvalue) | |
| 852 | − { | |
| 853 | − maxvalue = biasedpeak; | |
| 854 | − peakindex = n; | |
| 855 | − } | |
| 856 | − } | |
| 857 | − } | |
| 858 | − } | |
| 859 | − s->periodindex = peakindex; | |
| 860 | − return; | |
| 861 | −} | |
| 862 | − | |
| 863 | − | |
| 864 | −// verify period length via frequency domain (up till SR/4) | |
| 865 | −// frequency domain is more precise than lag domain for period lengths < 8 | |
| 866 | −// argument 'periodlength' is initial estimation from autocorrelation | |
| 867 | −static float snac_spectralpeak(tSNAC* const snac, float periodlength) | |
| 868 | −{ | |
| 869 | − _tSNAC* s = *snac; | |
| 870 | − | |
| 871 | − if(periodlength < 4.0f) return periodlength; | |
| 872 | − | |
| 873 | − float max = 0.; | |
| 874 | − int n, startbin, stopbin, peakbin = 0; | |
| 875 | − int spectrumsize = s->framesize>>1; | |
| 876 | − float *spectrumbuf = s->spectrumbuf; | |
| 877 | − float peaklocation = (float)(s->framesize * 2.0f) / periodlength; | |
| 878 | − | |
| 879 | − startbin = (int)(peaklocation * 0.8f + 0.5f); | |
| 880 | − if(startbin < 1) startbin = 1; | |
| 881 | − stopbin = (int)(peaklocation * 1.25f + 0.5f); | |
| 882 | − if(stopbin >= spectrumsize - 1) stopbin = spectrumsize - 1; | |
| 883 | − | |
| 884 | − for(n=startbin; n<stopbin; n++) | |
| 885 | − { | |
| 886 | − if(spectrumbuf[n] >= spectrumbuf[n-1]) | |
| 887 | − { | |
| 888 | − if(spectrumbuf[n] > spectrumbuf[n+1]) | |
| 889 | − { | |
| 890 | − if(spectrumbuf[n] > max) | |
| 891 | − { | |
| 892 | − max = spectrumbuf[n]; | |
| 893 | − peakbin = n; | |
| 894 | − } | |
| 895 | − } | |
| 896 | − } | |
| 897 | − } | |
| 898 | − | |
| 899 | − // calculate amplitudes in peak region | |
| 900 | − for(n=(peakbin-1); n<(peakbin+2); n++) | |
| 901 | − { | |
| 902 | − spectrumbuf[n] = sqrtf(spectrumbuf[n]); | |
| 903 | − } | |
| 904 | − | |
| 905 | − peaklocation = (float)peakbin + interpolate3phase(spectrumbuf, peakbin); | |
| 906 | − periodlength = (float)(s->framesize * 2.0f) / peaklocation; | |
| 907 | − | |
| 908 | − return periodlength; | |
| 909 | −} | |
| 910 | − | |
| 911 | − | |
| 912 | −// modified logarithmic bias function | |
| 913 | −static void snac_biasbuf(tSNAC* const snac) | |
| 914 | −{ | |
| 915 | − _tSNAC* s = *snac; | |
| 916 | − | |
| 917 | − int n; | |
| 918 | − int maxperiod = (int)(s->framesize * (float)SEEK); | |
| 919 | − float bias = s->biasfactor / logf((float)(maxperiod - 4)); | |
| 920 | − float *biasbuf = s->biasbuf; | |
| 921 | − | |
| 922 | − for(n=0; n<5; n++) // periods < 5 samples can't be tracked | |
| 923 | − { | |
| 924 | − biasbuf[n] = 0.0f; | |
| 925 | − } | |
| 926 | − | |
| 927 | − for(n=5; n<maxperiod; n++) | |
| 928 | − { | |
| 929 | − biasbuf[n] = 1.0f - (float)logf(n - 4) * bias; | |
| 930 | − } | |
| 931 | −} | |
| 932 | − | |
| 933 | −//=========================================================================== | |
| 934 | −// PERIODDETECTION | |
| 935 | −//=========================================================================== | |
| 936 | −void tPeriodDetection_init (tPeriodDetection* const pd, float* in, float* out, int bufSize, int frameSize) | |
| 937 | −{ | |
| 938 | − tPeriodDetection_initToPool(pd, in, out, bufSize, frameSize, &leaf.mempool); | |
| 939 | −} | |
| 940 | − | |
| 941 | −void tPeriodDetection_free (tPeriodDetection* const pd) | |
| 942 | −{ | |
| 943 | − tPeriodDetection_freeFromPool(pd, &leaf.mempool); | |
| 944 | −} | |
| 945 | − | |
| 946 | −void tPeriodDetection_initToPool (tPeriodDetection* const pd, float* in, float* out, int bufSize, int frameSize, tMempool* const mp) | |
| 947 | −{ | |
| 948 | − _tMempool* m = *mp; | |
| 949 | − _tPeriodDetection* p = *pd = (_tPeriodDetection*) mpool_calloc(sizeof(_tPeriodDetection), m); | |
| 950 | − | |
| 951 | − p->inBuffer = in; | |
| 952 | − p->outBuffer = out; | |
| 953 | − p->bufSize = bufSize; | |
| 954 | − p->frameSize = frameSize; | |
| 955 | − p->framesPerBuffer = p->bufSize / p->frameSize; | |
| 956 | − p->curBlock = 1; | |
| 957 | − p->lastBlock = 0; | |
| 958 | − p->index = 0; | |
| 959 | − | |
| 960 | − p->hopSize = DEFHOPSIZE; | |
| 961 | − p->windowSize = DEFWINDOWSIZE; | |
| 962 | − p->fba = FBA; | |
| 963 | − | |
| 964 | − tEnvPD_initToPool(&p->env, p->windowSize, p->hopSize, p->frameSize, mp); | |
| 965 | − | |
| 966 | − tSNAC_initToPool(&p->snac, DEFOVERLAP, mp); | |
| 967 | − | |
| 968 | − p->timeConstant = DEFTIMECONSTANT; | |
| 969 | − p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant); | |
| 970 | − p->fidelityThreshold = 0.95; | |
| 971 | −} | |
| 972 | − | |
| 973 | −void tPeriodDetection_freeFromPool (tPeriodDetection* const pd, tMempool* const mp) | |
| 974 | −{ | |
| 975 | − _tMempool* m = *mp; | |
| 976 | − _tPeriodDetection* p = *pd; | |
| 977 | − | |
| 978 | − tEnvPD_freeFromPool(&p->env, mp); | |
| 979 | − tSNAC_freeFromPool(&p->snac, mp); | |
| 980 | − mpool_free((char*)p, m); | |
| 981 | −} | |
| 982 | − | |
| 983 | −float tPeriodDetection_tick (tPeriodDetection* pd, float sample) | |
| 984 | −{ | |
| 985 | − _tPeriodDetection* p = *pd; | |
| 986 | − | |
| 987 | − int i, iLast; | |
| 988 | − | |
| 989 | − i = (p->curBlock*p->frameSize); | |
| 990 | − iLast = (p->lastBlock*p->frameSize)+p->index; | |
| 991 | − | |
| 992 | − p->i = i; | |
| 993 | − p->iLast = iLast; | |
| 994 | − | |
| 995 | − p->inBuffer[i+p->index] = sample; | |
| 996 | − | |
| 997 | − p->index++; | |
| 998 | − p->indexstore = p->index; | |
| 999 | − if (p->index >= p->frameSize) | |
| 1000 | − { | |
| 1001 | − p->index = 0; | |
| 1002 | − | |
| 1003 | − tEnvPD_processBlock(&p->env, &(p->inBuffer[i])); | |
| 1004 | − | |
| 1005 | − tSNAC_ioSamples(&p->snac, &(p->inBuffer[i]), &(p->outBuffer[i]), p->frameSize); | |
| 1006 | − float fidelity = tSNAC_getFidelity(&p->snac); | |
| 1007 | − // Fidelity threshold recommended by Katja Vetters is 0.95 for most instruments/voices http://www.katjaas.nl/helmholtz/helmholtz.html | |
| 1008 | − if (fidelity > p->fidelityThreshold) p->period = tSNAC_getPeriod(&p->snac); | |
| 1009 | − | |
| 1010 | − p->curBlock++; | |
| 1011 | − if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0; | |
| 1012 | − p->lastBlock++; | |
| 1013 | − if (p->lastBlock >= p->framesPerBuffer) p->lastBlock = 0; | |
| 1014 | − } | |
| 1015 | − | |
| 1016 | − return p->period; | |
| 1017 | −} | |
| 1018 | − | |
| 1019 | −float tPeriodDetection_getPeriod(tPeriodDetection* pd) | |
| 1020 | −{ | |
| 1021 | − _tPeriodDetection* p = *pd; | |
| 1022 | − return p->period; | |
| 1023 | −} | |
| 1024 | − | |
| 1025 | −void tPeriodDetection_setHopSize(tPeriodDetection* pd, int hs) | |
| 1026 | −{ | |
| 1027 | − _tPeriodDetection* p = *pd; | |
| 1028 | − p->hopSize = hs; | |
| 1029 | −} | |
| 1030 | − | |
| 1031 | −void tPeriodDetection_setWindowSize(tPeriodDetection* pd, int ws) | |
| 1032 | −{ | |
| 1033 | − _tPeriodDetection* p = *pd; | |
| 1034 | − p->windowSize = ws; | |
| 1035 | −} | |
| 1036 | − | |
| 1037 | −void tPeriodDetection_setFidelityThreshold(tPeriodDetection* pd, float threshold) | |
| 1038 | −{ | |
| 1039 | − _tPeriodDetection* p = *pd; | |
| 1040 | − p->fidelityThreshold = threshold; | |
| 1041 | −} | |
| 1042 | − | |
| 1043 | −void tPeriodDetection_setAlpha (tPeriodDetection* pd, float alpha) | |
| 1044 | −{ | |
| 1045 | − _tPeriodDetection* p = *pd; | |
| 1046 | − p->alpha = LEAF_clip(0.0f, alpha, 1.0f); | |
| 1047 | −} | |
| 1048 | − | |
| 1049 | −void tPeriodDetection_setTolerance (tPeriodDetection* pd, float tolerance) | |
| 1050 | −{ | |
| 1051 | − _tPeriodDetection* p = *pd; | |
| 1052 | − if (tolerance < 0.0f) p->tolerance = 0.0f; | |
| 1053 | − else p->tolerance = tolerance; | |
| 1054 | −} | |
| @@ -1,928 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-delay.c | |
| 4 | − Created: 20 Jan 2017 12:01:24pm | |
| 5 | − Author: Michael R Mulshine | |
| 6 | − | |
| 7 | −==============================================================================*/ | |
| 8 | − | |
| 9 | −#if _WIN32 || _WIN64 | |
| 10 | − | |
| 11 | −#include "..\Inc\leaf-delay.h" | |
| 12 | −#include "..\leaf.h" | |
| 13 | − | |
| 14 | −#else | |
| 15 | − | |
| 16 | −#include "../Inc/leaf-delay.h" | |
| 17 | −#include "../leaf.h" | |
| 18 | − | |
| 19 | −#endif | |
| 20 | − | |
| 21 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Delay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 22 | −void tDelay_init (tDelay* const dl, uint32_t delay, uint32_t maxDelay) | |
| 23 | −{ | |
| 24 | − tDelay_initToPool(dl, delay, maxDelay, &leaf.mempool); | |
| 25 | −} | |
| 26 | − | |
| 27 | −void tDelay_free(tDelay* const dl) | |
| 28 | −{ | |
| 29 | − tDelay_freeFromPool(dl, &leaf.mempool); | |
| 30 | −} | |
| 31 | − | |
| 32 | −void tDelay_initToPool (tDelay* const dl, uint32_t delay, uint32_t maxDelay, tMempool* const mp) | |
| 33 | −{ | |
| 34 | − _tMempool* m = *mp; | |
| 35 | − _tDelay* d = *dl = (_tDelay*) mpool_alloc(sizeof(_tDelay), m); | |
| 36 | − | |
| 37 | − d->maxDelay = maxDelay; | |
| 38 | − | |
| 39 | − d->delay = delay; | |
| 40 | − | |
| 41 | − d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m); | |
| 42 | − | |
| 43 | − d->inPoint = 0; | |
| 44 | − d->outPoint = 0; | |
| 45 | − | |
| 46 | − d->lastIn = 0.0f; | |
| 47 | − d->lastOut = 0.0f; | |
| 48 | − | |
| 49 | − d->gain = 1.0f; | |
| 50 | − | |
| 51 | − tDelay_setDelay(dl, d->delay); | |
| 52 | −} | |
| 53 | − | |
| 54 | −void tDelay_freeFromPool (tDelay* const dl, tMempool* const mp) | |
| 55 | −{ | |
| 56 | − _tMempool* m = *mp; | |
| 57 | − _tDelay* d = *dl; | |
| 58 | − | |
| 59 | − mpool_free((char*)d->buff, m); | |
| 60 | − mpool_free((char*)d, m); | |
| 61 | −} | |
| 62 | − | |
| 63 | −void tDelay_clear(tDelay* const dl) | |
| 64 | −{ | |
| 65 | − _tDelay* d = *dl; | |
| 66 | − for (int i = 0; i < d->maxDelay; i++) | |
| 67 | − { | |
| 68 | − d->buff[i] = 0; | |
| 69 | − } | |
| 70 | −} | |
| 71 | − | |
| 72 | −float tDelay_tick (tDelay* const dl, float input) | |
| 73 | −{ | |
| 74 | − _tDelay* d = *dl; | |
| 75 | − | |
| 76 | − // Input | |
| 77 | − d->lastIn = input; | |
| 78 | − d->buff[d->inPoint] = input * d->gain; | |
| 79 | − if (++(d->inPoint) == d->maxDelay) d->inPoint = 0; | |
| 80 | − | |
| 81 | − // Output | |
| 82 | − d->lastOut = d->buff[d->outPoint]; | |
| 83 | − if (++(d->outPoint) == d->maxDelay) d->outPoint = 0; | |
| 84 | − | |
| 85 | − return d->lastOut; | |
| 86 | −} | |
| 87 | − | |
| 88 | −int tDelay_setDelay (tDelay* const dl, uint32_t delay) | |
| 89 | −{ | |
| 90 | − _tDelay* d = *dl; | |
| 91 | − | |
| 92 | − d->delay = LEAF_clip(0.0f, delay, d->maxDelay); | |
| 93 | − | |
| 94 | − // read chases write | |
| 95 | − if ( d->inPoint >= delay ) d->outPoint = d->inPoint - d->delay; | |
| 96 | − else d->outPoint = d->maxDelay + d->inPoint - d->delay; | |
| 97 | − | |
| 98 | − return 0; | |
| 99 | −} | |
| 100 | − | |
| 101 | −float tDelay_tapOut (tDelay* const dl, uint32_t tapDelay) | |
| 102 | −{ | |
| 103 | − _tDelay* d = *dl; | |
| 104 | − | |
| 105 | − int32_t tap = d->inPoint - tapDelay - 1; | |
| 106 | − | |
| 107 | − // Check for wraparound. | |
| 108 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 109 | − | |
| 110 | − return d->buff[tap]; | |
| 111 | − | |
| 112 | −} | |
| 113 | − | |
| 114 | −void tDelay_tapIn (tDelay* const dl, float value, uint32_t tapDelay) | |
| 115 | −{ | |
| 116 | − _tDelay* d = *dl; | |
| 117 | − | |
| 118 | − int32_t tap = d->inPoint - tapDelay - 1; | |
| 119 | − | |
| 120 | − // Check for wraparound. | |
| 121 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 122 | − | |
| 123 | − d->buff[tap] = value; | |
| 124 | −} | |
| 125 | − | |
| 126 | −float tDelay_addTo (tDelay* const dl, float value, uint32_t tapDelay) | |
| 127 | −{ | |
| 128 | − _tDelay* d = *dl; | |
| 129 | − | |
| 130 | − int32_t tap = d->inPoint - tapDelay - 1; | |
| 131 | − | |
| 132 | − // Check for wraparound. | |
| 133 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 134 | − | |
| 135 | − return (d->buff[tap] += value); | |
| 136 | −} | |
| 137 | − | |
| 138 | −uint32_t tDelay_getDelay (tDelay* const dl) | |
| 139 | −{ | |
| 140 | − _tDelay* d = *dl; | |
| 141 | − return d->delay; | |
| 142 | −} | |
| 143 | − | |
| 144 | −float tDelay_getLastOut (tDelay* const dl) | |
| 145 | −{ | |
| 146 | − _tDelay* d = *dl; | |
| 147 | − return d->lastOut; | |
| 148 | −} | |
| 149 | − | |
| 150 | −float tDelay_getLastIn (tDelay* const dl) | |
| 151 | −{ | |
| 152 | − _tDelay* d = *dl; | |
| 153 | − return d->lastIn; | |
| 154 | −} | |
| 155 | − | |
| 156 | −void tDelay_setGain (tDelay* const dl, float gain) | |
| 157 | −{ | |
| 158 | − _tDelay* d = *dl; | |
| 159 | − if (gain < 0.0f) d->gain = 0.0f; | |
| 160 | − else d->gain = gain; | |
| 161 | −} | |
| 162 | − | |
| 163 | −float tDelay_getGain (tDelay* const dl) | |
| 164 | −{ | |
| 165 | − _tDelay* d = *dl; | |
| 166 | − return d->gain; | |
| 167 | −} | |
| 168 | − | |
| 169 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ LinearDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 170 | −void tLinearDelay_init (tLinearDelay* const dl, float delay, uint32_t maxDelay) | |
| 171 | −{ | |
| 172 | − tLinearDelay_initToPool(dl, delay, maxDelay, &leaf.mempool); | |
| 173 | −} | |
| 174 | − | |
| 175 | −void tLinearDelay_free(tLinearDelay* const dl) | |
| 176 | −{ | |
| 177 | − tLinearDelay_freeFromPool(dl, &leaf.mempool); | |
| 178 | −} | |
| 179 | − | |
| 180 | −void tLinearDelay_initToPool (tLinearDelay* const dl, float delay, uint32_t maxDelay, tMempool* const mp) | |
| 181 | −{ | |
| 182 | − _tMempool* m = *mp; | |
| 183 | − _tLinearDelay* d = *dl = (_tLinearDelay*) mpool_alloc(sizeof(_tLinearDelay), m); | |
| 184 | − | |
| 185 | − d->maxDelay = maxDelay; | |
| 186 | − | |
| 187 | − if (delay > maxDelay) d->delay = maxDelay; | |
| 188 | − else if (delay < 0.0f) d->delay = 0.0f; | |
| 189 | − else d->delay = delay; | |
| 190 | − | |
| 191 | − d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m); | |
| 192 | − | |
| 193 | − d->gain = 1.0f; | |
| 194 | − | |
| 195 | − d->lastIn = 0.0f; | |
| 196 | − d->lastOut = 0.0f; | |
| 197 | − | |
| 198 | − d->inPoint = 0; | |
| 199 | − d->outPoint = 0; | |
| 200 | − | |
| 201 | − tLinearDelay_setDelay(dl, d->delay); | |
| 202 | −} | |
| 203 | − | |
| 204 | −void tLinearDelay_freeFromPool(tLinearDelay* const dl, tMempool* const mp) | |
| 205 | −{ | |
| 206 | − _tMempool* m = *mp; | |
| 207 | − _tLinearDelay* d = *dl; | |
| 208 | − | |
| 209 | − mpool_free((char*)d->buff, m); | |
| 210 | − mpool_free((char*)d, m); | |
| 211 | −} | |
| 212 | − | |
| 213 | −void tLinearDelay_clear(tLinearDelay* const dl) | |
| 214 | −{ | |
| 215 | − _tLinearDelay* d = *dl; | |
| 216 | − for (int i = 0; i < d->maxDelay; i++) | |
| 217 | − { | |
| 218 | − d->buff[i] = 0; | |
| 219 | − } | |
| 220 | −} | |
| 221 | − | |
| 222 | −float tLinearDelay_tick (tLinearDelay* const dl, float input) | |
| 223 | −{ | |
| 224 | − _tLinearDelay* d = *dl; | |
| 225 | − | |
| 226 | − d->buff[d->inPoint] = input * d->gain; | |
| 227 | − | |
| 228 | − // Increment input pointer modulo length. | |
| 229 | − if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0; | |
| 230 | − | |
| 231 | − uint32_t idx = (uint32_t) d->outPoint; | |
| 232 | − // First 1/2 of interpolation | |
| 233 | − d->lastOut = d->buff[idx] * d->omAlpha; | |
| 234 | − // Second 1/2 of interpolation | |
| 235 | − if ((idx + 1) < d->maxDelay) | |
| 236 | − d->lastOut += d->buff[idx+1] * d->alpha; | |
| 237 | − else | |
| 238 | − d->lastOut += d->buff[0] * d->alpha; | |
| 239 | − | |
| 240 | − // Increment output pointer modulo length | |
| 241 | − if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0; | |
| 242 | − | |
| 243 | − return d->lastOut; | |
| 244 | −} | |
| 245 | − | |
| 246 | −void tLinearDelay_tickIn (tLinearDelay* const dl, float input) | |
| 247 | −{ | |
| 248 | − _tLinearDelay* d = *dl; | |
| 249 | − | |
| 250 | − d->buff[d->inPoint] = input * d->gain; | |
| 251 | − | |
| 252 | − // Increment input pointer modulo length. | |
| 253 | − if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0; | |
| 254 | −} | |
| 255 | − | |
| 256 | −float tLinearDelay_tickOut (tLinearDelay* const dl) | |
| 257 | −{ | |
| 258 | − _tLinearDelay* d = *dl; | |
| 259 | − | |
| 260 | − uint32_t idx = (uint32_t) d->outPoint; | |
| 261 | − // First 1/2 of interpolation | |
| 262 | − d->lastOut = d->buff[idx] * d->omAlpha; | |
| 263 | − // Second 1/2 of interpolation | |
| 264 | − if ((idx + 1) < d->maxDelay) | |
| 265 | − d->lastOut += d->buff[idx+1] * d->alpha; | |
| 266 | − else | |
| 267 | − d->lastOut += d->buff[0] * d->alpha; | |
| 268 | − | |
| 269 | − // Increment output pointer modulo length | |
| 270 | − if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0; | |
| 271 | − | |
| 272 | − return d->lastOut; | |
| 273 | −} | |
| 274 | − | |
| 275 | −int tLinearDelay_setDelay (tLinearDelay* const dl, float delay) | |
| 276 | −{ | |
| 277 | − _tLinearDelay* d = *dl; | |
| 278 | − | |
| 279 | − d->delay = LEAF_clip(0.0f, delay, d->maxDelay); | |
| 280 | − | |
| 281 | − float outPointer = d->inPoint - d->delay; | |
| 282 | − | |
| 283 | − while ( outPointer < 0 ) | |
| 284 | − outPointer += d->maxDelay; // modulo maximum length | |
| 285 | − | |
| 286 | − d->outPoint = (uint32_t) outPointer; // integer part | |
| 287 | − | |
| 288 | − d->alpha = outPointer - d->outPoint; // fractional part | |
| 289 | − d->omAlpha = 1.0f - d->alpha; | |
| 290 | − | |
| 291 | − if ( d->outPoint == d->maxDelay ) d->outPoint = 0; | |
| 292 | − | |
| 293 | − return 0; | |
| 294 | −} | |
| 295 | − | |
| 296 | −float tLinearDelay_tapOut (tLinearDelay* const dl, uint32_t tapDelay) | |
| 297 | −{ | |
| 298 | − _tLinearDelay* d = *dl; | |
| 299 | − | |
| 300 | − uint32_t tap = d->inPoint - tapDelay - 1; | |
| 301 | − // Check for wraparound. | |
| 302 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 303 | − | |
| 304 | − return d->buff[tap]; | |
| 305 | −} | |
| 306 | − | |
| 307 | −void tLinearDelay_tapIn (tLinearDelay* const dl, float value, uint32_t tapDelay) | |
| 308 | −{ | |
| 309 | − _tLinearDelay* d = *dl; | |
| 310 | − | |
| 311 | − uint32_t tap = d->inPoint - tapDelay - 1; | |
| 312 | − | |
| 313 | − // Check for wraparound. | |
| 314 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 315 | − | |
| 316 | − d->buff[tap] = value; | |
| 317 | −} | |
| 318 | − | |
| 319 | −float tLinearDelay_addTo (tLinearDelay* const dl, float value, uint32_t tapDelay) | |
| 320 | −{ | |
| 321 | − _tLinearDelay* d = *dl; | |
| 322 | − | |
| 323 | − int32_t tap = d->inPoint - tapDelay - 1; | |
| 324 | − | |
| 325 | − // Check for wraparound. | |
| 326 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 327 | − | |
| 328 | − return (d->buff[tap] += value); | |
| 329 | −} | |
| 330 | − | |
| 331 | −float tLinearDelay_getDelay (tLinearDelay* const dl) | |
| 332 | −{ | |
| 333 | − _tLinearDelay* d = *dl; | |
| 334 | − return d->delay; | |
| 335 | −} | |
| 336 | − | |
| 337 | −float tLinearDelay_getLastOut (tLinearDelay* const dl) | |
| 338 | −{ | |
| 339 | − _tLinearDelay* d = *dl; | |
| 340 | − return d->lastOut; | |
| 341 | −} | |
| 342 | − | |
| 343 | −float tLinearDelay_getLastIn (tLinearDelay* const dl) | |
| 344 | −{ | |
| 345 | − _tLinearDelay* d = *dl; | |
| 346 | − return d->lastIn; | |
| 347 | −} | |
| 348 | − | |
| 349 | −void tLinearDelay_setGain (tLinearDelay* const dl, float gain) | |
| 350 | −{ | |
| 351 | − _tLinearDelay* d = *dl; | |
| 352 | − if (gain < 0.0f) d->gain = 0.0f; | |
| 353 | − else d->gain = gain; | |
| 354 | −} | |
| 355 | − | |
| 356 | −float tLinearDelay_getGain (tLinearDelay* const dl) | |
| 357 | −{ | |
| 358 | − _tLinearDelay* d = *dl; | |
| 359 | − return d->gain; | |
| 360 | −} | |
| 361 | − | |
| 362 | − | |
| 363 | − | |
| 364 | − | |
| 365 | − | |
| 366 | −/// Hermite Interpolated Delay | |
| 367 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ LinearDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 368 | −void tHermiteDelay_init (tHermiteDelay* const dl, float delay, uint32_t maxDelay) | |
| 369 | −{ | |
| 370 | − tHermiteDelay_initToPool(dl, delay, maxDelay, &leaf.mempool); | |
| 371 | −} | |
| 372 | − | |
| 373 | −void tHermiteDelay_free(tHermiteDelay* const dl) | |
| 374 | −{ | |
| 375 | − tHermiteDelay_freeFromPool(dl, &leaf.mempool); | |
| 376 | −} | |
| 377 | − | |
| 378 | −void tHermiteDelay_initToPool (tHermiteDelay* const dl, float delay, uint32_t maxDelay, tMempool* const mp) | |
| 379 | −{ | |
| 380 | − _tMempool* m = *mp; | |
| 381 | − _tHermiteDelay* d = *dl = (_tHermiteDelay*) mpool_alloc(sizeof(_tHermiteDelay), m); | |
| 382 | − | |
| 383 | − d->maxDelay = maxDelay; | |
| 384 | − | |
| 385 | − if (delay > maxDelay) d->delay = maxDelay; | |
| 386 | − else if (delay < 0.0f) d->delay = 0.0f; | |
| 387 | − else d->delay = delay; | |
| 388 | − | |
| 389 | − d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m); | |
| 390 | − | |
| 391 | − d->gain = 1.0f; | |
| 392 | − | |
| 393 | − d->lastIn = 0.0f; | |
| 394 | − d->lastOut = 0.0f; | |
| 395 | − | |
| 396 | − d->inPoint = 0; | |
| 397 | − d->outPoint = 0; | |
| 398 | − | |
| 399 | − tHermiteDelay_setDelay(dl, d->delay); | |
| 400 | −} | |
| 401 | − | |
| 402 | −void tHermiteDelay_freeFromPool(tHermiteDelay* const dl, tMempool* const mp) | |
| 403 | −{ | |
| 404 | − _tMempool* m = *mp; | |
| 405 | − _tHermiteDelay* d = *dl; | |
| 406 | − | |
| 407 | − mpool_free((char*)d->buff, m); | |
| 408 | − mpool_free((char*)d, m); | |
| 409 | −} | |
| 410 | − | |
| 411 | − | |
| 412 | −void tHermiteDelay_clear(tHermiteDelay* const dl) | |
| 413 | −{ | |
| 414 | − _tHermiteDelay* d = *dl; | |
| 415 | − for (int i = 0; i < d->maxDelay; i++) | |
| 416 | − { | |
| 417 | − d->buff[i] = 0; | |
| 418 | − } | |
| 419 | −} | |
| 420 | − | |
| 421 | −float tHermiteDelay_tick (tHermiteDelay* const dl, float input) | |
| 422 | −{ | |
| 423 | − _tHermiteDelay* d = *dl; | |
| 424 | − | |
| 425 | − d->buff[d->inPoint] = input * d->gain; | |
| 426 | − | |
| 427 | − // Increment input pointer modulo length. | |
| 428 | − if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0; | |
| 429 | − | |
| 430 | − | |
| 431 | − uint32_t idx = (uint32_t) d->outPoint; | |
| 432 | − d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay], | |
| 433 | − d->buff[idx], | |
| 434 | − d->buff[(idx + 1) % d->maxDelay], | |
| 435 | − d->buff[(idx + 2) % d->maxDelay], | |
| 436 | − d->alpha); | |
| 437 | − | |
| 438 | − // Increment output pointer modulo length | |
| 439 | − if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0; | |
| 440 | − | |
| 441 | − return d->lastOut; | |
| 442 | −} | |
| 443 | − | |
| 444 | −void tHermiteDelay_tickIn (tHermiteDelay* const dl, float input) | |
| 445 | −{ | |
| 446 | − _tHermiteDelay* d = *dl; | |
| 447 | − | |
| 448 | − d->buff[d->inPoint] = input * d->gain; | |
| 449 | − | |
| 450 | − // Increment input pointer modulo length. | |
| 451 | − if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0; | |
| 452 | −} | |
| 453 | − | |
| 454 | −float tHermiteDelay_tickOut (tHermiteDelay* const dl) | |
| 455 | −{ | |
| 456 | − _tHermiteDelay* d = *dl; | |
| 457 | − | |
| 458 | − uint32_t idx = (uint32_t) d->outPoint; | |
| 459 | − | |
| 460 | − | |
| 461 | − | |
| 462 | − d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay], | |
| 463 | − d->buff[idx], | |
| 464 | − d->buff[(idx + 1) % d->maxDelay], | |
| 465 | − d->buff[(idx + 2) % d->maxDelay], | |
| 466 | − d->alpha); | |
| 467 | − | |
| 468 | − // Increment output pointer modulo length | |
| 469 | − if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0; | |
| 470 | − | |
| 471 | − return d->lastOut; | |
| 472 | −} | |
| 473 | − | |
| 474 | −int tHermiteDelay_setDelay (tHermiteDelay* const dl, float delay) | |
| 475 | −{ | |
| 476 | − _tHermiteDelay* d = *dl; | |
| 477 | − | |
| 478 | − d->delay = LEAF_clip(0.0f, delay, d->maxDelay); | |
| 479 | − | |
| 480 | − float outPointer = d->inPoint - d->delay; | |
| 481 | − | |
| 482 | − while ( outPointer < 0 ) | |
| 483 | − outPointer += d->maxDelay; // modulo maximum length | |
| 484 | − | |
| 485 | − d->outPoint = (uint32_t) outPointer; // integer part | |
| 486 | − | |
| 487 | − d->alpha = outPointer - d->outPoint; // fractional part | |
| 488 | − d->omAlpha = 1.0f - d->alpha; | |
| 489 | − | |
| 490 | − if ( d->outPoint == d->maxDelay ) d->outPoint = 0; | |
| 491 | − | |
| 492 | − return 0; | |
| 493 | −} | |
| 494 | − | |
| 495 | −float tHermiteDelay_tapOut (tHermiteDelay* const dl, uint32_t tapDelay) | |
| 496 | −{ | |
| 497 | − _tHermiteDelay* d = *dl; | |
| 498 | − | |
| 499 | − uint32_t tap = d->inPoint - tapDelay - 1; | |
| 500 | − | |
| 501 | − // Check for wraparound. | |
| 502 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 503 | − | |
| 504 | − return d->buff[tap]; | |
| 505 | − | |
| 506 | −} | |
| 507 | − | |
| 508 | −void tHermiteDelay_tapIn (tHermiteDelay* const dl, float value, uint32_t tapDelay) | |
| 509 | −{ | |
| 510 | − _tHermiteDelay* d = *dl; | |
| 511 | − | |
| 512 | − int32_t tap = d->inPoint - tapDelay - 1; | |
| 513 | − | |
| 514 | − // Check for wraparound. | |
| 515 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 516 | − | |
| 517 | − d->buff[tap] = value; | |
| 518 | −} | |
| 519 | − | |
| 520 | −float tHermiteDelay_addTo (tHermiteDelay* const dl, float value, uint32_t tapDelay) | |
| 521 | −{ | |
| 522 | − _tHermiteDelay* d = *dl; | |
| 523 | − | |
| 524 | − int32_t tap = d->inPoint - tapDelay - 1; | |
| 525 | − | |
| 526 | − // Check for wraparound. | |
| 527 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 528 | − | |
| 529 | − return (d->buff[tap] += value); | |
| 530 | −} | |
| 531 | − | |
| 532 | −float tHermiteDelay_getDelay (tHermiteDelay* const dl) | |
| 533 | −{ | |
| 534 | − _tHermiteDelay* d = *dl; | |
| 535 | − return d->delay; | |
| 536 | −} | |
| 537 | − | |
| 538 | −float tHermiteDelay_getLastOut (tHermiteDelay* const dl) | |
| 539 | −{ | |
| 540 | − _tHermiteDelay* d = *dl; | |
| 541 | − return d->lastOut; | |
| 542 | −} | |
| 543 | − | |
| 544 | −float tHermiteDelay_getLastIn (tHermiteDelay* const dl) | |
| 545 | −{ | |
| 546 | − _tHermiteDelay* d = *dl; | |
| 547 | − return d->lastIn; | |
| 548 | −} | |
| 549 | − | |
| 550 | −void tHermiteDelay_setGain (tHermiteDelay* const dl, float gain) | |
| 551 | −{ | |
| 552 | − _tHermiteDelay* d = *dl; | |
| 553 | − if (gain < 0.0f) d->gain = 0.0f; | |
| 554 | − else d->gain = gain; | |
| 555 | −} | |
| 556 | − | |
| 557 | −float tHermiteDelay_getGain (tHermiteDelay* const dl) | |
| 558 | −{ | |
| 559 | − _tHermiteDelay* d = *dl; | |
| 560 | − return d->gain; | |
| 561 | −} | |
| 562 | − | |
| 563 | − | |
| 564 | − | |
| 565 | − | |
| 566 | − | |
| 567 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ AllpassDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 568 | −void tAllpassDelay_init (tAllpassDelay* const dl, float delay, uint32_t maxDelay) | |
| 569 | −{ | |
| 570 | − tAllpassDelay_initToPool(dl, delay, maxDelay, &leaf.mempool); | |
| 571 | −} | |
| 572 | − | |
| 573 | −void tAllpassDelay_free(tAllpassDelay* const dl) | |
| 574 | −{ | |
| 575 | − tAllpassDelay_freeFromPool(dl, &leaf.mempool); | |
| 576 | −} | |
| 577 | − | |
| 578 | −void tAllpassDelay_initToPool (tAllpassDelay* const dl, float delay, uint32_t maxDelay, tMempool* const mp) | |
| 579 | −{ | |
| 580 | − _tMempool* m = *mp; | |
| 581 | − _tAllpassDelay* d = *dl = (_tAllpassDelay*) mpool_alloc(sizeof(_tAllpassDelay), m); | |
| 582 | − | |
| 583 | − d->maxDelay = maxDelay; | |
| 584 | − | |
| 585 | − if (delay > maxDelay) d->delay = maxDelay; | |
| 586 | − else if (delay < 0.0f) d->delay = 0.0f; | |
| 587 | − else d->delay = delay; | |
| 588 | − | |
| 589 | − d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m); | |
| 590 | − | |
| 591 | − d->gain = 1.0f; | |
| 592 | − | |
| 593 | − d->lastIn = 0.0f; | |
| 594 | − d->lastOut = 0.0f; | |
| 595 | − | |
| 596 | − d->inPoint = 0; | |
| 597 | − d->outPoint = 0; | |
| 598 | − | |
| 599 | − tAllpassDelay_setDelay(dl, d->delay); | |
| 600 | − | |
| 601 | − d->apInput = 0.0f; | |
| 602 | −} | |
| 603 | − | |
| 604 | −void tAllpassDelay_freeFromPool(tAllpassDelay* const dl, tMempool* const mp) | |
| 605 | −{ | |
| 606 | − _tMempool* m = *mp; | |
| 607 | − _tAllpassDelay* d = *dl; | |
| 608 | − | |
| 609 | − mpool_free((char*)d->buff, m); | |
| 610 | − mpool_free((char*)d, m); | |
| 611 | −} | |
| 612 | − | |
| 613 | −void tAllpassDelay_clear(tAllpassDelay* const dl) | |
| 614 | −{ | |
| 615 | − _tAllpassDelay* d = *dl; | |
| 616 | − for (int i = 0; i < d->maxDelay; i++) | |
| 617 | − { | |
| 618 | − d->buff[i] = 0; | |
| 619 | − } | |
| 620 | −} | |
| 621 | − | |
| 622 | −float tAllpassDelay_tick (tAllpassDelay* const dl, float input) | |
| 623 | −{ | |
| 624 | − _tAllpassDelay* d = *dl; | |
| 625 | − | |
| 626 | − d->buff[d->inPoint] = input * d->gain; | |
| 627 | − | |
| 628 | − // Increment input pointer modulo length. | |
| 629 | − if ( ++(d->inPoint) >= d->maxDelay ) d->inPoint = 0; | |
| 630 | − | |
| 631 | − // Do allpass interpolation delay. | |
| 632 | − float out = d->lastOut * -d->coeff; | |
| 633 | − out += d->apInput + ( d->coeff * d->buff[d->outPoint] ); | |
| 634 | − d->lastOut = out; | |
| 635 | − | |
| 636 | − // Save allpass input | |
| 637 | − d->apInput = d->buff[d->outPoint]; | |
| 638 | − | |
| 639 | − // Increment output pointer modulo length. | |
| 640 | − if (++(d->outPoint) >= d->maxDelay ) d->outPoint = 0; | |
| 641 | − | |
| 642 | − return d->lastOut; | |
| 643 | −} | |
| 644 | − | |
| 645 | −int tAllpassDelay_setDelay (tAllpassDelay* const dl, float delay) | |
| 646 | −{ | |
| 647 | − _tAllpassDelay* d = *dl; | |
| 648 | − | |
| 649 | − d->delay = LEAF_clip(0.5f, delay, d->maxDelay); | |
| 650 | − | |
| 651 | − // outPoint chases inPoint | |
| 652 | − float outPointer = (float)d->inPoint - d->delay + 1.0f; | |
| 653 | − | |
| 654 | − while ( outPointer < 0 ) outPointer += d->maxDelay; // mod max length | |
| 655 | − | |
| 656 | − d->outPoint = (uint32_t) outPointer; // integer part | |
| 657 | − | |
| 658 | − if ( d->outPoint >= d->maxDelay ) d->outPoint = 0; | |
| 659 | − | |
| 660 | − d->alpha = 1.0f + (float)d->outPoint - outPointer; // fractional part | |
| 661 | − | |
| 662 | − if ( d->alpha < 0.5f ) | |
| 663 | − { | |
| 664 | − // The optimal range for alpha is about 0.5 - 1.5 in order to | |
| 665 | − // achieve the flattest phase delay response. | |
| 666 | − | |
| 667 | − d->outPoint += 1; | |
| 668 | − | |
| 669 | − if ( d->outPoint >= d->maxDelay ) d->outPoint -= d->maxDelay; | |
| 670 | − | |
| 671 | − d->alpha += 1.0f; | |
| 672 | − } | |
| 673 | − | |
| 674 | − d->coeff = (1.0f - d->alpha) / (1.0f + d->alpha); // coefficient for allpass | |
| 675 | − | |
| 676 | − return 0; | |
| 677 | −} | |
| 678 | − | |
| 679 | −float tAllpassDelay_tapOut (tAllpassDelay* const dl, uint32_t tapDelay) | |
| 680 | −{ | |
| 681 | − _tAllpassDelay* d = *dl; | |
| 682 | − | |
| 683 | − int32_t tap = d->inPoint - tapDelay - 1; | |
| 684 | − | |
| 685 | − // Check for wraparound. | |
| 686 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 687 | − | |
| 688 | − return d->buff[tap]; | |
| 689 | − | |
| 690 | −} | |
| 691 | − | |
| 692 | −void tAllpassDelay_tapIn (tAllpassDelay* const dl, float value, uint32_t tapDelay) | |
| 693 | −{ | |
| 694 | − _tAllpassDelay* d = *dl; | |
| 695 | − | |
| 696 | − int32_t tap = d->inPoint - tapDelay - 1; | |
| 697 | − | |
| 698 | − // Check for wraparound. | |
| 699 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 700 | − | |
| 701 | − d->buff[tap] = value; | |
| 702 | −} | |
| 703 | − | |
| 704 | −float tAllpassDelay_addTo (tAllpassDelay* const dl, float value, uint32_t tapDelay) | |
| 705 | −{ | |
| 706 | − _tAllpassDelay* d = *dl; | |
| 707 | − | |
| 708 | − int32_t tap = d->inPoint - tapDelay - 1; | |
| 709 | − | |
| 710 | − // Check for wraparound. | |
| 711 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 712 | − | |
| 713 | − return (d->buff[tap] += value); | |
| 714 | −} | |
| 715 | − | |
| 716 | −float tAllpassDelay_getDelay (tAllpassDelay* const dl) | |
| 717 | −{ | |
| 718 | − _tAllpassDelay* d = *dl; | |
| 719 | − return d->delay; | |
| 720 | −} | |
| 721 | − | |
| 722 | −float tAllpassDelay_getLastOut (tAllpassDelay* const dl) | |
| 723 | −{ | |
| 724 | − _tAllpassDelay* d = *dl; | |
| 725 | − return d->lastOut; | |
| 726 | −} | |
| 727 | − | |
| 728 | −float tAllpassDelay_getLastIn (tAllpassDelay* const dl) | |
| 729 | −{ | |
| 730 | − _tAllpassDelay* d = *dl; | |
| 731 | − return d->lastIn; | |
| 732 | −} | |
| 733 | − | |
| 734 | −void tAllpassDelay_setGain (tAllpassDelay* const dl, float gain) | |
| 735 | −{ | |
| 736 | − _tAllpassDelay* d = *dl; | |
| 737 | − if (gain < 0.0f) d->gain = 0.0f; | |
| 738 | − else d->gain = gain; | |
| 739 | −} | |
| 740 | − | |
| 741 | −float tAllpassDelay_getGain (tAllpassDelay* const dl) | |
| 742 | −{ | |
| 743 | − _tAllpassDelay* d = *dl; | |
| 744 | − return d->gain; | |
| 745 | −} | |
| 746 | − | |
| 747 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TapeDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 748 | −void tTapeDelay_init (tTapeDelay* const dl, float delay, uint32_t maxDelay) | |
| 749 | −{ | |
| 750 | − tTapeDelay_initToPool(dl, delay, maxDelay, &leaf.mempool); | |
| 751 | −} | |
| 752 | − | |
| 753 | −void tTapeDelay_free(tTapeDelay* const dl) | |
| 754 | −{ | |
| 755 | − tTapeDelay_freeFromPool(dl, &leaf.mempool); | |
| 756 | −} | |
| 757 | − | |
| 758 | −void tTapeDelay_initToPool (tTapeDelay* const dl, float delay, uint32_t maxDelay, tMempool* const mp) | |
| 759 | −{ | |
| 760 | − _tMempool* m = *mp; | |
| 761 | − _tTapeDelay* d = *dl = (_tTapeDelay*) mpool_alloc(sizeof(_tTapeDelay), m); | |
| 762 | − | |
| 763 | − d->maxDelay = maxDelay; | |
| 764 | − | |
| 765 | − d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m); | |
| 766 | − | |
| 767 | − d->gain = 1.0f; | |
| 768 | − | |
| 769 | − d->lastIn = 0.0f; | |
| 770 | − d->lastOut = 0.0f; | |
| 771 | − | |
| 772 | − d->idx = 0.0f; | |
| 773 | − d->inc = 1.0f; | |
| 774 | − d->inPoint = 0; | |
| 775 | − | |
| 776 | − tTapeDelay_setDelay(dl, delay); | |
| 777 | −} | |
| 778 | − | |
| 779 | −void tTapeDelay_freeFromPool(tTapeDelay* const dl, tMempool* const mp) | |
| 780 | −{ | |
| 781 | − _tMempool* m = *mp; | |
| 782 | − _tTapeDelay* d = *dl; | |
| 783 | − | |
| 784 | − mpool_free((char*)d->buff, m); | |
| 785 | − mpool_free((char*)d, m); | |
| 786 | −} | |
| 787 | − | |
| 788 | −void tTapeDelay_clear(tTapeDelay* const dl) | |
| 789 | −{ | |
| 790 | − _tTapeDelay* d = *dl; | |
| 791 | − for (int i = 0; i < d->maxDelay; i++) | |
| 792 | − { | |
| 793 | − d->buff[i] = 0; | |
| 794 | − } | |
| 795 | −} | |
| 796 | − | |
| 797 | −//#define SMOOTH_FACTOR 10.f | |
| 798 | − | |
| 799 | −float tTapeDelay_tick (tTapeDelay* const dl, float input) | |
| 800 | −{ | |
| 801 | − _tTapeDelay* d = *dl; | |
| 802 | − | |
| 803 | − d->buff[d->inPoint] = input * d->gain; | |
| 804 | − | |
| 805 | − // Increment input pointer modulo length. | |
| 806 | − if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0; | |
| 807 | − | |
| 808 | − int idx = (int) d->idx; | |
| 809 | − float alpha = d->idx - idx; | |
| 810 | − | |
| 811 | − d->lastOut = LEAF_interpolate_hermite_x (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay], | |
| 812 | − d->buff[idx], | |
| 813 | − d->buff[(idx + 1) % d->maxDelay], | |
| 814 | − d->buff[(idx + 2) % d->maxDelay], | |
| 815 | − alpha); | |
| 816 | − | |
| 817 | − float diff = (d->inPoint - d->idx); | |
| 818 | − while (diff < 0.f) diff += d->maxDelay; | |
| 819 | − | |
| 820 | − d->inc = 1.0f + (diff - d->delay) / d->delay; //* SMOOTH_FACTOR; | |
| 821 | − | |
| 822 | − d->idx += d->inc; | |
| 823 | − | |
| 824 | − if (d->idx >= d->maxDelay) d->idx = 0.0f; | |
| 825 | − | |
| 826 | − if (d->lastOut) | |
| 827 | − return d->lastOut; | |
| 828 | − return 0.0f; | |
| 829 | −} | |
| 830 | − | |
| 831 | −void tTapeDelay_incrementInPoint(tTapeDelay* const dl) | |
| 832 | −{ | |
| 833 | − _tTapeDelay* d = *dl; | |
| 834 | − // Increment input pointer modulo length. | |
| 835 | − if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0; | |
| 836 | −} | |
| 837 | − | |
| 838 | − | |
| 839 | −void tTapeDelay_setRate(tTapeDelay* const dl, float rate) | |
| 840 | −{ | |
| 841 | − _tTapeDelay* d = *dl; | |
| 842 | − d->inc = rate; | |
| 843 | −} | |
| 844 | − | |
| 845 | −void tTapeDelay_setDelay (tTapeDelay* const dl, float delay) | |
| 846 | −{ | |
| 847 | − _tTapeDelay* d = *dl; | |
| 848 | − d->delay = LEAF_clip(1.f, delay, d->maxDelay); | |
| 849 | −} | |
| 850 | − | |
| 851 | −float tTapeDelay_tapOut (tTapeDelay* const dl, float tapDelay) | |
| 852 | −{ | |
| 853 | − _tTapeDelay* d = *dl; | |
| 854 | − | |
| 855 | − float tap = (float) d->inPoint - tapDelay - 1.f; | |
| 856 | − | |
| 857 | − // Check for wraparound. | |
| 858 | − while ( tap < 0.f ) tap += (float)d->maxDelay; | |
| 859 | − | |
| 860 | − int idx = (int) tap; | |
| 861 | − | |
| 862 | − float alpha = tap - idx; | |
| 863 | − | |
| 864 | − float samp = LEAF_interpolate_hermite_x (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay], | |
| 865 | − d->buff[idx], | |
| 866 | − d->buff[(idx + 1) % d->maxDelay], | |
| 867 | − d->buff[(idx + 2) % d->maxDelay], | |
| 868 | − alpha); | |
| 869 | − | |
| 870 | − return samp; | |
| 871 | − | |
| 872 | −} | |
| 873 | − | |
| 874 | −void tTapeDelay_tapIn (tTapeDelay* const dl, float value, uint32_t tapDelay) | |
| 875 | −{ | |
| 876 | − _tTapeDelay* d = *dl; | |
| 877 | − | |
| 878 | − int32_t tap = d->inPoint - tapDelay - 1; | |
| 879 | − | |
| 880 | − // Check for wraparound. | |
| 881 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 882 | − | |
| 883 | − d->buff[tap] = value; | |
| 884 | −} | |
| 885 | − | |
| 886 | −float tTapeDelay_addTo (tTapeDelay* const dl, float value, uint32_t tapDelay) | |
| 887 | −{ | |
| 888 | − _tTapeDelay* d = *dl; | |
| 889 | − | |
| 890 | − int32_t tap = d->inPoint - tapDelay - 1; | |
| 891 | − | |
| 892 | − // Check for wraparound. | |
| 893 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 894 | − | |
| 895 | − return (d->buff[tap] += value); | |
| 896 | −} | |
| 897 | − | |
| 898 | −float tTapeDelay_getDelay (tTapeDelay *dl) | |
| 899 | −{ | |
| 900 | − _tTapeDelay* d = *dl; | |
| 901 | − return d->delay; | |
| 902 | −} | |
| 903 | − | |
| 904 | −float tTapeDelay_getLastOut (tTapeDelay* const dl) | |
| 905 | −{ | |
| 906 | − _tTapeDelay* d = *dl; | |
| 907 | − return d->lastOut; | |
| 908 | −} | |
| 909 | − | |
| 910 | −float tTapeDelay_getLastIn (tTapeDelay* const dl) | |
| 911 | −{ | |
| 912 | − _tTapeDelay* d = *dl; | |
| 913 | − return d->lastIn; | |
| 914 | −} | |
| 915 | − | |
| 916 | −void tTapeDelay_setGain (tTapeDelay* const dl, float gain) | |
| 917 | −{ | |
| 918 | − _tTapeDelay* d = *dl; | |
| 919 | − if (gain < 0.0f) d->gain = 0.0f; | |
| 920 | − else d->gain = gain; | |
| 921 | −} | |
| 922 | − | |
| 923 | −float tTapeDelay_getGain (tTapeDelay* const dl) | |
| 924 | −{ | |
| 925 | − _tTapeDelay* d = *dl; | |
| 926 | − return d->gain; | |
| 927 | −} | |
| 928 | − | |
| @@ -1,695 +0,0 @@ | ||
| 1 | −// | |
| 2 | −// leaf-distortion.c | |
| 3 | −// LEAF | |
| 4 | −// | |
| 5 | −// Created by Jeff Snyder, Matthew Wang, Michael Mulshine, and Joshua Becker | |
| 6 | −// Copyright © 2019 Princeton University. All rights reserved. | |
| 7 | −// | |
| 8 | − | |
| 9 | −#if _WIN32 || _WIN64 | |
| 10 | − | |
| 11 | −#include "..\Inc\leaf-distortion.h" | |
| 12 | −#include "..\Inc\leaf-tables.h" | |
| 13 | −#else | |
| 14 | − | |
| 15 | − | |
| 16 | −#include "../Inc/leaf-distortion.h" | |
| 17 | −#include "../Inc/leaf-tables.h" | |
| 18 | − | |
| 19 | −#endif | |
| 20 | − | |
| 21 | −//============================================================================================================ | |
| 22 | −// Sample-Rate reducer | |
| 23 | −//============================================================================================================ | |
| 24 | − | |
| 25 | − | |
| 26 | −void tSampleReducer_init(tSampleReducer* const sr) | |
| 27 | −{ | |
| 28 | − _tSampleReducer* s = *sr = (_tSampleReducer*) leaf_alloc(sizeof(_tSampleReducer)); | |
| 29 | − | |
| 30 | − s->invRatio = 1.0f; | |
| 31 | − s->hold = 0.0f; | |
| 32 | − s->count = 0; | |
| 33 | −} | |
| 34 | − | |
| 35 | −void tSampleReducer_free (tSampleReducer* const sr) | |
| 36 | −{ | |
| 37 | − _tSampleReducer* s = *sr; | |
| 38 | − | |
| 39 | − leaf_free((char*)s); | |
| 40 | −} | |
| 41 | − | |
| 42 | −void tSampleReducer_initToPool (tSampleReducer* const sr, tMempool* const mp) | |
| 43 | −{ | |
| 44 | − _tMempool* m = *mp; | |
| 45 | − _tSampleReducer* s = *sr = (_tSampleReducer*) mpool_alloc(sizeof(_tSampleReducer), m); | |
| 46 | − | |
| 47 | − s->invRatio = 1.0f; | |
| 48 | − s->hold = 0.0f; | |
| 49 | − s->count = 0; | |
| 50 | −} | |
| 51 | − | |
| 52 | −void tSampleReducer_freeFromPool (tSampleReducer* const sr, tMempool* const mp) | |
| 53 | −{ | |
| 54 | − _tMempool* m = *mp; | |
| 55 | − _tSampleReducer* s = *sr; | |
| 56 | − | |
| 57 | − mpool_free((char*)s, m); | |
| 58 | −} | |
| 59 | − | |
| 60 | −float tSampleReducer_tick(tSampleReducer* const sr, float input) | |
| 61 | −{ | |
| 62 | − _tSampleReducer* s = *sr; | |
| 63 | − if (s->count > s->invRatio) | |
| 64 | − { | |
| 65 | − s->hold = input; | |
| 66 | − s->count = 0; | |
| 67 | − } | |
| 68 | − | |
| 69 | − s->count++; | |
| 70 | − return s->hold; | |
| 71 | −} | |
| 72 | − | |
| 73 | − | |
| 74 | −void tSampleReducer_setRatio(tSampleReducer* const sr, float ratio) | |
| 75 | −{ | |
| 76 | − _tSampleReducer* s = *sr; | |
| 77 | − if ((ratio <= 1.0f) && (ratio >= 0.0f)) | |
| 78 | − s->invRatio = 1.0f / ratio; | |
| 79 | − | |
| 80 | −} | |
| 81 | − | |
| 82 | −//============================================================================================================ | |
| 83 | −// Oversampler | |
| 84 | −//============================================================================================================ | |
| 85 | −// Latency is equal to the phase length (numTaps / ratio) | |
| 86 | −void tOversampler_init(tOversampler* const osr, int ratio, oBool extraQuality) | |
| 87 | −{ | |
| 88 | − _tOversampler* os = *osr = (_tOversampler*) leaf_alloc(sizeof(_tOversampler)); | |
| 89 | − | |
| 90 | − uint8_t offset = 0; | |
| 91 | − if (extraQuality) offset = 6; | |
| 92 | − if (ratio == 2 || ratio == 4 || | |
| 93 | − ratio == 8 || ratio == 16 || | |
| 94 | − ratio == 32 || ratio == 64) { | |
| 95 | − os->ratio = ratio; | |
| 96 | − int idx = (int)(log2f(os->ratio))-1+offset; | |
| 97 | − os->numTaps = __leaf_tablesize_firNumTaps[idx]; | |
| 98 | − os->phaseLength = os->numTaps / os->ratio; | |
| 99 | − os->pCoeffs = (float*) __leaf_tableref_firCoeffs[idx]; | |
| 100 | − os->upState = (float*) leaf_alloc(sizeof(float) * os->numTaps * 2); | |
| 101 | − os->downState = (float*) leaf_alloc(sizeof(float) * os->numTaps * 2); | |
| 102 | − } | |
| 103 | −} | |
| 104 | − | |
| 105 | −void tOversampler_free(tOversampler* const osr) | |
| 106 | −{ | |
| 107 | − _tOversampler* os = *osr; | |
| 108 | − | |
| 109 | − leaf_free((char*)os->upState); | |
| 110 | − leaf_free((char*)os->downState); | |
| 111 | − leaf_free((char*)os); | |
| 112 | −} | |
| 113 | − | |
| 114 | −void tOversampler_initToPool (tOversampler* const osr, int ratio, oBool extraQuality, tMempool* const mp) | |
| 115 | −{ | |
| 116 | − _tMempool* m = *mp; | |
| 117 | − _tOversampler* os = *osr = (_tOversampler*) mpool_alloc(sizeof(_tOversampler), m); | |
| 118 | − | |
| 119 | − uint8_t offset = 0; | |
| 120 | − if (extraQuality) offset = 6; | |
| 121 | − if (ratio == 2 || ratio == 4 || | |
| 122 | − ratio == 8 || ratio == 16 || | |
| 123 | − ratio == 32 || ratio == 64) { | |
| 124 | − os->ratio = ratio; | |
| 125 | − int idx = (int)(log2f(os->ratio))-1+offset; | |
| 126 | − os->numTaps = __leaf_tablesize_firNumTaps[idx]; | |
| 127 | − os->phaseLength = os->numTaps / os->ratio; | |
| 128 | − os->pCoeffs = (float*) __leaf_tableref_firCoeffs[idx]; | |
| 129 | − os->upState = (float*) mpool_alloc(sizeof(float) * os->numTaps * 2, m); | |
| 130 | − os->downState = (float*) mpool_alloc(sizeof(float) * os->numTaps * 2, m); | |
| 131 | − } | |
| 132 | −} | |
| 133 | − | |
| 134 | −void tOversampler_freeFromPool (tOversampler* const osr, tMempool* const mp) | |
| 135 | −{ | |
| 136 | − _tMempool* m = *mp; | |
| 137 | − _tOversampler* os = *osr; | |
| 138 | − | |
| 139 | − mpool_free((char*)os->upState, m); | |
| 140 | − mpool_free((char*)os->downState, m); | |
| 141 | − mpool_free((char*)os, m); | |
| 142 | −} | |
| 143 | − | |
| 144 | −float tOversampler_tick(tOversampler* const osr, float input, float (*effectTick)(float)) | |
| 145 | −{ | |
| 146 | − _tOversampler* os = *osr; | |
| 147 | − | |
| 148 | − float buf[os->ratio]; | |
| 149 | − | |
| 150 | − tOversampler_upsample(osr, input, buf); | |
| 151 | − | |
| 152 | − for (int i = 0; i < os->ratio; ++i) { | |
| 153 | − buf[i] = effectTick(buf[i]); | |
| 154 | − } | |
| 155 | − | |
| 156 | − return tOversampler_downsample(osr, buf); | |
| 157 | −} | |
| 158 | − | |
| 159 | −// From CMSIS DSP Library | |
| 160 | −void tOversampler_upsample(tOversampler* const osr, float input, float* output) | |
| 161 | −{ | |
| 162 | − _tOversampler* os = *osr; | |
| 163 | − | |
| 164 | − float *pState = os->upState; /* State pointer */ | |
| 165 | − float *pCoeffs = os->pCoeffs; /* Coefficient pointer */ | |
| 166 | − float *pStateCur; | |
| 167 | − float *ptr1; /* Temporary pointer for state buffer */ | |
| 168 | − float *ptr2; /* Temporary pointer for coefficient buffer */ | |
| 169 | − float sum0; /* Accumulators */ | |
| 170 | − uint32_t i, tapCnt; /* Loop counters */ | |
| 171 | − uint32_t phaseLen = os->phaseLength; /* Length of each polyphase filter component */ | |
| 172 | − uint32_t j; | |
| 173 | − | |
| 174 | − /* os->pState buffer contains previous frame (phaseLen - 1) samples */ | |
| 175 | − /* pStateCur points to the location where the new input data should be written */ | |
| 176 | − pStateCur = os->upState + (phaseLen - 1U); | |
| 177 | − | |
| 178 | − /* Copy new input sample into the state buffer */ | |
| 179 | − *pStateCur = input; | |
| 180 | − | |
| 181 | − /* Address modifier index of coefficient buffer */ | |
| 182 | − j = 1U; | |
| 183 | − | |
| 184 | − /* Loop over the Interpolation factor. */ | |
| 185 | − i = os->ratio; | |
| 186 | − | |
| 187 | − while (i > 0U) | |
| 188 | − { | |
| 189 | − /* Set accumulator to zero */ | |
| 190 | − sum0 = 0.0f; | |
| 191 | − | |
| 192 | − /* Initialize state pointer */ | |
| 193 | − ptr1 = pState; | |
| 194 | − | |
| 195 | − /* Initialize coefficient pointer */ | |
| 196 | − ptr2 = pCoeffs + (os->ratio - j); | |
| 197 | − | |
| 198 | − /* Loop over the polyPhase length. | |
| 199 | − Repeat until we've computed numTaps-(4*os->L) coefficients. */ | |
| 200 | − | |
| 201 | − /* Initialize tapCnt with number of samples */ | |
| 202 | − tapCnt = phaseLen; | |
| 203 | − | |
| 204 | − while (tapCnt > 0U) | |
| 205 | − { | |
| 206 | − /* Perform the multiply-accumulate */ | |
| 207 | − sum0 += *ptr1++ * *ptr2; | |
| 208 | − | |
| 209 | − /* Upsampling is done by stuffing L-1 zeros between each sample. | |
| 210 | − * So instead of multiplying zeros with coefficients, | |
| 211 | − * Increment the coefficient pointer by interpolation factor times. */ | |
| 212 | − ptr2 += os->ratio; | |
| 213 | − | |
| 214 | − /* Decrement loop counter */ | |
| 215 | − tapCnt--; | |
| 216 | − } | |
| 217 | − | |
| 218 | − /* The result is in the accumulator, store in the destination buffer. */ | |
| 219 | − *output++ = sum0 * os->ratio; | |
| 220 | − | |
| 221 | − /* Increment the address modifier index of coefficient buffer */ | |
| 222 | − j++; | |
| 223 | − | |
| 224 | − /* Decrement the loop counter */ | |
| 225 | − i--; | |
| 226 | − } | |
| 227 | − | |
| 228 | − /* Advance the state pointer by 1 | |
| 229 | − * to process the next group of interpolation factor number samples */ | |
| 230 | − pState = pState + 1; | |
| 231 | − | |
| 232 | − /* Processing is complete. | |
| 233 | − Now copy the last phaseLen - 1 samples to the satrt of the state buffer. | |
| 234 | − This prepares the state buffer for the next function call. */ | |
| 235 | − | |
| 236 | − /* Points to the start of the state buffer */ | |
| 237 | − pStateCur = os->upState; | |
| 238 | − | |
| 239 | − /* Initialize tapCnt with number of samples */ | |
| 240 | − tapCnt = (phaseLen - 1U); | |
| 241 | − | |
| 242 | − /* Copy data */ | |
| 243 | − while (tapCnt > 0U) | |
| 244 | − { | |
| 245 | − *pStateCur++ = *pState++; | |
| 246 | − | |
| 247 | − /* Decrement loop counter */ | |
| 248 | − tapCnt--; | |
| 249 | − } | |
| 250 | −} | |
| 251 | − | |
| 252 | −// From CMSIS DSP Library | |
| 253 | −float tOversampler_downsample(tOversampler *const osr, float* input) | |
| 254 | −{ | |
| 255 | − _tOversampler* os = *osr; | |
| 256 | − | |
| 257 | − float *pState = os->downState; /* State pointer */ | |
| 258 | − float *pCoeffs = os->pCoeffs; /* Coefficient pointer */ | |
| 259 | − float *pStateCur; /* Points to the current sample of the state */ | |
| 260 | − float *px0; /* Temporary pointer for state buffer */ | |
| 261 | − float *pb; /* Temporary pointer for coefficient buffer */ | |
| 262 | − float x0, c0; /* Temporary variables to hold state and coefficient values */ | |
| 263 | − float acc0; /* Accumulator */ | |
| 264 | − uint32_t numTaps = os->numTaps; /* Number of filter coefficients in the filter */ | |
| 265 | − uint32_t i, tapCnt; | |
| 266 | − float output; | |
| 267 | − | |
| 268 | − /* os->pState buffer contains previous frame (numTaps - 1) samples */ | |
| 269 | − /* pStateCur points to the location where the new input data should be written */ | |
| 270 | − pStateCur = os->downState + (numTaps - 1U); | |
| 271 | − | |
| 272 | − /* Copy decimation factor number of new input samples into the state buffer */ | |
| 273 | − i = os->ratio; | |
| 274 | − | |
| 275 | − do | |
| 276 | − { | |
| 277 | − *pStateCur++ = *input++; | |
| 278 | − | |
| 279 | − } while (--i); | |
| 280 | − | |
| 281 | − /* Set accumulator to zero */ | |
| 282 | − acc0 = 0.0f; | |
| 283 | − | |
| 284 | − /* Initialize state pointer */ | |
| 285 | − px0 = pState; | |
| 286 | − | |
| 287 | − /* Initialize coeff pointer */ | |
| 288 | − pb = pCoeffs; | |
| 289 | − | |
| 290 | − /* Initialize tapCnt with number of taps */ | |
| 291 | − tapCnt = numTaps; | |
| 292 | − | |
| 293 | − while (tapCnt > 0U) | |
| 294 | − { | |
| 295 | − /* Read coefficients */ | |
| 296 | − c0 = *pb++; | |
| 297 | − | |
| 298 | − /* Fetch 1 state variable */ | |
| 299 | − x0 = *px0++; | |
| 300 | − | |
| 301 | − /* Perform the multiply-accumulate */ | |
| 302 | − acc0 += x0 * c0; | |
| 303 | − | |
| 304 | − /* Decrement loop counter */ | |
| 305 | − tapCnt--; | |
| 306 | − } | |
| 307 | − | |
| 308 | − /* Advance the state pointer by the decimation factor | |
| 309 | − * to process the next group of decimation factor number samples */ | |
| 310 | − pState = pState + os->ratio; | |
| 311 | − | |
| 312 | − /* The result is in the accumulator, store in the destination buffer. */ | |
| 313 | − output = acc0; | |
| 314 | − | |
| 315 | − /* Processing is complete. | |
| 316 | − Now copy the last numTaps - 1 samples to the start of the state buffer. | |
| 317 | − This prepares the state buffer for the next function call. */ | |
| 318 | − | |
| 319 | − /* Points to the start of the state buffer */ | |
| 320 | − pStateCur = os->downState; | |
| 321 | − | |
| 322 | − /* Initialize tapCnt with number of taps */ | |
| 323 | − tapCnt = (numTaps - 1U); | |
| 324 | − | |
| 325 | − /* Copy data */ | |
| 326 | − while (tapCnt > 0U) | |
| 327 | − { | |
| 328 | − *pStateCur++ = *pState++; | |
| 329 | − | |
| 330 | − /* Decrement loop counter */ | |
| 331 | − tapCnt--; | |
| 332 | − } | |
| 333 | − | |
| 334 | − return output; | |
| 335 | −} | |
| 336 | − | |
| 337 | −int tOversampler_getLatency(tOversampler* const osr) | |
| 338 | −{ | |
| 339 | − _tOversampler* os = *osr; | |
| 340 | − return os->phaseLength; | |
| 341 | −} | |
| 342 | − | |
| 343 | −//============================================================================================================ | |
| 344 | −// WAVEFOLDER | |
| 345 | −//============================================================================================================ | |
| 346 | − | |
| 347 | − | |
| 348 | −//from the paper: Virtual Analog Model of the Lockhart Wavefolder | |
| 349 | −//by Fabián Esqueda, Henri Pöntynen, Julian D. Parker and Stefan Bilbao | |
| 350 | − | |
| 351 | −void tLockhartWavefolder_init(tLockhartWavefolder* const wf) | |
| 352 | −{ | |
| 353 | − tLockhartWavefolder_initToPool (wf, &leaf.mempool); | |
| 354 | −} | |
| 355 | − | |
| 356 | −void tLockhartWavefolder_free(tLockhartWavefolder* const wf) | |
| 357 | −{ | |
| 358 | − _tLockhartWavefolder* w = *wf; | |
| 359 | − | |
| 360 | − leaf_free((char*)w); | |
| 361 | −} | |
| 362 | − | |
| 363 | −void tLockhartWavefolder_initToPool (tLockhartWavefolder* const wf, tMempool* const mp) | |
| 364 | −{ | |
| 365 | − _tMempool* m = *mp; | |
| 366 | − _tLockhartWavefolder* w = *wf = (_tLockhartWavefolder*) mpool_alloc(sizeof(_tLockhartWavefolder), m); | |
| 367 | − | |
| 368 | − w->Ln1 = 0.0; | |
| 369 | − w->Fn1 = 0.0; | |
| 370 | − w->xn1 = 0.0; | |
| 371 | − | |
| 372 | − w->RL = 7.5e3; | |
| 373 | − w->R = 15e3; | |
| 374 | − w->VT = 26e-3; | |
| 375 | − w->Is = 10e-16; | |
| 376 | − | |
| 377 | − w->a = 2.0*w->RL/w->R; | |
| 378 | − w->b = (w->R+2.0*w->RL)/(w->VT*w->R); | |
| 379 | − w->d = (w->RL*w->Is)/w->VT; | |
| 380 | − w->half_a = 0.5 * w->a; | |
| 381 | − w->longthing = (0.5*w->VT/w->b); | |
| 382 | − | |
| 383 | − | |
| 384 | − // Antialiasing error threshold | |
| 385 | − w->AAthresh = 10e-10; //10 | |
| 386 | − | |
| 387 | − w->LambertThresh = 10e-10; //12 //was 8 | |
| 388 | − | |
| 389 | − | |
| 390 | − w->w = 0.0f; | |
| 391 | − w->expw = 0.0f; | |
| 392 | − w->p = 0.0f; | |
| 393 | − w->r = 0.0f; | |
| 394 | − w->s= 0.0f; | |
| 395 | − w->myerr = 0.0f; | |
| 396 | − w->l = 0.0f; | |
| 397 | − w->u = 0.0f; | |
| 398 | − w->Ln = 0.0f; | |
| 399 | − w->Fn = 0.0f; | |
| 400 | − w->tempsDenom = 0.0f; | |
| 401 | − w->tempErrDenom = 0.0f; | |
| 402 | − w->tempOutDenom = 0.0f; | |
| 403 | − | |
| 404 | − | |
| 405 | −} | |
| 406 | − | |
| 407 | −void tLockhartWavefolder_freeFromPool (tLockhartWavefolder* const wf, tMempool* const mp) | |
| 408 | −{ | |
| 409 | − _tMempool* m = *mp; | |
| 410 | − _tLockhartWavefolder* w = *wf; | |
| 411 | − | |
| 412 | − mpool_free((char*)w, m); | |
| 413 | −} | |
| 414 | − | |
| 415 | − | |
| 416 | − | |
| 417 | −double tLockhartWavefolderLambert(tLockhartWavefolder* const wf, double x, double ln) | |
| 418 | −{ | |
| 419 | − _tLockhartWavefolder* mwf = *wf; | |
| 420 | − | |
| 421 | − | |
| 422 | − // Initial guess (use previous value) | |
| 423 | − mwf->w = ln; | |
| 424 | − | |
| 425 | − // Haley's method (Sec. 4.2 of the paper) | |
| 426 | − for(int i=0; i<3000; i+=1) { //1000 | |
| 427 | − | |
| 428 | − mwf->expw = exp(mwf->w); | |
| 429 | − /* | |
| 430 | − if (isinf(mwf->expw) || isnan(mwf->expw)) | |
| 431 | − { | |
| 432 | − mwf->expw = 10e-5; | |
| 433 | − LEAF_error(); | |
| 434 | − } | |
| 435 | − */ | |
| 436 | − mwf->p = mwf->w*mwf->expw - x; | |
| 437 | − /* | |
| 438 | − if (isinf(mwf->p) || isnan(mwf->p)) | |
| 439 | − { | |
| 440 | − mwf->p = 10e-5; | |
| 441 | − LEAF_error(); | |
| 442 | − } | |
| 443 | − */ | |
| 444 | − mwf->r = (mwf->w+1.0)*mwf->expw; | |
| 445 | − /* | |
| 446 | − if (isinf(mwf->r) || isnan(mwf->r)) | |
| 447 | − { | |
| 448 | − mwf->r = 10e-5; | |
| 449 | − LEAF_error(); | |
| 450 | − } | |
| 451 | − */ | |
| 452 | − mwf->tempsDenom = (2.0*(mwf->w+1.0)); | |
| 453 | − /* | |
| 454 | − if ((mwf->tempsDenom == 0.0) || isinf(mwf->tempsDenom) || isnan(mwf->tempsDenom)) | |
| 455 | − { | |
| 456 | − mwf->tempsDenom = 10e-5; | |
| 457 | − LEAF_error(); | |
| 458 | − } | |
| 459 | − */ | |
| 460 | − mwf->s = (mwf->w+2.0)/mwf->tempsDenom; | |
| 461 | − /* | |
| 462 | − if (isnan(mwf->s) || isinf(mwf->s)) | |
| 463 | − { | |
| 464 | − mwf->s = 10e-5; | |
| 465 | − LEAF_error(); | |
| 466 | − } | |
| 467 | − */ | |
| 468 | − mwf->tempErrDenom = (mwf->r-(mwf->p*mwf->s)); | |
| 469 | − /* | |
| 470 | − if ((mwf->tempErrDenom == 0.0) || isinf(mwf->tempErrDenom) || isnan(mwf->tempErrDenom)) | |
| 471 | − { | |
| 472 | − mwf->tempErrDenom = 10e-5; | |
| 473 | − LEAF_error(); | |
| 474 | − } | |
| 475 | − */ | |
| 476 | − mwf->myerr = (mwf->p/mwf->tempErrDenom); | |
| 477 | − /* | |
| 478 | − if (isnan(mwf->myerr) || isinf(mwf->myerr)) | |
| 479 | − { | |
| 480 | − mwf->myerr = 10e-5; | |
| 481 | − LEAF_error(); | |
| 482 | − } | |
| 483 | − */ | |
| 484 | − | |
| 485 | − if ((fabs(mwf->myerr))<mwf->LambertThresh) { | |
| 486 | − | |
| 487 | − break; | |
| 488 | − } | |
| 489 | − | |
| 490 | − mwf->w = mwf->w - mwf->myerr; | |
| 491 | − | |
| 492 | − /* | |
| 493 | − if (isinf(mwf->w) || isnan(mwf->w)) | |
| 494 | − { | |
| 495 | − mwf->w = 10e-5; | |
| 496 | − LEAF_error(); | |
| 497 | − } | |
| 498 | −*/ | |
| 499 | − | |
| 500 | − } | |
| 501 | − return mwf->w; | |
| 502 | −} | |
| 503 | − | |
| 504 | −float tLockhartWavefolder_tick(tLockhartWavefolder* const wf, float in) | |
| 505 | −{ | |
| 506 | − _tLockhartWavefolder* w = *wf; | |
| 507 | − | |
| 508 | − float out = 0.0f; | |
| 509 | − | |
| 510 | − // Compute Antiderivative | |
| 511 | − w->l = (in > 0.0) - (in < 0.0); | |
| 512 | − w->u = w->d*exp(w->l*w->b*in); | |
| 513 | − /* | |
| 514 | − if ((w->u == 0.0) || isinf(w->u) || isnan(w->u)) | |
| 515 | − { | |
| 516 | − w->u = 10e-5; | |
| 517 | − LEAF_error(); | |
| 518 | − } | |
| 519 | − */ | |
| 520 | − | |
| 521 | − w->Ln = tLockhartWavefolderLambert(wf,w->u,w->Ln1); | |
| 522 | − /* | |
| 523 | − if ((w->Ln == 0.0) || isinf(w->Ln) || isnan(w->Ln)) | |
| 524 | − { | |
| 525 | − w->Ln = 10e-5; | |
| 526 | − LEAF_error(); | |
| 527 | − } | |
| 528 | −*/ | |
| 529 | − w->Fn = (w->longthing*(w->Ln*(w->Ln + 2.0))) - (w->half_a*in*in); | |
| 530 | − /* | |
| 531 | − if ((w->Fn == 0.0) || isinf(w->Fn) || isnan(w->Fn)) | |
| 532 | − { | |
| 533 | − w->Fn = 10e-5; | |
| 534 | − LEAF_error(); | |
| 535 | − } | |
| 536 | − */ | |
| 537 | − // Check for ill-conditioning | |
| 538 | − | |
| 539 | − if (fabs(in-w->xn1)<w->AAthresh) | |
| 540 | − { | |
| 541 | − | |
| 542 | − // Compute Averaged Wavefolder Output | |
| 543 | − double xn = 0.5*(in+w->xn1); | |
| 544 | − w->u = w->d*exp(w->l*w->b*xn); | |
| 545 | − /* | |
| 546 | − if ((w->u == 0.0) || isinf(w->u) || isnan(w->u)) | |
| 547 | − { | |
| 548 | − w->u = 10e-5; | |
| 549 | − LEAF_error(); | |
| 550 | − | |
| 551 | − } | |
| 552 | − */ | |
| 553 | − w->Ln = tLockhartWavefolderLambert(wf,w->u,w->Ln1); | |
| 554 | − /* | |
| 555 | − if ((w->Ln == 0.0) || isinf(w->Ln) || isnan(w->Ln)) | |
| 556 | − { | |
| 557 | − w->Ln = 10e-5; | |
| 558 | − LEAF_error(); | |
| 559 | − } | |
| 560 | − */ | |
| 561 | − out = (float)((w->l*w->VT*w->Ln) - (w->a*xn)); | |
| 562 | − | |
| 563 | − } | |
| 564 | − else | |
| 565 | − { | |
| 566 | − | |
| 567 | − // Apply AA Form | |
| 568 | − w->tempOutDenom = (in-w->xn1); | |
| 569 | − /* | |
| 570 | − if ((w->tempOutDenom == 0.0) || isinf(w->tempOutDenom)) | |
| 571 | − { | |
| 572 | − w->tempOutDenom = 10e-5; | |
| 573 | − LEAF_error(); | |
| 574 | − } | |
| 575 | − */ | |
| 576 | − out = ((w->Fn-w->Fn1)/w->tempOutDenom); | |
| 577 | − /* | |
| 578 | − if (isinf(out) || isnan(out)) | |
| 579 | − { | |
| 580 | − out = 10e-5; | |
| 581 | − LEAF_error(); | |
| 582 | − } | |
| 583 | − */ | |
| 584 | − | |
| 585 | − } | |
| 586 | − | |
| 587 | − // Update States | |
| 588 | − w->Ln1 = w->Ln; | |
| 589 | − w->Fn1 = w->Fn; | |
| 590 | − w->xn1 = (double)in; | |
| 591 | − | |
| 592 | − return out; | |
| 593 | −} | |
| 594 | − | |
| 595 | −//============================================================================================================ | |
| 596 | −// CRUSHER | |
| 597 | −//============================================================================================================ | |
| 598 | −#define SCALAR 5000.f | |
| 599 | − | |
| 600 | −void tCrusher_init (tCrusher* const cr) | |
| 601 | −{ | |
| 602 | − _tCrusher* c = *cr = (_tCrusher*) leaf_alloc(sizeof(_tCrusher)); | |
| 603 | − | |
| 604 | − c->op = 4; | |
| 605 | − c->div = SCALAR; | |
| 606 | − c->rnd = 0.25f; | |
| 607 | − c->srr = 0.25f; | |
| 608 | − tSampleReducer_init(&c->sReducer); | |
| 609 | − c->gain = (c->div / SCALAR) * 0.7f + 0.3f; | |
| 610 | −} | |
| 611 | − | |
| 612 | −void tCrusher_free (tCrusher* const cr) | |
| 613 | −{ | |
| 614 | − _tCrusher* c = *cr; | |
| 615 | − tSampleReducer_free(&c->sReducer); | |
| 616 | − leaf_free((char*)c); | |
| 617 | −} | |
| 618 | − | |
| 619 | −void tCrusher_initToPool (tCrusher* const cr, tMempool* const mp) | |
| 620 | −{ | |
| 621 | − _tMempool* m = *mp; | |
| 622 | − _tCrusher* c = *cr = (_tCrusher*) mpool_alloc(sizeof(_tCrusher), m); | |
| 623 | − | |
| 624 | − c->op = 4; | |
| 625 | − c->div = SCALAR; | |
| 626 | − c->rnd = 0.25f; | |
| 627 | − c->srr = 0.25f; | |
| 628 | − tSampleReducer_initToPool(&c->sReducer, mp); | |
| 629 | − c->gain = (c->div / SCALAR) * 0.7f + 0.3f; | |
| 630 | −} | |
| 631 | − | |
| 632 | −void tCrusher_freeFromPool (tCrusher* const cr, tMempool* const mp) | |
| 633 | −{ | |
| 634 | − _tMempool* m = *mp; | |
| 635 | − _tCrusher* c = *cr; | |
| 636 | − tSampleReducer_freeFromPool(&c->sReducer, mp); | |
| 637 | − mpool_free((char*)c, m); | |
| 638 | −} | |
| 639 | − | |
| 640 | −float tCrusher_tick (tCrusher* const cr, float input) | |
| 641 | −{ | |
| 642 | − _tCrusher* c = *cr; | |
| 643 | − | |
| 644 | − float sample = input; | |
| 645 | − | |
| 646 | − sample *= SCALAR; // SCALAR is 5000 by default | |
| 647 | − | |
| 648 | − sample = (int32_t) sample; | |
| 649 | − | |
| 650 | − sample /= c->div; | |
| 651 | − | |
| 652 | − sample = LEAF_bitwise_xor(sample, c->op << 23); | |
| 653 | − | |
| 654 | − sample = LEAF_clip(-1.f, sample, 1.f); | |
| 655 | − | |
| 656 | − sample = LEAF_round(sample, c->rnd); | |
| 657 | − | |
| 658 | − sample = tSampleReducer_tick(&c->sReducer, sample); | |
| 659 | − | |
| 660 | − return sample * c->gain; | |
| 661 | − | |
| 662 | −} | |
| 663 | − | |
| 664 | −void tCrusher_setOperation (tCrusher* const cr, float op) | |
| 665 | −{ | |
| 666 | − _tCrusher* c = *cr; | |
| 667 | − c->op = (uint32_t) (op * 8.0f); | |
| 668 | −} | |
| 669 | − | |
| 670 | −// 0.0 - 1.0 | |
| 671 | −void tCrusher_setQuality (tCrusher* const cr, float val) | |
| 672 | −{ | |
| 673 | − _tCrusher* c = *cr; | |
| 674 | − | |
| 675 | − val = LEAF_clip(0.0f, val, 1.0f); | |
| 676 | − | |
| 677 | − c->div = 0.01f + val * SCALAR; | |
| 678 | − | |
| 679 | − c->gain = (c->div / SCALAR) * 0.7f + 0.3f; | |
| 680 | −} | |
| 681 | − | |
| 682 | −// what decimal to round to | |
| 683 | −void tCrusher_setRound (tCrusher* const cr, float rnd) | |
| 684 | −{ | |
| 685 | − _tCrusher* c = *cr; | |
| 686 | − c->rnd = fabsf(rnd); | |
| 687 | −} | |
| 688 | − | |
| 689 | −void tCrusher_setSamplingRatio (tCrusher* const cr, float ratio) | |
| 690 | −{ | |
| 691 | − _tCrusher* c = *cr; | |
| 692 | − c->srr = ratio; | |
| 693 | − tSampleReducer_setRatio(&c->sReducer, ratio); | |
| 694 | − | |
| 695 | −} | |
| @@ -1,281 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-dynamics.c | |
| 4 | − Created: 30 Nov 2018 11:56:49am | |
| 5 | − Author: airship | |
| 6 | − | |
| 7 | −==============================================================================*/ | |
| 8 | − | |
| 9 | −#if _WIN32 || _WIN64 | |
| 10 | − | |
| 11 | −#include "..\Inc\leaf-dynamics.h" | |
| 12 | − | |
| 13 | −#else | |
| 14 | − | |
| 15 | −#include "../Inc/leaf-dynamics.h" | |
| 16 | − | |
| 17 | −#endif | |
| 18 | − | |
| 19 | −//============================================================================== | |
| 20 | − | |
| 21 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Compressor ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 22 | − | |
| 23 | −/* | |
| 24 | − tCompressor* tCompressorInit(int tauAttack, int tauRelease) | |
| 25 | − { | |
| 26 | − tCompressor* c = &leaf.tCompressorRegistry[leaf.registryIndex[T_COMPRESSOR]++]; | |
| 27 | − | |
| 28 | − c->tauAttack = tauAttack; | |
| 29 | − c->tauRelease = tauRelease; | |
| 30 | − | |
| 31 | − c->x_G[0] = 0.0f, c->x_G[1] = 0.0f, | |
| 32 | − c->y_G[0] = 0.0f, c->y_G[1] = 0.0f, | |
| 33 | − c->x_T[0] = 0.0f, c->x_T[1] = 0.0f, | |
| 34 | − c->y_T[0] = 0.0f, c->y_T[1] = 0.0f; | |
| 35 | − | |
| 36 | − c->T = 0.0f; // Threshold | |
| 37 | − c->R = 1.0f; // compression Ratio | |
| 38 | − c->M = 0.0f; // decibel Make-up gain | |
| 39 | − c->W = 0.0f; // decibel Width of knee transition | |
| 40 | − | |
| 41 | − return c; | |
| 42 | − } | |
| 43 | − */ | |
| 44 | −void tCompressor_init(tCompressor* const comp) | |
| 45 | −{ | |
| 46 | − _tCompressor* c = *comp = (_tCompressor*) leaf_alloc(sizeof(_tCompressor)); | |
| 47 | − | |
| 48 | − c->tauAttack = 100; | |
| 49 | − c->tauRelease = 100; | |
| 50 | − | |
| 51 | − c->isActive = OFALSE; | |
| 52 | − | |
| 53 | − c->T = 0.0f; // Threshold | |
| 54 | − c->R = 0.5f; // compression Ratio | |
| 55 | − c->M = 3.0f; // decibel Width of knee transition | |
| 56 | − c->W = 1.0f; // decibel Make-up gain | |
| 57 | −} | |
| 58 | − | |
| 59 | −void tCompressor_free(tCompressor* const comp) | |
| 60 | −{ | |
| 61 | − _tCompressor* c = *comp; | |
| 62 | − | |
| 63 | − leaf_free((char*)c); | |
| 64 | −} | |
| 65 | − | |
| 66 | −void tCompressor_initToPool (tCompressor* const comp, tMempool* const mp) | |
| 67 | −{ | |
| 68 | − _tMempool* m = *mp; | |
| 69 | − _tCompressor* c = *comp = (_tCompressor*) mpool_alloc(sizeof(_tCompressor), m); | |
| 70 | − | |
| 71 | − c->tauAttack = 100; | |
| 72 | − c->tauRelease = 100; | |
| 73 | − | |
| 74 | − c->isActive = OFALSE; | |
| 75 | − | |
| 76 | − c->T = 0.0f; // Threshold | |
| 77 | − c->R = 0.5f; // compression Ratio | |
| 78 | − c->M = 3.0f; // decibel Width of knee transition | |
| 79 | − c->W = 1.0f; // decibel Make-up gain | |
| 80 | −} | |
| 81 | − | |
| 82 | −void tCompressor_freeFromPool(tCompressor* const comp, tMempool* const mp) | |
| 83 | −{ | |
| 84 | − _tMempool* m = *mp; | |
| 85 | − _tCompressor* c = *comp; | |
| 86 | − | |
| 87 | − mpool_free((char*)c, m); | |
| 88 | −} | |
| 89 | − | |
| 90 | −float tCompressor_tick(tCompressor* const comp, float in) | |
| 91 | −{ | |
| 92 | − _tCompressor* c = *comp; | |
| 93 | − | |
| 94 | − float slope, overshoot; | |
| 95 | − float alphaAtt, alphaRel; | |
| 96 | − | |
| 97 | − float in_db = 20.0f * log10f( fmaxf( fabsf( in), 0.000001f)), out_db = 0.0f; | |
| 98 | − | |
| 99 | − c->y_T[1] = c->y_T[0]; | |
| 100 | − | |
| 101 | − slope = c->R - 1.0f; // feed-forward topology; was 1/C->R - 1 | |
| 102 | − | |
| 103 | − overshoot = in_db - c->T; | |
| 104 | − | |
| 105 | − | |
| 106 | − if (overshoot <= -(c->W * 0.5f)) | |
| 107 | − { | |
| 108 | − out_db = in_db; | |
| 109 | − c->isActive = OFALSE; | |
| 110 | − } | |
| 111 | − else if ((overshoot > -(c->W * 0.5f)) && (overshoot < (c->W * 0.5f))) | |
| 112 | − { | |
| 113 | − out_db = in_db + slope * (powf((overshoot + c->W*0.5f),2) / (2.0f * c->W)); // .^ 2 ??? | |
| 114 | − c->isActive = OTRUE; | |
| 115 | − } | |
| 116 | − else if (overshoot >= (c->W * 0.5f)) | |
| 117 | − { | |
| 118 | − out_db = in_db + slope * overshoot; | |
| 119 | − c->isActive = OTRUE; | |
| 120 | − } | |
| 121 | − | |
| 122 | − | |
| 123 | − | |
| 124 | − c->x_T[0] = out_db - in_db; | |
| 125 | − | |
| 126 | − alphaAtt = expf(-1.0f/(0.001f * c->tauAttack * leaf.sampleRate)); | |
| 127 | − alphaRel = expf(-1.0f/(0.001f * c->tauRelease * leaf.sampleRate)); | |
| 128 | − | |
| 129 | − if (c->x_T[0] > c->y_T[1]) | |
| 130 | − c->y_T[0] = alphaAtt * c->y_T[1] + (1-alphaAtt) * c->x_T[0]; | |
| 131 | − else | |
| 132 | − c->y_T[0] = alphaRel * c->y_T[1] + (1-alphaRel) * c->x_T[0]; | |
| 133 | − | |
| 134 | − float attenuation = powf(10.0f, ((c->M - c->y_T[0])/20.0f)); | |
| 135 | − | |
| 136 | − return attenuation * in; | |
| 137 | −} | |
| 138 | − | |
| 139 | −/* Feedback Leveler */ | |
| 140 | − | |
| 141 | −void tFeedbackLeveler_init(tFeedbackLeveler* const fb, float targetLevel, float factor, float strength, int mode) | |
| 142 | −{ | |
| 143 | − _tFeedbackLeveler* p = *fb = (_tFeedbackLeveler*) leaf_alloc(sizeof(_tFeedbackLeveler)); | |
| 144 | − | |
| 145 | − p->curr=0.0f; | |
| 146 | − p->targetLevel=targetLevel; | |
| 147 | − tPowerFollower_init(&p->pwrFlw,factor); | |
| 148 | − p->mode=mode; | |
| 149 | − p->strength=strength; | |
| 150 | −} | |
| 151 | − | |
| 152 | −void tFeedbackLeveler_free(tFeedbackLeveler* const fb) | |
| 153 | −{ | |
| 154 | − _tFeedbackLeveler* p = *fb; | |
| 155 | − | |
| 156 | − tPowerFollower_free(&p->pwrFlw); | |
| 157 | − leaf_free((char*)p); | |
| 158 | −} | |
| 159 | − | |
| 160 | −void tFeedbackLeveler_initToPool (tFeedbackLeveler* const fb, float targetLevel, float factor, float strength, int mode, tMempool* const mp) | |
| 161 | −{ | |
| 162 | − _tMempool* m = *mp; | |
| 163 | − _tFeedbackLeveler* p = *fb = (_tFeedbackLeveler*) mpool_alloc(sizeof(_tFeedbackLeveler), m); | |
| 164 | − | |
| 165 | − p->curr=0.0f; | |
| 166 | − p->targetLevel=targetLevel; | |
| 167 | − tPowerFollower_initToPool(&p->pwrFlw,factor, mp); | |
| 168 | − p->mode=mode; | |
| 169 | − p->strength=strength; | |
| 170 | −} | |
| 171 | − | |
| 172 | −void tFeedbackLeveler_freeFromPool (tFeedbackLeveler* const fb, tMempool* const mp) | |
| 173 | −{ | |
| 174 | − _tMempool* m = *mp; | |
| 175 | − _tFeedbackLeveler* p = *fb; | |
| 176 | − | |
| 177 | − tPowerFollower_freeFromPool(&p->pwrFlw, mp); | |
| 178 | − mpool_free((char*)p, m); | |
| 179 | −} | |
| 180 | − | |
| 181 | −void tFeedbackLeveler_setStrength(tFeedbackLeveler* const fb, float strength) | |
| 182 | −{ // strength is how strongly level diff is affecting the amp ratio | |
| 183 | − // try 0.125 for a start | |
| 184 | − _tFeedbackLeveler* p = *fb; | |
| 185 | − p->strength=strength; | |
| 186 | −} | |
| 187 | − | |
| 188 | −void tFeedbackLeveler_setFactor(tFeedbackLeveler* const fb, float factor) | |
| 189 | −{ | |
| 190 | − _tFeedbackLeveler* p = *fb; | |
| 191 | − tPowerFollower_setFactor(&p->pwrFlw,factor); | |
| 192 | −} | |
| 193 | − | |
| 194 | −void tFeedbackLeveler_setMode(tFeedbackLeveler* const fb, int mode) | |
| 195 | −{ // 0 for decaying with upwards lev limiting, 1 for constrained absolute level (also downwards limiting) | |
| 196 | − _tFeedbackLeveler* p = *fb; | |
| 197 | − p->mode=mode; | |
| 198 | −} | |
| 199 | − | |
| 200 | −float tFeedbackLeveler_tick(tFeedbackLeveler* const fb, float input) | |
| 201 | −{ | |
| 202 | − _tFeedbackLeveler* p = *fb; | |
| 203 | − float levdiff=(tPowerFollower_tick(&p->pwrFlw, input)-p->targetLevel); | |
| 204 | − if (p->mode==0 && levdiff<0.0f) levdiff=0.0f; | |
| 205 | − p->curr=input*(1.0f-p->strength*levdiff); | |
| 206 | − return p->curr; | |
| 207 | −} | |
| 208 | − | |
| 209 | −float tFeedbackLeveler_sample(tFeedbackLeveler* const fb) | |
| 210 | −{ | |
| 211 | − _tFeedbackLeveler* p = *fb; | |
| 212 | − return p->curr; | |
| 213 | −} | |
| 214 | − | |
| 215 | − | |
| 216 | −void tFeedbackLeveler_setTargetLevel (tFeedbackLeveler* const fb, float TargetLevel) | |
| 217 | −{ | |
| 218 | − _tFeedbackLeveler* p = *fb; | |
| 219 | − p->targetLevel=TargetLevel; | |
| 220 | −} | |
| 221 | − | |
| 222 | − | |
| 223 | − | |
| 224 | −void tThreshold_init(tThreshold* const th, float low, float high) | |
| 225 | −{ | |
| 226 | − tThreshold_initToPool(th, low, high, &leaf.mempool); | |
| 227 | −} | |
| 228 | − | |
| 229 | −void tThreshold_free(tThreshold* const th) | |
| 230 | −{ | |
| 231 | − tThreshold_freeFromPool(th, &leaf.mempool); | |
| 232 | −} | |
| 233 | − | |
| 234 | −void tThreshold_initToPool (tThreshold* const th, float low, float high, tMempool* const mp) | |
| 235 | −{ | |
| 236 | − _tMempool* m = *mp; | |
| 237 | − _tThreshold* t = *th = (_tThreshold*) mpool_alloc(sizeof(_tThreshold), m); | |
| 238 | − | |
| 239 | − t->highThresh = high; | |
| 240 | − t->lowThresh = low; | |
| 241 | − | |
| 242 | − t->currentValue = 0; | |
| 243 | −} | |
| 244 | − | |
| 245 | −void tThreshold_freeFromPool(tThreshold* const th, tMempool* const mp) | |
| 246 | −{ | |
| 247 | − _tMempool* m = *mp; | |
| 248 | − _tThreshold* t = *th; | |
| 249 | − | |
| 250 | − mpool_free((char*)t, m); | |
| 251 | −} | |
| 252 | − | |
| 253 | −int tThreshold_tick(tThreshold* const th, float in) | |
| 254 | −{ | |
| 255 | − _tThreshold* t = *th; | |
| 256 | − | |
| 257 | − if (in >= t->highThresh) | |
| 258 | − { | |
| 259 | − t->currentValue = 1; | |
| 260 | − } | |
| 261 | − else if (in <= t->lowThresh) | |
| 262 | − { | |
| 263 | − t->currentValue = 0; | |
| 264 | − } | |
| 265 | − | |
| 266 | − return t->currentValue; | |
| 267 | −} | |
| 268 | − | |
| 269 | −void tThreshold_setLow(tThreshold* const th, float low) | |
| 270 | −{ | |
| 271 | − _tThreshold* t = *th; | |
| 272 | − | |
| 273 | − t->lowThresh = low; | |
| 274 | −} | |
| 275 | − | |
| 276 | −void tThreshold_setHigh(tThreshold* const th, float high) | |
| 277 | −{ | |
| 278 | − _tThreshold* t = *th; | |
| 279 | − | |
| 280 | − t->highThresh = high; | |
| 281 | −} | |
| @@ -1,1853 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-vocoder.c | |
| 4 | − Created: 20 Jan 2017 12:01:54pm | |
| 5 | − Author: Michael R Mulshine | |
| 6 | − | |
| 7 | − ==============================================================================*/ | |
| 8 | − | |
| 9 | −#if _WIN32 || _WIN64 | |
| 10 | − | |
| 11 | −#include "..\Inc\leaf-effects.c" | |
| 12 | −#include "..\leaf.h" | |
| 13 | − | |
| 14 | −#else | |
| 15 | − | |
| 16 | −#include "../Inc/leaf-effects.h" | |
| 17 | −#include "../leaf.h" | |
| 18 | − | |
| 19 | −#endif | |
| 20 | − | |
| 21 | − | |
| 22 | − | |
| 23 | −//============================================================================================================ | |
| 24 | −// TALKBOX | |
| 25 | −//============================================================================================================ | |
| 26 | − | |
| 27 | −//LPC vocoder adapted from MDA's excellent open source talkbox plugin code | |
| 28 | −void tTalkbox_init(tTalkbox* const voc, int bufsize) | |
| 29 | −{ | |
| 30 | − | |
| 31 | − _tTalkbox* v = *voc = (_tTalkbox*) leaf_alloc(sizeof(_tTalkbox)); | |
| 32 | − | |
| 33 | − v->param[0] = 0.5f; //wet | |
| 34 | − v->param[1] = 0.0f; //dry | |
| 35 | − v->param[2] = 0; // Swap | |
| 36 | − v->param[3] = 1.0f; //quality | |
| 37 | − v->warpFactor = 0.0f; | |
| 38 | − v->warpOn = 0; | |
| 39 | − v->bufsize = bufsize; | |
| 40 | − | |
| 41 | − v->car0 = (float*) leaf_alloc(sizeof(float) * v->bufsize); | |
| 42 | − v->car1 = (float*) leaf_alloc(sizeof(float) * v->bufsize); | |
| 43 | − v->window = (float*) leaf_alloc(sizeof(float) * v->bufsize); | |
| 44 | − v->buf0 = (float*) leaf_alloc(sizeof(float) * v->bufsize); | |
| 45 | − v->buf1 = (float*) leaf_alloc(sizeof(float) * v->bufsize); | |
| 46 | − | |
| 47 | − tTalkbox_update(voc); | |
| 48 | − tTalkbox_suspend(voc); | |
| 49 | −} | |
| 50 | − | |
| 51 | −void tTalkbox_free(tTalkbox* const voc) | |
| 52 | −{ | |
| 53 | − _tTalkbox* v = *voc; | |
| 54 | − | |
| 55 | − leaf_free((char*)v->buf1); | |
| 56 | − leaf_free((char*)v->buf0); | |
| 57 | − leaf_free((char*)v->window); | |
| 58 | − leaf_free((char*)v->car1); | |
| 59 | − leaf_free((char*)v->car0); | |
| 60 | − | |
| 61 | − leaf_free((char*)v); | |
| 62 | −} | |
| 63 | − | |
| 64 | −void tTalkbox_initToPool (tTalkbox* const voc, int bufsize, tMempool* const mp) | |
| 65 | −{ | |
| 66 | − _tMempool* m = *mp; | |
| 67 | − _tTalkbox* v = *voc = (_tTalkbox*) mpool_alloc(sizeof(_tTalkbox), m); | |
| 68 | − | |
| 69 | − v->param[0] = 0.5f; //wet | |
| 70 | − v->param[1] = 0.0f; //dry | |
| 71 | − v->param[2] = 0; // Swap | |
| 72 | − v->param[3] = 1.0f; //quality | |
| 73 | − v->warpFactor = 0.0f; | |
| 74 | − v->warpOn = 0; | |
| 75 | − v->bufsize = bufsize; | |
| 76 | − | |
| 77 | − v->car0 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m); | |
| 78 | − v->car1 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m); | |
| 79 | − v->window = (float*) mpool_alloc(sizeof(float) * v->bufsize, m); | |
| 80 | − v->buf0 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m); | |
| 81 | − v->buf1 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m); | |
| 82 | − | |
| 83 | − tTalkbox_update(voc); | |
| 84 | − tTalkbox_suspend(voc); | |
| 85 | −} | |
| 86 | − | |
| 87 | −void tTalkbox_freeFromPool (tTalkbox* const voc, tMempool* const mp) | |
| 88 | −{ | |
| 89 | − _tMempool* m = *mp; | |
| 90 | − _tTalkbox* v = *voc; | |
| 91 | − | |
| 92 | − mpool_free((char*)v->buf1, m); | |
| 93 | − mpool_free((char*)v->buf0, m); | |
| 94 | − mpool_free((char*)v->window, m); | |
| 95 | − mpool_free((char*)v->car1, m); | |
| 96 | − mpool_free((char*)v->car0, m); | |
| 97 | − | |
| 98 | − mpool_free((char*)v, m); | |
| 99 | −} | |
| 100 | − | |
| 101 | −void tTalkbox_update(tTalkbox* const voc) ///update internal parameters... | |
| 102 | −{ | |
| 103 | − _tTalkbox* v = *voc; | |
| 104 | − | |
| 105 | − float fs = leaf.sampleRate; | |
| 106 | − if(fs < 8000.0f) fs = 8000.0f; | |
| 107 | − if(fs > 96000.0f) fs = 96000.0f; | |
| 108 | − | |
| 109 | − int32_t n = (int32_t)(0.01633f * fs); //this sets the window time to 16ms if the buffer is large enough. Buffer needs to be at least 784 samples at 48000 | |
| 110 | − if(n > v->bufsize) n = v->bufsize; | |
| 111 | − | |
| 112 | − //O = (VstInt32)(0.0005f * fs); | |
| 113 | − v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * fs); | |
| 114 | − | |
| 115 | − if(n != v->N) //recalc hanning window | |
| 116 | − { | |
| 117 | − v->N = n; | |
| 118 | − float dp = TWO_PI / v->N; | |
| 119 | − float p = 0.0f; | |
| 120 | − for(n=0; n<v->N; n++) | |
| 121 | − { | |
| 122 | − v->window[n] = 0.5f - 0.5f * cosf(p); | |
| 123 | − p += dp; | |
| 124 | − } | |
| 125 | − } | |
| 126 | − v->wet = 0.5f * v->param[0] * v->param[0]; | |
| 127 | − v->dry = 2.0f * v->param[1] * v->param[1]; | |
| 128 | −} | |
| 129 | − | |
| 130 | −void tTalkbox_suspend(tTalkbox* const voc) ///clear any buffers... | |
| 131 | −{ | |
| 132 | − _tTalkbox* v = *voc; | |
| 133 | − | |
| 134 | − v->pos = v->K = 0; | |
| 135 | − v->emphasis = 0.0f; | |
| 136 | − v->FX = 0; | |
| 137 | − | |
| 138 | − v->u0 = v->u1 = v->u2 = v->u3 = v->u4 = 0.0f; | |
| 139 | − v->d0 = v->d1 = v->d2 = v->d3 = v->d4 = 0.0f; | |
| 140 | − | |
| 141 | − for (int32_t i = 0; i < v->bufsize; i++) | |
| 142 | − { | |
| 143 | − v->buf0[i] = 0; | |
| 144 | − v->buf1[i] = 0; | |
| 145 | − v->car0[i] = 0; | |
| 146 | − v->car1[i] = 0; | |
| 147 | − } | |
| 148 | −} | |
| 149 | − | |
| 150 | −// warped autocorrelation adapted from ten.enegatum@liam's post on music-dsp 2004-04-07 09:37:51 | |
| 151 | −//find the order-P autocorrelation array, R, for the sequence x of length L and warping of lambda | |
| 152 | −//wAutocorrelate(&pfSrc[stIndex],siglen,R,P,0); | |
| 153 | −void tTalkbox_warpedAutocorrelate(float * x, unsigned int L, float * R, unsigned int P, float lambda) | |
| 154 | −{ | |
| 155 | − double dl[L]; | |
| 156 | − double Rt[L]; | |
| 157 | − double r1,r2,r1t; | |
| 158 | − R[0]=0; | |
| 159 | − Rt[0]=0; | |
| 160 | − r1=0; | |
| 161 | − r2=0; | |
| 162 | − r1t=0; | |
| 163 | − for(int32_t k=0; k<L;k++) | |
| 164 | − { | |
| 165 | − Rt[0] += (double)(x[k]) * (double)(x[k]); | |
| 166 | − | |
| 167 | − dl[k]= r1 - (double)(lambda) * (double)(x[k]-r2); | |
| 168 | − r1 = x[k]; | |
| 169 | − r2 = dl[k]; | |
| 170 | − } | |
| 171 | − for(int32_t i=1; i<=P; i++) | |
| 172 | − { | |
| 173 | − Rt[i]=0; | |
| 174 | − r1=0; | |
| 175 | − r2=0; | |
| 176 | − for(unsigned int k=0; k<L;k++) | |
| 177 | − { | |
| 178 | − Rt[i] += (double) (dl[k]) * (double)(x[k]); | |
| 179 | − | |
| 180 | − r1t = dl[k]; | |
| 181 | − dl[k]= r1 - (double)(lambda) * (double)(r1t-r2); | |
| 182 | − r1 = r1t; | |
| 183 | − r2 = dl[k]; | |
| 184 | − } | |
| 185 | − } | |
| 186 | − for(int32_t i=0; i<=P; i++) | |
| 187 | − { | |
| 188 | − R[i]=(float)(Rt[i]); | |
| 189 | − } | |
| 190 | − | |
| 191 | −} | |
| 192 | − | |
| 193 | − | |
| 194 | − | |
| 195 | −#define ORD_MAX 35 // Was 100. | |
| 196 | −// order is defined by the set_quality function. | |
| 197 | −// it's set to max out at 0.0005 of sample rate (if you don't go above 1.0f in the quality setting) == at 48000 that's 24. | |
| 198 | −// -JS | |
| 199 | −void tTalkbox_lpc(float *buf, float *car, int32_t n, int32_t o, float warp, int warpOn) | |
| 200 | −{ | |
| 201 | − float z[ORD_MAX], r[ORD_MAX], k[ORD_MAX], G, x; | |
| 202 | − int32_t i, j, nn=n; | |
| 203 | − | |
| 204 | − if (warpOn == 0) | |
| 205 | − { | |
| 206 | − for(j=0; j<=o; j++, nn--) //buf[] is already emphasized and windowed | |
| 207 | − { | |
| 208 | − z[j] = r[j] = 0.0f; | |
| 209 | − for(i=0; i<nn; i++) r[j] += buf[i] * buf[i+j]; //autocorrelation | |
| 210 | − } | |
| 211 | − } | |
| 212 | − else | |
| 213 | − { | |
| 214 | − for(j=0; j<=o; j++, nn--) //buf[] is already emphasized and windowed | |
| 215 | − { | |
| 216 | − z[j] = r[j] = 0.0f; | |
| 217 | − } | |
| 218 | − tTalkbox_warpedAutocorrelate(buf, n, r, o, warp); | |
| 219 | − } | |
| 220 | − | |
| 221 | − r[0] *= 1.001f; //stability fix | |
| 222 | − | |
| 223 | − float min = 0.00001f; | |
| 224 | − if(r[0] < min) { for(i=0; i<n; i++) buf[i] = 0.0f; return; } | |
| 225 | − | |
| 226 | − tTalkbox_lpcDurbin(r, o, k, &G); //calc reflection coeffs | |
| 227 | − | |
| 228 | − //this is for stability to keep reflection coefficients inside the unit circle | |
| 229 | − //but in Harma's papers I've seen 0.998. just needs to be less than 1 it seems but maybe some wiggle room to avoid instability from floating point precision -JS | |
| 230 | − for(i=0; i<=o; i++) | |
| 231 | − { | |
| 232 | − if(k[i] > 0.995f) k[i] = 0.995f; else if(k[i] < -0.995f) k[i] = -.995f; | |
| 233 | − } | |
| 234 | − | |
| 235 | − for(i=0; i<n; i++) | |
| 236 | − { | |
| 237 | − x = G * car[i]; | |
| 238 | − for(j=o; j>0; j--) //lattice filter | |
| 239 | − { | |
| 240 | − x -= k[j] * z[j-1]; | |
| 241 | − z[j] = z[j-1] + k[j] * x; | |
| 242 | − } | |
| 243 | − buf[i] = z[0] = x; //output buf[] will be windowed elsewhere | |
| 244 | − } | |
| 245 | −} | |
| 246 | − | |
| 247 | − | |
| 248 | −void tTalkbox_lpcDurbin(float *r, int p, float *k, float *g) | |
| 249 | −{ | |
| 250 | − int i, j; | |
| 251 | − float a[ORD_MAX], at[ORD_MAX], e=r[0]; | |
| 252 | − | |
| 253 | − for(i=0; i<=p; i++) a[i] = 0.0f; //probably don't need to clear at[] or k[] | |
| 254 | − at[0] = 0.0f; | |
| 255 | − for(i=1; i<=p; i++) | |
| 256 | − { | |
| 257 | − k[i] = -r[i]; | |
| 258 | − | |
| 259 | − for(j=1; j<i; j++) | |
| 260 | − { | |
| 261 | − at[j] = a[j]; | |
| 262 | − k[i] -= a[j] * r[i-j]; | |
| 263 | − } | |
| 264 | − if(fabs(e) < 1.0e-20f) { e = 0.0f; break; } | |
| 265 | − k[i] /= e; | |
| 266 | − | |
| 267 | − a[i] = k[i]; | |
| 268 | − for(j=1; j<i; j++) a[j] = at[j] + k[i] * at[i-j]; | |
| 269 | − | |
| 270 | − e *= 1.0f - k[i] * k[i]; | |
| 271 | − } | |
| 272 | − | |
| 273 | − if(e < 1.0e-20f) e = 0.0f; | |
| 274 | − *g = sqrtf(e); | |
| 275 | −} | |
| 276 | − | |
| 277 | −float tTalkbox_tick(tTalkbox* const voc, float synth, float voice) | |
| 278 | −{ | |
| 279 | − _tTalkbox* v = *voc; | |
| 280 | − | |
| 281 | − int32_t p0=v->pos, p1 = (v->pos + v->N/2) % v->N; | |
| 282 | − float e=v->emphasis, w, o, x, fx=v->FX; | |
| 283 | − float p, q, h0=0.3f, h1=0.77f; | |
| 284 | − | |
| 285 | − o = voice; | |
| 286 | − x = synth; | |
| 287 | − | |
| 288 | − | |
| 289 | − | |
| 290 | − p = v->d0 + h0 * x; v->d0 = v->d1; v->d1 = x - h0 * p; | |
| 291 | − q = v->d2 + h1 * v->d4; v->d2 = v->d3; v->d3 = v->d4 - h1 * q; | |
| 292 | − v->d4 = x; | |
| 293 | − x = p + q; | |
| 294 | − | |
| 295 | − if(v->K++) | |
| 296 | − { | |
| 297 | − v->K = 0; | |
| 298 | − | |
| 299 | − v->car0[p0] = v->car1[p1] = x; //carrier input | |
| 300 | − | |
| 301 | − x = o - e; e = o; //6dB/oct pre-emphasis | |
| 302 | − | |
| 303 | − w = v->window[p0]; fx = v->buf0[p0] * w; v->buf0[p0] = x * w; //50% overlapping hanning windows | |
| 304 | − if(++p0 >= v->N) { tTalkbox_lpc(v->buf0, v->car0, v->N, v->O, v->warpFactor, v->warpOn); p0 = 0; } | |
| 305 | − | |
| 306 | − w = 1.0f - w; fx += v->buf1[p1] * w; v->buf1[p1] = x * w; | |
| 307 | − if(++p1 >= v->N) { tTalkbox_lpc(v->buf1, v->car1, v->N, v->O, v->warpFactor, v->warpOn); p1 = 0; } | |
| 308 | − } | |
| 309 | − | |
| 310 | − p = v->u0 + h0 * fx; v->u0 = v->u1; v->u1 = fx - h0 * p; | |
| 311 | − q = v->u2 + h1 * v->u4; v->u2 = v->u3; v->u3 = v->u4 - h1 * q; | |
| 312 | − v->u4 = fx; | |
| 313 | − x = p + q; | |
| 314 | − | |
| 315 | − o = x; | |
| 316 | − | |
| 317 | − v->emphasis = e; | |
| 318 | − v->pos = p0; | |
| 319 | − v->FX = fx; | |
| 320 | − | |
| 321 | − | |
| 322 | − return o; | |
| 323 | −} | |
| 324 | − | |
| 325 | −void tTalkbox_setQuality(tTalkbox* const voc, float quality) | |
| 326 | −{ | |
| 327 | − _tTalkbox* v = *voc; | |
| 328 | − | |
| 329 | − v->param[3] = quality; | |
| 330 | − v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * leaf.sampleRate); | |
| 331 | − if (v->O >= ORD_MAX) | |
| 332 | − { | |
| 333 | − v->O = ORD_MAX-1; | |
| 334 | − } | |
| 335 | −} | |
| 336 | − | |
| 337 | −void tTalkbox_setWarpFactor(tTalkbox* const voc, float warpFactor) | |
| 338 | −{ | |
| 339 | − _tTalkbox* v = *voc; | |
| 340 | − | |
| 341 | − v->warpFactor = warpFactor; | |
| 342 | −} | |
| 343 | − | |
| 344 | −void tTalkbox_setWarpOn(tTalkbox* const voc, float warpOn) | |
| 345 | −{ | |
| 346 | − _tTalkbox* v = *voc; | |
| 347 | − | |
| 348 | − v->warpOn = warpOn; | |
| 349 | −} | |
| 350 | − | |
| 351 | − | |
| 352 | −//============================================================================================================ | |
| 353 | −// VOCODER | |
| 354 | −//============================================================================================================ | |
| 355 | − | |
| 356 | −void tVocoder_init (tVocoder* const voc) | |
| 357 | −{ | |
| 358 | − _tVocoder* v = *voc = (_tVocoder*) leaf_alloc(sizeof(_tVocoder)); | |
| 359 | − | |
| 360 | − v->param[0] = 0.33f; //input select | |
| 361 | − v->param[1] = 0.50f; //output dB | |
| 362 | − v->param[2] = 0.40f; //hi thru | |
| 363 | − v->param[3] = 0.40f; //hi band | |
| 364 | − v->param[4] = 0.16f; //envelope | |
| 365 | − v->param[5] = 0.55f; //filter q | |
| 366 | − v->param[6] = 0.6667f;//freq range | |
| 367 | − v->param[7] = 0.33f; //num bands | |
| 368 | − | |
| 369 | − tVocoder_update(voc); | |
| 370 | −} | |
| 371 | − | |
| 372 | −void tVocoder_free (tVocoder* const voc) | |
| 373 | −{ | |
| 374 | − _tVocoder* v = *voc; | |
| 375 | − | |
| 376 | − leaf_free((char*)v); | |
| 377 | −} | |
| 378 | − | |
| 379 | −void tVocoder_initToPool (tVocoder* const voc, tMempool* const mp) | |
| 380 | −{ | |
| 381 | − _tMempool* m = *mp; | |
| 382 | − _tVocoder* v = *voc = (_tVocoder*) mpool_alloc(sizeof(_tVocoder), m); | |
| 383 | − | |
| 384 | − v->param[0] = 0.33f; //input select | |
| 385 | − v->param[1] = 0.50f; //output dB | |
| 386 | − v->param[2] = 0.40f; //hi thru | |
| 387 | − v->param[3] = 0.40f; //hi band | |
| 388 | − v->param[4] = 0.16f; //envelope | |
| 389 | − v->param[5] = 0.55f; //filter q | |
| 390 | − v->param[6] = 0.6667f;//freq range | |
| 391 | − v->param[7] = 0.33f; //num bands | |
| 392 | − | |
| 393 | − tVocoder_update(voc); | |
| 394 | −} | |
| 395 | − | |
| 396 | −void tVocoder_freeFromPool (tVocoder* const voc, tMempool* const mp) | |
| 397 | −{ | |
| 398 | − _tMempool* m = *mp; | |
| 399 | − _tVocoder* v = *voc; | |
| 400 | − | |
| 401 | − mpool_free((char*)v, m); | |
| 402 | −} | |
| 403 | − | |
| 404 | −void tVocoder_update (tVocoder* const voc) | |
| 405 | −{ | |
| 406 | − _tVocoder* v = *voc; | |
| 407 | − | |
| 408 | − float tpofs = 6.2831853f * leaf.invSampleRate; | |
| 409 | − | |
| 410 | − float rr, th, re; | |
| 411 | − | |
| 412 | − float sh; | |
| 413 | − | |
| 414 | − int32_t i; | |
| 415 | − | |
| 416 | − v->gain = (float)pow(10.0f, 2.0f * v->param[1] - 3.0f * v->param[5] - 2.0f); | |
| 417 | − | |
| 418 | − v->thru = (float)pow(10.0f, 0.5f + 2.0f * v->param[1]); | |
| 419 | − v->high = v->param[3] * v->param[3] * v->param[3] * v->thru; | |
| 420 | − v->thru *= v->param[2] * v->param[2] * v->param[2]; | |
| 421 | − | |
| 422 | − if(v->param[7]<0.5f) | |
| 423 | − { | |
| 424 | − v->nbnd=8; | |
| 425 | − re=0.003f; | |
| 426 | − v->f[1][2] = 3000.0f; | |
| 427 | − v->f[2][2] = 2200.0f; | |
| 428 | − v->f[3][2] = 1500.0f; | |
| 429 | − v->f[4][2] = 1080.0f; | |
| 430 | − v->f[5][2] = 700.0f; | |
| 431 | − v->f[6][2] = 390.0f; | |
| 432 | − v->f[7][2] = 190.0f; | |
| 433 | − } | |
| 434 | − else | |
| 435 | − { | |
| 436 | − v->nbnd=16; | |
| 437 | − re=0.0015f; | |
| 438 | − v->f[ 1][2] = 5000.0f; //+1000 | |
| 439 | − v->f[ 2][2] = 4000.0f; //+750 | |
| 440 | − v->f[ 3][2] = 3250.0f; //+500 | |
| 441 | − v->f[ 4][2] = 2750.0f; //+450 | |
| 442 | − v->f[ 5][2] = 2300.0f; //+300 | |
| 443 | − v->f[ 6][2] = 2000.0f; //+250 | |
| 444 | − v->f[ 7][2] = 1750.0f; //+250 | |
| 445 | − v->f[ 8][2] = 1500.0f; //+250 | |
| 446 | − v->f[ 9][2] = 1250.0f; //+250 | |
| 447 | − v->f[10][2] = 1000.0f; //+250 | |
| 448 | − v->f[11][2] = 750.0f; //+210 | |
| 449 | − v->f[12][2] = 540.0f; //+190 | |
| 450 | − v->f[13][2] = 350.0f; //+155 | |
| 451 | − v->f[14][2] = 195.0f; //+100 | |
| 452 | − v->f[15][2] = 95.0f; | |
| 453 | − } | |
| 454 | − | |
| 455 | − if(v->param[4]<0.05f) //freeze | |
| 456 | − { | |
| 457 | − for(i=0;i<v->nbnd;i++) v->f[i][12]=0.0f; | |
| 458 | − } | |
| 459 | − else | |
| 460 | − { | |
| 461 | − v->f[0][12] = (float)pow(10.0, -1.7 - 2.7f * v->param[4]); //envelope speed | |
| 462 | − | |
| 463 | − rr = 0.022f / (float)v->nbnd; //minimum proportional to frequency to stop distortion | |
| 464 | − for(i=1;i<v->nbnd;i++) | |
| 465 | − { | |
| 466 | − v->f[i][12] = (float)(0.025 - rr * (double)i); | |
| 467 | − if(v->f[0][12] < v->f[i][12]) v->f[i][12] = v->f[0][12]; | |
| 468 | − } | |
| 469 | − v->f[0][12] = 0.5f * v->f[0][12]; //only top band is at full rate | |
| 470 | − } | |
| 471 | − | |
| 472 | − rr = 1.0 - pow(10.0f, -1.0f - 1.2f * v->param[5]); | |
| 473 | − sh = (float)pow(2.0f, 3.0f * v->param[6] - 1.0f); //filter bank range shift | |
| 474 | − | |
| 475 | − for(i=1;i<v->nbnd;i++) | |
| 476 | − { | |
| 477 | − v->f[i][2] *= sh; | |
| 478 | − th = acos((2.0 * rr * cos(tpofs * v->f[i][2])) / (1.0 + rr * rr)); | |
| 479 | − v->f[i][0] = (float)(2.0 * rr * cos(th)); //a0 | |
| 480 | − v->f[i][1] = (float)(-rr * rr); //a1 | |
| 481 | − //was .98 | |
| 482 | − v->f[i][2] *= 0.96f; //shift 2nd stage slightly to stop high resonance peaks | |
| 483 | − th = acos((2.0 * rr * cos(tpofs * v->f[i][2])) / (1.0 + rr * rr)); | |
| 484 | − v->f[i][2] = (float)(2.0 * rr * cos(th)); | |
| 485 | − } | |
| 486 | −} | |
| 487 | − | |
| 488 | −float tVocoder_tick (tVocoder* const voc, float synth, float voice) | |
| 489 | −{ | |
| 490 | − _tVocoder* v = *voc; | |
| 491 | − | |
| 492 | − float a, b, o=0.0f, aa, bb, oo = v->kout, g = v->gain, ht = v->thru, hh = v->high, tmp; | |
| 493 | − uint32_t i, k = v->kval, nb = v->nbnd; | |
| 494 | − | |
| 495 | − a = voice; //speech | |
| 496 | − b = synth; //synth | |
| 497 | − | |
| 498 | − tmp = a - v->f[0][7]; //integrate modulator for HF band and filter bank pre-emphasis | |
| 499 | − v->f[0][7] = a; | |
| 500 | − a = tmp; | |
| 501 | − | |
| 502 | − if(tmp<0.0f) tmp = -tmp; | |
| 503 | − v->f[0][11] -= v->f[0][12] * (v->f[0][11] - tmp); //high band envelope | |
| 504 | − o = v->f[0][11] * (ht * a + hh * (b - v->f[0][3])); //high band + high thru | |
| 505 | − | |
| 506 | − v->f[0][3] = b; //integrate carrier for HF band | |
| 507 | − | |
| 508 | − if(++k & 0x1) //this block runs at half sample rate | |
| 509 | − { | |
| 510 | − oo = 0.0f; | |
| 511 | − aa = a + v->f[0][9] - v->f[0][8] - v->f[0][8]; //apply zeros here instead of in each reson | |
| 512 | − v->f[0][9] = v->f[0][8]; v->f[0][8] = a; | |
| 513 | − bb = b + v->f[0][5] - v->f[0][4] - v->f[0][4]; | |
| 514 | − v->f[0][5] = v->f[0][4]; v->f[0][4] = b; | |
| 515 | − | |
| 516 | − for(i=1; i<nb; i++) //filter bank: 4th-order band pass | |
| 517 | − { | |
| 518 | − tmp = v->f[i][0] * v->f[i][3] + v->f[i][1] * v->f[i][4] + bb; | |
| 519 | − v->f[i][4] = v->f[i][3]; | |
| 520 | − v->f[i][3] = tmp; | |
| 521 | − tmp += v->f[i][2] * v->f[i][5] + v->f[i][1] * v->f[i][6]; | |
| 522 | − v->f[i][6] = v->f[i][5]; | |
| 523 | − v->f[i][5] = tmp; | |
| 524 | − | |
| 525 | − tmp = v->f[i][0] * v->f[i][7] + v->f[i][1] * v->f[i][8] + aa; | |
| 526 | − v->f[i][8] = v->f[i][7]; | |
| 527 | − v->f[i][7] = tmp; | |
| 528 | − tmp += v->f[i][2] * v->f[i][9] + v->f[i][1] * v->f[i][10]; | |
| 529 | − v->f[i][10] = v->f[i][9]; | |
| 530 | − v->f[i][9] = tmp; | |
| 531 | − | |
| 532 | − if(tmp<0.0f) tmp = -tmp; | |
| 533 | − v->f[i][11] -= v->f[i][12] * (v->f[i][11] - tmp); | |
| 534 | − oo += v->f[i][5] * v->f[i][11]; | |
| 535 | − } | |
| 536 | − } | |
| 537 | − o += oo * g; //effect of interpolating back up to Fs would be minimal (aliasing >16kHz) | |
| 538 | − | |
| 539 | − v->kout = oo; | |
| 540 | − v->kval = k & 0x1; | |
| 541 | − if(fabs(v->f[0][11])<1.0e-10) v->f[0][11] = 0.0f; //catch HF envelope denormal | |
| 542 | − | |
| 543 | − for(i=1;i<nb;i++) | |
| 544 | − if(fabs(v->f[i][3])<1.0e-10 || fabs(v->f[i][7])<1.0e-10) | |
| 545 | − for(k=3; k<12; k++) v->f[i][k] = 0.0f; //catch reson & envelope denormals | |
| 546 | − | |
| 547 | − if(fabs(o)>10.0f) tVocoder_suspend(voc); //catch instability | |
| 548 | − | |
| 549 | − return o; | |
| 550 | − | |
| 551 | −} | |
| 552 | − | |
| 553 | −void tVocoder_suspend (tVocoder* const voc) | |
| 554 | −{ | |
| 555 | − _tVocoder* v = *voc; | |
| 556 | − | |
| 557 | − int32_t i, j; | |
| 558 | − | |
| 559 | − for(i=0; i<v->nbnd; i++) for(j=3; j<12; j++) v->f[i][j] = 0.0f; //zero band filters and envelopes | |
| 560 | − v->kout = 0.0f; | |
| 561 | − v->kval = 0; | |
| 562 | −} | |
| 563 | − | |
| 564 | − | |
| 565 | − | |
| 566 | −/// Glottal Pulse (Rosenberg model) | |
| 567 | − | |
| 568 | −void tRosenbergGlottalPulse_init (tRosenbergGlottalPulse* const gp) | |
| 569 | −{ | |
| 570 | − tRosenbergGlottalPulse_initToPool(gp, &leaf.mempool); | |
| 571 | −} | |
| 572 | −void tRosenbergGlottalPulse_free (tRosenbergGlottalPulse* const gp) | |
| 573 | −{ | |
| 574 | − tRosenbergGlottalPulse_freeFromPool(gp, &leaf.mempool); | |
| 575 | −} | |
| 576 | −void tRosenbergGlottalPulse_initToPool (tRosenbergGlottalPulse* const gp, tMempool* const mp) | |
| 577 | −{ | |
| 578 | − | |
| 579 | − _tMempool* m = *mp; | |
| 580 | − _tRosenbergGlottalPulse* g = *gp = (_tRosenbergGlottalPulse*) mpool_alloc(sizeof(_tRosenbergGlottalPulse), m); | |
| 581 | − | |
| 582 | − g->phase = 0.0f; | |
| 583 | − g->openLength = 0.0f; | |
| 584 | − g->pulseLength = 0.0f; | |
| 585 | − g->freq = 0.0f; | |
| 586 | − g->inc = 0.0f; | |
| 587 | − | |
| 588 | − | |
| 589 | −} | |
| 590 | −void tRosenbergGlottalPulse_freeFromPool (tRosenbergGlottalPulse* const gp, tMempool* const mp) | |
| 591 | −{ | |
| 592 | − _tMempool* m = *mp; | |
| 593 | − _tRosenbergGlottalPulse* g = *gp; | |
| 594 | − mpool_free((char*)g, m); | |
| 595 | −} | |
| 596 | − | |
| 597 | −float tRosenbergGlottalPulse_tick (tRosenbergGlottalPulse* const gp) | |
| 598 | −{ | |
| 599 | − _tRosenbergGlottalPulse* g = *gp; | |
| 600 | − | |
| 601 | − float output = 0.0f; | |
| 602 | − | |
| 603 | − // Phasor increment | |
| 604 | − g->phase += g->inc; | |
| 605 | − while (g->phase >= 1.0f) g->phase -= 1.0f; | |
| 606 | − while (g->phase < 0.0f) g->phase += 1.0f; | |
| 607 | − | |
| 608 | − if (g->phase < g->openLength) | |
| 609 | − { | |
| 610 | − output = 0.5f*(1.0f-cosf(PI * g->phase)); | |
| 611 | − } | |
| 612 | − | |
| 613 | − else if (g->phase < g->pulseLength) | |
| 614 | − { | |
| 615 | − output = cosf(HALF_PI * (g->phase-g->openLength)/(g->pulseLength-g->openLength)); | |
| 616 | − } | |
| 617 | − | |
| 618 | − else | |
| 619 | − { | |
| 620 | − output = 0.0f; | |
| 621 | − } | |
| 622 | − return output; | |
| 623 | −} | |
| 624 | − | |
| 625 | −void tRosenbergGlottalPulse_setFreq (tRosenbergGlottalPulse* const gp, float freq) | |
| 626 | −{ | |
| 627 | − _tRosenbergGlottalPulse* g = *gp; | |
| 628 | − g->freq = freq; | |
| 629 | − g->inc = freq * leaf.invSampleRate; | |
| 630 | −} | |
| 631 | − | |
| 632 | −void tRosenbergGlottalPulse_setOpenLength (tRosenbergGlottalPulse* const gp, float openLength) | |
| 633 | −{ | |
| 634 | − _tRosenbergGlottalPulse* g = *gp; | |
| 635 | − g->openLength = openLength; | |
| 636 | −} | |
| 637 | − | |
| 638 | −void tRosenbergGlottalPulse_setPulseLength (tRosenbergGlottalPulse* const gp, float pulseLength) | |
| 639 | −{ | |
| 640 | − _tRosenbergGlottalPulse* g = *gp; | |
| 641 | − g->pulseLength = pulseLength; | |
| 642 | −} | |
| 643 | − | |
| 644 | − | |
| 645 | − | |
| 646 | − | |
| 647 | −//============================================================================================================ | |
| 648 | −// SOLAD | |
| 649 | −//============================================================================================================ | |
| 650 | −/******************************************************************************/ | |
| 651 | −/***************** static function declarations *******************************/ | |
| 652 | −/******************************************************************************/ | |
| 653 | − | |
| 654 | −static void solad_init(_tSOLAD *w); | |
| 655 | −static inline float read_sample(_tSOLAD *w, float floatindex); | |
| 656 | −static void pitchdown(_tSOLAD *w, float *out); | |
| 657 | −static void pitchup(_tSOLAD *w, float *out); | |
| 658 | − | |
| 659 | −/******************************************************************************/ | |
| 660 | −/***************** public access functions ************************************/ | |
| 661 | −/******************************************************************************/ | |
| 662 | − | |
| 663 | −// init | |
| 664 | −void tSOLAD_init(tSOLAD* const wp) | |
| 665 | −{ | |
| 666 | − _tSOLAD* w = *wp = (_tSOLAD*) leaf_calloc(sizeof(_tSOLAD)); | |
| 667 | − | |
| 668 | − w->pitchfactor = 1.; | |
| 669 | − w->delaybuf = (float*) leaf_calloc(sizeof(float) * (LOOPSIZE+16)); | |
| 670 | − | |
| 671 | − solad_init(w); | |
| 672 | −} | |
| 673 | − | |
| 674 | −void tSOLAD_free(tSOLAD* const wp) | |
| 675 | −{ | |
| 676 | − _tSOLAD* w = *wp; | |
| 677 | − | |
| 678 | − leaf_free((char*)w->delaybuf); | |
| 679 | − leaf_free((char*)w); | |
| 680 | −} | |
| 681 | − | |
| 682 | −void tSOLAD_initToPool (tSOLAD* const wp, tMempool* const mp) | |
| 683 | −{ | |
| 684 | − _tMempool* m = *mp; | |
| 685 | − | |
| 686 | − _tSOLAD* w = *wp = (_tSOLAD*) mpool_calloc(sizeof(_tSOLAD), m); | |
| 687 | − | |
| 688 | − w->pitchfactor = 1.; | |
| 689 | − w->delaybuf = (float*) mpool_calloc(sizeof(float) * (LOOPSIZE+16), m); | |
| 690 | − | |
| 691 | − solad_init(w); | |
| 692 | −} | |
| 693 | − | |
| 694 | −void tSOLAD_freeFromPool (tSOLAD* const wp, tMempool* const mp) | |
| 695 | −{ | |
| 696 | − _tMempool* m = *mp; | |
| 697 | − _tSOLAD* w = *wp; | |
| 698 | − | |
| 699 | − mpool_free((char*)w->delaybuf, m); | |
| 700 | − mpool_free((char*)w, m); | |
| 701 | −} | |
| 702 | − | |
| 703 | −// send one block of input samples, receive one block of output samples | |
| 704 | −void tSOLAD_ioSamples(tSOLAD* const wp, float* in, float* out, int blocksize) | |
| 705 | −{ | |
| 706 | − _tSOLAD* w = *wp; | |
| 707 | − | |
| 708 | − int i = w->timeindex; | |
| 709 | − int n = w->blocksize = blocksize; | |
| 710 | − | |
| 711 | − if(!i) w->delaybuf[LOOPSIZE] = in[0]; // copy one sample for interpolation | |
| 712 | − while(n--) w->delaybuf[i++] = *in++; // copy one input block to delay buffer | |
| 713 | − | |
| 714 | − if(w->pitchfactor > 1) pitchup(w, out); | |
| 715 | − else pitchdown(w, out); | |
| 716 | − | |
| 717 | − w->timeindex += blocksize; | |
| 718 | − w->timeindex &= LOOPMASK; | |
| 719 | −} | |
| 720 | − | |
| 721 | −// set periodicity analysis data | |
| 722 | −void tSOLAD_setPeriod(tSOLAD* const wp, float period) | |
| 723 | −{ | |
| 724 | − _tSOLAD* w = *wp; | |
| 725 | − | |
| 726 | − if(period > MAXPERIOD) period = MAXPERIOD; | |
| 727 | − if(period > MINPERIOD) w->period = period; // ignore period when too small | |
| 728 | −} | |
| 729 | − | |
| 730 | −// set pitch factor between 0.25 and 4 | |
| 731 | −void tSOLAD_setPitchFactor(tSOLAD* const wp, float pitchfactor) | |
| 732 | −{ | |
| 733 | − _tSOLAD* w = *wp; | |
| 734 | − | |
| 735 | − if (pitchfactor <= 0.0f) return; | |
| 736 | − w->pitchfactor = pitchfactor; | |
| 737 | −} | |
| 738 | − | |
| 739 | −// force readpointer lag | |
| 740 | −void tSOLAD_setReadLag(tSOLAD* const wp, float readlag) | |
| 741 | −{ | |
| 742 | − _tSOLAD* w = *wp; | |
| 743 | − | |
| 744 | − if(readlag < 0) readlag = 0; | |
| 745 | − if(readlag < w->readlag) // do not jump backward, only forward | |
| 746 | − { | |
| 747 | − w->jump = w->readlag - readlag; | |
| 748 | − w->readlag = readlag; | |
| 749 | − w->xfadelength = readlag; | |
| 750 | − w->xfadevalue = 1; | |
| 751 | − } | |
| 752 | −} | |
| 753 | − | |
| 754 | −// reset state variables | |
| 755 | −void tSOLAD_resetState(tSOLAD* const wp) | |
| 756 | −{ | |
| 757 | − _tSOLAD* w = *wp; | |
| 758 | − | |
| 759 | − int n = LOOPSIZE + 1; | |
| 760 | − float *buf = w->delaybuf; | |
| 761 | − | |
| 762 | − while(n--) *buf++ = 0; | |
| 763 | − solad_init(w); | |
| 764 | −} | |
| 765 | − | |
| 766 | −/******************************************************************************/ | |
| 767 | −/******************** private procedures **************************************/ | |
| 768 | −/******************************************************************************/ | |
| 769 | − | |
| 770 | −/* | |
| 771 | − Function pitchdown() is called to read samples from the delay buffer when pitch | |
| 772 | − factor is between 0.25 and 1. The read pointer lags behind because of the slowed | |
| 773 | − down speed, and it must jump forward towards the write pointer soon as there is | |
| 774 | − sufficient space to jump. That is, if there is at least one period of the input | |
| 775 | − signal between read pointer and write pointer. When short periods follow up on | |
| 776 | − long periods, the read pointer may have space to jump over more than one period | |
| 777 | − lenghts. Jump length must be [periodlength ^ 2] in any case. | |
| 778 | − | |
| 779 | − A linear crossfade function joins the jump-from point with the jump-to point. | |
| 780 | − The crossfade must be completed before another read pointer jump is allowed. | |
| 781 | − Length of the crossfade function is stored as a number of samples in terms of | |
| 782 | − the input sample rate. This length is dynamically translated | |
| 783 | − to a crossfade length expressed in output reading rate, according to pitch | |
| 784 | − factor which can change before the crossfade is completed. Crossfade length does | |
| 785 | − not cover an invariable length in periods for all pitch transposition factors. | |
| 786 | − For pitch factors from 0.5 till 1, crossfade length is stretched in the | |
| 787 | − output just as much as the signal itself, as crossfade speed is set to equal | |
| 788 | − pitch factor. For pitch factors below 0.5, the read pointer wants to jump | |
| 789 | − forward before one period is read, therefore the crossfade length as expressed | |
| 790 | − in output periods must be shorter. Crossfade speed is set to [1 - pitchfactor] | |
| 791 | − for those cases. Pitch factor 0.5 is the natural switch point between crossfade | |
| 792 | − speeds [pitchfactor] and [1 - pitchfactor] because 0.5 == 1 - 0.5. The crossfade | |
| 793 | − speed modification for pitch factors below 0.5 also means that much of the | |
| 794 | − original signal content will be skipped. | |
| 795 | − */ | |
| 796 | − | |
| 797 | − | |
| 798 | −static void pitchdown(_tSOLAD* const w, float *out) | |
| 799 | −{ | |
| 800 | − int n = w->blocksize; | |
| 801 | − float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values! | |
| 802 | − float pitchfactor = w->pitchfactor; | |
| 803 | − float period = w->period; | |
| 804 | − float readlag = w->readlag; | |
| 805 | − float readlagstep = 1 - pitchfactor; | |
| 806 | − float jump = w->jump; | |
| 807 | − float xfadevalue = w->xfadevalue; | |
| 808 | − float xfadelength = w->xfadelength; | |
| 809 | − float xfadespeed, xfadestep, readindex, outputsample; | |
| 810 | − | |
| 811 | − if(pitchfactor > 0.5) xfadespeed = pitchfactor; | |
| 812 | − else xfadespeed = 1 - pitchfactor; | |
| 813 | − xfadestep = xfadespeed / xfadelength; | |
| 814 | − | |
| 815 | − while(n--) | |
| 816 | − { | |
| 817 | − if(readlag > period) // check if read pointer may jump forward... | |
| 818 | − { | |
| 819 | − if(xfadevalue <= 0) // ...but do not interrupt crossfade | |
| 820 | − { | |
| 821 | − jump = period; // jump forward | |
| 822 | − while((jump * 2) < readlag) jump *= 2; // use available space | |
| 823 | − readlag -= jump; // reduce read pointer lag | |
| 824 | − xfadevalue = 1; // start crossfade | |
| 825 | − xfadelength = period - 1; | |
| 826 | − xfadestep = xfadespeed / xfadelength; | |
| 827 | − } | |
| 828 | − } | |
| 829 | − | |
| 830 | − readindex = refindex - readlag; | |
| 831 | − outputsample = read_sample(w, readindex); | |
| 832 | − | |
| 833 | − if(xfadevalue > 0) | |
| 834 | − { | |
| 835 | − outputsample *= (1 - xfadevalue); // fadein | |
| 836 | − outputsample += read_sample(w, readindex - jump) * xfadevalue; // fadeout | |
| 837 | − xfadevalue -= xfadestep; | |
| 838 | − } | |
| 839 | − | |
| 840 | − *out++ = outputsample; | |
| 841 | − refindex += 1; | |
| 842 | − readlag += readlagstep; | |
| 843 | − } | |
| 844 | − | |
| 845 | − w->jump = jump; // state variables | |
| 846 | − w->readlag = readlag; | |
| 847 | − w->xfadevalue = xfadevalue; | |
| 848 | − w->xfadelength = xfadelength; | |
| 849 | −} | |
| 850 | − | |
| 851 | − | |
| 852 | −/* | |
| 853 | − Function pitchup() for pitch factors above 1 is more complicated than | |
| 854 | − pitchdown(). The read pointer increments faster than the write pointer and a | |
| 855 | − backward jump must happen in time, reckoning with the crossfade region. The read | |
| 856 | − pointer backward jump length is always one period. In order to minimize the area | |
| 857 | − of signal duplicates, crossfade length is aimed at [period / pitchfactor]. | |
| 858 | − This leads to a crossfade speed of [pitchfactor * pitchfactor]. | |
| 859 | − | |
| 860 | − Some samples for the fade out (but not all of them) must already be in the | |
| 861 | − buffer, otherwise we will run out of input samples before the crossfade is | |
| 862 | − completed. The ratio of past samples and future samples for a crossfade of any | |
| 863 | − length is as follows: | |
| 864 | − | |
| 865 | − past samples: xfadelength * (1 - 1 / pitchfactor) | |
| 866 | − future samples: xfadelength * (1 / pitchfactor) | |
| 867 | − | |
| 868 | − For example in the case of pitch factor 1.5 this would be: | |
| 869 | − | |
| 870 | − past samples: xfadelength * (1 - 1 / 1.5) = xfadelength * 1 / 3 | |
| 871 | − future samples: xfadelength * (1 / 1.5) = xfadelength * 2 / 3 | |
| 872 | − | |
| 873 | − In the case of pitch factor 4 this would be: | |
| 874 | − | |
| 875 | − past samples: xfadelength * (1 - 1 / 4) = xfadelength * 3 / 4 | |
| 876 | − future samples: xfadelength * (1 / 4) = xfadelength * 1 / 4 | |
| 877 | − | |
| 878 | − The read pointer lag must therefore preserve a minimum dependent on pitch | |
| 879 | − factor. The minimum is called 'limit' here: | |
| 880 | − | |
| 881 | − limit = period * (pitchfactor - 1) / pitchfactor * pitchfactor | |
| 882 | − | |
| 883 | − Components of this expression are combined to reuse them in operations, while | |
| 884 | − (pitchfactor - 1) is changed to (pitchfactor - 0.99) to avoid numerical | |
| 885 | − resolution issues for pitch factors slightly above 1: | |
| 886 | − | |
| 887 | − xfadespeed = pitchfactor * pitchfactor | |
| 888 | − limitfactor = (pitchfactor - 0.99) / xfadespeed | |
| 889 | − limit = period * limitfactor | |
| 890 | − | |
| 891 | − When read lag is smaller than this limit, the read pointer must preferably | |
| 892 | − jump backward, unless a previous crossfade is not yet completed. Crossfades must | |
| 893 | − preferably be completed, unless the read pointer lag becomes smaller than zero. | |
| 894 | − With fluctuating period lengths and pitch factors, the readpointer lag limit may | |
| 895 | − change from one input block to the next in such a way that the actual lag is | |
| 896 | − suddenly much smaller than the limit, and the intended crossfade length can not | |
| 897 | − be applied. Therefore the crossfade length is simply calculated from the | |
| 898 | − available amount of samples for all cases, like so: | |
| 899 | − | |
| 900 | − xfadelength = readlag / limitfactor | |
| 901 | − | |
| 902 | − For most occurrences, this will amount to a crossfade length reduced to | |
| 903 | − [period / pitchfactor] in the output for pitch factors above 1, while in some | |
| 904 | − cases it will be considerably shorter. Fortunately, an incidental aberration of | |
| 905 | − the intended crossfade length hardly ever creates an audible artifact. The | |
| 906 | − reason to specify preferred crossfade length according to pitch factor is to | |
| 907 | − minimize the impression of echoes without sacrificing too much of the signal | |
| 908 | − content. The readpointer jump length remains one period in any case. | |
| 909 | − | |
| 910 | − Sometimes, the input signal periodicity may decrease substantially between one | |
| 911 | − signal block and the next. In such cases it may be possible for the read pointer | |
| 912 | − to jump forward and reduce latency. For every signal block, a check on this | |
| 913 | − possibility is done. A previous crossfade must be completed before a forward | |
| 914 | − jump is allowed. | |
| 915 | − */ | |
| 916 | −static void pitchup(_tSOLAD* const w, float *out) | |
| 917 | −{ | |
| 918 | − int n = w->blocksize; | |
| 919 | − float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values | |
| 920 | − float pitchfactor = w->pitchfactor; | |
| 921 | − float period = w->period; | |
| 922 | − float readlag = w->readlag; | |
| 923 | − float jump = w->jump; | |
| 924 | − float xfadevalue = w->xfadevalue; | |
| 925 | − float xfadelength = w->xfadelength; | |
| 926 | − | |
| 927 | − float readlagstep = pitchfactor - 1; | |
| 928 | − float xfadespeed = pitchfactor * pitchfactor; | |
| 929 | − float xfadestep = xfadespeed / xfadelength; | |
| 930 | − float limitfactor = (pitchfactor - (float)0.99) / xfadespeed; | |
| 931 | − float limit = period * limitfactor; | |
| 932 | − float readindex, outputsample; | |
| 933 | − | |
| 934 | − if((readlag > (period + 2 * limit)) & (xfadevalue < 0)) | |
| 935 | − { | |
| 936 | − jump = period; // jump forward | |
| 937 | − while((jump * 2) < (readlag - 2 * limit)) jump *= 2; // use available space | |
| 938 | − readlag -= jump; // reduce read pointer lag | |
| 939 | − xfadevalue = 1; // start crossfade | |
| 940 | − xfadelength = period - 1; | |
| 941 | − xfadestep = xfadespeed / xfadelength; | |
| 942 | − } | |
| 943 | − | |
| 944 | − while(n--) | |
| 945 | − { | |
| 946 | − if(readlag < limit) // check if read pointer should jump backward... | |
| 947 | − { | |
| 948 | − if((xfadevalue < 0) | (readlag < 0)) // ...but try not to interrupt crossfade | |
| 949 | − { | |
| 950 | − xfadelength = readlag / limitfactor; | |
| 951 | − if(xfadelength < 1) xfadelength = 1; | |
| 952 | − xfadestep = xfadespeed / xfadelength; | |
| 953 | − | |
| 954 | − jump = -period; // jump backward | |
| 955 | − readlag += period; // increase read pointer lag | |
| 956 | − xfadevalue = 1; // start crossfade | |
| 957 | − } | |
| 958 | − } | |
| 959 | − | |
| 960 | − readindex = refindex - readlag; | |
| 961 | − outputsample = read_sample(w, readindex); | |
| 962 | − | |
| 963 | − if(xfadevalue > 0) | |
| 964 | − { | |
| 965 | − outputsample *= (1 - xfadevalue); | |
| 966 | − outputsample += read_sample(w, readindex - jump) * xfadevalue; | |
| 967 | − xfadevalue -= xfadestep; | |
| 968 | − } | |
| 969 | − | |
| 970 | − *out++ = outputsample; | |
| 971 | − refindex += 1; | |
| 972 | − readlag -= readlagstep; | |
| 973 | − } | |
| 974 | − | |
| 975 | − w->readlag = readlag; // state variables | |
| 976 | − w->jump = jump; | |
| 977 | − w->xfadelength = xfadelength; | |
| 978 | − w->xfadevalue = xfadevalue; | |
| 979 | −} | |
| 980 | − | |
| 981 | −// read one sample from delay buffer, with linear interpolation | |
| 982 | −static inline float read_sample(_tSOLAD* const w, float floatindex) | |
| 983 | −{ | |
| 984 | − int index = (int)floatindex; | |
| 985 | − float fraction = floatindex - (float)index; | |
| 986 | − float *buf = w->delaybuf; | |
| 987 | − index &= LOOPMASK; | |
| 988 | − | |
| 989 | − return (buf[index] + (fraction * (buf[index+1] - buf[index]))); | |
| 990 | −} | |
| 991 | − | |
| 992 | −static void solad_init(_tSOLAD* const w) | |
| 993 | −{ | |
| 994 | − w->timeindex = 0; | |
| 995 | − w->xfadevalue = -1; | |
| 996 | − w->period = INITPERIOD; | |
| 997 | − w->readlag = INITPERIOD; | |
| 998 | − w->blocksize = INITPERIOD; | |
| 999 | −} | |
| 1000 | − | |
| 1001 | −//============================================================================================================ | |
| 1002 | −// PITCHSHIFT | |
| 1003 | −//============================================================================================================ | |
| 1004 | − | |
| 1005 | −static int pitchshift_attackdetect(_tPitchShift* ps) | |
| 1006 | −{ | |
| 1007 | − float envout; | |
| 1008 | − | |
| 1009 | − _tPeriodDetection* p = *ps->p; | |
| 1010 | − | |
| 1011 | − envout = tEnvPD_tick(&p->env); | |
| 1012 | − | |
| 1013 | − if (envout >= 1.0f) | |
| 1014 | − { | |
| 1015 | − p->lastmax = p->max; | |
| 1016 | − if (envout > p->max) | |
| 1017 | − { | |
| 1018 | − p->max = envout; | |
| 1019 | − } | |
| 1020 | − else | |
| 1021 | − { | |
| 1022 | − p->deltamax = envout - p->max; | |
| 1023 | − p->max = p->max * ps->radius; | |
| 1024 | − } | |
| 1025 | − p->deltamax = p->max - p->lastmax; | |
| 1026 | − } | |
| 1027 | − | |
| 1028 | − p->fba = p->fba ? (p->fba - 1) : 0; | |
| 1029 | − | |
| 1030 | − return (p->fba == 0 && (p->max > 60 && p->deltamax > 6)) ? 1 : 0; | |
| 1031 | −} | |
| 1032 | − | |
| 1033 | −void tPitchShift_init (tPitchShift* const psr, tPeriodDetection* pd, float* out, int bufSize) | |
| 1034 | −{ | |
| 1035 | − _tPitchShift* ps = *psr = (_tPitchShift*) leaf_calloc(sizeof(_tPitchShift)); | |
| 1036 | − _tPeriodDetection* p = *pd; | |
| 1037 | − | |
| 1038 | − ps->p = pd; | |
| 1039 | − | |
| 1040 | − ps->outBuffer = out; | |
| 1041 | − ps->bufSize = bufSize; | |
| 1042 | − ps->frameSize = p->frameSize; | |
| 1043 | − ps->framesPerBuffer = ps->bufSize / ps->frameSize; | |
| 1044 | − ps->curBlock = 1; | |
| 1045 | − ps->lastBlock = 0; | |
| 1046 | − ps->index = 0; | |
| 1047 | − ps->pitchFactor = 1.0f; | |
| 1048 | − | |
| 1049 | − tSOLAD_init(&ps->sola); | |
| 1050 | − | |
| 1051 | − tHighpass_init(&ps->hp, HPFREQ); | |
| 1052 | − | |
| 1053 | − tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO); | |
| 1054 | −} | |
| 1055 | − | |
| 1056 | −void tPitchShift_free(tPitchShift* const psr) | |
| 1057 | −{ | |
| 1058 | − _tPitchShift* ps = *psr; | |
| 1059 | − | |
| 1060 | − tSOLAD_free(&ps->sola); | |
| 1061 | − tHighpass_free(&ps->hp); | |
| 1062 | − leaf_free((char*)ps); | |
| 1063 | −} | |
| 1064 | − | |
| 1065 | −void tPitchShift_initToPool (tPitchShift* const psr, tPeriodDetection* const pd, float* out, int bufSize, tMempool* const mp) | |
| 1066 | −{ | |
| 1067 | − _tMempool* m = *mp; | |
| 1068 | − | |
| 1069 | − _tPitchShift* ps = *psr = (_tPitchShift*) mpool_calloc(sizeof(_tPitchShift), m); | |
| 1070 | − | |
| 1071 | − _tPeriodDetection* p = *pd; | |
| 1072 | − | |
| 1073 | − ps->p = pd; | |
| 1074 | − | |
| 1075 | − ps->outBuffer = out; | |
| 1076 | − ps->bufSize = bufSize; | |
| 1077 | − ps->frameSize = p->frameSize; | |
| 1078 | − ps->framesPerBuffer = ps->bufSize / ps->frameSize; | |
| 1079 | − ps->curBlock = 1; | |
| 1080 | − ps->lastBlock = 0; | |
| 1081 | − ps->index = 0; | |
| 1082 | − ps->pitchFactor = 1.0f; | |
| 1083 | − | |
| 1084 | − tSOLAD_initToPool(&ps->sola, mp); | |
| 1085 | − | |
| 1086 | − tHighpass_initToPool(&ps->hp, HPFREQ, mp); | |
| 1087 | − | |
| 1088 | − tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO); | |
| 1089 | −} | |
| 1090 | − | |
| 1091 | −void tPitchShift_freeFromPool (tPitchShift* const psr, tMempool* const mp) | |
| 1092 | −{ | |
| 1093 | − _tMempool* m = *mp; | |
| 1094 | − _tPitchShift* ps = *psr; | |
| 1095 | − | |
| 1096 | − tSOLAD_freeFromPool(&ps->sola, mp); | |
| 1097 | − tHighpass_freeFromPool(&ps->hp, mp); | |
| 1098 | − mpool_free((char*)ps, m); | |
| 1099 | −} | |
| 1100 | − | |
| 1101 | −void tPitchShift_setPitchFactor(tPitchShift* psr, float pf) | |
| 1102 | −{ | |
| 1103 | − _tPitchShift* ps = *psr; | |
| 1104 | − | |
| 1105 | − ps->pitchFactor = pf; | |
| 1106 | −} | |
| 1107 | − | |
| 1108 | −float tPitchShift_shift (tPitchShift* psr) | |
| 1109 | −{ | |
| 1110 | − _tPitchShift* ps = *psr; | |
| 1111 | − _tPeriodDetection* p = *ps->p; | |
| 1112 | − | |
| 1113 | − float period, out; | |
| 1114 | − int i, iLast; | |
| 1115 | − | |
| 1116 | − i = p->i; | |
| 1117 | − iLast = p->iLast; | |
| 1118 | − | |
| 1119 | − out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]); | |
| 1120 | − | |
| 1121 | − if (p->indexstore >= ps->frameSize) | |
| 1122 | − { | |
| 1123 | − period = tPeriodDetection_getPeriod(&p); | |
| 1124 | − | |
| 1125 | − if(pitchshift_attackdetect(ps) == 1) | |
| 1126 | − { | |
| 1127 | − p->fba = 5; | |
| 1128 | − tSOLAD_setReadLag(&ps->sola, p->windowSize); | |
| 1129 | − } | |
| 1130 | − | |
| 1131 | − tSOLAD_setPeriod(&ps->sola, period); | |
| 1132 | − tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor); | |
| 1133 | − | |
| 1134 | − tSOLAD_ioSamples(&ps->sola, &(p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize); | |
| 1135 | − } | |
| 1136 | − | |
| 1137 | − return out; | |
| 1138 | −} | |
| 1139 | − | |
| 1140 | −float tPitchShift_shiftToFreq (tPitchShift* psr, float freq) | |
| 1141 | −{ | |
| 1142 | − _tPitchShift* ps = *psr; | |
| 1143 | − _tPeriodDetection* p = *ps->p; | |
| 1144 | − | |
| 1145 | − float period, out; | |
| 1146 | − int i, iLast; | |
| 1147 | − | |
| 1148 | − i = p->i; | |
| 1149 | − iLast = p->iLast; | |
| 1150 | − | |
| 1151 | − out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]); | |
| 1152 | − | |
| 1153 | − if (p->indexstore >= ps->frameSize) | |
| 1154 | − { | |
| 1155 | − period = tPeriodDetection_getPeriod(&p); | |
| 1156 | − | |
| 1157 | − if(pitchshift_attackdetect(ps) == 1) | |
| 1158 | − { | |
| 1159 | − p->fba = 5; | |
| 1160 | − tSOLAD_setReadLag(&ps->sola, p->windowSize); | |
| 1161 | − } | |
| 1162 | − | |
| 1163 | − tSOLAD_setPeriod(&ps->sola, period); | |
| 1164 | − | |
| 1165 | − if (period != 0) ps->pitchFactor = period*freq*leaf.invSampleRate; | |
| 1166 | − else ps->pitchFactor = 1.0f; | |
| 1167 | − | |
| 1168 | − tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor); | |
| 1169 | − | |
| 1170 | − tSOLAD_ioSamples(&ps->sola, &(p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize); | |
| 1171 | − } | |
| 1172 | − return out; | |
| 1173 | −} | |
| 1174 | − | |
| 1175 | −float tPitchShift_shiftToFunc (tPitchShift* psr, float (*fun)(float)) | |
| 1176 | −{ | |
| 1177 | − _tPitchShift* ps = *psr; | |
| 1178 | − _tPeriodDetection* p = *ps->p; | |
| 1179 | − | |
| 1180 | − float period, out; | |
| 1181 | − int i, iLast; | |
| 1182 | − | |
| 1183 | − i = p->i; | |
| 1184 | − iLast = p->iLast; | |
| 1185 | − | |
| 1186 | − out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]); | |
| 1187 | − | |
| 1188 | − if (p->indexstore >= ps->frameSize) | |
| 1189 | − { | |
| 1190 | − period = tPeriodDetection_getPeriod(&p); | |
| 1191 | − | |
| 1192 | − if(pitchshift_attackdetect(ps) == 1) | |
| 1193 | − { | |
| 1194 | − p->fba = 5; | |
| 1195 | − tSOLAD_setReadLag(&ps->sola, p->windowSize); | |
| 1196 | − } | |
| 1197 | − | |
| 1198 | − tSOLAD_setPeriod(&ps->sola, period); | |
| 1199 | − | |
| 1200 | − ps->pitchFactor = period/fun(period); | |
| 1201 | − tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor); | |
| 1202 | − | |
| 1203 | − tSOLAD_ioSamples(&ps->sola, &(p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize); | |
| 1204 | − | |
| 1205 | − ps->curBlock++; | |
| 1206 | − if (ps->curBlock >= p->framesPerBuffer) ps->curBlock = 0; | |
| 1207 | − ps->lastBlock++; | |
| 1208 | − if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0; | |
| 1209 | − } | |
| 1210 | − | |
| 1211 | − return out; | |
| 1212 | −} | |
| 1213 | − | |
| 1214 | −//============================================================================================================ | |
| 1215 | −// RETUNE | |
| 1216 | −//============================================================================================================ | |
| 1217 | − | |
| 1218 | −void tRetune_init(tRetune* const rt, int numVoices, int bufSize, int frameSize) | |
| 1219 | −{ | |
| 1220 | − tRetune_initToPool(rt, numVoices, bufSize, frameSize, &leaf.mempool); | |
| 1221 | −} | |
| 1222 | − | |
| 1223 | −void tRetune_free(tRetune* const rt) | |
| 1224 | −{ | |
| 1225 | − tRetune_freeFromPool(rt, &leaf.mempool); | |
| 1226 | −} | |
| 1227 | − | |
| 1228 | −void tRetune_initToPool (tRetune* const rt, int numVoices, int bufSize, int frameSize, tMempool* const mp) | |
| 1229 | −{ | |
| 1230 | − _tMempool* m = *mp; | |
| 1231 | − _tRetune* r = *rt = (_tRetune*) mpool_alloc(sizeof(_tRetune), m); | |
| 1232 | − | |
| 1233 | − r->bufSize = bufSize; | |
| 1234 | − r->frameSize = frameSize; | |
| 1235 | − r->numVoices = numVoices; | |
| 1236 | − | |
| 1237 | − r->inBuffer = (float*) mpool_calloc(sizeof(float) * r->bufSize, m); | |
| 1238 | − r->outBuffers = (float**) mpool_calloc(sizeof(float*) * r->numVoices, m); | |
| 1239 | − | |
| 1240 | − r->hopSize = DEFHOPSIZE; | |
| 1241 | − r->windowSize = DEFWINDOWSIZE; | |
| 1242 | − r->fba = FBA; | |
| 1243 | − tRetune_setTimeConstant(rt, DEFTIMECONSTANT); | |
| 1244 | − | |
| 1245 | − r->inputPeriod = 0.0f; | |
| 1246 | − | |
| 1247 | − r->ps = (tPitchShift*) mpool_calloc(sizeof(tPitchShift) * r->numVoices, m); | |
| 1248 | − r->pitchFactor = (float*) mpool_calloc(sizeof(float) * r->numVoices, m); | |
| 1249 | − r->tickOutput = (float*) mpool_calloc(sizeof(float) * r->numVoices, m); | |
| 1250 | − for (int i = 0; i < r->numVoices; ++i) | |
| 1251 | − { | |
| 1252 | − r->outBuffers[i] = (float*) mpool_calloc(sizeof(float) * r->bufSize, m); | |
| 1253 | − } | |
| 1254 | − | |
| 1255 | − tPeriodDetection_initToPool(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize, mp); | |
| 1256 | − | |
| 1257 | − for (int i = 0; i < r->numVoices; ++i) | |
| 1258 | − { | |
| 1259 | − tPitchShift_initToPool(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize, mp); | |
| 1260 | − } | |
| 1261 | −} | |
| 1262 | − | |
| 1263 | −void tRetune_freeFromPool (tRetune* const rt, tMempool* const mp) | |
| 1264 | −{ | |
| 1265 | − _tMempool* m = *mp; | |
| 1266 | − _tRetune* r = *rt; | |
| 1267 | − | |
| 1268 | − tPeriodDetection_freeFromPool(&r->pd, mp); | |
| 1269 | − for (int i = 0; i < r->numVoices; ++i) | |
| 1270 | − { | |
| 1271 | − tPitchShift_freeFromPool(&r->ps[i], mp); | |
| 1272 | − mpool_free((char*)r->outBuffers[i], m); | |
| 1273 | − } | |
| 1274 | − mpool_free((char*)r->tickOutput, m); | |
| 1275 | − mpool_free((char*)r->pitchFactor, m); | |
| 1276 | − mpool_free((char*)r->ps, m); | |
| 1277 | − mpool_free((char*)r->inBuffer, m); | |
| 1278 | − mpool_free((char*)r->outBuffers, m); | |
| 1279 | − mpool_free((char*)r, m); | |
| 1280 | −} | |
| 1281 | − | |
| 1282 | −float* tRetune_tick(tRetune* const rt, float sample) | |
| 1283 | −{ | |
| 1284 | − _tRetune* r = *rt; | |
| 1285 | − | |
| 1286 | − r->inputPeriod = tPeriodDetection_tick(&r->pd, sample); | |
| 1287 | − | |
| 1288 | − for (int v = 0; v < r->numVoices; ++v) | |
| 1289 | − { | |
| 1290 | − r->tickOutput[v] = tPitchShift_shift(&r->ps[v]); | |
| 1291 | − } | |
| 1292 | − | |
| 1293 | − return r->tickOutput; | |
| 1294 | −} | |
| 1295 | − | |
| 1296 | −void tRetune_setNumVoices(tRetune* const rt, int numVoices) | |
| 1297 | −{ | |
| 1298 | − _tRetune* r = *rt; | |
| 1299 | − | |
| 1300 | − for (int i = 0; i < r->numVoices; ++i) | |
| 1301 | − { | |
| 1302 | − tPitchShift_free(&r->ps[i]); | |
| 1303 | − leaf_free((char*)r->outBuffers[i]); | |
| 1304 | − } | |
| 1305 | − leaf_free((char*)r->tickOutput); | |
| 1306 | − leaf_free((char*)r->pitchFactor); | |
| 1307 | − leaf_free((char*)r->ps); | |
| 1308 | − leaf_free((char*)r->outBuffers); | |
| 1309 | − | |
| 1310 | − r->numVoices = numVoices; | |
| 1311 | − | |
| 1312 | − r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices); | |
| 1313 | − r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices); | |
| 1314 | − r->pitchFactor = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 1315 | − r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 1316 | − for (int i = 0; i < r->numVoices; ++i) | |
| 1317 | − { | |
| 1318 | − r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 1319 | − tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize); | |
| 1320 | − } | |
| 1321 | −} | |
| 1322 | − | |
| 1323 | −void tRetune_setPitchFactors(tRetune* const rt, float pf) | |
| 1324 | −{ | |
| 1325 | − _tRetune* r = *rt; | |
| 1326 | − | |
| 1327 | − for (int i = 0; i < r->numVoices; ++i) | |
| 1328 | − { | |
| 1329 | − r->pitchFactor[i] = pf; | |
| 1330 | − tPitchShift_setPitchFactor(&r->ps[i], r->pitchFactor[i]); | |
| 1331 | − } | |
| 1332 | −} | |
| 1333 | − | |
| 1334 | −void tRetune_setPitchFactor(tRetune* const rt, float pf, int voice) | |
| 1335 | −{ | |
| 1336 | − _tRetune* r = *rt; | |
| 1337 | − | |
| 1338 | − r->pitchFactor[voice] = pf; | |
| 1339 | − tPitchShift_setPitchFactor(&r->ps[voice], r->pitchFactor[voice]); | |
| 1340 | −} | |
| 1341 | − | |
| 1342 | −void tRetune_setTimeConstant(tRetune* const rt, float tc) | |
| 1343 | −{ | |
| 1344 | − _tRetune* r = *rt; | |
| 1345 | − | |
| 1346 | − r->timeConstant = tc; | |
| 1347 | − r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant); | |
| 1348 | −} | |
| 1349 | − | |
| 1350 | −void tRetune_setHopSize(tRetune* const rt, int hs) | |
| 1351 | −{ | |
| 1352 | − _tRetune* r = *rt; | |
| 1353 | − | |
| 1354 | − r->hopSize = hs; | |
| 1355 | − tPeriodDetection_setHopSize(&r->pd, r->hopSize); | |
| 1356 | −} | |
| 1357 | − | |
| 1358 | −void tRetune_setWindowSize(tRetune* const rt, int ws) | |
| 1359 | −{ | |
| 1360 | − _tRetune* r = *rt; | |
| 1361 | − | |
| 1362 | − r->windowSize = ws; | |
| 1363 | − tPeriodDetection_setWindowSize(&r->pd, r->windowSize); | |
| 1364 | −} | |
| 1365 | − | |
| 1366 | −void tRetune_setFidelityThreshold(tRetune* const rt, float threshold) | |
| 1367 | −{ | |
| 1368 | − _tRetune* r = *rt; | |
| 1369 | − | |
| 1370 | − tPeriodDetection_setFidelityThreshold(&r->pd, threshold); | |
| 1371 | −} | |
| 1372 | − | |
| 1373 | −float tRetune_getInputPeriod(tRetune* const rt) | |
| 1374 | −{ | |
| 1375 | − _tRetune* r = *rt; | |
| 1376 | − | |
| 1377 | − return (r->inputPeriod * leaf.invSampleRate); | |
| 1378 | −} | |
| 1379 | − | |
| 1380 | −float tRetune_getInputFreq(tRetune* const rt) | |
| 1381 | −{ | |
| 1382 | − _tRetune* r = *rt; | |
| 1383 | − | |
| 1384 | − return 1.0f/(r->inputPeriod * leaf.invSampleRate); | |
| 1385 | −} | |
| 1386 | − | |
| 1387 | −//============================================================================================================ | |
| 1388 | −// AUTOTUNE | |
| 1389 | −//============================================================================================================ | |
| 1390 | − | |
| 1391 | −void tAutotune_init(tAutotune* const rt, int numVoices, int bufSize, int frameSize) | |
| 1392 | −{ | |
| 1393 | − tAutotune_initToPool(rt, numVoices, bufSize, frameSize, &leaf.mempool); | |
| 1394 | −} | |
| 1395 | − | |
| 1396 | −void tAutotune_free(tAutotune* const rt) | |
| 1397 | −{ | |
| 1398 | − tAutotune_freeFromPool(rt, &leaf.mempool); | |
| 1399 | −} | |
| 1400 | − | |
| 1401 | −void tAutotune_initToPool (tAutotune* const rt, int numVoices, int bufSize, int frameSize, tMempool* const mp) | |
| 1402 | −{ | |
| 1403 | − _tMempool* m = *mp; | |
| 1404 | − _tAutotune* r = *rt = (_tAutotune*) mpool_alloc(sizeof(_tAutotune), m); | |
| 1405 | − | |
| 1406 | − r->bufSize = bufSize; | |
| 1407 | − r->frameSize = frameSize; | |
| 1408 | − r->numVoices = numVoices; | |
| 1409 | − | |
| 1410 | − r->inBuffer = (float*) mpool_alloc(sizeof(float) * r->bufSize, m); | |
| 1411 | − r->outBuffers = (float**) mpool_alloc(sizeof(float*) * r->numVoices, m); | |
| 1412 | − | |
| 1413 | − r->hopSize = DEFHOPSIZE; | |
| 1414 | − r->windowSize = DEFWINDOWSIZE; | |
| 1415 | − r->fba = FBA; | |
| 1416 | − tAutotune_setTimeConstant(rt, DEFTIMECONSTANT); | |
| 1417 | − | |
| 1418 | − r->ps = (tPitchShift*) mpool_alloc(sizeof(tPitchShift) * r->numVoices, m); | |
| 1419 | − r->freq = (float*) mpool_alloc(sizeof(float) * r->numVoices, m); | |
| 1420 | − r->tickOutput = (float*) mpool_alloc(sizeof(float) * r->numVoices, m); | |
| 1421 | − for (int i = 0; i < r->numVoices; ++i) | |
| 1422 | − { | |
| 1423 | − r->outBuffers[i] = (float*) mpool_alloc(sizeof(float) * r->bufSize, m); | |
| 1424 | − } | |
| 1425 | − | |
| 1426 | − tPeriodDetection_initToPool(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize, mp); | |
| 1427 | − | |
| 1428 | − for (int i = 0; i < r->numVoices; ++i) | |
| 1429 | − { | |
| 1430 | − tPitchShift_initToPool(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize, mp); | |
| 1431 | − } | |
| 1432 | − | |
| 1433 | − r->inputPeriod = 0.0f; | |
| 1434 | −} | |
| 1435 | − | |
| 1436 | −void tAutotune_freeFromPool (tAutotune* const rt, tMempool* const mp) | |
| 1437 | −{ | |
| 1438 | − _tMempool* m = *mp; | |
| 1439 | − _tAutotune* r = *rt; | |
| 1440 | − | |
| 1441 | − tPeriodDetection_freeFromPool(&r->pd, mp); | |
| 1442 | − for (int i = 0; i < r->numVoices; ++i) | |
| 1443 | − { | |
| 1444 | − tPitchShift_freeFromPool(&r->ps[i], mp); | |
| 1445 | − mpool_free((char*)r->outBuffers[i], m); | |
| 1446 | − } | |
| 1447 | − mpool_free((char*)r->tickOutput, m); | |
| 1448 | − mpool_free((char*)r->freq, m); | |
| 1449 | − mpool_free((char*)r->ps, m); | |
| 1450 | − mpool_free((char*)r->inBuffer, m); | |
| 1451 | − mpool_free((char*)r->outBuffers, m); | |
| 1452 | − mpool_free((char*)r, m); | |
| 1453 | −} | |
| 1454 | − | |
| 1455 | −float* tAutotune_tick(tAutotune* const rt, float sample) | |
| 1456 | −{ | |
| 1457 | − _tAutotune* r = *rt; | |
| 1458 | − | |
| 1459 | − float tempPeriod = tPeriodDetection_tick(&r->pd, sample); | |
| 1460 | − if (tempPeriod < 1000.0f) //to avoid trying to follow consonants JS | |
| 1461 | − { | |
| 1462 | − r->inputPeriod = tempPeriod; | |
| 1463 | − } | |
| 1464 | − | |
| 1465 | − for (int v = 0; v < r->numVoices; ++v) | |
| 1466 | − { | |
| 1467 | − r->tickOutput[v] = tPitchShift_shiftToFreq(&r->ps[v], r->freq[v]); | |
| 1468 | − } | |
| 1469 | − | |
| 1470 | − return r->tickOutput; | |
| 1471 | −} | |
| 1472 | − | |
| 1473 | −void tAutotune_setNumVoices(tAutotune* const rt, int numVoices) | |
| 1474 | −{ | |
| 1475 | − _tAutotune* r = *rt; | |
| 1476 | − | |
| 1477 | − for (int i = 0; i < r->numVoices; ++i) | |
| 1478 | − { | |
| 1479 | − tPitchShift_free(&r->ps[i]); | |
| 1480 | − leaf_free((char*)r->outBuffers[i]); | |
| 1481 | − } | |
| 1482 | − leaf_free((char*)r->tickOutput); | |
| 1483 | − leaf_free((char*)r->freq); | |
| 1484 | − leaf_free((char*)r->ps); | |
| 1485 | − leaf_free((char*)r->outBuffers); | |
| 1486 | − | |
| 1487 | − r->numVoices = numVoices; | |
| 1488 | − | |
| 1489 | − r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices); | |
| 1490 | − r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices); | |
| 1491 | − r->freq = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 1492 | − r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 1493 | − for (int i = 0; i < r->numVoices; ++i) | |
| 1494 | − { | |
| 1495 | − r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 1496 | − tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize); | |
| 1497 | − } | |
| 1498 | −} | |
| 1499 | − | |
| 1500 | −void tAutotune_setFreqs(tAutotune* const rt, float f) | |
| 1501 | −{ | |
| 1502 | − _tAutotune* r = *rt; | |
| 1503 | − | |
| 1504 | − for (int i = 0; i < r->numVoices; ++i) | |
| 1505 | − { | |
| 1506 | − r->freq[i] = f; | |
| 1507 | − } | |
| 1508 | −} | |
| 1509 | − | |
| 1510 | −void tAutotune_setFreq(tAutotune* const rt, float f, int voice) | |
| 1511 | −{ | |
| 1512 | − _tAutotune* r = *rt; | |
| 1513 | − | |
| 1514 | − r->freq[voice] = f; | |
| 1515 | −} | |
| 1516 | − | |
| 1517 | −void tAutotune_setTimeConstant(tAutotune* const rt, float tc) | |
| 1518 | −{ | |
| 1519 | − _tAutotune* r = *rt; | |
| 1520 | − | |
| 1521 | − r->timeConstant = tc; | |
| 1522 | − r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant); | |
| 1523 | −} | |
| 1524 | − | |
| 1525 | −void tAutotune_setHopSize(tAutotune* const rt, int hs) | |
| 1526 | −{ | |
| 1527 | − _tAutotune* r = *rt; | |
| 1528 | − | |
| 1529 | − r->hopSize = hs; | |
| 1530 | − tPeriodDetection_setHopSize(&r->pd, r->hopSize); | |
| 1531 | −} | |
| 1532 | − | |
| 1533 | −void tAutotune_setWindowSize(tAutotune* const rt, int ws) | |
| 1534 | −{ | |
| 1535 | − _tAutotune* r = *rt; | |
| 1536 | − | |
| 1537 | − r->windowSize = ws; | |
| 1538 | − tPeriodDetection_setWindowSize(&r->pd, r->windowSize); | |
| 1539 | −} | |
| 1540 | − | |
| 1541 | −void tAutotune_setFidelityThreshold(tAutotune* const rt, float threshold) | |
| 1542 | −{ | |
| 1543 | − _tAutotune* r = *rt; | |
| 1544 | − | |
| 1545 | − tPeriodDetection_setFidelityThreshold(&r->pd, threshold); | |
| 1546 | −} | |
| 1547 | − | |
| 1548 | −void tAutotune_setAlpha (tAutotune* rt, float alpha) | |
| 1549 | −{ | |
| 1550 | − _tAutotune* r = *rt; | |
| 1551 | − tPeriodDetection_setAlpha(&r->pd, alpha); | |
| 1552 | −} | |
| 1553 | − | |
| 1554 | −void tAutotune_setTolerance (tAutotune* rt, float tolerance) | |
| 1555 | −{ | |
| 1556 | − _tAutotune* r = *rt; | |
| 1557 | − tPeriodDetection_setTolerance(&r->pd, tolerance); | |
| 1558 | −} | |
| 1559 | − | |
| 1560 | −float tAutotune_getInputPeriod(tAutotune* const rt) | |
| 1561 | −{ | |
| 1562 | − _tAutotune* r = *rt; | |
| 1563 | − | |
| 1564 | − return r->inputPeriod; | |
| 1565 | −} | |
| 1566 | − | |
| 1567 | −float tAutotune_getInputFreq(tAutotune* const rt) | |
| 1568 | −{ | |
| 1569 | − _tAutotune* r = *rt; | |
| 1570 | − | |
| 1571 | − return 1.0f/r->inputPeriod; | |
| 1572 | −} | |
| 1573 | − | |
| 1574 | −//============================================================================================================ | |
| 1575 | −// FORMANTSHIFTER | |
| 1576 | −//============================================================================================================ | |
| 1577 | −// algorithm from Tom Baran's autotalent code. | |
| 1578 | − | |
| 1579 | −void tFormantShifter_init(tFormantShifter* const fsr, int order) | |
| 1580 | −{ | |
| 1581 | − _tFormantShifter* fs = *fsr = (_tFormantShifter*) leaf_alloc(sizeof(_tFormantShifter)); | |
| 1582 | − | |
| 1583 | − fs->ford = order; | |
| 1584 | − fs->fk = (float*) leaf_calloc(sizeof(float) * fs->ford); | |
| 1585 | − fs->fb = (float*) leaf_calloc(sizeof(float) * fs->ford); | |
| 1586 | − fs->fc = (float*) leaf_calloc(sizeof(float) * fs->ford); | |
| 1587 | − fs->frb = (float*) leaf_calloc(sizeof(float) * fs->ford); | |
| 1588 | − fs->frc = (float*) leaf_calloc(sizeof(float) * fs->ford); | |
| 1589 | − fs->fsig = (float*) leaf_calloc(sizeof(float) * fs->ford); | |
| 1590 | − fs->fsmooth = (float*) leaf_calloc(sizeof(float) * fs->ford); | |
| 1591 | − fs->ftvec = (float*) leaf_calloc(sizeof(float) * fs->ford); | |
| 1592 | − fs->fbuff = (float*) leaf_calloc(sizeof(float*) * fs->ford); | |
| 1593 | − | |
| 1594 | − fs->falph = powf(0.001f, 40.0f * leaf.invSampleRate); | |
| 1595 | − fs->flamb = -(0.8517f*sqrtf(atanf(0.06583f*leaf.sampleRate))-0.1916f); | |
| 1596 | − fs->fhp = 0.0f; | |
| 1597 | − fs->flp = 0.0f; | |
| 1598 | − fs->flpa = powf(0.001f, 10.0f * leaf.invSampleRate); | |
| 1599 | − fs->fmute = 1.0f; | |
| 1600 | − fs->fmutealph = powf(0.001f, 0.5f * leaf.invSampleRate); | |
| 1601 | − fs->cbi = 0; | |
| 1602 | − fs->intensity = 1.0f; | |
| 1603 | − fs->invIntensity = 1.0f; | |
| 1604 | − tHighpass_init(&fs->hp, 10.0f); | |
| 1605 | − tHighpass_init(&fs->hp2, 10.0f); | |
| 1606 | − tFeedbackLeveler_init(&fs->fbl1, 0.99f, 0.005f, 0.125f, 0); | |
| 1607 | − tFeedbackLeveler_init(&fs->fbl2, 0.99f, 0.005f, 0.125f, 0); | |
| 1608 | −} | |
| 1609 | − | |
| 1610 | −void tFormantShifter_free(tFormantShifter* const fsr) | |
| 1611 | −{ | |
| 1612 | − _tFormantShifter* fs = *fsr; | |
| 1613 | − | |
| 1614 | − leaf_free((char*)fs->fk); | |
| 1615 | − leaf_free((char*)fs->fb); | |
| 1616 | − leaf_free((char*)fs->fc); | |
| 1617 | − leaf_free((char*)fs->frb); | |
| 1618 | − leaf_free((char*)fs->frc); | |
| 1619 | − leaf_free((char*)fs->fsig); | |
| 1620 | − leaf_free((char*)fs->fsmooth); | |
| 1621 | − leaf_free((char*)fs->ftvec); | |
| 1622 | − leaf_free((char*)fs->fbuff); | |
| 1623 | − tHighpass_free(&fs->hp); | |
| 1624 | − tHighpass_free(&fs->hp2); | |
| 1625 | − tFeedbackLeveler_free(&fs->fbl1); | |
| 1626 | − tFeedbackLeveler_free(&fs->fbl2); | |
| 1627 | − leaf_free((char*)fs); | |
| 1628 | −} | |
| 1629 | − | |
| 1630 | −void tFormantShifter_initToPool (tFormantShifter* const fsr, int order, tMempool* const mp) | |
| 1631 | −{ | |
| 1632 | − _tMempool* m = *mp; | |
| 1633 | − _tFormantShifter* fs = *fsr = (_tFormantShifter*) mpool_alloc(sizeof(_tFormantShifter), m); | |
| 1634 | − | |
| 1635 | − fs->ford = order; | |
| 1636 | − fs->fk = (float*) mpool_calloc(sizeof(float) * fs->ford, m); | |
| 1637 | − fs->fb = (float*) mpool_calloc(sizeof(float) * fs->ford, m); | |
| 1638 | − fs->fc = (float*) mpool_calloc(sizeof(float) * fs->ford, m); | |
| 1639 | − fs->frb = (float*) mpool_calloc(sizeof(float) * fs->ford, m); | |
| 1640 | − fs->frc = (float*) mpool_calloc(sizeof(float) * fs->ford, m); | |
| 1641 | − fs->fsig = (float*) mpool_calloc(sizeof(float) * fs->ford, m); | |
| 1642 | − fs->fsmooth = (float*) mpool_calloc(sizeof(float) * fs->ford, m); | |
| 1643 | − fs->ftvec = (float*) mpool_calloc(sizeof(float) * fs->ford, m); | |
| 1644 | − | |
| 1645 | − fs->fbuff = (float*) mpool_calloc(sizeof(float*) * fs->ford, m); | |
| 1646 | − | |
| 1647 | − | |
| 1648 | − fs->falph = powf(0.001f, 10.0f * leaf.invSampleRate); | |
| 1649 | − fs->flamb = -(0.8517f*sqrtf(atanf(0.06583f*leaf.sampleRate))-0.1916f); | |
| 1650 | − fs->fhp = 0.0f; | |
| 1651 | − fs->flp = 0.0f; | |
| 1652 | − fs->flpa = powf(0.001f, 10.0f * leaf.invSampleRate); | |
| 1653 | − fs->fmute = 1.0f; | |
| 1654 | − fs->fmutealph = powf(0.001f, 1.0f * leaf.invSampleRate); | |
| 1655 | − fs->cbi = 0; | |
| 1656 | − fs->intensity = 1.0f; | |
| 1657 | − fs->invIntensity = 1.0f; | |
| 1658 | − tHighpass_initToPool(&fs->hp, 20.0f, mp); | |
| 1659 | − tHighpass_initToPool(&fs->hp2, 20.0f, mp); | |
| 1660 | − tFeedbackLeveler_initToPool(&fs->fbl1, 0.8f, .005f, 0.125, 1, mp); | |
| 1661 | − tFeedbackLeveler_initToPool(&fs->fbl2, 0.8f, .005f, 0.125, 1, mp); | |
| 1662 | −} | |
| 1663 | − | |
| 1664 | −void tFormantShifter_freeFromPool (tFormantShifter* const fsr, tMempool* const mp) | |
| 1665 | −{ | |
| 1666 | − _tMempool* m = *mp; | |
| 1667 | − _tFormantShifter* fs = *fsr; | |
| 1668 | − | |
| 1669 | − mpool_free((char*)fs->fk, m); | |
| 1670 | − mpool_free((char*)fs->fb, m); | |
| 1671 | − mpool_free((char*)fs->fc, m); | |
| 1672 | − mpool_free((char*)fs->frb, m); | |
| 1673 | − mpool_free((char*)fs->frc, m); | |
| 1674 | − mpool_free((char*)fs->fsig, m); | |
| 1675 | − mpool_free((char*)fs->fsmooth, m); | |
| 1676 | − mpool_free((char*)fs->ftvec, m); | |
| 1677 | − mpool_free((char*)fs->fbuff, m); | |
| 1678 | − tHighpass_freeFromPool(&fs->hp, mp); | |
| 1679 | − tHighpass_freeFromPool(&fs->hp2, mp); | |
| 1680 | − tFeedbackLeveler_freeFromPool(&fs->fbl1, mp); | |
| 1681 | − tFeedbackLeveler_freeFromPool(&fs->fbl2, mp); | |
| 1682 | − mpool_free((char*)fs, m); | |
| 1683 | −} | |
| 1684 | − | |
| 1685 | −float tFormantShifter_tick(tFormantShifter* const fsr, float in) | |
| 1686 | −{ | |
| 1687 | − return tFormantShifter_add(fsr, tFormantShifter_remove(fsr, in)); | |
| 1688 | −} | |
| 1689 | − | |
| 1690 | −float tFormantShifter_remove(tFormantShifter* const fsr, float in) | |
| 1691 | −{ | |
| 1692 | − _tFormantShifter* fs = *fsr; | |
| 1693 | − in = tFeedbackLeveler_tick(&fs->fbl1, in); | |
| 1694 | − in = tHighpass_tick(&fs->hp, in * fs->intensity); | |
| 1695 | − | |
| 1696 | − | |
| 1697 | − float fa, fb, fc, foma, falph, ford, flamb, tf, fk; | |
| 1698 | − | |
| 1699 | − ford = fs->ford; | |
| 1700 | − falph = fs->falph; | |
| 1701 | − foma = (1.0f - falph); | |
| 1702 | − flamb = fs->flamb; | |
| 1703 | − | |
| 1704 | − tf = in; | |
| 1705 | − | |
| 1706 | − fa = tf - fs->fhp; | |
| 1707 | − fs->fhp = tf; | |
| 1708 | − fb = fa; | |
| 1709 | − for(int i = 0; i < ford; i++) | |
| 1710 | − { | |
| 1711 | − fs->fsig[i] = fa*fa*foma + fs->fsig[i]*falph; | |
| 1712 | − fc = (fb - fs->fc[i])*flamb + fs->fb[i]; | |
| 1713 | − fs->fc[i] = fc; | |
| 1714 | − fs->fb[i] = fb; | |
| 1715 | − fk = fa*fc*foma + fs->fk[i]*falph; | |
| 1716 | − fs->fk[i] = fk; | |
| 1717 | − tf = fk/(fs->fsig[i] + 0.000001f); | |
| 1718 | − tf = tf*foma + fs->fsmooth[i]*falph; | |
| 1719 | − fs->fsmooth[i] = tf; | |
| 1720 | − fs->fbuff[i] = tf; | |
| 1721 | − fb = fc - tf*fa; | |
| 1722 | − fa = fa - tf*fc; | |
| 1723 | − } | |
| 1724 | − | |
| 1725 | − //return fa * 0.1f; | |
| 1726 | − return fa; | |
| 1727 | −} | |
| 1728 | − | |
| 1729 | −float tFormantShifter_add(tFormantShifter* const fsr, float in) | |
| 1730 | −{ | |
| 1731 | − _tFormantShifter* fs = *fsr; | |
| 1732 | − | |
| 1733 | − float fa, fb, fc, ford, flpa, flamb, tf, tf2, f0resp, f1resp, frlamb; | |
| 1734 | − ford = fs->ford; | |
| 1735 | − | |
| 1736 | − flpa = fs->flpa; | |
| 1737 | − flamb = fs->flamb; | |
| 1738 | − tf = fs->shiftFactor * (1.0f+flamb)/(1.0f-flamb); | |
| 1739 | − frlamb = (tf-1.0f)/(tf+1.0f); | |
| 1740 | − | |
| 1741 | − tf2 = in; | |
| 1742 | − fa = 0.0f; | |
| 1743 | − fb = fa; | |
| 1744 | − for (int i=0; i<ford; i++) | |
| 1745 | − { | |
| 1746 | − fc = (fb-fs->frc[i])*frlamb + fs->frb[i]; | |
| 1747 | − tf = fs->fbuff[i]; | |
| 1748 | − fb = fc - tf*fa; | |
| 1749 | − fs->ftvec[i] = tf*fc; | |
| 1750 | − fa = fa - fs->ftvec[i]; | |
| 1751 | − } | |
| 1752 | − tf = -fa; | |
| 1753 | − for (int i=ford-1; i>=0; i--) | |
| 1754 | − { | |
| 1755 | − tf = tf + fs->ftvec[i]; | |
| 1756 | − } | |
| 1757 | − f0resp = tf; | |
| 1758 | − | |
| 1759 | − // second time: compute 1-response | |
| 1760 | − fa = 1.0f; | |
| 1761 | − fb = fa; | |
| 1762 | − for (int i=0; i<ford; i++) | |
| 1763 | − { | |
| 1764 | − fc = (fb-fs->frc[i])*frlamb + fs->frb[i]; | |
| 1765 | − tf = fs->fbuff[i]; | |
| 1766 | − fb = fc - tf*fa; | |
| 1767 | − fs->ftvec[i] = tf*fc; | |
| 1768 | − fa = fa - fs->ftvec[i]; | |
| 1769 | − } | |
| 1770 | − tf = -fa; | |
| 1771 | − for (int i=ford-1; i>=0; i--) | |
| 1772 | − { | |
| 1773 | − tf = tf + fs->ftvec[i]; | |
| 1774 | − } | |
| 1775 | − f1resp = tf; | |
| 1776 | − | |
| 1777 | − // now solve equations for output, based on 0-response and 1-response | |
| 1778 | − tf = 2.0f*tf2; | |
| 1779 | − tf2 = tf; | |
| 1780 | − tf = (1.0f - f1resp + f0resp); | |
| 1781 | − if (tf!=0.0f) | |
| 1782 | − { | |
| 1783 | − tf2 = (tf2 + f0resp) / tf; | |
| 1784 | − } | |
| 1785 | − else | |
| 1786 | − { | |
| 1787 | − tf2 = 0.0f; | |
| 1788 | − } | |
| 1789 | − | |
| 1790 | − // third time: update delay registers | |
| 1791 | − fa = tf2; | |
| 1792 | − fb = fa; | |
| 1793 | − for (int i=0; i<ford; i++) | |
| 1794 | − { | |
| 1795 | − fc = (fb-fs->frc[i])*frlamb + fs->frb[i]; | |
| 1796 | − fs->frc[i] = fc; | |
| 1797 | − fs->frb[i] = fb; | |
| 1798 | − tf = fs->fbuff[i]; | |
| 1799 | − fb = fc - tf*fa; | |
| 1800 | − fa = fa - tf*fc; | |
| 1801 | − } | |
| 1802 | − tf = tf2; | |
| 1803 | − tf = tf + flpa * fs->flp; // lowpass post-emphasis filter | |
| 1804 | − fs->flp = tf; | |
| 1805 | − | |
| 1806 | − // Bring up the gain slowly when formant correction goes from disabled | |
| 1807 | − // to enabled, while things stabilize. | |
| 1808 | − if (fs->fmute>0.5f) | |
| 1809 | − { | |
| 1810 | − tf = tf*(fs->fmute - 0.5f)*2.0f; | |
| 1811 | − } | |
| 1812 | − else | |
| 1813 | − { | |
| 1814 | − tf = 0.0f; | |
| 1815 | − } | |
| 1816 | − tf2 = fs->fmutealph; | |
| 1817 | − fs->fmute = (1.0f-tf2) + tf2*fs->fmute; | |
| 1818 | − // now tf is signal output | |
| 1819 | − // ...and we're done messing with formants | |
| 1820 | − //tf = tFeedbackLeveler_tick(&fs->fbl2, tf); | |
| 1821 | − tf = tHighpass_tick(&fs->hp2, tanhf(tf)); | |
| 1822 | − | |
| 1823 | − return tf * fs->invIntensity; | |
| 1824 | −} | |
| 1825 | − | |
| 1826 | −// 1.0f is no change, 2.0f is an octave up, 0.5f is an octave down | |
| 1827 | −void tFormantShifter_setShiftFactor(tFormantShifter* const fsr, float shiftFactor) | |
| 1828 | −{ | |
| 1829 | − _tFormantShifter* fs = *fsr; | |
| 1830 | − fs->shiftFactor = shiftFactor; | |
| 1831 | −} | |
| 1832 | − | |
| 1833 | −void tFormantShifter_setIntensity(tFormantShifter* const fsr, float intensity) | |
| 1834 | −{ | |
| 1835 | − _tFormantShifter* fs = *fsr; | |
| 1836 | − | |
| 1837 | − | |
| 1838 | − | |
| 1839 | − fs->intensity = LEAF_clip(1.0f, intensity, 100.0f); | |
| 1840 | − | |
| 1841 | − // tFeedbackLeveler_setTargetLevel(&fs->fbl1, fs->intensity); | |
| 1842 | − //tFeedbackLeveler_setTargetLevel(&fs->fbl2, fs->intensity); | |
| 1843 | − //make sure you don't divide by zero, doofies | |
| 1844 | − if (fs->intensity != 0.0f) | |
| 1845 | − { | |
| 1846 | − fs->invIntensity = 1.0f/fs->intensity; | |
| 1847 | − } | |
| 1848 | − else | |
| 1849 | − { | |
| 1850 | − fs->invIntensity = 1.0f; | |
| 1851 | − } | |
| 1852 | − | |
| 1853 | −} | |
| @@ -1,551 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * leaf-electrical.c | |
| 3 | − * | |
| 4 | − * Created on: Sep 25, 2019 | |
| 5 | − * Author: jeffsnyder | |
| 6 | − */ | |
| 7 | − | |
| 8 | −#if _WIN32 || _WIN64 | |
| 9 | − | |
| 10 | −#include "..\Inc\leaf-electrical.h" | |
| 11 | −#include "..\leaf.h" | |
| 12 | − | |
| 13 | −#else | |
| 14 | − | |
| 15 | −#include "../Inc/leaf-electrical.h" | |
| 16 | −#include "../leaf.h" | |
| 17 | − | |
| 18 | −#endif | |
| 19 | − | |
| 20 | −//============================================================================== | |
| 21 | − | |
| 22 | −static float get_port_resistance_for_resistor(tWDF* const r); | |
| 23 | −static float get_port_resistance_for_capacitor(tWDF* const r); | |
| 24 | −static float get_port_resistance_for_inductor(tWDF* const r); | |
| 25 | −static float get_port_resistance_for_resistive(tWDF* const r); | |
| 26 | −static float get_port_resistance_for_inverter(tWDF* const r); | |
| 27 | −static float get_port_resistance_for_series(tWDF* const r); | |
| 28 | −static float get_port_resistance_for_parallel(tWDF* const r); | |
| 29 | −static float get_port_resistance_for_root(tWDF* const r); | |
| 30 | − | |
| 31 | −static void set_incident_wave_for_leaf(tWDF* const r, float incident_wave, float input); | |
| 32 | −static void set_incident_wave_for_leaf_inverted(tWDF* const r, float incident_wave, float input); | |
| 33 | −static void set_incident_wave_for_inverter(tWDF* const r, float incident_wave, float input); | |
| 34 | −static void set_incident_wave_for_series(tWDF* const r, float incident_wave, float input); | |
| 35 | −static void set_incident_wave_for_parallel(tWDF* const r, float incident_wave, float input); | |
| 36 | − | |
| 37 | −static float get_reflected_wave_for_resistor(tWDF* const r, float input); | |
| 38 | −static float get_reflected_wave_for_capacitor(tWDF* const r, float input); | |
| 39 | −static float get_reflected_wave_for_resistive(tWDF* const r, float input); | |
| 40 | −static float get_reflected_wave_for_inverter(tWDF* const r, float input); | |
| 41 | −static float get_reflected_wave_for_series(tWDF* const r, float input); | |
| 42 | −static float get_reflected_wave_for_parallel(tWDF* const r, float input); | |
| 43 | − | |
| 44 | −static float get_reflected_wave_for_ideal(tWDF* const n, float input, float incident_wave); | |
| 45 | −static float get_reflected_wave_for_diode(tWDF* const n, float input, float incident_wave); | |
| 46 | −static float get_reflected_wave_for_diode_pair(tWDF* const n, float input, float incident_wave); | |
| 47 | − | |
| 48 | −static void wdf_init(tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR) | |
| 49 | −{ | |
| 50 | − _tWDF* r = *wdf; | |
| 51 | − | |
| 52 | − r->type = type; | |
| 53 | − r->child_left = rL; | |
| 54 | − r->child_right = rR; | |
| 55 | − r->incident_wave_up = 0.0f; | |
| 56 | − r->incident_wave_left = 0.0f; | |
| 57 | − r->incident_wave_right = 0.0f; | |
| 58 | − r->reflected_wave_up = 0.0f; | |
| 59 | − r->reflected_wave_left = 0.0f; | |
| 60 | − r->reflected_wave_right = 0.0f; | |
| 61 | − r->sample_rate = leaf.sampleRate; | |
| 62 | − r->value = value; | |
| 63 | − | |
| 64 | − tWDF* child; | |
| 65 | − if (r->child_left != NULL) child = r->child_left; | |
| 66 | − else child = r->child_right; | |
| 67 | − | |
| 68 | − if (r->type == Resistor) | |
| 69 | − { | |
| 70 | − r->port_resistance_up = r->value; | |
| 71 | − r->port_conductance_up = 1.0f / r->value; | |
| 72 | − | |
| 73 | − r->get_port_resistance = &get_port_resistance_for_resistor; | |
| 74 | − r->get_reflected_wave_up = &get_reflected_wave_for_resistor; | |
| 75 | − r->set_incident_wave = &set_incident_wave_for_leaf; | |
| 76 | − } | |
| 77 | − else if (r->type == Capacitor) | |
| 78 | − { | |
| 79 | − r->port_conductance_up = r->sample_rate * 2.0f * r->value; | |
| 80 | − r->port_resistance_up = 1.0f / r->port_conductance_up; //based on trapezoidal discretization | |
| 81 | − | |
| 82 | − r->get_port_resistance = &get_port_resistance_for_capacitor; | |
| 83 | − r->get_reflected_wave_up = &get_reflected_wave_for_capacitor; | |
| 84 | − r->set_incident_wave = &set_incident_wave_for_leaf; | |
| 85 | − } | |
| 86 | − else if (r->type == Inductor) | |
| 87 | − { | |
| 88 | − r->port_resistance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization | |
| 89 | − r->port_conductance_up = 1.0f / r->port_resistance_up; | |
| 90 | − | |
| 91 | − r->get_port_resistance = &get_port_resistance_for_inductor; | |
| 92 | − r->get_reflected_wave_up = &get_reflected_wave_for_capacitor; // same as capacitor | |
| 93 | − r->set_incident_wave = &set_incident_wave_for_leaf_inverted; | |
| 94 | − } | |
| 95 | − else if (r->type == ResistiveSource) | |
| 96 | − { | |
| 97 | − r->port_resistance_up = r->value; | |
| 98 | − r->port_conductance_up = 1.0f / r->port_resistance_up; | |
| 99 | − | |
| 100 | − r->get_port_resistance = &get_port_resistance_for_resistive; | |
| 101 | − r->get_reflected_wave_up = &get_reflected_wave_for_resistive; | |
| 102 | − r->set_incident_wave = &set_incident_wave_for_leaf; | |
| 103 | − } | |
| 104 | − else if (r->type == Inverter) | |
| 105 | − { | |
| 106 | − r->port_resistance_up = tWDF_getPortResistance(r->child_left); | |
| 107 | − r->port_conductance_up = 1.0f / r->port_resistance_up; | |
| 108 | − | |
| 109 | − r->get_port_resistance = &get_port_resistance_for_inverter; | |
| 110 | − r->get_reflected_wave_up = &get_reflected_wave_for_inverter; | |
| 111 | − r->set_incident_wave = &set_incident_wave_for_inverter; | |
| 112 | − } | |
| 113 | − else if (r->type == SeriesAdaptor) | |
| 114 | − { | |
| 115 | − r->port_resistance_left = tWDF_getPortResistance(r->child_left); | |
| 116 | − r->port_resistance_right = tWDF_getPortResistance(r->child_right); | |
| 117 | − r->port_resistance_up = r->port_resistance_left + r->port_resistance_right; | |
| 118 | − r->port_conductance_up = 1.0f / r->port_resistance_up; | |
| 119 | − r->port_conductance_left = 1.0f / r->port_resistance_left; | |
| 120 | − r->port_conductance_right = 1.0f / r->port_resistance_right; | |
| 121 | − r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left); | |
| 122 | − | |
| 123 | − r->get_port_resistance = &get_port_resistance_for_series; | |
| 124 | − r->get_reflected_wave_up = &get_reflected_wave_for_series; | |
| 125 | − r->set_incident_wave = &set_incident_wave_for_series; | |
| 126 | − } | |
| 127 | − else if (r->type == ParallelAdaptor) | |
| 128 | − { | |
| 129 | − r->port_resistance_left = tWDF_getPortResistance(r->child_left); | |
| 130 | − r->port_resistance_right = tWDF_getPortResistance(r->child_right); | |
| 131 | − r->port_resistance_up = (r->port_resistance_left * r->port_resistance_right) / (r->port_resistance_left + r->port_resistance_right); | |
| 132 | − r->port_conductance_up = 1.0f / r->port_resistance_up; | |
| 133 | − r->port_conductance_left = 1.0f / r->port_resistance_left; | |
| 134 | − r->port_conductance_right = 1.0f / r->port_resistance_right; | |
| 135 | − r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left); | |
| 136 | − | |
| 137 | − r->get_port_resistance = &get_port_resistance_for_parallel; | |
| 138 | − r->get_reflected_wave_up = &get_reflected_wave_for_parallel; | |
| 139 | − r->set_incident_wave = &set_incident_wave_for_parallel; | |
| 140 | − } | |
| 141 | − else if (r->type == IdealSource) | |
| 142 | − { | |
| 143 | − r->port_resistance_up = tWDF_getPortResistance(child); | |
| 144 | − r->port_conductance_up = 1.0f / r->port_resistance_up; | |
| 145 | − | |
| 146 | − r->get_reflected_wave_down = &get_reflected_wave_for_ideal; | |
| 147 | − r->get_port_resistance = &get_port_resistance_for_root; | |
| 148 | − } | |
| 149 | − else if (r->type == Diode) | |
| 150 | − { | |
| 151 | − r->port_resistance_up = tWDF_getPortResistance(child); | |
| 152 | − r->port_conductance_up = 1.0f / r->port_resistance_up; | |
| 153 | − | |
| 154 | − r->get_reflected_wave_down = &get_reflected_wave_for_diode; | |
| 155 | − r->get_port_resistance = &get_port_resistance_for_root; | |
| 156 | − } | |
| 157 | − else if (r->type == DiodePair) | |
| 158 | − { | |
| 159 | − r->port_resistance_up = tWDF_getPortResistance(child); | |
| 160 | − r->port_conductance_up = 1.0f / r->port_resistance_up; | |
| 161 | − | |
| 162 | − r->get_reflected_wave_down = &get_reflected_wave_for_diode_pair; | |
| 163 | − r->get_port_resistance = &get_port_resistance_for_root; | |
| 164 | − } | |
| 165 | −} | |
| 166 | −//WDF | |
| 167 | −void tWDF_init(tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR) | |
| 168 | −{ | |
| 169 | − *wdf = (_tWDF*) leaf_alloc(sizeof(_tWDF)); | |
| 170 | − | |
| 171 | − wdf_init(wdf, type, value, rL, rR); | |
| 172 | −} | |
| 173 | − | |
| 174 | −void tWDF_free(tWDF* const wdf) | |
| 175 | −{ | |
| 176 | − _tWDF* r = *wdf; | |
| 177 | − | |
| 178 | − leaf_free((char*)r); | |
| 179 | −} | |
| 180 | − | |
| 181 | −void tWDF_initToPool (tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR, tMempool* const mp) | |
| 182 | −{ | |
| 183 | − _tMempool* m = *mp; | |
| 184 | − *wdf = (_tWDF*) mpool_alloc(sizeof(_tWDF), m); | |
| 185 | − | |
| 186 | − wdf_init(wdf, type, value, rL, rR); | |
| 187 | −} | |
| 188 | − | |
| 189 | −void tWDF_freeFromPool (tWDF* const wdf, tMempool* const mp) | |
| 190 | −{ | |
| 191 | − _tMempool* m = *mp; | |
| 192 | − _tWDF* r = *wdf; | |
| 193 | − | |
| 194 | − mpool_free((char*)r, m); | |
| 195 | −} | |
| 196 | − | |
| 197 | −float tWDF_tick(tWDF* const wdf, float sample, tWDF* const outputPoint, uint8_t paramsChanged) | |
| 198 | −{ | |
| 199 | − _tWDF* r = *wdf; | |
| 200 | − | |
| 201 | − tWDF* child; | |
| 202 | − if (r->child_left != NULL) child = r->child_left; | |
| 203 | − else child = r->child_right; | |
| 204 | − | |
| 205 | − //step 0 : update port resistances if something changed | |
| 206 | − if (paramsChanged) tWDF_getPortResistance(wdf); | |
| 207 | − | |
| 208 | − //step 1 : set inputs to what they should be | |
| 209 | − float input = sample; | |
| 210 | − | |
| 211 | − //step 2 : scan the waves up the tree | |
| 212 | − r->incident_wave_up = tWDF_getReflectedWaveUp(child, input); | |
| 213 | − | |
| 214 | − //step 3 : do root scattering computation | |
| 215 | − r->reflected_wave_up = tWDF_getReflectedWaveDown(wdf, input, r->incident_wave_up); | |
| 216 | − | |
| 217 | − //step 4 : propogate waves down the tree | |
| 218 | − tWDF_setIncidentWave(child, r->reflected_wave_up, input); | |
| 219 | − | |
| 220 | − //step 5 : grab whatever voltages or currents we want as outputs | |
| 221 | − return tWDF_getVoltage(outputPoint); | |
| 222 | −} | |
| 223 | − | |
| 224 | −void tWDF_setValue(tWDF* const wdf, float value) | |
| 225 | −{ | |
| 226 | − _tWDF* r = *wdf; | |
| 227 | − r->value = value; | |
| 228 | −} | |
| 229 | − | |
| 230 | −void tWDF_setSampleRate(tWDF* const wdf, float sample_rate) | |
| 231 | −{ | |
| 232 | − _tWDF* r = *wdf; | |
| 233 | − r->sample_rate = sample_rate; | |
| 234 | −} | |
| 235 | − | |
| 236 | −uint8_t tWDF_isLeaf(tWDF* const wdf) | |
| 237 | −{ | |
| 238 | − _tWDF* r = *wdf; | |
| 239 | − if (r->child_left == NULL && r->child_right == NULL) return 1; | |
| 240 | − return 0; | |
| 241 | −} | |
| 242 | − | |
| 243 | −float tWDF_getPortResistance(tWDF* const wdf) | |
| 244 | −{ | |
| 245 | − _tWDF* r = *wdf; | |
| 246 | − return r->get_port_resistance(wdf); | |
| 247 | −} | |
| 248 | − | |
| 249 | −void tWDF_setIncidentWave(tWDF* const wdf, float incident_wave, float input) | |
| 250 | −{ | |
| 251 | − _tWDF* r = *wdf; | |
| 252 | − r->set_incident_wave(wdf, incident_wave, input); | |
| 253 | −} | |
| 254 | − | |
| 255 | −float tWDF_getReflectedWaveUp(tWDF* const wdf, float input) | |
| 256 | −{ | |
| 257 | − _tWDF* r = *wdf; | |
| 258 | − return r->get_reflected_wave_up(wdf, input); | |
| 259 | −} | |
| 260 | − | |
| 261 | −float tWDF_getReflectedWaveDown(tWDF* const wdf, float input, float incident_wave) | |
| 262 | −{ | |
| 263 | − _tWDF* r = *wdf; | |
| 264 | − return r->get_reflected_wave_down(wdf, input, incident_wave); | |
| 265 | −} | |
| 266 | − | |
| 267 | −float tWDF_getVoltage(tWDF* const wdf) | |
| 268 | −{ | |
| 269 | − _tWDF* r = *wdf; | |
| 270 | − return ((r->incident_wave_up * 0.5f) + (r->reflected_wave_up * 0.5f)); | |
| 271 | −} | |
| 272 | − | |
| 273 | −float tWDF_getCurrent(tWDF* const wdf) | |
| 274 | −{ | |
| 275 | − _tWDF* r = *wdf; | |
| 276 | − return (((r->incident_wave_up * 0.5f) - (r->reflected_wave_up * 0.5f)) * r->port_conductance_up); | |
| 277 | −} | |
| 278 | − | |
| 279 | −//============ Static Functions to be Pointed To ==================== | |
| 280 | −//=================================================================== | |
| 281 | −//============ Get and Calculate Port Resistances =================== | |
| 282 | − | |
| 283 | −static float get_port_resistance_for_resistor(tWDF* const wdf) | |
| 284 | −{ | |
| 285 | − _tWDF* r = *wdf; | |
| 286 | − | |
| 287 | − r->port_resistance_up = r->value; | |
| 288 | − r->port_conductance_up = 1.0f / r->value; | |
| 289 | − | |
| 290 | − return r->port_resistance_up; | |
| 291 | −} | |
| 292 | − | |
| 293 | −static float get_port_resistance_for_capacitor(tWDF* const wdf) | |
| 294 | −{ | |
| 295 | − _tWDF* r = *wdf; | |
| 296 | − | |
| 297 | − r->port_conductance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization | |
| 298 | − r->port_resistance_up = (1.0f / r->port_conductance_up); | |
| 299 | − | |
| 300 | − return r->port_resistance_up; | |
| 301 | −} | |
| 302 | − | |
| 303 | −static float get_port_resistance_for_inductor(tWDF* const wdf) | |
| 304 | −{ | |
| 305 | − _tWDF* r = *wdf; | |
| 306 | − | |
| 307 | − r->port_resistance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization | |
| 308 | − r->port_conductance_up = (1.0f / r->port_resistance_up); | |
| 309 | − | |
| 310 | − return r->port_resistance_up; | |
| 311 | −} | |
| 312 | − | |
| 313 | −static float get_port_resistance_for_resistive(tWDF* const wdf) | |
| 314 | −{ | |
| 315 | − _tWDF* r = *wdf; | |
| 316 | − | |
| 317 | − r->port_resistance_up = r->value; | |
| 318 | − r->port_conductance_up = 1.0f / r->port_resistance_up; | |
| 319 | − | |
| 320 | − return r->port_resistance_up; | |
| 321 | −} | |
| 322 | − | |
| 323 | −static float get_port_resistance_for_inverter(tWDF* const wdf) | |
| 324 | −{ | |
| 325 | − _tWDF* r = *wdf; | |
| 326 | − | |
| 327 | − r->port_resistance_up = tWDF_getPortResistance(r->child_left); | |
| 328 | − r->port_conductance_up = 1.0f / r->port_resistance_up; | |
| 329 | − | |
| 330 | − return r->port_resistance_up; | |
| 331 | −} | |
| 332 | − | |
| 333 | −static float get_port_resistance_for_series(tWDF* const wdf) | |
| 334 | −{ | |
| 335 | − _tWDF* r = *wdf; | |
| 336 | − | |
| 337 | − r->port_resistance_left = tWDF_getPortResistance(r->child_left); | |
| 338 | − r->port_resistance_right = tWDF_getPortResistance(r->child_right); | |
| 339 | − r->port_resistance_up = r->port_resistance_left + r->port_resistance_right; | |
| 340 | − r->port_conductance_up = 1.0f / r->port_resistance_up; | |
| 341 | − r->port_conductance_left = 1.0f / r->port_resistance_left; | |
| 342 | − r->port_conductance_right = 1.0f / r->port_resistance_right; | |
| 343 | − r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left); | |
| 344 | − | |
| 345 | − return r->port_resistance_up; | |
| 346 | −} | |
| 347 | − | |
| 348 | −static float get_port_resistance_for_parallel(tWDF* const wdf) | |
| 349 | −{ | |
| 350 | − _tWDF* r = *wdf; | |
| 351 | − | |
| 352 | − r->port_resistance_left = tWDF_getPortResistance(r->child_left); | |
| 353 | − r->port_resistance_right = tWDF_getPortResistance(r->child_right); | |
| 354 | − r->port_resistance_up = (r->port_resistance_left * r->port_resistance_right) / (r->port_resistance_left + r->port_resistance_right); | |
| 355 | − r->port_conductance_up = 1.0f / r->port_resistance_up; | |
| 356 | − r->port_conductance_left = 1.0f / r->port_resistance_left; | |
| 357 | − r->port_conductance_right = 1.0f / r->port_resistance_right; | |
| 358 | − r->gamma_zero = 1.0f / (r->port_conductance_right + r->port_conductance_left); | |
| 359 | − | |
| 360 | − return r->port_resistance_up; | |
| 361 | −} | |
| 362 | − | |
| 363 | −static float get_port_resistance_for_root(tWDF* const wdf) | |
| 364 | −{ | |
| 365 | − _tWDF* r = *wdf; | |
| 366 | − | |
| 367 | − tWDF* child; | |
| 368 | − if (r->child_left != NULL) child = r->child_left; | |
| 369 | − else child = r->child_right; | |
| 370 | − | |
| 371 | − r->port_resistance_up = tWDF_getPortResistance(child); | |
| 372 | − r->port_conductance_up = 1.0f / r->port_resistance_up; | |
| 373 | − | |
| 374 | − return r->port_resistance_up; | |
| 375 | −} | |
| 376 | − | |
| 377 | −//=================================================================== | |
| 378 | −//================ Set Incident Waves =============================== | |
| 379 | − | |
| 380 | −static void set_incident_wave_for_leaf(tWDF* const wdf, float incident_wave, float input) | |
| 381 | −{ | |
| 382 | − _tWDF* r = *wdf; | |
| 383 | − r->incident_wave_up = incident_wave; | |
| 384 | −} | |
| 385 | − | |
| 386 | −static void set_incident_wave_for_leaf_inverted(tWDF* const wdf, float incident_wave, float input) | |
| 387 | −{ | |
| 388 | − _tWDF* r = *wdf; | |
| 389 | − r->incident_wave_up = -1.0f * incident_wave; | |
| 390 | −} | |
| 391 | − | |
| 392 | −static void set_incident_wave_for_inverter(tWDF* const wdf, float incident_wave, float input) | |
| 393 | −{ | |
| 394 | − _tWDF* r = *wdf; | |
| 395 | − r->incident_wave_up = incident_wave; | |
| 396 | − tWDF_setIncidentWave(r->child_left, -1.0f * incident_wave, input); | |
| 397 | −} | |
| 398 | − | |
| 399 | −static void set_incident_wave_for_series(tWDF* const wdf, float incident_wave, float input) | |
| 400 | −{ | |
| 401 | − _tWDF* r = *wdf; | |
| 402 | − | |
| 403 | − r->incident_wave_up = incident_wave; | |
| 404 | − float gamma_left = r->port_resistance_left * r->gamma_zero; | |
| 405 | − float gamma_right = r->port_resistance_right * r->gamma_zero; | |
| 406 | − float left_wave = tWDF_getReflectedWaveUp(r->child_left, input); | |
| 407 | − float right_wave = tWDF_getReflectedWaveUp(r->child_right, input); | |
| 408 | −// downPorts[0]->b = yl * ( downPorts[0]->a * ((1.0 / yl) - 1) - downPorts[1]->a - descendingWave ); | |
| 409 | −// downPorts[1]->b = yr * ( downPorts[1]->a * ((1.0 / yr) - 1) - downPorts[0]->a - descendingWave ); | |
| 410 | − tWDF_setIncidentWave(r->child_left, (-1.0f * gamma_left * incident_wave) + (gamma_right * left_wave) - (gamma_left * right_wave), input); | |
| 411 | − tWDF_setIncidentWave(r->child_right, (-1.0f * gamma_right * incident_wave) + (gamma_left * right_wave) - (gamma_right * left_wave), input); | |
| 412 | − // From rt-wdf | |
| 413 | −// tWDF_setIncidentWave(r->child_left, gamma_left * (left_wave * ((1.0f / gamma_left) - 1.0f) - right_wave - incident_wave)); | |
| 414 | −// tWDF_setIncidentWave(r->child_right, gamma_right * (right_wave * ((1.0f / gamma_right) - 1.0f) - left_wave - incident_wave)); | |
| 415 | − | |
| 416 | −} | |
| 417 | − | |
| 418 | −static void set_incident_wave_for_parallel(tWDF* const wdf, float incident_wave, float input) | |
| 419 | −{ | |
| 420 | − _tWDF* r = *wdf; | |
| 421 | − | |
| 422 | − r->incident_wave_up = incident_wave; | |
| 423 | − float gamma_left = r->port_conductance_left * r->gamma_zero; | |
| 424 | − float gamma_right = r->port_conductance_right * r->gamma_zero; | |
| 425 | − float left_wave = tWDF_getReflectedWaveUp(r->child_left, input); | |
| 426 | − float right_wave = tWDF_getReflectedWaveUp(r->child_right, input); | |
| 427 | −// downPorts[0]->b = ( ( dl - 1 ) * downPorts[0]->a + dr * downPorts[1]->a + du * descendingWave ); | |
| 428 | −// downPorts[1]->b = ( dl * downPorts[0]->a + ( dr - 1 ) * downPorts[1]->a + du * descendingWave ); | |
| 429 | − tWDF_setIncidentWave(r->child_left, (gamma_left - 1.0f) * left_wave + gamma_right * right_wave + incident_wave, input); | |
| 430 | − tWDF_setIncidentWave(r->child_right, gamma_left * left_wave + (gamma_right - 1.0f) * right_wave + incident_wave, input); | |
| 431 | −} | |
| 432 | − | |
| 433 | −//=================================================================== | |
| 434 | −//================ Get Reflected Waves ============================== | |
| 435 | − | |
| 436 | −static float get_reflected_wave_for_resistor(tWDF* const wdf, float input) | |
| 437 | −{ | |
| 438 | − _tWDF* r = *wdf; | |
| 439 | − r->reflected_wave_up = 0.0f; | |
| 440 | − return r->reflected_wave_up; | |
| 441 | −} | |
| 442 | − | |
| 443 | −static float get_reflected_wave_for_capacitor(tWDF* const wdf, float input) | |
| 444 | −{ | |
| 445 | − _tWDF* r = *wdf; | |
| 446 | − r->reflected_wave_up = r->incident_wave_up; | |
| 447 | − return r->reflected_wave_up; | |
| 448 | −} | |
| 449 | − | |
| 450 | −static float get_reflected_wave_for_resistive(tWDF* const wdf, float input) | |
| 451 | −{ | |
| 452 | − _tWDF* r = *wdf; | |
| 453 | − r->reflected_wave_up = input; | |
| 454 | − return r->reflected_wave_up; | |
| 455 | −} | |
| 456 | − | |
| 457 | −static float get_reflected_wave_for_inverter(tWDF* const wdf, float input) | |
| 458 | −{ | |
| 459 | − _tWDF* r = *wdf; | |
| 460 | − r->reflected_wave_up = -1.0f * tWDF_getReflectedWaveUp(r->child_left, input); | |
| 461 | − return r->reflected_wave_up; | |
| 462 | −} | |
| 463 | − | |
| 464 | −static float get_reflected_wave_for_series(tWDF* const wdf, float input) | |
| 465 | −{ | |
| 466 | − _tWDF* r = *wdf; | |
| 467 | − //-( downPorts[0]->a + downPorts[1]->a ); | |
| 468 | − r->reflected_wave_up = (-1.0f * (tWDF_getReflectedWaveUp(r->child_left, input) + tWDF_getReflectedWaveUp(r->child_right, input))); | |
| 469 | − return r->reflected_wave_up; | |
| 470 | −} | |
| 471 | − | |
| 472 | −static float get_reflected_wave_for_parallel(tWDF* const wdf, float input) | |
| 473 | −{ | |
| 474 | − _tWDF* r = *wdf; | |
| 475 | − | |
| 476 | − float gamma_left = r->port_conductance_left * r->gamma_zero; | |
| 477 | − float gamma_right = r->port_conductance_right * r->gamma_zero; | |
| 478 | − //return ( dl * downPorts[0]->a + dr * downPorts[1]->a ); | |
| 479 | − r->reflected_wave_up = (gamma_left * tWDF_getReflectedWaveUp(r->child_left, input) + gamma_right * tWDF_getReflectedWaveUp(r->child_right, input)); | |
| 480 | − return r->reflected_wave_up; | |
| 481 | −} | |
| 482 | − | |
| 483 | −static float get_reflected_wave_for_ideal(tWDF* const wdf, float input, float incident_wave) | |
| 484 | −{ | |
| 485 | − return (2.0f * input) - incident_wave; | |
| 486 | −} | |
| 487 | − | |
| 488 | −#define l2A 0.1640425613334452f | |
| 489 | −#define l2B -1.098865286222744f | |
| 490 | −#define l2Y 3.148297929334117f | |
| 491 | −#define l2K -2.213475204444817f | |
| 492 | −static float log2Approximation(float x) | |
| 493 | −{ | |
| 494 | − return (l2A * x*x*x) + (l2B * x*x) + (l2Y * x) + l2K; | |
| 495 | −} | |
| 496 | − | |
| 497 | −#define wX1 -3.684303659906469f | |
| 498 | −#define wX2 1.972967391708859f | |
| 499 | −#define wA 9.451797158780131e-3f | |
| 500 | −#define wB 0.1126446405111627f | |
| 501 | −#define wY 0.4451353886588814f | |
| 502 | −#define wK 0.5836596684310648f | |
| 503 | −static float wrightOmega3(float x) | |
| 504 | −{ | |
| 505 | − if (x <= wX1) | |
| 506 | − { | |
| 507 | − return 0; | |
| 508 | − } | |
| 509 | − else if (x < wX2) | |
| 510 | − { | |
| 511 | − return (wA * x*x*x) + (wB * x*x) + (wY * x) + wK; | |
| 512 | − } | |
| 513 | − else | |
| 514 | − { | |
| 515 | − return x - logf(x); | |
| 516 | − } | |
| 517 | −} | |
| 518 | − | |
| 519 | −static float wrightOmegaApproximation(float x) | |
| 520 | −{ | |
| 521 | − float w3 = wrightOmega3(x); | |
| 522 | − return w3 - ((w3 - expf(x - w3)) / (w3 + 1.0f)); | |
| 523 | −} | |
| 524 | − | |
| 525 | −static float lambertW(float a, float r, float I, float iVT) | |
| 526 | −{ | |
| 527 | − return wrightOmegaApproximation(((a + r*I) * iVT) + log((r * I) * iVT)); | |
| 528 | −} | |
| 529 | − | |
| 530 | −#define Is_DIODE 2.52e-9f | |
| 531 | −#define VT_DIODE 0.02585f | |
| 532 | −static float get_reflected_wave_for_diode(tWDF* const wdf, float input, float incident_wave) | |
| 533 | −{ | |
| 534 | − _tWDF* n = *wdf; | |
| 535 | − | |
| 536 | − float a = incident_wave; | |
| 537 | − float r = n->port_resistance_up; | |
| 538 | − return a + 2.0f*r*Is_DIODE - 2.0f*VT_DIODE*lambertW(a, r, Is_DIODE, 1.0f/VT_DIODE); | |
| 539 | −} | |
| 540 | − | |
| 541 | −static float get_reflected_wave_for_diode_pair(tWDF* const wdf, float input, float incident_wave) | |
| 542 | −{ | |
| 543 | − _tWDF* n = *wdf; | |
| 544 | − | |
| 545 | − float a = incident_wave; | |
| 546 | − float sgn = 0.0f; | |
| 547 | − if (a > 0.0f) sgn = 1.0f; | |
| 548 | − else if (a < 0.0f) sgn = -1.0f; | |
| 549 | − float r = n->port_resistance_up; | |
| 550 | − return a + 2 * sgn * (r*Is_DIODE - VT_DIODE*lambertW(sgn*a, r, Is_DIODE, 1.0f/VT_DIODE)); | |
| 551 | −} | |
| @@ -1,1612 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − ============================================================================== | |
| 3 | − | |
| 4 | − leaf-envelopes.c | |
| 5 | − Created: 20 Jan 2017 12:02:17pm | |
| 6 | − Author: Michael R Mulshine | |
| 7 | − | |
| 8 | − ============================================================================== | |
| 9 | −*/ | |
| 10 | − | |
| 11 | − | |
| 12 | −#if _WIN32 || _WIN64 | |
| 13 | − | |
| 14 | −#include "..\Inc\leaf-envelopes.h" | |
| 15 | −#include "..\Inc\leaf-tables.h" | |
| 16 | −#include "..\leaf.h" | |
| 17 | − | |
| 18 | −#else | |
| 19 | − | |
| 20 | −#include "../Inc/leaf-envelopes.h" | |
| 21 | −#include "../Inc/leaf-tables.h" | |
| 22 | −#include "../leaf.h" | |
| 23 | − | |
| 24 | −#endif | |
| 25 | − | |
| 26 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Envelope ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 27 | −void tEnvelope_init(tEnvelope* const envlp, float attack, float decay, int loop) | |
| 28 | −{ | |
| 29 | − _tEnvelope* env = *envlp = (_tEnvelope*) leaf_alloc(sizeof(_tEnvelope)); | |
| 30 | − | |
| 31 | − env->exp_buff = __leaf_table_exp_decay; | |
| 32 | − env->inc_buff = __leaf_table_attack_decay_inc; | |
| 33 | − env->buff_size = sizeof(__leaf_table_exp_decay); | |
| 34 | − | |
| 35 | − env->loop = loop; | |
| 36 | − | |
| 37 | − if (attack > 8192.0f) | |
| 38 | − attack = 8192.0f; | |
| 39 | − if (attack < 0.0f) | |
| 40 | − attack = 0.0f; | |
| 41 | − | |
| 42 | − if (decay > 8192.0f) | |
| 43 | − decay = 8192.0f; | |
| 44 | − if (decay < 0.0f) | |
| 45 | − decay = 0.0f; | |
| 46 | − | |
| 47 | − int16_t attackIndex = ((int16_t)(attack * 8.0f))-1; | |
| 48 | − int16_t decayIndex = ((int16_t)(decay * 8.0f))-1; | |
| 49 | − int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1; | |
| 50 | − | |
| 51 | − if (attackIndex < 0) | |
| 52 | − attackIndex = 0; | |
| 53 | − if (decayIndex < 0) | |
| 54 | − decayIndex = 0; | |
| 55 | − if (rampIndex < 0) | |
| 56 | − rampIndex = 0; | |
| 57 | − | |
| 58 | − env->inRamp = OFALSE; | |
| 59 | − env->inAttack = OFALSE; | |
| 60 | − env->inDecay = OFALSE; | |
| 61 | − | |
| 62 | − env->attackInc = env->inc_buff[attackIndex]; | |
| 63 | − env->decayInc = env->inc_buff[decayIndex]; | |
| 64 | − env->rampInc = env->inc_buff[rampIndex]; | |
| 65 | −} | |
| 66 | − | |
| 67 | −void tEnvelope_free(tEnvelope* const envlp) | |
| 68 | −{ | |
| 69 | − _tEnvelope* env = *envlp; | |
| 70 | − leaf_free((char*)env); | |
| 71 | −} | |
| 72 | − | |
| 73 | −void tEnvelope_initToPool (tEnvelope* const envlp, float attack, float decay, int loop, tMempool* const mp) | |
| 74 | −{ | |
| 75 | − _tMempool* m = *mp; | |
| 76 | − _tEnvelope* env = *envlp = (_tEnvelope*) mpool_alloc(sizeof(_tEnvelope), m); | |
| 77 | − | |
| 78 | − env->exp_buff = __leaf_table_exp_decay; | |
| 79 | − env->inc_buff = __leaf_table_attack_decay_inc; | |
| 80 | − env->buff_size = sizeof(__leaf_table_exp_decay); | |
| 81 | − | |
| 82 | − env->loop = loop; | |
| 83 | − | |
| 84 | − if (attack > 8192.0f) | |
| 85 | − attack = 8192.0f; | |
| 86 | − if (attack < 0.0f) | |
| 87 | − attack = 0.0f; | |
| 88 | − | |
| 89 | − if (decay > 8192.0f) | |
| 90 | − decay = 8192.0f; | |
| 91 | − if (decay < 0.0f) | |
| 92 | − decay = 0.0f; | |
| 93 | − | |
| 94 | − int16_t attackIndex = ((int16_t)(attack * 8.0f))-1; | |
| 95 | − int16_t decayIndex = ((int16_t)(decay * 8.0f))-1; | |
| 96 | − int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1; | |
| 97 | − | |
| 98 | − if (attackIndex < 0) | |
| 99 | − attackIndex = 0; | |
| 100 | − if (decayIndex < 0) | |
| 101 | − decayIndex = 0; | |
| 102 | − if (rampIndex < 0) | |
| 103 | − rampIndex = 0; | |
| 104 | − | |
| 105 | − env->inRamp = OFALSE; | |
| 106 | − env->inAttack = OFALSE; | |
| 107 | − env->inDecay = OFALSE; | |
| 108 | − | |
| 109 | − env->attackInc = env->inc_buff[attackIndex]; | |
| 110 | − env->decayInc = env->inc_buff[decayIndex]; | |
| 111 | − env->rampInc = env->inc_buff[rampIndex]; | |
| 112 | −} | |
| 113 | − | |
| 114 | −void tEnvelope_freeFromPool (tEnvelope* const envlp, tMempool* const mp) | |
| 115 | −{ | |
| 116 | − _tMempool* m = *mp; | |
| 117 | − _tEnvelope* env = *envlp; | |
| 118 | − mpool_free((char*)env, m); | |
| 119 | −} | |
| 120 | − | |
| 121 | −void tEnvelope_setAttack(tEnvelope* const envlp, float attack) | |
| 122 | −{ | |
| 123 | − _tEnvelope* env = *envlp; | |
| 124 | − | |
| 125 | − int32_t attackIndex; | |
| 126 | − | |
| 127 | − if (attack < 0.0f) { | |
| 128 | − attackIndex = 0.0f; | |
| 129 | − } else if (attack < 8192.0f) { | |
| 130 | − attackIndex = ((int32_t)(attack * 8.0f))-1; | |
| 131 | − } else { | |
| 132 | − attackIndex = ((int32_t)(8192.0f * 8.0f))-1; | |
| 133 | − } | |
| 134 | − | |
| 135 | − env->attackInc = env->inc_buff[attackIndex]; | |
| 136 | −} | |
| 137 | − | |
| 138 | −void tEnvelope_setDecay(tEnvelope* const envlp, float decay) | |
| 139 | −{ | |
| 140 | − _tEnvelope* env = *envlp; | |
| 141 | − | |
| 142 | − int32_t decayIndex; | |
| 143 | − | |
| 144 | − if (decay < 0.0f) { | |
| 145 | − decayIndex = 0; | |
| 146 | − } else if (decay < 8192.0f) { | |
| 147 | − decayIndex = ((int32_t)(decay * 8.0f)) - 1; | |
| 148 | − } else { | |
| 149 | − decayIndex = ((int32_t)(8192.0f * 8.0f)) - 1; | |
| 150 | − } | |
| 151 | − | |
| 152 | − env->decayInc = env->inc_buff[decayIndex]; | |
| 153 | −} | |
| 154 | − | |
| 155 | −void tEnvelope_loop(tEnvelope* const envlp, int loop) | |
| 156 | −{ | |
| 157 | − _tEnvelope* env = *envlp; | |
| 158 | − env->loop = loop; | |
| 159 | −} | |
| 160 | − | |
| 161 | − | |
| 162 | −void tEnvelope_on(tEnvelope* const envlp, float velocity) | |
| 163 | −{ | |
| 164 | − _tEnvelope* env = *envlp; | |
| 165 | − | |
| 166 | − if (env->inAttack || env->inDecay) // In case envelope retriggered while it is still happening. | |
| 167 | − { | |
| 168 | − env->rampPhase = 0; | |
| 169 | − env->inRamp = OTRUE; | |
| 170 | − env->rampPeak = env->next; | |
| 171 | − } | |
| 172 | − else // Normal start. | |
| 173 | − { | |
| 174 | − env->inAttack = OTRUE; | |
| 175 | − } | |
| 176 | − | |
| 177 | − | |
| 178 | − env->attackPhase = 0; | |
| 179 | − env->decayPhase = 0; | |
| 180 | − env->inDecay = OFALSE; | |
| 181 | − env->gain = velocity; | |
| 182 | −} | |
| 183 | − | |
| 184 | −float tEnvelope_tick(tEnvelope* const envlp) | |
| 185 | −{ | |
| 186 | − _tEnvelope* env = *envlp; | |
| 187 | − | |
| 188 | − if (env->inRamp) | |
| 189 | − { | |
| 190 | − if (env->rampPhase > UINT16_MAX) | |
| 191 | − { | |
| 192 | − env->inRamp = OFALSE; | |
| 193 | − env->inAttack = OTRUE; | |
| 194 | − env->next = 0.0f; | |
| 195 | − } | |
| 196 | − else | |
| 197 | − { | |
| 198 | − env->next = env->rampPeak * env->exp_buff[(uint32_t)env->rampPhase]; | |
| 199 | − } | |
| 200 | − | |
| 201 | − env->rampPhase += env->rampInc; | |
| 202 | − } | |
| 203 | − | |
| 204 | − if (env->inAttack) | |
| 205 | − { | |
| 206 | − | |
| 207 | − // If attack done, time to turn around. | |
| 208 | − if (env->attackPhase > UINT16_MAX) | |
| 209 | − { | |
| 210 | − env->inDecay = OTRUE; | |
| 211 | − env->inAttack = OFALSE; | |
| 212 | − env->next = env->gain * 1.0f; | |
| 213 | − } | |
| 214 | − else | |
| 215 | − { | |
| 216 | − // do interpolation ! | |
| 217 | − env->next = env->gain * env->exp_buff[UINT16_MAX - (uint32_t)env->attackPhase]; // inverted and backwards to get proper rising exponential shape/perception | |
| 218 | − } | |
| 219 | − | |
| 220 | − // Increment envelope attack. | |
| 221 | − env->attackPhase += env->attackInc; | |
| 222 | − | |
| 223 | − } | |
| 224 | − | |
| 225 | − if (env->inDecay) | |
| 226 | − { | |
| 227 | − | |
| 228 | − // If decay done, finish. | |
| 229 | − if (env->decayPhase >= UINT16_MAX) | |
| 230 | − { | |
| 231 | − env->inDecay = OFALSE; | |
| 232 | − | |
| 233 | − if (env->loop) | |
| 234 | − { | |
| 235 | − env->attackPhase = 0; | |
| 236 | − env->decayPhase = 0; | |
| 237 | − env->inAttack = OTRUE; | |
| 238 | − } | |
| 239 | − else | |
| 240 | − { | |
| 241 | − env->next = 0.0f; | |
| 242 | − } | |
| 243 | − | |
| 244 | − } else { | |
| 245 | − | |
| 246 | − env->next = env->gain * (env->exp_buff[(uint32_t)env->decayPhase]); // do interpolation ! | |
| 247 | − } | |
| 248 | − | |
| 249 | − // Increment envelope decay; | |
| 250 | − env->decayPhase += env->decayInc; | |
| 251 | − } | |
| 252 | − | |
| 253 | − return env->next; | |
| 254 | −} | |
| 255 | − | |
| 256 | − | |
| 257 | − | |
| 258 | −/* ADSR */ | |
| 259 | −void tADSR_init(tADSR* const adsrenv, float attack, float decay, float sustain, float release) | |
| 260 | −{ | |
| 261 | − tADSR_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool); | |
| 262 | −} | |
| 263 | − | |
| 264 | −void tADSR_free(tADSR* const adsrenv) | |
| 265 | −{ | |
| 266 | − tADSR_freeFromPool(adsrenv, &leaf.mempool); | |
| 267 | −} | |
| 268 | − | |
| 269 | −void tADSR_initToPool (tADSR* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp) | |
| 270 | −{ | |
| 271 | − _tMempool* m = *mp; | |
| 272 | − _tADSR* adsr = *adsrenv = (_tADSR*) mpool_alloc(sizeof(_tADSR), m); | |
| 273 | − | |
| 274 | − adsr->exp_buff = __leaf_table_exp_decay; | |
| 275 | − adsr->inc_buff = __leaf_table_attack_decay_inc; | |
| 276 | − adsr->buff_size = sizeof(__leaf_table_exp_decay); | |
| 277 | − | |
| 278 | − if (attack > 8192.0f) | |
| 279 | − attack = 8192.0f; | |
| 280 | − if (attack < 0.0f) | |
| 281 | − attack = 0.0f; | |
| 282 | − | |
| 283 | − if (decay > 8192.0f) | |
| 284 | − decay = 8192.0f; | |
| 285 | − if (decay < 0.0f) | |
| 286 | − decay = 0.0f; | |
| 287 | − | |
| 288 | − if (sustain > 1.0f) | |
| 289 | − sustain = 1.0f; | |
| 290 | − if (sustain < 0.0f) | |
| 291 | − sustain = 0.0f; | |
| 292 | − | |
| 293 | − if (release > 8192.0f) | |
| 294 | − release = 8192.0f; | |
| 295 | − if (release < 0.0f) | |
| 296 | − release = 0.0f; | |
| 297 | − | |
| 298 | − int16_t attackIndex = ((int16_t)(attack * 8.0f))-1; | |
| 299 | − int16_t decayIndex = ((int16_t)(decay * 8.0f))-1; | |
| 300 | − int16_t releaseIndex = ((int16_t)(release * 8.0f))-1; | |
| 301 | − int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1; | |
| 302 | − | |
| 303 | − if (attackIndex < 0) | |
| 304 | − attackIndex = 0; | |
| 305 | − if (decayIndex < 0) | |
| 306 | − decayIndex = 0; | |
| 307 | − if (releaseIndex < 0) | |
| 308 | − releaseIndex = 0; | |
| 309 | − if (rampIndex < 0) | |
| 310 | − rampIndex = 0; | |
| 311 | − | |
| 312 | − adsr->next = 0.0f; | |
| 313 | − | |
| 314 | − adsr->inRamp = OFALSE; | |
| 315 | − adsr->inAttack = OFALSE; | |
| 316 | − adsr->inDecay = OFALSE; | |
| 317 | − adsr->inSustain = OFALSE; | |
| 318 | − adsr->inRelease = OFALSE; | |
| 319 | − | |
| 320 | − adsr->sustain = sustain; | |
| 321 | − | |
| 322 | − adsr->attackInc = adsr->inc_buff[attackIndex]; | |
| 323 | − adsr->decayInc = adsr->inc_buff[decayIndex]; | |
| 324 | − adsr->releaseInc = adsr->inc_buff[releaseIndex]; | |
| 325 | − adsr->rampInc = adsr->inc_buff[rampIndex]; | |
| 326 | − | |
| 327 | − adsr->leakFactor = 1.0f; | |
| 328 | −} | |
| 329 | − | |
| 330 | −void tADSR_freeFromPool (tADSR* const adsrenv, tMempool* const mp) | |
| 331 | −{ | |
| 332 | − _tMempool* m = *mp; | |
| 333 | − _tADSR* adsr = *adsrenv; | |
| 334 | − mpool_free((char*)adsr, m); | |
| 335 | −} | |
| 336 | − | |
| 337 | −void tADSR_setAttack(tADSR* const adsrenv, float attack) | |
| 338 | −{ | |
| 339 | − _tADSR* adsr = *adsrenv; | |
| 340 | − | |
| 341 | − int32_t attackIndex; | |
| 342 | − | |
| 343 | − if (attack < 0.0f) { | |
| 344 | − attackIndex = 0.0f; | |
| 345 | − } else if (attack < 8192.0f) { | |
| 346 | − attackIndex = ((int32_t)(attack * 8.0f))-1; | |
| 347 | − } else { | |
| 348 | − attackIndex = ((int32_t)(8192.0f * 8.0f))-1; | |
| 349 | − } | |
| 350 | − | |
| 351 | − adsr->attackInc = adsr->inc_buff[attackIndex]; | |
| 352 | −} | |
| 353 | − | |
| 354 | −void tADSR_setDecay(tADSR* const adsrenv, float decay) | |
| 355 | −{ | |
| 356 | − _tADSR* adsr = *adsrenv; | |
| 357 | − | |
| 358 | − int32_t decayIndex; | |
| 359 | − | |
| 360 | − if (decay < 0.0f) { | |
| 361 | − decayIndex = 0.0f; | |
| 362 | − } else if (decay < 8192.0f) { | |
| 363 | − decayIndex = ((int32_t)(decay * 8.0f)) - 1; | |
| 364 | − } else { | |
| 365 | − decayIndex = ((int32_t)(8192.0f * 8.0f)) - 1; | |
| 366 | − } | |
| 367 | − | |
| 368 | − adsr->decayInc = adsr->inc_buff[decayIndex]; | |
| 369 | −} | |
| 370 | − | |
| 371 | −void tADSR_setSustain(tADSR* const adsrenv, float sustain) | |
| 372 | −{ | |
| 373 | − _tADSR* adsr = *adsrenv; | |
| 374 | − | |
| 375 | − if (sustain > 1.0f) adsr->sustain = 1.0f; | |
| 376 | − else if (sustain < 0.0f) adsr->sustain = 0.0f; | |
| 377 | − else adsr->sustain = sustain; | |
| 378 | −} | |
| 379 | − | |
| 380 | −void tADSR_setRelease(tADSR* const adsrenv, float release) | |
| 381 | −{ | |
| 382 | − _tADSR* adsr = *adsrenv; | |
| 383 | − | |
| 384 | − int32_t releaseIndex; | |
| 385 | − | |
| 386 | − if (release < 0.0f) { | |
| 387 | − releaseIndex = 0.0f; | |
| 388 | − } else if (release < 8192.0f) { | |
| 389 | − releaseIndex = ((int32_t)(release * 8.0f)) - 1; | |
| 390 | − } else { | |
| 391 | − releaseIndex = ((int32_t)(8192.0f * 8.0f)) - 1; | |
| 392 | − } | |
| 393 | − | |
| 394 | − adsr->releaseInc = adsr->inc_buff[releaseIndex]; | |
| 395 | −} | |
| 396 | − | |
| 397 | −// 0.999999 is slow leak, 0.9 is fast leak | |
| 398 | −void tADSR_setLeakFactor(tADSR* const adsrenv, float leakFactor) | |
| 399 | −{ | |
| 400 | − _tADSR* adsr = *adsrenv; | |
| 401 | − | |
| 402 | − | |
| 403 | − adsr->leakFactor = leakFactor; | |
| 404 | −} | |
| 405 | − | |
| 406 | −void tADSR_on(tADSR* const adsrenv, float velocity) | |
| 407 | −{ | |
| 408 | − _tADSR* adsr = *adsrenv; | |
| 409 | − | |
| 410 | − if ((adsr->inAttack || adsr->inDecay) || (adsr->inSustain || adsr->inRelease)) // In case ADSR retriggered while it is still happening. | |
| 411 | − { | |
| 412 | − adsr->rampPhase = 0; | |
| 413 | − adsr->inRamp = OTRUE; | |
| 414 | − adsr->rampPeak = adsr->next; | |
| 415 | − } | |
| 416 | − else // Normal start. | |
| 417 | − { | |
| 418 | − adsr->inAttack = OTRUE; | |
| 419 | − } | |
| 420 | − | |
| 421 | − adsr->attackPhase = 0; | |
| 422 | − adsr->decayPhase = 0; | |
| 423 | − adsr->releasePhase = 0; | |
| 424 | − adsr->inDecay = OFALSE; | |
| 425 | − adsr->inSustain = OFALSE; | |
| 426 | − adsr->inRelease = OFALSE; | |
| 427 | − adsr->gain = velocity; | |
| 428 | −} | |
| 429 | − | |
| 430 | −void tADSR_off(tADSR* const adsrenv) | |
| 431 | −{ | |
| 432 | − _tADSR* adsr = *adsrenv; | |
| 433 | − | |
| 434 | − if (adsr->inRelease) return; | |
| 435 | − | |
| 436 | − adsr->inAttack = OFALSE; | |
| 437 | − adsr->inDecay = OFALSE; | |
| 438 | − adsr->inSustain = OFALSE; | |
| 439 | − adsr->inRelease = OTRUE; | |
| 440 | − | |
| 441 | − adsr->releasePeak = adsr->next; | |
| 442 | −} | |
| 443 | − | |
| 444 | −float tADSR_tick(tADSR* const adsrenv) | |
| 445 | −{ | |
| 446 | − _tADSR* adsr = *adsrenv; | |
| 447 | − | |
| 448 | − | |
| 449 | − if (adsr->inRamp) | |
| 450 | − { | |
| 451 | − if (adsr->rampPhase > UINT16_MAX) | |
| 452 | − { | |
| 453 | − adsr->inRamp = OFALSE; | |
| 454 | − adsr->inAttack = OTRUE; | |
| 455 | − adsr->next = 0.0f; | |
| 456 | − } | |
| 457 | − else | |
| 458 | − { | |
| 459 | − adsr->next = adsr->rampPeak * adsr->exp_buff[(uint32_t)adsr->rampPhase]; | |
| 460 | − } | |
| 461 | − | |
| 462 | − adsr->rampPhase += adsr->rampInc; | |
| 463 | − } | |
| 464 | − | |
| 465 | − if (adsr->inAttack) | |
| 466 | − { | |
| 467 | − | |
| 468 | − // If attack done, time to turn around. | |
| 469 | − if (adsr->attackPhase > UINT16_MAX) | |
| 470 | − { | |
| 471 | − adsr->inDecay = OTRUE; | |
| 472 | − adsr->inAttack = OFALSE; | |
| 473 | − adsr->next = adsr->gain * 1.0f; | |
| 474 | − } | |
| 475 | − else | |
| 476 | − { | |
| 477 | − // do interpolation ! | |
| 478 | − adsr->next = adsr->gain * adsr->exp_buff[UINT16_MAX - (uint32_t)adsr->attackPhase]; // inverted and backwards to get proper rising exponential shape/perception | |
| 479 | − } | |
| 480 | − | |
| 481 | − // Increment ADSR attack. | |
| 482 | − adsr->attackPhase += adsr->attackInc; | |
| 483 | − | |
| 484 | − } | |
| 485 | − | |
| 486 | − if (adsr->inDecay) | |
| 487 | − { | |
| 488 | − | |
| 489 | − // If decay done, sustain. | |
| 490 | − if (adsr->decayPhase >= UINT16_MAX) | |
| 491 | − { | |
| 492 | − adsr->inDecay = OFALSE; | |
| 493 | − adsr->inSustain = OTRUE; | |
| 494 | − adsr->next = adsr->gain * adsr->sustain; | |
| 495 | − } | |
| 496 | − | |
| 497 | − else | |
| 498 | − { | |
| 499 | − adsr->next = (adsr->gain * (adsr->sustain + ((adsr->exp_buff[(uint32_t)adsr->decayPhase]) * (1.0f - adsr->sustain)))) * adsr->leakFactor; // do interpolation ! | |
| 500 | − } | |
| 501 | − | |
| 502 | − // Increment ADSR decay. | |
| 503 | − adsr->decayPhase += adsr->decayInc; | |
| 504 | − } | |
| 505 | − | |
| 506 | − if (adsr->inSustain) | |
| 507 | − { | |
| 508 | − adsr->next = adsr->next * adsr->leakFactor; | |
| 509 | − } | |
| 510 | − | |
| 511 | − if (adsr->inRelease) | |
| 512 | − { | |
| 513 | − // If release done, finish. | |
| 514 | − if (adsr->releasePhase >= UINT16_MAX) | |
| 515 | − { | |
| 516 | − adsr->inRelease = OFALSE; | |
| 517 | − adsr->next = 0.0f; | |
| 518 | − } | |
| 519 | − else { | |
| 520 | − | |
| 521 | − adsr->next = adsr->releasePeak * (adsr->exp_buff[(uint32_t)adsr->releasePhase]); // do interpolation ! | |
| 522 | − } | |
| 523 | − | |
| 524 | − // Increment envelope release; | |
| 525 | − adsr->releasePhase += adsr->releaseInc; | |
| 526 | − } | |
| 527 | − | |
| 528 | − | |
| 529 | − return adsr->next; | |
| 530 | −} | |
| 531 | − | |
| 532 | − | |
| 533 | − | |
| 534 | − | |
| 535 | −/* ADSR 2*/ | |
| 536 | −//This one is adapted from the VCV Rack code | |
| 537 | −//-JS | |
| 538 | − | |
| 539 | − | |
| 540 | − | |
| 541 | −const float ADSR2_MIN_TIME = 1e-3f; | |
| 542 | −const float ADSR2_INV_MIN_TIME = 1000.0f; | |
| 543 | −const float ADSR2_MAX_TIME = 10.f; | |
| 544 | −const float ADSR2_LAMBDA_BASE = 10000.0f; | |
| 545 | − | |
| 546 | − | |
| 547 | −void tADSR2_init(tADSR2* const adsrenv, float attack, float decay, float sustain, float release) | |
| 548 | −{ | |
| 549 | − tADSR2_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool); | |
| 550 | −} | |
| 551 | − | |
| 552 | −void tADSR2_free(tADSR2* const adsrenv) | |
| 553 | −{ | |
| 554 | − tADSR2_freeFromPool(adsrenv, &leaf.mempool); | |
| 555 | −} | |
| 556 | − | |
| 557 | −void tADSR2_initToPool (tADSR2* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp) | |
| 558 | −{ | |
| 559 | − _tMempool* m = *mp; | |
| 560 | − _tADSR2* adsr = *adsrenv = (_tADSR2*) mpool_alloc(sizeof(_tADSR2), m); | |
| 561 | − adsr->sampleRateInMs = leaf.sampleRate * 0.001f; | |
| 562 | − adsr->attack = LEAF_clip(0.0f, attack * 0.001f, 1.0f); | |
| 563 | − adsr->attackLambda = powf(ADSR2_LAMBDA_BASE, -adsr->attack) * ADSR2_INV_MIN_TIME; | |
| 564 | − | |
| 565 | − | |
| 566 | − adsr->decay = LEAF_clip(0.0f, decay * 0.001f, 1.0f); | |
| 567 | − adsr->decayLambda = powf(ADSR2_LAMBDA_BASE, -adsr->decay) * ADSR2_INV_MIN_TIME; | |
| 568 | − | |
| 569 | − | |
| 570 | − adsr->sustain= sustain; | |
| 571 | − | |
| 572 | − | |
| 573 | − adsr->release = LEAF_clip(0.0f, release * 0.001f, 1.0f); | |
| 574 | − adsr->releaseLambda = powf(ADSR2_LAMBDA_BASE, -adsr->release) * ADSR2_INV_MIN_TIME; | |
| 575 | − | |
| 576 | − adsr->attacking = 0; | |
| 577 | − adsr->gate = 0; | |
| 578 | − adsr->gain = 1.0f; | |
| 579 | − adsr->targetGainSquared = 1.0f; | |
| 580 | − adsr->factor = 0.01f; | |
| 581 | − adsr->oneMinusFactor = 0.99f; | |
| 582 | − adsr->env = 0.0f; | |
| 583 | − adsr->leakFactor = 1.0f; | |
| 584 | −} | |
| 585 | − | |
| 586 | −void tADSR2_freeFromPool (tADSR2* const adsrenv, tMempool* const mp) | |
| 587 | −{ | |
| 588 | − _tMempool* m = *mp; | |
| 589 | − _tADSR2* adsr = *adsrenv; | |
| 590 | − mpool_free((char*)adsr, m); | |
| 591 | −} | |
| 592 | − | |
| 593 | −void tADSR2_setAttack(tADSR2* const adsrenv, float attack) | |
| 594 | −{ | |
| 595 | − _tADSR2* adsr = *adsrenv; | |
| 596 | − adsr->attack = LEAF_clip(0.0f, attack * 0.001f, 1.0f); | |
| 597 | − adsr->attackLambda = fastPow(ADSR2_LAMBDA_BASE, -adsr->attack) * ADSR2_INV_MIN_TIME; | |
| 598 | − | |
| 599 | −} | |
| 600 | − | |
| 601 | −void tADSR2_setDecay(tADSR2* const adsrenv, float decay) | |
| 602 | −{ | |
| 603 | − _tADSR2* adsr = *adsrenv; | |
| 604 | − adsr->decay = LEAF_clip(0.0f, decay * 0.001f, 1.0f); | |
| 605 | − adsr->decayLambda = fastPow(ADSR2_LAMBDA_BASE, -adsr->decay) * ADSR2_INV_MIN_TIME; | |
| 606 | − | |
| 607 | −} | |
| 608 | − | |
| 609 | −void tADSR2_setSustain(tADSR2* const adsrenv, float sustain) | |
| 610 | −{ | |
| 611 | − _tADSR2* adsr = *adsrenv; | |
| 612 | − adsr->sustain = sustain; | |
| 613 | − | |
| 614 | − if (adsr->gate) | |
| 615 | − { | |
| 616 | − if (adsr->attacking == 0) | |
| 617 | − { | |
| 618 | − adsr->envTarget = sustain; | |
| 619 | − } | |
| 620 | − } | |
| 621 | −} | |
| 622 | − | |
| 623 | −void tADSR2_setRelease(tADSR2* const adsrenv, float release) | |
| 624 | −{ | |
| 625 | − _tADSR2* adsr = *adsrenv; | |
| 626 | − adsr->release = LEAF_clip(0.0f, release * 0.001f, 1.0f); | |
| 627 | − adsr->releaseLambda = fastPow(ADSR2_LAMBDA_BASE, -adsr->release) * ADSR2_INV_MIN_TIME; | |
| 628 | −} | |
| 629 | − | |
| 630 | −// 0.999999 is slow leak, 0.9 is fast leak | |
| 631 | −void tADSR2_setLeakFactor(tADSR2* const adsrenv, float leakFactor) | |
| 632 | −{ | |
| 633 | − _tADSR2* adsr = *adsrenv; | |
| 634 | − | |
| 635 | − adsr->leakFactor = leakFactor; | |
| 636 | −} | |
| 637 | − | |
| 638 | −void tADSR2_on(tADSR2* const adsrenv, float velocity) | |
| 639 | −{ | |
| 640 | − _tADSR2* adsr = *adsrenv; | |
| 641 | − adsr->targetGainSquared = velocity * velocity; | |
| 642 | − adsr->envTarget = 1.2f; | |
| 643 | − adsr->leakGain = 1.0f; | |
| 644 | − adsr->gate = 1; | |
| 645 | − adsr->attacking = 1; | |
| 646 | −} | |
| 647 | − | |
| 648 | −void tADSR2_off(tADSR2* const adsrenv) | |
| 649 | −{ | |
| 650 | − _tADSR2* adsr = *adsrenv; | |
| 651 | − adsr->gate = 0; | |
| 652 | − adsr->envTarget = 0.0f; | |
| 653 | −} | |
| 654 | − | |
| 655 | −float tADSR2_tick(tADSR2* const adsrenv) | |
| 656 | −{ | |
| 657 | − _tADSR2* adsr = *adsrenv; | |
| 658 | − float lambda; | |
| 659 | − | |
| 660 | − if (adsr->gate) | |
| 661 | − { | |
| 662 | − if (adsr->attacking) | |
| 663 | − { | |
| 664 | − lambda = adsr->attackLambda; | |
| 665 | − } | |
| 666 | − else | |
| 667 | − { | |
| 668 | − lambda = adsr->decayLambda; | |
| 669 | − } | |
| 670 | − } | |
| 671 | − else | |
| 672 | − { | |
| 673 | − lambda = adsr->releaseLambda; | |
| 674 | − } | |
| 675 | − | |
| 676 | − | |
| 677 | − // Adjust env | |
| 678 | − adsr->env += (adsr->envTarget - adsr->env) * lambda * leaf.invSampleRate; | |
| 679 | − | |
| 680 | − // Turn off attacking state if envelope is HIGH | |
| 681 | − if (adsr->env >= 1.0f) | |
| 682 | − { | |
| 683 | − adsr->attacking = 0; | |
| 684 | − adsr->envTarget = adsr->sustain; | |
| 685 | − } | |
| 686 | − | |
| 687 | − //smooth the gain value -- this is not ideal, a retrigger while the envelope is still going with a new gain will cause a jump, although it will be smoothed quickly. Maybe doing the math so the range is computed based on the gain rather than 0.->1. is preferable? But that's harder to get the exponential curve right without a lookup. | |
| 688 | − adsr->gain = ((adsr->factor*adsr->targetGainSquared)+(adsr->oneMinusFactor*adsr->gain)); | |
| 689 | − adsr->leakGain *= adsr->leakFactor; | |
| 690 | − return adsr->env * adsr->gain * adsr->leakGain; | |
| 691 | −} | |
| 692 | − | |
| 693 | −/* ADSR 3*/ | |
| 694 | −//This one doesn't use any lookup table - by Nigel Redmon from his blog. Thanks, Nigel! | |
| 695 | −//-JS | |
| 696 | − | |
| 697 | −float calcADSR3Coef(double rate, double targetRatio) | |
| 698 | −{ | |
| 699 | − return (rate <= 0.0f) ? 0.0f : exp(-log((1.0 + targetRatio) / targetRatio) / rate); | |
| 700 | −} | |
| 701 | − | |
| 702 | − | |
| 703 | −void tADSR3_init(tADSR3* const adsrenv, float attack, float decay, float sustain, float release) | |
| 704 | −{ | |
| 705 | − tADSR3_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool); | |
| 706 | −} | |
| 707 | − | |
| 708 | −void tADSR3_free(tADSR3* const adsrenv) | |
| 709 | −{ | |
| 710 | − tADSR3_freeFromPool(adsrenv, &leaf.mempool); | |
| 711 | −} | |
| 712 | − | |
| 713 | −void tADSR3_initToPool (tADSR3* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp) | |
| 714 | −{ | |
| 715 | − _tMempool* m = *mp; | |
| 716 | − _tADSR3* adsr = *adsrenv = (_tADSR3*) mpool_alloc(sizeof(_tADSR3), m); | |
| 717 | − adsr->sampleRateInMs = leaf.sampleRate * 0.001f; | |
| 718 | − adsr->targetRatioA = 0.3f; | |
| 719 | − adsr->targetRatioDR = 0.0001f; | |
| 720 | − adsr->attackRate = attack * adsr->sampleRateInMs; | |
| 721 | − adsr->attackCoef = calcADSR3Coef(attack * adsr->sampleRateInMs, adsr->targetRatioA); | |
| 722 | − adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef); | |
| 723 | − | |
| 724 | − adsr->decayRate = decay * adsr->sampleRateInMs; | |
| 725 | − adsr->decayCoef = calcADSR3Coef(decay * adsr->sampleRateInMs,adsr-> targetRatioDR); | |
| 726 | − adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef); | |
| 727 | − | |
| 728 | − adsr->sustainLevel = sustain; | |
| 729 | − adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef); | |
| 730 | − | |
| 731 | − adsr->releaseRate = release * adsr->sampleRateInMs; | |
| 732 | − adsr->releaseCoef = calcADSR3Coef(release * adsr->sampleRateInMs, adsr->targetRatioDR); | |
| 733 | − adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef); | |
| 734 | − | |
| 735 | − adsr->state = env_idle; | |
| 736 | − adsr->gain = 1.0f; | |
| 737 | − adsr->targetGainSquared = 1.0f; | |
| 738 | − adsr->factor = 0.01f; | |
| 739 | − adsr->oneMinusFactor = 0.99f; | |
| 740 | − adsr->output = 0.0f; | |
| 741 | − adsr->leakFactor = 1.0f; | |
| 742 | −} | |
| 743 | − | |
| 744 | −void tADSR3_freeFromPool (tADSR3* const adsrenv, tMempool* const mp) | |
| 745 | −{ | |
| 746 | − _tMempool* m = *mp; | |
| 747 | − _tADSR3* adsr = *adsrenv; | |
| 748 | − mpool_free((char*)adsr, m); | |
| 749 | −} | |
| 750 | − | |
| 751 | −void tADSR3_setAttack(tADSR3* const adsrenv, float attack) | |
| 752 | −{ | |
| 753 | − _tADSR3* adsr = *adsrenv; | |
| 754 | − | |
| 755 | − adsr->attackRate = attack * adsr->sampleRateInMs; | |
| 756 | − adsr->attackCoef = calcADSR3Coef(adsr->attackRate, adsr->targetRatioA); | |
| 757 | − adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef); | |
| 758 | −} | |
| 759 | − | |
| 760 | −void tADSR3_setDecay(tADSR3* const adsrenv, float decay) | |
| 761 | −{ | |
| 762 | − _tADSR3* adsr = *adsrenv; | |
| 763 | − | |
| 764 | − adsr->decayRate = decay * adsr->sampleRateInMs; | |
| 765 | − adsr->decayCoef = calcADSR3Coef(adsr->decayRate,adsr-> targetRatioDR); | |
| 766 | − adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef); | |
| 767 | −} | |
| 768 | − | |
| 769 | −void tADSR3_setSustain(tADSR3* const adsrenv, float sustain) | |
| 770 | −{ | |
| 771 | − _tADSR3* adsr = *adsrenv; | |
| 772 | − | |
| 773 | − adsr->sustainLevel = sustain; | |
| 774 | − adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef); | |
| 775 | −} | |
| 776 | − | |
| 777 | −void tADSR3_setRelease(tADSR3* const adsrenv, float release) | |
| 778 | −{ | |
| 779 | − _tADSR3* adsr = *adsrenv; | |
| 780 | − | |
| 781 | − adsr->releaseRate = release * adsr->sampleRateInMs; | |
| 782 | − adsr->releaseCoef = calcADSR3Coef(adsr->releaseRate, adsr->targetRatioDR); | |
| 783 | − adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef); | |
| 784 | −} | |
| 785 | − | |
| 786 | −// 0.999999 is slow leak, 0.9 is fast leak | |
| 787 | −void tADSR3_setLeakFactor(tADSR3* const adsrenv, float leakFactor) | |
| 788 | −{ | |
| 789 | − _tADSR3* adsr = *adsrenv; | |
| 790 | − | |
| 791 | − adsr->leakFactor = leakFactor; | |
| 792 | −} | |
| 793 | − | |
| 794 | −void tADSR3_on(tADSR3* const adsrenv, float velocity) | |
| 795 | −{ | |
| 796 | − _tADSR3* adsr = *adsrenv; | |
| 797 | − adsr->state = env_attack; | |
| 798 | − adsr->targetGainSquared = velocity * velocity; | |
| 799 | −} | |
| 800 | − | |
| 801 | −void tADSR3_off(tADSR3* const adsrenv) | |
| 802 | −{ | |
| 803 | − _tADSR3* adsr = *adsrenv; | |
| 804 | − | |
| 805 | − if (adsr->state != env_idle) | |
| 806 | − { | |
| 807 | − adsr->state = env_release; | |
| 808 | − } | |
| 809 | −} | |
| 810 | − | |
| 811 | −float tADSR3_tick(tADSR3* const adsrenv) | |
| 812 | −{ | |
| 813 | − _tADSR3* adsr = *adsrenv; | |
| 814 | − | |
| 815 | − | |
| 816 | − switch (adsr->state) { | |
| 817 | − case env_idle: | |
| 818 | − break; | |
| 819 | − case env_attack: | |
| 820 | − adsr->output = adsr->attackBase + adsr->output * adsr->attackCoef; | |
| 821 | − if (adsr->output >= 1.0f) { | |
| 822 | − adsr->output = 1.0f; | |
| 823 | − adsr->state = env_decay; | |
| 824 | − } | |
| 825 | − break; | |
| 826 | − case env_decay: | |
| 827 | − adsr->output = adsr->decayBase + adsr->output * adsr->decayCoef * adsr->leakFactor; | |
| 828 | − if (adsr->output <= adsr->sustainLevel) { | |
| 829 | − adsr->output = adsr->sustainLevel; | |
| 830 | − adsr->state = env_sustain; | |
| 831 | − } | |
| 832 | − break; | |
| 833 | − case env_sustain: | |
| 834 | − adsr->output = adsr->output * adsr->leakFactor; | |
| 835 | − break; | |
| 836 | − case env_release: | |
| 837 | − adsr->output = adsr->releaseBase + adsr->output * adsr->releaseCoef; | |
| 838 | − if (adsr->output <= 0.0f) { | |
| 839 | − adsr->output = 0.0f; | |
| 840 | − adsr->state = env_idle; | |
| 841 | − } | |
| 842 | − } | |
| 843 | − //smooth the gain value -- this is not ideal, a retrigger while the envelope is still going with a new gain will cause a jump, although it will be smoothed quickly. Maybe doing the math so the range is computed based on the gain rather than 0.->1. is preferable? But that's harder to get the exponential curve right without a lookup. | |
| 844 | − adsr->gain = (adsr->factor*adsr->targetGainSquared)+(adsr->oneMinusFactor*adsr->gain); | |
| 845 | − return adsr->output * adsr->gain; | |
| 846 | −} | |
| 847 | − | |
| 848 | − | |
| 849 | −/* ADSR 4 */ // new version of our original table-based ADSR but with the table passed in by the user | |
| 850 | −// use this if the size of the big ADSR tables is too much. | |
| 851 | −void tADSR4_init (tADSR4* const adsrenv, float attack, float decay, float sustain, float release, float* expBuffer, int bufferSize) | |
| 852 | −{ | |
| 853 | − tADSR4_initToPool (adsrenv, attack, decay, sustain, release, expBuffer, bufferSize, &leaf.mempool); | |
| 854 | −} | |
| 855 | − | |
| 856 | −void tADSR4_free(tADSR4* const adsrenv) | |
| 857 | −{ | |
| 858 | − tADSR4_freeFromPool(adsrenv, &leaf.mempool); | |
| 859 | −} | |
| 860 | − | |
| 861 | −//initialize with an exponential function that decays -- i.e. a call to LEAF_generate_exp(expBuffer, 0.001f, 0.0f, 1.0f, -0.0008f, EXP_BUFFER_SIZE); | |
| 862 | −//times are in ms | |
| 863 | −void tADSR4_initToPool (tADSR4* const adsrenv, float attack, float decay, float sustain, float release, float* expBuffer, int bufferSize, tMempool* const mp) | |
| 864 | −{ | |
| 865 | − _tMempool* m = *mp; | |
| 866 | − _tADSR4* adsr = *adsrenv = (_tADSR4*) mpool_alloc(sizeof(_tADSR4), m); | |
| 867 | − | |
| 868 | − adsr->exp_buff = expBuffer; | |
| 869 | − adsr->buff_size = bufferSize; | |
| 870 | − adsr->buff_sizeMinusOne = bufferSize - 1; | |
| 871 | − | |
| 872 | − adsr->bufferSizeDividedBySampleRateInMs = bufferSize / (leaf.sampleRate * 0.001f); | |
| 873 | − | |
| 874 | − if (attack < 0.0f) | |
| 875 | − attack = 0.0f; | |
| 876 | − | |
| 877 | − if (decay < 0.0f) | |
| 878 | − decay = 0.0f; | |
| 879 | − | |
| 880 | − if (sustain > 1.0f) | |
| 881 | − sustain = 1.0f; | |
| 882 | − if (sustain < 0.0f) | |
| 883 | − sustain = 0.0f; | |
| 884 | − | |
| 885 | − if (release < 0.0f) | |
| 886 | − release = 0.0f; | |
| 887 | − | |
| 888 | − adsr->next = 0.0f; | |
| 889 | − | |
| 890 | − adsr->whichStage = env_idle; | |
| 891 | − | |
| 892 | − adsr->sustain = sustain; | |
| 893 | − | |
| 894 | − adsr->attackInc = adsr->bufferSizeDividedBySampleRateInMs / attack; | |
| 895 | − adsr->decayInc = adsr->bufferSizeDividedBySampleRateInMs / decay; | |
| 896 | − adsr->releaseInc = adsr->bufferSizeDividedBySampleRateInMs / release; | |
| 897 | − adsr->rampInc = adsr->bufferSizeDividedBySampleRateInMs / 8.0f; | |
| 898 | − | |
| 899 | − adsr->leakFactor = 1.0f; | |
| 900 | −} | |
| 901 | − | |
| 902 | −void tADSR4_freeFromPool (tADSR4* const adsrenv, tMempool* const mp) | |
| 903 | −{ | |
| 904 | − _tMempool* m = *mp; | |
| 905 | − _tADSR4* adsr = *adsrenv; | |
| 906 | − mpool_free((char*)adsr, m); | |
| 907 | −} | |
| 908 | − | |
| 909 | −void tADSR4_setAttack(tADSR4* const adsrenv, float attack) | |
| 910 | −{ | |
| 911 | − _tADSR4* adsr = *adsrenv; | |
| 912 | − | |
| 913 | − if (attack < 0.0f) | |
| 914 | − { | |
| 915 | − attack = 0.0f; | |
| 916 | − } | |
| 917 | − | |
| 918 | − adsr->attackInc = adsr->bufferSizeDividedBySampleRateInMs / attack; | |
| 919 | −} | |
| 920 | − | |
| 921 | −void tADSR4_setDecay(tADSR4* const adsrenv, float decay) | |
| 922 | −{ | |
| 923 | − _tADSR4* adsr = *adsrenv; | |
| 924 | − | |
| 925 | − if (decay < 0.0f) | |
| 926 | − { | |
| 927 | − decay = 0.0f; | |
| 928 | − } | |
| 929 | − adsr->decayInc = adsr->bufferSizeDividedBySampleRateInMs / decay; | |
| 930 | −} | |
| 931 | − | |
| 932 | −void tADSR4_setSustain(tADSR4* const adsrenv, float sustain) | |
| 933 | −{ | |
| 934 | − _tADSR4* adsr = *adsrenv; | |
| 935 | − | |
| 936 | − if (sustain > 1.0f) adsr->sustain = 1.0f; | |
| 937 | − else if (sustain < 0.0f) adsr->sustain = 0.0f; | |
| 938 | − else adsr->sustain = sustain; | |
| 939 | −} | |
| 940 | − | |
| 941 | −void tADSR4_setRelease(tADSR4* const adsrenv, float release) | |
| 942 | −{ | |
| 943 | − _tADSR4* adsr = *adsrenv; | |
| 944 | − | |
| 945 | − if (release < 0.0f) | |
| 946 | − { | |
| 947 | − release = 0.0f; | |
| 948 | − } | |
| 949 | − adsr->releaseInc = adsr->bufferSizeDividedBySampleRateInMs / release; | |
| 950 | −} | |
| 951 | − | |
| 952 | −// 0.999999 is slow leak, 0.9 is fast leak | |
| 953 | −void tADSR4_setLeakFactor(tADSR4* const adsrenv, float leakFactor) | |
| 954 | −{ | |
| 955 | − _tADSR4* adsr = *adsrenv; | |
| 956 | − | |
| 957 | − | |
| 958 | − adsr->leakFactor = leakFactor; | |
| 959 | −} | |
| 960 | − | |
| 961 | −void tADSR4_on(tADSR4* const adsrenv, float velocity) | |
| 962 | −{ | |
| 963 | − _tADSR4* adsr = *adsrenv; | |
| 964 | − | |
| 965 | − if (adsr->whichStage != env_idle) // In case ADSR retriggered while it is still happening. | |
| 966 | − { | |
| 967 | − adsr->rampPhase = 0; | |
| 968 | − adsr->whichStage = env_ramp; | |
| 969 | − adsr->rampPeak = adsr->next; | |
| 970 | − } | |
| 971 | − else // Normal start. | |
| 972 | − { | |
| 973 | − adsr->whichStage = env_attack; | |
| 974 | − } | |
| 975 | − | |
| 976 | − adsr->attackPhase = 0; | |
| 977 | − adsr->decayPhase = 0; | |
| 978 | − adsr->releasePhase = 0; | |
| 979 | − adsr->gain = velocity; | |
| 980 | −} | |
| 981 | − | |
| 982 | −void tADSR4_off(tADSR4* const adsrenv) | |
| 983 | −{ | |
| 984 | − _tADSR4* adsr = *adsrenv; | |
| 985 | − | |
| 986 | − if (adsr->whichStage == env_idle) | |
| 987 | − { | |
| 988 | − return; | |
| 989 | − } | |
| 990 | − else | |
| 991 | − { | |
| 992 | − adsr->whichStage = env_release; | |
| 993 | − adsr->releasePeak = adsr->next; | |
| 994 | − } | |
| 995 | −} | |
| 996 | − | |
| 997 | −float tADSR4_tick(tADSR4* const adsrenv) | |
| 998 | −{ | |
| 999 | − _tADSR4* adsr = *adsrenv; | |
| 1000 | − | |
| 1001 | − switch (adsr->whichStage) | |
| 1002 | − { | |
| 1003 | − case env_ramp: | |
| 1004 | − if (adsr->rampPhase > adsr->buff_sizeMinusOne) | |
| 1005 | − { | |
| 1006 | − adsr->whichStage = env_attack; | |
| 1007 | − adsr->next = 0.0f; | |
| 1008 | − } | |
| 1009 | − else | |
| 1010 | − { | |
| 1011 | − uint32_t intPart = (uint32_t)adsr->rampPhase; | |
| 1012 | − float floatPart = adsr->rampPhase - intPart; | |
| 1013 | − float secondValue; | |
| 1014 | − if (adsr->rampPhase + 1.0f > adsr->buff_sizeMinusOne) | |
| 1015 | − { | |
| 1016 | − secondValue = 0.0f; | |
| 1017 | − } | |
| 1018 | − else | |
| 1019 | − { | |
| 1020 | − secondValue = adsr->exp_buff[(uint32_t)((adsr->rampPhase)+1)]; | |
| 1021 | − } | |
| 1022 | − adsr->next = adsr->rampPeak * LEAF_interpolation_linear(adsr->exp_buff[intPart], secondValue, floatPart); | |
| 1023 | − } | |
| 1024 | − | |
| 1025 | − adsr->rampPhase += adsr->rampInc; | |
| 1026 | − break; | |
| 1027 | − | |
| 1028 | − | |
| 1029 | − case env_attack: | |
| 1030 | − | |
| 1031 | − // If attack done, time to turn around. | |
| 1032 | − if (adsr->attackPhase > adsr->buff_sizeMinusOne) | |
| 1033 | − { | |
| 1034 | − adsr->whichStage = env_decay; | |
| 1035 | − adsr->next = adsr->gain; | |
| 1036 | − } | |
| 1037 | − else | |
| 1038 | − { | |
| 1039 | − // do interpolation ! | |
| 1040 | − uint32_t intPart = (uint32_t)adsr->attackPhase; | |
| 1041 | − float floatPart = adsr->attackPhase - intPart; | |
| 1042 | − float secondValue; | |
| 1043 | − if (adsr->attackPhase + 1.0f > adsr->buff_sizeMinusOne) | |
| 1044 | − { | |
| 1045 | − secondValue = 0.0f; | |
| 1046 | − } | |
| 1047 | − else | |
| 1048 | − { | |
| 1049 | − secondValue = adsr->exp_buff[(uint32_t)((adsr->attackPhase)+1)]; | |
| 1050 | − } | |
| 1051 | − | |
| 1052 | − adsr->next = adsr->gain * (1.0f - LEAF_interpolation_linear(adsr->exp_buff[intPart], secondValue, floatPart)); // inverted and backwards to get proper rising exponential shape/perception | |
| 1053 | − } | |
| 1054 | − | |
| 1055 | − // Increment ADSR attack. | |
| 1056 | − adsr->attackPhase += adsr->attackInc; | |
| 1057 | − break; | |
| 1058 | − | |
| 1059 | − case env_decay: | |
| 1060 | − | |
| 1061 | − // If decay done, sustain. | |
| 1062 | − if (adsr->decayPhase > adsr->buff_sizeMinusOne) | |
| 1063 | − { | |
| 1064 | − adsr->whichStage = env_sustain; | |
| 1065 | − adsr->next = adsr->gain * adsr->sustain; | |
| 1066 | − } | |
| 1067 | − | |
| 1068 | − else | |
| 1069 | − { | |
| 1070 | − uint32_t intPart = (uint32_t)adsr->decayPhase; | |
| 1071 | − float floatPart = adsr->decayPhase - intPart; | |
| 1072 | − float secondValue; | |
| 1073 | − if (adsr->decayPhase + 1.0f > adsr->buff_sizeMinusOne) | |
| 1074 | − { | |
| 1075 | − secondValue = 0.0f; | |
| 1076 | − } | |
| 1077 | − else | |
| 1078 | − { | |
| 1079 | − secondValue = adsr->exp_buff[(uint32_t)((adsr->decayPhase)+1)]; | |
| 1080 | − } | |
| 1081 | − float interpValue = (LEAF_interpolation_linear(adsr->exp_buff[intPart], secondValue, floatPart)); | |
| 1082 | − adsr->next = (adsr->gain * (adsr->sustain + (interpValue * (1.0f - adsr->sustain)))) * adsr->leakFactor; // do interpolation ! | |
| 1083 | − } | |
| 1084 | − | |
| 1085 | − // Increment ADSR decay. | |
| 1086 | − adsr->decayPhase += adsr->decayInc; | |
| 1087 | − break; | |
| 1088 | − | |
| 1089 | − case env_sustain: | |
| 1090 | − adsr->next = adsr->next * adsr->leakFactor; | |
| 1091 | − break; | |
| 1092 | − | |
| 1093 | − case env_release: | |
| 1094 | − // If release done, finish. | |
| 1095 | − if (adsr->releasePhase > adsr->buff_sizeMinusOne) | |
| 1096 | − { | |
| 1097 | − adsr->whichStage = env_idle; | |
| 1098 | − adsr->next = 0.0f; | |
| 1099 | − } | |
| 1100 | − else { | |
| 1101 | − uint32_t intPart = (uint32_t)adsr->releasePhase; | |
| 1102 | − float floatPart = adsr->releasePhase - intPart; | |
| 1103 | − float secondValue; | |
| 1104 | − if (adsr->releasePhase + 1.0f > adsr->buff_sizeMinusOne) | |
| 1105 | − { | |
| 1106 | − secondValue = 0.0f; | |
| 1107 | − } | |
| 1108 | − else | |
| 1109 | − { | |
| 1110 | − secondValue = adsr->exp_buff[(uint32_t)((adsr->releasePhase)+1)]; | |
| 1111 | − } | |
| 1112 | − adsr->next = adsr->releasePeak * (LEAF_interpolation_linear(adsr->exp_buff[intPart], secondValue, floatPart)); // do interpolation ! | |
| 1113 | − } | |
| 1114 | − | |
| 1115 | − // Increment envelope release; | |
| 1116 | − adsr->releasePhase += adsr->releaseInc; | |
| 1117 | − break; | |
| 1118 | − } | |
| 1119 | − return adsr->next; | |
| 1120 | −} | |
| 1121 | − | |
| 1122 | −float tADSR4_tickNoInterp(tADSR4* const adsrenv) | |
| 1123 | −{ | |
| 1124 | − _tADSR4* adsr = *adsrenv; | |
| 1125 | − | |
| 1126 | − switch (adsr->whichStage) | |
| 1127 | − { | |
| 1128 | − case env_ramp: | |
| 1129 | − if (adsr->rampPhase > adsr->buff_sizeMinusOne) | |
| 1130 | − { | |
| 1131 | − adsr->whichStage = env_attack; | |
| 1132 | − adsr->next = 0.0f; | |
| 1133 | − } | |
| 1134 | − else | |
| 1135 | − { | |
| 1136 | − adsr->next = adsr->rampPeak * adsr->exp_buff[(uint32_t)adsr->rampPhase]; | |
| 1137 | − } | |
| 1138 | − | |
| 1139 | − adsr->rampPhase += adsr->rampInc; | |
| 1140 | − break; | |
| 1141 | − | |
| 1142 | − | |
| 1143 | − case env_attack: | |
| 1144 | − | |
| 1145 | − // If attack done, time to turn around. | |
| 1146 | − if (adsr->attackPhase > adsr->buff_sizeMinusOne) | |
| 1147 | − { | |
| 1148 | − adsr->whichStage = env_decay; | |
| 1149 | − adsr->next = adsr->gain; | |
| 1150 | − } | |
| 1151 | − else | |
| 1152 | − { | |
| 1153 | − adsr->next = adsr->gain * (1.0f - adsr->exp_buff[(uint32_t)adsr->attackPhase]); // inverted and backwards to get proper rising exponential shape/perception | |
| 1154 | − } | |
| 1155 | − | |
| 1156 | − // Increment ADSR attack. | |
| 1157 | − adsr->attackPhase += adsr->attackInc; | |
| 1158 | − break; | |
| 1159 | − | |
| 1160 | − case env_decay: | |
| 1161 | − | |
| 1162 | − // If decay done, sustain. | |
| 1163 | − if (adsr->decayPhase > adsr->buff_sizeMinusOne) | |
| 1164 | − { | |
| 1165 | − adsr->whichStage = env_sustain; | |
| 1166 | − adsr->next = adsr->gain * adsr->sustain; | |
| 1167 | − } | |
| 1168 | − | |
| 1169 | − else | |
| 1170 | − { | |
| 1171 | − adsr->next = (adsr->gain * (adsr->sustain + (adsr->exp_buff[(uint32_t)adsr->decayPhase] * (1.0f - adsr->sustain)))) * adsr->leakFactor; | |
| 1172 | − } | |
| 1173 | − | |
| 1174 | − // Increment ADSR decay. | |
| 1175 | − adsr->decayPhase += adsr->decayInc; | |
| 1176 | − break; | |
| 1177 | − | |
| 1178 | − case env_sustain: | |
| 1179 | − adsr->next = adsr->next * adsr->leakFactor; | |
| 1180 | − break; | |
| 1181 | − | |
| 1182 | − case env_release: | |
| 1183 | − // If release done, finish. | |
| 1184 | − if (adsr->releasePhase > adsr->buff_sizeMinusOne) | |
| 1185 | − { | |
| 1186 | − adsr->whichStage = env_idle; | |
| 1187 | − adsr->next = 0.0f; | |
| 1188 | − } | |
| 1189 | − else { | |
| 1190 | − adsr->next = adsr->releasePeak * adsr->exp_buff[(uint32_t)adsr->releasePhase]; | |
| 1191 | − } | |
| 1192 | − | |
| 1193 | − // Increment envelope release; | |
| 1194 | − adsr->releasePhase += adsr->releaseInc; | |
| 1195 | − break; | |
| 1196 | − } | |
| 1197 | − return adsr->next; | |
| 1198 | −} | |
| 1199 | − | |
| 1200 | − | |
| 1201 | − | |
| 1202 | −/////----------------- | |
| 1203 | −/* Ramp */ | |
| 1204 | −void tRamp_init(tRamp* const r, float time, int samples_per_tick) | |
| 1205 | −{ | |
| 1206 | − _tRamp* ramp = *r = (_tRamp*) leaf_alloc(sizeof(_tRamp)); | |
| 1207 | − | |
| 1208 | − ramp->inv_sr_ms = 1.0f/(leaf.sampleRate*0.001f); | |
| 1209 | − ramp->minimum_time = ramp->inv_sr_ms * samples_per_tick; | |
| 1210 | − ramp->curr = 0.0f; | |
| 1211 | − ramp->dest = 0.0f; | |
| 1212 | − | |
| 1213 | − if (time < ramp->minimum_time) | |
| 1214 | − { | |
| 1215 | − ramp->time = ramp->minimum_time; | |
| 1216 | − } | |
| 1217 | − else | |
| 1218 | − { | |
| 1219 | − ramp->time = time; | |
| 1220 | − } | |
| 1221 | − ramp->factor = (1.0f / ramp->time) * ramp->inv_sr_ms; | |
| 1222 | − ramp->samples_per_tick = samples_per_tick; | |
| 1223 | − ramp->inc = ((ramp->dest - ramp->curr) / ramp->time * ramp->inv_sr_ms) * (float)ramp->samples_per_tick; | |
| 1224 | −} | |
| 1225 | − | |
| 1226 | −void tRamp_free(tRamp* const r) | |
| 1227 | −{ | |
| 1228 | − _tRamp* ramp = *r; | |
| 1229 | − | |
| 1230 | − leaf_free((char*)ramp); | |
| 1231 | −} | |
| 1232 | − | |
| 1233 | −void tRamp_initToPool (tRamp* const r, float time, int samples_per_tick, tMempool* const mp) | |
| 1234 | −{ | |
| 1235 | − _tMempool* m = *mp; | |
| 1236 | − _tRamp* ramp = *r = (_tRamp*) mpool_alloc(sizeof(_tRamp), m); | |
| 1237 | − | |
| 1238 | − ramp->inv_sr_ms = 1.0f/(leaf.sampleRate*0.001f); | |
| 1239 | − ramp->minimum_time = ramp->inv_sr_ms * samples_per_tick; | |
| 1240 | − ramp->curr = 0.0f; | |
| 1241 | − ramp->dest = 0.0f; | |
| 1242 | − | |
| 1243 | − if (time < ramp->minimum_time) | |
| 1244 | − { | |
| 1245 | − ramp->time = ramp->minimum_time; | |
| 1246 | − } | |
| 1247 | − else | |
| 1248 | − { | |
| 1249 | − ramp->time = time; | |
| 1250 | − } | |
| 1251 | − ramp->samples_per_tick = samples_per_tick; | |
| 1252 | − ramp->factor = (1.0f / ramp->time) * ramp->inv_sr_ms * (float)ramp->samples_per_tick; | |
| 1253 | − ramp->inc = (ramp->dest - ramp->curr) * ramp->factor; | |
| 1254 | −} | |
| 1255 | − | |
| 1256 | −void tRamp_freeFromPool (tRamp* const r, tMempool* const mp) | |
| 1257 | −{ | |
| 1258 | − _tMempool* m = *mp; | |
| 1259 | − _tRamp* ramp = *r; | |
| 1260 | − | |
| 1261 | − mpool_free((char*)ramp, m); | |
| 1262 | −} | |
| 1263 | − | |
| 1264 | −void tRamp_setTime(tRamp* const ramp, float time) | |
| 1265 | −{ | |
| 1266 | − _tRamp* r = *ramp; | |
| 1267 | − | |
| 1268 | − if (time < r->minimum_time) | |
| 1269 | − { | |
| 1270 | − r->time = r->minimum_time; | |
| 1271 | − } | |
| 1272 | − else | |
| 1273 | − { | |
| 1274 | − r->time = time; | |
| 1275 | − } | |
| 1276 | − r->factor = (1.0f / r->time) * r->inv_sr_ms * (float)r->samples_per_tick; | |
| 1277 | − r->inc = (r->dest - r->curr) * r->factor; | |
| 1278 | − | |
| 1279 | −} | |
| 1280 | − | |
| 1281 | −void tRamp_setDest(tRamp* const ramp, float dest) | |
| 1282 | −{ | |
| 1283 | − _tRamp* r = *ramp; | |
| 1284 | − r->dest = dest; | |
| 1285 | − r->inc = (r->dest - r->curr) * r->factor; | |
| 1286 | −} | |
| 1287 | − | |
| 1288 | −void tRamp_setVal(tRamp* const ramp, float val) | |
| 1289 | −{ | |
| 1290 | − _tRamp* r = *ramp; | |
| 1291 | − r->curr = val; | |
| 1292 | − r->inc = (r->dest - r->curr) * r->factor; | |
| 1293 | −} | |
| 1294 | − | |
| 1295 | −float tRamp_tick(tRamp* const ramp) | |
| 1296 | −{ | |
| 1297 | − _tRamp* r = *ramp; | |
| 1298 | − | |
| 1299 | − r->curr += r->inc; | |
| 1300 | − | |
| 1301 | − if (((r->curr >= r->dest) && (r->inc > 0.0f)) || ((r->curr <= r->dest) && (r->inc < 0.0f))) | |
| 1302 | − { | |
| 1303 | − r->inc = 0.0f; | |
| 1304 | − r->curr=r->dest; | |
| 1305 | − } | |
| 1306 | − | |
| 1307 | − return r->curr; | |
| 1308 | −} | |
| 1309 | − | |
| 1310 | −float tRamp_sample(tRamp* const ramp) | |
| 1311 | −{ | |
| 1312 | − _tRamp* r = *ramp; | |
| 1313 | − return r->curr; | |
| 1314 | −} | |
| 1315 | − | |
| 1316 | −void tRampSampleRateChanged(tRamp* const ramp) | |
| 1317 | −{ | |
| 1318 | − _tRamp* r = *ramp; | |
| 1319 | − r->inv_sr_ms = 1.0f / (leaf.sampleRate * 0.001f); | |
| 1320 | − r->factor = (1.0f / r->time) * r->inv_sr_ms * (float)r->samples_per_tick; | |
| 1321 | − r->inc = (r->dest - r->curr) * r->factor; | |
| 1322 | −} | |
| 1323 | − | |
| 1324 | − | |
| 1325 | − | |
| 1326 | −/* RampUpDown */ | |
| 1327 | −void tRampUpDown_init(tRampUpDown* const r, float upTime, float downTime, int samples_per_tick) | |
| 1328 | −{ | |
| 1329 | − tRampUpDown_initToPool(r, upTime, downTime, samples_per_tick, &leaf.mempool); | |
| 1330 | −} | |
| 1331 | − | |
| 1332 | −void tRampUpDown_free(tRampUpDown* const r) | |
| 1333 | −{ | |
| 1334 | − tRampUpDown_freeFromPool(r, &leaf.mempool); | |
| 1335 | −} | |
| 1336 | − | |
| 1337 | −void tRampUpDown_initToPool(tRampUpDown* const r, float upTime, float downTime, int samples_per_tick, tMempool* const mp) | |
| 1338 | −{ | |
| 1339 | − _tMempool* m = *mp; | |
| 1340 | − _tRampUpDown* ramp = *r = (_tRampUpDown*) mpool_alloc(sizeof(_tRampUpDown), m); | |
| 1341 | − | |
| 1342 | − ramp->inv_sr_ms = 1.0f/(leaf.sampleRate*0.001f); | |
| 1343 | − ramp->minimum_time = ramp->inv_sr_ms * samples_per_tick; | |
| 1344 | − ramp->curr = 0.0f; | |
| 1345 | − ramp->dest = 0.0f; | |
| 1346 | − | |
| 1347 | − if (upTime < ramp->minimum_time) | |
| 1348 | − { | |
| 1349 | − ramp->upTime = ramp->minimum_time; | |
| 1350 | − } | |
| 1351 | − else | |
| 1352 | − { | |
| 1353 | − ramp->upTime = upTime; | |
| 1354 | − } | |
| 1355 | − | |
| 1356 | − if (downTime < ramp->minimum_time) | |
| 1357 | − { | |
| 1358 | − ramp->downTime = ramp->minimum_time; | |
| 1359 | − } | |
| 1360 | − else | |
| 1361 | − { | |
| 1362 | − ramp->downTime = downTime; | |
| 1363 | − } | |
| 1364 | − | |
| 1365 | − ramp->samples_per_tick = samples_per_tick; | |
| 1366 | − ramp->upInc = ((ramp->dest - ramp->curr) / ramp->upTime * ramp->inv_sr_ms) * (float)ramp->samples_per_tick; | |
| 1367 | − ramp->downInc = ((ramp->dest - ramp->curr) / ramp->downTime * ramp->inv_sr_ms) * (float)ramp->samples_per_tick; | |
| 1368 | −} | |
| 1369 | − | |
| 1370 | −void tRampUpDown_freeFromPool (tRampUpDown* const r, tMempool* const mp) | |
| 1371 | −{ | |
| 1372 | − _tMempool* m = *mp; | |
| 1373 | − _tRampUpDown* ramp = *r; | |
| 1374 | − | |
| 1375 | − mpool_free((char*)ramp, m); | |
| 1376 | −} | |
| 1377 | − | |
| 1378 | −void tRampUpDown_setUpTime(tRampUpDown* const ramp, float upTime) | |
| 1379 | −{ | |
| 1380 | − _tRampUpDown* r = *ramp; | |
| 1381 | − | |
| 1382 | − if (upTime < r->minimum_time) | |
| 1383 | − { | |
| 1384 | − r->upTime = r->minimum_time; | |
| 1385 | − } | |
| 1386 | − else | |
| 1387 | − { | |
| 1388 | − r->upTime = upTime; | |
| 1389 | − } | |
| 1390 | − r->upInc = ((r->dest - r->curr) / r->upTime * r->inv_sr_ms) * (float)r->samples_per_tick; | |
| 1391 | −} | |
| 1392 | − | |
| 1393 | − | |
| 1394 | −void tRampUpDown_setDownTime(tRampUpDown* const ramp, float downTime) | |
| 1395 | −{ | |
| 1396 | − _tRampUpDown* r = *ramp; | |
| 1397 | − | |
| 1398 | − if (downTime < r->minimum_time) | |
| 1399 | − { | |
| 1400 | − r->downTime = r->minimum_time; | |
| 1401 | − } | |
| 1402 | − else | |
| 1403 | − { | |
| 1404 | − r->downTime = downTime; | |
| 1405 | − } | |
| 1406 | − r->downInc = ((r->dest - r->curr) / r->downTime * r->inv_sr_ms) * (float)r->samples_per_tick; | |
| 1407 | −} | |
| 1408 | − | |
| 1409 | −void tRampUpDown_setDest(tRampUpDown* const ramp, float dest) | |
| 1410 | −{ | |
| 1411 | − _tRampUpDown* r = *ramp; | |
| 1412 | − r->dest = dest; | |
| 1413 | − r->upInc = ((r->dest - r->curr) / r->upTime * r->inv_sr_ms) * (float)r->samples_per_tick; | |
| 1414 | − r->downInc = ((r->dest - r->curr) / r->downTime * r->inv_sr_ms) * (float)r->samples_per_tick; | |
| 1415 | −} | |
| 1416 | − | |
| 1417 | −void tRampUpDown_setVal(tRampUpDown* const ramp, float val) | |
| 1418 | −{ | |
| 1419 | − _tRampUpDown* r = *ramp; | |
| 1420 | − r->curr = val; | |
| 1421 | − r->upInc = ((r->dest - r->curr) / r->upTime * r->inv_sr_ms) * (float)r->samples_per_tick; | |
| 1422 | − r->downInc = ((r->dest - r->curr) / r->downTime * r->inv_sr_ms) * (float)r->samples_per_tick; | |
| 1423 | −} | |
| 1424 | − | |
| 1425 | −float tRampUpDown_tick(tRampUpDown* const ramp) | |
| 1426 | −{ | |
| 1427 | − _tRampUpDown* r = *ramp; | |
| 1428 | − float test; | |
| 1429 | − | |
| 1430 | − if (r->dest < r->curr) | |
| 1431 | − { | |
| 1432 | − test = r->curr + r->downInc; | |
| 1433 | − if (test > r->dest) | |
| 1434 | − { | |
| 1435 | − r->curr = test; | |
| 1436 | − } | |
| 1437 | − else | |
| 1438 | − { | |
| 1439 | − r->downInc = 0.0f; | |
| 1440 | − r->curr = r->dest; | |
| 1441 | − } | |
| 1442 | − } | |
| 1443 | − else if (r->dest > r->curr) | |
| 1444 | − { | |
| 1445 | − test = r->curr + r->upInc; | |
| 1446 | − if (test < r->dest) | |
| 1447 | − { | |
| 1448 | − r->curr = test; | |
| 1449 | − } | |
| 1450 | − else | |
| 1451 | − { | |
| 1452 | − r->upInc = 0.0f; | |
| 1453 | − r->curr = r->dest; | |
| 1454 | − } | |
| 1455 | − } | |
| 1456 | − return r->curr; | |
| 1457 | −} | |
| 1458 | − | |
| 1459 | −float tRampUpDown_sample(tRampUpDown* const ramp) | |
| 1460 | −{ | |
| 1461 | − _tRampUpDown* r = *ramp; | |
| 1462 | − return r->curr; | |
| 1463 | −} | |
| 1464 | − | |
| 1465 | − | |
| 1466 | − | |
| 1467 | − | |
| 1468 | − | |
| 1469 | − | |
| 1470 | −/* Exponential Smoother */ | |
| 1471 | −void tExpSmooth_init(tExpSmooth* const expsmooth, float val, float factor) | |
| 1472 | −{ // factor is usually a value between 0 and 0.1. Lower value is slower. 0.01 for example gives you a smoothing time of about 10ms | |
| 1473 | − _tExpSmooth* smooth = *expsmooth = (_tExpSmooth*) leaf_alloc(sizeof(_tExpSmooth)); | |
| 1474 | − | |
| 1475 | − smooth->curr=val; | |
| 1476 | − smooth->dest=val; | |
| 1477 | − if (factor<0) factor=0; | |
| 1478 | − if (factor>1) factor=1; | |
| 1479 | − smooth->factor=factor; | |
| 1480 | − smooth->oneminusfactor=1.0f-factor; | |
| 1481 | −} | |
| 1482 | − | |
| 1483 | −void tExpSmooth_free(tExpSmooth* const expsmooth) | |
| 1484 | −{ | |
| 1485 | − _tExpSmooth* smooth = *expsmooth; | |
| 1486 | − | |
| 1487 | − leaf_free((char*)smooth); | |
| 1488 | −} | |
| 1489 | − | |
| 1490 | −void tExpSmooth_initToPool (tExpSmooth* const expsmooth, float val, float factor, tMempool* const mp) | |
| 1491 | −{ | |
| 1492 | − _tMempool* m = *mp; | |
| 1493 | − _tExpSmooth* smooth = *expsmooth = (_tExpSmooth*) mpool_alloc(sizeof(_tExpSmooth), m); | |
| 1494 | − | |
| 1495 | − smooth->curr=val; | |
| 1496 | − smooth->dest=val; | |
| 1497 | − if (factor<0) factor=0; | |
| 1498 | − if (factor>1) factor=1; | |
| 1499 | − smooth->factor=factor; | |
| 1500 | − smooth->oneminusfactor=1.0f-factor; | |
| 1501 | −} | |
| 1502 | − | |
| 1503 | −void tExpSmooth_freeFromPool (tExpSmooth* const expsmooth, tMempool* const mp) | |
| 1504 | −{ | |
| 1505 | − _tMempool* m = *mp; | |
| 1506 | − _tExpSmooth* smooth = *expsmooth; | |
| 1507 | − | |
| 1508 | − mpool_free((char*)smooth, m); | |
| 1509 | −} | |
| 1510 | − | |
| 1511 | −void tExpSmooth_setFactor(tExpSmooth* const expsmooth, float factor) | |
| 1512 | −{ // factor is usually a value between 0 and 0.1. Lower value is slower. 0.01 for example gives you a smoothing time of about 10ms | |
| 1513 | − _tExpSmooth* smooth = *expsmooth; | |
| 1514 | − | |
| 1515 | − if (factor<0) | |
| 1516 | − factor=0; | |
| 1517 | − else | |
| 1518 | − if (factor>1) factor=1; | |
| 1519 | − smooth->factor=factor; | |
| 1520 | − smooth->oneminusfactor=1.0f-factor; | |
| 1521 | −} | |
| 1522 | − | |
| 1523 | −void tExpSmooth_setDest(tExpSmooth* const expsmooth, float dest) | |
| 1524 | −{ | |
| 1525 | − _tExpSmooth* smooth = *expsmooth; | |
| 1526 | − smooth->dest=dest; | |
| 1527 | −} | |
| 1528 | − | |
| 1529 | −void tExpSmooth_setVal(tExpSmooth* const expsmooth, float val) | |
| 1530 | −{ | |
| 1531 | − _tExpSmooth* smooth = *expsmooth; | |
| 1532 | − smooth->curr=val; | |
| 1533 | −} | |
| 1534 | − | |
| 1535 | −void tExpSmooth_setValAndDest(tExpSmooth* const expsmooth, float val) | |
| 1536 | −{ | |
| 1537 | − _tExpSmooth* smooth = *expsmooth; | |
| 1538 | − smooth->curr=val; | |
| 1539 | − smooth->dest=val; | |
| 1540 | −} | |
| 1541 | − | |
| 1542 | −float tExpSmooth_tick(tExpSmooth* const expsmooth) | |
| 1543 | −{ | |
| 1544 | − _tExpSmooth* smooth = *expsmooth; | |
| 1545 | − smooth->curr = smooth->factor*smooth->dest+smooth->oneminusfactor*smooth->curr; | |
| 1546 | − return smooth->curr; | |
| 1547 | −} | |
| 1548 | − | |
| 1549 | −float tExpSmooth_sample(tExpSmooth* const expsmooth) | |
| 1550 | −{ | |
| 1551 | − _tExpSmooth* smooth = *expsmooth; | |
| 1552 | − return smooth->curr; | |
| 1553 | −} | |
| 1554 | − | |
| 1555 | −//tSlide is based on the max/msp slide~ object | |
| 1556 | −//// | |
| 1557 | − | |
| 1558 | −void tSlide_init (tSlide* const sl, float upSlide, float downSlide) | |
| 1559 | −{ | |
| 1560 | − tSlide_initToPool (sl, upSlide, downSlide, &leaf.mempool); | |
| 1561 | −} | |
| 1562 | −void tSlide_free (tSlide* const sl) | |
| 1563 | −{ | |
| 1564 | − tSlide_freeFromPool (sl, &leaf.mempool); | |
| 1565 | −} | |
| 1566 | −void tSlide_initToPool (tSlide* const sl, float upSlide, float downSlide, tMempool* const mp) | |
| 1567 | −{ | |
| 1568 | − _tMempool* m = *mp; | |
| 1569 | − _tSlide* s = *sl = (_tSlide*) mpool_alloc(sizeof(_tSlide), m); | |
| 1570 | − s->prevIn = 0.0f; | |
| 1571 | − s->currentOut = 0.0f; | |
| 1572 | − s->prevOut = 0.0f; | |
| 1573 | − if (upSlide < 1.0f) | |
| 1574 | − { | |
| 1575 | − upSlide = 1.0f; | |
| 1576 | − } | |
| 1577 | − | |
| 1578 | − if (downSlide < 1.0f) | |
| 1579 | − { | |
| 1580 | − downSlide = 1.0f; | |
| 1581 | − } | |
| 1582 | − s->invUpSlide = 1.0f / upSlide; | |
| 1583 | − s->invDownSlide = 1.0f / downSlide; | |
| 1584 | −} | |
| 1585 | − | |
| 1586 | −void tSlide_freeFromPool (tSlide* const sl, tMempool* const mp) | |
| 1587 | −{ | |
| 1588 | − _tMempool* m = *mp; | |
| 1589 | − _tSlide* s = *sl; | |
| 1590 | − | |
| 1591 | − mpool_free((char*)s, m); | |
| 1592 | −} | |
| 1593 | − | |
| 1594 | −float tSlide_tick(tSlide* const sl, float in) | |
| 1595 | −{ | |
| 1596 | − _tSlide* s = *sl; | |
| 1597 | − | |
| 1598 | − | |
| 1599 | − if (in >= s->prevOut) | |
| 1600 | − { | |
| 1601 | − s->currentOut = s->prevOut + ((in - s->prevOut) * s->invUpSlide); | |
| 1602 | − } | |
| 1603 | − else | |
| 1604 | − { | |
| 1605 | − s->currentOut = s->prevOut + ((in - s->prevOut) * s->invDownSlide); | |
| 1606 | − } | |
| 1607 | − if (s->currentOut < VSF) s->currentOut = 0.0f; | |
| 1608 | − s->prevIn = in; | |
| 1609 | − s->prevOut = s->currentOut; | |
| 1610 | − return s->currentOut; | |
| 1611 | −} | |
| 1612 | − | |
| @@ -1,1802 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-filter.c | |
| 4 | − Created: 20 Jan 2017 12:01:10pm | |
| 5 | − Author: Michael R Mulshine | |
| 6 | − | |
| 7 | −==============================================================================*/ | |
| 8 | − | |
| 9 | −#if _WIN32 || _WIN64 | |
| 10 | − | |
| 11 | −#include "..\Inc\leaf-filters.h" | |
| 12 | −#include "..\Inc\leaf-tables.h" | |
| 13 | −#include "..\leaf.h" | |
| 14 | − | |
| 15 | −#else | |
| 16 | − | |
| 17 | −#include "../Inc/leaf-filters.h" | |
| 18 | −#include "../Inc/leaf-tables.h" | |
| 19 | −#include "../leaf.h" | |
| 20 | −//#include "tim.h" | |
| 21 | −#endif | |
| 22 | − | |
| 23 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 24 | −void tAllpass_init(tAllpass* const ft, float initDelay, uint32_t maxDelay) | |
| 25 | −{ | |
| 26 | − _tAllpass* f = *ft = (_tAllpass*) leaf_alloc(sizeof(_tAllpass)); | |
| 27 | − | |
| 28 | − f->gain = 0.7f; | |
| 29 | − | |
| 30 | − f->lastOut = 0.0f; | |
| 31 | − | |
| 32 | − tLinearDelay_init(&f->delay, initDelay, maxDelay); | |
| 33 | −} | |
| 34 | − | |
| 35 | −void tAllpass_free(tAllpass* const ft) | |
| 36 | −{ | |
| 37 | − _tAllpass* f = *ft; | |
| 38 | − | |
| 39 | − tLinearDelay_free(&f->delay); | |
| 40 | − leaf_free((char*)f); | |
| 41 | −} | |
| 42 | − | |
| 43 | −void tAllpass_initToPool (tAllpass* const ft, float initDelay, uint32_t maxDelay, tMempool* const mp) | |
| 44 | −{ | |
| 45 | − _tMempool* m = *mp; | |
| 46 | − _tAllpass* f = *ft = (_tAllpass*) mpool_alloc(sizeof(_tAllpass), m); | |
| 47 | − | |
| 48 | − f->gain = 0.7f; | |
| 49 | − | |
| 50 | − f->lastOut = 0.0f; | |
| 51 | − | |
| 52 | − tLinearDelay_initToPool(&f->delay, initDelay, maxDelay, mp); | |
| 53 | −} | |
| 54 | − | |
| 55 | −void tAllpass_freeFromPool (tAllpass* const ft, tMempool* const mp) | |
| 56 | −{ | |
| 57 | − _tMempool* m = *mp; | |
| 58 | − _tAllpass* f = *ft; | |
| 59 | − | |
| 60 | − tLinearDelay_freeFromPool(&f->delay, mp); | |
| 61 | − mpool_free((char*)f, m); | |
| 62 | −} | |
| 63 | − | |
| 64 | −void tAllpass_setDelay(tAllpass* const ft, float delay) | |
| 65 | −{ | |
| 66 | − _tAllpass* f = *ft; | |
| 67 | − | |
| 68 | − tLinearDelay_setDelay(&f->delay, delay); | |
| 69 | −} | |
| 70 | − | |
| 71 | −void tAllpass_setGain(tAllpass* const ft, float gain) | |
| 72 | −{ | |
| 73 | − _tAllpass* f = *ft; | |
| 74 | − | |
| 75 | − f->gain = gain; | |
| 76 | −} | |
| 77 | − | |
| 78 | −float tAllpass_tick(tAllpass* const ft, float input) | |
| 79 | −{ | |
| 80 | − _tAllpass* f = *ft; | |
| 81 | − | |
| 82 | − float s1 = (-f->gain) * f->lastOut + input; | |
| 83 | − | |
| 84 | − float s2 = tLinearDelay_tick(&f->delay, s1) + (f->gain) * input; | |
| 85 | − | |
| 86 | − f->lastOut = s2; | |
| 87 | − | |
| 88 | − return f->lastOut; | |
| 89 | −} | |
| 90 | − | |
| 91 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 92 | −void tOnePole_init(tOnePole* const ft, float freq) | |
| 93 | −{ | |
| 94 | − _tOnePole* f = *ft = (_tOnePole*) leaf_alloc(sizeof(_tOnePole)); | |
| 95 | − | |
| 96 | − f->gain = 1.0f; | |
| 97 | − f->a0 = 1.0; | |
| 98 | − | |
| 99 | − tOnePole_setFreq(ft, freq); | |
| 100 | − | |
| 101 | − f->lastIn = 0.0f; | |
| 102 | − f->lastOut = 0.0f; | |
| 103 | −} | |
| 104 | − | |
| 105 | −void tOnePole_free(tOnePole* const ft) | |
| 106 | −{ | |
| 107 | − _tOnePole* f = *ft; | |
| 108 | − | |
| 109 | − leaf_free((char*)f); | |
| 110 | −} | |
| 111 | − | |
| 112 | −void tOnePole_initToPool (tOnePole* const ft, float freq, tMempool* const mp) | |
| 113 | −{ | |
| 114 | − _tMempool* m = *mp; | |
| 115 | − _tOnePole* f = *ft = (_tOnePole*) mpool_alloc(sizeof(_tOnePole), m); | |
| 116 | − | |
| 117 | − f->gain = 1.0f; | |
| 118 | − f->a0 = 1.0; | |
| 119 | − | |
| 120 | − tOnePole_setFreq(ft, freq); | |
| 121 | − | |
| 122 | − f->lastIn = 0.0f; | |
| 123 | − f->lastOut = 0.0f; | |
| 124 | −} | |
| 125 | − | |
| 126 | −void tOnePole_freeFromPool (tOnePole* const ft, tMempool* const mp) | |
| 127 | −{ | |
| 128 | − _tMempool* m = *mp; | |
| 129 | − _tOnePole* f = *ft; | |
| 130 | − | |
| 131 | − mpool_free((char*)f, m); | |
| 132 | −} | |
| 133 | − | |
| 134 | −void tOnePole_setB0(tOnePole* const ft, float b0) | |
| 135 | −{ | |
| 136 | − _tOnePole* f = *ft; | |
| 137 | − f->b0 = b0; | |
| 138 | −} | |
| 139 | − | |
| 140 | −void tOnePole_setA1(tOnePole* const ft, float a1) | |
| 141 | −{ | |
| 142 | − _tOnePole* f = *ft; | |
| 143 | − if (a1 >= 1.0f) a1 = 0.999999f; | |
| 144 | − f->a1 = a1; | |
| 145 | −} | |
| 146 | − | |
| 147 | −void tOnePole_setPole(tOnePole* const ft, float thePole) | |
| 148 | −{ | |
| 149 | − _tOnePole* f = *ft; | |
| 150 | − | |
| 151 | − if (thePole >= 1.0f) thePole = 0.999999f; | |
| 152 | − | |
| 153 | − // Normalize coefficients for peak unity gain. | |
| 154 | − if (thePole > 0.0f) f->b0 = (1.0f - thePole); | |
| 155 | − else f->b0 = (1.0f + thePole); | |
| 156 | − | |
| 157 | − f->a1 = -thePole; | |
| 158 | −} | |
| 159 | − | |
| 160 | −void tOnePole_setFreq (tOnePole* const ft, float freq) | |
| 161 | −{ | |
| 162 | − _tOnePole* f = *ft; | |
| 163 | − f->b0 = freq * leaf.twoPiTimesInvSampleRate; | |
| 164 | − f->b0 = LEAF_clip(0.0f, f->b0, 1.0f); | |
| 165 | − f->a1 = 1.0f - f->b0; | |
| 166 | −} | |
| 167 | − | |
| 168 | −void tOnePole_setCoefficients(tOnePole* const ft, float b0, float a1) | |
| 169 | −{ | |
| 170 | − _tOnePole* f = *ft; | |
| 171 | − if (a1 >= 1.0f) a1 = 0.999999f; | |
| 172 | − f->b0 = b0; | |
| 173 | − f->a1 = a1; | |
| 174 | −} | |
| 175 | − | |
| 176 | −void tOnePole_setGain(tOnePole* const ft, float gain) | |
| 177 | −{ | |
| 178 | − _tOnePole* f = *ft; | |
| 179 | − f->gain = gain; | |
| 180 | −} | |
| 181 | − | |
| 182 | −float tOnePole_tick(tOnePole* const ft, float input) | |
| 183 | −{ | |
| 184 | − _tOnePole* f = *ft; | |
| 185 | − | |
| 186 | − float in = input * f->gain; | |
| 187 | − float out = (f->b0 * in) + (f->a1 * f->lastOut); | |
| 188 | − | |
| 189 | − f->lastIn = in; | |
| 190 | − f->lastOut = out; | |
| 191 | − | |
| 192 | − return out; | |
| 193 | −} | |
| 194 | − | |
| 195 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoPole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 196 | −void tTwoPole_init(tTwoPole* const ft) | |
| 197 | −{ | |
| 198 | − _tTwoPole* f = *ft = (_tTwoPole*) leaf_alloc(sizeof(_tTwoPole)); | |
| 199 | − | |
| 200 | − f->gain = 1.0f; | |
| 201 | − f->a0 = 1.0; | |
| 202 | − f->b0 = 1.0; | |
| 203 | − | |
| 204 | − f->lastOut[0] = 0.0f; | |
| 205 | − f->lastOut[1] = 0.0f; | |
| 206 | −} | |
| 207 | − | |
| 208 | −void tTwoPole_free(tTwoPole* const ft) | |
| 209 | −{ | |
| 210 | − _tTwoPole* f = *ft; | |
| 211 | − | |
| 212 | − leaf_free((char*)f); | |
| 213 | −} | |
| 214 | − | |
| 215 | −void tTwoPole_initToPool (tTwoPole* const ft, tMempool* const mp) | |
| 216 | −{ | |
| 217 | − _tMempool* m = *mp; | |
| 218 | − _tTwoPole* f = *ft = (_tTwoPole*) mpool_alloc(sizeof(_tTwoPole), m); | |
| 219 | − | |
| 220 | − f->gain = 1.0f; | |
| 221 | − f->a0 = 1.0; | |
| 222 | − f->b0 = 1.0; | |
| 223 | − | |
| 224 | − f->lastOut[0] = 0.0f; | |
| 225 | − f->lastOut[1] = 0.0f; | |
| 226 | −} | |
| 227 | − | |
| 228 | −void tTwoPole_freeFromPool (tTwoPole* const ft, tMempool* const mp) | |
| 229 | −{ | |
| 230 | − _tMempool* m = *mp; | |
| 231 | − _tTwoPole* f = *ft; | |
| 232 | − | |
| 233 | − mpool_free((char*)f, m); | |
| 234 | −} | |
| 235 | − | |
| 236 | −float tTwoPole_tick(tTwoPole* const ft, float input) | |
| 237 | −{ | |
| 238 | − _tTwoPole* f = *ft; | |
| 239 | − | |
| 240 | − float in = input * f->gain; | |
| 241 | − float out = (f->b0 * in) - (f->a1 * f->lastOut[0]) - (f->a2 * f->lastOut[1]); | |
| 242 | − | |
| 243 | − f->lastOut[1] = f->lastOut[0]; | |
| 244 | − f->lastOut[0] = out; | |
| 245 | − | |
| 246 | − return out; | |
| 247 | −} | |
| 248 | − | |
| 249 | −void tTwoPole_setB0(tTwoPole* const ft, float b0) | |
| 250 | −{ | |
| 251 | − _tTwoPole* f = *ft; | |
| 252 | − f->b0 = b0; | |
| 253 | −} | |
| 254 | − | |
| 255 | −void tTwoPole_setA1(tTwoPole* const ft, float a1) | |
| 256 | −{ | |
| 257 | − _tTwoPole* f = *ft; | |
| 258 | − f->a1 = a1; | |
| 259 | −} | |
| 260 | − | |
| 261 | −void tTwoPole_setA2(tTwoPole* const ft, float a2) | |
| 262 | −{ | |
| 263 | − _tTwoPole* f = *ft; | |
| 264 | − f->a2 = a2; | |
| 265 | −} | |
| 266 | − | |
| 267 | − | |
| 268 | −void tTwoPole_setResonance(tTwoPole* const ft, float frequency, float radius, oBool normalize) | |
| 269 | −{ | |
| 270 | − _tTwoPole* f = *ft; | |
| 271 | − | |
| 272 | − if (frequency < 0.0f) frequency = 0.0f; | |
| 273 | − if (frequency > (leaf.sampleRate * 0.49f)) frequency = leaf.sampleRate * 0.49f; | |
| 274 | − if (radius < 0.0f) radius = 0.0f; | |
| 275 | − if (radius >= 1.0f) radius = 0.999999f; | |
| 276 | − | |
| 277 | − f->radius = radius; | |
| 278 | − f->frequency = frequency; | |
| 279 | − f->normalize = normalize; | |
| 280 | − | |
| 281 | − f->a2 = radius * radius; | |
| 282 | − f->a1 = -2.0f * radius * cosf(frequency * leaf.twoPiTimesInvSampleRate); | |
| 283 | − | |
| 284 | − if ( normalize ) | |
| 285 | − { | |
| 286 | − // Normalize the filter gain ... not terribly efficient. | |
| 287 | − float real = 1 - radius + (f->a2 - radius) * cosf(2 * frequency * leaf.twoPiTimesInvSampleRate); | |
| 288 | − float imag = (f->a2 - radius) * sinf(2 * frequency * leaf.twoPiTimesInvSampleRate); | |
| 289 | − f->b0 = sqrtf( powf(real, 2) + powf(imag, 2) ); | |
| 290 | − } | |
| 291 | −} | |
| 292 | − | |
| 293 | −void tTwoPole_setCoefficients(tTwoPole* const ft, float b0, float a1, float a2) | |
| 294 | −{ | |
| 295 | − _tTwoPole* f = *ft; | |
| 296 | − f->b0 = b0; | |
| 297 | − f->a1 = a1; | |
| 298 | − f->a2 = a2; | |
| 299 | −} | |
| 300 | − | |
| 301 | −void tTwoPole_setGain(tTwoPole* const ft, float gain) | |
| 302 | −{ | |
| 303 | − _tTwoPole* f = *ft; | |
| 304 | − f->gain = gain; | |
| 305 | −} | |
| 306 | − | |
| 307 | −void tTwoPoleSampleRateChanged (tTwoPole* const ft) | |
| 308 | −{ | |
| 309 | − _tTwoPole* f = *ft; | |
| 310 | − | |
| 311 | − f->a2 = f->radius * f->radius; | |
| 312 | − f->a1 = -2.0f * f->radius * cosf(f->frequency * leaf.twoPiTimesInvSampleRate); | |
| 313 | − | |
| 314 | − if ( f->normalize ) | |
| 315 | − { | |
| 316 | − // Normalize the filter gain ... not terribly efficient. | |
| 317 | − float real = 1 - f->radius + (f->a2 - f->radius) * cosf(2 * f->frequency * leaf.twoPiTimesInvSampleRate); | |
| 318 | − float imag = (f->a2 - f->radius) * sinf(2 * f->frequency * leaf.twoPiTimesInvSampleRate); | |
| 319 | − f->b0 = sqrtf( powf(real, 2) + powf(imag, 2) ); | |
| 320 | − } | |
| 321 | −} | |
| 322 | − | |
| 323 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OneZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 324 | −void tOneZero_init(tOneZero* const ft, float theZero) | |
| 325 | −{ | |
| 326 | − _tOneZero* f = *ft = (_tOneZero*) leaf_alloc(sizeof(_tOneZero)); | |
| 327 | − | |
| 328 | − f->gain = 1.0f; | |
| 329 | − f->lastIn = 0.0f; | |
| 330 | − f->lastOut = 0.0f; | |
| 331 | − tOneZero_setZero(ft, theZero); | |
| 332 | −} | |
| 333 | − | |
| 334 | −void tOneZero_free(tOneZero* const ft) | |
| 335 | −{ | |
| 336 | − _tOneZero* f = *ft; | |
| 337 | − | |
| 338 | − leaf_free((char*)f); | |
| 339 | −} | |
| 340 | − | |
| 341 | −void tOneZero_initToPool (tOneZero* const ft, float theZero, tMempool* const mp) | |
| 342 | −{ | |
| 343 | − _tMempool* m = *mp; | |
| 344 | − _tOneZero* f = *ft = (_tOneZero*) mpool_alloc(sizeof(_tOneZero), m); | |
| 345 | − | |
| 346 | − f->gain = 1.0f; | |
| 347 | − f->lastIn = 0.0f; | |
| 348 | − f->lastOut = 0.0f; | |
| 349 | − tOneZero_setZero(ft, theZero); | |
| 350 | −} | |
| 351 | − | |
| 352 | −void tOneZero_freeFromPool (tOneZero* const ft, tMempool* const mp) | |
| 353 | −{ | |
| 354 | − _tMempool* m = *mp; | |
| 355 | − _tOneZero* f = *ft; | |
| 356 | − | |
| 357 | − mpool_free((char*)f, m); | |
| 358 | −} | |
| 359 | − | |
| 360 | −float tOneZero_tick(tOneZero* const ft, float input) | |
| 361 | −{ | |
| 362 | − _tOneZero* f = *ft; | |
| 363 | − | |
| 364 | − float in = input * f->gain; | |
| 365 | − float out = f->b1 * f->lastIn + f->b0 * in; | |
| 366 | − | |
| 367 | − f->lastIn = in; | |
| 368 | − | |
| 369 | − return out; | |
| 370 | −} | |
| 371 | − | |
| 372 | −void tOneZero_setZero(tOneZero* const ft, float theZero) | |
| 373 | −{ | |
| 374 | − _tOneZero* f = *ft; | |
| 375 | − | |
| 376 | − if (theZero > 0.0f) f->b0 = 1.0f / (1.0f + theZero); | |
| 377 | − else f->b0 = 1.0f / (1.0f - theZero); | |
| 378 | − | |
| 379 | − f->b1 = -theZero * f->b0; | |
| 380 | − | |
| 381 | −} | |
| 382 | − | |
| 383 | −void tOneZero_setB0(tOneZero* const ft, float b0) | |
| 384 | −{ | |
| 385 | − _tOneZero* f = *ft; | |
| 386 | − | |
| 387 | − f->b0 = b0; | |
| 388 | −} | |
| 389 | − | |
| 390 | −void tOneZero_setB1(tOneZero* const ft, float b1) | |
| 391 | −{ | |
| 392 | − _tOneZero* f = *ft; | |
| 393 | − f->b1 = b1; | |
| 394 | −} | |
| 395 | − | |
| 396 | −void tOneZero_setCoefficients(tOneZero* const ft, float b0, float b1) | |
| 397 | −{ | |
| 398 | − _tOneZero* f = *ft; | |
| 399 | − f->b0 = b0; | |
| 400 | − f->b1 = b1; | |
| 401 | −} | |
| 402 | − | |
| 403 | −void tOneZero_setGain(tOneZero *ft, float gain) | |
| 404 | −{ | |
| 405 | − _tOneZero* f = *ft; | |
| 406 | − f->gain = gain; | |
| 407 | −} | |
| 408 | − | |
| 409 | −float tOneZero_getPhaseDelay(tOneZero* const ft, float frequency ) | |
| 410 | −{ | |
| 411 | − _tOneZero* f = *ft; | |
| 412 | − | |
| 413 | − if ( frequency <= 0.0f) frequency = 0.05f; | |
| 414 | − | |
| 415 | − f->frequency = frequency; | |
| 416 | − | |
| 417 | − float omegaT = 2 * PI * frequency * leaf.invSampleRate; | |
| 418 | − float real = 0.0, imag = 0.0; | |
| 419 | − | |
| 420 | − real += f->b0; | |
| 421 | − | |
| 422 | − real += f->b1 * cosf(omegaT); | |
| 423 | − imag -= f->b1 * sinf(omegaT); | |
| 424 | − | |
| 425 | − real *= f->gain; | |
| 426 | − imag *= f->gain; | |
| 427 | − | |
| 428 | − float phase = atan2f( imag, real ); | |
| 429 | − | |
| 430 | − real = 0.0; imag = 0.0; | |
| 431 | − | |
| 432 | − phase -= atan2f( imag, real ); | |
| 433 | − | |
| 434 | − phase = fmodf( -phase, 2 * PI ); | |
| 435 | − | |
| 436 | − return phase / omegaT; | |
| 437 | −} | |
| 438 | − | |
| 439 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 440 | −void tTwoZero_init(tTwoZero* const ft) | |
| 441 | −{ | |
| 442 | − _tTwoZero* f = *ft = (_tTwoZero*) leaf_alloc(sizeof(_tTwoZero)); | |
| 443 | − | |
| 444 | − f->gain = 1.0f; | |
| 445 | − f->lastIn[0] = 0.0f; | |
| 446 | − f->lastIn[1] = 0.0f; | |
| 447 | −} | |
| 448 | − | |
| 449 | −void tTwoZero_free(tTwoZero* const ft) | |
| 450 | −{ | |
| 451 | − _tTwoZero* f = *ft; | |
| 452 | − | |
| 453 | − leaf_free((char*)f); | |
| 454 | −} | |
| 455 | − | |
| 456 | −void tTwoZero_initToPool (tTwoZero* const ft, tMempool* const mp) | |
| 457 | −{ | |
| 458 | − _tMempool* m = *mp; | |
| 459 | − _tTwoZero* f = *ft = (_tTwoZero*) mpool_alloc(sizeof(_tTwoZero), m); | |
| 460 | − | |
| 461 | − f->gain = 1.0f; | |
| 462 | − f->lastIn[0] = 0.0f; | |
| 463 | − f->lastIn[1] = 0.0f; | |
| 464 | −} | |
| 465 | − | |
| 466 | −void tTwoZero_freeFromPool (tTwoZero* const ft, tMempool* const mp) | |
| 467 | −{ | |
| 468 | − _tMempool* m = *mp; | |
| 469 | − _tTwoZero* f = *ft; | |
| 470 | − | |
| 471 | − mpool_free((char*)f, m); | |
| 472 | −} | |
| 473 | − | |
| 474 | −float tTwoZero_tick(tTwoZero* const ft, float input) | |
| 475 | −{ | |
| 476 | − _tTwoZero* f = *ft; | |
| 477 | − | |
| 478 | − float in = input * f->gain; | |
| 479 | − float out = f->b2 * f->lastIn[1] + f->b1 * f->lastIn[0] + f->b0 * in; | |
| 480 | − | |
| 481 | − f->lastIn[1] = f->lastIn[0]; | |
| 482 | − f->lastIn[0] = in; | |
| 483 | − | |
| 484 | − return out; | |
| 485 | −} | |
| 486 | − | |
| 487 | −void tTwoZero_setNotch(tTwoZero* const ft, float freq, float radius) | |
| 488 | −{ | |
| 489 | − _tTwoZero* f = *ft; | |
| 490 | − | |
| 491 | − // Should also deal with frequency being > half sample rate / nyquist. See STK | |
| 492 | − if (freq < 0.0f) freq = 0.0f; | |
| 493 | − if (radius < 0.0f) radius = 0.0f; | |
| 494 | − | |
| 495 | − f->frequency = freq; | |
| 496 | − f->radius = radius; | |
| 497 | − | |
| 498 | − f->b2 = radius * radius; | |
| 499 | − f->b1 = -2.0f * radius * cosf(freq * leaf.twoPiTimesInvSampleRate); // OPTIMIZE with LOOKUP or APPROXIMATION | |
| 500 | − | |
| 501 | − // Normalize the filter gain. From STK. | |
| 502 | − if ( f->b1 > 0.0f ) // Maximum at z = 0. | |
| 503 | − f->b0 = 1.0f / ( 1.0f + f->b1 + f->b2 ); | |
| 504 | − else // Maximum at z = -1. | |
| 505 | − f->b0 = 1.0f / ( 1.0f - f->b1 + f->b2 ); | |
| 506 | − f->b1 *= f->b0; | |
| 507 | − f->b2 *= f->b0; | |
| 508 | − | |
| 509 | −} | |
| 510 | − | |
| 511 | −void tTwoZero_setB0(tTwoZero* const ft, float b0) | |
| 512 | −{ | |
| 513 | − _tTwoZero* f = *ft; | |
| 514 | − f->b0 = b0; | |
| 515 | −} | |
| 516 | − | |
| 517 | −void tTwoZero_setB1(tTwoZero* const ft, float b1) | |
| 518 | −{ | |
| 519 | − _tTwoZero* f = *ft; | |
| 520 | − f->b1 = b1; | |
| 521 | −} | |
| 522 | − | |
| 523 | −void tTwoZero_setCoefficients(tTwoZero* const ft, float b0, float b1, float b2) | |
| 524 | −{ | |
| 525 | − _tTwoZero* f = *ft; | |
| 526 | − f->b0 = b0; | |
| 527 | − f->b1 = b1; | |
| 528 | − f->b2 = b2; | |
| 529 | −} | |
| 530 | − | |
| 531 | −void tTwoZero_setGain(tTwoZero* const ft, float gain) | |
| 532 | −{ | |
| 533 | − _tTwoZero* f = *ft; | |
| 534 | − f->gain = gain; | |
| 535 | −} | |
| 536 | − | |
| 537 | −void tTwoZeroSampleRateChanged(tTwoZero* const ft) | |
| 538 | −{ | |
| 539 | − _tTwoZero* f = *ft; | |
| 540 | − | |
| 541 | − tTwoZero_setNotch(ft, f->frequency, f->radius); | |
| 542 | −} | |
| 543 | − | |
| 544 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PoleZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 545 | −void tPoleZero_init(tPoleZero* const pzf) | |
| 546 | −{ | |
| 547 | − _tPoleZero* f = *pzf = (_tPoleZero*) leaf_alloc(sizeof(_tPoleZero)); | |
| 548 | − | |
| 549 | − f->gain = 1.0f; | |
| 550 | − f->b0 = 1.0; | |
| 551 | − f->a0 = 1.0; | |
| 552 | − | |
| 553 | − f->lastIn = 0.0f; | |
| 554 | − f->lastOut = 0.0f; | |
| 555 | −} | |
| 556 | − | |
| 557 | −void tPoleZero_free(tPoleZero* const pzf) | |
| 558 | −{ | |
| 559 | − _tPoleZero* f = *pzf; | |
| 560 | − | |
| 561 | − leaf_free((char*)f); | |
| 562 | −} | |
| 563 | − | |
| 564 | −void tPoleZero_initToPool (tPoleZero* const pzf, tMempool* const mp) | |
| 565 | −{ | |
| 566 | − _tMempool* m = *mp; | |
| 567 | − _tPoleZero* f = *pzf = (_tPoleZero*) mpool_alloc(sizeof(_tPoleZero), m); | |
| 568 | − | |
| 569 | − f->gain = 1.0f; | |
| 570 | − f->b0 = 1.0; | |
| 571 | − f->a0 = 1.0; | |
| 572 | − | |
| 573 | − f->lastIn = 0.0f; | |
| 574 | − f->lastOut = 0.0f; | |
| 575 | −} | |
| 576 | − | |
| 577 | −void tPoleZero_freeFromPool (tPoleZero* const pzf, tMempool* const mp) | |
| 578 | −{ | |
| 579 | − _tMempool* m = *mp; | |
| 580 | − _tPoleZero* f = *pzf; | |
| 581 | − | |
| 582 | − mpool_free((char*)f, m); | |
| 583 | −} | |
| 584 | − | |
| 585 | −void tPoleZero_setB0(tPoleZero* const pzf, float b0) | |
| 586 | −{ | |
| 587 | − _tPoleZero* f = *pzf; | |
| 588 | − f->b0 = b0; | |
| 589 | −} | |
| 590 | − | |
| 591 | −void tPoleZero_setB1(tPoleZero* const pzf, float b1) | |
| 592 | −{ | |
| 593 | − _tPoleZero* f = *pzf; | |
| 594 | − f->b1 = b1; | |
| 595 | −} | |
| 596 | − | |
| 597 | −void tPoleZero_setA1(tPoleZero* const pzf, float a1) | |
| 598 | −{ | |
| 599 | − _tPoleZero* f = *pzf; | |
| 600 | − | |
| 601 | − if (a1 >= 1.0f) // a1 should be less than 1.0 | |
| 602 | − { | |
| 603 | − a1 = 0.999999f; | |
| 604 | − } | |
| 605 | − | |
| 606 | − f->a1 = a1; | |
| 607 | −} | |
| 608 | − | |
| 609 | −void tPoleZero_setCoefficients(tPoleZero* const pzf, float b0, float b1, float a1) | |
| 610 | −{ | |
| 611 | − _tPoleZero* f = *pzf; | |
| 612 | − | |
| 613 | − if (a1 >= 1.0f) // a1 should be less than 1.0 | |
| 614 | − { | |
| 615 | − a1 = 0.999999f; | |
| 616 | − } | |
| 617 | − | |
| 618 | − f->b0 = b0; | |
| 619 | − f->b1 = b1; | |
| 620 | − f->a1 = a1; | |
| 621 | −} | |
| 622 | − | |
| 623 | −void tPoleZero_setAllpass(tPoleZero* const pzf, float coeff) | |
| 624 | −{ | |
| 625 | − _tPoleZero* f = *pzf; | |
| 626 | − | |
| 627 | − if (coeff >= 1.0f) // allpass coefficient >= 1.0 makes filter unstable | |
| 628 | − { | |
| 629 | − coeff = 0.999999f; | |
| 630 | − } | |
| 631 | − | |
| 632 | − f->b0 = coeff; | |
| 633 | − f->b1 = 1.0f; | |
| 634 | − f->a0 = 1.0f; | |
| 635 | − f->a1 = coeff; | |
| 636 | −} | |
| 637 | − | |
| 638 | −void tPoleZero_setBlockZero(tPoleZero* const pzf, float thePole) | |
| 639 | −{ | |
| 640 | − _tPoleZero* f = *pzf; | |
| 641 | − | |
| 642 | − if (thePole >= 1.0f) // allpass coefficient >= 1.0 makes filter unstable | |
| 643 | − { | |
| 644 | − thePole = 0.999999f; | |
| 645 | − } | |
| 646 | − | |
| 647 | − f->b0 = 1.0f; | |
| 648 | − f->b1 = -1.0f; | |
| 649 | − f->a0 = 1.0f; | |
| 650 | − f->a1 = -thePole; | |
| 651 | −} | |
| 652 | − | |
| 653 | −void tPoleZero_setGain(tPoleZero* const pzf, float gain) | |
| 654 | −{ | |
| 655 | − _tPoleZero* f = *pzf; | |
| 656 | − f->gain = gain; | |
| 657 | −} | |
| 658 | − | |
| 659 | −float tPoleZero_tick(tPoleZero* const pzf, float input) | |
| 660 | −{ | |
| 661 | − _tPoleZero* f = *pzf; | |
| 662 | − | |
| 663 | − float in = input * f->gain; | |
| 664 | − float out = (f->b0 * in) + (f->b1 * f->lastIn) - (f->a1 * f->lastOut); | |
| 665 | − | |
| 666 | − f->lastIn = in; | |
| 667 | − f->lastOut = out; | |
| 668 | − | |
| 669 | − return out; | |
| 670 | −} | |
| 671 | − | |
| 672 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ BiQuad Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 673 | −void tBiQuad_init(tBiQuad* const ft) | |
| 674 | −{ | |
| 675 | − _tBiQuad* f = *ft = (_tBiQuad*) leaf_alloc(sizeof(_tBiQuad)); | |
| 676 | − | |
| 677 | − f->gain = 1.0f; | |
| 678 | − | |
| 679 | − f->b0 = 0.0f; | |
| 680 | − f->a0 = 0.0f; | |
| 681 | − | |
| 682 | − f->lastIn[0] = 0.0f; | |
| 683 | − f->lastIn[1] = 0.0f; | |
| 684 | − f->lastOut[0] = 0.0f; | |
| 685 | − f->lastOut[1] = 0.0f; | |
| 686 | −} | |
| 687 | − | |
| 688 | −void tBiQuad_free(tBiQuad* const ft) | |
| 689 | −{ | |
| 690 | − _tBiQuad* f = *ft; | |
| 691 | − | |
| 692 | − leaf_free((char*)f); | |
| 693 | −} | |
| 694 | − | |
| 695 | −void tBiQuad_initToPool (tBiQuad* const ft, tMempool* const mp) | |
| 696 | −{ | |
| 697 | − _tMempool* m = *mp; | |
| 698 | − _tBiQuad* f = *ft = (_tBiQuad*) mpool_alloc(sizeof(_tBiQuad), m); | |
| 699 | − | |
| 700 | − f->gain = 1.0f; | |
| 701 | − | |
| 702 | − f->b0 = 0.0f; | |
| 703 | − f->a0 = 0.0f; | |
| 704 | − | |
| 705 | − f->lastIn[0] = 0.0f; | |
| 706 | − f->lastIn[1] = 0.0f; | |
| 707 | − f->lastOut[0] = 0.0f; | |
| 708 | − f->lastOut[1] = 0.0f; | |
| 709 | −} | |
| 710 | − | |
| 711 | −void tBiQuad_freeFromPool (tBiQuad* const ft, tMempool* const mp) | |
| 712 | −{ | |
| 713 | − _tMempool* m = *mp; | |
| 714 | − _tBiQuad* f = *ft; | |
| 715 | − | |
| 716 | − mpool_free((char*)f, m); | |
| 717 | −} | |
| 718 | − | |
| 719 | −float tBiQuad_tick(tBiQuad* const ft, float input) | |
| 720 | −{ | |
| 721 | − _tBiQuad* f = *ft; | |
| 722 | − | |
| 723 | − float in = input * f->gain; | |
| 724 | − float out = f->b0 * in + f->b1 * f->lastIn[0] + f->b2 * f->lastIn[1]; | |
| 725 | − out -= f->a2 * f->lastOut[1] + f->a1 * f->lastOut[0]; | |
| 726 | − | |
| 727 | − f->lastIn[1] = f->lastIn[0]; | |
| 728 | − f->lastIn[0] = in; | |
| 729 | − | |
| 730 | − f->lastOut[1] = f->lastOut[0]; | |
| 731 | − f->lastOut[0] = out; | |
| 732 | − | |
| 733 | − return out; | |
| 734 | −} | |
| 735 | − | |
| 736 | −void tBiQuad_setResonance(tBiQuad* const ft, float freq, float radius, oBool normalize) | |
| 737 | −{ | |
| 738 | − _tBiQuad* f = *ft; | |
| 739 | − | |
| 740 | − if (freq < 0.0f) freq = 0.0f; | |
| 741 | − if (freq > (leaf.sampleRate * 0.49f)) freq = leaf.sampleRate * 0.49f; | |
| 742 | − if (radius < 0.0f) radius = 0.0f; | |
| 743 | − if (radius >= 1.0f) radius = 1.0f; | |
| 744 | − | |
| 745 | − f->frequency = freq; | |
| 746 | − f->radius = radius; | |
| 747 | − f->normalize = normalize; | |
| 748 | − | |
| 749 | − f->a2 = radius * radius; | |
| 750 | − f->a1 = -2.0f * radius * cosf(freq * leaf.twoPiTimesInvSampleRate); | |
| 751 | − | |
| 752 | − if (normalize) | |
| 753 | − { | |
| 754 | − f->b0 = 0.5f - 0.5f * f->a2; | |
| 755 | − f->b1 = 0.0f; | |
| 756 | − f->b2 = -f->b0; | |
| 757 | − } | |
| 758 | −} | |
| 759 | − | |
| 760 | −void tBiQuad_setNotch(tBiQuad* const ft, float freq, float radius) | |
| 761 | −{ | |
| 762 | − _tBiQuad* f = *ft; | |
| 763 | − | |
| 764 | − if (freq < 0.0f) freq = 0.0f; | |
| 765 | − if (freq > (leaf.sampleRate * 0.49f)) freq = leaf.sampleRate * 0.49f; | |
| 766 | − if (radius < 0.0f) radius = 0.0f; | |
| 767 | − | |
| 768 | − f->b2 = radius * radius; | |
| 769 | − f->b1 = -2.0f * radius * cosf(freq * leaf.twoPiTimesInvSampleRate); // OPTIMIZE with LOOKUP or APPROXIMATION | |
| 770 | − | |
| 771 | − // Does not attempt to normalize filter gain. | |
| 772 | −} | |
| 773 | − | |
| 774 | −void tBiQuad_setEqualGainZeros(tBiQuad* const ft) | |
| 775 | −{ | |
| 776 | − _tBiQuad* f = *ft; | |
| 777 | − f->b0 = 1.0f; | |
| 778 | − f->b1 = 0.0f; | |
| 779 | − f->b2 = -1.0f; | |
| 780 | −} | |
| 781 | − | |
| 782 | −void tBiQuad_setB0(tBiQuad* const ft, float b0) | |
| 783 | −{ | |
| 784 | − _tBiQuad* f = *ft; | |
| 785 | − f->b0 = b0; | |
| 786 | −} | |
| 787 | − | |
| 788 | −void tBiQuad_setB1(tBiQuad* const ft, float b1) | |
| 789 | −{ | |
| 790 | − _tBiQuad* f = *ft; | |
| 791 | − f->b1 = b1; | |
| 792 | −} | |
| 793 | − | |
| 794 | −void tBiQuad_setB2(tBiQuad* const ft, float b2) | |
| 795 | −{ | |
| 796 | − _tBiQuad* f = *ft; | |
| 797 | − f->b2 = b2; | |
| 798 | −} | |
| 799 | − | |
| 800 | −void tBiQuad_setA1(tBiQuad* const ft, float a1) | |
| 801 | −{ | |
| 802 | − _tBiQuad* f = *ft; | |
| 803 | − f->a1 = a1; | |
| 804 | −} | |
| 805 | − | |
| 806 | −void tBiQuad_setA2(tBiQuad* const ft, float a2) | |
| 807 | −{ | |
| 808 | − _tBiQuad* f = *ft; | |
| 809 | − f->a2 = a2; | |
| 810 | −} | |
| 811 | − | |
| 812 | −void tBiQuad_setCoefficients(tBiQuad* const ft, float b0, float b1, float b2, float a1, float a2) | |
| 813 | −{ | |
| 814 | − _tBiQuad* f = *ft; | |
| 815 | − f->b0 = b0; | |
| 816 | − f->b1 = b1; | |
| 817 | − f->b2 = b2; | |
| 818 | − f->a1 = a1; | |
| 819 | − f->a2 = a2; | |
| 820 | −} | |
| 821 | − | |
| 822 | −void tBiQuad_setGain(tBiQuad* const ft, float gain) | |
| 823 | −{ | |
| 824 | − _tBiQuad* f = *ft; | |
| 825 | − f->gain = gain; | |
| 826 | −} | |
| 827 | − | |
| 828 | −void tBiQuadSampleRateChanged(tBiQuad* const ft) | |
| 829 | −{ | |
| 830 | − _tBiQuad* f = *ft; | |
| 831 | − f->a2 = f->radius * f->radius; | |
| 832 | − f->a1 = -2.0f * f->radius * cosf(f->frequency * leaf.twoPiTimesInvSampleRate); | |
| 833 | − | |
| 834 | − if (f->normalize) | |
| 835 | − { | |
| 836 | − f->b0 = 0.5f - 0.5f * f->a2; | |
| 837 | − f->b1 = 0.0f; | |
| 838 | − f->b2 = -f->b0; | |
| 839 | − } | |
| 840 | −} | |
| 841 | − | |
| 842 | −// Less efficient, more accurate version of SVF, in which cutoff frequency is taken as floating point Hz value and tanf | |
| 843 | −// is calculated when frequency changes. | |
| 844 | −void tSVF_init(tSVF* const svff, SVFType type, float freq, float Q) | |
| 845 | −{ | |
| 846 | − tSVF_initToPool (svff, type, freq, Q, &leaf.mempool); | |
| 847 | − | |
| 848 | − // or maybe this? | |
| 849 | − /* | |
| 850 | − * hp=1 bp=A/Q (where A is 10^(G/40) and G is gain in decibels) and lp = 1 | |
| 851 | − */ | |
| 852 | − | |
| 853 | −} | |
| 854 | − | |
| 855 | −void tSVF_free(tSVF* const svff) | |
| 856 | −{ | |
| 857 | − tSVF_freeFromPool (svff, &leaf.mempool); | |
| 858 | −} | |
| 859 | − | |
| 860 | −void tSVF_initToPool (tSVF* const svff, SVFType type, float freq, float Q, tMempool* const mp) | |
| 861 | −{ | |
| 862 | − _tMempool* m = *mp; | |
| 863 | − _tSVF* svf = *svff = (_tSVF*) mpool_alloc(sizeof(_tSVF), m); | |
| 864 | − | |
| 865 | − svf->type = type; | |
| 866 | − | |
| 867 | − svf->ic1eq = 0; | |
| 868 | − svf->ic2eq = 0; | |
| 869 | − svf->Q = Q; | |
| 870 | − svf->cutoff = freq; | |
| 871 | − svf->g = tanf(PI * freq * leaf.invSampleRate); | |
| 872 | − svf->k = 1.0f/Q; | |
| 873 | − svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k)); | |
| 874 | − svf->a2 = svf->g*svf->a1; | |
| 875 | − svf->a3 = svf->g*svf->a2; | |
| 876 | − svf->cH = 0.0f; | |
| 877 | − svf->cB = 0.0f; | |
| 878 | − svf->cL = 1.0f; | |
| 879 | − | |
| 880 | − if (type == SVFTypeLowpass) | |
| 881 | − { | |
| 882 | − svf->cH = 0.0f; | |
| 883 | − svf->cB = 0.0f; | |
| 884 | − svf->cBK = 0.0f; | |
| 885 | − svf->cL = 1.0f; | |
| 886 | − } | |
| 887 | − else if (type == SVFTypeBandpass) | |
| 888 | − { | |
| 889 | − svf->cH = 0.0f; | |
| 890 | − svf->cB = 1.0f; | |
| 891 | − svf->cBK = 0.0f; | |
| 892 | − svf->cL = 0.0f; | |
| 893 | − } | |
| 894 | − | |
| 895 | − else if (type == SVFTypeHighpass) | |
| 896 | − { | |
| 897 | − svf->cH = 1.0f; | |
| 898 | − svf->cB = 0.0f; | |
| 899 | − svf->cBK = -1.0f; | |
| 900 | − svf->cL = -1.0f; | |
| 901 | − } | |
| 902 | − | |
| 903 | − else if (type == SVFTypeNotch) | |
| 904 | − { | |
| 905 | − svf->cH = 1.0f; | |
| 906 | − svf->cB = 0.0f; | |
| 907 | − svf->cBK = -1.0f; | |
| 908 | − svf->cL = 0.0f; | |
| 909 | − } | |
| 910 | − | |
| 911 | − | |
| 912 | − else if (type == SVFTypePeak) | |
| 913 | − { | |
| 914 | − svf->cH = 1.0f; | |
| 915 | − svf->cB = 0.0f; | |
| 916 | − svf->cBK = -1.0f; | |
| 917 | − svf->cL = -2.0f; | |
| 918 | − } | |
| 919 | −} | |
| 920 | − | |
| 921 | −void tSVF_freeFromPool (tSVF* const svff, tMempool* const mp) | |
| 922 | −{ | |
| 923 | − _tMempool* m = *mp; | |
| 924 | − _tSVF* svf = *svff; | |
| 925 | − | |
| 926 | − mpool_free((char*)svf, m); | |
| 927 | −} | |
| 928 | − | |
| 929 | −float tSVF_tick(tSVF* const svff, float v0) | |
| 930 | −{ | |
| 931 | − _tSVF* svf = *svff; | |
| 932 | − | |
| 933 | − float v1,v2,v3; | |
| 934 | − v3 = v0 - svf->ic2eq; | |
| 935 | − v1 = (svf->a1 * svf->ic1eq) + (svf->a2 * v3); | |
| 936 | − v2 = svf->ic2eq + (svf->a2 * svf->ic1eq) + (svf->a3 * v3); | |
| 937 | − svf->ic1eq = (2.0f * v1) - svf->ic1eq; | |
| 938 | − svf->ic2eq = (2.0f * v2) - svf->ic2eq; | |
| 939 | − | |
| 940 | − return (v0 * svf->cH) + (v1 * svf->cB) + (svf->k * v1 * svf->cBK) + (v2 * svf->cL); | |
| 941 | −} | |
| 942 | − | |
| 943 | −void tSVF_setFreq(tSVF* const svff, float freq) | |
| 944 | −{ | |
| 945 | − _tSVF* svf = *svff; | |
| 946 | − svf->cutoff = freq; | |
| 947 | − svf->g = tanf(PI * freq * leaf.invSampleRate); | |
| 948 | − svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k)); | |
| 949 | − svf->a2 = svf->g * svf->a1; | |
| 950 | − svf->a3 = svf->g * svf->a2; | |
| 951 | −} | |
| 952 | − | |
| 953 | −void tSVF_setQ(tSVF* const svff, float Q) | |
| 954 | −{ | |
| 955 | − _tSVF* svf = *svff; | |
| 956 | − svf->Q = Q; | |
| 957 | − svf->k = 1.0f/Q; | |
| 958 | − | |
| 959 | − svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k)); | |
| 960 | − svf->a2 = svf->g * svf->a1; | |
| 961 | − svf->a3 = svf->g * svf->a2; | |
| 962 | −} | |
| 963 | − | |
| 964 | −void tSVF_setFreqAndQ(tSVF* const svff, float freq, float Q) | |
| 965 | −{ | |
| 966 | − _tSVF* svf = *svff; | |
| 967 | − svf->k = 1.0f/Q; | |
| 968 | − svf->g = tanf(PI * freq * leaf.invSampleRate); | |
| 969 | − svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k)); | |
| 970 | − svf->a2 = svf->g * svf->a1; | |
| 971 | − svf->a3 = svf->g * svf->a2; | |
| 972 | −} | |
| 973 | − | |
| 974 | −// Efficient version of tSVF where frequency is set based on 12-bit integer input for lookup in tanh wavetable. | |
| 975 | −void tEfficientSVF_init(tEfficientSVF* const svff, SVFType type, uint16_t input, float Q) | |
| 976 | −{ | |
| 977 | − _tEfficientSVF* svf = *svff = (_tEfficientSVF*) leaf_alloc(sizeof(_tEfficientSVF)); | |
| 978 | − | |
| 979 | − svf->type = type; | |
| 980 | − | |
| 981 | − svf->ic1eq = 0; | |
| 982 | − svf->ic2eq = 0; | |
| 983 | − | |
| 984 | − svf->g = __leaf_table_filtertan[input]; | |
| 985 | − svf->k = 1.0f/Q; | |
| 986 | − svf->a1 = 1.0f/(1.0f+svf->g*(svf->g+svf->k)); | |
| 987 | − svf->a2 = svf->g*svf->a1; | |
| 988 | − svf->a3 = svf->g*svf->a2; | |
| 989 | −} | |
| 990 | − | |
| 991 | −void tEfficientSVF_free(tEfficientSVF* const svff) | |
| 992 | −{ | |
| 993 | − _tEfficientSVF* svf = *svff; | |
| 994 | − | |
| 995 | − leaf_free((char*)svf); | |
| 996 | −} | |
| 997 | − | |
| 998 | −void tEfficientSVF_initToPool (tEfficientSVF* const svff, SVFType type, uint16_t input, float Q, tMempool* const mp) | |
| 999 | −{ | |
| 1000 | − _tMempool* m = *mp; | |
| 1001 | − _tEfficientSVF* svf = *svff = (_tEfficientSVF*) mpool_alloc(sizeof(_tEfficientSVF), m); | |
| 1002 | − | |
| 1003 | − svf->type = type; | |
| 1004 | − | |
| 1005 | − svf->ic1eq = 0; | |
| 1006 | − svf->ic2eq = 0; | |
| 1007 | − | |
| 1008 | − svf->g = __leaf_table_filtertan[input]; | |
| 1009 | − svf->k = 1.0f/Q; | |
| 1010 | − svf->a1 = 1.0f/(1.0f+svf->g*(svf->g+svf->k)); | |
| 1011 | − svf->a2 = svf->g*svf->a1; | |
| 1012 | − svf->a3 = svf->g*svf->a2; | |
| 1013 | −} | |
| 1014 | − | |
| 1015 | −void tEfficientSVF_freeFromPool (tEfficientSVF* const svff, tMempool* const mp) | |
| 1016 | −{ | |
| 1017 | − _tMempool* m = *mp; | |
| 1018 | − _tEfficientSVF* svf = *svff; | |
| 1019 | − | |
| 1020 | − mpool_free((char*)svf, m); | |
| 1021 | −} | |
| 1022 | − | |
| 1023 | −float tEfficientSVF_tick(tEfficientSVF* const svff, float v0) | |
| 1024 | −{ | |
| 1025 | − _tEfficientSVF* svf = *svff; | |
| 1026 | − | |
| 1027 | − float v1,v2,v3; | |
| 1028 | − v3 = v0 - svf->ic2eq; | |
| 1029 | − v1 = (svf->a1 * svf->ic1eq) + (svf->a2 * v3); | |
| 1030 | − v2 = svf->ic2eq + (svf->a2 * svf->ic1eq) + (svf->a3 * v3); | |
| 1031 | − svf->ic1eq = (2.0f * v1) - svf->ic1eq; | |
| 1032 | − svf->ic2eq = (2.0f * v2) - svf->ic2eq; | |
| 1033 | − | |
| 1034 | − if (svf->type == SVFTypeLowpass) return v2; | |
| 1035 | − else if (svf->type == SVFTypeBandpass) return v1; | |
| 1036 | − else if (svf->type == SVFTypeHighpass) return v0 - (svf->k * v1) - v2; | |
| 1037 | − else if (svf->type == SVFTypeNotch) return v0 - (svf->k * v1); | |
| 1038 | − else if (svf->type == SVFTypePeak) return v0 - (svf->k * v1) - (2.0f * v2); | |
| 1039 | − else return 0.0f; | |
| 1040 | − | |
| 1041 | −} | |
| 1042 | − | |
| 1043 | −void tEfficientSVF_setFreq(tEfficientSVF* const svff, uint16_t input) | |
| 1044 | −{ | |
| 1045 | − _tEfficientSVF* svf = *svff; | |
| 1046 | − | |
| 1047 | − svf->g = __leaf_table_filtertan[input]; | |
| 1048 | − svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k)); | |
| 1049 | − svf->a2 = svf->g * svf->a1; | |
| 1050 | − svf->a3 = svf->g * svf->a2; | |
| 1051 | −} | |
| 1052 | − | |
| 1053 | −void tEfficientSVF_setQ(tEfficientSVF* const svff, float Q) | |
| 1054 | −{ | |
| 1055 | − _tEfficientSVF* svf = *svff; | |
| 1056 | − | |
| 1057 | − svf->k = 1.0f/Q; | |
| 1058 | − svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k)); | |
| 1059 | − svf->a2 = svf->g * svf->a1; | |
| 1060 | − svf->a3 = svf->g * svf->a2; | |
| 1061 | −} | |
| 1062 | − | |
| 1063 | −/* Highpass */ | |
| 1064 | −void tHighpass_init(tHighpass* const ft, float freq) | |
| 1065 | −{ | |
| 1066 | − _tHighpass* f = *ft = (_tHighpass*) leaf_alloc(sizeof(_tHighpass)); | |
| 1067 | − | |
| 1068 | − f->R = (1.0f - (freq * leaf.twoPiTimesInvSampleRate)); | |
| 1069 | − f->ys = 0.0f; | |
| 1070 | − f->xs = 0.0f; | |
| 1071 | − | |
| 1072 | − f->frequency = freq; | |
| 1073 | −} | |
| 1074 | − | |
| 1075 | −void tHighpass_free(tHighpass* const ft) | |
| 1076 | −{ | |
| 1077 | − _tHighpass* f = *ft; | |
| 1078 | − | |
| 1079 | − leaf_free((char*)f); | |
| 1080 | −} | |
| 1081 | − | |
| 1082 | −void tHighpass_initToPool (tHighpass* const ft, float freq, tMempool* const mp) | |
| 1083 | −{ | |
| 1084 | − _tMempool* m = *mp; | |
| 1085 | − _tHighpass* f = *ft = (_tHighpass*) mpool_calloc(sizeof(_tHighpass), m); | |
| 1086 | − | |
| 1087 | − f->R = (1.0f - (freq * leaf.twoPiTimesInvSampleRate)); | |
| 1088 | − f->ys = 0.0f; | |
| 1089 | − f->xs = 0.0f; | |
| 1090 | − | |
| 1091 | − f->frequency = freq; | |
| 1092 | −} | |
| 1093 | − | |
| 1094 | −void tHighpass_freeFromPool (tHighpass* const ft, tMempool* const mp) | |
| 1095 | −{ | |
| 1096 | − _tMempool* m = *mp; | |
| 1097 | − _tHighpass* f = *ft; | |
| 1098 | − | |
| 1099 | − mpool_free((char*)f, m); | |
| 1100 | −} | |
| 1101 | − | |
| 1102 | −void tHighpass_setFreq(tHighpass* const ft, float freq) | |
| 1103 | −{ | |
| 1104 | − _tHighpass* f = *ft; | |
| 1105 | − f->frequency = freq; | |
| 1106 | − f->R = (1.0f - (freq * leaf.twoPiTimesInvSampleRate)); | |
| 1107 | − | |
| 1108 | −} | |
| 1109 | − | |
| 1110 | −float tHighpass_getFreq(tHighpass* const ft) | |
| 1111 | −{ | |
| 1112 | − _tHighpass* f = *ft; | |
| 1113 | − return f->frequency; | |
| 1114 | −} | |
| 1115 | − | |
| 1116 | −// From JOS DC Blocker | |
| 1117 | −float tHighpass_tick(tHighpass* const ft, float x) | |
| 1118 | −{ | |
| 1119 | − _tHighpass* f = *ft; | |
| 1120 | − f->ys = x - f->xs + f->R * f->ys; | |
| 1121 | − f->xs = x; | |
| 1122 | − return f->ys; | |
| 1123 | −} | |
| 1124 | − | |
| 1125 | −void tHighpassSampleRateChanged(tHighpass* const ft) | |
| 1126 | −{ | |
| 1127 | − _tHighpass* f = *ft; | |
| 1128 | − f->R = (1.0f-((f->frequency * 2.0f * 3.14f) * leaf.invSampleRate)); | |
| 1129 | −} | |
| 1130 | − | |
| 1131 | −void tButterworth_init(tButterworth* const ft, int N, float f1, float f2) | |
| 1132 | −{ | |
| 1133 | − _tButterworth* f = *ft = (_tButterworth*) leaf_alloc(sizeof(_tButterworth)); | |
| 1134 | − | |
| 1135 | − f->f1 = f1; | |
| 1136 | − f->f2 = f2; | |
| 1137 | − f->gain = 1.0f; | |
| 1138 | − | |
| 1139 | − f->N = N; | |
| 1140 | − | |
| 1141 | − if (f->N > NUM_SVF_BW) f->N = NUM_SVF_BW; | |
| 1142 | − | |
| 1143 | − for(int i = 0; i < N/2; ++i) | |
| 1144 | − { | |
| 1145 | − tSVF_init(&f->low[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N))); | |
| 1146 | − tSVF_init(&f->high[i], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N))); | |
| 1147 | − } | |
| 1148 | −} | |
| 1149 | − | |
| 1150 | −void tButterworth_free(tButterworth* const ft) | |
| 1151 | −{ | |
| 1152 | − _tButterworth* f = *ft; | |
| 1153 | − | |
| 1154 | − for(int i = 0; i < f->N/2; ++i) | |
| 1155 | − { | |
| 1156 | − tSVF_free(&f->low[i]); | |
| 1157 | − tSVF_free(&f->high[i]); | |
| 1158 | − } | |
| 1159 | − | |
| 1160 | − leaf_free((char*)f); | |
| 1161 | −} | |
| 1162 | − | |
| 1163 | −void tButterworth_initToPool (tButterworth* const ft, int N, float f1, float f2, tMempool* const mp) | |
| 1164 | −{ | |
| 1165 | − _tMempool* m = *mp; | |
| 1166 | − _tButterworth* f = *ft = (_tButterworth*) mpool_alloc(sizeof(_tButterworth), m); | |
| 1167 | − | |
| 1168 | − f->f1 = f1; | |
| 1169 | − f->f2 = f2; | |
| 1170 | − f->gain = 1.0f; | |
| 1171 | − | |
| 1172 | − f->N = N; | |
| 1173 | − | |
| 1174 | − if (f->N > NUM_SVF_BW) f->N = NUM_SVF_BW; | |
| 1175 | − | |
| 1176 | − for(int i = 0; i < N/2; ++i) | |
| 1177 | − { | |
| 1178 | − tSVF_initToPool(&f->low[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)), mp); | |
| 1179 | − tSVF_initToPool(&f->high[i], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)), mp); | |
| 1180 | − } | |
| 1181 | −} | |
| 1182 | − | |
| 1183 | −void tButterworth_freeFromPool (tButterworth* const ft, tMempool* const mp) | |
| 1184 | −{ | |
| 1185 | − _tMempool* m = *mp; | |
| 1186 | − _tButterworth* f = *ft; | |
| 1187 | − | |
| 1188 | − for(int i = 0; i < f->N/2; ++i) | |
| 1189 | − { | |
| 1190 | − tSVF_freeFromPool(&f->low[i], mp); | |
| 1191 | − tSVF_freeFromPool(&f->high[i], mp); | |
| 1192 | − } | |
| 1193 | − | |
| 1194 | − mpool_free((char*)f, m); | |
| 1195 | −} | |
| 1196 | − | |
| 1197 | −float tButterworth_tick(tButterworth* const ft, float samp) | |
| 1198 | −{ | |
| 1199 | − _tButterworth* f = *ft; | |
| 1200 | − | |
| 1201 | − for(int i = 0; i < ((f->N)/2); ++i) | |
| 1202 | − { | |
| 1203 | − samp = tSVF_tick(&f->low[i],samp); | |
| 1204 | − samp = tSVF_tick(&f->high[i],samp); | |
| 1205 | − } | |
| 1206 | − return samp; | |
| 1207 | −} | |
| 1208 | − | |
| 1209 | −void tButterworth_setF1(tButterworth* const ft, float f1) | |
| 1210 | −{ | |
| 1211 | − _tButterworth* f = *ft; | |
| 1212 | − | |
| 1213 | − f->f1 = f1; | |
| 1214 | − for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->low[i], f1); | |
| 1215 | −} | |
| 1216 | − | |
| 1217 | −void tButterworth_setF2(tButterworth* const ft, float f2) | |
| 1218 | −{ | |
| 1219 | − _tButterworth* f = *ft; | |
| 1220 | − | |
| 1221 | − f->f2 = f2; | |
| 1222 | − for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->high[i], f2); | |
| 1223 | −} | |
| 1224 | − | |
| 1225 | −void tButterworth_setFreqs(tButterworth* const ft, float f1, float f2) | |
| 1226 | −{ | |
| 1227 | − _tButterworth* f = *ft; | |
| 1228 | − | |
| 1229 | − f->f1 = f1; | |
| 1230 | − f->f2 = f2; | |
| 1231 | − for(int i = 0; i < ((f->N)/2); ++i) | |
| 1232 | − { | |
| 1233 | − tSVF_setFreq(&f->low[i], f1); | |
| 1234 | − tSVF_setFreq(&f->high[i], f2); | |
| 1235 | − } | |
| 1236 | −} | |
| 1237 | − | |
| 1238 | −void tFIR_init(tFIR* const firf, float* coeffs, int numTaps) | |
| 1239 | −{ | |
| 1240 | − _tFIR* fir = *firf = (_tFIR*) leaf_alloc(sizeof(_tFIR)); | |
| 1241 | − | |
| 1242 | − fir->numTaps = numTaps; | |
| 1243 | − fir->coeff = coeffs; | |
| 1244 | − fir->past = (float*)leaf_alloc(sizeof(float) * fir->numTaps); | |
| 1245 | − for (int i = 0; i < fir->numTaps; ++i) fir->past[i] = 0.0f; | |
| 1246 | −} | |
| 1247 | − | |
| 1248 | −void tFIR_free(tFIR* const firf) | |
| 1249 | −{ | |
| 1250 | − _tFIR* fir = *firf; | |
| 1251 | − | |
| 1252 | − leaf_free((char*)fir->past); | |
| 1253 | − leaf_free((char*)fir); | |
| 1254 | −} | |
| 1255 | − | |
| 1256 | −void tFIR_initToPool (tFIR* const firf, float* coeffs, int numTaps, tMempool* const mp) | |
| 1257 | −{ | |
| 1258 | − _tMempool* m = *mp; | |
| 1259 | − _tFIR* fir = *firf = (_tFIR*) mpool_alloc(sizeof(_tFIR), m); | |
| 1260 | − | |
| 1261 | − fir->numTaps = numTaps; | |
| 1262 | − fir->coeff = coeffs; | |
| 1263 | − fir->past = (float*) mpool_alloc(sizeof(float) * fir->numTaps, m); | |
| 1264 | − for (int i = 0; i < fir->numTaps; ++i) fir->past[i] = 0.0f; | |
| 1265 | −} | |
| 1266 | − | |
| 1267 | −void tFIR_freeFromPool (tFIR* const firf, tMempool* const mp) | |
| 1268 | −{ | |
| 1269 | − _tMempool* m = *mp; | |
| 1270 | − _tFIR* fir = *firf; | |
| 1271 | − | |
| 1272 | − mpool_free((char*)fir->past, m); | |
| 1273 | − mpool_free((char*)fir, m); | |
| 1274 | −} | |
| 1275 | − | |
| 1276 | −float tFIR_tick(tFIR* const firf, float input) | |
| 1277 | −{ | |
| 1278 | − _tFIR* fir = *firf; | |
| 1279 | − | |
| 1280 | − fir->past[0] = input; | |
| 1281 | − float y = 0.0f; | |
| 1282 | − for (int i = 0; i < fir->numTaps; ++i) y += fir->past[i]*fir->coeff[i]; | |
| 1283 | − for (int i = fir->numTaps-1; i > 0; --i) fir->past[i] = fir->past[i-1]; | |
| 1284 | − return y; | |
| 1285 | −} | |
| 1286 | − | |
| 1287 | −//--------------------------------------------- | |
| 1288 | −//// | |
| 1289 | −/// Median filter implemented based on James McCartney's median filter in Supercollider, | |
| 1290 | −/// translated from a Gen~ port of the Supercollider code that I believe was made by Rodrigo Costanzo and which I got from PA Tremblay - JS | |
| 1291 | − | |
| 1292 | − | |
| 1293 | −void tMedianFilter_init (tMedianFilter* const f, int size) | |
| 1294 | −{ | |
| 1295 | − tMedianFilter_initToPool(f, size, &leaf.mempool); | |
| 1296 | −} | |
| 1297 | −void tMedianFilter_free (tMedianFilter* const f) | |
| 1298 | −{ | |
| 1299 | − tMedianFilter_freeFromPool(f, &leaf.mempool); | |
| 1300 | −} | |
| 1301 | −void tMedianFilter_initToPool (tMedianFilter* const mf, int size, tMempool* const mp) | |
| 1302 | −{ | |
| 1303 | − _tMempool* m = *mp; | |
| 1304 | − _tMedianFilter* f = *mf = (_tMedianFilter*) mpool_alloc(sizeof(_tMedianFilter), m); | |
| 1305 | − | |
| 1306 | − f->size = size; | |
| 1307 | − f->middlePosition = size / 2; | |
| 1308 | − f->last = size - 1; | |
| 1309 | − f->pos = -1; | |
| 1310 | − f->val = (float*) mpool_alloc(sizeof(float) * size, m); | |
| 1311 | − f->age = (int*) mpool_alloc(sizeof(int) * size, m); | |
| 1312 | − for (int i = 0; i < f->size; ++i) | |
| 1313 | − { | |
| 1314 | − f->val[i] = 0.0f; | |
| 1315 | − f->age[i] = i; | |
| 1316 | − } | |
| 1317 | − | |
| 1318 | −} | |
| 1319 | −void tMedianFilter_freeFromPool (tMedianFilter* const mf, tMempool* const mp) | |
| 1320 | −{ | |
| 1321 | − _tMempool* m = *mp; | |
| 1322 | − _tMedianFilter* f = *mf; | |
| 1323 | − | |
| 1324 | − mpool_free((char*)f->val, m); | |
| 1325 | − mpool_free((char*)f->age, m); | |
| 1326 | − mpool_free((char*)f, m); | |
| 1327 | −} | |
| 1328 | − | |
| 1329 | −float tMedianFilter_tick (tMedianFilter* const mf, float input) | |
| 1330 | −{ | |
| 1331 | − _tMedianFilter* f = *mf; | |
| 1332 | − | |
| 1333 | − for(int i=0; i<f->size; i++) { | |
| 1334 | − int thisAge = f->age[i]; | |
| 1335 | − if(thisAge == f->last) { | |
| 1336 | − f->pos = i; | |
| 1337 | − } | |
| 1338 | − else { | |
| 1339 | − thisAge++; | |
| 1340 | − f->age[i] = thisAge; | |
| 1341 | − } | |
| 1342 | − } | |
| 1343 | − | |
| 1344 | − while( f->pos!=0 ) { | |
| 1345 | − float test = f->val[f->pos-1]; | |
| 1346 | − if(input < test) { | |
| 1347 | − f->val[f->pos]=test; | |
| 1348 | − f->age[f->pos]=f->age[f->pos-1]; | |
| 1349 | − f->pos -= 1; | |
| 1350 | − } else {break;} | |
| 1351 | − } | |
| 1352 | − | |
| 1353 | − while(f->pos != f->last) { | |
| 1354 | − float test = f->val[f->pos+1]; | |
| 1355 | − if( input > test) { | |
| 1356 | − f->val[f->pos] = test; | |
| 1357 | − f->age[f->pos] = f->age[f->pos+1]; | |
| 1358 | − f->pos += 1; | |
| 1359 | − } else {break;} | |
| 1360 | − } | |
| 1361 | − | |
| 1362 | − f->val[f->pos] = input; | |
| 1363 | − f->age[f->pos] = 0; | |
| 1364 | − | |
| 1365 | − return f->val[f->middlePosition]; | |
| 1366 | −} | |
| 1367 | − | |
| 1368 | −///// | |
| 1369 | − | |
| 1370 | −void tVZFilter_init (tVZFilter* const vf, VZFilterType type, float freq, float bandWidth) | |
| 1371 | −{ | |
| 1372 | − tVZFilter_initToPool(vf, type, freq, bandWidth, &leaf.mempool); | |
| 1373 | −} | |
| 1374 | − | |
| 1375 | −void tVZFilter_free (tVZFilter* const vf) | |
| 1376 | −{ | |
| 1377 | − tVZFilter_freeFromPool(vf, &leaf.mempool); | |
| 1378 | −} | |
| 1379 | −void tVZFilter_initToPool (tVZFilter* const vf, VZFilterType type, float freq, float bandWidth, tMempool* const mp) | |
| 1380 | −{ | |
| 1381 | − | |
| 1382 | − _tMempool* m = *mp; | |
| 1383 | − _tVZFilter* f = *vf = (_tVZFilter*) mpool_alloc(sizeof(_tVZFilter), m); | |
| 1384 | − f->fc = freq; | |
| 1385 | − f->type = type; | |
| 1386 | − f->G = ONE_OVER_SQRT2; | |
| 1387 | − f->invG = 1.0f/ONE_OVER_SQRT2; | |
| 1388 | − f->B = bandWidth; | |
| 1389 | − f->m = 0.0f; | |
| 1390 | − f->s1 = 0.0f; | |
| 1391 | − f->s2 = 0.0f; | |
| 1392 | − f->sr = leaf.sampleRate; | |
| 1393 | − f->inv_sr = leaf.invSampleRate; | |
| 1394 | − tVZFilter_calcCoeffs(vf); | |
| 1395 | − | |
| 1396 | − | |
| 1397 | −} | |
| 1398 | −void tVZFilter_freeFromPool (tVZFilter* const vf, tMempool* const mp) | |
| 1399 | −{ | |
| 1400 | − _tMempool* m = *mp; | |
| 1401 | − _tVZFilter* f = *vf = (_tVZFilter*) mpool_alloc(sizeof(_tVZFilter), m); | |
| 1402 | − mpool_free((char*)f, m); | |
| 1403 | −} | |
| 1404 | − | |
| 1405 | −void tVZFilter_setSampleRate (tVZFilter* const vf, float sampleRate) | |
| 1406 | −{ | |
| 1407 | − _tVZFilter* f = *vf; | |
| 1408 | − f->sr = sampleRate; | |
| 1409 | − f->inv_sr = 1.0f/sampleRate; | |
| 1410 | −} | |
| 1411 | − | |
| 1412 | −float tVZFilter_tick (tVZFilter* const vf, float in) | |
| 1413 | −{ | |
| 1414 | − _tVZFilter* f = *vf; | |
| 1415 | − | |
| 1416 | − float yL, yB, yH; | |
| 1417 | − | |
| 1418 | − // compute highpass output via Eq. 5.1: | |
| 1419 | − yH = (in - f->R2*f->s1 - f->g*f->s1 - f->s2) * f->h; | |
| 1420 | − | |
| 1421 | − // compute bandpass output by applying 1st integrator to highpass output: | |
| 1422 | − yB = tanhf(f->g*yH) + f->s1; | |
| 1423 | − f->s1 = f->g*yH + yB; // state update in 1st integrator | |
| 1424 | − | |
| 1425 | − // compute lowpass output by applying 2nd integrator to bandpass output: | |
| 1426 | − yL = tanhf(f->g*yB) + f->s2; | |
| 1427 | − f->s2 = f->g*yB + yL; // state update in 2nd integrator | |
| 1428 | − | |
| 1429 | − //according to the Vadim paper, we could add saturation to this model by adding a tanh in the integration stage. | |
| 1430 | − // | |
| 1431 | − //seems like that might look like this: | |
| 1432 | − // y = tanh(g*x) + s; // output computation | |
| 1433 | − // s = g*x + y; // state update | |
| 1434 | − | |
| 1435 | − //instead of this: | |
| 1436 | − // y = g*x + s; // output computation | |
| 1437 | − // s = g*x + y; // state update | |
| 1438 | − | |
| 1439 | − return f->cL*yL + f->cB*yB + f->cH*yH; | |
| 1440 | − | |
| 1441 | −} | |
| 1442 | − | |
| 1443 | −float tVZFilter_tickEfficient (tVZFilter* const vf, float in) | |
| 1444 | −{ | |
| 1445 | − _tVZFilter* f = *vf; | |
| 1446 | − | |
| 1447 | − float yL, yB, yH; | |
| 1448 | − | |
| 1449 | − // compute highpass output via Eq. 5.1: | |
| 1450 | − yH = (in - f->R2*f->s1 - f->g*f->s1 - f->s2) * f->h; | |
| 1451 | − | |
| 1452 | − // compute bandpass output by applying 1st integrator to highpass output: | |
| 1453 | − yB = (f->g*yH) + f->s1; | |
| 1454 | − f->s1 = f->g*yH + yB; // state update in 1st integrator | |
| 1455 | − | |
| 1456 | − // compute lowpass output by applying 2nd integrator to bandpass output: | |
| 1457 | − yL = (f->g*yB) + f->s2; | |
| 1458 | − f->s2 = f->g*yB + yL; // state update in 2nd integrator | |
| 1459 | − | |
| 1460 | − //according to the Vadim paper, we could add saturation to this model by adding a tanh in the integration stage. | |
| 1461 | − // | |
| 1462 | − //seems like that might look like this: | |
| 1463 | − // y = tanh(g*x) + s; // output computation | |
| 1464 | − // s = g*x + y; // state update | |
| 1465 | − | |
| 1466 | − //instead of this: | |
| 1467 | − // y = g*x + s; // output computation | |
| 1468 | − // s = g*x + y; // state update | |
| 1469 | − | |
| 1470 | − return f->cL*yL + f->cB*yB + f->cH*yH; | |
| 1471 | − | |
| 1472 | −} | |
| 1473 | − | |
| 1474 | −float tVZFilter_tickEfficientBP (tVZFilter* const vf, float in) | |
| 1475 | −{ | |
| 1476 | − _tVZFilter* f = *vf; | |
| 1477 | − | |
| 1478 | − float yL, yB, yH; | |
| 1479 | − | |
| 1480 | − // compute highpass output via Eq. 5.1: | |
| 1481 | − yH = (in - f->R2*f->s1 - f->g*f->s1 - f->s2) * f->h; | |
| 1482 | − | |
| 1483 | − // compute bandpass output by applying 1st integrator to highpass output: | |
| 1484 | − yB = (f->g*yH) + f->s1; | |
| 1485 | − f->s1 = f->g*yH + yB; // state update in 1st integrator | |
| 1486 | − | |
| 1487 | − // compute lowpass output by applying 2nd integrator to bandpass output: | |
| 1488 | − yL = (f->g*yB) + f->s2; | |
| 1489 | − f->s2 = f->g*yB + yL; // state update in 2nd integrator | |
| 1490 | − | |
| 1491 | − //according to the Vadim paper, we could add saturation to this model by adding a tanh in the integration stage. | |
| 1492 | − // | |
| 1493 | − //seems like that might look like this: | |
| 1494 | − // y = tanh(g*x) + s; // output computation | |
| 1495 | − // s = g*x + y; // state update | |
| 1496 | − | |
| 1497 | − //instead of this: | |
| 1498 | − // y = g*x + s; // output computation | |
| 1499 | − // s = g*x + y; // state update | |
| 1500 | − | |
| 1501 | − return f->cL*yL + f->cB*yB + f->cH*yH; | |
| 1502 | − | |
| 1503 | −} | |
| 1504 | − | |
| 1505 | − | |
| 1506 | −void tVZFilter_calcCoeffs (tVZFilter* const vf) | |
| 1507 | −{ | |
| 1508 | − | |
| 1509 | − _tVZFilter* f = *vf; | |
| 1510 | − f->g = tanf(PI * f->fc * f->inv_sr); // embedded integrator gain (Fig 3.11) | |
| 1511 | − | |
| 1512 | − switch( f->type ) | |
| 1513 | − { | |
| 1514 | − case Bypass: | |
| 1515 | − { | |
| 1516 | − f->R2 = f->invG; // can we use an arbitrary value here, for example R2 = 1? | |
| 1517 | − f->cL = 1.0f; | |
| 1518 | − f->cB = f->R2; | |
| 1519 | − f->cH = 1.0f; | |
| 1520 | − } | |
| 1521 | − break; | |
| 1522 | − case Lowpass: | |
| 1523 | − { | |
| 1524 | − f->R2 = f->invG; | |
| 1525 | − f->cL = 1.0f; f->cB = 0.0f; f->cH = 0.0f; | |
| 1526 | − } | |
| 1527 | − break; | |
| 1528 | − case Highpass: | |
| 1529 | − { | |
| 1530 | − f->R2 = f->invG; | |
| 1531 | − f->cL = 0.0f; f->cB = 0.0f; f->cH = 1.0f; | |
| 1532 | − } | |
| 1533 | − break; | |
| 1534 | − case BandpassSkirt: | |
| 1535 | − { | |
| 1536 | − f->R2 = f->invG; | |
| 1537 | − f->cL = 0.0f; f->cB = 1.0f; f->cH = 0.0f; | |
| 1538 | − } | |
| 1539 | − break; | |
| 1540 | − case BandpassPeak: | |
| 1541 | − { | |
| 1542 | − f->R2 = 2.0f*tVZFilter_BandwidthToR(vf, f->B); | |
| 1543 | − f->cL = 0.0f; f->cB = f->R2; f->cH = 0.0f; | |
| 1544 | − } | |
| 1545 | − break; | |
| 1546 | − case BandReject: | |
| 1547 | − { | |
| 1548 | − f->R2 = 2.0f*tVZFilter_BandwidthToR(vf, f->B); | |
| 1549 | − f->cL = 1.0f; f->cB = 0.0f; f->cH = 1.0f; | |
| 1550 | − } | |
| 1551 | − break; | |
| 1552 | − case Bell: | |
| 1553 | − { | |
| 1554 | − float fl = f->fc*powf(2.0f, (-f->B)*0.5f); // lower bandedge frequency (in Hz) | |
| 1555 | − float wl = tanf(PI*fl*f->inv_sr); // warped radian lower bandedge frequency /(2*fs) | |
| 1556 | − float r = f->g/wl; | |
| 1557 | − r *= r; // warped frequency ratio wu/wl == (wc/wl)^2 where wu is the | |
| 1558 | − // warped upper bandedge, wc the center | |
| 1559 | − f->R2 = 2.0f*sqrtf(((r*r+1.0f)/r-2.0f)/(4.0f*f->G)); | |
| 1560 | − f->cL = 1.0f; f->cB = f->R2*f->G; f->cH = 1.0f; | |
| 1561 | − } | |
| 1562 | − break; | |
| 1563 | − case Lowshelf: | |
| 1564 | − { | |
| 1565 | − float A = sqrtf(f->G); | |
| 1566 | − f->g /= sqrtf(A); // scale SVF-cutoff frequency for shelvers | |
| 1567 | − f->R2 = 2*sinhf(f->B*logf(2.0f)*0.5f); | |
| 1568 | − f->cL = f->G; f->cB = f->R2*A; f->cH = 1.0f; | |
| 1569 | − } | |
| 1570 | − break; | |
| 1571 | − case Highshelf: | |
| 1572 | − { | |
| 1573 | − float A = sqrtf(f->G); | |
| 1574 | − f->g *= sqrtf(A); // scale SVF-cutoff frequency for shelvers | |
| 1575 | − f->R2 = 2.0f*sinhf(f->B*logf(2.0f)*0.5f); | |
| 1576 | − f->cL = 1.0f; f->cB = f->R2*A; f->cH = f->G; | |
| 1577 | − } | |
| 1578 | − break; | |
| 1579 | − case Allpass: | |
| 1580 | − { | |
| 1581 | − f->R2 = 2.0f*tVZFilter_BandwidthToR(vf, f->B); | |
| 1582 | − f->cL = 1.0f; f->cB = -f->R2; f->cH = 1.0f; | |
| 1583 | − } | |
| 1584 | − break; | |
| 1585 | − | |
| 1586 | − // experimental - maybe we must find better curves for cL, cB, cH: | |
| 1587 | − case Morph: | |
| 1588 | − { | |
| 1589 | − f->R2 = f->invG; | |
| 1590 | − float x = 2.0f*f->m-1.0f; | |
| 1591 | − | |
| 1592 | − f->cL = maximum(-x, 0.0f); /*cL *= cL;*/ | |
| 1593 | − f->cH = minimum( x, 0.0f); /*cH *= cH;*/ | |
| 1594 | − f->cB = 1.0f-x*x; | |
| 1595 | − | |
| 1596 | − // bottom line: we need to test different versions for how they feel when tweaking the | |
| 1597 | − // morph parameter | |
| 1598 | − | |
| 1599 | − // this scaling ensures constant magnitude at the cutoff point (we divide the coefficients by | |
| 1600 | − // the magnitude response value at the cutoff frequency and scale back by the gain): | |
| 1601 | − float s = f->G * sqrtf((f->R2*f->R2) / (f->cL*f->cL + f->cB*f->cB + f->cH*f->cH - 2.0f*f->cL*f->cH)); | |
| 1602 | − f->cL *= s; f->cB *= s; f->cH *= s; | |
| 1603 | − } | |
| 1604 | − break; | |
| 1605 | − | |
| 1606 | − } | |
| 1607 | − | |
| 1608 | − f->h = 1.0f / (1.0f + f->R2*f->g + f->g*f->g); // factor for feedback precomputation | |
| 1609 | −} | |
| 1610 | − | |
| 1611 | − | |
| 1612 | −void tVZFilter_setBandwidth (tVZFilter* const vf, float B) | |
| 1613 | −{ | |
| 1614 | − _tVZFilter* f = *vf; | |
| 1615 | − f->B = LEAF_clip(0.0f, B, 100.0f); | |
| 1616 | − tVZFilter_calcCoeffs(vf); | |
| 1617 | −} | |
| 1618 | −void tVZFilter_setFreq (tVZFilter* const vf, float freq) | |
| 1619 | −{ | |
| 1620 | − _tVZFilter* f = *vf; | |
| 1621 | − f->fc = LEAF_clip(0.0f, freq, 0.5f*leaf.sampleRate); | |
| 1622 | − tVZFilter_calcCoeffs(vf); | |
| 1623 | −} | |
| 1624 | −void tVZFilter_setFreqAndBandwidth (tVZFilter* const vf, float freq, float bw) | |
| 1625 | −{ | |
| 1626 | − _tVZFilter* f = *vf; | |
| 1627 | − f->B = LEAF_clip(0.0f,bw, 100.0f); | |
| 1628 | − f->fc = LEAF_clip(0.0f, freq, 0.5f*leaf.sampleRate); | |
| 1629 | − tVZFilter_calcCoeffs(vf); | |
| 1630 | −} | |
| 1631 | − | |
| 1632 | −void tVZFilter_setGain (tVZFilter* const vf, float gain) | |
| 1633 | −{ | |
| 1634 | − _tVZFilter* f = *vf; | |
| 1635 | − f->G = LEAF_clip(0.000001f, gain, 100.0f); | |
| 1636 | − f->invG = 1.0f/f->G; | |
| 1637 | − tVZFilter_calcCoeffs(vf); | |
| 1638 | −} | |
| 1639 | − | |
| 1640 | −void tVZFilter_setMorph (tVZFilter* const vf, float morph) | |
| 1641 | −{ | |
| 1642 | − _tVZFilter* f = *vf; | |
| 1643 | − f->m = LEAF_clip(0.0f, morph, 1.0f); | |
| 1644 | − tVZFilter_calcCoeffs(vf); | |
| 1645 | −} | |
| 1646 | − | |
| 1647 | −void tVZFilter_setType (tVZFilter* const vf, VZFilterType type) | |
| 1648 | −{ | |
| 1649 | − _tVZFilter* f = *vf; | |
| 1650 | − f->type = type; | |
| 1651 | − tVZFilter_calcCoeffs(vf); | |
| 1652 | −} | |
| 1653 | − | |
| 1654 | −float tVZFilter_BandwidthToR(tVZFilter* const vf, float B) | |
| 1655 | −{ | |
| 1656 | − _tVZFilter* f = *vf; | |
| 1657 | − float fl = f->fc*powf(2.0f, -B*0.5f); // lower bandedge frequency (in Hz) | |
| 1658 | − float gl = tanf(PI*fl*f->inv_sr); // warped radian lower bandedge frequency /(2*fs) | |
| 1659 | − float r = gl/f->g; // ratio between warped lower bandedge- and center-frequencies | |
| 1660 | − // unwarped: r = pow(2, -B/2) -> approximation for low | |
| 1661 | − // center-frequencies | |
| 1662 | − return sqrtf((1.0f-r*r)*(1.0f-r*r)/(4.0f*r*r)); | |
| 1663 | −} | |
| 1664 | − | |
| 1665 | − | |
| 1666 | − | |
| 1667 | −void tDiodeFilter_init (tDiodeFilter* const vf, float cutoff, float resonance) | |
| 1668 | −{ | |
| 1669 | − tDiodeFilter_initToPool(vf, cutoff, resonance, &leaf.mempool); | |
| 1670 | −} | |
| 1671 | − | |
| 1672 | −void tDiodeFilter_free (tDiodeFilter* const vf) | |
| 1673 | −{ | |
| 1674 | − tDiodeFilter_freeFromPool(vf, &leaf.mempool); | |
| 1675 | −} | |
| 1676 | −void tDiodeFilter_initToPool (tDiodeFilter* const vf, float cutoff, float resonance, tMempool* const mp) | |
| 1677 | −{ | |
| 1678 | − | |
| 1679 | − _tMempool* m = *mp; | |
| 1680 | − _tDiodeFilter* f = *vf = (_tDiodeFilter*) mpool_alloc(sizeof(_tDiodeFilter), m); | |
| 1681 | − // initialization (the resonance factor is between 0 and 8 according to the article) | |
| 1682 | − f->f = tan(PI * cutoff/leaf.sampleRate); | |
| 1683 | − f->r = (7.f * resonance + 0.5f); | |
| 1684 | − f->Vt = 0.5f; | |
| 1685 | − f->n = 1.836f; | |
| 1686 | − f->zi = 0.0f; //previous input value | |
| 1687 | − f->gamma = f->Vt*f->n; | |
| 1688 | − f->s0 = 0.01f; | |
| 1689 | − f->s1 = 0.02f; | |
| 1690 | − f->s2 = 0.03f; | |
| 1691 | − f->s3 = 0.04f; | |
| 1692 | − f->g0inv = 1.f/(2.f*f->Vt); | |
| 1693 | − f->g1inv = 1.f/(2.f*f->gamma); | |
| 1694 | − f->g2inv = 1.f/(6.f*f->gamma); | |
| 1695 | − | |
| 1696 | − | |
| 1697 | −} | |
| 1698 | −void tDiodeFilter_freeFromPool (tDiodeFilter* const vf, tMempool* const mp) | |
| 1699 | −{ | |
| 1700 | − _tMempool* m = *mp; | |
| 1701 | − _tDiodeFilter* f = *vf = (_tDiodeFilter*) mpool_alloc(sizeof(_tDiodeFilter), m); | |
| 1702 | − mpool_free((char*)f, m); | |
| 1703 | −} | |
| 1704 | − | |
| 1705 | −float tanhXdX(float x) | |
| 1706 | −{ | |
| 1707 | − float a = x*x; | |
| 1708 | − // IIRC I got this as Pade-approx for tanh(sqrt(x))/sqrt(x) | |
| 1709 | − return ((a + 105.0f)*a + 945.0f) / ((15.0f*a + 420.0f)*a + 945.0f); | |
| 1710 | −} | |
| 1711 | − | |
| 1712 | −float tDiodeFilter_tick (tDiodeFilter* const vf, float in) | |
| 1713 | −{ | |
| 1714 | − _tDiodeFilter* f = *vf; | |
| 1715 | − | |
| 1716 | − // the input x[n+1] is given by 'in', and x[n] by zi | |
| 1717 | − // input with half delay | |
| 1718 | − float ih = 0.5f * (in + f->zi); | |
| 1719 | − | |
| 1720 | − // evaluate the non-linear factors | |
| 1721 | − float t0 = f->f*tanhXdX((ih - f->r * f->s3)*f->g0inv)*f->g0inv; | |
| 1722 | − float t1 = f->f*tanhXdX((f->s1-f->s0)*f->g1inv)*f->g1inv; | |
| 1723 | − float t2 = f->f*tanhXdX((f->s2-f->s1)*f->g1inv)*f->g1inv; | |
| 1724 | − float t3 = f->f*tanhXdX((f->s3-f->s2)*f->g1inv)*f->g1inv; | |
| 1725 | − float t4 = f->f*tanhXdX((f->s3)*f->g2inv)*f->g2inv; | |
| 1726 | − | |
| 1727 | − | |
| 1728 | − | |
| 1729 | − // This formula gives the result for y3 thanks to MATLAB | |
| 1730 | − float y3 = (f->s2 + f->s3 + t2*(f->s1 + f->s2 + f->s3 + t1*(f->s0 + f->s1 + f->s2 + f->s3 + t0*in)) + t1*(2.0f*f->s2 + 2.0f*f->s3))*t3 + f->s3 + 2.0f*f->s3*t1 + t2*(2.0f*f->s3 + 3.0f*f->s3*t1); | |
| 1731 | −// if (isnan(y3)) | |
| 1732 | −// { | |
| 1733 | −// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400); | |
| 1734 | −// } | |
| 1735 | − float tempy3denom = (t4 + t1*(2.0f*t4 + 4.0f) + t2*(t4 + t1*(t4 + f->r*t0 + 4.0f) + 3.0f) + 2.0f)*t3 + t4 + t1*(2.0f*t4 + 2.0f) + t2*(2.0f*t4 + t1*(3.0f*t4 + 3.0f) + 2.0f) + 1.0f; | |
| 1736 | −// if (isnan(tempy3denom)) | |
| 1737 | −// { | |
| 1738 | −// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400); | |
| 1739 | −// } | |
| 1740 | − if (tempy3denom == 0.0f) | |
| 1741 | − { | |
| 1742 | − tempy3denom = 0.000001f; | |
| 1743 | − } | |
| 1744 | − y3 = y3 / tempy3denom; | |
| 1745 | −// if (isnan(y3)) | |
| 1746 | −// { | |
| 1747 | −// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400); | |
| 1748 | −// } | |
| 1749 | − if (t1 == 0.0f) | |
| 1750 | − { | |
| 1751 | − t1 = 0.000001f; | |
| 1752 | − } | |
| 1753 | − if (t2 == 0.0f) | |
| 1754 | − { | |
| 1755 | − t2 = 0.000001f; | |
| 1756 | − } | |
| 1757 | − if (t3 == 0.0f) | |
| 1758 | − { | |
| 1759 | − t3 = 0.000001f; | |
| 1760 | − } | |
| 1761 | − // Other outputs | |
| 1762 | − float y2 = (f->s3 - (1+t4+t3)*y3) / (-t3); | |
| 1763 | − float y1 = (f->s2 - (1+t3+t2)*y2 + t3*y3) / (-t2); | |
| 1764 | − float y0 = (f->s1 - (1+t2+t1)*y1 + t2*y2) / (-t1); | |
| 1765 | − float xx = (in - f->r*y3); | |
| 1766 | − | |
| 1767 | − // update state | |
| 1768 | − f->s0 += 2.0f * (t0*xx + t1*(y1-y0)); | |
| 1769 | −// if (isnan(f->s0)) | |
| 1770 | −// { | |
| 1771 | −// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400); | |
| 1772 | −// } | |
| 1773 | − | |
| 1774 | −// if (isinf(f->s0)) | |
| 1775 | −// { | |
| 1776 | −// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400); | |
| 1777 | −// } | |
| 1778 | − f->s1 += 2.0f * (t2*(y2-y1) - t1*(y1-y0)); | |
| 1779 | − f->s2 += 2.0f * (t3*(y3-y2) - t2*(y2-y1)); | |
| 1780 | − f->s3 += 2.0f * (-t4*(y3) - t3*(y3-y2)); | |
| 1781 | − | |
| 1782 | − f->zi = in; | |
| 1783 | − return y3*f->r; | |
| 1784 | − | |
| 1785 | −} | |
| 1786 | − | |
| 1787 | − | |
| 1788 | − | |
| 1789 | −void tDiodeFilter_setFreq (tDiodeFilter* const vf, float cutoff) | |
| 1790 | −{ | |
| 1791 | − _tDiodeFilter* f = *vf; | |
| 1792 | − f->f = tanf(PI * LEAF_clip(10.0f, cutoff, 20000.0f)*leaf.invSampleRate); | |
| 1793 | −} | |
| 1794 | − | |
| 1795 | − | |
| 1796 | −void tDiodeFilter_setQ (tDiodeFilter* const vf, float resonance) | |
| 1797 | −{ | |
| 1798 | − _tDiodeFilter* f = *vf; | |
| 1799 | − f->r = LEAF_clip(0.5, (7.f * resonance + 0.5f), 8.0f); | |
| 1800 | − | |
| 1801 | −} | |
| 1802 | − | |
| @@ -1,706 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-instruments.c | |
| 4 | − Created: 30 Nov 2018 10:24:21am | |
| 5 | − Author: airship | |
| 6 | − | |
| 7 | −==============================================================================*/ | |
| 8 | − | |
| 9 | −#if _WIN32 || _WIN64 | |
| 10 | − | |
| 11 | −#include "..\Inc\leaf-instruments.h" | |
| 12 | − | |
| 13 | −#else | |
| 14 | − | |
| 15 | −#include "../Inc/leaf-instruments.h" | |
| 16 | − | |
| 17 | −#endif | |
| 18 | − | |
| 19 | −// ----------------- COWBELL ----------------------------// | |
| 20 | − | |
| 21 | −void t808Cowbell_init(t808Cowbell* const cowbellInst, int useStick) | |
| 22 | −{ | |
| 23 | − _t808Cowbell* cowbell = *cowbellInst = (_t808Cowbell*) leaf_alloc(sizeof(_t808Cowbell)); | |
| 24 | − | |
| 25 | − tSquare_init(&cowbell->p[0]); | |
| 26 | − tSquare_setFreq(&cowbell->p[0], 540.0f); | |
| 27 | − | |
| 28 | − tSquare_init(&cowbell->p[1]); | |
| 29 | − tSquare_setFreq(&cowbell->p[1], 1.48148f * 540.0f); | |
| 30 | − | |
| 31 | − cowbell->oscMix = 0.5f; | |
| 32 | − | |
| 33 | − tSVF_init(&cowbell->bandpassOsc, SVFTypeBandpass, 2500, 1.0f); | |
| 34 | − | |
| 35 | − tSVF_init(&cowbell->bandpassStick, SVFTypeBandpass, 1800, 1.0f); | |
| 36 | − | |
| 37 | − tEnvelope_init(&cowbell->envGain, 5.0f, 100.0f, OFALSE); | |
| 38 | − | |
| 39 | − tEnvelope_init(&cowbell->envFilter, 5.0, 100.0f, OFALSE); | |
| 40 | − | |
| 41 | − tHighpass_init(&cowbell->highpass, 1000.0f); | |
| 42 | − | |
| 43 | − tNoise_init(&cowbell->stick, WhiteNoise); | |
| 44 | − | |
| 45 | − tEnvelope_init(&cowbell->envStick, 5.0f, 5.0f, 0); | |
| 46 | − | |
| 47 | − cowbell->useStick = useStick; | |
| 48 | −} | |
| 49 | − | |
| 50 | −void t808Cowebell_free(t808Cowbell* const cowbellInst) | |
| 51 | −{ | |
| 52 | − _t808Cowbell* cowbell = *cowbellInst; | |
| 53 | − | |
| 54 | − tSquare_free(&cowbell->p[0]); | |
| 55 | − tSquare_free(&cowbell->p[1]); | |
| 56 | − tSVF_free(&cowbell->bandpassOsc); | |
| 57 | − tSVF_free(&cowbell->bandpassStick); | |
| 58 | − tEnvelope_free(&cowbell->envGain); | |
| 59 | − tEnvelope_free(&cowbell->envFilter); | |
| 60 | − tHighpass_free(&cowbell->highpass); | |
| 61 | − tNoise_free(&cowbell->stick); | |
| 62 | − tEnvelope_free(&cowbell->envStick); | |
| 63 | − leaf_free((char*)cowbell); | |
| 64 | −} | |
| 65 | − | |
| 66 | −void t808Cowbell_initToPool (t808Cowbell* const cowbellInst, int useStick, tMempool* const mp) | |
| 67 | −{ | |
| 68 | − _tMempool* m = *mp; | |
| 69 | − _t808Cowbell* cowbell = *cowbellInst = (_t808Cowbell*) mpool_alloc(sizeof(_t808Cowbell), m); | |
| 70 | − | |
| 71 | − tSquare_initToPool(&cowbell->p[0], mp); | |
| 72 | − tSquare_setFreq(&cowbell->p[0], 540.0f); | |
| 73 | − | |
| 74 | − tSquare_initToPool(&cowbell->p[1], mp); | |
| 75 | − tSquare_setFreq(&cowbell->p[1], 1.48148f * 540.0f); | |
| 76 | − | |
| 77 | − cowbell->oscMix = 0.5f; | |
| 78 | − | |
| 79 | − tSVF_initToPool(&cowbell->bandpassOsc, SVFTypeBandpass, 2500, 1.0f, mp); | |
| 80 | − | |
| 81 | − tSVF_initToPool(&cowbell->bandpassStick, SVFTypeBandpass, 1800, 1.0f, mp); | |
| 82 | − | |
| 83 | − tEnvelope_initToPool(&cowbell->envGain, 5.0f, 100.0f, OFALSE, mp); | |
| 84 | − | |
| 85 | − tEnvelope_initToPool(&cowbell->envFilter, 5.0, 100.0f, OFALSE, mp); | |
| 86 | − | |
| 87 | − tHighpass_initToPool(&cowbell->highpass, 1000.0f, mp); | |
| 88 | − | |
| 89 | − tNoise_initToPool(&cowbell->stick, WhiteNoise, mp); | |
| 90 | − | |
| 91 | − tEnvelope_initToPool(&cowbell->envStick, 5.0f, 5.0f, 0, mp); | |
| 92 | − | |
| 93 | − cowbell->useStick = useStick; | |
| 94 | −} | |
| 95 | − | |
| 96 | −void t808Cowbell_freeFromPool (t808Cowbell* const cowbellInst, tMempool* const mp) | |
| 97 | −{ | |
| 98 | − _tMempool* m = *mp; | |
| 99 | − _t808Cowbell* cowbell = *cowbellInst; | |
| 100 | − | |
| 101 | − tSquare_freeFromPool(&cowbell->p[0], mp); | |
| 102 | − tSquare_freeFromPool(&cowbell->p[1], mp); | |
| 103 | − tSVF_freeFromPool(&cowbell->bandpassOsc, mp); | |
| 104 | − tSVF_freeFromPool(&cowbell->bandpassStick, mp); | |
| 105 | − tEnvelope_freeFromPool(&cowbell->envGain, mp); | |
| 106 | − tEnvelope_freeFromPool(&cowbell->envFilter, mp); | |
| 107 | − tHighpass_freeFromPool(&cowbell->highpass, mp); | |
| 108 | − tNoise_freeFromPool(&cowbell->stick, mp); | |
| 109 | − tEnvelope_freeFromPool(&cowbell->envStick, mp); | |
| 110 | − mpool_free((char*)cowbell, m); | |
| 111 | −} | |
| 112 | − | |
| 113 | −void t808Cowbell_on(t808Cowbell* const cowbellInst, float vel) | |
| 114 | −{ | |
| 115 | − _t808Cowbell* cowbell = *cowbellInst; | |
| 116 | − | |
| 117 | − tEnvelope_on(&cowbell->envGain, vel); | |
| 118 | − | |
| 119 | − if (cowbell->useStick) | |
| 120 | − tEnvelope_on(&cowbell->envStick,vel); | |
| 121 | −} | |
| 122 | − | |
| 123 | −float t808Cowbell_tick(t808Cowbell* const cowbellInst) | |
| 124 | −{ | |
| 125 | − _t808Cowbell* cowbell = *cowbellInst; | |
| 126 | − | |
| 127 | − float sample = 0.0f; | |
| 128 | − | |
| 129 | − // Mix oscillators. | |
| 130 | − sample = (cowbell->oscMix * tSquare_tick(&cowbell->p[0])) + ((1.0f-cowbell->oscMix) * tSquare_tick(&cowbell->p[1])); | |
| 131 | − | |
| 132 | − // Filter dive and filter. | |
| 133 | − tSVF_setFreq(&cowbell->bandpassOsc, cowbell->filterCutoff + 1000.0f * tEnvelope_tick(&cowbell->envFilter)); | |
| 134 | − sample = tSVF_tick(&cowbell->bandpassOsc,sample); | |
| 135 | − | |
| 136 | − sample *= (0.9f * tEnvelope_tick(&cowbell->envGain)); | |
| 137 | − | |
| 138 | − if (cowbell->useStick) | |
| 139 | − sample += (0.1f * tEnvelope_tick(&cowbell->envStick) * tSVF_tick(&cowbell->bandpassStick, tNoise_tick(&cowbell->stick))); | |
| 140 | − | |
| 141 | − | |
| 142 | − sample = tHighpass_tick(&cowbell->highpass, sample); | |
| 143 | − | |
| 144 | − return sample; | |
| 145 | −} | |
| 146 | − | |
| 147 | −void t808Cowbell_setDecay(t808Cowbell* const cowbellInst, float decay) | |
| 148 | −{ | |
| 149 | − _t808Cowbell* cowbell = *cowbellInst; | |
| 150 | − tEnvelope_setDecay(&cowbell->envGain,decay); | |
| 151 | −} | |
| 152 | − | |
| 153 | −void t808Cowbell_setHighpassFreq(t808Cowbell *cowbellInst, float freq) | |
| 154 | −{ | |
| 155 | − _t808Cowbell* cowbell = *cowbellInst; | |
| 156 | − tHighpass_setFreq(&cowbell->highpass,freq); | |
| 157 | −} | |
| 158 | − | |
| 159 | −void t808Cowbell_setBandpassFreq(t808Cowbell* const cowbellInst, float freq) | |
| 160 | −{ | |
| 161 | − _t808Cowbell* cowbell = *cowbellInst; | |
| 162 | − cowbell->filterCutoff = freq; | |
| 163 | −} | |
| 164 | − | |
| 165 | −void t808Cowbell_setFreq(t808Cowbell* const cowbellInst, float freq) | |
| 166 | −{ | |
| 167 | − _t808Cowbell* cowbell = *cowbellInst; | |
| 168 | − tSquare_setFreq(&cowbell->p[0],freq); | |
| 169 | − tSquare_setFreq(&cowbell->p[1],1.48148f*freq); | |
| 170 | −} | |
| 171 | − | |
| 172 | −void t808Cowbell_setOscMix(t808Cowbell* const cowbellInst, float oscMix) | |
| 173 | −{ | |
| 174 | − _t808Cowbell* cowbell = *cowbellInst; | |
| 175 | − cowbell->oscMix = oscMix; | |
| 176 | −} | |
| 177 | − | |
| 178 | −void t808Cowbell_setStick(t808Cowbell* const cowbellInst, int useStick) | |
| 179 | −{ | |
| 180 | − _t808Cowbell* cowbell = *cowbellInst; | |
| 181 | − cowbell->useStick = useStick; | |
| 182 | −} | |
| 183 | − | |
| 184 | −// ----------------- HIHAT ----------------------------// | |
| 185 | − | |
| 186 | −void t808Hihat_init(t808Hihat* const hihatInst) | |
| 187 | −{ | |
| 188 | − _t808Hihat* hihat = *hihatInst = (_t808Hihat*) leaf_alloc(sizeof(_t808Hihat)); | |
| 189 | − | |
| 190 | − for (int i = 0; i < 6; i++) | |
| 191 | − { | |
| 192 | − tSquare_init(&hihat->p[i]); | |
| 193 | − } | |
| 194 | − | |
| 195 | − tNoise_init(&hihat->stick, PinkNoise); | |
| 196 | − tNoise_init(&hihat->n, WhiteNoise); | |
| 197 | − | |
| 198 | − // need to fix SVF to be generic | |
| 199 | − tSVF_init(&hihat->bandpassStick, SVFTypeBandpass,2500.0f,1.2f); | |
| 200 | − tSVF_init(&hihat->bandpassOsc, SVFTypeBandpass,3500.0f,0.3f); | |
| 201 | − | |
| 202 | − tEnvelope_init(&hihat->envGain, 0.0f, 50.0f, OFALSE); | |
| 203 | − tEnvelope_init(&hihat->envStick, 0.0f, 7.0f, OFALSE); | |
| 204 | − | |
| 205 | − | |
| 206 | − tHighpass_init(&hihat->highpass, 7000.0f); | |
| 207 | − | |
| 208 | − hihat->freq = 40.0f; | |
| 209 | − hihat->stretch = 0.0f; | |
| 210 | − | |
| 211 | − tSquare_setFreq(&hihat->p[0], 2.0f * hihat->freq); | |
| 212 | − tSquare_setFreq(&hihat->p[1], 3.00f * hihat->freq); | |
| 213 | − tSquare_setFreq(&hihat->p[2], 4.16f * hihat->freq); | |
| 214 | − tSquare_setFreq(&hihat->p[3], 5.43f * hihat->freq); | |
| 215 | − tSquare_setFreq(&hihat->p[4], 6.79f * hihat->freq); | |
| 216 | − tSquare_setFreq(&hihat->p[5], 8.21f * hihat->freq); | |
| 217 | −} | |
| 218 | − | |
| 219 | −void t808Hihat_free(t808Hihat* const hihatInst) | |
| 220 | −{ | |
| 221 | − _t808Hihat* hihat = *hihatInst; | |
| 222 | − | |
| 223 | − for (int i = 0; i < 6; i++) | |
| 224 | − { | |
| 225 | − tSquare_free(&hihat->p[i]); | |
| 226 | − } | |
| 227 | − | |
| 228 | − tNoise_free(&hihat->stick); | |
| 229 | − tNoise_free(&hihat->n); | |
| 230 | − | |
| 231 | − // need to fix SVF to be generic | |
| 232 | − tSVF_free(&hihat->bandpassStick); | |
| 233 | − tSVF_free(&hihat->bandpassOsc); | |
| 234 | − tEnvelope_free(&hihat->envGain); | |
| 235 | − tEnvelope_free(&hihat->envStick); | |
| 236 | − | |
| 237 | − tHighpass_free(&hihat->highpass); | |
| 238 | − | |
| 239 | − leaf_free((char*)hihat); | |
| 240 | −} | |
| 241 | − | |
| 242 | −void t808Hihat_initToPool (t808Hihat* const hihatInst, tMempool* const mp) | |
| 243 | −{ | |
| 244 | − _tMempool* m = *mp; | |
| 245 | − _t808Hihat* hihat = *hihatInst = (_t808Hihat*) mpool_alloc(sizeof(_t808Hihat), m); | |
| 246 | − | |
| 247 | − for (int i = 0; i < 6; i++) | |
| 248 | − { | |
| 249 | − tSquare_initToPool(&hihat->p[i], mp); | |
| 250 | − } | |
| 251 | − | |
| 252 | − tNoise_initToPool(&hihat->stick, PinkNoise, mp); | |
| 253 | − tNoise_initToPool(&hihat->n, WhiteNoise, mp); | |
| 254 | − | |
| 255 | − // need to fix SVF to be generic | |
| 256 | − tSVF_initToPool(&hihat->bandpassStick, SVFTypeBandpass,2500.0f,1.2f, mp); | |
| 257 | − tSVF_initToPool(&hihat->bandpassOsc, SVFTypeBandpass,3500.0f,0.3f, mp); | |
| 258 | − | |
| 259 | − tEnvelope_initToPool(&hihat->envGain, 0.0f, 50.0f, OFALSE, mp); | |
| 260 | − tEnvelope_initToPool(&hihat->envStick, 0.0f, 7.0f, OFALSE, mp); | |
| 261 | − | |
| 262 | − | |
| 263 | − tHighpass_initToPool(&hihat->highpass, 7000.0f, mp); | |
| 264 | − | |
| 265 | − hihat->freq = 40.0f; | |
| 266 | − hihat->stretch = 0.0f; | |
| 267 | − | |
| 268 | − tSquare_setFreq(&hihat->p[0], 2.0f * hihat->freq); | |
| 269 | − tSquare_setFreq(&hihat->p[1], 3.00f * hihat->freq); | |
| 270 | − tSquare_setFreq(&hihat->p[2], 4.16f * hihat->freq); | |
| 271 | − tSquare_setFreq(&hihat->p[3], 5.43f * hihat->freq); | |
| 272 | − tSquare_setFreq(&hihat->p[4], 6.79f * hihat->freq); | |
| 273 | − tSquare_setFreq(&hihat->p[5], 8.21f * hihat->freq); | |
| 274 | −} | |
| 275 | − | |
| 276 | −void t808Hihat_freeFromPool (t808Hihat* const hihatInst, tMempool* const mp) | |
| 277 | −{ | |
| 278 | − _tMempool* m = *mp; | |
| 279 | − _t808Hihat* hihat = *hihatInst; | |
| 280 | − | |
| 281 | − for (int i = 0; i < 6; i++) | |
| 282 | − { | |
| 283 | − tSquare_freeFromPool(&hihat->p[i], mp); | |
| 284 | − } | |
| 285 | − | |
| 286 | − tNoise_freeFromPool(&hihat->stick, mp); | |
| 287 | − tNoise_freeFromPool(&hihat->n, mp); | |
| 288 | − | |
| 289 | − // need to fix SVF to be generic | |
| 290 | − tSVF_freeFromPool(&hihat->bandpassStick, mp); | |
| 291 | − tSVF_freeFromPool(&hihat->bandpassOsc, mp); | |
| 292 | − tEnvelope_freeFromPool(&hihat->envGain, mp); | |
| 293 | − tEnvelope_freeFromPool(&hihat->envStick, mp); | |
| 294 | − | |
| 295 | − tHighpass_freeFromPool(&hihat->highpass, mp); | |
| 296 | − | |
| 297 | − mpool_free((char*)hihat, m); | |
| 298 | −} | |
| 299 | − | |
| 300 | −void t808Hihat_on(t808Hihat* const hihatInst, float vel) | |
| 301 | −{ | |
| 302 | − _t808Hihat* hihat = *hihatInst; | |
| 303 | − tEnvelope_on(&hihat->envGain, vel); | |
| 304 | − tEnvelope_on(&hihat->envStick, vel); | |
| 305 | −} | |
| 306 | − | |
| 307 | −void t808Hihat_setOscNoiseMix(t808Hihat* const hihatInst, float oscNoiseMix) | |
| 308 | −{ | |
| 309 | − _t808Hihat* hihat = *hihatInst; | |
| 310 | − hihat->oscNoiseMix = oscNoiseMix; | |
| 311 | −} | |
| 312 | − | |
| 313 | −float t808Hihat_tick(t808Hihat* const hihatInst) | |
| 314 | −{ | |
| 315 | − _t808Hihat* hihat = *hihatInst; | |
| 316 | − | |
| 317 | − float sample = 0.0f; | |
| 318 | − float gainScale = 0.1666f; | |
| 319 | − | |
| 320 | − float myNoise = tNoise_tick(&hihat->n); | |
| 321 | − | |
| 322 | − tSquare_setFreq(&hihat->p[0], ((2.0f + hihat->stretch) * hihat->freq)); | |
| 323 | − tSquare_setFreq(&hihat->p[1], ((3.00f + hihat->stretch) * hihat->freq)); | |
| 324 | − tSquare_setFreq(&hihat->p[2], ((4.16f + hihat->stretch) * hihat->freq)); | |
| 325 | − tSquare_setFreq(&hihat->p[3], ((5.43f + hihat->stretch) * hihat->freq)); | |
| 326 | − tSquare_setFreq(&hihat->p[4], ((6.79f + hihat->stretch) * hihat->freq)); | |
| 327 | − tSquare_setFreq(&hihat->p[5], ((8.21f + hihat->stretch) * hihat->freq)); | |
| 328 | − | |
| 329 | − for (int i = 0; i < 6; i++) | |
| 330 | − { | |
| 331 | − sample += tSquare_tick(&hihat->p[i]); | |
| 332 | − } | |
| 333 | − | |
| 334 | − sample *= gainScale; | |
| 335 | − | |
| 336 | − sample = (hihat->oscNoiseMix * sample) + ((1.0f-hihat->oscNoiseMix) * myNoise); | |
| 337 | − | |
| 338 | − sample = tSVF_tick(&hihat->bandpassOsc, sample); | |
| 339 | − | |
| 340 | − float myGain = tEnvelope_tick(&hihat->envGain); | |
| 341 | − sample *= (myGain*myGain);//square the output gain envelope | |
| 342 | − sample = tHighpass_tick(&hihat->highpass, sample); | |
| 343 | − sample += ((0.5f * tEnvelope_tick(&hihat->envStick)) * tSVF_tick(&hihat->bandpassStick, tNoise_tick(&hihat->stick))); | |
| 344 | − sample = tanhf(sample * 2.0f); | |
| 345 | − | |
| 346 | − return sample; | |
| 347 | −} | |
| 348 | − | |
| 349 | −void t808Hihat_setDecay(t808Hihat* const hihatInst, float decay) | |
| 350 | −{ | |
| 351 | − _t808Hihat* hihat = *hihatInst; | |
| 352 | − tEnvelope_setDecay(&hihat->envGain,decay); | |
| 353 | −} | |
| 354 | − | |
| 355 | −void t808Hihat_setHighpassFreq(t808Hihat* const hihatInst, float freq) | |
| 356 | −{ | |
| 357 | − _t808Hihat* hihat = *hihatInst; | |
| 358 | − tHighpass_setFreq(&hihat->highpass,freq); | |
| 359 | −} | |
| 360 | − | |
| 361 | −void t808Hihat_setStretch(t808Hihat* const hihatInst, float stretch) | |
| 362 | −{ | |
| 363 | − _t808Hihat* hihat = *hihatInst; | |
| 364 | − hihat->stretch = stretch; | |
| 365 | −} | |
| 366 | − | |
| 367 | −void t808Hihat_setFM(t808Hihat* const hihatInst, float FM_amount) | |
| 368 | −{ | |
| 369 | − _t808Hihat* hihat = *hihatInst; | |
| 370 | − hihat->FM_amount = FM_amount; | |
| 371 | −} | |
| 372 | − | |
| 373 | −void t808Hihat_setOscBandpassFreq(t808Hihat* const hihatInst, float freq) | |
| 374 | −{ | |
| 375 | − _t808Hihat* hihat = *hihatInst; | |
| 376 | − tSVF_setFreq(&hihat->bandpassOsc,freq); | |
| 377 | −} | |
| 378 | − | |
| 379 | −void t808Hihat_setOscBandpassQ(t808Hihat* const hihatInst, float Q) | |
| 380 | −{ | |
| 381 | − _t808Hihat* hihat = *hihatInst; | |
| 382 | − tSVF_setQ(&hihat->bandpassOsc,Q); | |
| 383 | −} | |
| 384 | − | |
| 385 | −void t808Hihat_setStickBandPassFreq(t808Hihat* const hihatInst, float freq) | |
| 386 | −{ | |
| 387 | − _t808Hihat* hihat = *hihatInst; | |
| 388 | − tSVF_setFreq(&hihat->bandpassStick,freq); | |
| 389 | −} | |
| 390 | − | |
| 391 | −void t808Hihat_setStickBandPassQ(t808Hihat* const hihatInst, float Q) | |
| 392 | −{ | |
| 393 | − _t808Hihat* hihat = *hihatInst; | |
| 394 | − tSVF_setQ(&hihat->bandpassStick,Q); | |
| 395 | −} | |
| 396 | − | |
| 397 | −void t808Hihat_setOscFreq(t808Hihat* const hihatInst, float freq) | |
| 398 | −{ | |
| 399 | − _t808Hihat* hihat = *hihatInst; | |
| 400 | − hihat->freq = freq; | |
| 401 | −} | |
| 402 | − | |
| 403 | −// ----------------- SNARE ----------------------------// | |
| 404 | − | |
| 405 | −void t808Snare_init(t808Snare* const snareInst) | |
| 406 | −{ | |
| 407 | − _t808Snare* snare = *snareInst = (_t808Snare*) leaf_alloc(sizeof(_t808Snare)); | |
| 408 | − | |
| 409 | − float ratio[2] = {1.0, 1.5}; | |
| 410 | − for (int i = 0; i < 2; i++) | |
| 411 | − { | |
| 412 | − tTriangle_init(&snare->tone[i]); | |
| 413 | − | |
| 414 | − tTriangle_setFreq(&snare->tone[i], ratio[i] * 400.0f); | |
| 415 | − tSVF_init(&snare->toneLowpass[i], SVFTypeLowpass, 4000, 1.0f); | |
| 416 | − tEnvelope_init(&snare->toneEnvOsc[i], 0.0f, 50.0f, OFALSE); | |
| 417 | − tEnvelope_init(&snare->toneEnvGain[i], 1.0f, 150.0f, OFALSE); | |
| 418 | − tEnvelope_init(&snare->toneEnvFilter[i], 1.0f, 2000.0f, OFALSE); | |
| 419 | − | |
| 420 | − snare->toneGain[i] = 0.5f; | |
| 421 | − } | |
| 422 | − | |
| 423 | − snare->tone1Freq = ratio[0] * 100.0f; | |
| 424 | − snare->tone2Freq = ratio[1] * 100.0f; | |
| 425 | − snare->noiseFilterFreq = 3000.0f; | |
| 426 | − tNoise_init(&snare->noiseOsc, WhiteNoise); | |
| 427 | − tSVF_init(&snare->noiseLowpass, SVFTypeLowpass, 12000.0f, 0.8f); | |
| 428 | − tEnvelope_init(&snare->noiseEnvGain, 0.0f, 100.0f, OFALSE); | |
| 429 | − tEnvelope_init(&snare->noiseEnvFilter, 0.0f, 1000.0f, OFALSE); | |
| 430 | − snare->noiseGain = 1.0f; | |
| 431 | −} | |
| 432 | − | |
| 433 | −void t808Snare_free (t808Snare* const snareInst) | |
| 434 | −{ | |
| 435 | − _t808Snare* snare = *snareInst; | |
| 436 | − | |
| 437 | − for (int i = 0; i < 2; i++) | |
| 438 | − { | |
| 439 | − tTriangle_free(&snare->tone[i]); | |
| 440 | − tSVF_free(&snare->toneLowpass[i]); | |
| 441 | − tEnvelope_free(&snare->toneEnvOsc[i]); | |
| 442 | − tEnvelope_free(&snare->toneEnvGain[i]); | |
| 443 | − tEnvelope_free(&snare->toneEnvFilter[i]); | |
| 444 | − } | |
| 445 | − | |
| 446 | − tNoise_free(&snare->noiseOsc); | |
| 447 | − tSVF_free(&snare->noiseLowpass); | |
| 448 | − tEnvelope_free(&snare->noiseEnvGain); | |
| 449 | − tEnvelope_free(&snare->noiseEnvFilter); | |
| 450 | − | |
| 451 | − leaf_free((char*)snare); | |
| 452 | −} | |
| 453 | − | |
| 454 | −void t808Snare_initToPool (t808Snare* const snareInst, tMempool* const mp) | |
| 455 | −{ | |
| 456 | − _tMempool* m = *mp; | |
| 457 | − _t808Snare* snare = *snareInst = (_t808Snare*) mpool_alloc(sizeof(_t808Snare), m); | |
| 458 | − | |
| 459 | − float ratio[2] = {1.0, 1.5}; | |
| 460 | − for (int i = 0; i < 2; i++) | |
| 461 | − { | |
| 462 | − tTriangle_initToPool(&snare->tone[i], mp); | |
| 463 | − | |
| 464 | − tTriangle_setFreq(&snare->tone[i], ratio[i] * 400.0f); | |
| 465 | − tSVF_initToPool(&snare->toneLowpass[i], SVFTypeLowpass, 4000, 1.0f, mp); | |
| 466 | − tEnvelope_initToPool(&snare->toneEnvOsc[i], 0.0f, 50.0f, OFALSE, mp); | |
| 467 | − tEnvelope_initToPool(&snare->toneEnvGain[i], 1.0f, 150.0f, OFALSE, mp); | |
| 468 | − tEnvelope_initToPool(&snare->toneEnvFilter[i], 1.0f, 2000.0f, OFALSE, mp); | |
| 469 | − | |
| 470 | − snare->toneGain[i] = 0.5f; | |
| 471 | − } | |
| 472 | − | |
| 473 | − snare->tone1Freq = ratio[0] * 100.0f; | |
| 474 | − snare->tone2Freq = ratio[1] * 100.0f; | |
| 475 | − snare->noiseFilterFreq = 3000.0f; | |
| 476 | − tNoise_initToPool(&snare->noiseOsc, WhiteNoise, mp); | |
| 477 | − tSVF_initToPool(&snare->noiseLowpass, SVFTypeLowpass, 12000.0f, 0.8f, mp); | |
| 478 | − tEnvelope_initToPool(&snare->noiseEnvGain, 0.0f, 100.0f, OFALSE, mp); | |
| 479 | − tEnvelope_initToPool(&snare->noiseEnvFilter, 0.0f, 1000.0f, OFALSE, mp); | |
| 480 | − snare->noiseGain = 1.0f; | |
| 481 | −} | |
| 482 | − | |
| 483 | −void t808Snare_freeFromPool (t808Snare* const snareInst, tMempool* const mp) | |
| 484 | −{ | |
| 485 | − _tMempool* m = *mp; | |
| 486 | − _t808Snare* snare = *snareInst; | |
| 487 | − | |
| 488 | − for (int i = 0; i < 2; i++) | |
| 489 | − { | |
| 490 | − tTriangle_freeFromPool(&snare->tone[i], mp); | |
| 491 | − tSVF_freeFromPool(&snare->toneLowpass[i], mp); | |
| 492 | − tEnvelope_freeFromPool(&snare->toneEnvOsc[i], mp); | |
| 493 | − tEnvelope_freeFromPool(&snare->toneEnvGain[i], mp); | |
| 494 | − tEnvelope_freeFromPool(&snare->toneEnvFilter[i], mp); | |
| 495 | − } | |
| 496 | − | |
| 497 | − tNoise_freeFromPool(&snare->noiseOsc, mp); | |
| 498 | − tSVF_freeFromPool(&snare->noiseLowpass, mp); | |
| 499 | − tEnvelope_freeFromPool(&snare->noiseEnvGain, mp); | |
| 500 | − tEnvelope_freeFromPool(&snare->noiseEnvFilter, mp); | |
| 501 | − | |
| 502 | − mpool_free((char*)snare, m); | |
| 503 | −} | |
| 504 | − | |
| 505 | −void t808Snare_on(t808Snare* const snareInst, float vel) | |
| 506 | −{ | |
| 507 | − _t808Snare* snare = *snareInst; | |
| 508 | − | |
| 509 | − for (int i = 0; i < 2; i++) | |
| 510 | − { | |
| 511 | − tEnvelope_on(&snare->toneEnvOsc[i], vel); | |
| 512 | − tEnvelope_on(&snare->toneEnvGain[i], vel); | |
| 513 | − tEnvelope_on(&snare->toneEnvFilter[i], vel); | |
| 514 | − } | |
| 515 | − | |
| 516 | − tEnvelope_on(&snare->noiseEnvGain, vel); | |
| 517 | − tEnvelope_on(&snare->noiseEnvFilter, vel); | |
| 518 | −} | |
| 519 | − | |
| 520 | −void t808Snare_setTone1Freq(t808Snare* const snareInst, float freq) | |
| 521 | −{ | |
| 522 | − _t808Snare* snare = *snareInst; | |
| 523 | − snare->tone1Freq = freq; | |
| 524 | − tTriangle_setFreq(&snare->tone[0], freq); | |
| 525 | −} | |
| 526 | − | |
| 527 | −void t808Snare_setTone2Freq(t808Snare* const snareInst, float freq) | |
| 528 | −{ | |
| 529 | − _t808Snare* snare = *snareInst; | |
| 530 | − snare->tone2Freq = freq; | |
| 531 | − tTriangle_setFreq(&snare->tone[1],freq); | |
| 532 | −} | |
| 533 | − | |
| 534 | −void t808Snare_setTone1Decay(t808Snare* const snareInst, float decay) | |
| 535 | −{ | |
| 536 | − _t808Snare* snare = *snareInst; | |
| 537 | − tEnvelope_setDecay(&snare->toneEnvGain[0],decay); | |
| 538 | −} | |
| 539 | − | |
| 540 | −void t808Snare_setTone2Decay(t808Snare* const snareInst, float decay) | |
| 541 | −{ | |
| 542 | − _t808Snare* snare = *snareInst; | |
| 543 | − tEnvelope_setDecay(&snare->toneEnvGain[1],decay); | |
| 544 | −} | |
| 545 | − | |
| 546 | −void t808Snare_setNoiseDecay(t808Snare* const snareInst, float decay) | |
| 547 | −{ | |
| 548 | − _t808Snare* snare = *snareInst; | |
| 549 | − tEnvelope_setDecay(&snare->noiseEnvGain,decay); | |
| 550 | −} | |
| 551 | − | |
| 552 | −void t808Snare_setToneNoiseMix(t808Snare* const snareInst, float toneNoiseMix) | |
| 553 | −{ | |
| 554 | − _t808Snare* snare = *snareInst; | |
| 555 | − snare->toneNoiseMix = toneNoiseMix; | |
| 556 | −} | |
| 557 | − | |
| 558 | −void t808Snare_setNoiseFilterFreq(t808Snare* const snareInst, float noiseFilterFreq) | |
| 559 | −{ | |
| 560 | − _t808Snare* snare = *snareInst; | |
| 561 | − snare->noiseFilterFreq = noiseFilterFreq; | |
| 562 | −} | |
| 563 | − | |
| 564 | −void t808Snare_setNoiseFilterQ(t808Snare* const snareInst, float noiseFilterQ) | |
| 565 | −{ | |
| 566 | − _t808Snare* snare = *snareInst; | |
| 567 | − tSVF_setQ(&snare->noiseLowpass, noiseFilterQ); | |
| 568 | −} | |
| 569 | − | |
| 570 | −static float tone[2]; | |
| 571 | − | |
| 572 | −float t808Snare_tick(t808Snare* const snareInst) | |
| 573 | −{ | |
| 574 | − _t808Snare* snare = *snareInst; | |
| 575 | − | |
| 576 | − for (int i = 0; i < 2; i++) | |
| 577 | − { | |
| 578 | − tTriangle_setFreq(&snare->tone[i], snare->tone1Freq + (20.0f * tEnvelope_tick(&snare->toneEnvOsc[i]))); | |
| 579 | − tone[i] = tTriangle_tick(&snare->tone[i]); | |
| 580 | − | |
| 581 | − tSVF_setFreq(&snare->toneLowpass[i], 2000.0f + (500.0f * tEnvelope_tick(&snare->toneEnvFilter[i]))); | |
| 582 | − tone[i] = tSVF_tick(&snare->toneLowpass[i], tone[i]) * tEnvelope_tick(&snare->toneEnvGain[i]); | |
| 583 | − } | |
| 584 | − | |
| 585 | − float noise = tNoise_tick(&snare->noiseOsc); | |
| 586 | − tSVF_setFreq(&snare->noiseLowpass, snare->noiseFilterFreq + (1000.0f * tEnvelope_tick(&snare->noiseEnvFilter))); | |
| 587 | − noise = tSVF_tick(&snare->noiseLowpass, noise) * tEnvelope_tick(&snare->noiseEnvGain); | |
| 588 | − | |
| 589 | − float sample = (snare->toneNoiseMix)*(tone[0] * snare->toneGain[0] + tone[1] * snare->toneGain[1]) + (1.0f-snare->toneNoiseMix) * (noise * snare->noiseGain); | |
| 590 | − sample = tanhf(sample * 2.0f); | |
| 591 | − return sample; | |
| 592 | −} | |
| 593 | − | |
| 594 | −// ----------------- KICK ----------------------------// | |
| 595 | − | |
| 596 | −void t808Kick_init (t808Kick* const kickInst) | |
| 597 | −{ | |
| 598 | − _t808Kick* kick = *kickInst = (_t808Kick*) leaf_alloc(sizeof(_t808Kick)); | |
| 599 | − | |
| 600 | − tCycle_init(&kick->tone); | |
| 601 | − kick->toneInitialFreq = 40.0f; | |
| 602 | − kick->sighAmountInHz = 7.0f; | |
| 603 | − kick->chirpRatioMinusOne = 3.3f; | |
| 604 | − tCycle_setFreq(&kick->tone, 50.0f); | |
| 605 | − tSVF_init(&kick->toneLowpass, SVFTypeLowpass, 2000.0f, 0.5f); | |
| 606 | − tEnvelope_init(&kick->toneEnvOscChirp, 0.0f, 20.0f, OFALSE); | |
| 607 | − tEnvelope_init(&kick->toneEnvOscSigh, 0.0f, 2500.0f, OFALSE); | |
| 608 | − tEnvelope_init(&kick->toneEnvGain, 0.0f, 800.0f, OFALSE); | |
| 609 | − tNoise_init(&kick->noiseOsc, PinkNoise); | |
| 610 | − tEnvelope_init(&kick->noiseEnvGain, 0.0f, 1.0f, OFALSE); | |
| 611 | − kick->noiseGain = 0.3f; | |
| 612 | −} | |
| 613 | − | |
| 614 | −void t808Kick_free (t808Kick* const kickInst) | |
| 615 | −{ | |
| 616 | − _t808Kick* kick = *kickInst; | |
| 617 | − | |
| 618 | − tCycle_free(&kick->tone); | |
| 619 | − tSVF_free(&kick->toneLowpass); | |
| 620 | − tEnvelope_free(&kick->toneEnvOscChirp); | |
| 621 | − tEnvelope_free(&kick->toneEnvOscSigh); | |
| 622 | − tEnvelope_free(&kick->toneEnvGain); | |
| 623 | − tNoise_free(&kick->noiseOsc); | |
| 624 | − tEnvelope_free(&kick->noiseEnvGain); | |
| 625 | − | |
| 626 | − leaf_free((char*)kick); | |
| 627 | −} | |
| 628 | − | |
| 629 | −void t808Kick_initToPool (t808Kick* const kickInst, tMempool* const mp) | |
| 630 | −{ | |
| 631 | − _tMempool* m = *mp; | |
| 632 | − _t808Kick* kick = *kickInst = (_t808Kick*) mpool_alloc(sizeof(_t808Kick), m); | |
| 633 | − | |
| 634 | − tCycle_initToPool(&kick->tone, mp); | |
| 635 | − kick->toneInitialFreq = 40.0f; | |
| 636 | − kick->sighAmountInHz = 7.0f; | |
| 637 | − kick->chirpRatioMinusOne = 3.3f; | |
| 638 | − tCycle_setFreq(&kick->tone, 50.0f); | |
| 639 | − tSVF_initToPool(&kick->toneLowpass, SVFTypeLowpass, 2000.0f, 0.5f, mp); | |
| 640 | − tEnvelope_initToPool(&kick->toneEnvOscChirp, 0.0f, 20.0f, OFALSE, mp); | |
| 641 | − tEnvelope_initToPool(&kick->toneEnvOscSigh, 0.0f, 2500.0f, OFALSE, mp); | |
| 642 | − tEnvelope_initToPool(&kick->toneEnvGain, 0.0f, 800.0f, OFALSE, mp); | |
| 643 | − tNoise_initToPool(&kick->noiseOsc, PinkNoise, mp); | |
| 644 | − tEnvelope_initToPool(&kick->noiseEnvGain, 0.0f, 1.0f, OFALSE, mp); | |
| 645 | − kick->noiseGain = 0.3f; | |
| 646 | −} | |
| 647 | − | |
| 648 | −void t808Kick_freeFromPool (t808Kick* const kickInst, tMempool* const mp) | |
| 649 | −{ | |
| 650 | − _tMempool* m = *mp; | |
| 651 | − _t808Kick* kick = *kickInst; | |
| 652 | − | |
| 653 | − tCycle_freeFromPool(&kick->tone, mp); | |
| 654 | − tSVF_freeFromPool(&kick->toneLowpass, mp); | |
| 655 | − tEnvelope_freeFromPool(&kick->toneEnvOscChirp, mp); | |
| 656 | − tEnvelope_freeFromPool(&kick->toneEnvOscSigh, mp); | |
| 657 | − tEnvelope_freeFromPool(&kick->toneEnvGain, mp); | |
| 658 | − tNoise_freeFromPool(&kick->noiseOsc, mp); | |
| 659 | − tEnvelope_freeFromPool(&kick->noiseEnvGain, mp); | |
| 660 | − | |
| 661 | − mpool_free((char*)kick, m); | |
| 662 | −} | |
| 663 | − | |
| 664 | −float t808Kick_tick (t808Kick* const kickInst) | |
| 665 | −{ | |
| 666 | − _t808Kick* kick = *kickInst; | |
| 667 | − | |
| 668 | − tCycle_setFreq(&kick->tone, (kick->toneInitialFreq * (1.0f + (kick->chirpRatioMinusOne * tEnvelope_tick(&kick->toneEnvOscChirp)))) + (kick->sighAmountInHz * tEnvelope_tick(&kick->toneEnvOscSigh))); | |
| 669 | − float sample = tCycle_tick(&kick->tone) * tEnvelope_tick(&kick->toneEnvGain); | |
| 670 | − sample+= tNoise_tick(&kick->noiseOsc) * tEnvelope_tick(&kick->noiseEnvGain); | |
| 671 | − //add distortion here | |
| 672 | − sample = tSVF_tick(&kick->toneLowpass, sample); | |
| 673 | − return sample; | |
| 674 | −} | |
| 675 | − | |
| 676 | −void t808Kick_on (t808Kick* const kickInst, float vel) | |
| 677 | −{ | |
| 678 | − _t808Kick* kick = *kickInst; | |
| 679 | − tEnvelope_on(&kick->toneEnvOscChirp, vel); | |
| 680 | − tEnvelope_on(&kick->toneEnvOscSigh, vel); | |
| 681 | − tEnvelope_on(&kick->toneEnvGain, vel); | |
| 682 | − tEnvelope_on(&kick->noiseEnvGain, vel); | |
| 683 | − | |
| 684 | −} | |
| 685 | −void t808Kick_setToneFreq (t808Kick* const kickInst, float freq) | |
| 686 | −{ | |
| 687 | − _t808Kick* kick = *kickInst; | |
| 688 | − kick->toneInitialFreq = freq; | |
| 689 | − | |
| 690 | −} | |
| 691 | − | |
| 692 | −void t808Kick_setToneDecay (t808Kick* const kickInst, float decay) | |
| 693 | −{ | |
| 694 | − _t808Kick* kick = *kickInst; | |
| 695 | − tEnvelope_setDecay(&kick->toneEnvGain,decay); | |
| 696 | − tEnvelope_setDecay(&kick->toneEnvGain,decay * 3.0f); | |
| 697 | −} | |
| 698 | − | |
| 699 | −void t808Kick_setNoiseDecay (t808Kick* const kickInst, float decay); | |
| 700 | −void t808Kick_setSighAmount (t808Kick* const kickInst, float sigh); | |
| 701 | −void t808Kick_setChirpAmount (t808Kick* const kickInst, float chirp); | |
| 702 | −void t808Kick_setToneNoiseMix (t808Kick* const kickInst, float toneNoiseMix); | |
| 703 | −void t808Kick_setNoiseFilterFreq (t808Kick* const kickInst, float noiseFilterFreq); | |
| 704 | −void t808Kick_setNoiseFilterQ (t808Kick* const kickInst, float noiseFilterQ); | |
| 705 | − | |
| 706 | − | |
| @@ -1,655 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-math.c | |
| 4 | − Created: 22 Jan 2017 7:02:56pm | |
| 5 | − Author: Michael R Mulshine | |
| 6 | − | |
| 7 | − ==============================================================================*/ | |
| 8 | − | |
| 9 | −#if _WIN32 || _WIN64 | |
| 10 | − | |
| 11 | −#include "..\Inc\leaf-math.h" | |
| 12 | −#include "..\Inc\leaf-tables.h" | |
| 13 | − | |
| 14 | −#else | |
| 15 | − | |
| 16 | −#include "../Inc/leaf-math.h" | |
| 17 | −#include "../Inc/leaf-tables.h" | |
| 18 | − | |
| 19 | −#endif | |
| 20 | − | |
| 21 | − | |
| 22 | −#define EXPONENTIAL_TABLE_SIZE 65536 | |
| 23 | − | |
| 24 | −#define log10f_fast(x) (log2f_approx(x)*0.3010299956639812f) | |
| 25 | − | |
| 26 | −// This is a fast approximation to log2() found on http://openaudio.blogspot.com/2017/02/faster-log10-and-pow.html credited to this post https://community.arm.com/developer/tools-software/tools/f/armds-forum/4292/cmsis-dsp-new-functionality-proposal/22621#22621 | |
| 27 | −// Y = C[0]*F*F*F + C[1]*F*F + C[2]*F + C[3] + E; | |
| 28 | −float log2f_approx(float X) { | |
| 29 | − float Y, F; | |
| 30 | − int E; | |
| 31 | − F = frexpf(fabsf(X), &E); | |
| 32 | − Y = 1.23149591368684f; | |
| 33 | − Y *= F; | |
| 34 | − Y += -4.11852516267426f; | |
| 35 | − Y *= F; | |
| 36 | − Y += 6.02197014179219f; | |
| 37 | − Y *= F; | |
| 38 | − Y += -3.13396450166353f; | |
| 39 | − Y += E; | |
| 40 | − return(Y); | |
| 41 | −} | |
| 42 | − | |
| 43 | −float interpolate3max(float *buf, const int peakindex) | |
| 44 | −{ | |
| 45 | − float a = buf[peakindex-1]; | |
| 46 | − float b = buf[peakindex]; | |
| 47 | − float c = buf[peakindex+1]; | |
| 48 | − float realpeak; | |
| 49 | − | |
| 50 | − realpeak = b + (float)0.125 * (c - a) * (c - a) / ((float)2. * b - a - c); | |
| 51 | − | |
| 52 | − return(realpeak); | |
| 53 | −} | |
| 54 | − | |
| 55 | −float interpolate3phase(float *buf, const int peakindex) | |
| 56 | −{ | |
| 57 | − float a = buf[peakindex-1]; | |
| 58 | − float b = buf[peakindex]; | |
| 59 | − float c = buf[peakindex+1]; | |
| 60 | − float fraction; | |
| 61 | − | |
| 62 | − fraction = ((float)0.5 * (c - a)) / ((float)2. * b - a - c); | |
| 63 | − | |
| 64 | − return(fraction); | |
| 65 | −} | |
| 66 | − | |
| 67 | −// alternative implementation for abs() | |
| 68 | −// REQUIRES: 32 bit integers | |
| 69 | −int fastabs_int(int in){ | |
| 70 | − unsigned int r; | |
| 71 | − int const mask = in >> 31; | |
| 72 | − | |
| 73 | − r = (in ^ mask) - mask; | |
| 74 | − | |
| 75 | − return (r); | |
| 76 | −} | |
| 77 | − | |
| 78 | −// alternative implementation for abs() | |
| 79 | −// REQUIRES: 32 bit floats | |
| 80 | −float fastabsf(float f) | |
| 81 | −{ | |
| 82 | − union | |
| 83 | − { | |
| 84 | − float f; | |
| 85 | − unsigned int ui; | |
| 86 | − }alias; | |
| 87 | − | |
| 88 | − alias.f = f; | |
| 89 | − alias.ui &= 0x7fffffff; | |
| 90 | − return alias.f; | |
| 91 | −} | |
| 92 | − | |
| 93 | −double fastexp(double x) { | |
| 94 | − x = 1.0 + (x * 0.0009765625); | |
| 95 | − x *= x; x *= x; x *= x; x *= x; | |
| 96 | − x *= x; x *= x; x *= x; x *= x; | |
| 97 | − x *= x; x *= x; | |
| 98 | − return x; | |
| 99 | −} | |
| 100 | − | |
| 101 | −float fastexpf(float x) { | |
| 102 | − x = 1.0f + (x * 0.0009765625f); | |
| 103 | − x *= x; x *= x; x *= x; x *= x; | |
| 104 | − x *= x; x *= x; x *= x; x *= x; | |
| 105 | − x *= x; x *= x; | |
| 106 | − return x; | |
| 107 | −} | |
| 108 | − | |
| 109 | −double fasterexp(double x) { | |
| 110 | − x = 1.0 + (x * 0.00390625); | |
| 111 | − x *= x; x *= x; x *= x; x *= x; | |
| 112 | − x *= x; x *= x; x *= x; x *= x; | |
| 113 | − return x; | |
| 114 | −} | |
| 115 | − | |
| 116 | −float fasterexpf(float x) { | |
| 117 | − x = 1.0f + (x * 0.00390625f); | |
| 118 | − x *= x; x *= x; x *= x; x *= x; | |
| 119 | − x *= x; x *= x; x *= x; x *= x; | |
| 120 | − return x; | |
| 121 | −} | |
| 122 | − | |
| 123 | −// fast floating-point exp2 function taken from Robert Bristow Johnson's | |
| 124 | −// post in the music-dsp list on Date: Tue, 02 Sep 2014 16:50:11 -0400 | |
| 125 | −float fastexp2f(float x) | |
| 126 | −{ | |
| 127 | − if (x >= -127.0) | |
| 128 | − { | |
| 129 | − float accumulator, xPower; | |
| 130 | − union {float f; int32_t i;} xBits; | |
| 131 | − | |
| 132 | − xBits.i = (int32_t)(x + 4096.0f) - 4096L; /* integer part */ | |
| 133 | − x -= (float)(xBits.i); /* fractional part */ | |
| 134 | − | |
| 135 | − accumulator = 1.0f + 0.69303212081966f*x; | |
| 136 | − xPower = x*x; | |
| 137 | − accumulator += 0.24137976293709f*xPower; | |
| 138 | − xPower *= x; | |
| 139 | − accumulator += 0.05203236900844f*xPower; | |
| 140 | − xPower *= x; | |
| 141 | − accumulator += 0.01355574723481f*xPower; | |
| 142 | − | |
| 143 | − xBits.i += 127; /* bias integer part */ | |
| 144 | − xBits.i<<= 23; /* move biased int part into exponent bits */ | |
| 145 | − | |
| 146 | − return accumulator * xBits.f; | |
| 147 | − } | |
| 148 | − else | |
| 149 | − { | |
| 150 | − return 0.0f; | |
| 151 | − } | |
| 152 | −} | |
| 153 | − | |
| 154 | − | |
| 155 | −float fastPowf(float a, float b) { | |
| 156 | − union | |
| 157 | − { | |
| 158 | − float d; int x; | |
| 159 | − } | |
| 160 | − u = { a }; | |
| 161 | − | |
| 162 | − u.x = (int)(b * (u.x - 1064866805) + 1064866805); | |
| 163 | − return u.d; | |
| 164 | −} | |
| 165 | − | |
| 166 | − | |
| 167 | −double fastPow(double a, double b) { | |
| 168 | − union { | |
| 169 | − double d; | |
| 170 | − int x[2]; | |
| 171 | − } u = { a }; | |
| 172 | − | |
| 173 | − u.x[1] = (int)(b * (u.x[1] - 1072632447) + 1072632447); | |
| 174 | − | |
| 175 | − u.x[0] = 0; | |
| 176 | − return u.d; | |
| 177 | −} | |
| 178 | − | |
| 179 | − | |
| 180 | − | |
| 181 | − | |
| 182 | − | |
| 183 | −/* | |
| 184 | − you pass in a float array to get back two indexes representing the volumes of the left (index 0) and right (index 1) channels | |
| 185 | − when t is -1, volumes[0] = 0, volumes[1] = 1 | |
| 186 | − when t = 0, volumes[0] = 0.707, volumes[1] = 0.707 (equal-power cross fade) | |
| 187 | − when t = 1, volumes[0] = 1, volumes[1] = 0 | |
| 188 | − */ | |
| 189 | − | |
| 190 | −void LEAF_crossfade(float fade, float* volumes) { | |
| 191 | − volumes[0] = sqrtf(0.5f * (1.0f + fade)); | |
| 192 | − volumes[1] = sqrtf(0.5f * (1.0f - fade)); | |
| 193 | −} | |
| 194 | − | |
| 195 | −// dope af | |
| 196 | −float LEAF_chebyshevT(float in, int n){ | |
| 197 | − if (n == 0) return 1; | |
| 198 | − else if (n == 1) return in; | |
| 199 | − else return 2.0f * in * LEAF_chebyshevT(in, n-1) - LEAF_chebyshevT(in, n-2); | |
| 200 | −} | |
| 201 | − | |
| 202 | −#if !(_WIN32 || _WIN64) | |
| 203 | −float LEAF_CompoundChebyshevT(float in, int n, float* amps){ | |
| 204 | − float T[n+1]; | |
| 205 | − T[0] = 1.0f; | |
| 206 | − T[1] = in; | |
| 207 | − for (int i = 2; i <= n; ++i) | |
| 208 | − T[i] = 2*in*T[i-1] - T[i-2]; | |
| 209 | − float out = 0; | |
| 210 | − float amp = 0; | |
| 211 | − for (int i = 0; i < n; ++i){ | |
| 212 | − out += amps[i]*T[i+1]; | |
| 213 | − amp += amps[i]; | |
| 214 | − } | |
| 215 | − return out / amp ; | |
| 216 | −} | |
| 217 | −#endif | |
| 218 | − | |
| 219 | −float LEAF_frequencyToMidi(float f) | |
| 220 | −{ | |
| 221 | − return (69.0f + 12.0f * log2f(f * INV_440)); | |
| 222 | −} | |
| 223 | − | |
| 224 | −// Jones shaper | |
| 225 | −float LEAF_shaper(float input, float m_drive) | |
| 226 | −{ | |
| 227 | − float fx = input * 2.0f; // prescale | |
| 228 | − float w, c, xc, xc2, xc4; | |
| 229 | − | |
| 230 | − xc = LEAF_clip(-SQRT8, fx, SQRT8); | |
| 231 | − xc2 = xc*xc; | |
| 232 | − c = 0.5f*fx*(3.0f - (xc2)); | |
| 233 | − xc4 = xc2 * xc2; | |
| 234 | − w = (1.0f - xc2*0.25f + xc4*0.015625f) * WSCALE; | |
| 235 | − float shaperOut = w*(c+ 0.05f*xc2)*(m_drive + 0.75f); | |
| 236 | − shaperOut *= 0.5f; // post_scale | |
| 237 | − return shaperOut; | |
| 238 | −} | |
| 239 | − | |
| 240 | −// round input to nearest rnd | |
| 241 | −float LEAF_round (float input, float rnd) | |
| 242 | −{ | |
| 243 | − rnd = fabsf(rnd); | |
| 244 | − | |
| 245 | − if (rnd <= 0.0000001f) return input; | |
| 246 | − | |
| 247 | − float scale = 1.f / rnd; | |
| 248 | − | |
| 249 | − return roundf(input * scale) / scale; | |
| 250 | −} | |
| 251 | − | |
| 252 | − | |
| 253 | − | |
| 254 | −float LEAF_bitwise_xor(float input, uint32_t op) | |
| 255 | −{ | |
| 256 | − union unholy_t unholy; | |
| 257 | − unholy.f = input; | |
| 258 | − unholy.i = (unholy.i ^ op); | |
| 259 | − | |
| 260 | − return unholy.f; | |
| 261 | −} | |
| 262 | − | |
| 263 | −float LEAF_reedTable(float input, float offset, float slope) | |
| 264 | −{ | |
| 265 | − float output = offset + (slope * input); | |
| 266 | − if ( output > 1.0f) output = 1.0f; | |
| 267 | − if ( output < -1.0f) output = -1.0f; | |
| 268 | − return output; | |
| 269 | −} | |
| 270 | − | |
| 271 | −float LEAF_softClip(float val, float thresh) | |
| 272 | −{ | |
| 273 | − float x; | |
| 274 | − | |
| 275 | − if(val > thresh) | |
| 276 | − { | |
| 277 | − x = thresh / val; | |
| 278 | − return (1.0f - x) * (1.0f - thresh) + thresh; | |
| 279 | − } | |
| 280 | − else if(val < -thresh) | |
| 281 | − { | |
| 282 | − x = -thresh / val; | |
| 283 | − return -((1.0f - x) * (1.0f - thresh) + thresh); | |
| 284 | − } | |
| 285 | − else | |
| 286 | − { | |
| 287 | − return val; | |
| 288 | − } | |
| 289 | −} | |
| 290 | − | |
| 291 | −float LEAF_clip(float min, float val, float max) | |
| 292 | −{ | |
| 293 | − float tempmin = min; | |
| 294 | − float tempmax = max; | |
| 295 | − if (min > max) | |
| 296 | − { | |
| 297 | − tempmin = max; | |
| 298 | − tempmax = min; | |
| 299 | − } | |
| 300 | − if (val < tempmin) { | |
| 301 | − return tempmin; | |
| 302 | − } else if (val > tempmax) { | |
| 303 | − return tempmax; | |
| 304 | − } else { | |
| 305 | − return val; | |
| 306 | − } | |
| 307 | −} | |
| 308 | − | |
| 309 | −int LEAF_clipInt(int min, int val, int max) | |
| 310 | −{ | |
| 311 | − int tempmin = min; | |
| 312 | − int tempmax = max; | |
| 313 | − if (min > max) | |
| 314 | − { | |
| 315 | − tempmin = max; | |
| 316 | − tempmax = min; | |
| 317 | − } | |
| 318 | − if (val < tempmin) { | |
| 319 | − return tempmin; | |
| 320 | − } else if (val > tempmax) { | |
| 321 | − return tempmax; | |
| 322 | − } else { | |
| 323 | − return val; | |
| 324 | − } | |
| 325 | −} | |
| 326 | − | |
| 327 | −oBool LEAF_isPrime(uint64_t number ) | |
| 328 | −{ | |
| 329 | − if ( number == 2 ) return OTRUE; | |
| 330 | − if ( number & 1 ) { | |
| 331 | − for ( int i=3; i<(int)sqrt((double)number)+1; i+=2 ) | |
| 332 | − if ( (number % i) == 0 ) return OFALSE; | |
| 333 | − return OTRUE; // prime | |
| 334 | − } | |
| 335 | − else return OFALSE; // even | |
| 336 | −} | |
| 337 | − | |
| 338 | −// Adapted from MusicDSP: http://www.musicdsp.org/showone.php?id=238 | |
| 339 | −float LEAF_tanh(float x) | |
| 340 | −{ | |
| 341 | − | |
| 342 | − if( x < -3.0f ) | |
| 343 | − return -1.0f; | |
| 344 | − else if( x > 3.0f ) | |
| 345 | − return 1.0f; | |
| 346 | − else | |
| 347 | − return x * ( 27.0f + x * x ) / ( 27.0f + 9.0f * x * x ); | |
| 348 | −} | |
| 349 | − | |
| 350 | − | |
| 351 | −void LEAF_generate_sine(float* buffer, int size) | |
| 352 | −{ | |
| 353 | − float phase; | |
| 354 | − for (int i = 0; i < size; i++) | |
| 355 | − { | |
| 356 | − phase = (float) i / (float) size; | |
| 357 | − buffer[i] = sinf(phase * TWO_PI); | |
| 358 | − } | |
| 359 | −} | |
| 360 | − | |
| 361 | −void LEAF_generate_sawtooth(float* buffer, float basefreq, int size) | |
| 362 | −{ | |
| 363 | − int harmonic = 1; | |
| 364 | − float phase = 0.0f; | |
| 365 | − float freq = harmonic * basefreq; | |
| 366 | − float amp; | |
| 367 | − | |
| 368 | − while (freq < (leaf.sampleRate * 0.5)) | |
| 369 | − { | |
| 370 | − amp = 1.0f / harmonic; | |
| 371 | − for (int i = 0; i < size; i++) | |
| 372 | − { | |
| 373 | − phase = (float) i / (float) size; | |
| 374 | − buffer[i] += (amp * sinf(harmonic * phase * TWO_PI)); | |
| 375 | − } | |
| 376 | − | |
| 377 | − harmonic++; | |
| 378 | − freq = harmonic * basefreq; | |
| 379 | − } | |
| 380 | −} | |
| 381 | − | |
| 382 | − | |
| 383 | −void LEAF_generate_triangle(float* buffer, float basefreq, int size) | |
| 384 | −{ | |
| 385 | − int harmonic = 1; | |
| 386 | − float phase = 0.0f; | |
| 387 | − float freq = harmonic * basefreq; | |
| 388 | − float amp = 1.0f; | |
| 389 | − | |
| 390 | − int count = 0; | |
| 391 | − float mult = 1.0f; | |
| 392 | − | |
| 393 | − while (freq < (leaf.sampleRate * 0.5)) | |
| 394 | − { | |
| 395 | − amp = 1.0f / (float)(harmonic * harmonic); | |
| 396 | − | |
| 397 | − if (count % 2) mult = -1.0f; | |
| 398 | − else mult = 1.0f; | |
| 399 | − | |
| 400 | − for (int i = 0; i < size; i++) | |
| 401 | − { | |
| 402 | − phase = (float) i / (float) size; | |
| 403 | − buffer[i] += (mult * amp * sinf(harmonic * phase * TWO_PI)); | |
| 404 | − } | |
| 405 | − | |
| 406 | − count++; | |
| 407 | − harmonic += 2; | |
| 408 | − freq = harmonic * basefreq; | |
| 409 | − } | |
| 410 | −} | |
| 411 | − | |
| 412 | −void LEAF_generate_square(float* buffer, float basefreq, int size) | |
| 413 | −{ | |
| 414 | − int harmonic = 1; | |
| 415 | − float phase = 0.0f; | |
| 416 | − float freq = harmonic * basefreq; | |
| 417 | − float amp = 1.0f; | |
| 418 | − | |
| 419 | − while (freq < (leaf.sampleRate * 0.5)) | |
| 420 | − { | |
| 421 | − amp = 1.0f / (float)(harmonic); | |
| 422 | − | |
| 423 | − for (int i = 0; i < size; i++) | |
| 424 | − { | |
| 425 | − phase = (float) i / (float) size; | |
| 426 | − buffer[i] += (amp * sinf(harmonic * phase * TWO_PI)); | |
| 427 | − } | |
| 428 | − | |
| 429 | − harmonic += 2; | |
| 430 | − freq = harmonic * basefreq; | |
| 431 | − } | |
| 432 | −} | |
| 433 | − | |
| 434 | − | |
| 435 | −//0.001 base gives a good curve that goes from 1 to near zero | |
| 436 | −void LEAF_generate_exp(float* buffer, float base, float start, float end, float offset, int size) | |
| 437 | −{ | |
| 438 | − float increment = (end - start) / (float)size; | |
| 439 | − float x = start; | |
| 440 | − for (int i = 0; i < size; i++) | |
| 441 | − { | |
| 442 | − buffer[i] = powf(base, x) + offset; | |
| 443 | − x += increment; | |
| 444 | − } | |
| 445 | −} | |
| 446 | − | |
| 447 | − | |
| 448 | −// http://www.martin-finke.de/blog/articles/audio-plugins-018-polyblep-oscillator/ | |
| 449 | −// http://www.kvraudio.com/forum/viewtopic.php?t=375517 | |
| 450 | −// t = phase, dt = inc, assuming 0-1 phase | |
| 451 | −// assumes discontinuity at 0, so offset inputs as needed | |
| 452 | −float LEAF_poly_blep(float t, float dt) | |
| 453 | −{ | |
| 454 | − // 0 <= t < 1 | |
| 455 | − if (t < dt) { | |
| 456 | − t /= dt; | |
| 457 | − return t+t - t*t - 1.0f; | |
| 458 | − } | |
| 459 | − // -1 < t < 0 | |
| 460 | − else if (t > 1.0f - dt) { | |
| 461 | − t = (t - 1.0f) / dt; | |
| 462 | − return t*t + t+t + 1.0f; | |
| 463 | − } | |
| 464 | − // 0 otherwise | |
| 465 | − else return 0.0f; | |
| 466 | − | |
| 467 | −// | |
| 468 | −// float y = 0.0f; | |
| 469 | −// if (t < 2.0f * dt) | |
| 470 | −// { | |
| 471 | −// float x = t / dt; | |
| 472 | −// float u = 2.0f - x; | |
| 473 | −// u *= u; | |
| 474 | −// u *= u; | |
| 475 | −// y += u; | |
| 476 | −// if (t < dt) { | |
| 477 | −// float v = 1.0f - x; | |
| 478 | −// v *= v; | |
| 479 | −// v *= v; | |
| 480 | −// y -= 4.0f * v; | |
| 481 | −// } | |
| 482 | −// } | |
| 483 | −// else if (t > 1.0f - (2.0f * dt)) | |
| 484 | −// { | |
| 485 | −// float x = (t - 1.0f) / dt; | |
| 486 | −// float u = 2.0f - x; | |
| 487 | −// u *= u; | |
| 488 | −// u *= u; | |
| 489 | −// y += u; | |
| 490 | −// if (t > 1.0f - dt) { | |
| 491 | −// float v = 1.0f - x; | |
| 492 | −// v *= v; | |
| 493 | −// v *= v; | |
| 494 | −// y += 4.0f * v; | |
| 495 | −// } | |
| 496 | −// } | |
| 497 | −// return y / 12.0f; | |
| 498 | −} | |
| 499 | − | |
| 500 | − | |
| 501 | −//----------------------------------------------------------------------------- | |
| 502 | −// name: mtof() | |
| 503 | −// desc: midi to freq, from PD source | |
| 504 | −//----------------------------------------------------------------------------- | |
| 505 | −float LEAF_midiToFrequency(float f) | |
| 506 | −{ | |
| 507 | − if( f <= -1500.0f ) return (0); | |
| 508 | − else if( f > 1499.0f ) return (LEAF_midiToFrequency(1499.0f)); | |
| 509 | − else return ( powf(2.0f, (f - 69.0f) * 0.083333333333333f) * 440.0f ); | |
| 510 | −} | |
| 511 | − | |
| 512 | − | |
| 513 | −// alpha, [0.0, 1.0] | |
| 514 | −float LEAF_interpolate_hermite (float A, float B, float C, float D, float alpha) | |
| 515 | −{ | |
| 516 | − alpha = LEAF_clip(0.0f, alpha, 1.0f); | |
| 517 | − | |
| 518 | − float a = -A*0.5f + (3.0f*B)*0.5f - (3.0f*C)*0.5f + D*0.5f; | |
| 519 | − float b = A - (5.0f*B)*0.5f + 2.0f*C - D * 0.5f; | |
| 520 | − float c = -A*0.5f + C*0.5f; | |
| 521 | − float d = B; | |
| 522 | − | |
| 523 | − return a*alpha*alpha*alpha + b*alpha*alpha + c*alpha + d; | |
| 524 | −} | |
| 525 | − | |
| 526 | − | |
| 527 | −// from http://www.musicdsp.org/archive.php?classid=5#93 | |
| 528 | −//xx is alpha (fractional part of sample value) | |
| 529 | −//grabbed this from Tom Erbe's Delay pd code | |
| 530 | −float LEAF_interpolate_hermite_x(float yy0, float yy1, float yy2, float yy3, float xx) | |
| 531 | −{ | |
| 532 | − // 4-point, 3rd-order Hermite (x-form) | |
| 533 | − float c0 = yy1; | |
| 534 | − float c1 = 0.5f * (yy2 - yy0); | |
| 535 | − float y0my1 = yy0 - yy1; | |
| 536 | − float c3 = (yy1 - yy2) + 0.5f * (yy3 - y0my1 - yy2); | |
| 537 | − float c2 = y0my1 + c1 - c3; | |
| 538 | − | |
| 539 | − return ((c3 * xx + c2) * xx + c1) * xx + c0; | |
| 540 | −} | |
| 541 | − | |
| 542 | −// alpha, [0.0, 1.0] | |
| 543 | −float LEAF_interpolation_linear (float A, float B, float alpha) | |
| 544 | −{ | |
| 545 | − alpha = LEAF_clip(0.0f, alpha, 1.0f); | |
| 546 | − | |
| 547 | − float omAlpha = 1.0f - alpha; | |
| 548 | − | |
| 549 | − // First 1/2 of interpolation | |
| 550 | − float out = A * omAlpha; | |
| 551 | − | |
| 552 | − out += B * alpha; | |
| 553 | − | |
| 554 | − return out; | |
| 555 | −} | |
| 556 | − | |
| 557 | −#define LOGTEN 2.302585092994 | |
| 558 | − | |
| 559 | −float mtof(float f) | |
| 560 | −{ | |
| 561 | − if (f <= -1500.0f) return(0); | |
| 562 | − else if (f > 1499.0f) return(mtof(1499.0f)); | |
| 563 | − else return (8.17579891564f * expf(0.0577622650f * f)); | |
| 564 | −} | |
| 565 | − | |
| 566 | −float fast_mtof(float f) | |
| 567 | −{ | |
| 568 | − return (8.17579891564f * fastexpf(0.0577622650f * f)); | |
| 569 | −} | |
| 570 | − | |
| 571 | −float faster_mtof(float f) | |
| 572 | −{ | |
| 573 | − return (8.17579891564f * fastexpf(0.0577622650f * f)); | |
| 574 | −} | |
| 575 | − | |
| 576 | −float ftom(float f) | |
| 577 | −{ | |
| 578 | − return (f > 0 ? 17.3123405046f * logf(.12231220585f * f) : -1500.0f); | |
| 579 | −} | |
| 580 | − | |
| 581 | −float powtodb(float f) | |
| 582 | −{ | |
| 583 | − if (f <= 0) return (0); | |
| 584 | − else | |
| 585 | − { | |
| 586 | − float val = 100.0f + 10.0f/LOGTEN * logf(f); | |
| 587 | − return (val < 0.0f ? 0.0f : val); | |
| 588 | − } | |
| 589 | −} | |
| 590 | − | |
| 591 | −float rmstodb(float f) | |
| 592 | −{ | |
| 593 | − if (f <= 0) return (0); | |
| 594 | − else | |
| 595 | − { | |
| 596 | − float val = 100 + 20.f/LOGTEN * log(f); | |
| 597 | − return (val < 0 ? 0 : val); | |
| 598 | − } | |
| 599 | −} | |
| 600 | − | |
| 601 | −float dbtopow(float f) | |
| 602 | −{ | |
| 603 | − if (f <= 0) | |
| 604 | − return(0); | |
| 605 | − else | |
| 606 | − { | |
| 607 | − if (f > 870.0f) | |
| 608 | − f = 870.0f; | |
| 609 | − return (expf((LOGTEN * 0.1f) * (f-100.0f))); | |
| 610 | − } | |
| 611 | −} | |
| 612 | − | |
| 613 | −float dbtorms(float f) | |
| 614 | −{ | |
| 615 | − if (f <= 0) | |
| 616 | − return(0); | |
| 617 | − else | |
| 618 | − { | |
| 619 | − if (f > 485.0f) | |
| 620 | − f = 485.0f; | |
| 621 | − } | |
| 622 | − return (expf((LOGTEN * 0.05f) * (f-100.0f))); | |
| 623 | −} | |
| 624 | − | |
| 625 | − | |
| 626 | −float atodb(float a) | |
| 627 | −{ | |
| 628 | − return 20.0f*log10f(a); | |
| 629 | −} | |
| 630 | − | |
| 631 | −float dbtoa(float db) | |
| 632 | −{ | |
| 633 | − return powf(10.0f, db * 0.05f); | |
| 634 | − //return expf(0.115129254649702f * db); //faster version from http://openaudio.blogspot.com/2017/02/faster-log10-and-pow.html | |
| 635 | −} | |
| 636 | − | |
| 637 | − | |
| 638 | −float fastdbtoa(float db) | |
| 639 | −{ | |
| 640 | − //return powf(10.0f, db * 0.05f); | |
| 641 | − return expf(0.115129254649702f * db); //faster version from http://openaudio.blogspot.com/2017/02/faster-log10-and-pow.html | |
| 642 | −} | |
| 643 | − | |
| 644 | − | |
| 645 | −float maximum (float num1, float num2) | |
| 646 | −{ | |
| 647 | − return (num1 > num2 ) ? num1 : num2; | |
| 648 | −} | |
| 649 | − | |
| 650 | −float minimum (float num1, float num2) | |
| 651 | −{ | |
| 652 | − return (num1 < num2 ) ? num1 : num2; | |
| 653 | −} | |
| 654 | − | |
| 655 | − | |
| @@ -1,412 +0,0 @@ | ||
| 1 | − | |
| 2 | −/** mpool source significantly modified by Mike Mulshine, Jeff Snyder, et al., Princeton University Music Department **/ | |
| 3 | − | |
| 4 | −/** | |
| 5 | − In short, mpool is distributed under so called "BSD license", | |
| 6 | − | |
| 7 | − Copyright (c) 2009-2010 Tatsuhiko Kubo <cubicdaiya@gmail.com> | |
| 8 | − All rights reserved. | |
| 9 | − | |
| 10 | − Redistribution and use in source and binary forms, with or without modification, | |
| 11 | − are permitted provided that the following conditions are met: | |
| 12 | − | |
| 13 | − * Redistributions of source code must retain the above copyright notice, | |
| 14 | − this list of conditions and the following disclaimer. | |
| 15 | − | |
| 16 | − * Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | − this list of conditions and the following disclaimer in the documentation | |
| 18 | − and/or other materials provided with the distribution. | |
| 19 | − | |
| 20 | − * Neither the name of the authors nor the names of its contributors | |
| 21 | − may be used to endorse or promote products derived from this software | |
| 22 | − without specific prior written permission. | |
| 23 | − | |
| 24 | − THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 25 | − "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 26 | − LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 27 | − A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 28 | − OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 29 | − SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
| 30 | − TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 31 | − PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 32 | − LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 33 | − NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 34 | − SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 35 | − */ | |
| 36 | − | |
| 37 | −/* written with C99 style */ | |
| 38 | − | |
| 39 | −#if _WIN32 || _WIN64 | |
| 40 | − | |
| 41 | −#include "..\Inc\leaf-mempool.h" | |
| 42 | −#include "..\leaf.h" | |
| 43 | − | |
| 44 | −#else | |
| 45 | − | |
| 46 | −#include "../Inc/leaf-mempool.h" | |
| 47 | −#include "../leaf.h" | |
| 48 | − | |
| 49 | −#endif | |
| 50 | − | |
| 51 | −/** | |
| 52 | − * private function | |
| 53 | − */ | |
| 54 | −static inline size_t mpool_align(size_t size); | |
| 55 | −static inline mpool_node_t* create_node(char* block_location, mpool_node_t* next, mpool_node_t* prev, size_t size); | |
| 56 | −static inline void delink_node(mpool_node_t* node); | |
| 57 | − | |
| 58 | −/** | |
| 59 | − * create memory pool | |
| 60 | − */ | |
| 61 | −void mpool_create (char* memory, size_t size, _tMempool* pool) | |
| 62 | −{ | |
| 63 | − leaf.header_size = mpool_align(sizeof(mpool_node_t)); | |
| 64 | − | |
| 65 | − pool->mpool = (char*)memory; | |
| 66 | − pool->usize = 0; | |
| 67 | − pool->msize = size; | |
| 68 | − | |
| 69 | − pool->head = create_node(pool->mpool, NULL, NULL, pool->msize-leaf.header_size); | |
| 70 | − | |
| 71 | − /* | |
| 72 | − for (int i = 0; i < pool->head->size; i++) | |
| 73 | − { | |
| 74 | − memory[i+leaf.header_size]=0; | |
| 75 | − } | |
| 76 | − */ | |
| 77 | − //is zeroing out the memory necessary? This takes a long time on large pools - JS | |
| 78 | −} | |
| 79 | − | |
| 80 | −void leaf_pool_init(char* memory, size_t size) | |
| 81 | −{ | |
| 82 | − mpool_create(memory, size, &leaf._mempool); | |
| 83 | − | |
| 84 | − leaf.mempool = &leaf._mempool; | |
| 85 | −} | |
| 86 | − | |
| 87 | −/** | |
| 88 | − * allocate memory from memory pool | |
| 89 | − */ | |
| 90 | −char* mpool_alloc(size_t asize, _tMempool* pool) | |
| 91 | −{ | |
| 92 | − // If the head is NULL, the mempool is full | |
| 93 | − if (pool->head == NULL) | |
| 94 | − { | |
| 95 | − leaf_mempool_overrun(); | |
| 96 | − return NULL; | |
| 97 | − } | |
| 98 | − | |
| 99 | − // Should we alloc the first block large enough or check all blocks and pick the one closest in size? | |
| 100 | − size_t size_to_alloc = mpool_align(asize); | |
| 101 | − mpool_node_t* node_to_alloc = pool->head; | |
| 102 | − | |
| 103 | − // Traverse the free list for a large enough block | |
| 104 | − while (node_to_alloc->size < size_to_alloc) | |
| 105 | − { | |
| 106 | − node_to_alloc = node_to_alloc->next; | |
| 107 | − | |
| 108 | − // If we reach the end of the free list, there | |
| 109 | − // are no blocks large enough, return NULL | |
| 110 | − if (node_to_alloc == NULL) | |
| 111 | − { | |
| 112 | − leaf_mempool_overrun(); | |
| 113 | − return NULL; | |
| 114 | − } | |
| 115 | − } | |
| 116 | − | |
| 117 | − // Create a new node after the node to be allocated if there is enough space | |
| 118 | − mpool_node_t* new_node; | |
| 119 | − size_t leftover = node_to_alloc->size - size_to_alloc; | |
| 120 | − node_to_alloc->size = size_to_alloc; | |
| 121 | − if (leftover > leaf.header_size) | |
| 122 | − { | |
| 123 | − long offset = (char*) node_to_alloc - (char*) pool->mpool; | |
| 124 | − offset += leaf.header_size + node_to_alloc->size; | |
| 125 | − new_node = create_node(&pool->mpool[offset], | |
| 126 | − node_to_alloc->next, | |
| 127 | − node_to_alloc->prev, | |
| 128 | − leftover - leaf.header_size); | |
| 129 | − } | |
| 130 | − else | |
| 131 | − { | |
| 132 | − // Add any leftover space to the allocated node to avoid fragmentation | |
| 133 | − node_to_alloc->size += leftover; | |
| 134 | − | |
| 135 | − new_node = node_to_alloc->next; | |
| 136 | − } | |
| 137 | − | |
| 138 | − // Update the head if we are allocating the first node of the free list | |
| 139 | − // The head will be NULL if there is no space left | |
| 140 | − if (pool->head == node_to_alloc) | |
| 141 | − { | |
| 142 | − pool->head = new_node; | |
| 143 | − } | |
| 144 | − | |
| 145 | − // Remove the allocated node from the free list | |
| 146 | − delink_node(node_to_alloc); | |
| 147 | − | |
| 148 | − pool->usize += leaf.header_size + node_to_alloc->size; | |
| 149 | − | |
| 150 | − if (leaf.clearOnAllocation > 0) | |
| 151 | − { | |
| 152 | − char* new_pool = (char*)node_to_alloc->pool; | |
| 153 | − for (int i = 0; i < node_to_alloc->size; i++) new_pool[i] = 0; | |
| 154 | − } | |
| 155 | − | |
| 156 | − // Return the pool of the allocated node; | |
| 157 | − return node_to_alloc->pool; | |
| 158 | −} | |
| 159 | − | |
| 160 | − | |
| 161 | −/** | |
| 162 | − * allocate memory from memory pool and also clear that memory to be blank | |
| 163 | − */ | |
| 164 | −char* mpool_calloc(size_t asize, _tMempool* pool) | |
| 165 | −{ | |
| 166 | − // If the head is NULL, the mempool is full | |
| 167 | − if (pool->head == NULL) | |
| 168 | − { | |
| 169 | − leaf_mempool_overrun(); | |
| 170 | − return NULL; | |
| 171 | − } | |
| 172 | − | |
| 173 | − // Should we alloc the first block large enough or check all blocks and pick the one closest in size? | |
| 174 | − size_t size_to_alloc = mpool_align(asize); | |
| 175 | − mpool_node_t* node_to_alloc = pool->head; | |
| 176 | − | |
| 177 | − // Traverse the free list for a large enough block | |
| 178 | − while (node_to_alloc->size < size_to_alloc) | |
| 179 | − { | |
| 180 | − node_to_alloc = node_to_alloc->next; | |
| 181 | − | |
| 182 | − // If we reach the end of the free list, there | |
| 183 | − // are no blocks large enough, return NULL | |
| 184 | − if (node_to_alloc == NULL) | |
| 185 | − { | |
| 186 | − leaf_mempool_overrun(); | |
| 187 | − return NULL; | |
| 188 | − } | |
| 189 | − } | |
| 190 | − | |
| 191 | − // Create a new node after the node to be allocated if there is enough space | |
| 192 | − mpool_node_t* new_node; | |
| 193 | − size_t leftover = node_to_alloc->size - size_to_alloc; | |
| 194 | − node_to_alloc->size = size_to_alloc; | |
| 195 | − if (leftover > leaf.header_size) | |
| 196 | − { | |
| 197 | − long offset = (char*) node_to_alloc - (char*) pool->mpool; | |
| 198 | − offset += leaf.header_size + node_to_alloc->size; | |
| 199 | − new_node = create_node(&pool->mpool[offset], | |
| 200 | − node_to_alloc->next, | |
| 201 | − node_to_alloc->prev, | |
| 202 | − leftover - leaf.header_size); | |
| 203 | − } | |
| 204 | − else | |
| 205 | − { | |
| 206 | − // Add any leftover space to the allocated node to avoid fragmentation | |
| 207 | − node_to_alloc->size += leftover; | |
| 208 | − | |
| 209 | − new_node = node_to_alloc->next; | |
| 210 | − } | |
| 211 | − | |
| 212 | − // Update the head if we are allocating the first node of the free list | |
| 213 | − // The head will be NULL if there is no space left | |
| 214 | − if (pool->head == node_to_alloc) | |
| 215 | − { | |
| 216 | − pool->head = new_node; | |
| 217 | − } | |
| 218 | − | |
| 219 | − // Remove the allocated node from the free list | |
| 220 | − delink_node(node_to_alloc); | |
| 221 | − | |
| 222 | − pool->usize += leaf.header_size + node_to_alloc->size; | |
| 223 | − // Format the new pool | |
| 224 | − char* new_pool = (char*)node_to_alloc->pool; | |
| 225 | − for (int i = 0; i < node_to_alloc->size; i++) new_pool[i] = 0; | |
| 226 | − // Return the pool of the allocated node; | |
| 227 | − return node_to_alloc->pool; | |
| 228 | −} | |
| 229 | − | |
| 230 | −char* leaf_alloc(size_t size) | |
| 231 | −{ | |
| 232 | − //printf("alloc %i\n", size); | |
| 233 | − char* block = mpool_alloc(size, &leaf._mempool); | |
| 234 | − | |
| 235 | − if (block == NULL) leaf_mempool_overrun(); | |
| 236 | − | |
| 237 | − return block; | |
| 238 | −} | |
| 239 | − | |
| 240 | −char* leaf_calloc(size_t size) | |
| 241 | −{ | |
| 242 | − //printf("alloc %i\n", size); | |
| 243 | − char* block = mpool_calloc(size, &leaf._mempool); | |
| 244 | − | |
| 245 | − if (block == NULL) leaf_mempool_overrun(); | |
| 246 | − | |
| 247 | − | |
| 248 | − return block; | |
| 249 | −} | |
| 250 | − | |
| 251 | −void mpool_free(char* ptr, _tMempool* pool) | |
| 252 | −{ | |
| 253 | − //if (ptr < pool->mpool || ptr >= pool->mpool + pool->msize) | |
| 254 | − // Get the node at the freed space | |
| 255 | − mpool_node_t* freed_node = (mpool_node_t*) (ptr - leaf.header_size); | |
| 256 | − | |
| 257 | − pool->usize -= leaf.header_size + freed_node->size; | |
| 258 | − | |
| 259 | − // Check each node in the list against the newly freed one to see if it's adjacent in memory | |
| 260 | − mpool_node_t* other_node = pool->head; | |
| 261 | − mpool_node_t* next_node; | |
| 262 | − while (other_node != NULL) | |
| 263 | − { | |
| 264 | − next_node = other_node->next; | |
| 265 | − // Check if a node is directly after the freed node | |
| 266 | − if ((long) freed_node + (leaf.header_size + freed_node->size) == (long) other_node) | |
| 267 | − { | |
| 268 | − // Increase freed node's size | |
| 269 | − freed_node->size += leaf.header_size + other_node->size; | |
| 270 | − // If we are merging with the head, move the head forward | |
| 271 | − if (other_node == pool->head) pool->head = pool->head->next; | |
| 272 | − // Delink the merged node | |
| 273 | − delink_node(other_node); | |
| 274 | − } | |
| 275 | − | |
| 276 | − // Check if a node is directly before the freed node | |
| 277 | − else if ((long) other_node + (leaf.header_size + other_node->size) == (long) freed_node) | |
| 278 | − { | |
| 279 | − // Increase the merging node's size | |
| 280 | − other_node->size += leaf.header_size + freed_node->size; | |
| 281 | − | |
| 282 | − if (other_node != pool->head) | |
| 283 | − { | |
| 284 | − // Delink the merging node | |
| 285 | − delink_node(other_node); | |
| 286 | − // Attach the merging node to the head | |
| 287 | − other_node->next = pool->head; | |
| 288 | − // Merge | |
| 289 | − freed_node = other_node; | |
| 290 | − } | |
| 291 | − else | |
| 292 | − { | |
| 293 | − // If we are merging with the head, move the head forward | |
| 294 | − pool->head = pool->head->next; | |
| 295 | − // Merge | |
| 296 | − freed_node = other_node; | |
| 297 | − } | |
| 298 | − } | |
| 299 | − | |
| 300 | − other_node = next_node; | |
| 301 | − } | |
| 302 | − | |
| 303 | − // Ensure the freed node is attached to the head | |
| 304 | − freed_node->next = pool->head; | |
| 305 | − if (pool->head != NULL) pool->head->prev = freed_node; | |
| 306 | − pool->head = freed_node; | |
| 307 | − | |
| 308 | − // Format the freed pool | |
| 309 | − // char* freed_pool = (char*)freed_node->pool; | |
| 310 | − // for (int i = 0; i < freed_node->size; i++) freed_pool[i] = 0; | |
| 311 | −} | |
| 312 | − | |
| 313 | −void leaf_free(char* ptr) | |
| 314 | −{ | |
| 315 | − mpool_free(ptr, &leaf._mempool); | |
| 316 | −} | |
| 317 | − | |
| 318 | −size_t mpool_get_size(_tMempool* pool) | |
| 319 | −{ | |
| 320 | − return pool->msize; | |
| 321 | −} | |
| 322 | − | |
| 323 | −size_t mpool_get_used(_tMempool* pool) | |
| 324 | −{ | |
| 325 | − return pool->usize; | |
| 326 | −} | |
| 327 | − | |
| 328 | −size_t leaf_pool_get_size(void) | |
| 329 | −{ | |
| 330 | − return mpool_get_size(&leaf._mempool); | |
| 331 | −} | |
| 332 | − | |
| 333 | −size_t leaf_pool_get_used(void) | |
| 334 | −{ | |
| 335 | − return mpool_get_used(&leaf._mempool); | |
| 336 | −} | |
| 337 | − | |
| 338 | −char* leaf_pool_get_pool(void) | |
| 339 | −{ | |
| 340 | − char* buff = leaf._mempool.mpool; | |
| 341 | − | |
| 342 | − return buff; | |
| 343 | −} | |
| 344 | − | |
| 345 | −/** | |
| 346 | − * align byte boundary | |
| 347 | − */ | |
| 348 | −static inline size_t mpool_align(size_t size) { | |
| 349 | − return (size + (MPOOL_ALIGN_SIZE - 1)) & ~(MPOOL_ALIGN_SIZE - 1); | |
| 350 | −} | |
| 351 | − | |
| 352 | −static inline mpool_node_t* create_node(char* block_location, mpool_node_t* next, mpool_node_t* prev, size_t size) | |
| 353 | −{ | |
| 354 | − mpool_node_t* node = (mpool_node_t*)block_location; | |
| 355 | − node->pool = block_location + leaf.header_size; | |
| 356 | − node->next = next; | |
| 357 | − node->prev = prev; | |
| 358 | − node->size = size; | |
| 359 | − | |
| 360 | − return node; | |
| 361 | −} | |
| 362 | − | |
| 363 | −static inline void delink_node(mpool_node_t* node) | |
| 364 | −{ | |
| 365 | − // If there is a node after the node to remove | |
| 366 | − if (node->next != NULL) | |
| 367 | − { | |
| 368 | − // Close the link | |
| 369 | − node->next->prev = node->prev; | |
| 370 | − } | |
| 371 | − // If there is a node before the node to remove | |
| 372 | − if (node->prev != NULL) | |
| 373 | − { | |
| 374 | − // Close the link | |
| 375 | − node->prev->next = node->next; | |
| 376 | − } | |
| 377 | − | |
| 378 | − node->next = NULL; | |
| 379 | − node->prev = NULL; | |
| 380 | −} | |
| 381 | − | |
| 382 | −void leaf_mempool_overrun(void) | |
| 383 | −{ | |
| 384 | − LEAF_error(1); | |
| 385 | − //TODO: we should make a set of real error codes that are in an enum type | |
| 386 | −} | |
| 387 | − | |
| 388 | −void tMempool_init(tMempool* const mp, char* memory, size_t size) | |
| 389 | −{ | |
| 390 | − tMempool_initToPool(mp, memory, size, &leaf.mempool); | |
| 391 | −} | |
| 392 | − | |
| 393 | −void tMempool_free(tMempool* const mp) | |
| 394 | −{ | |
| 395 | − tMempool_freeFromPool(mp, &leaf.mempool); | |
| 396 | −} | |
| 397 | − | |
| 398 | −void tMempool_initToPool (tMempool* const mp, char* memory, size_t size, tMempool* const mem) | |
| 399 | −{ | |
| 400 | − _tMempool* mm = *mem; | |
| 401 | − _tMempool* m = *mp = (_tMempool*) mpool_alloc(sizeof(_tMempool), mm); | |
| 402 | − | |
| 403 | − mpool_create (memory, size, m); | |
| 404 | −} | |
| 405 | − | |
| 406 | −void tMempool_freeFromPool (tMempool* const mp, tMempool* const mem) | |
| 407 | −{ | |
| 408 | − _tMempool* mm = *mem; | |
| 409 | − _tMempool* m = *mp; | |
| 410 | − | |
| 411 | − mpool_free((char*)m, mm); | |
| 412 | −} | |
| @@ -1,980 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-midi.c | |
| 4 | − Created: 30 Nov 2018 11:29:16am | |
| 5 | − Author: airship | |
| 6 | − | |
| 7 | −==============================================================================*/ | |
| 8 | − | |
| 9 | −#if _WIN32 || _WIN64 | |
| 10 | − | |
| 11 | −#include "..\Inc\leaf-midi.h" | |
| 12 | − | |
| 13 | −#else | |
| 14 | − | |
| 15 | −#include "../Inc/leaf-midi.h" | |
| 16 | − | |
| 17 | −#endif | |
| 18 | − | |
| 19 | −//==================================================================================== | |
| 20 | −/* Stack */ | |
| 21 | −//==================================================================================== | |
| 22 | − | |
| 23 | −void tStack_init(tStack* const stack) | |
| 24 | −{ | |
| 25 | − _tStack* ns = *stack = (_tStack*) leaf_alloc(sizeof(_tStack)); | |
| 26 | − | |
| 27 | − ns->ordered = OFALSE; | |
| 28 | − ns->size = 0; | |
| 29 | − ns->pos = 0; | |
| 30 | − ns->capacity = STACK_SIZE; | |
| 31 | − | |
| 32 | − for (int i = 0; i < STACK_SIZE; i++) ns->data[i] = -1; | |
| 33 | −} | |
| 34 | − | |
| 35 | −void tStack_free(tStack* const stack) | |
| 36 | −{ | |
| 37 | − _tStack* ns = *stack; | |
| 38 | − | |
| 39 | − leaf_free((char*)ns); | |
| 40 | −} | |
| 41 | − | |
| 42 | −void tStack_initToPool (tStack* const stack, tMempool* const mp) | |
| 43 | −{ | |
| 44 | − _tMempool* m = *mp; | |
| 45 | − _tStack* ns = *stack = (_tStack*) mpool_alloc(sizeof(_tStack), m); | |
| 46 | − | |
| 47 | − ns->ordered = OFALSE; | |
| 48 | − ns->size = 0; | |
| 49 | − ns->pos = 0; | |
| 50 | − ns->capacity = STACK_SIZE; | |
| 51 | − | |
| 52 | − for (int i = 0; i < STACK_SIZE; i++) ns->data[i] = -1; | |
| 53 | −} | |
| 54 | − | |
| 55 | −void tStack_freeFromPool (tStack* const stack, tMempool* const mp) | |
| 56 | −{ | |
| 57 | − _tMempool* m = *mp; | |
| 58 | − _tStack* ns = *stack; | |
| 59 | − | |
| 60 | − mpool_free((char*)ns, m); | |
| 61 | −} | |
| 62 | − | |
| 63 | −// If stack contains note, returns index. Else returns -1; | |
| 64 | −int tStack_contains(tStack* const stack, uint16_t noteVal) | |
| 65 | −{ | |
| 66 | − _tStack* ns = *stack; | |
| 67 | − for (int i = 0; i < ns->size; i++) | |
| 68 | − { | |
| 69 | − if (ns->data[i] == noteVal) return i; | |
| 70 | − } | |
| 71 | − return -1; | |
| 72 | −} | |
| 73 | − | |
| 74 | −void tStack_add(tStack* const stack, uint16_t noteVal) | |
| 75 | −{ | |
| 76 | − _tStack* ns = *stack; | |
| 77 | − | |
| 78 | − uint8_t j; | |
| 79 | − | |
| 80 | − int whereToInsert = 0; | |
| 81 | − if (ns->ordered) | |
| 82 | − { | |
| 83 | − for (j = 0; j < ns->size; j++) | |
| 84 | − { | |
| 85 | − if (noteVal > ns->data[j]) | |
| 86 | − { | |
| 87 | − if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1)) | |
| 88 | − { | |
| 89 | − whereToInsert = j+1; | |
| 90 | − break; | |
| 91 | − } | |
| 92 | − } | |
| 93 | − } | |
| 94 | − } | |
| 95 | − | |
| 96 | − //first move notes that are already in the stack one position to the right | |
| 97 | − for (j = ns->size; j > whereToInsert; j--) | |
| 98 | − { | |
| 99 | − ns->data[j] = ns->data[(j - 1)]; | |
| 100 | − } | |
| 101 | − | |
| 102 | − //then, insert the new note into the front of the stack | |
| 103 | − ns->data[whereToInsert] = noteVal; | |
| 104 | − | |
| 105 | − ns->size++; | |
| 106 | −} | |
| 107 | − | |
| 108 | −int tStack_addIfNotAlreadyThere(tStack* const stack, uint16_t noteVal) | |
| 109 | −{ | |
| 110 | − _tStack* ns = *stack; | |
| 111 | − | |
| 112 | − uint8_t j; | |
| 113 | − | |
| 114 | − int added = 0; | |
| 115 | − | |
| 116 | − if (tStack_contains(stack, noteVal) == -1) | |
| 117 | − { | |
| 118 | − int whereToInsert = 0; | |
| 119 | − if (ns->ordered) | |
| 120 | − { | |
| 121 | − for (j = 0; j < ns->size; j++) | |
| 122 | − { | |
| 123 | − if (noteVal > ns->data[j]) | |
| 124 | − { | |
| 125 | − if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1)) | |
| 126 | − { | |
| 127 | − whereToInsert = j+1; | |
| 128 | − break; | |
| 129 | − } | |
| 130 | − } | |
| 131 | − } | |
| 132 | − } | |
| 133 | − | |
| 134 | − //first move notes that are already in the stack one position to the right | |
| 135 | − for (j = ns->size; j > whereToInsert; j--) | |
| 136 | − { | |
| 137 | − ns->data[j] = ns->data[(j - 1)]; | |
| 138 | − } | |
| 139 | − | |
| 140 | − //then, insert the new note into the front of the stack | |
| 141 | − ns->data[whereToInsert] = noteVal; | |
| 142 | − | |
| 143 | − ns->size++; | |
| 144 | − | |
| 145 | − added = 1; | |
| 146 | − } | |
| 147 | − | |
| 148 | − return added; | |
| 149 | −} | |
| 150 | − | |
| 151 | −// Remove noteVal. return 1 if removed, 0 if not | |
| 152 | −int tStack_remove(tStack* const stack, uint16_t noteVal) | |
| 153 | −{ | |
| 154 | − _tStack* ns = *stack; | |
| 155 | − | |
| 156 | − uint8_t k; | |
| 157 | − int foundIndex = tStack_contains(stack, noteVal); | |
| 158 | − int removed = 0; | |
| 159 | − | |
| 160 | − if (foundIndex >= 0) | |
| 161 | − { | |
| 162 | − for (k = 0; k < (ns->size - foundIndex); k++) | |
| 163 | − { | |
| 164 | − if ((k+foundIndex) >= (ns->capacity - 1)) | |
| 165 | − { | |
| 166 | − ns->data[k + foundIndex] = -1; | |
| 167 | − } | |
| 168 | − else | |
| 169 | − { | |
| 170 | − ns->data[k + foundIndex] = ns->data[k + foundIndex + 1]; | |
| 171 | − if ((k + foundIndex) == (ns->size - 1)) | |
| 172 | − { | |
| 173 | − ns->data[k + foundIndex + 1] = -1; | |
| 174 | − } | |
| 175 | − } | |
| 176 | − | |
| 177 | − } | |
| 178 | − // in case it got put on the stack multiple times | |
| 179 | − foundIndex--; | |
| 180 | − ns->size--; | |
| 181 | − removed = 1; | |
| 182 | − } | |
| 183 | − | |
| 184 | − return removed; | |
| 185 | −} | |
| 186 | − | |
| 187 | −// Doesn't change size of data types | |
| 188 | −void tStack_setCapacity(tStack* const stack, uint16_t cap) | |
| 189 | −{ | |
| 190 | − _tStack* ns = *stack; | |
| 191 | − | |
| 192 | − if (cap <= 0) | |
| 193 | − ns->capacity = 1; | |
| 194 | − else if (cap <= STACK_SIZE) | |
| 195 | − ns->capacity = cap; | |
| 196 | − else | |
| 197 | − ns->capacity = STACK_SIZE; | |
| 198 | − | |
| 199 | − for (int i = cap; i < STACK_SIZE; i++) | |
| 200 | − { | |
| 201 | − if ((int)ns->data[i] != -1) | |
| 202 | − { | |
| 203 | − ns->data[i] = -1; | |
| 204 | − ns->size -= 1; | |
| 205 | − } | |
| 206 | − } | |
| 207 | − | |
| 208 | − if (ns->pos >= cap) | |
| 209 | − { | |
| 210 | − ns->pos = 0; | |
| 211 | − } | |
| 212 | −} | |
| 213 | − | |
| 214 | −int tStack_getSize(tStack* const stack) | |
| 215 | −{ | |
| 216 | − _tStack* ns = *stack; | |
| 217 | − | |
| 218 | − return ns->size; | |
| 219 | −} | |
| 220 | − | |
| 221 | −void tStack_clear(tStack* const stack) | |
| 222 | −{ | |
| 223 | − _tStack* ns = *stack; | |
| 224 | − | |
| 225 | − for (int i = 0; i < STACK_SIZE; i++) | |
| 226 | − { | |
| 227 | − ns->data[i] = -1; | |
| 228 | − } | |
| 229 | − ns->pos = 0; | |
| 230 | − ns->size = 0; | |
| 231 | −} | |
| 232 | − | |
| 233 | −// Next item in order of addition to stack. Return 0-31 if there is a next item to move to. Returns -1 otherwise. | |
| 234 | −int tStack_next(tStack* const stack) | |
| 235 | −{ | |
| 236 | − _tStack* ns = *stack; | |
| 237 | − | |
| 238 | − int step = 0; | |
| 239 | − if (ns->size != 0) // if there is at least one note in the stack | |
| 240 | − { | |
| 241 | − if (ns->pos > 0) // if you're not at the most recent note (first one), then go backward in the array (moving from earliest to latest) | |
| 242 | − { | |
| 243 | − ns->pos--; | |
| 244 | − } | |
| 245 | − else | |
| 246 | − { | |
| 247 | − ns->pos = (ns->size - 1); // if you are the most recent note, go back to the earliest note in the array | |
| 248 | − } | |
| 249 | − | |
| 250 | − step = ns->data[ns->pos]; | |
| 251 | − return step; | |
| 252 | − } | |
| 253 | − else | |
| 254 | − { | |
| 255 | − return -1; | |
| 256 | − } | |
| 257 | −} | |
| 258 | − | |
| 259 | −int tStack_get(tStack* const stack, int which) | |
| 260 | −{ | |
| 261 | − _tStack* ns = *stack; | |
| 262 | − return ns->data[which]; | |
| 263 | −} | |
| 264 | − | |
| 265 | −int tStack_first(tStack* const stack) | |
| 266 | −{ | |
| 267 | − _tStack* ns = *stack; | |
| 268 | − return ns->data[0]; | |
| 269 | −} | |
| 270 | − | |
| 271 | − | |
| 272 | −// POLY | |
| 273 | −void tPoly_init(tPoly* const polyh, int maxNumVoices) | |
| 274 | −{ | |
| 275 | − _tPoly* poly = *polyh = (_tPoly*) leaf_alloc(sizeof(_tPoly)); | |
| 276 | − | |
| 277 | − poly->numVoices = maxNumVoices; | |
| 278 | − poly->maxNumVoices = maxNumVoices; | |
| 279 | − poly->lastVoiceToChange = 0; | |
| 280 | − | |
| 281 | − // Arp mode stuff | |
| 282 | − poly->currentVoice = 0; | |
| 283 | − poly->maxLength = 128; | |
| 284 | − poly->currentNote = -1; | |
| 285 | − | |
| 286 | − //default learned CCs and notes are just the CCs 1-128 - notes are skipped | |
| 287 | − for (int i = 0; i < 128; i++) | |
| 288 | − { | |
| 289 | − poly->notes[i][0] = 0; | |
| 290 | − poly->notes[i][1] = -1; | |
| 291 | − } | |
| 292 | − | |
| 293 | − poly->glideTime = 5.0f; | |
| 294 | − | |
| 295 | − poly->ramps = (tRamp*) leaf_alloc(sizeof(tRamp) * poly->maxNumVoices); | |
| 296 | − poly->rampVals = (float*) leaf_alloc(sizeof(float) * poly->maxNumVoices); | |
| 297 | − poly->firstReceived = (oBool*) leaf_alloc(sizeof(oBool) * poly->maxNumVoices); | |
| 298 | − poly->voices = (int**) leaf_alloc(sizeof(int*) * poly->maxNumVoices); | |
| 299 | − | |
| 300 | − for (int i = 0; i < poly->maxNumVoices; ++i) | |
| 301 | − { | |
| 302 | − poly->voices[i] = (int*) leaf_alloc(sizeof(int) * 2); | |
| 303 | − poly->voices[i][0] = -1; | |
| 304 | − poly->firstReceived[i] = OFALSE; | |
| 305 | − | |
| 306 | − tRamp_init(&poly->ramps[i], poly->glideTime, 1); | |
| 307 | − } | |
| 308 | − | |
| 309 | − poly->pitchBend = 0.0f; | |
| 310 | − | |
| 311 | − tRamp_init(&poly->pitchBendRamp, 1.0f, 1); | |
| 312 | − tStack_init(&poly->stack); | |
| 313 | − tStack_init(&poly->orderStack); | |
| 314 | − | |
| 315 | − poly->pitchGlideIsActive = OFALSE; | |
| 316 | −} | |
| 317 | − | |
| 318 | −void tPoly_free(tPoly* const polyh) | |
| 319 | −{ | |
| 320 | − _tPoly* poly = *polyh; | |
| 321 | − | |
| 322 | − for (int i = 0; i < poly->maxNumVoices; i++) | |
| 323 | − { | |
| 324 | − tRamp_free(&poly->ramps[i]); | |
| 325 | − leaf_free((char*)poly->voices[i]); | |
| 326 | − } | |
| 327 | − tRamp_free(&poly->pitchBendRamp); | |
| 328 | − tStack_free(&poly->stack); | |
| 329 | − tStack_free(&poly->orderStack); | |
| 330 | − | |
| 331 | − leaf_free((char*)poly->voices); | |
| 332 | − leaf_free((char*)poly->ramps); | |
| 333 | − leaf_free((char*)poly->rampVals); | |
| 334 | − leaf_free((char*)poly->firstReceived); | |
| 335 | − | |
| 336 | − leaf_free((char*)poly); | |
| 337 | −} | |
| 338 | − | |
| 339 | −void tPoly_initToPool (tPoly* const polyh, int maxNumVoices, tMempool* const mp) | |
| 340 | −{ | |
| 341 | − _tMempool* m = *mp; | |
| 342 | − _tPoly* poly = *polyh = (_tPoly*) mpool_alloc(sizeof(_tPoly), m); | |
| 343 | − | |
| 344 | − poly->numVoices = maxNumVoices; | |
| 345 | − poly->maxNumVoices = maxNumVoices; | |
| 346 | − poly->lastVoiceToChange = 0; | |
| 347 | − | |
| 348 | − // Arp mode stuff | |
| 349 | − poly->currentVoice = 0; | |
| 350 | − poly->maxLength = 128; | |
| 351 | − poly->currentNote = -1; | |
| 352 | − | |
| 353 | − //default learned CCs and notes are just the CCs 1-128 - notes are skipped | |
| 354 | − for (int i = 0; i < 128; i++) | |
| 355 | − { | |
| 356 | − poly->notes[i][0] = 0; | |
| 357 | − poly->notes[i][1] = -1; | |
| 358 | − } | |
| 359 | − | |
| 360 | − poly->glideTime = 5.0f; | |
| 361 | − | |
| 362 | − poly->ramps = (tRamp*) mpool_alloc(sizeof(tRamp) * poly->maxNumVoices, m); | |
| 363 | − poly->rampVals = (float*) mpool_alloc(sizeof(float) * poly->maxNumVoices, m); | |
| 364 | − poly->firstReceived = (oBool*) mpool_alloc(sizeof(oBool) * poly->maxNumVoices, m); | |
| 365 | − poly->voices = (int**) mpool_alloc(sizeof(int*) * poly->maxNumVoices, m); | |
| 366 | − | |
| 367 | − for (int i = 0; i < poly->maxNumVoices; ++i) | |
| 368 | − { | |
| 369 | − poly->voices[i] = (int*) mpool_alloc(sizeof(int) * 2, m); | |
| 370 | − poly->voices[i][0] = -1; | |
| 371 | − poly->firstReceived[i] = OFALSE; | |
| 372 | − | |
| 373 | − tRamp_initToPool(&poly->ramps[i], poly->glideTime, 1, mp); | |
| 374 | − } | |
| 375 | − | |
| 376 | − poly->pitchBend = 0.0f; | |
| 377 | − | |
| 378 | − tRamp_initToPool(&poly->pitchBendRamp, 1.0f, 1, mp); | |
| 379 | − tStack_initToPool(&poly->stack, mp); | |
| 380 | − tStack_initToPool(&poly->orderStack, mp); | |
| 381 | − | |
| 382 | − poly->pitchGlideIsActive = OFALSE; | |
| 383 | −} | |
| 384 | − | |
| 385 | −void tPoly_freeFromPool (tPoly* const polyh, tMempool* const mp) | |
| 386 | −{ | |
| 387 | − _tMempool* m = *mp; | |
| 388 | − _tPoly* poly = *polyh; | |
| 389 | − | |
| 390 | − for (int i = 0; i < poly->maxNumVoices; i++) | |
| 391 | − { | |
| 392 | − tRamp_freeFromPool(&poly->ramps[i], mp); | |
| 393 | − mpool_free((char*)poly->voices[i], m); | |
| 394 | − } | |
| 395 | − tRamp_freeFromPool(&poly->pitchBendRamp, mp); | |
| 396 | − tStack_freeFromPool(&poly->stack, mp); | |
| 397 | − tStack_freeFromPool(&poly->orderStack, mp); | |
| 398 | − | |
| 399 | − mpool_free((char*)poly->voices, m); | |
| 400 | − mpool_free((char*)poly->ramps, m); | |
| 401 | − mpool_free((char*)poly->rampVals, m); | |
| 402 | − mpool_free((char*)poly->firstReceived, m); | |
| 403 | − | |
| 404 | − mpool_free((char*)poly, m); | |
| 405 | −} | |
| 406 | − | |
| 407 | −void tPoly_tickPitch(tPoly* polyh) | |
| 408 | −{ | |
| 409 | − tPoly_tickPitchGlide(polyh); | |
| 410 | − tPoly_tickPitchBend(polyh); | |
| 411 | −} | |
| 412 | − | |
| 413 | −void tPoly_tickPitchGlide(tPoly* polyh) | |
| 414 | −{ | |
| 415 | − _tPoly* poly = *polyh; | |
| 416 | − for (int i = 0; i < poly->maxNumVoices; ++i) | |
| 417 | − { | |
| 418 | − tRamp_tick(&poly->ramps[i]); | |
| 419 | − } | |
| 420 | −} | |
| 421 | − | |
| 422 | −void tPoly_tickPitchBend(tPoly* polyh) | |
| 423 | −{ | |
| 424 | − _tPoly* poly = *polyh; | |
| 425 | − tRamp_tick(&poly->pitchBendRamp); | |
| 426 | −} | |
| 427 | − | |
| 428 | −void tPoly_setPitchBend(tPoly* const polyh, float pitchBend) | |
| 429 | −{ | |
| 430 | − _tPoly* poly = *polyh; | |
| 431 | − poly->pitchBend = pitchBend; | |
| 432 | − tRamp_setDest(&poly->pitchBendRamp, poly->pitchBend); | |
| 433 | −} | |
| 434 | − | |
| 435 | −int tPoly_noteOn(tPoly* const polyh, int note, uint8_t vel) | |
| 436 | −{ | |
| 437 | − _tPoly* poly = *polyh; | |
| 438 | − | |
| 439 | − // if not in keymap or already on stack, dont do anything. else, add that note. | |
| 440 | − if (tStack_contains(&poly->stack, note) >= 0) return -1; | |
| 441 | − else | |
| 442 | − { | |
| 443 | − tPoly_orderedAddToStack(polyh, note); | |
| 444 | − tStack_add(&poly->stack, note); | |
| 445 | − | |
| 446 | − int alteredVoice = -1; | |
| 447 | − oBool found = OFALSE; | |
| 448 | − for (int i = 0; i < poly->numVoices; i++) | |
| 449 | − { | |
| 450 | − if (poly->voices[i][0] < 0) // if inactive voice, give this note to voice | |
| 451 | − { | |
| 452 | − if (!poly->firstReceived[i] || !poly->pitchGlideIsActive) | |
| 453 | − { | |
| 454 | − tRamp_setVal(&poly->ramps[i], note); | |
| 455 | − poly->firstReceived[i] = OTRUE; | |
| 456 | − } | |
| 457 | − | |
| 458 | − found = OTRUE; | |
| 459 | − | |
| 460 | − poly->voices[i][0] = note; | |
| 461 | − poly->voices[i][1] = vel; | |
| 462 | − poly->lastVoiceToChange = i; | |
| 463 | − poly->notes[note][0] = vel; | |
| 464 | − poly->notes[note][1] = i; | |
| 465 | − | |
| 466 | − tRamp_setDest(&poly->ramps[i], poly->voices[i][0]); | |
| 467 | − | |
| 468 | − alteredVoice = i; | |
| 469 | − break; | |
| 470 | − } | |
| 471 | − } | |
| 472 | − | |
| 473 | − if (!found) //steal | |
| 474 | − { | |
| 475 | − int whichVoice, whichNote; | |
| 476 | − for (int j = tStack_getSize(&poly->stack) - 1; j >= 0; j--) | |
| 477 | − { | |
| 478 | − whichNote = tStack_get(&poly->stack, j); | |
| 479 | − whichVoice = poly->notes[whichNote][1]; | |
| 480 | − if (whichVoice >= 0) | |
| 481 | − { | |
| 482 | − poly->lastVoiceToChange = whichVoice; | |
| 483 | − int oldNote = poly->voices[whichVoice][0]; | |
| 484 | − poly->voices[whichVoice][0] = note; | |
| 485 | − poly->voices[whichVoice][1] = vel; | |
| 486 | − poly->notes[oldNote][1] = -1; //mark the stolen voice as inactive (in the second dimension of the notes array) | |
| 487 | − poly->notes[note][0] = vel; | |
| 488 | − poly->notes[note][1] = whichVoice; | |
| 489 | − | |
| 490 | − if (poly->pitchGlideIsActive) | |
| 491 | − { | |
| 492 | − tRamp_setTime(&poly->ramps[whichVoice], poly->glideTime); | |
| 493 | − } | |
| 494 | − else | |
| 495 | − { | |
| 496 | − tRamp_setVal(&poly->ramps[whichVoice], note); | |
| 497 | − } | |
| 498 | − tRamp_setDest(&poly->ramps[whichVoice], poly->voices[whichVoice][0]); | |
| 499 | − | |
| 500 | − alteredVoice = whichVoice; | |
| 501 | − | |
| 502 | − break; | |
| 503 | − } | |
| 504 | − } | |
| 505 | − } | |
| 506 | − return alteredVoice; | |
| 507 | − } | |
| 508 | −} | |
| 509 | − | |
| 510 | − | |
| 511 | −int16_t noteToTest = -1; | |
| 512 | − | |
| 513 | −int tPoly_noteOff(tPoly* const polyh, uint8_t note) | |
| 514 | −{ | |
| 515 | − _tPoly* poly = *polyh; | |
| 516 | − | |
| 517 | − tStack_remove(&poly->stack, note); | |
| 518 | − tStack_remove(&poly->orderStack, note); | |
| 519 | − poly->notes[note][0] = 0; | |
| 520 | − poly->notes[note][1] = -1; | |
| 521 | − | |
| 522 | − int deactivatedVoice = -1; | |
| 523 | − for (int i = 0; i < poly->maxNumVoices; i++) | |
| 524 | − { | |
| 525 | − if (poly->voices[i][0] == note) | |
| 526 | − { | |
| 527 | − poly->voices[i][0] = -1; | |
| 528 | − poly->voices[i][1] = 0; | |
| 529 | − poly->lastVoiceToChange = i; | |
| 530 | − deactivatedVoice = i; | |
| 531 | − break; | |
| 532 | − } | |
| 533 | − } | |
| 534 | − /* | |
| 535 | − //monophonic handling | |
| 536 | − if ((poly->numVoices == 1) && (tStack_getSize(poly->stack) > 0)) | |
| 537 | − { | |
| 538 | − int oldNote = tStack_first(poly->stack); | |
| 539 | − poly->voices[0][0] = oldNote; | |
| 540 | − poly->voices[0][1] = poly->notes[oldNote][0]; | |
| 541 | − poly->lastVoiceToChange = 0; | |
| 542 | − } | |
| 543 | − */ | |
| 544 | − | |
| 545 | − //grab old notes off the stack if there are notes waiting to replace the free voice | |
| 546 | − if (deactivatedVoice >= 0) | |
| 547 | − { | |
| 548 | − for (int j = 0; j < tStack_getSize(&poly->stack); ++j) | |
| 549 | − { | |
| 550 | − noteToTest = tStack_get(&poly->stack, j); | |
| 551 | − | |
| 552 | − if (poly->notes[noteToTest][1] < 0) //if there is a stolen note waiting (marked inactive but on the stack) | |
| 553 | − { | |
| 554 | − poly->voices[deactivatedVoice][0] = noteToTest; //set the newly free voice to use the old stolen note | |
| 555 | − if (poly->pitchGlideIsActive) | |
| 556 | − { | |
| 557 | − tRamp_setTime(&poly->ramps[deactivatedVoice], poly->glideTime); | |
| 558 | − } | |
| 559 | − else | |
| 560 | − { | |
| 561 | − tRamp_setVal(&poly->ramps[deactivatedVoice], noteToTest); | |
| 562 | − } | |
| 563 | − tRamp_setDest(&poly->ramps[deactivatedVoice], poly->voices[deactivatedVoice][0]); | |
| 564 | − poly->voices[deactivatedVoice][1] = poly->notes[noteToTest][0]; // set the velocity of the voice to be the velocity of that note | |
| 565 | − poly->notes[noteToTest][1] = deactivatedVoice; //mark that it is no longer stolen and is now active | |
| 566 | − return -1; | |
| 567 | − } | |
| 568 | − } | |
| 569 | − } | |
| 570 | − return deactivatedVoice; | |
| 571 | −} | |
| 572 | − | |
| 573 | −void tPoly_orderedAddToStack(tPoly* const polyh, uint8_t noteVal) | |
| 574 | −{ | |
| 575 | − _tPoly* poly = *polyh; | |
| 576 | − | |
| 577 | − uint8_t j; | |
| 578 | − int myPitch, thisPitch, nextPitch; | |
| 579 | − | |
| 580 | − tStack ns = poly->orderStack; | |
| 581 | − | |
| 582 | − int whereToInsert = 0; | |
| 583 | − | |
| 584 | − for (j = 0; j < ns->size; j++) | |
| 585 | − { | |
| 586 | − myPitch = noteVal; | |
| 587 | − thisPitch = ns->data[j]; | |
| 588 | − nextPitch = ns->data[j+1]; | |
| 589 | − | |
| 590 | − if (myPitch > thisPitch) | |
| 591 | − { | |
| 592 | − if ((myPitch < nextPitch) || (nextPitch == -1)) | |
| 593 | − { | |
| 594 | − whereToInsert = j+1; | |
| 595 | − break; | |
| 596 | − } | |
| 597 | − } | |
| 598 | − } | |
| 599 | − | |
| 600 | − //first move notes that are already in the stack one position to the right | |
| 601 | − for (j = ns->size; j > whereToInsert; j--) | |
| 602 | − { | |
| 603 | − ns->data[j] = ns->data[(j - 1)]; | |
| 604 | − } | |
| 605 | − | |
| 606 | − //then, insert the new note into the front of the stack | |
| 607 | − ns->data[whereToInsert] = noteVal; | |
| 608 | − | |
| 609 | − ns->size++; | |
| 610 | − | |
| 611 | −} | |
| 612 | − | |
| 613 | −void tPoly_setNumVoices(tPoly* const polyh, uint8_t numVoices) | |
| 614 | −{ | |
| 615 | − _tPoly* poly = *polyh; | |
| 616 | − poly->numVoices = (numVoices > poly->maxNumVoices) ? poly->maxNumVoices : numVoices; | |
| 617 | −} | |
| 618 | − | |
| 619 | −void tPoly_setPitchGlideActive(tPoly* const polyh, oBool isActive) | |
| 620 | −{ | |
| 621 | − _tPoly* poly = *polyh; | |
| 622 | − poly->pitchGlideIsActive = isActive; | |
| 623 | −} | |
| 624 | − | |
| 625 | −void tPoly_setPitchGlideTime(tPoly* const polyh, float t) | |
| 626 | −{ | |
| 627 | − _tPoly* poly = *polyh; | |
| 628 | − poly->glideTime = t; | |
| 629 | − for (int i = 0; i < poly->maxNumVoices; ++i) | |
| 630 | − { | |
| 631 | − tRamp_setTime(&poly->ramps[i], poly->glideTime); | |
| 632 | − } | |
| 633 | −} | |
| 634 | − | |
| 635 | −void tPoly_setBendGlideTime(tPoly* const polyh, float t) | |
| 636 | −{ | |
| 637 | − _tPoly* poly = *polyh; | |
| 638 | − tRamp_setTime(&poly->pitchBendRamp, t); | |
| 639 | −} | |
| 640 | − | |
| 641 | −void tPoly_setBendSamplesPerTick(tPoly* const polyh, float t) | |
| 642 | −{ | |
| 643 | − _tPoly* poly = *polyh; | |
| 644 | − poly->pitchBendRamp->samples_per_tick = t; | |
| 645 | −} | |
| 646 | − | |
| 647 | −int tPoly_getNumVoices(tPoly* const polyh) | |
| 648 | −{ | |
| 649 | − _tPoly* poly = *polyh; | |
| 650 | − return poly->numVoices; | |
| 651 | −} | |
| 652 | − | |
| 653 | −int tPoly_getNumActiveVoices(tPoly* const polyh) | |
| 654 | −{ | |
| 655 | − _tPoly* poly = *polyh; | |
| 656 | − return LEAF_clip(0, tStack_getSize(&poly->stack), poly->numVoices); | |
| 657 | −} | |
| 658 | − | |
| 659 | −float tPoly_getPitch(tPoly* const polyh, uint8_t voice) | |
| 660 | −{ | |
| 661 | − _tPoly* poly = *polyh; | |
| 662 | − return tRamp_sample(&poly->ramps[voice]) + tRamp_sample(&poly->pitchBendRamp); | |
| 663 | −} | |
| 664 | − | |
| 665 | −int tPoly_getKey(tPoly* const polyh, uint8_t voice) | |
| 666 | −{ | |
| 667 | − _tPoly* poly = *polyh; | |
| 668 | − return poly->voices[voice][0]; | |
| 669 | −} | |
| 670 | − | |
| 671 | −int tPoly_getVelocity(tPoly* const polyh, uint8_t voice) | |
| 672 | −{ | |
| 673 | − _tPoly* poly = *polyh; | |
| 674 | − return poly->voices[voice][1]; | |
| 675 | −} | |
| 676 | − | |
| 677 | −int tPoly_isOn(tPoly* const polyh, uint8_t voice) | |
| 678 | −{ | |
| 679 | − _tPoly* poly = *polyh; | |
| 680 | − return (poly->voices[voice][0] > 0) ? 1 : 0; | |
| 681 | −} | |
| 682 | − | |
| 683 | − | |
| 684 | − | |
| 685 | − | |
| 686 | −//tSimplePoly = much more efficient implementation without ramps and glide | |
| 687 | − | |
| 688 | − | |
| 689 | −// SIMPLE POLY | |
| 690 | −void tSimplePoly_init(tSimplePoly* const polyh, int maxNumVoices) | |
| 691 | −{ | |
| 692 | − tSimplePoly_initToPool(polyh, maxNumVoices, &leaf.mempool); | |
| 693 | −} | |
| 694 | − | |
| 695 | −void tSimplePoly_free(tSimplePoly* const polyh) | |
| 696 | −{ | |
| 697 | − tSimplePoly_freeFromPool(polyh, &leaf.mempool); | |
| 698 | −} | |
| 699 | − | |
| 700 | −void tSimplePoly_initToPool (tSimplePoly* const polyh, int maxNumVoices, tMempool* const mp) | |
| 701 | −{ | |
| 702 | − _tMempool* m = *mp; | |
| 703 | − _tSimplePoly* poly = *polyh = (_tSimplePoly*) mpool_alloc(sizeof(_tSimplePoly), m); | |
| 704 | − | |
| 705 | − poly->numVoices = maxNumVoices; | |
| 706 | − poly->maxNumVoices = maxNumVoices; | |
| 707 | − | |
| 708 | − for (int i = 0; i < 128; i++) | |
| 709 | − { | |
| 710 | − poly->notes[i][0] = -1; | |
| 711 | − poly->notes[i][1] = 0; | |
| 712 | − } | |
| 713 | − poly->stealing_on = 1; | |
| 714 | − poly->recover_stolen = 1; | |
| 715 | − poly->voices = (int**) mpool_alloc(sizeof(int*) * poly->maxNumVoices, m); | |
| 716 | − | |
| 717 | − for (int i = 0; i < poly->maxNumVoices; ++i) | |
| 718 | − { | |
| 719 | − poly->voices[i] = (int*) mpool_alloc(sizeof(int) * 3, m); | |
| 720 | − poly->voices[i][0] = -1; | |
| 721 | − } | |
| 722 | − tStack_initToPool(&poly->stack, mp); | |
| 723 | − | |
| 724 | −} | |
| 725 | − | |
| 726 | −void tSimplePoly_freeFromPool (tSimplePoly* const polyh, tMempool* const mp) | |
| 727 | −{ | |
| 728 | − _tMempool* m = *mp; | |
| 729 | − _tSimplePoly* poly = *polyh; | |
| 730 | − | |
| 731 | − for (int i = 0; i < poly->maxNumVoices; i++) | |
| 732 | − { | |
| 733 | − mpool_free((char*)poly->voices[i], m); | |
| 734 | − } | |
| 735 | − tStack_freeFromPool(&poly->stack, mp); | |
| 736 | − mpool_free((char*)poly->voices, m); | |
| 737 | − mpool_free((char*)poly, m); | |
| 738 | −} | |
| 739 | − | |
| 740 | −int tSimplePoly_noteOn(tSimplePoly* const polyh, int note, uint8_t vel) | |
| 741 | −{ | |
| 742 | − _tSimplePoly* poly = *polyh; | |
| 743 | − int whichVoice, whichNote, oldNote, alteredVoice; | |
| 744 | − // if not in keymap or already on stack, dont do anything. else, add that note. | |
| 745 | − if (tStack_contains(&poly->stack, note) >= 0) return -1; | |
| 746 | − else | |
| 747 | − { | |
| 748 | − alteredVoice = -1; | |
| 749 | − oBool found = OFALSE; | |
| 750 | − for (int i = 0; i < poly->numVoices; i++) | |
| 751 | − { | |
| 752 | − if (poly->voices[i][0] == -1) // if inactive voice, give this note to voice | |
| 753 | − { | |
| 754 | − | |
| 755 | − found = OTRUE; | |
| 756 | − | |
| 757 | − poly->voices[i][0] = note; | |
| 758 | − poly->voices[i][1] = vel; | |
| 759 | − poly->notes[note][0] = i; | |
| 760 | − poly->notes[note][1] = vel; | |
| 761 | − poly->voices[i][2] = note; // voices[i][2] is the output midi note, (avoiding the -1 when a voice is inactive) | |
| 762 | − | |
| 763 | − alteredVoice = i; | |
| 764 | − tStack_add(&poly->stack, note); | |
| 765 | − break; | |
| 766 | − } | |
| 767 | − } | |
| 768 | − if (!found) | |
| 769 | − { | |
| 770 | − //second preference is grabbing one that is in release phase but not finished sounding yet | |
| 771 | − for (int i = 0 ; i < poly->numVoices; i++) | |
| 772 | − { | |
| 773 | − if (poly->voices[i][0] == -2) // if voice is released but still sounding, take over this voice | |
| 774 | − { | |
| 775 | − | |
| 776 | − found = OTRUE; | |
| 777 | − | |
| 778 | − poly->voices[i][0] = note; | |
| 779 | − poly->voices[i][1] = vel; | |
| 780 | − poly->notes[note][0] = i; | |
| 781 | − poly->notes[note][1] = vel; | |
| 782 | − poly->voices[i][2] = note; // voices[i][2] is the output midi note, (avoiding the -1 when a voice is inactive) | |
| 783 | − | |
| 784 | − alteredVoice = i; | |
| 785 | − tStack_add(&poly->stack, note); | |
| 786 | − break; | |
| 787 | − } | |
| 788 | − } | |
| 789 | − } | |
| 790 | − if ((!found) && (poly->stealing_on)) //steal | |
| 791 | − { | |
| 792 | − for (int j = tStack_getSize(&poly->stack) - 1; j >= 0; j--) | |
| 793 | − { | |
| 794 | − whichNote = tStack_get(&poly->stack, j); | |
| 795 | − whichVoice = poly->notes[whichNote][0]; | |
| 796 | − if (whichVoice >= 0) | |
| 797 | − { | |
| 798 | − oldNote = poly->voices[whichVoice][0]; | |
| 799 | − poly->voices[whichVoice][0] = note; | |
| 800 | − poly->voices[whichVoice][1] = vel; | |
| 801 | − poly->notes[oldNote][0] = -3; //mark the stolen voice as stolen (in the second dimension of the notes array) | |
| 802 | − poly->notes[note][0] = whichVoice; | |
| 803 | − poly->notes[note][1] = vel; | |
| 804 | − | |
| 805 | − poly->voices[whichVoice][2] = note; | |
| 806 | − | |
| 807 | − alteredVoice = whichVoice; | |
| 808 | − tStack_add(&poly->stack, note); | |
| 809 | − break; | |
| 810 | − } | |
| 811 | − } | |
| 812 | − } | |
| 813 | − return alteredVoice; | |
| 814 | − } | |
| 815 | −} | |
| 816 | − | |
| 817 | − | |
| 818 | − | |
| 819 | −int tSimplePoly_noteOff(tSimplePoly* const polyh, uint8_t note) | |
| 820 | −{ | |
| 821 | − _tSimplePoly* poly = *polyh; | |
| 822 | − int16_t noteToTest = -1; | |
| 823 | − | |
| 824 | − tStack_remove(&poly->stack, note); | |
| 825 | − poly->notes[note][0] = -1; | |
| 826 | − | |
| 827 | − int deactivatedVoice = -1; | |
| 828 | − for (int i = 0; i < poly->maxNumVoices; i++) | |
| 829 | − { | |
| 830 | − if (poly->voices[i][0] == note) | |
| 831 | − { | |
| 832 | − poly->voices[i][0] = -1; | |
| 833 | − poly->voices[i][1] = 0; | |
| 834 | − deactivatedVoice = i; | |
| 835 | − break; | |
| 836 | − } | |
| 837 | − } | |
| 838 | − | |
| 839 | − if (poly->recover_stolen) | |
| 840 | − { | |
| 841 | − //grab old notes off the stack if there are notes waiting to replace the free voice | |
| 842 | − if (deactivatedVoice >= 0) | |
| 843 | − { | |
| 844 | − for (int j = 0; j < tStack_getSize(&poly->stack); ++j) | |
| 845 | − { | |
| 846 | − noteToTest = tStack_get(&poly->stack, j); | |
| 847 | − | |
| 848 | − if (poly->notes[noteToTest][0] == -3) //if there is a stolen note waiting (marked inactive but on the stack) | |
| 849 | − { | |
| 850 | − poly->voices[deactivatedVoice][0] = noteToTest; //set the newly free voice to use the old stolen note | |
| 851 | − poly->voices[deactivatedVoice][1] = poly->notes[noteToTest][1]; // set the velocity of the voice to be the velocity of that note | |
| 852 | − poly->voices[deactivatedVoice][2] = noteToTest; | |
| 853 | − poly->notes[noteToTest][0] = deactivatedVoice; //mark that it is no longer stolen and is now active | |
| 854 | − return -1; | |
| 855 | − } | |
| 856 | − } | |
| 857 | − } | |
| 858 | − } | |
| 859 | − return deactivatedVoice; | |
| 860 | −} | |
| 861 | − | |
| 862 | − | |
| 863 | −void tSimplePoly_deactivateVoice(tSimplePoly* const polyh, uint8_t voice) | |
| 864 | −{ | |
| 865 | − _tSimplePoly* poly = *polyh; | |
| 866 | − | |
| 867 | − if (poly->voices[voice][0] == -2) //only do this if the voice is waiting for deactivation (not already reassigned while waiting) | |
| 868 | − { | |
| 869 | − poly->voices[voice][0] = -1; | |
| 870 | − poly->voices[voice][1] = 0; | |
| 871 | − if (poly->recover_stolen) | |
| 872 | − { | |
| 873 | − //grab old notes off the stack if there are notes waiting to replace the free voice | |
| 874 | − for (int j = 0; j < tStack_getSize(&poly->stack); ++j) | |
| 875 | − { | |
| 876 | − noteToTest = tStack_get(&poly->stack, j); | |
| 877 | − | |
| 878 | − if (poly->notes[noteToTest][0] == -3) //if there is a stolen note waiting (marked inactive but on the stack) | |
| 879 | − { | |
| 880 | − poly->voices[voice][0] = noteToTest; //set the newly free voice to use the old stolen note | |
| 881 | − poly->voices[voice][1] = poly->notes[noteToTest][1]; // set the velocity of the voice to be the velocity of that note | |
| 882 | − poly->voices[voice][2] = noteToTest; | |
| 883 | − poly->notes[noteToTest][0] = voice; //mark that it is no longer stolen and is now active | |
| 884 | − } | |
| 885 | − } | |
| 886 | − } | |
| 887 | − } | |
| 888 | −} | |
| 889 | − | |
| 890 | −int tSimplePoly_findVoiceAssignedToNote(tSimplePoly* const polyh, uint8_t note) | |
| 891 | −{ | |
| 892 | − _tSimplePoly* poly = *polyh; | |
| 893 | − | |
| 894 | − | |
| 895 | − int voiceWithThatNote = -1; | |
| 896 | − for (int i = 0; i < poly->maxNumVoices; i++) | |
| 897 | − { | |
| 898 | − if (poly->voices[i][0] == note) | |
| 899 | − { | |
| 900 | − voiceWithThatNote = i; | |
| 901 | − break; | |
| 902 | − } | |
| 903 | − } | |
| 904 | − return voiceWithThatNote; | |
| 905 | −} | |
| 906 | − | |
| 907 | − | |
| 908 | −int tSimplePoly_markPendingNoteOff(tSimplePoly* const polyh, uint8_t note) | |
| 909 | −{ | |
| 910 | − _tSimplePoly* poly = *polyh; | |
| 911 | − int deactivatedVoice = -1; | |
| 912 | − | |
| 913 | − if (tStack_remove(&poly->stack, note)) | |
| 914 | − | |
| 915 | − { | |
| 916 | − | |
| 917 | − poly->notes[note][0] = -2; | |
| 918 | − | |
| 919 | − | |
| 920 | − | |
| 921 | − for (int i = 0; i < poly->maxNumVoices; i++) | |
| 922 | − { | |
| 923 | − if (poly->voices[i][0] == note) | |
| 924 | − { | |
| 925 | − poly->voices[i][0] = -2; | |
| 926 | − poly->voices[i][1] = 0; | |
| 927 | − deactivatedVoice = i; | |
| 928 | − break; | |
| 929 | − } | |
| 930 | − } | |
| 931 | − | |
| 932 | − | |
| 933 | − } | |
| 934 | − return deactivatedVoice; | |
| 935 | −} | |
| 936 | − | |
| 937 | −void tSimplePoly_setNumVoices(tSimplePoly* const polyh, uint8_t numVoices) | |
| 938 | −{ | |
| 939 | − _tSimplePoly* poly = *polyh; | |
| 940 | − poly->numVoices = (numVoices > poly->maxNumVoices) ? poly->maxNumVoices : numVoices; | |
| 941 | −} | |
| 942 | − | |
| 943 | − | |
| 944 | −int tSimplePoly_getNumVoices(tSimplePoly* const polyh) | |
| 945 | −{ | |
| 946 | − _tSimplePoly* poly = *polyh; | |
| 947 | − return poly->numVoices; | |
| 948 | −} | |
| 949 | − | |
| 950 | −int tSimplePoly_getNumActiveVoices(tSimplePoly* const polyh) | |
| 951 | −{ | |
| 952 | − _tSimplePoly* poly = *polyh; | |
| 953 | − return LEAF_clip(0, tStack_getSize(&poly->stack), poly->numVoices); | |
| 954 | −} | |
| 955 | − | |
| 956 | − | |
| 957 | −int tSimplePoly_getPitch(tSimplePoly* const polyh, uint8_t voice) | |
| 958 | −{ | |
| 959 | − _tSimplePoly* poly = *polyh; | |
| 960 | − return poly->voices[voice][2]; | |
| 961 | −} | |
| 962 | − | |
| 963 | −//this one returns negative one if the voice is inactive | |
| 964 | −int tSimplePoly_getPitchAndCheckActive(tSimplePoly* const polyh, uint8_t voice) | |
| 965 | −{ | |
| 966 | − _tSimplePoly* poly = *polyh; | |
| 967 | − return poly->voices[voice][0]; | |
| 968 | −} | |
| 969 | − | |
| 970 | −int tSimplePoly_getVelocity(tSimplePoly* const polyh, uint8_t voice) | |
| 971 | −{ | |
| 972 | − _tSimplePoly* poly = *polyh; | |
| 973 | − return poly->voices[voice][1]; | |
| 974 | −} | |
| 975 | − | |
| 976 | −int tSimplePoly_isOn(tSimplePoly* const polyh, uint8_t voice) | |
| 977 | −{ | |
| 978 | − _tSimplePoly* poly = *polyh; | |
| 979 | − return (poly->voices[voice][0] > 0) ? 1 : 0; | |
| 980 | −} | |
| @@ -1,1660 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − leaf-oscillators.c | |
| 3 | − Created: 20 Jan 2017 12:00:58pm | |
| 4 | − Author: Michael R Mulshine | |
| 5 | − ==============================================================================*/ | |
| 6 | − | |
| 7 | −#if _WIN32 || _WIN64 | |
| 8 | − | |
| 9 | −#include "..\Inc\leaf-oscillators.h" | |
| 10 | −#include "..\leaf.h" | |
| 11 | − | |
| 12 | −#else | |
| 13 | − | |
| 14 | −#include "../Inc/leaf-oscillators.h" | |
| 15 | −#include "../leaf.h" | |
| 16 | − | |
| 17 | −#endif | |
| 18 | − | |
| 19 | −// Cycle | |
| 20 | −void tCycle_init(tCycle* const cy) | |
| 21 | −{ | |
| 22 | − tCycle_initToPool(cy, &leaf.mempool); | |
| 23 | −} | |
| 24 | − | |
| 25 | −void tCycle_free(tCycle* const cy) | |
| 26 | −{ | |
| 27 | − tCycle_freeFromPool(cy, &leaf.mempool); | |
| 28 | −} | |
| 29 | − | |
| 30 | −void tCycle_initToPool (tCycle* const cy, tMempool* const mp) | |
| 31 | −{ | |
| 32 | − _tMempool* m = *mp; | |
| 33 | − _tCycle* c = *cy = (_tCycle*) mpool_alloc(sizeof(_tCycle), m); | |
| 34 | − | |
| 35 | − c->inc = 0.0f; | |
| 36 | − c->phase = 0.0f; | |
| 37 | − | |
| 38 | −} | |
| 39 | − | |
| 40 | −void tCycle_freeFromPool (tCycle* const cy, tMempool* const mp) | |
| 41 | −{ | |
| 42 | − _tMempool* m = *mp; | |
| 43 | − _tCycle* c = *cy; | |
| 44 | − | |
| 45 | − mpool_free((char*)c, m); | |
| 46 | −} | |
| 47 | − | |
| 48 | −void tCycle_setFreq(tCycle* const cy, float freq) | |
| 49 | −{ | |
| 50 | − _tCycle* c = *cy; | |
| 51 | − | |
| 52 | − c->freq = freq; | |
| 53 | − | |
| 54 | − c->inc = freq * leaf.invSampleRate; | |
| 55 | −} | |
| 56 | − | |
| 57 | −//need to check bounds and wrap table properly to allow through-zero FM | |
| 58 | −float tCycle_tick(tCycle* const cy) | |
| 59 | −{ | |
| 60 | − _tCycle* c = *cy; | |
| 61 | − float temp;; | |
| 62 | − int intPart;; | |
| 63 | − float fracPart; | |
| 64 | − float samp0; | |
| 65 | − float samp1; | |
| 66 | − | |
| 67 | − // Phasor increment | |
| 68 | − c->phase += c->inc; | |
| 69 | − while (c->phase >= 1.0f) c->phase -= 1.0f; | |
| 70 | − while (c->phase < 0.0f) c->phase += 1.0f; | |
| 71 | − | |
| 72 | − // Wavetable synthesis | |
| 73 | − | |
| 74 | − temp = SINE_TABLE_SIZE * c->phase; | |
| 75 | − intPart = (int)temp; | |
| 76 | − fracPart = temp - (float)intPart; | |
| 77 | − samp0 = __leaf_table_sinewave[intPart]; | |
| 78 | − if (++intPart >= SINE_TABLE_SIZE) intPart = 0; | |
| 79 | − samp1 = __leaf_table_sinewave[intPart]; | |
| 80 | − | |
| 81 | − return (samp0 + (samp1 - samp0) * fracPart); | |
| 82 | − | |
| 83 | −} | |
| 84 | − | |
| 85 | −void tCycleSampleRateChanged (tCycle* const cy) | |
| 86 | −{ | |
| 87 | − _tCycle* c = *cy; | |
| 88 | − | |
| 89 | − c->inc = c->freq * leaf.invSampleRate; | |
| 90 | −} | |
| 91 | − | |
| 92 | −//======================================================================== | |
| 93 | −/* Triangle */ | |
| 94 | −void tTriangle_init(tTriangle* const cy) | |
| 95 | −{ | |
| 96 | − tTriangle_initToPool(cy, &leaf.mempool); | |
| 97 | −} | |
| 98 | − | |
| 99 | −void tTriangle_free(tTriangle* const cy) | |
| 100 | −{ | |
| 101 | − tTriangle_freeFromPool(cy, &leaf.mempool); | |
| 102 | −} | |
| 103 | − | |
| 104 | −void tTriangle_initToPool (tTriangle* const cy, tMempool* const mp) | |
| 105 | −{ | |
| 106 | − _tMempool* m = *mp; | |
| 107 | − _tTriangle* c = *cy = (_tTriangle*) mpool_alloc(sizeof(_tTriangle), m); | |
| 108 | − | |
| 109 | − c->inc = 0.0f; | |
| 110 | − c->phase = 0.0f; | |
| 111 | − tTriangle_setFreq(cy, 220); | |
| 112 | −} | |
| 113 | − | |
| 114 | −void tTriangle_freeFromPool (tTriangle* const cy, tMempool* const mp) | |
| 115 | −{ | |
| 116 | − _tMempool* m = *mp; | |
| 117 | − _tTriangle* c = *cy; | |
| 118 | − | |
| 119 | − mpool_free((char*)c, m); | |
| 120 | −} | |
| 121 | − | |
| 122 | −void tTriangle_setFreq(tTriangle* const cy, float freq) | |
| 123 | −{ | |
| 124 | − _tTriangle* c = *cy; | |
| 125 | − | |
| 126 | − c->freq = freq; | |
| 127 | − | |
| 128 | − c->inc = c->freq * leaf.invSampleRate; | |
| 129 | − | |
| 130 | − c->w = c->freq * INV_20; | |
| 131 | − for (c->oct = 0; c->w > 2.0f; c->oct++) | |
| 132 | − { | |
| 133 | − c->w = 0.5f * c->w; | |
| 134 | − } | |
| 135 | − c->w = 2.0f - c->w; | |
| 136 | −} | |
| 137 | − | |
| 138 | − | |
| 139 | −float tTriangle_tick(tTriangle* const cy) | |
| 140 | −{ | |
| 141 | − _tTriangle* c = *cy; | |
| 142 | − | |
| 143 | − // Phasor increment | |
| 144 | − c->phase += c->inc; | |
| 145 | − while (c->phase >= 1.0f) c->phase -= 1.0f; | |
| 146 | − while (c->phase < 0.0f) c->phase += 1.0f; | |
| 147 | − | |
| 148 | − float out = 0.0f; | |
| 149 | − | |
| 150 | − int idx = (int)(c->phase * TRI_TABLE_SIZE); | |
| 151 | − | |
| 152 | − // Wavetable synthesis | |
| 153 | − out = __leaf_table_triangle[c->oct+1][idx] + | |
| 154 | − (__leaf_table_triangle[c->oct][idx] - __leaf_table_triangle[c->oct+1][idx]) * c->w; | |
| 155 | − | |
| 156 | − return out; | |
| 157 | −} | |
| 158 | − | |
| 159 | −void tTriangleSampleRateChanged (tTriangle* const cy) | |
| 160 | −{ | |
| 161 | − _tTriangle* c = *cy; | |
| 162 | − | |
| 163 | − c->inc = c->freq * leaf.invSampleRate; | |
| 164 | −} | |
| 165 | − | |
| 166 | −//======================================================================== | |
| 167 | −/* Square */ | |
| 168 | −void tSquare_init(tSquare* const cy) | |
| 169 | −{ | |
| 170 | − tSquare_initToPool(cy, &leaf.mempool); | |
| 171 | −} | |
| 172 | − | |
| 173 | −void tSquare_free(tSquare* const cy) | |
| 174 | −{ | |
| 175 | − tSquare_freeFromPool(cy, &leaf.mempool); | |
| 176 | −} | |
| 177 | − | |
| 178 | −void tSquare_initToPool (tSquare* const cy, tMempool* const mp) | |
| 179 | −{ | |
| 180 | − _tMempool* m = *mp; | |
| 181 | − _tSquare* c = *cy = (_tSquare*) mpool_alloc(sizeof(_tSquare), m); | |
| 182 | − | |
| 183 | − c->inc = 0.0f; | |
| 184 | − c->phase = 0.0f; | |
| 185 | − tSquare_setFreq(cy, 220); | |
| 186 | −} | |
| 187 | − | |
| 188 | −void tSquare_freeFromPool(tSquare* const cy, tMempool* const mp) | |
| 189 | −{ | |
| 190 | − _tMempool* m = *mp; | |
| 191 | − _tSquare* c = *cy; | |
| 192 | − | |
| 193 | − mpool_free((char*)c, m); | |
| 194 | −} | |
| 195 | − | |
| 196 | −void tSquare_setFreq(tSquare* const cy, float freq) | |
| 197 | −{ | |
| 198 | − _tSquare* c = *cy; | |
| 199 | − | |
| 200 | − c->freq = freq; | |
| 201 | − | |
| 202 | − c->inc = c->freq * leaf.invSampleRate; | |
| 203 | − | |
| 204 | − c->w = c->freq * INV_20; | |
| 205 | − for (c->oct = 0; c->w > 2.0f; c->oct++) | |
| 206 | − { | |
| 207 | − c->w = 0.5f * c->w; | |
| 208 | − } | |
| 209 | − c->w = 2.0f - c->w; | |
| 210 | −} | |
| 211 | − | |
| 212 | −float tSquare_tick(tSquare* const cy) | |
| 213 | −{ | |
| 214 | − _tSquare* c = *cy; | |
| 215 | − | |
| 216 | − // Phasor increment | |
| 217 | − c->phase += c->inc; | |
| 218 | − while (c->phase >= 1.0f) c->phase -= 1.0f; | |
| 219 | − while (c->phase < 0.0f) c->phase += 1.0f; | |
| 220 | − | |
| 221 | − float out = 0.0f; | |
| 222 | − | |
| 223 | − int idx = (int)(c->phase * SQR_TABLE_SIZE); | |
| 224 | − | |
| 225 | − // Wavetable synthesis | |
| 226 | − out = __leaf_table_squarewave[c->oct+1][idx] + | |
| 227 | − (__leaf_table_squarewave[c->oct][idx] - __leaf_table_squarewave[c->oct+1][idx]) * c->w; | |
| 228 | − | |
| 229 | − return out; | |
| 230 | −} | |
| 231 | − | |
| 232 | −void tSquareSampleRateChanged (tSquare* const cy) | |
| 233 | −{ | |
| 234 | − _tSquare* c = *cy; | |
| 235 | − | |
| 236 | − c->inc = c->freq * leaf.invSampleRate; | |
| 237 | −} | |
| 238 | − | |
| 239 | −//===================================================================== | |
| 240 | −// Sawtooth | |
| 241 | −void tSawtooth_init(tSawtooth* const cy) | |
| 242 | −{ | |
| 243 | − tSawtooth_initToPool(cy, &leaf.mempool); | |
| 244 | −} | |
| 245 | − | |
| 246 | −void tSawtooth_free(tSawtooth* const cy) | |
| 247 | −{ | |
| 248 | − tSawtooth_freeFromPool(cy, &leaf.mempool); | |
| 249 | −} | |
| 250 | − | |
| 251 | −void tSawtooth_initToPool (tSawtooth* const cy, tMempool* const mp) | |
| 252 | −{ | |
| 253 | − _tMempool* m = *mp; | |
| 254 | − _tSawtooth* c = *cy = (_tSawtooth*) mpool_alloc(sizeof(_tSawtooth), m); | |
| 255 | − | |
| 256 | − c->inc = 0.0f; | |
| 257 | − c->phase = 0.0f; | |
| 258 | − tSawtooth_setFreq(cy, 220); | |
| 259 | −} | |
| 260 | − | |
| 261 | −void tSawtooth_freeFromPool (tSawtooth* const cy, tMempool* const mp) | |
| 262 | −{ | |
| 263 | − _tMempool* m = *mp; | |
| 264 | − _tSawtooth* c = *cy; | |
| 265 | − | |
| 266 | − mpool_free((char*)c, m); | |
| 267 | −} | |
| 268 | − | |
| 269 | −void tSawtooth_setFreq(tSawtooth* const cy, float freq) | |
| 270 | −{ | |
| 271 | − _tSawtooth* c = *cy; | |
| 272 | − | |
| 273 | − c->freq = freq; | |
| 274 | − | |
| 275 | − c->inc = c->freq * leaf.invSampleRate; | |
| 276 | − | |
| 277 | − c->w = c->freq * INV_20; | |
| 278 | − for (c->oct = 0; c->w > 2.0f; c->oct++) | |
| 279 | − { | |
| 280 | − c->w = 0.5f * c->w; | |
| 281 | − } | |
| 282 | − c->w = 2.0f - c->w; | |
| 283 | −} | |
| 284 | − | |
| 285 | −float tSawtooth_tick(tSawtooth* const cy) | |
| 286 | −{ | |
| 287 | − _tSawtooth* c = *cy; | |
| 288 | − | |
| 289 | − // Phasor increment | |
| 290 | − c->phase += c->inc; | |
| 291 | − while (c->phase >= 1.0f) c->phase -= 1.0f; | |
| 292 | − while (c->phase < 0.0f) c->phase += 1.0f; | |
| 293 | − | |
| 294 | − float out = 0.0f; | |
| 295 | − | |
| 296 | − int idx = (int)(c->phase * SAW_TABLE_SIZE); | |
| 297 | − | |
| 298 | − // Wavetable synthesis | |
| 299 | − out = __leaf_table_sawtooth[c->oct+1][idx] + | |
| 300 | − (__leaf_table_sawtooth[c->oct][idx] - __leaf_table_sawtooth[c->oct+1][idx]) * c->w; | |
| 301 | − | |
| 302 | − return out; | |
| 303 | −} | |
| 304 | − | |
| 305 | −void tSawtoothSampleRateChanged (tSawtooth* const cy) | |
| 306 | −{ | |
| 307 | − _tSawtooth* c = *cy; | |
| 308 | − | |
| 309 | − c->inc = c->freq * leaf.invSampleRate; | |
| 310 | −} | |
| 311 | − | |
| 312 | −//======================================================================== | |
| 313 | −// Sine | |
| 314 | −void tSine_init(tSine* const cy, int size) | |
| 315 | −{ | |
| 316 | − tSine_initToPool(cy, size, &leaf.mempool); | |
| 317 | −} | |
| 318 | − | |
| 319 | −void tSine_free(tSine* const cy) | |
| 320 | −{ | |
| 321 | − tSine_freeFromPool(cy, &leaf.mempool); | |
| 322 | −} | |
| 323 | − | |
| 324 | −void tSine_initToPool (tSine* const cy, int size, tMempool* const mp) | |
| 325 | −{ | |
| 326 | − _tMempool* m = *mp; | |
| 327 | − _tSine* c = *cy = (_tSine*) mpool_alloc(sizeof(_tSine), m); | |
| 328 | − | |
| 329 | − c->size = size; | |
| 330 | − c->sine = (float*) mpool_alloc(sizeof(float) * c->size, m); | |
| 331 | − LEAF_generate_sine(c->sine, size); | |
| 332 | − c->inc = 0.0f; | |
| 333 | − c->phase = 0.0f; | |
| 334 | −} | |
| 335 | − | |
| 336 | −void tSine_freeFromPool (tSine* const cy, tMempool* const mp) | |
| 337 | −{ | |
| 338 | − _tMempool* m = *mp; | |
| 339 | − _tSine* c = *cy; | |
| 340 | − | |
| 341 | − mpool_free((char*)c->sine, m); | |
| 342 | − mpool_free((char*)c, m); | |
| 343 | −} | |
| 344 | − | |
| 345 | −void tSine_setFreq(tSine* const cy, float freq) | |
| 346 | −{ | |
| 347 | − _tSine* c = *cy; | |
| 348 | − | |
| 349 | − c->freq = freq; | |
| 350 | − c->inc = freq * leaf.invSampleRate; | |
| 351 | −} | |
| 352 | − | |
| 353 | −float tSine_tick(tSine* const cy) | |
| 354 | −{ | |
| 355 | − _tSine* c = *cy; | |
| 356 | − float temp; | |
| 357 | − int intPart; | |
| 358 | − float fracPart; | |
| 359 | − float samp0; | |
| 360 | − float samp1; | |
| 361 | − | |
| 362 | − // Phasor increment | |
| 363 | − c->phase += c->inc; | |
| 364 | − while (c->phase >= 1.0f) c->phase -= 1.0f; | |
| 365 | − while (c->phase < 0.0f) c->phase += 1.0f; | |
| 366 | − | |
| 367 | − // Wavetable synthesis | |
| 368 | − | |
| 369 | − temp = c->size * c->phase; | |
| 370 | − intPart = (int)temp; | |
| 371 | − fracPart = temp - (float)intPart; | |
| 372 | − samp0 = c->sine[intPart]; | |
| 373 | − if (++intPart >= c->size) intPart = 0; | |
| 374 | − samp1 = c->sine[intPart]; | |
| 375 | − | |
| 376 | − return (samp0 + (samp1 - samp0) * fracPart); | |
| 377 | − | |
| 378 | −} | |
| 379 | − | |
| 380 | −void tSineSampleRateChanged (tSine* const cy) | |
| 381 | −{ | |
| 382 | − _tSine* c = *cy; | |
| 383 | − | |
| 384 | − c->inc = c->freq * leaf.invSampleRate; | |
| 385 | −} | |
| 386 | − | |
| 387 | −//============================================================================== | |
| 388 | − | |
| 389 | −/* tTri: Anti-aliased Triangle waveform. */ | |
| 390 | −void tTri_init (tTri* const osc) | |
| 391 | −{ | |
| 392 | − tTri_initToPool(osc, &leaf.mempool); | |
| 393 | −} | |
| 394 | − | |
| 395 | −void tTri_free (tTri* const osc) | |
| 396 | −{ | |
| 397 | − tTri_freeFromPool(osc, &leaf.mempool); | |
| 398 | −} | |
| 399 | − | |
| 400 | −void tTri_initToPool (tTri* const osc, tMempool* const mp) | |
| 401 | −{ | |
| 402 | − _tMempool* m = *mp; | |
| 403 | − _tTri* c = *osc = (_tTri*) mpool_alloc(sizeof(_tTri), m); | |
| 404 | − | |
| 405 | − c->inc = 0.0f; | |
| 406 | − c->phase = 0.0f; | |
| 407 | − c->skew = 0.5f; | |
| 408 | − c->lastOut = 0.0f; | |
| 409 | −} | |
| 410 | − | |
| 411 | −void tTri_freeFromPool (tTri* const cy, tMempool* const mp) | |
| 412 | −{ | |
| 413 | − _tMempool* m = *mp; | |
| 414 | − _tTri* c = *cy; | |
| 415 | − | |
| 416 | − mpool_free((char*)c, m); | |
| 417 | −} | |
| 418 | − | |
| 419 | −float tTri_tick (tTri* const osc) | |
| 420 | −{ | |
| 421 | − _tTri* c = *osc; | |
| 422 | − | |
| 423 | − float out; | |
| 424 | − float skew; | |
| 425 | − | |
| 426 | − if (c->phase < c->skew) | |
| 427 | − { | |
| 428 | − out = 1.0f; | |
| 429 | − skew = (1.0f - c->skew) * 2.0f; | |
| 430 | − } | |
| 431 | − else | |
| 432 | − { | |
| 433 | − out = -1.0f; | |
| 434 | − skew = c->skew * 2.0f; | |
| 435 | − } | |
| 436 | − | |
| 437 | − out += LEAF_poly_blep(c->phase, c->inc); | |
| 438 | − out -= LEAF_poly_blep(fmod(c->phase + (1.0f - c->skew), 1.0f), c->inc); | |
| 439 | − | |
| 440 | − out = (skew * c->inc * out) + ((1 - c->inc) * c->lastOut); | |
| 441 | − c->lastOut = out; | |
| 442 | − | |
| 443 | − c->phase += c->inc; | |
| 444 | − if (c->phase >= 1.0f) | |
| 445 | − { | |
| 446 | − c->phase -= 1.0f; | |
| 447 | − } | |
| 448 | − | |
| 449 | − return out; | |
| 450 | −} | |
| 451 | − | |
| 452 | −void tTri_setFreq (tTri* const osc, float freq) | |
| 453 | −{ | |
| 454 | − _tTri* c = *osc; | |
| 455 | − | |
| 456 | − c->freq = freq; | |
| 457 | − c->inc = freq * leaf.invSampleRate; | |
| 458 | −} | |
| 459 | − | |
| 460 | −void tTri_setSkew (tTri* const osc, float skew) | |
| 461 | −{ | |
| 462 | − _tTri* c = *osc; | |
| 463 | − c->skew = (skew + 1.0f) * 0.5f; | |
| 464 | −} | |
| 465 | − | |
| 466 | − | |
| 467 | −//============================================================================== | |
| 468 | − | |
| 469 | −/* tPulse: Anti-aliased pulse waveform. */ | |
| 470 | −void tPulse_init (tPulse* const osc) | |
| 471 | −{ | |
| 472 | − tPulse_initToPool(osc, &leaf.mempool); | |
| 473 | −} | |
| 474 | − | |
| 475 | −void tPulse_free (tPulse* const osc) | |
| 476 | −{ | |
| 477 | − tPulse_freeFromPool(osc, &leaf.mempool); | |
| 478 | −} | |
| 479 | − | |
| 480 | −void tPulse_initToPool (tPulse* const osc, tMempool* const mp) | |
| 481 | −{ | |
| 482 | − _tMempool* m = *mp; | |
| 483 | − _tPulse* c = *osc = (_tPulse*) mpool_alloc(sizeof(_tPulse), m); | |
| 484 | − | |
| 485 | − c->inc = 0.0f; | |
| 486 | − c->phase = 0.0f; | |
| 487 | − c->width = 0.5f; | |
| 488 | −} | |
| 489 | − | |
| 490 | −void tPulse_freeFromPool(tPulse* const osc, tMempool* const mp) | |
| 491 | −{ | |
| 492 | − _tMempool* m = *mp; | |
| 493 | − _tPulse* c = *osc; | |
| 494 | − | |
| 495 | − mpool_free((char*)c, m); | |
| 496 | −} | |
| 497 | − | |
| 498 | −float tPulse_tick (tPulse* const osc) | |
| 499 | −{ | |
| 500 | − _tPulse* c = *osc; | |
| 501 | − | |
| 502 | − float out; | |
| 503 | − if (c->phase < c->width) out = 1.0f; | |
| 504 | − else out = -1.0f; | |
| 505 | − out += LEAF_poly_blep(c->phase, c->inc); | |
| 506 | − out -= LEAF_poly_blep(fmod(c->phase + (1.0f - c->width), 1.0f), c->inc); | |
| 507 | − | |
| 508 | − c->phase += c->inc; | |
| 509 | − if (c->phase >= 1.0f) | |
| 510 | − { | |
| 511 | − c->phase -= 1.0f; | |
| 512 | − } | |
| 513 | − | |
| 514 | − return out; | |
| 515 | −} | |
| 516 | − | |
| 517 | −void tPulse_setFreq (tPulse* const osc, float freq) | |
| 518 | −{ | |
| 519 | − _tPulse* c = *osc; | |
| 520 | − | |
| 521 | − c->freq = freq; | |
| 522 | − c->inc = freq * leaf.invSampleRate; | |
| 523 | −} | |
| 524 | − | |
| 525 | −void tPulse_setWidth (tPulse* const osc, float width) | |
| 526 | −{ | |
| 527 | − _tPulse* c = *osc; | |
| 528 | − c->width = width; | |
| 529 | −} | |
| 530 | − | |
| 531 | − | |
| 532 | −//============================================================================== | |
| 533 | − | |
| 534 | −/* tSawtooth: Anti-aliased Sawtooth waveform. */ | |
| 535 | −void tSaw_init (tSaw* const osc) | |
| 536 | −{ | |
| 537 | − tSaw_initToPool(osc, &leaf.mempool); | |
| 538 | −} | |
| 539 | − | |
| 540 | −void tSaw_free (tSaw* const osc) | |
| 541 | −{ | |
| 542 | − tSaw_freeFromPool(osc, &leaf.mempool); | |
| 543 | −} | |
| 544 | − | |
| 545 | −void tSaw_initToPool (tSaw* const osc, tMempool* const mp) | |
| 546 | −{ | |
| 547 | − _tMempool* m = *mp; | |
| 548 | − _tSaw* c = *osc = (_tSaw*) mpool_alloc(sizeof(_tSaw), m); | |
| 549 | − | |
| 550 | − c->inc = 0.0f; | |
| 551 | − c->phase = 0.0f; | |
| 552 | −} | |
| 553 | − | |
| 554 | −void tSaw_freeFromPool (tSaw* const osc, tMempool* const mp) | |
| 555 | −{ | |
| 556 | − _tMempool* m = *mp; | |
| 557 | − _tSaw* c = *osc; | |
| 558 | − | |
| 559 | − mpool_free((char*)c, m); | |
| 560 | −} | |
| 561 | − | |
| 562 | −float tSaw_tick (tSaw* const osc) | |
| 563 | −{ | |
| 564 | − _tSaw* c = *osc; | |
| 565 | − | |
| 566 | − float out = (c->phase * 2.0f) - 1.0f; | |
| 567 | − out -= LEAF_poly_blep(c->phase, c->inc); | |
| 568 | − | |
| 569 | − c->phase += c->inc; | |
| 570 | − if (c->phase >= 1.0f) | |
| 571 | − { | |
| 572 | − c->phase -= 1.0f; | |
| 573 | − } | |
| 574 | − | |
| 575 | − return out; | |
| 576 | −} | |
| 577 | − | |
| 578 | −void tSaw_setFreq (tSaw* const osc, float freq) | |
| 579 | −{ | |
| 580 | − _tSaw* c = *osc; | |
| 581 | − | |
| 582 | − c->freq = freq; | |
| 583 | − | |
| 584 | − c->inc = freq * leaf.invSampleRate; | |
| 585 | −} | |
| 586 | − | |
| 587 | −//======================================================================== | |
| 588 | −/* Phasor */ | |
| 589 | −void tPhasorSampleRateChanged (tPhasor* const ph) | |
| 590 | −{ | |
| 591 | − _tPhasor* p = *ph; | |
| 592 | − | |
| 593 | − p->inc = p->freq * leaf.invSampleRate; | |
| 594 | −}; | |
| 595 | − | |
| 596 | −void tPhasor_init(tPhasor* const ph) | |
| 597 | −{ | |
| 598 | − tPhasor_initToPool(ph, &leaf.mempool); | |
| 599 | −} | |
| 600 | − | |
| 601 | −void tPhasor_free(tPhasor* const ph) | |
| 602 | −{ | |
| 603 | − tPhasor_freeFromPool(ph, &leaf.mempool); | |
| 604 | −} | |
| 605 | − | |
| 606 | −void tPhasor_initToPool (tPhasor* const ph, tMempool* const mp) | |
| 607 | −{ | |
| 608 | − _tMempool* m = *mp; | |
| 609 | − _tPhasor* p = *ph = (_tPhasor*) mpool_alloc(sizeof(_tPhasor), m); | |
| 610 | − | |
| 611 | − p->phase = 0.0f; | |
| 612 | − p->inc = 0.0f; | |
| 613 | − p->phaseDidReset = 0; | |
| 614 | −} | |
| 615 | − | |
| 616 | −void tPhasor_freeFromPool(tPhasor* const ph, tMempool* const mp) | |
| 617 | −{ | |
| 618 | − _tMempool* m = *mp; | |
| 619 | − _tPhasor* p = *ph; | |
| 620 | − | |
| 621 | − mpool_free((char*)p, m); | |
| 622 | −} | |
| 623 | − | |
| 624 | −void tPhasor_setFreq(tPhasor* const ph, float freq) | |
| 625 | −{ | |
| 626 | − _tPhasor* p = *ph; | |
| 627 | − | |
| 628 | − p->freq = freq; | |
| 629 | − | |
| 630 | − p->inc = freq * leaf.invSampleRate; | |
| 631 | −} | |
| 632 | − | |
| 633 | −float tPhasor_tick(tPhasor* const ph) | |
| 634 | −{ | |
| 635 | − _tPhasor* p = *ph; | |
| 636 | − | |
| 637 | − p->phase += p->inc; | |
| 638 | − | |
| 639 | − | |
| 640 | − p->phaseDidReset = 0; | |
| 641 | − if (p->phase >= 1.0f) | |
| 642 | − { | |
| 643 | − p->phaseDidReset = 1; | |
| 644 | − p->phase -= 1.0f; | |
| 645 | − } | |
| 646 | − | |
| 647 | − return p->phase; | |
| 648 | −} | |
| 649 | − | |
| 650 | −/* Noise */ | |
| 651 | −void tNoise_init(tNoise* const ns, NoiseType type) | |
| 652 | −{ | |
| 653 | − tNoise_initToPool(ns, type, &leaf.mempool); | |
| 654 | −} | |
| 655 | − | |
| 656 | −void tNoise_free(tNoise* const ns) | |
| 657 | −{ | |
| 658 | − tNoise_freeFromPool(ns, &leaf.mempool); | |
| 659 | −} | |
| 660 | − | |
| 661 | −void tNoise_initToPool (tNoise* const ns, NoiseType type, tMempool* const mp) | |
| 662 | −{ | |
| 663 | − _tMempool* m = *mp; | |
| 664 | − _tNoise* n = *ns = (_tNoise*) mpool_alloc(sizeof(_tNoise), m); | |
| 665 | − | |
| 666 | − n->type = type; | |
| 667 | − n->rand = leaf.random; | |
| 668 | −} | |
| 669 | − | |
| 670 | −void tNoise_freeFromPool (tNoise* const ns, tMempool* const mp) | |
| 671 | −{ | |
| 672 | − _tMempool* m = *mp; | |
| 673 | − _tNoise* n = *ns; | |
| 674 | − | |
| 675 | − mpool_free((char*)n, m); | |
| 676 | −} | |
| 677 | − | |
| 678 | −float tNoise_tick(tNoise* const ns) | |
| 679 | −{ | |
| 680 | − _tNoise* n = *ns; | |
| 681 | − | |
| 682 | − float rand = (n->rand() * 2.0f) - 1.0f; | |
| 683 | − | |
| 684 | − if (n->type == PinkNoise) | |
| 685 | − { | |
| 686 | − float tmp; | |
| 687 | − n->pinkb0 = 0.99765f * n->pinkb0 + rand * 0.0990460f; | |
| 688 | − n->pinkb1 = 0.96300f * n->pinkb1 + rand * 0.2965164f; | |
| 689 | − n->pinkb2 = 0.57000f * n->pinkb2 + rand * 1.0526913f; | |
| 690 | − tmp = n->pinkb0 + n->pinkb1 + n->pinkb2 + rand * 0.1848f; | |
| 691 | − return (tmp * 0.05f); | |
| 692 | − } | |
| 693 | − else // WhiteNoise | |
| 694 | − { | |
| 695 | − return rand; | |
| 696 | − } | |
| 697 | −} | |
| 698 | − | |
| 699 | −//================================================================================= | |
| 700 | −/* Neuron */ | |
| 701 | − | |
| 702 | −void tNeuronSampleRateChanged(tNeuron* nr) | |
| 703 | −{ | |
| 704 | − | |
| 705 | −} | |
| 706 | − | |
| 707 | −void tNeuron_init(tNeuron* const nr) | |
| 708 | −{ | |
| 709 | − tNeuron_initToPool(nr, &leaf.mempool); | |
| 710 | −} | |
| 711 | − | |
| 712 | −void tNeuron_free(tNeuron* const nr) | |
| 713 | −{ | |
| 714 | − tNeuron_freeFromPool(nr, &leaf.mempool); | |
| 715 | −} | |
| 716 | − | |
| 717 | −void tNeuron_initToPool (tNeuron* const nr, tMempool* const mp) | |
| 718 | −{ | |
| 719 | − _tMempool* m = *mp; | |
| 720 | − _tNeuron* n = *nr = (_tNeuron*) mpool_alloc(sizeof(_tNeuron), m); | |
| 721 | − | |
| 722 | − tPoleZero_initToPool(&n->f, mp); | |
| 723 | − | |
| 724 | − tPoleZero_setBlockZero(&n->f, 0.99f); | |
| 725 | − | |
| 726 | − n->timeStep = 1.0f / 50.0f; | |
| 727 | − | |
| 728 | − n->current = 0.0f; // 100.0f for sound | |
| 729 | − n->voltage = 0.0f; | |
| 730 | − | |
| 731 | − n->mode = NeuronNormal; | |
| 732 | − | |
| 733 | − n->P[0] = 0.0f; | |
| 734 | − n->P[1] = 0.0f; | |
| 735 | − n->P[2] = 1.0f; | |
| 736 | − | |
| 737 | − n->V[0] = -12.0f; | |
| 738 | − n->V[1] = 115.0f; | |
| 739 | − n->V[2] = 10.613f; | |
| 740 | − | |
| 741 | − n->gK = 36.0f; | |
| 742 | − n->gN = 120.0f; | |
| 743 | − n->gL = 0.3f; | |
| 744 | − n->C = 1.0f; | |
| 745 | − | |
| 746 | − n->rate[2] = n->gL/n->C; | |
| 747 | −} | |
| 748 | − | |
| 749 | −void tNeuron_freeFromPool(tNeuron* const nr, tMempool* const mp) | |
| 750 | −{ | |
| 751 | − _tMempool* m = *mp; | |
| 752 | − _tNeuron* n = *nr; | |
| 753 | − | |
| 754 | − tPoleZero_free(&n->f); | |
| 755 | − mpool_free((char*)n, m); | |
| 756 | −} | |
| 757 | − | |
| 758 | −void tNeuron_reset(tNeuron* const nr) | |
| 759 | −{ | |
| 760 | − _tNeuron* n = *nr; | |
| 761 | − | |
| 762 | − tPoleZero_setBlockZero(&n->f, 0.99f); | |
| 763 | − | |
| 764 | − n->timeStep = 1.0f / 50.0f; | |
| 765 | − | |
| 766 | − n->current = 0.0f; // 100.0f for sound | |
| 767 | − n->voltage = 0.0f; | |
| 768 | − | |
| 769 | − n->mode = NeuronNormal; | |
| 770 | − | |
| 771 | − n->P[0] = 0.0f; | |
| 772 | − n->P[1] = 0.0f; | |
| 773 | − n->P[2] = 1.0f; | |
| 774 | − | |
| 775 | − n->V[0] = -12.0f; | |
| 776 | − n->V[1] = 115.0f; | |
| 777 | − n->V[2] = 10.613f; | |
| 778 | − | |
| 779 | − n->gK = 36.0f; | |
| 780 | − n->gN = 120.0f; | |
| 781 | − n->gL = 0.3f; | |
| 782 | − n->C = 1.0f; | |
| 783 | − | |
| 784 | − n->rate[2] = n->gL/n->C; | |
| 785 | −} | |
| 786 | − | |
| 787 | −void tNeuron_setV1(tNeuron* const nr, float V1) | |
| 788 | −{ | |
| 789 | − _tNeuron* n = *nr; | |
| 790 | − n->V[0] = V1; | |
| 791 | −} | |
| 792 | − | |
| 793 | − | |
| 794 | −void tNeuron_setV2(tNeuron* const nr, float V2) | |
| 795 | −{ | |
| 796 | − _tNeuron* n = *nr; | |
| 797 | − n->V[1] = V2; | |
| 798 | −} | |
| 799 | − | |
| 800 | −void tNeuron_setV3(tNeuron* const nr, float V3) | |
| 801 | −{ | |
| 802 | − _tNeuron* n = *nr; | |
| 803 | − n->V[2] = V3; | |
| 804 | −} | |
| 805 | − | |
| 806 | −void tNeuron_setTimeStep(tNeuron* const nr, float timeStep) | |
| 807 | −{ | |
| 808 | − _tNeuron* n = *nr; | |
| 809 | − n->timeStep = timeStep; | |
| 810 | −} | |
| 811 | − | |
| 812 | −void tNeuron_setK(tNeuron* const nr, float K) | |
| 813 | −{ | |
| 814 | − _tNeuron* n = *nr; | |
| 815 | − n->gK = K; | |
| 816 | −} | |
| 817 | − | |
| 818 | −void tNeuron_setL(tNeuron* const nr, float L) | |
| 819 | −{ | |
| 820 | − _tNeuron* n = *nr; | |
| 821 | − n->gL = L; | |
| 822 | − n->rate[2] = n->gL/n->C; | |
| 823 | −} | |
| 824 | − | |
| 825 | −void tNeuron_setN(tNeuron* const nr, float N) | |
| 826 | −{ | |
| 827 | − _tNeuron* n = *nr; | |
| 828 | − n->gN = N; | |
| 829 | −} | |
| 830 | − | |
| 831 | −void tNeuron_setC(tNeuron* const nr, float C) | |
| 832 | −{ | |
| 833 | − _tNeuron* n = *nr; | |
| 834 | − n->C = C; | |
| 835 | − n->rate[2] = n->gL/n->C; | |
| 836 | −} | |
| 837 | − | |
| 838 | −float tNeuron_tick(tNeuron* const nr) | |
| 839 | −{ | |
| 840 | − _tNeuron* n = *nr; | |
| 841 | − | |
| 842 | − float output = 0.0f; | |
| 843 | − float voltage = n->voltage; | |
| 844 | − | |
| 845 | − n->alpha[0] = (0.01f * (10.0f - voltage)) / (expf((10.0f - voltage)/10.0f) - 1.0f); | |
| 846 | − n->alpha[1] = (0.1f * (25.0f-voltage)) / (expf((25.0f-voltage)/10.0f) - 1.0f); | |
| 847 | − n->alpha[2] = (0.07f * expf((-1.0f * voltage)/20.0f)); | |
| 848 | − | |
| 849 | − n->beta[0] = (0.125f * expf((-1.0f* voltage)/80.0f)); | |
| 850 | − n->beta[1] = (4.0f * expf((-1.0f * voltage)/18.0f)); | |
| 851 | − n->beta[2] = (1.0f / (expf((30.0f-voltage)/10.0f) + 1.0f)); | |
| 852 | − | |
| 853 | − for (int i = 0; i < 3; i++) | |
| 854 | − { | |
| 855 | − n->P[i] = (n->alpha[i] * n->timeStep) + ((1.0f - ((n->alpha[i] + n->beta[i]) * n->timeStep)) * n->P[i]); | |
| 856 | − | |
| 857 | − if (n->P[i] > 1.0f) n->P[i] = 0.0f; | |
| 858 | − else if (n->P[i] < -1.0f) n->P[i] = 0.0f; | |
| 859 | − } | |
| 860 | − // rate[0]= k ; rate[1] = Na ; rate[2] = l | |
| 861 | − n->rate[0] = ((n->gK * powf(n->P[0], 4.0f)) / n->C); | |
| 862 | − n->rate[1] = ((n->gN * powf(n->P[1], 3.0f) * n->P[2]) / n->C); | |
| 863 | − | |
| 864 | − //calculate the final membrane voltage based on the computed variables | |
| 865 | − n->voltage = voltage + | |
| 866 | − (n->timeStep * n->current / n->C) - | |
| 867 | − (n->timeStep * ( n->rate[0] * (voltage - n->V[0]) + n->rate[1] * (voltage - n->V[1]) + n->rate[2] * (voltage - n->V[2]))); | |
| 868 | − | |
| 869 | − if (n->mode == NeuronTanh) | |
| 870 | − { | |
| 871 | − n->voltage = 100.0f * tanhf(0.01f * n->voltage); | |
| 872 | − } | |
| 873 | − else if (n->mode == NeuronAaltoShaper) | |
| 874 | − { | |
| 875 | − float shapeVoltage = 0.01f * n->voltage; | |
| 876 | − | |
| 877 | − float w, c, xc, xc2, xc4; | |
| 878 | − | |
| 879 | − float sqrt8 = 2.82842712475f; | |
| 880 | − | |
| 881 | − float wscale = 1.30612244898f; | |
| 882 | − float m_drive = 1.0f; | |
| 883 | − | |
| 884 | − xc = LEAF_clip(-sqrt8, shapeVoltage, sqrt8); | |
| 885 | − | |
| 886 | − xc2 = xc*xc; | |
| 887 | − | |
| 888 | − c = 0.5f * shapeVoltage * (3.0f - (xc2)); | |
| 889 | − | |
| 890 | − xc4 = xc2 * xc2; | |
| 891 | − | |
| 892 | − w = (1.0f - xc2 * 0.25f + xc4 * 0.015625f) * wscale; | |
| 893 | − | |
| 894 | − shapeVoltage = w * (c + 0.05f * xc2) * (m_drive + 0.75f); | |
| 895 | − | |
| 896 | − n->voltage = 100.0f * shapeVoltage; | |
| 897 | − } | |
| 898 | − | |
| 899 | − | |
| 900 | − if (n->voltage > 100.0f) n->voltage = 100.0f; | |
| 901 | − else if (n->voltage < -100.) n->voltage = -100.0f; | |
| 902 | − | |
| 903 | − //(inputCurrent + (voltage - ((voltage * timeStep) / timeConstant)) + P[0] + P[1] + P[2]) => voltage; | |
| 904 | − // now we should have a result | |
| 905 | − //set the output voltage to the "step" ugen, which controls the DAC. | |
| 906 | − output = n->voltage * 0.01f; // volts | |
| 907 | − | |
| 908 | − output = tPoleZero_tick(&n->f, output); | |
| 909 | − | |
| 910 | − return output; | |
| 911 | − | |
| 912 | −} | |
| 913 | − | |
| 914 | −void tNeuron_setMode (tNeuron* const nr, NeuronMode mode) | |
| 915 | −{ | |
| 916 | − _tNeuron* n = *nr; | |
| 917 | − n->mode = mode; | |
| 918 | −} | |
| 919 | − | |
| 920 | −void tNeuron_setCurrent (tNeuron* const nr, float current) | |
| 921 | −{ | |
| 922 | − _tNeuron* n = *nr; | |
| 923 | − n->current = current; | |
| 924 | −} | |
| 925 | − | |
| 926 | − | |
| 927 | − | |
| 928 | −void tMinBLEP_init (tMinBLEP* const minblep, int zeroCrossings, int oversamplerRatio) | |
| 929 | −{ | |
| 930 | − tMinBLEP_initToPool(minblep, zeroCrossings, oversamplerRatio, &leaf.mempool); | |
| 931 | −} | |
| 932 | − | |
| 933 | −void tMinBLEP_free (tMinBLEP* const minblep) | |
| 934 | −{ | |
| 935 | − tMinBLEP_freeFromPool(minblep, &leaf.mempool); | |
| 936 | −} | |
| 937 | − | |
| 938 | −void tMinBLEP_initToPool (tMinBLEP* const minblep, int zeroCrossings, int oversamplerRatio, tMempool* const mp) | |
| 939 | −{ | |
| 940 | − _tMempool* m = *mp; | |
| 941 | − _tMinBLEP* mb = *minblep = (_tMinBLEP*) mpool_alloc(sizeof(_tMinBLEP), m); | |
| 942 | − | |
| 943 | − mb->overSamplingRatio = zeroCrossings; | |
| 944 | − mb->zeroCrossings = oversamplerRatio; | |
| 945 | − mb->returnDerivative = 0; | |
| 946 | − mb->proportionalBlepFreq = (float) mb->zeroCrossings / (float) mb->overSamplingRatio; // defaults to NyQuist .... | |
| 947 | − | |
| 948 | − mb->lastValue = 0; | |
| 949 | − mb->lastDelta = 0; | |
| 950 | − | |
| 951 | −// float* x1, x2, y1, y2; | |
| 952 | − // AA FILTER | |
| 953 | −// zeromem (coefficients, sizeof (coefficients)); | |
| 954 | − | |
| 955 | − mb->minBlepSize = (mb->zeroCrossings * 2 * mb->overSamplingRatio) + 1; | |
| 956 | − | |
| 957 | − mb->ratio = 1; | |
| 958 | − mb->lastRatio = 1; | |
| 959 | − | |
| 960 | −// createLowPass (ratio); | |
| 961 | −// resetFilters(); | |
| 962 | − | |
| 963 | − mb->blepIndex = 0; | |
| 964 | − mb->numActiveBleps = 0; | |
| 965 | − //currentActiveBlepOffsets; | |
| 966 | − | |
| 967 | − // These probably don't need to be this large | |
| 968 | − mb->offset = (float*) mpool_alloc(sizeof(float) * mb->minBlepSize, m); | |
| 969 | −// mb->freqMultiple = (float*) mpool_alloc(sizeof(float) * mb->minBlepSize, m); | |
| 970 | − mb->pos_change_magnitude = (float*) mpool_alloc(sizeof(float) * mb->minBlepSize, m); | |
| 971 | − mb->vel_change_magnitude = (float*) mpool_alloc(sizeof(float) * mb->minBlepSize, m); | |
| 972 | − | |
| 973 | − mb->minBlepArray = (float*) mpool_alloc(sizeof(float) * mb->minBlepSize, m); | |
| 974 | − mb->minBlepDerivArray = (float*) mpool_alloc(sizeof(float) * mb->minBlepSize, m); | |
| 975 | − | |
| 976 | − tMinBLEP_buildBLEP(minblep); | |
| 977 | −} | |
| 978 | − | |
| 979 | −void tMinBLEP_freeFromPool (tMinBLEP* const minblep, tMempool* const mp) | |
| 980 | −{ | |
| 981 | − _tMempool* m = *mp; | |
| 982 | − _tMinBLEP* mb = *minblep; | |
| 983 | − | |
| 984 | − mpool_free((char*)mb->offset, m); | |
| 985 | −// mpool_free(mb->freqMultiple, m); | |
| 986 | − mpool_free((char*)mb->pos_change_magnitude, m); | |
| 987 | − mpool_free((char*)mb->vel_change_magnitude, m); | |
| 988 | − | |
| 989 | − mpool_free((char*)mb->minBlepArray, m); | |
| 990 | − mpool_free((char*)mb->minBlepDerivArray, m); | |
| 991 | − | |
| 992 | − mpool_free((char*)mb, m); | |
| 993 | −} | |
| 994 | − | |
| 995 | −// SINC Function | |
| 996 | −static float SINC(float x) | |
| 997 | −{ | |
| 998 | − float pix; | |
| 999 | − | |
| 1000 | − if(x == 0.0f) | |
| 1001 | − return 1.0f; | |
| 1002 | − else | |
| 1003 | − { | |
| 1004 | − pix = PI * x; | |
| 1005 | − return sinf(pix) / pix; | |
| 1006 | − } | |
| 1007 | −} | |
| 1008 | − | |
| 1009 | −// Generate Blackman Window | |
| 1010 | −static void BlackmanWindow(int n, float *w) | |
| 1011 | −{ | |
| 1012 | − int m = n - 1; | |
| 1013 | − int i; | |
| 1014 | − float f1, f2, fm; | |
| 1015 | − | |
| 1016 | − fm = (float)m; | |
| 1017 | − for(i = 0; i <= m; i++) | |
| 1018 | − { | |
| 1019 | − f1 = (2.0f * PI * (float)i) / fm; | |
| 1020 | − f2 = 2.0f * f1; | |
| 1021 | − w[i] = 0.42f - (0.5f * cosf(f1)) + (0.08f * cosf(f2)); | |
| 1022 | − } | |
| 1023 | −} | |
| 1024 | − | |
| 1025 | −// Discrete Fourier Transform | |
| 1026 | −static void DFT(int n, float *realTime, float *imagTime, float *realFreq, float *imagFreq) | |
| 1027 | −{ | |
| 1028 | − int k, i; | |
| 1029 | − float sr, si, p; | |
| 1030 | − | |
| 1031 | − for(k = 0; k < n; k++) | |
| 1032 | − { | |
| 1033 | − realFreq[k] = 0.0f; | |
| 1034 | − imagFreq[k] = 0.0f; | |
| 1035 | − } | |
| 1036 | − | |
| 1037 | − for(k = 0; k < n; k++) | |
| 1038 | − for(i = 0; i < n; i++) | |
| 1039 | − { | |
| 1040 | − p = (2.0f * PI * (float)(k * i)) / n; | |
| 1041 | − sr = cosf(p); | |
| 1042 | − si = -sinf(p); | |
| 1043 | − realFreq[k] += (realTime[i] * sr) - (imagTime[i] * si); | |
| 1044 | − imagFreq[k] += (realTime[i] * si) + (imagTime[i] * sr); | |
| 1045 | − } | |
| 1046 | −} | |
| 1047 | − | |
| 1048 | −// Inverse Discrete Fourier Transform | |
| 1049 | −static void InverseDFT(int n, float *realTime, float *imagTime, float *realFreq, float *imagFreq) | |
| 1050 | −{ | |
| 1051 | − int k, i; | |
| 1052 | − float sr, si, p; | |
| 1053 | − | |
| 1054 | − for(k = 0; k < n; k++) | |
| 1055 | − { | |
| 1056 | − realTime[k] = 0.0f; | |
| 1057 | − imagTime[k] = 0.0f; | |
| 1058 | − } | |
| 1059 | − | |
| 1060 | − for(k = 0; k < n; k++) | |
| 1061 | − { | |
| 1062 | − for(i = 0; i < n; i++) | |
| 1063 | − { | |
| 1064 | − p = (2.0f * PI * (float)(k * i)) / n; | |
| 1065 | − sr = cosf(p); | |
| 1066 | − si = -sinf(p); | |
| 1067 | − realTime[k] += (realFreq[i] * sr) + (imagFreq[i] * si); | |
| 1068 | − imagTime[k] += (realFreq[i] * si) - (imagFreq[i] * sr); | |
| 1069 | − } | |
| 1070 | − realTime[k] /= n; | |
| 1071 | − imagTime[k] /= n; | |
| 1072 | − } | |
| 1073 | −} | |
| 1074 | − | |
| 1075 | −// Complex Absolute Value | |
| 1076 | −static float complexabs(float x, float y) | |
| 1077 | −{ | |
| 1078 | − return sqrtf((x * x) + (y * y)); | |
| 1079 | −} | |
| 1080 | − | |
| 1081 | −// Complex Exponential | |
| 1082 | −static void complexexp(float x, float y, float *zx, float *zy) | |
| 1083 | −{ | |
| 1084 | − float expx; | |
| 1085 | − | |
| 1086 | − expx = expf(x); | |
| 1087 | − *zx = expx * cosf(y); | |
| 1088 | − *zy = expx * sinf(y); | |
| 1089 | −} | |
| 1090 | − | |
| 1091 | −// Compute Real Cepstrum Of Signal | |
| 1092 | −static void RealCepstrum(int n, float *signal, float *realCepstrum) | |
| 1093 | −{ | |
| 1094 | − int i; | |
| 1095 | − | |
| 1096 | − float realTime[n]; | |
| 1097 | − float imagTime[n]; | |
| 1098 | − float realFreq[n]; | |
| 1099 | − float imagFreq[n]; | |
| 1100 | − | |
| 1101 | − // Compose Complex FFT Input | |
| 1102 | − | |
| 1103 | − for(i = 0; i < n; i++) | |
| 1104 | − { | |
| 1105 | − realTime[i] = signal[i]; | |
| 1106 | − imagTime[i] = 0.0f; | |
| 1107 | − } | |
| 1108 | − | |
| 1109 | − // Perform DFT | |
| 1110 | − | |
| 1111 | − DFT(n, realTime, imagTime, realFreq, imagFreq); | |
| 1112 | − | |
| 1113 | − // Calculate Log Of Absolute Value | |
| 1114 | − | |
| 1115 | − for(i = 0; i < n; i++) | |
| 1116 | − { | |
| 1117 | − realFreq[i] = logf(complexabs(realFreq[i], imagFreq[i])); | |
| 1118 | − imagFreq[i] = 0.0f; | |
| 1119 | − } | |
| 1120 | − | |
| 1121 | − // Perform Inverse FFT | |
| 1122 | − | |
| 1123 | − InverseDFT(n, realTime, imagTime, realFreq, imagFreq); | |
| 1124 | − | |
| 1125 | − // Output Real Part Of FFT | |
| 1126 | − for(i = 0; i < n; i++) | |
| 1127 | − realCepstrum[i] = realTime[i]; | |
| 1128 | −} | |
| 1129 | − | |
| 1130 | −// Compute Minimum Phase Reconstruction Of Signal | |
| 1131 | −static void MinimumPhase(int n, float *realCepstrum, float *minimumPhase) | |
| 1132 | −{ | |
| 1133 | − int i, nd2; | |
| 1134 | − float realTime[n]; | |
| 1135 | − float imagTime[n]; | |
| 1136 | − float realFreq[n]; | |
| 1137 | − float imagFreq[n]; | |
| 1138 | − | |
| 1139 | − nd2 = n / 2; | |
| 1140 | − | |
| 1141 | − if((n % 2) == 1) | |
| 1142 | − { | |
| 1143 | − realTime[0] = realCepstrum[0]; | |
| 1144 | − for(i = 1; i < nd2; i++) | |
| 1145 | − realTime[i] = 2.0f * realCepstrum[i]; | |
| 1146 | − for(i = nd2; i < n; i++) | |
| 1147 | − realTime[i] = 0.0f; | |
| 1148 | − } | |
| 1149 | − else | |
| 1150 | − { | |
| 1151 | − realTime[0] = realCepstrum[0]; | |
| 1152 | − for(i = 1; i < nd2; i++) | |
| 1153 | − realTime[i] = 2.0f * realCepstrum[i]; | |
| 1154 | − realTime[nd2] = realCepstrum[nd2]; | |
| 1155 | − for(i = nd2 + 1; i < n; i++) | |
| 1156 | − realTime[i] = 0.0f; | |
| 1157 | − } | |
| 1158 | − | |
| 1159 | − for(i = 0; i < n; i++) | |
| 1160 | − imagTime[i] = 0.0f; | |
| 1161 | − | |
| 1162 | − DFT(n, realTime, imagTime, realFreq, imagFreq); | |
| 1163 | − | |
| 1164 | − for(i = 0; i < n; i++) | |
| 1165 | − complexexp(realFreq[i], imagFreq[i], &realFreq[i], &imagFreq[i]); | |
| 1166 | − | |
| 1167 | − InverseDFT(n, realTime, imagTime, realFreq, imagFreq); | |
| 1168 | − | |
| 1169 | − for(i = 0; i < n; i++) | |
| 1170 | − minimumPhase[i] = realTime[i]; | |
| 1171 | −} | |
| 1172 | − | |
| 1173 | − | |
| 1174 | −// Generate the MinBLEP | |
| 1175 | −void tMinBLEP_buildBLEP(tMinBLEP* const minblep) | |
| 1176 | −{ | |
| 1177 | − _tMinBLEP* m = *minblep; | |
| 1178 | − | |
| 1179 | − int i, n; | |
| 1180 | − float r, a, b; | |
| 1181 | − | |
| 1182 | − n = m->minBlepSize; | |
| 1183 | − | |
| 1184 | − // Generate Sinc | |
| 1185 | − | |
| 1186 | − a = -m->overSamplingRatio; | |
| 1187 | − b = m->overSamplingRatio; | |
| 1188 | − for(i = 0; i < n; i++) | |
| 1189 | − { | |
| 1190 | − r = ((float)i) / ((float)(n - 1)); | |
| 1191 | − m->minBlepArray[i] = SINC(a + (r * (b - a))); | |
| 1192 | − m->minBlepDerivArray[i] = 0; | |
| 1193 | − } | |
| 1194 | − | |
| 1195 | − // Window Sinc | |
| 1196 | − | |
| 1197 | − BlackmanWindow(n, m->minBlepDerivArray); | |
| 1198 | − for(i = 0; i < n; i++) | |
| 1199 | − m->minBlepArray[i] *= m->minBlepDerivArray[i]; | |
| 1200 | − | |
| 1201 | − // Minimum Phase Reconstruction | |
| 1202 | − | |
| 1203 | − RealCepstrum(n, m->minBlepArray, m->minBlepDerivArray); | |
| 1204 | − MinimumPhase(n, m->minBlepDerivArray, m->minBlepArray); | |
| 1205 | − | |
| 1206 | − // Integrate Into MinBLEP | |
| 1207 | − a = 0.0f; | |
| 1208 | − float secondInt = 0.0f; | |
| 1209 | − for(i = 0; i < n; i++) | |
| 1210 | − { | |
| 1211 | − a += m->minBlepArray[i]; | |
| 1212 | − m->minBlepArray[i] = a; | |
| 1213 | − | |
| 1214 | − secondInt += a; | |
| 1215 | − m->minBlepDerivArray[i] = secondInt; | |
| 1216 | − } | |
| 1217 | − | |
| 1218 | − // Normalize | |
| 1219 | − a = m->minBlepArray[n - 1]; | |
| 1220 | − a = 1.0f / a; | |
| 1221 | − b = 0.0f; | |
| 1222 | − for(i = 0; i < n; i++) | |
| 1223 | − { | |
| 1224 | − m->minBlepArray[i] *= a; | |
| 1225 | − b = fmaxf(b, m->minBlepDerivArray[i]); | |
| 1226 | − } | |
| 1227 | − | |
| 1228 | − // Normalize ... | |
| 1229 | − b = 1.0f/b; | |
| 1230 | − for (i = 0; i < n; i++) | |
| 1231 | − { | |
| 1232 | − m->minBlepDerivArray[i] *= b; | |
| 1233 | − m->minBlepDerivArray[i] -= ((float)i) / ((float) n-1); | |
| 1234 | − | |
| 1235 | − // SUBTRACT 1 and invert so the signal (so it goes 1->0) | |
| 1236 | − m->minBlepArray[i] -= 1.0f; | |
| 1237 | − m->minBlepArray[i] = -m->minBlepArray[i]; | |
| 1238 | − } | |
| 1239 | −} | |
| 1240 | − | |
| 1241 | −void tMinBLEP_addBLEP (tMinBLEP* const minblep, float offset, float posChange, float velChange) | |
| 1242 | −{ | |
| 1243 | − _tMinBLEP* m = *minblep; | |
| 1244 | − | |
| 1245 | − int n = m->minBlepSize; | |
| 1246 | − | |
| 1247 | − m->offset[m->blepIndex] = offset; | |
| 1248 | −// m->freqMultiple[m->blepIndex] = m->overSamplingRatio*m->proportionalBlepFreq; | |
| 1249 | − m->pos_change_magnitude[m->blepIndex] = posChange; | |
| 1250 | − m->vel_change_magnitude[m->blepIndex] = velChange; | |
| 1251 | − | |
| 1252 | − m->blepIndex++; | |
| 1253 | − if (m->blepIndex >= n) m->blepIndex = 0; | |
| 1254 | − | |
| 1255 | − m->numActiveBleps++; | |
| 1256 | −} | |
| 1257 | − | |
| 1258 | −float tMinBLEP_tick (tMinBLEP* const minblep, float input) | |
| 1259 | −{ | |
| 1260 | − _tMinBLEP* m = *minblep; | |
| 1261 | − // PROCESS ALL BLEPS - | |
| 1262 | − /// for each offset, copy a portion of the blep array to the output .... | |
| 1263 | − | |
| 1264 | − float sample = input; | |
| 1265 | − | |
| 1266 | − int n = m->minBlepSize; | |
| 1267 | − | |
| 1268 | − for (int blep = 1; blep <= m->numActiveBleps; blep++) | |
| 1269 | − { | |
| 1270 | − int i = (m->blepIndex - blep + n) % n; | |
| 1271 | − float adjusted_Freq = m->overSamplingRatio*m->proportionalBlepFreq;//m->freqMultiple[i]; | |
| 1272 | − float exactPosition = m->offset[i]; | |
| 1273 | − | |
| 1274 | − float blepPosExact = adjusted_Freq*(exactPosition + 1); // +1 because this needs to trigger on the LOW SAMPLE | |
| 1275 | − float blepPosSample = 0; | |
| 1276 | − float fraction = modff(blepPosExact, &blepPosSample); | |
| 1277 | − | |
| 1278 | − // LIMIT the scaling on the derivative array | |
| 1279 | − // otherwise, it can get TOO large | |
| 1280 | − float depthLimited = m->proportionalBlepFreq; //jlimit<double>(.1, 1, proportionalBlepFreq); | |
| 1281 | − float blepDeriv_PosExact = depthLimited*m->overSamplingRatio*(exactPosition + 1); | |
| 1282 | − float blepDeriv_Sample = 0; | |
| 1283 | − float fraction_Deriv = modff(blepDeriv_PosExact, &blepDeriv_Sample); | |
| 1284 | − | |
| 1285 | − | |
| 1286 | − // DONE ... we reached the end ... | |
| 1287 | − if (((int) blepPosExact > n) && ((int) blepDeriv_PosExact > n)) | |
| 1288 | − break; | |
| 1289 | − | |
| 1290 | − // BLEP has not yet occurred ... | |
| 1291 | − if (blepPosExact < 0) | |
| 1292 | − continue; | |
| 1293 | − | |
| 1294 | − | |
| 1295 | − // 0TH ORDER COMPENSATION :::: | |
| 1296 | − /// add the BLEP to compensate for discontinuties in the POSITION | |
| 1297 | − if ( fabs(m->pos_change_magnitude[i]) > 0 && blepPosSample < n) | |
| 1298 | − { | |
| 1299 | − // LINEAR INTERPOLATION :::: | |
| 1300 | − float lowValue = m->minBlepArray[(int) blepPosSample]; | |
| 1301 | − float hiValue = lowValue; | |
| 1302 | − | |
| 1303 | − if ((int) blepPosSample + 1 < n) | |
| 1304 | − hiValue = m->minBlepArray[(int) blepPosSample + 1]; | |
| 1305 | − | |
| 1306 | − float delta = hiValue - lowValue; | |
| 1307 | − float exactValue = lowValue + fraction*delta; | |
| 1308 | − | |
| 1309 | − // SCALE by the discontinuity magnitude | |
| 1310 | − exactValue *= m->pos_change_magnitude[i]; | |
| 1311 | − | |
| 1312 | − // ADD to the thruput | |
| 1313 | − sample += exactValue; | |
| 1314 | − } | |
| 1315 | − | |
| 1316 | − | |
| 1317 | − // 1ST ORDER COMPENSATION :::: | |
| 1318 | − /// add the BLEP DERIVATIVE to compensate for discontinuties in the VELOCITY | |
| 1319 | − if ( fabs(m->vel_change_magnitude[i]) > 0 && blepDeriv_PosExact < n) | |
| 1320 | − { | |
| 1321 | − | |
| 1322 | − // LINEAR INTERPOLATION :::: | |
| 1323 | − double lowValue = m->minBlepDerivArray[(int) blepDeriv_PosExact]; | |
| 1324 | − double hiValue = lowValue; | |
| 1325 | − | |
| 1326 | − if ((int) blepDeriv_PosExact + 1 < n) | |
| 1327 | − hiValue = m->minBlepDerivArray[(int) blepDeriv_PosExact + 1]; | |
| 1328 | − | |
| 1329 | − double delta = hiValue - lowValue; | |
| 1330 | − double exactValue = lowValue + fraction_Deriv*delta; | |
| 1331 | − | |
| 1332 | − // SCALE by the discontinuity magnitude` | |
| 1333 | − exactValue *= m->vel_change_magnitude[i]; | |
| 1334 | − | |
| 1335 | − // ADD to the thruput | |
| 1336 | − sample += exactValue; | |
| 1337 | − | |
| 1338 | − } | |
| 1339 | − | |
| 1340 | − // UPDATE :::: | |
| 1341 | − m->offset[i] += 1.0f; | |
| 1342 | − if (m->offset[i] * adjusted_Freq > n) | |
| 1343 | − { | |
| 1344 | − m->numActiveBleps--; | |
| 1345 | − } | |
| 1346 | − } | |
| 1347 | − return sample; | |
| 1348 | −} | |
| 1349 | − | |
| 1350 | −//============================================================================== | |
| 1351 | − | |
| 1352 | −/* tMBTriangle: Anti-aliased Triangle waveform. */ | |
| 1353 | −void tMBTriangle_init (tMBTriangle* const osc) | |
| 1354 | −{ | |
| 1355 | − tMBTriangle_initToPool(osc, &leaf.mempool); | |
| 1356 | −} | |
| 1357 | − | |
| 1358 | −void tMBTriangle_free (tMBTriangle* const osc) | |
| 1359 | −{ | |
| 1360 | − tMBTriangle_freeFromPool(osc, &leaf.mempool); | |
| 1361 | −} | |
| 1362 | − | |
| 1363 | −void tMBTriangle_initToPool (tMBTriangle* const osc, tMempool* const mp) | |
| 1364 | −{ | |
| 1365 | − _tMempool* m = *mp; | |
| 1366 | − _tMBTriangle* c = *osc = (_tMBTriangle*) mpool_alloc(sizeof(_tMBTriangle), m); | |
| 1367 | − | |
| 1368 | − c->inc = 0.0f; | |
| 1369 | − c->phase = 0.0f; | |
| 1370 | − c->skew = 0.5f; | |
| 1371 | − c->lastOut = 0.0f; | |
| 1372 | − | |
| 1373 | − tMinBLEP_initToPool(&c->minBlep, 16, 32, mp); | |
| 1374 | − tHighpass_initToPool(&c->dcBlock, 5.0f, mp); | |
| 1375 | −} | |
| 1376 | − | |
| 1377 | −void tMBTriangle_freeFromPool (tMBTriangle* const cy, tMempool* const mp) | |
| 1378 | −{ | |
| 1379 | − _tMempool* m = *mp; | |
| 1380 | − _tMBTriangle* c = *cy; | |
| 1381 | − | |
| 1382 | − tMinBLEP_freeFromPool(&c->minBlep, mp); | |
| 1383 | − tHighpass_freeFromPool(&c->dcBlock, mp); | |
| 1384 | − | |
| 1385 | − mpool_free((char*)c, m); | |
| 1386 | −} | |
| 1387 | − | |
| 1388 | −float tMBTriangle_tick (tMBTriangle* const osc) | |
| 1389 | −{ | |
| 1390 | − _tMBTriangle* c = *osc; | |
| 1391 | − | |
| 1392 | − float out; | |
| 1393 | − | |
| 1394 | − c->phase += c->inc; | |
| 1395 | − if (c->phase >= 1.0f) | |
| 1396 | − { | |
| 1397 | − c->phase -= 1.0f; | |
| 1398 | − float offset = 1.0f - ((c->inc - c->phase) / c->inc); | |
| 1399 | − tMinBLEP_addBLEP(&c->minBlep, offset, -2, 0.0f); | |
| 1400 | − } | |
| 1401 | − if (c->skew <= c->phase && c->phase < c->skew + c->inc) | |
| 1402 | − { | |
| 1403 | − float offset = 1.0f - ((c->inc - c->phase + c->skew) / c->inc); | |
| 1404 | − tMinBLEP_addBLEP(&c->minBlep, offset, 2, 0.0f); | |
| 1405 | − } | |
| 1406 | − | |
| 1407 | − if (c->phase < c->skew) | |
| 1408 | − { | |
| 1409 | − out = (1.0f - c->skew) * 2.0f; | |
| 1410 | − } | |
| 1411 | − else | |
| 1412 | − { | |
| 1413 | − out = -c->skew * 2.0f; | |
| 1414 | − } | |
| 1415 | − | |
| 1416 | − out = tMinBLEP_tick(&c->minBlep, out);// - phasor->inc * 2.0f; | |
| 1417 | − | |
| 1418 | − out = (c->inc * out) + ((1 - c->inc) * c->lastOut); | |
| 1419 | − c->lastOut = out; | |
| 1420 | − | |
| 1421 | − return tHighpass_tick(&c->dcBlock, out * 4.0f); | |
| 1422 | − | |
| 1423 | −// float offset; | |
| 1424 | −// float vel = 2; | |
| 1425 | −// c->phase += c->inc; | |
| 1426 | −// if (c->phase >= 1.0f) | |
| 1427 | −// { | |
| 1428 | −// c->phase -= 1.0f; | |
| 1429 | −// offset = 1.0f - ((c->inc - c->phase) / c->inc); | |
| 1430 | −// tMinBLEP_addBLEP(&c->minBlep, offset, 0.0f, -vel); | |
| 1431 | −// } | |
| 1432 | −// if (c->skew <= c->phase && c->phase < c->skew + c->inc) | |
| 1433 | −// { | |
| 1434 | −// offset = 1.0f - ((c->inc - c->phase + c->skew) / c->inc); | |
| 1435 | −// tMinBLEP_addBLEP(&c->minBlep, offset, 0.0f, vel); | |
| 1436 | −// } | |
| 1437 | −// | |
| 1438 | −// float out; | |
| 1439 | −// if (c->phase < c->skew) out = 1.0f - (c->phase / c->skew); | |
| 1440 | −// else out = (c->phase - c->skew) / (1 - c->skew); | |
| 1441 | −// | |
| 1442 | −// out = (out - 0.5f) * 2.0f; | |
| 1443 | −// | |
| 1444 | −//// return tHighpass_tick(&c->dcBlock, tMinBLEP_tick(&c->minBlep, out)); | |
| 1445 | −// return tMinBLEP_tick(&c->minBlep, out); | |
| 1446 | −} | |
| 1447 | − | |
| 1448 | −void tMBTriangle_setFreq (tMBTriangle* const osc, float freq) | |
| 1449 | −{ | |
| 1450 | − _tMBTriangle* c = *osc; | |
| 1451 | − | |
| 1452 | − c->freq = freq; | |
| 1453 | − c->inc = freq * leaf.invSampleRate; | |
| 1454 | − | |
| 1455 | −// tHighpass_setFreq(&c->dcBlock, freq*0.5); | |
| 1456 | −} | |
| 1457 | − | |
| 1458 | −void tMBTriangle_setSkew (tMBTriangle* const osc, float skew) | |
| 1459 | −{ | |
| 1460 | − _tMBTriangle* c = *osc; | |
| 1461 | − c->skew = (skew + 1.0f) * 0.5f; | |
| 1462 | −} | |
| 1463 | − | |
| 1464 | −void tMBTriangle_sync (tMBTriangle* const osc, float phase) | |
| 1465 | −{ | |
| 1466 | − _tMBTriangle* c = *osc; | |
| 1467 | − | |
| 1468 | − phase += 0.5f; | |
| 1469 | − | |
| 1470 | − int intPart = (int) phase; | |
| 1471 | − phase = phase - (float) intPart; | |
| 1472 | − | |
| 1473 | − float before, after; | |
| 1474 | − | |
| 1475 | − if (c->phase < c->skew) before = (1.0f - c->skew - c->phase) * 2.0f; | |
| 1476 | − else before = -(c->skew - c->phase) * 2.0f; | |
| 1477 | − | |
| 1478 | − if (phase < c->skew) after = (1.0f - c->skew - c->phase) * 2.0f; | |
| 1479 | − else after = -(c->skew - c->phase) * 2.0f; | |
| 1480 | − | |
| 1481 | − c->phase = phase; | |
| 1482 | − | |
| 1483 | − float offset = 0.0f;//1.0f - ((c->inc - c->phase) / c->inc); | |
| 1484 | − tMinBLEP_addBLEP(&c->minBlep, offset, before - after, 0.0f); | |
| 1485 | − | |
| 1486 | − if (c->phase < c->skew) c->lastOut = 1.0f - (c->phase / c->skew); | |
| 1487 | − else c->lastOut = (c->phase - c->skew) / (1.0f - c->skew); | |
| 1488 | −} | |
| 1489 | − | |
| 1490 | −//============================================================================== | |
| 1491 | − | |
| 1492 | −/* tMBPulse: Anti-aliased pulse waveform. */ | |
| 1493 | −void tMBPulse_init (tMBPulse* const osc) | |
| 1494 | −{ | |
| 1495 | − tMBPulse_initToPool(osc, &leaf.mempool); | |
| 1496 | −} | |
| 1497 | − | |
| 1498 | −void tMBPulse_free (tMBPulse* const osc) | |
| 1499 | −{ | |
| 1500 | − tMBPulse_freeFromPool(osc, &leaf.mempool); | |
| 1501 | −} | |
| 1502 | − | |
| 1503 | −void tMBPulse_initToPool (tMBPulse* const osc, tMempool* const mp) | |
| 1504 | −{ | |
| 1505 | − _tMempool* m = *mp; | |
| 1506 | − _tMBPulse* c = *osc = (_tMBPulse*) mpool_alloc(sizeof(_tMBPulse), m); | |
| 1507 | − | |
| 1508 | − c->inc = 0.0f; | |
| 1509 | − c->phase = 0.0f; | |
| 1510 | − c->width = 0.5f; | |
| 1511 | − | |
| 1512 | − tMinBLEP_initToPool(&c->minBlep, 16, 32, mp); | |
| 1513 | − tHighpass_initToPool(&c->dcBlock, 10.0f, mp); | |
| 1514 | −} | |
| 1515 | − | |
| 1516 | −void tMBPulse_freeFromPool(tMBPulse* const osc, tMempool* const mp) | |
| 1517 | −{ | |
| 1518 | − _tMempool* m = *mp; | |
| 1519 | − _tMBPulse* c = *osc; | |
| 1520 | − | |
| 1521 | − tMinBLEP_freeFromPool(&c->minBlep, mp); | |
| 1522 | − tHighpass_freeFromPool(&c->dcBlock, mp); | |
| 1523 | − | |
| 1524 | − mpool_free((char*)c, m); | |
| 1525 | −} | |
| 1526 | − | |
| 1527 | −float tMBPulse_tick (tMBPulse* const osc) | |
| 1528 | −{ | |
| 1529 | − _tMBPulse* c = *osc; | |
| 1530 | − | |
| 1531 | − | |
| 1532 | − | |
| 1533 | − c->phase += c->inc; | |
| 1534 | − if (c->phase >= 1.0f) | |
| 1535 | − { | |
| 1536 | − c->phase -= 1.0f; | |
| 1537 | − float offset = 1.0f - ((c->inc - c->phase) / c->inc); | |
| 1538 | − tMinBLEP_addBLEP(&c->minBlep, offset, -2.0f, 0.0f); | |
| 1539 | − } | |
| 1540 | − if (c->width <= c->phase && c->phase < c->width + c->inc) | |
| 1541 | − { | |
| 1542 | − float offset = 1.0f - ((c->inc - c->phase + c->width) / c->inc); | |
| 1543 | − tMinBLEP_addBLEP(&c->minBlep, offset, 2.0f, 0.0f); | |
| 1544 | − } | |
| 1545 | − | |
| 1546 | − float out; | |
| 1547 | − if (c->phase < c->width) out = 1.0f; | |
| 1548 | − else out = -1.0f; | |
| 1549 | − | |
| 1550 | − return tHighpass_tick(&c->dcBlock, tMinBLEP_tick(&c->minBlep, out)); | |
| 1551 | −} | |
| 1552 | − | |
| 1553 | −void tMBPulse_setFreq (tMBPulse* const osc, float freq) | |
| 1554 | −{ | |
| 1555 | − _tMBPulse* c = *osc; | |
| 1556 | − | |
| 1557 | − c->freq = freq; | |
| 1558 | − c->inc = freq * leaf.invSampleRate; | |
| 1559 | −} | |
| 1560 | − | |
| 1561 | −void tMBPulse_setWidth (tMBPulse* const osc, float width) | |
| 1562 | −{ | |
| 1563 | − _tMBPulse* c = *osc; | |
| 1564 | − c->width = width; | |
| 1565 | −} | |
| 1566 | − | |
| 1567 | −void tMBPulse_sync (tMBPulse* const osc, float phase) | |
| 1568 | −{ | |
| 1569 | − _tMBPulse* c = *osc; | |
| 1570 | − int intPart = (int) phase; | |
| 1571 | − phase = phase - (float) intPart; | |
| 1572 | − | |
| 1573 | − float before, after; | |
| 1574 | − | |
| 1575 | − if (c->phase < c->width) before = 1.0f; | |
| 1576 | − else before = -1.0f; | |
| 1577 | − | |
| 1578 | − if (phase < c->width) after = 1.0; | |
| 1579 | − else after = -1.0f; | |
| 1580 | − | |
| 1581 | − float offset = 0.0f;//1.0f - ((c->inc - c->phase) / c->inc); | |
| 1582 | − tMinBLEP_addBLEP(&c->minBlep, offset, before - after, 0.0f); | |
| 1583 | − | |
| 1584 | − c->phase = phase; | |
| 1585 | −} | |
| 1586 | − | |
| 1587 | − | |
| 1588 | −//============================================================================== | |
| 1589 | − | |
| 1590 | −/* tMBSawtooth: Anti-aliased Sawtooth waveform. */ | |
| 1591 | −void tMBSaw_init (tMBSaw* const osc) | |
| 1592 | −{ | |
| 1593 | − tMBSaw_initToPool(osc, &leaf.mempool); | |
| 1594 | −} | |
| 1595 | − | |
| 1596 | −void tMBSaw_free (tMBSaw* const osc) | |
| 1597 | −{ | |
| 1598 | − tMBSaw_freeFromPool(osc, &leaf.mempool); | |
| 1599 | −} | |
| 1600 | − | |
| 1601 | −void tMBSaw_initToPool (tMBSaw* const osc, tMempool* const mp) | |
| 1602 | −{ | |
| 1603 | − _tMempool* m = *mp; | |
| 1604 | − _tMBSaw* c = *osc = (_tMBSaw*) mpool_alloc(sizeof(_tMBSaw), m); | |
| 1605 | − | |
| 1606 | − c->inc = 0.0f; | |
| 1607 | − c->phase = 0.0f; | |
| 1608 | − | |
| 1609 | − tMinBLEP_initToPool(&c->minBlep, 16, 32, mp); | |
| 1610 | − tHighpass_initToPool(&c->dcBlock, 10.0f, mp); | |
| 1611 | −} | |
| 1612 | − | |
| 1613 | −void tMBSaw_freeFromPool (tMBSaw* const osc, tMempool* const mp) | |
| 1614 | −{ | |
| 1615 | − _tMempool* m = *mp; | |
| 1616 | − _tMBSaw* c = *osc; | |
| 1617 | − | |
| 1618 | − tMinBLEP_freeFromPool(&c->minBlep, mp); | |
| 1619 | − tHighpass_freeFromPool(&c->dcBlock, mp); | |
| 1620 | − | |
| 1621 | − mpool_free((char*)c, m); | |
| 1622 | −} | |
| 1623 | − | |
| 1624 | −float tMBSaw_tick (tMBSaw* const osc) | |
| 1625 | −{ | |
| 1626 | − _tMBSaw* c = *osc; | |
| 1627 | − | |
| 1628 | − c->phase += c->inc; | |
| 1629 | − if (c->phase >= 1.0f) | |
| 1630 | − { | |
| 1631 | − c->phase -= 1.0f; | |
| 1632 | − float offset = 1.0f - ((c->inc - c->phase) / c->inc); | |
| 1633 | − tMinBLEP_addBLEP(&c->minBlep, offset, 2.0f, 0.0f); | |
| 1634 | − } | |
| 1635 | − | |
| 1636 | − float out = (c->phase * 2.0f) - 1.0f; | |
| 1637 | − | |
| 1638 | − return tHighpass_tick(&c->dcBlock, tMinBLEP_tick(&c->minBlep, out)); | |
| 1639 | −} | |
| 1640 | − | |
| 1641 | −void tMBSaw_setFreq (tMBSaw* const osc, float freq) | |
| 1642 | −{ | |
| 1643 | − _tMBSaw* c = *osc; | |
| 1644 | − | |
| 1645 | − c->freq = freq; | |
| 1646 | − | |
| 1647 | − c->inc = freq * leaf.invSampleRate; | |
| 1648 | −} | |
| 1649 | − | |
| 1650 | −void tMBSaw_sync (tMBSaw* const osc, float phase) | |
| 1651 | −{ | |
| 1652 | − _tMBSaw* c = *osc; | |
| 1653 | − int intPart = (int) phase; | |
| 1654 | − phase = phase - (float) intPart; | |
| 1655 | − | |
| 1656 | − float offset = 0.0f;//1.0f - ((c->inc - phase +) / c->inc); | |
| 1657 | − tMinBLEP_addBLEP(&c->minBlep, offset, (c->phase - phase) * 2.0f, 0.0f); | |
| 1658 | − | |
| 1659 | − c->phase = phase; | |
| 1660 | −} | |
| @@ -1,747 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-string.c | |
| 4 | − Created: 30 Nov 2018 10:41:42am | |
| 5 | − Author: airship | |
| 6 | − | |
| 7 | −==============================================================================*/ | |
| 8 | − | |
| 9 | −#if _WIN32 || _WIN64 | |
| 10 | − | |
| 11 | −#include "..\Inc\leaf-physical.h" | |
| 12 | − | |
| 13 | −#else | |
| 14 | − | |
| 15 | −#include "../Inc/leaf-physical.h" | |
| 16 | − | |
| 17 | −#endif | |
| 18 | − | |
| 19 | −/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tPluck ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */ | |
| 20 | −void tPluck_init (tPluck* const pl, float lowestFrequency) | |
| 21 | −{ | |
| 22 | − tPluck_initToPool(pl, lowestFrequency, &leaf.mempool); | |
| 23 | −} | |
| 24 | − | |
| 25 | −void tPluck_free (tPluck* const pl) | |
| 26 | −{ | |
| 27 | − tPluck_freeFromPool(pl, &leaf.mempool); | |
| 28 | −} | |
| 29 | − | |
| 30 | −void tPluck_initToPool (tPluck* const pl, float lowestFrequency, tMempool* const mp) | |
| 31 | −{ | |
| 32 | − _tMempool* m = *mp; | |
| 33 | − _tPluck* p = *pl = (_tPluck*) mpool_alloc(sizeof(_tPluck), m); | |
| 34 | − | |
| 35 | − if ( lowestFrequency <= 0.0f ) lowestFrequency = 10.0f; | |
| 36 | − | |
| 37 | − tNoise_initToPool(&p->noise, WhiteNoise, mp); | |
| 38 | − | |
| 39 | − tOnePole_initToPool(&p->pickFilter, 0.0f, mp); | |
| 40 | − | |
| 41 | − tOneZero_initToPool(&p->loopFilter, 0.0f, mp); | |
| 42 | − | |
| 43 | − tAllpassDelay_initToPool(&p->delayLine, 0.0f, leaf.sampleRate * 2, mp); | |
| 44 | − tAllpassDelay_clear(&p->delayLine); | |
| 45 | − | |
| 46 | − tPluck_setFrequency(pl, 220.0f); | |
| 47 | −} | |
| 48 | − | |
| 49 | −void tPluck_freeFromPool (tPluck* const pl, tMempool* const mp) | |
| 50 | −{ | |
| 51 | − _tMempool* m = *mp; | |
| 52 | − _tPluck* p = *pl; | |
| 53 | − | |
| 54 | − tNoise_freeFromPool(&p->noise, mp); | |
| 55 | − tOnePole_freeFromPool(&p->pickFilter, mp); | |
| 56 | − tOneZero_freeFromPool(&p->loopFilter, mp); | |
| 57 | − tAllpassDelay_freeFromPool(&p->delayLine, mp); | |
| 58 | − | |
| 59 | − mpool_free((char*)p, m); | |
| 60 | −} | |
| 61 | − | |
| 62 | −float tPluck_getLastOut (tPluck* const pl) | |
| 63 | −{ | |
| 64 | − _tPluck* p = *pl; | |
| 65 | − return p->lastOut; | |
| 66 | −} | |
| 67 | − | |
| 68 | −float tPluck_tick (tPluck* const pl) | |
| 69 | −{ | |
| 70 | − _tPluck* p = *pl; | |
| 71 | − return (p->lastOut = 3.0f * tAllpassDelay_tick(&p->delayLine, tOneZero_tick(&p->loopFilter, tAllpassDelay_getLastOut(&p->delayLine) * p->loopGain ) )); | |
| 72 | −} | |
| 73 | − | |
| 74 | −void tPluck_pluck (tPluck* const pl, float amplitude) | |
| 75 | −{ | |
| 76 | − _tPluck* p = *pl; | |
| 77 | − | |
| 78 | − if ( amplitude < 0.0f) amplitude = 0.0f; | |
| 79 | − else if (amplitude > 1.0f) amplitude = 1.0f; | |
| 80 | − | |
| 81 | − tOnePole_setPole(&p->pickFilter, 0.999f - (amplitude * 0.15f)); | |
| 82 | − tOnePole_setGain(&p->pickFilter, amplitude * 0.5f ); | |
| 83 | − | |
| 84 | − // Fill delay with noise additively with current contents. | |
| 85 | − for ( uint32_t i = 0; i < (uint32_t)tAllpassDelay_getDelay(&p->delayLine); i++ ) | |
| 86 | − tAllpassDelay_tick(&p->delayLine, 0.6f * tAllpassDelay_getLastOut(&p->delayLine) + tOnePole_tick(&p->pickFilter, tNoise_tick(&p->noise) ) ); | |
| 87 | −} | |
| 88 | − | |
| 89 | −// Start a note with the given frequency and amplitude.; | |
| 90 | −void tPluck_noteOn (tPluck* const pl, float frequency, float amplitude ) | |
| 91 | −{ | |
| 92 | − _tPluck* p = *pl; | |
| 93 | − p->lastFreq = frequency; | |
| 94 | − tPluck_setFrequency( pl, frequency ); | |
| 95 | − tPluck_pluck( pl, amplitude ); | |
| 96 | −} | |
| 97 | − | |
| 98 | −// Stop a note with the given amplitude (speed of decay). | |
| 99 | −void tPluck_noteOff (tPluck* const pl, float amplitude ) | |
| 100 | −{ | |
| 101 | − _tPluck* p = *pl; | |
| 102 | − | |
| 103 | − if ( amplitude < 0.0f) amplitude = 0.0f; | |
| 104 | − else if (amplitude > 1.0f) amplitude = 1.0f; | |
| 105 | − | |
| 106 | − p->loopGain = 1.0f - amplitude; | |
| 107 | −} | |
| 108 | − | |
| 109 | −// Set instrument parameters for a particular frequency. | |
| 110 | −void tPluck_setFrequency (tPluck* const pl, float frequency ) | |
| 111 | −{ | |
| 112 | − _tPluck* p = *pl; | |
| 113 | − | |
| 114 | − if ( frequency <= 0.0f ) frequency = 0.001f; | |
| 115 | − | |
| 116 | − // Delay = length - filter delay. | |
| 117 | − float delay = ( leaf.sampleRate / frequency ) - tOneZero_getPhaseDelay(&p->loopFilter, frequency ); | |
| 118 | − | |
| 119 | − tAllpassDelay_setDelay(&p->delayLine, delay ); | |
| 120 | − | |
| 121 | − p->loopGain = 0.99f + (frequency * 0.000005f); | |
| 122 | − | |
| 123 | − if ( p->loopGain >= 0.999f ) p->loopGain = 0.999f; | |
| 124 | − | |
| 125 | −} | |
| 126 | − | |
| 127 | −// Perform the control change specified by \e number and \e value (0.0 - 128.0). | |
| 128 | −void tPluck_controlChange (tPluck* const pl, int number, float value) | |
| 129 | −{ | |
| 130 | − return; | |
| 131 | −} | |
| 132 | − | |
| 133 | −void tPluckSampleRateChanged(tPluck* const pl) | |
| 134 | −{ | |
| 135 | − _tPluck* p = *pl; | |
| 136 | − tPluck_setFrequency(pl, p->lastFreq); | |
| 137 | −} | |
| 138 | − | |
| 139 | −/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tKarplusStrong ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */ | |
| 140 | −void tKarplusStrong_init (tKarplusStrong* const pl, float lowestFrequency) | |
| 141 | −{ | |
| 142 | − tKarplusStrong_initToPool(pl, lowestFrequency, &leaf.mempool); | |
| 143 | −} | |
| 144 | − | |
| 145 | −void tKarplusStrong_free (tKarplusStrong* const pl) | |
| 146 | −{ | |
| 147 | − tKarplusStrong_freeFromPool(pl, &leaf.mempool); | |
| 148 | −} | |
| 149 | − | |
| 150 | −void tKarplusStrong_initToPool (tKarplusStrong* const pl, float lowestFrequency, tMempool* const mp) | |
| 151 | −{ | |
| 152 | − _tMempool* m = *mp; | |
| 153 | − _tKarplusStrong* p = *pl = (_tKarplusStrong*) mpool_alloc(sizeof(_tKarplusStrong), m); | |
| 154 | − | |
| 155 | − if ( lowestFrequency <= 0.0f ) lowestFrequency = 8.0f; | |
| 156 | − | |
| 157 | − tAllpassDelay_initToPool(&p->delayLine, 0.0f, leaf.sampleRate * 2, mp); | |
| 158 | − tAllpassDelay_clear(&p->delayLine); | |
| 159 | − | |
| 160 | − tLinearDelay_initToPool(&p->combDelay, 0.0f, leaf.sampleRate * 2, mp); | |
| 161 | − tLinearDelay_clear(&p->combDelay); | |
| 162 | − | |
| 163 | − tOneZero_initToPool(&p->filter, 0.0f, mp); | |
| 164 | − | |
| 165 | − tNoise_initToPool(&p->noise, WhiteNoise, mp); | |
| 166 | − | |
| 167 | − for (int i = 0; i < 4; i++) | |
| 168 | − { | |
| 169 | − tBiQuad_initToPool(&p->biquad[i], mp); | |
| 170 | − } | |
| 171 | − | |
| 172 | − p->pluckAmplitude = 0.3f; | |
| 173 | − p->pickupPosition = 0.4f; | |
| 174 | − | |
| 175 | − p->stretching = 0.9999f; | |
| 176 | − p->baseLoopGain = 0.995f; | |
| 177 | − p->loopGain = 0.999f; | |
| 178 | − | |
| 179 | − tKarplusStrong_setFrequency( pl, 220.0f ); | |
| 180 | −} | |
| 181 | − | |
| 182 | −void tKarplusStrong_freeFromPool (tKarplusStrong* const pl, tMempool* const mp) | |
| 183 | −{ | |
| 184 | − _tMempool* m = *mp; | |
| 185 | − _tKarplusStrong* p = *pl; | |
| 186 | − | |
| 187 | − tAllpassDelay_freeFromPool(&p->delayLine, mp); | |
| 188 | − tLinearDelay_freeFromPool(&p->combDelay, mp); | |
| 189 | − tOneZero_freeFromPool(&p->filter, mp); | |
| 190 | − tNoise_freeFromPool(&p->noise, mp); | |
| 191 | − | |
| 192 | − for (int i = 0; i < 4; i++) | |
| 193 | − { | |
| 194 | − tBiQuad_freeFromPool(&p->biquad[i], mp); | |
| 195 | − } | |
| 196 | − | |
| 197 | − mpool_free((char*)p, m); | |
| 198 | −} | |
| 199 | − | |
| 200 | −float tKarplusStrong_getLastOut (tKarplusStrong* const pl) | |
| 201 | −{ | |
| 202 | − _tKarplusStrong* p = *pl; | |
| 203 | − return p->lastOut; | |
| 204 | −} | |
| 205 | − | |
| 206 | −float tKarplusStrong_tick (tKarplusStrong* const pl) | |
| 207 | −{ | |
| 208 | − _tKarplusStrong* p = *pl; | |
| 209 | − | |
| 210 | − float temp = tAllpassDelay_getLastOut(&p->delayLine) * p->loopGain; | |
| 211 | − | |
| 212 | − // Calculate allpass stretching. | |
| 213 | − for (int i=0; i<4; i++) temp = tBiQuad_tick(&p->biquad[i],temp); | |
| 214 | − | |
| 215 | − // Moving average filter. | |
| 216 | − temp = tOneZero_tick(&p->filter, temp); | |
| 217 | − | |
| 218 | − float out = tAllpassDelay_tick(&p->delayLine, temp); | |
| 219 | − out = out - tLinearDelay_tick(&p->combDelay, out); | |
| 220 | − p->lastOut = out; | |
| 221 | − | |
| 222 | − return p->lastOut; | |
| 223 | −} | |
| 224 | − | |
| 225 | −void tKarplusStrong_pluck (tKarplusStrong* const pl, float amplitude) | |
| 226 | −{ | |
| 227 | − _tKarplusStrong* p = *pl; | |
| 228 | − | |
| 229 | − if ( amplitude < 0.0f) amplitude = 0.0f; | |
| 230 | − else if (amplitude > 1.0f) amplitude = 1.0f; | |
| 231 | − | |
| 232 | − p->pluckAmplitude = amplitude; | |
| 233 | − | |
| 234 | − for ( uint32_t i=0; i < (uint32_t)tAllpassDelay_getDelay(&p->delayLine); i++ ) | |
| 235 | − { | |
| 236 | − // Fill delay with noise additively with current contents. | |
| 237 | − tAllpassDelay_tick(&p->delayLine, (tAllpassDelay_getLastOut(&p->delayLine) * 0.6f) + 0.4f * tNoise_tick(&p->noise) * p->pluckAmplitude ); | |
| 238 | − //delayLine_.tick( combDelay_.tick((delayLine_.lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude_) ); | |
| 239 | − } | |
| 240 | −} | |
| 241 | − | |
| 242 | −// Start a note with the given frequency and amplitude.; | |
| 243 | −void tKarplusStrong_noteOn (tKarplusStrong* const pl, float frequency, float amplitude ) | |
| 244 | −{ | |
| 245 | − tKarplusStrong_setFrequency( pl, frequency ); | |
| 246 | − tKarplusStrong_pluck( pl, amplitude ); | |
| 247 | −} | |
| 248 | − | |
| 249 | −// Stop a note with the given amplitude (speed of decay). | |
| 250 | −void tKarplusStrong_noteOff (tKarplusStrong* const pl, float amplitude ) | |
| 251 | −{ | |
| 252 | − _tKarplusStrong* p = *pl; | |
| 253 | − | |
| 254 | − if ( amplitude < 0.0f) amplitude = 0.0f; | |
| 255 | − else if (amplitude > 1.0f) amplitude = 1.0f; | |
| 256 | − | |
| 257 | − p->loopGain = 1.0f - amplitude; | |
| 258 | −} | |
| 259 | − | |
| 260 | −// Set instrument parameters for a particular frequency. | |
| 261 | −void tKarplusStrong_setFrequency (tKarplusStrong* const pl, float frequency ) | |
| 262 | −{ | |
| 263 | − _tKarplusStrong* p = *pl; | |
| 264 | − | |
| 265 | − if ( frequency <= 0.0f ) frequency = 0.001f; | |
| 266 | − | |
| 267 | − p->lastFrequency = frequency; | |
| 268 | − p->lastLength = leaf.sampleRate / p->lastFrequency; | |
| 269 | − float delay = p->lastLength - 0.5f; | |
| 270 | − tAllpassDelay_setDelay(&p->delayLine, delay); | |
| 271 | − | |
| 272 | − // MAYBE MODIFY LOOP GAINS | |
| 273 | − p->loopGain = p->baseLoopGain + (frequency * 0.000005f); | |
| 274 | − if (p->loopGain >= 1.0f) p->loopGain = 0.99999f; | |
| 275 | − | |
| 276 | − tKarplusStrong_setStretch(pl, p->stretching); | |
| 277 | − | |
| 278 | − tLinearDelay_setDelay(&p->combDelay, 0.5f * p->pickupPosition * p->lastLength ); | |
| 279 | − | |
| 280 | −} | |
| 281 | − | |
| 282 | −// Set the stretch "factor" of the string (0.0 - 1.0). | |
| 283 | −void tKarplusStrong_setStretch (tKarplusStrong* const pl, float stretch ) | |
| 284 | −{ | |
| 285 | − _tKarplusStrong* p = *pl; | |
| 286 | − | |
| 287 | − p->stretching = stretch; | |
| 288 | − float coefficient; | |
| 289 | − float freq = p->lastFrequency * 2.0f; | |
| 290 | − float dFreq = ( (0.5f * leaf.sampleRate) - freq ) * 0.25f; | |
| 291 | − float temp = 0.5f + (stretch * 0.5f); | |
| 292 | − if ( temp > 0.9999f ) temp = 0.9999f; | |
| 293 | − | |
| 294 | − for ( int i=0; i<4; i++ ) | |
| 295 | − { | |
| 296 | − coefficient = temp * temp; | |
| 297 | − tBiQuad_setA2(&p->biquad[i], coefficient); | |
| 298 | − tBiQuad_setB0(&p->biquad[i], coefficient); | |
| 299 | − tBiQuad_setB2(&p->biquad[i], 1.0f); | |
| 300 | − | |
| 301 | − coefficient = -2.0f * temp * cos(TWO_PI * freq / leaf.sampleRate); | |
| 302 | − tBiQuad_setA1(&p->biquad[i], coefficient); | |
| 303 | − tBiQuad_setB1(&p->biquad[i], coefficient); | |
| 304 | − | |
| 305 | − freq += dFreq; | |
| 306 | − } | |
| 307 | −} | |
| 308 | − | |
| 309 | −// Set the pluck or "excitation" position along the string (0.0 - 1.0). | |
| 310 | −void tKarplusStrong_setPickupPosition (tKarplusStrong* const pl, float position ) | |
| 311 | −{ | |
| 312 | − _tKarplusStrong* p = *pl; | |
| 313 | − | |
| 314 | − if (position < 0.0f) p->pickupPosition = 0.0f; | |
| 315 | − else if (position <= 1.0f) p->pickupPosition = position; | |
| 316 | − else p->pickupPosition = 1.0f; | |
| 317 | − | |
| 318 | − tLinearDelay_setDelay(&p->combDelay, 0.5f * p->pickupPosition * p->lastLength); | |
| 319 | −} | |
| 320 | − | |
| 321 | −// Set the base loop gain. | |
| 322 | −void tKarplusStrong_setBaseLoopGain (tKarplusStrong* const pl, float aGain ) | |
| 323 | −{ | |
| 324 | − _tKarplusStrong* p = *pl; | |
| 325 | − | |
| 326 | − p->baseLoopGain = aGain; | |
| 327 | − p->loopGain = p->baseLoopGain + (p->lastFrequency * 0.000005f); | |
| 328 | − if ( p->loopGain > 0.99999f ) p->loopGain = 0.99999f; | |
| 329 | −} | |
| 330 | − | |
| 331 | −// Perform the control change specified by \e number and \e value (0.0 - 128.0). | |
| 332 | −void tKarplusStrong_controlChange (tKarplusStrong* const pl, SKControlType type, float value) | |
| 333 | −{ | |
| 334 | − if ( value < 0.0f ) value = 0.0f; | |
| 335 | − else if (value > 128.0f) value = 128.0f; | |
| 336 | − | |
| 337 | − float normalizedValue = value * INV_128; | |
| 338 | − | |
| 339 | − if (type == SKPickPosition) // 4 | |
| 340 | − tKarplusStrong_setPickupPosition( pl, normalizedValue ); | |
| 341 | − else if (type == SKStringDamping) // 11 | |
| 342 | − tKarplusStrong_setBaseLoopGain( pl, 0.97f + (normalizedValue * 0.03f) ); | |
| 343 | − else if (type == SKDetune) // 1 | |
| 344 | − tKarplusStrong_setStretch( pl, 0.91f + (0.09f * (1.0f - normalizedValue)) ); | |
| 345 | −} | |
| 346 | − | |
| 347 | −void tKarplusStrongSampleRateChanged (tKarplusStrong* const pl) | |
| 348 | −{ | |
| 349 | − _tKarplusStrong* p = *pl; | |
| 350 | − | |
| 351 | − tKarplusStrong_setFrequency(pl, p->lastFrequency); | |
| 352 | − tKarplusStrong_setStretch(pl, p->stretching); | |
| 353 | −} | |
| 354 | − | |
| 355 | −/* Simple Living String*/ | |
| 356 | − | |
| 357 | −void tSimpleLivingString_init(tSimpleLivingString* const pl, float freq, float dampFreq, | |
| 358 | − float decay, float targetLev, float levSmoothFactor, | |
| 359 | − float levStrength, int levMode) | |
| 360 | −{ | |
| 361 | − tSimpleLivingString_initToPool(pl, freq, dampFreq, decay, targetLev, levSmoothFactor, levStrength, levMode, &leaf.mempool); | |
| 362 | −} | |
| 363 | − | |
| 364 | −void tSimpleLivingString_free(tSimpleLivingString* const pl) | |
| 365 | −{ | |
| 366 | − tSimpleLivingString_freeFromPool(pl, &leaf.mempool); | |
| 367 | −} | |
| 368 | − | |
| 369 | −void tSimpleLivingString_initToPool (tSimpleLivingString* const pl, float freq, float dampFreq, | |
| 370 | − float decay, float targetLev, float levSmoothFactor, | |
| 371 | − float levStrength, int levMode, tMempool* const mp) | |
| 372 | −{ | |
| 373 | − _tMempool* m = *mp; | |
| 374 | − _tSimpleLivingString* p = *pl = (_tSimpleLivingString*) mpool_alloc(sizeof(_tSimpleLivingString), m); | |
| 375 | − | |
| 376 | − p->curr=0.0f; | |
| 377 | − tExpSmooth_initToPool(&p->wlSmooth, leaf.sampleRate/freq, 0.01, mp); // smoother for string wavelength (not freq, to avoid expensive divisions) | |
| 378 | − tSimpleLivingString_setFreq(pl, freq); | |
| 379 | − tLinearDelay_initToPool(&p->delayLine,p->waveLengthInSamples, 2400, mp); | |
| 380 | − tLinearDelay_clear(&p->delayLine); | |
| 381 | − tOnePole_initToPool(&p->bridgeFilter, dampFreq, mp); | |
| 382 | − tHighpass_initToPool(&p->DCblocker,13, mp); | |
| 383 | − p->decay=decay; | |
| 384 | − tFeedbackLeveler_initToPool(&p->fbLev, targetLev, levSmoothFactor, levStrength, levMode, mp); | |
| 385 | − p->levMode=levMode; | |
| 386 | −} | |
| 387 | − | |
| 388 | −void tSimpleLivingString_freeFromPool (tSimpleLivingString* const pl, tMempool* const mp) | |
| 389 | −{ | |
| 390 | − _tMempool* m = *mp; | |
| 391 | − _tSimpleLivingString* p = *pl; | |
| 392 | − | |
| 393 | − tExpSmooth_freeFromPool(&p->wlSmooth, mp); | |
| 394 | − tLinearDelay_freeFromPool(&p->delayLine, mp); | |
| 395 | − tOnePole_freeFromPool(&p->bridgeFilter, mp); | |
| 396 | − tHighpass_freeFromPool(&p->DCblocker, mp); | |
| 397 | − tFeedbackLeveler_freeFromPool(&p->fbLev, mp); | |
| 398 | − | |
| 399 | − mpool_free((char*)p, m); | |
| 400 | −} | |
| 401 | − | |
| 402 | −void tSimpleLivingString_setFreq(tSimpleLivingString* const pl, float freq) | |
| 403 | −{ | |
| 404 | − _tSimpleLivingString* p = *pl; | |
| 405 | − | |
| 406 | − if (freq<20) freq=20; | |
| 407 | − else if (freq>10000) freq=10000; | |
| 408 | − p->waveLengthInSamples = leaf.sampleRate/freq; | |
| 409 | − tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples); | |
| 410 | −} | |
| 411 | − | |
| 412 | −void tSimpleLivingString_setWaveLength(tSimpleLivingString* const pl, float waveLength) | |
| 413 | −{ | |
| 414 | − _tSimpleLivingString* p = *pl; | |
| 415 | − | |
| 416 | − if (waveLength<4.8) waveLength=4.8; | |
| 417 | − else if (waveLength>2400) waveLength=2400; | |
| 418 | − p->waveLengthInSamples = waveLength; | |
| 419 | − tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples); | |
| 420 | −} | |
| 421 | − | |
| 422 | −void tSimpleLivingString_setDampFreq(tSimpleLivingString* const pl, float dampFreq) | |
| 423 | −{ | |
| 424 | − _tSimpleLivingString* p = *pl; | |
| 425 | − tOnePole_setFreq(&p->bridgeFilter, dampFreq); | |
| 426 | −} | |
| 427 | − | |
| 428 | −void tSimpleLivingString_setDecay(tSimpleLivingString* const pl, float decay) | |
| 429 | −{ | |
| 430 | − _tSimpleLivingString* p = *pl; | |
| 431 | − p->decay=decay; | |
| 432 | −} | |
| 433 | − | |
| 434 | −void tSimpleLivingString_setTargetLev(tSimpleLivingString* const pl, float targetLev) | |
| 435 | −{ | |
| 436 | − _tSimpleLivingString* p = *pl; | |
| 437 | − tFeedbackLeveler_setTargetLevel(&p->fbLev, targetLev); | |
| 438 | −} | |
| 439 | − | |
| 440 | −void tSimpleLivingString_setLevSmoothFactor(tSimpleLivingString* const pl, float levSmoothFactor) | |
| 441 | −{ | |
| 442 | − _tSimpleLivingString* p = *pl; | |
| 443 | − tFeedbackLeveler_setFactor(&p->fbLev, levSmoothFactor); | |
| 444 | −} | |
| 445 | − | |
| 446 | −void tSimpleLivingString_setLevStrength(tSimpleLivingString* const pl, float levStrength) | |
| 447 | −{ | |
| 448 | − _tSimpleLivingString* p = *pl; | |
| 449 | − tFeedbackLeveler_setStrength(&p->fbLev, levStrength); | |
| 450 | −} | |
| 451 | − | |
| 452 | −void tSimpleLivingString_setLevMode(tSimpleLivingString* const pl, int levMode) | |
| 453 | −{ | |
| 454 | − _tSimpleLivingString* p = *pl; | |
| 455 | − tFeedbackLeveler_setMode(&p->fbLev, levMode); | |
| 456 | − p->levMode=levMode; | |
| 457 | −} | |
| 458 | − | |
| 459 | −float tSimpleLivingString_tick(tSimpleLivingString* const pl, float input) | |
| 460 | −{ | |
| 461 | − _tSimpleLivingString* p = *pl; | |
| 462 | − | |
| 463 | − float stringOut=tOnePole_tick(&p->bridgeFilter,tLinearDelay_tickOut(&p->delayLine)); | |
| 464 | − float stringInput=tHighpass_tick(&p->DCblocker, tFeedbackLeveler_tick(&p->fbLev, (p->levMode==0?p->decay*stringOut:stringOut)+input)); | |
| 465 | − tLinearDelay_tickIn(&p->delayLine, stringInput); | |
| 466 | − tLinearDelay_setDelay(&p->delayLine, tExpSmooth_tick(&p->wlSmooth)); | |
| 467 | − p->curr = stringOut; | |
| 468 | − return p->curr; | |
| 469 | −} | |
| 470 | − | |
| 471 | −float tSimpleLivingString_sample(tSimpleLivingString* const pl) | |
| 472 | −{ | |
| 473 | − _tSimpleLivingString* p = *pl; | |
| 474 | − return p->curr; | |
| 475 | −} | |
| 476 | − | |
| 477 | −/* Living String*/ | |
| 478 | − | |
| 479 | −void tLivingString_init(tLivingString* const pl, float freq, float pickPos, float prepIndex, | |
| 480 | − float dampFreq, float decay, float targetLev, float levSmoothFactor, | |
| 481 | − float levStrength, int levMode) | |
| 482 | −{ | |
| 483 | − tLivingString_initToPool(pl, freq, pickPos, prepIndex, dampFreq, decay, targetLev, levSmoothFactor, levStrength, levMode, &leaf.mempool); | |
| 484 | −} | |
| 485 | − | |
| 486 | −void tLivingString_free(tLivingString* const pl) | |
| 487 | −{ | |
| 488 | − tLivingString_freeFromPool(pl, &leaf.mempool); | |
| 489 | −} | |
| 490 | − | |
| 491 | −void tLivingString_initToPool (tLivingString* const pl, float freq, float pickPos, float prepIndex, | |
| 492 | − float dampFreq, float decay, float targetLev, float levSmoothFactor, | |
| 493 | − float levStrength, int levMode, tMempool* const mp) | |
| 494 | −{ | |
| 495 | − _tMempool* m = *mp; | |
| 496 | − _tLivingString* p = *pl = (_tLivingString*) mpool_alloc(sizeof(_tLivingString), m); | |
| 497 | − | |
| 498 | − p->curr=0.0f; | |
| 499 | − tExpSmooth_initToPool(&p->wlSmooth, leaf.sampleRate/freq, 0.01, mp); // smoother for string wavelength (not freq, to avoid expensive divisions) | |
| 500 | − tLivingString_setFreq(pl, freq); | |
| 501 | − p->freq = freq; | |
| 502 | − tExpSmooth_initToPool(&p->ppSmooth, pickPos, 0.01, mp); // smoother for pick position | |
| 503 | − tLivingString_setPickPos(pl, pickPos); | |
| 504 | − p->prepIndex=prepIndex; | |
| 505 | − tLinearDelay_initToPool(&p->delLF,p->waveLengthInSamples, 2400, mp); | |
| 506 | − tLinearDelay_initToPool(&p->delUF,p->waveLengthInSamples, 2400, mp); | |
| 507 | − tLinearDelay_initToPool(&p->delUB,p->waveLengthInSamples, 2400, mp); | |
| 508 | − tLinearDelay_initToPool(&p->delLB,p->waveLengthInSamples, 2400, mp); | |
| 509 | − tLinearDelay_clear(&p->delLF); | |
| 510 | − tLinearDelay_clear(&p->delUF); | |
| 511 | − tLinearDelay_clear(&p->delUB); | |
| 512 | − tLinearDelay_clear(&p->delLB); | |
| 513 | − p->dampFreq = dampFreq; | |
| 514 | − tOnePole_initToPool(&p->bridgeFilter, dampFreq, mp); | |
| 515 | − tOnePole_initToPool(&p->nutFilter, dampFreq, mp); | |
| 516 | − tOnePole_initToPool(&p->prepFilterU, dampFreq, mp); | |
| 517 | − tOnePole_initToPool(&p->prepFilterL, dampFreq, mp); | |
| 518 | − tHighpass_initToPool(&p->DCblockerU,13, mp); | |
| 519 | − tHighpass_initToPool(&p->DCblockerL,13, mp); | |
| 520 | − p->decay=decay; | |
| 521 | − p->prepIndex = prepIndex; | |
| 522 | − tFeedbackLeveler_initToPool(&p->fbLevU, targetLev, levSmoothFactor, levStrength, levMode, mp); | |
| 523 | − tFeedbackLeveler_initToPool(&p->fbLevL, targetLev, levSmoothFactor, levStrength, levMode, mp); | |
| 524 | − p->levMode=levMode; | |
| 525 | −} | |
| 526 | − | |
| 527 | −void tLivingString_freeFromPool (tLivingString* const pl, tMempool* const mp) | |
| 528 | −{ | |
| 529 | − _tMempool* m = *mp; | |
| 530 | − _tLivingString* p = *pl; | |
| 531 | − | |
| 532 | − tExpSmooth_freeFromPool(&p->wlSmooth, mp); | |
| 533 | − tExpSmooth_freeFromPool(&p->ppSmooth, mp); | |
| 534 | − tLinearDelay_freeFromPool(&p->delLF, mp); | |
| 535 | − tLinearDelay_freeFromPool(&p->delUF, mp); | |
| 536 | − tLinearDelay_freeFromPool(&p->delUB, mp); | |
| 537 | − tLinearDelay_freeFromPool(&p->delLB, mp); | |
| 538 | − tOnePole_freeFromPool(&p->bridgeFilter, mp); | |
| 539 | − tOnePole_freeFromPool(&p->nutFilter, mp); | |
| 540 | − tOnePole_freeFromPool(&p->prepFilterU, mp); | |
| 541 | − tOnePole_freeFromPool(&p->prepFilterL, mp); | |
| 542 | − tHighpass_freeFromPool(&p->DCblockerU, mp); | |
| 543 | − tHighpass_freeFromPool(&p->DCblockerL, mp); | |
| 544 | − tFeedbackLeveler_freeFromPool(&p->fbLevU, mp); | |
| 545 | − tFeedbackLeveler_freeFromPool(&p->fbLevL, mp); | |
| 546 | − | |
| 547 | − mpool_free((char*)p, m); | |
| 548 | −} | |
| 549 | − | |
| 550 | −void tLivingString_setFreq(tLivingString* const pl, float freq) | |
| 551 | −{ // NOTE: It is faster to set wavelength in samples directly | |
| 552 | − _tLivingString* p = *pl; | |
| 553 | − if (freq<20) freq=20; | |
| 554 | − else if (freq>10000) freq=10000; | |
| 555 | − p->waveLengthInSamples = leaf.sampleRate/freq; | |
| 556 | − tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples); | |
| 557 | −} | |
| 558 | − | |
| 559 | −void tLivingString_setWaveLength(tLivingString* const pl, float waveLength) | |
| 560 | −{ | |
| 561 | − _tLivingString* p = *pl; | |
| 562 | − if (waveLength<4.8) waveLength=4.8; | |
| 563 | − else if (waveLength>2400) waveLength=2400; | |
| 564 | − p->waveLengthInSamples = waveLength; | |
| 565 | − tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples); | |
| 566 | −} | |
| 567 | − | |
| 568 | −void tLivingString_setPickPos(tLivingString* const pl, float pickPos) | |
| 569 | −{ // between 0 and 1 | |
| 570 | − _tLivingString* p = *pl; | |
| 571 | − if (pickPos<0.f) pickPos=0.f; | |
| 572 | − else if (pickPos>1.f) pickPos=1.f; | |
| 573 | − p->pickPos = pickPos; | |
| 574 | − tExpSmooth_setDest(&p->ppSmooth, p->pickPos); | |
| 575 | −} | |
| 576 | − | |
| 577 | −void tLivingString_setPrepIndex(tLivingString* const pl, float prepIndex) | |
| 578 | −{ // between 0 and 1 | |
| 579 | − _tLivingString* p = *pl; | |
| 580 | − if (prepIndex<0.f) prepIndex=0.f; | |
| 581 | − else if (prepIndex>1.f) prepIndex=1.f; | |
| 582 | − p->prepIndex = prepIndex; | |
| 583 | −} | |
| 584 | − | |
| 585 | −void tLivingString_setDampFreq(tLivingString* const pl, float dampFreq) | |
| 586 | −{ | |
| 587 | − _tLivingString* p = *pl; | |
| 588 | − tOnePole_setFreq(&p->bridgeFilter, dampFreq); | |
| 589 | − tOnePole_setFreq(&p->nutFilter, dampFreq); | |
| 590 | − tOnePole_setFreq(&p->prepFilterU, dampFreq); | |
| 591 | − tOnePole_setFreq(&p->prepFilterL, dampFreq); | |
| 592 | −} | |
| 593 | − | |
| 594 | −void tLivingString_setDecay(tLivingString* const pl, float decay) | |
| 595 | −{ | |
| 596 | − _tLivingString* p = *pl; | |
| 597 | − p->decay=decay; | |
| 598 | −} | |
| 599 | − | |
| 600 | −void tLivingString_setTargetLev(tLivingString* const pl, float targetLev) | |
| 601 | −{ | |
| 602 | − _tLivingString* p = *pl; | |
| 603 | − tFeedbackLeveler_setTargetLevel(&p->fbLevU, targetLev); | |
| 604 | − tFeedbackLeveler_setTargetLevel(&p->fbLevL, targetLev); | |
| 605 | −} | |
| 606 | − | |
| 607 | −void tLivingString_setLevSmoothFactor(tLivingString* const pl, float levSmoothFactor) | |
| 608 | −{ | |
| 609 | − _tLivingString* p = *pl; | |
| 610 | − tFeedbackLeveler_setFactor(&p->fbLevU, levSmoothFactor); | |
| 611 | − tFeedbackLeveler_setFactor(&p->fbLevL, levSmoothFactor); | |
| 612 | −} | |
| 613 | − | |
| 614 | −void tLivingString_setLevStrength(tLivingString* const pl, float levStrength) | |
| 615 | −{ | |
| 616 | − _tLivingString* p = *pl; | |
| 617 | − tFeedbackLeveler_setStrength(&p->fbLevU, levStrength); | |
| 618 | − tFeedbackLeveler_setStrength(&p->fbLevL, levStrength); | |
| 619 | −} | |
| 620 | − | |
| 621 | −void tLivingString_setLevMode(tLivingString* const pl, int levMode) | |
| 622 | −{ | |
| 623 | − _tLivingString* p = *pl; | |
| 624 | − tFeedbackLeveler_setMode(&p->fbLevU, levMode); | |
| 625 | − tFeedbackLeveler_setMode(&p->fbLevL, levMode); | |
| 626 | − p->levMode=levMode; | |
| 627 | −} | |
| 628 | − | |
| 629 | −float tLivingString_tick(tLivingString* const pl, float input) | |
| 630 | −{ | |
| 631 | − _tLivingString* p = *pl; | |
| 632 | − | |
| 633 | − // from pickPos upwards=forwards | |
| 634 | − float fromLF=tLinearDelay_tickOut(&p->delLF); | |
| 635 | − float fromUF=tLinearDelay_tickOut(&p->delUF); | |
| 636 | − float fromUB=tLinearDelay_tickOut(&p->delUB); | |
| 637 | − float fromLB=tLinearDelay_tickOut(&p->delLB); | |
| 638 | − // into upper half of string, from nut, going backwards | |
| 639 | − float fromNut=-tFeedbackLeveler_tick(&p->fbLevU, (p->levMode==0?p->decay:1)*tHighpass_tick(&p->DCblockerU, tOnePole_tick(&p->nutFilter, fromUF))); | |
| 640 | − tLinearDelay_tickIn(&p->delUB, fromNut); | |
| 641 | − // into lower half of string, from pickpoint, going backwards | |
| 642 | − float fromLowerPrep=-tOnePole_tick(&p->prepFilterL, fromLF); | |
| 643 | − float intoLower=p->prepIndex*fromLowerPrep+(1.0f - p->prepIndex)*fromUB+input; | |
| 644 | − tLinearDelay_tickIn(&p->delLB, intoLower); | |
| 645 | − // into lower half of string, from bridge | |
| 646 | − float fromBridge=-tFeedbackLeveler_tick(&p->fbLevL, (p->levMode==0?p->decay:1.0f)*tHighpass_tick(&p->DCblockerL, tOnePole_tick(&p->bridgeFilter, fromLB))); | |
| 647 | − tLinearDelay_tickIn(&p->delLF, fromBridge); | |
| 648 | − // into upper half of string, from pickpoint, going forwards/upwards | |
| 649 | − float fromUpperPrep=-tOnePole_tick(&p->prepFilterU, fromUB); | |
| 650 | − float intoUpper=p->prepIndex*fromUpperPrep+(1.0f - p->prepIndex)*fromLF+input; | |
| 651 | − tLinearDelay_tickIn(&p->delUF, intoUpper); | |
| 652 | − // update all delay lengths | |
| 653 | − float pickP=tExpSmooth_tick(&p->ppSmooth); | |
| 654 | − float wLen=tExpSmooth_tick(&p->wlSmooth); | |
| 655 | − float lowLen=pickP*wLen; | |
| 656 | − float upLen=(1.0f-pickP)*wLen; | |
| 657 | − tLinearDelay_setDelay(&p->delLF, lowLen); | |
| 658 | − tLinearDelay_setDelay(&p->delLB, lowLen); | |
| 659 | − tLinearDelay_setDelay(&p->delUF, upLen); | |
| 660 | − tLinearDelay_setDelay(&p->delUB, upLen); | |
| 661 | − p->curr = fromBridge; | |
| 662 | − return p->curr; | |
| 663 | −} | |
| 664 | − | |
| 665 | −float tLivingString_sample(tLivingString* const pl) | |
| 666 | −{ | |
| 667 | − _tLivingString* p = *pl; | |
| 668 | − return p->curr; | |
| 669 | −} | |
| 670 | − | |
| 671 | −///Reed Table model | |
| 672 | −//default values from STK are 0.6 offset and -0.8 slope | |
| 673 | − | |
| 674 | −void tReedTable_init (tReedTable* const pm, float offset, float slope) | |
| 675 | −{ | |
| 676 | − _tReedTable* p = *pm = (_tReedTable*) leaf_alloc(sizeof(_tReedTable)); | |
| 677 | − | |
| 678 | − p->offset = offset; | |
| 679 | − p->slope = slope; | |
| 680 | −} | |
| 681 | − | |
| 682 | −void tReedTable_free (tReedTable* const pm) | |
| 683 | −{ | |
| 684 | − _tReedTable* p = *pm; | |
| 685 | − | |
| 686 | − leaf_free((char*)p); | |
| 687 | −} | |
| 688 | − | |
| 689 | −void tReedTable_initToPool (tReedTable* const pm, float offset, float slope, tMempool* const mp) | |
| 690 | −{ | |
| 691 | − _tMempool* m = *mp; | |
| 692 | − _tReedTable* p = *pm = (_tReedTable*) mpool_alloc(sizeof(_tReedTable), m); | |
| 693 | − | |
| 694 | − p->offset = offset; | |
| 695 | − p->slope = slope; | |
| 696 | −} | |
| 697 | − | |
| 698 | −void tReedTable_freeFromPool (tReedTable* const pm, tMempool* const mp) | |
| 699 | −{ | |
| 700 | − _tMempool* m = *mp; | |
| 701 | − _tReedTable* p = *pm; | |
| 702 | − | |
| 703 | − mpool_free((char*)p, m); | |
| 704 | −} | |
| 705 | − | |
| 706 | −float tReedTable_tick (tReedTable* const pm, float input) | |
| 707 | −{ | |
| 708 | − _tReedTable* p = *pm; | |
| 709 | − | |
| 710 | − // The input is differential pressure across the reed. | |
| 711 | − float output = p->offset + (p->slope * input); | |
| 712 | − | |
| 713 | − // If output is > 1, the reed has slammed shut and the | |
| 714 | − // reflection function value saturates at 1.0. | |
| 715 | − if ( output > 1.0f) output = 1.0f; | |
| 716 | − | |
| 717 | − // This is nearly impossible in a physical system, but | |
| 718 | − // a reflection function value of -1.0 corresponds to | |
| 719 | − // an open end (and no discontinuity in bore profile). | |
| 720 | − if ( output < -1.0f) output = -1.0f; | |
| 721 | − | |
| 722 | − return output; | |
| 723 | −} | |
| 724 | − | |
| 725 | −float tReedTable_tanh_tick (tReedTable* const pm, float input) | |
| 726 | −{ | |
| 727 | − _tReedTable* p = *pm; | |
| 728 | − | |
| 729 | − // The input is differential pressure across the reed. | |
| 730 | − float output = p->offset + (p->slope * input); | |
| 731 | − | |
| 732 | − // If output is > 1, the reed has slammed shut and the | |
| 733 | − // reflection function value saturates at 1.0. | |
| 734 | − return tanhf(output); | |
| 735 | −} | |
| 736 | − | |
| 737 | −void tReedTable_setOffset (tReedTable* const pm, float offset) | |
| 738 | −{ | |
| 739 | − _tReedTable* p = *pm; | |
| 740 | − p->offset = offset; | |
| 741 | −} | |
| 742 | − | |
| 743 | −void tReedTable_setSlope (tReedTable* const pm, float slope) | |
| 744 | −{ | |
| 745 | − _tReedTable* p = *pm; | |
| 746 | − p->slope = slope; | |
| 747 | −} | |
| @@ -1,925 +0,0 @@ | ||
| 1 | −/*============================================================================== | |
| 2 | − | |
| 3 | − leaf-reverb.c | |
| 4 | − Created: 20 Jan 2017 12:02:04pm | |
| 5 | − Author: Michael R Mulshine | |
| 6 | − | |
| 7 | −==============================================================================*/ | |
| 8 | − | |
| 9 | −#if _WIN32 || _WIN64 | |
| 10 | − | |
| 11 | −#include "..\Inc\leaf-reverb.h" | |
| 12 | −#include "..\leaf.h" | |
| 13 | − | |
| 14 | −#else | |
| 15 | − | |
| 16 | −#include "../Inc/leaf-reverb.h" | |
| 17 | −#include "../leaf.h" | |
| 18 | − | |
| 19 | −#endif | |
| 20 | − | |
| 21 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PRCReverb ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 22 | −void tPRCReverb_init(tPRCReverb* const rev, float t60) | |
| 23 | −{ | |
| 24 | − _tPRCReverb* r = *rev = (_tPRCReverb*) leaf_alloc(sizeof(_tPRCReverb)); | |
| 25 | − | |
| 26 | − if (t60 <= 0.0f) t60 = 0.001f; | |
| 27 | − | |
| 28 | − r->inv_441 = 1.0f/44100.0f; | |
| 29 | − | |
| 30 | − int lengths[4] = { 341, 613, 1557, 2137 }; // Delay lengths for 44100 Hz sample rate. | |
| 31 | − double scaler = leaf.sampleRate * r->inv_441; | |
| 32 | − | |
| 33 | − int delay, i; | |
| 34 | − if (scaler != 1.0f) | |
| 35 | − { | |
| 36 | − for (i=0; i<4; i++) | |
| 37 | − { | |
| 38 | − delay = (int) scaler * lengths[i]; | |
| 39 | − | |
| 40 | − if ( (delay & 1) == 0) delay++; | |
| 41 | − | |
| 42 | − while ( !LEAF_isPrime(delay) ) delay += 2; | |
| 43 | − | |
| 44 | − lengths[i] = delay; | |
| 45 | − } | |
| 46 | − } | |
| 47 | − | |
| 48 | − tDelay_init(&r->allpassDelays[0], lengths[0], lengths[0] * 2); | |
| 49 | − tDelay_init(&r->allpassDelays[1], lengths[1], lengths[1] * 2); | |
| 50 | − tDelay_init(&r->combDelay, lengths[2], lengths[2] * 2); | |
| 51 | − | |
| 52 | − tPRCReverb_setT60(rev, t60); | |
| 53 | − | |
| 54 | − r->allpassCoeff = 0.7f; | |
| 55 | − r->mix = 0.5f; | |
| 56 | −} | |
| 57 | − | |
| 58 | −void tPRCReverb_free(tPRCReverb* const rev) | |
| 59 | −{ | |
| 60 | − _tPRCReverb* r = *rev; | |
| 61 | − | |
| 62 | − tDelay_free(&r->allpassDelays[0]); | |
| 63 | − tDelay_free(&r->allpassDelays[1]); | |
| 64 | − tDelay_free(&r->combDelay); | |
| 65 | − leaf_free((char*)r); | |
| 66 | −} | |
| 67 | − | |
| 68 | −void tPRCReverb_initToPool (tPRCReverb* const rev, float t60, tMempool* const mp) | |
| 69 | −{ | |
| 70 | − _tMempool* m = *mp; | |
| 71 | − _tPRCReverb* r = *rev = (_tPRCReverb*) mpool_alloc(sizeof(_tPRCReverb), m); | |
| 72 | − | |
| 73 | − if (t60 <= 0.0f) t60 = 0.001f; | |
| 74 | − | |
| 75 | − r->inv_441 = 1.0f/44100.0f; | |
| 76 | − | |
| 77 | − int lengths[4] = { 341, 613, 1557, 2137 }; // Delay lengths for 44100 Hz sample rate. | |
| 78 | − double scaler = leaf.sampleRate * r->inv_441; | |
| 79 | − | |
| 80 | − int delay, i; | |
| 81 | − if (scaler != 1.0f) | |
| 82 | − { | |
| 83 | − for (i=0; i<4; i++) | |
| 84 | − { | |
| 85 | − delay = (int) scaler * lengths[i]; | |
| 86 | − | |
| 87 | − if ( (delay & 1) == 0) delay++; | |
| 88 | − | |
| 89 | − while ( !LEAF_isPrime(delay) ) delay += 2; | |
| 90 | − | |
| 91 | − lengths[i] = delay; | |
| 92 | − } | |
| 93 | − } | |
| 94 | − | |
| 95 | − tDelay_initToPool(&r->allpassDelays[0], lengths[0], lengths[0] * 2, mp); | |
| 96 | − tDelay_initToPool(&r->allpassDelays[1], lengths[1], lengths[1] * 2, mp); | |
| 97 | − tDelay_initToPool(&r->combDelay, lengths[2], lengths[2] * 2, mp); | |
| 98 | − | |
| 99 | − tPRCReverb_setT60(rev, t60); | |
| 100 | − | |
| 101 | − r->allpassCoeff = 0.7f; | |
| 102 | − r->mix = 0.5f; | |
| 103 | −} | |
| 104 | − | |
| 105 | −void tPRCReverb_freeFromPool (tPRCReverb* const rev, tMempool* const mp) | |
| 106 | −{ | |
| 107 | − _tMempool* m = *mp; | |
| 108 | − _tPRCReverb* r = *rev; | |
| 109 | − | |
| 110 | − tDelay_freeFromPool(&r->allpassDelays[0], mp); | |
| 111 | − tDelay_freeFromPool(&r->allpassDelays[1], mp); | |
| 112 | − tDelay_freeFromPool(&r->combDelay, mp); | |
| 113 | − mpool_free((char*)r, m); | |
| 114 | −} | |
| 115 | − | |
| 116 | −void tPRCRevert_clear(tPRCReverb* const rev) | |
| 117 | −{ | |
| 118 | − _tPRCReverb* r = *rev; | |
| 119 | − | |
| 120 | − tDelay_clear(&r->allpassDelays[0]); | |
| 121 | − tDelay_clear(&r->allpassDelays[1]); | |
| 122 | − tDelay_clear(&r->combDelay); | |
| 123 | −} | |
| 124 | − | |
| 125 | −void tPRCReverb_setT60(tPRCReverb* const rev, float t60) | |
| 126 | −{ | |
| 127 | − _tPRCReverb* r = *rev; | |
| 128 | − | |
| 129 | − if ( t60 <= 0.0f ) t60 = 0.001f; | |
| 130 | − | |
| 131 | − r->t60 = t60; | |
| 132 | − | |
| 133 | − r->combCoeff = pow(10.0f, (-3.0f * tDelay_getDelay(&r->combDelay) * leaf.invSampleRate / t60 )); | |
| 134 | − | |
| 135 | −} | |
| 136 | − | |
| 137 | −void tPRCReverb_setMix(tPRCReverb* const rev, float mix) | |
| 138 | −{ | |
| 139 | − _tPRCReverb* r = *rev; | |
| 140 | − r->mix = mix; | |
| 141 | −} | |
| 142 | − | |
| 143 | −float tPRCReverb_tick(tPRCReverb* const rev, float input) | |
| 144 | −{ | |
| 145 | − _tPRCReverb* r = *rev; | |
| 146 | − | |
| 147 | − float temp, temp0, temp1, temp2; | |
| 148 | − float out; | |
| 149 | − | |
| 150 | − r->lastIn = input; | |
| 151 | − | |
| 152 | − temp = tDelay_getLastOut(&r->allpassDelays[0]); | |
| 153 | − temp0 = r->allpassCoeff * temp; | |
| 154 | − temp0 += input; | |
| 155 | − tDelay_tick(&r->allpassDelays[0], temp0); | |
| 156 | − temp0 = -( r->allpassCoeff * temp0) + temp; | |
| 157 | − | |
| 158 | − temp = tDelay_getLastOut(&r->allpassDelays[1]); | |
| 159 | − temp1 = r->allpassCoeff * temp; | |
| 160 | − temp1 += temp0; | |
| 161 | − tDelay_tick(&r->allpassDelays[1], temp1); | |
| 162 | − temp1 = -(r->allpassCoeff * temp1) + temp; | |
| 163 | − | |
| 164 | − temp2 = temp1 + ( r->combCoeff * tDelay_getLastOut(&r->combDelay)); | |
| 165 | − | |
| 166 | − out = r->mix * tDelay_tick(&r->combDelay, temp2); | |
| 167 | − | |
| 168 | − temp = (1.0f - r->mix) * input; | |
| 169 | − | |
| 170 | − out += temp; | |
| 171 | − | |
| 172 | − r->lastOut = out; | |
| 173 | − | |
| 174 | − return out; | |
| 175 | −} | |
| 176 | − | |
| 177 | −void tPRCReverbSampleRateChanged (tPRCReverb* const rev) | |
| 178 | −{ | |
| 179 | − _tPRCReverb* r = *rev; | |
| 180 | − r->combCoeff = pow(10.0f, (-3.0f * tDelay_getDelay(&r->combDelay) * leaf.invSampleRate / r->t60 )); | |
| 181 | −} | |
| 182 | − | |
| 183 | −/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ NReverb ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */ | |
| 184 | −void tNReverb_init(tNReverb* const rev, float t60) | |
| 185 | −{ | |
| 186 | − _tNReverb* r = *rev = (_tNReverb*) leaf_alloc(sizeof(_tNReverb)); | |
| 187 | − | |
| 188 | − if (t60 <= 0.0f) t60 = 0.001f; | |
| 189 | − | |
| 190 | − r->inv_441 = 1.0f/44100.0f; | |
| 191 | − | |
| 192 | − int lengths[15] = {1433, 1601, 1867, 2053, 2251, 2399, 347, 113, 37, 59, 53, 43, 37, 29, 19}; // Delay lengths for 44100 Hz sample rate. | |
| 193 | − double scaler = leaf.sampleRate / 25641.0f; | |
| 194 | − | |
| 195 | − int delay, i; | |
| 196 | − | |
| 197 | − for (i=0; i < 15; i++) | |
| 198 | − { | |
| 199 | − delay = (int) scaler * lengths[i]; | |
| 200 | − if ( (delay & 1) == 0) | |
| 201 | − delay++; | |
| 202 | − while ( !LEAF_isPrime(delay) ) | |
| 203 | − delay += 2; | |
| 204 | − lengths[i] = delay; | |
| 205 | − } | |
| 206 | − | |
| 207 | − for ( i=0; i<6; i++ ) | |
| 208 | − { | |
| 209 | − tLinearDelay_init(&r->combDelays[i], lengths[i], lengths[i] * 2.0f); | |
| 210 | − tLinearDelay_clear(&r->combDelays[i]); | |
| 211 | − r->combCoeffs[i] = pow(10.0, (-3 * lengths[i] * leaf.invSampleRate / t60)); | |
| 212 | − } | |
| 213 | − | |
| 214 | − for ( i=0; i<8; i++ ) | |
| 215 | − { | |
| 216 | − tLinearDelay_init(&r->allpassDelays[i], lengths[i+6], lengths[i+6] * 2.0f); | |
| 217 | − tLinearDelay_clear(&r->allpassDelays[i]); | |
| 218 | − } | |
| 219 | − | |
| 220 | − | |
| 221 | − tNReverb_setT60(rev, t60); | |
| 222 | − r->allpassCoeff = 0.7f; | |
| 223 | − r->mix = 0.3f; | |
| 224 | −} | |
| 225 | − | |
| 226 | −void tNReverb_free(tNReverb* const rev) | |
| 227 | −{ | |
| 228 | − _tNReverb* r = *rev; | |
| 229 | − | |
| 230 | − for (int i = 0; i < 6; i++) | |
| 231 | − { | |
| 232 | − tLinearDelay_free(&r->combDelays[i]); | |
| 233 | − } | |
| 234 | − | |
| 235 | − for (int i = 0; i < 8; i++) | |
| 236 | − { | |
| 237 | − tLinearDelay_free(&r->allpassDelays[i]); | |
| 238 | − } | |
| 239 | − | |
| 240 | − leaf_free((char*)r); | |
| 241 | −} | |
| 242 | − | |
| 243 | −void tNReverb_initToPool (tNReverb* const rev, float t60, tMempool* const mp) | |
| 244 | −{ | |
| 245 | − _tMempool* m = *mp; | |
| 246 | − _tNReverb* r = *rev = (_tNReverb*) mpool_alloc(sizeof(_tNReverb), m); | |
| 247 | − | |
| 248 | − if (t60 <= 0.0f) t60 = 0.001f; | |
| 249 | − | |
| 250 | − r->inv_441 = 1.0f/44100.0f; | |
| 251 | − | |
| 252 | − int lengths[15] = {1433, 1601, 1867, 2053, 2251, 2399, 347, 113, 37, 59, 53, 43, 37, 29, 19}; // Delay lengths for 44100 Hz sample rate. | |
673 more lines aren’t shown here.
This diff is large: its 867 lines aren’t shown here.
This diff is large: its 14062 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 155 lines aren’t shown here.
Binary file not shown.
This diff is large: its 126 lines aren’t shown here.
Binary file not shown.
This diff is large: its 9 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 9 lines aren’t shown here.