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.
|
Apply an arbitrary Frequency Impulse Response filter.
|
||||||
|
|
||||||
This filter is designed for applying long FIR filters,
|
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,
|
It can be used as component for digital crossover filters,
|
||||||
room equalization, cross talk cancellation, wavefield synthesis,
|
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.
|
Set Impulse Response filter length. Default is 1, which means whole IR is processed.
|
||||||
|
|
||||||
@item again
|
@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
|
@item maxir
|
||||||
Set max allowed Impulse Response filter duration in seconds. Default is 30 seconds.
|
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;
|
AudioFIRContext *s = ctx->priv;
|
||||||
int i, ch, n, N;
|
int i, ch, n, N;
|
||||||
|
float power = 0;
|
||||||
|
|
||||||
s->nb_taps = av_audio_fifo_size(s->fifo);
|
s->nb_taps = av_audio_fifo_size(s->fifo);
|
||||||
if (s->nb_taps <= 0)
|
if (s->nb_taps <= 0)
|
||||||
@ -333,22 +334,48 @@ static int convert_coeffs(AVFilterContext *ctx)
|
|||||||
if (s->response)
|
if (s->response)
|
||||||
draw_response(ctx, s->video);
|
draw_response(ctx, s->video);
|
||||||
|
|
||||||
|
s->gain = 1;
|
||||||
|
|
||||||
if (s->again) {
|
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++) {
|
for (i = 0; i < s->nb_taps; i++)
|
||||||
float *time = (float *)s->in[1]->extended_data[!s->one2many * ch];
|
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++)
|
for (i = 0; i < s->nb_taps; i++)
|
||||||
power += FFABS(time[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));
|
s->gain = FFMIN(s->gain * s->ir_gain, 1.f);
|
||||||
for (ch = 0; ch < ctx->inputs[1]->channels; ch++) {
|
av_log(ctx, AV_LOG_DEBUG, "power %f, gain %f\n", power, s->gain);
|
||||||
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];
|
||||||
|
|
||||||
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++) {
|
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 },
|
{ "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 },
|
{ "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 },
|
{ "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 },
|
{ "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 },
|
{ "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 },
|
{ "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 dry_gain;
|
||||||
float length;
|
float length;
|
||||||
int again;
|
int again;
|
||||||
|
int gtype;
|
||||||
|
float ir_gain;
|
||||||
float max_ir_len;
|
float max_ir_len;
|
||||||
int response;
|
int response;
|
||||||
int w, h;
|
int w, h;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user