Showing the changes to LEAF/Src_cpp/leaf-string.cpp (1 of 147 files). Show all
Unified · Split
| @@ -0,0 +1,294 @@ | |||
| 1 | /* | ||
| 2 | ============================================================================== | ||
| 3 | |||
| 4 | leaf-string.cpp | ||
| 5 | Created: 30 Nov 2018 10:41:42am | ||
| 6 | Author: airship | ||
| 7 | |||
| 8 | ============================================================================== | ||
| 9 | */ | ||
| 10 | |||
| 11 | #if _WIN32 || _WIN64 | ||
| 12 | |||
| 13 | #include "..\Inc\leaf-string.h" | ||
| 14 | |||
| 15 | #else | ||
| 16 | |||
| 17 | #include "../Inc/leaf-string.h" | ||
| 18 | |||
| 19 | #endif | ||
| 20 | |||
| 21 | /* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tPluck ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */ | ||
| 22 | void tPluck_init (tPluck* const p, float lowestFrequency) | ||
| 23 | { | ||
| 24 | if ( lowestFrequency <= 0.0f ) lowestFrequency = 10.0f; | ||
| 25 | |||
| 26 | p->noise = (tNoise*)leaf_alloc(sizeof(tNoise)); | ||
| 27 | tNoise_init(p->noise, WhiteNoise); | ||
| 28 | |||
| 29 | p->pickFilter = (tOnePole*) leaf_alloc(sizeof(tOnePole)); | ||
| 30 | tOnePole_init(p->pickFilter, 0.0f); | ||
| 31 | |||
| 32 | p->loopFilter = (tOneZero*) leaf_alloc(sizeof(tOneZero)); | ||
| 33 | tOneZero_init(p->loopFilter, 0.0f); | ||
| 34 | |||
| 35 | p->delayLine = (tDelayA*) leaf_alloc(sizeof(tDelayA)); | ||
| 36 | tDelayA_init(p->delayLine, 0.0f, leaf.sampleRate * 2); | ||
| 37 | |||
| 38 | tPluck_setFrequency(p, 220.0f); | ||
| 39 | } | ||
| 40 | |||
| 41 | float tPluck_getLastOut (tPluck *p) | ||
| 42 | { | ||
| 43 | return p->lastOut; | ||
| 44 | } | ||
| 45 | |||
| 46 | float tPluck_tick (tPluck *p) | ||
| 47 | { | ||
| 48 | return (p->lastOut = 3.0f * tDelayA_tick(p->delayLine, tOneZero_tick(p->loopFilter, tDelayA_getLastOut(p->delayLine) * p->loopGain ) )); | ||
| 49 | } | ||
| 50 | |||
| 51 | void tPluck_pluck (tPluck* const p, float amplitude) | ||
| 52 | { | ||
| 53 | if ( amplitude < 0.0f) amplitude = 0.0f; | ||
| 54 | else if (amplitude > 1.0f) amplitude = 1.0f; | ||
| 55 | |||
| 56 | tOnePole_setPole(p->pickFilter, 0.999f - (amplitude * 0.15f)); | ||
| 57 | tOnePole_setGain(p->pickFilter, amplitude * 0.5f ); | ||
| 58 | |||
| 59 | // Fill delay with noise additively with current contents. | ||
| 60 | for ( uint32_t i = 0; i < (uint32_t)tDelayA_getDelay(p->delayLine); i++ ) | ||
| 61 | tDelayA_tick(p->delayLine, 0.6f * tDelayA_getLastOut(p->delayLine) + tOnePole_tick(p->pickFilter, tNoise_tick(p->noise) ) ); | ||
| 62 | } | ||
| 63 | |||
| 64 | // Start a note with the given frequency and amplitude.; | ||
| 65 | void tPluck_noteOn (tPluck* const p, float frequency, float amplitude ) | ||
| 66 | { | ||
| 67 | p->lastFreq = frequency; | ||
| 68 | tPluck_setFrequency( p, frequency ); | ||
| 69 | tPluck_pluck( p, amplitude ); | ||
| 70 | } | ||
| 71 | |||
| 72 | // Stop a note with the given amplitude (speed of decay). | ||
| 73 | void tPluck_noteOff (tPluck* const p, float amplitude ) | ||
| 74 | { | ||
| 75 | if ( amplitude < 0.0f) amplitude = 0.0f; | ||
| 76 | else if (amplitude > 1.0f) amplitude = 1.0f; | ||
| 77 | |||
| 78 | p->loopGain = 1.0f - amplitude; | ||
| 79 | } | ||
| 80 | |||
| 81 | // Set instrument parameters for a particular frequency. | ||
| 82 | void tPluck_setFrequency (tPluck* const p, float frequency ) | ||
| 83 | { | ||
| 84 | if ( frequency <= 0.0f ) frequency = 0.001f; | ||
| 85 | |||
| 86 | // Delay = length - filter delay. | ||
| 87 | float delay = ( leaf.sampleRate / frequency ) - tOneZero_getPhaseDelay(p->loopFilter, frequency ); | ||
| 88 | |||
| 89 | tDelayA_setDelay(p->delayLine, delay ); | ||
| 90 | |||
| 91 | p->loopGain = 0.99f + (frequency * 0.000005f); | ||
| 92 | |||
| 93 | if ( p->loopGain >= 0.999f ) p->loopGain = 0.999f; | ||
| 94 | |||
| 95 | } | ||
| 96 | |||
| 97 | // Perform the control change specified by \e number and \e value (0.0 - 128.0). | ||
| 98 | void tPluck_controlChange (tPluck* const p, int number, float value) | ||
| 99 | { | ||
| 100 | return; | ||
| 101 | } | ||
| 102 | |||
| 103 | void tPluckSampleRateChanged(tPluck* const p) | ||
| 104 | { | ||
| 105 | //tPluckSetFrequency(p, p->lastFreq); | ||
| 106 | } | ||
| 107 | |||
| 108 | /* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tStifKarp ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */ | ||
| 109 | void tStifKarp_init (tStifKarp* const p, float lowestFrequency) | ||
| 110 | { | ||
| 111 | if ( lowestFrequency <= 0.0f ) lowestFrequency = 8.0f; | ||
| 112 | |||
| 113 | p->delayLine = (tDelayA*) leaf_alloc(sizeof(tDelayA)); | ||
| 114 | tDelayA_init(p->delayLine, 0.0f, leaf.sampleRate * 2); | ||
| 115 | |||
| 116 | p->combDelay = (tDelayL*) leaf_alloc(sizeof(tDelayL)); | ||
| 117 | tDelayL_init(p->combDelay, 0.0f, leaf.sampleRate * 2); | ||
| 118 | |||
| 119 | p->filter = (tOneZero*) leaf_alloc(sizeof(tOneZero)); | ||
| 120 | tOneZero_init(p->filter, 0.0f); | ||
| 121 | |||
| 122 | p->noise = (tNoise*) leaf_alloc(sizeof(tNoise)); | ||
| 123 | tNoise_init(p->noise, WhiteNoise); | ||
| 124 | |||
| 125 | for (int i = 0; i < 4; i++) | ||
| 126 | { | ||
| 127 | p->biquad[i] = (tBiQuad*) leaf_alloc(sizeof(tBiQuad)); | ||
| 128 | tBiQuad_init(p->biquad[i]); | ||
| 129 | } | ||
| 130 | |||
| 131 | p->pluckAmplitude = 0.3f; | ||
| 132 | p->pickupPosition = 0.4f; | ||
| 133 | |||
| 134 | p->stretching = 0.9999f; | ||
| 135 | p->baseLoopGain = 0.995f; | ||
| 136 | p->loopGain = 0.999f; | ||
| 137 | |||
| 138 | tStifKarp_setFrequency( p, 220.0f ); | ||
| 139 | |||
| 140 | } | ||
| 141 | |||
| 142 | void tStifKarp_free (tStifKarp* const p) | ||
| 143 | { | ||
| 144 | tDelayA_free(p->delayLine); | ||
| 145 | tDelayL_free(p->combDelay); | ||
| 146 | tOneZero_free(p->filter); | ||
| 147 | tNoise_free(p->noise); | ||
| 148 | |||
| 149 | for (int i = 0; i < 4; i++) | ||
| 150 | { | ||
| 151 | tBiQuad_free(p->biquad[i]); | ||
| 152 | } | ||
| 153 | |||
| 154 | leaf_free(p); | ||
| 155 | } | ||
| 156 | |||
| 157 | float tStifKarp_getLastOut (tStifKarp* const p) | ||
| 158 | { | ||
| 159 | return p->lastOut; | ||
| 160 | } | ||
| 161 | |||
| 162 | float tStifKarp_tick (tStifKarp* const p) | ||
| 163 | { | ||
| 164 | float temp = tDelayA_getLastOut(p->delayLine) * p->loopGain; | ||
| 165 | |||
| 166 | // Calculate allpass stretching. | ||
| 167 | for (int i=0; i<4; i++) temp = tBiQuad_tick(p->biquad[i],temp); | ||
| 168 | |||
| 169 | // Moving average filter. | ||
| 170 | temp = tOneZero_tick(p->filter, temp); | ||
| 171 | |||
| 172 | float out = tDelayA_tick(p->delayLine, temp); | ||
| 173 | out = out - tDelayL_tick(p->combDelay, out); | ||
| 174 | p->lastOut = out; | ||
| 175 | |||
| 176 | return p->lastOut; | ||
| 177 | } | ||
| 178 | |||
| 179 | void tStifKarp_pluck (tStifKarp* const p, float amplitude) | ||
| 180 | { | ||
| 181 | if ( amplitude < 0.0f) amplitude = 0.0f; | ||
| 182 | else if (amplitude > 1.0f) amplitude = 1.0f; | ||
| 183 | |||
| 184 | p->pluckAmplitude = amplitude; | ||
| 185 | |||
| 186 | for ( uint32_t i=0; i < (uint32_t)tDelayA_getDelay(p->delayLine); i++ ) | ||
| 187 | { | ||
| 188 | // Fill delay with noise additively with current contents. | ||
| 189 | tDelayA_tick(p->delayLine, (tDelayA_getLastOut(p->delayLine) * 0.6f) + 0.4f * tNoise_tick(p->noise) * p->pluckAmplitude ); | ||
| 190 | //delayLine_.tick( combDelay_.tick((delayLine_.lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude_) ); | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | // Start a note with the given frequency and amplitude.; | ||
| 195 | void tStifKarp_noteOn (tStifKarp* const p, float frequency, float amplitude ) | ||
| 196 | { | ||
| 197 | tStifKarp_setFrequency( p, frequency ); | ||
| 198 | tStifKarp_pluck( p, amplitude ); | ||
| 199 | } | ||
| 200 | |||
| 201 | // Stop a note with the given amplitude (speed of decay). | ||
| 202 | void tStifKarp_noteOff (tStifKarp* const p, float amplitude ) | ||
| 203 | { | ||
| 204 | if ( amplitude < 0.0f) amplitude = 0.0f; | ||
| 205 | else if (amplitude > 1.0f) amplitude = 1.0f; | ||
| 206 | |||
| 207 | p->loopGain = 1.0f - amplitude; | ||
| 208 | } | ||
| 209 | |||
| 210 | // Set instrument parameters for a particular frequency. | ||
| 211 | void tStifKarp_setFrequency (tStifKarp* const p, float frequency ) | ||
| 212 | { | ||
| 213 | if ( frequency <= 0.0f ) frequency = 0.001f; | ||
| 214 | |||
| 215 | p->lastFrequency = frequency; | ||
| 216 | p->lastLength = leaf.sampleRate / p->lastFrequency; | ||
| 217 | float delay = p->lastLength - 0.5f; | ||
| 218 | tDelayA_setDelay(p->delayLine, delay ); | ||
| 219 | |||
| 220 | // MAYBE MODIFY LOOP GAINS | ||
| 221 | p->loopGain = p->baseLoopGain + (frequency * 0.000005f); | ||
| 222 | if (p->loopGain >= 1.0f) p->loopGain = 0.99999f; | ||
| 223 | |||
| 224 | tStifKarp_setStretch(p, p->stretching); | ||
| 225 | |||
| 226 | tDelayL_setDelay(p->combDelay, 0.5f * p->pickupPosition * p->lastLength ); | ||
| 227 | |||
| 228 | } | ||
| 229 | |||
| 230 | // Set the stretch "factor" of the string (0.0 - 1.0). | ||
| 231 | void tStifKarp_setStretch (tStifKarp* const p, float stretch ) | ||
| 232 | { | ||
| 233 | p->stretching = stretch; | ||
| 234 | float coefficient; | ||
| 235 | float freq = p->lastFrequency * 2.0f; | ||
| 236 | float dFreq = ( (0.5f * leaf.sampleRate) - freq ) * 0.25f; | ||
| 237 | float temp = 0.5f + (stretch * 0.5f); | ||
| 238 | if ( temp > 0.9999f ) temp = 0.9999f; | ||
| 239 | |||
| 240 | for ( int i=0; i<4; i++ ) | ||
| 241 | { | ||
| 242 | coefficient = temp * temp; | ||
| 243 | tBiQuad_setA2(p->biquad[i], coefficient); | ||
| 244 | tBiQuad_setB0(p->biquad[i], coefficient); | ||
| 245 | tBiQuad_setB2(p->biquad[i], 1.0f); | ||
| 246 | |||
| 247 | coefficient = -2.0f * temp * cos(TWO_PI * freq / leaf.sampleRate); | ||
| 248 | tBiQuad_setA1(p->biquad[i], coefficient); | ||
| 249 | tBiQuad_setB1(p->biquad[i], coefficient); | ||
| 250 | |||
| 251 | freq += dFreq; | ||
| 252 | } | ||
| 253 | } | ||
| 254 | |||
| 255 | // Set the pluck or "excitation" position along the string (0.0 - 1.0). | ||
| 256 | void tStifKarp_setPickupPosition (tStifKarp* const p, float position ) | ||
| 257 | { | ||
| 258 | if (position < 0.0f) p->pickupPosition = 0.0f; | ||
| 259 | else if (position <= 1.0f) p->pickupPosition = position; | ||
| 260 | else p->pickupPosition = 1.0f; | ||
| 261 | |||
| 262 | tDelayL_setDelay(p->combDelay, 0.5f * p->pickupPosition * p->lastLength); | ||
| 263 | } | ||
| 264 | |||
| 265 | // Set the base loop gain. | ||
| 266 | void tStifKarp_setBaseLoopGain (tStifKarp* const p, float aGain ) | ||
| 267 | { | ||
| 268 | p->baseLoopGain = aGain; | ||
| 269 | p->loopGain = p->baseLoopGain + (p->lastFrequency * 0.000005f); | ||
| 270 | if ( p->loopGain > 0.99999f ) p->loopGain = 0.99999f; | ||
| 271 | } | ||
| 272 | |||
| 273 | // Perform the control change specified by \e number and \e value (0.0 - 128.0). | ||
| 274 | void tStifKarp_controlChange (tStifKarp* const p, SKControlType type, float value) | ||
| 275 | { | ||
| 276 | if ( value < 0.0f ) value = 0.0f; | ||
| 277 | else if (value > 128.0f) value = 128.0f; | ||
| 278 | |||
| 279 | float normalizedValue = value * INV_128; | ||
| 280 | |||
| 281 | if (type == SKPickPosition) // 4 | ||
| 282 | tStifKarp_setPickupPosition( p, normalizedValue ); | ||
| 283 | else if (type == SKStringDamping) // 11 | ||
| 284 | tStifKarp_setBaseLoopGain( p, 0.97f + (normalizedValue * 0.03f) ); | ||
| 285 | else if (type == SKDetune) // 1 | ||
| 286 | tStifKarp_setStretch( p, 0.91f + (0.09f * (1.0f - normalizedValue)) ); | ||
| 287 | |||
| 288 | } | ||
| 289 | |||
| 290 | void tStifKarpSampleRateChanged (tStifKarp* const c) | ||
| 291 | { | ||
| 292 | tStifKarp_setFrequency(c, c->lastFrequency); | ||
| 293 | tStifKarp_setStretch(c, c->stretching); | ||
| 294 | } | ||