• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  *
3  * unit test for FFT library
4  *
5  * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include <gst/check/gstcheck.h>
28 
29 #include <gst/fft/gstfft.h>
30 #include <gst/fft/gstffts16.h>
31 #include <gst/fft/gstffts32.h>
32 #include <gst/fft/gstfftf32.h>
33 #include <gst/fft/gstfftf64.h>
34 
GST_START_TEST(test_next_fast_length)35 GST_START_TEST (test_next_fast_length)
36 {
37   fail_unless_equals_int (gst_fft_next_fast_length (13), 16);
38   fail_unless_equals_int (gst_fft_next_fast_length (30), 30);
39   fail_unless_equals_int (gst_fft_next_fast_length (31), 32);
40   fail_unless_equals_int (gst_fft_next_fast_length (1), 2);
41 }
42 
43 GST_END_TEST;
44 
GST_START_TEST(test_s16_0hz)45 GST_START_TEST (test_s16_0hz)
46 {
47   gint i;
48   gint16 *in;
49   GstFFTS16Complex *out;
50   GstFFTS16 *ctx;
51 
52   in = g_new (gint16, 2048);
53   out = g_new (GstFFTS16Complex, 1025);
54   ctx = gst_fft_s16_new (2048, FALSE);
55 
56   for (i = 0; i < 2048; i++)
57     in[i] = G_MAXINT16;
58 
59   gst_fft_s16_window (ctx, in, GST_FFT_WINDOW_HAMMING);
60   gst_fft_s16_fft (ctx, in, out);
61 
62   for (i = 0; i < 1025; i++) {
63     gdouble mag;
64 
65     mag = (gdouble) out[i].r * (gdouble) out[i].r;
66     mag += (gdouble) out[i].i * (gdouble) out[i].i;
67     mag /= 32767.0 * 32767.0;
68     mag = 10.0 * log10 (mag);
69     if (i < 2)
70       fail_unless (mag > -15.0);
71     else
72       fail_unless (mag < -55.0);
73   }
74 
75   gst_fft_s16_free (ctx);
76   g_free (in);
77   g_free (out);
78 }
79 
80 GST_END_TEST;
81 
GST_START_TEST(test_s16_11025hz)82 GST_START_TEST (test_s16_11025hz)
83 {
84   gint i;
85   gint16 *in;
86   GstFFTS16Complex *out;
87   GstFFTS16 *ctx;
88 
89   in = g_new (gint16, 2048);
90   out = g_new (GstFFTS16Complex, 1025);
91   ctx = gst_fft_s16_new (2048, FALSE);
92 
93   for (i = 0; i < 2048; i += 4) {
94     in[i] = 0;
95     in[i + 1] = G_MAXINT16;
96     in[i + 2] = 0;
97     in[i + 3] = G_MININT16;
98   }
99 
100   gst_fft_s16_window (ctx, in, GST_FFT_WINDOW_HAMMING);
101   gst_fft_s16_fft (ctx, in, out);
102 
103   for (i = 0; i < 1025; i++) {
104     gdouble mag;
105 
106     mag = (gdouble) out[i].r * (gdouble) out[i].r;
107     mag += (gdouble) out[i].i * (gdouble) out[i].i;
108     mag /= 32767.0 * 32767.0;
109     mag = 10.0 * log10 (mag);
110 
111     if (abs (512 - i) < 2)
112       fail_unless (mag > -20.0);
113     else
114       fail_unless (mag < -55.0);
115   }
116 
117   gst_fft_s16_free (ctx);
118   g_free (in);
119   g_free (out);
120 }
121 
122 GST_END_TEST;
123 
GST_START_TEST(test_s16_22050hz)124 GST_START_TEST (test_s16_22050hz)
125 {
126   gint i;
127   gint16 *in;
128   GstFFTS16Complex *out;
129   GstFFTS16 *ctx;
130 
131   in = g_new (gint16, 2048);
132   out = g_new (GstFFTS16Complex, 1025);
133   ctx = gst_fft_s16_new (2048, FALSE);
134 
135   for (i = 0; i < 2048; i += 2) {
136     in[i] = G_MAXINT16;
137     in[i + 1] = G_MININT16;
138   }
139 
140   gst_fft_s16_window (ctx, in, GST_FFT_WINDOW_HAMMING);
141   gst_fft_s16_fft (ctx, in, out);
142 
143   for (i = 0; i < 1025; i++) {
144     gdouble mag;
145 
146     mag = (gdouble) out[i].r * (gdouble) out[i].r;
147     mag += (gdouble) out[i].i * (gdouble) out[i].i;
148     mag /= 32767.0 * 32767.0;
149     mag = 10.0 * log10 (mag);
150 
151     if (i > 1022)
152       fail_unless (mag > -15.0);
153     else
154       fail_unless (mag < -55.0);
155   }
156 
157   gst_fft_s16_free (ctx);
158   g_free (in);
159   g_free (out);
160 }
161 
162 GST_END_TEST;
163 
GST_START_TEST(test_s32_0hz)164 GST_START_TEST (test_s32_0hz)
165 {
166   gint i;
167   gint32 *in;
168   GstFFTS32Complex *out;
169   GstFFTS32 *ctx;
170 
171   in = g_new (gint32, 2048);
172   out = g_new (GstFFTS32Complex, 1025);
173   ctx = gst_fft_s32_new (2048, FALSE);
174 
175   for (i = 0; i < 2048; i++)
176     in[i] = 2147483647;
177 
178   gst_fft_s32_window (ctx, in, GST_FFT_WINDOW_HAMMING);
179   gst_fft_s32_fft (ctx, in, out);
180 
181   for (i = 0; i < 1025; i++) {
182     gdouble mag;
183 
184     mag = (gdouble) out[i].r * (gdouble) out[i].r;
185     mag += (gdouble) out[i].i * (gdouble) out[i].i;
186     mag /= 2147483647.0 * 2147483647.0;
187     mag = 10.0 * log10 (mag);
188 
189     if (i < 2)
190       fail_unless (mag > -15.0);
191     else
192       fail_unless (mag < -60.0);
193   }
194 
195   gst_fft_s32_free (ctx);
196   g_free (in);
197   g_free (out);
198 }
199 
200 GST_END_TEST;
201 
GST_START_TEST(test_s32_11025hz)202 GST_START_TEST (test_s32_11025hz)
203 {
204   gint i;
205   gint32 *in;
206   GstFFTS32Complex *out;
207   GstFFTS32 *ctx;
208 
209   in = g_new (gint32, 2048);
210   out = g_new (GstFFTS32Complex, 1025);
211   ctx = gst_fft_s32_new (2048, FALSE);
212 
213   for (i = 0; i < 2048; i += 4) {
214     in[i] = 0;
215     in[i + 1] = G_MAXINT32;
216     in[i + 2] = 0;
217     in[i + 3] = G_MININT32;
218   }
219 
220   gst_fft_s32_window (ctx, in, GST_FFT_WINDOW_HAMMING);
221   gst_fft_s32_fft (ctx, in, out);
222 
223   for (i = 0; i < 1025; i++) {
224     gdouble mag;
225 
226     mag = (gdouble) out[i].r * (gdouble) out[i].r;
227     mag += (gdouble) out[i].i * (gdouble) out[i].i;
228     mag /= 2147483647.0 * 2147483647.0;
229     mag = 10.0 * log10 (mag);
230 
231     if (abs (512 - i) < 2)
232       fail_unless (mag > -20.0);
233     else
234       fail_unless (mag < -60.0);
235   }
236 
237   gst_fft_s32_free (ctx);
238   g_free (in);
239   g_free (out);
240 }
241 
242 GST_END_TEST;
243 
GST_START_TEST(test_s32_22050hz)244 GST_START_TEST (test_s32_22050hz)
245 {
246   gint i;
247   gint32 *in;
248   GstFFTS32Complex *out;
249   GstFFTS32 *ctx;
250 
251   in = g_new (gint32, 2048);
252   out = g_new (GstFFTS32Complex, 1025);
253   ctx = gst_fft_s32_new (2048, FALSE);
254 
255   for (i = 0; i < 2048; i += 2) {
256     in[i] = G_MAXINT32;
257     in[i + 1] = G_MININT32;
258   }
259 
260   gst_fft_s32_window (ctx, in, GST_FFT_WINDOW_HAMMING);
261   gst_fft_s32_fft (ctx, in, out);
262 
263   for (i = 0; i < 1025; i++) {
264     gdouble mag;
265 
266     mag = (gdouble) out[i].r * (gdouble) out[i].r;
267     mag += (gdouble) out[i].i * (gdouble) out[i].i;
268     mag /= 2147483647.0 * 2147483647.0;
269     mag = 10.0 * log10 (mag);
270 
271     if (i > 1022)
272       fail_unless (mag > -15.0);
273     else
274       fail_unless (mag < -60.0);
275   }
276 
277   gst_fft_s32_free (ctx);
278   g_free (in);
279   g_free (out);
280 }
281 
282 GST_END_TEST;
283 
GST_START_TEST(test_f32_0hz)284 GST_START_TEST (test_f32_0hz)
285 {
286   gint i;
287   gfloat *in;
288   GstFFTF32Complex *out;
289   GstFFTF32 *ctx;
290 
291   in = g_new (gfloat, 2048);
292   out = g_new (GstFFTF32Complex, 1025);
293   ctx = gst_fft_f32_new (2048, FALSE);
294 
295   for (i = 0; i < 2048; i++)
296     in[i] = 1.0;
297 
298   gst_fft_f32_window (ctx, in, GST_FFT_WINDOW_HAMMING);
299   gst_fft_f32_fft (ctx, in, out);
300 
301   for (i = 0; i < 1025; i++) {
302     gdouble mag;
303 
304     mag = (gdouble) out[i].r * (gdouble) out[i].r;
305     mag += (gdouble) out[i].i * (gdouble) out[i].i;
306     mag /= 2048.0 * 2048.0;
307     mag = 10.0 * log10 (mag);
308 
309     if (i < 2)
310       fail_unless (mag > -15.0);
311     else
312       fail_unless (mag < -60.0);
313   }
314 
315   gst_fft_f32_free (ctx);
316   g_free (in);
317   g_free (out);
318 }
319 
320 GST_END_TEST;
321 
GST_START_TEST(test_f32_11025hz)322 GST_START_TEST (test_f32_11025hz)
323 {
324   gint i;
325   gfloat *in;
326   GstFFTF32Complex *out;
327   GstFFTF32 *ctx;
328 
329   in = g_new (gfloat, 2048);
330   out = g_new (GstFFTF32Complex, 1025);
331   ctx = gst_fft_f32_new (2048, FALSE);
332 
333   for (i = 0; i < 2048; i += 4) {
334     in[i] = 0.0;
335     in[i + 1] = 1.0;
336     in[i + 2] = 0.0;
337     in[i + 3] = -1.0;
338   }
339 
340   gst_fft_f32_window (ctx, in, GST_FFT_WINDOW_HAMMING);
341   gst_fft_f32_fft (ctx, in, out);
342 
343   for (i = 0; i < 1025; i++) {
344     gdouble mag;
345 
346     mag = (gdouble) out[i].r * (gdouble) out[i].r;
347     mag += (gdouble) out[i].i * (gdouble) out[i].i;
348     mag /= 2048.0 * 2048.0;
349     mag = 10.0 * log10 (mag);
350 
351     if (abs (512 - i) < 2)
352       fail_unless (mag > -20.0);
353     else
354       fail_unless (mag < -60.0);
355   }
356 
357   gst_fft_f32_free (ctx);
358   g_free (in);
359   g_free (out);
360 }
361 
362 GST_END_TEST;
363 
GST_START_TEST(test_f32_22050hz)364 GST_START_TEST (test_f32_22050hz)
365 {
366   gint i;
367   gfloat *in;
368   GstFFTF32Complex *out;
369   GstFFTF32 *ctx;
370 
371   in = g_new (gfloat, 2048);
372   out = g_new (GstFFTF32Complex, 1025);
373   ctx = gst_fft_f32_new (2048, FALSE);
374 
375   for (i = 0; i < 2048; i += 2) {
376     in[i] = 1.0;
377     in[i + 1] = -1.0;
378   }
379 
380   gst_fft_f32_window (ctx, in, GST_FFT_WINDOW_HAMMING);
381   gst_fft_f32_fft (ctx, in, out);
382 
383   for (i = 0; i < 1025; i++) {
384     gdouble mag;
385 
386     mag = (gdouble) out[i].r * (gdouble) out[i].r;
387     mag += (gdouble) out[i].i * (gdouble) out[i].i;
388     mag /= 2048.0 * 2048.0;
389     mag = 10.0 * log10 (mag);
390 
391     if (i > 1022)
392       fail_unless (mag > -15.0);
393     else
394       fail_unless (mag < -60.0);
395   }
396 
397   gst_fft_f32_free (ctx);
398   g_free (in);
399   g_free (out);
400 }
401 
402 GST_END_TEST;
403 
GST_START_TEST(test_f64_0hz)404 GST_START_TEST (test_f64_0hz)
405 {
406   gint i;
407   gdouble *in;
408   GstFFTF64Complex *out;
409   GstFFTF64 *ctx;
410 
411   in = g_new (gdouble, 2048);
412   out = g_new (GstFFTF64Complex, 1025);
413   ctx = gst_fft_f64_new (2048, FALSE);
414 
415   for (i = 0; i < 2048; i++)
416     in[i] = 1.0;
417 
418   gst_fft_f64_window (ctx, in, GST_FFT_WINDOW_HAMMING);
419   gst_fft_f64_fft (ctx, in, out);
420 
421   for (i = 0; i < 1025; i++) {
422     gdouble mag;
423 
424     mag = (gdouble) out[i].r * (gdouble) out[i].r;
425     mag += (gdouble) out[i].i * (gdouble) out[i].i;
426     mag /= 2048.0 * 2048.0;
427     mag = 10.0 * log10 (mag);
428 
429     if (i < 2)
430       fail_unless (mag > -15.0);
431     else
432       fail_unless (mag < -60.0);
433   }
434 
435   gst_fft_f64_free (ctx);
436   g_free (in);
437   g_free (out);
438 }
439 
440 GST_END_TEST;
441 
GST_START_TEST(test_f64_11025hz)442 GST_START_TEST (test_f64_11025hz)
443 {
444   gint i;
445   gdouble *in;
446   GstFFTF64Complex *out;
447   GstFFTF64 *ctx;
448 
449   in = g_new (gdouble, 2048);
450   out = g_new (GstFFTF64Complex, 1025);
451   ctx = gst_fft_f64_new (2048, FALSE);
452 
453   for (i = 0; i < 2048; i += 4) {
454     in[i] = 0.0;
455     in[i + 1] = 1.0;
456     in[i + 2] = 0.0;
457     in[i + 3] = -1.0;
458   }
459 
460   gst_fft_f64_window (ctx, in, GST_FFT_WINDOW_HAMMING);
461   gst_fft_f64_fft (ctx, in, out);
462 
463   for (i = 0; i < 1025; i++) {
464     gdouble mag;
465 
466     mag = (gdouble) out[i].r * (gdouble) out[i].r;
467     mag += (gdouble) out[i].i * (gdouble) out[i].i;
468     mag /= 2048.0 * 2048.0;
469     mag = 10.0 * log10 (mag);
470 
471     if (abs (512 - i) < 2)
472       fail_unless (mag > -20.0);
473     else
474       fail_unless (mag < -60.0);
475   }
476 
477   gst_fft_f64_free (ctx);
478   g_free (in);
479   g_free (out);
480 }
481 
482 GST_END_TEST;
483 
GST_START_TEST(test_f64_22050hz)484 GST_START_TEST (test_f64_22050hz)
485 {
486   gint i;
487   gdouble *in;
488   GstFFTF64Complex *out;
489   GstFFTF64 *ctx;
490 
491   in = g_new (gdouble, 2048);
492   out = g_new (GstFFTF64Complex, 1025);
493   ctx = gst_fft_f64_new (2048, FALSE);
494 
495   for (i = 0; i < 2048; i += 2) {
496     in[i] = 1.0;
497     in[i + 1] = -1.0;
498   }
499 
500   gst_fft_f64_window (ctx, in, GST_FFT_WINDOW_HAMMING);
501   gst_fft_f64_fft (ctx, in, out);
502 
503   for (i = 0; i < 1025; i++) {
504     gdouble mag;
505 
506     mag = (gdouble) out[i].r * (gdouble) out[i].r;
507     mag += (gdouble) out[i].i * (gdouble) out[i].i;
508     mag /= 2048.0 * 2048.0;
509     mag = 10.0 * log10 (mag);
510 
511     if (i > 1022)
512       fail_unless (mag > -15.0);
513     else
514       fail_unless (mag < -60.0);
515   }
516 
517   gst_fft_f64_free (ctx);
518   g_free (in);
519   g_free (out);
520 }
521 
522 GST_END_TEST;
523 
524 static Suite *
fft_suite(void)525 fft_suite (void)
526 {
527   Suite *s = suite_create ("fft library");
528   TCase *tc_chain = tcase_create ("general");
529 
530   suite_add_tcase (s, tc_chain);
531   tcase_add_test (tc_chain, test_next_fast_length);
532   tcase_add_test (tc_chain, test_s16_0hz);
533   tcase_add_test (tc_chain, test_s16_11025hz);
534   tcase_add_test (tc_chain, test_s16_22050hz);
535   tcase_add_test (tc_chain, test_s32_0hz);
536   tcase_add_test (tc_chain, test_s32_11025hz);
537   tcase_add_test (tc_chain, test_s32_22050hz);
538   tcase_add_test (tc_chain, test_f32_0hz);
539   tcase_add_test (tc_chain, test_f32_11025hz);
540   tcase_add_test (tc_chain, test_f32_22050hz);
541   tcase_add_test (tc_chain, test_f64_0hz);
542   tcase_add_test (tc_chain, test_f64_11025hz);
543   tcase_add_test (tc_chain, test_f64_22050hz);
544 
545   return s;
546 }
547 
548 GST_CHECK_MAIN (fft);
549