Mercurial > hg > libxtract
comparison src/vector.c @ 70:adcecb0b5d99
Further updated xtract_spectrum() to hopefully fix fft iteration bug and nyquist/DC inclusion. Added new boolean argument 'withDC' to select whether the DC component is required in the output
author | Jamie Bullock <jamie@postlude.co.uk> |
---|---|
date | Mon, 19 Mar 2007 18:58:21 +0000 |
parents | 99ea1aae68ec |
children | 06ee24d94059 |
comparison
equal
deleted
inserted
replaced
69:99ea1aae68ec | 70:adcecb0b5d99 |
---|---|
33 | 33 |
34 int xtract_spectrum(const float *data, const int N, const void *argv, float *result){ | 34 int xtract_spectrum(const float *data, const int N, const void *argv, float *result){ |
35 | 35 |
36 float *input, *rfft, q, temp; | 36 float *input, *rfft, q, temp; |
37 size_t bytes; | 37 size_t bytes; |
38 int n , NxN, M, vector; | 38 int n , NxN, M, vector, withDC; |
39 fftwf_plan plan; | 39 fftwf_plan plan; |
40 | 40 |
41 M = N >> 1; | 41 M = N >> 1; |
42 NxN = XTRACT_SQ(N); | 42 NxN = XTRACT_SQ(N); |
43 withDC = 0; | |
43 | 44 |
44 rfft = (float *)fftwf_malloc(N * sizeof(float)); | 45 rfft = (float *)fftwf_malloc(N * sizeof(float)); |
45 input = (float *)malloc(bytes = N * sizeof(float)); | 46 input = (float *)malloc(bytes = N * sizeof(float)); |
46 input = memcpy(input, data, bytes); | 47 input = memcpy(input, data, bytes); |
47 | 48 |
48 q = *(float *)argv; | 49 q = *(float *)argv; |
49 vector = (int)*((float *)argv+1); | 50 vector = (int)*((float *)argv+1); |
51 withDC = (int)*((float *)argv+2); | |
50 | 52 |
51 XTRACT_CHECK_q; | 53 XTRACT_CHECK_q; |
52 | 54 |
53 plan = fftwf_plan_r2r_1d(N, input, rfft, FFTW_R2HC, FFTW_ESTIMATE); | 55 plan = fftwf_plan_r2r_1d(N, input, rfft, FFTW_R2HC, FFTW_ESTIMATE); |
54 | 56 |
55 fftwf_execute(plan); | 57 fftwf_execute(plan); |
56 | 58 |
57 switch(vector){ | 59 switch(vector){ |
58 | 60 |
59 /* case XTRACT_MAGNITUDE_SPECTRUM: | |
60 for(n = 1; n < M; n++){ | |
61 result[n] = sqrt(XTRACT_SQ(rfft[n]) + | |
62 XTRACT_SQ(rfft[N - n - 1])) / N; | |
63 result[M + n] = n * q; | |
64 } | |
65 break; | |
66 */ | |
67 case XTRACT_LOG_MAGNITUDE_SPECTRUM: | 61 case XTRACT_LOG_MAGNITUDE_SPECTRUM: |
68 for(n = 1; n < M; n++){ | 62 for(n = 1; n < M; n++){ |
69 if ((temp = XTRACT_SQ(rfft[n]) + | 63 if ((temp = XTRACT_SQ(rfft[n]) + |
70 XTRACT_SQ(rfft[N - n - 1])) > XTRACT_LOG_LIMIT) | 64 XTRACT_SQ(rfft[N - n])) > XTRACT_LOG_LIMIT) |
71 temp = log(sqrt(temp) / N); | 65 temp = log(sqrt(temp) / N); |
72 else | 66 else |
73 temp = XTRACT_LOG_LIMIT_DB; | 67 temp = XTRACT_LOG_LIMIT_DB; |
74 /*Normalise*/ | 68 if(withDC) { |
75 result[n] = | 69 result[n] = |
76 (temp + XTRACT_DB_SCALE_OFFSET) / XTRACT_DB_SCALE_OFFSET; | 70 /*Normalise*/ |
77 result[M + n] = n * q; | 71 (temp + XTRACT_DB_SCALE_OFFSET) / |
72 XTRACT_DB_SCALE_OFFSET; | |
73 result[M + n + 1] = n * q; | |
74 } | |
75 else { | |
76 result[n - 1] = | |
77 (temp + XTRACT_DB_SCALE_OFFSET) / | |
78 XTRACT_DB_SCALE_OFFSET; | |
79 result[M + n - 1] = n * q; | |
80 } | |
78 } | 81 } |
79 break; | 82 break; |
80 | 83 |
81 case XTRACT_POWER_SPECTRUM: | 84 case XTRACT_POWER_SPECTRUM: |
82 for(n = 1; n < M; n++){ | 85 for(n = 1; n < M; n++){ |
83 result[n] = (XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n - 1])) | 86 if(withDC){ |
84 / NxN; | 87 result[n] = (XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) |
85 result[M + n] = n * q; | 88 / NxN; |
89 result[M + n + 1] = n * q; | |
90 } | |
91 else { | |
92 result[n - 1] = | |
93 (XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) / NxN; | |
94 result[M + n - 1] = n * q; | |
95 } | |
86 } | 96 } |
87 break; | 97 break; |
88 | 98 |
89 case XTRACT_LOG_POWER_SPECTRUM: | 99 case XTRACT_LOG_POWER_SPECTRUM: |
90 for(n = 1; n < M; n++){ | 100 for(n = 1; n < M; n++){ |
91 if ((temp = XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n - 1])) > | 101 if ((temp = XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) > |
92 XTRACT_LOG_LIMIT) | 102 XTRACT_LOG_LIMIT) |
93 temp = log(temp / NxN); | 103 temp = log(temp / NxN); |
94 else | 104 else |
95 temp = XTRACT_LOG_LIMIT_DB; | 105 temp = XTRACT_LOG_LIMIT_DB; |
96 result[n] = (temp + XTRACT_DB_SCALE_OFFSET) / | 106 if(withDC){ |
97 XTRACT_DB_SCALE_OFFSET; | 107 result[n] = (temp + XTRACT_DB_SCALE_OFFSET) / |
98 result[M + n] = n * q; | 108 XTRACT_DB_SCALE_OFFSET; |
109 result[M + n + 1] = n * q; | |
110 } | |
111 else { | |
112 result[n - 1] = (temp + XTRACT_DB_SCALE_OFFSET) / | |
113 XTRACT_DB_SCALE_OFFSET; | |
114 result[M + n - 1] = n * q; | |
115 } | |
99 } | 116 } |
100 break; | 117 break; |
101 | 118 |
102 default: | 119 default: |
103 /* MAGNITUDE_SPECTRUM */ | 120 /* MAGNITUDE_SPECTRUM */ |
104 for(n = 1; n < M; n++){ | 121 for(n = 1; n < M; n++){ |
105 result[n] = sqrt(XTRACT_SQ(rfft[n]) + | 122 if(withDC){ |
106 XTRACT_SQ(rfft[N - n - 1])) / N; | 123 result[n] = sqrt(XTRACT_SQ(rfft[n]) + |
107 result[M + n] = n * q; | 124 XTRACT_SQ(rfft[N - n])) / N; |
125 result[M + n + 1] = n * q; | |
126 } | |
127 else { | |
128 result[n - 1] = sqrt(XTRACT_SQ(rfft[n]) + | |
129 XTRACT_SQ(rfft[N - n])) / N; | |
130 result[M + n - 1] = n * q; | |
131 } | |
108 } | 132 } |
109 break; | 133 break; |
110 } | 134 } |
111 | 135 |
112 /* Set the DC component to 0 */ | 136 if(withDC){ |
113 result[0] = result[M] = 0.f; | 137 /* The DC component */ |
114 /* Set the Nyquist */ | 138 result[0] = XTRACT_SQ(rfft[0]); |
115 result[N] = q * M; | 139 result[M + 1] = 0.f; |
140 /* The Nyquist */ | |
141 result[M] = XTRACT_SQ(rfft[M]); | |
142 result[N + 1] = q * M; | |
143 } | |
144 else { | |
145 /* The Nyquist */ | |
146 result[M - 1] = XTRACT_SQ(rfft[M]); | |
147 result[N - 1] = q * M; | |
148 } | |
116 | 149 |
117 fftwf_destroy_plan(plan); | 150 fftwf_destroy_plan(plan); |
118 fftwf_free(rfft); | 151 fftwf_free(rfft); |
119 free(input); | 152 free(input); |
120 | 153 |