Browse code

avfilter: add audio limiter filter

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

Paul B Mahol authored on 2015/09/06 04:12:58
Showing 6 changed files
... ...
@@ -5,6 +5,7 @@ version <next>:
5 5
 - DXV decoding
6 6
 - extrastereo filter
7 7
 - ocr filter
8
+- alimiter filter
8 9
 
9 10
 
10 11
 version 2.8:
... ...
@@ -641,6 +641,41 @@ Force the output to either unsigned 8-bit or signed 16-bit stereo
641 641
 aformat=sample_fmts=u8|s16:channel_layouts=stereo
642 642
 @end example
643 643
 
644
+@section alimiter
645
+
646
+The limiter prevents input signal from raising over a desired threshold.
647
+This limiter uses lookahead technology to prevent your signal from distorting.
648
+It means that there is a small delay after signal is processed. Keep in mind
649
+that the delay it produces is the attack time you set.
650
+
651
+The filter accepts the following options:
652
+
653
+@table @option
654
+@item limit
655
+Don't let signals above this level pass the limiter. The removed amplitude is
656
+added automatically. Default is 1.
657
+
658
+@item attack
659
+The limiter will reach its attenuation level in this amount of time in
660
+milliseconds. Default is 5 milliseconds.
661
+
662
+@item release
663
+Come back from limiting to attenuation 1.0 in this amount of milliseconds.
664
+Default is 50 milliseconds.
665
+
666
+@item asc
667
+When gain reduction is always needed ASC takes care of releasing to an
668
+average reduction level rather than reaching a reduction of 0 in the release
669
+time.
670
+
671
+@item asc_level
672
+Select how much the release time is affected by ASC, 0 means nearly no changes
673
+in release time while 1 produces higher release times.
674
+@end table
675
+
676
+Depending on picked setting it is recommended to upsample input 2x or 4x times
677
+with @ref{aresample} before applying this filter.
678
+
644 679
 @section allpass
645 680
 
646 681
 Apply a two-pole all-pass filter with central frequency (in Hz)
... ...
@@ -30,6 +30,7 @@ OBJS-$(CONFIG_AEVAL_FILTER)                  += aeval.o
30 30
 OBJS-$(CONFIG_AFADE_FILTER)                  += af_afade.o
31 31
 OBJS-$(CONFIG_AFORMAT_FILTER)                += af_aformat.o
32 32
 OBJS-$(CONFIG_AINTERLEAVE_FILTER)            += f_interleave.o
33
+OBJS-$(CONFIG_ALIMITER_FILTER)               += af_alimiter.o
33 34
 OBJS-$(CONFIG_ALLPASS_FILTER)                += af_biquads.o
34 35
 OBJS-$(CONFIG_AMERGE_FILTER)                 += af_amerge.o
35 36
 OBJS-$(CONFIG_AMIX_FILTER)                   += af_amix.o
