2
This file is part of PulseAudio.
4
PulseAudio is free software; you can redistribute it and/or modify
5
it under the terms of the GNU Lesser General Public License as published
6
by the Free Software Foundation; either version 2.1 of the License,
7
or (at your option) any later version.
9
PulseAudio is distributed in the hope that it will be useful, but
10
WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
General Public License for more details.
14
You should have received a copy of the GNU Lesser General Public License
15
along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
24
#include <pulse/pulseaudio.h>
25
#include <pulse/sample.h>
26
#include <pulsecore/memblock.h>
28
#include <pulsecore/filter/lfe-filter.h>
30
struct lfe_filter_test {
36
static uint8_t *ori_sample_ptr;
38
#define ONE_BLOCK_SAMPLES 4096
39
#define TOTAL_SAMPLES 8192
40
#define TOLERANT_VARIATION 1
42
static void save_data_block(struct lfe_filter_test *lft, void *d, pa_memblock *blk) {
43
uint8_t *dst = d, *src;
44
size_t blk_size = pa_frame_size(lft->ss) * ONE_BLOCK_SAMPLES;
46
src = pa_memblock_acquire(blk);
47
memcpy(dst, src, blk_size);
48
pa_memblock_release(blk);
51
static pa_memblock* generate_data_block(struct lfe_filter_test *lft, int start) {
53
uint8_t *d, *s = ori_sample_ptr;
54
size_t blk_size = pa_frame_size(lft->ss) * ONE_BLOCK_SAMPLES;
56
pa_assert_se(r = pa_memblock_new(lft->pool, blk_size));
57
d = pa_memblock_acquire(r);
58
memcpy(d, s + start, blk_size);
59
pa_memblock_release(r);
64
static int compare_data_block(struct lfe_filter_test *lft, void *a, void *b) {
67
uint16_t *r = a, *u = b;
69
pa_assert(lft->ss->format == PA_SAMPLE_S16NE);
71
for (i = 0; i < ONE_BLOCK_SAMPLES; i++) {
72
if (abs(*r++ - *u++) > TOLERANT_VARIATION) {
73
pa_log_error("lfe-filter-test: test failed, the output data in the position 0x%x of a block does not equal!\n", i);
81
/* in this test case, we pass two blocks of sample data to lfe-filter, each
82
block contains 4096 samples, and don't let rewind_samples exceed TOTAL_SAMPLES */
83
static int lfe_filter_rewind_test(struct lfe_filter_test *lft, int rewind_samples)
88
uint32_t fz = pa_frame_size(lft->ss);
90
if (rewind_samples > TOTAL_SAMPLES || rewind_samples < TOTAL_SAMPLES - ONE_BLOCK_SAMPLES) {
91
pa_log_error("lfe-filter-test: Please keep %d samples < rewind_samples < %d samples\n", TOTAL_SAMPLES - ONE_BLOCK_SAMPLES, TOTAL_SAMPLES);
95
outptr = pa_xmalloc(fz * TOTAL_SAMPLES);
97
/* let lfe-filter process all samples first, and save the processed data to the temp buffer,
98
then rewind back to some position, reprocess some samples and compare the output data with
99
the processed data saved before. */
100
for (i = 0; i < TOTAL_SAMPLES / ONE_BLOCK_SAMPLES; i++) {
101
mc.memblock = generate_data_block(lft, i * ONE_BLOCK_SAMPLES * fz);
102
mc.length = pa_memblock_get_length(mc.memblock);
104
pa_lfe_filter_process(lft->lf, &mc);
105
save_data_block(lft, outptr + i * ONE_BLOCK_SAMPLES * fz, mc.memblock);
106
pa_memblock_unref(mc.memblock);
109
pa_lfe_filter_rewind(lft->lf, rewind_samples * fz);
110
pos = (TOTAL_SAMPLES - rewind_samples) * fz;
111
mc.memblock = generate_data_block(lft, pos);
112
mc.length = pa_memblock_get_length(mc.memblock);
114
pa_lfe_filter_process(lft->lf, &mc);
115
ret = compare_data_block(lft, outptr + pos, pa_memblock_acquire(mc.memblock));
116
pa_memblock_release(mc.memblock);
117
pa_memblock_unref(mc.memblock);
124
START_TEST (lfe_filter_test) {
127
unsigned i, crossover_freq = 120;
128
pa_channel_map chmapmono = {1, {PA_CHANNEL_POSITION_LFE}};
129
struct lfe_filter_test lft;
132
pa_log_set_level(PA_LOG_DEBUG);
136
a.format = PA_SAMPLE_S16LE;
139
pa_assert_se(lft.pool = pa_mempool_new(false, 0));
141
/* We prepare pseudo-random input audio samples for lfe-filter rewind testing*/
142
ori_sample_ptr = pa_xmalloc(pa_frame_size(lft.ss) * TOTAL_SAMPLES);
143
tmp_ptr = (short *) ori_sample_ptr;
144
for (i = 0; i < pa_frame_size(lft.ss) * TOTAL_SAMPLES / sizeof(short); i++)
145
*tmp_ptr++ = random();
147
/* we create a lfe-filter with cutoff frequency 120Hz and max rewind time 10 seconds */
148
pa_assert_se(lft.lf = pa_lfe_filter_new(&a, &chmapmono, crossover_freq, a.rate * 10));
149
/* rewind to a block boundary */
150
ret = lfe_filter_rewind_test(&lft, ONE_BLOCK_SAMPLES);
152
pa_log_error("lfe-filer-test: rewind to block boundary test failed!!!");
153
pa_lfe_filter_free(lft.lf);
155
/* we create a lfe-filter with cutoff frequency 120Hz and max rewind time 10 seconds */
156
pa_assert_se(lft.lf = pa_lfe_filter_new(&a, &chmapmono, crossover_freq, a.rate * 10));
157
/* rewind to the middle position of a block */
158
ret = lfe_filter_rewind_test(&lft, ONE_BLOCK_SAMPLES + ONE_BLOCK_SAMPLES / 2);
160
pa_log_error("lfe-filer-test: rewind to middle of block test failed!!!");
162
pa_xfree(ori_sample_ptr);
164
pa_lfe_filter_free(lft.lf);
166
pa_mempool_free(lft.pool);
169
pa_log_debug("lfe-filter-test: tests for both rewind to block boundary and rewind to middle position of a block passed!");
171
fail_unless(ret == 0);
175
int main(int argc, char *argv[]) {
181
if (!getenv("MAKE_CHECK"))
182
pa_log_set_level(PA_LOG_DEBUG);
184
s = suite_create("lfe-filter");
185
tc = tcase_create("lfe-filter");
186
tcase_add_test(tc, lfe_filter_test);
187
tcase_set_timeout(tc, 10);
188
suite_add_tcase(s, tc);
190
sr = srunner_create(s);
191
srunner_run_all(sr, CK_NORMAL);
192
failed = srunner_ntests_failed(sr);
195
return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;