LCOV - code coverage report
Current view: top level - libavfilter - af_alimiter.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 129 167 77.2 %
Date: 2017-12-17 16:07:53 Functions: 6 6 100.0 %

          Line data    Source code
       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           0 :         double a_att = limit / (s->asc_coeff * s->asc) * (double)s->asc_c;
     103             : 
     104           0 :         if (a_att > patt) {
     105           0 :             double delta = FFMAX((a_att - patt) / (sample_rate * release), rdelta / 10);
     106             : 
     107           0 :             if (delta < rdelta)
     108           0 :                 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           0 :         out = ff_get_audio_buffer(inlink, in->nb_samples);
     139           0 :         if (!out) {
     140           0 :             av_frame_free(&in);
     141           0 :             return AVERROR(ENOMEM);
     142             :         }
     143           0 :         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           0 :             s->asc += peak;
     159           0 :             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           0 :             s->asc_pos = -1;
     210             : 
     211      264600 :         if (s->auto_release && s->asc_pos == -1 && peak > limit) {
     212           0 :             s->asc -= peak;
     213           0 :             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           0 :                 s->delta = get_rdelta(s, release, inlink->sample_rate,
     224             :                                       peak, limit, s->att, 1);
     225           0 :                 if (s->nextlen > 1) {
     226           0 :                     int pnextpos = nextpos[(s->nextiter + 1) % buffer_size];
     227           0 :                     double ppeak = fabs(buffer[pnextpos]) > fabs(buffer[pnextpos + 1]) ?
     228           0 :                                                             fabs(buffer[pnextpos]) :
     229           0 :                                                             fabs(buffer[pnextpos + 1]);
     230           0 :                     double pdelta = (limit / ppeak - s->att) /
     231           0 :                                     (((buffer_size + pnextpos -
     232           0 :                                     ((s->pos + channels) % buffer_size)) %
     233           0 :                                     buffer_size) / channels);
     234           0 :                     if (pdelta < s->delta)
     235           0 :                         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           0 :             s->att = 0.0000000000001;
     257           0 :             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           0 :             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           0 :         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           0 :         return AVERROR(ENOMEM);
     293           1 :     ret = ff_set_common_channel_layouts(ctx, layouts);
     294           1 :     if (ret < 0)
     295           0 :         return ret;
     296             : 
     297           1 :     formats = ff_make_format_list(sample_fmts);
     298           1 :     if (!formats)
     299           0 :         return AVERROR(ENOMEM);
     300           1 :     ret = ff_set_common_formats(ctx, formats);
     301           1 :     if (ret < 0)
     302           0 :         return ret;
     303             : 
     304           1 :     formats = ff_all_samplerates();
     305           1 :     if (!formats)
     306           0 :         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           0 :         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           0 :         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 :     return 0;
     331             : }
     332             : 
     333           1 : static av_cold void uninit(AVFilterContext *ctx)
     334             : {
     335           1 :     AudioLimiterContext *s = ctx->priv;
     336             : 
     337           1 :     av_freep(&s->buffer);
     338           1 :     av_freep(&s->nextdelta);
     339           1 :     av_freep(&s->nextpos);
     340           1 : }
     341             : 
     342             : static const AVFilterPad alimiter_inputs[] = {
     343             :     {
     344             :         .name         = "main",
     345             :         .type         = AVMEDIA_TYPE_AUDIO,
     346             :         .filter_frame = filter_frame,
     347             :         .config_props = config_input,
     348             :     },
     349             :     { NULL }
     350             : };
     351             : 
     352             : static const AVFilterPad alimiter_outputs[] = {
     353             :     {
     354             :         .name = "default",
     355             :         .type = AVMEDIA_TYPE_AUDIO,
     356             :     },
     357             :     { NULL }
     358             : };
     359             : 
     360             : AVFilter ff_af_alimiter = {
     361             :     .name           = "alimiter",
     362             :     .description    = NULL_IF_CONFIG_SMALL("Audio lookahead limiter."),
     363             :     .priv_size      = sizeof(AudioLimiterContext),
     364             :     .priv_class     = &alimiter_class,
     365             :     .init           = init,
     366             :     .uninit         = uninit,
     367             :     .query_formats  = query_formats,
     368             :     .inputs         = alimiter_inputs,
     369             :     .outputs        = alimiter_outputs,
     370             : };

Generated by: LCOV version 1.13