ref: b0581564da7738318ea9f7805fb2bd3b0b73bcc4
dir: /LEAF/Src/leaf-reverb.c/
/*============================================================================== leaf-reverb.c Created: 20 Jan 2017 12:02:04pm Author: Michael R Mulshine ==============================================================================*/ #if _WIN32 || _WIN64 #include "..\Inc\leaf-reverb.h" #include "..\leaf.h" #else #include "../Inc/leaf-reverb.h" #include "../leaf.h" #endif // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PRCReverb ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // static void prcreverb_init(tPRCReverb* const rev, float t60) { _tPRCReverb* r = *rev; if (t60 <= 0.0f) t60 = 0.001f; r->inv_441 = 1.0f/44100.0f; // Delay lengths for 44100 Hz sample rate. r->lengths[0] = 341; r->lengths[1] = 613; r->lengths[2] = 1557; r->lengths[3] = 2137; double scaler = leaf.sampleRate * r->inv_441; int delay, i; if (scaler != 1.0f) { for (i=0; i<4; i++) { delay = (int) scaler * r->lengths[i]; if ( (delay & 1) == 0) delay++; while ( !LEAF_isPrime(delay) ) delay += 2; r->lengths[i] = delay; } } tPRCReverb_setT60(rev, t60); r->allpassCoeff = 0.7f; r->mix = 0.5f; } void tPRCReverb_init(tPRCReverb* const rev, float t60) { _tPRCReverb* r = *rev = (_tPRCReverb*) leaf_alloc(sizeof(_tPRCReverb)); prcreverb_init(rev, t60); tDelay_init(&r->allpassDelays[0], r->lengths[0], r->lengths[0] * 2); tDelay_init(&r->allpassDelays[1], r->lengths[1], r->lengths[1] * 2); tDelay_init(&r->combDelay, r->lengths[2], r->lengths[2] * 2); } void tPRCReverb_free(tPRCReverb* const rev) { _tPRCReverb* r = *rev; tDelay_free(&r->allpassDelays[0]); tDelay_free(&r->allpassDelays[1]); tDelay_free(&r->combDelay); leaf_free(r); } void tPRCReverb_initToPool (tPRCReverb* const rev, float t60, tMempool* const mp) { _tMempool* m = *mp; _tPRCReverb* r = *rev = (_tPRCReverb*) mpool_alloc(sizeof(_tPRCReverb), &m->pool); prcreverb_init(rev, t60); tDelay_initToPool(&r->allpassDelays[0], r->lengths[0], r->lengths[0] * 2, mp); tDelay_initToPool(&r->allpassDelays[1], r->lengths[1], r->lengths[1] * 2, mp); tDelay_initToPool(&r->combDelay, r->lengths[2], r->lengths[2] * 2, mp); } void tPRCReverb_freeFromPool (tPRCReverb* const rev, tMempool* const mp) { _tMempool* m = *mp; _tPRCReverb* r = *rev; tDelay_freeFromPool(&r->allpassDelays[0], mp); tDelay_freeFromPool(&r->allpassDelays[1], mp); tDelay_freeFromPool(&r->combDelay, mp); mpool_free(r, &m->pool); } void tPRCReverb_setT60(tPRCReverb* const rev, float t60) { _tPRCReverb* r = *rev; if ( t60 <= 0.0f ) t60 = 0.001f; r->t60 = t60; r->combCoeff = pow(10.0f, (-3.0f * tDelay_getDelay(&r->combDelay) * leaf.invSampleRate / t60 )); } void tPRCReverb_setMix(tPRCReverb* const rev, float mix) { _tPRCReverb* r = *rev; r->mix = mix; } float tPRCReverb_tick(tPRCReverb* const rev, float input) { _tPRCReverb* r = *rev; float temp, temp0, temp1, temp2; float out; r->lastIn = input; temp = tDelay_getLastOut(&r->allpassDelays[0]); temp0 = r->allpassCoeff * temp; temp0 += input; tDelay_tick(&r->allpassDelays[0], temp0); temp0 = -( r->allpassCoeff * temp0) + temp; temp = tDelay_getLastOut(&r->allpassDelays[1]); temp1 = r->allpassCoeff * temp; temp1 += temp0; tDelay_tick(&r->allpassDelays[1], temp1); temp1 = -(r->allpassCoeff * temp1) + temp; temp2 = temp1 + ( r->combCoeff * tDelay_getLastOut(&r->combDelay)); out = r->mix * tDelay_tick(&r->combDelay, temp2); temp = (1.0f - r->mix) * input; out += temp; r->lastOut = out; return out; } void tPRCReverbSampleRateChanged (tPRCReverb* const rev) { _tPRCReverb* r = *rev; r->combCoeff = pow(10.0f, (-3.0f * tDelay_getDelay(&r->combDelay) * leaf.invSampleRate / r->t60 )); } /* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ NReverb ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */ static void nreverb_init(tNReverb* const rev, float t60) { _tNReverb* r = *rev; if (t60 <= 0.0f) t60 = 0.001f; r->inv_441 = 1.0f/44100.0f; int l[15] = {1433, 1601, 1867, 2053, 2251, 2399, 347, 113, 37, 59, 53, 43, 37, 29, 19}; // Delay lengths for 44100 Hz sample rate. for (int i = 0; i < 15; i++) r->lengths[i] = l[i]; double scaler = leaf.sampleRate / 25641.0f; int delay, i; for (i=0; i < 15; i++) { delay = (int) scaler * r->lengths[i]; if ( (delay & 1) == 0) delay++; while ( !LEAF_isPrime(delay) ) delay += 2; r->lengths[i] = delay; } tNReverb_setT60(rev, t60); r->allpassCoeff = 0.7f; r->mix = 0.3f; for (int i = 0; i < 6; i++) { r->combCoeffs[i] = pow(10.0, (-3 * r->lengths[i] * leaf.invSampleRate / t60)); } } void tNReverb_init(tNReverb* const rev, float t60) { _tNReverb* r = *rev = (_tNReverb*) leaf_alloc(sizeof(_tNReverb)); nreverb_init(rev, t60); for (int i = 0; i < 6; i++) { tLinearDelay_init(&r->combDelays[i], r->lengths[i], r->lengths[i] * 2.0f); } for (int i = 0; i < 8; i++) { tLinearDelay_init(&r->allpassDelays[i], r->lengths[i+6], r->lengths[i+6] * 2.0f); } } void tNReverb_free(tNReverb* const rev) { _tNReverb* r = *rev; for (int i = 0; i < 6; i++) { tLinearDelay_free(&r->combDelays[i]); } for (int i = 0; i < 8; i++) { tLinearDelay_free(&r->allpassDelays[i]); } leaf_free(r); } void tNReverb_initToPool (tNReverb* const rev, float t60, tMempool* const mp) { _tMempool* m = *mp; _tNReverb* r = *rev = (_tNReverb*) mpool_alloc(sizeof(_tNReverb), &m->pool); nreverb_init(rev, t60); for (int i = 0; i < 6; i++) { tLinearDelay_initToPool(&r->combDelays[i], r->lengths[i], r->lengths[i] * 2.0f, mp); } for (int i = 0; i < 8; i++) { tLinearDelay_initToPool(&r->allpassDelays[i], r->lengths[i+6], r->lengths[i+6] * 2.0f, mp); } } void tNReverb_freeFromPool (tNReverb* const rev, tMempool* const mp) { _tMempool* m = *mp; _tNReverb* r = *rev; for (int i = 0; i < 6; i++) { tLinearDelay_freeFromPool(&r->combDelays[i], mp); } for (int i = 0; i < 8; i++) { tLinearDelay_freeFromPool(&r->allpassDelays[i], mp); } mpool_free(r, &m->pool); } void tNReverb_setT60(tNReverb* const rev, float t60) { _tNReverb* r = *rev; if (t60 <= 0.0f) t60 = 0.001f; r->t60 = t60; for (int i=0; i<6; i++) r->combCoeffs[i] = pow(10.0, (-3.0 * tLinearDelay_getDelay(&r->combDelays[i]) * leaf.invSampleRate / t60 )); } void tNReverb_setMix(tNReverb* const rev, float mix) { _tNReverb* r = *rev; r->mix = mix; } float tNReverb_tick(tNReverb* const rev, float input) { _tNReverb* r = *rev; r->lastIn = input; float temp, temp0, temp1, temp2, out; int i; temp0 = 0.0; for ( i=0; i<6; i++ ) { temp = input + (r->combCoeffs[i] * tLinearDelay_getLastOut(&r->combDelays[i])); temp0 += tLinearDelay_tick(&r->combDelays[i],temp); } for ( i=0; i<3; i++ ) { temp = tLinearDelay_getLastOut(&r->allpassDelays[i]); temp1 = r->allpassCoeff * temp; temp1 += temp0; tLinearDelay_tick(&r->allpassDelays[i], temp1); temp0 = -(r->allpassCoeff * temp1) + temp; } // One-pole lowpass filter. r->lowpassState = 0.7f * r->lowpassState + 0.3f * temp0; temp = tLinearDelay_getLastOut(&r->allpassDelays[3]); temp1 = r->allpassCoeff * temp; temp1 += r->lowpassState; tLinearDelay_tick(&r->allpassDelays[3], temp1 ); temp1 = -(r->allpassCoeff * temp1) + temp; temp = tLinearDelay_getLastOut(&r->allpassDelays[4]); temp2 = r->allpassCoeff * temp; temp2 += temp1; tLinearDelay_tick(&r->allpassDelays[4], temp2 ); out = -( r->allpassCoeff * temp2 ) + temp ; //the other channel in stereo version below /* temp = tLinearDelay_getLastOut(&r->allpassDelays[5]); temp3 = r->allpassCoeff * temp; temp3 += temp1; tLinearDelay_tick(&r->allpassDelays[5], temp3 ); out = r->mix *( - ( r->allpassCoeff * temp3 ) + temp ); */ temp = ( 1.0f - r->mix ) * input; out += temp; r->lastOut = out; return out; } void tNReverb_tickStereo(tNReverb* const rev, float input, float* output) { _tNReverb* r = *rev; r->lastIn = input; float temp, temp0, temp1, temp2, temp3, out; int i; temp0 = 0.0; for ( i=0; i<6; i++ ) { temp = input + (r->combCoeffs[i] * tLinearDelay_getLastOut(&r->combDelays[i])); temp0 += tLinearDelay_tick(&r->combDelays[i],temp); } for ( i=0; i<3; i++ ) { temp = tLinearDelay_getLastOut(&r->allpassDelays[i]); temp1 = r->allpassCoeff * temp; temp1 += temp0; tLinearDelay_tick(&r->allpassDelays[i], temp1); temp0 = -(r->allpassCoeff * temp1) + temp; } // One-pole lowpass filter. r->lowpassState = 0.7f * r->lowpassState + 0.3f * temp0; temp = tLinearDelay_getLastOut(&r->allpassDelays[3]); temp1 = r->allpassCoeff * temp; temp1 += r->lowpassState; tLinearDelay_tick(&r->allpassDelays[3], temp1 ); temp1 = -(r->allpassCoeff * temp1) + temp; float drymix = ( 1.0f - r->mix ) * input; temp = tLinearDelay_getLastOut(&r->allpassDelays[4]); temp2 = r->allpassCoeff * temp; temp2 += temp1; tLinearDelay_tick(&r->allpassDelays[4], temp2 ); output[0] = -( r->allpassCoeff * temp2 ) + temp + drymix; out = output[0]; temp = tLinearDelay_getLastOut(&r->allpassDelays[5]); temp3 = r->allpassCoeff * temp; temp3 += temp1; tLinearDelay_tick(&r->allpassDelays[5], temp3 ); output[1] = r->mix *( - ( r->allpassCoeff * temp3 ) + temp + drymix); r->lastOut = out; } void tNReverbSampleRateChanged (tNReverb* const rev) { _tNReverb* r = *rev; for (int i=0; i<6; i++) r->combCoeffs[i] = pow(10.0, (-3.0 * tLinearDelay_getDelay(&r->combDelays[i]) * leaf.invSampleRate / r->t60 )); } // ======================================DATTORRO========================================= #define SAMP(in) (in*r->t) float in_allpass_delays[4] = { 4.771f, 3.595f, 12.73f, 9.307f }; float in_allpass_gains[4] = { 0.75f, 0.75f, 0.625f, 0.625f }; static void dattorroreverb_init (tDattorroReverb* const rev) { _tDattorroReverb* r = *rev; r->size_max = 2.0f; r->size = 1.f; r->frozen = 0; // INPUT for (int i = 0; i < 4; i++) { tAllpass_setGain(&r->in_allpass[i], in_allpass_gains[i]); } // FEEDBACK 1 tAllpass_setGain(&r->f1_allpass, 0.7f); tCycle_setFreq(&r->f1_lfo, 0.1f); // FEEDBACK 2 tAllpass_setGain(&r->f2_allpass, 0.7f); tCycle_setFreq(&r->f2_lfo, 0.07f); // PARAMETERS tDattorroReverb_setMix(rev, 0.5f); tDattorroReverb_setInputDelay(rev, 0.f); tDattorroReverb_setInputFilter(rev, 10000.f); tDattorroReverb_setFeedbackFilter(rev, 5000.f); tDattorroReverb_setFeedbackGain(rev, 0.4f); } void tDattorroReverb_init (tDattorroReverb* const rev) { _tDattorroReverb* r = *rev = (_tDattorroReverb*) leaf_alloc(sizeof(_tDattorroReverb)); float size_max = 2.0f; r->t = leaf.sampleRate * 0.001f; // INPUT tTapeDelay_init(&r->in_delay, 0.f, SAMP(200.f)); tOnePole_init(&r->in_filter, 1.f); for (int i = 0; i < 4; i++) { tAllpass_init(&r->in_allpass[i], SAMP(in_allpass_delays[i]), SAMP(20.f)); // * r->size_max } // FEEDBACK 1 tAllpass_init(&r->f1_allpass, SAMP(30.51f), SAMP(100.f)); // * r->size_max tTapeDelay_init(&r->f1_delay_1, SAMP(141.69f), SAMP(200.0f) * size_max + 1); tTapeDelay_init(&r->f1_delay_2, SAMP(89.24f), SAMP(100.0f) * size_max + 1); tTapeDelay_init(&r->f1_delay_3, SAMP(125.f), SAMP(200.0f) * size_max + 1); tOnePole_init(&r->f1_filter, 1.f); tHighpass_init(&r->f1_hp, 20.f); tCycle_init(&r->f1_lfo); // FEEDBACK 2 tAllpass_init(&r->f2_allpass, SAMP(22.58f), SAMP(100.f)); // * r->size_max tTapeDelay_init(&r->f2_delay_1, SAMP(149.62f), SAMP(200.f) * size_max + 1); tTapeDelay_init(&r->f2_delay_2, SAMP(60.48f), SAMP(100.f) * size_max + 1); tTapeDelay_init(&r->f2_delay_3, SAMP(106.28f), SAMP(200.f) * size_max + 1); tOnePole_init(&r->f2_filter, 1.f); tHighpass_init(&r->f2_hp, 20.f); tCycle_init(&r->f2_lfo); dattorroreverb_init(rev); } void tDattorroReverb_free (tDattorroReverb* const rev) { _tDattorroReverb* r = *rev; // INPUT tTapeDelay_free(&r->in_delay); tOnePole_free(&r->in_filter); for (int i = 0; i < 4; i++) { tAllpass_free(&r->in_allpass[i]); } // FEEDBACK 1 tAllpass_free(&r->f1_allpass); tTapeDelay_free(&r->f1_delay_1); tTapeDelay_free(&r->f1_delay_2); tTapeDelay_free(&r->f1_delay_3); tOnePole_free(&r->f1_filter); tHighpass_free(&r->f1_hp); tCycle_free(&r->f1_lfo); // FEEDBACK 2 tAllpass_free(&r->f2_allpass); tTapeDelay_free(&r->f2_delay_1); tTapeDelay_free(&r->f2_delay_2); tTapeDelay_free(&r->f2_delay_3); tOnePole_free(&r->f2_filter); tHighpass_free(&r->f2_hp); tCycle_free(&r->f2_lfo); leaf_free(r); } void tDattorroReverb_initToPool (tDattorroReverb* const rev, tMempool* const mp) { _tMempool* m = *mp; _tDattorroReverb* r = *rev = (_tDattorroReverb*) mpool_alloc(sizeof(_tDattorroReverb), &m->pool); float size_max = 2.0f; r->t = leaf.sampleRate * 0.001f; // INPUT tTapeDelay_initToPool(&r->in_delay, 0.f, SAMP(200.f), mp); tOnePole_initToPool(&r->in_filter, 1.f, mp); for (int i = 0; i < 4; i++) { tAllpass_initToPool(&r->in_allpass[i], SAMP(in_allpass_delays[i]), SAMP(20.f), mp); // * r->size_max } // FEEDBACK 1 tAllpass_initToPool(&r->f1_allpass, SAMP(30.51f), SAMP(100.f), mp); // * r->size_max tTapeDelay_initToPool(&r->f1_delay_1, SAMP(141.69f), SAMP(200.0f) * size_max + 1, mp); tTapeDelay_initToPool(&r->f1_delay_2, SAMP(89.24f), SAMP(100.0f) * size_max + 1, mp); tTapeDelay_initToPool(&r->f1_delay_3, SAMP(125.f), SAMP(200.0f) * size_max + 1, mp); tOnePole_initToPool(&r->f1_filter, 1.f, mp); tHighpass_initToPool(&r->f1_hp, 20.f, mp); tCycle_initToPool(&r->f1_lfo, mp); // FEEDBACK 2 tAllpass_initToPool(&r->f2_allpass, SAMP(22.58f), SAMP(100.f), mp); // * r->size_max tTapeDelay_initToPool(&r->f2_delay_1, SAMP(149.62f), SAMP(200.f) * size_max + 1, mp); tTapeDelay_initToPool(&r->f2_delay_2, SAMP(60.48f), SAMP(100.f) * size_max + 1, mp); tTapeDelay_initToPool(&r->f2_delay_3, SAMP(106.28f), SAMP(200.f) * size_max + 1, mp); tOnePole_initToPool(&r->f2_filter, 1.f, mp); tHighpass_initToPool(&r->f2_hp, 20.f, mp); tCycle_initToPool(&r->f2_lfo, mp); dattorroreverb_init(rev); } void tDattorroReverb_freeFromPool (tDattorroReverb* const rev, tMempool* const mp) { _tMempool* m = *mp; _tDattorroReverb* r = *rev; // INPUT tTapeDelay_freeFromPool(&r->in_delay, mp); tOnePole_freeFromPool(&r->in_filter, mp); for (int i = 0; i < 4; i++) { tAllpass_freeFromPool(&r->in_allpass[i], mp); } // FEEDBACK 1 tAllpass_freeFromPool(&r->f1_allpass, mp); tTapeDelay_freeFromPool(&r->f1_delay_1, mp); tTapeDelay_freeFromPool(&r->f1_delay_2, mp); tTapeDelay_freeFromPool(&r->f1_delay_3, mp); tOnePole_freeFromPool(&r->f1_filter, mp); tHighpass_freeFromPool(&r->f1_hp, mp); tCycle_freeFromPool(&r->f1_lfo, mp); // FEEDBACK 2 tAllpass_freeFromPool(&r->f2_allpass, mp); tTapeDelay_freeFromPool(&r->f2_delay_1, mp); tTapeDelay_freeFromPool(&r->f2_delay_2, mp); tTapeDelay_freeFromPool(&r->f2_delay_3, mp); tOnePole_freeFromPool(&r->f2_filter, mp); tHighpass_freeFromPool(&r->f2_hp, mp); tCycle_freeFromPool(&r->f2_lfo, mp); mpool_free(r, &m->pool); } float tDattorroReverb_tick (tDattorroReverb* const rev, float input) { _tDattorroReverb* r = *rev; float in_sample, f1_sample,f1_delay_2_sample, f2_sample, f2_delay_2_sample; if (r->frozen) { input = 0.0f; //r->f1_last = 0.0f; //r->f2_last = 0.0f; } // INPUT in_sample = tTapeDelay_tick(&r->in_delay, input); in_sample = tOnePole_tick(&r->in_filter, in_sample); for (int i = 0; i < 4; i++) { in_sample = tAllpass_tick(&r->in_allpass[i], in_sample); } // FEEDBACK 1 f1_sample = in_sample + r->f2_last; // + f2_last_out; tAllpass_setDelay(&r->f1_allpass, SAMP(30.51f) + tCycle_tick(&r->f1_lfo) * SAMP(4.0f)); f1_sample = tAllpass_tick(&r->f1_allpass, f1_sample); f1_sample = tTapeDelay_tick(&r->f1_delay_1, f1_sample); f1_sample = tOnePole_tick(&r->f1_filter, f1_sample); f1_sample = f1_sample + r->f1_delay_2_last * 0.5f; f1_delay_2_sample = tTapeDelay_tick(&r->f1_delay_2, f1_sample * 0.5f); r->f1_delay_2_last = f1_delay_2_sample; f1_sample = r->f1_delay_2_last + f1_sample; f1_sample = tHighpass_tick(&r->f1_hp, f1_sample); f1_sample *= r->feedback_gain; r->f1_last = tTapeDelay_tick(&r->f1_delay_3, f1_sample); // FEEDBACK 2 f2_sample = in_sample + r->f1_last; tAllpass_setDelay(&r->f2_allpass, SAMP(22.58f) + tCycle_tick(&r->f2_lfo) * SAMP(4.0f)); f2_sample = tAllpass_tick(&r->f2_allpass, f2_sample); f2_sample = tTapeDelay_tick(&r->f2_delay_1, f2_sample); f2_sample = tOnePole_tick(&r->f2_filter, f2_sample); f2_sample = f2_sample + r->f2_delay_2_last * 0.5f; f2_delay_2_sample = tTapeDelay_tick(&r->f2_delay_2, f2_sample * 0.5f); r->f2_delay_2_last = f2_delay_2_sample; f2_sample = r->f2_delay_2_last + f2_sample; f2_sample = tHighpass_tick(&r->f2_hp, f2_sample); f2_sample *= r->feedback_gain; r->f2_last = tTapeDelay_tick(&r->f2_delay_3, f2_sample); // TAP OUT 1 f1_sample = tTapeDelay_tapOut(&r->f1_delay_1, SAMP(8.9f)) + tTapeDelay_tapOut(&r->f1_delay_1, SAMP(99.8f)); f1_sample -= tTapeDelay_tapOut(&r->f1_delay_2, SAMP(64.2f)); f1_sample += tTapeDelay_tapOut(&r->f1_delay_3, SAMP(67.f)); f1_sample -= tTapeDelay_tapOut(&r->f2_delay_1, SAMP(66.8f)); f1_sample -= tTapeDelay_tapOut(&r->f2_delay_2, SAMP(6.3f)); f1_sample -= tTapeDelay_tapOut(&r->f2_delay_3, SAMP(35.8f)); f1_sample *= 0.14f; // TAP OUT 2 f2_sample = tTapeDelay_tapOut(&r->f2_delay_1, SAMP(11.8f)) + tTapeDelay_tapOut(&r->f2_delay_1, SAMP(121.7f)); f2_sample -= tTapeDelay_tapOut(&r->f2_delay_2, SAMP(6.3f)); f2_sample += tTapeDelay_tapOut(&r->f2_delay_3, SAMP(89.7f)); f2_sample -= tTapeDelay_tapOut(&r->f1_delay_1, SAMP(70.8f)); f2_sample -= tTapeDelay_tapOut(&r->f1_delay_2, SAMP(11.2f)); f2_sample -= tTapeDelay_tapOut(&r->f1_delay_3, SAMP(4.1f)); f2_sample *= 0.14f; float sample = (f1_sample + f2_sample) * 0.5f; return (input * (1.0f - r->mix) + sample * r->mix); } void tDattorroReverb_tickStereo (tDattorroReverb* const rev, float input, float* output) { _tDattorroReverb* r = *rev; float in_sample, f1_sample,f1_delay_2_sample, f2_sample, f2_delay_2_sample; if (r->frozen) { input = 0.0f; //r->f1_last = 0.0f; //r->f2_last = 0.0f; } // INPUT in_sample = tTapeDelay_tick(&r->in_delay, input); in_sample = tOnePole_tick(&r->in_filter, in_sample); for (int i = 0; i < 4; i++) { in_sample = tAllpass_tick(&r->in_allpass[i], in_sample); } // FEEDBACK 1 f1_sample = in_sample + r->f2_last; // + f2_last_out; tAllpass_setDelay(&r->f1_allpass, SAMP(30.51f) + tCycle_tick(&r->f1_lfo) * SAMP(4.0f)); f1_sample = tAllpass_tick(&r->f1_allpass, f1_sample); f1_sample = tTapeDelay_tick(&r->f1_delay_1, f1_sample); f1_sample = tOnePole_tick(&r->f1_filter, f1_sample); f1_sample = f1_sample + r->f1_delay_2_last * 0.5f; f1_delay_2_sample = tTapeDelay_tick(&r->f1_delay_2, f1_sample * 0.5f); r->f1_delay_2_last = f1_delay_2_sample; f1_sample = r->f1_delay_2_last + f1_sample; f1_sample = tHighpass_tick(&r->f1_hp, f1_sample); f1_sample *= r->feedback_gain; if (r->frozen) { f1_sample = 0.0f; } r->f1_last = tTapeDelay_tick(&r->f1_delay_3, f1_sample); // FEEDBACK 2 f2_sample = in_sample + r->f1_last; tAllpass_setDelay(&r->f2_allpass, SAMP(22.58f) + tCycle_tick(&r->f2_lfo) * SAMP(4.0f)); f2_sample = tAllpass_tick(&r->f2_allpass, f2_sample); f2_sample = tTapeDelay_tick(&r->f2_delay_1, f2_sample); f2_sample = tOnePole_tick(&r->f2_filter, f2_sample); f2_sample = f2_sample + r->f2_delay_2_last * 0.5f; f2_delay_2_sample = tTapeDelay_tick(&r->f2_delay_2, f2_sample * 0.5f); r->f2_delay_2_last = f2_delay_2_sample; f2_sample = r->f2_delay_2_last + f2_sample; f2_sample = tHighpass_tick(&r->f2_hp, f2_sample); f2_sample *= r->feedback_gain; if (r->frozen) { f2_sample = 0.0f; } r->f2_last = tTapeDelay_tick(&r->f2_delay_3, f2_sample); // TAP OUT 1 f1_sample = tTapeDelay_tapOut(&r->f1_delay_1, SAMP(8.9f)) + tTapeDelay_tapOut(&r->f1_delay_1, SAMP(99.8f)); f1_sample -= tTapeDelay_tapOut(&r->f1_delay_2, SAMP(64.2f)); f1_sample += tTapeDelay_tapOut(&r->f1_delay_3, SAMP(67.f)); f1_sample -= tTapeDelay_tapOut(&r->f2_delay_1, SAMP(66.8f)); f1_sample -= tTapeDelay_tapOut(&r->f2_delay_2, SAMP(6.3f)); f1_sample -= tTapeDelay_tapOut(&r->f2_delay_3, SAMP(35.8f)); f1_sample *= 0.14f; // TAP OUT 2 f2_sample = tTapeDelay_tapOut(&r->f2_delay_1, SAMP(11.8f)) + tTapeDelay_tapOut(&r->f2_delay_1, SAMP(121.7f)); f2_sample -= tTapeDelay_tapOut(&r->f2_delay_2, SAMP(6.3f)); f2_sample += tTapeDelay_tapOut(&r->f2_delay_3, SAMP(89.7f)); f2_sample -= tTapeDelay_tapOut(&r->f1_delay_1, SAMP(70.8f)); f2_sample -= tTapeDelay_tapOut(&r->f1_delay_2, SAMP(11.2f)); f2_sample -= tTapeDelay_tapOut(&r->f1_delay_3, SAMP(4.1f)); f2_sample *= 0.14f; output[0] = input * (1.0f - r->mix) + f1_sample * r->mix; output[1] = input * (1.0f - r->mix) + f2_sample * r->mix; } void tDattorroReverb_setMix (tDattorroReverb* const rev, float mix) { _tDattorroReverb* r = *rev; r->mix = LEAF_clip(0.0f, mix, 1.0f); } void tDattorroReverb_setFreeze (tDattorroReverb* const rev, uint32_t freeze) { _tDattorroReverb* r = *rev; r->frozen = freeze; if (freeze) { tAllpass_setGain(&r->f2_allpass, 1.0f); tAllpass_setGain(&r->f1_allpass, 1.0f); for (int i = 0; i < 4; i++) { //tAllpass_setGain(&r->in_allpass[i], 1.0f); } tCycle_setFreq(&r->f1_lfo, 0.0f); tCycle_setFreq(&r->f2_lfo, 0.0f); } else { tAllpass_setGain(&r->f2_allpass, 0.7f); tAllpass_setGain(&r->f1_allpass, 0.7f); for (int i = 0; i < 4; i++) { //tAllpass_setGain(&r->in_allpass[i], in_allpass_gains[i]); } tCycle_setFreq(&r->f1_lfo, 0.1f); tCycle_setFreq(&r->f2_lfo, 0.07f); } } void tDattorroReverb_setHP (tDattorroReverb* const rev, float freq) { _tDattorroReverb* r = *rev; float newFreq = LEAF_clip(20.0f, freq, 20000.0f); tHighpass_setFreq(&r->f1_hp, newFreq); tHighpass_setFreq(&r->f2_hp, newFreq); } void tDattorroReverb_setSize (tDattorroReverb* const rev, float size) { _tDattorroReverb* r = *rev; r->size = LEAF_clip(0.01f, size*r->size_max, r->size_max); r->t = r->size * leaf.sampleRate * 0.001f; /* for (int i = 0; i < 4; i++) { tAllpass_setDelay(&r->in_allpass[i], SAMP(in_allpass_delays[i])); } */ // FEEDBACK 1 //tAllpass_setDelay(&r->f1_allpass, SAMP(30.51f)); tTapeDelay_setDelay(&r->f1_delay_1, SAMP(141.69f)); tTapeDelay_setDelay(&r->f1_delay_2, SAMP(89.24f)); tTapeDelay_setDelay(&r->f1_delay_3, SAMP(125.f)); // maybe change rate of SINE LFO's when size changes? //tCycle_setFreq(&r->f2_lfo, 0.07f * size * r->size_max); // FEEDBACK 2 //tAllpass_setDelay(&r->f2_allpass, SAMP(22.58f)); tTapeDelay_setDelay(&r->f2_delay_1, SAMP(149.62f)); tTapeDelay_setDelay(&r->f2_delay_2, SAMP(60.48f)); tTapeDelay_setDelay(&r->f2_delay_3, SAMP(106.28f)); } void tDattorroReverb_setInputDelay (tDattorroReverb* const rev, float preDelay) { _tDattorroReverb* r = *rev; r->predelay = LEAF_clip(0.0f, preDelay, 200.0f); tTapeDelay_setDelay(&r->in_delay, SAMP(r->predelay)); } void tDattorroReverb_setInputFilter (tDattorroReverb* const rev, float freq) { _tDattorroReverb* r = *rev; r->input_filter = LEAF_clip(0.0f, freq, 20000.0f); tOnePole_setFreq(&r->in_filter, r->input_filter); } void tDattorroReverb_setFeedbackFilter (tDattorroReverb* const rev, float freq) { _tDattorroReverb* r = *rev; r->feedback_filter = LEAF_clip(0.0f, freq, 20000.0f); tOnePole_setFreq(&r->f1_filter, r->feedback_filter); tOnePole_setFreq(&r->f2_filter, r->feedback_filter); } void tDattorroReverb_setFeedbackGain (tDattorroReverb* const rev, float gain) { _tDattorroReverb* r = *rev; r->feedback_gain = gain; }