LCOV - code coverage report
Current view: top level - src/libavfilter - af_aphaser.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 77 0.0 %
Date: 2017-01-28 02:43:52 Functions: 0 13 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Paul B Mahol
       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             : /**
      22             :  * @file
      23             :  * phaser audio filter
      24             :  */
      25             : 
      26             : #include "libavutil/avassert.h"
      27             : #include "libavutil/opt.h"
      28             : #include "audio.h"
      29             : #include "avfilter.h"
      30             : #include "internal.h"
      31             : #include "generate_wave_table.h"
      32             : 
      33             : typedef struct AudioPhaserContext {
      34             :     const AVClass *class;
      35             :     double in_gain, out_gain;
      36             :     double delay;
      37             :     double decay;
      38             :     double speed;
      39             : 
      40             :     int type;
      41             : 
      42             :     int delay_buffer_length;
      43             :     double *delay_buffer;
      44             : 
      45             :     int modulation_buffer_length;
      46             :     int32_t *modulation_buffer;
      47             : 
      48             :     int delay_pos, modulation_pos;
      49             : 
      50             :     void (*phaser)(struct AudioPhaserContext *s,
      51             :                    uint8_t * const *src, uint8_t **dst,
      52             :                    int nb_samples, int channels);
      53             : } AudioPhaserContext;
      54             : 
      55             : #define OFFSET(x) offsetof(AudioPhaserContext, x)
      56             : #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
      57             : 
      58             : static const AVOption aphaser_options[] = {
      59             :     { "in_gain",  "set input gain",            OFFSET(in_gain),  AV_OPT_TYPE_DOUBLE, {.dbl=.4},  0,  1,   FLAGS },
      60             :     { "out_gain", "set output gain",           OFFSET(out_gain), AV_OPT_TYPE_DOUBLE, {.dbl=.74}, 0,  1e9, FLAGS },
      61             :     { "delay",    "set delay in milliseconds", OFFSET(delay),    AV_OPT_TYPE_DOUBLE, {.dbl=3.},  0,  5,   FLAGS },
      62             :     { "decay",    "set decay",                 OFFSET(decay),    AV_OPT_TYPE_DOUBLE, {.dbl=.4},  0, .99,  FLAGS },
      63             :     { "speed",    "set modulation speed",      OFFSET(speed),    AV_OPT_TYPE_DOUBLE, {.dbl=.5}, .1,  2,   FLAGS },
      64             :     { "type",     "set modulation type",       OFFSET(type),     AV_OPT_TYPE_INT,    {.i64=WAVE_TRI}, 0, WAVE_NB-1, FLAGS, "type" },
      65             :     { "triangular",  NULL, 0, AV_OPT_TYPE_CONST,  {.i64=WAVE_TRI}, 0, 0, FLAGS, "type" },
      66             :     { "t",           NULL, 0, AV_OPT_TYPE_CONST,  {.i64=WAVE_TRI}, 0, 0, FLAGS, "type" },
      67             :     { "sinusoidal",  NULL, 0, AV_OPT_TYPE_CONST,  {.i64=WAVE_SIN}, 0, 0, FLAGS, "type" },
      68             :     { "s",           NULL, 0, AV_OPT_TYPE_CONST,  {.i64=WAVE_SIN}, 0, 0, FLAGS, "type" },
      69             :     { NULL }
      70             : };
      71             : 
      72             : AVFILTER_DEFINE_CLASS(aphaser);
      73             : 
      74           0 : static av_cold int init(AVFilterContext *ctx)
      75             : {
      76           0 :     AudioPhaserContext *s = ctx->priv;
      77             : 
      78           0 :     if (s->in_gain > (1 - s->decay * s->decay))
      79           0 :         av_log(ctx, AV_LOG_WARNING, "in_gain may cause clipping\n");
      80           0 :     if (s->in_gain / (1 - s->decay) > 1 / s->out_gain)
      81           0 :         av_log(ctx, AV_LOG_WARNING, "out_gain may cause clipping\n");
      82             : 
      83           0 :     return 0;
      84             : }
      85             : 
      86           0 : static int query_formats(AVFilterContext *ctx)
      87             : {
      88             :     AVFilterFormats *formats;
      89             :     AVFilterChannelLayouts *layouts;
      90             :     static const enum AVSampleFormat sample_fmts[] = {
      91             :         AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP,
      92             :         AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
      93             :         AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32P,
      94             :         AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P,
      95             :         AV_SAMPLE_FMT_NONE
      96             :     };
      97             :     int ret;
      98             : 
      99           0 :     layouts = ff_all_channel_counts();
     100           0 :     if (!layouts)
     101           0 :         return AVERROR(ENOMEM);
     102           0 :     ret = ff_set_common_channel_layouts(ctx, layouts);
     103           0 :     if (ret < 0)
     104           0 :         return ret;
     105             : 
     106           0 :     formats = ff_make_format_list(sample_fmts);
     107           0 :     if (!formats)
     108           0 :         return AVERROR(ENOMEM);
     109           0 :     ret = ff_set_common_formats(ctx, formats);
     110           0 :     if (ret < 0)
     111           0 :         return ret;
     112             : 
     113           0 :     formats = ff_all_samplerates();
     114           0 :     if (!formats)
     115           0 :         return AVERROR(ENOMEM);
     116           0 :     return ff_set_common_samplerates(ctx, formats);
     117             : }
     118             : 
     119             : #define MOD(a, b) (((a) >= (b)) ? (a) - (b) : (a))
     120             : 
     121             : #define PHASER_PLANAR(name, type)                                      \
     122             : static void phaser_## name ##p(AudioPhaserContext *s,                  \
     123             :                                uint8_t * const *ssrc, uint8_t **ddst,  \
     124             :                                int nb_samples, int channels)           \
     125             : {                                                                      \
     126             :     int i, c, delay_pos, modulation_pos;                               \
     127             :                                                                        \
     128             :     av_assert0(channels > 0);                                          \
     129             :     for (c = 0; c < channels; c++) {                                   \
     130             :         type *src = (type *)ssrc[c];                                   \
     131             :         type *dst = (type *)ddst[c];                                   \
     132             :         double *buffer = s->delay_buffer +                             \
     133             :                          c * s->delay_buffer_length;                   \
     134             :                                                                        \
     135             :         delay_pos      = s->delay_pos;                                 \
     136             :         modulation_pos = s->modulation_pos;                            \
     137             :                                                                        \
     138             :         for (i = 0; i < nb_samples; i++, src++, dst++) {               \
     139             :             double v = *src * s->in_gain + buffer[                     \
     140             :                        MOD(delay_pos + s->modulation_buffer[           \
     141             :                        modulation_pos],                                \
     142             :                        s->delay_buffer_length)] * s->decay;            \
     143             :                                                                        \
     144             :             modulation_pos = MOD(modulation_pos + 1,                   \
     145             :                              s->modulation_buffer_length);             \
     146             :             delay_pos = MOD(delay_pos + 1, s->delay_buffer_length);    \
     147             :             buffer[delay_pos] = v;                                     \
     148             :                                                                        \
     149             :             *dst = v * s->out_gain;                                    \
     150             :         }                                                              \
     151             :     }                                                                  \
     152             :                                                                        \
     153             :     s->delay_pos      = delay_pos;                                     \
     154             :     s->modulation_pos = modulation_pos;                                \
     155             : }
     156             : 
     157             : #define PHASER(name, type)                                              \
     158             : static void phaser_## name (AudioPhaserContext *s,                      \
     159             :                             uint8_t * const *ssrc, uint8_t **ddst,      \
     160             :                             int nb_samples, int channels)               \
     161             : {                                                                       \
     162             :     int i, c, delay_pos, modulation_pos;                                \
     163             :     type *src = (type *)ssrc[0];                                        \
     164             :     type *dst = (type *)ddst[0];                                        \
     165             :     double *buffer = s->delay_buffer;                                   \
     166             :                                                                         \
     167             :     delay_pos      = s->delay_pos;                                      \
     168             :     modulation_pos = s->modulation_pos;                                 \
     169             :                                                                         \
     170             :     for (i = 0; i < nb_samples; i++) {                                  \
     171             :         int pos = MOD(delay_pos + s->modulation_buffer[modulation_pos], \
     172             :                       s->delay_buffer_length) * channels;               \
     173             :         int npos;                                                       \
     174             :                                                                         \
     175             :         delay_pos = MOD(delay_pos + 1, s->delay_buffer_length);         \
     176             :         npos = delay_pos * channels;                                    \
     177             :         for (c = 0; c < channels; c++, src++, dst++) {                  \
     178             :             double v = *src * s->in_gain + buffer[pos + c] * s->decay;  \
     179             :                                                                         \
     180             :             buffer[npos + c] = v;                                       \
     181             :                                                                         \
     182             :             *dst = v * s->out_gain;                                     \
     183             :         }                                                               \
     184             :                                                                         \
     185             :         modulation_pos = MOD(modulation_pos + 1,                        \
     186             :                          s->modulation_buffer_length);                  \
     187             :     }                                                                   \
     188             :                                                                         \
     189             :     s->delay_pos      = delay_pos;                                      \
     190             :     s->modulation_pos = modulation_pos;                                 \
     191             : }
     192             : 
     193           0 : PHASER_PLANAR(dbl, double)
     194           0 : PHASER_PLANAR(flt, float)
     195           0 : PHASER_PLANAR(s16, int16_t)
     196           0 : PHASER_PLANAR(s32, int32_t)
     197             : 
     198           0 : PHASER(dbl, double)
     199           0 : PHASER(flt, float)
     200           0 : PHASER(s16, int16_t)
     201           0 : PHASER(s32, int32_t)
     202             : 
     203           0 : static int config_output(AVFilterLink *outlink)
     204             : {
     205           0 :     AudioPhaserContext *s = outlink->src->priv;
     206           0 :     AVFilterLink *inlink = outlink->src->inputs[0];
     207             : 
     208           0 :     s->delay_buffer_length = s->delay * 0.001 * inlink->sample_rate + 0.5;
     209           0 :     if (s->delay_buffer_length <= 0) {
     210           0 :         av_log(outlink->src, AV_LOG_ERROR, "delay is too small\n");
     211           0 :         return AVERROR(EINVAL);
     212             :     }
     213           0 :     s->delay_buffer = av_calloc(s->delay_buffer_length, sizeof(*s->delay_buffer) * inlink->channels);
     214           0 :     s->modulation_buffer_length = inlink->sample_rate / s->speed + 0.5;
     215           0 :     s->modulation_buffer = av_malloc_array(s->modulation_buffer_length, sizeof(*s->modulation_buffer));
     216             : 
     217           0 :     if (!s->modulation_buffer || !s->delay_buffer)
     218           0 :         return AVERROR(ENOMEM);
     219             : 
     220           0 :     ff_generate_wave_table(s->type, AV_SAMPLE_FMT_S32,
     221           0 :                            s->modulation_buffer, s->modulation_buffer_length,
     222           0 :                            1., s->delay_buffer_length, M_PI / 2.0);
     223             : 
     224           0 :     s->delay_pos = s->modulation_pos = 0;
     225             : 
     226           0 :     switch (inlink->format) {
     227           0 :     case AV_SAMPLE_FMT_DBL:  s->phaser = phaser_dbl;  break;
     228           0 :     case AV_SAMPLE_FMT_DBLP: s->phaser = phaser_dblp; break;
     229           0 :     case AV_SAMPLE_FMT_FLT:  s->phaser = phaser_flt;  break;
     230           0 :     case AV_SAMPLE_FMT_FLTP: s->phaser = phaser_fltp; break;
     231           0 :     case AV_SAMPLE_FMT_S16:  s->phaser = phaser_s16;  break;
     232           0 :     case AV_SAMPLE_FMT_S16P: s->phaser = phaser_s16p; break;
     233           0 :     case AV_SAMPLE_FMT_S32:  s->phaser = phaser_s32;  break;
     234           0 :     case AV_SAMPLE_FMT_S32P: s->phaser = phaser_s32p; break;
     235           0 :     default: av_assert0(0);
     236             :     }
     237             : 
     238           0 :     return 0;
     239             : }
     240             : 
     241           0 : static int filter_frame(AVFilterLink *inlink, AVFrame *inbuf)
     242             : {
     243           0 :     AudioPhaserContext *s = inlink->dst->priv;
     244           0 :     AVFilterLink *outlink = inlink->dst->outputs[0];
     245             :     AVFrame *outbuf;
     246             : 
     247           0 :     if (av_frame_is_writable(inbuf)) {
     248           0 :         outbuf = inbuf;
     249             :     } else {
     250           0 :         outbuf = ff_get_audio_buffer(inlink, inbuf->nb_samples);
     251           0 :         if (!outbuf)
     252           0 :             return AVERROR(ENOMEM);
     253           0 :         av_frame_copy_props(outbuf, inbuf);
     254             :     }
     255             : 
     256           0 :     s->phaser(s, inbuf->extended_data, outbuf->extended_data,
     257             :               outbuf->nb_samples, av_frame_get_channels(outbuf));
     258             : 
     259           0 :     if (inbuf != outbuf)
     260           0 :         av_frame_free(&inbuf);
     261             : 
     262           0 :     return ff_filter_frame(outlink, outbuf);
     263             : }
     264             : 
     265           0 : static av_cold void uninit(AVFilterContext *ctx)
     266             : {
     267           0 :     AudioPhaserContext *s = ctx->priv;
     268             : 
     269           0 :     av_freep(&s->delay_buffer);
     270           0 :     av_freep(&s->modulation_buffer);
     271           0 : }
     272             : 
     273             : static const AVFilterPad aphaser_inputs[] = {
     274             :     {
     275             :         .name         = "default",
     276             :         .type         = AVMEDIA_TYPE_AUDIO,
     277             :         .filter_frame = filter_frame,
     278             :     },
     279             :     { NULL }
     280             : };
     281             : 
     282             : static const AVFilterPad aphaser_outputs[] = {
     283             :     {
     284             :         .name         = "default",
     285             :         .type         = AVMEDIA_TYPE_AUDIO,
     286             :         .config_props = config_output,
     287             :     },
     288             :     { NULL }
     289             : };
     290             : 
     291             : AVFilter ff_af_aphaser = {
     292             :     .name          = "aphaser",
     293             :     .description   = NULL_IF_CONFIG_SMALL("Add a phasing effect to the audio."),
     294             :     .query_formats = query_formats,
     295             :     .priv_size     = sizeof(AudioPhaserContext),
     296             :     .init          = init,
     297             :     .uninit        = uninit,
     298             :     .inputs        = aphaser_inputs,
     299             :     .outputs       = aphaser_outputs,
     300             :     .priv_class    = &aphaser_class,
     301             : };

Generated by: LCOV version 1.12