diff options
| author | Pierre Bourdon <delroth@gmail.com> | 2016-06-24 10:43:46 +0200 |
|---|---|---|
| committer | Pierre Bourdon <delroth@gmail.com> | 2016-06-24 10:43:46 +0200 |
| commit | 3570c7f03a2aa90aa634f96c0af1969af610f14d (patch) | |
| tree | 4252e03c0e853ba7cffe022937698c854ad0eaa9 /Source/Core/AudioCommon/DPL2Decoder.cpp | |
| parent | 2115e8a4a6814e32107b5205ff5c95bbd3c6e99c (diff) | |
Reformat all the things. Have fun with merge conflicts.
Diffstat (limited to 'Source/Core/AudioCommon/DPL2Decoder.cpp')
| -rw-r--r-- | Source/Core/AudioCommon/DPL2Decoder.cpp | 574 |
1 files changed, 285 insertions, 289 deletions
diff --git a/Source/Core/AudioCommon/DPL2Decoder.cpp b/Source/Core/AudioCommon/DPL2Decoder.cpp index 036f0e96c8..fa483249e6 100644 --- a/Source/Core/AudioCommon/DPL2Decoder.cpp +++ b/Source/Core/AudioCommon/DPL2Decoder.cpp @@ -35,54 +35,56 @@ static float adapt_l_gain, adapt_r_gain, adapt_lpr_gain, adapt_lmr_gain; static std::vector<float> lf, rf, lr, rr, cf, cr; static float LFE_buf[256]; static unsigned int lfe_pos; -static float *filter_coefs_lfe; +static float* filter_coefs_lfe; static unsigned int len125; -template<class T, class _ftype_t> -static _ftype_t DotProduct(int count, const T *buf, const _ftype_t *coefficients) +template <class T, class _ftype_t> +static _ftype_t DotProduct(int count, const T* buf, const _ftype_t* coefficients) { - int i; - float sum0 = 0.0f, sum1 = 0.0f, sum2 = 0.0f, sum3 = 0.0f; - - // Unrolled loop - for (i = 0; (i + 3) < count; i += 4) - { - sum0 += buf[i + 0] * coefficients[i + 0]; - sum1 += buf[i + 1] * coefficients[i + 1]; - sum2 += buf[i + 2] * coefficients[i + 2]; - sum3 += buf[i + 3] * coefficients[i + 3]; - } - - // Epilogue of unrolled loop - for (; i < count; i++) - sum0 += buf[i] * coefficients[i]; - - return sum0 + sum1 + sum2 + sum3; + int i; + float sum0 = 0.0f, sum1 = 0.0f, sum2 = 0.0f, sum3 = 0.0f; + + // Unrolled loop + for (i = 0; (i + 3) < count; i += 4) + { + sum0 += buf[i + 0] * coefficients[i + 0]; + sum1 += buf[i + 1] * coefficients[i + 1]; + sum2 += buf[i + 2] * coefficients[i + 2]; + sum3 += buf[i + 3] * coefficients[i + 3]; + } + + // Epilogue of unrolled loop + for (; i < count; i++) + sum0 += buf[i] * coefficients[i]; + + return sum0 + sum1 + sum2 + sum3; } -template<class T> -static T FIRFilter(const T *buf, int pos, int len, int count, const float *coefficients) +template <class T> +static T FIRFilter(const T* buf, int pos, int len, int count, const float* coefficients) { - int count1, count2; - - if (pos >= count) - { - pos -= count; - count1 = count; count2 = 0; - } - else - { - count2 = pos; - count1 = count - pos; - pos = len - count1; - } - - // high part of window - const T *ptr = &buf[pos]; - - float r1 = DotProduct(count1, ptr, coefficients); coefficients += count1; - float r2 = DotProduct(count2, buf, coefficients); - return T(r1 + r2); + int count1, count2; + + if (pos >= count) + { + pos -= count; + count1 = count; + count2 = 0; + } + else + { + count2 = pos; + count1 = count - pos; + pos = len - count1; + } + + // high part of window + const T* ptr = &buf[pos]; + + float r1 = DotProduct(count1, ptr, coefficients); + coefficients += count1; + float r2 = DotProduct(count2, buf, coefficients); + return T(r1 + r2); } /* @@ -96,11 +98,11 @@ static T FIRFilter(const T *buf, int pos, int len, int count, const float *coeff */ static void Hamming(int n, float* w) { - float k = float(2*M_PI/((float)(n - 1))); // 2*pi/(N-1) + float k = float(2 * M_PI / ((float)(n - 1))); // 2*pi/(N-1) - // Calculate window coefficients - for (int i = 0; i < n; i++) - *w++ = float(0.54 - 0.46*cos(k*(float)i)); + // Calculate window coefficients + for (int i = 0; i < n; i++) + *w++ = float(0.54 - 0.46 * cos(k * (float)i)); } /****************************************************************************** @@ -120,276 +122,270 @@ opt beta constant used only when designing using kaiser windows returns 0 if OK, -1 if fail */ -static float* DesignFIR(unsigned int *n, float* fc, float opt) +static float* DesignFIR(unsigned int* n, float* fc, float opt) { - unsigned int o = *n & 1; // Indicator for odd filter length - unsigned int end = ((*n + 1) >> 1) - o; // Loop end - - float k1 = 2 * float(M_PI); // 2*pi*fc1 - float k2 = 0.5f * (float)(1 - o); // Constant used if the filter has even length - float g = 0.0f; // Gain - float t1; // Temporary variables - float fc1; // Cutoff frequencies - - // Sanity check - if (*n == 0) - return nullptr; - - fc[0] = MathUtil::Clamp(fc[0], 0.001f, 1.0f); - - float *w = (float*)calloc(sizeof(float), *n); - - // Get window coefficients - Hamming(*n, w); - - fc1 = *fc; - // Cutoff frequency must be < 0.5 where 0.5 <=> Fs/2 - fc1 = ((fc1 <= 1.0) && (fc1 > 0.0)) ? fc1 / 2 : 0.25f; - k1 *= fc1; - - // Low pass filter - - // If the filter length is odd, there is one point which is exactly - // in the middle. The value at this point is 2*fCutoff*sin(x)/x, - // where x is zero. To make sure nothing strange happens, we set this - // value separately. - if (o) - { - w[end] = fc1 * w[end] * 2.0f; - g = w[end]; - } - - // Create filter - for (u32 i = 0; i < end; i++) - { - t1 = (float)(i + 1) - k2; - w[end - i - 1] = w[*n - end + i] = float(w[end - i - 1] * sin(k1 * t1)/(M_PI * t1)); // Sinc - g += 2*w[end - i - 1]; // Total gain in filter - } - - - // Normalize gain - g = 1/g; - for (u32 i = 0; i < *n; i++) - w[i] *= g; - - return w; + unsigned int o = *n & 1; // Indicator for odd filter length + unsigned int end = ((*n + 1) >> 1) - o; // Loop end + + float k1 = 2 * float(M_PI); // 2*pi*fc1 + float k2 = 0.5f * (float)(1 - o); // Constant used if the filter has even length + float g = 0.0f; // Gain + float t1; // Temporary variables + float fc1; // Cutoff frequencies + + // Sanity check + if (*n == 0) + return nullptr; + + fc[0] = MathUtil::Clamp(fc[0], 0.001f, 1.0f); + + float* w = (float*)calloc(sizeof(float), *n); + + // Get window coefficients + Hamming(*n, w); + + fc1 = *fc; + // Cutoff frequency must be < 0.5 where 0.5 <=> Fs/2 + fc1 = ((fc1 <= 1.0) && (fc1 > 0.0)) ? fc1 / 2 : 0.25f; + k1 *= fc1; + + // Low pass filter + + // If the filter length is odd, there is one point which is exactly + // in the middle. The value at this point is 2*fCutoff*sin(x)/x, + // where x is zero. To make sure nothing strange happens, we set this + // value separately. + if (o) + { + w[end] = fc1 * w[end] * 2.0f; + g = w[end]; + } + + // Create filter + for (u32 i = 0; i < end; i++) + { + t1 = (float)(i + 1) - k2; + w[end - i - 1] = w[*n - end + i] = float(w[end - i - 1] * sin(k1 * t1) / (M_PI * t1)); // Sinc + g += 2 * w[end - i - 1]; // Total gain in filter + } + + // Normalize gain + g = 1 / g; + for (u32 i = 0; i < *n; i++) + w[i] *= g; + + return w; } static void OnSeek() { - l_fwr = r_fwr = lpr_fwr = lmr_fwr = 0; - std::fill(fwrbuf_l.begin(), fwrbuf_l.end(), 0.0f); - std::fill(fwrbuf_r.begin(), fwrbuf_r.end(), 0.0f); - adapt_l_gain = adapt_r_gain = adapt_lpr_gain = adapt_lmr_gain = 0; - std::fill(lf.begin(), lf.end(), 0.0f); - std::fill(rf.begin(), rf.end(), 0.0f); - std::fill(lr.begin(), lr.end(), 0.0f); - std::fill(rr.begin(), rr.end(), 0.0f); - std::fill(cf.begin(), cf.end(), 0.0f); - std::fill(cr.begin(), cr.end(), 0.0f); - lfe_pos = 0; - memset(LFE_buf, 0, sizeof(LFE_buf)); + l_fwr = r_fwr = lpr_fwr = lmr_fwr = 0; + std::fill(fwrbuf_l.begin(), fwrbuf_l.end(), 0.0f); + std::fill(fwrbuf_r.begin(), fwrbuf_r.end(), 0.0f); + adapt_l_gain = adapt_r_gain = adapt_lpr_gain = adapt_lmr_gain = 0; + std::fill(lf.begin(), lf.end(), 0.0f); + std::fill(rf.begin(), rf.end(), 0.0f); + std::fill(lr.begin(), lr.end(), 0.0f); + std::fill(rr.begin(), rr.end(), 0.0f); + std::fill(cf.begin(), cf.end(), 0.0f); + std::fill(cr.begin(), cr.end(), 0.0f); + lfe_pos = 0; + memset(LFE_buf, 0, sizeof(LFE_buf)); } static void Done() { - OnSeek(); + OnSeek(); - if (filter_coefs_lfe) - { - free(filter_coefs_lfe); - } + if (filter_coefs_lfe) + { + free(filter_coefs_lfe); + } - filter_coefs_lfe = nullptr; + filter_coefs_lfe = nullptr; } static float* CalculateCoefficients125HzLowpass(int rate) { - len125 = 256; - float f = 125.0f / (rate / 2); - float *coeffs = DesignFIR(&len125, &f, 0); - static const float M3_01DB = 0.7071067812f; - for (unsigned int i = 0; i < len125; i++) - { - coeffs[i] *= M3_01DB; - } - return coeffs; + len125 = 256; + float f = 125.0f / (rate / 2); + float* coeffs = DesignFIR(&len125, &f, 0); + static const float M3_01DB = 0.7071067812f; + for (unsigned int i = 0; i < len125; i++) + { + coeffs[i] *= M3_01DB; + } + return coeffs; } static float PassiveLock(float x) { - static const float MATAGCLOCK = 0.2f; /* AGC range (around 1) where the matrix behaves passively */ - const float x1 = x - 1; - const float ax1s = fabs(x - 1) * (1.0f / MATAGCLOCK); - return x1 - x1 / (1 + ax1s * ax1s) + 1; + static const float MATAGCLOCK = + 0.2f; /* AGC range (around 1) where the matrix behaves passively */ + const float x1 = x - 1; + const float ax1s = fabs(x - 1) * (1.0f / MATAGCLOCK); + return x1 - x1 / (1 + ax1s * ax1s) + 1; } -static void MatrixDecode(const float *in, const int k, const int il, - const int ir, bool decode_rear, - const int _dlbuflen, - float _l_fwr, float _r_fwr, - float _lpr_fwr, float _lmr_fwr, - float *_adapt_l_gain, float *_adapt_r_gain, - float *_adapt_lpr_gain, float *_adapt_lmr_gain, - float *_lf, float *_rf, float *_lr, - float *_rr, float *_cf) +static void MatrixDecode(const float* in, const int k, const int il, const int ir, bool decode_rear, + const int _dlbuflen, float _l_fwr, float _r_fwr, float _lpr_fwr, + float _lmr_fwr, float* _adapt_l_gain, float* _adapt_r_gain, + float* _adapt_lpr_gain, float* _adapt_lmr_gain, float* _lf, float* _rf, + float* _lr, float* _rr, float* _cf) { - static const float M9_03DB = 0.3535533906f; - static const float MATAGCTRIG = 8.0f; /* (Fuzzy) AGC trigger */ - static const float MATAGCDECAY = 1.0f; /* AGC baseline decay rate (1/samp.) */ - static const float MATCOMPGAIN = 0.37f; /* Cross talk compensation gain, 0.50 - 0.55 is full cancellation. */ - - const int kr = (k + olddelay) % _dlbuflen; - float l_gain = (_l_fwr + _r_fwr) / (1 + _l_fwr + _l_fwr); - float r_gain = (_l_fwr + _r_fwr) / (1 + _r_fwr + _r_fwr); - // The 2nd axis has strong gain fluctuations, and therefore require - // limits. The factor corresponds to the 1 / amplification of (Lt - // - Rt) when (Lt, Rt) is strongly correlated. (e.g. during - // dialogues). It should be bigger than -12 dB to prevent - // distortion. - float lmr_lim_fwr = _lmr_fwr > M9_03DB * _lpr_fwr ? _lmr_fwr : M9_03DB * _lpr_fwr; - float lpr_gain = (_lpr_fwr + lmr_lim_fwr) / (1 + _lpr_fwr + _lpr_fwr); - float lmr_gain = (_lpr_fwr + lmr_lim_fwr) / (1 + lmr_lim_fwr + lmr_lim_fwr); - float lmr_unlim_gain = (_lpr_fwr + _lmr_fwr) / (1 + _lmr_fwr + _lmr_fwr); - float lpr, lmr; - float l_agc, r_agc, lpr_agc, lmr_agc; - float f, d_gain, c_gain, c_agc_cfk; - - /*** AXIS NO. 1: (Lt, Rt) -> (C, Ls, Rs) ***/ - /* AGC adaption */ - d_gain = (fabs(l_gain - *_adapt_l_gain) + fabs(r_gain - *_adapt_r_gain)) * 0.5f; - f = d_gain * (1.0f / MATAGCTRIG); - f = MATAGCDECAY - MATAGCDECAY / (1 + f * f); - *_adapt_l_gain = (1 - f) * *_adapt_l_gain + f * l_gain; - *_adapt_r_gain = (1 - f) * *_adapt_r_gain + f * r_gain; - /* Matrix */ - l_agc = in[il] * PassiveLock(*_adapt_l_gain); - r_agc = in[ir] * PassiveLock(*_adapt_r_gain); - _cf[k] = (l_agc + r_agc) * (float)M_SQRT1_2; - if (decode_rear) - { - _lr[kr] = _rr[kr] = (l_agc - r_agc) * (float)M_SQRT1_2; - // Stereo rear channel is steered with the same AGC steering as - // the decoding matrix. Note this requires a fast updating AGC - // at the order of 20 ms (which is the case here). - _lr[kr] *= (_l_fwr + _l_fwr) / (1 + _l_fwr + _r_fwr); - _rr[kr] *= (_r_fwr + _r_fwr) / (1 + _l_fwr + _r_fwr); - } - - /*** AXIS NO. 2: (Lt + Rt, Lt - Rt) -> (L, R) ***/ - lpr = (in[il] + in[ir]) * (float)M_SQRT1_2; - lmr = (in[il] - in[ir]) * (float)M_SQRT1_2; - /* AGC adaption */ - d_gain = fabs(lmr_unlim_gain - *_adapt_lmr_gain); - f = d_gain * (1.0f / MATAGCTRIG); - f = MATAGCDECAY - MATAGCDECAY / (1 + f * f); - *_adapt_lpr_gain = (1 - f) * *_adapt_lpr_gain + f * lpr_gain; - *_adapt_lmr_gain = (1 - f) * *_adapt_lmr_gain + f * lmr_gain; - /* Matrix */ - lpr_agc = lpr * PassiveLock(*_adapt_lpr_gain); - lmr_agc = lmr * PassiveLock(*_adapt_lmr_gain); - _lf[k] = (lpr_agc + lmr_agc) * (float)M_SQRT1_2; - _rf[k] = (lpr_agc - lmr_agc) * (float)M_SQRT1_2; - - /*** CENTER FRONT CANCELLATION ***/ - // A heuristic approach exploits that Lt + Rt gain contains the - // information about Lt, Rt correlation. This effectively reshapes - // the front and rear "cones" to concentrate Lt + Rt to C and - // introduce Lt - Rt in L, R. - /* 0.67677 is the empirical lower bound for lpr_gain. */ - c_gain = 8 * (*_adapt_lpr_gain - 0.67677f); - c_gain = c_gain > 0 ? c_gain : 0; - // c_gain should not be too high, not even reaching full - // cancellation (~ 0.50 - 0.55 at current AGC implementation), or - // the center will sound too narrow. */ - c_gain = MATCOMPGAIN / (1 + c_gain * c_gain); - c_agc_cfk = c_gain * _cf[k]; - _lf[k] -= c_agc_cfk; - _rf[k] -= c_agc_cfk; - _cf[k] += c_agc_cfk + c_agc_cfk; + static const float M9_03DB = 0.3535533906f; + static const float MATAGCTRIG = 8.0f; /* (Fuzzy) AGC trigger */ + static const float MATAGCDECAY = 1.0f; /* AGC baseline decay rate (1/samp.) */ + static const float MATCOMPGAIN = + 0.37f; /* Cross talk compensation gain, 0.50 - 0.55 is full cancellation. */ + + const int kr = (k + olddelay) % _dlbuflen; + float l_gain = (_l_fwr + _r_fwr) / (1 + _l_fwr + _l_fwr); + float r_gain = (_l_fwr + _r_fwr) / (1 + _r_fwr + _r_fwr); + // The 2nd axis has strong gain fluctuations, and therefore require + // limits. The factor corresponds to the 1 / amplification of (Lt + // - Rt) when (Lt, Rt) is strongly correlated. (e.g. during + // dialogues). It should be bigger than -12 dB to prevent + // distortion. + float lmr_lim_fwr = _lmr_fwr > M9_03DB * _lpr_fwr ? _lmr_fwr : M9_03DB * _lpr_fwr; + float lpr_gain = (_lpr_fwr + lmr_lim_fwr) / (1 + _lpr_fwr + _lpr_fwr); + float lmr_gain = (_lpr_fwr + lmr_lim_fwr) / (1 + lmr_lim_fwr + lmr_lim_fwr); + float lmr_unlim_gain = (_lpr_fwr + _lmr_fwr) / (1 + _lmr_fwr + _lmr_fwr); + float lpr, lmr; + float l_agc, r_agc, lpr_agc, lmr_agc; + float f, d_gain, c_gain, c_agc_cfk; + + /*** AXIS NO. 1: (Lt, Rt) -> (C, Ls, Rs) ***/ + /* AGC adaption */ + d_gain = (fabs(l_gain - *_adapt_l_gain) + fabs(r_gain - *_adapt_r_gain)) * 0.5f; + f = d_gain * (1.0f / MATAGCTRIG); + f = MATAGCDECAY - MATAGCDECAY / (1 + f * f); + *_adapt_l_gain = (1 - f) * *_adapt_l_gain + f * l_gain; + *_adapt_r_gain = (1 - f) * *_adapt_r_gain + f * r_gain; + /* Matrix */ + l_agc = in[il] * PassiveLock(*_adapt_l_gain); + r_agc = in[ir] * PassiveLock(*_adapt_r_gain); + _cf[k] = (l_agc + r_agc) * (float)M_SQRT1_2; + if (decode_rear) + { + _lr[kr] = _rr[kr] = (l_agc - r_agc) * (float)M_SQRT1_2; + // Stereo rear channel is steered with the same AGC steering as + // the decoding matrix. Note this requires a fast updating AGC + // at the order of 20 ms (which is the case here). + _lr[kr] *= (_l_fwr + _l_fwr) / (1 + _l_fwr + _r_fwr); + _rr[kr] *= (_r_fwr + _r_fwr) / (1 + _l_fwr + _r_fwr); + } + + /*** AXIS NO. 2: (Lt + Rt, Lt - Rt) -> (L, R) ***/ + lpr = (in[il] + in[ir]) * (float)M_SQRT1_2; + lmr = (in[il] - in[ir]) * (float)M_SQRT1_2; + /* AGC adaption */ + d_gain = fabs(lmr_unlim_gain - *_adapt_lmr_gain); + f = d_gain * (1.0f / MATAGCTRIG); + f = MATAGCDECAY - MATAGCDECAY / (1 + f * f); + *_adapt_lpr_gain = (1 - f) * *_adapt_lpr_gain + f * lpr_gain; + *_adapt_lmr_gain = (1 - f) * *_adapt_lmr_gain + f * lmr_gain; + /* Matrix */ + lpr_agc = lpr * PassiveLock(*_adapt_lpr_gain); + lmr_agc = lmr * PassiveLock(*_adapt_lmr_gain); + _lf[k] = (lpr_agc + lmr_agc) * (float)M_SQRT1_2; + _rf[k] = (lpr_agc - lmr_agc) * (float)M_SQRT1_2; + + /*** CENTER FRONT CANCELLATION ***/ + // A heuristic approach exploits that Lt + Rt gain contains the + // information about Lt, Rt correlation. This effectively reshapes + // the front and rear "cones" to concentrate Lt + Rt to C and + // introduce Lt - Rt in L, R. + /* 0.67677 is the empirical lower bound for lpr_gain. */ + c_gain = 8 * (*_adapt_lpr_gain - 0.67677f); + c_gain = c_gain > 0 ? c_gain : 0; + // c_gain should not be too high, not even reaching full + // cancellation (~ 0.50 - 0.55 at current AGC implementation), or + // the center will sound too narrow. */ + c_gain = MATCOMPGAIN / (1 + c_gain * c_gain); + c_agc_cfk = c_gain * _cf[k]; + _lf[k] -= c_agc_cfk; + _rf[k] -= c_agc_cfk; + _cf[k] += c_agc_cfk + c_agc_cfk; } -void DPL2Decode(float *samples, int numsamples, float *out) +void DPL2Decode(float* samples, int numsamples, float* out) { - static const unsigned int FWRDURATION = 240; // FWR average duration (samples) - static const int cfg_delay = 0; - static const unsigned int fmt_freq = 48000; - static const unsigned int fmt_nchannels = 2; // input channels - - int cur = 0; - - if (olddelay != cfg_delay || oldfreq != fmt_freq) - { - Done(); - olddelay = cfg_delay; - oldfreq = fmt_freq; - dlbuflen = std::max(FWRDURATION, (fmt_freq * cfg_delay / 1000)); //+(len7000-1); - cyc_pos = dlbuflen - 1; - fwrbuf_l.resize(dlbuflen); - fwrbuf_r.resize(dlbuflen); - lf.resize(dlbuflen); - rf.resize(dlbuflen); - lr.resize(dlbuflen); - rr.resize(dlbuflen); - cf.resize(dlbuflen); - cr.resize(dlbuflen); - filter_coefs_lfe = CalculateCoefficients125HzLowpass(fmt_freq); - lfe_pos = 0; - memset(LFE_buf, 0, sizeof(LFE_buf)); - } - - float *in = samples; // Input audio data - float *end = in + numsamples * fmt_nchannels; // Loop end - - while (in < end) - { - const int k = cyc_pos; - - const int fwr_pos = (k + FWRDURATION) % dlbuflen; - /* Update the full wave rectified total amplitude */ - /* Input matrix decoder */ - l_fwr += fabs(in[0]) - fabs(fwrbuf_l[fwr_pos]); - r_fwr += fabs(in[1]) - fabs(fwrbuf_r[fwr_pos]); - lpr_fwr += fabs(in[0] + in[1]) - fabs(fwrbuf_l[fwr_pos] + fwrbuf_r[fwr_pos]); - lmr_fwr += fabs(in[0] - in[1]) - fabs(fwrbuf_l[fwr_pos] - fwrbuf_r[fwr_pos]); - - /* Matrix encoded 2 channel sources */ - fwrbuf_l[k] = in[0]; - fwrbuf_r[k] = in[1]; - MatrixDecode(in, k, 0, 1, true, dlbuflen, - l_fwr, r_fwr, - lpr_fwr, lmr_fwr, - &adapt_l_gain, &adapt_r_gain, - &adapt_lpr_gain, &adapt_lmr_gain, - &lf[0], &rf[0], &lr[0], &rr[0], &cf[0]); - - out[cur + 0] = lf[k]; - out[cur + 1] = rf[k]; - out[cur + 2] = cf[k]; - LFE_buf[lfe_pos] = (lf[k] + rf[k] + 2.0f * cf[k] + lr[k] + rr[k]) / 2.0f; - out[cur + 3] = FIRFilter(LFE_buf, lfe_pos, len125, len125, filter_coefs_lfe); - lfe_pos++; - if (lfe_pos == len125) - { - lfe_pos = 0; - } - out[cur + 4] = lr[k]; - out[cur + 5] = rr[k]; - // Next sample... - in += 2; - cur += 6; - cyc_pos--; - if (cyc_pos < 0) - { - cyc_pos += dlbuflen; - } - } + static const unsigned int FWRDURATION = 240; // FWR average duration (samples) + static const int cfg_delay = 0; + static const unsigned int fmt_freq = 48000; + static const unsigned int fmt_nchannels = 2; // input channels + + int cur = 0; + + if (olddelay != cfg_delay || oldfreq != fmt_freq) + { + Done(); + olddelay = cfg_delay; + oldfreq = fmt_freq; + dlbuflen = std::max(FWRDURATION, (fmt_freq * cfg_delay / 1000)); //+(len7000-1); + cyc_pos = dlbuflen - 1; + fwrbuf_l.resize(dlbuflen); + fwrbuf_r.resize(dlbuflen); + lf.resize(dlbuflen); + rf.resize(dlbuflen); + lr.resize(dlbuflen); + rr.resize(dlbuflen); + cf.resize(dlbuflen); + cr.resize(dlbuflen); + filter_coefs_lfe = CalculateCoefficients125HzLowpass(fmt_freq); + lfe_pos = 0; + memset(LFE_buf, 0, sizeof(LFE_buf)); + } + + float* in = samples; // Input audio data + float* end = in + numsamples * fmt_nchannels; // Loop end + + while (in < end) + { + const int k = cyc_pos; + + const int fwr_pos = (k + FWRDURATION) % dlbuflen; + /* Update the full wave rectified total amplitude */ + /* Input matrix decoder */ + l_fwr += fabs(in[0]) - fabs(fwrbuf_l[fwr_pos]); + r_fwr += fabs(in[1]) - fabs(fwrbuf_r[fwr_pos]); + lpr_fwr += fabs(in[0] + in[1]) - fabs(fwrbuf_l[fwr_pos] + fwrbuf_r[fwr_pos]); + lmr_fwr += fabs(in[0] - in[1]) - fabs(fwrbuf_l[fwr_pos] - fwrbuf_r[fwr_pos]); + + /* Matrix encoded 2 channel sources */ + fwrbuf_l[k] = in[0]; + fwrbuf_r[k] = in[1]; + MatrixDecode(in, k, 0, 1, true, dlbuflen, l_fwr, r_fwr, lpr_fwr, lmr_fwr, &adapt_l_gain, + &adapt_r_gain, &adapt_lpr_gain, &adapt_lmr_gain, &lf[0], &rf[0], &lr[0], &rr[0], + &cf[0]); + + out[cur + 0] = lf[k]; + out[cur + 1] = rf[k]; + out[cur + 2] = cf[k]; + LFE_buf[lfe_pos] = (lf[k] + rf[k] + 2.0f * cf[k] + lr[k] + rr[k]) / 2.0f; + out[cur + 3] = FIRFilter(LFE_buf, lfe_pos, len125, len125, filter_coefs_lfe); + lfe_pos++; + if (lfe_pos == len125) + { + lfe_pos = 0; + } + out[cur + 4] = lr[k]; + out[cur + 5] = rr[k]; + // Next sample... + in += 2; + cur += 6; + cyc_pos--; + if (cyc_pos < 0) + { + cyc_pos += dlbuflen; + } + } } void DPL2Reset() { - olddelay = -1; - oldfreq = 0; - filter_coefs_lfe = nullptr; + olddelay = -1; + oldfreq = 0; + filter_coefs_lfe = nullptr; } |
