[pulseaudio-discuss] [PATCH 2/3] resampler: Add optional soxr resampler
Peter Meerwald
pmeerw at pmeerw.net
Mon Aug 4 05:40:13 PDT 2014
see http://sourceforge.net/p/soxr/wiki/Home/
Signed-off-by: Peter Meerwald <pmeerw at pmeerw.net>
Signed-off-by: poljar (Damir Jelić) <poljarinho at gmail.com>
--
rebased and leftover handling is external to _resample() now;
this fixes a bug in the leftover_length computation since soxr supports
s16 and float32, hence sizeof(float) is wrong
---
configure.ac | 17 ++++++
src/Makefile.am | 6 ++
src/pulsecore/resampler.c | 14 ++++-
src/pulsecore/resampler.h | 2 +
src/pulsecore/resampler/soxr.c | 124 +++++++++++++++++++++++++++++++++++++++++
5 files changed, 162 insertions(+), 1 deletion(-)
create mode 100644 src/pulsecore/resampler/soxr.c
diff --git a/configure.ac b/configure.ac
index 837e81e..cf63eca 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1109,6 +1109,21 @@ AS_IF([test "x$with_speex" = "xyes" && test "x$HAVE_SPEEX" = "x0"],
AM_CONDITIONAL([HAVE_SPEEX], [test "x$HAVE_SPEEX" = "x1"])
AS_IF([test "x$HAVE_SPEEX" = "x1"], AC_DEFINE([HAVE_SPEEX], 1, [Have speex]))
+#### sox resampler support (optional) ####
+
+AC_ARG_ENABLE([soxr],
+ AS_HELP_STRING([--disable-soxr],[Disable optional soxr support]))
+
+AS_IF([test "x$enable_soxr" != "xno"],
+ [PKG_CHECK_MODULES(SOXR, soxr, HAVE_SOXR=1, HAVE_SOXR=0)],
+ HAVE_SOXR=0)
+
+AS_IF([test "x$enable_soxr" = "xyes" && test "x$HAVE_SOXR" = "x0"],
+ [AC_MSG_ERROR([*** soxr not found])])
+
+AM_CONDITIONAL([HAVE_SOXR], [test "x$HAVE_SOXR" = x1])
+AS_IF([test "x$HAVE_SOXR" = "x1"], AC_DEFINE([HAVE_SOXR], 1, [Have soxr]))
+
#### Xen support (optional) ####
AC_ARG_ENABLE([xen],
@@ -1445,6 +1460,7 @@ AS_IF([test "x$HAVE_FFTW" = "x1"], ENABLE_FFTW=yes, ENABLE_FFTW=no)
AS_IF([test "x$HAVE_ORC" = "xyes"], ENABLE_ORC=yes, ENABLE_ORC=no)
AS_IF([test "x$HAVE_ADRIAN_EC" = "x1"], ENABLE_ADRIAN_EC=yes, ENABLE_ADRIAN_EC=no)
AS_IF([test "x$HAVE_SPEEX" = "x1"], ENABLE_SPEEX=yes, ENABLE_SPEEX=no)
+AS_IF([test "x$HAVE_SOXR" = "x1"], ENABLE_SOXR=yes, ENABLE_SOXR=no)
AS_IF([test "x$HAVE_WEBRTC" = "x1"], ENABLE_WEBRTC=yes, ENABLE_WEBRTC=no)
AS_IF([test "x$HAVE_TDB" = "x1"], ENABLE_TDB=yes, ENABLE_TDB=no)
AS_IF([test "x$HAVE_GDBM" = "x1"], ENABLE_GDBM=yes, ENABLE_GDBM=no)
@@ -1501,6 +1517,7 @@ echo "
Enable orc: ${ENABLE_ORC}
Enable Adrian echo canceller: ${ENABLE_ADRIAN_EC}
Enable speex (resampler, AEC): ${ENABLE_SPEEX}
+ Enable soxr: ${ENABLE_SOXR}
Enable WebRTC echo canceller: ${ENABLE_WEBRTC}
Enable gcov coverage: ${ENABLE_GCOV}
Enable unit tests: ${ENABLE_TESTS}
diff --git a/src/Makefile.am b/src/Makefile.am
index 21eb365..9df52df 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -992,6 +992,12 @@ libpulsecore_ at PA_MAJORMINOR@_la_CFLAGS += $(LIBSAMPLERATE_CFLAGS)
libpulsecore_ at PA_MAJORMINOR@_la_LIBADD += $(LIBSAMPLERATE_LIBS)
endif
+if HAVE_SOXR
+libpulsecore_ at PA_MAJORMINOR@_la_SOURCES += pulsecore/resampler/soxr.c
+libpulsecore_ at PA_MAJORMINOR@_la_CFLAGS += $(SOXR_CFLAGS)
+libpulsecore_ at PA_MAJORMINOR@_la_LIBADD += $(SOXR_LIBS)
+endif
+
# We split the foreign code off to not be annoyed by warnings we don't care about
noinst_LTLIBRARIES += libpulsecore-foreign.la
diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index de58f3f..e366be6 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -117,6 +117,11 @@ static int (* const init_table[])(pa_resampler *r) = {
[PA_RESAMPLER_AUTO] = NULL,
[PA_RESAMPLER_COPY] = copy_init,
[PA_RESAMPLER_PEAKS] = pa_resampler_peaks_init,
+#ifdef HAVE_SOXR
+ [PA_RESAMPLER_SOXR] = pa_resampler_soxr_init,
+#else
+ [PA_RESAMPLER_SOXR] = NULL,
+#endif
};
static bool speex_is_fixed_point(void);
@@ -163,6 +168,7 @@ static pa_resample_method_t fix_method(
break;
}
/* Else fall through */
+ case PA_RESAMPLER_SOXR:
case PA_RESAMPLER_FFMPEG:
if (flags & PA_RESAMPLER_VARIABLE_RATE) {
pa_log_info("Resampler '%s' cannot do variable rate, reverting to resampler 'auto'.", pa_resample_method_to_string(method));
@@ -606,7 +612,8 @@ static const char * const resample_methods[] = {
"ffmpeg",
"auto",
"copy",
- "peaks"
+ "peaks",
+ "soxr"
};
const char *pa_resample_method_to_string(pa_resample_method_t m) {
@@ -634,6 +641,11 @@ int pa_resample_method_supported(pa_resample_method_t m) {
return 0;
#endif
+#ifndef HAVE_SOXR
+ if (m == PA_RESAMPLER_SOXR)
+ return 0;
+#endif
+
return 1;
}
diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h
index 13d8c35..1d248e2 100644
--- a/src/pulsecore/resampler.h
+++ b/src/pulsecore/resampler.h
@@ -61,6 +61,7 @@ typedef enum pa_resample_method {
PA_RESAMPLER_AUTO, /* automatic select based on sample format */
PA_RESAMPLER_COPY,
PA_RESAMPLER_PEAKS,
+ PA_RESAMPLER_SOXR,
PA_RESAMPLER_MAX
} pa_resample_method_t;
@@ -164,6 +165,7 @@ int pa_resampler_ffmpeg_init(pa_resampler *r);
int pa_resampler_libsamplerate_init(pa_resampler *r);
int pa_resampler_peaks_init(pa_resampler *r);
int pa_resampler_speex_init(pa_resampler *r);
+int pa_resampler_soxr_init(pa_resampler *r);
int pa_resampler_trivial_init(pa_resampler*r);
#endif
diff --git a/src/pulsecore/resampler/soxr.c b/src/pulsecore/resampler/soxr.c
new file mode 100644
index 0000000..4614a4f
--- /dev/null
+++ b/src/pulsecore/resampler/soxr.c
@@ -0,0 +1,124 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2013 Damir Jelić
+
+ PulseAudio 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.
+
+ PulseAudio 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <soxr.h>
+
+#include "pulsecore/resampler.h"
+
+static void soxr_free(pa_resampler *r);
+
+static unsigned soxr_resample(pa_resampler *r, const pa_memchunk *input,
+ unsigned in_n_frames, pa_memchunk *output,
+ unsigned *out_n_frames) {
+ soxr_t state;
+ soxr_error_t error;
+ uint8_t *out;
+ uint8_t *in;
+ size_t odone;
+ size_t consumed;
+
+ pa_assert(r);
+ pa_assert(input);
+ pa_assert(output);
+ pa_assert(out_n_frames);
+
+ state = r->impl.data;
+
+ in = pa_memblock_acquire_chunk(input);
+ out = pa_memblock_acquire_chunk(output);
+
+ error = soxr_process(state, in, in_n_frames, &consumed, out, *out_n_frames, &odone);
+ pa_assert(error == 0);
+
+ pa_memblock_release(input->memblock);
+ pa_memblock_release(output->memblock);
+
+ *out_n_frames = odone;
+
+ return in_n_frames - consumed;
+}
+
+static void soxr_udpate_rates(pa_resampler *r) {
+ pa_assert(r);
+
+ soxr_free(r);
+ pa_resampler_soxr_init(r);
+}
+
+static void soxr_reset(pa_resampler *r) {
+ pa_assert(r);
+
+ /* TODO use soxr_clear() since it is the documented way to reset the resamlper;
+ * for some reason soxr_process crashes after we use soxr_clear() here */
+ soxr_free(r);
+ pa_resampler_soxr_init(r);
+}
+
+static void soxr_free(pa_resampler *r) {
+ soxr_t state;
+ pa_assert(r);
+
+ state = r->impl.data;
+ soxr_delete(state);
+}
+
+int pa_resampler_soxr_init(pa_resampler *r) {
+ soxr_t state;
+ soxr_error_t error;
+ soxr_io_spec_t io_spec;
+ soxr_runtime_spec_t runtime_spec;
+ soxr_quality_spec_t quality_spec;
+ unsigned int format;
+
+ pa_assert(r);
+
+ switch (r->work_format) {
+ case PA_SAMPLE_S16NE:
+ format = SOXR_INT16;
+ break;
+ case PA_SAMPLE_FLOAT32NE:
+ format = SOXR_FLOAT32;
+ break;
+ default:
+ pa_assert_not_reached();
+ }
+
+ io_spec = soxr_io_spec(format, format);
+ runtime_spec = soxr_runtime_spec(0);
+ quality_spec = soxr_quality_spec(SOXR_QQ, 0);
+
+ state = soxr_create(r->i_ss.rate, r->o_ss.rate, r->work_channels, &error, &io_spec, &quality_spec, &runtime_spec);
+
+ if (error)
+ return -1;
+
+ r->impl.resample = soxr_resample;
+ r->impl.update_rates = soxr_udpate_rates;
+ r->impl.reset = soxr_reset;
+ r->impl.free = soxr_free;
+ r->impl.data = state;
+
+ return 0;
+}
--
1.9.1
More information about the pulseaudio-discuss
mailing list