Browse code

avfilter: add adeclick and adeclip audio filters

Signed-off-by: Paul B Mahol <onemda@gmail.com>

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