[pulseaudio-commits] src/pulsecore
Tanu Kaskinen
tanuk at kemper.freedesktop.org
Fri May 23 03:33:15 PDT 2014
src/pulsecore/resampler.c | 57 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 56 insertions(+), 1 deletion(-)
New commits:
commit ac984f59d36ef555bc5b0df9af1cd48193d0d14f
Author: Alexander E. Patrakov <patrakov at gmail.com>
Date: Tue May 13 21:50:52 2014 +0600
resampler: Support speex resampler compiled with FIXED_POINT
speex_resample_float() does not work with speex compiled with
--enable-fixed-point, because speex expects its float input
to be normalized to ±32768 instead of the more usual ±1.
It is possible to fix speex_resample_float(), as demonstrated at
http://lists.freedesktop.org/archives/pulseaudio-discuss/2014-May/020617.html
However, a better idea is to avoid using the speex-float resampler and
the associated s16 <-> float conversions that speex will immediately undo
internally if it is known that speex has been compiled with FIXED_POINT.
So, transparently change speex-float-* to speex-fixed-* in that case.
Signed-off-by: Alexander E. Patrakov <patrakov at gmail.com>
Reported-by: Fahad Arslan <fahad_arslan at mentor.com>
Cc: Damir JeliÄ <poljarinho at gmail.com>
Cc: Peter Meerwald <pmeerw at pmeerw.net>
FIXED_POINT detection is based on code by Peter Meerwald.
diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index 1153281..7799cfa 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -39,6 +39,7 @@
#include <pulsecore/macro.h>
#include <pulsecore/strbuf.h>
#include <pulsecore/remap.h>
+#include <pulsecore/once.h>
#include <pulsecore/core-util.h>
#include "ffmpeg/avcodec.h"
@@ -185,6 +186,8 @@ static int (* const init_table[])(pa_resampler*r) = {
[PA_RESAMPLER_PEAKS] = peaks_init,
};
+static bool speex_is_fixed_point(void);
+
static pa_resample_method_t choose_auto_resampler(pa_resample_flags_t flags) {
pa_resample_method_t method;
@@ -250,6 +253,20 @@ static pa_resample_method_t pa_resampler_fix_method(
if (method == PA_RESAMPLER_AUTO)
method = choose_auto_resampler(flags);
+ /* At this point, method is supported in the sense that it
+ * has an init function and supports the required flags. However,
+ * speex-float implementation in PulseAudio relies on the
+ * assumption that is invalid if speex has been compiled with
+ * --enable-fixed-point. Besides, speex-fixed is more efficient
+ * in this configuration. So use it instead.
+ */
+ if (method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && method <= PA_RESAMPLER_SPEEX_FLOAT_MAX) {
+ if (speex_is_fixed_point()) {
+ pa_log_info("Speex appears to be compiled with --enable-fixed-point. "
+ "Switching to a fixed-point resampler because it should be faster.");
+ method = method - PA_RESAMPLER_SPEEX_FLOAT_BASE + PA_RESAMPLER_SPEEX_FIXED_BASE;
+ }
+ }
return method;
}
@@ -1469,9 +1486,37 @@ static int libsamplerate_init(pa_resampler *r) {
}
#endif
-#ifdef HAVE_SPEEX
/*** speex based implementation ***/
+static bool speex_is_fixed_point(void) {
+ static bool result = false;
+#ifdef HAVE_SPEEX
+ PA_ONCE_BEGIN {
+ float f_out = -1.0f, f_in = 1.0f;
+ spx_uint32_t in_len = 1, out_len = 1;
+ SpeexResamplerState *s;
+
+ pa_assert_se(s = speex_resampler_init(1, 1, 1,
+ SPEEX_RESAMPLER_QUALITY_MIN, NULL));
+
+ /* feed one sample that is too soft for fixed-point speex */
+ pa_assert_se(speex_resampler_process_float(s, 0, &f_in, &in_len,
+ &f_out, &out_len) == RESAMPLER_ERR_SUCCESS);
+
+ /* expecting sample has been processed, one sample output */
+ pa_assert_se(in_len == 1 && out_len == 1);
+
+ /* speex compiled with --enable-fixed-point will output 0.0 due to insufficient precision */
+ if (fabsf(f_out) < 0.00001f)
+ result = true;
+
+ speex_resampler_destroy(s);
+ } PA_ONCE_END;
+#endif
+ return result;
+}
+
+#ifdef HAVE_SPEEX
static unsigned speex_resample_float(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
float *in, *out;
uint32_t inf = in_n_frames, outf = *out_n_frames;
@@ -1487,6 +1532,16 @@ static unsigned speex_resample_float(pa_resampler *r, const pa_memchunk *input,
in = pa_memblock_acquire_chunk(input);
out = pa_memblock_acquire_chunk(output);
+ /* Strictly speaking, speex resampler expects its input
+ * to be normalized to the [-32768.0 .. 32767.0] range.
+ * This matters if speex has been compiled with --enable-fixed-point,
+ * because such speex will round the samples to the nearest
+ * integer. speex with --enable-fixed-point is therefore incompatible
+ * with PulseAudio's floating-point sample range [-1 .. 1]. speex
+ * without --enable-fixed-point works fine with this range.
+ * Care has been taken to call speex_resample_float() only
+ * for speex compiled without --enable-fixed-point.
+ */
pa_assert_se(speex_resampler_process_interleaved_float(state, in, &inf, out, &outf) == 0);
pa_memblock_release(input->memblock);
More information about the pulseaudio-commits
mailing list