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

3G开发

开发平台:

Visual C++

  1. //
  2. //  File =spec_analyzer.cpp
  3. //
  4. #include <stdlib.h>
  5. #include <fstream>
  6. #include "parmfile.h"
  7. #include "model_graph.h"
  8. #include "spec_analyzer.h"
  9. #include "hann.h"
  10. #include "misdefs.h"
  11. #include "fft_T.h"
  12. #include "samp_spect_util.h"
  13. #include "bart_pdgm_util.h"
  14. #ifdef _DEBUG
  15.   extern ofstream *DebugFile;
  16. #endif
  17. extern ParmFile *ParmInput;
  18. extern int PassNumber;
  19. extern char *DateString;
  20. extern bool DateInFileNames;
  21. //======================================================
  22. template <class T>
  23. SpectrumAnalyzer<T>::SpectrumAnalyzer( char* instance_name,
  24.                                   PracSimModel* outer_model,
  25.                                   Signal<T>* in_sig )
  26.                 :PracSimModel( instance_name,
  27.                                 outer_model )
  28. {
  29.   MODEL_NAME(SpectrumAnalyzer_T);
  30.   OPEN_PARM_BLOCK;
  31.   Kind_Of_Spec_Estim = GetKindOfSpectCalcParm("Kind_Of_Spec_Estim");
  32.   GET_INT_PARM(Num_Segs_To_Avg);
  33.   GET_INT_PARM(Seg_Len);
  34.   GET_INT_PARM(Fft_Len);
  35.   GET_INT_PARM(Hold_Off);
  36.   //Psd_File_Name = new char[255];
  37.   //strcpy(Psd_File_Name, "");
  38.   GET_STRING_PARM(Psd_File_Name);
  39.   //char* temp_str = new char[255];
  40.   //strcpy(temp_str,Psd_File_Name);
  41.   //delete[] Psd_File_Name;
  42.   //Psd_File_Name = new char[255];
  43.    if(DateInFileNames){
  44.       strcat(Psd_File_Name,"_");
  45.       strcat(Psd_File_Name, DateString);
  46.       }
  47.    strcat(Psd_File_Name,".txt");
  48.   GET_DOUBLE_PARM(Norm_Factor);
  49.   GET_DOUBLE_PARM(Freq_Norm_Factor);
  50.   GET_BOOL_PARM(Output_In_Decibels);
  51.   GET_BOOL_PARM(Plot_Two_Sided);
  52.   GET_BOOL_PARM(Halt_When_Completed);
  53.   GET_BOOL_PARM(Plot_Relative_To_Peak);
  54.   In_Sig = in_sig;
  55.   MAKE_INPUT(In_Sig);
  56.   Time_Seg = new T[Seg_Len];
  57.   Psd_Est = new double[Fft_Len];
  58.   //Sample_Spectrum = new std::complex<double>[Fft_Len];
  59.   for(int is=0; is<Fft_Len; is++)
  60.     {
  61.     Psd_Est[is] = 0.0;
  62.     }
  63.   Psd_File = new ofstream(Psd_File_Name, ios::out);
  64.   Processing_Completed = false;
  65. }
  66. template <class T>
  67. SpectrumAnalyzer<T>::~SpectrumAnalyzer( void ){ };
  68. template <class T>
  69. void SpectrumAnalyzer<T>::Initialize(void)
  70. {
  71.   Segs_In_Est = 0;
  72.   Samps_Needed = Seg_Len;
  73.   Block_Size = In_Sig->GetBlockSize();
  74.   Samp_Intvl = In_Sig->GetSampIntvl();
  75.   Delta_F = 1.0/(Samp_Intvl*Fft_Len);
  76.    switch(Kind_Of_Spec_Estim)
  77.    {
  78.    case SPECT_CALC_SAMPLE_SPECTRUM:
  79.       Spec_Estim = new SampleSpectrum<T>( Seg_Len,
  80.                                              Fft_Len,
  81.                                              Samp_Intvl);
  82.       break;
  83.    case SPECT_CALC_BARTLETT_PDGM:
  84.       Spec_Estim = new BartlettPeriodogram<T>( Seg_Len,
  85.                                              Fft_Len,
  86.                                              Samp_Intvl);
  87.       Data_Window = new HannWindow( Seg_Len, _NO_ZERO_ENDS );
  88.       break;
  89.    }
  90. };
  91. template <class T>
  92. int SpectrumAnalyzer<T>::Execute()
  93. {
  94.    int is;
  95.    double scale_factor;
  96.    double *data_window;
  97.    double total_power;
  98.    double offset;
  99.    #ifdef _DEBUG
  100.       *DebugFile << "In SpectrumAnalyzer::Execute" << endl;
  101.    #endif
  102.    if(Processing_Completed) return(_MES_AOK);
  103.    if(PassNumber < Hold_Off) return (_MES_AOK);
  104.    //--------------------------------
  105.    //  Get pointers for buffers
  106.    T *in_sig_ptr = GET_INPUT_PTR(In_Sig);
  107.    int samps_avail = Block_Size;
  108.    while(Samps_Needed <= samps_avail)
  109.    {
  110.       //  The new input block has enough samples to finish a segment.
  111.       //  Fill up FFT buffer by getting Samps_Needed input samples.
  112.       for(is=Samps_Needed; is>0; is--)
  113.       {
  114.          Time_Seg[Seg_Len - is] = *in_sig_ptr++;
  115.       }
  116.       samps_avail -= Samps_Needed;
  117.       //  Apply window to the time segment
  118.       data_window = Data_Window->GetDataWindow();
  119.       for(is=0; is<Seg_Len; is++) {
  120.          Time_Seg[is] *= float(*data_window++);
  121.       }
  122.       //  Perform FFT
  123.       //FFT<double>(   Time_Seg,
  124.       //               Sample_Spectrum,
  125.       //               Seg_Len,
  126.       //               Fft_Len);
  127.       //  Perform FFT
  128.       Spec_Estim->Calculate( Time_Seg );
  129.       Spec_Estim->GetEstimate( Psd_Est);
  130.       for(is=0; is<Seg_Len; is++)
  131.       {
  132.          Time_Seg[is] = 0.0;
  133.       }
  134.       Samps_Needed = Seg_Len;
  135.       //  merge sample spectrum into PSD estimate
  136. //      for(is=0; is<Fft_Len; is++)
  137. //      {
  138.          //Psd_Est[is] += std::norm(Sample_Spectrum[is]);
  139. //         Psd_Est[is] += Sample_Spectrum[is];
  140. //      }
  141.       Segs_In_Est++;
  142.       // is it time to dump the results?
  143.       if(Segs_In_Est == Num_Segs_To_Avg)
  144.       {
  145.          //------------------------------------
  146.          // find peak
  147.          double peak_val=0.0;
  148.          int peak_idx=0;
  149.          total_power = 0.0;
  150.          for(is=0; is<Fft_Len; is++) {
  151.             total_power += Psd_Est[is];
  152.          }
  153.          total_power /= double(Num_Segs_To_Avg);
  154.          for(is=0; is<Fft_Len/2; is++)
  155.          {
  156.             if(Psd_Est[is] <= peak_val) continue;
  157.             //else
  158.             peak_val = Psd_Est[is];
  159.             peak_idx = is;
  160.          }
  161.          //scale_factor = double(Num_Segs_To_Avg*Seg_Len*Norm_Factor);
  162. ////         scale_factor = double(Seg_Len*Norm_Factor/2.0);
  163. //030726         scale_factor = Num_Segs_To_Avg;
  164.             scale_factor = Num_Segs_To_Avg * Delta_F;
  165.          //scale_factor = double(Seg_Len/2);
  166.          if(Output_In_Decibels)
  167.          {
  168.             if(Plot_Relative_To_Peak)
  169.             {
  170.                offset = 10.0*log10(Psd_Est[peak_idx]/scale_factor);
  171.             }
  172.             else
  173.             {
  174.                offset = 10.0*log10(1.0/scale_factor);
  175.             }
  176.             if(Plot_Two_Sided)
  177.             {
  178.                for(is=-(Fft_Len/2-1); is<0; is++)
  179.                {
  180.                   if( Psd_Est[-is] >0 )
  181.                   {
  182.                      if(Plot_Relative_To_Peak)
  183.                      {
  184.                         (*Psd_File) << is * Delta_F * Freq_Norm_Factor << ", " 
  185.                                     << (10.0*log10(Psd_Est[-is]/scale_factor)-offset) << endl;
  186.                      }
  187.                      else
  188.                      {
  189.                         (*Psd_File) << is * Delta_F * Freq_Norm_Factor << ", " 
  190.                                     << (10.0*log10(Psd_Est[-is]/scale_factor)) << endl;
  191.                      }
  192.                   }
  193.                   else
  194.                   {
  195.                      (*Psd_File) << is * Delta_F * Freq_Norm_Factor << ", -200.0" << endl;
  196.                   }
  197.                }
  198.             }
  199.             for(is=0; is<Fft_Len/2; is++)
  200.             {
  201.                if( Psd_Est[is] >0 )
  202.                {
  203.                   if(Plot_Relative_To_Peak)
  204.                   {
  205.                      (*Psd_File) << is * Delta_F * Freq_Norm_Factor << ", " 
  206.                                  << (10.0*log10(Psd_Est[is]/scale_factor)-offset) << endl;
  207.                   }
  208.                   else
  209.                   {
  210.                      (*Psd_File) << is * Delta_F * Freq_Norm_Factor << ", " 
  211.                                  << (10.0*log10(Psd_Est[is]/scale_factor)) << endl;
  212.                   }
  213.                   Psd_Est[is] = 0.0;
  214.                }
  215.                else
  216.                {
  217.                   (*Psd_File) << is * Delta_F * Freq_Norm_Factor << ", -200.0" << endl;
  218.                }
  219.             }
  220.          }
  221.          else
  222.          {
  223.             // plot as linear ordinate
  224.             if(Plot_Two_Sided)
  225.             {
  226.                for(is=-(Fft_Len/2-1); is<0; is++)
  227.                {
  228.                   (*Psd_File) << is * Delta_F * Freq_Norm_Factor << ", " 
  229.                               << Psd_Est[-is]/scale_factor << endl;
  230.                }
  231.             }
  232.             for(is=0; is<Fft_Len/2; is++)
  233.             {
  234.                (*Psd_File) << is * Delta_F * Freq_Norm_Factor << ", " 
  235.                            << Psd_Est[is]/scale_factor << endl;
  236.                Psd_Est[is] = 0.0;
  237.             }
  238.          }
  239.          Processing_Completed = true;
  240.          Psd_File->close();
  241.          BasicResults << Instance_Name << ": total_power = " << total_power << endl;
  242.          if(Halt_When_Completed)
  243.          {
  244.             #ifdef _DEBUG
  245.                *DebugFile << "Execution halted by " << GetModelName() << endl;
  246.             #endif
  247.             exit(0);
  248.          }
  249.       }
  250.    }// end of while
  251.   //  The number of avail new samples is not sufficient to finish a segment.
  252.   //  Copy the avaialble samples and then wait for the next pass
  253.   //  to get some more.
  254.    for(is=0; is<samps_avail; is++)
  255.    {
  256.       Time_Seg[Seg_Len - Samps_Needed + is] = *in_sig_ptr++;
  257.    }
  258.    Samps_Needed -= samps_avail;
  259.    return(_MES_AOK);
  260. }
  261. template SpectrumAnalyzer<std::complex<float> >;
  262. template SpectrumAnalyzer<float>;