Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

SpectDirLine2.cc

Go to the documentation of this file.
00001 /*
00002 
00003     Spectrum based direction finding for dipole array
00004     Copyright (C) 2000-2002 Jussi Laako
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 */
00021 
00022 
00023 #include <cstdio>
00024 #include <cmath>
00025 #include <complex>
00026 
00027 #include "SpectDirLine2.hh"
00028 
00029 
00030 void clSpectDirLine2::Calculate (int iScaling, stpSpectDir2RN spRemoveNoise)
00031 {
00032     long lSensorCntr;
00033     long lSpectCntr;
00034     GDT fMagnitude;
00035     GDT fPhaseDiff;
00036     GDT fFrequency;
00037     GDT fScaleExp;
00038     GDT *fpLeftRN;
00039     GDT *fpRightRN;
00040     GCDT *spLeftSpect;
00041     GCDT *spRightSpect;
00042 
00043     for (lSensorCntr = 0l; lSensorCntr < lSensorCount; lSensorCntr++)
00044     {
00045         DSP.Mul(vfpProcBuf[lSensorCntr], fpWinFunc, lFFTSize);
00046         DSP.FFTi(vspSpect[lSensorCntr], vfpProcBuf[lSensorCntr]);
00047         if (spRemoveNoise->iType != SDL2_BNER_NONE)
00048         {
00049             DSP.Magnitude(vfpRNBuf[lSensorCntr], vspSpect[lSensorCntr],
00050                 lSpectSize);
00051             switch (spRemoveNoise->iType)
00052             {
00053                 case SDL2_BNER_TPSW:
00054                     BNER.TPSW(vfpRNBuf[lSensorCntr], spRemoveNoise->fAlpha,
00055                         spRemoveNoise->lMeanLength, spRemoveNoise->lGapLength,
00056                         lSpectSize);
00057                     break;
00058                 case SDL2_BNER_OTA:
00059                     BNER.OTA(vfpRNBuf[lSensorCntr], spRemoveNoise->fAlpha,
00060                         spRemoveNoise->lMeanLength, lSpectSize);
00061                     break;
00062                 case SDL2_BNER_DIFF:
00063                     BNER.Diff(vfpRNBuf[lSensorCntr], spRemoveNoise->fAlpha,
00064                         lSpectSize);
00065                     break;
00066                 case SDL2_BNER_IDIFF:
00067                     BNER.InvDiff(vfpRNBuf[lSensorCntr], spRemoveNoise->fAlpha,
00068                         lSpectSize);
00069                     break;
00070             }
00071         }
00072     }
00073     for (lSensorCntr = 0l; lSensorCntr < (lSensorCount - 1); lSensorCntr++)
00074     {
00075         fpLeftRN = vfpRNBuf[lSensorCntr];
00076         fpRightRN = vfpRNBuf[lSensorCntr + 1];
00077         spLeftSpect = vspSpect[lSensorCntr];
00078         spRightSpect = vspSpect[lSensorCntr + 1];
00079         for (lSpectCntr = lMinBin; lSpectCntr < lMaxBin; lSpectCntr++)
00080         {
00081             std::complex<GDT> cplxLeft(spLeftSpect[lSpectCntr].R, 
00082                 spLeftSpect[lSpectCntr].I);
00083             std::complex<GDT> cplxRight(spRightSpect[lSpectCntr].R, 
00084                 spRightSpect[lSpectCntr].I);
00085             std::complex<GDT> cplxCorr = cplxLeft * conj(cplxRight);
00086             if (spRemoveNoise->iType == SDL2_BNER_NONE)
00087                 //fMagnitude = norm(cplxLeft) + norm(cplxRight);
00088                 fMagnitude = norm(cplxCorr);
00089             else
00090                 fMagnitude = fpLeftRN[lSpectCntr] + fpRightRN[lSpectCntr];
00091             switch (iScaling)
00092             {
00093                 case SDL2_SCALE_LIN:
00094                     break;
00095                 case SDL2_SCALE_LOG:
00096                 default:
00097                     fMagnitude = 1.0 / (fabs(20.0 * log10(fMagnitude)) + 1.0);
00098                     break;
00099             }
00100             fPhaseDiff = arg(cplxCorr);
00101             fFrequency = lSpectCntr * fFreqRes;
00102             fpLevRes[lSpectCntr] += fMagnitude;
00103             fpDirRes[lSpectCntr] *= GetDirection(fFrequency, fPhaseDiff);
00104         }
00105     }
00106     fScaleExp = (GDT) 1.0 / (GDT) (lSensorCount - 1);
00107     for (lSpectCntr = lMinBin; lSpectCntr < lMaxBin; lSpectCntr++)
00108     {
00109         fpDirRes[lSpectCntr] = pow(fpDirRes[lSpectCntr], fScaleExp);
00110     }
00111 }
00112 
00113 
00114 clSpectDirLine2::clSpectDirLine2 (long lSensors, GDT fSensorSpacing, 
00115     GDT fSoundSpeed, double dSampleRate, long lFiltSize, int iFilterType, 
00116     long lWindowSize, GDT fIntTimeReq, bool bEnableDebug)
00117 {
00118     long lSensorCntr;
00119     long lTwosPower;
00120     GDT fWindowTime;
00121     GDT *fpNullPtr = NULL;
00122     
00123     lSensorCount = lSensors;
00124     SetSensorSpacing(fSensorSpacing);
00125     SetSoundSpeed(fSoundSpeed);
00126     bDebug = bEnableDebug;
00127     lFilterSize = lFiltSize;
00128     lFFTSize = lWindowSize;
00129     lTwosPower = (long)
00130         floor(log(dSampleRate / 2.0 / GetArrayFrequency()) / log(2.0));
00131     lDecimation = (long) pow(2.0, (double) lTwosPower);
00132     lSpectSize = lFFTSize / 2 + 1;
00133     fFreqRes =
00134         (GDT) dSampleRate / (GDT) lDecimation / (GDT) 2 / (GDT) lSpectSize;
00135     fWindowTime = (GDT) lFFTSize / ((GDT) dSampleRate / (GDT) lDecimation);
00136     if (fIntTimeReq <= 0)
00137     {
00138         fIntTime = fWindowTime;
00139         fOverlap = 0.0f;
00140     }
00141     else
00142     {
00143         fOverlap = 1.0f - fIntTimeReq / fWindowTime;
00144         lOldData = DSP.Round(lFFTSize * fOverlap);
00145         if (lOldData >= lFFTSize) lOldData = lFFTSize - 1l;
00146         lNewData = lFFTSize - lOldData;
00147         fIntTime = fWindowTime * ((GDT) lNewData / (GDT) lFFTSize);
00148     }
00149     lMaxBin = DSP.Round(GetArrayFrequency() / fFreqRes);
00150     fpWinFunc = (GDT *) WinFuncBuf.Size(lFFTSize * sizeof(GDT));
00151     DSP.WinExactBlackman(fpWinFunc, lFFTSize);
00152     fpLevRes = (GDT *) LevResBuf.Size(lSpectSize * sizeof(GDT));
00153     fpDirRes = (GDT *) DirResBuf.Size(lSpectSize * sizeof(GDT));
00154     vProcBuf.resize(lSensorCount);
00155     vPrevBuf.resize(lSensorCount);
00156     vRNBuf.resize(lSensorCount);
00157     vSpectBuf.resize(lSensorCount);
00158     for (lSensorCntr = 0l; lSensorCntr < lSensorCount; lSensorCntr++)
00159     {
00160         vProcBuf[lSensorCntr].Size(lFFTSize * sizeof(GDT));
00161         vfpProcBuf.push_back(vProcBuf[lSensorCntr]);
00162         vPrevBuf[lSensorCntr].Size(lFFTSize * sizeof(GDT));
00163         vfpPrevBuf.push_back(vPrevBuf[lSensorCntr]);
00164         vRNBuf[lSensorCntr].Size(lSpectSize * sizeof(GDT));
00165         vfpRNBuf.push_back(vRNBuf[lSensorCntr]);
00166         vSpectBuf[lSensorCntr].Size(sizeof(GCDT) * lSpectSize);
00167         vspSpect.push_back(vSpectBuf[lSensorCntr]);
00168         vDecimator.push_back(new clRecDecimator);
00169         vDecimator[lSensorCntr]->Initialize(lDecimation, lFilterSize, 
00170             fpNullPtr, 0, iFilterType);
00171     }
00172     DSP.FFTInitialize(lFFTSize, true);
00173     if (bDebug)
00174     {
00175         printf("Filter size %li, DFT size %li\n", lFilterSize, lFFTSize);
00176         switch (iFilterType)
00177         {
00178             case clRecDecimator::FILTER_TYPE_FFT:
00179                 puts("Using FFT decimation filter");
00180                 break;
00181             case clRecDecimator::FILTER_TYPE_FIR:
00182                 puts("Using FIR decimation filter");
00183                 break;
00184             case clRecDecimator::FILTER_TYPE_IIR:
00185                 puts("Using IIR decimation filter");
00186                 break;
00187         }
00188         if (lOldData > 0l)
00189         {
00190             printf("Overlap %.1f%%, %li/%li\n", fOverlap * 100.0f, 
00191                 lNewData, lOldData);
00192         }
00193         printf("Array frequency %.2f\n", GetArrayFrequency());
00194         printf("Decimation %li, Nyquist %.2f, resolution %.3f\n",
00195             lDecimation, ((GDT) dSampleRate / (GDT) lDecimation / (GDT) 2),
00196             fFreqRes);
00197     }
00198 }
00199 
00200 
00201 clSpectDirLine2::~clSpectDirLine2 ()
00202 {
00203     while (vDecimator.size() > 0)
00204     {
00205         delete vDecimator[vDecimator.size() - 1];
00206         vDecimator.pop_back();
00207     }
00208 }
00209 
00210 
00211 void clSpectDirLine2::PutData (const GDT *fpInputData, long lSampleCount, 
00212     long lStartCh, long lChCount)
00213 {
00214     long lSensorCntr;
00215     long lChSampleCount;
00216 
00217     lChSampleCount = lSampleCount / lChCount;
00218     fpExtBuf = (GDT *) ExtBuf.Size(lChSampleCount * sizeof(GDT));
00219     for (lSensorCntr = 0l; lSensorCntr < lSensorCount; lSensorCntr++)
00220     {
00221         DSP.Extract(fpExtBuf, fpInputData, lStartCh + lSensorCntr, lChCount,
00222             lSampleCount);
00223         vDecimator[lSensorCntr]->Put(fpExtBuf, lChSampleCount);
00224     }
00225 }
00226 
00227 
00228 bool clSpectDirLine2::GetResults (GDT *fpLevelResults, GDT *fpDirResults, 
00229     GDT fLowFreqLimit, int iScaling, stpSpectDir2RN spRemoveNoise)
00230 {
00231     long lSensorCntr;
00232 
00233     for (lSensorCntr = 0l; lSensorCntr < lSensorCount; lSensorCntr++)
00234     {
00235         if (lOldData <= 0l)
00236         {
00237             if (!vDecimator[lSensorCntr]->Get(vfpProcBuf[lSensorCntr], 
00238                 lFFTSize)) return false;
00239         }
00240         else
00241         {
00242             GDT *fpProc = vfpProcBuf[lSensorCntr];
00243             GDT *fpOld = vfpPrevBuf[lSensorCntr];
00244             
00245             if (vDecimator[lSensorCntr]->Get(&fpProc[lOldData], lNewData))
00246             {
00247                 DSP.Copy(fpProc, &fpOld[lNewData], lOldData);
00248                 DSP.Copy(fpOld, fpProc, lFFTSize);
00249             }
00250             else return false;
00251         }
00252     }
00253     lMinBin = DSP.Round(fLowFreqLimit / fFreqRes);
00254     if (lMinBin <= 0l) lMinBin = 1l;
00255     else if (lMinBin >= lMaxBin) lMinBin = lMaxBin - 1l;
00256     DSP.Zero(fpLevRes, lSpectSize);
00257     DSP.Zero(fpDirRes, lSpectSize);
00258     Calculate(iScaling, spRemoveNoise);
00259     if (fpLevelResults != NULL)
00260         DSP.Copy(fpLevelResults, fpLevRes, lSpectSize);
00261     if (fpDirResults != NULL)
00262         DSP.Copy(fpDirResults, fpDirRes, lSpectSize);
00263     return true;
00264 }

Generated on Sun Oct 26 19:11:22 2003 for HASAS by doxygen 1.3.3