16#ifndef R8B_CDSPBLOCKCONVOLVER_INCLUDED
17#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,
218 (
size_t) PrevInputLen *
sizeof( PrevInput[ 0 ]));
220 if( DoConsumeLatency )
222 LatencyLeft = Latency;
230 memset( &CurOutput[ 0 ], 0,
231 (
size_t) ( BlockLen2 >> DownShift ) *
232 sizeof( CurOutput[ 0 ]));
236 memset( &CurOutput[ BlockLen2 - OutOffset ], 0,
237 (
size_t) OutOffset *
sizeof( CurOutput[ 0 ]));
239 memset( &CurOutput[ 0 ], 0,
240 (
size_t) ( InputLen - OutOffset ) *
241 sizeof( CurOutput[ 0 ]));
245 memset( CurInput, 0, (
size_t) InputDelay *
sizeof( CurInput[ 0 ]));
247 InDataLeft = InputLen - InputDelay;
249 DownSkip = DownSkipInit;
252 virtual int process(
double* ip,
int l0,
double*& op0 )
255 R8BASSERT( UpFactor / DownFactor <= 1 || ip != op0 || l0 == 0 );
258 int l = l0 * UpFactor;
263 const int Offs = InputLen - InDataLeft;
271 memcpy( &CurInput[ Offs >> UpShift ], ip,
272 (
size_t) ( l >> UpShift ) *
sizeof( CurInput[ 0 ]));
276 copyUpsample( ip, &CurInput[ Offs ], l );
279 copyToOutput( Offs - OutOffset, op, l, l0 );
283 const int b = InDataLeft;
285 InDataLeft = InputLen;
290 const int bu = b >> UpShift;
291 memcpy( &CurInput[ Offs >> UpShift ], ip,
292 (
size_t) bu *
sizeof( CurInput[ 0 ]));
295 ilu = InputLen >> UpShift;
299 copyUpsample( ip, &CurInput[ Offs ], b );
303 const size_t pil = (size_t) PrevInputLen *
sizeof( CurInput[ 0 ]);
304 memcpy( &CurInput[ ilu ], PrevInput, pil );
305 memcpy( PrevInput, &CurInput[ ilu - PrevInputLen ], pil );
307 (*fftin) -> forward( CurInput );
312 mirrorInputSpectrum( (
float*) CurInput );
314 mirrorInputSpectrum( CurInput );
318 if( Filter -> isZeroPhase() )
320 (*fftout) -> multiplyBlocksZP( Filter -> getKernelBlock(),
325 (*fftout) -> multiplyBlocks( Filter -> getKernelBlock(),
331 const int z = BlockLen2 >> DownShift;
334 float*
const kb = (
float*) Filter -> getKernelBlock();
335 float*
const p = (
float*) CurInput;
337 const double*
const kb = Filter -> getKernelBlock();
338 double*
const p = CurInput;
341 p[ 1 ] = kb[ z ] * p[ z ] - kb[ z + 1 ] * p[ z + 1 ];
344 (*fftout) -> inverse( CurInput );
346 copyToOutput( Offs - OutOffset, op, b, l0 );
348 double*
const tmp = CurInput;
349 CurInput = CurOutput;
399 bool DoConsumeLatency;
414 void copyUpsample(
double*& ip0,
double* op,
int l0 )
416 int b =
min( UpSkip, l0 );
434 const int upf = UpFactor;
436 int lz = l0 - l * upf;
467 const size_t zc = (size_t) ( upf - 1 ) *
sizeof( op[ 0 ]);
474 memset( op + 1, 0, zc );
512 void copyToOutput(
int Offs,
double*& op0,
int b,
int& l0 )
522 copyToOutput( Offs + BlockLen2, op0, -Offs, l0 );
528 if( LatencyLeft != 0 )
530 if( LatencyLeft >= b )
541 const int df = DownFactor;
545 int Skip = Offs & ( df - 1 );
556 b = ( b + df - 1 ) >> DownShift;
557 memcpy( op0, &CurOutput[ Offs >> DownShift ],
558 (
size_t) b *
sizeof( op0[ 0 ]));
568 const double* ip = &CurOutput[ Offs + DownSkip ];
569 int l = ( b + df - 1 - DownSkip ) / df;
570 DownSkip += l * df - b;
586 memcpy( op0, &CurOutput[ Offs ],
587 (
size_t) b *
sizeof( op0[ 0 ]));
606 template<
typename T >
607 void mirrorInputSpectrum( T*
const p )
609 const int bl1 = BlockLen2 >> UpShift;
610 const int bl2 = bl1 + bl1;
613 for( i = bl1 + 2; i < bl2; i += 2 )
615 p[ i ] = p[ bl2 - i ];
616 p[ i + 1 ] = -p[ bl2 - i + 1 ];
620 p[ bl1 + 1 ] = (T) 0;
623 for( i = 1; i < UpShift; i++ )
625 const int z = bl1 << i;
626 memcpy( &p[ z ], p, (
size_t) z *
sizeof( p[ 0 ]));
FIR filter generator and filter cache classes.
The base virtual class for DSP processing algorithms.
#define R8BASSERT(e)
Assertion macro used to check for certain run-time conditions. By default, no action is taken if asse...
Definition r8bconf.h:28
#define R8BCONSOLE(...)
Console output macro, used to output various resampler status strings, including filter design parame...
Definition r8bconf.h:41
The "r8brain-free-src" library namespace.
Definition CDSPBlockConvolver.h:22
T min(const T &v1, const T &v2)
Returns minimum of two values.
Definition r8bbase.h:1079
int getBitOccupancy(const int v)
Calculate the exact number of bits a value needs for representation.
Definition r8bbase.h:766
Single-block overlap-save convolution processing class.
Definition CDSPBlockConvolver.h:40
virtual int getMaxOutLen(const int MaxInLen) const
Returns the maximal length of the output buffer required when processing the MaxInLen number of input...
Definition CDSPBlockConvolver.h:208
virtual double getLatencyFrac() const
Returns fractional latency, in samples, which is present in the output signal.
Definition CDSPBlockConvolver.h:203
virtual int getInLenBeforeOutPos(const int ReqOutPos) const
Returns the number of input samples required to advance to the specified output sample position (so t...
Definition CDSPBlockConvolver.h:192
virtual int getLatency() const
Return the latency, in samples, which is present in the output signal.
Definition CDSPBlockConvolver.h:198
virtual void clear()
Clears (resets) the state of this object and returns it to the state after construction.
Definition CDSPBlockConvolver.h:215
CDSPBlockConvolver(CDSPFIRFilter &aFilter, const int aUpFactor, const int aDownFactor, const double PrevLatency=0.0, const bool aDoConsumeLatency=true)
Initializes internal variables and constants of this object.
Definition CDSPBlockConvolver.h:62
virtual int process(double *ip, int l0, double *&op0)
Performs DSP processing.
Definition CDSPBlockConvolver.h:252
Calculation and storage class for FIR filters.
Definition CDSPFIRFilter.h:59
A "keeper" class for real-valued FFT transform objects.
Definition CDSPRealFFT.h:519
Pointer-to-object "keeper" class with automatic deletion.
Definition r8bbase.h:405