[pulseaudio-discuss] [PATCH 1/4] Added libsoxr resampler backend.

2014-11-11 Thread Andrey Semashev
The new backend supports 4 quality levels: lq, mq, hq and vhq; 16 and 32-bit 
integer samples and 32-bit float samples. The libsoxr resampler generally 
offers better quality and speed compared to speex.
---
 src/pulsecore/resampler/soxr.c | 168 +
 1 file changed, 168 insertions(+)
 create mode 100644 src/pulsecore/resampler/soxr.c

diff --git a/src/pulsecore/resampler/soxr.c b/src/pulsecore/resampler/soxr.c
new file mode 100644
index 000..ba45d36
--- /dev/null
+++ b/src/pulsecore/resampler/soxr.c
@@ -0,0 +1,168 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2014 Andrey Semashev
+
+  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 
+#endif
+
+#include 
+#include 
+
+#include 
+
+static unsigned resampler_soxr_resample(pa_resampler *r, const pa_memchunk 
*input, unsigned in_n_frames,
+pa_memchunk *output, unsigned 
*out_n_frames) {
+soxr_t state;
+void *in, *out;
+size_t consumed = 0, produced = 0;
+
+pa_assert(r);
+pa_assert(input);
+pa_assert(output);
+pa_assert(out_n_frames);
+
+state = r->impl.data;
+pa_assert(state);
+
+in = pa_memblock_acquire_chunk(input);
+out = pa_memblock_acquire_chunk(output);
+
+pa_assert_se(soxr_process(state, in, in_n_frames, &consumed, out, 
*out_n_frames, &produced) == 0);
+
+pa_memblock_release(input->memblock);
+pa_memblock_release(output->memblock);
+
+*out_n_frames = produced;
+
+return in_n_frames - consumed;
+}
+
+static void resampler_soxr_free(pa_resampler *r) {
+pa_assert(r);
+
+if (!r->impl.data)
+return;
+
+soxr_delete(r->impl.data);
+r->impl.data = NULL;
+}
+
+static void resampler_soxr_reset(pa_resampler *r) {
+soxr_t old_state;
+
+pa_assert(r);
+
+/* This makes soxr_process() crash afterwards,
+   so don't use this function until libsoxr is fixed.
+soxr_clear(r->impl.data); */
+
+old_state = r->impl.data;
+r->impl.data = NULL;
+
+if (pa_resampler_soxr_init(r) == 0) {
+if (old_state)
+soxr_delete(old_state);
+} else {
+r->impl.data = old_state;
+pa_log_error("Failed to reset libsoxr context");
+}
+}
+
+static void resampler_soxr_update_rates(pa_resampler *r) {
+soxr_t old_state;
+
+pa_assert(r);
+
+/* There is no update method in libsoxr,
+   so just re-create the resampler context */
+
+old_state = r->impl.data;
+r->impl.data = NULL;
+
+if (pa_resampler_soxr_init(r) == 0) {
+if (old_state)
+soxr_delete(old_state);
+} else {
+r->impl.data = old_state;
+pa_log_error("Failed to update libsoxr sample rates");
+}
+}
+
+int pa_resampler_soxr_init(pa_resampler *r) {
+soxr_t state;
+soxr_datatype_t io_format;
+soxr_io_spec_t io_spec;
+unsigned long quality_recipe;
+soxr_quality_spec_t quality;
+soxr_error_t err = NULL;
+
+pa_assert(r);
+
+switch (r->work_format) {
+case PA_SAMPLE_S16NE:
+io_format = SOXR_INT16_I;
+break;
+case PA_SAMPLE_S32NE:
+io_format = SOXR_INT32_I;
+break;
+case PA_SAMPLE_FLOAT32NE:
+io_format = SOXR_FLOAT32_I;
+break;
+default:
+pa_assert(0 && "Unsupported sample format for libsoxr");
+return -1;
+}
+
+io_spec = soxr_io_spec(io_format, io_format);
+
+switch (r->method) {
+case PA_RESAMPLER_SOXR_LQ:
+quality_recipe = SOXR_LQ | SOXR_LINEAR_PHASE;
+break;
+case PA_RESAMPLER_SOXR_MQ:
+quality_recipe = SOXR_MQ | SOXR_LINEAR_PHASE;
+break;
+case PA_RESAMPLER_SOXR_VHQ:
+quality_recipe = SOXR_VHQ | SOXR_LINEAR_PHASE;
+break;
+default:
+pa_assert(0 && "Unexpected libsoxr resampling method");
+case PA_RESAMPLER_SOXR_HQ:
+quality_recipe = SOXR_HQ | SOXR_LINEAR_PHASE;
+break;
+}
+
+quality = soxr_quality_spec(quality_recipe, 0);
+
+state = soxr_create(r->i_ss.rate, r->o_ss.rate, r->work_channels, &err, 
&io_spec, &quality, NULL);
+if (!state) {
+pa_log_error("Failed to create libsoxr resampler con

[pulseaudio-discuss] [PATCH 1/4] Added libsoxr resampler backend.

2014-11-14 Thread Andrey Semashev
The new backend supports 3 quality levels: mq, hq and vhq; 16 integer and 
32-bit float samples. Discussion and quality assessment are here:

http://comments.gmane.org/gmane.comp.audio.pulseaudio.general/22158
---
 src/pulsecore/resampler/soxr.c | 170 +
 1 file changed, 170 insertions(+)
 create mode 100644 src/pulsecore/resampler/soxr.c

diff --git a/src/pulsecore/resampler/soxr.c b/src/pulsecore/resampler/soxr.c
new file mode 100644
index 000..c2fd8ee
--- /dev/null
+++ b/src/pulsecore/resampler/soxr.c
@@ -0,0 +1,170 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2014 Andrey Semashev
+
+  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 
+#endif
+
+#include 
+#include 
+
+#include 
+
+static unsigned resampler_soxr_resample(pa_resampler *r, const pa_memchunk 
*input, unsigned in_n_frames,
+pa_memchunk *output, unsigned 
*out_n_frames) {
+soxr_t state;
+void *in, *out;
+size_t consumed = 0, produced = 0;
+
+pa_assert(r);
+pa_assert(input);
+pa_assert(output);
+pa_assert(out_n_frames);
+
+state = r->impl.data;
+pa_assert(state);
+
+in = pa_memblock_acquire_chunk(input);
+out = pa_memblock_acquire_chunk(output);
+
+pa_assert_se(soxr_process(state, in, in_n_frames, &consumed, out, 
*out_n_frames, &produced) == 0);
+
+pa_memblock_release(input->memblock);
+pa_memblock_release(output->memblock);
+
+*out_n_frames = produced;
+
+return in_n_frames - consumed;
+}
+
+static void resampler_soxr_free(pa_resampler *r) {
+pa_assert(r);
+
+if (!r->impl.data)
+return;
+
+soxr_delete(r->impl.data);
+r->impl.data = NULL;
+}
+
+static void resampler_soxr_reset(pa_resampler *r) {
+soxr_t old_state;
+
+pa_assert(r);
+
+/*
+ * soxr_clear() makes soxr_process() crash afterwards,
+ * so don't use this function until libsoxr is fixed.
+ *
+ * soxr_clear(r->impl.data);
+ */
+
+old_state = r->impl.data;
+r->impl.data = NULL;
+
+if (pa_resampler_soxr_init(r) == 0) {
+if (old_state)
+soxr_delete(old_state);
+} else {
+r->impl.data = old_state;
+pa_log_error("Failed to reset libsoxr context");
+}
+}
+
+static void resampler_soxr_update_rates(pa_resampler *r) {
+soxr_t old_state;
+
+pa_assert(r);
+
+/* There is no update method in libsoxr,
+ * so just re-create the resampler context */
+
+old_state = r->impl.data;
+r->impl.data = NULL;
+
+if (pa_resampler_soxr_init(r) == 0) {
+if (old_state)
+soxr_delete(old_state);
+} else {
+r->impl.data = old_state;
+pa_log_error("Failed to update libsoxr sample rates");
+}
+}
+
+int pa_resampler_soxr_init(pa_resampler *r) {
+soxr_t state;
+soxr_datatype_t io_format;
+soxr_io_spec_t io_spec;
+soxr_runtime_spec_t runtime_spec;
+unsigned long quality_recipe;
+soxr_quality_spec_t quality;
+soxr_error_t err = NULL;
+
+pa_assert(r);
+
+switch (r->work_format) {
+case PA_SAMPLE_S16NE:
+io_format = SOXR_INT16_I;
+break;
+case PA_SAMPLE_FLOAT32NE:
+io_format = SOXR_FLOAT32_I;
+break;
+default:
+pa_assert_not_reached();
+return -1;
+}
+
+io_spec = soxr_io_spec(io_format, io_format);
+
+/* Resample in one thread. Multithreading makes
+ * performance worse with small chunks of audio. */
+runtime_spec = soxr_runtime_spec(1);
+
+switch (r->method) {
+case PA_RESAMPLER_SOXR_MQ:
+quality_recipe = SOXR_MQ | SOXR_LINEAR_PHASE;
+break;
+case PA_RESAMPLER_SOXR_VHQ:
+quality_recipe = SOXR_VHQ | SOXR_LINEAR_PHASE;
+break;
+default:
+pa_assert_not_reached();
+case PA_RESAMPLER_SOXR_HQ:
+quality_recipe = SOXR_HQ | SOXR_LINEAR_PHASE;
+break;
+}
+
+quality = soxr_quality_spec(quality_recipe, 0);
+
+state = soxr_create(r->i_ss.rate, r->o_ss.rate, r->work_channels, &err, 
&io_spec, &quality, &runtime_spec);
+if (!state) {
+pa_log_error("Failed to create libsoxr resampler context: %s.", (err ? 
err : "

[pulseaudio-discuss] [PATCH 1/4] Added libsoxr resampler backend.

2015-01-07 Thread Andrey Semashev
The new backend supports 3 quality levels: mq, hq and vhq; 16-bit integer and 
32-bit float samples. Discussion and quality assessment are here:

http://comments.gmane.org/gmane.comp.audio.pulseaudio.general/22158
---
 src/pulsecore/resampler/soxr.c | 171 +
 1 file changed, 171 insertions(+)
 create mode 100644 src/pulsecore/resampler/soxr.c

diff --git a/src/pulsecore/resampler/soxr.c b/src/pulsecore/resampler/soxr.c
new file mode 100644
index 000..769228b
--- /dev/null
+++ b/src/pulsecore/resampler/soxr.c
@@ -0,0 +1,171 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2014, 2015 Andrey Semashev
+
+  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 
+#endif
+
+#include 
+#include 
+
+#include 
+
+static unsigned resampler_soxr_resample(pa_resampler *r, const pa_memchunk 
*input, unsigned in_n_frames,
+pa_memchunk *output, unsigned 
*out_n_frames) {
+soxr_t state;
+void *in, *out;
+size_t consumed = 0, produced = 0;
+
+pa_assert(r);
+pa_assert(input);
+pa_assert(output);
+pa_assert(out_n_frames);
+
+state = r->impl.data;
+pa_assert(state);
+
+in = pa_memblock_acquire_chunk(input);
+out = pa_memblock_acquire_chunk(output);
+
+pa_assert_se(soxr_process(state, in, in_n_frames, &consumed, out, 
*out_n_frames, &produced) == 0);
+
+pa_memblock_release(input->memblock);
+pa_memblock_release(output->memblock);
+
+*out_n_frames = produced;
+
+return in_n_frames - consumed;
+}
+
+static void resampler_soxr_free(pa_resampler *r) {
+pa_assert(r);
+
+if (!r->impl.data)
+return;
+
+soxr_delete(r->impl.data);
+r->impl.data = NULL;
+}
+
+static void resampler_soxr_reset(pa_resampler *r) {
+soxr_t old_state;
+
+pa_assert(r);
+
+/*
+ * soxr_clear() makes soxr_process() crash afterwards,
+ * so don't use this function until libsoxr is fixed.
+ *
+ * soxr_clear(r->impl.data);
+ */
+
+old_state = r->impl.data;
+r->impl.data = NULL;
+
+if (pa_resampler_soxr_init(r) == 0) {
+if (old_state)
+soxr_delete(old_state);
+} else {
+r->impl.data = old_state;
+pa_log_error("Failed to reset libsoxr context");
+}
+}
+
+static void resampler_soxr_update_rates(pa_resampler *r) {
+soxr_t old_state;
+
+pa_assert(r);
+
+/* There is no update method in libsoxr,
+ * so just re-create the resampler context */
+
+old_state = r->impl.data;
+r->impl.data = NULL;
+
+if (pa_resampler_soxr_init(r) == 0) {
+if (old_state)
+soxr_delete(old_state);
+} else {
+r->impl.data = old_state;
+pa_log_error("Failed to update libsoxr sample rates");
+}
+}
+
+int pa_resampler_soxr_init(pa_resampler *r) {
+soxr_t state;
+soxr_datatype_t io_format;
+soxr_io_spec_t io_spec;
+soxr_runtime_spec_t runtime_spec;
+unsigned long quality_recipe;
+soxr_quality_spec_t quality;
+soxr_error_t err = NULL;
+
+pa_assert(r);
+
+switch (r->work_format) {
+case PA_SAMPLE_S16NE:
+io_format = SOXR_INT16_I;
+break;
+case PA_SAMPLE_FLOAT32NE:
+io_format = SOXR_FLOAT32_I;
+break;
+default:
+pa_assert_not_reached();
+return -1;
+}
+
+io_spec = soxr_io_spec(io_format, io_format);
+
+/* Resample in one thread. Multithreading makes
+ * performance worse with small chunks of audio. */
+runtime_spec = soxr_runtime_spec(1);
+
+switch (r->method) {
+case PA_RESAMPLER_SOXR_MQ:
+quality_recipe = SOXR_MQ | SOXR_LINEAR_PHASE;
+break;
+case PA_RESAMPLER_SOXR_HQ:
+quality_recipe = SOXR_HQ | SOXR_LINEAR_PHASE;
+break;
+case PA_RESAMPLER_SOXR_VHQ:
+quality_recipe = SOXR_VHQ | SOXR_LINEAR_PHASE;
+break;
+default:
+pa_assert_not_reached();
+return -1;
+}
+
+quality = soxr_quality_spec(quality_recipe, 0);
+
+state = soxr_create(r->i_ss.rate, r->o_ss.rate, r->work_channels, &err, 
&io_spec, &quality, &runtime_spec);
+if (!state) {
+pa_log_error("Failed to create libsoxr resamp

[pulseaudio-discuss] [PATCH 1/4] Added libsoxr resampler backend.

2015-01-08 Thread Andrey Semashev
The new backend supports 3 quality levels: mq, hq and vhq; 16-bit integer and 
32-bit float samples. Discussion and quality assessment are here:

http://comments.gmane.org/gmane.comp.audio.pulseaudio.general/22158
---
 src/pulsecore/resampler/soxr.c | 171 +
 1 file changed, 171 insertions(+)
 create mode 100644 src/pulsecore/resampler/soxr.c

diff --git a/src/pulsecore/resampler/soxr.c b/src/pulsecore/resampler/soxr.c
new file mode 100644
index 000..769228b
--- /dev/null
+++ b/src/pulsecore/resampler/soxr.c
@@ -0,0 +1,171 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2014, 2015 Andrey Semashev
+
+  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 
+#endif
+
+#include 
+#include 
+
+#include 
+
+static unsigned resampler_soxr_resample(pa_resampler *r, const pa_memchunk 
*input, unsigned in_n_frames,
+pa_memchunk *output, unsigned 
*out_n_frames) {
+soxr_t state;
+void *in, *out;
+size_t consumed = 0, produced = 0;
+
+pa_assert(r);
+pa_assert(input);
+pa_assert(output);
+pa_assert(out_n_frames);
+
+state = r->impl.data;
+pa_assert(state);
+
+in = pa_memblock_acquire_chunk(input);
+out = pa_memblock_acquire_chunk(output);
+
+pa_assert_se(soxr_process(state, in, in_n_frames, &consumed, out, 
*out_n_frames, &produced) == 0);
+
+pa_memblock_release(input->memblock);
+pa_memblock_release(output->memblock);
+
+*out_n_frames = produced;
+
+return in_n_frames - consumed;
+}
+
+static void resampler_soxr_free(pa_resampler *r) {
+pa_assert(r);
+
+if (!r->impl.data)
+return;
+
+soxr_delete(r->impl.data);
+r->impl.data = NULL;
+}
+
+static void resampler_soxr_reset(pa_resampler *r) {
+soxr_t old_state;
+
+pa_assert(r);
+
+/*
+ * soxr_clear() makes soxr_process() crash afterwards,
+ * so don't use this function until libsoxr is fixed.
+ *
+ * soxr_clear(r->impl.data);
+ */
+
+old_state = r->impl.data;
+r->impl.data = NULL;
+
+if (pa_resampler_soxr_init(r) == 0) {
+if (old_state)
+soxr_delete(old_state);
+} else {
+r->impl.data = old_state;
+pa_log_error("Failed to reset libsoxr context");
+}
+}
+
+static void resampler_soxr_update_rates(pa_resampler *r) {
+soxr_t old_state;
+
+pa_assert(r);
+
+/* There is no update method in libsoxr,
+ * so just re-create the resampler context */
+
+old_state = r->impl.data;
+r->impl.data = NULL;
+
+if (pa_resampler_soxr_init(r) == 0) {
+if (old_state)
+soxr_delete(old_state);
+} else {
+r->impl.data = old_state;
+pa_log_error("Failed to update libsoxr sample rates");
+}
+}
+
+int pa_resampler_soxr_init(pa_resampler *r) {
+soxr_t state;
+soxr_datatype_t io_format;
+soxr_io_spec_t io_spec;
+soxr_runtime_spec_t runtime_spec;
+unsigned long quality_recipe;
+soxr_quality_spec_t quality;
+soxr_error_t err = NULL;
+
+pa_assert(r);
+
+switch (r->work_format) {
+case PA_SAMPLE_S16NE:
+io_format = SOXR_INT16_I;
+break;
+case PA_SAMPLE_FLOAT32NE:
+io_format = SOXR_FLOAT32_I;
+break;
+default:
+pa_assert_not_reached();
+return -1;
+}
+
+io_spec = soxr_io_spec(io_format, io_format);
+
+/* Resample in one thread. Multithreading makes
+ * performance worse with small chunks of audio. */
+runtime_spec = soxr_runtime_spec(1);
+
+switch (r->method) {
+case PA_RESAMPLER_SOXR_MQ:
+quality_recipe = SOXR_MQ | SOXR_LINEAR_PHASE;
+break;
+case PA_RESAMPLER_SOXR_HQ:
+quality_recipe = SOXR_HQ | SOXR_LINEAR_PHASE;
+break;
+case PA_RESAMPLER_SOXR_VHQ:
+quality_recipe = SOXR_VHQ | SOXR_LINEAR_PHASE;
+break;
+default:
+pa_assert_not_reached();
+return -1;
+}
+
+quality = soxr_quality_spec(quality_recipe, 0);
+
+state = soxr_create(r->i_ss.rate, r->o_ss.rate, r->work_channels, &err, 
&io_spec, &quality, &runtime_spec);
+if (!state) {
+pa_log_error("Failed to create libsoxr resamp

[pulseaudio-discuss] [PATCH 1/4] Added libsoxr resampler backend.

2015-01-14 Thread Andrey Semashev
The new backend supports 3 quality levels: mq, hq and vhq; 16-bit integer and 
32-bit float samples. Discussion and quality assessment are here:

http://comments.gmane.org/gmane.comp.audio.pulseaudio.general/22158
---
 src/pulsecore/resampler/soxr.c | 167 +
 1 file changed, 167 insertions(+)
 create mode 100644 src/pulsecore/resampler/soxr.c

diff --git a/src/pulsecore/resampler/soxr.c b/src/pulsecore/resampler/soxr.c
new file mode 100644
index 000..b5f0007
--- /dev/null
+++ b/src/pulsecore/resampler/soxr.c
@@ -0,0 +1,167 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2014, 2015 Andrey Semashev
+
+  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, see .
+***/
+
+#ifdef HAVE_CONFIG_H
+#include 
+#endif
+
+#include 
+#include 
+
+#include 
+
+static unsigned resampler_soxr_resample(pa_resampler *r, const pa_memchunk 
*input, unsigned in_n_frames,
+pa_memchunk *output, unsigned 
*out_n_frames) {
+soxr_t state;
+void *in, *out;
+size_t consumed = 0, produced = 0;
+
+pa_assert(r);
+pa_assert(input);
+pa_assert(output);
+pa_assert(out_n_frames);
+
+state = r->impl.data;
+pa_assert(state);
+
+in = pa_memblock_acquire_chunk(input);
+out = pa_memblock_acquire_chunk(output);
+
+pa_assert_se(soxr_process(state, in, in_n_frames, &consumed, out, 
*out_n_frames, &produced) == 0);
+
+pa_memblock_release(input->memblock);
+pa_memblock_release(output->memblock);
+
+*out_n_frames = produced;
+
+return in_n_frames - consumed;
+}
+
+static void resampler_soxr_free(pa_resampler *r) {
+pa_assert(r);
+
+if (!r->impl.data)
+return;
+
+soxr_delete(r->impl.data);
+r->impl.data = NULL;
+}
+
+static void resampler_soxr_reset(pa_resampler *r) {
+soxr_t old_state;
+
+pa_assert(r);
+
+/*
+ * soxr_clear() makes soxr_process() crash afterwards,
+ * so don't use this function until libsoxr is fixed.
+ *
+ * soxr_clear(r->impl.data);
+ */
+
+old_state = r->impl.data;
+r->impl.data = NULL;
+
+if (pa_resampler_soxr_init(r) == 0) {
+if (old_state)
+soxr_delete(old_state);
+} else {
+r->impl.data = old_state;
+pa_log_error("Failed to reset libsoxr context");
+}
+}
+
+static void resampler_soxr_update_rates(pa_resampler *r) {
+soxr_t old_state;
+
+pa_assert(r);
+
+/* There is no update method in libsoxr,
+ * so just re-create the resampler context */
+
+old_state = r->impl.data;
+r->impl.data = NULL;
+
+if (pa_resampler_soxr_init(r) == 0) {
+if (old_state)
+soxr_delete(old_state);
+} else {
+r->impl.data = old_state;
+pa_log_error("Failed to update libsoxr sample rates");
+}
+}
+
+int pa_resampler_soxr_init(pa_resampler *r) {
+soxr_t state;
+soxr_datatype_t io_format;
+soxr_io_spec_t io_spec;
+soxr_runtime_spec_t runtime_spec;
+unsigned long quality_recipe;
+soxr_quality_spec_t quality;
+soxr_error_t err = NULL;
+
+pa_assert(r);
+
+switch (r->work_format) {
+case PA_SAMPLE_S16NE:
+io_format = SOXR_INT16_I;
+break;
+case PA_SAMPLE_FLOAT32NE:
+io_format = SOXR_FLOAT32_I;
+break;
+default:
+pa_assert_not_reached();
+}
+
+io_spec = soxr_io_spec(io_format, io_format);
+
+/* Resample in one thread. Multithreading makes
+ * performance worse with small chunks of audio. */
+runtime_spec = soxr_runtime_spec(1);
+
+switch (r->method) {
+case PA_RESAMPLER_SOXR_MQ:
+quality_recipe = SOXR_MQ | SOXR_LINEAR_PHASE;
+break;
+case PA_RESAMPLER_SOXR_HQ:
+quality_recipe = SOXR_HQ | SOXR_LINEAR_PHASE;
+break;
+case PA_RESAMPLER_SOXR_VHQ:
+quality_recipe = SOXR_VHQ | SOXR_LINEAR_PHASE;
+break;
+default:
+pa_assert_not_reached();
+}
+
+quality = soxr_quality_spec(quality_recipe, 0);
+
+state = soxr_create(r->i_ss.rate, r->o_ss.rate, r->work_channels, &err, 
&io_spec, &quality, &runtime_spec);
+if (!state) {
+pa_log_error("Failed to create libsoxr resampler context: %s.", (err ? 
err : "[unknown error]"));
+return -1;
+}
+
+r->impl.free = resampler_soxr_

Re: [pulseaudio-discuss] [PATCH 1/4] Added libsoxr resampler backend.

2014-11-12 Thread Peter Meerwald
Hello Andrey,

> The new backend supports 4 quality levels: lq, mq, hq and vhq; 16 and 
> 32-bit integer samples and 32-bit float samples. The libsoxr resampler 
> generally offers better quality and speed compared to speex.

soxr support was proposed previously,
http://lists.freedesktop.org/archives/pulseaudio-discuss/2014-August/021050.html

the common consensus currently seems to be that soxr doesn't offer enough 
advantage to justify inclusion in PA

I think the claim "is almost always faster" needs to be substantiated; 
some comparison has been done here: 
http://poljar.blogspot.co.at/2013/08/vol-2-resampling-methods.html

I am  pro-choice wrt resamplers :)
on the other hand PA's framework to add more resamplers is not very 
sustainable (huge table with different qualities)

regards, p.

> ---
>  src/pulsecore/resampler/soxr.c | 168 
> +
>  1 file changed, 168 insertions(+)
>  create mode 100644 src/pulsecore/resampler/soxr.c
> 
> diff --git a/src/pulsecore/resampler/soxr.c b/src/pulsecore/resampler/soxr.c
> new file mode 100644
> index 000..ba45d36
> --- /dev/null
> +++ b/src/pulsecore/resampler/soxr.c
> @@ -0,0 +1,168 @@
> +/***
> +  This file is part of PulseAudio.
> +
> +  Copyright 2014 Andrey Semashev
> +
> +  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 
> +#endif
> +
> +#include 
> +#include 
> +
> +#include 
> +
> +static unsigned resampler_soxr_resample(pa_resampler *r, const pa_memchunk 
> *input, unsigned in_n_frames,
> +pa_memchunk *output, unsigned 
> *out_n_frames) {
> +soxr_t state;
> +void *in, *out;
> +size_t consumed = 0, produced = 0;
> +
> +pa_assert(r);
> +pa_assert(input);
> +pa_assert(output);
> +pa_assert(out_n_frames);
> +
> +state = r->impl.data;
> +pa_assert(state);
> +
> +in = pa_memblock_acquire_chunk(input);
> +out = pa_memblock_acquire_chunk(output);
> +
> +pa_assert_se(soxr_process(state, in, in_n_frames, &consumed, out, 
> *out_n_frames, &produced) == 0);
> +
> +pa_memblock_release(input->memblock);
> +pa_memblock_release(output->memblock);
> +
> +*out_n_frames = produced;
> +
> +return in_n_frames - consumed;
> +}
> +
> +static void resampler_soxr_free(pa_resampler *r) {
> +pa_assert(r);
> +
> +if (!r->impl.data)
> +return;
> +
> +soxr_delete(r->impl.data);
> +r->impl.data = NULL;
> +}
> +
> +static void resampler_soxr_reset(pa_resampler *r) {
> +soxr_t old_state;
> +
> +pa_assert(r);
> +
> +/* This makes soxr_process() crash afterwards,
> +   so don't use this function until libsoxr is fixed.
> +soxr_clear(r->impl.data); */
> +
> +old_state = r->impl.data;
> +r->impl.data = NULL;
> +
> +if (pa_resampler_soxr_init(r) == 0) {
> +if (old_state)
> +soxr_delete(old_state);
> +} else {
> +r->impl.data = old_state;
> +pa_log_error("Failed to reset libsoxr context");
> +}
> +}
> +
> +static void resampler_soxr_update_rates(pa_resampler *r) {
> +soxr_t old_state;
> +
> +pa_assert(r);
> +
> +/* There is no update method in libsoxr,
> +   so just re-create the resampler context */
> +
> +old_state = r->impl.data;
> +r->impl.data = NULL;
> +
> +if (pa_resampler_soxr_init(r) == 0) {
> +if (old_state)
> +soxr_delete(old_state);
> +} else {
> +r->impl.data = old_state;
> +pa_log_error("Failed to update libsoxr sample rates");
> +}
> +}
> +
> +int pa_resampler_soxr_init(pa_resampler *r) {
> +soxr_t state;
> +soxr_datatype_t io_format;
> +soxr_io_spec_t io_spec;
> +unsigned long quality_recipe;
> +soxr_quality_spec_t quality;
> +soxr_error_t err = NULL;
> +
> +pa_assert(r);
> +
> +switch (r->work_format) {
> +case PA_SAMPLE_S16NE:
> +io_format = SOXR_INT16_I;
> +break;
> +case PA_SAMPLE_S32NE:
> +io_format = SOXR_INT32_I;
> +break;
> +case PA_SAMPLE_FLOAT32NE:
> +io_format = SOXR_FLOAT32_I;
> +break;
> +default:
> +pa_assert(0 && "Unsupported sample format for libsoxr");
> +retu

Re: [pulseaudio-discuss] [PATCH 1/4] Added libsoxr resampler backend.

2014-11-12 Thread Peter Meerwald

comments below

> ---
>  src/pulsecore/resampler/soxr.c | 168 
> +
>  1 file changed, 168 insertions(+)
>  create mode 100644 src/pulsecore/resampler/soxr.c
> 
> diff --git a/src/pulsecore/resampler/soxr.c b/src/pulsecore/resampler/soxr.c
> new file mode 100644
> index 000..ba45d36
> --- /dev/null
> +++ b/src/pulsecore/resampler/soxr.c
> @@ -0,0 +1,168 @@
> +/***
> +  This file is part of PulseAudio.
> +
> +  Copyright 2014 Andrey Semashev
> +
> +  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 
> +#endif
> +
> +#include 
> +#include 
> +
> +#include 
> +
> +static unsigned resampler_soxr_resample(pa_resampler *r, const pa_memchunk 
> *input, unsigned in_n_frames,
> +pa_memchunk *output, unsigned 
> *out_n_frames) {
> +soxr_t state;
> +void *in, *out;
> +size_t consumed = 0, produced = 0;
> +
> +pa_assert(r);
> +pa_assert(input);
> +pa_assert(output);
> +pa_assert(out_n_frames);
> +
> +state = r->impl.data;
> +pa_assert(state);
> +
> +in = pa_memblock_acquire_chunk(input);
> +out = pa_memblock_acquire_chunk(output);
> +
> +pa_assert_se(soxr_process(state, in, in_n_frames, &consumed, out, 
> *out_n_frames, &produced) == 0);
> +
> +pa_memblock_release(input->memblock);
> +pa_memblock_release(output->memblock);
> +
> +*out_n_frames = produced;
> +
> +return in_n_frames - consumed;
> +}
> +
> +static void resampler_soxr_free(pa_resampler *r) {
> +pa_assert(r);
> +
> +if (!r->impl.data)
> +return;
> +
> +soxr_delete(r->impl.data);
> +r->impl.data = NULL;
> +}
> +
> +static void resampler_soxr_reset(pa_resampler *r) {
> +soxr_t old_state;
> +
> +pa_assert(r);
> +
> +/* This makes soxr_process() crash afterwards,
> +   so don't use this function until libsoxr is fixed.
> +soxr_clear(r->impl.data); */
> +
> +old_state = r->impl.data;
> +r->impl.data = NULL;
> +
> +if (pa_resampler_soxr_init(r) == 0) {
> +if (old_state)
> +soxr_delete(old_state);
> +} else {
> +r->impl.data = old_state;
> +pa_log_error("Failed to reset libsoxr context");
> +}
> +}
> +
> +static void resampler_soxr_update_rates(pa_resampler *r) {
> +soxr_t old_state;
> +
> +pa_assert(r);
> +
> +/* There is no update method in libsoxr,
> +   so just re-create the resampler context */

/*
 * 

> +
> +old_state = r->impl.data;
> +r->impl.data = NULL;
> +
> +if (pa_resampler_soxr_init(r) == 0) {
> +if (old_state)
> +soxr_delete(old_state);
> +} else {
> +r->impl.data = old_state;
> +pa_log_error("Failed to update libsoxr sample rates");
> +}
> +}
> +
> +int pa_resampler_soxr_init(pa_resampler *r) {
> +soxr_t state;
> +soxr_datatype_t io_format;
> +soxr_io_spec_t io_spec;
> +unsigned long quality_recipe;
> +soxr_quality_spec_t quality;
> +soxr_error_t err = NULL;
> +
> +pa_assert(r);
> +
> +switch (r->work_format) {
> +case PA_SAMPLE_S16NE:
> +io_format = SOXR_INT16_I;
> +break;
> +case PA_SAMPLE_S32NE:
> +io_format = SOXR_INT32_I;
> +break;

currently work_format is either S16NE or FLOAT32NE;
I think more work is needed to add S32NE as a work format

> +case PA_SAMPLE_FLOAT32NE:
> +io_format = SOXR_FLOAT32_I;
> +break;
> +default:
> +pa_assert(0 && "Unsupported sample format for libsoxr");
> +return -1;
> +}
> +
> +io_spec = soxr_io_spec(io_format, io_format);
> +
> +switch (r->method) {
> +case PA_RESAMPLER_SOXR_LQ:
> +quality_recipe = SOXR_LQ | SOXR_LINEAR_PHASE;
> +break;
> +case PA_RESAMPLER_SOXR_MQ:
> +quality_recipe = SOXR_MQ | SOXR_LINEAR_PHASE;
> +break;
> +case PA_RESAMPLER_SOXR_VHQ:
> +quality_recipe = SOXR_VHQ | SOXR_LINEAR_PHASE;
> +break;
> +default:
> +pa_assert(0 && "Unexpected libsoxr resampling method");

0 && ???

> +case PA_RESAMPLER_SOXR_HQ:
> +quality_recipe = SOXR_HQ | SOXR_LINEAR_PH

Re: [pulseaudio-discuss] [PATCH 1/4] Added libsoxr resampler backend.

2014-11-12 Thread Andrey Semashev
On Wed, Nov 12, 2014 at 1:15 PM, Peter Meerwald  wrote:
>
>> +switch (r->work_format) {
>> +case PA_SAMPLE_S16NE:
>> +io_format = SOXR_INT16_I;
>> +break;
>> +case PA_SAMPLE_S32NE:
>> +io_format = SOXR_INT32_I;
>> +break;
>
> currently work_format is either S16NE or FLOAT32NE;
> I think more work is needed to add S32NE as a work format

Yes, I found that out when I was adding this backend to the general
code in resampler.c. I decided to leave this case nevertheless, so
that if resampler.c is enhanced, soxr backend doesn't need any
changes.

If that's considered unneeded clutter I can remove it no problem.

>> +case PA_SAMPLE_FLOAT32NE:
>> +io_format = SOXR_FLOAT32_I;
>> +break;
>> +default:
>> +pa_assert(0 && "Unsupported sample format for libsoxr");
>> +return -1;
>> +}
>> +
>> +io_spec = soxr_io_spec(io_format, io_format);
>> +
>> +switch (r->method) {
>> +case PA_RESAMPLER_SOXR_LQ:
>> +quality_recipe = SOXR_LQ | SOXR_LINEAR_PHASE;
>> +break;
>> +case PA_RESAMPLER_SOXR_MQ:
>> +quality_recipe = SOXR_MQ | SOXR_LINEAR_PHASE;
>> +break;
>> +case PA_RESAMPLER_SOXR_VHQ:
>> +quality_recipe = SOXR_VHQ | SOXR_LINEAR_PHASE;
>> +break;
>> +default:
>> +pa_assert(0 && "Unexpected libsoxr resampling method");
>
> 0 && ???

It's a common approach for injecting a message into the assertion
failure. The C runtime typically displays the condition that fails,
and in this case it will include the message. It helps debugging.
___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH 1/4] Added libsoxr resampler backend.

2014-11-12 Thread Alexander E. Patrakov

12.11.2014 16:57, Andrey Semashev wrote:

It's a common approach for injecting a message into the assertion
failure. The C runtime typically displays the condition that fails,
and in this case it will include the message. It helps debugging.


We have pa_assert_not_reached just for that. It doesn't have a way to 
inject a custom message, but it does log a file and a line.


--
Alexander E. Patrakov
___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH 1/4] Added libsoxr resampler backend.

2014-11-12 Thread Andrey Semashev
On Wed, Nov 12, 2014 at 3:00 PM, Alexander E. Patrakov
 wrote:
> 12.11.2014 16:57, Andrey Semashev wrote:
>>
>> It's a common approach for injecting a message into the assertion
>> failure. The C runtime typically displays the condition that fails,
>> and in this case it will include the message. It helps debugging.
>
>
> We have pa_assert_not_reached just for that. It doesn't have a way to inject
> a custom message, but it does log a file and a line.

Ok, I will use it then.
___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss