19#ifndef R8B_CDSPREALFFT_INCLUDED
20#define R8B_CDSPREALFFT_INCLUDED
25 #include "fft/pffft_double.h"
27 #include "fft/pffft.h"
29 #include "fft/fft4g.h"
58 friend class CDSPRealFFTKeeper;
68 return( InvMulConst );
102 float*
const op = (
float*) p;
105 for( i = 0; i < Len; i++ )
107 op[ i ] = (float) p[ i ];
114 ippsFFTFwd_RToPerm_64f( p, p, SPtr, WorkBuffer );
118 pffft_transform_ordered( setup, op, op, work, PFFFT_FORWARD );
120 #elif R8B_PFFFT_DOUBLE
122 pffftd_transform_ordered( setup, p, p, work, PFFFT_FORWARD );
126 ooura_fft :: rdft( Len, 1, p, wi, wd );
142 ippsFFTInv_PermToR_64f( p, p, SPtr, WorkBuffer );
146 pffft_transform_ordered( setup, (
float*) p, (
float*) p, work,
149 #elif R8B_PFFFT_DOUBLE
151 pffftd_transform_ordered( setup, p, p, work, PFFFT_BACKWARD );
155 ooura_fft :: rdft( Len, -1, p, wi, wd );
161 const float*
const ip = (
const float*) p;
164 for( i = Len - 1; i >= 0; i-- )
187 double*
const aop )
const
191 const float*
const ip1 = (
const float*) aip1;
192 const float*
const ip2 = (
const float*) aip2;
193 float*
const op = (
float*) aop;
197 const double*
const ip1 = aip1;
198 const double*
const ip2 = aip2;
199 double*
const op = aop;
205 ippsMulPerm_64f( (Ipp64f*) ip1, (Ipp64f*) ip2, (Ipp64f*) op, Len );
209 op[ 0 ] = ip1[ 0 ] * ip2[ 0 ];
210 op[ 1 ] = ip1[ 1 ] * ip2[ 1 ];
216 op[ i ] = ip1[ i ] * ip2[ i ] - ip1[ i + 1 ] * ip2[ i + 1 ];
217 op[ i + 1 ] = ip1[ i ] * ip2[ i + 1 ] + ip1[ i + 1 ] * ip2[ i ];
239 const float*
const ip = (
const float*) aip;
240 float*
const op = (
float*) aop;
245 const double*
const ip = aip;
246 double*
const op = aop;
256 ippsMulPerm_64f( (Ipp64f*) op, (Ipp64f*) ip, (Ipp64f*) op, Len );
267 t = op[ i ] * ip[ i ] - op[ i + 1 ] * ip[ i + 1 ];
268 op[ i + 1 ] = op[ i ] * ip[ i + 1 ] + op[ i + 1 ] * ip[ i ];
293 const float*
const ip = (
const float*) aip;
294 float*
const op = (
float*) aop;
298 const double* ip = aip;
305 #if !R8B_FLOATFFT && defined( R8B_SSE2 )
311 const __m128d iv1 = _mm_load_pd( ip );
312 const __m128d iv2 = _mm_load_pd( ip + 2 );
313 const __m128d ov1 = _mm_load_pd( op );
314 const __m128d ov2 = _mm_load_pd( op + 2 );
315 _mm_store_pd( op, _mm_mul_pd( iv1, ov1 ));
316 _mm_store_pd( op + 2, _mm_mul_pd( iv2, ov2 ));
318 const __m128d iv3 = _mm_load_pd( ip + 4 );
319 const __m128d ov3 = _mm_load_pd( op + 4 );
320 const __m128d iv4 = _mm_load_pd( ip + 6 );
321 const __m128d ov4 = _mm_load_pd( op + 6 );
322 _mm_store_pd( op + 4, _mm_mul_pd( iv3, ov3 ));
323 _mm_store_pd( op + 6, _mm_mul_pd( iv4, ov4 ));
340 #elif !R8B_FLOATFFT && defined( R8B_NEON )
346 const float64x2_t iv1 = vld1q_f64( ip );
347 const float64x2_t iv2 = vld1q_f64( ip + 2 );
348 const float64x2_t ov1 = vld1q_f64( op );
349 const float64x2_t ov2 = vld1q_f64( op + 2 );
350 vst1q_f64( op, vmulq_f64( iv1, ov1 ));
351 vst1q_f64( op + 2, vmulq_f64( iv2, ov2 ));
353 const float64x2_t iv3 = vld1q_f64( ip + 4 );
354 const float64x2_t iv4 = vld1q_f64( ip + 6 );
355 const float64x2_t ov3 = vld1q_f64( op + 4 );
356 const float64x2_t ov4 = vld1q_f64( op + 6 );
357 vst1q_f64( op + 4, vmulq_f64( iv3, ov3 ));
358 vst1q_f64( op + 6, vmulq_f64( iv4, ov4 ));
379 for( i = 0; i < Len; i++ )
399 float*
const p = (
float*) ap;
403 double*
const p = ap;
423 IppsFFTSpec_R_64f* SPtr;
430 #elif R8B_PFFFT_DOUBLE
450 CDSPRealFFT(
const int aLenBits )
451 : LenBits( aLenBits )
452 , Len( 1 << aLenBits )
454 , InvMulConst( 1.0 / Len )
456 , InvMulConst( 1.0 / Len )
458 , InvMulConst( 1.0 / Len )
460 , InvMulConst( 2.0 / Len )
469 ippsFFTGetSize_R_64f( LenBits, IPP_FFT_NODIV_BY_ANY,
470 ippAlgHintFast, &SpecSize, &SpecBufferSize, &BufferSize );
472 CFixedBuffer< unsigned char > InitBuffer( SpecBufferSize );
473 SpecBuffer.
alloc( SpecSize );
474 WorkBuffer.
alloc( BufferSize );
476 ippsFFTInit_R_64f( &SPtr, LenBits, IPP_FFT_NODIV_BY_ANY,
477 ippAlgHintFast, SpecBuffer, InitBuffer );
481 setup = pffft_new_setup( Len, PFFFT_REAL );
484 #elif R8B_PFFFT_DOUBLE
486 setup = pffftd_new_setup( Len, PFFFT_REAL );
491 wi.
alloc( (
int) ceil( 2.0 + sqrt( (
double) ( Len >> 1 ))));
493 wd.
alloc( Len >> 1 );
501 pffft_destroy_setup( setup );
502 #elif R8B_PFFFT_DOUBLE
503 pffftd_destroy_setup( setup );
537 Object = acquire( LenBits );
571 if( Object -> LenBits == LenBits )
579 Object = acquire( LenBits );
606 R8BASSERT( LenBits > 0 && LenBits <= 30 );
610 if( getFFTObjects()[ LenBits ] ==
R8B_NULL )
615 CDSPRealFFT* ffto = getFFTObjects()[ LenBits ].unkeep();
616 getFFTObjects()[ LenBits ] = ffto -> Next;
627 void release( CDSPRealFFT*
const ffto )
631 ffto -> Next = getFFTObjects()[ ffto -> LenBits ].unkeep();
632 getFFTObjects()[ ffto -> LenBits ] = ffto;
639 static CPtrKeeper< CDSPRealFFT >* getFFTObjects()
641 R8B_EXITDTOR static CPtrKeeper< CDSPRealFFT > FFTObjects[ 31 ];
643 return( FFTObjects );
650 static CSyncObject& getStateSync()
682 const int LenMult = 2,
const bool DoFinalMul =
true,
683 double*
const DCGroupDelay =
R8B_NULL )
689 const int Len = 1 << LenBits;
690 const int Len2 = Len >> 1;
696 memcpy( &ip[ 0 ], Kernel, (
size_t) KernelLen *
sizeof( ip[ 0 ]));
697 memset( &ip[ KernelLen ], 0,
698 (
size_t) ( Len - KernelLen ) *
sizeof( ip[ 0 ]));
701 ffto -> forward( ip );
707 float*
const aip = (
float*) &ip[ 0 ];
708 float*
const aip2 = (
float*) &ip2[ 0 ];
709 const float nzbias = 1e-35;
711 double*
const aip = &ip[ 0 ];
712 double*
const aip2 = &ip2[ 0 ];
713 const double nzbias = 1e-300;
716 aip2[ 0 ] = aip[ 0 ];
717 aip[ 0 ] = log( fabs( aip[ 0 ]) + nzbias );
718 aip2[ Len2 ] = aip[ 1 ];
719 aip[ 1 ] = log( fabs( aip[ 1 ]) + nzbias );
721 for( i = 1; i < Len2; i++ )
723 aip2[ i ] = sqrt( aip[ i * 2 ] * aip[ i * 2 ] +
724 aip[ i * 2 + 1 ] * aip[ i * 2 + 1 ]);
726 aip[ i * 2 ] = log( aip2[ i ] + nzbias );
727 aip[ i * 2 + 1 ] = 0.0;
732 ffto -> inverse( ip );
734 const double m1 = ffto -> getInvMulConst();
735 const double m2 = -m1;
739 for( i = 1; i < Len2; i++ )
746 for( i = Len2 + 1; i < Len; i++ )
755 ffto -> forward( ip );
757 aip[ 0 ] = aip2[ 0 ];
758 aip[ 1 ] = aip2[ Len2 ];
760 for( i = 1; i < Len2; i++ )
762 aip[ i * 2 + 0 ] = cos( aip[ i * 2 + 1 ]) * aip2[ i ];
763 aip[ i * 2 + 1 ] = sin( aip[ i * 2 + 1 ]) * aip2[ i ];
766 ffto -> inverse( ip );
770 for( i = 0; i < KernelLen; i++ )
772 Kernel[ i ] = ip[ i ] * m1;
777 memcpy( &Kernel[ 0 ], &ip[ 0 ],
778 (
size_t) KernelLen *
sizeof( Kernel[ 0 ]));
The "base" header file with basic classes and functions.
#define R8BSYNC(SyncObject)
Thread synchronization macro.
Definition r8bbase.h:655
#define R8B_EXITDTOR
Macro that defines the attribute specifying that the exit-time destructor should be called for a stat...
Definition r8bbase.h:149
#define R8B_NULL
The "null pointer" value, portable between C++11 and earlier C++ versions.
Definition r8bbase.h:101
#define R8BNOCTOR(ClassName)
Macro that defines empty copy-constructor and copy operator with the "private:" prefix.
Definition r8bbase.h:198
#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 R8B_PFFFT
When defined as 1, enables PFFFT routines which are fast, but which are limited to 24-bit precision.
Definition r8bconf.h:183
#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:56
#define R8B_PFFFT_DOUBLE
When defined as 1, enables PFFFT "double" routines which are fast, and which provide the highest prec...
Definition r8bconf.h:171
#define R8B_IPP
Set this macro definition to 1 to enable the use of Intel IPP's fast Fourier transform functions....
Definition r8bconf.h:159
The "r8brain-free-src" library namespace.
Definition CDSPBlockConvolver.h:22
double calcFIRFilterGroupDelay(const double *const flt, const int fltlen, const double th)
FIR filter's group delay calculation function.
Definition r8bbase.h:876
int getBitOccupancy(const int v)
Calculate the exact number of bits a value needs for representation.
Definition r8bbase.h:766
void calcMinPhaseTransform(double *const Kernel, const int KernelLen, const int LenMult=2, const bool DoFinalMul=true, double *const DCGroupDelay=R8B_NULL)
Calculates the minimum-phase transform of the filter kernel, using a discrete Hilbert transform in ce...
Definition CDSPRealFFT.h:681
Real-valued FFT transform class.
Definition CDSPRealFFT.h:54
int getLenBits() const
Returns the length (the number of real values in a transform) of this FFT object, expressed as Nth po...
Definition CDSPRealFFT.h:76
void convertToZP(double *const ap) const
Converts the specified forward-transformed block into "zero-phase" form, suitable for use with the mu...
Definition CDSPRealFFT.h:395
void multiplyBlocks(const double *const aip, double *const aop) const
Nultiplies two complex-valued data blocks in-place.
Definition CDSPRealFFT.h:235
double getInvMulConst() const
Return a multiplication constant that should be used after inverse transform to obtain a correct valu...
Definition CDSPRealFFT.h:66
void inverse(double *const p) const
Performs in-place inverse FFT.
Definition CDSPRealFFT.h:138
void multiplyBlocks(const double *const aip1, const double *const aip2, double *const aop) const
Multiplies two complex-valued data blocks and places result in a new data block.
Definition CDSPRealFFT.h:186
void forward(double *const p) const
Performs in-place forward FFT.
Definition CDSPRealFFT.h:98
int getLen() const
Returns the length (the number of real values in a transform) of this FFT object.
Definition CDSPRealFFT.h:86
void multiplyBlocksZP(const double *const aip, double *const aop) const
Multiplies two complex-valued data blocks in-place, considering that the aip block contains "zero-pha...
Definition CDSPRealFFT.h:289
A "keeper" class for real-valued FFT transform objects.
Definition CDSPRealFFT.h:519
void init(const int LenBits)
Acquires FFT object with the specified block length. This function can be called any number of times.
Definition CDSPRealFFT.h:567
void reset()
Releases a previously acquired FFT object.
Definition CDSPRealFFT.h:586
CDSPRealFFTKeeper(const int LenBits)
Acquires FFT object with the specified block length.
Definition CDSPRealFFT.h:535
const CDSPRealFFT * operator->() const
Returns pointer to the acquired FFT object.
Definition CDSPRealFFT.h:552
Templated memory buffer class for element buffers of fixed capacity.
Definition r8bbase.h:281
void alloc(const int Capacity)
Allocates memory so that the specified number of elements of type T can be stored in this buffer obje...
Definition r8bbase.h:320
Pointer-to-object "keeper" class with automatic deletion.
Definition r8bbase.h:405