62 friend class CDSPFIRFilterCache;
119 return( IsZeroPhase );
138 return( LatencyFrac );
158 return( BlockLenBits );
173 return( KernelBlock );
220 void buildLPFilter(
const double*
const ExtAttenCorrs )
222 const double tb = ReqTransBand * 0.01;
226 double atten = -ReqAtten;
230 if( ReqAtten >= 117.0 )
235 if( ReqAtten >= 60.0 )
247 if( ReqAtten >= 117.0 )
252 if( ReqAtten >= 60.0 )
263 if( ReqAtten >= 117.0 )
268 if( ReqAtten >= 60.0 )
278 static const int AttenCorrCount = 264;
279 static const double AttenCorrMin = 49.0;
280 static const double AttenCorrDiff = 176.25;
281 int AttenCorr = (int) floor(( -atten - AttenCorrMin ) *
282 AttenCorrCount / AttenCorrDiff + 0.5 );
284 AttenCorr =
min( AttenCorrCount,
max( 0, AttenCorr ));
288 atten -= ExtAttenCorrs[ AttenCorr ];
293 static const double AttenCorrScale = 101.0;
294 static const signed char AttenCorrs[] = {
295 -127, -127, -125, -125, -122, -119, -115, -110, -104, -97,
296 -91, -82, -75, -24, -16, -6, 4, 14, 24, 29, 30, 32, 37, 44,
297 51, 57, 63, 67, 65, 50, 53, 56, 58, 60, 63, 64, 66, 68, 74,
298 77, 78, 78, 78, 79, 79, 60, 60, 60, 61, 59, 52, 47, 41, 36,
299 30, 24, 17, 9, 0, -8, -10, -11, -14, -13, -18, -25, -31, -38,
300 -44, -50, -57, -63, -68, -74, -81, -89, -96, -101, -104, -107,
301 -109, -110, -86, -84, -85, -82, -80, -77, -73, -67, -62, -55,
302 -48, -42, -35, -30, -20, -11, -2, 5, 6, 6, 7, 11, 16, 21, 26,
303 34, 41, 46, 49, 52, 55, 56, 48, 49, 51, 51, 52, 52, 52, 52,
304 52, 51, 51, 50, 47, 47, 50, 48, 46, 42, 38, 35, 31, 27, 24,
305 20, 16, 12, 11, 12, 10, 8, 4, -1, -6, -11, -16, -19, -17, -21,
306 -24, -27, -32, -34, -37, -38, -40, -41, -40, -40, -42, -41,
307 -44, -45, -43, -41, -34, -31, -28, -24, -21, -18, -14, -10,
308 -5, -1, 2, 5, 8, 7, 4, 3, 2, 2, 4, 6, 8, 9, 9, 10, 10, 10, 10,
309 9, 8, 9, 11, 14, 13, 12, 11, 10, 8, 7, 6, 5, 3, 2, 2, -1, -1,
310 -3, -3, -4, -4, -5, -4, -6, -7, -9, -5, -1, -1, 0, 1, 0, -2,
311 -3, -4, -5, -5, -8, -13, -13, -13, -12, -13, -12, -11, -11,
312 -9, -8, -7, -5, -3, -1, 2, 4, 6, 9, 10, 11, 14, 18, 21, 24,
313 27, 30, 34, 37, 37, 39, 40 };
315 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
320 static const double AttenCorrScale = 210.0;
321 static const signed char AttenCorrs[] = {
322 -113, -118, -122, -125, -126, -97, -95, -92, -92, -89, -82,
323 -75, -69, -48, -42, -36, -30, -22, -14, -5, -2, 1, 6, 13, 22,
324 28, 35, 41, 48, 55, 56, 56, 61, 65, 71, 77, 81, 83, 85, 85,
325 74, 74, 73, 72, 71, 70, 68, 64, 59, 56, 49, 52, 46, 42, 36,
326 32, 26, 20, 13, 7, -2, -6, -10, -15, -20, -27, -33, -38, -44,
327 -43, -48, -53, -57, -63, -69, -73, -75, -79, -81, -74, -76,
328 -77, -77, -78, -81, -80, -80, -78, -76, -65, -62, -59, -56,
329 -51, -48, -44, -38, -33, -25, -19, -13, -5, -1, 2, 7, 13, 17,
330 21, 25, 30, 35, 40, 45, 50, 53, 56, 57, 55, 58, 59, 62, 64,
331 67, 67, 68, 68, 62, 61, 61, 59, 59, 57, 57, 55, 52, 48, 42,
332 38, 35, 31, 26, 20, 15, 13, 10, 7, 3, -2, -8, -13, -17, -23,
333 -28, -34, -37, -40, -41, -45, -48, -50, -53, -57, -59, -62,
334 -63, -63, -57, -57, -56, -56, -54, -54, -53, -49, -48, -41,
335 -38, -33, -31, -26, -23, -18, -12, -9, -7, -7, -3, 0, 5, 9,
336 14, 16, 20, 22, 21, 23, 25, 27, 28, 29, 34, 33, 35, 33, 31,
337 30, 29, 29, 26, 26, 25, 24, 20, 19, 15, 10, 8, 4, 1, -2, -6,
338 -10, -16, -19, -23, -26, -27, -30, -34, -39, -43, -47, -51,
339 -52, -54, -56, -58, -59, -62, -63, -66, -65, -65, -64, -59,
340 -57, -54, -52, -48, -44, -42, -37, -32, -22, -17, -10, -3, 5,
341 13, 22, 30, 40, 50, 60, 72 };
343 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
347 static const double AttenCorrScale = 196.0;
348 static const signed char AttenCorrs[] = {
349 -15, -17, -20, -20, -20, -21, -20, -16, -17, -18, -17, -13,
350 -12, -11, -9, -7, -5, -4, -1, 1, 3, 4, 5, 6, 7, 9, 9, 10, 10,
351 10, 11, 11, 11, 12, 12, 12, 10, 11, 10, 10, 8, 10, 11, 10, 11,
352 11, 13, 14, 15, 19, 27, 26, 23, 18, 14, 8, 4, -2, -6, -12,
353 -17, -23, -28, -33, -37, -42, -46, -49, -53, -57, -60, -61,
354 -64, -65, -67, -66, -66, -66, -65, -64, -61, -59, -56, -52,
355 -48, -42, -38, -31, -27, -19, -13, -7, -1, 8, 14, 22, 29, 37,
356 45, 52, 59, 66, 73, 80, 86, 91, 96, 100, 104, 108, 111, 114,
357 115, 117, 118, 120, 120, 118, 117, 114, 113, 111, 107, 103,
358 99, 95, 89, 84, 78, 72, 66, 60, 52, 44, 37, 30, 21, 14, 6, -3,
359 -11, -18, -26, -34, -43, -51, -58, -65, -73, -78, -85, -90,
360 -97, -102, -107, -113, -115, -118, -121, -125, -125, -126,
361 -126, -126, -125, -124, -121, -119, -115, -111, -109, -101,
362 -102, -95, -88, -81, -73, -67, -63, -54, -47, -40, -33, -26,
363 -18, -11, -5, 2, 8, 14, 19, 25, 31, 36, 37, 43, 47, 49, 51,
364 52, 57, 57, 56, 57, 58, 58, 58, 57, 56, 52, 52, 50, 48, 44,
365 41, 39, 37, 33, 31, 26, 24, 21, 18, 14, 11, 8, 4, 2, -2, -5,
366 -7, -9, -11, -13, -15, -16, -18, -19, -20, -23, -24, -24, -25,
367 -27, -26, -27, -29, -30, -31, -32, -35, -36, -39, -40, -44,
368 -46, -51, -54, -59, -63, -69, -76, -83, -91, -98 };
370 atten -= AttenCorrs[ AttenCorr ] / AttenCorrScale;
373 pwr = 7.43932822146293e-8 *
sqr( atten ) + 0.000102747434588003 *
374 cos( 0.00785021930010397 * atten ) * cos( 0.633854318781239 +
375 0.103208573657699 * atten ) - 0.00798132247867036 -
376 0.000903555213543865 * atten - 0.0969365532127236 * exp(
377 0.0779275237937911 * atten ) - 1.37304948662012e-5 * atten * cos(
378 0.00785021930010397 * atten );
380 if( pwr <= 0.067665322581 )
384 hl = 2.6778150875894 / tb + 300.547590563091 * atan( atan(
385 2.68959772209918 * pwr )) / ( 5.5099277187035 * tb - tb *
386 tanh( cos(
asinh( atten ))));
388 fo1 = 0.987205355829873 * tb + 1.00011788929851 * atan2(
389 -0.321432067051302 - 6.19131357321578 * sqrt( pwr ),
390 hl + -1.14861472207245 / ( hl - 14.1821147585957 ) + pow(
391 0.9521145021664, pow( atan2( 1.12018764830637, tb ),
392 2.10988901686912 * hl - 20.9691278378345 )));
397 hl = ( 1.56688617018066 + 142.064321294568 * pwr +
398 0.00419441117131136 * cos( 243.633511747297 * pwr ) -
399 0.022953443903576 * atten - 0.026629568860284 * cos(
400 127.715550622571 * pwr )) / tb;
402 fo1 = 0.982299356642411 * tb + 0.999441744774215 *
asinh((
403 -0.361783054039583 - 5.80540593623676 * sqrt( pwr )) /
408 hl = ( 2.45739657014937 + 269.183679500541 * pwr * cos(
409 5.73225668178813 + atan2( cosh( 0.988861169868941 -
410 17.2201556280744 * pwr ), 1.08340138240431 * pwr ))) / tb;
412 fo1 = 2.291956939 * tb + 0.01942450693 *
sqr( tb ) * hl -
413 4.67538973161837 * pwr * tb - 1.668433124 * tb *
421 hl = ( 1.50258368698213 + 158.556968859477 *
asinh( pwr ) *
422 tanh( 57.9466246871383 * tanh( pwr )) -
423 0.0105440479814834 * atten ) / tb;
425 fo1 = 0.994024401639321 * tb + ( -0.236282717577215 -
426 6.8724924545387 * sqrt( sin( pwr ))) / hl;
431 hl = ( 1.50277377248945 + 158.222625721046 *
asinh( pwr ) *
432 tanh( 1.02875299001715 + 42.072277322604 * pwr ) -
433 0.0108380943845632 * atten ) / tb;
435 fo1 = 0.992539376734551 * tb + ( -0.251747813037178 -
436 6.74159892452584 * sqrt( tanh( tanh( tan( pwr ))))) / hl;
440 hl = ( 1.15990238966306 * pwr - 5.02124037125213 *
sqr(
441 pwr ) - 0.158676856669827 * atten * cos( 1.1609073390614 *
442 pwr - 6.33932586197475 * pwr *
sqr( pwr ))) / tb;
444 fo1 = 0.867344453126885 * tb + 0.052693817907757 * tb * log(
445 pwr ) + 0.0895511178735932 * tb * atan( 59.7538527741309 *
446 pwr ) - 0.0745653568081453 * pwr * tb;
450 double WinParams[ 2 ];
451 WinParams[ 0 ] = 125.0;
452 WinParams[ 1 ] = pwr;
454 CDSPSincFilterGen sinc;
455 sinc.Len2 = 0.25 * hl / ReqNormFreq;
457 sinc.Freq2 =
R8B_PI * ( 1.0 - fo1 ) * ReqNormFreq;
458 sinc.initBand( CDSPSincFilterGen :: wftKaiser, WinParams,
true );
460 KernelLen = sinc.KernelLen;
462 const int BlockLen = 1 << BlockLenBits;
464 KernelBlock.alloc( BlockLen * 2 );
465 sinc.generateBand( &KernelBlock[ 0 ],
466 &CDSPSincFilterGen :: calcWindowKaiser );
482 Latency = (int) DCGroupDelay;
483 LatencyFrac = DCGroupDelay - Latency;
486 CDSPRealFFTKeeper ffto( BlockLenBits + 1 );
495 for( i = 0; i < KernelLen; i++ )
497 s += KernelBlock[ i ];
500 s = ffto -> getInvMulConst() * ReqGain / s;
505 for( i = 0; i <= sinc.fl2; i++ )
507 KernelBlock[ i ] = KernelBlock[ sinc.fl2 + i ] * s;
510 for( i = 1; i <= sinc.fl2; i++ )
512 KernelBlock[ BlockLen * 2 - i ] = KernelBlock[ i ];
515 memset( &KernelBlock[ sinc.fl2 + 1 ], 0,
516 (
size_t) ( BlockLen * 2 - KernelLen ) *
517 sizeof( KernelBlock[ 0 ]));
519 ffto -> forward( KernelBlock );
520 ffto -> convertToZP( KernelBlock );
525 ffto -> getInvMulConst() * ReqGain );
527 memset( &KernelBlock[ KernelLen ], 0,
528 (
size_t) ( BlockLen * 2 - KernelLen ) *
529 sizeof( KernelBlock[ 0 ]));
531 ffto -> forward( KernelBlock );
534 R8BCONSOLE(
"CDSPFIRFilter: flt_len=%i latency=%i nfreq=%.4f "
535 "tb=%.1f att=%.1f gain=%.3f\n", KernelLen, Latency,
536 ReqNormFreq, ReqTransBand, ReqAtten, ReqGain );