📄 channelestimation.cpp
字号:
}
void CChannelEstimation::UpdateWienerFiltCoef(CReal rNewSNR, CReal rRatPDSLen,
CReal rRatPDSOffs)
{
int j, i;
int iDiff;
int iCurPil;
/* Calculate all possible wiener filters */
for (j = 0; j < iNumWienerFilt; j++)
{
matcWienerFilter[j] = FreqOptimalFilter(iScatPilFreqInt, j, rNewSNR,
rRatPDSLen, rRatPDSOffs, iLengthWiener);
}
#if 0
/* Save filter coefficients */
static FILE* pFile = fopen("test/wienerfreq.dat", "w");
for (j = 0; j < iNumWienerFilt; j++)
{
for (i = 0; i < iLengthWiener; i++)
{
fprintf(pFile, "%e %e\n", Real(matcWienerFilter[j][i]),
Imag(matcWienerFilter[j][i]));
}
}
fflush(pFile);
#endif
/* Set matrix with filter taps, one filter for each carrier */
for (j = 0; j < iNumCarrier; j++)
{
/* We define the current pilot position as the last pilot which the
index "j" has passed */
iCurPil = (int) (j / iScatPilFreqInt);
/* Consider special cases at the edges of the DRM spectrum */
if (iCurPil < iPilOffset)
{
/* Special case: left edge */
veciPilOffTab[j] = 0;
}
else if (iCurPil - iPilOffset > iNumIntpFreqPil - iLengthWiener)
{
/* Special case: right edge */
veciPilOffTab[j] = iNumIntpFreqPil - iLengthWiener;
}
else
{
/* In the middle */
veciPilOffTab[j] = iCurPil - iPilOffset;
}
/* Special case for robustness mode D, since the DC carrier is not used
as a pilot and therefore we use the same method for the edges of the
spectrum also in the middle of robustness mode D */
if (iDCPos != 0)
{
if ((iDCPos - iCurPil < iLengthWiener) && (iDCPos - iCurPil > 0))
{
/* Left side of DC carrier */
veciPilOffTab[j] = iDCPos - iLengthWiener;
}
if ((iCurPil - iDCPos < iLengthWiener) && (iCurPil - iDCPos > 0))
{
/* Right side of DC carrier */
veciPilOffTab[j] = iDCPos + 1;
}
}
/* Difference between the position of the first pilot (for filtering)
and the position of the observed carrier */
iDiff = j - veciPilOffTab[j] * iScatPilFreqInt;
/* Copy correct filter in matrix */
for (i = 0; i < iLengthWiener; i++)
matcFiltFreq[j][i] = matcWienerFilter[iDiff][i];
}
}
_REAL CChannelEstimation::CalAndBoundSNR(const _REAL rSignalEst,
const _REAL rNoiseEst)
{
_REAL rReturn;
/* "rNoiseEst" must not be zero */
if (rNoiseEst != (_REAL) 0.0)
rReturn = rSignalEst / rNoiseEst;
else
rReturn = (_REAL) 1.0;
/* Bound the SNR at 0 dB */
if (rReturn < (_REAL) 1.0)
rReturn = (_REAL) 1.0;
return rReturn;
}
_BOOLEAN CChannelEstimation::GetSNREstdB(_REAL& rSNREstRes) const
{
const _REAL rNomBWSNR = rSNREstimate * rSNRSysToNomBWCorrFact;
/* Bound the SNR at 0 dB */
if ((rNomBWSNR > (_REAL) 1.0) && (bSNRInitPhase == FALSE))
rSNREstRes = (_REAL) 10.0 * log10(rNomBWSNR);
else
rSNREstRes = (_REAL) 0.0;
if (bSNRInitPhase == TRUE)
return FALSE;
else
return TRUE;
}
_REAL CChannelEstimation::GetMSCMEREstdB()
{
/* Calculate final result (signal to noise ratio) and consider correction
factor for average signal energy */
const _REAL rCurMSCMEREst = rSNRSysToNomBWCorrFact *
CalAndBoundSNR(AV_DATA_CELLS_POWER, rNoiseEstMSCMER);
/* Bound the MCS MER at 0 dB */
if (rCurMSCMEREst > (_REAL) 1.0)
return (_REAL) 10.0 * log10(rCurMSCMEREst);
else
return (_REAL) 0.0;
}
_REAL CChannelEstimation::GetMSCWMEREstdB()
{
_REAL rAvNoiseEstMSC = (_REAL) 0.0;
_REAL rAvSigEstMSC = (_REAL) 0.0;
/* Lock resources */
Lock(); /* Lock start */
{
/* Average results from all carriers */
for (int i = 0; i < iNumCarrier; i++)
{
rAvNoiseEstMSC += vecrNoiseEstMSC[i];
rAvSigEstMSC += vecrSigEstMSC[i];
}
}
Unlock(); /* Lock end */
/* Calculate final result (signal to noise ratio) and consider correction
factor for average signal energy */
const _REAL rCurMSCWMEREst = rSNRSysToNomBWCorrFact *
CalAndBoundSNR(rAvSigEstMSC, rAvNoiseEstMSC);
/* Bound the MCS MER at 0 dB */
if (rCurMSCWMEREst > (_REAL) 1.0)
return (_REAL) 10.0 * log10(rCurMSCWMEREst);
else
return (_REAL) 0.0;
}
_BOOLEAN CChannelEstimation::GetSigma(_REAL& rSigma)
{
/* Doppler estimation is only implemented in the Wiener time interpolation
module */
if (TypeIntTime == TWIENER)
{
rSigma = TimeWiener.GetSigma();
return TRUE;
}
else
{
rSigma = (_REAL) 0.0;
return FALSE;
}
}
_REAL CChannelEstimation::GetDelay() const
{
/* Delay in ms */
return rLenPDSEst * iFFTSizeN /
(SOUNDCRD_SAMPLE_RATE * iNumIntpFreqPil * iScatPilFreqInt) * 1000;
}
_REAL CChannelEstimation::GetMinDelay()
{
/* Lock because of vector "vecrDelayHist" access */
Lock();
/* Return minimum delay in history */
_REAL rMinDelay = vecrDelayHist[0];
for (int i = 0; i < iLenDelayHist; i++)
{
if (rMinDelay > vecrDelayHist[i])
rMinDelay = vecrDelayHist[i];
}
Unlock();
/* Return delay in ms */
return rMinDelay * iFFTSizeN /
(SOUNDCRD_SAMPLE_RATE * iNumIntpFreqPil * iScatPilFreqInt) * 1000;
}
void CChannelEstimation::GetTransferFunction(CVector<_REAL>& vecrData,
CVector<_REAL>& vecrGrpDly,
CVector<_REAL>& vecrScale)
{
/* Init output vectors */
vecrData.Init(iNumCarrier, (_REAL) 0.0);
vecrGrpDly.Init(iNumCarrier, (_REAL) 0.0);
vecrScale.Init(iNumCarrier, (_REAL) 0.0);
/* Do copying of data only if vector is of non-zero length which means that
the module was already initialized */
if (iNumCarrier != 0)
{
_REAL rDiffPhase, rOldPhase;
/* Lock resources */
Lock();
/* Init constants for normalization */
const _REAL rTu = (CReal) iFFTSizeN / SOUNDCRD_SAMPLE_RATE;
const _REAL rNormData = (_REAL) _MAXSHORT * _MAXSHORT;
/* Copy data in output vector and set scale
(carrier index as x-scale) */
for (int i = 0; i < iNumCarrier; i++)
{
/* Transfer function */
const _REAL rNormSqMagChanEst = SqMag(veccChanEst[i]) / rNormData;
if (rNormSqMagChanEst > 0)
vecrData[i] = (_REAL) 10.0 * Log10(rNormSqMagChanEst);
else
vecrData[i] = RET_VAL_LOG_0;
/* Group delay */
if (i == 0)
{
/* At position 0 we cannot calculate a derivation -> use
the same value as position 0 */
rDiffPhase = Angle(veccChanEst[1]) - Angle(veccChanEst[0]);
}
else
rDiffPhase = Angle(veccChanEst[i]) - rOldPhase;
/* Take care of wrap around of angle() function */
if (rDiffPhase > WRAP_AROUND_BOUND_GRP_DLY)
rDiffPhase -= 2.0 * crPi;
if (rDiffPhase < -WRAP_AROUND_BOUND_GRP_DLY)
rDiffPhase += 2.0 * crPi;
/* Apply normalization */
vecrGrpDly[i] = rDiffPhase * rTu * 1000.0 /* ms */;
/* Store old phase */
rOldPhase = Angle(veccChanEst[i]);
/* Scale (carrier index) */
vecrScale[i] = i;
}
/* Release resources */
Unlock();
}
}
void CChannelEstimation::GetSNRProfile(CVector<_REAL>& vecrData,
CVector<_REAL>& vecrScale)
{
int i;
/* Init output vectors */
vecrData.Init(iNumCarrier, (_REAL) 0.0);
vecrScale.Init(iNumCarrier, (_REAL) 0.0);
/* Do copying of data only if vector is of non-zero length which means that
the module was already initialized */
if (iNumCarrier != 0)
{
/* Lock resources */
Lock();
/* We want to suppress the carriers on which no SNR measurement can be
performed (DC carrier, frequency pilots carriers) */
int iNewNumCar = 0;
for (i = 0; i < iNumCarrier; i++)
{
if (vecrSigEstMSC[i] != (_REAL) 0.0)
iNewNumCar++;
}
/* Init output vectors for new size */
vecrData.Init(iNewNumCar, (_REAL) 0.0);
vecrScale.Init(iNewNumCar, (_REAL) 0.0);
/* Copy data in output vector and set scale
(carrier index as x-scale) */
int iCurOutIndx = 0;
for (i = 0; i < iNumCarrier; i++)
{
/* Suppress carriers where no SNR measurement is possible */
if (vecrSigEstMSC[i] != (_REAL) 0.0)
{
/* Calculate final result (signal to noise ratio). Consider
correction factor for average signal energy */
const _REAL rNomBWSNR =
CalAndBoundSNR(vecrSigEstMSC[i], vecrNoiseEstMSC[i]) *
rSNRFACSigCorrFact * rSNRSysToNomBWCorrFact;
/* Bound the SNR at 0 dB */
if ((rNomBWSNR > (_REAL) 1.0) && (bSNRInitPhase == FALSE))
vecrData[iCurOutIndx] = (_REAL) 10.0 * Log10(rNomBWSNR);
else
vecrData[iCurOutIndx] = (_REAL) 0.0;
/* Scale (carrier index) */
vecrScale[iCurOutIndx] = i;
iCurOutIndx++;
}
}
/* Release resources */
Unlock();
}
}
void CChannelEstimation::GetAvPoDeSp(CVector<_REAL>& vecrData,
CVector<_REAL>& vecrScale,
_REAL& rLowerBound, _REAL& rHigherBound,
_REAL& rStartGuard, _REAL& rEndGuard,
_REAL& rPDSBegin, _REAL& rPDSEnd)
{
/* Lock resources */
Lock();
TimeSyncTrack.GetAvPoDeSp(vecrData, vecrScale, rLowerBound,
rHigherBound, rStartGuard, rEndGuard, rPDSBegin, rPDSEnd);
/* Release resources */
Unlock();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -