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