mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-16 05:11:49 -05:00
Added a windowed FIR filter calculator analogous to Scipy's firwin (this one from Iowa Hills Software LLC code)
This commit is contained in:
parent
4d5fdfc913
commit
6c9dbb79c4
@ -136,6 +136,7 @@ set(sdrbase_SOURCES
|
||||
sdrbase/dsp/spectrumvis.cpp
|
||||
sdrbase/dsp/threadedbasebandsamplesink.cpp
|
||||
sdrbase/dsp/threadedbasebandsamplesource.cpp
|
||||
sdrbase/dsp/wfir.cpp
|
||||
|
||||
sdrbase/gui/aboutdialog.cpp
|
||||
sdrbase/gui/addpresetdialog.cpp
|
||||
@ -257,6 +258,7 @@ set(sdrbase_HEADERS
|
||||
sdrbase/dsp/spectrumvis.h
|
||||
sdrbase/dsp/threadedbasebandsamplesink.h
|
||||
sdrbase/dsp/threadedbasebandsamplesource.h
|
||||
sdrbase/dsp/wfir.h
|
||||
|
||||
sdrbase/gui/aboutdialog.h
|
||||
sdrbase/gui/addpresetdialog.h
|
||||
|
377
sdrbase/dsp/wfir.cpp
Normal file
377
sdrbase/dsp/wfir.cpp
Normal file
@ -0,0 +1,377 @@
|
||||
/*
|
||||
July 15, 2015
|
||||
Iowa Hills Software LLC
|
||||
http://www.iowahills.com
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <new>
|
||||
#include <iostream>
|
||||
|
||||
#include "wfir.h"
|
||||
|
||||
#define M_2PI 6.28318530717958647692 // M_PI should be in the math.h file
|
||||
|
||||
// This first calculates the impulse response for a rectangular window.
|
||||
// It then applies the windowing function of choice to the impulse response.
|
||||
void WFIR::BasicFIR(double *FirCoeff, int NumTaps, TPassTypeName PassType,
|
||||
double OmegaC, double BW, TWindowType WindowType, double WinBeta)
|
||||
{
|
||||
int j;
|
||||
double Arg, OmegaLow, OmegaHigh;
|
||||
|
||||
switch (PassType)
|
||||
{
|
||||
case LPF:
|
||||
for (j = 0; j < NumTaps; j++)
|
||||
{
|
||||
Arg = (double) j - (double) (NumTaps - 1) / 2.0;
|
||||
FirCoeff[j] = OmegaC * Sinc(OmegaC * Arg * M_PI);
|
||||
}
|
||||
break;
|
||||
|
||||
case HPF:
|
||||
if (NumTaps % 2 == 1) // Odd tap counts
|
||||
{
|
||||
for (j = 0; j < NumTaps; j++)
|
||||
{
|
||||
Arg = (double) j - (double) (NumTaps - 1) / 2.0;
|
||||
FirCoeff[j] = Sinc(Arg * M_PI)
|
||||
- OmegaC * Sinc(OmegaC * Arg * M_PI);
|
||||
}
|
||||
}
|
||||
|
||||
else // Even tap counts
|
||||
{
|
||||
for (j = 0; j < NumTaps; j++)
|
||||
{
|
||||
Arg = (double) j - (double) (NumTaps - 1) / 2.0;
|
||||
if (Arg == 0.0)
|
||||
FirCoeff[j] = 0.0;
|
||||
else
|
||||
FirCoeff[j] = cos(OmegaC * Arg * M_PI) / M_PI / Arg
|
||||
+ cos(Arg * M_PI);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BPF:
|
||||
OmegaLow = OmegaC - BW / 2.0;
|
||||
OmegaHigh = OmegaC + BW / 2.0;
|
||||
for (j = 0; j < NumTaps; j++)
|
||||
{
|
||||
Arg = (double) j - (double) (NumTaps - 1) / 2.0;
|
||||
if (Arg == 0.0)
|
||||
FirCoeff[j] = 0.0;
|
||||
else
|
||||
FirCoeff[j] = (cos(OmegaLow * Arg * M_PI)
|
||||
- cos(OmegaHigh * Arg * M_PI)) / M_PI / Arg;
|
||||
}
|
||||
break;
|
||||
|
||||
case NOTCH: // If NumTaps is even for Notch filters, the response at Pi is attenuated.
|
||||
OmegaLow = OmegaC - BW / 2.0;
|
||||
OmegaHigh = OmegaC + BW / 2.0;
|
||||
for (j = 0; j < NumTaps; j++)
|
||||
{
|
||||
Arg = (double) j - (double) (NumTaps - 1) / 2.0;
|
||||
FirCoeff[j] = Sinc(Arg * M_PI)
|
||||
- OmegaHigh * Sinc(OmegaHigh * Arg * M_PI)
|
||||
- OmegaLow * Sinc(OmegaLow * Arg * M_PI);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// WindowData can be used to window data before an FFT. When used for FIR filters we set
|
||||
// Alpha = 0.0 to prevent a flat top on the window and
|
||||
// set UnityGain = false to prevent the window gain from getting set to unity.
|
||||
WindowData(FirCoeff, NumTaps, WindowType, 0.0, WinBeta, false);
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// This gets used with the Kaiser window.
|
||||
double WFIR::Bessel(double x)
|
||||
{
|
||||
double Sum = 0.0, XtoIpower;
|
||||
int i, j, Factorial;
|
||||
for (i = 1; i < 10; i++)
|
||||
{
|
||||
XtoIpower = pow(x / 2.0, (double) i);
|
||||
Factorial = 1;
|
||||
for (j = 1; j <= i; j++)
|
||||
Factorial *= j;
|
||||
Sum += pow(XtoIpower / (double) Factorial, 2.0);
|
||||
}
|
||||
return (1.0 + Sum);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// This gets used with the Sinc window and various places in the BasicFIR function.
|
||||
double WFIR::Sinc(double x)
|
||||
{
|
||||
if (x > -1.0E-5 && x < 1.0E-5)
|
||||
return (1.0);
|
||||
return (sin(x) / x);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// These are the various windows definitions. These windows can be used for either
|
||||
// FIR filter design or with an FFT for spectral analysis.
|
||||
// Sourced verbatim from: ~MyDocs\Code\Common\FFTFunctions.cpp
|
||||
// For definitions, see this article: http://en.wikipedia.org/wiki/Window_function
|
||||
|
||||
// This function has 6 inputs
|
||||
// Data is the array, of length N, containing the data to to be windowed.
|
||||
// This data is either a FIR filter sinc pulse, or the data to be analyzed by an fft.
|
||||
|
||||
// WindowType is an enum defined in the header file, which is at the bottom of this file.
|
||||
// e.g. wtKAISER, wtSINC, wtHANNING, wtHAMMING, wtBLACKMAN, ...
|
||||
|
||||
// Alpha sets the width of the flat top.
|
||||
// Windows such as the Tukey and Trapezoid are defined to have a variably wide flat top.
|
||||
// As can be seen by its definition, the Tukey is just a Hanning window with a flat top.
|
||||
// Alpha can be used to give any of these windows a partial flat top, except the Flattop and Kaiser.
|
||||
// Alpha = 0 gives the original window. (i.e. no flat top)
|
||||
// To generate a Tukey window, use a Hanning with 0 < Alpha < 1
|
||||
// To generate a Bartlett window (triangular), use a Trapezoid window with Alpha = 0.
|
||||
// Alpha = 1 generates a rectangular window in all cases. (except the Flattop and Kaiser)
|
||||
|
||||
// Beta is used with the Kaiser, Sinc, and Sine windows only.
|
||||
// These three windows are primarily used for FIR filter design, not spectral analysis.
|
||||
// In FIR filter design, Beta controls the filter's transition bandwidth and the sidelobe levels.
|
||||
// The code ignores Beta except in the Kaiser, Sinc, and Sine window cases.
|
||||
|
||||
// UnityGain controls whether the gain of these windows is set to unity.
|
||||
// Only the Flattop window has unity gain by design. The Hanning window, for example, has a gain
|
||||
// of 1/2. UnityGain = true will set the gain of all these windows to 1.
|
||||
// Then, when the window is applied to a signal, the signal's energy content is preserved.
|
||||
// Don't use this with FIR filter design however. Since most of the enegy in an FIR sinc pulse
|
||||
// is in the middle of the window, the window needs a peak amplitude of one, not unity gain.
|
||||
// Setting UnityGain = true will simply cause the resulting FIR filter to have excess gain.
|
||||
|
||||
// If using these windows for FIR filters, start with the Kaiser, Sinc, or Sine windows and
|
||||
// adjust Beta for the desired transition BW and sidelobe levels (set Alpha = 0).
|
||||
// While the FlatTop is an excellent window for spectral analysis, don't use it for FIR filter design.
|
||||
// It has a peak amplitude of ~ 4.7 which causes the resulting FIR filter to have about this much gain.
|
||||
// It works poorly for FIR filters even if you adjust its peak amplitude.
|
||||
// The Trapezoid also works poorly for FIR filter design.
|
||||
|
||||
// If using these windows with an fft for spectral analysis, start with the Hanning, Gauss, or Flattop.
|
||||
// When choosing a window for spectral analysis, you must trade off between resolution and amplitude accuracy.
|
||||
// The Hanning has the best resolution while the Flatop has the best amplitude accuracy.
|
||||
// The Gauss is midway between these two for both accuracy and resolution.
|
||||
// These three were the only windows available in the HP 89410A Vector Signal Analyzer. Which is to say,
|
||||
// unless you have specific windowing requirements, use one of these 3 for general purpose signal analysis.
|
||||
// Set UnityGain = true when using any of these windows for spectral analysis to preserve the signal's enegy level.
|
||||
|
||||
void WFIR::WindowData(double *Data, int N, TWindowType WindowType, double Alpha,
|
||||
double Beta, bool UnityGain)
|
||||
{
|
||||
if (WindowType == wtNONE)
|
||||
return;
|
||||
|
||||
int j, M, TopWidth;
|
||||
double dM, *WinCoeff;
|
||||
|
||||
if (WindowType == wtKAISER || WindowType == wtFLATTOP)
|
||||
Alpha = 0.0;
|
||||
|
||||
if (Alpha < 0.0)
|
||||
Alpha = 0.0;
|
||||
if (Alpha > 1.0)
|
||||
Alpha = 1.0;
|
||||
|
||||
if (Beta < 0.0)
|
||||
Beta = 0.0;
|
||||
if (Beta > 10.0)
|
||||
Beta = 10.0;
|
||||
|
||||
WinCoeff = new (std::nothrow) double[N + 2];
|
||||
if (WinCoeff == 0)
|
||||
{
|
||||
std::cerr
|
||||
<< "Failed to allocate memory in FFTFunctions::WindowFFTData() "
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
TopWidth = (int) (Alpha * (double) N);
|
||||
if (TopWidth % 2 != 0)
|
||||
TopWidth++;
|
||||
if (TopWidth > N)
|
||||
TopWidth = N;
|
||||
M = N - TopWidth;
|
||||
dM = M + 1;
|
||||
|
||||
// Calculate the window for N/2 points, then fold the window over (at the bottom).
|
||||
// TopWidth points will be set to 1.
|
||||
if (WindowType == wtKAISER)
|
||||
{
|
||||
double Arg;
|
||||
for (j = 0; j < M; j++)
|
||||
{
|
||||
Arg = Beta * sqrt(1.0 - pow(((double) (2 * j + 2) - dM) / dM, 2.0));
|
||||
WinCoeff[j] = Bessel(Arg) / Bessel(Beta);
|
||||
}
|
||||
}
|
||||
|
||||
else if (WindowType == wtSINC) // Lanczos
|
||||
{
|
||||
for (j = 0; j < M; j++)
|
||||
WinCoeff[j] = Sinc((double) (2 * j + 1 - M) / dM * M_PI);
|
||||
for (j = 0; j < M; j++)
|
||||
WinCoeff[j] = pow(WinCoeff[j], Beta);
|
||||
}
|
||||
|
||||
else if (WindowType == wtSINE) // Hanning if Beta = 2
|
||||
{
|
||||
for (j = 0; j < M / 2; j++)
|
||||
WinCoeff[j] = sin((double) (j + 1) * M_PI / dM);
|
||||
for (j = 0; j < M / 2; j++)
|
||||
WinCoeff[j] = pow(WinCoeff[j], Beta);
|
||||
}
|
||||
|
||||
else if (WindowType == wtHANNING)
|
||||
{
|
||||
for (j = 0; j < M / 2; j++)
|
||||
WinCoeff[j] = 0.5 - 0.5 * cos((double) (j + 1) * M_2PI / dM);
|
||||
}
|
||||
|
||||
else if (WindowType == wtHAMMING)
|
||||
{
|
||||
for (j = 0; j < M / 2; j++)
|
||||
WinCoeff[j] = 0.54 - 0.46 * cos((double) (j + 1) * M_2PI / dM);
|
||||
}
|
||||
|
||||
else if (WindowType == wtBLACKMAN)
|
||||
{
|
||||
for (j = 0; j < M / 2; j++)
|
||||
{
|
||||
WinCoeff[j] = 0.42 - 0.50 * cos((double) (j + 1) * M_2PI / dM)
|
||||
+ 0.08 * cos((double) (j + 1) * M_2PI * 2.0 / dM);
|
||||
}
|
||||
}
|
||||
|
||||
// See: http://www.bth.se/fou/forskinfo.nsf/0/130c0940c5e7ffcdc1256f7f0065ac60/$file/ICOTA_2004_ttr_icl_mdh.pdf
|
||||
else if (WindowType == wtFLATTOP)
|
||||
{
|
||||
for (j = 0; j <= M / 2; j++)
|
||||
{
|
||||
WinCoeff[j] = 1.0
|
||||
- 1.93293488969227 * cos((double) (j + 1) * M_2PI / dM)
|
||||
+ 1.28349769674027
|
||||
* cos((double) (j + 1) * M_2PI * 2.0 / dM)
|
||||
- 0.38130801681619
|
||||
* cos((double) (j + 1) * M_2PI * 3.0 / dM)
|
||||
+ 0.02929730258511
|
||||
* cos((double) (j + 1) * M_2PI * 4.0 / dM);
|
||||
}
|
||||
}
|
||||
|
||||
else if (WindowType == wtBLACKMAN_HARRIS)
|
||||
{
|
||||
for (j = 0; j < M / 2; j++)
|
||||
{
|
||||
WinCoeff[j] = 0.35875 - 0.48829 * cos((double) (j + 1) * M_2PI / dM)
|
||||
+ 0.14128 * cos((double) (j + 1) * M_2PI * 2.0 / dM)
|
||||
- 0.01168 * cos((double) (j + 1) * M_2PI * 3.0 / dM);
|
||||
}
|
||||
}
|
||||
|
||||
else if (WindowType == wtBLACKMAN_NUTTALL)
|
||||
{
|
||||
for (j = 0; j < M / 2; j++)
|
||||
{
|
||||
WinCoeff[j] = 0.3535819
|
||||
- 0.4891775 * cos((double) (j + 1) * M_2PI / dM)
|
||||
+ 0.1365995 * cos((double) (j + 1) * M_2PI * 2.0 / dM)
|
||||
- 0.0106411 * cos((double) (j + 1) * M_2PI * 3.0 / dM);
|
||||
}
|
||||
}
|
||||
|
||||
else if (WindowType == wtNUTTALL)
|
||||
{
|
||||
for (j = 0; j < M / 2; j++)
|
||||
{
|
||||
WinCoeff[j] = 0.355768
|
||||
- 0.487396 * cos((double) (j + 1) * M_2PI / dM)
|
||||
+ 0.144232 * cos((double) (j + 1) * M_2PI * 2.0 / dM)
|
||||
- 0.012604 * cos((double) (j + 1) * M_2PI * 3.0 / dM);
|
||||
}
|
||||
}
|
||||
|
||||
else if (WindowType == wtKAISER_BESSEL)
|
||||
{
|
||||
for (j = 0; j <= M / 2; j++)
|
||||
{
|
||||
WinCoeff[j] = 0.402 - 0.498 * cos(M_2PI * (double) (j + 1) / dM)
|
||||
+ 0.098 * cos(2.0 * M_2PI * (double) (j + 1) / dM)
|
||||
+ 0.001 * cos(3.0 * M_2PI * (double) (j + 1) / dM);
|
||||
}
|
||||
}
|
||||
|
||||
else if (WindowType == wtTRAPEZOID) // Rectangle for Alpha = 1 Triangle for Alpha = 0
|
||||
{
|
||||
int K = M / 2;
|
||||
if (M % 2)
|
||||
K++;
|
||||
for (j = 0; j < K; j++)
|
||||
WinCoeff[j] = (double) (j + 1) / (double) K;
|
||||
}
|
||||
|
||||
// This definition is from http://en.wikipedia.org/wiki/Window_function (Gauss Generalized normal window)
|
||||
// We set their p = 2, and use Alpha in the numerator, instead of Sigma in the denominator, as most others do.
|
||||
// Alpha = 2.718 puts the Gauss window response midway between the Hanning and the Flattop (basically what we want).
|
||||
// It also gives the same BW as the Gauss window used in the HP 89410A Vector Signal Analyzer.
|
||||
// Alpha = 1.8 puts it quite close to the Hanning.
|
||||
else if (WindowType == wtGAUSS)
|
||||
{
|
||||
for (j = 0; j < M / 2; j++)
|
||||
{
|
||||
WinCoeff[j] = ((double) (j + 1) - dM / 2.0) / (dM / 2.0) * 2.7183;
|
||||
WinCoeff[j] *= WinCoeff[j];
|
||||
WinCoeff[j] = exp(-WinCoeff[j]);
|
||||
}
|
||||
}
|
||||
|
||||
else // Error.
|
||||
{
|
||||
std::cerr << "Incorrect window type in WindowFFTData" << std::endl;
|
||||
delete[] WinCoeff;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fold the coefficients over.
|
||||
for (j = 0; j < M / 2; j++)
|
||||
WinCoeff[N - j - 1] = WinCoeff[j];
|
||||
|
||||
// This is the flat top if Alpha > 0. Cannot be applied to a Kaiser or Flat Top.
|
||||
if (WindowType != wtKAISER && WindowType != wtFLATTOP)
|
||||
{
|
||||
for (j = M / 2; j < N - M / 2; j++)
|
||||
WinCoeff[j] = 1.0;
|
||||
}
|
||||
|
||||
// This will set the gain of the window to 1. Only the Flattop window has unity gain by design.
|
||||
if (UnityGain)
|
||||
{
|
||||
double Sum = 0.0;
|
||||
for (j = 0; j < N; j++)
|
||||
Sum += WinCoeff[j];
|
||||
Sum /= (double) N;
|
||||
if (Sum != 0.0)
|
||||
for (j = 0; j < N; j++)
|
||||
WinCoeff[j] /= Sum;
|
||||
}
|
||||
|
||||
// Apply the window to the data.
|
||||
for (j = 0; j < N; j++)
|
||||
Data[j] *= WinCoeff[j];
|
||||
|
||||
delete[] WinCoeff;
|
||||
|
||||
}
|
93
sdrbase/dsp/wfir.h
Normal file
93
sdrbase/dsp/wfir.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
July 15, 2015
|
||||
Iowa Hills Software LLC
|
||||
http://www.iowahills.com
|
||||
|
||||
If you find a problem with this code, please leave us a note on:
|
||||
http://www.iowahills.com/feedbackcomments.html
|
||||
|
||||
Source: ~Projects\Common\BasicFIRFilterCode.cpp
|
||||
|
||||
This generic FIR filter code is described in most textbooks.
|
||||
e.g. Discrete Time Signal Processing, Oppenheim and Shafer
|
||||
|
||||
A nice paper on this topic is:
|
||||
http://dea.brunel.ac.uk/cmsp/Home_Saeed_Vaseghi/Chapter05-DigitalFilters.pdf
|
||||
|
||||
This code first generates either a low pass, high pass, band pass, or notch
|
||||
impulse response for a rectangular window. It then applies a window to this
|
||||
impulse response.
|
||||
|
||||
There are several windows available, including the Kaiser, Sinc, Hanning,
|
||||
Blackman, and Hamming. Of these, the Kaiser and Sinc are probably the most useful
|
||||
for FIR filters because their sidelobe levels can be controlled with the Beta parameter.
|
||||
|
||||
This is a typical function call:
|
||||
BasicFIR(FirCoeff, NumTaps, PassType, OmegaC, BW, wtKAISER, Beta);
|
||||
BasicFIR(FirCoeff, 33, LPF, 0.2, 0.0, wtKAISER, 3.2);
|
||||
33 tap, low pass, corner frequency at 0.2, BW=0 (ignored in the low pass code),
|
||||
Kaiser window, Kaiser Beta = 3.2
|
||||
|
||||
These variables should be defined similar to this:
|
||||
double FirCoeff[MAXNUMTAPS];
|
||||
int NumTaps; NumTaps can be even or odd, but must be less than the FirCoeff array size.
|
||||
TPassTypeName PassType; PassType is an enum defined in the header file. LPF, HPF, BPF, or NOTCH
|
||||
double OmegaC 0.0 < OmegaC < 1.0 The filters corner freq, or center freq if BPF or NOTCH
|
||||
double BW 0.0 < BW < 1.0 The filters band width if BPF or NOTCH
|
||||
TWindowType WindowType; WindowType is an enum defined in the header to be one of these.
|
||||
wtNONE, wtKAISER, wtSINC, wtHANNING, .... and others.
|
||||
double Beta; 0 <= Beta <= 10.0 Beta is used with the Kaiser, Sinc, and Sine windows only.
|
||||
It controls the transition BW and sidelobe level of the filters.
|
||||
|
||||
|
||||
If you want to use it, Kaiser originally defined Beta as follows.
|
||||
He derived its value based on the desired sidelobe level, dBAtten.
|
||||
double dBAtten, Beta, Beta1=0.0, Beta2=0.0;
|
||||
if(dBAtten < 21.0)dBAtten = 21.0;
|
||||
if(dBAtten > 50.0)Beta1 = 0.1102 * (dBAtten - 8.7);
|
||||
if(dBAtten >= 21.0 && dBAtten <= 50.0) Beta2 = 0.5842 * pow(dBAtten - 21.0, 0.4) + 0.07886 * (dBAtten - 21.0);
|
||||
Beta = Beta1 + Beta2;
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _WFIR_H_
|
||||
#define _WFIR_H_
|
||||
|
||||
class WFIR
|
||||
{
|
||||
public:
|
||||
enum TPassTypeName
|
||||
{
|
||||
LPF, HPF, BPF, NOTCH
|
||||
};
|
||||
|
||||
enum TWindowType
|
||||
{
|
||||
wtNONE,
|
||||
wtKAISER,
|
||||
wtSINC,
|
||||
wtHANNING,
|
||||
wtHAMMING,
|
||||
wtBLACKMAN,
|
||||
wtFLATTOP,
|
||||
wtBLACKMAN_HARRIS,
|
||||
wtBLACKMAN_NUTTALL,
|
||||
wtNUTTALL,
|
||||
wtKAISER_BESSEL,
|
||||
wtTRAPEZOID,
|
||||
wtGAUSS,
|
||||
wtSINE,
|
||||
wtTEST
|
||||
};
|
||||
|
||||
static void BasicFIR(double *FirCoeff, int NumTaps, TPassTypeName PassType,
|
||||
double OmegaC, double BW, TWindowType WindowType, double WinBeta);
|
||||
|
||||
private:
|
||||
static void WindowData(double *Data, int N, TWindowType WindowType,
|
||||
double Alpha, double Beta, bool UnityGain);
|
||||
static double Bessel(double x);
|
||||
static double Sinc(double x);
|
||||
};
|
||||
|
||||
#endif
|
@ -89,6 +89,7 @@ SOURCES += mainwindow.cpp\
|
||||
dsp/spectrumvis.cpp\
|
||||
dsp/threadedbasebandsamplesink.cpp\
|
||||
dsp/threadedbasebandsamplesource.cpp\
|
||||
dsp/wfir.cpp\
|
||||
gui/aboutdialog.cpp\
|
||||
gui/addpresetdialog.cpp\
|
||||
gui/basicchannelsettingswidget.cpp\
|
||||
@ -196,6 +197,7 @@ HEADERS += mainwindow.h\
|
||||
dsp/spectrumvis.h\
|
||||
dsp/threadedbasebandsamplesink.h\
|
||||
dsp/threadedbasebandsamplesource.h\
|
||||
dsp/wfir.h\
|
||||
gui/aboutdialog.h\
|
||||
gui/addpresetdialog.h\
|
||||
gui/audiodialog.h\
|
||||
|
Loading…
Reference in New Issue
Block a user