36 37
new file mode 100644
... ...
@@ -0,0 +1,361 @@
0
+/*
1
+ * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
2
+ * Copyright (c) 2015 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
+/**
22
+ * @file
23
+ * Lookahead limiter filter
24
+ */
25
+
26
+#include "libavutil/avassert.h"
27
+#include "libavutil/channel_layout.h"
28
+#include "libavutil/common.h"
29
+#include "libavutil/opt.h"
30
+
31
+#include "audio.h"
32
+#include "avfilter.h"
33
+#include "formats.h"
34
+#include "internal.h"
35
+
36
+typedef struct AudioLimiterContext {
37
+    const AVClass *class;
38
+
39
+    double limit;
40
+    double attack;
41
+    double release;
42
+    double att;
43
+    int auto_release;
44
+    double asc;
45
+    int asc_c;
46
+    int asc_pos;
47
+    double asc_coeff;
48
+
49
+    double *buffer;
50
+    int buffer_size;
51
+    int pos;
52
+    int *nextpos;
53
+    double *nextdelta;
54
+
55
+    double delta;
56
+    int nextiter;
57
+    int nextlen;
58
+    int asc_changed;
59
+} AudioLimiterContext;
60
+
61
+#define OFFSET(x) offsetof(AudioLimiterContext, x)
62
+#define A AV_OPT_FLAG_AUDIO_PARAM
63
+#define F AV_OPT_FLAG_FILTERING_PARAM
64
+
65
+static const AVOption alimiter_options[] = {
66
+    { "limit",     "set limit",     OFFSET(limit),        AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.0625,    1, A|F },
67
+    { "attack",    "set attack",    OFFSET(attack),       AV_OPT_TYPE_DOUBLE, {.dbl=5},    0.1,   80, A|F },
68
+    { "release",   "set release",   OFFSET(release),      AV_OPT_TYPE_DOUBLE, {.dbl=50},     1, 8000, A|F },
69
+    { "asc",       "enable asc",    OFFSET(auto_release), AV_OPT_TYPE_BOOL,   {.i64=0},      0,    1, A|F },
70
+    { "asc_level", "set asc level", OFFSET(asc_coeff),    AV_OPT_TYPE_DOUBLE, {.dbl=0.5},    0,    1, A|F },
71
+    { NULL }
72
+};
73
+
74
+AVFILTER_DEFINE_CLASS(alimiter);
75
+
76
+static av_cold int init(AVFilterContext *ctx)
77
+{
78
+    AudioLimiterContext *s = ctx->priv;
79
+
80
+    s->attack   /= 1000.;
81
+    s->release  /= 1000.;
82
+    s->att       = 1.;
83
+    s->asc_pos   = -1;
84
+    s->asc_coeff = pow(0.5, s->asc_coeff - 0.5) * 2 * -1;
85
+
86
+    return 0;
87
+}
88
+
89
+static double get_rdelta(AudioLimiterContext *s, double release, int sample_rate,
90
+                         double peak, double limit, double patt, int asc)
91
+{
92
+    double rdelta = (1.0 - patt) / (sample_rate * release);
93
+
94
+    if (asc && s->auto_release && s->asc_c > 0) {
95
+        double a_att = limit / (s->asc_coeff * s->asc) * (double)s->asc_c;
96
+
97
+        if (a_att > patt) {
98
+            double delta = FFMAX((a_att - patt) / (sample_rate * release), rdelta / 10);
99
+
100
+            if (delta < rdelta)
101
+                rdelta = delta;
102
+        }
103
+    }
104
+
105
+    return rdelta;
106
+}
107
+
108
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
109
+{
110
+    AVFilterContext *ctx = inlink->dst;
111
+    AudioLimiterContext *s = ctx->priv;
112
+    AVFilterLink *outlink = ctx->outputs[0];
113
+    const double *src = (const double *)in->data[0];
114
+    const int channels = inlink->channels;
115
+    const int buffer_size = s->buffer_size;
116
+    double *dst, *buffer = s->buffer;
117
+    const double release = s->release;
118
+    const double limit = s->limit;
119
+    double *nextdelta = s->nextdelta;
120
+    int *nextpos = s->nextpos;
121
+    AVFrame *out;
122
+    double *buf;
123
+    int n, c, i;
124
+
125
+    if (av_frame_is_writable(in)) {
126
+        out = in;
127
+    } else {
128
+        out = ff_get_audio_buffer(inlink, in->nb_samples);
129
+        if (!out) {
130
+            av_frame_free(&in);
131
+            return AVERROR(ENOMEM);
132
+        }
133
+        av_frame_copy_props(out, in);
134
+    }
135
+    dst = (double *)out->data[0];
136
+
137
+    for (n = 0; n < in->nb_samples; n++) {
138
+        double peak = 0;
139
+
140
+        for (c = 0; c < channels; c++) {
141
+            double sample = src[c];
142
+
143
+            buffer[s->pos + c] = sample;
144
+            peak = FFMAX(peak, fabs(sample));
145
+        }
146
+
147
+        if (s->auto_release && peak > limit) {
148
+            s->asc += peak;
149
+            s->asc_c++;
150
+        }
151
+
152
+        if (peak > limit) {
153
+            double patt = FFMIN(limit / peak, 1.);
154
+            double rdelta = get_rdelta(s, release, inlink->sample_rate,
155
+                                       peak, limit, patt, 0);
156
+            double delta = (limit / peak - s->att) / buffer_size * channels;
157
+            int found = 0;
158
+
159
+            if (delta < s->delta) {
160
+                s->delta = delta;
161
+                nextpos[0] = s->pos;
162
+                nextpos[1] = -1;
163
+                nextdelta[0] = rdelta;
164
+                s->nextlen = 1;
165
+                s->nextiter= 0;
166
+            } else {
167
+                for (i = s->nextiter; i < s->nextiter + s->nextlen; i++) {
168
+                    int j = i % buffer_size;
169
+                    double ppeak, pdelta;
170
+
171
+                    ppeak = fabs(buffer[nextpos[j]]) > fabs(buffer[nextpos[j] + 1]) ?
172
+                            fabs(buffer[nextpos[j]]) : fabs(buffer[nextpos[j] + 1]);
173
+                    pdelta = (limit / peak - limit / ppeak) / (((buffer_size - nextpos[j] + s->pos) % buffer_size) / channels);
174
+                    if (pdelta < nextdelta[j]) {
175
+                        nextdelta[j] = pdelta;
176
+                        found = 1;
177
+                        break;
178
+                    }
179
+                }
180
+                if (found) {
181
+                    s->nextlen = i - s->nextiter + 1;
182
+                    nextpos[(s->nextiter + s->nextlen) % buffer_size] = s->pos;
183
+                    nextdelta[(s->nextiter + s->nextlen) % buffer_size] = rdelta;
184
+                    nextpos[(s->nextiter + s->nextlen + 1) % buffer_size] = -1;
185
+                    s->nextlen++;
186
+                }
187
+            }
188
+        }
189
+
190
+        buf = &s->buffer[(s->pos + channels) % buffer_size];
191
+        peak = 0;
192
+        for (c = 0; c < channels; c++) {
193
+            double sample = buf[c];
194
+
195
+            peak = FFMAX(peak, fabs(sample));
196
+        }
197
+
198
+        if (s->pos == s->asc_pos && !s->asc_changed)
199
+            s->asc_pos = -1;
200
+
201
+        if (s->auto_release && s->asc_pos == -1 && peak > limit) {
202
+            s->asc -= peak;
203
+            s->asc_c--;
204
+        }
205
+
206
+        s->att += s->delta;
207
+
208
+        for (c = 0; c < channels; c++)
209
+            dst[c] = buf[c] * s->att;
210
+
211
+        if ((s->pos + channels) % buffer_size == nextpos[s->nextiter]) {
212
+            if (s->auto_release) {
213
+                s->delta = get_rdelta(s, release, inlink->sample_rate,
214
+                                      peak, limit, s->att, 1);
215
+                if (s->nextlen > 1) {
216
+                    int pnextpos = nextpos[(s->nextiter + 1) % buffer_size];
217
+                    double ppeak = fabs(buffer[pnextpos]) > fabs(buffer[pnextpos + 1]) ?
218
+                                                            fabs(buffer[pnextpos]) :
219
+                                                            fabs(buffer[pnextpos + 1]);
220
+                    double pdelta = (limit / ppeak - s->att) /
221
+                                    (((buffer_size + pnextpos -
222
+                                    ((s->pos + channels) % buffer_size)) %
223
+                                    buffer_size) / channels);
224
+                    if (pdelta < s->delta)
225
+                        s->delta = pdelta;
226
+                }
227
+            } else {
228
+                s->delta = nextdelta[s->nextiter];
229
+                s->att = limit / peak;
230
+            }
231
+
232
+            s->nextlen -= 1;
233
+            nextpos[s->nextiter] = -1;
234
+            s->nextiter = (s->nextiter + 1) % buffer_size;
235
+        }
236
+
237
+        if (s->att > 1.) {
238
+            s->att = 1.;
239
+            s->delta = 0.;
240
+            s->nextiter = 0;
241
+            s->nextlen = 0;
242
+            nextpos[0] = -1;
243
+        }
244
+
245
+        if (s->att <= 0.) {
246
+            s->att = 0.0000000000001;
247
+            s->delta = (1.0 - s->att) / (inlink->sample_rate * release);
248
+        }
249
+
250
+        if (s->att != 1. && (1. - s->att) < 0.0000000000001)
251
+            s->att = 1.;
252
+
253
+        if (s->delta != 0. && fabs(s->delta) < 0.00000000000001)
254
+            s->delta = 0.;
255
+
256
+        for (c = 0; c < channels; c++)
257
+            dst[c] = av_clipd(dst[c], -limit, limit);
258
+
259
+        s->pos = (s->pos + channels) % buffer_size;
260
+        src += channels;
261
+        dst += channels;
262
+    }
263
+
264
+    if (in != out)
265
+        av_frame_free(&in);
266
+
267
+    return ff_filter_frame(outlink, out);
268
+}
269
+
270
+static int query_formats(AVFilterContext *ctx)
271
+{
272
+    AVFilterFormats *formats;
273
+    AVFilterChannelLayouts *layouts;
274
+    static const enum AVSampleFormat sample_fmts[] = {
275
+        AV_SAMPLE_FMT_DBL,
276
+        AV_SAMPLE_FMT_NONE
277
+    };
278
+    int ret;
279
+
280
+    layouts = ff_all_channel_counts();
281
+    if (!layouts)
282
+        return AVERROR(ENOMEM);
283
+    ret = ff_set_common_channel_layouts(ctx, layouts);
284
+    if (ret < 0)
285
+        return ret;
286
+
287
+    formats = ff_make_format_list(sample_fmts);
288
+    if (!formats)
289
+        return AVERROR(ENOMEM);
290
+    ret = ff_set_common_formats(ctx, formats);
291
+    if (ret < 0)
292
+        return ret;
293
+
294
+    formats = ff_all_samplerates();
295
+    if (!formats)
296
+        return AVERROR(ENOMEM);
297
+    return ff_set_common_samplerates(ctx, formats);
298
+}
299
+
300
+static int config_input(AVFilterLink *inlink)
301
+{
302
+    AVFilterContext *ctx = inlink->dst;
303
+    AudioLimiterContext *s = ctx->priv;
304
+    int obuffer_size;
305
+
306
+    obuffer_size = inlink->sample_rate * inlink->channels * 100 / 1000. + inlink->channels;
307
+    if (obuffer_size < inlink->channels)
308
+        return AVERROR(EINVAL);
309
+
310
+    s->buffer = av_calloc(obuffer_size, sizeof(*s->buffer));
311
+    s->nextdelta = av_calloc(obuffer_size, sizeof(*s->nextdelta));
312
+    s->nextpos = av_malloc_array(obuffer_size, sizeof(*s->nextpos));
313
+    if (!s->buffer || !s->nextdelta || !s->nextpos)
314
+        return AVERROR(ENOMEM);
315
+
316
+    memset(s->nextpos, -1, obuffer_size * sizeof(*s->nextpos));
317
+    s->buffer_size = inlink->sample_rate * s->attack * inlink->channels;
318
+    s->buffer_size -= s->buffer_size % inlink->channels;
319
+
320
+    return 0;
321
+}
322
+
323
+static av_cold void uninit(AVFilterContext *ctx)
324
+{
325
+    AudioLimiterContext *s = ctx->priv;
326
+
327
+    av_freep(&s->buffer);
328
+    av_freep(&s->nextdelta);
329
+    av_freep(&s->nextpos);
330
+}
331
+
332
+static const AVFilterPad alimiter_inputs[] = {
333
+    {
334
+        .name         = "main",
335
+        .type         = AVMEDIA_TYPE_AUDIO,
336
+        .filter_frame = filter_frame,
337
+        .config_props = config_input,
338
+    },
339
+    { NULL }
340
+};
341
+
342
+static const AVFilterPad alimiter_outputs[] = {
343
+    {
344
+        .name = "default",
345
+        .type = AVMEDIA_TYPE_AUDIO,
346
+    },
347
+    { NULL }
348
+};
349
+
350
+AVFilter ff_af_alimiter = {
351
+    .name           = "alimiter",
352
+    .description    = NULL_IF_CONFIG_SMALL("Lookahead limiter."),
353
+    .priv_size      = sizeof(AudioLimiterContext),
354
+    .priv_class     = &alimiter_class,
355
+    .init           = init,
356
+    .uninit         = uninit,
357
+    .query_formats  = query_formats,
358
+    .inputs         = alimiter_inputs,
359
+    .outputs        = alimiter_outputs,
360
+};
... ...
@@ -52,6 +52,7 @@ void avfilter_register_all(void)
52 52
     REGISTER_FILTER(AFADE,          afade,          af);
53 53
     REGISTER_FILTER(AFORMAT,        aformat,        af);
54 54
     REGISTER_FILTER(AINTERLEAVE,    ainterleave,    af);
55
+    REGISTER_FILTER(ALIMITER,       alimiter,       af);
55 56
     REGISTER_FILTER(ALLPASS,        allpass,        af);
56 57
     REGISTER_FILTER(AMERGE,         amerge,         af);
57 58
     REGISTER_FILTER(AMIX,           amix,           af);
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/version.h"
31 31
 
32 32
 #define LIBAVFILTER_VERSION_MAJOR   6
33
-#define LIBAVFILTER_VERSION_MINOR   2
33
+#define LIBAVFILTER_VERSION_MINOR   3
34 34
 #define LIBAVFILTER_VERSION_MICRO 100
35 35
 
36 36
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \