Unified · Split
Binary file not shown.
Binary file not shown.
| @@ -105,47 +105,144 @@ extern "C" { · 104 unmodified lines | |||
| 105 | }; | 105 | }; |
| 106 | 106 | ||
| 107 | /* ADSR */ | 107 | /* ADSR */ |
| 108 | typedef struct _tADSR | 108 | typedef struct _tADSR |
| 109 | { | 109 | { |
| 110 | float sampleRateInMs; | 110 | const float *exp_buff; |
| 111 | int state; | 111 | const float *inc_buff; |
| 112 | float output; | 112 | uint32_t buff_size; |
| 113 | float attackRate; | 113 | |
| 114 | float decayRate; | 114 | float next; |
| 115 | float releaseRate; | 115 | |
| 116 | float attackCoef; | 116 | float attackInc, decayInc, releaseInc, rampInc; |
| 117 | float decayCoef; | 117 | |
| 118 | float releaseCoef; | 118 | oBool inAttack, inDecay, inSustain, inRelease, inRamp; |
| 119 | float sustainLevel; | 119 | |
| 120 | float targetRatioA; | 120 | float sustain, gain, rampPeak, releasePeak; |
| 121 | float targetRatioDR; | 121 | |
| 122 | float attackBase; | 122 | float attackPhase, decayPhase, releasePhase, rampPhase; |
| 123 | float decayBase; | 123 | |
| 124 | float releaseBase; | 124 | float leakFactor; |
| 125 | float leakFactor; | 125 | |
| 126 | float gain; | 126 | |
| 127 | 127 | } _tADSR; | |
| 128 | } _tADSR; | 128 | |
| 129 | 129 | typedef _tADSR* tADSR; | |
| 130 | typedef _tADSR* tADSR; | 130 | |
| 131 | 131 | void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release); | |
| 132 | void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release); | 132 | void tADSR_free (tADSR* const); |
| 133 | void tADSR_free (tADSR* const); | 133 | void tADSR_initToPool (tADSR* const, float attack, float decay, float sustain, float release, tMempool* const); |
| 134 | void tADSR_initToPool (tADSR* const, float attack, float decay, float sustain, float release, tMempool* const); | 134 | void tADSR_freeFromPool (tADSR* const, tMempool* const); |
| 135 | void tADSR_freeFromPool (tADSR* const, tMempool* const); | 135 | |
| 136 | 136 | float tADSR_tick (tADSR* const); | |
| 137 | float tADSR_tick (tADSR* const); | 137 | void tADSR_setAttack (tADSR* const, float attack); |
| 138 | void tADSR_setAttack (tADSR* const, float attack); | 138 | void tADSR_setDecay (tADSR* const, float decay); |
| 139 | void tADSR_setDecay (tADSR* const, float decay); | 139 | void tADSR_setSustain (tADSR* const, float sustain); |
| 140 | void tADSR_setSustain (tADSR* const, float sustain); | 140 | void tADSR_setRelease (tADSR* const, float release); |
| 141 | void tADSR_setRelease (tADSR* const, float release); | 141 | void tADSR_setLeakFactor (tADSR* const, float leakFactor); |
| 142 | void tADSR_setLeakFactor (tADSR* const, float leakFactor); | 142 | void tADSR_on (tADSR* const, float velocity); |
| 143 | void tADSR_on (tADSR* const, float velocity); | 143 | void tADSR_off (tADSR* const); |
| 144 | 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 | /* Ramp */ | 248 | /* Ramp */ |
| @@ -254,116 +254,553 @@ float tEnvelope_tick(tEnvelope* const envlp) · 253 unmodified lines | |||
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | 256 | ||
| 257 | |||
| 257 | /* ADSR */ | 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 | //-JS | 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 | return (rate <= 0.0f) ? 0.0f : exp(-log((1.0 + targetRatio) / targetRatio) / rate); | 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 | _tMempool* m = *mp; | 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 | adsr->sampleRateInMs = leaf.sampleRate * 0.001f; | 717 | adsr->sampleRateInMs = leaf.sampleRate * 0.001f; |
| 284 | adsr->targetRatioA = 0.3f; | 718 | adsr->targetRatioA = 0.3f; |
| 285 | adsr->targetRatioDR = 0.0001f; | 719 | adsr->targetRatioDR = 0.0001f; |
| 286 | adsr->attackRate = attack * adsr->sampleRateInMs; | 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 | adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef); | 722 | adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef); |
| 289 | 723 | ||
| 290 | adsr->decayRate = decay * adsr->sampleRateInMs; | 724 | adsr->decayRate = decay * adsr->sampleRateInMs; |
| 291 | adsr->decayCoef = calcADSRCoef(decay * adsr->sampleRateInMs,adsr-> targetRatioDR); | 725 | adsr->decayCoef = calcADSRCoef(decay * adsr->sampleRateInMs,adsr-> targetRatioDR); |
| 292 | adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef); | 726 | adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef); |
| 293 | 727 | ||
| 294 | adsr->sustainLevel = sustain; | 728 | adsr->sustainLevel = sustain; |
| 295 | adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef); | 729 | adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef); |
| 296 | 730 | ||
| 297 | adsr->releaseRate = release * adsr->sampleRateInMs; | 731 | adsr->releaseRate = release * adsr->sampleRateInMs; |
| 298 | adsr->releaseCoef = calcADSRCoef(release * adsr->sampleRateInMs, adsr->targetRatioDR); | 732 | adsr->releaseCoef = calcADSRCoef(release * adsr->sampleRateInMs, adsr->targetRatioDR); |
| 299 | adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef); | 733 | adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef); |
| 300 | 734 | ||
| 301 | adsr->state = env_idle; | 735 | adsr->state = env_idle; |
| 302 | adsr->gain = 1.0f; | 736 | adsr->gain = 1.0f; |
| 737 | adsr->targetGainSquared = 1.0f; | ||
| 738 | adsr->factor = 0.01f; | ||
| 739 | adsr->oneMinusFactor = 0.99f; | ||
| 303 | adsr->output = 0.0f; | 740 | adsr->output = 0.0f; |
| 304 | adsr->leakFactor = 1.0f; | 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 | _tMempool* m = *mp; | 746 | _tMempool* m = *mp; |
| 310 | _tADSR* adsr = *adsrenv; | 747 | _tADSR3* adsr = *adsrenv; |
| 311 | mpool_free(adsr, m); | 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 | adsr->attackRate = attack * adsr->sampleRateInMs; | 755 | adsr->attackRate = attack * adsr->sampleRateInMs; |
| 319 | adsr->attackCoef = calcADSRCoef(adsr->attackRate, adsr->targetRatioA); | 756 | adsr->attackCoef = calcADSR3Coef(adsr->attackRate, adsr->targetRatioA); |
| 320 | adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef); | 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; | 762 | _tADSR3* adsr = *adsrenv; |
| 326 | 763 | ||
| 327 | adsr->decayRate = decay * adsr->sampleRateInMs; | 764 | adsr->decayRate = decay * adsr->sampleRateInMs; |
| 328 | adsr->decayCoef = calcADSRCoef(adsr->decayRate,adsr-> targetRatioDR); | 765 | adsr->decayCoef = calcADSR3Coef(adsr->decayRate,adsr-> targetRatioDR); |
| 329 | adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef); | 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; | 771 | _tADSR3* adsr = *adsrenv; |
| 335 | 772 | ||
| 336 | adsr->sustainLevel = sustain; | 773 | adsr->sustainLevel = sustain; |
| 337 | adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef); | 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; | 779 | _tADSR3* adsr = *adsrenv; |
| 343 | 780 | ||
| 344 | adsr->releaseRate = release * adsr->sampleRateInMs; | 781 | adsr->releaseRate = release * adsr->sampleRateInMs; |
| 345 | adsr->releaseCoef = calcADSRCoef(adsr->releaseRate, adsr->targetRatioDR); | 782 | adsr->releaseCoef = calcADSR3Coef(adsr->releaseRate, adsr->targetRatioDR); |
| 346 | adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef); | 783 | adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef); |
| 347 | } | 784 | } |
| 348 | 785 | ||
| 349 | // 0.999999 is slow leak, 0.9 is fast leak | 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 | adsr->leakFactor = leakFactor; | 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 | adsr->state = env_attack; | 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 | if (adsr->state != env_idle) | 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; | 813 | _tADSR3* adsr = *adsrenv; |
| 377 | 814 | ||
| 378 | 815 | ||
| 379 | switch (adsr->state) { | 816 | switch (adsr->state) { |
| 380 | case env_idle: | 817 | case env_idle: |
| @@ -403,14 +840,13 @@ float tADSR_tick(tADSR* const adsrenv) · 22 unmodified lines | |||
| 403 | adsr->state = env_idle; | 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 | return adsr->output * adsr->gain; | 845 | return adsr->output * adsr->gain; |
| 407 | } | 846 | } |
| 408 | 847 | ||
| 409 | 848 | ||
| 410 | 849 | ||
| 411 | |||
| 412 | |||
| 413 | |||
| 414 | /////----------------- | 850 | /////----------------- |
| 415 | /* Ramp */ | 851 | /* Ramp */ |
| 416 | void tRamp_init(tRamp* const r, float time, int samples_per_tick) | 852 | void tRamp_init(tRamp* const r, float time, int samples_per_tick) |