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@0
|
50 if (fft_type == 0)
|
andrew@0
|
51 {
|
andrew@0
|
52 free(split.realp);
|
andrew@0
|
53 free(split.imagp);
|
andrew@0
|
54 vDSP_destroy_fftsetup(fftSetup);
|
andrew@0
|
55 }
|
andrew@0
|
56 else if (fft_type == 1)
|
andrew@0
|
57 {
|
andrew@0
|
58 free(d_split.realp);
|
andrew@0
|
59 free(d_split.imagp);
|
andrew@0
|
60 vDSP_destroy_fftsetupD(fftSetupD);
|
andrew@0
|
61 }
|
andrew@0
|
62
|
andrew@0
|
63
|
andrew@0
|
64 }
|
andrew@0
|
65
|
andrew@0
|
66 void accFFT :: forward_FFT_f(float *buffer,float *real,float *imag)
|
andrew@0
|
67 {
|
andrew@0
|
68 //convert to split complex format with evens in real and odds in imag
|
andrew@0
|
69 vDSP_ctoz((COMPLEX *) buffer, 2, &split, 1, fftSizeOver2);
|
andrew@0
|
70
|
andrew@0
|
71 //calc fft
|
andrew@0
|
72 vDSP_fft_zrip(fftSetup, &split, 1, log2n, FFT_FORWARD);
|
andrew@0
|
73
|
andrew@0
|
74 // set Nyquist component to imaginary of 0 component
|
andrew@0
|
75 split.realp[fftSizeOver2] = split.imagp[0];
|
andrew@0
|
76 split.imagp[fftSizeOver2] = 0.0;
|
andrew@0
|
77
|
andrew@0
|
78 // set 0 component to zero
|
andrew@0
|
79 split.imagp[0] = 0.0;
|
andrew@0
|
80
|
andrew@0
|
81 // multiply by 0.5 to get correct output (to do with Apple's FFT implementation)
|
andrew@0
|
82 for (i = 0; i <= fftSizeOver2; i++)
|
andrew@0
|
83 {
|
andrew@0
|
84 split.realp[i] *= 0.5;
|
andrew@0
|
85 split.imagp[i] *= 0.5;
|
andrew@0
|
86 }
|
andrew@0
|
87
|
andrew@0
|
88 // set values above N/2+1 which are complex conjugate mirror image of those below
|
andrew@0
|
89 for (i = fftSizeOver2 - 1;i > 0;--i)
|
andrew@0
|
90 {
|
andrew@0
|
91 split.realp[2*fftSizeOver2 - i] = split.realp[i];
|
andrew@0
|
92 split.imagp[2*fftSizeOver2 - i] = -1*split.imagp[i];
|
andrew@0
|
93
|
andrew@0
|
94 //cout << split_data.realp[2*fftSizeOver2 - i] << " " << split_data.imagp[2*fftSizeOver2 - i] << "i" << endl;
|
andrew@0
|
95 }
|
andrew@0
|
96
|
andrew@0
|
97 for (i = 0;i < fftSize;i++)
|
andrew@0
|
98 {
|
andrew@0
|
99 real[i] = split.realp[i];
|
andrew@0
|
100 imag[i] = split.imagp[i];
|
andrew@0
|
101 }
|
andrew@0
|
102 }
|
andrew@0
|
103
|
andrew@0
|
104
|
andrew@0
|
105
|
andrew@0
|
106 void accFFT :: forward_FFT_d(double *buffer,fft_complex *out)
|
andrew@0
|
107 {
|
andrew@0
|
108 //convert to split complex format with evens in real and odds in imag
|
andrew@0
|
109 vDSP_ctozD((DOUBLE_COMPLEX *) buffer, 2, &d_split, 1, fftSizeOver2);
|
andrew@0
|
110
|
andrew@0
|
111 //calc fft
|
andrew@0
|
112 vDSP_fft_zripD(fftSetupD, &d_split, 1, log2n, FFT_FORWARD);
|
andrew@0
|
113
|
andrew@0
|
114 // set Nyquist component to imaginary of 0 component
|
andrew@0
|
115 d_split.realp[fftSizeOver2] = d_split.imagp[0];
|
andrew@0
|
116 d_split.imagp[fftSizeOver2] = 0.0;
|
andrew@0
|
117
|
andrew@0
|
118 // set 0 component to zero
|
andrew@0
|
119 d_split.imagp[0] = 0.0;
|
andrew@0
|
120
|
andrew@0
|
121 // multiply by 0.5 to get correct output (to do with Apple's FFT implementation)
|
andrew@0
|
122 for (i = 0; i <= fftSizeOver2; i++)
|
andrew@0
|
123 {
|
andrew@0
|
124 d_split.realp[i] *= 0.5;
|
andrew@0
|
125 d_split.imagp[i] *= 0.5;
|
andrew@0
|
126 }
|
andrew@0
|
127
|
andrew@0
|
128 // set values above N/2+1 which are complex conjugate mirror image of those below
|
andrew@0
|
129 for (i = fftSizeOver2 - 1;i > 0;--i)
|
andrew@0
|
130 {
|
andrew@0
|
131 d_split.realp[2*fftSizeOver2 - i] = d_split.realp[i];
|
andrew@0
|
132 d_split.imagp[2*fftSizeOver2 - i] = -1*d_split.imagp[i];
|
andrew@0
|
133 }
|
andrew@0
|
134
|
andrew@0
|
135 for (i = 0;i < fftSize;i++)
|
andrew@0
|
136 {
|
andrew@0
|
137 out[i][0] = d_split.realp[i];
|
andrew@0
|
138 out[i][1] = d_split.imagp[i];
|
andrew@0
|
139 }
|
andrew@0
|
140 } |