diff -r 000000000000 -r 0e761a78d257 gst_plugins_base/tests/check/libs/fft.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gst_plugins_base/tests/check/libs/fft.c Thu Dec 17 08:53:32 2009 +0200 @@ -0,0 +1,563 @@ +/* GStreamer + * + * unit test for FFT library + * + * Copyright (C) 2007 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include +#include +#include + +GST_START_TEST (test_next_fast_length) +{ + fail_unless_equals_int (gst_fft_next_fast_length (13), 16); + fail_unless_equals_int (gst_fft_next_fast_length (30), 30); + fail_unless_equals_int (gst_fft_next_fast_length (31), 32); + fail_unless_equals_int (gst_fft_next_fast_length (1), 2); +} + +GST_END_TEST; + +GST_START_TEST (test_s16_0hz) +{ + gint i; + gint16 *in; + GstFFTS16Complex *out; + GstFFTS16 *ctx; + + in = g_new (gint16, 2048); + out = g_new (GstFFTS16Complex, 1025); + ctx = gst_fft_s16_new (2048, FALSE); + + for (i = 0; i < 2048; i++) + in[i] = G_MAXINT16; + + gst_fft_s16_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_s16_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 32767.0 * 32767.0; + mag = 10.0 * log10 (mag); + if (i < 2) + fail_unless (mag > -15.0); + else + fail_unless (mag < -55.0); + } + + gst_fft_s16_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_s16_11025hz) +{ + gint i; + gint16 *in; + GstFFTS16Complex *out; + GstFFTS16 *ctx; + + in = g_new (gint16, 2048); + out = g_new (GstFFTS16Complex, 1025); + ctx = gst_fft_s16_new (2048, FALSE); + + for (i = 0; i < 2048; i += 4) { + in[i] = 0; + in[i + 1] = G_MAXINT16; + in[i + 2] = 0; + in[i + 3] = G_MININT16; + } + + gst_fft_s16_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_s16_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 32767.0 * 32767.0; + mag = 10.0 * log10 (mag); + + if (abs (512 - i) < 2) + fail_unless (mag > -20.0); + else + fail_unless (mag < -55.0); + } + + gst_fft_s16_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_s16_22050hz) +{ + gint i; + gint16 *in; + GstFFTS16Complex *out; + GstFFTS16 *ctx; + + in = g_new (gint16, 2048); + out = g_new (GstFFTS16Complex, 1025); + ctx = gst_fft_s16_new (2048, FALSE); + + for (i = 0; i < 2048; i += 2) { + in[i] = G_MAXINT16; + in[i + 1] = G_MININT16; + } + + gst_fft_s16_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_s16_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 32767.0 * 32767.0; + mag = 10.0 * log10 (mag); + + if (i > 1022) + fail_unless (mag > -15.0); + else + fail_unless (mag < -55.0); + } + + gst_fft_s16_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_s32_0hz) +{ + gint i; + gint32 *in; + GstFFTS32Complex *out; + GstFFTS32 *ctx; + + in = g_new (gint32, 2048); + out = g_new (GstFFTS32Complex, 1025); + ctx = gst_fft_s32_new (2048, FALSE); + + for (i = 0; i < 2048; i++) + in[i] = 2147483647; + + gst_fft_s32_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_s32_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2147483647.0 * 2147483647.0; + mag = 10.0 * log10 (mag); + + if (i < 2) + fail_unless (mag > -15.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_s32_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_s32_11025hz) +{ + gint i; + gint32 *in; + GstFFTS32Complex *out; + GstFFTS32 *ctx; + + in = g_new (gint32, 2048); + out = g_new (GstFFTS32Complex, 1025); + ctx = gst_fft_s32_new (2048, FALSE); + + for (i = 0; i < 2048; i += 4) { + in[i] = 0; + in[i + 1] = G_MAXINT32; + in[i + 2] = 0; + in[i + 3] = G_MININT32; + } + + gst_fft_s32_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_s32_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2147483647.0 * 2147483647.0; + mag = 10.0 * log10 (mag); + + if (abs (512 - i) < 2) + fail_unless (mag > -20.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_s32_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_s32_22050hz) +{ + gint i; + gint32 *in; + GstFFTS32Complex *out; + GstFFTS32 *ctx; + + in = g_new (gint32, 2048); + out = g_new (GstFFTS32Complex, 1025); + ctx = gst_fft_s32_new (2048, FALSE); + + for (i = 0; i < 2048; i += 2) { + in[i] = G_MAXINT32; + in[i + 1] = G_MININT32; + } + + gst_fft_s32_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_s32_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2147483647.0 * 2147483647.0; + mag = 10.0 * log10 (mag); + + if (i > 1022) + fail_unless (mag > -15.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_s32_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_f32_0hz) +{ + gint i; + gfloat *in; + GstFFTF32Complex *out; + GstFFTF32 *ctx; + + in = g_new (gfloat, 2048); + out = g_new (GstFFTF32Complex, 1025); + ctx = gst_fft_f32_new (2048, FALSE); + + for (i = 0; i < 2048; i++) + in[i] = 1.0; + + gst_fft_f32_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_f32_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2048.0 * 2048.0; + mag = 10.0 * log10 (mag); + + if (i < 2) + fail_unless (mag > -15.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_f32_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_f32_11025hz) +{ + gint i; + gfloat *in; + GstFFTF32Complex *out; + GstFFTF32 *ctx; + + in = g_new (gfloat, 2048); + out = g_new (GstFFTF32Complex, 1025); + ctx = gst_fft_f32_new (2048, FALSE); + + for (i = 0; i < 2048; i += 4) { + in[i] = 0.0; + in[i + 1] = 1.0; + in[i + 2] = 0.0; + in[i + 3] = -1.0; + } + + gst_fft_f32_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_f32_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2048.0 * 2048.0; + mag = 10.0 * log10 (mag); + + if (abs (512 - i) < 2) + fail_unless (mag > -20.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_f32_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_f32_22050hz) +{ + gint i; + gfloat *in; + GstFFTF32Complex *out; + GstFFTF32 *ctx; + + in = g_new (gfloat, 2048); + out = g_new (GstFFTF32Complex, 1025); + ctx = gst_fft_f32_new (2048, FALSE); + + for (i = 0; i < 2048; i += 2) { + in[i] = 1.0; + in[i + 1] = -1.0; + } + + gst_fft_f32_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_f32_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2048.0 * 2048.0; + mag = 10.0 * log10 (mag); + + if (i > 1022) + fail_unless (mag > -15.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_f32_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_f64_0hz) +{ + gint i; + gdouble *in; + GstFFTF64Complex *out; + GstFFTF64 *ctx; + + in = g_new (gdouble, 2048); + out = g_new (GstFFTF64Complex, 1025); + ctx = gst_fft_f64_new (2048, FALSE); + + for (i = 0; i < 2048; i++) + in[i] = 1.0; + + gst_fft_f64_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_f64_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2048.0 * 2048.0; + mag = 10.0 * log10 (mag); + + if (i < 2) + fail_unless (mag > -15.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_f64_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_f64_11025hz) +{ + gint i; + gdouble *in; + GstFFTF64Complex *out; + GstFFTF64 *ctx; + + in = g_new (gdouble, 2048); + out = g_new (GstFFTF64Complex, 1025); + ctx = gst_fft_f64_new (2048, FALSE); + + for (i = 0; i < 2048; i += 4) { + in[i] = 0.0; + in[i + 1] = 1.0; + in[i + 2] = 0.0; + in[i + 3] = -1.0; + } + + gst_fft_f64_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_f64_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2048.0 * 2048.0; + mag = 10.0 * log10 (mag); + + if (abs (512 - i) < 2) + fail_unless (mag > -20.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_f64_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_f64_22050hz) +{ + gint i; + gdouble *in; + GstFFTF64Complex *out; + GstFFTF64 *ctx; + + in = g_new (gdouble, 2048); + out = g_new (GstFFTF64Complex, 1025); + ctx = gst_fft_f64_new (2048, FALSE); + + for (i = 0; i < 2048; i += 2) { + in[i] = 1.0; + in[i + 1] = -1.0; + } + + gst_fft_f64_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_f64_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2048.0 * 2048.0; + mag = 10.0 * log10 (mag); + + if (i > 1022) + fail_unless (mag > -15.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_f64_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +static Suite * +fft_suite (void) +{ + Suite *s = suite_create ("fft library"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_next_fast_length); + tcase_add_test (tc_chain, test_s16_0hz); + tcase_add_test (tc_chain, test_s16_11025hz); + tcase_add_test (tc_chain, test_s16_22050hz); + tcase_add_test (tc_chain, test_s32_0hz); + tcase_add_test (tc_chain, test_s32_11025hz); + tcase_add_test (tc_chain, test_s32_22050hz); + tcase_add_test (tc_chain, test_f32_0hz); + tcase_add_test (tc_chain, test_f32_11025hz); + tcase_add_test (tc_chain, test_f32_22050hz); + tcase_add_test (tc_chain, test_f64_0hz); + tcase_add_test (tc_chain, test_f64_11025hz); + tcase_add_test (tc_chain, test_f64_22050hz); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = fft_suite (); + SRunner *sr = srunner_create (s); + + gst_check_init (&argc, &argv); + + srunner_run_all (sr, CK_NORMAL); + nf = srunner_ntests_failed (sr); + srunner_free (sr); + + return nf; +}