History

avfilter/af_afir: add irnorm and irlink options

Deprecate gtype option.

Paul B Mahol committed 2 years ago

Commit 5452cbd1 parent 07c303b4 files · +91 −119Browse files

Unified · Split

4 files
  1. doc/filters.texi +14 −23
  2. libavfilter/af_afir.c +47 −10
  3. libavfilter/af_afir.h +3 −0
  4. libavfilter/afir_template.c +27 −86
doc/filters.texi+14−23
@@ -1794,33 +1794,24 @@ Set wet gain. This sets final output gain. · 1793 unmodified lines
17941794 Set Impulse Response filter length. Default is 1, which means whole IR is processed.
17951795
17961796 @item gtype
1797−Enable applying gain measured from power of IR.
1797+This option is deprecated, and does nothing.
17981798
1799−Set which approach to use for auto gain measurement.
1799+@item irnorm
1800+Set norm to be applied to IR coefficients before filtering.
1801+Allowed range is from @var{-1} to @var{2}.
1802+IR coefficients are normalized with calculated vector norm set by this option.
1803+For negative values, no norm is calculated, and IR coefficients are not modified at all.
1804+Default is @var{1}.
18001805
1801−@table @option
1802−@item none
1803−Do not apply any gain.
1804−
1805−@item peak
1806−select peak gain, very conservative approach. This is default value.
1807−
1808−@item dc
1809−select DC gain, limited application.
1810−
1811−@item gn
1812−select gain to noise approach, this is most popular one.
1813−
1814−@item ac
1815−select AC gain.
1816−
1817−@item rms
1818−select RMS gain.
1819−@end table
1806+@item irlink
1807+For multichannel IR if this option is set to @var{true}. All IR channels will be
1808+normalized with maximal measured gain of all IR channels coefficients as set by @code{irnorm} option.
1809+When disabled, all IR coefficients in each IR channel will be normalized independently.
1810+Default is @var{true}.
18201811
18211812 @item irgain
18221813 Set gain to be applied to IR coefficients before filtering.
1823−Allowed range is 0 to 1. This gain is applied after any gain applied with @var{gtype} option.
1814+Allowed range is 0 to 1. This gain is applied after any gain applied with @var{irnorm} option.
18241815
18251816 @item irfmt
18261817 Set format of IR stream. Can be @code{mono} or @code{input}.
@@ -1899,7 +1890,7 @@ ffmpeg -i input.wav -i middle_tunnel_1way_mono.wav -lavfi afir output.wav · 72 unmodified lines
18991890 Apply true stereo processing given input stereo stream, and two stereo impulse responses for left and right channel,
19001891 the impulse response files are files with names l_ir.wav and r_ir.wav:
19011892 @example
1902−"pan=4C|c0=FL|c1=FL|c2=FR|c3=FR[a];amovie=l_ir.wav[LIR];amovie=r_ir.wav[RIR];[LIR][RIR]amerge[ir];[a][ir]afir=irfmt=input:gtype=gn:irgain=-5dB,pan=stereo|FL<c0+c2|FR<c1+c3"
1893+"pan=4C|c0=FL|c1=FL|c2=FR|c3=FR[a];amovie=l_ir.wav[LIR];amovie=r_ir.wav[RIR];[LIR][RIR]amerge[ir];[a][ir]afir=irfmt=input:irgain=-5dB,pan=stereo|FL<c0+c2|FR<c1+c3"
19031894 @end example
19041895 @end itemize
19051896
libavfilter/af_afir.c+47−10
@@ -393,6 +393,22 @@ skip: · 392 unmodified lines
393393
394394 switch (s->format) {
395395 case AV_SAMPLE_FMT_FLTP:
396+ for (int ch = 0; ch < s->nb_channels; ch++) {
397+ const float *tsrc = (const float *)s->ir[selir]->extended_data[!s->one2many * ch];
398+
399+ s->ch_gain[ch] = ir_gain_float(ctx, s, nb_taps, tsrc);
400+ }
401+
402+ if (s->ir_link) {
403+ float gain = +INFINITY;
404+
405+ for (int ch = 0; ch < s->nb_channels; ch++)
406+ gain = fminf(gain, s->ch_gain[ch]);
407+
408+ for (int ch = 0; ch < s->nb_channels; ch++)
409+ s->ch_gain[ch] = gain;
410+ }
411+
396412 for (int ch = 0; ch < s->nb_channels; ch++) {
397413 const float *tsrc = (const float *)s->ir[selir]->extended_data[!s->one2many * ch];
398414 float *time = (float *)s->norm_ir[selir]->extended_data[ch];
@@ -401,7 +417,7 @@ skip: · 2 unmodified lines
401417 for (int i = FFMAX(1, s->length * nb_taps); i < nb_taps; i++)
402418 time[i] = 0;
403419
404− get_power_float(ctx, s, nb_taps, ch, time);
420+ ir_scale_float(ctx, s, nb_taps, ch, time, s->ch_gain[ch]);
405421
406422 for (int n = 0; n < s->nb_segments[selir]; n++) {
407423 AudioFIRSegment *seg = &s->seg[selir][n];
@@ -417,6 +433,22 @@ skip: · 9 unmodified lines
417433 }
418434 break;
419435 case AV_SAMPLE_FMT_DBLP:
436+ for (int ch = 0; ch < s->nb_channels; ch++) {
437+ const double *tsrc = (const double *)s->ir[selir]->extended_data[!s->one2many * ch];
438+
439+ s->ch_gain[ch] = ir_gain_double(ctx, s, nb_taps, tsrc);
440+ }
441+
442+ if (s->ir_link) {
443+ double gain = +INFINITY;
444+
445+ for (int ch = 0; ch < s->nb_channels; ch++)
446+ gain = fmin(gain, s->ch_gain[ch]);
447+
448+ for (int ch = 0; ch < s->nb_channels; ch++)
449+ s->ch_gain[ch] = gain;
450+ }
451+
420452 for (int ch = 0; ch < s->nb_channels; ch++) {
421453 const double *tsrc = (const double *)s->ir[selir]->extended_data[!s->one2many * ch];
422454 double *time = (double *)s->norm_ir[selir]->extended_data[ch];
@@ -425,7 +457,8 @@ skip: · 2 unmodified lines
425457 for (int i = FFMAX(1, s->length * nb_taps); i < nb_taps; i++)
426458 time[i] = 0;
427459
428− get_power_double(ctx, s, nb_taps, ch, time);
460+ ir_scale_double(ctx, s, nb_taps, ch, time, s->ch_gain[ch]);
461+
429462 for (int n = 0; n < s->nb_segments[selir]; n++) {
430463 AudioFIRSegment *seg = &s->seg[selir][n];
431464
@@ -627,8 +660,9 @@ FF_ENABLE_DEPRECATION_WARNINGS · 195 unmodified lines
627660
628661 s->format = outlink->format;
629662 s->nb_channels = outlink->ch_layout.nb_channels;
663+ s->ch_gain = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*s->ch_gain));
630664 s->loading = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*s->loading));
631− if (!s->loading)
665+ if (!s->loading || !s->ch_gain)
632666 return AVERROR(ENOMEM);
633667
634668 s->fadein[0] = ff_get_audio_buffer(outlink, s->min_part_size);
@@ -674,6 +708,7 @@ static av_cold void uninit(AVFilterContext *ctx) · 39 unmodified lines
674708 AudioFIRContext *s = ctx->priv;
675709
676710 av_freep(&s->fdsp);
711+ av_freep(&s->ch_gain);
677712 av_freep(&s->loading);
678713
679714 for (int i = 0; i < s->nb_irs; i++) {
@@ -812,13 +847,15 @@ static const AVOption afir_options[] = { · 132 unmodified lines
812847 { "dry", "set dry gain", OFFSET(dry_gain), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, AFR },
813848 { "wet", "set wet gain", OFFSET(wet_gain), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, AFR },
814849 { "length", "set IR length", OFFSET(length), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, AF },
815− { "gtype", "set IR auto gain type",OFFSET(gtype), AV_OPT_TYPE_INT, {.i64=0}, -1, 4, AF, "gtype" },
816− { "none", "without auto gain", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "gtype" },
817− { "peak", "peak gain", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "gtype" },
818− { "dc", "DC gain", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "gtype" },
819− { "gn", "gain to noise", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "gtype" },
820− { "ac", "AC gain", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "gtype" },
821− { "rms", "RMS gain", 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, AF, "gtype" },
850+ { "gtype", "set IR auto gain type",OFFSET(gtype), AV_OPT_TYPE_INT, {.i64=0}, -1, 4, AF|AV_OPT_FLAG_DEPRECATED, "gtype" },
851+ { "none", "without auto gain", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF|AV_OPT_FLAG_DEPRECATED, "gtype" },
852+ { "peak", "peak gain", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF|AV_OPT_FLAG_DEPRECATED, "gtype" },
853+ { "dc", "DC gain", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF|AV_OPT_FLAG_DEPRECATED, "gtype" },
854+ { "gn", "gain to noise", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF|AV_OPT_FLAG_DEPRECATED, "gtype" },
855+ { "ac", "AC gain", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF|AV_OPT_FLAG_DEPRECATED, "gtype" },
856+ { "rms", "RMS gain", 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, AF|AV_OPT_FLAG_DEPRECATED, "gtype" },
857+ { "irnorm", "set IR norm", OFFSET(ir_norm), AV_OPT_TYPE_FLOAT, {.dbl=1}, -1, 2, AF },
858+ { "irlink", "set IR link", OFFSET(ir_link), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, AF },
822859 { "irgain", "set IR gain", OFFSET(ir_gain), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, AF },
823860 { "irfmt", "set IR format", OFFSET(ir_format), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, AF, "irfmt" },
824861 { "mono", "single channel", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "irfmt" },
libavfilter/af_afir.h+3−0
@@ -63,6 +63,8 @@ typedef struct AudioFIRContext { · 62 unmodified lines
6363 float dry_gain;
6464 float length;
6565 int gtype;
66+ float ir_norm;
67+ float ir_link;
6668 float ir_gain;
6769 int ir_format;
6870 int ir_load;
@@ -87,6 +89,7 @@ typedef struct AudioFIRContext { · 18 unmodified lines
8789 int nb_channels;
8890 int one2many;
8991 int *loading;
92+ double *ch_gain;
9093
9194 AudioFIRSegment seg[MAX_IR_STREAMS][1024];
9295
libavfilter/afir_template.c+27−86
@@ -29,6 +29,8 @@ · 28 unmodified lines
2929 #undef HYPOT
3030 #undef SAMPLE_FORMAT
3131 #undef TX_TYPE
32+#undef FABS
33+#undef POW
3234 #if DEPTH == 32
3335 #define SAMPLE_FORMAT float
3436 #define SQRT sqrtf
@@ -36,6 +38,8 @@ · 1 unmodified line
3638 #define ctype AVComplexFloat
3739 #define ftype float
3840 #define TX_TYPE AV_TX_FLOAT_RDFT
41+#define FABS fabsf
42+#define POW powf
3943 #else
4044 #define SAMPLE_FORMAT double
4145 #define SQRT sqrt
@@ -43,6 +47,8 @@ · 1 unmodified line
4347 #define ctype AVComplexDouble
4448 #define ftype double
4549 #define TX_TYPE AV_TX_DOUBLE_RDFT
50+#define FABS fabs
51+#define POW pow
4652 #endif
4753
4854 #define fn3(a,b) a##_##b
@@ -139,95 +145,32 @@ end: · 90 unmodified lines
139145 av_free(mag);
140146 }
141147
142−static int fn(get_power)(AVFilterContext *ctx, AudioFIRContext *s,
143− int cur_nb_taps, int ch,
144− ftype *time)
148+static ftype fn(ir_gain)(AVFilterContext *ctx, AudioFIRContext *s,
149+ int cur_nb_taps, const ftype *time)
145150 {
146− ftype ch_gain = 1;
151+ ftype ch_gain, sum = 0;
147152
148− switch (s->gtype) {
149− case -1:
153+ if (s->ir_norm < 0.f) {
150154 ch_gain = 1;
151− break;
152− case 0:
153− {
154− ftype sum = 0;
155−
156− for (int i = 0; i < cur_nb_taps; i++)
157− sum += FFABS(time[i]);
158− ch_gain = 1. / sum;
159− }
160− break;
161− case 1:
162− {
163− ftype sum = 0;
164−
165− for (int i = 0; i < cur_nb_taps; i++)
166− sum += time[i];
167− ch_gain = 1. / sum;
168− }
169− break;
170− case 2:
171− {
172− ftype sum = 0;
173−
174− for (int i = 0; i < cur_nb_taps; i++)
175− sum += time[i] * time[i];
176− ch_gain = 1. / SQRT(sum);
177− }
178− break;
179− case 3:
180− case 4:
181− {
182− ftype *inc, *outc, scale, power;
183− AVTXContext *tx;
184− av_tx_fn tx_fn;
185− int ret, size;
186−
187− size = 1 << av_ceil_log2_c(cur_nb_taps);
188− inc = av_calloc(size + 2, sizeof(SAMPLE_FORMAT));
189− outc = av_calloc(size + 2, sizeof(SAMPLE_FORMAT));
190− if (!inc || !outc) {
191− av_free(outc);
192− av_free(inc);
193− break;
194− }
195−
196− scale = 1.;
197− ret = av_tx_init(&tx, &tx_fn, TX_TYPE, 0, size, &scale, 0);
198− if (ret < 0) {
199− av_free(outc);
200− av_free(inc);
201− break;
202− }
203−
204− {
205− memcpy(inc, time, cur_nb_taps * sizeof(SAMPLE_FORMAT));
206− tx_fn(tx, outc, inc, sizeof(SAMPLE_FORMAT));
207−
208− power = 0;
209− if (s->gtype == 3) {
210− for (int i = 0; i < size / 2 + 1; i++)
211− power = FFMAX(power, HYPOT(outc[i * 2], outc[i * 2 + 1]));
212− } else {
213− ftype sum = 0;
214− for (int i = 0; i < size / 2 + 1; i++)
215− sum += HYPOT(outc[i * 2], outc[i * 2 + 1]);
216− power = SQRT(sum / (size / 2 + 1));
217− }
218−
219− ch_gain = 1. / power;
220− }
221−
222− av_tx_uninit(&tx);
223− av_free(outc);
224− av_free(inc);
225− }
226− break;
227− default:
228− return AVERROR_BUG;
155+ } else if (s->ir_norm == 0.f) {
156+ for (int i = 0; i < cur_nb_taps; i++)
157+ sum += time[i];
158+ ch_gain = 1. / sum;
159+ } else {
160+ ftype ir_norm = s->ir_norm;
161+
162+ for (int i = 0; i < cur_nb_taps; i++)
163+ sum += POW(FABS(time[i]), ir_norm);
164+ ch_gain = 1. / POW(sum, 1. / ir_norm);
229165 }
230166
167+ return ch_gain;
168+}
169+
170+static void fn(ir_scale)(AVFilterContext *ctx, AudioFIRContext *s,
171+ int cur_nb_taps, int ch,
172+ ftype *time, ftype ch_gain)
173+{
231174 if (ch_gain != 1. || s->ir_gain != 1.) {
232175 ftype gain = ch_gain * s->ir_gain;
233176
@@ -238,8 +181,6 @@ static int fn(get_power)(AVFilterContext *ctx, AudioFIRContext *s, · 4 unmodified lines
238181 s->fdsp->vector_dmul_scalar(time, time, gain, FFALIGN(cur_nb_taps, 8));
239182 #endif
240183 }
241−
242− return 0;
243184 }
244185
245186 static void fn(convert_channel)(AVFilterContext *ctx, AudioFIRContext *s, int ch,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t