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 A AV_OPT_FLAG_AUDIO_PARAM
66 #define F AV_OPT_FLAG_FILTERING_PARAM
67 
68 static const AVOption alimiter_options[] = {
69  { "level_in", "set input level", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=1},.015625, 64, A|F },
70  { "level_out", "set output level", OFFSET(level_out), AV_OPT_TYPE_DOUBLE, {.dbl=1},.015625, 64, A|F },
71  { "limit", "set limit", OFFSET(limit), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.0625, 1, A|F },
72  { "attack", "set attack", OFFSET(attack), AV_OPT_TYPE_DOUBLE, {.dbl=5}, 0.1, 80, A|F },
73  { "release", "set release", OFFSET(release), AV_OPT_TYPE_DOUBLE, {.dbl=50}, 1, 8000, A|F },
74  { "asc", "enable asc", OFFSET(auto_release), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, A|F },
75  { "asc_level", "set asc level", OFFSET(asc_coeff), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 1, A|F },
76  { "level", "auto level", OFFSET(auto_level), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, A|F },
77  { NULL }
78 };
79 
80 AVFILTER_DEFINE_CLASS(alimiter);
81 
83 {
84  AudioLimiterContext *s = ctx->priv;
85 
86  s->attack /= 1000.;
87  s->release /= 1000.;
88  s->att = 1.;
89  s->asc_pos = -1;
90  s->asc_coeff = pow(0.5, s->asc_coeff - 0.5) * 2 * -1;
91 
92  return 0;
93 }
94 
95 static double get_rdelta(AudioLimiterContext *s, double release, int sample_rate,
96  double peak, double limit, double patt, int asc)
97 {
98  double rdelta = (1.0 - patt) / (sample_rate * release);
99 
100  if (asc && s->auto_release && s->asc_c > 0) {
101  double a_att = limit / (s->asc_coeff * s->asc) * (double)s->asc_c;
102 
103  if (a_att > patt) {
104  double delta = FFMAX((a_att - patt) / (sample_rate * release), rdelta / 10);
105 
106  if (delta < rdelta)
107  rdelta = delta;
108  }
109  }
110 
111  return rdelta;
112 }
113 
115 {
116  AVFilterContext *ctx = inlink->dst;
117  AudioLimiterContext *s = ctx->priv;
118  AVFilterLink *outlink = ctx->outputs[0];
119  const double *src = (const double *)in->data[0];
120  const int channels = inlink->channels;
121  const int buffer_size = s->buffer_size;
122  double *dst, *buffer = s->buffer;
123  const double release = s->release;
124  const double limit = s->limit;
125  double *nextdelta = s->nextdelta;
126  double level = s->auto_level ? 1 / limit : 1;
127  const double level_out = s->level_out;
128  const double level_in = s->level_in;
129  int *nextpos = s->nextpos;
130  AVFrame *out;
131  double *buf;
132  int n, c, i;
133 
134  if (av_frame_is_writable(in)) {
135  out = in;
136  } else {
137  out = ff_get_audio_buffer(outlink, in->nb_samples);
138  if (!out) {
139  av_frame_free(&in);
140  return AVERROR(ENOMEM);
141  }
143  }
144  dst = (double *)out->data[0];
145 
146  for (n = 0; n < in->nb_samples; n++) {
147  double peak = 0;
148 
149  for (c = 0; c < channels; c++) {
150  double sample = src[c] * level_in;
151 
152  buffer[s->pos + c] = sample;
153  peak = FFMAX(peak, fabs(sample));
154  }
155 
156  if (s->auto_release && peak > limit) {
157  s->asc += peak;
158  s->asc_c++;
159  }
160 
161  if (peak > limit) {
162  double patt = FFMIN(limit / peak, 1.);
163  double rdelta = get_rdelta(s, release, inlink->sample_rate,
164  peak, limit, patt, 0);
165  double delta = (limit / peak - s->att) / buffer_size * channels;
166  int found = 0;
167 
168  if (delta < s->delta) {
169  s->delta = delta;
170  nextpos[0] = s->pos;
171  nextpos[1] = -1;
172  nextdelta[0] = rdelta;
173  s->nextlen = 1;
174  s->nextiter= 0;
175  } else {
176  for (i = s->nextiter; i < s->nextiter + s->nextlen; i++) {
177  int j = i % buffer_size;
178  double ppeak, pdelta;
179 
180  ppeak = fabs(buffer[nextpos[j]]) > fabs(buffer[nextpos[j] + 1]) ?
181  fabs(buffer[nextpos[j]]) : fabs(buffer[nextpos[j] + 1]);
182  pdelta = (limit / peak - limit / ppeak) / (((buffer_size - nextpos[j] + s->pos) % buffer_size) / channels);
183  if (pdelta < nextdelta[j]) {
184  nextdelta[j] = pdelta;
185  found = 1;
186  break;
187  }
188  }
189  if (found) {
190  s->nextlen = i - s->nextiter + 1;
191  nextpos[(s->nextiter + s->nextlen) % buffer_size] = s->pos;
192  nextdelta[(s->nextiter + s->nextlen) % buffer_size] = rdelta;
193  nextpos[(s->nextiter + s->nextlen + 1) % buffer_size] = -1;
194  s->nextlen++;
195  }
196  }
197  }
198 
199  buf = &s->buffer[(s->pos + channels) % buffer_size];
200  peak = 0;
201  for (c = 0; c < channels; c++) {
202  double sample = buf[c];
203 
204  peak = FFMAX(peak, fabs(sample));
205  }
206 
207  if (s->pos == s->asc_pos && !s->asc_changed)
208  s->asc_pos = -1;
209 
210  if (s->auto_release && s->asc_pos == -1 && peak > limit) {
211  s->asc -= peak;
212  s->asc_c--;
213  }
214 
215  s->att += s->delta;
216 
217  for (c = 0; c < channels; c++)
218  dst[c] = buf[c] * s->att;
219 
220  if ((s->pos + channels) % buffer_size == nextpos[s->nextiter]) {
221  if (s->auto_release) {
222  s->delta = get_rdelta(s, release, inlink->sample_rate,
223  peak, limit, s->att, 1);
224  if (s->nextlen > 1) {
225  int pnextpos = nextpos[(s->nextiter + 1) % buffer_size];
226  double ppeak = fabs(buffer[pnextpos]) > fabs(buffer[pnextpos + 1]) ?
227  fabs(buffer[pnextpos]) :
228  fabs(buffer[pnextpos + 1]);
229  double pdelta = (limit / ppeak - s->att) /
230  (((buffer_size + pnextpos -
231  ((s->pos + channels) % buffer_size)) %
232  buffer_size) / channels);
233  if (pdelta < s->delta)
234  s->delta = pdelta;
235  }
236  } else {
237  s->delta = nextdelta[s->nextiter];
238  s->att = limit / peak;
239  }
240 
241  s->nextlen -= 1;
242  nextpos[s->nextiter] = -1;
243  s->nextiter = (s->nextiter + 1) % buffer_size;
244  }
245 
246  if (s->att > 1.) {
247  s->att = 1.;
248  s->delta = 0.;
249  s->nextiter = 0;
250  s->nextlen = 0;
251  nextpos[0] = -1;
252  }
253 
254  if (s->att <= 0.) {
255  s->att = 0.0000000000001;
256  s->delta = (1.0 - s->att) / (inlink->sample_rate * release);
257  }
258 
259  if (s->att != 1. && (1. - s->att) < 0.0000000000001)
260  s->att = 1.;
261 
262  if (s->delta != 0. && fabs(s->delta) < 0.00000000000001)
263  s->delta = 0.;
264 
265  for (c = 0; c < channels; c++)
266  dst[c] = av_clipd(dst[c], -limit, limit) * level * level_out;
267 
268  s->pos = (s->pos + channels) % buffer_size;
269  src += channels;
270  dst += channels;
271  }
272 
273  if (in != out)
274  av_frame_free(&in);
275 
276  return ff_filter_frame(outlink, out);
277 }
278 
280 {
281  AVFilterContext *ctx = inlink->dst;
282  AudioLimiterContext *s = ctx->priv;
283  int obuffer_size;
284 
285  obuffer_size = inlink->sample_rate * inlink->channels * 100 / 1000. + inlink->channels;
286  if (obuffer_size < inlink->channels)
287  return AVERROR(EINVAL);
288 
289  s->buffer = av_calloc(obuffer_size, sizeof(*s->buffer));
290  s->nextdelta = av_calloc(obuffer_size, sizeof(*s->nextdelta));
291  s->nextpos = av_malloc_array(obuffer_size, sizeof(*s->nextpos));
292  if (!s->buffer || !s->nextdelta || !s->nextpos)
293  return AVERROR(ENOMEM);
294 
295  memset(s->nextpos, -1, obuffer_size * sizeof(*s->nextpos));
296  s->buffer_size = inlink->sample_rate * s->attack * inlink->channels;
297  s->buffer_size -= s->buffer_size % inlink->channels;
298 
299  if (s->buffer_size <= 0) {
300  av_log(ctx, AV_LOG_ERROR, "Attack is too small.\n");
301  return AVERROR(EINVAL);
302  }
303 
304  return 0;
305 }
306 
308 {
309  AudioLimiterContext *s = ctx->priv;
310 
311  av_freep(&s->buffer);
312  av_freep(&s->nextdelta);
313  av_freep(&s->nextpos);
314 }
315 
316 static const AVFilterPad alimiter_inputs[] = {
317  {
318  .name = "main",
319  .type = AVMEDIA_TYPE_AUDIO,
320  .filter_frame = filter_frame,
321  .config_props = config_input,
322  },
323 };
324 
325 static const AVFilterPad alimiter_outputs[] = {
326  {
327  .name = "default",
328  .type = AVMEDIA_TYPE_AUDIO,
329  },
330 };
331 
333  .name = "alimiter",
334  .description = NULL_IF_CONFIG_SMALL("Audio lookahead limiter."),
335  .priv_size = sizeof(AudioLimiterContext),
336  .priv_class = &alimiter_class,
337  .init = init,
338  .uninit = uninit,
342 };
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:68
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:82
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:112
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:303
alimiter_inputs
static const AVFilterPad alimiter_inputs[]
Definition: af_alimiter.c:316
AVOption
AVOption.
Definition: opt.h:247
alimiter_outputs
static const AVFilterPad alimiter_outputs[]
Definition: af_alimiter.c:325
AudioLimiterContext::auto_level
int auto_level
Definition: af_alimiter.c:46
ff_af_alimiter
const AVFilter ff_af_alimiter
Definition: af_alimiter.c:332
F
#define F
Definition: af_alimiter.c:66
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:153
AudioLimiterContext::pos
int pos
Definition: af_alimiter.c:54
sample_rate
sample_rate
Definition: ffmpeg_filter.c:156
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:317
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:307
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:114
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
A
#define A
Definition: af_alimiter.c:65
AudioLimiterContext::release
double release
Definition: af_alimiter.c:41
internal.h
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:369
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:149
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:95
AVFilterContext
An instance of a filter.
Definition: avfilter.h:386
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:279
AV_SAMPLE_FMT_DBL
@ AV_SAMPLE_FMT_DBL
double
Definition: samplefmt.h:64
AudioLimiterContext::nextdelta
double * nextdelta
Definition: af_alimiter.c:56