15 #ifndef R8B_CDSPFIRFILTER_INCLUDED 16 #define R8B_CDSPFIRFILTER_INCLUDED 117 return( IsZeroPhase );
136 return( LatencyFrac );
156 return( BlockLenBits );
169 return( KernelBlock );
227 void buildLPFilter(
const double*
const ExtAttenCorrs )
229 const double tb = ReqTransBand * 0.01;
233 double atten = -ReqAtten;
237 if( ReqAtten >= 117.0 )
242 if( ReqAtten >= 60.0 )
254 if( ReqAtten >= 117.0 )
259 if( ReqAtten >= 60.0 )
270 if( ReqAtten >= 117.0 )
275 if( ReqAtten >= 60.0 )
285 static const int AttenCorrCount = 264;
286 static const double AttenCorrMin = 49.0;
287 static const double AttenCorrDiff = 176.25;
288 int AttenCorr = (int) floor(( -atten - AttenCorrMin ) *
289 AttenCorrCount / AttenCorrDiff + 0.5 );
291 AttenCorr =
min( AttenCorrCount,
max( 0, AttenCorr ));
293 if( ExtAttenCorrs != NULL )
295 atten -= ExtAttenCorrs[ AttenCorr ];
300 static const double AttenCorrScale = 101.0;
301 static const signed char AttenCorrs[] = {
302 -127, -127, -125, -125, -122, -119, -115, -110, -104, -97,
303 -91, -82, -75, -24, -16, -6, 4, 14, 24, 29, 30, 32, 37, 44,
304 51, 57, 63, 67, 65, 50, 53, 56, 58, 60, 63, 64, 66, 68, 74,
305 77, 78, 78, 78, 79, 79, 60, 60, 60, 61, 59, 52, 47, 41, 36,
306 30, 24, 17, 9, 0, -8, -10, -11, -14, -13, -18, -25, -31, -38,
307 -44, -50, -57, -63, -68, -74, -81, -89, -96, -101, -104, -107,
308 -109, -110, -86, -84, -85, -82, -80, -77, -73, -67, -62, -55,
309 -48, -42, -35, -30, -20, -11, -2, 5, 6, 6, 7, 11, 16, 21, 26,
310 34, 41, 46, 49, 52, 55, 56, 48, 49, 51, 51, 52, 52, 52, 52,
311 52, 51, 51, 50, 47, 47, 50, 48, 46, 42, 38, 35, 31, 27, 24,
312 20, 16, 12, 11, 12, 10, 8, 4, -1, -6, -11, -16, -19, -17, -21,
313 -24, -27, -32, -34, -37, -38, -40, -41, -40, -40, -42, -41,
314 -44, -45, -43, -41, -34, -31, -28, -24, -21, -18, -14, -10,
315 -5, -1, 2, 5, 8, 7, 4, 3, 2, 2, 4, 6, 8, 9, 9, 10, 10, 10, 10,
316 9, 8, 9, 11, 14, 13, 12, 11, 10, 8, 7, 6, 5, 3, 2, 2, -1, -1,
317 -3, -3, -4, -4, -5, -4, -6, -7, -9, -5, -1, -1, 0, 1, 0, -2,
318 -3, -4, -5, -5, -8, -13, -13, -13, -12, -13, -12, -11, -11,
319 -9, -8, -7, -5, -3, -1, 2, 4, 6, 9, 10, 11, 14, 18, 21, 24,
320 27, 30, 34, 37, 37, 39, 40 };
322 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
327 static const double AttenCorrScale = 210.0;
328 static const signed char AttenCorrs[] = {
329 -113, -118, -122, -125, -126, -97, -95, -92, -92, -89, -82,
330 -75, -69, -48, -42, -36, -30, -22, -14, -5, -2, 1, 6, 13, 22,
331 28, 35, 41, 48, 55, 56, 56, 61, 65, 71, 77, 81, 83, 85, 85,
332 74, 74, 73, 72, 71, 70, 68, 64, 59, 56, 49, 52, 46, 42, 36,
333 32, 26, 20, 13, 7, -2, -6, -10, -15, -20, -27, -33, -38, -44,
334 -43, -48, -53, -57, -63, -69, -73, -75, -79, -81, -74, -76,
335 -77, -77, -78, -81, -80, -80, -78, -76, -65, -62, -59, -56,
336 -51, -48, -44, -38, -33, -25, -19, -13, -5, -1, 2, 7, 13, 17,
337 21, 25, 30, 35, 40, 45, 50, 53, 56, 57, 55, 58, 59, 62, 64,
338 67, 67, 68, 68, 62, 61, 61, 59, 59, 57, 57, 55, 52, 48, 42,
339 38, 35, 31, 26, 20, 15, 13, 10, 7, 3, -2, -8, -13, -17, -23,
340 -28, -34, -37, -40, -41, -45, -48, -50, -53, -57, -59, -62,
341 -63, -63, -57, -57, -56, -56, -54, -54, -53, -49, -48, -41,
342 -38, -33, -31, -26, -23, -18, -12, -9, -7, -7, -3, 0, 5, 9,
343 14, 16, 20, 22, 21, 23, 25, 27, 28, 29, 34, 33, 35, 33, 31,
344 30, 29, 29, 26, 26, 25, 24, 20, 19, 15, 10, 8, 4, 1, -2, -6,
345 -10, -16, -19, -23, -26, -27, -30, -34, -39, -43, -47, -51,
346 -52, -54, -56, -58, -59, -62, -63, -66, -65, -65, -64, -59,
347 -57, -54, -52, -48, -44, -42, -37, -32, -22, -17, -10, -3, 5,
348 13, 22, 30, 40, 50, 60, 72 };
350 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
354 static const double AttenCorrScale = 196.0;
355 static const signed char AttenCorrs[] = {
356 -15, -17, -20, -20, -20, -21, -20, -16, -17, -18, -17, -13,
357 -12, -11, -9, -7, -5, -4, -1, 1, 3, 4, 5, 6, 7, 9, 9, 10, 10,
358 10, 11, 11, 11, 12, 12, 12, 10, 11, 10, 10, 8, 10, 11, 10, 11,
359 11, 13, 14, 15, 19, 27, 26, 23, 18, 14, 8, 4, -2, -6, -12,
360 -17, -23, -28, -33, -37, -42, -46, -49, -53, -57, -60, -61,
361 -64, -65, -67, -66, -66, -66, -65, -64, -61, -59, -56, -52,
362 -48, -42, -38, -31, -27, -19, -13, -7, -1, 8, 14, 22, 29, 37,
363 45, 52, 59, 66, 73, 80, 86, 91, 96, 100, 104, 108, 111, 114,
364 115, 117, 118, 120, 120, 118, 117, 114, 113, 111, 107, 103,
365 99, 95, 89, 84, 78, 72, 66, 60, 52, 44, 37, 30, 21, 14, 6, -3,
366 -11, -18, -26, -34, -43, -51, -58, -65, -73, -78, -85, -90,
367 -97, -102, -107, -113, -115, -118, -121, -125, -125, -126,
368 -126, -126, -125, -124, -121, -119, -115, -111, -109, -101,
369 -102, -95, -88, -81, -73, -67, -63, -54, -47, -40, -33, -26,
370 -18, -11, -5, 2, 8, 14, 19, 25, 31, 36, 37, 43, 47, 49, 51,
371 52, 57, 57, 56, 57, 58, 58, 58, 57, 56, 52, 52, 50, 48, 44,
372 41, 39, 37, 33, 31, 26, 24, 21, 18, 14, 11, 8, 4, 2, -2, -5,
373 -7, -9, -11, -13, -15, -16, -18, -19, -20, -23, -24, -24, -25,
374 -27, -26, -27, -29, -30, -31, -32, -35, -36, -39, -40, -44,
375 -46, -51, -54, -59, -63, -69, -76, -83, -91, -98 };
377 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
380 pwr = 7.43932822146293e-8 *
sqr( atten ) + 0.000102747434588003 *
381 cos( 0.00785021930010397 * atten ) * cos( 0.633854318781239 +
382 0.103208573657699 * atten ) - 0.00798132247867036 -
383 0.000903555213543865 * atten - 0.0969365532127236 * exp(
384 0.0779275237937911 * atten ) - 1.37304948662012e-5 * atten * cos(
385 0.00785021930010397 * atten );
387 if( pwr <= 0.067665322581 )
391 hl = 2.6778150875894 / tb + 300.547590563091 * atan( atan(
392 2.68959772209918 * pwr )) / ( 5.5099277187035 * tb - tb *
393 tanh( cos(
asinh( atten ))));
395 fo1 = 0.987205355829873 * tb + 1.00011788929851 * atan2(
396 -0.321432067051302 - 6.19131357321578 * sqrt( pwr ),
397 hl + -1.14861472207245 / ( hl - 14.1821147585957 ) + pow(
398 0.9521145021664, pow( atan2( 1.12018764830637, tb ),
399 2.10988901686912 * hl - 20.9691278378345 )));
404 hl = ( 1.56688617018066 + 142.064321294568 * pwr +
405 0.00419441117131136 * cos( 243.633511747297 * pwr ) -
406 0.022953443903576 * atten - 0.026629568860284 * cos(
407 127.715550622571 * pwr )) / tb;
409 fo1 = 0.982299356642411 * tb + 0.999441744774215 *
asinh((
410 -0.361783054039583 - 5.80540593623676 * sqrt( pwr )) /
415 hl = ( 2.45739657014937 + 269.183679500541 * pwr * cos(
416 5.73225668178813 + atan2( cosh( 0.988861169868941 -
417 17.2201556280744 * pwr ), 1.08340138240431 * pwr ))) / tb;
419 fo1 = 2.291956939 * tb + 0.01942450693 *
sqr( tb ) * hl -
420 4.67538973161837 * pwr * tb - 1.668433124 * tb *
428 hl = ( 1.50258368698213 + 158.556968859477 *
asinh( pwr ) *
429 tanh( 57.9466246871383 * tanh( pwr )) -
430 0.0105440479814834 * atten ) / tb;
432 fo1 = 0.994024401639321 * tb + ( -0.236282717577215 -
433 6.8724924545387 * sqrt( sin( pwr ))) / hl;
438 hl = ( 1.50277377248945 + 158.222625721046 *
asinh( pwr ) *
439 tanh( 1.02875299001715 + 42.072277322604 * pwr ) -
440 0.0108380943845632 * atten ) / tb;
442 fo1 = 0.992539376734551 * tb + ( -0.251747813037178 -
443 6.74159892452584 * sqrt( tanh( tanh( tan( pwr ))))) / hl;
447 hl = ( 1.15990238966306 * pwr - 5.02124037125213 *
sqr(
448 pwr ) - 0.158676856669827 * atten * cos( 1.1609073390614 *
449 pwr - 6.33932586197475 * pwr *
sqr( pwr ))) / tb;
451 fo1 = 0.867344453126885 * tb + 0.052693817907757 * tb * log(
452 pwr ) + 0.0895511178735932 * tb * atan( 59.7538527741309 *
453 pwr ) - 0.0745653568081453 * pwr * tb;
457 double WinParams[ 2 ];
458 WinParams[ 0 ] = 125.0;
459 WinParams[ 1 ] = pwr;
462 sinc.
Len2 = 0.25 * hl / ReqNormFreq;
464 sinc.
Freq2 =
M_PI * ( 1.0 - fo1 ) * ReqNormFreq;
469 const int BlockLen = 1 << BlockLenBits;
471 KernelBlock.
alloc( BlockLen * 2 );
489 Latency = (int) DCGroupDelay;
490 LatencyFrac = DCGroupDelay - Latency;
502 for( i = 0; i < KernelLen; i++ )
504 s += KernelBlock[ i ];
507 s = ffto -> getInvMulConst() * ReqGain / s;
512 for( i = 0; i <= sinc.
fl2; i++ )
514 KernelBlock[ i ] = KernelBlock[ sinc.
fl2 + i ] * s;
517 for( i = 1; i <= sinc.
fl2; i++ )
519 KernelBlock[ BlockLen * 2 - i ] = KernelBlock[ i ];
522 memset( &KernelBlock[ sinc.
fl2 + 1 ], 0,
523 ( BlockLen * 2 - KernelLen ) *
sizeof(
double ));
528 ffto -> getInvMulConst() * ReqGain );
530 memset( &KernelBlock[ KernelLen ], 0,
531 ( BlockLen * 2 - KernelLen ) *
sizeof(
double ));
534 ffto -> forward( KernelBlock );
538 ffto -> convertToZ( KernelBlock );
541 R8BCONSOLE(
"CDSPFIRFilter: flt_len=%i latency=%i nfreq=%.4f " 542 "tb=%.1f att=%.1f gain=%.3f\n", KernelLen, Latency,
543 ReqNormFreq, ReqTransBand, ReqAtten, ReqGain );
603 const double ReqTransBand,
const double ReqAtten,
605 const double*
const AttenCorrs = NULL )
607 R8BASSERT( ReqNormFreq > 0.0 && ReqNormFreq <= 1.0 );
619 while( CurObj != NULL )
621 if( CurObj -> ReqNormFreq == ReqNormFreq &&
622 CurObj -> ReqTransBand == ReqTransBand &&
623 CurObj -> ReqAtten == ReqAtten &&
624 CurObj -> ReqPhase == ReqPhase &&
625 CurObj -> ReqGain == ReqGain )
632 if( CurObj -> RefCount == 0 )
636 PrevObj -> Next = NULL;
645 PrevObj -> Next = NULL;
646 CurObj -> Next = Objects.unkeep();
655 CurObj = CurObj -> Next;
660 CurObj -> RefCount++;
662 if( PrevObj == NULL )
669 PrevObj -> Next = CurObj -> Next;
677 CurObj -> ReqNormFreq = ReqNormFreq;
678 CurObj -> ReqTransBand = ReqTransBand;
679 CurObj -> ReqAtten = ReqAtten;
680 CurObj -> ReqPhase = ReqPhase;
681 CurObj -> ReqGain = ReqGain;
684 CurObj -> buildLPFilter( AttenCorrs );
689 CurObj -> Next = Objects.unkeep();
712 R8BSYNC( CDSPFIRFilterCache :: StateSync );
721 #endif // R8B_CDSPFIRFILTER_INCLUDED double asinh(const double v)
Definition: r8bbase.h:1205
int getBitOccupancy(const int v)
Definition: r8bbase.h:775
static double getLPMaxAtten()
Definition: CDSPFIRFilter.h:106
int getKernelLen() const
Definition: CDSPFIRFilter.h:144
#define R8BCONSOLE(...)
Console output macro, used to output various resampler status strings, including filter design parame...
Definition: r8bconf.h:85
#define R8BASSERT(e)
Assertion macro used to check for certain run-time conditions.
Definition: r8bconf.h:72
void normalizeFIRFilter(double *const p, const int l, const double DCGain, const int pstep=1)
Function normalizes FIR filter so that its frequency response at DC is equal to DCGain.
Definition: r8bbase.h:943
static int getObjCount()
Definition: CDSPFIRFilter.h:566
const double * getKernelBlock() const
Definition: CDSPFIRFilter.h:167
double Freq1
Required corner circular frequency 1 [0; pi].
Definition: CDSPSincFilterGen.h:50
Pointer-to-object "keeper" class with automatic deletion.
Definition: r8bbase.h:429
Linear-phase response.
Definition: CDSPFIRFilter.h:29
Sinc function-based FIR filter generator class.
Definition: CDSPSincFilterGen.h:31
Calculation and storage class for FIR filters.
Definition: CDSPFIRFilter.h:57
int fl2
Internal "half kernel length" value.
Definition: CDSPSincFilterGen.h:41
void generateBand(T *op, CWindowFunc wfunc=&CDSPSincFilterGen ::calcWindowBlackman)
Function calculates band-limited windowed sinc function-based filter kernel.
Definition: CDSPSincFilterGen.h:330
Minimum-phase response.
Definition: CDSPFIRFilter.h:33
#define R8BNOCTOR(ClassName)
A special macro that defines empty copy-constructor and copy operator with the "private:" prefix...
Definition: r8bbase.h:144
Multi-threaded synchronization object class.
Definition: r8bbase.h:526
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
int KernelLen
Resulting length of the filter kernel, this variable.
Definition: CDSPSincFilterGen.h:38
#define R8B_EXTFFT
This macro, when equal to 1, extends length of low-pass filters' FFT block by a factor of 2 by zero-p...
Definition: r8bconf.h:168
T max(const T &v1, const T &v2)
Definition: r8bbase.h:1134
T min(const T &v1, const T &v2)
Definition: r8bbase.h:1118
FIR filter cache class.
Definition: CDSPFIRFilter.h:554
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
Sinc function-based FIR filter generator class.
A "keeper" class for real-valued FFT transform objects.
Definition: CDSPRealFFT.h:461
int getBlockLenBits() const
Definition: CDSPFIRFilter.h:154
double Freq2
Required corner circular frequency 2 [0; pi].
Definition: CDSPSincFilterGen.h:53
double Len2
Required half filter kernel's length in samples (can be.
Definition: CDSPSincFilterGen.h:34
Real-valued FFT transform class.
#define R8B_FILTER_CACHE_MAX
This macro specifies the number of filters kept in the cache at most.
Definition: r8bconf.h:118
#define R8BSYNC(SyncObject)
The synchronization macro.
Definition: r8bbase.h:664
double getLatencyFrac() const
Definition: CDSPFIRFilter.h:134
int getLatency() const
Definition: CDSPFIRFilter.h:124
Kaiser window function.
Definition: CDSPSincFilterGen.h:81
static double getLPMinAtten()
Definition: CDSPFIRFilter.h:96
static CDSPFIRFilter & getLPFilter(const double ReqNormFreq, const double ReqTransBand, const double ReqAtten, const EDSPFilterPhaseResponse ReqPhase, const double ReqGain, const double *const AttenCorrs=NULL)
Function calculates or returns reference to a previously calculated (cached) low-pass FIR filter...
Definition: CDSPFIRFilter.h:602
static double getLPMaxTransBand()
Definition: CDSPFIRFilter.h:86
#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:99
EDSPFilterPhaseResponse
Enumeration of filter's phase responses.
Definition: CDSPFIRFilter.h:27
bool isZeroPhase() const
Definition: CDSPFIRFilter.h:115
void calcMinPhaseTransform(double *const Kernel, const int KernelLen, const int LenMult=2, const bool DoFinalMul=true, double *const DCGroupDelay=NULL)
Function calculates the minimum-phase transform of the filter kernel, using a discrete Hilbert transf...
Definition: CDSPRealFFT.h:609
The "r8brain-free-src" library namespace.
Definition: CDSPBlockConvolver.h:21
static double getLPMinTransBand()
Definition: CDSPFIRFilter.h:76
void alloc(const int Capacity)
Function allocates memory so that the specified number of elements of type T can be stored in *this b...
Definition: r8bbase.h:318
double calcWindowKaiser()
Definition: CDSPSincFilterGen.h:246
void unref()
This function should be called when the filter obtained via the filter cache is no longer needed...
Definition: CDSPFIRFilter.h:710