15#ifndef R8B_CDSPFIRFILTER_INCLUDED
16#define R8B_CDSPFIRFILTER_INCLUDED
117 return( IsZeroPhase );
136 return( LatencyFrac );
156 return( BlockLenBits );
169 return( KernelBlock );
214 void buildLPFilter(
const double*
const ExtAttenCorrs )
216 const double tb = ReqTransBand * 0.01;
220 double atten = -ReqAtten;
224 if( ReqAtten >= 117.0 )
229 if( ReqAtten >= 60.0 )
241 if( ReqAtten >= 117.0 )
246 if( ReqAtten >= 60.0 )
257 if( ReqAtten >= 117.0 )
262 if( ReqAtten >= 60.0 )
272 static const int AttenCorrCount = 264;
273 static const double AttenCorrMin = 49.0;
274 static const double AttenCorrDiff = 176.25;
275 int AttenCorr = (int) floor(( -atten - AttenCorrMin ) *
276 AttenCorrCount / AttenCorrDiff + 0.5 );
278 AttenCorr =
min( AttenCorrCount,
max( 0, AttenCorr ));
280 if( ExtAttenCorrs != NULL )
282 atten -= ExtAttenCorrs[ AttenCorr ];
287 static const double AttenCorrScale = 101.0;
288 static const signed char AttenCorrs[] = {
289 -127, -127, -125, -125, -122, -119, -115, -110, -104, -97,
290 -91, -82, -75, -24, -16, -6, 4, 14, 24, 29, 30, 32, 37, 44,
291 51, 57, 63, 67, 65, 50, 53, 56, 58, 60, 63, 64, 66, 68, 74,
292 77, 78, 78, 78, 79, 79, 60, 60, 60, 61, 59, 52, 47, 41, 36,
293 30, 24, 17, 9, 0, -8, -10, -11, -14, -13, -18, -25, -31, -38,
294 -44, -50, -57, -63, -68, -74, -81, -89, -96, -101, -104, -107,
295 -109, -110, -86, -84, -85, -82, -80, -77, -73, -67, -62, -55,
296 -48, -42, -35, -30, -20, -11, -2, 5, 6, 6, 7, 11, 16, 21, 26,
297 34, 41, 46, 49, 52, 55, 56, 48, 49, 51, 51, 52, 52, 52, 52,
298 52, 51, 51, 50, 47, 47, 50, 48, 46, 42, 38, 35, 31, 27, 24,
299 20, 16, 12, 11, 12, 10, 8, 4, -1, -6, -11, -16, -19, -17, -21,
300 -24, -27, -32, -34, -37, -38, -40, -41, -40, -40, -42, -41,
301 -44, -45, -43, -41, -34, -31, -28, -24, -21, -18, -14, -10,
302 -5, -1, 2, 5, 8, 7, 4, 3, 2, 2, 4, 6, 8, 9, 9, 10, 10, 10, 10,
303 9, 8, 9, 11, 14, 13, 12, 11, 10, 8, 7, 6, 5, 3, 2, 2, -1, -1,
304 -3, -3, -4, -4, -5, -4, -6, -7, -9, -5, -1, -1, 0, 1, 0, -2,
305 -3, -4, -5, -5, -8, -13, -13, -13, -12, -13, -12, -11, -11,
306 -9, -8, -7, -5, -3, -1, 2, 4, 6, 9, 10, 11, 14, 18, 21, 24,
307 27, 30, 34, 37, 37, 39, 40 };
309 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
314 static const double AttenCorrScale = 210.0;
315 static const signed char AttenCorrs[] = {
316 -113, -118, -122, -125, -126, -97, -95, -92, -92, -89, -82,
317 -75, -69, -48, -42, -36, -30, -22, -14, -5, -2, 1, 6, 13, 22,
318 28, 35, 41, 48, 55, 56, 56, 61, 65, 71, 77, 81, 83, 85, 85,
319 74, 74, 73, 72, 71, 70, 68, 64, 59, 56, 49, 52, 46, 42, 36,
320 32, 26, 20, 13, 7, -2, -6, -10, -15, -20, -27, -33, -38, -44,
321 -43, -48, -53, -57, -63, -69, -73, -75, -79, -81, -74, -76,
322 -77, -77, -78, -81, -80, -80, -78, -76, -65, -62, -59, -56,
323 -51, -48, -44, -38, -33, -25, -19, -13, -5, -1, 2, 7, 13, 17,
324 21, 25, 30, 35, 40, 45, 50, 53, 56, 57, 55, 58, 59, 62, 64,
325 67, 67, 68, 68, 62, 61, 61, 59, 59, 57, 57, 55, 52, 48, 42,
326 38, 35, 31, 26, 20, 15, 13, 10, 7, 3, -2, -8, -13, -17, -23,
327 -28, -34, -37, -40, -41, -45, -48, -50, -53, -57, -59, -62,
328 -63, -63, -57, -57, -56, -56, -54, -54, -53, -49, -48, -41,
329 -38, -33, -31, -26, -23, -18, -12, -9, -7, -7, -3, 0, 5, 9,
330 14, 16, 20, 22, 21, 23, 25, 27, 28, 29, 34, 33, 35, 33, 31,
331 30, 29, 29, 26, 26, 25, 24, 20, 19, 15, 10, 8, 4, 1, -2, -6,
332 -10, -16, -19, -23, -26, -27, -30, -34, -39, -43, -47, -51,
333 -52, -54, -56, -58, -59, -62, -63, -66, -65, -65, -64, -59,
334 -57, -54, -52, -48, -44, -42, -37, -32, -22, -17, -10, -3, 5,
335 13, 22, 30, 40, 50, 60, 72 };
337 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
341 static const double AttenCorrScale = 196.0;
342 static const signed char AttenCorrs[] = {
343 -15, -17, -20, -20, -20, -21, -20, -16, -17, -18, -17, -13,
344 -12, -11, -9, -7, -5, -4, -1, 1, 3, 4, 5, 6, 7, 9, 9, 10, 10,
345 10, 11, 11, 11, 12, 12, 12, 10, 11, 10, 10, 8, 10, 11, 10, 11,
346 11, 13, 14, 15, 19, 27, 26, 23, 18, 14, 8, 4, -2, -6, -12,
347 -17, -23, -28, -33, -37, -42, -46, -49, -53, -57, -60, -61,
348 -64, -65, -67, -66, -66, -66, -65, -64, -61, -59, -56, -52,
349 -48, -42, -38, -31, -27, -19, -13, -7, -1, 8, 14, 22, 29, 37,
350 45, 52, 59, 66, 73, 80, 86, 91, 96, 100, 104, 108, 111, 114,
351 115, 117, 118, 120, 120, 118, 117, 114, 113, 111, 107, 103,
352 99, 95, 89, 84, 78, 72, 66, 60, 52, 44, 37, 30, 21, 14, 6, -3,
353 -11, -18, -26, -34, -43, -51, -58, -65, -73, -78, -85, -90,
354 -97, -102, -107, -113, -115, -118, -121, -125, -125, -126,
355 -126, -126, -125, -124, -121, -119, -115, -111, -109, -101,
356 -102, -95, -88, -81, -73, -67, -63, -54, -47, -40, -33, -26,
357 -18, -11, -5, 2, 8, 14, 19, 25, 31, 36, 37, 43, 47, 49, 51,
358 52, 57, 57, 56, 57, 58, 58, 58, 57, 56, 52, 52, 50, 48, 44,
359 41, 39, 37, 33, 31, 26, 24, 21, 18, 14, 11, 8, 4, 2, -2, -5,
360 -7, -9, -11, -13, -15, -16, -18, -19, -20, -23, -24, -24, -25,
361 -27, -26, -27, -29, -30, -31, -32, -35, -36, -39, -40, -44,
362 -46, -51, -54, -59, -63, -69, -76, -83, -91, -98 };
364 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
367 pwr = 7.43932822146293e-8 *
sqr( atten ) + 0.000102747434588003 *
368 cos( 0.00785021930010397 * atten ) * cos( 0.633854318781239 +
369 0.103208573657699 * atten ) - 0.00798132247867036 -
370 0.000903555213543865 * atten - 0.0969365532127236 * exp(
371 0.0779275237937911 * atten ) - 1.37304948662012e-5 * atten * cos(
372 0.00785021930010397 * atten );
374 if( pwr <= 0.067665322581 )
378 hl = 2.6778150875894 / tb + 300.547590563091 * atan( atan(
379 2.68959772209918 * pwr )) / ( 5.5099277187035 * tb - tb *
380 tanh( cos(
asinh( atten ))));
382 fo1 = 0.987205355829873 * tb + 1.00011788929851 * atan2(
383 -0.321432067051302 - 6.19131357321578 * sqrt( pwr ),
384 hl + -1.14861472207245 / ( hl - 14.1821147585957 ) + pow(
385 0.9521145021664, pow( atan2( 1.12018764830637, tb ),
386 2.10988901686912 * hl - 20.9691278378345 )));
391 hl = ( 1.56688617018066 + 142.064321294568 * pwr +
392 0.00419441117131136 * cos( 243.633511747297 * pwr ) -
393 0.022953443903576 * atten - 0.026629568860284 * cos(
394 127.715550622571 * pwr )) / tb;
396 fo1 = 0.982299356642411 * tb + 0.999441744774215 *
asinh((
397 -0.361783054039583 - 5.80540593623676 * sqrt( pwr )) /
402 hl = ( 2.45739657014937 + 269.183679500541 * pwr * cos(
403 5.73225668178813 + atan2( cosh( 0.988861169868941 -
404 17.2201556280744 * pwr ), 1.08340138240431 * pwr ))) / tb;
406 fo1 = 2.291956939 * tb + 0.01942450693 *
sqr( tb ) * hl -
407 4.67538973161837 * pwr * tb - 1.668433124 * tb *
415 hl = ( 1.50258368698213 + 158.556968859477 *
asinh( pwr ) *
416 tanh( 57.9466246871383 * tanh( pwr )) -
417 0.0105440479814834 * atten ) / tb;
419 fo1 = 0.994024401639321 * tb + ( -0.236282717577215 -
420 6.8724924545387 * sqrt( sin( pwr ))) / hl;
425 hl = ( 1.50277377248945 + 158.222625721046 *
asinh( pwr ) *
426 tanh( 1.02875299001715 + 42.072277322604 * pwr ) -
427 0.0108380943845632 * atten ) / tb;
429 fo1 = 0.992539376734551 * tb + ( -0.251747813037178 -
430 6.74159892452584 * sqrt( tanh( tanh( tan( pwr ))))) / hl;
434 hl = ( 1.15990238966306 * pwr - 5.02124037125213 *
sqr(
435 pwr ) - 0.158676856669827 * atten * cos( 1.1609073390614 *
436 pwr - 6.33932586197475 * pwr *
sqr( pwr ))) / tb;
438 fo1 = 0.867344453126885 * tb + 0.052693817907757 * tb * log(
439 pwr ) + 0.0895511178735932 * tb * atan( 59.7538527741309 *
440 pwr ) - 0.0745653568081453 * pwr * tb;
444 double WinParams[ 2 ];
445 WinParams[ 0 ] = 125.0;
446 WinParams[ 1 ] = pwr;
448 CDSPSincFilterGen sinc;
449 sinc.Len2 = 0.25 * hl / ReqNormFreq;
451 sinc.Freq2 =
R8B_PI * ( 1.0 - fo1 ) * ReqNormFreq;
452 sinc.initBand( CDSPSincFilterGen :: wftKaiser, WinParams,
true );
454 KernelLen = sinc.KernelLen;
456 const int BlockLen = 1 << BlockLenBits;
458 KernelBlock.
alloc( BlockLen * 2 );
459 sinc.generateBand( &KernelBlock[ 0 ],
460 &CDSPSincFilterGen :: calcWindowKaiser );
476 Latency = (int) DCGroupDelay;
477 LatencyFrac = DCGroupDelay - Latency;
480 CDSPRealFFTKeeper ffto( BlockLenBits + 1 );
489 for( i = 0; i < KernelLen; i++ )
491 s += KernelBlock[ i ];
494 s = ffto -> getInvMulConst() * ReqGain / s;
499 for( i = 0; i <= sinc.fl2; i++ )
501 KernelBlock[ i ] = KernelBlock[ sinc.fl2 + i ] * s;
504 for( i = 1; i <= sinc.fl2; i++ )
506 KernelBlock[ BlockLen * 2 - i ] = KernelBlock[ i ];
509 memset( &KernelBlock[ sinc.fl2 + 1 ], 0,
510 ( BlockLen * 2 - KernelLen ) *
sizeof( KernelBlock[ 0 ]));
512 ffto -> forward( KernelBlock );
513 ffto -> convertToZP( KernelBlock );
518 ffto -> getInvMulConst() * ReqGain );
520 memset( &KernelBlock[ KernelLen ], 0,
521 ( BlockLen * 2 - KernelLen ) *
sizeof( KernelBlock[ 0 ]));
523 ffto -> forward( KernelBlock );
526 R8BCONSOLE(
"CDSPFIRFilter: flt_len=%i latency=%i nfreq=%.4f "
527 "tb=%.1f att=%.1f gain=%.3f\n", KernelLen, Latency,
528 ReqNormFreq, ReqTransBand, ReqAtten, ReqGain );
589 const double ReqTransBand,
const double ReqAtten,
591 const double*
const AttenCorrs = NULL )
593 R8BASSERT( ReqNormFreq > 0.0 && ReqNormFreq <= 1.0 );
594 R8BASSERT( ReqTransBand >= CDSPFIRFilter :: getLPMinTransBand() );
595 R8BASSERT( ReqTransBand <= CDSPFIRFilter :: getLPMaxTransBand() );
596 R8BASSERT( ReqAtten >= CDSPFIRFilter :: getLPMinAtten() );
597 R8BASSERT( ReqAtten <= CDSPFIRFilter :: getLPMaxAtten() );
605 while( CurObj != NULL )
607 if( CurObj -> ReqNormFreq == ReqNormFreq &&
608 CurObj -> ReqTransBand == ReqTransBand &&
609 CurObj -> ReqGain == ReqGain &&
610 CurObj -> ReqAtten == ReqAtten &&
611 CurObj -> ReqPhase == ReqPhase )
618 if( CurObj -> RefCount == 0 )
622 PrevObj -> Next = NULL;
631 PrevObj -> Next = NULL;
632 CurObj -> Next = Objects.unkeep();
641 CurObj = CurObj -> Next;
646 CurObj -> RefCount++;
648 if( PrevObj == NULL )
655 PrevObj -> Next = CurObj -> Next;
663 CurObj -> ReqNormFreq = ReqNormFreq;
664 CurObj -> ReqTransBand = ReqTransBand;
665 CurObj -> ReqAtten = ReqAtten;
666 CurObj -> ReqPhase = ReqPhase;
667 CurObj -> ReqGain = ReqGain;
670 CurObj -> buildLPFilter( AttenCorrs );
675 CurObj -> Next = Objects.unkeep();
693inline void CDSPFIRFilter :: unref()
695 R8BSYNC( CDSPFIRFilterCache :: StateSync );
Real-valued FFT transform class.
Sinc function-based FIR filter generator class.
#define R8BSYNC(SyncObject)
Definition: r8bbase.h:660
#define R8B_PI
Definition: r8bbase.h:119
#define R8BNOCTOR(ClassName)
Definition: r8bbase.h:154
#define R8B_EXTFFT
Definition: r8bconf.h:134
#define R8BASSERT(e)
Definition: r8bconf.h:27
#define R8B_BASECLASS
Definition: r8bconf.h:54
#define R8BCONSOLE(...)
Definition: r8bconf.h:40
#define R8B_FILTER_CACHE_MAX
Definition: r8bconf.h:84
The "r8brain-free-src" library namespace.
Definition: CDSPBlockConvolver.h:21
EDSPFilterPhaseResponse
Definition: CDSPFIRFilter.h:28
@ fprMinPhase
Minimum-phase response. Features a minimal-latency response, but the response's phase is non-linear....
Definition: CDSPFIRFilter.h:32
@ fprLinearPhase
Linear-phase response. Features a linear-phase, high-latency response, with the latency expressed as ...
Definition: CDSPFIRFilter.h:29
T min(const T &v1, const T &v2)
Definition: r8bbase.h:1063
int getBitOccupancy(const int v)
Definition: r8bbase.h:766
double asinh(const double v)
Definition: r8bbase.h:1152
T max(const T &v1, const T &v2)
Definition: r8bbase.h:1080
void calcMinPhaseTransform(double *const Kernel, const int KernelLen, const int LenMult=2, const bool DoFinalMul=true, double *const DCGroupDelay=NULL)
Definition: CDSPRealFFT.h:691
void normalizeFIRFilter(double *const p, const int l, const double DCGain, const int pstep=1)
Definition: r8bbase.h:928
double sqr(const double x)
Definition: r8bbase.h:1120
Calculation and storage class for FIR filters.
Definition: CDSPFIRFilter.h:58
int getBlockLenBits() const
Definition: CDSPFIRFilter.h:154
int getLatency() const
Definition: CDSPFIRFilter.h:124
static double getLPMaxTransBand()
Definition: CDSPFIRFilter.h:86
void unref()
Definition: CDSPFIRFilter.h:693
double getLatencyFrac() const
Definition: CDSPFIRFilter.h:134
static double getLPMinAtten()
Definition: CDSPFIRFilter.h:96
int getKernelLen() const
Definition: CDSPFIRFilter.h:144
const double * getKernelBlock() const
Definition: CDSPFIRFilter.h:167
static double getLPMaxAtten()
Definition: CDSPFIRFilter.h:106
static double getLPMinTransBand()
Definition: CDSPFIRFilter.h:76
bool isZeroPhase() const
Definition: CDSPFIRFilter.h:115
FIR filter cache class.
Definition: CDSPFIRFilter.h:540
static int getObjCount()
Definition: CDSPFIRFilter.h:551
static CDSPFIRFilter & getLPFilter(const double ReqNormFreq, const double ReqTransBand, const double ReqAtten, const EDSPFilterPhaseResponse ReqPhase, const double ReqGain, const double *const AttenCorrs=NULL)
Definition: CDSPFIRFilter.h:588
void alloc(const int Capacity)
Definition: r8bbase.h:343
Pointer-to-object "keeper" class with automatic deletion.
Definition: r8bbase.h:428
Multi-threaded synchronization object class.
Definition: r8bbase.h:526