r8brain-free-src
High-quality pro audio sample rate converter library
 
Loading...
Searching...
No Matches
CDSPRealFFT.h
Go to the documentation of this file.
1//$ nobt
2//$ nocpp
3
18
19#ifndef R8B_CDSPREALFFT_INCLUDED
20#define R8B_CDSPREALFFT_INCLUDED
21
22#include "r8bbase.h"
23
24#if R8B_PFFFT_DOUBLE
25 #include "fft/pffft_double.h"
26#elif R8B_PFFFT
27 #include "fft/pffft.h"
28#elif !R8B_IPP
29 #include "fft/fft4g.h"
30#endif // !R8B_IPP
31
32namespace r8b {
33
34#if R8B_PFFFT
35 typedef float realfft_t;
36#else // R8B_PFFFT
37 typedef double realfft_t;
38#endif // R8B_PFFFT
39
47
48class CDSPRealFFTSetup : public R8B_BASECLASS
49{
50 R8BNOCTOR( CDSPRealFFTSetup )
51
52 friend class CPtrKeeper< CDSPRealFFTSetup >;
53 friend class CDSPRealFFT;
54 friend class CDSPRealFFTKeeper;
55
56public:
61
62 double getInvMulConst() const
63 {
64 return( InvMulConst );
65 }
66
71
72 int getLenBits() const
73 {
74 return( LenBits );
75 }
76
81
82 int getLen() const
83 {
84 return( Len );
85 }
86
87private:
88 int LenBits;
89 int Len;
90 double InvMulConst;
91
92 #if R8B_IPP
93 IppsFFTSpec_R_64f* SpecPtr;
96 int WorkBufferSize;
97 #elif R8B_PFFFT
98 PFFFT_Setup* setup;
99 #elif R8B_PFFFT_DOUBLE
100 PFFFTD_Setup* setup;
101 #else // R8B_PFFFT_DOUBLE
104 #endif // R8B_PFFFT_DOUBLE
105
113
114 CDSPRealFFTSetup( const int aLenBits )
115 : LenBits( aLenBits )
116 , Len( 1 << aLenBits )
117 #if R8B_OOURA
118 , InvMulConst( 2.0 / Len )
119 #else // R8B_OOURA
120 , InvMulConst( 1.0 / Len )
121 #endif // R8B_OOURA
122 {
123 #if R8B_IPP
124
125 int SpecBufferSize;
126 int InitBufferSize;
127
128 ippsFFTGetSize_R_64f( LenBits, IPP_FFT_NODIV_BY_ANY,
129 ippAlgHintFast, &SpecBufferSize, &InitBufferSize,
130 &WorkBufferSize );
131
132 CFixedBuffer< unsigned char > InitBuffer( InitBufferSize );
133 SpecBuffer.alloc( SpecBufferSize );
134
135 ippsFFTInit_R_64f( &SpecPtr, LenBits, IPP_FFT_NODIV_BY_ANY,
136 ippAlgHintFast, SpecBuffer, InitBuffer );
137
138 #elif R8B_PFFFT
139
140 setup = pffft_new_setup( Len, PFFFT_REAL );
141
142 #elif R8B_PFFFT_DOUBLE
143
144 setup = pffftd_new_setup( Len, PFFFT_REAL );
145
146 #else // R8B_PFFFT_DOUBLE
147
148 wi.alloc( (int) ceil( 2.0 + sqrt( (double) ( Len >> 1 ))));
149 wd.alloc( Len >> 1 );
150
151 ooura_fft :: rdftinit( Len, wi, wd );
152
153 #endif // R8B_PFFFT_DOUBLE
154 }
155
156 ~CDSPRealFFTSetup()
157 {
158 #if R8B_PFFFT
159 pffft_destroy_setup( setup );
160 #elif R8B_PFFFT_DOUBLE
161 pffftd_destroy_setup( setup );
162 #endif // R8B_PFFFT_DOUBLE
163 }
164};
165
189
190class CDSPRealFFT : public R8B_BASECLASS,
191 private CSinglyLinkedListItem< CDSPRealFFT >
192{
193 R8BNOCTOR( CDSPRealFFT )
194
195 friend class CSinglyLinkedListItem< CDSPRealFFT >;
196 friend class CPtrKeeper< CDSPRealFFT >;
197 friend class CDSPRealFFTKeeper;
198
199public:
204
205 double getInvMulConst() const
206 {
207 return( s -> InvMulConst );
208 }
209
214
215 int getLenBits() const
216 {
217 return( s -> LenBits );
218 }
219
224
225 int getLen() const
226 {
227 return( Len );
228 }
229
240
241 realfft_t* forward( double* const p ) const
242 {
243 #if R8B_IPP
244
245 ippsFFTFwd_RToPerm_64f( p, p, s -> SpecPtr, WorkBuffer );
246
247 return( p );
248
249 #elif R8B_PFFFT
250
251 float* const tp = &work[ Len ];
252 int i;
253
254 for( i = 0; i < Len; i++ )
255 {
256 tp[ i ] = (float) p[ i ];
257 }
258
259 float* const op = construct_ptr< float >( (void*) p, (size_t) Len );
260
261 pffft_transform( s -> setup, tp, op, work, PFFFT_FORWARD );
262
263 return( op );
264
265 #elif R8B_PFFFT_DOUBLE
266
267 pffftd_transform( s -> setup, p, p, work, PFFFT_FORWARD );
268
269 return( p );
270
271 #else // R8B_PFFFT_DOUBLE
272
273 ooura_fft :: rdft( Len, 1, p, s -> wi, s -> wd );
274
275 return( p );
276
277 #endif // R8B_PFFFT_DOUBLE
278 }
279
289
290 void inverse( realfft_t* const p ) const
291 {
292 #if R8B_IPP
293
294 ippsFFTInv_PermToR_64f( p, p, s -> SpecPtr, WorkBuffer );
295
296 #elif R8B_PFFFT
297
298 float* const tp = &work[ Len ];
299
300 pffft_transform( s -> setup, p, tp, work, PFFFT_BACKWARD );
301
302 double* const op = construct_ptr< double >( (void*) p, (size_t) Len );
303 int i;
304
305 for( i = 0; i < Len; i++ )
306 {
307 op[ i ] = tp[ i ];
308 }
309
310 #elif R8B_PFFFT_DOUBLE
311
312 pffftd_transform( s -> setup, p, p, work, PFFFT_BACKWARD );
313
314 #else // R8B_PFFFT_DOUBLE
315
316 ooura_fft :: rdft( Len, -1, p, s -> wi, s -> wd );
317
318 #endif // R8B_PFFFT_DOUBLE
319 }
320
330
332 {
333 #if R8B_PFFFT || R8B_PFFFT_DOUBLE
334
335 return( work );
336
337 #else // R8B_PFFFT || R8B_PFFFT_DOUBLE
338
339 return( R8B_NULL );
340
341 #endif // R8B_PFFFT || R8B_PFFFT_DOUBLE
342 }
343
353
354 realfft_t* reorderForward( realfft_t* const p, realfft_t* const op ) const
355 {
356 #if R8B_PFFFT
357
358 pffft_zreorder( s -> setup, p, op, PFFFT_FORWARD );
359
360 return( op );
361
362 #elif R8B_PFFFT_DOUBLE
363
364 pffftd_zreorder( s -> setup, p, op, PFFFT_FORWARD );
365
366 return( op );
367
368 #else // R8B_PFFFT_DOUBLE
369
370 (void) op;
371
372 return( p );
373
374 #endif // R8B_PFFFT_DOUBLE
375 }
376
387
389 double* const op ) const
390 {
391 #if R8B_PFFFT
392
393 float* const op2 = construct_ptr< float >( (void*) op, Len );
394
395 pffft_zreorder( s -> setup, ip, op2, PFFFT_BACKWARD );
396
397 return( op2 );
398
399 #elif R8B_PFFFT_DOUBLE
400
401 pffftd_zreorder( s -> setup, ip, op, PFFFT_BACKWARD );
402
403 return( op );
404
405 #else // R8B_PFFFT_DOUBLE
406
407 if( ip != op )
408 {
409 memcpy( op, ip, (size_t) Len * sizeof( double ));
410 }
411
412 return( op );
413
414 #endif // R8B_PFFFT_DOUBLE
415 }
416
423
424 static void setBinNyquist( realfft_t* const p, const realfft_t v )
425 {
426 #if R8B_PFFFT || R8B_PFFFT_DOUBLE
427
428 p[ 4 ] = v;
429
430 #else // R8B_PFFFT || R8B_PFFFT_DOUBLE
431
432 p[ 1 ] = v;
433
434 #endif // R8B_PFFFT || R8B_PFFFT_DOUBLE
435 }
436
450
451 void multiplyBlocks( const realfft_t* const ip1,
452 const realfft_t* const ip2, realfft_t* const op ) const
453 {
454 #if R8B_IPP
455
456 ippsMulPerm_64f( (Ipp64f*) ip1, (Ipp64f*) ip2, (Ipp64f*) op, Len );
457
458 #elif R8B_PFFFT
459
460 pffft_zconvolve( s -> setup, ip1, ip2, op );
461
462 #elif R8B_PFFFT_DOUBLE
463
464 pffftd_zconvolve( s -> setup, ip1, ip2, op );
465
466 #else // R8B_PFFFT_DOUBLE
467
468 op[ 0 ] = ip1[ 0 ] * ip2[ 0 ];
469 op[ 1 ] = ip1[ 1 ] * ip2[ 1 ];
470
471 int i = 2;
472
473 while( i < Len )
474 {
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 ];
477 i += 2;
478 }
479
480 #endif // R8B_PFFFT_DOUBLE
481 }
482
493
494 void multiplyBlocks( const realfft_t* const ip, realfft_t* const op ) const
495 {
496 #if R8B_IPP
497
498 ippsMulPerm_64f( (Ipp64f*) op, (Ipp64f*) ip, (Ipp64f*) op, Len );
499
500 #elif R8B_PFFFT
501
502 pffft_zconvolve( s -> setup, ip, op, op );
503
504 #elif R8B_PFFFT_DOUBLE
505
506 pffftd_zconvolve( s -> setup, ip, op, op );
507
508 #else // R8B_PFFFT_DOUBLE
509
510 op[ 0 ] *= ip[ 0 ];
511 op[ 1 ] *= ip[ 1 ];
512
513 realfft_t t;
514 int i = 2;
515
516 while( i < Len )
517 {
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 ];
520 op[ i ] = t;
521 i += 2;
522 }
523
524 #endif // R8B_PFFFT_DOUBLE
525 }
526
539
540 void multiplyBlocksZP( const realfft_t* ip, realfft_t* op ) const
541 {
542 // SIMD implementations assume that pointers are address-aligned.
543
544 #if R8B_PFFFT_DOUBLE
545
546 pffftd_zconvolve_zp( s -> setup, op, ip, op );
547
548 #elif R8B_PFFFT && defined( R8B_SSE2 )
549
550 int c16 = Len >> 4;
551
552 while( c16 != 0 )
553 {
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 ));
560
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 ));
567
568 ip += 16;
569 op += 16;
570 c16--;
571 }
572
573 int c = Len & 15;
574
575 while( c != 0 )
576 {
577 *op *= *ip;
578 ip++;
579 op++;
580 c--;
581 }
582
583 #elif R8B_PFFFT && defined( R8B_NEON )
584
585 int c16 = Len >> 4;
586
587 while( c16 != 0 )
588 {
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 ));
595
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 ));
602
603 ip += 16;
604 op += 16;
605 c16--;
606 }
607
608 int c = Len & 15;
609
610 while( c != 0 )
611 {
612 *op *= *ip;
613 ip++;
614 op++;
615 c--;
616 }
617
618 #elif !R8B_PFFFT && defined( R8B_SSE2 )
619
620 int c8 = Len >> 3;
621
622 while( c8 != 0 )
623 {
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 ));
630
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 ));
637
638 ip += 8;
639 op += 8;
640 c8--;
641 }
642
643 int c = Len & 7;
644
645 while( c != 0 )
646 {
647 *op *= *ip;
648 ip++;
649 op++;
650 c--;
651 }
652
653 #elif !R8B_PFFFT && defined( R8B_NEON )
654
655 int c8 = Len >> 3;
656
657 while( c8 != 0 )
658 {
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 ));
665
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 ));
672
673 ip += 8;
674 op += 8;
675 c8--;
676 }
677
678 int c = Len & 7;
679
680 while( c != 0 )
681 {
682 *op *= *ip;
683 ip++;
684 op++;
685 c--;
686 }
687
688 #else // SIMD
689
690 int i;
691
692 for( i = 0; i < Len; i++ )
693 {
694 op[ i ] *= ip[ i ];
695 }
696
697 #endif // SIMD
698 }
699
707
708 void convertToZP( realfft_t* const p ) const
709 {
710 #if R8B_PFFFT
711
712 pffft_zreorder( s -> setup, p, work, PFFFT_FORWARD );
713
714 int i = 2;
715
716 while( i < Len )
717 {
718 work[ i + 1 ] = work[ i ];
719 i += 2;
720 }
721
722 pffft_zreorder( s -> setup, work, p, PFFFT_BACKWARD );
723
724 #elif R8B_PFFFT_DOUBLE
725
726 pffftd_zconvert_zp( s -> setup, p, p, (double) Len );
727
728 #else // R8B_PFFFT_DOUBLE
729
730 int i = 2;
731
732 while( i < Len )
733 {
734 p[ i + 1 ] = p[ i ];
735 i += 2;
736 }
737
738 #endif // R8B_PFFFT_DOUBLE
739 }
740
741private:
742 const CDSPRealFFTSetup* s;
744 int Len;
745
746 #if R8B_IPP
748 #elif R8B_PFFFT
751 #elif R8B_PFFFT_DOUBLE
753 #endif // R8B_PFFFT_DOUBLE
754
760
761 CDSPRealFFT( const CDSPRealFFTSetup* const s0 )
762 : s( s0 )
763 , Len( s -> Len )
764 {
765 #if R8B_IPP
766
767 WorkBuffer.alloc( s -> WorkBufferSize );
768
769 #elif R8B_PFFFT
770
771 work.alloc( Len * 2 );
772
773 #elif R8B_PFFFT_DOUBLE
774
775 work.alloc( Len );
776
777 #endif // R8B_PFFFT_DOUBLE
778 }
779};
780
788
789class CDSPRealFFTKeeper : public R8B_BASECLASS
790{
791 R8BNOCTOR( CDSPRealFFTKeeper )
792
793public:
794 CDSPRealFFTKeeper()
795 : Object( R8B_NULL )
796 {
797 }
798
805
806 CDSPRealFFTKeeper( const int LenBits )
807 {
808 Object = acquire( LenBits );
809 }
810
812 {
813 if( Object != R8B_NULL )
814 {
815 release( Object );
816 }
817 }
818
822
824 {
825 R8BASSERT( Object != R8B_NULL );
826
827 return( Object );
828 }
829
837
838 void init( const int LenBits )
839 {
840 if( Object != R8B_NULL )
841 {
842 if( Object -> getLenBits() == LenBits )
843 {
844 return;
845 }
846
847 release( Object );
848 }
849
850 Object = acquire( LenBits );
851 }
852
856
857 void reset()
858 {
859 if( Object != R8B_NULL )
860 {
861 release( Object );
862 Object = R8B_NULL;
863 }
864 }
865
866private:
867 CDSPRealFFT* Object;
868
874
875 CDSPRealFFT* acquire( const int LenBits )
876 {
877 R8BASSERT( LenBits > 0 && LenBits <= 30 );
878
879 R8BSYNC( getStateSync() );
880
881 CDSPRealFFTSetup* s = getFFTSetupObjects()[ LenBits ];
882
883 if( s == R8B_NULL )
884 {
885 s = new CDSPRealFFTSetup( LenBits );
886 getFFTSetupObjects()[ LenBits ] = s;
887 }
888
889 #if R8B_OOURA
890
891 if( getFFTObjects()[ LenBits ] == R8B_NULL )
892 {
893 getFFTObjects()[ LenBits ] = new CDSPRealFFT( s );
894 }
895
896 return( getFFTObjects()[ LenBits ]);
897
898 #else // R8B_OOURA
899
900 if( getFFTObjects()[ LenBits ] == R8B_NULL )
901 {
902 return( new CDSPRealFFT( s ));
903 }
904
905 CDSPRealFFT* const ffto = getFFTObjects()[ LenBits ].unkeep();
906 getFFTObjects()[ LenBits ] = ffto -> Next;
907 ffto -> Next = R8B_NULL;
908
909 return( ffto );
910
911 #endif // R8B_OOURA
912 }
913
919
920 void release( CDSPRealFFT* const ffto )
921 {
922 #if R8B_OOURA
923
924 (void) ffto;
925
926 #else // R8B_OOURA
927
928 R8BSYNC( getStateSync() );
929
930 ffto -> Next = getFFTObjects()[ ffto -> getLenBits() ].unkeep();
931 getFFTObjects()[ ffto -> getLenBits() ] = ffto;
932
933 #endif // R8B_OOURA
934 }
935
939
940 static CPtrKeeper< CDSPRealFFTSetup >* getFFTSetupObjects()
941 {
942 R8B_EXITDTOR static CPtrKeeper< CDSPRealFFTSetup > FFTSetups[ 31 ];
943
944 return( FFTSetups );
945 }
946
950
951 static CPtrKeeper< CDSPRealFFT >* getFFTObjects()
952 {
953 R8B_EXITDTOR static CPtrKeeper< CDSPRealFFT > FFTObjects[ 31 ];
954
955 return( FFTObjects );
956 }
957
961
962 static CSyncObject& getStateSync()
963 {
964 R8B_EXITDTOR static CSyncObject StateSync;
965
966 return( StateSync );
967 }
968};
969
992
993inline void calcMinPhaseTransform( double* const Kernel, const int KernelLen,
994 const int LenMult = 2, const bool DoFinalMul = true,
995 double* const DCGroupDelay = R8B_NULL )
996{
997 R8BASSERT( KernelLen > 0 );
998 R8BASSERT( LenMult >= 2 );
999
1000 const int LenBits = getBitOccupancy(( KernelLen * LenMult ) - 1 );
1001 const int Len = 1 << LenBits;
1002 const int Len2 = Len >> 1;
1003 int i;
1004
1005 CFixedBuffer< double > ip( Len );
1006 CFixedBuffer< realfft_t > ip2( Len2 + 1 );
1007
1008 memcpy( &ip[ 0 ], Kernel, (size_t) KernelLen * sizeof( ip[ 0 ]));
1009 memset( &ip[ KernelLen ], 0,
1010 (size_t) ( Len - KernelLen ) * sizeof( ip[ 0 ]));
1011
1012 CDSPRealFFTKeeper ffto( LenBits );
1013
1014 realfft_t* aip = ffto -> reorderForward( ffto -> forward( ip ),
1015 ffto -> getWorkBuf() );
1016
1017 realfft_t* const aip2 = &ip2[ 0 ];
1018
1019 const realfft_t nzbias = ( sizeof( realfft_t ) < sizeof( double ) ?
1020 1e-35 : 1e-300 );
1021
1022 // Create the "log |c|" spectrum while saving the original power spectrum
1023 // in the "ip2" buffer.
1024
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 );
1029
1030 for( i = 1; i < Len2; i++ )
1031 {
1032 aip2[ i ] = sqrt( aip[ i * 2 ] * aip[ i * 2 ] +
1033 aip[ i * 2 + 1 ] * aip[ i * 2 + 1 ]);
1034
1035 aip[ i * 2 ] = log( aip2[ i ] + nzbias );
1036 aip[ i * 2 + 1 ] = 0.0;
1037 }
1038
1039 // Convert to cepstrum and apply discrete Hilbert transform.
1040
1041 ffto -> inverse( ffto -> reorderInverse( aip, ip ));
1042
1043 const double m1 = ffto -> getInvMulConst();
1044 const double m2 = -m1;
1045
1046 ip[ 0 ] = 0.0;
1047
1048 for( i = 1; i < Len2; i++ )
1049 {
1050 ip[ i ] *= m1;
1051 }
1052
1053 ip[ Len2 ] = 0.0;
1054
1055 for( i = Len2 + 1; i < Len; i++ )
1056 {
1057 ip[ i ] *= m2;
1058 }
1059
1060 // Convert Hilbert-transformed cepstrum back to the "log |c|" spectrum and
1061 // perform its exponentiation, multiplied by the power spectrum previously
1062 // saved in the "ip2" buffer.
1063
1064 aip = ffto -> reorderForward( ffto -> forward( ip ),
1065 ffto -> getWorkBuf() );
1066
1067 aip[ 0 ] = aip2[ 0 ];
1068 aip[ 1 ] = aip2[ Len2 ];
1069
1070 for( i = 1; i < Len2; i++ )
1071 {
1072 aip[ i * 2 + 0 ] = cos( aip[ i * 2 + 1 ]) * aip2[ i ];
1073 aip[ i * 2 + 1 ] = sin( aip[ i * 2 + 1 ]) * aip2[ i ];
1074 }
1075
1076 ffto -> inverse( ffto -> reorderInverse( aip, ip ));
1077
1078 if( DoFinalMul )
1079 {
1080 for( i = 0; i < KernelLen; i++ )
1081 {
1082 Kernel[ i ] = ip[ i ] * m1;
1083 }
1084 }
1085 else
1086 {
1087 memcpy( &Kernel[ 0 ], &ip[ 0 ],
1088 (size_t) KernelLen * sizeof( Kernel[ 0 ]));
1089 }
1090
1091 if( DCGroupDelay != R8B_NULL )
1092 {
1093 *DCGroupDelay = calcFIRFilterGroupDelay( Kernel, KernelLen, 0.0 );
1094 }
1095}
1096
1097} // namespace r8b
1098
1099#endif // R8B_CDSPREALFFT_INCLUDED
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