| https://bugs.gentoo.org/539680 |
| |
| From: Luca Barbato <lu_zero@gentoo.org> |
| Description: lavr: Add a libavresample based rate plugin |
| Date: Mon, 14 Apr 2014 10:01:07 +0200 |
| |
| Provide lavcrate compatibility. |
| |
| Index: alsa-plugins-1.0.28/configure.ac |
| =================================================================== |
| --- alsa-plugins-1.0.28.orig/configure.ac |
| +++ alsa-plugins-1.0.28/configure.ac |
| @@ -66,7 +66,7 @@ if test "$use_maemo_rm" = "yes"; then |
| fi |
| |
| AC_ARG_ENABLE([avcodec], |
| - AS_HELP_STRING([--disable-avcodec], [Don't build plugins depending on avcodec (a52)])) |
| + AS_HELP_STRING([--disable-avcodec], [Do not build plugins depending on avcodec (a52)])) |
| |
| if test "x$enable_avcodec" != "xno"; then |
| PKG_CHECK_MODULES(AVCODEC, [libavcodec libavutil], [HAVE_AVCODEC=yes], [HAVE_AVCODEC=no]) |
| @@ -101,6 +101,10 @@ if test $HAVE_AVCODEC = yes; then |
| if test -z "$AVCODEC_HEADER"; then |
| HAVE_AVCODEC=no |
| fi |
| + SAVE_LIBS=$LIBS |
| + LIBS="$LIBS $AVCODEC_LIBS" |
| + AC_CHECK_FUNCS([av_resample_init]) |
| + LIBS=$SAVE_LIBS |
| fi |
| |
| AM_CONDITIONAL(HAVE_AVCODEC, test x$HAVE_AVCODEC = xyes) |
| @@ -108,6 +112,18 @@ AC_SUBST(AVCODEC_CFLAGS) |
| AC_SUBST(AVCODEC_LIBS) |
| AC_SUBST(AVCODEC_HEADER) |
| |
| +AC_ARG_ENABLE([avresample], |
| + AS_HELP_STRING([--disable-avresample], [Do not build plugins depending on avcodec (lavrate)])) |
| + |
| +if test "x$enable_avresample" != "xno"; then |
| + PKG_CHECK_MODULES(AVRESAMPLE, [libavresample libavutil], [HAVE_AVRESAMPLE=yes], [HAVE_AVRESAMPLE=no]) |
| +fi |
| + |
| +AM_CONDITIONAL(HAVE_AVRESAMPLE, test x$HAVE_AVCODEC = xyes) |
| +AC_SUBST(AVRESAMPLE_CFLAGS) |
| +AC_SUBST(AVRESAMPLE_LIBS) |
| +AC_SUBST(AVRESAMPLE_HEADER) |
| + |
| PKG_CHECK_MODULES(speexdsp, [speexdsp >= 1.2], [HAVE_SPEEXDSP="yes"], [HAVE_SPEEXDSP=""]) |
| AM_CONDITIONAL(HAVE_SPEEXDSP, test "$HAVE_SPEEXDSP" = "yes") |
| |
| @@ -181,7 +197,7 @@ AC_OUTPUT([ |
| mix/Makefile |
| rate/Makefile |
| a52/Makefile |
| - rate-lavc/Makefile |
| + rate-lavr/Makefile |
| maemo/Makefile |
| doc/Makefile |
| usb_stream/Makefile |
| Index: alsa-plugins-1.0.28/Makefile.am |
| =================================================================== |
| --- alsa-plugins-1.0.28.orig/Makefile.am |
| +++ alsa-plugins-1.0.28/Makefile.am |
| @@ -9,8 +9,14 @@ if HAVE_SAMPLERATE |
| SUBDIRS += rate |
| endif |
| if HAVE_AVCODEC |
| +SUBDIRS += a52 |
| +if !HAVE_AVRESAMPLE |
| SUBDIRS += a52 rate-lavc |
| endif |
| +endif |
| +if HAVE_AVRESAMPLE |
| +SUBDIRS += rate-lavr |
| +endif |
| if HAVE_MAEMO_PLUGIN |
| SUBDIRS += maemo |
| endif |
| Index: alsa-plugins-1.0.28/rate-lavr/Makefile.am |
| =================================================================== |
| --- /dev/null |
| +++ alsa-plugins-1.0.28/rate-lavr/Makefile.am |
| @@ -0,0 +1,22 @@ |
| +asound_module_rate_lavr_LTLIBRARIES = libasound_module_rate_lavr.la |
| + |
| +asound_module_rate_lavrdir = @ALSA_PLUGIN_DIR@ |
| + |
| +AM_CFLAGS = -Wall -g @ALSA_CFLAGS@ @AVRESAMPLE_CFLAGS@ |
| +AM_LDFLAGS = -module -avoid-version -export-dynamic -no-undefined $(LDFLAGS_NOUNDEFINED) |
| + |
| +libasound_module_rate_lavr_la_SOURCES = rate_lavr.c |
| +libasound_module_rate_lavr_la_LIBADD = @ALSA_LIBS@ @AVRESAMPLE_LIBS@ |
| + |
| + |
| +install-exec-hook: |
| + rm -f $(DESTDIR)@ALSA_PLUGIN_DIR@/libasound_module_rate_lavcrate*.so |
| + $(LN_S) libasound_module_rate_lavr.so $(DESTDIR)@ALSA_PLUGIN_DIR@/libasound_module_rate_lavcrate.so |
| + $(LN_S) libasound_module_rate_lavr.so $(DESTDIR)@ALSA_PLUGIN_DIR@/libasound_module_rate_lavcrate_higher.so |
| + $(LN_S) libasound_module_rate_lavr.so $(DESTDIR)@ALSA_PLUGIN_DIR@/libasound_module_rate_lavcrate_high.so |
| + $(LN_S) libasound_module_rate_lavr.so $(DESTDIR)@ALSA_PLUGIN_DIR@/libasound_module_rate_lavcrate_fast.so |
| + $(LN_S) libasound_module_rate_lavr.so $(DESTDIR)@ALSA_PLUGIN_DIR@/libasound_module_rate_lavcrate_faster.so |
| + |
| +uninstall-hook: |
| + rm -f $(DESTDIR)@ALSA_PLUGIN_DIR@/libasound_module_rate_lavcrate*.so |
| + rm -f $(DESTDIR)@ALSA_PLUGIN_DIR@/libasound_module_rate_lavr*.so |
| Index: alsa-plugins-1.0.28/rate-lavr/rate_lavr.c |
| =================================================================== |
| --- /dev/null |
| +++ alsa-plugins-1.0.28/rate-lavr/rate_lavr.c |
| @@ -0,0 +1,227 @@ |
| +/* |
| + * Rate converter plugin using libavresample |
| + * Copyright (c) 2014 by Anton Khirnov |
| + * |
| + * This library 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. |
| + * |
| + * This library 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. |
| + */ |
| + |
| +#include <stdio.h> |
| +#include <alsa/asoundlib.h> |
| +#include <alsa/pcm_rate.h> |
| + |
| +#include <libavresample/avresample.h> |
| +#include <libavutil/channel_layout.h> |
| +#include <libavutil/opt.h> |
| +#include <libavutil/mathematics.h> |
| +#include <libavutil/samplefmt.h> |
| + |
| + |
| +static int filter_size = 16; |
| +static int phase_shift = 10; /* auto-adjusts */ |
| +static double cutoff = 0; /* auto-adjusts */ |
| + |
| +struct rate_src { |
| + AVAudioResampleContext *avr; |
| + |
| + int in_rate; |
| + int out_rate; |
| + unsigned int channels; |
| +}; |
| + |
| +static snd_pcm_uframes_t input_frames(void *obj, snd_pcm_uframes_t frames) |
| +{ |
| + return frames; |
| +} |
| + |
| +static snd_pcm_uframes_t output_frames(void *obj, snd_pcm_uframes_t frames) |
| +{ |
| + return frames; |
| +} |
| + |
| +static void pcm_src_free(void *obj) |
| +{ |
| + struct rate_src *rate = obj; |
| + avresample_free(&rate->avr); |
| +} |
| + |
| +static int pcm_src_init(void *obj, snd_pcm_rate_info_t *info) |
| +{ |
| + struct rate_src *rate = obj; |
| + int i, ir, or; |
| + |
| + if (!rate->avr || rate->channels != info->channels) { |
| + int ret; |
| + |
| + pcm_src_free(rate); |
| + rate->channels = info->channels; |
| + ir = rate->in_rate = info->in.rate; |
| + or = rate->out_rate = info->out.rate; |
| + i = av_gcd(or, ir); |
| + if (or > ir) { |
| + phase_shift = or/i; |
| + } else { |
| + phase_shift = ir/i; |
| + } |
| + if (cutoff <= 0.0) { |
| + cutoff = 1.0 - 1.0/filter_size; |
| + if (cutoff < 0.80) |
| + cutoff = 0.80; |
| + } |
| + |
| + rate->avr = avresample_alloc_context(); |
| + if (!rate->avr) |
| + return -ENOMEM; |
| + |
| + av_opt_set_int(rate->avr, "in_sample_rate", info->in.rate, 0); |
| + av_opt_set_int(rate->avr, "out_sample_rate", info->out.rate, 0); |
| + av_opt_set_int(rate->avr, "in_sample_format", AV_SAMPLE_FMT_S16, 0); |
| + av_opt_set_int(rate->avr, "out_sample_format", AV_SAMPLE_FMT_S16, 0); |
| + av_opt_set_int(rate->avr, "in_channel_layout", av_get_default_channel_layout(rate->channels), 0); |
| + av_opt_set_int(rate->avr, "out_channel_layout", av_get_default_channel_layout(rate->channels), 0); |
| + |
| + av_opt_set_int(rate->avr, "filter_size", filter_size, 0); |
| + av_opt_set_int(rate->avr, "phase_shift", phase_shift, 0); |
| + av_opt_set_double(rate->avr, "cutoff", cutoff, 0); |
| + |
| + ret = avresample_open(rate->avr); |
| + if (ret < 0) { |
| + avresample_free(&rate->avr); |
| + return -EINVAL; |
| + } |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +static int pcm_src_adjust_pitch(void *obj, snd_pcm_rate_info_t *info) |
| +{ |
| + struct rate_src *rate = obj; |
| + |
| + if (info->out.rate != rate->out_rate || info->in.rate != rate->in_rate) |
| + pcm_src_init(obj, info); |
| + return 0; |
| +} |
| + |
| +static void pcm_src_reset(void *obj) |
| +{ |
| + struct rate_src *rate = obj; |
| + |
| + if (rate->avr) { |
| + avresample_close(rate->avr); |
| + avresample_open(rate->avr); |
| + } |
| +} |
| + |
| +static void pcm_src_convert_s16(void *obj, int16_t *dst, unsigned int |
| + dst_frames, const int16_t *src, unsigned int src_frames) |
| +{ |
| + struct rate_src *rate = obj; |
| + int consumed = 0, chans=rate->channels, ret=0, i; |
| + int total_in = avresample_get_delay(rate->avr) + src_frames; |
| + |
| + ret = avresample_convert(rate->avr, &dst, dst_frames * chans * 2, dst_frames, |
| + &src, src_frames * chans * 2, src_frames); |
| + |
| + avresample_set_compensation(rate->avr, |
| + total_in - src_frames > filter_size ? 0 : 1, src_frames); |
| +} |
| + |
| +static void pcm_src_close(void *obj) |
| +{ |
| + pcm_src_free(obj); |
| +} |
| + |
| +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010002 |
| +static int get_supported_rates(void *obj, unsigned int *rate_min, |
| + unsigned int *rate_max) |
| +{ |
| + *rate_min = *rate_max = 0; /* both unlimited */ |
| + return 0; |
| +} |
| + |
| +static void dump(void *obj, snd_output_t *out) |
| +{ |
| + snd_output_printf(out, "Converter: libavr\n"); |
| +} |
| +#endif |
| + |
| +static snd_pcm_rate_ops_t pcm_src_ops = { |
| + .close = pcm_src_close, |
| + .init = pcm_src_init, |
| + .free = pcm_src_free, |
| + .adjust_pitch = pcm_src_adjust_pitch, |
| + .convert_s16 = pcm_src_convert_s16, |
| + .input_frames = input_frames, |
| + .output_frames = output_frames, |
| +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010002 |
| + .version = SND_PCM_RATE_PLUGIN_VERSION, |
| + .get_supported_rates = get_supported_rates, |
| + .dump = dump, |
| +#endif |
| +}; |
| + |
| +int pcm_src_open(unsigned int version, void **objp, snd_pcm_rate_ops_t *ops) |
| + |
| +{ |
| + struct rate_src *rate; |
| + |
| +#if SND_PCM_RATE_PLUGIN_VERSION < 0x010002 |
| + if (version != SND_PCM_RATE_PLUGIN_VERSION) { |
| + fprintf(stderr, "Invalid rate plugin version %x\n", version); |
| + return -EINVAL; |
| + } |
| +#endif |
| + rate = calloc(1, sizeof(*rate)); |
| + if (!rate) |
| + return -ENOMEM; |
| + |
| + *objp = rate; |
| + rate->avr = NULL; |
| +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010002 |
| + if (version == 0x010001) |
| + memcpy(ops, &pcm_src_ops, sizeof(snd_pcm_rate_old_ops_t)); |
| + else |
| +#endif |
| + *ops = pcm_src_ops; |
| + return 0; |
| +} |
| + |
| +int SND_PCM_RATE_PLUGIN_ENTRY(lavcrate)(unsigned int version, void **objp, |
| + snd_pcm_rate_ops_t *ops) |
| +{ |
| + return pcm_src_open(version, objp, ops); |
| +} |
| +int SND_PCM_RATE_PLUGIN_ENTRY(lavcrate_higher)(unsigned int version, |
| + void **objp, snd_pcm_rate_ops_t *ops) |
| +{ |
| + filter_size = 64; |
| + return pcm_src_open(version, objp, ops); |
| +} |
| +int SND_PCM_RATE_PLUGIN_ENTRY(lavcrate_high)(unsigned int version, |
| + void **objp, snd_pcm_rate_ops_t *ops) |
| +{ |
| + filter_size = 32; |
| + return pcm_src_open(version, objp, ops); |
| +} |
| +int SND_PCM_RATE_PLUGIN_ENTRY(lavcrate_fast)(unsigned int version, |
| + void **objp, snd_pcm_rate_ops_t *ops) |
| +{ |
| + filter_size = 8; |
| + return pcm_src_open(version, objp, ops); |
| +} |
| +int SND_PCM_RATE_PLUGIN_ENTRY(lavcrate_faster)(unsigned int version, |
| + void **objp, snd_pcm_rate_ops_t *ops) |
| +{ |
| + filter_size = 4; |
| + return pcm_src_open(version, objp, ops); |
| +} |
| + |
| + |