SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
Public Types | Static Public Member Functions | Static Private Member Functions | List of all members
WFIR Class Reference

#include <wfir.h>

Public Types

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 Public Member Functions

static void BasicFIR (double *FirCoeff, int NumTaps, TPassTypeName PassType, double OmegaC, double BW, TWindowType WindowType, double WinBeta)
 

Static Private Member Functions

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)
 

Detailed Description

Definition at line 58 of file wfir.h.

Member Enumeration Documentation

◆ TPassTypeName

Enumerator
LPF 
HPF 
BPF 
NOTCH 

Definition at line 61 of file wfir.h.

62  {
63  LPF, HPF, BPF, NOTCH
64  };
Definition: wfir.h:63
Definition: wfir.h:63
Definition: wfir.h:63

◆ TWindowType

Enumerator
wtNONE 
wtKAISER 
wtSINC 
wtHANNING 
wtHAMMING 
wtBLACKMAN 
wtFLATTOP 
wtBLACKMAN_HARRIS 
wtBLACKMAN_NUTTALL 
wtNUTTALL 
wtKAISER_BESSEL 
wtTRAPEZOID 
wtGAUSS 
wtSINE 
wtTEST 

Definition at line 66 of file wfir.h.

Member Function Documentation

◆ BasicFIR()

void WFIR::BasicFIR ( double *  FirCoeff,
int  NumTaps,
TPassTypeName  PassType,
double  OmegaC,
double  BW,
TWindowType  WindowType,
double  WinBeta 
)
static

Definition at line 19 of file wfir.cpp.

References BPF, cos(), HPF, LPF, M_PI, NOTCH, Sinc(), and WindowData().

Referenced by DevicePlutoSDRBox::formatFIRCoefficients().

