gstreamer/tests/check/libs/fft.c
Sebastian Dröge edb4a505d7 Remove the magnitude and phase calculation functions as these have very special use cases and can't even be used for ...
Original commit message from CVS:
* docs/libs/gst-plugins-base-libs-sections.txt:
* gst-libs/gst/fft/gstfftf32.c:
* gst-libs/gst/fft/gstfftf32.h:
* gst-libs/gst/fft/gstfftf64.c:
* gst-libs/gst/fft/gstfftf64.h:
* gst-libs/gst/fft/gstffts16.c:
* gst-libs/gst/fft/gstffts16.h:
* gst-libs/gst/fft/gstffts32.c:
* gst-libs/gst/fft/gstffts32.h:
* tests/check/libs/fft.c: (GST_START_TEST):
Remove the magnitude and phase calculation functions as these have
very special use cases and can't even be used for the spectrum
element. Also adjust the docs to mention some properties of the used
FFT implemention, i.e. how the values are scaled. Fixes #492098.
2007-11-06 11:58:59 +00:00

569 lines
12 KiB
C

/* GStreamer
*
* unit test for FFT library
*
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
*
* 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 <gst/check/gstcheck.h>
#include <gst/fft/gstfft.h>
#include <gst/fft/gstffts16.h>
#include <gst/fft/gstffts32.h>
#include <gst/fft/gstfftf32.h>
#include <gst/fft/gstfftf64.h>
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 *= 2048.0;
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 *= 2048.0;
mag /= 32767.0 * 32767.0;
mag = 10.0 * log10 (mag);
if (abs (512 - 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_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 *= 2048.0;
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 *= 2048.0;
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 *= 2048.0;
mag /= 2147483647.0 * 2147483647.0;
mag = 10.0 * log10 (mag);
if (abs (512 - 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_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 *= 2048.0;
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;
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;
mag = 10.0 * log10 (mag);
if (abs (512 - 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_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;
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;
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;
mag = 10.0 * log10 (mag);
if (abs (512 - 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_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;
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;
}