History

fixing file organization

Matthew Wang committed 6 years ago

Commit 5dc1c251 parent cf5c3f252 files · +54 −35876Browse files

Unified · Split

52 files
  1. .DS_Store +0 −0
  2. LEAF/.DS_Store +0 −0
  3. LEAF/.gitignore +0 −11
  4. LEAF/Externals/.DS_Store +0 −0
  5. LEAF/Externals/d_fft_mayer.c +0 −423
  6. LEAF/Externals/d_fft_mayer.h +0 −31
  7. LEAF/Externals/trigtbl.h +0 −173
  8. LEAF/Inc/leaf-analysis.h +0 −296
  9. LEAF/Inc/leaf-delay.h +0 −229
  10. LEAF/Inc/leaf-distortion.h +0 −164
  11. LEAF/Inc/leaf-dynamics.h +0 −122
  12. LEAF/Inc/leaf-effects.h +0 −360
  13. LEAF/Inc/leaf-electrical.h +0 −103
  14. LEAF/Inc/leaf-envelopes.h +0 −366
  15. LEAF/Inc/leaf-filters.h +0 −486
  16. LEAF/Inc/leaf-global.h +0 −52
  17. LEAF/Inc/leaf-instruments.h +0 −209
  18. LEAF/Inc/leaf-math.h +0 −212
  19. LEAF/Inc/leaf-mempool.h +0 −159
  20. LEAF/Inc/leaf-midi.h +0 −510
  21. LEAF/Inc/leaf-oscillators.h +0 −1143
  22. LEAF/Inc/leaf-physical.h +0 −259
  23. LEAF/Inc/leaf-reverb.h +0 −175
  24. LEAF/Inc/leaf-sampling.h +0 −188
  25. LEAF/Inc/leaf-tables.h +0 −104
  26. LEAF/Src/leaf-analysis.c +0 −1054
  27. LEAF/Src/leaf-delay.c +0 −928
  28. LEAF/Src/leaf-distortion.c +0 −695
  29. LEAF/Src/leaf-dynamics.c +0 −281
  30. LEAF/Src/leaf-effects.c +0 −1853
  31. LEAF/Src/leaf-electrical.c +0 −551
  32. LEAF/Src/leaf-envelopes.c +0 −1612
  33. LEAF/Src/leaf-filters.c +0 −1802
  34. LEAF/Src/leaf-instruments.c +0 −706
  35. LEAF/Src/leaf-math.c +0 −655
  36. LEAF/Src/leaf-mempool.c +0 −412
  37. LEAF/Src/leaf-midi.c +0 −980
  38. LEAF/Src/leaf-oscillators.c +0 −1660
  39. LEAF/Src/leaf-physical.c +0 −747
  40. LEAF/Src/leaf-reverb.c +0 −925
  41. LEAF/Src/leaf-sampling.c +0 −866
  42. LEAF/Src/leaf-tables.c +0 −14061
  43. LEAF/Src/leaf.c +0 −60
  44. LEAF/leaf.cpp +0 −45
  45. LEAF/leaf.h +0 −154
  46. LEAF_JUCEPlugin/.DS_Store +0 −0
  47. LEAF_JUCEPlugin/LEAF.jucer +59 −59
  48. LEAF_JUCEPlugin/Source/.DS_Store +0 −0
  49. LEAF_JUCEPlugin/Source/LEAFTest.h +1 −1
  50. leaf/.DS_Store +0 −0
  51. leaf/Externals/.DS_Store +0 −0
  52. leaf/leaf.h +1 −1
.DS_Store+0−0

Binary file not shown.

LEAF/.DS_Store+0−0

Binary file not shown.

LEAF/.gitignore+0−11
@@ -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
LEAF/Externals/.DS_Store+0−0

Binary file not shown.

