/* Design FIR filter using the Window method n filter length must be odd for HP and BS filters w buffer for the filter taps (must be n long) fc cutoff frequencies (1 for LP and HP, 2 for BP and BS) 0 < fc < 1 where 1 <=> Fs/2 flags window and filter type as defined in filter.h variables are ored together: i.e. LP|HAMMING will give a low pass filter designed using a hamming window 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) { 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; }
/** * Calculate MFCC and log energy for one frame. Perform spectral subtraction * if @a ssbuf is specified. * * @param w [i/o] MFCC calculation work area * @param mfcc [out] buffer to hold the resulting MFCC vector * @param para [in] configuration parameters */ void WMP_calc(MFCCWork *w, float *mfcc, Value *para) { float energy = 0.0; float c0 = 0.0; int p; if (para->zmeanframe) { ZMeanFrame(w->bf, para->framesize); } if (para->energy && para->raw_e) { /* calculate log raw energy */ energy = CalcLogRawE(w->bf, para->framesize); } /* pre-emphasize */ PreEmphasise(w->bf, para->framesize, para->preEmph); /* hamming window */ Hamming(w->bf, para->framesize, w); if (para->energy && ! para->raw_e) { /* calculate log energy */ energy = CalcLogRawE(w->bf, para->framesize); } /* filterbank */ MakeFBank(w->bf, w, para); /* 0'th cepstral parameter */ if (para->c0) c0 = CalcC0(w, para); /* MFCC */ MakeMFCC(mfcc, para, w); /* weight cepstrum */ WeightCepstrum(mfcc, para, w); /* set energy to mfcc */ p = para->mfcc_dim; if (para->c0) mfcc[p++] = c0; if (para->energy) mfcc[p++] = energy; }
bool IPLFFT::processInputData(IPLImage* image , int, bool) { // delete previous result delete _result; _result = NULL; int width = image->width(); int height = image->height(); int cWidth = IPLComplexImage::nextPowerOf2(width); int cHeight = IPLComplexImage::nextPowerOf2(height); int size = cHeight = cWidth = (cWidth>cHeight)? cWidth : cHeight; _result = new IPLComplexImage(cWidth, cHeight); // get properties int mode = getProcessPropertyInt("mode"); int progress = 0; int maxProgress = image->height() * image->getNumberOfPlanes(); // image center int dx = ( cWidth - width )/2; int dy = ( cHeight - height )/2; IPLImagePlane* plane = image->plane(0); for(int y=0; y<height; y++) { // progress notifyProgressEventHandler(100*progress++/maxProgress); for(int x=0; x<width; x++) { _result->c(x+dx, y+dy) = Complex(plane->p(x,y), 0.0); } } // windowing function switch(mode) { case 0: // rectangular break; case 1: // Hanning for( int y=0; y<size; y++ ) for( int x=0; x<size; x++ ) _result->c(x,y) *= Hanning(x, size) * Hanning(y, size); break; case 2: // Hamming for( int y=0; y<size; y++ ) for( int x=0; x<size; x++ ) _result->c(x,y) *= Hamming(x, size) * Hamming(y, size); break; case 3: // Blackman for( int y=0; y<size; y++ ) for( int x=0; x<size; x++ ) _result->c(x,y) *= Blackman(x, size) * Blackman(y, size); break; case 4: // Border only int border = size / 32; for( int y=0; y<border; y++ ) for( int x=0; x<size; x++ ) { double factor = (0.54 - 0.46 * cos( 2.0 * PI * y / border / 2.0 )); _result->c(x,y) *= factor; _result->c(x,size-y-1) *= factor; } for( int x=0; x<border; x++ ) for( int y=0; y<size; y++ ) { double factor = (0.54 - 0.46 * cos( 2.0 * PI * x / border / 2.0 )); _result->c(x,y) *= factor; _result->c(size-x-1,y) *= factor; } break; } _result->FFT(); return true; }
void CTimeSyncTrack::Init(CParameter& Parameter, int iNewSymbDelay) { iNumCarrier = Parameter.iNumCarrier; //ok? iScatPilFreqInt = Parameter.iScatPilFreqInt; //ok? iNumIntpFreqPil = Parameter.iNumIntpFreqPil; //ok? iDFTSize = Parameter.iFFTSizeN; //ok? /* Timing correction history */ iSymDelay = iNewSymbDelay; vecTiCorrHist.Init(iSymDelay, 0); /* History for new measurements (corrections) */ veciNewMeasHist.Init(iSymDelay - 1, 0); /* Init vector for received data at pilot positions */ veccPilots.Init(iNumIntpFreqPil); /* Vector for averaged power delay spread estimation */ //vecrAvPoDeSp.Init(iNumIntpFreqPil, (CReal) 0.0); vecrAvPoDeSp.Init(iNumIntpFreqPil, 0); /* Lambda for IIR filter for averaging the PDS */ rLamAvPDS = IIR1Lam(TICONST_PDS_EST_TISYNC, SOUNDCRD_SAMPLE_RATE / Parameter.iSymbolBlockSize); //changed CReal to CFReal here /* Vector for rotated result */ vecrAvPoDeSpRot.Init(iNumIntpFreqPil); /* Length of guard-interval with respect to FFT-size! */ rGuardSizeFFT = (CReal) iNumCarrier * Parameter.RatioTgTu.iEnum / Parameter.RatioTgTu.iDenom; /* Get the hamming window taps. The window is to reduce the leakage effect of a DFT transformation */ vecrHammingWindow.Init(iNumIntpFreqPil); vecrHammingWindow = Hamming(iNumIntpFreqPil); /* Weights for peak bound calculation, in Eq. (19), special values for robustness mode D! */ if (Parameter.GetWaveMode() == RM_ROBUSTNESS_MODE_D) { //rConst1 = pow(10, (_REAL) -TETA1_DIST_FROM_MAX_DB_RMD / 10); //rConst2 = pow(10, (_REAL) TETA2_DIST_FROM_MIN_DB_RMD / 10); rConst1 = pow(10, (FXP) -TETA1_DIST_FROM_MAX_DB_RMD / 10); rConst2 = pow(10, (FXP) TETA2_DIST_FROM_MIN_DB_RMD / 10); } else { //rConst1 = pow(10, (_REAL) -TETA1_DIST_FROM_MAX_DB / 10); //rConst2 = pow(10, (_REAL) TETA2_DIST_FROM_MIN_DB / 10); rConst1 = pow(10, (FXP) -TETA1_DIST_FROM_MAX_DB / 10); rConst2 = pow(10, (FXP) TETA2_DIST_FROM_MIN_DB / 10); } /* Define start point for rotation of detection vector for acausal taps. Per definition is this point somewhere in the region after the actual guard-interval window */ if ((int) rGuardSizeFFT > iNumIntpFreqPil) iStPoRot = iNumIntpFreqPil; else { /* "+ 1" because of "Matlab indices" used in ".Merge()" function */ iStPoRot = (int) (rGuardSizeFFT + Ceil((iNumIntpFreqPil - rGuardSizeFFT) / 2) + 1); } /* Init fractional part of timing correction to zero and fractional part of controlling */ rFracPartTiCor_fxp = 0; rFracPartContr_fxp = 0; /* Inits for the time synchronization tracking type */ SetTiSyncTracType(TypeTiSyncTrac); /* Init begin and end of PDS estimation with zero and the length of guard- interval respectively */ rEstPDSBegin_fxp = 0; rEstPDSEnd_fxp = rGuardSizeFFT; /* Init plans for FFT (faster processing of Fft and Ifft commands) */ FftPlan.Init(iNumIntpFreqPil); /* Inits for sample rate offset estimation ------------------------------ */ /* Calculate number of symbols for a given time span as defined for the length of the sample rate offset estimation history size */ iLenCorrectionHist = (int) ((_REAL) SOUNDCRD_SAMPLE_RATE * HIST_LEN_SAM_OFF_EST_TI_CORR / Parameter.iSymbolBlockSize); /* Init count for acquisition */ iResOffAcqCntMax = (int) ((_REAL) SOUNDCRD_SAMPLE_RATE * SAM_OFF_EST_TI_CORR_ACQ_LEN / Parameter.iSymbolBlockSize); /* Init sample rate offset estimation acquisition count */ iResOffsetAcquCnt = iResOffAcqCntMax; veciSRTiCorrHist.Init(iLenCorrectionHist, 0); /* Init with zeros */ iIntegTiCorrections = 0; /* Symbol block size converted in domain of estimated PDS */ rSymBloSiIRDomain = (CFReal) Parameter.iSymbolBlockSize * iNumCarrier / iDFTSize; /* changed from CReal to CFReal here */ /* Init variable for storing the old difference of maximum position */ iOldNonZeroDiff = 0; }
/** * Compute average spectrum of audio input. * This is used to estimate a noise spectrum from input samples. * * @param wave [in] input audio data sequence * @param wavelen [in] length of above * @param slen [out] length of returned buffer * @param w [i/o] MFCC calculation work area * @param para [in] parameter * * @return a newly allocated buffer that contains the calculated spectrum. */ float * new_SS_calculate(SP16 *wave, int wavelen, int *slen, MFCCWork *w, Value *para) { float *spec; int t, framenum, start, end, k, i; double x, y; /* allocate work area */ spec = (float *)mymalloc((w->fb.fftN + 1) * sizeof(float)); for(i=0; i<w->fb.fftN; i++) spec[i] = 0.0; /* Caluculate sum of noise power spectrum */ framenum = (int)((wavelen - para->framesize) / para->frameshift) + 1; if (framenum < 1) { jlog("Error: too short to get noise spectrum: length < 1 frame\n"); jlog("Error: no SS will be performed\n"); *slen = w->fb.fftN; return spec; } start = 1; end = 0; for (t = 0; t < framenum; t++) { if (end != 0) start = end - (para->framesize - para->frameshift) - 1; k = 1; for (i = start; i <= start + para->framesize; i++) { w->bf[k] = (float)wave[i-1]; k++; } end = i; if (para->zmeanframe) { ZMeanFrame(w->bf, para->framesize); } /* Pre-emphasis */ PreEmphasise(w->bf, para->framesize, para->preEmph); /* Hamming Window */ Hamming(w->bf, para->framesize, w); /* FFT Spectrum */ for (i = 1; i <= para->framesize; i++) { w->fb.Re[i-1] = w->bf[i]; w->fb.Im[i-1] = 0.0; } for (i = para->framesize + 1; i <= w->fb.fftN; i++) { w->fb.Re[i-1] = 0.0; w->fb.Im[i-1] = 0.0; } FFT(w->fb.Re, w->fb.Im, w->fb.n, w); /* Sum noise spectrum */ for(i = 1; i <= w->fb.fftN; i++) { x = w->fb.Re[i - 1]; y = w->fb.Im[i - 1]; spec[i - 1] += sqrt(x * x + y * y); } } /* Calculate average noise spectrum */ for(t=0; t<w->fb.fftN; t++) { spec[t] /= (float)framenum; } /* return the new spec[] */ *slen = w->fb.fftN; return(spec); }
void CFreqSyncAcq::InitInternal(CParameter& ReceiverParam) { int i; /* Needed for calculating offset in Hertz in case of synchronized input (for simulation) */ iFFTSize = ReceiverParam.iFFTSizeN; /* We using parameters from robustness mode B as pattern for the desired frequency pilot positions */ veciTableFreqPilots[0] = iTableFreqPilRobModB[0][0] * NUM_BLOCKS_4_FREQ_ACQU; veciTableFreqPilots[1] = iTableFreqPilRobModB[1][0] * NUM_BLOCKS_4_FREQ_ACQU; veciTableFreqPilots[2] = iTableFreqPilRobModB[2][0] * NUM_BLOCKS_4_FREQ_ACQU; /* Size of FFT */ iFrAcFFTSize = RMB_FFT_SIZE_N * NUM_BLOCKS_4_FREQ_ACQU; /* ------------------------------------------------------------------------- Set start- and endpoint of search window for DC carrier after the correlation with the known pilot structure */ /* Normalize the desired position and window size which are in Hertz */ const _REAL rNormDesPos = rCenterFreq / SOUNDCRD_SAMPLE_RATE * 2; const _REAL rNormHalfWinSize = rWinSize / SOUNDCRD_SAMPLE_RATE; /* Length of the half of the spectrum of real input signal (the other half is the same because of the real input signal). We have to consider the Nyquist frequency ("iFrAcFFTSize" is always even!) */ iHalfBuffer = iFrAcFFTSize / 2 + 1; /* Search window is smaller than haft-buffer size because of correlation with pilot positions */ iSearchWinSize = iHalfBuffer - veciTableFreqPilots[2]; /* Calculate actual indices of start and end of search window */ iStartDCSearch = (int) Floor((rNormDesPos - rNormHalfWinSize) * iHalfBuffer); iEndDCSearch = (int) Ceil((rNormDesPos + rNormHalfWinSize) * iHalfBuffer); /* Check range. If out of range -> correct */ if (!((iStartDCSearch > 0) && (iStartDCSearch < iSearchWinSize))) iStartDCSearch = 0; if (!((iEndDCSearch > 0) && (iEndDCSearch < iSearchWinSize))) iEndDCSearch = iSearchWinSize; /* Set bound for ratio between filtered signal to signal. Use a lower bound if the search window is smaller */ if (((FXP) iEndDCSearch - iStartDCSearch) / iHalfBuffer < (FXP) 0.042) rPeakBoundFiltToSig_fxp = PEAK_BOUND_FILT2SIGNAL_0_042_fxp; else rPeakBoundFiltToSig_fxp = PEAK_BOUND_FILT2SIGNAL_1_fxp; /* Init vectors and FFT-plan -------------------------------------------- */ /* Allocate memory for FFT-histories and init with zeros */ iHistBufSize = iFrAcFFTSize * NUM_BLOCKS_USED_FOR_AV; vecrFFTHistory_fxp.Init(iHistBufSize, (FXP) 0); vecrFFTInput_fxp.Init(iFrAcFFTSize); vecrSqMagFFTOut_fxp.Init(iHalfBuffer); /* Allocate memory for PSD after pilot correlation */ vecrPSDPilCor_fxp.Init(iHalfBuffer); /* Init vectors for filtering in frequency direction */ vecrFiltResLR_fxp.Init(iHalfBuffer); vecrFiltResRL_fxp.Init(iHalfBuffer); vecrFiltRes_fxp.Init(iHalfBuffer); /* Index memory for detected peaks (assume worst case with the size) */ veciPeakIndex_fxp.Init(iHalfBuffer); /* Init plans for FFT (faster processing of Fft and Ifft commands) */ FftPlan.Init(iFrAcFFTSize); /* Init Hamming window */ vecrHammingWin.Init(iFrAcFFTSize); vecrHammingWin = Hamming(iFrAcFFTSize); vecrHammingWin_fxp.Init(iFrAcFFTSize); for (i = 0; i < iFrAcFFTSize; i++) vecrHammingWin_fxp[i] = (FXP) vecrHammingWin[i]; /* Init moving average class for SqMag FFT results */ vvrPSDMovAv_fxp.InitVec(NUM_FFT_RES_AV_BLOCKS, iHalfBuffer); /* Frequency correction */ /* Start with phase null (arbitrary) */ cCurExp = (_REAL) 1.0; rInternIFNorm = (_REAL) ReceiverParam.iIndexDCFreq / iFFTSize; /* Init bandpass filter object */ BPFilter.Init(ReceiverParam.iSymbolBlockSize, VIRTUAL_INTERMED_FREQ, ReceiverParam.GetSpectrumOccup(), CDRMBandpassFilt::FT_RECEIVER); /* Define block-sizes for input (The output block size is set inside the processing routine, therefore only a maximum block size is set here) */ iInputBlockSize = ReceiverParam.iSymbolBlockSize; /* We have to consider that the next module can take up to two symbols per step. This can be satisfied be multiplying with "3". We also want to ship the whole FFT buffer after finishing the frequency acquisition so that these samples can be reused for synchronization and do not get lost */ iMaxOutputBlockSize = 3 * ReceiverParam.iSymbolBlockSize + iHistBufSize; }
void CChannelEstimation::InitInternal(CParameter& ReceiverParam) { /* Get parameters from global struct */ iScatPilTimeInt = ReceiverParam.iScatPilTimeInt; iScatPilFreqInt = ReceiverParam.iScatPilFreqInt; iNumIntpFreqPil = ReceiverParam.iNumIntpFreqPil; iNumCarrier = ReceiverParam.iNumCarrier; iFFTSizeN = ReceiverParam.iFFTSizeN; iNumSymPerFrame = ReceiverParam.iNumSymPerFrame; /* Length of guard-interval with respect to FFT-size! */ rGuardSizeFFT = (_REAL) iNumCarrier * ReceiverParam.RatioTgTu.iEnum / ReceiverParam.RatioTgTu.iDenom; /* If robustness mode D is active, get DC position. This position cannot be "0" since in mode D no 5 kHz mode is defined (see DRM-standard). Therefore we can also use this variable to get information whether mode D is active or not (by simply write: "if (iDCPos != 0)") */ iDCPos = 0; /* FFT must be longer than "iNumCarrier" because of zero padding effect ( not in robustness mode D! -> "iLongLenFreq = iNumCarrier") */ iLongLenFreq = iNumCarrier + iScatPilFreqInt - 1; /* Init vector for received data at pilot positions */ veccPilots.Init(iNumIntpFreqPil); /* Init vector for interpolated pilots */ veccIntPil.Init(iLongLenFreq); /* Init plans for FFT (faster processing of Fft and Ifft commands) */ FftPlanShort.Init(iNumIntpFreqPil); FftPlanLong.Init(iLongLenFreq); /* Choose time interpolation method and set pointer to correcponding object */ switch (TypeIntTime) { case TLINEAR: pTimeInt = &TimeLinear; break; case TWIENER: pTimeInt = &TimeWiener; break; } /* Init time interpolation interface and set delay for interpolation */ iLenHistBuff = pTimeInt->Init(ReceiverParam); /* Init time synchronization tracking unit */ TimeSyncTrack.Init(ReceiverParam, iLenHistBuff); /* Set channel estimation delay in global struct. This is needed for simulation */ ReceiverParam.iChanEstDelay = iLenHistBuff; /* Init window for DFT operation for frequency interpolation ------------ */ /* Init memory */ vecrDFTWindow.Init(iNumIntpFreqPil); vecrDFTwindowInv.Init(iNumCarrier); /* Set window coefficients */ switch (eDFTWindowingMethod) { case DFT_WIN_RECT: vecrDFTWindow = Ones(iNumIntpFreqPil); vecrDFTwindowInv = Ones(iNumCarrier); break; case DFT_WIN_HAMM: vecrDFTWindow = Hamming(iNumIntpFreqPil); vecrDFTwindowInv = (CReal) 1.0 / Hamming(iNumCarrier); break; } /* Set start index for zero padding in time domain for DFT method */ iStartZeroPadding = (int) rGuardSizeFFT; if (iStartZeroPadding > iNumIntpFreqPil) iStartZeroPadding = iNumIntpFreqPil; /* Allocate memory for channel estimation */ veccChanEst.Init(iNumCarrier); /* Allocate memory for history buffer (Matrix) and zero out */ matcHistory.Init(iLenHistBuff, iNumCarrier, _COMPLEX((_REAL) 0.0, (_REAL) 0.0)); /* After an initialization we do not put out data befor the number symbols of the channel estimation delay have been processed */ iInitCnt = iLenHistBuff - 1; /* Inits for SNR estimation (noise and signal averages) */ rSNREstimate = (_REAL) pow(10.0, INIT_VALUE_SNR_ESTIM_DB / 10); rSignalEst = (_REAL) 0.0; rNoiseEst = (_REAL) 0.0; /* For SNR estimation initialization */ iNumCellsSNRInit = iNumSymPerFrame * iNumCarrier; /* 1 DRM frame */ iSNREstInitCnt = iNumCellsSNRInit; bWasSNRInit = TRUE; /* Lambda for IIR filter */ rLamSNREstFast = IIR1Lam(TICONST_SNREST_FAST, (CReal) SOUNDCRD_SAMPLE_RATE / ReceiverParam.iSymbolBlockSize); rLamSNREstSlow = IIR1Lam(TICONST_SNREST_SLOW, (CReal) SOUNDCRD_SAMPLE_RATE / ReceiverParam.iSymbolBlockSize); /* SNR correction factor. We need this factor since we evalute the signal-to-noise ratio only on the pilots and these have a higher power as the other cells */ rSNRCorrectFact = ReceiverParam.rAvPilPowPerSym / ReceiverParam.rAvPowPerSymbol; /* Init delay spread length estimation (index) */ rLenPDSEst = (_REAL) 0.0; /* Init maximum estimated delay spread and offset in one DRM frame */ rMaxLenPDSInFra = (_REAL) 0.0; rMinOffsPDSInFra = rGuardSizeFFT; /* Inits for Wiener interpolation in frequency direction ---------------- */ /* Length of wiener filter */ switch (ReceiverParam.GetWaveMode()) { case RM_ROBUSTNESS_MODE_A: iLengthWiener = LEN_WIENER_FILT_FREQ_RMA; break; case RM_ROBUSTNESS_MODE_B: iLengthWiener = LEN_WIENER_FILT_FREQ_RMB; break; case RM_ROBUSTNESS_MODE_E: iLengthWiener = LEN_WIENER_FILT_FREQ_RME; break; } /* Inits for wiener filter ---------------------------------------------- */ /* In frequency direction we can use pilots from both sides for interpolation */ iPilOffset = iLengthWiener / 2; /* Allocate memory */ matcFiltFreq.Init(iNumCarrier, iLengthWiener); /* Pilot offset table */ veciPilOffTab.Init(iNumCarrier); /* Number of different wiener filters */ iNoWienerFilt = (iLengthWiener - 1) * iScatPilFreqInt + 1; /* Allocate temporary matlib vector for filter coefficients */ matcWienerFilter.Init(iNoWienerFilt, iLengthWiener); #ifdef UPD_WIENER_FREQ_EACH_DRM_FRAME /* Init Update counter for wiener filter update */ iUpCntWienFilt = iNumSymPerFrame; #endif /* Initial Wiener filter. Use initial SNR definition and assume that the PDS ranges from the beginning of the guard-intervall to the end */ UpdateWienerFiltCoef(pow(10.0, INIT_VALUE_SNR_WIEN_FREQ_DB / 10), (_REAL) ReceiverParam.RatioTgTu.iEnum / ReceiverParam.RatioTgTu.iDenom, (CReal) 0.0); /* Define block-sizes for input and output */ iInputBlockSize = iNumCarrier; iMaxOutputBlockSize = iNumCarrier; }