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"
53 friend class CDSPRealFFT;
54 friend class CDSPRealFFTKeeper;
64 return( InvMulConst );
93 IppsFFTSpec_R_64f* SpecPtr;
99 #elif R8B_PFFFT_DOUBLE
115 : LenBits( aLenBits )
116 , Len( 1 << aLenBits )
118 , InvMulConst( 2.0 / Len )
120 , InvMulConst( 1.0 / Len )
128 ippsFFTGetSize_R_64f( LenBits, IPP_FFT_NODIV_BY_ANY,
129 ippAlgHintFast, &SpecBufferSize, &InitBufferSize,
133 SpecBuffer.
alloc( SpecBufferSize );
135 ippsFFTInit_R_64f( &SpecPtr, LenBits, IPP_FFT_NODIV_BY_ANY,
136 ippAlgHintFast, SpecBuffer, InitBuffer );
140 setup = pffft_new_setup( Len, PFFFT_REAL );
142 #elif R8B_PFFFT_DOUBLE
144 setup = pffftd_new_setup( Len, PFFFT_REAL );
148 wi.
alloc( (
int) ceil( 2.0 + sqrt( (
double) ( Len >> 1 ))));
149 wd.
alloc( Len >> 1 );
151 ooura_fft :: rdftinit( Len, wi, wd );
159 pffft_destroy_setup( setup );
160 #elif R8B_PFFFT_DOUBLE
161 pffftd_destroy_setup( setup );
191 private CSinglyLinkedListItem< CDSPRealFFT >
195 friend class CSinglyLinkedListItem< CDSPRealFFT >;
197 friend class CDSPRealFFTKeeper;
207 return( s -> InvMulConst );
217 return( s -> LenBits );
245 ippsFFTFwd_RToPerm_64f( p, p, s -> SpecPtr, WorkBuffer );
251 float*
const tp = &work[ Len ];
254 for( i = 0; i < Len; i++ )
256 tp[ i ] = (float) p[ i ];
261 pffft_transform( s -> setup, tp, op, work, PFFFT_FORWARD );
265 #elif R8B_PFFFT_DOUBLE
267 pffftd_transform( s -> setup, p, p, work, PFFFT_FORWARD );
273 ooura_fft :: rdft( Len, 1, p, s -> wi, s -> wd );
294 ippsFFTInv_PermToR_64f( p, p, s -> SpecPtr, WorkBuffer );
298 float*
const tp = &work[ Len ];
300 pffft_transform( s -> setup, p, tp, work, PFFFT_BACKWARD );
305 for( i = 0; i < Len; i++ )
310 #elif R8B_PFFFT_DOUBLE
312 pffftd_transform( s -> setup, p, p, work, PFFFT_BACKWARD );
316 ooura_fft :: rdft( Len, -1, p, s -> wi, s -> wd );
333 #if R8B_PFFFT || R8B_PFFFT_DOUBLE
358 pffft_zreorder( s -> setup, p, op, PFFFT_FORWARD );
362 #elif R8B_PFFFT_DOUBLE
364 pffftd_zreorder( s -> setup, p, op, PFFFT_FORWARD );
389 double*
const op )
const
395 pffft_zreorder( s -> setup, ip, op2, PFFFT_BACKWARD );
399 #elif R8B_PFFFT_DOUBLE
401 pffftd_zreorder( s -> setup, ip, op, PFFFT_BACKWARD );
409 memcpy( op, ip, (
size_t) Len *
sizeof(
double ));
426 #if R8B_PFFFT || R8B_PFFFT_DOUBLE
456 ippsMulPerm_64f( (Ipp64f*) ip1, (Ipp64f*) ip2, (Ipp64f*) op, Len );
460 pffft_zconvolve( s -> setup, ip1, ip2, op );
462 #elif R8B_PFFFT_DOUBLE
464 pffftd_zconvolve( s -> setup, ip1, ip2, op );
468 op[ 0 ] = ip1[ 0 ] * ip2[ 0 ];
469 op[ 1 ] = ip1[ 1 ] * ip2[ 1 ];
475 op[ i ] = ip1[ i ] * ip2[ i ] - ip1[ i + 1 ] * ip2[ i + 1 ];
476 op[ i + 1 ] = ip1[ i ] * ip2[ i + 1 ] + ip1[ i + 1 ] * ip2[ i ];
498 ippsMulPerm_64f( (Ipp64f*) op, (Ipp64f*) ip, (Ipp64f*) op, Len );
502 pffft_zconvolve( s -> setup, ip, op, op );
504 #elif R8B_PFFFT_DOUBLE
506 pffftd_zconvolve( s -> setup, ip, op, op );
518 t = op[ i ] * ip[ i ] - op[ i + 1 ] * ip[ i + 1 ];
519 op[ i + 1 ] = op[ i ] * ip[ i + 1 ] + op[ i + 1 ] * ip[ i ];
546 pffftd_zconvolve_zp( s -> setup, op, ip, op );
548 #elif R8B_PFFFT && defined( R8B_SSE2 )
554 const __m128 iv1 = _mm_load_ps( ip );
555 const __m128 iv2 = _mm_load_ps( ip + 4 );
556 const __m128 ov1 = _mm_load_ps( op );
557 const __m128 ov2 = _mm_load_ps( op + 4 );
558 _mm_store_ps( op, _mm_mul_ps( iv1, ov1 ));
559 _mm_store_ps( op + 4, _mm_mul_ps( iv2, ov2 ));
561 const __m128 iv3 = _mm_load_ps( ip + 8 );
562 const __m128 iv4 = _mm_load_ps( ip + 12 );
563 const __m128 ov3 = _mm_load_ps( op + 8 );
564 const __m128 ov4 = _mm_load_ps( op + 12 );
565 _mm_store_ps( op + 8, _mm_mul_ps( iv3, ov3 ));
566 _mm_store_ps( op + 12, _mm_mul_ps( iv4, ov4 ));
583 #elif R8B_PFFFT && defined( R8B_NEON )
589 const float32x4_t iv1 = vld1q_f32( ip );
590 const float32x4_t iv2 = vld1q_f32( ip + 4 );
591 const float32x4_t ov1 = vld1q_f32( op );
592 const float32x4_t ov2 = vld1q_f32( op + 4 );
593 vst1q_f32( op, vmulq_f32( iv1, ov1 ));
594 vst1q_f32( op + 4, vmulq_f32( iv2, ov2 ));
596 const float32x4_t iv3 = vld1q_f32( ip + 8 );
597 const float32x4_t iv4 = vld1q_f32( ip + 12 );
598 const float32x4_t ov3 = vld1q_f32( op + 8 );
599 const float32x4_t ov4 = vld1q_f32( op + 12 );
600 vst1q_f32( op + 8, vmulq_f32( iv3, ov3 ));
601 vst1q_f32( op + 12, vmulq_f32( iv4, ov4 ));
618 #elif !R8B_PFFFT && defined( R8B_SSE2 )
624 const __m128d iv1 = _mm_load_pd( ip );
625 const __m128d iv2 = _mm_load_pd( ip + 2 );
626 const __m128d ov1 = _mm_load_pd( op );
627 const __m128d ov2 = _mm_load_pd( op + 2 );
628 _mm_store_pd( op, _mm_mul_pd( iv1, ov1 ));
629 _mm_store_pd( op + 2, _mm_mul_pd( iv2, ov2 ));
631 const __m128d iv3 = _mm_load_pd( ip + 4 );
632 const __m128d iv4 = _mm_load_pd( ip + 6 );
633 const __m128d ov3 = _mm_load_pd( op + 4 );
634 const __m128d ov4 = _mm_load_pd( op + 6 );
635 _mm_store_pd( op + 4, _mm_mul_pd( iv3, ov3 ));
636 _mm_store_pd( op + 6, _mm_mul_pd( iv4, ov4 ));
653 #elif !R8B_PFFFT && defined( R8B_NEON )
659 const float64x2_t iv1 = vld1q_f64( ip );
660 const float64x2_t iv2 = vld1q_f64( ip + 2 );
661 const float64x2_t ov1 = vld1q_f64( op );
662 const float64x2_t ov2 = vld1q_f64( op + 2 );
663 vst1q_f64( op, vmulq_f64( iv1, ov1 ));
664 vst1q_f64( op + 2, vmulq_f64( iv2, ov2 ));
666 const float64x2_t iv3 = vld1q_f64( ip + 4 );
667 const float64x2_t iv4 = vld1q_f64( ip + 6 );
668 const float64x2_t ov3 = vld1q_f64( op + 4 );
669 const float64x2_t ov4 = vld1q_f64( op + 6 );
670 vst1q_f64( op + 4, vmulq_f64( iv3, ov3 ));
671 vst1q_f64( op + 6, vmulq_f64( iv4, ov4 ));
692 for( i = 0; i < Len; i++ )
712 pffft_zreorder( s -> setup, p, work, PFFFT_FORWARD );
718 work[ i + 1 ] = work[ i ];
722 pffft_zreorder( s -> setup, work, p, PFFFT_BACKWARD );
724 #elif R8B_PFFFT_DOUBLE
726 pffftd_zconvert_zp( s -> setup, p, p, (
double) Len );
751 #elif R8B_PFFFT_DOUBLE
767 WorkBuffer.
alloc( s -> WorkBufferSize );
771 work.
alloc( Len * 2 );
773 #elif R8B_PFFFT_DOUBLE
808 Object = acquire( LenBits );
842 if( Object -> getLenBits() == LenBits )
850 Object = acquire( LenBits );
877 R8BASSERT( LenBits > 0 && LenBits <= 30 );
886 getFFTSetupObjects()[ LenBits ] = s;
891 if( getFFTObjects()[ LenBits ] ==
R8B_NULL )
893 getFFTObjects()[ LenBits ] =
new CDSPRealFFT( s );
896 return( getFFTObjects()[ LenBits ]);
900 if( getFFTObjects()[ LenBits ] ==
R8B_NULL )
902 return(
new CDSPRealFFT( s ));
905 CDSPRealFFT*
const ffto = getFFTObjects()[ LenBits ].unkeep();
906 getFFTObjects()[ LenBits ] = ffto -> Next;
920 void release( CDSPRealFFT*
const ffto )
930 ffto -> Next = getFFTObjects()[ ffto -> getLenBits() ].unkeep();
931 getFFTObjects()[ ffto -> getLenBits() ] = ffto;
940 static CPtrKeeper< CDSPRealFFTSetup >* getFFTSetupObjects()
942 R8B_EXITDTOR static CPtrKeeper< CDSPRealFFTSetup > FFTSetups[ 31 ];
951 static CPtrKeeper< CDSPRealFFT >* getFFTObjects()
953 R8B_EXITDTOR static CPtrKeeper< CDSPRealFFT > FFTObjects[ 31 ];
955 return( FFTObjects );
962 static CSyncObject& getStateSync()
994 const int LenMult = 2,
const bool DoFinalMul =
true,
995 double*
const DCGroupDelay =
R8B_NULL )
1001 const int Len = 1 << LenBits;
1002 const int Len2 = Len >> 1;
1008 memcpy( &ip[ 0 ], Kernel, (
size_t) KernelLen *
sizeof( ip[ 0 ]));
1009 memset( &ip[ KernelLen ], 0,
1010 (
size_t) ( Len - KernelLen ) *
sizeof( ip[ 0 ]));
1014 realfft_t* aip = ffto -> reorderForward( ffto -> forward( ip ),
1015 ffto -> getWorkBuf() );
1025 aip2[ 0 ] = aip[ 0 ];
1026 aip[ 0 ] = log( fabs( aip[ 0 ]) + nzbias );
1027 aip2[ Len2 ] = aip[ 1 ];
1028 aip[ 1 ] = log( fabs( aip[ 1 ]) + nzbias );
1030 for( i = 1; i < Len2; i++ )
1032 aip2[ i ] = sqrt( aip[ i * 2 ] * aip[ i * 2 ] +
1033 aip[ i * 2 + 1 ] * aip[ i * 2 + 1 ]);
1035 aip[ i * 2 ] = log( aip2[ i ] + nzbias );
1036 aip[ i * 2 + 1 ] = 0.0;
1041 ffto -> inverse( ffto -> reorderInverse( aip, ip ));
1043 const double m1 = ffto -> getInvMulConst();
1044 const double m2 = -m1;
1048 for( i = 1; i < Len2; i++ )
1055 for( i = Len2 + 1; i < Len; i++ )
1064 aip = ffto -> reorderForward( ffto -> forward( ip ),
1065 ffto -> getWorkBuf() );
1067 aip[ 0 ] = aip2[ 0 ];
1068 aip[ 1 ] = aip2[ Len2 ];
1070 for( i = 1; i < Len2; i++ )
1072 aip[ i * 2 + 0 ] = cos( aip[ i * 2 + 1 ]) * aip2[ i ];
1073 aip[ i * 2 + 1 ] = sin( aip[ i * 2 + 1 ]) * aip2[ i ];
1076 ffto -> inverse( ffto -> reorderInverse( aip, ip ));
1080 for( i = 0; i < KernelLen; i++ )
1082 Kernel[ i ] = ip[ i ] * m1;
1087 memcpy( &Kernel[ 0 ], &ip[ 0 ],
1088 (
size_t) KernelLen *
sizeof( Kernel[ 0 ]));
The "base" header file with basic classes and functions.
#define R8BSYNC(SyncObject)
Thread synchronization macro.
Definition r8bbase.h:833
#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.
Definition r8bbase.h:213
#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_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_OOURA
This macro is set to 1 if the default Ooura FFT is in use.
Definition r8bconf.h:187
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:1054
double realfft_t
Forward transform's native type.
Definition CDSPRealFFT.h:37
int getBitOccupancy(const int v)
Calculate the exact number of bits a value needs for representation.
Definition r8bbase.h:944
T * construct_ptr(void *const ptr, const size_t c)
Performs placement new to turn a block of unoccupied memory into a "constructed" array of elements of...
Definition r8bbase.h:289
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:993
Real-valued FFT setup class.
Definition CDSPRealFFT.h:49
double getInvMulConst() const
Return a multiplication constant that should be used after inverse transform to obtain a correct valu...
Definition CDSPRealFFT.h:62
int getLen() const
Returns the length (the number of real values in a transform) of this FFT setup object.
Definition CDSPRealFFT.h:82
int getLenBits() const
Returns the length (the number of real values in a transform) of this FFT setup object,...
Definition CDSPRealFFT.h:72
Real-valued FFT transform class.
Definition CDSPRealFFT.h:192
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:215
double getInvMulConst() const
Return a multiplication constant that should be used after inverse transform to obtain a correct valu...
Definition CDSPRealFFT.h:205
realfft_t * reorderInverse(const realfft_t *const ip, double *const op) const
Reorders FFT bins from sequential ordering (before the inverse transform) to native ordering.
Definition CDSPRealFFT.h:388
realfft_t * reorderForward(realfft_t *const p, realfft_t *const op) const
Reorders FFT bins from native ordering (after the forward transform) to sequential ordering.
Definition CDSPRealFFT.h:354
static void setBinNyquist(realfft_t *const p, const realfft_t v)
Replaces the Nyquist FFT bin in the specified block.
Definition CDSPRealFFT.h:424
void inverse(realfft_t *const p) const
Performs in-place inverse FFT.
Definition CDSPRealFFT.h:290
void multiplyBlocks(const realfft_t *const ip1, const realfft_t *const ip2, realfft_t *const op) const
Multiplies two complex-valued data blocks and places result in a new data block.
Definition CDSPRealFFT.h:451
void multiplyBlocksZP(const realfft_t *ip, realfft_t *op) const
Multiplies two complex-valued FFT blocks in-place, considering that the ip block contains "zero-phase...
Definition CDSPRealFFT.h:540
void multiplyBlocks(const realfft_t *const ip, realfft_t *const op) const
Multiplies two complex-valued FFT blocks in-place.
Definition CDSPRealFFT.h:494
realfft_t * getWorkBuf() const
Returns pointer to the internal work buffer.
Definition CDSPRealFFT.h:331
int getLen() const
Returns the length (the number of real values in a transform) of this FFT object.
Definition CDSPRealFFT.h:225
realfft_t * forward(double *const p) const
Performs in-place forward FFT.
Definition CDSPRealFFT.h:241
void convertToZP(realfft_t *const p) const
Converts the specified forward-transformed FFT block into "zero-phase" form, suitable for use with th...
Definition CDSPRealFFT.h:708
A "keeper" class for real-valued FFT transform objects.
Definition CDSPRealFFT.h:790
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:838
void reset()
Releases a previously acquired FFT object.
Definition CDSPRealFFT.h:857
CDSPRealFFTKeeper(const int LenBits)
Acquires FFT object with the specified block length.
Definition CDSPRealFFT.h:806
const CDSPRealFFT * operator->() const
Returns pointer to the acquired FFT object.
Definition CDSPRealFFT.h:823
Templated memory buffer class for element buffers of fixed capacity.
Definition r8bbase.h:314
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:354
Pointer-to-object "keeper" class with automatic deletion.
Definition r8bbase.h:457