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 0000000..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 <config.h> > +#endif > + > +#include <stddef.h> > +#include <soxr.h> > + > +#include <pulsecore/resampler.h> > + > +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 context: %s.", (err ? err : "[unknown error]")); > + return -1; > + } > + > + r->impl.free = resampler_soxr_free; > + r->impl.reset = resampler_soxr_reset; > + r->impl.update_rates = resampler_soxr_update_rates; > + r->impl.resample = resampler_soxr_resample; > + r->impl.data = state; > + > + return 0; > +} > -- > 2.1.0 > > _______________________________________________ > pulseaudio-discuss mailing list > pulseaudio-discuss at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss > -- Peter Meerwald +43-664-2444418 (mobile)