LCOV - code coverage report
Current view: top level - src/libavfilter - af_apulsator.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 94 0.0 %
Date: 2017-01-24 04:42:20 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
       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/avassert.h"
      22             : #include "libavutil/opt.h"
      23             : #include "avfilter.h"
      24             : #include "internal.h"
      25             : #include "audio.h"
      26             : 
      27             : enum PulsatorModes { SINE, TRIANGLE, SQUARE, SAWUP, SAWDOWN, NB_MODES };
      28             : enum PulsatorTimings { UNIT_BPM, UNIT_MS, UNIT_HZ, NB_TIMINGS };
      29             : 
      30             : typedef struct SimpleLFO {
      31             :     double phase;
      32             :     double freq;
      33             :     double offset;
      34             :     double amount;
      35             :     double pwidth;
      36             :     int mode;
      37             :     int srate;
      38             : } SimpleLFO;
      39             : 
      40             : typedef struct AudioPulsatorContext {
      41             :     const AVClass *class;
      42             :     int mode;
      43             :     double level_in;
      44             :     double level_out;
      45             :     double amount;
      46             :     double offset_l;
      47             :     double offset_r;
      48             :     double pwidth;
      49             :     double bpm;
      50             :     double hertz;
      51             :     int ms;
      52             :     int timing;
      53             : 
      54             :     SimpleLFO lfoL, lfoR;
      55             : } AudioPulsatorContext;
      56             : 
      57             : #define OFFSET(x) offsetof(AudioPulsatorContext, x)
      58             : #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
      59             : 
      60             : static const AVOption apulsator_options[] = {
      61             :     { "level_in",   "set input gain", OFFSET(level_in),  AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, FLAGS, },
      62             :     { "level_out", "set output gain", OFFSET(level_out), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, FLAGS, },
      63             :     { "mode",             "set mode", OFFSET(mode),      AV_OPT_TYPE_INT,    {.i64=SINE}, SINE,   NB_MODES-1, FLAGS, "mode" },
      64             :     {   "sine",                 NULL, 0,                 AV_OPT_TYPE_CONST,  {.i64=SINE},    0,            0, FLAGS, "mode" },
      65             :     {   "triangle",             NULL, 0,                 AV_OPT_TYPE_CONST,  {.i64=TRIANGLE},0,            0, FLAGS, "mode" },
      66             :     {   "square",               NULL, 0,                 AV_OPT_TYPE_CONST,  {.i64=SQUARE},  0,            0, FLAGS, "mode" },
      67             :     {   "sawup",                NULL, 0,                 AV_OPT_TYPE_CONST,  {.i64=SAWUP},   0,            0, FLAGS, "mode" },
      68             :     {   "sawdown",              NULL, 0,                 AV_OPT_TYPE_CONST,  {.i64=SAWDOWN}, 0,            0, FLAGS, "mode" },
      69             :     { "amount",     "set modulation", OFFSET(amount),    AV_OPT_TYPE_DOUBLE, {.dbl=1},       0,            1, FLAGS },
      70             :     { "offset_l",     "set offset L", OFFSET(offset_l),  AV_OPT_TYPE_DOUBLE, {.dbl=0},       0,            1, FLAGS },
      71             :     { "offset_r",     "set offset R", OFFSET(offset_r),  AV_OPT_TYPE_DOUBLE, {.dbl=.5},      0,            1, FLAGS },
      72             :     { "width",     "set pulse width", OFFSET(pwidth),    AV_OPT_TYPE_DOUBLE, {.dbl=1},       0,            2, FLAGS },
      73             :     { "timing",         "set timing", OFFSET(timing),    AV_OPT_TYPE_INT,    {.i64=2},       0, NB_TIMINGS-1, FLAGS, "timing" },
      74             :     {   "bpm",                  NULL, 0,                 AV_OPT_TYPE_CONST,  {.i64=UNIT_BPM},  0,          0, FLAGS, "timing" },
      75             :     {   "ms",                   NULL, 0,                 AV_OPT_TYPE_CONST,  {.i64=UNIT_MS},   0,          0, FLAGS, "timing" },
      76             :     {   "hz",                   NULL, 0,                 AV_OPT_TYPE_CONST,  {.i64=UNIT_HZ},   0,          0, FLAGS, "timing" },
      77             :     { "bpm",               "set BPM", OFFSET(bpm),       AV_OPT_TYPE_DOUBLE, {.dbl=120},    30,          300, FLAGS },
      78             :     { "ms",                 "set ms", OFFSET(ms),        AV_OPT_TYPE_INT,    {.i64=500},    10,         2000, FLAGS },
      79             :     { "hz",          "set frequency", OFFSET(hertz),     AV_OPT_TYPE_DOUBLE, {.dbl=2},    0.01,          100, FLAGS },
      80             :     { NULL }
      81             : };
      82             : 
      83             : AVFILTER_DEFINE_CLASS(apulsator);
      84             : 
      85           0 : static void lfo_advance(SimpleLFO *lfo, unsigned count)
      86             : {
      87           0 :     lfo->phase = fabs(lfo->phase + count * lfo->freq / lfo->srate);
      88           0 :     if (lfo->phase >= 1)
      89           0 :         lfo->phase = fmod(lfo->phase, 1);
      90           0 : }
      91             : 
      92           0 : static double lfo_get_value(SimpleLFO *lfo)
      93             : {
      94           0 :     double phs = FFMIN(100, lfo->phase / FFMIN(1.99, FFMAX(0.01, lfo->pwidth)) + lfo->offset);
      95             :     double val;
      96             : 
      97           0 :     if (phs > 1)
      98           0 :         phs = fmod(phs, 1.);
      99             : 
     100           0 :     switch (lfo->mode) {
     101             :     case SINE:
     102           0 :         val = sin(phs * 2 * M_PI);
     103           0 :         break;
     104             :     case TRIANGLE:
     105           0 :         if (phs > 0.75)
     106           0 :             val = (phs - 0.75) * 4 - 1;
     107           0 :         else if (phs > 0.25)
     108           0 :             val = -4 * phs + 2;
     109             :         else
     110           0 :             val = phs * 4;
     111           0 :         break;
     112             :     case SQUARE:
     113           0 :         val = phs < 0.5 ? -1 : +1;
     114           0 :         break;
     115             :     case SAWUP:
     116           0 :         val = phs * 2 - 1;
     117           0 :         break;
     118             :     case SAWDOWN:
     119           0 :         val = 1 - phs * 2;
     120           0 :         break;
     121           0 :     default: av_assert0(0);
     122             :     }
     123             : 
     124           0 :     return val * lfo->amount;
     125             : }
     126             : 
     127           0 : static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     128             : {
     129           0 :     AVFilterContext *ctx = inlink->dst;
     130           0 :     AVFilterLink *outlink = ctx->outputs[0];
     131           0 :     AudioPulsatorContext *s = ctx->priv;
     132           0 :     const double *src = (const double *)in->data[0];
     133           0 :     const int nb_samples = in->nb_samples;
     134           0 :     const double level_out = s->level_out;
     135           0 :     const double level_in = s->level_in;
     136           0 :     const double amount = s->amount;
     137             :     AVFrame *out;
     138             :     double *dst;
     139             :     int n;
     140             : 
     141           0 :     if (av_frame_is_writable(in)) {
     142           0 :         out = in;
     143             :     } else {
     144           0 :         out = ff_get_audio_buffer(inlink, in->nb_samples);
     145           0 :         if (!out) {
     146           0 :             av_frame_free(&in);
     147           0 :             return AVERROR(ENOMEM);
     148             :         }
     149           0 :         av_frame_copy_props(out, in);
     150             :     }
     151           0 :     dst = (double *)out->data[0];
     152             : 
     153           0 :     for (n = 0; n < nb_samples; n++) {
     154             :         double outL;
     155             :         double outR;
     156           0 :         double inL = src[0] * level_in;
     157           0 :         double inR = src[1] * level_in;
     158           0 :         double procL = inL;
     159           0 :         double procR = inR;
     160             : 
     161           0 :         procL *= lfo_get_value(&s->lfoL) * 0.5 + amount / 2;
     162           0 :         procR *= lfo_get_value(&s->lfoR) * 0.5 + amount / 2;
     163             : 
     164           0 :         outL = procL + inL * (1 - amount);
     165           0 :         outR = procR + inR * (1 - amount);
     166             : 
     167           0 :         outL *= level_out;
     168           0 :         outR *= level_out;
     169             : 
     170           0 :         dst[0] = outL;
     171           0 :         dst[1] = outR;
     172             : 
     173           0 :         lfo_advance(&s->lfoL, 1);
     174           0 :         lfo_advance(&s->lfoR, 1);
     175             : 
     176           0 :         dst += 2;
     177           0 :         src += 2;
     178             :     }
     179             : 
     180           0 :     if (in != out)
     181           0 :         av_frame_free(&in);
     182             : 
     183           0 :     return ff_filter_frame(outlink, out);
     184             : }
     185             : 
     186           0 : static int query_formats(AVFilterContext *ctx)
     187             : {
     188           0 :     AVFilterChannelLayouts *layout = NULL;
     189           0 :     AVFilterFormats *formats = NULL;
     190             :     int ret;
     191             : 
     192           0 :     if ((ret = ff_add_format                 (&formats, AV_SAMPLE_FMT_DBL  )) < 0 ||
     193           0 :         (ret = ff_set_common_formats         (ctx     , formats            )) < 0 ||
     194           0 :         (ret = ff_add_channel_layout         (&layout , AV_CH_LAYOUT_STEREO)) < 0 ||
     195           0 :         (ret = ff_set_common_channel_layouts (ctx     , layout             )) < 0)
     196           0 :         return ret;
     197             : 
     198           0 :     formats = ff_all_samplerates();
     199           0 :     return ff_set_common_samplerates(ctx, formats);
     200             : }
     201             : 
     202           0 : static int config_input(AVFilterLink *inlink)
     203             : {
     204           0 :     AVFilterContext *ctx = inlink->dst;
     205           0 :     AudioPulsatorContext *s = ctx->priv;
     206             :     double freq;
     207             : 
     208           0 :     switch (s->timing) {
     209           0 :     case UNIT_BPM:  freq = s->bpm / 60;         break;
     210           0 :     case UNIT_MS:   freq = 1 / (s->ms / 1000.); break;
     211           0 :     case UNIT_HZ:   freq = s->hertz;            break;
     212           0 :     default: av_assert0(0);
     213             :     }
     214             : 
     215           0 :     s->lfoL.freq   = freq;
     216           0 :     s->lfoR.freq   = freq;
     217           0 :     s->lfoL.mode   = s->mode;
     218           0 :     s->lfoR.mode   = s->mode;
     219           0 :     s->lfoL.offset = s->offset_l;
     220           0 :     s->lfoR.offset = s->offset_r;
     221           0 :     s->lfoL.srate  = inlink->sample_rate;
     222           0 :     s->lfoR.srate  = inlink->sample_rate;
     223           0 :     s->lfoL.amount = s->amount;
     224           0 :     s->lfoR.amount = s->amount;
     225           0 :     s->lfoL.pwidth = s->pwidth;
     226           0 :     s->lfoR.pwidth = s->pwidth;
     227             : 
     228           0 :     return 0;
     229             : }
     230             : 
     231             : static const AVFilterPad inputs[] = {
     232             :     {
     233             :         .name         = "default",
     234             :         .type         = AVMEDIA_TYPE_AUDIO,
     235             :         .config_props = config_input,
     236             :         .filter_frame = filter_frame,
     237             :     },
     238             :     { NULL }
     239             : };
     240             : 
     241             : static const AVFilterPad outputs[] = {
     242             :     {
     243             :         .name = "default",
     244             :         .type = AVMEDIA_TYPE_AUDIO,
     245             :     },
     246             :     { NULL }
     247             : };
     248             : 
     249             : AVFilter ff_af_apulsator = {
     250             :     .name          = "apulsator",
     251             :     .description   = NULL_IF_CONFIG_SMALL("Audio pulsator."),
     252             :     .priv_size     = sizeof(AudioPulsatorContext),
     253             :     .priv_class    = &apulsator_class,
     254             :     .query_formats = query_formats,
     255             :     .inputs        = inputs,
     256             :     .outputs       = outputs,
     257             : };

Generated by: LCOV version 1.12