On Sun, Apr 05, 2015 at 05:50:47PM +0000, Paul B Mahol wrote: > Signed-off-by: Paul B Mahol <one...@gmail.com> > --- > doc/filters.texi | 32 ++++ > libavfilter/Makefile | 1 + > libavfilter/af_chorus.c | 370 > +++++++++++++++++++++++++++++++++++++++++++++++ > libavfilter/allfilters.c | 1 + > 4 files changed, 404 insertions(+) > create mode 100644 libavfilter/af_chorus.c > > diff --git a/doc/filters.texi b/doc/filters.texi > index b75ce5a..4926d1c 100644 > --- a/doc/filters.texi > +++ b/doc/filters.texi > @@ -1320,6 +1320,38 @@ front_center.wav -map '[LFE]' lfe.wav -map '[SL]' > side_left.wav -map '[SR]' > side_right.wav > @end example > > +@section chorus > +Add a chorus effect to the audio. > +Can make a single vocal sound like a chorus, but can also be applied to > instrumentation. > + > +Chorus resembles an echo effect with a short delay, but whereas with echo > the delay is > +constant, with chorus, it is varied using using sinusoidal or triangular > modulation. > +The modulation depth defines the range the modulated delay is played before > or after > +the delay. Hence the delayed sound will sound slower or faster, that is the > delayed > +sound tuned around the original one, like in a chorus where some vocals are > slightly > +off key. > + > +It accepts the following parameters: > +@table @option > +@item in_gain > +Set input gain. Default is 0.4. > + > +@item out_gain > +Set output gain. Default is 0.4. > + > +@item delays > +Set delays. > + > +@item decays > +Set decays. > + > +@item speeds > +Set speeds. > + > +@item depths > +Set depths. > +@end table > +
please add an example to the documentation > @section compand > Compress or expand the audio's dynamic range. > > diff --git a/libavfilter/Makefile b/libavfilter/Makefile > index 73e7adf..48cee50 100644 > --- a/libavfilter/Makefile > +++ b/libavfilter/Makefile > @@ -64,6 +64,7 @@ OBJS-$(CONFIG_BIQUAD_FILTER) += af_biquads.o > OBJS-$(CONFIG_BS2B_FILTER) += af_bs2b.o > OBJS-$(CONFIG_CHANNELMAP_FILTER) += af_channelmap.o > OBJS-$(CONFIG_CHANNELSPLIT_FILTER) += af_channelsplit.o > +OBJS-$(CONFIG_CHORUS_FILTER) += af_chorus.o > generate_wave_table.o > OBJS-$(CONFIG_COMPAND_FILTER) += af_compand.o > OBJS-$(CONFIG_DCSHIFT_FILTER) += af_dcshift.o > OBJS-$(CONFIG_EARWAX_FILTER) += af_earwax.o > diff --git a/libavfilter/af_chorus.c b/libavfilter/af_chorus.c > new file mode 100644 > index 0000000..6daf571 > --- /dev/null > +++ b/libavfilter/af_chorus.c > @@ -0,0 +1,370 @@ > +/* > + * Copyright (c) 1998 Juergen Mueller And Sundry Contributors > + * This source code is freely redistributable and may be used for > + * any purpose. This copyright notice must be maintained. > + * Juergen Mueller And Sundry Contributors are not responsible for > + * the consequences of using this software. > + * > + * Copyright (c) 2015 Paul B Mahol > + * > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > + */ > + > +/** > + * @file > + * chorus audio filter > + */ > + > +#include "libavutil/avstring.h" > +#include "libavutil/opt.h" > +#include "audio.h" > +#include "avfilter.h" > +#include "internal.h" > +#include "generate_wave_table.h" > + > +typedef struct ChorusContext { > + const AVClass *class; > + float in_gain, out_gain; > + char *delays_str; > + char *decays_str; > + char *speeds_str; > + char *depths_str; > + float *delays; > + float *decays; > + float *speeds; > + float *depths; > + uint8_t **chorusbuf; > + int **phase; > + int *length; > + int32_t **lookup_table; > + int *counter; > + int num_chorus; > + int max_samples; > + int channels; > + int modulation; > + int fade_out; > + int64_t next_pts; > +} ChorusContext; > + > +#define OFFSET(x) offsetof(ChorusContext, x) > +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM > + > +static const AVOption chorus_options[] = { > + { "in_gain", "set input gain", OFFSET(in_gain), AV_OPT_TYPE_FLOAT, > {.dbl=.4}, 0, 1, A }, > + { "out_gain", "set output gain", OFFSET(out_gain), AV_OPT_TYPE_FLOAT, > {.dbl=.4}, 0, 1, A }, > + { "delays", "set delays", OFFSET(delays_str), AV_OPT_TYPE_STRING, > {.str=NULL}, 0, 0, A }, > + { "decays", "set decays", OFFSET(decays_str), AV_OPT_TYPE_STRING, > {.str=NULL}, 0, 0, A }, > + { "speeds", "set speeds", OFFSET(speeds_str), AV_OPT_TYPE_STRING, > {.str=NULL}, 0, 0, A }, > + { "depths", "set depths", OFFSET(depths_str), AV_OPT_TYPE_STRING, > {.str=NULL}, 0, 0, A }, > + { NULL } > +}; > + > +AVFILTER_DEFINE_CLASS(chorus); > + > +static void count_items(char *item_str, int *nb_items) > +{ > + char *p; > + > + *nb_items = 1; > + for (p = item_str; *p; p++) { > + if (*p == '|') > + (*nb_items)++; > + } > + > +} > + > +static void fill_items(char *item_str, int *nb_items, float *items) > +{ > + char *p, *saveptr = NULL; > + int i, new_nb_items = 0; > + > + p = item_str; > + for (i = 0; i < *nb_items; i++) { > + char *tstr = av_strtok(p, "|", &saveptr); > + p = NULL; > + new_nb_items += sscanf(tstr, "%f", &items[i]) == 1; > + } > + > + *nb_items = new_nb_items; > +} > + > +static av_cold int init(AVFilterContext *ctx) > +{ > + ChorusContext *s = ctx->priv; > + int nb_delays, nb_decays, nb_speeds, nb_depths; > + > + if (!s->delays_str || !s->decays_str || !s->speeds_str || !s->depths_str) > + return AVERROR(EINVAL); > + > + count_items(s->delays_str, &nb_delays); > + count_items(s->decays_str, &nb_decays); > + count_items(s->speeds_str, &nb_speeds); > + count_items(s->depths_str, &nb_depths); > + > + s->delays = av_realloc_f(s->delays, nb_delays, sizeof(*s->delays)); > + s->decays = av_realloc_f(s->decays, nb_decays, sizeof(*s->decays)); > + s->speeds = av_realloc_f(s->speeds, nb_speeds, sizeof(*s->speeds)); > + s->depths = av_realloc_f(s->depths, nb_depths, sizeof(*s->depths)); > + > + if (!s->delays || !s->decays || !s->speeds || !s->depths) > + return AVERROR(ENOMEM); > + > + fill_items(s->delays_str, &nb_delays, s->delays); > + fill_items(s->decays_str, &nb_decays, s->decays); > + fill_items(s->speeds_str, &nb_speeds, s->speeds); > + fill_items(s->depths_str, &nb_depths, s->depths); > + > + if (nb_delays != nb_decays && nb_delays != nb_speeds && nb_delays != > nb_depths) > + return AVERROR(EINVAL); please add error messages to the cases where the user has provided invalid parameters so that she knows what is wrong [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB If you think the mosad wants you dead since a long time then you are either wrong or dead since a long time.
signature.asc
Description: Digital signature
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel