LCOV - code coverage report
Current view: top level - libavfilter - af_stereotools.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 98 181 54.1 %
Date: 2017-12-15 11:05:35 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen
       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             : #include "libavutil/channel_layout.h"
      22             : #include "libavutil/opt.h"
      23             : #include "avfilter.h"
      24             : #include "audio.h"
      25             : #include "formats.h"
      26             : 
      27             : typedef struct StereoToolsContext {
      28             :     const AVClass *class;
      29             : 
      30             :     int softclip;
      31             :     int mute_l;
      32             :     int mute_r;
      33             :     int phase_l;
      34             :     int phase_r;
      35             :     int mode;
      36             :     int bmode_in;
      37             :     int bmode_out;
      38             :     double slev;
      39             :     double sbal;
      40             :     double mlev;
      41             :     double mpan;
      42             :     double phase;
      43             :     double base;
      44             :     double delay;
      45             :     double balance_in;
      46             :     double balance_out;
      47             :     double phase_sin_coef;
      48             :     double phase_cos_coef;
      49             :     double sc_level;
      50             :     double inv_atan_shape;
      51             :     double level_in;
      52             :     double level_out;
      53             : 
      54             :     double *buffer;
      55             :     int length;
      56             :     int pos;
      57             : } StereoToolsContext;
      58             : 
      59             : #define OFFSET(x) offsetof(StereoToolsContext, x)
      60             : #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
      61             : 
      62             : static const AVOption stereotools_options[] = {
      63             :     { "level_in",    "set level in",     OFFSET(level_in),    AV_OPT_TYPE_DOUBLE, {.dbl=1},   0.015625,  64, A },
      64             :     { "level_out",   "set level out",    OFFSET(level_out),   AV_OPT_TYPE_DOUBLE, {.dbl=1},   0.015625,  64, A },
      65             :     { "balance_in",  "set balance in",   OFFSET(balance_in),  AV_OPT_TYPE_DOUBLE, {.dbl=0},  -1,          1, A },
      66             :     { "balance_out", "set balance out",  OFFSET(balance_out), AV_OPT_TYPE_DOUBLE, {.dbl=0},  -1,          1, A },
      67             :     { "softclip",    "enable softclip",  OFFSET(softclip),    AV_OPT_TYPE_BOOL,   {.i64=0},   0,          1, A },
      68             :     { "mutel",       "mute L",           OFFSET(mute_l),      AV_OPT_TYPE_BOOL,   {.i64=0},   0,          1, A },
      69             :     { "muter",       "mute R",           OFFSET(mute_r),      AV_OPT_TYPE_BOOL,   {.i64=0},   0,          1, A },
      70             :     { "phasel",      "phase L",          OFFSET(phase_l),     AV_OPT_TYPE_BOOL,   {.i64=0},   0,          1, A },
      71             :     { "phaser",      "phase R",          OFFSET(phase_r),     AV_OPT_TYPE_BOOL,   {.i64=0},   0,          1, A },
      72             :     { "mode",        "set stereo mode",  OFFSET(mode),        AV_OPT_TYPE_INT,    {.i64=0},   0,          8, A, "mode" },
      73             :     {     "lr>lr",   0,                  0,                   AV_OPT_TYPE_CONST,  {.i64=0},   0,          0, A, "mode" },
      74             :     {     "lr>ms",   0,                  0,                   AV_OPT_TYPE_CONST,  {.i64=1},   0,          0, A, "mode" },
      75             :     {     "ms>lr",   0,                  0,                   AV_OPT_TYPE_CONST,  {.i64=2},   0,          0, A, "mode" },
      76             :     {     "lr>ll",   0,                  0,                   AV_OPT_TYPE_CONST,  {.i64=3},   0,          0, A, "mode" },
      77             :     {     "lr>rr",   0,                  0,                   AV_OPT_TYPE_CONST,  {.i64=4},   0,          0, A, "mode" },
      78             :     {     "lr>l+r",  0,                  0,                   AV_OPT_TYPE_CONST,  {.i64=5},   0,          0, A, "mode" },
      79             :     {     "lr>rl",   0,                  0,                   AV_OPT_TYPE_CONST,  {.i64=6},   0,          0, A, "mode" },
      80             :     {     "ms>ll",   0,                  0,                   AV_OPT_TYPE_CONST,  {.i64=7},   0,          0, A, "mode" },
      81             :     {     "ms>rr",   0,                  0,                   AV_OPT_TYPE_CONST,  {.i64=8},   0,          0, A, "mode" },
      82             :     { "slev",        "set side level",   OFFSET(slev),        AV_OPT_TYPE_DOUBLE, {.dbl=1},   0.015625,  64, A },
      83             :     { "sbal",        "set side balance", OFFSET(sbal),        AV_OPT_TYPE_DOUBLE, {.dbl=0},  -1,          1, A },
      84             :     { "mlev",        "set middle level", OFFSET(mlev),        AV_OPT_TYPE_DOUBLE, {.dbl=1},   0.015625,  64, A },
      85             :     { "mpan",        "set middle pan",   OFFSET(mpan),        AV_OPT_TYPE_DOUBLE, {.dbl=0},  -1,          1, A },
      86             :     { "base",        "set stereo base",  OFFSET(base),        AV_OPT_TYPE_DOUBLE, {.dbl=0},  -1,          1, A },
      87             :     { "delay",       "set delay",        OFFSET(delay),       AV_OPT_TYPE_DOUBLE, {.dbl=0}, -20,         20, A },
      88             :     { "sclevel",     "set S/C level",    OFFSET(sc_level),    AV_OPT_TYPE_DOUBLE, {.dbl=1},   1,        100, A },
      89             :     { "phase",       "set stereo phase", OFFSET(phase),       AV_OPT_TYPE_DOUBLE, {.dbl=0},   0,        360, A },
      90             :     { "bmode_in",    "set balance in mode", OFFSET(bmode_in), AV_OPT_TYPE_INT,    {.i64=0},   0,          2, A, "bmode" },
      91             :     {     "balance",   0,                0,                   AV_OPT_TYPE_CONST,  {.i64=0},   0,          0, A, "bmode" },
      92             :     {     "amplitude", 0,                0,                   AV_OPT_TYPE_CONST,  {.i64=1},   0,          0, A, "bmode" },
      93             :     {     "power",     0,                0,                   AV_OPT_TYPE_CONST,  {.i64=2},   0,          0, A, "bmode" },
      94             :     { "bmode_out", "set balance out mode", OFFSET(bmode_out), AV_OPT_TYPE_INT,    {.i64=0},   0,          2, A, "bmode" },
      95             :     { NULL }
      96             : };
      97             : 
      98             : AVFILTER_DEFINE_CLASS(stereotools);
      99             : 
     100           1 : static int query_formats(AVFilterContext *ctx)
     101             : {
     102           1 :     AVFilterFormats *formats = NULL;
     103           1 :     AVFilterChannelLayouts *layout = NULL;
     104             :     int ret;
     105             : 
     106           2 :     if ((ret = ff_add_format                 (&formats, AV_SAMPLE_FMT_DBL  )) < 0 ||
     107           2 :         (ret = ff_set_common_formats         (ctx     , formats            )) < 0 ||
     108           1 :         (ret = ff_add_channel_layout         (&layout , AV_CH_LAYOUT_STEREO)) < 0 ||
     109           1 :         (ret = ff_set_common_channel_layouts (ctx     , layout             )) < 0)
     110           0 :         return ret;
     111             : 
     112           1 :     formats = ff_all_samplerates();
     113           1 :     return ff_set_common_samplerates(ctx, formats);
     114             : }
     115             : 
     116           1 : static int config_input(AVFilterLink *inlink)
     117             : {
     118           1 :     AVFilterContext *ctx = inlink->dst;
     119           1 :     StereoToolsContext *s = ctx->priv;
     120             : 
     121           1 :     s->length = 2 * inlink->sample_rate * 0.05;
     122           1 :     if (s->length <= 1 || s->length & 1) {
     123           0 :         av_log(ctx, AV_LOG_ERROR, "sample rate is too small\n");
     124           0 :         return AVERROR(EINVAL);
     125             :     }
     126           1 :     s->buffer = av_calloc(s->length, sizeof(*s->buffer));
     127           1 :     if (!s->buffer)
     128           0 :         return AVERROR(ENOMEM);
     129             : 
     130           1 :     s->inv_atan_shape = 1.0 / atan(s->sc_level);
     131           1 :     s->phase_cos_coef = cos(s->phase / 180 * M_PI);
     132           1 :     s->phase_sin_coef = sin(s->phase / 180 * M_PI);
     133             : 
     134           1 :     return 0;
     135             : }
     136             : 
     137          20 : static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     138             : {
     139          20 :     AVFilterContext *ctx = inlink->dst;
     140          20 :     AVFilterLink *outlink = ctx->outputs[0];
     141          20 :     StereoToolsContext *s = ctx->priv;
     142          20 :     const double *src = (const double *)in->data[0];
     143          20 :     const double sb = s->base < 0 ? s->base * 0.5 : s->base;
     144          20 :     const double sbal = 1 + s->sbal;
     145          20 :     const double mpan = 1 + s->mpan;
     146          20 :     const double slev = s->slev;
     147          20 :     const double mlev = s->mlev;
     148          20 :     const double balance_in = s->balance_in;
     149          20 :     const double balance_out = s->balance_out;
     150          20 :     const double level_in = s->level_in;
     151          20 :     const double level_out = s->level_out;
     152          20 :     const double sc_level = s->sc_level;
     153          20 :     const double delay = s->delay;
     154          20 :     const int length = s->length;
     155          20 :     const int mute_l = s->mute_l;
     156          20 :     const int mute_r = s->mute_r;
     157          20 :     const int phase_l = s->phase_l;
     158          20 :     const int phase_r = s->phase_r;
     159          20 :     double *buffer = s->buffer;
     160             :     AVFrame *out;
     161             :     double *dst;
     162          20 :     int nbuf = inlink->sample_rate * (fabs(delay) / 1000.);
     163             :     int n;
     164             : 
     165          20 :     nbuf -= nbuf % 2;
     166          20 :     if (av_frame_is_writable(in)) {
     167          20 :         out = in;
     168             :     } else {
     169           0 :         out = ff_get_audio_buffer(inlink, in->nb_samples);
     170           0 :         if (!out) {
     171           0 :             av_frame_free(&in);
     172           0 :             return AVERROR(ENOMEM);
     173             :         }
     174           0 :         av_frame_copy_props(out, in);
     175             :     }
     176          20 :     dst = (double *)out->data[0];
     177             : 
     178       20500 :     for (n = 0; n < in->nb_samples; n++, src += 2, dst += 2) {
     179       20480 :         double L = src[0], R = src[1], l, r, m, S, gl, gr, gd;
     180             : 
     181       20480 :         L *= level_in;
     182       20480 :         R *= level_in;
     183             : 
     184       20480 :         gl = 1. - FFMAX(0., balance_in);
     185       20480 :         gr = 1. + FFMIN(0., balance_in);
     186       20480 :         switch (s->bmode_in) {
     187           0 :         case 1:
     188           0 :             gd = gl - gr;
     189           0 :             gl = 1. + gd;
     190           0 :             gr = 1. - gd;
     191           0 :             break;
     192           0 :         case 2:
     193           0 :             if (balance_in < 0.) {
     194           0 :                 gr = FFMAX(0.5, gr);
     195           0 :                 gl = 1. / gr;
     196           0 :             } else if (balance_in > 0.) {
     197           0 :                 gl = FFMAX(0.5, gl);
     198           0 :                 gr = 1. / gl;
     199             :             }
     200           0 :             break;
     201             :         }
     202       20480 :         L *= gl;
     203       20480 :         R *= gr;
     204             : 
     205       20480 :         if (s->softclip) {
     206           0 :             R = s->inv_atan_shape * atan(R * sc_level);
     207           0 :             L = s->inv_atan_shape * atan(L * sc_level);
     208             :         }
     209             : 
     210       20480 :         switch (s->mode) {
     211       20480 :         case 0:
     212       20480 :             m = (L + R) * 0.5;
     213       20480 :             S = (L - R) * 0.5;
     214       20480 :             l = m * mlev * FFMIN(1., 2. - mpan) + S * slev * FFMIN(1., 2. - sbal);
     215       20480 :             r = m * mlev * FFMIN(1., mpan)      - S * slev * FFMIN(1., sbal);
     216       20480 :             L = l;
     217       20480 :             R = r;
     218       20480 :             break;
     219           0 :         case 1:
     220           0 :             l = L * FFMIN(1., 2. - sbal);
     221           0 :             r = R * FFMIN(1., sbal);
     222           0 :             L = 0.5 * (l + r) * mlev;
     223           0 :             R = 0.5 * (l - r) * slev;
     224           0 :             break;
     225           0 :         case 2:
     226           0 :             l = L * mlev * FFMIN(1., 2. - mpan) + R * slev * FFMIN(1., 2. - sbal);
     227           0 :             r = L * mlev * FFMIN(1., mpan)      - R * slev * FFMIN(1., sbal);
     228           0 :             L = l;
     229           0 :             R = r;
     230           0 :             break;
     231           0 :         case 3:
     232           0 :             R = L;
     233           0 :             break;
     234           0 :         case 4:
     235           0 :             L = R;
     236           0 :             break;
     237           0 :         case 5:
     238           0 :             L = (L + R) / 2;
     239           0 :             R = L;
     240           0 :             break;
     241           0 :         case 6:
     242           0 :             l = L;
     243           0 :             L = R;
     244           0 :             R = l;
     245           0 :             m = (L + R) * 0.5;
     246           0 :             S = (L - R) * 0.5;
     247           0 :             l = m * mlev * FFMIN(1., 2. - mpan) + S * slev * FFMIN(1., 2. - sbal);
     248           0 :             r = m * mlev * FFMIN(1., mpan)      - S * slev * FFMIN(1., sbal);
     249           0 :             L = l;
     250           0 :             R = r;
     251           0 :             break;
     252           0 :         case 7:
     253           0 :             l = L * mlev * FFMIN(1., 2. - mpan) + R * slev * FFMIN(1., 2. - sbal);
     254           0 :             L = l;
     255           0 :             R = l;
     256           0 :             break;
     257           0 :         case 8:
     258           0 :             r = L * mlev * FFMIN(1., mpan)      - R * slev * FFMIN(1., sbal);
     259           0 :             L = r;
     260           0 :             R = r;
     261           0 :             break;
     262             :         }
     263             : 
     264       20480 :         L *= 1. - mute_l;
     265       20480 :         R *= 1. - mute_r;
     266             : 
     267       20480 :         L *= (2. * (1. - phase_l)) - 1.;
     268       20480 :         R *= (2. * (1. - phase_r)) - 1.;
     269             : 
     270       20480 :         buffer[s->pos  ] = L;
     271       20480 :         buffer[s->pos+1] = R;
     272             : 
     273       20480 :         if (delay > 0.) {
     274           0 :             R = buffer[(s->pos - (int)nbuf + 1 + length) % length];
     275       20480 :         } else if (delay < 0.) {
     276           0 :             L = buffer[(s->pos - (int)nbuf + length)     % length];
     277             :         }
     278             : 
     279       20480 :         l = L + sb * L - sb * R;
     280       20480 :         r = R + sb * R - sb * L;
     281             : 
     282       20480 :         L = l;
     283       20480 :         R = r;
     284             : 
     285       20480 :         l = L * s->phase_cos_coef - R * s->phase_sin_coef;
     286       20480 :         r = L * s->phase_sin_coef + R * s->phase_cos_coef;
     287             : 
     288       20480 :         L = l;
     289       20480 :         R = r;
     290             : 
     291       20480 :         s->pos = (s->pos + 2) % s->length;
     292             : 
     293       20480 :         gl = 1. - FFMAX(0., balance_out);
     294       20480 :         gr = 1. + FFMIN(0., balance_out);
     295       20480 :         switch (s->bmode_out) {
     296           0 :         case 1:
     297           0 :             gd = gl - gr;
     298           0 :             gl = 1. + gd;
     299           0 :             gr = 1. - gd;
     300           0 :             break;
     301           0 :         case 2:
     302           0 :             if (balance_out < 0.) {
     303           0 :                 gr = FFMAX(0.5, gr);
     304           0 :                 gl = 1. / gr;
     305           0 :             } else if (balance_out > 0.) {
     306           0 :                 gl = FFMAX(0.5, gl);
     307           0 :                 gr = 1. / gl;
     308             :             }
     309           0 :             break;
     310             :         }
     311       20480 :         L *= gl;
     312       20480 :         R *= gr;
     313             : 
     314             : 
     315       20480 :         L *= level_out;
     316       20480 :         R *= level_out;
     317             : 
     318       20480 :         dst[0] = L;
     319       20480 :         dst[1] = R;
     320             :     }
     321             : 
     322          20 :     if (out != in)
     323           0 :         av_frame_free(&in);
     324          20 :     return ff_filter_frame(outlink, out);
     325             : }
     326             : 
     327           1 : static av_cold void uninit(AVFilterContext *ctx)
     328             : {
     329           1 :     StereoToolsContext *s = ctx->priv;
     330             : 
     331           1 :     av_freep(&s->buffer);
     332           1 : }
     333             : 
     334             : static const AVFilterPad inputs[] = {
     335             :     {
     336             :         .name         = "default",
     337             :         .type         = AVMEDIA_TYPE_AUDIO,
     338             :         .filter_frame = filter_frame,
     339             :         .config_props = config_input,
     340             :     },
     341             :     { NULL }
     342             : };
     343             : 
     344             : static const AVFilterPad outputs[] = {
     345             :     {
     346             :         .name = "default",
     347             :         .type = AVMEDIA_TYPE_AUDIO,
     348             :     },
     349             :     { NULL }
     350             : };
     351             : 
     352             : AVFilter ff_af_stereotools = {
     353             :     .name           = "stereotools",
     354             :     .description    = NULL_IF_CONFIG_SMALL("Apply various stereo tools."),
     355             :     .query_formats  = query_formats,
     356             :     .priv_size      = sizeof(StereoToolsContext),
     357             :     .priv_class     = &stereotools_class,
     358             :     .uninit         = uninit,
     359             :     .inputs         = inputs,
     360             :     .outputs        = outputs,
     361             : };

Generated by: LCOV version 1.13