[pulseaudio-discuss] [PATCH 8/9] tests: adding lfe-filter-test

David Henningsson david.henningsson at canonical.com
Wed Mar 25 02:46:26 PDT 2015


From: Hui Wang <hui.wang at canonical.com>

so far, this test only includes rewind test, it works as below:
let lfe-filter process 2 blocks mono lfe channel audio samples, the
sample format is PA_SAMPLE_S16LE, save the processed data to the temp
buffer, then rewind the lfe-filter back 1 block and 1.5 blocks
respectively, reprocess the audio samples from the rewind position,
then comparing the output data with previously saved data.

Signed-off-by: Hui Wang <hui.wang at canonical.com>
---
 src/Makefile.am             |   8 +-
 src/tests/lfe-filter-test.c | 194 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 201 insertions(+), 1 deletion(-)
 create mode 100644 src/tests/lfe-filter-test.c

diff --git a/src/Makefile.am b/src/Makefile.am
index 302c532..d582e57 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -262,7 +262,8 @@ TESTS_default = \
 		cpu-sconv-test \
 		cpu-volume-test \
 		lock-autospawn-test \
-		mult-s16-test
+		mult-s16-test \
+		lfe-filter-test
 
 TESTS_norun = \
 		ipacl-test \
@@ -554,6 +555,11 @@ mult_s16_test_LDADD = $(AM_LDADD) libpulsecore- at PA_MAJORMINOR@.la libpulse.la li
 mult_s16_test_CFLAGS = $(AM_CFLAGS) $(LIBCHECK_CFLAGS)
 mult_s16_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBCHECK_LIBS)
 
+lfe_filter_test_SOURCES = tests/lfe-filter-test.c
+lfe_filter_test_LDADD = $(AM_LDADD) libpulsecore- at PA_MAJORMINOR@.la libpulse.la libpulsecommon- at PA_MAJORMINOR@.la
+lfe_filter_test_CFLAGS = $(AM_CFLAGS) $(LIBCHECK_CFLAGS)
+lfe_filter_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBCHECK_LIBS)
+
 rtstutter_SOURCES = tests/rtstutter.c
 rtstutter_LDADD = $(AM_LDADD) libpulsecore- at PA_MAJORMINOR@.la libpulse.la libpulsecommon- at PA_MAJORMINOR@.la
 rtstutter_CFLAGS = $(AM_CFLAGS)
