]> git.sesse.net Git - ffmpeg/blob - libavfilter/af_adeclick.c
Merge commit 'b93026777aada7742583d8c5ab079e9f4dfe9a5d'
[ffmpeg] / libavfilter / af_adeclick.c
1 /*
2  * Copyright (c) 2018 Paul B Mahol
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include "libavutil/audio_fifo.h"
22 #include "libavutil/opt.h"
23 #include "avfilter.h"
24 #include "audio.h"
25 #include "formats.h"
26
27 typedef struct DeclickChannel {
28     double *auxiliary;
29     double *detection;
30     double *acoefficients;
31     double *acorrelation;
32     double *tmp;
33     double *interpolated;
34     double *matrix;
35     int matrix_size;
36     double *vector;
37     int vector_size;
38     double *y;
39     int y_size;
40     uint8_t *click;
41     int *index;
42     unsigned *histogram;
43     int histogram_size;
44 } DeclickChannel;
45
46 typedef struct AudioDeclickContext {
47     const AVClass *class;
48
49     double w;
50     double overlap;
51     double threshold;
52     double ar;
53     double burst;
54     int method;
55     int nb_hbins;
56
57     int is_declip;
58     int ar_order;
59     int nb_burst_samples;
60     int window_size;
61     int hop_size;
62     int overlap_skip;
63
64     AVFrame *in;
65     AVFrame *out;
66     AVFrame *buffer;
67     AVFrame *is;
68
69     DeclickChannel *chan;
70
71     int64_t pts;
72     int nb_channels;
73     uint64_t nb_samples;
74     uint64_t detected_errors;
75     int samples_left;
76
77     AVAudioFifo *fifo;
78     double *window_func_lut;
79
80     int (*detector)(struct AudioDeclickContext *s, DeclickChannel *c,
81                     double sigmae, double *detection,
82                     double *acoefficients, uint8_t *click, int *index,
83                     const double *src, double *dst);
84 } AudioDeclickContext;
85
86 #define OFFSET(x) offsetof(AudioDeclickContext, x)
87 #define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
88
89 static const AVOption adeclick_options[] = {
90     { "w", "set window size",          OFFSET(w),         AV_OPT_TYPE_DOUBLE, {.dbl=55}, 10,  100, AF },
91     { "o", "set window overlap",       OFFSET(overlap),   AV_OPT_TYPE_DOUBLE, {.dbl=75}, 50,   95, AF },
92     { "a", "set autoregression order", OFFSET(ar),        AV_OPT_TYPE_DOUBLE, {.dbl=2},   0,   25, AF },
93     { "t", "set threshold",            OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=2},   1,  100, AF },
94     { "b", "set burst fusion",         OFFSET(burst),     AV_OPT_TYPE_DOUBLE, {.dbl=2},   0,   10, AF },
95     { "m", "set overlap method",       OFFSET(method),    AV_OPT_TYPE_INT,    {.i64=0},   0,    1, AF, "m" },
96     { "a", "overlap-add",              0,                 AV_OPT_TYPE_CONST,  {.i64=0},   0,    0, AF, "m" },
97     { "s", "overlap-save",             0,                 AV_OPT_TYPE_CONST,  {.i64=1},   0,    0, AF, "m" },
98     { NULL }
99 };
100
101 AVFILTER_DEFINE_CLASS(adeclick);
102
103 static int query_formats(AVFilterContext *ctx)
104 {
105     AVFilterFormats *formats = NULL;
106     AVFilterChannelLayouts *layouts = NULL;
107     static const enum AVSampleFormat sample_fmts[] = {
108         AV_SAMPLE_FMT_DBLP,
109         AV_SAMPLE_FMT_NONE
110     };
111     int ret;
112
113     formats = ff_make_format_list(sample_fmts);
114     if (!formats)
115         return AVERROR(ENOMEM);
116     ret = ff_set_common_formats(ctx, formats);
117     if (ret < 0)
118         return ret;
119
120     layouts = ff_all_channel_counts();
121     if (!layouts)
122         return AVERROR(ENOMEM);
123
124     ret = ff_set_common_channel_layouts(ctx, layouts);
125     if (ret < 0)
126         return ret;
127
128     formats = ff_all_samplerates();
129     return ff_set_common_samplerates(ctx, formats);
130 }
131
132 static int config_input(AVFilterLink *inlink)
133 {
134     AVFilterContext *ctx = inlink->dst;
135     AudioDeclickContext *s = ctx->priv;
136     int i;
137
138     s->pts = AV_NOPTS_VALUE;
139     s->window_size = inlink->sample_rate * s->w / 1000.;
140     if (s->window_size < 100)
141         return AVERROR(EINVAL);
142     s->ar_order = FFMAX(s->window_size * s->ar / 100., 1);
143     s->nb_burst_samples = s->window_size * s->burst / 1000.;
144     s->hop_size = s->window_size * (1. - (s->overlap / 100.));
145     if (s->hop_size < 1)
146         return AVERROR(EINVAL);
147
148     s->window_func_lut = av_calloc(s->window_size, sizeof(*s->window_func_lut));
149     if (!s->window_func_lut)
150         return AVERROR(ENOMEM);
151     for (i = 0; i < s->window_size; i++)
152         s->window_func_lut[i] = sin(M_PI * i / s->window_size) *
153                                 (1. - (s->overlap / 100.)) * M_PI_2;
154
155     av_frame_free(&s->in);
156     av_frame_free(&s->out);
157     av_frame_free(&s->buffer);
158     av_frame_free(&s->is);
159     s->in = ff_get_audio_buffer(inlink, s->window_size);
160     s->out = ff_get_audio_buffer(inlink, s->window_size);
161     s->buffer = ff_get_audio_buffer(inlink, s->window_size * 2);
162     s->is = ff_get_audio_buffer(inlink, s->window_size);
163     if (!s->in || !s->out || !s->buffer || !s->is)
164         return AVERROR(ENOMEM);
165
166     s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, s->window_size);
167     if (!s->fifo)
168         return AVERROR(ENOMEM);
169     s->overlap_skip = s->method ? (s->window_size - s->hop_size) / 2 : 0;
170     if (s->overlap_skip > 0) {
171         av_audio_fifo_write(s->fifo, (void **)s->in->extended_data,
172                             s->overlap_skip);
173     }
174
175     s->nb_channels = inlink->channels;
176     s->chan = av_calloc(inlink->channels, sizeof(*s->chan));
177     if (!s->chan)
178         return AVERROR(ENOMEM);
179
180     for (i = 0; i < inlink->channels; i++) {
181         DeclickChannel *c = &s->chan[i];
182
183         c->detection = av_calloc(s->window_size, sizeof(*c->detection));
184         c->auxiliary = av_calloc(s->ar_order + 1, sizeof(*c->auxiliary));
185         c->acoefficients = av_calloc(s->ar_order + 1, sizeof(*c->acoefficients));
186         c->acorrelation = av_calloc(s->ar_order + 1, sizeof(*c->acorrelation));
187         c->tmp = av_calloc(s->ar_order, sizeof(*c->tmp));
188         c->click = av_calloc(s->window_size, sizeof(*c->click));
189         c->index = av_calloc(s->window_size, sizeof(*c->index));
190         c->interpolated = av_calloc(s->window_size, sizeof(*c->interpolated));
191         if (!c->auxiliary || !c->acoefficients || !c->detection || !c->click ||
192             !c->index || !c->interpolated || !c->acorrelation || !c->tmp)
193             return AVERROR(ENOMEM);
194     }
195
196     return 0;
197 }
198
199 static void autocorrelation(const double *input, int order, int size,
200                             double *output, double scale)
201 {
202     int i, j;
203
204     for (i = 0; i <= order; i++) {
205         double value = 0.;
206
207         for (j = i; j < size; j++)
208             value += input[j] * input[j - i];
209
210         output[i] = value * scale;
211     }
212 }
213
214 static double autoregression(const double *samples, int ar_order,
215                              int nb_samples, double *k, double *r, double *a)
216 {
217     double alpha;
218     int i, j;
219
220     memset(a, 0, ar_order * sizeof(*a));
221
222     autocorrelation(samples, ar_order, nb_samples, r, 1. / nb_samples);
223
224     /* Levinson-Durbin algorithm */
225     k[0] = a[0] = -r[1] / r[0];
226     alpha = r[0] * (1. - k[0] * k[0]);
227     for (i = 1; i < ar_order; i++) {
228         double epsilon = 0.;
229
230         for (j = 0; j < i; j++)
231             epsilon += a[j] * r[i - j];
232         epsilon += r[i + 1];
233
234         k[i] = -epsilon / alpha;
235         alpha *= (1. - k[i] * k[i]);
236         for (j = i - 1; j >= 0; j--)
237             k[j] = a[j] + k[i] * a[i - j - 1];
238         for (j = 0; j <= i; j++)
239             a[j] = k[j];
240     }
241
242     k[0] = 1.;
243     for (i = 1; i <= ar_order; i++)
244         k[i] = a[i - 1];
245
246     return sqrt(alpha);
247 }
248
249 static int isfinite_array(double *samples, int nb_samples)
250 {
251     int i;
252
253     for (i = 0; i < nb_samples; i++)
254         if (!isfinite(samples[i]))
255             return 0;
256
257     return 1;
258 }
259
260 static int find_index(int *index, int value, int size)
261 {
262     int i, start, end;
263
264     if ((value < index[0]) || (value > index[size - 1]))
265         return 1;
266
267     i = start = 0;
268     end = size - 1;
269
270     while (start <= end) {
271         i = (end + start) / 2;
272         if (index[i] == value)
273             return 0;
274         if (value < index[i])
275             end = i - 1;
276         if (value > index[i])
277             start = i + 1;
278     }
279
280     return 1;
281 }
282
283 static int factorization(double *matrix, int n)
284 {
285     int i, j, k;
286
287     for (i = 0; i < n; i++) {
288         const int in = i * n;
289         double value;
290
291         value = matrix[in + i];
292         for (j = 0; j < i; j++)
293             value -= matrix[j * n + j] * matrix[in + j] * matrix[in + j];
294
295         if (value == 0.) {
296             return -1;
297         }
298
299         matrix[in + i] = value;
300         for (j = i + 1; j < n; j++) {
301             const int jn = j * n;
302             double x;
303
304             x = matrix[jn + i];
305             for (k = 0; k < i; k++)
306                 x -= matrix[k * n + k] * matrix[in + k] * matrix[jn + k];
307             matrix[jn + i] = x / matrix[in + i];
308         }
309     }
310
311     return 0;
312 }
313
314 static int do_interpolation(DeclickChannel *c, double *matrix,
315                             double *vector, int n, double *out)
316 {
317     int i, j, ret;
318     double *y;
319
320     ret = factorization(matrix, n);
321     if (ret < 0)
322         return ret;
323
324     av_fast_malloc(&c->y, &c->y_size, n * sizeof(*c->y));
325     y = c->y;
326     if (!y)
327         return AVERROR(ENOMEM);
328
329     for (i = 0; i < n; i++) {
330         const int in = i * n;
331         double value;
332
333         value = vector[i];
334         for (j = 0; j < i; j++)
335             value -= matrix[in + j] * y[j];
336         y[i] = value;
337     }
338
339     for (i = n - 1; i >= 0; i--) {
340         out[i] = y[i] / matrix[i * n + i];
341         for (j = i + 1; j < n; j++)
342             out[i] -= matrix[j * n + i] * out[j];
343     }
344
345     return 0;
346 }
347
348 static int interpolation(DeclickChannel *c, const double *src, int ar_order,
349                          double *acoefficients, int *index, int nb_errors,
350                          double *auxiliary, double *interpolated)
351 {
352     double *vector, *matrix;
353     int i, j;
354
355     av_fast_malloc(&c->matrix, &c->matrix_size, nb_errors * nb_errors * sizeof(*c->matrix));
356     matrix = c->matrix;
357     if (!matrix)
358         return AVERROR(ENOMEM);
359
360     av_fast_malloc(&c->vector, &c->vector_size, nb_errors * sizeof(*c->vector));
361     vector = c->vector;
362     if (!vector)
363         return AVERROR(ENOMEM);
364
365     autocorrelation(acoefficients, ar_order, ar_order + 1, auxiliary, 1.);
366
367     for (i = 0; i < nb_errors; i++) {
368         const int im = i * nb_errors;
369
370         for (j = i; j < nb_errors; j++) {
371             if (abs(index[j] - index[i]) <= ar_order) {
372                 matrix[j * nb_errors + i] = matrix[im + j] = auxiliary[abs(index[j] - index[i])];
373             } else {
374                 matrix[j * nb_errors + i] = matrix[im + j] = 0;
375             }
376         }
377     }
378
379     for (i = 0; i < nb_errors; i++) {
380         double value = 0.;
381
382         for (j = -ar_order; j <= ar_order; j++)
383             if (find_index(index, index[i] - j, nb_errors))
384                 value -= src[index[i] - j] * auxiliary[abs(j)];
385
386         vector[i] = value;
387     }
388
389     return do_interpolation(c, matrix, vector, nb_errors, interpolated);
390 }
391
392 static int detect_clips(AudioDeclickContext *s, DeclickChannel *c,
393                         double unused0,
394                         double *unused1, double *unused2,
395                         uint8_t *clip, int *index,
396                         const double *src, double *dst)
397 {
398     const double threshold = s->threshold;
399     double max_amplitude = 0;
400     unsigned *histogram;
401     int i, nb_clips = 0;
402
403     av_fast_malloc(&c->histogram, &c->histogram_size, s->nb_hbins * sizeof(*c->histogram));
404     if (!c->histogram)
405         return AVERROR(ENOMEM);
406     histogram = c->histogram;
407     memset(histogram, 0, sizeof(*histogram) * s->nb_hbins);
408
409     for (i = 0; i < s->window_size; i++) {
410         const unsigned index = fmin(fabs(src[i]), 1) * (s->nb_hbins - 1);
411
412         histogram[index]++;
413         dst[i] = src[i];
414         clip[i] = 0;
415     }
416
417     for (i = s->nb_hbins - 1; i > 1; i--) {
418         if (histogram[i]) {
419             if (histogram[i] / (double)FFMAX(histogram[i - 1], 1) > threshold) {
420                 max_amplitude = i / (double)s->nb_hbins;
421             }
422             break;
423         }
424     }
425
426     if (max_amplitude > 0.) {
427         for (i = 0; i < s->window_size; i++) {
428             clip[i] = fabs(src[i]) >= max_amplitude;
429         }
430     }
431
432     memset(clip, 0, s->ar_order * sizeof(*clip));
433     memset(clip + (s->window_size - s->ar_order), 0, s->ar_order * sizeof(*clip));
434
435     for (i = s->ar_order; i < s->window_size - s->ar_order; i++)
436         if (clip[i])
437             index[nb_clips++] = i;
438
439     return nb_clips;
440 }
441
442 static int detect_clicks(AudioDeclickContext *s, DeclickChannel *c,
443                          double sigmae,
444                          double *detection, double *acoefficients,
445                          uint8_t *click, int *index,
446                          const double *src, double *dst)
447 {
448     const double threshold = s->threshold;
449     int i, j, nb_clicks = 0, prev = -1;
450
451     memset(detection, 0, s->window_size * sizeof(*detection));
452
453     for (i = s->ar_order; i < s->window_size; i++) {
454         for (j = 0; j <= s->ar_order; j++) {
455             detection[i] += acoefficients[j] * src[i - j];
456         }
457     }
458
459     for (i = 0; i < s->window_size; i++) {
460         click[i] = fabs(detection[i]) > sigmae * threshold;
461         dst[i] = src[i];
462     }
463
464     for (i = 0; i < s->window_size; i++) {
465         if (!click[i])
466             continue;
467
468         if (prev >= 0 && (i > prev + 1) && (i <= s->nb_burst_samples + prev))
469             for (j = prev + 1; j < i; j++)
470                 click[j] = 1;
471         prev = i;
472     }
473
474     memset(click, 0, s->ar_order * sizeof(*click));
475     memset(click + (s->window_size - s->ar_order), 0, s->ar_order * sizeof(*click));
476
477     for (i = s->ar_order; i < s->window_size - s->ar_order; i++)
478         if (click[i])
479             index[nb_clicks++] = i;
480
481     return nb_clicks;
482 }
483
484 typedef struct ThreadData {
485     AVFrame *out;
486 } ThreadData;
487
488 static int filter_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs)
489 {
490     AudioDeclickContext *s = ctx->priv;
491     ThreadData *td = arg;
492     AVFrame *out = td->out;
493     const double *src = (const double *)s->in->extended_data[ch];
494     double *is = (double *)s->is->extended_data[ch];
495     double *dst = (double *)s->out->extended_data[ch];
496     double *ptr = (double *)out->extended_data[ch];
497     double *buf = (double *)s->buffer->extended_data[ch];
498     const double *w = s->window_func_lut;
499     DeclickChannel *c = &s->chan[ch];
500     double sigmae;
501     int j, ret;
502
503     sigmae = autoregression(src, s->ar_order, s->window_size, c->acoefficients, c->acorrelation, c->tmp);
504
505     if (isfinite_array(c->acoefficients, s->ar_order + 1)) {
506         double *interpolated = c->interpolated;
507         int *index = c->index;
508         int nb_errors;
509
510         nb_errors = s->detector(s, c, sigmae, c->detection, c->acoefficients,
511                                 c->click, index, src, dst);
512         if (nb_errors > 0) {
513             ret = interpolation(c, src, s->ar_order, c->acoefficients, index,
514                                 nb_errors, c->auxiliary, interpolated);
515             if (ret < 0)
516                 return ret;
517
518             for (j = 0; j < nb_errors; j++) {
519                 dst[index[j]] = interpolated[j];
520                 is[index[j]] = 1;
521             }
522         }
523     } else {
524         memcpy(dst, src, s->window_size * sizeof(*dst));
525     }
526
527     if (s->method == 0) {
528         for (j = 0; j < s->window_size; j++)
529             buf[j] += dst[j] * w[j];
530     } else {
531         const int skip = s->overlap_skip;
532
533         for (j = 0; j < s->hop_size; j++)
534             buf[j] = dst[skip + j];
535     }
536     for (j = 0; j < s->hop_size; j++)
537         ptr[j] = buf[j];
538
539     memmove(buf, buf + s->hop_size, (s->window_size * 2 - s->hop_size) * sizeof(*buf));
540     memmove(is, is + s->hop_size, (s->window_size - s->hop_size) * sizeof(*is));
541     memset(buf + s->window_size * 2 - s->hop_size, 0, s->hop_size * sizeof(*buf));
542     memset(is + s->window_size - s->hop_size, 0, s->hop_size * sizeof(*is));
543
544     return 0;
545 }
546
547 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
548 {
549     AVFilterContext *ctx = inlink->dst;
550     AVFilterLink *outlink = ctx->outputs[0];
551     AudioDeclickContext *s = ctx->priv;
552     AVFrame *out = NULL;
553     int ret = 0;
554
555     if (s->pts == AV_NOPTS_VALUE)
556         s->pts = in->pts;
557
558     ret = av_audio_fifo_write(s->fifo, (void **)in->extended_data,
559                               in->nb_samples);
560     av_frame_free(&in);
561
562     while (av_audio_fifo_size(s->fifo) >= s->window_size) {
563         int j, ch, detected_errors = 0;
564         ThreadData td;
565
566         out = ff_get_audio_buffer(outlink, s->hop_size);
567         if (!out)
568             return AVERROR(ENOMEM);
569
570         ret = av_audio_fifo_peek(s->fifo, (void **)s->in->extended_data,
571                                  s->window_size);
572         if (ret < 0)
573             break;
574
575         td.out = out;
576         ret = ctx->internal->execute(ctx, filter_channel, &td, NULL, inlink->channels);
577         if (ret < 0)
578             goto fail;
579
580         for (ch = 0; ch < s->in->channels; ch++) {
581             double *is = (double *)s->is->extended_data[ch];
582
583             for (j = 0; j < s->hop_size; j++) {
584                 if (is[j])
585                     detected_errors++;
586             }
587         }
588
589         av_audio_fifo_drain(s->fifo, s->hop_size);
590
591         if (s->samples_left > 0)
592             out->nb_samples = FFMIN(s->hop_size, s->samples_left);
593
594         out->pts = s->pts;
595         s->pts += s->hop_size;
596
597         s->detected_errors += detected_errors;
598         s->nb_samples += out->nb_samples * inlink->channels;
599
600         ret = ff_filter_frame(outlink, out);
601         if (ret < 0)
602             break;
603
604         if (s->samples_left > 0) {
605             s->samples_left -= s->hop_size;
606             if (s->samples_left <= 0)
607                 av_audio_fifo_drain(s->fifo, av_audio_fifo_size(s->fifo));
608         }
609     }
610
611 fail:
612     if (ret < 0)
613         av_frame_free(&out);
614     return ret;
615 }
616
617 static int request_frame(AVFilterLink *outlink)
618 {
619     AVFilterContext *ctx = outlink->src;
620     AudioDeclickContext *s = ctx->priv;
621     int ret = 0;
622
623     ret = ff_request_frame(ctx->inputs[0]);
624
625     if (ret == AVERROR_EOF && av_audio_fifo_size(s->fifo) > 0) {
626         if (!s->samples_left)
627             s->samples_left = av_audio_fifo_size(s->fifo) - s->overlap_skip;
628
629         if (s->samples_left > 0) {
630             AVFrame *in = ff_get_audio_buffer(outlink, s->window_size - s->samples_left);
631             if (!in)
632                 return AVERROR(ENOMEM);
633             ret = filter_frame(ctx->inputs[0], in);
634         }
635     }
636
637     return ret;
638 }
639
640 static av_cold int init(AVFilterContext *ctx)
641 {
642     AudioDeclickContext *s = ctx->priv;
643
644     s->is_declip = !strcmp(ctx->filter->name, "adeclip");
645     if (s->is_declip) {
646         s->detector = detect_clips;
647     } else {
648         s->detector = detect_clicks;
649     }
650
651     return 0;
652 }
653
654 static av_cold void uninit(AVFilterContext *ctx)
655 {
656     AudioDeclickContext *s = ctx->priv;
657     int i;
658
659     av_log(ctx, AV_LOG_INFO, "Detected %s in %"PRId64" of %"PRId64" samples (%g%%).\n",
660            s->is_declip ? "clips" : "clicks", s->detected_errors,
661            s->nb_samples, 100. * s->detected_errors / s->nb_samples);
662
663     av_audio_fifo_free(s->fifo);
664     av_freep(&s->window_func_lut);
665     av_frame_free(&s->in);
666     av_frame_free(&s->out);
667     av_frame_free(&s->buffer);
668     av_frame_free(&s->is);
669
670     if (s->chan) {
671         for (i = 0; i < s->nb_channels; i++) {
672             DeclickChannel *c = &s->chan[i];
673
674             av_freep(&c->detection);
675             av_freep(&c->auxiliary);
676             av_freep(&c->acoefficients);
677             av_freep(&c->acorrelation);
678             av_freep(&c->tmp);
679             av_freep(&c->click);
680             av_freep(&c->index);
681             av_freep(&c->interpolated);
682             av_freep(&c->matrix);
683             c->matrix_size = 0;
684             av_freep(&c->histogram);
685             c->histogram_size = 0;
686             av_freep(&c->vector);
687             c->vector_size = 0;
688             av_freep(&c->y);
689             c->y_size = 0;
690         }
691     }
692     av_freep(&s->chan);
693     s->nb_channels = 0;
694 }
695
696 static const AVFilterPad inputs[] = {
697     {
698         .name         = "default",
699         .type         = AVMEDIA_TYPE_AUDIO,
700         .filter_frame = filter_frame,
701         .config_props = config_input,
702     },
703     { NULL }
704 };
705
706 static const AVFilterPad outputs[] = {
707     {
708         .name          = "default",
709         .type          = AVMEDIA_TYPE_AUDIO,
710         .request_frame = request_frame,
711     },
712     { NULL }
713 };
714
715 AVFilter ff_af_adeclick = {
716     .name          = "adeclick",
717     .description   = NULL_IF_CONFIG_SMALL("Remove impulsive noise from input audio."),
718     .query_formats = query_formats,
719     .priv_size     = sizeof(AudioDeclickContext),
720     .priv_class    = &adeclick_class,
721     .init          = init,
722     .uninit        = uninit,
723     .inputs        = inputs,
724     .outputs       = outputs,
725     .flags         = AVFILTER_FLAG_SLICE_THREADS,
726 };
727
728 static const AVOption adeclip_options[] = {
729     { "w", "set window size",          OFFSET(w),              AV_OPT_TYPE_DOUBLE, {.dbl=55},     10,  100, AF },
730     { "o", "set window overlap",       OFFSET(overlap),        AV_OPT_TYPE_DOUBLE, {.dbl=75},     50,   95, AF },
731     { "a", "set autoregression order", OFFSET(ar),             AV_OPT_TYPE_DOUBLE, {.dbl=8},       0,   25, AF },
732     { "t", "set threshold",            OFFSET(threshold),      AV_OPT_TYPE_DOUBLE, {.dbl=10},      1,  100, AF },
733     { "n", "set histogram size",       OFFSET(nb_hbins),       AV_OPT_TYPE_INT,    {.i64=1000},  100, 9999, AF },
734     { "m", "set overlap method",       OFFSET(method),         AV_OPT_TYPE_INT,    {.i64=0},       0,    1, AF, "m" },
735     { "a", "overlap-add",              0,                      AV_OPT_TYPE_CONST,  {.i64=0},       0,    0, AF, "m" },
736     { "s", "overlap-save",             0,                      AV_OPT_TYPE_CONST,  {.i64=1},       0,    0, AF, "m" },
737     { NULL }
738 };
739
740 AVFILTER_DEFINE_CLASS(adeclip);
741
742 AVFilter ff_af_adeclip = {
743     .name          = "adeclip",
744     .description   = NULL_IF_CONFIG_SMALL("Remove clipping from input audio."),
745     .query_formats = query_formats,
746     .priv_size     = sizeof(AudioDeclickContext),
747     .priv_class    = &adeclip_class,
748     .init          = init,
749     .uninit        = uninit,
750     .inputs        = inputs,
751     .outputs       = outputs,
752     .flags         = AVFILTER_FLAG_SLICE_THREADS,
753 };