From 85ab9679dff777507b2b405af19dd930d6d1f75d Mon Sep 17 00:00:00 2001 From: Vitaly Ostrosablin <tmp6...@yandex.ru> Date: Sat, 6 Aug 2016 10:50:35 +0300 Subject: [PATCH] avfilter: add crystalizer filter.
Signed-off-by: Vitaly Ostrosablin <tmp6...@yandex.ru> --- Changelog | 1 + doc/filters.texi | 16 ++++ libavfilter/Makefile | 1 + libavfilter/af_crystalizer.c | 150 ++++++++++++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- tests/fate/filter-audio.mak | 5 ++ tests/ref/fate/filter-crystalizer | 25 +++++++ 8 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 libavfilter/af_crystalizer.c create mode 100644 tests/ref/fate/filter-crystalizer diff --git a/Changelog b/Changelog index 0f9b4cf..df0f2bb 100644 --- a/Changelog +++ b/Changelog @@ -12,6 +12,7 @@ version <next>: - 16-bit support in selectivecolor filter - OpenH264 decoder wrapper - MediaCodec hwaccel +- crystalizer audio filter version 3.1: diff --git a/doc/filters.texi b/doc/filters.texi index e950c14..ce9ca55 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -2110,6 +2110,22 @@ Set temperature degree in Celsius. This is the temperature of the environment. Default is 20. @end table +@section crystalizer + +Expands dynamic range of sound. Ported from Audacious's Crystalizer +plugin algorithm. + +The filter accepts the following option: + +@table @option +@item i +Sets the intensity of effect (default: 2.0). Must be in range between 0.0 +(unchanged sound) to 10.0 (maximum effect). + +@item c +Enable clipping. By default is enabled. +@end table + @section dcshift Apply a DC shift to the audio. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 65a831e..f8562e7 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -84,6 +84,7 @@ OBJS-$(CONFIG_EARWAX_FILTER) += af_earwax.o OBJS-$(CONFIG_EBUR128_FILTER) += f_ebur128.o OBJS-$(CONFIG_EQUALIZER_FILTER) += af_biquads.o OBJS-$(CONFIG_EXTRASTEREO_FILTER) += af_extrastereo.o +OBJS-$(CONFIG_CRYSTALIZER_FILTER) += af_crystalizer.o OBJS-$(CONFIG_FIREQUALIZER_FILTER) += af_firequalizer.o OBJS-$(CONFIG_FLANGER_FILTER) += af_flanger.o generate_wave_table.o OBJS-$(CONFIG_HIGHPASS_FILTER) += af_biquads.o diff --git a/libavfilter/af_crystalizer.c b/libavfilter/af_crystalizer.c new file mode 100644 index 0000000..72c1103 --- /dev/null +++ b/libavfilter/af_crystalizer.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2016 The FFmpeg Project + * + * 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 + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "audio.h" +#include "formats.h" + +typedef struct CrystalizerContext { + const AVClass *class; + float mult; + int clip; + AVFrame *prev; +} CrystalizerContext; + +#define OFFSET(x) offsetof(CrystalizerContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption crystalizer_options[] = { + { "i", "effect intensity", OFFSET(mult), AV_OPT_TYPE_FLOAT, {.dbl=2.0}, 0, 10, A }, + { "c", "enable clipping", OFFSET(clip), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, A }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(crystalizer); + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + AVFilterChannelLayouts *layouts = NULL; + int ret; + + if ((ret = ff_add_format (&formats, AV_SAMPLE_FMT_FLT )) < 0 || + (ret = ff_set_common_formats (ctx , formats )) < 0) + return 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_all_samplerates(); + return ff_set_common_samplerates(ctx, formats); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + CrystalizerContext *s = ctx->priv; + const float *src = (const float *)in->data[0]; + const float mult = s->mult; + AVFrame *out; + float *dst; + float *prv; + int n; + int c; + + + if (!s->prev) { + s->prev = ff_get_audio_buffer(inlink, 1); + if (!s->prev) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(s->prev, in); + } + 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); + } + dst = (float *)out->data[0]; + prv = (float *)s->prev->data[0]; + + for (n = 0; n < in->nb_samples; n++) { + for (c = 0; c < in->channels; c++) { + float current = src[n * (in->channels) + c]; + dst[n * (in->channels) + c] = current + (current - prv[c]) * mult; + prv[c] = current; + if (s->clip) { + dst[n * (in->channels) + c] = av_clipf(dst[n * (in->channels) + c], -1, 1); + } + } + } + + if (out != in) + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + CrystalizerContext *s = ctx->priv; + + av_frame_free(&s->prev); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_crystalizer = { + .name = "crystalizer", + .description = NULL_IF_CONFIG_SMALL("Expand dynamic range of audio."), + .query_formats = query_formats, + .priv_size = sizeof(CrystalizerContext), + .priv_class = &crystalizer_class, + .uninit = uninit, + .inputs = inputs, + .outputs = outputs, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index d0d491e..b051040 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -95,6 +95,7 @@ void avfilter_register_all(void) REGISTER_FILTER(CHANNELSPLIT, channelsplit, af); REGISTER_FILTER(CHORUS, chorus, af); REGISTER_FILTER(COMPAND, compand, af); + REGISTER_FILTER(CRYSTALIZER, crystalizer, af); REGISTER_FILTER(COMPENSATIONDELAY, compensationdelay, af); REGISTER_FILTER(DCSHIFT, dcshift, af); REGISTER_FILTER(DYNAUDNORM, dynaudnorm, af); diff --git a/libavfilter/version.h b/libavfilter/version.h index 9d21de4..f44edf8 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 49 +#define LIBAVFILTER_VERSION_MINOR 50 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/tests/fate/filter-audio.mak b/tests/fate/filter-audio.mak index d9db494..3d33548 100644 --- a/tests/fate/filter-audio.mak +++ b/tests/fate/filter-audio.mak @@ -114,6 +114,11 @@ fate-filter-extrastereo: tests/data/asynth-44100-2.wav fate-filter-extrastereo: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav fate-filter-extrastereo: CMD = framecrc -i $(SRC) -aframes 20 -af extrastereo=m=2 +FATE_AFILTER-$(call FILTERDEMDECENCMUX, CRYSTALIZER, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-crystalizer +fate-filter-crystalizer: tests/data/asynth-44100-2.wav +fate-filter-crystalizer: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav +fate-filter-crystalizer: CMD = framecrc -i $(SRC) -aframes 20 -af crystalizer=i=2 + FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, SILENCEREMOVE, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-silenceremove fate-filter-silenceremove: SRC = $(TARGET_SAMPLES)/audio-reference/divertimenti_2ch_96kHz_s24.wav fate-filter-silenceremove: CMD = framecrc -i $(SRC) -aframes 30 -af silenceremove=0:0:0:-1:0:-90dB diff --git a/tests/ref/fate/filter-crystalizer b/tests/ref/fate/filter-crystalizer new file mode 100644 index 0000000..b1a5873 --- /dev/null +++ b/tests/ref/fate/filter-crystalizer @@ -0,0 +1,25 @@ +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 44100 +#channel_layout 0: 3 +0, 0, 0, 1024, 4096, 0xfe26f8e5 +0, 1024, 1024, 1024, 4096, 0xa1d80690 +0, 2048, 2048, 1024, 4096, 0xdd250abe +0, 3072, 3072, 1024, 4096, 0xb89e021e +0, 4096, 4096, 1024, 4096, 0xb80aeeff +0, 5120, 5120, 1024, 4096, 0xf846fe13 +0, 6144, 6144, 1024, 4096, 0xf93bfefb +0, 7168, 7168, 1024, 4096, 0x808d09f2 +0, 8192, 8192, 1024, 4096, 0x432ae69d +0, 9216, 9216, 1024, 4096, 0x56b40106 +0, 10240, 10240, 1024, 4096, 0x3561eaff +0, 11264, 11264, 1024, 4096, 0xa87102be +0, 12288, 12288, 1024, 4096, 0xddc2efd7 +0, 13312, 13312, 1024, 4096, 0xc0fffb93 +0, 14336, 14336, 1024, 4096, 0x637cf499 +0, 15360, 15360, 1024, 4096, 0x5f0bfe57 +0, 16384, 16384, 1024, 4096, 0xd7d4f735 +0, 17408, 17408, 1024, 4096, 0xf12eea55 +0, 18432, 18432, 1024, 4096, 0xc1c7e629 +0, 19456, 19456, 1024, 4096, 0xd408eec7 -- 2.7.3
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel