-
-
Notifications
You must be signed in to change notification settings - Fork 77
/
Copy pathfilters.c
81 lines (65 loc) · 2.8 KB
/
filters.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include "utils.h"
#include <libplacebo/filters.h>
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);
}