CRealVector CNoiseReduction::OptimalFilter(const CComplexVector& veccSigFreq, const CRealVector& vecrSqMagSigFreq, const CRealVector& vecrNoisePSD) { CRealVector vecrReturn(iBlockLenLong); /* Calculate optimal filter coefficients in the frequency domain: G_opt = max(1 - S_nn(n) / S_xx(n), 0) */ veccOptFilt = Max(Zeros(iFreqBlLen), Ones(iFreqBlLen) - vecrNoisePSD / vecrSqMagSigFreq); /* Constrain the optimal filter in time domain to avoid aliasing */ vecrOptFiltTime = rifft(veccOptFilt, FftPlan); vecrOptFiltTime.Merge(vecrOptFiltTime(1, iBlockLen), Zeros(iBlockLen)); veccOptFilt = rfft(vecrOptFiltTime, FftPlan); /* Actual filtering in frequency domain */ vecrReturn = rifft(veccSigFreq * veccOptFilt, FftPlan); /* Cut out correct samples (to get from cyclic convolution to linear convolution) */ return vecrReturn(iBlockLen + 1, iBlockLenLong); }
CReal CTimeWiener::TimeOptimalFilter(CRealVector& vecrTaps, const int iTimeInt, const int iDiff, const CReal rNewSNR, const CReal rNewSigma, const CReal rTs, const int iLength) { int i; CReal rFactorArgExp; CReal rMMSE; int iCurPos; CRealVector vecrReturn(iLength); CRealVector vecrRpp(iLength); CRealVector vecrRhp(iLength); /* Factor for the argument of the exponetial function to generate the correlation function */ rFactorArgExp = (CReal) -2.0 * crPi * crPi * rTs * rTs * rNewSigma * rNewSigma; /* Doppler-spectrum for short-wave channel is Gaussian (Calculation of R_hp!) */ for (i = 0; i < iLength; i++) { iCurPos = i * iTimeInt + iDiff; vecrRhp[i] = exp(rFactorArgExp * iCurPos * iCurPos); } /* Doppler-spectrum for short-wave channel is Gaussian (Calculation of R_pp!) */ for (i = 0; i < iLength; i++) { iCurPos = i * iTimeInt; vecrRpp[i] = exp(rFactorArgExp * iCurPos * iCurPos); } /* Add SNR at first tap */ vecrRpp[0] += (CReal) 1.0 / rNewSNR; /* Call levinson algorithm to solve matrix system for optimal solution */ vecrTaps = Levinson(vecrRpp, vecrRhp); /* Calculate MMSE for the current wiener filter */ rMMSE = (CReal) 1.0 - Sum(vecrRhp * vecrTaps); return rMMSE; }