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

SpectDirLine.cc

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

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