From ff6e3c025658a5fa1affd094f220b623e7e1b24b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 22:38:23 +0200 Subject: Adding upstream version 6.338.2. Signed-off-by: Daniel Baumann --- src/tests/filters.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/tests/filters.c (limited to 'src/tests/filters.c') diff --git a/src/tests/filters.c b/src/tests/filters.c new file mode 100644 index 0000000..b6b323c --- /dev/null +++ b/src/tests/filters.c @@ -0,0 +1,81 @@ +#include "tests.h" + +#include + +int main() +{ + pl_log log = pl_test_logger(); + + for (int i = 0; i < pl_num_filter_functions; i++) { + const struct pl_filter_function *fun = pl_filter_functions[i]; + if (fun->opaque) + continue; + + printf("Testing filter function '%s'\n", fun->name); + + struct pl_filter_ctx ctx = { .radius = fun->radius }; + memcpy(ctx.params, fun->params, sizeof(ctx.params)); + + // Ensure the kernel is correctly scaled + REQUIRE_FEQ(fun->weight(&ctx, 0.0), 1.0, 1e-7); + + // Only box filters are radius 1, these are unwindowed by design. + // Gaussian technically never reaches 0 even at its preconfigured radius. + if (fun->radius > 1.0 && fun != &pl_filter_function_gaussian) + REQUIRE_FEQ(fun->weight(&ctx, fun->radius), 0.0, 1e-7); + } + + for (int c = 0; c < pl_num_filter_configs; c++) { + const struct pl_filter_config *conf = pl_filter_configs[c]; + if (conf->kernel->opaque) + continue; + + printf("Testing filter config '%s'\n", conf->name); + pl_filter flt = pl_filter_generate(log, pl_filter_params( + .config = *conf, + .lut_entries = 256, + .cutoff = 1e-3, + )); + REQUIRE(flt); + const float radius = PL_DEF(conf->radius, conf->kernel->radius); + REQUIRE_CMP(flt->radius, <=, radius, "f"); + REQUIRE_CMP(flt->radius_zero, >, 0.0, "f"); + REQUIRE_CMP(flt->radius_zero, <=, flt->radius, "f"); + + if (conf->polar) { + + // Test LUT accuracy + const int range = flt->params.lut_entries - 1; + double scale = flt->weights[0] / pl_filter_sample(conf, 0.0); + double err = 0.0; + for (float k = 0.0; k <= 1.0; k += 1e-3f) { + double ref = scale * pl_filter_sample(conf, k * flt->radius); + double idx = k * range; + int base = floorf(idx); + double fpart = idx - base; + int next = PL_MIN(base + 1, range); + double interp = PL_MIX(flt->weights[base], flt->weights[next], fpart); + err = fmaxf(err, fabs(interp - ref)); + } + REQUIRE_CMP(err, <=, 1e-4, "g"); + + } else { + + // Ensure the weights for each row add up to unity + for (int i = 0; i < flt->params.lut_entries; i++) { + const float *row = flt->weights + i * flt->row_stride; + float sum = 0.0; + REQUIRE(flt->row_size); + REQUIRE_CMP(flt->row_stride, >=, flt->row_size, "d"); + for (int n = 0; n < flt->row_size; n++) + sum += row[n]; + REQUIRE_FEQ(sum, 1.0, 1e-6); + } + + } + + pl_filter_free(&flt); + } + + pl_log_destroy(&log); +} -- cgit v1.2.3