Unified · Split
Binary file not shown.
| @@ -33,12 +33,14 @@ extern "C" { · 32 unmodified lines | ||
| 33 | 33 | |
| 34 | 34 | typedef _tEnvelopeFollower* tEnvelopeFollower; |
| 35 | 35 | |
| 36 | − void tEnvelopeFollower_init (tEnvelopeFollower* const, float attackThreshold, float decayCoeff); | |
| 37 | − void tEnvelopeFollower_free (tEnvelopeFollower* const); | |
| 36 | + void tEnvelopeFollower_init (tEnvelopeFollower* const, float attackThreshold, float decayCoeff); | |
| 37 | + void tEnvelopeFollower_free (tEnvelopeFollower* const); | |
| 38 | + void tEnvelopeFollower_initToPool (tEnvelopeFollower* const, float attackThreshold, float decayCoeff, tMempool* const); | |
| 39 | + void tEnvelopeFollower_freeFromPool (tEnvelopeFollower* const, tMempool* const); | |
| 38 | 40 | |
| 39 | − float tEnvelopeFollower_tick (tEnvelopeFollower* const, float x); | |
| 40 | − int tEnvelopeFollower_decayCoeff (tEnvelopeFollower* const, float decayCoeff); | |
| 41 | − int tEnvelopeFollower_attackThresh (tEnvelopeFollower* const, float attackThresh); | |
| 41 | + float tEnvelopeFollower_tick (tEnvelopeFollower* const, float x); | |
| 42 | + int tEnvelopeFollower_decayCoeff (tEnvelopeFollower* const, float decayCoeff); | |
| 43 | + int tEnvelopeFollower_attackThresh (tEnvelopeFollower* const, float attackThresh); | |
| 42 | 44 | |
| 43 | 45 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
| 44 | 46 | |
| @@ -51,11 +53,14 @@ extern "C" { · 6 unmodified lines | ||
| 51 | 53 | |
| 52 | 54 | typedef _tPowerFollower* tPowerFollower; |
| 53 | 55 | |
| 54 | − void tPowerFollower_init (tPowerFollower* const, float factor); | |
| 55 | − void tPowerFollower_free (tPowerFollower* const); | |
| 56 | − float tPowerFollower_tick (tPowerFollower* const, float input); | |
| 57 | − float tPowerFollower_sample (tPowerFollower* const); | |
| 58 | − int tPowerFollower_setFactor (tPowerFollower* const, float factor); | |
| 56 | + void tPowerFollower_init (tPowerFollower* const, float factor); | |
| 57 | + void tPowerFollower_free (tPowerFollower* const); | |
| 58 | + void tPowerFollower_initToPool (tPowerFollower* const, float factor, tMempool* const); | |
| 59 | + void tPowerFollower_freeFromPool (tPowerFollower* const, tMempool* const); | |
| 60 | + | |
| 61 | + float tPowerFollower_tick (tPowerFollower* const, float input); | |
| 62 | + float tPowerFollower_sample (tPowerFollower* const); | |
| 63 | + int tPowerFollower_setFactor (tPowerFollower* const, float factor); | |
| 59 | 64 | |
| 60 | 65 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
| 61 | 66 | |
| @@ -81,10 +86,13 @@ extern "C" { · 19 unmodified lines | ||
| 81 | 86 | |
| 82 | 87 | typedef _tEnvPD* tEnvPD; |
| 83 | 88 | |
| 84 | − void tEnvPD_init (tEnvPD* const, int windowSize, int hopSize, int blockSize); | |
| 85 | − void tEnvPD_free (tEnvPD* const); | |
| 86 | − float tEnvPD_tick (tEnvPD* const); | |
| 87 | − void tEnvPD_processBlock (tEnvPD* const, float* in); | |
| 89 | + void tEnvPD_init (tEnvPD* const, int windowSize, int hopSize, int blockSize); | |
| 90 | + void tEnvPD_free (tEnvPD* const); | |
| 91 | + void tEnvPD_initToPool (tEnvPD* const, int windowSize, int hopSize, int blockSize, tMempool* const); | |
| 92 | + void tEnvPD_freeFromPool (tEnvPD* const, tMempool* const); | |
| 93 | + | |
| 94 | + float tEnvPD_tick (tEnvPD* const); | |
| 95 | + void tEnvPD_processBlock (tEnvPD* const, float* in); | |
| 88 | 96 | |
| 89 | 97 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
| 90 | 98 | |
| @@ -117,27 +125,28 @@ extern "C" { · 26 unmodified lines | ||
| 117 | 125 | |
| 118 | 126 | typedef _tAttackDetection* tAttackDetection; |
| 119 | 127 | |
| 120 | − void tAttackDetection_init (tAttackDetection* const, int blocksize); | |
| 121 | − void tAttackDetection_init_expanded (tAttackDetection* const, int blocksize, int atk, int rel); | |
| 122 | − void tAttackDetection_free (tAttackDetection* const); | |
| 128 | + void tAttackDetection_init (tAttackDetection* const, int blocksize, int atk, int rel); | |
| 129 | + void tAttackDetection_free (tAttackDetection* const); | |
| 130 | + void tAttackDetection_initToPool (tAttackDetection* const, int blocksize, int atk, int rel, tMempool* const); | |
| 131 | + void tAttackDetection_freeFromPool (tAttackDetection* const, tMempool* const); | |
| 123 | 132 | |
| 124 | 133 | // set expected input blocksize |
| 125 | − void tAttackDetection_setBlocksize (tAttackDetection* const, int size); | |
| 134 | + void tAttackDetection_setBlocksize (tAttackDetection* const, int size); | |
| 126 | 135 | |
| 127 | 136 | // change atkDetector sample rate |
| 128 | − void tAttackDetection_setSamplerate (tAttackDetection* const, int inRate); | |
| 137 | + void tAttackDetection_setSamplerate (tAttackDetection* const, int inRate); | |
| 129 | 138 | |
| 130 | 139 | // set attack time and coeff |
| 131 | − void tAttackDetection_setAtk (tAttackDetection* const, int inAtk); | |
| 140 | + void tAttackDetection_setAttack (tAttackDetection* const, int inAtk); | |
| 132 | 141 | |
| 133 | 142 | // set release time and coeff |
| 134 | − void tAttackDetection_setRel (tAttackDetection* const, int inRel); | |
| 143 | + void tAttackDetection_setRelease (tAttackDetection* const, int inRel); | |
| 135 | 144 | |
| 136 | 145 | // 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 | 148 | // 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 | 178 | typedef _tSNAC* tSNAC; |
| 170 | 179 | |
| 171 | − void tSNAC_init (tSNAC* const, int overlaparg); // constructor | |
| 172 | − void tSNAC_free (tSNAC* const); // destructor | |
| 180 | + void tSNAC_init (tSNAC* const, int overlaparg); | |
| 181 | + void tSNAC_free (tSNAC* const); | |
| 182 | + void tSNAC_initToPool (tSNAC* const, int overlaparg, tMempool* const); | |
| 183 | + void tSNAC_freeFromPool (tSNAC* const, tMempool* const); | |
| 173 | 184 | |
| 174 | 185 | void tSNAC_ioSamples (tSNAC *s, float *in, float *out, int size); |
| 175 | 186 | void tSNAC_setOverlap (tSNAC *s, int lap); |
| @@ -178,7 +189,7 @@ extern "C" { · 2 unmodified lines | ||
| 178 | 189 | |
| 179 | 190 | /*To get freq, perform SAMPLE_RATE/snac_getperiod() */ |
| 180 | 191 | float tSNAC_getPeriod (tSNAC *s); |
| 181 | − float tSNAC_getfidelity (tSNAC *s); | |
| 192 | + float tSNAC_getFidelity (tSNAC *s); | |
| 182 | 193 | |
| 183 | 194 | #define DEFPITCHRATIO 2.0f |
| 184 | 195 | #define DEFTIMECONSTANT 100.0f |
| @@ -220,12 +231,14 @@ extern "C" { · 35 unmodified lines | ||
| 220 | 231 | |
| 221 | 232 | typedef _tPeriodDetection* tPeriodDetection; |
| 222 | 233 | |
| 223 | − void tPeriodDetection_init (tPeriodDetection* const, float* in, float* out, int bufSize, int frameSize); | |
| 224 | − void tPeriodDetection_free (tPeriodDetection* const); | |
| 234 | + void tPeriodDetection_init (tPeriodDetection* const, float* in, float* out, int bufSize, int frameSize); | |
| 235 | + void tPeriodDetection_free (tPeriodDetection* const); | |
| 236 | + void tPeriodDetection_initToPool (tPeriodDetection* const, float* in, float* out, int bufSize, int frameSize, tMempool* const); | |
| 237 | + void tPeriodDetection_freeFromPool (tPeriodDetection* const, tMempool* const); | |
| 225 | 238 | |
| 226 | − float tPeriodDetection_findPeriod (tPeriodDetection* const, float sample); | |
| 227 | − void tPeriodDetection_setHopSize (tPeriodDetection* p, int hs); | |
| 228 | − void tPeriodDetection_setWindowSize (tPeriodDetection* p, int ws); | |
| 239 | + float tPeriodDetection_findPeriod (tPeriodDetection* const, float sample); | |
| 240 | + void tPeriodDetection_setHopSize (tPeriodDetection* p, int hs); | |
| 241 | + void tPeriodDetection_setWindowSize (tPeriodDetection* p, int ws); | |
| 229 | 242 | |
| 230 | 243 | //============================================================================== |
| 231 | 244 | |
| @@ -16,6 +16,7 @@ extern "C" { · 15 unmodified lines | ||
| 16 | 16 | //============================================================================== |
| 17 | 17 | |
| 18 | 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 | 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 | 40 | void tDelay_free (tDelay* const); |
| 40 | − | |
| 41 | − int tDelay_setDelay (tDelay* const, uint32_t delay); | |
| 42 | − uint32_t tDelay_getDelay (tDelay* const); | |
| 43 | − void tDelay_tapIn (tDelay* const, float in, uint32_t tapDelay); | |
| 44 | − float tDelay_tapOut (tDelay* const, uint32_t tapDelay); | |
| 45 | − float tDelay_addTo (tDelay* const, float value, uint32_t tapDelay); | |
| 46 | − float tDelay_tick (tDelay* const, float sample); | |
| 47 | − float tDelay_getLastOut (tDelay* const); | |
| 48 | − float tDelay_getLastIn (tDelay* const); | |
| 41 | + void tDelay_initToPool (tDelay* const, uint32_t delay, uint32_t maxDelay, tMempool* const); | |
| 42 | + void tDelay_freeFromPool (tDelay* const, tMempool* const); | |
| 43 | + | |
| 44 | + int tDelay_setDelay (tDelay* const, uint32_t delay); | |
| 45 | + uint32_t tDelay_getDelay (tDelay* const); | |
| 46 | + void tDelay_tapIn (tDelay* const, float in, uint32_t tapDelay); | |
| 47 | + float tDelay_tapOut (tDelay* const, uint32_t tapDelay); | |
| 48 | + float tDelay_addTo (tDelay* const, float value, uint32_t tapDelay); | |
| 49 | + float tDelay_tick (tDelay* const, float sample); | |
| 50 | + float tDelay_getLastOut (tDelay* const); | |
| 51 | + float tDelay_getLastIn (tDelay* const); | |
| 49 | 52 | |
| 50 | 53 | //============================================================================== |
| 51 | 54 | |
| @@ -69,20 +72,65 @@ extern "C" { · 17 unmodified lines | ||
| 69 | 72 | |
| 70 | 73 | typedef _tLinearDelay* tLinearDelay; |
| 71 | 74 | |
| 72 | − void tLinearDelay_init (tLinearDelay* const, float delay, uint32_t maxDelay); | |
| 73 | − void tLinearDelay_free (tLinearDelay* const); | |
| 74 | − | |
| 75 | − int tLinearDelay_setDelay (tLinearDelay* const, float delay); | |
| 76 | − float tLinearDelay_getDelay (tLinearDelay* const); | |
| 77 | − void tLinearDelay_tapIn (tLinearDelay* const, float in, uint32_t tapDelay); | |
| 78 | − float tLinearDelay_tapOut (tLinearDelay* const, float tapDelay); | |
| 79 | − float tLinearDelay_addTo (tLinearDelay* const, float value, uint32_t tapDelay); | |
| 80 | − float tLinearDelay_tick (tLinearDelay* const, float sample); | |
| 81 | − void tLinearDelay_tickIn (tLinearDelay* const, float input); | |
| 82 | − float tLinearDelay_tickOut (tLinearDelay* const); | |
| 83 | − float tLinearDelay_getLastOut (tLinearDelay* const); | |
| 84 | − float tLinearDelay_getLastIn (tLinearDelay* const); | |
| 75 | + void tLinearDelay_init (tLinearDelay* const, float delay, uint32_t maxDelay); | |
| 76 | + void tLinearDelay_free (tLinearDelay* const); | |
| 77 | + void tLinearDelay_initToPool (tLinearDelay* const, float delay, uint32_t maxDelay, tMempool* const); | |
| 78 | + void tLinearDelay_freeFromPool(tLinearDelay* const, tMempool* const); | |
| 79 | + void tLinearDelay_clear (tLinearDelay* const dl); | |
| 80 | + int tLinearDelay_setDelay (tLinearDelay* const, float delay); | |
| 81 | + float tLinearDelay_getDelay (tLinearDelay* const); | |
| 82 | + void tLinearDelay_tapIn (tLinearDelay* const, float in, uint32_t tapDelay); | |
| 83 | + float tLinearDelay_tapOut (tLinearDelay* const, uint32_t tapDelay); | |
| 84 | + float tLinearDelay_addTo (tLinearDelay* const, float value, uint32_t tapDelay); | |
| 85 | + float tLinearDelay_tick (tLinearDelay* const, float sample); | |
| 86 | + void tLinearDelay_tickIn (tLinearDelay* const, float input); | |
| 87 | + float tLinearDelay_tickOut (tLinearDelay* const); | |
| 88 | + float tLinearDelay_getLastOut (tLinearDelay* const); | |
| 89 | + float tLinearDelay_getLastIn (tLinearDelay* const); | |
| 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 | 136 | /* Allpass-interpolating delay, reimplemented from STK (Cook and Scavone). */ |
| @@ -107,17 +155,19 @@ extern "C" { · 18 unmodified lines | ||
| 107 | 155 | |
| 108 | 156 | typedef _tAllpassDelay* tAllpassDelay; |
| 109 | 157 | |
| 110 | − void tAllpassDelay_init (tAllpassDelay* const, float delay, uint32_t maxDelay); | |
| 111 | − void tAllpassDelay_free (tAllpassDelay* const); | |
| 158 | + void tAllpassDelay_init (tAllpassDelay* const, float delay, uint32_t maxDelay); | |
| 159 | + void tAllpassDelay_free (tAllpassDelay* const); | |
| 160 | + void tAllpassDelay_initToPool (tAllpassDelay* const, float delay, uint32_t maxDelay, tMempool* const); | |
| 161 | + void tAllpassDelay_freeFromPool(tAllpassDelay* const, tMempool* const); | |
| 112 | 162 | |
| 113 | − int tAllpassDelay_setDelay (tAllpassDelay* const, float delay); | |
| 114 | − float tAllpassDelay_getDelay (tAllpassDelay* const); | |
| 115 | − void tAllpassDelay_tapIn (tAllpassDelay* const, float in, uint32_t tapDelay); | |
| 116 | − float tAllpassDelay_tapOut (tAllpassDelay* const, uint32_t tapDelay); | |
| 117 | − float tAllpassDelay_addTo (tAllpassDelay* const, float value, uint32_t tapDelay); | |
| 118 | − float tAllpassDelay_tick (tAllpassDelay* const, float sample); | |
| 119 | − float tAllpassDelay_getLastOut (tAllpassDelay* const); | |
| 120 | − float tAllpassDelay_getLastIn (tAllpassDelay* const); | |
| 163 | + int tAllpassDelay_setDelay (tAllpassDelay* const, float delay); | |
| 164 | + float tAllpassDelay_getDelay (tAllpassDelay* const); | |
| 165 | + void tAllpassDelay_tapIn (tAllpassDelay* const, float in, uint32_t tapDelay); | |
| 166 | + float tAllpassDelay_tapOut (tAllpassDelay* const, uint32_t tapDelay); | |
| 167 | + float tAllpassDelay_addTo (tAllpassDelay* const, float value, uint32_t tapDelay); | |
| 168 | + float tAllpassDelay_tick (tAllpassDelay* const, float sample); | |
| 169 | + float tAllpassDelay_getLastOut (tAllpassDelay* const); | |
| 170 | + float tAllpassDelay_getLastIn (tAllpassDelay* const); | |
| 121 | 171 | |
| 122 | 172 | //============================================================================== |
| 123 | 173 | |
| @@ -141,18 +191,20 @@ extern "C" { · 17 unmodified lines | ||
| 141 | 191 | |
| 142 | 192 | typedef _tTapeDelay* tTapeDelay; |
| 143 | 193 | |
| 144 | − void tTapeDelay_init (tTapeDelay* const, float delay, uint32_t maxDelay); | |
| 145 | − void tTapeDelay_free (tTapeDelay* const); | |
| 146 | − | |
| 147 | − void tTapeDelay_setDelay (tTapeDelay* const, float delay); | |
| 148 | − float tTapeDelay_getDelay (tTapeDelay* const); | |
| 149 | − void tTapeDelay_tapIn (tTapeDelay* const, float in, uint32_t tapDelay); | |
| 150 | − float tTapeDelay_tapOut (tTapeDelay* const d, float tapDelay); | |
| 151 | − float tTapeDelay_addTo (tTapeDelay* const, float value, uint32_t tapDelay); | |
| 152 | − float tTapeDelay_tick (tTapeDelay* const, float sample); | |
| 153 | − void tTapeDelay_incrementInPoint(tTapeDelay* const dl); | |
| 154 | − float tTapeDelay_getLastOut (tTapeDelay* const); | |
| 155 | − float tTapeDelay_getLastIn (tTapeDelay* const); | |
| 194 | + void tTapeDelay_init (tTapeDelay* const, float delay, uint32_t maxDelay); | |
| 195 | + void tTapeDelay_free (tTapeDelay* const); | |
| 196 | + void tTapeDelay_initToPool (tTapeDelay* const, float delay, uint32_t maxDelay, tMempool* const); | |
| 197 | + void tTapeDelay_freeFromPool(tTapeDelay* const, tMempool* const); | |
| 198 | + | |
| 199 | + void tTapeDelay_setDelay (tTapeDelay* const, float delay); | |
| 200 | + float tTapeDelay_getDelay (tTapeDelay* const); | |
| 201 | + void tTapeDelay_tapIn (tTapeDelay* const, float in, uint32_t tapDelay); | |
| 202 | + float tTapeDelay_tapOut (tTapeDelay* const d, float tapDelay); | |
| 203 | + float tTapeDelay_addTo (tTapeDelay* const, float value, uint32_t tapDelay); | |
| 204 | + float tTapeDelay_tick (tTapeDelay* const, float sample); | |
| 205 | + void tTapeDelay_incrementInPoint(tTapeDelay* const dl); | |
| 206 | + float tTapeDelay_getLastOut (tTapeDelay* const); | |
| 207 | + float tTapeDelay_getLastIn (tTapeDelay* const); | |
| 156 | 208 | |
| 157 | 209 | //============================================================================== |
| 158 | 210 | |
| @@ -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 | 69 | /* tLockhartWavefolder */ |
| 25 | 70 | |
| 26 | 71 | typedef struct _tLockhartWavefolder |
| @@ -49,29 +94,10 @@ extern "C" { · 22 unmodified lines | ||
| 49 | 94 | |
| 50 | 95 | void tLockhartWavefolder_init (tLockhartWavefolder* const); |
| 51 | 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 | 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 | 119 | void tCrusher_init (tCrusher* const); |
| 94 | 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 | 124 | float tCrusher_tick (tCrusher* const, float input); |
| 97 | 125 | |
| @@ -107,29 +135,6 @@ extern "C" { · 9 unmodified lines | ||
| 107 | 135 | // sampling ratio |
| 108 | 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 | 140 | #ifdef __cplusplus |
| @@ -18,6 +18,7 @@ extern "C" { · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | #include "leaf-global.h" |
| 20 | 20 | #include "leaf-math.h" |
| 21 | +#include "leaf-mempool.h" | |
| 21 | 22 | #include "leaf-analysis.h" |
| 22 | 23 | |
| 23 | 24 | //============================================================================== |
| @@ -38,9 +39,12 @@ extern "C" { · 14 unmodified lines | ||
| 38 | 39 | |
| 39 | 40 | typedef _tCompressor* tCompressor; |
| 40 | 41 | |
| 41 | − void tCompressor_init (tCompressor* const); | |
| 42 | − void tCompressor_free (tCompressor* const); | |
| 43 | − float tCompressor_tick (tCompressor* const, float input); | |
| 42 | + void tCompressor_init (tCompressor* const); | |
| 43 | + void tCompressor_free (tCompressor* const); | |
| 44 | + void tCompressor_initToPool (tCompressor* const, tMempool* const); | |
| 45 | + void tCompressor_freeFromPool(tCompressor* const, tMempool* const); | |
| 46 | + | |
| 47 | + float tCompressor_tick (tCompressor* const, float input); | |
| 44 | 48 | |
| 45 | 49 | /// |
| 46 | 50 | /* Feedback leveller */ |
| @@ -61,15 +65,17 @@ extern "C" { · 14 unmodified lines | ||
| 61 | 65 | |
| 62 | 66 | typedef _tFeedbackLeveler* tFeedbackLeveler; |
| 63 | 67 | |
| 64 | − void tFeedbackLeveler_init (tFeedbackLeveler* const, float targetLevel, float factor, float strength, int mode); | |
| 65 | − void tFeedbackLeveler_free (tFeedbackLeveler* const); | |
| 68 | + void tFeedbackLeveler_init (tFeedbackLeveler* const, float targetLevel, float factor, float strength, int mode); | |
| 69 | + void tFeedbackLeveler_free (tFeedbackLeveler* const); | |
| 70 | + void tFeedbackLeveler_initToPool (tFeedbackLeveler* const, float targetLevel, float factor, float strength, int mode, tMempool* const); | |
| 71 | + void tFeedbackLeveler_freeFromPool (tFeedbackLeveler* const, tMempool* const); | |
| 66 | 72 | |
| 67 | − float tFeedbackLeveler_tick (tFeedbackLeveler* const, float input); | |
| 68 | − float tFeedbackLeveler_sample (tFeedbackLeveler* const); | |
| 69 | − void tFeedbackLeveler_setTargetLevel (tFeedbackLeveler* const, float TargetLevel); | |
| 70 | − void tFeedbackLeveler_setFactor (tFeedbackLeveler* const, float factor); | |
| 71 | − void tFeedbackLeveler_setMode (tFeedbackLeveler* const, int mode); // 0 for upwards limiting only, 1 for biderctional limiting | |
| 72 | − void tFeedbackLeveler_setStrength (tFeedbackLeveler* const, float strength); | |
| 73 | + float tFeedbackLeveler_tick (tFeedbackLeveler* const, float input); | |
| 74 | + float tFeedbackLeveler_sample (tFeedbackLeveler* const); | |
| 75 | + void tFeedbackLeveler_setTargetLevel (tFeedbackLeveler* const, float TargetLevel); | |
| 76 | + void tFeedbackLeveler_setFactor (tFeedbackLeveler* const, float factor); | |
| 77 | + void tFeedbackLeveler_setMode (tFeedbackLeveler* const, int mode); // 0 for upwards limiting only, 1 for biderctional limiting | |
| 78 | + void tFeedbackLeveler_setStrength (tFeedbackLeveler* const, float strength); | |
| 73 | 79 | |
| 74 | 80 | |
| 75 | 81 | //============================================================================== |
| @@ -14,9 +14,10 @@ extern "C" { · 13 unmodified lines | ||
| 14 | 14 | #endif |
| 15 | 15 | |
| 16 | 16 | //============================================================================== |
| 17 | −#include "leaf-dynamics.h" | |
| 18 | 17 | #include "leaf-global.h" |
| 19 | 18 | #include "leaf-math.h" |
| 19 | +#include "leaf-mempool.h" | |
| 20 | +#include "leaf-dynamics.h" | |
| 20 | 21 | #include "leaf-analysis.h" |
| 21 | 22 | |
| 22 | 23 | //============================================================================== |
| @@ -45,14 +46,17 @@ extern "C" { · 22 unmodified lines | ||
| 45 | 46 | |
| 46 | 47 | typedef _tTalkbox* tTalkbox; |
| 47 | 48 | |
| 48 | − void tTalkbox_init (tTalkbox* const, int bufsize); | |
| 49 | − void tTalkbox_free (tTalkbox* const); | |
| 50 | − float tTalkbox_tick (tTalkbox* const, float synth, float voice); | |
| 51 | − void tTalkbox_update (tTalkbox* const); | |
| 52 | − void tTalkbox_suspend (tTalkbox* const); | |
| 53 | − void tTalkbox_lpcDurbin (float *r, int p, float *k, float *g); | |
| 54 | − void tTalkbox_lpc (float *buf, float *car, int32_t n, int32_t o); | |
| 55 | − void tTalkbox_setQuality (tTalkbox* const, float quality); | |
| 49 | + void tTalkbox_init (tTalkbox* const, int bufsize); | |
| 50 | + void tTalkbox_free (tTalkbox* const); | |
| 51 | + void tTalkbox_initToPool (tTalkbox* const, int bufsize, tMempool* const); | |
| 52 | + void tTalkbox_freeFromPool (tTalkbox* const, tMempool* const); | |
| 53 | + | |
| 54 | + float tTalkbox_tick (tTalkbox* const, float synth, float voice); | |
| 55 | + void tTalkbox_update (tTalkbox* const); | |
| 56 | + void tTalkbox_suspend (tTalkbox* const); | |
| 57 | + void tTalkbox_lpcDurbin (float *r, int p, float *k, float *g); | |
| 58 | + void tTalkbox_lpc (float *buf, float *car, int32_t n, int32_t o); | |
| 59 | + void tTalkbox_setQuality (tTalkbox* const, float quality); | |
| 56 | 60 | |
| 57 | 61 | //============================================================================== |
| 58 | 62 | |
| @@ -77,11 +81,14 @@ extern "C" { · 18 unmodified lines | ||
| 77 | 81 | |
| 78 | 82 | typedef _tVocoder* tVocoder; |
| 79 | 83 | |
| 80 | − void tVocoder_init (tVocoder* const); | |
| 81 | − void tVocoder_free (tVocoder* const); | |
| 82 | − float tVocoder_tick (tVocoder* const, float synth, float voice); | |
| 83 | − void tVocoder_update (tVocoder* const); | |
| 84 | − void tVocoder_suspend (tVocoder* const); | |
| 84 | + void tVocoder_init (tVocoder* const); | |
| 85 | + void tVocoder_free (tVocoder* const); | |
| 86 | + void tVocoder_initToPool (tVocoder* const, tMempool* const); | |
| 87 | + void tVocoder_freeFromPool (tVocoder* const, tMempool* const); | |
| 88 | + | |
| 89 | + float tVocoder_tick (tVocoder* const, float synth, float voice); | |
| 90 | + void tVocoder_update (tVocoder* const); | |
| 91 | + void tVocoder_suspend (tVocoder* const); | |
| 85 | 92 | |
| 86 | 93 | //============================================================================== |
| 87 | 94 | |
| @@ -117,6 +124,9 @@ extern "C" { · 29 unmodified lines | ||
| 117 | 124 | |
| 118 | 125 | void tSOLAD_init (tSOLAD* const); |
| 119 | 126 | void tSOLAD_free (tSOLAD* const); |
| 127 | + void tSOLAD_initToPool (tSOLAD* const, tMempool* const); | |
| 128 | + void tSOLAD_freeFromPool (tSOLAD* const, tMempool* const); | |
| 129 | + | |
| 120 | 130 | // send one block of input samples, receive one block of output samples |
| 121 | 131 | void tSOLAD_ioSamples (tSOLAD *w, float* in, float* out, int blocksize); |
| 122 | 132 | // set periodicity analysis data |
| @@ -151,12 +161,15 @@ extern "C" { · 28 unmodified lines | ||
| 151 | 161 | |
| 152 | 162 | typedef _tPitchShift* tPitchShift; |
| 153 | 163 | |
| 154 | − void tPitchShift_init (tPitchShift* const, tPeriodDetection* const, float* out, int bufSize); | |
| 155 | − void tPitchShift_free (tPitchShift* const); | |
| 156 | − float tPitchShift_shift (tPitchShift* const); | |
| 157 | − float tPitchShift_shiftToFunc (tPitchShift* const, float (*fun)(float)); | |
| 158 | − float tPitchShift_shiftToFreq (tPitchShift* const, float freq); | |
| 159 | − void tPitchShift_setPitchFactor (tPitchShift* const, float pf); | |
| 164 | + void tPitchShift_init (tPitchShift* const, tPeriodDetection* const, float* out, int bufSize); | |
| 165 | + void tPitchShift_free (tPitchShift* const); | |
| 166 | + void tPitchShift_initToPool (tPitchShift* const, tPeriodDetection* const, float* out, int bufSize, tMempool* const); | |
| 167 | + void tPitchShift_freeFromPool (tPitchShift* const, tMempool* const); | |
| 168 | + | |
| 169 | + float tPitchShift_shift (tPitchShift* const); | |
| 170 | + float tPitchShift_shiftToFunc (tPitchShift* const, float (*fun)(float)); | |
| 171 | + float tPitchShift_shiftToFreq (tPitchShift* const, float freq); | |
| 172 | + void tPitchShift_setPitchFactor (tPitchShift* const, float pf); | |
| 160 | 173 | |
| 161 | 174 | // Retune |
| 162 | 175 | typedef struct _tRetune |
| @@ -185,18 +198,20 @@ extern "C" { · 22 unmodified lines | ||
| 185 | 198 | |
| 186 | 199 | typedef _tRetune* tRetune; |
| 187 | 200 | |
| 188 | − void tRetune_init (tRetune* const, int numVoices, int bufSize, int frameSize); | |
| 189 | − void tRetune_free (tRetune* const); | |
| 190 | − | |
| 191 | − float* tRetune_tick (tRetune* const, float sample); | |
| 192 | − void tRetune_setNumVoices (tRetune* const, int numVoices); | |
| 193 | − void tRetune_setPitchFactors (tRetune* const, float pf); | |
| 194 | − void tRetune_setPitchFactor (tRetune* const, float pf, int voice); | |
| 195 | − void tRetune_setTimeConstant (tRetune* const, float tc); | |
| 196 | − void tRetune_setHopSize (tRetune* const, int hs); | |
| 197 | − void tRetune_setWindowSize (tRetune* const, int ws); | |
| 198 | − float tRetune_getInputPeriod (tRetune* const); | |
| 199 | − float tRetune_getInputFreq (tRetune* const); | |
| 201 | + void tRetune_init (tRetune* const, int numVoices, int bufSize, int frameSize); | |
| 202 | + void tRetune_free (tRetune* const); | |
| 203 | + void tRetune_initToPool (tRetune* const, int numVoices, int bufSize, int frameSize, tMempool* const); | |
| 204 | + void tRetune_freeFromPool (tRetune* const, tMempool* const); | |
| 205 | + | |
| 206 | + float* tRetune_tick (tRetune* const, float sample); | |
| 207 | + void tRetune_setNumVoices (tRetune* const, int numVoices); | |
| 208 | + void tRetune_setPitchFactors (tRetune* const, float pf); | |
| 209 | + void tRetune_setPitchFactor (tRetune* const, float pf, int voice); | |
| 210 | + void tRetune_setTimeConstant (tRetune* const, float tc); | |
| 211 | + void tRetune_setHopSize (tRetune* const, int hs); | |
| 212 | + void tRetune_setWindowSize (tRetune* const, int ws); | |
| 213 | + float tRetune_getInputPeriod (tRetune* const); | |
| 214 | + float tRetune_getInputFreq (tRetune* const); | |
| 200 | 215 | |
| 201 | 216 | // Autotune |
| 202 | 217 | typedef struct _tAutotune |
| @@ -225,18 +240,20 @@ extern "C" { · 22 unmodified lines | ||
| 225 | 240 | |
| 226 | 241 | typedef _tAutotune* tAutotune; |
| 227 | 242 | |
| 228 | − void tAutotune_init (tAutotune* const, int numVoices, int bufSize, int frameSize); | |
| 229 | − void tAutotune_free (tAutotune* const); | |
| 230 | − | |
| 231 | − float* tAutotune_tick (tAutotune* const, float sample); | |
| 232 | − void tAutotune_setNumVoices (tAutotune* const, int numVoices); | |
| 233 | − void tAutotune_setFreqs (tAutotune* const, float f); | |
| 234 | − void tAutotune_setFreq (tAutotune* const, float f, int voice); | |
| 235 | − void tAutotune_setTimeConstant (tAutotune* const, float tc); | |
| 236 | − void tAutotune_setHopSize (tAutotune* const, int hs); | |
| 237 | − void tAutotune_setWindowSize (tAutotune* const, int ws); | |
| 238 | − float tAutotune_getInputPeriod (tAutotune* const); | |
| 239 | − float tAutotune_getInputFreq (tAutotune* const); | |
| 243 | + void tAutotune_init (tAutotune* const, int numVoices, int bufSize, int frameSize); | |
| 244 | + void tAutotune_free (tAutotune* const); | |
| 245 | + void tAutotune_initToPool (tAutotune* const, int numVoices, int bufSize, int frameSize, tMempool* const); | |
| 246 | + void tAutotune_freeFromPool (tAutotune* const, tMempool* const); | |
| 247 | + | |
| 248 | + float* tAutotune_tick (tAutotune* const, float sample); | |
| 249 | + void tAutotune_setNumVoices (tAutotune* const, int numVoices); | |
| 250 | + void tAutotune_setFreqs (tAutotune* const, float f); | |
| 251 | + void tAutotune_setFreq (tAutotune* const, float f, int voice); | |
| 252 | + void tAutotune_setTimeConstant (tAutotune* const, float tc); | |
| 253 | + void tAutotune_setHopSize (tAutotune* const, int hs); | |
| 254 | + void tAutotune_setWindowSize (tAutotune* const, int ws); | |
| 255 | + float tAutotune_getInputPeriod (tAutotune* const); | |
| 256 | + float tAutotune_getInputFreq (tAutotune* const); | |
| 240 | 257 | |
| 241 | 258 | //============================================================================== |
| 242 | 259 | |
| @@ -273,15 +290,17 @@ extern "C" { · 30 unmodified lines | ||
| 273 | 290 | |
| 274 | 291 | typedef _tFormantShifter* tFormantShifter; |
| 275 | 292 | |
| 276 | − void tFormantShifter_init (tFormantShifter* const, int bufsize, int order); | |
| 277 | − void tFormantShifter_free (tFormantShifter* const); | |
| 278 | − | |
| 279 | − float tFormantShifter_tick (tFormantShifter* const, float input); | |
| 280 | − float tFormantShifter_remove (tFormantShifter* const, float input); | |
| 281 | − float tFormantShifter_add (tFormantShifter* const, float input); | |
| 282 | − void tFormantShifter_ioSamples (tFormantShifter* const, float* in, float* out, int size, float fwarp); | |
| 283 | − void tFormantShifter_setShiftFactor (tFormantShifter* const, float shiftFactor); | |
| 284 | − void tFormantShifter_setIntensity (tFormantShifter* const, float intensity); | |
| 293 | + void tFormantShifter_init (tFormantShifter* const, int bufsize, int order); | |
| 294 | + void tFormantShifter_free (tFormantShifter* const); | |
| 295 | + void tFormantShifter_initToPool (tFormantShifter* const, int bufsize, int order, tMempool* const); | |
| 296 | + void tFormantShifter_freeFromPool (tFormantShifter* const, tMempool* const); | |
| 297 | + | |
| 298 | + float tFormantShifter_tick (tFormantShifter* const, float input); | |
| 299 | + float tFormantShifter_remove (tFormantShifter* const, float input); | |
| 300 | + float tFormantShifter_add (tFormantShifter* const, float input); | |
| 301 | + void tFormantShifter_ioSamples (tFormantShifter* const, float* in, float* out, int size, float fwarp); | |
| 302 | + void tFormantShifter_setShiftFactor (tFormantShifter* const, float shiftFactor); | |
| 303 | + void tFormantShifter_setIntensity (tFormantShifter* const, float intensity); | |
| 285 | 304 | |
| 286 | 305 | //============================================================================== |
| 287 | 306 | |
| @@ -16,6 +16,7 @@ extern "C" { · 15 unmodified lines | ||
| 16 | 16 | |
| 17 | 17 | #include "leaf-global.h" |
| 18 | 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 | 67 | //WDF Linear Components |
| 67 | − void tWDF_init(tWDF* const r, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR); | |
| 68 | − void tWDF_free(tWDF* const r); | |
| 69 | − float tWDF_tick(tWDF* const r, float sample, tWDF* const outputPoint, uint8_t paramsChanged); | |
| 68 | + void tWDF_init (tWDF* const, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR); | |
| 69 | + void tWDF_free (tWDF* const); | |
| 70 | + void tWDF_initToPool (tWDF* const, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR, tMempool* const); | |
| 71 | + void tWDF_freeFromPool (tWDF* const, tMempool* const); | |
| 70 | 72 | |
| 71 | − void tWDF_setValue(tWDF* const r, float value); | |
| 72 | − void tWDF_setSampleRate(tWDF* const r, float sample_rate); | |
| 73 | − uint8_t tWDF_isLeaf(tWDF* const r); | |
| 73 | + float tWDF_tick (tWDF* const, float sample, tWDF* const outputPoint, uint8_t paramsChanged); | |
| 74 | 74 | |
| 75 | − float tWDF_getPortResistance(tWDF* const r); | |
| 76 | − float tWDF_getReflectedWaveUp(tWDF* const r, float input); //for tree, only uses input for resistive source | |
| 77 | − float tWDF_getReflectedWaveDown(tWDF* const r, float input, float incident_wave); //for roots | |
| 78 | − void tWDF_setIncidentWave(tWDF* const r, float incident_wave, float input); | |
| 75 | + void tWDF_setValue (tWDF* const, float value); | |
| 76 | + void tWDF_setSampleRate (tWDF* const, float sample_rate); | |
| 77 | + uint8_t tWDF_isLeaf (tWDF* const); | |
| 79 | 78 | |
| 80 | − float tWDF_getVoltage(tWDF* const r); | |
| 81 | − float tWDF_getCurrent(tWDF* const r); | |
| 79 | + float tWDF_getPortResistance (tWDF* const); | |
| 80 | + float tWDF_getReflectedWaveUp (tWDF* const, float input); //for tree, only uses input for resistive source | |
| 81 | + float tWDF_getReflectedWaveDown (tWDF* const, float input, float incident_wave); //for roots | |
| 82 | + void tWDF_setIncidentWave (tWDF* const, float incident_wave, float input); | |
| 83 | + | |
| 84 | + float tWDF_getVoltage (tWDF* const); | |
| 85 | + float tWDF_getCurrent (tWDF* const); | |
| 82 | 86 | |
| 83 | 87 | |
| 84 | 88 | //============================================================================== |
| @@ -18,6 +18,7 @@ extern "C" { · 17 unmodified lines | ||
| 18 | 18 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
| 19 | 19 | |
| 20 | 20 | #include "leaf-math.h" |
| 21 | +#include "leaf-mempool.h" | |
| 21 | 22 | #include "leaf-filters.h" |
| 22 | 23 | #include "leaf-delay.h" |
| 23 | 24 | |
| @@ -26,8 +27,8 @@ extern "C" { · 2 unmodified lines | ||
| 26 | 27 | /* Attack-Decay envelope */ |
| 27 | 28 | typedef struct _tEnvelope { |
| 28 | 29 | |
| 29 | − const float *exp_buff; | |
| 30 | − const float *inc_buff; | |
| 30 | + const float *exp_buff; | |
| 31 | + const float *inc_buff; | |
| 31 | 32 | uint32_t buff_size; |
| 32 | 33 | |
| 33 | 34 | float next; |
| @@ -46,22 +47,24 @@ extern "C" { · 12 unmodified lines | ||
| 46 | 47 | |
| 47 | 48 | typedef _tEnvelope* tEnvelope; |
| 48 | 49 | |
| 49 | − void tEnvelope_init (tEnvelope* const, float attack, float decay, oBool loop); | |
| 50 | − void tEnvelope_free (tEnvelope* const); | |
| 50 | + void tEnvelope_init (tEnvelope* const, float attack, float decay, oBool loop); | |
| 51 | + void tEnvelope_free (tEnvelope* const); | |
| 52 | + void tEnvelope_initToPool (tEnvelope* const, float attack, float decay, oBool loop, tMempool* const); | |
| 53 | + void tEnvelope_freeFromPool (tEnvelope* const, tMempool* const); | |
| 51 | 54 | |
| 52 | − float tEnvelope_tick (tEnvelope* const); | |
| 53 | − void tEnvelope_setAttack (tEnvelope* const, float attack); | |
| 54 | − void tEnvelope_setDecay (tEnvelope* const, float decay); | |
| 55 | − void tEnvelope_loop (tEnvelope* const, oBool loop); | |
| 56 | − void tEnvelope_on (tEnvelope* const, float velocity); | |
| 55 | + float tEnvelope_tick (tEnvelope* const); | |
| 56 | + void tEnvelope_setAttack (tEnvelope* const, float attack); | |
| 57 | + void tEnvelope_setDecay (tEnvelope* const, float decay); | |
| 58 | + void tEnvelope_loop (tEnvelope* const, oBool loop); | |
| 59 | + void tEnvelope_on (tEnvelope* const, float velocity); | |
| 57 | 60 | |
| 58 | 61 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
| 59 | 62 | |
| 60 | 63 | /* ADSR */ |
| 61 | 64 | typedef struct _tADSR |
| 62 | 65 | { |
| 63 | − const float *exp_buff; | |
| 64 | − const float *inc_buff; | |
| 66 | + const float *exp_buff; | |
| 67 | + const float *inc_buff; | |
| 65 | 68 | uint32_t buff_size; |
| 66 | 69 | |
| 67 | 70 | float next; |
| @@ -78,16 +81,18 @@ extern "C" { · 10 unmodified lines | ||
| 78 | 81 | |
| 79 | 82 | typedef _tADSR* tADSR; |
| 80 | 83 | |
| 81 | − void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release); | |
| 82 | − void tADSR_free (tADSR* const); | |
| 84 | + void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release); | |
| 85 | + void tADSR_free (tADSR* const); | |
| 86 | + void tADSR_initToPool (tADSR* const, float attack, float decay, float sustain, float release, tMempool* const); | |
| 87 | + void tADSR_freeFromPool (tADSR* const, tMempool* const); | |
| 83 | 88 | |
| 84 | − float tADSR_tick (tADSR* const); | |
| 85 | − void tADSR_setAttack (tADSR* const, float attack); | |
| 86 | − void tADSR_setDecay (tADSR* const, float decay); | |
| 87 | − void tADSR_setSustain(tADSR* const, float sustain); | |
| 88 | − void tADSR_setRelease(tADSR* const, float release); | |
| 89 | − void tADSR_on (tADSR* const, float velocity); | |
| 90 | − void tADSR_off (tADSR* const); | |
| 89 | + float tADSR_tick (tADSR* const); | |
| 90 | + void tADSR_setAttack (tADSR* const, float attack); | |
| 91 | + void tADSR_setDecay (tADSR* const, float decay); | |
| 92 | + void tADSR_setSustain (tADSR* const, float sustain); | |
| 93 | + void tADSR_setRelease (tADSR* const, float release); | |
| 94 | + void tADSR_on (tADSR* const, float velocity); | |
| 95 | + void tADSR_off (tADSR* const); | |
| 91 | 96 | |
| 92 | 97 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
| 93 | 98 | |
| @@ -106,14 +111,16 @@ extern "C" { · 12 unmodified lines | ||
| 106 | 111 | |
| 107 | 112 | typedef _tRamp* tRamp; |
| 108 | 113 | |
| 109 | − void tRamp_init (tRamp* const, float time, int samplesPerTick); | |
| 110 | − void tRamp_free (tRamp* const); | |
| 114 | + void tRamp_init (tRamp* const, float time, int samplesPerTick); | |
| 115 | + void tRamp_free (tRamp* const); | |
| 116 | + void tRamp_initToPool (tRamp* const, float time, int samplesPerTick, tMempool* const); | |
| 117 | + void tRamp_freeFromPool (tRamp* const, tMempool* const); | |
| 111 | 118 | |
| 112 | − float tRamp_tick (tRamp* const); | |
| 113 | − float tRamp_sample (tRamp* const); | |
| 114 | − void tRamp_setTime (tRamp* const, float time); | |
| 115 | − void tRamp_setDest (tRamp* const, float dest); | |
| 116 | − void tRamp_setVal (tRamp* const, float val); | |
| 119 | + float tRamp_tick (tRamp* const); | |
| 120 | + float tRamp_sample (tRamp* const); | |
| 121 | + void tRamp_setTime (tRamp* const, float time); | |
| 122 | + void tRamp_setDest (tRamp* const, float dest); | |
| 123 | + void tRamp_setVal (tRamp* const, float val); | |
| 117 | 124 | |
| 118 | 125 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
| 119 | 126 | |
| @@ -126,14 +133,16 @@ extern "C" { · 6 unmodified lines | ||
| 126 | 133 | |
| 127 | 134 | typedef _tExpSmooth* tExpSmooth; |
| 128 | 135 | |
| 129 | − void tExpSmooth_init (tExpSmooth* const, float val, float factor); | |
| 130 | − void tExpSmooth_free (tExpSmooth* const); | |
| 136 | + void tExpSmooth_init (tExpSmooth* const, float val, float factor); | |
| 137 | + void tExpSmooth_free (tExpSmooth* const); | |
| 138 | + void tExpSmooth_initToPool (tExpSmooth* const, float val, float factor, tMempool* const); | |
| 139 | + void tExpSmooth_freeFromPool (tExpSmooth* const, tMempool* const); | |
| 131 | 140 | |
| 132 | − float tExpSmooth_tick (tExpSmooth* const); | |
| 133 | − float tExpSmooth_sample (tExpSmooth* const); | |
| 134 | − void tExpSmooth_setFactor (tExpSmooth* const, float factor); | |
| 135 | − void tExpSmooth_setDest (tExpSmooth* const, float dest); | |
| 136 | − void tExpSmooth_setVal (tExpSmooth* const, float val); | |
| 141 | + float tExpSmooth_tick (tExpSmooth* const); | |
| 142 | + float tExpSmooth_sample (tExpSmooth* const); | |
| 143 | + void tExpSmooth_setFactor (tExpSmooth* const, float factor); | |
| 144 | + void tExpSmooth_setDest (tExpSmooth* const, float dest); | |
| 145 | + void tExpSmooth_setVal (tExpSmooth* const, float val); | |
| 137 | 146 | |
| 138 | 147 | #ifdef __cplusplus |
| 139 | 148 | } |
| @@ -16,6 +16,7 @@ extern "C" { · 15 unmodified lines | ||
| 16 | 16 | //============================================================================== |
| 17 | 17 | |
| 18 | 18 | #include "leaf-math.h" |
| 19 | +#include "leaf-mempool.h" | |
| 19 | 20 | #include "leaf-delay.h" |
| 20 | 21 | #include "leaf-tables.h" |
| 21 | 22 | |
| @@ -34,12 +35,14 @@ extern "C" { · 12 unmodified lines | ||
| 34 | 35 | |
| 35 | 36 | typedef _tAllpass* tAllpass; |
| 36 | 37 | |
| 37 | − void tAllpass_init (tAllpass* const, float initDelay, uint32_t maxDelay); | |
| 38 | − void tAllpass_free (tAllpass* const); | |
| 38 | + void tAllpass_init (tAllpass* const, float initDelay, uint32_t maxDelay); | |
| 39 | + void tAllpass_free (tAllpass* const); | |
| 40 | + void tAllpass_initToPool (tAllpass* const, float initDelay, uint32_t maxDelay, tMempool* const); | |
| 41 | + void tAllpass_freeFromPool (tAllpass* const, tMempool* const); | |
| 39 | 42 | |
| 40 | − float tAllpass_tick (tAllpass* const, float input); | |
| 41 | − void tAllpass_setGain (tAllpass* const, float gain); | |
| 42 | − void tAllpass_setDelay (tAllpass* const f, float delay); | |
| 43 | + float tAllpass_tick (tAllpass* const, float input); | |
| 44 | + void tAllpass_setGain (tAllpass* const, float gain); | |
| 45 | + void tAllpass_setDelay (tAllpass* const, float delay); | |
| 43 | 46 | |
| 44 | 47 | |
| 45 | 48 | //============================================================================== |
| @@ -57,16 +60,18 @@ extern "C" { · 11 unmodified lines | ||
| 57 | 60 | |
| 58 | 61 | typedef _tOnePole* tOnePole; |
| 59 | 62 | |
| 60 | − void tOnePole_init (tOnePole* const, float thePole); | |
| 61 | − void tOnePole_free (tOnePole* const); | |
| 63 | + void tOnePole_init (tOnePole* const, float thePole); | |
| 64 | + void tOnePole_free (tOnePole* const); | |
| 65 | + void tOnePole_initToPool (tOnePole* const, float thePole, tMempool* const); | |
| 66 | + void tOnePole_freeFromPool (tOnePole* const, tMempool* const); | |
| 62 | 67 | |
| 63 | − float tOnePole_tick (tOnePole* const, float input); | |
| 64 | − void tOnePole_setB0 (tOnePole* const, float b0); | |
| 65 | − void tOnePole_setA1 (tOnePole* const, float a1); | |
| 66 | − void tOnePole_setPole (tOnePole* const, float thePole); | |
| 67 | − void tOnePole_setFreq (tOnePole* const, float freq); | |
| 68 | − void tOnePole_setCoefficients(tOnePole* const, float b0, float a1); | |
| 69 | − void tOnePole_setGain (tOnePole* const, float gain); | |
| 68 | + float tOnePole_tick (tOnePole* const, float input); | |
| 69 | + void tOnePole_setB0 (tOnePole* const, float b0); | |
| 70 | + void tOnePole_setA1 (tOnePole* const, float a1); | |
| 71 | + void tOnePole_setPole (tOnePole* const, float thePole); | |
| 72 | + void tOnePole_setFreq (tOnePole* const, float freq); | |
| 73 | + void tOnePole_setCoefficients(tOnePole* const, float b0, float a1); | |
| 74 | + void tOnePole_setGain (tOnePole* const, float gain); | |
| 70 | 75 | |
| 71 | 76 | //============================================================================== |
| 72 | 77 | |
| @@ -86,16 +91,18 @@ extern "C" { · 13 unmodified lines | ||
| 86 | 91 | |
| 87 | 92 | typedef _tTwoPole* tTwoPole; |
| 88 | 93 | |
| 89 | − void tTwoPole_init (tTwoPole* const); | |
| 90 | − void tTwoPole_free (tTwoPole* const); | |
| 94 | + void tTwoPole_init (tTwoPole* const); | |
| 95 | + void tTwoPole_free (tTwoPole* const); | |
| 96 | + void tTwoPole_initToPool (tTwoPole* const, tMempool* const); | |
| 97 | + void tTwoPole_freeFromPool (tTwoPole* const, tMempool* const); | |
| 91 | 98 | |
| 92 | − float tTwoPole_tick (tTwoPole* const, float input); | |
| 93 | − void tTwoPole_setB0 (tTwoPole* const, float b0); | |
| 94 | − void tTwoPole_setA1 (tTwoPole* const, float a1); | |
| 95 | − void tTwoPole_setA2 (tTwoPole* const, float a2); | |
| 96 | − void tTwoPole_setResonance (tTwoPole* const, float freq, float radius, oBool normalize); | |
| 97 | − void tTwoPole_setCoefficients(tTwoPole* const, float b0, float a1, float a2); | |
| 98 | − void tTwoPole_setGain (tTwoPole* const, float gain); | |
| 99 | + float tTwoPole_tick (tTwoPole* const, float input); | |
| 100 | + void tTwoPole_setB0 (tTwoPole* const, float b0); | |
| 101 | + void tTwoPole_setA1 (tTwoPole* const, float a1); | |
| 102 | + void tTwoPole_setA2 (tTwoPole* const, float a2); | |
| 103 | + void tTwoPole_setResonance (tTwoPole* const, float freq, float radius, oBool normalize); | |
| 104 | + void tTwoPole_setCoefficients(tTwoPole* const, float b0, float a1, float a2); | |
| 105 | + void tTwoPole_setGain (tTwoPole* const, float gain); | |
| 99 | 106 | |
| 100 | 107 | //============================================================================== |
| 101 | 108 | |
| @@ -110,15 +117,18 @@ extern "C" { · 8 unmodified lines | ||
| 110 | 117 | |
| 111 | 118 | typedef _tOneZero* tOneZero; |
| 112 | 119 | |
| 113 | − void tOneZero_init (tOneZero* const, float theZero); | |
| 114 | − void tOneZero_free (tOneZero* const); | |
| 115 | − float tOneZero_tick (tOneZero* const, float input); | |
| 116 | − void tOneZero_setB0 (tOneZero* const, float b0); | |
| 117 | − void tOneZero_setB1 (tOneZero* const, float b1); | |
| 118 | − void tOneZero_setZero (tOneZero* const, float theZero); | |
| 119 | − void tOneZero_setCoefficients(tOneZero* const, float b0, float b1); | |
| 120 | − void tOneZero_setGain (tOneZero* const, float gain); | |
| 121 | − float tOneZero_getPhaseDelay(tOneZero *f, float frequency ); | |
| 120 | + void tOneZero_init (tOneZero* const, float theZero); | |
| 121 | + void tOneZero_free (tOneZero* const); | |
| 122 | + void tOneZero_initToPool (tOneZero* const, float theZero, tMempool* const); | |
| 123 | + void tOneZero_freeFromPool (tOneZero* const, tMempool* const); | |
| 124 | + | |
| 125 | + float tOneZero_tick (tOneZero* const, float input); | |
| 126 | + void tOneZero_setB0 (tOneZero* const, float b0); | |
| 127 | + void tOneZero_setB1 (tOneZero* const, float b1); | |
| 128 | + void tOneZero_setZero (tOneZero* const, float theZero); | |
| 129 | + void tOneZero_setCoefficients(tOneZero* const, float b0, float b1); | |
| 130 | + void tOneZero_setGain (tOneZero* const, float gain); | |
| 131 | + float tOneZero_getPhaseDelay (tOneZero *f, float frequency ); | |
| 122 | 132 | |
| 123 | 133 | //============================================================================== |
| 124 | 134 | |
| @@ -136,16 +146,18 @@ extern "C" { · 11 unmodified lines | ||
| 136 | 146 | |
| 137 | 147 | typedef _tTwoZero* tTwoZero; |
| 138 | 148 | |
| 139 | − void tTwoZero_init (tTwoZero* const); | |
| 140 | − void tTwoZero_free (tTwoZero* const); | |
| 149 | + void tTwoZero_init (tTwoZero* const); | |
| 150 | + void tTwoZero_free (tTwoZero* const); | |
| 151 | + void tTwoZero_initToPool (tTwoZero* const, tMempool* const); | |
| 152 | + void tTwoZero_freeFromPool (tTwoZero* const, tMempool* const); | |
| 141 | 153 | |
| 142 | − float tTwoZero_tick (tTwoZero* const, float input); | |
| 143 | − void tTwoZero_setB0 (tTwoZero* const, float b0); | |
| 144 | − void tTwoZero_setB1 (tTwoZero* const, float b1); | |
| 145 | − void tTwoZero_setB2 (tTwoZero* const, float b2); | |
| 146 | − void tTwoZero_setNotch (tTwoZero* const, float frequency, float radius); | |
| 147 | − void tTwoZero_setCoefficients(tTwoZero* const, float b0, float b1, float b2); | |
| 148 | − void tTwoZero_setGain (tTwoZero* const, float gain); | |
| 154 | + float tTwoZero_tick (tTwoZero* const, float input); | |
| 155 | + void tTwoZero_setB0 (tTwoZero* const, float b0); | |
| 156 | + void tTwoZero_setB1 (tTwoZero* const, float b1); | |
| 157 | + void tTwoZero_setB2 (tTwoZero* const, float b2); | |
| 158 | + void tTwoZero_setNotch (tTwoZero* const, float frequency, float radius); | |
| 159 | + void tTwoZero_setCoefficients(tTwoZero* const, float b0, float b1, float b2); | |
| 160 | + void tTwoZero_setGain (tTwoZero* const, float gain); | |
| 149 | 161 | |
| 150 | 162 | //============================================================================== |
| 151 | 163 | |
| @@ -162,17 +174,19 @@ extern "C" { · 10 unmodified lines | ||
| 162 | 174 | |
| 163 | 175 | typedef _tPoleZero* tPoleZero; |
| 164 | 176 | |
| 165 | − void tPoleZero_init (tPoleZero* const); | |
| 166 | − void tPoleZero_free (tPoleZero* const); | |
| 177 | + void tPoleZero_init (tPoleZero* const); | |
| 178 | + void tPoleZero_free (tPoleZero* const); | |
| 179 | + void tPoleZero_initToPool (tPoleZero* const, tMempool* const); | |
| 180 | + void tPoleZero_freeFromPool (tPoleZero* const, tMempool* const); | |
| 167 | 181 | |
| 168 | − float tPoleZero_tick (tPoleZero* const, float input); | |
| 169 | − void tPoleZero_setB0 (tPoleZero* const, float b0); | |
| 170 | − void tPoleZero_setB1 (tPoleZero* const, float b1); | |
| 171 | − void tPoleZero_setA1 (tPoleZero* const, float a1); | |
| 172 | − void tPoleZero_setCoefficients (tPoleZero* const, float b0, float b1, float a1); | |
| 173 | − void tPoleZero_setAllpass (tPoleZero* const, float coeff); | |
| 174 | − void tPoleZero_setBlockZero (tPoleZero* const, float thePole); | |
| 175 | − void tPoleZero_setGain (tPoleZero* const, float gain); | |
| 182 | + float tPoleZero_tick (tPoleZero* const, float input); | |
| 183 | + void tPoleZero_setB0 (tPoleZero* const, float b0); | |
| 184 | + void tPoleZero_setB1 (tPoleZero* const, float b1); | |
| 185 | + void tPoleZero_setA1 (tPoleZero* const, float a1); | |
| 186 | + void tPoleZero_setCoefficients (tPoleZero* const, float b0, float b1, float a1); | |
| 187 | + void tPoleZero_setAllpass (tPoleZero* const, float coeff); | |
| 188 | + void tPoleZero_setBlockZero (tPoleZero* const, float thePole); | |
| 189 | + void tPoleZero_setGain (tPoleZero* const, float gain); | |
| 176 | 190 | |
| 177 | 191 | //============================================================================== |
| 178 | 192 | |
| @@ -192,19 +206,21 @@ extern "C" { · 13 unmodified lines | ||
| 192 | 206 | |
| 193 | 207 | typedef _tBiQuad* tBiQuad; |
| 194 | 208 | |
| 195 | − void tBiQuad_init (tBiQuad* const); | |
| 196 | − void tBiQuad_free (tBiQuad* const); | |
| 197 | − | |
| 198 | − float tBiQuad_tick (tBiQuad* const, float input); | |
| 199 | − void tBiQuad_setB0 (tBiQuad* const, float b0); | |
| 200 | − void tBiQuad_setB1 (tBiQuad* const, float b1); | |
| 201 | − void tBiQuad_setB2 (tBiQuad* const, float b2); | |
| 202 | − void tBiQuad_setA1 (tBiQuad* const, float a1); | |
| 203 | − void tBiQuad_setA2 (tBiQuad* const, float a2); | |
| 204 | − void tBiQuad_setNotch (tBiQuad* const, float freq, float radius); | |
| 205 | − void tBiQuad_setResonance (tBiQuad* const, float freq, float radius, oBool normalize); | |
| 206 | − void tBiQuad_setCoefficients(tBiQuad* const, float b0, float b1, float b2, float a1, float a2); | |
| 207 | − void tBiQuad_setGain (tBiQuad* const, float gain); | |
| 209 | + void tBiQuad_init (tBiQuad* const); | |
| 210 | + void tBiQuad_free (tBiQuad* const); | |
| 211 | + void tBiQuad_initToPool (tBiQuad* const, tMempool* const); | |
| 212 | + void tBiQuad_freeFromPool (tBiQuad* const, tMempool* const); | |
| 213 | + | |
| 214 | + float tBiQuad_tick (tBiQuad* const, float input); | |
| 215 | + void tBiQuad_setB0 (tBiQuad* const, float b0); | |
| 216 | + void tBiQuad_setB1 (tBiQuad* const, float b1); | |
| 217 | + void tBiQuad_setB2 (tBiQuad* const, float b2); | |
| 218 | + void tBiQuad_setA1 (tBiQuad* const, float a1); | |
| 219 | + void tBiQuad_setA2 (tBiQuad* const, float a2); | |
| 220 | + void tBiQuad_setNotch (tBiQuad* const, float freq, float radius); | |
| 221 | + void tBiQuad_setResonance (tBiQuad* const, float freq, float radius, oBool normalize); | |
| 222 | + void tBiQuad_setCoefficients(tBiQuad* const, float b0, float b1, float b2, float a1, float a2); | |
| 223 | + void tBiQuad_setGain (tBiQuad* const, float gain); | |
| 208 | 224 | |
| 209 | 225 | //============================================================================== |
| 210 | 226 | |
| @@ -229,12 +245,14 @@ extern "C" { · 18 unmodified lines | ||
| 229 | 245 | |
| 230 | 246 | typedef _tSVF* tSVF; |
| 231 | 247 | |
| 232 | − void tSVF_init (tSVF* const, SVFType type, float freq, float Q); | |
| 233 | − void tSVF_free (tSVF* const); | |
| 248 | + void tSVF_init (tSVF* const, SVFType type, float freq, float Q); | |
| 249 | + void tSVF_free (tSVF* const); | |
| 250 | + void tSVF_initToPool (tSVF* const, SVFType type, float freq, float Q, tMempool* const); | |
| 251 | + void tSVF_freeFromPool (tSVF* const, tMempool* const); | |
| 234 | 252 | |
| 235 | − float tSVF_tick (tSVF* const, float v0); | |
| 236 | − void tSVF_setFreq (tSVF* const, float freq); | |
| 237 | − void tSVF_setQ (tSVF* const, float Q); | |
| 253 | + float tSVF_tick (tSVF* const, float v0); | |
| 254 | + void tSVF_setFreq (tSVF* const, float freq); | |
| 255 | + void tSVF_setQ (tSVF* const, float Q); | |
| 238 | 256 | |
| 239 | 257 | //============================================================================== |
| 240 | 258 | |
| @@ -250,12 +268,14 @@ extern "C" { · 9 unmodified lines | ||
| 250 | 268 | |
| 251 | 269 | typedef _tEfficientSVF* tEfficientSVF; |
| 252 | 270 | |
| 253 | − void tEfficientSVF_init (tEfficientSVF* const, SVFType type, uint16_t controlFreq, float Q); | |
| 254 | − void tEfficientSVF_free (tEfficientSVF* const); | |
| 271 | + void tEfficientSVF_init (tEfficientSVF* const, SVFType type, uint16_t input, float Q); | |
| 272 | + void tEfficientSVF_free (tEfficientSVF* const); | |
| 273 | + void tEfficientSVF_initToPool (tEfficientSVF* const, SVFType type, uint16_t input, float Q, tMempool* const); | |
| 274 | + void tEfficientSVF_freeFromPool (tEfficientSVF* const, tMempool* const); | |
| 255 | 275 | |
| 256 | − float tEfficientSVF_tick (tEfficientSVF* const, float v0); | |
| 257 | − void tEfficientSVF_setFreq (tEfficientSVF* const, uint16_t controlFreq); | |
| 258 | − void tEfficientSVF_setQ (tEfficientSVF* const, float Q); | |
| 276 | + float tEfficientSVF_tick (tEfficientSVF* const, float v0); | |
| 277 | + void tEfficientSVF_setFreq (tEfficientSVF* const, uint16_t controlFreq); | |
| 278 | + void tEfficientSVF_setQ (tEfficientSVF* const, float Q); | |
| 259 | 279 | |
| 260 | 280 | //============================================================================== |
| 261 | 281 | |
| @@ -269,12 +289,14 @@ extern "C" { · 7 unmodified lines | ||
| 269 | 289 | |
| 270 | 290 | typedef _tHighpass* tHighpass; |
| 271 | 291 | |
| 272 | − void tHighpass_init (tHighpass* const, float freq); | |
| 273 | − void tHighpass_free (tHighpass* const); | |
| 292 | + void tHighpass_init (tHighpass* const, float freq); | |
| 293 | + void tHighpass_free (tHighpass* const); | |
| 294 | + void tHighpass_initToPool (tHighpass* const, float freq, tMempool* const); | |
| 295 | + void tHighpass_freeFromPool (tHighpass* const, tMempool* const); | |
| 274 | 296 | |
| 275 | − float tHighpass_tick (tHighpass* const, float x); | |
| 276 | − void tHighpass_setFreq (tHighpass* const, float freq); | |
| 277 | − float tHighpass_getFreq (tHighpass* const); | |
| 297 | + float tHighpass_tick (tHighpass* const, float x); | |
| 298 | + void tHighpass_setFreq (tHighpass* const, float freq); | |
| 299 | + float tHighpass_getFreq (tHighpass* const); | |
| 278 | 300 | |
| 279 | 301 | //============================================================================== |
| 280 | 302 | |
| @@ -295,13 +317,15 @@ extern "C" { · 14 unmodified lines | ||
| 295 | 317 | |
| 296 | 318 | typedef _tButterworth* tButterworth; |
| 297 | 319 | |
| 298 | − void tButterworth_init (tButterworth* const, int N, float f1, float f2); | |
| 299 | − void tButterworth_free (tButterworth* const); | |
| 320 | + void tButterworth_init (tButterworth* const, int N, float f1, float f2); | |
| 321 | + void tButterworth_free (tButterworth* const); | |
| 322 | + void tButterworth_initToPool (tButterworth* const, int N, float f1, float f2, tMempool* const); | |
| 323 | + void tButterworth_freeFromPool (tButterworth* const, tMempool* const); | |
| 300 | 324 | |
| 301 | − float tButterworth_tick (tButterworth* const, float input); | |
| 302 | − void tButterworth_setF1 (tButterworth* const, float in); | |
| 303 | − void tButterworth_setF2 (tButterworth* const, float in); | |
| 304 | − void tButterworth_setFreqs (tButterworth* const, float f1, float f2); | |
| 325 | + float tButterworth_tick (tButterworth* const, float input); | |
| 326 | + void tButterworth_setF1 (tButterworth* const, float in); | |
| 327 | + void tButterworth_setF2 (tButterworth* const, float in); | |
| 328 | + void tButterworth_setFreqs (tButterworth* const, float f1, float f2); | |
| 305 | 329 | |
| 306 | 330 | //============================================================================== |
| 307 | 331 | |
| @@ -310,16 +334,17 @@ extern "C" { · 2 unmodified lines | ||
| 310 | 334 | float* past; |
| 311 | 335 | float* coeff; |
| 312 | 336 | int numTaps; |
| 313 | − | |
| 314 | 337 | } _tFIR; |
| 315 | 338 | |
| 316 | 339 | typedef _tFIR* tFIR; |
| 317 | 340 | |
| 318 | − void tFIR_init (tFIR* const, float* coeffs, int numTaps); | |
| 319 | − void tFIR_free (tFIR* const); | |
| 341 | + void tFIR_init (tFIR* const, float* coeffs, int numTaps); | |
| 342 | + void tFIR_free (tFIR* const); | |
| 343 | + void tFIR_initToPool (tFIR* const, float* coeffs, int numTaps, tMempool* const); | |
| 344 | + void tFIR_freeFromPool (tFIR* const, tMempool* const); | |
| 320 | 345 | |
| 321 | − float tFIR_tick (tFIR* const, float input); | |
| 322 | − void tFIR_coeffs (tFIR* const, float in); | |
| 346 | + float tFIR_tick (tFIR* const, float input); | |
| 347 | + void tFIR_coeffs (tFIR* const, float in); | |
| 323 | 348 | |
| 324 | 349 | //============================================================================== |
| 325 | 350 | |
| @@ -1,12 +1,12 @@ | ||
| 1 | 1 | /* |
| 2 | − ============================================================================== | |
| 3 | − | |
| 4 | − leaf-global.h | |
| 5 | − Created: 24 Oct 2019 2:24:38pm | |
| 6 | − Author: Matthew Wang | |
| 7 | − | |
| 8 | − ============================================================================== | |
| 9 | −*/ | |
| 2 | + ============================================================================== | |
| 3 | + | |
| 4 | + leaf-global.h | |
| 5 | + Created: 24 Oct 2019 2:24:38pm | |
| 6 | + Author: Matthew Wang | |
| 7 | + | |
| 8 | + ============================================================================== | |
| 9 | + */ | |
| 10 | 10 | |
| 11 | 11 | #ifndef LEAF_GLOBAL_H_INCLUDED |
| 12 | 12 | #define LEAF_GLOBAL_H_INCLUDED |
| @@ -14,17 +14,17 @@ · 1 unmodified line | ||
| 14 | 14 | #ifdef __cplusplus |
| 15 | 15 | extern "C" { |
| 16 | 16 | #endif |
| 17 | − | |
| 18 | −typedef struct _LEAF | |
| 19 | −{ | |
| 20 | − float sampleRate; | |
| 21 | − float invSampleRate; | |
| 22 | − int blockSize; | |
| 23 | − float twoPiTimesInvSampleRate; | |
| 24 | − float (*random)(void); | |
| 25 | −} LEAF; | |
| 26 | − | |
| 27 | −extern LEAF leaf; // The global instance of LEAF. | |
| 17 | + | |
| 18 | + typedef struct _LEAF | |
| 19 | + { | |
| 20 | + float sampleRate; | |
| 21 | + float invSampleRate; | |
| 22 | + int blockSize; | |
| 23 | + float twoPiTimesInvSampleRate; | |
| 24 | + float (*random)(void); | |
| 25 | + } LEAF; | |
| 26 | + | |
| 27 | + extern LEAF leaf; // The global instance of LEAF. | |
| 28 | 28 | |
| 29 | 29 | //============================================================================== |
| 30 | 30 | |
| @@ -35,3 +35,4 @@ extern LEAF leaf; // The global instance of LEAF. · 4 unmodified lines | ||
| 35 | 35 | #endif // LEAF_GLOBAL_H_INCLUDED |
| 36 | 36 | |
| 37 | 37 | //============================================================================== |
| 38 | + | |
| @@ -42,16 +42,19 @@ extern "C" { · 41 unmodified lines | ||
| 42 | 42 | |
| 43 | 43 | typedef _t808Cowbell* t808Cowbell; |
| 44 | 44 | |
| 45 | − void t808Cowbell_init (t808Cowbell* const, int useStick); | |
| 46 | − void t808Cowbell_free (t808Cowbell* const); | |
| 47 | − float t808Cowbell_tick (t808Cowbell* const); | |
| 48 | − void t808Cowbell_on (t808Cowbell* const, float vel); | |
| 49 | − void t808Cowbell_setDecay (t808Cowbell* const, float decay); | |
| 50 | − void t808Cowbell_setHighpassFreq (t808Cowbell* const, float freq); | |
| 51 | − void t808Cowbell_setBandpassFreq (t808Cowbell* const, float freq); | |
| 52 | − void t808Cowbell_setFreq (t808Cowbell* const, float freq); | |
| 53 | − void t808Cowbell_setOscMix (t808Cowbell* const, float oscMix); | |
| 54 | − void t808Cowbell_setStick (t808Cowbell* const, int useStick); | |
| 45 | + void t808Cowbell_init (t808Cowbell* const, int useStick); | |
| 46 | + void t808Cowbell_free (t808Cowbell* const); | |
| 47 | + void t808Cowbell_initToPool (t808Cowbell* const, int useStick, tMempool* const); | |
| 48 | + void t808Cowbell_freeFromPool (t808Cowbell* const, tMempool* const); | |
| 49 | + | |
| 50 | + float t808Cowbell_tick (t808Cowbell* const); | |
| 51 | + void t808Cowbell_on (t808Cowbell* const, float vel); | |
| 52 | + void t808Cowbell_setDecay (t808Cowbell* const, float decay); | |
| 53 | + void t808Cowbell_setHighpassFreq (t808Cowbell* const, float freq); | |
| 54 | + void t808Cowbell_setBandpassFreq (t808Cowbell* const, float freq); | |
| 55 | + void t808Cowbell_setFreq (t808Cowbell* const, float freq); | |
| 56 | + void t808Cowbell_setOscMix (t808Cowbell* const, float oscMix); | |
| 57 | + void t808Cowbell_setStick (t808Cowbell* const, int useStick); | |
| 55 | 58 | |
| 56 | 59 | //============================================================================== |
| 57 | 60 | |
| @@ -78,21 +81,23 @@ extern "C" { · 20 unmodified lines | ||
| 78 | 81 | |
| 79 | 82 | typedef _t808Hihat* t808Hihat; |
| 80 | 83 | |
| 81 | − void t808Hihat_init (t808Hihat* const); | |
| 82 | − void t808Hihat_free (t808Hihat* const); | |
| 83 | − | |
| 84 | − float t808Hihat_tick (t808Hihat* const); | |
| 85 | − void t808Hihat_on (t808Hihat* const, float vel); | |
| 86 | − void t808Hihat_setOscNoiseMix (t808Hihat* const, float oscNoiseMix); | |
| 87 | − void t808Hihat_setDecay (t808Hihat* const, float decay); | |
| 88 | − void t808Hihat_setHighpassFreq (t808Hihat* const, float freq); | |
| 89 | − void t808Hihat_setOscBandpassFreq (t808Hihat* const, float freq); | |
| 90 | − void t808Hihat_setOscBandpassQ (t808Hihat* const hihat, float Q); | |
| 91 | − void t808Hihat_setStickBandPassFreq (t808Hihat* const, float freq); | |
| 92 | − void t808Hihat_setStickBandPassQ (t808Hihat* const hihat, float Q); | |
| 93 | − void t808Hihat_setOscFreq (t808Hihat* const, float freq); | |
| 94 | − void t808Hihat_setStretch (t808Hihat* const hihat, float stretch); | |
| 95 | − void t808Hihat_setFM (t808Hihat* const hihat, float FM_amount); | |
| 84 | + void t808Hihat_init (t808Hihat* const); | |
| 85 | + void t808Hihat_free (t808Hihat* const); | |
| 86 | + void t808Hihat_initToPool (t808Hihat* const, tMempool* const); | |
| 87 | + void t808Hihat_freeFromPool (t808Hihat* const, tMempool* const); | |
| 88 | + | |
| 89 | + float t808Hihat_tick (t808Hihat* const); | |
| 90 | + void t808Hihat_on (t808Hihat* const, float vel); | |
| 91 | + void t808Hihat_setOscNoiseMix (t808Hihat* const, float oscNoiseMix); | |
| 92 | + void t808Hihat_setDecay (t808Hihat* const, float decay); | |
| 93 | + void t808Hihat_setHighpassFreq (t808Hihat* const, float freq); | |
| 94 | + void t808Hihat_setOscBandpassFreq (t808Hihat* const, float freq); | |
| 95 | + void t808Hihat_setOscBandpassQ (t808Hihat* const hihat, float Q); | |
| 96 | + void t808Hihat_setStickBandPassFreq (t808Hihat* const, float freq); | |
| 97 | + void t808Hihat_setStickBandPassQ (t808Hihat* const hihat, float Q); | |
| 98 | + void t808Hihat_setOscFreq (t808Hihat* const, float freq); | |
| 99 | + void t808Hihat_setStretch (t808Hihat* const hihat, float stretch); | |
| 100 | + void t808Hihat_setFM (t808Hihat* const hihat, float FM_amount); | |
| 96 | 101 | |
| 97 | 102 | //============================================================================== |
| 98 | 103 | |
| @@ -123,19 +128,21 @@ extern "C" { · 24 unmodified lines | ||
| 123 | 128 | |
| 124 | 129 | typedef _t808Snare* t808Snare; |
| 125 | 130 | |
| 126 | − void t808Snare_init (t808Snare* const); | |
| 127 | − void t808Snare_free (t808Snare* const); | |
| 128 | − | |
| 129 | − float t808Snare_tick (t808Snare* const); | |
| 130 | − void t808Snare_on (t808Snare* const, float vel); | |
| 131 | − void t808Snare_setTone1Freq (t808Snare* const, float freq); | |
| 132 | − void t808Snare_setTone2Freq (t808Snare* const, float freq); | |
| 133 | − void t808Snare_setTone1Decay (t808Snare* const, float decay); | |
| 134 | − void t808Snare_setTone2Decay (t808Snare* const, float decay); | |
| 135 | − void t808Snare_setNoiseDecay (t808Snare* const, float decay); | |
| 136 | − void t808Snare_setToneNoiseMix (t808Snare* const, float toneNoiseMix); | |
| 137 | − void t808Snare_setNoiseFilterFreq (t808Snare* const, float noiseFilterFreq); | |
| 138 | − void t808Snare_setNoiseFilterQ (t808Snare* const, float noiseFilterQ); | |
| 131 | + void t808Snare_init (t808Snare* const); | |
| 132 | + void t808Snare_free (t808Snare* const); | |
| 133 | + void t808Snare_initToPool (t808Snare* const, tMempool* const); | |
| 134 | + void t808Snare_freeFromPool (t808Snare* const, tMempool* const); | |
| 135 | + | |
| 136 | + float t808Snare_tick (t808Snare* const); | |
| 137 | + void t808Snare_on (t808Snare* const, float vel); | |
| 138 | + void t808Snare_setTone1Freq (t808Snare* const, float freq); | |
| 139 | + void t808Snare_setTone2Freq (t808Snare* const, float freq); | |
| 140 | + void t808Snare_setTone1Decay (t808Snare* const, float decay); | |
| 141 | + void t808Snare_setTone2Decay (t808Snare* const, float decay); | |
| 142 | + void t808Snare_setNoiseDecay (t808Snare* const, float decay); | |
| 143 | + void t808Snare_setToneNoiseMix (t808Snare* const, float toneNoiseMix); | |
| 144 | + void t808Snare_setNoiseFilterFreq (t808Snare* const, float noiseFilterFreq); | |
| 145 | + void t808Snare_setNoiseFilterQ (t808Snare* const, float noiseFilterQ); | |
| 139 | 146 | |
| 140 | 147 | //============================================================================== |
| 141 | 148 | |
| @@ -164,19 +171,21 @@ extern "C" { · 22 unmodified lines | ||
| 164 | 171 | |
| 165 | 172 | typedef _t808Kick* t808Kick; |
| 166 | 173 | |
| 167 | − void t808Kick_init (t808Kick* const); | |
| 168 | − void t808Kick_free (t808Kick* const); | |
| 169 | − | |
| 170 | − float t808Kick_tick (t808Kick* const); | |
| 171 | − void t808Kick_on (t808Kick* const, float vel); | |
| 172 | − void t808Kick_setToneFreq (t808Kick* const, float freq); | |
| 173 | − void t808Kick_setToneDecay (t808Kick* const, float decay); | |
| 174 | − void t808Kick_setNoiseDecay (t808Kick* const, float decay); | |
| 175 | − void t808Kick_setSighAmount (t808Kick* const, float sigh); | |
| 176 | − void t808Kick_setChirpAmount (t808Kick* const, float chirp); | |
| 177 | − void t808Kick_setToneNoiseMix (t808Kick* const, float toneNoiseMix); | |
| 178 | − void t808Kick_setNoiseFilterFreq (t808Kick* const, float noiseFilterFreq); | |
| 179 | − void t808Kick_setNoiseFilterQ (t808Kick* const, float noiseFilterQ); | |
| 174 | + void t808Kick_init (t808Kick* const); | |
| 175 | + void t808Kick_free (t808Kick* const); | |
| 176 | + void t808Kick_initToPool (t808Kick* const, tMempool* const); | |
| 177 | + void t808Kick_freeFromPool (t808Kick* const, tMempool* const); | |
| 178 | + | |
| 179 | + float t808Kick_tick (t808Kick* const); | |
| 180 | + void t808Kick_on (t808Kick* const, float vel); | |
| 181 | + void t808Kick_setToneFreq (t808Kick* const, float freq); | |
| 182 | + void t808Kick_setToneDecay (t808Kick* const, float decay); | |
| 183 | + void t808Kick_setNoiseDecay (t808Kick* const, float decay); | |
| 184 | + void t808Kick_setSighAmount (t808Kick* const, float sigh); | |
| 185 | + void t808Kick_setChirpAmount (t808Kick* const, float chirp); | |
| 186 | + void t808Kick_setToneNoiseMix (t808Kick* const, float toneNoiseMix); | |
| 187 | + void t808Kick_setNoiseFilterFreq (t808Kick* const, float noiseFilterFreq); | |
| 188 | + void t808Kick_setNoiseFilterQ (t808Kick* const, float noiseFilterQ); | |
| 180 | 189 | |
| 181 | 190 | //============================================================================== |
| 182 | 191 | |
| @@ -1,38 +1,38 @@ | ||
| 1 | 1 | /*============================================================================== |
| 2 | 2 | |
| 3 | − In short, mpool is distributed under so called "BSD license", | |
| 4 | − | |
| 5 | − Copyright (c) 2009-2010 Tatsuhiko Kubo <cubicdaiya@gmail.com> | |
| 6 | − All rights reserved. | |
| 7 | − | |
| 8 | − Redistribution and use in source and binary forms, with or without modification, | |
| 9 | − are permitted provided that the following conditions are met: | |
| 10 | − | |
| 11 | − * Redistributions of source code must retain the above copyright notice, | |
| 12 | − this list of conditions and the following disclaimer. | |
| 13 | − | |
| 14 | − * Redistributions in binary form must reproduce the above copyright notice, | |
| 15 | − this list of conditions and the following disclaimer in the documentation | |
| 16 | − and/or other materials provided with the distribution. | |
| 17 | − | |
| 18 | − * Neither the name of the authors nor the names of its contributors | |
| 19 | − may be used to endorse or promote products derived from this software | |
| 20 | − without specific prior written permission. | |
| 21 | − | |
| 22 | − THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 23 | − "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 24 | − LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 25 | − A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 26 | − OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 27 | − SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
| 28 | − TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 29 | − PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 30 | − LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 31 | − NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 32 | − SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 3 | + In short, mpool is distributed under so called "BSD license", | |
| 33 | 4 | |
| 34 | − written by C99 style | |
| 35 | −==============================================================================*/ | |
| 5 | + Copyright (c) 2009-2010 Tatsuhiko Kubo <cubicdaiya@gmail.com> | |
| 6 | + All rights reserved. | |
| 7 | + | |
| 8 | + Redistribution and use in source and binary forms, with or without modification, | |
| 9 | + are permitted provided that the following conditions are met: | |
| 10 | + | |
| 11 | + * Redistributions of source code must retain the above copyright notice, | |
| 12 | + this list of conditions and the following disclaimer. | |
| 13 | + | |
| 14 | + * Redistributions in binary form must reproduce the above copyright notice, | |
| 15 | + this list of conditions and the following disclaimer in the documentation | |
| 16 | + and/or other materials provided with the distribution. | |
| 17 | + | |
| 18 | + * Neither the name of the authors nor the names of its contributors | |
| 19 | + may be used to endorse or promote products derived from this software | |
| 20 | + without specific prior written permission. | |
| 21 | + | |
| 22 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 23 | + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 24 | + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 25 | + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 26 | + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 27 | + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
| 28 | + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 29 | + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 30 | + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 31 | + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 32 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 33 | + | |
| 34 | + written by C99 style | |
| 35 | + ==============================================================================*/ | |
| 36 | 36 | |
| 37 | 37 | #ifndef LEAF_MPOOL_H_INCLUDED |
| 38 | 38 | #define LEAF_MPOOL_H_INCLUDED |
| @@ -41,60 +41,76 @@ · 2 unmodified lines | ||
| 41 | 41 | extern "C" { |
| 42 | 42 | #endif |
| 43 | 43 | |
| 44 | −//============================================================================== | |
| 45 | − | |
| 44 | + //============================================================================== | |
| 45 | + | |
| 46 | 46 | #include <stdio.h> |
| 47 | 47 | #include <stdlib.h> |
| 48 | 48 | #include <string.h> |
| 49 | 49 | #include <stdbool.h> |
| 50 | 50 | |
| 51 | −//============================================================================== | |
| 52 | − | |
| 51 | + //============================================================================== | |
| 52 | + | |
| 53 | 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 | |
| 62 | −typedef struct mpool_node_t { | |
| 63 | − void *pool; // memory pool field | |
| 64 | − struct mpool_node_t *next; // next node pointer | |
| 65 | − struct mpool_node_t *prev; // prev node pointer | |
| 66 | − size_t size; | |
| 67 | −} mpool_node_t; | |
| 68 | − | |
| 69 | −typedef struct mpool_t { | |
| 70 | − void* mpool; // start of the mpool | |
| 71 | − size_t usize; // used size of the pool | |
| 72 | − size_t msize; // max size of the pool | |
| 73 | − mpool_node_t* head; // first node of memory pool free list | |
| 74 | −} mpool_t; | |
| 75 | − | |
| 76 | −void mpool_create (char* memory, size_t size, mpool_t* pool); | |
| 77 | − | |
| 78 | −void *mpool_alloc(size_t size, mpool_t* pool); | |
| 79 | −void mpool_free(void* ptr, mpool_t* pool); | |
| 80 | − | |
| 81 | −size_t mpool_get_size(mpool_t* pool); | |
| 82 | −size_t mpool_get_used(mpool_t* pool); | |
| 83 | − | |
| 84 | −void leaf_pool_init(char* memory, size_t size); | |
| 85 | − | |
| 86 | −void* leaf_alloc(size_t size); | |
| 87 | −void leaf_free(void* ptr); | |
| 88 | − | |
| 89 | −size_t leaf_pool_get_size(void); | |
| 90 | −size_t leaf_pool_get_used(void); | |
| 91 | − | |
| 92 | −void* leaf_pool_get_pool(void); | |
| 93 | − | |
| 94 | −void leaf_mempool_overrun(void); | |
| 95 | 54 | |
| 96 | −//============================================================================== | |
| 97 | − | |
| 55 | + //#define size_t unsigned long | |
| 56 | + | |
| 57 | + /** | |
| 58 | + * memory pool structure | |
| 59 | + */ | |
| 60 | + | |
| 61 | + // node of free list | |
| 62 | + typedef struct mpool_node_t { | |
| 63 | + void *pool; // memory pool field | |
| 64 | + struct mpool_node_t *next; // next node pointer | |
| 65 | + struct mpool_node_t *prev; // prev node pointer | |
| 66 | + size_t size; | |
| 67 | + } mpool_node_t; | |
| 68 | + | |
| 69 | + typedef struct mpool_t { | |
| 70 | + void* mpool; // start of the mpool | |
| 71 | + size_t usize; // used size of the pool | |
| 72 | + size_t msize; // max size of the pool | |
| 73 | + mpool_node_t* head; // first node of memory pool free list | |
| 74 | + } mpool_t; | |
| 75 | + | |
| 76 | + void mpool_create (char* memory, size_t size, mpool_t* pool); | |
| 77 | + | |
| 78 | + void* mpool_alloc(size_t size, mpool_t* pool); | |
| 79 | + void* mpool_allocAndClear(size_t asize, mpool_t* pool); | |
| 80 | + void mpool_free(void* ptr, mpool_t* pool); | |
| 81 | + | |
| 82 | + size_t mpool_get_size(mpool_t* pool); | |
| 83 | + size_t mpool_get_used(mpool_t* pool); | |
| 84 | + | |
| 85 | + void leaf_pool_init(char* memory, size_t size); | |
| 86 | + | |
| 87 | + void* leaf_alloc(size_t size); | |
| 88 | + void* leaf_allocAndClear(size_t size); | |
| 89 | + void leaf_free(void* ptr); | |
| 90 | + | |
| 91 | + size_t leaf_pool_get_size(void); | |
| 92 | + size_t leaf_pool_get_used(void); | |
| 93 | + | |
| 94 | + void* leaf_pool_get_pool(void); | |
| 95 | + | |
| 96 | + void leaf_mempool_overrun(void); | |
| 97 | + | |
| 98 | + // User object for creating additional mempools | |
| 99 | + | |
| 100 | + typedef struct _tMempool | |
| 101 | + { | |
| 102 | + mpool_t* pool; | |
| 103 | + } _tMempool; | |
| 104 | + | |
| 105 | + typedef _tMempool* tMempool; | |
| 106 | + | |
| 107 | + void tMempool_init (tMempool* const, char* memory, size_t size); | |
| 108 | + void tMempool_free (tMempool* const); | |
| 109 | + void tMempool_initToPool (tMempool* const, char* memory, size_t size, tMempool* const); | |
| 110 | + void tMempool_freeFromPool (tMempool* const, tMempool* const); | |
| 111 | + | |
| 112 | + //============================================================================== | |
| 113 | + | |
| 98 | 114 | #ifdef __cplusplus |
| 99 | 115 | } |
| 100 | 116 | #endif |
| @@ -104,3 +120,4 @@ void leaf_mempool_overrun(void); · 3 unmodified lines | ||
| 104 | 120 | //============================================================================== |
| 105 | 121 | |
| 106 | 122 | |
| 123 | + | |
| @@ -40,6 +40,8 @@ extern "C" { · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | void tStack_init (tStack* const); |
| 42 | 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 | 46 | void tStack_setCapacity (tStack* const, uint16_t cap); |
| 45 | 47 | int tStack_addIfNotAlreadyThere (tStack* const, uint16_t item); |
| @@ -91,28 +93,30 @@ extern "C" { · 45 unmodified lines | ||
| 91 | 93 | typedef _tPoly* tPoly; |
| 92 | 94 | |
| 93 | 95 | /* MPoly*/ |
| 94 | − void tPoly_init(tPoly* const, int maxNumVoices); | |
| 95 | − void tPoly_free(tPoly* const); | |
| 96 | + void tPoly_init (tPoly* const, int maxNumVoices); | |
| 97 | + void tPoly_free (tPoly* const); | |
| 98 | + void tPoly_initToPool (tPoly* const, int maxNumVoices, tMempool* const); | |
| 99 | + void tPoly_freeFromPool (tPoly* const, tMempool* const); | |
| 96 | 100 | |
| 97 | 101 | //ADDING A NOTE |
| 98 | − int tPoly_noteOn(tPoly* const, int note, uint8_t vel); | |
| 99 | − int tPoly_noteOff(tPoly* const, uint8_t note); | |
| 100 | − void tPoly_orderedAddToStack(tPoly* const, uint8_t noteVal); | |
| 101 | − void tPoly_setNumVoices(tPoly* const, uint8_t numVoices); | |
| 102 | − | |
| 103 | − void tPoly_setPitchBend(tPoly* const, float pitchBend); | |
| 104 | − void tPoly_setPitchGlideActive(tPoly* const, oBool isActive); | |
| 105 | − void tPoly_setPitchGlideTime(tPoly* const, float t); | |
| 106 | − void tPoly_tickPitch(tPoly* const); | |
| 107 | − void tPoly_tickPitchGlide(tPoly* const); | |
| 108 | − void tPoly_tickPitchBend(tPoly* const); | |
| 109 | − | |
| 110 | − int tPoly_getNumVoices(tPoly* const); | |
| 111 | − int tPoly_getNumActiveVoices(tPoly* const); | |
| 112 | − float tPoly_getPitch(tPoly* const, uint8_t voice); | |
| 113 | − int tPoly_getKey(tPoly* const, uint8_t voice); | |
| 114 | − int tPoly_getVelocity(tPoly* const, uint8_t voice); | |
| 115 | − int tPoly_isOn(tPoly* const, uint8_t voice); | |
| 102 | + int tPoly_noteOn (tPoly* const, int note, uint8_t vel); | |
| 103 | + int tPoly_noteOff (tPoly* const, uint8_t note); | |
| 104 | + void tPoly_orderedAddToStack (tPoly* const, uint8_t noteVal); | |
| 105 | + void tPoly_setNumVoices (tPoly* const, uint8_t numVoices); | |
| 106 | + | |
| 107 | + void tPoly_setPitchBend (tPoly* const, float pitchBend); | |
| 108 | + void tPoly_setPitchGlideActive (tPoly* const, oBool isActive); | |
| 109 | + void tPoly_setPitchGlideTime (tPoly* const, float t); | |
| 110 | + void tPoly_tickPitch (tPoly* const); | |
| 111 | + void tPoly_tickPitchGlide (tPoly* const); | |
| 112 | + void tPoly_tickPitchBend (tPoly* const); | |
| 113 | + | |
| 114 | + int tPoly_getNumVoices (tPoly* const); | |
| 115 | + int tPoly_getNumActiveVoices (tPoly* const); | |
| 116 | + float tPoly_getPitch (tPoly* const, uint8_t voice); | |
| 117 | + int tPoly_getKey (tPoly* const, uint8_t voice); | |
| 118 | + int tPoly_getVelocity (tPoly* const, uint8_t voice); | |
| 119 | + int tPoly_isOn (tPoly* const, uint8_t voice); | |
| 116 | 120 | |
| 117 | 121 | //============================================================================== |
| 118 | 122 | |
| @@ -14,6 +14,7 @@ extern "C" { · 13 unmodified lines | ||
| 14 | 14 | //============================================================================== |
| 15 | 15 | |
| 16 | 16 | #include "leaf-math.h" |
| 17 | +#include "leaf-mempool.h" | |
| 17 | 18 | #include "leaf-filters.h" |
| 18 | 19 | |
| 19 | 20 | //============================================================================== |
| @@ -25,13 +26,17 @@ extern "C" { · 5 unmodified lines | ||
| 25 | 26 | float phase; |
| 26 | 27 | float inc,freq; |
| 27 | 28 | |
| 28 | − } tCycle; | |
| 29 | + } _tCycle; | |
| 29 | 30 | |
| 30 | − void tCycle_init (tCycle* const); | |
| 31 | − void tCycle_free (tCycle* const); | |
| 31 | + typedef _tCycle* tCycle; | |
| 32 | 32 | |
| 33 | − float tCycle_tick (tCycle* const); | |
| 34 | − int tCycle_setFreq (tCycle* const, float freq); | |
| 33 | + void tCycle_init (tCycle* const); | |
| 34 | + void tCycle_free (tCycle* const); | |
| 35 | + void tCycle_initToPool (tCycle* const, tMempool* const); | |
| 36 | + void tCycle_freeFromPool (tCycle* const, tMempool* const); | |
| 37 | + | |
| 38 | + float tCycle_tick (tCycle* const); | |
| 39 | + int tCycle_setFreq (tCycle* const, float freq); | |
| 35 | 40 | |
| 36 | 41 | //============================================================================== |
| 37 | 42 | |
| @@ -42,13 +47,17 @@ extern "C" { · 4 unmodified lines | ||
| 42 | 47 | float phase; |
| 43 | 48 | float inc,freq; |
| 44 | 49 | |
| 45 | − } tTriangle; | |
| 50 | + } _tTriangle; | |
| 51 | + | |
| 52 | + typedef _tTriangle* tTriangle; | |
| 46 | 53 | |
| 47 | − void tTriangle_init (tTriangle* const); | |
| 48 | − void tTriangle_free (tTriangle* const); | |
| 54 | + void tTriangle_init (tTriangle* const); | |
| 55 | + void tTriangle_free (tTriangle* const); | |
| 56 | + void tTriangle_initToPool (tTriangle* const, tMempool* const); | |
| 57 | + void tTriangle_freeFromPool (tTriangle* const, tMempool* const); | |
| 49 | 58 | |
| 50 | − float tTriangle_tick (tTriangle* const); | |
| 51 | − int tTriangle_setFreq (tTriangle* const, float freq); | |
| 59 | + float tTriangle_tick (tTriangle* const); | |
| 60 | + int tTriangle_setFreq (tTriangle* const, float freq); | |
| 52 | 61 | |
| 53 | 62 | //============================================================================== |
| 54 | 63 | |
| @@ -59,13 +68,17 @@ extern "C" { · 4 unmodified lines | ||
| 59 | 68 | float phase; |
| 60 | 69 | float inc,freq; |
| 61 | 70 | |
| 62 | − } tSquare; | |
| 71 | + } _tSquare; | |
| 63 | 72 | |
| 64 | − void tSquare_init (tSquare* const); | |
| 65 | − void tSquare_free (tSquare* const); | |
| 73 | + typedef _tSquare* tSquare; | |
| 66 | 74 | |
| 67 | − float tSquare_tick (tSquare* const); | |
| 68 | − int tSquare_setFreq (tSquare* const, float freq); | |
| 75 | + void tSquare_init (tSquare* const); | |
| 76 | + void tSquare_free (tSquare* const); | |
| 77 | + void tSquare_initToPool (tSquare* const, tMempool* const); | |
| 78 | + void tSquare_freeFromPool(tSquare* const, tMempool* const); | |
| 79 | + | |
| 80 | + float tSquare_tick (tSquare* const); | |
| 81 | + int tSquare_setFreq (tSquare* const, float freq); | |
| 69 | 82 | |
| 70 | 83 | //============================================================================== |
| 71 | 84 | |
| @@ -76,13 +89,17 @@ extern "C" { · 4 unmodified lines | ||
| 76 | 89 | float phase; |
| 77 | 90 | float inc,freq; |
| 78 | 91 | |
| 79 | − } tSawtooth; | |
| 92 | + } _tSawtooth; | |
| 93 | + | |
| 94 | + typedef _tSawtooth* tSawtooth; | |
| 80 | 95 | |
| 81 | − void tSawtooth_init (tSawtooth* const); | |
| 82 | − void tSawtooth_free (tSawtooth* const); | |
| 96 | + void tSawtooth_init (tSawtooth* const); | |
| 97 | + void tSawtooth_free (tSawtooth* const); | |
| 98 | + void tSawtooth_initToPool (tSawtooth* const, tMempool* const); | |
| 99 | + void tSawtooth_freeFromPool (tSawtooth* const, tMempool* const); | |
| 83 | 100 | |
| 84 | − float tSawtooth_tick (tSawtooth* const); | |
| 85 | − int tSawtooth_setFreq (tSawtooth* const, float freq); | |
| 101 | + float tSawtooth_tick (tSawtooth* const); | |
| 102 | + int tSawtooth_setFreq (tSawtooth* const, float freq); | |
| 86 | 103 | |
| 87 | 104 | //============================================================================== |
| 88 | 105 | |
| @@ -92,13 +109,17 @@ extern "C" { · 3 unmodified lines | ||
| 92 | 109 | float phase; |
| 93 | 110 | float inc,freq; |
| 94 | 111 | |
| 95 | − } tPhasor; | |
| 112 | + } _tPhasor; | |
| 96 | 113 | |
| 97 | − void tPhasor_init (tPhasor* const); | |
| 98 | − void tPhasor_free (tPhasor* const); | |
| 114 | + typedef _tPhasor* tPhasor; | |
| 99 | 115 | |
| 100 | − float tPhasor_tick (tPhasor* const); | |
| 101 | − int tPhasor_setFreq (tPhasor* const, float freq); | |
| 116 | + void tPhasor_init (tPhasor* const); | |
| 117 | + void tPhasor_free (tPhasor* const); | |
| 118 | + void tPhasor_initToPool (tPhasor* const, tMempool* const); | |
| 119 | + void tPhasor_freeFromPool(tPhasor* const, tMempool* const); | |
| 120 | + | |
| 121 | + float tPhasor_tick (tPhasor* const); | |
| 122 | + int tPhasor_setFreq (tPhasor* const, float freq); | |
| 102 | 123 | |
| 103 | 124 | //============================================================================== |
| 104 | 125 | |
| @@ -116,12 +137,16 @@ extern "C" { · 11 unmodified lines | ||
| 116 | 137 | float pinkb0, pinkb1, pinkb2; |
| 117 | 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); | |
| 122 | − void tNoise_free (tNoise* const); | |
| 144 | + void tNoise_init (tNoise* const, NoiseType type); | |
| 145 | + void tNoise_free (tNoise* const); | |
| 146 | + void tNoise_initToPool (tNoise* const, NoiseType type, tMempool* const); | |
| 147 | + void tNoise_freeFromPool (tNoise* const, tMempool* const); | |
| 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 | 174 | float V[3]; |
| 150 | 175 | float P[3]; |
| 151 | 176 | float gK, gN, gL, C; |
| 152 | − } tNeuron; | |
| 153 | − | |
| 154 | − void tNeuron_init (tNeuron* const); | |
| 155 | − void tNeuron_free (tNeuron* const); | |
| 156 | − | |
| 157 | − void tNeuron_reset (tNeuron* const); | |
| 158 | − float tNeuron_Tick (tNeuron* const); | |
| 159 | − void tNeuron_setMode (tNeuron* const, NeuronMode mode); | |
| 160 | − void tNeuron_setCurrent (tNeuron* const, float current); | |
| 161 | − void tNeuron_setK (tNeuron* const, float K); | |
| 162 | − void tNeuron_setL (tNeuron* const, float L); | |
| 163 | − void tNeuron_setN (tNeuron* const, float N); | |
| 164 | − void tNeuron_setC (tNeuron* const, float C); | |
| 165 | − void tNeuron_setV1 (tNeuron* const, float V1); | |
| 166 | − void tNeuron_setV2 (tNeuron* const, float V2); | |
| 167 | − void tNeuron_setV3 (tNeuron* const, float V3); | |
| 168 | − void tNeuron_setTimeStep (tNeuron* const, float timestep); | |
| 177 | + } _tNeuron; | |
| 178 | + | |
| 179 | + typedef _tNeuron* tNeuron; | |
| 180 | + | |
| 181 | + void tNeuron_init (tNeuron* const); | |
| 182 | + void tNeuron_free (tNeuron* const); | |
| 183 | + void tNeuron_initToPool (tNeuron* const, tMempool* const); | |
| 184 | + void tNeuron_freeFromPool(tNeuron* const, tMempool* const); | |
| 185 | + | |
| 186 | + void tNeuron_reset (tNeuron* const); | |
| 187 | + float tNeuron_tick (tNeuron* const); | |
| 188 | + void tNeuron_setMode (tNeuron* const, NeuronMode mode); | |
| 189 | + void tNeuron_setCurrent (tNeuron* const, float current); | |
| 190 | + void tNeuron_setK (tNeuron* const, float K); | |
| 191 | + void tNeuron_setL (tNeuron* const, float L); | |
| 192 | + void tNeuron_setN (tNeuron* const, float N); | |
| 193 | + void tNeuron_setC (tNeuron* const, float C); | |
| 194 | + void tNeuron_setV1 (tNeuron* const, float V1); | |
| 195 | + void tNeuron_setV2 (tNeuron* const, float V2); | |
| 196 | + void tNeuron_setV3 (tNeuron* const, float V3); | |
| 197 | + void tNeuron_setTimeStep (tNeuron* const, float timestep); | |
| 169 | 198 | |
| 170 | 199 | //============================================================================== |
| 171 | 200 | |
| @@ -176,3 +205,4 @@ extern "C" { · 4 unmodified lines | ||
| 176 | 205 | #endif // LEAF_OSCILLATORS_H_INCLUDED |
| 177 | 206 | |
| 178 | 207 | //============================================================================== |
| 208 | + | |
| @@ -19,6 +19,7 @@ extern "C" { · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 20 | #include "leaf-global.h" |
| 21 | 21 | #include "leaf-math.h" |
| 22 | +#include "leaf-mempool.h" | |
| 22 | 23 | #include "leaf-delay.h" |
| 23 | 24 | #include "leaf-filters.h" |
| 24 | 25 | #include "leaf-oscillators.h" |
| @@ -45,28 +46,30 @@ extern "C" { · 20 unmodified lines | ||
| 45 | 46 | |
| 46 | 47 | typedef _tPluck* tPluck; |
| 47 | 48 | |
| 48 | − void tPluck_init (tPluck* const, float lowestFrequency); //float delayBuff[DELAY_LENGTH]); | |
| 49 | − void tPluck_free (tPluck* const); | |
| 49 | + void tPluck_init (tPluck* const, float lowestFrequency); //float delayBuff[DELAY_LENGTH]); | |
| 50 | + void tPluck_free (tPluck* const); | |
| 51 | + void tPluck_initToPool (tPluck* const, float lowestFrequency, tMempool* const); | |
| 52 | + void tPluck_freeFromPool (tPluck* const, tMempool* const); | |
| 50 | 53 | |
| 51 | − float tPluck_tick (tPluck* const); | |
| 54 | + float tPluck_tick (tPluck* const); | |
| 52 | 55 | |
| 53 | 56 | // Pluck the string. |
| 54 | − void tPluck_pluck (tPluck* const, float amplitude); | |
| 57 | + void tPluck_pluck (tPluck* const, float amplitude); | |
| 55 | 58 | |
| 56 | 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 | 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 | 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 | 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 | 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 | 106 | typedef _tKarplusStrong* tKarplusStrong; |
| 104 | 107 | |
| 105 | − void tKarplusStrong_init (tKarplusStrong* const, float lowestFrequency); // float delayBuff[2][DELAY_LENGTH]); | |
| 106 | − void tKarplusStrong_free (tKarplusStrong* const); | |
| 108 | + void tKarplusStrong_init (tKarplusStrong* const, float lowestFrequency); // float delayBuff[2][DELAY_LENGTH]); | |
| 109 | + void tKarplusStrong_free (tKarplusStrong* const); | |
| 110 | + void tKarplusStrong_initToPool (tKarplusStrong* const, float lowestFrequency, tMempool* const); | |
| 111 | + void tKarplusStrong_freeFromPool (tKarplusStrong* const, tMempool* const); | |
| 107 | 112 | |
| 108 | − float tKarplusStrong_tick (tKarplusStrong* const); | |
| 113 | + float tKarplusStrong_tick (tKarplusStrong* const); | |
| 109 | 114 | |
| 110 | 115 | // Pluck the string. |
| 111 | − void tKarplusStrong_pluck (tKarplusStrong* const, float amplitude); | |
| 116 | + void tKarplusStrong_pluck (tKarplusStrong* const, float amplitude); | |
| 112 | 117 | |
| 113 | 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 | 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 | 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 | 127 | // Perform the control change specified by \e number and \e value (0.0 - 128.0). |
| 123 | 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 | 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 | 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 | 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 | 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 | 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); | |
| 157 | − void tSimpleLivingString_free (tSimpleLivingString* const); | |
| 158 | − float tSimpleLivingString_tick (tSimpleLivingString* const, float input); | |
| 159 | − float tSimpleLivingString_sample (tSimpleLivingString* const); | |
| 160 | − void tSimpleLivingString_setFreq (tSimpleLivingString* const, float freq); | |
| 161 | − void tSimpleLivingString_setWaveLength (tSimpleLivingString* const, float waveLength); // in samples | |
| 162 | − void tSimpleLivingString_setDampFreq (tSimpleLivingString* const, float dampFreq); | |
| 163 | − void tSimpleLivingString_setDecay (tSimpleLivingString* const, float decay); // should be near 1.0 | |
| 161 | + void tSimpleLivingString_init (tSimpleLivingString* const, float freq, float dampFreq, | |
| 162 | + float decay, float targetLev, float levSmoothFactor, | |
| 163 | + float levStrength, int levMode); | |
| 164 | + void tSimpleLivingString_free (tSimpleLivingString* const); | |
| 165 | + void tSimpleLivingString_initToPool (tSimpleLivingString* const, float freq, float dampFreq, | |
| 166 | + float decay, float targetLev, float levSmoothFactor, | |
| 167 | + float levStrength, int levMode, tMempool* const); | |
| 168 | + void tSimpleLivingString_freeFromPool (tSimpleLivingString* const, tMempool* const); | |
| 169 | + | |
| 170 | + float tSimpleLivingString_tick (tSimpleLivingString* const, float input); | |
| 171 | + float tSimpleLivingString_sample (tSimpleLivingString* const); | |
| 172 | + void tSimpleLivingString_setFreq (tSimpleLivingString* const, float freq); | |
| 173 | + void tSimpleLivingString_setWaveLength (tSimpleLivingString* const, float waveLength); // in samples | |
| 174 | + void tSimpleLivingString_setDampFreq (tSimpleLivingString* const, float dampFreq); | |
| 175 | + void tSimpleLivingString_setDecay (tSimpleLivingString* const, float decay); // should be near 1.0 | |
| 164 | 176 | void tSimpleLivingString_setTargetLev (tSimpleLivingString* const, float targetLev); |
| 165 | 177 | void tSimpleLivingString_setLevSmoothFactor (tSimpleLivingString* const, float levSmoothFactor); |
| 166 | − void tSimpleLivingString_setLevStrength (tSimpleLivingString* const, float levStrength); | |
| 167 | − void tSimpleLivingString_setLevMode (tSimpleLivingString* const, int levMode); | |
| 178 | + void tSimpleLivingString_setLevStrength (tSimpleLivingString* const, float levStrength); | |
| 179 | + void tSimpleLivingString_setLevMode (tSimpleLivingString* const, int levMode); | |
| 168 | 180 | |
| 169 | 181 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
| 170 | 182 | |
| @@ -186,19 +198,25 @@ extern "C" { · 15 unmodified lines | ||
| 186 | 198 | |
| 187 | 199 | typedef _tLivingString* tLivingString; |
| 188 | 200 | |
| 189 | − void tLivingString_init (tLivingString* const, float freq, float pickPos, float prepIndex, float dampFreq, float decay, | |
| 190 | − float targetLev, float levSmoothFactor, float levStrength, int levMode); | |
| 191 | − void tLivingString_free (tLivingString* const); | |
| 192 | − float tLivingString_tick (tLivingString* const, float input); | |
| 193 | − float tLivingString_sample (tLivingString* const); | |
| 201 | + void tLivingString_init (tLivingString* const, float freq, float pickPos, float prepIndex, | |
| 202 | + float dampFreq, float decay, float targetLev, float levSmoothFactor, | |
| 203 | + float levStrength, int levMode); | |
| 204 | + void tLivingString_free (tLivingString* const); | |
| 205 | + void tLivingString_initToPool (tLivingString* const, float freq, float pickPos, float prepIndex, | |
| 206 | + float dampFreq, float decay, float targetLev, float levSmoothFactor, | |
| 207 | + float levStrength, int levMode, tMempool* const); | |
| 208 | + void tLivingString_freeFromPool (tLivingString* const, tMempool* const); | |
| 209 | + | |
| 210 | + float tLivingString_tick (tLivingString* const, float input); | |
| 211 | + float tLivingString_sample (tLivingString* const); | |
| 194 | 212 | void tLivingString_setFreq (tLivingString* const, float freq); |
| 195 | − void tLivingString_setWaveLength (tLivingString* const, float waveLength); // in samples | |
| 196 | − void tLivingString_setPickPos (tLivingString* const, float pickPos); | |
| 197 | − void tLivingString_setPrepIndex (tLivingString* const, float prepIndex); | |
| 213 | + void tLivingString_setWaveLength (tLivingString* const, float waveLength); // in samples | |
| 214 | + void tLivingString_setPickPos (tLivingString* const, float pickPos); | |
| 215 | + void tLivingString_setPrepIndex (tLivingString* const, float prepIndex); | |
| 198 | 216 | void tLivingString_setDampFreq (tLivingString* const, float dampFreq); |
| 199 | − void tLivingString_setDecay (tLivingString* const, float decay); // should be near 1.0 | |
| 200 | − void tLivingString_setTargetLev (tLivingString* const, float targetLev); | |
| 201 | − void tLivingString_setLevSmoothFactor (tLivingString* const, float levSmoothFactor); | |
| 217 | + void tLivingString_setDecay (tLivingString* const, float decay); // should be near 1.0 | |
| 218 | + void tLivingString_setTargetLev (tLivingString* const, float targetLev); | |
| 219 | + void tLivingString_setLevSmoothFactor (tLivingString* const, float levSmoothFactor); | |
| 202 | 220 | void tLivingString_setLevStrength (tLivingString* const, float levStrength); |
| 203 | 221 | void tLivingString_setLevMode (tLivingString* const, int levMode); |
| 204 | 222 | |
| @@ -211,12 +229,15 @@ extern "C" { · 6 unmodified lines | ||
| 211 | 229 | |
| 212 | 230 | typedef _tReedTable* tReedTable; |
| 213 | 231 | |
| 214 | − void tReedTable_init (tReedTable* const, float offset, float slope); | |
| 215 | − void tReedTable_free (tReedTable* const); | |
| 216 | − float tReedTable_tick (tReedTable* const, float input); | |
| 217 | − float tReedTable_tanh_tick (tReedTable* const p, float input); //tanh softclip version of reed table - replacing the hard clip in original stk code | |
| 218 | − void tReedTable_setOffset (tReedTable* const, float offset); | |
| 219 | − void tReedTable_setSlope (tReedTable* const, float slope); | |
| 232 | + void tReedTable_init (tReedTable* const, float offset, float slope); | |
| 233 | + void tReedTable_free (tReedTable* const); | |
| 234 | + void tReedTable_initToPool (tReedTable* const, float offset, float slope, tMempool* const); | |
| 235 | + void tReedTable_freeFromPool (tReedTable* const, tMempool* const); | |
| 236 | + | |
| 237 | + float tReedTable_tick (tReedTable* const, float input); | |
| 238 | + float tReedTable_tanh_tick (tReedTable* const, float input); //tanh softclip version of reed table - replacing the hard clip in original stk code | |
| 239 | + void tReedTable_setOffset (tReedTable* const, float offset); | |
| 240 | + void tReedTable_setSlope (tReedTable* const, float slope); | |
| 220 | 241 | |
| 221 | 242 | //============================================================================== |
| 222 | 243 | |
| @@ -17,6 +17,7 @@ extern "C" { · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | #include "leaf-global.h" |
| 19 | 19 | #include "leaf-math.h" |
| 20 | +#include "leaf-mempool.h" | |
| 20 | 21 | #include "leaf-delay.h" |
| 21 | 22 | #include "leaf-filters.h" |
| 22 | 23 | #include "leaf-oscillators.h" |
| @@ -41,16 +42,18 @@ extern "C" { · 18 unmodified lines | ||
| 41 | 42 | |
| 42 | 43 | typedef _tPRCReverb* tPRCReverb; |
| 43 | 44 | |
| 44 | − void tPRCReverb_init (tPRCReverb* const, float t60); | |
| 45 | − void tPRCReverb_free (tPRCReverb* const); | |
| 45 | + void tPRCReverb_init (tPRCReverb* const, float t60); | |
| 46 | + void tPRCReverb_free (tPRCReverb* const); | |
| 47 | + void tPRCReverb_initToPool (tPRCReverb* const, float t60, tMempool* const); | |
| 48 | + void tPRCReverb_freeFromPool (tPRCReverb* const, tMempool* const); | |
| 46 | 49 | |
| 47 | − float tPRCReverb_tick (tPRCReverb* const, float input); | |
| 50 | + float tPRCReverb_tick (tPRCReverb* const, float input); | |
| 48 | 51 | |
| 49 | 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 | 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 | 77 | typedef _tNReverb* tNReverb; |
| 75 | 78 | |
| 76 | − void tNReverb_init (tNReverb* const, float t60); | |
| 77 | − void tNReverb_free (tNReverb* const); | |
| 79 | + void tNReverb_init (tNReverb* const, float t60); | |
| 80 | + void tNReverb_free (tNReverb* const); | |
| 81 | + void tNReverb_initToPool (tNReverb* const, float t60, tMempool* const); | |
| 82 | + void tNReverb_freeFromPool (tNReverb* const, tMempool* const); | |
| 78 | 83 | |
| 79 | − float tNReverb_tick (tNReverb* const, float input); | |
| 80 | − void tNReverb_tickStereo(tNReverb* const rev, float input, float* output); | |
| 84 | + float tNReverb_tick (tNReverb* const, float input); | |
| 85 | + void tNReverb_tickStereo (tNReverb* const rev, float input, float* output); | |
| 81 | 86 | |
| 82 | 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 | 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 | 141 | void tDattorroReverb_init (tDattorroReverb* const); |
| 137 | 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 | 146 | float tDattorroReverb_tick (tDattorroReverb* const, float input); |
| 140 | 147 | void tDattorroReverb_tickStereo (tDattorroReverb* const rev, float input, float* output); |
| 141 | 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 | 150 | void tDattorroReverb_setHP (tDattorroReverb* const, float freq); |
| 144 | 151 | void tDattorroReverb_setSize (tDattorroReverb* const, float size); |
| 145 | 152 | void tDattorroReverb_setInputDelay (tDattorroReverb* const, float preDelay); |
| @@ -18,6 +18,7 @@ extern "C" { · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | #include "leaf-global.h" |
| 20 | 20 | #include "leaf-math.h" |
| 21 | +#include "leaf-mempool.h" | |
| 21 | 22 | #include "leaf-envelopes.h" |
| 22 | 23 | #include "leaf-mempool.h" |
| 23 | 24 | |
| @@ -45,27 +46,27 @@ extern "C" { · 21 unmodified lines | ||
| 45 | 46 | |
| 46 | 47 | typedef _tBuffer* tBuffer; |
| 47 | 48 | |
| 48 | − void tBuffer_init (tBuffer* const, uint32_t length); | |
| 49 | − void tBuffer_init_locate (tBuffer* const sb, uint32_t length, mpool_t* pool); | |
| 50 | − void tBuffer_free (tBuffer* const); | |
| 51 | − void tBuffer_free_locate (tBuffer* const sb, mpool_t* pool); | |
| 49 | + void tBuffer_init (tBuffer* const, uint32_t length); | |
| 50 | + void tBuffer_free (tBuffer* const); | |
| 51 | + void tBuffer_initToPool (tBuffer* const, uint32_t length, tMempool* const); | |
| 52 | + void tBuffer_freeFromPool (tBuffer* const, tMempool* const); | |
| 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_stop (tBuffer* const); | |
| 61 | − int tBuffer_getRecordPosition(tBuffer* const); | |
| 60 | + void tBuffer_record (tBuffer* const); | |
| 61 | + void tBuffer_stop (tBuffer* const); | |
| 62 | + int tBuffer_getRecordPosition (tBuffer* const); | |
| 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_getRecordedLength(tBuffer* const sb); | |
| 68 | + uint32_t tBuffer_getBufferLength (tBuffer* const); | |
| 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 | 108 | typedef _tSampler* tSampler; |
| 108 | 109 | |
| 109 | − void tSampler_init (tSampler* const, tBuffer* const); | |
| 110 | − void tSampler_free (tSampler* const); | |
| 110 | + void tSampler_init (tSampler* const, tBuffer* const); | |
| 111 | + void tSampler_free (tSampler* const); | |
| 112 | + void tSampler_initToPool (tSampler* const, tBuffer* const, tMempool* const); | |
| 113 | + void tSampler_freeFromPool (tSampler* const, tMempool* const); | |
| 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); | |
| 119 | − void tSampler_stop (tSampler* const); | |
| 121 | + void tSampler_play (tSampler* const); | |
| 122 | + void tSampler_stop (tSampler* const); | |
| 120 | 123 | |
| 121 | − void tSampler_setStart (tSampler* const, int32_t start); | |
| 122 | − void tSampler_setEnd (tSampler* const, int32_t end); | |
| 124 | + void tSampler_setStart (tSampler* const, int32_t start); | |
| 125 | + void tSampler_setEnd (tSampler* const, int32_t end); | |
| 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 | |
| @@ -38,6 +38,24 @@ void tEnvelopeFollower_free(tEnvelopeFollower* const ef) · 37 unmodified lines | ||
| 38 | 38 | leaf_free(e); |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | +void tEnvelopeFollower_initToPool (tEnvelopeFollower* const ef, float attackThreshold, float decayCoeff, tMempool* const mp) | |
| 42 | +{ | |
| 43 | + _tMempool* m = *mp; | |
| 44 | + _tEnvelopeFollower* e = *ef = (_tEnvelopeFollower*) mpool_alloc(sizeof(_tEnvelopeFollower), m->pool); | |
| 45 | + | |
| 46 | + e->y = 0.0f; | |
| 47 | + e->a_thresh = attackThreshold; | |
| 48 | + e->d_coeff = decayCoeff; | |
| 49 | +} | |
| 50 | + | |
| 51 | +void tEnvelopeFollower_freeFromPool (tEnvelopeFollower* const ef, tMempool* const mp) | |
| 52 | +{ | |
| 53 | + _tMempool* m = *mp; | |
| 54 | + _tEnvelopeFollower* e = *ef; | |
| 55 | + | |
| 56 | + mpool_free(e, m->pool); | |
| 57 | +} | |
| 58 | + | |
| 41 | 59 | float tEnvelopeFollower_tick(tEnvelopeFollower* const ef, float x) |
| 42 | 60 | { |
| 43 | 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 | 90 | /* Power Follower */ |
| 76 | 91 | //=========================================================================== |
| @@ -90,6 +105,24 @@ void tPowerFollower_free(tPowerFollower* const pf) · 13 unmodified lines | ||
| 90 | 105 | leaf_free(p); |
| 91 | 106 | } |
| 92 | 107 | |
| 108 | +void tPowerFollower_initToPool (tPowerFollower* const pf, float factor, tMempool* const mp) | |
| 109 | +{ | |
| 110 | + _tMempool* m = *mp; | |
| 111 | + _tPowerFollower* p = *pf = (_tPowerFollower*) mpool_alloc(sizeof(_tPowerFollower), m->pool); | |
| 112 | + | |
| 113 | + p->curr=0.0f; | |
| 114 | + p->factor=factor; | |
| 115 | + p->oneminusfactor=1.0f-factor; | |
| 116 | +} | |
| 117 | + | |
| 118 | +void tPowerFollower_freeFromPool (tPowerFollower* const pf, tMempool* const mp) | |
| 119 | +{ | |
| 120 | + _tMempool* m = *mp; | |
| 121 | + _tPowerFollower* p = *pf; | |
| 122 | + | |
| 123 | + mpool_free(p, m->pool); | |
| 124 | +} | |
| 125 | + | |
| 93 | 126 | int tPowerFollower_setFactor(tPowerFollower* const pf, float factor) |
| 94 | 127 | { |
| 95 | 128 | _tPowerFollower* p = *pf; |
| @@ -123,7 +156,57 @@ float tPowerFollower_sample(tPowerFollower* const pf) · 27 unmodified lines | ||
| 123 | 156 | |
| 124 | 157 | void 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 | + | |
| 199 | +void tEnvPD_free (tEnvPD* const xpd) | |
| 200 | +{ | |
| 201 | + _tEnvPD* x = *xpd; | |
| 202 | + | |
| 203 | + leaf_free(x); | |
| 204 | +} | |
| 205 | + | |
| 206 | +void tEnvPD_initToPool (tEnvPD* const xpd, int ws, int hs, int bs, tMempool* const mp) | |
| 207 | +{ | |
| 208 | + _tMempool* m = *mp; | |
| 209 | + _tEnvPD* x = *xpd = (_tEnvPD*) mpool_alloc(sizeof(_tEnvPD), m->pool); | |
| 127 | 210 | |
| 128 | 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 | |
| 166 | −void tEnvPD_free (tEnvPD* const xpd) | |
| 249 | +void tEnvPD_freeFromPool (tEnvPD* const xpd, tMempool* const mp) | |
| 167 | 250 | { |
| 251 | + _tMempool* m = *mp; | |
| 168 | 252 | _tEnvPD* x = *xpd; |
| 169 | 253 | |
| 170 | − leaf_free(x); | |
| 254 | + mpool_free(x, m->pool); | |
| 171 | 255 | } |
| 172 | 256 | |
| 173 | 257 | float tEnvPD_tick (tEnvPD* const xpd) |
| @@ -222,25 +306,34 @@ static void atkdtk_envelope(tAttackDetection* const a, float *in); · 48 unmodified lines | ||
| 222 | 306 | |
| 223 | 307 | /********Constructor/Destructor***************/ |
| 224 | 308 | |
| 225 | −void tAttackDetection_init(tAttackDetection* const ad, int blocksize) | |
| 309 | +void tAttackDetection_init(tAttackDetection* const ad, int blocksize, int atk, int rel) | |
| 226 | 310 | { |
| 227 | 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 | |
| 232 | −void tAttackDetection_init_expanded(tAttackDetection* const ad, int blocksize, int atk, int rel) | |
| 316 | +void 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 | + | |
| 323 | +void tAttackDetection_initToPool (tAttackDetection* const ad, int blocksize, int atk, int rel, tMempool* const mp) | |
| 324 | +{ | |
| 325 | + _tMempool* m = *mp; | |
| 326 | + *ad = (_tAttackDetection*) mpool_alloc(sizeof(_tAttackDetection), m->pool); | |
| 235 | 327 | |
| 236 | 328 | atkdtk_init(ad, blocksize, atk, rel); |
| 237 | 329 | } |
| 238 | 330 | |
| 239 | −void tAttackDetection_free(tAttackDetection* const ad) | |
| 331 | +void tAttackDetection_freeFromPool (tAttackDetection* const ad, tMempool* const mp) | |
| 240 | 332 | { |
| 333 | + _tMempool* m = *mp; | |
| 241 | 334 | _tAttackDetection* a = *ad; |
| 242 | 335 | |
| 243 | − leaf_free(a); | |
| 336 | + mpool_free(a, m->pool); | |
| 244 | 337 | } |
| 245 | 338 | |
| 246 | 339 | /*******Public Functions***********/ |
| @@ -265,8 +358,8 @@ void tAttackDetection_setSamplerate(tAttackDetection* const ad, int inRate) · 18 unmodified lines | ||
| 265 | 358 | a->samplerate = inRate; |
| 266 | 359 | |
| 267 | 360 | //Reset atk and rel to recalculate coeff |
| 268 | − tAttackDetection_setAtk(ad, a->atk); | |
| 269 | − tAttackDetection_setRel(ad, a->rel); | |
| 361 | + tAttackDetection_setAttack(ad, a->atk); | |
| 362 | + tAttackDetection_setRelease(ad, a->rel); | |
| 270 | 363 | } |
| 271 | 364 | |
| 272 | 365 | void tAttackDetection_setThreshold(tAttackDetection* const ad, float thres) |
| @@ -275,14 +368,14 @@ void tAttackDetection_setThreshold(tAttackDetection* const ad, float thres) · 2 unmodified lines | ||
| 275 | 368 | a->threshold = thres; |
| 276 | 369 | } |
| 277 | 370 | |
| 278 | −void tAttackDetection_setAtk(tAttackDetection* const ad, int inAtk) | |
| 371 | +void tAttackDetection_setAttack(tAttackDetection* const ad, int inAtk) | |
| 279 | 372 | { |
| 280 | 373 | _tAttackDetection* a = *ad; |
| 281 | 374 | a->atk = inAtk; |
| 282 | 375 | a->atk_coeff = pow(0.01, 1.0/(a->atk * a->samplerate * 0.001)); |
| 283 | 376 | } |
| 284 | 377 | |
| 285 | −void tAttackDetection_setRel(tAttackDetection* const ad, int inRel) | |
| 378 | +void tAttackDetection_setRelease(tAttackDetection* const ad, int inRel) | |
| 286 | 379 | { |
| 287 | 380 | _tAttackDetection* a = *ad; |
| 288 | 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 | 416 | a->env = 0; |
| 324 | 417 | |
| 325 | − tAttackDetection_setAtk(ad, atk); | |
| 326 | − tAttackDetection_setRel(ad, rel); | |
| 418 | + tAttackDetection_setAttack(ad, atk); | |
| 419 | + tAttackDetection_setRelease(ad, rel); | |
| 327 | 420 | } |
| 328 | 421 | |
| 329 | 422 | static void atkdtk_envelope(tAttackDetection* const ad, float *in) |
| @@ -343,98 +436,6 @@ static void atkdtk_envelope(tAttackDetection* const ad, float *in) · 13 unmodified lines | ||
| 343 | 436 | |
| 344 | 437 | } |
| 345 | 438 | |
| 346 | −//=========================================================================== | |
| 347 | −// PERIODDETECTION | |
| 348 | −//=========================================================================== | |
| 349 | −void tPeriodDetection_init (tPeriodDetection* const pd, float* in, float* out, int bufSize, int frameSize) | |
| 350 | −{ | |
| 351 | − _tPeriodDetection* p = *pd = (_tPeriodDetection*) leaf_alloc(sizeof(_tPeriodDetection)); | |
| 352 | − | |
| 353 | − p->inBuffer = in; | |
| 354 | − p->outBuffer = out; | |
| 355 | − p->bufSize = bufSize; | |
| 356 | − p->frameSize = frameSize; | |
| 357 | − p->framesPerBuffer = p->bufSize / p->frameSize; | |
| 358 | − p->curBlock = 1; | |
| 359 | − p->lastBlock = 0; | |
| 360 | − p->index = 0; | |
| 361 | − | |
| 362 | − p->hopSize = DEFHOPSIZE; | |
| 363 | − p->windowSize = DEFWINDOWSIZE; | |
| 364 | − p->fba = FBA; | |
| 365 | − | |
| 366 | − tEnvPD_init(&p->env, p->windowSize, p->hopSize, p->frameSize); | |
| 367 | − | |
| 368 | − tSNAC_init(&p->snac, DEFOVERLAP); | |
| 369 | − | |
| 370 | − p->timeConstant = DEFTIMECONSTANT; | |
| 371 | − p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant); | |
| 372 | −} | |
| 373 | − | |
| 374 | −void tPeriodDetection_free (tPeriodDetection* const pd) | |
| 375 | −{ | |
| 376 | − _tPeriodDetection* p = *pd; | |
| 377 | − | |
| 378 | − tEnvPD_free(&p->env); | |
| 379 | − tSNAC_free(&p->snac); | |
| 380 | − leaf_free(p); | |
| 381 | −} | |
| 382 | − | |
| 383 | −float tPeriodDetection_findPeriod (tPeriodDetection* pd, float sample) | |
| 384 | −{ | |
| 385 | − _tPeriodDetection* p = *pd; | |
| 386 | − | |
| 387 | − int i, iLast; | |
| 388 | − | |
| 389 | − i = (p->curBlock*p->frameSize); | |
| 390 | − iLast = (p->lastBlock*p->frameSize)+p->index; | |
| 391 | − | |
| 392 | − p->i = i; | |
| 393 | − p->iLast = iLast; | |
| 394 | − | |
| 395 | − p->inBuffer[i+p->index] = sample; | |
| 396 | − | |
| 397 | − p->index++; | |
| 398 | − p->indexstore = p->index; | |
| 399 | − if (p->index >= p->frameSize) | |
| 400 | − { | |
| 401 | − p->index = 0; | |
| 402 | − | |
| 403 | − tEnvPD_processBlock(&p->env, &(p->inBuffer[i])); | |
| 404 | − | |
| 405 | − tSNAC_ioSamples(&p->snac, &(p->inBuffer[i]), &(p->outBuffer[i]), p->frameSize); | |
| 406 | − p->period = tSNAC_getPeriod(&p->snac); | |
| 407 | − | |
| 408 | − p->curBlock++; | |
| 409 | − if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0; | |
| 410 | − p->lastBlock++; | |
| 411 | − if (p->lastBlock >= p->framesPerBuffer) p->lastBlock = 0; | |
| 412 | − } | |
| 413 | − | |
| 414 | − // changed from period to p->period | |
| 415 | − return p->period; | |
| 416 | −} | |
| 417 | − | |
| 418 | −void tPeriodDetection_setHopSize(tPeriodDetection* pd, int hs) | |
| 419 | −{ | |
| 420 | − _tPeriodDetection* p = *pd; | |
| 421 | − p->hopSize = hs; | |
| 422 | −} | |
| 423 | − | |
| 424 | −void tPeriodDetection_setWindowSize(tPeriodDetection* pd, int ws) | |
| 425 | −{ | |
| 426 | − _tPeriodDetection* p = *pd; | |
| 427 | − p->windowSize = ws; | |
| 428 | −} | |
| 429 | − | |
| 430 | − | |
| 431 | − | |
| 432 | − | |
| 433 | − | |
| 434 | − | |
| 435 | − | |
| 436 | − | |
| 437 | − | |
| 438 | 439 | //=========================================================================== |
| 439 | 440 | // SNAC |
| 440 | 441 | //=========================================================================== |
| @@ -461,7 +462,7 @@ static float snac_spectralpeak(tSNAC* const s, float periodlength); · 20 unmodified lines | ||
| 461 | 462 | |
| 462 | 463 | void 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 | 467 | s->biasfactor = DEFBIAS; |
| 467 | 468 | s->timeindex = 0; |
| @@ -471,10 +472,10 @@ void tSNAC_init(tSNAC* const snac, int overlaparg) · 3 unmodified lines | ||
| 471 | 472 | s->minrms = DEFMINRMS; |
| 472 | 473 | s->framesize = SNAC_FRAME_SIZE; |
| 473 | 474 | |
| 474 | − s->inputbuf = (float*) leaf_alloc(sizeof(float) * SNAC_FRAME_SIZE); | |
| 475 | − s->processbuf = (float*) leaf_alloc(sizeof(float) * (SNAC_FRAME_SIZE * 2)); | |
| 476 | − s->spectrumbuf = (float*) leaf_alloc(sizeof(float) * (SNAC_FRAME_SIZE / 2)); | |
| 477 | − s->biasbuf = (float*) leaf_alloc(sizeof(float) * SNAC_FRAME_SIZE); | |
| 475 | + s->inputbuf = (float*) leaf_allocAndClear(sizeof(float) * SNAC_FRAME_SIZE); | |
| 476 | + s->processbuf = (float*) leaf_allocAndClear(sizeof(float) * (SNAC_FRAME_SIZE * 2)); | |
| 477 | + s->spectrumbuf = (float*) leaf_allocAndClear(sizeof(float) * (SNAC_FRAME_SIZE / 2)); | |
| 478 | + s->biasbuf = (float*) leaf_allocAndClear(sizeof(float) * SNAC_FRAME_SIZE); | |
| 478 | 479 | |
| 479 | 480 | snac_biasbuf(snac); |
| 480 | 481 | tSNAC_setOverlap(snac, overlaparg); |
| @@ -490,6 +491,41 @@ void tSNAC_free(tSNAC* const snac) · 9 unmodified lines | ||
| 490 | 491 | leaf_free(s->biasbuf); |
| 491 | 492 | leaf_free(s); |
| 492 | 493 | } |
| 494 | + | |
| 495 | +void tSNAC_initToPool (tSNAC* const snac, int overlaparg, tMempool* const mp) | |
| 496 | +{ | |
| 497 | + _tMempool* m = *mp; | |
| 498 | + _tSNAC* s = *snac = (_tSNAC*) mpool_alloc(sizeof(_tSNAC), m->pool); | |
| 499 | + | |
| 500 | + s->biasfactor = DEFBIAS; | |
| 501 | + s->timeindex = 0; | |
| 502 | + s->periodindex = 0; | |
| 503 | + s->periodlength = 0.; | |
| 504 | + s->fidelity = 0.; | |
| 505 | + s->minrms = DEFMINRMS; | |
| 506 | + s->framesize = SNAC_FRAME_SIZE; | |
| 507 | + | |
| 508 | + s->inputbuf = (float*) mpool_allocAndClear(sizeof(float) * SNAC_FRAME_SIZE, m->pool); | |
| 509 | + s->processbuf = (float*) mpool_allocAndClear(sizeof(float) * (SNAC_FRAME_SIZE * 2), m->pool); | |
| 510 | + s->spectrumbuf = (float*) mpool_allocAndClear(sizeof(float) * (SNAC_FRAME_SIZE / 2), m->pool); | |
| 511 | + s->biasbuf = (float*) mpool_allocAndClear(sizeof(float) * SNAC_FRAME_SIZE, m->pool); | |
| 512 | + | |
| 513 | + snac_biasbuf(snac); | |
| 514 | + tSNAC_setOverlap(snac, overlaparg); | |
| 515 | +} | |
| 516 | + | |
| 517 | +void tSNAC_freeFromPool (tSNAC* const snac, tMempool* const mp) | |
| 518 | +{ | |
| 519 | + _tMempool* m = *mp; | |
| 520 | + _tSNAC* s = *snac; | |
| 521 | + | |
| 522 | + mpool_free(s->inputbuf, m->pool); | |
| 523 | + mpool_free(s->processbuf, m->pool); | |
| 524 | + mpool_free(s->spectrumbuf, m->pool); | |
| 525 | + mpool_free(s->biasbuf, m->pool); | |
| 526 | + mpool_free(s, m->pool); | |
| 527 | +} | |
| 528 | + | |
| 493 | 529 | /******************************************************************************/ |
| 494 | 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 | 774 | _tSNAC* s = *snac; |
| 739 | 775 | |
| 740 | − if(periodlength < 4.) return periodlength; | |
| 776 | + if(periodlength < 4.0f) return periodlength; | |
| 741 | 777 | |
| 742 | 778 | float max = 0.; |
| 743 | 779 | int n, startbin, stopbin, peakbin = 0; |
| 744 | 780 | int spectrumsize = s->framesize>>1; |
| 745 | 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 | 785 | if(startbin < 1) startbin = 1; |
| 750 | − stopbin = (int)(peaklocation * 1.25 + 0.5); | |
| 786 | + stopbin = (int)(peaklocation * 1.25f + 0.5f); | |
| 751 | 787 | if(stopbin >= spectrumsize - 1) stopbin = spectrumsize - 1; |
| 752 | 788 | |
| 753 | 789 | for(n=startbin; n<stopbin; n++) |
| @@ -768,7 +804,7 @@ static float snac_spectralpeak(tSNAC* const snac, float periodlength) · 14 unmodified lines | ||
| 768 | 804 | // calculate amplitudes in peak region |
| 769 | 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 | 810 | peaklocation = (float)peakbin + interpolate3phase(spectrumbuf, peakbin); |
| @@ -785,17 +821,137 @@ static void snac_biasbuf(tSNAC* const snac) · 10 unmodified lines | ||
| 785 | 821 | |
| 786 | 822 | int n; |
| 787 | 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 | 825 | float *biasbuf = s->biasbuf; |
| 790 | 826 | |
| 791 | 827 | 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 | 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 | +//=========================================================================== | |
| 841 | +void tPeriodDetection_init (tPeriodDetection* const pd, float* in, float* out, int bufSize, int frameSize) | |
| 842 | +{ | |
| 843 | + _tPeriodDetection* p = *pd = (_tPeriodDetection*) leaf_allocAndClear(sizeof(_tPeriodDetection)); | |
| 844 | + | |
| 845 | + p->inBuffer = in; | |
| 846 | + p->outBuffer = out; | |
| 847 | + p->bufSize = bufSize; | |
| 848 | + p->frameSize = frameSize; | |
| 849 | + p->framesPerBuffer = p->bufSize / p->frameSize; | |
| 850 | + p->curBlock = 1; | |
| 851 | + p->lastBlock = 0; | |
| 852 | + p->index = 0; | |
| 853 | + | |
| 854 | + p->hopSize = DEFHOPSIZE; | |
| 855 | + p->windowSize = DEFWINDOWSIZE; | |
| 856 | + p->fba = FBA; | |
| 857 | + | |
| 858 | + tEnvPD_init(&p->env, p->windowSize, p->hopSize, p->frameSize); | |
| 859 | + | |
| 860 | + tSNAC_init(&p->snac, DEFOVERLAP); | |
| 861 | + | |
| 862 | + p->timeConstant = DEFTIMECONSTANT; | |
| 863 | + p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant); | |
| 864 | +} | |
| 865 | + | |
| 866 | +void tPeriodDetection_free (tPeriodDetection* const pd) | |
| 867 | +{ | |
| 868 | + _tPeriodDetection* p = *pd; | |
| 869 | + | |
| 870 | + tEnvPD_free(&p->env); | |
| 871 | + tSNAC_free(&p->snac); | |
| 872 | + leaf_free(p); | |
| 873 | +} | |
| 874 | + | |
| 875 | +void tPeriodDetection_initToPool (tPeriodDetection* const pd, float* in, float* out, int bufSize, int frameSize, tMempool* const mp) | |
| 876 | +{ | |
| 877 | + _tMempool* m = *mp; | |
| 878 | + _tPeriodDetection* p = *pd = (_tPeriodDetection*) mpool_alloc(sizeof(_tPeriodDetection), m->pool); | |
| 879 | + | |
| 880 | + p->inBuffer = in; | |
| 881 | + p->outBuffer = out; | |
| 882 | + p->bufSize = bufSize; | |
| 883 | + p->frameSize = frameSize; | |
| 884 | + p->framesPerBuffer = p->bufSize / p->frameSize; | |
| 885 | + p->curBlock = 1; | |
| 886 | + p->lastBlock = 0; | |
| 887 | + p->index = 0; | |
| 888 | + | |
| 889 | + p->hopSize = DEFHOPSIZE; | |
| 890 | + p->windowSize = DEFWINDOWSIZE; | |
| 891 | + p->fba = FBA; | |
| 892 | + | |
| 893 | + tEnvPD_initToPool(&p->env, p->windowSize, p->hopSize, p->frameSize, mp); | |
| 894 | + | |
| 895 | + tSNAC_initToPool(&p->snac, DEFOVERLAP, mp); | |
| 896 | + | |
| 897 | + p->timeConstant = DEFTIMECONSTANT; | |
| 898 | + p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant); | |
| 899 | +} | |
| 900 | + | |
| 901 | +void tPeriodDetection_freeFromPool (tPeriodDetection* const pd, tMempool* const mp) | |
| 902 | +{ | |
| 903 | + _tMempool* m = *mp; | |
| 904 | + _tPeriodDetection* p = *pd; | |
| 905 | + | |
| 906 | + tEnvPD_freeFromPool(&p->env, mp); | |
| 907 | + tSNAC_freeFromPool(&p->snac, mp); | |
| 908 | + mpool_free(p, m->pool); | |
| 909 | +} | |
| 910 | + | |
| 911 | +float tPeriodDetection_findPeriod (tPeriodDetection* pd, float sample) | |
| 912 | +{ | |
| 913 | + _tPeriodDetection* p = *pd; | |
| 914 | + | |
| 915 | + int i, iLast; | |
| 916 | + | |
| 917 | + i = (p->curBlock*p->frameSize); | |
| 918 | + iLast = (p->lastBlock*p->frameSize)+p->index; | |
| 919 | + | |
| 920 | + p->i = i; | |
| 921 | + p->iLast = iLast; | |
| 922 | + | |
| 923 | + p->inBuffer[i+p->index] = sample; | |
| 924 | + | |
| 925 | + p->index++; | |
| 926 | + p->indexstore = p->index; | |
| 927 | + if (p->index >= p->frameSize) | |
| 928 | + { | |
| 929 | + p->index = 0; | |
| 930 | + | |
| 931 | + tEnvPD_processBlock(&p->env, &(p->inBuffer[i])); | |
| 932 | + | |
| 933 | + tSNAC_ioSamples(&p->snac, &(p->inBuffer[i]), &(p->outBuffer[i]), p->frameSize); | |
| 934 | + p->period = tSNAC_getPeriod(&p->snac); | |
| 935 | + | |
| 936 | + p->curBlock++; | |
| 937 | + if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0; | |
| 938 | + p->lastBlock++; | |
| 939 | + if (p->lastBlock >= p->framesPerBuffer) p->lastBlock = 0; | |
| 799 | 940 | } |
| 941 | + | |
| 942 | + // changed from period to p->period | |
| 943 | + return p->period; | |
| 944 | +} | |
| 945 | + | |
| 946 | +void tPeriodDetection_setHopSize(tPeriodDetection* pd, int hs) | |
| 947 | +{ | |
| 948 | + _tPeriodDetection* p = *pd; | |
| 949 | + p->hopSize = hs; | |
| 950 | +} | |
| 951 | + | |
| 952 | +void tPeriodDetection_setWindowSize(tPeriodDetection* pd, int ws) | |
| 953 | +{ | |
| 954 | + _tPeriodDetection* p = *pd; | |
| 955 | + p->windowSize = ws; | |
| 800 | 956 | } |
| 801 | 957 | |
| @@ -19,7 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #endif |
| 20 | 20 | |
| 21 | 21 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Delay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // |
| 22 | −void tDelay_init (tDelay* const dl, uint32_t delay, uint32_t maxDelay) | |
| 22 | +void tDelay_init (tDelay* const dl, uint32_t delay, uint32_t maxDelay) | |
| 23 | 23 | { |
| 24 | 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 | 48 | leaf_free(d); |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | +void tDelay_initToPool (tDelay* const dl, uint32_t delay, uint32_t maxDelay, tMempool* const mp) | |
| 52 | +{ | |
| 53 | + _tMempool* m = *mp; | |
| 54 | + _tDelay* d = *dl = (_tDelay*) mpool_alloc(sizeof(_tDelay), m->pool); | |
| 55 | + | |
| 56 | + d->maxDelay = maxDelay; | |
| 57 | + | |
| 58 | + d->delay = delay; | |
| 59 | + | |
| 60 | + d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m->pool); | |
| 61 | + | |
| 62 | + d->inPoint = 0; | |
| 63 | + d->outPoint = 0; | |
| 64 | + | |
| 65 | + d->lastIn = 0.0f; | |
| 66 | + d->lastOut = 0.0f; | |
| 67 | + | |
| 68 | + d->gain = 1.0f; | |
| 69 | + | |
| 70 | + tDelay_setDelay(dl, d->delay); | |
| 71 | +} | |
| 72 | + | |
| 73 | +void tDelay_freeFromPool (tDelay* const dl, tMempool* const mp) | |
| 74 | +{ | |
| 75 | + _tMempool* m = *mp; | |
| 76 | + _tDelay* d = *dl; | |
| 77 | + | |
| 78 | + mpool_free(d->buff, m->pool); | |
| 79 | + mpool_free(d, m->pool); | |
| 80 | +} | |
| 81 | + | |
| 51 | 82 | float tDelay_tick (tDelay* const dl, float input) |
| 52 | 83 | { |
| 53 | 84 | _tDelay* d = *dl; |
| @@ -177,6 +208,51 @@ void tLinearDelay_free(tLinearDelay* const dl) · 123 unmodified lines | ||
| 177 | 208 | leaf_free(d); |
| 178 | 209 | } |
| 179 | 210 | |
| 211 | +void tLinearDelay_initToPool (tLinearDelay* const dl, float delay, uint32_t maxDelay, tMempool* const mp) | |
| 212 | +{ | |
| 213 | + _tMempool* m = *mp; | |
| 214 | + _tLinearDelay* d = *dl = (_tLinearDelay*) mpool_alloc(sizeof(_tLinearDelay), m->pool); | |
| 215 | + | |
| 216 | + d->maxDelay = maxDelay; | |
| 217 | + | |
| 218 | + if (delay > maxDelay) d->delay = maxDelay; | |
| 219 | + else if (delay < 0.0f) d->delay = 0.0f; | |
| 220 | + else d->delay = delay; | |
| 221 | + | |
| 222 | + d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m->pool); | |
| 223 | + | |
| 224 | + d->gain = 1.0f; | |
| 225 | + | |
| 226 | + d->lastIn = 0.0f; | |
| 227 | + d->lastOut = 0.0f; | |
| 228 | + | |
| 229 | + d->inPoint = 0; | |
| 230 | + d->outPoint = 0; | |
| 231 | + | |
| 232 | + tLinearDelay_setDelay(dl, d->delay); | |
| 233 | +} | |
| 234 | + | |
| 235 | +void tLinearDelay_freeFromPool(tLinearDelay* const dl, tMempool* const mp) | |
| 236 | +{ | |
| 237 | + _tMempool* m = *mp; | |
| 238 | + _tLinearDelay* d = *dl; | |
| 239 | + | |
| 240 | + mpool_free(d->buff, m->pool); | |
| 241 | + mpool_free(d, m->pool); | |
| 242 | +} | |
| 243 | + | |
| 244 | + | |
| 245 | +void tLinearDelay_clear(tLinearDelay* const dl) | |
| 246 | +{ | |
| 247 | + _tLinearDelay* d = *dl; | |
| 248 | + for (int i = 0; i < d->maxDelay; i++) | |
| 249 | + { | |
| 250 | + d->buff[i] = 0; | |
| 251 | + } | |
| 252 | + | |
| 253 | + | |
| 254 | +} | |
| 255 | + | |
| 180 | 256 | float tLinearDelay_tick (tLinearDelay* const dl, float input) |
| 181 | 257 | { |
| 182 | 258 | _tLinearDelay* d = *dl; |
| @@ -186,15 +262,15 @@ float tLinearDelay_tick (tLinearDelay* const dl, float input) · 3 unmodified lines | ||
| 186 | 262 | // Increment input pointer modulo length. |
| 187 | 263 | if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0; |
| 188 | 264 | |
| 189 | − | |
| 190 | 265 | uint32_t idx = (uint32_t) d->outPoint; |
| 191 | − | |
| 192 | − d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay], | |
| 193 | − d->buff[idx], | |
| 194 | − d->buff[(idx + 1) % d->maxDelay], | |
| 195 | − d->buff[(idx + 2) % d->maxDelay], | |
| 196 | − d->alpha); | |
| 197 | − | |
| 266 | + // First 1/2 of interpolation | |
| 267 | + d->lastOut = d->buff[idx] * d->omAlpha; | |
| 268 | + // Second 1/2 of interpolation | |
| 269 | + if ((idx + 1) < d->maxDelay) | |
| 270 | + d->lastOut += d->buff[idx+1] * d->alpha; | |
| 271 | + else | |
| 272 | + d->lastOut += d->buff[0] * d->alpha; | |
| 273 | + | |
| 198 | 274 | // Increment output pointer modulo length |
| 199 | 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 | 292 | _tLinearDelay* d = *dl; |
| 217 | 293 | |
| 218 | − uint32_t idx = (uint32_t) d->outPoint; | |
| 219 | − | |
| 220 | − d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay], | |
| 221 | − d->buff[idx], | |
| 222 | − d->buff[(idx + 1) % d->maxDelay], | |
| 223 | − d->buff[(idx + 2) % d->maxDelay], | |
| 224 | − d->alpha); | |
| 294 | + uint32_t idx = (uint32_t) d->outPoint; | |
| 295 | + // First 1/2 of interpolation | |
| 296 | + d->lastOut = d->buff[idx] * d->omAlpha; | |
| 297 | + // Second 1/2 of interpolation | |
| 298 | + if ((idx + 1) < d->maxDelay) | |
| 299 | + d->lastOut += d->buff[idx+1] * d->alpha; | |
| 300 | + else | |
| 301 | + d->lastOut += d->buff[0] * d->alpha; | |
| 225 | 302 | |
| 226 | − // Increment output pointer modulo length | |
| 227 | − if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0; | |
| 303 | + // Increment output pointer modulo length | |
| 304 | + if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0; | |
| 228 | 305 | |
| 229 | − return d->lastOut; | |
| 306 | + return d->lastOut; | |
| 230 | 307 | } |
| 231 | 308 | |
| 232 | 309 | int tLinearDelay_setDelay (tLinearDelay* const dl, float delay) |
| @@ -250,38 +327,22 @@ int tLinearDelay_setDelay (tLinearDelay* const dl, float delay) · 17 unmodified lines | ||
| 250 | 327 | return 0; |
| 251 | 328 | } |
| 252 | 329 | |
| 253 | −float tLinearDelay_tapOut (tLinearDelay* const dl, float tapDelay) | |
| 330 | +float tLinearDelay_tapOut (tLinearDelay* const dl, uint32_t tapDelay) | |
| 254 | 331 | { |
| 255 | 332 | _tLinearDelay* d = *dl; |
| 256 | 333 | |
| 257 | − float tap = (float) d->inPoint - tapDelay - 1.f; | |
| 258 | − | |
| 334 | + uint32_t tap = d->inPoint - tapDelay - 1; | |
| 259 | 335 | // Check for wraparound. |
| 260 | − while ( tap < 0.f ) tap += (float)d->maxDelay; | |
| 261 | − | |
| 262 | − float alpha = tap - (int)tap; | |
| 263 | − float omAlpha = 1.f - alpha; | |
| 264 | − | |
| 265 | − int ptx = (int) tap; | |
| 266 | − | |
| 267 | − // First 1/2 of interpolation | |
| 268 | − float samp = d->buff[ptx] * omAlpha; | |
| 269 | − | |
| 270 | − // Second 1/2 of interpolation | |
| 271 | − if ((ptx + 1) < d->maxDelay) | |
| 272 | − samp += d->buff[ptx+1] * d->alpha; | |
| 273 | − else | |
| 274 | − samp += d->buff[0] * d->alpha; | |
| 275 | − | |
| 276 | − return samp; | |
| 336 | + while ( tap < 0 ) tap += d->maxDelay; | |
| 277 | 337 | |
| 338 | + return d->buff[tap]; | |
| 278 | 339 | } |
| 279 | 340 | |
| 280 | 341 | void tLinearDelay_tapIn (tLinearDelay* const dl, float value, uint32_t tapDelay) |
| 281 | 342 | { |
| 282 | 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 | 347 | // Check for wraparound. |
| 287 | 348 | while ( tap < 0 ) tap += d->maxDelay; |
| @@ -332,6 +393,234 @@ float tLinearDelay_getGain (tLinearDelay* const dl) · 44 unmodified lines | ||
| 332 | 393 | return d->gain; |
| 333 | 394 | } |
| 334 | 395 | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | +/// Hermite Interpolated Delay | |
| 401 | +// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ LinearDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 402 | +void tHermiteDelay_init (tHermiteDelay* const dl, float delay, uint32_t maxDelay) | |
| 403 | +{ | |
| 404 | + _tHermiteDelay* d = *dl = (_tHermiteDelay*) leaf_alloc(sizeof(_tHermiteDelay)); | |
| 405 | + | |
| 406 | + d->maxDelay = maxDelay; | |
| 407 | + | |
| 408 | + if (delay > maxDelay) d->delay = maxDelay; | |
| 409 | + else if (delay < 0.0f) d->delay = 0.0f; | |
| 410 | + else d->delay = delay; | |
| 411 | + | |
| 412 | + d->buff = (float*) leaf_alloc(sizeof(float) * maxDelay); | |
| 413 | + | |
| 414 | + d->gain = 1.0f; | |
| 415 | + | |
| 416 | + d->lastIn = 0.0f; | |
| 417 | + d->lastOut = 0.0f; | |
| 418 | + | |
| 419 | + d->inPoint = 0; | |
| 420 | + d->outPoint = 0; | |
| 421 | + | |
| 422 | + tHermiteDelay_setDelay(dl, d->delay); | |
| 423 | +} | |
| 424 | + | |
| 425 | +void tHermiteDelay_free(tHermiteDelay* const dl) | |
| 426 | +{ | |
| 427 | + _tHermiteDelay* d = *dl; | |
| 428 | + | |
| 429 | + leaf_free(d->buff); | |
| 430 | + leaf_free(d); | |
| 431 | +} | |
| 432 | + | |
| 433 | +void tHermiteDelay_initToPool (tHermiteDelay* const dl, float delay, uint32_t maxDelay, tMempool* const mp) | |
| 434 | +{ | |
| 435 | + _tMempool* m = *mp; | |
| 436 | + _tHermiteDelay* d = *dl = (_tHermiteDelay*) mpool_alloc(sizeof(_tHermiteDelay), m->pool); | |
| 437 | + | |
| 438 | + d->maxDelay = maxDelay; | |
| 439 | + | |
| 440 | + if (delay > maxDelay) d->delay = maxDelay; | |
| 441 | + else if (delay < 0.0f) d->delay = 0.0f; | |
| 442 | + else d->delay = delay; | |
| 443 | + | |
| 444 | + d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m->pool); | |
| 445 | + | |
| 446 | + d->gain = 1.0f; | |
| 447 | + | |
| 448 | + d->lastIn = 0.0f; | |
| 449 | + d->lastOut = 0.0f; | |
| 450 | + | |
| 451 | + d->inPoint = 0; | |
| 452 | + d->outPoint = 0; | |
| 453 | + | |
| 454 | + tHermiteDelay_setDelay(dl, d->delay); | |
| 455 | +} | |
| 456 | + | |
| 457 | +void tHermiteDelay_freeFromPool(tHermiteDelay* const dl, tMempool* const mp) | |
| 458 | +{ | |
| 459 | + _tMempool* m = *mp; | |
| 460 | + _tHermiteDelay* d = *dl; | |
| 461 | + | |
| 462 | + mpool_free(d->buff, m->pool); | |
| 463 | + mpool_free(d, m->pool); | |
| 464 | +} | |
| 465 | + | |
| 466 | + | |
| 467 | +void tHermiteDelay_clear(tHermiteDelay* const dl) | |
| 468 | +{ | |
| 469 | + _tHermiteDelay* d = *dl; | |
| 470 | + for (int i = 0; i < d->maxDelay; i++) | |
| 471 | + { | |
| 472 | + d->buff[i] = 0; | |
| 473 | + } | |
| 474 | + | |
| 475 | + | |
| 476 | +} | |
| 477 | + | |
| 478 | +float tHermiteDelay_tick (tHermiteDelay* const dl, float input) | |
| 479 | +{ | |
| 480 | + _tHermiteDelay* d = *dl; | |
| 481 | + | |
| 482 | + d->buff[d->inPoint] = input * d->gain; | |
| 483 | + | |
| 484 | + // Increment input pointer modulo length. | |
| 485 | + if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0; | |
| 486 | + | |
| 487 | + | |
| 488 | + uint32_t idx = (uint32_t) d->outPoint; | |
| 489 | + d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay], | |
| 490 | + d->buff[idx], | |
| 491 | + d->buff[(idx + 1) % d->maxDelay], | |
| 492 | + d->buff[(idx + 2) % d->maxDelay], | |
| 493 | + d->alpha); | |
| 494 | + | |
| 495 | + // Increment output pointer modulo length | |
| 496 | + if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0; | |
| 497 | + | |
| 498 | + return d->lastOut; | |
| 499 | +} | |
| 500 | + | |
| 501 | +void tHermiteDelay_tickIn (tHermiteDelay* const dl, float input) | |
| 502 | +{ | |
| 503 | + _tHermiteDelay* d = *dl; | |
| 504 | + | |
| 505 | + d->buff[d->inPoint] = input * d->gain; | |
| 506 | + | |
| 507 | + // Increment input pointer modulo length. | |
| 508 | + if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0; | |
| 509 | +} | |
| 510 | + | |
| 511 | +float tHermiteDelay_tickOut (tHermiteDelay* const dl) | |
| 512 | +{ | |
| 513 | + _tHermiteDelay* d = *dl; | |
| 514 | + | |
| 515 | + uint32_t idx = (uint32_t) d->outPoint; | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay], | |
| 520 | + d->buff[idx], | |
| 521 | + d->buff[(idx + 1) % d->maxDelay], | |
| 522 | + d->buff[(idx + 2) % d->maxDelay], | |
| 523 | + d->alpha); | |
| 524 | + | |
| 525 | + // Increment output pointer modulo length | |
| 526 | + if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0; | |
| 527 | + | |
| 528 | + return d->lastOut; | |
| 529 | +} | |
| 530 | + | |
| 531 | +int tHermiteDelay_setDelay (tHermiteDelay* const dl, float delay) | |
| 532 | +{ | |
| 533 | + _tHermiteDelay* d = *dl; | |
| 534 | + | |
| 535 | + d->delay = LEAF_clip(0.0f, delay, d->maxDelay); | |
| 536 | + | |
| 537 | + float outPointer = d->inPoint - d->delay; | |
| 538 | + | |
| 539 | + while ( outPointer < 0 ) | |
| 540 | + outPointer += d->maxDelay; // modulo maximum length | |
| 541 | + | |
| 542 | + d->outPoint = (uint32_t) outPointer; // integer part | |
| 543 | + | |
| 544 | + d->alpha = outPointer - d->outPoint; // fractional part | |
| 545 | + d->omAlpha = 1.0f - d->alpha; | |
| 546 | + | |
| 547 | + if ( d->outPoint == d->maxDelay ) d->outPoint = 0; | |
| 548 | + | |
| 549 | + return 0; | |
| 550 | +} | |
| 551 | + | |
| 552 | +float tHermiteDelay_tapOut (tHermiteDelay* const dl, uint32_t tapDelay) | |
| 553 | +{ | |
| 554 | + _tHermiteDelay* d = *dl; | |
| 555 | + | |
| 556 | + uint32_t tap = d->inPoint - tapDelay - 1; | |
| 557 | + | |
| 558 | + // Check for wraparound. | |
| 559 | + while ( tap < 0 ) tap += d->maxDelay; | |
| 560 | + | |
| 561 | + return d->buff[tap]; | |
| 562 | + | |
| 563 | +} | |
| 564 | + | |
| 565 | +void tHermiteDelay_tapIn (tHermiteDelay* const dl, float value, uint32_t tapDelay) | |
| 566 | +{ | |
| 567 | + _tHermiteDelay* d = *dl; | |
| 568 | + | |
| 569 | + int32_t tap = d->inPoint - tapDelay - 1; | |
| 570 | + | |
| 571 | + // Check for wraparound. | |
| 572 | + while ( tap < 0 ) tap += d->maxDelay; | |
| 573 | + | |
| 574 | + d->buff[tap] = value; | |
| 575 | +} | |
| 576 | + | |
| 577 | +float tHermiteDelay_addTo (tHermiteDelay* const dl, float value, uint32_t tapDelay) | |
| 578 | +{ | |
| 579 | + _tHermiteDelay* d = *dl; | |
| 580 | + | |
| 581 | + int32_t tap = d->inPoint - tapDelay - 1; | |
| 582 | + | |
| 583 | + // Check for wraparound. | |
| 584 | + while ( tap < 0 ) tap += d->maxDelay; | |
| 585 | + | |
| 586 | + return (d->buff[tap] += value); | |
| 587 | +} | |
| 588 | + | |
| 589 | +float tHermiteDelay_getDelay (tHermiteDelay* const dl) | |
| 590 | +{ | |
| 591 | + _tHermiteDelay* d = *dl; | |
| 592 | + return d->delay; | |
| 593 | +} | |
| 594 | + | |
| 595 | +float tHermiteDelay_getLastOut (tHermiteDelay* const dl) | |
| 596 | +{ | |
| 597 | + _tHermiteDelay* d = *dl; | |
| 598 | + return d->lastOut; | |
| 599 | +} | |
| 600 | + | |
| 601 | +float tHermiteDelay_getLastIn (tHermiteDelay* const dl) | |
| 602 | +{ | |
| 603 | + _tHermiteDelay* d = *dl; | |
| 604 | + return d->lastIn; | |
| 605 | +} | |
| 606 | + | |
| 607 | +void tHermiteDelay_setGain (tHermiteDelay* const dl, float gain) | |
| 608 | +{ | |
| 609 | + _tHermiteDelay* d = *dl; | |
| 610 | + if (gain < 0.0f) d->gain = 0.0f; | |
| 611 | + else d->gain = gain; | |
| 612 | +} | |
| 613 | + | |
| 614 | +float tHermiteDelay_getGain (tHermiteDelay* const dl) | |
| 615 | +{ | |
| 616 | + _tHermiteDelay* d = *dl; | |
| 617 | + return d->gain; | |
| 618 | +} | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 335 | 624 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ AllpassDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // |
| 336 | 625 | void 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 | 655 | leaf_free(d); |
| 367 | 656 | } |
| 368 | 657 | |
| 658 | +void tAllpassDelay_initToPool (tAllpassDelay* const dl, float delay, uint32_t maxDelay, tMempool* const mp) | |
| 659 | +{ | |
| 660 | + _tMempool* m = *mp; | |
| 661 | + _tAllpassDelay* d = *dl = (_tAllpassDelay*) mpool_alloc(sizeof(_tAllpassDelay), m->pool); | |
| 662 | + | |
| 663 | + d->maxDelay = maxDelay; | |
| 664 | + | |
| 665 | + if (delay > maxDelay) d->delay = maxDelay; | |
| 666 | + else if (delay < 0.0f) d->delay = 0.0f; | |
| 667 | + else d->delay = delay; | |
| 668 | + | |
| 669 | + d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m->pool); | |
| 670 | + | |
| 671 | + d->gain = 1.0f; | |
| 672 | + | |
| 673 | + d->lastIn = 0.0f; | |
| 674 | + d->lastOut = 0.0f; | |
| 675 | + | |
| 676 | + d->inPoint = 0; | |
| 677 | + d->outPoint = 0; | |
| 678 | + | |
| 679 | + tAllpassDelay_setDelay(dl, d->delay); | |
| 680 | + | |
| 681 | + d->apInput = 0.0f; | |
| 682 | +} | |
| 683 | + | |
| 684 | +void tAllpassDelay_freeFromPool(tAllpassDelay* const dl, tMempool* const mp) | |
| 685 | +{ | |
| 686 | + _tMempool* m = *mp; | |
| 687 | + _tAllpassDelay* d = *dl; | |
| 688 | + | |
| 689 | + mpool_free(d->buff, m->pool); | |
| 690 | + mpool_free(d, m->pool); | |
| 691 | +} | |
| 692 | + | |
| 369 | 693 | float tAllpassDelay_tick (tAllpassDelay* const dl, float input) |
| 370 | 694 | { |
| 371 | 695 | _tAllpassDelay* d = *dl; |
| @@ -520,6 +844,36 @@ void tTapeDelay_free(tTapeDelay* const dl) · 148 unmodified lines | ||
| 520 | 844 | leaf_free(d); |
| 521 | 845 | } |
| 522 | 846 | |
| 847 | +void tTapeDelay_initToPool (tTapeDelay* const dl, float delay, uint32_t maxDelay, tMempool* const mp) | |
| 848 | +{ | |
| 849 | + _tMempool* m = *mp; | |
| 850 | + _tTapeDelay* d = *dl = (_tTapeDelay*) mpool_alloc(sizeof(_tTapeDelay), m->pool); | |
| 851 | + | |
| 852 | + d->maxDelay = maxDelay; | |
| 853 | + | |
| 854 | + d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m->pool); | |
| 855 | + | |
| 856 | + d->gain = 1.0f; | |
| 857 | + | |
| 858 | + d->lastIn = 0.0f; | |
| 859 | + d->lastOut = 0.0f; | |
| 860 | + | |
| 861 | + d->idx = 0.0f; | |
| 862 | + d->inc = 1.0f; | |
| 863 | + d->inPoint = 0; | |
| 864 | + | |
| 865 | + tTapeDelay_setDelay(dl, delay); | |
| 866 | +} | |
| 867 | + | |
| 868 | +void tTapeDelay_freeFromPool(tTapeDelay* const dl, tMempool* const mp) | |
| 869 | +{ | |
| 870 | + _tMempool* m = *mp; | |
| 871 | + _tTapeDelay* d = *dl; | |
| 872 | + | |
| 873 | + mpool_free(d->buff, m->pool); | |
| 874 | + mpool_free(d, m->pool); | |
| 875 | +} | |
| 876 | + | |
| 523 | 877 | //#define SMOOTH_FACTOR 10.f |
| 524 | 878 | |
| 525 | 879 | float tTapeDelay_tick (tTapeDelay* const dl, float input) |
| @@ -534,7 +888,7 @@ float tTapeDelay_tick (tTapeDelay* const dl, float input) · 8 unmodified lines | ||
| 534 | 888 | int idx = (int) d->idx; |
| 535 | 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 | 892 | d->buff[idx], |
| 539 | 893 | d->buff[(idx + 1) % d->maxDelay], |
| 540 | 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 | 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 | 943 | d->buff[idx], |
| 590 | 944 | d->buff[(idx + 1) % d->maxDelay], |
| 591 | 945 | d->buff[(idx + 2) % d->maxDelay], |
| @@ -17,232 +17,58 @@ · 16 unmodified lines | ||
| 17 | 17 | #include "../Inc/leaf-tables.h" |
| 18 | 18 | |
| 19 | 19 | //testing |
| 20 | −#include "gpio.h" | |
| 20 | +//#include "gpio.h" | |
| 21 | 21 | |
| 22 | 22 | #endif |
| 23 | 23 | |
| 24 | 24 | //============================================================================================================ |
| 25 | −// WAVEFOLDER | |
| 25 | +// Sample-Rate reducer | |
| 26 | 26 | //============================================================================================================ |
| 27 | 27 | |
| 28 | 28 | |
| 29 | −//from the paper: Virtual Analog Model of the Lockhart Wavefolder | |
| 30 | −//by Fabián Esqueda, Henri Pöntynen, Julian D. Parker and Stefan Bilbao | |
| 31 | − | |
| 32 | −void tLockhartWavefolder_init(tLockhartWavefolder* const wf) | |
| 33 | −{ | |
| 34 | − _tLockhartWavefolder* w = *wf = (_tLockhartWavefolder*) leaf_alloc(sizeof(_tLockhartWavefolder)); | |
| 35 | − | |
| 36 | − w->Ln1 = 0.0; | |
| 37 | − w->Fn1 = 0.0; | |
| 38 | − w->xn1 = 0.0f; | |
| 39 | − | |
| 40 | − w->RL = 7.5e3; | |
| 41 | − w->R = 15e3; | |
| 42 | − w->VT = 26e-3; | |
| 43 | − w->Is = 10e-16; | |
| 44 | − | |
| 45 | − w->a = 2.0*w->RL/w->R; | |
| 46 | − w->b = (w->R+2.0*w->RL)/(w->VT*w->R); | |
| 47 | − w->d = (w->RL*w->Is)/w->VT; | |
| 48 | − w->half_a = 0.5 * w->a; | |
| 49 | − w->longthing = (0.5*w->VT/w->b); | |
| 50 | − | |
| 51 | − | |
| 52 | − // Antialiasing error threshold | |
| 53 | − w->thresh = 10e-10; | |
| 54 | −} | |
| 55 | − | |
| 56 | −void tLockhartWavefolder_free(tLockhartWavefolder* const wf) | |
| 57 | −{ | |
| 58 | − _tLockhartWavefolder* w = *wf; | |
| 59 | − | |
| 60 | − leaf_free(w); | |
| 61 | −} | |
| 62 | − | |
| 63 | −double tLockhartWavefolderLambert(double x, double ln) | |
| 64 | −{ | |
| 65 | − double thresh, w, expw, p, r, s, err; | |
| 66 | − // Error threshold | |
| 67 | − thresh = 10e-12; | |
| 68 | − // Initial guess (use previous value) | |
| 69 | − w = ln; | |
| 70 | − | |
| 71 | − // Haley's method (Sec. 4.2 of the paper) | |
| 72 | − for(int i=0; i<1000; i+=1) { | |
| 73 | − | |
| 74 | − expw = exp(w); | |
| 75 | − | |
| 76 | − p = w*expw - x; | |
| 77 | − r = (w+1.0)*expw; | |
| 78 | − s = (w+2.0)/(2.0*(w+1.0)); | |
| 79 | − err = (p/(r-(p*s))); | |
| 80 | − | |
| 81 | − if (fabs(err)<thresh) { | |
| 82 | − | |
| 83 | − break; | |
| 84 | − } | |
| 85 | − | |
| 86 | − w = w - err; | |
| 87 | − if (i == 999) | |
| 88 | − { | |
| 89 | − //HAL_GPIO_WritePin(GPIOG, GPIO_PIN_7, GPIO_PIN_SET); | |
| 90 | − } | |
| 91 | − | |
| 92 | − } | |
| 93 | − return w; | |
| 94 | −} | |
| 95 | − | |
| 96 | −float tLockhartWavefolder_tick(tLockhartWavefolder* const wf, float samp) | |
| 29 | +void tSampleReducer_init(tSampleReducer* const sr) | |
| 97 | 30 | { |
| 98 | − _tLockhartWavefolder* w = *wf; | |
| 99 | − | |
| 100 | − float out = 0.0f; | |
| 101 | − | |
| 102 | − // Compute Antiderivative | |
| 103 | − int l = (samp > 0.0f) - (samp < 0.0f); | |
| 104 | − double u = w->d*exp(l*w->b*samp); | |
| 105 | − double Ln = tLockhartWavefolderLambert(u,w->Ln1); | |
| 106 | − double Fn = w->longthing*(Ln*(Ln + 2.0)) - w->half_a*samp*samp; | |
| 107 | − | |
| 108 | − // Check for ill-conditioning | |
| 109 | − if (fabs(samp-w->xn1)<w->thresh) { | |
| 110 | − | |
| 111 | − // Compute Averaged Wavefolder Output | |
| 112 | − float xn = 0.5f*(samp+w->xn1); | |
| 113 | − u = w->d*exp(l*w->b*xn); | |
| 114 | − Ln = tLockhartWavefolderLambert(u,w->Ln1); | |
| 115 | − out = (float) (l*w->VT*Ln - w->a*xn); | |
| 116 | − | |
| 117 | − } | |
| 118 | − else { | |
| 119 | − | |
| 120 | − // Apply AA Form | |
| 121 | − out = (float) ((Fn-w->Fn1)/(samp-w->xn1)); | |
| 122 | − } | |
| 123 | − | |
| 124 | − // Update States | |
| 125 | − w->Ln1 = Ln; | |
| 126 | − w->Fn1 = Fn; | |
| 127 | − w->xn1 = samp; | |
| 31 | + _tSampleReducer* s = *sr = (_tSampleReducer*) leaf_alloc(sizeof(_tSampleReducer)); | |
| 128 | 32 | |
| 129 | − return out; | |
| 33 | + s->invRatio = 1.0f; | |
| 34 | + s->hold = 0.0f; | |
| 35 | + s->count = 0; | |
| 130 | 36 | } |
| 131 | 37 | |
| 132 | −//============================================================================================================ | |
| 133 | −// CRUSHER | |
| 134 | −//============================================================================================================ | |
| 135 | −#define SCALAR 5000.f | |
| 136 | − | |
| 137 | −void tCrusher_init (tCrusher* const cr) | |
| 38 | +void tSampleReducer_free (tSampleReducer* const sr) | |
| 138 | 39 | { |
| 139 | − _tCrusher* c = *cr = (_tCrusher*) leaf_alloc(sizeof(_tCrusher)); | |
| 40 | + _tSampleReducer* s = *sr; | |
| 140 | 41 | |
| 141 | − c->op = 4; | |
| 142 | − c->div = SCALAR; | |
| 143 | − c->rnd = 0.25f; | |
| 144 | − c->srr = 0.25f; | |
| 145 | − tSampleReducer_init(&c->sReducer); | |
| 146 | − c->gain = (c->div / SCALAR) * 0.7f + 0.3f; | |
| 147 | −} | |
| 148 | − | |
| 149 | −void tCrusher_free (tCrusher* const cr) | |
| 150 | −{ | |
| 151 | − _tCrusher* c = *cr; | |
| 152 | − tSampleReducer_free(&c->sReducer); | |
| 153 | − leaf_free(c); | |
| 42 | + leaf_free(s); | |
| 154 | 43 | } |
| 155 | 44 | |
| 156 | −float tCrusher_tick (tCrusher* const cr, float input) | |
| 45 | +void tSampleReducer_initToPool (tSampleReducer* const sr, tMempool* const mp) | |
| 157 | 46 | { |
| 158 | − _tCrusher* c = *cr; | |
| 159 | − | |
| 160 | − float sample = input; | |
| 161 | − | |
| 162 | − sample *= SCALAR; // SCALAR is 5000 by default | |
| 163 | − | |
| 164 | − sample = (int32_t) sample; | |
| 165 | − | |
| 166 | − sample /= c->div; | |
| 167 | − | |
| 168 | − sample = LEAF_bitwise_xor(sample, c->op << 23); | |
| 169 | − | |
| 170 | − sample = LEAF_clip(-1.f, sample, 1.f); | |
| 171 | − | |
| 172 | − sample = LEAF_round(sample, c->rnd); | |
| 47 | + _tMempool* m = *mp; | |
| 48 | + _tSampleReducer* s = *sr = (_tSampleReducer*) mpool_alloc(sizeof(_tSampleReducer), m->pool); | |
| 173 | 49 | |
| 174 | − sample = tSampleReducer_tick(&c->sReducer, sample); | |
| 175 | − | |
| 176 | − return sample * c->gain; | |
| 177 | − | |
| 178 | −} | |
| 179 | − | |
| 180 | −void tCrusher_setOperation (tCrusher* const cr, float op) | |
| 181 | −{ | |
| 182 | − _tCrusher* c = *cr; | |
| 183 | − c->op = (uint32_t) (op * 8.0f); | |
| 50 | + s->invRatio = 1.0f; | |
| 51 | + s->hold = 0.0f; | |
| 52 | + s->count = 0; | |
| 184 | 53 | } |
| 185 | 54 | |
| 186 | −// 0.0 - 1.0 | |
| 187 | −void tCrusher_setQuality (tCrusher* const cr, float val) | |
| 55 | +void tSampleReducer_freeFromPool (tSampleReducer* const sr, tMempool* const mp) | |
| 188 | 56 | { |
| 189 | − _tCrusher* c = *cr; | |
| 190 | − | |
| 191 | − val = LEAF_clip(0.0f, val, 1.0f); | |
| 192 | − | |
| 193 | − c->div = 0.01f + val * SCALAR; | |
| 57 | + _tMempool* m = *mp; | |
| 58 | + _tSampleReducer* s = *sr; | |
| 194 | 59 | |
| 195 | − c->gain = (c->div / SCALAR) * 0.7f + 0.3f; | |
| 196 | −} | |
| 197 | − | |
| 198 | −// what decimal to round to | |
| 199 | −void tCrusher_setRound (tCrusher* const cr, float rnd) | |
| 200 | −{ | |
| 201 | − _tCrusher* c = *cr; | |
| 202 | − c->rnd = fabsf(rnd); | |
| 203 | −} | |
| 204 | − | |
| 205 | −void tCrusher_setSamplingRatio (tCrusher* const cr, float ratio) | |
| 206 | −{ | |
| 207 | − _tCrusher* c = *cr; | |
| 208 | − c->srr = ratio; | |
| 209 | − tSampleReducer_setRatio(&c->sReducer, ratio); | |
| 210 | − | |
| 211 | −} | |
| 212 | − | |
| 213 | −//============================================================================================================ | |
| 214 | −// Sample-Rate reducer | |
| 215 | −//============================================================================================================ | |
| 216 | − | |
| 217 | − | |
| 218 | −void tSampleReducer_init(tSampleReducer* const sr) | |
| 219 | −{ | |
| 220 | − _tSampleReducer* s = *sr = (_tSampleReducer*) leaf_alloc(sizeof(_tSampleReducer)); | |
| 221 | − | |
| 222 | − | |
| 223 | − | |
| 224 | − s->invRatio = 1.0f; | |
| 225 | − s->hold = 0.0f; | |
| 226 | − s->count = 0; | |
| 227 | − | |
| 228 | −} | |
| 229 | − | |
| 230 | −void tSampleReducer_free (tSampleReducer* const sr) | |
| 231 | −{ | |
| 232 | − _tSampleReducer* s = *sr; | |
| 233 | − | |
| 234 | − leaf_free(s); | |
| 60 | + mpool_free(s, m->pool); | |
| 235 | 61 | } |
| 236 | 62 | |
| 237 | 63 | float tSampleReducer_tick(tSampleReducer* const sr, float input) |
| 238 | 64 | { |
| 239 | − _tSampleReducer* s = *sr; | |
| 65 | + _tSampleReducer* s = *sr; | |
| 240 | 66 | if (s->count > s->invRatio) |
| 241 | 67 | { |
| 242 | 68 | s->hold = input; |
| 243 | 69 | s->count = 0; |
| 244 | 70 | } |
| 245 | − | |
| 71 | + | |
| 246 | 72 | s->count++; |
| 247 | 73 | return s->hold; |
| 248 | 74 | } |
| @@ -250,10 +76,10 @@ float tSampleReducer_tick(tSampleReducer* const sr, float input) · 1 unmodified line | ||
| 250 | 76 | |
| 251 | 77 | void tSampleReducer_setRatio(tSampleReducer* const sr, float ratio) |
| 252 | 78 | { |
| 253 | − _tSampleReducer* s = *sr; | |
| 254 | − if ((ratio <= 1.0f) && (ratio >= 0.0f)) | |
| 255 | − s->invRatio = 1.0f / ratio; | |
| 256 | − | |
| 79 | + _tSampleReducer* s = *sr; | |
| 80 | + if ((ratio <= 1.0f) && (ratio >= 0.0f)) | |
| 81 | + s->invRatio = 1.0f / ratio; | |
| 82 | + | |
| 257 | 83 | } |
| 258 | 84 | |
| 259 | 85 | //============================================================================================================ |
| @@ -288,6 +114,36 @@ void tOversampler_free(tOversampler* const osr) · 28 unmodified lines | ||
| 288 | 114 | leaf_free(os); |
| 289 | 115 | } |
| 290 | 116 | |
| 117 | +void tOversampler_initToPool (tOversampler* const osr, int ratio, oBool extraQuality, tMempool* const mp) | |
| 118 | +{ | |
| 119 | + _tMempool* m = *mp; | |
| 120 | + _tOversampler* os = *osr = (_tOversampler*) mpool_alloc(sizeof(_tOversampler), m->pool); | |
| 121 | + | |
| 122 | + uint8_t offset = 0; | |
| 123 | + if (extraQuality) offset = 6; | |
| 124 | + if (ratio == 2 || ratio == 4 || | |
| 125 | + ratio == 8 || ratio == 16 || | |
| 126 | + ratio == 32 || ratio == 64) { | |
| 127 | + os->ratio = ratio; | |
| 128 | + int idx = (int)(log2f(os->ratio))-1+offset; | |
| 129 | + os->numTaps = firNumTaps[idx]; | |
| 130 | + os->phaseLength = os->numTaps / os->ratio; | |
| 131 | + os->pCoeffs = (float*) firCoeffs[idx]; | |
| 132 | + os->upState = mpool_alloc(sizeof(float) * os->numTaps * 2, m->pool); | |
| 133 | + os->downState = mpool_alloc(sizeof(float) * os->numTaps * 2, m->pool); | |
| 134 | + } | |
| 135 | +} | |
| 136 | + | |
| 137 | +void tOversampler_freeFromPool (tOversampler* const osr, tMempool* const mp) | |
| 138 | +{ | |
| 139 | + _tMempool* m = *mp; | |
| 140 | + _tOversampler* os = *osr; | |
| 141 | + | |
| 142 | + mpool_free(os->upState, m->pool); | |
| 143 | + mpool_free(os->downState, m->pool); | |
| 144 | + mpool_free(os, m->pool); | |
| 145 | +} | |
| 146 | + | |
| 291 | 147 | float tOversampler_tick(tOversampler* const osr, float input, float (*effectTick)(float)) |
| 292 | 148 | { |
| 293 | 149 | _tOversampler* os = *osr; |
| @@ -486,3 +342,246 @@ int tOversampler_getLatency(tOversampler* const osr) · 192 unmodified lines | ||
| 486 | 342 | _tOversampler* os = *osr; |
| 487 | 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 | + | |
| 354 | +void tLockhartWavefolder_init(tLockhartWavefolder* const wf) | |
| 355 | +{ | |
| 356 | + _tLockhartWavefolder* w = *wf = (_tLockhartWavefolder*) leaf_alloc(sizeof(_tLockhartWavefolder)); | |
| 357 | + | |
| 358 | + w->Ln1 = 0.0; | |
| 359 | + w->Fn1 = 0.0; | |
| 360 | + w->xn1 = 0.0f; | |
| 361 | + | |
| 362 | + w->RL = 7.5e3; | |
| 363 | + w->R = 15e3; | |
| 364 | + w->VT = 26e-3; | |
| 365 | + w->Is = 10e-16; | |
| 366 | + | |
| 367 | + w->a = 2.0*w->RL/w->R; | |
| 368 | + w->b = (w->R+2.0*w->RL)/(w->VT*w->R); | |
| 369 | + w->d = (w->RL*w->Is)/w->VT; | |
| 370 | + w->half_a = 0.5 * w->a; | |
| 371 | + w->longthing = (0.5*w->VT/w->b); | |
| 372 | + | |
| 373 | + | |
| 374 | + // Antialiasing error threshold | |
| 375 | + w->thresh = 10e-10; | |
| 376 | +} | |
| 377 | + | |
| 378 | +void tLockhartWavefolder_free(tLockhartWavefolder* const wf) | |
| 379 | +{ | |
| 380 | + _tLockhartWavefolder* w = *wf; | |
| 381 | + | |
| 382 | + leaf_free(w); | |
| 383 | +} | |
| 384 | + | |
| 385 | +void tLockhartWavefolder_initToPool (tLockhartWavefolder* const wf, tMempool* const mp) | |
| 386 | +{ | |
| 387 | + _tMempool* m = *mp; | |
| 388 | + _tLockhartWavefolder* w = *wf = (_tLockhartWavefolder*) mpool_alloc(sizeof(_tLockhartWavefolder), m->pool); | |
| 389 | + | |
| 390 | + w->Ln1 = 0.0; | |
| 391 | + w->Fn1 = 0.0; | |
| 392 | + w->xn1 = 0.0f; | |
| 393 | + | |
| 394 | + w->RL = 7.5e3; | |
| 395 | + w->R = 15e3; | |
| 396 | + w->VT = 26e-3; | |
| 397 | + w->Is = 10e-16; | |
| 398 | + | |
| 399 | + w->a = 2.0*w->RL/w->R; | |
| 400 | + w->b = (w->R+2.0*w->RL)/(w->VT*w->R); | |
| 401 | + w->d = (w->RL*w->Is)/w->VT; | |
| 402 | + w->half_a = 0.5 * w->a; | |
| 403 | + w->longthing = (0.5*w->VT/w->b); | |
| 404 | + | |
| 405 | + | |
| 406 | + // Antialiasing error threshold | |
| 407 | + w->thresh = 10e-10; | |
| 408 | +} | |
| 409 | + | |
| 410 | +void tLockhartWavefolder_freeFromPool (tLockhartWavefolder* const wf, tMempool* const mp) | |
| 411 | +{ | |
| 412 | + _tMempool* m = *mp; | |
| 413 | + _tLockhartWavefolder* w = *wf; | |
| 414 | + | |
| 415 | + mpool_free(w, m->pool); | |
| 416 | +} | |
| 417 | + | |
| 418 | +double tLockhartWavefolderLambert(double x, double ln) | |
| 419 | +{ | |
| 420 | + double thresh, w, expw, p, r, s, err; | |
| 421 | + // Error threshold | |
| 422 | + thresh = 10e-12; | |
| 423 | + // Initial guess (use previous value) | |
| 424 | + w = ln; | |
| 425 | + | |
| 426 | + // Haley's method (Sec. 4.2 of the paper) | |
| 427 | + for(int i=0; i<1000; i+=1) { | |
| 428 | + | |
| 429 | + expw = exp(w); | |
| 430 | + | |
| 431 | + p = w*expw - x; | |
| 432 | + r = (w+1.0)*expw; | |
| 433 | + s = (w+2.0)/(2.0*(w+1.0)); | |
| 434 | + err = (p/(r-(p*s))); | |
| 435 | + | |
| 436 | + if (fabs(err)<thresh) { | |
| 437 | + | |
| 438 | + break; | |
| 439 | + } | |
| 440 | + | |
| 441 | + w = w - err; | |
| 442 | + if (i == 999) | |
| 443 | + { | |
| 444 | + //HAL_GPIO_WritePin(GPIOG, GPIO_PIN_7, GPIO_PIN_SET); | |
| 445 | + } | |
| 446 | + | |
| 447 | + } | |
| 448 | + return w; | |
| 449 | +} | |
| 450 | + | |
| 451 | +float tLockhartWavefolder_tick(tLockhartWavefolder* const wf, float samp) | |
| 452 | +{ | |
| 453 | + _tLockhartWavefolder* w = *wf; | |
| 454 | + | |
| 455 | + float out = 0.0f; | |
| 456 | + | |
| 457 | + // Compute Antiderivative | |
| 458 | + int l = (samp > 0.0f) - (samp < 0.0f); | |
| 459 | + double u = w->d*exp(l*w->b*samp); | |
| 460 | + double Ln = tLockhartWavefolderLambert(u,w->Ln1); | |
| 461 | + double Fn = w->longthing*(Ln*(Ln + 2.0)) - w->half_a*samp*samp; | |
| 462 | + | |
| 463 | + // Check for ill-conditioning | |
| 464 | + if (fabs(samp-w->xn1)<w->thresh) { | |
| 465 | + | |
| 466 | + // Compute Averaged Wavefolder Output | |
| 467 | + float xn = 0.5f*(samp+w->xn1); | |
| 468 | + u = w->d*exp(l*w->b*xn); | |
| 469 | + Ln = tLockhartWavefolderLambert(u,w->Ln1); | |
| 470 | + out = (float) (l*w->VT*Ln - w->a*xn); | |
| 471 | + | |
| 472 | + } | |
| 473 | + else { | |
| 474 | + | |
| 475 | + // Apply AA Form | |
| 476 | + out = (float) ((Fn-w->Fn1)/(samp-w->xn1)); | |
| 477 | + } | |
| 478 | + | |
| 479 | + // Update States | |
| 480 | + w->Ln1 = Ln; | |
| 481 | + w->Fn1 = Fn; | |
| 482 | + w->xn1 = samp; | |
| 483 | + | |
| 484 | + return out; | |
| 485 | +} | |
| 486 | + | |
| 487 | +//============================================================================================================ | |
| 488 | +// CRUSHER | |
| 489 | +//============================================================================================================ | |
| 490 | +#define SCALAR 5000.f | |
| 491 | + | |
| 492 | +void tCrusher_init (tCrusher* const cr) | |
| 493 | +{ | |
| 494 | + _tCrusher* c = *cr = (_tCrusher*) leaf_alloc(sizeof(_tCrusher)); | |
| 495 | + | |
| 496 | + c->op = 4; | |
| 497 | + c->div = SCALAR; | |
| 498 | + c->rnd = 0.25f; | |
| 499 | + c->srr = 0.25f; | |
| 500 | + tSampleReducer_init(&c->sReducer); | |
| 501 | + c->gain = (c->div / SCALAR) * 0.7f + 0.3f; | |
| 502 | +} | |
| 503 | + | |
| 504 | +void tCrusher_free (tCrusher* const cr) | |
| 505 | +{ | |
| 506 | + _tCrusher* c = *cr; | |
| 507 | + tSampleReducer_free(&c->sReducer); | |
| 508 | + leaf_free(c); | |
| 509 | +} | |
| 510 | + | |
| 511 | +void tCrusher_initToPool (tCrusher* const cr, tMempool* const mp) | |
| 512 | +{ | |
| 513 | + _tMempool* m = *mp; | |
| 514 | + _tCrusher* c = *cr = (_tCrusher*) mpool_alloc(sizeof(_tCrusher), m->pool); | |
| 515 | + | |
| 516 | + c->op = 4; | |
| 517 | + c->div = SCALAR; | |
| 518 | + c->rnd = 0.25f; | |
| 519 | + c->srr = 0.25f; | |
| 520 | + tSampleReducer_initToPool(&c->sReducer, mp); | |
| 521 | + c->gain = (c->div / SCALAR) * 0.7f + 0.3f; | |
| 522 | +} | |
| 523 | + | |
| 524 | +void tCrusher_freeFromPool (tCrusher* const cr, tMempool* const mp) | |
| 525 | +{ | |
| 526 | + _tMempool* m = *mp; | |
| 527 | + _tCrusher* c = *cr; | |
| 528 | + tSampleReducer_freeFromPool(&c->sReducer, mp); | |
| 529 | + mpool_free(c, m->pool); | |
| 530 | +} | |
| 531 | + | |
| 532 | +float tCrusher_tick (tCrusher* const cr, float input) | |
| 533 | +{ | |
| 534 | + _tCrusher* c = *cr; | |
| 535 | + | |
| 536 | + float sample = input; | |
| 537 | + | |
| 538 | + sample *= SCALAR; // SCALAR is 5000 by default | |
| 539 | + | |
| 540 | + sample = (int32_t) sample; | |
| 541 | + | |
| 542 | + sample /= c->div; | |
| 543 | + | |
| 544 | + sample = LEAF_bitwise_xor(sample, c->op << 23); | |
| 545 | + | |
| 546 | + sample = LEAF_clip(-1.f, sample, 1.f); | |
| 547 | + | |
| 548 | + sample = LEAF_round(sample, c->rnd); | |
| 549 | + | |
| 550 | + sample = tSampleReducer_tick(&c->sReducer, sample); | |
| 551 | + | |
| 552 | + return sample * c->gain; | |
| 553 | + | |
| 554 | +} | |
| 555 | + | |
| 556 | +void tCrusher_setOperation (tCrusher* const cr, float op) | |
| 557 | +{ | |
| 558 | + _tCrusher* c = *cr; | |
| 559 | + c->op = (uint32_t) (op * 8.0f); | |
| 560 | +} | |
| 561 | + | |
| 562 | +// 0.0 - 1.0 | |
| 563 | +void tCrusher_setQuality (tCrusher* const cr, float val) | |
| 564 | +{ | |
| 565 | + _tCrusher* c = *cr; | |
| 566 | + | |
| 567 | + val = LEAF_clip(0.0f, val, 1.0f); | |
| 568 | + | |
| 569 | + c->div = 0.01f + val * SCALAR; | |
| 570 | + | |
| 571 | + c->gain = (c->div / SCALAR) * 0.7f + 0.3f; | |
| 572 | +} | |
| 573 | + | |
| 574 | +// what decimal to round to | |
| 575 | +void tCrusher_setRound (tCrusher* const cr, float rnd) | |
| 576 | +{ | |
| 577 | + _tCrusher* c = *cr; | |
| 578 | + c->rnd = fabsf(rnd); | |
| 579 | +} | |
| 580 | + | |
| 581 | +void tCrusher_setSamplingRatio (tCrusher* const cr, float ratio) | |
| 582 | +{ | |
| 583 | + _tCrusher* c = *cr; | |
| 584 | + c->srr = ratio; | |
| 585 | + tSampleReducer_setRatio(&c->sReducer, ratio); | |
| 586 | + | |
| 587 | +} | |
| @@ -63,6 +63,30 @@ void tCompressor_free(tCompressor* const comp) · 62 unmodified lines | ||
| 63 | 63 | leaf_free(c); |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | +void tCompressor_initToPool (tCompressor* const comp, tMempool* const mp) | |
| 67 | +{ | |
| 68 | + _tMempool* m = *mp; | |
| 69 | + _tCompressor* c = *comp = (_tCompressor*) mpool_alloc(sizeof(_tCompressor), m->pool); | |
| 70 | + | |
| 71 | + c->tauAttack = 100; | |
| 72 | + c->tauRelease = 100; | |
| 73 | + | |
| 74 | + c->isActive = OFALSE; | |
| 75 | + | |
| 76 | + c->T = 0.0f; // Threshold | |
| 77 | + c->R = 0.5f; // compression Ratio | |
| 78 | + c->M = 3.0f; // decibel Width of knee transition | |
| 79 | + c->W = 1.0f; // decibel Make-up gain | |
| 80 | +} | |
| 81 | + | |
| 82 | +void tCompressor_freeFromPool(tCompressor* const comp, tMempool* const mp) | |
| 83 | +{ | |
| 84 | + _tMempool* m = *mp; | |
| 85 | + _tCompressor* c = *comp; | |
| 86 | + | |
| 87 | + mpool_free(c, m->pool); | |
| 88 | +} | |
| 89 | + | |
| 66 | 90 | float tCompressor_tick(tCompressor* const comp, float in) |
| 67 | 91 | { |
| 68 | 92 | _tCompressor* c = *comp; |
| @@ -133,6 +157,27 @@ void tFeedbackLeveler_free(tFeedbackLeveler* const fb) · 64 unmodified lines | ||
| 133 | 157 | leaf_free(p); |
| 134 | 158 | } |
| 135 | 159 | |
| 160 | +void tFeedbackLeveler_initToPool (tFeedbackLeveler* const fb, float targetLevel, float factor, float strength, int mode, tMempool* const mp) | |
| 161 | +{ | |
| 162 | + _tMempool* m = *mp; | |
| 163 | + _tFeedbackLeveler* p = *fb = (_tFeedbackLeveler*) mpool_alloc(sizeof(_tFeedbackLeveler), m->pool); | |
| 164 | + | |
| 165 | + p->curr=0.0f; | |
| 166 | + p->targetLevel=targetLevel; | |
| 167 | + tPowerFollower_initToPool(&p->pwrFlw,factor, mp); | |
| 168 | + p->mode=mode; | |
| 169 | + p->strength=strength; | |
| 170 | +} | |
| 171 | + | |
| 172 | +void tFeedbackLeveler_freeFromPool (tFeedbackLeveler* const fb, tMempool* const mp) | |
| 173 | +{ | |
| 174 | + _tMempool* m = *mp; | |
| 175 | + _tFeedbackLeveler* p = *fb; | |
| 176 | + | |
| 177 | + tPowerFollower_freeFromPool(&p->pwrFlw, mp); | |
| 178 | + mpool_free(p, m->pool); | |
| 179 | +} | |
| 180 | + | |
| 136 | 181 | void tFeedbackLeveler_setStrength(tFeedbackLeveler* const fb, float strength) |
| 137 | 182 | { // strength is how strongly level diff is affecting the amp ratio |
| 138 | 183 | // try 0.125 for a start |
| @@ -156,8 +201,8 @@ float tFeedbackLeveler_tick(tFeedbackLeveler* const fb, float input) · 17 unmodified lines | ||
| 156 | 201 | { |
| 157 | 202 | _tFeedbackLeveler* p = *fb; |
| 158 | 203 | float levdiff=(tPowerFollower_tick(&p->pwrFlw, input)-p->targetLevel); |
| 159 | − if (p->mode==0 && levdiff<0) levdiff=0; | |
| 160 | − p->curr=input*(1-p->strength*levdiff); | |
| 204 | + if (p->mode==0 && levdiff<0.0f) levdiff=0.0f; | |
| 205 | + p->curr=input*(1.0f-p->strength*levdiff); | |
| 161 | 206 | return p->curr; |
| 162 | 207 | } |
| 163 | 208 | |
| @@ -59,6 +59,42 @@ void tTalkbox_free(tTalkbox* const voc) · 58 unmodified lines | ||
| 59 | 59 | leaf_free(v); |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | +void tTalkbox_initToPool (tTalkbox* const voc, int bufsize, tMempool* const mp) | |
| 63 | +{ | |
| 64 | + _tMempool* m = *mp; | |
| 65 | + _tTalkbox* v = *voc = (_tTalkbox*) mpool_alloc(sizeof(_tTalkbox), m->pool); | |
| 66 | + | |
| 67 | + v->param[0] = 0.5f; //wet | |
| 68 | + v->param[1] = 0.0f; //dry | |
| 69 | + v->param[2] = 0; // Swap | |
| 70 | + v->param[3] = 1.0f; //quality | |
| 71 | + | |
| 72 | + v->bufsize = bufsize; | |
| 73 | + | |
| 74 | + v->car0 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m->pool); | |
| 75 | + v->car1 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m->pool); | |
| 76 | + v->window = (float*) mpool_alloc(sizeof(float) * v->bufsize, m->pool); | |
| 77 | + v->buf0 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m->pool); | |
| 78 | + v->buf1 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m->pool); | |
| 79 | + | |
| 80 | + tTalkbox_update(voc); | |
| 81 | + tTalkbox_suspend(voc); | |
| 82 | +} | |
| 83 | + | |
| 84 | +void tTalkbox_freeFromPool (tTalkbox* const voc, tMempool* const mp) | |
| 85 | +{ | |
| 86 | + _tMempool* m = *mp; | |
| 87 | + _tTalkbox* v = *voc; | |
| 88 | + | |
| 89 | + mpool_free(v->buf1, m->pool); | |
| 90 | + mpool_free(v->buf0, m->pool); | |
| 91 | + mpool_free(v->window, m->pool); | |
| 92 | + mpool_free(v->car1, m->pool); | |
| 93 | + mpool_free(v->car0, m->pool); | |
| 94 | + | |
| 95 | + mpool_free(v, m->pool); | |
| 96 | +} | |
| 97 | + | |
| 62 | 98 | void tTalkbox_update(tTalkbox* const voc) ///update internal parameters... |
| 63 | 99 | { |
| 64 | 100 | _tTalkbox* v = *voc; |
| @@ -266,6 +302,31 @@ void tVocoder_free (tVocoder* const voc) · 201 unmodified lines | ||
| 266 | 302 | leaf_free(v); |
| 267 | 303 | } |
| 268 | 304 | |
| 305 | +void tVocoder_initToPool (tVocoder* const voc, tMempool* const mp) | |
| 306 | +{ | |
| 307 | + _tMempool* m = *mp; | |
| 308 | + _tVocoder* v = *voc = (_tVocoder*) mpool_alloc(sizeof(_tVocoder), m->pool); | |
| 309 | + | |
| 310 | + v->param[0] = 0.33f; //input select | |
| 311 | + v->param[1] = 0.50f; //output dB | |
| 312 | + v->param[2] = 0.40f; //hi thru | |
| 313 | + v->param[3] = 0.40f; //hi band | |
| 314 | + v->param[4] = 0.16f; //envelope | |
| 315 | + v->param[5] = 0.55f; //filter q | |
| 316 | + v->param[6] = 0.6667f;//freq range | |
| 317 | + v->param[7] = 0.33f; //num bands | |
| 318 | + | |
| 319 | + tVocoder_update(voc); | |
| 320 | +} | |
| 321 | + | |
| 322 | +void tVocoder_freeFromPool (tVocoder* const voc, tMempool* const mp) | |
| 323 | +{ | |
| 324 | + _tMempool* m = *mp; | |
| 325 | + _tVocoder* v = *voc; | |
| 326 | + | |
| 327 | + mpool_free(v, m->pool); | |
| 328 | +} | |
| 329 | + | |
| 269 | 330 | void tVocoder_update (tVocoder* const voc) |
| 270 | 331 | { |
| 271 | 332 | _tVocoder* v = *voc; |
| @@ -427,319 +488,354 @@ void tVocoder_suspend (tVocoder* const voc) · 155 unmodified lines | ||
| 427 | 488 | } |
| 428 | 489 | |
| 429 | 490 | //============================================================================================================ |
| 430 | −// RETUNE | |
| 491 | +// SOLAD | |
| 431 | 492 | //============================================================================================================ |
| 493 | +/******************************************************************************/ | |
| 494 | +/***************** static function declarations *******************************/ | |
| 495 | +/******************************************************************************/ | |
| 432 | 496 | |
| 433 | −void tRetune_init(tRetune* const rt, int numVoices, int bufSize, int frameSize) | |
| 497 | +static void solad_init(_tSOLAD *w); | |
| 498 | +static inline float read_sample(_tSOLAD *w, float floatindex); | |
| 499 | +static void pitchdown(_tSOLAD *w, float *out); | |
| 500 | +static void pitchup(_tSOLAD *w, float *out); | |
| 501 | + | |
| 502 | +/******************************************************************************/ | |
| 503 | +/***************** public access functions ************************************/ | |
| 504 | +/******************************************************************************/ | |
| 505 | + | |
| 506 | +// init | |
| 507 | +void tSOLAD_init(tSOLAD* const wp) | |
| 434 | 508 | { |
| 435 | − _tRetune* r = *rt = (_tRetune*) leaf_alloc(sizeof(_tRetune)); | |
| 436 | − | |
| 437 | − r->bufSize = bufSize; | |
| 438 | − r->frameSize = frameSize; | |
| 439 | − r->numVoices = numVoices; | |
| 440 | − | |
| 441 | − r->inBuffer = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 442 | − r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices); | |
| 443 | − | |
| 444 | − r->hopSize = DEFHOPSIZE; | |
| 445 | − r->windowSize = DEFWINDOWSIZE; | |
| 446 | − r->fba = FBA; | |
| 447 | − tRetune_setTimeConstant(rt, DEFTIMECONSTANT); | |
| 448 | − | |
| 449 | − r->inputPeriod = 0.0f; | |
| 450 | − | |
| 451 | − r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices); | |
| 452 | − r->pitchFactor = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 453 | − r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 454 | − for (int i = 0; i < r->numVoices; ++i) | |
| 455 | − { | |
| 456 | − r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 457 | − } | |
| 458 | − | |
| 459 | − tPeriodDetection_init(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize); | |
| 509 | + _tSOLAD* w = *wp = (_tSOLAD*) leaf_allocAndClear(sizeof(_tSOLAD)); | |
| 460 | 510 | |
| 461 | − for (int i = 0; i < r->numVoices; ++i) | |
| 462 | − { | |
| 463 | − tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize); | |
| 464 | − } | |
| 511 | + w->pitchfactor = 1.; | |
| 512 | + w->delaybuf = (float*) leaf_allocAndClear(sizeof(float) * (LOOPSIZE+16)); | |
| 513 | + solad_init(w); | |
| 465 | 514 | } |
| 466 | 515 | |
| 467 | −void tRetune_free(tRetune* const rt) | |
| 516 | +void tSOLAD_free(tSOLAD* const wp) | |
| 468 | 517 | { |
| 469 | − _tRetune* r = *rt; | |
| 518 | + _tSOLAD* w = *wp; | |
| 470 | 519 | |
| 471 | − tPeriodDetection_free(&r->pd); | |
| 472 | − for (int i = 0; i < r->numVoices; ++i) | |
| 473 | − { | |
| 474 | − tPitchShift_free(&r->ps[i]); | |
| 475 | − leaf_free(r->outBuffers[i]); | |
| 476 | − } | |
| 477 | − leaf_free(r->tickOutput); | |
| 478 | − leaf_free(r->pitchFactor); | |
| 479 | − leaf_free(r->ps); | |
| 480 | − leaf_free(r->inBuffer); | |
| 481 | − leaf_free(r->outBuffers); | |
| 482 | − leaf_free(r); | |
| 520 | + leaf_free(w->delaybuf); | |
| 521 | + leaf_free(w); | |
| 483 | 522 | } |
| 484 | 523 | |
| 485 | −float* tRetune_tick(tRetune* const rt, float sample) | |
| 524 | +void tSOLAD_initToPool (tSOLAD* const wp, tMempool* const mp) | |
| 486 | 525 | { |
| 487 | − _tRetune* r = *rt; | |
| 488 | − | |
| 489 | − r->inputPeriod = tPeriodDetection_findPeriod(&r->pd, sample); | |
| 490 | − | |
| 491 | − for (int v = 0; v < r->numVoices; ++v) | |
| 492 | − { | |
| 493 | − r->tickOutput[v] = tPitchShift_shift(&r->ps[v]); | |
| 494 | − } | |
| 526 | + _tMempool* m = *mp; | |
| 527 | + _tSOLAD* w = *wp = (_tSOLAD*) mpool_allocAndClear(sizeof(_tSOLAD), m->pool); | |
| 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 | |
| 499 | −void tRetune_setNumVoices(tRetune* const rt, int numVoices) | |
| 534 | +void 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) | |
| 504 | − { | |
| 505 | − tPitchShift_free(&r->ps[i]); | |
| 506 | − leaf_free(r->outBuffers[i]); | |
| 507 | − } | |
| 508 | − leaf_free(r->tickOutput); | |
| 509 | − leaf_free(r->pitchFactor); | |
| 510 | − leaf_free(r->ps); | |
| 511 | − leaf_free(r->outBuffers); | |
| 539 | + mpool_free(w->delaybuf, m->pool); | |
| 540 | + mpool_free(w, m->pool); | |
| 541 | +} | |
| 542 | + | |
| 543 | +// send one block of input samples, receive one block of output samples | |
| 544 | +void tSOLAD_ioSamples(tSOLAD* const wp, float* in, float* out, int blocksize) | |
| 545 | +{ | |
| 546 | + _tSOLAD* w = *wp; | |
| 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); | |
| 516 | − r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices); | |
| 517 | − r->pitchFactor = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 518 | − r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 519 | − for (int i = 0; i < r->numVoices; ++i) | |
| 520 | − { | |
| 521 | − r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 522 | − tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize); | |
| 523 | − } | |
| 551 | + if(!i) w->delaybuf[LOOPSIZE] = in[0]; // copy one sample for interpolation | |
| 552 | + while(n--) w->delaybuf[i++] = *in++; // copy one input block to delay buffer | |
| 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 | |
| 528 | −void tRetune_setPitchFactors(tRetune* const rt, float pf) | |
| 561 | +// set periodicity analysis data | |
| 562 | +void 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) | |
| 533 | − { | |
| 534 | − r->pitchFactor[i] = pf; | |
| 535 | − tPitchShift_setPitchFactor(&r->ps[i], r->pitchFactor[i]); | |
| 536 | − } | |
| 566 | + if(period > MAXPERIOD) period = MAXPERIOD; | |
| 567 | + if(period > MINPERIOD) w->period = period; // ignore period when too small | |
| 537 | 568 | } |
| 538 | 569 | |
| 539 | −void tRetune_setPitchFactor(tRetune* const rt, float pf, int voice) | |
| 570 | +// set pitch factor between 0.25 and 4 | |
| 571 | +void tSOLAD_setPitchFactor(tSOLAD* const wp, float pitchfactor) | |
| 540 | 572 | { |
| 541 | − _tRetune* r = *rt; | |
| 573 | + _tSOLAD* w = *wp; | |
| 542 | 574 | |
| 543 | − r->pitchFactor[voice] = pf; | |
| 544 | − tPitchShift_setPitchFactor(&r->ps[voice], r->pitchFactor[voice]); | |
| 575 | + if (pitchfactor <= 0.0f) return; | |
| 576 | + w->pitchfactor = pitchfactor; | |
| 545 | 577 | } |
| 546 | 578 | |
| 547 | −void tRetune_setTimeConstant(tRetune* const rt, float tc) | |
| 579 | +// force readpointer lag | |
| 580 | +void tSOLAD_setReadLag(tSOLAD* const wp, float readlag) | |
| 548 | 581 | { |
| 549 | − _tRetune* r = *rt; | |
| 582 | + _tSOLAD* w = *wp; | |
| 550 | 583 | |
| 551 | − r->timeConstant = tc; | |
| 552 | − r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant); | |
| 584 | + if(readlag < 0) readlag = 0; | |
| 585 | + if(readlag < w->readlag) // do not jump backward, only forward | |
| 586 | + { | |
| 587 | + w->jump = w->readlag - readlag; | |
| 588 | + w->readlag = readlag; | |
| 589 | + w->xfadelength = readlag; | |
| 590 | + w->xfadevalue = 1; | |
| 591 | + } | |
| 553 | 592 | } |
| 554 | 593 | |
| 555 | −void tRetune_setHopSize(tRetune* const rt, int hs) | |
| 594 | +// reset state variables | |
| 595 | +void tSOLAD_resetState(tSOLAD* const wp) | |
| 556 | 596 | { |
| 557 | − _tRetune* r = *rt; | |
| 597 | + _tSOLAD* w = *wp; | |
| 558 | 598 | |
| 559 | − r->hopSize = hs; | |
| 560 | − tPeriodDetection_setHopSize(&r->pd, r->hopSize); | |
| 561 | −} | |
| 562 | − | |
| 563 | −void tRetune_setWindowSize(tRetune* const rt, int ws) | |
| 564 | −{ | |
| 565 | − _tRetune* r = *rt; | |
| 599 | + int n = LOOPSIZE + 1; | |
| 600 | + float *buf = w->delaybuf; | |
| 566 | 601 | |
| 567 | − r->windowSize = ws; | |
| 568 | − tPeriodDetection_setWindowSize(&r->pd, r->windowSize); | |
| 602 | + while(n--) *buf++ = 0; | |
| 603 | + solad_init(w); | |
| 569 | 604 | } |
| 570 | 605 | |
| 571 | −float tRetune_getInputPeriod(tRetune* const rt) | |
| 572 | −{ | |
| 573 | − _tRetune* r = *rt; | |
| 574 | − | |
| 575 | − return r->inputPeriod; | |
| 576 | −} | |
| 606 | +/******************************************************************************/ | |
| 607 | +/******************** private procedures **************************************/ | |
| 608 | +/******************************************************************************/ | |
| 577 | 609 | |
| 578 | −float tRetune_getInputFreq(tRetune* const rt) | |
| 579 | −{ | |
| 580 | − _tRetune* r = *rt; | |
| 581 | − | |
| 582 | − return 1.0f/r->inputPeriod; | |
| 583 | −} | |
| 610 | +/* | |
| 611 | + Function pitchdown() is called to read samples from the delay buffer when pitch | |
| 612 | + factor is between 0.25 and 1. The read pointer lags behind because of the slowed | |
| 613 | + down speed, and it must jump forward towards the write pointer soon as there is | |
| 614 | + sufficient space to jump. That is, if there is at least one period of the input | |
| 615 | + signal between read pointer and write pointer. When short periods follow up on | |
| 616 | + long periods, the read pointer may have space to jump over more than one period | |
| 617 | + lenghts. Jump length must be [periodlength ^ 2] in any case. | |
| 618 | + | |
| 619 | + A linear crossfade function joins the jump-from point with the jump-to point. | |
| 620 | + The crossfade must be completed before another read pointer jump is allowed. | |
| 621 | + Length of the crossfade function is stored as a number of samples in terms of | |
| 622 | + the input sample rate. This length is dynamically translated | |
| 623 | + to a crossfade length expressed in output reading rate, according to pitch | |
| 624 | + factor which can change before the crossfade is completed. Crossfade length does | |
| 625 | + not cover an invariable length in periods for all pitch transposition factors. | |
| 626 | + For pitch factors from 0.5 till 1, crossfade length is stretched in the | |
| 627 | + output just as much as the signal itself, as crossfade speed is set to equal | |
| 628 | + pitch factor. For pitch factors below 0.5, the read pointer wants to jump | |
| 629 | + forward before one period is read, therefore the crossfade length as expressed | |
| 630 | + in output periods must be shorter. Crossfade speed is set to [1 - pitchfactor] | |
| 631 | + for those cases. Pitch factor 0.5 is the natural switch point between crossfade | |
| 632 | + speeds [pitchfactor] and [1 - pitchfactor] because 0.5 == 1 - 0.5. The crossfade | |
| 633 | + speed modification for pitch factors below 0.5 also means that much of the | |
| 634 | + original signal content will be skipped. | |
| 635 | + */ | |
| 584 | 636 | |
| 585 | −//============================================================================================================ | |
| 586 | −// AUTOTUNE | |
| 587 | −//============================================================================================================ | |
| 588 | 637 | |
| 589 | −void tAutotune_init(tAutotune* const rt, int numVoices, int bufSize, int frameSize) | |
| 638 | +static void pitchdown(_tSOLAD* const w, float *out) | |
| 590 | 639 | { |
| 591 | − _tAutotune* r = *rt = (_tAutotune*) leaf_alloc(sizeof(_tAutotune)); | |
| 592 | − | |
| 593 | − r->bufSize = bufSize; | |
| 594 | − r->frameSize = frameSize; | |
| 595 | − r->numVoices = numVoices; | |
| 596 | − | |
| 597 | − r->inBuffer = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 598 | − r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices); | |
| 599 | − | |
| 600 | − r->hopSize = DEFHOPSIZE; | |
| 601 | − r->windowSize = DEFWINDOWSIZE; | |
| 602 | − r->fba = FBA; | |
| 603 | − tAutotune_setTimeConstant(rt, DEFTIMECONSTANT); | |
| 604 | − | |
| 605 | − | |
| 606 | − | |
| 607 | − r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices); | |
| 608 | − r->freq = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 609 | − r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 610 | − for (int i = 0; i < r->numVoices; ++i) | |
| 611 | − { | |
| 612 | − r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 613 | − } | |
| 640 | + int n = w->blocksize; | |
| 641 | + float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values! | |
| 642 | + float pitchfactor = w->pitchfactor; | |
| 643 | + float period = w->period; | |
| 644 | + float readlag = w->readlag; | |
| 645 | + float readlagstep = 1 - pitchfactor; | |
| 646 | + float jump = w->jump; | |
| 647 | + float xfadevalue = w->xfadevalue; | |
| 648 | + float xfadelength = w->xfadelength; | |
| 649 | + float xfadespeed, xfadestep, readindex, outputsample; | |
| 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; | |
| 623 | −} | |
| 624 | − | |
| 625 | −void tAutotune_free(tAutotune* const rt) | |
| 626 | −{ | |
| 627 | − _tAutotune* r = *rt; | |
| 628 | − | |
| 629 | − tPeriodDetection_free(&r->pd); | |
| 630 | − for (int i = 0; i < r->numVoices; ++i) | |
| 631 | − { | |
| 632 | − tPitchShift_free(&r->ps[i]); | |
| 633 | − leaf_free(r->outBuffers[i]); | |
| 634 | − } | |
| 635 | − leaf_free(r->tickOutput); | |
| 636 | − leaf_free(r->freq); | |
| 637 | − leaf_free(r->ps); | |
| 638 | − leaf_free(r->inBuffer); | |
| 639 | − leaf_free(r->outBuffers); | |
| 640 | − leaf_free(r); | |
| 685 | + w->jump = jump; // state variables | |
| 686 | + w->readlag = readlag; | |
| 687 | + w->xfadevalue = xfadevalue; | |
| 688 | + w->xfadelength = xfadelength; | |
| 641 | 689 | } |
| 642 | 690 | |
| 643 | −float* tAutotune_tick(tAutotune* const rt, float sample) | |
| 644 | −{ | |
| 645 | − _tAutotune* r = *rt; | |
| 646 | − | |
| 647 | − float tempPeriod = tPeriodDetection_findPeriod(&r->pd, sample); | |
| 648 | − if (tempPeriod < 1000.0f) //to avoid trying to follow consonants JS | |
| 649 | − { | |
| 650 | − r->inputPeriod = tempPeriod; | |
| 651 | − } | |
| 652 | − | |
| 653 | − for (int v = 0; v < r->numVoices; ++v) | |
| 654 | − { | |
| 655 | − r->tickOutput[v] = tPitchShift_shiftToFreq(&r->ps[v], r->freq[v]); | |
| 656 | − } | |
| 657 | 691 | |
| 658 | − return r->tickOutput; | |
| 659 | −} | |
| 660 | − | |
| 661 | −void tAutotune_setNumVoices(tAutotune* const rt, int numVoices) | |
| 692 | +/* | |
| 693 | + Function pitchup() for pitch factors above 1 is more complicated than | |
| 694 | + pitchdown(). The read pointer increments faster than the write pointer and a | |
| 695 | + backward jump must happen in time, reckoning with the crossfade region. The read | |
| 696 | + pointer backward jump length is always one period. In order to minimize the area | |
| 697 | + of signal duplicates, crossfade length is aimed at [period / pitchfactor]. | |
| 698 | + This leads to a crossfade speed of [pitchfactor * pitchfactor]. | |
| 699 | + | |
| 700 | + Some samples for the fade out (but not all of them) must already be in the | |
| 701 | + buffer, otherwise we will run out of input samples before the crossfade is | |
| 702 | + completed. The ratio of past samples and future samples for a crossfade of any | |
| 703 | + length is as follows: | |
| 704 | + | |
| 705 | + past samples: xfadelength * (1 - 1 / pitchfactor) | |
| 706 | + future samples: xfadelength * (1 / pitchfactor) | |
| 707 | + | |
| 708 | + For example in the case of pitch factor 1.5 this would be: | |
| 709 | + | |
| 710 | + past samples: xfadelength * (1 - 1 / 1.5) = xfadelength * 1 / 3 | |
| 711 | + future samples: xfadelength * (1 / 1.5) = xfadelength * 2 / 3 | |
| 712 | + | |
| 713 | + In the case of pitch factor 4 this would be: | |
| 714 | + | |
| 715 | + past samples: xfadelength * (1 - 1 / 4) = xfadelength * 3 / 4 | |
| 716 | + future samples: xfadelength * (1 / 4) = xfadelength * 1 / 4 | |
| 717 | + | |
| 718 | + The read pointer lag must therefore preserve a minimum dependent on pitch | |
| 719 | + factor. The minimum is called 'limit' here: | |
| 720 | + | |
| 721 | + limit = period * (pitchfactor - 1) / pitchfactor * pitchfactor | |
| 722 | + | |
| 723 | + Components of this expression are combined to reuse them in operations, while | |
| 724 | + (pitchfactor - 1) is changed to (pitchfactor - 0.99) to avoid numerical | |
| 725 | + resolution issues for pitch factors slightly above 1: | |
| 726 | + | |
| 727 | + xfadespeed = pitchfactor * pitchfactor | |
| 728 | + limitfactor = (pitchfactor - 0.99) / xfadespeed | |
| 729 | + limit = period * limitfactor | |
| 730 | + | |
| 731 | + When read lag is smaller than this limit, the read pointer must preferably | |
| 732 | + jump backward, unless a previous crossfade is not yet completed. Crossfades must | |
| 733 | + preferably be completed, unless the read pointer lag becomes smaller than zero. | |
| 734 | + With fluctuating period lengths and pitch factors, the readpointer lag limit may | |
| 735 | + change from one input block to the next in such a way that the actual lag is | |
| 736 | + suddenly much smaller than the limit, and the intended crossfade length can not | |
| 737 | + be applied. Therefore the crossfade length is simply calculated from the | |
| 738 | + available amount of samples for all cases, like so: | |
| 739 | + | |
| 740 | + xfadelength = readlag / limitfactor | |
| 741 | + | |
| 742 | + For most occurrences, this will amount to a crossfade length reduced to | |
| 743 | + [period / pitchfactor] in the output for pitch factors above 1, while in some | |
| 744 | + cases it will be considerably shorter. Fortunately, an incidental aberration of | |
| 745 | + the intended crossfade length hardly ever creates an audible artifact. The | |
| 746 | + reason to specify preferred crossfade length according to pitch factor is to | |
| 747 | + minimize the impression of echoes without sacrificing too much of the signal | |
| 748 | + content. The readpointer jump length remains one period in any case. | |
| 749 | + | |
| 750 | + Sometimes, the input signal periodicity may decrease substantially between one | |
| 751 | + signal block and the next. In such cases it may be possible for the read pointer | |
| 752 | + to jump forward and reduce latency. For every signal block, a check on this | |
| 753 | + possibility is done. A previous crossfade must be completed before a forward | |
| 754 | + jump is allowed. | |
| 755 | + */ | |
| 756 | +static void pitchup(_tSOLAD* const w, float *out) | |
| 662 | 757 | { |
| 663 | − _tAutotune* r = *rt; | |
| 664 | − | |
| 665 | − for (int i = 0; i < r->numVoices; ++i) | |
| 666 | − { | |
| 667 | − tPitchShift_free(&r->ps[i]); | |
| 668 | − leaf_free(r->outBuffers[i]); | |
| 669 | − } | |
| 670 | − leaf_free(r->tickOutput); | |
| 671 | − leaf_free(r->freq); | |
| 672 | − leaf_free(r->ps); | |
| 673 | − leaf_free(r->outBuffers); | |
| 758 | + int n = w->blocksize; | |
| 759 | + float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values | |
| 760 | + float pitchfactor = w->pitchfactor; | |
| 761 | + float period = w->period; | |
| 762 | + float readlag = w->readlag; | |
| 763 | + float jump = w->jump; | |
| 764 | + float xfadevalue = w->xfadevalue; | |
| 765 | + float xfadelength = w->xfadelength; | |
| 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); | |
| 678 | − r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices); | |
| 679 | − r->freq = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 680 | − r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 681 | − for (int i = 0; i < r->numVoices; ++i) | |
| 774 | + if((readlag > (period + 2 * limit)) & (xfadevalue < 0)) | |
| 682 | 775 | { |
| 683 | − r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 684 | − tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize); | |
| 776 | + jump = period; // jump forward | |
| 777 | + while((jump * 2) < (readlag - 2 * limit)) jump *= 2; // use available space | |
| 778 | + readlag -= jump; // reduce read pointer lag | |
| 779 | + xfadevalue = 1; // start crossfade | |
| 780 | + xfadelength = period - 1; | |
| 781 | + xfadestep = xfadespeed / xfadelength; | |
| 685 | 782 | } |
| 686 | 783 | |
| 687 | − | |
| 688 | −} | |
| 689 | − | |
| 690 | −void tAutotune_setFreqs(tAutotune* const rt, float f) | |
| 691 | −{ | |
| 692 | − _tAutotune* r = *rt; | |
| 693 | − | |
| 694 | − for (int i = 0; i < r->numVoices; ++i) | |
| 784 | + while(n--) | |
| 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 | − | |
| 700 | −void tAutotune_setFreq(tAutotune* const rt, float f, int voice) | |
| 701 | −{ | |
| 702 | − _tAutotune* r = *rt; | |
| 703 | 814 | |
| 704 | − r->freq[voice] = f; | |
| 705 | −} | |
| 706 | − | |
| 707 | −void tAutotune_setTimeConstant(tAutotune* const rt, float tc) | |
| 708 | −{ | |
| 709 | − _tAutotune* r = *rt; | |
| 710 | − | |
| 711 | − r->timeConstant = tc; | |
| 712 | − r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant); | |
| 713 | −} | |
| 714 | − | |
| 715 | −void tAutotune_setHopSize(tAutotune* const rt, int hs) | |
| 716 | −{ | |
| 717 | − _tAutotune* r = *rt; | |
| 718 | − | |
| 719 | − r->hopSize = hs; | |
| 720 | − tPeriodDetection_setHopSize(&r->pd, r->hopSize); | |
| 721 | −} | |
| 722 | − | |
| 723 | −void tAutotune_setWindowSize(tAutotune* const rt, int ws) | |
| 724 | −{ | |
| 725 | − _tAutotune* r = *rt; | |
| 726 | − | |
| 727 | − r->windowSize = ws; | |
| 728 | − tPeriodDetection_setWindowSize(&r->pd, r->windowSize); | |
| 815 | + w->readlag = readlag; // state variables | |
| 816 | + w->jump = jump; | |
| 817 | + w->xfadelength = xfadelength; | |
| 818 | + w->xfadevalue = xfadevalue; | |
| 729 | 819 | } |
| 730 | 820 | |
| 731 | −float tAutotune_getInputPeriod(tAutotune* const rt) | |
| 821 | +// read one sample from delay buffer, with linear interpolation | |
| 822 | +static inline float read_sample(_tSOLAD* const w, float floatindex) | |
| 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 | |
| 738 | −float tAutotune_getInputFreq(tAutotune* const rt) | |
| 832 | +static void solad_init(_tSOLAD* const w) | |
| 739 | 833 | { |
| 740 | − _tAutotune* r = *rt; | |
| 741 | − | |
| 742 | − return 1.0f/r->inputPeriod; | |
| 834 | + w->timeindex = 0; | |
| 835 | + w->xfadevalue = -1; | |
| 836 | + w->period = INITPERIOD; | |
| 837 | + w->readlag = INITPERIOD; | |
| 838 | + w->blocksize = INITPERIOD; | |
| 743 | 839 | } |
| 744 | 840 | |
| 745 | 841 | //============================================================================================================ |
| @@ -776,7 +872,7 @@ static int pitchshift_attackdetect(_tPitchShift* ps) · 30 unmodified lines | ||
| 776 | 872 | |
| 777 | 873 | void 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 | 876 | _tPeriodDetection* p = *pd; |
| 781 | 877 | |
| 782 | 878 | ps->p = pd; |
| @@ -806,6 +902,40 @@ void tPitchShift_free(tPitchShift* const psr) · 23 unmodified lines | ||
| 806 | 902 | leaf_free(ps); |
| 807 | 903 | } |
| 808 | 904 | |
| 905 | +void tPitchShift_initToPool (tPitchShift* const psr, tPeriodDetection* const pd, float* out, int bufSize, tMempool* const mp) | |
| 906 | +{ | |
| 907 | + _tMempool* m = *mp; | |
| 908 | + _tPitchShift* ps = *psr = (_tPitchShift*) mpool_allocAndClear(sizeof(_tPitchShift), m->pool); | |
| 909 | + _tPeriodDetection* p = *pd; | |
| 910 | + | |
| 911 | + ps->p = pd; | |
| 912 | + | |
| 913 | + ps->outBuffer = out; | |
| 914 | + ps->bufSize = bufSize; | |
| 915 | + ps->frameSize = p->frameSize; | |
| 916 | + ps->framesPerBuffer = ps->bufSize / ps->frameSize; | |
| 917 | + ps->curBlock = 1; | |
| 918 | + ps->lastBlock = 0; | |
| 919 | + ps->index = 0; | |
| 920 | + ps->pitchFactor = 1.0f; | |
| 921 | + | |
| 922 | + tSOLAD_initToPool(&ps->sola, mp); | |
| 923 | + | |
| 924 | + tHighpass_initToPool(&ps->hp, HPFREQ, mp); | |
| 925 | + | |
| 926 | + tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO); | |
| 927 | +} | |
| 928 | + | |
| 929 | +void tPitchShift_freeFromPool (tPitchShift* const psr, tMempool* const mp) | |
| 930 | +{ | |
| 931 | + _tMempool* m = *mp; | |
| 932 | + _tPitchShift* ps = *psr; | |
| 933 | + | |
| 934 | + tSOLAD_freeFromPool(&ps->sola, mp); | |
| 935 | + tHighpass_freeFromPool(&ps->hp, mp); | |
| 936 | + mpool_free(ps, m->pool); | |
| 937 | +} | |
| 938 | + | |
| 809 | 939 | void tPitchShift_setPitchFactor(tPitchShift* psr, float pf) |
| 810 | 940 | { |
| 811 | 941 | _tPitchShift* ps = *psr; |
| @@ -916,340 +1046,435 @@ float tPitchShift_shiftToFunc (tPitchShift* psr, float (*fun)(float)) · 104 unmodified lines | ||
| 916 | 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 | + | |
| 1056 | +void tRetune_init(tRetune* const rt, int numVoices, int bufSize, int frameSize) | |
| 1057 | +{ | |
| 1058 | + _tRetune* r = *rt = (_tRetune*) leaf_allocAndClear(sizeof(_tRetune)); | |
| 1059 | + | |
| 1060 | + r->bufSize = bufSize; | |
| 1061 | + r->frameSize = frameSize; | |
| 1062 | + r->numVoices = numVoices; | |
| 1063 | + | |
| 1064 | + r->inBuffer = (float*) leaf_allocAndClear(sizeof(float) * r->bufSize); | |
| 1065 | + r->outBuffers = (float**) leaf_allocAndClear(sizeof(float*) * r->numVoices); | |
| 1066 | + | |
| 1067 | + r->hopSize = DEFHOPSIZE; | |
| 1068 | + r->windowSize = DEFWINDOWSIZE; | |
| 1069 | + r->fba = FBA; | |
| 1070 | + tRetune_setTimeConstant(rt, DEFTIMECONSTANT); | |
| 1071 | + | |
| 1072 | + r->inputPeriod = 0.0f; | |
| 1073 | + | |
| 1074 | + r->ps = (tPitchShift*) leaf_allocAndClear(sizeof(tPitchShift) * r->numVoices); | |
| 1075 | + r->pitchFactor = (float*) leaf_allocAndClear(sizeof(float) * r->numVoices); | |
| 1076 | + r->tickOutput = (float*) leaf_allocAndClear(sizeof(float) * r->numVoices); | |
| 1077 | + for (int i = 0; i < r->numVoices; ++i) | |
| 1078 | + { | |
| 1079 | + r->outBuffers[i] = (float*) leaf_allocAndClear(sizeof(float) * r->bufSize); | |
| 1080 | + } | |
| 1081 | + | |
| 1082 | + tPeriodDetection_init(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize); | |
| 1083 | + | |
| 1084 | + for (int i = 0; i < r->numVoices; ++i) | |
| 1085 | + { | |
| 1086 | + tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize); | |
| 1087 | + } | |
| 1088 | +} | |
| 1089 | + | |
| 1090 | +void tRetune_free(tRetune* const rt) | |
| 1091 | +{ | |
| 1092 | + _tRetune* r = *rt; | |
| 1093 | + | |
| 1094 | + tPeriodDetection_free(&r->pd); | |
| 1095 | + for (int i = 0; i < r->numVoices; ++i) | |
| 1096 | + { | |
| 1097 | + tPitchShift_free(&r->ps[i]); | |
| 1098 | + leaf_free(r->outBuffers[i]); | |
| 1099 | + } | |
| 1100 | + leaf_free(r->tickOutput); | |
| 1101 | + leaf_free(r->pitchFactor); | |
| 1102 | + leaf_free(r->ps); | |
| 1103 | + leaf_free(r->inBuffer); | |
| 1104 | + leaf_free(r->outBuffers); | |
| 1105 | + leaf_free(r); | |
| 1106 | +} | |
| 1107 | + | |
| 1108 | +void tRetune_initToPool (tRetune* const rt, int numVoices, int bufSize, int frameSize, tMempool* const mp) | |
| 1109 | +{ | |
| 1110 | + _tMempool* m = *mp; | |
| 1111 | + _tRetune* r = *rt = (_tRetune*) mpool_alloc(sizeof(_tRetune), m->pool); | |
| 1112 | + | |
| 1113 | + r->bufSize = bufSize; | |
| 1114 | + r->frameSize = frameSize; | |
| 1115 | + r->numVoices = numVoices; | |
| 1116 | + | |
| 1117 | + r->inBuffer = (float*) mpool_allocAndClear(sizeof(float) * r->bufSize, m->pool); | |
| 1118 | + r->outBuffers = (float**) mpool_allocAndClear(sizeof(float*) * r->numVoices, m->pool); | |
| 1119 | + | |
| 1120 | + r->hopSize = DEFHOPSIZE; | |
| 1121 | + r->windowSize = DEFWINDOWSIZE; | |
| 1122 | + r->fba = FBA; | |
| 1123 | + tRetune_setTimeConstant(rt, DEFTIMECONSTANT); | |
| 1124 | + | |
| 1125 | + r->inputPeriod = 0.0f; | |
| 1126 | + | |
| 1127 | + r->ps = (tPitchShift*) mpool_allocAndClear(sizeof(tPitchShift) * r->numVoices, m->pool); | |
| 1128 | + r->pitchFactor = (float*) mpool_allocAndClear(sizeof(float) * r->numVoices, m->pool); | |
| 1129 | + r->tickOutput = (float*) mpool_allocAndClear(sizeof(float) * r->numVoices, m->pool); | |
| 1130 | + for (int i = 0; i < r->numVoices; ++i) | |
| 1131 | + { | |
| 1132 | + r->outBuffers[i] = (float*) mpool_allocAndClear(sizeof(float) * r->bufSize, m->pool); | |
| 1133 | + } | |
| 1134 | + | |
| 1135 | + tPeriodDetection_initToPool(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize, mp); | |
| 1136 | + | |
| 1137 | + for (int i = 0; i < r->numVoices; ++i) | |
| 1138 | + { | |
| 1139 | + tPitchShift_initToPool(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize, mp); | |
| 1140 | + } | |
| 1141 | +} | |
| 1142 | + | |
| 1143 | +void tRetune_freeFromPool (tRetune* const rt, tMempool* const mp) | |
| 1144 | +{ | |
| 1145 | + _tMempool* m = *mp; | |
| 1146 | + _tRetune* r = *rt; | |
| 1147 | + | |
| 1148 | + tPeriodDetection_freeFromPool(&r->pd, mp); | |
| 1149 | + for (int i = 0; i < r->numVoices; ++i) | |
| 1150 | + { | |
| 1151 | + tPitchShift_freeFromPool(&r->ps[i], mp); | |
| 1152 | + mpool_free(r->outBuffers[i], m->pool); | |
| 1153 | + } | |
| 1154 | + mpool_free(r->tickOutput, m->pool); | |
| 1155 | + mpool_free(r->pitchFactor, m->pool); | |
| 1156 | + mpool_free(r->ps, m->pool); | |
| 1157 | + mpool_free(r->inBuffer, m->pool); | |
| 1158 | + mpool_free(r->outBuffers, m->pool); | |
| 1159 | + mpool_free(r, m->pool); | |
| 1160 | +} | |
| 1161 | + | |
| 1162 | +float* tRetune_tick(tRetune* const rt, float sample) | |
| 1163 | +{ | |
| 1164 | + _tRetune* r = *rt; | |
| 1165 | + | |
| 1166 | + r->inputPeriod = tPeriodDetection_findPeriod(&r->pd, sample); | |
| 1167 | + | |
| 1168 | + for (int v = 0; v < r->numVoices; ++v) | |
| 1169 | + { | |
| 1170 | + r->tickOutput[v] = tPitchShift_shift(&r->ps[v]); | |
| 1171 | + } | |
| 1172 | + | |
| 1173 | + return r->tickOutput; | |
| 1174 | +} | |
| 1175 | + | |
| 1176 | +void tRetune_setNumVoices(tRetune* const rt, int numVoices) | |
| 1177 | +{ | |
| 1178 | + _tRetune* r = *rt; | |
| 1179 | + | |
| 1180 | + for (int i = 0; i < r->numVoices; ++i) | |
| 1181 | + { | |
| 1182 | + tPitchShift_free(&r->ps[i]); | |
| 1183 | + leaf_free(r->outBuffers[i]); | |
| 1184 | + } | |
| 1185 | + leaf_free(r->tickOutput); | |
| 1186 | + leaf_free(r->pitchFactor); | |
| 1187 | + leaf_free(r->ps); | |
| 1188 | + leaf_free(r->outBuffers); | |
| 1189 | + | |
| 1190 | + r->numVoices = numVoices; | |
| 1191 | + | |
| 1192 | + r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices); | |
| 1193 | + r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices); | |
| 1194 | + r->pitchFactor = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 1195 | + r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 1196 | + for (int i = 0; i < r->numVoices; ++i) | |
| 1197 | + { | |
| 1198 | + r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 1199 | + tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize); | |
| 1200 | + } | |
| 1201 | + | |
| 1202 | + | |
| 920 | 1203 | } |
| 921 | 1204 | |
| 922 | −//============================================================================================================ | |
| 923 | −// SOLAD | |
| 924 | −//============================================================================================================ | |
| 925 | −/******************************************************************************/ | |
| 926 | −/***************** static function declarations *******************************/ | |
| 927 | −/******************************************************************************/ | |
| 928 | − | |
| 929 | −static void solad_init(_tSOLAD *w); | |
| 930 | −static inline float read_sample(_tSOLAD *w, float floatindex); | |
| 931 | −static void pitchdown(_tSOLAD *w, float *out); | |
| 932 | −static void pitchup(_tSOLAD *w, float *out); | |
| 933 | − | |
| 934 | −/******************************************************************************/ | |
| 935 | −/***************** public access functions ************************************/ | |
| 936 | −/******************************************************************************/ | |
| 937 | − | |
| 938 | −// init | |
| 939 | −void tSOLAD_init(tSOLAD* const wp) | |
| 1205 | +void tRetune_setPitchFactors(tRetune* const rt, float pf) | |
| 940 | 1206 | { |
| 941 | − _tSOLAD* w = *wp = (_tSOLAD*) leaf_alloc(sizeof(_tSOLAD)); | |
| 1207 | + _tRetune* r = *rt; | |
| 942 | 1208 | |
| 943 | − w->pitchfactor = 1.; | |
| 944 | − w->delaybuf = (float*) leaf_alloc(sizeof(float) * (LOOPSIZE+16)); | |
| 945 | − solad_init(w); | |
| 1209 | + for (int i = 0; i < r->numVoices; ++i) | |
| 1210 | + { | |
| 1211 | + r->pitchFactor[i] = pf; | |
| 1212 | + tPitchShift_setPitchFactor(&r->ps[i], r->pitchFactor[i]); | |
| 1213 | + } | |
| 946 | 1214 | } |
| 947 | 1215 | |
| 948 | −void tSOLAD_free(tSOLAD* const wp) | |
| 1216 | +void 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); | |
| 953 | − leaf_free(w); | |
| 1220 | + r->pitchFactor[voice] = pf; | |
| 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 samples | |
| 957 | −void tSOLAD_ioSamples(tSOLAD* const wp, float* in, float* out, int blocksize) | |
| 1224 | +void tRetune_setTimeConstant(tRetune* const rt, float tc) | |
| 958 | 1225 | { |
| 959 | − _tSOLAD* w = *wp; | |
| 960 | − | |
| 961 | − int i = w->timeindex; | |
| 962 | − int n = w->blocksize = blocksize; | |
| 1226 | + _tRetune* r = *rt; | |
| 963 | 1227 | |
| 964 | − if(!i) w->delaybuf[LOOPSIZE] = in[0]; // copy one sample for interpolation | |
| 965 | − while(n--) w->delaybuf[i++] = *in++; // copy one input block to delay buffer | |
| 1228 | + r->timeConstant = tc; | |
| 1229 | + r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant); | |
| 1230 | +} | |
| 1231 | + | |
| 1232 | +void tRetune_setHopSize(tRetune* const rt, int hs) | |
| 1233 | +{ | |
| 1234 | + _tRetune* r = *rt; | |
| 966 | 1235 | |
| 967 | − if(w->pitchfactor > 1) pitchup(w, out); | |
| 968 | − else pitchdown(w, out); | |
| 1236 | + r->hopSize = hs; | |
| 1237 | + tPeriodDetection_setHopSize(&r->pd, r->hopSize); | |
| 1238 | +} | |
| 1239 | + | |
| 1240 | +void tRetune_setWindowSize(tRetune* const rt, int ws) | |
| 1241 | +{ | |
| 1242 | + _tRetune* r = *rt; | |
| 969 | 1243 | |
| 970 | − w->timeindex += blocksize; | |
| 971 | − w->timeindex &= LOOPMASK; | |
| 1244 | + r->windowSize = ws; | |
| 1245 | + tPeriodDetection_setWindowSize(&r->pd, r->windowSize); | |
| 972 | 1246 | } |
| 973 | 1247 | |
| 974 | −// set periodicity analysis data | |
| 975 | −void tSOLAD_setPeriod(tSOLAD* const wp, float period) | |
| 1248 | +float tRetune_getInputPeriod(tRetune* const rt) | |
| 976 | 1249 | { |
| 977 | − _tSOLAD* w = *wp; | |
| 1250 | + _tRetune* r = *rt; | |
| 978 | 1251 | |
| 979 | − if(period > MAXPERIOD) period = MAXPERIOD; | |
| 980 | − if(period > MINPERIOD) w->period = period; // ignore period when too small | |
| 1252 | + return r->inputPeriod; | |
| 981 | 1253 | } |
| 982 | 1254 | |
| 983 | −// set pitch factor between 0.25 and 4 | |
| 984 | −void tSOLAD_setPitchFactor(tSOLAD* const wp, float pitchfactor) | |
| 1255 | +float tRetune_getInputFreq(tRetune* const rt) | |
| 985 | 1256 | { |
| 986 | − _tSOLAD* w = *wp; | |
| 1257 | + _tRetune* r = *rt; | |
| 987 | 1258 | |
| 988 | − if (pitchfactor <= 0.0f) return; | |
| 989 | − w->pitchfactor = pitchfactor; | |
| 1259 | + return 1.0f/r->inputPeriod; | |
| 990 | 1260 | } |
| 991 | 1261 | |
| 992 | −// force readpointer lag | |
| 993 | −void tSOLAD_setReadLag(tSOLAD* const wp, float readlag) | |
| 1262 | +//============================================================================================================ | |
| 1263 | +// AUTOTUNE | |
| 1264 | +//============================================================================================================ | |
| 1265 | + | |
| 1266 | +void tAutotune_init(tAutotune* const rt, int numVoices, int bufSize, int frameSize) | |
| 994 | 1267 | { |
| 995 | − _tSOLAD* w = *wp; | |
| 1268 | + _tAutotune* r = *rt = (_tAutotune*) leaf_alloc(sizeof(_tAutotune)); | |
| 996 | 1269 | |
| 997 | − if(readlag < 0) readlag = 0; | |
| 998 | − if(readlag < w->readlag) // do not jump backward, only forward | |
| 1270 | + r->bufSize = bufSize; | |
| 1271 | + r->frameSize = frameSize; | |
| 1272 | + r->numVoices = numVoices; | |
| 1273 | + | |
| 1274 | + r->inBuffer = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 1275 | + r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices); | |
| 1276 | + | |
| 1277 | + r->hopSize = DEFHOPSIZE; | |
| 1278 | + r->windowSize = DEFWINDOWSIZE; | |
| 1279 | + r->fba = FBA; | |
| 1280 | + tAutotune_setTimeConstant(rt, DEFTIMECONSTANT); | |
| 1281 | + | |
| 1282 | + | |
| 1283 | + | |
| 1284 | + r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices); | |
| 1285 | + r->freq = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 1286 | + r->tickOutput = (float*) leaf_alloc(sizeof(float) * r->numVoices); | |
| 1287 | + for (int i = 0; i < r->numVoices; ++i) | |
| 999 | 1288 | { |
| 1000 | − w->jump = w->readlag - readlag; | |
| 1001 | − w->readlag = readlag; | |
| 1002 | − w->xfadelength = readlag; | |
| 1003 | − w->xfadevalue = 1; | |
| 1289 | + r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 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 variables | |
| 1008 | −void tSOLAD_resetState(tSOLAD* const wp) | |
| 1302 | +void tAutotune_free(tAutotune* const rt) | |
| 1009 | 1303 | { |
| 1010 | − _tSOLAD* w = *wp; | |
| 1011 | − | |
| 1012 | − int n = LOOPSIZE + 1; | |
| 1013 | − float *buf = w->delaybuf; | |
| 1304 | + _tAutotune* r = *rt; | |
| 1014 | 1305 | |
| 1015 | − while(n--) *buf++ = 0; | |
| 1016 | − solad_init(w); | |
| 1306 | + tPeriodDetection_free(&r->pd); | |
| 1307 | + for (int i = 0; i < r->numVoices; ++i) | |
| 1308 | + { | |
| 1309 | + tPitchShift_free(&r->ps[i]); | |
| 1310 | + leaf_free(r->outBuffers[i]); | |
| 1311 | + } | |
| 1312 | + leaf_free(r->tickOutput); | |
| 1313 | + leaf_free(r->freq); | |
| 1314 | + leaf_free(r->ps); | |
| 1315 | + leaf_free(r->inBuffer); | |
| 1316 | + leaf_free(r->outBuffers); | |
| 1317 | + leaf_free(r); | |
| 1017 | 1318 | } |
| 1018 | 1319 | |
| 1019 | −/******************************************************************************/ | |
| 1020 | −/******************** private procedures **************************************/ | |
| 1021 | −/******************************************************************************/ | |
| 1022 | − | |
| 1023 | −/* | |
| 1024 | − Function pitchdown() is called to read samples from the delay buffer when pitch | |
| 1025 | − factor is between 0.25 and 1. The read pointer lags behind because of the slowed | |
| 1026 | − down speed, and it must jump forward towards the write pointer soon as there is | |
| 1027 | − sufficient space to jump. That is, if there is at least one period of the input | |
| 1028 | − signal between read pointer and write pointer. When short periods follow up on | |
| 1029 | − long periods, the read pointer may have space to jump over more than one period | |
| 1030 | − lenghts. Jump length must be [periodlength ^ 2] in any case. | |
| 1031 | − | |
| 1032 | − A linear crossfade function joins the jump-from point with the jump-to point. | |
| 1033 | − The crossfade must be completed before another read pointer jump is allowed. | |
| 1034 | − Length of the crossfade function is stored as a number of samples in terms of | |
| 1035 | − the input sample rate. This length is dynamically translated | |
| 1036 | − to a crossfade length expressed in output reading rate, according to pitch | |
| 1037 | − factor which can change before the crossfade is completed. Crossfade length does | |
| 1038 | − not cover an invariable length in periods for all pitch transposition factors. | |
| 1039 | − For pitch factors from 0.5 till 1, crossfade length is stretched in the | |
| 1040 | − output just as much as the signal itself, as crossfade speed is set to equal | |
| 1041 | − pitch factor. For pitch factors below 0.5, the read pointer wants to jump | |
| 1042 | − forward before one period is read, therefore the crossfade length as expressed | |
| 1043 | − in output periods must be shorter. Crossfade speed is set to [1 - pitchfactor] | |
| 1044 | − for those cases. Pitch factor 0.5 is the natural switch point between crossfade | |
| 1045 | − speeds [pitchfactor] and [1 - pitchfactor] because 0.5 == 1 - 0.5. The crossfade | |
| 1046 | − speed modification for pitch factors below 0.5 also means that much of the | |
| 1047 | − original signal content will be skipped. | |
| 1048 | − */ | |
| 1049 | − | |
| 1050 | − | |
| 1051 | −static void pitchdown(_tSOLAD* const w, float *out) | |
| 1320 | +void tAutotune_initToPool (tAutotune* const rt, int numVoices, int bufSize, int frameSize, tMempool* const mp) | |
| 1052 | 1321 | { |
| 1053 | − int n = w->blocksize; | |
| 1054 | − float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values! | |
| 1055 | − float pitchfactor = w->pitchfactor; | |
| 1056 | − float period = w->period; | |
| 1057 | − float readlag = w->readlag; | |
| 1058 | − float readlagstep = 1 - pitchfactor; | |
| 1059 | − float jump = w->jump; | |
| 1060 | − float xfadevalue = w->xfadevalue; | |
| 1061 | − float xfadelength = w->xfadelength; | |
| 1062 | − float xfadespeed, xfadestep, readindex, outputsample; | |
| 1322 | + _tMempool* m = *mp; | |
| 1323 | + _tAutotune* r = *rt = (_tAutotune*) mpool_alloc(sizeof(_tAutotune), m->pool); | |
| 1063 | 1324 | |
| 1064 | − if(pitchfactor > 0.5) xfadespeed = pitchfactor; | |
| 1065 | − else xfadespeed = 1 - pitchfactor; | |
| 1066 | − xfadestep = xfadespeed / xfadelength; | |
| 1325 | + r->bufSize = bufSize; | |
| 1326 | + r->frameSize = frameSize; | |
| 1327 | + r->numVoices = numVoices; | |
| 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... | |
| 1071 | − { | |
| 1072 | − if(xfadevalue <= 0) // ...but do not interrupt crossfade | |
| 1073 | − { | |
| 1074 | − jump = period; // jump forward | |
| 1075 | − while((jump * 2) < readlag) jump *= 2; // use available space | |
| 1076 | − readlag -= jump; // reduce read pointer lag | |
| 1077 | − xfadevalue = 1; // start crossfade | |
| 1078 | − xfadelength = period - 1; | |
| 1079 | − xfadestep = xfadespeed / xfadelength; | |
| 1080 | − } | |
| 1081 | − } | |
| 1082 | − | |
| 1083 | − readindex = refindex - readlag; | |
| 1084 | − outputsample = read_sample(w, readindex); | |
| 1085 | − | |
| 1086 | − if(xfadevalue > 0) | |
| 1087 | − { | |
| 1088 | − outputsample *= (1 - xfadevalue); // fadein | |
| 1089 | − outputsample += read_sample(w, readindex - jump) * xfadevalue; // fadeout | |
| 1090 | − xfadevalue -= xfadestep; | |
| 1091 | − } | |
| 1092 | − | |
| 1093 | − *out++ = outputsample; | |
| 1094 | − refindex += 1; | |
| 1095 | − readlag += readlagstep; | |
| 1344 | + r->outBuffers[i] = (float*) mpool_alloc(sizeof(float) * r->bufSize, m->pool); | |
| 1345 | + } | |
| 1346 | + | |
| 1347 | + tPeriodDetection_initToPool(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize, mp); | |
| 1348 | + | |
| 1349 | + for (int i = 0; i < r->numVoices; ++i) | |
| 1350 | + { | |
| 1351 | + tPitchShift_initToPool(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize, mp); | |
| 1096 | 1352 | } |
| 1097 | 1353 | |
| 1098 | − w->jump = jump; // state variables | |
| 1099 | − w->readlag = readlag; | |
| 1100 | − w->xfadevalue = xfadevalue; | |
| 1101 | − w->xfadelength = xfadelength; | |
| 1354 | + r->inputPeriod = 0.0f; | |
| 1102 | 1355 | } |
| 1103 | 1356 | |
| 1357 | +void tAutotune_freeFromPool (tAutotune* const rt, tMempool* const mp) | |
| 1358 | +{ | |
| 1359 | + _tMempool* m = *mp; | |
| 1360 | + _tAutotune* r = *rt; | |
| 1361 | + | |
| 1362 | + tPeriodDetection_freeFromPool(&r->pd, mp); | |
| 1363 | + for (int i = 0; i < r->numVoices; ++i) | |
| 1364 | + { | |
| 1365 | + tPitchShift_freeFromPool(&r->ps[i], mp); | |
| 1366 | + mpool_free(r->outBuffers[i], m->pool); | |
| 1367 | + } | |
| 1368 | + mpool_free(r->tickOutput, m->pool); | |
| 1369 | + mpool_free(r->freq, m->pool); | |
| 1370 | + mpool_free(r->ps, m->pool); | |
| 1371 | + mpool_free(r->inBuffer, m->pool); | |
| 1372 | + mpool_free(r->outBuffers, m->pool); | |
| 1373 | + mpool_free(r, m->pool); | |
| 1374 | +} | |
| 1104 | 1375 | |
| 1105 | −/* | |
| 1106 | − Function pitchup() for pitch factors above 1 is more complicated than | |
| 1107 | − pitchdown(). The read pointer increments faster than the write pointer and a | |
| 1108 | − backward jump must happen in time, reckoning with the crossfade region. The read | |
| 1109 | − pointer backward jump length is always one period. In order to minimize the area | |
| 1110 | − of signal duplicates, crossfade length is aimed at [period / pitchfactor]. | |
| 1111 | − This leads to a crossfade speed of [pitchfactor * pitchfactor]. | |
| 1112 | − | |
| 1113 | − Some samples for the fade out (but not all of them) must already be in the | |
| 1114 | − buffer, otherwise we will run out of input samples before the crossfade is | |
| 1115 | − completed. The ratio of past samples and future samples for a crossfade of any | |
| 1116 | − length is as follows: | |
| 1117 | − | |
| 1118 | − past samples: xfadelength * (1 - 1 / pitchfactor) | |
| 1119 | − future samples: xfadelength * (1 / pitchfactor) | |
| 1120 | − | |
| 1121 | − For example in the case of pitch factor 1.5 this would be: | |
| 1122 | − | |
| 1123 | − past samples: xfadelength * (1 - 1 / 1.5) = xfadelength * 1 / 3 | |
| 1124 | − future samples: xfadelength * (1 / 1.5) = xfadelength * 2 / 3 | |
| 1125 | − | |
| 1126 | − In the case of pitch factor 4 this would be: | |
| 1127 | − | |
| 1128 | − past samples: xfadelength * (1 - 1 / 4) = xfadelength * 3 / 4 | |
| 1129 | − future samples: xfadelength * (1 / 4) = xfadelength * 1 / 4 | |
| 1130 | − | |
| 1131 | − The read pointer lag must therefore preserve a minimum dependent on pitch | |
| 1132 | − factor. The minimum is called 'limit' here: | |
| 1133 | − | |
| 1134 | − limit = period * (pitchfactor - 1) / pitchfactor * pitchfactor | |
| 1135 | − | |
| 1136 | − Components of this expression are combined to reuse them in operations, while | |
| 1137 | − (pitchfactor - 1) is changed to (pitchfactor - 0.99) to avoid numerical | |
| 1138 | − resolution issues for pitch factors slightly above 1: | |
| 1139 | − | |
| 1140 | − xfadespeed = pitchfactor * pitchfactor | |
| 1141 | − limitfactor = (pitchfactor - 0.99) / xfadespeed | |
| 1142 | − limit = period * limitfactor | |
| 1143 | − | |
| 1144 | − When read lag is smaller than this limit, the read pointer must preferably | |
| 1145 | − jump backward, unless a previous crossfade is not yet completed. Crossfades must | |
| 1146 | − preferably be completed, unless the read pointer lag becomes smaller than zero. | |
| 1147 | − With fluctuating period lengths and pitch factors, the readpointer lag limit may | |
| 1148 | − change from one input block to the next in such a way that the actual lag is | |
| 1149 | − suddenly much smaller than the limit, and the intended crossfade length can not | |
| 1150 | − be applied. Therefore the crossfade length is simply calculated from the | |
| 1151 | − available amount of samples for all cases, like so: | |
| 1152 | − | |
| 1153 | − xfadelength = readlag / limitfactor | |
| 1154 | − | |
| 1155 | − For most occurrences, this will amount to a crossfade length reduced to | |
| 1156 | − [period / pitchfactor] in the output for pitch factors above 1, while in some | |
| 1157 | − cases it will be considerably shorter. Fortunately, an incidental aberration of | |
| 1158 | − the intended crossfade length hardly ever creates an audible artifact. The | |
| 1159 | − reason to specify preferred crossfade length according to pitch factor is to | |
| 1160 | − minimize the impression of echoes without sacrificing too much of the signal | |
| 1161 | − content. The readpointer jump length remains one period in any case. | |
| 1162 | − | |
| 1163 | − Sometimes, the input signal periodicity may decrease substantially between one | |
| 1164 | − signal block and the next. In such cases it may be possible for the read pointer | |
| 1165 | − to jump forward and reduce latency. For every signal block, a check on this | |
| 1166 | − possibility is done. A previous crossfade must be completed before a forward | |
| 1167 | − jump is allowed. | |
| 1168 | − */ | |
| 1169 | −static void pitchup(_tSOLAD* const w, float *out) | |
| 1376 | +float* tAutotune_tick(tAutotune* const rt, float sample) | |
| 1170 | 1377 | { |
| 1171 | − int n = w->blocksize; | |
| 1172 | − float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values | |
| 1173 | − float pitchfactor = w->pitchfactor; | |
| 1174 | − float period = w->period; | |
| 1175 | − float readlag = w->readlag; | |
| 1176 | − float jump = w->jump; | |
| 1177 | − float xfadevalue = w->xfadevalue; | |
| 1178 | − float xfadelength = w->xfadelength; | |
| 1378 | + _tAutotune* r = *rt; | |
| 1179 | 1379 | |
| 1180 | − float readlagstep = pitchfactor - 1; | |
| 1181 | − float xfadespeed = pitchfactor * pitchfactor; | |
| 1182 | − float xfadestep = xfadespeed / xfadelength; | |
| 1183 | − float limitfactor = (pitchfactor - (float)0.99) / xfadespeed; | |
| 1184 | − float limit = period * limitfactor; | |
| 1185 | − float readindex, outputsample; | |
| 1380 | + float tempPeriod = tPeriodDetection_findPeriod(&r->pd, sample); | |
| 1381 | + if (tempPeriod < 1000.0f) //to avoid trying to follow consonants JS | |
| 1382 | + { | |
| 1383 | + r->inputPeriod = tempPeriod; | |
| 1384 | + } | |
| 1385 | + | |
| 1386 | + for (int v = 0; v < r->numVoices; ++v) | |
| 1387 | + { | |
| 1388 | + r->tickOutput[v] = tPitchShift_shiftToFreq(&r->ps[v], r->freq[v]); | |
| 1389 | + } | |
| 1390 | + | |
| 1391 | + return r->tickOutput; | |
| 1392 | +} | |
| 1393 | + | |
| 1394 | +void tAutotune_setNumVoices(tAutotune* const rt, int numVoices) | |
| 1395 | +{ | |
| 1396 | + _tAutotune* r = *rt; | |
| 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 forward | |
| 1190 | − while((jump * 2) < (readlag - 2 * limit)) jump *= 2; // use available space | |
| 1191 | − readlag -= jump; // reduce read pointer lag | |
| 1192 | − xfadevalue = 1; // start crossfade | |
| 1193 | − xfadelength = period - 1; | |
| 1194 | − xfadestep = xfadespeed / xfadelength; | |
| 1400 | + tPitchShift_free(&r->ps[i]); | |
| 1401 | + leaf_free(r->outBuffers[i]); | |
| 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... | |
| 1200 | − { | |
| 1201 | − if((xfadevalue < 0) | (readlag < 0)) // ...but try not to interrupt crossfade | |
| 1202 | − { | |
| 1203 | − xfadelength = readlag / limitfactor; | |
| 1204 | − if(xfadelength < 1) xfadelength = 1; | |
| 1205 | − xfadestep = xfadespeed / xfadelength; | |
| 1206 | − | |
| 1207 | − jump = -period; // jump backward | |
| 1208 | − readlag += period; // increase read pointer lag | |
| 1209 | − xfadevalue = 1; // start crossfade | |
| 1210 | − } | |
| 1211 | − } | |
| 1212 | − | |
| 1213 | − readindex = refindex - readlag; | |
| 1214 | − outputsample = read_sample(w, readindex); | |
| 1215 | − | |
| 1216 | − if(xfadevalue > 0) | |
| 1217 | − { | |
| 1218 | − outputsample *= (1 - xfadevalue); | |
| 1219 | − outputsample += read_sample(w, readindex - jump) * xfadevalue; | |
| 1220 | − xfadevalue -= xfadestep; | |
| 1221 | − } | |
| 1222 | − | |
| 1223 | − *out++ = outputsample; | |
| 1224 | − refindex += 1; | |
| 1225 | − readlag -= readlagstep; | |
| 1416 | + r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 1417 | + tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize); | |
| 1226 | 1418 | } |
| 1227 | 1419 | |
| 1228 | − w->readlag = readlag; // state variables | |
| 1229 | − w->jump = jump; | |
| 1230 | − w->xfadelength = xfadelength; | |
| 1231 | − w->xfadevalue = xfadevalue; | |
| 1420 | + | |
| 1232 | 1421 | } |
| 1233 | 1422 | |
| 1234 | −// read one sample from delay buffer, with linear interpolation | |
| 1235 | −static inline float read_sample(_tSOLAD* const w, float floatindex) | |
| 1423 | +void tAutotune_setFreqs(tAutotune* const rt, float f) | |
| 1236 | 1424 | { |
| 1237 | − int index = (int)floatindex; | |
| 1238 | − float fraction = floatindex - (float)index; | |
| 1239 | − float *buf = w->delaybuf; | |
| 1240 | − index &= LOOPMASK; | |
| 1425 | + _tAutotune* r = *rt; | |
| 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 | |
| 1245 | −static void solad_init(_tSOLAD* const w) | |
| 1433 | +void tAutotune_setFreq(tAutotune* const rt, float f, int voice) | |
| 1246 | 1434 | { |
| 1247 | − w->timeindex = 0; | |
| 1248 | − w->xfadevalue = -1; | |
| 1249 | − w->period = INITPERIOD; | |
| 1250 | − w->readlag = INITPERIOD; | |
| 1251 | − w->blocksize = INITPERIOD; | |
| 1435 | + _tAutotune* r = *rt; | |
| 1436 | + | |
| 1437 | + r->freq[voice] = f; | |
| 1438 | +} | |
| 1439 | + | |
| 1440 | +void tAutotune_setTimeConstant(tAutotune* const rt, float tc) | |
| 1441 | +{ | |
| 1442 | + _tAutotune* r = *rt; | |
| 1443 | + | |
| 1444 | + r->timeConstant = tc; | |
| 1445 | + r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant); | |
| 1446 | +} | |
| 1447 | + | |
| 1448 | +void tAutotune_setHopSize(tAutotune* const rt, int hs) | |
| 1449 | +{ | |
| 1450 | + _tAutotune* r = *rt; | |
| 1451 | + | |
| 1452 | + r->hopSize = hs; | |
| 1453 | + tPeriodDetection_setHopSize(&r->pd, r->hopSize); | |
| 1454 | +} | |
| 1455 | + | |
| 1456 | +void tAutotune_setWindowSize(tAutotune* const rt, int ws) | |
| 1457 | +{ | |
| 1458 | + _tAutotune* r = *rt; | |
| 1459 | + | |
| 1460 | + r->windowSize = ws; | |
| 1461 | + tPeriodDetection_setWindowSize(&r->pd, r->windowSize); | |
| 1462 | +} | |
| 1463 | + | |
| 1464 | +float tAutotune_getInputPeriod(tAutotune* const rt) | |
| 1465 | +{ | |
| 1466 | + _tAutotune* r = *rt; | |
| 1467 | + | |
| 1468 | + return r->inputPeriod; | |
| 1469 | +} | |
| 1470 | + | |
| 1471 | +float tAutotune_getInputFreq(tAutotune* const rt) | |
| 1472 | +{ | |
| 1473 | + _tAutotune* r = *rt; | |
| 1474 | + | |
| 1475 | + return 1.0f/r->inputPeriod; | |
| 1252 | 1476 | } |
| 1477 | + | |
| 1253 | 1478 | //============================================================================================================ |
| 1254 | 1479 | // FORMANTSHIFTER |
| 1255 | 1480 | //============================================================================================================ |
| @@ -1289,8 +1514,8 @@ void tFormantShifter_init(tFormantShifter* const fsr, int bufsize, int order) · 33 unmodified lines | ||
| 1289 | 1514 | fs->invIntensity = 1.0f; |
| 1290 | 1515 | tHighpass_init(&fs->hp, 20.0f); |
| 1291 | 1516 | tHighpass_init(&fs->hp2, 20.0f); |
| 1292 | − tFeedbackLeveler_init(&fs->fbl1, 0.8f, .005f, 0.125, 1); | |
| 1293 | − tFeedbackLeveler_init(&fs->fbl2, 0.8f, .005f, 0.125, 1); | |
| 1517 | + tFeedbackLeveler_init(&fs->fbl1, 0.8f, 0.01f, 0.125f, 0); | |
| 1518 | + tFeedbackLeveler_init(&fs->fbl2, 0.8f, 0.01f, 0.125f, 0); | |
| 1294 | 1519 | } |
| 1295 | 1520 | |
| 1296 | 1521 | void tFormantShifter_free(tFormantShifter* const fsr) |
| @@ -1317,6 +1542,68 @@ void tFormantShifter_free(tFormantShifter* const fsr) · 20 unmodified lines | ||
| 1317 | 1542 | leaf_free(fs); |
| 1318 | 1543 | } |
| 1319 | 1544 | |
| 1545 | +void tFormantShifter_initToPool (tFormantShifter* const fsr, int bufsize, int order, tMempool* const mp) | |
| 1546 | +{ | |
| 1547 | + _tMempool* m = *mp; | |
| 1548 | + _tFormantShifter* fs = *fsr = (_tFormantShifter*) mpool_alloc(sizeof(_tFormantShifter), m->pool); | |
| 1549 | + | |
| 1550 | + fs->ford = order; | |
| 1551 | + fs->bufsize = bufsize; | |
| 1552 | + fs->fk = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool); | |
| 1553 | + fs->fb = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool); | |
| 1554 | + fs->fc = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool); | |
| 1555 | + fs->frb = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool); | |
| 1556 | + fs->frc = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool); | |
| 1557 | + fs->fsig = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool); | |
| 1558 | + fs->fsmooth = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool); | |
| 1559 | + fs->ftvec = (float*) mpool_alloc(sizeof(float) * fs->ford, m->pool); | |
| 1560 | + | |
| 1561 | + fs->fbuff = (float**) mpool_alloc(sizeof(float*) * fs->ford, m->pool); | |
| 1562 | + for (int i = 0; i < fs->ford; i++) | |
| 1563 | + { | |
| 1564 | + fs->fbuff[i] = (float*) mpool_alloc(sizeof(float) * fs->bufsize, m->pool); | |
| 1565 | + } | |
| 1566 | + | |
| 1567 | + fs->falph = powf(0.001f, 80.0f / (leaf.sampleRate)); | |
| 1568 | + fs->flamb = -(0.8517f*sqrtf(atanf(0.06583f*leaf.sampleRate))-0.1916f); | |
| 1569 | + fs->fhp = 0.0f; | |
| 1570 | + fs->flp = 0.0f; | |
| 1571 | + fs->flpa = powf(0.001f, 10.0f / (leaf.sampleRate)); | |
| 1572 | + fs->fmute = 1.0f; | |
| 1573 | + fs->fmutealph = powf(0.001f, 1.0f / (leaf.sampleRate)); | |
| 1574 | + fs->cbi = 0; | |
| 1575 | + fs->intensity = 1.0f; | |
| 1576 | + fs->invIntensity = 1.0f; | |
| 1577 | + tHighpass_initToPool(&fs->hp, 20.0f, mp); | |
| 1578 | + tHighpass_initToPool(&fs->hp2, 20.0f, mp); | |
| 1579 | + tFeedbackLeveler_initToPool(&fs->fbl1, 0.8f, .005f, 0.125, 1, mp); | |
| 1580 | + tFeedbackLeveler_initToPool(&fs->fbl2, 0.8f, .005f, 0.125, 1, mp); | |
| 1581 | +} | |
| 1582 | + | |
| 1583 | +void tFormantShifter_freeFromPool (tFormantShifter* const fsr, tMempool* const mp) | |
| 1584 | +{ | |
| 1585 | + _tMempool* m = *mp; | |
| 1586 | + _tFormantShifter* fs = *fsr; | |
| 1587 | + | |
| 1588 | + mpool_free(fs->fk, m->pool); | |
| 1589 | + mpool_free(fs->fb, m->pool); | |
| 1590 | + mpool_free(fs->fc, m->pool); | |
| 1591 | + mpool_free(fs->frb, m->pool); | |
| 1592 | + mpool_free(fs->frc, m->pool); | |
| 1593 | + mpool_free(fs->fsig, m->pool); | |
| 1594 | + mpool_free(fs->fsmooth, m->pool); | |
| 1595 | + mpool_free(fs->ftvec, m->pool); | |
| 1596 | + for (int i = 0; i < fs->ford; i++) | |
| 1597 | + { | |
| 1598 | + mpool_free(fs->fbuff[i], m->pool); | |
| 1599 | + } | |
| 1600 | + mpool_free(fs->fbuff, m->pool); | |
| 1601 | + tHighpass_freeFromPool(&fs->hp, mp); | |
| 1602 | + tHighpass_freeFromPool(&fs->hp2, mp); | |
| 1603 | + tFeedbackLeveler_freeFromPool(&fs->fbl1, mp); | |
| 1604 | + tFeedbackLeveler_freeFromPool(&fs->fbl2, mp); | |
| 1605 | + mpool_free(fs, m->pool); | |
| 1606 | +} | |
| 1320 | 1607 | |
| 1321 | 1608 | float tFormantShifter_tick(tFormantShifter* const fsr, float in) |
| 1322 | 1609 | { |
| @@ -1326,8 +1613,8 @@ float tFormantShifter_tick(tFormantShifter* const fsr, float in) · 3 unmodified lines | ||
| 1326 | 1613 | float tFormantShifter_remove(tFormantShifter* const fsr, float in) |
| 1327 | 1614 | { |
| 1328 | 1615 | _tFormantShifter* fs = *fsr; |
| 1329 | − in = tFeedbackLeveler_tick(&fs->fbl1, in); | |
| 1330 | − in = tHighpass_tick(&fs->hp, tanhf(in * fs->intensity)); | |
| 1616 | + in = tFeedbackLeveler_tick(&fs->fbl1, in * fs->intensity); | |
| 1617 | + in = tHighpass_tick(&fs->hp, in); | |
| 1331 | 1618 | |
| 1332 | 1619 | |
| 1333 | 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 | 1651 | fs->cbi = 0; |
| 1365 | 1652 | } |
| 1366 | − | |
| 1367 | − return fa * fs->invIntensity; | |
| 1653 | + return fa; | |
| 1654 | + //return fa * fs->invIntensity; | |
| 1368 | 1655 | } |
| 1369 | 1656 | |
| 1370 | 1657 | float tFormantShifter_add(tFormantShifter* const fsr, float in) |
| @@ -1460,8 +1747,8 @@ float tFormantShifter_add(tFormantShifter* const fsr, float in) · 89 unmodified lines | ||
| 1460 | 1747 | fs->fmute = (1.0f-tf2) + tf2*fs->fmute; |
| 1461 | 1748 | // now tf is signal output |
| 1462 | 1749 | // ...and we're done messing with formants |
| 1463 | − tf = tFeedbackLeveler_tick(&fs->fbl2, tf); | |
| 1464 | − //tf = tHighpass_tick(&fs->hp2, tanhf(tf)); | |
| 1750 | + //tf = tFeedbackLeveler_tick(&fs->fbl2, tf); | |
| 1751 | + tf = tHighpass_tick(&fs->hp2, tanhf(tf)); | |
| 1465 | 1752 | |
| 1466 | 1753 | return tf; |
| 1467 | 1754 | } |
| @@ -45,45 +45,44 @@ static float get_reflected_wave_for_ideal(tWDF* const n, float input, float inci · 44 unmodified lines | ||
| 45 | 45 | static float get_reflected_wave_for_diode(tWDF* const n, float input, float incident_wave); |
| 46 | 46 | static float get_reflected_wave_for_diode_pair(tWDF* const n, float input, float incident_wave); |
| 47 | 47 | |
| 48 | −//WDF | |
| 49 | −void tWDF_init(tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR) | |
| 48 | +static void wdf_init(tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR) | |
| 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 | 53 | r->child_left = rL; |
| 55 | 54 | r->child_right = rR; |
| 56 | − r->incident_wave_up = 0.0f; | |
| 57 | − r->incident_wave_left = 0.0f; | |
| 58 | − r->incident_wave_right = 0.0f; | |
| 59 | − r->reflected_wave_up = 0.0f; | |
| 60 | − r->reflected_wave_left = 0.0f; | |
| 61 | − r->reflected_wave_right = 0.0f; | |
| 62 | − r->sample_rate = leaf.sampleRate; | |
| 63 | − r->value = value; | |
| 55 | + r->incident_wave_up = 0.0f; | |
| 56 | + r->incident_wave_left = 0.0f; | |
| 57 | + r->incident_wave_right = 0.0f; | |
| 58 | + r->reflected_wave_up = 0.0f; | |
| 59 | + r->reflected_wave_left = 0.0f; | |
| 60 | + r->reflected_wave_right = 0.0f; | |
| 61 | + r->sample_rate = leaf.sampleRate; | |
| 62 | + r->value = value; | |
| 64 | 63 | |
| 65 | 64 | tWDF* child; |
| 66 | 65 | if (r->child_left != NULL) child = r->child_left; |
| 67 | 66 | else child = r->child_right; |
| 68 | 67 | |
| 69 | 68 | if (r->type == Resistor) |
| 70 | − { | |
| 71 | − r->port_resistance_up = r->value; | |
| 72 | − r->port_conductance_up = 1.0f / r->value; | |
| 73 | − | |
| 74 | − r->get_port_resistance = &get_port_resistance_for_resistor; | |
| 75 | − r->get_reflected_wave_up = &get_reflected_wave_for_resistor; | |
| 76 | − r->set_incident_wave = &set_incident_wave_for_leaf; | |
| 77 | − } | |
| 78 | − else if (r->type == Capacitor) | |
| 79 | − { | |
| 69 | + { | |
| 70 | + r->port_resistance_up = r->value; | |
| 71 | + r->port_conductance_up = 1.0f / r->value; | |
| 72 | + | |
| 73 | + r->get_port_resistance = &get_port_resistance_for_resistor; | |
| 74 | + r->get_reflected_wave_up = &get_reflected_wave_for_resistor; | |
| 75 | + r->set_incident_wave = &set_incident_wave_for_leaf; | |
| 76 | + } | |
| 77 | + else if (r->type == Capacitor) | |
| 78 | + { | |
| 80 | 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 discretization | |
| 82 | − | |
| 83 | − r->get_port_resistance = &get_port_resistance_for_capacitor; | |
| 84 | − r->get_reflected_wave_up = &get_reflected_wave_for_capacitor; | |
| 85 | − r->set_incident_wave = &set_incident_wave_for_leaf; | |
| 86 | − } | |
| 80 | + r->port_resistance_up = 1.0f / r->port_conductance_up; //based on trapezoidal discretization | |
| 81 | + | |
| 82 | + r->get_port_resistance = &get_port_resistance_for_capacitor; | |
| 83 | + r->get_reflected_wave_up = &get_reflected_wave_for_capacitor; | |
| 84 | + r->set_incident_wave = &set_incident_wave_for_leaf; | |
| 85 | + } | |
| 87 | 86 | else if (r->type == Inductor) |
| 88 | 87 | { |
| 89 | 88 | 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 | 92 | r->get_reflected_wave_up = &get_reflected_wave_for_capacitor; // same as capacitor |
| 94 | 93 | r->set_incident_wave = &set_incident_wave_for_leaf_inverted; |
| 95 | 94 | } |
| 96 | − else if (r->type == ResistiveSource) | |
| 97 | − { | |
| 95 | + else if (r->type == ResistiveSource) | |
| 96 | + { | |
| 98 | 97 | r->port_resistance_up = r->value; |
| 99 | 98 | r->port_conductance_up = 1.0f / r->port_resistance_up; |
| 100 | 99 | |
| 101 | 100 | r->get_port_resistance = &get_port_resistance_for_resistive; |
| 102 | 101 | r->get_reflected_wave_up = &get_reflected_wave_for_resistive; |
| 103 | 102 | r->set_incident_wave = &set_incident_wave_for_leaf; |
| 104 | − } | |
| 103 | + } | |
| 105 | 104 | else if (r->type == Inverter) |
| 106 | 105 | { |
| 107 | 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 | 163 | r->get_port_resistance = &get_port_resistance_for_root; |
| 165 | 164 | } |
| 166 | 165 | } |
| 166 | +//WDF | |
| 167 | +void tWDF_init(tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR) | |
| 168 | +{ | |
| 169 | + *wdf = (_tWDF*) leaf_alloc(sizeof(_tWDF)); | |
| 170 | + | |
| 171 | + wdf_init(wdf, type, value, rL, rR); | |
| 172 | +} | |
| 167 | 173 | |
| 168 | 174 | void tWDF_free(tWDF* const wdf) |
| 169 | 175 | { |
| @@ -172,6 +178,22 @@ void tWDF_free(tWDF* const wdf) · 2 unmodified lines | ||
| 172 | 178 | leaf_free(r); |
| 173 | 179 | } |
| 174 | 180 | |
| 181 | +void tWDF_initToPool (tWDF* const wdf, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR, tMempool* const mp) | |
| 182 | +{ | |
| 183 | + _tMempool* m = *mp; | |
| 184 | + *wdf = (_tWDF*) mpool_alloc(sizeof(_tWDF), m->pool); | |
| 185 | + | |
| 186 | + wdf_init(wdf, type, value, rL, rR); | |
| 187 | +} | |
| 188 | + | |
| 189 | +void tWDF_freeFromPool (tWDF* const wdf, tMempool* const mp) | |
| 190 | +{ | |
| 191 | + _tMempool* m = *mp; | |
| 192 | + _tWDF* r = *wdf; | |
| 193 | + | |
| 194 | + mpool_free(r, m->pool); | |
| 195 | +} | |
| 196 | + | |
| 175 | 197 | float tWDF_tick(tWDF* const wdf, float sample, tWDF* const outputPoint, uint8_t paramsChanged) |
| 176 | 198 | { |
| 177 | 199 | _tWDF* r = *wdf; |
| @@ -62,7 +62,6 @@ void tEnvelope_init(tEnvelope* const envlp, float attack, float decay, oBool · 61 unmodified lines | ||
| 62 | 62 | env->attackInc = env->inc_buff[attackIndex]; |
| 63 | 63 | env->decayInc = env->inc_buff[decayIndex]; |
| 64 | 64 | env->rampInc = env->inc_buff[rampIndex]; |
| 65 | − | |
| 66 | 65 | } |
| 67 | 66 | |
| 68 | 67 | void tEnvelope_free(tEnvelope* const envlp) |
| @@ -71,6 +70,54 @@ void tEnvelope_free(tEnvelope* const envlp) · 2 unmodified lines | ||
| 71 | 70 | leaf_free(env); |
| 72 | 71 | } |
| 73 | 72 | |
| 73 | +void tEnvelope_initToPool (tEnvelope* const envlp, float attack, float decay, oBool loop, tMempool* const mp) | |
| 74 | +{ | |
| 75 | + _tMempool* m = *mp; | |
| 76 | + _tEnvelope* env = *envlp = (_tEnvelope*) mpool_alloc(sizeof(_tEnvelope), m->pool); | |
| 77 | + | |
| 78 | + env->exp_buff = exp_decay; | |
| 79 | + env->inc_buff = attack_decay_inc; | |
| 80 | + env->buff_size = sizeof(exp_decay); | |
| 81 | + | |
| 82 | + env->loop = loop; | |
| 83 | + | |
| 84 | + if (attack > 8192.0f) | |
| 85 | + attack = 8192.0f; | |
| 86 | + if (attack < 0.0f) | |
| 87 | + attack = 0.0f; | |
| 88 | + | |
| 89 | + if (decay > 8192.0f) | |
| 90 | + decay = 8192.0f; | |
| 91 | + if (decay < 0.0f) | |
| 92 | + decay = 0.0f; | |
| 93 | + | |
| 94 | + int16_t attackIndex = ((int16_t)(attack * 8.0f))-1; | |
| 95 | + int16_t decayIndex = ((int16_t)(decay * 8.0f))-1; | |
| 96 | + int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1; | |
| 97 | + | |
| 98 | + if (attackIndex < 0) | |
| 99 | + attackIndex = 0; | |
| 100 | + if (decayIndex < 0) | |
| 101 | + decayIndex = 0; | |
| 102 | + if (rampIndex < 0) | |
| 103 | + rampIndex = 0; | |
| 104 | + | |
| 105 | + env->inRamp = OFALSE; | |
| 106 | + env->inAttack = OFALSE; | |
| 107 | + env->inDecay = OFALSE; | |
| 108 | + | |
| 109 | + env->attackInc = env->inc_buff[attackIndex]; | |
| 110 | + env->decayInc = env->inc_buff[decayIndex]; | |
| 111 | + env->rampInc = env->inc_buff[rampIndex]; | |
| 112 | +} | |
| 113 | + | |
| 114 | +void tEnvelope_freeFromPool (tEnvelope* const envlp, tMempool* const mp) | |
| 115 | +{ | |
| 116 | + _tMempool* m = *mp; | |
| 117 | + _tEnvelope* env = *envlp; | |
| 118 | + mpool_free(env, m->pool); | |
| 119 | +} | |
| 120 | + | |
| 74 | 121 | void tEnvelope_setAttack(tEnvelope* const envlp, float attack) |
| 75 | 122 | { |
| 76 | 123 | _tEnvelope* env = *envlp; |
| @@ -270,6 +317,71 @@ void tADSR_free(tADSR* const adsrenv) · 193 unmodified lines | ||
| 270 | 317 | leaf_free(adsr); |
| 271 | 318 | } |
| 272 | 319 | |
| 320 | +void tADSR_initToPool (tADSR* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp) | |
| 321 | +{ | |
| 322 | + _tMempool* m = *mp; | |
| 323 | + _tADSR* adsr = *adsrenv = (_tADSR*) mpool_alloc(sizeof(_tADSR), m->pool); | |
| 324 | + | |
| 325 | + adsr->exp_buff = exp_decay; | |
| 326 | + adsr->inc_buff = attack_decay_inc; | |
| 327 | + adsr->buff_size = sizeof(exp_decay); | |
| 328 | + | |
| 329 | + if (attack > 8192.0f) | |
| 330 | + attack = 8192.0f; | |
| 331 | + if (attack < 0.0f) | |
| 332 | + attack = 0.0f; | |
| 333 | + | |
| 334 | + if (decay > 8192.0f) | |
| 335 | + decay = 8192.0f; | |
| 336 | + if (decay < 0.0f) | |
| 337 | + decay = 0.0f; | |
| 338 | + | |
| 339 | + if (sustain > 1.0f) | |
| 340 | + sustain = 1.0f; | |
| 341 | + if (sustain < 0.0f) | |
| 342 | + sustain = 0.0f; | |
| 343 | + | |
| 344 | + if (release > 8192.0f) | |
| 345 | + release = 8192.0f; | |
| 346 | + if (release < 0.0f) | |
| 347 | + release = 0.0f; | |
| 348 | + | |
| 349 | + int16_t attackIndex = ((int16_t)(attack * 8.0f))-1; | |
| 350 | + int16_t decayIndex = ((int16_t)(decay * 8.0f))-1; | |
| 351 | + int16_t releaseIndex = ((int16_t)(release * 8.0f))-1; | |
| 352 | + int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1; | |
| 353 | + | |
| 354 | + if (attackIndex < 0) | |
| 355 | + attackIndex = 0; | |
| 356 | + if (decayIndex < 0) | |
| 357 | + decayIndex = 0; | |
| 358 | + if (releaseIndex < 0) | |
| 359 | + releaseIndex = 0; | |
| 360 | + if (rampIndex < 0) | |
| 361 | + rampIndex = 0; | |
| 362 | + | |
| 363 | + adsr->inRamp = OFALSE; | |
| 364 | + adsr->inAttack = OFALSE; | |
| 365 | + adsr->inDecay = OFALSE; | |
| 366 | + adsr->inSustain = OFALSE; | |
| 367 | + adsr->inRelease = OFALSE; | |
| 368 | + | |
| 369 | + adsr->sustain = sustain; | |
| 370 | + | |
| 371 | + adsr->attackInc = adsr->inc_buff[attackIndex]; | |
| 372 | + adsr->decayInc = adsr->inc_buff[decayIndex]; | |
| 373 | + adsr->releaseInc = adsr->inc_buff[releaseIndex]; | |
| 374 | + adsr->rampInc = adsr->inc_buff[rampIndex]; | |
| 375 | +} | |
| 376 | + | |
| 377 | +void tADSR_freeFromPool (tADSR* const adsrenv, tMempool* const mp) | |
| 378 | +{ | |
| 379 | + _tMempool* m = *mp; | |
| 380 | + _tADSR* adsr = *adsrenv; | |
| 381 | + | |
| 382 | + mpool_free(adsr, m->pool); | |
| 383 | +} | |
| 384 | + | |
| 273 | 385 | void tADSR_setAttack(tADSR* const adsrenv, float attack) |
| 274 | 386 | { |
| 275 | 387 | _tADSR* adsr = *adsrenv; |
| @@ -479,6 +591,37 @@ void tRamp_free(tRamp* const r) · 203 unmodified lines | ||
| 479 | 591 | leaf_free(ramp); |
| 480 | 592 | } |
| 481 | 593 | |
| 594 | +void tRamp_initToPool (tRamp* const r, float time, int samples_per_tick, tMempool* const mp) | |
| 595 | +{ | |
| 596 | + _tMempool* m = *mp; | |
| 597 | + _tRamp* ramp = *r = (_tRamp*) mpool_alloc(sizeof(_tRamp), m->pool); | |
| 598 | + | |
| 599 | + ramp->inv_sr_ms = 1.0f/(leaf.sampleRate*0.001f); | |
| 600 | + ramp->minimum_time = ramp->inv_sr_ms * samples_per_tick; | |
| 601 | + ramp->curr = 0.0f; | |
| 602 | + ramp->dest = 0.0f; | |
| 603 | + | |
| 604 | + if (time < ramp->minimum_time) | |
| 605 | + { | |
| 606 | + ramp->time = ramp->minimum_time; | |
| 607 | + } | |
| 608 | + else | |
| 609 | + { | |
| 610 | + ramp->time = time; | |
| 611 | + } | |
| 612 | + | |
| 613 | + ramp->samples_per_tick = samples_per_tick; | |
| 614 | + ramp->inc = ((ramp->dest - ramp->curr) / ramp->time * ramp->inv_sr_ms) * (float)ramp->samples_per_tick; | |
| 615 | +} | |
| 616 | + | |
| 617 | +void tRamp_freeFromPool (tRamp* const r, tMempool* const mp) | |
| 618 | +{ | |
| 619 | + _tMempool* m = *mp; | |
| 620 | + _tRamp* ramp = *r; | |
| 621 | + | |
| 622 | + mpool_free(ramp, m->pool); | |
| 623 | +} | |
| 624 | + | |
| 482 | 625 | void tRamp_setTime(tRamp* const ramp, float time) |
| 483 | 626 | { |
| 484 | 627 | _tRamp* r = *ramp; |
| @@ -560,6 +703,27 @@ void tExpSmooth_free(tExpSmooth* const expsmooth) · 75 unmodified lines | ||
| 560 | 703 | leaf_free(smooth); |
| 561 | 704 | } |
| 562 | 705 | |
| 706 | +void tExpSmooth_initToPool (tExpSmooth* const expsmooth, float val, float factor, tMempool* const mp) | |
| 707 | +{ | |
| 708 | + _tMempool* m = *mp; | |
| 709 | + _tExpSmooth* smooth = *expsmooth = (_tExpSmooth*) mpool_alloc(sizeof(_tExpSmooth), m->pool); | |
| 710 | + | |
| 711 | + smooth->curr=val; | |
| 712 | + smooth->dest=val; | |
| 713 | + if (factor<0) factor=0; | |
| 714 | + if (factor>1) factor=1; | |
| 715 | + smooth->factor=factor; | |
| 716 | + smooth->oneminusfactor=1.0f-factor; | |
| 717 | +} | |
| 718 | + | |
| 719 | +void tExpSmooth_freeFromPool (tExpSmooth* const expsmooth, tMempool* const mp) | |
| 720 | +{ | |
| 721 | + _tMempool* m = *mp; | |
| 722 | + _tExpSmooth* smooth = *expsmooth; | |
| 723 | + | |
| 724 | + mpool_free(smooth, m->pool); | |
| 725 | +} | |
| 726 | + | |
| 563 | 727 | void tExpSmooth_setFactor(tExpSmooth* const expsmooth, float factor) |
| 564 | 728 | { // 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 | 729 | _tExpSmooth* smooth = *expsmooth; |
| @@ -40,6 +40,27 @@ void tAllpass_free(tAllpass* const ft) · 39 unmodified lines | ||
| 40 | 40 | leaf_free(f); |
| 41 | 41 | } |
| 42 | 42 | |
| 43 | +void tAllpass_initToPool (tAllpass* const ft, float initDelay, uint32_t maxDelay, tMempool* const mp) | |
| 44 | +{ | |
| 45 | + _tMempool* m = *mp; | |
| 46 | + _tAllpass* f = *ft = (_tAllpass*) mpool_alloc(sizeof(_tAllpass), m->pool); | |
| 47 | + | |
| 48 | + f->gain = 0.7f; | |
| 49 | + | |
| 50 | + f->lastOut = 0.0f; | |
| 51 | + | |
| 52 | + tLinearDelay_initToPool(&f->delay, initDelay, maxDelay, mp); | |
| 53 | +} | |
| 54 | + | |
| 55 | +void tAllpass_freeFromPool (tAllpass* const ft, tMempool* const mp) | |
| 56 | +{ | |
| 57 | + _tMempool* m = *mp; | |
| 58 | + _tAllpass* f = *ft; | |
| 59 | + | |
| 60 | + tLinearDelay_freeFromPool(&f->delay, mp); | |
| 61 | + mpool_free(f, m->pool); | |
| 62 | +} | |
| 63 | + | |
| 43 | 64 | void tAllpass_setDelay(tAllpass* const ft, float delay) |
| 44 | 65 | { |
| 45 | 66 | _tAllpass* f = *ft; |
| @@ -67,77 +88,236 @@ float tAllpass_tick(tAllpass* const ft, float input) · 21 unmodified lines | ||
| 67 | 88 | return f->lastOut; |
| 68 | 89 | } |
| 69 | 90 | |
| 70 | −void tButterworth_init(tButterworth* const ft, int N, float f1, float f2) | |
| 91 | +// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 92 | +void tOnePole_init(tOnePole* const ft, float freq) | |
| 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; | |
| 75 | − f->f2 = f2; | |
| 76 | − f->gain = 1.0f; | |
| 96 | + f->gain = 1.0f; | |
| 97 | + f->a0 = 1.0; | |
| 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) | |
| 83 | − { | |
| 84 | − tSVF_init(&f->low[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N))); | |
| 85 | − tSVF_init(&f->high[i], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N))); | |
| 86 | − } | |
| 105 | +void tOnePole_free(tOnePole* const ft) | |
| 106 | +{ | |
| 107 | + _tOnePole* f = *ft; | |
| 108 | + | |
| 109 | + leaf_free(f); | |
| 87 | 110 | } |
| 88 | 111 | |
| 89 | −void tButterworth_free(tButterworth* const ft) | |
| 112 | +void 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) | |
| 94 | − { | |
| 95 | − tSVF_free(&f->low[i]); | |
| 96 | − tSVF_free(&f->high[i]); | |
| 97 | − } | |
| 117 | + f->gain = 1.0f; | |
| 118 | + f->a0 = 1.0; | |
| 119 | + | |
| 120 | + tOnePole_setFreq(ft, freq); | |
| 121 | + | |
| 122 | + f->lastIn = 0.0f; | |
| 123 | + f->lastOut = 0.0f; | |
| 124 | +} | |
| 125 | + | |
| 126 | +void tOnePole_freeFromPool (tOnePole* const ft, tMempool* const mp) | |
| 127 | +{ | |
| 128 | + _tMempool* m = *mp; | |
| 129 | + _tOnePole* f = *ft; | |
| 130 | + | |
| 131 | + mpool_free(f, m->pool); | |
| 132 | +} | |
| 133 | + | |
| 134 | +void tOnePole_setB0(tOnePole* const ft, float b0) | |
| 135 | +{ | |
| 136 | + _tOnePole* f = *ft; | |
| 137 | + f->b0 = b0; | |
| 138 | +} | |
| 139 | + | |
| 140 | +void tOnePole_setA1(tOnePole* const ft, float a1) | |
| 141 | +{ | |
| 142 | + _tOnePole* f = *ft; | |
| 143 | + if (a1 >= 1.0f) a1 = 0.999999f; | |
| 144 | + f->a1 = a1; | |
| 145 | +} | |
| 146 | + | |
| 147 | +void tOnePole_setPole(tOnePole* const ft, float thePole) | |
| 148 | +{ | |
| 149 | + _tOnePole* f = *ft; | |
| 150 | + | |
| 151 | + if (thePole >= 1.0f) thePole = 0.999999f; | |
| 152 | + | |
| 153 | + // Normalize coefficients for peak unity gain. | |
| 154 | + if (thePole > 0.0f) f->b0 = (1.0f - thePole); | |
| 155 | + else f->b0 = (1.0f + thePole); | |
| 156 | + | |
| 157 | + f->a1 = -thePole; | |
| 158 | +} | |
| 159 | + | |
| 160 | +void tOnePole_setFreq (tOnePole* const ft, float freq) | |
| 161 | +{ | |
| 162 | + _tOnePole* f = *ft; | |
| 163 | + f->b0 = freq * leaf.twoPiTimesInvSampleRate; | |
| 164 | + f->b0 = LEAF_clip(0.0f, f->b0, 1.0f); | |
| 165 | + f->a1 = 1.0f - f->b0; | |
| 166 | +} | |
| 167 | + | |
| 168 | +void tOnePole_setCoefficients(tOnePole* const ft, float b0, float a1) | |
| 169 | +{ | |
| 170 | + _tOnePole* f = *ft; | |
| 171 | + if (a1 >= 1.0f) a1 = 0.999999f; | |
| 172 | + f->b0 = b0; | |
| 173 | + f->a1 = a1; | |
| 174 | +} | |
| 175 | + | |
| 176 | +void tOnePole_setGain(tOnePole* const ft, float gain) | |
| 177 | +{ | |
| 178 | + _tOnePole* f = *ft; | |
| 179 | + f->gain = gain; | |
| 180 | +} | |
| 181 | + | |
| 182 | +float tOnePole_tick(tOnePole* const ft, float input) | |
| 183 | +{ | |
| 184 | + _tOnePole* f = *ft; | |
| 185 | + | |
| 186 | + float in = input * f->gain; | |
| 187 | + float out = (f->b0 * in) + (f->a1 * f->lastOut); | |
| 188 | + | |
| 189 | + f->lastIn = in; | |
| 190 | + f->lastOut = out; | |
| 191 | + | |
| 192 | + return out; | |
| 193 | +} | |
| 194 | + | |
| 195 | +// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoPole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 196 | +void tTwoPole_init(tTwoPole* const ft) | |
| 197 | +{ | |
| 198 | + _tTwoPole* f = *ft = (_tTwoPole*) leaf_alloc(sizeof(_tTwoPole)); | |
| 199 | + | |
| 200 | + f->gain = 1.0f; | |
| 201 | + f->a0 = 1.0; | |
| 202 | + f->b0 = 1.0; | |
| 203 | + | |
| 204 | + f->lastOut[0] = 0.0f; | |
| 205 | + f->lastOut[1] = 0.0f; | |
| 206 | +} | |
| 207 | + | |
| 208 | +void tTwoPole_free(tTwoPole* const ft) | |
| 209 | +{ | |
| 210 | + _tTwoPole* f = *ft; | |
| 98 | 211 | |
| 99 | 212 | leaf_free(f); |
| 100 | 213 | } |
| 101 | 214 | |
| 102 | −float tButterworth_tick(tButterworth* const ft, float samp) | |
| 215 | +void 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) | |
| 107 | − { | |
| 108 | − samp = tSVF_tick(&f->low[i],samp); | |
| 109 | − samp = tSVF_tick(&f->high[i],samp); | |
| 110 | − } | |
| 111 | − return samp; | |
| 224 | + f->lastOut[0] = 0.0f; | |
| 225 | + f->lastOut[1] = 0.0f; | |
| 112 | 226 | } |
| 113 | 227 | |
| 114 | −void tButterworth_setF1(tButterworth* const ft, float f1) | |
| 228 | +void 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; | |
| 119 | − for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->low[i], f1); | |
| 233 | + mpool_free(f, m->pool); | |
| 120 | 234 | } |
| 121 | 235 | |
| 122 | −void tButterworth_setF2(tButterworth* const ft, float f2) | |
| 236 | +float tTwoPole_tick(tTwoPole* const ft, float input) | |
| 123 | 237 | { |
| 124 | − _tButterworth* f = *ft; | |
| 238 | + _tTwoPole* f = *ft; | |
| 125 | 239 | |
| 126 | − f->f2 = f2; | |
| 127 | − for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->high[i], f2); | |
| 240 | + float in = input * f->gain; | |
| 241 | + float out = (f->b0 * in) - (f->a1 * f->lastOut[0]) - (f->a2 * f->lastOut[1]); | |
| 242 | + | |
| 243 | + f->lastOut[1] = f->lastOut[0]; | |
| 244 | + f->lastOut[0] = out; | |
| 245 | + | |
| 246 | + return out; | |
| 128 | 247 | } |
| 129 | 248 | |
| 130 | −void tButterworth_setFreqs(tButterworth* const ft, float f1, float f2) | |
| 249 | +void tTwoPole_setB0(tTwoPole* const ft, float b0) | |
| 131 | 250 | { |
| 132 | − _tButterworth* f = *ft; | |
| 251 | + _tTwoPole* f = *ft; | |
| 252 | + f->b0 = b0; | |
| 253 | +} | |
| 254 | + | |
| 255 | +void tTwoPole_setA1(tTwoPole* const ft, float a1) | |
| 256 | +{ | |
| 257 | + _tTwoPole* f = *ft; | |
| 258 | + f->a1 = a1; | |
| 259 | +} | |
| 260 | + | |
| 261 | +void tTwoPole_setA2(tTwoPole* const ft, float a2) | |
| 262 | +{ | |
| 263 | + _tTwoPole* f = *ft; | |
| 264 | + f->a2 = a2; | |
| 265 | +} | |
| 266 | + | |
| 267 | + | |
| 268 | +void tTwoPole_setResonance(tTwoPole* const ft, float frequency, float radius, oBool normalize) | |
| 269 | +{ | |
| 270 | + _tTwoPole* f = *ft; | |
| 271 | + | |
| 272 | + if (frequency < 0.0f) frequency = 0.0f; | |
| 273 | + if (frequency > (leaf.sampleRate * 0.49f)) frequency = leaf.sampleRate * 0.49f; | |
| 274 | + if (radius < 0.0f) radius = 0.0f; | |
| 275 | + if (radius >= 1.0f) radius = 0.999999f; | |
| 276 | + | |
| 277 | + f->radius = radius; | |
| 278 | + f->frequency = frequency; | |
| 279 | + f->normalize = normalize; | |
| 280 | + | |
| 281 | + f->a2 = radius * radius; | |
| 282 | + f->a1 = -2.0f * radius * cosf(frequency * leaf.twoPiTimesInvSampleRate); | |
| 283 | + | |
| 284 | + if ( normalize ) | |
| 285 | + { | |
| 286 | + // Normalize the filter gain ... not terribly efficient. | |
| 287 | + float real = 1 - radius + (f->a2 - radius) * cosf(2 * frequency * leaf.twoPiTimesInvSampleRate); | |
| 288 | + float imag = (f->a2 - radius) * sinf(2 * frequency * leaf.twoPiTimesInvSampleRate); | |
| 289 | + f->b0 = sqrtf( powf(real, 2) + powf(imag, 2) ); | |
| 290 | + } | |
| 291 | +} | |
| 292 | + | |
| 293 | +void tTwoPole_setCoefficients(tTwoPole* const ft, float b0, float a1, float a2) | |
| 294 | +{ | |
| 295 | + _tTwoPole* f = *ft; | |
| 296 | + f->b0 = b0; | |
| 297 | + f->a1 = a1; | |
| 298 | + f->a2 = a2; | |
| 299 | +} | |
| 300 | + | |
| 301 | +void tTwoPole_setGain(tTwoPole* const ft, float gain) | |
| 302 | +{ | |
| 303 | + _tTwoPole* f = *ft; | |
| 304 | + f->gain = gain; | |
| 305 | +} | |
| 306 | + | |
| 307 | +void tTwoPoleSampleRateChanged (tTwoPole* const ft) | |
| 308 | +{ | |
| 309 | + _tTwoPole* f = *ft; | |
| 310 | + | |
| 311 | + f->a2 = f->radius * f->radius; | |
| 312 | + f->a1 = -2.0f * f->radius * cosf(f->frequency * leaf.twoPiTimesInvSampleRate); | |
| 133 | 313 | |
| 134 | − f->f1 = f1; | |
| 135 | − f->f2 = f2; | |
| 136 | − for(int i = 0; i < ((f->N)/2); ++i) | |
| 137 | − { | |
| 138 | − tSVF_setFreq(&f->low[i], f1); | |
| 139 | − tSVF_setFreq(&f->high[i], f2); | |
| 140 | − } | |
| 314 | + if ( f->normalize ) | |
| 315 | + { | |
| 316 | + // Normalize the filter gain ... not terribly efficient. | |
| 317 | + float real = 1 - f->radius + (f->a2 - f->radius) * cosf(2 * f->frequency * leaf.twoPiTimesInvSampleRate); | |
| 318 | + float imag = (f->a2 - f->radius) * sinf(2 * f->frequency * leaf.twoPiTimesInvSampleRate); | |
| 319 | + f->b0 = sqrtf( powf(real, 2) + powf(imag, 2) ); | |
| 320 | + } | |
| 141 | 321 | } |
| 142 | 322 | |
| 143 | 323 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OneZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // |
| @@ -158,6 +338,25 @@ void tOneZero_free(tOneZero* const ft) · 14 unmodified lines | ||
| 158 | 338 | leaf_free(f); |
| 159 | 339 | } |
| 160 | 340 | |
| 341 | +void tOneZero_initToPool (tOneZero* const ft, float theZero, tMempool* const mp) | |
| 342 | +{ | |
| 343 | + _tMempool* m = *mp; | |
| 344 | + _tOneZero* f = *ft = (_tOneZero*) mpool_alloc(sizeof(_tOneZero), m->pool); | |
| 345 | + | |
| 346 | + f->gain = 1.0f; | |
| 347 | + f->lastIn = 0.0f; | |
| 348 | + f->lastOut = 0.0f; | |
| 349 | + tOneZero_setZero(ft, theZero); | |
| 350 | +} | |
| 351 | + | |
| 352 | +void tOneZero_freeFromPool (tOneZero* const ft, tMempool* const mp) | |
| 353 | +{ | |
| 354 | + _tMempool* m = *mp; | |
| 355 | + _tOneZero* f = *ft; | |
| 356 | + | |
| 357 | + mpool_free(f, m->pool); | |
| 358 | +} | |
| 359 | + | |
| 161 | 360 | float tOneZero_tick(tOneZero* const ft, float input) |
| 162 | 361 | { |
| 163 | 362 | _tOneZero* f = *ft; |
| @@ -254,6 +453,24 @@ void tTwoZero_free(tTwoZero* const ft) · 90 unmodified lines | ||
| 254 | 453 | leaf_free(f); |
| 255 | 454 | } |
| 256 | 455 | |
| 456 | +void tTwoZero_initToPool (tTwoZero* const ft, tMempool* const mp) | |
| 457 | +{ | |
| 458 | + _tMempool* m = *mp; | |
| 459 | + _tTwoZero* f = *ft = (_tTwoZero*) mpool_alloc(sizeof(_tTwoZero), m->pool); | |
| 460 | + | |
| 461 | + f->gain = 1.0f; | |
| 462 | + f->lastIn[0] = 0.0f; | |
| 463 | + f->lastIn[1] = 0.0f; | |
| 464 | +} | |
| 465 | + | |
| 466 | +void tTwoZero_freeFromPool (tTwoZero* const ft, tMempool* const mp) | |
| 467 | +{ | |
| 468 | + _tMempool* m = *mp; | |
| 469 | + _tTwoZero* f = *ft; | |
| 470 | + | |
| 471 | + mpool_free(f, m->pool); | |
| 472 | +} | |
| 473 | + | |
| 257 | 474 | float tTwoZero_tick(tTwoZero* const ft, float input) |
| 258 | 475 | { |
| 259 | 476 | _tTwoZero* f = *ft; |
| @@ -324,199 +541,30 @@ void tTwoZeroSampleRateChanged(tTwoZero* const ft) · 64 unmodified lines | ||
| 324 | 541 | tTwoZero_setNotch(ft, f->frequency, f->radius); |
| 325 | 542 | } |
| 326 | 543 | |
| 327 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 328 | −void tOnePole_init(tOnePole* const ft, float freq) | |
| 544 | +// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PoleZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 545 | +void 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 | 549 | f->gain = 1.0f; |
| 550 | + f->b0 = 1.0; | |
| 333 | 551 | f->a0 = 1.0; |
| 334 | − | |
| 335 | − tOnePole_setFreq(ft, freq); | |
| 336 | 552 | |
| 337 | 553 | f->lastIn = 0.0f; |
| 338 | 554 | f->lastOut = 0.0f; |
| 339 | 555 | } |
| 340 | 556 | |
| 341 | −void tOnePole_free(tOnePole* const ft) | |
| 342 | −{ | |
| 343 | − _tOnePole* f = *ft; | |
| 344 | − | |
| 345 | − leaf_free(f); | |
| 346 | −} | |
| 347 | − | |
| 348 | −void tOnePole_setB0(tOnePole* const ft, float b0) | |
| 349 | −{ | |
| 350 | − _tOnePole* f = *ft; | |
| 351 | − f->b0 = b0; | |
| 352 | −} | |
| 353 | − | |
| 354 | −void tOnePole_setA1(tOnePole* const ft, float a1) | |
| 355 | −{ | |
| 356 | − _tOnePole* f = *ft; | |
| 357 | − if (a1 >= 1.0f) a1 = 0.999999f; | |
| 358 | − f->a1 = a1; | |
| 359 | −} | |
| 360 | − | |
| 361 | −void tOnePole_setPole(tOnePole* const ft, float thePole) | |
| 362 | −{ | |
| 363 | − _tOnePole* f = *ft; | |
| 364 | − | |
| 365 | − if (thePole >= 1.0f) thePole = 0.999999f; | |
| 366 | − | |
| 367 | − // Normalize coefficients for peak unity gain. | |
| 368 | − if (thePole > 0.0f) f->b0 = (1.0f - thePole); | |
| 369 | − else f->b0 = (1.0f + thePole); | |
| 370 | − | |
| 371 | − f->a1 = -thePole; | |
| 372 | −} | |
| 373 | − | |
| 374 | −void tOnePole_setFreq (tOnePole* const ft, float freq) | |
| 375 | −{ | |
| 376 | − _tOnePole* f = *ft; | |
| 377 | − f->b0 = freq * leaf.twoPiTimesInvSampleRate; | |
| 378 | − f->b0 = LEAF_clip(0.0f, f->b0, 1.0f); | |
| 379 | − f->a1 = 1.0f - f->b0; | |
| 380 | −} | |
| 381 | − | |
| 382 | −void tOnePole_setCoefficients(tOnePole* const ft, float b0, float a1) | |
| 383 | −{ | |
| 384 | − _tOnePole* f = *ft; | |
| 385 | − if (a1 >= 1.0f) a1 = 0.999999f; | |
| 386 | − f->b0 = b0; | |
| 387 | − f->a1 = a1; | |
| 388 | −} | |
| 389 | − | |
| 390 | −void tOnePole_setGain(tOnePole* const ft, float gain) | |
| 391 | −{ | |
| 392 | − _tOnePole* f = *ft; | |
| 393 | − f->gain = gain; | |
| 394 | −} | |
| 395 | − | |
| 396 | −float tOnePole_tick(tOnePole* const ft, float input) | |
| 397 | −{ | |
| 398 | − _tOnePole* f = *ft; | |
| 399 | − | |
| 400 | − float in = input * f->gain; | |
| 401 | − float out = (f->b0 * in) + (f->a1 * f->lastOut); | |
| 402 | − | |
| 403 | − f->lastIn = in; | |
| 404 | − f->lastOut = out; | |
| 405 | − | |
| 406 | − return out; | |
| 407 | −} | |
| 408 | − | |
| 409 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoPole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 410 | −void tTwoPole_init(tTwoPole* const ft) | |
| 411 | −{ | |
| 412 | − _tTwoPole* f = *ft = (_tTwoPole*) leaf_alloc(sizeof(_tTwoPole)); | |
| 413 | − | |
| 414 | − f->gain = 1.0f; | |
| 415 | − f->a0 = 1.0; | |
| 416 | − f->b0 = 1.0; | |
| 417 | − | |
| 418 | − f->lastOut[0] = 0.0f; | |
| 419 | − f->lastOut[1] = 0.0f; | |
| 420 | −} | |
| 421 | − | |
| 422 | −void tTwoPole_free(tTwoPole* const ft) | |
| 557 | +void tPoleZero_free(tPoleZero* const pzf) | |
| 423 | 558 | { |
| 424 | − _tTwoPole* f = *ft; | |
| 559 | + _tPoleZero* f = *pzf; | |
| 425 | 560 | |
| 426 | 561 | leaf_free(f); |
| 427 | 562 | } |
| 428 | 563 | |
| 429 | −float tTwoPole_tick(tTwoPole* const ft, float input) | |
| 564 | +void tPoleZero_initToPool (tPoleZero* const pzf, tMempool* const mp) | |
| 430 | 565 | { |
| 431 | − _tTwoPole* f = *ft; | |
| 432 | − | |
| 433 | − float in = input * f->gain; | |
| 434 | − float out = (f->b0 * in) - (f->a1 * f->lastOut[0]) - (f->a2 * f->lastOut[1]); | |
| 435 | − | |
| 436 | − f->lastOut[1] = f->lastOut[0]; | |
| 437 | − f->lastOut[0] = out; | |
| 438 | − | |
| 439 | − return out; | |
| 440 | −} | |
| 441 | − | |
| 442 | −void tTwoPole_setB0(tTwoPole* const ft, float b0) | |
| 443 | −{ | |
| 444 | − _tTwoPole* f = *ft; | |
| 445 | − f->b0 = b0; | |
| 446 | −} | |
| 447 | − | |
| 448 | −void tTwoPole_setA1(tTwoPole* const ft, float a1) | |
| 449 | −{ | |
| 450 | − _tTwoPole* f = *ft; | |
| 451 | − f->a1 = a1; | |
| 452 | −} | |
| 453 | − | |
| 454 | −void tTwoPole_setA2(tTwoPole* const ft, float a2) | |
| 455 | −{ | |
| 456 | − _tTwoPole* f = *ft; | |
| 457 | − f->a2 = a2; | |
| 458 | −} | |
| 459 | − | |
| 460 | − | |
| 461 | −void tTwoPole_setResonance(tTwoPole* const ft, float frequency, float radius, oBool normalize) | |
| 462 | −{ | |
| 463 | − _tTwoPole* f = *ft; | |
| 464 | − | |
| 465 | − if (frequency < 0.0f) frequency = 0.0f; | |
| 466 | − if (frequency > (leaf.sampleRate * 0.49f)) frequency = leaf.sampleRate * 0.49f; | |
| 467 | − if (radius < 0.0f) radius = 0.0f; | |
| 468 | − if (radius >= 1.0f) radius = 0.999999f; | |
| 469 | − | |
| 470 | − f->radius = radius; | |
| 471 | − f->frequency = frequency; | |
| 472 | − f->normalize = normalize; | |
| 473 | − | |
| 474 | − f->a2 = radius * radius; | |
| 475 | − f->a1 = -2.0f * radius * cosf(frequency * leaf.twoPiTimesInvSampleRate); | |
| 476 | − | |
| 477 | − if ( normalize ) | |
| 478 | − { | |
| 479 | − // Normalize the filter gain ... not terribly efficient. | |
| 480 | − float real = 1 - radius + (f->a2 - radius) * cosf(2 * frequency * leaf.twoPiTimesInvSampleRate); | |
| 481 | − float imag = (f->a2 - radius) * sinf(2 * frequency * leaf.twoPiTimesInvSampleRate); | |
| 482 | − f->b0 = sqrtf( powf(real, 2) + powf(imag, 2) ); | |
| 483 | − } | |
| 484 | −} | |
| 485 | − | |
| 486 | −void tTwoPole_setCoefficients(tTwoPole* const ft, float b0, float a1, float a2) | |
| 487 | −{ | |
| 488 | − _tTwoPole* f = *ft; | |
| 489 | − f->b0 = b0; | |
| 490 | − f->a1 = a1; | |
| 491 | − f->a2 = a2; | |
| 492 | −} | |
| 493 | − | |
| 494 | −void tTwoPole_setGain(tTwoPole* const ft, float gain) | |
| 495 | −{ | |
| 496 | − _tTwoPole* f = *ft; | |
| 497 | − f->gain = gain; | |
| 498 | −} | |
| 499 | − | |
| 500 | −void tTwoPoleSampleRateChanged (tTwoPole* const ft) | |
| 501 | −{ | |
| 502 | − _tTwoPole* f = *ft; | |
| 503 | − | |
| 504 | − f->a2 = f->radius * f->radius; | |
| 505 | − f->a1 = -2.0f * f->radius * cosf(f->frequency * leaf.twoPiTimesInvSampleRate); | |
| 506 | − | |
| 507 | − if ( f->normalize ) | |
| 508 | − { | |
| 509 | − // Normalize the filter gain ... not terribly efficient. | |
| 510 | − float real = 1 - f->radius + (f->a2 - f->radius) * cosf(2 * f->frequency * leaf.twoPiTimesInvSampleRate); | |
| 511 | − float imag = (f->a2 - f->radius) * sinf(2 * f->frequency * leaf.twoPiTimesInvSampleRate); | |
| 512 | − f->b0 = sqrtf( powf(real, 2) + powf(imag, 2) ); | |
| 513 | − } | |
| 514 | −} | |
| 515 | − | |
| 516 | −// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PoleZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // | |
| 517 | −void tPoleZero_init(tPoleZero* const pzf) | |
| 518 | −{ | |
| 519 | − _tPoleZero* f = *pzf = (_tPoleZero*) leaf_alloc(sizeof(_tPoleZero)); | |
| 566 | + _tMempool* m = *mp; | |
| 567 | + _tPoleZero* f = *pzf = (_tPoleZero*) mpool_alloc(sizeof(_tPoleZero), m->pool); | |
| 520 | 568 | |
| 521 | 569 | f->gain = 1.0f; |
| 522 | 570 | f->b0 = 1.0; |
| @@ -526,11 +574,12 @@ void tPoleZero_init(tPoleZero* const pzf) · 3 unmodified lines | ||
| 526 | 574 | f->lastOut = 0.0f; |
| 527 | 575 | } |
| 528 | 576 | |
| 529 | −void tPoleZero_free(tPoleZero* const pzf) | |
| 577 | +void tPoleZero_freeFromPool (tPoleZero* const pzf, tMempool* const mp) | |
| 530 | 578 | { |
| 579 | + _tMempool* m = *mp; | |
| 531 | 580 | _tPoleZero* f = *pzf; |
| 532 | 581 | |
| 533 | − leaf_free(f); | |
| 582 | + mpool_free(f, m->pool); | |
| 534 | 583 | } |
| 535 | 584 | |
| 536 | 585 | void tPoleZero_setB0(tPoleZero* const pzf, float b0) |
| @@ -643,6 +692,30 @@ void tBiQuad_free(tBiQuad* const ft) · 106 unmodified lines | ||
| 643 | 692 | leaf_free(f); |
| 644 | 693 | } |
| 645 | 694 | |
| 695 | +void tBiQuad_initToPool (tBiQuad* const ft, tMempool* const mp) | |
| 696 | +{ | |
| 697 | + _tMempool* m = *mp; | |
| 698 | + _tBiQuad* f = *ft = (_tBiQuad*) mpool_alloc(sizeof(_tBiQuad), m->pool); | |
| 699 | + | |
| 700 | + f->gain = 1.0f; | |
| 701 | + | |
| 702 | + f->b0 = 0.0f; | |
| 703 | + f->a0 = 0.0f; | |
| 704 | + | |
| 705 | + f->lastIn[0] = 0.0f; | |
| 706 | + f->lastIn[1] = 0.0f; | |
| 707 | + f->lastOut[0] = 0.0f; | |
| 708 | + f->lastOut[1] = 0.0f; | |
| 709 | +} | |
| 710 | + | |
| 711 | +void tBiQuad_freeFromPool (tBiQuad* const ft, tMempool* const mp) | |
| 712 | +{ | |
| 713 | + _tMempool* m = *mp; | |
| 714 | + _tBiQuad* f = *ft; | |
| 715 | + | |
| 716 | + mpool_free(f, m->pool); | |
| 717 | +} | |
| 718 | + | |
| 646 | 719 | float tBiQuad_tick(tBiQuad* const ft, float input) |
| 647 | 720 | { |
| 648 | 721 | _tBiQuad* f = *ft; |
| @@ -766,78 +839,54 @@ void tBiQuadSampleRateChanged(tBiQuad* const ft) · 117 unmodified lines | ||
| 766 | 839 | } |
| 767 | 840 | } |
| 768 | 841 | |
| 769 | −/* Highpass */ | |
| 770 | −void tHighpass_init(tHighpass* const ft, float freq) | |
| 842 | +// Less efficient, more accurate version of SVF, in which cutoff frequency is taken as floating point Hz value and tanf | |
| 843 | +// is calculated when frequency changes. | |
| 844 | +void tSVF_init(tSVF* const svff, SVFType type, float freq, float Q) | |
| 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)); | |
| 775 | − f->ys = 0.0f; | |
| 776 | − f->xs = 0.0f; | |
| 848 | + svf->type = type; | |
| 777 | 849 | |
| 778 | − f->frequency = freq; | |
| 779 | −} | |
| 780 | − | |
| 781 | −void tHighpass_free(tHighpass* const ft) | |
| 782 | −{ | |
| 783 | − _tHighpass* f = *ft; | |
| 850 | + svf->ic1eq = 0; | |
| 851 | + svf->ic2eq = 0; | |
| 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 | |
| 788 | −void tHighpass_setFreq(tHighpass* const ft, float freq) | |
| 860 | +void tSVF_free(tSVF* const svff) | |
| 789 | 861 | { |
| 790 | − _tHighpass* f = *ft; | |
| 791 | − f->frequency = freq; | |
| 792 | − f->R = (1.0f - (freq * leaf.twoPiTimesInvSampleRate)); | |
| 862 | + _tSVF* svf = *svff; | |
| 793 | 863 | |
| 864 | + leaf_free(svf); | |
| 794 | 865 | } |
| 795 | 866 | |
| 796 | −float tHighpass_getFreq(tHighpass* const ft) | |
| 797 | −{ | |
| 798 | − _tHighpass* f = *ft; | |
| 799 | − return f->frequency; | |
| 800 | −} | |
| 801 | − | |
| 802 | −// From JOS DC Blocker | |
| 803 | −float tHighpass_tick(tHighpass* const ft, float x) | |
| 804 | −{ | |
| 805 | − _tHighpass* f = *ft; | |
| 806 | − f->ys = x - f->xs + f->R * f->ys; | |
| 807 | − f->xs = x; | |
| 808 | − return f->ys; | |
| 809 | −} | |
| 810 | − | |
| 811 | −void tHighpassSampleRateChanged(tHighpass* const ft) | |
| 812 | −{ | |
| 813 | − _tHighpass* f = *ft; | |
| 814 | − f->R = (1.0f-((f->frequency * 2.0f * 3.14f) * leaf.invSampleRate)); | |
| 815 | −} | |
| 816 | − | |
| 817 | −// Less efficient, more accurate version of SVF, in which cutoff frequency is taken as floating point Hz value and tanf | |
| 818 | −// is calculated when frequency changes. | |
| 819 | −void tSVF_init(tSVF* const svff, SVFType type, float freq, float Q) | |
| 867 | +void tSVF_initToPool (tSVF* const svff, SVFType type, float freq, float Q, tMempool* const mp) | |
| 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 | 872 | svf->type = type; |
| 824 | 873 | |
| 825 | 874 | svf->ic1eq = 0; |
| 826 | 875 | svf->ic2eq = 0; |
| 827 | 876 | |
| 828 | − float a1,a2,a3,g,k; | |
| 829 | 877 | svf->g = tanf(PI * freq * leaf.invSampleRate); |
| 830 | 878 | svf->k = 1.0f/Q; |
| 831 | 879 | svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k)); |
| 832 | − svf->a2 = g*a1; | |
| 833 | − svf->a3 = g*a2; | |
| 880 | + svf->a2 = svf->g*svf->a1; | |
| 881 | + svf->a3 = svf->g*svf->a2; | |
| 834 | 882 | } |
| 835 | 883 | |
| 836 | −void tSVF_free(tSVF* const svff) | |
| 884 | +void tSVF_freeFromPool (tSVF* const svff, tMempool* const mp) | |
| 837 | 885 | { |
| 886 | + _tMempool* m = *mp; | |
| 838 | 887 | _tSVF* svf = *svff; |
| 839 | 888 | |
| 840 | − leaf_free(svf); | |
| 889 | + mpool_free(svf, m->pool); | |
| 841 | 890 | } |
| 842 | 891 | |
| 843 | 892 | float tSVF_tick(tSVF* const svff, float v0) |
| @@ -890,12 +939,11 @@ void tEfficientSVF_init(tEfficientSVF* const svff, SVFType type, uint16_t inpu · 46 unmodified lines | ||
| 890 | 939 | svf->ic1eq = 0; |
| 891 | 940 | svf->ic2eq = 0; |
| 892 | 941 | |
| 893 | − float a1,a2,a3,g,k; | |
| 894 | 942 | svf->g = filtertan[input]; |
| 895 | 943 | svf->k = 1.0f/Q; |
| 896 | − svf->a1 = 1.0f/(1.0f+g*(g+k)); | |
| 897 | − svf->a2 = g*a1; | |
| 898 | − svf->a3 = g*a2; | |
| 944 | + svf->a1 = 1.0f/(1.0f+svf->g*(svf->g+svf->k)); | |
| 945 | + svf->a2 = svf->g*svf->a1; | |
| 946 | + svf->a3 = svf->g*svf->a2; | |
| 899 | 947 | } |
| 900 | 948 | |
| 901 | 949 | void tEfficientSVF_free(tEfficientSVF* const svff) |
| @@ -905,6 +953,31 @@ void tEfficientSVF_free(tEfficientSVF* const svff) · 3 unmodified lines | ||
| 905 | 953 | leaf_free(svf); |
| 906 | 954 | } |
| 907 | 955 | |
| 956 | +void tEfficientSVF_initToPool (tEfficientSVF* const svff, SVFType type, uint16_t input, float Q, tMempool* const mp) | |
| 957 | +{ | |
| 958 | + _tMempool* m = *mp; | |
| 959 | + _tEfficientSVF* svf = *svff = (_tEfficientSVF*) mpool_alloc(sizeof(_tEfficientSVF), m->pool); | |
| 960 | + | |
| 961 | + svf->type = type; | |
| 962 | + | |
| 963 | + svf->ic1eq = 0; | |
| 964 | + svf->ic2eq = 0; | |
| 965 | + | |
| 966 | + svf->g = filtertan[input]; | |
| 967 | + svf->k = 1.0f/Q; | |
| 968 | + svf->a1 = 1.0f/(1.0f+svf->g*(svf->g+svf->k)); | |
| 969 | + svf->a2 = svf->g*svf->a1; | |
| 970 | + svf->a3 = svf->g*svf->a2; | |
| 971 | +} | |
| 972 | + | |
| 973 | +void tEfficientSVF_freeFromPool (tEfficientSVF* const svff, tMempool* const mp) | |
| 974 | +{ | |
| 975 | + _tMempool* m = *mp; | |
| 976 | + _tEfficientSVF* svf = *svff; | |
| 977 | + | |
| 978 | + mpool_free(svf, m->pool); | |
| 979 | +} | |
| 980 | + | |
| 908 | 981 | float tEfficientSVF_tick(tEfficientSVF* const svff, float v0) |
| 909 | 982 | { |
| 910 | 983 | _tEfficientSVF* svf = *svff; |
| @@ -945,6 +1018,181 @@ void tEfficientSVF_setQ(tEfficientSVF* const svff, float Q) · 34 unmodified lines | ||
| 945 | 1018 | svf->a3 = svf->g * svf->a2; |
| 946 | 1019 | } |
| 947 | 1020 | |
| 1021 | +/* Highpass */ | |
| 1022 | +void tHighpass_init(tHighpass* const ft, float freq) | |
| 1023 | +{ | |
| 1024 | + _tHighpass* f = *ft = (_tHighpass*) leaf_alloc(sizeof(_tHighpass)); | |
| 1025 | + | |
| 1026 | + f->R = (1.0f - (freq * leaf.twoPiTimesInvSampleRate)); | |
| 1027 | + f->ys = 0.0f; | |
| 1028 | + f->xs = 0.0f; | |
| 1029 | + | |
| 1030 | + f->frequency = freq; | |
| 1031 | +} | |
| 1032 | + | |
| 1033 | +void tHighpass_free(tHighpass* const ft) | |
| 1034 | +{ | |
| 1035 | + _tHighpass* f = *ft; | |
| 1036 | + | |
| 1037 | + leaf_free(f); | |
| 1038 | +} | |
| 1039 | + | |
| 1040 | +void tHighpass_initToPool (tHighpass* const ft, float freq, tMempool* const mp) | |
| 1041 | +{ | |
| 1042 | + _tMempool* m = *mp; | |
| 1043 | + _tHighpass* f = *ft = (_tHighpass*) mpool_alloc(sizeof(_tHighpass), m->pool); | |
| 1044 | + | |
| 1045 | + f->R = (1.0f - (freq * leaf.twoPiTimesInvSampleRate)); | |
| 1046 | + f->ys = 0.0f; | |
| 1047 | + f->xs = 0.0f; | |
| 1048 | + | |
| 1049 | + f->frequency = freq; | |
| 1050 | +} | |
| 1051 | + | |
| 1052 | +void tHighpass_freeFromPool (tHighpass* const ft, tMempool* const mp) | |
| 1053 | +{ | |
| 1054 | + _tMempool* m = *mp; | |
| 1055 | + _tHighpass* f = *ft; | |
| 1056 | + | |
| 1057 | + mpool_free(f, m->pool); | |
| 1058 | +} | |
| 1059 | + | |
| 1060 | +void tHighpass_setFreq(tHighpass* const ft, float freq) | |
| 1061 | +{ | |
| 1062 | + _tHighpass* f = *ft; | |
| 1063 | + f->frequency = freq; | |
| 1064 | + f->R = (1.0f - (freq * leaf.twoPiTimesInvSampleRate)); | |
| 1065 | + | |
| 1066 | +} | |
| 1067 | + | |
| 1068 | +float tHighpass_getFreq(tHighpass* const ft) | |
| 1069 | +{ | |
| 1070 | + _tHighpass* f = *ft; | |
| 1071 | + return f->frequency; | |
| 1072 | +} | |
| 1073 | + | |
| 1074 | +// From JOS DC Blocker | |
| 1075 | +float tHighpass_tick(tHighpass* const ft, float x) | |
| 1076 | +{ | |
| 1077 | + _tHighpass* f = *ft; | |
| 1078 | + f->ys = x - f->xs + f->R * f->ys; | |
| 1079 | + f->xs = x; | |
| 1080 | + return f->ys; | |
| 1081 | +} | |
| 1082 | + | |
| 1083 | +void tHighpassSampleRateChanged(tHighpass* const ft) | |
| 1084 | +{ | |
| 1085 | + _tHighpass* f = *ft; | |
| 1086 | + f->R = (1.0f-((f->frequency * 2.0f * 3.14f) * leaf.invSampleRate)); | |
| 1087 | +} | |
| 1088 | + | |
| 1089 | +void tButterworth_init(tButterworth* const ft, int N, float f1, float f2) | |
| 1090 | +{ | |
| 1091 | + _tButterworth* f = *ft = (_tButterworth*) leaf_alloc(sizeof(_tButterworth)); | |
| 1092 | + | |
| 1093 | + f->f1 = f1; | |
| 1094 | + f->f2 = f2; | |
| 1095 | + f->gain = 1.0f; | |
| 1096 | + | |
| 1097 | + f->N = N; | |
| 1098 | + | |
| 1099 | + if (f->N > NUM_SVF_BW) f->N = NUM_SVF_BW; | |
| 1100 | + | |
| 1101 | + for(int i = 0; i < N/2; ++i) | |
| 1102 | + { | |
| 1103 | + tSVF_init(&f->low[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N))); | |
| 1104 | + tSVF_init(&f->high[i], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N))); | |
| 1105 | + } | |
| 1106 | +} | |
| 1107 | + | |
| 1108 | +void tButterworth_free(tButterworth* const ft) | |
| 1109 | +{ | |
| 1110 | + _tButterworth* f = *ft; | |
| 1111 | + | |
| 1112 | + for(int i = 0; i < f->N/2; ++i) | |
| 1113 | + { | |
| 1114 | + tSVF_free(&f->low[i]); | |
| 1115 | + tSVF_free(&f->high[i]); | |
| 1116 | + } | |
| 1117 | + | |
| 1118 | + leaf_free(f); | |
| 1119 | +} | |
| 1120 | + | |
| 1121 | +void tButterworth_initToPool (tButterworth* const ft, int N, float f1, float f2, tMempool* const mp) | |
| 1122 | +{ | |
| 1123 | + _tMempool* m = *mp; | |
| 1124 | + _tButterworth* f = *ft = (_tButterworth*) mpool_alloc(sizeof(_tButterworth), m->pool); | |
| 1125 | + | |
| 1126 | + f->f1 = f1; | |
| 1127 | + f->f2 = f2; | |
| 1128 | + f->gain = 1.0f; | |
| 1129 | + | |
| 1130 | + f->N = N; | |
| 1131 | + | |
| 1132 | + if (f->N > NUM_SVF_BW) f->N = NUM_SVF_BW; | |
| 1133 | + | |
| 1134 | + for(int i = 0; i < N/2; ++i) | |
| 1135 | + { | |
| 1136 | + tSVF_initToPool(&f->low[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)), mp); | |
| 1137 | + tSVF_initToPool(&f->high[i], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)), mp); | |
| 1138 | + } | |
| 1139 | +} | |
| 1140 | + | |
| 1141 | +void tButterworth_freeFromPool (tButterworth* const ft, tMempool* const mp) | |
| 1142 | +{ | |
| 1143 | + _tMempool* m = *mp; | |
| 1144 | + _tButterworth* f = *ft; | |
| 1145 | + | |
| 1146 | + for(int i = 0; i < f->N/2; ++i) | |
| 1147 | + { | |
| 1148 | + tSVF_freeFromPool(&f->low[i], mp); | |
| 1149 | + tSVF_freeFromPool(&f->high[i], mp); | |
| 1150 | + } | |
| 1151 | + | |
| 1152 | + mpool_free(f, m->pool); | |
| 1153 | +} | |
| 1154 | + | |
| 1155 | +float tButterworth_tick(tButterworth* const ft, float samp) | |
| 1156 | +{ | |
| 1157 | + _tButterworth* f = *ft; | |
| 1158 | + | |
| 1159 | + for(int i = 0; i < ((f->N)/2); ++i) | |
| 1160 | + { | |
| 1161 | + samp = tSVF_tick(&f->low[i],samp); | |
| 1162 | + samp = tSVF_tick(&f->high[i],samp); | |
| 1163 | + } | |
| 1164 | + return samp; | |
| 1165 | +} | |
| 1166 | + | |
| 1167 | +void tButterworth_setF1(tButterworth* const ft, float f1) | |
| 1168 | +{ | |
| 1169 | + _tButterworth* f = *ft; | |
| 1170 | + | |
| 1171 | + f->f1 = f1; | |
| 1172 | + for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->low[i], f1); | |
| 1173 | +} | |
| 1174 | + | |
| 1175 | +void tButterworth_setF2(tButterworth* const ft, float f2) | |
| 1176 | +{ | |
| 1177 | + _tButterworth* f = *ft; | |
| 1178 | + | |
| 1179 | + f->f2 = f2; | |
| 1180 | + for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->high[i], f2); | |
| 1181 | +} | |
| 1182 | + | |
| 1183 | +void tButterworth_setFreqs(tButterworth* const ft, float f1, float f2) | |
| 1184 | +{ | |
| 1185 | + _tButterworth* f = *ft; | |
| 1186 | + | |
| 1187 | + f->f1 = f1; | |
| 1188 | + f->f2 = f2; | |
| 1189 | + for(int i = 0; i < ((f->N)/2); ++i) | |
| 1190 | + { | |
| 1191 | + tSVF_setFreq(&f->low[i], f1); | |
| 1192 | + tSVF_setFreq(&f->high[i], f2); | |
| 1193 | + } | |
| 1194 | +} | |
| 1195 | + | |
| 948 | 1196 | void tFIR_init(tFIR* const firf, float* coeffs, int numTaps) |
| 949 | 1197 | { |
| 950 | 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 | 1203 | for (int i = 0; i < fir->numTaps; ++i) fir->past[i] = 0.0f; |
| 956 | 1204 | } |
| 957 | 1205 | |
| 1206 | +void tFIR_free(tFIR* const firf) | |
| 1207 | +{ | |
| 1208 | + _tFIR* fir = *firf; | |
| 1209 | + | |
| 1210 | + leaf_free(fir->past); | |
| 1211 | + leaf_free(fir); | |
| 1212 | +} | |
| 1213 | + | |
| 1214 | +void tFIR_initToPool (tFIR* const firf, float* coeffs, int numTaps, tMempool* const mp) | |
| 1215 | +{ | |
| 1216 | + _tMempool* m = *mp; | |
| 1217 | + _tFIR* fir = *firf = (_tFIR*) mpool_alloc(sizeof(_tFIR), m->pool); | |
| 1218 | + | |
| 1219 | + fir->numTaps = numTaps; | |
| 1220 | + fir->coeff = coeffs; | |
| 1221 | + fir->past = (float*) mpool_alloc(sizeof(float) * fir->numTaps, m->pool); | |
| 1222 | + for (int i = 0; i < fir->numTaps; ++i) fir->past[i] = 0.0f; | |
| 1223 | +} | |
| 1224 | + | |
| 1225 | +void tFIR_freeFromPool (tFIR* const firf, tMempool* const mp) | |
| 1226 | +{ | |
| 1227 | + _tMempool* m = *mp; | |
| 1228 | + _tFIR* fir = *firf; | |
| 1229 | + | |
| 1230 | + mpool_free(fir->past, m->pool); | |
| 1231 | + mpool_free(fir, m->pool); | |
| 1232 | +} | |
| 1233 | + | |
| 958 | 1234 | float tFIR_tick(tFIR* const firf, float input) |
| 959 | 1235 | { |
| 960 | 1236 | _tFIR* fir = *firf; |
| @@ -965,11 +1241,3 @@ float tFIR_tick(tFIR* const firf, float input) · 4 unmodified lines | ||
| 965 | 1241 | for (int i = fir->numTaps-1; i > 0; --i) fir->past[i] = fir->past[i-1]; |
| 966 | 1242 | return y; |
| 967 | 1243 | } |
| 968 | − | |
| 969 | −void tFIR_free(tFIR* const firf) | |
| 970 | −{ | |
| 971 | − _tFIR* fir = *firf; | |
| 972 | − | |
| 973 | − leaf_free(fir->past); | |
| 974 | − leaf_free(fir); | |
| 975 | −} | |
| @@ -63,6 +63,53 @@ void t808Cowebell_free(t808Cowbell* const cowbellInst) · 62 unmodified lines | ||
| 63 | 63 | leaf_free(cowbell); |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | +void t808Cowbell_initToPool (t808Cowbell* const cowbellInst, int useStick, tMempool* const mp) | |
| 67 | +{ | |
| 68 | + _tMempool* m = *mp; | |
| 69 | + _t808Cowbell* cowbell = *cowbellInst = (_t808Cowbell*) mpool_alloc(sizeof(_t808Cowbell), m->pool); | |
| 70 | + | |
| 71 | + tSquare_initToPool(&cowbell->p[0], mp); | |
| 72 | + tSquare_setFreq(&cowbell->p[0], 540.0f); | |
| 73 | + | |
| 74 | + tSquare_initToPool(&cowbell->p[1], mp); | |
| 75 | + tSquare_setFreq(&cowbell->p[1], 1.48148f * 540.0f); | |
| 76 | + | |
| 77 | + cowbell->oscMix = 0.5f; | |
| 78 | + | |
| 79 | + tSVF_initToPool(&cowbell->bandpassOsc, SVFTypeBandpass, 2500, 1.0f, mp); | |
| 80 | + | |
| 81 | + tSVF_initToPool(&cowbell->bandpassStick, SVFTypeBandpass, 1800, 1.0f, mp); | |
| 82 | + | |
| 83 | + tEnvelope_initToPool(&cowbell->envGain, 5.0f, 100.0f, OFALSE, mp); | |
| 84 | + | |
| 85 | + tEnvelope_initToPool(&cowbell->envFilter, 5.0, 100.0f, OFALSE, mp); | |
| 86 | + | |
| 87 | + tHighpass_initToPool(&cowbell->highpass, 1000.0f, mp); | |
| 88 | + | |
| 89 | + tNoise_initToPool(&cowbell->stick, WhiteNoise, mp); | |
| 90 | + | |
| 91 | + tEnvelope_initToPool(&cowbell->envStick, 5.0f, 5.0f, 0, mp); | |
| 92 | + | |
| 93 | + cowbell->useStick = useStick; | |
| 94 | +} | |
| 95 | + | |
| 96 | +void t808Cowbell_freeFromPool (t808Cowbell* const cowbellInst, tMempool* const mp) | |
| 97 | +{ | |
| 98 | + _tMempool* m = *mp; | |
| 99 | + _t808Cowbell* cowbell = *cowbellInst; | |
| 100 | + | |
| 101 | + tSquare_freeFromPool(&cowbell->p[0], mp); | |
| 102 | + tSquare_freeFromPool(&cowbell->p[1], mp); | |
| 103 | + tSVF_freeFromPool(&cowbell->bandpassOsc, mp); | |
| 104 | + tSVF_freeFromPool(&cowbell->bandpassStick, mp); | |
| 105 | + tEnvelope_freeFromPool(&cowbell->envGain, mp); | |
| 106 | + tEnvelope_freeFromPool(&cowbell->envFilter, mp); | |
| 107 | + tHighpass_freeFromPool(&cowbell->highpass, mp); | |
| 108 | + tNoise_freeFromPool(&cowbell->stick, mp); | |
| 109 | + tEnvelope_freeFromPool(&cowbell->envStick, mp); | |
| 110 | + mpool_free(cowbell, m->pool); | |
| 111 | +} | |
| 112 | + | |
| 66 | 113 | void t808Cowbell_on(t808Cowbell* const cowbellInst, float vel) |
| 67 | 114 | { |
| 68 | 115 | _t808Cowbell* cowbell = *cowbellInst; |
| @@ -192,6 +239,64 @@ void t808Hihat_free(t808Hihat* const hihatInst) · 123 unmodified lines | ||
| 192 | 239 | leaf_free(hihat); |
| 193 | 240 | } |
| 194 | 241 | |
| 242 | +void t808Hihat_initToPool (t808Hihat* const hihatInst, tMempool* const mp) | |
| 243 | +{ | |
| 244 | + _tMempool* m = *mp; | |
| 245 | + _t808Hihat* hihat = *hihatInst = (_t808Hihat*) mpool_alloc(sizeof(_t808Hihat), m->pool); | |
| 246 | + | |
| 247 | + for (int i = 0; i < 6; i++) | |
| 248 | + { | |
| 249 | + tSquare_initToPool(&hihat->p[i], mp); | |
| 250 | + } | |
| 251 | + | |
| 252 | + tNoise_initToPool(&hihat->stick, PinkNoise, mp); | |
| 253 | + tNoise_initToPool(&hihat->n, WhiteNoise, mp); | |
| 254 | + | |
| 255 | + // need to fix SVF to be generic | |
| 256 | + tSVF_initToPool(&hihat->bandpassStick, SVFTypeBandpass,2500.0f,1.2f, mp); | |
| 257 | + tSVF_initToPool(&hihat->bandpassOsc, SVFTypeBandpass,3500.0f,0.3f, mp); | |
| 258 | + | |
| 259 | + tEnvelope_initToPool(&hihat->envGain, 0.0f, 50.0f, OFALSE, mp); | |
| 260 | + tEnvelope_initToPool(&hihat->envStick, 0.0f, 7.0f, OFALSE, mp); | |
| 261 | + | |
| 262 | + | |
| 263 | + tHighpass_initToPool(&hihat->highpass, 7000.0f, mp); | |
| 264 | + | |
| 265 | + hihat->freq = 40.0f; | |
| 266 | + hihat->stretch = 0.0f; | |
| 267 | + | |
| 268 | + tSquare_setFreq(&hihat->p[0], 2.0f * hihat->freq); | |
| 269 | + tSquare_setFreq(&hihat->p[1], 3.00f * hihat->freq); | |
| 270 | + tSquare_setFreq(&hihat->p[2], 4.16f * hihat->freq); | |
| 271 | + tSquare_setFreq(&hihat->p[3], 5.43f * hihat->freq); | |
| 272 | + tSquare_setFreq(&hihat->p[4], 6.79f * hihat->freq); | |
| 273 | + tSquare_setFreq(&hihat->p[5], 8.21f * hihat->freq); | |
| 274 | +} | |
| 275 | + | |
| 276 | +void t808Hihat_freeFromPool (t808Hihat* const hihatInst, tMempool* const mp) | |
| 277 | +{ | |
| 278 | + _tMempool* m = *mp; | |
| 279 | + _t808Hihat* hihat = *hihatInst; | |
| 280 | + | |
| 281 | + for (int i = 0; i < 6; i++) | |
| 282 | + { | |
| 283 | + tSquare_freeFromPool(&hihat->p[i], mp); | |
| 284 | + } | |
| 285 | + | |
| 286 | + tNoise_freeFromPool(&hihat->stick, mp); | |
| 287 | + tNoise_freeFromPool(&hihat->n, mp); | |
| 288 | + | |
| 289 | + // need to fix SVF to be generic | |
| 290 | + tSVF_freeFromPool(&hihat->bandpassStick, mp); | |
| 291 | + tSVF_freeFromPool(&hihat->bandpassOsc, mp); | |
| 292 | + tEnvelope_freeFromPool(&hihat->envGain, mp); | |
| 293 | + tEnvelope_freeFromPool(&hihat->envStick, mp); | |
| 294 | + | |
| 295 | + tHighpass_freeFromPool(&hihat->highpass, mp); | |
| 296 | + | |
| 297 | + mpool_free(hihat, m->pool); | |
| 298 | +} | |
| 299 | + | |
| 195 | 300 | void t808Hihat_on(t808Hihat* const hihatInst, float vel) |
| 196 | 301 | { |
| 197 | 302 | _t808Hihat* hihat = *hihatInst; |
| @@ -289,8 +394,6 @@ void t808Hihat_setStickBandPassQ(t808Hihat* const hihatInst, float Q) · 91 unmodified lines | ||
| 289 | 394 | tSVF_setQ(&hihat->bandpassStick,Q); |
| 290 | 395 | } |
| 291 | 396 | |
| 292 | − | |
| 293 | − | |
| 294 | 397 | void t808Hihat_setOscFreq(t808Hihat* const hihatInst, float freq) |
| 295 | 398 | { |
| 296 | 399 | _t808Hihat* hihat = *hihatInst; |
| @@ -348,6 +451,57 @@ void t808Snare_free (t808Snare* const snareInst) · 51 unmodified lines | ||
| 348 | 451 | leaf_free(snare); |
| 349 | 452 | } |
| 350 | 453 | |
| 454 | +void t808Snare_initToPool (t808Snare* const snareInst, tMempool* const mp) | |
| 455 | +{ | |
| 456 | + _tMempool* m = *mp; | |
| 457 | + _t808Snare* snare = *snareInst = (_t808Snare*) mpool_alloc(sizeof(_t808Snare), m->pool); | |
| 458 | + | |
| 459 | + float ratio[2] = {1.0, 1.5}; | |
| 460 | + for (int i = 0; i < 2; i++) | |
| 461 | + { | |
| 462 | + tTriangle_initToPool(&snare->tone[i], mp); | |
| 463 | + | |
| 464 | + tTriangle_setFreq(&snare->tone[i], ratio[i] * 400.0f); | |
| 465 | + tSVF_initToPool(&snare->toneLowpass[i], SVFTypeLowpass, 4000, 1.0f, mp); | |
| 466 | + tEnvelope_initToPool(&snare->toneEnvOsc[i], 0.0f, 50.0f, OFALSE, mp); | |
| 467 | + tEnvelope_initToPool(&snare->toneEnvGain[i], 1.0f, 150.0f, OFALSE, mp); | |
| 468 | + tEnvelope_initToPool(&snare->toneEnvFilter[i], 1.0f, 2000.0f, OFALSE, mp); | |
| 469 | + | |
| 470 | + snare->toneGain[i] = 0.5f; | |
| 471 | + } | |
| 472 | + | |
| 473 | + snare->tone1Freq = ratio[0] * 100.0f; | |
| 474 | + snare->tone2Freq = ratio[1] * 100.0f; | |
| 475 | + snare->noiseFilterFreq = 3000.0f; | |
| 476 | + tNoise_initToPool(&snare->noiseOsc, WhiteNoise, mp); | |
| 477 | + tSVF_initToPool(&snare->noiseLowpass, SVFTypeLowpass, 12000.0f, 0.8f, mp); | |
| 478 | + tEnvelope_initToPool(&snare->noiseEnvGain, 0.0f, 100.0f, OFALSE, mp); | |
| 479 | + tEnvelope_initToPool(&snare->noiseEnvFilter, 0.0f, 1000.0f, OFALSE, mp); | |
| 480 | + snare->noiseGain = 1.0f; | |
| 481 | +} | |
| 482 | + | |
| 483 | +void t808Snare_freeFromPool (t808Snare* const snareInst, tMempool* const mp) | |
| 484 | +{ | |
| 485 | + _tMempool* m = *mp; | |
| 486 | + _t808Snare* snare = *snareInst; | |
| 487 | + | |
| 488 | + for (int i = 0; i < 2; i++) | |
| 489 | + { | |
| 490 | + tTriangle_freeFromPool(&snare->tone[i], mp); | |
| 491 | + tSVF_freeFromPool(&snare->toneLowpass[i], mp); | |
| 492 | + tEnvelope_freeFromPool(&snare->toneEnvOsc[i], mp); | |
| 493 | + tEnvelope_freeFromPool(&snare->toneEnvGain[i], mp); | |
| 494 | + tEnvelope_freeFromPool(&snare->toneEnvFilter[i], mp); | |
| 495 | + } | |
| 496 | + | |
| 497 | + tNoise_freeFromPool(&snare->noiseOsc, mp); | |
| 498 | + tSVF_freeFromPool(&snare->noiseLowpass, mp); | |
| 499 | + tEnvelope_freeFromPool(&snare->noiseEnvGain, mp); | |
| 500 | + tEnvelope_freeFromPool(&snare->noiseEnvFilter, mp); | |
| 501 | + | |
| 502 | + mpool_free(snare, m->pool); | |
| 503 | +} | |
| 504 | + | |
| 351 | 505 | void t808Snare_on(t808Snare* const snareInst, float vel) |
| 352 | 506 | { |
| 353 | 507 | _t808Snare* snare = *snareInst; |
| @@ -472,6 +626,41 @@ void t808Kick_free (t808Kick* const kickInst) · 118 unmodified lines | ||
| 472 | 626 | leaf_free(kick); |
| 473 | 627 | } |
| 474 | 628 | |
| 629 | +void t808Kick_initToPool (t808Kick* const kickInst, tMempool* const mp) | |
| 630 | +{ | |
| 631 | + _tMempool* m = *mp; | |
| 632 | + _t808Kick* kick = *kickInst = (_t808Kick*) mpool_alloc(sizeof(_t808Kick), m->pool); | |
| 633 | + | |
| 634 | + tCycle_initToPool(&kick->tone, mp); | |
| 635 | + kick->toneInitialFreq = 40.0f; | |
| 636 | + kick->sighAmountInHz = 7.0f; | |
| 637 | + kick->chirpRatioMinusOne = 3.3f; | |
| 638 | + tCycle_setFreq(&kick->tone, 50.0f); | |
| 639 | + tSVF_initToPool(&kick->toneLowpass, SVFTypeLowpass, 2000.0f, 0.5f, mp); | |
| 640 | + tEnvelope_initToPool(&kick->toneEnvOscChirp, 0.0f, 20.0f, OFALSE, mp); | |
| 641 | + tEnvelope_initToPool(&kick->toneEnvOscSigh, 0.0f, 2500.0f, OFALSE, mp); | |
| 642 | + tEnvelope_initToPool(&kick->toneEnvGain, 0.0f, 800.0f, OFALSE, mp); | |
| 643 | + tNoise_initToPool(&kick->noiseOsc, PinkNoise, mp); | |
| 644 | + tEnvelope_initToPool(&kick->noiseEnvGain, 0.0f, 1.0f, OFALSE, mp); | |
| 645 | + kick->noiseGain = 0.3f; | |
| 646 | +} | |
| 647 | + | |
| 648 | +void t808Kick_freeFromPool (t808Kick* const kickInst, tMempool* const mp) | |
| 649 | +{ | |
| 650 | + _tMempool* m = *mp; | |
| 651 | + _t808Kick* kick = *kickInst; | |
| 652 | + | |
| 653 | + tCycle_freeFromPool(&kick->tone, mp); | |
| 654 | + tSVF_freeFromPool(&kick->toneLowpass, mp); | |
| 655 | + tEnvelope_freeFromPool(&kick->toneEnvOscChirp, mp); | |
| 656 | + tEnvelope_freeFromPool(&kick->toneEnvOscSigh, mp); | |
| 657 | + tEnvelope_freeFromPool(&kick->toneEnvGain, mp); | |
| 658 | + tNoise_freeFromPool(&kick->noiseOsc, mp); | |
| 659 | + tEnvelope_freeFromPool(&kick->noiseEnvGain, mp); | |
| 660 | + | |
| 661 | + mpool_free(kick, m->pool); | |
| 662 | +} | |
| 663 | + | |
| 475 | 664 | float t808Kick_tick (t808Kick* const kickInst) |
| 476 | 665 | { |
| 477 | 666 | _t808Kick* kick = *kickInst; |
| @@ -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 | − | |
| 82 | 80 | void leaf_pool_init(char* memory, size_t size) |
| 83 | 81 | { |
| 84 | 82 | mpool_create(memory, size, &leaf_pool); |
| @@ -143,6 +141,68 @@ void* mpool_alloc(size_t asize, mpool_t* pool) · 58 unmodified lines | ||
| 143 | 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 | + */ | |
| 148 | +void* mpool_allocAndClear(size_t asize, mpool_t* pool) | |
| 149 | +{ | |
| 150 | + // If the head is NULL, the mempool is full | |
| 151 | + if (pool->head == NULL) return NULL; | |
| 152 | + | |
| 153 | + // Should we alloc the first block large enough or check all blocks and pick the one closest in size? | |
| 154 | + size_t size_to_alloc = mpool_align(asize); | |
| 155 | + mpool_node_t* node_to_alloc = pool->head; | |
| 156 | + | |
| 157 | + // Traverse the free list for a large enough block | |
| 158 | + while (node_to_alloc->size < size_to_alloc) | |
| 159 | + { | |
| 160 | + node_to_alloc = node_to_alloc->next; | |
| 161 | + | |
| 162 | + // If we reach the end of the free list, there | |
| 163 | + // are no blocks large enough, return NULL | |
| 164 | + if (node_to_alloc == NULL) return NULL; | |
| 165 | + } | |
| 166 | + | |
| 167 | + // Create a new node after the node to be allocated if there is enough space | |
| 168 | + mpool_node_t* new_node; | |
| 169 | + size_t leftover = node_to_alloc->size - size_to_alloc; | |
| 170 | + node_to_alloc->size = size_to_alloc; | |
| 171 | + if (leftover > header_size) | |
| 172 | + { | |
| 173 | + long offset = (char*) node_to_alloc - (char*) pool->mpool; | |
| 174 | + offset += header_size + node_to_alloc->size; | |
| 175 | + new_node = create_node(&pool->mpool[offset], | |
| 176 | + node_to_alloc->next, | |
| 177 | + node_to_alloc->prev, | |
| 178 | + leftover - header_size); | |
| 179 | + } | |
| 180 | + else | |
| 181 | + { | |
| 182 | + // Add any leftover space to the allocated node to avoid fragmentation | |
| 183 | + node_to_alloc->size += leftover; | |
| 184 | + | |
| 185 | + new_node = node_to_alloc->next; | |
| 186 | + } | |
| 187 | + | |
| 188 | + // Update the head if we are allocating the first node of the free list | |
| 189 | + // The head will be NULL if there is no space left | |
| 190 | + if (pool->head == node_to_alloc) | |
| 191 | + { | |
| 192 | + pool->head = new_node; | |
| 193 | + } | |
| 194 | + | |
| 195 | + // Remove the allocated node from the free list | |
| 196 | + delink_node(node_to_alloc); | |
| 197 | + | |
| 198 | + pool->usize += header_size + node_to_alloc->size; | |
| 199 | + // Format the new pool | |
| 200 | + char* new_pool = (char*)node_to_alloc->pool; | |
| 201 | + for (int i = 0; i < node_to_alloc->size; i++) new_pool[i] = 0; | |
| 202 | + // Return the pool of the allocated node; | |
| 203 | + return node_to_alloc->pool; | |
| 204 | +} | |
| 205 | + | |
| 146 | 206 | void* leaf_alloc(size_t size) |
| 147 | 207 | { |
| 148 | 208 | //printf("alloc %i\n", size); |
| @@ -153,6 +213,17 @@ void* leaf_alloc(size_t size) · 4 unmodified lines | ||
| 153 | 213 | return block; |
| 154 | 214 | } |
| 155 | 215 | |
| 216 | +void* leaf_allocAndClear(size_t size) | |
| 217 | +{ | |
| 218 | + //printf("alloc %i\n", size); | |
| 219 | + void* block = mpool_allocAndClear(size, &leaf_pool); | |
| 220 | + | |
| 221 | + if (block == NULL) leaf_mempool_overrun(); | |
| 222 | + | |
| 223 | + | |
| 224 | + return block; | |
| 225 | +} | |
| 226 | + | |
| 156 | 227 | void mpool_free(void* ptr, mpool_t* pool) |
| 157 | 228 | { |
| 158 | 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 | 282 | pool->head = freed_node; |
| 212 | 283 | |
| 213 | 284 | // Format the freed pool |
| 214 | − char* freed_pool = (char*)freed_node->pool; | |
| 215 | − for (int i = 0; i < freed_node->size; i++) freed_pool[i] = 0; | |
| 285 | +// char* freed_pool = (char*)freed_node->pool; | |
| 286 | +// for (int i = 0; i < freed_node->size; i++) freed_pool[i] = 0; | |
| 216 | 287 | } |
| 217 | 288 | |
| 218 | 289 | void leaf_free(void* ptr) |
| @@ -289,3 +360,32 @@ void leaf_mempool_overrun(void) · 70 unmodified lines | ||
| 289 | 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 | |
| 363 | +void tMempool_init(tMempool* const mp, char* memory, size_t size) | |
| 364 | +{ | |
| 365 | + _tMempool* m = *mp = (_tMempool*) leaf_alloc(sizeof(_tMempool)); | |
| 366 | + | |
| 367 | + mpool_create (memory, size, m->pool); | |
| 368 | +} | |
| 369 | + | |
| 370 | +void tMempool_free(tMempool* const mp) | |
| 371 | +{ | |
| 372 | + _tMempool* m = *mp; | |
| 373 | + | |
| 374 | + leaf_free(m); | |
| 375 | +} | |
| 376 | + | |
| 377 | +void tMempool_initToPool (tMempool* const mp, char* memory, size_t size, tMempool* const mem) | |
| 378 | +{ | |
| 379 | + _tMempool* mm = *mem; | |
| 380 | + _tMempool* m = *mp = (_tMempool*) mpool_alloc(sizeof(_tMempool), mm->pool); | |
| 381 | + | |
| 382 | + mpool_create (memory, size, m->pool); | |
| 383 | +} | |
| 384 | + | |
| 385 | +void tMempool_freeFromPool (tMempool* const mp, tMempool* const mem) | |
| 386 | +{ | |
| 387 | + _tMempool* mm = *mem; | |
| 388 | + _tMempool* m = *mp; | |
| 389 | + | |
| 390 | + mpool_free(m, mm->pool); | |
| 391 | +} | |
| @@ -16,10 +16,330 @@ · 15 unmodified lines | ||
| 16 | 16 | |
| 17 | 17 | #endif |
| 18 | 18 | |
| 19 | +//==================================================================================== | |
| 20 | +/* Stack */ | |
| 21 | +//==================================================================================== | |
| 22 | + | |
| 23 | +void tStack_init(tStack* const stack) | |
| 24 | +{ | |
| 25 | + _tStack* ns = *stack = (_tStack*) leaf_alloc(sizeof(_tStack)); | |
| 26 | + | |
| 27 | + ns->ordered = OFALSE; | |
| 28 | + ns->size = 0; | |
| 29 | + ns->pos = 0; | |
| 30 | + ns->capacity = STACK_SIZE; | |
| 31 | + | |
| 32 | + for (int i = 0; i < STACK_SIZE; i++) ns->data[i] = -1; | |
| 33 | +} | |
| 34 | + | |
| 35 | +void tStack_free(tStack* const stack) | |
| 36 | +{ | |
| 37 | + _tStack* ns = *stack; | |
| 38 | + | |
| 39 | + leaf_free(ns); | |
| 40 | +} | |
| 41 | + | |
| 42 | +void tStack_initToPool (tStack* const stack, tMempool* const mp) | |
| 43 | +{ | |
| 44 | + _tMempool* m = *mp; | |
| 45 | + _tStack* ns = *stack = (_tStack*) mpool_alloc(sizeof(_tStack), m->pool); | |
| 46 | + | |
| 47 | + ns->ordered = OFALSE; | |
| 48 | + ns->size = 0; | |
| 49 | + ns->pos = 0; | |
| 50 | + ns->capacity = STACK_SIZE; | |
| 51 | + | |
| 52 | + for (int i = 0; i < STACK_SIZE; i++) ns->data[i] = -1; | |
| 53 | +} | |
| 54 | + | |
| 55 | +void tStack_freeFromPool (tStack* const stack, tMempool* const mp) | |
| 56 | +{ | |
| 57 | + _tMempool* m = *mp; | |
| 58 | + _tStack* ns = *stack; | |
| 59 | + | |
| 60 | + mpool_free(ns, m->pool); | |
| 61 | +} | |
| 62 | + | |
| 63 | +// If stack contains note, returns index. Else returns -1; | |
| 64 | +int tStack_contains(tStack* const stack, uint16_t noteVal) | |
| 65 | +{ | |
| 66 | + _tStack* ns = *stack; | |
| 67 | + for (int i = 0; i < ns->size; i++) | |
| 68 | + { | |
| 69 | + if (ns->data[i] == noteVal) return i; | |
| 70 | + } | |
| 71 | + return -1; | |
| 72 | +} | |
| 73 | + | |
| 74 | +void tStack_add(tStack* const stack, uint16_t noteVal) | |
| 75 | +{ | |
| 76 | + _tStack* ns = *stack; | |
| 77 | + | |
| 78 | + uint8_t j; | |
| 79 | + | |
| 80 | + int whereToInsert = 0; | |
| 81 | + if (ns->ordered) | |
| 82 | + { | |
| 83 | + for (j = 0; j < ns->size; j++) | |
| 84 | + { | |
| 85 | + if (noteVal > ns->data[j]) | |
| 86 | + { | |
| 87 | + if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1)) | |
| 88 | + { | |
| 89 | + whereToInsert = j+1; | |
| 90 | + break; | |
| 91 | + } | |
| 92 | + } | |
| 93 | + } | |
| 94 | + } | |
| 95 | + | |
| 96 | + //first move notes that are already in the stack one position to the right | |
| 97 | + for (j = ns->size; j > whereToInsert; j--) | |
| 98 | + { | |
| 99 | + ns->data[j] = ns->data[(j - 1)]; | |
| 100 | + } | |
| 101 | + | |
| 102 | + //then, insert the new note into the front of the stack | |
| 103 | + ns->data[whereToInsert] = noteVal; | |
| 104 | + | |
| 105 | + ns->size++; | |
| 106 | +} | |
| 107 | + | |
| 108 | +int tStack_addIfNotAlreadyThere(tStack* const stack, uint16_t noteVal) | |
| 109 | +{ | |
| 110 | + _tStack* ns = *stack; | |
| 111 | + | |
| 112 | + uint8_t j; | |
| 113 | + | |
| 114 | + int added = 0; | |
| 115 | + | |
| 116 | + if (tStack_contains(stack, noteVal) == -1) | |
| 117 | + { | |
| 118 | + int whereToInsert = 0; | |
| 119 | + if (ns->ordered) | |
| 120 | + { | |
| 121 | + for (j = 0; j < ns->size; j++) | |
| 122 | + { | |
| 123 | + if (noteVal > ns->data[j]) | |
| 124 | + { | |
| 125 | + if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1)) | |
| 126 | + { | |
| 127 | + whereToInsert = j+1; | |
| 128 | + break; | |
| 129 | + } | |
| 130 | + } | |
| 131 | + } | |
| 132 | + } | |
| 133 | + | |
| 134 | + //first move notes that are already in the stack one position to the right | |
| 135 | + for (j = ns->size; j > whereToInsert; j--) | |
| 136 | + { | |
| 137 | + ns->data[j] = ns->data[(j - 1)]; | |
| 138 | + } | |
| 139 | + | |
| 140 | + //then, insert the new note into the front of the stack | |
| 141 | + ns->data[whereToInsert] = noteVal; | |
| 142 | + | |
| 143 | + ns->size++; | |
| 144 | + | |
| 145 | + added = 1; | |
| 146 | + } | |
| 147 | + | |
| 148 | + return added; | |
| 149 | +} | |
| 150 | + | |
| 151 | +// Remove noteVal. return 1 if removed, 0 if not | |
| 152 | +int tStack_remove(tStack* const stack, uint16_t noteVal) | |
| 153 | +{ | |
| 154 | + _tStack* ns = *stack; | |
| 155 | + | |
| 156 | + uint8_t k; | |
| 157 | + int foundIndex = tStack_contains(stack, noteVal); | |
| 158 | + int removed = 0; | |
| 159 | + | |
| 160 | + if (foundIndex >= 0) | |
| 161 | + { | |
| 162 | + for (k = 0; k < (ns->size - foundIndex); k++) | |
| 163 | + { | |
| 164 | + if ((k+foundIndex) >= (ns->capacity - 1)) | |
| 165 | + { | |
| 166 | + ns->data[k + foundIndex] = -1; | |
| 167 | + } | |
| 168 | + else | |
| 169 | + { | |
| 170 | + ns->data[k + foundIndex] = ns->data[k + foundIndex + 1]; | |
| 171 | + if ((k + foundIndex) == (ns->size - 1)) | |
| 172 | + { | |
| 173 | + ns->data[k + foundIndex + 1] = -1; | |
| 174 | + } | |
| 175 | + } | |
| 176 | + | |
| 177 | + } | |
| 178 | + // in case it got put on the stack multiple times | |
| 179 | + foundIndex--; | |
| 180 | + ns->size--; | |
| 181 | + removed = 1; | |
| 182 | + } | |
| 183 | + | |
| 184 | + return removed; | |
| 185 | +} | |
| 186 | + | |
| 187 | +// Doesn't change size of data types | |
| 188 | +void tStack_setCapacity(tStack* const stack, uint16_t cap) | |
| 189 | +{ | |
| 190 | + _tStack* ns = *stack; | |
| 191 | + | |
| 192 | + if (cap <= 0) | |
| 193 | + ns->capacity = 1; | |
| 194 | + else if (cap <= STACK_SIZE) | |
| 195 | + ns->capacity = cap; | |
| 196 | + else | |
| 197 | + ns->capacity = STACK_SIZE; | |
| 198 | + | |
| 199 | + for (int i = cap; i < STACK_SIZE; i++) | |
| 200 | + { | |
| 201 | + if ((int)ns->data[i] != -1) | |
| 202 | + { | |
| 203 | + ns->data[i] = -1; | |
| 204 | + ns->size -= 1; | |
| 205 | + } | |
| 206 | + } | |
| 207 | + | |
| 208 | + if (ns->pos >= cap) | |
| 209 | + { | |
| 210 | + ns->pos = 0; | |
| 211 | + } | |
| 212 | +} | |
| 213 | + | |
| 214 | +int tStack_getSize(tStack* const stack) | |
| 215 | +{ | |
| 216 | + _tStack* ns = *stack; | |
| 217 | + | |
| 218 | + return ns->size; | |
| 219 | +} | |
| 220 | + | |
| 221 | +void tStack_clear(tStack* const stack) | |
| 222 | +{ | |
| 223 | + _tStack* ns = *stack; | |
| 224 | + | |
| 225 | + for (int i = 0; i < STACK_SIZE; i++) | |
| 226 | + { | |
| 227 | + ns->data[i] = -1; | |
| 228 | + } | |
| 229 | + ns->pos = 0; | |
| 230 | + ns->size = 0; | |
| 231 | +} | |
| 232 | + | |
| 233 | +// Next item in order of addition to stack. Return 0-31 if there is a next item to move to. Returns -1 otherwise. | |
| 234 | +int tStack_next(tStack* const stack) | |
| 235 | +{ | |
| 236 | + _tStack* ns = *stack; | |
| 237 | + | |
| 238 | + int step = 0; | |
| 239 | + if (ns->size != 0) // if there is at least one note in the stack | |
| 240 | + { | |
| 241 | + if (ns->pos > 0) // if you're not at the most recent note (first one), then go backward in the array (moving from earliest to latest) | |
| 242 | + { | |
| 243 | + ns->pos--; | |
| 244 | + } | |
| 245 | + else | |
| 246 | + { | |
| 247 | + ns->pos = (ns->size - 1); // if you are the most recent note, go back to the earliest note in the array | |
| 248 | + } | |
| 249 | + | |
| 250 | + step = ns->data[ns->pos]; | |
| 251 | + return step; | |
| 252 | + } | |
| 253 | + else | |
| 254 | + { | |
| 255 | + return -1; | |
| 256 | + } | |
| 257 | +} | |
| 258 | + | |
| 259 | +int tStack_get(tStack* const stack, int which) | |
| 260 | +{ | |
| 261 | + _tStack* ns = *stack; | |
| 262 | + return ns->data[which]; | |
| 263 | +} | |
| 264 | + | |
| 265 | +int tStack_first(tStack* const stack) | |
| 266 | +{ | |
| 267 | + _tStack* ns = *stack; | |
| 268 | + return ns->data[0]; | |
| 269 | +} | |
| 270 | + | |
| 271 | + | |
| 19 | 272 | // POLY |
| 20 | 273 | void 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 | + | |
| 318 | +void tPoly_free(tPoly* const polyh) | |
| 319 | +{ | |
| 320 | + _tPoly* poly = *polyh; | |
| 321 | + | |
| 322 | + for (int i = 0; i < poly->maxNumVoices; i++) | |
| 323 | + { | |
| 324 | + tRamp_free(&poly->ramps[i]); | |
| 325 | + leaf_free(poly->voices[i]); | |
| 326 | + } | |
| 327 | + tRamp_free(&poly->pitchBendRamp); | |
| 328 | + tStack_free(&poly->stack); | |
| 329 | + tStack_free(&poly->orderStack); | |
| 330 | + | |
| 331 | + leaf_free(poly->voices); | |
| 332 | + leaf_free(poly->ramps); | |
| 333 | + leaf_free(poly->rampVals); | |
| 334 | + leaf_free(poly->firstReceived); | |
| 335 | + | |
| 336 | + leaf_free(poly); | |
| 337 | +} | |
| 338 | + | |
| 339 | +void tPoly_initToPool (tPoly* const polyh, int maxNumVoices, tMempool* const mp) | |
| 340 | +{ | |
| 341 | + _tMempool* m = *mp; | |
| 342 | + _tPoly* poly = *polyh = (_tPoly*) mpool_alloc(sizeof(_tPoly), m->pool); | |
| 23 | 343 | |
| 24 | 344 | poly->numVoices = maxNumVoices; |
| 25 | 345 | poly->maxNumVoices = maxNumVoices; |
| @@ -39,48 +359,49 @@ void tPoly_init(tPoly* const polyh, int maxNumVoices) · 13 unmodified lines | ||
| 39 | 359 | |
| 40 | 360 | poly->glideTime = 5.0f; |
| 41 | 361 | |
| 42 | − poly->ramps = (tRamp*) leaf_alloc(sizeof(tRamp) * poly->maxNumVoices); | |
| 43 | − poly->rampVals = (float*) leaf_alloc(sizeof(float) * poly->maxNumVoices); | |
| 44 | − poly->firstReceived = (oBool*) leaf_alloc(sizeof(oBool) * poly->maxNumVoices); | |
| 45 | − poly->voices = (int**) leaf_alloc(sizeof(int*) * poly->maxNumVoices); | |
| 362 | + poly->ramps = (tRamp*) mpool_alloc(sizeof(tRamp) * poly->maxNumVoices, m->pool); | |
| 363 | + poly->rampVals = (float*) mpool_alloc(sizeof(float) * poly->maxNumVoices, m->pool); | |
| 364 | + poly->firstReceived = (oBool*) mpool_alloc(sizeof(oBool) * poly->maxNumVoices, m->pool); | |
| 365 | + poly->voices = (int**) mpool_alloc(sizeof(int*) * poly->maxNumVoices, m->pool); | |
| 46 | 366 | |
| 47 | 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 | 370 | poly->voices[i][0] = -1; |
| 51 | 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 | 376 | poly->pitchBend = 0.0f; |
| 57 | 377 | |
| 58 | − tRamp_init(&poly->pitchBendRamp, 1.0f, 1); | |
| 59 | − tStack_init(&poly->stack); | |
| 60 | − tStack_init(&poly->orderStack); | |
| 378 | + tRamp_initToPool(&poly->pitchBendRamp, 1.0f, 1, mp); | |
| 379 | + tStack_initToPool(&poly->stack, mp); | |
| 380 | + tStack_initToPool(&poly->orderStack, mp); | |
| 61 | 381 | |
| 62 | 382 | poly->pitchGlideIsActive = OFALSE; |
| 63 | 383 | } |
| 64 | 384 | |
| 65 | −void tPoly_free(tPoly* const polyh) | |
| 385 | +void tPoly_freeFromPool (tPoly* const polyh, tMempool* const mp) | |
| 66 | 386 | { |
| 387 | + _tMempool* m = *mp; | |
| 67 | 388 | _tPoly* poly = *polyh; |
| 68 | 389 | |
| 69 | 390 | for (int i = 0; i < poly->maxNumVoices; i++) |
| 70 | 391 | { |
| 71 | − tRamp_free(&poly->ramps[i]); | |
| 72 | − leaf_free(poly->voices[i]); | |
| 392 | + tRamp_freeFromPool(&poly->ramps[i], mp); | |
| 393 | + mpool_free(poly->voices[i], m->pool); | |
| 73 | 394 | } |
| 74 | − tRamp_free(&poly->pitchBendRamp); | |
| 75 | − tStack_free(&poly->stack); | |
| 76 | − tStack_free(&poly->orderStack); | |
| 395 | + tRamp_freeFromPool(&poly->pitchBendRamp, mp); | |
| 396 | + tStack_freeFromPool(&poly->stack, mp); | |
| 397 | + tStack_freeFromPool(&poly->orderStack, mp); | |
| 77 | 398 | |
| 78 | − leaf_free(poly->voices); | |
| 79 | − leaf_free(poly->ramps); | |
| 80 | − leaf_free(poly->rampVals); | |
| 81 | − leaf_free(poly->firstReceived); | |
| 399 | + mpool_free(poly->voices, m->pool); | |
| 400 | + mpool_free(poly->ramps, m->pool); | |
| 401 | + mpool_free(poly->rampVals, m->pool); | |
| 402 | + mpool_free(poly->firstReceived, m->pool); | |
| 82 | 403 | |
| 83 | − leaf_free(poly); | |
| 404 | + mpool_free(poly, m->pool); | |
| 84 | 405 | } |
| 85 | 406 | |
| 86 | 407 | void tPoly_tickPitch(tPoly* polyh) |
| @@ -332,236 +653,3 @@ int tPoly_isOn(tPoly* const polyh, uint8_t voice) · 245 unmodified lines | ||
| 332 | 653 | _tPoly* poly = *polyh; |
| 333 | 654 | return (poly->voices[voice][0] > 0) ? 1 : 0; |
| 334 | 655 | } |
| 335 | − | |
| 336 | − | |
| 337 | −//==================================================================================== | |
| 338 | −/* Stack */ | |
| 339 | −//==================================================================================== | |
| 340 | − | |
| 341 | −void tStack_init(tStack* const stack) | |
| 342 | −{ | |
| 343 | − _tStack* ns = *stack = (_tStack*) leaf_alloc(sizeof(_tStack)); | |
| 344 | − | |
| 345 | − ns->ordered = OFALSE; | |
| 346 | − ns->size = 0; | |
| 347 | − ns->pos = 0; | |
| 348 | − ns->capacity = STACK_SIZE; | |
| 349 | − | |
| 350 | − for (int i = 0; i < STACK_SIZE; i++) ns->data[i] = -1; | |
| 351 | −} | |
| 352 | − | |
| 353 | −void tStack_free(tStack* const stack) | |
| 354 | −{ | |
| 355 | − _tStack* ns = *stack; | |
| 356 | − | |
| 357 | − leaf_free(ns); | |
| 358 | −} | |
| 359 | − | |
| 360 | −// If stack contains note, returns index. Else returns -1; | |
| 361 | −int tStack_contains(tStack* const stack, uint16_t noteVal) | |
| 362 | −{ | |
| 363 | − _tStack* ns = *stack; | |
| 364 | − for (int i = 0; i < ns->size; i++) | |
| 365 | − { | |
| 366 | − if (ns->data[i] == noteVal) return i; | |
| 367 | − } | |
| 368 | − return -1; | |
| 369 | −} | |
| 370 | − | |
| 371 | −void tStack_add(tStack* const stack, uint16_t noteVal) | |
| 372 | −{ | |
| 373 | − _tStack* ns = *stack; | |
| 374 | − | |
| 375 | − uint8_t j; | |
| 376 | − | |
| 377 | − int whereToInsert = 0; | |
| 378 | − if (ns->ordered) | |
| 379 | − { | |
| 380 | − for (j = 0; j < ns->size; j++) | |
| 381 | − { | |
| 382 | − if (noteVal > ns->data[j]) | |
| 383 | − { | |
| 384 | − if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1)) | |
| 385 | − { | |
| 386 | − whereToInsert = j+1; | |
| 387 | − break; | |
| 388 | − } | |
| 389 | − } | |
| 390 | − } | |
| 391 | − } | |
| 392 | − | |
| 393 | − //first move notes that are already in the stack one position to the right | |
| 394 | − for (j = ns->size; j > whereToInsert; j--) | |
| 395 | − { | |
| 396 | − ns->data[j] = ns->data[(j - 1)]; | |
| 397 | − } | |
| 398 | − | |
| 399 | − //then, insert the new note into the front of the stack | |
| 400 | − ns->data[whereToInsert] = noteVal; | |
| 401 | − | |
| 402 | − ns->size++; | |
| 403 | −} | |
| 404 | − | |
| 405 | −int tStack_addIfNotAlreadyThere(tStack* const stack, uint16_t noteVal) | |
| 406 | −{ | |
| 407 | − _tStack* ns = *stack; | |
| 408 | − | |
| 409 | − uint8_t j; | |
| 410 | − | |
| 411 | − int added = 0; | |
| 412 | − | |
| 413 | − if (tStack_contains(stack, noteVal) == -1) | |
| 414 | − { | |
| 415 | − int whereToInsert = 0; | |
| 416 | − if (ns->ordered) | |
| 417 | − { | |
| 418 | − for (j = 0; j < ns->size; j++) | |
| 419 | − { | |
| 420 | − if (noteVal > ns->data[j]) | |
| 421 | − { | |
| 422 | − if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1)) | |
| 423 | − { | |
| 424 | − whereToInsert = j+1; | |
| 425 | − break; | |
| 426 | − } | |
| 427 | − } | |
| 428 | − } | |
| 429 | − } | |
| 430 | − | |
| 431 | − //first move notes that are already in the stack one position to the right | |
| 432 | − for (j = ns->size; j > whereToInsert; j--) | |
| 433 | − { | |
| 434 | − ns->data[j] = ns->data[(j - 1)]; | |
| 435 | − } | |
| 436 | − | |
| 437 | − //then, insert the new note into the front of the stack | |
| 438 | − ns->data[whereToInsert] = noteVal; | |
| 439 | − | |
| 440 | − ns->size++; | |
| 441 | − | |
| 442 | − added = 1; | |
| 443 | − } | |
| 444 | − | |
| 445 | − return added; | |
| 446 | −} | |
| 447 | − | |
| 448 | − | |
| 449 | −// Remove noteVal. return 1 if removed, 0 if not | |
| 450 | −int tStack_remove(tStack* const stack, uint16_t noteVal) | |
| 451 | −{ | |
| 452 | − _tStack* ns = *stack; | |
| 453 | − | |
| 454 | − uint8_t k; | |
| 455 | − int foundIndex = tStack_contains(stack, noteVal); | |
| 456 | − int removed = 0; | |
| 457 | − | |
| 458 | − if (foundIndex >= 0) | |
| 459 | − { | |
| 460 | − for (k = 0; k < (ns->size - foundIndex); k++) | |
| 461 | − { | |
| 462 | − if ((k+foundIndex) >= (ns->capacity - 1)) | |
| 463 | − { | |
| 464 | − ns->data[k + foundIndex] = -1; | |
| 465 | − } | |
| 466 | − else | |
| 467 | − { | |
| 468 | − ns->data[k + foundIndex] = ns->data[k + foundIndex + 1]; | |
| 469 | − if ((k + foundIndex) == (ns->size - 1)) | |
| 470 | − { | |
| 471 | − ns->data[k + foundIndex + 1] = -1; | |
| 472 | − } | |
| 473 | − } | |
| 474 | − | |
| 475 | − } | |
| 476 | − // in case it got put on the stack multiple times | |
| 477 | − foundIndex--; | |
| 478 | − ns->size--; | |
| 479 | − removed = 1; | |
| 480 | − } | |
| 481 | − | |
| 482 | − return removed; | |
| 483 | −} | |
| 484 | − | |
| 485 | −// Doesn't change size of data types | |
| 486 | −void tStack_setCapacity(tStack* const stack, uint16_t cap) | |
| 487 | −{ | |
| 488 | − _tStack* ns = *stack; | |
| 489 | − | |
| 490 | − if (cap <= 0) | |
| 491 | − ns->capacity = 1; | |
| 492 | − else if (cap <= STACK_SIZE) | |
| 493 | − ns->capacity = cap; | |
| 494 | − else | |
| 495 | − ns->capacity = STACK_SIZE; | |
| 496 | − | |
| 497 | − for (int i = cap; i < STACK_SIZE; i++) | |
| 498 | − { | |
| 499 | − if ((int)ns->data[i] != -1) | |
| 500 | − { | |
| 501 | − ns->data[i] = -1; | |
| 502 | − ns->size -= 1; | |
| 503 | − } | |
| 504 | − } | |
| 505 | − | |
| 506 | − if (ns->pos >= cap) | |
| 507 | − { | |
| 508 | − ns->pos = 0; | |
| 509 | − } | |
| 510 | −} | |
| 511 | − | |
| 512 | −int tStack_getSize(tStack* const stack) | |
| 513 | −{ | |
| 514 | − _tStack* ns = *stack; | |
| 515 | − | |
| 516 | − return ns->size; | |
| 517 | −} | |
| 518 | − | |
| 519 | −void tStack_clear(tStack* const stack) | |
| 520 | −{ | |
| 521 | − _tStack* ns = *stack; | |
| 522 | − | |
| 523 | − for (int i = 0; i < STACK_SIZE; i++) | |
| 524 | − { | |
| 525 | − ns->data[i] = -1; | |
| 526 | − } | |
| 527 | − ns->pos = 0; | |
| 528 | − ns->size = 0; | |
| 529 | −} | |
| 530 | − | |
| 531 | −// Next item in order of addition to stack. Return 0-31 if there is a next item to move to. Returns -1 otherwise. | |
| 532 | −int tStack_next(tStack* const stack) | |
| 533 | −{ | |
| 534 | − _tStack* ns = *stack; | |
| 535 | − | |
| 536 | − int step = 0; | |
| 537 | − if (ns->size != 0) // if there is at least one note in the stack | |
| 538 | − { | |
| 539 | − if (ns->pos > 0) // if you're not at the most recent note (first one), then go backward in the array (moving from earliest to latest) | |
| 540 | − { | |
| 541 | − ns->pos--; | |
| 542 | − } | |
| 543 | − else | |
| 544 | − { | |
| 545 | − ns->pos = (ns->size - 1); // if you are the most recent note, go back to the earliest note in the array | |
| 546 | − } | |
| 547 | − | |
| 548 | − step = ns->data[ns->pos]; | |
| 549 | − return step; | |
| 550 | − } | |
| 551 | − else | |
| 552 | − { | |
| 553 | − return -1; | |
| 554 | − } | |
| 555 | −} | |
| 556 | − | |
| 557 | −int tStack_get(tStack* const stack, int which) | |
| 558 | −{ | |
| 559 | − _tStack* ns = *stack; | |
| 560 | − return ns->data[which]; | |
| 561 | −} | |
| 562 | − | |
| 563 | −int tStack_first(tStack* const stack) | |
| 564 | −{ | |
| 565 | − _tStack* ns = *stack; | |
| 566 | − return ns->data[0]; | |
| 567 | −} | |
| @@ -19,19 +19,42 @@ · 18 unmodified lines | ||
| 19 | 19 | #endif |
| 20 | 20 | |
| 21 | 21 | // Cycle |
| 22 | −void tCycle_init(tCycle* const c) | |
| 22 | +void tCycle_init(tCycle* const cy) | |
| 23 | 23 | { |
| 24 | + _tCycle* c = *cy = (_tCycle*) leaf_alloc(sizeof(_tCycle)); | |
| 25 | + | |
| 24 | 26 | c->inc = 0.0f; |
| 25 | 27 | c->phase = 0.0f; |
| 26 | 28 | } |
| 27 | 29 | |
| 28 | −void tCycle_free(tCycle* const c) | |
| 30 | +void tCycle_free(tCycle* const cy) | |
| 31 | +{ | |
| 32 | + _tCycle* c = *cy; | |
| 33 | + | |
| 34 | + leaf_free(c); | |
| 35 | +} | |
| 36 | + | |
| 37 | +void tCycle_initToPool (tCycle* const cy, tMempool* const mp) | |
| 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 | |
| 33 | −int tCycle_setFreq(tCycle* const c, float freq) | |
| 46 | +void 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 | + | |
| 54 | +int tCycle_setFreq(tCycle* const cy, float freq) | |
| 55 | +{ | |
| 56 | + _tCycle* c = *cy; | |
| 57 | + | |
| 35 | 58 | if (freq < 0.0f) freq = 0.0f; |
| 36 | 59 | |
| 37 | 60 | c->freq = freq; |
| @@ -40,8 +63,10 @@ int tCycle_setFreq(tCycle* const c, float freq) · 2 unmodified lines | ||
| 40 | 63 | return 0; |
| 41 | 64 | } |
| 42 | 65 | |
| 43 | −float tCycle_tick(tCycle* const c) | |
| 66 | +float tCycle_tick(tCycle* const cy) | |
| 44 | 67 | { |
| 68 | + _tCycle* c = *cy; | |
| 69 | + | |
| 45 | 70 | // Phasor increment |
| 46 | 71 | c->phase += c->inc; |
| 47 | 72 | while (c->phase >= 1.0f) c->phase -= 1.0f; |
| @@ -56,31 +81,51 @@ float tCycle_tick(tCycle* const c) · 8 unmodified lines | ||
| 56 | 81 | return (samp0 + (samp1 - samp0) * fracPart); |
| 57 | 82 | } |
| 58 | 83 | |
| 59 | −void tCycleSampleRateChanged (tCycle* const c) | |
| 84 | +void tCycleSampleRateChanged (tCycle* const cy) | |
| 60 | 85 | { |
| 86 | + _tCycle* c = *cy; | |
| 87 | + | |
| 61 | 88 | c->inc = c->freq * leaf.invSampleRate; |
| 62 | 89 | } |
| 63 | 90 | |
| 64 | 91 | //======================================================================== |
| 65 | 92 | /* Triangle */ |
| 66 | −void tTriangle_start(tTriangle* const c) | |
| 93 | +void 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 | |
| 71 | −void tTriangle_init(tTriangle* const c) | |
| 101 | +void tTriangle_free(tTriangle* const cy) | |
| 72 | 102 | { |
| 103 | + _tTriangle* c = *cy; | |
| 104 | + | |
| 105 | + leaf_free(c); | |
| 106 | +} | |
| 107 | + | |
| 108 | +void tTriangle_initToPool (tTriangle* const cy, tMempool* const mp) | |
| 109 | +{ | |
| 110 | + _tMempool* m = *mp; | |
| 111 | + _tTriangle* c = *cy = (_tTriangle*) mpool_alloc(sizeof(_tTriangle), m->pool); | |
| 112 | + | |
| 73 | 113 | c->inc = 0.0f; |
| 74 | 114 | c->phase = 0.0f; |
| 75 | 115 | } |
| 76 | 116 | |
| 77 | −void tTriangle_free(tTriangle* const c) | |
| 117 | +void 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 | |
| 82 | −int tTriangle_setFreq(tTriangle* const c, float freq) | |
| 125 | +int tTriangle_setFreq(tTriangle* const cy, float freq) | |
| 83 | 126 | { |
| 127 | + _tTriangle* c = *cy; | |
| 128 | + | |
| 84 | 129 | if (freq < 0.0f) freq = 0.0f; |
| 85 | 130 | |
| 86 | 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 | |
| 93 | −float tTriangle_tick(tTriangle* const c) | |
| 138 | +float tTriangle_tick(tTriangle* const cy) | |
| 94 | 139 | { |
| 140 | + _tTriangle* c = *cy; | |
| 141 | + | |
| 95 | 142 | // Phasor increment |
| 96 | 143 | c->phase += c->inc; |
| 97 | 144 | while (c->phase >= 1.0f) c->phase -= 1.0f; |
| @@ -165,26 +212,51 @@ float tTriangle_tick(tTriangle* const c) · 67 unmodified lines | ||
| 165 | 212 | return out; |
| 166 | 213 | } |
| 167 | 214 | |
| 168 | −void tTriangleSampleRateChanged (tTriangle* const c) | |
| 215 | +void tTriangleSampleRateChanged (tTriangle* const cy) | |
| 169 | 216 | { |
| 217 | + _tTriangle* c = *cy; | |
| 218 | + | |
| 170 | 219 | c->inc = c->freq * leaf.invSampleRate; |
| 171 | 220 | } |
| 172 | 221 | |
| 173 | 222 | //======================================================================== |
| 174 | 223 | /* Square */ |
| 175 | −void tSquare_init(tSquare* const c) | |
| 224 | +void tSquare_init(tSquare* const cy) | |
| 176 | 225 | { |
| 226 | + _tSquare* c = *cy = (_tSquare*) leaf_alloc(sizeof(_tSquare)); | |
| 227 | + | |
| 177 | 228 | c->inc = 0.0f; |
| 178 | 229 | c->phase = 0.0f; |
| 179 | 230 | } |
| 180 | 231 | |
| 181 | −void tSquare_free(tSquare* const c) | |
| 232 | +void tSquare_free(tSquare* const cy) | |
| 182 | 233 | { |
| 234 | + _tSquare* c = *cy; | |
| 183 | 235 | |
| 236 | + leaf_free(c); | |
| 184 | 237 | } |
| 185 | 238 | |
| 186 | −int tSquare_setFreq(tSquare* const c, float freq) | |
| 239 | +void 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 | + | |
| 248 | +void tSquare_freeFromPool(tSquare* const cy, tMempool* const mp) | |
| 249 | +{ | |
| 250 | + _tMempool* m = *mp; | |
| 251 | + _tSquare* c = *cy; | |
| 252 | + | |
| 253 | + mpool_free(c, m->pool); | |
| 254 | +} | |
| 255 | + | |
| 256 | +int tSquare_setFreq(tSquare* const cy, float freq) | |
| 257 | +{ | |
| 258 | + _tSquare* c = *cy; | |
| 259 | + | |
| 188 | 260 | if (freq < 0.0f) freq = 0.0f; |
| 189 | 261 | |
| 190 | 262 | c->freq = freq; |
| @@ -193,8 +265,10 @@ int tSquare_setFreq(tSquare* const c, float freq) · 2 unmodified lines | ||
| 193 | 265 | return 0; |
| 194 | 266 | } |
| 195 | 267 | |
| 196 | −float tSquare_tick(tSquare* const c) | |
| 268 | +float tSquare_tick(tSquare* const cy) | |
| 197 | 269 | { |
| 270 | + _tSquare* c = *cy; | |
| 271 | + | |
| 198 | 272 | // Phasor increment |
| 199 | 273 | c->phase += c->inc; |
| 200 | 274 | while (c->phase >= 1.0f) c->phase -= 1.0f; |
| @@ -267,26 +341,51 @@ float tSquare_tick(tSquare* const c) · 66 unmodified lines | ||
| 267 | 341 | return out; |
| 268 | 342 | } |
| 269 | 343 | |
| 270 | −void tSquareSampleRateChanged (tSquare* const c) | |
| 344 | +void tSquareSampleRateChanged (tSquare* const cy) | |
| 271 | 345 | { |
| 346 | + _tSquare* c = *cy; | |
| 347 | + | |
| 272 | 348 | c->inc = c->freq * leaf.invSampleRate; |
| 273 | 349 | } |
| 274 | 350 | |
| 275 | 351 | //===================================================================== |
| 276 | 352 | // Sawtooth |
| 277 | −void tSawtooth_init(tSawtooth* const c) | |
| 353 | +void tSawtooth_init(tSawtooth* const cy) | |
| 354 | +{ | |
| 355 | + _tSawtooth* c = *cy = (_tSawtooth*) leaf_alloc(sizeof(_tSawtooth)); | |
| 356 | + | |
| 357 | + c->inc = 0.0f; | |
| 358 | + c->phase = 0.0f; | |
| 359 | +} | |
| 360 | + | |
| 361 | +void tSawtooth_free(tSawtooth* const cy) | |
| 278 | 362 | { |
| 363 | + _tSawtooth* c = *cy; | |
| 364 | + | |
| 365 | + leaf_free(c); | |
| 366 | +} | |
| 367 | + | |
| 368 | +void tSawtooth_initToPool (tSawtooth* const cy, tMempool* const mp) | |
| 369 | +{ | |
| 370 | + _tMempool* m = *mp; | |
| 371 | + _tSawtooth* c = *cy = (_tSawtooth*) mpool_alloc(sizeof(_tSawtooth), m->pool); | |
| 372 | + | |
| 279 | 373 | c->inc = 0.0f; |
| 280 | 374 | c->phase = 0.0f; |
| 281 | 375 | } |
| 282 | 376 | |
| 283 | −void tSawtooth_free(tSawtooth* const c) | |
| 377 | +void 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 | |
| 288 | −int tSawtooth_setFreq(tSawtooth* const c, float freq) | |
| 385 | +int tSawtooth_setFreq(tSawtooth* const cy, float freq) | |
| 289 | 386 | { |
| 387 | + _tSawtooth* c = *cy; | |
| 388 | + | |
| 290 | 389 | if (freq < 0.0f) freq = 0.0f; |
| 291 | 390 | |
| 292 | 391 | c->freq = freq; |
| @@ -295,8 +394,10 @@ int tSawtooth_setFreq(tSawtooth* const c, float freq) · 2 unmodified lines | ||
| 295 | 394 | return 0; |
| 296 | 395 | } |
| 297 | 396 | |
| 298 | −float tSawtooth_tick(tSawtooth* const c) | |
| 397 | +float tSawtooth_tick(tSawtooth* const cy) | |
| 299 | 398 | { |
| 399 | + _tSawtooth* c = *cy; | |
| 400 | + | |
| 300 | 401 | // Phasor increment |
| 301 | 402 | c->phase += c->inc; |
| 302 | 403 | while (c->phase >= 1.0f) c->phase -= 1.0f; |
| @@ -370,31 +471,58 @@ float tSawtooth_tick(tSawtooth* const c) · 67 unmodified lines | ||
| 370 | 471 | return out; |
| 371 | 472 | } |
| 372 | 473 | |
| 373 | −void tSawtoothSampleRateChanged (tSawtooth* const c) | |
| 474 | +void tSawtoothSampleRateChanged (tSawtooth* const cy) | |
| 374 | 475 | { |
| 476 | + _tSawtooth* c = *cy; | |
| 477 | + | |
| 375 | 478 | c->inc = c->freq * leaf.invSampleRate; |
| 376 | 479 | } |
| 377 | 480 | |
| 378 | 481 | //======================================================================== |
| 379 | 482 | /* Phasor */ |
| 380 | −void tPhasorSampleRateChanged (tPhasor* const p) | |
| 483 | +void tPhasorSampleRateChanged (tPhasor* const ph) | |
| 381 | 484 | { |
| 485 | + _tPhasor* p = *ph; | |
| 486 | + | |
| 382 | 487 | p->inc = p->freq * leaf.invSampleRate; |
| 383 | 488 | }; |
| 384 | 489 | |
| 385 | −void tPhasor_init(tPhasor* const p) | |
| 490 | +void tPhasor_init(tPhasor* const ph) | |
| 386 | 491 | { |
| 492 | + _tPhasor* p = *ph = (_tPhasor*) leaf_alloc(sizeof(_tPhasor)); | |
| 493 | + | |
| 387 | 494 | p->phase = 0.0f; |
| 388 | 495 | p->inc = 0.0f; |
| 389 | 496 | } |
| 390 | 497 | |
| 391 | −void tPhasor_free(tPhasor* const p) | |
| 498 | +void tPhasor_free(tPhasor* const ph) | |
| 392 | 499 | { |
| 500 | + _tPhasor* p = *ph; | |
| 393 | 501 | |
| 502 | + leaf_free(p); | |
| 394 | 503 | } |
| 395 | 504 | |
| 396 | −int tPhasor_setFreq(tPhasor* const p, float freq) | |
| 505 | +void 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 | + | |
| 514 | +void tPhasor_freeFromPool(tPhasor* const ph, tMempool* const mp) | |
| 515 | +{ | |
| 516 | + _tMempool* m = *mp; | |
| 517 | + _tPhasor* p = *ph; | |
| 518 | + | |
| 519 | + mpool_free(p, m->pool); | |
| 520 | +} | |
| 521 | + | |
| 522 | +int tPhasor_setFreq(tPhasor* const ph, float freq) | |
| 523 | +{ | |
| 524 | + _tPhasor* p = *ph; | |
| 525 | + | |
| 398 | 526 | if (freq < 0.0f) freq = 0.0f; |
| 399 | 527 | |
| 400 | 528 | p->freq = freq; |
| @@ -403,8 +531,10 @@ int tPhasor_setFreq(tPhasor* const p, float freq) · 2 unmodified lines | ||
| 403 | 531 | return 0; |
| 404 | 532 | } |
| 405 | 533 | |
| 406 | −float tPhasor_tick(tPhasor* const p) | |
| 534 | +float tPhasor_tick(tPhasor* const ph) | |
| 407 | 535 | { |
| 536 | + _tPhasor* p = *ph; | |
| 537 | + | |
| 408 | 538 | p->phase += p->inc; |
| 409 | 539 | |
| 410 | 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 | 545 | /* Noise */ |
| 416 | −void tNoise_init(tNoise* const n, NoiseType type) | |
| 546 | +void tNoise_init(tNoise* const ns, NoiseType type) | |
| 547 | +{ | |
| 548 | + _tNoise* n = *ns = (_tNoise*) leaf_alloc(sizeof(_tNoise)); | |
| 549 | + | |
| 550 | + n->type = type; | |
| 551 | + n->rand = leaf.random; | |
| 552 | +} | |
| 553 | + | |
| 554 | +void tNoise_free(tNoise* const ns) | |
| 417 | 555 | { |
| 556 | + _tNoise* n = *ns; | |
| 557 | + | |
| 558 | + leaf_free(n); | |
| 559 | +} | |
| 560 | + | |
| 561 | +void tNoise_initToPool (tNoise* const ns, NoiseType type, tMempool* const mp) | |
| 562 | +{ | |
| 563 | + _tMempool* m = *mp; | |
| 564 | + _tNoise* n = *ns = (_tNoise*) mpool_alloc(sizeof(_tNoise), m->pool); | |
| 565 | + | |
| 418 | 566 | n->type = type; |
| 419 | 567 | n->rand = leaf.random; |
| 420 | 568 | } |
| 421 | 569 | |
| 422 | −void tNoise_free(tNoise* const n) | |
| 570 | +void 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 | |
| 427 | −float tNoise_tick(tNoise* const n) | |
| 578 | +float tNoise_tick(tNoise* const ns) | |
| 428 | 579 | { |
| 580 | + _tNoise* n = *ns; | |
| 581 | + | |
| 429 | 582 | float rand = (n->rand() * 2.0f) - 1.0f; |
| 430 | 583 | |
| 431 | 584 | if (n->type == PinkNoise) |
| @@ -446,13 +599,15 @@ float tNoise_tick(tNoise* const n) · 14 unmodified lines | ||
| 446 | 599 | //================================================================================= |
| 447 | 600 | /* Neuron */ |
| 448 | 601 | |
| 449 | −void tNeuronSampleRateChanged(tNeuron* n) | |
| 602 | +void tNeuronSampleRateChanged(tNeuron* nr) | |
| 450 | 603 | { |
| 451 | 604 | |
| 452 | 605 | } |
| 453 | 606 | |
| 454 | −void tNeuron_init(tNeuron* const n) | |
| 607 | +void tNeuron_init(tNeuron* const nr) | |
| 455 | 608 | { |
| 609 | + _tNeuron* n = *nr = (_tNeuron*) leaf_alloc(sizeof(_tNeuron)); | |
| 610 | + | |
| 456 | 611 | tPoleZero_init(&n->f); |
| 457 | 612 | |
| 458 | 613 | tPoleZero_setBlockZero(&n->f, 0.99f); |
| @@ -480,13 +635,20 @@ void tNeuron_init(tNeuron* const n) · 21 unmodified lines | ||
| 480 | 635 | n->rate[2] = n->gL/n->C; |
| 481 | 636 | } |
| 482 | 637 | |
| 483 | −void tNeuron_free(tNeuron* const n) | |
| 638 | +void tNeuron_free(tNeuron* const nr) | |
| 484 | 639 | { |
| 640 | + _tNeuron* n = *nr; | |
| 641 | + | |
| 485 | 642 | tPoleZero_free(&n->f); |
| 643 | + leaf_free(n); | |
| 486 | 644 | } |
| 487 | 645 | |
| 488 | −void tNeuron_reset(tNeuron* const n) | |
| 646 | +void 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 | 653 | tPoleZero_setBlockZero(&n->f, 0.99f); |
| 492 | 654 | |
| @@ -513,52 +675,99 @@ void tNeuron_reset(tNeuron* const n) · 20 unmodified lines | ||
| 513 | 675 | n->rate[2] = n->gL/n->C; |
| 514 | 676 | } |
| 515 | 677 | |
| 678 | +void tNeuron_freeFromPool(tNeuron* const nr, tMempool* const mp) | |
| 679 | +{ | |
| 680 | + _tMempool* m = *mp; | |
| 681 | + _tNeuron* n = *nr; | |
| 682 | + | |
| 683 | + tPoleZero_free(&n->f); | |
| 684 | + mpool_free(n, m->pool); | |
| 685 | +} | |
| 686 | + | |
| 687 | +void tNeuron_reset(tNeuron* const nr) | |
| 688 | +{ | |
| 689 | + _tNeuron* n = *nr; | |
| 690 | + | |
| 691 | + tPoleZero_setBlockZero(&n->f, 0.99f); | |
| 692 | + | |
| 693 | + n->timeStep = 1.0f / 50.0f; | |
| 694 | + | |
| 695 | + n->current = 0.0f; // 100.0f for sound | |
| 696 | + n->voltage = 0.0f; | |
| 697 | + | |
| 698 | + n->mode = NeuronNormal; | |
| 699 | + | |
| 700 | + n->P[0] = 0.0f; | |
| 701 | + n->P[1] = 0.0f; | |
| 702 | + n->P[2] = 1.0f; | |
| 703 | + | |
| 704 | + n->V[0] = -12.0f; | |
| 705 | + n->V[1] = 115.0f; | |
| 706 | + n->V[2] = 10.613f; | |
| 707 | + | |
| 708 | + n->gK = 36.0f; | |
| 709 | + n->gN = 120.0f; | |
| 710 | + n->gL = 0.3f; | |
| 711 | + n->C = 1.0f; | |
| 712 | + | |
| 713 | + n->rate[2] = n->gL/n->C; | |
| 714 | +} | |
| 516 | 715 | |
| 517 | −void tNeuron_setV1(tNeuron* const n, float V1) | |
| 716 | +void tNeuron_setV1(tNeuron* const nr, float V1) | |
| 518 | 717 | { |
| 718 | + _tNeuron* n = *nr; | |
| 519 | 719 | n->V[0] = V1; |
| 520 | 720 | } |
| 521 | 721 | |
| 522 | 722 | |
| 523 | −void tNeuron_setV2(tNeuron* const n, float V2) | |
| 723 | +void tNeuron_setV2(tNeuron* const nr, float V2) | |
| 524 | 724 | { |
| 725 | + _tNeuron* n = *nr; | |
| 525 | 726 | n->V[1] = V2; |
| 526 | 727 | } |
| 527 | 728 | |
| 528 | −void tNeuron_setV3(tNeuron* const n, float V3) | |
| 729 | +void tNeuron_setV3(tNeuron* const nr, float V3) | |
| 529 | 730 | { |
| 731 | + _tNeuron* n = *nr; | |
| 530 | 732 | n->V[2] = V3; |
| 531 | 733 | } |
| 532 | 734 | |
| 533 | −void tNeuron_setTimeStep(tNeuron* const n, float timeStep) | |
| 735 | +void tNeuron_setTimeStep(tNeuron* const nr, float timeStep) | |
| 534 | 736 | { |
| 737 | + _tNeuron* n = *nr; | |
| 535 | 738 | n->timeStep = timeStep; |
| 536 | 739 | } |
| 537 | 740 | |
| 538 | −void tNeuron_setK(tNeuron* const n, float K) | |
| 741 | +void tNeuron_setK(tNeuron* const nr, float K) | |
| 539 | 742 | { |
| 743 | + _tNeuron* n = *nr; | |
| 540 | 744 | n->gK = K; |
| 541 | 745 | } |
| 542 | 746 | |
| 543 | −void tNeuron_setL(tNeuron* const n, float L) | |
| 747 | +void tNeuron_setL(tNeuron* const nr, float L) | |
| 544 | 748 | { |
| 749 | + _tNeuron* n = *nr; | |
| 545 | 750 | n->gL = L; |
| 546 | 751 | n->rate[2] = n->gL/n->C; |
| 547 | 752 | } |
| 548 | 753 | |
| 549 | −void tNeuron_setN(tNeuron* const n, float N) | |
| 754 | +void tNeuron_setN(tNeuron* const nr, float N) | |
| 550 | 755 | { |
| 756 | + _tNeuron* n = *nr; | |
| 551 | 757 | n->gN = N; |
| 552 | 758 | } |
| 553 | 759 | |
| 554 | −void tNeuron_setC(tNeuron* const n, float C) | |
| 760 | +void tNeuron_setC(tNeuron* const nr, float C) | |
| 555 | 761 | { |
| 762 | + _tNeuron* n = *nr; | |
| 556 | 763 | n->C = C; |
| 557 | 764 | n->rate[2] = n->gL/n->C; |
| 558 | 765 | } |
| 559 | 766 | |
| 560 | −float tNeuron_tick(tNeuron* const n) | |
| 767 | +float tNeuron_tick(tNeuron* const nr) | |
| 561 | 768 | { |
| 769 | + _tNeuron* n = *nr; | |
| 770 | + | |
| 562 | 771 | float output = 0.0f; |
| 563 | 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 | |
| 634 | −void tNeuron_setMode (tNeuron* const n, NeuronMode mode) | |
| 843 | +void tNeuron_setMode (tNeuron* const nr, NeuronMode mode) | |
| 635 | 844 | { |
| 845 | + _tNeuron* n = *nr; | |
| 636 | 846 | n->mode = mode; |
| 637 | 847 | } |
| 638 | 848 | |
| 639 | −void tNeuron_setCurrent (tNeuron* const n, float current) | |
| 849 | +void tNeuron_setCurrent (tNeuron* const nr, float current) | |
| 640 | 850 | { |
| 851 | + _tNeuron* n = *nr; | |
| 641 | 852 | n->current = current; |
| 642 | 853 | } |
| @@ -46,6 +46,37 @@ void tPluck_free (tPluck* const pl) · 45 unmodified lines | ||
| 46 | 46 | leaf_free(p); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | +void tPluck_initToPool (tPluck* const pl, float lowestFrequency, tMempool* const mp) | |
| 50 | +{ | |
| 51 | + _tMempool* m = *mp; | |
| 52 | + _tPluck* p = *pl = (_tPluck*) mpool_alloc(sizeof(_tPluck), m->pool); | |
| 53 | + | |
| 54 | + if ( lowestFrequency <= 0.0f ) lowestFrequency = 10.0f; | |
| 55 | + | |
| 56 | + tNoise_initToPool(&p->noise, WhiteNoise, mp); | |
| 57 | + | |
| 58 | + tOnePole_initToPool(&p->pickFilter, 0.0f, mp); | |
| 59 | + | |
| 60 | + tOneZero_initToPool(&p->loopFilter, 0.0f, mp); | |
| 61 | + | |
| 62 | + tAllpassDelay_initToPool(&p->delayLine, 0.0f, leaf.sampleRate * 2, mp); | |
| 63 | + | |
| 64 | + tPluck_setFrequency(pl, 220.0f); | |
| 65 | +} | |
| 66 | + | |
| 67 | +void tPluck_freeFromPool (tPluck* const pl, tMempool* const mp) | |
| 68 | +{ | |
| 69 | + _tMempool* m = *mp; | |
| 70 | + _tPluck* p = *pl; | |
| 71 | + | |
| 72 | + tNoise_freeFromPool(&p->noise, mp); | |
| 73 | + tOnePole_freeFromPool(&p->pickFilter, mp); | |
| 74 | + tOneZero_freeFromPool(&p->loopFilter, mp); | |
| 75 | + tAllpassDelay_freeFromPool(&p->delayLine, mp); | |
| 76 | + | |
| 77 | + mpool_free(p, m->pool); | |
| 78 | +} | |
| 79 | + | |
| 49 | 80 | float tPluck_getLastOut (tPluck* const pl) |
| 50 | 81 | { |
| 51 | 82 | _tPluck* p = *pl; |
| @@ -124,7 +155,7 @@ void tPluckSampleRateChanged(tPluck* const pl) · 72 unmodified lines | ||
| 124 | 155 | } |
| 125 | 156 | |
| 126 | 157 | /* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tKarplusStrong ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */ |
| 127 | −void tKarplusStrong_init (tKarplusStrong* const pl, float lowestFrequency) | |
| 158 | +void tKarplusStrong_init (tKarplusStrong* const pl, float lowestFrequency) | |
| 128 | 159 | { |
| 129 | 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 | 182 | p->loopGain = 0.999f; |
| 152 | 183 | |
| 153 | 184 | tKarplusStrong_setFrequency( pl, 220.0f ); |
| 154 | − | |
| 155 | 185 | } |
| 156 | 186 | |
| 157 | 187 | void tKarplusStrong_free (tKarplusStrong* const pl) |
| @@ -171,6 +201,54 @@ void tKarplusStrong_free (tKarplusStrong* const pl) · 13 unmodified lines | ||
| 171 | 201 | leaf_free(p); |
| 172 | 202 | } |
| 173 | 203 | |
| 204 | +void tKarplusStrong_initToPool (tKarplusStrong* const pl, float lowestFrequency, tMempool* const mp) | |
| 205 | +{ | |
| 206 | + _tMempool* m = *mp; | |
| 207 | + _tKarplusStrong* p = *pl = (_tKarplusStrong*) mpool_alloc(sizeof(_tKarplusStrong), m->pool); | |
| 208 | + | |
| 209 | + if ( lowestFrequency <= 0.0f ) lowestFrequency = 8.0f; | |
| 210 | + | |
| 211 | + tAllpassDelay_initToPool(&p->delayLine, 0.0f, leaf.sampleRate * 2, mp); | |
| 212 | + | |
| 213 | + tLinearDelay_initToPool(&p->combDelay, 0.0f, leaf.sampleRate * 2, mp); | |
| 214 | + | |
| 215 | + tOneZero_initToPool(&p->filter, 0.0f, mp); | |
| 216 | + | |
| 217 | + tNoise_initToPool(&p->noise, WhiteNoise, mp); | |
| 218 | + | |
| 219 | + for (int i = 0; i < 4; i++) | |
| 220 | + { | |
| 221 | + tBiQuad_initToPool(&p->biquad[i], mp); | |
| 222 | + } | |
| 223 | + | |
| 224 | + p->pluckAmplitude = 0.3f; | |
| 225 | + p->pickupPosition = 0.4f; | |
| 226 | + | |
| 227 | + p->stretching = 0.9999f; | |
| 228 | + p->baseLoopGain = 0.995f; | |
| 229 | + p->loopGain = 0.999f; | |
| 230 | + | |
| 231 | + tKarplusStrong_setFrequency( pl, 220.0f ); | |
| 232 | +} | |
| 233 | + | |
| 234 | +void tKarplusStrong_freeFromPool (tKarplusStrong* const pl, tMempool* const mp) | |
| 235 | +{ | |
| 236 | + _tMempool* m = *mp; | |
| 237 | + _tKarplusStrong* p = *pl; | |
| 238 | + | |
| 239 | + tAllpassDelay_freeFromPool(&p->delayLine, mp); | |
| 240 | + tLinearDelay_freeFromPool(&p->combDelay, mp); | |
| 241 | + tOneZero_freeFromPool(&p->filter, mp); | |
| 242 | + tNoise_freeFromPool(&p->noise, mp); | |
| 243 | + | |
| 244 | + for (int i = 0; i < 4; i++) | |
| 245 | + { | |
| 246 | + tBiQuad_freeFromPool(&p->biquad[i], mp); | |
| 247 | + } | |
| 248 | + | |
| 249 | + mpool_free(p, m->pool); | |
| 250 | +} | |
| 251 | + | |
| 174 | 252 | float tKarplusStrong_getLastOut (tKarplusStrong* const pl) |
| 175 | 253 | { |
| 176 | 254 | _tKarplusStrong* p = *pl; |
| @@ -328,7 +406,9 @@ void tKarplusStrongSampleRateChanged (tKarplusStrong* const pl) · 151 unmodified lines | ||
| 328 | 406 | |
| 329 | 407 | /* Simple Living String*/ |
| 330 | 408 | |
| 331 | −void tSimpleLivingString_init(tSimpleLivingString* const pl, float freq, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode) | |
| 409 | +void tSimpleLivingString_init(tSimpleLivingString* const pl, float freq, float dampFreq, | |
| 410 | + float decay, float targetLev, float levSmoothFactor, | |
| 411 | + float levStrength, int levMode) | |
| 332 | 412 | { |
| 333 | 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 | 436 | leaf_free(p); |
| 357 | 437 | } |
| 358 | 438 | |
| 439 | +void tSimpleLivingString_initToPool (tSimpleLivingString* const pl, float freq, float dampFreq, | |
| 440 | + float decay, float targetLev, float levSmoothFactor, | |
| 441 | + float levStrength, int levMode, tMempool* const mp) | |
| 442 | +{ | |
| 443 | + _tMempool* m = *mp; | |
| 444 | + _tSimpleLivingString* p = *pl = (_tSimpleLivingString*) mpool_alloc(sizeof(_tSimpleLivingString), m->pool); | |
| 445 | + | |
| 446 | + p->curr=0.0f; | |
| 447 | + tExpSmooth_initToPool(&p->wlSmooth, leaf.sampleRate/freq, 0.01, mp); // smoother for string wavelength (not freq, to avoid expensive divisions) | |
| 448 | + tSimpleLivingString_setFreq(pl, freq); | |
| 449 | + tLinearDelay_initToPool(&p->delayLine,p->waveLengthInSamples, 2400, mp); | |
| 450 | + tOnePole_initToPool(&p->bridgeFilter, dampFreq, mp); | |
| 451 | + tHighpass_initToPool(&p->DCblocker,13, mp); | |
| 452 | + p->decay=decay; | |
| 453 | + tFeedbackLeveler_initToPool(&p->fbLev, targetLev, levSmoothFactor, levStrength, levMode, mp); | |
| 454 | + p->levMode=levMode; | |
| 455 | +} | |
| 456 | + | |
| 457 | +void tSimpleLivingString_freeFromPool (tSimpleLivingString* const pl, tMempool* const mp) | |
| 458 | +{ | |
| 459 | + _tMempool* m = *mp; | |
| 460 | + _tSimpleLivingString* p = *pl; | |
| 461 | + | |
| 462 | + tExpSmooth_freeFromPool(&p->wlSmooth, mp); | |
| 463 | + tLinearDelay_freeFromPool(&p->delayLine, mp); | |
| 464 | + tOnePole_freeFromPool(&p->bridgeFilter, mp); | |
| 465 | + tHighpass_freeFromPool(&p->DCblocker, mp); | |
| 466 | + tFeedbackLeveler_freeFromPool(&p->fbLev, mp); | |
| 467 | + | |
| 468 | + mpool_free(p, m->pool); | |
| 469 | +} | |
| 470 | + | |
| 359 | 471 | void tSimpleLivingString_setFreq(tSimpleLivingString* const pl, float freq) |
| 360 | 472 | { |
| 361 | 473 | _tSimpleLivingString* p = *pl; |
| @@ -433,7 +545,9 @@ float tSimpleLivingString_sample(tSimpleLivingString* const pl) · 71 unmodified lines | ||
| 433 | 545 | |
| 434 | 546 | /* Living String*/ |
| 435 | 547 | |
| 436 | −void tLivingString_init(tLivingString* const pl, float freq, float pickPos, float prepIndex, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode) | |
| 548 | +void tLivingString_init(tLivingString* const pl, float freq, float pickPos, float prepIndex, | |
| 549 | + float dampFreq, float decay, float targetLev, float levSmoothFactor, | |
| 550 | + float levStrength, int levMode) | |
| 437 | 551 | { |
| 438 | 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 | 598 | leaf_free(p); |
| 485 | 599 | } |
| 486 | 600 | |
| 601 | +void tLivingString_initToPool (tLivingString* const pl, float freq, float pickPos, float prepIndex, | |
| 602 | + float dampFreq, float decay, float targetLev, float levSmoothFactor, | |
| 603 | + float levStrength, int levMode, tMempool* const mp) | |
| 604 | +{ | |
| 605 | + _tMempool* m = *mp; | |
| 606 | + _tLivingString* p = *pl = (_tLivingString*) mpool_alloc(sizeof(_tLivingString), m->pool); | |
| 607 | + | |
| 608 | + p->curr=0.0f; | |
| 609 | + tExpSmooth_initToPool(&p->wlSmooth, leaf.sampleRate/freq, 0.01, mp); // smoother for string wavelength (not freq, to avoid expensive divisions) | |
| 610 | + tLivingString_setFreq(pl, freq); | |
| 611 | + p->freq = freq; | |
| 612 | + tExpSmooth_initToPool(&p->ppSmooth, pickPos, 0.01, mp); // smoother for pick position | |
| 613 | + tLivingString_setPickPos(pl, pickPos); | |
| 614 | + p->prepIndex=prepIndex; | |
| 615 | + tLinearDelay_initToPool(&p->delLF,p->waveLengthInSamples, 2400, mp); | |
| 616 | + tLinearDelay_initToPool(&p->delUF,p->waveLengthInSamples, 2400, mp); | |
| 617 | + tLinearDelay_initToPool(&p->delUB,p->waveLengthInSamples, 2400, mp); | |
| 618 | + tLinearDelay_initToPool(&p->delLB,p->waveLengthInSamples, 2400, mp); | |
| 619 | + p->dampFreq = dampFreq; | |
| 620 | + tOnePole_initToPool(&p->bridgeFilter, dampFreq, mp); | |
| 621 | + tOnePole_initToPool(&p->nutFilter, dampFreq, mp); | |
| 622 | + tOnePole_initToPool(&p->prepFilterU, dampFreq, mp); | |
| 623 | + tOnePole_initToPool(&p->prepFilterL, dampFreq, mp); | |
| 624 | + tHighpass_initToPool(&p->DCblockerU,13, mp); | |
| 625 | + tHighpass_initToPool(&p->DCblockerL,13, mp); | |
| 626 | + p->decay=decay; | |
| 627 | + p->prepIndex = prepIndex; | |
| 628 | + tFeedbackLeveler_initToPool(&p->fbLevU, targetLev, levSmoothFactor, levStrength, levMode, mp); | |
| 629 | + tFeedbackLeveler_initToPool(&p->fbLevL, targetLev, levSmoothFactor, levStrength, levMode, mp); | |
| 630 | + p->levMode=levMode; | |
| 631 | +} | |
| 632 | + | |
| 633 | +void tLivingString_freeFromPool (tLivingString* const pl, tMempool* const mp) | |
| 634 | +{ | |
| 635 | + _tMempool* m = *mp; | |
| 636 | + _tLivingString* p = *pl; | |
| 637 | + | |
| 638 | + tExpSmooth_freeFromPool(&p->wlSmooth, mp); | |
| 639 | + tExpSmooth_freeFromPool(&p->ppSmooth, mp); | |
| 640 | + tLinearDelay_freeFromPool(&p->delLF, mp); | |
| 641 | + tLinearDelay_freeFromPool(&p->delUF, mp); | |
| 642 | + tLinearDelay_freeFromPool(&p->delUB, mp); | |
| 643 | + tLinearDelay_freeFromPool(&p->delLB, mp); | |
| 644 | + tOnePole_freeFromPool(&p->bridgeFilter, mp); | |
| 645 | + tOnePole_freeFromPool(&p->nutFilter, mp); | |
| 646 | + tOnePole_freeFromPool(&p->prepFilterU, mp); | |
| 647 | + tOnePole_freeFromPool(&p->prepFilterL, mp); | |
| 648 | + tHighpass_freeFromPool(&p->DCblockerU, mp); | |
| 649 | + tHighpass_freeFromPool(&p->DCblockerL, mp); | |
| 650 | + tFeedbackLeveler_freeFromPool(&p->fbLevU, mp); | |
| 651 | + tFeedbackLeveler_freeFromPool(&p->fbLevL, mp); | |
| 652 | + | |
| 653 | + mpool_free(p, m->pool); | |
| 654 | +} | |
| 655 | + | |
| 487 | 656 | void tLivingString_setFreq(tLivingString* const pl, float freq) |
| 488 | 657 | { // NOTE: It is faster to set wavelength in samples directly |
| 489 | 658 | _tLivingString* p = *pl; |
| @@ -577,20 +746,20 @@ float tLivingString_tick(tLivingString* const pl, float input) · 87 unmodified lines | ||
| 577 | 746 | tLinearDelay_tickIn(&p->delUB, fromNut); |
| 578 | 747 | // into lower half of string, from pickpoint, going backwards |
| 579 | 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 | 750 | tLinearDelay_tickIn(&p->delLB, intoLower); |
| 582 | 751 | // 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 | 753 | tLinearDelay_tickIn(&p->delLF, fromBridge); |
| 585 | 754 | // into upper half of string, from pickpoint, going forwards/upwards |
| 586 | 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 | 757 | tLinearDelay_tickIn(&p->delUF, intoUpper); |
| 589 | 758 | // update all delay lengths |
| 590 | 759 | float pickP=tExpSmooth_tick(&p->ppSmooth); |
| 591 | 760 | float wLen=tExpSmooth_tick(&p->wlSmooth); |
| 592 | 761 | float lowLen=pickP*wLen; |
| 593 | − float upLen=(1-pickP)*wLen; | |
| 762 | + float upLen=(1.0f-pickP)*wLen; | |
| 594 | 763 | tLinearDelay_setDelay(&p->delLF, lowLen); |
| 595 | 764 | tLinearDelay_setDelay(&p->delLB, lowLen); |
| 596 | 765 | tLinearDelay_setDelay(&p->delUF, upLen); |
| @@ -623,6 +792,23 @@ void tReedTable_free (tReedTable* const pm) · 26 unmodified lines | ||
| 623 | 792 | leaf_free(p); |
| 624 | 793 | } |
| 625 | 794 | |
| 795 | +void tReedTable_initToPool (tReedTable* const pm, float offset, float slope, tMempool* const mp) | |
| 796 | +{ | |
| 797 | + _tMempool* m = *mp; | |
| 798 | + _tReedTable* p = *pm = (_tReedTable*) mpool_alloc(sizeof(_tReedTable), m->pool); | |
| 799 | + | |
| 800 | + p->offset = offset; | |
| 801 | + p->slope = slope; | |
| 802 | +} | |
| 803 | + | |
| 804 | +void tReedTable_freeFromPool (tReedTable* const pm, tMempool* const mp) | |
| 805 | +{ | |
| 806 | + _tMempool* m = *mp; | |
| 807 | + _tReedTable* p = *pm; | |
| 808 | + | |
| 809 | + mpool_free(p, m->pool); | |
| 810 | +} | |
| 811 | + | |
| 626 | 812 | float tReedTable_tick (tReedTable* const pm, float input) |
| 627 | 813 | { |
| 628 | 814 | _tReedTable* p = *pm; |
| @@ -65,6 +65,54 @@ void tPRCReverb_free(tPRCReverb* const rev) · 64 unmodified lines | ||
| 65 | 65 | leaf_free(r); |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | +void tPRCReverb_initToPool (tPRCReverb* const rev, float t60, tMempool* const mp) | |
| 69 | +{ | |
| 70 | + _tMempool* m = *mp; | |
| 71 | + _tPRCReverb* r = *rev = (_tPRCReverb*) mpool_alloc(sizeof(_tPRCReverb), m->pool); | |
| 72 | + | |
| 73 | + if (t60 <= 0.0f) t60 = 0.001f; | |
| 74 | + | |
| 75 | + r->inv_441 = 1.0f/44100.0f; | |
| 76 | + | |
| 77 | + int lengths[4] = { 341, 613, 1557, 2137 }; // Delay lengths for 44100 Hz sample rate. | |
| 78 | + double scaler = leaf.sampleRate * r->inv_441; | |
| 79 | + | |
| 80 | + int delay, i; | |
| 81 | + if (scaler != 1.0f) | |
| 82 | + { | |
| 83 | + for (i=0; i<4; i++) | |
| 84 | + { | |
| 85 | + delay = (int) scaler * lengths[i]; | |
| 86 | + | |
| 87 | + if ( (delay & 1) == 0) delay++; | |
| 88 | + | |
| 89 | + while ( !LEAF_isPrime(delay) ) delay += 2; | |
| 90 | + | |
| 91 | + lengths[i] = delay; | |
| 92 | + } | |
| 93 | + } | |
| 94 | + | |
| 95 | + tDelay_initToPool(&r->allpassDelays[0], lengths[0], lengths[0] * 2, mp); | |
| 96 | + tDelay_initToPool(&r->allpassDelays[1], lengths[1], lengths[1] * 2, mp); | |
| 97 | + tDelay_initToPool(&r->combDelay, lengths[2], lengths[2] * 2, mp); | |
| 98 | + | |
| 99 | + tPRCReverb_setT60(rev, t60); | |
| 100 | + | |
| 101 | + r->allpassCoeff = 0.7f; | |
| 102 | + r->mix = 0.5f; | |
| 103 | +} | |
| 104 | + | |
| 105 | +void tPRCReverb_freeFromPool (tPRCReverb* const rev, tMempool* const mp) | |
| 106 | +{ | |
| 107 | + _tMempool* m = *mp; | |
| 108 | + _tPRCReverb* r = *rev; | |
| 109 | + | |
| 110 | + tDelay_freeFromPool(&r->allpassDelays[0], mp); | |
| 111 | + tDelay_freeFromPool(&r->allpassDelays[1], mp); | |
| 112 | + tDelay_freeFromPool(&r->combDelay, mp); | |
| 113 | + mpool_free(r, m->pool); | |
| 114 | +} | |
| 115 | + | |
| 68 | 116 | void tPRCReverb_setT60(tPRCReverb* const rev, float t60) |
| 69 | 117 | { |
| 70 | 118 | _tPRCReverb* r = *rev; |
| @@ -150,12 +198,14 @@ void tNReverb_init(tNReverb* const rev, float t60) · 79 unmodified lines | ||
| 150 | 198 | for ( i=0; i<6; i++ ) |
| 151 | 199 | { |
| 152 | 200 | tLinearDelay_init(&r->combDelays[i], lengths[i], lengths[i] * 2.0f); |
| 201 | + tLinearDelay_clear(&r->combDelays[i]); | |
| 153 | 202 | r->combCoeffs[i] = pow(10.0, (-3 * lengths[i] * leaf.invSampleRate / t60)); |
| 154 | 203 | } |
| 155 | 204 | |
| 156 | 205 | for ( i=0; i<8; i++ ) |
| 157 | 206 | { |
| 158 | 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 | 231 | leaf_free(r); |
| 182 | 232 | } |
| 183 | 233 | |
| 234 | +void tNReverb_initToPool (tNReverb* const rev, float t60, tMempool* const mp) | |
| 235 | +{ | |
| 236 | + _tMempool* m = *mp; | |
| 237 | + _tNReverb* r = *rev = (_tNReverb*) mpool_alloc(sizeof(_tNReverb), m->pool); | |
| 238 | + | |
| 239 | + if (t60 <= 0.0f) t60 = 0.001f; | |
| 240 | + | |
| 241 | + r->inv_441 = 1.0f/44100.0f; | |
| 242 | + | |
| 243 | + int lengths[15] = {1433, 1601, 1867, 2053, 2251, 2399, 347, 113, 37, 59, 53, 43, 37, 29, 19}; // Delay lengths for 44100 Hz sample rate. | |
| 244 | + double scaler = leaf.sampleRate / 25641.0f; | |
| 245 | + | |
| 246 | + int delay, i; | |
| 247 | + | |
| 248 | + for (i=0; i < 15; i++) | |
| 249 | + { | |
| 250 | + delay = (int) scaler * lengths[i]; | |
| 251 | + if ( (delay & 1) == 0) | |
| 252 | + delay++; | |
| 253 | + while ( !LEAF_isPrime(delay) ) | |
| 254 | + delay += 2; | |
| 255 | + lengths[i] = delay; | |
| 256 | + } | |
| 257 | + | |
| 258 | + for ( i=0; i<6; i++ ) | |
| 259 | + { | |
| 260 | + tLinearDelay_initToPool(&r->combDelays[i], lengths[i], lengths[i] * 2.0f, mp); | |
| 261 | + r->combCoeffs[i] = pow(10.0, (-3 * lengths[i] * leaf.invSampleRate / t60)); | |
| 262 | + } | |
| 263 | + | |
| 264 | + for ( i=0; i<8; i++ ) | |
| 265 | + { | |
| 266 | + tLinearDelay_initToPool(&r->allpassDelays[i], lengths[i+6], lengths[i+6] * 2.0f, mp); | |
| 267 | + } | |
| 268 | + | |
| 269 | + | |
| 270 | + tNReverb_setT60(rev, t60); | |
| 271 | + r->allpassCoeff = 0.7f; | |
| 272 | + r->mix = 0.3f; | |
| 273 | +} | |
| 274 | + | |
| 275 | +void tNReverb_freeFromPool (tNReverb* const rev, tMempool* const mp) | |
| 276 | +{ | |
| 277 | + _tMempool* m = *mp; | |
| 278 | + _tNReverb* r = *rev; | |
| 279 | + | |
| 280 | + for (int i = 0; i < 6; i++) | |
| 281 | + { | |
| 282 | + tLinearDelay_freeFromPool(&r->combDelays[i], mp); | |
| 283 | + } | |
| 284 | + | |
| 285 | + for (int i = 0; i < 8; i++) | |
| 286 | + { | |
| 287 | + tLinearDelay_freeFromPool(&r->allpassDelays[i], mp); | |
| 288 | + } | |
| 289 | + | |
| 290 | + mpool_free(r, m->pool); | |
| 291 | +} | |
| 292 | + | |
| 184 | 293 | void tNReverb_setT60(tNReverb* const rev, float t60) |
| 185 | 294 | { |
| 186 | 295 | _tNReverb* r = *rev; |
| @@ -204,7 +313,7 @@ float tNReverb_tick(tNReverb* const rev, float input) · 17 unmodified lines | ||
| 204 | 313 | _tNReverb* r = *rev; |
| 205 | 314 | r->lastIn = input; |
| 206 | 315 | |
| 207 | − float temp, temp0, temp1, temp2, temp3, out; | |
| 316 | + float temp, temp0, temp1, temp2, out; | |
| 208 | 317 | int i; |
| 209 | 318 | |
| 210 | 319 | temp0 = 0.0; |
| @@ -381,8 +490,6 @@ void tDattorroReverb_init (tDattorroReverb* const rev) · 170 unmodified lines | ||
| 381 | 490 | tDattorroReverb_setFeedbackFilter(rev, 5000.f); |
| 382 | 491 | |
| 383 | 492 | tDattorroReverb_setFeedbackGain(rev, 0.4f); |
| 384 | − | |
| 385 | − | |
| 386 | 493 | } |
| 387 | 494 | |
| 388 | 495 | void tDattorroReverb_free (tDattorroReverb* const rev) |
| @@ -427,6 +534,111 @@ void tDattorroReverb_free (tDattorroReverb* const rev) · 38 unmodified lines | ||
| 427 | 534 | leaf_free(r); |
| 428 | 535 | } |
| 429 | 536 | |
| 537 | +void tDattorroReverb_initToPool (tDattorroReverb* const rev, tMempool* const mp) | |
| 538 | +{ | |
| 539 | + _tMempool* m = *mp; | |
| 540 | + _tDattorroReverb* r = *rev = (_tDattorroReverb*) mpool_alloc(sizeof(_tDattorroReverb), m->pool); | |
| 541 | + | |
| 542 | + r->size_max = 2.0f; | |
| 543 | + r->size = 1.f; | |
| 544 | + r->t = r->size * leaf.sampleRate * 0.001f; | |
| 545 | + r->frozen = 0; | |
| 546 | + // INPUT | |
| 547 | + tTapeDelay_initToPool(&r->in_delay, 0.f, SAMP(200.f), mp); | |
| 548 | + tOnePole_initToPool(&r->in_filter, 1.f, mp); | |
| 549 | + | |
| 550 | + for (int i = 0; i < 4; i++) | |
| 551 | + { | |
| 552 | + tAllpass_initToPool(&r->in_allpass[i], SAMP(in_allpass_delays[i]), SAMP(20.f), mp); // * r->size_max | |
| 553 | + tAllpass_setGain(&r->in_allpass[i], in_allpass_gains[i]); | |
| 554 | + } | |
| 555 | + | |
| 556 | + // FEEDBACK 1 | |
| 557 | + tAllpass_initToPool(&r->f1_allpass, SAMP(30.51f), SAMP(100.f), mp); // * r->size_max | |
| 558 | + tAllpass_setGain(&r->f1_allpass, 0.7f); | |
| 559 | + | |
| 560 | + tTapeDelay_initToPool(&r->f1_delay_1, SAMP(141.69f), SAMP(200.0f) * r->size_max + 1, mp); | |
| 561 | + tTapeDelay_initToPool(&r->f1_delay_2, SAMP(89.24f), SAMP(100.0f) * r->size_max + 1, mp); | |
| 562 | + tTapeDelay_initToPool(&r->f1_delay_3, SAMP(125.f), SAMP(200.0f) * r->size_max + 1, mp); | |
| 563 | + | |
| 564 | + tOnePole_initToPool(&r->f1_filter, 1.f, mp); | |
| 565 | + | |
| 566 | + tHighpass_initToPool(&r->f1_hp, 20.f, mp); | |
| 567 | + | |
| 568 | + tCycle_initToPool(&r->f1_lfo, mp); | |
| 569 | + tCycle_setFreq(&r->f1_lfo, 0.1f); | |
| 570 | + | |
| 571 | + // FEEDBACK 2 | |
| 572 | + tAllpass_initToPool(&r->f2_allpass, SAMP(22.58f), SAMP(100.f), mp); // * r->size_max | |
| 573 | + tAllpass_setGain(&r->f2_allpass, 0.7f); | |
| 574 | + | |
| 575 | + tTapeDelay_initToPool(&r->f2_delay_1, SAMP(149.62f), SAMP(200.f) * r->size_max + 1, mp); | |
| 576 | + tTapeDelay_initToPool(&r->f2_delay_2, SAMP(60.48f), SAMP(100.f) * r->size_max + 1, mp); | |
| 577 | + tTapeDelay_initToPool(&r->f2_delay_3, SAMP(106.28f), SAMP(200.f) * r->size_max + 1, mp); | |
| 578 | + | |
| 579 | + tOnePole_initToPool(&r->f2_filter, 1.f, mp); | |
| 580 | + | |
| 581 | + tHighpass_initToPool(&r->f2_hp, 20.f, mp); | |
| 582 | + | |
| 583 | + tCycle_initToPool(&r->f2_lfo, mp); | |
| 584 | + tCycle_setFreq(&r->f2_lfo, 0.07f); | |
| 585 | + | |
| 586 | + | |
| 587 | + // PARAMETERS | |
| 588 | + tDattorroReverb_setMix(rev, 0.5f); | |
| 589 | + | |
| 590 | + tDattorroReverb_setInputDelay(rev, 0.f); | |
| 591 | + | |
| 592 | + tDattorroReverb_setInputFilter(rev, 10000.f); | |
| 593 | + | |
| 594 | + tDattorroReverb_setFeedbackFilter(rev, 5000.f); | |
| 595 | + | |
| 596 | + tDattorroReverb_setFeedbackGain(rev, 0.4f); | |
| 597 | +} | |
| 598 | + | |
| 599 | +void tDattorroReverb_freeFromPool (tDattorroReverb* const rev, tMempool* const mp) | |
| 600 | +{ | |
| 601 | + _tMempool* m = *mp; | |
| 602 | + _tDattorroReverb* r = *rev; | |
| 603 | + | |
| 604 | + // INPUT | |
| 605 | + tTapeDelay_freeFromPool(&r->in_delay, mp); | |
| 606 | + tOnePole_freeFromPool(&r->in_filter, mp); | |
| 607 | + | |
| 608 | + for (int i = 0; i < 4; i++) | |
| 609 | + { | |
| 610 | + tAllpass_freeFromPool(&r->in_allpass[i], mp); | |
| 611 | + } | |
| 612 | + | |
| 613 | + // FEEDBACK 1 | |
| 614 | + tAllpass_freeFromPool(&r->f1_allpass, mp); | |
| 615 | + | |
| 616 | + tTapeDelay_freeFromPool(&r->f1_delay_1, mp); | |
| 617 | + tTapeDelay_freeFromPool(&r->f1_delay_2, mp); | |
| 618 | + tTapeDelay_freeFromPool(&r->f1_delay_3, mp); | |
| 619 | + | |
| 620 | + tOnePole_freeFromPool(&r->f1_filter, mp); | |
| 621 | + | |
| 622 | + tHighpass_freeFromPool(&r->f1_hp, mp); | |
| 623 | + | |
| 624 | + tCycle_freeFromPool(&r->f1_lfo, mp); | |
| 625 | + | |
| 626 | + // FEEDBACK 2 | |
| 627 | + tAllpass_freeFromPool(&r->f2_allpass, mp); | |
| 628 | + | |
| 629 | + tTapeDelay_freeFromPool(&r->f2_delay_1, mp); | |
| 630 | + tTapeDelay_freeFromPool(&r->f2_delay_2, mp); | |
| 631 | + tTapeDelay_freeFromPool(&r->f2_delay_3, mp); | |
| 632 | + | |
| 633 | + tOnePole_freeFromPool(&r->f2_filter, mp); | |
| 634 | + | |
| 635 | + tHighpass_freeFromPool(&r->f2_hp, mp); | |
| 636 | + | |
| 637 | + tCycle_freeFromPool(&r->f2_lfo, mp); | |
| 638 | + | |
| 639 | + mpool_free(r, m->pool); | |
| 640 | +} | |
| 641 | + | |
| 430 | 642 | float tDattorroReverb_tick (tDattorroReverb* const rev, float input) |
| 431 | 643 | { |
| 432 | 644 | _tDattorroReverb* r = *rev; |
| @@ -35,22 +35,6 @@ void tBuffer_init (tBuffer* const sb, uint32_t length) · 34 unmodified lines | ||
| 35 | 35 | s->active = 0; |
| 36 | 36 | s->idx = 0; |
| 37 | 37 | s->mode = RecordOneShot; |
| 38 | − | |
| 39 | − tBuffer_clear(sb); | |
| 40 | −} | |
| 41 | − | |
| 42 | −void tBuffer_init_locate (tBuffer* const sb, uint32_t length, mpool_t* pool) | |
| 43 | −{ | |
| 44 | − _tBuffer* s = *sb = (_tBuffer*) mpool_alloc(sizeof(_tBuffer), pool); | |
| 45 | − | |
| 46 | − s->buff = (float*) mpool_alloc( sizeof(float) * length, pool); | |
| 47 | − | |
| 48 | − s->bufferLength = length; | |
| 49 | − s->recordedLength = 0; | |
| 50 | − s->idx = 0; | |
| 51 | − s->mode = RecordOneShot; | |
| 52 | − | |
| 53 | − tBuffer_clear(sb); | |
| 54 | 38 | } |
| 55 | 39 | |
| 56 | 40 | void tBuffer_free (tBuffer* const sb) |
| @@ -61,15 +45,28 @@ void tBuffer_free (tBuffer* const sb) · 4 unmodified lines | ||
| 61 | 45 | leaf_free(s); |
| 62 | 46 | } |
| 63 | 47 | |
| 64 | −void tBuffer_free_locate (tBuffer* const sb, mpool_t* pool) | |
| 48 | +void 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 | + | |
| 61 | +void tBuffer_freeFromPool (tBuffer* const sb, tMempool* const mp) | |
| 62 | +{ | |
| 63 | + _tMempool* m = *mp; | |
| 66 | 64 | _tBuffer* s = *sb; |
| 67 | 65 | |
| 68 | − mpool_free(s->buff, pool); | |
| 69 | − mpool_free(s, pool); | |
| 66 | + mpool_free(s->buff, m->pool); | |
| 67 | + mpool_free(s, m->pool); | |
| 70 | 68 | } |
| 71 | 69 | |
| 72 | − | |
| 73 | 70 | void tBuffer_tick (tBuffer* const sb, float sample) |
| 74 | 71 | { |
| 75 | 72 | _tBuffer* s = *sb; |