00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdio.h>
00024 #include <signal.h>
00025 #include <unistd.h>
00026 #include <math.h>
00027 #include <float.h>
00028 #include <limits.h>
00029 #include <sys/time.h>
00030
00031 #include <Alloc.hh>
00032
00033 #include "Spectrum.hh"
00034
00035
00036 static bool bDebug;
00037 static bool bDaemon;
00038 clSpectrum *Spectrum;
00039
00040 #define SPECT_NWIN 13
00041 static const char *cpaWindowFuncs[] = {
00042 "Rectangle",
00043 "Bartlett",
00044 "Blackman",
00045 "Blackman-Harris",
00046 "Cosine tapered",
00047 "Exponential",
00048 "Flat-top",
00049 "Generic cosine",
00050 "Hamming",
00051 "Hanning",
00052 "Kaiser",
00053 "Kaiser-Bessel",
00054 "Tukey" };
00055
00056
00057 void SigHandler (int iSigNum)
00058 {
00059 switch (iSigNum)
00060 {
00061 case SIGSEGV:
00062 if (bDebug)
00063 {
00064 printf("Oops, received SIGSEGV, crash...\n");
00065 abort();
00066 }
00067 else exit(-1);
00068 break;
00069 }
00070 }
00071
00072
00073 int main (int argc, char *argv[])
00074 {
00075 int iRetVal;
00076
00077 bDebug = false;
00078 bDaemon = false;
00079 signal(SIGPIPE, SIG_IGN);
00080 signal(SIGFPE, SIG_IGN);
00081 signal(SIGSEGV, SigHandler);
00082 if (argc >= 2)
00083 {
00084 if (strcmp(argv[1], "--debug") == 0)
00085 {
00086 bDebug = true;
00087 }
00088 if (strcmp(argv[1], "-D") == 0)
00089 {
00090 bDaemon = true;
00091 }
00092 }
00093 if (bDebug) printf("spectrum: Started\n");
00094 Spectrum = new clSpectrum(3, 4);
00095 iRetVal = Spectrum->Main();
00096 delete Spectrum;
00097 if (bDebug) printf("spectrum: Exit = %i\n", iRetVal);
00098 return iRetVal;
00099 }
00100
00101
00102 bool clSpectrum::GetCfg ()
00103 {
00104 Cfg.SetFileName(SD_CFGFILE);
00105 if (!Cfg.GetStr("LocalSocket", cpStreamSocket)) return false;
00106 Cfg.SetFileName(SPECT_CFGFILE);
00107 if (!Cfg.GetInt("FilterSize", &lFilterSize))
00108 lFilterSize = SPECT_DEF_FILTSIZE;
00109 if (!Cfg.GetInt("FilterType", &iFilterType))
00110 iFilterType = clRecDecimator::FILTER_TYPE_FFT;
00111 return true;
00112 }
00113
00114
00115 bool clSpectrum::GetRq ()
00116 {
00117 char cpMsgBuf[GLOBAL_HEADER_LEN];
00118
00119 if (!SOpRequest.ReadSelect(SPECT_REQ_TIMEOUT)) return false;
00120 if (SOpRequest.ReadN(cpMsgBuf, GLOBAL_HEADER_LEN) != GLOBAL_HEADER_LEN)
00121 return false;
00122 Msg.GetRequest(cpMsgBuf, &sReq);
00123 return true;
00124 }
00125
00126
00127 bool clSpectrum::ConnectStream ()
00128 {
00129 int iSockH;
00130 stRawDataReq sStreamReq;
00131
00132 iSockH = SClient.Connect(cpStreamSocket);
00133 if (iSockH < 0) return false;
00134 SOpData.SetHandle(iSockH);
00135 if (!SOpData.ReadSelect(SPECT_RAW1ST_TIMEOUT)) return false;
00136 if (SOpData.ReadN(&sRawHdr, sizeof(sRawHdr)) < (int) sizeof(sRawHdr))
00137 return false;
00138 sStreamReq.iChannel = sReq.iChannel;
00139 if (SOpData.WriteN(&sStreamReq, sizeof(sStreamReq)) <
00140 (int) sizeof(sStreamReq)) return false;
00141 return true;
00142 }
00143
00144
00145 bool clSpectrum::Init ()
00146 {
00147 GDT *fpNullPtr = NULL;
00148
00149 lInDataCount = abs(lFilterSize) / 2;
00150 iInDataSize = lInDataCount * sizeof(GDT);
00151 InData.Size(iInDataSize);
00152 if (bDebug)
00153 {
00154 printf("spectrum: Filter size %li\n", lFilterSize);
00155 switch (iFilterType)
00156 {
00157 case clRecDecimator::FILTER_TYPE_FFT:
00158 puts("spectrum: Using FFT decimation filter");
00159 break;
00160 case clRecDecimator::FILTER_TYPE_FIR:
00161 puts("spectrum: Using FIR decimation filter");
00162 break;
00163 case clRecDecimator::FILTER_TYPE_IIR:
00164 puts("spectrum: Using IIR decimation filter");
00165 break;
00166 }
00167 }
00168 CreateFilter();
00169 switch (sReq.iType)
00170 {
00171 case MSG_SPECT_TYPE_FFT:
00172 if (bDebug) printf("spectrum: STFT\n");
00173 lSpectPoints = sReq.lLength;
00174 lSpectLen = lSpectPoints / 2 + 1;
00175 FFT.FFTInitialize(lSpectPoints, true);
00176 break;
00177 case MSG_SPECT_TYPE_MRFFT:
00178 printf("spectrum: Multiresolution-STFT not implemented yet\n");
00179 break;
00180 case MSG_SPECT_TYPE_GABOR:
00181 printf("spectrum: Gabor transform not implemented yet\n");
00182 break;
00183 case MSG_SPECT_TYPE_WVD:
00184 if (bDebug) printf("spectrum: Wigner-Ville Distribution\n");
00185 lSpectPoints = sReq.lLength;
00186 lSpectLen = lSpectPoints / 2 + 1;
00187 FFT.FFTInitialize(lSpectPoints, true);
00188 WVDDec.Initialize(2, -128, (GDT *) NULL, (GDT) 0.25,
00189 clRecDecimator::FILTER_TYPE_FIR);
00190 sReq.iOverlap = 50;
00191 break;
00192 case MSG_SPECT_TYPE_HANKEL:
00193 if (bDebug) printf("spectrum: Hankel transform\n");
00194 lSpectPoints = sReq.lLength / 2 + 1;
00195 lSpectLen = lSpectPoints;
00196 Hankel.Initialize(sReq.lLength, fpNullPtr);
00197 break;
00198 case MSG_SPECT_TYPE_AUTOCORR:
00199 if (bDebug) printf("spectrum: Autocorrelation\n");
00200 lSpectPoints = sReq.lLength;
00201 lSpectLen = lSpectPoints / 2;
00202 FFT.FFTInitialize(lSpectPoints, true);
00203 break;
00204 case MSG_SPECT_TYPE_CEPSTRUM:
00205 if (bDebug) printf("spectrum: Cepstrum\n");
00206 lSpectPoints = sReq.lLength;
00207 lSpectLen = lSpectPoints / 2;
00208 FFT.FFTInitialize(lSpectPoints, true);
00209 break;
00210 default:
00211 printf("spectrum: unknown transform requested\n");
00212 }
00213 lResSize = GLOBAL_HEADER_LEN + lSpectLen * sizeof(GDT);
00214 SpectIn.Size(lSpectPoints * sizeof(GDT));
00215 SpectOut.Size(lSpectLen * sizeof(GDT));
00216 ResMsg.Size(lResSize);
00217 lOldDataCount = (long) (lSpectPoints * (sReq.iOverlap / 100.0) + 0.5);
00218 lNewDataCount = lSpectPoints - lOldDataCount;
00219 if (lNewDataCount < 1)
00220 {
00221 lNewDataCount = 1;
00222 lOldDataCount = lSpectPoints - lNewDataCount;
00223 }
00224 if (bDebug)
00225 {
00226 printf("spectrum: %li samples old, %li samples new data\n",
00227 lOldDataCount, lNewDataCount);
00228 }
00229 Window.Size(lSpectPoints * sizeof(GDT));
00230 switch (sReq.iWindow)
00231 {
00232 case MSG_SPECT_WND_RECT:
00233 DSP.Set((GDT *) Window, (GDT) 1, lSpectPoints);
00234 break;
00235 case MSG_SPECT_WND_BARTLETT:
00236 DSP.WinBartlett((GDT *) Window, lSpectPoints);
00237 break;
00238 case MSG_SPECT_WND_BLACKMAN:
00239 DSP.WinExactBlackman((GDT *) Window, lSpectPoints);
00240 break;
00241 case MSG_SPECT_WND_BM_HAR:
00242 DSP.WinBlackmanHarris((GDT *) Window, lSpectPoints);
00243 break;
00244 case MSG_SPECT_WND_COS_TAPER:
00245 DSP.WinCosTapered((GDT *) Window, lSpectPoints);
00246 break;
00247 case MSG_SPECT_WND_EXP:
00248 DSP.WinExp((GDT *) Window, (GDT) sReq.fWinParam, lSpectPoints);
00249 break;
00250 case MSG_SPECT_WND_FLATTOP:
00251 DSP.WinFlatTop((GDT *) Window, lSpectPoints);
00252 break;
00253 case MSG_SPECT_WND_GEN_COS:
00254 DSP.Set((GDT *) Window, (GDT) 1, lSpectPoints);
00255 break;
00256 case MSG_SPECT_WND_HAMMING:
00257 DSP.WinHamming((GDT *) Window, lSpectPoints);
00258 break;
00259 case MSG_SPECT_WND_HANNING:
00260 DSP.WinHanning((GDT *) Window, lSpectPoints);
00261 break;
00262 case MSG_SPECT_WND_KAISER:
00263 DSP.WinKaiser((GDT *) Window, (GDT) sReq.fWinParam, lSpectPoints);
00264 break;
00265 case MSG_SPECT_WND_KAI_BES:
00266 DSP.WinKaiserBessel((GDT *) Window, (GDT) sReq.fWinParam,
00267 lSpectPoints);
00268 break;
00269 case MSG_SPECT_WND_TUKEY:
00270 DSP.WinTukey((GDT *) Window, lSpectPoints);
00271 break;
00272 default:
00273 printf("spectrum: unknown window function requested\n");
00274 }
00275 if (sReq.iWindow < SPECT_NWIN && bDebug)
00276 printf("spectrum: %s window\n", cpaWindowFuncs[sReq.iWindow]);
00277 return true;
00278 }
00279
00280
00281 void clSpectrum::CreateFilter ()
00282 {
00283 int iBandNo;
00284 long lTwosPower;
00285 float fNyquist;
00286 float fBandWidth;
00287 GDT fBandCenter;
00288 GDT *fpNullPtr = NULL;
00289
00290 fNyquist = (float) sRawHdr.dSampleRate / 2.0f;
00291 if (sReq.iLowFreq == sReq.iHighFreq)
00292 {
00293 sReq.iLowFreq = 0;
00294 sReq.iHighFreq = (int) fNyquist;
00295 }
00296 fBandWidth = sReq.iHighFreq - sReq.iLowFreq;
00297 lTwosPower = (long) (log(fNyquist / fBandWidth) / log(2.0) + 0.5);
00298 lDecimation = (long) pow(2.0, lTwosPower);
00299 fBandWidth = fNyquist / lDecimation;
00300 iBandNo = (int) (sReq.iHighFreq / fBandWidth + 0.5f);
00301 if ((fBandWidth * iBandNo) < (sReq.iLowFreq + fBandWidth / 2.0f))
00302 iBandNo++;
00303 fHighCorner = fBandWidth * iBandNo;
00304 fLowCorner = fHighCorner - fBandWidth;
00305 fBandCenter = (fLowCorner + fBandWidth / 2.0f) / fNyquist;
00306 bReverseOrder = ((iBandNo - 1) % 2 == 0) ? false : true;
00307 if (bDebug)
00308 {
00309 printf("spectrum: lower corner %.2f higher corner %.2f\n",
00310 fLowCorner, fHighCorner);
00311 printf("spectrum: decimation %li, %s order\n",
00312 lDecimation,
00313 (bReverseOrder) ? "reverse" : "normal");
00314 printf("spectrum: normalized center %f\n", fBandCenter);
00315 }
00316 Decimator.Initialize(lDecimation, lFilterSize, fpNullPtr, fBandCenter,
00317 iFilterType);
00318 }
00319
00320
00321 void clSpectrum::ProcessLoop ()
00322 {
00323 long lSpectCntr;
00324 long lSpectMax;
00325 GDT fScale;
00326 GDT fLogScale;
00327 GDT fPeakLevel;
00328 GDT *fpWindow = Window;
00329 GDT *fpSpectIn = SpectIn;
00330 GDT *fpSpectOut = SpectOut;
00331 GDT *fpOldData;
00332 GDT *fpNewData;
00333 GDT *fpRevBuf;
00334 GDT *fpTemp;
00335 GCDT *spCplxSpect;
00336 clDSPAlloc OldData;
00337 clDSPAlloc NewData;
00338 clDSPAlloc RevBuf;
00339 clDSPAlloc Temp;
00340 clDSPAlloc CplxSpect;
00341
00342 fpOldData = (GDT *) OldData.Size(lOldDataCount * sizeof(GDT));
00343 DSP.Zero(fpOldData, lOldDataCount);
00344 fpNewData = (GDT *) NewData.Size(lNewDataCount * sizeof(GDT));
00345 fpRevBuf = (GDT *) RevBuf.Size(lSpectLen * sizeof(GDT));
00346 fpTemp = (GDT *) Temp.Size(lSpectPoints * sizeof(GDT));
00347 DSP.Zero(fpTemp, lSpectPoints);
00348 spCplxSpect = (GCDT *) CplxSpect.Size(lSpectPoints * sizeof(GCDT));
00349 DSP.Zero(spCplxSpect, lSpectPoints);
00350 fLogScale = 1.0f / sReq.fDynRange;
00351 while (bRun)
00352 {
00353 if (!GetData())
00354 {
00355 Stop();
00356 break;
00357 }
00358 while (PullData(fpNewData, lNewDataCount) && bRun)
00359 {
00360 DSP.Copy(fpSpectIn, fpOldData, lOldDataCount);
00361 DSP.Copy(&fpSpectIn[lOldDataCount], fpNewData, lNewDataCount);
00362 DSP.Copy(fpOldData, &fpSpectIn[lNewDataCount], lOldDataCount);
00363 fPeakLevel = DSP.PeakLevel(fpSpectIn, lSpectPoints);
00364 switch (sReq.iType)
00365 {
00366 case MSG_SPECT_TYPE_FFT:
00367 DSP.Mul(fpSpectIn, fpWindow, lSpectPoints);
00368 FFT.FFTi(spCplxSpect, fpSpectIn);
00369 DSP.Magnitude(fpSpectOut, spCplxSpect, lSpectLen);
00370 break;
00371 case MSG_SPECT_TYPE_MRFFT:
00372 break;
00373 case MSG_SPECT_TYPE_GABOR:
00374 break;
00375 case MSG_SPECT_TYPE_WVD:
00376
00377
00378
00379
00380
00381 FFT.FFTi(spCplxSpect, fpSpectIn);
00382 DSP.MulC(spCplxSpect, spCplxSpect,
00383 lSpectPoints / 2 + 1);
00384 DSP.Magnitude(fpSpectOut, spCplxSpect, lSpectLen);
00385 DSP.Mul(fpSpectOut, (GDT) 2, lSpectLen);
00386 break;
00387 case MSG_SPECT_TYPE_HANKEL:
00388 DSP.Mul(fpSpectIn, fpWindow, lSpectPoints);
00389 Hankel.Process0(fpSpectOut, fpSpectIn);
00390
00391 break;
00392 case MSG_SPECT_TYPE_AUTOCORR:
00393 DSP.Mul(fpSpectIn, fpWindow, lSpectPoints);
00394 FFT.FFTi(spCplxSpect, fpSpectIn);
00395 DSP.MulC(spCplxSpect, spCplxSpect,
00396 lSpectPoints / 2 + 1);
00397 FFT.IFFTo(fpTemp, spCplxSpect);
00398 DSP.Copy(fpSpectOut, fpTemp, lSpectLen);
00399 break;
00400 case MSG_SPECT_TYPE_CEPSTRUM:
00401 DSP.Mul(fpSpectIn, fpWindow, lSpectPoints);
00402 FFT.FFTi(spCplxSpect, fpSpectIn);
00403 lSpectMax = lSpectPoints / 2 + 1;
00404 for (lSpectCntr = 0;
00405 lSpectCntr < lSpectMax;
00406 lSpectCntr++)
00407 {
00408 #ifndef HAVE_GLIBC
00409 spCplxSpect[lSpectCntr].R = log10(sqrt(
00410 spCplxSpect[lSpectCntr].R *
00411 spCplxSpect[lSpectCntr].R +
00412 spCplxSpect[lSpectCntr].I *
00413 spCplxSpect[lSpectCntr].I));
00414 #else
00415 spCplxSpect[lSpectCntr].R = log10(hypot(
00416 spCplxSpect[lSpectCntr].R,
00417 spCplxSpect[lSpectCntr].I));
00418 #endif
00419 spCplxSpect[lSpectCntr].I = 0;
00420 }
00421 FFT.IFFTo(fpTemp, spCplxSpect);
00422 fpTemp[0] = 0;
00423 fpTemp[1] = 0;
00424 fScale = (GDT) 2 / (GDT) lSpectPoints;
00425 DSP.Mul(fpSpectOut, fpTemp, fScale, lSpectLen);
00426 break;
00427 }
00428 if (!sReq.bLinear)
00429 {
00430 if (!sReq.bNormalize)
00431 {
00432 for (lSpectCntr = 0;
00433 lSpectCntr < lSpectLen;
00434 lSpectCntr++)
00435 {
00436 fpSpectOut[lSpectCntr] = (GDT)
00437 (20.0 * log10(fpSpectOut[lSpectCntr]) +
00438 sReq.fDynRange) * fLogScale;
00439 }
00440 }
00441 else
00442 {
00443 for (lSpectCntr = 0;
00444 lSpectCntr < lSpectLen;
00445 lSpectCntr++)
00446 {
00447 fpSpectOut[lSpectCntr] = (GDT)
00448 (20.0 * log10(fpSpectOut[lSpectCntr]));
00449 }
00450 }
00451 }
00452 if (bReverseOrder)
00453 {
00454 DSP.Copy(fpRevBuf, fpSpectOut, lSpectLen);
00455 DSP.Reverse(fpSpectOut, fpRevBuf, lSpectLen);
00456 }
00457 if (sReq.bNormalize)
00458 {
00459 DSP.Scale01(fpSpectOut, lSpectLen);
00460 }
00461 if (sReq.fSlope != 0.0f)
00462 {
00463 double dSlopeMul = pow(10.0, sReq.fSlope / 20.0);
00464 double dNyquist = (double) sRawHdr.dSampleRate /
00465 (double) lDecimation / 2.0;
00466 double dFreqRes = dNyquist / (double) lSpectLen;
00467 for (long lFreqBinCntr = 1;
00468 lFreqBinCntr < lSpectLen;
00469 lFreqBinCntr++)
00470 {
00471 double dBinFreq = dFreqRes * lFreqBinCntr;
00472 fpSpectOut[lFreqBinCntr] *= (GDT)
00473 (pow(dSlopeMul, log(dBinFreq) / log(2.0)));
00474 }
00475 }
00476 if (sReq.fGain != 0.0f)
00477 {
00478 GDT fGainMul = (GDT) pow(10.0, sReq.fGain / 20.0);
00479 DSP.Mul(fpSpectOut, fGainMul, lSpectLen);
00480 }
00481 switch (sReq.iRemoveNoise)
00482 {
00483 case MSG_SPECT_BNER_NONE:
00484 break;
00485 case MSG_SPECT_BNER_TPSW:
00486 RN.TPSW(fpSpectOut, sReq.fAlpha, sReq.lMeanLength,
00487 sReq.lGapLength, lSpectLen);
00488 break;
00489 case MSG_SPECT_BNER_OTA:
00490 RN.OTA(fpSpectOut, sReq.fAlpha, sReq.lMeanLength,
00491 lSpectLen);
00492 break;
00493 case MSG_SPECT_BNER_DIFF:
00494 RN.Diff(fpSpectOut, sReq.fAlpha, lSpectLen);
00495 break;
00496 case MSG_SPECT_BNER_IDIFF:
00497 RN.InvDiff(fpSpectOut, sReq.fAlpha, lSpectLen);
00498 break;
00499 default:
00500
00501 break;
00502 }
00503 gettimeofday(&sResHdr.sTimeStamp, NULL);
00504 sResHdr.iChannel = sReq.iChannel;
00505 sResHdr.lLength = lSpectLen;
00506 sResHdr.iLowFreq = (int) (fLowCorner + 0.5f);
00507 sResHdr.iHighFreq = (int) (fHighCorner + 0.5f);
00508 sResHdr.iSampleRate = (int) (sRawHdr.dSampleRate + 0.5);
00509 sResHdr.bLinear = sReq.bLinear;
00510 sResHdr.fPeakLevel = fPeakLevel;
00511 if (lDecimation > 0)
00512 {
00513 sResHdr.fLineTime =
00514 (float) lNewDataCount /
00515 ((float) sRawHdr.dSampleRate / (float) lDecimation);
00516 }
00517 else
00518 {
00519 sResHdr.fLineTime = (float) lNewDataCount /
00520 (float) sRawHdr.dSampleRate;
00521 }
00522 Msg.SetResult(ResMsg, &sResHdr, fpSpectOut);
00523 if (SOpResult.WriteN(ResMsg, lResSize) < lResSize)
00524 {
00525 if (bDebug)
00526 printf("spectrum: clSockOp::WriteN() error, client disconnected?\n");
00527 Stop();
00528 return;
00529 }
00530 }
00531 }
00532 }
00533
00534
00535 bool clSpectrum::GetData ()
00536 {
00537 GDT *fpInData = InData;
00538
00539 if (SOpData.ReadN(InData, iInDataSize) < iInDataSize)
00540 {
00541 if (bDebug)
00542 printf("spectrum: clSockOp::ReadN() error, server disconnected?\n");
00543 return false;
00544 }
00545 if (lDecimation < 2)
00546 ReBuffer.Put(fpInData, lInDataCount);
00547 else
00548 Decimator.Put(fpInData, lInDataCount);
00549 return true;
00550 }
00551
00552
00553 bool clSpectrum::PullData (GDT *fpDestBuf, long lDestCount)
00554 {
00555 if (lDecimation < 2)
00556 return ReBuffer.Get(fpDestBuf, lDestCount);
00557 else
00558 return Decimator.Get(fpDestBuf, lDestCount);
00559 }
00560
00561
00562 clSpectrum::clSpectrum (int iInHandle, int iOutHandle)
00563 {
00564 bRun = true;
00565 SOpRequest.SetHandle(iInHandle);
00566 SOpResult.SetHandle(iOutHandle);
00567 }
00568
00569
00570 clSpectrum::~clSpectrum ()
00571 {
00572 }
00573
00574
00575 int clSpectrum::Main ()
00576 {
00577 if (!GetCfg())
00578 {
00579 if (bDebug) printf("spectrum: Error reading configuration\n");
00580 return 1;
00581 }
00582 if (!GetRq())
00583 {
00584 if (bDebug) printf("spectrum: Unable to receive request message\n");
00585 return 1;
00586 }
00587 if (!ConnectStream())
00588 {
00589 if (bDebug) printf("spectrum: Unable to connect to streamdist\n");
00590 return 1;
00591 }
00592 if (!Init())
00593 {
00594 if (bDebug)
00595 printf("spectrum: Direction finding initialization failed\n");
00596 return 1;
00597 }
00598 ProcessLoop();
00599 return 0;
00600 }