andrew@0
|
1 //
|
andrew@0
|
2 // accFFT.cpp
|
andrew@0
|
3 // AccelerateFFTtool
|
andrew@0
|
4 //
|
andrew@0
|
5 // Created by Adam Stark on 17/07/2012.
|
andrew@0
|
6 // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
|
andrew@0
|
7 //
|
andrew@0
|
8
|
andrew@0
|
9 #include "accFFT.h"
|
andrew@0
|
10
|
andrew@0
|
11
|
andrew@0
|
12 accFFT :: accFFT(int fft_size,int type)
|
andrew@0
|
13 {
|
andrew@0
|
14 fft_type = type;
|
andrew@0
|
15
|
andrew@0
|
16 fftSize = fft_size;
|
andrew@0
|
17 fftSizeOver2 = fftSize/2;
|
andrew@0
|
18 log2n = log2f(fftSize);
|
andrew@0
|
19 log2nOver2 = log2n/2;
|
andrew@0
|
20
|
andrew@0
|
21 if (fft_type == 0)
|
andrew@0
|
22 {
|
andrew@0
|
23 split.realp = (float *) malloc(fftSize * sizeof(float));
|
andrew@0
|
24 split.imagp = (float *) malloc(fftSize * sizeof(float));
|
andrew@0
|
25
|
andrew@0
|
26 // allocate the fft object once
|
andrew@0
|
27 fftSetup = vDSP_create_fftsetup(log2n, FFT_RADIX2);
|
andrew@0
|
28 if (fftSetup == NULL) {
|
andrew@0
|
29 //printf("FFT Setup failed\n");
|
andrew@0
|
30 }
|
andrew@0
|
31 }
|
andrew@0
|
32 else if (fft_type == 1)
|
andrew@0
|
33 {
|
andrew@0
|
34 d_split.realp = (double *) malloc(fftSize * sizeof(double));
|
andrew@0
|
35 d_split.imagp = (double *) malloc(fftSize * sizeof(double));
|
andrew@0
|
36
|
andrew@0
|
37 // allocate the fft object once
|
andrew@0
|
38 fftSetupD = vDSP_create_fftsetupD(log2n, FFT_RADIX2);
|
andrew@0
|
39 if (fftSetupD == NULL) {
|
andrew@0
|
40 //printf("FFT Setup failed\n");
|
andrew@0
|
41 }
|
andrew@0
|
42 }
|
andrew@0
|
43
|
andrew@0
|
44
|
andrew@0
|
45
|
andrew@0
|
46 }
|
andrew@0
|
47
|
andrew@0
|
48 accFFT :: ~accFFT()
|
andrew@0
|
49 {
|
andrew@6
|
50 printf("accFFT destructor\n");
|
andrew@0
|
51 if (fft_type == 0)
|
andrew@0
|
52 {
|
andrew@0
|
53 free(split.realp);
|
andrew@0
|
54 free(split.imagp);
|
andrew@0
|
55 vDSP_destroy_fftsetup(fftSetup);
|
andrew@0
|
56 }
|
andrew@0
|
57 else if (fft_type == 1)
|
andrew@0
|
58 {
|
andrew@0
|
59 free(d_split.realp);
|
andrew@0
|
60 free(d_split.imagp);
|
andrew@0
|
61 vDSP_destroy_fftsetupD(fftSetupD);
|
andrew@0
|
62 }
|
andrew@0
|
63
|
andrew@0
|
64
|
andrew@0
|
65 }
|
andrew@0
|
66
|
andrew@0
|
67 void accFFT :: forward_FFT_f(float *buffer,float *real,float *imag)
|
andrew@0
|
68 {
|
andrew@0
|
69 //convert to split complex format with evens in real and odds in imag
|
andrew@0
|
70 vDSP_ctoz((COMPLEX *) buffer, 2, &split, 1, fftSizeOver2);
|
andrew@0
|
71
|
andrew@0
|
72 //calc fft
|
andrew@0
|
73 vDSP_fft_zrip(fftSetup, &split, 1, log2n, FFT_FORWARD);
|
andrew@0
|
74
|
andrew@0
|
75 // set Nyquist component to imaginary of 0 component
|
andrew@0
|
76 split.realp[fftSizeOver2] = split.imagp[0];
|
andrew@0
|
77 split.imagp[fftSizeOver2] = 0.0;
|
andrew@0
|
78
|
andrew@0
|
79 // set 0 component to zero
|
andrew@0
|
80 split.imagp[0] = 0.0;
|
andrew@0
|
81
|
andrew@0
|
82 // multiply by 0.5 to get correct output (to do with Apple's FFT implementation)
|
andrew@0
|
83 for (i = 0; i <= fftSizeOver2; i++)
|
andrew@0
|
84 {
|
andrew@0
|
85 split.realp[i] *= 0.5;
|
andrew@0
|
86 split.imagp[i] *= 0.5;
|
andrew@0
|
87 }
|
andrew@0
|
88
|
andrew@0
|
89 // set values above N/2+1 which are complex conjugate mirror image of those below
|
andrew@0
|
90 for (i = fftSizeOver2 - 1;i > 0;--i)
|
andrew@0
|
91 {
|
andrew@0
|
92 split.realp[2*fftSizeOver2 - i] = split.realp[i];
|
andrew@0
|
93 split.imagp[2*fftSizeOver2 - i] = -1*split.imagp[i];
|
andrew@0
|
94
|
andrew@0
|
95 //cout << split_data.realp[2*fftSizeOver2 - i] << " " << split_data.imagp[2*fftSizeOver2 - i] << "i" << endl;
|
andrew@0
|
96 }
|
andrew@0
|
97
|
andrew@0
|
98 for (i = 0;i < fftSize;i++)
|
andrew@0
|
99 {
|
andrew@0
|
100 real[i] = split.realp[i];
|
andrew@0
|
101 imag[i] = split.imagp[i];
|
andrew@0
|
102 }
|
andrew@0
|
103 }
|
andrew@0
|
104
|
andrew@0
|
105
|
andrew@0
|
106
|
andrew@0
|
107 void accFFT :: forward_FFT_d(double *buffer,fft_complex *out)
|
andrew@0
|
108 {
|
andrew@0
|
109 //convert to split complex format with evens in real and odds in imag
|
andrew@0
|
110 vDSP_ctozD((DOUBLE_COMPLEX *) buffer, 2, &d_split, 1, fftSizeOver2);
|
andrew@0
|
111
|
andrew@0
|
112 //calc fft
|
andrew@0
|
113 vDSP_fft_zripD(fftSetupD, &d_split, 1, log2n, FFT_FORWARD);
|
andrew@0
|
114
|
andrew@0
|
115 // set Nyquist component to imaginary of 0 component
|
andrew@0
|
116 d_split.realp[fftSizeOver2] = d_split.imagp[0];
|
andrew@0
|
117 d_split.imagp[fftSizeOver2] = 0.0;
|
andrew@0
|
118
|
andrew@0
|
119 // set 0 component to zero
|
andrew@0
|
120 d_split.imagp[0] = 0.0;
|
andrew@0
|
121
|
andrew@0
|
122 // multiply by 0.5 to get correct output (to do with Apple's FFT implementation)
|
andrew@0
|
123 for (i = 0; i <= fftSizeOver2; i++)
|
andrew@0
|
124 {
|
andrew@0
|
125 d_split.realp[i] *= 0.5;
|
andrew@0
|
126 d_split.imagp[i] *= 0.5;
|
andrew@0
|
127 }
|
andrew@0
|
128
|
andrew@0
|
129 // set values above N/2+1 which are complex conjugate mirror image of those below
|
andrew@0
|
130 for (i = fftSizeOver2 - 1;i > 0;--i)
|
andrew@0
|
131 {
|
andrew@0
|
132 d_split.realp[2*fftSizeOver2 - i] = d_split.realp[i];
|
andrew@0
|
133 d_split.imagp[2*fftSizeOver2 - i] = -1*d_split.imagp[i];
|
andrew@0
|
134 }
|
andrew@0
|
135
|
andrew@0
|
136 for (i = 0;i < fftSize;i++)
|
andrew@0
|
137 {
|
andrew@0
|
138 out[i][0] = d_split.realp[i];
|
andrew@0
|
139 out[i][1] = d_split.imagp[i];
|
andrew@0
|
140 }
|
andrew@0
|
141 } |