Flan
CDSPSincFilterGen.h
Go to the documentation of this file.
1 //$ nobt
2 //$ nocpp
3 
16 #ifndef R8B_CDSPSINCFILTERGEN_INCLUDED
17 #define R8B_CDSPSINCFILTERGEN_INCLUDED
18 
19 #include "r8bbase.h"
20 
21 namespace r8b {
22 
32 {
33 public:
34  double Len2;
35  int KernelLen;
39  int fl2;
42 
46  union
47  {
48  struct
49  {
50  double Freq1;
51  double Freq2;
54  };
59 
60  struct
61  {
62  double FracDelay;
63  };
70  };
71 
77  {
79  wftKaiser,
85  };
88 
89  typedef double( CDSPSincFilterGen :: *CWindowFunc )();
90 
106  void initWindow( const EWindowFunctionType WinType = wftCosine,
107  const double* const Params = NULL, const bool UsePower = false )
108  {
109  R8BASSERT( Len2 >= 2.0 );
110 
111  fl2 = (int) floor( Len2 );
112  KernelLen = fl2 + fl2 + 1;
113 
114  setWindow( WinType, Params, UsePower, true );
115  }
116 
131  void initBand( const EWindowFunctionType WinType = wftCosine,
132  const double* const Params = NULL, const bool UsePower = false )
133  {
134  R8BASSERT( Len2 >= 2.0 );
135 
136  fl2 = (int) floor( Len2 );
137  KernelLen = fl2 + fl2 + 1;
138  f1.init( Freq1, 0.0 );
139  f2.init( Freq2, 0.0 );
140 
141  setWindow( WinType, Params, UsePower, true );
142  }
143 
159  const double* const Params = NULL, const bool UsePower = false )
160  {
161  R8BASSERT( Len2 >= 2.0 );
162 
163  fl2 = (int) floor( Len2 );
164  KernelLen = fl2 + fl2 + 1;
165 
166  setWindow( WinType, Params, UsePower, true );
167  }
168 
184  void initFrac( const EWindowFunctionType WinType = wftCosine,
185  const double* const Params = NULL, const bool UsePower = false )
186  {
187  R8BASSERT( Len2 >= 2.0 );
188 
189  fl2 = (int) ceil( Len2 );
190  KernelLen = fl2 + fl2;
191 
192  setWindow( WinType, Params, UsePower, false, FracDelay );
193  }
194 
199  double calcWindowhann()
200  {
201  return( 0.5 + 0.5 * w1.generate() );
202  }
203 
209  {
210  return( 0.54 + 0.46 * w1.generate() );
211  }
212 
218  {
219  return( 0.42 + 0.5 * w1.generate() + 0.08 * w2.generate() );
220  }
221 
227  {
228  return( 0.355768 + 0.487396 * w1.generate() +
229  0.144232 * w2.generate() + 0.012604 * w3.generate() );
230  }
231 
237  {
238  return( 0.3635819 + 0.4891775 * w1.generate() +
239  0.1365995 * w2.generate() + 0.0106411 * w3.generate() );
240  }
241 
247  {
248  const double n = 1.0 - sqr( wn / Len2 + KaiserLen2Frac );
249  wn++;
250 
251  if( n < 0.0 )
252  {
253  return( 0.0 );
254  }
255 
256  return( besselI0( KaiserBeta * sqrt( n )) / KaiserDiv );
257  }
258 
264  {
265  const double f = exp( -0.5 * sqr( wn / GaussianSigma +
267 
268  wn++;
269 
270  return( f );
271  }
272 
280  template< class T >
281  void generateWindow( T* op,
283  {
284  op += fl2;
285  T* op2 = op;
286 
287  int l = fl2;
288 
289  if( Power < 0.0 )
290  {
291  *op = ( *this.*wfunc )();
292 
293  while( l > 0 )
294  {
295  const double v = ( *this.*wfunc )();
296 
297  op++;
298  op2--;
299  *op = v;
300  *op2 = v;
301  l--;
302  }
303  }
304  else
305  {
306  *op = pows(( *this.*wfunc )(), Power );
307 
308  while( l > 0 )
309  {
310  const double v = pows(( *this.*wfunc )(), Power );
311 
312  op++;
313  op2--;
314  *op = v;
315  *op2 = v;
316  l--;
317  }
318  }
319  }
320 
329  template< class T >
330  void generateBand( T* op,
332  {
333  op += fl2;
334  T* op2 = op;
335  f1.generate();
336  f2.generate();
337  int t = 1;
338 
339  if( Power < 0.0 )
340  {
341  *op = ( Freq2 - Freq1 ) * ( *this.*wfunc )() / M_PI;
342 
343  while( t <= fl2 )
344  {
345  const double v = ( f2.generate() - f1.generate() ) *
346  ( *this.*wfunc )() / t / M_PI;
347 
348  op++;
349  op2--;
350  *op = v;
351  *op2 = v;
352  t++;
353  }
354  }
355  else
356  {
357  *op = ( Freq2 - Freq1 ) * pows(( *this.*wfunc )(), Power ) / M_PI;
358 
359  while( t <= fl2 )
360  {
361  const double v = ( f2.generate() - f1.generate() ) *
362  pows(( *this.*wfunc )(), Power ) / t / M_PI;
363 
364  op++;
365  op2--;
366  *op = v;
367  *op2 = v;
368  t++;
369  }
370  }
371  }
372 
380  template< class T >
381  void generateHilbert( T* op,
383  {
384  static const double fvalues[ 2 ] = { 0.0, 2.0 };
385  op += fl2;
386  T* op2 = op;
387 
388  ( *this.*wfunc )();
389  *op = 0.0;
390 
391  int t = 1;
392 
393  if( Power < 0.0 )
394  {
395  while( t <= fl2 )
396  {
397  const double v = fvalues[ t & 1 ] *
398  ( *this.*wfunc )() / t / M_PI;
399 
400  op++;
401  op2--;
402  *op = v;
403  *op2 = -v;
404  t++;
405  }
406  }
407  else
408  {
409  while( t <= fl2 )
410  {
411  const double v = fvalues[ t & 1 ] *
412  pows( ( *this.*wfunc )(), Power ) / t / M_PI;
413 
414  op++;
415  op2--;
416  *op = v;
417  *op2 = -v;
418  t++;
419  }
420  }
421  }
422 
431  template< class T >
432  void generateFrac( T* op,
434  const int opinc = 1 )
435  {
436  R8BASSERT( opinc != 0 );
437 
438  double f[ 2 ];
439  f[ 0 ] = sin( FracDelay * M_PI );
440  f[ 1 ] = -f[ 0 ];
441 
442  int t = -fl2;
443 
444  if( t + FracDelay < -Len2 )
445  {
446  ( *this.*wfunc )();
447  *op = 0.0;
448  op += opinc;
449  t++;
450  }
451 
452  int mt = ( FracDelay >= 1.0 - 1e-13 && FracDelay <= 1.0 + 1e-13 ?
453  -1 : 0 );
454 
455  if( Power < 0.0 )
456  {
457  while( t < mt )
458  {
459  *op = f[ t & 1 ] * ( *this.*wfunc )() / ( t + FracDelay ) /
460  M_PI;
461 
462  op += opinc;
463  t++;
464  }
465 
466  double ut = t + FracDelay;
467  *op = ( fabs( ut ) <= 1e-13 ? ( *this.*wfunc )() :
468  f[ t & 1 ] * ( *this.*wfunc )() / ut / M_PI );
469 
470  mt = fl2 - 2;
471 
472  while( t < mt )
473  {
474  op += opinc;
475  t++;
476  *op = f[ t & 1 ] * ( *this.*wfunc )() / ( t + FracDelay ) /
477  M_PI;
478  }
479 
480  op += opinc;
481  t++;
482  ut = t + FracDelay;
483  *op = ( ut > Len2 ? 0.0 :
484  f[ t & 1 ] * ( *this.*wfunc )() / ut / M_PI );
485  }
486  else
487  {
488  while( t < mt )
489  {
490  *op = f[ t & 1 ] * pows( ( *this.*wfunc )(), Power ) /
491  ( t + FracDelay ) / M_PI;
492 
493  op += opinc;
494  t++;
495  }
496 
497  double ut = t + FracDelay;
498  *op = ( fabs( ut ) <= 1e-13 ? pows( ( *this.*wfunc )(), Power ) :
499  f[ t & 1 ] * pows( ( *this.*wfunc )(), Power ) / ut / M_PI );
500 
501  mt = fl2 - 2;
502 
503  while( t < mt )
504  {
505  op += opinc;
506  t++;
507  *op = f[ t & 1 ] * pows( ( *this.*wfunc )(), Power ) /
508  ( t + FracDelay ) / M_PI;
509  }
510 
511  op += opinc;
512  t++;
513  ut = t + FracDelay;
514  *op = ( ut > Len2 ? 0.0 :
515  f[ t & 1 ] * pows( ( *this.*wfunc )(), Power ) / ut / M_PI );
516  }
517  }
518 
519 private:
520  double Power;
521  CSineGen f1;
524  CSineGen f2;
526  int wn;
528  CSineGen w1;
531  CSineGen w2;
533  CSineGen w3;
535 
537  union
538  {
539  struct
540  {
541  double KaiserBeta;
542  double KaiserDiv;
545  double KaiserLen2Frac;
547  };
549 
550  struct
551  {
552  double GaussianSigma;
553  double GaussianSigmaFrac;
556  };
558  };
559 
572  void setWindowKaiser( const double* Params, const bool UsePower,
573  const bool IsCentered )
574  {
575  wn = ( IsCentered ? 0 : -fl2 );
576 
577  if( Params == NULL )
578  {
579  KaiserBeta = 9.5945013206755156;
580  Power = ( UsePower ? 1.9718457932433306 : -1.0 );
581  }
582  else
583  {
584  KaiserBeta = clampr( Params[ 0 ], 1.0, 350.0 );
585  Power = ( UsePower ? fabs( Params[ 1 ]) : -1.0 );
586  }
587 
590  }
591 
605  void setWindowGaussian( const double* Params, const bool UsePower,
606  const bool IsCentered )
607  {
608  wn = ( IsCentered ? 0 : -fl2 );
609 
610  if( Params == NULL )
611  {
612  GaussianSigma = 1.0;
613  Power = -1.0;
614  }
615  else
616  {
617  GaussianSigma = clampr( fabs( Params[ 0 ]), 1e-1, 100.0 );
618  Power = ( UsePower ? fabs( Params[ 1 ]) : -1.0 );
619  }
620 
621  GaussianSigma *= Len2;
623  }
624 
641  void setWindow( const EWindowFunctionType WinType,
642  const double* const Params, const bool UsePower,
643  const bool IsCentered, const double UseFracDelay = 0.0 )
644  {
645  FracDelay = UseFracDelay;
646 
647  if( WinType == wftCosine )
648  {
649  if( IsCentered )
650  {
651  w1.init( M_PI / Len2, M_PI * 0.5 );
652  w2.init( M_2PI / Len2, M_PI * 0.5 );
653  w3.init( M_3PI / Len2, M_PI * 0.5 );
654  }
655  else
656  {
657  const double step1 = M_PI / Len2;
658  w1.init( step1, M_PI * 0.5 - step1 * fl2 +
659  step1 * FracDelay );
660 
661  const double step2 = M_2PI / Len2;
662  w2.init( step2, M_PI * 0.5 - step2 * fl2 +
663  step2 * FracDelay );
664 
665  const double step3 = M_3PI / Len2;
666  w3.init( step3, M_PI * 0.5 - step3 * fl2 +
667  step3 * FracDelay );
668  }
669 
670  Power = ( UsePower && Params != NULL ? Params[ 0 ] : -1.0 );
671  }
672  else
673  if( WinType == wftKaiser )
674  {
675  setWindowKaiser( Params, UsePower, IsCentered );
676  }
677  else
678  if( WinType == wftGaussian )
679  {
680  setWindowGaussian( Params, UsePower, IsCentered );
681  }
682  }
683 };
684 
685 } // namespace r8b
686 
687 #endif // R8B_CDSPSINCFILTERGEN_INCLUDED
Sine signal generator class.
Definition: r8bbase.h:674
double clampr(const double Value, const double minv, const double maxv)
Function "clamps" (clips) the specified value so that it is not lesser than "minv", and not greater than "maxv".
Definition: r8bbase.h:1151
#define M_2PI
The M_2PI macro equals to "2 * pi" constant, fits 53-bit floating point mantissa. ...
Definition: r8bbase.h:103
Generalized cosine window function.
Definition: CDSPSincFilterGen.h:78
double calcWindowHamming()
Definition: CDSPSincFilterGen.h:208
#define R8BASSERT(e)
Assertion macro used to check for certain run-time conditions.
Definition: r8bconf.h:72
void initFrac(const EWindowFunctionType WinType=wftCosine, const double *const Params=NULL, const bool UsePower=false)
Function initializes *this structure for generation of full-bandwidth fractional delay sinc filter ke...
Definition: CDSPSincFilterGen.h:184
double Freq1
Required corner circular frequency 1 [0; pi].
Definition: CDSPSincFilterGen.h:50
void generateHilbert(T *op, CWindowFunc wfunc=&CDSPSincFilterGen ::calcWindowBlackman)
Function calculates windowed Hilbert transformer filter kernel.
Definition: CDSPSincFilterGen.h:381
double FracDelay
Fractional delay in the range [0; 1], used.
Definition: CDSPSincFilterGen.h:62
void initWindow(const EWindowFunctionType WinType=wftCosine, const double *const Params=NULL, const bool UsePower=false)
Function initializes *this structure for generation of a window function, odd-sized.
Definition: CDSPSincFilterGen.h:106
Sinc function-based FIR filter generator class.
Definition: CDSPSincFilterGen.h:31
int fl2
Internal "half kernel length" value.
Definition: CDSPSincFilterGen.h:41
Gaussian window function.
Definition: CDSPSincFilterGen.h:84
void generateWindow(T *op, CWindowFunc wfunc=&CDSPSincFilterGen ::calcWindowBlackman)
Function calculates window function only.
Definition: CDSPSincFilterGen.h:281
void generateBand(T *op, CWindowFunc wfunc=&CDSPSincFilterGen ::calcWindowBlackman)
Function calculates band-limited windowed sinc function-based filter kernel.
Definition: CDSPSincFilterGen.h:330
double(CDSPSincFilterGen ::* CWindowFunc)()
Window.
Definition: CDSPSincFilterGen.h:89
double KaiserDiv
Kaiser window function&#39;s divisor.
Definition: CDSPSincFilterGen.h:544
double calcWindowBlackmanNuttall()
Definition: CDSPSincFilterGen.h:236
void initBand(const EWindowFunctionType WinType=wftCosine, const double *const Params=NULL, const bool UsePower=false)
Function initializes *this structure for generation of band-limited sinc filter kernel.
Definition: CDSPSincFilterGen.h:131
The "base" inclusion file with basic classes and functions.
double GaussianSigma
Gaussian window function&#39;s "Sigma".
Definition: CDSPSincFilterGen.h:552
double KaiserBeta
Kaiser window function&#39;s "Beta".
Definition: CDSPSincFilterGen.h:541
int KernelLen
Resulting length of the filter kernel, this variable.
Definition: CDSPSincFilterGen.h:38
double KaiserLen2Frac
Equals FracDelay / Len2.
Definition: CDSPSincFilterGen.h:546
double GaussianSigmaFrac
Equals FracDelay / GaussianSigma.
Definition: CDSPSincFilterGen.h:555
#define M_3PI
The M_3PI macro equals to "3 * pi" constant, fits 53-bit floating point mantissa. ...
Definition: r8bbase.h:112
double calcWindowNuttall()
Definition: CDSPSincFilterGen.h:226
double pows(const double v, const double p)
Definition: r8bbase.h:1185
double calcWindowBlackman()
Definition: CDSPSincFilterGen.h:217
double sqr(const double x)
Definition: r8bbase.h:1174
#define M_PI
The macro equals to "pi" constant, fits 53-bit floating point mantissa.
Definition: r8bbase.h:94
double calcWindowhann()
Definition: CDSPSincFilterGen.h:199
double Freq2
Required corner circular frequency 2 [0; pi].
Definition: CDSPSincFilterGen.h:53
double Len2
Required half filter kernel&#39;s length in samples (can be.
Definition: CDSPSincFilterGen.h:34
EWindowFunctionType
Window function type.
Definition: CDSPSincFilterGen.h:76
Kaiser window function.
Definition: CDSPSincFilterGen.h:81
void generateFrac(T *op, CWindowFunc wfunc=&CDSPSincFilterGen ::calcWindowBlackman, const int opinc=1)
Function calculates windowed fractional delay filter kernel.
Definition: CDSPSincFilterGen.h:432
double generate()
Definition: r8bbase.h:749
double besselI0(const double x)
Definition: r8bbase.h:1216
The "r8brain-free-src" library namespace.
Definition: CDSPBlockConvolver.h:21
void init(const double si, const double ph)
Function initializes *this sine signal generator.
Definition: r8bbase.h:721
void initHilbert(const EWindowFunctionType WinType=wftCosine, const double *const Params=NULL, const bool UsePower=false)
Function initializes *this structure for Hilbert transformation filter calculation.
Definition: CDSPSincFilterGen.h:158
double calcWindowKaiser()
Definition: CDSPSincFilterGen.h:246
double calcWindowGaussian()
Definition: CDSPSincFilterGen.h:263