r8brain-free-src
High-quality pro audio sample rate converter library
 
Loading...
Searching...
No Matches
CDSPFIRFilter.h
Go to the documentation of this file.
1//$ nobt
2//$ nocpp
3
15
16#ifndef R8B_CDSPFIRFILTER_INCLUDED
17#define R8B_CDSPFIRFILTER_INCLUDED
18
19#include "CDSPSincFilterGen.h"
20#include "CDSPRealFFT.h"
21
22namespace r8b {
23
27
48
57
58class CDSPFIRFilter : public R8B_BASECLASS,
59 private CSinglyLinkedListItem< CDSPFIRFilter >
60{
61 R8BNOCTOR( CDSPFIRFilter )
62
63 friend class CSinglyLinkedListItem< CDSPFIRFilter >;
64 friend class CDSPFIRFilterCache;
65
66public:
71
72 static double getLPMinTransBand()
73 {
74 return( 0.5 );
75 }
76
81
82 static double getLPMaxTransBand()
83 {
84 return( 45.0 );
85 }
86
91
92 static double getLPMinAtten()
93 {
94 return( 49.0 );
95 }
96
101
102 static double getLPMaxAtten()
103 {
104 return( 218.0 );
105 }
106
111
112 bool isZeroPhase() const
113 {
114 return( IsZeroPhase );
115 }
116
120
121 int getLatency() const
122 {
123 return( Latency );
124 }
125
130
131 double getLatencyFrac() const
132 {
133 return( LatencyFrac );
134 }
135
140
141 int getKernelLen() const
142 {
143 return( KernelLen );
144 }
145
152
153 int getBlockLenBits() const
154 {
155 return( BlockLenBits );
156 }
157
170
172 {
173 return( KernelBlockFFT );
174 }
175
187
189 const realfft_t im ) const
190 {
191 return( dsnRe * re - dsnIm * im );
192 }
193
200
201 void unref();
202
203private:
204 double ReqNormFreq;
205 double ReqTransBand;
207 double ReqAtten;
209 EDSPFilterPhaseResponse ReqPhase;
210 double ReqGain;
211 int ReqDownShift;
212 int RefCount;
213 bool IsZeroPhase;
215 int Latency;
216 double LatencyFrac;
217 int KernelLen;
218 int BlockLenBits;
221 CFixedBuffer< double > KernelBlock;
225 realfft_t* KernelBlockFFT;
227 realfft_t dsnRe;
228 realfft_t dsnIm;
229
231 : RefCount( 1 )
232 {
233 }
234
241
242 void buildLPFilter( const double* const ExtAttenCorrs )
243 {
244 const double tb = ReqTransBand * 0.01;
245 double pwr;
246 double fo1;
247 double hl;
248 double atten = -ReqAtten;
249
250 if( tb >= 0.25 )
251 {
252 if( ReqAtten >= 117.0 )
253 {
254 atten -= 1.60;
255 }
256 else
257 if( ReqAtten >= 60.0 )
258 {
259 atten -= 1.91;
260 }
261 else
262 {
263 atten -= 2.25;
264 }
265 }
266 else
267 if( tb >= 0.10 )
268 {
269 if( ReqAtten >= 117.0 )
270 {
271 atten -= 0.69;
272 }
273 else
274 if( ReqAtten >= 60.0 )
275 {
276 atten -= 0.73;
277 }
278 else
279 {
280 atten -= 1.13;
281 }
282 }
283 else
284 {
285 if( ReqAtten >= 117.0 )
286 {
287 atten -= 0.21;
288 }
289 else
290 if( ReqAtten >= 60.0 )
291 {
292 atten -= 0.25;
293 }
294 else
295 {
296 atten -= 0.36;
297 }
298 }
299
300 static const int AttenCorrCount = 264;
301 static const double AttenCorrMin = 49.0;
302 static const double AttenCorrDiff = 176.25;
303 int AttenCorr = (int) floor(( -atten - AttenCorrMin ) *
304 AttenCorrCount / AttenCorrDiff + 0.5 );
305
306 AttenCorr = min( AttenCorrCount, max( 0, AttenCorr ));
307
308 if( ExtAttenCorrs != R8B_NULL )
309 {
310 atten -= ExtAttenCorrs[ AttenCorr ];
311 }
312 else
313 if( tb >= 0.25 )
314 {
315 static const double AttenCorrScale = 101.0;
316 static const signed char AttenCorrs[] = {
317 -127, -127, -125, -125, -122, -119, -115, -110, -104, -97,
318 -91, -82, -75, -24, -16, -6, 4, 14, 24, 29, 30, 32, 37, 44,
319 51, 57, 63, 67, 65, 50, 53, 56, 58, 60, 63, 64, 66, 68, 74,
320 77, 78, 78, 78, 79, 79, 60, 60, 60, 61, 59, 52, 47, 41, 36,
321 30, 24, 17, 9, 0, -8, -10, -11, -14, -13, -18, -25, -31, -38,
322 -44, -50, -57, -63, -68, -74, -81, -89, -96, -101, -104, -107,
323 -109, -110, -86, -84, -85, -82, -80, -77, -73, -67, -62, -55,
324 -48, -42, -35, -30, -20, -11, -2, 5, 6, 6, 7, 11, 16, 21, 26,
325 34, 41, 46, 49, 52, 55, 56, 48, 49, 51, 51, 52, 52, 52, 52,
326 52, 51, 51, 50, 47, 47, 50, 48, 46, 42, 38, 35, 31, 27, 24,
327 20, 16, 12, 11, 12, 10, 8, 4, -1, -6, -11, -16, -19, -17, -21,
328 -24, -27, -32, -34, -37, -38, -40, -41, -40, -40, -42, -41,
329 -44, -45, -43, -41, -34, -31, -28, -24, -21, -18, -14, -10,
330 -5, -1, 2, 5, 8, 7, 4, 3, 2, 2, 4, 6, 8, 9, 9, 10, 10, 10, 10,
331 9, 8, 9, 11, 14, 13, 12, 11, 10, 8, 7, 6, 5, 3, 2, 2, -1, -1,
332 -3, -3, -4, -4, -5, -4, -6, -7, -9, -5, -1, -1, 0, 1, 0, -2,
333 -3, -4, -5, -5, -8, -13, -13, -13, -12, -13, -12, -11, -11,
334 -9, -8, -7, -5, -3, -1, 2, 4, 6, 9, 10, 11, 14, 18, 21, 24,
335 27, 30, 34, 37, 37, 39, 40 };
336
337 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
338 }
339 else
340 if( tb >= 0.10 )
341 {
342 static const double AttenCorrScale = 210.0;
343 static const signed char AttenCorrs[] = {
344 -113, -118, -122, -125, -126, -97, -95, -92, -92, -89, -82,
345 -75, -69, -48, -42, -36, -30, -22, -14, -5, -2, 1, 6, 13, 22,
346 28, 35, 41, 48, 55, 56, 56, 61, 65, 71, 77, 81, 83, 85, 85,
347 74, 74, 73, 72, 71, 70, 68, 64, 59, 56, 49, 52, 46, 42, 36,
348 32, 26, 20, 13, 7, -2, -6, -10, -15, -20, -27, -33, -38, -44,
349 -43, -48, -53, -57, -63, -69, -73, -75, -79, -81, -74, -76,
350 -77, -77, -78, -81, -80, -80, -78, -76, -65, -62, -59, -56,
351 -51, -48, -44, -38, -33, -25, -19, -13, -5, -1, 2, 7, 13, 17,
352 21, 25, 30, 35, 40, 45, 50, 53, 56, 57, 55, 58, 59, 62, 64,
353 67, 67, 68, 68, 62, 61, 61, 59, 59, 57, 57, 55, 52, 48, 42,
354 38, 35, 31, 26, 20, 15, 13, 10, 7, 3, -2, -8, -13, -17, -23,
355 -28, -34, -37, -40, -41, -45, -48, -50, -53, -57, -59, -62,
356 -63, -63, -57, -57, -56, -56, -54, -54, -53, -49, -48, -41,
357 -38, -33, -31, -26, -23, -18, -12, -9, -7, -7, -3, 0, 5, 9,
358 14, 16, 20, 22, 21, 23, 25, 27, 28, 29, 34, 33, 35, 33, 31,
359 30, 29, 29, 26, 26, 25, 24, 20, 19, 15, 10, 8, 4, 1, -2, -6,
360 -10, -16, -19, -23, -26, -27, -30, -34, -39, -43, -47, -51,
361 -52, -54, -56, -58, -59, -62, -63, -66, -65, -65, -64, -59,
362 -57, -54, -52, -48, -44, -42, -37, -32, -22, -17, -10, -3, 5,
363 13, 22, 30, 40, 50, 60, 72 };
364
365 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
366 }
367 else
368 {
369 static const double AttenCorrScale = 196.0;
370 static const signed char AttenCorrs[] = {
371 -15, -17, -20, -20, -20, -21, -20, -16, -17, -18, -17, -13,
372 -12, -11, -9, -7, -5, -4, -1, 1, 3, 4, 5, 6, 7, 9, 9, 10, 10,
373 10, 11, 11, 11, 12, 12, 12, 10, 11, 10, 10, 8, 10, 11, 10, 11,
374 11, 13, 14, 15, 19, 27, 26, 23, 18, 14, 8, 4, -2, -6, -12,
375 -17, -23, -28, -33, -37, -42, -46, -49, -53, -57, -60, -61,
376 -64, -65, -67, -66, -66, -66, -65, -64, -61, -59, -56, -52,
377 -48, -42, -38, -31, -27, -19, -13, -7, -1, 8, 14, 22, 29, 37,
378 45, 52, 59, 66, 73, 80, 86, 91, 96, 100, 104, 108, 111, 114,
379 115, 117, 118, 120, 120, 118, 117, 114, 113, 111, 107, 103,
380 99, 95, 89, 84, 78, 72, 66, 60, 52, 44, 37, 30, 21, 14, 6, -3,
381 -11, -18, -26, -34, -43, -51, -58, -65, -73, -78, -85, -90,
382 -97, -102, -107, -113, -115, -118, -121, -125, -125, -126,
383 -126, -126, -125, -124, -121, -119, -115, -111, -109, -101,
384 -102, -95, -88, -81, -73, -67, -63, -54, -47, -40, -33, -26,
385 -18, -11, -5, 2, 8, 14, 19, 25, 31, 36, 37, 43, 47, 49, 51,
386 52, 57, 57, 56, 57, 58, 58, 58, 57, 56, 52, 52, 50, 48, 44,
387 41, 39, 37, 33, 31, 26, 24, 21, 18, 14, 11, 8, 4, 2, -2, -5,
388 -7, -9, -11, -13, -15, -16, -18, -19, -20, -23, -24, -24, -25,
389 -27, -26, -27, -29, -30, -31, -32, -35, -36, -39, -40, -44,
390 -46, -51, -54, -59, -63, -69, -76, -83, -91, -98 };
391
392 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
393 }
394
395 pwr = 7.43932822146293e-8 * sqr( atten ) + 0.000102747434588003 *
396 cos( 0.00785021930010397 * atten ) * cos( 0.633854318781239 +
397 0.103208573657699 * atten ) - 0.00798132247867036 -
398 0.000903555213543865 * atten - 0.0969365532127236 * exp(
399 0.0779275237937911 * atten ) - 1.37304948662012e-5 * atten * cos(
400 0.00785021930010397 * atten );
401
402 if( pwr <= 0.067665322581 )
403 {
404 if( tb >= 0.25 )
405 {
406 hl = 2.6778150875894 / tb + 300.547590563091 * atan( atan(
407 2.68959772209918 * pwr )) / ( 5.5099277187035 * tb - tb *
408 tanh( cos( asinh( atten ))));
409
410 fo1 = 0.987205355829873 * tb + 1.00011788929851 * atan2(
411 -0.321432067051302 - 6.19131357321578 * sqrt( pwr ),
412 hl + -1.14861472207245 / ( hl - 14.1821147585957 ) + pow(
413 0.9521145021664, pow( atan2( 1.12018764830637, tb ),
414 2.10988901686912 * hl - 20.9691278378345 )));
415 }
416 else
417 if( tb >= 0.10 )
418 {
419 hl = ( 1.56688617018066 + 142.064321294568 * pwr +
420 0.00419441117131136 * cos( 243.633511747297 * pwr ) -
421 0.022953443903576 * atten - 0.026629568860284 * cos(
422 127.715550622571 * pwr )) / tb;
423
424 fo1 = 0.982299356642411 * tb + 0.999441744774215 * asinh((
425 -0.361783054039583 - 5.80540593623676 * sqrt( pwr )) /
426 hl );
427 }
428 else
429 {
430 hl = ( 2.45739657014937 + 269.183679500541 * pwr * cos(
431 5.73225668178813 + atan2( cosh( 0.988861169868941 -
432 17.2201556280744 * pwr ), 1.08340138240431 * pwr ))) / tb;
433
434 fo1 = 2.291956939 * tb + 0.01942450693 * sqr( tb ) * hl -
435 4.67538973161837 * pwr * tb - 1.668433124 * tb *
436 pow( pwr, pwr );
437 }
438 }
439 else
440 {
441 if( tb >= 0.25 )
442 {
443 hl = ( 1.50258368698213 + 158.556968859477 * asinh( pwr ) *
444 tanh( 57.9466246871383 * tanh( pwr )) -
445 0.0105440479814834 * atten ) / tb;
446
447 fo1 = 0.994024401639321 * tb + ( -0.236282717577215 -
448 6.8724924545387 * sqrt( sin( pwr ))) / hl;
449 }
450 else
451 if( tb >= 0.10 )
452 {
453 hl = ( 1.50277377248945 + 158.222625721046 * asinh( pwr ) *
454 tanh( 1.02875299001715 + 42.072277322604 * pwr ) -
455 0.0108380943845632 * atten ) / tb;
456
457 fo1 = 0.992539376734551 * tb + ( -0.251747813037178 -
458 6.74159892452584 * sqrt( tanh( tanh( tan( pwr ))))) / hl;
459 }
460 else
461 {
462 hl = ( 1.15990238966306 * pwr - 5.02124037125213 * sqr(
463 pwr ) - 0.158676856669827 * atten * cos( 1.1609073390614 *
464 pwr - 6.33932586197475 * pwr * sqr( pwr ))) / tb;
465
466 fo1 = 0.867344453126885 * tb + 0.052693817907757 * tb * log(
467 pwr ) + 0.0895511178735932 * tb * atan( 59.7538527741309 *
468 pwr ) - 0.0745653568081453 * pwr * tb;
469 }
470 }
471
472 double WinParams[ 2 ];
473 WinParams[ 0 ] = 125.0;
474 WinParams[ 1 ] = pwr;
475
476 CDSPSincFilterGen sinc;
477 sinc.Len2 = 0.25 * hl / ReqNormFreq;
478 sinc.Freq1 = 0.0;
479 sinc.Freq2 = R8B_PI * ( 1.0 - fo1 ) * ReqNormFreq;
480 sinc.initBand( CDSPSincFilterGen :: wftKaiser, WinParams, true );
481
482 KernelLen = sinc.KernelLen;
483 BlockLenBits = getBitOccupancy( KernelLen - 1 ) + R8B_EXTFFT;
484 const int BlockLen = 1 << BlockLenBits;
485
486 KernelBlock.alloc( BlockLen * 2 );
487 sinc.generateBand( &KernelBlock[ 0 ],
488 &CDSPSincFilterGen :: calcWindowKaiser );
489
490 if( ReqPhase == fprLinearPhase )
491 {
492 IsZeroPhase = true;
493 Latency = sinc.fl2;
494 LatencyFrac = 0.0;
495 }
496 else
497 {
498 IsZeroPhase = false;
499 double DCGroupDelay;
500
501 calcMinPhaseTransform( &KernelBlock[ 0 ], KernelLen, 16, false,
502 &DCGroupDelay );
503
504 Latency = (int) DCGroupDelay;
505 LatencyFrac = DCGroupDelay - Latency;
506 }
507
508 CDSPRealFFTKeeper ffto( BlockLenBits + 1 );
509
510 dsnRe = 0;
511 dsnIm = 0;
512
513 if( IsZeroPhase )
514 {
515 // Calculate DC gain.
516
517 double s = 0.0;
518 int i;
519
520 for( i = 0; i < KernelLen; i++ )
521 {
522 s += KernelBlock[ i ];
523 }
524
525 s = ffto -> getInvMulConst() * ReqGain / s;
526
527 // Time-shift the filter so that zero-phase response is produced.
528 // Simultaneously multiply by "s".
529
530 for( i = 0; i <= sinc.fl2; i++ )
531 {
532 KernelBlock[ i ] = KernelBlock[ sinc.fl2 + i ] * s;
533 }
534
535 for( i = 1; i <= sinc.fl2; i++ )
536 {
537 KernelBlock[ BlockLen * 2 - i ] = KernelBlock[ i ];
538 }
539
540 memset( &KernelBlock[ sinc.fl2 + 1 ], 0,
541 (size_t) ( BlockLen * 2 - KernelLen ) *
542 sizeof( KernelBlock[ 0 ]));
543
544 KernelBlockFFT = ffto -> forward( KernelBlock );
545
546 if( ReqDownShift > 0 )
547 {
548 KernelBlockFFT = ffto -> reorderForward( KernelBlockFFT,
549 ffto -> getWorkBuf() );
550
551 const int z = ( 2 << BlockLenBits ) >> ReqDownShift;
552 dsnRe = KernelBlockFFT[ z ];
553 dsnIm = KernelBlockFFT[ z + 1 ];
554
555 CDSPRealFFTKeeper ffto2( BlockLenBits + 1 - ReqDownShift );
556 CFixedBuffer< double > NewBlock( ffto2 -> getLen() *
557 (int) sizeof( realfft_t ) / (int) sizeof( double ));
558
559 KernelBlockFFT = ffto2 -> reorderInverse( KernelBlockFFT,
560 NewBlock );
561
562 ffto2 -> convertToZP( KernelBlockFFT );
563
564 KernelBlock.moveFrom( NewBlock );
565 }
566 else
567 {
568 ffto -> convertToZP( KernelBlockFFT );
569 }
570 }
571 else
572 {
573 normalizeFIRFilter( &KernelBlock[ 0 ], KernelLen,
574 ffto -> getInvMulConst() * ReqGain );
575
576 memset( &KernelBlock[ KernelLen ], 0,
577 (size_t) ( BlockLen * 2 - KernelLen ) *
578 sizeof( KernelBlock[ 0 ]));
579
580 KernelBlockFFT = ffto -> forward( KernelBlock );
581
582 if( ReqDownShift > 0 )
583 {
584 KernelBlockFFT = ffto -> reorderForward( KernelBlockFFT,
585 ffto -> getWorkBuf() );
586
587 const int z = ( 2 << BlockLenBits ) >> ReqDownShift;
588 dsnRe = KernelBlockFFT[ z ];
589 dsnIm = KernelBlockFFT[ z + 1 ];
590
591 CDSPRealFFTKeeper ffto2( BlockLenBits + 1 - ReqDownShift );
592 CFixedBuffer< double > NewBlock( ffto2 -> getLen() *
593 (int) sizeof( realfft_t ) / (int) sizeof( double ));
594
595 KernelBlockFFT = ffto2 -> reorderInverse( KernelBlockFFT,
596 NewBlock );
597
598 KernelBlock.moveFrom( NewBlock );
599 }
600 }
601
602 R8BCONSOLE( "CDSPFIRFilter: flt_len=%i latency=%i nfreq=%.4f "
603 "tb=%.1f att=%.1f gain=%.3f dsh=%i\n", KernelLen, Latency,
604 ReqNormFreq, ReqTransBand, ReqAtten, ReqGain, ReqDownShift );
605 }
606};
607
614
616{
618
619 friend class CDSPFIRFilter;
620
621public:
626
627 static int getObjCount()
628 {
630
631 return( getObjCountStatic() );
632 }
633
666
667 static CDSPFIRFilter& getLPFilter( const double ReqNormFreq,
668 const double ReqTransBand, const double ReqAtten,
669 const EDSPFilterPhaseResponse ReqPhase, const double ReqGain,
670 const int ReqDownFactor, const double* const AttenCorrs = R8B_NULL )
671 {
672 R8BASSERT( ReqNormFreq > 0.0 && ReqNormFreq <= 1.0 );
673 R8BASSERT( ReqTransBand >= CDSPFIRFilter :: getLPMinTransBand() );
674 R8BASSERT( ReqTransBand <= CDSPFIRFilter :: getLPMaxTransBand() );
675 R8BASSERT( ReqAtten >= CDSPFIRFilter :: getLPMinAtten() );
676 R8BASSERT( ReqAtten <= CDSPFIRFilter :: getLPMaxAtten() );
677 R8BASSERT( ReqGain > 0.0 );
678 R8BASSERT( ReqDownFactor > 0 );
679
680 R8B_EXITDTOR static CPtrKeeper< CDSPFIRFilter > Objects; // The chain
681 // of cached objects.
682
683 int ReqDownShift = getBitOccupancy( ReqDownFactor ) - 1;
684
685 if(( 1 << ReqDownShift ) != ReqDownFactor )
686 {
687 ReqDownShift = 0;
688 }
689
691
692 int& ObjCount = getObjCountStatic();
693 CDSPFIRFilter* PrevObj = R8B_NULL;
694 CDSPFIRFilter* CurObj = Objects;
695
696 while( CurObj != R8B_NULL )
697 {
698 if( CurObj -> ReqNormFreq == ReqNormFreq &&
699 CurObj -> ReqTransBand == ReqTransBand &&
700 CurObj -> ReqGain == ReqGain &&
701 CurObj -> ReqDownShift == ReqDownShift &&
702 CurObj -> ReqAtten == ReqAtten &&
703 CurObj -> ReqPhase == ReqPhase )
704 {
705 break;
706 }
707
708 if( CurObj -> Next == R8B_NULL &&
709 ObjCount >= R8B_FILTER_CACHE_MAX )
710 {
711 if( CurObj -> RefCount == 0 )
712 {
713 // Delete the last filter which is not used.
714
715 PrevObj -> Next = R8B_NULL;
716 delete CurObj;
717 ObjCount--;
718 }
719 else
720 {
721 // Move the last filter to the top of the list since it
722 // seems to be in use for a long time.
723
724 PrevObj -> Next = R8B_NULL;
725 CurObj -> Next = Objects.unkeep();
726 Objects = CurObj;
727 }
728
729 CurObj = R8B_NULL;
730 break;
731 }
732
733 PrevObj = CurObj;
734 CurObj = CurObj -> Next;
735 }
736
737 if( CurObj != R8B_NULL )
738 {
739 CurObj -> RefCount++;
740
741 if( PrevObj == R8B_NULL )
742 {
743 return( *CurObj );
744 }
745
746 // Remove the filter from the list temporarily.
747
748 PrevObj -> Next = CurObj -> Next;
749 }
750 else
751 {
752 // Create a new filter object (with RefCount == 1) and build the
753 // filter kernel.
754
755 CPtrKeeper< CDSPFIRFilter > f( new CDSPFIRFilter() );
756
757 f -> ReqNormFreq = ReqNormFreq;
758 f -> ReqTransBand = ReqTransBand;
759 f -> ReqAtten = ReqAtten;
760 f -> ReqPhase = ReqPhase;
761 f -> ReqGain = ReqGain;
762 f -> ReqDownShift = ReqDownShift;
763
764 f -> buildLPFilter( AttenCorrs );
765
766 CurObj = f.unkeep();
767 ObjCount++;
768 }
769
770 // Insert the filter at the start of the list.
771
772 CurObj -> Next = Objects.unkeep();
773 Objects = CurObj;
774
775 return( *CurObj );
776 }
777
778protected:
782
784 {
785 R8B_EXITDTOR static CSyncObject StateSync;
786
787 return( StateSync );
788 }
789
793
794 static int& getObjCountStatic()
795 {
796 R8B_EXITDTOR static int ObjCount = 0; // The number of objects
797 // currently preset in the cache.
798
799 return( ObjCount );
800 }
801};
802
803// ---------------------------------------------------------------------------
804// CDSPFIRFilter PUBLIC
805// ---------------------------------------------------------------------------
806
807inline void CDSPFIRFilter :: unref()
808{
809 R8BSYNC( CDSPFIRFilterCache :: getStateSync() );
810
811 RefCount--;
812}
813
814// ---------------------------------------------------------------------------
815
816} // namespace r8b
817
818#endif // R8B_CDSPFIRFILTER_INCLUDED
Real-valued FFT transform class.
Sinc function-based FIR filter generator class.
#define R8BSYNC(SyncObject)
Thread synchronization macro.
Definition r8bbase.h:833
#define R8B_EXITDTOR
Macro that defines the attribute specifying that the exit-time destructor should be called for a stat...
Definition r8bbase.h:149
#define R8B_NULL
The "null pointer" value, portable between C++11 and earlier C++ versions.
Definition r8bbase.h:101
#define R8BNOCTOR(ClassName)
Macro that defines empty copy-constructor and copy operator.
Definition r8bbase.h:213
#define R8B_EXTFFT
This macro, when equal to 1, extends length of low-pass filters' FFT block by a factor of 2,...
Definition r8bconf.h:129
#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
#define R8B_BASECLASS
Macro defines the name of the class from which all classes that are designed to be created on heap ar...
Definition r8bconf.h:56
#define R8BCONSOLE(...)
Console output macro, used to output various resampler status strings, including filter design parame...
Definition r8bconf.h:41
#define R8B_FILTER_CACHE_MAX
Macro specifies the number of filters kept in the cache at most.
Definition r8bconf.h:90
The "r8brain-free-src" library namespace.
Definition CDSPBlockConvolver.h:22
double realfft_t
Forward transform's native type.
Definition CDSPRealFFT.h:37
R8B_CONST double R8B_PI
Equals pi.
Definition r8bbase.h:185
EDSPFilterPhaseResponse
Enumeration of filter's phase responses.
Definition CDSPFIRFilter.h:29
@ fprMinPhase
Minimum-phase response. Features a minimal-latency response, but the response's phase is non-linear....
Definition CDSPFIRFilter.h:33
@ fprLinearPhase
Linear-phase response. Features a linear-phase, high-latency response, with the latency expressed as ...
Definition CDSPFIRFilter.h:30
T min(const T &v1, const T &v2)
Returns minimum of two values.
Definition r8bbase.h:1257
int getBitOccupancy(const int v)
Calculate the exact number of bits a value needs for representation.
Definition r8bbase.h:944
double asinh(const double v)
Hyperbolic sine of a value.
Definition r8bbase.h:1356
void calcMinPhaseTransform(double *const Kernel, const int KernelLen, const int LenMult=2, const bool DoFinalMul=true, double *const DCGroupDelay=R8B_NULL)
Calculates the minimum-phase transform of the filter kernel, using a discrete Hilbert transform in ce...
Definition CDSPRealFFT.h:993
T max(const T &v1, const T &v2)
Returns maximum of two values.
Definition r8bbase.h:1276
void normalizeFIRFilter(double *const p, const int l, const double DCGain, const int pstep=1)
FIR filter's gain normalization.
Definition r8bbase.h:1112
double sqr(const double x)
Returns square ot a value.
Definition r8bbase.h:1318
Calculation and storage class for FIR filters.
Definition CDSPFIRFilter.h:60
int getBlockLenBits() const
Returns filter's block length, expressed as Nth power of 2.
Definition CDSPFIRFilter.h:153
int getLatency() const
Returns filter's latency, in samples (integer part).
Definition CDSPFIRFilter.h:121
const realfft_t * getKernelBlock() const
Returns pointer to filter's kernel block, in complex-numbered form obtained via the CDSPRealFFT::forw...
Definition CDSPFIRFilter.h:171
static double getLPMaxTransBand()
Returns the maximal allowed low-pass filter's transition band, in percent.
Definition CDSPFIRFilter.h:82
void unref()
Reduces reference count to this object.
Definition CDSPFIRFilter.h:807
double getLatencyFrac() const
Returns filter's latency, in samples (fractional part). Always zero for linear-phase filters.
Definition CDSPFIRFilter.h:131
static double getLPMinAtten()
Returns the minimal allowed low-pass filter's stop-band attenuation, in decibel.
Definition CDSPFIRFilter.h:92
int getKernelLen() const
Returns filter kernel length, in samples. Not to be confused with the block length.
Definition CDSPFIRFilter.h:141
realfft_t calcDownShiftNyquist(const realfft_t re, const realfft_t im) const
Calculates Nyquist bin value for downsampling using power-of-2 down-shifting.
Definition CDSPFIRFilter.h:188
static double getLPMaxAtten()
Returns the maximal allowed low-pass filter's stop-band attenuation, in decibel.
Definition CDSPFIRFilter.h:102
static double getLPMinTransBand()
Returns the minimal allowed low-pass filter's transition band, in percent.
Definition CDSPFIRFilter.h:72
bool isZeroPhase() const
Returns true if kernel block of this filter has zero-phase response.
Definition CDSPFIRFilter.h:112
FIR filter cache class.
Definition CDSPFIRFilter.h:616
static CDSPFIRFilter & getLPFilter(const double ReqNormFreq, const double ReqTransBand, const double ReqAtten, const EDSPFilterPhaseResponse ReqPhase, const double ReqGain, const int ReqDownFactor, const double *const AttenCorrs=R8B_NULL)
Calculates or returns reference to a previously calculated (cached) low-pass FIR filter.
Definition CDSPFIRFilter.h:667
static int getObjCount()
Returns the number of filters present in the cache now. This value can be monitored for debugging "fo...
Definition CDSPFIRFilter.h:627
static int & getObjCountStatic()
Returns reference to variable containing cache object count.
Definition CDSPFIRFilter.h:794
static CSyncObject & getStateSync()
Returns reference to filter cache sync object.
Definition CDSPFIRFilter.h:783
Pointer-to-object "keeper" class with automatic deletion.
Definition r8bbase.h:457
T * unkeep()
Returns the keeped pointer and resets it in this keeper without object deletion.
Definition r8bbase.h:535
Multi-threaded synchronization object class.
Definition r8bbase.h:691