Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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. #include "libavutil/avassert.h"
  23. #include "libavutil/avstring.h"
  24. #include "libavutil/opt.h"
  25. #include "libavutil/samplefmt.h"
  26. #include "avfilter.h"
  27. #include "audio.h"
  28. #include "internal.h"
  29.  
  30. typedef struct AudioEchoContext {
  31.     const AVClass *class;
  32.     float in_gain, out_gain;
  33.     char *delays, *decays;
  34.     float *delay, *decay;
  35.     int nb_echoes;
  36.     int delay_index;
  37.     uint8_t **delayptrs;
  38.     int max_samples, fade_out;
  39.     int *samples;
  40.     int64_t next_pts;
  41.  
  42.     void (*echo_samples)(struct AudioEchoContext *ctx, uint8_t **delayptrs,
  43.                          uint8_t * const *src, uint8_t **dst,
  44.                          int nb_samples, int channels);
  45. } AudioEchoContext;
  46.  
  47. #define OFFSET(x) offsetof(AudioEchoContext, x)
  48. #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
  49.  
  50. static const AVOption aecho_options[] = {
  51.     { "in_gain",  "set signal input gain",  OFFSET(in_gain),  AV_OPT_TYPE_FLOAT,  {.dbl=0.6}, 0, 1, A },
  52.     { "out_gain", "set signal output gain", OFFSET(out_gain), AV_OPT_TYPE_FLOAT,  {.dbl=0.3}, 0, 1, A },
  53.     { "delays",   "set list of signal delays", OFFSET(delays), AV_OPT_TYPE_STRING, {.str="1000"}, 0, 0, A },
  54.     { "decays",   "set list of signal decays", OFFSET(decays), AV_OPT_TYPE_STRING, {.str="0.5"}, 0, 0, A },
  55.     { NULL }
  56. };
  57.  
  58. AVFILTER_DEFINE_CLASS(aecho);
  59.  
  60. static void count_items(char *item_str, int *nb_items)
  61. {
  62.     char *p;
  63.  
  64.     *nb_items = 1;
  65.     for (p = item_str; *p; p++) {
  66.         if (*p == '|')
  67.             (*nb_items)++;
  68.     }
  69.  
  70. }
  71.  
  72. static void fill_items(char *item_str, int *nb_items, float *items)
  73. {
  74.     char *p, *saveptr = NULL;
  75.     int i, new_nb_items = 0;
  76.  
  77.     p = item_str;
  78.     for (i = 0; i < *nb_items; i++) {
  79.         char *tstr = av_strtok(p, "|", &saveptr);
  80.         p = NULL;
  81.         new_nb_items += sscanf(tstr, "%f", &items[i]) == 1;
  82.     }
  83.  
  84.     *nb_items = new_nb_items;
  85. }
  86.  
  87. static av_cold void uninit(AVFilterContext *ctx)
  88. {
  89.     AudioEchoContext *s = ctx->priv;
  90.  
  91.     av_freep(&s->delay);
  92.     av_freep(&s->decay);
  93.     av_freep(&s->samples);
  94.  
  95.     if (s->delayptrs)
  96.         av_freep(&s->delayptrs[0]);
  97.     av_freep(&s->delayptrs);
  98. }
  99.  
  100. static av_cold int init(AVFilterContext *ctx)
  101. {
  102.     AudioEchoContext *s = ctx->priv;
  103.     int nb_delays, nb_decays, i;
  104.  
  105.     if (!s->delays || !s->decays) {
  106.         av_log(ctx, AV_LOG_ERROR, "Missing delays and/or decays.\n");
  107.         return AVERROR(EINVAL);
  108.     }
  109.  
  110.     count_items(s->delays, &nb_delays);
  111.     count_items(s->decays, &nb_decays);
  112.  
  113.     s->delay = av_realloc_f(s->delay, nb_delays, sizeof(*s->delay));
  114.     s->decay = av_realloc_f(s->decay, nb_decays, sizeof(*s->decay));
  115.     if (!s->delay || !s->decay)
  116.         return AVERROR(ENOMEM);
  117.  
  118.     fill_items(s->delays, &nb_delays, s->delay);
  119.     fill_items(s->decays, &nb_decays, s->decay);
  120.  
  121.     if (nb_delays != nb_decays) {
  122.         av_log(ctx, AV_LOG_ERROR, "Number of delays %d differs from number of decays %d.\n", nb_delays, nb_decays);
  123.         return AVERROR(EINVAL);
  124.     }
  125.  
  126.     s->nb_echoes = nb_delays;
  127.     if (!s->nb_echoes) {
  128.         av_log(ctx, AV_LOG_ERROR, "At least one decay & delay must be set.\n");
  129.         return AVERROR(EINVAL);
  130.     }
  131.  
  132.     s->samples = av_realloc_f(s->samples, nb_delays, sizeof(*s->samples));
  133.     if (!s->samples)
  134.         return AVERROR(ENOMEM);
  135.  
  136.     for (i = 0; i < nb_delays; i++) {
  137.         if (s->delay[i] <= 0 || s->delay[i] > 90000) {
  138.             av_log(ctx, AV_LOG_ERROR, "delay[%d]: %f is out of allowed range: (0, 90000]\n", i, s->delay[i]);
  139.             return AVERROR(EINVAL);
  140.         }
  141.         if (s->decay[i] <= 0 || s->decay[i] > 1) {
  142.             av_log(ctx, AV_LOG_ERROR, "decay[%d]: %f is out of allowed range: (0, 1]\n", i, s->decay[i]);
  143.             return AVERROR(EINVAL);
  144.         }
  145.     }
  146.  
  147.     s->next_pts = AV_NOPTS_VALUE;
  148.  
  149.     av_log(ctx, AV_LOG_DEBUG, "nb_echoes:%d\n", s->nb_echoes);
  150.     return 0;
  151. }
  152.  
  153. static int query_formats(AVFilterContext *ctx)
  154. {
  155.     AVFilterChannelLayouts *layouts;
  156.     AVFilterFormats *formats;
  157.     static const enum AVSampleFormat sample_fmts[] = {
  158.         AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P,
  159.         AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP,
  160.         AV_SAMPLE_FMT_NONE
  161.     };
  162.  
  163.     layouts = ff_all_channel_layouts();
  164.     if (!layouts)
  165.         return AVERROR(ENOMEM);
  166.     ff_set_common_channel_layouts(ctx, layouts);
  167.  
  168.     formats = ff_make_format_list(sample_fmts);
  169.     if (!formats)
  170.         return AVERROR(ENOMEM);
  171.     ff_set_common_formats(ctx, formats);
  172.  
  173.     formats = ff_all_samplerates();
  174.     if (!formats)
  175.         return AVERROR(ENOMEM);
  176.     ff_set_common_samplerates(ctx, formats);
  177.  
  178.     return 0;
  179. }
  180.  
  181. #define MOD(a, b) (((a) >= (b)) ? (a) - (b) : (a))
  182.  
  183. #define ECHO(name, type, min, max)                                          \
  184. static void echo_samples_## name ##p(AudioEchoContext *ctx,                 \
  185.                                      uint8_t **delayptrs,                   \
  186.                                      uint8_t * const *src, uint8_t **dst,   \
  187.                                      int nb_samples, int channels)          \
  188. {                                                                           \
  189.     const double out_gain = ctx->out_gain;                                  \
  190.     const double in_gain = ctx->in_gain;                                    \
  191.     const int nb_echoes = ctx->nb_echoes;                                   \
  192.     const int max_samples = ctx->max_samples;                               \
  193.     int i, j, chan, av_uninit(index);                                       \
  194.                                                                             \
  195.     av_assert1(channels > 0); /* would corrupt delay_index */               \
  196.                                                                             \
  197.     for (chan = 0; chan < channels; chan++) {                               \
  198.         const type *s = (type *)src[chan];                                  \
  199.         type *d = (type *)dst[chan];                                        \
  200.         type *dbuf = (type *)delayptrs[chan];                               \
  201.                                                                             \
  202.         index = ctx->delay_index;                                           \
  203.         for (i = 0; i < nb_samples; i++, s++, d++) {                        \
  204.             double out, in;                                                 \
  205.                                                                             \
  206.             in = *s;                                                        \
  207.             out = in * in_gain;                                             \
  208.             for (j = 0; j < nb_echoes; j++) {                               \
  209.                 int ix = index + max_samples - ctx->samples[j];             \
  210.                 ix = MOD(ix, max_samples);                                  \
  211.                 out += dbuf[ix] * ctx->decay[j];                            \
  212.             }                                                               \
  213.             out *= out_gain;                                                \
  214.                                                                             \
  215.             *d = av_clipd(out, min, max);                                   \
  216.             dbuf[index] = in;                                               \
  217.                                                                             \
  218.             index = MOD(index + 1, max_samples);                            \
  219.         }                                                                   \
  220.     }                                                                       \
  221.     ctx->delay_index = index;                                               \
  222. }
  223.  
  224. ECHO(dbl, double,  -1.0,      1.0      )
  225. ECHO(flt, float,   -1.0,      1.0      )
  226. ECHO(s16, int16_t, INT16_MIN, INT16_MAX)
  227. ECHO(s32, int32_t, INT32_MIN, INT32_MAX)
  228.  
  229. static int config_output(AVFilterLink *outlink)
  230. {
  231.     AVFilterContext *ctx = outlink->src;
  232.     AudioEchoContext *s = ctx->priv;
  233.     float volume = 1.0;
  234.     int i;
  235.  
  236.     for (i = 0; i < s->nb_echoes; i++) {
  237.         s->samples[i] = s->delay[i] * outlink->sample_rate / 1000.0;
  238.         s->max_samples = FFMAX(s->max_samples, s->samples[i]);
  239.         volume += s->decay[i];
  240.     }
  241.  
  242.     if (s->max_samples <= 0) {
  243.         av_log(ctx, AV_LOG_ERROR, "Nothing to echo - missing delay samples.\n");
  244.         return AVERROR(EINVAL);
  245.     }
  246.     s->fade_out = s->max_samples;
  247.  
  248.     if (volume * s->in_gain * s->out_gain > 1.0)
  249.         av_log(ctx, AV_LOG_WARNING,
  250.                "out_gain %f can cause saturation of output\n", s->out_gain);
  251.  
  252.     switch (outlink->format) {
  253.     case AV_SAMPLE_FMT_DBLP: s->echo_samples = echo_samples_dblp; break;
  254.     case AV_SAMPLE_FMT_FLTP: s->echo_samples = echo_samples_fltp; break;
  255.     case AV_SAMPLE_FMT_S16P: s->echo_samples = echo_samples_s16p; break;
  256.     case AV_SAMPLE_FMT_S32P: s->echo_samples = echo_samples_s32p; break;
  257.     }
  258.  
  259.  
  260.     if (s->delayptrs)
  261.         av_freep(&s->delayptrs[0]);
  262.     av_freep(&s->delayptrs);
  263.  
  264.     return av_samples_alloc_array_and_samples(&s->delayptrs, NULL,
  265.                                               outlink->channels,
  266.                                               s->max_samples,
  267.                                               outlink->format, 0);
  268. }
  269.  
  270. static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
  271. {
  272.     AVFilterContext *ctx = inlink->dst;
  273.     AudioEchoContext *s = ctx->priv;
  274.     AVFrame *out_frame;
  275.  
  276.     if (av_frame_is_writable(frame)) {
  277.         out_frame = frame;
  278.     } else {
  279.         out_frame = ff_get_audio_buffer(inlink, frame->nb_samples);
  280.         if (!out_frame)
  281.             return AVERROR(ENOMEM);
  282.         av_frame_copy_props(out_frame, frame);
  283.     }
  284.  
  285.     s->echo_samples(s, s->delayptrs, frame->extended_data, out_frame->extended_data,
  286.                     frame->nb_samples, inlink->channels);
  287.  
  288.     if (frame != out_frame)
  289.         av_frame_free(&frame);
  290.  
  291.     s->next_pts = frame->pts + av_rescale_q(frame->nb_samples, (AVRational){1, inlink->sample_rate}, inlink->time_base);
  292.     return ff_filter_frame(ctx->outputs[0], out_frame);
  293. }
  294.  
  295. static int request_frame(AVFilterLink *outlink)
  296. {
  297.     AVFilterContext *ctx = outlink->src;
  298.     AudioEchoContext *s = ctx->priv;
  299.     int ret;
  300.  
  301.     ret = ff_request_frame(ctx->inputs[0]);
  302.  
  303.     if (ret == AVERROR_EOF && !ctx->is_disabled && s->fade_out) {
  304.         int nb_samples = FFMIN(s->fade_out, 2048);
  305.         AVFrame *frame;
  306.  
  307.         frame = ff_get_audio_buffer(outlink, nb_samples);
  308.         if (!frame)
  309.             return AVERROR(ENOMEM);
  310.         s->fade_out -= nb_samples;
  311.  
  312.         av_samples_set_silence(frame->extended_data, 0,
  313.                                frame->nb_samples,
  314.                                outlink->channels,
  315.                                frame->format);
  316.  
  317.         s->echo_samples(s, s->delayptrs, frame->extended_data, frame->extended_data,
  318.                         frame->nb_samples, outlink->channels);
  319.  
  320.         frame->pts = s->next_pts;
  321.         if (s->next_pts != AV_NOPTS_VALUE)
  322.             s->next_pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base);
  323.  
  324.         return ff_filter_frame(outlink, frame);
  325.     }
  326.  
  327.     return ret;
  328. }
  329.  
  330. static const AVFilterPad aecho_inputs[] = {
  331.     {
  332.         .name         = "default",
  333.         .type         = AVMEDIA_TYPE_AUDIO,
  334.         .filter_frame = filter_frame,
  335.     },
  336.     { NULL }
  337. };
  338.  
  339. static const AVFilterPad aecho_outputs[] = {
  340.     {
  341.         .name          = "default",
  342.         .request_frame = request_frame,
  343.         .config_props  = config_output,
  344.         .type          = AVMEDIA_TYPE_AUDIO,
  345.     },
  346.     { NULL }
  347. };
  348.  
  349. AVFilter avfilter_af_aecho = {
  350.     .name          = "aecho",
  351.     .description   = NULL_IF_CONFIG_SMALL("Add echoing to the audio."),
  352.     .query_formats = query_formats,
  353.     .priv_size     = sizeof(AudioEchoContext),
  354.     .priv_class    = &aecho_class,
  355.     .init          = init,
  356.     .uninit        = uninit,
  357.     .inputs        = aecho_inputs,
  358.     .outputs       = aecho_outputs,
  359. };
  360.