1 |
|
|
/* |
2 |
|
|
* Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others |
3 |
|
|
* Copyright (c) 2015 Paul B Mahol |
4 |
|
|
* |
5 |
|
|
* This file is part of FFmpeg. |
6 |
|
|
* |
7 |
|
|
* FFmpeg is free software; you can redistribute it and/or |
8 |
|
|
* modify it under the terms of the GNU Lesser General Public |
9 |
|
|
* License as published by the Free Software Foundation; either |
10 |
|
|
* version 2.1 of the License, or (at your option) any later version. |
11 |
|
|
* |
12 |
|
|
* FFmpeg is distributed in the hope that it will be useful, |
13 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 |
|
|
* Lesser General Public License for more details. |
16 |
|
|
* |
17 |
|
|
* You should have received a copy of the GNU Lesser General Public |
18 |
|
|
* License along with FFmpeg; if not, write to the Free Software |
19 |
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 |
|
|
*/ |
21 |
|
|
|
22 |
|
|
/** |
23 |
|
|
* @file |
24 |
|
|
* Lookahead limiter filter |
25 |
|
|
*/ |
26 |
|
|
|
27 |
|
|
#include "libavutil/avassert.h" |
28 |
|
|
#include "libavutil/channel_layout.h" |
29 |
|
|
#include "libavutil/common.h" |
30 |
|
|
#include "libavutil/opt.h" |
31 |
|
|
|
32 |
|
|
#include "audio.h" |
33 |
|
|
#include "avfilter.h" |
34 |
|
|
#include "formats.h" |
35 |
|
|
#include "internal.h" |
36 |
|
|
|
37 |
|
|
typedef struct AudioLimiterContext { |
38 |
|
|
const AVClass *class; |
39 |
|
|
|
40 |
|
|
double limit; |
41 |
|
|
double attack; |
42 |
|
|
double release; |
43 |
|
|
double att; |
44 |
|
|
double level_in; |
45 |
|
|
double level_out; |
46 |
|
|
int auto_release; |
47 |
|
|
int auto_level; |
48 |
|
|
double asc; |
49 |
|
|
int asc_c; |
50 |
|
|
int asc_pos; |
51 |
|
|
double asc_coeff; |
52 |
|
|
|
53 |
|
|
double *buffer; |
54 |
|
|
int buffer_size; |
55 |
|
|
int pos; |
56 |
|
|
int *nextpos; |
57 |
|
|
double *nextdelta; |
58 |
|
|
|
59 |
|
|
double delta; |
60 |
|
|
int nextiter; |
61 |
|
|
int nextlen; |
62 |
|
|
int asc_changed; |
63 |
|
|
} AudioLimiterContext; |
64 |
|
|
|
65 |
|
|
#define OFFSET(x) offsetof(AudioLimiterContext, x) |
66 |
|
|
#define A AV_OPT_FLAG_AUDIO_PARAM |
67 |
|
|
#define F AV_OPT_FLAG_FILTERING_PARAM |
68 |
|
|
|
69 |
|
|
static const AVOption alimiter_options[] = { |
70 |
|
|
{ "level_in", "set input level", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=1},.015625, 64, A|F }, |
71 |
|
|
{ "level_out", "set output level", OFFSET(level_out), AV_OPT_TYPE_DOUBLE, {.dbl=1},.015625, 64, A|F }, |
72 |
|
|
{ "limit", "set limit", OFFSET(limit), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.0625, 1, A|F }, |
73 |
|
|
{ "attack", "set attack", OFFSET(attack), AV_OPT_TYPE_DOUBLE, {.dbl=5}, 0.1, 80, A|F }, |
74 |
|
|
{ "release", "set release", OFFSET(release), AV_OPT_TYPE_DOUBLE, {.dbl=50}, 1, 8000, A|F }, |
75 |
|
|
{ "asc", "enable asc", OFFSET(auto_release), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, A|F }, |
76 |
|
|
{ "asc_level", "set asc level", OFFSET(asc_coeff), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 1, A|F }, |
77 |
|
|
{ "level", "auto level", OFFSET(auto_level), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, A|F }, |
78 |
|
|
{ NULL } |
79 |
|
|
}; |
80 |
|
|
|
81 |
|
|
AVFILTER_DEFINE_CLASS(alimiter); |
82 |
|
|
|
83 |
|
1 |
static av_cold int init(AVFilterContext *ctx) |
84 |
|
|
{ |
85 |
|
1 |
AudioLimiterContext *s = ctx->priv; |
86 |
|
|
|
87 |
|
1 |
s->attack /= 1000.; |
88 |
|
1 |
s->release /= 1000.; |
89 |
|
1 |
s->att = 1.; |
90 |
|
1 |
s->asc_pos = -1; |
91 |
|
1 |
s->asc_coeff = pow(0.5, s->asc_coeff - 0.5) * 2 * -1; |
92 |
|
|
|
93 |
|
1 |
return 0; |
94 |
|
|
} |
95 |
|
|
|
96 |
|
138816 |
static double get_rdelta(AudioLimiterContext *s, double release, int sample_rate, |
97 |
|
|
double peak, double limit, double patt, int asc) |
98 |
|
|
{ |
99 |
|
138816 |
double rdelta = (1.0 - patt) / (sample_rate * release); |
100 |
|
|
|
101 |
✗✓✗✗ ✗✗ |
138816 |
if (asc && s->auto_release && s->asc_c > 0) { |
102 |
|
|
double a_att = limit / (s->asc_coeff * s->asc) * (double)s->asc_c; |
103 |
|
|
|
104 |
|
|
if (a_att > patt) { |
105 |
|
|
double delta = FFMAX((a_att - patt) / (sample_rate * release), rdelta / 10); |
106 |
|
|
|
107 |
|
|
if (delta < rdelta) |
108 |
|
|
rdelta = delta; |
109 |
|
|
} |
110 |
|
|
} |
111 |
|
|
|
112 |
|
138816 |
return rdelta; |
113 |
|
|
} |
114 |
|
|
|
115 |
|
259 |
static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
116 |
|
|
{ |
117 |
|
259 |
AVFilterContext *ctx = inlink->dst; |
118 |
|
259 |
AudioLimiterContext *s = ctx->priv; |
119 |
|
259 |
AVFilterLink *outlink = ctx->outputs[0]; |
120 |
|
259 |
const double *src = (const double *)in->data[0]; |
121 |
|
259 |
const int channels = inlink->channels; |
122 |
|
259 |
const int buffer_size = s->buffer_size; |
123 |
|
259 |
double *dst, *buffer = s->buffer; |
124 |
|
259 |
const double release = s->release; |
125 |
|
259 |
const double limit = s->limit; |
126 |
|
259 |
double *nextdelta = s->nextdelta; |
127 |
✓✗ |
259 |
double level = s->auto_level ? 1 / limit : 1; |
128 |
|
259 |
const double level_out = s->level_out; |
129 |
|
259 |
const double level_in = s->level_in; |
130 |
|
259 |
int *nextpos = s->nextpos; |
131 |
|
|
AVFrame *out; |
132 |
|
|
double *buf; |
133 |
|
|
int n, c, i; |
134 |
|
|
|
135 |
✓✗ |
259 |
if (av_frame_is_writable(in)) { |
136 |
|
259 |
out = in; |
137 |
|
|
} else { |
138 |
|
|
out = ff_get_audio_buffer(outlink, in->nb_samples); |
139 |
|
|
if (!out) { |
140 |
|
|
av_frame_free(&in); |
141 |
|
|
return AVERROR(ENOMEM); |
142 |
|
|
} |
143 |
|
|
av_frame_copy_props(out, in); |
144 |
|
|
} |
145 |
|
259 |
dst = (double *)out->data[0]; |
146 |
|
|
|
147 |
✓✓ |
264859 |
for (n = 0; n < in->nb_samples; n++) { |
148 |
|
264600 |
double peak = 0; |
149 |
|
|
|
150 |
✓✓ |
793800 |
for (c = 0; c < channels; c++) { |
151 |
|
529200 |
double sample = src[c] * level_in; |
152 |
|
|
|
153 |
|
529200 |
buffer[s->pos + c] = sample; |
154 |
✓✓ |
529200 |
peak = FFMAX(peak, fabs(sample)); |
155 |
|
|
} |
156 |
|
|
|
157 |
✗✓✗✗
|
264600 |
if (s->auto_release && peak > limit) { |
158 |
|
|
s->asc += peak; |
159 |
|
|
s->asc_c++; |
160 |
|
|
} |
161 |
|
|
|
162 |
✓✓ |
264600 |
if (peak > limit) { |
163 |
✗✓ |
138816 |
double patt = FFMIN(limit / peak, 1.); |
164 |
|
138816 |
double rdelta = get_rdelta(s, release, inlink->sample_rate, |
165 |
|
|
peak, limit, patt, 0); |
166 |
|
138816 |
double delta = (limit / peak - s->att) / buffer_size * channels; |
167 |
|
138816 |
int found = 0; |
168 |
|
|
|
169 |
✓✓ |
138816 |
if (delta < s->delta) { |
170 |
|
1669 |
s->delta = delta; |
171 |
|
1669 |
nextpos[0] = s->pos; |
172 |
|
1669 |
nextpos[1] = -1; |
173 |
|
1669 |
nextdelta[0] = rdelta; |
174 |
|
1669 |
s->nextlen = 1; |
175 |
|
1669 |
s->nextiter= 0; |
176 |
|
|
} else { |
177 |
✓✓ |
564375 |
for (i = s->nextiter; i < s->nextiter + s->nextlen; i++) { |
178 |
|
439864 |
int j = i % buffer_size; |
179 |
|
|
double ppeak, pdelta; |
180 |
|
|
|
181 |
|
879728 |
ppeak = fabs(buffer[nextpos[j]]) > fabs(buffer[nextpos[j] + 1]) ? |
182 |
✓✓ |
439864 |
fabs(buffer[nextpos[j]]) : fabs(buffer[nextpos[j] + 1]); |
183 |
|
439864 |
pdelta = (limit / peak - limit / ppeak) / (((buffer_size - nextpos[j] + s->pos) % buffer_size) / channels); |
184 |
✓✓ |
439864 |
if (pdelta < nextdelta[j]) { |
185 |
|
12636 |
nextdelta[j] = pdelta; |
186 |
|
12636 |
found = 1; |
187 |
|
12636 |
break; |
188 |
|
|
} |
189 |
|
|
} |
190 |
✓✓ |
137147 |
if (found) { |
191 |
|
12636 |
s->nextlen = i - s->nextiter + 1; |
192 |
|
12636 |
nextpos[(s->nextiter + s->nextlen) % buffer_size] = s->pos; |
193 |
|
12636 |
nextdelta[(s->nextiter + s->nextlen) % buffer_size] = rdelta; |
194 |
|
12636 |
nextpos[(s->nextiter + s->nextlen + 1) % buffer_size] = -1; |
195 |
|
12636 |
s->nextlen++; |
196 |
|
|
} |
197 |
|
|
} |
198 |
|
|
} |
199 |
|
|
|
200 |
|
264600 |
buf = &s->buffer[(s->pos + channels) % buffer_size]; |
201 |
|
264600 |
peak = 0; |
202 |
✓✓ |
793800 |
for (c = 0; c < channels; c++) { |
203 |
|
529200 |
double sample = buf[c]; |
204 |
|
|
|
205 |
✓✓ |
529200 |
peak = FFMAX(peak, fabs(sample)); |
206 |
|
|
} |
207 |
|
|
|
208 |
✗✓✗✗
|
264600 |
if (s->pos == s->asc_pos && !s->asc_changed) |
209 |
|
|
s->asc_pos = -1; |
210 |
|
|
|
211 |
✗✓✗✗ ✗✗ |
264600 |
if (s->auto_release && s->asc_pos == -1 && peak > limit) { |
212 |
|
|
s->asc -= peak; |
213 |
|
|
s->asc_c--; |
214 |
|
|
} |
215 |
|
|
|
216 |
|
264600 |
s->att += s->delta; |
217 |
|
|
|
218 |
✓✓ |
793800 |
for (c = 0; c < channels; c++) |
219 |
|
529200 |
dst[c] = buf[c] * s->att; |
220 |
|
|
|
221 |
✓✓ |
264600 |
if ((s->pos + channels) % buffer_size == nextpos[s->nextiter]) { |
222 |
✗✓ |
2019 |
if (s->auto_release) { |
223 |
|
|
s->delta = get_rdelta(s, release, inlink->sample_rate, |
224 |
|
|
peak, limit, s->att, 1); |
225 |
|
|
if (s->nextlen > 1) { |
226 |
|
|
int pnextpos = nextpos[(s->nextiter + 1) % buffer_size]; |
227 |
|
|
double ppeak = fabs(buffer[pnextpos]) > fabs(buffer[pnextpos + 1]) ? |
228 |
|
|
fabs(buffer[pnextpos]) : |
229 |
|
|
fabs(buffer[pnextpos + 1]); |
230 |
|
|
double pdelta = (limit / ppeak - s->att) / |
231 |
|
|
(((buffer_size + pnextpos - |
232 |
|
|
((s->pos + channels) % buffer_size)) % |
233 |
|
|
buffer_size) / channels); |
234 |
|
|
if (pdelta < s->delta) |
235 |
|
|
s->delta = pdelta; |
236 |
|
|
} |
237 |
|
|
} else { |
238 |
|
2019 |
s->delta = nextdelta[s->nextiter]; |
239 |
|
2019 |
s->att = limit / peak; |
240 |
|
|
} |
241 |
|
|
|
242 |
|
2019 |
s->nextlen -= 1; |
243 |
|
2019 |
nextpos[s->nextiter] = -1; |
244 |
|
2019 |
s->nextiter = (s->nextiter + 1) % buffer_size; |
245 |
|
|
} |
246 |
|
|
|
247 |
✓✓ |
264600 |
if (s->att > 1.) { |
248 |
|
11 |
s->att = 1.; |
249 |
|
11 |
s->delta = 0.; |
250 |
|
11 |
s->nextiter = 0; |
251 |
|
11 |
s->nextlen = 0; |
252 |
|
11 |
nextpos[0] = -1; |
253 |
|
|
} |
254 |
|
|
|
255 |
✗✓ |
264600 |
if (s->att <= 0.) { |
256 |
|
|
s->att = 0.0000000000001; |
257 |
|
|
s->delta = (1.0 - s->att) / (inlink->sample_rate * release); |
258 |
|
|
} |
259 |
|
|
|
260 |
✓✓✓✓
|
264600 |
if (s->att != 1. && (1. - s->att) < 0.0000000000001) |
261 |
|
5 |
s->att = 1.; |
262 |
|
|
|
263 |
✓✓✗✓
|
264600 |
if (s->delta != 0. && fabs(s->delta) < 0.00000000000001) |
264 |
|
|
s->delta = 0.; |
265 |
|
|
|
266 |
✓✓ |
793800 |
for (c = 0; c < channels; c++) |
267 |
|
529200 |
dst[c] = av_clipd(dst[c], -limit, limit) * level * level_out; |
268 |
|
|
|
269 |
|
264600 |
s->pos = (s->pos + channels) % buffer_size; |
270 |
|
264600 |
src += channels; |
271 |
|
264600 |
dst += channels; |
272 |
|
|
} |
273 |
|
|
|
274 |
✗✓ |
259 |
if (in != out) |
275 |
|
|
av_frame_free(&in); |
276 |
|
|
|
277 |
|
259 |
return ff_filter_frame(outlink, out); |
278 |
|
|
} |
279 |
|
|
|
280 |
|
1 |
static int query_formats(AVFilterContext *ctx) |
281 |
|
|
{ |
282 |
|
|
AVFilterFormats *formats; |
283 |
|
|
AVFilterChannelLayouts *layouts; |
284 |
|
|
static const enum AVSampleFormat sample_fmts[] = { |
285 |
|
|
AV_SAMPLE_FMT_DBL, |
286 |
|
|
AV_SAMPLE_FMT_NONE |
287 |
|
|
}; |
288 |
|
|
int ret; |
289 |
|
|
|
290 |
|
1 |
layouts = ff_all_channel_counts(); |
291 |
✗✓ |
1 |
if (!layouts) |
292 |
|
|
return AVERROR(ENOMEM); |
293 |
|
1 |
ret = ff_set_common_channel_layouts(ctx, layouts); |
294 |
✗✓ |
1 |
if (ret < 0) |
295 |
|
|
return ret; |
296 |
|
|
|
297 |
|
1 |
formats = ff_make_format_list(sample_fmts); |
298 |
✗✓ |
1 |
if (!formats) |
299 |
|
|
return AVERROR(ENOMEM); |
300 |
|
1 |
ret = ff_set_common_formats(ctx, formats); |
301 |
✗✓ |
1 |
if (ret < 0) |
302 |
|
|
return ret; |
303 |
|
|
|
304 |
|
1 |
formats = ff_all_samplerates(); |
305 |
✗✓ |
1 |
if (!formats) |
306 |
|
|
return AVERROR(ENOMEM); |
307 |
|
1 |
return ff_set_common_samplerates(ctx, formats); |
308 |
|
|
} |
309 |
|
|
|
310 |
|
1 |
static int config_input(AVFilterLink *inlink) |
311 |
|
|
{ |
312 |
|
1 |
AVFilterContext *ctx = inlink->dst; |
313 |
|
1 |
AudioLimiterContext *s = ctx->priv; |
314 |
|
|
int obuffer_size; |
315 |
|
|
|
316 |
|
1 |
obuffer_size = inlink->sample_rate * inlink->channels * 100 / 1000. + inlink->channels; |
317 |
✗✓ |
1 |
if (obuffer_size < inlink->channels) |
318 |
|
|
return AVERROR(EINVAL); |
319 |
|
|
|
320 |
|
1 |
s->buffer = av_calloc(obuffer_size, sizeof(*s->buffer)); |
321 |
|
1 |
s->nextdelta = av_calloc(obuffer_size, sizeof(*s->nextdelta)); |
322 |
|
1 |
s->nextpos = av_malloc_array(obuffer_size, sizeof(*s->nextpos)); |
323 |
✓✗✓✗ ✗✓ |
1 |
if (!s->buffer || !s->nextdelta || !s->nextpos) |
324 |
|
|
return AVERROR(ENOMEM); |
325 |
|
|
|
326 |
|
1 |
memset(s->nextpos, -1, obuffer_size * sizeof(*s->nextpos)); |
327 |
|
1 |
s->buffer_size = inlink->sample_rate * s->attack * inlink->channels; |
328 |
|
1 |
s->buffer_size -= s->buffer_size % inlink->channels; |
329 |
|
|
|
330 |
✗✓ |
1 |
if (s->buffer_size <= 0) { |
331 |
|
|
av_log(ctx, AV_LOG_ERROR, "Attack is too small.\n"); |
332 |
|
|
return AVERROR(EINVAL); |
333 |
|
|
} |
334 |
|
|
|
335 |
|
1 |
return 0; |
336 |
|
|
} |
337 |
|
|
|
338 |
|
1 |
static av_cold void uninit(AVFilterContext *ctx) |
339 |
|
|
{ |
340 |
|
1 |
AudioLimiterContext *s = ctx->priv; |
341 |
|
|
|
342 |
|
1 |
av_freep(&s->buffer); |
343 |
|
1 |
av_freep(&s->nextdelta); |
344 |
|
1 |
av_freep(&s->nextpos); |
345 |
|
1 |
} |
346 |
|
|
|
347 |
|
|
static const AVFilterPad alimiter_inputs[] = { |
348 |
|
|
{ |
349 |
|
|
.name = "main", |
350 |
|
|
.type = AVMEDIA_TYPE_AUDIO, |
351 |
|
|
.filter_frame = filter_frame, |
352 |
|
|
.config_props = config_input, |
353 |
|
|
}, |
354 |
|
|
{ NULL } |
355 |
|
|
}; |
356 |
|
|
|
357 |
|
|
static const AVFilterPad alimiter_outputs[] = { |
358 |
|
|
{ |
359 |
|
|
.name = "default", |
360 |
|
|
.type = AVMEDIA_TYPE_AUDIO, |
361 |
|
|
}, |
362 |
|
|
{ NULL } |
363 |
|
|
}; |
364 |
|
|
|
365 |
|
|
AVFilter ff_af_alimiter = { |
366 |
|
|
.name = "alimiter", |
367 |
|
|
.description = NULL_IF_CONFIG_SMALL("Audio lookahead limiter."), |
368 |
|
|
.priv_size = sizeof(AudioLimiterContext), |
369 |
|
|
.priv_class = &alimiter_class, |
370 |
|
|
.init = init, |
371 |
|
|
.uninit = uninit, |
372 |
|
|
.query_formats = query_formats, |
373 |
|
|
.inputs = alimiter_inputs, |
374 |
|
|
.outputs = alimiter_outputs, |
375 |
|
|
}; |