diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2014-05-01 16:14:10 +0400 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-05-01 16:14:10 +0400 |
commit | 154d80eae70b73c683e70a157e73173aabb26a58 (patch) | |
tree | 98854991ca12fbd5ddaebaa641919b978507088a | |
parent | 7a0e689c4517d8e6ccec6027354bd827965a9ba2 (diff) | |
parent | 1c0210c7981b6a61043d9171f506b435ff5a1f5e (diff) |
Merge commit '1c0210c7981b6a61043d9171f506b435ff5a1f5e'
* commit '1c0210c7981b6a61043d9171f506b435ff5a1f5e':
lavfi: add Bauer stereo-to-binaural audio filter
Conflicts:
Changelog
configure
doc/filters.texi
libavfilter/Makefile
libavfilter/allfilters.c
libavfilter/version.h
Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | Changelog | 1 | ||||
-rwxr-xr-x | configure | 4 | ||||
-rw-r--r-- | doc/filters.texi | 30 | ||||
-rw-r--r-- | libavfilter/Makefile | 1 | ||||
-rw-r--r-- | libavfilter/af_bs2b.c | 222 | ||||
-rw-r--r-- | libavfilter/allfilters.c | 1 | ||||
-rw-r--r-- | libavfilter/version.h | 2 |
7 files changed, 260 insertions, 1 deletions
@@ -21,6 +21,7 @@ version <next>: - Magic Lantern Video (MLV) demuxer - On2 AVC (Audio for Video) decoder - support for decoding through DXVA2 in ffmpeg +- libbs2b-based stereo-to-binaural audio filter version 2.2: @@ -199,6 +199,7 @@ External library support: --enable-libaacplus enable AAC+ encoding via libaacplus [no] --enable-libass enable libass subtitles rendering [no] --enable-libbluray enable BluRay reading using libbluray [no] + --enable-libbs2b enable bs2b DSP library [no] --enable-libcaca enable textual display using libcaca --enable-libcelt enable CELT decoding via libcelt [no] --enable-libcdio enable audio CD grabbing with libcdio @@ -1311,6 +1312,7 @@ EXTERNAL_LIBRARY_LIST=" libaacplus libass libbluray + libbs2b libcaca libcdio libcelt @@ -2464,6 +2466,7 @@ atempo_filter_select="rdft" azmq_filter_deps="libzmq" blackframe_filter_deps="gpl" boxblur_filter_deps="gpl" +bs2b_filter_deps="libbs2b" colormatrix_filter_deps="gpl" cropdetect_filter_deps="gpl" dctdnoiz_filter_deps="avcodec" @@ -4604,6 +4607,7 @@ enabled libiec61883 && require libiec61883 libiec61883/iec61883.h iec61883 enabled libaacplus && require "libaacplus >= 2.0.0" aacplus.h aacplusEncOpen -laacplus enabled libass && require_pkg_config libass ass/ass.h ass_library_init enabled libbluray && require_pkg_config libbluray libbluray/bluray.h bd_open +enabled libbs2b && require_pkg_config libbs2b bs2b.h bs2b_open enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && { check_lib celt/celt.h celt_decoder_create_custom -lcelt0 || die "ERROR: libcelt must be installed and version must be >= 0.11.0."; } diff --git a/doc/filters.texi b/doc/filters.texi index d53f645a55..93548e1a7a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1206,6 +1206,36 @@ Apply a biquad IIR filter with the given coefficients. Where @var{b0}, @var{b1}, @var{b2} and @var{a0}, @var{a1}, @var{a2} are the numerator and denominator coefficients respectively. +@section bs2b +Bauer stereo to binaural transformation, which improves headphone listening of +stereo audio records. + +It accepts the following parameters: +@table @option + +@item profile +Pre-defined crossfeed level. +@table @option + +@item default +Default level (fcut=700, feed=50). + +@item cmoy +Chu Moy circuit (fcut=700, feed=60). + +@item jmeier +Jan Meier circuit (fcut=650, feed=95). + +@end table + +@item fcut +Cut frequency (in Hz). + +@item feed +Feed level (in Hz). + +@end table + @section channelmap Remap input channels to new locations. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 7e66c91668..65786cf0c1 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -85,6 +85,7 @@ OBJS-$(CONFIG_BANDPASS_FILTER) += af_biquads.o OBJS-$(CONFIG_BANDREJECT_FILTER) += af_biquads.o OBJS-$(CONFIG_BASS_FILTER) += af_biquads.o 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_COMPAND_FILTER) += af_compand.o diff --git a/libavfilter/af_bs2b.c b/libavfilter/af_bs2b.c new file mode 100644 index 0000000000..5c8e8e5dd8 --- /dev/null +++ b/libavfilter/af_bs2b.c @@ -0,0 +1,222 @@ +/* + * 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 + * Bauer stereo-to-binaural filter + */ + +#include <bs2b.h> + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "audio.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" + +typedef struct Bs2bContext { + const AVClass *class; + + int profile; + int fcut; + int feed; + + t_bs2bdp bs2bp; + + void (*filter)(t_bs2bdp bs2bdp, uint8_t *sample, int n); +} Bs2bContext; + +#define OFFSET(x) offsetof(Bs2bContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM + +static const AVOption options[] = { + { "profile", "Apply a pre-defined crossfeed level", + OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = BS2B_DEFAULT_CLEVEL }, 0, INT_MAX, A, "profile" }, + { "default", "default profile", 0, AV_OPT_TYPE_CONST, { .i64 = BS2B_DEFAULT_CLEVEL }, 0, 0, A, "profile" }, + { "cmoy", "Chu Moy circuit", 0, AV_OPT_TYPE_CONST, { .i64 = BS2B_CMOY_CLEVEL }, 0, 0, A, "profile" }, + { "jmeier", "Jan Meier circuit", 0, AV_OPT_TYPE_CONST, { .i64 = BS2B_JMEIER_CLEVEL }, 0, 0, A, "profile" }, + { "fcut", "Set cut frequency (in Hz)", + OFFSET(fcut), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BS2B_MAXFCUT, A }, + { "feed", "Set feed level (in Hz)", + OFFSET(feed), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BS2B_MAXFEED, A }, + { NULL }, +}; + +static const AVClass bs2b_class = { + .class_name = "bs2b filter", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static av_cold int init(AVFilterContext *ctx) +{ + Bs2bContext *bs2b = ctx->priv; + + if (!(bs2b->bs2bp = bs2b_open())) + return AVERROR(ENOMEM); + + bs2b_set_level(bs2b->bs2bp, bs2b->profile); + + if (bs2b->fcut) + bs2b_set_level_fcut(bs2b->bs2bp, bs2b->fcut); + + if (bs2b->feed) + bs2b_set_level_feed(bs2b->bs2bp, bs2b->feed); + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + Bs2bContext *bs2b = ctx->priv; + + if (bs2b->bs2bp) + bs2b_close(bs2b->bs2bp); +} + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + AVFilterChannelLayouts *layouts = NULL; + + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_U8, + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_S32, + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_DBL, + AV_SAMPLE_FMT_NONE, + }; + + if (ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO) != 0) + return AVERROR(ENOMEM); + ff_set_common_channel_layouts(ctx, layouts); + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ff_set_common_formats(ctx, formats); + + formats = ff_all_samplerates(); + if (!formats) + return AVERROR(ENOMEM); + ff_set_common_samplerates(ctx, formats); + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + int ret; + AVFrame *out_frame; + + Bs2bContext *bs2b = inlink->dst->priv; + AVFilterLink *outlink = inlink->dst->outputs[0]; + + if (av_frame_is_writable(frame)) { + out_frame = frame; + } else { + out_frame = ff_get_audio_buffer(inlink, frame->nb_samples); + if (!out_frame) + return AVERROR(ENOMEM); + av_frame_copy(out_frame, frame); + ret = av_frame_copy_props(out_frame, frame); + if (ret < 0) { + av_frame_free(&out_frame); + av_frame_free(&frame); + return ret; + } + } + + bs2b->filter(bs2b->bs2bp, out_frame->extended_data[0], out_frame->nb_samples); + + if (frame != out_frame) + av_frame_free(&frame); + + return ff_filter_frame(outlink, out_frame); +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + Bs2bContext *bs2b = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + + int srate = inlink->sample_rate; + + switch (inlink->format) { + case AV_SAMPLE_FMT_U8: + bs2b->filter = bs2b_cross_feed_u8; + break; + case AV_SAMPLE_FMT_S16: + bs2b->filter = bs2b_cross_feed_s16; + break; + case AV_SAMPLE_FMT_S32: + bs2b->filter = bs2b_cross_feed_s32; + break; + case AV_SAMPLE_FMT_FLT: + bs2b->filter = bs2b_cross_feed_f; + break; + case AV_SAMPLE_FMT_DBL: + bs2b->filter = bs2b_cross_feed_d; + break; + default: + return AVERROR_BUG; + } + + if ((srate < BS2B_MINSRATE) || (srate > BS2B_MAXSRATE)) + return AVERROR(ENOSYS); + + bs2b_set_srate(bs2b->bs2bp, srate); + + return 0; +} + +static const AVFilterPad bs2b_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad bs2b_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_af_bs2b = { + .name = "bs2b", + .description = NULL_IF_CONFIG_SMALL("Bauer stereo-to-binaural filter."), + .query_formats = query_formats, + .priv_size = sizeof(Bs2bContext), + .priv_class = &bs2b_class, + .init = init, + .uninit = uninit, + .inputs = bs2b_inputs, + .outputs = bs2b_outputs, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index e351eac5ff..22d643d3e1 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -80,6 +80,7 @@ void avfilter_register_all(void) REGISTER_FILTER(BANDREJECT, bandreject, af); REGISTER_FILTER(BASS, bass, af); REGISTER_FILTER(BIQUAD, biquad, af); + REGISTER_FILTER(BS2B, bs2b, af); REGISTER_FILTER(CHANNELMAP, channelmap, af); REGISTER_FILTER(CHANNELSPLIT, channelsplit, af); REGISTER_FILTER(COMPAND, compand, af); diff --git a/libavfilter/version.h b/libavfilter/version.h index 1540d55bb0..7a6321e53e 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 4 -#define LIBAVFILTER_VERSION_MINOR 4 +#define LIBAVFILTER_VERSION_MINOR 5 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ |