15 #ifndef R8B_CDSPFRACINTERPOLATOR_INCLUDED 16 #define R8B_CDSPFRACINTERPOLATOR_INCLUDED 24 extern int InterpFilterFracs;
25 extern int InterpFilterFracsThird;
65 const int aInterpPoints,
const double aReqAtten,
const bool aIsThird )
66 : InitFilterFracs( aFilterFracs )
67 , ElementSize( aElementSize )
68 , InterpPoints( aInterpPoints )
69 , ReqAtten( aReqAtten )
74 R8BASSERT( ElementSize >= 1 && ElementSize <= 4 );
78 const double*
const Params = getWinParams( ReqAtten, IsThird,
81 FilterSize = FilterLen * ElementSize;
83 if( InitFilterFracs == -1 )
85 FilterFracs = (int) ceil( 1.792462178761753 *
86 exp( 0.033300466782047 * ReqAtten ));
92 if( InterpFilterFracsThird != -1 )
94 FilterFracs = InterpFilterFracsThird;
99 if( InterpFilterFracs != -1 )
101 FilterFracs = InterpFilterFracs;
105 #endif // R8B_FLTTEST 109 FilterFracs = InitFilterFracs;
112 Table.
alloc( FilterSize * ( FilterFracs + InterpPoints ));
115 sinc.
Len2 = FilterLen / 2;
118 const int pc2 = InterpPoints / 2;
121 for( i = -pc2 + 1; i <= FilterFracs + pc2; i++ )
123 sinc.
FracDelay = (double) ( FilterFracs - i ) / FilterFracs;
132 const int TablePos2 = FilterSize;
133 const int TablePos3 = FilterSize * 2;
134 const int TablePos4 = FilterSize * 3;
135 const int TablePos5 = FilterSize * 4;
136 const int TablePos6 = FilterSize * 5;
137 const int TablePos7 = FilterSize * 6;
138 const int TablePos8 = FilterSize * 7;
139 double*
const TableEnd = Table + ( FilterFracs + 1 ) * FilterSize;
142 if( InterpPoints == 8 )
144 if( ElementSize == 3 )
149 while( p < TableEnd )
152 p[ TablePos3 ], p[ TablePos4 ], p[ TablePos5 ],
153 p[ TablePos6 ], p[ TablePos7 ], p[ TablePos8 ]);
159 if( ElementSize == 4 )
164 while( p < TableEnd )
167 p[ TablePos3 ], p[ TablePos4 ], p[ TablePos5 ],
168 p[ TablePos6 ], p[ TablePos7 ], p[ TablePos8 ]);
176 if( ElementSize == 2 )
180 while( p < TableEnd )
182 p[ 1 ] = p[ TablePos2 ] - p[ 0 ];
188 R8BCONSOLE(
"CDSPFracDelayFilterBank: fracs=%i order=%i taps=%i " 189 "att=%.1f third=%i\n", FilterFracs, ElementSize - 1, FilterLen,
190 ReqAtten, (
int) IsThird );
210 getWinParams( att, aIsThird, tmp );
229 return( FilterFracs );
241 return( Table[ i * FilterSize ]);
290 static const double* getWinParams(
double& att,
const bool aIsThird,
293 const int CoeffCount = 13;
294 static const double Coeffs[ CoeffCount ][ 3 ] = {
295 { 2.6504246356892924, 1.9035845248358245, 51.7280 },
296 { 4.0759654812373016, 1.5747323142948524, 67.1095 },
297 { 4.9036508646352033, 1.6207644759455790, 81.8379 },
298 { 5.6131421124830716, 1.6947677220415129, 96.4021 },
299 { 5.9433751253133691, 1.8730186383321272, 111.1300 },
300 { 6.8308658253825660, 1.8549555120377224, 125.4649 },
301 { 7.6648458853758372, 1.8565765953924642, 139.7378 },
302 { 8.2038730802326842, 1.9269521308895179, 154.0532 },
303 { 8.7865151489187561, 1.9775307528231671, 168.2101 },
304 { 9.5945013206755156, 1.9718457932433306, 182.1076 },
305 { 10.5163048616210250, 1.9504085061576968, 195.5668 },
306 { 10.2382664677006100, 2.1608878780497056, 209.0609 },
307 { 10.9976663155261660, 2.1536415815428249, 222.5009 },
310 const int CoeffCountThird = 10;
311 static const double CoeffsThird[ CoeffCountThird ][ 3 ] = {
312 { 4.0738201365282452, 1.5774150265957998, 67.2431 },
313 { 4.9502289040040495, 1.7149006172407628, 86.4870 },
314 { 5.5995071332976192, 1.8930163359641823, 106.1171 },
315 { 6.3627287856776054, 1.9945748303811506, 125.2304 },
316 { 7.4299554386534528, 1.9893399585993299, 144.3469 },
317 { 8.0667710807396436, 2.0928202837610885, 163.4098 },
318 { 8.7469991933128526, 2.1640274270903488, 181.0694 },
319 { 10.0823164330540570, 2.0896732996403280, 199.2880 },
320 { 19.1718281840114810, 1.2030083075440616, 215.2990 },
321 { 21.0914128488567630, 1.1919045429676862, 233.9152 },
324 const double* Params;
329 while( i != CoeffCountThird - 1 && CoeffsThird[ i ][ 2 ] < att )
334 Params = &CoeffsThird[ i ][ 0 ];
335 att = CoeffsThird[ i ][ 2 ];
339 while( i != CoeffCount - 1 && Coeffs[ i ][ 2 ] < att )
344 Params = &Coeffs[ i ][ 0 ];
345 att = Coeffs[ i ][ 2 ];
348 fltlen = ( i + 3 ) * 2;
395 const int aElementSize,
const int aInterpPoints,
396 double ReqAtten,
const bool IsThird,
const bool IsStatic )
406 while( CurObj != NULL )
408 if( CurObj -> InitFilterFracs == aFilterFracs &&
409 CurObj -> ElementSize == aElementSize &&
410 CurObj -> InterpPoints == aInterpPoints &&
411 CurObj -> ReqAtten == ReqAtten &&
412 CurObj -> IsThird == IsThird )
417 CurObj = CurObj -> Next;
423 aInterpPoints, ReqAtten, IsThird );
427 CurObj -> Next = StaticObjects.unkeep();
428 StaticObjects = CurObj;
436 while( CurObj != NULL )
438 if( CurObj -> InitFilterFracs == aFilterFracs &&
439 CurObj -> ElementSize == aElementSize &&
440 CurObj -> InterpPoints == aInterpPoints &&
441 CurObj -> ReqAtten == ReqAtten &&
442 CurObj -> IsThird == IsThird )
449 if( CurObj -> RefCount == 0 )
453 PrevObj -> Next = NULL;
462 PrevObj -> Next = NULL;
463 CurObj -> Next = Objects.unkeep();
472 CurObj = CurObj -> Next;
477 CurObj -> RefCount++;
479 if( PrevObj == NULL )
486 PrevObj -> Next = CurObj -> Next;
493 aInterpPoints, ReqAtten, IsThird );
500 CurObj -> Next = Objects.unkeep();
526 R8BSYNC( CDSPFracDelayFilterBankCache :: StateSync );
539 inline bool findGCD(
double l,
double s,
double& GCD )
551 const double r = l - s;
553 s = ( r < 0.0 ? -r : r );
574 const double DSampleRate,
int& ResInStep,
int& ResOutStep )
578 if( !
findGCD( SSampleRate, DSampleRate, GCD ) || GCD < 1.0 )
583 const double InStep0 = SSampleRate / GCD;
584 ResInStep = (int) InStep0;
585 const double OutStep0 = DSampleRate / GCD;
586 ResOutStep = (int) OutStep0;
588 if( InStep0 != ResInStep || OutStep0 != ResOutStep )
593 if( ResOutStep > 1500 )
637 const double aDstSampleRate,
const double ReqAtten,
638 const bool IsThird,
const double PrevLatency )
639 : SrcSampleRate( aSrcSampleRate )
640 , DstSampleRate( aDstSampleRate )
642 , FracStep( aSrcSampleRate / aDstSampleRate )
649 R8BASSERT(( 1 << BufLenBits ) >= FilterLen * 3 );
651 InitFracPos = PrevLatency;
652 Latency = (int) InitFracPos;
653 InitFracPos -= Latency;
669 InitFracPosW = (int) ( InitFracPos * OutStep );
670 LatencyFrac = InitFracPos - (double) InitFracPosW / OutStep;
672 OutStep, 1, 2, ReqAtten, IsThird,
false );
678 -1, 3, 8, ReqAtten, IsThird,
true );
681 #endif // R8B_FLTTEST 684 fl2 = FilterLen >> 1;
688 static const CConvolveFn FltConvFn0[ 13 ] = {
689 &CDSPFracInterpolator :: convolve0< 6 >,
690 &CDSPFracInterpolator :: convolve0< 8 >,
691 &CDSPFracInterpolator :: convolve0< 10 >,
692 &CDSPFracInterpolator :: convolve0< 12 >,
693 &CDSPFracInterpolator :: convolve0< 14 >,
694 &CDSPFracInterpolator :: convolve0< 16 >,
695 &CDSPFracInterpolator :: convolve0< 18 >,
696 &CDSPFracInterpolator :: convolve0< 20 >,
697 &CDSPFracInterpolator :: convolve0< 22 >,
698 &CDSPFracInterpolator :: convolve0< 24 >,
699 &CDSPFracInterpolator :: convolve0< 26 >,
700 &CDSPFracInterpolator :: convolve0< 28 >,
701 &CDSPFracInterpolator :: convolve0< 30 >
704 convfn = ( IsWhole ? FltConvFn0[ fl2 - 3 ] :
705 &CDSPFracInterpolator :: convolve2 );
707 R8BCONSOLE(
"CDSPFracInterpolator: src=%.2f dst=%.2f taps=%i " 708 "fracs=%i third=%i step=%.6f\n", SrcSampleRate, DstSampleRate,
709 FilterLen, ( IsWhole ? OutStep : FilterBank ->
getFilterFracs() ),
710 (
int) IsThird, aSrcSampleRate / aDstSampleRate );
723 FilterBank ->
unref();
725 #endif // R8B_FLTTEST 735 return( LatencyFrac );
742 return( (
int) ceil( MaxInLen * DstSampleRate / SrcSampleRate ) + 1 );
747 LatencyLeft = Latency;
750 ReadPos = BufLen - fll;
753 memset( &Buf[ ReadPos ], 0, fll *
sizeof(
double ));
757 InPosFracW = InitFracPosW;
761 InPosFrac = InitFracPos;
766 InPosShift = InitFracPos * DstSampleRate / SrcSampleRate;
767 #endif // !R8B_FASTTIMING 771 virtual int process(
double* ip,
int l,
double*& op0 )
774 R8BASSERT( ip != op0 || l == 0 || SrcSampleRate > DstSampleRate );
776 if( LatencyLeft > 0 )
778 if( LatencyLeft >= l )
795 const int b =
min(
min( l, BufLen - WritePos ),
796 BufLen - fll - BufLeft );
798 double*
const wp1 = Buf + WritePos;
799 memcpy( wp1, ip, b *
sizeof(
double ));
803 const int c =
min( b, flo - WritePos );
804 memcpy( wp1 + BufLen, wp1, c *
sizeof(
double ));
808 WritePos = ( WritePos + b ) & BufLenMask;
814 op = ( *this.*convfn )( op );
819 if( !IsWhole && InCounter > 1000 )
826 InPosShift = InPosFrac * DstSampleRate / SrcSampleRate;
829 #endif // !R8B_FASTTIMING 831 return( (
int) ( op - op0 ));
835 static const int BufLenBits = 8;
836 static const int BufLen = 1 << BufLenBits;
845 static const int BufLenMask = BufLen - 1;
858 double Buf[ BufLen + 29 ];
860 double SrcSampleRate;
863 double DstSampleRate;
903 #else // R8B_FASTTIMING 909 #endif // R8B_FASTTIMING 926 template<
int fltlen >
927 double* convolve0(
double* op )
929 while( BufLeft > fl2 )
931 const double*
const ftp = &(*FilterBank)[ InPosFracW ];
932 const double*
const rp = Buf + ReadPos;
936 for( i = 0; i < fltlen; i++ )
938 s += ftp[ i ] * rp[ i ];
944 InPosFracW += InStep;
945 const int PosIncr = InPosFracW / OutStep;
946 InPosFracW -= PosIncr * OutStep;
948 ReadPos = ( ReadPos + PosIncr ) & BufLenMask;
962 double* convolve2(
double* op )
964 while( BufLeft > fl2 )
967 const int fti = (int) x;
970 const double x2 = x * x;
971 const double*
const ftp = &(*FilterBank)[ fti ];
972 const double*
const rp = Buf + ReadPos;
977 for( i = 0; i < FilterLen; i++ )
979 s += ( ftp[ ii ] + ftp[ ii + 1 ] * x +
980 ftp[ ii + 2 ] * x2 ) * rp[ i ];
990 InPosFrac += FracStep;
991 const int PosIncr = (int) InPosFrac;
992 InPosFrac -= PosIncr;
994 #else // R8B_FASTTIMING 997 const double NextInPos = ( InCounter + InPosShift ) *
998 SrcSampleRate / DstSampleRate;
1000 const int NextInPosInt = (int) NextInPos;
1001 const int PosIncr = NextInPosInt - InPosInt;
1002 InPosInt = NextInPosInt;
1003 InPosFrac = NextInPos - NextInPosInt;
1005 #endif // R8B_FASTTIMING 1007 ReadPos = ( ReadPos + PosIncr ) & BufLenMask;
1019 #endif // R8B_CDSPFRACINTERPOLATOR_INCLUDED virtual int getLatency() const
Definition: CDSPFracInterpolator.h:728
const double & operator[](const int i) const
Definition: CDSPFracInterpolator.h:237
#define R8BCONSOLE(...)
Console output macro, used to output various resampler status strings, including filter design parame...
Definition: r8bconf.h:85
void calcSpline2p8Coeffs(double *c, const double xm3, const double xm2, const double xm1, const double x0, const double x1, const double x2, const double x3, const double x4)
Function calculates coefficients used to calculate 2rd order spline (polynomial) on the equidistant l...
Definition: r8bbase.h:1019
#define R8BASSERT(e)
Assertion macro used to check for certain run-time conditions.
Definition: r8bconf.h:72
Sinc function-based fractional delay filter bank class.
Definition: CDSPFracInterpolator.h:41
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
void initFrac(const EWindowFunctionType WinType=wftCosine, const double *const Params=NULL, const bool UsePower=false)
Function initializes *this structure for generation of full-bandwidth fractional delay sinc filter ke...
Definition: CDSPSincFilterGen.h:184
Pointer-to-object "keeper" class with automatic deletion.
Definition: r8bbase.h:429
double FracDelay
Fractional delay in the range [0; 1], used.
Definition: CDSPSincFilterGen.h:62
Sinc function-based FIR filter generator class.
Definition: CDSPSincFilterGen.h:31
Fractional delay filter cache class.
Definition: CDSPFracInterpolator.h:360
The base virtual class for DSP processing algorithms.
CDSPFracInterpolator(const double aSrcSampleRate, const double aDstSampleRate, const double ReqAtten, const bool IsThird, const double PrevLatency)
Constructor initalizes the interpolator.
Definition: CDSPFracInterpolator.h:636
#define R8BNOCTOR(ClassName)
A special macro that defines empty copy-constructor and copy operator with the "private:" prefix...
Definition: r8bbase.h:144
static CDSPFracDelayFilterBank & getFilterBank(const int aFilterFracs, const int aElementSize, const int aInterpPoints, double ReqAtten, const bool IsThird, const bool IsStatic)
Function calculates or returns reference to a previously calculated (cached) fractional delay filter ...
Definition: CDSPFracInterpolator.h:394
static int getObjCount()
Definition: CDSPFracInterpolator.h:372
Multi-threaded synchronization object class.
Definition: r8bbase.h:526
CDSPFracDelayFilterBank(const int aFilterFracs, const int aElementSize, const int aInterpPoints, const double aReqAtten, const bool aIsThird)
Constructor.
Definition: CDSPFracInterpolator.h:64
bool findGCD(double l, double s, double &GCD)
Definition: CDSPFracInterpolator.h:539
T min(const T &v1, const T &v2)
Definition: r8bbase.h:1118
virtual int process(double *ip, int l, double *&op0)
Function performs DSP processing.
Definition: CDSPFracInterpolator.h:771
bool getWholeStepping(const double SSampleRate, const double DSampleRate, int &ResInStep, int &ResOutStep)
Function evaluates source and destination sample rate ratio and returns the required input and output...
Definition: CDSPFracInterpolator.h:573
#define R8B_FASTTIMING
This macro, when equal to 1, enables fast approach to interpolation sample timing.
Definition: r8bconf.h:155
Sinc function-based FIR filter generator class.
int getFilterFracs() const
Function returns the number of fractional positions sampled by the bank.
Definition: CDSPFracInterpolator.h:227
virtual int getMaxOutLen(const int MaxInLen) const
Definition: CDSPFracInterpolator.h:738
double Len2
Required half filter kernel's length in samples (can be.
Definition: CDSPSincFilterGen.h:34
#define R8BSYNC(SyncObject)
The synchronization macro.
Definition: r8bbase.h:664
virtual double getLatencyFrac() const
Definition: CDSPFracInterpolator.h:733
Kaiser window function.
Definition: CDSPSincFilterGen.h:81
void generateFrac(T *op, CWindowFunc wfunc=&CDSPSincFilterGen ::calcWindowBlackman, const int opinc=1)
Function calculates windowed fractional delay filter kernel.
Definition: CDSPSincFilterGen.h:432
static void roundReqAtten(double &att, const bool aIsThird)
Function "rounds" the specified attenuation to the nearest effective value.
Definition: CDSPFracInterpolator.h:207
The base virtual class for DSP processing algorithms.
Definition: CDSPProcessor.h:31
void calcSpline3p8Coeffs(double *c, const double xm3, const double xm2, const double xm1, const double x0, const double x1, const double x2, const double x3, const double x4)
Function calculates coefficients used to calculate 3rd order spline (polynomial) on the equidistant l...
Definition: r8bbase.h:987
virtual void clear()
Function clears (resets) the state of *this object and returns it to the state after construction...
Definition: CDSPFracInterpolator.h:745
Fractional delay filter bank-based interpolator class.
Definition: CDSPFracInterpolator.h:619
#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
The "r8brain-free-src" library namespace.
Definition: CDSPBlockConvolver.h:21
void unref()
This function should be called when the filter obtained via the filter bank cache is no longer needed...
Definition: CDSPFracInterpolator.h:524
#define R8B_FRACBANK_CACHE_MAX
This macro specifies the number of whole-number stepping fractional delay filter banks kept in the ca...
Definition: r8bconf.h:130
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
int getFilterLen() const
Function returns the length of the filter.
Definition: CDSPFracInterpolator.h:217
double calcWindowKaiser()
Definition: CDSPSincFilterGen.h:246