FFmpeg
af_alimiter.c
Go to the documentation of this file.
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 
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  double level_in;
44  double level_out;
47  double asc;
48  int asc_c;
49  int asc_pos;
50  double asc_coeff;
51 
52  double *buffer;
54  int pos;
55  int *nextpos;
56  double *nextdelta;
57 
58  double delta;
59  int nextiter;
60  int nextlen;
63 
64 #define OFFSET(x) offsetof(AudioLimiterContext, x)
65 #define AF AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM
66 
67 static const AVOption alimiter_options[] = {
68  { "level_in", "set input level", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=1},.015625, 64, AF },
69  { "level_out", "set output level", OFFSET(level_out), AV_OPT_TYPE_DOUBLE, {.dbl=1},.015625, 64, AF },
70  { "limit", "set limit", OFFSET(limit), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.0625, 1, AF },
71  { "attack", "set attack", OFFSET(attack), AV_OPT_TYPE_DOUBLE, {.dbl=5}, 0.1, 80, AF },
72  { "release", "set release", OFFSET(release), AV_OPT_TYPE_DOUBLE, {.dbl=50}, 1, 8000, AF },
73  { "asc", "enable asc", OFFSET(auto_release), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AF },
74  { "asc_level", "set asc level", OFFSET(asc_coeff), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 1, AF },
75  { "level", "auto level", OFFSET(auto_level), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, AF },
76  { NULL }
77 };
78 
79 AVFILTER_DEFINE_CLASS(alimiter);
80 
82 {
83  AudioLimiterContext *s = ctx->priv;
84 
85  s->attack /= 1000.;
86  s->release /= 1000.;
87  s->att = 1.;
88  s->asc_pos = -1;
89  s->asc_coeff = pow(0.5, s->asc_coeff - 0.5) * 2 * -1;
90 
91  return 0;
92 }
93 
94 static double get_rdelta(AudioLimiterContext *s, double release, int sample_rate,
95  double peak, double limit, double patt, int asc)
96 {
97  double rdelta = (1.0 - patt) / (sample_rate * release);
98 
99  if (asc && s->auto_release && s->asc_c > 0) {
100  double a_att = limit / (s->asc_coeff * s->asc) * (double)s->asc_c;
101 
102  if (a_att > patt) {
103  double delta = FFMAX((a_att - patt) / (sample_rate * release), rdelta / 10);
104 
105  if (delta < rdelta)
106  rdelta = delta;
107  }
108  }
109 
110  return rdelta;
111 }
112 
114 {
115  AVFilterContext *ctx = inlink->dst;
116  AudioLimiterContext *s = ctx->priv;
117  AVFilterLink *outlink = ctx->outputs[0];
118  const double *src = (const double *)in->data[0];
119  const int channels = inlink->channels;
120  const int buffer_size = s->buffer_size;
121  double *dst, *buffer = s->buffer;
122  const double release = s->release;
123  const double limit = s->limit;
124  double *nextdelta = s->nextdelta;
125  double level = s->auto_level ? 1 / limit : 1;
126  const double level_out = s->level_out;
127  const double level_in = s->level_in;
128  int *nextpos = s->nextpos;
129  AVFrame *out;
130  double *buf;
131  int n, c, i;
132 
133  if (av_frame_is_writable(in)) {
134  out = in;
135  } else {
136  out = ff_get_audio_buffer(outlink, in->nb_samples);
137  if (!out) {
138  av_frame_free(&in);
139  return AVERROR(ENOMEM);
140  }
142  }
143  dst = (double *)out->data[0];
144 
145  for (n = 0; n < in->nb_samples; n++) {
146  double peak = 0;
147 
148  for (c = 0; c < channels; c++) {
149  double sample = src[c] * level_in;
150 
151  buffer[s->pos + c] = sample;
152  peak = FFMAX(peak, fabs(sample));
153  }
154 
155  if (s->auto_release && peak > limit) {
156  s->asc += peak;
157  s->asc_c++;
158  }
159 
160  if (peak > limit) {
161  double patt = FFMIN(limit / peak, 1.);
162  double rdelta = get_rdelta(s, release, inlink->sample_rate,
163  peak, limit, patt, 0);
164  double delta = (limit / peak - s->att) / buffer_size * channels;
165  int found = 0;
166 
167  if (delta < s->delta) {
168  s->delta = delta;
169  nextpos[0] = s->pos;
170  nextpos[1] = -1;
171  nextdelta[0] = rdelta;
172  s->nextlen = 1;
173  s->nextiter= 0;
174  } else {
175  for (i = s->nextiter; i < s->nextiter + s->nextlen; i++) {
176  int j = i % buffer_size;
177  double ppeak, pdelta;
178 
179  ppeak = fabs(buffer[nextpos[j]]) > fabs(buffer[nextpos[j] + 1]) ?
180  fabs(buffer[nextpos[j]]) : fabs(buffer[nextpos[j] + 1]);
181  pdelta = (limit / peak - limit / ppeak) / (((buffer_size - nextpos[j] + s->pos) % buffer_size) / channels);
182  if (pdelta < nextdelta[j]) {
183  nextdelta[j] = pdelta;
184  found = 1;
185  break;
186  }
187  }
188  if (found) {
189  s->nextlen = i - s->nextiter + 1;
190  nextpos[(s->nextiter + s->nextlen) % buffer_size] = s->pos;
191  nextdelta[(s->nextiter + s->nextlen) % buffer_size] = rdelta;
192  nextpos[(s->nextiter + s->nextlen + 1) % buffer_size] = -1;
193  s->nextlen++;
194  }
195  }
196  }
197 
198  buf = &s->buffer[(s->pos + channels) % buffer_size];
199  peak = 0;
200  for (c = 0; c < channels; c++) {
201  double sample = buf[c];
202 
203  peak = FFMAX(peak, fabs(sample));
204  }
205 
206  if (s->pos == s->asc_pos && !s->asc_changed)
207  s->asc_pos = -1;
208 
209  if (s->auto_release && s->asc_pos == -1 && peak > limit) {
210  s->asc -= peak;
211  s->asc_c--;
212  }
213 
214  s->att += s->delta;
215 
216  for (c = 0; c < channels; c++)
217  dst[c] = buf[c] * s->att;
218 
219  if ((s->pos + channels) % buffer_size == nextpos[s->nextiter]) {
220  if (s->auto_release) {
221  s->delta = get_rdelta(s, release, inlink->sample_rate,
222  peak, limit, s->att, 1);
223  if (s->nextlen > 1) {
224  int pnextpos = nextpos[(s->nextiter + 1) % buffer_size];
225  double ppeak = fabs(buffer[pnextpos]) > fabs(buffer[pnextpos + 1]) ?
226  fabs(buffer[pnextpos]) :
227  fabs(buffer[pnextpos + 1]);
228  double pdelta = (limit / ppeak - s->att) /
229  (((buffer_size + pnextpos -
230  ((s->pos + channels) % buffer_size)) %
231  buffer_size) / channels);
232  if (pdelta < s->delta)
233  s->delta = pdelta;
234  }
235  } else {
236  s->delta = nextdelta[s->nextiter];
237  s->att = limit / peak;
238  }
239 
240  s->nextlen -= 1;
241  nextpos[s->nextiter] = -1;
242  s->nextiter = (s->nextiter + 1) % buffer_size;
243  }
244 
245  if (s->att > 1.) {
246  s->att = 1.;
247  s->delta = 0.;
248  s->nextiter = 0;
249  s->nextlen = 0;
250  nextpos[0] = -1;
251  }
252 
253  if (s->att <= 0.) {
254  s->att = 0.0000000000001;
255  s->delta = (1.0 - s->att) / (inlink->sample_rate * release);
256  }
257 
258  if (s->att != 1. && (1. - s->att) < 0.0000000000001)
259  s->att = 1.;
260 
261  if (s->delta != 0. && fabs(s->delta) < 0.00000000000001)
262  s->delta = 0.;
263 
264  for (c = 0; c < channels; c++)
265  dst[c] = av_clipd(dst[c], -limit, limit) * level * level_out;
266 
267  s->pos = (s->pos + channels) % buffer_size;
268  src += channels;
269  dst += channels;
270  }
271 
272  if (in != out)
273  av_frame_free(&in);
274 
275  return ff_filter_frame(outlink, out);
276 }
277 
279 {
280  AVFilterContext *ctx = inlink->dst;
281  AudioLimiterContext *s = ctx->priv;
282  int obuffer_size;
283 
284  obuffer_size = inlink->sample_rate * inlink->channels * 100 / 1000. + inlink->channels;
285  if (obuffer_size < inlink->channels)
286  return AVERROR(EINVAL);
287 
288  s->buffer = av_calloc(obuffer_size, sizeof(*s->buffer));
289  s->nextdelta = av_calloc(obuffer_size, sizeof(*s->nextdelta));
290  s->nextpos = av_malloc_array(obuffer_size, sizeof(*s->nextpos));
291  if (!s->buffer || !s->nextdelta || !s->nextpos)
292  return AVERROR(ENOMEM);
293 
294  memset(s->nextpos, -1, obuffer_size * sizeof(*s->nextpos));
295  s->buffer_size = inlink->sample_rate * s->attack * inlink->channels;
296  s->buffer_size -= s->buffer_size % inlink->channels;
297 
298  if (s->buffer_size <= 0) {
299  av_log(ctx, AV_LOG_ERROR, "Attack is too small.\n");
300  return AVERROR(EINVAL);
301  }
302 
303  return 0;
304 }
305 
307 {
308  AudioLimiterContext *s = ctx->priv;
309 
310  av_freep(&s->buffer);
311  av_freep(&s->nextdelta);
312  av_freep(&s->nextpos);
313 }
314 
315 static const AVFilterPad alimiter_inputs[] = {
316  {
317  .name = "main",
318  .type = AVMEDIA_TYPE_AUDIO,
319  .filter_frame = filter_frame,
320  .config_props = config_input,
321  },
322 };
323 
324 static const AVFilterPad alimiter_outputs[] = {
325  {
326  .name = "default",
327  .type = AVMEDIA_TYPE_AUDIO,
328  },
329 };
330 
332  .name = "alimiter",
333  .description = NULL_IF_CONFIG_SMALL("Audio lookahead limiter."),
334  .priv_size = sizeof(AudioLimiterContext),
335  .priv_class = &alimiter_class,
336  .init = init,
337  .uninit = uninit,
341  .process_command = ff_filter_process_command,
343 };
ff_get_audio_buffer
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:88
alimiter_options
static const AVOption alimiter_options[]
Definition: af_alimiter.c:67
level
uint8_t level
Definition: svq3.c:204
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
out
FILE * out
Definition: movenc.c:54
init
static av_cold int init(AVFilterContext *ctx)
Definition: af_alimiter.c:81
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1018
AudioLimiterContext::asc_c
int asc_c
Definition: af_alimiter.c:48
AudioLimiterContext::attack
double attack
Definition: af_alimiter.c:40
FILTER_SINGLE_SAMPLEFMT
#define FILTER_SINGLE_SAMPLEFMT(sample_fmt_)
Definition: internal.h:184
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:109
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:317
alimiter_inputs
static const AVFilterPad alimiter_inputs[]
Definition: af_alimiter.c:315
AVOption
AVOption.
Definition: opt.h:247
alimiter_outputs
static const AVFilterPad alimiter_outputs[]
Definition: af_alimiter.c:324
AudioLimiterContext::auto_level
int auto_level
Definition: af_alimiter.c:46
ff_af_alimiter
const AVFilter ff_af_alimiter
Definition: af_alimiter.c:331
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:169
AudioLimiterContext::pos
int pos
Definition: af_alimiter.c:54
sample_rate
sample_rate
Definition: ffmpeg_filter.c:153
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:338
formats.h
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:50
AudioLimiterContext::asc_coeff
double asc_coeff
Definition: af_alimiter.c:50
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
s
#define s(width, name)
Definition: cbs_vp9.c:257
AV_OPT_TYPE_DOUBLE
@ AV_OPT_TYPE_DOUBLE
Definition: opt.h:226
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_alimiter.c:306
ctx
AVFormatContext * ctx
Definition: movenc.c:48
channels
channels
Definition: aptx.h:33
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:191
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: af_alimiter.c:113
if
if(ret)
Definition: filter_design.txt:179
AudioLimiterContext::level_in
double level_in
Definition: af_alimiter.c:43
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
fabs
static __device__ float fabs(float a)
Definition: cuda_runtime.h:182
NULL
#define NULL
Definition: coverity.c:32
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:537
AudioLimiterContext
Definition: af_alimiter.c:36
src
#define src
Definition: vp8dsp.c:255
AudioLimiterContext::nextlen
int nextlen
Definition: af_alimiter.c:60
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
for
for(j=16;j >0;--j)
Definition: h264pred_template.c:469
AudioLimiterContext::asc
double asc
Definition: af_alimiter.c:47
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
av_clipd
#define av_clipd
Definition: common.h:147
AudioLimiterContext::buffer
double * buffer
Definition: af_alimiter.c:52
sample
#define sample
Definition: flacdsp_template.c:44
av_frame_is_writable
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition: frame.c:473
AF
#define AF
Definition: af_alimiter.c:65
ff_filter_process_command
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options.
Definition: avfilter.c:882
AudioLimiterContext::release
double release
Definition: af_alimiter.c:41
internal.h
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
Definition: avfilter.h:146
AudioLimiterContext::delta
double delta
Definition: af_alimiter.c:58
AVFrame::nb_samples
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:397
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
AudioLimiterContext::buffer_size
int buffer_size
Definition: af_alimiter.c:53
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:32
common.h
delta
float delta
Definition: vorbis_enc_data.h:430
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AudioLimiterContext::nextpos
int * nextpos
Definition: af_alimiter.c:55
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:56
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:271
limit
static double limit(double x)
Definition: vf_pseudocolor.c:128
AVFilter
Filter definition.
Definition: avfilter.h:165
AudioLimiterContext::nextiter
int nextiter
Definition: af_alimiter.c:59
OFFSET
#define OFFSET(x)
Definition: af_alimiter.c:64
channel_layout.h
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
patt
static const int8_t patt[4]
Definition: vf_noise.c:67
avfilter.h
AudioLimiterContext::asc_pos
int asc_pos
Definition: af_alimiter.c:49
AudioLimiterContext::level_out
double level_out
Definition: af_alimiter.c:44
get_rdelta
static double get_rdelta(AudioLimiterContext *s, double release, int sample_rate, double peak, double limit, double patt, int asc)
Definition: af_alimiter.c:94
AVFilterContext
An instance of a filter.
Definition: avfilter.h:402
AudioLimiterContext::auto_release
int auto_release
Definition: af_alimiter.c:45
audio.h
AudioLimiterContext::asc_changed
int asc_changed
Definition: af_alimiter.c:61
AudioLimiterContext::att
double att
Definition: af_alimiter.c:42
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(alimiter)
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:241
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:192
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
AudioLimiterContext::limit
double limit
Definition: af_alimiter.c:39
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
config_input
static int config_input(AVFilterLink *inlink)
Definition: af_alimiter.c:278
AV_SAMPLE_FMT_DBL
@ AV_SAMPLE_FMT_DBL
double
Definition: samplefmt.h:64
AudioLimiterContext::nextdelta
double * nextdelta
Definition: af_alimiter.c:56