From patchwork Sat Aug 6 08:05:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?0J7RgdGC0YDQvtGB0LDQsdC70LjQvSDQktC40YLQsNC70LjQuQ==?= X-Patchwork-Id: 107 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.140.67 with SMTP id o64csp2094191vsd; Sat, 6 Aug 2016 01:05:57 -0700 (PDT) X-Received: by 10.28.144.5 with SMTP id s5mr6657122wmd.39.1470470757202; Sat, 06 Aug 2016 01:05:57 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id q190si8476221wmg.61.2016.08.06.01.05.56; Sat, 06 Aug 2016 01:05:57 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@yandex.ru; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE dis=NONE) header.from=yandex.ru Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 70D4968A791; Sat, 6 Aug 2016 11:05:37 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from forward9p.cmail.yandex.net (forward9p.cmail.yandex.net [87.250.241.194]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8439768A75A for ; Sat, 6 Aug 2016 11:05:23 +0300 (EEST) Received: from mxback1m.mail.yandex.net (mxback1m.mail.yandex.net [37.140.138.61]) by forward9p.cmail.yandex.net (Yandex) with ESMTP id 01EFF21C0D for ; Sat, 6 Aug 2016 11:05:30 +0300 (MSK) Received: from web4m.yandex.ru (web4m.yandex.ru [37.140.138.95]) by mxback1m.mail.yandex.net (nwsmtp/Yandex) with ESMTP id WxGLkUDPay-5TR01Piq; Sat, 06 Aug 2016 11:05:29 +0300 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1470470729; bh=LCERZDn4uq9A+ybkS56Qxw3yuONi3P1KQQkUztH9vCI=; h=From:To:Subject:Message-Id:Date; b=EWj8l4rmD7OFAg9FIjjkD4uU4QajEDwreoZP8Q/TGpb8d5b4N/eJvyLCmKxeHhL4A ERS9J83uZwoKgmbQAyNx7M9N2xYTyQpVueGmJnngMiTRf5KFuu2Br8wfA/svyX5CD+ xJqFRvHOqC/78pEaoM1d36ikaqubF4A636ys3qVE= Authentication-Results: mxback1m.mail.yandex.net; dkim=pass header.i=@yandex.ru Received: by web4m.yandex.ru with HTTP; Sat, 06 Aug 2016 11:05:29 +0300 From: =?utf-8?B?0J7RgdGC0YDQvtGB0LDQsdC70LjQvSDQktC40YLQsNC70LjQuQ==?= To: ffmpeg-devel@ffmpeg.org MIME-Version: 1.0 Message-Id: <15971470470729@web4m.yandex.ru> X-Mailer: Yamail [ http://yandex.ru ] 5.0 Date: Sat, 06 Aug 2016 11:05:29 +0300 X-Content-Filtered-By: Mailman/MimeDel 2.1.20 Subject: [FFmpeg-devel] [PATCH] avfilter: add crystalizer filter. X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From 85ab9679dff777507b2b405af19dd930d6d1f75d Mon Sep 17 00:00:00 2001 From: Vitaly Ostrosablin Date: Sat, 6 Aug 2016 10:50:35 +0300 Subject: [PATCH] avfilter: add crystalizer filter. Signed-off-by: Vitaly Ostrosablin --- 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 : - 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