r8brain-free-src
High-quality pro audio sample rate converter library
 
Loading...
Searching...
No Matches
CDSPSincFilterGen.h
Go to the documentation of this file.
1//$ nobt
2//$ nocpp
3
16
17#ifndef R8B_CDSPSINCFILTERGEN_INCLUDED
18#define R8B_CDSPSINCFILTERGEN_INCLUDED
19
20#include "r8bbase.h"
21
22namespace r8b {
23
31
33{
34public:
35 double Len2;
38 double Len2i;
43 int fl2;
46
47 double Freq1;
49 double Freq2;
52 double FracDelay;
57
61
71
72 typedef double( CDSPSincFilterGen ::* CWindowFunc )();
74
87
89 const double* const Params = R8B_NULL, const bool UsePower = false )
90 {
91 R8BASSERT( Len2 >= 2.0 );
92
93 fl2 = (int) floor( Len2 );
94 KernelLen = fl2 + fl2 + 1;
95
96 setWindow( WinType, Params, UsePower, true );
97 }
98
113
115 const double* const Params = R8B_NULL, const bool UsePower = false )
116 {
117 R8BASSERT( Len2 >= 2.0 );
118
119 fl2 = (int) floor( Len2 );
120 KernelLen = fl2 + fl2 + 1;
121
122 setWindow( WinType, Params, UsePower, true );
123 }
124
140
142 const double* const Params = R8B_NULL, const bool UsePower = false )
143 {
144 R8BASSERT( Len2 >= 2.0 );
145
146 fl2 = (int) floor( Len2 );
147 KernelLen = fl2 + fl2 + 1;
148
149 setWindow( WinType, Params, UsePower, true );
150 }
151
167
169 const double* const Params = R8B_NULL, const bool UsePower = false )
170 {
171 R8BASSERT( Len2 >= 2.0 );
172
173 fl2 = (int) ceil( Len2 );
174 KernelLen = fl2 + fl2;
175
176 setWindow( WinType, Params, UsePower, false, FracDelay );
177 }
178
182
184 {
185 return( 0.5 + 0.5 * w1.generate() );
186 }
187
191
193 {
194 return( 0.54 + 0.46 * w1.generate() );
195 }
196
200
202 {
203 return( 0.42 + 0.5 * w1.generate() + 0.08 * w2.generate() );
204 }
205
209
211 {
212 return( 0.355768 + 0.487396 * w1.generate() +
213 0.144232 * w2.generate() + 0.012604 * w3.generate() );
214 }
215
219
221 {
222 return( 0.3635819 + 0.4891775 * w1.generate() +
223 0.1365995 * w2.generate() + 0.0106411 * w3.generate() );
224 }
225
229
231 {
232 const double n = 1.0 - sqr( wn * Len2i + KaiserLen2Frac );
233 wn++;
234
235 if( n <= 0.0 )
236 {
237 return( 0.0 );
238 }
239
240 return( besselI0( KaiserBeta * sqrt( n )) * KaiserMul );
241 }
242
246
248 {
249 const double f = exp( -0.5 * sqr( wn * GaussianSigmaI +
250 GaussianSigmaFrac ));
251
252 wn++;
253
254 return( f );
255 }
256
263
264 void generateWindow( double* op,
265 CWindowFunc wfunc = &CDSPSincFilterGen :: calcWindowBlackman )
266 {
267 op += fl2;
268 double* op2 = op;
269
270 int l = fl2;
271
272 if( Power < 0.0 )
273 {
274 *op = ( *this.*wfunc )();
275
276 while( l > 0 )
277 {
278 const double v = ( *this.*wfunc )();
279
280 op++;
281 op2--;
282 *op = v;
283 *op2 = v;
284 l--;
285 }
286 }
287 else
288 {
289 *op = pow_a(( *this.*wfunc )(), Power );
290
291 while( l > 0 )
292 {
293 const double v = pow_a(( *this.*wfunc )(), Power );
294
295 op++;
296 op2--;
297 *op = v;
298 *op2 = v;
299 l--;
300 }
301 }
302 }
303
311
312 void generateBand( double* op,
313 CWindowFunc wfunc = &CDSPSincFilterGen :: calcWindowBlackman )
314 {
315 CSineGen f2( Freq2, 0.0, 1.0 / R8B_PI );
316 f2.generate();
317
318 op += fl2;
319 double* op2 = op;
320 const double pw = Power;
321 int t = 1;
322
323 if( Freq1 < 2.3e-13 )
324 {
325 if( pw < 0.0 )
326 {
327 *op = Freq2 * ( *this.*wfunc )() / R8B_PI;
328
329 while( t <= fl2 )
330 {
331 const double v = f2.generate() * ( *this.*wfunc )() / t;
332 op++;
333 op2--;
334 *op = v;
335 *op2 = v;
336 t++;
337 }
338 }
339 else
340 {
341 *op = Freq2 * pow_a(( *this.*wfunc )(), pw ) / R8B_PI;
342
343 while( t <= fl2 )
344 {
345 const double v = f2.generate() *
346 pow_a(( *this.*wfunc )(), pw ) / t;
347
348 op++;
349 op2--;
350 *op = v;
351 *op2 = v;
352 t++;
353 }
354 }
355 }
356 else
357 {
358 CSineGen f1( Freq1, 0.0, 1.0 / R8B_PI );
359 f1.generate();
360
361 if( pw < 0.0 )
362 {
363 *op = ( Freq2 - Freq1 ) * ( *this.*wfunc )() / R8B_PI;
364
365 while( t <= fl2 )
366 {
367 const double v = ( f2.generate() - f1.generate() ) *
368 ( *this.*wfunc )() / t;
369
370 op++;
371 op2--;
372 *op = v;
373 *op2 = v;
374 t++;
375 }
376 }
377 else
378 {
379 *op = ( Freq2 - Freq1 ) *
380 pow_a(( *this.*wfunc )(), pw ) / R8B_PI;
381
382 while( t <= fl2 )
383 {
384 const double v = ( f2.generate() - f1.generate() ) *
385 pow_a(( *this.*wfunc )(), pw ) / t;
386
387 op++;
388 op2--;
389 *op = v;
390 *op2 = v;
391 t++;
392 }
393 }
394 }
395 }
396
403
404 void generateHilbert( double* op,
405 CWindowFunc wfunc = &CDSPSincFilterGen :: calcWindowBlackman )
406 {
407 static const double fvalues[ 2 ] = { 0.0, 2.0 / R8B_PI };
408 op += fl2;
409 double* op2 = op;
410
411 ( *this.*wfunc )();
412 *op = 0.0;
413
414 int t = 1;
415
416 if( Power < 0.0 )
417 {
418 while( t <= fl2 )
419 {
420 const double v = fvalues[ t & 1 ] * ( *this.*wfunc )() / t;
421 op++;
422 op2--;
423 *op = v;
424 *op2 = -v;
425 t++;
426 }
427 }
428 else
429 {
430 while( t <= fl2 )
431 {
432 const double v = fvalues[ t & 1 ] *
433 pow_a(( *this.*wfunc )(), Power ) / t;
434
435 op++;
436 op2--;
437 *op = v;
438 *op2 = -v;
439 t++;
440 }
441 }
442 }
443
451
452 void generateFrac( double* op,
453 CWindowFunc wfunc = &CDSPSincFilterGen :: calcWindowBlackman,
454 const int opinc = 1 )
455 {
456 R8BASSERT( opinc != 0 );
457
458 const double pw = Power;
459 const double fd = FracDelay;
460 int t = -fl2;
461
462 if( t + fd < -Len2 )
463 {
464 ( *this.*wfunc )();
465 *op = 0.0;
466 op += opinc;
467 t++;
468 }
469
470 double f = sin( fd * R8B_PI ) / R8B_PI;
471
472 if(( t & 1 ) != 0 )
473 {
474 f = -f;
475 }
476
477 int IsZeroX = ( fabs( fd - 1.0 ) < 2.3e-13 );
478 int mt = 0 - IsZeroX;
479 IsZeroX = ( IsZeroX || fabs( fd ) < 2.3e-13 );
480
481 if( pw < 0.0 )
482 {
483 while( t < mt )
484 {
485 *op = f * ( *this.*wfunc )() / ( t + fd );
486 op += opinc;
487 t++;
488 f = -f;
489 }
490
491 if( IsZeroX ) // t+FracDelay==0
492 {
493 *op = ( *this.*wfunc )();
494 }
495 else
496 {
497 *op = f * ( *this.*wfunc )() / fd; // t==0
498 }
499
500 mt = fl2 - 2;
501
502 while( t < mt )
503 {
504 op += opinc;
505 t++;
506 f = -f;
507 *op = f * ( *this.*wfunc )() / ( t + fd );
508 }
509
510 op += opinc;
511 t++;
512 f = -f;
513 const double ut = t + fd;
514 *op = ( ut > Len2 ? 0.0 : f * ( *this.*wfunc )() / ut );
515 }
516 else
517 {
518 while( t < mt )
519 {
520 *op = f * pow_a(( *this.*wfunc )(), pw ) / ( t + fd );
521 op += opinc;
522 t++;
523 f = -f;
524 }
525
526 if( IsZeroX ) // t+FracDelay==0
527 {
528 *op = pow_a(( *this.*wfunc )(), pw );
529 }
530 else
531 {
532 *op = f * pow_a(( *this.*wfunc )(), pw ) / fd; // t==0
533 }
534
535 mt = fl2 - 2;
536
537 while( t < mt )
538 {
539 op += opinc;
540 t++;
541 f = -f;
542 *op = f * pow_a(( *this.*wfunc )(), pw ) / ( t + fd );
543 }
544
545 op += opinc;
546 t++;
547 f = -f;
548 const double ut = t + FracDelay;
549 *op = ( ut > Len2 ? 0.0 :
550 f * pow_a(( *this.*wfunc )(), pw ) / ut );
551 }
552 }
553
554private:
555 double Power;
557 CSineGen w1;
558 CSineGen w2;
559 CSineGen w3;
560
561 double KaiserBeta;
562 double KaiserMul;
563 double KaiserLen2Frac;
564 double GaussianSigmaI;
566 double GaussianSigmaFrac;
567
568 int wn;
570
585
586 void setWindowKaiser( const double* Params, const bool UsePower,
587 const bool IsCentered )
588 {
589 wn = ( IsCentered ? 0 : -fl2 );
590
591 if( Params == R8B_NULL )
592 {
593 KaiserBeta = 9.5945013206755156;
594 Power = ( UsePower ? 1.9718457932433306 : -1.0 );
595 }
596 else
597 {
598 KaiserBeta = clampr( Params[ 0 ], 1.0, 350.0 );
599 Power = ( UsePower ? fabs( Params[ 1 ]) : -1.0 );
600 }
601
602 KaiserMul = 1.0 / besselI0( KaiserBeta );
603 Len2i = 1.0 / Len2;
604 KaiserLen2Frac = FracDelay * Len2i;
605 }
606
621
622 void setWindowGaussian( const double* Params, const bool UsePower,
623 const bool IsCentered )
624 {
625 wn = ( IsCentered ? 0 : -fl2 );
626
627 if( Params == R8B_NULL )
628 {
629 GaussianSigmaI = 1.0;
630 Power = -1.0;
631 }
632 else
633 {
634 GaussianSigmaI = clampr( fabs( Params[ 0 ]), 1e-1, 100.0 );
635 Power = ( UsePower ? fabs( Params[ 1 ]) : -1.0 );
636 }
637
638 GaussianSigmaI *= Len2;
639 GaussianSigmaI = 1.0 / GaussianSigmaI;
640 GaussianSigmaFrac = FracDelay * GaussianSigmaI;
641 }
642
658
659 void setWindow( const EWindowFunctionType WinType,
660 const double* const Params, const bool UsePower,
661 const bool IsCentered, const double UseFracDelay = 0.0 )
662 {
663 FracDelay = UseFracDelay;
664
665 if( WinType == wftCosine )
666 {
667 if( IsCentered )
668 {
669 w1.init( R8B_PI / Len2, R8B_PId2 );
670 w2.init( R8B_2PI / Len2, R8B_PId2 );
671 w3.init( R8B_3PI / Len2, R8B_PId2 );
672 }
673 else
674 {
675 const double step1 = R8B_PI / Len2;
676 w1.init( step1, R8B_PId2 - step1 * fl2 + step1 * FracDelay );
677
678 const double step2 = R8B_2PI / Len2;
679 w2.init( step2, R8B_PId2 - step2 * fl2 + step2 * FracDelay );
680
681 const double step3 = R8B_3PI / Len2;
682 w3.init( step3, R8B_PId2 - step3 * fl2 + step3 * FracDelay );
683 }
684
685 Power = ( UsePower && Params != R8B_NULL ? Params[ 0 ] : -1.0 );
686 }
687 else
688 if( WinType == wftKaiser )
689 {
690 setWindowKaiser( Params, UsePower, IsCentered );
691 }
692 else
693 if( WinType == wftGaussian )
694 {
695 setWindowGaussian( Params, UsePower, IsCentered );
696 }
697 }
698};
699
700} // namespace r8b
701
702#endif // R8B_CDSPSINCFILTERGEN_INCLUDED
The "base" header file with basic classes and functions.
#define R8B_NULL
The "null pointer" value, portable between C++11 and earlier C++ versions.
Definition r8bbase.h:101
#define R8BASSERT(e)
Assertion macro used to check for certain run-time conditions. By default, no action is taken if asse...
Definition r8bconf.h:28
The "r8brain-free-src" library namespace.
Definition CDSPBlockConvolver.h:22
double pow_a(const double v, const double p)
Power of an absolute value.
Definition r8bbase.h:1154
R8B_CONST double R8B_PI
Equals pi.
Definition r8bbase.h:179
R8B_CONST double R8B_3PI
Equals 3*pi.
Definition r8bbase.h:181
R8B_CONST double R8B_2PI
Equals 2*pi.
Definition r8bbase.h:180
R8B_CONST double R8B_PId2
Equals 0.5*pi.
Definition r8bbase.h:182
double clampr(const double Value, const double minv, const double maxv)
Clamps a value to be within the specified min-max range.
Definition r8bbase.h:1117
double besselI0(const double x)
1st kind, 0th order modified Bessel function of a value.
Definition r8bbase.h:1192
double sqr(const double x)
Returns square ot a value.
Definition r8bbase.h:1140
Sinc function-based FIR filter generator class.
Definition CDSPSincFilterGen.h:33
double calcWindowGaussian()
Returns the next "Gaussian" window function coefficient.
Definition CDSPSincFilterGen.h:247
void initHilbert(const EWindowFunctionType WinType=wftCosine, const double *const Params=R8B_NULL, const bool UsePower=false)
Initializes this structure for Hilbert transformation filter calculation.
Definition CDSPSincFilterGen.h:141
double FracDelay
Fractional delay in the range [0; 1], used only in the generateFrac() function. Note that the FracDel...
Definition CDSPSincFilterGen.h:52
EWindowFunctionType
Window function type.
Definition CDSPSincFilterGen.h:63
@ wftKaiser
Kaiser window function. Requires the "Beta" parameter. The "Power" parameter is optional.
Definition CDSPSincFilterGen.h:66
@ wftCosine
Generalized cosine window function. No parameters required. The "Power" parameter is optional.
Definition CDSPSincFilterGen.h:64
@ wftGaussian
Gaussian window function. Requires the "Sigma" parameter. The "Power" parameter is optional.
Definition CDSPSincFilterGen.h:68
double calcWindowHamming()
Returns the next "Hamming" window function coefficient.
Definition CDSPSincFilterGen.h:192
void generateFrac(double *op, CWindowFunc wfunc=&CDSPSincFilterGen ::calcWindowBlackman, const int opinc=1)
Calculates windowed fractional delay filter kernel.
Definition CDSPSincFilterGen.h:452
void generateHilbert(double *op, CWindowFunc wfunc=&CDSPSincFilterGen ::calcWindowBlackman)
Calculates windowed Hilbert transformer filter kernel.
Definition CDSPSincFilterGen.h:404
int fl2
Internal "half kernel length" value. This value can be used as filter's latency in samples (taps),...
Definition CDSPSincFilterGen.h:43
void generateBand(double *op, CWindowFunc wfunc=&CDSPSincFilterGen ::calcWindowBlackman)
Calculates band-limited windowed sinc function-based filter kernel.
Definition CDSPSincFilterGen.h:312
void initBand(const EWindowFunctionType WinType=wftCosine, const double *const Params=R8B_NULL, const bool UsePower=false)
Initializes this structure for generation of band-limited sinc filter kernel.
Definition CDSPSincFilterGen.h:114
double calcWindowBlackmanNuttall()
Returns the next "Blackman-Nuttall" window function coefficient.
Definition CDSPSincFilterGen.h:220
double Freq1
Required corner circular frequency 1 [0; pi]. Used only in the generateBand() function.
Definition CDSPSincFilterGen.h:47
int KernelLen
Resulting length of the filter kernel, this variable is set after the call to one of the "init" funct...
Definition CDSPSincFilterGen.h:41
void initWindow(const EWindowFunctionType WinType=wftCosine, const double *const Params=R8B_NULL, const bool UsePower=false)
Initializes this structure for generation of a window function, odd-sized.
Definition CDSPSincFilterGen.h:88
double(CDSPSincFilterGen ::* CWindowFunc)()
Window calculation function pointer type.
Definition CDSPSincFilterGen.h:72
double Len2i
Equals 1.0 / Len2, initialized and used by some window functions for optimization (should not be init...
Definition CDSPSincFilterGen.h:38
double calcWindowKaiser()
Returns the next "Kaiser" window function coefficient.
Definition CDSPSincFilterGen.h:230
void initFrac(const EWindowFunctionType WinType=wftCosine, const double *const Params=R8B_NULL, const bool UsePower=false)
Initializes this structure for generation of full-bandwidth fractional delay sinc filter kernel.
Definition CDSPSincFilterGen.h:168
double calcWindowBlackman()
Returns the next "Blackman" window function coefficient.
Definition CDSPSincFilterGen.h:201
double Freq2
Required corner circular frequency 2 [0; pi]. Used only in the generateBand() function....
Definition CDSPSincFilterGen.h:49
double calcWindowNuttall()
Returns the next "Nuttall" window function coefficient.
Definition CDSPSincFilterGen.h:210
void generateWindow(double *op, CWindowFunc wfunc=&CDSPSincFilterGen ::calcWindowBlackman)
Calculates the window function only.
Definition CDSPSincFilterGen.h:264
double Len2
Required half filter kernel's length in samples (can be a fractional value). Final physical kernel le...
Definition CDSPSincFilterGen.h:35
double calcWindowHann()
Returns the next "Hann" window function coefficient.
Definition CDSPSincFilterGen.h:183
Sine signal generator class.
Definition r8bbase.h:667
double generate()
Generates the next sample.
Definition r8bbase.h:741