/************************************************************************************ ** ** ** UHSDR Firmware ** ** O Belousov - R1CBU 2021 ** ** ** **--------------------------------------------------------------------------------** ** ** ** File name: ** ** Description: ** ** Last Modified: ** ** Licence: GNU GPLv3 ** ************************************************************************************/ #include "uhsdr_board.h" #include "audio_reverb.h" //#define CF0 2595 //#define CF1 2241 //#define CF2 2911 //#define CF3 3234 #define DECIM 5 //#define AP0 480 //#define AP1 161 //#define AP2 46 #define CF0 (3460 / DECIM) #define CF1 (2988 / DECIM) #define CF2 (3882 / DECIM) #define CF3 (4312 / DECIM) #define AP0 (480 / DECIM) #define AP1 (161 / DECIM) #define AP2 (46 / DECIM) static float32_t cfbuf0[CF0]; static float32_t cfbuf1[CF1]; static float32_t cfbuf2[CF2]; static float32_t cfbuf3[CF3]; static float32_t apbuf0[AP0]; static float32_t apbuf1[AP1]; static float32_t apbuf2[AP2]; typedef struct { float32_t *buf; uint16_t index; uint16_t delay; float32_t gain; } item_t; static float32_t wet0 = 1.0f; static float32_t wet1 = 0.0f; static float32_t result = 0.0f; static uint8_t decim_count = 0; static item_t cf0, cf1, cf2, cf3; static item_t ap0, ap1, ap2; static float32_t CalcComb(float32_t in, item_t *comb) { float32_t readback = comb->buf[comb->index]; float32_t new = readback * comb->gain + in; comb->buf[comb->index] = new; comb->index++; if (comb->index > comb->delay) comb->index = 0; return readback; } static float32_t CalcAllPass(float32_t in, item_t *allpass) { float32_t reedback = allpass->buf[allpass->index] - allpass->gain*in; float32_t new = reedback*allpass->gain + in; allpass->buf[allpass->index] = new; allpass->index++; if (allpass->index > allpass->delay) allpass->index = 0; return reedback; } void AudioReverb_Init(void) { cf0.buf = (float32_t*) &cfbuf0; cf0.gain = 0.805f; cf1.buf = (float32_t*) &cfbuf1; cf1.gain = 0.827f; cf2.buf = (float32_t*) &cfbuf2; cf2.gain = 0.783f; cf3.buf = (float32_t*) &cfbuf3; cf3.gain = 0.764f; ap0.buf = (float32_t*) &apbuf0; ap0.gain = 0.7f; ap1.buf = (float32_t*) &apbuf1; ap1.gain = 0.7f; ap2.buf = (float32_t*) &apbuf2; ap2.gain = 0.7f; wet0 = 1.0f; wet1 = 0.0f; result = 0.0f; decim_count = 0; // AudioReverb_SetDelay(1.0f); // AudioReverb_SetWet(0.5f); AudioReverb_SetDelay(); AudioReverb_SetWet(); } //void AudioReverb_SetDelay(float32_t x) { // cf0.delay = (uint16_t) (x * CF0); // cf1.delay = (uint16_t) (x * CF1); // cf2.delay = (uint16_t) (x * CF2); // cf3.delay = (uint16_t) (x * CF3); // // ap0.delay = (uint16_t) (x * AP0); // ap1.delay = (uint16_t) (x * AP1); // ap2.delay = (uint16_t) (x * AP2); //} void AudioReverb_SetDelay() { float32_t x = ts.reverb_delay / 100.f; cf0.index = 0; cf0.delay = (uint16_t) (x * CF0); cf1.index = 0; cf1.delay = (uint16_t) (x * CF1); cf2.index = 0; cf2.delay = (uint16_t) (x * CF2); cf3.index = 0; cf3.delay = (uint16_t) (x * CF3); ap0.index = 0; ap0.delay = (uint16_t) (x * AP0); ap1.index = 0; ap1.delay = (uint16_t) (x * AP1); ap2.index = 0; ap2.delay = (uint16_t) (x * AP2); } //void AudioReverb_SetWet(float32_t x) { void AudioReverb_SetWet() { float32_t x = ts.reverb_gain / 100.0f; wet0 = x; wet1 = 1.0f - x; } float32_t AudioReverb_Calc(float32_t in) { // float32_t new = (CalcComb(in, &cf0) + CalcComb(in, &cf1) + CalcComb(in, &cf2) + CalcComb(in, &cf3)) / 4.0f; decim_count++; if (decim_count >= DECIM) { result = (CalcComb(in, &cf0) + CalcComb(in, &cf1) + CalcComb(in, &cf2) + CalcComb(in, &cf3)) / 4.0f; result = CalcAllPass(result, &ap0); result = CalcAllPass(result, &ap1); result = CalcAllPass(result, &ap2); // new = CalcAllPass(new, &ap0); // new = CalcAllPass(new, &ap1); // new = CalcAllPass(new, &ap2); decim_count = 0; } // return wet0 * new + wet1 * in; return wet0 * result + wet1 * in; }