59 private CSinglyLinkedListItem< CDSPFIRFilter >
63 friend class CSinglyLinkedListItem< CDSPFIRFilter >;
64 friend class CDSPFIRFilterCache;
114 return( IsZeroPhase );
133 return( LatencyFrac );
155 return( BlockLenBits );
173 return( KernelBlockFFT );
191 return( dsnRe * re - dsnIm * im );
242 void buildLPFilter(
const double*
const ExtAttenCorrs )
244 const double tb = ReqTransBand * 0.01;
248 double atten = -ReqAtten;
252 if( ReqAtten >= 117.0 )
257 if( ReqAtten >= 60.0 )
269 if( ReqAtten >= 117.0 )
274 if( ReqAtten >= 60.0 )
285 if( ReqAtten >= 117.0 )
290 if( ReqAtten >= 60.0 )
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 );
306 AttenCorr =
min( AttenCorrCount,
max( 0, AttenCorr ));
310 atten -= ExtAttenCorrs[ AttenCorr ];
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 };
337 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
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 };
365 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
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 };
392 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
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 );
402 if( pwr <= 0.067665322581 )
406 hl = 2.6778150875894 / tb + 300.547590563091 * atan( atan(
407 2.68959772209918 * pwr )) / ( 5.5099277187035 * tb - tb *
408 tanh( cos(
asinh( atten ))));
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 )));
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;
424 fo1 = 0.982299356642411 * tb + 0.999441744774215 *
asinh((
425 -0.361783054039583 - 5.80540593623676 * sqrt( pwr )) /
430 hl = ( 2.45739657014937 + 269.183679500541 * pwr * cos(
431 5.73225668178813 + atan2( cosh( 0.988861169868941 -
432 17.2201556280744 * pwr ), 1.08340138240431 * pwr ))) / tb;
434 fo1 = 2.291956939 * tb + 0.01942450693 *
sqr( tb ) * hl -
435 4.67538973161837 * pwr * tb - 1.668433124 * tb *
443 hl = ( 1.50258368698213 + 158.556968859477 *
asinh( pwr ) *
444 tanh( 57.9466246871383 * tanh( pwr )) -
445 0.0105440479814834 * atten ) / tb;
447 fo1 = 0.994024401639321 * tb + ( -0.236282717577215 -
448 6.8724924545387 * sqrt( sin( pwr ))) / hl;
453 hl = ( 1.50277377248945 + 158.222625721046 *
asinh( pwr ) *
454 tanh( 1.02875299001715 + 42.072277322604 * pwr ) -
455 0.0108380943845632 * atten ) / tb;
457 fo1 = 0.992539376734551 * tb + ( -0.251747813037178 -
458 6.74159892452584 * sqrt( tanh( tanh( tan( pwr ))))) / hl;
462 hl = ( 1.15990238966306 * pwr - 5.02124037125213 *
sqr(
463 pwr ) - 0.158676856669827 * atten * cos( 1.1609073390614 *
464 pwr - 6.33932586197475 * pwr *
sqr( pwr ))) / tb;
466 fo1 = 0.867344453126885 * tb + 0.052693817907757 * tb * log(
467 pwr ) + 0.0895511178735932 * tb * atan( 59.7538527741309 *
468 pwr ) - 0.0745653568081453 * pwr * tb;
472 double WinParams[ 2 ];
473 WinParams[ 0 ] = 125.0;
474 WinParams[ 1 ] = pwr;
476 CDSPSincFilterGen sinc;
477 sinc.Len2 = 0.25 * hl / ReqNormFreq;
479 sinc.Freq2 =
R8B_PI * ( 1.0 - fo1 ) * ReqNormFreq;
480 sinc.initBand( CDSPSincFilterGen :: wftKaiser, WinParams,
true );
482 KernelLen = sinc.KernelLen;
484 const int BlockLen = 1 << BlockLenBits;
486 KernelBlock.alloc( BlockLen * 2 );
487 sinc.generateBand( &KernelBlock[ 0 ],
488 &CDSPSincFilterGen :: calcWindowKaiser );
504 Latency = (int) DCGroupDelay;
505 LatencyFrac = DCGroupDelay - Latency;
508 CDSPRealFFTKeeper ffto( BlockLenBits + 1 );
520 for( i = 0; i < KernelLen; i++ )
522 s += KernelBlock[ i ];
525 s = ffto -> getInvMulConst() * ReqGain / s;
530 for( i = 0; i <= sinc.fl2; i++ )
532 KernelBlock[ i ] = KernelBlock[ sinc.fl2 + i ] * s;
535 for( i = 1; i <= sinc.fl2; i++ )
537 KernelBlock[ BlockLen * 2 - i ] = KernelBlock[ i ];
540 memset( &KernelBlock[ sinc.fl2 + 1 ], 0,
541 (
size_t) ( BlockLen * 2 - KernelLen ) *
542 sizeof( KernelBlock[ 0 ]));
544 KernelBlockFFT = ffto -> forward( KernelBlock );
546 if( ReqDownShift > 0 )
548 KernelBlockFFT = ffto -> reorderForward( KernelBlockFFT,
549 ffto -> getWorkBuf() );
551 const int z = ( 2 << BlockLenBits ) >> ReqDownShift;
552 dsnRe = KernelBlockFFT[ z ];
553 dsnIm = KernelBlockFFT[ z + 1 ];
555 CDSPRealFFTKeeper ffto2( BlockLenBits + 1 - ReqDownShift );
556 CFixedBuffer< double > NewBlock( ffto2 -> getLen() *
557 (
int)
sizeof(
realfft_t ) / (
int)
sizeof(
double ));
559 KernelBlockFFT = ffto2 -> reorderInverse( KernelBlockFFT,
562 ffto2 -> convertToZP( KernelBlockFFT );
564 KernelBlock.moveFrom( NewBlock );
568 ffto -> convertToZP( KernelBlockFFT );
574 ffto -> getInvMulConst() * ReqGain );
576 memset( &KernelBlock[ KernelLen ], 0,
577 (
size_t) ( BlockLen * 2 - KernelLen ) *
578 sizeof( KernelBlock[ 0 ]));
580 KernelBlockFFT = ffto -> forward( KernelBlock );
582 if( ReqDownShift > 0 )
584 KernelBlockFFT = ffto -> reorderForward( KernelBlockFFT,
585 ffto -> getWorkBuf() );
587 const int z = ( 2 << BlockLenBits ) >> ReqDownShift;
588 dsnRe = KernelBlockFFT[ z ];
589 dsnIm = KernelBlockFFT[ z + 1 ];
591 CDSPRealFFTKeeper ffto2( BlockLenBits + 1 - ReqDownShift );
592 CFixedBuffer< double > NewBlock( ffto2 -> getLen() *
593 (
int)
sizeof(
realfft_t ) / (
int)
sizeof(
double ));
595 KernelBlockFFT = ffto2 -> reorderInverse( KernelBlockFFT,
598 KernelBlock.moveFrom( NewBlock );
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 );