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

SpectDirDipole.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 "SpectDirDipole.hh"
00028 
00029 
00030 void clSpectDirDipole::Calculate (int iScaling, stpSpectDirRN spRemoveNoise)
00031 {
00032     long lSensorCntr;
00033     long lSpectCntr;
00034     GDT fMagnitude;
00035     GDT fPhaseDiff;
00036     GDT fFrequency;
00037     GDT *fpLeftRN;
00038     GDT *fpRightRN;
00039     GCDT *spLeftSpect;
00040     GCDT *spRightSpect;
00041 
00042     for (lSensorCntr = 0l; lSensorCntr < 2l; lSensorCntr++)
00043     {
00044         DSP.Mul(fpProcBuf[lSensorCntr], fpWinFunc, lFFTSize);
00045         DSP.FFTi(spSpect[lSensorCntr], fpProcBuf[lSensorCntr]);
00046         if (spRemoveNoise->iType != SDD_BNER_NONE)
00047         {
00048             DSP.Magnitude(fpRNBuf[lSensorCntr], spSpect[lSensorCntr],
00049                 lSpectSize);
00050             switch (spRemoveNoise->iType)
00051             {
00052                 case SDD_BNER_TPSW:
00053                     BNER.TPSW(fpRNBuf[lSensorCntr], spRemoveNoise->fAlpha,
00054                         spRemoveNoise->lMeanLength, spRemoveNoise->lGapLength,
00055                         lSpectSize);
00056                     break;
00057                 case SDD_BNER_OTA:
00058                     BNER.OTA(fpRNBuf[lSensorCntr], spRemoveNoise->fAlpha,
00059                         spRemoveNoise->lMeanLength, lSpectSize);
00060                     break;
00061                 case SDD_BNER_DIFF:
00062                     BNER.Diff(fpRNBuf[lSensorCntr], spRemoveNoise->fAlpha,
00063                         lSpectSize);
00064                     break;
00065                 case SDD_BNER_IDIFF:
00066                     BNER.InvDiff(fpRNBuf[lSensorCntr], spRemoveNoise->fAlpha,
00067                         lSpectSize);
00068                     break;
00069             }
00070         }
00071     }
00072     fpLeftRN = fpRNBuf[0];
00073     fpRightRN = fpRNBuf[1];
00074     spLeftSpect = spSpect[0];
00075     spRightSpect = spSpect[1];
00076     for (lSpectCntr = lMinBin; lSpectCntr < lMaxBin; lSpectCntr++)
00077     {
00078         std::complex<GDT> cplxLeft(spLeftSpect[lSpectCntr].R, 
00079             spLeftSpect[lSpectCntr].I);
00080         std::complex<GDT> cplxRight(spRightSpect[lSpectCntr].R, 
00081             spRightSpect[lSpectCntr].I);
00082         std::complex<GDT> cplxCorr = cplxLeft * conj(cplxRight);
00083         if (spRemoveNoise->iType == SDD_BNER_NONE)
00084             //fMagnitude = norm(cplxLeft) + norm(cplxRight);
00085             fMagnitude = norm(cplxCorr);
00086         else
00087             fMagnitude = fpLeftRN[lSpectCntr] + fpRightRN[lSpectCntr];
00088         switch (iScaling)
00089         {
00090             case SDD_SCALE_LIN:
00091                 break;
00092             case SDD_SCALE_LOG:
00093             default:
00094                 fMagnitude = 1.0 / (fabs(20.0 * log10(fMagnitude)) + 1.0);
00095                 break;
00096         }
00097         fPhaseDiff = arg(cplxCorr);
00098         fFrequency = lSpectCntr * fFreqRes;
00099         SetDirection(fFrequency, fMagnitude, fPhaseDiff);
00100     }
00101 }
00102 
00103 
00104 clSpectDirDipole::clSpectDirDipole (GDT fSensorSpacing, GDT fSoundSpeed,
00105     double dSampleRate, long lFiltSize, int iFilterType, long lWindowSize, 
00106     long lDirCount, GDT fIntTimeReq, bool bEnableDebug)
00107 {
00108     long lSensorCntr;
00109     long lTwosPower;
00110     GDT fWindowTime;
00111     GDT *fpNullPtr = NULL;
00112     
00113     SetSensorSpacing(fSensorSpacing);
00114     SetSoundSpeed(fSoundSpeed);
00115     SetDirectionCount(lDirCount);
00116     bDebug = bEnableDebug;
00117     lDirectionCount = lDirCount;
00118     lFilterSize = lFiltSize;
00119     lFFTSize = lWindowSize;
00120     lTwosPower = (long)
00121         floor(log(dSampleRate / 2.0 / GetArrayFrequency()) / log(2.0));
00122     lDecimation = (long) pow(2.0, (double) lTwosPower);
00123     lSpectSize = lFFTSize / 2 + 1;
00124     fFreqRes =
00125         (GDT) dSampleRate / (GDT) lDecimation / (GDT) 2 / (GDT) lSpectSize;
00126     fWindowTime = (GDT) lFFTSize / ((GDT) dSampleRate / (GDT) lDecimation);
00127     if (fIntTimeReq <= 0)
00128     {
00129         fIntTime = fWindowTime;
00130         fOverlap = 0.0f;
00131     }
00132     else
00133     {
00134         fOverlap = 1.0f - fIntTimeReq / fWindowTime;
00135         lOldData = DSP.Round(lFFTSize * fOverlap);
00136         if (lOldData >= lFFTSize) lOldData = lFFTSize - 1l;
00137         lNewData = lFFTSize - lOldData;
00138         fIntTime = fWindowTime * ((GDT) lNewData / (GDT) lFFTSize);
00139     }
00140     lMaxBin = DSP.Round(GetArrayFrequency() / fFreqRes);
00141     WinFuncBuf.Size(lFFTSize * sizeof(GDT));
00142     fpWinFunc = WinFuncBuf;
00143     DSP.WinExactBlackman(fpWinFunc, lFFTSize);
00144     for (lSensorCntr = 0l; lSensorCntr < 2; lSensorCntr++)
00145     {
00146         ProcBuf[lSensorCntr].Size(lFFTSize * sizeof(GDT));
00147         fpProcBuf[lSensorCntr] = ProcBuf[lSensorCntr];
00148         PrevBuf[lSensorCntr].Size(lFFTSize * sizeof(GDT));
00149         fpPrevBuf[lSensorCntr] = PrevBuf[lSensorCntr];
00150         RNBuf[lSensorCntr].Size(lSpectSize * sizeof(GDT));
00151         fpRNBuf[lSensorCntr] = RNBuf[lSensorCntr];
00152         Decimator[lSensorCntr].Initialize(lDecimation, lFilterSize, fpNullPtr,
00153             0, iFilterType);
00154         SpectBuf[lSensorCntr].Size(sizeof(GCDT) * lSpectSize);
00155         spSpect[lSensorCntr] = SpectBuf[lSensorCntr];
00156     }
00157     DSP.FFTInitialize(lFFTSize, true);
00158     if (bDebug)
00159     {
00160         printf("Filter size %li, DFT size %li\n", lFilterSize, lFFTSize);
00161         switch (iFilterType)
00162         {
00163             case clRecDecimator::FILTER_TYPE_FFT:
00164                 puts("Using FFT decimation filter");
00165                 break;
00166             case clRecDecimator::FILTER_TYPE_FIR:
00167                 puts("Using FIR decimation filter");
00168                 break;
00169             case clRecDecimator::FILTER_TYPE_IIR:
00170                 puts("Using IIR decimation filter");
00171                 break;
00172         }
00173         if (lOldData > 0l)
00174         {
00175             printf("Overlap %.1f%%, %li/%li\n", fOverlap * 100.0f, 
00176                 lNewData, lOldData);
00177         }
00178         printf("Array frequency %.2f\n", GetArrayFrequency());
00179         printf("Decimation %li, Nyquist %.2f, resolution %.3f\n",
00180             lDecimation, ((GDT) dSampleRate / (GDT) lDecimation / (GDT) 2),
00181             fFreqRes);
00182     }
00183 }
00184 
00185 
00186 clSpectDirDipole::~clSpectDirDipole ()
00187 {
00188 }
00189 
00190 
00191 void clSpectDirDipole::PutData (const GDT *fpInputData, long lSampleCount,
00192     long lStartCh, long lChCount)
00193 {
00194     long lSensorCntr;
00195     long lChSampleCount;
00196     GDT *fpExtBuf;
00197     
00198     lChSampleCount = lSampleCount / lChCount;
00199     fpExtBuf = (GDT *) ExtBuf.Size(lChSampleCount * sizeof(GDT));
00200     for (lSensorCntr = 0l; lSensorCntr < 2l; lSensorCntr++)
00201     {
00202         DSP.Extract(fpExtBuf, fpInputData, lStartCh + lSensorCntr, lChCount,
00203             lSampleCount);
00204         Decimator[lSensorCntr].Put(fpExtBuf, lChSampleCount);
00205     }
00206 }
00207 
00208 
00209 bool clSpectDirDipole::GetResults (GDT *fpResults, GDT fLowFreqLimit,
00210     int iScaling, stpSpectDirRN spRemoveNoise)
00211 {
00212     long lSensorCntr;
00213 
00214     for (lSensorCntr = 0l; lSensorCntr < 2l; lSensorCntr++)
00215     {
00216         if (lOldData <= 0l)
00217         {
00218             if (!Decimator[lSensorCntr].Get(fpProcBuf[lSensorCntr], 
00219                 lFFTSize)) return false;
00220         }
00221         else
00222         {
00223             GDT *fpProc = fpProcBuf[lSensorCntr];
00224             GDT *fpOld = fpPrevBuf[lSensorCntr];
00225             
00226             if (Decimator[lSensorCntr].Get(&fpProc[lOldData], lNewData))
00227             {
00228                 DSP.Copy(fpProc, &fpOld[lNewData], lOldData);
00229                 DSP.Copy(fpOld, fpProc, lFFTSize);
00230             }
00231             else return false;
00232         }
00233     }
00234     lMinBin = DSP.Round(fLowFreqLimit / fFreqRes);
00235     if (lMinBin <= 0l) lMinBin = 1l;
00236     else if (lMinBin >= lMaxBin) lMinBin = lMaxBin - 1l;
00237     Calculate(iScaling, spRemoveNoise);
00238     GetDirections(fpResults);
00239     return true;
00240 }
00241 
00242 
00243 void clSpectDirDipole::ResetResults ()
00244 {
00245     ResetDirections();
00246 }
00247 

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