Unified · Split
| @@ -317,6 +317,13 @@ extern "C" { · 316 unmodified lines | ||
| 317 | 317 | @param position |
| 318 | 318 | @return |
| 319 | 319 | |
| 320 | + @fn float tHermiteDelay_tapOutInterpolated (tHermiteDelay* const dl, uint32_t tapDelay, float alpha); | |
| 321 | + @brief | |
| 322 | + @param delay A pointer to the relevant tHermiteDelay. | |
| 323 | + @param integer position | |
| 324 | + @param fractional portion of the position | |
| 325 | + @return | |
| 326 | + | |
| 320 | 327 | @fn void tHermiteDelay_tapIn (tHermiteDelay* const dl, float value, uint32_t tapDelay) |
| 321 | 328 | @brief |
| 322 | 329 | @param delay A pointer to the relevant tHermiteDelay. |
| @@ -361,15 +368,14 @@ extern "C" { · 38 unmodified lines | ||
| 361 | 368 | { |
| 362 | 369 | tMempool mempool; |
| 363 | 370 | |
| 364 | − float gain; | |
| 365 | 371 | float* buff; |
| 366 | − | |
| 372 | + uint32_t bufferMask; | |
| 367 | 373 | float lastOut, lastIn; |
| 368 | 374 | |
| 369 | 375 | uint32_t inPoint, outPoint; |
| 370 | 376 | |
| 371 | 377 | uint32_t maxDelay; |
| 372 | − | |
| 378 | + float gain; | |
| 373 | 379 | float delay; |
| 374 | 380 | |
| 375 | 381 | float alpha, omAlpha; |
| @@ -387,6 +393,7 @@ extern "C" { · 11 unmodified lines | ||
| 387 | 393 | float tHermiteDelay_tickOut (tHermiteDelay* const dl); |
| 388 | 394 | void tHermiteDelay_setDelay (tHermiteDelay* const dl, float delay); |
| 389 | 395 | float tHermiteDelay_tapOut (tHermiteDelay* const dl, uint32_t tapDelay); |
| 396 | + float tHermiteDelay_tapOutInterpolated (tHermiteDelay* const dl, uint32_t tapDelay, float alpha); | |
| 390 | 397 | void tHermiteDelay_tapIn (tHermiteDelay* const dl, float value, uint32_t tapDelay); |
| 391 | 398 | float tHermiteDelay_addTo (tHermiteDelay* const dl, float value, uint32_t tapDelay); |
| 392 | 399 | float tHermiteDelay_getDelay (tHermiteDelay* const dl); |
| @@ -444,7 +444,133 @@ extern "C" { · 443 unmodified lines | ||
| 444 | 444 | void tLivingString_setLevMode (tLivingString* const, int levMode); |
| 445 | 445 | |
| 446 | 446 | |
| 447 | + // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 448 | + | |
| 449 | + | |
| 450 | + /*! | |
| 451 | + @defgroup tlivingstring2 tLivingString2 | |
| 452 | + @ingroup physical | |
| 453 | + @brief String model with preparation and pick position separated. | |
| 454 | + @{ | |
| 455 | + | |
| 456 | + @fn void tLivingString2_init (tLivingString2* const, float freq, float pickPos, float prepIndex, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode, LEAF* const leaf) | |
| 457 | + @brief Initialize a tLivingString to the default mempool of a LEAF instance. | |
| 458 | + @param string A pointer to the tLivingString2 to initialize. | |
| 459 | + @param leaf A pointer to the leaf instance. | |
| 460 | + | |
| 461 | + @fn void tLivingString2_initToPool (tLivingString2* const, float freq, float pickPos, float prepIndex, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode, tMempool* const) | |
| 462 | + @brief Initialize a tLivingString2 to a specified mempool. | |
| 463 | + @param string A pointer to the tLivingString2 to initialize. | |
| 464 | + @param mempool A pointer to the tMempool to use. | |
| 465 | + | |
| 466 | + @fn void tLivingString2_free (tLivingString2* const) | |
| 467 | + @brief Free a tLivingString2 from its mempool. | |
| 468 | + @param string A pointer to the tLivingString2 to free. | |
| 469 | + | |
| 470 | + @fn float tLivingString2_tick (tLivingString2* const, float input) | |
| 471 | + @brief | |
| 472 | + @param string A pointer to the relevant tLivingString2. | |
| 473 | + | |
| 474 | + @fn float tLivingString2_sample (tLivingString2* const) | |
| 475 | + @brief | |
| 476 | + @param string A pointer to the relevant tLivingString2. | |
| 477 | + | |
| 478 | + @fn void tLivingString2_setFreq (tLivingString2* const, float freq) | |
| 479 | + @brief | |
| 480 | + @param string A pointer to the relevant tLivingString2. | |
| 481 | + | |
| 482 | + @fn void tLivingString2_setWaveLength (tLivingString2* const, float waveLength) | |
| 483 | + @brief | |
| 484 | + @param string A pointer to the relevant tLivingString2. | |
| 485 | + | |
| 486 | + @fn void tLivingString2_setPickPos (tLivingString2* const, float pickPos) | |
| 487 | + @brief | |
| 488 | + @param string A pointer to the relevant tLivingString2. | |
| 489 | + | |
| 490 | + @fn void tLivingString2_setPrepPosition (tLivingString2* const, float prepPos) | |
| 491 | + @brief | |
| 492 | + @param string A pointer to the relevant tLivingString2. | |
| 493 | + | |
| 494 | + | |
| 495 | + @fn void tLivingString2_setPrepIndex (tLivingString2* const, float prepIndex) | |
| 496 | + @brief | |
| 497 | + @param string A pointer to the relevant tLivingString2. | |
| 498 | + | |
| 499 | + @fn void tLivingString2_setBrightness (tLivingString2* const, float brightness) | |
| 500 | + @brief | |
| 501 | + @param string A pointer to the relevant tLivingString2. | |
| 502 | + @param float The brightness parameter from 0 to 1. | |
| 503 | + | |
| 504 | + @fn void tLivingString2_setDecay (tLivingString2* const, float decay) | |
| 505 | + @brief | |
| 506 | + @param string A pointer to the relevant tLivingString2. | |
| 507 | + @param float The decay parameter from 0 to 1. | |
| 508 | + | |
| 509 | + @fn void tLivingString2_setTargetLev (tLivingString2* const, float targetLev) | |
| 510 | + @brief | |
| 511 | + @param string A pointer to the relevant tLivingString2. | |
| 512 | + | |
| 513 | + @fn void tLivingString2_setLevSmoothFactor (tLivingString2* const, float levSmoothFactor) | |
| 514 | + @brief | |
| 515 | + @param string A pointer to the relevant tLivingString2. | |
| 516 | + | |
| 517 | + @fn void tLivingString2_setLevStrength (tLivingString2* const, float levStrength) | |
| 518 | + @brief | |
| 519 | + @param string A pointer to the relevant tLivingString2. | |
| 520 | + | |
| 521 | + @fn void tLivingString2_setLevMode (tLivingString2* const, int levMode) | |
| 522 | + @brief | |
| 523 | + @param string A pointer to the relevant tLivingString2. | |
| 524 | + | |
| 525 | + @} */ | |
| 526 | + typedef struct _tLivingString2 | |
| 527 | + { | |
| 528 | + | |
| 529 | + tMempool mempool; | |
| 530 | + float freq, waveLengthInSamples; // the frequency of the whole string, determining delay length | |
| 531 | + float pickPos; // the pick position, dividing the string in two, in ratio | |
| 532 | + float prepPos; // the preparation position, dividing the string in two, in ratio | |
| 533 | + float pickupPos; // the preparation position, dividing the string in two, in ratio | |
| 534 | + float prepIndex; // the amount of pressure on the preparation position of the string (near 0=soft obj, near 1=hard obj) | |
| 535 | + float decay; // amplitude damping factor for the string (only active in mode 0) | |
| 536 | + int levMode; | |
| 537 | + float brightness; | |
| 538 | + float curr; | |
| 539 | + tHermiteDelay delLF,delUF,delUB,delLB; // delay for lower/upper/forward/backward part of the waveguide model | |
| 540 | + tTwoZero bridgeFilter, nutFilter, prepFilterU, prepFilterL; | |
| 541 | + tHighpass DCblockerL, DCblockerU; | |
| 542 | + tFeedbackLeveler fbLevU, fbLevL; | |
| 543 | + tExpSmooth wlSmooth, ppSmooth, prpSmooth, puSmooth; | |
| 544 | + } _tLivingString2; | |
| 545 | + | |
| 546 | + typedef _tLivingString2* tLivingString2; | |
| 547 | + | |
| 548 | + void tLivingString2_init (tLivingString2* const, float freq, float pickPos, float prepPos, float pickupPos, float prepIndex, | |
| 549 | + float brightness, float decay, float targetLev, float levSmoothFactor, | |
| 550 | + float levStrength, int levMode, LEAF* const leaf); | |
| 551 | + void tLivingString2_initToPool (tLivingString2* const, float freq, float pickPos, float prepPos, float pickupPos, float prepIndex, | |
| 552 | + float brightness, float decay, float targetLev, float levSmoothFactor, | |
| 553 | + float levStrength, int levMode, tMempool* const); | |
| 554 | + void tLivingString2_free (tLivingString2* const); | |
| 555 | + | |
| 556 | + float tLivingString2_tick (tLivingString2* const, float input); | |
| 557 | + float tLivingString2_sample (tLivingString2* const); | |
| 558 | + void tLivingString2_setFreq (tLivingString2* const, float freq); | |
| 559 | + void tLivingString2_setWaveLength (tLivingString2* const, float waveLength); // in samples | |
| 560 | + void tLivingString2_setPickPos (tLivingString2* const, float pickPos); | |
| 561 | + void tLivingString2_setPrepPos (tLivingString2* const, float prepPos); | |
| 562 | + void tLivingString2_setPickupPos (tLivingString2* const, float pickupPos); | |
| 563 | + void tLivingString2_setPrepIndex (tLivingString2* const, float prepIndex); | |
| 564 | + void tLivingString2_setBrightness (tLivingString2* const, float brightness); | |
| 565 | + void tLivingString2_setDecay (tLivingString2* const, float decay); // from 0 to 1, gets converted to real decay factor | |
| 566 | + void tLivingString2_setTargetLev (tLivingString2* const, float targetLev); | |
| 567 | + void tLivingString2_setLevSmoothFactor (tLivingString2* const, float levSmoothFactor); | |
| 568 | + void tLivingString2_setLevStrength (tLivingString2* const, float levStrength); | |
| 569 | + void tLivingString2_setLevMode (tLivingString2* const, int levMode); | |
| 570 | + | |
| 571 | + | |
| 447 | 572 | |
| 573 | + // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
| 448 | 574 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
| 449 | 575 | |
| 450 | 576 | /*! |
| @@ -368,6 +368,25 @@ void tHermiteDelay_initToPool (tHermiteDelay* const dl, float delay, uint32_t m · 367 unmodified lines | ||
| 368 | 368 | else if (delay < 0.0f) d->delay = 0.0f; |
| 369 | 369 | else d->delay = delay; |
| 370 | 370 | |
| 371 | + | |
| 372 | + if ((maxDelay != 0) && ((maxDelay & (maxDelay - 1)) == 0)) | |
| 373 | + { | |
| 374 | + d->maxDelay = maxDelay; | |
| 375 | + d->bufferMask = maxDelay - 1; | |
| 376 | + } | |
| 377 | + else | |
| 378 | + { | |
| 379 | + //make the delay size into a power of 2 | |
| 380 | + maxDelay--; | |
| 381 | + maxDelay |= maxDelay >> 1; | |
| 382 | + maxDelay |= maxDelay >> 2; | |
| 383 | + maxDelay |= maxDelay >> 4; | |
| 384 | + maxDelay |= maxDelay >> 8; | |
| 385 | + maxDelay |= maxDelay >> 16; | |
| 386 | + maxDelay++; | |
| 387 | + d->maxDelay = maxDelay; | |
| 388 | + d->bufferMask = maxDelay - 1; | |
| 389 | + } | |
| 371 | 390 | d->buff = (float*) mpool_alloc(sizeof(float) * maxDelay, m); |
| 372 | 391 | |
| 373 | 392 | d->gain = 1.0f; |
| @@ -405,19 +424,20 @@ float tHermiteDelay_tick (tHermiteDelay* const dl, float input) · 31 unmodified lines | ||
| 405 | 424 | |
| 406 | 425 | d->buff[d->inPoint] = input * d->gain; |
| 407 | 426 | |
| 427 | + | |
| 408 | 428 | // Increment input pointer modulo length. |
| 409 | − if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0; | |
| 410 | − | |
| 411 | − | |
| 429 | + d->inPoint = (d->inPoint + 1) & d->bufferMask; | |
| 430 | + | |
| 431 | + | |
| 412 | 432 | uint32_t idx = (uint32_t) d->outPoint; |
| 413 | − d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay], | |
| 414 | − d->buff[idx], | |
| 415 | − d->buff[(idx + 1) % d->maxDelay], | |
| 416 | − d->buff[(idx + 2) % d->maxDelay], | |
| 417 | − d->alpha); | |
| 418 | − | |
| 433 | + d->lastOut = LEAF_interpolate_hermite_x (d->buff[((idx - 1) + d->maxDelay) & d->bufferMask], | |
| 434 | + d->buff[idx], | |
| 435 | + d->buff[(idx + 1) & d->bufferMask], | |
| 436 | + d->buff[(idx + 2) & d->bufferMask], | |
| 437 | + d->alpha); | |
| 438 | + | |
| 419 | 439 | // Increment output pointer modulo length |
| 420 | − if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0; | |
| 440 | + d->outPoint = (d->outPoint + 1) & d->bufferMask; | |
| 421 | 441 | |
| 422 | 442 | return d->lastOut; |
| 423 | 443 | } |
| @@ -425,86 +445,88 @@ float tHermiteDelay_tick (tHermiteDelay* const dl, float input) · 1 unmodified line | ||
| 425 | 445 | void tHermiteDelay_tickIn (tHermiteDelay* const dl, float input) |
| 426 | 446 | { |
| 427 | 447 | _tHermiteDelay* d = *dl; |
| 428 | − | |
| 429 | − d->buff[d->inPoint] = input * d->gain; | |
| 430 | − | |
| 448 | + | |
| 449 | + d->buff[d->inPoint] = input; | |
| 450 | + | |
| 431 | 451 | // Increment input pointer modulo length. |
| 432 | − if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0; | |
| 452 | + d->inPoint = (d->inPoint + 1) & d->bufferMask; | |
| 433 | 453 | } |
| 434 | 454 | |
| 435 | 455 | float tHermiteDelay_tickOut (tHermiteDelay* const dl) |
| 436 | 456 | { |
| 437 | 457 | _tHermiteDelay* d = *dl; |
| 438 | − | |
| 458 | + | |
| 439 | 459 | uint32_t idx = (uint32_t) d->outPoint; |
| 440 | − | |
| 441 | − | |
| 442 | − | |
| 443 | − d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay], | |
| 444 | − d->buff[idx], | |
| 445 | − d->buff[(idx + 1) % d->maxDelay], | |
| 446 | − d->buff[(idx + 2) % d->maxDelay], | |
| 447 | − d->alpha); | |
| 448 | − | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + d->lastOut = LEAF_interpolate_hermite_x (d->buff[((idx - 1) + d->maxDelay) & d->bufferMask], | |
| 464 | + d->buff[idx], | |
| 465 | + d->buff[(idx + 1) & d->bufferMask], | |
| 466 | + d->buff[(idx + 2) & d->bufferMask], | |
| 467 | + d->alpha); | |
| 468 | + | |
| 449 | 469 | // Increment output pointer modulo length |
| 450 | − if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0; | |
| 451 | − | |
| 470 | + d->outPoint = (d->outPoint + 1) & d->bufferMask; | |
| 471 | + | |
| 452 | 472 | return d->lastOut; |
| 453 | 473 | } |
| 454 | 474 | |
| 455 | 475 | void tHermiteDelay_setDelay (tHermiteDelay* const dl, float delay) |
| 456 | 476 | { |
| 457 | 477 | _tHermiteDelay* d = *dl; |
| 458 | − | |
| 459 | − d->delay = LEAF_clip(0.0f, delay, d->maxDelay); | |
| 460 | − | |
| 478 | + //d->delay = LEAF_clip(0.0f, delay, d->maxDelay); | |
| 479 | + d->delay = delay; // not safe but faster | |
| 461 | 480 | float outPointer = d->inPoint - d->delay; |
| 462 | − | |
| 463 | 481 | while ( outPointer < 0 ) |
| 464 | 482 | outPointer += d->maxDelay; // modulo maximum length |
| 465 | − | |
| 483 | + | |
| 466 | 484 | d->outPoint = (uint32_t) outPointer; // integer part |
| 467 | − | |
| 485 | + | |
| 468 | 486 | d->alpha = outPointer - d->outPoint; // fractional part |
| 469 | 487 | d->omAlpha = 1.0f - d->alpha; |
| 470 | − | |
| 471 | − if ( d->outPoint == d->maxDelay ) d->outPoint = 0; | |
| 488 | + | |
| 489 | + d->outPoint &= d->bufferMask; | |
| 472 | 490 | } |
| 473 | 491 | |
| 474 | 492 | float tHermiteDelay_tapOut (tHermiteDelay* const dl, uint32_t tapDelay) |
| 475 | 493 | { |
| 476 | 494 | _tHermiteDelay* d = *dl; |
| 477 | − | |
| 478 | − int32_t tap = d->inPoint - tapDelay - 1; | |
| 479 | − | |
| 480 | − // Check for wraparound. | |
| 481 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 482 | − | |
| 495 | + | |
| 496 | + int32_t tap = (d->inPoint - tapDelay - 1) & d->bufferMask; | |
| 497 | + | |
| 483 | 498 | return d->buff[tap]; |
| 484 | 499 | |
| 485 | 500 | } |
| 486 | 501 | |
| 487 | −void tHermiteDelay_tapIn (tHermiteDelay* const dl, float value, uint32_t tapDelay) | |
| 502 | +float tHermiteDelay_tapOutInterpolated (tHermiteDelay* const dl, uint32_t tapDelay, float alpha) | |
| 488 | 503 | { |
| 489 | 504 | _tHermiteDelay* d = *dl; |
| 505 | + | |
| 506 | + int32_t idx = (d->inPoint - tapDelay - 1) & d->bufferMask; | |
| 507 | + | |
| 508 | + return LEAF_interpolate_hermite_x (d->buff[((idx - 1) + d->maxDelay) & d->bufferMask], | |
| 509 | + d->buff[idx], | |
| 510 | + d->buff[(idx + 1) & d->bufferMask], | |
| 511 | + d->buff[(idx + 2) & d->bufferMask], | |
| 512 | + alpha); | |
| 513 | +} | |
| 490 | 514 | |
| 491 | − int32_t tap = d->inPoint - tapDelay - 1; | |
| 492 | − | |
| 493 | − // Check for wraparound. | |
| 494 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 495 | − | |
| 515 | +void tHermiteDelay_tapIn (tHermiteDelay* const dl, float value, uint32_t tapDelay) | |
| 516 | +{ | |
| 517 | + _tHermiteDelay* d = *dl; | |
| 518 | + | |
| 519 | + int32_t tap = (d->inPoint - tapDelay - 1) & d->bufferMask; | |
| 520 | + | |
| 496 | 521 | d->buff[tap] = value; |
| 497 | 522 | } |
| 498 | 523 | |
| 499 | 524 | float tHermiteDelay_addTo (tHermiteDelay* const dl, float value, uint32_t tapDelay) |
| 500 | 525 | { |
| 501 | 526 | _tHermiteDelay* d = *dl; |
| 502 | − | |
| 503 | − int32_t tap = d->inPoint - tapDelay - 1; | |
| 504 | − | |
| 505 | − // Check for wraparound. | |
| 506 | − while ( tap < 0 ) tap += d->maxDelay; | |
| 507 | − | |
| 527 | + | |
| 528 | + int32_t tap = (d->inPoint - tapDelay - 1) & d->bufferMask; | |
| 529 | + | |
| 508 | 530 | return (d->buff[tap] += value); |
| 509 | 531 | } |
| 510 | 532 | |
| @@ -659,6 +659,309 @@ float tLivingString_sample(tLivingString* const pl) · 658 unmodified lines | ||
| 659 | 659 | } |
| 660 | 660 | |
| 661 | 661 | |
| 662 | +//////////--------------------------- | |
| 663 | +/* Version of Living String with Hermite Interpolation */ | |
| 664 | +/*Living String experiment 2 */ | |
| 665 | + | |
| 666 | +/* Living String*/ | |
| 667 | + | |
| 668 | +void tLivingString2_init(tLivingString2* const pl, float freq, float pickPos, float prepPos, float pickupPos, float prepIndex, | |
| 669 | + float brightness, float decay, float targetLev, float levSmoothFactor, | |
| 670 | + float levStrength, int levMode, LEAF* const leaf) | |
| 671 | +{ | |
| 672 | + tLivingString2_initToPool(pl, freq, pickPos, prepPos, pickupPos, prepIndex, brightness, decay, targetLev, levSmoothFactor, levStrength, levMode, &leaf->mempool); | |
| 673 | +} | |
| 674 | + | |
| 675 | +void tLivingString2_initToPool (tLivingString2* const pl, float freq, float pickPos, float prepPos, float pickupPos, float prepIndex, | |
| 676 | + float brightness, float decay, float targetLev, float levSmoothFactor, | |
| 677 | + float levStrength, int levMode, tMempool* const mp) | |
| 678 | +{ | |
| 679 | + _tMempool* m = *mp; | |
| 680 | + _tLivingString2* p = *pl = (_tLivingString2*) mpool_alloc(sizeof(_tLivingString2), m); | |
| 681 | + p->mempool = m; | |
| 682 | + LEAF* leaf = p->mempool->leaf; | |
| 683 | + | |
| 684 | + p->curr=0.0f; | |
| 685 | + tExpSmooth_initToPool(&p->wlSmooth, leaf->sampleRate/freq, 0.01f, mp); // smoother for string wavelength (not freq, to avoid expensive divisions) | |
| 686 | + tLivingString2_setFreq(pl, freq); | |
| 687 | + p->freq = freq; | |
| 688 | + p->prepPos = prepPos; | |
| 689 | + tExpSmooth_initToPool(&p->ppSmooth, pickPos, 0.01f, mp); // smoother for pick position | |
| 690 | + tExpSmooth_initToPool(&p->prpSmooth, prepPos, 0.01f, mp); // smoother for prep position | |
| 691 | + tExpSmooth_initToPool(&p->puSmooth, pickupPos, 0.01f, mp); // smoother for pickup position | |
| 692 | + tLivingString2_setPickPos(pl, pickPos); | |
| 693 | + tLivingString2_setPrepPos(pl, prepPos); | |
| 694 | + p->prepIndex=prepIndex; | |
| 695 | + p->pickupPos = pickupPos; | |
| 696 | + tHermiteDelay_initToPool(&p->delLF,p->waveLengthInSamples, 2400, mp); | |
| 697 | + tHermiteDelay_initToPool(&p->delUF,p->waveLengthInSamples, 2400, mp); | |
| 698 | + tHermiteDelay_initToPool(&p->delUB,p->waveLengthInSamples, 2400, mp); | |
| 699 | + tHermiteDelay_initToPool(&p->delLB,p->waveLengthInSamples, 2400, mp); | |
| 700 | + tHermiteDelay_clear(&p->delLF); | |
| 701 | + tHermiteDelay_clear(&p->delUF); | |
| 702 | + tHermiteDelay_clear(&p->delUB); | |
| 703 | + tHermiteDelay_clear(&p->delLB); | |
| 704 | + p->brightness = brightness; | |
| 705 | + tTwoZero_initToPool(&p->bridgeFilter, mp); | |
| 706 | + tTwoZero_initToPool(&p->nutFilter, mp); | |
| 707 | + tTwoZero_initToPool(&p->prepFilterU, mp); | |
| 708 | + tTwoZero_initToPool(&p->prepFilterL, mp); | |
| 709 | + tHighpass_initToPool(&p->DCblockerU,13, mp); | |
| 710 | + tHighpass_initToPool(&p->DCblockerL,13, mp); | |
| 711 | + p->decay=decay; | |
| 712 | + p->prepIndex = prepIndex; | |
| 713 | + tFeedbackLeveler_initToPool(&p->fbLevU, targetLev, levSmoothFactor, levStrength, levMode, mp); | |
| 714 | + tFeedbackLeveler_initToPool(&p->fbLevL, targetLev, levSmoothFactor, levStrength, levMode, mp); | |
| 715 | + p->levMode=levMode; | |
| 716 | +} | |
| 717 | + | |
| 718 | +void tLivingString2_free (tLivingString2* const pl) | |
| 719 | +{ | |
| 720 | + _tLivingString2* p = *pl; | |
| 721 | + | |
| 722 | + tExpSmooth_free(&p->wlSmooth); | |
| 723 | + tExpSmooth_free(&p->ppSmooth); | |
| 724 | + tExpSmooth_free(&p->prpSmooth); | |
| 725 | + tExpSmooth_free(&p->puSmooth); | |
| 726 | + tHermiteDelay_free(&p->delLF); | |
| 727 | + tHermiteDelay_free(&p->delUF); | |
| 728 | + tHermiteDelay_free(&p->delUB); | |
| 729 | + tHermiteDelay_free(&p->delLB); | |
| 730 | + tTwoZero_free(&p->bridgeFilter); | |
| 731 | + tTwoZero_free(&p->nutFilter); | |
| 732 | + tTwoZero_free(&p->prepFilterU); | |
| 733 | + tTwoZero_free(&p->prepFilterL); | |
| 734 | + tHighpass_free(&p->DCblockerU); | |
| 735 | + tHighpass_free(&p->DCblockerL); | |
| 736 | + tFeedbackLeveler_free(&p->fbLevU); | |
| 737 | + tFeedbackLeveler_free(&p->fbLevL); | |
| 738 | + | |
| 739 | + mpool_free((char*)p, p->mempool); | |
| 740 | +} | |
| 741 | + | |
| 742 | +void tLivingString2_setFreq(tLivingString2* const pl, float freq) | |
| 743 | +{ // NOTE: It is faster to set wavelength in samples directly | |
| 744 | + _tLivingString2* p = *pl; | |
| 745 | + LEAF* leaf = p->mempool->leaf; | |
| 746 | + if (freq<20.f) freq=20.f; | |
| 747 | + else if (freq>10000.f) freq=10000.f; | |
| 748 | + p->freq = freq; | |
| 749 | + p->waveLengthInSamples = (leaf->sampleRate/freq) - 1; | |
| 750 | + tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples); | |
| 751 | +} | |
| 752 | + | |
| 753 | +void tLivingString2_setWaveLength(tLivingString2* const pl, float waveLength) | |
| 754 | +{ | |
| 755 | + _tLivingString2* p = *pl; | |
| 756 | + LEAF* leaf = p->mempool->leaf; | |
| 757 | + if (waveLength<4.8f) waveLength=4.8f; | |
| 758 | + else if (waveLength>2400.f) waveLength=2400.f; | |
| 759 | + p->waveLengthInSamples = waveLength - 1; | |
| 760 | + p->freq = leaf->sampleRate / waveLength; | |
| 761 | + tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples); | |
| 762 | +} | |
| 763 | + | |
| 764 | +void tLivingString2_setPickPos(tLivingString2* const pl, float pickPos) | |
| 765 | +{ // between 0 and 1 | |
| 766 | + _tLivingString2* p = *pl; | |
| 767 | + if (pickPos<0.f) pickPos=0.f; | |
| 768 | + else if (pickPos>1.f) pickPos=1.f; | |
| 769 | + p->pickPos = pickPos; | |
| 770 | + tExpSmooth_setDest(&p->ppSmooth, p->pickPos); | |
| 771 | +} | |
| 772 | + | |
| 773 | +void tLivingString2_setPrepPos(tLivingString2* const pl, float prepPos) | |
| 774 | +{ // between 0 and 1 | |
| 775 | + _tLivingString2* p = *pl; | |
| 776 | + if (prepPos<0.f) prepPos=0.f; | |
| 777 | + else if (prepPos>1.f) prepPos=1.f; | |
| 778 | + p->prepPos = prepPos; | |
| 779 | + tExpSmooth_setDest(&p->prpSmooth, p->prepPos); | |
| 780 | +} | |
| 781 | + | |
| 782 | +void tLivingString2_setPickupPos(tLivingString2* const pl, float pickupPos) | |
| 783 | +{ // between 0 and 1 | |
| 784 | + _tLivingString2* p = *pl; | |
| 785 | + if (pickupPos<0.f) pickupPos=0.f; | |
| 786 | + else if (pickupPos>1.f) pickupPos=1.f; | |
| 787 | + p->pickupPos = pickupPos; | |
| 788 | + tExpSmooth_setDest(&p->puSmooth, p->pickupPos); | |
| 789 | +} | |
| 790 | + | |
| 791 | +void tLivingString2_setPrepIndex(tLivingString2* const pl, float prepIndex) | |
| 792 | +{ // between 0 and 1 | |
| 793 | + _tLivingString2* p = *pl; | |
| 794 | + if (prepIndex<0.f) prepIndex=0.f; | |
| 795 | + else if (prepIndex>1.f) prepIndex=1.f; | |
| 796 | + p->prepIndex = prepIndex; | |
| 797 | +} | |
| 798 | + | |
| 799 | +void tLivingString2_setBrightness(tLivingString2* const pl, float brightness) | |
| 800 | +{ | |
| 801 | + _tLivingString2* p = *pl; | |
| 802 | + float h0=(1.0 + brightness) * 0.5f; | |
| 803 | + float h1=(1.0 - brightness) * 0.25f; | |
| 804 | + | |
| 805 | + tTwoZero_setCoefficients(&p->bridgeFilter, h1, h0, h1); | |
| 806 | + tTwoZero_setCoefficients(&p->nutFilter, h1, h0, h1); | |
| 807 | + tTwoZero_setCoefficients(&p->prepFilterU, h1, h0, h1); | |
| 808 | + tTwoZero_setCoefficients(&p->prepFilterL, h1, h0, h1); | |
| 809 | +} | |
| 810 | + | |
| 811 | +void tLivingString2_setDecay(tLivingString2* const pl, float decay) | |
| 812 | +{ | |
| 813 | + _tLivingString2* p = *pl; | |
| 814 | + p->decay=powf(0.001f,1.0f/(p->freq*decay)); | |
| 815 | +} | |
| 816 | + | |
| 817 | +void tLivingString2_setTargetLev(tLivingString2* const pl, float targetLev) | |
| 818 | +{ | |
| 819 | + _tLivingString2* p = *pl; | |
| 820 | + tFeedbackLeveler_setTargetLevel(&p->fbLevU, targetLev); | |
| 821 | + tFeedbackLeveler_setTargetLevel(&p->fbLevL, targetLev); | |
| 822 | +} | |
| 823 | + | |
| 824 | +void tLivingString2_setLevSmoothFactor(tLivingString2* const pl, float levSmoothFactor) | |
| 825 | +{ | |
| 826 | + _tLivingString2* p = *pl; | |
| 827 | + tFeedbackLeveler_setFactor(&p->fbLevU, levSmoothFactor); | |
| 828 | + tFeedbackLeveler_setFactor(&p->fbLevL, levSmoothFactor); | |
| 829 | +} | |
| 830 | + | |
| 831 | +void tLivingString2_setLevStrength(tLivingString2* const pl, float levStrength) | |
| 832 | +{ | |
| 833 | + _tLivingString2* p = *pl; | |
| 834 | + tFeedbackLeveler_setStrength(&p->fbLevU, levStrength); | |
| 835 | + tFeedbackLeveler_setStrength(&p->fbLevL, levStrength); | |
| 836 | +} | |
| 837 | + | |
| 838 | +void tLivingString2_setLevMode(tLivingString2* const pl, int levMode) | |
| 839 | +{ | |
| 840 | + _tLivingString2* p = *pl; | |
| 841 | + tFeedbackLeveler_setMode(&p->fbLevU, levMode); | |
| 842 | + tFeedbackLeveler_setMode(&p->fbLevL, levMode); | |
| 843 | + p->levMode=levMode; | |
| 844 | +} | |
| 845 | + | |
| 846 | +float tLivingString2_tick(tLivingString2* const pl, float input) | |
| 847 | +{ | |
| 848 | + _tLivingString2* p = *pl; | |
| 849 | + | |
| 850 | + input = input * 0.5f; // drop gain by half since we'll be equally adding it at half amplitude to forward and backward waveguides | |
| 851 | + // from prepPos upwards=forwards | |
| 852 | + float wLen=tExpSmooth_tick(&p->wlSmooth); | |
| 853 | + | |
| 854 | + float pickP=tExpSmooth_tick(&p->ppSmooth); | |
| 855 | + | |
| 856 | + //float pickupPos=tExpSmooth_tick(&p->puSmooth); | |
| 857 | + | |
| 858 | + //need to determine which delay line to put it into (should be half amplitude into forward and backward lines for the correct portion of string) | |
| 859 | + float prepP=tExpSmooth_tick(&p->prpSmooth); | |
| 860 | + float lowLen=prepP*wLen; | |
| 861 | + float upLen=(1.0f-prepP)*wLen; | |
| 862 | + uint32_t pickPInt; | |
| 863 | +/* | |
| 864 | + if (pickP > prepP) | |
| 865 | + { | |
| 866 | + float fullPickPoint = ((pickP*wLen) - lowLen); | |
| 867 | + pickPInt = (uint) fullPickPoint; // where does the input go? that's the pick point | |
| 868 | + float pickPFloat = fullPickPoint - pickPInt; | |
| 869 | + | |
| 870 | + tHermiteDelay_addTo(&p->delUF, input * (1.0f - pickPFloat), pickPInt); | |
| 871 | + tHermiteDelay_addTo(&p->delUF, input * pickPFloat, pickPInt + 1); | |
| 872 | + tHermiteDelay_addTo(&p->delUB, input * (1.0f - pickPFloat), (uint) (upLen - pickPInt)); | |
| 873 | + tHermiteDelay_addTo(&p->delUB, input * pickPFloat, (uint) (upLen - pickPInt - 1)); | |
| 874 | + } | |
| 875 | + else | |
| 876 | + { | |
| 877 | + float fullPickPoint = pickP * wLen; | |
| 878 | + pickPInt = (uint) fullPickPoint; // where does the input go? that's the pick point | |
| 879 | + float pickPFloat = fullPickPoint - pickPInt; | |
| 880 | + | |
| 881 | + tHermiteDelay_addTo(&p->delLF, input * (1.0f - pickPFloat), pickPInt); | |
| 882 | + tHermiteDelay_addTo(&p->delLF, input * pickPFloat, pickPInt + 1); | |
| 883 | + tHermiteDelay_addTo(&p->delLB, input * (1.0f - pickPFloat), (uint) (lowLen - pickPInt)); | |
| 884 | + tHermiteDelay_addTo(&p->delLB, input * pickPFloat, (uint) (lowLen - pickPInt - 1)); | |
| 885 | + } | |
| 886 | +*/ | |
| 887 | + if (pickP > prepP) | |
| 888 | + { | |
| 889 | + float fullPickPoint = ((pickP*wLen) - lowLen); | |
| 890 | + pickPInt = (uint32_t) fullPickPoint; // where does the input go? that's the pick point | |
| 891 | + | |
| 892 | + tHermiteDelay_addTo(&p->delUF, input, pickPInt); | |
| 893 | + tHermiteDelay_addTo(&p->delUB, input, (uint32_t) (upLen - pickPInt)); | |
| 894 | + } | |
| 895 | + else | |
| 896 | + { | |
| 897 | + float fullPickPoint = pickP * wLen; | |
| 898 | + pickPInt = (uint32_t) fullPickPoint; // where does the input go? that's the pick point | |
| 899 | + | |
| 900 | + tHermiteDelay_addTo(&p->delLF, input, pickPInt); | |
| 901 | + tHermiteDelay_addTo(&p->delLB, input, (uint32_t) (lowLen - pickPInt)); | |
| 902 | + } | |
| 903 | + | |
| 904 | + float fromLF=tHermiteDelay_tickOut(&p->delLF); | |
| 905 | + float fromUF=tHermiteDelay_tickOut(&p->delUF); | |
| 906 | + float fromUB=tHermiteDelay_tickOut(&p->delUB); | |
| 907 | + float fromLB=tHermiteDelay_tickOut(&p->delLB); | |
| 908 | + // into upper half of string, from bridge, going backwards | |
| 909 | + float fromBridge=-tFeedbackLeveler_tick(&p->fbLevU, (p->levMode==0?p->decay:1)*tHighpass_tick(&p->DCblockerU, tTwoZero_tick(&p->bridgeFilter, fromUF))); | |
| 910 | + tHermiteDelay_tickIn(&p->delUB, fromBridge); | |
| 911 | + // into lower half of string, from prepPoint, going backwards | |
| 912 | + float fromLowerPrep=-tTwoZero_tick(&p->prepFilterL, fromLF); | |
| 913 | + float intoLower=p->prepIndex*fromLowerPrep+(1.0f - p->prepIndex)*fromUB; //used to add input here | |
| 914 | + tHermiteDelay_tickIn(&p->delLB, intoLower); | |
| 915 | + // into lower half of string, from nut | |
| 916 | + float fromNut=-tFeedbackLeveler_tick(&p->fbLevL, (p->levMode==0?p->decay:1.0f)*tHighpass_tick(&p->DCblockerL, tTwoZero_tick(&p->nutFilter, fromLB))); | |
| 917 | + tHermiteDelay_tickIn(&p->delLF, fromNut); | |
| 918 | + // into upper half of string, from prepPoint, going forwards/upwards | |
| 919 | + float fromUpperPrep=-tTwoZero_tick(&p->prepFilterU, fromUB); | |
| 920 | + float intoUpper=p->prepIndex*fromUpperPrep+(1.0f - p->prepIndex)*fromLF; | |
| 921 | + tHermiteDelay_tickIn(&p->delUF, intoUpper); | |
| 922 | + // update all delay lengths | |
| 923 | + | |
| 924 | + tHermiteDelay_setDelay(&p->delLF, lowLen); | |
| 925 | + tHermiteDelay_setDelay(&p->delLB, lowLen); | |
| 926 | + tHermiteDelay_setDelay(&p->delUF, upLen); | |
| 927 | + tHermiteDelay_setDelay(&p->delUB, upLen); | |
| 928 | + | |
| 929 | + /* | |
| 930 | + uint pickupPosInt; | |
| 931 | + float pickupOut = 0.0f; | |
| 932 | + if (pickupPos < 0.9f) | |
| 933 | + { | |
| 934 | + float fullPickupPos = (pickupPos*upLen); | |
| 935 | + pickupPosInt = (uint) fullPickupPos; | |
| 936 | + float pickupPosFloat = fullPickupPos - pickupPosInt; | |
| 937 | + if (pickupPosInt == 0) | |
| 938 | + { | |
| 939 | + pickupPosInt = 1; | |
| 940 | + } | |
| 941 | + pickupOut = tHermiteDelay_tapOutInterpolated(&p->delUF, pickupPosInt, pickupPosFloat); | |
| 942 | + pickupOut += tHermiteDelay_tapOutInterpolated(&p->delUB, (uint) (upLen - pickupPosInt), pickupPosFloat); | |
| 943 | + p->curr = pickupOut; | |
| 944 | + } | |
| 945 | + else | |
| 946 | + */ | |
| 947 | + //{ | |
| 948 | + p->curr = fromBridge; | |
| 949 | + //} | |
| 950 | + | |
| 951 | + //p->curr = fromBridge; | |
| 952 | + //p->curr += fromNut; | |
| 953 | + | |
| 954 | + return p->curr; | |
| 955 | +} | |
| 956 | + | |
| 957 | +float tLivingString2_sample(tLivingString2* const pl) | |
| 958 | +{ | |
| 959 | + _tLivingString2* p = *pl; | |
| 960 | + return p->curr; | |
| 961 | +} | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 662 | 965 | //////////--------------------------- |
| 663 | 966 | |
| 664 | 967 | /* Complex Living String (has pick position and preparation position separated) */ |
| @@ -58,7 +58,7 @@ · 57 unmodified lines | ||
| 58 | 58 | |
| 59 | 59 | #define LEAF_USE_CMSIS 0 |
| 60 | 60 | |
| 61 | −//! Use stdlib malloc() and free() internally instead of LEAF's normal mempool behavior for when you want to avoid being limited to and managing mempool a fixed mempool size. Usage of all object remains essentially the same. | |
| 61 | +//! Use stdlib malloc() and free() internally instead of LEAF's normal mempool behavior for when you want to avoid being limited to and managing mempool a fixed mempool size. Usage of all object remains essentially the same. | |
| 62 | 62 | #define LEAF_USE_DYNAMIC_ALLOCATION 1 |
| 63 | 63 | |
| 64 | 64 | //============================================================================== |