Dana 20. 9. 2015. 06:28 osoba "Kyle Swanson" <k...@ylo.ph> napisala je: > > Signed-off-by: Kyle Swanson <k...@ylo.ph> > --- > doc/filters.texi | 19 ++++++ > libavfilter/Makefile | 1 + > libavfilter/af_tremolo.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++ > libavfilter/allfilters.c | 1 + > libavfilter/version.h | 2 +- > 5 files changed, 195 insertions(+), 1 deletion(-) > create mode 100644 libavfilter/af_tremolo.c > > diff --git a/doc/filters.texi b/doc/filters.texi > index 88cb3ce..5bbbaf0 100644 > --- a/doc/filters.texi > +++ b/doc/filters.texi > @@ -2568,6 +2568,25 @@ slope > Determine how steep is the filter's shelf transition. > @end table > > +@section tremolo > + > +Sinusoidal amplitude modulation. > + > +The filter accepts the following options: > + > +@table @option > +@item f > +Modulation frequency in Hertz. Modulation frequencies in the subharmonic range > +(20 Hz or lower) will result in a tremolo effect. > +This filter may also be used as a ring modulator by specifying > +a modulation frequency higher than 20 Hz. > +Range is 0.1 - 20000.0. Default value is 5.0 Hz. > + > +@item d > +Depth of modulation as a percentage. Range is 0.0 - 1.0. > +Default value is 0.5. > +@end table > + > @section volume > > Adjust the input audio volume. > diff --git a/libavfilter/Makefile b/libavfilter/Makefile > index 05effd6..45fca3b 100644 > --- a/libavfilter/Makefile > +++ b/libavfilter/Makefile > @@ -82,6 +82,7 @@ OBJS-$(CONFIG_SILENCEDETECT_FILTER) += af_silencedetect.o > OBJS-$(CONFIG_SILENCEREMOVE_FILTER) += af_silenceremove.o > OBJS-$(CONFIG_STEREOTOOLS_FILTER) += af_stereotools.o > OBJS-$(CONFIG_STEREOWIDEN_FILTER) += af_stereowiden.o > +OBJS-$(CONFIG_TREMOLO_FILTER) += af_tremolo.o generate_wave_table.o
nit: Should be after treble. > OBJS-$(CONFIG_TREBLE_FILTER) += af_biquads.o > OBJS-$(CONFIG_VOLUME_FILTER) += af_volume.o > OBJS-$(CONFIG_VOLUMEDETECT_FILTER) += af_volumedetect.o > diff --git a/libavfilter/af_tremolo.c b/libavfilter/af_tremolo.c > new file mode 100644 > index 0000000..7896127 > --- /dev/null > +++ b/libavfilter/af_tremolo.c > @@ -0,0 +1,173 @@ > +/* > + * Tremolo > + * Copyright (c) 2015 Kyle Swanson <k...@ylo.ph>. Some rights reserved. What this means? Better remove: Some rights reserved. > + * > + * 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 > + * Tremolo > + */ > + > +#include "libavutil/opt.h" > +#include "avfilter.h" > +#include "internal.h" > +#include "audio.h" > +#include "generate_wave_table.h" > + > +typedef struct TremoloContext { > + const AVClass *class; > + double freq; > + double depth; > + double *wave_table; > + int wave_table_index; > + int sample_rate; > +} TremoloContext; > + > +#define OFFSET(x) offsetof(TremoloContext, x) > +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM > + > +static const AVOption tremolo_options[] = { > + { "f", "set frequency in hertz", OFFSET(freq), AV_OPT_TYPE_DOUBLE, {.dbl = 5.0}, 0.1, 20000.0, FLAGS }, > + { "d", "set depth as percentage", OFFSET(depth), AV_OPT_TYPE_DOUBLE, {.dbl = 0.5}, 0.0, 1.0, FLAGS }, > + { NULL } > +}; > + > +AVFILTER_DEFINE_CLASS(tremolo); > + > +static float trem_env(AVFilterContext *ctx) > +{ > + TremoloContext *s = ctx->priv; > + float env = s->wave_table[s->wave_table_index]; > + s->wave_table_index++; > + if (s->wave_table_index >= s->sample_rate / s->freq) > + s->wave_table_index = 0; > + return 1.0 - (s->depth * env); > +} Shouldnt this use doubles instead of floats? > + > +static int filter_frame(AVFilterLink *inlink, AVFrame *in) > +{ > + AVFilterContext *ctx = inlink->dst; > + AVFilterLink *outlink = ctx->outputs[0]; > + AVFrame *out; > + > + if (av_frame_is_writable(in)) { > + out = in; > + } else { > + out = ff_get_audio_buffer(inlink, in->nb_samples); > + if (!out) { > + av_frame_free(&in); > + return AVERROR(ENOMEM); > + } > + av_frame_copy_props(out, in); > + } > + > + int channels = inlink->channels; > + int nb_samples = in->nb_samples; > + double *dst = (double *)out->data[0]; > + int n, c; > + > + for (n = 0; n < nb_samples; n++) { > + float env = trem_env(ctx); > + for (c = 0; c < channels; c++) { > + dst[c] *= env; Out can be zero if frame is not writable. So use: dst - src * env. > + } > + dst += channels; > + } > + > + if (in != out) > + av_frame_free(&in); > + > + return ff_filter_frame(outlink, out); > +} > + > +static int query_formats(AVFilterContext *ctx) > +{ > + AVFilterFormats *formats; > + AVFilterChannelLayouts *layouts; > + static const enum AVSampleFormat sample_fmts[] = { > + AV_SAMPLE_FMT_DBL, > + AV_SAMPLE_FMT_NONE > + }; > + int ret; > + > + layouts = ff_all_channel_counts(); > + if (!layouts) > + return AVERROR(ENOMEM); > + ret = ff_set_common_channel_layouts(ctx, layouts); > + if (ret < 0) > + return ret; > + > + formats = ff_make_format_list(sample_fmts); > + if (!formats) > + return AVERROR(ENOMEM); > + ret = ff_set_common_formats(ctx, formats); > + if (ret < 0) > + return ret; > + > + formats = ff_all_samplerates(); > + if (!formats) > + return AVERROR(ENOMEM); > + return ff_set_common_samplerates(ctx, formats); > +} > + > +static av_cold void uninit(AVFilterContext *ctx) > +{ > + TremoloContext *s = ctx->priv; > + av_free(s->wave_table); > +} > + > +static int config_input(AVFilterLink *inlink) > +{ > + AVFilterContext *ctx = inlink->dst; > + TremoloContext *s = ctx->priv; > + s->sample_rate = inlink->sample_rate; > + s->wave_table = av_malloc_array(sizeof(double), s->sample_rate / s->freq); > + ff_generate_wave_table(WAVE_SIN, AV_SAMPLE_FMT_DBL, s->wave_table, s->sample_rate / s->freq, 0.0, 1.0, 0.0); > + s->wave_table_index = 0; > + return 0; > +} > + > +static const AVFilterPad avfilter_af_tremolo_inputs[] = { > + { > + .name = "default", > + .type = AVMEDIA_TYPE_AUDIO, > + .config_props = config_input, > + .filter_frame = filter_frame, > + }, > + { NULL } > +}; > + > +static const AVFilterPad avfilter_af_tremolo_outputs[] = { > + { > + .name = "default", > + .type = AVMEDIA_TYPE_AUDIO, > + }, > + { NULL } > +}; > + > +AVFilter ff_af_tremolo = { > + .name = "tremolo", > + .description = NULL_IF_CONFIG_SMALL("Audio Tremolo."), > + .priv_size = sizeof(TremoloContext), > + .priv_class = &tremolo_class, > + .uninit = uninit, > + .query_formats = query_formats, > + .inputs = avfilter_af_tremolo_inputs, > + .outputs = avfilter_af_tremolo_outputs, > +}; > diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c > index cab4564..59ba5f5 100644 > --- a/libavfilter/allfilters.c > +++ b/libavfilter/allfilters.c > @@ -105,6 +105,7 @@ void avfilter_register_all(void) > REGISTER_FILTER(STEREOTOOLS, stereotools, af); > REGISTER_FILTER(STEREOWIDEN, stereowiden, af); > REGISTER_FILTER(TREBLE, treble, af); > + REGISTER_FILTER(TREMOLO, tremolo, af); > REGISTER_FILTER(VOLUME, volume, af); > REGISTER_FILTER(VOLUMEDETECT, volumedetect, af); > > diff --git a/libavfilter/version.h b/libavfilter/version.h > index e918184..9d44fd0 100644 > --- a/libavfilter/version.h > +++ b/libavfilter/version.h > @@ -30,7 +30,7 @@ > #include "libavutil/version.h" > > #define LIBAVFILTER_VERSION_MAJOR 6 > -#define LIBAVFILTER_VERSION_MINOR 5 > +#define LIBAVFILTER_VERSION_MINOR 6 > #define LIBAVFILTER_VERSION_MICRO 100 > > #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ > -- > 1.8.4 > Will do some minor changes, and apply after are questions I raised resolved. > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel