summaryrefslogtreecommitdiffstats
path: root/pph/rate_speexrate.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2007-02-22 13:18:07 +0100
committerTakashi Iwai <tiwai@suse.de>2007-02-22 13:18:07 +0100
commit36ccb62d45d6c1192e2dc01ac639e6debc585f00 (patch)
tree3cf5dcea69b2c69e20cc7c09047923fa6ba9ea47 /pph/rate_speexrate.c
parentee123ac93ea59d11e7d3c48aed9cf88d1a5de431 (diff)
Add rate resampler plugin based on speex
Added another rate resampler plugin based on speex code. Light weight and much better quality. From: Jean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Diffstat (limited to 'pph/rate_speexrate.c')
-rw-r--r--pph/rate_speexrate.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/pph/rate_speexrate.c b/pph/rate_speexrate.c
new file mode 100644
index 0000000..07679b4
--- /dev/null
+++ b/pph/rate_speexrate.c
@@ -0,0 +1,162 @@
+/* Rate converter plugin using Public Parrot Hack
+ Copyright (C) 2007 Jean-Marc Valin
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <samplerate.h>
+#include <alsa/asoundlib.h>
+#include <alsa/pcm_rate.h>
+
+#include "speex_resampler.h"
+
+struct rate_src {
+ int quality;
+ unsigned int channels;
+ SpeexResamplerState *st;
+};
+
+static snd_pcm_uframes_t input_frames(void *obj, snd_pcm_uframes_t frames)
+{
+ int num, den;
+ struct rate_src *rate = obj;
+ if (frames == 0)
+ return 0;
+ speex_resampler_get_ratio(rate->st, &num, &den);
+ return (snd_pcm_uframes_t)((frames*num+(den>>1))/den);
+}
+
+static snd_pcm_uframes_t output_frames(void *obj, snd_pcm_uframes_t frames)
+{
+ int num, den;
+ struct rate_src *rate = obj;
+ if (frames == 0)
+ return 0;
+ speex_resampler_get_ratio(rate->st, &num, &den);
+ return (snd_pcm_uframes_t)((frames*den+(num>>1))/num);
+}
+
+static void pcm_src_free(void *obj)
+{
+ struct rate_src *rate = obj;
+ if (rate->st)
+ {
+ speex_resampler_destroy(rate->st);
+ rate->st = NULL;
+ }
+}
+
+static int pcm_src_init(void *obj, snd_pcm_rate_info_t *info)
+{
+ struct rate_src *rate = obj;
+
+ if (! rate->st || rate->channels != info->channels) {
+ if (rate->st)
+ speex_resampler_destroy(rate->st);
+ rate->channels = info->channels;
+ rate->st = speex_resampler_init_frac(rate->channels, info->in.period_size, info->out.period_size, info->in.rate, info->out.rate, rate->quality);
+ if (! rate->st)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int pcm_src_adjust_pitch(void *obj, snd_pcm_rate_info_t *info)
+{
+ struct rate_src *rate = obj;
+ speex_resampler_set_rate_frac(rate->st, info->in.period_size, info->out.period_size, info->in.rate, info->out.rate);
+ return 0;
+}
+
+static void pcm_src_reset(void *obj)
+{
+ struct rate_src *rate = obj;
+ speex_resampler_reset_mem(rate->st);
+}
+
+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;
+ speex_resampler_process_interleaved_int(rate->st, src, &src_frames, dst, &dst_frames);
+}
+
+static void pcm_src_close(void *obj)
+{
+ free(obj);
+}
+
+static snd_pcm_rate_ops_t pcm_src_ops = {
+ .close = pcm_src_close,
+ .init = pcm_src_init,
+ .free = pcm_src_free,
+ .reset = pcm_src_reset,
+ .adjust_pitch = pcm_src_adjust_pitch,
+ .convert_s16 = pcm_src_convert_s16,
+ .input_frames = input_frames,
+ .output_frames = output_frames,
+};
+
+static int pcm_src_open(unsigned int version, void **objp,
+ snd_pcm_rate_ops_t *ops, int quality)
+{
+ struct rate_src *rate;
+
+ if (version != SND_PCM_RATE_PLUGIN_VERSION) {
+ fprintf(stderr, "Invalid rate plugin version %x\n", version);
+ return -EINVAL;
+ }
+
+ rate = calloc(1, sizeof(*rate));
+ if (! rate)
+ return -ENOMEM;
+ rate->quality = quality;
+
+ *objp = rate;
+ *ops = pcm_src_ops;
+ return 0;
+}
+
+int SND_PCM_RATE_PLUGIN_ENTRY(speexrate) (unsigned int version, void **objp,
+ snd_pcm_rate_ops_t *ops)
+{
+ return pcm_src_open(version, objp, ops, 3);
+}
+
+int SND_PCM_RATE_PLUGIN_ENTRY(speexrate_best) (unsigned int version, void **objp,
+ snd_pcm_rate_ops_t *ops)
+{
+ return pcm_src_open(version, objp, ops, 10);
+}
+
+int SND_PCM_RATE_PLUGIN_ENTRY(speexrate_medium) (unsigned int version, void **objp,
+ snd_pcm_rate_ops_t *ops)
+{
+ return pcm_src_open(version, objp, ops, 5);
+}