📄 welch_pdgm.cpp
字号:
//
// File = welch_pdgm.cpp
//
#include <stdlib.h>
#include <fstream>
#include "parmfile.h"
#include "model_graph.h"
#include "welch_pdgm.h"
#include "trianglr.h"
#include "hamming.h"
#include "hann.h"
#include "fft_T.h"
#include "dump_spect.h"
#ifdef _DEBUG
extern ofstream *DebugFile;
#endif
#define _NO_ZERO_ENDS 0
#define _ZERO_ENDS 1
extern ParmFile *ParmInput;
extern int PassNumber;
//======================================================
template <class T>
WelchPeriodogram<T>::WelchPeriodogram( char* instance_name,
PracSimModel* outer_model,
Signal<T>* in_sig )
:PracSimModel( instance_name,
outer_model )
{
MODEL_NAME(WelchPeriodogram);
OPEN_PARM_BLOCK;
int is;
GET_INT_PARM(Seg_Len);
GET_INT_PARM(Fft_Len);
GET_INT_PARM(Hold_Off);
GET_INT_PARM(Shift_Between_Segs);
GET_INT_PARM(Num_Segs_To_Avg);
Psd_File_Name = new char[64];
strcpy(Psd_File_Name, "\0");
GET_STRING_PARM(Psd_File_Name);
//GET_DOUBLE_PARM(Norm_Factor);
GET_DOUBLE_PARM(Freq_Norm_Factor);
GET_BOOL_PARM(Output_In_Decibels);
GET_BOOL_PARM(Plot_Two_Sided);
GET_BOOL_PARM(Halt_When_Completed);
GET_BOOL_PARM(Using_Window);
if(Using_Window)
{
Window_Shape = GetWindowShapeParm("Window_Shape\0");
switch(Window_Shape)
{
case WINDOW_SHAPE_TRIANGULAR:
Data_Window = new TriangularWindow( Seg_Len, _NO_ZERO_ENDS );
break;
case WINDOW_SHAPE_HAMMING:
Data_Window = new HammingWindow( Seg_Len );
break;
case WINDOW_SHAPE_HANN:
Data_Window = new HannWindow( Seg_Len, _NO_ZERO_ENDS );
break;
default:
break;
}
ofstream* lag_win_file = new ofstream("lag_win.txt\0", ios::out);
// Data_Window->DumpHalfLagWindow(lag_win_file);
Window_Taps = Data_Window->GetDataWindow();
Window_Power = 0.0;
for(is=0; is<Seg_Len; is++)
{
Window_Power += Window_Taps[is]*Window_Taps[is];
}
Window_Power /= double(Seg_Len);
double window_scale = sqrt(Window_Power);
for(is=0; is<Seg_Len; is++)
{
Window_Taps[is] /= window_scale;
}
}
In_Sig = in_sig;
MAKE_INPUT(In_Sig);
Time_Seg = new T[Seg_Len];
Overlap_Len = Seg_Len - Shift_Between_Segs;
Overlap_Seg = Time_Seg + Shift_Between_Segs;
Win_Time_Seg = new T[Seg_Len];
Sample_Spectrum = new double[Fft_Len];
Freq_Seg = new std::complex<double>[Fft_Len];
for(is=0; is<Fft_Len; is++)
{
Sample_Spectrum[is] = 0.0;
}
Psd_File = new ofstream(Psd_File_Name, ios::out);
Processing_Completed = false;
}
template <class T>
WelchPeriodogram<T>::~WelchPeriodogram( void ){ };
template <class T>
void WelchPeriodogram<T>::Initialize(void)
{
Segs_In_Est = 0;
Samps_Needed = Seg_Len;
Block_Size = In_Sig->GetBlockSize();
Samp_Intvl = In_Sig->GetSampIntvl();
Delta_F = 1.0/(Samp_Intvl*Fft_Len);
};
template <class T>
int WelchPeriodogram<T>::Execute()
{
int i,is;
#ifdef _DEBUG
*DebugFile << "In WelchPeriodogram::Execute\0" << endl;
#endif
if(Processing_Completed) return(_MES_AOK);
if(PassNumber < Hold_Off) return (_MES_AOK);
//--------------------------------
// Get pointers for buffers
T *in_sig_ptr = GET_INPUT_PTR(In_Sig);
int samps_avail = Block_Size;
while(Samps_Needed <= samps_avail)
{
// The new input block has enough samples to finish a segment.
// Fill up FFT buffer by getting Samps_Needed input samples.
for(is=Samps_Needed; is>0; is--)
{
Time_Seg[Seg_Len - is] = *in_sig_ptr++;
}
samps_avail -= Samps_Needed;
if(Using_Window)
{
for(is=0; is<Seg_Len; is++)
{
Win_Time_Seg[is] = Window_Taps[is]*Time_Seg[is];
}
}
else
{
for(is=0; is<Seg_Len; is++)
{
Win_Time_Seg[is] = Time_Seg[is];
}
}
// Perform FFT
FFT<double>( Win_Time_Seg,
Freq_Seg,
Seg_Len,
Fft_Len);
for(i=0; i<Seg_Len; i++)
{
//Sample_Spectrum[i] += Samp_Intvl * std::norm(Freq_Seg[i])/(Window_Power*Seg_Len);
Sample_Spectrum[i] += Samp_Intvl * std::norm(Freq_Seg[i])/Seg_Len;
}
//for(is=0; is<Seg_Len; is++)
//{
// Time_Seg[is] = 0.0;
//}
// copy overlap samples down to start of buffer
//memmove( Time_Seg, Overlap_Seg,
// (sizeof(T)/sizeof(char))*Overlap_Len);
for(i=0; i<Overlap_Len; i++)
{
Time_Seg[i] = Overlap_Seg[i];
}
Samps_Needed = Shift_Between_Segs;
Segs_In_Est++;
// is it time to dump the results?
if(Segs_In_Est == Num_Segs_To_Avg)
{
for(i=0; i<Seg_Len; i++)
{
Sample_Spectrum[i] /= double(Num_Segs_To_Avg);
}
DumpSpectrum( Sample_Spectrum,
Fft_Len,
Delta_F,
Freq_Norm_Factor,
Output_In_Decibels,
Plot_Two_Sided,
Psd_File);
Processing_Completed = true;
Psd_File->close();
if(Halt_When_Completed)
{
#ifdef _DEBUG
*DebugFile << "Execution halted by " << GetModelName() << endl;
#endif
exit(0);
}
}
}// end of while
// The number of avail new samples is not sufficient to finish a segment.
// Copy the avaialble samples and then wait for the next pass
// to get some more.
for(is=0; is<samps_avail; is++)
{
Time_Seg[Seg_Len - Samps_Needed + is] = *in_sig_ptr++;
}
Samps_Needed -= samps_avail;
return(_MES_AOK);
}
template WelchPeriodogram<float>;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -