From 525f83becd7c1cc8de4c1def6584510026c12f23 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 25 May 2022 11:13:32 +0200 Subject: avfilter: add tiltshelf audio filter --- Changelog | 1 + doc/filters.texi | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ libavfilter/af_biquads.c | 39 +++++++++++++++++---- libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- 5 files changed, 127 insertions(+), 7 deletions(-) diff --git a/Changelog b/Changelog index 53130f072f..c5eab22c83 100644 --- a/Changelog +++ b/Changelog @@ -17,6 +17,7 @@ version 5.1: - multiply video filter - PGS subtitle frame merge bitstream filter - blurdetect filter +- tiltshelf audio filter version 5.0: diff --git a/doc/filters.texi b/doc/filters.texi index 0e10946cca..d65e83d4d0 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6690,6 +6690,97 @@ Set window overlap. If set to 1, the recommended overlap for selected window function will be picked. Default is @code{0.5}. @end table +@section tiltshelf + +Boost or cut the lower frequencies and cut or boost higher frequencies +of the audio using a two-pole shelving filter with a response similar to +that of a standard hi-fi's tone-controls. +This is also known as shelving equalisation (EQ). + +The filter accepts the following options: + +@table @option +@item gain, g +Give the gain at 0 Hz. Its useful range is about -20 +(for a large cut) to +20 (for a large boost). +Beware of clipping when using a positive gain. + +@item frequency, f +Set the filter's central frequency and so can be used +to extend or reduce the frequency range to be boosted or cut. +The default value is @code{3000} Hz. + +@item width_type, t +Set method to specify band-width of filter. +@table @option +@item h +Hz +@item q +Q-Factor +@item o +octave +@item s +slope +@item k +kHz +@end table + +@item width, w +Determine how steep is the filter's shelf transition. + +@item poles, p +Set number of poles. Default is 2. + +@item mix, m +How much to use filtered signal in output. Default is 1. +Range is between 0 and 1. + +@item channels, c +Specify which channels to filter, by default all available are filtered. + +@item normalize, n +Normalize biquad coefficients, by default is disabled. +Enabling it will normalize magnitude response at DC to 0dB. + +@item transform, a +Set transform type of IIR filter. +@table @option +@item di +@item dii +@item tdi +@item tdii +@item latt +@item svf +@item zdf +@end table + +@item precision, r +Set precison of filtering. +@table @option +@item auto +Pick automatic sample format depending on surround filters. +@item s16 +Always use signed 16-bit. +@item s32 +Always use signed 32-bit. +@item f32 +Always use float 32-bit. +@item f64 +Always use float 64-bit. +@end table + +@item block_size, b +Set block size used for reverse IIR processing. If this value is set to high enough +value (higher than impulse response length truncated when reaches near zero values) filtering +will become linear phase otherwise if not big enough it will just produce nasty artifacts. + +Note that filter delay will be exactly this many samples when set to non-zero value. +@end table + +@subsection Commands + +This filter supports some options as @ref{commands}. + @section treble, highshelf Boost or cut treble (upper) frequencies of the audio using a two-pole diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index 26cb4d49bb..9110faabac 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -85,6 +85,7 @@ enum FilterType { lowpass, lowshelf, highshelf, + tiltshelf, }; enum WidthType { @@ -698,6 +699,17 @@ static void convert_dir2zdf(BiquadsContext *s, int sample_rate) m[1] = k * (A - 1.); m[2] = A * A - 1.; break; + case tiltshelf: + A = ff_exp10(s->gain / 20.); + g = tan(M_PI * s->frequency / sample_rate) / sqrt(A); + k = 1. / Q; + a[0] = 1. / (1. + g * (g + k)); + a[1] = g * a[0]; + a[2] = g * a[1]; + m[0] = 1./ A; + m[1] = k * (A - 1.) / A; + m[2] = (A * A - 1.) / A; + break; case treble: case highshelf: A = ff_exp10(s->gain / 40.); @@ -777,7 +789,8 @@ static int config_filter(AVFilterLink *outlink, int reset) AVFilterContext *ctx = outlink->src; BiquadsContext *s = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; - double A = ff_exp10(s->gain / 40); + double gain = s->gain * ((s->filter_type == tiltshelf) + 1.); + double A = ff_exp10(gain / 40); double w0 = 2 * M_PI * s->frequency / inlink->sample_rate; double K = tan(w0 / 2.); double alpha, beta; @@ -835,9 +848,10 @@ static int config_filter(AVFilterLink *outlink, int reset) break; case bass: beta = sqrt((A * A + 1) - (A - 1) * (A - 1)); + case tiltshelf: case lowshelf: if (s->poles == 1) { - double A = ff_exp10(s->gain / 20); + double A = ff_exp10(gain / 20); double ro = -sin(w0 / 2. - M_PI_4) / sin(w0 / 2. + M_PI_4); double n = (A + 1) / (A - 1); double alpha1 = A == 1. ? 0. : n - FFSIGN(n) * sqrt(n * n - 1); @@ -863,7 +877,7 @@ static int config_filter(AVFilterLink *outlink, int reset) beta = sqrt((A * A + 1) - (A - 1) * (A - 1)); case highshelf: if (s->poles == 1) { - double A = ff_exp10(s->gain / 20); + double A = ff_exp10(gain / 20); double ro = sin(w0 / 2. - M_PI_4) / sin(w0 / 2. + M_PI_4); double n = (A + 1) / (A - 1); double alpha1 = A == 1. ? 0. : n - FFSIGN(n) * sqrt(n * n - 1); @@ -985,6 +999,14 @@ static int config_filter(AVFilterLink *outlink, int reset) s->b2 *= factor; } + switch (s->filter_type) { + case tiltshelf: + s->b0 /= A; + s->b1 /= A; + s->b2 /= A; + break; + } + s->cache = av_realloc_f(s->cache, sizeof(ChanCache), inlink->ch_layout.nb_channels); if (!s->cache) return AVERROR(ENOMEM); @@ -1528,7 +1550,7 @@ DEFINE_BIQUAD_FILTER_2(bass, "Boost or cut lower frequencies.", bass_lowshelf); DEFINE_BIQUAD_FILTER_2(lowshelf, "Apply a low shelf filter.", bass_lowshelf); #endif /* CONFIG_LOWSHELF_FILTER */ #endif /* CONFIG_BASS_FILTER || CONFIG LOWSHELF_FILTER */ -#if CONFIG_TREBLE_FILTER || CONFIG_HIGHSHELF_FILTER +#if CONFIG_TREBLE_FILTER || CONFIG_HIGHSHELF_FILTER || CONFIG_TILTSHELF_FILTER static const AVOption treble_highshelf_options[] = { {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, @@ -1572,7 +1594,7 @@ static const AVOption treble_highshelf_options[] = { {NULL} }; -AVFILTER_DEFINE_CLASS_EXT(treble_highshelf, "treble/highshelf", +AVFILTER_DEFINE_CLASS_EXT(treble_highshelf, "treble/high/tiltshelf", treble_highshelf_options); #if CONFIG_TREBLE_FILTER @@ -1582,7 +1604,12 @@ DEFINE_BIQUAD_FILTER_2(treble, "Boost or cut upper frequencies.", treble_highshe #if CONFIG_HIGHSHELF_FILTER DEFINE_BIQUAD_FILTER_2(highshelf, "Apply a high shelf filter.", treble_highshelf); #endif /* CONFIG_HIGHSHELF_FILTER */ -#endif /* CONFIG_TREBLE_FILTER || CONFIG_HIGHSHELF_FILTER */ + +#if CONFIG_TILTSHELF_FILTER +DEFINE_BIQUAD_FILTER_2(tiltshelf, "Apply a tilt shelf filter.", treble_highshelf); +#endif +#endif /* CONFIG_TREBLE_FILTER || CONFIG_HIGHSHELF_FILTER || CONFIG_TILTSHELF_FILTER */ + #if CONFIG_BANDPASS_FILTER static const AVOption bandpass_options[] = { {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 2409964e53..2f72477523 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -149,6 +149,7 @@ extern const AVFilter ff_af_stereotools; extern const AVFilter ff_af_stereowiden; extern const AVFilter ff_af_superequalizer; extern const AVFilter ff_af_surround; +extern const AVFilter ff_af_tiltshelf; extern const AVFilter ff_af_treble; extern const AVFilter ff_af_tremolo; extern const AVFilter ff_af_vibrato; diff --git a/libavfilter/version.h b/libavfilter/version.h index df23710223..86b33c4174 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFILTER_VERSION_MINOR 39 +#define LIBAVFILTER_VERSION_MINOR 40 #define LIBAVFILTER_VERSION_MICRO 100 -- cgit v1.2.3