welch_pdgm.cpp
上传用户:jtjnyq9001
上传日期:2014-11-21
资源大小:3974k
文件大小:6k
源码类别:

3G开发

开发平台:

Visual C++

  1. //
  2. //  File = welch_pdgm.cpp
  3. //
  4. #include <stdlib.h>
  5. #include <fstream>
  6. #include "parmfile.h"
  7. #include "model_graph.h"
  8. #include "welch_pdgm.h"
  9. #include "trianglr.h"
  10. #include "hamming.h"
  11. #include "hann.h"
  12. #include "fft_T.h"
  13. #include "dump_spect.h"
  14. #ifdef _DEBUG
  15.   extern ofstream *DebugFile;
  16. #endif
  17. #define _NO_ZERO_ENDS 0
  18. #define _ZERO_ENDS 1
  19. extern ParmFile *ParmInput;
  20. extern int PassNumber;
  21. //======================================================
  22. template <class T>
  23. WelchPeriodogram<T>::WelchPeriodogram( char* instance_name,
  24.                                   PracSimModel* outer_model,
  25.                                   Signal<T>* in_sig )
  26.                 :PracSimModel( instance_name,
  27.                                 outer_model )
  28. {
  29.   MODEL_NAME(WelchPeriodogram);
  30.   OPEN_PARM_BLOCK;
  31.   int is;
  32.   GET_INT_PARM(Seg_Len);
  33.   GET_INT_PARM(Fft_Len);
  34.   GET_INT_PARM(Hold_Off);
  35.   GET_INT_PARM(Shift_Between_Segs);
  36.   GET_INT_PARM(Num_Segs_To_Avg);
  37.   Psd_File_Name = new char[64];
  38.   strcpy(Psd_File_Name, "");
  39.   GET_STRING_PARM(Psd_File_Name);
  40.   //GET_DOUBLE_PARM(Norm_Factor);
  41.   GET_DOUBLE_PARM(Freq_Norm_Factor);
  42.   GET_BOOL_PARM(Output_In_Decibels);
  43.   GET_BOOL_PARM(Plot_Two_Sided);
  44.   GET_BOOL_PARM(Halt_When_Completed);
  45.   GET_BOOL_PARM(Using_Window);
  46.   if(Using_Window)
  47.   {
  48.       Window_Shape = GetWindowShapeParm("Window_Shape");
  49.       switch(Window_Shape)
  50.       {
  51.       case WINDOW_SHAPE_TRIANGULAR:
  52.         Data_Window = new TriangularWindow( Seg_Len, _NO_ZERO_ENDS );
  53.         break;
  54.       case WINDOW_SHAPE_HAMMING:
  55.         Data_Window = new HammingWindow( Seg_Len );
  56.         break;
  57.       case WINDOW_SHAPE_HANN:
  58.         Data_Window = new HannWindow( Seg_Len, _NO_ZERO_ENDS );
  59.         break;
  60.       default:
  61.         break;
  62.       }
  63.       ofstream* lag_win_file = new ofstream("lag_win.txt", ios::out);
  64. //      Data_Window->DumpHalfLagWindow(lag_win_file);
  65.       Window_Taps = Data_Window->GetDataWindow();
  66.       Window_Power = 0.0;
  67.       for(is=0; is<Seg_Len; is++)
  68.       {
  69.          Window_Power += Window_Taps[is]*Window_Taps[is];
  70.       }
  71.       Window_Power /= double(Seg_Len);
  72.       double window_scale = sqrt(Window_Power);
  73.       for(is=0; is<Seg_Len; is++)
  74.       {
  75.          Window_Taps[is] /= window_scale;
  76.       }
  77.    }
  78.   In_Sig = in_sig;
  79.   MAKE_INPUT(In_Sig);
  80.   Time_Seg = new T[Seg_Len];
  81.   Overlap_Len = Seg_Len - Shift_Between_Segs;
  82.   Overlap_Seg = Time_Seg + Shift_Between_Segs;
  83.   Win_Time_Seg = new T[Seg_Len];
  84.   Sample_Spectrum = new double[Fft_Len];
  85.   Freq_Seg = new std::complex<double>[Fft_Len];
  86.   for(is=0; is<Fft_Len; is++)
  87.     {
  88.     Sample_Spectrum[is] = 0.0;
  89.     }
  90.   Psd_File = new ofstream(Psd_File_Name, ios::out);
  91.   Processing_Completed = false;
  92. }
  93. template <class T>
  94. WelchPeriodogram<T>::~WelchPeriodogram( void ){ };
  95. template <class T>
  96. void WelchPeriodogram<T>::Initialize(void)
  97. {
  98.   Segs_In_Est = 0;
  99.   Samps_Needed = Seg_Len;
  100.   Block_Size = In_Sig->GetBlockSize();
  101.   Samp_Intvl = In_Sig->GetSampIntvl();
  102.   Delta_F = 1.0/(Samp_Intvl*Fft_Len);
  103. };
  104. template <class T>
  105. int WelchPeriodogram<T>::Execute()
  106. {
  107.    int i,is;
  108.    #ifdef _DEBUG
  109.       *DebugFile << "In WelchPeriodogram::Execute" << endl;
  110.    #endif
  111.    if(Processing_Completed) return(_MES_AOK);
  112.    if(PassNumber < Hold_Off) return (_MES_AOK);
  113.    //--------------------------------
  114.    //  Get pointers for buffers
  115.    T *in_sig_ptr = GET_INPUT_PTR(In_Sig);
  116.    int samps_avail = Block_Size;
  117.    while(Samps_Needed <= samps_avail)
  118.    {
  119.       //  The new input block has enough samples to finish a segment.
  120.       //  Fill up FFT buffer by getting Samps_Needed input samples.
  121.       for(is=Samps_Needed; is>0; is--)
  122.       {
  123.          Time_Seg[Seg_Len - is] = *in_sig_ptr++;
  124.       }
  125.       samps_avail -= Samps_Needed;
  126.       if(Using_Window)
  127.       {
  128.          for(is=0; is<Seg_Len; is++)
  129.          {
  130.             Win_Time_Seg[is] = Window_Taps[is]*Time_Seg[is];
  131.          }
  132.       }
  133.       else
  134.       {
  135.          for(is=0; is<Seg_Len; is++)
  136.          {
  137.             Win_Time_Seg[is] = Time_Seg[is];
  138.          }
  139.       }
  140.       //  Perform FFT
  141.       FFT<double>(   Win_Time_Seg,
  142.                      Freq_Seg,
  143.                      Seg_Len,
  144.                      Fft_Len);
  145.       for(i=0; i<Seg_Len; i++)
  146.       {
  147.          //Sample_Spectrum[i] += Samp_Intvl * std::norm(Freq_Seg[i])/(Window_Power*Seg_Len);
  148.          Sample_Spectrum[i] += Samp_Intvl * std::norm(Freq_Seg[i])/Seg_Len;
  149.       }
  150.       //for(is=0; is<Seg_Len; is++)
  151.       //{
  152.       //   Time_Seg[is] = 0.0;
  153.       //}
  154.       // copy overlap samples down to start of buffer
  155.       //memmove( Time_Seg, Overlap_Seg, 
  156.       //        (sizeof(T)/sizeof(char))*Overlap_Len);
  157.       for(i=0; i<Overlap_Len; i++)
  158.       {
  159.          Time_Seg[i] = Overlap_Seg[i];
  160.       }
  161.       Samps_Needed = Shift_Between_Segs;
  162.       Segs_In_Est++;
  163.       // is it time to dump the results?
  164.       if(Segs_In_Est == Num_Segs_To_Avg)
  165.       {
  166.          for(i=0; i<Seg_Len; i++)
  167.          {
  168.             Sample_Spectrum[i] /= double(Num_Segs_To_Avg);
  169.          }
  170.          DumpSpectrum(  Sample_Spectrum,
  171.                         Fft_Len,
  172.                         Delta_F,
  173.                         Freq_Norm_Factor,
  174.                         Output_In_Decibels,
  175.                         Plot_Two_Sided,
  176.                         Psd_File);
  177.          Processing_Completed = true;
  178.          Psd_File->close();
  179.          if(Halt_When_Completed)
  180.          {
  181.             #ifdef _DEBUG
  182.                *DebugFile << "Execution halted by " << GetModelName() << endl;
  183.             #endif
  184.             exit(0);
  185.          }
  186.       }
  187.    }// end of while
  188.   //  The number of avail new samples is not sufficient to finish a segment.
  189.   //  Copy the avaialble samples and then wait for the next pass
  190.   //  to get some more.
  191.    for(is=0; is<samps_avail; is++)
  192.    {
  193.       Time_Seg[Seg_Len - Samps_Needed + is] = *in_sig_ptr++;
  194.    }
  195.    Samps_Needed -= samps_avail;
  196.    return(_MES_AOK);
  197. }
  198. template WelchPeriodogram<float>;