History

fixed linear interpolater, added hermite interpolation, fixed issues in formant shifter

spiricom committed 6 years ago

Commit 765bd481 parent bc99f4832 files · +4769 −2166Browse files

Unified · Split

32 files
  1. .DS_Store +0 −0
  2. LEAF/Inc/leaf-analysis.h +44 −31
  3. LEAF/Inc/leaf-delay.h +97 −45
  4. LEAF/Inc/leaf-distortion.h +49 −44
  5. LEAF/Inc/leaf-dynamics.h +17 −11
  6. LEAF/Inc/leaf-effects.h +72 −53
  7. LEAF/Inc/leaf-electrical.h +16 −12
  8. LEAF/Inc/leaf-envelopes.h +43 −34
  9. LEAF/Inc/leaf-filters.h +115 −90
  10. LEAF/Inc/leaf-global.h +20 −19
  11. LEAF/Inc/leaf-instruments.h +60 −51
  12. LEAF/Inc/leaf-mempool.h +96 −79
  13. LEAF/Inc/leaf-midi.h +24 −20
  14. LEAF/Inc/leaf-oscillators.h +76 −46
  15. LEAF/Inc/leaf-physical.h +69 −48
  16. LEAF/Inc/leaf-reverb.h +19 −12
  17. LEAF/Inc/leaf-sampling.h +29 −26
  18. LEAF/Src/leaf-analysis.c +279 −123
  19. LEAF/Src/leaf-delay.c +396 −42
  20. LEAF/Src/leaf-distortion.c +299 −200
  21. LEAF/Src/leaf-dynamics.c +47 −2
  22. LEAF/Src/leaf-effects.c +816 −529
  23. LEAF/Src/leaf-electrical.c +53 −31
  24. LEAF/Src/leaf-envelopes.c +165 −1
  25. LEAF/Src/leaf-filters.c +551 −283
  26. LEAF/Src/leaf-instruments.c +191 −2
  27. LEAF/Src/leaf-mempool.c +104 −4
  28. LEAF/Src/leaf-midi.c +342 −254
  29. LEAF/Src/leaf-oscillators.c +255 −44
  30. LEAF/Src/leaf-physical.c +194 −8
  31. LEAF/Src/leaf-reverb.c +215 −3
  32. LEAF/Src/leaf-sampling.c +17 −20
.DS_Store+0−0

Binary file not shown.

LEAF/Inc/leaf-analysis.h+44−31
@@ -33,12 +33,14 @@ extern "C" { · 32 unmodified lines
3333
3434 typedef _tEnvelopeFollower* tEnvelopeFollower;
3535
36− void tEnvelopeFollower_init (tEnvelopeFollower* const, float attackThreshold, float decayCoeff);
37− void tEnvelopeFollower_free (tEnvelopeFollower* const);
36+ void tEnvelopeFollower_init (tEnvelopeFollower* const, float attackThreshold, float decayCoeff);
37+ void tEnvelopeFollower_free (tEnvelopeFollower* const);
38+ void tEnvelopeFollower_initToPool (tEnvelopeFollower* const, float attackThreshold, float decayCoeff, tMempool* const);
39+ void tEnvelopeFollower_freeFromPool (tEnvelopeFollower* const, tMempool* const);
3840
39− float tEnvelopeFollower_tick (tEnvelopeFollower* const, float x);
40− int tEnvelopeFollower_decayCoeff (tEnvelopeFollower* const, float decayCoeff);
41− int tEnvelopeFollower_attackThresh (tEnvelopeFollower* const, float attackThresh);
41+ float tEnvelopeFollower_tick (tEnvelopeFollower* const, float x);
42+ int tEnvelopeFollower_decayCoeff (tEnvelopeFollower* const, float decayCoeff);
43+ int tEnvelopeFollower_attackThresh (tEnvelopeFollower* const, float attackThresh);
4244
4345 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
4446
@@ -51,11 +53,14 @@ extern "C" { · 6 unmodified lines
5153
5254 typedef _tPowerFollower* tPowerFollower;
5355
54− void tPowerFollower_init (tPowerFollower* const, float factor);
55− void tPowerFollower_free (tPowerFollower* const);
56− float tPowerFollower_tick (tPowerFollower* const, float input);
57− float tPowerFollower_sample (tPowerFollower* const);
58− int tPowerFollower_setFactor (tPowerFollower* const, float factor);
56+ void tPowerFollower_init (tPowerFollower* const, float factor);
57+ void tPowerFollower_free (tPowerFollower* const);
58+ void tPowerFollower_initToPool (tPowerFollower* const, float factor, tMempool* const);
59+ void tPowerFollower_freeFromPool (tPowerFollower* const, tMempool* const);
60+
61+ float tPowerFollower_tick (tPowerFollower* const, float input);
62+ float tPowerFollower_sample (tPowerFollower* const);
63+ int tPowerFollower_setFactor (tPowerFollower* const, float factor);
5964
6065 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
6166
@@ -81,10 +86,13 @@ extern "C" { · 19 unmodified lines
8186
8287 typedef _tEnvPD* tEnvPD;
8388
84− void tEnvPD_init (tEnvPD* const, int windowSize, int hopSize, int blockSize);
85− void tEnvPD_free (tEnvPD* const);
86− float tEnvPD_tick (tEnvPD* const);
87− void tEnvPD_processBlock (tEnvPD* const, float* in);
89+ void tEnvPD_init (tEnvPD* const, int windowSize, int hopSize, int blockSize);
90+ void tEnvPD_free (tEnvPD* const);
91+ void tEnvPD_initToPool (tEnvPD* const, int windowSize, int hopSize, int blockSize, tMempool* const);
92+ void tEnvPD_freeFromPool (tEnvPD* const, tMempool* const);
93+
94+ float tEnvPD_tick (tEnvPD* const);
95+ void tEnvPD_processBlock (tEnvPD* const, float* in);
8896
8997 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
9098
@@ -117,27 +125,28 @@ extern "C" { · 26 unmodified lines
117125
118126 typedef _tAttackDetection* tAttackDetection;
119127
120− void tAttackDetection_init (tAttackDetection* const, int blocksize);
121− void tAttackDetection_init_expanded (tAttackDetection* const, int blocksize, int atk, int rel);
122− void tAttackDetection_free (tAttackDetection* const);
128+ void tAttackDetection_init (tAttackDetection* const, int blocksize, int atk, int rel);
129+ void tAttackDetection_free (tAttackDetection* const);
130+ void tAttackDetection_initToPool (tAttackDetection* const, int blocksize, int atk, int rel, tMempool* const);
131+ void tAttackDetection_freeFromPool (tAttackDetection* const, tMempool* const);
123132
124133 // set expected input blocksize
125− void tAttackDetection_setBlocksize (tAttackDetection* const, int size);
134+ void tAttackDetection_setBlocksize (tAttackDetection* const, int size);
126135
127136 // change atkDetector sample rate
128− void tAttackDetection_setSamplerate (tAttackDetection* const, int inRate);
137+ void tAttackDetection_setSamplerate (tAttackDetection* const, int inRate);
129138
130139 // set attack time and coeff
131− void tAttackDetection_setAtk (tAttackDetection* const, int inAtk);
140+ void tAttackDetection_setAttack (tAttackDetection* const, int inAtk);
132141
133142 // set release time and coeff
134− void tAttackDetection_setRel (tAttackDetection* const, int inRel);
143+ void tAttackDetection_setRelease (tAttackDetection* const, int inRel);
135144
136145 // set level above which values are identified as attacks
137− void tAttackDetection_setThreshold (tAttackDetection* const, float thres);
146+ void tAttackDetection_setThreshold (tAttackDetection* const, float thres);
138147
139148 // find largest transient in input block, return index of attack
140− int tAttackDetection_detect (tAttackDetection* const, float *in);
149+ int tAttackDetection_detect (tAttackDetection* const, float *in);
141150
142151 //==============================================================================
143152
@@ -168,8 +177,10 @@ extern "C" { · 24 unmodified lines
168177
169178 typedef _tSNAC* tSNAC;
170179
171− void tSNAC_init (tSNAC* const, int overlaparg); // constructor
172− void tSNAC_free (tSNAC* const); // destructor
180+ void tSNAC_init (tSNAC* const, int overlaparg);
181+ void tSNAC_free (tSNAC* const);
182+ void tSNAC_initToPool (tSNAC* const, int overlaparg, tMempool* const);
183+ void tSNAC_freeFromPool (tSNAC* const, tMempool* const);
173184
174185 void tSNAC_ioSamples (tSNAC *s, float *in, float *out, int size);
175186 void tSNAC_setOverlap (tSNAC *s, int lap);
@@ -178,7 +189,7 @@ extern "C" { · 2 unmodified lines
178189
179190 /*To get freq, perform SAMPLE_RATE/snac_getperiod() */
180191 float tSNAC_getPeriod (tSNAC *s);
181− float tSNAC_getfidelity (tSNAC *s);
192+ float tSNAC_getFidelity (tSNAC *s);
182193
183194 #define DEFPITCHRATIO 2.0f
184195 #define DEFTIMECONSTANT 100.0f
@@ -220,12 +231,14 @@ extern "C" { · 35 unmodified lines
220231
221232 typedef _tPeriodDetection* tPeriodDetection;
222233
223− void tPeriodDetection_init (tPeriodDetection* const, float* in, float* out, int bufSize, int frameSize);
224− void tPeriodDetection_free (tPeriodDetection* const);
234+ void tPeriodDetection_init (tPeriodDetection* const, float* in, float* out, int bufSize, int frameSize);
235+ void tPeriodDetection_free (tPeriodDetection* const);
236+ void tPeriodDetection_initToPool (tPeriodDetection* const, float* in, float* out, int bufSize, int frameSize, tMempool* const);
237+ void tPeriodDetection_freeFromPool (tPeriodDetection* const, tMempool* const);
225238
226− float tPeriodDetection_findPeriod (tPeriodDetection* const, float sample);
227− void tPeriodDetection_setHopSize (tPeriodDetection* p, int hs);
228− void tPeriodDetection_setWindowSize (tPeriodDetection* p, int ws);
239+ float tPeriodDetection_findPeriod (tPeriodDetection* const, float sample);
240+ void tPeriodDetection_setHopSize (tPeriodDetection* p, int hs);
241+ void tPeriodDetection_setWindowSize (tPeriodDetection* p, int ws);
229242
230243 //==============================================================================
231244
LEAF/Inc/leaf-delay.h+97−45
@@ -16,6 +16,7 @@ extern "C" { · 15 unmodified lines
1616 //==============================================================================
1717
1818 #include "leaf-math.h"
19+#include "leaf-mempool.h"
1920
2021 //==============================================================================
2122
@@ -35,17 +36,19 @@ extern "C" { · 13 unmodified lines
3536
3637 typedef _tDelay* tDelay;
3738
38− void tDelay_init (tDelay* const, uint32_t delay, uint32_t maxDelay);
39+ void tDelay_init (tDelay* const, uint32_t delay, uint32_t maxDelay);
3940 void tDelay_free (tDelay* const);
40−
41− int tDelay_setDelay (tDelay* const, uint32_t delay);
42− uint32_t tDelay_getDelay (tDelay* const);
43− void tDelay_tapIn (tDelay* const, float in, uint32_t tapDelay);
44− float tDelay_tapOut (tDelay* const, uint32_t tapDelay);
45− float tDelay_addTo (tDelay* const, float value, uint32_t tapDelay);
46− float tDelay_tick (tDelay* const, float sample);
47− float tDelay_getLastOut (tDelay* const);
48− float tDelay_getLastIn (tDelay* const);
41+ void tDelay_initToPool (tDelay* const, uint32_t delay, uint32_t maxDelay, tMempool* const);
42+ void tDelay_freeFromPool (tDelay* const, tMempool* const);
43+
44+ int tDelay_setDelay (tDelay* const, uint32_t delay);
45+ uint32_t tDelay_getDelay (tDelay* const);
46+ void tDelay_tapIn (tDelay* const, float in, uint32_t tapDelay);
47+ float tDelay_tapOut (tDelay* const, uint32_t tapDelay);
48+ float tDelay_addTo (tDelay* const, float value, uint32_t tapDelay);
49+ float tDelay_tick (tDelay* const, float sample);
50+ float tDelay_getLastOut (tDelay* const);
51+ float tDelay_getLastIn (tDelay* const);
4952
5053 //==============================================================================
5154
@@ -69,20 +72,65 @@ extern "C" { · 17 unmodified lines
6972
7073 typedef _tLinearDelay* tLinearDelay;
7174
72− void tLinearDelay_init (tLinearDelay* const, float delay, uint32_t maxDelay);
73− void tLinearDelay_free (tLinearDelay* const);
74−
75− int tLinearDelay_setDelay (tLinearDelay* const, float delay);
76− float tLinearDelay_getDelay (tLinearDelay* const);
77− void tLinearDelay_tapIn (tLinearDelay* const, float in, uint32_t tapDelay);
78− float tLinearDelay_tapOut (tLinearDelay* const, float tapDelay);
79− float tLinearDelay_addTo (tLinearDelay* const, float value, uint32_t tapDelay);
80− float tLinearDelay_tick (tLinearDelay* const, float sample);
81− void tLinearDelay_tickIn (tLinearDelay* const, float input);
82− float tLinearDelay_tickOut (tLinearDelay* const);
83− float tLinearDelay_getLastOut (tLinearDelay* const);
84− float tLinearDelay_getLastIn (tLinearDelay* const);
75+ void tLinearDelay_init (tLinearDelay* const, float delay, uint32_t maxDelay);
76+ void tLinearDelay_free (tLinearDelay* const);
77+ void tLinearDelay_initToPool (tLinearDelay* const, float delay, uint32_t maxDelay, tMempool* const);
78+ void tLinearDelay_freeFromPool(tLinearDelay* const, tMempool* const);
79+ void tLinearDelay_clear (tLinearDelay* const dl);
80+ int tLinearDelay_setDelay (tLinearDelay* const, float delay);
81+ float tLinearDelay_getDelay (tLinearDelay* const);
82+ void tLinearDelay_tapIn (tLinearDelay* const, float in, uint32_t tapDelay);
83+ float tLinearDelay_tapOut (tLinearDelay* const, uint32_t tapDelay);
84+ float tLinearDelay_addTo (tLinearDelay* const, float value, uint32_t tapDelay);
85+ float tLinearDelay_tick (tLinearDelay* const, float sample);
86+ void tLinearDelay_tickIn (tLinearDelay* const, float input);
87+ float tLinearDelay_tickOut (tLinearDelay* const);
88+ float tLinearDelay_getLastOut (tLinearDelay* const);
89+ float tLinearDelay_getLastIn (tLinearDelay* const);
8590
91+
92+
93+ //==============================================================================
94+
95+ /* Hermite-interpolating delay, created by adapting STK linear delay with Hermite interpolation */
96+ typedef struct _tHermiteDelay
97+ {
98+ float gain;
99+ float* buff;
100+
101+ float lastOut, lastIn;
102+
103+ uint32_t inPoint, outPoint;
104+
105+ uint32_t maxDelay;
106+
107+ float delay;
108+
109+ float alpha, omAlpha;
110+
111+ } _tHermiteDelay;
112+
113+ typedef _tHermiteDelay* tHermiteDelay;
114+
115+ void tHermiteDelay_init (tHermiteDelay* const dl, float delay, uint32_t maxDelay);
116+ void tHermiteDelay_free (tHermiteDelay* const dl);
117+ void tHermiteDelay_initToPool (tHermiteDelay* const dl, float delay, uint32_t maxDelay, tMempool* const mp);
118+ void tHermiteDelay_freeFromPool (tHermiteDelay* const dl, tMempool* const mp);
119+ void tHermiteDelay_clear (tHermiteDelay* const dl);
120+ float tHermiteDelay_tick (tHermiteDelay* const dl, float input);
121+ void tHermiteDelay_tickIn (tHermiteDelay* const dl, float input);
122+ float tHermiteDelay_tickOut (tHermiteDelay* const dl);
123+ int tHermiteDelay_setDelay (tHermiteDelay* const dl, float delay);
124+ float tHermiteDelay_tapOut (tHermiteDelay* const dl, uint32_t tapDelay);
125+ void tHermiteDelay_tapIn (tHermiteDelay* const dl, float value, uint32_t tapDelay);
126+ float tHermiteDelay_addTo (tHermiteDelay* const dl, float value, uint32_t tapDelay);
127+ float tHermiteDelay_getDelay (tHermiteDelay* const dl);
128+ float tHermiteDelay_getLastOut (tHermiteDelay* const dl);
129+ float tHermiteDelay_getLastIn (tHermiteDelay* const dl);
130+ void tHermiteDelay_setGain (tHermiteDelay* const dl, float gain);
131+ float tHermiteDelay_getGain (tHermiteDelay* const dl);
132+
133+
86134 //==============================================================================
87135
88136 /* Allpass-interpolating delay, reimplemented from STK (Cook and Scavone). */
@@ -107,17 +155,19 @@ extern "C" { · 18 unmodified lines
107155
108156 typedef _tAllpassDelay* tAllpassDelay;
109157
110− void tAllpassDelay_init (tAllpassDelay* const, float delay, uint32_t maxDelay);
111− void tAllpassDelay_free (tAllpassDelay* const);
158+ void tAllpassDelay_init (tAllpassDelay* const, float delay, uint32_t maxDelay);
159+ void tAllpassDelay_free (tAllpassDelay* const);
160+ void tAllpassDelay_initToPool (tAllpassDelay* const, float delay, uint32_t maxDelay, tMempool* const);
161+ void tAllpassDelay_freeFromPool(tAllpassDelay* const, tMempool* const);
112162
113− int tAllpassDelay_setDelay (tAllpassDelay* const, float delay);
114− float tAllpassDelay_getDelay (tAllpassDelay* const);
115− void tAllpassDelay_tapIn (tAllpassDelay* const, float in, uint32_t tapDelay);
116− float tAllpassDelay_tapOut (tAllpassDelay* const, uint32_t tapDelay);
117− float tAllpassDelay_addTo (tAllpassDelay* const, float value, uint32_t tapDelay);
118− float tAllpassDelay_tick (tAllpassDelay* const, float sample);
119− float tAllpassDelay_getLastOut (tAllpassDelay* const);
120− float tAllpassDelay_getLastIn (tAllpassDelay* const);
163+ int tAllpassDelay_setDelay (tAllpassDelay* const, float delay);
164+ float tAllpassDelay_getDelay (tAllpassDelay* const);
165+ void tAllpassDelay_tapIn (tAllpassDelay* const, float in, uint32_t tapDelay);
166+ float tAllpassDelay_tapOut (tAllpassDelay* const, uint32_t tapDelay);
167+ float tAllpassDelay_addTo (tAllpassDelay* const, float value, uint32_t tapDelay);
168+ float tAllpassDelay_tick (tAllpassDelay* const, float sample);
169+ float tAllpassDelay_getLastOut (tAllpassDelay* const);
170+ float tAllpassDelay_getLastIn (tAllpassDelay* const);
121171
122172 //==============================================================================
123173
@@ -141,18 +191,20 @@ extern "C" { · 17 unmodified lines
141191
142192 typedef _tTapeDelay* tTapeDelay;
143193
144− void tTapeDelay_init (tTapeDelay* const, float delay, uint32_t maxDelay);
145− void tTapeDelay_free (tTapeDelay* const);
146−
147− void tTapeDelay_setDelay (tTapeDelay* const, float delay);
148− float tTapeDelay_getDelay (tTapeDelay* const);
149− void tTapeDelay_tapIn (tTapeDelay* const, float in, uint32_t tapDelay);
150− float tTapeDelay_tapOut (tTapeDelay* const d, float tapDelay);
151− float tTapeDelay_addTo (tTapeDelay* const, float value, uint32_t tapDelay);
152− float tTapeDelay_tick (tTapeDelay* const, float sample);
153− void tTapeDelay_incrementInPoint(tTapeDelay* const dl);
154− float tTapeDelay_getLastOut (tTapeDelay* const);
155− float tTapeDelay_getLastIn (tTapeDelay* const);
194+ void tTapeDelay_init (tTapeDelay* const, float delay, uint32_t maxDelay);
195+ void tTapeDelay_free (tTapeDelay* const);
196+ void tTapeDelay_initToPool (tTapeDelay* const, float delay, uint32_t maxDelay, tMempool* const);
197+ void tTapeDelay_freeFromPool(tTapeDelay* const, tMempool* const);
198+
199+ void tTapeDelay_setDelay (tTapeDelay* const, float delay);
200+ float tTapeDelay_getDelay (tTapeDelay* const);
201+ void tTapeDelay_tapIn (tTapeDelay* const, float in, uint32_t tapDelay);
202+ float tTapeDelay_tapOut (tTapeDelay* const d, float tapDelay);
203+ float tTapeDelay_addTo (tTapeDelay* const, float value, uint32_t tapDelay);
204+ float tTapeDelay_tick (tTapeDelay* const, float sample);
205+ void tTapeDelay_incrementInPoint(tTapeDelay* const dl);
206+ float tTapeDelay_getLastOut (tTapeDelay* const);
207+ float tTapeDelay_getLastIn (tTapeDelay* const);
156208
157209 //==============================================================================
158210
LEAF/Inc/leaf-distortion.h+49−44
@@ -21,6 +21,51 @@ extern "C" { · 20 unmodified lines
2121
2222 //==============================================================================
2323
24+ typedef struct _tSampleReducer
25+ {
26+ float invRatio;
27+ float hold;
28+ uint32_t count;
29+ } _tSampleReducer;
30+
31+ typedef _tSampleReducer* tSampleReducer;
32+
33+ void tSampleReducer_init (tSampleReducer* const);
34+ void tSampleReducer_free (tSampleReducer* const);
35+ void tSampleReducer_initToPool (tSampleReducer* const, tMempool* const);
36+ void tSampleReducer_freeFromPool (tSampleReducer* const, tMempool* const);
37+
38+ float tSampleReducer_tick (tSampleReducer* const, float input);
39+
40+ // sampling ratio
41+ void tSampleReducer_setRatio (tSampleReducer* const, float ratio);
42+
43+ //==============================================================================
44+
45+ typedef struct _tOversampler
46+ {
47+ int ratio;
48+ float* pCoeffs;
49+ float* upState;
50+ float* downState;
51+ int numTaps;
52+ int phaseLength;
53+ } _tOversampler;
54+
55+ typedef _tOversampler* tOversampler;
56+
57+ void tOversampler_init (tOversampler* const, int order, oBool extraQuality);
58+ void tOversampler_free (tOversampler* const);
59+ void tOversampler_initToPool (tOversampler* const, int order, oBool extraQuality, tMempool* const);
60+ void tOversampler_freeFromPool (tOversampler* const, tMempool* const);
61+
62+ void tOversampler_upsample (tOversampler* const, float input, float* output);
63+ float tOversampler_downsample (tOversampler* const os, float* input);
64+ float tOversampler_tick (tOversampler* const, float input, float (*effectTick)(float));
65+ int tOversampler_getLatency (tOversampler* const os);
66+
67+ //==============================================================================
68+
2469 /* tLockhartWavefolder */
2570
2671 typedef struct _tLockhartWavefolder
@@ -49,29 +94,10 @@ extern "C" { · 22 unmodified lines
4994
5095 void tLockhartWavefolder_init (tLockhartWavefolder* const);
5196 void tLockhartWavefolder_free (tLockhartWavefolder* const);
97+ void tLockhartWavefolder_initToPool (tLockhartWavefolder* const, tMempool* const);
98+ void tLockhartWavefolder_freeFromPool (tLockhartWavefolder* const, tMempool* const);
5299
53100 float tLockhartWavefolder_tick (tLockhartWavefolder* const, float samp);
54−
55− //==============================================================================
56−
57−
58−
59− typedef struct _tSampleReducer
60− {
61− float invRatio;
62− float hold;
63− uint32_t count;
64− } _tSampleReducer;
65−
66− typedef _tSampleReducer* tSampleReducer;
67−
68− void tSampleReducer_init (tSampleReducer* const);
69− void tSampleReducer_free (tSampleReducer* const);
70−
71− float tSampleReducer_tick (tSampleReducer* const, float input);
72−
73− // sampling ratio
74− void tSampleReducer_setRatio (tSampleReducer* const, float ratio);
75101
76102 //==============================================================================
77103
@@ -92,6 +118,8 @@ extern "C" { · 14 unmodified lines
92118
93119 void tCrusher_init (tCrusher* const);
94120 void tCrusher_free (tCrusher* const);
121+ void tCrusher_initToPool (tCrusher* const, tMempool* const);
122+ void tCrusher_freeFromPool (tCrusher* const, tMempool* const);
95123
96124 float tCrusher_tick (tCrusher* const, float input);
97125
@@ -107,29 +135,6 @@ extern "C" { · 9 unmodified lines
107135 // sampling ratio
108136 void tCrusher_setSamplingRatio (tCrusher* const, float ratio);
109137
110−
111− //==============================================================================
112−
113−
114− typedef struct _tOversampler
115− {
116− int ratio;
117− float* pCoeffs;
118− float* upState;
119− float* downState;
120− int numTaps;
121− int phaseLength;
122− } _tOversampler;
123−
124− typedef _tOversampler* tOversampler;
125−
126− void tOversampler_init(tOversampler* const, int order, oBool extraQuality);
127− void tOversampler_free(tOversampler* const);
128− void tOversampler_upsample(tOversampler* const, float input, float* output);
129− float tOversampler_downsample(tOversampler* const os, float* input);
130− float tOversampler_tick(tOversampler* const, float input, float (*effectTick)(float));
131− int tOversampler_getLatency(tOversampler* const os);
132−
133138 //==============================================================================
134139
135140 #ifdef __cplusplus
LEAF/Inc/leaf-dynamics.h+17−11
@@ -18,6 +18,7 @@ extern "C" { · 17 unmodified lines
1818
1919 #include "leaf-global.h"
2020 #include "leaf-math.h"
21+#include "leaf-mempool.h"
2122 #include "leaf-analysis.h"
2223
2324 //==============================================================================
@@ -38,9 +39,12 @@ extern "C" { · 14 unmodified lines
3839
3940 typedef _tCompressor* tCompressor;
4041
41− void tCompressor_init (tCompressor* const);
42− void tCompressor_free (tCompressor* const);
43− float tCompressor_tick (tCompressor* const, float input);
42+ void tCompressor_init (tCompressor* const);
43+ void tCompressor_free (tCompressor* const);
44+ void tCompressor_initToPool (tCompressor* const, tMempool* const);
45+ void tCompressor_freeFromPool(tCompressor* const, tMempool* const);
46+
47+ float tCompressor_tick (tCompressor* const, float input);
4448
4549 ///
4650 /* Feedback leveller */
@@ -61,15 +65,17 @@ extern "C" { · 14 unmodified lines
6165
6266 typedef _tFeedbackLeveler* tFeedbackLeveler;
6367
64− void tFeedbackLeveler_init (tFeedbackLeveler* const, float targetLevel, float factor, float strength, int mode);
65− void tFeedbackLeveler_free (tFeedbackLeveler* const);
68+ void tFeedbackLeveler_init (tFeedbackLeveler* const, float targetLevel, float factor, float strength, int mode);
69+ void tFeedbackLeveler_free (tFeedbackLeveler* const);
70+ void tFeedbackLeveler_initToPool (tFeedbackLeveler* const, float targetLevel, float factor, float strength, int mode, tMempool* const);
71+ void tFeedbackLeveler_freeFromPool (tFeedbackLeveler* const, tMempool* const);
6672
67− float tFeedbackLeveler_tick (tFeedbackLeveler* const, float input);
68− float tFeedbackLeveler_sample (tFeedbackLeveler* const);
69− void tFeedbackLeveler_setTargetLevel (tFeedbackLeveler* const, float TargetLevel);
70− void tFeedbackLeveler_setFactor (tFeedbackLeveler* const, float factor);
71− void tFeedbackLeveler_setMode (tFeedbackLeveler* const, int mode); // 0 for upwards limiting only, 1 for biderctional limiting
72− void tFeedbackLeveler_setStrength (tFeedbackLeveler* const, float strength);
73+ float tFeedbackLeveler_tick (tFeedbackLeveler* const, float input);
74+ float tFeedbackLeveler_sample (tFeedbackLeveler* const);
75+ void tFeedbackLeveler_setTargetLevel (tFeedbackLeveler* const, float TargetLevel);
76+ void tFeedbackLeveler_setFactor (tFeedbackLeveler* const, float factor);
77+ void tFeedbackLeveler_setMode (tFeedbackLeveler* const, int mode); // 0 for upwards limiting only, 1 for biderctional limiting
78+ void tFeedbackLeveler_setStrength (tFeedbackLeveler* const, float strength);
7379
7480
7581 //==============================================================================
LEAF/Inc/leaf-effects.h+72−53
@@ -14,9 +14,10 @@ extern "C" { · 13 unmodified lines
1414 #endif
1515
1616 //==============================================================================
17−#include "leaf-dynamics.h"
1817 #include "leaf-global.h"
1918 #include "leaf-math.h"
19+#include "leaf-mempool.h"
20+#include "leaf-dynamics.h"
2021 #include "leaf-analysis.h"
2122
2223 //==============================================================================
@@ -45,14 +46,17 @@ extern "C" { · 22 unmodified lines
4546
4647 typedef _tTalkbox* tTalkbox;
4748
48− void tTalkbox_init (tTalkbox* const, int bufsize);
49− void tTalkbox_free (tTalkbox* const);
50− float tTalkbox_tick (tTalkbox* const, float synth, float voice);
51− void tTalkbox_update (tTalkbox* const);
52− void tTalkbox_suspend (tTalkbox* const);
53− void tTalkbox_lpcDurbin (float *r, int p, float *k, float *g);
54− void tTalkbox_lpc (float *buf, float *car, int32_t n, int32_t o);
55− void tTalkbox_setQuality (tTalkbox* const, float quality);
49+ void tTalkbox_init (tTalkbox* const, int bufsize);
50+ void tTalkbox_free (tTalkbox* const);
51+ void tTalkbox_initToPool (tTalkbox* const, int bufsize, tMempool* const);
52+ void tTalkbox_freeFromPool (tTalkbox* const, tMempool* const);
53+
54+ float tTalkbox_tick (tTalkbox* const, float synth, float voice);
55+ void tTalkbox_update (tTalkbox* const);
56+ void tTalkbox_suspend (tTalkbox* const);
57+ void tTalkbox_lpcDurbin (float *r, int p, float *k, float *g);
58+ void tTalkbox_lpc (float *buf, float *car, int32_t n, int32_t o);
59+ void tTalkbox_setQuality (tTalkbox* const, float quality);
5660
5761 //==============================================================================
5862
@@ -77,11 +81,14 @@ extern "C" { · 18 unmodified lines
7781
7882 typedef _tVocoder* tVocoder;
7983
80− void tVocoder_init (tVocoder* const);
81− void tVocoder_free (tVocoder* const);
82− float tVocoder_tick (tVocoder* const, float synth, float voice);
83− void tVocoder_update (tVocoder* const);
84− void tVocoder_suspend (tVocoder* const);
84+ void tVocoder_init (tVocoder* const);
85+ void tVocoder_free (tVocoder* const);
86+ void tVocoder_initToPool (tVocoder* const, tMempool* const);
87+ void tVocoder_freeFromPool (tVocoder* const, tMempool* const);
88+
89+ float tVocoder_tick (tVocoder* const, float synth, float voice);
90+ void tVocoder_update (tVocoder* const);
91+ void tVocoder_suspend (tVocoder* const);
8592
8693 //==============================================================================
8794
@@ -117,6 +124,9 @@ extern "C" { · 29 unmodified lines
117124
118125 void tSOLAD_init (tSOLAD* const);
119126 void tSOLAD_free (tSOLAD* const);
127+ void tSOLAD_initToPool (tSOLAD* const, tMempool* const);
128+ void tSOLAD_freeFromPool (tSOLAD* const, tMempool* const);
129+
120130 // send one block of input samples, receive one block of output samples
121131 void tSOLAD_ioSamples (tSOLAD *w, float* in, float* out, int blocksize);
122132 // set periodicity analysis data
@@ -151,12 +161,15 @@ extern "C" { · 28 unmodified lines
151161
152162 typedef _tPitchShift* tPitchShift;
153163
154− void tPitchShift_init (tPitchShift* const, tPeriodDetection* const, float* out, int bufSize);
155− void tPitchShift_free (tPitchShift* const);
156− float tPitchShift_shift (tPitchShift* const);
157− float tPitchShift_shiftToFunc (tPitchShift* const, float (*fun)(float));
158− float tPitchShift_shiftToFreq (tPitchShift* const, float freq);
159− void tPitchShift_setPitchFactor (tPitchShift* const, float pf);
164+ void tPitchShift_init (tPitchShift* const, tPeriodDetection* const, float* out, int bufSize);
165+ void tPitchShift_free (tPitchShift* const);
166+ void tPitchShift_initToPool (tPitchShift* const, tPeriodDetection* const, float* out, int bufSize, tMempool* const);
167+ void tPitchShift_freeFromPool (tPitchShift* const, tMempool* const);
168+
169+ float tPitchShift_shift (tPitchShift* const);
170+ float tPitchShift_shiftToFunc (tPitchShift* const, float (*fun)(float));
171+ float tPitchShift_shiftToFreq (tPitchShift* const, float freq);
172+ void tPitchShift_setPitchFactor (tPitchShift* const, float pf);
160173
161174 // Retune
162175 typedef struct _tRetune
@@ -185,18 +198,20 @@ extern "C" { · 22 unmodified lines
185198
186199 typedef _tRetune* tRetune;
187200
188− void tRetune_init (tRetune* const, int numVoices, int bufSize, int frameSize);
189− void tRetune_free (tRetune* const);
190−
191− float* tRetune_tick (tRetune* const, float sample);
192− void tRetune_setNumVoices (tRetune* const, int numVoices);
193− void tRetune_setPitchFactors (tRetune* const, float pf);
194− void tRetune_setPitchFactor (tRetune* const, float pf, int voice);
195− void tRetune_setTimeConstant (tRetune* const, float tc);
196− void tRetune_setHopSize (tRetune* const, int hs);
197− void tRetune_setWindowSize (tRetune* const, int ws);
198− float tRetune_getInputPeriod (tRetune* const);
199− float tRetune_getInputFreq (tRetune* const);
201+ void tRetune_init (tRetune* const, int numVoices, int bufSize, int frameSize);
202+ void tRetune_free (tRetune* const);
203+ void tRetune_initToPool (tRetune* const, int numVoices, int bufSize, int frameSize, tMempool* const);
204+ void tRetune_freeFromPool (tRetune* const, tMempool* const);
205+
206+ float* tRetune_tick (tRetune* const, float sample);
207+ void tRetune_setNumVoices (tRetune* const, int numVoices);
208+ void tRetune_setPitchFactors (tRetune* const, float pf);
209+ void tRetune_setPitchFactor (tRetune* const, float pf, int voice);
210+ void tRetune_setTimeConstant (tRetune* const, float tc);
211+ void tRetune_setHopSize (tRetune* const, int hs);
212+ void tRetune_setWindowSize (tRetune* const, int ws);
213+ float tRetune_getInputPeriod (tRetune* const);
214+ float tRetune_getInputFreq (tRetune* const);
200215
201216 // Autotune
202217 typedef struct _tAutotune
@@ -225,18 +240,20 @@ extern "C" { · 22 unmodified lines
225240
226241 typedef _tAutotune* tAutotune;
227242
228− void tAutotune_init (tAutotune* const, int numVoices, int bufSize, int frameSize);
229− void tAutotune_free (tAutotune* const);
230−
231− float* tAutotune_tick (tAutotune* const, float sample);
232− void tAutotune_setNumVoices (tAutotune* const, int numVoices);
233− void tAutotune_setFreqs (tAutotune* const, float f);
234− void tAutotune_setFreq (tAutotune* const, float f, int voice);
235− void tAutotune_setTimeConstant (tAutotune* const, float tc);
236− void tAutotune_setHopSize (tAutotune* const, int hs);
237− void tAutotune_setWindowSize (tAutotune* const, int ws);
238− float tAutotune_getInputPeriod (tAutotune* const);
239− float tAutotune_getInputFreq (tAutotune* const);
243+ void tAutotune_init (tAutotune* const, int numVoices, int bufSize, int frameSize);
244+ void tAutotune_free (tAutotune* const);
245+ void tAutotune_initToPool (tAutotune* const, int numVoices, int bufSize, int frameSize, tMempool* const);
246+ void tAutotune_freeFromPool (tAutotune* const, tMempool* const);
247+
248+ float* tAutotune_tick (tAutotune* const, float sample);
249+ void tAutotune_setNumVoices (tAutotune* const, int numVoices);
250+ void tAutotune_setFreqs (tAutotune* const, float f);
251+ void tAutotune_setFreq (tAutotune* const, float f, int voice);
252+ void tAutotune_setTimeConstant (tAutotune* const, float tc);
253+ void tAutotune_setHopSize (tAutotune* const, int hs);
254+ void tAutotune_setWindowSize (tAutotune* const, int ws);
255+ float tAutotune_getInputPeriod (tAutotune* const);
256+ float tAutotune_getInputFreq (tAutotune* const);
240257
241258 //==============================================================================
242259
@@ -273,15 +290,17 @@ extern "C" { · 30 unmodified lines
273290
274291 typedef _tFormantShifter* tFormantShifter;
275292
276− void tFormantShifter_init (tFormantShifter* const, int bufsize, int order);
277− void tFormantShifter_free (tFormantShifter* const);
278−
279− float tFormantShifter_tick (tFormantShifter* const, float input);
280− float tFormantShifter_remove (tFormantShifter* const, float input);
281− float tFormantShifter_add (tFormantShifter* const, float input);
282− void tFormantShifter_ioSamples (tFormantShifter* const, float* in, float* out, int size, float fwarp);
283− void tFormantShifter_setShiftFactor (tFormantShifter* const, float shiftFactor);
284− void tFormantShifter_setIntensity (tFormantShifter* const, float intensity);
293+ void tFormantShifter_init (tFormantShifter* const, int bufsize, int order);
294+ void tFormantShifter_free (tFormantShifter* const);
295+ void tFormantShifter_initToPool (tFormantShifter* const, int bufsize, int order, tMempool* const);
296+ void tFormantShifter_freeFromPool (tFormantShifter* const, tMempool* const);
297+
298+ float tFormantShifter_tick (tFormantShifter* const, float input);
299+ float tFormantShifter_remove (tFormantShifter* const, float input);
300+ float tFormantShifter_add (tFormantShifter* const, float input);
301+ void tFormantShifter_ioSamples (tFormantShifter* const, float* in, float* out, int size, float fwarp);
302+ void tFormantShifter_setShiftFactor (tFormantShifter* const, float shiftFactor);
303+ void tFormantShifter_setIntensity (tFormantShifter* const, float intensity);
285304
286305 //==============================================================================
287306
LEAF/Inc/leaf-electrical.h+16−12
@@ -16,6 +16,7 @@ extern "C" { · 15 unmodified lines
1616
1717 #include "leaf-global.h"
1818 #include "leaf-math.h"
19+#include "leaf-mempool.h"
1920
2021 //==============================================================================
2122
@@ -64,21 +65,24 @@ extern "C" { · 42 unmodified lines
6465 };
6566
6667 //WDF Linear Components
67− void tWDF_init(tWDF* const r, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR);
68− void tWDF_free(tWDF* const r);
69− float tWDF_tick(tWDF* const r, float sample, tWDF* const outputPoint, uint8_t paramsChanged);
68+ void tWDF_init (tWDF* const, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR);
69+ void tWDF_free (tWDF* const);
70+ void tWDF_initToPool (tWDF* const, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR, tMempool* const);
71+ void tWDF_freeFromPool (tWDF* const, tMempool* const);
7072
71− void tWDF_setValue(tWDF* const r, float value);
72− void tWDF_setSampleRate(tWDF* const r, float sample_rate);
73− uint8_t tWDF_isLeaf(tWDF* const r);
73+ float tWDF_tick (tWDF* const, float sample, tWDF* const outputPoint, uint8_t paramsChanged);
7474
75− float tWDF_getPortResistance(tWDF* const r);
76− float tWDF_getReflectedWaveUp(tWDF* const r, float input); //for tree, only uses input for resistive source
77− float tWDF_getReflectedWaveDown(tWDF* const r, float input, float incident_wave); //for roots
78− void tWDF_setIncidentWave(tWDF* const r, float incident_wave, float input);
75+ void tWDF_setValue (tWDF* const, float value);
76+ void tWDF_setSampleRate (tWDF* const, float sample_rate);
77+ uint8_t tWDF_isLeaf (tWDF* const);
7978
80− float tWDF_getVoltage(tWDF* const r);
81− float tWDF_getCurrent(tWDF* const r);
79+ float tWDF_getPortResistance (tWDF* const);
80+ float tWDF_getReflectedWaveUp (tWDF* const, float input); //for tree, only uses input for resistive source
81+ float tWDF_getReflectedWaveDown (tWDF* const, float input, float incident_wave); //for roots
82+ void tWDF_setIncidentWave (tWDF* const, float incident_wave, float input);
83+
84+ float tWDF_getVoltage (tWDF* const);
85+ float tWDF_getCurrent (tWDF* const);
8286
8387
8488 //==============================================================================
LEAF/Inc/leaf-envelopes.h+43−34
@@ -18,6 +18,7 @@ extern "C" { · 17 unmodified lines
1818 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
1919
2020 #include "leaf-math.h"
21+#include "leaf-mempool.h"
2122 #include "leaf-filters.h"
2223 #include "leaf-delay.h"
2324
@@ -26,8 +27,8 @@ extern "C" { · 2 unmodified lines
2627 /* Attack-Decay envelope */
2728 typedef struct _tEnvelope {
2829
29− const float *exp_buff;
30− const float *inc_buff;
30+ const float *exp_buff;
31+ const float *inc_buff;
3132 uint32_t buff_size;
3233
3334 float next;
@@ -46,22 +47,24 @@ extern "C" { · 12 unmodified lines
4647
4748 typedef _tEnvelope* tEnvelope;
4849
49− void tEnvelope_init (tEnvelope* const, float attack, float decay, oBool loop);
50− void tEnvelope_free (tEnvelope* const);
50+ void tEnvelope_init (tEnvelope* const, float attack, float decay, oBool loop);
51+ void tEnvelope_free (tEnvelope* const);
52+ void tEnvelope_initToPool (tEnvelope* const, float attack, float decay, oBool loop, tMempool* const);
53+ void tEnvelope_freeFromPool (tEnvelope* const, tMempool* const);
5154
52− float tEnvelope_tick (tEnvelope* const);
53− void tEnvelope_setAttack (tEnvelope* const, float attack);
54− void tEnvelope_setDecay (tEnvelope* const, float decay);
55− void tEnvelope_loop (tEnvelope* const, oBool loop);
56− void tEnvelope_on (tEnvelope* const, float velocity);
55+ float tEnvelope_tick (tEnvelope* const);
56+ void tEnvelope_setAttack (tEnvelope* const, float attack);
57+ void tEnvelope_setDecay (tEnvelope* const, float decay);
58+ void tEnvelope_loop (tEnvelope* const, oBool loop);
59+ void tEnvelope_on (tEnvelope* const, float velocity);
5760
5861 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
5962
6063 /* ADSR */
6164 typedef struct _tADSR
6265 {
63− const float *exp_buff;
64− const float *inc_buff;
66+ const float *exp_buff;
67+ const float *inc_buff;
6568 uint32_t buff_size;
6669
6770 float next;
@@ -78,16 +81,18 @@ extern "C" { · 10 unmodified lines
7881
7982 typedef _tADSR* tADSR;
8083
81− void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release);
82− void tADSR_free (tADSR* const);
84+ void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release);
85+ void tADSR_free (tADSR* const);
86+ void tADSR_initToPool (tADSR* const, float attack, float decay, float sustain, float release, tMempool* const);
87+ void tADSR_freeFromPool (tADSR* const, tMempool* const);
8388
84− float tADSR_tick (tADSR* const);
85− void tADSR_setAttack (tADSR* const, float attack);
86− void tADSR_setDecay (tADSR* const, float decay);
87− void tADSR_setSustain(tADSR* const, float sustain);
88− void tADSR_setRelease(tADSR* const, float release);
89− void tADSR_on (tADSR* const, float velocity);
90− void tADSR_off (tADSR* const);
89+ float tADSR_tick (tADSR* const);
90+ void tADSR_setAttack (tADSR* const, float attack);
91+ void tADSR_setDecay (tADSR* const, float decay);
92+ void tADSR_setSustain (tADSR* const, float sustain);
93+ void tADSR_setRelease (tADSR* const, float release);
94+ void tADSR_on (tADSR* const, float velocity);
95+ void tADSR_off (tADSR* const);
9196
9297 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
9398
@@ -106,14 +111,16 @@ extern "C" { · 12 unmodified lines
106111
107112 typedef _tRamp* tRamp;
108113
109− void tRamp_init (tRamp* const, float time, int samplesPerTick);
110− void tRamp_free (tRamp* const);
114+ void tRamp_init (tRamp* const, float time, int samplesPerTick);
115+ void tRamp_free (tRamp* const);
116+ void tRamp_initToPool (tRamp* const, float time, int samplesPerTick, tMempool* const);
117+ void tRamp_freeFromPool (tRamp* const, tMempool* const);
111118
112− float tRamp_tick (tRamp* const);
113− float tRamp_sample (tRamp* const);
114− void tRamp_setTime (tRamp* const, float time);
115− void tRamp_setDest (tRamp* const, float dest);
116− void tRamp_setVal (tRamp* const, float val);
119+ float tRamp_tick (tRamp* const);
120+ float tRamp_sample (tRamp* const);
121+ void tRamp_setTime (tRamp* const, float time);
122+ void tRamp_setDest (tRamp* const, float dest);
123+ void tRamp_setVal (tRamp* const, float val);
117124
118125 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
119126
@@ -126,14 +133,16 @@ extern "C" { · 6 unmodified lines
126133
127134 typedef _tExpSmooth* tExpSmooth;
128135
129− void tExpSmooth_init (tExpSmooth* const, float val, float factor);
130− void tExpSmooth_free (tExpSmooth* const);
136+ void tExpSmooth_init (tExpSmooth* const, float val, float factor);
137+ void tExpSmooth_free (tExpSmooth* const);
138+ void tExpSmooth_initToPool (tExpSmooth* const, float val, float factor, tMempool* const);
139+ void tExpSmooth_freeFromPool (tExpSmooth* const, tMempool* const);
131140
132− float tExpSmooth_tick (tExpSmooth* const);
133− float tExpSmooth_sample (tExpSmooth* const);
134− void tExpSmooth_setFactor (tExpSmooth* const, float factor);
135− void tExpSmooth_setDest (tExpSmooth* const, float dest);
136− void tExpSmooth_setVal (tExpSmooth* const, float val);
141+ float tExpSmooth_tick (tExpSmooth* const);
142+ float tExpSmooth_sample (tExpSmooth* const);
143+ void tExpSmooth_setFactor (tExpSmooth* const, float factor);
144+ void tExpSmooth_setDest (tExpSmooth* const, float dest);
145+ void tExpSmooth_setVal (tExpSmooth* const, float val);
137146
138147 #ifdef __cplusplus
139148 }
LEAF/Inc/leaf-filters.h+115−90
@@ -16,6 +16,7 @@ extern "C" { · 15 unmodified lines
1616 //==============================================================================
1717
1818 #include "leaf-math.h"
19+#include "leaf-mempool.h"
1920 #include "leaf-delay.h"
2021 #include "leaf-tables.h"
2122
@@ -34,12 +35,14 @@ extern "C" { · 12 unmodified lines
3435
3536 typedef _tAllpass* tAllpass;
3637
37− void tAllpass_init (tAllpass* const, float initDelay, uint32_t maxDelay);
38− void tAllpass_free (tAllpass* const);
38+ void tAllpass_init (tAllpass* const, float initDelay, uint32_t maxDelay);
39+ void tAllpass_free (tAllpass* const);
40+ void tAllpass_initToPool (tAllpass* const, float initDelay, uint32_t maxDelay, tMempool* const);
41+ void tAllpass_freeFromPool (tAllpass* const, tMempool* const);
3942
40− float tAllpass_tick (tAllpass* const, float input);
41− void tAllpass_setGain (tAllpass* const, float gain);
42− void tAllpass_setDelay (tAllpass* const f, float delay);
43+ float tAllpass_tick (tAllpass* const, float input);
44+ void tAllpass_setGain (tAllpass* const, float gain);
45+ void tAllpass_setDelay (tAllpass* const, float delay);
4346
4447
4548 //==============================================================================
@@ -57,16 +60,18 @@ extern "C" { · 11 unmodified lines
5760
5861 typedef _tOnePole* tOnePole;
5962
60− void tOnePole_init (tOnePole* const, float thePole);
61− void tOnePole_free (tOnePole* const);
63+ void tOnePole_init (tOnePole* const, float thePole);
64+ void tOnePole_free (tOnePole* const);
65+ void tOnePole_initToPool (tOnePole* const, float thePole, tMempool* const);
66+ void tOnePole_freeFromPool (tOnePole* const, tMempool* const);
6267
63− float tOnePole_tick (tOnePole* const, float input);
64− void tOnePole_setB0 (tOnePole* const, float b0);
65− void tOnePole_setA1 (tOnePole* const, float a1);
66− void tOnePole_setPole (tOnePole* const, float thePole);
67− void tOnePole_setFreq (tOnePole* const, float freq);
68− void tOnePole_setCoefficients(tOnePole* const, float b0, float a1);
69− void tOnePole_setGain (tOnePole* const, float gain);
68+ float tOnePole_tick (tOnePole* const, float input);
69+ void tOnePole_setB0 (tOnePole* const, float b0);
70+ void tOnePole_setA1 (tOnePole* const, float a1);
71+ void tOnePole_setPole (tOnePole* const, float thePole);
72+ void tOnePole_setFreq (tOnePole* const, float freq);
73+ void tOnePole_setCoefficients(tOnePole* const, float b0, float a1);
74+ void tOnePole_setGain (tOnePole* const, float gain);
7075
7176 //==============================================================================
7277
@@ -86,16 +91,18 @@ extern "C" { · 13 unmodified lines
8691
8792 typedef _tTwoPole* tTwoPole;
8893
89− void tTwoPole_init (tTwoPole* const);
90− void tTwoPole_free (tTwoPole* const);
94+ void tTwoPole_init (tTwoPole* const);
95+ void tTwoPole_free (tTwoPole* const);
96+ void tTwoPole_initToPool (tTwoPole* const, tMempool* const);
97+ void tTwoPole_freeFromPool (tTwoPole* const, tMempool* const);
9198
92− float tTwoPole_tick (tTwoPole* const, float input);
93− void tTwoPole_setB0 (tTwoPole* const, float b0);
94− void tTwoPole_setA1 (tTwoPole* const, float a1);
95− void tTwoPole_setA2 (tTwoPole* const, float a2);
96− void tTwoPole_setResonance (tTwoPole* const, float freq, float radius, oBool normalize);
97− void tTwoPole_setCoefficients(tTwoPole* const, float b0, float a1, float a2);
98− void tTwoPole_setGain (tTwoPole* const, float gain);
99+ float tTwoPole_tick (tTwoPole* const, float input);
100+ void tTwoPole_setB0 (tTwoPole* const, float b0);
101+ void tTwoPole_setA1 (tTwoPole* const, float a1);
102+ void tTwoPole_setA2 (tTwoPole* const, float a2);
103+ void tTwoPole_setResonance (tTwoPole* const, float freq, float radius, oBool normalize);
104+ void tTwoPole_setCoefficients(tTwoPole* const, float b0, float a1, float a2);
105+ void tTwoPole_setGain (tTwoPole* const, float gain);
99106
100107 //==============================================================================
101108
@@ -110,15 +117,18 @@ extern "C" { · 8 unmodified lines
110117
111118 typedef _tOneZero* tOneZero;
112119
113− void tOneZero_init (tOneZero* const, float theZero);
114− void tOneZero_free (tOneZero* const);
115− float tOneZero_tick (tOneZero* const, float input);
116− void tOneZero_setB0 (tOneZero* const, float b0);
117− void tOneZero_setB1 (tOneZero* const, float b1);
118− void tOneZero_setZero (tOneZero* const, float theZero);
119− void tOneZero_setCoefficients(tOneZero* const, float b0, float b1);
120− void tOneZero_setGain (tOneZero* const, float gain);
121− float tOneZero_getPhaseDelay(tOneZero *f, float frequency );
120+ void tOneZero_init (tOneZero* const, float theZero);
121+ void tOneZero_free (tOneZero* const);
122+ void tOneZero_initToPool (tOneZero* const, float theZero, tMempool* const);
123+ void tOneZero_freeFromPool (tOneZero* const, tMempool* const);
124+
125+ float tOneZero_tick (tOneZero* const, float input);
126+ void tOneZero_setB0 (tOneZero* const, float b0);
127+ void tOneZero_setB1 (tOneZero* const, float b1);
128+ void tOneZero_setZero (tOneZero* const, float theZero);
129+ void tOneZero_setCoefficients(tOneZero* const, float b0, float b1);
130+ void tOneZero_setGain (tOneZero* const, float gain);
131+ float tOneZero_getPhaseDelay (tOneZero *f, float frequency );
122132
123133 //==============================================================================
124134
@@ -136,16 +146,18 @@ extern "C" { · 11 unmodified lines
136146
137147 typedef _tTwoZero* tTwoZero;
138148
139− void tTwoZero_init (tTwoZero* const);
140− void tTwoZero_free (tTwoZero* const);
149+ void tTwoZero_init (tTwoZero* const);
150+ void tTwoZero_free (tTwoZero* const);
151+ void tTwoZero_initToPool (tTwoZero* const, tMempool* const);
152+ void tTwoZero_freeFromPool (tTwoZero* const, tMempool* const);
141153
142− float tTwoZero_tick (tTwoZero* const, float input);
143− void tTwoZero_setB0 (tTwoZero* const, float b0);
144− void tTwoZero_setB1 (tTwoZero* const, float b1);
145− void tTwoZero_setB2 (tTwoZero* const, float b2);
146− void tTwoZero_setNotch (tTwoZero* const, float frequency, float radius);
147− void tTwoZero_setCoefficients(tTwoZero* const, float b0, float b1, float b2);
148− void tTwoZero_setGain (tTwoZero* const, float gain);
154+ float tTwoZero_tick (tTwoZero* const, float input);
155+ void tTwoZero_setB0 (tTwoZero* const, float b0);
156+ void tTwoZero_setB1 (tTwoZero* const, float b1);
157+ void tTwoZero_setB2 (tTwoZero* const, float b2);
158+ void tTwoZero_setNotch (tTwoZero* const, float frequency, float radius);
159+ void tTwoZero_setCoefficients(tTwoZero* const, float b0, float b1, float b2);
160+ void tTwoZero_setGain (tTwoZero* const, float gain);
149161
150162 //==============================================================================
151163
@@ -162,17 +174,19 @@ extern "C" { · 10 unmodified lines
162174
163175 typedef _tPoleZero* tPoleZero;
164176
165− void tPoleZero_init (tPoleZero* const);
166− void tPoleZero_free (tPoleZero* const);
177+ void tPoleZero_init (tPoleZero* const);
178+ void tPoleZero_free (tPoleZero* const);
179+ void tPoleZero_initToPool (tPoleZero* const, tMempool* const);
180+ void tPoleZero_freeFromPool (tPoleZero* const, tMempool* const);
167181
168− float tPoleZero_tick (tPoleZero* const, float input);
169− void tPoleZero_setB0 (tPoleZero* const, float b0);
170− void tPoleZero_setB1 (tPoleZero* const, float b1);
171− void tPoleZero_setA1 (tPoleZero* const, float a1);
172− void tPoleZero_setCoefficients (tPoleZero* const, float b0, float b1, float a1);
173− void tPoleZero_setAllpass (tPoleZero* const, float coeff);
174− void tPoleZero_setBlockZero (tPoleZero* const, float thePole);
175− void tPoleZero_setGain (tPoleZero* const, float gain);
182+ float tPoleZero_tick (tPoleZero* const, float input);
183+ void tPoleZero_setB0 (tPoleZero* const, float b0);
184+ void tPoleZero_setB1 (tPoleZero* const, float b1);
185+ void tPoleZero_setA1 (tPoleZero* const, float a1);
186+ void tPoleZero_setCoefficients (tPoleZero* const, float b0, float b1, float a1);
187+ void tPoleZero_setAllpass (tPoleZero* const, float coeff);
188+ void tPoleZero_setBlockZero (tPoleZero* const, float thePole);
189+ void tPoleZero_setGain (tPoleZero* const, float gain);
176190
177191 //==============================================================================
178192
@@ -192,19 +206,21 @@ extern "C" { · 13 unmodified lines
192206
193207 typedef _tBiQuad* tBiQuad;
194208
195− void tBiQuad_init (tBiQuad* const);
196− void tBiQuad_free (tBiQuad* const);
197−
198− float tBiQuad_tick (tBiQuad* const, float input);
199− void tBiQuad_setB0 (tBiQuad* const, float b0);
200− void tBiQuad_setB1 (tBiQuad* const, float b1);
201− void tBiQuad_setB2 (tBiQuad* const, float b2);
202− void tBiQuad_setA1 (tBiQuad* const, float a1);
203− void tBiQuad_setA2 (tBiQuad* const, float a2);
204− void tBiQuad_setNotch (tBiQuad* const, float freq, float radius);
205− void tBiQuad_setResonance (tBiQuad* const, float freq, float radius, oBool normalize);
206− void tBiQuad_setCoefficients(tBiQuad* const, float b0, float b1, float b2, float a1, float a2);
207− void tBiQuad_setGain (tBiQuad* const, float gain);
209+ void tBiQuad_init (tBiQuad* const);
210+ void tBiQuad_free (tBiQuad* const);
211+ void tBiQuad_initToPool (tBiQuad* const, tMempool* const);
212+ void tBiQuad_freeFromPool (tBiQuad* const, tMempool* const);
213+
214+ float tBiQuad_tick (tBiQuad* const, float input);
215+ void tBiQuad_setB0 (tBiQuad* const, float b0);
216+ void tBiQuad_setB1 (tBiQuad* const, float b1);
217+ void tBiQuad_setB2 (tBiQuad* const, float b2);
218+ void tBiQuad_setA1 (tBiQuad* const, float a1);
219+ void tBiQuad_setA2 (tBiQuad* const, float a2);
220+ void tBiQuad_setNotch (tBiQuad* const, float freq, float radius);
221+ void tBiQuad_setResonance (tBiQuad* const, float freq, float radius, oBool normalize);
222+ void tBiQuad_setCoefficients(tBiQuad* const, float b0, float b1, float b2, float a1, float a2);
223+ void tBiQuad_setGain (tBiQuad* const, float gain);
208224
209225 //==============================================================================
210226
@@ -229,12 +245,14 @@ extern "C" { · 18 unmodified lines
229245
230246 typedef _tSVF* tSVF;
231247
232− void tSVF_init (tSVF* const, SVFType type, float freq, float Q);
233− void tSVF_free (tSVF* const);
248+ void tSVF_init (tSVF* const, SVFType type, float freq, float Q);
249+ void tSVF_free (tSVF* const);
250+ void tSVF_initToPool (tSVF* const, SVFType type, float freq, float Q, tMempool* const);
251+ void tSVF_freeFromPool (tSVF* const, tMempool* const);
234252
235− float tSVF_tick (tSVF* const, float v0);
236− void tSVF_setFreq (tSVF* const, float freq);
237− void tSVF_setQ (tSVF* const, float Q);
253+ float tSVF_tick (tSVF* const, float v0);
254+ void tSVF_setFreq (tSVF* const, float freq);
255+ void tSVF_setQ (tSVF* const, float Q);
238256
239257 //==============================================================================
240258
@@ -250,12 +268,14 @@ extern "C" { · 9 unmodified lines
250268
251269 typedef _tEfficientSVF* tEfficientSVF;
252270
253− void tEfficientSVF_init (tEfficientSVF* const, SVFType type, uint16_t controlFreq, float Q);
254− void tEfficientSVF_free (tEfficientSVF* const);
271+ void tEfficientSVF_init (tEfficientSVF* const, SVFType type, uint16_t input, float Q);
272+ void tEfficientSVF_free (tEfficientSVF* const);
273+ void tEfficientSVF_initToPool (tEfficientSVF* const, SVFType type, uint16_t input, float Q, tMempool* const);
274+ void tEfficientSVF_freeFromPool (tEfficientSVF* const, tMempool* const);
255275
256− float tEfficientSVF_tick (tEfficientSVF* const, float v0);
257− void tEfficientSVF_setFreq (tEfficientSVF* const, uint16_t controlFreq);
258− void tEfficientSVF_setQ (tEfficientSVF* const, float Q);
276+ float tEfficientSVF_tick (tEfficientSVF* const, float v0);
277+ void tEfficientSVF_setFreq (tEfficientSVF* const, uint16_t controlFreq);
278+ void tEfficientSVF_setQ (tEfficientSVF* const, float Q);
259279
260280 //==============================================================================
261281
@@ -269,12 +289,14 @@ extern "C" { · 7 unmodified lines
269289
270290 typedef _tHighpass* tHighpass;
271291
272− void tHighpass_init (tHighpass* const, float freq);
273− void tHighpass_free (tHighpass* const);
292+ void tHighpass_init (tHighpass* const, float freq);
293+ void tHighpass_free (tHighpass* const);
294+ void tHighpass_initToPool (tHighpass* const, float freq, tMempool* const);
295+ void tHighpass_freeFromPool (tHighpass* const, tMempool* const);
274296
275− float tHighpass_tick (tHighpass* const, float x);
276− void tHighpass_setFreq (tHighpass* const, float freq);
277− float tHighpass_getFreq (tHighpass* const);
297+ float tHighpass_tick (tHighpass* const, float x);
298+ void tHighpass_setFreq (tHighpass* const, float freq);
299+ float tHighpass_getFreq (tHighpass* const);
278300
279301 //==============================================================================
280302
@@ -295,13 +317,15 @@ extern "C" { · 14 unmodified lines
295317
296318 typedef _tButterworth* tButterworth;
297319
298− void tButterworth_init (tButterworth* const, int N, float f1, float f2);
299− void tButterworth_free (tButterworth* const);
320+ void tButterworth_init (tButterworth* const, int N, float f1, float f2);
321+ void tButterworth_free (tButterworth* const);
322+ void tButterworth_initToPool (tButterworth* const, int N, float f1, float f2, tMempool* const);
323+ void tButterworth_freeFromPool (tButterworth* const, tMempool* const);
300324
301− float tButterworth_tick (tButterworth* const, float input);
302− void tButterworth_setF1 (tButterworth* const, float in);
303− void tButterworth_setF2 (tButterworth* const, float in);
304− void tButterworth_setFreqs (tButterworth* const, float f1, float f2);
325+ float tButterworth_tick (tButterworth* const, float input);
326+ void tButterworth_setF1 (tButterworth* const, float in);
327+ void tButterworth_setF2 (tButterworth* const, float in);
328+ void tButterworth_setFreqs (tButterworth* const, float f1, float f2);
305329
306330 //==============================================================================
307331
@@ -310,16 +334,17 @@ extern "C" { · 2 unmodified lines
310334 float* past;
311335 float* coeff;
312336 int numTaps;
313−
314337 } _tFIR;
315338
316339 typedef _tFIR* tFIR;
317340
318− void tFIR_init (tFIR* const, float* coeffs, int numTaps);
319− void tFIR_free (tFIR* const);
341+ void tFIR_init (tFIR* const, float* coeffs, int numTaps);
342+ void tFIR_free (tFIR* const);
343+ void tFIR_initToPool (tFIR* const, float* coeffs, int numTaps, tMempool* const);
344+ void tFIR_freeFromPool (tFIR* const, tMempool* const);
320345
321− float tFIR_tick (tFIR* const, float input);
322− void tFIR_coeffs (tFIR* const, float in);
346+ float tFIR_tick (tFIR* const, float input);
347+ void tFIR_coeffs (tFIR* const, float in);
323348
324349 //==============================================================================
325350
LEAF/Inc/leaf-global.h+20−19
@@ -1,12 +1,12 @@
11 /*
2− ==============================================================================
3−
4− leaf-global.h
5− Created: 24 Oct 2019 2:24:38pm
6− Author: Matthew Wang
7−
8− ==============================================================================
9−*/
2+ ==============================================================================
3+
4+ leaf-global.h
5+ Created: 24 Oct 2019 2:24:38pm
6+ Author: Matthew Wang
7+
8+ ==============================================================================
9+ */
1010
1111 #ifndef LEAF_GLOBAL_H_INCLUDED
1212 #define LEAF_GLOBAL_H_INCLUDED
@@ -14,17 +14,17 @@ · 1 unmodified line
1414 #ifdef __cplusplus
1515 extern "C" {
1616 #endif
17−
18−typedef struct _LEAF
19−{
20− float sampleRate;
21− float invSampleRate;
22− int blockSize;
23− float twoPiTimesInvSampleRate;
24− float (*random)(void);
25−} LEAF;
26−
27−extern LEAF leaf; // The global instance of LEAF.
17+
18+ typedef struct _LEAF
19+ {
20+ float sampleRate;
21+ float invSampleRate;
22+ int blockSize;
23+ float twoPiTimesInvSampleRate;
24+ float (*random)(void);
25+ } LEAF;
26+
27+ extern LEAF leaf; // The global instance of LEAF.
2828
2929 //==============================================================================
3030
@@ -35,3 +35,4 @@ extern LEAF leaf; // The global instance of LEAF. · 4 unmodified lines
3535 #endif // LEAF_GLOBAL_H_INCLUDED
3636
3737 //==============================================================================
38+
LEAF/Inc/leaf-instruments.h+60−51
@@ -42,16 +42,19 @@ extern "C" { · 41 unmodified lines
4242
4343 typedef _t808Cowbell* t808Cowbell;
4444
45− void t808Cowbell_init (t808Cowbell* const, int useStick);
46− void t808Cowbell_free (t808Cowbell* const);
47− float t808Cowbell_tick (t808Cowbell* const);
48− void t808Cowbell_on (t808Cowbell* const, float vel);
49− void t808Cowbell_setDecay (t808Cowbell* const, float decay);
50− void t808Cowbell_setHighpassFreq (t808Cowbell* const, float freq);
51− void t808Cowbell_setBandpassFreq (t808Cowbell* const, float freq);
52− void t808Cowbell_setFreq (t808Cowbell* const, float freq);
53− void t808Cowbell_setOscMix (t808Cowbell* const, float oscMix);
54− void t808Cowbell_setStick (t808Cowbell* const, int useStick);
45+ void t808Cowbell_init (t808Cowbell* const, int useStick);
46+ void t808Cowbell_free (t808Cowbell* const);
47+ void t808Cowbell_initToPool (t808Cowbell* const, int useStick, tMempool* const);
48+ void t808Cowbell_freeFromPool (t808Cowbell* const, tMempool* const);
49+
50+ float t808Cowbell_tick (t808Cowbell* const);
51+ void t808Cowbell_on (t808Cowbell* const, float vel);
52+ void t808Cowbell_setDecay (t808Cowbell* const, float decay);
53+ void t808Cowbell_setHighpassFreq (t808Cowbell* const, float freq);
54+ void t808Cowbell_setBandpassFreq (t808Cowbell* const, float freq);
55+ void t808Cowbell_setFreq (t808Cowbell* const, float freq);
56+ void t808Cowbell_setOscMix (t808Cowbell* const, float oscMix);
57+ void t808Cowbell_setStick (t808Cowbell* const, int useStick);
5558
5659 //==============================================================================
5760
@@ -78,21 +81,23 @@ extern "C" { · 20 unmodified lines
7881
7982 typedef _t808Hihat* t808Hihat;
8083
81− void t808Hihat_init (t808Hihat* const);
82− void t808Hihat_free (t808Hihat* const);
83−
84− float t808Hihat_tick (t808Hihat* const);
85− void t808Hihat_on (t808Hihat* const, float vel);
86− void t808Hihat_setOscNoiseMix (t808Hihat* const, float oscNoiseMix);
87− void t808Hihat_setDecay (t808Hihat* const, float decay);
88− void t808Hihat_setHighpassFreq (t808Hihat* const, float freq);
89− void t808Hihat_setOscBandpassFreq (t808Hihat* const, float freq);
90− void t808Hihat_setOscBandpassQ (t808Hihat* const hihat, float Q);
91− void t808Hihat_setStickBandPassFreq (t808Hihat* const, float freq);
92− void t808Hihat_setStickBandPassQ (t808Hihat* const hihat, float Q);
93− void t808Hihat_setOscFreq (t808Hihat* const, float freq);
94− void t808Hihat_setStretch (t808Hihat* const hihat, float stretch);
95− void t808Hihat_setFM (t808Hihat* const hihat, float FM_amount);
84+ void t808Hihat_init (t808Hihat* const);
85+ void t808Hihat_free (t808Hihat* const);
86+ void t808Hihat_initToPool (t808Hihat* const, tMempool* const);
87+ void t808Hihat_freeFromPool (t808Hihat* const, tMempool* const);
88+
89+ float t808Hihat_tick (t808Hihat* const);
90+ void t808Hihat_on (t808Hihat* const, float vel);
91+ void t808Hihat_setOscNoiseMix (t808Hihat* const, float oscNoiseMix);
92+ void t808Hihat_setDecay (t808Hihat* const, float decay);
93+ void t808Hihat_setHighpassFreq (t808Hihat* const, float freq);
94+ void t808Hihat_setOscBandpassFreq (t808Hihat* const, float freq);
95+ void t808Hihat_setOscBandpassQ (t808Hihat* const hihat, float Q);
96+ void t808Hihat_setStickBandPassFreq (t808Hihat* const, float freq);
97+ void t808Hihat_setStickBandPassQ (t808Hihat* const hihat, float Q);
98+ void t808Hihat_setOscFreq (t808Hihat* const, float freq);
99+ void t808Hihat_setStretch (t808Hihat* const hihat, float stretch);
100+ void t808Hihat_setFM (t808Hihat* const hihat, float FM_amount);
96101
97102 //==============================================================================
98103
@@ -123,19 +128,21 @@ extern "C" { · 24 unmodified lines
123128
124129 typedef _t808Snare* t808Snare;
125130
126− void t808Snare_init (t808Snare* const);
127− void t808Snare_free (t808Snare* const);
128−
129− float t808Snare_tick (t808Snare* const);
130− void t808Snare_on (t808Snare* const, float vel);
131− void t808Snare_setTone1Freq (t808Snare* const, float freq);
132− void t808Snare_setTone2Freq (t808Snare* const, float freq);
133− void t808Snare_setTone1Decay (t808Snare* const, float decay);
134− void t808Snare_setTone2Decay (t808Snare* const, float decay);
135− void t808Snare_setNoiseDecay (t808Snare* const, float decay);
136− void t808Snare_setToneNoiseMix (t808Snare* const, float toneNoiseMix);
137− void t808Snare_setNoiseFilterFreq (t808Snare* const, float noiseFilterFreq);
138− void t808Snare_setNoiseFilterQ (t808Snare* const, float noiseFilterQ);
131+ void t808Snare_init (t808Snare* const);
132+ void t808Snare_free (t808Snare* const);
133+ void t808Snare_initToPool (t808Snare* const, tMempool* const);
134+ void t808Snare_freeFromPool (t808Snare* const, tMempool* const);
135+
136+ float t808Snare_tick (t808Snare* const);
137+ void t808Snare_on (t808Snare* const, float vel);
138+ void t808Snare_setTone1Freq (t808Snare* const, float freq);
139+ void t808Snare_setTone2Freq (t808Snare* const, float freq);
140+ void t808Snare_setTone1Decay (t808Snare* const, float decay);
141+ void t808Snare_setTone2Decay (t808Snare* const, float decay);
142+ void t808Snare_setNoiseDecay (t808Snare* const, float decay);
143+ void t808Snare_setToneNoiseMix (t808Snare* const, float toneNoiseMix);
144+ void t808Snare_setNoiseFilterFreq (t808Snare* const, float noiseFilterFreq);
145+ void t808Snare_setNoiseFilterQ (t808Snare* const, float noiseFilterQ);
139146
140147 //==============================================================================
141148
@@ -164,19 +171,21 @@ extern "C" { · 22 unmodified lines
164171
165172 typedef _t808Kick* t808Kick;
166173
167− void t808Kick_init (t808Kick* const);
168− void t808Kick_free (t808Kick* const);
169−
170− float t808Kick_tick (t808Kick* const);
171− void t808Kick_on (t808Kick* const, float vel);
172− void t808Kick_setToneFreq (t808Kick* const, float freq);
173− void t808Kick_setToneDecay (t808Kick* const, float decay);
174− void t808Kick_setNoiseDecay (t808Kick* const, float decay);
175− void t808Kick_setSighAmount (t808Kick* const, float sigh);
176− void t808Kick_setChirpAmount (t808Kick* const, float chirp);
177− void t808Kick_setToneNoiseMix (t808Kick* const, float toneNoiseMix);
178− void t808Kick_setNoiseFilterFreq (t808Kick* const, float noiseFilterFreq);
179− void t808Kick_setNoiseFilterQ (t808Kick* const, float noiseFilterQ);
174+ void t808Kick_init (t808Kick* const);
175+ void t808Kick_free (t808Kick* const);
176+ void t808Kick_initToPool (t808Kick* const, tMempool* const);
177+ void t808Kick_freeFromPool (t808Kick* const, tMempool* const);
178+
179+ float t808Kick_tick (t808Kick* const);
180+ void t808Kick_on (t808Kick* const, float vel);
181+ void t808Kick_setToneFreq (t808Kick* const, float freq);
182+ void t808Kick_setToneDecay (t808Kick* const, float decay);
183+ void t808Kick_setNoiseDecay (t808Kick* const, float decay);
184+ void t808Kick_setSighAmount (t808Kick* const, float sigh);
185+ void t808Kick_setChirpAmount (t808Kick* const, float chirp);
186+ void t808Kick_setToneNoiseMix (t808Kick* const, float toneNoiseMix);
187+ void t808Kick_setNoiseFilterFreq (t808Kick* const, float noiseFilterFreq);
188+ void t808Kick_setNoiseFilterQ (t808Kick* const, float noiseFilterQ);
180189
181190 //==============================================================================
182191
LEAF/Inc/leaf-mempool.h+96−79
@@ -1,38 +1,38 @@
11 /*==============================================================================
22
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.
3+ In short, mpool is distributed under so called "BSD license",
334
34− written by C99 style
35−==============================================================================*/
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+ ==============================================================================*/
3636
3737 #ifndef LEAF_MPOOL_H_INCLUDED
3838 #define LEAF_MPOOL_H_INCLUDED
@@ -41,60 +41,76 @@ · 2 unmodified lines
4141 extern "C" {
4242 #endif
4343
44−//==============================================================================
45−
44+ //==============================================================================
45+
4646 #include <stdio.h>
4747 #include <stdlib.h>
4848 #include <string.h>
4949 #include <stdbool.h>
5050
51−//==============================================================================
52−
51+ //==============================================================================
52+
5353 #define MPOOL_ALIGN_SIZE (8)
54−
55−//#define size_t unsigned long
56−
57−/**
58− * memory pool structure
59− */
60−
61−// node of free list
62−typedef struct mpool_node_t {
63− void *pool; // memory pool field
64− struct mpool_node_t *next; // next node pointer
65− struct mpool_node_t *prev; // prev node pointer
66− size_t size;
67−} mpool_node_t;
68−
69−typedef struct mpool_t {
70− void* mpool; // start of the mpool
71− size_t usize; // used size of the pool
72− size_t msize; // max size of the pool
73− mpool_node_t* head; // first node of memory pool free list
74−} mpool_t;
75−
76−void mpool_create (char* memory, size_t size, mpool_t* pool);
77−
78−void *mpool_alloc(size_t size, mpool_t* pool);
79−void mpool_free(void* ptr, mpool_t* pool);
80−
81−size_t mpool_get_size(mpool_t* pool);
82−size_t mpool_get_used(mpool_t* pool);
83−
84−void leaf_pool_init(char* memory, size_t size);
85−
86−void* leaf_alloc(size_t size);
87−void leaf_free(void* ptr);
88−
89−size_t leaf_pool_get_size(void);
90−size_t leaf_pool_get_used(void);
91−
92−void* leaf_pool_get_pool(void);
93−
94−void leaf_mempool_overrun(void);
9554
96−//==============================================================================
97−
55+ //#define size_t unsigned long
56+
57+ /**
58+ * memory pool structure
59+ */
60+
61+ // node of free list
62+ typedef struct mpool_node_t {
63+ void *pool; // memory pool field
64+ struct mpool_node_t *next; // next node pointer
65+ struct mpool_node_t *prev; // prev node pointer
66+ size_t size;
67+ } mpool_node_t;
68+
69+ typedef struct mpool_t {
70+ void* mpool; // start of the mpool
71+ size_t usize; // used size of the pool
72+ size_t msize; // max size of the pool
73+ mpool_node_t* head; // first node of memory pool free list
74+ } mpool_t;
75+
76+ void mpool_create (char* memory, size_t size, mpool_t* pool);
77+
78+ void* mpool_alloc(size_t size, mpool_t* pool);
79+ void* mpool_allocAndClear(size_t asize, mpool_t* pool);
80+ void mpool_free(void* ptr, mpool_t* pool);
81+
82+ size_t mpool_get_size(mpool_t* pool);
83+ size_t mpool_get_used(mpool_t* pool);
84+
85+ void leaf_pool_init(char* memory, size_t size);
86+
87+ void* leaf_alloc(size_t size);
88+ void* leaf_allocAndClear(size_t size);
89+ void leaf_free(void* ptr);
90+
91+ size_t leaf_pool_get_size(void);
92+ size_t leaf_pool_get_used(void);
93+
94+ void* leaf_pool_get_pool(void);
95+
96+ void leaf_mempool_overrun(void);
97+
98+ // User object for creating additional mempools
99+
100+ typedef struct _tMempool
101+ {
102+ mpool_t* pool;
103+ } _tMempool;
104+
105+ typedef _tMempool* tMempool;
106+
107+ void tMempool_init (tMempool* const, char* memory, size_t size);
108+ void tMempool_free (tMempool* const);
109+ void tMempool_initToPool (tMempool* const, char* memory, size_t size, tMempool* const);
110+ void tMempool_freeFromPool (tMempool* const, tMempool* const);
111+
112+ //==============================================================================
113+
98114 #ifdef __cplusplus
99115 }
100116 #endif
@@ -104,3 +120,4 @@ void leaf_mempool_overrun(void); · 3 unmodified lines
104120 //==============================================================================
105121
106122
123+
LEAF/Inc/leaf-midi.h+24−20
@@ -40,6 +40,8 @@ extern "C" { · 39 unmodified lines
4040
4141 void tStack_init (tStack* const);
4242 void tStack_free (tStack* const);
43+ void tStack_initToPool (tStack* const, tMempool* const);
44+ void tStack_freeFromPool (tStack* const, tMempool* const);
4345
4446 void tStack_setCapacity (tStack* const, uint16_t cap);
4547 int tStack_addIfNotAlreadyThere (tStack* const, uint16_t item);
@@ -91,28 +93,30 @@ extern "C" { · 45 unmodified lines
9193 typedef _tPoly* tPoly;
9294
9395 /* MPoly*/
94− void tPoly_init(tPoly* const, int maxNumVoices);
95− void tPoly_free(tPoly* const);
96+ void tPoly_init (tPoly* const, int maxNumVoices);
97+ void tPoly_free (tPoly* const);
98+ void tPoly_initToPool (tPoly* const, int maxNumVoices, tMempool* const);
99+ void tPoly_freeFromPool (tPoly* const, tMempool* const);
96100
97101 //ADDING A NOTE
98− int tPoly_noteOn(tPoly* const, int note, uint8_t vel);
99− int tPoly_noteOff(tPoly* const, uint8_t note);
100− void tPoly_orderedAddToStack(tPoly* const, uint8_t noteVal);
101− void tPoly_setNumVoices(tPoly* const, uint8_t numVoices);
102−
103− void tPoly_setPitchBend(tPoly* const, float pitchBend);
104− void tPoly_setPitchGlideActive(tPoly* const, oBool isActive);
105− void tPoly_setPitchGlideTime(tPoly* const, float t);
106− void tPoly_tickPitch(tPoly* const);
107− void tPoly_tickPitchGlide(tPoly* const);
108− void tPoly_tickPitchBend(tPoly* const);
109−
110− int tPoly_getNumVoices(tPoly* const);
111− int tPoly_getNumActiveVoices(tPoly* const);
112− float tPoly_getPitch(tPoly* const, uint8_t voice);
113− int tPoly_getKey(tPoly* const, uint8_t voice);
114− int tPoly_getVelocity(tPoly* const, uint8_t voice);
115− int tPoly_isOn(tPoly* const, uint8_t voice);
102+ int tPoly_noteOn (tPoly* const, int note, uint8_t vel);
103+ int tPoly_noteOff (tPoly* const, uint8_t note);
104+ void tPoly_orderedAddToStack (tPoly* const, uint8_t noteVal);
105+ void tPoly_setNumVoices (tPoly* const, uint8_t numVoices);
106+
107+ void tPoly_setPitchBend (tPoly* const, float pitchBend);
108+ void tPoly_setPitchGlideActive (tPoly* const, oBool isActive);
109+ void tPoly_setPitchGlideTime (tPoly* const, float t);
110+ void tPoly_tickPitch (tPoly* const);
111+ void tPoly_tickPitchGlide (tPoly* const);
112+ void tPoly_tickPitchBend (tPoly* const);
113+
114+ int tPoly_getNumVoices (tPoly* const);
115+ int tPoly_getNumActiveVoices (tPoly* const);
116+ float tPoly_getPitch (tPoly* const, uint8_t voice);
117+ int tPoly_getKey (tPoly* const, uint8_t voice);
118+ int tPoly_getVelocity (tPoly* const, uint8_t voice);
119+ int tPoly_isOn (tPoly* const, uint8_t voice);
116120
117121 //==============================================================================
118122
LEAF/Inc/leaf-oscillators.h+76−46
@@ -14,6 +14,7 @@ extern "C" { · 13 unmodified lines
1414 //==============================================================================
1515
1616 #include "leaf-math.h"
17+#include "leaf-mempool.h"
1718 #include "leaf-filters.h"
1819
1920 //==============================================================================
@@ -25,13 +26,17 @@ extern "C" { · 5 unmodified lines
2526 float phase;
2627 float inc,freq;
2728
28− } tCycle;
29+ } _tCycle;
2930
30− void tCycle_init (tCycle* const);
31− void tCycle_free (tCycle* const);
31+ typedef _tCycle* tCycle;
3232
33− float tCycle_tick (tCycle* const);
34− int tCycle_setFreq (tCycle* const, float freq);
33+ void tCycle_init (tCycle* const);
34+ void tCycle_free (tCycle* const);
35+ void tCycle_initToPool (tCycle* const, tMempool* const);
36+ void tCycle_freeFromPool (tCycle* const, tMempool* const);
37+
38+ float tCycle_tick (tCycle* const);
39+ int tCycle_setFreq (tCycle* const, float freq);
3540
3641 //==============================================================================
3742
@@ -42,13 +47,17 @@ extern "C" { · 4 unmodified lines
4247 float phase;
4348 float inc,freq;
4449
45− } tTriangle;
50+ } _tTriangle;
51+
52+ typedef _tTriangle* tTriangle;
4653
47− void tTriangle_init (tTriangle* const);
48− void tTriangle_free (tTriangle* const);
54+ void tTriangle_init (tTriangle* const);
55+ void tTriangle_free (tTriangle* const);
56+ void tTriangle_initToPool (tTriangle* const, tMempool* const);
57+ void tTriangle_freeFromPool (tTriangle* const, tMempool* const);
4958
50− float tTriangle_tick (tTriangle* const);
51− int tTriangle_setFreq (tTriangle* const, float freq);
59+ float tTriangle_tick (tTriangle* const);
60+ int tTriangle_setFreq (tTriangle* const, float freq);
5261
5362 //==============================================================================
5463
@@ -59,13 +68,17 @@ extern "C" { · 4 unmodified lines
5968 float phase;
6069 float inc,freq;
6170
62− } tSquare;
71+ } _tSquare;
6372
64− void tSquare_init (tSquare* const);
65− void tSquare_free (tSquare* const);
73+ typedef _tSquare* tSquare;
6674
67− float tSquare_tick (tSquare* const);
68− int tSquare_setFreq (tSquare* const, float freq);
75+ void tSquare_init (tSquare* const);
76+ void tSquare_free (tSquare* const);
77+ void tSquare_initToPool (tSquare* const, tMempool* const);
78+ void tSquare_freeFromPool(tSquare* const, tMempool* const);
79+
80+ float tSquare_tick (tSquare* const);
81+ int tSquare_setFreq (tSquare* const, float freq);
6982
7083 //==============================================================================
7184
@@ -76,13 +89,17 @@ extern "C" { · 4 unmodified lines
7689 float phase;
7790 float inc,freq;
7891
79− } tSawtooth;
92+ } _tSawtooth;
93+
94+ typedef _tSawtooth* tSawtooth;
8095
81− void tSawtooth_init (tSawtooth* const);
82− void tSawtooth_free (tSawtooth* const);
96+ void tSawtooth_init (tSawtooth* const);
97+ void tSawtooth_free (tSawtooth* const);
98+ void tSawtooth_initToPool (tSawtooth* const, tMempool* const);
99+ void tSawtooth_freeFromPool (tSawtooth* const, tMempool* const);
83100
84− float tSawtooth_tick (tSawtooth* const);
85− int tSawtooth_setFreq (tSawtooth* const, float freq);
101+ float tSawtooth_tick (tSawtooth* const);
102+ int tSawtooth_setFreq (tSawtooth* const, float freq);
86103
87104 //==============================================================================
88105
@@ -92,13 +109,17 @@ extern "C" { · 3 unmodified lines
92109 float phase;
93110 float inc,freq;
94111
95− } tPhasor;
112+ } _tPhasor;
96113
97− void tPhasor_init (tPhasor* const);
98− void tPhasor_free (tPhasor* const);
114+ typedef _tPhasor* tPhasor;
99115
100− float tPhasor_tick (tPhasor* const);
101− int tPhasor_setFreq (tPhasor* const, float freq);
116+ void tPhasor_init (tPhasor* const);
117+ void tPhasor_free (tPhasor* const);
118+ void tPhasor_initToPool (tPhasor* const, tMempool* const);
119+ void tPhasor_freeFromPool(tPhasor* const, tMempool* const);
120+
121+ float tPhasor_tick (tPhasor* const);
122+ int tPhasor_setFreq (tPhasor* const, float freq);
102123
103124 //==============================================================================
104125
@@ -116,12 +137,16 @@ extern "C" { · 11 unmodified lines
116137 float pinkb0, pinkb1, pinkb2;
117138 float(*rand)(void);
118139
119− } tNoise;
140+ } _tNoise;
141+
142+ typedef _tNoise* tNoise;
120143
121− void tNoise_init (tNoise* const, NoiseType type);
122− void tNoise_free (tNoise* const);
144+ void tNoise_init (tNoise* const, NoiseType type);
145+ void tNoise_free (tNoise* const);
146+ void tNoise_initToPool (tNoise* const, NoiseType type, tMempool* const);
147+ void tNoise_freeFromPool (tNoise* const, tMempool* const);
123148
124− float tNoise_tick (tNoise* const);
149+ float tNoise_tick (tNoise* const);
125150
126151 //==============================================================================
127152
@@ -149,23 +174,27 @@ extern "C" { · 21 unmodified lines
149174 float V[3];
150175 float P[3];
151176 float gK, gN, gL, C;
152− } tNeuron;
153−
154− void tNeuron_init (tNeuron* const);
155− void tNeuron_free (tNeuron* const);
156−
157− void tNeuron_reset (tNeuron* const);
158− float tNeuron_Tick (tNeuron* const);
159− void tNeuron_setMode (tNeuron* const, NeuronMode mode);
160− void tNeuron_setCurrent (tNeuron* const, float current);
161− void tNeuron_setK (tNeuron* const, float K);
162− void tNeuron_setL (tNeuron* const, float L);
163− void tNeuron_setN (tNeuron* const, float N);
164− void tNeuron_setC (tNeuron* const, float C);
165− void tNeuron_setV1 (tNeuron* const, float V1);
166− void tNeuron_setV2 (tNeuron* const, float V2);
167− void tNeuron_setV3 (tNeuron* const, float V3);
168− void tNeuron_setTimeStep (tNeuron* const, float timestep);
177+ } _tNeuron;
178+
179+ typedef _tNeuron* tNeuron;
180+
181+ void tNeuron_init (tNeuron* const);
182+ void tNeuron_free (tNeuron* const);
183+ void tNeuron_initToPool (tNeuron* const, tMempool* const);
184+ void tNeuron_freeFromPool(tNeuron* const, tMempool* const);
185+
186+ void tNeuron_reset (tNeuron* const);
187+ float tNeuron_tick (tNeuron* const);
188+ void tNeuron_setMode (tNeuron* const, NeuronMode mode);
189+ void tNeuron_setCurrent (tNeuron* const, float current);
190+ void tNeuron_setK (tNeuron* const, float K);
191+ void tNeuron_setL (tNeuron* const, float L);
192+ void tNeuron_setN (tNeuron* const, float N);
193+ void tNeuron_setC (tNeuron* const, float C);
194+ void tNeuron_setV1 (tNeuron* const, float V1);
195+ void tNeuron_setV2 (tNeuron* const, float V2);
196+ void tNeuron_setV3 (tNeuron* const, float V3);
197+ void tNeuron_setTimeStep (tNeuron* const, float timestep);
169198
170199 //==============================================================================
171200
@@ -176,3 +205,4 @@ extern "C" { · 4 unmodified lines
176205 #endif // LEAF_OSCILLATORS_H_INCLUDED
177206
178207 //==============================================================================
208+
LEAF/Inc/leaf-physical.h+69−48
@@ -19,6 +19,7 @@ extern "C" { · 18 unmodified lines
1919
2020 #include "leaf-global.h"
2121 #include "leaf-math.h"
22+#include "leaf-mempool.h"
2223 #include "leaf-delay.h"
2324 #include "leaf-filters.h"
2425 #include "leaf-oscillators.h"
@@ -45,28 +46,30 @@ extern "C" { · 20 unmodified lines
4546
4647 typedef _tPluck* tPluck;
4748
48− void tPluck_init (tPluck* const, float lowestFrequency); //float delayBuff[DELAY_LENGTH]);
49− void tPluck_free (tPluck* const);
49+ void tPluck_init (tPluck* const, float lowestFrequency); //float delayBuff[DELAY_LENGTH]);
50+ void tPluck_free (tPluck* const);
51+ void tPluck_initToPool (tPluck* const, float lowestFrequency, tMempool* const);
52+ void tPluck_freeFromPool (tPluck* const, tMempool* const);
5053
51− float tPluck_tick (tPluck* const);
54+ float tPluck_tick (tPluck* const);
5255
5356 // Pluck the string.
54− void tPluck_pluck (tPluck* const, float amplitude);
57+ void tPluck_pluck (tPluck* const, float amplitude);
5558
5659 // Start a note with the given frequency and amplitude.;
57− void tPluck_noteOn (tPluck* const, float frequency, float amplitude );
60+ void tPluck_noteOn (tPluck* const, float frequency, float amplitude );
5861
5962 // Stop a note with the given amplitude (speed of decay).
60− void tPluck_noteOff (tPluck* const, float amplitude );
63+ void tPluck_noteOff (tPluck* const, float amplitude );
6164
6265 // Set instrument parameters for a particular frequency.
63− void tPluck_setFrequency (tPluck* const, float frequency );
66+ void tPluck_setFrequency (tPluck* const, float frequency );
6467
6568 // Perform the control change specified by \e number and \e value (0.0 - 128.0).
66− void tPluck_controlChange (tPluck* const, int number, float value);
69+ void tPluck_controlChange (tPluck* const, int number, float value);
6770
6871 // tPluck Utilities.
69− float tPluck_getLastOut (tPluck* const);
72+ float tPluck_getLastOut (tPluck* const);
7073
7174 //==============================================================================
7275
@@ -102,38 +105,40 @@ extern "C" { · 29 unmodified lines
102105
103106 typedef _tKarplusStrong* tKarplusStrong;
104107
105− void tKarplusStrong_init (tKarplusStrong* const, float lowestFrequency); // float delayBuff[2][DELAY_LENGTH]);
106− void tKarplusStrong_free (tKarplusStrong* const);
108+ void tKarplusStrong_init (tKarplusStrong* const, float lowestFrequency); // float delayBuff[2][DELAY_LENGTH]);
109+ void tKarplusStrong_free (tKarplusStrong* const);
110+ void tKarplusStrong_initToPool (tKarplusStrong* const, float lowestFrequency, tMempool* const);
111+ void tKarplusStrong_freeFromPool (tKarplusStrong* const, tMempool* const);
107112
108− float tKarplusStrong_tick (tKarplusStrong* const);
113+ float tKarplusStrong_tick (tKarplusStrong* const);
109114
110115 // Pluck the string.
111− void tKarplusStrong_pluck (tKarplusStrong* const, float amplitude);
116+ void tKarplusStrong_pluck (tKarplusStrong* const, float amplitude);
112117
113118 // Start a note with the given frequency and amplitude.;
114− void tKarplusStrong_noteOn (tKarplusStrong* const, float frequency, float amplitude );
119+ void tKarplusStrong_noteOn (tKarplusStrong* const, float frequency, float amplitude );
115120
116121 // Stop a note with the given amplitude (speed of decay).
117− void tKarplusStrong_noteOff (tKarplusStrong* const, float amplitude );
122+ void tKarplusStrong_noteOff (tKarplusStrong* const, float amplitude );
118123
119124 // Set instrument parameters for a particular frequency.
120− void tKarplusStrong_setFrequency (tKarplusStrong* const, float frequency );
125+ void tKarplusStrong_setFrequency (tKarplusStrong* const, float frequency );
121126
122127 // Perform the control change specified by \e number and \e value (0.0 - 128.0).
123128 // Use SKPickPosition, SKStringDamping, or SKDetune for type.
124− void tKarplusStrong_controlChange (tKarplusStrong* const, SKControlType type, float value);
129+ void tKarplusStrong_controlChange (tKarplusStrong* const, SKControlType type, float value);
125130
126131 // Set the stretch "factor" of the string (0.0 - 1.0).
127− void tKarplusStrong_setStretch (tKarplusStrong* const, float stretch );
132+ void tKarplusStrong_setStretch (tKarplusStrong* const, float stretch );
128133
129134 // Set the pluck or "excitation" position along the string (0.0 - 1.0).
130− void tKarplusStrong_setPickupPosition (tKarplusStrong* const, float position );
135+ void tKarplusStrong_setPickupPosition (tKarplusStrong* const, float position );
131136
132137 // Set the base loop gain.
133− void tKarplusStrong_setBaseLoopGain (tKarplusStrong* const, float aGain );
138+ void tKarplusStrong_setBaseLoopGain (tKarplusStrong* const, float aGain );
134139
135140 // tKarplusStrong utilities.
136− float tKarplusStrong_getLastOut (tKarplusStrong* const);
141+ float tKarplusStrong_getLastOut (tKarplusStrong* const);
137142
138143 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
139144
@@ -153,18 +158,25 @@ extern "C" { · 13 unmodified lines
153158
154159 typedef _tSimpleLivingString* tSimpleLivingString;
155160
156− void tSimpleLivingString_init (tSimpleLivingString* const, float freq, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode);
157− void tSimpleLivingString_free (tSimpleLivingString* const);
158− float tSimpleLivingString_tick (tSimpleLivingString* const, float input);
159− float tSimpleLivingString_sample (tSimpleLivingString* const);
160− void tSimpleLivingString_setFreq (tSimpleLivingString* const, float freq);
161− void tSimpleLivingString_setWaveLength (tSimpleLivingString* const, float waveLength); // in samples
162− void tSimpleLivingString_setDampFreq (tSimpleLivingString* const, float dampFreq);
163− void tSimpleLivingString_setDecay (tSimpleLivingString* const, float decay); // should be near 1.0
161+ void tSimpleLivingString_init (tSimpleLivingString* const, float freq, float dampFreq,
162+ float decay, float targetLev, float levSmoothFactor,
163+ float levStrength, int levMode);
164+ void tSimpleLivingString_free (tSimpleLivingString* const);
165+ void tSimpleLivingString_initToPool (tSimpleLivingString* const, float freq, float dampFreq,
166+ float decay, float targetLev, float levSmoothFactor,
167+ float levStrength, int levMode, tMempool* const);
168+ void tSimpleLivingString_freeFromPool (tSimpleLivingString* const, tMempool* const);
169+
170+ float tSimpleLivingString_tick (tSimpleLivingString* const, float input);
171+ float tSimpleLivingString_sample (tSimpleLivingString* const);
172+ void tSimpleLivingString_setFreq (tSimpleLivingString* const, float freq);
173+ void tSimpleLivingString_setWaveLength (tSimpleLivingString* const, float waveLength); // in samples
174+ void tSimpleLivingString_setDampFreq (tSimpleLivingString* const, float dampFreq);
175+ void tSimpleLivingString_setDecay (tSimpleLivingString* const, float decay); // should be near 1.0
164176 void tSimpleLivingString_setTargetLev (tSimpleLivingString* const, float targetLev);
165177 void tSimpleLivingString_setLevSmoothFactor (tSimpleLivingString* const, float levSmoothFactor);
166− void tSimpleLivingString_setLevStrength (tSimpleLivingString* const, float levStrength);
167− void tSimpleLivingString_setLevMode (tSimpleLivingString* const, int levMode);
178+ void tSimpleLivingString_setLevStrength (tSimpleLivingString* const, float levStrength);
179+ void tSimpleLivingString_setLevMode (tSimpleLivingString* const, int levMode);
168180
169181 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
170182
@@ -186,19 +198,25 @@ extern "C" { · 15 unmodified lines
186198
187199 typedef _tLivingString* tLivingString;
188200
189− void tLivingString_init (tLivingString* const, float freq, float pickPos, float prepIndex, float dampFreq, float decay,
190− float targetLev, float levSmoothFactor, float levStrength, int levMode);
191− void tLivingString_free (tLivingString* const);
192− float tLivingString_tick (tLivingString* const, float input);
193− float tLivingString_sample (tLivingString* const);
201+ void tLivingString_init (tLivingString* const, float freq, float pickPos, float prepIndex,
202+ float dampFreq, float decay, float targetLev, float levSmoothFactor,
203+ float levStrength, int levMode);
204+ void tLivingString_free (tLivingString* const);
205+ void tLivingString_initToPool (tLivingString* const, float freq, float pickPos, float prepIndex,
206+ float dampFreq, float decay, float targetLev, float levSmoothFactor,
207+ float levStrength, int levMode, tMempool* const);
208+ void tLivingString_freeFromPool (tLivingString* const, tMempool* const);
209+
210+ float tLivingString_tick (tLivingString* const, float input);
211+ float tLivingString_sample (tLivingString* const);
194212 void tLivingString_setFreq (tLivingString* const, float freq);
195− void tLivingString_setWaveLength (tLivingString* const, float waveLength); // in samples
196− void tLivingString_setPickPos (tLivingString* const, float pickPos);
197− void tLivingString_setPrepIndex (tLivingString* const, float prepIndex);
213+ void tLivingString_setWaveLength (tLivingString* const, float waveLength); // in samples
214+ void tLivingString_setPickPos (tLivingString* const, float pickPos);
215+ void tLivingString_setPrepIndex (tLivingString* const, float prepIndex);
198216 void tLivingString_setDampFreq (tLivingString* const, float dampFreq);
199− void tLivingString_setDecay (tLivingString* const, float decay); // should be near 1.0
200− void tLivingString_setTargetLev (tLivingString* const, float targetLev);
201− void tLivingString_setLevSmoothFactor (tLivingString* const, float levSmoothFactor);
217+ void tLivingString_setDecay (tLivingString* const, float decay); // should be near 1.0
218+ void tLivingString_setTargetLev (tLivingString* const, float targetLev);
219+ void tLivingString_setLevSmoothFactor (tLivingString* const, float levSmoothFactor);
202220 void tLivingString_setLevStrength (tLivingString* const, float levStrength);
203221 void tLivingString_setLevMode (tLivingString* const, int levMode);
204222
@@ -211,12 +229,15 @@ extern "C" { · 6 unmodified lines
211229
212230 typedef _tReedTable* tReedTable;
213231
214− void tReedTable_init (tReedTable* const, float offset, float slope);
215− void tReedTable_free (tReedTable* const);
216− float tReedTable_tick (tReedTable* const, float input);
217− float tReedTable_tanh_tick (tReedTable* const p, float input); //tanh softclip version of reed table - replacing the hard clip in original stk code
218− void tReedTable_setOffset (tReedTable* const, float offset);
219− void tReedTable_setSlope (tReedTable* const, float slope);
232+ void tReedTable_init (tReedTable* const, float offset, float slope);
233+ void tReedTable_free (tReedTable* const);
234+ void tReedTable_initToPool (tReedTable* const, float offset, float slope, tMempool* const);
235+ void tReedTable_freeFromPool (tReedTable* const, tMempool* const);
236+
237+ float tReedTable_tick (tReedTable* const, float input);
238+ float tReedTable_tanh_tick (tReedTable* const, float input); //tanh softclip version of reed table - replacing the hard clip in original stk code
239+ void tReedTable_setOffset (tReedTable* const, float offset);
240+ void tReedTable_setSlope (tReedTable* const, float slope);
220241
221242 //==============================================================================
222243
LEAF/Inc/leaf-reverb.h+19−12
@@ -17,6 +17,7 @@ extern "C" { · 16 unmodified lines
1717
1818 #include "leaf-global.h"
1919 #include "leaf-math.h"
20+#include "leaf-mempool.h"
2021 #include "leaf-delay.h"
2122 #include "leaf-filters.h"
2223 #include "leaf-oscillators.h"
@@ -41,16 +42,18 @@ extern "C" { · 18 unmodified lines
4142
4243 typedef _tPRCReverb* tPRCReverb;
4344
44− void tPRCReverb_init (tPRCReverb* const, float t60);
45− void tPRCReverb_free (tPRCReverb* const);
45+ void tPRCReverb_init (tPRCReverb* const, float t60);
46+ void tPRCReverb_free (tPRCReverb* const);
47+ void tPRCReverb_initToPool (tPRCReverb* const, float t60, tMempool* const);
48+ void tPRCReverb_freeFromPool (tPRCReverb* const, tMempool* const);
4649
47− float tPRCReverb_tick (tPRCReverb* const, float input);
50+ float tPRCReverb_tick (tPRCReverb* const, float input);
4851
4952 // Set reverb time in seconds.
50− void tPRCReverb_setT60 (tPRCReverb* const, float t60);
53+ void tPRCReverb_setT60 (tPRCReverb* const, float t60);
5154
5255 // Set mix between dry input and wet output signal.
53− void tPRCReverb_setMix (tPRCReverb* const, float mix);
56+ void tPRCReverb_setMix (tPRCReverb* const, float mix);
5457
5558 //==============================================================================
5659
@@ -73,17 +76,19 @@ extern "C" { · 16 unmodified lines
7376
7477 typedef _tNReverb* tNReverb;
7578
76− void tNReverb_init (tNReverb* const, float t60);
77− void tNReverb_free (tNReverb* const);
79+ void tNReverb_init (tNReverb* const, float t60);
80+ void tNReverb_free (tNReverb* const);
81+ void tNReverb_initToPool (tNReverb* const, float t60, tMempool* const);
82+ void tNReverb_freeFromPool (tNReverb* const, tMempool* const);
7883
79− float tNReverb_tick (tNReverb* const, float input);
80− void tNReverb_tickStereo(tNReverb* const rev, float input, float* output);
84+ float tNReverb_tick (tNReverb* const, float input);
85+ void tNReverb_tickStereo (tNReverb* const rev, float input, float* output);
8186
8287 // Set reverb time in seconds.
83− void tNReverb_setT60 (tNReverb* const, float t60);
88+ void tNReverb_setT60 (tNReverb* const, float t60);
8489
8590 // Set mix between dry input and wet output signal.
86− void tNReverb_setMix (tNReverb* const, float mix);
91+ void tNReverb_setMix (tNReverb* const, float mix);
8792
8893 //==============================================================================
8994
@@ -135,11 +140,13 @@ extern "C" { · 45 unmodified lines
135140
136141 void tDattorroReverb_init (tDattorroReverb* const);
137142 void tDattorroReverb_free (tDattorroReverb* const);
143+ void tDattorroReverb_initToPool (tDattorroReverb* const, tMempool* const);
144+ void tDattorroReverb_freeFromPool (tDattorroReverb* const, tMempool* const);
138145
139146 float tDattorroReverb_tick (tDattorroReverb* const, float input);
140147 void tDattorroReverb_tickStereo (tDattorroReverb* const rev, float input, float* output);
141148 void tDattorroReverb_setMix (tDattorroReverb* const, float mix);
142− void tDattorroReverb_setFreeze (tDattorroReverb* const rev, uint32_t freeze);
149+ void tDattorroReverb_setFreeze (tDattorroReverb* const rev, uint32_t freeze);
143150 void tDattorroReverb_setHP (tDattorroReverb* const, float freq);
144151 void tDattorroReverb_setSize (tDattorroReverb* const, float size);
145152 void tDattorroReverb_setInputDelay (tDattorroReverb* const, float preDelay);
LEAF/Inc/leaf-sampling.h+29−26
@@ -18,6 +18,7 @@ extern "C" { · 17 unmodified lines
1818
1919 #include "leaf-global.h"
2020 #include "leaf-math.h"
21+#include "leaf-mempool.h"
2122 #include "leaf-envelopes.h"
2223 #include "leaf-mempool.h"
2324
@@ -45,27 +46,27 @@ extern "C" { · 21 unmodified lines
4546
4647 typedef _tBuffer* tBuffer;
4748
48− void tBuffer_init (tBuffer* const, uint32_t length);
49− void tBuffer_init_locate (tBuffer* const sb, uint32_t length, mpool_t* pool);
50− void tBuffer_free (tBuffer* const);
51− void tBuffer_free_locate (tBuffer* const sb, mpool_t* pool);
49+ void tBuffer_init (tBuffer* const, uint32_t length);
50+ void tBuffer_free (tBuffer* const);
51+ void tBuffer_initToPool (tBuffer* const, uint32_t length, tMempool* const);
52+ void tBuffer_freeFromPool (tBuffer* const, tMempool* const);
5253
53− void tBuffer_tick (tBuffer* const, float sample);
54+ void tBuffer_tick (tBuffer* const, float sample);
5455
55− void tBuffer_read(tBuffer* const, float* buff, uint32_t len);
56+ void tBuffer_read (tBuffer* const, float* buff, uint32_t len);
5657
57− float tBuffer_get (tBuffer* const, int idx);
58+ float tBuffer_get (tBuffer* const, int idx);
5859
59− void tBuffer_record (tBuffer* const);
60− void tBuffer_stop (tBuffer* const);
61− int tBuffer_getRecordPosition(tBuffer* const);
60+ void tBuffer_record (tBuffer* const);
61+ void tBuffer_stop (tBuffer* const);
62+ int tBuffer_getRecordPosition (tBuffer* const);
6263
63− void tBuffer_setRecordMode (tBuffer* const, RecordMode mode);
64+ void tBuffer_setRecordMode (tBuffer* const, RecordMode mode);
6465
65− void tBuffer_clear (tBuffer* const);
66+ void tBuffer_clear (tBuffer* const);
6667
67− uint32_t tBuffer_getBufferLength(tBuffer* const);
68− uint32_t tBuffer_getRecordedLength(tBuffer* const sb);
68+ uint32_t tBuffer_getBufferLength (tBuffer* const);
69+ uint32_t tBuffer_getRecordedLength (tBuffer* const sb);
6970
7071 //==============================================================================
7172
@@ -106,26 +107,28 @@ extern "C" { · 34 unmodified lines
106107
107108 typedef _tSampler* tSampler;
108109
109− void tSampler_init (tSampler* const, tBuffer* const);
110− void tSampler_free (tSampler* const);
110+ void tSampler_init (tSampler* const, tBuffer* const);
111+ void tSampler_free (tSampler* const);
112+ void tSampler_initToPool (tSampler* const, tBuffer* const, tMempool* const);
113+ void tSampler_freeFromPool (tSampler* const, tMempool* const);
111114
112− float tSampler_tick (tSampler* const);
115+ float tSampler_tick (tSampler* const);
113116
114− void tSampler_setSample (tSampler* const, tBuffer* const);
117+ void tSampler_setSample (tSampler* const, tBuffer* const);
115118
116− void tSampler_setMode (tSampler* const, PlayMode mode);
119+ void tSampler_setMode (tSampler* const, PlayMode mode);
117120
118− void tSampler_play (tSampler* const);
119− void tSampler_stop (tSampler* const);
121+ void tSampler_play (tSampler* const);
122+ void tSampler_stop (tSampler* const);
120123
121− void tSampler_setStart (tSampler* const, int32_t start);
122− void tSampler_setEnd (tSampler* const, int32_t end);
124+ void tSampler_setStart (tSampler* const, int32_t start);
125+ void tSampler_setEnd (tSampler* const, int32_t end);
123126
124− static void handleStartEndChange(tSampler* const sp);
127+ static void handleStartEndChange (tSampler* const sp);
125128
126− void tSampler_setCrossfadeLength (tSampler* const sp, uint32_t length);
129+ void tSampler_setCrossfadeLength (tSampler* const sp, uint32_t length);
127130
128− void tSampler_setRate (tSampler* const, float rate);
131+ void tSampler_setRate (tSampler* const, float rate);
129132
130133 //==============================================================================
131134
LEAF/Src/leaf-analysis.c+279−123
@@ -38,6 +38,24 @@ void tEnvelopeFollower_free(tEnvelopeFollower* const ef) · 37 unmodified lines
3838 leaf_free(e);
3939 }
4040
41+void tEnvelopeFollower_initToPool (tEnvelopeFollower* const ef, float attackThreshold, float decayCoeff, tMempool* const mp)
42+{
43+ _tMempool* m = *mp;
44+ _tEnvelopeFollower* e = *ef = (_tEnvelopeFollower*) mpool_alloc(sizeof(_tEnvelopeFollower), m->pool);
45+
46+ e->y = 0.0f;
47+ e->a_thresh = attackThreshold;
48+ e->d_coeff = decayCoeff;
49+}
50+
51+void tEnvelopeFollower_freeFromPool (tEnvelopeFollower* const ef, tMempool* const mp)
52+{
53+ _tMempool* m = *mp;
54+ _tEnvelopeFollower* e = *ef;
55+
56+ mpool_free(e, m->pool);
57+}
58+
4159 float tEnvelopeFollower_tick(tEnvelopeFollower* const ef, float x)
4260 {
4361 _tEnvelopeFollower* e = *ef;
@@ -68,9 +86,6 @@ int tEnvelopeFollower_attackThresh(tEnvelopeFollower* const ef, float attack · 24 unmodified lines
6886 }
6987
7088
71−
72−
73−
7489 //===========================================================================
7590 /* Power Follower */
7691 //===========================================================================
@@ -90,6 +105,24 @@ void tPowerFollower_free(tPowerFollower* const pf) · 13 unmodified lines
90105 leaf_free(p);
91106 }
92107
108+void tPowerFollower_initToPool (tPowerFollower* const pf, float factor, tMempool* const mp)
109+{
110+ _tMempool* m = *mp;
111+ _tPowerFollower* p = *pf = (_tPowerFollower*) mpool_alloc(sizeof(_tPowerFollower), m->pool);
112+
113+ p->curr=0.0f;
114+ p->factor=factor;
115+ p->oneminusfactor=1.0f-factor;
116+}
117+
118+void tPowerFollower_freeFromPool (tPowerFollower* const pf, tMempool* const mp)
119+{
120+ _tMempool* m = *mp;
121+ _tPowerFollower* p = *pf;
122+
123+ mpool_free(p, m->pool);
124+}
125+
93126 int tPowerFollower_setFactor(tPowerFollower* const pf, float factor)
94127 {
95128 _tPowerFollower* p = *pf;
@@ -123,7 +156,57 @@ float tPowerFollower_sample(tPowerFollower* const pf) · 27 unmodified lines
123156
124157 void tEnvPD_init(tEnvPD* const xpd, int ws, int hs, int bs)
125158 {
126− _tEnvPD* x = *xpd = (_tEnvPD*) leaf_alloc(sizeof(_tEnvPD));
159+ _tEnvPD* x = *xpd = (_tEnvPD*) leaf_allocAndClear(sizeof(_tEnvPD));
160+
161+ int period = hs, npoints = ws;
162+
163+ int i;
164+
165+ if (npoints < 1) npoints = 1024;
166+ if (period < 1) period = npoints/2;
167+ if (period < npoints / MAXOVERLAP + 1)
168+ period = npoints / MAXOVERLAP + 1;
169+
170+ x->x_npoints = npoints;
171+ x->x_phase = 0;
172+ x->x_period = period;
173+
174+ x->windowSize = npoints;
175+ x->hopSize = period;
176+ x->blockSize = bs;
177+
178+ for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0.0f;
179+ for (i = 0; i < npoints; i++)
180+ x->buf[i] = (1.0f - cosf((TWO_PI * i) / npoints))/npoints;
181+ for (; i < npoints+INITVSTAKEN; i++) x->buf[i] = 0.0f;
182+
183+ x->x_f = 0.0f;
184+
185+ x->x_allocforvs = INITVSTAKEN;
186+
187+ // ~ ~ ~ dsp ~ ~ ~
188+ if (x->x_period % x->blockSize)
189+ {
190+ x->x_realperiod = x->x_period + x->blockSize - (x->x_period % x->blockSize);
191+ }
192+ else
193+ {
194+ x->x_realperiod = x->x_period;
195+ }
196+ // ~ ~ ~ ~ ~ ~ ~ ~
197+}
198+
199+void tEnvPD_free (tEnvPD* const xpd)
200+{
201+ _tEnvPD* x = *xpd;
202+
203+ leaf_free(x);
204+}
205+
206+void tEnvPD_initToPool (tEnvPD* const xpd, int ws, int hs, int bs, tMempool* const mp)
207+{
208+ _tMempool* m = *mp;
209+ _tEnvPD* x = *xpd = (_tEnvPD*) mpool_alloc(sizeof(_tEnvPD), m->pool);
127210
128211 int period = hs, npoints = ws;
129212
@@ -163,11 +246,12 @@ void tEnvPD_init(tEnvPD* const xpd, int ws, int hs, int bs) · 33 unmodified lines
163246 // ~ ~ ~ ~ ~ ~ ~ ~
164247 }
165248
166−void tEnvPD_free (tEnvPD* const xpd)
249+void tEnvPD_freeFromPool (tEnvPD* const xpd, tMempool* const mp)
167250 {
251+ _tMempool* m = *mp;
168252 _tEnvPD* x = *xpd;
169253
170− leaf_free(x);
254+ mpool_free(x, m->pool);
171255 }
172256
173257 float tEnvPD_tick (tEnvPD* const xpd)
@@ -222,25 +306,34 @@ static void atkdtk_envelope(tAttackDetection* const a, float *in); · 48 unmodified lines
222306
223307 /********Constructor/Destructor***************/
224308
225−void tAttackDetection_init(tAttackDetection* const ad, int blocksize)
309+void tAttackDetection_init(tAttackDetection* const ad, int blocksize, int atk, int rel)
226310 {
227311 *ad = (_tAttackDetection*) leaf_alloc(sizeof(_tAttackDetection));
228312
229− atkdtk_init(ad, blocksize, DEFATTACK, DEFRELEASE);
313+ atkdtk_init(ad, blocksize, atk, rel);
230314 }
231315
232−void tAttackDetection_init_expanded(tAttackDetection* const ad, int blocksize, int atk, int rel)
316+void tAttackDetection_free(tAttackDetection* const ad)
233317 {
234− *ad = (_tAttackDetection*) leaf_alloc(sizeof(_tAttackDetection));
318+ _tAttackDetection* a = *ad;
319+
320+ leaf_free(a);
321+}
322+
323+void tAttackDetection_initToPool (tAttackDetection* const ad, int blocksize, int atk, int rel, tMempool* const mp)
324+{
325+ _tMempool* m = *mp;
326+ *ad = (_tAttackDetection*) mpool_alloc(sizeof(_tAttackDetection), m->pool);
235327
236328 atkdtk_init(ad, blocksize, atk, rel);
237329 }
238330
239−void tAttackDetection_free(tAttackDetection* const ad)
331+void tAttackDetection_freeFromPool (tAttackDetection* const ad, tMempool* const mp)
240332 {
333+ _tMempool* m = *mp;
241334 _tAttackDetection* a = *ad;
242335
243− leaf_free(a);
336+ mpool_free(a, m->pool);
244337 }
245338
246339 /*******Public Functions***********/
@@ -265,8 +358,8 @@ void tAttackDetection_setSamplerate(tAttackDetection* const ad, int inRate) · 18 unmodified lines
265358 a->samplerate = inRate;
266359
267360 //Reset atk and rel to recalculate coeff
268− tAttackDetection_setAtk(ad, a->atk);
269− tAttackDetection_setRel(ad, a->rel);
361+ tAttackDetection_setAttack(ad, a->atk);
362+ tAttackDetection_setRelease(ad, a->rel);
270363 }
271364
272365 void tAttackDetection_setThreshold(tAttackDetection* const ad, float thres)
@@ -275,14 +368,14 @@ void tAttackDetection_setThreshold(tAttackDetection* const ad, float thres) · 2 unmodified lines
275368 a->threshold = thres;
276369 }
277370
278−void tAttackDetection_setAtk(tAttackDetection* const ad, int inAtk)
371+void tAttackDetection_setAttack(tAttackDetection* const ad, int inAtk)
279372 {
280373 _tAttackDetection* a = *ad;
281374 a->atk = inAtk;
282375 a->atk_coeff = pow(0.01, 1.0/(a->atk * a->samplerate * 0.001));
283376 }
284377
285−void tAttackDetection_setRel(tAttackDetection* const ad, int inRel)
378+void tAttackDetection_setRelease(tAttackDetection* const ad, int inRel)
286379 {
287380 _tAttackDetection* a = *ad;
288381 a->rel = inRel;
@@ -322,8 +415,8 @@ static void atkdtk_init(tAttackDetection* const ad, int blocksize, int atk, int · 33 unmodified lines
322415
323416 a->env = 0;
324417
325− tAttackDetection_setAtk(ad, atk);
326− tAttackDetection_setRel(ad, rel);
418+ tAttackDetection_setAttack(ad, atk);
419+ tAttackDetection_setRelease(ad, rel);
327420 }
328421
329422 static void atkdtk_envelope(tAttackDetection* const ad, float *in)
@@ -343,98 +436,6 @@ static void atkdtk_envelope(tAttackDetection* const ad, float *in) · 13 unmodified lines
343436
344437 }
345438
346−//===========================================================================
347−// PERIODDETECTION
348−//===========================================================================
349−void tPeriodDetection_init (tPeriodDetection* const pd, float* in, float* out, int bufSize, int frameSize)
350−{
351− _tPeriodDetection* p = *pd = (_tPeriodDetection*) leaf_alloc(sizeof(_tPeriodDetection));
352−
353− p->inBuffer = in;
354− p->outBuffer = out;
355− p->bufSize = bufSize;
356− p->frameSize = frameSize;
357− p->framesPerBuffer = p->bufSize / p->frameSize;
358− p->curBlock = 1;
359− p->lastBlock = 0;
360− p->index = 0;
361−
362− p->hopSize = DEFHOPSIZE;
363− p->windowSize = DEFWINDOWSIZE;
364− p->fba = FBA;
365−
366− tEnvPD_init(&p->env, p->windowSize, p->hopSize, p->frameSize);
367−
368− tSNAC_init(&p->snac, DEFOVERLAP);
369−
370− p->timeConstant = DEFTIMECONSTANT;
371− p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant);
372−}
373−
374−void tPeriodDetection_free (tPeriodDetection* const pd)
375−{
376− _tPeriodDetection* p = *pd;
377−
378− tEnvPD_free(&p->env);
379− tSNAC_free(&p->snac);
380− leaf_free(p);
381−}
382−
383−float tPeriodDetection_findPeriod (tPeriodDetection* pd, float sample)
384−{
385− _tPeriodDetection* p = *pd;
386−
387− int i, iLast;
388−
389− i = (p->curBlock*p->frameSize);
390− iLast = (p->lastBlock*p->frameSize)+p->index;
391−
392− p->i = i;
393− p->iLast = iLast;
394−
395− p->inBuffer[i+p->index] = sample;
396−
397− p->index++;
398− p->indexstore = p->index;
399− if (p->index >= p->frameSize)
400− {
401− p->index = 0;
402−
403− tEnvPD_processBlock(&p->env, &(p->inBuffer[i]));
404−
405− tSNAC_ioSamples(&p->snac, &(p->inBuffer[i]), &(p->outBuffer[i]), p->frameSize);
406− p->period = tSNAC_getPeriod(&p->snac);
407−
408− p->curBlock++;
409− if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0;
410− p->lastBlock++;
411− if (p->lastBlock >= p->framesPerBuffer) p->lastBlock = 0;
412− }
413−
414− // changed from period to p->period
415− return p->period;
416−}
417−
418−void tPeriodDetection_setHopSize(tPeriodDetection* pd, int hs)
419−{
420− _tPeriodDetection* p = *pd;
421− p->hopSize = hs;
422−}
423−
424−void tPeriodDetection_setWindowSize(tPeriodDetection* pd, int ws)
425−{
426− _tPeriodDetection* p = *pd;
427− p->windowSize = ws;
428−}
429−
430−
431−
432−
433−
434−
435−
436−
437−
438439 //===========================================================================
439440 // SNAC
440441 //===========================================================================
@@ -461,7 +462,7 @@ static float snac_spectralpeak(tSNAC* const s, float periodlength); · 20 unmodified lines
461462
462463 void tSNAC_init(tSNAC* const snac, int overlaparg)
463464 {
464− _tSNAC* s = *snac = (_tSNAC*) leaf_alloc(sizeof(_tSNAC));
465+ _tSNAC* s = *snac = (_tSNAC*) leaf_allocAndClear(sizeof(_tSNAC));
465466
466467 s->biasfactor = DEFBIAS;
467468 s->timeindex = 0;
@@ -471,10 +472,10 @@ void tSNAC_init(tSNAC* const snac, int overlaparg) · 3 unmodified lines
471472 s->minrms = DEFMINRMS;
472473 s->framesize = SNAC_FRAME_SIZE;
473474
474− s->inputbuf = (float*) leaf_alloc(sizeof(float) * SNAC_FRAME_SIZE);
475− s->processbuf = (float*) leaf_alloc(sizeof(float) * (SNAC_FRAME_SIZE * 2));
476− s->spectrumbuf = (float*) leaf_alloc(sizeof(float) * (SNAC_FRAME_SIZE / 2));
477− s->biasbuf = (float*) leaf_alloc(sizeof(float) * SNAC_FRAME_SIZE);
475+ s->inputbuf = (float*) leaf_allocAndClear(sizeof(float) * SNAC_FRAME_SIZE);
476+ s->processbuf = (float*) leaf_allocAndClear(sizeof(float) * (SNAC_FRAME_SIZE * 2));
477+ s->spectrumbuf = (float*) leaf_allocAndClear(sizeof(float) * (SNAC_FRAME_SIZE / 2));
478+ s->biasbuf = (float*) leaf_allocAndClear(sizeof(float) * SNAC_FRAME_SIZE);
478479
479480 snac_biasbuf(snac);
480481 tSNAC_setOverlap(snac, overlaparg);
@@ -490,6 +491,41 @@ void tSNAC_free(tSNAC* const snac) · 9 unmodified lines
490491 leaf_free(s->biasbuf);
491492 leaf_free(s);
492493 }
494+
495+void tSNAC_initToPool (tSNAC* const snac, int overlaparg, tMempool* const mp)
496+{
497+ _tMempool* m = *mp;
498+ _tSNAC* s = *snac = (_tSNAC*) mpool_alloc(sizeof(_tSNAC), m->pool);
499+
500+ s->biasfactor = DEFBIAS;
501+ s->timeindex = 0;
502+ s->periodindex = 0;
503+ s->periodlength = 0.;
504+ s->fidelity = 0.;
505+ s->minrms = DEFMINRMS;
506+ s->framesize = SNAC_FRAME_SIZE;
507+
508+ s->inputbuf = (float*) mpool_allocAndClear(sizeof(float) * SNAC_FRAME_SIZE, m->pool);
509+ s->processbuf = (float*) mpool_allocAndClear(sizeof(float) * (SNAC_FRAME_SIZE * 2), m->pool);
510+ s->spectrumbuf = (float*) mpool_allocAndClear(sizeof(float) * (SNAC_FRAME_SIZE / 2), m->pool);
511+ s->biasbuf = (float*) mpool_allocAndClear(sizeof(float) * SNAC_FRAME_SIZE, m->pool);
512+
513+ snac_biasbuf(snac);
514+ tSNAC_setOverlap(snac, overlaparg);
515+}
516+
517+void tSNAC_freeFromPool (tSNAC* const snac, tMempool* const mp)
518+{
519+ _tMempool* m = *mp;
520+ _tSNAC* s = *snac;
521+
522+ mpool_free(s->inputbuf, m->pool);
523+ mpool_free(s->processbuf, m->pool);
524+ mpool_free(s->spectrumbuf, m->pool);
525+ mpool_free(s->biasbuf, m->pool);
526+ mpool_free(s, m->pool);
527+}
528+
493529 /******************************************************************************/
494530 /************************** public access functions****************************/
495531 /******************************************************************************/
@@ -737,17 +773,17 @@ static float snac_spectralpeak(tSNAC* const snac, float periodlength) · 241 unmodified lines
737773 {
738774 _tSNAC* s = *snac;
739775
740− if(periodlength < 4.) return periodlength;
776+ if(periodlength < 4.0f) return periodlength;
741777
742778 float max = 0.;
743779 int n, startbin, stopbin, peakbin = 0;
744780 int spectrumsize = s->framesize>>1;
745781 float *spectrumbuf = s->spectrumbuf;
746− float peaklocation = (float)(s->framesize * 2.) / periodlength;
782+ float peaklocation = (float)(s->framesize * 2.0f) / periodlength;
747783
748− startbin = (int)(peaklocation * 0.8 + 0.5);
784+ startbin = (int)(peaklocation * 0.8f + 0.5f);
749785 if(startbin < 1) startbin = 1;
750− stopbin = (int)(peaklocation * 1.25 + 0.5);
786+ stopbin = (int)(peaklocation * 1.25f + 0.5f);
751787 if(stopbin >= spectrumsize - 1) stopbin = spectrumsize - 1;
752788
753789 for(n=startbin; n<stopbin; n++)
@@ -768,7 +804,7 @@ static float snac_spectralpeak(tSNAC* const snac, float periodlength) · 14 unmodified lines
768804 // calculate amplitudes in peak region
769805 for(n=(peakbin-1); n<(peakbin+2); n++)
770806 {
771− spectrumbuf[n] = sqrt(spectrumbuf[n]);
807+ spectrumbuf[n] = sqrtf(spectrumbuf[n]);
772808 }
773809
774810 peaklocation = (float)peakbin + interpolate3phase(spectrumbuf, peakbin);
@@ -785,17 +821,137 @@ static void snac_biasbuf(tSNAC* const snac) · 10 unmodified lines
785821
786822 int n;
787823 int maxperiod = (int)(s->framesize * (float)SEEK);
788− float bias = s->biasfactor / log((float)(maxperiod - 4));
824+ float bias = s->biasfactor / logf((float)(maxperiod - 4));
789825 float *biasbuf = s->biasbuf;
790826
791827 for(n=0; n<5; n++) // periods < 5 samples can't be tracked
792828 {
793− biasbuf[n] = 0.;
829+ biasbuf[n] = 0.0f;
794830 }
795831
796832 for(n=5; n<maxperiod; n++)
797833 {
798− biasbuf[n] = 1.0f - (float)log(n - 4) * bias;
834+ biasbuf[n] = 1.0f - (float)logf(n - 4) * bias;
835+ }
836+}
837+
838+//===========================================================================
839+// PERIODDETECTION
840+//===========================================================================
841+void tPeriodDetection_init (tPeriodDetection* const pd, float* in, float* out, int bufSize, int frameSize)
842+{
843+ _tPeriodDetection* p = *pd = (_tPeriodDetection*) leaf_allocAndClear(sizeof(_tPeriodDetection));
844+
845+ p->inBuffer = in;
846+ p->outBuffer = out;
847+ p->bufSize = bufSize;
848+ p->frameSize = frameSize;
849+ p->framesPerBuffer = p->bufSize / p->frameSize;
850+ p->curBlock = 1;
851+ p->lastBlock = 0;
852+ p->index = 0;
853+
854+ p->hopSize = DEFHOPSIZE;
855+ p->windowSize = DEFWINDOWSIZE;
856+ p->fba = FBA;
857+
858+ tEnvPD_init(&p->env, p->windowSize, p->hopSize, p->frameSize);
859+
860+ tSNAC_init(&p->snac, DEFOVERLAP);
861+
862+ p->timeConstant = DEFTIMECONSTANT;
863+ p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant);
864+}
865+
866+void tPeriodDetection_free (tPeriodDetection* const pd)
867+{
868+ _tPeriodDetection* p = *pd;
869+
870+ tEnvPD_free(&p->env);
871+ tSNAC_free(&p->snac);
872+ leaf_free(p);
873+}
874+
875+void tPeriodDetection_initToPool (tPeriodDetection* const pd, float* in, float* out, int bufSize, int frameSize, tMempool* const mp)
876+{
877+ _tMempool* m = *mp;
878+ _tPeriodDetection* p = *pd = (_tPeriodDetection*) mpool_alloc(sizeof(_tPeriodDetection), m->pool);
879+
880+ p->inBuffer = in;
881+ p->outBuffer = out;
882+ p->bufSize = bufSize;
883+ p->frameSize = frameSize;
884+ p->framesPerBuffer = p->bufSize / p->frameSize;
885+ p->curBlock = 1;
886+ p->lastBlock = 0;
887+ p->index = 0;
888+
889+ p->hopSize = DEFHOPSIZE;
890+ p->windowSize = DEFWINDOWSIZE;
891+ p->fba = FBA;
892+
893+ tEnvPD_initToPool(&p->env, p->windowSize, p->hopSize, p->frameSize, mp);
894+
895+ tSNAC_initToPool(&p->snac, DEFOVERLAP, mp);
896+
897+ p->timeConstant = DEFTIMECONSTANT;
898+ p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant);
899+}
900+
901+void tPeriodDetection_freeFromPool (tPeriodDetection* const pd, tMempool* const mp)
902+{
903+ _tMempool* m = *mp;
904+ _tPeriodDetection* p = *pd;
905+
906+ tEnvPD_freeFromPool(&p->env, mp);
907+ tSNAC_freeFromPool(&p->snac, mp);
908+ mpool_free(p, m->pool);
909+}
910+
911+float tPeriodDetection_findPeriod (tPeriodDetection* pd, float sample)
912+{
913+ _tPeriodDetection* p = *pd;
914+
915+ int i, iLast;
916+
917+ i = (p->curBlock*p->frameSize);
918+ iLast = (p->lastBlock*p->frameSize)+p->index;
919+
920+ p->i = i;
921+ p->iLast = iLast;
922+
923+ p->inBuffer[i+p->index] = sample;
924+
925+ p->index++;
926+ p->indexstore = p->index;
927+ if (p->index >= p->frameSize)
928+ {
929+ p->index = 0;
930+
931+ tEnvPD_processBlock(&p->env, &(p->inBuffer[i]));
932+
933+ tSNAC_ioSamples(&p->snac, &(p->inBuffer[i]), &(p->outBuffer[i]), p->frameSize);
934+ p->period = tSNAC_getPeriod(&p->snac);
935+
936+ p->curBlock++;
937+ if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0;
938+ p->lastBlock++;
939+ if (p->lastBlock >= p->framesPerBuffer) p->lastBlock = 0;
799940 }
941+
942+ // changed from period to p->period
943+ return p->period;
944+}
945+
946+void tPeriodDetection_setHopSize(tPeriodDetection* pd, int hs)
947+{
948+ _tPeriodDetection* p = *pd;
949+ p->hopSize = hs;
950+}
951+
952+void tPeriodDetection_setWindowSize(tPeriodDetection* pd, int ws)
953+{
954+ _tPeriodDetection* p = *pd;
955+ p->windowSize = ws;
800956 }
801957
LEAF/Src/leaf-delay.c+396−42
@@ -19,7 +19,7 @@ · 18 unmodified lines
1919 #endif
2020
2121 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Delay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
22−void tDelay_init (tDelay* const dl, uint32_t delay, uint32_t maxDelay)
22+void tDelay_init (tDelay* const dl, uint32_t delay, uint32_t maxDelay)
2323 {
2424 _tDelay* d = *dl = (_tDelay*) leaf_alloc(sizeof(_tDelay));
2525
@@ -48,6 +48,37 @@ void tDelay_free(tDelay* const dl) · 22 unmodified lines
4848 leaf_free(d);
4949 }
5050
51+void tDelay_initToPool (tDelay* const dl, uint32_t delay, uint32_t maxDelay, tMempool* const mp)
52+{
53+ _tMempool* m = *mp;
54+ _tDelay* d = *dl = (_tDelay*) mpool_alloc(sizeof(_tDelay), m->pool);
55+
56+ d->maxDelay = maxDelay;
57+
58+ d->delay = delay;
59+
60+ d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m->pool);
61+
62+ d->inPoint = 0;
63+ d->outPoint = 0;
64+
65+ d->lastIn = 0.0f;
66+ d->lastOut = 0.0f;
67+
68+ d->gain = 1.0f;
69+
70+ tDelay_setDelay(dl, d->delay);
71+}
72+
73+void tDelay_freeFromPool (tDelay* const dl, tMempool* const mp)
74+{
75+ _tMempool* m = *mp;
76+ _tDelay* d = *dl;
77+
78+ mpool_free(d->buff, m->pool);
79+ mpool_free(d, m->pool);
80+}
81+
5182 float tDelay_tick (tDelay* const dl, float input)
5283 {
5384 _tDelay* d = *dl;
@@ -177,6 +208,51 @@ void tLinearDelay_free(tLinearDelay* const dl) · 123 unmodified lines
177208 leaf_free(d);
178209 }
179210
211+void tLinearDelay_initToPool (tLinearDelay* const dl, float delay, uint32_t maxDelay, tMempool* const mp)
212+{
213+ _tMempool* m = *mp;
214+ _tLinearDelay* d = *dl = (_tLinearDelay*) mpool_alloc(sizeof(_tLinearDelay), m->pool);
215+
216+ d->maxDelay = maxDelay;
217+
218+ if (delay > maxDelay) d->delay = maxDelay;
219+ else if (delay < 0.0f) d->delay = 0.0f;
220+ else d->delay = delay;
221+
222+ d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m->pool);
223+
224+ d->gain = 1.0f;
225+
226+ d->lastIn = 0.0f;
227+ d->lastOut = 0.0f;
228+
229+ d->inPoint = 0;
230+ d->outPoint = 0;
231+
232+ tLinearDelay_setDelay(dl, d->delay);
233+}
234+
235+void tLinearDelay_freeFromPool(tLinearDelay* const dl, tMempool* const mp)
236+{
237+ _tMempool* m = *mp;
238+ _tLinearDelay* d = *dl;
239+
240+ mpool_free(d->buff, m->pool);
241+ mpool_free(d, m->pool);
242+}
243+
244+
245+void tLinearDelay_clear(tLinearDelay* const dl)
246+{
247+ _tLinearDelay* d = *dl;
248+ for (int i = 0; i < d->maxDelay; i++)
249+ {
250+ d->buff[i] = 0;
251+ }
252+
253+
254+}
255+
180256 float tLinearDelay_tick (tLinearDelay* const dl, float input)
181257 {
182258 _tLinearDelay* d = *dl;
@@ -186,15 +262,15 @@ float tLinearDelay_tick (tLinearDelay* const dl, float input) · 3 unmodified lines
186262 // Increment input pointer modulo length.
187263 if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0;
188264
189−
190265 uint32_t idx = (uint32_t) d->outPoint;
191−
192− d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay],
193− d->buff[idx],
194− d->buff[(idx + 1) % d->maxDelay],
195− d->buff[(idx + 2) % d->maxDelay],
196− d->alpha);
197−
266+ // First 1/2 of interpolation
267+ d->lastOut = d->buff[idx] * d->omAlpha;
268+ // Second 1/2 of interpolation
269+ if ((idx + 1) < d->maxDelay)
270+ d->lastOut += d->buff[idx+1] * d->alpha;
271+ else
272+ d->lastOut += d->buff[0] * d->alpha;
273+
198274 // Increment output pointer modulo length
199275 if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0;
200276
@@ -215,18 +291,19 @@ float tLinearDelay_tickOut (tLinearDelay* const dl) · 14 unmodified lines
215291 {
216292 _tLinearDelay* d = *dl;
217293
218− uint32_t idx = (uint32_t) d->outPoint;
219−
220− d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay],
221− d->buff[idx],
222− d->buff[(idx + 1) % d->maxDelay],
223− d->buff[(idx + 2) % d->maxDelay],
224− d->alpha);
294+ uint32_t idx = (uint32_t) d->outPoint;
295+ // First 1/2 of interpolation
296+ d->lastOut = d->buff[idx] * d->omAlpha;
297+ // Second 1/2 of interpolation
298+ if ((idx + 1) < d->maxDelay)
299+ d->lastOut += d->buff[idx+1] * d->alpha;
300+ else
301+ d->lastOut += d->buff[0] * d->alpha;
225302
226− // Increment output pointer modulo length
227− if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0;
303+ // Increment output pointer modulo length
304+ if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0;
228305
229− return d->lastOut;
306+ return d->lastOut;
230307 }
231308
232309 int tLinearDelay_setDelay (tLinearDelay* const dl, float delay)
@@ -250,38 +327,22 @@ int tLinearDelay_setDelay (tLinearDelay* const dl, float delay) · 17 unmodified lines
250327 return 0;
251328 }
252329
253−float tLinearDelay_tapOut (tLinearDelay* const dl, float tapDelay)
330+float tLinearDelay_tapOut (tLinearDelay* const dl, uint32_t tapDelay)
254331 {
255332 _tLinearDelay* d = *dl;
256333
257− float tap = (float) d->inPoint - tapDelay - 1.f;
258−
334+ uint32_t tap = d->inPoint - tapDelay - 1;
259335 // Check for wraparound.
260− while ( tap < 0.f ) tap += (float)d->maxDelay;
261−
262− float alpha = tap - (int)tap;
263− float omAlpha = 1.f - alpha;
264−
265− int ptx = (int) tap;
266−
267− // First 1/2 of interpolation
268− float samp = d->buff[ptx] * omAlpha;
269−
270− // Second 1/2 of interpolation
271− if ((ptx + 1) < d->maxDelay)
272− samp += d->buff[ptx+1] * d->alpha;
273− else
274− samp += d->buff[0] * d->alpha;
275−
276− return samp;
336+ while ( tap < 0 ) tap += d->maxDelay;
277337
338+ return d->buff[tap];
278339 }
279340
280341 void tLinearDelay_tapIn (tLinearDelay* const dl, float value, uint32_t tapDelay)
281342 {
282343 _tLinearDelay* d = *dl;
283344
284− int32_t tap = d->inPoint - tapDelay - 1;
345+ uint32_t tap = d->inPoint - tapDelay - 1;
285346
286347 // Check for wraparound.
287348 while ( tap < 0 ) tap += d->maxDelay;
@@ -332,6 +393,234 @@ float tLinearDelay_getGain (tLinearDelay* const dl) · 44 unmodified lines
332393 return d->gain;
333394 }
334395
396+
397+
398+
399+
400+/// Hermite Interpolated Delay
401+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ LinearDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
402+void tHermiteDelay_init (tHermiteDelay* const dl, float delay, uint32_t maxDelay)
403+{
404+ _tHermiteDelay* d = *dl = (_tHermiteDelay*) leaf_alloc(sizeof(_tHermiteDelay));
405+
406+ d->maxDelay = maxDelay;
407+
408+ if (delay > maxDelay) d->delay = maxDelay;
409+ else if (delay < 0.0f) d->delay = 0.0f;
410+ else d->delay = delay;
411+
412+ d->buff = (float*) leaf_alloc(sizeof(float) * maxDelay);
413+
414+ d->gain = 1.0f;
415+
416+ d->lastIn = 0.0f;
417+ d->lastOut = 0.0f;
418+
419+ d->inPoint = 0;
420+ d->outPoint = 0;
421+
422+ tHermiteDelay_setDelay(dl, d->delay);
423+}
424+
425+void tHermiteDelay_free(tHermiteDelay* const dl)
426+{
427+ _tHermiteDelay* d = *dl;
428+
429+ leaf_free(d->buff);
430+ leaf_free(d);
431+}
432+
433+void tHermiteDelay_initToPool (tHermiteDelay* const dl, float delay, uint32_t maxDelay, tMempool* const mp)
434+{
435+ _tMempool* m = *mp;
436+ _tHermiteDelay* d = *dl = (_tHermiteDelay*) mpool_alloc(sizeof(_tHermiteDelay), m->pool);
437+
438+ d->maxDelay = maxDelay;
439+
440+ if (delay > maxDelay) d->delay = maxDelay;
441+ else if (delay < 0.0f) d->delay = 0.0f;
442+ else d->delay = delay;
443+
444+ d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m->pool);
445+
446+ d->gain = 1.0f;
447+
448+ d->lastIn = 0.0f;
449+ d->lastOut = 0.0f;
450+
451+ d->inPoint = 0;
452+ d->outPoint = 0;
453+
454+ tHermiteDelay_setDelay(dl, d->delay);
455+}
456+
457+void tHermiteDelay_freeFromPool(tHermiteDelay* const dl, tMempool* const mp)
458+{
459+ _tMempool* m = *mp;
460+ _tHermiteDelay* d = *dl;
461+
462+ mpool_free(d->buff, m->pool);
463+ mpool_free(d, m->pool);
464+}
465+
466+
467+void tHermiteDelay_clear(tHermiteDelay* const dl)
468+{
469+ _tHermiteDelay* d = *dl;
470+ for (int i = 0; i < d->maxDelay; i++)
471+ {
472+ d->buff[i] = 0;
473+ }
474+
475+
476+}
477+
478+float tHermiteDelay_tick (tHermiteDelay* const dl, float input)
479+{
480+ _tHermiteDelay* d = *dl;
481+
482+ d->buff[d->inPoint] = input * d->gain;
483+
484+ // Increment input pointer modulo length.
485+ if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0;
486+
487+
488+ uint32_t idx = (uint32_t) d->outPoint;
489+ d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay],
490+ d->buff[idx],
491+ d->buff[(idx + 1) % d->maxDelay],
492+ d->buff[(idx + 2) % d->maxDelay],
493+ d->alpha);
494+
495+ // Increment output pointer modulo length
496+ if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0;
497+
498+ return d->lastOut;
499+}
500+
501+void tHermiteDelay_tickIn (tHermiteDelay* const dl, float input)
502+{
503+ _tHermiteDelay* d = *dl;
504+
505+ d->buff[d->inPoint] = input * d->gain;
506+
507+ // Increment input pointer modulo length.
508+ if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0;
509+}
510+
511+float tHermiteDelay_tickOut (tHermiteDelay* const dl)
512+{
513+ _tHermiteDelay* d = *dl;
514+
515+ uint32_t idx = (uint32_t) d->outPoint;
516+
517+
518+
519+ d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay],
520+ d->buff[idx],
521+ d->buff[(idx + 1) % d->maxDelay],
522+ d->buff[(idx + 2) % d->maxDelay],
523+ d->alpha);
524+
525+ // Increment output pointer modulo length
526+ if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0;
527+
528+ return d->lastOut;
529+}
530+
531+int tHermiteDelay_setDelay (tHermiteDelay* const dl, float delay)
532+{
533+ _tHermiteDelay* d = *dl;
534+
535+ d->delay = LEAF_clip(0.0f, delay, d->maxDelay);
536+
537+ float outPointer = d->inPoint - d->delay;
538+
539+ while ( outPointer < 0 )
540+ outPointer += d->maxDelay; // modulo maximum length
541+
542+ d->outPoint = (uint32_t) outPointer; // integer part
543+
544+ d->alpha = outPointer - d->outPoint; // fractional part
545+ d->omAlpha = 1.0f - d->alpha;
546+
547+ if ( d->outPoint == d->maxDelay ) d->outPoint = 0;
548+
549+ return 0;
550+}
551+
552+float tHermiteDelay_tapOut (tHermiteDelay* const dl, uint32_t tapDelay)
553+{
554+ _tHermiteDelay* d = *dl;
555+
556+ uint32_t tap = d->inPoint - tapDelay - 1;
557+
558+ // Check for wraparound.
559+ while ( tap < 0 ) tap += d->maxDelay;
560+
561+ return d->buff[tap];
562+
563+}
564+
565+void tHermiteDelay_tapIn (tHermiteDelay* const dl, float value, uint32_t tapDelay)
566+{
567+ _tHermiteDelay* d = *dl;
568+
569+ int32_t tap = d->inPoint - tapDelay - 1;
570+
571+ // Check for wraparound.
572+ while ( tap < 0 ) tap += d->maxDelay;
573+
574+ d->buff[tap] = value;
575+}
576+
577+float tHermiteDelay_addTo (tHermiteDelay* const dl, float value, uint32_t tapDelay)
578+{
579+ _tHermiteDelay* d = *dl;
580+
581+ int32_t tap = d->inPoint - tapDelay - 1;
582+
583+ // Check for wraparound.
584+ while ( tap < 0 ) tap += d->maxDelay;
585+
586+ return (d->buff[tap] += value);
587+}
588+
589+float tHermiteDelay_getDelay (tHermiteDelay* const dl)
590+{
591+ _tHermiteDelay* d = *dl;
592+ return d->delay;
593+}
594+
595+float tHermiteDelay_getLastOut (tHermiteDelay* const dl)
596+{
597+ _tHermiteDelay* d = *dl;
598+ return d->lastOut;
599+}
600+
601+float tHermiteDelay_getLastIn (tHermiteDelay* const dl)
602+{
603+ _tHermiteDelay* d = *dl;
604+ return d->lastIn;
605+}
606+
607+void tHermiteDelay_setGain (tHermiteDelay* const dl, float gain)
608+{
609+ _tHermiteDelay* d = *dl;
610+ if (gain < 0.0f) d->gain = 0.0f;
611+ else d->gain = gain;
612+}
613+
614+float tHermiteDelay_getGain (tHermiteDelay* const dl)
615+{
616+ _tHermiteDelay* d = *dl;
617+ return d->gain;
618+}
619+
620+
621+
622+
623+
335624 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ AllpassDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
336625 void tAllpassDelay_init (tAllpassDelay* const dl, float delay, uint32_t maxDelay)
337626 {
@@ -366,6 +655,41 @@ void tAllpassDelay_free(tAllpassDelay* const dl) · 28 unmodified lines
366655 leaf_free(d);
367656 }
368657
658+void tAllpassDelay_initToPool (tAllpassDelay* const dl, float delay, uint32_t maxDelay, tMempool* const mp)
659+{
660+ _tMempool* m = *mp;
661+ _tAllpassDelay* d = *dl = (_tAllpassDelay*) mpool_alloc(sizeof(_tAllpassDelay), m->pool);
662+
663+ d->maxDelay = maxDelay;
664+
665+ if (delay > maxDelay) d->delay = maxDelay;
666+ else if (delay < 0.0f) d->delay = 0.0f;
667+ else d->delay = delay;
668+
669+ d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m->pool);
670+
671+ d->gain = 1.0f;
672+
673+ d->lastIn = 0.0f;
674+ d->lastOut = 0.0f;
675+
676+ d->inPoint = 0;
677+ d->outPoint = 0;
678+
679+ tAllpassDelay_setDelay(dl, d->delay);
680+
681+ d->apInput = 0.0f;
682+}
683+
684+void tAllpassDelay_freeFromPool(tAllpassDelay* const dl, tMempool* const mp)
685+{
686+ _tMempool* m = *mp;
687+ _tAllpassDelay* d = *dl;
688+
689+ mpool_free(d->buff, m->pool);
690+ mpool_free(d, m->pool);
691+}
692+
369693 float tAllpassDelay_tick (tAllpassDelay* const dl, float input)
370694 {
371695 _tAllpassDelay* d = *dl;
@@ -520,6 +844,36 @@ void tTapeDelay_free(tTapeDelay* const dl) · 148 unmodified lines
520844 leaf_free(d);
521845 }
522846
847+void tTapeDelay_initToPool (tTapeDelay* const dl, float delay, uint32_t maxDelay, tMempool* const mp)
848+{
849+ _tMempool* m = *mp;
850+ _tTapeDelay* d = *dl = (_tTapeDelay*) mpool_alloc(sizeof(_tTapeDelay), m->pool);
851+
852+ d->maxDelay = maxDelay;
853+
854+ d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m->pool);
855+
856+ d->gain = 1.0f;
857+
858+ d->lastIn = 0.0f;
859+ d->lastOut = 0.0f;
860+
861+ d->idx = 0.0f;
862+ d->inc = 1.0f;
863+ d->inPoint = 0;
864+
865+ tTapeDelay_setDelay(dl, delay);
866+}
867+
868+void tTapeDelay_freeFromPool(tTapeDelay* const dl, tMempool* const mp)
869+{
870+ _tMempool* m = *mp;
871+ _tTapeDelay* d = *dl;
872+
873+ mpool_free(d->buff, m->pool);
874+ mpool_free(d, m->pool);
875+}
876+
523877 //#define SMOOTH_FACTOR 10.f
524878
525879 float tTapeDelay_tick (tTapeDelay* const dl, float input)
@@ -534,7 +888,7 @@ float tTapeDelay_tick (tTapeDelay* const dl, float input) · 8 unmodified lines
534888 int idx = (int) d->idx;
535889 float alpha = d->idx - idx;
536890
537− d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay],
891+ d->lastOut = LEAF_interpolate_hermite_x (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay],
538892 d->buff[idx],
539893 d->buff[(idx + 1) % d->maxDelay],
540894 d->buff[(idx + 2) % d->maxDelay],
@@ -585,7 +939,7 @@ float tTapeDelay_tapOut (tTapeDelay* const dl, float tapDelay) · 44 unmodified lines
585939
586940 float alpha = tap - idx;
587941
588− float samp = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay],
942+ float samp = LEAF_interpolate_hermite_x (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay],
589943 d->buff[idx],
590944 d->buff[(idx + 1) % d->maxDelay],
591945 d->buff[(idx + 2) % d->maxDelay],
LEAF/Src/leaf-distortion.c+299−200
@@ -17,232 +17,58 @@ · 16 unmodified lines
1717 #include "../Inc/leaf-tables.h"
1818
1919 //testing
20−#include "gpio.h"
20+//#include "gpio.h"
2121
2222 #endif
2323
2424 //============================================================================================================
25−// WAVEFOLDER
25+// Sample-Rate reducer
2626 //============================================================================================================
2727
2828
29−//from the paper: Virtual Analog Model of the Lockhart Wavefolder
30−//by Fabián Esqueda, Henri Pöntynen, Julian D. Parker and Stefan Bilbao
31−
32−void tLockhartWavefolder_init(tLockhartWavefolder* const wf)
33−{
34− _tLockhartWavefolder* w = *wf = (_tLockhartWavefolder*) leaf_alloc(sizeof(_tLockhartWavefolder));
35−
36− w->Ln1 = 0.0;
37− w->Fn1 = 0.0;
38− w->xn1 = 0.0f;
39−
40− w->RL = 7.5e3;
41− w->R = 15e3;
42− w->VT = 26e-3;
43− w->Is = 10e-16;
44−
45− w->a = 2.0*w->RL/w->R;
46− w->b = (w->R+2.0*w->RL)/(w->VT*w->R);
47− w->d = (w->RL*w->Is)/w->VT;
48− w->half_a = 0.5 * w->a;
49− w->longthing = (0.5*w->VT/w->b);
50−
51−
52− // Antialiasing error threshold
53− w->thresh = 10e-10;
54−}
55−
56−void tLockhartWavefolder_free(tLockhartWavefolder* const wf)
57−{
58− _tLockhartWavefolder* w = *wf;
59−
60− leaf_free(w);
61−}
62−
63−double tLockhartWavefolderLambert(double x, double ln)
64−{
65− double thresh, w, expw, p, r, s, err;
66− // Error threshold
67− thresh = 10e-12;
68− // Initial guess (use previous value)
69− w = ln;
70−
71− // Haley's method (Sec. 4.2 of the paper)
72− for(int i=0; i<1000; i+=1) {
73−
74− expw = exp(w);
75−
76− p = w*expw - x;
77− r = (w+1.0)*expw;
78− s = (w+2.0)/(2.0*(w+1.0));
79− err = (p/(r-(p*s)));
80−
81− if (fabs(err)<thresh) {
82−
83− break;
84− }
85−
86− w = w - err;
87− if (i == 999)
88− {
89− //HAL_GPIO_WritePin(GPIOG, GPIO_PIN_7, GPIO_PIN_SET);
90− }
91−
92− }
93− return w;
94−}
95−
96−float tLockhartWavefolder_tick(tLockhartWavefolder* const wf, float samp)
29+void tSampleReducer_init(tSampleReducer* const sr)
9730 {
98− _tLockhartWavefolder* w = *wf;
99−
100− float out = 0.0f;
101−
102− // Compute Antiderivative
103− int l = (samp > 0.0f) - (samp < 0.0f);
104− double u = w->d*exp(l*w->b*samp);
105− double Ln = tLockhartWavefolderLambert(u,w->Ln1);
106− double Fn = w->longthing*(Ln*(Ln + 2.0)) - w->half_a*samp*samp;
107−
108− // Check for ill-conditioning
109− if (fabs(samp-w->xn1)<w->thresh) {
110−
111− // Compute Averaged Wavefolder Output
112− float xn = 0.5f*(samp+w->xn1);
113− u = w->d*exp(l*w->b*xn);
114− Ln = tLockhartWavefolderLambert(u,w->Ln1);
115− out = (float) (l*w->VT*Ln - w->a*xn);
116−
117− }
118− else {
119−
120− // Apply AA Form
121− out = (float) ((Fn-w->Fn1)/(samp-w->xn1));
122− }
123−
124− // Update States
125− w->Ln1 = Ln;
126− w->Fn1 = Fn;
127− w->xn1 = samp;
31+ _tSampleReducer* s = *sr = (_tSampleReducer*) leaf_alloc(sizeof(_tSampleReducer));
12832
129− return out;
33+ s->invRatio = 1.0f;
34+ s->hold = 0.0f;
35+ s->count = 0;
13036 }
13137
132−//============================================================================================================
133−// CRUSHER
134−//============================================================================================================
135−#define SCALAR 5000.f
136−
137−void tCrusher_init (tCrusher* const cr)
38+void tSampleReducer_free (tSampleReducer* const sr)
13839 {
139− _tCrusher* c = *cr = (_tCrusher*) leaf_alloc(sizeof(_tCrusher));
40+ _tSampleReducer* s = *sr;
14041
141− c->op = 4;
142− c->div = SCALAR;
143− c->rnd = 0.25f;
144− c->srr = 0.25f;
145− tSampleReducer_init(&c->sReducer);
146− c->gain = (c->div / SCALAR) * 0.7f + 0.3f;
147−}
148−
149−void tCrusher_free (tCrusher* const cr)
150−{
151− _tCrusher* c = *cr;
152− tSampleReducer_free(&c->sReducer);
153− leaf_free(c);
42+ leaf_free(s);
15443 }
15544
156−float tCrusher_tick (tCrusher* const cr, float input)
45+void tSampleReducer_initToPool (tSampleReducer* const sr, tMempool* const mp)
15746 {
158− _tCrusher* c = *cr;
159−
160− float sample = input;
161−
162− sample *= SCALAR; // SCALAR is 5000 by default
163−
164− sample = (int32_t) sample;
165−
166− sample /= c->div;
167−
168− sample = LEAF_bitwise_xor(sample, c->op << 23);
169−
170− sample = LEAF_clip(-1.f, sample, 1.f);
171−
172− sample = LEAF_round(sample, c->rnd);
47+ _tMempool* m = *mp;
48+ _tSampleReducer* s = *sr = (_tSampleReducer*) mpool_alloc(sizeof(_tSampleReducer), m->pool);
17349
174− sample = tSampleReducer_tick(&c->sReducer, sample);
175−
176− return sample * c->gain;
177−
178−}
179−
180−void tCrusher_setOperation (tCrusher* const cr, float op)
181−{
182− _tCrusher* c = *cr;
183− c->op = (uint32_t) (op * 8.0f);
50+ s->invRatio = 1.0f;
51+ s->hold = 0.0f;
52+ s->count = 0;
18453 }
18554
186−// 0.0 - 1.0
187−void tCrusher_setQuality (tCrusher* const cr, float val)
55+void tSampleReducer_freeFromPool (tSampleReducer* const sr, tMempool* const mp)
18856 {
189− _tCrusher* c = *cr;
190−
191− val = LEAF_clip(0.0f, val, 1.0f);
192−
193− c->div = 0.01f + val * SCALAR;
57+ _tMempool* m = *mp;
58+ _tSampleReducer* s = *sr;
19459
195− c->gain = (c->div / SCALAR) * 0.7f + 0.3f;
196−}
197−
198−// what decimal to round to
199−void tCrusher_setRound (tCrusher* const cr, float rnd)
200−{
201− _tCrusher* c = *cr;
202− c->rnd = fabsf(rnd);
203−}
204−
205−void tCrusher_setSamplingRatio (tCrusher* const cr, float ratio)
206−{
207− _tCrusher* c = *cr;
208− c->srr = ratio;
209− tSampleReducer_setRatio(&c->sReducer, ratio);
210−
211−}
212−
213−//============================================================================================================
214−// Sample-Rate reducer
215−//============================================================================================================
216−
217−
218−void tSampleReducer_init(tSampleReducer* const sr)
219−{
220− _tSampleReducer* s = *sr = (_tSampleReducer*) leaf_alloc(sizeof(_tSampleReducer));
221−
222−
223−
224− s->invRatio = 1.0f;
225− s->hold = 0.0f;
226− s->count = 0;
227−
228−}
229−
230−void tSampleReducer_free (tSampleReducer* const sr)
231−{
232− _tSampleReducer* s = *sr;
233−
234− leaf_free(s);
60+ mpool_free(s, m->pool);
23561 }
23662
23763 float tSampleReducer_tick(tSampleReducer* const sr, float input)
23864 {
239− _tSampleReducer* s = *sr;
65+ _tSampleReducer* s = *sr;
24066 if (s->count > s->invRatio)
24167 {
24268 s->hold = input;
24369 s->count = 0;
24470 }
245−
71+
24672 s->count++;
24773 return s->hold;
24874 }
@@ -250,10 +76,10 @@ float tSampleReducer_tick(tSampleReducer* const sr, float input) · 1 unmodified line
25076
25177 void tSampleReducer_setRatio(tSampleReducer* const sr, float ratio)
25278 {
253− _tSampleReducer* s = *sr;
254− if ((ratio <= 1.0f) && (ratio >= 0.0f))
255− s->invRatio = 1.0f / ratio;
256−
79+ _tSampleReducer* s = *sr;
80+ if ((ratio <= 1.0f) && (ratio >= 0.0f))
81+ s->invRatio = 1.0f / ratio;
82+
25783 }
25884
25985 //============================================================================================================
@@ -288,6 +114,36 @@ void tOversampler_free(tOversampler* const osr) · 28 unmodified lines
288114 leaf_free(os);
289115 }
290116
117+void tOversampler_initToPool (tOversampler* const osr, int ratio, oBool extraQuality, tMempool* const mp)
118+{
119+ _tMempool* m = *mp;
120+ _tOversampler* os = *osr = (_tOversampler*) mpool_alloc(sizeof(_tOversampler), m->pool);
121+
122+ uint8_t offset = 0;
123+ if (extraQuality) offset = 6;
124+ if (ratio == 2 || ratio == 4 ||
125+ ratio == 8 || ratio == 16 ||
126+ ratio == 32 || ratio == 64) {
127+ os->ratio = ratio;
128+ int idx = (int)(log2f(os->ratio))-1+offset;
129+ os->numTaps = firNumTaps[idx];
130+ os->phaseLength = os->numTaps / os->ratio;
131+ os->pCoeffs = (float*) firCoeffs[idx];
132+ os->upState = mpool_alloc(sizeof(float) * os->numTaps * 2, m->pool);
133+ os->downState = mpool_alloc(sizeof(float) * os->numTaps * 2, m->pool);
134+ }
135+}
136+
137+void tOversampler_freeFromPool (tOversampler* const osr, tMempool* const mp)
138+{
139+ _tMempool* m = *mp;
140+ _tOversampler* os = *osr;
141+
142+ mpool_free(os->upState, m->pool);
143+ mpool_free(os->downState, m->pool);
144+ mpool_free(os, m->pool);
145+}
146+
291147 float tOversampler_tick(tOversampler* const osr, float input, float (*effectTick)(float))
292148 {
293149 _tOversampler* os = *osr;
@@ -486,3 +342,246 @@ int tOversampler_getLatency(tOversampler* const osr) · 192 unmodified lines
486342 _tOversampler* os = *osr;
487343 return os->phaseLength;
488344 }
345+
346+//============================================================================================================
347+// WAVEFOLDER
348+//============================================================================================================
349+
350+
351+//from the paper: Virtual Analog Model of the Lockhart Wavefolder
352+//by Fabián Esqueda, Henri Pöntynen, Julian D. Parker and Stefan Bilbao
353+
354+void tLockhartWavefolder_init(tLockhartWavefolder* const wf)
355+{
356+ _tLockhartWavefolder* w = *wf = (_tLockhartWavefolder*) leaf_alloc(sizeof(_tLockhartWavefolder));
357+
358+ w->Ln1 = 0.0;
359+ w->Fn1 = 0.0;
360+ w->xn1 = 0.0f;
361+
362+ w->RL = 7.5e3;
363+ w->R = 15e3;
364+ w->VT = 26e-3;
365+ w->Is = 10e-16;
366+
367+ w->a = 2.0*w->RL/w->R;
368+ w->b = (w->R+2.0*w->RL)/(w->VT*w->R);
369+ w->d = (w->RL*w->Is)/w->VT;
370+ w->half_a = 0.5 * w->a;
371+ w->longthing = (0.5*w->VT/w->b);
372+
373+
374+ // Antialiasing error threshold
375+ w->thresh = 10e-10;
376+}
377+
378+void tLockhartWavefolder_free(tLockhartWavefolder* const wf)
379+{
380+ _tLockhartWavefolder* w = *wf;
381+
382+ leaf_free(w);
383+}
384+
385+void tLockhartWavefolder_initToPool (tLockhartWavefolder* const wf, tMempool* const mp)
386+{
387+ _tMempool* m = *mp;
388+ _tLockhartWavefolder* w = *wf = (_tLockhartWavefolder*) mpool_alloc(sizeof(_tLockhartWavefolder), m->pool);
389+
390+ w->Ln1 = 0.0;
391+ w->Fn1 = 0.0;
392+ w->xn1 = 0.0f;
393+
394+ w->RL = 7.5e3;
395+ w->R = 15e3;
396+ w->VT = 26e-3;
397+ w->Is = 10e-16;
398+
399+ w->a = 2.0*w->RL/w->R;
400+ w->b = (w->R+2.0*w->RL)/(w->VT*w->R);
401+ w->d = (w->RL*w->Is)/w->VT;
402+ w->half_a = 0.5 * w->a;
403+ w->longthing = (0.5*w->VT/w->b);
404+
405+
406+ // Antialiasing error threshold
407+ w->thresh = 10e-10;
408+}
409+
410+void tLockhartWavefolder_freeFromPool (tLockhartWavefolder* const wf, tMempool* const mp)
411+{
412+ _tMempool* m = *mp;
413+ _tLockhartWavefolder* w = *wf;
414+
415+ mpool_free(w, m->pool);
416+}
417+
418+double tLockhartWavefolderLambert(double x, double ln)
419+{
420+ double thresh, w, expw, p, r, s, err;
421+ // Error threshold
422+ thresh = 10e-12;
423+ // Initial guess (use previous value)
424+ w = ln;
425+
426+ // Haley's method (Sec. 4.2 of the paper)
427+ for(int i=0; i<1000; i+=1) {
428+
429+ expw = exp(w);
430+
431+ p = w*expw - x;
432+ r = (w+1.0)*expw;
433+ s = (w+2.0)/(2.0*(w+1.0));
434+ err = (p/(r-(p*s)));
435+
436+ if (fabs(err)<thresh) {
437+
438+ break;
439+ }
440+
441+ w = w - err;
442+ if (i == 999)
443+ {
444+ //HAL_GPIO_WritePin(GPIOG, GPIO_PIN_7, GPIO_PIN_SET);
445+ }
446+
447+ }
448+ return w;
449+}
450+
451+float tLockhartWavefolder_tick(tLockhartWavefolder* const wf, float samp)
452+{
453+ _tLockhartWavefolder* w = *wf;
454+
455+ float out = 0.0f;
456+
457+ // Compute Antiderivative
458+ int l = (samp > 0.0f) - (samp < 0.0f);
459+ double u = w->d*exp(l*w->b*samp);
460+ double Ln = tLockhartWavefolderLambert(u,w->Ln1);
461+ double Fn = w->longthing*(Ln*(Ln + 2.0)) - w->half_a*samp*samp;
462+
463+ // Check for ill-conditioning
464+ if (fabs(samp-w->xn1)<w->thresh) {
465+
466+ // Compute Averaged Wavefolder Output
467+ float xn = 0.5f*(samp+w->xn1);
468+ u = w->d*exp(l*w->b*xn);
469+ Ln = tLockhartWavefolderLambert(u,w->Ln1);
470+ out = (float) (l*w->VT*Ln - w->a*xn);
471+
472+ }
473+ else {
474+
475+ // Apply AA Form
476+ out = (float) ((Fn-w->Fn1)/(samp-w->xn1));
477+ }
478+
479+ // Update States
480+ w->Ln1 = Ln;
481+ w->Fn1 = Fn;
482+ w->xn1 = samp;
483+
484+ return out;
485+}
486+
487+//============================================================================================================
488+// CRUSHER
489+//============================================================================================================
490+#define SCALAR 5000.f
491+
492+void tCrusher_init (tCrusher* const cr)
493+{
494+ _tCrusher* c = *cr = (_tCrusher*) leaf_alloc(sizeof(_tCrusher));
495+
496+ c->op = 4;
497+ c->div = SCALAR;
498+ c->rnd = 0.25f;
499+ c->srr = 0.25f;
500+ tSampleReducer_init(&c->sReducer);
501+ c->gain = (c->div / SCALAR) * 0.7f + 0.3f;
502+}
503+
504+void tCrusher_free (tCrusher* const cr)
505+{
506+ _tCrusher* c = *cr;
507+ tSampleReducer_free(&c->sReducer);
508+ leaf_free(c);
509+}
510+
511+void tCrusher_initToPool (tCrusher* const cr, tMempool* const mp)
512+{
513+ _tMempool* m = *mp;
514+ _tCrusher* c = *cr = (_tCrusher*) mpool_alloc(sizeof(_tCrusher), m->pool);
515+
516+ c->op = 4;
517+ c->div = SCALAR;
518+ c->rnd = 0.25f;
519+ c->srr = 0.25f;
520+ tSampleReducer_initToPool(&c->sReducer, mp);
521+ c->gain = (c->div / SCALAR) * 0.7f + 0.3f;
522+}
523+
524+void tCrusher_freeFromPool (tCrusher* const cr, tMempool* const mp)
525+{
526+ _tMempool* m = *mp;
527+ _tCrusher* c = *cr;
528+ tSampleReducer_freeFromPool(&c->sReducer, mp);
529+ mpool_free(c, m->pool);
530+}
531+
532+float tCrusher_tick (tCrusher* const cr, float input)
533+{
534+ _tCrusher* c = *cr;
535+
536+ float sample = input;
537+
538+ sample *= SCALAR; // SCALAR is 5000 by default
539+
540+ sample = (int32_t) sample;
541+
542+ sample /= c->div;
543+
544+ sample = LEAF_bitwise_xor(sample, c->op << 23);
545+
546+ sample = LEAF_clip(-1.f, sample, 1.f);
547+
548+ sample = LEAF_round(sample, c->rnd);
549+
550+ sample = tSampleReducer_tick(&c->sReducer, sample);
551+
552+ return sample * c->gain;
553+
554+}
555+
556+void tCrusher_setOperation (tCrusher* const cr, float op)
557+{
558+ _tCrusher* c = *cr;
559+ c->op = (uint32_t) (op * 8.0f);
560+}
561+
562+// 0.0 - 1.0
563+void tCrusher_setQuality (tCrusher* const cr, float val)
564+{
565+ _tCrusher* c = *cr;
566+
567+ val = LEAF_clip(0.0f, val, 1.0f);
568+
569+ c->div = 0.01f + val * SCALAR;
570+
571+ c->gain = (c->div / SCALAR) * 0.7f + 0.3f;
572+}
573+
574+// what decimal to round to
575+void tCrusher_setRound (tCrusher* const cr, float rnd)
576+{
577+ _tCrusher* c = *cr;
578+ c->rnd = fabsf(rnd);
579+}
580+
581+void tCrusher_setSamplingRatio (tCrusher* const cr, float ratio)
582+{
583+ _tCrusher* c = *cr;
584+ c->srr = ratio;
585+ tSampleReducer_setRatio(&c->sReducer, ratio);
586+
587+}
LEAF/Src/leaf-dynamics.c+47−2
@@ -63,6 +63,30 @@ void tCompressor_free(tCompressor* const comp) · 62 unmodified lines
6363 leaf_free(c);
6464 }
6565
66+void tCompressor_initToPool (tCompressor* const comp, tMempool* const mp)
67+{
68+ _tMempool* m = *mp;
69+ _tCompressor* c = *comp = (_tCompressor*) mpool_alloc(sizeof(_tCompressor), m->pool);
70+
71+ c->tauAttack = 100;
72+ c->tauRelease = 100;
73+
74+ c->isActive = OFALSE;
75+
76+ c->T = 0.0f; // Threshold
77+ c->R = 0.5f; // compression Ratio
78+ c->M = 3.0f; // decibel Width of knee transition
79+ c->W = 1.0f; // decibel Make-up gain
80+}
81+
82+void tCompressor_freeFromPool(tCompressor* const comp, tMempool* const mp)
83+{
84+ _tMempool* m = *mp;
85+ _tCompressor* c = *comp;
86+
87+ mpool_free(c, m->pool);
88+}
89+
6690 float tCompressor_tick(tCompressor* const comp, float in)
6791 {
6892 _tCompressor* c = *comp;
@@ -133,6 +157,27 @@ void tFeedbackLeveler_free(tFeedbackLeveler* const fb) · 64 unmodified lines
133157 leaf_free(p);
134158 }
135159
160+void tFeedbackLeveler_initToPool (tFeedbackLeveler* const fb, float targetLevel, float factor, float strength, int mode, tMempool* const mp)
161+{
162+ _tMempool* m = *mp;
163+ _tFeedbackLeveler* p = *fb = (_tFeedbackLeveler*) mpool_alloc(sizeof(_tFeedbackLeveler), m->pool);
164+
165+ p->curr=0.0f;
166+ p->targetLevel=targetLevel;
167+ tPowerFollower_initToPool(&p->pwrFlw,factor, mp);
168+ p->mode=mode;
169+ p->strength=strength;
170+}
171+
172+void tFeedbackLeveler_freeFromPool (tFeedbackLeveler* const fb, tMempool* const mp)
173+{
174+ _tMempool* m = *mp;
175+ _tFeedbackLeveler* p = *fb;
176+
177+ tPowerFollower_freeFromPool(&p->pwrFlw, mp);
178+ mpool_free(p, m->pool);
179+}
180+
136181 void tFeedbackLeveler_setStrength(tFeedbackLeveler* const fb, float strength)
137182 { // strength is how strongly level diff is affecting the amp ratio
138183 // try 0.125 for a start
@@ -156,8 +201,8 @@ float tFeedbackLeveler_tick(tFeedbackLeveler* const fb, float input) · 17 unmodified lines
156201 {
157202 _tFeedbackLeveler* p = *fb;
158203 float levdiff=(tPowerFollower_tick(&p->pwrFlw, input)-p->targetLevel);
159− if (p->mode==0 && levdiff<0) levdiff=0;
160− p->curr=input*(1-p->strength*levdiff);
204+ if (p->mode==0 && levdiff<0.0f) levdiff=0.0f;
205+ p->curr=input*(1.0f-p->strength*levdiff);
161206 return p->curr;
162207 }
163208
LEAF/Src/leaf-effects.c+816−529
@@ -59,6 +59,42 @@ void tTalkbox_free(tTalkbox* const voc) · 58 unmodified lines
5959 leaf_free(v);
6060 }
6161
62+void tTalkbox_initToPool (tTalkbox* const voc, int bufsize, tMempool* const mp)
63+{
64+ _tMempool* m = *mp;
65+ _tTalkbox* v = *voc = (_tTalkbox*) mpool_alloc(sizeof(_tTalkbox), m->pool);
66+
67+ v->param[0] = 0.5f; //wet
68+ v->param[1] = 0.0f; //dry
69+ v->param[2] = 0; // Swap
70+ v->param[3] = 1.0f; //quality
71+
72+ v->bufsize = bufsize;
73+
74+ v->car0 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m->pool);
75+ v->car1 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m->pool);
76+ v->window = (float*) mpool_alloc(sizeof(float) * v->bufsize, m->pool);
77+ v->buf0 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m->pool);
78+ v->buf1 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m->pool);
79+
80+ tTalkbox_update(voc);
81+ tTalkbox_suspend(voc);
82+}
83+
84+void tTalkbox_freeFromPool (tTalkbox* const voc, tMempool* const mp)
85+{
86+ _tMempool* m = *mp;
87+ _tTalkbox* v = *voc;
88+
89+ mpool_free(v->buf1, m->pool);
90+ mpool_free(v->buf0, m->pool);
91+ mpool_free(v->window, m->pool);
92+ mpool_free(v->car1, m->pool);
93+ mpool_free(v->car0, m->pool);
94+
95+ mpool_free(v, m->pool);
96+}
97+
6298 void tTalkbox_update(tTalkbox* const voc) ///update internal parameters...
6399 {
64100 _tTalkbox* v = *voc;
@@ -266,6 +302,31 @@ void tVocoder_free (tVocoder* const voc) · 201 unmodified lines
266302 leaf_free(v);
267303 }
268304
305+void tVocoder_initToPool (tVocoder* const voc, tMempool* const mp)
306+{
307+ _tMempool* m = *mp;
308+ _tVocoder* v = *voc = (_tVocoder*) mpool_alloc(sizeof(_tVocoder), m->pool);
309+
310+ v->param[0] = 0.33f; //input select
311+ v->param[1] = 0.50f; //output dB
312+ v->param[2] = 0.40f; //hi thru
313+ v->param[3] = 0.40f; //hi band
314+ v->param[4] = 0.16f; //envelope
315+ v->param[5] = 0.55f; //filter q
316+ v->param[6] = 0.6667f;//freq range
317+ v->param[7] = 0.33f; //num bands
318+
319+ tVocoder_update(voc);
320+}
321+
322+void tVocoder_freeFromPool (tVocoder* const voc, tMempool* const mp)
323+{
324+ _tMempool* m = *mp;
325+ _tVocoder* v = *voc;
326+
327+ mpool_free(v, m->pool);
328+}
329+
269330 void tVocoder_update (tVocoder* const voc)
270331 {
271332 _tVocoder* v = *voc;
@@ -427,319 +488,354 @@ void tVocoder_suspend (tVocoder* const voc) · 155 unmodified lines
427488 }
428489
429490 //============================================================================================================
430−// RETUNE
491+// SOLAD
431492 //============================================================================================================
493+/******************************************************************************/
494+/***************** static function declarations *******************************/
495+/******************************************************************************/
432496
433−void tRetune_init(tRetune* const rt, int numVoices, int bufSize, int frameSize)
497+static void solad_init(_tSOLAD *w);
498+static inline float read_sample(_tSOLAD *w, float floatindex);
499+static void pitchdown(_tSOLAD *w, float *out);
500+static void pitchup(_tSOLAD *w, float *out);
501+
502+/******************************************************************************/
503+/***************** public access functions ************************************/
504+/******************************************************************************/
505+
506+// init
507+void tSOLAD_init(tSOLAD* const wp)
434508 {
435− _tRetune* r = *rt = (_tRetune*) leaf_alloc(sizeof(_tRetune));
436−
437− r->bufSize = bufSize;
438− r->frameSize = frameSize;
439− r->numVoices = numVoices;
440−
441− r->inBuffer = (float*) leaf_alloc(sizeof(float) * r->bufSize);
442− r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices);
443−
444− r->hopSize = DEFHOPSIZE;
445− r->windowSize = DEFWINDOWSIZE;
446− r->fba = FBA;
447− tRetune_setTimeConstant(rt, DEFTIMECONSTANT);
448−
449− r->inputPeriod = 0.0f;
450−
451− r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices);
452− r->pitchFactor = (float*) leaf_alloc(sizeof(float) * r->numVoices);
453− r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices);
454− for (int i = 0; i < r->numVoices; ++i)
455− {
456− r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize);
457− }
458−
459− tPeriodDetection_init(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize);
509+ _tSOLAD* w = *wp = (_tSOLAD*) leaf_allocAndClear(sizeof(_tSOLAD));
460510
461− for (int i = 0; i < r->numVoices; ++i)
462− {
463− tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize);
464− }
511+ w->pitchfactor = 1.;
512+ w->delaybuf = (float*) leaf_allocAndClear(sizeof(float) * (LOOPSIZE+16));
513+ solad_init(w);
465514 }
466515
467−void tRetune_free(tRetune* const rt)
516+void tSOLAD_free(tSOLAD* const wp)
468517 {
469− _tRetune* r = *rt;
518+ _tSOLAD* w = *wp;
470519
471− tPeriodDetection_free(&r->pd);
472− for (int i = 0; i < r->numVoices; ++i)
473− {
474− tPitchShift_free(&r->ps[i]);
475− leaf_free(r->outBuffers[i]);
476− }
477− leaf_free(r->tickOutput);
478− leaf_free(r->pitchFactor);
479− leaf_free(r->ps);
480− leaf_free(r->inBuffer);
481− leaf_free(r->outBuffers);
482− leaf_free(r);
520+ leaf_free(w->delaybuf);
521+ leaf_free(w);
483522 }
484523
485−float* tRetune_tick(tRetune* const rt, float sample)
524+void tSOLAD_initToPool (tSOLAD* const wp, tMempool* const mp)
486525 {
487− _tRetune* r = *rt;
488−
489− r->inputPeriod = tPeriodDetection_findPeriod(&r->pd, sample);
490−
491− for (int v = 0; v < r->numVoices; ++v)
492− {
493− r->tickOutput[v] = tPitchShift_shift(&r->ps[v]);
494− }
526+ _tMempool* m = *mp;
527+ _tSOLAD* w = *wp = (_tSOLAD*) mpool_allocAndClear(sizeof(_tSOLAD), m->pool);
495528
496− return r->tickOutput;
529+ w->pitchfactor = 1.;
530+ w->delaybuf = (float*) mpool_allocAndClear(sizeof(float) * (LOOPSIZE+16), m->pool);
531+ solad_init(w);
497532 }
498533
499−void tRetune_setNumVoices(tRetune* const rt, int numVoices)
534+void tSOLAD_freeFromPool (tSOLAD* const wp, tMempool* const mp)
500535 {
501− _tRetune* r = *rt;
536+ _tMempool* m = *mp;
537+ _tSOLAD* w = *wp;
502538
503− for (int i = 0; i < r->numVoices; ++i)
504− {
505− tPitchShift_free(&r->ps[i]);
506− leaf_free(r->outBuffers[i]);
507− }
508− leaf_free(r->tickOutput);
509− leaf_free(r->pitchFactor);
510− leaf_free(r->ps);
511− leaf_free(r->outBuffers);
539+ mpool_free(w->delaybuf, m->pool);
540+ mpool_free(w, m->pool);
541+}
542+
543+// send one block of input samples, receive one block of output samples
544+void tSOLAD_ioSamples(tSOLAD* const wp, float* in, float* out, int blocksize)
545+{
546+ _tSOLAD* w = *wp;
512547
513− r->numVoices = numVoices;
548+ int i = w->timeindex;
549+ int n = w->blocksize = blocksize;
514550
515− r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices);
516− r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices);
517− r->pitchFactor = (float*) leaf_alloc(sizeof(float) * r->numVoices);
518− r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices);
519− for (int i = 0; i < r->numVoices; ++i)
520− {
521− r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize);
522− tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize);
523− }
551+ if(!i) w->delaybuf[LOOPSIZE] = in[0]; // copy one sample for interpolation
552+ while(n--) w->delaybuf[i++] = *in++; // copy one input block to delay buffer
524553
554+ if(w->pitchfactor > 1) pitchup(w, out);
555+ else pitchdown(w, out);
525556
557+ w->timeindex += blocksize;
558+ w->timeindex &= LOOPMASK;
526559 }
527560
528−void tRetune_setPitchFactors(tRetune* const rt, float pf)
561+// set periodicity analysis data
562+void tSOLAD_setPeriod(tSOLAD* const wp, float period)
529563 {
530− _tRetune* r = *rt;
564+ _tSOLAD* w = *wp;
531565
532− for (int i = 0; i < r->numVoices; ++i)
533− {
534− r->pitchFactor[i] = pf;
535− tPitchShift_setPitchFactor(&r->ps[i], r->pitchFactor[i]);
536− }
566+ if(period > MAXPERIOD) period = MAXPERIOD;
567+ if(period > MINPERIOD) w->period = period; // ignore period when too small
537568 }
538569
539−void tRetune_setPitchFactor(tRetune* const rt, float pf, int voice)
570+// set pitch factor between 0.25 and 4
571+void tSOLAD_setPitchFactor(tSOLAD* const wp, float pitchfactor)
540572 {
541− _tRetune* r = *rt;
573+ _tSOLAD* w = *wp;
542574
543− r->pitchFactor[voice] = pf;
544− tPitchShift_setPitchFactor(&r->ps[voice], r->pitchFactor[voice]);
575+ if (pitchfactor <= 0.0f) return;
576+ w->pitchfactor = pitchfactor;
545577 }
546578
547−void tRetune_setTimeConstant(tRetune* const rt, float tc)
579+// force readpointer lag
580+void tSOLAD_setReadLag(tSOLAD* const wp, float readlag)
548581 {
549− _tRetune* r = *rt;
582+ _tSOLAD* w = *wp;
550583
551− r->timeConstant = tc;
552− r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant);
584+ if(readlag < 0) readlag = 0;
585+ if(readlag < w->readlag) // do not jump backward, only forward
586+ {
587+ w->jump = w->readlag - readlag;
588+ w->readlag = readlag;
589+ w->xfadelength = readlag;
590+ w->xfadevalue = 1;
591+ }
553592 }
554593
555−void tRetune_setHopSize(tRetune* const rt, int hs)
594+// reset state variables
595+void tSOLAD_resetState(tSOLAD* const wp)
556596 {
557− _tRetune* r = *rt;
597+ _tSOLAD* w = *wp;
558598
559− r->hopSize = hs;
560− tPeriodDetection_setHopSize(&r->pd, r->hopSize);
561−}
562−
563−void tRetune_setWindowSize(tRetune* const rt, int ws)
564−{
565− _tRetune* r = *rt;
599+ int n = LOOPSIZE + 1;
600+ float *buf = w->delaybuf;
566601
567− r->windowSize = ws;
568− tPeriodDetection_setWindowSize(&r->pd, r->windowSize);
602+ while(n--) *buf++ = 0;
603+ solad_init(w);
569604 }
570605
571−float tRetune_getInputPeriod(tRetune* const rt)
572−{
573− _tRetune* r = *rt;
574−
575− return r->inputPeriod;
576−}
606+/******************************************************************************/
607+/******************** private procedures **************************************/
608+/******************************************************************************/
577609
578−float tRetune_getInputFreq(tRetune* const rt)
579−{
580− _tRetune* r = *rt;
581−
582− return 1.0f/r->inputPeriod;
583−}
610+/*
611+ Function pitchdown() is called to read samples from the delay buffer when pitch
612+ factor is between 0.25 and 1. The read pointer lags behind because of the slowed
613+ down speed, and it must jump forward towards the write pointer soon as there is
614+ sufficient space to jump. That is, if there is at least one period of the input
615+ signal between read pointer and write pointer. When short periods follow up on
616+ long periods, the read pointer may have space to jump over more than one period
617+ lenghts. Jump length must be [periodlength ^ 2] in any case.
618+
619+ A linear crossfade function joins the jump-from point with the jump-to point.
620+ The crossfade must be completed before another read pointer jump is allowed.
621+ Length of the crossfade function is stored as a number of samples in terms of
622+ the input sample rate. This length is dynamically translated
623+ to a crossfade length expressed in output reading rate, according to pitch
624+ factor which can change before the crossfade is completed. Crossfade length does
625+ not cover an invariable length in periods for all pitch transposition factors.
626+ For pitch factors from 0.5 till 1, crossfade length is stretched in the
627+ output just as much as the signal itself, as crossfade speed is set to equal
628+ pitch factor. For pitch factors below 0.5, the read pointer wants to jump
629+ forward before one period is read, therefore the crossfade length as expressed
630+ in output periods must be shorter. Crossfade speed is set to [1 - pitchfactor]
631+ for those cases. Pitch factor 0.5 is the natural switch point between crossfade
632+ speeds [pitchfactor] and [1 - pitchfactor] because 0.5 == 1 - 0.5. The crossfade
633+ speed modification for pitch factors below 0.5 also means that much of the
634+ original signal content will be skipped.
635+ */
584636
585−//============================================================================================================
586−// AUTOTUNE
587−//============================================================================================================
588637
589−void tAutotune_init(tAutotune* const rt, int numVoices, int bufSize, int frameSize)
638+static void pitchdown(_tSOLAD* const w, float *out)
590639 {
591− _tAutotune* r = *rt = (_tAutotune*) leaf_alloc(sizeof(_tAutotune));
592−
593− r->bufSize = bufSize;
594− r->frameSize = frameSize;
595− r->numVoices = numVoices;
596−
597− r->inBuffer = (float*) leaf_alloc(sizeof(float) * r->bufSize);
598− r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices);
599−
600− r->hopSize = DEFHOPSIZE;
601− r->windowSize = DEFWINDOWSIZE;
602− r->fba = FBA;
603− tAutotune_setTimeConstant(rt, DEFTIMECONSTANT);
604−
605−
606−
607− r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices);
608− r->freq = (float*) leaf_alloc(sizeof(float) * r->numVoices);
609− r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices);
610− for (int i = 0; i < r->numVoices; ++i)
611− {
612− r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize);
613− }
640+ int n = w->blocksize;
641+ float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values!
642+ float pitchfactor = w->pitchfactor;
643+ float period = w->period;
644+ float readlag = w->readlag;
645+ float readlagstep = 1 - pitchfactor;
646+ float jump = w->jump;
647+ float xfadevalue = w->xfadevalue;
648+ float xfadelength = w->xfadelength;
649+ float xfadespeed, xfadestep, readindex, outputsample;
614650
615− tPeriodDetection_init(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize);
651+ if(pitchfactor > 0.5) xfadespeed = pitchfactor;
652+ else xfadespeed = 1 - pitchfactor;
653+ xfadestep = xfadespeed / xfadelength;
616654
617− for (int i = 0; i < r->numVoices; ++i)
655+ while(n--)
618656 {
619− tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize);
657+ if(readlag > period) // check if read pointer may jump forward...
658+ {
659+ if(xfadevalue <= 0) // ...but do not interrupt crossfade
660+ {
661+ jump = period; // jump forward
662+ while((jump * 2) < readlag) jump *= 2; // use available space
663+ readlag -= jump; // reduce read pointer lag
664+ xfadevalue = 1; // start crossfade
665+ xfadelength = period - 1;
666+ xfadestep = xfadespeed / xfadelength;
667+ }
668+ }
669+
670+ readindex = refindex - readlag;
671+ outputsample = read_sample(w, readindex);
672+
673+ if(xfadevalue > 0)
674+ {
675+ outputsample *= (1 - xfadevalue); // fadein
676+ outputsample += read_sample(w, readindex - jump) * xfadevalue; // fadeout
677+ xfadevalue -= xfadestep;
678+ }
679+
680+ *out++ = outputsample;
681+ refindex += 1;
682+ readlag += readlagstep;
620683 }
621684
622− r->inputPeriod = 0.0f;
623−}
624−
625−void tAutotune_free(tAutotune* const rt)
626−{
627− _tAutotune* r = *rt;
628−
629− tPeriodDetection_free(&r->pd);
630− for (int i = 0; i < r->numVoices; ++i)
631− {
632− tPitchShift_free(&r->ps[i]);
633− leaf_free(r->outBuffers[i]);
634− }
635− leaf_free(r->tickOutput);
636− leaf_free(r->freq);
637− leaf_free(r->ps);
638− leaf_free(r->inBuffer);
639− leaf_free(r->outBuffers);
640− leaf_free(r);
685+ w->jump = jump; // state variables
686+ w->readlag = readlag;
687+ w->xfadevalue = xfadevalue;
688+ w->xfadelength = xfadelength;
641689 }
642690
643−float* tAutotune_tick(tAutotune* const rt, float sample)
644−{
645− _tAutotune* r = *rt;
646−
647− float tempPeriod = tPeriodDetection_findPeriod(&r->pd, sample);
648− if (tempPeriod < 1000.0f) //to avoid trying to follow consonants JS
649− {
650− r->inputPeriod = tempPeriod;
651− }
652−
653− for (int v = 0; v < r->numVoices; ++v)
654− {
655− r->tickOutput[v] = tPitchShift_shiftToFreq(&r->ps[v], r->freq[v]);
656− }
657691
658− return r->tickOutput;
659−}
660−
661−void tAutotune_setNumVoices(tAutotune* const rt, int numVoices)
692+/*
693+ Function pitchup() for pitch factors above 1 is more complicated than
694+ pitchdown(). The read pointer increments faster than the write pointer and a
695+ backward jump must happen in time, reckoning with the crossfade region. The read
696+ pointer backward jump length is always one period. In order to minimize the area
697+ of signal duplicates, crossfade length is aimed at [period / pitchfactor].
698+ This leads to a crossfade speed of [pitchfactor * pitchfactor].
699+
700+ Some samples for the fade out (but not all of them) must already be in the
701+ buffer, otherwise we will run out of input samples before the crossfade is
702+ completed. The ratio of past samples and future samples for a crossfade of any
703+ length is as follows:
704+
705+ past samples: xfadelength * (1 - 1 / pitchfactor)
706+ future samples: xfadelength * (1 / pitchfactor)
707+
708+ For example in the case of pitch factor 1.5 this would be:
709+
710+ past samples: xfadelength * (1 - 1 / 1.5) = xfadelength * 1 / 3
711+ future samples: xfadelength * (1 / 1.5) = xfadelength * 2 / 3
712+
713+ In the case of pitch factor 4 this would be:
714+
715+ past samples: xfadelength * (1 - 1 / 4) = xfadelength * 3 / 4
716+ future samples: xfadelength * (1 / 4) = xfadelength * 1 / 4
717+
718+ The read pointer lag must therefore preserve a minimum dependent on pitch
719+ factor. The minimum is called 'limit' here:
720+
721+ limit = period * (pitchfactor - 1) / pitchfactor * pitchfactor
722+
723+ Components of this expression are combined to reuse them in operations, while
724+ (pitchfactor - 1) is changed to (pitchfactor - 0.99) to avoid numerical
725+ resolution issues for pitch factors slightly above 1:
726+
727+ xfadespeed = pitchfactor * pitchfactor
728+ limitfactor = (pitchfactor - 0.99) / xfadespeed
729+ limit = period * limitfactor
730+
731+ When read lag is smaller than this limit, the read pointer must preferably
732+ jump backward, unless a previous crossfade is not yet completed. Crossfades must
733+ preferably be completed, unless the read pointer lag becomes smaller than zero.
734+ With fluctuating period lengths and pitch factors, the readpointer lag limit may
735+ change from one input block to the next in such a way that the actual lag is
736+ suddenly much smaller than the limit, and the intended crossfade length can not
737+ be applied. Therefore the crossfade length is simply calculated from the
738+ available amount of samples for all cases, like so:
739+
740+ xfadelength = readlag / limitfactor
741+
742+ For most occurrences, this will amount to a crossfade length reduced to
743+ [period / pitchfactor] in the output for pitch factors above 1, while in some
744+ cases it will be considerably shorter. Fortunately, an incidental aberration of
745+ the intended crossfade length hardly ever creates an audible artifact. The
746+ reason to specify preferred crossfade length according to pitch factor is to
747+ minimize the impression of echoes without sacrificing too much of the signal
748+ content. The readpointer jump length remains one period in any case.
749+
750+ Sometimes, the input signal periodicity may decrease substantially between one
751+ signal block and the next. In such cases it may be possible for the read pointer
752+ to jump forward and reduce latency. For every signal block, a check on this
753+ possibility is done. A previous crossfade must be completed before a forward
754+ jump is allowed.
755+ */
756+static void pitchup(_tSOLAD* const w, float *out)
662757 {
663− _tAutotune* r = *rt;
664−
665− for (int i = 0; i < r->numVoices; ++i)
666− {
667− tPitchShift_free(&r->ps[i]);
668− leaf_free(r->outBuffers[i]);
669− }
670− leaf_free(r->tickOutput);
671− leaf_free(r->freq);
672− leaf_free(r->ps);
673− leaf_free(r->outBuffers);
758+ int n = w->blocksize;
759+ float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values
760+ float pitchfactor = w->pitchfactor;
761+ float period = w->period;
762+ float readlag = w->readlag;
763+ float jump = w->jump;
764+ float xfadevalue = w->xfadevalue;
765+ float xfadelength = w->xfadelength;
674766
675− r->numVoices = numVoices;
767+ float readlagstep = pitchfactor - 1;
768+ float xfadespeed = pitchfactor * pitchfactor;
769+ float xfadestep = xfadespeed / xfadelength;
770+ float limitfactor = (pitchfactor - (float)0.99) / xfadespeed;
771+ float limit = period * limitfactor;
772+ float readindex, outputsample;
676773
677− r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices);
678− r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices);
679− r->freq = (float*) leaf_alloc(sizeof(float) * r->numVoices);
680− r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices);
681− for (int i = 0; i < r->numVoices; ++i)
774+ if((readlag > (period + 2 * limit)) & (xfadevalue < 0))
682775 {
683− r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize);
684− tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize);
776+ jump = period; // jump forward
777+ while((jump * 2) < (readlag - 2 * limit)) jump *= 2; // use available space
778+ readlag -= jump; // reduce read pointer lag
779+ xfadevalue = 1; // start crossfade
780+ xfadelength = period - 1;
781+ xfadestep = xfadespeed / xfadelength;
685782 }
686783
687−
688−}
689−
690−void tAutotune_setFreqs(tAutotune* const rt, float f)
691−{
692− _tAutotune* r = *rt;
693−
694− for (int i = 0; i < r->numVoices; ++i)
784+ while(n--)
695785 {
696− r->freq[i] = f;
786+ if(readlag < limit) // check if read pointer should jump backward...
787+ {
788+ if((xfadevalue < 0) | (readlag < 0)) // ...but try not to interrupt crossfade
789+ {
790+ xfadelength = readlag / limitfactor;
791+ if(xfadelength < 1) xfadelength = 1;
792+ xfadestep = xfadespeed / xfadelength;
793+
794+ jump = -period; // jump backward
795+ readlag += period; // increase read pointer lag
796+ xfadevalue = 1; // start crossfade
797+ }
798+ }
799+
800+ readindex = refindex - readlag;
801+ outputsample = read_sample(w, readindex);
802+
803+ if(xfadevalue > 0)
804+ {
805+ outputsample *= (1 - xfadevalue);
806+ outputsample += read_sample(w, readindex - jump) * xfadevalue;
807+ xfadevalue -= xfadestep;
808+ }
809+
810+ *out++ = outputsample;
811+ refindex += 1;
812+ readlag -= readlagstep;
697813 }
698−}
699−
700−void tAutotune_setFreq(tAutotune* const rt, float f, int voice)
701−{
702− _tAutotune* r = *rt;
703814
704− r->freq[voice] = f;
705−}
706−
707−void tAutotune_setTimeConstant(tAutotune* const rt, float tc)
708−{
709− _tAutotune* r = *rt;
710−
711− r->timeConstant = tc;
712− r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant);
713−}
714−
715−void tAutotune_setHopSize(tAutotune* const rt, int hs)
716−{
717− _tAutotune* r = *rt;
718−
719− r->hopSize = hs;
720− tPeriodDetection_setHopSize(&r->pd, r->hopSize);
721−}
722−
723−void tAutotune_setWindowSize(tAutotune* const rt, int ws)
724−{
725− _tAutotune* r = *rt;
726−
727− r->windowSize = ws;
728− tPeriodDetection_setWindowSize(&r->pd, r->windowSize);
815+ w->readlag = readlag; // state variables
816+ w->jump = jump;
817+ w->xfadelength = xfadelength;
818+ w->xfadevalue = xfadevalue;
729819 }
730820
731−float tAutotune_getInputPeriod(tAutotune* const rt)
821+// read one sample from delay buffer, with linear interpolation
822+static inline float read_sample(_tSOLAD* const w, float floatindex)
732823 {
733− _tAutotune* r = *rt;
824+ int index = (int)floatindex;
825+ float fraction = floatindex - (float)index;
826+ float *buf = w->delaybuf;
827+ index &= LOOPMASK;
734828
735− return r->inputPeriod;
829+ return (buf[index] + (fraction * (buf[index+1] - buf[index])));
736830 }
737831
738−float tAutotune_getInputFreq(tAutotune* const rt)
832+static void solad_init(_tSOLAD* const w)
739833 {
740− _tAutotune* r = *rt;
741−
742− return 1.0f/r->inputPeriod;
834+ w->timeindex = 0;
835+ w->xfadevalue = -1;
836+ w->period = INITPERIOD;
837+ w->readlag = INITPERIOD;
838+ w->blocksize = INITPERIOD;
743839 }
744840
745841 //============================================================================================================
@@ -776,7 +872,7 @@ static int pitchshift_attackdetect(_tPitchShift* ps) · 30 unmodified lines
776872
777873 void tPitchShift_init (tPitchShift* const psr, tPeriodDetection* pd, float* out, int bufSize)
778874 {
779− _tPitchShift* ps = *psr = (_tPitchShift*) leaf_alloc(sizeof(_tPitchShift));
875+ _tPitchShift* ps = *psr = (_tPitchShift*) leaf_allocAndClear(sizeof(_tPitchShift));
780876 _tPeriodDetection* p = *pd;
781877
782878 ps->p = pd;
@@ -806,6 +902,40 @@ void tPitchShift_free(tPitchShift* const psr) · 23 unmodified lines
806902 leaf_free(ps);
807903 }
808904
905+void tPitchShift_initToPool (tPitchShift* const psr, tPeriodDetection* const pd, float* out, int bufSize, tMempool* const mp)
906+{
907+ _tMempool* m = *mp;
908+ _tPitchShift* ps = *psr = (_tPitchShift*) mpool_allocAndClear(sizeof(_tPitchShift), m->pool);
909+ _tPeriodDetection* p = *pd;
910+
911+ ps->p = pd;
912+
913+ ps->outBuffer = out;
914+ ps->bufSize = bufSize;
915+ ps->frameSize = p->frameSize;
916+ ps->framesPerBuffer = ps->bufSize / ps->frameSize;
917+ ps->curBlock = 1;
918+ ps->lastBlock = 0;
919+ ps->index = 0;
920+ ps->pitchFactor = 1.0f;
921+
922+ tSOLAD_initToPool(&ps->sola, mp);
923+
924+ tHighpass_initToPool(&ps->hp, HPFREQ, mp);
925+
926+ tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO);
927+}
928+
929+void tPitchShift_freeFromPool (tPitchShift* const psr, tMempool* const mp)
930+{
931+ _tMempool* m = *mp;
932+ _tPitchShift* ps = *psr;
933+
934+ tSOLAD_freeFromPool(&ps->sola, mp);
935+ tHighpass_freeFromPool(&ps->hp, mp);
936+ mpool_free(ps, m->pool);
937+}
938+
809939 void tPitchShift_setPitchFactor(tPitchShift* psr, float pf)
810940 {
811941 _tPitchShift* ps = *psr;
@@ -916,340 +1046,435 @@ float tPitchShift_shiftToFunc (tPitchShift* psr, float (*fun)(float)) · 104 unmodified lines
9161046 if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
9171047 }
9181048
919− return out;
1049+ return out;
1050+}
1051+
1052+//============================================================================================================
1053+// RETUNE
1054+//============================================================================================================
1055+
1056+void tRetune_init(tRetune* const rt, int numVoices, int bufSize, int frameSize)
1057+{
1058+ _tRetune* r = *rt = (_tRetune*) leaf_allocAndClear(sizeof(_tRetune));
1059+
1060+ r->bufSize = bufSize;
1061+ r->frameSize = frameSize;
1062+ r->numVoices = numVoices;
1063+
1064+ r->inBuffer = (float*) leaf_allocAndClear(sizeof(float) * r->bufSize);
1065+ r->outBuffers = (float**) leaf_allocAndClear(sizeof(float*) * r->numVoices);
1066+
1067+ r->hopSize = DEFHOPSIZE;
1068+ r->windowSize = DEFWINDOWSIZE;
1069+ r->fba = FBA;
1070+ tRetune_setTimeConstant(rt, DEFTIMECONSTANT);
1071+
1072+ r->inputPeriod = 0.0f;
1073+
1074+ r->ps = (tPitchShift*) leaf_allocAndClear(sizeof(tPitchShift) * r->numVoices);
1075+ r->pitchFactor = (float*) leaf_allocAndClear(sizeof(float) * r->numVoices);
1076+ r->tickOutput = (float*) leaf_allocAndClear(sizeof(float) * r->numVoices);
1077+ for (int i = 0; i < r->numVoices; ++i)
1078+ {
1079+ r->outBuffers[i] = (float*) leaf_allocAndClear(sizeof(float) * r->bufSize);
1080+ }
1081+
1082+ tPeriodDetection_init(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize);
1083+
1084+ for (int i = 0; i < r->numVoices; ++i)
1085+ {
1086+ tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize);
1087+ }
1088+}
1089+
1090+void tRetune_free(tRetune* const rt)
1091+{
1092+ _tRetune* r = *rt;
1093+
1094+ tPeriodDetection_free(&r->pd);
1095+ for (int i = 0; i < r->numVoices; ++i)
1096+ {
1097+ tPitchShift_free(&r->ps[i]);
1098+ leaf_free(r->outBuffers[i]);
1099+ }
1100+ leaf_free(r->tickOutput);
1101+ leaf_free(r->pitchFactor);
1102+ leaf_free(r->ps);
1103+ leaf_free(r->inBuffer);
1104+ leaf_free(r->outBuffers);
1105+ leaf_free(r);
1106+}
1107+
1108+void tRetune_initToPool (tRetune* const rt, int numVoices, int bufSize, int frameSize, tMempool* const mp)
1109+{
1110+ _tMempool* m = *mp;
1111+ _tRetune* r = *rt = (_tRetune*) mpool_alloc(sizeof(_tRetune), m->pool);
1112+
1113+ r->bufSize = bufSize;
1114+ r->frameSize = frameSize;
1115+ r->numVoices = numVoices;
1116+
1117+ r->inBuffer = (float*) mpool_allocAndClear(sizeof(float) * r->bufSize, m->pool);
1118+ r->outBuffers = (float**) mpool_allocAndClear(sizeof(float*) * r->numVoices, m->pool);
1119+
1120+ r->hopSize = DEFHOPSIZE;
1121+ r->windowSize = DEFWINDOWSIZE;
1122+ r->fba = FBA;
1123+ tRetune_setTimeConstant(rt, DEFTIMECONSTANT);
1124+
1125+ r->inputPeriod = 0.0f;
1126+
1127+ r->ps = (tPitchShift*) mpool_allocAndClear(sizeof(tPitchShift) * r->numVoices, m->pool);
1128+ r->pitchFactor = (float*) mpool_allocAndClear(sizeof(float) * r->numVoices, m->pool);
1129+ r->tickOutput = (float*) mpool_allocAndClear(sizeof(float) * r->numVoices, m->pool);
1130+ for (int i = 0; i < r->numVoices; ++i)
1131+ {
1132+ r->outBuffers[i] = (float*) mpool_allocAndClear(sizeof(float) * r->bufSize, m->pool);
1133+ }
1134+
1135+ tPeriodDetection_initToPool(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize, mp);
1136+
1137+ for (int i = 0; i < r->numVoices; ++i)
1138+ {
1139+ tPitchShift_initToPool(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize, mp);
1140+ }
1141+}
1142+
1143+void tRetune_freeFromPool (tRetune* const rt, tMempool* const mp)
1144+{
1145+ _tMempool* m = *mp;
1146+ _tRetune* r = *rt;
1147+
1148+ tPeriodDetection_freeFromPool(&r->pd, mp);
1149+ for (int i = 0; i < r->numVoices; ++i)
1150+ {
1151+ tPitchShift_freeFromPool(&r->ps[i], mp);
1152+ mpool_free(r->outBuffers[i], m->pool);
1153+ }
1154+ mpool_free(r->tickOutput, m->pool);
1155+ mpool_free(r->pitchFactor, m->pool);
1156+ mpool_free(r->ps, m->pool);
1157+ mpool_free(r->inBuffer, m->pool);
1158+ mpool_free(r->outBuffers, m->pool);
1159+ mpool_free(r, m->pool);
1160+}
1161+
1162+float* tRetune_tick(tRetune* const rt, float sample)
1163+{
1164+ _tRetune* r = *rt;
1165+
1166+ r->inputPeriod = tPeriodDetection_findPeriod(&r->pd, sample);
1167+
1168+ for (int v = 0; v < r->numVoices; ++v)
1169+ {
1170+ r->tickOutput[v] = tPitchShift_shift(&r->ps[v]);
1171+ }
1172+
1173+ return r->tickOutput;
1174+}
1175+
1176+void tRetune_setNumVoices(tRetune* const rt, int numVoices)
1177+{
1178+ _tRetune* r = *rt;
1179+
1180+ for (int i = 0; i < r->numVoices; ++i)
1181+ {
1182+ tPitchShift_free(&r->ps[i]);
1183+ leaf_free(r->outBuffers[i]);
1184+ }
1185+ leaf_free(r->tickOutput);
1186+ leaf_free(r->pitchFactor);
1187+ leaf_free(r->ps);
1188+ leaf_free(r->outBuffers);
1189+
1190+ r->numVoices = numVoices;
1191+
1192+ r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices);
1193+ r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices);
1194+ r->pitchFactor = (float*) leaf_alloc(sizeof(float) * r->numVoices);
1195+ r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices);
1196+ for (int i = 0; i < r->numVoices; ++i)
1197+ {
1198+ r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize);
1199+ tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize);
1200+ }
1201+
1202+
9201203 }
9211204
922−//============================================================================================================
923−// SOLAD
924−//============================================================================================================
925−/******************************************************************************/
926−/***************** static function declarations *******************************/
927−/******************************************************************************/
928−
929−static void solad_init(_tSOLAD *w);
930−static inline float read_sample(_tSOLAD *w, float floatindex);
931−static void pitchdown(_tSOLAD *w, float *out);
932−static void pitchup(_tSOLAD *w, float *out);
933−
934−/******************************************************************************/
935−/***************** public access functions ************************************/
936−/******************************************************************************/
937−
938−// init
939−void tSOLAD_init(tSOLAD* const wp)
1205+void tRetune_setPitchFactors(tRetune* const rt, float pf)
9401206 {
941− _tSOLAD* w = *wp = (_tSOLAD*) leaf_alloc(sizeof(_tSOLAD));
1207+ _tRetune* r = *rt;
9421208
943− w->pitchfactor = 1.;
944− w->delaybuf = (float*) leaf_alloc(sizeof(float) * (LOOPSIZE+16));
945− solad_init(w);
1209+ for (int i = 0; i < r->numVoices; ++i)
1210+ {
1211+ r->pitchFactor[i] = pf;
1212+ tPitchShift_setPitchFactor(&r->ps[i], r->pitchFactor[i]);
1213+ }
9461214 }
9471215
948−void tSOLAD_free(tSOLAD* const wp)
1216+void tRetune_setPitchFactor(tRetune* const rt, float pf, int voice)
9491217 {
950− _tSOLAD* w = *wp;
1218+ _tRetune* r = *rt;
9511219
952− leaf_free(w->delaybuf);
953− leaf_free(w);
1220+ r->pitchFactor[voice] = pf;
1221+ tPitchShift_setPitchFactor(&r->ps[voice], r->pitchFactor[voice]);
9541222 }
9551223
956−// send one block of input samples, receive one block of output samples
957−void tSOLAD_ioSamples(tSOLAD* const wp, float* in, float* out, int blocksize)
1224+void tRetune_setTimeConstant(tRetune* const rt, float tc)
9581225 {
959− _tSOLAD* w = *wp;
960−
961− int i = w->timeindex;
962− int n = w->blocksize = blocksize;
1226+ _tRetune* r = *rt;
9631227
964− if(!i) w->delaybuf[LOOPSIZE] = in[0]; // copy one sample for interpolation
965− while(n--) w->delaybuf[i++] = *in++; // copy one input block to delay buffer
1228+ r->timeConstant = tc;
1229+ r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant);
1230+}
1231+
1232+void tRetune_setHopSize(tRetune* const rt, int hs)
1233+{
1234+ _tRetune* r = *rt;
9661235
967− if(w->pitchfactor > 1) pitchup(w, out);
968− else pitchdown(w, out);
1236+ r->hopSize = hs;
1237+ tPeriodDetection_setHopSize(&r->pd, r->hopSize);
1238+}
1239+
1240+void tRetune_setWindowSize(tRetune* const rt, int ws)
1241+{
1242+ _tRetune* r = *rt;
9691243
970− w->timeindex += blocksize;
971− w->timeindex &= LOOPMASK;
1244+ r->windowSize = ws;
1245+ tPeriodDetection_setWindowSize(&r->pd, r->windowSize);
9721246 }
9731247
974−// set periodicity analysis data
975−void tSOLAD_setPeriod(tSOLAD* const wp, float period)
1248+float tRetune_getInputPeriod(tRetune* const rt)
9761249 {
977− _tSOLAD* w = *wp;
1250+ _tRetune* r = *rt;
9781251
979− if(period > MAXPERIOD) period = MAXPERIOD;
980− if(period > MINPERIOD) w->period = period; // ignore period when too small
1252+ return r->inputPeriod;
9811253 }
9821254
983−// set pitch factor between 0.25 and 4
984−void tSOLAD_setPitchFactor(tSOLAD* const wp, float pitchfactor)
1255+float tRetune_getInputFreq(tRetune* const rt)
9851256 {
986− _tSOLAD* w = *wp;
1257+ _tRetune* r = *rt;
9871258
988− if (pitchfactor <= 0.0f) return;
989− w->pitchfactor = pitchfactor;
1259+ return 1.0f/r->inputPeriod;
9901260 }
9911261
992−// force readpointer lag
993−void tSOLAD_setReadLag(tSOLAD* const wp, float readlag)
1262+//============================================================================================================
1263+// AUTOTUNE
1264+//============================================================================================================
1265+
1266+void tAutotune_init(tAutotune* const rt, int numVoices, int bufSize, int frameSize)
9941267 {
995− _tSOLAD* w = *wp;
1268+ _tAutotune* r = *rt = (_tAutotune*) leaf_alloc(sizeof(_tAutotune));
9961269
997− if(readlag < 0) readlag = 0;
998− if(readlag < w->readlag) // do not jump backward, only forward
1270+ r->bufSize = bufSize;
1271+ r->frameSize = frameSize;
1272+ r->numVoices = numVoices;
1273+
1274+ r->inBuffer = (float*) leaf_alloc(sizeof(float) * r->bufSize);
1275+ r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices);
1276+
1277+ r->hopSize = DEFHOPSIZE;
1278+ r->windowSize = DEFWINDOWSIZE;
1279+ r->fba = FBA;
1280+ tAutotune_setTimeConstant(rt, DEFTIMECONSTANT);
1281+
1282+
1283+
1284+ r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices);
1285+ r->freq = (float*) leaf_alloc(sizeof(float) * r->numVoices);
1286+ r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices);
1287+ for (int i = 0; i < r->numVoices; ++i)
9991288 {
1000− w->jump = w->readlag - readlag;
1001− w->readlag = readlag;
1002− w->xfadelength = readlag;
1003− w->xfadevalue = 1;
1289+ r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize);
10041290 }
1291+
1292+ tPeriodDetection_init(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize);
1293+
1294+ for (int i = 0; i < r->numVoices; ++i)
1295+ {
1296+ tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize);
1297+ }
1298+
1299+ r->inputPeriod = 0.0f;
10051300 }
10061301
1007−// reset state variables
1008−void tSOLAD_resetState(tSOLAD* const wp)
1302+void tAutotune_free(tAutotune* const rt)
10091303 {
1010− _tSOLAD* w = *wp;
1011−
1012− int n = LOOPSIZE + 1;
1013− float *buf = w->delaybuf;
1304+ _tAutotune* r = *rt;
10141305
1015− while(n--) *buf++ = 0;
1016− solad_init(w);
1306+ tPeriodDetection_free(&r->pd);
1307+ for (int i = 0; i < r->numVoices; ++i)
1308+ {
1309+ tPitchShift_free(&r->ps[i]);
1310+ leaf_free(r->outBuffers[i]);
1311+ }
1312+ leaf_free(r->tickOutput);
1313+ leaf_free(r->freq);
1314+ leaf_free(r->ps);
1315+ leaf_free(r->inBuffer);
1316+ leaf_free(r->outBuffers);
1317+ leaf_free(r);
10171318 }
10181319
1019−/******************************************************************************/
1020−/******************** private procedures **************************************/
1021−/******************************************************************************/
1022−
1023−/*
1024− Function pitchdown() is called to read samples from the delay buffer when pitch
1025− factor is between 0.25 and 1. The read pointer lags behind because of the slowed
1026− down speed, and it must jump forward towards the write pointer soon as there is
1027− sufficient space to jump. That is, if there is at least one period of the input
1028− signal between read pointer and write pointer. When short periods follow up on
1029− long periods, the read pointer may have space to jump over more than one period
1030− lenghts. Jump length must be [periodlength ^ 2] in any case.
1031−
1032− A linear crossfade function joins the jump-from point with the jump-to point.
1033− The crossfade must be completed before another read pointer jump is allowed.
1034− Length of the crossfade function is stored as a number of samples in terms of
1035− the input sample rate. This length is dynamically translated
1036− to a crossfade length expressed in output reading rate, according to pitch
1037− factor which can change before the crossfade is completed. Crossfade length does
1038− not cover an invariable length in periods for all pitch transposition factors.
1039− For pitch factors from 0.5 till 1, crossfade length is stretched in the
1040− output just as much as the signal itself, as crossfade speed is set to equal
1041− pitch factor. For pitch factors below 0.5, the read pointer wants to jump
1042− forward before one period is read, therefore the crossfade length as expressed
1043− in output periods must be shorter. Crossfade speed is set to [1 - pitchfactor]
1044− for those cases. Pitch factor 0.5 is the natural switch point between crossfade
1045− speeds [pitchfactor] and [1 - pitchfactor] because 0.5 == 1 - 0.5. The crossfade
1046− speed modification for pitch factors below 0.5 also means that much of the
1047− original signal content will be skipped.
1048− */
1049−
1050−
1051−static void pitchdown(_tSOLAD* const w, float *out)
1320+void tAutotune_initToPool (tAutotune* const rt, int numVoices, int bufSize, int frameSize, tMempool* const mp)
10521321 {
1053− int n = w->blocksize;
1054− float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values!
1055− float pitchfactor = w->pitchfactor;
1056− float period = w->period;
1057− float readlag = w->readlag;
1058− float readlagstep = 1 - pitchfactor;
1059− float jump = w->jump;
1060− float xfadevalue = w->xfadevalue;
1061− float xfadelength = w->xfadelength;
1062− float xfadespeed, xfadestep, readindex, outputsample;
1322+ _tMempool* m = *mp;
1323+ _tAutotune* r = *rt = (_tAutotune*) mpool_alloc(sizeof(_tAutotune), m->pool);
10631324
1064− if(pitchfactor > 0.5) xfadespeed = pitchfactor;
1065− else xfadespeed = 1 - pitchfactor;
1066− xfadestep = xfadespeed / xfadelength;
1325+ r->bufSize = bufSize;
1326+ r->frameSize = frameSize;
1327+ r->numVoices = numVoices;
10671328
1068− while(n--)
1329+ r->inBuffer = (float*) mpool_alloc(sizeof(float) * r->bufSize, m->pool);
1330+ r->outBuffers = (float**) mpool_alloc(sizeof(float*) * r->numVoices, m->pool);
1331+
1332+ r->hopSize = DEFHOPSIZE;
1333+ r->windowSize = DEFWINDOWSIZE;
1334+ r->fba = FBA;
1335+ tAutotune_setTimeConstant(rt, DEFTIMECONSTANT);
1336+
1337+
1338+
1339+ r->ps = (tPitchShift*) mpool_alloc(sizeof(tPitchShift) * r->numVoices, m->pool);
1340+ r->freq = (float*) mpool_alloc(sizeof(float) * r->numVoices, m->pool);
1341+ r->tickOutput = (float*) mpool_alloc(sizeof(float) * r->numVoices, m->pool);
1342+ for (int i = 0; i < r->numVoices; ++i)
10691343 {
1070− if(readlag > period) // check if read pointer may jump forward...
1071− {
1072− if(xfadevalue <= 0) // ...but do not interrupt crossfade
1073− {
1074− jump = period; // jump forward
1075− while((jump * 2) < readlag) jump *= 2; // use available space
1076− readlag -= jump; // reduce read pointer lag
1077− xfadevalue = 1; // start crossfade
1078− xfadelength = period - 1;
1079− xfadestep = xfadespeed / xfadelength;
1080− }
1081− }
1082−
1083− readindex = refindex - readlag;
1084− outputsample = read_sample(w, readindex);
1085−
1086− if(xfadevalue > 0)
1087− {
1088− outputsample *= (1 - xfadevalue); // fadein
1089− outputsample += read_sample(w, readindex - jump) * xfadevalue; // fadeout
1090− xfadevalue -= xfadestep;
1091− }
1092−
1093− *out++ = outputsample;
1094− refindex += 1;
1095− readlag += readlagstep;
1344+ r->outBuffers[i] = (float*) mpool_alloc(sizeof(float) * r->bufSize, m->pool);
1345+ }
1346+
1347+ tPeriodDetection_initToPool(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize, mp);
1348+
1349+ for (int i = 0; i < r->numVoices; ++i)
1350+ {
1351+ tPitchShift_initToPool(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize, mp);
10961352 }
10971353
1098− w->jump = jump; // state variables
1099− w->readlag = readlag;
1100− w->xfadevalue = xfadevalue;
1101− w->xfadelength = xfadelength;
1354+ r->inputPeriod = 0.0f;
11021355 }
11031356
1357+void tAutotune_freeFromPool (tAutotune* const rt, tMempool* const mp)
1358+{
1359+ _tMempool* m = *mp;
1360+ _tAutotune* r = *rt;
1361+
1362+ tPeriodDetection_freeFromPool(&r->pd, mp);
1363+ for (int i = 0; i < r->numVoices; ++i)
1364+ {
1365+ tPitchShift_freeFromPool(&r->ps[i], mp);
1366+ mpool_free(r->outBuffers[i], m->pool);
1367+ }
1368+ mpool_free(r->tickOutput, m->pool);
1369+ mpool_free(r->freq, m->pool);
1370+ mpool_free(r->ps, m->pool);
1371+ mpool_free(r->inBuffer, m->pool);
1372+ mpool_free(r->outBuffers, m->pool);
1373+ mpool_free(r, m->pool);
1374+}
11041375
1105−/*
1106− Function pitchup() for pitch factors above 1 is more complicated than
1107− pitchdown(). The read pointer increments faster than the write pointer and a
1108− backward jump must happen in time, reckoning with the crossfade region. The read
1109− pointer backward jump length is always one period. In order to minimize the area
1110− of signal duplicates, crossfade length is aimed at [period / pitchfactor].
1111− This leads to a crossfade speed of [pitchfactor * pitchfactor].
1112−
1113− Some samples for the fade out (but not all of them) must already be in the
1114− buffer, otherwise we will run out of input samples before the crossfade is
1115− completed. The ratio of past samples and future samples for a crossfade of any
1116− length is as follows:
1117−
1118− past samples: xfadelength * (1 - 1 / pitchfactor)
1119− future samples: xfadelength * (1 / pitchfactor)
1120−
1121− For example in the case of pitch factor 1.5 this would be:
1122−
1123− past samples: xfadelength * (1 - 1 / 1.5) = xfadelength * 1 / 3
1124− future samples: xfadelength * (1 / 1.5) = xfadelength * 2 / 3
1125−
1126− In the case of pitch factor 4 this would be:
1127−
1128− past samples: xfadelength * (1 - 1 / 4) = xfadelength * 3 / 4
1129− future samples: xfadelength * (1 / 4) = xfadelength * 1 / 4
1130−
1131− The read pointer lag must therefore preserve a minimum dependent on pitch
1132− factor. The minimum is called 'limit' here:
1133−
1134− limit = period * (pitchfactor - 1) / pitchfactor * pitchfactor
1135−
1136− Components of this expression are combined to reuse them in operations, while
1137− (pitchfactor - 1) is changed to (pitchfactor - 0.99) to avoid numerical
1138− resolution issues for pitch factors slightly above 1:
1139−
1140− xfadespeed = pitchfactor * pitchfactor
1141− limitfactor = (pitchfactor - 0.99) / xfadespeed
1142− limit = period * limitfactor
1143−
1144− When read lag is smaller than this limit, the read pointer must preferably
1145− jump backward, unless a previous crossfade is not yet completed. Crossfades must
1146− preferably be completed, unless the read pointer lag becomes smaller than zero.
1147− With fluctuating period lengths and pitch factors, the readpointer lag limit may
1148− change from one input block to the next in such a way that the actual lag is
1149− suddenly much smaller than the limit, and the intended crossfade length can not
1150− be applied. Therefore the crossfade length is simply calculated from the
1151− available amount of samples for all cases, like so:
1152−
1153− xfadelength = readlag / limitfactor
1154−
1155− For most occurrences, this will amount to a crossfade length reduced to
1156− [period / pitchfactor] in the output for pitch factors above 1, while in some
1157− cases it will be considerably shorter. Fortunately, an incidental aberration of
1158− the intended crossfade length hardly ever creates an audible artifact. The
1159− reason to specify preferred crossfade length according to pitch factor is to
1160− minimize the impression of echoes without sacrificing too much of the signal
1161− content. The readpointer jump length remains one period in any case.
1162−
1163− Sometimes, the input signal periodicity may decrease substantially between one
1164− signal block and the next. In such cases it may be possible for the read pointer
1165− to jump forward and reduce latency. For every signal block, a check on this
1166− possibility is done. A previous crossfade must be completed before a forward
1167− jump is allowed.
1168− */
1169−static void pitchup(_tSOLAD* const w, float *out)
1376+float* tAutotune_tick(tAutotune* const rt, float sample)
11701377 {
1171− int n = w->blocksize;
1172− float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values
1173− float pitchfactor = w->pitchfactor;
1174− float period = w->period;
1175− float readlag = w->readlag;
1176− float jump = w->jump;
1177− float xfadevalue = w->xfadevalue;
1178− float xfadelength = w->xfadelength;
1378+ _tAutotune* r = *rt;
11791379
1180− float readlagstep = pitchfactor - 1;
1181− float xfadespeed = pitchfactor * pitchfactor;
1182− float xfadestep = xfadespeed / xfadelength;
1183− float limitfactor = (pitchfactor - (float)0.99) / xfadespeed;
1184− float limit = period * limitfactor;
1185− float readindex, outputsample;
1380+ float tempPeriod = tPeriodDetection_findPeriod(&r->pd, sample);
1381+ if (tempPeriod < 1000.0f) //to avoid trying to follow consonants JS
1382+ {
1383+ r->inputPeriod = tempPeriod;
1384+ }
1385+
1386+ for (int v = 0; v < r->numVoices; ++v)
1387+ {
1388+ r->tickOutput[v] = tPitchShift_shiftToFreq(&r->ps[v], r->freq[v]);
1389+ }
1390+
1391+ return r->tickOutput;
1392+}
1393+
1394+void tAutotune_setNumVoices(tAutotune* const rt, int numVoices)
1395+{
1396+ _tAutotune* r = *rt;
11861397
1187− if((readlag > (period + 2 * limit)) & (xfadevalue < 0))
1398+ for (int i = 0; i < r->numVoices; ++i)
11881399 {
1189− jump = period; // jump forward
1190− while((jump * 2) < (readlag - 2 * limit)) jump *= 2; // use available space
1191− readlag -= jump; // reduce read pointer lag
1192− xfadevalue = 1; // start crossfade
1193− xfadelength = period - 1;
1194− xfadestep = xfadespeed / xfadelength;
1400+ tPitchShift_free(&r->ps[i]);
1401+ leaf_free(r->outBuffers[i]);
11951402 }
1403+ leaf_free(r->tickOutput);
1404+ leaf_free(r->freq);
1405+ leaf_free(r->ps);
1406+ leaf_free(r->outBuffers);
11961407
1197− while(n--)
1408+ r->numVoices = numVoices;
1409+
1410+ r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices);
1411+ r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices);
1412+ r->freq = (float*) leaf_alloc(sizeof(float) * r->numVoices);
1413+ r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices);
1414+ for (int i = 0; i < r->numVoices; ++i)
11981415 {
1199− if(readlag < limit) // check if read pointer should jump backward...
1200− {
1201− if((xfadevalue < 0) | (readlag < 0)) // ...but try not to interrupt crossfade
1202− {
1203− xfadelength = readlag / limitfactor;
1204− if(xfadelength < 1) xfadelength = 1;
1205− xfadestep = xfadespeed / xfadelength;
1206−
1207− jump = -period; // jump backward
1208− readlag += period; // increase read pointer lag
1209− xfadevalue = 1; // start crossfade
1210− }
1211− }
1212−
1213− readindex = refindex - readlag;
1214− outputsample = read_sample(w, readindex);
1215−
1216− if(xfadevalue > 0)
1217− {
1218− outputsample *= (1 - xfadevalue);
1219− outputsample += read_sample(w, readindex - jump) * xfadevalue;
1220− xfadevalue -= xfadestep;
1221− }
1222−
1223− *out++ = outputsample;
1224− refindex += 1;
1225− readlag -= readlagstep;
1416+ r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize);
1417+ tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize);
12261418 }
12271419
1228− w->readlag = readlag; // state variables
1229− w->jump = jump;
1230− w->xfadelength = xfadelength;
1231− w->xfadevalue = xfadevalue;
1420+
12321421 }
12331422
1234−// read one sample from delay buffer, with linear interpolation
1235−static inline float read_sample(_tSOLAD* const w, float floatindex)
1423+void tAutotune_setFreqs(tAutotune* const rt, float f)
12361424 {
1237− int index = (int)floatindex;
1238− float fraction = floatindex - (float)index;
1239− float *buf = w->delaybuf;
1240− index &= LOOPMASK;
1425+ _tAutotune* r = *rt;
12411426
1242− return (buf[index] + (fraction * (buf[index+1] - buf[index])));
1427+ for (int i = 0; i < r->numVoices; ++i)
1428+ {
1429+ r->freq[i] = f;
1430+ }
12431431 }
12441432
1245−static void solad_init(_tSOLAD* const w)
1433+void tAutotune_setFreq(tAutotune* const rt, float f, int voice)
12461434 {
1247− w->timeindex = 0;
1248− w->xfadevalue = -1;
1249− w->period = INITPERIOD;
1250− w->readlag = INITPERIOD;
1251− w->blocksize = INITPERIOD;
1435+ _tAutotune* r = *rt;
1436+
1437+ r->freq[voice] = f;
1438+}
1439+
1440+void tAutotune_setTimeConstant(tAutotune* const rt, float tc)
1441+{
1442+ _tAutotune* r = *rt;
1443+
1444+ r->timeConstant = tc;
1445+ r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant);
1446+}
1447+
1448+void tAutotune_setHopSize(tAutotune* const rt, int hs)
1449+{
1450+ _tAutotune* r = *rt;
1451+
1452+ r->hopSize = hs;
1453+ tPeriodDetection_setHopSize(&r->pd, r->hopSize);
1454+}
1455+
1456+void tAutotune_setWindowSize(tAutotune* const rt, int ws)
1457+{
1458+ _tAutotune* r = *rt;
1459+
1460+ r->windowSize = ws;
1461+ tPeriodDetection_setWindowSize(&r->pd, r->windowSize);
1462+}
1463+
1464+float tAutotune_getInputPeriod(tAutotune* const rt)
1465+{
1466+ _tAutotune* r = *rt;
1467+
1468+ return r->inputPeriod;
1469+}
1470+
1471+float tAutotune_getInputFreq(tAutotune* const rt)
1472+{
1473+ _tAutotune* r = *rt;
1474+
1475+ return 1.0f/r->inputPeriod;
12521476 }
1477+
12531478 //============================================================================================================
12541479 // FORMANTSHIFTER
12551480 //============================================================================================================
@@ -1289,8 +1514,8 @@ void tFormantShifter_init(tFormantShifter* const fsr, int bufsize, int order) · 33 unmodified lines
12891514 fs->invIntensity = 1.0f;
12901515 tHighpass_init(&fs->hp, 20.0f);
12911516 tHighpass_init(&fs->hp2, 20.0f);
1292− tFeedbackLeveler_init(&fs->fbl1, 0.8f, .005f, 0.125, 1);
1293− tFeedbackLeveler_init(&fs->fbl2, 0.8f, .005f, 0.125, 1);
1517+ tFeedbackLeveler_init(&fs->fbl1, 0.8f, 0.01f, 0.125f, 0);
1518+ tFeedbackLeveler_init(&fs->fbl2, 0.8f, 0.01f, 0.125f, 0);
12941519 }
12951520
12961521 void tFormantShifter_free(tFormantShifter* const fsr)
@@ -1317,6 +1542,68 @@ void tFormantShifter_free(tFormantShifter* const fsr) · 20 unmodified lines
13171542 leaf_free(fs);
13181543 }
13191544
1545+void tFormantShifter_initToPool (tFormantShifter* const fsr, int bufsize, int order, tMempool* const mp)
1546+{
1547+ _tMempool* m = *mp;
1548+ _tFormantShifter* fs = *fsr = (_tFormantShifter*) mpool_alloc(sizeof(_tFormantShifter), m->pool);
1549+
1550+ fs->ford = order;
1551+ fs->bufsize = bufsize;
1552+ fs->fk = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool);
1553+ fs->fb = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool);
1554+ fs->fc = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool);
1555+ fs->frb = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool);
1556+ fs->frc = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool);
1557+ fs->fsig = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool);
1558+ fs->fsmooth = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool);
1559+ fs->ftvec = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool);
1560+
1561+ fs->fbuff = (float**) mpool_alloc(sizeof(float*) * fs->ford, m->pool);
1562+ for (int i = 0; i < fs->ford; i++)
1563+ {
1564+ fs->fbuff[i] = (float*) mpool_alloc(sizeof(float) * fs->bufsize, m->pool);
1565+ }
1566+
1567+ fs->falph = powf(0.001f, 80.0f / (leaf.sampleRate));
1568+ fs->flamb = -(0.8517f*sqrtf(atanf(0.06583f*leaf.sampleRate))-0.1916f);
1569+ fs->fhp = 0.0f;
1570+ fs->flp = 0.0f;
1571+ fs->flpa = powf(0.001f, 10.0f / (leaf.sampleRate));
1572+ fs->fmute = 1.0f;
1573+ fs->fmutealph = powf(0.001f, 1.0f / (leaf.sampleRate));
1574+ fs->cbi = 0;
1575+ fs->intensity = 1.0f;
1576+ fs->invIntensity = 1.0f;
1577+ tHighpass_initToPool(&fs->hp, 20.0f, mp);
1578+ tHighpass_initToPool(&fs->hp2, 20.0f, mp);
1579+ tFeedbackLeveler_initToPool(&fs->fbl1, 0.8f, .005f, 0.125, 1, mp);
1580+ tFeedbackLeveler_initToPool(&fs->fbl2, 0.8f, .005f, 0.125, 1, mp);
1581+}
1582+
1583+void tFormantShifter_freeFromPool (tFormantShifter* const fsr, tMempool* const mp)
1584+{
1585+ _tMempool* m = *mp;
1586+ _tFormantShifter* fs = *fsr;
1587+
1588+ mpool_free(fs->fk, m->pool);
1589+ mpool_free(fs->fb, m->pool);
1590+ mpool_free(fs->fc, m->pool);
1591+ mpool_free(fs->frb, m->pool);
1592+ mpool_free(fs->frc, m->pool);
1593+ mpool_free(fs->fsig, m->pool);
1594+ mpool_free(fs->fsmooth, m->pool);
1595+ mpool_free(fs->ftvec, m->pool);
1596+ for (int i = 0; i < fs->ford; i++)
1597+ {
1598+ mpool_free(fs->fbuff[i], m->pool);
1599+ }
1600+ mpool_free(fs->fbuff, m->pool);
1601+ tHighpass_freeFromPool(&fs->hp, mp);
1602+ tHighpass_freeFromPool(&fs->hp2, mp);
1603+ tFeedbackLeveler_freeFromPool(&fs->fbl1, mp);
1604+ tFeedbackLeveler_freeFromPool(&fs->fbl2, mp);
1605+ mpool_free(fs, m->pool);
1606+}
13201607
13211608 float tFormantShifter_tick(tFormantShifter* const fsr, float in)
13221609 {
@@ -1326,8 +1613,8 @@ float tFormantShifter_tick(tFormantShifter* const fsr, float in) · 3 unmodified lines
13261613 float tFormantShifter_remove(tFormantShifter* const fsr, float in)
13271614 {
13281615 _tFormantShifter* fs = *fsr;
1329− in = tFeedbackLeveler_tick(&fs->fbl1, in);
1330− in = tHighpass_tick(&fs->hp, tanhf(in * fs->intensity));
1616+ in = tFeedbackLeveler_tick(&fs->fbl1, in * fs->intensity);
1617+ in = tHighpass_tick(&fs->hp, in);
13311618
13321619
13331620 float fa, fb, fc, foma, falph, ford, flamb, tf, fk;
@@ -1363,8 +1650,8 @@ float tFormantShifter_remove(tFormantShifter* const fsr, float in) · 29 unmodified lines
13631650 {
13641651 fs->cbi = 0;
13651652 }
1366−
1367− return fa * fs->invIntensity;
1653+ return fa;
1654+ //return fa * fs->invIntensity;
13681655 }
13691656
13701657 float tFormantShifter_add(tFormantShifter* const fsr, float in)
@@ -1460,8 +1747,8 @@ float tFormantShifter_add(tFormantShifter* const fsr, float in) · 89 unmodified lines
14601747 fs->fmute = (1.0f-tf2) + tf2*fs->fmute;
14611748 // now tf is signal output
14621749 // ...and we're done messing with formants
1463− tf = tFeedbackLeveler_tick(&fs->fbl2, tf);
1464− //tf = tHighpass_tick(&fs->hp2, tanhf(tf));
1750+ //tf = tFeedbackLeveler_tick(&fs->fbl2, tf);
1751+ tf = tHighpass_tick(&fs->hp2, tanhf(tf));
14651752
14661753 return tf;
14671754 }
LEAF/Src/leaf-electrical.c+53−31
@@ -45,45 +45,44 @@ static float get_reflected_wave_for_ideal(tWDF* const n, float input, float inci · 44 unmodified lines
4545 static float get_reflected_wave_for_diode(tWDF* const n, float input, float incident_wave);
4646 static float get_reflected_wave_for_diode_pair(tWDF* const n, float input, float incident_wave);
4747
48−//WDF
49−void tWDF_init(tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR)
48+static void wdf_init(tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR)
5049 {
51− _tWDF* r = *wdf = (_tWDF*) leaf_alloc(sizeof(_tWDF));
50+ _tWDF* r = *wdf;
5251
53− r->type = type;
52+ r->type = type;
5453 r->child_left = rL;
5554 r->child_right = rR;
56− r->incident_wave_up = 0.0f;
57− r->incident_wave_left = 0.0f;
58− r->incident_wave_right = 0.0f;
59− r->reflected_wave_up = 0.0f;
60− r->reflected_wave_left = 0.0f;
61− r->reflected_wave_right = 0.0f;
62− r->sample_rate = leaf.sampleRate;
63− r->value = value;
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;
6463
6564 tWDF* child;
6665 if (r->child_left != NULL) child = r->child_left;
6766 else child = r->child_right;
6867
6968 if (r->type == Resistor)
70− {
71− r->port_resistance_up = r->value;
72− r->port_conductance_up = 1.0f / r->value;
73−
74− r->get_port_resistance = &get_port_resistance_for_resistor;
75− r->get_reflected_wave_up = &get_reflected_wave_for_resistor;
76− r->set_incident_wave = &set_incident_wave_for_leaf;
77− }
78− else if (r->type == Capacitor)
79− {
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+ {
8079 r->port_conductance_up = r->sample_rate * 2.0f * r->value;
81− r->port_resistance_up = 1.0f / r->port_conductance_up; //based on trapezoidal discretization
82−
83− r->get_port_resistance = &get_port_resistance_for_capacitor;
84− r->get_reflected_wave_up = &get_reflected_wave_for_capacitor;
85− r->set_incident_wave = &set_incident_wave_for_leaf;
86− }
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+ }
8786 else if (r->type == Inductor)
8887 {
8988 r->port_resistance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization
@@ -93,15 +92,15 @@ void tWDF_init(tWDF* const wdf, WDFComponentType type, float value, tWDF* const · 3 unmodified lines
9392 r->get_reflected_wave_up = &get_reflected_wave_for_capacitor; // same as capacitor
9493 r->set_incident_wave = &set_incident_wave_for_leaf_inverted;
9594 }
96− else if (r->type == ResistiveSource)
97− {
95+ else if (r->type == ResistiveSource)
96+ {
9897 r->port_resistance_up = r->value;
9998 r->port_conductance_up = 1.0f / r->port_resistance_up;
10099
101100 r->get_port_resistance = &get_port_resistance_for_resistive;
102101 r->get_reflected_wave_up = &get_reflected_wave_for_resistive;
103102 r->set_incident_wave = &set_incident_wave_for_leaf;
104− }
103+ }
105104 else if (r->type == Inverter)
106105 {
107106 r->port_resistance_up = tWDF_getPortResistance(r->child_left);
@@ -164,6 +163,13 @@ void tWDF_init(tWDF* const wdf, WDFComponentType type, float value, tWDF* const · 56 unmodified lines
164163 r->get_port_resistance = &get_port_resistance_for_root;
165164 }
166165 }
166+//WDF
167+void tWDF_init(tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR)
168+{
169+ *wdf = (_tWDF*) leaf_alloc(sizeof(_tWDF));
170+
171+ wdf_init(wdf, type, value, rL, rR);
172+}
167173
168174 void tWDF_free(tWDF* const wdf)
169175 {
@@ -172,6 +178,22 @@ void tWDF_free(tWDF* const wdf) · 2 unmodified lines
172178 leaf_free(r);
173179 }
174180
181+void tWDF_initToPool (tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR, tMempool* const mp)
182+{
183+ _tMempool* m = *mp;
184+ *wdf = (_tWDF*) mpool_alloc(sizeof(_tWDF), m->pool);
185+
186+ wdf_init(wdf, type, value, rL, rR);
187+}
188+
189+void tWDF_freeFromPool (tWDF* const wdf, tMempool* const mp)
190+{
191+ _tMempool* m = *mp;
192+ _tWDF* r = *wdf;
193+
194+ mpool_free(r, m->pool);
195+}
196+
175197 float tWDF_tick(tWDF* const wdf, float sample, tWDF* const outputPoint, uint8_t paramsChanged)
176198 {
177199 _tWDF* r = *wdf;
LEAF/Src/leaf-envelopes.c+165−1
@@ -62,7 +62,6 @@ void tEnvelope_init(tEnvelope* const envlp, float attack, float decay, oBool · 61 unmodified lines
6262 env->attackInc = env->inc_buff[attackIndex];
6363 env->decayInc = env->inc_buff[decayIndex];
6464 env->rampInc = env->inc_buff[rampIndex];
65−
6665 }
6766
6867 void tEnvelope_free(tEnvelope* const envlp)
@@ -71,6 +70,54 @@ void tEnvelope_free(tEnvelope* const envlp) · 2 unmodified lines
7170 leaf_free(env);
7271 }
7372
73+void tEnvelope_initToPool (tEnvelope* const envlp, float attack, float decay, oBool loop, tMempool* const mp)
74+{
75+ _tMempool* m = *mp;
76+ _tEnvelope* env = *envlp = (_tEnvelope*) mpool_alloc(sizeof(_tEnvelope), m->pool);
77+
78+ env->exp_buff = exp_decay;
79+ env->inc_buff = attack_decay_inc;
80+ env->buff_size = sizeof(exp_decay);
81+
82+ env->loop = loop;
83+
84+ if (attack > 8192.0f)
85+ attack = 8192.0f;
86+ if (attack < 0.0f)
87+ attack = 0.0f;
88+
89+ if (decay > 8192.0f)
90+ decay = 8192.0f;
91+ if (decay < 0.0f)
92+ decay = 0.0f;
93+
94+ int16_t attackIndex = ((int16_t)(attack * 8.0f))-1;
95+ int16_t decayIndex = ((int16_t)(decay * 8.0f))-1;
96+ int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1;
97+
98+ if (attackIndex < 0)
99+ attackIndex = 0;
100+ if (decayIndex < 0)
101+ decayIndex = 0;
102+ if (rampIndex < 0)
103+ rampIndex = 0;
104+
105+ env->inRamp = OFALSE;
106+ env->inAttack = OFALSE;
107+ env->inDecay = OFALSE;
108+
109+ env->attackInc = env->inc_buff[attackIndex];
110+ env->decayInc = env->inc_buff[decayIndex];
111+ env->rampInc = env->inc_buff[rampIndex];
112+}
113+
114+void tEnvelope_freeFromPool (tEnvelope* const envlp, tMempool* const mp)
115+{
116+ _tMempool* m = *mp;
117+ _tEnvelope* env = *envlp;
118+ mpool_free(env, m->pool);
119+}
120+
74121 void tEnvelope_setAttack(tEnvelope* const envlp, float attack)
75122 {
76123 _tEnvelope* env = *envlp;
@@ -270,6 +317,71 @@ void tADSR_free(tADSR* const adsrenv) · 193 unmodified lines
270317 leaf_free(adsr);
271318 }
272319
320+void tADSR_initToPool (tADSR* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp)
321+{
322+ _tMempool* m = *mp;
323+ _tADSR* adsr = *adsrenv = (_tADSR*) mpool_alloc(sizeof(_tADSR), m->pool);
324+
325+ adsr->exp_buff = exp_decay;
326+ adsr->inc_buff = attack_decay_inc;
327+ adsr->buff_size = sizeof(exp_decay);
328+
329+ if (attack > 8192.0f)
330+ attack = 8192.0f;
331+ if (attack < 0.0f)
332+ attack = 0.0f;
333+
334+ if (decay > 8192.0f)
335+ decay = 8192.0f;
336+ if (decay < 0.0f)
337+ decay = 0.0f;
338+
339+ if (sustain > 1.0f)
340+ sustain = 1.0f;
341+ if (sustain < 0.0f)
342+ sustain = 0.0f;
343+
344+ if (release > 8192.0f)
345+ release = 8192.0f;
346+ if (release < 0.0f)
347+ release = 0.0f;
348+
349+ int16_t attackIndex = ((int16_t)(attack * 8.0f))-1;
350+ int16_t decayIndex = ((int16_t)(decay * 8.0f))-1;
351+ int16_t releaseIndex = ((int16_t)(release * 8.0f))-1;
352+ int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1;
353+
354+ if (attackIndex < 0)
355+ attackIndex = 0;
356+ if (decayIndex < 0)
357+ decayIndex = 0;
358+ if (releaseIndex < 0)
359+ releaseIndex = 0;
360+ if (rampIndex < 0)
361+ rampIndex = 0;
362+
363+ adsr->inRamp = OFALSE;
364+ adsr->inAttack = OFALSE;
365+ adsr->inDecay = OFALSE;
366+ adsr->inSustain = OFALSE;
367+ adsr->inRelease = OFALSE;
368+
369+ adsr->sustain = sustain;
370+
371+ adsr->attackInc = adsr->inc_buff[attackIndex];
372+ adsr->decayInc = adsr->inc_buff[decayIndex];
373+ adsr->releaseInc = adsr->inc_buff[releaseIndex];
374+ adsr->rampInc = adsr->inc_buff[rampIndex];
375+}
376+
377+void tADSR_freeFromPool (tADSR* const adsrenv, tMempool* const mp)
378+{
379+ _tMempool* m = *mp;
380+ _tADSR* adsr = *adsrenv;
381+
382+ mpool_free(adsr, m->pool);
383+}
384+
273385 void tADSR_setAttack(tADSR* const adsrenv, float attack)
274386 {
275387 _tADSR* adsr = *adsrenv;
@@ -479,6 +591,37 @@ void tRamp_free(tRamp* const r) · 203 unmodified lines
479591 leaf_free(ramp);
480592 }
481593
594+void tRamp_initToPool (tRamp* const r, float time, int samples_per_tick, tMempool* const mp)
595+{
596+ _tMempool* m = *mp;
597+ _tRamp* ramp = *r = (_tRamp*) mpool_alloc(sizeof(_tRamp), m->pool);
598+
599+ ramp->inv_sr_ms = 1.0f/(leaf.sampleRate*0.001f);
600+ ramp->minimum_time = ramp->inv_sr_ms * samples_per_tick;
601+ ramp->curr = 0.0f;
602+ ramp->dest = 0.0f;
603+
604+ if (time < ramp->minimum_time)
605+ {
606+ ramp->time = ramp->minimum_time;
607+ }
608+ else
609+ {
610+ ramp->time = time;
611+ }
612+
613+ ramp->samples_per_tick = samples_per_tick;
614+ ramp->inc = ((ramp->dest - ramp->curr) / ramp->time * ramp->inv_sr_ms) * (float)ramp->samples_per_tick;
615+}
616+
617+void tRamp_freeFromPool (tRamp* const r, tMempool* const mp)
618+{
619+ _tMempool* m = *mp;
620+ _tRamp* ramp = *r;
621+
622+ mpool_free(ramp, m->pool);
623+}
624+
482625 void tRamp_setTime(tRamp* const ramp, float time)
483626 {
484627 _tRamp* r = *ramp;
@@ -560,6 +703,27 @@ void tExpSmooth_free(tExpSmooth* const expsmooth) · 75 unmodified lines
560703 leaf_free(smooth);
561704 }
562705
706+void tExpSmooth_initToPool (tExpSmooth* const expsmooth, float val, float factor, tMempool* const mp)
707+{
708+ _tMempool* m = *mp;
709+ _tExpSmooth* smooth = *expsmooth = (_tExpSmooth*) mpool_alloc(sizeof(_tExpSmooth), m->pool);
710+
711+ smooth->curr=val;
712+ smooth->dest=val;
713+ if (factor<0) factor=0;
714+ if (factor>1) factor=1;
715+ smooth->factor=factor;
716+ smooth->oneminusfactor=1.0f-factor;
717+}
718+
719+void tExpSmooth_freeFromPool (tExpSmooth* const expsmooth, tMempool* const mp)
720+{
721+ _tMempool* m = *mp;
722+ _tExpSmooth* smooth = *expsmooth;
723+
724+ mpool_free(smooth, m->pool);
725+}
726+
563727 void tExpSmooth_setFactor(tExpSmooth* const expsmooth, float factor)
564728 { // 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
565729 _tExpSmooth* smooth = *expsmooth;
LEAF/Src/leaf-filters.c+551−283
@@ -40,6 +40,27 @@ void tAllpass_free(tAllpass* const ft) · 39 unmodified lines
4040 leaf_free(f);
4141 }
4242
43+void tAllpass_initToPool (tAllpass* const ft, float initDelay, uint32_t maxDelay, tMempool* const mp)
44+{
45+ _tMempool* m = *mp;
46+ _tAllpass* f = *ft = (_tAllpass*) mpool_alloc(sizeof(_tAllpass), m->pool);
47+
48+ f->gain = 0.7f;
49+
50+ f->lastOut = 0.0f;
51+
52+ tLinearDelay_initToPool(&f->delay, initDelay, maxDelay, mp);
53+}
54+
55+void tAllpass_freeFromPool (tAllpass* const ft, tMempool* const mp)
56+{
57+ _tMempool* m = *mp;
58+ _tAllpass* f = *ft;
59+
60+ tLinearDelay_freeFromPool(&f->delay, mp);
61+ mpool_free(f, m->pool);
62+}
63+
4364 void tAllpass_setDelay(tAllpass* const ft, float delay)
4465 {
4566 _tAllpass* f = *ft;
@@ -67,77 +88,236 @@ float tAllpass_tick(tAllpass* const ft, float input) · 21 unmodified lines
6788 return f->lastOut;
6889 }
6990
70−void tButterworth_init(tButterworth* const ft, int N, float f1, float f2)
91+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
92+void tOnePole_init(tOnePole* const ft, float freq)
7193 {
72− _tButterworth* f = *ft = (_tButterworth*) leaf_alloc(sizeof(_tButterworth));
94+ _tOnePole* f = *ft = (_tOnePole*) leaf_alloc(sizeof(_tOnePole));
7395
74− f->f1 = f1;
75− f->f2 = f2;
76− f->gain = 1.0f;
96+ f->gain = 1.0f;
97+ f->a0 = 1.0;
7798
78− f->N = N;
99+ tOnePole_setFreq(ft, freq);
79100
80− if (f->N > NUM_SVF_BW) f->N = NUM_SVF_BW;
101+ f->lastIn = 0.0f;
102+ f->lastOut = 0.0f;
103+}
81104
82− for(int i = 0; i < N/2; ++i)
83− {
84− tSVF_init(&f->low[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)));
85− tSVF_init(&f->high[i], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)));
86− }
105+void tOnePole_free(tOnePole* const ft)
106+{
107+ _tOnePole* f = *ft;
108+
109+ leaf_free(f);
87110 }
88111
89−void tButterworth_free(tButterworth* const ft)
112+void tOnePole_initToPool (tOnePole* const ft, float freq, tMempool* const mp)
90113 {
91− _tButterworth* f = *ft;
114+ _tMempool* m = *mp;
115+ _tOnePole* f = *ft = (_tOnePole*) mpool_alloc(sizeof(_tOnePole), m->pool);
92116
93− for(int i = 0; i < f->N/2; ++i)
94− {
95− tSVF_free(&f->low[i]);
96− tSVF_free(&f->high[i]);
97− }
117+ f->gain = 1.0f;
118+ f->a0 = 1.0;
119+
120+ tOnePole_setFreq(ft, freq);
121+
122+ f->lastIn = 0.0f;
123+ f->lastOut = 0.0f;
124+}
125+
126+void tOnePole_freeFromPool (tOnePole* const ft, tMempool* const mp)
127+{
128+ _tMempool* m = *mp;
129+ _tOnePole* f = *ft;
130+
131+ mpool_free(f, m->pool);
132+}
133+
134+void tOnePole_setB0(tOnePole* const ft, float b0)
135+{
136+ _tOnePole* f = *ft;
137+ f->b0 = b0;
138+}
139+
140+void tOnePole_setA1(tOnePole* const ft, float a1)
141+{
142+ _tOnePole* f = *ft;
143+ if (a1 >= 1.0f) a1 = 0.999999f;
144+ f->a1 = a1;
145+}
146+
147+void tOnePole_setPole(tOnePole* const ft, float thePole)
148+{
149+ _tOnePole* f = *ft;
150+
151+ if (thePole >= 1.0f) thePole = 0.999999f;
152+
153+ // Normalize coefficients for peak unity gain.
154+ if (thePole > 0.0f) f->b0 = (1.0f - thePole);
155+ else f->b0 = (1.0f + thePole);
156+
157+ f->a1 = -thePole;
158+}
159+
160+void tOnePole_setFreq (tOnePole* const ft, float freq)
161+{
162+ _tOnePole* f = *ft;
163+ f->b0 = freq * leaf.twoPiTimesInvSampleRate;
164+ f->b0 = LEAF_clip(0.0f, f->b0, 1.0f);
165+ f->a1 = 1.0f - f->b0;
166+}
167+
168+void tOnePole_setCoefficients(tOnePole* const ft, float b0, float a1)
169+{
170+ _tOnePole* f = *ft;
171+ if (a1 >= 1.0f) a1 = 0.999999f;
172+ f->b0 = b0;
173+ f->a1 = a1;
174+}
175+
176+void tOnePole_setGain(tOnePole* const ft, float gain)
177+{
178+ _tOnePole* f = *ft;
179+ f->gain = gain;
180+}
181+
182+float tOnePole_tick(tOnePole* const ft, float input)
183+{
184+ _tOnePole* f = *ft;
185+
186+ float in = input * f->gain;
187+ float out = (f->b0 * in) + (f->a1 * f->lastOut);
188+
189+ f->lastIn = in;
190+ f->lastOut = out;
191+
192+ return out;
193+}
194+
195+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoPole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
196+void tTwoPole_init(tTwoPole* const ft)
197+{
198+ _tTwoPole* f = *ft = (_tTwoPole*) leaf_alloc(sizeof(_tTwoPole));
199+
200+ f->gain = 1.0f;
201+ f->a0 = 1.0;
202+ f->b0 = 1.0;
203+
204+ f->lastOut[0] = 0.0f;
205+ f->lastOut[1] = 0.0f;
206+}
207+
208+void tTwoPole_free(tTwoPole* const ft)
209+{
210+ _tTwoPole* f = *ft;
98211
99212 leaf_free(f);
100213 }
101214
102−float tButterworth_tick(tButterworth* const ft, float samp)
215+void tTwoPole_initToPool (tTwoPole* const ft, tMempool* const mp)
103216 {
104− _tButterworth* f = *ft;
217+ _tMempool* m = *mp;
218+ _tTwoPole* f = *ft = (_tTwoPole*) mpool_alloc(sizeof(_tTwoPole), m->pool);
219+
220+ f->gain = 1.0f;
221+ f->a0 = 1.0;
222+ f->b0 = 1.0;
105223
106− for(int i = 0; i < ((f->N)/2); ++i)
107− {
108− samp = tSVF_tick(&f->low[i],samp);
109− samp = tSVF_tick(&f->high[i],samp);
110− }
111− return samp;
224+ f->lastOut[0] = 0.0f;
225+ f->lastOut[1] = 0.0f;
112226 }
113227
114−void tButterworth_setF1(tButterworth* const ft, float f1)
228+void tTwoPole_freeFromPool (tTwoPole* const ft, tMempool* const mp)
115229 {
116− _tButterworth* f = *ft;
230+ _tMempool* m = *mp;
231+ _tTwoPole* f = *ft;
117232
118− f->f1 = f1;
119− for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->low[i], f1);
233+ mpool_free(f, m->pool);
120234 }
121235
122−void tButterworth_setF2(tButterworth* const ft, float f2)
236+float tTwoPole_tick(tTwoPole* const ft, float input)
123237 {
124− _tButterworth* f = *ft;
238+ _tTwoPole* f = *ft;
125239
126− f->f2 = f2;
127− for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->high[i], f2);
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;
128247 }
129248
130−void tButterworth_setFreqs(tButterworth* const ft, float f1, float f2)
249+void tTwoPole_setB0(tTwoPole* const ft, float b0)
131250 {
132− _tButterworth* f = *ft;
251+ _tTwoPole* f = *ft;
252+ f->b0 = b0;
253+}
254+
255+void tTwoPole_setA1(tTwoPole* const ft, float a1)
256+{
257+ _tTwoPole* f = *ft;
258+ f->a1 = a1;
259+}
260+
261+void tTwoPole_setA2(tTwoPole* const ft, float a2)
262+{
263+ _tTwoPole* f = *ft;
264+ f->a2 = a2;
265+}
266+
267+
268+void tTwoPole_setResonance(tTwoPole* const ft, float frequency, float radius, oBool normalize)
269+{
270+ _tTwoPole* f = *ft;
271+
272+ if (frequency < 0.0f) frequency = 0.0f;
273+ if (frequency > (leaf.sampleRate * 0.49f)) frequency = leaf.sampleRate * 0.49f;
274+ if (radius < 0.0f) radius = 0.0f;
275+ if (radius >= 1.0f) radius = 0.999999f;
276+
277+ f->radius = radius;
278+ f->frequency = frequency;
279+ f->normalize = normalize;
280+
281+ f->a2 = radius * radius;
282+ f->a1 = -2.0f * radius * cosf(frequency * leaf.twoPiTimesInvSampleRate);
283+
284+ if ( normalize )
285+ {
286+ // Normalize the filter gain ... not terribly efficient.
287+ float real = 1 - radius + (f->a2 - radius) * cosf(2 * frequency * leaf.twoPiTimesInvSampleRate);
288+ float imag = (f->a2 - radius) * sinf(2 * frequency * leaf.twoPiTimesInvSampleRate);
289+ f->b0 = sqrtf( powf(real, 2) + powf(imag, 2) );
290+ }
291+}
292+
293+void tTwoPole_setCoefficients(tTwoPole* const ft, float b0, float a1, float a2)
294+{
295+ _tTwoPole* f = *ft;
296+ f->b0 = b0;
297+ f->a1 = a1;
298+ f->a2 = a2;
299+}
300+
301+void tTwoPole_setGain(tTwoPole* const ft, float gain)
302+{
303+ _tTwoPole* f = *ft;
304+ f->gain = gain;
305+}
306+
307+void tTwoPoleSampleRateChanged (tTwoPole* const ft)
308+{
309+ _tTwoPole* f = *ft;
310+
311+ f->a2 = f->radius * f->radius;
312+ f->a1 = -2.0f * f->radius * cosf(f->frequency * leaf.twoPiTimesInvSampleRate);
133313
134− f->f1 = f1;
135− f->f2 = f2;
136− for(int i = 0; i < ((f->N)/2); ++i)
137− {
138− tSVF_setFreq(&f->low[i], f1);
139− tSVF_setFreq(&f->high[i], f2);
140− }
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+ }
141321 }
142322
143323 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OneZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
@@ -158,6 +338,25 @@ void tOneZero_free(tOneZero* const ft) · 14 unmodified lines
158338 leaf_free(f);
159339 }
160340
341+void tOneZero_initToPool (tOneZero* const ft, float theZero, tMempool* const mp)
342+{
343+ _tMempool* m = *mp;
344+ _tOneZero* f = *ft = (_tOneZero*) mpool_alloc(sizeof(_tOneZero), m->pool);
345+
346+ f->gain = 1.0f;
347+ f->lastIn = 0.0f;
348+ f->lastOut = 0.0f;
349+ tOneZero_setZero(ft, theZero);
350+}
351+
352+void tOneZero_freeFromPool (tOneZero* const ft, tMempool* const mp)
353+{
354+ _tMempool* m = *mp;
355+ _tOneZero* f = *ft;
356+
357+ mpool_free(f, m->pool);
358+}
359+
161360 float tOneZero_tick(tOneZero* const ft, float input)
162361 {
163362 _tOneZero* f = *ft;
@@ -254,6 +453,24 @@ void tTwoZero_free(tTwoZero* const ft) · 90 unmodified lines
254453 leaf_free(f);
255454 }
256455
456+void tTwoZero_initToPool (tTwoZero* const ft, tMempool* const mp)
457+{
458+ _tMempool* m = *mp;
459+ _tTwoZero* f = *ft = (_tTwoZero*) mpool_alloc(sizeof(_tTwoZero), m->pool);
460+
461+ f->gain = 1.0f;
462+ f->lastIn[0] = 0.0f;
463+ f->lastIn[1] = 0.0f;
464+}
465+
466+void tTwoZero_freeFromPool (tTwoZero* const ft, tMempool* const mp)
467+{
468+ _tMempool* m = *mp;
469+ _tTwoZero* f = *ft;
470+
471+ mpool_free(f, m->pool);
472+}
473+
257474 float tTwoZero_tick(tTwoZero* const ft, float input)
258475 {
259476 _tTwoZero* f = *ft;
@@ -324,199 +541,30 @@ void tTwoZeroSampleRateChanged(tTwoZero* const ft) · 64 unmodified lines
324541 tTwoZero_setNotch(ft, f->frequency, f->radius);
325542 }
326543
327−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
328−void tOnePole_init(tOnePole* const ft, float freq)
544+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PoleZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
545+void tPoleZero_init(tPoleZero* const pzf)
329546 {
330− _tOnePole* f = *ft = (_tOnePole*) leaf_alloc(sizeof(_tOnePole));
547+ _tPoleZero* f = *pzf = (_tPoleZero*) leaf_alloc(sizeof(_tPoleZero));
331548
332549 f->gain = 1.0f;
550+ f->b0 = 1.0;
333551 f->a0 = 1.0;
334−
335− tOnePole_setFreq(ft, freq);
336552
337553 f->lastIn = 0.0f;
338554 f->lastOut = 0.0f;
339555 }
340556
341−void tOnePole_free(tOnePole* const ft)
342−{
343− _tOnePole* f = *ft;
344−
345− leaf_free(f);
346−}
347−
348−void tOnePole_setB0(tOnePole* const ft, float b0)
349−{
350− _tOnePole* f = *ft;
351− f->b0 = b0;
352−}
353−
354−void tOnePole_setA1(tOnePole* const ft, float a1)
355−{
356− _tOnePole* f = *ft;
357− if (a1 >= 1.0f) a1 = 0.999999f;
358− f->a1 = a1;
359−}
360−
361−void tOnePole_setPole(tOnePole* const ft, float thePole)
362−{
363− _tOnePole* f = *ft;
364−
365− if (thePole >= 1.0f) thePole = 0.999999f;
366−
367− // Normalize coefficients for peak unity gain.
368− if (thePole > 0.0f) f->b0 = (1.0f - thePole);
369− else f->b0 = (1.0f + thePole);
370−
371− f->a1 = -thePole;
372−}
373−
374−void tOnePole_setFreq (tOnePole* const ft, float freq)
375−{
376− _tOnePole* f = *ft;
377− f->b0 = freq * leaf.twoPiTimesInvSampleRate;
378− f->b0 = LEAF_clip(0.0f, f->b0, 1.0f);
379− f->a1 = 1.0f - f->b0;
380−}
381−
382−void tOnePole_setCoefficients(tOnePole* const ft, float b0, float a1)
383−{
384− _tOnePole* f = *ft;
385− if (a1 >= 1.0f) a1 = 0.999999f;
386− f->b0 = b0;
387− f->a1 = a1;
388−}
389−
390−void tOnePole_setGain(tOnePole* const ft, float gain)
391−{
392− _tOnePole* f = *ft;
393− f->gain = gain;
394−}
395−
396−float tOnePole_tick(tOnePole* const ft, float input)
397−{
398− _tOnePole* f = *ft;
399−
400− float in = input * f->gain;
401− float out = (f->b0 * in) + (f->a1 * f->lastOut);
402−
403− f->lastIn = in;
404− f->lastOut = out;
405−
406− return out;
407−}
408−
409−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoPole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
410−void tTwoPole_init(tTwoPole* const ft)
411−{
412− _tTwoPole* f = *ft = (_tTwoPole*) leaf_alloc(sizeof(_tTwoPole));
413−
414− f->gain = 1.0f;
415− f->a0 = 1.0;
416− f->b0 = 1.0;
417−
418− f->lastOut[0] = 0.0f;
419− f->lastOut[1] = 0.0f;
420−}
421−
422−void tTwoPole_free(tTwoPole* const ft)
557+void tPoleZero_free(tPoleZero* const pzf)
423558 {
424− _tTwoPole* f = *ft;
559+ _tPoleZero* f = *pzf;
425560
426561 leaf_free(f);
427562 }
428563
429−float tTwoPole_tick(tTwoPole* const ft, float input)
564+void tPoleZero_initToPool (tPoleZero* const pzf, tMempool* const mp)
430565 {
431− _tTwoPole* f = *ft;
432−
433− float in = input * f->gain;
434− float out = (f->b0 * in) - (f->a1 * f->lastOut[0]) - (f->a2 * f->lastOut[1]);
435−
436− f->lastOut[1] = f->lastOut[0];
437− f->lastOut[0] = out;
438−
439− return out;
440−}
441−
442−void tTwoPole_setB0(tTwoPole* const ft, float b0)
443−{
444− _tTwoPole* f = *ft;
445− f->b0 = b0;
446−}
447−
448−void tTwoPole_setA1(tTwoPole* const ft, float a1)
449−{
450− _tTwoPole* f = *ft;
451− f->a1 = a1;
452−}
453−
454−void tTwoPole_setA2(tTwoPole* const ft, float a2)
455−{
456− _tTwoPole* f = *ft;
457− f->a2 = a2;
458−}
459−
460−
461−void tTwoPole_setResonance(tTwoPole* const ft, float frequency, float radius, oBool normalize)
462−{
463− _tTwoPole* f = *ft;
464−
465− if (frequency < 0.0f) frequency = 0.0f;
466− if (frequency > (leaf.sampleRate * 0.49f)) frequency = leaf.sampleRate * 0.49f;
467− if (radius < 0.0f) radius = 0.0f;
468− if (radius >= 1.0f) radius = 0.999999f;
469−
470− f->radius = radius;
471− f->frequency = frequency;
472− f->normalize = normalize;
473−
474− f->a2 = radius * radius;
475− f->a1 = -2.0f * radius * cosf(frequency * leaf.twoPiTimesInvSampleRate);
476−
477− if ( normalize )
478− {
479− // Normalize the filter gain ... not terribly efficient.
480− float real = 1 - radius + (f->a2 - radius) * cosf(2 * frequency * leaf.twoPiTimesInvSampleRate);
481− float imag = (f->a2 - radius) * sinf(2 * frequency * leaf.twoPiTimesInvSampleRate);
482− f->b0 = sqrtf( powf(real, 2) + powf(imag, 2) );
483− }
484−}
485−
486−void tTwoPole_setCoefficients(tTwoPole* const ft, float b0, float a1, float a2)
487−{
488− _tTwoPole* f = *ft;
489− f->b0 = b0;
490− f->a1 = a1;
491− f->a2 = a2;
492−}
493−
494−void tTwoPole_setGain(tTwoPole* const ft, float gain)
495−{
496− _tTwoPole* f = *ft;
497− f->gain = gain;
498−}
499−
500−void tTwoPoleSampleRateChanged (tTwoPole* const ft)
501−{
502− _tTwoPole* f = *ft;
503−
504− f->a2 = f->radius * f->radius;
505− f->a1 = -2.0f * f->radius * cosf(f->frequency * leaf.twoPiTimesInvSampleRate);
506−
507− if ( f->normalize )
508− {
509− // Normalize the filter gain ... not terribly efficient.
510− float real = 1 - f->radius + (f->a2 - f->radius) * cosf(2 * f->frequency * leaf.twoPiTimesInvSampleRate);
511− float imag = (f->a2 - f->radius) * sinf(2 * f->frequency * leaf.twoPiTimesInvSampleRate);
512− f->b0 = sqrtf( powf(real, 2) + powf(imag, 2) );
513− }
514−}
515−
516−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PoleZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
517−void tPoleZero_init(tPoleZero* const pzf)
518−{
519− _tPoleZero* f = *pzf = (_tPoleZero*) leaf_alloc(sizeof(_tPoleZero));
566+ _tMempool* m = *mp;
567+ _tPoleZero* f = *pzf = (_tPoleZero*) mpool_alloc(sizeof(_tPoleZero), m->pool);
520568
521569 f->gain = 1.0f;
522570 f->b0 = 1.0;
@@ -526,11 +574,12 @@ void tPoleZero_init(tPoleZero* const pzf) · 3 unmodified lines
526574 f->lastOut = 0.0f;
527575 }
528576
529−void tPoleZero_free(tPoleZero* const pzf)
577+void tPoleZero_freeFromPool (tPoleZero* const pzf, tMempool* const mp)
530578 {
579+ _tMempool* m = *mp;
531580 _tPoleZero* f = *pzf;
532581
533− leaf_free(f);
582+ mpool_free(f, m->pool);
534583 }
535584
536585 void tPoleZero_setB0(tPoleZero* const pzf, float b0)
@@ -643,6 +692,30 @@ void tBiQuad_free(tBiQuad* const ft) · 106 unmodified lines
643692 leaf_free(f);
644693 }
645694
695+void tBiQuad_initToPool (tBiQuad* const ft, tMempool* const mp)
696+{
697+ _tMempool* m = *mp;
698+ _tBiQuad* f = *ft = (_tBiQuad*) mpool_alloc(sizeof(_tBiQuad), m->pool);
699+
700+ f->gain = 1.0f;
701+
702+ f->b0 = 0.0f;
703+ f->a0 = 0.0f;
704+
705+ f->lastIn[0] = 0.0f;
706+ f->lastIn[1] = 0.0f;
707+ f->lastOut[0] = 0.0f;
708+ f->lastOut[1] = 0.0f;
709+}
710+
711+void tBiQuad_freeFromPool (tBiQuad* const ft, tMempool* const mp)
712+{
713+ _tMempool* m = *mp;
714+ _tBiQuad* f = *ft;
715+
716+ mpool_free(f, m->pool);
717+}
718+
646719 float tBiQuad_tick(tBiQuad* const ft, float input)
647720 {
648721 _tBiQuad* f = *ft;
@@ -766,78 +839,54 @@ void tBiQuadSampleRateChanged(tBiQuad* const ft) · 117 unmodified lines
766839 }
767840 }
768841
769−/* Highpass */
770−void tHighpass_init(tHighpass* const ft, float freq)
842+// Less efficient, more accurate version of SVF, in which cutoff frequency is taken as floating point Hz value and tanf
843+// is calculated when frequency changes.
844+void tSVF_init(tSVF* const svff, SVFType type, float freq, float Q)
771845 {
772− _tHighpass* f = *ft = (_tHighpass*) leaf_alloc(sizeof(_tHighpass));
846+ _tSVF* svf = *svff = (_tSVF*) leaf_alloc(sizeof(_tSVF));
773847
774− f->R = (1.0f - (freq * leaf.twoPiTimesInvSampleRate));
775− f->ys = 0.0f;
776− f->xs = 0.0f;
848+ svf->type = type;
777849
778− f->frequency = freq;
779−}
780−
781−void tHighpass_free(tHighpass* const ft)
782−{
783− _tHighpass* f = *ft;
850+ svf->ic1eq = 0;
851+ svf->ic2eq = 0;
784852
785− leaf_free(f);
853+ svf->g = tanf(PI * freq * leaf.invSampleRate);
854+ svf->k = 1.0f/Q;
855+ svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
856+ svf->a2 = svf->g*svf->a1;
857+ svf->a3 = svf->g*svf->a2;
786858 }
787859
788−void tHighpass_setFreq(tHighpass* const ft, float freq)
860+void tSVF_free(tSVF* const svff)
789861 {
790− _tHighpass* f = *ft;
791− f->frequency = freq;
792− f->R = (1.0f - (freq * leaf.twoPiTimesInvSampleRate));
862+ _tSVF* svf = *svff;
793863
864+ leaf_free(svf);
794865 }
795866
796−float tHighpass_getFreq(tHighpass* const ft)
797−{
798− _tHighpass* f = *ft;
799− return f->frequency;
800−}
801−
802−// From JOS DC Blocker
803−float tHighpass_tick(tHighpass* const ft, float x)
804−{
805− _tHighpass* f = *ft;
806− f->ys = x - f->xs + f->R * f->ys;
807− f->xs = x;
808− return f->ys;
809−}
810−
811−void tHighpassSampleRateChanged(tHighpass* const ft)
812−{
813− _tHighpass* f = *ft;
814− f->R = (1.0f-((f->frequency * 2.0f * 3.14f) * leaf.invSampleRate));
815−}
816−
817−// Less efficient, more accurate version of SVF, in which cutoff frequency is taken as floating point Hz value and tanf
818−// is calculated when frequency changes.
819−void tSVF_init(tSVF* const svff, SVFType type, float freq, float Q)
867+void tSVF_initToPool (tSVF* const svff, SVFType type, float freq, float Q, tMempool* const mp)
820868 {
821− _tSVF* svf = *svff = (_tSVF*) leaf_alloc(sizeof(_tSVF));
869+ _tMempool* m = *mp;
870+ _tSVF* svf = *svff = (_tSVF*) mpool_alloc(sizeof(_tSVF), m->pool);
822871
823872 svf->type = type;
824873
825874 svf->ic1eq = 0;
826875 svf->ic2eq = 0;
827876
828− float a1,a2,a3,g,k;
829877 svf->g = tanf(PI * freq * leaf.invSampleRate);
830878 svf->k = 1.0f/Q;
831879 svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
832− svf->a2 = g*a1;
833− svf->a3 = g*a2;
880+ svf->a2 = svf->g*svf->a1;
881+ svf->a3 = svf->g*svf->a2;
834882 }
835883
836−void tSVF_free(tSVF* const svff)
884+void tSVF_freeFromPool (tSVF* const svff, tMempool* const mp)
837885 {
886+ _tMempool* m = *mp;
838887 _tSVF* svf = *svff;
839888
840− leaf_free(svf);
889+ mpool_free(svf, m->pool);
841890 }
842891
843892 float tSVF_tick(tSVF* const svff, float v0)
@@ -890,12 +939,11 @@ void tEfficientSVF_init(tEfficientSVF* const svff, SVFType type, uint16_t inpu · 46 unmodified lines
890939 svf->ic1eq = 0;
891940 svf->ic2eq = 0;
892941
893− float a1,a2,a3,g,k;
894942 svf->g = filtertan[input];
895943 svf->k = 1.0f/Q;
896− svf->a1 = 1.0f/(1.0f+g*(g+k));
897− svf->a2 = g*a1;
898− svf->a3 = g*a2;
944+ svf->a1 = 1.0f/(1.0f+svf->g*(svf->g+svf->k));
945+ svf->a2 = svf->g*svf->a1;
946+ svf->a3 = svf->g*svf->a2;
899947 }
900948
901949 void tEfficientSVF_free(tEfficientSVF* const svff)
@@ -905,6 +953,31 @@ void tEfficientSVF_free(tEfficientSVF* const svff) · 3 unmodified lines
905953 leaf_free(svf);
906954 }
907955
956+void tEfficientSVF_initToPool (tEfficientSVF* const svff, SVFType type, uint16_t input, float Q, tMempool* const mp)
957+{
958+ _tMempool* m = *mp;
959+ _tEfficientSVF* svf = *svff = (_tEfficientSVF*) mpool_alloc(sizeof(_tEfficientSVF), m->pool);
960+
961+ svf->type = type;
962+
963+ svf->ic1eq = 0;
964+ svf->ic2eq = 0;
965+
966+ svf->g = filtertan[input];
967+ svf->k = 1.0f/Q;
968+ svf->a1 = 1.0f/(1.0f+svf->g*(svf->g+svf->k));
969+ svf->a2 = svf->g*svf->a1;
970+ svf->a3 = svf->g*svf->a2;
971+}
972+
973+void tEfficientSVF_freeFromPool (tEfficientSVF* const svff, tMempool* const mp)
974+{
975+ _tMempool* m = *mp;
976+ _tEfficientSVF* svf = *svff;
977+
978+ mpool_free(svf, m->pool);
979+}
980+
908981 float tEfficientSVF_tick(tEfficientSVF* const svff, float v0)
909982 {
910983 _tEfficientSVF* svf = *svff;
@@ -945,6 +1018,181 @@ void tEfficientSVF_setQ(tEfficientSVF* const svff, float Q) · 34 unmodified lines
9451018 svf->a3 = svf->g * svf->a2;
9461019 }
9471020
1021+/* Highpass */
1022+void tHighpass_init(tHighpass* const ft, float freq)
1023+{
1024+ _tHighpass* f = *ft = (_tHighpass*) leaf_alloc(sizeof(_tHighpass));
1025+
1026+ f->R = (1.0f - (freq * leaf.twoPiTimesInvSampleRate));
1027+ f->ys = 0.0f;
1028+ f->xs = 0.0f;
1029+
1030+ f->frequency = freq;
1031+}
1032+
1033+void tHighpass_free(tHighpass* const ft)
1034+{
1035+ _tHighpass* f = *ft;
1036+
1037+ leaf_free(f);
1038+}
1039+
1040+void tHighpass_initToPool (tHighpass* const ft, float freq, tMempool* const mp)
1041+{
1042+ _tMempool* m = *mp;
1043+ _tHighpass* f = *ft = (_tHighpass*) mpool_alloc(sizeof(_tHighpass), m->pool);
1044+
1045+ f->R = (1.0f - (freq * leaf.twoPiTimesInvSampleRate));
1046+ f->ys = 0.0f;
1047+ f->xs = 0.0f;
1048+
1049+ f->frequency = freq;
1050+}
1051+
1052+void tHighpass_freeFromPool (tHighpass* const ft, tMempool* const mp)
1053+{
1054+ _tMempool* m = *mp;
1055+ _tHighpass* f = *ft;
1056+
1057+ mpool_free(f, m->pool);
1058+}
1059+
1060+void tHighpass_setFreq(tHighpass* const ft, float freq)
1061+{
1062+ _tHighpass* f = *ft;
1063+ f->frequency = freq;
1064+ f->R = (1.0f - (freq * leaf.twoPiTimesInvSampleRate));
1065+
1066+}
1067+
1068+float tHighpass_getFreq(tHighpass* const ft)
1069+{
1070+ _tHighpass* f = *ft;
1071+ return f->frequency;
1072+}
1073+
1074+// From JOS DC Blocker
1075+float tHighpass_tick(tHighpass* const ft, float x)
1076+{
1077+ _tHighpass* f = *ft;
1078+ f->ys = x - f->xs + f->R * f->ys;
1079+ f->xs = x;
1080+ return f->ys;
1081+}
1082+
1083+void tHighpassSampleRateChanged(tHighpass* const ft)
1084+{
1085+ _tHighpass* f = *ft;
1086+ f->R = (1.0f-((f->frequency * 2.0f * 3.14f) * leaf.invSampleRate));
1087+}
1088+
1089+void tButterworth_init(tButterworth* const ft, int N, float f1, float f2)
1090+{
1091+ _tButterworth* f = *ft = (_tButterworth*) leaf_alloc(sizeof(_tButterworth));
1092+
1093+ f->f1 = f1;
1094+ f->f2 = f2;
1095+ f->gain = 1.0f;
1096+
1097+ f->N = N;
1098+
1099+ if (f->N > NUM_SVF_BW) f->N = NUM_SVF_BW;
1100+
1101+ for(int i = 0; i < N/2; ++i)
1102+ {
1103+ tSVF_init(&f->low[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)));
1104+ tSVF_init(&f->high[i], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)));
1105+ }
1106+}
1107+
1108+void tButterworth_free(tButterworth* const ft)
1109+{
1110+ _tButterworth* f = *ft;
1111+
1112+ for(int i = 0; i < f->N/2; ++i)
1113+ {
1114+ tSVF_free(&f->low[i]);
1115+ tSVF_free(&f->high[i]);
1116+ }
1117+
1118+ leaf_free(f);
1119+}
1120+
1121+void tButterworth_initToPool (tButterworth* const ft, int N, float f1, float f2, tMempool* const mp)
1122+{
1123+ _tMempool* m = *mp;
1124+ _tButterworth* f = *ft = (_tButterworth*) mpool_alloc(sizeof(_tButterworth), m->pool);
1125+
1126+ f->f1 = f1;
1127+ f->f2 = f2;
1128+ f->gain = 1.0f;
1129+
1130+ f->N = N;
1131+
1132+ if (f->N > NUM_SVF_BW) f->N = NUM_SVF_BW;
1133+
1134+ for(int i = 0; i < N/2; ++i)
1135+ {
1136+ tSVF_initToPool(&f->low[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)), mp);
1137+ tSVF_initToPool(&f->high[i], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)), mp);
1138+ }
1139+}
1140+
1141+void tButterworth_freeFromPool (tButterworth* const ft, tMempool* const mp)
1142+{
1143+ _tMempool* m = *mp;
1144+ _tButterworth* f = *ft;
1145+
1146+ for(int i = 0; i < f->N/2; ++i)
1147+ {
1148+ tSVF_freeFromPool(&f->low[i], mp);
1149+ tSVF_freeFromPool(&f->high[i], mp);
1150+ }
1151+
1152+ mpool_free(f, m->pool);
1153+}
1154+
1155+float tButterworth_tick(tButterworth* const ft, float samp)
1156+{
1157+ _tButterworth* f = *ft;
1158+
1159+ for(int i = 0; i < ((f->N)/2); ++i)
1160+ {
1161+ samp = tSVF_tick(&f->low[i],samp);
1162+ samp = tSVF_tick(&f->high[i],samp);
1163+ }
1164+ return samp;
1165+}
1166+
1167+void tButterworth_setF1(tButterworth* const ft, float f1)
1168+{
1169+ _tButterworth* f = *ft;
1170+
1171+ f->f1 = f1;
1172+ for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->low[i], f1);
1173+}
1174+
1175+void tButterworth_setF2(tButterworth* const ft, float f2)
1176+{
1177+ _tButterworth* f = *ft;
1178+
1179+ f->f2 = f2;
1180+ for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->high[i], f2);
1181+}
1182+
1183+void tButterworth_setFreqs(tButterworth* const ft, float f1, float f2)
1184+{
1185+ _tButterworth* f = *ft;
1186+
1187+ f->f1 = f1;
1188+ f->f2 = f2;
1189+ for(int i = 0; i < ((f->N)/2); ++i)
1190+ {
1191+ tSVF_setFreq(&f->low[i], f1);
1192+ tSVF_setFreq(&f->high[i], f2);
1193+ }
1194+}
1195+
9481196 void tFIR_init(tFIR* const firf, float* coeffs, int numTaps)
9491197 {
9501198 _tFIR* fir = *firf = (_tFIR*) leaf_alloc(sizeof(_tFIR));
@@ -955,6 +1203,34 @@ void tFIR_init(tFIR* const firf, float* coeffs, int numTaps) · 4 unmodified lines
9551203 for (int i = 0; i < fir->numTaps; ++i) fir->past[i] = 0.0f;
9561204 }
9571205
1206+void tFIR_free(tFIR* const firf)
1207+{
1208+ _tFIR* fir = *firf;
1209+
1210+ leaf_free(fir->past);
1211+ leaf_free(fir);
1212+}
1213+
1214+void tFIR_initToPool (tFIR* const firf, float* coeffs, int numTaps, tMempool* const mp)
1215+{
1216+ _tMempool* m = *mp;
1217+ _tFIR* fir = *firf = (_tFIR*) mpool_alloc(sizeof(_tFIR), m->pool);
1218+
1219+ fir->numTaps = numTaps;
1220+ fir->coeff = coeffs;
1221+ fir->past = (float*) mpool_alloc(sizeof(float) * fir->numTaps, m->pool);
1222+ for (int i = 0; i < fir->numTaps; ++i) fir->past[i] = 0.0f;
1223+}
1224+
1225+void tFIR_freeFromPool (tFIR* const firf, tMempool* const mp)
1226+{
1227+ _tMempool* m = *mp;
1228+ _tFIR* fir = *firf;
1229+
1230+ mpool_free(fir->past, m->pool);
1231+ mpool_free(fir, m->pool);
1232+}
1233+
9581234 float tFIR_tick(tFIR* const firf, float input)
9591235 {
9601236 _tFIR* fir = *firf;
@@ -965,11 +1241,3 @@ float tFIR_tick(tFIR* const firf, float input) · 4 unmodified lines
9651241 for (int i = fir->numTaps-1; i > 0; --i) fir->past[i] = fir->past[i-1];
9661242 return y;
9671243 }
968−
969−void tFIR_free(tFIR* const firf)
970−{
971− _tFIR* fir = *firf;
972−
973− leaf_free(fir->past);
974− leaf_free(fir);
975−}
LEAF/Src/leaf-instruments.c+191−2
@@ -63,6 +63,53 @@ void t808Cowebell_free(t808Cowbell* const cowbellInst) · 62 unmodified lines
6363 leaf_free(cowbell);
6464 }
6565
66+void t808Cowbell_initToPool (t808Cowbell* const cowbellInst, int useStick, tMempool* const mp)
67+{
68+ _tMempool* m = *mp;
69+ _t808Cowbell* cowbell = *cowbellInst = (_t808Cowbell*) mpool_alloc(sizeof(_t808Cowbell), m->pool);
70+
71+ tSquare_initToPool(&cowbell->p[0], mp);
72+ tSquare_setFreq(&cowbell->p[0], 540.0f);
73+
74+ tSquare_initToPool(&cowbell->p[1], mp);
75+ tSquare_setFreq(&cowbell->p[1], 1.48148f * 540.0f);
76+
77+ cowbell->oscMix = 0.5f;
78+
79+ tSVF_initToPool(&cowbell->bandpassOsc, SVFTypeBandpass, 2500, 1.0f, mp);
80+
81+ tSVF_initToPool(&cowbell->bandpassStick, SVFTypeBandpass, 1800, 1.0f, mp);
82+
83+ tEnvelope_initToPool(&cowbell->envGain, 5.0f, 100.0f, OFALSE, mp);
84+
85+ tEnvelope_initToPool(&cowbell->envFilter, 5.0, 100.0f, OFALSE, mp);
86+
87+ tHighpass_initToPool(&cowbell->highpass, 1000.0f, mp);
88+
89+ tNoise_initToPool(&cowbell->stick, WhiteNoise, mp);
90+
91+ tEnvelope_initToPool(&cowbell->envStick, 5.0f, 5.0f, 0, mp);
92+
93+ cowbell->useStick = useStick;
94+}
95+
96+void t808Cowbell_freeFromPool (t808Cowbell* const cowbellInst, tMempool* const mp)
97+{
98+ _tMempool* m = *mp;
99+ _t808Cowbell* cowbell = *cowbellInst;
100+
101+ tSquare_freeFromPool(&cowbell->p[0], mp);
102+ tSquare_freeFromPool(&cowbell->p[1], mp);
103+ tSVF_freeFromPool(&cowbell->bandpassOsc, mp);
104+ tSVF_freeFromPool(&cowbell->bandpassStick, mp);
105+ tEnvelope_freeFromPool(&cowbell->envGain, mp);
106+ tEnvelope_freeFromPool(&cowbell->envFilter, mp);
107+ tHighpass_freeFromPool(&cowbell->highpass, mp);
108+ tNoise_freeFromPool(&cowbell->stick, mp);
109+ tEnvelope_freeFromPool(&cowbell->envStick, mp);
110+ mpool_free(cowbell, m->pool);
111+}
112+
66113 void t808Cowbell_on(t808Cowbell* const cowbellInst, float vel)
67114 {
68115 _t808Cowbell* cowbell = *cowbellInst;
@@ -192,6 +239,64 @@ void t808Hihat_free(t808Hihat* const hihatInst) · 123 unmodified lines
192239 leaf_free(hihat);
193240 }
194241
242+void t808Hihat_initToPool (t808Hihat* const hihatInst, tMempool* const mp)
243+{
244+ _tMempool* m = *mp;
245+ _t808Hihat* hihat = *hihatInst = (_t808Hihat*) mpool_alloc(sizeof(_t808Hihat), m->pool);
246+
247+ for (int i = 0; i < 6; i++)
248+ {
249+ tSquare_initToPool(&hihat->p[i], mp);
250+ }
251+
252+ tNoise_initToPool(&hihat->stick, PinkNoise, mp);
253+ tNoise_initToPool(&hihat->n, WhiteNoise, mp);
254+
255+ // need to fix SVF to be generic
256+ tSVF_initToPool(&hihat->bandpassStick, SVFTypeBandpass,2500.0f,1.2f, mp);
257+ tSVF_initToPool(&hihat->bandpassOsc, SVFTypeBandpass,3500.0f,0.3f, mp);
258+
259+ tEnvelope_initToPool(&hihat->envGain, 0.0f, 50.0f, OFALSE, mp);
260+ tEnvelope_initToPool(&hihat->envStick, 0.0f, 7.0f, OFALSE, mp);
261+
262+
263+ tHighpass_initToPool(&hihat->highpass, 7000.0f, mp);
264+
265+ hihat->freq = 40.0f;
266+ hihat->stretch = 0.0f;
267+
268+ tSquare_setFreq(&hihat->p[0], 2.0f * hihat->freq);
269+ tSquare_setFreq(&hihat->p[1], 3.00f * hihat->freq);
270+ tSquare_setFreq(&hihat->p[2], 4.16f * hihat->freq);
271+ tSquare_setFreq(&hihat->p[3], 5.43f * hihat->freq);
272+ tSquare_setFreq(&hihat->p[4], 6.79f * hihat->freq);
273+ tSquare_setFreq(&hihat->p[5], 8.21f * hihat->freq);
274+}
275+
276+void t808Hihat_freeFromPool (t808Hihat* const hihatInst, tMempool* const mp)
277+{
278+ _tMempool* m = *mp;
279+ _t808Hihat* hihat = *hihatInst;
280+
281+ for (int i = 0; i < 6; i++)
282+ {
283+ tSquare_freeFromPool(&hihat->p[i], mp);
284+ }
285+
286+ tNoise_freeFromPool(&hihat->stick, mp);
287+ tNoise_freeFromPool(&hihat->n, mp);
288+
289+ // need to fix SVF to be generic
290+ tSVF_freeFromPool(&hihat->bandpassStick, mp);
291+ tSVF_freeFromPool(&hihat->bandpassOsc, mp);
292+ tEnvelope_freeFromPool(&hihat->envGain, mp);
293+ tEnvelope_freeFromPool(&hihat->envStick, mp);
294+
295+ tHighpass_freeFromPool(&hihat->highpass, mp);
296+
297+ mpool_free(hihat, m->pool);
298+}
299+
195300 void t808Hihat_on(t808Hihat* const hihatInst, float vel)
196301 {
197302 _t808Hihat* hihat = *hihatInst;
@@ -289,8 +394,6 @@ void t808Hihat_setStickBandPassQ(t808Hihat* const hihatInst, float Q) · 91 unmodified lines
289394 tSVF_setQ(&hihat->bandpassStick,Q);
290395 }
291396
292−
293−
294397 void t808Hihat_setOscFreq(t808Hihat* const hihatInst, float freq)
295398 {
296399 _t808Hihat* hihat = *hihatInst;
@@ -348,6 +451,57 @@ void t808Snare_free (t808Snare* const snareInst) · 51 unmodified lines
348451 leaf_free(snare);
349452 }
350453
454+void t808Snare_initToPool (t808Snare* const snareInst, tMempool* const mp)
455+{
456+ _tMempool* m = *mp;
457+ _t808Snare* snare = *snareInst = (_t808Snare*) mpool_alloc(sizeof(_t808Snare), m->pool);
458+
459+ float ratio[2] = {1.0, 1.5};
460+ for (int i = 0; i < 2; i++)
461+ {
462+ tTriangle_initToPool(&snare->tone[i], mp);
463+
464+ tTriangle_setFreq(&snare->tone[i], ratio[i] * 400.0f);
465+ tSVF_initToPool(&snare->toneLowpass[i], SVFTypeLowpass, 4000, 1.0f, mp);
466+ tEnvelope_initToPool(&snare->toneEnvOsc[i], 0.0f, 50.0f, OFALSE, mp);
467+ tEnvelope_initToPool(&snare->toneEnvGain[i], 1.0f, 150.0f, OFALSE, mp);
468+ tEnvelope_initToPool(&snare->toneEnvFilter[i], 1.0f, 2000.0f, OFALSE, mp);
469+
470+ snare->toneGain[i] = 0.5f;
471+ }
472+
473+ snare->tone1Freq = ratio[0] * 100.0f;
474+ snare->tone2Freq = ratio[1] * 100.0f;
475+ snare->noiseFilterFreq = 3000.0f;
476+ tNoise_initToPool(&snare->noiseOsc, WhiteNoise, mp);
477+ tSVF_initToPool(&snare->noiseLowpass, SVFTypeLowpass, 12000.0f, 0.8f, mp);
478+ tEnvelope_initToPool(&snare->noiseEnvGain, 0.0f, 100.0f, OFALSE, mp);
479+ tEnvelope_initToPool(&snare->noiseEnvFilter, 0.0f, 1000.0f, OFALSE, mp);
480+ snare->noiseGain = 1.0f;
481+}
482+
483+void t808Snare_freeFromPool (t808Snare* const snareInst, tMempool* const mp)
484+{
485+ _tMempool* m = *mp;
486+ _t808Snare* snare = *snareInst;
487+
488+ for (int i = 0; i < 2; i++)
489+ {
490+ tTriangle_freeFromPool(&snare->tone[i], mp);
491+ tSVF_freeFromPool(&snare->toneLowpass[i], mp);
492+ tEnvelope_freeFromPool(&snare->toneEnvOsc[i], mp);
493+ tEnvelope_freeFromPool(&snare->toneEnvGain[i], mp);
494+ tEnvelope_freeFromPool(&snare->toneEnvFilter[i], mp);
495+ }
496+
497+ tNoise_freeFromPool(&snare->noiseOsc, mp);
498+ tSVF_freeFromPool(&snare->noiseLowpass, mp);
499+ tEnvelope_freeFromPool(&snare->noiseEnvGain, mp);
500+ tEnvelope_freeFromPool(&snare->noiseEnvFilter, mp);
501+
502+ mpool_free(snare, m->pool);
503+}
504+
351505 void t808Snare_on(t808Snare* const snareInst, float vel)
352506 {
353507 _t808Snare* snare = *snareInst;
@@ -472,6 +626,41 @@ void t808Kick_free (t808Kick* const kickInst) · 118 unmodified lines
472626 leaf_free(kick);
473627 }
474628
629+void t808Kick_initToPool (t808Kick* const kickInst, tMempool* const mp)
630+{
631+ _tMempool* m = *mp;
632+ _t808Kick* kick = *kickInst = (_t808Kick*) mpool_alloc(sizeof(_t808Kick), m->pool);
633+
634+ tCycle_initToPool(&kick->tone, mp);
635+ kick->toneInitialFreq = 40.0f;
636+ kick->sighAmountInHz = 7.0f;
637+ kick->chirpRatioMinusOne = 3.3f;
638+ tCycle_setFreq(&kick->tone, 50.0f);
639+ tSVF_initToPool(&kick->toneLowpass, SVFTypeLowpass, 2000.0f, 0.5f, mp);
640+ tEnvelope_initToPool(&kick->toneEnvOscChirp, 0.0f, 20.0f, OFALSE, mp);
641+ tEnvelope_initToPool(&kick->toneEnvOscSigh, 0.0f, 2500.0f, OFALSE, mp);
642+ tEnvelope_initToPool(&kick->toneEnvGain, 0.0f, 800.0f, OFALSE, mp);
643+ tNoise_initToPool(&kick->noiseOsc, PinkNoise, mp);
644+ tEnvelope_initToPool(&kick->noiseEnvGain, 0.0f, 1.0f, OFALSE, mp);
645+ kick->noiseGain = 0.3f;
646+}
647+
648+void t808Kick_freeFromPool (t808Kick* const kickInst, tMempool* const mp)
649+{
650+ _tMempool* m = *mp;
651+ _t808Kick* kick = *kickInst;
652+
653+ tCycle_freeFromPool(&kick->tone, mp);
654+ tSVF_freeFromPool(&kick->toneLowpass, mp);
655+ tEnvelope_freeFromPool(&kick->toneEnvOscChirp, mp);
656+ tEnvelope_freeFromPool(&kick->toneEnvOscSigh, mp);
657+ tEnvelope_freeFromPool(&kick->toneEnvGain, mp);
658+ tNoise_freeFromPool(&kick->noiseOsc, mp);
659+ tEnvelope_freeFromPool(&kick->noiseEnvGain, mp);
660+
661+ mpool_free(kick, m->pool);
662+}
663+
475664 float t808Kick_tick (t808Kick* const kickInst)
476665 {
477666 _t808Kick* kick = *kickInst;
LEAF/Src/leaf-mempool.c+104−4
@@ -77,8 +77,6 @@ void mpool_create (char* memory, size_t size, mpool_t* pool) · 76 unmodified lines
7777 }
7878 }
7979
80−
81−
8280 void leaf_pool_init(char* memory, size_t size)
8381 {
8482 mpool_create(memory, size, &leaf_pool);
@@ -143,6 +141,68 @@ void* mpool_alloc(size_t asize, mpool_t* pool) · 58 unmodified lines
143141 return node_to_alloc->pool;
144142 }
145143
144+
145+/**
146+ * allocate memory from memory pool and also clear that memory to be blank
147+ */
148+void* mpool_allocAndClear(size_t asize, mpool_t* pool)
149+{
150+ // If the head is NULL, the mempool is full
151+ if (pool->head == NULL) return NULL;
152+
153+ // Should we alloc the first block large enough or check all blocks and pick the one closest in size?
154+ size_t size_to_alloc = mpool_align(asize);
155+ mpool_node_t* node_to_alloc = pool->head;
156+
157+ // Traverse the free list for a large enough block
158+ while (node_to_alloc->size < size_to_alloc)
159+ {
160+ node_to_alloc = node_to_alloc->next;
161+
162+ // If we reach the end of the free list, there
163+ // are no blocks large enough, return NULL
164+ if (node_to_alloc == NULL) return NULL;
165+ }
166+
167+ // Create a new node after the node to be allocated if there is enough space
168+ mpool_node_t* new_node;
169+ size_t leftover = node_to_alloc->size - size_to_alloc;
170+ node_to_alloc->size = size_to_alloc;
171+ if (leftover > header_size)
172+ {
173+ long offset = (char*) node_to_alloc - (char*) pool->mpool;
174+ offset += header_size + node_to_alloc->size;
175+ new_node = create_node(&pool->mpool[offset],
176+ node_to_alloc->next,
177+ node_to_alloc->prev,
178+ leftover - header_size);
179+ }
180+ else
181+ {
182+ // Add any leftover space to the allocated node to avoid fragmentation
183+ node_to_alloc->size += leftover;
184+
185+ new_node = node_to_alloc->next;
186+ }
187+
188+ // Update the head if we are allocating the first node of the free list
189+ // The head will be NULL if there is no space left
190+ if (pool->head == node_to_alloc)
191+ {
192+ pool->head = new_node;
193+ }
194+
195+ // Remove the allocated node from the free list
196+ delink_node(node_to_alloc);
197+
198+ pool->usize += header_size + node_to_alloc->size;
199+ // Format the new pool
200+ char* new_pool = (char*)node_to_alloc->pool;
201+ for (int i = 0; i < node_to_alloc->size; i++) new_pool[i] = 0;
202+ // Return the pool of the allocated node;
203+ return node_to_alloc->pool;
204+}
205+
146206 void* leaf_alloc(size_t size)
147207 {
148208 //printf("alloc %i\n", size);
@@ -153,6 +213,17 @@ void* leaf_alloc(size_t size) · 4 unmodified lines
153213 return block;
154214 }
155215
216+void* leaf_allocAndClear(size_t size)
217+{
218+ //printf("alloc %i\n", size);
219+ void* block = mpool_allocAndClear(size, &leaf_pool);
220+
221+ if (block == NULL) leaf_mempool_overrun();
222+
223+
224+ return block;
225+}
226+
156227 void mpool_free(void* ptr, mpool_t* pool)
157228 {
158229 //if (ptr < pool->mpool || ptr >= pool->mpool + pool->msize)
@@ -211,8 +282,8 @@ void mpool_free(void* ptr, mpool_t* pool) · 52 unmodified lines
211282 pool->head = freed_node;
212283
213284 // Format the freed pool
214− char* freed_pool = (char*)freed_node->pool;
215− for (int i = 0; i < freed_node->size; i++) freed_pool[i] = 0;
285+// char* freed_pool = (char*)freed_node->pool;
286+// for (int i = 0; i < freed_node->size; i++) freed_pool[i] = 0;
216287 }
217288
218289 void leaf_free(void* ptr)
@@ -289,3 +360,32 @@ void leaf_mempool_overrun(void) · 70 unmodified lines
289360 //TODO: we should set up some kind of leaf_error method that reaches user space to notify library users of things that failed.
290361 }
291362
363+void tMempool_init(tMempool* const mp, char* memory, size_t size)
364+{
365+ _tMempool* m = *mp = (_tMempool*) leaf_alloc(sizeof(_tMempool));
366+
367+ mpool_create (memory, size, m->pool);
368+}
369+
370+void tMempool_free(tMempool* const mp)
371+{
372+ _tMempool* m = *mp;
373+
374+ leaf_free(m);
375+}
376+
377+void tMempool_initToPool (tMempool* const mp, char* memory, size_t size, tMempool* const mem)
378+{
379+ _tMempool* mm = *mem;
380+ _tMempool* m = *mp = (_tMempool*) mpool_alloc(sizeof(_tMempool), mm->pool);
381+
382+ mpool_create (memory, size, m->pool);
383+}
384+
385+void tMempool_freeFromPool (tMempool* const mp, tMempool* const mem)
386+{
387+ _tMempool* mm = *mem;
388+ _tMempool* m = *mp;
389+
390+ mpool_free(m, mm->pool);
391+}
LEAF/Src/leaf-midi.c+342−254
@@ -16,10 +16,330 @@ · 15 unmodified lines
1616
1717 #endif
1818
19+//====================================================================================
20+/* Stack */
21+//====================================================================================
22+
23+void tStack_init(tStack* const stack)
24+{
25+ _tStack* ns = *stack = (_tStack*) leaf_alloc(sizeof(_tStack));
26+
27+ ns->ordered = OFALSE;
28+ ns->size = 0;
29+ ns->pos = 0;
30+ ns->capacity = STACK_SIZE;
31+
32+ for (int i = 0; i < STACK_SIZE; i++) ns->data[i] = -1;
33+}
34+
35+void tStack_free(tStack* const stack)
36+{
37+ _tStack* ns = *stack;
38+
39+ leaf_free(ns);
40+}
41+
42+void tStack_initToPool (tStack* const stack, tMempool* const mp)
43+{
44+ _tMempool* m = *mp;
45+ _tStack* ns = *stack = (_tStack*) mpool_alloc(sizeof(_tStack), m->pool);
46+
47+ ns->ordered = OFALSE;
48+ ns->size = 0;
49+ ns->pos = 0;
50+ ns->capacity = STACK_SIZE;
51+
52+ for (int i = 0; i < STACK_SIZE; i++) ns->data[i] = -1;
53+}
54+
55+void tStack_freeFromPool (tStack* const stack, tMempool* const mp)
56+{
57+ _tMempool* m = *mp;
58+ _tStack* ns = *stack;
59+
60+ mpool_free(ns, m->pool);
61+}
62+
63+// If stack contains note, returns index. Else returns -1;
64+int tStack_contains(tStack* const stack, uint16_t noteVal)
65+{
66+ _tStack* ns = *stack;
67+ for (int i = 0; i < ns->size; i++)
68+ {
69+ if (ns->data[i] == noteVal) return i;
70+ }
71+ return -1;
72+}
73+
74+void tStack_add(tStack* const stack, uint16_t noteVal)
75+{
76+ _tStack* ns = *stack;
77+
78+ uint8_t j;
79+
80+ int whereToInsert = 0;
81+ if (ns->ordered)
82+ {
83+ for (j = 0; j < ns->size; j++)
84+ {
85+ if (noteVal > ns->data[j])
86+ {
87+ if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1))
88+ {
89+ whereToInsert = j+1;
90+ break;
91+ }
92+ }
93+ }
94+ }
95+
96+ //first move notes that are already in the stack one position to the right
97+ for (j = ns->size; j > whereToInsert; j--)
98+ {
99+ ns->data[j] = ns->data[(j - 1)];
100+ }
101+
102+ //then, insert the new note into the front of the stack
103+ ns->data[whereToInsert] = noteVal;
104+
105+ ns->size++;
106+}
107+
108+int tStack_addIfNotAlreadyThere(tStack* const stack, uint16_t noteVal)
109+{
110+ _tStack* ns = *stack;
111+
112+ uint8_t j;
113+
114+ int added = 0;
115+
116+ if (tStack_contains(stack, noteVal) == -1)
117+ {
118+ int whereToInsert = 0;
119+ if (ns->ordered)
120+ {
121+ for (j = 0; j < ns->size; j++)
122+ {
123+ if (noteVal > ns->data[j])
124+ {
125+ if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1))
126+ {
127+ whereToInsert = j+1;
128+ break;
129+ }
130+ }
131+ }
132+ }
133+
134+ //first move notes that are already in the stack one position to the right
135+ for (j = ns->size; j > whereToInsert; j--)
136+ {
137+ ns->data[j] = ns->data[(j - 1)];
138+ }
139+
140+ //then, insert the new note into the front of the stack
141+ ns->data[whereToInsert] = noteVal;
142+
143+ ns->size++;
144+
145+ added = 1;
146+ }
147+
148+ return added;
149+}
150+
151+// Remove noteVal. return 1 if removed, 0 if not
152+int tStack_remove(tStack* const stack, uint16_t noteVal)
153+{
154+ _tStack* ns = *stack;
155+
156+ uint8_t k;
157+ int foundIndex = tStack_contains(stack, noteVal);
158+ int removed = 0;
159+
160+ if (foundIndex >= 0)
161+ {
162+ for (k = 0; k < (ns->size - foundIndex); k++)
163+ {
164+ if ((k+foundIndex) >= (ns->capacity - 1))
165+ {
166+ ns->data[k + foundIndex] = -1;
167+ }
168+ else
169+ {
170+ ns->data[k + foundIndex] = ns->data[k + foundIndex + 1];
171+ if ((k + foundIndex) == (ns->size - 1))
172+ {
173+ ns->data[k + foundIndex + 1] = -1;
174+ }
175+ }
176+
177+ }
178+ // in case it got put on the stack multiple times
179+ foundIndex--;
180+ ns->size--;
181+ removed = 1;
182+ }
183+
184+ return removed;
185+}
186+
187+// Doesn't change size of data types
188+void tStack_setCapacity(tStack* const stack, uint16_t cap)
189+{
190+ _tStack* ns = *stack;
191+
192+ if (cap <= 0)
193+ ns->capacity = 1;
194+ else if (cap <= STACK_SIZE)
195+ ns->capacity = cap;
196+ else
197+ ns->capacity = STACK_SIZE;
198+
199+ for (int i = cap; i < STACK_SIZE; i++)
200+ {
201+ if ((int)ns->data[i] != -1)
202+ {
203+ ns->data[i] = -1;
204+ ns->size -= 1;
205+ }
206+ }
207+
208+ if (ns->pos >= cap)
209+ {
210+ ns->pos = 0;
211+ }
212+}
213+
214+int tStack_getSize(tStack* const stack)
215+{
216+ _tStack* ns = *stack;
217+
218+ return ns->size;
219+}
220+
221+void tStack_clear(tStack* const stack)
222+{
223+ _tStack* ns = *stack;
224+
225+ for (int i = 0; i < STACK_SIZE; i++)
226+ {
227+ ns->data[i] = -1;
228+ }
229+ ns->pos = 0;
230+ ns->size = 0;
231+}
232+
233+// Next item in order of addition to stack. Return 0-31 if there is a next item to move to. Returns -1 otherwise.
234+int tStack_next(tStack* const stack)
235+{
236+ _tStack* ns = *stack;
237+
238+ int step = 0;
239+ if (ns->size != 0) // if there is at least one note in the stack
240+ {
241+ if (ns->pos > 0) // if you're not at the most recent note (first one), then go backward in the array (moving from earliest to latest)
242+ {
243+ ns->pos--;
244+ }
245+ else
246+ {
247+ ns->pos = (ns->size - 1); // if you are the most recent note, go back to the earliest note in the array
248+ }
249+
250+ step = ns->data[ns->pos];
251+ return step;
252+ }
253+ else
254+ {
255+ return -1;
256+ }
257+}
258+
259+int tStack_get(tStack* const stack, int which)
260+{
261+ _tStack* ns = *stack;
262+ return ns->data[which];
263+}
264+
265+int tStack_first(tStack* const stack)
266+{
267+ _tStack* ns = *stack;
268+ return ns->data[0];
269+}
270+
271+
19272 // POLY
20273 void tPoly_init(tPoly* const polyh, int maxNumVoices)
21274 {
22− _tPoly* poly = *polyh = (_tPoly*) leaf_alloc(sizeof(_tPoly));
275+ _tPoly* poly = *polyh = (_tPoly*) leaf_alloc(sizeof(_tPoly));
276+
277+ poly->numVoices = maxNumVoices;
278+ poly->maxNumVoices = maxNumVoices;
279+ poly->lastVoiceToChange = 0;
280+
281+ // Arp mode stuff
282+ poly->currentVoice = 0;
283+ poly->maxLength = 128;
284+ poly->currentNote = -1;
285+
286+ //default learned CCs and notes are just the CCs 1-128 - notes are skipped
287+ for (int i = 0; i < 128; i++)
288+ {
289+ poly->notes[i][0] = 0;
290+ poly->notes[i][1] = -1;
291+ }
292+
293+ poly->glideTime = 5.0f;
294+
295+ poly->ramps = (tRamp*) leaf_alloc(sizeof(tRamp) * poly->maxNumVoices);
296+ poly->rampVals = (float*) leaf_alloc(sizeof(float) * poly->maxNumVoices);
297+ poly->firstReceived = (oBool*) leaf_alloc(sizeof(oBool) * poly->maxNumVoices);
298+ poly->voices = (int**) leaf_alloc(sizeof(int*) * poly->maxNumVoices);
299+
300+ for (int i = 0; i < poly->maxNumVoices; ++i)
301+ {
302+ poly->voices[i] = (int*) leaf_alloc(sizeof(int) * 2);
303+ poly->voices[i][0] = -1;
304+ poly->firstReceived[i] = OFALSE;
305+
306+ tRamp_init(&poly->ramps[i], poly->glideTime, 1);
307+ }
308+
309+ poly->pitchBend = 0.0f;
310+
311+ tRamp_init(&poly->pitchBendRamp, 1.0f, 1);
312+ tStack_init(&poly->stack);
313+ tStack_init(&poly->orderStack);
314+
315+ poly->pitchGlideIsActive = OFALSE;
316+}
317+
318+void tPoly_free(tPoly* const polyh)
319+{
320+ _tPoly* poly = *polyh;
321+
322+ for (int i = 0; i < poly->maxNumVoices; i++)
323+ {
324+ tRamp_free(&poly->ramps[i]);
325+ leaf_free(poly->voices[i]);
326+ }
327+ tRamp_free(&poly->pitchBendRamp);
328+ tStack_free(&poly->stack);
329+ tStack_free(&poly->orderStack);
330+
331+ leaf_free(poly->voices);
332+ leaf_free(poly->ramps);
333+ leaf_free(poly->rampVals);
334+ leaf_free(poly->firstReceived);
335+
336+ leaf_free(poly);
337+}
338+
339+void tPoly_initToPool (tPoly* const polyh, int maxNumVoices, tMempool* const mp)
340+{
341+ _tMempool* m = *mp;
342+ _tPoly* poly = *polyh = (_tPoly*) mpool_alloc(sizeof(_tPoly), m->pool);
23343
24344 poly->numVoices = maxNumVoices;
25345 poly->maxNumVoices = maxNumVoices;
@@ -39,48 +359,49 @@ void tPoly_init(tPoly* const polyh, int maxNumVoices) · 13 unmodified lines
39359
40360 poly->glideTime = 5.0f;
41361
42− poly->ramps = (tRamp*) leaf_alloc(sizeof(tRamp) * poly->maxNumVoices);
43− poly->rampVals = (float*) leaf_alloc(sizeof(float) * poly->maxNumVoices);
44− poly->firstReceived = (oBool*) leaf_alloc(sizeof(oBool) * poly->maxNumVoices);
45− poly->voices = (int**) leaf_alloc(sizeof(int*) * poly->maxNumVoices);
362+ poly->ramps = (tRamp*) mpool_alloc(sizeof(tRamp) * poly->maxNumVoices, m->pool);
363+ poly->rampVals = (float*) mpool_alloc(sizeof(float) * poly->maxNumVoices, m->pool);
364+ poly->firstReceived = (oBool*) mpool_alloc(sizeof(oBool) * poly->maxNumVoices, m->pool);
365+ poly->voices = (int**) mpool_alloc(sizeof(int*) * poly->maxNumVoices, m->pool);
46366
47367 for (int i = 0; i < poly->maxNumVoices; ++i)
48368 {
49− poly->voices[i] = (int*) leaf_alloc(sizeof(int) * 2);
369+ poly->voices[i] = (int*) mpool_alloc(sizeof(int) * 2, m->pool);
50370 poly->voices[i][0] = -1;
51371 poly->firstReceived[i] = OFALSE;
52372
53− tRamp_init(&poly->ramps[i], poly->glideTime, 1);
373+ tRamp_initToPool(&poly->ramps[i], poly->glideTime, 1, mp);
54374 }
55375
56376 poly->pitchBend = 0.0f;
57377
58− tRamp_init(&poly->pitchBendRamp, 1.0f, 1);
59− tStack_init(&poly->stack);
60− tStack_init(&poly->orderStack);
378+ tRamp_initToPool(&poly->pitchBendRamp, 1.0f, 1, mp);
379+ tStack_initToPool(&poly->stack, mp);
380+ tStack_initToPool(&poly->orderStack, mp);
61381
62382 poly->pitchGlideIsActive = OFALSE;
63383 }
64384
65−void tPoly_free(tPoly* const polyh)
385+void tPoly_freeFromPool (tPoly* const polyh, tMempool* const mp)
66386 {
387+ _tMempool* m = *mp;
67388 _tPoly* poly = *polyh;
68389
69390 for (int i = 0; i < poly->maxNumVoices; i++)
70391 {
71− tRamp_free(&poly->ramps[i]);
72− leaf_free(poly->voices[i]);
392+ tRamp_freeFromPool(&poly->ramps[i], mp);
393+ mpool_free(poly->voices[i], m->pool);
73394 }
74− tRamp_free(&poly->pitchBendRamp);
75− tStack_free(&poly->stack);
76− tStack_free(&poly->orderStack);
395+ tRamp_freeFromPool(&poly->pitchBendRamp, mp);
396+ tStack_freeFromPool(&poly->stack, mp);
397+ tStack_freeFromPool(&poly->orderStack, mp);
77398
78− leaf_free(poly->voices);
79− leaf_free(poly->ramps);
80− leaf_free(poly->rampVals);
81− leaf_free(poly->firstReceived);
399+ mpool_free(poly->voices, m->pool);
400+ mpool_free(poly->ramps, m->pool);
401+ mpool_free(poly->rampVals, m->pool);
402+ mpool_free(poly->firstReceived, m->pool);
82403
83− leaf_free(poly);
404+ mpool_free(poly, m->pool);
84405 }
85406
86407 void tPoly_tickPitch(tPoly* polyh)
@@ -332,236 +653,3 @@ int tPoly_isOn(tPoly* const polyh, uint8_t voice) · 245 unmodified lines
332653 _tPoly* poly = *polyh;
333654 return (poly->voices[voice][0] > 0) ? 1 : 0;
334655 }
335−
336−
337−//====================================================================================
338−/* Stack */
339−//====================================================================================
340−
341−void tStack_init(tStack* const stack)
342−{
343− _tStack* ns = *stack = (_tStack*) leaf_alloc(sizeof(_tStack));
344−
345− ns->ordered = OFALSE;
346− ns->size = 0;
347− ns->pos = 0;
348− ns->capacity = STACK_SIZE;
349−
350− for (int i = 0; i < STACK_SIZE; i++) ns->data[i] = -1;
351−}
352−
353−void tStack_free(tStack* const stack)
354−{
355− _tStack* ns = *stack;
356−
357− leaf_free(ns);
358−}
359−
360−// If stack contains note, returns index. Else returns -1;
361−int tStack_contains(tStack* const stack, uint16_t noteVal)
362−{
363− _tStack* ns = *stack;
364− for (int i = 0; i < ns->size; i++)
365− {
366− if (ns->data[i] == noteVal) return i;
367− }
368− return -1;
369−}
370−
371−void tStack_add(tStack* const stack, uint16_t noteVal)
372−{
373− _tStack* ns = *stack;
374−
375− uint8_t j;
376−
377− int whereToInsert = 0;
378− if (ns->ordered)
379− {
380− for (j = 0; j < ns->size; j++)
381− {
382− if (noteVal > ns->data[j])
383− {
384− if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1))
385− {
386− whereToInsert = j+1;
387− break;
388− }
389− }
390− }
391− }
392−
393− //first move notes that are already in the stack one position to the right
394− for (j = ns->size; j > whereToInsert; j--)
395− {
396− ns->data[j] = ns->data[(j - 1)];
397− }
398−
399− //then, insert the new note into the front of the stack
400− ns->data[whereToInsert] = noteVal;
401−
402− ns->size++;
403−}
404−
405−int tStack_addIfNotAlreadyThere(tStack* const stack, uint16_t noteVal)
406−{
407− _tStack* ns = *stack;
408−
409− uint8_t j;
410−
411− int added = 0;
412−
413− if (tStack_contains(stack, noteVal) == -1)
414− {
415− int whereToInsert = 0;
416− if (ns->ordered)
417− {
418− for (j = 0; j < ns->size; j++)
419− {
420− if (noteVal > ns->data[j])
421− {
422− if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1))
423− {
424− whereToInsert = j+1;
425− break;
426− }
427− }
428− }
429− }
430−
431− //first move notes that are already in the stack one position to the right
432− for (j = ns->size; j > whereToInsert; j--)
433− {
434− ns->data[j] = ns->data[(j - 1)];
435− }
436−
437− //then, insert the new note into the front of the stack
438− ns->data[whereToInsert] = noteVal;
439−
440− ns->size++;
441−
442− added = 1;
443− }
444−
445− return added;
446−}
447−
448−
449−// Remove noteVal. return 1 if removed, 0 if not
450−int tStack_remove(tStack* const stack, uint16_t noteVal)
451−{
452− _tStack* ns = *stack;
453−
454− uint8_t k;
455− int foundIndex = tStack_contains(stack, noteVal);
456− int removed = 0;
457−
458− if (foundIndex >= 0)
459− {
460− for (k = 0; k < (ns->size - foundIndex); k++)
461− {
462− if ((k+foundIndex) >= (ns->capacity - 1))
463− {
464− ns->data[k + foundIndex] = -1;
465− }
466− else
467− {
468− ns->data[k + foundIndex] = ns->data[k + foundIndex + 1];
469− if ((k + foundIndex) == (ns->size - 1))
470− {
471− ns->data[k + foundIndex + 1] = -1;
472− }
473− }
474−
475− }
476− // in case it got put on the stack multiple times
477− foundIndex--;
478− ns->size--;
479− removed = 1;
480− }
481−
482− return removed;
483−}
484−
485−// Doesn't change size of data types
486−void tStack_setCapacity(tStack* const stack, uint16_t cap)
487−{
488− _tStack* ns = *stack;
489−
490− if (cap <= 0)
491− ns->capacity = 1;
492− else if (cap <= STACK_SIZE)
493− ns->capacity = cap;
494− else
495− ns->capacity = STACK_SIZE;
496−
497− for (int i = cap; i < STACK_SIZE; i++)
498− {
499− if ((int)ns->data[i] != -1)
500− {
501− ns->data[i] = -1;
502− ns->size -= 1;
503− }
504− }
505−
506− if (ns->pos >= cap)
507− {
508− ns->pos = 0;
509− }
510−}
511−
512−int tStack_getSize(tStack* const stack)
513−{
514− _tStack* ns = *stack;
515−
516− return ns->size;
517−}
518−
519−void tStack_clear(tStack* const stack)
520−{
521− _tStack* ns = *stack;
522−
523− for (int i = 0; i < STACK_SIZE; i++)
524− {
525− ns->data[i] = -1;
526− }
527− ns->pos = 0;
528− ns->size = 0;
529−}
530−
531−// Next item in order of addition to stack. Return 0-31 if there is a next item to move to. Returns -1 otherwise.
532−int tStack_next(tStack* const stack)
533−{
534− _tStack* ns = *stack;
535−
536− int step = 0;
537− if (ns->size != 0) // if there is at least one note in the stack
538− {
539− 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)
540− {
541− ns->pos--;
542− }
543− else
544− {
545− ns->pos = (ns->size - 1); // if you are the most recent note, go back to the earliest note in the array
546− }
547−
548− step = ns->data[ns->pos];
549− return step;
550− }
551− else
552− {
553− return -1;
554− }
555−}
556−
557−int tStack_get(tStack* const stack, int which)
558−{
559− _tStack* ns = *stack;
560− return ns->data[which];
561−}
562−
563−int tStack_first(tStack* const stack)
564−{
565− _tStack* ns = *stack;
566− return ns->data[0];
567−}
LEAF/Src/leaf-oscillators.c+255−44
@@ -19,19 +19,42 @@ · 18 unmodified lines
1919 #endif
2020
2121 // Cycle
22−void tCycle_init(tCycle* const c)
22+void tCycle_init(tCycle* const cy)
2323 {
24+ _tCycle* c = *cy = (_tCycle*) leaf_alloc(sizeof(_tCycle));
25+
2426 c->inc = 0.0f;
2527 c->phase = 0.0f;
2628 }
2729
28−void tCycle_free(tCycle* const c)
30+void tCycle_free(tCycle* const cy)
31+{
32+ _tCycle* c = *cy;
33+
34+ leaf_free(c);
35+}
36+
37+void tCycle_initToPool (tCycle* const cy, tMempool* const mp)
2938 {
39+ _tMempool* m = *mp;
40+ _tCycle* c = *cy = (_tCycle*) mpool_alloc(sizeof(_tCycle), m->pool);
3041
42+ c->inc = 0.0f;
43+ c->phase = 0.0f;
3144 }
3245
33−int tCycle_setFreq(tCycle* const c, float freq)
46+void tCycle_freeFromPool (tCycle* const cy, tMempool* const mp)
3447 {
48+ _tMempool* m = *mp;
49+ _tCycle* c = *cy;
50+
51+ mpool_free(c, m->pool);
52+}
53+
54+int tCycle_setFreq(tCycle* const cy, float freq)
55+{
56+ _tCycle* c = *cy;
57+
3558 if (freq < 0.0f) freq = 0.0f;
3659
3760 c->freq = freq;
@@ -40,8 +63,10 @@ int tCycle_setFreq(tCycle* const c, float freq) · 2 unmodified lines
4063 return 0;
4164 }
4265
43−float tCycle_tick(tCycle* const c)
66+float tCycle_tick(tCycle* const cy)
4467 {
68+ _tCycle* c = *cy;
69+
4570 // Phasor increment
4671 c->phase += c->inc;
4772 while (c->phase >= 1.0f) c->phase -= 1.0f;
@@ -56,31 +81,51 @@ float tCycle_tick(tCycle* const c) · 8 unmodified lines
5681 return (samp0 + (samp1 - samp0) * fracPart);
5782 }
5883
59−void tCycleSampleRateChanged (tCycle* const c)
84+void tCycleSampleRateChanged (tCycle* const cy)
6085 {
86+ _tCycle* c = *cy;
87+
6188 c->inc = c->freq * leaf.invSampleRate;
6289 }
6390
6491 //========================================================================
6592 /* Triangle */
66−void tTriangle_start(tTriangle* const c)
93+void tTriangle_init(tTriangle* const cy)
6794 {
95+ _tTriangle* c = *cy = (_tTriangle*) leaf_alloc(sizeof(_tTriangle));
6896
97+ c->inc = 0.0f;
98+ c->phase = 0.0f;
6999 }
70100
71−void tTriangle_init(tTriangle* const c)
101+void tTriangle_free(tTriangle* const cy)
72102 {
103+ _tTriangle* c = *cy;
104+
105+ leaf_free(c);
106+}
107+
108+void tTriangle_initToPool (tTriangle* const cy, tMempool* const mp)
109+{
110+ _tMempool* m = *mp;
111+ _tTriangle* c = *cy = (_tTriangle*) mpool_alloc(sizeof(_tTriangle), m->pool);
112+
73113 c->inc = 0.0f;
74114 c->phase = 0.0f;
75115 }
76116
77−void tTriangle_free(tTriangle* const c)
117+void tTriangle_freeFromPool (tTriangle* const cy, tMempool* const mp)
78118 {
119+ _tMempool* m = *mp;
120+ _tTriangle* c = *cy;
79121
122+ mpool_free(c, m->pool);
80123 }
81124
82−int tTriangle_setFreq(tTriangle* const c, float freq)
125+int tTriangle_setFreq(tTriangle* const cy, float freq)
83126 {
127+ _tTriangle* c = *cy;
128+
84129 if (freq < 0.0f) freq = 0.0f;
85130
86131 c->freq = freq;
@@ -90,8 +135,10 @@ int tTriangle_setFreq(tTriangle* const c, float freq) · 3 unmodified lines
90135 }
91136
92137
93−float tTriangle_tick(tTriangle* const c)
138+float tTriangle_tick(tTriangle* const cy)
94139 {
140+ _tTriangle* c = *cy;
141+
95142 // Phasor increment
96143 c->phase += c->inc;
97144 while (c->phase >= 1.0f) c->phase -= 1.0f;
@@ -165,26 +212,51 @@ float tTriangle_tick(tTriangle* const c) · 67 unmodified lines
165212 return out;
166213 }
167214
168−void tTriangleSampleRateChanged (tTriangle* const c)
215+void tTriangleSampleRateChanged (tTriangle* const cy)
169216 {
217+ _tTriangle* c = *cy;
218+
170219 c->inc = c->freq * leaf.invSampleRate;
171220 }
172221
173222 //========================================================================
174223 /* Square */
175−void tSquare_init(tSquare* const c)
224+void tSquare_init(tSquare* const cy)
176225 {
226+ _tSquare* c = *cy = (_tSquare*) leaf_alloc(sizeof(_tSquare));
227+
177228 c->inc = 0.0f;
178229 c->phase = 0.0f;
179230 }
180231
181−void tSquare_free(tSquare* const c)
232+void tSquare_free(tSquare* const cy)
182233 {
234+ _tSquare* c = *cy;
183235
236+ leaf_free(c);
184237 }
185238
186−int tSquare_setFreq(tSquare* const c, float freq)
239+void tSquare_initToPool (tSquare* const cy, tMempool* const mp)
187240 {
241+ _tMempool* m = *mp;
242+ _tSquare* c = *cy = (_tSquare*) mpool_alloc(sizeof(_tSquare), m->pool);
243+
244+ c->inc = 0.0f;
245+ c->phase = 0.0f;
246+}
247+
248+void tSquare_freeFromPool(tSquare* const cy, tMempool* const mp)
249+{
250+ _tMempool* m = *mp;
251+ _tSquare* c = *cy;
252+
253+ mpool_free(c, m->pool);
254+}
255+
256+int tSquare_setFreq(tSquare* const cy, float freq)
257+{
258+ _tSquare* c = *cy;
259+
188260 if (freq < 0.0f) freq = 0.0f;
189261
190262 c->freq = freq;
@@ -193,8 +265,10 @@ int tSquare_setFreq(tSquare* const c, float freq) · 2 unmodified lines
193265 return 0;
194266 }
195267
196−float tSquare_tick(tSquare* const c)
268+float tSquare_tick(tSquare* const cy)
197269 {
270+ _tSquare* c = *cy;
271+
198272 // Phasor increment
199273 c->phase += c->inc;
200274 while (c->phase >= 1.0f) c->phase -= 1.0f;
@@ -267,26 +341,51 @@ float tSquare_tick(tSquare* const c) · 66 unmodified lines
267341 return out;
268342 }
269343
270−void tSquareSampleRateChanged (tSquare* const c)
344+void tSquareSampleRateChanged (tSquare* const cy)
271345 {
346+ _tSquare* c = *cy;
347+
272348 c->inc = c->freq * leaf.invSampleRate;
273349 }
274350
275351 //=====================================================================
276352 // Sawtooth
277−void tSawtooth_init(tSawtooth* const c)
353+void tSawtooth_init(tSawtooth* const cy)
354+{
355+ _tSawtooth* c = *cy = (_tSawtooth*) leaf_alloc(sizeof(_tSawtooth));
356+
357+ c->inc = 0.0f;
358+ c->phase = 0.0f;
359+}
360+
361+void tSawtooth_free(tSawtooth* const cy)
278362 {
363+ _tSawtooth* c = *cy;
364+
365+ leaf_free(c);
366+}
367+
368+void tSawtooth_initToPool (tSawtooth* const cy, tMempool* const mp)
369+{
370+ _tMempool* m = *mp;
371+ _tSawtooth* c = *cy = (_tSawtooth*) mpool_alloc(sizeof(_tSawtooth), m->pool);
372+
279373 c->inc = 0.0f;
280374 c->phase = 0.0f;
281375 }
282376
283−void tSawtooth_free(tSawtooth* const c)
377+void tSawtooth_freeFromPool (tSawtooth* const cy, tMempool* const mp)
284378 {
379+ _tMempool* m = *mp;
380+ _tSawtooth* c = *cy;
285381
382+ mpool_free(c, m->pool);
286383 }
287384
288−int tSawtooth_setFreq(tSawtooth* const c, float freq)
385+int tSawtooth_setFreq(tSawtooth* const cy, float freq)
289386 {
387+ _tSawtooth* c = *cy;
388+
290389 if (freq < 0.0f) freq = 0.0f;
291390
292391 c->freq = freq;
@@ -295,8 +394,10 @@ int tSawtooth_setFreq(tSawtooth* const c, float freq) · 2 unmodified lines
295394 return 0;
296395 }
297396
298−float tSawtooth_tick(tSawtooth* const c)
397+float tSawtooth_tick(tSawtooth* const cy)
299398 {
399+ _tSawtooth* c = *cy;
400+
300401 // Phasor increment
301402 c->phase += c->inc;
302403 while (c->phase >= 1.0f) c->phase -= 1.0f;
@@ -370,31 +471,58 @@ float tSawtooth_tick(tSawtooth* const c) · 67 unmodified lines
370471 return out;
371472 }
372473
373−void tSawtoothSampleRateChanged (tSawtooth* const c)
474+void tSawtoothSampleRateChanged (tSawtooth* const cy)
374475 {
476+ _tSawtooth* c = *cy;
477+
375478 c->inc = c->freq * leaf.invSampleRate;
376479 }
377480
378481 //========================================================================
379482 /* Phasor */
380−void tPhasorSampleRateChanged (tPhasor* const p)
483+void tPhasorSampleRateChanged (tPhasor* const ph)
381484 {
485+ _tPhasor* p = *ph;
486+
382487 p->inc = p->freq * leaf.invSampleRate;
383488 };
384489
385−void tPhasor_init(tPhasor* const p)
490+void tPhasor_init(tPhasor* const ph)
386491 {
492+ _tPhasor* p = *ph = (_tPhasor*) leaf_alloc(sizeof(_tPhasor));
493+
387494 p->phase = 0.0f;
388495 p->inc = 0.0f;
389496 }
390497
391−void tPhasor_free(tPhasor* const p)
498+void tPhasor_free(tPhasor* const ph)
392499 {
500+ _tPhasor* p = *ph;
393501
502+ leaf_free(p);
394503 }
395504
396−int tPhasor_setFreq(tPhasor* const p, float freq)
505+void tPhasor_initToPool (tPhasor* const ph, tMempool* const mp)
397506 {
507+ _tMempool* m = *mp;
508+ _tPhasor* p = *ph = (_tPhasor*) mpool_alloc(sizeof(_tPhasor), m->pool);
509+
510+ p->phase = 0.0f;
511+ p->inc = 0.0f;
512+}
513+
514+void tPhasor_freeFromPool(tPhasor* const ph, tMempool* const mp)
515+{
516+ _tMempool* m = *mp;
517+ _tPhasor* p = *ph;
518+
519+ mpool_free(p, m->pool);
520+}
521+
522+int tPhasor_setFreq(tPhasor* const ph, float freq)
523+{
524+ _tPhasor* p = *ph;
525+
398526 if (freq < 0.0f) freq = 0.0f;
399527
400528 p->freq = freq;
@@ -403,8 +531,10 @@ int tPhasor_setFreq(tPhasor* const p, float freq) · 2 unmodified lines
403531 return 0;
404532 }
405533
406−float tPhasor_tick(tPhasor* const p)
534+float tPhasor_tick(tPhasor* const ph)
407535 {
536+ _tPhasor* p = *ph;
537+
408538 p->phase += p->inc;
409539
410540 if (p->phase >= 1.0f) p->phase -= 1.0f;
@@ -413,19 +543,42 @@ float tPhasor_tick(tPhasor* const p) · 2 unmodified lines
413543 }
414544
415545 /* Noise */
416−void tNoise_init(tNoise* const n, NoiseType type)
546+void tNoise_init(tNoise* const ns, NoiseType type)
547+{
548+ _tNoise* n = *ns = (_tNoise*) leaf_alloc(sizeof(_tNoise));
549+
550+ n->type = type;
551+ n->rand = leaf.random;
552+}
553+
554+void tNoise_free(tNoise* const ns)
417555 {
556+ _tNoise* n = *ns;
557+
558+ leaf_free(n);
559+}
560+
561+void tNoise_initToPool (tNoise* const ns, NoiseType type, tMempool* const mp)
562+{
563+ _tMempool* m = *mp;
564+ _tNoise* n = *ns = (_tNoise*) mpool_alloc(sizeof(_tNoise), m->pool);
565+
418566 n->type = type;
419567 n->rand = leaf.random;
420568 }
421569
422−void tNoise_free(tNoise* const n)
570+void tNoise_freeFromPool (tNoise* const ns, tMempool* const mp)
423571 {
572+ _tMempool* m = *mp;
573+ _tNoise* n = *ns;
424574
575+ mpool_free(n, m->pool);
425576 }
426577
427−float tNoise_tick(tNoise* const n)
578+float tNoise_tick(tNoise* const ns)
428579 {
580+ _tNoise* n = *ns;
581+
429582 float rand = (n->rand() * 2.0f) - 1.0f;
430583
431584 if (n->type == PinkNoise)
@@ -446,13 +599,15 @@ float tNoise_tick(tNoise* const n) · 14 unmodified lines
446599 //=================================================================================
447600 /* Neuron */
448601
449−void tNeuronSampleRateChanged(tNeuron* n)
602+void tNeuronSampleRateChanged(tNeuron* nr)
450603 {
451604
452605 }
453606
454−void tNeuron_init(tNeuron* const n)
607+void tNeuron_init(tNeuron* const nr)
455608 {
609+ _tNeuron* n = *nr = (_tNeuron*) leaf_alloc(sizeof(_tNeuron));
610+
456611 tPoleZero_init(&n->f);
457612
458613 tPoleZero_setBlockZero(&n->f, 0.99f);
@@ -480,13 +635,20 @@ void tNeuron_init(tNeuron* const n) · 21 unmodified lines
480635 n->rate[2] = n->gL/n->C;
481636 }
482637
483−void tNeuron_free(tNeuron* const n)
638+void tNeuron_free(tNeuron* const nr)
484639 {
640+ _tNeuron* n = *nr;
641+
485642 tPoleZero_free(&n->f);
643+ leaf_free(n);
486644 }
487645
488−void tNeuron_reset(tNeuron* const n)
646+void tNeuron_initToPool (tNeuron* const nr, tMempool* const mp)
489647 {
648+ _tMempool* m = *mp;
649+ _tNeuron* n = *nr = (_tNeuron*) mpool_alloc(sizeof(_tNeuron), m->pool);
650+
651+ tPoleZero_initToPool(&n->f, mp);
490652
491653 tPoleZero_setBlockZero(&n->f, 0.99f);
492654
@@ -513,52 +675,99 @@ void tNeuron_reset(tNeuron* const n) · 20 unmodified lines
513675 n->rate[2] = n->gL/n->C;
514676 }
515677
678+void tNeuron_freeFromPool(tNeuron* const nr, tMempool* const mp)
679+{
680+ _tMempool* m = *mp;
681+ _tNeuron* n = *nr;
682+
683+ tPoleZero_free(&n->f);
684+ mpool_free(n, m->pool);
685+}
686+
687+void tNeuron_reset(tNeuron* const nr)
688+{
689+ _tNeuron* n = *nr;
690+
691+ tPoleZero_setBlockZero(&n->f, 0.99f);
692+
693+ n->timeStep = 1.0f / 50.0f;
694+
695+ n->current = 0.0f; // 100.0f for sound
696+ n->voltage = 0.0f;
697+
698+ n->mode = NeuronNormal;
699+
700+ n->P[0] = 0.0f;
701+ n->P[1] = 0.0f;
702+ n->P[2] = 1.0f;
703+
704+ n->V[0] = -12.0f;
705+ n->V[1] = 115.0f;
706+ n->V[2] = 10.613f;
707+
708+ n->gK = 36.0f;
709+ n->gN = 120.0f;
710+ n->gL = 0.3f;
711+ n->C = 1.0f;
712+
713+ n->rate[2] = n->gL/n->C;
714+}
516715
517−void tNeuron_setV1(tNeuron* const n, float V1)
716+void tNeuron_setV1(tNeuron* const nr, float V1)
518717 {
718+ _tNeuron* n = *nr;
519719 n->V[0] = V1;
520720 }
521721
522722
523−void tNeuron_setV2(tNeuron* const n, float V2)
723+void tNeuron_setV2(tNeuron* const nr, float V2)
524724 {
725+ _tNeuron* n = *nr;
525726 n->V[1] = V2;
526727 }
527728
528−void tNeuron_setV3(tNeuron* const n, float V3)
729+void tNeuron_setV3(tNeuron* const nr, float V3)
529730 {
731+ _tNeuron* n = *nr;
530732 n->V[2] = V3;
531733 }
532734
533−void tNeuron_setTimeStep(tNeuron* const n, float timeStep)
735+void tNeuron_setTimeStep(tNeuron* const nr, float timeStep)
534736 {
737+ _tNeuron* n = *nr;
535738 n->timeStep = timeStep;
536739 }
537740
538−void tNeuron_setK(tNeuron* const n, float K)
741+void tNeuron_setK(tNeuron* const nr, float K)
539742 {
743+ _tNeuron* n = *nr;
540744 n->gK = K;
541745 }
542746
543−void tNeuron_setL(tNeuron* const n, float L)
747+void tNeuron_setL(tNeuron* const nr, float L)
544748 {
749+ _tNeuron* n = *nr;
545750 n->gL = L;
546751 n->rate[2] = n->gL/n->C;
547752 }
548753
549−void tNeuron_setN(tNeuron* const n, float N)
754+void tNeuron_setN(tNeuron* const nr, float N)
550755 {
756+ _tNeuron* n = *nr;
551757 n->gN = N;
552758 }
553759
554−void tNeuron_setC(tNeuron* const n, float C)
760+void tNeuron_setC(tNeuron* const nr, float C)
555761 {
762+ _tNeuron* n = *nr;
556763 n->C = C;
557764 n->rate[2] = n->gL/n->C;
558765 }
559766
560−float tNeuron_tick(tNeuron* const n)
767+float tNeuron_tick(tNeuron* const nr)
561768 {
769+ _tNeuron* n = *nr;
770+
562771 float output = 0.0f;
563772 float voltage = n->voltage;
564773
@@ -631,12 +840,14 @@ float tNeuron_tick(tNeuron* const n) · 66 unmodified lines
631840
632841 }
633842
634−void tNeuron_setMode (tNeuron* const n, NeuronMode mode)
843+void tNeuron_setMode (tNeuron* const nr, NeuronMode mode)
635844 {
845+ _tNeuron* n = *nr;
636846 n->mode = mode;
637847 }
638848
639−void tNeuron_setCurrent (tNeuron* const n, float current)
849+void tNeuron_setCurrent (tNeuron* const nr, float current)
640850 {
851+ _tNeuron* n = *nr;
641852 n->current = current;
642853 }
LEAF/Src/leaf-physical.c+194−8
@@ -46,6 +46,37 @@ void tPluck_free (tPluck* const pl) · 45 unmodified lines
4646 leaf_free(p);
4747 }
4848
49+void tPluck_initToPool (tPluck* const pl, float lowestFrequency, tMempool* const mp)
50+{
51+ _tMempool* m = *mp;
52+ _tPluck* p = *pl = (_tPluck*) mpool_alloc(sizeof(_tPluck), m->pool);
53+
54+ if ( lowestFrequency <= 0.0f ) lowestFrequency = 10.0f;
55+
56+ tNoise_initToPool(&p->noise, WhiteNoise, mp);
57+
58+ tOnePole_initToPool(&p->pickFilter, 0.0f, mp);
59+
60+ tOneZero_initToPool(&p->loopFilter, 0.0f, mp);
61+
62+ tAllpassDelay_initToPool(&p->delayLine, 0.0f, leaf.sampleRate * 2, mp);
63+
64+ tPluck_setFrequency(pl, 220.0f);
65+}
66+
67+void tPluck_freeFromPool (tPluck* const pl, tMempool* const mp)
68+{
69+ _tMempool* m = *mp;
70+ _tPluck* p = *pl;
71+
72+ tNoise_freeFromPool(&p->noise, mp);
73+ tOnePole_freeFromPool(&p->pickFilter, mp);
74+ tOneZero_freeFromPool(&p->loopFilter, mp);
75+ tAllpassDelay_freeFromPool(&p->delayLine, mp);
76+
77+ mpool_free(p, m->pool);
78+}
79+
4980 float tPluck_getLastOut (tPluck* const pl)
5081 {
5182 _tPluck* p = *pl;
@@ -124,7 +155,7 @@ void tPluckSampleRateChanged(tPluck* const pl) · 72 unmodified lines
124155 }
125156
126157 /* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tKarplusStrong ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
127−void tKarplusStrong_init (tKarplusStrong* const pl, float lowestFrequency)
158+void tKarplusStrong_init (tKarplusStrong* const pl, float lowestFrequency)
128159 {
129160 _tKarplusStrong* p = *pl = (_tKarplusStrong*) leaf_alloc(sizeof(_tKarplusStrong));
130161
@@ -151,7 +182,6 @@ void tKarplusStrong_init (tKarplusStrong* const pl, float lowestFreq · 20 unmodified lines
151182 p->loopGain = 0.999f;
152183
153184 tKarplusStrong_setFrequency( pl, 220.0f );
154−
155185 }
156186
157187 void tKarplusStrong_free (tKarplusStrong* const pl)
@@ -171,6 +201,54 @@ void tKarplusStrong_free (tKarplusStrong* const pl) · 13 unmodified lines
171201 leaf_free(p);
172202 }
173203
204+void tKarplusStrong_initToPool (tKarplusStrong* const pl, float lowestFrequency, tMempool* const mp)
205+{
206+ _tMempool* m = *mp;
207+ _tKarplusStrong* p = *pl = (_tKarplusStrong*) mpool_alloc(sizeof(_tKarplusStrong), m->pool);
208+
209+ if ( lowestFrequency <= 0.0f ) lowestFrequency = 8.0f;
210+
211+ tAllpassDelay_initToPool(&p->delayLine, 0.0f, leaf.sampleRate * 2, mp);
212+
213+ tLinearDelay_initToPool(&p->combDelay, 0.0f, leaf.sampleRate * 2, mp);
214+
215+ tOneZero_initToPool(&p->filter, 0.0f, mp);
216+
217+ tNoise_initToPool(&p->noise, WhiteNoise, mp);
218+
219+ for (int i = 0; i < 4; i++)
220+ {
221+ tBiQuad_initToPool(&p->biquad[i], mp);
222+ }
223+
224+ p->pluckAmplitude = 0.3f;
225+ p->pickupPosition = 0.4f;
226+
227+ p->stretching = 0.9999f;
228+ p->baseLoopGain = 0.995f;
229+ p->loopGain = 0.999f;
230+
231+ tKarplusStrong_setFrequency( pl, 220.0f );
232+}
233+
234+void tKarplusStrong_freeFromPool (tKarplusStrong* const pl, tMempool* const mp)
235+{
236+ _tMempool* m = *mp;
237+ _tKarplusStrong* p = *pl;
238+
239+ tAllpassDelay_freeFromPool(&p->delayLine, mp);
240+ tLinearDelay_freeFromPool(&p->combDelay, mp);
241+ tOneZero_freeFromPool(&p->filter, mp);
242+ tNoise_freeFromPool(&p->noise, mp);
243+
244+ for (int i = 0; i < 4; i++)
245+ {
246+ tBiQuad_freeFromPool(&p->biquad[i], mp);
247+ }
248+
249+ mpool_free(p, m->pool);
250+}
251+
174252 float tKarplusStrong_getLastOut (tKarplusStrong* const pl)
175253 {
176254 _tKarplusStrong* p = *pl;
@@ -328,7 +406,9 @@ void tKarplusStrongSampleRateChanged (tKarplusStrong* const pl) · 151 unmodified lines
328406
329407 /* Simple Living String*/
330408
331−void tSimpleLivingString_init(tSimpleLivingString* const pl, float freq, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode)
409+void tSimpleLivingString_init(tSimpleLivingString* const pl, float freq, float dampFreq,
410+ float decay, float targetLev, float levSmoothFactor,
411+ float levStrength, int levMode)
332412 {
333413 _tSimpleLivingString* p = *pl = (_tSimpleLivingString*) leaf_alloc(sizeof(_tSimpleLivingString));
334414
@@ -356,6 +436,38 @@ void tSimpleLivingString_free(tSimpleLivingString* const pl) · 21 unmodified lines
356436 leaf_free(p);
357437 }
358438
439+void tSimpleLivingString_initToPool (tSimpleLivingString* const pl, float freq, float dampFreq,
440+ float decay, float targetLev, float levSmoothFactor,
441+ float levStrength, int levMode, tMempool* const mp)
442+{
443+ _tMempool* m = *mp;
444+ _tSimpleLivingString* p = *pl = (_tSimpleLivingString*) mpool_alloc(sizeof(_tSimpleLivingString), m->pool);
445+
446+ p->curr=0.0f;
447+ tExpSmooth_initToPool(&p->wlSmooth, leaf.sampleRate/freq, 0.01, mp); // smoother for string wavelength (not freq, to avoid expensive divisions)
448+ tSimpleLivingString_setFreq(pl, freq);
449+ tLinearDelay_initToPool(&p->delayLine,p->waveLengthInSamples, 2400, mp);
450+ tOnePole_initToPool(&p->bridgeFilter, dampFreq, mp);
451+ tHighpass_initToPool(&p->DCblocker,13, mp);
452+ p->decay=decay;
453+ tFeedbackLeveler_initToPool(&p->fbLev, targetLev, levSmoothFactor, levStrength, levMode, mp);
454+ p->levMode=levMode;
455+}
456+
457+void tSimpleLivingString_freeFromPool (tSimpleLivingString* const pl, tMempool* const mp)
458+{
459+ _tMempool* m = *mp;
460+ _tSimpleLivingString* p = *pl;
461+
462+ tExpSmooth_freeFromPool(&p->wlSmooth, mp);
463+ tLinearDelay_freeFromPool(&p->delayLine, mp);
464+ tOnePole_freeFromPool(&p->bridgeFilter, mp);
465+ tHighpass_freeFromPool(&p->DCblocker, mp);
466+ tFeedbackLeveler_freeFromPool(&p->fbLev, mp);
467+
468+ mpool_free(p, m->pool);
469+}
470+
359471 void tSimpleLivingString_setFreq(tSimpleLivingString* const pl, float freq)
360472 {
361473 _tSimpleLivingString* p = *pl;
@@ -433,7 +545,9 @@ float tSimpleLivingString_sample(tSimpleLivingString* const pl) · 71 unmodified lines
433545
434546 /* Living String*/
435547
436−void tLivingString_init(tLivingString* const pl, float freq, float pickPos, float prepIndex, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode)
548+void tLivingString_init(tLivingString* const pl, float freq, float pickPos, float prepIndex,
549+ float dampFreq, float decay, float targetLev, float levSmoothFactor,
550+ float levStrength, int levMode)
437551 {
438552 _tLivingString* p = *pl = (_tLivingString*) leaf_alloc(sizeof(_tLivingString));
439553
@@ -484,6 +598,61 @@ void tLivingString_free(tLivingString* const pl) · 44 unmodified lines
484598 leaf_free(p);
485599 }
486600
601+void tLivingString_initToPool (tLivingString* const pl, float freq, float pickPos, float prepIndex,
602+ float dampFreq, float decay, float targetLev, float levSmoothFactor,
603+ float levStrength, int levMode, tMempool* const mp)
604+{
605+ _tMempool* m = *mp;
606+ _tLivingString* p = *pl = (_tLivingString*) mpool_alloc(sizeof(_tLivingString), m->pool);
607+
608+ p->curr=0.0f;
609+ tExpSmooth_initToPool(&p->wlSmooth, leaf.sampleRate/freq, 0.01, mp); // smoother for string wavelength (not freq, to avoid expensive divisions)
610+ tLivingString_setFreq(pl, freq);
611+ p->freq = freq;
612+ tExpSmooth_initToPool(&p->ppSmooth, pickPos, 0.01, mp); // smoother for pick position
613+ tLivingString_setPickPos(pl, pickPos);
614+ p->prepIndex=prepIndex;
615+ tLinearDelay_initToPool(&p->delLF,p->waveLengthInSamples, 2400, mp);
616+ tLinearDelay_initToPool(&p->delUF,p->waveLengthInSamples, 2400, mp);
617+ tLinearDelay_initToPool(&p->delUB,p->waveLengthInSamples, 2400, mp);
618+ tLinearDelay_initToPool(&p->delLB,p->waveLengthInSamples, 2400, mp);
619+ p->dampFreq = dampFreq;
620+ tOnePole_initToPool(&p->bridgeFilter, dampFreq, mp);
621+ tOnePole_initToPool(&p->nutFilter, dampFreq, mp);
622+ tOnePole_initToPool(&p->prepFilterU, dampFreq, mp);
623+ tOnePole_initToPool(&p->prepFilterL, dampFreq, mp);
624+ tHighpass_initToPool(&p->DCblockerU,13, mp);
625+ tHighpass_initToPool(&p->DCblockerL,13, mp);
626+ p->decay=decay;
627+ p->prepIndex = prepIndex;
628+ tFeedbackLeveler_initToPool(&p->fbLevU, targetLev, levSmoothFactor, levStrength, levMode, mp);
629+ tFeedbackLeveler_initToPool(&p->fbLevL, targetLev, levSmoothFactor, levStrength, levMode, mp);
630+ p->levMode=levMode;
631+}
632+
633+void tLivingString_freeFromPool (tLivingString* const pl, tMempool* const mp)
634+{
635+ _tMempool* m = *mp;
636+ _tLivingString* p = *pl;
637+
638+ tExpSmooth_freeFromPool(&p->wlSmooth, mp);
639+ tExpSmooth_freeFromPool(&p->ppSmooth, mp);
640+ tLinearDelay_freeFromPool(&p->delLF, mp);
641+ tLinearDelay_freeFromPool(&p->delUF, mp);
642+ tLinearDelay_freeFromPool(&p->delUB, mp);
643+ tLinearDelay_freeFromPool(&p->delLB, mp);
644+ tOnePole_freeFromPool(&p->bridgeFilter, mp);
645+ tOnePole_freeFromPool(&p->nutFilter, mp);
646+ tOnePole_freeFromPool(&p->prepFilterU, mp);
647+ tOnePole_freeFromPool(&p->prepFilterL, mp);
648+ tHighpass_freeFromPool(&p->DCblockerU, mp);
649+ tHighpass_freeFromPool(&p->DCblockerL, mp);
650+ tFeedbackLeveler_freeFromPool(&p->fbLevU, mp);
651+ tFeedbackLeveler_freeFromPool(&p->fbLevL, mp);
652+
653+ mpool_free(p, m->pool);
654+}
655+
487656 void tLivingString_setFreq(tLivingString* const pl, float freq)
488657 { // NOTE: It is faster to set wavelength in samples directly
489658 _tLivingString* p = *pl;
@@ -577,20 +746,20 @@ float tLivingString_tick(tLivingString* const pl, float input) · 87 unmodified lines
577746 tLinearDelay_tickIn(&p->delUB, fromNut);
578747 // into lower half of string, from pickpoint, going backwards
579748 float fromLowerPrep=-tOnePole_tick(&p->prepFilterL, fromLF);
580− float intoLower=p->prepIndex*fromLowerPrep+(1-p->prepIndex)*fromUB+input;
749+ float intoLower=p->prepIndex*fromLowerPrep+(1.0f - p->prepIndex)*fromUB+input;
581750 tLinearDelay_tickIn(&p->delLB, intoLower);
582751 // into lower half of string, from bridge
583− float fromBridge=-tFeedbackLeveler_tick(&p->fbLevL, (p->levMode==0?p->decay:1)*tHighpass_tick(&p->DCblockerL, tOnePole_tick(&p->bridgeFilter, fromLB)));
752+ float fromBridge=-tFeedbackLeveler_tick(&p->fbLevL, (p->levMode==0?p->decay:1.0f)*tHighpass_tick(&p->DCblockerL, tOnePole_tick(&p->bridgeFilter, fromLB)));
584753 tLinearDelay_tickIn(&p->delLF, fromBridge);
585754 // into upper half of string, from pickpoint, going forwards/upwards
586755 float fromUpperPrep=-tOnePole_tick(&p->prepFilterU, fromUB);
587− float intoUpper=p->prepIndex*fromUpperPrep+(1-p->prepIndex)*fromLF+input;
756+ float intoUpper=p->prepIndex*fromUpperPrep+(1.0f - p->prepIndex)*fromLF+input;
588757 tLinearDelay_tickIn(&p->delUF, intoUpper);
589758 // update all delay lengths
590759 float pickP=tExpSmooth_tick(&p->ppSmooth);
591760 float wLen=tExpSmooth_tick(&p->wlSmooth);
592761 float lowLen=pickP*wLen;
593− float upLen=(1-pickP)*wLen;
762+ float upLen=(1.0f-pickP)*wLen;
594763 tLinearDelay_setDelay(&p->delLF, lowLen);
595764 tLinearDelay_setDelay(&p->delLB, lowLen);
596765 tLinearDelay_setDelay(&p->delUF, upLen);
@@ -623,6 +792,23 @@ void tReedTable_free (tReedTable* const pm) · 26 unmodified lines
623792 leaf_free(p);
624793 }
625794
795+void tReedTable_initToPool (tReedTable* const pm, float offset, float slope, tMempool* const mp)
796+{
797+ _tMempool* m = *mp;
798+ _tReedTable* p = *pm = (_tReedTable*) mpool_alloc(sizeof(_tReedTable), m->pool);
799+
800+ p->offset = offset;
801+ p->slope = slope;
802+}
803+
804+void tReedTable_freeFromPool (tReedTable* const pm, tMempool* const mp)
805+{
806+ _tMempool* m = *mp;
807+ _tReedTable* p = *pm;
808+
809+ mpool_free(p, m->pool);
810+}
811+
626812 float tReedTable_tick (tReedTable* const pm, float input)
627813 {
628814 _tReedTable* p = *pm;
LEAF/Src/leaf-reverb.c+215−3
@@ -65,6 +65,54 @@ void tPRCReverb_free(tPRCReverb* const rev) · 64 unmodified lines
6565 leaf_free(r);
6666 }
6767
68+void tPRCReverb_initToPool (tPRCReverb* const rev, float t60, tMempool* const mp)
69+{
70+ _tMempool* m = *mp;
71+ _tPRCReverb* r = *rev = (_tPRCReverb*) mpool_alloc(sizeof(_tPRCReverb), m->pool);
72+
73+ if (t60 <= 0.0f) t60 = 0.001f;
74+
75+ r->inv_441 = 1.0f/44100.0f;
76+
77+ int lengths[4] = { 341, 613, 1557, 2137 }; // Delay lengths for 44100 Hz sample rate.
78+ double scaler = leaf.sampleRate * r->inv_441;
79+
80+ int delay, i;
81+ if (scaler != 1.0f)
82+ {
83+ for (i=0; i<4; i++)
84+ {
85+ delay = (int) scaler * lengths[i];
86+
87+ if ( (delay & 1) == 0) delay++;
88+
89+ while ( !LEAF_isPrime(delay) ) delay += 2;
90+
91+ lengths[i] = delay;
92+ }
93+ }
94+
95+ tDelay_initToPool(&r->allpassDelays[0], lengths[0], lengths[0] * 2, mp);
96+ tDelay_initToPool(&r->allpassDelays[1], lengths[1], lengths[1] * 2, mp);
97+ tDelay_initToPool(&r->combDelay, lengths[2], lengths[2] * 2, mp);
98+
99+ tPRCReverb_setT60(rev, t60);
100+
101+ r->allpassCoeff = 0.7f;
102+ r->mix = 0.5f;
103+}
104+
105+void tPRCReverb_freeFromPool (tPRCReverb* const rev, tMempool* const mp)
106+{
107+ _tMempool* m = *mp;
108+ _tPRCReverb* r = *rev;
109+
110+ tDelay_freeFromPool(&r->allpassDelays[0], mp);
111+ tDelay_freeFromPool(&r->allpassDelays[1], mp);
112+ tDelay_freeFromPool(&r->combDelay, mp);
113+ mpool_free(r, m->pool);
114+}
115+
68116 void tPRCReverb_setT60(tPRCReverb* const rev, float t60)
69117 {
70118 _tPRCReverb* r = *rev;
@@ -150,12 +198,14 @@ void tNReverb_init(tNReverb* const rev, float t60) · 79 unmodified lines
150198 for ( i=0; i<6; i++ )
151199 {
152200 tLinearDelay_init(&r->combDelays[i], lengths[i], lengths[i] * 2.0f);
201+ tLinearDelay_clear(&r->combDelays[i]);
153202 r->combCoeffs[i] = pow(10.0, (-3 * lengths[i] * leaf.invSampleRate / t60));
154203 }
155204
156205 for ( i=0; i<8; i++ )
157206 {
158207 tLinearDelay_init(&r->allpassDelays[i], lengths[i+6], lengths[i+6] * 2.0f);
208+ tLinearDelay_clear(&r->allpassDelays[i]);
159209 }
160210
161211
@@ -181,6 +231,65 @@ void tNReverb_free(tNReverb* const rev) · 19 unmodified lines
181231 leaf_free(r);
182232 }
183233
234+void tNReverb_initToPool (tNReverb* const rev, float t60, tMempool* const mp)
235+{
236+ _tMempool* m = *mp;
237+ _tNReverb* r = *rev = (_tNReverb*) mpool_alloc(sizeof(_tNReverb), m->pool);
238+
239+ if (t60 <= 0.0f) t60 = 0.001f;
240+
241+ r->inv_441 = 1.0f/44100.0f;
242+
243+ 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.
244+ double scaler = leaf.sampleRate / 25641.0f;
245+
246+ int delay, i;
247+
248+ for (i=0; i < 15; i++)
249+ {
250+ delay = (int) scaler * lengths[i];
251+ if ( (delay & 1) == 0)
252+ delay++;
253+ while ( !LEAF_isPrime(delay) )
254+ delay += 2;
255+ lengths[i] = delay;
256+ }
257+
258+ for ( i=0; i<6; i++ )
259+ {
260+ tLinearDelay_initToPool(&r->combDelays[i], lengths[i], lengths[i] * 2.0f, mp);
261+ r->combCoeffs[i] = pow(10.0, (-3 * lengths[i] * leaf.invSampleRate / t60));
262+ }
263+
264+ for ( i=0; i<8; i++ )
265+ {
266+ tLinearDelay_initToPool(&r->allpassDelays[i], lengths[i+6], lengths[i+6] * 2.0f, mp);
267+ }
268+
269+
270+ tNReverb_setT60(rev, t60);
271+ r->allpassCoeff = 0.7f;
272+ r->mix = 0.3f;
273+}
274+
275+void tNReverb_freeFromPool (tNReverb* const rev, tMempool* const mp)
276+{
277+ _tMempool* m = *mp;
278+ _tNReverb* r = *rev;
279+
280+ for (int i = 0; i < 6; i++)
281+ {
282+ tLinearDelay_freeFromPool(&r->combDelays[i], mp);
283+ }
284+
285+ for (int i = 0; i < 8; i++)
286+ {
287+ tLinearDelay_freeFromPool(&r->allpassDelays[i], mp);
288+ }
289+
290+ mpool_free(r, m->pool);
291+}
292+
184293 void tNReverb_setT60(tNReverb* const rev, float t60)
185294 {
186295 _tNReverb* r = *rev;
@@ -204,7 +313,7 @@ float tNReverb_tick(tNReverb* const rev, float input) · 17 unmodified lines
204313 _tNReverb* r = *rev;
205314 r->lastIn = input;
206315
207− float temp, temp0, temp1, temp2, temp3, out;
316+ float temp, temp0, temp1, temp2, out;
208317 int i;
209318
210319 temp0 = 0.0;
@@ -381,8 +490,6 @@ void tDattorroReverb_init (tDattorroReverb* const rev) · 170 unmodified lines
381490 tDattorroReverb_setFeedbackFilter(rev, 5000.f);
382491
383492 tDattorroReverb_setFeedbackGain(rev, 0.4f);
384−
385−
386493 }
387494
388495 void tDattorroReverb_free (tDattorroReverb* const rev)
@@ -427,6 +534,111 @@ void tDattorroReverb_free (tDattorroReverb* const rev) · 38 unmodified lines
427534 leaf_free(r);
428535 }
429536
537+void tDattorroReverb_initToPool (tDattorroReverb* const rev, tMempool* const mp)
538+{
539+ _tMempool* m = *mp;
540+ _tDattorroReverb* r = *rev = (_tDattorroReverb*) mpool_alloc(sizeof(_tDattorroReverb), m->pool);
541+
542+ r->size_max = 2.0f;
543+ r->size = 1.f;
544+ r->t = r->size * leaf.sampleRate * 0.001f;
545+ r->frozen = 0;
546+ // INPUT
547+ tTapeDelay_initToPool(&r->in_delay, 0.f, SAMP(200.f), mp);
548+ tOnePole_initToPool(&r->in_filter, 1.f, mp);
549+
550+ for (int i = 0; i < 4; i++)
551+ {
552+ tAllpass_initToPool(&r->in_allpass[i], SAMP(in_allpass_delays[i]), SAMP(20.f), mp); // * r->size_max
553+ tAllpass_setGain(&r->in_allpass[i], in_allpass_gains[i]);
554+ }
555+
556+ // FEEDBACK 1
557+ tAllpass_initToPool(&r->f1_allpass, SAMP(30.51f), SAMP(100.f), mp); // * r->size_max
558+ tAllpass_setGain(&r->f1_allpass, 0.7f);
559+
560+ tTapeDelay_initToPool(&r->f1_delay_1, SAMP(141.69f), SAMP(200.0f) * r->size_max + 1, mp);
561+ tTapeDelay_initToPool(&r->f1_delay_2, SAMP(89.24f), SAMP(100.0f) * r->size_max + 1, mp);
562+ tTapeDelay_initToPool(&r->f1_delay_3, SAMP(125.f), SAMP(200.0f) * r->size_max + 1, mp);
563+
564+ tOnePole_initToPool(&r->f1_filter, 1.f, mp);
565+
566+ tHighpass_initToPool(&r->f1_hp, 20.f, mp);
567+
568+ tCycle_initToPool(&r->f1_lfo, mp);
569+ tCycle_setFreq(&r->f1_lfo, 0.1f);
570+
571+ // FEEDBACK 2
572+ tAllpass_initToPool(&r->f2_allpass, SAMP(22.58f), SAMP(100.f), mp); // * r->size_max
573+ tAllpass_setGain(&r->f2_allpass, 0.7f);
574+
575+ tTapeDelay_initToPool(&r->f2_delay_1, SAMP(149.62f), SAMP(200.f) * r->size_max + 1, mp);
576+ tTapeDelay_initToPool(&r->f2_delay_2, SAMP(60.48f), SAMP(100.f) * r->size_max + 1, mp);
577+ tTapeDelay_initToPool(&r->f2_delay_3, SAMP(106.28f), SAMP(200.f) * r->size_max + 1, mp);
578+
579+ tOnePole_initToPool(&r->f2_filter, 1.f, mp);
580+
581+ tHighpass_initToPool(&r->f2_hp, 20.f, mp);
582+
583+ tCycle_initToPool(&r->f2_lfo, mp);
584+ tCycle_setFreq(&r->f2_lfo, 0.07f);
585+
586+
587+ // PARAMETERS
588+ tDattorroReverb_setMix(rev, 0.5f);
589+
590+ tDattorroReverb_setInputDelay(rev, 0.f);
591+
592+ tDattorroReverb_setInputFilter(rev, 10000.f);
593+
594+ tDattorroReverb_setFeedbackFilter(rev, 5000.f);
595+
596+ tDattorroReverb_setFeedbackGain(rev, 0.4f);
597+}
598+
599+void tDattorroReverb_freeFromPool (tDattorroReverb* const rev, tMempool* const mp)
600+{
601+ _tMempool* m = *mp;
602+ _tDattorroReverb* r = *rev;
603+
604+ // INPUT
605+ tTapeDelay_freeFromPool(&r->in_delay, mp);
606+ tOnePole_freeFromPool(&r->in_filter, mp);
607+
608+ for (int i = 0; i < 4; i++)
609+ {
610+ tAllpass_freeFromPool(&r->in_allpass[i], mp);
611+ }
612+
613+ // FEEDBACK 1
614+ tAllpass_freeFromPool(&r->f1_allpass, mp);
615+
616+ tTapeDelay_freeFromPool(&r->f1_delay_1, mp);
617+ tTapeDelay_freeFromPool(&r->f1_delay_2, mp);
618+ tTapeDelay_freeFromPool(&r->f1_delay_3, mp);
619+
620+ tOnePole_freeFromPool(&r->f1_filter, mp);
621+
622+ tHighpass_freeFromPool(&r->f1_hp, mp);
623+
624+ tCycle_freeFromPool(&r->f1_lfo, mp);
625+
626+ // FEEDBACK 2
627+ tAllpass_freeFromPool(&r->f2_allpass, mp);
628+
629+ tTapeDelay_freeFromPool(&r->f2_delay_1, mp);
630+ tTapeDelay_freeFromPool(&r->f2_delay_2, mp);
631+ tTapeDelay_freeFromPool(&r->f2_delay_3, mp);
632+
633+ tOnePole_freeFromPool(&r->f2_filter, mp);
634+
635+ tHighpass_freeFromPool(&r->f2_hp, mp);
636+
637+ tCycle_freeFromPool(&r->f2_lfo, mp);
638+
639+ mpool_free(r, m->pool);
640+}
641+
430642 float tDattorroReverb_tick (tDattorroReverb* const rev, float input)
431643 {
432644 _tDattorroReverb* r = *rev;
LEAF/Src/leaf-sampling.c+17−20
@@ -35,22 +35,6 @@ void tBuffer_init (tBuffer* const sb, uint32_t length) · 34 unmodified lines
3535 s->active = 0;
3636 s->idx = 0;
3737 s->mode = RecordOneShot;
38−
39− tBuffer_clear(sb);
40−}
41−
42−void tBuffer_init_locate (tBuffer* const sb, uint32_t length, mpool_t* pool)
43−{
44− _tBuffer* s = *sb = (_tBuffer*) mpool_alloc(sizeof(_tBuffer), pool);
45−
46− s->buff = (float*) mpool_alloc( sizeof(float) * length, pool);
47−
48− s->bufferLength = length;
49− s->recordedLength = 0;
50− s->idx = 0;
51− s->mode = RecordOneShot;
52−
53− tBuffer_clear(sb);
5438 }
5539
5640 void tBuffer_free (tBuffer* const sb)
@@ -61,15 +45,28 @@ void tBuffer_free (tBuffer* const sb) · 4 unmodified lines
6145 leaf_free(s);
6246 }
6347
64−void tBuffer_free_locate (tBuffer* const sb, mpool_t* pool)
48+void tBuffer_initToPool (tBuffer* const sb, uint32_t length, tMempool* const mp)
6549 {
50+ _tMempool* m = *mp;
51+ _tBuffer* s = *sb = (_tBuffer*) mpool_alloc(sizeof(_tBuffer), m->pool);
52+
53+ s->buff = (float*) mpool_alloc( sizeof(float) * length, m->pool);
54+
55+ s->bufferLength = length;
56+ s->recordedLength = 0;
57+ s->idx = 0;
58+ s->mode = RecordOneShot;
59+}
60+
61+void tBuffer_freeFromPool (tBuffer* const sb, tMempool* const mp)
62+{
63+ _tMempool* m = *mp;
6664 _tBuffer* s = *sb;
6765
68− mpool_free(s->buff, pool);
69− mpool_free(s, pool);
66+ mpool_free(s->buff, m->pool);
67+ mpool_free(s, m->pool);
7068 }
7169
72−
7370 void tBuffer_tick (tBuffer* const sb, float sample)
7471 {
7572 _tBuffer* s = *sb;

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