LEAF/Externals/d_fft_mayer.c+0−423
@@ -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
120static 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 };
139static 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 };
158static 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 };
177static 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 };
196static 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
220void mayer_fht(REAL *fz, int n)
221{
222/* REAL a,b;
223REAL 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
369void 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
384void 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
399void 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
412void 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}
LEAF/Externals/d_fft_mayer.h+0−31
@@ -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
13extern "C" {
14#endif
15
16typedef float t_sample; /* a float type at most the same size */
17
18#define REAL t_sample
19
20void mayer_fht(REAL *fz, int n);
21void mayer_fft(int n, REAL *real, REAL *imag);
22void mayer_ifft(int n, REAL *real, REAL *imag);
23void mayer_realfft(int n, REAL *real);
24void mayer_realifft(int n, REAL *real);
25
26
27#ifdef __cplusplus
28}
29#endif
30
31#endif /* D_FFT_MAYER_H_ */
LEAF/Externals/trigtbl.h+0−173
@@ -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
11extern "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
75static 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 };
94static 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 };
113static 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 };
132static 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 };
151static 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
LEAF/Inc/leaf-analysis.h+0−296
@@ -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
13extern "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
LEAF/Inc/leaf-delay.h+0−229
@@ -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
13extern "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
LEAF/Inc/leaf-distortion.h+0−164
@@ -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
13extern "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
LEAF/Inc/leaf-dynamics.h+0−122
@@ -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
14extern "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
LEAF/Inc/leaf-effects.h+0−360
@@ -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
13extern "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//==============================================================================
LEAF/Inc/leaf-electrical.h+0−103
@@ -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
12extern "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
LEAF/Inc/leaf-envelopes.h+0−366
@@ -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
15extern "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
LEAF/Inc/leaf-filters.h+0−486
@@ -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
13extern "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
LEAF/Inc/leaf-global.h+0−52
@@ -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
15extern "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
LEAF/Inc/leaf-instruments.h+0−209
@@ -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
13extern "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
LEAF/Inc/leaf-math.h+0−212
@@ -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
13extern "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
LEAF/Inc/leaf-mempool.h+0−159
@@ -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
41extern "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
LEAF/Inc/leaf-midi.h+0−510
@@ -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
13extern "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
LEAF/Inc/leaf-oscillators.h+0−1143
@@ -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
11extern "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
LEAF/Inc/leaf-physical.h+0−259
@@ -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
15extern "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
LEAF/Inc/leaf-reverb.h+0−175
@@ -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
13extern "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
LEAF/Inc/leaf-sampling.h+0−188
@@ -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
14extern "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//==============================================================================
LEAF/Inc/leaf-tables.h+0−104
@@ -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
13extern "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
39extern const float __leaf_table_shaper1[SHAPER1_TABLE_SIZE];
40
41#define COEFFS_SIZE 32
42extern const float* __leaf_tableref_firCoeffs[COEFFS_SIZE];
43extern const float __leaf_tablesize_firNumTaps[COEFFS_SIZE];
44extern const float __leaf_table_fir2XLow[32];
45extern const float __leaf_table_fir4XLow[64];
46extern const float __leaf_table_fir8XLow[64];
47extern const float __leaf_table_fir16XLow[128];
48extern const float __leaf_table_fir32XLow[256];
49extern const float __leaf_table_fir64XLow[256];
50extern const float __leaf_table_fir2XHigh[128];
51extern const float __leaf_table_fir4XHigh[256];
52extern const float __leaf_table_fir8XHigh[256];
53extern const float __leaf_table_fir16XHigh[512];
54extern const float __leaf_table_fir32XHigh[512];
55extern const float __leaf_table_fir64XHigh[1024];
56
57typedef 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
75extern const float __leaf_table_exp_decay[EXP_DECAY_TABLE_SIZE];
76extern const float __leaf_table_attack_decay_inc[ATTACK_DECAY_INC_TABLE_SIZE];
77
78extern const float __leaf_table_filtertan[FILTERTAN_TABLE_SIZE];
79
80extern const float __leaf_table_mtof1[MTOF1_TABLE_SIZE];
81extern const float __leaf_table_decayCoeffTable[DECAY_COEFF_TABLE_SIZE];
82
83extern const float __leaf_table_tanh1[TANH1_TABLE_SIZE];
84
85//==============================================================================
86
87/* Sine wave table ripped from http://aquaticus.info/pwm-sine-wave. */
88extern const float __leaf_table_sinewave[SINE_TABLE_SIZE];
89
90extern const float __leaf_table_sawtooth[11][SAW_TABLE_SIZE];
91
92extern const float __leaf_table_triangle[11][TRI_TABLE_SIZE];
93
94extern 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//==============================================================================
LEAF/Src/leaf-analysis.c+0−1054
@@ -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
25void 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
34void tEnvelopeFollower_free(tEnvelopeFollower* const ef)
35{
36 _tEnvelopeFollower* e = *ef;
37
38 leaf_free((char*)e);
39}
40
41void 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
51void 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
59float 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
76int tEnvelopeFollower_decayCoeff(tEnvelopeFollower* const ef, float decayCoeff)
77{
78 _tEnvelopeFollower* e = *ef;
79 return e->d_coeff = decayCoeff;
80}
81
82int 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
94void tZeroCrossing_init (tZeroCrossing* const zc, int maxWindowSize)
95{
96 tZeroCrossing_initToPool (zc, maxWindowSize, &leaf.mempool);
97}
98void tZeroCrossing_free (tZeroCrossing* const zc)
99{
100 tZeroCrossing_freeFromPool (zc, &leaf.mempool);
101}
102void 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
117void 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)
127float 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
166void 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//===========================================================================
187void 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
196void tPowerFollower_free(tPowerFollower* const pf)
197{
198 _tPowerFollower* p = *pf;
199
200 leaf_free((char*)p);
201}
202
203void 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
213void 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
221int 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
232float 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
239float 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
252void 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
294void tEnvPD_free (tEnvPD* const xpd)
295{
296 _tEnvPD* x = *xpd;
297
298 leaf_free((char*)x);
299}
300
301void 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
344void 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
352float tEnvPD_tick (tEnvPD* const xpd)
353{
354 _tEnvPD* x = *xpd;
355 return powtodb(x->x_result);
356}
357
358void 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**********/
399static void atkdtk_init(tAttackDetection* const a, int blocksize, int atk, int rel);
400static void atkdtk_envelope(tAttackDetection* const a, float *in);
401
402/********Constructor/Destructor***************/
403
404void 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
411void tAttackDetection_free(tAttackDetection* const ad)
412{
413 _tAttackDetection* a = *ad;
414
415 leaf_free((char*)a);
416}
417
418void 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
426void 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
437void 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
449void 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
460void tAttackDetection_setThreshold(tAttackDetection* const ad, float thres)
461{
462 _tAttackDetection* a = *ad;
463 a->threshold = thres;
464}
465
466void 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
473void 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
481int 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
501static 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
517static 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
544static void snac_analyzeframe(tSNAC* const s);
545static void snac_autocorrelation(tSNAC* const s);
546static void snac_normalize(tSNAC* const s);
547static void snac_pickpeak(tSNAC* const s);
548static void snac_periodandfidelity(tSNAC* const s);
549static void snac_biasbuf(tSNAC* const s);
550static float snac_spectralpeak(tSNAC* const s, float periodlength);
551
552
553/******************************************************************************/
554/******************************** constructor, destructor *********************/
555/******************************************************************************/
556
557
558void 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
579void 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
590void 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
612void 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
629void 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
651void 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
659void 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
670void 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
680float tSNAC_getPeriod(tSNAC* const snac)
681{
682 _tSNAC* s = *snac;
683 return(s->periodlength);
684}
685
686
687float 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
700static 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
731static 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
766static 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
805static 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
823static 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
867static 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
913static 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//===========================================================================
936void 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
941void tPeriodDetection_free (tPeriodDetection* const pd)
942{
943 tPeriodDetection_freeFromPool(pd, &leaf.mempool);
944}
945
946void 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
973void 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
983float 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
1019float tPeriodDetection_getPeriod(tPeriodDetection* pd)
1020{
1021 _tPeriodDetection* p = *pd;
1022 return p->period;
1023}
1024
1025void tPeriodDetection_setHopSize(tPeriodDetection* pd, int hs)
1026{
1027 _tPeriodDetection* p = *pd;
1028 p->hopSize = hs;
1029}
1030
1031void tPeriodDetection_setWindowSize(tPeriodDetection* pd, int ws)
1032{
1033 _tPeriodDetection* p = *pd;
1034 p->windowSize = ws;
1035}
1036
1037void tPeriodDetection_setFidelityThreshold(tPeriodDetection* pd, float threshold)
1038{
1039 _tPeriodDetection* p = *pd;
1040 p->fidelityThreshold = threshold;
1041}
1042
1043void tPeriodDetection_setAlpha (tPeriodDetection* pd, float alpha)
1044{
1045 _tPeriodDetection* p = *pd;
1046 p->alpha = LEAF_clip(0.0f, alpha, 1.0f);
1047}
1048
1049void 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}
LEAF/Src/leaf-delay.c+0−928
@@ -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 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
22void tDelay_init (tDelay* const dl, uint32_t delay, uint32_t maxDelay)
23{
24 tDelay_initToPool(dl, delay, maxDelay, &leaf.mempool);
25}
26
27void tDelay_free(tDelay* const dl)
28{
29 tDelay_freeFromPool(dl, &leaf.mempool);
30}
31
32void 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
54void 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
63void 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
72float 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
88int 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
101float 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
114void 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
126float 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
138uint32_t tDelay_getDelay (tDelay* const dl)
139{
140 _tDelay* d = *dl;
141 return d->delay;
142}
143
144float tDelay_getLastOut (tDelay* const dl)
145{
146 _tDelay* d = *dl;
147 return d->lastOut;
148}
149
150float tDelay_getLastIn (tDelay* const dl)
151{
152 _tDelay* d = *dl;
153 return d->lastIn;
154}
155
156void 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
163float tDelay_getGain (tDelay* const dl)
164{
165 _tDelay* d = *dl;
166 return d->gain;
167}
168
169// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ LinearDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
170void tLinearDelay_init (tLinearDelay* const dl, float delay, uint32_t maxDelay)
171{
172 tLinearDelay_initToPool(dl, delay, maxDelay, &leaf.mempool);
173}
174
175void tLinearDelay_free(tLinearDelay* const dl)
176{
177 tLinearDelay_freeFromPool(dl, &leaf.mempool);
178}
179
180void 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
204void 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
213void 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
222float 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
246void 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
256float 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
275int 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
296float 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
307void 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
319float 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
331float tLinearDelay_getDelay (tLinearDelay* const dl)
332{
333 _tLinearDelay* d = *dl;
334 return d->delay;
335}
336
337float tLinearDelay_getLastOut (tLinearDelay* const dl)
338{
339 _tLinearDelay* d = *dl;
340 return d->lastOut;
341}
342
343float tLinearDelay_getLastIn (tLinearDelay* const dl)
344{
345 _tLinearDelay* d = *dl;
346 return d->lastIn;
347}
348
349void 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
356float 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 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
368void tHermiteDelay_init (tHermiteDelay* const dl, float delay, uint32_t maxDelay)
369{
370 tHermiteDelay_initToPool(dl, delay, maxDelay, &leaf.mempool);
371}
372
373void tHermiteDelay_free(tHermiteDelay* const dl)
374{
375 tHermiteDelay_freeFromPool(dl, &leaf.mempool);
376}
377
378void 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
402void 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
412void 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
421float 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
444void 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
454float 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
474int 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
495float 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
508void 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
520float 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
532float tHermiteDelay_getDelay (tHermiteDelay* const dl)
533{
534 _tHermiteDelay* d = *dl;
535 return d->delay;
536}
537
538float tHermiteDelay_getLastOut (tHermiteDelay* const dl)
539{
540 _tHermiteDelay* d = *dl;
541 return d->lastOut;
542}
543
544float tHermiteDelay_getLastIn (tHermiteDelay* const dl)
545{
546 _tHermiteDelay* d = *dl;
547 return d->lastIn;
548}
549
550void 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
557float tHermiteDelay_getGain (tHermiteDelay* const dl)
558{
559 _tHermiteDelay* d = *dl;
560 return d->gain;
561}
562
563
564
565
566
567// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ AllpassDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
568void tAllpassDelay_init (tAllpassDelay* const dl, float delay, uint32_t maxDelay)
569{
570 tAllpassDelay_initToPool(dl, delay, maxDelay, &leaf.mempool);
571}
572
573void tAllpassDelay_free(tAllpassDelay* const dl)
574{
575 tAllpassDelay_freeFromPool(dl, &leaf.mempool);
576}
577
578void 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
604void 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
613void 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
622float 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
645int 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
679float 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
692void 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
704float 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
716float tAllpassDelay_getDelay (tAllpassDelay* const dl)
717{
718 _tAllpassDelay* d = *dl;
719 return d->delay;
720}
721
722float tAllpassDelay_getLastOut (tAllpassDelay* const dl)
723{
724 _tAllpassDelay* d = *dl;
725 return d->lastOut;
726}
727
728float tAllpassDelay_getLastIn (tAllpassDelay* const dl)
729{
730 _tAllpassDelay* d = *dl;
731 return d->lastIn;
732}
733
734void 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
741float tAllpassDelay_getGain (tAllpassDelay* const dl)
742{
743 _tAllpassDelay* d = *dl;
744 return d->gain;
745}
746
747// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TapeDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
748void tTapeDelay_init (tTapeDelay* const dl, float delay, uint32_t maxDelay)
749{
750 tTapeDelay_initToPool(dl, delay, maxDelay, &leaf.mempool);
751}
752
753void tTapeDelay_free(tTapeDelay* const dl)
754{
755 tTapeDelay_freeFromPool(dl, &leaf.mempool);
756}
757
758void 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
779void 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
788void 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
799float 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
831void 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
839void tTapeDelay_setRate(tTapeDelay* const dl, float rate)
840{
841 _tTapeDelay* d = *dl;
842 d->inc = rate;
843}
844
845void tTapeDelay_setDelay (tTapeDelay* const dl, float delay)
846{
847 _tTapeDelay* d = *dl;
848 d->delay = LEAF_clip(1.f, delay, d->maxDelay);
849}
850
851float 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
874void 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
886float 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
898float tTapeDelay_getDelay (tTapeDelay *dl)
899{
900 _tTapeDelay* d = *dl;
901 return d->delay;
902}
903
904float tTapeDelay_getLastOut (tTapeDelay* const dl)
905{
906 _tTapeDelay* d = *dl;
907 return d->lastOut;
908}
909
910float tTapeDelay_getLastIn (tTapeDelay* const dl)
911{
912 _tTapeDelay* d = *dl;
913 return d->lastIn;
914}
915
916void 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
923float tTapeDelay_getGain (tTapeDelay* const dl)
924{
925 _tTapeDelay* d = *dl;
926 return d->gain;
927}
928
LEAF/Src/leaf-distortion.c+0−695
@@ -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
26void 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
35void tSampleReducer_free (tSampleReducer* const sr)
36{
37 _tSampleReducer* s = *sr;
38
39 leaf_free((char*)s);
40}
41
42void 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
52void 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
60float 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
74void 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)
86void 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
105void 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
114void 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
134void 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
144float 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
160void 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
253float 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
337int 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
351void tLockhartWavefolder_init(tLockhartWavefolder* const wf)
352{
353 tLockhartWavefolder_initToPool (wf, &leaf.mempool);
354}
355
356void tLockhartWavefolder_free(tLockhartWavefolder* const wf)
357{
358 _tLockhartWavefolder* w = *wf;
359
360 leaf_free((char*)w);
361}
362
363void 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
407void 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
417double 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
504float 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
600void 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
612void tCrusher_free (tCrusher* const cr)
613{
614 _tCrusher* c = *cr;
615 tSampleReducer_free(&c->sReducer);
616 leaf_free((char*)c);
617}
618
619void 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
632void 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
640float 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
664void 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
671void 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
683void tCrusher_setRound (tCrusher* const cr, float rnd)
684{
685 _tCrusher* c = *cr;
686 c->rnd = fabsf(rnd);
687}
688
689void tCrusher_setSamplingRatio (tCrusher* const cr, float ratio)
690{
691 _tCrusher* c = *cr;
692 c->srr = ratio;
693 tSampleReducer_setRatio(&c->sReducer, ratio);
694
695}
LEAF/Src/leaf-dynamics.c+0−281
@@ -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 */
44void 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
59void tCompressor_free(tCompressor* const comp)
60{
61 _tCompressor* c = *comp;
62
63 leaf_free((char*)c);
64}
65
66void 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
82void 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
90float 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
141void 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
152void tFeedbackLeveler_free(tFeedbackLeveler* const fb)
153{
154 _tFeedbackLeveler* p = *fb;
155
156 tPowerFollower_free(&p->pwrFlw);
157 leaf_free((char*)p);
158}
159
160void 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
172void 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
181void 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
188void tFeedbackLeveler_setFactor(tFeedbackLeveler* const fb, float factor)
189{
190 _tFeedbackLeveler* p = *fb;
191 tPowerFollower_setFactor(&p->pwrFlw,factor);
192}
193
194void 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
200float 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
209float tFeedbackLeveler_sample(tFeedbackLeveler* const fb)
210{
211 _tFeedbackLeveler* p = *fb;
212 return p->curr;
213}
214
215
216void tFeedbackLeveler_setTargetLevel (tFeedbackLeveler* const fb, float TargetLevel)
217{
218 _tFeedbackLeveler* p = *fb;
219 p->targetLevel=TargetLevel;
220}
221
222
223
224void tThreshold_init(tThreshold* const th, float low, float high)
225{
226 tThreshold_initToPool(th, low, high, &leaf.mempool);
227}
228
229void tThreshold_free(tThreshold* const th)
230{
231 tThreshold_freeFromPool(th, &leaf.mempool);
232}
233
234void 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
245void 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
253int 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
269void tThreshold_setLow(tThreshold* const th, float low)
270{
271 _tThreshold* t = *th;
272
273 t->lowThresh = low;
274}
275
276void tThreshold_setHigh(tThreshold* const th, float high)
277{
278 _tThreshold* t = *th;
279
280 t->highThresh = high;
281}
LEAF/Src/leaf-effects.c+0−1853
@@ -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
28void 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
51void 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
64void 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
87void 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
101void 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
130void 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);
153void 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
199void 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
248void 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
277float 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
325void 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
337void tTalkbox_setWarpFactor(tTalkbox* const voc, float warpFactor)
338{
339 _tTalkbox* v = *voc;
340
341 v->warpFactor = warpFactor;
342}
343
344void 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
356void 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
372void tVocoder_free (tVocoder* const voc)
373{
374 _tVocoder* v = *voc;
375
376 leaf_free((char*)v);
377}
378
379void 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
396void 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
404void 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
488float 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
553void 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
568void tRosenbergGlottalPulse_init (tRosenbergGlottalPulse* const gp)
569{
570 tRosenbergGlottalPulse_initToPool(gp, &leaf.mempool);
571}
572void tRosenbergGlottalPulse_free (tRosenbergGlottalPulse* const gp)
573{
574 tRosenbergGlottalPulse_freeFromPool(gp, &leaf.mempool);
575}
576void 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}
590void 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
597float 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
625void tRosenbergGlottalPulse_setFreq (tRosenbergGlottalPulse* const gp, float freq)
626{
627 _tRosenbergGlottalPulse* g = *gp;
628 g->freq = freq;
629 g->inc = freq * leaf.invSampleRate;
630}
631
632void tRosenbergGlottalPulse_setOpenLength (tRosenbergGlottalPulse* const gp, float openLength)
633{
634 _tRosenbergGlottalPulse* g = *gp;
635 g->openLength = openLength;
636}
637
638void 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
654static void solad_init(_tSOLAD *w);
655static inline float read_sample(_tSOLAD *w, float floatindex);
656static void pitchdown(_tSOLAD *w, float *out);
657static void pitchup(_tSOLAD *w, float *out);
658
659/******************************************************************************/
660/***************** public access functions ************************************/
661/******************************************************************************/
662
663// init
664void 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
674void tSOLAD_free(tSOLAD* const wp)
675{
676 _tSOLAD* w = *wp;
677
678 leaf_free((char*)w->delaybuf);
679 leaf_free((char*)w);
680}
681
682void 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
694void 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
704void 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
722void 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
731void 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
740void 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
755void 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
798static 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 */
916static 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
982static 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
992static 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
1005static 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
1033void 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
1056void 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
1065void 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
1091void 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
1101void tPitchShift_setPitchFactor(tPitchShift* psr, float pf)
1102{
1103 _tPitchShift* ps = *psr;
1104
1105 ps->pitchFactor = pf;
1106}
1107
1108float 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
1140float 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
1175float 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
1218void tRetune_init(tRetune* const rt, int numVoices, int bufSize, int frameSize)
1219{
1220 tRetune_initToPool(rt, numVoices, bufSize, frameSize, &leaf.mempool);
1221}
1222
1223void tRetune_free(tRetune* const rt)
1224{
1225 tRetune_freeFromPool(rt, &leaf.mempool);
1226}
1227
1228void 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
1263void 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
1282float* 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
1296void 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
1323void 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
1334void 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
1342void 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
1350void 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
1358void 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
1366void tRetune_setFidelityThreshold(tRetune* const rt, float threshold)
1367{
1368 _tRetune* r = *rt;
1369
1370 tPeriodDetection_setFidelityThreshold(&r->pd, threshold);
1371}
1372
1373float tRetune_getInputPeriod(tRetune* const rt)
1374{
1375 _tRetune* r = *rt;
1376
1377 return (r->inputPeriod * leaf.invSampleRate);
1378}
1379
1380float 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
1391void tAutotune_init(tAutotune* const rt, int numVoices, int bufSize, int frameSize)
1392{
1393 tAutotune_initToPool(rt, numVoices, bufSize, frameSize, &leaf.mempool);
1394}
1395
1396void tAutotune_free(tAutotune* const rt)
1397{
1398 tAutotune_freeFromPool(rt, &leaf.mempool);
1399}
1400
1401void 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
1436void 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
1455float* 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
1473void 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
1500void 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
1510void tAutotune_setFreq(tAutotune* const rt, float f, int voice)
1511{
1512 _tAutotune* r = *rt;
1513
1514 r->freq[voice] = f;
1515}
1516
1517void 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
1525void 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
1533void 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
1541void tAutotune_setFidelityThreshold(tAutotune* const rt, float threshold)
1542{
1543 _tAutotune* r = *rt;
1544
1545 tPeriodDetection_setFidelityThreshold(&r->pd, threshold);
1546}
1547
1548void tAutotune_setAlpha (tAutotune* rt, float alpha)
1549{
1550 _tAutotune* r = *rt;
1551 tPeriodDetection_setAlpha(&r->pd, alpha);
1552}
1553
1554void tAutotune_setTolerance (tAutotune* rt, float tolerance)
1555{
1556 _tAutotune* r = *rt;
1557 tPeriodDetection_setTolerance(&r->pd, tolerance);
1558}
1559
1560float tAutotune_getInputPeriod(tAutotune* const rt)
1561{
1562 _tAutotune* r = *rt;
1563
1564 return r->inputPeriod;
1565}
1566
1567float 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
1579void 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
1610void 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
1630void 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
1664void 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
1685float tFormantShifter_tick(tFormantShifter* const fsr, float in)
1686{
1687 return tFormantShifter_add(fsr, tFormantShifter_remove(fsr, in));
1688}
1689
1690float 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
1729float 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
1827void tFormantShifter_setShiftFactor(tFormantShifter* const fsr, float shiftFactor)
1828{
1829 _tFormantShifter* fs = *fsr;
1830 fs->shiftFactor = shiftFactor;
1831}
1832
1833void 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}
LEAF/Src/leaf-electrical.c+0−551
@@ -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
22static float get_port_resistance_for_resistor(tWDF* const r);
23static float get_port_resistance_for_capacitor(tWDF* const r);
24static float get_port_resistance_for_inductor(tWDF* const r);
25static float get_port_resistance_for_resistive(tWDF* const r);
26static float get_port_resistance_for_inverter(tWDF* const r);
27static float get_port_resistance_for_series(tWDF* const r);
28static float get_port_resistance_for_parallel(tWDF* const r);
29static float get_port_resistance_for_root(tWDF* const r);
30
31static void set_incident_wave_for_leaf(tWDF* const r, float incident_wave, float input);
32static void set_incident_wave_for_leaf_inverted(tWDF* const r, float incident_wave, float input);
33static void set_incident_wave_for_inverter(tWDF* const r, float incident_wave, float input);
34static void set_incident_wave_for_series(tWDF* const r, float incident_wave, float input);
35static void set_incident_wave_for_parallel(tWDF* const r, float incident_wave, float input);
36
37static float get_reflected_wave_for_resistor(tWDF* const r, float input);
38static float get_reflected_wave_for_capacitor(tWDF* const r, float input);
39static float get_reflected_wave_for_resistive(tWDF* const r, float input);
40static float get_reflected_wave_for_inverter(tWDF* const r, float input);
41static float get_reflected_wave_for_series(tWDF* const r, float input);
42static float get_reflected_wave_for_parallel(tWDF* const r, float input);
43
44static float get_reflected_wave_for_ideal(tWDF* const n, float input, float incident_wave);
45static float get_reflected_wave_for_diode(tWDF* const n, float input, float incident_wave);
46static float get_reflected_wave_for_diode_pair(tWDF* const n, float input, float incident_wave);
47
48static 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
167void 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
174void tWDF_free(tWDF* const wdf)
175{
176 _tWDF* r = *wdf;
177
178 leaf_free((char*)r);
179}
180
181void 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
189void 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
197float 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
224void tWDF_setValue(tWDF* const wdf, float value)
225{
226 _tWDF* r = *wdf;
227 r->value = value;
228}
229
230void tWDF_setSampleRate(tWDF* const wdf, float sample_rate)
231{
232 _tWDF* r = *wdf;
233 r->sample_rate = sample_rate;
234}
235
236uint8_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
243float tWDF_getPortResistance(tWDF* const wdf)
244{
245 _tWDF* r = *wdf;
246 return r->get_port_resistance(wdf);
247}
248
249void 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
255float tWDF_getReflectedWaveUp(tWDF* const wdf, float input)
256{
257 _tWDF* r = *wdf;
258 return r->get_reflected_wave_up(wdf, input);
259}
260
261float 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
267float 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
273float 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
283static 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
293static 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
303static 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
313static 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
323static 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
333static 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
348static 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
363static 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
380static 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
386static 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
392static 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
399static 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
418static 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
436static 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
443static 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
450static 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
457static 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
464static 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
472static 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
483static 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
492static 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
503static 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
519static float wrightOmegaApproximation(float x)
520{
521 float w3 = wrightOmega3(x);
522 return w3 - ((w3 - expf(x - w3)) / (w3 + 1.0f));
523}
524
525static 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
532static 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
541static 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}
LEAF/Src/leaf-envelopes.c+0−1612
@@ -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 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
27void 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
67void tEnvelope_free(tEnvelope* const envlp)
68{
69 _tEnvelope* env = *envlp;
70 leaf_free((char*)env);
71}
72
73void 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
114void 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
121void 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
138void 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
155void tEnvelope_loop(tEnvelope* const envlp, int loop)
156{
157 _tEnvelope* env = *envlp;
158 env->loop = loop;
159}
160
161
162void 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
184float 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 */
259void 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
264void tADSR_free(tADSR* const adsrenv)
265{
266 tADSR_freeFromPool(adsrenv, &leaf.mempool);
267}
268
269void 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
330void 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
337void 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
354void 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
371void 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
380void 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
398void tADSR_setLeakFactor(tADSR* const adsrenv, float leakFactor)
399{
400 _tADSR* adsr = *adsrenv;
401
402
403 adsr->leakFactor = leakFactor;
404}
405
406void 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
430void 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
444float 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
541const float ADSR2_MIN_TIME = 1e-3f;
542const float ADSR2_INV_MIN_TIME = 1000.0f;
543const float ADSR2_MAX_TIME = 10.f;
544const float ADSR2_LAMBDA_BASE = 10000.0f;
545
546
547void 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
552void tADSR2_free(tADSR2* const adsrenv)
553{
554 tADSR2_freeFromPool(adsrenv, &leaf.mempool);
555}
556
557void 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
586void 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
593void 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
601void 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
609void 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
623void 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
631void tADSR2_setLeakFactor(tADSR2* const adsrenv, float leakFactor)
632{
633 _tADSR2* adsr = *adsrenv;
634
635 adsr->leakFactor = leakFactor;
636}
637
638void 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
648void tADSR2_off(tADSR2* const adsrenv)
649{
650 _tADSR2* adsr = *adsrenv;
651 adsr->gate = 0;
652 adsr->envTarget = 0.0f;
653}
654
655float 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
697float calcADSR3Coef(double rate, double targetRatio)
698{
699 return (rate <= 0.0f) ? 0.0f : exp(-log((1.0 + targetRatio) / targetRatio) / rate);
700}
701
702
703void 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
708void tADSR3_free(tADSR3* const adsrenv)
709{
710 tADSR3_freeFromPool(adsrenv, &leaf.mempool);
711}
712
713void 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
744void 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
751void 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
760void 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
769void 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
777void 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
787void tADSR3_setLeakFactor(tADSR3* const adsrenv, float leakFactor)
788{
789 _tADSR3* adsr = *adsrenv;
790
791 adsr->leakFactor = leakFactor;
792}
793
794void tADSR3_on(tADSR3* const adsrenv, float velocity)
795{
796 _tADSR3* adsr = *adsrenv;
797 adsr->state = env_attack;
798 adsr->targetGainSquared = velocity * velocity;
799}
800
801void 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
811float 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.
851void 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
856void 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
863void 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
902void 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
909void 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
921void 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
932void 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
941void 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
953void tADSR4_setLeakFactor(tADSR4* const adsrenv, float leakFactor)
954{
955 _tADSR4* adsr = *adsrenv;
956
957
958 adsr->leakFactor = leakFactor;
959}
960
961void 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
982void 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
997float 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
1122float 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 */
1204void 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
1226void tRamp_free(tRamp* const r)
1227{
1228 _tRamp* ramp = *r;
1229
1230 leaf_free((char*)ramp);
1231}
1232
1233void 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
1256void 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
1264void 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
1281void 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
1288void 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
1295float 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
1310float tRamp_sample(tRamp* const ramp)
1311{
1312 _tRamp* r = *ramp;
1313 return r->curr;
1314}
1315
1316void 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 */
1327void 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
1332void tRampUpDown_free(tRampUpDown* const r)
1333{
1334 tRampUpDown_freeFromPool(r, &leaf.mempool);
1335}
1336
1337void 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
1370void 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
1378void 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
1394void 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
1409void 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
1417void 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
1425float 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
1459float tRampUpDown_sample(tRampUpDown* const ramp)
1460{
1461 _tRampUpDown* r = *ramp;
1462 return r->curr;
1463}
1464
1465
1466
1467
1468
1469
1470/* Exponential Smoother */
1471void 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
1483void tExpSmooth_free(tExpSmooth* const expsmooth)
1484{
1485 _tExpSmooth* smooth = *expsmooth;
1486
1487 leaf_free((char*)smooth);
1488}
1489
1490void 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
1503void 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
1511void 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
1523void tExpSmooth_setDest(tExpSmooth* const expsmooth, float dest)
1524{
1525 _tExpSmooth* smooth = *expsmooth;
1526 smooth->dest=dest;
1527}
1528
1529void tExpSmooth_setVal(tExpSmooth* const expsmooth, float val)
1530{
1531 _tExpSmooth* smooth = *expsmooth;
1532 smooth->curr=val;
1533}
1534
1535void tExpSmooth_setValAndDest(tExpSmooth* const expsmooth, float val)
1536{
1537 _tExpSmooth* smooth = *expsmooth;
1538 smooth->curr=val;
1539 smooth->dest=val;
1540}
1541
1542float 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
1549float 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
1558void tSlide_init (tSlide* const sl, float upSlide, float downSlide)
1559{
1560 tSlide_initToPool (sl, upSlide, downSlide, &leaf.mempool);
1561}
1562void tSlide_free (tSlide* const sl)
1563{
1564 tSlide_freeFromPool (sl, &leaf.mempool);
1565}
1566void 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
1586void 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
1594float 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
LEAF/Src/leaf-filters.c+0−1802
@@ -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 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
24void 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
35void tAllpass_free(tAllpass* const ft)
36{
37 _tAllpass* f = *ft;
38
39 tLinearDelay_free(&f->delay);
40 leaf_free((char*)f);
41}
42
43void 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
55void 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
64void tAllpass_setDelay(tAllpass* const ft, float delay)
65{
66 _tAllpass* f = *ft;
67
68 tLinearDelay_setDelay(&f->delay, delay);
69}
70
71void tAllpass_setGain(tAllpass* const ft, float gain)
72{
73 _tAllpass* f = *ft;
74
75 f->gain = gain;
76}
77
78float 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 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
92void 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
105void tOnePole_free(tOnePole* const ft)
106{
107 _tOnePole* f = *ft;
108
109 leaf_free((char*)f);
110}
111
112void 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
126void 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
134void tOnePole_setB0(tOnePole* const ft, float b0)
135{
136 _tOnePole* f = *ft;
137 f->b0 = b0;
138}
139
140void 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
147void 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
160void 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
168void 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
176void tOnePole_setGain(tOnePole* const ft, float gain)
177{
178 _tOnePole* f = *ft;
179 f->gain = gain;
180}
181
182float 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 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
196void 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
208void tTwoPole_free(tTwoPole* const ft)
209{
210 _tTwoPole* f = *ft;
211
212 leaf_free((char*)f);
213}
214
215void 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
228void 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
236float 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
249void tTwoPole_setB0(tTwoPole* const ft, float b0)
250{
251 _tTwoPole* f = *ft;
252 f->b0 = b0;
253}
254
255void tTwoPole_setA1(tTwoPole* const ft, float a1)
256{
257 _tTwoPole* f = *ft;
258 f->a1 = a1;
259}
260
261void tTwoPole_setA2(tTwoPole* const ft, float a2)
262{
263 _tTwoPole* f = *ft;
264 f->a2 = a2;
265}
266
267
268void 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
293void 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
301void tTwoPole_setGain(tTwoPole* const ft, float gain)
302{
303 _tTwoPole* f = *ft;
304 f->gain = gain;
305}
306
307void 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 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
324void 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
334void tOneZero_free(tOneZero* const ft)
335{
336 _tOneZero* f = *ft;
337
338 leaf_free((char*)f);
339}
340
341void 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
352void 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
360float 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
372void 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
383void tOneZero_setB0(tOneZero* const ft, float b0)
384{
385 _tOneZero* f = *ft;
386
387 f->b0 = b0;
388}
389
390void tOneZero_setB1(tOneZero* const ft, float b1)
391{
392 _tOneZero* f = *ft;
393 f->b1 = b1;
394}
395
396void tOneZero_setCoefficients(tOneZero* const ft, float b0, float b1)
397{
398 _tOneZero* f = *ft;
399 f->b0 = b0;
400 f->b1 = b1;
401}
402
403void tOneZero_setGain(tOneZero *ft, float gain)
404{
405 _tOneZero* f = *ft;
406 f->gain = gain;
407}
408
409float 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 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
440void 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
449void tTwoZero_free(tTwoZero* const ft)
450{
451 _tTwoZero* f = *ft;
452
453 leaf_free((char*)f);
454}
455
456void 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
466void 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
474float 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
487void 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
511void tTwoZero_setB0(tTwoZero* const ft, float b0)
512{
513 _tTwoZero* f = *ft;
514 f->b0 = b0;
515}
516
517void tTwoZero_setB1(tTwoZero* const ft, float b1)
518{
519 _tTwoZero* f = *ft;
520 f->b1 = b1;
521}
522
523void 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
531void tTwoZero_setGain(tTwoZero* const ft, float gain)
532{
533 _tTwoZero* f = *ft;
534 f->gain = gain;
535}
536
537void tTwoZeroSampleRateChanged(tTwoZero* const ft)
538{
539 _tTwoZero* f = *ft;
540
541 tTwoZero_setNotch(ft, f->frequency, f->radius);
542}
543
544// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PoleZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
545void 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
557void tPoleZero_free(tPoleZero* const pzf)
558{
559 _tPoleZero* f = *pzf;
560
561 leaf_free((char*)f);
562}
563
564void 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
577void 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
585void tPoleZero_setB0(tPoleZero* const pzf, float b0)
586{
587 _tPoleZero* f = *pzf;
588 f->b0 = b0;
589}
590
591void tPoleZero_setB1(tPoleZero* const pzf, float b1)
592{
593 _tPoleZero* f = *pzf;
594 f->b1 = b1;
595}
596
597void 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
609void 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
623void 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
638void 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
653void tPoleZero_setGain(tPoleZero* const pzf, float gain)
654{
655 _tPoleZero* f = *pzf;
656 f->gain = gain;
657}
658
659float 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 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
673void 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
688void tBiQuad_free(tBiQuad* const ft)
689{
690 _tBiQuad* f = *ft;
691
692 leaf_free((char*)f);
693}
694
695void 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
711void 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
719float 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
736void 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
760void 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
774void 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
782void tBiQuad_setB0(tBiQuad* const ft, float b0)
783{
784 _tBiQuad* f = *ft;
785 f->b0 = b0;
786}
787
788void tBiQuad_setB1(tBiQuad* const ft, float b1)
789{
790 _tBiQuad* f = *ft;
791 f->b1 = b1;
792}
793
794void tBiQuad_setB2(tBiQuad* const ft, float b2)
795{
796 _tBiQuad* f = *ft;
797 f->b2 = b2;
798}
799
800void tBiQuad_setA1(tBiQuad* const ft, float a1)
801{
802 _tBiQuad* f = *ft;
803 f->a1 = a1;
804}
805
806void tBiQuad_setA2(tBiQuad* const ft, float a2)
807{
808 _tBiQuad* f = *ft;
809 f->a2 = a2;
810}
811
812void 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
822void tBiQuad_setGain(tBiQuad* const ft, float gain)
823{
824 _tBiQuad* f = *ft;
825 f->gain = gain;
826}
827
828void 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.
844void 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
855void tSVF_free(tSVF* const svff)
856{
857 tSVF_freeFromPool (svff, &leaf.mempool);
858}
859
860void 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
921void 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
929float 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
943void 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
953void 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
964void 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.
975void 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
991void tEfficientSVF_free(tEfficientSVF* const svff)
992{
993 _tEfficientSVF* svf = *svff;
994
995 leaf_free((char*)svf);
996}
997
998void 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
1015void 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
1023float 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
1043void 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
1053void 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 */
1064void 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
1075void tHighpass_free(tHighpass* const ft)
1076{
1077 _tHighpass* f = *ft;
1078
1079 leaf_free((char*)f);
1080}
1081
1082void 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
1094void 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
1102void 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
1110float tHighpass_getFreq(tHighpass* const ft)
1111{
1112 _tHighpass* f = *ft;
1113 return f->frequency;
1114}
1115
1116// From JOS DC Blocker
1117float 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
1125void tHighpassSampleRateChanged(tHighpass* const ft)
1126{
1127 _tHighpass* f = *ft;
1128 f->R = (1.0f-((f->frequency * 2.0f * 3.14f) * leaf.invSampleRate));
1129}
1130
1131void 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
1150void 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
1163void 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
1183void 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
1197float 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
1209void 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
1217void 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
1225void 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
1238void 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
1248void tFIR_free(tFIR* const firf)
1249{
1250 _tFIR* fir = *firf;
1251
1252 leaf_free((char*)fir->past);
1253 leaf_free((char*)fir);
1254}
1255
1256void 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
1267void 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
1276float 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
1293void tMedianFilter_init (tMedianFilter* const f, int size)
1294{
1295 tMedianFilter_initToPool(f, size, &leaf.mempool);
1296}
1297void tMedianFilter_free (tMedianFilter* const f)
1298{
1299 tMedianFilter_freeFromPool(f, &leaf.mempool);
1300}
1301void 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}
1319void 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
1329float 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
1370void tVZFilter_init (tVZFilter* const vf, VZFilterType type, float freq, float bandWidth)
1371{
1372 tVZFilter_initToPool(vf, type, freq, bandWidth, &leaf.mempool);
1373}
1374
1375void tVZFilter_free (tVZFilter* const vf)
1376{
1377 tVZFilter_freeFromPool(vf, &leaf.mempool);
1378}
1379void 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}
1398void 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
1405void 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
1412float 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
1443float 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
1474float 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
1506void 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
1612void 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}
1618void 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}
1624void 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
1632void 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
1640void 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
1647void tVZFilter_setType (tVZFilter* const vf, VZFilterType type)
1648{
1649 _tVZFilter* f = *vf;
1650 f->type = type;
1651 tVZFilter_calcCoeffs(vf);
1652}
1653
1654float 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
1667void tDiodeFilter_init (tDiodeFilter* const vf, float cutoff, float resonance)
1668{
1669 tDiodeFilter_initToPool(vf, cutoff, resonance, &leaf.mempool);
1670}
1671
1672void tDiodeFilter_free (tDiodeFilter* const vf)
1673{
1674 tDiodeFilter_freeFromPool(vf, &leaf.mempool);
1675}
1676void 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}
1698void 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
1705float 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
1712float 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
1789void 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
1796void 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
LEAF/Src/leaf-instruments.c+0−706
@@ -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
21void 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
50void 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
66void 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
96void 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
113void 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
123float 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
147void t808Cowbell_setDecay(t808Cowbell* const cowbellInst, float decay)
148{
149 _t808Cowbell* cowbell = *cowbellInst;
150 tEnvelope_setDecay(&cowbell->envGain,decay);
151}
152
153void t808Cowbell_setHighpassFreq(t808Cowbell *cowbellInst, float freq)
154{
155 _t808Cowbell* cowbell = *cowbellInst;
156 tHighpass_setFreq(&cowbell->highpass,freq);
157}
158
159void t808Cowbell_setBandpassFreq(t808Cowbell* const cowbellInst, float freq)
160{
161 _t808Cowbell* cowbell = *cowbellInst;
162 cowbell->filterCutoff = freq;
163}
164
165void 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
172void t808Cowbell_setOscMix(t808Cowbell* const cowbellInst, float oscMix)
173{
174 _t808Cowbell* cowbell = *cowbellInst;
175 cowbell->oscMix = oscMix;
176}
177
178void t808Cowbell_setStick(t808Cowbell* const cowbellInst, int useStick)
179{
180 _t808Cowbell* cowbell = *cowbellInst;
181 cowbell->useStick = useStick;
182}
183
184// ----------------- HIHAT ----------------------------//
185
186void 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
219void 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
242void 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
276void 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
300void 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
307void t808Hihat_setOscNoiseMix(t808Hihat* const hihatInst, float oscNoiseMix)
308{
309 _t808Hihat* hihat = *hihatInst;
310 hihat->oscNoiseMix = oscNoiseMix;
311}
312
313float 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
349void t808Hihat_setDecay(t808Hihat* const hihatInst, float decay)
350{
351 _t808Hihat* hihat = *hihatInst;
352 tEnvelope_setDecay(&hihat->envGain,decay);
353}
354
355void t808Hihat_setHighpassFreq(t808Hihat* const hihatInst, float freq)
356{
357 _t808Hihat* hihat = *hihatInst;
358 tHighpass_setFreq(&hihat->highpass,freq);
359}
360
361void t808Hihat_setStretch(t808Hihat* const hihatInst, float stretch)
362{
363 _t808Hihat* hihat = *hihatInst;
364 hihat->stretch = stretch;
365}
366
367void t808Hihat_setFM(t808Hihat* const hihatInst, float FM_amount)
368{
369 _t808Hihat* hihat = *hihatInst;
370 hihat->FM_amount = FM_amount;
371}
372
373void t808Hihat_setOscBandpassFreq(t808Hihat* const hihatInst, float freq)
374{
375 _t808Hihat* hihat = *hihatInst;
376 tSVF_setFreq(&hihat->bandpassOsc,freq);
377}
378
379void t808Hihat_setOscBandpassQ(t808Hihat* const hihatInst, float Q)
380{
381 _t808Hihat* hihat = *hihatInst;
382 tSVF_setQ(&hihat->bandpassOsc,Q);
383}
384
385void t808Hihat_setStickBandPassFreq(t808Hihat* const hihatInst, float freq)
386{
387 _t808Hihat* hihat = *hihatInst;
388 tSVF_setFreq(&hihat->bandpassStick,freq);
389}
390
391void t808Hihat_setStickBandPassQ(t808Hihat* const hihatInst, float Q)
392{
393 _t808Hihat* hihat = *hihatInst;
394 tSVF_setQ(&hihat->bandpassStick,Q);
395}
396
397void t808Hihat_setOscFreq(t808Hihat* const hihatInst, float freq)
398{
399 _t808Hihat* hihat = *hihatInst;
400 hihat->freq = freq;
401}
402
403// ----------------- SNARE ----------------------------//
404
405void 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
433void 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
454void 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
483void 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
505void 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
520void 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
527void 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
534void t808Snare_setTone1Decay(t808Snare* const snareInst, float decay)
535{
536 _t808Snare* snare = *snareInst;
537 tEnvelope_setDecay(&snare->toneEnvGain[0],decay);
538}
539
540void t808Snare_setTone2Decay(t808Snare* const snareInst, float decay)
541{
542 _t808Snare* snare = *snareInst;
543 tEnvelope_setDecay(&snare->toneEnvGain[1],decay);
544}
545
546void t808Snare_setNoiseDecay(t808Snare* const snareInst, float decay)
547{
548 _t808Snare* snare = *snareInst;
549 tEnvelope_setDecay(&snare->noiseEnvGain,decay);
550}
551
552void t808Snare_setToneNoiseMix(t808Snare* const snareInst, float toneNoiseMix)
553{
554 _t808Snare* snare = *snareInst;
555 snare->toneNoiseMix = toneNoiseMix;
556}
557
558void t808Snare_setNoiseFilterFreq(t808Snare* const snareInst, float noiseFilterFreq)
559{
560 _t808Snare* snare = *snareInst;
561 snare->noiseFilterFreq = noiseFilterFreq;
562}
563
564void t808Snare_setNoiseFilterQ(t808Snare* const snareInst, float noiseFilterQ)
565{
566 _t808Snare* snare = *snareInst;
567 tSVF_setQ(&snare->noiseLowpass, noiseFilterQ);
568}
569
570static float tone[2];
571
572float 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
596void 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
614void 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
629void 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
648void 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
664float 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
676void 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}
685void t808Kick_setToneFreq (t808Kick* const kickInst, float freq)
686{
687 _t808Kick* kick = *kickInst;
688 kick->toneInitialFreq = freq;
689
690}
691
692void 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
699void t808Kick_setNoiseDecay (t808Kick* const kickInst, float decay);
700void t808Kick_setSighAmount (t808Kick* const kickInst, float sigh);
701void t808Kick_setChirpAmount (t808Kick* const kickInst, float chirp);
702void t808Kick_setToneNoiseMix (t808Kick* const kickInst, float toneNoiseMix);
703void t808Kick_setNoiseFilterFreq (t808Kick* const kickInst, float noiseFilterFreq);
704void t808Kick_setNoiseFilterQ (t808Kick* const kickInst, float noiseFilterQ);
705
706
LEAF/Src/leaf-math.c+0−655
@@ -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;
28float 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
43float 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
55float 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
69int 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
80float 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
93double 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
101float 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
109double 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
116float 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
125float 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
155float 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
167double 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
190void 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
196float 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)
203float 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
219float LEAF_frequencyToMidi(float f)
220{
221 return (69.0f + 12.0f * log2f(f * INV_440));
222}
223
224// Jones shaper
225float 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
241float 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
254float 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
263float 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
271float 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
291float 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
309int 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
327oBool 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
339float 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
351void 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
361void 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
383void 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
412void 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
436void 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
452float 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//-----------------------------------------------------------------------------
505float 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]
514float 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
530float 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]
543float 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
559float 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
566float fast_mtof(float f)
567{
568 return (8.17579891564f * fastexpf(0.0577622650f * f));
569}
570
571float faster_mtof(float f)
572{
573 return (8.17579891564f * fastexpf(0.0577622650f * f));
574}
575
576float ftom(float f)
577{
578 return (f > 0 ? 17.3123405046f * logf(.12231220585f * f) : -1500.0f);
579}
580
581float 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
591float 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
601float 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
613float 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
626float atodb(float a)
627{
628 return 20.0f*log10f(a);
629}
630
631float 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
638float 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
645float maximum (float num1, float num2)
646{
647 return (num1 > num2 ) ? num1 : num2;
648}
649
650float minimum (float num1, float num2)
651{
652 return (num1 < num2 ) ? num1 : num2;
653}
654
655
LEAF/Src/leaf-mempool.c+0−412
@@ -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 */
54static inline size_t mpool_align(size_t size);
55static inline mpool_node_t* create_node(char* block_location, mpool_node_t* next, mpool_node_t* prev, size_t size);
56static inline void delink_node(mpool_node_t* node);
57
58/**
59 * create memory pool
60 */
61void 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
80void 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 */
90char* 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 */
164char* 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
230char* 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
240char* 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
251void 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
313void leaf_free(char* ptr)
314{
315 mpool_free(ptr, &leaf._mempool);
316}
317
318size_t mpool_get_size(_tMempool* pool)
319{
320 return pool->msize;
321}
322
323size_t mpool_get_used(_tMempool* pool)
324{
325 return pool->usize;
326}
327
328size_t leaf_pool_get_size(void)
329{
330 return mpool_get_size(&leaf._mempool);
331}
332
333size_t leaf_pool_get_used(void)
334{
335 return mpool_get_used(&leaf._mempool);
336}
337
338char* leaf_pool_get_pool(void)
339{
340 char* buff = leaf._mempool.mpool;
341
342 return buff;
343}
344
345/**
346 * align byte boundary
347 */
348static inline size_t mpool_align(size_t size) {
349 return (size + (MPOOL_ALIGN_SIZE - 1)) & ~(MPOOL_ALIGN_SIZE - 1);
350}
351
352static 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
363static 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
382void 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
388void tMempool_init(tMempool* const mp, char* memory, size_t size)
389{
390 tMempool_initToPool(mp, memory, size, &leaf.mempool);
391}
392
393void tMempool_free(tMempool* const mp)
394{
395 tMempool_freeFromPool(mp, &leaf.mempool);
396}
397
398void 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
406void 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}
LEAF/Src/leaf-midi.c+0−980
@@ -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
23void 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
35void tStack_free(tStack* const stack)
36{
37 _tStack* ns = *stack;
38
39 leaf_free((char*)ns);
40}
41
42void 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
55void 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;
64int 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
74void 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
108int 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
152int 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
188void 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
214int tStack_getSize(tStack* const stack)
215{
216 _tStack* ns = *stack;
217
218 return ns->size;
219}
220
221void 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.
234int 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
259int tStack_get(tStack* const stack, int which)
260{
261 _tStack* ns = *stack;
262 return ns->data[which];
263}
264
265int tStack_first(tStack* const stack)
266{
267 _tStack* ns = *stack;
268 return ns->data[0];
269}
270
271
272// POLY
273void 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
318void 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
339void 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
385void 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
407void tPoly_tickPitch(tPoly* polyh)
408{
409 tPoly_tickPitchGlide(polyh);
410 tPoly_tickPitchBend(polyh);
411}
412
413void 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
422void tPoly_tickPitchBend(tPoly* polyh)
423{
424 _tPoly* poly = *polyh;
425 tRamp_tick(&poly->pitchBendRamp);
426}
427
428void 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
435int 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
511int16_t noteToTest = -1;
512
513int 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
573void 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
613void tPoly_setNumVoices(tPoly* const polyh, uint8_t numVoices)
614{
615 _tPoly* poly = *polyh;
616 poly->numVoices = (numVoices > poly->maxNumVoices) ? poly->maxNumVoices : numVoices;
617}
618
619void tPoly_setPitchGlideActive(tPoly* const polyh, oBool isActive)
620{
621 _tPoly* poly = *polyh;
622 poly->pitchGlideIsActive = isActive;
623}
624
625void 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
635void tPoly_setBendGlideTime(tPoly* const polyh, float t)
636{
637 _tPoly* poly = *polyh;
638 tRamp_setTime(&poly->pitchBendRamp, t);
639}
640
641void tPoly_setBendSamplesPerTick(tPoly* const polyh, float t)
642{
643 _tPoly* poly = *polyh;
644 poly->pitchBendRamp->samples_per_tick = t;
645}
646
647int tPoly_getNumVoices(tPoly* const polyh)
648{
649 _tPoly* poly = *polyh;
650 return poly->numVoices;
651}
652
653int tPoly_getNumActiveVoices(tPoly* const polyh)
654{
655 _tPoly* poly = *polyh;
656 return LEAF_clip(0, tStack_getSize(&poly->stack), poly->numVoices);
657}
658
659float 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
665int tPoly_getKey(tPoly* const polyh, uint8_t voice)
666{
667 _tPoly* poly = *polyh;
668 return poly->voices[voice][0];
669}
670
671int tPoly_getVelocity(tPoly* const polyh, uint8_t voice)
672{
673 _tPoly* poly = *polyh;
674 return poly->voices[voice][1];
675}
676
677int 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
690void tSimplePoly_init(tSimplePoly* const polyh, int maxNumVoices)
691{
692 tSimplePoly_initToPool(polyh, maxNumVoices, &leaf.mempool);
693}
694
695void tSimplePoly_free(tSimplePoly* const polyh)
696{
697 tSimplePoly_freeFromPool(polyh, &leaf.mempool);
698}
699
700void 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
726void 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
740int 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
819int 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
863void 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
890int 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
908int 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
937void 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
944int tSimplePoly_getNumVoices(tSimplePoly* const polyh)
945{
946 _tSimplePoly* poly = *polyh;
947 return poly->numVoices;
948}
949
950int tSimplePoly_getNumActiveVoices(tSimplePoly* const polyh)
951{
952 _tSimplePoly* poly = *polyh;
953 return LEAF_clip(0, tStack_getSize(&poly->stack), poly->numVoices);
954}
955
956
957int 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
964int tSimplePoly_getPitchAndCheckActive(tSimplePoly* const polyh, uint8_t voice)
965{
966 _tSimplePoly* poly = *polyh;
967 return poly->voices[voice][0];
968}
969
970int tSimplePoly_getVelocity(tSimplePoly* const polyh, uint8_t voice)
971{
972 _tSimplePoly* poly = *polyh;
973 return poly->voices[voice][1];
974}
975
976int tSimplePoly_isOn(tSimplePoly* const polyh, uint8_t voice)
977{
978 _tSimplePoly* poly = *polyh;
979 return (poly->voices[voice][0] > 0) ? 1 : 0;
980}
LEAF/Src/leaf-oscillators.c+0−1660
@@ -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
20void tCycle_init(tCycle* const cy)
21{
22 tCycle_initToPool(cy, &leaf.mempool);
23}
24
25void tCycle_free(tCycle* const cy)
26{
27 tCycle_freeFromPool(cy, &leaf.mempool);
28}
29
30void 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
40void 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
48void 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
58float 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
85void tCycleSampleRateChanged (tCycle* const cy)
86{
87 _tCycle* c = *cy;
88
89 c->inc = c->freq * leaf.invSampleRate;
90}
91
92//========================================================================
93/* Triangle */
94void tTriangle_init(tTriangle* const cy)
95{
96 tTriangle_initToPool(cy, &leaf.mempool);
97}
98
99void tTriangle_free(tTriangle* const cy)
100{
101 tTriangle_freeFromPool(cy, &leaf.mempool);
102}
103
104void 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
114void 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
122void 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
139float 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
159void tTriangleSampleRateChanged (tTriangle* const cy)
160{
161 _tTriangle* c = *cy;
162
163 c->inc = c->freq * leaf.invSampleRate;
164}
165
166//========================================================================
167/* Square */
168void tSquare_init(tSquare* const cy)
169{
170 tSquare_initToPool(cy, &leaf.mempool);
171}
172
173void tSquare_free(tSquare* const cy)
174{
175 tSquare_freeFromPool(cy, &leaf.mempool);
176}
177
178void 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
188void 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
196void 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
212float 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
232void tSquareSampleRateChanged (tSquare* const cy)
233{
234 _tSquare* c = *cy;
235
236 c->inc = c->freq * leaf.invSampleRate;
237}
238
239//=====================================================================
240// Sawtooth
241void tSawtooth_init(tSawtooth* const cy)
242{
243 tSawtooth_initToPool(cy, &leaf.mempool);
244}
245
246void tSawtooth_free(tSawtooth* const cy)
247{
248 tSawtooth_freeFromPool(cy, &leaf.mempool);
249}
250
251void 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
261void 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
269void 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
285float 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
305void tSawtoothSampleRateChanged (tSawtooth* const cy)
306{
307 _tSawtooth* c = *cy;
308
309 c->inc = c->freq * leaf.invSampleRate;
310}
311
312//========================================================================
313// Sine
314void tSine_init(tSine* const cy, int size)
315{
316 tSine_initToPool(cy, size, &leaf.mempool);
317}
318
319void tSine_free(tSine* const cy)
320{
321 tSine_freeFromPool(cy, &leaf.mempool);
322}
323
324void 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
336void 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
345void 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
353float 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
380void 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. */
390void tTri_init (tTri* const osc)
391{
392 tTri_initToPool(osc, &leaf.mempool);
393}
394
395void tTri_free (tTri* const osc)
396{
397 tTri_freeFromPool(osc, &leaf.mempool);
398}
399
400void 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
411void 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
419float 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
452void 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
460void 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. */
470void tPulse_init (tPulse* const osc)
471{
472 tPulse_initToPool(osc, &leaf.mempool);
473}
474
475void tPulse_free (tPulse* const osc)
476{
477 tPulse_freeFromPool(osc, &leaf.mempool);
478}
479
480void 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
490void 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
498float 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
517void 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
525void 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. */
535void tSaw_init (tSaw* const osc)
536{
537 tSaw_initToPool(osc, &leaf.mempool);
538}
539
540void tSaw_free (tSaw* const osc)
541{
542 tSaw_freeFromPool(osc, &leaf.mempool);
543}
544
545void 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
554void 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
562float 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
578void 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 */
589void tPhasorSampleRateChanged (tPhasor* const ph)
590{
591 _tPhasor* p = *ph;
592
593 p->inc = p->freq * leaf.invSampleRate;
594};
595
596void tPhasor_init(tPhasor* const ph)
597{
598 tPhasor_initToPool(ph, &leaf.mempool);
599}
600
601void tPhasor_free(tPhasor* const ph)
602{
603 tPhasor_freeFromPool(ph, &leaf.mempool);
604}
605
606void 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
616void 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
624void 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
633float 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 */
651void tNoise_init(tNoise* const ns, NoiseType type)
652{
653 tNoise_initToPool(ns, type, &leaf.mempool);
654}
655
656void tNoise_free(tNoise* const ns)
657{
658 tNoise_freeFromPool(ns, &leaf.mempool);
659}
660
661void 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
670void 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
678float 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
702void tNeuronSampleRateChanged(tNeuron* nr)
703{
704
705}
706
707void tNeuron_init(tNeuron* const nr)
708{
709 tNeuron_initToPool(nr, &leaf.mempool);
710}
711
712void tNeuron_free(tNeuron* const nr)
713{
714 tNeuron_freeFromPool(nr, &leaf.mempool);
715}
716
717void 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
749void 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
758void 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
787void tNeuron_setV1(tNeuron* const nr, float V1)
788{
789 _tNeuron* n = *nr;
790 n->V[0] = V1;
791}
792
793
794void tNeuron_setV2(tNeuron* const nr, float V2)
795{
796 _tNeuron* n = *nr;
797 n->V[1] = V2;
798}
799
800void tNeuron_setV3(tNeuron* const nr, float V3)
801{
802 _tNeuron* n = *nr;
803 n->V[2] = V3;
804}
805
806void tNeuron_setTimeStep(tNeuron* const nr, float timeStep)
807{
808 _tNeuron* n = *nr;
809 n->timeStep = timeStep;
810}
811
812void tNeuron_setK(tNeuron* const nr, float K)
813{
814 _tNeuron* n = *nr;
815 n->gK = K;
816}
817
818void 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
825void tNeuron_setN(tNeuron* const nr, float N)
826{
827 _tNeuron* n = *nr;
828 n->gN = N;
829}
830
831void 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
838float 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
914void tNeuron_setMode (tNeuron* const nr, NeuronMode mode)
915{
916 _tNeuron* n = *nr;
917 n->mode = mode;
918}
919
920void tNeuron_setCurrent (tNeuron* const nr, float current)
921{
922 _tNeuron* n = *nr;
923 n->current = current;
924}
925
926
927
928void tMinBLEP_init (tMinBLEP* const minblep, int zeroCrossings, int oversamplerRatio)
929{
930 tMinBLEP_initToPool(minblep, zeroCrossings, oversamplerRatio, &leaf.mempool);
931}
932
933void tMinBLEP_free (tMinBLEP* const minblep)
934{
935 tMinBLEP_freeFromPool(minblep, &leaf.mempool);
936}
937
938void 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
979void 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
996static 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
1010static 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
1026static 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
1049static 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
1076static float complexabs(float x, float y)
1077{
1078 return sqrtf((x * x) + (y * y));
1079}
1080
1081// Complex Exponential
1082static 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
1092static 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
1131static 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
1175void 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
1241void 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
1258float 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. */
1353void tMBTriangle_init (tMBTriangle* const osc)
1354{
1355 tMBTriangle_initToPool(osc, &leaf.mempool);
1356}
1357
1358void tMBTriangle_free (tMBTriangle* const osc)
1359{
1360 tMBTriangle_freeFromPool(osc, &leaf.mempool);
1361}
1362
1363void 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
1377void 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
1388float 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
1448void 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
1458void tMBTriangle_setSkew (tMBTriangle* const osc, float skew)
1459{
1460 _tMBTriangle* c = *osc;
1461 c->skew = (skew + 1.0f) * 0.5f;
1462}
1463
1464void 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. */
1493void tMBPulse_init (tMBPulse* const osc)
1494{
1495 tMBPulse_initToPool(osc, &leaf.mempool);
1496}
1497
1498void tMBPulse_free (tMBPulse* const osc)
1499{
1500 tMBPulse_freeFromPool(osc, &leaf.mempool);
1501}
1502
1503void 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
1516void 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
1527float 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
1553void 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
1561void tMBPulse_setWidth (tMBPulse* const osc, float width)
1562{
1563 _tMBPulse* c = *osc;
1564 c->width = width;
1565}
1566
1567void 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. */
1591void tMBSaw_init (tMBSaw* const osc)
1592{
1593 tMBSaw_initToPool(osc, &leaf.mempool);
1594}
1595
1596void tMBSaw_free (tMBSaw* const osc)
1597{
1598 tMBSaw_freeFromPool(osc, &leaf.mempool);
1599}
1600
1601void 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
1613void 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
1624float 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
1641void 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
1650void 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}
LEAF/Src/leaf-physical.c+0−747
@@ -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 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
20void tPluck_init (tPluck* const pl, float lowestFrequency)
21{
22 tPluck_initToPool(pl, lowestFrequency, &leaf.mempool);
23}
24
25void tPluck_free (tPluck* const pl)
26{
27 tPluck_freeFromPool(pl, &leaf.mempool);
28}
29
30void 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
49void 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
62float tPluck_getLastOut (tPluck* const pl)
63{
64 _tPluck* p = *pl;
65 return p->lastOut;
66}
67
68float 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
74void 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.;
90void 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).
99void 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.
110void 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).
128void tPluck_controlChange (tPluck* const pl, int number, float value)
129{
130 return;
131}
132
133void tPluckSampleRateChanged(tPluck* const pl)
134{
135 _tPluck* p = *pl;
136 tPluck_setFrequency(pl, p->lastFreq);
137}
138
139/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tKarplusStrong ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
140void tKarplusStrong_init (tKarplusStrong* const pl, float lowestFrequency)
141{
142 tKarplusStrong_initToPool(pl, lowestFrequency, &leaf.mempool);
143}
144
145void tKarplusStrong_free (tKarplusStrong* const pl)
146{
147 tKarplusStrong_freeFromPool(pl, &leaf.mempool);
148}
149
150void 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
182void 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
200float tKarplusStrong_getLastOut (tKarplusStrong* const pl)
201{
202 _tKarplusStrong* p = *pl;
203 return p->lastOut;
204}
205
206float 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
225void 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.;
243void 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).
250void 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.
261void 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).
283void 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).
310void 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.
322void 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).
332void 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
347void 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
357void 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
364void tSimpleLivingString_free(tSimpleLivingString* const pl)
365{
366 tSimpleLivingString_freeFromPool(pl, &leaf.mempool);
367}
368
369void 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
388void 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
402void 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
412void 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
422void tSimpleLivingString_setDampFreq(tSimpleLivingString* const pl, float dampFreq)
423{
424 _tSimpleLivingString* p = *pl;
425 tOnePole_setFreq(&p->bridgeFilter, dampFreq);
426}
427
428void tSimpleLivingString_setDecay(tSimpleLivingString* const pl, float decay)
429{
430 _tSimpleLivingString* p = *pl;
431 p->decay=decay;
432}
433
434void tSimpleLivingString_setTargetLev(tSimpleLivingString* const pl, float targetLev)
435{
436 _tSimpleLivingString* p = *pl;
437 tFeedbackLeveler_setTargetLevel(&p->fbLev, targetLev);
438}
439
440void tSimpleLivingString_setLevSmoothFactor(tSimpleLivingString* const pl, float levSmoothFactor)
441{
442 _tSimpleLivingString* p = *pl;
443 tFeedbackLeveler_setFactor(&p->fbLev, levSmoothFactor);
444}
445
446void tSimpleLivingString_setLevStrength(tSimpleLivingString* const pl, float levStrength)
447{
448 _tSimpleLivingString* p = *pl;
449 tFeedbackLeveler_setStrength(&p->fbLev, levStrength);
450}
451
452void tSimpleLivingString_setLevMode(tSimpleLivingString* const pl, int levMode)
453{
454 _tSimpleLivingString* p = *pl;
455 tFeedbackLeveler_setMode(&p->fbLev, levMode);
456 p->levMode=levMode;
457}
458
459float 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
471float tSimpleLivingString_sample(tSimpleLivingString* const pl)
472{
473 _tSimpleLivingString* p = *pl;
474 return p->curr;
475}
476
477/* Living String*/
478
479void 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
486void tLivingString_free(tLivingString* const pl)
487{
488 tLivingString_freeFromPool(pl, &leaf.mempool);
489}
490
491void 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
527void 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
550void 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
559void 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
568void 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
577void 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
585void 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
594void tLivingString_setDecay(tLivingString* const pl, float decay)
595{
596 _tLivingString* p = *pl;
597 p->decay=decay;
598}
599
600void 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
607void 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
614void 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
621void 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
629float 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
665float 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
674void 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
682void tReedTable_free (tReedTable* const pm)
683{
684 _tReedTable* p = *pm;
685
686 leaf_free((char*)p);
687}
688
689void 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
698void 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
706float 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
725float 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
737void tReedTable_setOffset (tReedTable* const pm, float offset)
738{
739 _tReedTable* p = *pm;
740 p->offset = offset;
741}
742
743void tReedTable_setSlope (tReedTable* const pm, float slope)
744{
745 _tReedTable* p = *pm;
746 p->slope = slope;
747}
LEAF/Src/leaf-reverb.c+0−925
@@ -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 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
22void 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
58void 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
68void 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
105void 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
116void 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
125void 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
137void tPRCReverb_setMix(tPRCReverb* const rev, float mix)
138{
139 _tPRCReverb* r = *rev;
140 r->mix = mix;
141}
142
143float 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
177void 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 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
184void 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
226void 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
243void 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.

LEAF/Src/leaf-sampling.c+0−866

This diff is large: its 867 lines aren’t shown here.

LEAF/Src/leaf-tables.c+0−14061

This diff is large: its 14062 lines aren’t shown here.

LEAF/Src/leaf.c+0−60

This diff is large: its 61 lines aren’t shown here.

LEAF/leaf.cpp+0−45

This diff is large: its 46 lines aren’t shown here.

LEAF/leaf.h+0−154

This diff is large: its 155 lines aren’t shown here.

LEAF_JUCEPlugin/.DS_Store+0−0

Binary file not shown.

LEAF_JUCEPlugin/LEAF.jucer+59−59

This diff is large: its 126 lines aren’t shown here.

LEAF_JUCEPlugin/Source/.DS_Store+0−0

Binary file not shown.

LEAF_JUCEPlugin/Source/LEAFTest.h+1−1

This diff is large: its 9 lines aren’t shown here.

leaf/.DS_Store+0−0

Binary file not shown.

leaf/Externals/.DS_Store+0−0

Binary file not shown.

leaf/leaf.h+1−1

This diff is large: its 9 lines aren’t shown here.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t