[FFmpeg-cvslog] avfilter/af_afir: make IR gain control more flexible
Paul B Mahol
git at videolan.org
Wed Oct 3 22:49:05 EEST 2018
ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Wed Oct 3 21:43:40 2018 +0200| [9e45364a80f93f174ffa25a8e66abfbe7e05b740] | committer: Paul B Mahol
avfilter/af_afir: make IR gain control more flexible
For this reason introduce two more options.
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=9e45364a80f93f174ffa25a8e66abfbe7e05b740
---
doc/filters.texi | 23 +++++++++++++++++++++--
libavfilter/af_afir.c | 52 +++++++++++++++++++++++++++++++++++++++++----------
libavfilter/af_afir.h | 2 ++
3 files changed, 65 insertions(+), 12 deletions(-)
diff --git a/doc/filters.texi b/doc/filters.texi
index 6d3833317e..1c51e42388 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -1147,7 +1147,7 @@ afftfilt="1-clip((b/nb)*b,0,1)"
Apply an arbitrary Frequency Impulse Response filter.
This filter is designed for applying long FIR filters,
-up to 30 seconds long.
+up to 60 seconds long.
It can be used as component for digital crossover filters,
room equalization, cross talk cancellation, wavefield synthesis,
@@ -1172,7 +1172,26 @@ Set wet gain. This sets final output gain.
Set Impulse Response filter length. Default is 1, which means whole IR is processed.
@item again
-Enable applying gain measured from power of IR.
+Enable applying gain measured from power of IR. For approach to use for measuring power
+of IR see next option.
+
+ at item gtype
+Set which approach to use for auto gain measurement.
+
+ at table @option
+ at item peak
+select peak gain, very conservative approach. This is default value.
+
+ at item dc
+select DC gain, limited application.
+
+ at item gn
+select gain to noise approach, this is most popular one.
+ at end table
+
+ at item irgain
+Set gain to be applied to IR coefficients before filtering.
+Allowed range is 0 to 1. This can be set even with @var{again} used.
@item maxir
Set max allowed Impulse Response filter duration in seconds. Default is 30 seconds.
diff --git a/libavfilter/af_afir.c b/libavfilter/af_afir.c
index bdca9033cf..770b8be9f7 100644
--- a/libavfilter/af_afir.c
+++ b/libavfilter/af_afir.c
@@ -280,6 +280,7 @@ static int convert_coeffs(AVFilterContext *ctx)
{
AudioFIRContext *s = ctx->priv;
int i, ch, n, N;
+ float power = 0;
s->nb_taps = av_audio_fifo_size(s->fifo);
if (s->nb_taps <= 0)
@@ -333,22 +334,48 @@ static int convert_coeffs(AVFilterContext *ctx)
if (s->response)
draw_response(ctx, s->video);
+ s->gain = 1;
+
if (s->again) {
- float power = 0;
+ switch (s->gtype) {
+ case 0:
+ for (ch = 0; ch < ctx->inputs[1]->channels; ch++) {
+ float *time = (float *)s->in[1]->extended_data[!s->one2many * ch];
+
+ for (i = 0; i < s->nb_taps; i++)
+ power += FFABS(time[i]);
+ }
+ s->gain = ctx->inputs[1]->channels / power;
+ break;
+ case 1:
+ for (ch = 0; ch < ctx->inputs[1]->channels; ch++) {
+ float *time = (float *)s->in[1]->extended_data[!s->one2many * ch];
- for (ch = 0; ch < ctx->inputs[1]->channels; ch++) {
- float *time = (float *)s->in[1]->extended_data[!s->one2many * ch];
+ for (i = 0; i < s->nb_taps; i++)
+ power += time[i];
+ }
+ s->gain = ctx->inputs[1]->channels / power;
+ break;
+ case 2:
+ for (ch = 0; ch < ctx->inputs[1]->channels; ch++) {
+ float *time = (float *)s->in[1]->extended_data[!s->one2many * ch];
- for (i = 0; i < s->nb_taps; i++)
- power += FFABS(time[i]);
+ for (i = 0; i < s->nb_taps; i++)
+ power += time[i] * time[i];
+ }
+ s->gain = sqrtf(ch / power);
+ break;
+ default:
+ return AVERROR_BUG;
}
+ }
- s->gain = sqrtf(1.f / (ctx->inputs[1]->channels * power)) / (sqrtf(ctx->inputs[1]->channels));
- for (ch = 0; ch < ctx->inputs[1]->channels; ch++) {
- float *time = (float *)s->in[1]->extended_data[!s->one2many * ch];
+ s->gain = FFMIN(s->gain * s->ir_gain, 1.f);
+ av_log(ctx, AV_LOG_DEBUG, "power %f, gain %f\n", power, s->gain);
+ for (ch = 0; ch < ctx->inputs[1]->channels; ch++) {
+ float *time = (float *)s->in[1]->extended_data[!s->one2many * ch];
- s->fdsp->vector_fmul_scalar(time, time, s->gain, FFALIGN(s->nb_taps, 4));
- }
+ s->fdsp->vector_fmul_scalar(time, time, s->gain, FFALIGN(s->nb_taps, 4));
}
for (ch = 0; ch < ctx->inputs[1]->channels; ch++) {
@@ -727,6 +754,11 @@ static const AVOption afir_options[] = {
{ "wet", "set wet gain", OFFSET(wet_gain), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, AF },
{ "length", "set IR length", OFFSET(length), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, AF },
{ "again", "enable auto gain", OFFSET(again), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, AF },
+ { "gtype", "set auto gain type",OFFSET(gtype), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, AF, "gtype" },
+ { "peak", "peak gain", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "gtype" },
+ { "dc", "DC gain", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "gtype" },
+ { "gn", "gain to noise", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "gtype" },
+ { "irgain", "set IR gain", OFFSET(ir_gain), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, AF },
{ "maxir", "set max IR length", OFFSET(max_ir_len), AV_OPT_TYPE_FLOAT, {.dbl=30}, 0.1, 60, AF },
{ "response", "show IR frequency response", OFFSET(response), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, VF },
{ "channel", "set IR channel to display frequency response", OFFSET(ir_channel), AV_OPT_TYPE_INT, {.i64=0}, 0, 1024, VF },
diff --git a/libavfilter/af_afir.h b/libavfilter/af_afir.h
index 9489ad0b00..9e6f957a8d 100644
--- a/libavfilter/af_afir.h
+++ b/libavfilter/af_afir.h
@@ -39,6 +39,8 @@ typedef struct AudioFIRContext {
float dry_gain;
float length;
int again;
+ int gtype;
+ float ir_gain;
float max_ir_len;
int response;
int w, h;
More information about the ffmpeg-cvslog
mailing list