21 {
22  int j;
23  double Arg, OmegaLow, OmegaHigh;
24 
25  switch (PassType)
26  {
27  case LPF:
28  for (j = 0; j < NumTaps; j++)
29  {
30  Arg = (double) j - (double) (NumTaps - 1) / 2.0;
31  FirCoeff[j] = OmegaC * Sinc(OmegaC * Arg * M_PI);
32  }
33  break;
34 
35  case HPF:
36  if (NumTaps % 2 == 1) // Odd tap counts
37  {
38  for (j = 0; j < NumTaps; j++)
39  {
40  Arg = (double) j - (double) (NumTaps - 1) / 2.0;
41  FirCoeff[j] = Sinc(Arg * M_PI)
42  - OmegaC * Sinc(OmegaC * Arg * M_PI);
43  }
44  }
45 
46  else // Even tap counts
47  {
48  for (j = 0; j < NumTaps; j++)
49  {
50  Arg = (double) j - (double) (NumTaps - 1) / 2.0;
51  if (Arg == 0.0)
52  FirCoeff[j] = 0.0;
53  else
54  FirCoeff[j] = cos(OmegaC * Arg * M_PI) / M_PI / Arg
55  + cos(Arg * M_PI);
56  }
57  }
58  break;
59 
60  case BPF:
61  OmegaLow = OmegaC - BW / 2.0;
62  OmegaHigh = OmegaC + BW / 2.0;
63  for (j = 0; j < NumTaps; j++)
64  {
65  Arg = (double) j - (double) (NumTaps - 1) / 2.0;
66  if (Arg == 0.0)
67  FirCoeff[j] = 0.0;
68  else
69  FirCoeff[j] = (cos(OmegaLow * Arg * M_PI)
70  - cos(OmegaHigh * Arg * M_PI)) / M_PI / Arg;
71  }
72  break;
73 
74  case NOTCH: // If NumTaps is even for Notch filters, the response at Pi is attenuated.
75  OmegaLow = OmegaC - BW / 2.0;
76  OmegaHigh = OmegaC + BW / 2.0;
77  for (j = 0; j < NumTaps; j++)
78  {
79  Arg = (double) j - (double) (NumTaps - 1) / 2.0;
80  FirCoeff[j] = Sinc(Arg * M_PI)
81  - OmegaHigh * Sinc(OmegaHigh * Arg * M_PI)
82  - OmegaLow * Sinc(OmegaLow * Arg * M_PI);
83  }
84  break;
85  }
86 
87  // WindowData can be used to window data before an FFT. When used for FIR filters we set
88  // Alpha = 0.0 to prevent a flat top on the window and
89  // set UnityGain = false to prevent the window gain from getting set to unity.
90  WindowData(FirCoeff, NumTaps, WindowType, 0.0, WinBeta, false);
91 
92 }
Fixed< IntType, IntBits > cos(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2271
#define M_PI
Definition: wfir.cpp:14
static void WindowData(double *Data, int N, TWindowType WindowType, double Alpha, double Beta, bool UnityGain)
Definition: wfir.cpp:173
Definition: wfir.h:63
Definition: wfir.h:63
Definition: wfir.h:63
static double Sinc(double x)
Definition: wfir.cpp:115
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Bessel()

double WFIR::Bessel ( double  x)
staticprivate

Definition at line 97 of file wfir.cpp.

References i.

Referenced by WindowData().

98 {
99  double Sum = 0.0, XtoIpower;
100  int i, j, Factorial;
101  for (i = 1; i < 10; i++)
102  {
103  XtoIpower = pow(x / 2.0, (double) i);
104  Factorial = 1;
105  for (j = 1; j <= i; j++)
106  Factorial *= j;
107  Sum += pow(XtoIpower / (double) Factorial, 2.0);
108  }
109  return (1.0 + Sum);
110 }
int32_t i
Definition: decimators.h:244
+ Here is the caller graph for this function:

◆ Sinc()

double WFIR::Sinc ( double  x)
staticprivate

Definition at line 115 of file wfir.cpp.

References sin().

Referenced by BasicFIR(), and WindowData().

116 {
117  if (x > -1.0E-5 && x < 1.0E-5)
118  return (1.0);
119  return (sin(x) / x);
120 }
Fixed< IntType, IntBits > sin(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2265
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ WindowData()

void WFIR::WindowData ( double *  Data,
int  N,
TWindowType  WindowType,
double  Alpha,
double  Beta,
bool  UnityGain 
)
staticprivate

Definition at line 173 of file wfir.cpp.

References Bessel(), cos(), exp(), M_2PI, M_PI, sin(), Sinc(), sqrt(), wtBLACKMAN, wtBLACKMAN_HARRIS, wtBLACKMAN_NUTTALL, wtFLATTOP, wtGAUSS, wtHAMMING, wtHANNING, wtKAISER, wtKAISER_BESSEL, wtNONE, wtNUTTALL, wtSINC, wtSINE, and wtTRAPEZOID.

Referenced by BasicFIR().

175 {
176  if (WindowType == wtNONE)
177  return;
178 
179  int j, M, TopWidth;
180  double dM, *WinCoeff;
181 
182  if (WindowType == wtKAISER || WindowType == wtFLATTOP)
183  Alpha = 0.0;
184 
185  if (Alpha < 0.0)
186  Alpha = 0.0;
187  if (Alpha > 1.0)
188  Alpha = 1.0;
189 
190  if (Beta < 0.0)
191  Beta = 0.0;
192  if (Beta > 10.0)
193  Beta = 10.0;
194 
195  WinCoeff = new (std::nothrow) double[N + 2];
196  if (WinCoeff == 0)
197  {
198  std::cerr
199  << "Failed to allocate memory in FFTFunctions::WindowFFTData() "
200  << std::endl;
201  return;
202  }
203 
204  TopWidth = (int) (Alpha * (double) N);
205  if (TopWidth % 2 != 0)
206  TopWidth++;
207  if (TopWidth > N)
208  TopWidth = N;
209  M = N - TopWidth;
210  dM = M + 1;
211 
212  // Calculate the window for N/2 points, then fold the window over (at the bottom).
213  // TopWidth points will be set to 1.
214  if (WindowType == wtKAISER)
215  {
216  double Arg;
217  for (j = 0; j < M; j++)
218  {
219  Arg = Beta * sqrt(1.0 - pow(((double) (2 * j + 2) - dM) / dM, 2.0));
220  WinCoeff[j] = Bessel(Arg) / Bessel(Beta);
221  }
222  }
223 
224  else if (WindowType == wtSINC) // Lanczos
225  {
226  for (j = 0; j < M; j++)
227  WinCoeff[j] = Sinc((double) (2 * j + 1 - M) / dM * M_PI);
228  for (j = 0; j < M; j++)
229  WinCoeff[j] = pow(WinCoeff[j], Beta);
230  }
231 
232  else if (WindowType == wtSINE) // Hanning if Beta = 2
233  {
234  for (j = 0; j < M / 2; j++)
235  WinCoeff[j] = sin((double) (j + 1) * M_PI / dM);
236  for (j = 0; j < M / 2; j++)
237  WinCoeff[j] = pow(WinCoeff[j], Beta);
238  }
239 
240  else if (WindowType == wtHANNING)
241  {
242  for (j = 0; j < M / 2; j++)
243  WinCoeff[j] = 0.5 - 0.5 * cos((double) (j + 1) * M_2PI / dM);
244  }
245 
246  else if (WindowType == wtHAMMING)
247  {
248  for (j = 0; j < M / 2; j++)
249  WinCoeff[j] = 0.54 - 0.46 * cos((double) (j + 1) * M_2PI / dM);
250  }
251 
252  else if (WindowType == wtBLACKMAN)
253  {
254  for (j = 0; j < M / 2; j++)
255  {
256  WinCoeff[j] = 0.42 - 0.50 * cos((double) (j + 1) * M_2PI / dM)
257  + 0.08 * cos((double) (j + 1) * M_2PI * 2.0 / dM);
258  }
259  }
260 
261  // See: http://www.bth.se/fou/forskinfo.nsf/0/130c0940c5e7ffcdc1256f7f0065ac60/$file/ICOTA_2004_ttr_icl_mdh.pdf
262  else if (WindowType == wtFLATTOP)
263  {
264  for (j = 0; j <= M / 2; j++)
265  {
266  WinCoeff[j] = 1.0
267  - 1.93293488969227 * cos((double) (j + 1) * M_2PI / dM)
268  + 1.28349769674027
269  * cos((double) (j + 1) * M_2PI * 2.0 / dM)
270  - 0.38130801681619
271  * cos((double) (j + 1) * M_2PI * 3.0 / dM)
272  + 0.02929730258511
273  * cos((double) (j + 1) * M_2PI * 4.0 / dM);
274  }
275  }
276 
277  else if (WindowType == wtBLACKMAN_HARRIS)
278  {
279  for (j = 0; j < M / 2; j++)
280  {
281  WinCoeff[j] = 0.35875 - 0.48829 * cos((double) (j + 1) * M_2PI / dM)
282  + 0.14128 * cos((double) (j + 1) * M_2PI * 2.0 / dM)
283  - 0.01168 * cos((double) (j + 1) * M_2PI * 3.0 / dM);
284  }
285  }
286 
287  else if (WindowType == wtBLACKMAN_NUTTALL)
288  {
289  for (j = 0; j < M / 2; j++)
290  {
291  WinCoeff[j] = 0.3535819
292  - 0.4891775 * cos((double) (j + 1) * M_2PI / dM)
293  + 0.1365995 * cos((double) (j + 1) * M_2PI * 2.0 / dM)
294  - 0.0106411 * cos((double) (j + 1) * M_2PI * 3.0 / dM);
295  }
296  }
297 
298  else if (WindowType == wtNUTTALL)
299  {
300  for (j = 0; j < M / 2; j++)
301  {
302  WinCoeff[j] = 0.355768
303  - 0.487396 * cos((double) (j + 1) * M_2PI / dM)
304  + 0.144232 * cos((double) (j + 1) * M_2PI * 2.0 / dM)
305  - 0.012604 * cos((double) (j + 1) * M_2PI * 3.0 / dM);
306  }
307  }
308 
309  else if (WindowType == wtKAISER_BESSEL)
310  {
311  for (j = 0; j <= M / 2; j++)
312  {
313  WinCoeff[j] = 0.402 - 0.498 * cos(M_2PI * (double) (j + 1) / dM)
314  + 0.098 * cos(2.0 * M_2PI * (double) (j + 1) / dM)
315  + 0.001 * cos(3.0 * M_2PI * (double) (j + 1) / dM);
316  }
317  }
318 
319  else if (WindowType == wtTRAPEZOID) // Rectangle for Alpha = 1 Triangle for Alpha = 0
320  {
321  int K = M / 2;
322  if (M % 2)
323  K++;
324  for (j = 0; j < K; j++)
325  WinCoeff[j] = (double) (j + 1) / (double) K;
326  }
327 
328  // This definition is from http://en.wikipedia.org/wiki/Window_function (Gauss Generalized normal window)
329  // We set their p = 2, and use Alpha in the numerator, instead of Sigma in the denominator, as most others do.
330  // Alpha = 2.718 puts the Gauss window response midway between the Hanning and the Flattop (basically what we want).
331  // It also gives the same BW as the Gauss window used in the HP 89410A Vector Signal Analyzer.
332  // Alpha = 1.8 puts it quite close to the Hanning.
333  else if (WindowType == wtGAUSS)
334  {
335  for (j = 0; j < M / 2; j++)
336  {
337  WinCoeff[j] = ((double) (j + 1) - dM / 2.0) / (dM / 2.0) * 2.7183;
338  WinCoeff[j] *= WinCoeff[j];
339  WinCoeff[j] = exp(-WinCoeff[j]);
340  }
341  }
342 
343  else // Error.
344  {
345  std::cerr << "Incorrect window type in WindowFFTData" << std::endl;
346  delete[] WinCoeff;
347  return;
348  }
349 
350  // Fold the coefficients over.
351  for (j = 0; j < M / 2; j++)
352  WinCoeff[N - j - 1] = WinCoeff[j];
353 
354  // This is the flat top if Alpha > 0. Cannot be applied to a Kaiser or Flat Top.
355  if (WindowType != wtKAISER && WindowType != wtFLATTOP)
356  {
357  for (j = M / 2; j < N - M / 2; j++)
358  WinCoeff[j] = 1.0;
359  }
360 
361  // This will set the gain of the window to 1. Only the Flattop window has unity gain by design.
362  if (UnityGain)
363  {
364  double Sum = 0.0;
365  for (j = 0; j < N; j++)
366  Sum += WinCoeff[j];
367  Sum /= (double) N;
368  if (Sum != 0.0)
369  for (j = 0; j < N; j++)
370  WinCoeff[j] /= Sum;
371  }
372 
373  // Apply the window to the data.
374  for (j = 0; j < N; j++)
375  Data[j] *= WinCoeff[j];
376 
377  delete[] WinCoeff;
378 
379 }
#define M_2PI
Definition: wfir.cpp:15
Fixed< IntType, IntBits > cos(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2271
#define M_PI
Definition: wfir.cpp:14
Fixed< IntType, IntBits > exp(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2289
Fixed< IntType, IntBits > sin(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2265
Fixed< IntType, IntBits > sqrt(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2283
static double Bessel(double x)
Definition: wfir.cpp:97
static double Sinc(double x)
Definition: wfir.cpp:115
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

The documentation for this class was generated from the following files: