summaryrefslogtreecommitdiff
path: root/libavfilter/af_firequalizer.c
diff options
context:
space:
mode:
authorMuhammad Faiz <mfcc64@gmail.com>2016-10-18 22:55:39 +0700
committerMuhammad Faiz <mfcc64@gmail.com>2016-10-19 14:05:46 +0700
commit23b6f880d6d7418ca75783767e7f7c02af7cf456 (patch)
treeaa7f99e3acc1a2b9c4c84e440bd3b3385c4876cb /libavfilter/af_firequalizer.c
parent0ad71ed6f98e43fe99e642e95eb14436820521c7 (diff)
avfilter/firequalizer: add cubic_interpolate function on gain
smoother version of gain_interpolate Signed-off-by: Muhammad Faiz <mfcc64@gmail.com>
Diffstat (limited to 'libavfilter/af_firequalizer.c')
-rw-r--r--libavfilter/af_firequalizer.c49
1 files changed, 47 insertions, 2 deletions
diff --git a/libavfilter/af_firequalizer.c b/libavfilter/af_firequalizer.c
index 6868066b14..e799e34191 100644
--- a/libavfilter/af_firequalizer.c
+++ b/libavfilter/af_firequalizer.c
@@ -354,6 +354,51 @@ static double gain_interpolate_func(void *p, double freq)
return res[0].gain;
}
+static double cubic_interpolate_func(void *p, double freq)
+{
+ AVFilterContext *ctx = p;
+ FIREqualizerContext *s = ctx->priv;
+ GainEntry *res;
+ double x, x2, x3;
+ double a, b, c, d;
+ double m0, m1, m2, msum, unit;
+
+ if (!s->nb_gain_entry)
+ return 0;
+
+ if (freq <= s->gain_entry_tbl[0].freq)
+ return s->gain_entry_tbl[0].gain;
+
+ if (freq >= s->gain_entry_tbl[s->nb_gain_entry-1].freq)
+ return s->gain_entry_tbl[s->nb_gain_entry-1].gain;
+
+ res = bsearch(&freq, &s->gain_entry_tbl, s->nb_gain_entry - 1, sizeof(*res), gain_entry_compare);
+ av_assert0(res);
+
+ unit = res[1].freq - res[0].freq;
+ m0 = res != s->gain_entry_tbl ?
+ unit * (res[0].gain - res[-1].gain) / (res[0].freq - res[-1].freq) : 0;
+ m1 = res[1].gain - res[0].gain;
+ m2 = res != s->gain_entry_tbl + s->nb_gain_entry - 2 ?
+ unit * (res[2].gain - res[1].gain) / (res[2].freq - res[1].freq) : 0;
+
+ msum = fabs(m0) + fabs(m1);
+ m0 = msum > 0 ? (fabs(m0) * m1 + fabs(m1) * m0) / msum : 0;
+ msum = fabs(m1) + fabs(m2);
+ m1 = msum > 0 ? (fabs(m1) * m2 + fabs(m2) * m1) / msum : 0;
+
+ d = res[0].gain;
+ c = m0;
+ b = 3 * res[1].gain - m1 - 2 * c - 3 * d;
+ a = res[1].gain - b - c - d;
+
+ x = (freq - res[0].freq) / unit;
+ x2 = x * x;
+ x3 = x2 * x;
+
+ return a * x3 + b * x2 + c * x + d;
+}
+
static const char *const var_names[] = {
"f",
"sr",
@@ -379,9 +424,9 @@ static int generate_kernel(AVFilterContext *ctx, const char *gain, const char *g
FIREqualizerContext *s = ctx->priv;
AVFilterLink *inlink = ctx->inputs[0];
const char *gain_entry_func_names[] = { "entry", NULL };
- const char *gain_func_names[] = { "gain_interpolate", NULL };
+ const char *gain_func_names[] = { "gain_interpolate", "cubic_interpolate", NULL };
double (*gain_entry_funcs[])(void *, double, double) = { entry_func, NULL };
- double (*gain_funcs[])(void *, double) = { gain_interpolate_func, NULL };
+ double (*gain_funcs[])(void *, double) = { gain_interpolate_func, cubic_interpolate_func, NULL };
double vars[VAR_NB];
AVExpr *gain_expr;
int ret, k, center, ch;