Unified · Split
Binary file not shown.
Binary file not shown.
| @@ -105,47 +105,144 @@ extern "C" { · 104 unmodified lines | ||
| 105 | 105 | }; |
| 106 | 106 | |
| 107 | 107 | /* ADSR */ |
| 108 | − typedef struct _tADSR | |
| 109 | − { | |
| 110 | − float sampleRateInMs; | |
| 111 | − int state; | |
| 112 | − float output; | |
| 113 | − float attackRate; | |
| 114 | − float decayRate; | |
| 115 | − float releaseRate; | |
| 116 | − float attackCoef; | |
| 117 | − float decayCoef; | |
| 118 | − float releaseCoef; | |
| 119 | − float sustainLevel; | |
| 120 | − float targetRatioA; | |
| 121 | − float targetRatioDR; | |
| 122 | − float attackBase; | |
| 123 | − float decayBase; | |
| 124 | − float releaseBase; | |
| 125 | − float leakFactor; | |
| 126 | − float gain; | |
| 127 | − | |
| 128 | − } _tADSR; | |
| 129 | − | |
| 130 | − typedef _tADSR* tADSR; | |
| 131 | − | |
| 132 | − void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release); | |
| 133 | − void tADSR_free (tADSR* const); | |
| 134 | − void tADSR_initToPool (tADSR* const, float attack, float decay, float sustain, float release, tMempool* const); | |
| 135 | − void tADSR_freeFromPool (tADSR* const, tMempool* const); | |
| 136 | − | |
| 137 | − float tADSR_tick (tADSR* const); | |
| 138 | − void tADSR_setAttack (tADSR* const, float attack); | |
| 139 | − void tADSR_setDecay (tADSR* const, float decay); | |
| 140 | − void tADSR_setSustain (tADSR* const, float sustain); | |
| 141 | − void tADSR_setRelease (tADSR* const, float release); | |
| 142 | − void tADSR_setLeakFactor (tADSR* const, float leakFactor); | |
| 143 | − void tADSR_on (tADSR* const, float velocity); | |
| 144 | − void tADSR_off (tADSR* const); | |
| 108 | + typedef struct _tADSR | |
| 109 | + { | |
| 110 | + const float *exp_buff; | |
| 111 | + const float *inc_buff; | |
| 112 | + uint32_t buff_size; | |
| 113 | + | |
| 114 | + float next; | |
| 115 | + | |
| 116 | + float attackInc, decayInc, releaseInc, rampInc; | |
| 117 | + | |
| 118 | + oBool inAttack, inDecay, inSustain, inRelease, inRamp; | |
| 119 | + | |
| 120 | + float sustain, gain, rampPeak, releasePeak; | |
| 121 | + | |
| 122 | + float attackPhase, decayPhase, releasePhase, rampPhase; | |
| 123 | + | |
| 124 | + float leakFactor; | |
| 125 | + | |
| 126 | + | |
| 127 | + } _tADSR; | |
| 128 | + | |
| 129 | + typedef _tADSR* tADSR; | |
| 130 | + | |
| 131 | + void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release); | |
| 132 | + void tADSR_free (tADSR* const); | |
| 133 | + void tADSR_initToPool (tADSR* const, float attack, float decay, float sustain, float release, tMempool* const); | |
| 134 | + void tADSR_freeFromPool (tADSR* const, tMempool* const); | |
| 135 | + | |
| 136 | + float tADSR_tick (tADSR* const); | |
| 137 | + void tADSR_setAttack (tADSR* const, float attack); | |
| 138 | + void tADSR_setDecay (tADSR* const, float decay); | |
| 139 | + void tADSR_setSustain (tADSR* const, float sustain); | |
| 140 | + void tADSR_setRelease (tADSR* const, float release); | |
| 141 | + void tADSR_setLeakFactor (tADSR* const, float leakFactor); | |
| 142 | + void tADSR_on (tADSR* const, float velocity); | |
| 143 | + void tADSR_off (tADSR* const); | |
| 144 | + | |
| 145 | + | |
| 145 | 146 | |
| 146 | 147 | |
| 147 | 148 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
| 148 | 149 | |
| 150 | + | |
| 151 | + | |
| 152 | + /* ADSR2 */ | |
| 153 | + typedef struct _tADSR2 | |
| 154 | + { | |
| 155 | + float sampleRateInMs; | |
| 156 | + float attack; | |
| 157 | + float decay; | |
| 158 | + float release; | |
| 159 | + float attackLambda; | |
| 160 | + float decayLambda; | |
| 161 | + float releaseLambda; | |
| 162 | + float sustain; | |
| 163 | + float leakGain; | |
| 164 | + float leakFactor; | |
| 165 | + float targetGainSquared; | |
| 166 | + float factor; | |
| 167 | + float oneMinusFactor; | |
| 168 | + float gain; | |
| 169 | + uint8_t attacking; | |
| 170 | + uint8_t gate; | |
| 171 | + float env; | |
| 172 | + float envTarget; | |
| 173 | + } _tADSR2; | |
| 174 | + | |
| 175 | + typedef _tADSR2* tADSR2; | |
| 176 | + | |
| 177 | + void tADSR2_init (tADSR2* const, float attack, float decay, float sustain, float release); | |
| 178 | + void tADSR2_free (tADSR2* const); | |
| 179 | + void tADSR2_initToPool (tADSR2* const, float attack, float decay, float sustain, float release, tMempool* const); | |
| 180 | + void tADSR2_freeFromPool (tADSR2* const, tMempool* const); | |
| 181 | + | |
| 182 | + float tADSR2_tick (tADSR2* const); | |
| 183 | + void tADSR2_setAttack (tADSR2* const, float attack); | |
| 184 | + void tADSR2_setDecay (tADSR2* const, float decay); | |
| 185 | + void tADSR2_setSustain (tADSR2* const, float sustain); | |
| 186 | + void tADSR2_setRelease (tADSR2* const, float release); | |
| 187 | + void tADSR2_setLeakFactor (tADSR2* const, float leakFactor); | |
| 188 | + void tADSR2_on (tADSR2* const, float velocity); | |
| 189 | + void tADSR2_off (tADSR2* const); | |
| 190 | + | |
| 191 | + | |
| 192 | + // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 193 | + | |
| 194 | + // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 195 | + enum envState { | |
| 196 | + env_idle = 0, | |
| 197 | + env_attack, | |
| 198 | + env_decay, | |
| 199 | + env_sustain, | |
| 200 | + env_release | |
| 201 | + }; | |
| 202 | + | |
| 203 | + /* ADSR3 */ | |
| 204 | + typedef struct _tADSR3 | |
| 205 | + { | |
| 206 | + float sampleRateInMs; | |
| 207 | + int state; | |
| 208 | + float output; | |
| 209 | + float attackRate; | |
| 210 | + float decayRate; | |
| 211 | + float releaseRate; | |
| 212 | + float attackCoef; | |
| 213 | + float decayCoef; | |
| 214 | + float releaseCoef; | |
| 215 | + float sustainLevel; | |
| 216 | + float targetRatioA; | |
| 217 | + float targetRatioDR; | |
| 218 | + float attackBase; | |
| 219 | + float decayBase; | |
| 220 | + float releaseBase; | |
| 221 | + float leakFactor; | |
| 222 | + float targetGainSquared; | |
| 223 | + float factor; | |
| 224 | + float oneMinusFactor; | |
| 225 | + float gain; | |
| 226 | + | |
| 227 | + } _tADSR3; | |
| 228 | + | |
| 229 | + typedef _tADSR3* tADSR3; | |
| 230 | + | |
| 231 | + void tADSR3_init (tADSR3* const, float attack, float decay, float sustain, float release); | |
| 232 | + void tADSR3_free (tADSR3* const); | |
| 233 | + void tADSR3_initToPool (tADSR3* const, float attack, float decay, float sustain, float release, tMempool* const); | |
| 234 | + void tADSR3_freeFromPool (tADSR3* const, tMempool* const); | |
| 235 | + | |
| 236 | + float tADSR3_tick (tADSR3* const); | |
| 237 | + void tADSR3_setAttack (tADSR3* const, float attack); | |
| 238 | + void tADSR3_setDecay (tADSR3* const, float decay); | |
| 239 | + void tADSR3_setSustain (tADSR3* const, float sustain); | |
| 240 | + void tADSR3_setRelease (tADSR3* const, float release); | |
| 241 | + void tADSR3_setLeakFactor (tADSR3* const, float leakFactor); | |
| 242 | + void tADSR3_on (tADSR3* const, float velocity); | |
| 243 | + void tADSR3_off (tADSR3* const); | |
| 244 | + | |
| 245 | + // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 149 | 246 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
| 150 | 247 | |
| 151 | 248 | /* Ramp */ |
| @@ -254,116 +254,553 @@ float tEnvelope_tick(tEnvelope* const envlp) · 253 unmodified lines | ||
| 254 | 254 | } |
| 255 | 255 | |
| 256 | 256 | |
| 257 | + | |
| 257 | 258 | /* ADSR */ |
| 258 | −//replaced our older ADSR that relied on a large lookup table with this one by Nigel Redmon from his blog. Thanks, Nigel! | |
| 259 | +void tADSR_init(tADSR* const adsrenv, float attack, float decay, float sustain, float release) | |
| 260 | +{ | |
| 261 | + tADSR_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool); | |
| 262 | +} | |
| 263 | + | |
| 264 | +void tADSR_free(tADSR* const adsrenv) | |
| 265 | +{ | |
| 266 | + tADSR_freeFromPool(adsrenv, &leaf.mempool); | |
| 267 | +} | |
| 268 | + | |
| 269 | +void tADSR_initToPool (tADSR* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp) | |
| 270 | +{ | |
| 271 | + _tMempool* m = *mp; | |
| 272 | + _tADSR* adsr = *adsrenv = (_tADSR*) mpool_alloc(sizeof(_tADSR), m); | |
| 273 | + | |
| 274 | + adsr->exp_buff = __leaf_table_exp_decay; | |
| 275 | + adsr->inc_buff = __leaf_table_attack_decay_inc; | |
| 276 | + adsr->buff_size = sizeof(__leaf_table_exp_decay); | |
| 277 | + | |
| 278 | + if (attack > 8192.0f) | |
| 279 | + attack = 8192.0f; | |
| 280 | + if (attack < 0.0f) | |
| 281 | + attack = 0.0f; | |
| 282 | + | |
| 283 | + if (decay > 8192.0f) | |
| 284 | + decay = 8192.0f; | |
| 285 | + if (decay < 0.0f) | |
| 286 | + decay = 0.0f; | |
| 287 | + | |
| 288 | + if (sustain > 1.0f) | |
| 289 | + sustain = 1.0f; | |
| 290 | + if (sustain < 0.0f) | |
| 291 | + sustain = 0.0f; | |
| 292 | + | |
| 293 | + if (release > 8192.0f) | |
| 294 | + release = 8192.0f; | |
| 295 | + if (release < 0.0f) | |
| 296 | + release = 0.0f; | |
| 297 | + | |
| 298 | + int16_t attackIndex = ((int16_t)(attack * 8.0f))-1; | |
| 299 | + int16_t decayIndex = ((int16_t)(decay * 8.0f))-1; | |
| 300 | + int16_t releaseIndex = ((int16_t)(release * 8.0f))-1; | |
| 301 | + int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1; | |
| 302 | + | |
| 303 | + if (attackIndex < 0) | |
| 304 | + attackIndex = 0; | |
| 305 | + if (decayIndex < 0) | |
| 306 | + decayIndex = 0; | |
| 307 | + if (releaseIndex < 0) | |
| 308 | + releaseIndex = 0; | |
| 309 | + if (rampIndex < 0) | |
| 310 | + rampIndex = 0; | |
| 311 | + | |
| 312 | + adsr->next = 0.0f; | |
| 313 | + | |
| 314 | + adsr->inRamp = OFALSE; | |
| 315 | + adsr->inAttack = OFALSE; | |
| 316 | + adsr->inDecay = OFALSE; | |
| 317 | + adsr->inSustain = OFALSE; | |
| 318 | + adsr->inRelease = OFALSE; | |
| 319 | + | |
| 320 | + adsr->sustain = sustain; | |
| 321 | + | |
| 322 | + adsr->attackInc = adsr->inc_buff[attackIndex]; | |
| 323 | + adsr->decayInc = adsr->inc_buff[decayIndex]; | |
| 324 | + adsr->releaseInc = adsr->inc_buff[releaseIndex]; | |
| 325 | + adsr->rampInc = adsr->inc_buff[rampIndex]; | |
| 326 | + | |
| 327 | + adsr->leakFactor = 1.0f; | |
| 328 | +} | |
| 329 | + | |
| 330 | +void tADSR_freeFromPool (tADSR* const adsrenv, tMempool* const mp) | |
| 331 | +{ | |
| 332 | + _tMempool* m = *mp; | |
| 333 | + _tADSR* adsr = *adsrenv; | |
| 334 | + mpool_free(adsr, m); | |
| 335 | +} | |
| 336 | + | |
| 337 | +void tADSR_setAttack(tADSR* const adsrenv, float attack) | |
| 338 | +{ | |
| 339 | + _tADSR* adsr = *adsrenv; | |
| 340 | + | |
| 341 | + int32_t attackIndex; | |
| 342 | + | |
| 343 | + if (attack < 0.0f) { | |
| 344 | + attackIndex = 0.0f; | |
| 345 | + } else if (attack < 8192.0f) { | |
| 346 | + attackIndex = ((int32_t)(attack * 8.0f))-1; | |
| 347 | + } else { | |
| 348 | + attackIndex = ((int32_t)(8192.0f * 8.0f))-1; | |
| 349 | + } | |
| 350 | + | |
| 351 | + adsr->attackInc = adsr->inc_buff[attackIndex]; | |
| 352 | +} | |
| 353 | + | |
| 354 | +void tADSR_setDecay(tADSR* const adsrenv, float decay) | |
| 355 | +{ | |
| 356 | + _tADSR* adsr = *adsrenv; | |
| 357 | + | |
| 358 | + int32_t decayIndex; | |
| 359 | + | |
| 360 | + if (decay < 0.0f) { | |
| 361 | + decayIndex = 0.0f; | |
| 362 | + } else if (decay < 8192.0f) { | |
| 363 | + decayIndex = ((int32_t)(decay * 8.0f)) - 1; | |
| 364 | + } else { | |
| 365 | + decayIndex = ((int32_t)(8192.0f * 8.0f)) - 1; | |
| 366 | + } | |
| 367 | + | |
| 368 | + adsr->decayInc = adsr->inc_buff[decayIndex]; | |
| 369 | +} | |
| 370 | + | |
| 371 | +void tADSR_setSustain(tADSR* const adsrenv, float sustain) | |
| 372 | +{ | |
| 373 | + _tADSR* adsr = *adsrenv; | |
| 374 | + | |
| 375 | + if (sustain > 1.0f) adsr->sustain = 1.0f; | |
| 376 | + else if (sustain < 0.0f) adsr->sustain = 0.0f; | |
| 377 | + else adsr->sustain = sustain; | |
| 378 | +} | |
| 379 | + | |
| 380 | +void tADSR_setRelease(tADSR* const adsrenv, float release) | |
| 381 | +{ | |
| 382 | + _tADSR* adsr = *adsrenv; | |
| 383 | + | |
| 384 | + int32_t releaseIndex; | |
| 385 | + | |
| 386 | + if (release < 0.0f) { | |
| 387 | + releaseIndex = 0.0f; | |
| 388 | + } else if (release < 8192.0f) { | |
| 389 | + releaseIndex = ((int32_t)(release * 8.0f)) - 1; | |
| 390 | + } else { | |
| 391 | + releaseIndex = ((int32_t)(8192.0f * 8.0f)) - 1; | |
| 392 | + } | |
| 393 | + | |
| 394 | + adsr->releaseInc = adsr->inc_buff[releaseIndex]; | |
| 395 | +} | |
| 396 | + | |
| 397 | +// 0.999999 is slow leak, 0.9 is fast leak | |
| 398 | +void tADSR_setLeakFactor(tADSR* const adsrenv, float leakFactor) | |
| 399 | +{ | |
| 400 | + _tADSR* adsr = *adsrenv; | |
| 401 | + | |
| 402 | + | |
| 403 | + adsr->leakFactor = leakFactor; | |
| 404 | +} | |
| 405 | + | |
| 406 | +void tADSR_on(tADSR* const adsrenv, float velocity) | |
| 407 | +{ | |
| 408 | + _tADSR* adsr = *adsrenv; | |
| 409 | + | |
| 410 | + if ((adsr->inAttack || adsr->inDecay) || (adsr->inSustain || adsr->inRelease)) // In case ADSR retriggered while it is still happening. | |
| 411 | + { | |
| 412 | + adsr->rampPhase = 0; | |
| 413 | + adsr->inRamp = OTRUE; | |
| 414 | + adsr->rampPeak = adsr->next; | |
| 415 | + } | |
| 416 | + else // Normal start. | |
| 417 | + { | |
| 418 | + adsr->inAttack = OTRUE; | |
| 419 | + } | |
| 420 | + | |
| 421 | + adsr->attackPhase = 0; | |
| 422 | + adsr->decayPhase = 0; | |
| 423 | + adsr->releasePhase = 0; | |
| 424 | + adsr->inDecay = OFALSE; | |
| 425 | + adsr->inSustain = OFALSE; | |
| 426 | + adsr->inRelease = OFALSE; | |
| 427 | + adsr->gain = velocity; | |
| 428 | +} | |
| 429 | + | |
| 430 | +void tADSR_off(tADSR* const adsrenv) | |
| 431 | +{ | |
| 432 | + _tADSR* adsr = *adsrenv; | |
| 433 | + | |
| 434 | + if (adsr->inRelease) return; | |
| 435 | + | |
| 436 | + adsr->inAttack = OFALSE; | |
| 437 | + adsr->inDecay = OFALSE; | |
| 438 | + adsr->inSustain = OFALSE; | |
| 439 | + adsr->inRelease = OTRUE; | |
| 440 | + | |
| 441 | + adsr->releasePeak = adsr->next; | |
| 442 | +} | |
| 443 | + | |
| 444 | +float tADSR_tick(tADSR* const adsrenv) | |
| 445 | +{ | |
| 446 | + _tADSR* adsr = *adsrenv; | |
| 447 | + | |
| 448 | + | |
| 449 | + if (adsr->inRamp) | |
| 450 | + { | |
| 451 | + if (adsr->rampPhase > UINT16_MAX) | |
| 452 | + { | |
| 453 | + adsr->inRamp = OFALSE; | |
| 454 | + adsr->inAttack = OTRUE; | |
| 455 | + adsr->next = 0.0f; | |
| 456 | + } | |
| 457 | + else | |
| 458 | + { | |
| 459 | + adsr->next = adsr->rampPeak * adsr->exp_buff[(uint32_t)adsr->rampPhase]; | |
| 460 | + } | |
| 461 | + | |
| 462 | + adsr->rampPhase += adsr->rampInc; | |
| 463 | + } | |
| 464 | + | |
| 465 | + if (adsr->inAttack) | |
| 466 | + { | |
| 467 | + | |
| 468 | + // If attack done, time to turn around. | |
| 469 | + if (adsr->attackPhase > UINT16_MAX) | |
| 470 | + { | |
| 471 | + adsr->inDecay = OTRUE; | |
| 472 | + adsr->inAttack = OFALSE; | |
| 473 | + adsr->next = adsr->gain * 1.0f; | |
| 474 | + } | |
| 475 | + else | |
| 476 | + { | |
| 477 | + // do interpolation ! | |
| 478 | + adsr->next = adsr->gain * adsr->exp_buff[UINT16_MAX - (uint32_t)adsr->attackPhase]; // inverted and backwards to get proper rising exponential shape/perception | |
| 479 | + } | |
| 480 | + | |
| 481 | + // Increment ADSR attack. | |
| 482 | + adsr->attackPhase += adsr->attackInc; | |
| 483 | + | |
| 484 | + } | |
| 485 | + | |
| 486 | + if (adsr->inDecay) | |
| 487 | + { | |
| 488 | + | |
| 489 | + // If decay done, sustain. | |
| 490 | + if (adsr->decayPhase >= UINT16_MAX) | |
| 491 | + { | |
| 492 | + adsr->inDecay = OFALSE; | |
| 493 | + adsr->inSustain = OTRUE; | |
| 494 | + adsr->next = adsr->gain * adsr->sustain; | |
| 495 | + } | |
| 496 | + | |
| 497 | + else | |
| 498 | + { | |
| 499 | + adsr->next = adsr->gain * (adsr->sustain + ((adsr->exp_buff[(uint32_t)adsr->decayPhase]) * (1 - adsr->sustain))); // do interpolation ! | |
| 500 | + } | |
| 501 | + | |
| 502 | + // Increment ADSR decay. | |
| 503 | + adsr->decayPhase += adsr->decayInc; | |
| 504 | + } | |
| 505 | + | |
| 506 | + if (adsr->inSustain) | |
| 507 | + { | |
| 508 | + adsr->next = adsr->next * adsr->leakFactor; | |
| 509 | + } | |
| 510 | + | |
| 511 | + if (adsr->inRelease) | |
| 512 | + { | |
| 513 | + // If release done, finish. | |
| 514 | + if (adsr->releasePhase >= UINT16_MAX) | |
| 515 | + { | |
| 516 | + adsr->inRelease = OFALSE; | |
| 517 | + adsr->next = 0.0f; | |
| 518 | + } | |
| 519 | + else { | |
| 520 | + | |
| 521 | + adsr->next = adsr->releasePeak * (adsr->exp_buff[(uint32_t)adsr->releasePhase]); // do interpolation ! | |
| 522 | + } | |
| 523 | + | |
| 524 | + // Increment envelope release; | |
| 525 | + adsr->releasePhase += adsr->releaseInc; | |
| 526 | + } | |
| 527 | + | |
| 528 | + | |
| 529 | + return adsr->next; | |
| 530 | +} | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | +/* ADSR 2*/ | |
| 536 | +//This one is adapted from the VCV Rack code | |
| 259 | 537 | //-JS |
| 260 | 538 | |
| 261 | 539 | |
| 262 | 540 | |
| 263 | −float calcADSRCoef(double rate, double targetRatio) | |
| 541 | +const float ADSR2_MIN_TIME = 1e-3f; | |
| 542 | +const float ADSR2_INV_MIN_TIME = 1000.0f; | |
| 543 | +const float ADSR2_MAX_TIME = 10.f; | |
| 544 | +const float ADSR2_LAMBDA_BASE = 10000.0f; | |
| 545 | + | |
| 546 | + | |
| 547 | +void tADSR2_init(tADSR2* const adsrenv, float attack, float decay, float sustain, float release) | |
| 548 | +{ | |
| 549 | + tADSR2_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool); | |
| 550 | +} | |
| 551 | + | |
| 552 | +void tADSR2_free(tADSR2* const adsrenv) | |
| 553 | +{ | |
| 554 | + tADSR2_freeFromPool(adsrenv, &leaf.mempool); | |
| 555 | +} | |
| 556 | + | |
| 557 | +void tADSR2_initToPool (tADSR2* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp) | |
| 558 | +{ | |
| 559 | + _tMempool* m = *mp; | |
| 560 | + _tADSR2* adsr = *adsrenv = (_tADSR2*) mpool_alloc(sizeof(_tADSR2), m); | |
| 561 | + adsr->sampleRateInMs = leaf.sampleRate * 0.001f; | |
| 562 | + adsr->attack = LEAF_clip(0.0f, attack * 0.001f, 1.0f); | |
| 563 | + adsr->attackLambda = powf(ADSR2_LAMBDA_BASE, -adsr->attack) * ADSR2_INV_MIN_TIME; | |
| 564 | + | |
| 565 | + | |
| 566 | + adsr->decay = LEAF_clip(0.0f, decay * 0.001f, 1.0f); | |
| 567 | + adsr->decayLambda = powf(ADSR2_LAMBDA_BASE, -adsr->decay) * ADSR2_INV_MIN_TIME; | |
| 568 | + | |
| 569 | + | |
| 570 | + adsr->sustain= sustain; | |
| 571 | + | |
| 572 | + | |
| 573 | + adsr->release = LEAF_clip(0.0f, release * 0.001f, 1.0f); | |
| 574 | + adsr->releaseLambda = powf(ADSR2_LAMBDA_BASE, -adsr->release) * ADSR2_INV_MIN_TIME; | |
| 575 | + | |
| 576 | + adsr->attacking = 0; | |
| 577 | + adsr->gate = 0; | |
| 578 | + adsr->gain = 1.0f; | |
| 579 | + adsr->targetGainSquared = 1.0f; | |
| 580 | + adsr->factor = 0.01f; | |
| 581 | + adsr->oneMinusFactor = 0.99f; | |
| 582 | + adsr->env = 0.0f; | |
| 583 | + adsr->leakFactor = 1.0f; | |
| 584 | +} | |
| 585 | + | |
| 586 | +void tADSR2_freeFromPool (tADSR2* const adsrenv, tMempool* const mp) | |
| 587 | +{ | |
| 588 | + _tMempool* m = *mp; | |
| 589 | + _tADSR2* adsr = *adsrenv; | |
| 590 | + mpool_free(adsr, m); | |
| 591 | +} | |
| 592 | + | |
| 593 | +void tADSR2_setAttack(tADSR2* const adsrenv, float attack) | |
| 594 | +{ | |
| 595 | + _tADSR2* adsr = *adsrenv; | |
| 596 | + adsr->attack = LEAF_clip(0.0f, attack * 0.001f, 1.0f); | |
| 597 | + adsr->attackLambda = fastPow(ADSR2_LAMBDA_BASE, -adsr->attack) * ADSR2_INV_MIN_TIME; | |
| 598 | + | |
| 599 | +} | |
| 600 | + | |
| 601 | +void tADSR2_setDecay(tADSR2* const adsrenv, float decay) | |
| 602 | +{ | |
| 603 | + _tADSR2* adsr = *adsrenv; | |
| 604 | + adsr->decay = LEAF_clip(0.0f, decay * 0.001f, 1.0f); | |
| 605 | + adsr->decayLambda = fastPow(ADSR2_LAMBDA_BASE, -adsr->decay) * ADSR2_INV_MIN_TIME; | |
| 606 | + | |
| 607 | +} | |
| 608 | + | |
| 609 | +void tADSR2_setSustain(tADSR2* const adsrenv, float sustain) | |
| 610 | +{ | |
| 611 | + _tADSR2* adsr = *adsrenv; | |
| 612 | + adsr->sustain = sustain; | |
| 613 | + | |
| 614 | + if (adsr->gate) | |
| 615 | + { | |
| 616 | + if (adsr->attacking == 0) | |
| 617 | + { | |
| 618 | + adsr->envTarget = sustain; | |
| 619 | + } | |
| 620 | + } | |
| 621 | +} | |
| 622 | + | |
| 623 | +void tADSR2_setRelease(tADSR2* const adsrenv, float release) | |
| 624 | +{ | |
| 625 | + _tADSR2* adsr = *adsrenv; | |
| 626 | + adsr->release = LEAF_clip(0.0f, release * 0.001f, 1.0f); | |
| 627 | + adsr->releaseLambda = fastPow(ADSR2_LAMBDA_BASE, -adsr->release) * ADSR2_INV_MIN_TIME; | |
| 628 | +} | |
| 629 | + | |
| 630 | +// 0.999999 is slow leak, 0.9 is fast leak | |
| 631 | +void tADSR2_setLeakFactor(tADSR2* const adsrenv, float leakFactor) | |
| 632 | +{ | |
| 633 | + _tADSR2* adsr = *adsrenv; | |
| 634 | + | |
| 635 | + adsr->leakFactor = leakFactor; | |
| 636 | +} | |
| 637 | + | |
| 638 | +void tADSR2_on(tADSR2* const adsrenv, float velocity) | |
| 639 | +{ | |
| 640 | + _tADSR2* adsr = *adsrenv; | |
| 641 | + adsr->targetGainSquared = velocity * velocity; | |
| 642 | + adsr->envTarget = 1.2f; | |
| 643 | + adsr->leakGain = 1.0f; | |
| 644 | + adsr->gate = 1; | |
| 645 | + adsr->attacking = 1; | |
| 646 | +} | |
| 647 | + | |
| 648 | +void tADSR2_off(tADSR2* const adsrenv) | |
| 649 | +{ | |
| 650 | + _tADSR2* adsr = *adsrenv; | |
| 651 | + adsr->gate = 0; | |
| 652 | + adsr->envTarget = 0.0f; | |
| 653 | +} | |
| 654 | + | |
| 655 | +float tADSR2_tick(tADSR2* const adsrenv) | |
| 656 | +{ | |
| 657 | + _tADSR2* adsr = *adsrenv; | |
| 658 | + float lambda; | |
| 659 | + | |
| 660 | + if (adsr->gate) | |
| 661 | + { | |
| 662 | + if (adsr->attacking) | |
| 663 | + { | |
| 664 | + lambda = adsr->attackLambda; | |
| 665 | + } | |
| 666 | + else | |
| 667 | + { | |
| 668 | + lambda = adsr->decayLambda; | |
| 669 | + } | |
| 670 | + } | |
| 671 | + else | |
| 672 | + { | |
| 673 | + lambda = adsr->releaseLambda; | |
| 674 | + } | |
| 675 | + | |
| 676 | + | |
| 677 | + // Adjust env | |
| 678 | + adsr->env += (adsr->envTarget - adsr->env) * lambda * leaf.invSampleRate; | |
| 679 | + | |
| 680 | + // Turn off attacking state if envelope is HIGH | |
| 681 | + if (adsr->env >= 1.0f) | |
| 682 | + { | |
| 683 | + adsr->attacking = 0; | |
| 684 | + adsr->envTarget = adsr->sustain; | |
| 685 | + } | |
| 686 | + | |
| 687 | + //smooth the gain value -- this is not ideal, a retrigger while the envelope is still going with a new gain will cause a jump, although it will be smoothed quickly. Maybe doing the math so the range is computed based on the gain rather than 0.->1. is preferable? But that's harder to get the exponential curve right without a lookup. | |
| 688 | + adsr->gain = ((adsr->factor*adsr->targetGainSquared)+(adsr->oneMinusFactor*adsr->gain)); | |
| 689 | + adsr->leakGain *= adsr->leakFactor; | |
| 690 | + return adsr->env * adsr->gain * adsr->leakGain; | |
| 691 | +} | |
| 692 | + | |
| 693 | +/* ADSR 3*/ | |
| 694 | +//This one doesn't use any lookup table - by Nigel Redmon from his blog. Thanks, Nigel! | |
| 695 | +//-JS | |
| 696 | + | |
| 697 | +float calcADSR3Coef(double rate, double targetRatio) | |
| 264 | 698 | { |
| 265 | 699 | return (rate <= 0.0f) ? 0.0f : exp(-log((1.0 + targetRatio) / targetRatio) / rate); |
| 266 | 700 | } |
| 267 | 701 | |
| 268 | 702 | |
| 269 | −void tADSR_init(tADSR* const adsrenv, float attack, float decay, float sustain, float release) | |
| 703 | +void tADSR3_init(tADSR3* const adsrenv, float attack, float decay, float sustain, float release) | |
| 270 | 704 | { |
| 271 | − tADSR_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool); | |
| 705 | + tADSR3_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool); | |
| 272 | 706 | } |
| 273 | 707 | |
| 274 | −void tADSR_free(tADSR* const adsrenv) | |
| 708 | +void tADSR3_free(tADSR3* const adsrenv) | |
| 275 | 709 | { |
| 276 | − tADSR_freeFromPool(adsrenv, &leaf.mempool); | |
| 710 | + tADSR3_freeFromPool(adsrenv, &leaf.mempool); | |
| 277 | 711 | } |
| 278 | 712 | |
| 279 | −void tADSR_initToPool (tADSR* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp) | |
| 713 | +void tADSR3_initToPool (tADSR3* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp) | |
| 280 | 714 | { |
| 281 | 715 | _tMempool* m = *mp; |
| 282 | − _tADSR* adsr = *adsrenv = (_tADSR*) mpool_alloc(sizeof(_tADSR), m); | |
| 716 | + _tADSR3* adsr = *adsrenv = (_tADSR3*) mpool_alloc(sizeof(_tADSR3), m); | |
| 283 | 717 | adsr->sampleRateInMs = leaf.sampleRate * 0.001f; |
| 284 | 718 | adsr->targetRatioA = 0.3f; |
| 285 | 719 | adsr->targetRatioDR = 0.0001f; |
| 286 | 720 | adsr->attackRate = attack * adsr->sampleRateInMs; |
| 287 | − adsr->attackCoef = calcADSRCoef(attack * adsr->sampleRateInMs, adsr->targetRatioA); | |
| 721 | + adsr->attackCoef = calcADSR3Coef(attack * adsr->sampleRateInMs, adsr->targetRatioA); | |
| 288 | 722 | adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef); |
| 289 | − | |
| 723 | + | |
| 290 | 724 | adsr->decayRate = decay * adsr->sampleRateInMs; |
| 291 | 725 | adsr->decayCoef = calcADSRCoef(decay * adsr->sampleRateInMs,adsr-> targetRatioDR); |
| 292 | 726 | adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef); |
| 293 | − | |
| 727 | + | |
| 294 | 728 | adsr->sustainLevel = sustain; |
| 295 | 729 | adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef); |
| 296 | − | |
| 730 | + | |
| 297 | 731 | adsr->releaseRate = release * adsr->sampleRateInMs; |
| 298 | 732 | adsr->releaseCoef = calcADSRCoef(release * adsr->sampleRateInMs, adsr->targetRatioDR); |
| 299 | 733 | adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef); |
| 300 | 734 | |
| 301 | 735 | adsr->state = env_idle; |
| 302 | 736 | adsr->gain = 1.0f; |
| 737 | + adsr->targetGainSquared = 1.0f; | |
| 738 | + adsr->factor = 0.01f; | |
| 739 | + adsr->oneMinusFactor = 0.99f; | |
| 303 | 740 | adsr->output = 0.0f; |
| 304 | 741 | adsr->leakFactor = 1.0f; |
| 305 | 742 | } |
| 306 | 743 | |
| 307 | −void tADSR_freeFromPool (tADSR* const adsrenv, tMempool* const mp) | |
| 744 | +void tADSR3_freeFromPool (tADSR3* const adsrenv, tMempool* const mp) | |
| 308 | 745 | { |
| 309 | 746 | _tMempool* m = *mp; |
| 310 | − _tADSR* adsr = *adsrenv; | |
| 747 | + _tADSR3* adsr = *adsrenv; | |
| 311 | 748 | mpool_free(adsr, m); |
| 312 | 749 | } |
| 313 | 750 | |
| 314 | −void tADSR_setAttack(tADSR* const adsrenv, float attack) | |
| 751 | +void tADSR3_setAttack(tADSR3* const adsrenv, float attack) | |
| 315 | 752 | { |
| 316 | − _tADSR* adsr = *adsrenv; | |
| 753 | + _tADSR3* adsr = *adsrenv; | |
| 317 | 754 | |
| 318 | 755 | adsr->attackRate = attack * adsr->sampleRateInMs; |
| 319 | − adsr->attackCoef = calcADSRCoef(adsr->attackRate, adsr->targetRatioA); | |
| 756 | + adsr->attackCoef = calcADSR3Coef(adsr->attackRate, adsr->targetRatioA); | |
| 320 | 757 | adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef); |
| 321 | 758 | } |
| 322 | 759 | |
| 323 | −void tADSR_setDecay(tADSR* const adsrenv, float decay) | |
| 760 | +void tADSR3_setDecay(tADSR3* const adsrenv, float decay) | |
| 324 | 761 | { |
| 325 | − _tADSR* adsr = *adsrenv; | |
| 326 | − | |
| 762 | + _tADSR3* adsr = *adsrenv; | |
| 763 | + | |
| 327 | 764 | adsr->decayRate = decay * adsr->sampleRateInMs; |
| 328 | − adsr->decayCoef = calcADSRCoef(adsr->decayRate,adsr-> targetRatioDR); | |
| 765 | + adsr->decayCoef = calcADSR3Coef(adsr->decayRate,adsr-> targetRatioDR); | |
| 329 | 766 | adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef); |
| 330 | 767 | } |
| 331 | 768 | |
| 332 | −void tADSR_setSustain(tADSR* const adsrenv, float sustain) | |
| 769 | +void tADSR3_setSustain(tADSR3* const adsrenv, float sustain) | |
| 333 | 770 | { |
| 334 | − _tADSR* adsr = *adsrenv; | |
| 335 | − | |
| 771 | + _tADSR3* adsr = *adsrenv; | |
| 772 | + | |
| 336 | 773 | adsr->sustainLevel = sustain; |
| 337 | 774 | adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef); |
| 338 | 775 | } |
| 339 | 776 | |
| 340 | −void tADSR_setRelease(tADSR* const adsrenv, float release) | |
| 777 | +void tADSR3_setRelease(tADSR3* const adsrenv, float release) | |
| 341 | 778 | { |
| 342 | − _tADSR* adsr = *adsrenv; | |
| 343 | − | |
| 779 | + _tADSR3* adsr = *adsrenv; | |
| 780 | + | |
| 344 | 781 | adsr->releaseRate = release * adsr->sampleRateInMs; |
| 345 | − adsr->releaseCoef = calcADSRCoef(adsr->releaseRate, adsr->targetRatioDR); | |
| 782 | + adsr->releaseCoef = calcADSR3Coef(adsr->releaseRate, adsr->targetRatioDR); | |
| 346 | 783 | adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef); |
| 347 | 784 | } |
| 348 | 785 | |
| 349 | 786 | // 0.999999 is slow leak, 0.9 is fast leak |
| 350 | −void tADSR_setLeakFactor(tADSR* const adsrenv, float leakFactor) | |
| 787 | +void tADSR3_setLeakFactor(tADSR3* const adsrenv, float leakFactor) | |
| 351 | 788 | { |
| 352 | − _tADSR* adsr = *adsrenv; | |
| 789 | + _tADSR3* adsr = *adsrenv; | |
| 353 | 790 | |
| 354 | 791 | adsr->leakFactor = leakFactor; |
| 355 | 792 | } |
| 356 | 793 | |
| 357 | −void tADSR_on(tADSR* const adsrenv, float velocity) | |
| 794 | +void tADSR3_on(tADSR3* const adsrenv, float velocity) | |
| 358 | 795 | { |
| 359 | − _tADSR* adsr = *adsrenv; | |
| 796 | + _tADSR3* adsr = *adsrenv; | |
| 360 | 797 | adsr->state = env_attack; |
| 361 | − adsr->gain = velocity; | |
| 798 | + adsr->targetGainSquared = velocity * velocity; | |
| 362 | 799 | } |
| 363 | 800 | |
| 364 | −void tADSR_off(tADSR* const adsrenv) | |
| 801 | +void tADSR3_off(tADSR3* const adsrenv) | |
| 365 | 802 | { |
| 366 | − _tADSR* adsr = *adsrenv; | |
| 803 | + _tADSR3* adsr = *adsrenv; | |
| 367 | 804 | |
| 368 | 805 | if (adsr->state != env_idle) |
| 369 | 806 | { |
| @@ -371,10 +808,10 @@ void tADSR_off(tADSR* const adsrenv) · 1 unmodified line | ||
| 371 | 808 | } |
| 372 | 809 | } |
| 373 | 810 | |
| 374 | −float tADSR_tick(tADSR* const adsrenv) | |
| 811 | +float tADSR3_tick(tADSR3* const adsrenv) | |
| 375 | 812 | { |
| 376 | − _tADSR* adsr = *adsrenv; | |
| 377 | − | |
| 813 | + _tADSR3* adsr = *adsrenv; | |
| 814 | + | |
| 378 | 815 | |
| 379 | 816 | switch (adsr->state) { |
| 380 | 817 | case env_idle: |
| @@ -403,14 +840,13 @@ float tADSR_tick(tADSR* const adsrenv) · 22 unmodified lines | ||
| 403 | 840 | adsr->state = env_idle; |
| 404 | 841 | } |
| 405 | 842 | } |
| 843 | + //smooth the gain value -- this is not ideal, a retrigger while the envelope is still going with a new gain will cause a jump, although it will be smoothed quickly. Maybe doing the math so the range is computed based on the gain rather than 0.->1. is preferable? But that's harder to get the exponential curve right without a lookup. | |
| 844 | + adsr->gain = (adsr->factor*adsr->targetGainSquared)+(adsr->oneMinusFactor*adsr->gain); | |
| 406 | 845 | return adsr->output * adsr->gain; |
| 407 | 846 | } |
| 408 | 847 | |
| 409 | 848 | |
| 410 | 849 | |
| 411 | − | |
| 412 | − | |
| 413 | − | |
| 414 | 850 | /////----------------- |
| 415 | 851 | /* Ramp */ |
| 416 | 852 | void tRamp_init(tRamp* const r, float time, int samples_per_tick) |