diff --git a/src/tests/lfe-filter-test.c b/src/tests/lfe-filter-test.c
new file mode 100644
index 0000000..2c6d597
--- /dev/null
+++ b/src/tests/lfe-filter-test.c
@@ -0,0 +1,194 @@
+/***
+  This file is part of PulseAudio.
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published
+  by the Free Software Foundation; either version 2.1 of the License,
+  or (at your option) any later version.
+
+  PulseAudio 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
+  General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <check.h>
+
+#include <pulse/pulseaudio.h>
+#include <pulse/sample.h>
+#include <pulsecore/memblock.h>
+
+#include <pulsecore/filter/lfe-filter.h>
+
+struct lfe_filter_test {
+    pa_lfe_filter_t *lf;
+    pa_mempool *pool;
+    pa_sample_spec *ss;
+};
+
+static uint8_t *ori_sample_ptr;
+
+#define ONE_BLOCK_SAMPLES 4096
+#define TOTAL_SAMPLES 8192
+
+static void save_data_block(struct lfe_filter_test *lft, void *d, pa_memblock *blk) {
+    uint8_t *dst = d, *src;
+    size_t blk_size = pa_frame_size(lft->ss) * ONE_BLOCK_SAMPLES;
+
+    src = pa_memblock_acquire(blk);
+    memcpy(dst, src, blk_size);
+    pa_memblock_release(blk);
+}
+
+static pa_memblock* generate_data_block(struct lfe_filter_test *lft, int start) {
+    pa_memblock *r;
+    uint8_t *d, *s = ori_sample_ptr;
+    size_t blk_size = pa_frame_size(lft->ss) * ONE_BLOCK_SAMPLES;
+
+    pa_assert_se(r = pa_memblock_new(lft->pool, blk_size));
+    d = pa_memblock_acquire(r);
+    memcpy(d, s + start,  blk_size);
+    pa_memblock_release(r);
+
+    return r;
+}
+
+static int compare_data_block(struct lfe_filter_test *lft, void *a, void *b) {
+    int ret = 0;
+    uint32_t i;
+    uint32_t fz = pa_frame_size(lft->ss);
+    uint8_t *r = a, *u = b;
+
+    for (i = 0; i < ONE_BLOCK_SAMPLES * fz; i++) {
+        if (*r++ != *u++) {
+            pa_log_error("lfe-filter-test: test failed, the output data in the position 0x%x of a block does not equal!\n", i);
+            ret = -1;
+            break;
+        }
+    }
+    return ret;
+}
+
+/* in this test case, we pass two blocks of sample data to lfe-filter, each
+   block contains 4096 samples, and don't let rewind_samples exceed TOTAL_SAMPLES */
+static int lfe_filter_rewind_test(struct lfe_filter_test *lft, int rewind_samples)
+{
+    int ret = -1, pos, i;
+    pa_memchunk mc;
+    uint8_t *outptr;
+    uint32_t fz = pa_frame_size(lft->ss);
+
+    if (rewind_samples > TOTAL_SAMPLES || rewind_samples < TOTAL_SAMPLES - ONE_BLOCK_SAMPLES) {
+        pa_log_error("lfe-filter-test: Please keep %d samples < rewind_samples < %d samples\n", TOTAL_SAMPLES - ONE_BLOCK_SAMPLES, TOTAL_SAMPLES);
+        return ret;
+    }
+
+    outptr = pa_xmalloc(fz * TOTAL_SAMPLES);
+
+    /* let lfe-filter process all samples first, and save the processed data to the temp buffer,
+       then rewind back to some position, reprocess some samples and compare the output data with
+       the processed data saved before. */
+    for (i = 0; i < TOTAL_SAMPLES / ONE_BLOCK_SAMPLES; i++) {
+        mc.memblock = generate_data_block(lft, i * ONE_BLOCK_SAMPLES * fz);
+        mc.length = pa_memblock_get_length(mc.memblock);
+        mc.index = 0;
+        pa_lfe_filter_process(lft->lf, &mc);
+        save_data_block(lft, outptr + i * ONE_BLOCK_SAMPLES * fz, mc.memblock);
+        pa_memblock_unref(mc.memblock);
+    }
+
+    pa_lfe_filter_rewind(lft->lf, rewind_samples * fz);
+    pos = (TOTAL_SAMPLES - rewind_samples) * fz;
+    mc.memblock = generate_data_block(lft, pos);
+    mc.length = pa_memblock_get_length(mc.memblock);
+    mc.index = 0;
+    pa_lfe_filter_process(lft->lf, &mc);
+    ret = compare_data_block(lft, outptr + pos, pa_memblock_acquire(mc.memblock));
+    pa_memblock_release(mc.memblock);
+    pa_memblock_unref(mc.memblock);
+
+    pa_xfree(outptr);
+
+    return ret;
+}
+
+START_TEST (lfe_filter_test) {
+    pa_sample_spec a;
+    int ret = -1;
+    unsigned i, crossover_freq = 120;
+    pa_channel_map chmapmono = {1, {PA_CHANNEL_POSITION_LFE}};
+    struct lfe_filter_test lft;
+    short *tmp_ptr;
+
+    pa_log_set_level(PA_LOG_DEBUG);
+
+    a.channels = 1;
+    a.rate = 44100;
+    a.format = PA_SAMPLE_S16LE;
+
+    lft.ss = &a;
+    pa_assert_se(lft.pool = pa_mempool_new(false, 0));
+
+    /* We prepare pseudo-random input audio samples for lfe-filter rewind testing*/
+    ori_sample_ptr = pa_xmalloc(pa_frame_size(lft.ss) * TOTAL_SAMPLES);
+    tmp_ptr = (short *) ori_sample_ptr;
+    for (i = 0; i < pa_frame_size(lft.ss) * TOTAL_SAMPLES / sizeof(short); i++)
+        *tmp_ptr++ = random();
+
+    /* we create a lfe-filter with cutoff frequency 120Hz and max rewind time 10 seconds */
+    pa_assert_se(lft.lf = pa_lfe_filter_new(&a, &chmapmono, crossover_freq, a.rate * 10));
+    /* rewind to a block boundary */
+    ret = lfe_filter_rewind_test(&lft, ONE_BLOCK_SAMPLES);
+    if (ret)
+        pa_log_error("lfe-filer-test: rewind to block boundary test failed!!!");
+    pa_lfe_filter_free(lft.lf);
+
+    /* we create a lfe-filter with cutoff frequency 120Hz and max rewind time 10 seconds */
+    pa_assert_se(lft.lf = pa_lfe_filter_new(&a, &chmapmono, crossover_freq, a.rate * 10));
+    /* rewind to the middle position of a block */
+    ret = lfe_filter_rewind_test(&lft, ONE_BLOCK_SAMPLES + ONE_BLOCK_SAMPLES / 2);
+    if (ret)
+        pa_log_error("lfe-filer-test: rewind to middle of block test failed!!!");
+
+    pa_xfree(ori_sample_ptr);
+
+    pa_lfe_filter_free(lft.lf);
+
+    pa_mempool_free(lft.pool);
+
+    if (!ret)
+        pa_log_debug("lfe-filter-test: tests for both rewind to block boundary and rewind to middle position of a block passed!");
+
+    fail_unless(ret == 0);
+}
+END_TEST
+
+int main(int argc, char *argv[]) {
+    int failed = 0;
+    Suite *s;
+    TCase *tc;
+    SRunner *sr;
+
+    if (!getenv("MAKE_CHECK"))
+        pa_log_set_level(PA_LOG_DEBUG);
+
+    s = suite_create("lfe-filter");
+    tc = tcase_create("lfe-filter");
+    tcase_add_test(tc, lfe_filter_test);
+    tcase_set_timeout(tc, 10);
+    suite_add_tcase(s, tc);
+
+    sr = srunner_create(s);
+    srunner_run_all(sr, CK_NORMAL);
+    failed = srunner_ntests_failed(sr);
+    srunner_free(sr);
+
+    return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
-- 
1.9.1



More information about the pulseaudio-discuss mailing list