Unified · Split
| @@ -64,7 +64,8 @@ extern "C" { · 63 unmodified lines | ||
| 64 | 64 | |
| 65 | 65 | float tauAttack, tauRelease; |
| 66 | 66 | float T, R, W, M; // Threshold, compression Ratio, decibel Width of knee transition, decibel Make-up gain |
| 67 | − | |
| 67 | + float invR; | |
| 68 | + float inv4W; | |
| 68 | 69 | float x_G[2], y_G[2], x_T[2], y_T[2]; |
| 69 | 70 | |
| 70 | 71 | int isActive; |
| @@ -1072,6 +1072,7 @@ extern "C" { · 1071 unmodified lines | ||
| 1072 | 1072 | void tVZFilter_setResonance (tVZFilter* const vf, float res); |
| 1073 | 1073 | void tVZFilter_setFrequencyAndResonance (tVZFilter* const vf, float freq, float res); |
| 1074 | 1074 | void tVZFilter_setFrequencyAndResonanceAndGain (tVZFilter* const vf, float freq, float res, float gains); |
| 1075 | + void tVZFilter_setFastFrequencyAndResonanceAndGain (tVZFilter* const vf, float freq, float res, float gain); | |
| 1075 | 1076 | void tVZFilter_setFrequencyAndBandwidthAndGain (tVZFilter* const vf, float freq, float BW, float gain); |
| 1076 | 1077 | void tVZFilter_setFrequencyAndResonanceAndMorph (tVZFilter* const vf, float freq, float res, float morph); |
| 1077 | 1078 | void tVZFilter_setMorphOnly (tVZFilter* const vf, float morph); |
| @@ -217,6 +217,8 @@ extern "C" { · 216 unmodified lines | ||
| 217 | 217 | |
| 218 | 218 | float atodb(float a); |
| 219 | 219 | |
| 220 | + float fasteratodb(float a); | |
| 221 | + | |
| 220 | 222 | float dbtoa(float db); |
| 221 | 223 | |
| 222 | 224 | float fastdbtoa(float db); |
| @@ -351,26 +351,28 @@ typedef struct _tSimpleLivingString3 · 350 unmodified lines | ||
| 351 | 351 | float curr; |
| 352 | 352 | float Uout; |
| 353 | 353 | float Lout; |
| 354 | + int maxLength; | |
| 354 | 355 | tLinearDelay delayLineU; |
| 355 | 356 | tLinearDelay delayLineL; |
| 356 | 357 | tOnePole bridgeFilter; |
| 357 | 358 | tHighpass DCblocker; |
| 358 | 359 | tFeedbackLeveler fbLev; |
| 359 | 360 | tExpSmooth wlSmooth; |
| 361 | + int oversampling; | |
| 360 | 362 | float sampleRate; |
| 361 | 363 | } _tSimpleLivingString3; |
| 362 | 364 | |
| 363 | 365 | typedef _tSimpleLivingString3* tSimpleLivingString3; |
| 364 | 366 | |
| 365 | −void tSimpleLivingString3_init (tSimpleLivingString3* const, float freq, float dampFreq, | |
| 367 | +void tSimpleLivingString3_init (tSimpleLivingString3* const, int oversampling, float freq, float dampFreq, | |
| 366 | 368 | float decay, float targetLev, float levSmoothFactor, |
| 367 | 369 | float levStrength, int levMode, LEAF* const leaf); |
| 368 | −void tSimpleLivingString3_initToPool (tSimpleLivingString3* const, float freq, float dampFreq, | |
| 369 | − float decay, float targetLev, float levSmoothFactor, | |
| 370 | − float levStrength, int levMode, tMempool* const); | |
| 370 | +void tSimpleLivingString3_initToPool (tSimpleLivingString3* const pl, int oversampling, float freq, float dampFreq, | |
| 371 | + float decay, float targetLev, float levSmoothFactor, | |
| 372 | + float levStrength, int levMode, tMempool* const mp); | |
| 371 | 373 | void tSimpleLivingString3_free (tSimpleLivingString3* const); |
| 372 | 374 | |
| 373 | −float tSimpleLivingString3_pluck (tSimpleLivingString3* const pl, float input, float position); | |
| 375 | +void tSimpleLivingString3_pluck (tSimpleLivingString3* const pl, float input, float position); | |
| 374 | 376 | float tSimpleLivingString3_tick (tSimpleLivingString3* const, float input); |
| 375 | 377 | float tSimpleLivingString3_sample (tSimpleLivingString3* const); |
| 376 | 378 | void tSimpleLivingString3_setFreq (tSimpleLivingString3* const, float freq); |
| @@ -64,8 +64,10 @@ void tCompressor_initToPool (tCompressor* const comp, tMempool* const mp) · 63 unmodified lines | ||
| 64 | 64 | c->y_T[0] = 0.0f, c->y_T[1] = 0.0f; |
| 65 | 65 | c->T = 0.0f; // Threshold |
| 66 | 66 | c->R = 0.5f; // compression Ratio |
| 67 | + c->invR = 2.0f; //inverse of ratio | |
| 67 | 68 | c->M = 3.0f; // decibel Make-up gain |
| 68 | − c->W = 1.0f; // decibel Width of knee transition | |
| 69 | + c->W = 1.5f; // decibel Width of knee transition | |
| 70 | + c->inv4W = 1.0f / (4.0f * c->W) ; | |
| 69 | 71 | |
| 70 | 72 | |
| 71 | 73 | } |
| @@ -83,34 +85,33 @@ float tCompressor_tick(tCompressor* const comp, float in) · 11 unmodified lines | ||
| 83 | 85 | |
| 84 | 86 | float slope, overshoot; |
| 85 | 87 | |
| 86 | − float in_db = LEAF_clip(-90.0f, atodb(fabsf(in)), 0.0f); | |
| 88 | + float in_db = LEAF_clip(-90.0f, fasteratodb(fastabsf(in)), 0.0f); | |
| 87 | 89 | float out_db = 0.0f; |
| 88 | 90 | |
| 89 | 91 | c->y_T[1] = c->y_T[0]; |
| 90 | 92 | |
| 91 | − slope = 1.0f - (1.0f/c->R); // feed-forward topology; | |
| 93 | + slope = 1.0f - c->invR; // feed-forward topology; | |
| 92 | 94 | |
| 93 | 95 | overshoot = in_db - c->T; |
| 94 | 96 | |
| 95 | − /* | |
| 96 | − if (overshoot <= -(c->W * 0.5f)) | |
| 97 | + | |
| 98 | + if (overshoot <= -(c->W)) | |
| 97 | 99 | { |
| 98 | 100 | out_db = in_db; |
| 99 | 101 | c->isActive = 0; |
| 100 | 102 | } |
| 101 | − | |
| 102 | − else if ((overshoot > -(c->W * 0.5f)) && (overshoot < (c->W * 0.5f))) | |
| 103 | + else if ((overshoot > -(c->W)) && (overshoot < (c->W))) | |
| 103 | 104 | { |
| 104 | − float squareit = (overshoot + c->W*0.5f); | |
| 105 | − out_db = in_db + slope * ((squareit * squareit) / (2.0f * c->W)); // .^ 2 ??? | |
| 105 | + float squareit = (overshoot + c->W); | |
| 106 | + out_db = in_db + slope * ((squareit * squareit) * c->inv4W); // .^ 2 ??? | |
| 106 | 107 | c->isActive = 1; |
| 107 | 108 | } |
| 108 | − else if (overshoot >= (c->W * 0.5f)) | |
| 109 | + else | |
| 109 | 110 | { |
| 110 | 111 | out_db = in_db + slope * overshoot; |
| 111 | 112 | c->isActive = 1; |
| 112 | 113 | } |
| 113 | − */ | |
| 114 | +/* // simpler hard-knee version | |
| 114 | 115 | if (overshoot <= 0.0f) |
| 115 | 116 | { |
| 116 | 117 | out_db = in_db; |
| @@ -121,26 +122,13 @@ float tCompressor_tick(tCompressor* const comp, float in) · 4 unmodified lines | ||
| 121 | 122 | out_db = in_db + slope * overshoot; |
| 122 | 123 | c->isActive = 1; |
| 123 | 124 | } |
| 124 | − | |
| 125 | + */ | |
| 125 | 126 | c->x_T[0] = out_db - in_db; |
| 126 | − | |
| 127 | − | |
| 128 | − | |
| 129 | 127 | if (c->x_T[0] > c->y_T[1]) |
| 130 | 128 | c->y_T[0] = c->tauAttack * c->y_T[1] + (1.0f-c->tauAttack) * c->x_T[0]; |
| 131 | 129 | else |
| 132 | 130 | c->y_T[0] = c->tauRelease * c->y_T[1] + (1.0f-c->tauRelease) * c->x_T[0]; |
| 133 | − if (isnan(c->y_T[0])) | |
| 134 | − { | |
| 135 | − out_db = 1.0f; | |
| 136 | − } | |
| 137 | − | |
| 138 | 131 | float attenuation = fasterdbtoa(c->M - c->y_T[0]); |
| 139 | − if (isnan(attenuation)) | |
| 140 | − { | |
| 141 | − out_db = 1.0f; | |
| 142 | − } | |
| 143 | − //float attenuation = 1.0f; | |
| 144 | 132 | return attenuation * in; |
| 145 | 133 | } |
| 146 | 134 | |
| @@ -158,10 +146,12 @@ void tCompressor_setParams(tCompressor* const comp, float thresh, float ratio, f · 11 unmodified lines | ||
| 158 | 146 | _tCompressor* c = *comp; |
| 159 | 147 | c->T = thresh; |
| 160 | 148 | c->R = ratio; |
| 161 | − c->W = knee; | |
| 149 | + c->invR = 1.0f / ratio; | |
| 150 | + c->W = knee * 0.5f; | |
| 151 | + c->inv4W = 1.0f / (2.0f * knee); | |
| 162 | 152 | c->M = makeup; |
| 163 | − c->tauAttack = expf(-1.0f/(0.001f * attack * c->sampleRate)); | |
| 164 | − c->tauRelease = expf(-1.0f/(0.001f * release * c->sampleRate)); | |
| 153 | + c->tauAttack = fasterexpf(-1.0f/(0.001f * attack * c->sampleRate)); | |
| 154 | + c->tauRelease = fasterexpf(-1.0f/(0.001f * release * c->sampleRate)); | |
| 165 | 155 | } |
| 166 | 156 | |
| 167 | 157 | /* Feedback Leveler */ |
| @@ -1524,7 +1524,7 @@ void tVZFilter_setFreqFast (tVZFilter* const vf, float cutoff) · 1523 unmodified lines | ||
| 1524 | 1524 | int intVer = (int)cutoff; |
| 1525 | 1525 | float floatVer = cutoff - (float)intVer; |
| 1526 | 1526 | f->g = (__leaf_table_filtertan[intVer] * (1.0f - floatVer)) + (__leaf_table_filtertan[intVer+1] * floatVer); |
| 1527 | − | |
| 1527 | + | |
| 1528 | 1528 | switch( f->type ) |
| 1529 | 1529 | { |
| 1530 | 1530 | case Bypass: |
| @@ -1697,6 +1697,18 @@ void tVZFilter_setFrequencyAndResonanceAndGain (tVZFilter* const vf, float freq, · 166 unmodified lines | ||
| 1697 | 1697 | f->invG = 1.0f/f->G; |
| 1698 | 1698 | tVZFilter_calcCoeffs(vf); |
| 1699 | 1699 | } |
| 1700 | + | |
| 1701 | +void tVZFilter_setFastFrequencyAndResonanceAndGain (tVZFilter* const vf, float freq, float res, float gain) | |
| 1702 | +{ | |
| 1703 | + _tVZFilter* f = *vf; | |
| 1704 | + //f->fc = LEAF_clip(0.1f, freq, 0.4f * f->sampleRate); | |
| 1705 | + f->Q = LEAF_clip(0.01f, res, 100.0f); | |
| 1706 | + f->R2 = 1.0f / f->Q; | |
| 1707 | + f->G = LEAF_clip(0.000001f, gain, 4000.0f); | |
| 1708 | + f->invG = 1.0f/f->G; | |
| 1709 | + tVZFilter_setFreqFast(vf, freq); | |
| 1710 | +} | |
| 1711 | + | |
| 1700 | 1712 | void tVZFilter_setFrequencyAndBandwidthAndGain (tVZFilter* const vf, float freq, float BW, float gain) |
| 1701 | 1713 | { |
| 1702 | 1714 | _tVZFilter* f = *vf; |
| @@ -1708,6 +1720,7 @@ void tVZFilter_setFrequencyAndBandwidthAndGain (tVZFilter* const vf, float freq, · 5 unmodified lines | ||
| 1708 | 1720 | tVZFilter_calcCoeffs(vf); |
| 1709 | 1721 | } |
| 1710 | 1722 | |
| 1723 | + | |
| 1711 | 1724 | void tVZFilter_setFrequencyAndResonanceAndMorph (tVZFilter* const vf, float freq, float res, float morph) |
| 1712 | 1725 | { |
| 1713 | 1726 | _tVZFilter* f = *vf; |
| @@ -810,11 +810,14 @@ float atodb(float a) · 809 unmodified lines | ||
| 810 | 810 | { |
| 811 | 811 | return 20.0f*log10f(a); |
| 812 | 812 | } |
| 813 | +float fasteratodb(float a) | |
| 814 | +{ | |
| 815 | + return 20.0f*log10f_fast(a); | |
| 816 | +} | |
| 813 | 817 | |
| 814 | 818 | float dbtoa(float db) |
| 815 | 819 | { |
| 816 | 820 | return powf(10.0f, db * 0.05f); |
| 817 | − //return expf(0.115129254649702f * db); //faster version from http://openaudio.blogspot.com/2017/02/faster-log10-and-pow.html | |
| 818 | 821 | } |
| 819 | 822 | |
| 820 | 823 | |
| @@ -501,14 +501,14 @@ void tSimpleLivingString_setSampleRate(tSimpleLivingString* const pl, float sr · 500 unmodified lines | ||
| 501 | 501 | |
| 502 | 502 | /* Simple Living String*/ |
| 503 | 503 | |
| 504 | −void tSimpleLivingString3_init(tSimpleLivingString3* const pl, float freq, float dampFreq, | |
| 504 | +void tSimpleLivingString3_init(tSimpleLivingString3* const pl, int oversampling, float freq, float dampFreq, | |
| 505 | 505 | float decay, float targetLev, float levSmoothFactor, |
| 506 | 506 | float levStrength, int levMode, LEAF* const leaf) |
| 507 | 507 | { |
| 508 | − tSimpleLivingString3_initToPool(pl, freq, dampFreq, decay, targetLev, levSmoothFactor, levStrength, levMode, &leaf->mempool); | |
| 508 | + tSimpleLivingString3_initToPool(pl, oversampling, freq, dampFreq, decay, targetLev, levSmoothFactor, levStrength, levMode, &leaf->mempool); | |
| 509 | 509 | } |
| 510 | 510 | |
| 511 | −void tSimpleLivingString3_initToPool (tSimpleLivingString3* const pl, float freq, float dampFreq, | |
| 511 | +void tSimpleLivingString3_initToPool (tSimpleLivingString3* const pl, int oversampling, float freq, float dampFreq, | |
| 512 | 512 | float decay, float targetLev, float levSmoothFactor, |
| 513 | 513 | float levStrength, int levMode, tMempool* const mp) |
| 514 | 514 | { |
| @@ -516,12 +516,13 @@ void tSimpleLivingString3_initToPool (tSimpleLivingString3* const pl, float · 1 unmodified line | ||
| 516 | 516 | _tSimpleLivingString3* p = *pl = (_tSimpleLivingString3*) mpool_alloc(sizeof(_tSimpleLivingString3), m); |
| 517 | 517 | p->mempool = m; |
| 518 | 518 | LEAF* leaf = p->mempool->leaf; |
| 519 | − | |
| 520 | − p->sampleRate = leaf->sampleRate; | |
| 519 | + p->oversampling = oversampling; | |
| 520 | + p->sampleRate = leaf->sampleRate * oversampling; | |
| 521 | 521 | p->curr=0.0f; |
| 522 | + p->maxLength = 2400 * oversampling; | |
| 522 | 523 | tExpSmooth_initToPool(&p->wlSmooth, p->sampleRate/freq/2.0f, 0.01f, mp); // smoother for string wavelength (not freq, to avoid expensive divisions) |
| 523 | − tLinearDelay_initToPool(&p->delayLineU,p->waveLengthInSamples, 2400, mp); | |
| 524 | − tLinearDelay_initToPool(&p->delayLineL,p->waveLengthInSamples, 2400, mp); | |
| 524 | + tLinearDelay_initToPool(&p->delayLineU,p->waveLengthInSamples, p->maxLength, mp); | |
| 525 | + tLinearDelay_initToPool(&p->delayLineL,p->waveLengthInSamples, p->maxLength, mp); | |
| 525 | 526 | tSimpleLivingString3_setFreq(pl, freq); |
| 526 | 527 | tLinearDelay_setDelay(&p->delayLineU, p->waveLengthInSamples); |
| 527 | 528 | tLinearDelay_setDelay(&p->delayLineL, p->waveLengthInSamples); |
| @@ -554,10 +555,11 @@ void tSimpleLivingString3_free (tSimpleLivingString3* const pl) · 26 unmodified lines | ||
| 554 | 555 | void tSimpleLivingString3_setFreq(tSimpleLivingString3* const pl, float freq) |
| 555 | 556 | { |
| 556 | 557 | _tSimpleLivingString3* p = *pl; |
| 557 | − | |
| 558 | − if (freq<20) freq=20; | |
| 559 | − else if (freq>10000) freq=10000; | |
| 560 | − p->waveLengthInSamples = (p->sampleRate/freq) * 0.5f; | |
| 558 | + p->freq = freq; | |
| 559 | + float waveLength = (p->sampleRate/freq); | |
| 560 | + if (waveLength<4.8) waveLength=4.8f; | |
| 561 | + else if (waveLength>p->maxLength*2) waveLength=p->maxLength*2; | |
| 562 | + p->waveLengthInSamples = waveLength * 0.5f; | |
| 561 | 563 | tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples); |
| 562 | 564 | } |
| 563 | 565 | |
| @@ -566,7 +568,7 @@ void tSimpleLivingString3_setWaveLength(tSimpleLivingString3* const pl, floa · 2 unmodified lines | ||
| 566 | 568 | _tSimpleLivingString3* p = *pl; |
| 567 | 569 | |
| 568 | 570 | if (waveLength<4.8) waveLength=4.8f; |
| 569 | − else if (waveLength>4800) waveLength=4800; | |
| 571 | + else if (waveLength>p->maxLength*2) waveLength=p->maxLength*2; | |
| 570 | 572 | p->waveLengthInSamples = waveLength * 0.5f; |
| 571 | 573 | tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples); |
| 572 | 574 | } |
| @@ -608,7 +610,7 @@ void tSimpleLivingString3_setLevMode(tSimpleLivingString3* const pl, int lev · 35 unmodified lines | ||
| 608 | 610 | p->levMode=levMode; |
| 609 | 611 | } |
| 610 | 612 | |
| 611 | −float tSimpleLivingString3_pluck(tSimpleLivingString3* const pl, float input, float position) | |
| 613 | +void tSimpleLivingString3_pluck(tSimpleLivingString3* const pl, float input, float position) | |
| 612 | 614 | { |
| 613 | 615 | _tSimpleLivingString3* p = *pl; |
| 614 | 616 | int length = p->waveLengthInSamples; |
| @@ -636,7 +638,6 @@ float tSimpleLivingString3_pluck(tSimpleLivingString3* const pl, float input, · 21 unmodified lines | ||
| 636 | 638 | int currentBufReadPointMod = currentBufReadPoint % p->delayLineU->maxDelay; |
| 637 | 639 | p->delayLineL->buff[currentBufWritePoint] = p->delayLineU->buff[currentBufReadPointMod]; |
| 638 | 640 | } |
| 639 | − | |
| 640 | 641 | } |
| 641 | 642 | |
| 642 | 643 | float tSimpleLivingString3_tick(tSimpleLivingString3* const pl, float input) |
| @@ -644,8 +645,6 @@ float tSimpleLivingString3_tick(tSimpleLivingString3* const pl, float input) · 1 unmodified line | ||
| 644 | 645 | _tSimpleLivingString3* p = *pl; |
| 645 | 646 | tLinearDelay_setDelay(&p->delayLineU, tExpSmooth_tick(&p->wlSmooth)); |
| 646 | 647 | tLinearDelay_setDelay(&p->delayLineL, tExpSmooth_tick(&p->wlSmooth)); |
| 647 | − //tLinearDelay_setDelay(&p->delayLineU, p->waveLengthInSamples); | |
| 648 | − //tLinearDelay_setDelay(&p->delayLineL, p->waveLengthInSamples); | |
| 649 | 648 | |
| 650 | 649 | p->Uout = tOnePole_tick(&p->bridgeFilter,tLinearDelay_tickOut(&p->delayLineU)); |
| 651 | 650 | p->Lout = tLinearDelay_tickOut(&p->delayLineL); |