History

avfilter/afir_template: make IR transitions artifacts free

Paul B Mahol committed 3 years ago

Commit 38795551 parent 62da0b43 files · +161 −69Browse files

Unified · Split

3 files
  1. libavfilter/af_afir.c +66 −18
  2. libavfilter/af_afir.h +4 −5
  3. libavfilter/afir_template.c +91 −46
libavfilter/af_afir.c+66−18
@@ -155,7 +155,7 @@ static int fir_frame(AudioFIRContext *s, AVFrame *in, AVFilterLink *outlink) · 154 unmodified lines
155155 return ff_filter_frame(outlink, out);
156156 }
157157
158−static int init_segment(AVFilterContext *ctx, AudioFIRSegment *seg,
158+static int init_segment(AVFilterContext *ctx, AudioFIRSegment *seg, int selir,
159159 int offset, int nb_partitions, int part_size, int index)
160160 {
161161 AudioFIRContext *s = ctx->priv;
@@ -221,12 +221,10 @@ static int init_segment(AVFilterContext *ctx, AudioFIRSegment *seg, · 59 unmodified lines
221221 seg->tempin = ff_get_audio_buffer(ctx->inputs[0], seg->block_size);
222222 seg->tempout = ff_get_audio_buffer(ctx->inputs[0], seg->block_size);
223223 seg->buffer = ff_get_audio_buffer(ctx->inputs[0], seg->part_size);
224− seg->coeff = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->coeff_size * 2);
225224 seg->input = ff_get_audio_buffer(ctx->inputs[0], seg->input_size);
226− seg->output = ff_get_audio_buffer(ctx->inputs[0], seg->part_size);
227− seg->loaded = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions);
225+ seg->output = ff_get_audio_buffer(ctx->inputs[0], seg->part_size * 5);
228226 if (!seg->buffer || !seg->sumin || !seg->sumout || !seg->blockout ||
229− !seg->coeff || !seg->input || !seg->output || !seg->loaded || !seg->tempin || !seg->tempout)
227+ !seg->input || !seg->output || !seg->tempin || !seg->tempout)
230228 return AVERROR(ENOMEM);
231229
232230 return 0;
@@ -264,18 +262,18 @@ static void uninit_segment(AVFilterContext *ctx, AudioFIRSegment *seg) · 31 unmodified lines
264262 av_frame_free(&seg->sumin);
265263 av_frame_free(&seg->sumout);
266264 av_frame_free(&seg->buffer);
267− av_frame_free(&seg->coeff);
268265 av_frame_free(&seg->input);
269266 av_frame_free(&seg->output);
270− av_frame_free(&seg->loaded);
271267 seg->input_size = 0;
268+
269+ for (int i = 0; i < MAX_IR_STREAMS; i++)
270+ av_frame_free(&seg->coeff[i]);
272271 }
273272
274273 static int convert_coeffs(AVFilterContext *ctx, int selir)
275274 {
276275 AudioFIRContext *s = ctx->priv;
277− const int prev_selir = s->prev_selir;
278− int ret, nb_taps, cur_nb_taps, prev_nb_taps;
276+ int ret, nb_taps, cur_nb_taps;
279277
280278 if (!s->nb_taps[selir]) {
281279 int part_size, max_part_size;
@@ -302,7 +300,7 @@ static int convert_coeffs(AVFilterContext *ctx, int selir) · 20 unmodified lines
302300 int nb_partitions = FFMIN(step, (left + part_size - 1) / part_size);
303301
304302 s->nb_segments = i + 1;
305− ret = init_segment(ctx, &s->seg[i], offset, nb_partitions, part_size, i);
303+ ret = init_segment(ctx, &s->seg[i], selir, offset, nb_partitions, part_size, i);
306304 if (ret < 0)
307305 return ret;
308306 offset += nb_partitions * part_size;
@@ -333,19 +331,68 @@ skip: · 24 unmodified lines
333331 }
334332
335333 cur_nb_taps = s->ir[selir]->nb_samples;
336− prev_nb_taps = s->ir[prev_selir]->nb_samples;
337− nb_taps = FFMAX(cur_nb_taps, prev_nb_taps);
334+ nb_taps = cur_nb_taps;
338335
339− if (!s->norm_ir || s->norm_ir->nb_samples < nb_taps) {
340− av_frame_free(&s->norm_ir);
341− s->norm_ir = ff_get_audio_buffer(ctx->inputs[0], FFALIGN(nb_taps, 8));
342− if (!s->norm_ir)
336+ if (!s->norm_ir[selir] || s->norm_ir[selir]->nb_samples < nb_taps) {
337+ av_frame_free(&s->norm_ir[selir]);
338+ s->norm_ir[selir] = ff_get_audio_buffer(ctx->inputs[0], FFALIGN(nb_taps, 8));
339+ if (!s->norm_ir[selir])
343340 return AVERROR(ENOMEM);
344341 }
345342
346343 av_log(ctx, AV_LOG_DEBUG, "nb_taps: %d\n", cur_nb_taps);
347344 av_log(ctx, AV_LOG_DEBUG, "nb_segments: %d\n", s->nb_segments);
348345
346+ switch (s->format) {
347+ case AV_SAMPLE_FMT_FLTP:
348+ for (int ch = 0; ch < s->nb_channels; ch++) {
349+ const float *tsrc = (const float *)s->ir[selir]->extended_data[!s->one2many * ch];
350+ float *time = (float *)s->norm_ir[selir]->extended_data[ch];
351+
352+ memcpy(time, tsrc, sizeof(*time) * nb_taps);
353+ for (int i = FFMAX(1, s->length * nb_taps); i < nb_taps; i++)
354+ time[i] = 0;
355+
356+ get_power_float(ctx, s, nb_taps, ch, time);
357+
358+ for (int n = 0; n < s->nb_segments; n++) {
359+ AudioFIRSegment *seg = &s->seg[n];
360+
361+ if (!seg->coeff[selir])
362+ seg->coeff[selir] = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->coeff_size * 2);
363+ if (!seg->coeff[selir])
364+ return AVERROR(ENOMEM);
365+
366+ for (int i = 0; i < seg->nb_partitions; i++)
367+ convert_channel_float(ctx, s, ch, seg, i, selir);
368+ }
369+ }
370+ break;
371+ case AV_SAMPLE_FMT_DBLP:
372+ for (int ch = 0; ch < s->nb_channels; ch++) {
373+ const double *tsrc = (const double *)s->ir[selir]->extended_data[!s->one2many * ch];
374+ double *time = (double *)s->norm_ir[selir]->extended_data[ch];
375+
376+ memcpy(time, tsrc, sizeof(*time) * nb_taps);
377+ for (int i = FFMAX(1, s->length * nb_taps); i < nb_taps; i++)
378+ time[i] = 0;
379+
380+ get_power_double(ctx, s, nb_taps, ch, time);
381+ for (int n = 0; n < s->nb_segments; n++) {
382+ AudioFIRSegment *seg = &s->seg[n];
383+
384+ if (!seg->coeff[selir])
385+ seg->coeff[selir] = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->coeff_size * 2);
386+ if (!seg->coeff[selir])
387+ return AVERROR(ENOMEM);
388+
389+ for (int i = 0; i < seg->nb_partitions; i++)
390+ convert_channel_double(ctx, s, ch, seg, i, selir);
391+ }
392+ }
393+ break;
394+ }
395+
349396 s->have_coeffs[selir] = 1;
350397
351398 return 0;
@@ -536,9 +583,10 @@ static av_cold void uninit(AVFilterContext *ctx) · 184 unmodified lines
536583
537584 av_freep(&s->fdsp);
538585
539− av_frame_free(&s->norm_ir);
540− for (int i = 0; i < s->nb_irs; i++)
586+ for (int i = 0; i < s->nb_irs; i++) {
541587 av_frame_free(&s->ir[i]);
588+ av_frame_free(&s->norm_ir[i]);
589+ }
542590
543591 av_frame_free(&s->video);
544592 }
libavfilter/af_afir.h+4−5
@@ -28,6 +28,8 @@ · 27 unmodified lines
2828 #include "avfilter.h"
2929 #include "af_afirdsp.h"
3030
31+#define MAX_IR_STREAMS 32
32+
3133 typedef struct AudioFIRSegment {
3234 int nb_partitions;
3335 int part_size;
@@ -47,17 +49,14 @@ typedef struct AudioFIRSegment { · 13 unmodified lines
4749 AVFrame *tempin;
4850 AVFrame *tempout;
4951 AVFrame *buffer;
50− AVFrame *coeff;
52+ AVFrame *coeff[MAX_IR_STREAMS];
5153 AVFrame *input;
5254 AVFrame *output;
53− AVFrame *loaded;
5455
5556 AVTXContext **ctx, **tx, **itx;
5657 av_tx_fn ctx_fn, tx_fn, itx_fn;
5758 } AudioFIRSegment;
5859
59−#define MAX_IR_STREAMS 32
60−
6160 typedef struct AudioFIRContext {
6261 const AVClass *class;
6362
@@ -91,7 +90,7 @@ typedef struct AudioFIRContext { · 27 unmodified lines
9190
9291 AVFrame *in;
9392 AVFrame *ir[MAX_IR_STREAMS];
94− AVFrame *norm_ir;
93+ AVFrame *norm_ir[MAX_IR_STREAMS];
9594 AVFrame *video;
9695 int min_part_size;
9796 int64_t pts;
libavfilter/afir_template.c+91−46
@@ -141,7 +141,8 @@ end: · 140 unmodified lines
141141 }
142142
143143 static int fn(get_power)(AVFilterContext *ctx, AudioFIRContext *s,
144− int cur_nb_taps, int ch)
144+ int cur_nb_taps, int ch,
145+ ftype *time)
145146 {
146147 ftype ch_gain = 1;
147148
@@ -151,7 +152,6 @@ static int fn(get_power)(AVFilterContext *ctx, AudioFIRContext *s, · 3 unmodified lines
151152 break;
152153 case 0:
153154 {
154− ftype *time = (ftype *)s->norm_ir->extended_data[ch];
155155 ftype sum = 0;
156156
157157 for (int i = 0; i < cur_nb_taps; i++)
@@ -161,7 +161,6 @@ static int fn(get_power)(AVFilterContext *ctx, AudioFIRContext *s, · 3 unmodified lines
161161 break;
162162 case 1:
163163 {
164− ftype *time = (ftype *)s->norm_ir->extended_data[ch];
165164 ftype sum = 0;
166165
167166 for (int i = 0; i < cur_nb_taps; i++)
@@ -171,7 +170,6 @@ static int fn(get_power)(AVFilterContext *ctx, AudioFIRContext *s, · 3 unmodified lines
171170 break;
172171 case 2:
173172 {
174− ftype *time = (ftype *)s->norm_ir->extended_data[ch];
175173 ftype sum = 0;
176174
177175 for (int i = 0; i < cur_nb_taps; i++)
@@ -182,7 +180,7 @@ static int fn(get_power)(AVFilterContext *ctx, AudioFIRContext *s, · 4 unmodified lines
182180 case 3:
183181 case 4:
184182 {
185− ftype *inc, *outc, scale;
183+ ftype *inc, *outc, scale, power;
186184 AVTXContext *tx;
187185 av_tx_fn tx_fn;
188186 int ret, size;
@@ -205,7 +203,6 @@ static int fn(get_power)(AVFilterContext *ctx, AudioFIRContext *s, · 16 unmodified lines
205203 }
206204
207205 {
208− ftype power, *time = (ftype *)s->norm_ir->extended_data[ch];
209206 memcpy(inc, time, cur_nb_taps * sizeof(SAMPLE_FORMAT));
210207 tx_fn(tx, outc, inc, sizeof(SAMPLE_FORMAT));
211208
@@ -233,7 +230,6 @@ static int fn(get_power)(AVFilterContext *ctx, AudioFIRContext *s, · 21 unmodified lines
233230 }
234231
235232 if (ch_gain != 1. || s->ir_gain != 1.) {
236− ftype *time = (ftype *)s->norm_ir->extended_data[ch];
237233 ftype gain = ch_gain * s->ir_gain;
238234
239235 av_log(ctx, AV_LOG_DEBUG, "ch%d gain %f\n", ch, gain);
@@ -248,45 +244,24 @@ static int fn(get_power)(AVFilterContext *ctx, AudioFIRContext *s, · 8 unmodified lines
248244 }
249245
250246 static void fn(convert_channel)(AVFilterContext *ctx, AudioFIRContext *s, int ch,
251− AudioFIRSegment *seg)
247+ AudioFIRSegment *seg, int coeff_partition, int selir)
252248 {
253− const int coeff_partition = seg->loading[ch];
254249 const int coffset = coeff_partition * seg->coeff_size;
255− const int selir = s->selir;
256250 const int nb_taps = s->nb_taps[selir];
257− ftype *tsrc = (ftype *)s->ir[selir]->extended_data[!s->one2many * ch];
258− ftype *time = (ftype *)s->norm_ir->extended_data[ch];
251+ ftype *time = (ftype *)s->norm_ir[selir]->extended_data[ch];
259252 ftype *tempin = (ftype *)seg->tempin->extended_data[ch];
260253 ftype *tempout = (ftype *)seg->tempout->extended_data[ch];
261− ctype *coeff = (ctype *)seg->coeff->extended_data[ch];
262− int *loaded = (int *)seg->loaded->extended_data[ch];
254+ ctype *coeff = (ctype *)seg->coeff[selir]->extended_data[ch];
263255 const int remaining = nb_taps - (seg->input_offset + coeff_partition * seg->part_size);
264256 const int size = remaining >= seg->part_size ? seg->part_size : remaining;
265257
266− if (loaded[coeff_partition] == selir + 1)
267− return;
268− loaded[coeff_partition] = selir + 1;
269−
270− memcpy(time, tsrc, sizeof(*time) * nb_taps);
271− for (int i = FFMAX(1, s->length * nb_taps); i < nb_taps; i++)
272− time[i] = 0;
273−
274−#if DEPTH == 32
275− get_power_float(ctx, s, nb_taps, ch);
276−#else
277− get_power_double(ctx, s, nb_taps, ch);
278−#endif
279−
280− av_log(ctx, AV_LOG_DEBUG, "channel: %d\n", ch);
281−
282258 memset(tempin + size, 0, sizeof(*tempin) * (seg->block_size - size));
283259 memcpy(tempin, time + seg->input_offset + coeff_partition * seg->part_size,
284260 size * sizeof(*tempin));
285−
286261 seg->ctx_fn(seg->ctx[ch], tempout, tempin, sizeof(*tempin));
287−
288262 memcpy(coeff + coffset, tempout, seg->coeff_size * sizeof(*coeff));
289263
264+ av_log(ctx, AV_LOG_DEBUG, "channel: %d\n", ch);
290265 av_log(ctx, AV_LOG_DEBUG, "nb_partitions: %d\n", seg->nb_partitions);
291266 av_log(ctx, AV_LOG_DEBUG, "partition size: %d\n", seg->part_size);
292267 av_log(ctx, AV_LOG_DEBUG, "block size: %d\n", seg->block_size);
@@ -314,11 +289,12 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offse · 21 unmodified lines
314289 {
315290 AudioFIRContext *s = ctx->priv;
316291 const ftype *in = (const ftype *)s->in->extended_data[ch] + offset;
317− ftype *blockout, *buf, *ptr = (ftype *)out->extended_data[ch] + offset;
292+ ftype *blockout, *ptr = (ftype *)out->extended_data[ch] + offset;
318293 const int min_part_size = s->min_part_size;
319294 const int nb_samples = FFMIN(min_part_size, out->nb_samples - offset);
320295 const int nb_segments = s->nb_segments;
321296 const float dry_gain = s->dry_gain;
297+ const int selir = s->selir;
322298
323299 for (int segment = 0; segment < nb_segments; segment++) {
324300 AudioFIRSegment *seg = &s->seg[segment];
@@ -327,6 +303,7 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offse · 2 unmodified lines
327303 ftype *sumin = (ftype *)seg->sumin->extended_data[ch];
328304 ftype *sumout = (ftype *)seg->sumout->extended_data[ch];
329305 ftype *tempin = (ftype *)seg->tempin->extended_data[ch];
306+ ftype *buf = (ftype *)seg->buffer->extended_data[ch];
330307 int *output_offset = &seg->output_offset[ch];
331308 const int nb_partitions = seg->nb_partitions;
332309 const int input_offset = seg->input_offset;
@@ -359,28 +336,71 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offse · 26 unmodified lines
359336 }
360337
361338 memset(sumin, 0, sizeof(*sumin) * seg->fft_length);
339+
340+ if (seg->loading[ch] < nb_partitions) {
341+ j = seg->part_index[ch] <= 0 ? nb_partitions - 1 : seg->part_index[ch] - 1;
342+ for (int i = 0; i < nb_partitions; i++) {
343+ const int input_partition = j;
344+ const int coeff_partition = i;
345+ const int coffset = coeff_partition * seg->coeff_size;
346+ const ftype *blockout = (const ftype *)seg->blockout->extended_data[ch] + input_partition * seg->block_size;
347+ const ctype *coeff = ((const ctype *)seg->coeff[selir]->extended_data[ch]) + coffset;
348+
349+ if (j == 0)
350+ j = nb_partitions;
351+ j--;
352+
353+#if DEPTH == 32
354+ s->afirdsp.fcmul_add(sumin, blockout, (const ftype *)coeff, part_size);
355+#else
356+ s->afirdsp.dcmul_add(sumin, blockout, (const ftype *)coeff, part_size);
357+#endif
358+ }
359+
360+ seg->itx_fn(seg->itx[ch], sumout, sumin, sizeof(ctype));
361+ memcpy(dst + part_size, sumout + part_size, part_size * sizeof(*buf));
362+ memset(sumin, 0, sizeof(*sumin) * seg->fft_length);
363+ }
364+
362365 blockout = (ftype *)seg->blockout->extended_data[ch] + seg->part_index[ch] * seg->block_size;
363366 memset(tempin + part_size, 0, sizeof(*tempin) * (seg->block_size - part_size));
364367 memcpy(tempin, src, sizeof(*src) * part_size);
365−
366368 seg->tx_fn(seg->tx[ch], blockout, tempin, sizeof(ftype));
367369
368− j = seg->part_index[ch];
369370 if (seg->loading[ch] < nb_partitions) {
371+ const int selir = s->prev_selir;
372+
373+ j = seg->part_index[ch];
374+ for (int i = 0; i < nb_partitions; i++) {
375+ const int input_partition = j;
376+ const int coeff_partition = i;
377+ const int coffset = coeff_partition * seg->coeff_size;
378+ const ftype *blockout = (const ftype *)seg->blockout->extended_data[ch] + input_partition * seg->block_size;
379+ const ctype *coeff = ((const ctype *)seg->coeff[selir]->extended_data[ch]) + coffset;
380+
381+ if (j == 0)
382+ j = nb_partitions;
383+ j--;
384+
370385 #if DEPTH == 32
371− convert_channel_float(ctx, s, ch, seg);
386+ s->afirdsp.fcmul_add(sumin, blockout, (const ftype *)coeff, part_size);
372387 #else
373− convert_channel_double(ctx, s, ch, seg);
388+ s->afirdsp.dcmul_add(sumin, blockout, (const ftype *)coeff, part_size);
374389 #endif
375− seg->loading[ch]++;
390+ }
391+
392+ seg->itx_fn(seg->itx[ch], sumout, sumin, sizeof(ctype));
393+ memcpy(dst + 2 * part_size, sumout, 2 * part_size * sizeof(*dst));
394+ memset(sumin, 0, sizeof(*sumin) * seg->fft_length);
376395 }
377396
397+ j = seg->part_index[ch];
378398 for (int i = 0; i < nb_partitions; i++) {
379399 const int input_partition = j;
380400 const int coeff_partition = i;
381401 const int coffset = coeff_partition * seg->coeff_size;
382402 const ftype *blockout = (const ftype *)seg->blockout->extended_data[ch] + input_partition * seg->block_size;
383− const ctype *coeff = ((const ctype *)seg->coeff->extended_data[ch]) + coffset;
403+ const ctype *coeff = ((const ctype *)seg->coeff[selir]->extended_data[ch]) + coffset;
384404
385405 if (j == 0)
386406 j = nb_partitions;
@@ -395,18 +415,43 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offse · 8 unmodified lines
395415
396416 seg->itx_fn(seg->itx[ch], sumout, sumin, sizeof(ctype));
397417
398− buf = (ftype *)seg->buffer->extended_data[ch];
399− fn(fir_fadd)(s, buf, sumout, part_size);
400−
401− memcpy(dst, buf, part_size * sizeof(*dst));
402− memcpy(buf, sumout + part_size, part_size * sizeof(*buf));
418+ if (seg->loading[ch] < nb_partitions) {
419+ ftype *ptr1 = dst + part_size;
420+ ftype *ptr2 = dst + part_size * 2;
421+ ftype *ptr3 = dst + part_size * 3;
422+ ftype *ptr4 = dst + part_size * 4;
423+ if (seg->loading[ch] == 0)
424+ memcpy(ptr4, buf, sizeof(*ptr4) * part_size);
425+ for (int n = 0; n < part_size; n++)
426+ ptr2[n] += ptr4[n];
427+
428+ if (seg->loading[ch] < nb_partitions - 1)
429+ memcpy(ptr4, ptr3, part_size * sizeof(*dst));
430+ for (int n = 0; n < part_size; n++)
431+ ptr1[n] += sumout[n];
432+
433+ if (seg->loading[ch] == nb_partitions - 1)
434+ memcpy(buf, sumout + part_size, part_size * sizeof(*buf));
435+
436+ for (int i = 0; i < part_size; i++) {
437+ const ftype factor = (part_size * seg->loading[ch] + i) / (ftype)(part_size * nb_partitions);
438+ const ftype ifactor = 1 - factor;
439+ dst[i] = ptr1[i] * factor + ptr2[i] * ifactor;
440+ }
441+ } else {
442+ fn(fir_fadd)(s, buf, sumout, part_size);
443+ memcpy(dst, buf, part_size * sizeof(*dst));
444+ memcpy(buf, sumout + part_size, part_size * sizeof(*buf));
445+ }
403446
404− seg->part_index[ch] = (seg->part_index[ch] + 1) % nb_partitions;
447+ fn(fir_fadd)(s, ptr, dst, nb_samples);
405448
406449 if (part_size != min_part_size)
407450 memmove(src, src + min_part_size, (seg->input_size - min_part_size) * sizeof(*src));
408451
409− fn(fir_fadd)(s, ptr, dst, nb_samples);
452+ seg->part_index[ch] = (seg->part_index[ch] + 1) % nb_partitions;
453+ if (seg->loading[ch] < nb_partitions)
454+ seg->loading[ch]++;
410455 }
411456
412457 if (s->wet_gain == 1.f)

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