[FFmpeg-devel] [PATCH] lavfi: add earwax audio filter, ported from Sox
Stefano Sabatini
stefasab at gmail.com
Tue Nov 1 19:24:49 CET 2011
On date Tuesday 2011-11-01 03:23:51 +0100, Michael Niedermayer encoded:
> On Tue, Nov 01, 2011 at 01:51:32AM +0100, Stefano Sabatini wrote:
> > From: Mina Nagy Zaki <mnzaki at gmail.com>
> >
> > Signed-off-by: Stefano Sabatini <stefasab at gmail.com>
> > ---
> > doc/filters.texi | 10 +++
> > libavfilter/Makefile | 1 +
> > libavfilter/af_earwax.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++
> > libavfilter/allfilters.c | 1 +
> > 4 files changed, 171 insertions(+), 0 deletions(-)
> > create mode 100644 libavfilter/af_earwax.c
> >
> > diff --git a/doc/filters.texi b/doc/filters.texi
> > index f282b18..7085ae1 100644
> > --- a/doc/filters.texi
> > +++ b/doc/filters.texi
> > @@ -224,6 +224,16 @@ expressed in the form "[@var{c0} @var{c1} @var{c2} @var{c3} @var{c4} @var{c5}
> > @var{c6} @var{c7}]"
> > @end table
> >
> > + at section earwax
> > +
> > +Make audio easier to listen to on headphones. Adds `cues' to 44.1kHz
> > +stereo (i.e. audio CD format) audio so that when listened to on
> > +headphones the stereo image is moved from inside your head (standard
> > +for headphones) to outside and in front of the listener (standard for
> > +speakers).
> > +
> > +Ported from SoX.
> > +
> > @section ladspa
> >
> > Apply a LADSPA effect.
> > diff --git a/libavfilter/Makefile b/libavfilter/Makefile
> > index 040d565..583dd6d 100644
> > --- a/libavfilter/Makefile
> > +++ b/libavfilter/Makefile
> > @@ -28,6 +28,7 @@ OBJS-$(CONFIG_AFORMAT_FILTER) += af_aformat.o
> > OBJS-$(CONFIG_ANULL_FILTER) += af_anull.o
> > OBJS-$(CONFIG_ARESAMPLE_FILTER) += af_aresample.o
> > OBJS-$(CONFIG_ASHOWINFO_FILTER) += af_ashowinfo.o
> > +OBJS-$(CONFIG_EARWAX_FILTER) += af_earwax.o
> > OBJS-$(CONFIG_LADSPA_FILTER) += af_ladspa.o
> > OBJS-$(CONFIG_SOX_FILTER) += af_sox.o
> >
> > diff --git a/libavfilter/af_earwax.c b/libavfilter/af_earwax.c
> > new file mode 100644
> > index 0000000..21099e2
> > --- /dev/null
> > +++ b/libavfilter/af_earwax.c
> > @@ -0,0 +1,159 @@
> > +/*
> > + * Copyright (c) 2011 Mina Nagy Zaki
> > + * Copyright (c) 2000 Edward Beingessner And Sundry Contributors.
> > + * This source code is freely redistributable and may be used for any purpose.
> > + * This copyright notice must be maintained. Edward Beingessner And Sundry
> > + * Contributors are not responsible for the consequences of using this
> > + * software.
> > + *
> > + * 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
> > + * Stereo Widening Effect. Adds audio cues to move stereo image in
> > + * front of the listener. Adapted from the libsox earwax effect.
> > + */
> > +
> > +#include "libavutil/audioconvert.h"
> > +#include "avfilter.h"
> > +
> > +#define NUMTAPS 64
> > +
> > +static const int8_t filt[NUMTAPS] = {
> > +/* 30° 330° */
> > + 4, -6, /* 32 tap stereo FIR filter. */
> > + 4, -11, /* One side filters as if the */
> > + -1, -5, /* signal was from 30 degrees */
> > + 3, 3, /* from the ear, the other as */
> > + -2, 5, /* if 330 degrees. */
> > + -5, 0,
> > + 9, 1,
> > + 6, 3, /* Input */
> > + -4, -1, /* Left Right */
> > + -5, -3, /* __________ __________ */
> > + -2, -5, /* | | | | */
> > + -7, 1, /* .---| Hh,0(f) | | Hh,0(f) |---. */
> > + 6, -7, /* / |__________| |__________| \ */
> > + 30, -29, /* / \ / \ */
> > + 12, -3, /* / X \ */
> > + -11, 4, /* / / \ \ */
> > + -3, 7, /* ____V_____ __________V V__________ _____V____ */
> > + -20, 23, /* | | | | | | | | */
> > + 2, 0, /* | Hh,30(f) | | Hh,330(f)| | Hh,330(f)| | Hh,30(f) | */
> > + 1, -6, /* |__________| |__________| |__________| |__________| */
> > + -14, -5, /* \ ___ / \ ___ / */
> > + 15, -18, /* \ / \ / _____ \ / \ / */
> > + 6, 7, /* `->| + |<--' / \ `-->| + |<-' */
> > + 15, -10, /* \___/ _/ \_ \___/ */
> > + -14, 22, /* \ / \ / \ / */
> > + -7, -2, /* `--->| | | |<---' */
> > + -4, 9, /* \_/ \_/ */
> > + 6, -12, /* */
> > + 6, -6, /* Headphones */
> > + 0, -11,
> > + 0, -5,
> > + 4, 0};
> > +
> > +typedef struct {
> > + int16_t taps[NUMTAPS * 2];
> > +} EarwaxContext;
> > +
> > +static int query_formats(AVFilterContext *ctx)
> > +{
> > + AVFilterFormats *formats = NULL;
> > + avfilter_add_format(&formats, AV_SAMPLE_FMT_S16);
> > + avfilter_set_common_sample_formats(ctx, formats);
> > + formats = NULL;
> > + avfilter_add_format(&formats, AV_CH_LAYOUT_STEREO);
> > + avfilter_set_common_channel_layouts(ctx, formats);
> > + formats = NULL;
> > + avfilter_add_format(&formats, AVFILTER_PACKED);
> > + avfilter_set_common_packing_formats(ctx, formats);
> > +
> > + return 0;
> > +}
> > +
> > +static int config_input(AVFilterLink *inlink)
> > +{
> > + if (inlink->sample_rate != 44100) {
> > + av_log(inlink->dst, AV_LOG_ERROR,
> > + "The earwax filter only works for 44.1kHz audio. Insert "
> > + "a resample filter before this\n");
> > + return AVERROR(EINVAL);
> > + }
> > + return 0;
> > +}
>
> does the code check for stereo somewhere?
Yes, in query_formats().
> > +
> > +//FIXME: replace with DSPContext.scalarproduct_int16
> > +static inline int16_t *scalarproduct(int16_t *in, int16_t *endin, int16_t *out)
>
> const in, const endin
Fixed.
> > +{
> > + int32_t sample;
> > + int16_t j;
> > +
> > + while (in < endin) {
> > + sample = 0;
>
> 32 for rounding
I suppose you mean sample = 32.
>
>
> > + for (j = 0; j < NUMTAPS; j++)
> > + sample += in[j] * filt[j];
> > + *out = sample >> 6;
> > + out++; in++;
> > + }
>
> i assume this matches SOX
Yes, but SOX works in float32 so the code looks somehow different:
while (len--) { /* update taps and calculate output */
double output = 0;
for (i = NUMTAPS - 1; i; --i) {
p->tap[i] = p->tap[i - 1];
output += p->tap[i] * filt[i];
}
p->tap[0] = *ibuf++ / 64; /* scale output */
output += p->tap[0] * filt[0];
*obuf++ = SOX_ROUND_CLIP_COUNT(output, effp->clips);
}
> And for the record, this can be implemented with 2 FFTs but i am not
> sure it would beat a naive SIMD scalarproduct
>
> either way, patch LGTM otherwise
Updated.
--
FFmpeg = Foolish and Foolish Marvellous Peaceful Evangelical Guide
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0005-lavfi-add-earwax-audio-filter-ported-from-Sox.patch
Type: text/x-diff
Size: 9050 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20111101/92967e4b/attachment.bin>
More information about the ffmpeg-devel
mailing list