X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Faf_adeclick.c;h=798838f522cb5f0f90b376bf6fef5cd39c956bb7;hb=a859e57424ca0a00d17bdc034c52005c18184961;hp=50eef7492181f2bfe62ea78fbf742a665dddf416;hpb=e6c7d838ea90e569e2b03457a6c6637c6b315c10;p=ffmpeg diff --git a/libavfilter/af_adeclick.c b/libavfilter/af_adeclick.c index 50eef749218..798838f522c 100644 --- a/libavfilter/af_adeclick.c +++ b/libavfilter/af_adeclick.c @@ -63,6 +63,7 @@ typedef struct AudioDeclickContext { int hop_size; int overlap_skip; + AVFrame *enabled; AVFrame *in; AVFrame *out; AVFrame *buffer; @@ -77,6 +78,7 @@ typedef struct AudioDeclickContext { int samples_left; int eof; + AVAudioFifo *efifo; AVAudioFifo *fifo; double *window_func_lut; @@ -90,13 +92,21 @@ typedef struct AudioDeclickContext { #define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption adeclick_options[] = { + { "window", "set window size", OFFSET(w), AV_OPT_TYPE_DOUBLE, {.dbl=55}, 10, 100, AF }, { "w", "set window size", OFFSET(w), AV_OPT_TYPE_DOUBLE, {.dbl=55}, 10, 100, AF }, + { "overlap", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_DOUBLE, {.dbl=75}, 50, 95, AF }, { "o", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_DOUBLE, {.dbl=75}, 50, 95, AF }, + { "arorder", "set autoregression order", OFFSET(ar), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, 25, AF }, { "a", "set autoregression order", OFFSET(ar), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, 25, AF }, + { "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 1, 100, AF }, { "t", "set threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 1, 100, AF }, + { "burst", "set burst fusion", OFFSET(burst), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, 10, AF }, { "b", "set burst fusion", OFFSET(burst), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, 10, AF }, + { "method", "set overlap method", OFFSET(method), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "m" }, { "m", "set overlap method", OFFSET(method), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "m" }, + { "add", "overlap-add", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "m" }, { "a", "overlap-add", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "m" }, + { "save", "overlap-save", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "m" }, { "s", "overlap-save", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "m" }, { NULL } }; @@ -159,13 +169,17 @@ static int config_input(AVFilterLink *inlink) av_frame_free(&s->out); av_frame_free(&s->buffer); av_frame_free(&s->is); + s->enabled = ff_get_audio_buffer(inlink, s->window_size); s->in = ff_get_audio_buffer(inlink, s->window_size); s->out = ff_get_audio_buffer(inlink, s->window_size); s->buffer = ff_get_audio_buffer(inlink, s->window_size * 2); s->is = ff_get_audio_buffer(inlink, s->window_size); - if (!s->in || !s->out || !s->buffer || !s->is) + if (!s->in || !s->out || !s->buffer || !s->is || !s->enabled) return AVERROR(ENOMEM); + s->efifo = av_audio_fifo_alloc(inlink->format, 1, s->window_size); + if (!s->efifo) + return AVERROR(ENOMEM); s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, s->window_size); if (!s->fifo) return AVERROR(ENOMEM); @@ -513,14 +527,20 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) nb_errors = s->detector(s, c, sigmae, c->detection, c->acoefficients, c->click, index, src, dst); if (nb_errors > 0) { + double *enabled = (double *)s->enabled->extended_data[0]; + ret = interpolation(c, src, s->ar_order, c->acoefficients, index, nb_errors, c->auxiliary, interpolated); if (ret < 0) return ret; + av_audio_fifo_peek(s->efifo, (void**)s->enabled->extended_data, s->window_size); + for (j = 0; j < nb_errors; j++) { - dst[index[j]] = interpolated[j]; - is[index[j]] = 1; + if (enabled[index[j]]) { + dst[index[j]] = interpolated[j]; + is[index[j]] = 1; + } } } } else { @@ -580,19 +600,20 @@ static int filter_frame(AVFilterLink *inlink) } av_audio_fifo_drain(s->fifo, s->hop_size); + av_audio_fifo_drain(s->efifo, s->hop_size); if (s->samples_left > 0) out->nb_samples = FFMIN(s->hop_size, s->samples_left); out->pts = s->pts; - s->pts += s->hop_size; + s->pts += av_rescale_q(s->hop_size, (AVRational){1, outlink->sample_rate}, outlink->time_base); s->detected_errors += detected_errors; s->nb_samples += out->nb_samples * inlink->channels; ret = ff_filter_frame(outlink, out); if (ret < 0) - goto fail; + return ret; if (s->samples_left > 0) { s->samples_left -= s->hop_size; @@ -621,11 +642,17 @@ static int activate(AVFilterContext *ctx) if (ret < 0) return ret; if (ret > 0) { + double *e = (double *)s->enabled->extended_data[0]; + if (s->pts == AV_NOPTS_VALUE) s->pts = in->pts; ret = av_audio_fifo_write(s->fifo, (void **)in->extended_data, in->nb_samples); + for (int i = 0; i < in->nb_samples; i++) + e[i] = !ctx->is_disabled; + + av_audio_fifo_write(s->efifo, (void**)s->enabled->extended_data, in->nb_samples); av_frame_free(&in); if (ret < 0) return ret; @@ -684,7 +711,9 @@ static av_cold void uninit(AVFilterContext *ctx) s->nb_samples, 100. * s->detected_errors / s->nb_samples); av_audio_fifo_free(s->fifo); + av_audio_fifo_free(s->efifo); av_freep(&s->window_func_lut); + av_frame_free(&s->enabled); av_frame_free(&s->in); av_frame_free(&s->out); av_frame_free(&s->buffer); @@ -733,7 +762,7 @@ static const AVFilterPad outputs[] = { { NULL } }; -AVFilter ff_af_adeclick = { +const AVFilter ff_af_adeclick = { .name = "adeclick", .description = NULL_IF_CONFIG_SMALL("Remove impulsive noise from input audio."), .query_formats = query_formats, @@ -744,24 +773,32 @@ AVFilter ff_af_adeclick = { .uninit = uninit, .inputs = inputs, .outputs = outputs, - .flags = AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, }; static const AVOption adeclip_options[] = { - { "w", "set window size", OFFSET(w), AV_OPT_TYPE_DOUBLE, {.dbl=55}, 10, 100, AF }, - { "o", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_DOUBLE, {.dbl=75}, 50, 95, AF }, - { "a", "set autoregression order", OFFSET(ar), AV_OPT_TYPE_DOUBLE, {.dbl=8}, 0, 25, AF }, - { "t", "set threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=10}, 1, 100, AF }, - { "n", "set histogram size", OFFSET(nb_hbins), AV_OPT_TYPE_INT, {.i64=1000}, 100, 9999, AF }, - { "m", "set overlap method", OFFSET(method), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "m" }, - { "a", "overlap-add", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "m" }, - { "s", "overlap-save", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "m" }, + { "window", "set window size", OFFSET(w), AV_OPT_TYPE_DOUBLE, {.dbl=55}, 10, 100, AF }, + { "w", "set window size", OFFSET(w), AV_OPT_TYPE_DOUBLE, {.dbl=55}, 10, 100, AF }, + { "overlap", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_DOUBLE, {.dbl=75}, 50, 95, AF }, + { "o", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_DOUBLE, {.dbl=75}, 50, 95, AF }, + { "arorder", "set autoregression order", OFFSET(ar), AV_OPT_TYPE_DOUBLE, {.dbl=8}, 0, 25, AF }, + { "a", "set autoregression order", OFFSET(ar), AV_OPT_TYPE_DOUBLE, {.dbl=8}, 0, 25, AF }, + { "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=10}, 1, 100, AF }, + { "t", "set threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=10}, 1, 100, AF }, + { "hsize", "set histogram size", OFFSET(nb_hbins), AV_OPT_TYPE_INT, {.i64=1000}, 100, 9999, AF }, + { "n", "set histogram size", OFFSET(nb_hbins), AV_OPT_TYPE_INT, {.i64=1000}, 100, 9999, AF }, + { "method", "set overlap method", OFFSET(method), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "m" }, + { "m", "set overlap method", OFFSET(method), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "m" }, + { "add", "overlap-add", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "m" }, + { "a", "overlap-add", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "m" }, + { "save", "overlap-save", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "m" }, + { "s", "overlap-save", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "m" }, { NULL } }; AVFILTER_DEFINE_CLASS(adeclip); -AVFilter ff_af_adeclip = { +const AVFilter ff_af_adeclip = { .name = "adeclip", .description = NULL_IF_CONFIG_SMALL("Remove clipping from input audio."), .query_formats = query_formats, @@ -772,5 +809,5 @@ AVFilter ff_af_adeclip = { .uninit = uninit, .inputs = inputs, .outputs = outputs, - .flags = AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, };