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
33 33
34 typedef _tEnvelopeFollower* tEnvelopeFollower;34 typedef _tEnvelopeFollower* tEnvelopeFollower;
35 35
36 void tEnvelopeFollower_init (tEnvelopeFollower* const, float attackThreshold, float decayCoeff);36 void tEnvelopeFollower_init (tEnvelopeFollower* const, float attackThreshold, float decayCoeff);
37 void tEnvelopeFollower_free (tEnvelopeFollower* const);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);
38 40
39 float tEnvelopeFollower_tick (tEnvelopeFollower* const, float x);41 float tEnvelopeFollower_tick (tEnvelopeFollower* const, float x);
40 int tEnvelopeFollower_decayCoeff (tEnvelopeFollower* const, float decayCoeff);42 int tEnvelopeFollower_decayCoeff (tEnvelopeFollower* const, float decayCoeff);
41 int tEnvelopeFollower_attackThresh (tEnvelopeFollower* const, float attackThresh);43 int tEnvelopeFollower_attackThresh (tEnvelopeFollower* const, float attackThresh);
42 44
43 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~45 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
44 46
@@ -51,11 +53,14 @@ extern "C" { · 6 unmodified lines
51 53
52 typedef _tPowerFollower* tPowerFollower;54 typedef _tPowerFollower* tPowerFollower;
53 55
54 void tPowerFollower_init (tPowerFollower* const, float factor);56 void tPowerFollower_init (tPowerFollower* const, float factor);
55 void tPowerFollower_free (tPowerFollower* const);57 void tPowerFollower_free (tPowerFollower* const);
56 float tPowerFollower_tick (tPowerFollower* const, float input);58 void tPowerFollower_initToPool (tPowerFollower* const, float factor, tMempool* const);
57 float tPowerFollower_sample (tPowerFollower* const);59 void tPowerFollower_freeFromPool (tPowerFollower* const, tMempool* const);
58 int tPowerFollower_setFactor (tPowerFollower* const, float factor);60
61 float tPowerFollower_tick (tPowerFollower* const, float input);
62 float tPowerFollower_sample (tPowerFollower* const);
63 int tPowerFollower_setFactor (tPowerFollower* const, float factor);
59 64
60 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~65 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
61 66
@@ -81,10 +86,13 @@ extern "C" { · 19 unmodified lines
81 86
82 typedef _tEnvPD* tEnvPD;87 typedef _tEnvPD* tEnvPD;
83 88
84 void tEnvPD_init (tEnvPD* const, int windowSize, int hopSize, int blockSize);89 void tEnvPD_init (tEnvPD* const, int windowSize, int hopSize, int blockSize);
85 void tEnvPD_free (tEnvPD* const);90 void tEnvPD_free (tEnvPD* const);
86 float tEnvPD_tick (tEnvPD* const);91 void tEnvPD_initToPool (tEnvPD* const, int windowSize, int hopSize, int blockSize, tMempool* const);
87 void tEnvPD_processBlock (tEnvPD* const, float* in);92 void tEnvPD_freeFromPool (tEnvPD* const, tMempool* const);
93
94 float tEnvPD_tick (tEnvPD* const);
95 void tEnvPD_processBlock (tEnvPD* const, float* in);
88 96
89 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~97 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
90 98
@@ -117,27 +125,28 @@ extern "C" { · 26 unmodified lines
117 125
118 typedef _tAttackDetection* tAttackDetection;126 typedef _tAttackDetection* tAttackDetection;
119 127
120 void tAttackDetection_init (tAttackDetection* const, int blocksize);128 void tAttackDetection_init (tAttackDetection* const, int blocksize, int atk, int rel);
121 void tAttackDetection_init_expanded (tAttackDetection* const, int blocksize, int atk, int rel);129 void tAttackDetection_free (tAttackDetection* const);
122 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);
123 132
124 // set expected input blocksize133 // set expected input blocksize
125 void tAttackDetection_setBlocksize (tAttackDetection* const, int size);134 void tAttackDetection_setBlocksize (tAttackDetection* const, int size);
126 135
127 // change atkDetector sample rate136 // change atkDetector sample rate
128 void tAttackDetection_setSamplerate (tAttackDetection* const, int inRate);137 void tAttackDetection_setSamplerate (tAttackDetection* const, int inRate);
129 138
130 // set attack time and coeff139 // set attack time and coeff
131 void tAttackDetection_setAtk (tAttackDetection* const, int inAtk);140 void tAttackDetection_setAttack (tAttackDetection* const, int inAtk);
132 141
133 // set release time and coeff142 // set release time and coeff
134 void tAttackDetection_setRel (tAttackDetection* const, int inRel);143 void tAttackDetection_setRelease (tAttackDetection* const, int inRel);
135 144
136 // set level above which values are identified as attacks145 // 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);
138 147
139 // find largest transient in input block, return index of attack148 // 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);
141 150
142 //==============================================================================151 //==============================================================================
143 152
@@ -168,8 +177,10 @@ extern "C" { · 24 unmodified lines
168 177
169 typedef _tSNAC* tSNAC;178 typedef _tSNAC* tSNAC;
170 179
171 void tSNAC_init (tSNAC* const, int overlaparg); // constructor180 void tSNAC_init (tSNAC* const, int overlaparg);
172 void tSNAC_free (tSNAC* const); // destructor181 void tSNAC_free (tSNAC* const);
182 void tSNAC_initToPool (tSNAC* const, int overlaparg, tMempool* const);
183 void tSNAC_freeFromPool (tSNAC* const, tMempool* const);
173 184
174 void tSNAC_ioSamples (tSNAC *s, float *in, float *out, int size);185 void tSNAC_ioSamples (tSNAC *s, float *in, float *out, int size);
175 void tSNAC_setOverlap (tSNAC *s, int lap);186 void tSNAC_setOverlap (tSNAC *s, int lap);
@@ -178,7 +189,7 @@ extern "C" { · 2 unmodified lines
178 189
179 /*To get freq, perform SAMPLE_RATE/snac_getperiod() */190 /*To get freq, perform SAMPLE_RATE/snac_getperiod() */
180 float tSNAC_getPeriod (tSNAC *s);191 float tSNAC_getPeriod (tSNAC *s);
181 float tSNAC_getfidelity (tSNAC *s);192 float tSNAC_getFidelity (tSNAC *s);
182 193
183#define DEFPITCHRATIO 2.0f194#define DEFPITCHRATIO 2.0f
184#define DEFTIMECONSTANT 100.0f195#define DEFTIMECONSTANT 100.0f
@@ -220,12 +231,14 @@ extern "C" { · 35 unmodified lines
220 231
221 typedef _tPeriodDetection* tPeriodDetection;232 typedef _tPeriodDetection* tPeriodDetection;
222 233
223 void tPeriodDetection_init (tPeriodDetection* const, float* in, float* out, int bufSize, int frameSize);234 void tPeriodDetection_init (tPeriodDetection* const, float* in, float* out, int bufSize, int frameSize);
224 void tPeriodDetection_free (tPeriodDetection* const);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);
225 238
226 float tPeriodDetection_findPeriod (tPeriodDetection* const, float sample);239 float tPeriodDetection_findPeriod (tPeriodDetection* const, float sample);
227 void tPeriodDetection_setHopSize (tPeriodDetection* p, int hs);240 void tPeriodDetection_setHopSize (tPeriodDetection* p, int hs);
228 void tPeriodDetection_setWindowSize (tPeriodDetection* p, int ws);241 void tPeriodDetection_setWindowSize (tPeriodDetection* p, int ws);
229 242
230 //==============================================================================243 //==============================================================================
231 244
LEAF/Inc/leaf-delay.h+97−45
@@ -16,6 +16,7 @@ extern "C" { · 15 unmodified lines
16 //==============================================================================16 //==============================================================================
17 17
18#include "leaf-math.h"18#include "leaf-math.h"
19#include "leaf-mempool.h"
19 20
20 //==============================================================================21 //==============================================================================
21 22
@@ -35,17 +36,19 @@ extern "C" { · 13 unmodified lines
35 36
36 typedef _tDelay* tDelay;37 typedef _tDelay* tDelay;
37 38
38 void tDelay_init (tDelay* const, uint32_t delay, uint32_t maxDelay);39 void tDelay_init (tDelay* const, uint32_t delay, uint32_t maxDelay);
39 void tDelay_free (tDelay* const);40 void tDelay_free (tDelay* const);
40 41 void tDelay_initToPool (tDelay* const, uint32_t delay, uint32_t maxDelay, tMempool* const);
41 int tDelay_setDelay (tDelay* const, uint32_t delay);42 void tDelay_freeFromPool (tDelay* const, tMempool* const);
42 uint32_t tDelay_getDelay (tDelay* const);43
43 void tDelay_tapIn (tDelay* const, float in, uint32_t tapDelay);44 int tDelay_setDelay (tDelay* const, uint32_t delay);
44 float tDelay_tapOut (tDelay* const, uint32_t tapDelay);45 uint32_t tDelay_getDelay (tDelay* const);
45 float tDelay_addTo (tDelay* const, float value, uint32_t tapDelay);46 void tDelay_tapIn (tDelay* const, float in, uint32_t tapDelay);
46 float tDelay_tick (tDelay* const, float sample);47 float tDelay_tapOut (tDelay* const, uint32_t tapDelay);
47 float tDelay_getLastOut (tDelay* const);48 float tDelay_addTo (tDelay* const, float value, uint32_t tapDelay);
48 float tDelay_getLastIn (tDelay* const);49 float tDelay_tick (tDelay* const, float sample);
50 float tDelay_getLastOut (tDelay* const);
51 float tDelay_getLastIn (tDelay* const);
49 52
50 //==============================================================================53 //==============================================================================
51 54
@@ -69,20 +72,65 @@ extern "C" { · 17 unmodified lines
69 72
70 typedef _tLinearDelay* tLinearDelay;73 typedef _tLinearDelay* tLinearDelay;
71 74
72 void tLinearDelay_init (tLinearDelay* const, float delay, uint32_t maxDelay);75 void tLinearDelay_init (tLinearDelay* const, float delay, uint32_t maxDelay);
73 void tLinearDelay_free (tLinearDelay* const);76 void tLinearDelay_free (tLinearDelay* const);
74 77 void tLinearDelay_initToPool (tLinearDelay* const, float delay, uint32_t maxDelay, tMempool* const);
75 int tLinearDelay_setDelay (tLinearDelay* const, float delay);78 void tLinearDelay_freeFromPool(tLinearDelay* const, tMempool* const);
76 float tLinearDelay_getDelay (tLinearDelay* const);79 void tLinearDelay_clear (tLinearDelay* const dl);
77 void tLinearDelay_tapIn (tLinearDelay* const, float in, uint32_t tapDelay);80 int tLinearDelay_setDelay (tLinearDelay* const, float delay);
78 float tLinearDelay_tapOut (tLinearDelay* const, float tapDelay);81 float tLinearDelay_getDelay (tLinearDelay* const);
79 float tLinearDelay_addTo (tLinearDelay* const, float value, uint32_t tapDelay);82 void tLinearDelay_tapIn (tLinearDelay* const, float in, uint32_t tapDelay);
80 float tLinearDelay_tick (tLinearDelay* const, float sample);83 float tLinearDelay_tapOut (tLinearDelay* const, uint32_t tapDelay);
81 void tLinearDelay_tickIn (tLinearDelay* const, float input);84 float tLinearDelay_addTo (tLinearDelay* const, float value, uint32_t tapDelay);
82 float tLinearDelay_tickOut (tLinearDelay* const);85 float tLinearDelay_tick (tLinearDelay* const, float sample);
83 float tLinearDelay_getLastOut (tLinearDelay* const);86 void tLinearDelay_tickIn (tLinearDelay* const, float input);
84 float tLinearDelay_getLastIn (tLinearDelay* const);87 float tLinearDelay_tickOut (tLinearDelay* const);
88 float tLinearDelay_getLastOut (tLinearDelay* const);
89 float tLinearDelay_getLastIn (tLinearDelay* const);
85 90
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
86 //==============================================================================134 //==============================================================================
87 135
88 /* Allpass-interpolating delay, reimplemented from STK (Cook and Scavone). */136 /* Allpass-interpolating delay, reimplemented from STK (Cook and Scavone). */
@@ -107,17 +155,19 @@ extern "C" { · 18 unmodified lines
107 155
108 typedef _tAllpassDelay* tAllpassDelay;156 typedef _tAllpassDelay* tAllpassDelay;
109 157
110 void tAllpassDelay_init (tAllpassDelay* const, float delay, uint32_t maxDelay);158 void tAllpassDelay_init (tAllpassDelay* const, float delay, uint32_t maxDelay);
111 void tAllpassDelay_free (tAllpassDelay* const);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);
112 162
113 int tAllpassDelay_setDelay (tAllpassDelay* const, float delay);163 int tAllpassDelay_setDelay (tAllpassDelay* const, float delay);
114 float tAllpassDelay_getDelay (tAllpassDelay* const);164 float tAllpassDelay_getDelay (tAllpassDelay* const);
115 void tAllpassDelay_tapIn (tAllpassDelay* const, float in, uint32_t tapDelay);165 void tAllpassDelay_tapIn (tAllpassDelay* const, float in, uint32_t tapDelay);
116 float tAllpassDelay_tapOut (tAllpassDelay* const, uint32_t tapDelay);166 float tAllpassDelay_tapOut (tAllpassDelay* const, uint32_t tapDelay);
117 float tAllpassDelay_addTo (tAllpassDelay* const, float value, uint32_t tapDelay);167 float tAllpassDelay_addTo (tAllpassDelay* const, float value, uint32_t tapDelay);
118 float tAllpassDelay_tick (tAllpassDelay* const, float sample);168 float tAllpassDelay_tick (tAllpassDelay* const, float sample);
119 float tAllpassDelay_getLastOut (tAllpassDelay* const);169 float tAllpassDelay_getLastOut (tAllpassDelay* const);
120 float tAllpassDelay_getLastIn (tAllpassDelay* const);170 float tAllpassDelay_getLastIn (tAllpassDelay* const);
121 171
122 //==============================================================================172 //==============================================================================
123 173
@@ -141,18 +191,20 @@ extern "C" { · 17 unmodified lines
141 191
142 typedef _tTapeDelay* tTapeDelay;192 typedef _tTapeDelay* tTapeDelay;
143 193
144 void tTapeDelay_init (tTapeDelay* const, float delay, uint32_t maxDelay);194 void tTapeDelay_init (tTapeDelay* const, float delay, uint32_t maxDelay);
145 void tTapeDelay_free (tTapeDelay* const);195 void tTapeDelay_free (tTapeDelay* const);
146 196 void tTapeDelay_initToPool (tTapeDelay* const, float delay, uint32_t maxDelay, tMempool* const);
147 void tTapeDelay_setDelay (tTapeDelay* const, float delay);197 void tTapeDelay_freeFromPool(tTapeDelay* const, tMempool* const);
148 float tTapeDelay_getDelay (tTapeDelay* const);198
149 void tTapeDelay_tapIn (tTapeDelay* const, float in, uint32_t tapDelay);199 void tTapeDelay_setDelay (tTapeDelay* const, float delay);
150 float tTapeDelay_tapOut (tTapeDelay* const d, float tapDelay);200 float tTapeDelay_getDelay (tTapeDelay* const);
151 float tTapeDelay_addTo (tTapeDelay* const, float value, uint32_t tapDelay);201 void tTapeDelay_tapIn (tTapeDelay* const, float in, uint32_t tapDelay);
152 float tTapeDelay_tick (tTapeDelay* const, float sample);202 float tTapeDelay_tapOut (tTapeDelay* const d, float tapDelay);
153 void tTapeDelay_incrementInPoint(tTapeDelay* const dl);203 float tTapeDelay_addTo (tTapeDelay* const, float value, uint32_t tapDelay);
154 float tTapeDelay_getLastOut (tTapeDelay* const);204 float tTapeDelay_tick (tTapeDelay* const, float sample);
155 float tTapeDelay_getLastIn (tTapeDelay* const);205 void tTapeDelay_incrementInPoint(tTapeDelay* const dl);
206 float tTapeDelay_getLastOut (tTapeDelay* const);
207 float tTapeDelay_getLastIn (tTapeDelay* const);
156 208
157 //==============================================================================209 //==============================================================================
158 210
LEAF/Inc/leaf-distortion.h+49−44
@@ -21,6 +21,51 @@ extern "C" { · 20 unmodified lines
21 21
22 //==============================================================================22 //==============================================================================
23 23
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
24 /* tLockhartWavefolder */69 /* tLockhartWavefolder */
25 70
26 typedef struct _tLockhartWavefolder71 typedef struct _tLockhartWavefolder
@@ -49,29 +94,10 @@ extern "C" { · 22 unmodified lines
49 94
50 void tLockhartWavefolder_init (tLockhartWavefolder* const);95 void tLockhartWavefolder_init (tLockhartWavefolder* const);
51 void tLockhartWavefolder_free (tLockhartWavefolder* const);96 void tLockhartWavefolder_free (tLockhartWavefolder* const);
97 void tLockhartWavefolder_initToPool (tLockhartWavefolder* const, tMempool* const);
98 void tLockhartWavefolder_freeFromPool (tLockhartWavefolder* const, tMempool* const);
52 99
53 float tLockhartWavefolder_tick (tLockhartWavefolder* const, float samp);100 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);
75 101
76 //==============================================================================102 //==============================================================================
77 103
@@ -92,6 +118,8 @@ extern "C" { · 14 unmodified lines
92 118
93 void tCrusher_init (tCrusher* const);119 void tCrusher_init (tCrusher* const);
94 void tCrusher_free (tCrusher* const);120 void tCrusher_free (tCrusher* const);
121 void tCrusher_initToPool (tCrusher* const, tMempool* const);
122 void tCrusher_freeFromPool (tCrusher* const, tMempool* const);
95 123
96 float tCrusher_tick (tCrusher* const, float input);124 float tCrusher_tick (tCrusher* const, float input);
97 125
@@ -107,29 +135,6 @@ extern "C" { · 9 unmodified lines
107 // sampling ratio135 // sampling ratio
108 void tCrusher_setSamplingRatio (tCrusher* const, float ratio);136 void tCrusher_setSamplingRatio (tCrusher* const, float ratio);
109 137
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
133 //==============================================================================138 //==============================================================================
134 139
135#ifdef __cplusplus140#ifdef __cplusplus
LEAF/Inc/leaf-dynamics.h+17−11
@@ -18,6 +18,7 @@ extern "C" { · 17 unmodified lines
18 18
19#include "leaf-global.h"19#include "leaf-global.h"
20#include "leaf-math.h"20#include "leaf-math.h"
21#include "leaf-mempool.h"
21#include "leaf-analysis.h"22#include "leaf-analysis.h"
22 23
23 //==============================================================================24 //==============================================================================
@@ -38,9 +39,12 @@ extern "C" { · 14 unmodified lines
38 39
39 typedef _tCompressor* tCompressor;40 typedef _tCompressor* tCompressor;
40 41
41 void tCompressor_init (tCompressor* const);42 void tCompressor_init (tCompressor* const);
42 void tCompressor_free (tCompressor* const);43 void tCompressor_free (tCompressor* const);
43 float tCompressor_tick (tCompressor* const, float input);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);
44 48
45 ///49 ///
46 /* Feedback leveller */50 /* Feedback leveller */
@@ -61,15 +65,17 @@ extern "C" { · 14 unmodified lines
61 65
62 typedef _tFeedbackLeveler* tFeedbackLeveler;66 typedef _tFeedbackLeveler* tFeedbackLeveler;
63 67
64 void tFeedbackLeveler_init (tFeedbackLeveler* const, float targetLevel, float factor, float strength, int mode);68 void tFeedbackLeveler_init (tFeedbackLeveler* const, float targetLevel, float factor, float strength, int mode);
65 void tFeedbackLeveler_free (tFeedbackLeveler* const);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);
66 72
67 float tFeedbackLeveler_tick (tFeedbackLeveler* const, float input);73 float tFeedbackLeveler_tick (tFeedbackLeveler* const, float input);
68 float tFeedbackLeveler_sample (tFeedbackLeveler* const);74 float tFeedbackLeveler_sample (tFeedbackLeveler* const);
69 void tFeedbackLeveler_setTargetLevel (tFeedbackLeveler* const, float TargetLevel);75 void tFeedbackLeveler_setTargetLevel (tFeedbackLeveler* const, float TargetLevel);
70 void tFeedbackLeveler_setFactor (tFeedbackLeveler* const, float factor);76 void tFeedbackLeveler_setFactor (tFeedbackLeveler* const, float factor);
71 void tFeedbackLeveler_setMode (tFeedbackLeveler* const, int mode); // 0 for upwards limiting only, 1 for biderctional limiting77 void tFeedbackLeveler_setMode (tFeedbackLeveler* const, int mode); // 0 for upwards limiting only, 1 for biderctional limiting
72 void tFeedbackLeveler_setStrength (tFeedbackLeveler* const, float strength);78 void tFeedbackLeveler_setStrength (tFeedbackLeveler* const, float strength);
73 79
74 80
75 //==============================================================================81 //==============================================================================
LEAF/Inc/leaf-effects.h+72−53
@@ -14,9 +14,10 @@ extern "C" { · 13 unmodified lines
14#endif14#endif
15 15
16 //==============================================================================16 //==============================================================================
17#include "leaf-dynamics.h"
18#include "leaf-global.h"17#include "leaf-global.h"
19#include "leaf-math.h"18#include "leaf-math.h"
19#include "leaf-mempool.h"
20#include "leaf-dynamics.h"
20#include "leaf-analysis.h"21#include "leaf-analysis.h"
21 22
22 //==============================================================================23 //==============================================================================
@@ -45,14 +46,17 @@ extern "C" { · 22 unmodified lines
45 46
46 typedef _tTalkbox* tTalkbox;47 typedef _tTalkbox* tTalkbox;
47 48
48 void tTalkbox_init (tTalkbox* const, int bufsize);49 void tTalkbox_init (tTalkbox* const, int bufsize);
49 void tTalkbox_free (tTalkbox* const);50 void tTalkbox_free (tTalkbox* const);
50 float tTalkbox_tick (tTalkbox* const, float synth, float voice);51 void tTalkbox_initToPool (tTalkbox* const, int bufsize, tMempool* const);
51 void tTalkbox_update (tTalkbox* const);52 void tTalkbox_freeFromPool (tTalkbox* const, tMempool* const);
52 void tTalkbox_suspend (tTalkbox* const);53
53 void tTalkbox_lpcDurbin (float *r, int p, float *k, float *g);54 float tTalkbox_tick (tTalkbox* const, float synth, float voice);
54 void tTalkbox_lpc (float *buf, float *car, int32_t n, int32_t o);55 void tTalkbox_update (tTalkbox* const);
55 void tTalkbox_setQuality (tTalkbox* const, float quality);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);
56 60
57 //==============================================================================61 //==============================================================================
58 62
@@ -77,11 +81,14 @@ extern "C" { · 18 unmodified lines
77 81
78 typedef _tVocoder* tVocoder;82 typedef _tVocoder* tVocoder;
79 83
80 void tVocoder_init (tVocoder* const);84 void tVocoder_init (tVocoder* const);
81 void tVocoder_free (tVocoder* const);85 void tVocoder_free (tVocoder* const);
82 float tVocoder_tick (tVocoder* const, float synth, float voice);86 void tVocoder_initToPool (tVocoder* const, tMempool* const);
83 void tVocoder_update (tVocoder* const);87 void tVocoder_freeFromPool (tVocoder* const, tMempool* const);
84 void tVocoder_suspend (tVocoder* const);88
89 float tVocoder_tick (tVocoder* const, float synth, float voice);
90 void tVocoder_update (tVocoder* const);
91 void tVocoder_suspend (tVocoder* const);
85 92
86 //==============================================================================93 //==============================================================================
87 94
@@ -117,6 +124,9 @@ extern "C" { · 29 unmodified lines
117 124
118 void tSOLAD_init (tSOLAD* const);125 void tSOLAD_init (tSOLAD* const);
119 void tSOLAD_free (tSOLAD* const);126 void tSOLAD_free (tSOLAD* const);
127 void tSOLAD_initToPool (tSOLAD* const, tMempool* const);
128 void tSOLAD_freeFromPool (tSOLAD* const, tMempool* const);
129
120 // send one block of input samples, receive one block of output samples130 // send one block of input samples, receive one block of output samples
121 void tSOLAD_ioSamples (tSOLAD *w, float* in, float* out, int blocksize);131 void tSOLAD_ioSamples (tSOLAD *w, float* in, float* out, int blocksize);
122 // set periodicity analysis data132 // set periodicity analysis data
@@ -151,12 +161,15 @@ extern "C" { · 28 unmodified lines
151 161
152 typedef _tPitchShift* tPitchShift;162 typedef _tPitchShift* tPitchShift;
153 163
154 void tPitchShift_init (tPitchShift* const, tPeriodDetection* const, float* out, int bufSize);164 void tPitchShift_init (tPitchShift* const, tPeriodDetection* const, float* out, int bufSize);
155 void tPitchShift_free (tPitchShift* const);165 void tPitchShift_free (tPitchShift* const);
156 float tPitchShift_shift (tPitchShift* const);166 void tPitchShift_initToPool (tPitchShift* const, tPeriodDetection* const, float* out, int bufSize, tMempool* const);
157 float tPitchShift_shiftToFunc (tPitchShift* const, float (*fun)(float));167 void tPitchShift_freeFromPool (tPitchShift* const, tMempool* const);
158 float tPitchShift_shiftToFreq (tPitchShift* const, float freq);168
159 void tPitchShift_setPitchFactor (tPitchShift* const, float pf);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);
160 173
161 // Retune174 // Retune
162 typedef struct _tRetune175 typedef struct _tRetune
@@ -185,18 +198,20 @@ extern "C" { · 22 unmodified lines
185 198
186 typedef _tRetune* tRetune;199 typedef _tRetune* tRetune;
187 200
188 void tRetune_init (tRetune* const, int numVoices, int bufSize, int frameSize);201 void tRetune_init (tRetune* const, int numVoices, int bufSize, int frameSize);
189 void tRetune_free (tRetune* const);202 void tRetune_free (tRetune* const);
190 203 void tRetune_initToPool (tRetune* const, int numVoices, int bufSize, int frameSize, tMempool* const);
191 float* tRetune_tick (tRetune* const, float sample);204 void tRetune_freeFromPool (tRetune* const, tMempool* const);
192 void tRetune_setNumVoices (tRetune* const, int numVoices);205
193 void tRetune_setPitchFactors (tRetune* const, float pf);206 float* tRetune_tick (tRetune* const, float sample);
194 void tRetune_setPitchFactor (tRetune* const, float pf, int voice);207 void tRetune_setNumVoices (tRetune* const, int numVoices);
195 void tRetune_setTimeConstant (tRetune* const, float tc);208 void tRetune_setPitchFactors (tRetune* const, float pf);
196 void tRetune_setHopSize (tRetune* const, int hs);209 void tRetune_setPitchFactor (tRetune* const, float pf, int voice);
197 void tRetune_setWindowSize (tRetune* const, int ws);210 void tRetune_setTimeConstant (tRetune* const, float tc);
198 float tRetune_getInputPeriod (tRetune* const);211 void tRetune_setHopSize (tRetune* const, int hs);
199 float tRetune_getInputFreq (tRetune* const);212 void tRetune_setWindowSize (tRetune* const, int ws);
213 float tRetune_getInputPeriod (tRetune* const);
214 float tRetune_getInputFreq (tRetune* const);
200 215
201 // Autotune216 // Autotune
202 typedef struct _tAutotune217 typedef struct _tAutotune
@@ -225,18 +240,20 @@ extern "C" { · 22 unmodified lines
225 240
226 typedef _tAutotune* tAutotune;241 typedef _tAutotune* tAutotune;
227 242
228 void tAutotune_init (tAutotune* const, int numVoices, int bufSize, int frameSize);243 void tAutotune_init (tAutotune* const, int numVoices, int bufSize, int frameSize);
229 void tAutotune_free (tAutotune* const);244 void tAutotune_free (tAutotune* const);
230 245 void tAutotune_initToPool (tAutotune* const, int numVoices, int bufSize, int frameSize, tMempool* const);
231 float* tAutotune_tick (tAutotune* const, float sample);246 void tAutotune_freeFromPool (tAutotune* const, tMempool* const);
232 void tAutotune_setNumVoices (tAutotune* const, int numVoices);247
233 void tAutotune_setFreqs (tAutotune* const, float f);248 float* tAutotune_tick (tAutotune* const, float sample);
234 void tAutotune_setFreq (tAutotune* const, float f, int voice);249 void tAutotune_setNumVoices (tAutotune* const, int numVoices);
235 void tAutotune_setTimeConstant (tAutotune* const, float tc);250 void tAutotune_setFreqs (tAutotune* const, float f);
236 void tAutotune_setHopSize (tAutotune* const, int hs);251 void tAutotune_setFreq (tAutotune* const, float f, int voice);
237 void tAutotune_setWindowSize (tAutotune* const, int ws);252 void tAutotune_setTimeConstant (tAutotune* const, float tc);
238 float tAutotune_getInputPeriod (tAutotune* const);253 void tAutotune_setHopSize (tAutotune* const, int hs);
239 float tAutotune_getInputFreq (tAutotune* const);254 void tAutotune_setWindowSize (tAutotune* const, int ws);
255 float tAutotune_getInputPeriod (tAutotune* const);
256 float tAutotune_getInputFreq (tAutotune* const);
240 257
241 //==============================================================================258 //==============================================================================
242 259
@@ -273,15 +290,17 @@ extern "C" { · 30 unmodified lines
273 290
274 typedef _tFormantShifter* tFormantShifter;291 typedef _tFormantShifter* tFormantShifter;
275 292
276 void tFormantShifter_init (tFormantShifter* const, int bufsize, int order);293 void tFormantShifter_init (tFormantShifter* const, int bufsize, int order);
277 void tFormantShifter_free (tFormantShifter* const);294 void tFormantShifter_free (tFormantShifter* const);
278 295 void tFormantShifter_initToPool (tFormantShifter* const, int bufsize, int order, tMempool* const);
279 float tFormantShifter_tick (tFormantShifter* const, float input);296 void tFormantShifter_freeFromPool (tFormantShifter* const, tMempool* const);
280 float tFormantShifter_remove (tFormantShifter* const, float input);297
281 float tFormantShifter_add (tFormantShifter* const, float input);298 float tFormantShifter_tick (tFormantShifter* const, float input);
282 void tFormantShifter_ioSamples (tFormantShifter* const, float* in, float* out, int size, float fwarp);299 float tFormantShifter_remove (tFormantShifter* const, float input);
283 void tFormantShifter_setShiftFactor (tFormantShifter* const, float shiftFactor);300 float tFormantShifter_add (tFormantShifter* const, float input);
284 void tFormantShifter_setIntensity (tFormantShifter* const, float intensity);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);
285 304
286 //==============================================================================305 //==============================================================================
287 306
LEAF/Inc/leaf-electrical.h+16−12
@@ -16,6 +16,7 @@ extern "C" { · 15 unmodified lines
16 16
17#include "leaf-global.h"17#include "leaf-global.h"
18#include "leaf-math.h"18#include "leaf-math.h"
19#include "leaf-mempool.h"
19 20
20 //==============================================================================21 //==============================================================================
21 22
@@ -64,21 +65,24 @@ extern "C" { · 42 unmodified lines
64 };65 };
65 66
66 //WDF Linear Components67 //WDF Linear Components
67 void tWDF_init(tWDF* const r, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR);68 void tWDF_init (tWDF* const, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR);
68 void tWDF_free(tWDF* const r);69 void tWDF_free (tWDF* const);
69 float tWDF_tick(tWDF* const r, float sample, tWDF* const outputPoint, uint8_t paramsChanged);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);
70 72
71 void tWDF_setValue(tWDF* const r, float value);73 float tWDF_tick (tWDF* const, float sample, tWDF* const outputPoint, uint8_t paramsChanged);
72 void tWDF_setSampleRate(tWDF* const r, float sample_rate);
73 uint8_t tWDF_isLeaf(tWDF* const r);
74 74
75 float tWDF_getPortResistance(tWDF* const r);75 void tWDF_setValue (tWDF* const, float value);
76 float tWDF_getReflectedWaveUp(tWDF* const r, float input); //for tree, only uses input for resistive source76 void tWDF_setSampleRate (tWDF* const, float sample_rate);
77 float tWDF_getReflectedWaveDown(tWDF* const r, float input, float incident_wave); //for roots77 uint8_t tWDF_isLeaf (tWDF* const);
78 void tWDF_setIncidentWave(tWDF* const r, float incident_wave, float input);
79 78
80 float tWDF_getVoltage(tWDF* const r);79 float tWDF_getPortResistance (tWDF* const);
81 float tWDF_getCurrent(tWDF* const r);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);
82 86
83 87
84 //==============================================================================88 //==============================================================================
LEAF/Inc/leaf-envelopes.h+43−34
@@ -18,6 +18,7 @@ extern "C" { · 17 unmodified lines
18 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~18 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
19 19
20#include "leaf-math.h"20#include "leaf-math.h"
21#include "leaf-mempool.h"
21#include "leaf-filters.h"22#include "leaf-filters.h"
22#include "leaf-delay.h"23#include "leaf-delay.h"
23 24
@@ -26,8 +27,8 @@ extern "C" { · 2 unmodified lines
26 /* Attack-Decay envelope */27 /* Attack-Decay envelope */
27 typedef struct _tEnvelope {28 typedef struct _tEnvelope {
28 29
29 const float *exp_buff;30 const float *exp_buff;
30 const float *inc_buff;31 const float *inc_buff;
31 uint32_t buff_size;32 uint32_t buff_size;
32 33
33 float next;34 float next;
@@ -46,22 +47,24 @@ extern "C" { · 12 unmodified lines
46 47
47 typedef _tEnvelope* tEnvelope;48 typedef _tEnvelope* tEnvelope;
48 49
49 void tEnvelope_init (tEnvelope* const, float attack, float decay, oBool loop);50 void tEnvelope_init (tEnvelope* const, float attack, float decay, oBool loop);
50 void tEnvelope_free (tEnvelope* const);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);
51 54
52 float tEnvelope_tick (tEnvelope* const);55 float tEnvelope_tick (tEnvelope* const);
53 void tEnvelope_setAttack (tEnvelope* const, float attack);56 void tEnvelope_setAttack (tEnvelope* const, float attack);
54 void tEnvelope_setDecay (tEnvelope* const, float decay);57 void tEnvelope_setDecay (tEnvelope* const, float decay);
55 void tEnvelope_loop (tEnvelope* const, oBool loop);58 void tEnvelope_loop (tEnvelope* const, oBool loop);
56 void tEnvelope_on (tEnvelope* const, float velocity);59 void tEnvelope_on (tEnvelope* const, float velocity);
57 60
58 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~61 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
59 62
60 /* ADSR */63 /* ADSR */
61 typedef struct _tADSR64 typedef struct _tADSR
62 {65 {
63 const float *exp_buff;66 const float *exp_buff;
64 const float *inc_buff;67 const float *inc_buff;
65 uint32_t buff_size;68 uint32_t buff_size;
66 69
67 float next;70 float next;
@@ -78,16 +81,18 @@ extern "C" { · 10 unmodified lines
78 81
79 typedef _tADSR* tADSR;82 typedef _tADSR* tADSR;
80 83
81 void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release);84 void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release);
82 void tADSR_free (tADSR* const);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);
83 88
84 float tADSR_tick (tADSR* const);89 float tADSR_tick (tADSR* const);
85 void tADSR_setAttack (tADSR* const, float attack);90 void tADSR_setAttack (tADSR* const, float attack);
86 void tADSR_setDecay (tADSR* const, float decay);91 void tADSR_setDecay (tADSR* const, float decay);
87 void tADSR_setSustain(tADSR* const, float sustain);92 void tADSR_setSustain (tADSR* const, float sustain);
88 void tADSR_setRelease(tADSR* const, float release);93 void tADSR_setRelease (tADSR* const, float release);
89 void tADSR_on (tADSR* const, float velocity);94 void tADSR_on (tADSR* const, float velocity);
90 void tADSR_off (tADSR* const);95 void tADSR_off (tADSR* const);
91 96
92 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~97 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
93 98
@@ -106,14 +111,16 @@ extern "C" { · 12 unmodified lines
106 111
107 typedef _tRamp* tRamp;112 typedef _tRamp* tRamp;
108 113
109 void tRamp_init (tRamp* const, float time, int samplesPerTick);114 void tRamp_init (tRamp* const, float time, int samplesPerTick);
110 void tRamp_free (tRamp* const);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);
111 118
112 float tRamp_tick (tRamp* const);119 float tRamp_tick (tRamp* const);
113 float tRamp_sample (tRamp* const);120 float tRamp_sample (tRamp* const);
114 void tRamp_setTime (tRamp* const, float time);121 void tRamp_setTime (tRamp* const, float time);
115 void tRamp_setDest (tRamp* const, float dest);122 void tRamp_setDest (tRamp* const, float dest);
116 void tRamp_setVal (tRamp* const, float val);123 void tRamp_setVal (tRamp* const, float val);
117 124
118 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~125 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
119 126
@@ -126,14 +133,16 @@ extern "C" { · 6 unmodified lines
126 133
127 typedef _tExpSmooth* tExpSmooth;134 typedef _tExpSmooth* tExpSmooth;
128 135
129 void tExpSmooth_init (tExpSmooth* const, float val, float factor);136 void tExpSmooth_init (tExpSmooth* const, float val, float factor);
130 void tExpSmooth_free (tExpSmooth* const);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);
131 140
132 float tExpSmooth_tick (tExpSmooth* const);141 float tExpSmooth_tick (tExpSmooth* const);
133 float tExpSmooth_sample (tExpSmooth* const);142 float tExpSmooth_sample (tExpSmooth* const);
134 void tExpSmooth_setFactor (tExpSmooth* const, float factor);143 void tExpSmooth_setFactor (tExpSmooth* const, float factor);
135 void tExpSmooth_setDest (tExpSmooth* const, float dest);144 void tExpSmooth_setDest (tExpSmooth* const, float dest);
136 void tExpSmooth_setVal (tExpSmooth* const, float val);145 void tExpSmooth_setVal (tExpSmooth* const, float val);
137 146
138#ifdef __cplusplus147#ifdef __cplusplus
139}148}
LEAF/Inc/leaf-filters.h+115−90
@@ -16,6 +16,7 @@ extern "C" { · 15 unmodified lines
16 //==============================================================================16 //==============================================================================
17 17
18#include "leaf-math.h"18#include "leaf-math.h"
19#include "leaf-mempool.h"
19#include "leaf-delay.h"20#include "leaf-delay.h"
20#include "leaf-tables.h"21#include "leaf-tables.h"
21 22
@@ -34,12 +35,14 @@ extern "C" { · 12 unmodified lines
34 35
35 typedef _tAllpass* tAllpass;36 typedef _tAllpass* tAllpass;
36 37
37 void tAllpass_init (tAllpass* const, float initDelay, uint32_t maxDelay);38 void tAllpass_init (tAllpass* const, float initDelay, uint32_t maxDelay);
38 void tAllpass_free (tAllpass* const);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);
39 42
40 float tAllpass_tick (tAllpass* const, float input);43 float tAllpass_tick (tAllpass* const, float input);
41 void tAllpass_setGain (tAllpass* const, float gain);44 void tAllpass_setGain (tAllpass* const, float gain);
42 void tAllpass_setDelay (tAllpass* const f, float delay);45 void tAllpass_setDelay (tAllpass* const, float delay);
43 46
44 47
45 //==============================================================================48 //==============================================================================
@@ -57,16 +60,18 @@ extern "C" { · 11 unmodified lines
57 60
58 typedef _tOnePole* tOnePole;61 typedef _tOnePole* tOnePole;
59 62
60 void tOnePole_init (tOnePole* const, float thePole);63 void tOnePole_init (tOnePole* const, float thePole);
61 void tOnePole_free (tOnePole* const);64 void tOnePole_free (tOnePole* const);
65 void tOnePole_initToPool (tOnePole* const, float thePole, tMempool* const);
66 void tOnePole_freeFromPool (tOnePole* const, tMempool* const);
62 67
63 float tOnePole_tick (tOnePole* const, float input);68 float tOnePole_tick (tOnePole* const, float input);
64 void tOnePole_setB0 (tOnePole* const, float b0);69 void tOnePole_setB0 (tOnePole* const, float b0);
65 void tOnePole_setA1 (tOnePole* const, float a1);70 void tOnePole_setA1 (tOnePole* const, float a1);
66 void tOnePole_setPole (tOnePole* const, float thePole);71 void tOnePole_setPole (tOnePole* const, float thePole);
67 void tOnePole_setFreq (tOnePole* const, float freq);72 void tOnePole_setFreq (tOnePole* const, float freq);
68 void tOnePole_setCoefficients(tOnePole* const, float b0, float a1);73 void tOnePole_setCoefficients(tOnePole* const, float b0, float a1);
69 void tOnePole_setGain (tOnePole* const, float gain);74 void tOnePole_setGain (tOnePole* const, float gain);
70 75
71 //==============================================================================76 //==============================================================================
72 77
@@ -86,16 +91,18 @@ extern "C" { · 13 unmodified lines
86 91
87 typedef _tTwoPole* tTwoPole;92 typedef _tTwoPole* tTwoPole;
88 93
89 void tTwoPole_init (tTwoPole* const);94 void tTwoPole_init (tTwoPole* const);
90 void tTwoPole_free (tTwoPole* const);95 void tTwoPole_free (tTwoPole* const);
96 void tTwoPole_initToPool (tTwoPole* const, tMempool* const);
97 void tTwoPole_freeFromPool (tTwoPole* const, tMempool* const);
91 98
92 float tTwoPole_tick (tTwoPole* const, float input);99 float tTwoPole_tick (tTwoPole* const, float input);
93 void tTwoPole_setB0 (tTwoPole* const, float b0);100 void tTwoPole_setB0 (tTwoPole* const, float b0);
94 void tTwoPole_setA1 (tTwoPole* const, float a1);101 void tTwoPole_setA1 (tTwoPole* const, float a1);
95 void tTwoPole_setA2 (tTwoPole* const, float a2);102 void tTwoPole_setA2 (tTwoPole* const, float a2);
96 void tTwoPole_setResonance (tTwoPole* const, float freq, float radius, oBool normalize);103 void tTwoPole_setResonance (tTwoPole* const, float freq, float radius, oBool normalize);
97 void tTwoPole_setCoefficients(tTwoPole* const, float b0, float a1, float a2);104 void tTwoPole_setCoefficients(tTwoPole* const, float b0, float a1, float a2);
98 void tTwoPole_setGain (tTwoPole* const, float gain);105 void tTwoPole_setGain (tTwoPole* const, float gain);
99 106
100 //==============================================================================107 //==============================================================================
101 108
@@ -110,15 +117,18 @@ extern "C" { · 8 unmodified lines
110 117
111 typedef _tOneZero* tOneZero;118 typedef _tOneZero* tOneZero;
112 119
113 void tOneZero_init (tOneZero* const, float theZero);120 void tOneZero_init (tOneZero* const, float theZero);
114 void tOneZero_free (tOneZero* const);121 void tOneZero_free (tOneZero* const);
115 float tOneZero_tick (tOneZero* const, float input);122 void tOneZero_initToPool (tOneZero* const, float theZero, tMempool* const);
116 void tOneZero_setB0 (tOneZero* const, float b0);123 void tOneZero_freeFromPool (tOneZero* const, tMempool* const);
117 void tOneZero_setB1 (tOneZero* const, float b1);124
118 void tOneZero_setZero (tOneZero* const, float theZero);125 float tOneZero_tick (tOneZero* const, float input);
119 void tOneZero_setCoefficients(tOneZero* const, float b0, float b1);126 void tOneZero_setB0 (tOneZero* const, float b0);
120 void tOneZero_setGain (tOneZero* const, float gain);127 void tOneZero_setB1 (tOneZero* const, float b1);
121 float tOneZero_getPhaseDelay(tOneZero *f, float frequency );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 );
122 132
123 //==============================================================================133 //==============================================================================
124 134
@@ -136,16 +146,18 @@ extern "C" { · 11 unmodified lines
136 146
137 typedef _tTwoZero* tTwoZero;147 typedef _tTwoZero* tTwoZero;
138 148
139 void tTwoZero_init (tTwoZero* const);149 void tTwoZero_init (tTwoZero* const);
140 void tTwoZero_free (tTwoZero* const);150 void tTwoZero_free (tTwoZero* const);
151 void tTwoZero_initToPool (tTwoZero* const, tMempool* const);
152 void tTwoZero_freeFromPool (tTwoZero* const, tMempool* const);
141 153
142 float tTwoZero_tick (tTwoZero* const, float input);154 float tTwoZero_tick (tTwoZero* const, float input);
143 void tTwoZero_setB0 (tTwoZero* const, float b0);155 void tTwoZero_setB0 (tTwoZero* const, float b0);
144 void tTwoZero_setB1 (tTwoZero* const, float b1);156 void tTwoZero_setB1 (tTwoZero* const, float b1);
145 void tTwoZero_setB2 (tTwoZero* const, float b2);157 void tTwoZero_setB2 (tTwoZero* const, float b2);
146 void tTwoZero_setNotch (tTwoZero* const, float frequency, float radius);158 void tTwoZero_setNotch (tTwoZero* const, float frequency, float radius);
147 void tTwoZero_setCoefficients(tTwoZero* const, float b0, float b1, float b2);159 void tTwoZero_setCoefficients(tTwoZero* const, float b0, float b1, float b2);
148 void tTwoZero_setGain (tTwoZero* const, float gain);160 void tTwoZero_setGain (tTwoZero* const, float gain);
149 161
150 //==============================================================================162 //==============================================================================
151 163
@@ -162,17 +174,19 @@ extern "C" { · 10 unmodified lines
162 174
163 typedef _tPoleZero* tPoleZero;175 typedef _tPoleZero* tPoleZero;
164 176
165 void tPoleZero_init (tPoleZero* const);177 void tPoleZero_init (tPoleZero* const);
166 void tPoleZero_free (tPoleZero* const);178 void tPoleZero_free (tPoleZero* const);
179 void tPoleZero_initToPool (tPoleZero* const, tMempool* const);
180 void tPoleZero_freeFromPool (tPoleZero* const, tMempool* const);
167 181
168 float tPoleZero_tick (tPoleZero* const, float input);182 float tPoleZero_tick (tPoleZero* const, float input);
169 void tPoleZero_setB0 (tPoleZero* const, float b0);183 void tPoleZero_setB0 (tPoleZero* const, float b0);
170 void tPoleZero_setB1 (tPoleZero* const, float b1);184 void tPoleZero_setB1 (tPoleZero* const, float b1);
171 void tPoleZero_setA1 (tPoleZero* const, float a1);185 void tPoleZero_setA1 (tPoleZero* const, float a1);
172 void tPoleZero_setCoefficients (tPoleZero* const, float b0, float b1, float a1);186 void tPoleZero_setCoefficients (tPoleZero* const, float b0, float b1, float a1);
173 void tPoleZero_setAllpass (tPoleZero* const, float coeff);187 void tPoleZero_setAllpass (tPoleZero* const, float coeff);
174 void tPoleZero_setBlockZero (tPoleZero* const, float thePole);188 void tPoleZero_setBlockZero (tPoleZero* const, float thePole);
175 void tPoleZero_setGain (tPoleZero* const, float gain);189 void tPoleZero_setGain (tPoleZero* const, float gain);
176 190
177 //==============================================================================191 //==============================================================================
178 192
@@ -192,19 +206,21 @@ extern "C" { · 13 unmodified lines
192 206
193 typedef _tBiQuad* tBiQuad;207 typedef _tBiQuad* tBiQuad;
194 208
195 void tBiQuad_init (tBiQuad* const);209 void tBiQuad_init (tBiQuad* const);
196 void tBiQuad_free (tBiQuad* const);210 void tBiQuad_free (tBiQuad* const);
197 211 void tBiQuad_initToPool (tBiQuad* const, tMempool* const);
198 float tBiQuad_tick (tBiQuad* const, float input);212 void tBiQuad_freeFromPool (tBiQuad* const, tMempool* const);
199 void tBiQuad_setB0 (tBiQuad* const, float b0);213
200 void tBiQuad_setB1 (tBiQuad* const, float b1);214 float tBiQuad_tick (tBiQuad* const, float input);
201 void tBiQuad_setB2 (tBiQuad* const, float b2);215 void tBiQuad_setB0 (tBiQuad* const, float b0);
202 void tBiQuad_setA1 (tBiQuad* const, float a1);216 void tBiQuad_setB1 (tBiQuad* const, float b1);
203 void tBiQuad_setA2 (tBiQuad* const, float a2);217 void tBiQuad_setB2 (tBiQuad* const, float b2);
204 void tBiQuad_setNotch (tBiQuad* const, float freq, float radius);218 void tBiQuad_setA1 (tBiQuad* const, float a1);
205 void tBiQuad_setResonance (tBiQuad* const, float freq, float radius, oBool normalize);219 void tBiQuad_setA2 (tBiQuad* const, float a2);
206 void tBiQuad_setCoefficients(tBiQuad* const, float b0, float b1, float b2, float a1, float a2);220 void tBiQuad_setNotch (tBiQuad* const, float freq, float radius);
207 void tBiQuad_setGain (tBiQuad* const, float gain);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);
208 224
209 //==============================================================================225 //==============================================================================
210 226
@@ -229,12 +245,14 @@ extern "C" { · 18 unmodified lines
229 245
230 typedef _tSVF* tSVF;246 typedef _tSVF* tSVF;
231 247
232 void tSVF_init (tSVF* const, SVFType type, float freq, float Q);248 void tSVF_init (tSVF* const, SVFType type, float freq, float Q);
233 void tSVF_free (tSVF* const);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);
234 252
235 float tSVF_tick (tSVF* const, float v0);253 float tSVF_tick (tSVF* const, float v0);
236 void tSVF_setFreq (tSVF* const, float freq);254 void tSVF_setFreq (tSVF* const, float freq);
237 void tSVF_setQ (tSVF* const, float Q);255 void tSVF_setQ (tSVF* const, float Q);
238 256
239 //==============================================================================257 //==============================================================================
240 258
@@ -250,12 +268,14 @@ extern "C" { · 9 unmodified lines
250 268
251 typedef _tEfficientSVF* tEfficientSVF;269 typedef _tEfficientSVF* tEfficientSVF;
252 270
253 void tEfficientSVF_init (tEfficientSVF* const, SVFType type, uint16_t controlFreq, float Q);271 void tEfficientSVF_init (tEfficientSVF* const, SVFType type, uint16_t input, float Q);
254 void tEfficientSVF_free (tEfficientSVF* const);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);
255 275
256 float tEfficientSVF_tick (tEfficientSVF* const, float v0);276 float tEfficientSVF_tick (tEfficientSVF* const, float v0);
257 void tEfficientSVF_setFreq (tEfficientSVF* const, uint16_t controlFreq);277 void tEfficientSVF_setFreq (tEfficientSVF* const, uint16_t controlFreq);
258 void tEfficientSVF_setQ (tEfficientSVF* const, float Q);278 void tEfficientSVF_setQ (tEfficientSVF* const, float Q);
259 279
260 //==============================================================================280 //==============================================================================
261 281
@@ -269,12 +289,14 @@ extern "C" { · 7 unmodified lines
269 289
270 typedef _tHighpass* tHighpass;290 typedef _tHighpass* tHighpass;
271 291
272 void tHighpass_init (tHighpass* const, float freq);292 void tHighpass_init (tHighpass* const, float freq);
273 void tHighpass_free (tHighpass* const);293 void tHighpass_free (tHighpass* const);
294 void tHighpass_initToPool (tHighpass* const, float freq, tMempool* const);
295 void tHighpass_freeFromPool (tHighpass* const, tMempool* const);
274 296
275 float tHighpass_tick (tHighpass* const, float x);297 float tHighpass_tick (tHighpass* const, float x);
276 void tHighpass_setFreq (tHighpass* const, float freq);298 void tHighpass_setFreq (tHighpass* const, float freq);
277 float tHighpass_getFreq (tHighpass* const);299 float tHighpass_getFreq (tHighpass* const);
278 300
279 //==============================================================================301 //==============================================================================
280 302
@@ -295,13 +317,15 @@ extern "C" { · 14 unmodified lines
295 317
296 typedef _tButterworth* tButterworth;318 typedef _tButterworth* tButterworth;
297 319
298 void tButterworth_init (tButterworth* const, int N, float f1, float f2);320 void tButterworth_init (tButterworth* const, int N, float f1, float f2);
299 void tButterworth_free (tButterworth* const);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);
300 324
301 float tButterworth_tick (tButterworth* const, float input);325 float tButterworth_tick (tButterworth* const, float input);
302 void tButterworth_setF1 (tButterworth* const, float in);326 void tButterworth_setF1 (tButterworth* const, float in);
303 void tButterworth_setF2 (tButterworth* const, float in);327 void tButterworth_setF2 (tButterworth* const, float in);
304 void tButterworth_setFreqs (tButterworth* const, float f1, float f2);328 void tButterworth_setFreqs (tButterworth* const, float f1, float f2);
305 329
306 //==============================================================================330 //==============================================================================
307 331
@@ -310,16 +334,17 @@ extern "C" { · 2 unmodified lines
310 float* past;334 float* past;
311 float* coeff;335 float* coeff;
312 int numTaps;336 int numTaps;
313
314 } _tFIR;337 } _tFIR;
315 338
316 typedef _tFIR* tFIR;339 typedef _tFIR* tFIR;
317 340
318 void tFIR_init (tFIR* const, float* coeffs, int numTaps);341 void tFIR_init (tFIR* const, float* coeffs, int numTaps);
319 void tFIR_free (tFIR* const);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);
320 345
321 float tFIR_tick (tFIR* const, float input);346 float tFIR_tick (tFIR* const, float input);
322 void tFIR_coeffs (tFIR* const, float in);347 void tFIR_coeffs (tFIR* const, float in);
323 348
324 //==============================================================================349 //==============================================================================
325 350
LEAF/Inc/leaf-global.h+20−19
@@ -1,12 +1,12 @@
1/*1/*
2 ==============================================================================2 ==============================================================================
3 3
4 leaf-global.h4 leaf-global.h
5 Created: 24 Oct 2019 2:24:38pm5 Created: 24 Oct 2019 2:24:38pm
6 Author: Matthew Wang6 Author: Matthew Wang
7 7
8 ==============================================================================8 ==============================================================================
9*/9 */
10 10
11#ifndef LEAF_GLOBAL_H_INCLUDED11#ifndef LEAF_GLOBAL_H_INCLUDED
12#define LEAF_GLOBAL_H_INCLUDED12#define LEAF_GLOBAL_H_INCLUDED
@@ -14,17 +14,17 @@ · 1 unmodified line
14#ifdef __cplusplus14#ifdef __cplusplus
15extern "C" {15extern "C" {
16#endif16#endif
17 17
18typedef struct _LEAF18 typedef struct _LEAF
19{19 {
20 float sampleRate;20 float sampleRate;
21 float invSampleRate;21 float invSampleRate;
22 int blockSize;22 int blockSize;
23 float twoPiTimesInvSampleRate;23 float twoPiTimesInvSampleRate;
24 float (*random)(void);24 float (*random)(void);
25} LEAF;25 } LEAF;
26 26
27extern LEAF leaf; // The global instance of LEAF.27 extern LEAF leaf; // The global instance of LEAF.
28 28
29 //==============================================================================29 //==============================================================================
30 30
@@ -35,3 +35,4 @@ extern LEAF leaf; // The global instance of LEAF. · 4 unmodified lines
35#endif // LEAF_GLOBAL_H_INCLUDED35#endif // LEAF_GLOBAL_H_INCLUDED
36 36
37//==============================================================================37//==============================================================================
38
LEAF/Inc/leaf-instruments.h+60−51
@@ -42,16 +42,19 @@ extern "C" { · 41 unmodified lines
42 42
43 typedef _t808Cowbell* t808Cowbell;43 typedef _t808Cowbell* t808Cowbell;
44 44
45 void t808Cowbell_init (t808Cowbell* const, int useStick);45 void t808Cowbell_init (t808Cowbell* const, int useStick);
46 void t808Cowbell_free (t808Cowbell* const);46 void t808Cowbell_free (t808Cowbell* const);
47 float t808Cowbell_tick (t808Cowbell* const);47 void t808Cowbell_initToPool (t808Cowbell* const, int useStick, tMempool* const);
48 void t808Cowbell_on (t808Cowbell* const, float vel);48 void t808Cowbell_freeFromPool (t808Cowbell* const, tMempool* const);
49 void t808Cowbell_setDecay (t808Cowbell* const, float decay);49
50 void t808Cowbell_setHighpassFreq (t808Cowbell* const, float freq);50 float t808Cowbell_tick (t808Cowbell* const);
51 void t808Cowbell_setBandpassFreq (t808Cowbell* const, float freq);51 void t808Cowbell_on (t808Cowbell* const, float vel);
52 void t808Cowbell_setFreq (t808Cowbell* const, float freq);52 void t808Cowbell_setDecay (t808Cowbell* const, float decay);
53 void t808Cowbell_setOscMix (t808Cowbell* const, float oscMix);53 void t808Cowbell_setHighpassFreq (t808Cowbell* const, float freq);
54 void t808Cowbell_setStick (t808Cowbell* const, int useStick);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);
55 58
56 //==============================================================================59 //==============================================================================
57 60
@@ -78,21 +81,23 @@ extern "C" { · 20 unmodified lines
78 81
79 typedef _t808Hihat* t808Hihat;82 typedef _t808Hihat* t808Hihat;
80 83
81 void t808Hihat_init (t808Hihat* const);84 void t808Hihat_init (t808Hihat* const);
82 void t808Hihat_free (t808Hihat* const);85 void t808Hihat_free (t808Hihat* const);
83 86 void t808Hihat_initToPool (t808Hihat* const, tMempool* const);
84 float t808Hihat_tick (t808Hihat* const);87 void t808Hihat_freeFromPool (t808Hihat* const, tMempool* const);
85 void t808Hihat_on (t808Hihat* const, float vel);88
86 void t808Hihat_setOscNoiseMix (t808Hihat* const, float oscNoiseMix);89 float t808Hihat_tick (t808Hihat* const);
87 void t808Hihat_setDecay (t808Hihat* const, float decay);90 void t808Hihat_on (t808Hihat* const, float vel);
88 void t808Hihat_setHighpassFreq (t808Hihat* const, float freq);91 void t808Hihat_setOscNoiseMix (t808Hihat* const, float oscNoiseMix);
89 void t808Hihat_setOscBandpassFreq (t808Hihat* const, float freq);92 void t808Hihat_setDecay (t808Hihat* const, float decay);
90 void t808Hihat_setOscBandpassQ (t808Hihat* const hihat, float Q);93 void t808Hihat_setHighpassFreq (t808Hihat* const, float freq);
91 void t808Hihat_setStickBandPassFreq (t808Hihat* const, float freq);94 void t808Hihat_setOscBandpassFreq (t808Hihat* const, float freq);
92 void t808Hihat_setStickBandPassQ (t808Hihat* const hihat, float Q);95 void t808Hihat_setOscBandpassQ (t808Hihat* const hihat, float Q);
93 void t808Hihat_setOscFreq (t808Hihat* const, float freq);96 void t808Hihat_setStickBandPassFreq (t808Hihat* const, float freq);
94 void t808Hihat_setStretch (t808Hihat* const hihat, float stretch);97 void t808Hihat_setStickBandPassQ (t808Hihat* const hihat, float Q);
95 void t808Hihat_setFM (t808Hihat* const hihat, float FM_amount);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);
96 101
97 //==============================================================================102 //==============================================================================
98 103
@@ -123,19 +128,21 @@ extern "C" { · 24 unmodified lines
123 128
124 typedef _t808Snare* t808Snare;129 typedef _t808Snare* t808Snare;
125 130
126 void t808Snare_init (t808Snare* const);131 void t808Snare_init (t808Snare* const);
127 void t808Snare_free (t808Snare* const);132 void t808Snare_free (t808Snare* const);
128 133 void t808Snare_initToPool (t808Snare* const, tMempool* const);
129 float t808Snare_tick (t808Snare* const);134 void t808Snare_freeFromPool (t808Snare* const, tMempool* const);
130 void t808Snare_on (t808Snare* const, float vel);135
131 void t808Snare_setTone1Freq (t808Snare* const, float freq);136 float t808Snare_tick (t808Snare* const);
132 void t808Snare_setTone2Freq (t808Snare* const, float freq);137 void t808Snare_on (t808Snare* const, float vel);
133 void t808Snare_setTone1Decay (t808Snare* const, float decay);138 void t808Snare_setTone1Freq (t808Snare* const, float freq);
134 void t808Snare_setTone2Decay (t808Snare* const, float decay);139 void t808Snare_setTone2Freq (t808Snare* const, float freq);
135 void t808Snare_setNoiseDecay (t808Snare* const, float decay);140 void t808Snare_setTone1Decay (t808Snare* const, float decay);
136 void t808Snare_setToneNoiseMix (t808Snare* const, float toneNoiseMix);141 void t808Snare_setTone2Decay (t808Snare* const, float decay);
137 void t808Snare_setNoiseFilterFreq (t808Snare* const, float noiseFilterFreq);142 void t808Snare_setNoiseDecay (t808Snare* const, float decay);
138 void t808Snare_setNoiseFilterQ (t808Snare* const, float noiseFilterQ);143 void t808Snare_setToneNoiseMix (t808Snare* const, float toneNoiseMix);
144 void t808Snare_setNoiseFilterFreq (t808Snare* const, float noiseFilterFreq);
145 void t808Snare_setNoiseFilterQ (t808Snare* const, float noiseFilterQ);
139 146
140 //==============================================================================147 //==============================================================================
141 148
@@ -164,19 +171,21 @@ extern "C" { · 22 unmodified lines
164 171
165 typedef _t808Kick* t808Kick;172 typedef _t808Kick* t808Kick;
166 173
167 void t808Kick_init (t808Kick* const);174 void t808Kick_init (t808Kick* const);
168 void t808Kick_free (t808Kick* const);175 void t808Kick_free (t808Kick* const);
169 176 void t808Kick_initToPool (t808Kick* const, tMempool* const);
170 float t808Kick_tick (t808Kick* const);177 void t808Kick_freeFromPool (t808Kick* const, tMempool* const);
171 void t808Kick_on (t808Kick* const, float vel);178
172 void t808Kick_setToneFreq (t808Kick* const, float freq);179 float t808Kick_tick (t808Kick* const);
173 void t808Kick_setToneDecay (t808Kick* const, float decay);180 void t808Kick_on (t808Kick* const, float vel);
174 void t808Kick_setNoiseDecay (t808Kick* const, float decay);181 void t808Kick_setToneFreq (t808Kick* const, float freq);
175 void t808Kick_setSighAmount (t808Kick* const, float sigh);182 void t808Kick_setToneDecay (t808Kick* const, float decay);
176 void t808Kick_setChirpAmount (t808Kick* const, float chirp);183 void t808Kick_setNoiseDecay (t808Kick* const, float decay);
177 void t808Kick_setToneNoiseMix (t808Kick* const, float toneNoiseMix);184 void t808Kick_setSighAmount (t808Kick* const, float sigh);
178 void t808Kick_setNoiseFilterFreq (t808Kick* const, float noiseFilterFreq);185 void t808Kick_setChirpAmount (t808Kick* const, float chirp);
179 void t808Kick_setNoiseFilterQ (t808Kick* const, float noiseFilterQ);186 void t808Kick_setToneNoiseMix (t808Kick* const, float toneNoiseMix);
187 void t808Kick_setNoiseFilterFreq (t808Kick* const, float noiseFilterFreq);
188 void t808Kick_setNoiseFilterQ (t808Kick* const, float noiseFilterQ);
180 189
181 //==============================================================================190 //==============================================================================
182 191
LEAF/Inc/leaf-mempool.h+96−79
@@ -1,38 +1,38 @@
1/*==============================================================================1/*==============================================================================
2 2
3 In short, mpool is distributed under so called "BSD license",3 In short, mpool is distributed under so called "BSD license",
4
5 Copyright (c) 2009-2010 Tatsuhiko Kubo <cubicdaiya@gmail.com>
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
10
11 * Redistributions of source code must retain the above copyright notice,
12 this list of conditions and the following disclaimer.
13
14 * Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation
16 and/or other materials provided with the distribution.
17
18 * Neither the name of the authors nor the names of its contributors
19 may be used to endorse or promote products derived from this software
20 without specific prior written permission.
21
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
28 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 4
34 written by C99 style5 Copyright (c) 2009-2010 Tatsuhiko Kubo <cubicdaiya@gmail.com>
35==============================================================================*/6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
10
11 * Redistributions of source code must retain the above copyright notice,
12 this list of conditions and the following disclaimer.
13
14 * Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation
16 and/or other materials provided with the distribution.
17
18 * Neither the name of the authors nor the names of its contributors
19 may be used to endorse or promote products derived from this software
20 without specific prior written permission.
21
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
28 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34 written by C99 style
35 ==============================================================================*/
36 36
37#ifndef LEAF_MPOOL_H_INCLUDED37#ifndef LEAF_MPOOL_H_INCLUDED
38#define LEAF_MPOOL_H_INCLUDED38#define LEAF_MPOOL_H_INCLUDED
@@ -41,60 +41,76 @@ · 2 unmodified lines
41extern "C" {41extern "C" {
42#endif42#endif
43 43
44//==============================================================================44 //==============================================================================
45 45
46#include <stdio.h>46#include <stdio.h>
47#include <stdlib.h>47#include <stdlib.h>
48#include <string.h>48#include <string.h>
49#include <stdbool.h>49#include <stdbool.h>
50 50
51//==============================================================================51 //==============================================================================
52 52
53#define MPOOL_ALIGN_SIZE (8)53#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
62typedef 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
69typedef 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
76void mpool_create (char* memory, size_t size, mpool_t* pool);
77
78void *mpool_alloc(size_t size, mpool_t* pool);
79void mpool_free(void* ptr, mpool_t* pool);
80
81size_t mpool_get_size(mpool_t* pool);
82size_t mpool_get_used(mpool_t* pool);
83
84void leaf_pool_init(char* memory, size_t size);
85
86void* leaf_alloc(size_t size);
87void leaf_free(void* ptr);
88
89size_t leaf_pool_get_size(void);
90size_t leaf_pool_get_used(void);
91
92void* leaf_pool_get_pool(void);
93
94void leaf_mempool_overrun(void);
95 54
96//==============================================================================55 //#define size_t unsigned long
97 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
98#ifdef __cplusplus114#ifdef __cplusplus
99}115}
100#endif116#endif
@@ -104,3 +120,4 @@ void leaf_mempool_overrun(void); · 3 unmodified lines
104//==============================================================================120//==============================================================================
105 121
106 122
123
LEAF/Inc/leaf-midi.h+24−20
@@ -40,6 +40,8 @@ extern "C" { · 39 unmodified lines
40 40
41 void tStack_init (tStack* const);41 void tStack_init (tStack* const);
42 void tStack_free (tStack* const);42 void tStack_free (tStack* const);
43 void tStack_initToPool (tStack* const, tMempool* const);
44 void tStack_freeFromPool (tStack* const, tMempool* const);
43 45
44 void tStack_setCapacity (tStack* const, uint16_t cap);46 void tStack_setCapacity (tStack* const, uint16_t cap);
45 int tStack_addIfNotAlreadyThere (tStack* const, uint16_t item);47 int tStack_addIfNotAlreadyThere (tStack* const, uint16_t item);
@@ -91,28 +93,30 @@ extern "C" { · 45 unmodified lines
91 typedef _tPoly* tPoly;93 typedef _tPoly* tPoly;
92 94
93 /* MPoly*/95 /* MPoly*/
94 void tPoly_init(tPoly* const, int maxNumVoices);96 void tPoly_init (tPoly* const, int maxNumVoices);
95 void tPoly_free(tPoly* const);97 void tPoly_free (tPoly* const);
98 void tPoly_initToPool (tPoly* const, int maxNumVoices, tMempool* const);
99 void tPoly_freeFromPool (tPoly* const, tMempool* const);
96 100
97 //ADDING A NOTE101 //ADDING A NOTE
98 int tPoly_noteOn(tPoly* const, int note, uint8_t vel);102 int tPoly_noteOn (tPoly* const, int note, uint8_t vel);
99 int tPoly_noteOff(tPoly* const, uint8_t note);103 int tPoly_noteOff (tPoly* const, uint8_t note);
100 void tPoly_orderedAddToStack(tPoly* const, uint8_t noteVal);104 void tPoly_orderedAddToStack (tPoly* const, uint8_t noteVal);
101 void tPoly_setNumVoices(tPoly* const, uint8_t numVoices);105 void tPoly_setNumVoices (tPoly* const, uint8_t numVoices);
102 106
103 void tPoly_setPitchBend(tPoly* const, float pitchBend);107 void tPoly_setPitchBend (tPoly* const, float pitchBend);
104 void tPoly_setPitchGlideActive(tPoly* const, oBool isActive);108 void tPoly_setPitchGlideActive (tPoly* const, oBool isActive);
105 void tPoly_setPitchGlideTime(tPoly* const, float t);109 void tPoly_setPitchGlideTime (tPoly* const, float t);
106 void tPoly_tickPitch(tPoly* const);110 void tPoly_tickPitch (tPoly* const);
107 void tPoly_tickPitchGlide(tPoly* const);111 void tPoly_tickPitchGlide (tPoly* const);
108 void tPoly_tickPitchBend(tPoly* const);112 void tPoly_tickPitchBend (tPoly* const);
109 113
110 int tPoly_getNumVoices(tPoly* const);114 int tPoly_getNumVoices (tPoly* const);
111 int tPoly_getNumActiveVoices(tPoly* const);115 int tPoly_getNumActiveVoices (tPoly* const);
112 float tPoly_getPitch(tPoly* const, uint8_t voice);116 float tPoly_getPitch (tPoly* const, uint8_t voice);
113 int tPoly_getKey(tPoly* const, uint8_t voice);117 int tPoly_getKey (tPoly* const, uint8_t voice);
114 int tPoly_getVelocity(tPoly* const, uint8_t voice);118 int tPoly_getVelocity (tPoly* const, uint8_t voice);
115 int tPoly_isOn(tPoly* const, uint8_t voice);119 int tPoly_isOn (tPoly* const, uint8_t voice);
116 120
117 //==============================================================================121 //==============================================================================
118 122
LEAF/Inc/leaf-oscillators.h+76−46
@@ -14,6 +14,7 @@ extern "C" { · 13 unmodified lines
14 //==============================================================================14 //==============================================================================
15 15
16#include "leaf-math.h"16#include "leaf-math.h"
17#include "leaf-mempool.h"
17#include "leaf-filters.h"18#include "leaf-filters.h"
18 19
19 //==============================================================================20 //==============================================================================
@@ -25,13 +26,17 @@ extern "C" { · 5 unmodified lines
25 float phase;26 float phase;
26 float inc,freq;27 float inc,freq;
27 28
28 } tCycle;29 } _tCycle;
29 30
30 void tCycle_init (tCycle* const);31 typedef _tCycle* tCycle;
31 void tCycle_free (tCycle* const);
32 32
33 float tCycle_tick (tCycle* const);33 void tCycle_init (tCycle* const);
34 int tCycle_setFreq (tCycle* const, float freq);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);
35 40
36 //==============================================================================41 //==============================================================================
37 42
@@ -42,13 +47,17 @@ extern "C" { · 4 unmodified lines
42 float phase;47 float phase;
43 float inc,freq;48 float inc,freq;
44 49
45 } tTriangle;50 } _tTriangle;
51
52 typedef _tTriangle* tTriangle;
46 53
47 void tTriangle_init (tTriangle* const);54 void tTriangle_init (tTriangle* const);
48 void tTriangle_free (tTriangle* const);55 void tTriangle_free (tTriangle* const);
56 void tTriangle_initToPool (tTriangle* const, tMempool* const);
57 void tTriangle_freeFromPool (tTriangle* const, tMempool* const);
49 58
50 float tTriangle_tick (tTriangle* const);59 float tTriangle_tick (tTriangle* const);
51 int tTriangle_setFreq (tTriangle* const, float freq);60 int tTriangle_setFreq (tTriangle* const, float freq);
52 61
53 //==============================================================================62 //==============================================================================
54 63
@@ -59,13 +68,17 @@ extern "C" { · 4 unmodified lines
59 float phase;68 float phase;
60 float inc,freq;69 float inc,freq;
61 70
62 } tSquare;71 } _tSquare;
63 72
64 void tSquare_init (tSquare* const);73 typedef _tSquare* tSquare;
65 void tSquare_free (tSquare* const);
66 74
67 float tSquare_tick (tSquare* const);75 void tSquare_init (tSquare* const);
68 int tSquare_setFreq (tSquare* const, float freq);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);
69 82
70 //==============================================================================83 //==============================================================================
71 84
@@ -76,13 +89,17 @@ extern "C" { · 4 unmodified lines
76 float phase;89 float phase;
77 float inc,freq;90 float inc,freq;
78 91
79 } tSawtooth;92 } _tSawtooth;
93
94 typedef _tSawtooth* tSawtooth;
80 95
81 void tSawtooth_init (tSawtooth* const);96 void tSawtooth_init (tSawtooth* const);
82 void tSawtooth_free (tSawtooth* const);97 void tSawtooth_free (tSawtooth* const);
98 void tSawtooth_initToPool (tSawtooth* const, tMempool* const);
99 void tSawtooth_freeFromPool (tSawtooth* const, tMempool* const);
83 100
84 float tSawtooth_tick (tSawtooth* const);101 float tSawtooth_tick (tSawtooth* const);
85 int tSawtooth_setFreq (tSawtooth* const, float freq);102 int tSawtooth_setFreq (tSawtooth* const, float freq);
86 103
87 //==============================================================================104 //==============================================================================
88 105
@@ -92,13 +109,17 @@ extern "C" { · 3 unmodified lines
92 float phase;109 float phase;
93 float inc,freq;110 float inc,freq;
94 111
95 } tPhasor;112 } _tPhasor;
96 113
97 void tPhasor_init (tPhasor* const);114 typedef _tPhasor* tPhasor;
98 void tPhasor_free (tPhasor* const);
99 115
100 float tPhasor_tick (tPhasor* const);116 void tPhasor_init (tPhasor* const);
101 int tPhasor_setFreq (tPhasor* const, float freq);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);
102 123
103 //==============================================================================124 //==============================================================================
104 125
@@ -116,12 +137,16 @@ extern "C" { · 11 unmodified lines
116 float pinkb0, pinkb1, pinkb2;137 float pinkb0, pinkb1, pinkb2;
117 float(*rand)(void);138 float(*rand)(void);
118 139
119 } tNoise;140 } _tNoise;
141
142 typedef _tNoise* tNoise;
120 143
121 void tNoise_init (tNoise* const, NoiseType type);144 void tNoise_init (tNoise* const, NoiseType type);
122 void tNoise_free (tNoise* const);145 void tNoise_free (tNoise* const);
146 void tNoise_initToPool (tNoise* const, NoiseType type, tMempool* const);
147 void tNoise_freeFromPool (tNoise* const, tMempool* const);
123 148
124 float tNoise_tick (tNoise* const);149 float tNoise_tick (tNoise* const);
125 150
126 //==============================================================================151 //==============================================================================
127 152
@@ -149,23 +174,27 @@ extern "C" { · 21 unmodified lines
149 float V[3];174 float V[3];
150 float P[3];175 float P[3];
151 float gK, gN, gL, C;176 float gK, gN, gL, C;
152 } tNeuron;177 } _tNeuron;
153 178
154 void tNeuron_init (tNeuron* const);179 typedef _tNeuron* tNeuron;
155 void tNeuron_free (tNeuron* const);180
156 181 void tNeuron_init (tNeuron* const);
157 void tNeuron_reset (tNeuron* const);182 void tNeuron_free (tNeuron* const);
158 float tNeuron_Tick (tNeuron* const);183 void tNeuron_initToPool (tNeuron* const, tMempool* const);
159 void tNeuron_setMode (tNeuron* const, NeuronMode mode);184 void tNeuron_freeFromPool(tNeuron* const, tMempool* const);
160 void tNeuron_setCurrent (tNeuron* const, float current);185
161 void tNeuron_setK (tNeuron* const, float K);186 void tNeuron_reset (tNeuron* const);
162 void tNeuron_setL (tNeuron* const, float L);187 float tNeuron_tick (tNeuron* const);
163 void tNeuron_setN (tNeuron* const, float N);188 void tNeuron_setMode (tNeuron* const, NeuronMode mode);
164 void tNeuron_setC (tNeuron* const, float C);189 void tNeuron_setCurrent (tNeuron* const, float current);
165 void tNeuron_setV1 (tNeuron* const, float V1);190 void tNeuron_setK (tNeuron* const, float K);
166 void tNeuron_setV2 (tNeuron* const, float V2);191 void tNeuron_setL (tNeuron* const, float L);
167 void tNeuron_setV3 (tNeuron* const, float V3);192 void tNeuron_setN (tNeuron* const, float N);
168 void tNeuron_setTimeStep (tNeuron* const, float timestep);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);
169 198
170 //==============================================================================199 //==============================================================================
171 200
@@ -176,3 +205,4 @@ extern "C" { · 4 unmodified lines
176#endif // LEAF_OSCILLATORS_H_INCLUDED205#endif // LEAF_OSCILLATORS_H_INCLUDED
177 206
178//==============================================================================207//==============================================================================
208
LEAF/Inc/leaf-physical.h+69−48
@@ -19,6 +19,7 @@ extern "C" { · 18 unmodified lines
19 19
20#include "leaf-global.h"20#include "leaf-global.h"
21#include "leaf-math.h"21#include "leaf-math.h"
22#include "leaf-mempool.h"
22#include "leaf-delay.h"23#include "leaf-delay.h"
23#include "leaf-filters.h"24#include "leaf-filters.h"
24#include "leaf-oscillators.h"25#include "leaf-oscillators.h"
@@ -45,28 +46,30 @@ extern "C" { · 20 unmodified lines
45 46
46 typedef _tPluck* tPluck;47 typedef _tPluck* tPluck;
47 48
48 void tPluck_init (tPluck* const, float lowestFrequency); //float delayBuff[DELAY_LENGTH]);49 void tPluck_init (tPluck* const, float lowestFrequency); //float delayBuff[DELAY_LENGTH]);
49 void tPluck_free (tPluck* const);50 void tPluck_free (tPluck* const);
51 void tPluck_initToPool (tPluck* const, float lowestFrequency, tMempool* const);
52 void tPluck_freeFromPool (tPluck* const, tMempool* const);
50 53
51 float tPluck_tick (tPluck* const);54 float tPluck_tick (tPluck* const);
52 55
53 // Pluck the string.56 // Pluck the string.
54 void tPluck_pluck (tPluck* const, float amplitude);57 void tPluck_pluck (tPluck* const, float amplitude);
55 58
56 // Start a note with the given frequency and amplitude.;59 // 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 );
58 61
59 // Stop a note with the given amplitude (speed of decay).62 // 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 );
61 64
62 // Set instrument parameters for a particular frequency.65 // Set instrument parameters for a particular frequency.
63 void tPluck_setFrequency (tPluck* const, float frequency );66 void tPluck_setFrequency (tPluck* const, float frequency );
64 67
65 // Perform the control change specified by \e number and \e value (0.0 - 128.0).68 // 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);
67 70
68 // tPluck Utilities.71 // tPluck Utilities.
69 float tPluck_getLastOut (tPluck* const);72 float tPluck_getLastOut (tPluck* const);
70 73
71 //==============================================================================74 //==============================================================================
72 75
@@ -102,38 +105,40 @@ extern "C" { · 29 unmodified lines
102 105
103 typedef _tKarplusStrong* tKarplusStrong;106 typedef _tKarplusStrong* tKarplusStrong;
104 107
105 void tKarplusStrong_init (tKarplusStrong* const, float lowestFrequency); // float delayBuff[2][DELAY_LENGTH]);108 void tKarplusStrong_init (tKarplusStrong* const, float lowestFrequency); // float delayBuff[2][DELAY_LENGTH]);
106 void tKarplusStrong_free (tKarplusStrong* const);109 void tKarplusStrong_free (tKarplusStrong* const);
110 void tKarplusStrong_initToPool (tKarplusStrong* const, float lowestFrequency, tMempool* const);
111 void tKarplusStrong_freeFromPool (tKarplusStrong* const, tMempool* const);
107 112
108 float tKarplusStrong_tick (tKarplusStrong* const);113 float tKarplusStrong_tick (tKarplusStrong* const);
109 114
110 // Pluck the string.115 // Pluck the string.
111 void tKarplusStrong_pluck (tKarplusStrong* const, float amplitude);116 void tKarplusStrong_pluck (tKarplusStrong* const, float amplitude);
112 117
113 // Start a note with the given frequency and amplitude.;118 // 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 );
115 120
116 // Stop a note with the given amplitude (speed of decay).121 // 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 );
118 123
119 // Set instrument parameters for a particular frequency.124 // Set instrument parameters for a particular frequency.
120 void tKarplusStrong_setFrequency (tKarplusStrong* const, float frequency );125 void tKarplusStrong_setFrequency (tKarplusStrong* const, float frequency );
121 126
122 // Perform the control change specified by \e number and \e value (0.0 - 128.0).127 // Perform the control change specified by \e number and \e value (0.0 - 128.0).
123 // Use SKPickPosition, SKStringDamping, or SKDetune for type.128 // 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);
125 130
126 // Set the stretch "factor" of the string (0.0 - 1.0).131 // 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 );
128 133
129 // Set the pluck or "excitation" position along the string (0.0 - 1.0).134 // 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 );
131 136
132 // Set the base loop gain.137 // Set the base loop gain.
133 void tKarplusStrong_setBaseLoopGain (tKarplusStrong* const, float aGain );138 void tKarplusStrong_setBaseLoopGain (tKarplusStrong* const, float aGain );
134 139
135 // tKarplusStrong utilities.140 // tKarplusStrong utilities.
136 float tKarplusStrong_getLastOut (tKarplusStrong* const);141 float tKarplusStrong_getLastOut (tKarplusStrong* const);
137 142
138 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~143 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
139 144
@@ -153,18 +158,25 @@ extern "C" { · 13 unmodified lines
153 158
154 typedef _tSimpleLivingString* tSimpleLivingString;159 typedef _tSimpleLivingString* tSimpleLivingString;
155 160
156 void tSimpleLivingString_init (tSimpleLivingString* const, float freq, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode);161 void tSimpleLivingString_init (tSimpleLivingString* const, float freq, float dampFreq,
157 void tSimpleLivingString_free (tSimpleLivingString* const);162 float decay, float targetLev, float levSmoothFactor,
158 float tSimpleLivingString_tick (tSimpleLivingString* const, float input);163 float levStrength, int levMode);
159 float tSimpleLivingString_sample (tSimpleLivingString* const);164 void tSimpleLivingString_free (tSimpleLivingString* const);
160 void tSimpleLivingString_setFreq (tSimpleLivingString* const, float freq);165 void tSimpleLivingString_initToPool (tSimpleLivingString* const, float freq, float dampFreq,
161 void tSimpleLivingString_setWaveLength (tSimpleLivingString* const, float waveLength); // in samples166 float decay, float targetLev, float levSmoothFactor,
162 void tSimpleLivingString_setDampFreq (tSimpleLivingString* const, float dampFreq);167 float levStrength, int levMode, tMempool* const);
163 void tSimpleLivingString_setDecay (tSimpleLivingString* const, float decay); // should be near 1.0168 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
164 void tSimpleLivingString_setTargetLev (tSimpleLivingString* const, float targetLev);176 void tSimpleLivingString_setTargetLev (tSimpleLivingString* const, float targetLev);
165 void tSimpleLivingString_setLevSmoothFactor (tSimpleLivingString* const, float levSmoothFactor);177 void tSimpleLivingString_setLevSmoothFactor (tSimpleLivingString* const, float levSmoothFactor);
166 void tSimpleLivingString_setLevStrength (tSimpleLivingString* const, float levStrength);178 void tSimpleLivingString_setLevStrength (tSimpleLivingString* const, float levStrength);
167 void tSimpleLivingString_setLevMode (tSimpleLivingString* const, int levMode);179 void tSimpleLivingString_setLevMode (tSimpleLivingString* const, int levMode);
168 180
169 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~181 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
170 182
@@ -186,19 +198,25 @@ extern "C" { · 15 unmodified lines
186 198
187 typedef _tLivingString* tLivingString;199 typedef _tLivingString* tLivingString;
188 200
189 void tLivingString_init (tLivingString* const, float freq, float pickPos, float prepIndex, float dampFreq, float decay,201 void tLivingString_init (tLivingString* const, float freq, float pickPos, float prepIndex,
190 float targetLev, float levSmoothFactor, float levStrength, int levMode);202 float dampFreq, float decay, float targetLev, float levSmoothFactor,
191 void tLivingString_free (tLivingString* const);203 float levStrength, int levMode);
192 float tLivingString_tick (tLivingString* const, float input);204 void tLivingString_free (tLivingString* const);
193 float tLivingString_sample (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);
194 void tLivingString_setFreq (tLivingString* const, float freq);212 void tLivingString_setFreq (tLivingString* const, float freq);
195 void tLivingString_setWaveLength (tLivingString* const, float waveLength); // in samples213 void tLivingString_setWaveLength (tLivingString* const, float waveLength); // in samples
196 void tLivingString_setPickPos (tLivingString* const, float pickPos);214 void tLivingString_setPickPos (tLivingString* const, float pickPos);
197 void tLivingString_setPrepIndex (tLivingString* const, float prepIndex);215 void tLivingString_setPrepIndex (tLivingString* const, float prepIndex);
198 void tLivingString_setDampFreq (tLivingString* const, float dampFreq);216 void tLivingString_setDampFreq (tLivingString* const, float dampFreq);
199 void tLivingString_setDecay (tLivingString* const, float decay); // should be near 1.0217 void tLivingString_setDecay (tLivingString* const, float decay); // should be near 1.0
200 void tLivingString_setTargetLev (tLivingString* const, float targetLev);218 void tLivingString_setTargetLev (tLivingString* const, float targetLev);
201 void tLivingString_setLevSmoothFactor (tLivingString* const, float levSmoothFactor);219 void tLivingString_setLevSmoothFactor (tLivingString* const, float levSmoothFactor);
202 void tLivingString_setLevStrength (tLivingString* const, float levStrength);220 void tLivingString_setLevStrength (tLivingString* const, float levStrength);
203 void tLivingString_setLevMode (tLivingString* const, int levMode);221 void tLivingString_setLevMode (tLivingString* const, int levMode);
204 222
@@ -211,12 +229,15 @@ extern "C" { · 6 unmodified lines
211 229
212 typedef _tReedTable* tReedTable;230 typedef _tReedTable* tReedTable;
213 231
214 void tReedTable_init (tReedTable* const, float offset, float slope);232 void tReedTable_init (tReedTable* const, float offset, float slope);
215 void tReedTable_free (tReedTable* const);233 void tReedTable_free (tReedTable* const);
216 float tReedTable_tick (tReedTable* const, float input);234 void tReedTable_initToPool (tReedTable* const, float offset, float slope, tMempool* const);
217 float tReedTable_tanh_tick (tReedTable* const p, float input); //tanh softclip version of reed table - replacing the hard clip in original stk code235 void tReedTable_freeFromPool (tReedTable* const, tMempool* const);
218 void tReedTable_setOffset (tReedTable* const, float offset);236
219 void tReedTable_setSlope (tReedTable* const, float slope);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);
220 241
221 //==============================================================================242 //==============================================================================
222 243
LEAF/Inc/leaf-reverb.h+19−12
@@ -17,6 +17,7 @@ extern "C" { · 16 unmodified lines
17 17
18#include "leaf-global.h"18#include "leaf-global.h"
19#include "leaf-math.h"19#include "leaf-math.h"
20#include "leaf-mempool.h"
20#include "leaf-delay.h"21#include "leaf-delay.h"
21#include "leaf-filters.h"22#include "leaf-filters.h"
22#include "leaf-oscillators.h"23#include "leaf-oscillators.h"
@@ -41,16 +42,18 @@ extern "C" { · 18 unmodified lines
41 42
42 typedef _tPRCReverb* tPRCReverb;43 typedef _tPRCReverb* tPRCReverb;
43 44
44 void tPRCReverb_init (tPRCReverb* const, float t60);45 void tPRCReverb_init (tPRCReverb* const, float t60);
45 void tPRCReverb_free (tPRCReverb* const);46 void tPRCReverb_free (tPRCReverb* const);
47 void tPRCReverb_initToPool (tPRCReverb* const, float t60, tMempool* const);
48 void tPRCReverb_freeFromPool (tPRCReverb* const, tMempool* const);
46 49
47 float tPRCReverb_tick (tPRCReverb* const, float input);50 float tPRCReverb_tick (tPRCReverb* const, float input);
48 51
49 // Set reverb time in seconds.52 // Set reverb time in seconds.
50 void tPRCReverb_setT60 (tPRCReverb* const, float t60);53 void tPRCReverb_setT60 (tPRCReverb* const, float t60);
51 54
52 // Set mix between dry input and wet output signal.55 // 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);
54 57
55 //==============================================================================58 //==============================================================================
56 59
@@ -73,17 +76,19 @@ extern "C" { · 16 unmodified lines
73 76
74 typedef _tNReverb* tNReverb;77 typedef _tNReverb* tNReverb;
75 78
76 void tNReverb_init (tNReverb* const, float t60);79 void tNReverb_init (tNReverb* const, float t60);
77 void tNReverb_free (tNReverb* const);80 void tNReverb_free (tNReverb* const);
81 void tNReverb_initToPool (tNReverb* const, float t60, tMempool* const);
82 void tNReverb_freeFromPool (tNReverb* const, tMempool* const);
78 83
79 float tNReverb_tick (tNReverb* const, float input);84 float tNReverb_tick (tNReverb* const, float input);
80 void tNReverb_tickStereo(tNReverb* const rev, float input, float* output);85 void tNReverb_tickStereo (tNReverb* const rev, float input, float* output);
81 86
82 // Set reverb time in seconds.87 // Set reverb time in seconds.
83 void tNReverb_setT60 (tNReverb* const, float t60);88 void tNReverb_setT60 (tNReverb* const, float t60);
84 89
85 // Set mix between dry input and wet output signal.90 // 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);
87 92
88 //==============================================================================93 //==============================================================================
89 94
@@ -135,11 +140,13 @@ extern "C" { · 45 unmodified lines
135 140
136 void tDattorroReverb_init (tDattorroReverb* const);141 void tDattorroReverb_init (tDattorroReverb* const);
137 void tDattorroReverb_free (tDattorroReverb* const);142 void tDattorroReverb_free (tDattorroReverb* const);
143 void tDattorroReverb_initToPool (tDattorroReverb* const, tMempool* const);
144 void tDattorroReverb_freeFromPool (tDattorroReverb* const, tMempool* const);
138 145
139 float tDattorroReverb_tick (tDattorroReverb* const, float input);146 float tDattorroReverb_tick (tDattorroReverb* const, float input);
140 void tDattorroReverb_tickStereo (tDattorroReverb* const rev, float input, float* output);147 void tDattorroReverb_tickStereo (tDattorroReverb* const rev, float input, float* output);
141 void tDattorroReverb_setMix (tDattorroReverb* const, float mix);148 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);
143 void tDattorroReverb_setHP (tDattorroReverb* const, float freq);150 void tDattorroReverb_setHP (tDattorroReverb* const, float freq);
144 void tDattorroReverb_setSize (tDattorroReverb* const, float size);151 void tDattorroReverb_setSize (tDattorroReverb* const, float size);
145 void tDattorroReverb_setInputDelay (tDattorroReverb* const, float preDelay);152 void tDattorroReverb_setInputDelay (tDattorroReverb* const, float preDelay);
LEAF/Inc/leaf-sampling.h+29−26
@@ -18,6 +18,7 @@ extern "C" { · 17 unmodified lines
18 18
19#include "leaf-global.h"19#include "leaf-global.h"
20#include "leaf-math.h"20#include "leaf-math.h"
21#include "leaf-mempool.h"
21#include "leaf-envelopes.h"22#include "leaf-envelopes.h"
22#include "leaf-mempool.h"23#include "leaf-mempool.h"
23 24
@@ -45,27 +46,27 @@ extern "C" { · 21 unmodified lines
45 46
46 typedef _tBuffer* tBuffer;47 typedef _tBuffer* tBuffer;
47 48
48 void tBuffer_init (tBuffer* const, uint32_t length);49 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);
50 void tBuffer_free (tBuffer* const);51 void tBuffer_initToPool (tBuffer* const, uint32_t length, tMempool* const);
51 void tBuffer_free_locate (tBuffer* const sb, mpool_t* pool);52 void tBuffer_freeFromPool (tBuffer* const, tMempool* const);
52 53
53 void tBuffer_tick (tBuffer* const, float sample);54 void tBuffer_tick (tBuffer* const, float sample);
54 55
55 void tBuffer_read(tBuffer* const, float* buff, uint32_t len);56 void tBuffer_read (tBuffer* const, float* buff, uint32_t len);
56 57
57 float tBuffer_get (tBuffer* const, int idx);58 float tBuffer_get (tBuffer* const, int idx);
58 59
59 void tBuffer_record (tBuffer* const);60 void tBuffer_record (tBuffer* const);
60 void tBuffer_stop (tBuffer* const);61 void tBuffer_stop (tBuffer* const);
61 int tBuffer_getRecordPosition(tBuffer* const);62 int tBuffer_getRecordPosition (tBuffer* const);
62 63
63 void tBuffer_setRecordMode (tBuffer* const, RecordMode mode);64 void tBuffer_setRecordMode (tBuffer* const, RecordMode mode);
64 65
65 void tBuffer_clear (tBuffer* const);66 void tBuffer_clear (tBuffer* const);
66 67
67 uint32_t tBuffer_getBufferLength(tBuffer* const);68 uint32_t tBuffer_getBufferLength (tBuffer* const);
68 uint32_t tBuffer_getRecordedLength(tBuffer* const sb);69 uint32_t tBuffer_getRecordedLength (tBuffer* const sb);
69 70
70 //==============================================================================71 //==============================================================================
71 72
@@ -106,26 +107,28 @@ extern "C" { · 34 unmodified lines
106 107
107 typedef _tSampler* tSampler;108 typedef _tSampler* tSampler;
108 109
109 void tSampler_init (tSampler* const, tBuffer* const);110 void tSampler_init (tSampler* const, tBuffer* const);
110 void tSampler_free (tSampler* 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);
111 114
112 float tSampler_tick (tSampler* const);115 float tSampler_tick (tSampler* const);
113 116
114 void tSampler_setSample (tSampler* const, tBuffer* const);117 void tSampler_setSample (tSampler* const, tBuffer* const);
115 118
116 void tSampler_setMode (tSampler* const, PlayMode mode);119 void tSampler_setMode (tSampler* const, PlayMode mode);
117 120
118 void tSampler_play (tSampler* const);121 void tSampler_play (tSampler* const);
119 void tSampler_stop (tSampler* const);122 void tSampler_stop (tSampler* const);
120 123
121 void tSampler_setStart (tSampler* const, int32_t start);124 void tSampler_setStart (tSampler* const, int32_t start);
122 void tSampler_setEnd (tSampler* const, int32_t end);125 void tSampler_setEnd (tSampler* const, int32_t end);
123 126
124 static void handleStartEndChange(tSampler* const sp);127 static void handleStartEndChange (tSampler* const sp);
125 128
126 void tSampler_setCrossfadeLength (tSampler* const sp, uint32_t length);129 void tSampler_setCrossfadeLength (tSampler* const sp, uint32_t length);
127 130
128 void tSampler_setRate (tSampler* const, float rate);131 void tSampler_setRate (tSampler* const, float rate);
129 132
130 //==============================================================================133 //==============================================================================
131 134
LEAF/Src/leaf-analysis.c+279−123
@@ -38,6 +38,24 @@ void tEnvelopeFollower_free(tEnvelopeFollower* const ef) · 37 unmodified lines
38 leaf_free(e);38 leaf_free(e);
39}39}
40 40
41void tEnvelopeFollower_initToPool (tEnvelopeFollower* const ef, float attackThreshold, float decayCoeff, tMempool* const mp)
42{
43 _tMempool* m = *mp;
44 _tEnvelopeFollower* e = *ef = (_tEnvelopeFollower*) mpool_alloc(sizeof(_tEnvelopeFollower), m->pool);
45
46 e->y = 0.0f;
47 e->a_thresh = attackThreshold;
48 e->d_coeff = decayCoeff;
49}
50
51void tEnvelopeFollower_freeFromPool (tEnvelopeFollower* const ef, tMempool* const mp)
52{
53 _tMempool* m = *mp;
54 _tEnvelopeFollower* e = *ef;
55
56 mpool_free(e, m->pool);
57}
58
41float tEnvelopeFollower_tick(tEnvelopeFollower* const ef, float x)59float tEnvelopeFollower_tick(tEnvelopeFollower* const ef, float x)
42{60{
43 _tEnvelopeFollower* e = *ef;61 _tEnvelopeFollower* e = *ef;
@@ -68,9 +86,6 @@ int tEnvelopeFollower_attackThresh(tEnvelopeFollower* const ef, float attack · 24 unmodified lines
68}86}
69 87
70 88
71
72
73
74//===========================================================================89//===========================================================================
75/* Power Follower */90/* Power Follower */
76//===========================================================================91//===========================================================================
@@ -90,6 +105,24 @@ void tPowerFollower_free(tPowerFollower* const pf) · 13 unmodified lines
90 leaf_free(p);105 leaf_free(p);
91}106}
92 107
108void 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
118void 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
93int tPowerFollower_setFactor(tPowerFollower* const pf, float factor)126int tPowerFollower_setFactor(tPowerFollower* const pf, float factor)
94{127{
95 _tPowerFollower* p = *pf;128 _tPowerFollower* p = *pf;
@@ -123,7 +156,57 @@ float tPowerFollower_sample(tPowerFollower* const pf) · 27 unmodified lines
123 156
124void tEnvPD_init(tEnvPD* const xpd, int ws, int hs, int bs)157void tEnvPD_init(tEnvPD* const xpd, int ws, int hs, int bs)
125{158{
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
199void tEnvPD_free (tEnvPD* const xpd)
200{
201 _tEnvPD* x = *xpd;
202
203 leaf_free(x);
204}
205
206void 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);
127 210
128 int period = hs, npoints = ws;211 int period = hs, npoints = ws;
129 212
@@ -163,11 +246,12 @@ void tEnvPD_init(tEnvPD* const xpd, int ws, int hs, int bs) · 33 unmodified lines
163 // ~ ~ ~ ~ ~ ~ ~ ~246 // ~ ~ ~ ~ ~ ~ ~ ~
164}247}
165 248
166void tEnvPD_free (tEnvPD* const xpd)249void tEnvPD_freeFromPool (tEnvPD* const xpd, tMempool* const mp)
167{250{
251 _tMempool* m = *mp;
168 _tEnvPD* x = *xpd;252 _tEnvPD* x = *xpd;
169 253
170 leaf_free(x);254 mpool_free(x, m->pool);
171}255}
172 256
173float tEnvPD_tick (tEnvPD* const xpd)257float tEnvPD_tick (tEnvPD* const xpd)
@@ -222,25 +306,34 @@ static void atkdtk_envelope(tAttackDetection* const a, float *in); · 48 unmodified lines
222 306
223/********Constructor/Destructor***************/307/********Constructor/Destructor***************/
224 308
225void tAttackDetection_init(tAttackDetection* const ad, int blocksize)309void tAttackDetection_init(tAttackDetection* const ad, int blocksize, int atk, int rel)
226{310{
227 *ad = (_tAttackDetection*) leaf_alloc(sizeof(_tAttackDetection));311 *ad = (_tAttackDetection*) leaf_alloc(sizeof(_tAttackDetection));
228 312
229 atkdtk_init(ad, blocksize, DEFATTACK, DEFRELEASE);313 atkdtk_init(ad, blocksize, atk, rel);
230}314}
231 315
232void tAttackDetection_init_expanded(tAttackDetection* const ad, int blocksize, int atk, int rel)316void tAttackDetection_free(tAttackDetection* const ad)
233{317{
234 *ad = (_tAttackDetection*) leaf_alloc(sizeof(_tAttackDetection));318 _tAttackDetection* a = *ad;
319
320 leaf_free(a);
321}
322
323void 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);
235 327
236 atkdtk_init(ad, blocksize, atk, rel);328 atkdtk_init(ad, blocksize, atk, rel);
237}329}
238 330
239void tAttackDetection_free(tAttackDetection* const ad)331void tAttackDetection_freeFromPool (tAttackDetection* const ad, tMempool* const mp)
240{332{
333 _tMempool* m = *mp;
241 _tAttackDetection* a = *ad;334 _tAttackDetection* a = *ad;
242 335
243 leaf_free(a);336 mpool_free(a, m->pool);
244}337}
245 338
246/*******Public Functions***********/339/*******Public Functions***********/
@@ -265,8 +358,8 @@ void tAttackDetection_setSamplerate(tAttackDetection* const ad, int inRate) · 18 unmodified lines
265 a->samplerate = inRate;358 a->samplerate = inRate;
266 359
267 //Reset atk and rel to recalculate coeff360 //Reset atk and rel to recalculate coeff
268 tAttackDetection_setAtk(ad, a->atk);361 tAttackDetection_setAttack(ad, a->atk);
269 tAttackDetection_setRel(ad, a->rel);362 tAttackDetection_setRelease(ad, a->rel);
270}363}
271 364
272void tAttackDetection_setThreshold(tAttackDetection* const ad, float thres)365void tAttackDetection_setThreshold(tAttackDetection* const ad, float thres)
@@ -275,14 +368,14 @@ void tAttackDetection_setThreshold(tAttackDetection* const ad, float thres) · 2 unmodified lines
275 a->threshold = thres;368 a->threshold = thres;
276}369}
277 370
278void tAttackDetection_setAtk(tAttackDetection* const ad, int inAtk)371void tAttackDetection_setAttack(tAttackDetection* const ad, int inAtk)
279{372{
280 _tAttackDetection* a = *ad;373 _tAttackDetection* a = *ad;
281 a->atk = inAtk;374 a->atk = inAtk;
282 a->atk_coeff = pow(0.01, 1.0/(a->atk * a->samplerate * 0.001));375 a->atk_coeff = pow(0.01, 1.0/(a->atk * a->samplerate * 0.001));
283}376}
284 377
285void tAttackDetection_setRel(tAttackDetection* const ad, int inRel)378void tAttackDetection_setRelease(tAttackDetection* const ad, int inRel)
286{379{
287 _tAttackDetection* a = *ad;380 _tAttackDetection* a = *ad;
288 a->rel = inRel;381 a->rel = inRel;
@@ -322,8 +415,8 @@ static void atkdtk_init(tAttackDetection* const ad, int blocksize, int atk, int · 33 unmodified lines
322 415
323 a->env = 0;416 a->env = 0;
324 417
325 tAttackDetection_setAtk(ad, atk);418 tAttackDetection_setAttack(ad, atk);
326 tAttackDetection_setRel(ad, rel);419 tAttackDetection_setRelease(ad, rel);
327}420}
328 421
329static void atkdtk_envelope(tAttackDetection* const ad, float *in)422static void atkdtk_envelope(tAttackDetection* const ad, float *in)
@@ -343,98 +436,6 @@ static void atkdtk_envelope(tAttackDetection* const ad, float *in) · 13 unmodified lines
343 436
344}437}
345 438
346//===========================================================================
347// PERIODDETECTION
348//===========================================================================
349void 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
374void 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
383float 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
418void tPeriodDetection_setHopSize(tPeriodDetection* pd, int hs)
419{
420 _tPeriodDetection* p = *pd;
421 p->hopSize = hs;
422}
423
424void 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
438//===========================================================================439//===========================================================================
439// SNAC440// SNAC
440//===========================================================================441//===========================================================================
@@ -461,7 +462,7 @@ static float snac_spectralpeak(tSNAC* const s, float periodlength); · 20 unmodified lines
461 462
462void tSNAC_init(tSNAC* const snac, int overlaparg)463void tSNAC_init(tSNAC* const snac, int overlaparg)
463{464{
464 _tSNAC* s = *snac = (_tSNAC*) leaf_alloc(sizeof(_tSNAC));465 _tSNAC* s = *snac = (_tSNAC*) leaf_allocAndClear(sizeof(_tSNAC));
465 466
466 s->biasfactor = DEFBIAS;467 s->biasfactor = DEFBIAS;
467 s->timeindex = 0;468 s->timeindex = 0;
@@ -471,10 +472,10 @@ void tSNAC_init(tSNAC* const snac, int overlaparg) · 3 unmodified lines
471 s->minrms = DEFMINRMS;472 s->minrms = DEFMINRMS;
472 s->framesize = SNAC_FRAME_SIZE;473 s->framesize = SNAC_FRAME_SIZE;
473 474
474 s->inputbuf = (float*) leaf_alloc(sizeof(float) * SNAC_FRAME_SIZE);475 s->inputbuf = (float*) leaf_allocAndClear(sizeof(float) * SNAC_FRAME_SIZE);
475 s->processbuf = (float*) leaf_alloc(sizeof(float) * (SNAC_FRAME_SIZE * 2));476 s->processbuf = (float*) leaf_allocAndClear(sizeof(float) * (SNAC_FRAME_SIZE * 2));
476 s->spectrumbuf = (float*) leaf_alloc(sizeof(float) * (SNAC_FRAME_SIZE / 2));477 s->spectrumbuf = (float*) leaf_allocAndClear(sizeof(float) * (SNAC_FRAME_SIZE / 2));
477 s->biasbuf = (float*) leaf_alloc(sizeof(float) * SNAC_FRAME_SIZE);478 s->biasbuf = (float*) leaf_allocAndClear(sizeof(float) * SNAC_FRAME_SIZE);
478 479
479 snac_biasbuf(snac);480 snac_biasbuf(snac);
480 tSNAC_setOverlap(snac, overlaparg);481 tSNAC_setOverlap(snac, overlaparg);
@@ -490,6 +491,41 @@ void tSNAC_free(tSNAC* const snac) · 9 unmodified lines
490 leaf_free(s->biasbuf);491 leaf_free(s->biasbuf);
491 leaf_free(s);492 leaf_free(s);
492}493}
494
495void 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
517void 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
493/******************************************************************************/529/******************************************************************************/
494/************************** public access functions****************************/530/************************** public access functions****************************/
495/******************************************************************************/531/******************************************************************************/
@@ -737,17 +773,17 @@ static float snac_spectralpeak(tSNAC* const snac, float periodlength) · 241 unmodified lines
737{773{
738 _tSNAC* s = *snac;774 _tSNAC* s = *snac;
739 775
740 if(periodlength < 4.) return periodlength;776 if(periodlength < 4.0f) return periodlength;
741 777
742 float max = 0.;778 float max = 0.;
743 int n, startbin, stopbin, peakbin = 0;779 int n, startbin, stopbin, peakbin = 0;
744 int spectrumsize = s->framesize>>1;780 int spectrumsize = s->framesize>>1;
745 float *spectrumbuf = s->spectrumbuf;781 float *spectrumbuf = s->spectrumbuf;
746 float peaklocation = (float)(s->framesize * 2.) / periodlength;782 float peaklocation = (float)(s->framesize * 2.0f) / periodlength;
747 783
748 startbin = (int)(peaklocation * 0.8 + 0.5);784 startbin = (int)(peaklocation * 0.8f + 0.5f);
749 if(startbin < 1) startbin = 1;785 if(startbin < 1) startbin = 1;
750 stopbin = (int)(peaklocation * 1.25 + 0.5);786 stopbin = (int)(peaklocation * 1.25f + 0.5f);
751 if(stopbin >= spectrumsize - 1) stopbin = spectrumsize - 1;787 if(stopbin >= spectrumsize - 1) stopbin = spectrumsize - 1;
752 788
753 for(n=startbin; n<stopbin; n++)789 for(n=startbin; n<stopbin; n++)
@@ -768,7 +804,7 @@ static float snac_spectralpeak(tSNAC* const snac, float periodlength) · 14 unmodified lines
768 // calculate amplitudes in peak region804 // calculate amplitudes in peak region
769 for(n=(peakbin-1); n<(peakbin+2); n++)805 for(n=(peakbin-1); n<(peakbin+2); n++)
770 {806 {
771 spectrumbuf[n] = sqrt(spectrumbuf[n]);807 spectrumbuf[n] = sqrtf(spectrumbuf[n]);
772 }808 }
773 809
774 peaklocation = (float)peakbin + interpolate3phase(spectrumbuf, peakbin);810 peaklocation = (float)peakbin + interpolate3phase(spectrumbuf, peakbin);
@@ -785,17 +821,137 @@ static void snac_biasbuf(tSNAC* const snac) · 10 unmodified lines
785 821
786 int n;822 int n;
787 int maxperiod = (int)(s->framesize * (float)SEEK);823 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));
789 float *biasbuf = s->biasbuf;825 float *biasbuf = s->biasbuf;
790 826
791 for(n=0; n<5; n++) // periods < 5 samples can't be tracked827 for(n=0; n<5; n++) // periods < 5 samples can't be tracked
792 {828 {
793 biasbuf[n] = 0.;829 biasbuf[n] = 0.0f;
794 }830 }
795 831
796 for(n=5; n<maxperiod; n++)832 for(n=5; n<maxperiod; n++)
797 {833 {
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//===========================================================================
841void 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
866void 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
875void 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
901void 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
911float 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;
799 }940 }
941
942 // changed from period to p->period
943 return p->period;
944}
945
946void tPeriodDetection_setHopSize(tPeriodDetection* pd, int hs)
947{
948 _tPeriodDetection* p = *pd;
949 p->hopSize = hs;
950}
951
952void tPeriodDetection_setWindowSize(tPeriodDetection* pd, int ws)
953{
954 _tPeriodDetection* p = *pd;
955 p->windowSize = ws;
800}956}
801 957
LEAF/Src/leaf-delay.c+396−42
@@ -19,7 +19,7 @@ · 18 unmodified lines
19#endif19#endif
20 20
21// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Delay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //21// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Delay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
22void tDelay_init (tDelay* const dl, uint32_t delay, uint32_t maxDelay)22void tDelay_init (tDelay* const dl, uint32_t delay, uint32_t maxDelay)
23{23{
24 _tDelay* d = *dl = (_tDelay*) leaf_alloc(sizeof(_tDelay));24 _tDelay* d = *dl = (_tDelay*) leaf_alloc(sizeof(_tDelay));
25 25
@@ -48,6 +48,37 @@ void tDelay_free(tDelay* const dl) · 22 unmodified lines
48 leaf_free(d);48 leaf_free(d);
49}49}
50 50
51void 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
73void 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
51float tDelay_tick (tDelay* const dl, float input)82float tDelay_tick (tDelay* const dl, float input)
52{83{
53 _tDelay* d = *dl;84 _tDelay* d = *dl;
@@ -177,6 +208,51 @@ void tLinearDelay_free(tLinearDelay* const dl) · 123 unmodified lines
177 leaf_free(d);208 leaf_free(d);
178}209}
179 210
211void 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
235void 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
245void 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
180float tLinearDelay_tick (tLinearDelay* const dl, float input)256float tLinearDelay_tick (tLinearDelay* const dl, float input)
181{257{
182 _tLinearDelay* d = *dl;258 _tLinearDelay* d = *dl;
@@ -186,15 +262,15 @@ float tLinearDelay_tick (tLinearDelay* const dl, float input) · 3 unmodified lines
186 // Increment input pointer modulo length.262 // Increment input pointer modulo length.
187 if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0;263 if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0;
188 264
189
190 uint32_t idx = (uint32_t) d->outPoint;265 uint32_t idx = (uint32_t) d->outPoint;
191 266 // First 1/2 of interpolation
192 d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay],267 d->lastOut = d->buff[idx] * d->omAlpha;
193 d->buff[idx],268 // Second 1/2 of interpolation
194 d->buff[(idx + 1) % d->maxDelay],269 if ((idx + 1) < d->maxDelay)
195 d->buff[(idx + 2) % d->maxDelay],270 d->lastOut += d->buff[idx+1] * d->alpha;
196 d->alpha);271 else
197 272 d->lastOut += d->buff[0] * d->alpha;
273
198 // Increment output pointer modulo length274 // Increment output pointer modulo length
199 if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0;275 if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0;
200 276
@@ -215,18 +291,19 @@ float tLinearDelay_tickOut (tLinearDelay* const dl) · 14 unmodified lines
215{291{
216 _tLinearDelay* d = *dl;292 _tLinearDelay* d = *dl;
217 293
218 uint32_t idx = (uint32_t) d->outPoint;294 uint32_t idx = (uint32_t) d->outPoint;
219 295 // First 1/2 of interpolation
220 d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay],296 d->lastOut = d->buff[idx] * d->omAlpha;
221 d->buff[idx],297 // Second 1/2 of interpolation
222 d->buff[(idx + 1) % d->maxDelay],298 if ((idx + 1) < d->maxDelay)
223 d->buff[(idx + 2) % d->maxDelay],299 d->lastOut += d->buff[idx+1] * d->alpha;
224 d->alpha);300 else
301 d->lastOut += d->buff[0] * d->alpha;
225 302
226 // Increment output pointer modulo length303 // Increment output pointer modulo length
227 if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0;304 if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0;
228 305
229 return d->lastOut;306 return d->lastOut;
230}307}
231 308
232int tLinearDelay_setDelay (tLinearDelay* const dl, float delay)309int tLinearDelay_setDelay (tLinearDelay* const dl, float delay)
@@ -250,38 +327,22 @@ int tLinearDelay_setDelay (tLinearDelay* const dl, float delay) · 17 unmodified lines
250 return 0;327 return 0;
251}328}
252 329
253float tLinearDelay_tapOut (tLinearDelay* const dl, float tapDelay)330float tLinearDelay_tapOut (tLinearDelay* const dl, uint32_t tapDelay)
254{331{
255 _tLinearDelay* d = *dl;332 _tLinearDelay* d = *dl;
256 333
257 float tap = (float) d->inPoint - tapDelay - 1.f;334 uint32_t tap = d->inPoint - tapDelay - 1;
258
259 // Check for wraparound.335 // Check for wraparound.
260 while ( tap < 0.f ) tap += (float)d->maxDelay;336 while ( tap < 0 ) tap += 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;
277 337
338 return d->buff[tap];
278}339}
279 340
280void tLinearDelay_tapIn (tLinearDelay* const dl, float value, uint32_t tapDelay)341void tLinearDelay_tapIn (tLinearDelay* const dl, float value, uint32_t tapDelay)
281{342{
282 _tLinearDelay* d = *dl;343 _tLinearDelay* d = *dl;
283 344
284 int32_t tap = d->inPoint - tapDelay - 1;345 uint32_t tap = d->inPoint - tapDelay - 1;
285 346
286 // Check for wraparound.347 // Check for wraparound.
287 while ( tap < 0 ) tap += d->maxDelay;348 while ( tap < 0 ) tap += d->maxDelay;
@@ -332,6 +393,234 @@ float tLinearDelay_getGain (tLinearDelay* const dl) · 44 unmodified lines
332 return d->gain;393 return d->gain;
333}394}
334 395
396
397
398
399
400/// Hermite Interpolated Delay
401// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ LinearDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
402void 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
425void tHermiteDelay_free(tHermiteDelay* const dl)
426{
427 _tHermiteDelay* d = *dl;
428
429 leaf_free(d->buff);
430 leaf_free(d);
431}
432
433void 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
457void 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
467void 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
478float 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
501void 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
511float 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
531int 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
552float 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
565void 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
577float 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
589float tHermiteDelay_getDelay (tHermiteDelay* const dl)
590{
591 _tHermiteDelay* d = *dl;
592 return d->delay;
593}
594
595float tHermiteDelay_getLastOut (tHermiteDelay* const dl)
596{
597 _tHermiteDelay* d = *dl;
598 return d->lastOut;
599}
600
601float tHermiteDelay_getLastIn (tHermiteDelay* const dl)
602{
603 _tHermiteDelay* d = *dl;
604 return d->lastIn;
605}
606
607void 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
614float tHermiteDelay_getGain (tHermiteDelay* const dl)
615{
616 _tHermiteDelay* d = *dl;
617 return d->gain;
618}
619
620
621
622
623
335// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ AllpassDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //624// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ AllpassDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
336void tAllpassDelay_init (tAllpassDelay* const dl, float delay, uint32_t maxDelay)625void tAllpassDelay_init (tAllpassDelay* const dl, float delay, uint32_t maxDelay)
337{626{
@@ -366,6 +655,41 @@ void tAllpassDelay_free(tAllpassDelay* const dl) · 28 unmodified lines
366 leaf_free(d);655 leaf_free(d);
367}656}
368 657
658void 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
684void 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
369float tAllpassDelay_tick (tAllpassDelay* const dl, float input)693float tAllpassDelay_tick (tAllpassDelay* const dl, float input)
370{694{
371 _tAllpassDelay* d = *dl;695 _tAllpassDelay* d = *dl;
@@ -520,6 +844,36 @@ void tTapeDelay_free(tTapeDelay* const dl) · 148 unmodified lines
520 leaf_free(d);844 leaf_free(d);
521}845}
522 846
847void 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
868void 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
523//#define SMOOTH_FACTOR 10.f877//#define SMOOTH_FACTOR 10.f
524 878
525float tTapeDelay_tick (tTapeDelay* const dl, float input)879float tTapeDelay_tick (tTapeDelay* const dl, float input)
@@ -534,7 +888,7 @@ float tTapeDelay_tick (tTapeDelay* const dl, float input) · 8 unmodified lines
534 int idx = (int) d->idx;888 int idx = (int) d->idx;
535 float alpha = d->idx - idx;889 float alpha = d->idx - idx;
536 890
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],
538 d->buff[idx],892 d->buff[idx],
539 d->buff[(idx + 1) % d->maxDelay],893 d->buff[(idx + 1) % d->maxDelay],
540 d->buff[(idx + 2) % d->maxDelay],894 d->buff[(idx + 2) % d->maxDelay],
@@ -585,7 +939,7 @@ float tTapeDelay_tapOut (tTapeDelay* const dl, float tapDelay) · 44 unmodified lines
585 939
586 float alpha = tap - idx;940 float alpha = tap - idx;
587 941
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],
589 d->buff[idx],943 d->buff[idx],
590 d->buff[(idx + 1) % d->maxDelay],944 d->buff[(idx + 1) % d->maxDelay],
591 d->buff[(idx + 2) % d->maxDelay],945 d->buff[(idx + 2) % d->maxDelay],
LEAF/Src/leaf-distortion.c+299−200
@@ -17,232 +17,58 @@ · 16 unmodified lines
17#include "../Inc/leaf-tables.h"17#include "../Inc/leaf-tables.h"
18 18
19//testing19//testing
20#include "gpio.h"20//#include "gpio.h"
21 21
22#endif22#endif
23 23
24//============================================================================================================24//============================================================================================================
25// WAVEFOLDER25// Sample-Rate reducer
26//============================================================================================================26//============================================================================================================
27 27
28 28
29//from the paper: Virtual Analog Model of the Lockhart Wavefolder29void tSampleReducer_init(tSampleReducer* const sr)
30//by Fabián Esqueda, Henri Pöntynen, Julian D. Parker and Stefan Bilbao
31
32void 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
56void tLockhartWavefolder_free(tLockhartWavefolder* const wf)
57{
58 _tLockhartWavefolder* w = *wf;
59
60 leaf_free(w);
61}
62
63double 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
96float tLockhartWavefolder_tick(tLockhartWavefolder* const wf, float samp)
97{30{
98 _tLockhartWavefolder* w = *wf;31 _tSampleReducer* s = *sr = (_tSampleReducer*) leaf_alloc(sizeof(_tSampleReducer));
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;
128 32
129 return out;33 s->invRatio = 1.0f;
34 s->hold = 0.0f;
35 s->count = 0;
130}36}
131 37
132//============================================================================================================38void tSampleReducer_free (tSampleReducer* const sr)
133// CRUSHER
134//============================================================================================================
135#define SCALAR 5000.f
136
137void tCrusher_init (tCrusher* const cr)
138{39{
139 _tCrusher* c = *cr = (_tCrusher*) leaf_alloc(sizeof(_tCrusher));40 _tSampleReducer* s = *sr;
140 41
141 c->op = 4;42 leaf_free(s);
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
149void tCrusher_free (tCrusher* const cr)
150{
151 _tCrusher* c = *cr;
152 tSampleReducer_free(&c->sReducer);
153 leaf_free(c);
154}43}
155 44
156float tCrusher_tick (tCrusher* const cr, float input)45void tSampleReducer_initToPool (tSampleReducer* const sr, tMempool* const mp)
157{46{
158 _tCrusher* c = *cr;47 _tMempool* m = *mp;
159 48 _tSampleReducer* s = *sr = (_tSampleReducer*) mpool_alloc(sizeof(_tSampleReducer), m->pool);
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);
173 49
174 sample = tSampleReducer_tick(&c->sReducer, sample);50 s->invRatio = 1.0f;
175 51 s->hold = 0.0f;
176 return sample * c->gain;52 s->count = 0;
177
178}
179
180void tCrusher_setOperation (tCrusher* const cr, float op)
181{
182 _tCrusher* c = *cr;
183 c->op = (uint32_t) (op * 8.0f);
184}53}
185 54
186// 0.0 - 1.055void tSampleReducer_freeFromPool (tSampleReducer* const sr, tMempool* const mp)
187void tCrusher_setQuality (tCrusher* const cr, float val)
188{56{
189 _tCrusher* c = *cr;57 _tMempool* m = *mp;
190 58 _tSampleReducer* s = *sr;
191 val = LEAF_clip(0.0f, val, 1.0f);
192
193 c->div = 0.01f + val * SCALAR;
194 59
195 c->gain = (c->div / SCALAR) * 0.7f + 0.3f;60 mpool_free(s, m->pool);
196}
197
198// what decimal to round to
199void tCrusher_setRound (tCrusher* const cr, float rnd)
200{
201 _tCrusher* c = *cr;
202 c->rnd = fabsf(rnd);
203}
204
205void 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
218void 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
230void tSampleReducer_free (tSampleReducer* const sr)
231{
232 _tSampleReducer* s = *sr;
233
234 leaf_free(s);
235}61}
236 62
237float tSampleReducer_tick(tSampleReducer* const sr, float input)63float tSampleReducer_tick(tSampleReducer* const sr, float input)
238{64{
239 _tSampleReducer* s = *sr;65 _tSampleReducer* s = *sr;
240 if (s->count > s->invRatio)66 if (s->count > s->invRatio)
241 {67 {
242 s->hold = input;68 s->hold = input;
243 s->count = 0;69 s->count = 0;
244 }70 }
245 71
246 s->count++;72 s->count++;
247 return s->hold;73 return s->hold;
248}74}
@@ -250,10 +76,10 @@ float tSampleReducer_tick(tSampleReducer* const sr, float input) · 1 unmodified line
250 76
251void tSampleReducer_setRatio(tSampleReducer* const sr, float ratio)77void tSampleReducer_setRatio(tSampleReducer* const sr, float ratio)
252{78{
253 _tSampleReducer* s = *sr;79 _tSampleReducer* s = *sr;
254 if ((ratio <= 1.0f) && (ratio >= 0.0f))80 if ((ratio <= 1.0f) && (ratio >= 0.0f))
255 s->invRatio = 1.0f / ratio;81 s->invRatio = 1.0f / ratio;
256 82
257}83}
258 84
259//============================================================================================================85//============================================================================================================
@@ -288,6 +114,36 @@ void tOversampler_free(tOversampler* const osr) · 28 unmodified lines
288 leaf_free(os);114 leaf_free(os);
289}115}
290 116
117void 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
137void 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
291float tOversampler_tick(tOversampler* const osr, float input, float (*effectTick)(float))147float tOversampler_tick(tOversampler* const osr, float input, float (*effectTick)(float))
292{148{
293 _tOversampler* os = *osr;149 _tOversampler* os = *osr;
@@ -486,3 +342,246 @@ int tOversampler_getLatency(tOversampler* const osr) · 192 unmodified lines
486 _tOversampler* os = *osr;342 _tOversampler* os = *osr;
487 return os->phaseLength;343 return os->phaseLength;
488}344}
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
354void 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
378void tLockhartWavefolder_free(tLockhartWavefolder* const wf)
379{
380 _tLockhartWavefolder* w = *wf;
381
382 leaf_free(w);
383}
384
385void 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
410void 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
418double 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
451float 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
492void 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
504void tCrusher_free (tCrusher* const cr)
505{
506 _tCrusher* c = *cr;
507 tSampleReducer_free(&c->sReducer);
508 leaf_free(c);
509}
510
511void 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
524void 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
532float 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
556void 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
563void 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
575void tCrusher_setRound (tCrusher* const cr, float rnd)
576{
577 _tCrusher* c = *cr;
578 c->rnd = fabsf(rnd);
579}
580
581void 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
63 leaf_free(c);63 leaf_free(c);
64}64}
65 65
66void tCompressor_initToPool (tCompressor* const comp, tMempool* const mp)
67{
68 _tMempool* m = *mp;
69 _tCompressor* c = *comp = (_tCompressor*) mpool_alloc(sizeof(_tCompressor), m->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
82void 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
66float tCompressor_tick(tCompressor* const comp, float in)90float tCompressor_tick(tCompressor* const comp, float in)
67{91{
68 _tCompressor* c = *comp;92 _tCompressor* c = *comp;
@@ -133,6 +157,27 @@ void tFeedbackLeveler_free(tFeedbackLeveler* const fb) · 64 unmodified lines
133 leaf_free(p);157 leaf_free(p);
134}158}
135 159
160void tFeedbackLeveler_initToPool (tFeedbackLeveler* const fb, float targetLevel, float factor, float strength, int mode, tMempool* const mp)
161{
162 _tMempool* m = *mp;
163 _tFeedbackLeveler* p = *fb = (_tFeedbackLeveler*) mpool_alloc(sizeof(_tFeedbackLeveler), m->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
172void tFeedbackLeveler_freeFromPool (tFeedbackLeveler* const fb, tMempool* const mp)
173{
174 _tMempool* m = *mp;
175 _tFeedbackLeveler* p = *fb;
176
177 tPowerFollower_freeFromPool(&p->pwrFlw, mp);
178 mpool_free(p, m->pool);
179}
180
136void tFeedbackLeveler_setStrength(tFeedbackLeveler* const fb, float strength)181void tFeedbackLeveler_setStrength(tFeedbackLeveler* const fb, float strength)
137{ // strength is how strongly level diff is affecting the amp ratio182{ // strength is how strongly level diff is affecting the amp ratio
138 // try 0.125 for a start183 // try 0.125 for a start
@@ -156,8 +201,8 @@ float tFeedbackLeveler_tick(tFeedbackLeveler* const fb, float input) · 17 unmodified lines
156{201{
157 _tFeedbackLeveler* p = *fb;202 _tFeedbackLeveler* p = *fb;
158 float levdiff=(tPowerFollower_tick(&p->pwrFlw, input)-p->targetLevel);203 float levdiff=(tPowerFollower_tick(&p->pwrFlw, input)-p->targetLevel);
159 if (p->mode==0 && levdiff<0) levdiff=0;204 if (p->mode==0 && levdiff<0.0f) levdiff=0.0f;
160 p->curr=input*(1-p->strength*levdiff);205 p->curr=input*(1.0f-p->strength*levdiff);
161 return p->curr;206 return p->curr;
162}207}
163 208
LEAF/Src/leaf-effects.c+816−529
@@ -59,6 +59,42 @@ void tTalkbox_free(tTalkbox* const voc) · 58 unmodified lines
59 leaf_free(v);59 leaf_free(v);
60}60}
61 61
62void 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
84void 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
62void tTalkbox_update(tTalkbox* const voc) ///update internal parameters...98void tTalkbox_update(tTalkbox* const voc) ///update internal parameters...
63{99{
64 _tTalkbox* v = *voc;100 _tTalkbox* v = *voc;
@@ -266,6 +302,31 @@ void tVocoder_free (tVocoder* const voc) · 201 unmodified lines
266 leaf_free(v);302 leaf_free(v);
267}303}
268 304
305void 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
322void 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
269void tVocoder_update (tVocoder* const voc)330void tVocoder_update (tVocoder* const voc)
270{331{
271 _tVocoder* v = *voc;332 _tVocoder* v = *voc;
@@ -427,319 +488,354 @@ void tVocoder_suspend (tVocoder* const voc) · 155 unmodified lines
427}488}
428 489
429//============================================================================================================490//============================================================================================================
430// RETUNE491// SOLAD
431//============================================================================================================492//============================================================================================================
493/******************************************************************************/
494/***************** static function declarations *******************************/
495/******************************************************************************/
432 496
433void tRetune_init(tRetune* const rt, int numVoices, int bufSize, int frameSize)497static void solad_init(_tSOLAD *w);
498static inline float read_sample(_tSOLAD *w, float floatindex);
499static void pitchdown(_tSOLAD *w, float *out);
500static void pitchup(_tSOLAD *w, float *out);
501
502/******************************************************************************/
503/***************** public access functions ************************************/
504/******************************************************************************/
505
506// init
507void tSOLAD_init(tSOLAD* const wp)
434{508{
435 _tRetune* r = *rt = (_tRetune*) leaf_alloc(sizeof(_tRetune));509 _tSOLAD* w = *wp = (_tSOLAD*) leaf_allocAndClear(sizeof(_tSOLAD));
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);
460 510
461 for (int i = 0; i < r->numVoices; ++i)511 w->pitchfactor = 1.;
462 {512 w->delaybuf = (float*) leaf_allocAndClear(sizeof(float) * (LOOPSIZE+16));
463 tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize);513 solad_init(w);
464 }
465}514}
466 515
467void tRetune_free(tRetune* const rt)516void tSOLAD_free(tSOLAD* const wp)
468{517{
469 _tRetune* r = *rt;518 _tSOLAD* w = *wp;
470 519
471 tPeriodDetection_free(&r->pd);520 leaf_free(w->delaybuf);
472 for (int i = 0; i < r->numVoices; ++i)521 leaf_free(w);
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);
483}522}
484 523
485float* tRetune_tick(tRetune* const rt, float sample)524void tSOLAD_initToPool (tSOLAD* const wp, tMempool* const mp)
486{525{
487 _tRetune* r = *rt;526 _tMempool* m = *mp;
488 527 _tSOLAD* w = *wp = (_tSOLAD*) mpool_allocAndClear(sizeof(_tSOLAD), m->pool);
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 }
495 528
496 return r->tickOutput;529 w->pitchfactor = 1.;
530 w->delaybuf = (float*) mpool_allocAndClear(sizeof(float) * (LOOPSIZE+16), m->pool);
531 solad_init(w);
497}532}
498 533
499void tRetune_setNumVoices(tRetune* const rt, int numVoices)534void tSOLAD_freeFromPool (tSOLAD* const wp, tMempool* const mp)
500{535{
501 _tRetune* r = *rt;536 _tMempool* m = *mp;
537 _tSOLAD* w = *wp;
502 538
503 for (int i = 0; i < r->numVoices; ++i)539 mpool_free(w->delaybuf, m->pool);
504 {540 mpool_free(w, m->pool);
505 tPitchShift_free(&r->ps[i]);541}
506 leaf_free(r->outBuffers[i]);542
507 }543// send one block of input samples, receive one block of output samples
508 leaf_free(r->tickOutput);544void tSOLAD_ioSamples(tSOLAD* const wp, float* in, float* out, int blocksize)
509 leaf_free(r->pitchFactor);545{
510 leaf_free(r->ps);546 _tSOLAD* w = *wp;
511 leaf_free(r->outBuffers);
512 547
513 r->numVoices = numVoices;548 int i = w->timeindex;
549 int n = w->blocksize = blocksize;
514 550
515 r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices);551 if(!i) w->delaybuf[LOOPSIZE] = in[0]; // copy one sample for interpolation
516 r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices);552 while(n--) w->delaybuf[i++] = *in++; // copy one input block to delay buffer
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 }
524 553
554 if(w->pitchfactor > 1) pitchup(w, out);
555 else pitchdown(w, out);
525 556
557 w->timeindex += blocksize;
558 w->timeindex &= LOOPMASK;
526}559}
527 560
528void tRetune_setPitchFactors(tRetune* const rt, float pf)561// set periodicity analysis data
562void tSOLAD_setPeriod(tSOLAD* const wp, float period)
529{563{
530 _tRetune* r = *rt;564 _tSOLAD* w = *wp;
531 565
532 for (int i = 0; i < r->numVoices; ++i)566 if(period > MAXPERIOD) period = MAXPERIOD;
533 {567 if(period > MINPERIOD) w->period = period; // ignore period when too small
534 r->pitchFactor[i] = pf;
535 tPitchShift_setPitchFactor(&r->ps[i], r->pitchFactor[i]);
536 }
537}568}
538 569
539void tRetune_setPitchFactor(tRetune* const rt, float pf, int voice)570// set pitch factor between 0.25 and 4
571void tSOLAD_setPitchFactor(tSOLAD* const wp, float pitchfactor)
540{572{
541 _tRetune* r = *rt;573 _tSOLAD* w = *wp;
542 574
543 r->pitchFactor[voice] = pf;575 if (pitchfactor <= 0.0f) return;
544 tPitchShift_setPitchFactor(&r->ps[voice], r->pitchFactor[voice]);576 w->pitchfactor = pitchfactor;
545}577}
546 578
547void tRetune_setTimeConstant(tRetune* const rt, float tc)579// force readpointer lag
580void tSOLAD_setReadLag(tSOLAD* const wp, float readlag)
548{581{
549 _tRetune* r = *rt;582 _tSOLAD* w = *wp;
550 583
551 r->timeConstant = tc;584 if(readlag < 0) readlag = 0;
552 r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant);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 }
553}592}
554 593
555void tRetune_setHopSize(tRetune* const rt, int hs)594// reset state variables
595void tSOLAD_resetState(tSOLAD* const wp)
556{596{
557 _tRetune* r = *rt;597 _tSOLAD* w = *wp;
558 598
559 r->hopSize = hs;599 int n = LOOPSIZE + 1;
560 tPeriodDetection_setHopSize(&r->pd, r->hopSize);600 float *buf = w->delaybuf;
561}
562
563void tRetune_setWindowSize(tRetune* const rt, int ws)
564{
565 _tRetune* r = *rt;
566 601
567 r->windowSize = ws;602 while(n--) *buf++ = 0;
568 tPeriodDetection_setWindowSize(&r->pd, r->windowSize);603 solad_init(w);
569}604}
570 605
571float tRetune_getInputPeriod(tRetune* const rt)606/******************************************************************************/
572{607/******************** private procedures **************************************/
573 _tRetune* r = *rt;608/******************************************************************************/
574
575 return r->inputPeriod;
576}
577 609
578float tRetune_getInputFreq(tRetune* const rt)610/*
579{611 Function pitchdown() is called to read samples from the delay buffer when pitch
580 _tRetune* r = *rt;612 factor is between 0.25 and 1. The read pointer lags behind because of the slowed
581 613 down speed, and it must jump forward towards the write pointer soon as there is
582 return 1.0f/r->inputPeriod;614 sufficient space to jump. That is, if there is at least one period of the input
583}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 */
584 636
585//============================================================================================================
586// AUTOTUNE
587//============================================================================================================
588 637
589void tAutotune_init(tAutotune* const rt, int numVoices, int bufSize, int frameSize)638static void pitchdown(_tSOLAD* const w, float *out)
590{639{
591 _tAutotune* r = *rt = (_tAutotune*) leaf_alloc(sizeof(_tAutotune));640 int n = w->blocksize;
592 641 float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values!
593 r->bufSize = bufSize;642 float pitchfactor = w->pitchfactor;
594 r->frameSize = frameSize;643 float period = w->period;
595 r->numVoices = numVoices;644 float readlag = w->readlag;
596 645 float readlagstep = 1 - pitchfactor;
597 r->inBuffer = (float*) leaf_alloc(sizeof(float) * r->bufSize);646 float jump = w->jump;
598 r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices);647 float xfadevalue = w->xfadevalue;
599 648 float xfadelength = w->xfadelength;
600 r->hopSize = DEFHOPSIZE;649 float xfadespeed, xfadestep, readindex, outputsample;
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 }
614 650
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;
616 654
617 for (int i = 0; i < r->numVoices; ++i)655 while(n--)
618 {656 {
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;
620 }683 }
621 684
622 r->inputPeriod = 0.0f;685 w->jump = jump; // state variables
623}686 w->readlag = readlag;
624 687 w->xfadevalue = xfadevalue;
625void tAutotune_free(tAutotune* const rt)688 w->xfadelength = xfadelength;
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);
641}689}
642 690
643float* 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 }
657 691
658 return r->tickOutput;692/*
659}693 Function pitchup() for pitch factors above 1 is more complicated than
660 694 pitchdown(). The read pointer increments faster than the write pointer and a
661void tAutotune_setNumVoices(tAutotune* const rt, int numVoices)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 */
756static void pitchup(_tSOLAD* const w, float *out)
662{757{
663 _tAutotune* r = *rt;758 int n = w->blocksize;
664 759 float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values
665 for (int i = 0; i < r->numVoices; ++i)760 float pitchfactor = w->pitchfactor;
666 {761 float period = w->period;
667 tPitchShift_free(&r->ps[i]);762 float readlag = w->readlag;
668 leaf_free(r->outBuffers[i]);763 float jump = w->jump;
669 }764 float xfadevalue = w->xfadevalue;
670 leaf_free(r->tickOutput);765 float xfadelength = w->xfadelength;
671 leaf_free(r->freq);
672 leaf_free(r->ps);
673 leaf_free(r->outBuffers);
674 766
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;
676 773
677 r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices);774 if((readlag > (period + 2 * limit)) & (xfadevalue < 0))
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)
682 {775 {
683 r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize);776 jump = period; // jump forward
684 tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize);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;
685 }782 }
686 783
687 784 while(n--)
688}
689
690void tAutotune_setFreqs(tAutotune* const rt, float f)
691{
692 _tAutotune* r = *rt;
693
694 for (int i = 0; i < r->numVoices; ++i)
695 {785 {
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;
697 }813 }
698}
699
700void tAutotune_setFreq(tAutotune* const rt, float f, int voice)
701{
702 _tAutotune* r = *rt;
703 814
704 r->freq[voice] = f;815 w->readlag = readlag; // state variables
705}816 w->jump = jump;
706 817 w->xfadelength = xfadelength;
707void tAutotune_setTimeConstant(tAutotune* const rt, float tc)818 w->xfadevalue = xfadevalue;
708{
709 _tAutotune* r = *rt;
710
711 r->timeConstant = tc;
712 r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant);
713}
714
715void 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
723void tAutotune_setWindowSize(tAutotune* const rt, int ws)
724{
725 _tAutotune* r = *rt;
726
727 r->windowSize = ws;
728 tPeriodDetection_setWindowSize(&r->pd, r->windowSize);
729}819}
730 820
731float tAutotune_getInputPeriod(tAutotune* const rt)821// read one sample from delay buffer, with linear interpolation
822static inline float read_sample(_tSOLAD* const w, float floatindex)
732{823{
733 _tAutotune* r = *rt;824 int index = (int)floatindex;
825 float fraction = floatindex - (float)index;
826 float *buf = w->delaybuf;
827 index &= LOOPMASK;
734 828
735 return r->inputPeriod;829 return (buf[index] + (fraction * (buf[index+1] - buf[index])));
736}830}
737 831
738float tAutotune_getInputFreq(tAutotune* const rt)832static void solad_init(_tSOLAD* const w)
739{833{
740 _tAutotune* r = *rt;834 w->timeindex = 0;
741 835 w->xfadevalue = -1;
742 return 1.0f/r->inputPeriod;836 w->period = INITPERIOD;
837 w->readlag = INITPERIOD;
838 w->blocksize = INITPERIOD;
743}839}
744 840
745//============================================================================================================841//============================================================================================================
@@ -776,7 +872,7 @@ static int pitchshift_attackdetect(_tPitchShift* ps) · 30 unmodified lines
776 872
777void tPitchShift_init (tPitchShift* const psr, tPeriodDetection* pd, float* out, int bufSize)873void tPitchShift_init (tPitchShift* const psr, tPeriodDetection* pd, float* out, int bufSize)
778{874{
779 _tPitchShift* ps = *psr = (_tPitchShift*) leaf_alloc(sizeof(_tPitchShift));875 _tPitchShift* ps = *psr = (_tPitchShift*) leaf_allocAndClear(sizeof(_tPitchShift));
780 _tPeriodDetection* p = *pd;876 _tPeriodDetection* p = *pd;
781 877
782 ps->p = pd;878 ps->p = pd;
@@ -806,6 +902,40 @@ void tPitchShift_free(tPitchShift* const psr) · 23 unmodified lines
806 leaf_free(ps);902 leaf_free(ps);
807}903}
808 904
905void 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
929void 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
809void tPitchShift_setPitchFactor(tPitchShift* psr, float pf)939void tPitchShift_setPitchFactor(tPitchShift* psr, float pf)
810{940{
811 _tPitchShift* ps = *psr;941 _tPitchShift* ps = *psr;
@@ -916,340 +1046,435 @@ float tPitchShift_shiftToFunc (tPitchShift* psr, float (*fun)(float)) · 104 unmodified lines
916 if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;1046 if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
917 }1047 }
918 1048
919 return out;1049 return out;
1050}
1051
1052//============================================================================================================
1053// RETUNE
1054//============================================================================================================
1055
1056void 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
1090void 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
1108void 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
1143void 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
1162float* 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
1176void 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
920}1203}
921 1204
922//============================================================================================================1205void tRetune_setPitchFactors(tRetune* const rt, float pf)
923// SOLAD
924//============================================================================================================
925/******************************************************************************/
926/***************** static function declarations *******************************/
927/******************************************************************************/
928
929static void solad_init(_tSOLAD *w);
930static inline float read_sample(_tSOLAD *w, float floatindex);
931static void pitchdown(_tSOLAD *w, float *out);
932static void pitchup(_tSOLAD *w, float *out);
933
934/******************************************************************************/
935/***************** public access functions ************************************/
936/******************************************************************************/
937
938// init
939void tSOLAD_init(tSOLAD* const wp)
940{1206{
941 _tSOLAD* w = *wp = (_tSOLAD*) leaf_alloc(sizeof(_tSOLAD));1207 _tRetune* r = *rt;
942 1208
943 w->pitchfactor = 1.;1209 for (int i = 0; i < r->numVoices; ++i)
944 w->delaybuf = (float*) leaf_alloc(sizeof(float) * (LOOPSIZE+16));1210 {
945 solad_init(w);1211 r->pitchFactor[i] = pf;
1212 tPitchShift_setPitchFactor(&r->ps[i], r->pitchFactor[i]);
1213 }
946}1214}
947 1215
948void tSOLAD_free(tSOLAD* const wp)1216void tRetune_setPitchFactor(tRetune* const rt, float pf, int voice)
949{1217{
950 _tSOLAD* w = *wp;1218 _tRetune* r = *rt;
951 1219
952 leaf_free(w->delaybuf);1220 r->pitchFactor[voice] = pf;
953 leaf_free(w);1221 tPitchShift_setPitchFactor(&r->ps[voice], r->pitchFactor[voice]);
954}1222}
955 1223
956// send one block of input samples, receive one block of output samples1224void tRetune_setTimeConstant(tRetune* const rt, float tc)
957void tSOLAD_ioSamples(tSOLAD* const wp, float* in, float* out, int blocksize)
958{1225{
959 _tSOLAD* w = *wp;1226 _tRetune* r = *rt;
960
961 int i = w->timeindex;
962 int n = w->blocksize = blocksize;
963 1227
964 if(!i) w->delaybuf[LOOPSIZE] = in[0]; // copy one sample for interpolation1228 r->timeConstant = tc;
965 while(n--) w->delaybuf[i++] = *in++; // copy one input block to delay buffer1229 r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant);
1230}
1231
1232void tRetune_setHopSize(tRetune* const rt, int hs)
1233{
1234 _tRetune* r = *rt;
966 1235
967 if(w->pitchfactor > 1) pitchup(w, out);1236 r->hopSize = hs;
968 else pitchdown(w, out);1237 tPeriodDetection_setHopSize(&r->pd, r->hopSize);
1238}
1239
1240void tRetune_setWindowSize(tRetune* const rt, int ws)
1241{
1242 _tRetune* r = *rt;
969 1243
970 w->timeindex += blocksize;1244 r->windowSize = ws;
971 w->timeindex &= LOOPMASK;1245 tPeriodDetection_setWindowSize(&r->pd, r->windowSize);
972}1246}
973 1247
974// set periodicity analysis data1248float tRetune_getInputPeriod(tRetune* const rt)
975void tSOLAD_setPeriod(tSOLAD* const wp, float period)
976{1249{
977 _tSOLAD* w = *wp;1250 _tRetune* r = *rt;
978 1251
979 if(period > MAXPERIOD) period = MAXPERIOD;1252 return r->inputPeriod;
980 if(period > MINPERIOD) w->period = period; // ignore period when too small
981}1253}
982 1254
983// set pitch factor between 0.25 and 41255float tRetune_getInputFreq(tRetune* const rt)
984void tSOLAD_setPitchFactor(tSOLAD* const wp, float pitchfactor)
985{1256{
986 _tSOLAD* w = *wp;1257 _tRetune* r = *rt;
987 1258
988 if (pitchfactor <= 0.0f) return;1259 return 1.0f/r->inputPeriod;
989 w->pitchfactor = pitchfactor;
990}1260}
991 1261
992// force readpointer lag1262//============================================================================================================
993void tSOLAD_setReadLag(tSOLAD* const wp, float readlag)1263// AUTOTUNE
1264//============================================================================================================
1265
1266void tAutotune_init(tAutotune* const rt, int numVoices, int bufSize, int frameSize)
994{1267{
995 _tSOLAD* w = *wp;1268 _tAutotune* r = *rt = (_tAutotune*) leaf_alloc(sizeof(_tAutotune));
996 1269
997 if(readlag < 0) readlag = 0;1270 r->bufSize = bufSize;
998 if(readlag < w->readlag) // do not jump backward, only forward1271 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)
999 {1288 {
1000 w->jump = w->readlag - readlag;1289 r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize);
1001 w->readlag = readlag;
1002 w->xfadelength = readlag;
1003 w->xfadevalue = 1;
1004 }1290 }
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;
1005}1300}
1006 1301
1007// reset state variables1302void tAutotune_free(tAutotune* const rt)
1008void tSOLAD_resetState(tSOLAD* const wp)
1009{1303{
1010 _tSOLAD* w = *wp;1304 _tAutotune* r = *rt;
1011
1012 int n = LOOPSIZE + 1;
1013 float *buf = w->delaybuf;
1014 1305
1015 while(n--) *buf++ = 0;1306 tPeriodDetection_free(&r->pd);
1016 solad_init(w);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);
1017}1318}
1018 1319
1019/******************************************************************************/1320void tAutotune_initToPool (tAutotune* const rt, int numVoices, int bufSize, int frameSize, tMempool* const mp)
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
1051static void pitchdown(_tSOLAD* const w, float *out)
1052{1321{
1053 int n = w->blocksize;1322 _tMempool* m = *mp;
1054 float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values!1323 _tAutotune* r = *rt = (_tAutotune*) mpool_alloc(sizeof(_tAutotune), m->pool);
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;
1063 1324
1064 if(pitchfactor > 0.5) xfadespeed = pitchfactor;1325 r->bufSize = bufSize;
1065 else xfadespeed = 1 - pitchfactor;1326 r->frameSize = frameSize;
1066 xfadestep = xfadespeed / xfadelength;1327 r->numVoices = numVoices;
1067 1328
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)
1069 {1343 {
1070 if(readlag > period) // check if read pointer may jump forward...1344 r->outBuffers[i] = (float*) mpool_alloc(sizeof(float) * r->bufSize, m->pool);
1071 {1345 }
1072 if(xfadevalue <= 0) // ...but do not interrupt crossfade1346
1073 {1347 tPeriodDetection_initToPool(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize, mp);
1074 jump = period; // jump forward1348
1075 while((jump * 2) < readlag) jump *= 2; // use available space1349 for (int i = 0; i < r->numVoices; ++i)
1076 readlag -= jump; // reduce read pointer lag1350 {
1077 xfadevalue = 1; // start crossfade1351 tPitchShift_initToPool(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize, mp);
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;
1096 }1352 }
1097 1353
1098 w->jump = jump; // state variables1354 r->inputPeriod = 0.0f;
1099 w->readlag = readlag;
1100 w->xfadevalue = xfadevalue;
1101 w->xfadelength = xfadelength;
1102}1355}
1103 1356
1357void 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}
1104 1375
1105/*1376float* tAutotune_tick(tAutotune* const rt, float sample)
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 */
1169static void pitchup(_tSOLAD* const w, float *out)
1170{1377{
1171 int n = w->blocksize;1378 _tAutotune* r = *rt;
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;
1179 1379
1180 float readlagstep = pitchfactor - 1;1380 float tempPeriod = tPeriodDetection_findPeriod(&r->pd, sample);
1181 float xfadespeed = pitchfactor * pitchfactor;1381 if (tempPeriod < 1000.0f) //to avoid trying to follow consonants JS
1182 float xfadestep = xfadespeed / xfadelength;1382 {
1183 float limitfactor = (pitchfactor - (float)0.99) / xfadespeed;1383 r->inputPeriod = tempPeriod;
1184 float limit = period * limitfactor;1384 }
1185 float readindex, outputsample;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
1394void tAutotune_setNumVoices(tAutotune* const rt, int numVoices)
1395{
1396 _tAutotune* r = *rt;
1186 1397
1187 if((readlag > (period + 2 * limit)) & (xfadevalue < 0))1398 for (int i = 0; i < r->numVoices; ++i)
1188 {1399 {
1189 jump = period; // jump forward1400 tPitchShift_free(&r->ps[i]);
1190 while((jump * 2) < (readlag - 2 * limit)) jump *= 2; // use available space1401 leaf_free(r->outBuffers[i]);
1191 readlag -= jump; // reduce read pointer lag
1192 xfadevalue = 1; // start crossfade
1193 xfadelength = period - 1;
1194 xfadestep = xfadespeed / xfadelength;
1195 }1402 }
1403 leaf_free(r->tickOutput);
1404 leaf_free(r->freq);
1405 leaf_free(r->ps);
1406 leaf_free(r->outBuffers);
1196 1407
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)
1198 {1415 {
1199 if(readlag < limit) // check if read pointer should jump backward...1416 r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize);
1200 {1417 tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize);
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;
1226 }1418 }
1227 1419
1228 w->readlag = readlag; // state variables1420
1229 w->jump = jump;
1230 w->xfadelength = xfadelength;
1231 w->xfadevalue = xfadevalue;
1232}1421}
1233 1422
1234// read one sample from delay buffer, with linear interpolation1423void tAutotune_setFreqs(tAutotune* const rt, float f)
1235static inline float read_sample(_tSOLAD* const w, float floatindex)
1236{1424{
1237 int index = (int)floatindex;1425 _tAutotune* r = *rt;
1238 float fraction = floatindex - (float)index;
1239 float *buf = w->delaybuf;
1240 index &= LOOPMASK;
1241 1426
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 }
1243}1431}
1244 1432
1245static void solad_init(_tSOLAD* const w)1433void tAutotune_setFreq(tAutotune* const rt, float f, int voice)
1246{1434{
1247 w->timeindex = 0;1435 _tAutotune* r = *rt;
1248 w->xfadevalue = -1;1436
1249 w->period = INITPERIOD;1437 r->freq[voice] = f;
1250 w->readlag = INITPERIOD;1438}
1251 w->blocksize = INITPERIOD;1439
1440void 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
1448void 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
1456void 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
1464float tAutotune_getInputPeriod(tAutotune* const rt)
1465{
1466 _tAutotune* r = *rt;
1467
1468 return r->inputPeriod;
1469}
1470
1471float tAutotune_getInputFreq(tAutotune* const rt)
1472{
1473 _tAutotune* r = *rt;
1474
1475 return 1.0f/r->inputPeriod;
1252}1476}
1477
1253//============================================================================================================1478//============================================================================================================
1254// FORMANTSHIFTER1479// FORMANTSHIFTER
1255//============================================================================================================1480//============================================================================================================
@@ -1289,8 +1514,8 @@ void tFormantShifter_init(tFormantShifter* const fsr, int bufsize, int order) · 33 unmodified lines
1289 fs->invIntensity = 1.0f;1514 fs->invIntensity = 1.0f;
1290 tHighpass_init(&fs->hp, 20.0f);1515 tHighpass_init(&fs->hp, 20.0f);
1291 tHighpass_init(&fs->hp2, 20.0f);1516 tHighpass_init(&fs->hp2, 20.0f);
1292 tFeedbackLeveler_init(&fs->fbl1, 0.8f, .005f, 0.125, 1);1517 tFeedbackLeveler_init(&fs->fbl1, 0.8f, 0.01f, 0.125f, 0);
1293 tFeedbackLeveler_init(&fs->fbl2, 0.8f, .005f, 0.125, 1);1518 tFeedbackLeveler_init(&fs->fbl2, 0.8f, 0.01f, 0.125f, 0);
1294}1519}
1295 1520
1296void tFormantShifter_free(tFormantShifter* const fsr)1521void tFormantShifter_free(tFormantShifter* const fsr)
@@ -1317,6 +1542,68 @@ void tFormantShifter_free(tFormantShifter* const fsr) · 20 unmodified lines
1317 leaf_free(fs);1542 leaf_free(fs);
1318}1543}
1319 1544
1545void 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
1583void 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}
1320 1607
1321float tFormantShifter_tick(tFormantShifter* const fsr, float in)1608float tFormantShifter_tick(tFormantShifter* const fsr, float in)
1322{1609{
@@ -1326,8 +1613,8 @@ float tFormantShifter_tick(tFormantShifter* const fsr, float in) · 3 unmodified lines
1326float tFormantShifter_remove(tFormantShifter* const fsr, float in)1613float tFormantShifter_remove(tFormantShifter* const fsr, float in)
1327{1614{
1328 _tFormantShifter* fs = *fsr;1615 _tFormantShifter* fs = *fsr;
1329 in = tFeedbackLeveler_tick(&fs->fbl1, in);1616 in = tFeedbackLeveler_tick(&fs->fbl1, in * fs->intensity);
1330 in = tHighpass_tick(&fs->hp, tanhf(in * fs->intensity));1617 in = tHighpass_tick(&fs->hp, in);
1331 1618
1332 1619
1333 float fa, fb, fc, foma, falph, ford, flamb, tf, fk;1620 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
1363 {1650 {
1364 fs->cbi = 0;1651 fs->cbi = 0;
1365 }1652 }
1366 1653 return fa;
1367 return fa * fs->invIntensity;1654 //return fa * fs->invIntensity;
1368}1655}
1369 1656
1370float tFormantShifter_add(tFormantShifter* const fsr, float in)1657float tFormantShifter_add(tFormantShifter* const fsr, float in)
@@ -1460,8 +1747,8 @@ float tFormantShifter_add(tFormantShifter* const fsr, float in) · 89 unmodified lines
1460 fs->fmute = (1.0f-tf2) + tf2*fs->fmute;1747 fs->fmute = (1.0f-tf2) + tf2*fs->fmute;
1461 // now tf is signal output1748 // now tf is signal output
1462 // ...and we're done messing with formants1749 // ...and we're done messing with formants
1463 tf = tFeedbackLeveler_tick(&fs->fbl2, tf);1750 //tf = tFeedbackLeveler_tick(&fs->fbl2, tf);
1464 //tf = tHighpass_tick(&fs->hp2, tanhf(tf));1751 tf = tHighpass_tick(&fs->hp2, tanhf(tf));
1465 1752
1466 return tf;1753 return tf;
1467}1754}
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
45static float get_reflected_wave_for_diode(tWDF* const n, float input, float incident_wave);45static float get_reflected_wave_for_diode(tWDF* const n, float input, float incident_wave);
46static float get_reflected_wave_for_diode_pair(tWDF* const n, float input, float incident_wave);46static float get_reflected_wave_for_diode_pair(tWDF* const n, float input, float incident_wave);
47 47
48//WDF48static void wdf_init(tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR)
49void tWDF_init(tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR)
50{49{
51 _tWDF* r = *wdf = (_tWDF*) leaf_alloc(sizeof(_tWDF));50 _tWDF* r = *wdf;
52 51
53 r->type = type;52 r->type = type;
54 r->child_left = rL;53 r->child_left = rL;
55 r->child_right = rR;54 r->child_right = rR;
56 r->incident_wave_up = 0.0f;55 r->incident_wave_up = 0.0f;
57 r->incident_wave_left = 0.0f;56 r->incident_wave_left = 0.0f;
58 r->incident_wave_right = 0.0f;57 r->incident_wave_right = 0.0f;
59 r->reflected_wave_up = 0.0f;58 r->reflected_wave_up = 0.0f;
60 r->reflected_wave_left = 0.0f;59 r->reflected_wave_left = 0.0f;
61 r->reflected_wave_right = 0.0f;60 r->reflected_wave_right = 0.0f;
62 r->sample_rate = leaf.sampleRate;61 r->sample_rate = leaf.sampleRate;
63 r->value = value;62 r->value = value;
64 63
65 tWDF* child;64 tWDF* child;
66 if (r->child_left != NULL) child = r->child_left;65 if (r->child_left != NULL) child = r->child_left;
67 else child = r->child_right;66 else child = r->child_right;
68 67
69 if (r->type == Resistor)68 if (r->type == Resistor)
70 {69 {
71 r->port_resistance_up = r->value;70 r->port_resistance_up = r->value;
72 r->port_conductance_up = 1.0f / r->value;71 r->port_conductance_up = 1.0f / r->value;
73 72
74 r->get_port_resistance = &get_port_resistance_for_resistor;73 r->get_port_resistance = &get_port_resistance_for_resistor;
75 r->get_reflected_wave_up = &get_reflected_wave_for_resistor;74 r->get_reflected_wave_up = &get_reflected_wave_for_resistor;
76 r->set_incident_wave = &set_incident_wave_for_leaf;75 r->set_incident_wave = &set_incident_wave_for_leaf;
77 }76 }
78 else if (r->type == Capacitor)77 else if (r->type == Capacitor)
79 {78 {
80 r->port_conductance_up = r->sample_rate * 2.0f * r->value;79 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 discretization80 r->port_resistance_up = 1.0f / r->port_conductance_up; //based on trapezoidal discretization
82 81
83 r->get_port_resistance = &get_port_resistance_for_capacitor;82 r->get_port_resistance = &get_port_resistance_for_capacitor;
84 r->get_reflected_wave_up = &get_reflected_wave_for_capacitor;83 r->get_reflected_wave_up = &get_reflected_wave_for_capacitor;
85 r->set_incident_wave = &set_incident_wave_for_leaf;84 r->set_incident_wave = &set_incident_wave_for_leaf;
86 }85 }
87 else if (r->type == Inductor)86 else if (r->type == Inductor)
88 {87 {
89 r->port_resistance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization88 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
93 r->get_reflected_wave_up = &get_reflected_wave_for_capacitor; // same as capacitor92 r->get_reflected_wave_up = &get_reflected_wave_for_capacitor; // same as capacitor
94 r->set_incident_wave = &set_incident_wave_for_leaf_inverted;93 r->set_incident_wave = &set_incident_wave_for_leaf_inverted;
95 }94 }
96 else if (r->type == ResistiveSource)95 else if (r->type == ResistiveSource)
97 {96 {
98 r->port_resistance_up = r->value;97 r->port_resistance_up = r->value;
99 r->port_conductance_up = 1.0f / r->port_resistance_up;98 r->port_conductance_up = 1.0f / r->port_resistance_up;
100 99
101 r->get_port_resistance = &get_port_resistance_for_resistive;100 r->get_port_resistance = &get_port_resistance_for_resistive;
102 r->get_reflected_wave_up = &get_reflected_wave_for_resistive;101 r->get_reflected_wave_up = &get_reflected_wave_for_resistive;
103 r->set_incident_wave = &set_incident_wave_for_leaf;102 r->set_incident_wave = &set_incident_wave_for_leaf;
104 }103 }
105 else if (r->type == Inverter)104 else if (r->type == Inverter)
106 {105 {
107 r->port_resistance_up = tWDF_getPortResistance(r->child_left);106 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
164 r->get_port_resistance = &get_port_resistance_for_root;163 r->get_port_resistance = &get_port_resistance_for_root;
165 }164 }
166}165}
166//WDF
167void tWDF_init(tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR)
168{
169 *wdf = (_tWDF*) leaf_alloc(sizeof(_tWDF));
170
171 wdf_init(wdf, type, value, rL, rR);
172}
167 173
168void tWDF_free(tWDF* const wdf)174void tWDF_free(tWDF* const wdf)
169{175{
@@ -172,6 +178,22 @@ void tWDF_free(tWDF* const wdf) · 2 unmodified lines
172 leaf_free(r);178 leaf_free(r);
173}179}
174 180
181void tWDF_initToPool (tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR, tMempool* const mp)
182{
183 _tMempool* m = *mp;
184 *wdf = (_tWDF*) mpool_alloc(sizeof(_tWDF), m->pool);
185
186 wdf_init(wdf, type, value, rL, rR);
187}
188
189void tWDF_freeFromPool (tWDF* const wdf, tMempool* const mp)
190{
191 _tMempool* m = *mp;
192 _tWDF* r = *wdf;
193
194 mpool_free(r, m->pool);
195}
196
175float tWDF_tick(tWDF* const wdf, float sample, tWDF* const outputPoint, uint8_t paramsChanged)197float tWDF_tick(tWDF* const wdf, float sample, tWDF* const outputPoint, uint8_t paramsChanged)
176{198{
177 _tWDF* r = *wdf;199 _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
62 env->attackInc = env->inc_buff[attackIndex];62 env->attackInc = env->inc_buff[attackIndex];
63 env->decayInc = env->inc_buff[decayIndex];63 env->decayInc = env->inc_buff[decayIndex];
64 env->rampInc = env->inc_buff[rampIndex];64 env->rampInc = env->inc_buff[rampIndex];
65
66}65}
67 66
68void tEnvelope_free(tEnvelope* const envlp)67void tEnvelope_free(tEnvelope* const envlp)
@@ -71,6 +70,54 @@ void tEnvelope_free(tEnvelope* const envlp) · 2 unmodified lines
71 leaf_free(env);70 leaf_free(env);
72}71}
73 72
73void 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
114void 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
74void tEnvelope_setAttack(tEnvelope* const envlp, float attack)121void tEnvelope_setAttack(tEnvelope* const envlp, float attack)
75{122{
76 _tEnvelope* env = *envlp;123 _tEnvelope* env = *envlp;
@@ -270,6 +317,71 @@ void tADSR_free(tADSR* const adsrenv) · 193 unmodified lines
270 leaf_free(adsr);317 leaf_free(adsr);
271}318}
272 319
320void 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
377void 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
273void tADSR_setAttack(tADSR* const adsrenv, float attack)385void tADSR_setAttack(tADSR* const adsrenv, float attack)
274{386{
275 _tADSR* adsr = *adsrenv;387 _tADSR* adsr = *adsrenv;
@@ -479,6 +591,37 @@ void tRamp_free(tRamp* const r) · 203 unmodified lines
479 leaf_free(ramp);591 leaf_free(ramp);
480}592}
481 593
594void 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
617void 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
482void tRamp_setTime(tRamp* const ramp, float time)625void tRamp_setTime(tRamp* const ramp, float time)
483{626{
484 _tRamp* r = *ramp;627 _tRamp* r = *ramp;
@@ -560,6 +703,27 @@ void tExpSmooth_free(tExpSmooth* const expsmooth) · 75 unmodified lines
560 leaf_free(smooth);703 leaf_free(smooth);
561}704}
562 705
706void 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
719void 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
563void tExpSmooth_setFactor(tExpSmooth* const expsmooth, float factor)727void tExpSmooth_setFactor(tExpSmooth* const expsmooth, float factor)
564{ // 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 10ms728{ // 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
565 _tExpSmooth* smooth = *expsmooth;729 _tExpSmooth* smooth = *expsmooth;
LEAF/Src/leaf-filters.c+551−283
@@ -40,6 +40,27 @@ void tAllpass_free(tAllpass* const ft) · 39 unmodified lines
40 leaf_free(f);40 leaf_free(f);
41}41}
42 42
43void tAllpass_initToPool (tAllpass* const ft, float initDelay, uint32_t maxDelay, tMempool* const mp)
44{
45 _tMempool* m = *mp;
46 _tAllpass* f = *ft = (_tAllpass*) mpool_alloc(sizeof(_tAllpass), m->pool);
47
48 f->gain = 0.7f;
49
50 f->lastOut = 0.0f;
51
52 tLinearDelay_initToPool(&f->delay, initDelay, maxDelay, mp);
53}
54
55void tAllpass_freeFromPool (tAllpass* const ft, tMempool* const mp)
56{
57 _tMempool* m = *mp;
58 _tAllpass* f = *ft;
59
60 tLinearDelay_freeFromPool(&f->delay, mp);
61 mpool_free(f, m->pool);
62}
63
43void tAllpass_setDelay(tAllpass* const ft, float delay)64void tAllpass_setDelay(tAllpass* const ft, float delay)
44{65{
45 _tAllpass* f = *ft;66 _tAllpass* f = *ft;
@@ -67,77 +88,236 @@ float tAllpass_tick(tAllpass* const ft, float input) · 21 unmodified lines
67 return f->lastOut;88 return f->lastOut;
68}89}
69 90
70void tButterworth_init(tButterworth* const ft, int N, float f1, float f2)91// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
92void tOnePole_init(tOnePole* const ft, float freq)
71{93{
72 _tButterworth* f = *ft = (_tButterworth*) leaf_alloc(sizeof(_tButterworth));94 _tOnePole* f = *ft = (_tOnePole*) leaf_alloc(sizeof(_tOnePole));
73 95
74 f->f1 = f1;96 f->gain = 1.0f;
75 f->f2 = f2;97 f->a0 = 1.0;
76 f->gain = 1.0f;
77 98
78 f->N = N;99 tOnePole_setFreq(ft, freq);
79 100
80 if (f->N > NUM_SVF_BW) f->N = NUM_SVF_BW;101 f->lastIn = 0.0f;
102 f->lastOut = 0.0f;
103}
81 104
82 for(int i = 0; i < N/2; ++i)105void tOnePole_free(tOnePole* const ft)
83 {106{
84 tSVF_init(&f->low[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)));107 _tOnePole* f = *ft;
85 tSVF_init(&f->high[i], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)));108
86 }109 leaf_free(f);
87}110}
88 111
89void tButterworth_free(tButterworth* const ft)112void tOnePole_initToPool (tOnePole* const ft, float freq, tMempool* const mp)
90{113{
91 _tButterworth* f = *ft;114 _tMempool* m = *mp;
115 _tOnePole* f = *ft = (_tOnePole*) mpool_alloc(sizeof(_tOnePole), m->pool);
92 116
93 for(int i = 0; i < f->N/2; ++i)117 f->gain = 1.0f;
94 {118 f->a0 = 1.0;
95 tSVF_free(&f->low[i]);119
96 tSVF_free(&f->high[i]);120 tOnePole_setFreq(ft, freq);
97 }121
122 f->lastIn = 0.0f;
123 f->lastOut = 0.0f;
124}
125
126void tOnePole_freeFromPool (tOnePole* const ft, tMempool* const mp)
127{
128 _tMempool* m = *mp;
129 _tOnePole* f = *ft;
130
131 mpool_free(f, m->pool);
132}
133
134void tOnePole_setB0(tOnePole* const ft, float b0)
135{
136 _tOnePole* f = *ft;
137 f->b0 = b0;
138}
139
140void tOnePole_setA1(tOnePole* const ft, float a1)
141{
142 _tOnePole* f = *ft;
143 if (a1 >= 1.0f) a1 = 0.999999f;
144 f->a1 = a1;
145}
146
147void tOnePole_setPole(tOnePole* const ft, float thePole)
148{
149 _tOnePole* f = *ft;
150
151 if (thePole >= 1.0f) thePole = 0.999999f;
152
153 // Normalize coefficients for peak unity gain.
154 if (thePole > 0.0f) f->b0 = (1.0f - thePole);
155 else f->b0 = (1.0f + thePole);
156
157 f->a1 = -thePole;
158}
159
160void tOnePole_setFreq (tOnePole* const ft, float freq)
161{
162 _tOnePole* f = *ft;
163 f->b0 = freq * leaf.twoPiTimesInvSampleRate;
164 f->b0 = LEAF_clip(0.0f, f->b0, 1.0f);
165 f->a1 = 1.0f - f->b0;
166}
167
168void tOnePole_setCoefficients(tOnePole* const ft, float b0, float a1)
169{
170 _tOnePole* f = *ft;
171 if (a1 >= 1.0f) a1 = 0.999999f;
172 f->b0 = b0;
173 f->a1 = a1;
174}
175
176void tOnePole_setGain(tOnePole* const ft, float gain)
177{
178 _tOnePole* f = *ft;
179 f->gain = gain;
180}
181
182float tOnePole_tick(tOnePole* const ft, float input)
183{
184 _tOnePole* f = *ft;
185
186 float in = input * f->gain;
187 float out = (f->b0 * in) + (f->a1 * f->lastOut);
188
189 f->lastIn = in;
190 f->lastOut = out;
191
192 return out;
193}
194
195// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoPole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
196void tTwoPole_init(tTwoPole* const ft)
197{
198 _tTwoPole* f = *ft = (_tTwoPole*) leaf_alloc(sizeof(_tTwoPole));
199
200 f->gain = 1.0f;
201 f->a0 = 1.0;
202 f->b0 = 1.0;
203
204 f->lastOut[0] = 0.0f;
205 f->lastOut[1] = 0.0f;
206}
207
208void tTwoPole_free(tTwoPole* const ft)
209{
210 _tTwoPole* f = *ft;
98 211
99 leaf_free(f);212 leaf_free(f);
100}213}
101 214
102float tButterworth_tick(tButterworth* const ft, float samp)215void tTwoPole_initToPool (tTwoPole* const ft, tMempool* const mp)
103{216{
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;
105 223
106 for(int i = 0; i < ((f->N)/2); ++i)224 f->lastOut[0] = 0.0f;
107 {225 f->lastOut[1] = 0.0f;
108 samp = tSVF_tick(&f->low[i],samp);
109 samp = tSVF_tick(&f->high[i],samp);
110 }
111 return samp;
112}226}
113 227
114void tButterworth_setF1(tButterworth* const ft, float f1)228void tTwoPole_freeFromPool (tTwoPole* const ft, tMempool* const mp)
115{229{
116 _tButterworth* f = *ft;230 _tMempool* m = *mp;
231 _tTwoPole* f = *ft;
117 232
118 f->f1 = f1;233 mpool_free(f, m->pool);
119 for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->low[i], f1);
120}234}
121 235
122void tButterworth_setF2(tButterworth* const ft, float f2)236float tTwoPole_tick(tTwoPole* const ft, float input)
123{237{
124 _tButterworth* f = *ft;238 _tTwoPole* f = *ft;
125 239
126 f->f2 = f2;240 float in = input * f->gain;
127 for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->high[i], f2);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;
128}247}
129 248
130void tButterworth_setFreqs(tButterworth* const ft, float f1, float f2)249void tTwoPole_setB0(tTwoPole* const ft, float b0)
131{250{
132 _tButterworth* f = *ft;251 _tTwoPole* f = *ft;
252 f->b0 = b0;
253}
254
255void tTwoPole_setA1(tTwoPole* const ft, float a1)
256{
257 _tTwoPole* f = *ft;
258 f->a1 = a1;
259}
260
261void tTwoPole_setA2(tTwoPole* const ft, float a2)
262{
263 _tTwoPole* f = *ft;
264 f->a2 = a2;
265}
266
267
268void tTwoPole_setResonance(tTwoPole* const ft, float frequency, float radius, oBool normalize)
269{
270 _tTwoPole* f = *ft;
271
272 if (frequency < 0.0f) frequency = 0.0f;
273 if (frequency > (leaf.sampleRate * 0.49f)) frequency = leaf.sampleRate * 0.49f;
274 if (radius < 0.0f) radius = 0.0f;
275 if (radius >= 1.0f) radius = 0.999999f;
276
277 f->radius = radius;
278 f->frequency = frequency;
279 f->normalize = normalize;
280
281 f->a2 = radius * radius;
282 f->a1 = -2.0f * radius * cosf(frequency * leaf.twoPiTimesInvSampleRate);
283
284 if ( normalize )
285 {
286 // Normalize the filter gain ... not terribly efficient.
287 float real = 1 - radius + (f->a2 - radius) * cosf(2 * frequency * leaf.twoPiTimesInvSampleRate);
288 float imag = (f->a2 - radius) * sinf(2 * frequency * leaf.twoPiTimesInvSampleRate);
289 f->b0 = sqrtf( powf(real, 2) + powf(imag, 2) );
290 }
291}
292
293void tTwoPole_setCoefficients(tTwoPole* const ft, float b0, float a1, float a2)
294{
295 _tTwoPole* f = *ft;
296 f->b0 = b0;
297 f->a1 = a1;
298 f->a2 = a2;
299}
300
301void tTwoPole_setGain(tTwoPole* const ft, float gain)
302{
303 _tTwoPole* f = *ft;
304 f->gain = gain;
305}
306
307void tTwoPoleSampleRateChanged (tTwoPole* const ft)
308{
309 _tTwoPole* f = *ft;
310
311 f->a2 = f->radius * f->radius;
312 f->a1 = -2.0f * f->radius * cosf(f->frequency * leaf.twoPiTimesInvSampleRate);
133 313
134 f->f1 = f1;314 if ( f->normalize )
135 f->f2 = f2;315 {
136 for(int i = 0; i < ((f->N)/2); ++i)316 // Normalize the filter gain ... not terribly efficient.
137 {317 float real = 1 - f->radius + (f->a2 - f->radius) * cosf(2 * f->frequency * leaf.twoPiTimesInvSampleRate);
138 tSVF_setFreq(&f->low[i], f1);318 float imag = (f->a2 - f->radius) * sinf(2 * f->frequency * leaf.twoPiTimesInvSampleRate);
139 tSVF_setFreq(&f->high[i], f2);319 f->b0 = sqrtf( powf(real, 2) + powf(imag, 2) );
140 }320 }
141}321}
142 322
143// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OneZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //323// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OneZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
@@ -158,6 +338,25 @@ void tOneZero_free(tOneZero* const ft) · 14 unmodified lines
158 leaf_free(f);338 leaf_free(f);
159}339}
160 340
341void tOneZero_initToPool (tOneZero* const ft, float theZero, tMempool* const mp)
342{
343 _tMempool* m = *mp;
344 _tOneZero* f = *ft = (_tOneZero*) mpool_alloc(sizeof(_tOneZero), m->pool);
345
346 f->gain = 1.0f;
347 f->lastIn = 0.0f;
348 f->lastOut = 0.0f;
349 tOneZero_setZero(ft, theZero);
350}
351
352void tOneZero_freeFromPool (tOneZero* const ft, tMempool* const mp)
353{
354 _tMempool* m = *mp;
355 _tOneZero* f = *ft;
356
357 mpool_free(f, m->pool);
358}
359
161float tOneZero_tick(tOneZero* const ft, float input)360float tOneZero_tick(tOneZero* const ft, float input)
162{361{
163 _tOneZero* f = *ft;362 _tOneZero* f = *ft;
@@ -254,6 +453,24 @@ void tTwoZero_free(tTwoZero* const ft) · 90 unmodified lines
254 leaf_free(f);453 leaf_free(f);
255}454}
256 455
456void tTwoZero_initToPool (tTwoZero* const ft, tMempool* const mp)
457{
458 _tMempool* m = *mp;
459 _tTwoZero* f = *ft = (_tTwoZero*) mpool_alloc(sizeof(_tTwoZero), m->pool);
460
461 f->gain = 1.0f;
462 f->lastIn[0] = 0.0f;
463 f->lastIn[1] = 0.0f;
464}
465
466void tTwoZero_freeFromPool (tTwoZero* const ft, tMempool* const mp)
467{
468 _tMempool* m = *mp;
469 _tTwoZero* f = *ft;
470
471 mpool_free(f, m->pool);
472}
473
257float tTwoZero_tick(tTwoZero* const ft, float input)474float tTwoZero_tick(tTwoZero* const ft, float input)
258{475{
259 _tTwoZero* f = *ft;476 _tTwoZero* f = *ft;
@@ -324,199 +541,30 @@ void tTwoZeroSampleRateChanged(tTwoZero* const ft) · 64 unmodified lines
324 tTwoZero_setNotch(ft, f->frequency, f->radius);541 tTwoZero_setNotch(ft, f->frequency, f->radius);
325}542}
326 543
327// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //544// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PoleZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
328void tOnePole_init(tOnePole* const ft, float freq)545void tPoleZero_init(tPoleZero* const pzf)
329{546{
330 _tOnePole* f = *ft = (_tOnePole*) leaf_alloc(sizeof(_tOnePole));547 _tPoleZero* f = *pzf = (_tPoleZero*) leaf_alloc(sizeof(_tPoleZero));
331 548
332 f->gain = 1.0f;549 f->gain = 1.0f;
550 f->b0 = 1.0;
333 f->a0 = 1.0;551 f->a0 = 1.0;
334
335 tOnePole_setFreq(ft, freq);
336 552
337 f->lastIn = 0.0f;553 f->lastIn = 0.0f;
338 f->lastOut = 0.0f;554 f->lastOut = 0.0f;
339}555}
340 556
341void tOnePole_free(tOnePole* const ft)557void tPoleZero_free(tPoleZero* const pzf)
342{
343 _tOnePole* f = *ft;
344
345 leaf_free(f);
346}
347
348void tOnePole_setB0(tOnePole* const ft, float b0)
349{
350 _tOnePole* f = *ft;
351 f->b0 = b0;
352}
353
354void 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
361void 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
374void 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
382void 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
390void tOnePole_setGain(tOnePole* const ft, float gain)
391{
392 _tOnePole* f = *ft;
393 f->gain = gain;
394}
395
396float 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 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
410void 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
422void tTwoPole_free(tTwoPole* const ft)
423{558{
424 _tTwoPole* f = *ft;559 _tPoleZero* f = *pzf;
425 560
426 leaf_free(f);561 leaf_free(f);
427}562}
428 563
429float tTwoPole_tick(tTwoPole* const ft, float input)564void tPoleZero_initToPool (tPoleZero* const pzf, tMempool* const mp)
430{565{
431 _tTwoPole* f = *ft;566 _tMempool* m = *mp;
432 567 _tPoleZero* f = *pzf = (_tPoleZero*) mpool_alloc(sizeof(_tPoleZero), m->pool);
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
442void tTwoPole_setB0(tTwoPole* const ft, float b0)
443{
444 _tTwoPole* f = *ft;
445 f->b0 = b0;
446}
447
448void tTwoPole_setA1(tTwoPole* const ft, float a1)
449{
450 _tTwoPole* f = *ft;
451 f->a1 = a1;
452}
453
454void tTwoPole_setA2(tTwoPole* const ft, float a2)
455{
456 _tTwoPole* f = *ft;
457 f->a2 = a2;
458}
459
460
461void 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
486void 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
494void tTwoPole_setGain(tTwoPole* const ft, float gain)
495{
496 _tTwoPole* f = *ft;
497 f->gain = gain;
498}
499
500void 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 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
517void tPoleZero_init(tPoleZero* const pzf)
518{
519 _tPoleZero* f = *pzf = (_tPoleZero*) leaf_alloc(sizeof(_tPoleZero));
520 568
521 f->gain = 1.0f;569 f->gain = 1.0f;
522 f->b0 = 1.0;570 f->b0 = 1.0;
@@ -526,11 +574,12 @@ void tPoleZero_init(tPoleZero* const pzf) · 3 unmodified lines
526 f->lastOut = 0.0f;574 f->lastOut = 0.0f;
527}575}
528 576
529void tPoleZero_free(tPoleZero* const pzf)577void tPoleZero_freeFromPool (tPoleZero* const pzf, tMempool* const mp)
530{578{
579 _tMempool* m = *mp;
531 _tPoleZero* f = *pzf;580 _tPoleZero* f = *pzf;
532 581
533 leaf_free(f);582 mpool_free(f, m->pool);
534}583}
535 584
536void tPoleZero_setB0(tPoleZero* const pzf, float b0)585void tPoleZero_setB0(tPoleZero* const pzf, float b0)
@@ -643,6 +692,30 @@ void tBiQuad_free(tBiQuad* const ft) · 106 unmodified lines
643 leaf_free(f);692 leaf_free(f);
644}693}
645 694
695void tBiQuad_initToPool (tBiQuad* const ft, tMempool* const mp)
696{
697 _tMempool* m = *mp;
698 _tBiQuad* f = *ft = (_tBiQuad*) mpool_alloc(sizeof(_tBiQuad), m->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
711void 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
646float tBiQuad_tick(tBiQuad* const ft, float input)719float tBiQuad_tick(tBiQuad* const ft, float input)
647{720{
648 _tBiQuad* f = *ft;721 _tBiQuad* f = *ft;
@@ -766,78 +839,54 @@ void tBiQuadSampleRateChanged(tBiQuad* const ft) · 117 unmodified lines
766 }839 }
767}840}
768 841
769/* Highpass */842// Less efficient, more accurate version of SVF, in which cutoff frequency is taken as floating point Hz value and tanf
770void tHighpass_init(tHighpass* const ft, float freq)843// is calculated when frequency changes.
844void tSVF_init(tSVF* const svff, SVFType type, float freq, float Q)
771{845{
772 _tHighpass* f = *ft = (_tHighpass*) leaf_alloc(sizeof(_tHighpass));846 _tSVF* svf = *svff = (_tSVF*) leaf_alloc(sizeof(_tSVF));
773 847
774 f->R = (1.0f - (freq * leaf.twoPiTimesInvSampleRate));848 svf->type = type;
775 f->ys = 0.0f;
776 f->xs = 0.0f;
777 849
778 f->frequency = freq;850 svf->ic1eq = 0;
779}851 svf->ic2eq = 0;
780
781void tHighpass_free(tHighpass* const ft)
782{
783 _tHighpass* f = *ft;
784 852
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;
786}858}
787 859
788void tHighpass_setFreq(tHighpass* const ft, float freq)860void tSVF_free(tSVF* const svff)
789{861{
790 _tHighpass* f = *ft;862 _tSVF* svf = *svff;
791 f->frequency = freq;
792 f->R = (1.0f - (freq * leaf.twoPiTimesInvSampleRate));
793 863
864 leaf_free(svf);
794}865}
795 866
796float tHighpass_getFreq(tHighpass* const ft)867void tSVF_initToPool (tSVF* const svff, SVFType type, float freq, float Q, tMempool* const mp)
797{
798 _tHighpass* f = *ft;
799 return f->frequency;
800}
801
802// From JOS DC Blocker
803float 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
811void 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.
819void tSVF_init(tSVF* const svff, SVFType type, float freq, float Q)
820{868{
821 _tSVF* svf = *svff = (_tSVF*) leaf_alloc(sizeof(_tSVF));869 _tMempool* m = *mp;
870 _tSVF* svf = *svff = (_tSVF*) mpool_alloc(sizeof(_tSVF), m->pool);
822 871
823 svf->type = type;872 svf->type = type;
824 873
825 svf->ic1eq = 0;874 svf->ic1eq = 0;
826 svf->ic2eq = 0;875 svf->ic2eq = 0;
827 876
828 float a1,a2,a3,g,k;
829 svf->g = tanf(PI * freq * leaf.invSampleRate);877 svf->g = tanf(PI * freq * leaf.invSampleRate);
830 svf->k = 1.0f/Q;878 svf->k = 1.0f/Q;
831 svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));879 svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
832 svf->a2 = g*a1;880 svf->a2 = svf->g*svf->a1;
833 svf->a3 = g*a2;881 svf->a3 = svf->g*svf->a2;
834}882}
835 883
836void tSVF_free(tSVF* const svff)884void tSVF_freeFromPool (tSVF* const svff, tMempool* const mp)
837{885{
886 _tMempool* m = *mp;
838 _tSVF* svf = *svff;887 _tSVF* svf = *svff;
839 888
840 leaf_free(svf);889 mpool_free(svf, m->pool);
841}890}
842 891
843float tSVF_tick(tSVF* const svff, float v0)892float 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
890 svf->ic1eq = 0;939 svf->ic1eq = 0;
891 svf->ic2eq = 0;940 svf->ic2eq = 0;
892 941
893 float a1,a2,a3,g,k;
894 svf->g = filtertan[input];942 svf->g = filtertan[input];
895 svf->k = 1.0f/Q;943 svf->k = 1.0f/Q;
896 svf->a1 = 1.0f/(1.0f+g*(g+k));944 svf->a1 = 1.0f/(1.0f+svf->g*(svf->g+svf->k));
897 svf->a2 = g*a1;945 svf->a2 = svf->g*svf->a1;
898 svf->a3 = g*a2;946 svf->a3 = svf->g*svf->a2;
899}947}
900 948
901void tEfficientSVF_free(tEfficientSVF* const svff)949void tEfficientSVF_free(tEfficientSVF* const svff)
@@ -905,6 +953,31 @@ void tEfficientSVF_free(tEfficientSVF* const svff) · 3 unmodified lines
905 leaf_free(svf);953 leaf_free(svf);
906}954}
907 955
956void 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
973void 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
908float tEfficientSVF_tick(tEfficientSVF* const svff, float v0)981float tEfficientSVF_tick(tEfficientSVF* const svff, float v0)
909{982{
910 _tEfficientSVF* svf = *svff;983 _tEfficientSVF* svf = *svff;
@@ -945,6 +1018,181 @@ void tEfficientSVF_setQ(tEfficientSVF* const svff, float Q) · 34 unmodified lines
945 svf->a3 = svf->g * svf->a2;1018 svf->a3 = svf->g * svf->a2;
946}1019}
947 1020
1021/* Highpass */
1022void 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
1033void tHighpass_free(tHighpass* const ft)
1034{
1035 _tHighpass* f = *ft;
1036
1037 leaf_free(f);
1038}
1039
1040void 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
1052void 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
1060void 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
1068float tHighpass_getFreq(tHighpass* const ft)
1069{
1070 _tHighpass* f = *ft;
1071 return f->frequency;
1072}
1073
1074// From JOS DC Blocker
1075float 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
1083void tHighpassSampleRateChanged(tHighpass* const ft)
1084{
1085 _tHighpass* f = *ft;
1086 f->R = (1.0f-((f->frequency * 2.0f * 3.14f) * leaf.invSampleRate));
1087}
1088
1089void 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
1108void 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
1121void 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
1141void 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
1155float 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
1167void 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
1175void 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
1183void 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
948void tFIR_init(tFIR* const firf, float* coeffs, int numTaps)1196void tFIR_init(tFIR* const firf, float* coeffs, int numTaps)
949{1197{
950 _tFIR* fir = *firf = (_tFIR*) leaf_alloc(sizeof(_tFIR));1198 _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
955 for (int i = 0; i < fir->numTaps; ++i) fir->past[i] = 0.0f;1203 for (int i = 0; i < fir->numTaps; ++i) fir->past[i] = 0.0f;
956}1204}
957 1205
1206void tFIR_free(tFIR* const firf)
1207{
1208 _tFIR* fir = *firf;
1209
1210 leaf_free(fir->past);
1211 leaf_free(fir);
1212}
1213
1214void 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
1225void 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
958float tFIR_tick(tFIR* const firf, float input)1234float tFIR_tick(tFIR* const firf, float input)
959{1235{
960 _tFIR* fir = *firf;1236 _tFIR* fir = *firf;
@@ -965,11 +1241,3 @@ float tFIR_tick(tFIR* const firf, float input) · 4 unmodified lines
965 for (int i = fir->numTaps-1; i > 0; --i) fir->past[i] = fir->past[i-1];1241 for (int i = fir->numTaps-1; i > 0; --i) fir->past[i] = fir->past[i-1];
966 return y;1242 return y;
967}1243}
968
969void 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
63 leaf_free(cowbell);63 leaf_free(cowbell);
64}64}
65 65
66void t808Cowbell_initToPool (t808Cowbell* const cowbellInst, int useStick, tMempool* const mp)
67{
68 _tMempool* m = *mp;
69 _t808Cowbell* cowbell = *cowbellInst = (_t808Cowbell*) mpool_alloc(sizeof(_t808Cowbell), m->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
96void t808Cowbell_freeFromPool (t808Cowbell* const cowbellInst, tMempool* const mp)
97{
98 _tMempool* m = *mp;
99 _t808Cowbell* cowbell = *cowbellInst;
100
101 tSquare_freeFromPool(&cowbell->p[0], mp);
102 tSquare_freeFromPool(&cowbell->p[1], mp);
103 tSVF_freeFromPool(&cowbell->bandpassOsc, mp);
104 tSVF_freeFromPool(&cowbell->bandpassStick, mp);
105 tEnvelope_freeFromPool(&cowbell->envGain, mp);
106 tEnvelope_freeFromPool(&cowbell->envFilter, mp);
107 tHighpass_freeFromPool(&cowbell->highpass, mp);
108 tNoise_freeFromPool(&cowbell->stick, mp);
109 tEnvelope_freeFromPool(&cowbell->envStick, mp);
110 mpool_free(cowbell, m->pool);
111}
112
66void t808Cowbell_on(t808Cowbell* const cowbellInst, float vel)113void t808Cowbell_on(t808Cowbell* const cowbellInst, float vel)
67{114{
68 _t808Cowbell* cowbell = *cowbellInst;115 _t808Cowbell* cowbell = *cowbellInst;
@@ -192,6 +239,64 @@ void t808Hihat_free(t808Hihat* const hihatInst) · 123 unmodified lines
192 leaf_free(hihat);239 leaf_free(hihat);
193}240}
194 241
242void t808Hihat_initToPool (t808Hihat* const hihatInst, tMempool* const mp)
243{
244 _tMempool* m = *mp;
245 _t808Hihat* hihat = *hihatInst = (_t808Hihat*) mpool_alloc(sizeof(_t808Hihat), m->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
276void t808Hihat_freeFromPool (t808Hihat* const hihatInst, tMempool* const mp)
277{
278 _tMempool* m = *mp;
279 _t808Hihat* hihat = *hihatInst;
280
281 for (int i = 0; i < 6; i++)
282 {
283 tSquare_freeFromPool(&hihat->p[i], mp);
284 }
285
286 tNoise_freeFromPool(&hihat->stick, mp);
287 tNoise_freeFromPool(&hihat->n, mp);
288
289 // need to fix SVF to be generic
290 tSVF_freeFromPool(&hihat->bandpassStick, mp);
291 tSVF_freeFromPool(&hihat->bandpassOsc, mp);
292 tEnvelope_freeFromPool(&hihat->envGain, mp);
293 tEnvelope_freeFromPool(&hihat->envStick, mp);
294
295 tHighpass_freeFromPool(&hihat->highpass, mp);
296
297 mpool_free(hihat, m->pool);
298}
299
195void t808Hihat_on(t808Hihat* const hihatInst, float vel)300void t808Hihat_on(t808Hihat* const hihatInst, float vel)
196{301{
197 _t808Hihat* hihat = *hihatInst;302 _t808Hihat* hihat = *hihatInst;
@@ -289,8 +394,6 @@ void t808Hihat_setStickBandPassQ(t808Hihat* const hihatInst, float Q) · 91 unmodified lines
289 tSVF_setQ(&hihat->bandpassStick,Q);394 tSVF_setQ(&hihat->bandpassStick,Q);
290}395}
291 396
292
293
294void t808Hihat_setOscFreq(t808Hihat* const hihatInst, float freq)397void t808Hihat_setOscFreq(t808Hihat* const hihatInst, float freq)
295{398{
296 _t808Hihat* hihat = *hihatInst;399 _t808Hihat* hihat = *hihatInst;
@@ -348,6 +451,57 @@ void t808Snare_free (t808Snare* const snareInst) · 51 unmodified lines
348 leaf_free(snare);451 leaf_free(snare);
349}452}
350 453
454void t808Snare_initToPool (t808Snare* const snareInst, tMempool* const mp)
455{
456 _tMempool* m = *mp;
457 _t808Snare* snare = *snareInst = (_t808Snare*) mpool_alloc(sizeof(_t808Snare), m->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
483void t808Snare_freeFromPool (t808Snare* const snareInst, tMempool* const mp)
484{
485 _tMempool* m = *mp;
486 _t808Snare* snare = *snareInst;
487
488 for (int i = 0; i < 2; i++)
489 {
490 tTriangle_freeFromPool(&snare->tone[i], mp);
491 tSVF_freeFromPool(&snare->toneLowpass[i], mp);
492 tEnvelope_freeFromPool(&snare->toneEnvOsc[i], mp);
493 tEnvelope_freeFromPool(&snare->toneEnvGain[i], mp);
494 tEnvelope_freeFromPool(&snare->toneEnvFilter[i], mp);
495 }
496
497 tNoise_freeFromPool(&snare->noiseOsc, mp);
498 tSVF_freeFromPool(&snare->noiseLowpass, mp);
499 tEnvelope_freeFromPool(&snare->noiseEnvGain, mp);
500 tEnvelope_freeFromPool(&snare->noiseEnvFilter, mp);
501
502 mpool_free(snare, m->pool);
503}
504
351void t808Snare_on(t808Snare* const snareInst, float vel)505void t808Snare_on(t808Snare* const snareInst, float vel)
352{506{
353 _t808Snare* snare = *snareInst;507 _t808Snare* snare = *snareInst;
@@ -472,6 +626,41 @@ void t808Kick_free (t808Kick* const kickInst) · 118 unmodified lines
472 leaf_free(kick);626 leaf_free(kick);
473}627}
474 628
629void t808Kick_initToPool (t808Kick* const kickInst, tMempool* const mp)
630{
631 _tMempool* m = *mp;
632 _t808Kick* kick = *kickInst = (_t808Kick*) mpool_alloc(sizeof(_t808Kick), m->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
648void t808Kick_freeFromPool (t808Kick* const kickInst, tMempool* const mp)
649{
650 _tMempool* m = *mp;
651 _t808Kick* kick = *kickInst;
652
653 tCycle_freeFromPool(&kick->tone, mp);
654 tSVF_freeFromPool(&kick->toneLowpass, mp);
655 tEnvelope_freeFromPool(&kick->toneEnvOscChirp, mp);
656 tEnvelope_freeFromPool(&kick->toneEnvOscSigh, mp);
657 tEnvelope_freeFromPool(&kick->toneEnvGain, mp);
658 tNoise_freeFromPool(&kick->noiseOsc, mp);
659 tEnvelope_freeFromPool(&kick->noiseEnvGain, mp);
660
661 mpool_free(kick, m->pool);
662}
663
475float t808Kick_tick (t808Kick* const kickInst)664float t808Kick_tick (t808Kick* const kickInst)
476{665{
477 _t808Kick* kick = *kickInst;666 _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
77 }77 }
78}78}
79 79
80
81
82void leaf_pool_init(char* memory, size_t size)80void leaf_pool_init(char* memory, size_t size)
83{81{
84 mpool_create(memory, size, &leaf_pool);82 mpool_create(memory, size, &leaf_pool);
@@ -143,6 +141,68 @@ void* mpool_alloc(size_t asize, mpool_t* pool) · 58 unmodified lines
143 return node_to_alloc->pool;141 return node_to_alloc->pool;
144}142}
145 143
144
145/**
146 * allocate memory from memory pool and also clear that memory to be blank
147 */
148void* 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
146void* leaf_alloc(size_t size)206void* leaf_alloc(size_t size)
147{207{
148 //printf("alloc %i\n", size);208 //printf("alloc %i\n", size);
@@ -153,6 +213,17 @@ void* leaf_alloc(size_t size) · 4 unmodified lines
153 return block;213 return block;
154}214}
155 215
216void* 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
156void mpool_free(void* ptr, mpool_t* pool)227void mpool_free(void* ptr, mpool_t* pool)
157{228{
158 //if (ptr < pool->mpool || ptr >= pool->mpool + pool->msize)229 //if (ptr < pool->mpool || ptr >= pool->mpool + pool->msize)
@@ -211,8 +282,8 @@ void mpool_free(void* ptr, mpool_t* pool) · 52 unmodified lines
211 pool->head = freed_node;282 pool->head = freed_node;
212 283
213 // Format the freed pool284 // Format the freed pool
214 char* freed_pool = (char*)freed_node->pool;285// char* freed_pool = (char*)freed_node->pool;
215 for (int i = 0; i < freed_node->size; i++) freed_pool[i] = 0;286// for (int i = 0; i < freed_node->size; i++) freed_pool[i] = 0;
216}287}
217 288
218void leaf_free(void* ptr)289void leaf_free(void* ptr)
@@ -289,3 +360,32 @@ void leaf_mempool_overrun(void) · 70 unmodified lines
289 //TODO: we should set up some kind of leaf_error method that reaches user space to notify library users of things that failed.360 //TODO: we should set up some kind of leaf_error method that reaches user space to notify library users of things that failed.
290}361}
291 362
363void 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
370void tMempool_free(tMempool* const mp)
371{
372 _tMempool* m = *mp;
373
374 leaf_free(m);
375}
376
377void 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
385void 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
16 16
17#endif17#endif
18 18
19//====================================================================================
20/* Stack */
21//====================================================================================
22
23void tStack_init(tStack* const stack)
24{
25 _tStack* ns = *stack = (_tStack*) leaf_alloc(sizeof(_tStack));
26
27 ns->ordered = OFALSE;
28 ns->size = 0;
29 ns->pos = 0;
30 ns->capacity = STACK_SIZE;
31
32 for (int i = 0; i < STACK_SIZE; i++) ns->data[i] = -1;
33}
34
35void tStack_free(tStack* const stack)
36{
37 _tStack* ns = *stack;
38
39 leaf_free(ns);
40}
41
42void tStack_initToPool (tStack* const stack, tMempool* const mp)
43{
44 _tMempool* m = *mp;
45 _tStack* ns = *stack = (_tStack*) mpool_alloc(sizeof(_tStack), m->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
55void 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;
64int tStack_contains(tStack* const stack, uint16_t noteVal)
65{
66 _tStack* ns = *stack;
67 for (int i = 0; i < ns->size; i++)
68 {
69 if (ns->data[i] == noteVal) return i;
70 }
71 return -1;
72}
73
74void tStack_add(tStack* const stack, uint16_t noteVal)
75{
76 _tStack* ns = *stack;
77
78 uint8_t j;
79
80 int whereToInsert = 0;
81 if (ns->ordered)
82 {
83 for (j = 0; j < ns->size; j++)
84 {
85 if (noteVal > ns->data[j])
86 {
87 if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1))
88 {
89 whereToInsert = j+1;
90 break;
91 }
92 }
93 }
94 }
95
96 //first move notes that are already in the stack one position to the right
97 for (j = ns->size; j > whereToInsert; j--)
98 {
99 ns->data[j] = ns->data[(j - 1)];
100 }
101
102 //then, insert the new note into the front of the stack
103 ns->data[whereToInsert] = noteVal;
104
105 ns->size++;
106}
107
108int tStack_addIfNotAlreadyThere(tStack* const stack, uint16_t noteVal)
109{
110 _tStack* ns = *stack;
111
112 uint8_t j;
113
114 int added = 0;
115
116 if (tStack_contains(stack, noteVal) == -1)
117 {
118 int whereToInsert = 0;
119 if (ns->ordered)
120 {
121 for (j = 0; j < ns->size; j++)
122 {
123 if (noteVal > ns->data[j])
124 {
125 if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1))
126 {
127 whereToInsert = j+1;
128 break;
129 }
130 }
131 }
132 }
133
134 //first move notes that are already in the stack one position to the right
135 for (j = ns->size; j > whereToInsert; j--)
136 {
137 ns->data[j] = ns->data[(j - 1)];
138 }
139
140 //then, insert the new note into the front of the stack
141 ns->data[whereToInsert] = noteVal;
142
143 ns->size++;
144
145 added = 1;
146 }
147
148 return added;
149}
150
151// Remove noteVal. return 1 if removed, 0 if not
152int tStack_remove(tStack* const stack, uint16_t noteVal)
153{
154 _tStack* ns = *stack;
155
156 uint8_t k;
157 int foundIndex = tStack_contains(stack, noteVal);
158 int removed = 0;
159
160 if (foundIndex >= 0)
161 {
162 for (k = 0; k < (ns->size - foundIndex); k++)
163 {
164 if ((k+foundIndex) >= (ns->capacity - 1))
165 {
166 ns->data[k + foundIndex] = -1;
167 }
168 else
169 {
170 ns->data[k + foundIndex] = ns->data[k + foundIndex + 1];
171 if ((k + foundIndex) == (ns->size - 1))
172 {
173 ns->data[k + foundIndex + 1] = -1;
174 }
175 }
176
177 }
178 // in case it got put on the stack multiple times
179 foundIndex--;
180 ns->size--;
181 removed = 1;
182 }
183
184 return removed;
185}
186
187// Doesn't change size of data types
188void tStack_setCapacity(tStack* const stack, uint16_t cap)
189{
190 _tStack* ns = *stack;
191
192 if (cap <= 0)
193 ns->capacity = 1;
194 else if (cap <= STACK_SIZE)
195 ns->capacity = cap;
196 else
197 ns->capacity = STACK_SIZE;
198
199 for (int i = cap; i < STACK_SIZE; i++)
200 {
201 if ((int)ns->data[i] != -1)
202 {
203 ns->data[i] = -1;
204 ns->size -= 1;
205 }
206 }
207
208 if (ns->pos >= cap)
209 {
210 ns->pos = 0;
211 }
212}
213
214int tStack_getSize(tStack* const stack)
215{
216 _tStack* ns = *stack;
217
218 return ns->size;
219}
220
221void tStack_clear(tStack* const stack)
222{
223 _tStack* ns = *stack;
224
225 for (int i = 0; i < STACK_SIZE; i++)
226 {
227 ns->data[i] = -1;
228 }
229 ns->pos = 0;
230 ns->size = 0;
231}
232
233// Next item in order of addition to stack. Return 0-31 if there is a next item to move to. Returns -1 otherwise.
234int tStack_next(tStack* const stack)
235{
236 _tStack* ns = *stack;
237
238 int step = 0;
239 if (ns->size != 0) // if there is at least one note in the stack
240 {
241 if (ns->pos > 0) // if you're not at the most recent note (first one), then go backward in the array (moving from earliest to latest)
242 {
243 ns->pos--;
244 }
245 else
246 {
247 ns->pos = (ns->size - 1); // if you are the most recent note, go back to the earliest note in the array
248 }
249
250 step = ns->data[ns->pos];
251 return step;
252 }
253 else
254 {
255 return -1;
256 }
257}
258
259int tStack_get(tStack* const stack, int which)
260{
261 _tStack* ns = *stack;
262 return ns->data[which];
263}
264
265int tStack_first(tStack* const stack)
266{
267 _tStack* ns = *stack;
268 return ns->data[0];
269}
270
271
19// POLY272// POLY
20void tPoly_init(tPoly* const polyh, int maxNumVoices)273void tPoly_init(tPoly* const polyh, int maxNumVoices)
21{274{
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
318void tPoly_free(tPoly* const polyh)
319{
320 _tPoly* poly = *polyh;
321
322 for (int i = 0; i < poly->maxNumVoices; i++)
323 {
324 tRamp_free(&poly->ramps[i]);
325 leaf_free(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
339void tPoly_initToPool (tPoly* const polyh, int maxNumVoices, tMempool* const mp)
340{
341 _tMempool* m = *mp;
342 _tPoly* poly = *polyh = (_tPoly*) mpool_alloc(sizeof(_tPoly), m->pool);
23 343
24 poly->numVoices = maxNumVoices;344 poly->numVoices = maxNumVoices;
25 poly->maxNumVoices = maxNumVoices;345 poly->maxNumVoices = maxNumVoices;
@@ -39,48 +359,49 @@ void tPoly_init(tPoly* const polyh, int maxNumVoices) · 13 unmodified lines
39 359
40 poly->glideTime = 5.0f;360 poly->glideTime = 5.0f;
41 361
42 poly->ramps = (tRamp*) leaf_alloc(sizeof(tRamp) * poly->maxNumVoices);362 poly->ramps = (tRamp*) mpool_alloc(sizeof(tRamp) * poly->maxNumVoices, m->pool);
43 poly->rampVals = (float*) leaf_alloc(sizeof(float) * poly->maxNumVoices);363 poly->rampVals = (float*) mpool_alloc(sizeof(float) * poly->maxNumVoices, m->pool);
44 poly->firstReceived = (oBool*) leaf_alloc(sizeof(oBool) * poly->maxNumVoices);364 poly->firstReceived = (oBool*) mpool_alloc(sizeof(oBool) * poly->maxNumVoices, m->pool);
45 poly->voices = (int**) leaf_alloc(sizeof(int*) * poly->maxNumVoices);365 poly->voices = (int**) mpool_alloc(sizeof(int*) * poly->maxNumVoices, m->pool);
46 366
47 for (int i = 0; i < poly->maxNumVoices; ++i)367 for (int i = 0; i < poly->maxNumVoices; ++i)
48 {368 {
49 poly->voices[i] = (int*) leaf_alloc(sizeof(int) * 2);369 poly->voices[i] = (int*) mpool_alloc(sizeof(int) * 2, m->pool);
50 poly->voices[i][0] = -1;370 poly->voices[i][0] = -1;
51 poly->firstReceived[i] = OFALSE;371 poly->firstReceived[i] = OFALSE;
52 372
53 tRamp_init(&poly->ramps[i], poly->glideTime, 1);373 tRamp_initToPool(&poly->ramps[i], poly->glideTime, 1, mp);
54 }374 }
55 375
56 poly->pitchBend = 0.0f;376 poly->pitchBend = 0.0f;
57 377
58 tRamp_init(&poly->pitchBendRamp, 1.0f, 1);378 tRamp_initToPool(&poly->pitchBendRamp, 1.0f, 1, mp);
59 tStack_init(&poly->stack);379 tStack_initToPool(&poly->stack, mp);
60 tStack_init(&poly->orderStack);380 tStack_initToPool(&poly->orderStack, mp);
61 381
62 poly->pitchGlideIsActive = OFALSE;382 poly->pitchGlideIsActive = OFALSE;
63}383}
64 384
65void tPoly_free(tPoly* const polyh)385void tPoly_freeFromPool (tPoly* const polyh, tMempool* const mp)
66{386{
387 _tMempool* m = *mp;
67 _tPoly* poly = *polyh;388 _tPoly* poly = *polyh;
68 389
69 for (int i = 0; i < poly->maxNumVoices; i++)390 for (int i = 0; i < poly->maxNumVoices; i++)
70 {391 {
71 tRamp_free(&poly->ramps[i]);392 tRamp_freeFromPool(&poly->ramps[i], mp);
72 leaf_free(poly->voices[i]);393 mpool_free(poly->voices[i], m->pool);
73 }394 }
74 tRamp_free(&poly->pitchBendRamp);395 tRamp_freeFromPool(&poly->pitchBendRamp, mp);
75 tStack_free(&poly->stack);396 tStack_freeFromPool(&poly->stack, mp);
76 tStack_free(&poly->orderStack);397 tStack_freeFromPool(&poly->orderStack, mp);
77 398
78 leaf_free(poly->voices);399 mpool_free(poly->voices, m->pool);
79 leaf_free(poly->ramps);400 mpool_free(poly->ramps, m->pool);
80 leaf_free(poly->rampVals);401 mpool_free(poly->rampVals, m->pool);
81 leaf_free(poly->firstReceived);402 mpool_free(poly->firstReceived, m->pool);
82 403
83 leaf_free(poly);404 mpool_free(poly, m->pool);
84}405}
85 406
86void tPoly_tickPitch(tPoly* polyh)407void tPoly_tickPitch(tPoly* polyh)
@@ -332,236 +653,3 @@ int tPoly_isOn(tPoly* const polyh, uint8_t voice) · 245 unmodified lines
332 _tPoly* poly = *polyh;653 _tPoly* poly = *polyh;
333 return (poly->voices[voice][0] > 0) ? 1 : 0;654 return (poly->voices[voice][0] > 0) ? 1 : 0;
334}655}
335
336
337//====================================================================================
338/* Stack */
339//====================================================================================
340
341void 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
353void 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;
361int 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
371void 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
405int 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
450int 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
486void 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
512int tStack_getSize(tStack* const stack)
513{
514 _tStack* ns = *stack;
515
516 return ns->size;
517}
518
519void 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.
532int 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
557int tStack_get(tStack* const stack, int which)
558{
559 _tStack* ns = *stack;
560 return ns->data[which];
561}
562
563int 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
19#endif19#endif
20 20
21// Cycle21// Cycle
22void tCycle_init(tCycle* const c)22void tCycle_init(tCycle* const cy)
23{23{
24 _tCycle* c = *cy = (_tCycle*) leaf_alloc(sizeof(_tCycle));
25
24 c->inc = 0.0f;26 c->inc = 0.0f;
25 c->phase = 0.0f;27 c->phase = 0.0f;
26}28}
27 29
28void tCycle_free(tCycle* const c)30void tCycle_free(tCycle* const cy)
31{
32 _tCycle* c = *cy;
33
34 leaf_free(c);
35}
36
37void tCycle_initToPool (tCycle* const cy, tMempool* const mp)
29{38{
39 _tMempool* m = *mp;
40 _tCycle* c = *cy = (_tCycle*) mpool_alloc(sizeof(_tCycle), m->pool);
30 41
42 c->inc = 0.0f;
43 c->phase = 0.0f;
31}44}
32 45
33int tCycle_setFreq(tCycle* const c, float freq)46void tCycle_freeFromPool (tCycle* const cy, tMempool* const mp)
34{47{
48 _tMempool* m = *mp;
49 _tCycle* c = *cy;
50
51 mpool_free(c, m->pool);
52}
53
54int tCycle_setFreq(tCycle* const cy, float freq)
55{
56 _tCycle* c = *cy;
57
35 if (freq < 0.0f) freq = 0.0f;58 if (freq < 0.0f) freq = 0.0f;
36 59
37 c->freq = freq;60 c->freq = freq;
@@ -40,8 +63,10 @@ int tCycle_setFreq(tCycle* const c, float freq) · 2 unmodified lines
40 return 0;63 return 0;
41}64}
42 65
43float tCycle_tick(tCycle* const c)66float tCycle_tick(tCycle* const cy)
44{67{
68 _tCycle* c = *cy;
69
45 // Phasor increment70 // Phasor increment
46 c->phase += c->inc;71 c->phase += c->inc;
47 while (c->phase >= 1.0f) c->phase -= 1.0f;72 while (c->phase >= 1.0f) c->phase -= 1.0f;
@@ -56,31 +81,51 @@ float tCycle_tick(tCycle* const c) · 8 unmodified lines
56 return (samp0 + (samp1 - samp0) * fracPart);81 return (samp0 + (samp1 - samp0) * fracPart);
57}82}
58 83
59void tCycleSampleRateChanged (tCycle* const c)84void tCycleSampleRateChanged (tCycle* const cy)
60{85{
86 _tCycle* c = *cy;
87
61 c->inc = c->freq * leaf.invSampleRate;88 c->inc = c->freq * leaf.invSampleRate;
62}89}
63 90
64//========================================================================91//========================================================================
65/* Triangle */92/* Triangle */
66void tTriangle_start(tTriangle* const c)93void tTriangle_init(tTriangle* const cy)
67{94{
95 _tTriangle* c = *cy = (_tTriangle*) leaf_alloc(sizeof(_tTriangle));
68 96
97 c->inc = 0.0f;
98 c->phase = 0.0f;
69}99}
70 100
71void tTriangle_init(tTriangle* const c)101void tTriangle_free(tTriangle* const cy)
72{102{
103 _tTriangle* c = *cy;
104
105 leaf_free(c);
106}
107
108void 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
73 c->inc = 0.0f;113 c->inc = 0.0f;
74 c->phase = 0.0f;114 c->phase = 0.0f;
75}115}
76 116
77void tTriangle_free(tTriangle* const c)117void tTriangle_freeFromPool (tTriangle* const cy, tMempool* const mp)
78{118{
119 _tMempool* m = *mp;
120 _tTriangle* c = *cy;
79 121
122 mpool_free(c, m->pool);
80}123}
81 124
82int tTriangle_setFreq(tTriangle* const c, float freq)125int tTriangle_setFreq(tTriangle* const cy, float freq)
83{126{
127 _tTriangle* c = *cy;
128
84 if (freq < 0.0f) freq = 0.0f;129 if (freq < 0.0f) freq = 0.0f;
85 130
86 c->freq = freq;131 c->freq = freq;
@@ -90,8 +135,10 @@ int tTriangle_setFreq(tTriangle* const c, float freq) · 3 unmodified lines
90}135}
91 136
92 137
93float tTriangle_tick(tTriangle* const c)138float tTriangle_tick(tTriangle* const cy)
94{139{
140 _tTriangle* c = *cy;
141
95 // Phasor increment142 // Phasor increment
96 c->phase += c->inc;143 c->phase += c->inc;
97 while (c->phase >= 1.0f) c->phase -= 1.0f;144 while (c->phase >= 1.0f) c->phase -= 1.0f;
@@ -165,26 +212,51 @@ float tTriangle_tick(tTriangle* const c) · 67 unmodified lines
165 return out;212 return out;
166}213}
167 214
168void tTriangleSampleRateChanged (tTriangle* const c)215void tTriangleSampleRateChanged (tTriangle* const cy)
169{216{
217 _tTriangle* c = *cy;
218
170 c->inc = c->freq * leaf.invSampleRate;219 c->inc = c->freq * leaf.invSampleRate;
171}220}
172 221
173//========================================================================222//========================================================================
174/* Square */223/* Square */
175void tSquare_init(tSquare* const c)224void tSquare_init(tSquare* const cy)
176{225{
226 _tSquare* c = *cy = (_tSquare*) leaf_alloc(sizeof(_tSquare));
227
177 c->inc = 0.0f;228 c->inc = 0.0f;
178 c->phase = 0.0f;229 c->phase = 0.0f;
179}230}
180 231
181void tSquare_free(tSquare* const c)232void tSquare_free(tSquare* const cy)
182{233{
234 _tSquare* c = *cy;
183 235
236 leaf_free(c);
184}237}
185 238
186int tSquare_setFreq(tSquare* const c, float freq)239void tSquare_initToPool (tSquare* const cy, tMempool* const mp)
187{240{
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
248void 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
256int tSquare_setFreq(tSquare* const cy, float freq)
257{
258 _tSquare* c = *cy;
259
188 if (freq < 0.0f) freq = 0.0f;260 if (freq < 0.0f) freq = 0.0f;
189 261
190 c->freq = freq;262 c->freq = freq;
@@ -193,8 +265,10 @@ int tSquare_setFreq(tSquare* const c, float freq) · 2 unmodified lines
193 return 0;265 return 0;
194}266}
195 267
196float tSquare_tick(tSquare* const c)268float tSquare_tick(tSquare* const cy)
197{269{
270 _tSquare* c = *cy;
271
198 // Phasor increment272 // Phasor increment
199 c->phase += c->inc;273 c->phase += c->inc;
200 while (c->phase >= 1.0f) c->phase -= 1.0f;274 while (c->phase >= 1.0f) c->phase -= 1.0f;
@@ -267,26 +341,51 @@ float tSquare_tick(tSquare* const c) · 66 unmodified lines
267 return out;341 return out;
268}342}
269 343
270void tSquareSampleRateChanged (tSquare* const c)344void tSquareSampleRateChanged (tSquare* const cy)
271{345{
346 _tSquare* c = *cy;
347
272 c->inc = c->freq * leaf.invSampleRate;348 c->inc = c->freq * leaf.invSampleRate;
273}349}
274 350
275//=====================================================================351//=====================================================================
276// Sawtooth352// Sawtooth
277void tSawtooth_init(tSawtooth* const c)353void 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
361void tSawtooth_free(tSawtooth* const cy)
278{362{
363 _tSawtooth* c = *cy;
364
365 leaf_free(c);
366}
367
368void 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
279 c->inc = 0.0f;373 c->inc = 0.0f;
280 c->phase = 0.0f;374 c->phase = 0.0f;
281}375}
282 376
283void tSawtooth_free(tSawtooth* const c)377void tSawtooth_freeFromPool (tSawtooth* const cy, tMempool* const mp)
284{378{
379 _tMempool* m = *mp;
380 _tSawtooth* c = *cy;
285 381
382 mpool_free(c, m->pool);
286}383}
287 384
288int tSawtooth_setFreq(tSawtooth* const c, float freq)385int tSawtooth_setFreq(tSawtooth* const cy, float freq)
289{386{
387 _tSawtooth* c = *cy;
388
290 if (freq < 0.0f) freq = 0.0f;389 if (freq < 0.0f) freq = 0.0f;
291 390
292 c->freq = freq;391 c->freq = freq;
@@ -295,8 +394,10 @@ int tSawtooth_setFreq(tSawtooth* const c, float freq) · 2 unmodified lines
295 return 0;394 return 0;
296}395}
297 396
298float tSawtooth_tick(tSawtooth* const c)397float tSawtooth_tick(tSawtooth* const cy)
299{398{
399 _tSawtooth* c = *cy;
400
300 // Phasor increment401 // Phasor increment
301 c->phase += c->inc;402 c->phase += c->inc;
302 while (c->phase >= 1.0f) c->phase -= 1.0f;403 while (c->phase >= 1.0f) c->phase -= 1.0f;
@@ -370,31 +471,58 @@ float tSawtooth_tick(tSawtooth* const c) · 67 unmodified lines
370 return out;471 return out;
371}472}
372 473
373void tSawtoothSampleRateChanged (tSawtooth* const c)474void tSawtoothSampleRateChanged (tSawtooth* const cy)
374{475{
476 _tSawtooth* c = *cy;
477
375 c->inc = c->freq * leaf.invSampleRate;478 c->inc = c->freq * leaf.invSampleRate;
376}479}
377 480
378//========================================================================481//========================================================================
379/* Phasor */482/* Phasor */
380void tPhasorSampleRateChanged (tPhasor* const p)483void tPhasorSampleRateChanged (tPhasor* const ph)
381{484{
485 _tPhasor* p = *ph;
486
382 p->inc = p->freq * leaf.invSampleRate;487 p->inc = p->freq * leaf.invSampleRate;
383};488};
384 489
385void tPhasor_init(tPhasor* const p)490void tPhasor_init(tPhasor* const ph)
386{491{
492 _tPhasor* p = *ph = (_tPhasor*) leaf_alloc(sizeof(_tPhasor));
493
387 p->phase = 0.0f;494 p->phase = 0.0f;
388 p->inc = 0.0f;495 p->inc = 0.0f;
389}496}
390 497
391void tPhasor_free(tPhasor* const p)498void tPhasor_free(tPhasor* const ph)
392{499{
500 _tPhasor* p = *ph;
393 501
502 leaf_free(p);
394}503}
395 504
396int tPhasor_setFreq(tPhasor* const p, float freq)505void tPhasor_initToPool (tPhasor* const ph, tMempool* const mp)
397{506{
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
514void 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
522int tPhasor_setFreq(tPhasor* const ph, float freq)
523{
524 _tPhasor* p = *ph;
525
398 if (freq < 0.0f) freq = 0.0f;526 if (freq < 0.0f) freq = 0.0f;
399 527
400 p->freq = freq;528 p->freq = freq;
@@ -403,8 +531,10 @@ int tPhasor_setFreq(tPhasor* const p, float freq) · 2 unmodified lines
403 return 0;531 return 0;
404}532}
405 533
406float tPhasor_tick(tPhasor* const p)534float tPhasor_tick(tPhasor* const ph)
407{535{
536 _tPhasor* p = *ph;
537
408 p->phase += p->inc;538 p->phase += p->inc;
409 539
410 if (p->phase >= 1.0f) p->phase -= 1.0f;540 if (p->phase >= 1.0f) p->phase -= 1.0f;
@@ -413,19 +543,42 @@ float tPhasor_tick(tPhasor* const p) · 2 unmodified lines
413}543}
414 544
415/* Noise */545/* Noise */
416void tNoise_init(tNoise* const n, NoiseType type)546void 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
554void tNoise_free(tNoise* const ns)
417{555{
556 _tNoise* n = *ns;
557
558 leaf_free(n);
559}
560
561void 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
418 n->type = type;566 n->type = type;
419 n->rand = leaf.random;567 n->rand = leaf.random;
420}568}
421 569
422void tNoise_free(tNoise* const n)570void tNoise_freeFromPool (tNoise* const ns, tMempool* const mp)
423{571{
572 _tMempool* m = *mp;
573 _tNoise* n = *ns;
424 574
575 mpool_free(n, m->pool);
425}576}
426 577
427float tNoise_tick(tNoise* const n)578float tNoise_tick(tNoise* const ns)
428{579{
580 _tNoise* n = *ns;
581
429 float rand = (n->rand() * 2.0f) - 1.0f;582 float rand = (n->rand() * 2.0f) - 1.0f;
430 583
431 if (n->type == PinkNoise)584 if (n->type == PinkNoise)
@@ -446,13 +599,15 @@ float tNoise_tick(tNoise* const n) · 14 unmodified lines
446//=================================================================================599//=================================================================================
447/* Neuron */600/* Neuron */
448 601
449void tNeuronSampleRateChanged(tNeuron* n)602void tNeuronSampleRateChanged(tNeuron* nr)
450{603{
451 604
452}605}
453 606
454void tNeuron_init(tNeuron* const n)607void tNeuron_init(tNeuron* const nr)
455{608{
609 _tNeuron* n = *nr = (_tNeuron*) leaf_alloc(sizeof(_tNeuron));
610
456 tPoleZero_init(&n->f);611 tPoleZero_init(&n->f);
457 612
458 tPoleZero_setBlockZero(&n->f, 0.99f);613 tPoleZero_setBlockZero(&n->f, 0.99f);
@@ -480,13 +635,20 @@ void tNeuron_init(tNeuron* const n) · 21 unmodified lines
480 n->rate[2] = n->gL/n->C;635 n->rate[2] = n->gL/n->C;
481}636}
482 637
483void tNeuron_free(tNeuron* const n)638void tNeuron_free(tNeuron* const nr)
484{639{
640 _tNeuron* n = *nr;
641
485 tPoleZero_free(&n->f);642 tPoleZero_free(&n->f);
643 leaf_free(n);
486}644}
487 645
488void tNeuron_reset(tNeuron* const n)646void tNeuron_initToPool (tNeuron* const nr, tMempool* const mp)
489{647{
648 _tMempool* m = *mp;
649 _tNeuron* n = *nr = (_tNeuron*) mpool_alloc(sizeof(_tNeuron), m->pool);
650
651 tPoleZero_initToPool(&n->f, mp);
490 652
491 tPoleZero_setBlockZero(&n->f, 0.99f);653 tPoleZero_setBlockZero(&n->f, 0.99f);
492 654
@@ -513,52 +675,99 @@ void tNeuron_reset(tNeuron* const n) · 20 unmodified lines
513 n->rate[2] = n->gL/n->C;675 n->rate[2] = n->gL/n->C;
514}676}
515 677
678void 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
687void 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}
516 715
517void tNeuron_setV1(tNeuron* const n, float V1)716void tNeuron_setV1(tNeuron* const nr, float V1)
518{717{
718 _tNeuron* n = *nr;
519 n->V[0] = V1;719 n->V[0] = V1;
520}720}
521 721
522 722
523void tNeuron_setV2(tNeuron* const n, float V2)723void tNeuron_setV2(tNeuron* const nr, float V2)
524{724{
725 _tNeuron* n = *nr;
525 n->V[1] = V2;726 n->V[1] = V2;
526}727}
527 728
528void tNeuron_setV3(tNeuron* const n, float V3)729void tNeuron_setV3(tNeuron* const nr, float V3)
529{730{
731 _tNeuron* n = *nr;
530 n->V[2] = V3;732 n->V[2] = V3;
531}733}
532 734
533void tNeuron_setTimeStep(tNeuron* const n, float timeStep)735void tNeuron_setTimeStep(tNeuron* const nr, float timeStep)
534{736{
737 _tNeuron* n = *nr;
535 n->timeStep = timeStep;738 n->timeStep = timeStep;
536}739}
537 740
538void tNeuron_setK(tNeuron* const n, float K)741void tNeuron_setK(tNeuron* const nr, float K)
539{742{
743 _tNeuron* n = *nr;
540 n->gK = K;744 n->gK = K;
541}745}
542 746
543void tNeuron_setL(tNeuron* const n, float L)747void tNeuron_setL(tNeuron* const nr, float L)
544{748{
749 _tNeuron* n = *nr;
545 n->gL = L;750 n->gL = L;
546 n->rate[2] = n->gL/n->C;751 n->rate[2] = n->gL/n->C;
547}752}
548 753
549void tNeuron_setN(tNeuron* const n, float N)754void tNeuron_setN(tNeuron* const nr, float N)
550{755{
756 _tNeuron* n = *nr;
551 n->gN = N;757 n->gN = N;
552}758}
553 759
554void tNeuron_setC(tNeuron* const n, float C)760void tNeuron_setC(tNeuron* const nr, float C)
555{761{
762 _tNeuron* n = *nr;
556 n->C = C;763 n->C = C;
557 n->rate[2] = n->gL/n->C;764 n->rate[2] = n->gL/n->C;
558}765}
559 766
560float tNeuron_tick(tNeuron* const n)767float tNeuron_tick(tNeuron* const nr)
561{768{
769 _tNeuron* n = *nr;
770
562 float output = 0.0f;771 float output = 0.0f;
563 float voltage = n->voltage;772 float voltage = n->voltage;
564 773
@@ -631,12 +840,14 @@ float tNeuron_tick(tNeuron* const n) · 66 unmodified lines
631 840
632}841}
633 842
634void tNeuron_setMode (tNeuron* const n, NeuronMode mode)843void tNeuron_setMode (tNeuron* const nr, NeuronMode mode)
635{844{
845 _tNeuron* n = *nr;
636 n->mode = mode;846 n->mode = mode;
637}847}
638 848
639void tNeuron_setCurrent (tNeuron* const n, float current)849void tNeuron_setCurrent (tNeuron* const nr, float current)
640{850{
851 _tNeuron* n = *nr;
641 n->current = current;852 n->current = current;
642}853}
LEAF/Src/leaf-physical.c+194−8
@@ -46,6 +46,37 @@ void tPluck_free (tPluck* const pl) · 45 unmodified lines
46 leaf_free(p);46 leaf_free(p);
47}47}
48 48
49void 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
67void 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
49float tPluck_getLastOut (tPluck* const pl)80float tPluck_getLastOut (tPluck* const pl)
50{81{
51 _tPluck* p = *pl;82 _tPluck* p = *pl;
@@ -124,7 +155,7 @@ void tPluckSampleRateChanged(tPluck* const pl) · 72 unmodified lines
124}155}
125 156
126/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tKarplusStrong ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */157/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tKarplusStrong ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
127void tKarplusStrong_init (tKarplusStrong* const pl, float lowestFrequency)158void tKarplusStrong_init (tKarplusStrong* const pl, float lowestFrequency)
128{159{
129 _tKarplusStrong* p = *pl = (_tKarplusStrong*) leaf_alloc(sizeof(_tKarplusStrong));160 _tKarplusStrong* p = *pl = (_tKarplusStrong*) leaf_alloc(sizeof(_tKarplusStrong));
130 161
@@ -151,7 +182,6 @@ void tKarplusStrong_init (tKarplusStrong* const pl, float lowestFreq · 20 unmodified lines
151 p->loopGain = 0.999f;182 p->loopGain = 0.999f;
152 183
153 tKarplusStrong_setFrequency( pl, 220.0f );184 tKarplusStrong_setFrequency( pl, 220.0f );
154
155}185}
156 186
157void tKarplusStrong_free (tKarplusStrong* const pl)187void tKarplusStrong_free (tKarplusStrong* const pl)
@@ -171,6 +201,54 @@ void tKarplusStrong_free (tKarplusStrong* const pl) · 13 unmodified lines
171 leaf_free(p);201 leaf_free(p);
172}202}
173 203
204void 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
234void 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
174float tKarplusStrong_getLastOut (tKarplusStrong* const pl)252float tKarplusStrong_getLastOut (tKarplusStrong* const pl)
175{253{
176 _tKarplusStrong* p = *pl;254 _tKarplusStrong* p = *pl;
@@ -328,7 +406,9 @@ void tKarplusStrongSampleRateChanged (tKarplusStrong* const pl) · 151 unmodified lines
328 406
329/* Simple Living String*/407/* Simple Living String*/
330 408
331void tSimpleLivingString_init(tSimpleLivingString* const pl, float freq, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode)409void tSimpleLivingString_init(tSimpleLivingString* const pl, float freq, float dampFreq,
410 float decay, float targetLev, float levSmoothFactor,
411 float levStrength, int levMode)
332{412{
333 _tSimpleLivingString* p = *pl = (_tSimpleLivingString*) leaf_alloc(sizeof(_tSimpleLivingString));413 _tSimpleLivingString* p = *pl = (_tSimpleLivingString*) leaf_alloc(sizeof(_tSimpleLivingString));
334 414
@@ -356,6 +436,38 @@ void tSimpleLivingString_free(tSimpleLivingString* const pl) · 21 unmodified lines
356 leaf_free(p);436 leaf_free(p);
357}437}
358 438
439void 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
457void 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
359void tSimpleLivingString_setFreq(tSimpleLivingString* const pl, float freq)471void tSimpleLivingString_setFreq(tSimpleLivingString* const pl, float freq)
360{472{
361 _tSimpleLivingString* p = *pl;473 _tSimpleLivingString* p = *pl;
@@ -433,7 +545,9 @@ float tSimpleLivingString_sample(tSimpleLivingString* const pl) · 71 unmodified lines
433 545
434/* Living String*/546/* Living String*/
435 547
436void tLivingString_init(tLivingString* const pl, float freq, float pickPos, float prepIndex, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode)548void 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)
437{551{
438 _tLivingString* p = *pl = (_tLivingString*) leaf_alloc(sizeof(_tLivingString));552 _tLivingString* p = *pl = (_tLivingString*) leaf_alloc(sizeof(_tLivingString));
439 553
@@ -484,6 +598,61 @@ void tLivingString_free(tLivingString* const pl) · 44 unmodified lines
484 leaf_free(p);598 leaf_free(p);
485}599}
486 600
601void 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
633void 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
487void tLivingString_setFreq(tLivingString* const pl, float freq)656void tLivingString_setFreq(tLivingString* const pl, float freq)
488{ // NOTE: It is faster to set wavelength in samples directly657{ // NOTE: It is faster to set wavelength in samples directly
489 _tLivingString* p = *pl;658 _tLivingString* p = *pl;
@@ -577,20 +746,20 @@ float tLivingString_tick(tLivingString* const pl, float input) · 87 unmodified lines
577 tLinearDelay_tickIn(&p->delUB, fromNut);746 tLinearDelay_tickIn(&p->delUB, fromNut);
578 // into lower half of string, from pickpoint, going backwards747 // into lower half of string, from pickpoint, going backwards
579 float fromLowerPrep=-tOnePole_tick(&p->prepFilterL, fromLF);748 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;
581 tLinearDelay_tickIn(&p->delLB, intoLower);750 tLinearDelay_tickIn(&p->delLB, intoLower);
582 // into lower half of string, from bridge751 // 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)));
584 tLinearDelay_tickIn(&p->delLF, fromBridge);753 tLinearDelay_tickIn(&p->delLF, fromBridge);
585 // into upper half of string, from pickpoint, going forwards/upwards754 // into upper half of string, from pickpoint, going forwards/upwards
586 float fromUpperPrep=-tOnePole_tick(&p->prepFilterU, fromUB);755 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;
588 tLinearDelay_tickIn(&p->delUF, intoUpper);757 tLinearDelay_tickIn(&p->delUF, intoUpper);
589 // update all delay lengths758 // update all delay lengths
590 float pickP=tExpSmooth_tick(&p->ppSmooth);759 float pickP=tExpSmooth_tick(&p->ppSmooth);
591 float wLen=tExpSmooth_tick(&p->wlSmooth);760 float wLen=tExpSmooth_tick(&p->wlSmooth);
592 float lowLen=pickP*wLen;761 float lowLen=pickP*wLen;
593 float upLen=(1-pickP)*wLen;762 float upLen=(1.0f-pickP)*wLen;
594 tLinearDelay_setDelay(&p->delLF, lowLen);763 tLinearDelay_setDelay(&p->delLF, lowLen);
595 tLinearDelay_setDelay(&p->delLB, lowLen);764 tLinearDelay_setDelay(&p->delLB, lowLen);
596 tLinearDelay_setDelay(&p->delUF, upLen);765 tLinearDelay_setDelay(&p->delUF, upLen);
@@ -623,6 +792,23 @@ void tReedTable_free (tReedTable* const pm) · 26 unmodified lines
623 leaf_free(p);792 leaf_free(p);
624}793}
625 794
795void 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
804void 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
626float tReedTable_tick (tReedTable* const pm, float input)812float tReedTable_tick (tReedTable* const pm, float input)
627{813{
628 _tReedTable* p = *pm;814 _tReedTable* p = *pm;
LEAF/Src/leaf-reverb.c+215−3
@@ -65,6 +65,54 @@ void tPRCReverb_free(tPRCReverb* const rev) · 64 unmodified lines
65 leaf_free(r);65 leaf_free(r);
66}66}
67 67
68void tPRCReverb_initToPool (tPRCReverb* const rev, float t60, tMempool* const mp)
69{
70 _tMempool* m = *mp;
71 _tPRCReverb* r = *rev = (_tPRCReverb*) mpool_alloc(sizeof(_tPRCReverb), m->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
105void tPRCReverb_freeFromPool (tPRCReverb* const rev, tMempool* const mp)
106{
107 _tMempool* m = *mp;
108 _tPRCReverb* r = *rev;
109
110 tDelay_freeFromPool(&r->allpassDelays[0], mp);
111 tDelay_freeFromPool(&r->allpassDelays[1], mp);
112 tDelay_freeFromPool(&r->combDelay, mp);
113 mpool_free(r, m->pool);
114}
115
68void tPRCReverb_setT60(tPRCReverb* const rev, float t60)116void tPRCReverb_setT60(tPRCReverb* const rev, float t60)
69{117{
70 _tPRCReverb* r = *rev;118 _tPRCReverb* r = *rev;
@@ -150,12 +198,14 @@ void tNReverb_init(tNReverb* const rev, float t60) · 79 unmodified lines
150 for ( i=0; i<6; i++ )198 for ( i=0; i<6; i++ )
151 {199 {
152 tLinearDelay_init(&r->combDelays[i], lengths[i], lengths[i] * 2.0f);200 tLinearDelay_init(&r->combDelays[i], lengths[i], lengths[i] * 2.0f);
201 tLinearDelay_clear(&r->combDelays[i]);
153 r->combCoeffs[i] = pow(10.0, (-3 * lengths[i] * leaf.invSampleRate / t60));202 r->combCoeffs[i] = pow(10.0, (-3 * lengths[i] * leaf.invSampleRate / t60));
154 }203 }
155 204
156 for ( i=0; i<8; i++ )205 for ( i=0; i<8; i++ )
157 {206 {
158 tLinearDelay_init(&r->allpassDelays[i], lengths[i+6], lengths[i+6] * 2.0f);207 tLinearDelay_init(&r->allpassDelays[i], lengths[i+6], lengths[i+6] * 2.0f);
208 tLinearDelay_clear(&r->allpassDelays[i]);
159 }209 }
160 210
161 211
@@ -181,6 +231,65 @@ void tNReverb_free(tNReverb* const rev) · 19 unmodified lines
181 leaf_free(r);231 leaf_free(r);
182}232}
183 233
234void 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
275void 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
184void tNReverb_setT60(tNReverb* const rev, float t60)293void tNReverb_setT60(tNReverb* const rev, float t60)
185{294{
186 _tNReverb* r = *rev;295 _tNReverb* r = *rev;
@@ -204,7 +313,7 @@ float tNReverb_tick(tNReverb* const rev, float input) · 17 unmodified lines
204 _tNReverb* r = *rev;313 _tNReverb* r = *rev;
205 r->lastIn = input;314 r->lastIn = input;
206 315
207 float temp, temp0, temp1, temp2, temp3, out;316 float temp, temp0, temp1, temp2, out;
208 int i;317 int i;
209 318
210 temp0 = 0.0;319 temp0 = 0.0;
@@ -381,8 +490,6 @@ void tDattorroReverb_init (tDattorroReverb* const rev) · 170 unmodified lines
381 tDattorroReverb_setFeedbackFilter(rev, 5000.f);490 tDattorroReverb_setFeedbackFilter(rev, 5000.f);
382 491
383 tDattorroReverb_setFeedbackGain(rev, 0.4f);492 tDattorroReverb_setFeedbackGain(rev, 0.4f);
384
385
386}493}
387 494
388void tDattorroReverb_free (tDattorroReverb* const rev)495void tDattorroReverb_free (tDattorroReverb* const rev)
@@ -427,6 +534,111 @@ void tDattorroReverb_free (tDattorroReverb* const rev) · 38 unmodified lines
427 leaf_free(r);534 leaf_free(r);
428}535}
429 536
537void 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
599void 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
430float tDattorroReverb_tick (tDattorroReverb* const rev, float input)642float tDattorroReverb_tick (tDattorroReverb* const rev, float input)
431{643{
432 _tDattorroReverb* r = *rev;644 _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
35 s->active = 0;35 s->active = 0;
36 s->idx = 0;36 s->idx = 0;
37 s->mode = RecordOneShot;37 s->mode = RecordOneShot;
38
39 tBuffer_clear(sb);
40}
41
42void 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);
54}38}
55 39
56void tBuffer_free (tBuffer* const sb)40void tBuffer_free (tBuffer* const sb)
@@ -61,15 +45,28 @@ void tBuffer_free (tBuffer* const sb) · 4 unmodified lines
61 leaf_free(s);45 leaf_free(s);
62}46}
63 47
64void tBuffer_free_locate (tBuffer* const sb, mpool_t* pool)48void tBuffer_initToPool (tBuffer* const sb, uint32_t length, tMempool* const mp)
65{49{
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
61void tBuffer_freeFromPool (tBuffer* const sb, tMempool* const mp)
62{
63 _tMempool* m = *mp;
66 _tBuffer* s = *sb;64 _tBuffer* s = *sb;
67 65
68 mpool_free(s->buff, pool);66 mpool_free(s->buff, m->pool);
69 mpool_free(s, pool);67 mpool_free(s, m->pool);
70}68}
71 69
72
73void tBuffer_tick (tBuffer* const sb, float sample)70void tBuffer_tick (tBuffer* const sb, float sample)
74{71{
75 _tBuffer* s = *sb;72 _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