|
1 /* GStreamer |
|
2 * Copyright (C) <2007> Sebastian Dröge <slomo@circular-chaos.org> |
|
3 * |
|
4 * This library is free software; you can redistribute it and/or |
|
5 * modify it under the terms of the GNU Library General Public |
|
6 * License as published by the Free Software Foundation; either |
|
7 * version 2 of the License, or (at your option) any later version. |
|
8 * |
|
9 * This library is distributed in the hope that it will be useful, |
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 * Library General Public License for more details. |
|
13 * |
|
14 * You should have received a copy of the GNU Library General Public |
|
15 * License along with this library; if not, write to the |
|
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
17 * Boston, MA 02111-1307, USA. |
|
18 */ |
|
19 |
|
20 #include <glib.h> |
|
21 #include <math.h> |
|
22 |
|
23 #include "kiss_fftr_s16.h" |
|
24 #include "gstfft.h" |
|
25 #include "gstffts16.h" |
|
26 |
|
27 /** |
|
28 * SECTION:gstffts16 |
|
29 * @short_description: FFT functions for signed 16 bit integer samples |
|
30 * |
|
31 * #GstFFTS16 provides a FFT implementation and related functions for |
|
32 * signed 16 bit integer samples. To use this call gst_fft_s16_new() for |
|
33 * allocating a #GstFFTS16 instance with the appropiate parameters and |
|
34 * then call gst_fft_s16_fft() or gst_fft_s16_inverse_fft() to perform the |
|
35 * FFT or inverse FFT on a buffer of samples. |
|
36 * |
|
37 * After use free the #GstFFTS16 instance with gst_fft_s16_free(). |
|
38 * |
|
39 * For the best performance use gst_fft_next_fast_length() to get a |
|
40 * number that is entirely a product of 2, 3 and 5 and use this as the |
|
41 * @len parameter for gst_fft_s16_new(). |
|
42 * |
|
43 * The @len parameter specifies the number of samples in the time domain that |
|
44 * will be processed or generated. The number of samples in the frequency domain |
|
45 * is @len/2 + 1. To get n samples in the frequency domain use 2*n - 2 as @len. |
|
46 * |
|
47 * Before performing the FFT on time domain data it usually makes sense |
|
48 * to apply a window function to it. For this gst_fft_s16_window() can comfortably |
|
49 * be used. |
|
50 * |
|
51 * Be aware, that you can't simply run gst_fft_s16_inverse_fft() on the |
|
52 * resulting frequency data of gst_fft_s16_fft() to get the original data back. |
|
53 * The relation between them is iFFT (FFT (x)) = x / nfft where nfft is the |
|
54 * length of the FFT. This also has to be taken into account when calculation |
|
55 * the magnitude of the frequency data. |
|
56 * |
|
57 */ |
|
58 |
|
59 /** |
|
60 * gst_fft_s16_new: |
|
61 * @len: Length of the FFT in the time domain |
|
62 * @inverse: %TRUE if the #GstFFTS16 instance should be used for the inverse FFT |
|
63 * |
|
64 * This returns a new #GstFFTS16 instance with the given parameters. It makes |
|
65 * sense to keep one instance for several calls for speed reasons. |
|
66 * |
|
67 * @len must be even and to get the best performance a product of |
|
68 * 2, 3 and 5. To get the next number with this characteristics use |
|
69 * gst_fft_next_fast_length(). |
|
70 * |
|
71 * Returns: a new #GstFFTS16 instance. |
|
72 */ |
|
73 #ifdef __SYMBIAN32__ |
|
74 EXPORT_C |
|
75 #endif |
|
76 |
|
77 GstFFTS16 * |
|
78 gst_fft_s16_new (gint len, gboolean inverse) |
|
79 { |
|
80 GstFFTS16 *self; |
|
81 |
|
82 g_return_val_if_fail (len > 0, NULL); |
|
83 g_return_val_if_fail (len % 2 == 0, NULL); |
|
84 |
|
85 self = g_new (GstFFTS16, 1); |
|
86 |
|
87 self->cfg = kiss_fftr_s16_alloc (len, (inverse) ? 1 : 0, NULL, NULL); |
|
88 g_assert (self->cfg); |
|
89 |
|
90 self->inverse = inverse; |
|
91 self->len = len; |
|
92 |
|
93 return self; |
|
94 } |
|
95 |
|
96 /** |
|
97 * gst_fft_s16_fft: |
|
98 * @self: #GstFFTS16 instance for this call |
|
99 * @timedata: Buffer of the samples in the time domain |
|
100 * @freqdata: Target buffer for the samples in the frequency domain |
|
101 * |
|
102 * This performs the FFT on @timedata and puts the result in @freqdata. |
|
103 * |
|
104 * @timedata must have as many samples as specified with the @len parameter while |
|
105 * allocating the #GstFFTS16 instance with gst_fft_s16_new(). |
|
106 * |
|
107 * @freqdata must be large enough to hold @len/2 + 1 #GstFFTS16Complex frequency |
|
108 * domain samples. |
|
109 * |
|
110 */ |
|
111 #ifdef __SYMBIAN32__ |
|
112 EXPORT_C |
|
113 #endif |
|
114 |
|
115 void |
|
116 gst_fft_s16_fft (GstFFTS16 * self, const gint16 * timedata, |
|
117 GstFFTS16Complex * freqdata) |
|
118 { |
|
119 g_return_if_fail (self); |
|
120 g_return_if_fail (!self->inverse); |
|
121 g_return_if_fail (timedata); |
|
122 g_return_if_fail (freqdata); |
|
123 |
|
124 kiss_fftr_s16 (self->cfg, timedata, (kiss_fft_s16_cpx *) freqdata); |
|
125 } |
|
126 |
|
127 /** |
|
128 * gst_fft_s16_inverse_fft: |
|
129 * @self: #GstFFTS16 instance for this call |
|
130 * @freqdata: Buffer of the samples in the frequency domain |
|
131 * @timedata: Target buffer for the samples in the time domain |
|
132 * |
|
133 * This performs the inverse FFT on @freqdata and puts the result in @timedata. |
|
134 * |
|
135 * @freqdata must have @len/2 + 1 samples, where @len is the parameter specified |
|
136 * while allocating the #GstFFTS16 instance with gst_fft_s16_new(). |
|
137 * |
|
138 * @timedata must be large enough to hold @len time domain samples. |
|
139 * |
|
140 */ |
|
141 #ifdef __SYMBIAN32__ |
|
142 EXPORT_C |
|
143 #endif |
|
144 |
|
145 void |
|
146 gst_fft_s16_inverse_fft (GstFFTS16 * self, const GstFFTS16Complex * freqdata, |
|
147 gint16 * timedata) |
|
148 { |
|
149 g_return_if_fail (self); |
|
150 g_return_if_fail (self->inverse); |
|
151 g_return_if_fail (timedata); |
|
152 g_return_if_fail (freqdata); |
|
153 |
|
154 kiss_fftri_s16 (self->cfg, (kiss_fft_s16_cpx *) freqdata, timedata); |
|
155 } |
|
156 |
|
157 /** |
|
158 * gst_fft_s16_free: |
|
159 * @self: #GstFFTS16 instance for this call |
|
160 * |
|
161 * This frees the memory allocated for @self. |
|
162 * |
|
163 */ |
|
164 #ifdef __SYMBIAN32__ |
|
165 EXPORT_C |
|
166 #endif |
|
167 |
|
168 void |
|
169 gst_fft_s16_free (GstFFTS16 * self) |
|
170 { |
|
171 kiss_fftr_s16_free (self->cfg); |
|
172 g_free (self); |
|
173 } |
|
174 |
|
175 /** |
|
176 * gst_fft_s16_window: |
|
177 * @self: #GstFFTS16 instance for this call |
|
178 * @timedata: Time domain samples |
|
179 * @window: Window function to apply |
|
180 * |
|
181 * This calls the window function @window on the @timedata sample buffer. |
|
182 * |
|
183 */ |
|
184 #ifdef __SYMBIAN32__ |
|
185 EXPORT_C |
|
186 #endif |
|
187 |
|
188 void |
|
189 gst_fft_s16_window (GstFFTS16 * self, gint16 * timedata, GstFFTWindow window) |
|
190 { |
|
191 gint i, len; |
|
192 |
|
193 g_return_if_fail (self); |
|
194 g_return_if_fail (timedata); |
|
195 |
|
196 len = self->len; |
|
197 |
|
198 switch (window) { |
|
199 case GST_FFT_WINDOW_RECTANGULAR: |
|
200 /* do nothing */ |
|
201 break; |
|
202 case GST_FFT_WINDOW_HAMMING: |
|
203 for (i = 0; i < len; i++) |
|
204 timedata[i] *= (0.53836 - 0.46164 * cos (2.0 * M_PI * i / len)); |
|
205 break; |
|
206 case GST_FFT_WINDOW_HANN: |
|
207 for (i = 0; i < len; i++) |
|
208 timedata[i] *= (0.5 - 0.5 * cos (2.0 * M_PI * i / len)); |
|
209 break; |
|
210 case GST_FFT_WINDOW_BARTLETT: |
|
211 for (i = 0; i < len; i++) |
|
212 timedata[i] *= (1.0 - fabs ((2.0 * i - len) / len)); |
|
213 break; |
|
214 case GST_FFT_WINDOW_BLACKMAN: |
|
215 for (i = 0; i < len; i++) |
|
216 timedata[i] *= (0.42 - 0.5 * cos ((2.0 * i) / len) + |
|
217 0.08 * cos ((4.0 * i) / len)); |
|
218 break; |
|
219 default: |
|
220 g_assert_not_reached (); |
|
221 break; |
|
222 } |
|
223 } |