mirror of https://git.ffmpeg.org/ffmpeg.git
avfilter/af_afir: make IR gain control more flexible
For this reason introduce two more options.
This commit is contained in:
parent
4c514edc5b
commit
9e45364a80
|
@ -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.
|
||||
|
||||
@item gtype
|
||||
Set which approach to use for auto gain measurement.
|
||||
|
||||
@table @option
|
||||
@item peak
|
||||
select peak gain, very conservative approach. This is default value.
|
||||
|
||||
@item dc
|
||||
select DC gain, limited application.
|
||||
|
||||
@item gn
|
||||
select gain to noise approach, this is most popular one.
|
||||
@end table
|
||||
|
||||
@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.
|
||||
|
|
|
@ -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 (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 (i = 0; i < s->nb_taps; i++)
|
||||
power += FFABS(time[i]);
|
||||
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 += 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 },
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue