15#ifndef R8B_CDSPBLOCKCONVOLVER_INCLUDED
16#define R8B_CDSPBLOCKCONVOLVER_INCLUDED
63 const int aDownFactor,
const double PrevLatency = 0.0,
64 const bool aDoConsumeLatency =
true )
66 , UpFactor( aUpFactor )
67 , DownFactor( aDownFactor )
68 , BlockLen2( 2 << Filter -> getBlockLenBits() )
69 , DoConsumeLatency( aDoConsumeLatency )
78 if(( 1 << UpShift ) == UpFactor )
80 fftinBits = Filter -> getBlockLenBits() + 1 - UpShift;
81 PrevInputLen = ( Filter -> getKernelLen() - 1 + UpFactor - 1 ) /
84 InputLen = BlockLen2 - PrevInputLen * UpFactor;
89 fftinBits = Filter -> getBlockLenBits() + 1;
90 PrevInputLen = Filter -> getKernelLen() - 1;
91 InputLen = BlockLen2 - PrevInputLen;
94 OutOffset = ( Filter -> isZeroPhase() ? Filter ->
getLatency() : 0 );
96 Latency = (int) LatencyFrac;
97 const int InLatency = Latency + Filter ->
getLatency() - OutOffset;
98 LatencyFrac -= Latency;
99 LatencyFrac /= DownFactor;
108 if(( 1 << DownShift ) == DownFactor )
110 fftoutBits = Filter -> getBlockLenBits() + 1 - DownShift;
126 const int ilc = InputLen & ( DownFactor - 1 );
133 const int lc = InLatency & ( DownFactor - 1 );
137 InputDelay = DownFactor - lc;
140 if( !DoConsumeLatency )
142 Latency /= DownFactor;
149 fftoutBits = Filter -> getBlockLenBits() + 1;
152 if( !DoConsumeLatency && DownFactor > 1 )
154 DownSkipInit = Latency % DownFactor;
155 Latency /= DownFactor;
163 if( fftoutBits == fftinBits )
173 WorkBlocks.
alloc( BlockLen2 * 2 + PrevInputLen );
174 CurInput = &WorkBlocks[ 0 ];
175 CurOutput = &WorkBlocks[ BlockLen2 ];
177 PrevInput = &WorkBlocks[ BlockLen2 * 2 ];
181 R8BCONSOLE(
"CDSPBlockConvolver: flt_len=%i in_len=%i io=%i/%i "
182 "fft=%i/%i latency=%i\n", Filter -> getKernelLen(), InputLen,
183 UpFactor, DownFactor, (*fftin) -> getLen(), (*fftout) -> getLen(),
194 return( (
int) (( Latency + (
double) ReqOutPos * DownFactor ) /
195 UpFactor + LatencyFrac * DownFactor / UpFactor ));
200 return( DoConsumeLatency ? 0 : Latency );
205 return( LatencyFrac );
212 return(( MaxInLen * UpFactor + DownFactor - 1 ) / DownFactor );
217 memset( &PrevInput[ 0 ], 0, PrevInputLen *
sizeof( PrevInput[ 0 ]));
219 if( DoConsumeLatency )
221 LatencyLeft = Latency;
229 memset( &CurOutput[ 0 ], 0, ( BlockLen2 >> DownShift ) *
230 sizeof( CurOutput[ 0 ]));
234 memset( &CurOutput[ BlockLen2 - OutOffset ], 0, OutOffset *
235 sizeof( CurOutput[ 0 ]));
237 memset( &CurOutput[ 0 ], 0, ( InputLen - OutOffset ) *
238 sizeof( CurOutput[ 0 ]));
242 memset( CurInput, 0, InputDelay *
sizeof( CurInput[ 0 ]));
244 InDataLeft = InputLen - InputDelay;
246 DownSkip = DownSkipInit;
249 virtual int process(
double* ip,
int l0,
double*& op0 )
252 R8BASSERT( UpFactor / DownFactor <= 1 || ip != op0 || l0 == 0 );
255 int l = l0 * UpFactor;
260 const int Offs = InputLen - InDataLeft;
268 memcpy( &CurInput[ Offs >> UpShift ], ip,
269 ( l >> UpShift ) *
sizeof( CurInput[ 0 ]));
273 copyUpsample( ip, &CurInput[ Offs ], l );
276 copyToOutput( Offs - OutOffset, op, l, l0 );
280 const int b = InDataLeft;
282 InDataLeft = InputLen;
287 const int bu = b >> UpShift;
288 memcpy( &CurInput[ Offs >> UpShift ], ip,
289 bu *
sizeof( CurInput[ 0 ]));
292 ilu = InputLen >> UpShift;
296 copyUpsample( ip, &CurInput[ Offs ], b );
300 const size_t pil = PrevInputLen *
sizeof( CurInput[ 0 ]);
301 memcpy( &CurInput[ ilu ], PrevInput, pil );
302 memcpy( PrevInput, &CurInput[ ilu - PrevInputLen ], pil );
304 (*fftin) -> forward( CurInput );
309 mirrorInputSpectrum( (
float*) CurInput );
311 mirrorInputSpectrum( CurInput );
315 if( Filter -> isZeroPhase() )
317 (*fftout) -> multiplyBlocksZP( Filter -> getKernelBlock(),
322 (*fftout) -> multiplyBlocks( Filter -> getKernelBlock(),
328 const int z = BlockLen2 >> DownShift;
331 float*
const kb = (
float*) Filter -> getKernelBlock();
332 float*
const p = (
float*) CurInput;
334 const double*
const kb = Filter -> getKernelBlock();
335 double*
const p = CurInput;
338 p[ 1 ] = kb[ z ] * p[ z ] - kb[ z + 1 ] * p[ z + 1 ];
341 (*fftout) -> inverse( CurInput );
343 copyToOutput( Offs - OutOffset, op, b, l0 );
345 double*
const tmp = CurInput;
346 CurInput = CurOutput;
394 bool DoConsumeLatency;
409 void copyUpsample(
double*& ip0,
double* op,
int l0 )
411 int b =
min( UpSkip, l0 );
429 const int upf = UpFactor;
431 int lz = l0 - l * upf;
462 const size_t zc = ( upf - 1 ) *
sizeof( op[ 0 ]);
469 memset( op + 1, 0, zc );
505 void copyToOutput(
int Offs,
double*& op0,
int b,
int& l0 )
515 copyToOutput( Offs + BlockLen2, op0, -Offs, l0 );
521 if( LatencyLeft != 0 )
523 if( LatencyLeft >= b )
534 const int df = DownFactor;
538 int Skip = Offs & ( df - 1 );
549 b = ( b + df - 1 ) >> DownShift;
550 memcpy( op0, &CurOutput[ Offs >> DownShift ],
551 b *
sizeof( op0[ 0 ]));
561 const double* ip = &CurOutput[ Offs + DownSkip ];
562 int l = ( b + df - 1 - DownSkip ) / df;
563 DownSkip += l * df - b;
579 memcpy( op0, &CurOutput[ Offs ], b *
sizeof( op0[ 0 ]));
595 template<
typename T >
596 void mirrorInputSpectrum( T*
const p )
598 const int bl1 = BlockLen2 >> UpShift;
599 const int bl2 = bl1 + bl1;
602 for( i = bl1 + 2; i < bl2; i += 2 )
604 p[ i ] = p[ bl2 - i ];
605 p[ i + 1 ] = -p[ bl2 - i + 1 ];
609 p[ bl1 + 1 ] = (T) 0;
612 for( i = 1; i < UpShift; i++ )
614 const int z = bl1 << i;
615 memcpy( &p[ z ], p, z *
sizeof( p[ 0 ]));
FIR filter generator and filter cache classes.
The base virtual class for DSP processing algorithms.
#define R8BASSERT(e)
Definition: r8bconf.h:27
#define R8BCONSOLE(...)
Definition: r8bconf.h:40
The "r8brain-free-src" library namespace.
Definition: CDSPBlockConvolver.h:21
T min(const T &v1, const T &v2)
Definition: r8bbase.h:1063
int getBitOccupancy(const int v)
Definition: r8bbase.h:766
Single-block overlap-save convolution processing class.
Definition: CDSPBlockConvolver.h:39
virtual int getMaxOutLen(const int MaxInLen) const
Definition: CDSPBlockConvolver.h:208
virtual double getLatencyFrac() const
Definition: CDSPBlockConvolver.h:203
virtual int getInLenBeforeOutPos(const int ReqOutPos) const
Definition: CDSPBlockConvolver.h:192
virtual int getLatency() const
Definition: CDSPBlockConvolver.h:198
virtual void clear()
Definition: CDSPBlockConvolver.h:215
CDSPBlockConvolver(CDSPFIRFilter &aFilter, const int aUpFactor, const int aDownFactor, const double PrevLatency=0.0, const bool aDoConsumeLatency=true)
Definition: CDSPBlockConvolver.h:62
virtual int process(double *ip, int l0, double *&op0)
Definition: CDSPBlockConvolver.h:249
Calculation and storage class for FIR filters.
Definition: CDSPFIRFilter.h:58
The base virtual class for DSP processing algorithms.
Definition: CDSPProcessor.h:32
A "keeper" class for real-valued FFT transform objects.
Definition: CDSPRealFFT.h:547
void alloc(const int Capacity)
Definition: r8bbase.h:343
Pointer-to-object "keeper" class with automatic deletion.
Definition: r8bbase.h:428