summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2007-08-14 16:21:52 +0200
committerTakashi Iwai <tiwai@suse.de>2007-08-14 16:21:52 +0200
commit1ee7b56befc16d0940bd162f3ac9b6ae66e85f0b (patch)
tree065c9830aa3999292faee1954e74abe0bd4c8675
parentf875609b187837c4332246a55c8032db07aa76c0 (diff)
Update speex rate converter code
Take speex rate converter code from speex SVN tree, which includes the fix for the noises with simple conversion (signed / unsigned mismatch).
-rw-r--r--pph/rate_speexrate.c3
-rw-r--r--pph/resample.c213
-rw-r--r--pph/speex_resampler.h65
3 files changed, 191 insertions, 90 deletions
diff --git a/pph/rate_speexrate.c b/pph/rate_speexrate.c
index 9eb33b9..38244b6 100644
--- a/pph/rate_speexrate.c
+++ b/pph/rate_speexrate.c
@@ -77,12 +77,13 @@ static void pcm_src_free(void *obj)
static int pcm_src_init(void *obj, snd_pcm_rate_info_t *info)
{
struct rate_src *rate = obj;
+ int err;
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);
+ rate->st = speex_resampler_init_frac(rate->channels, info->in.period_size, info->out.period_size, info->in.rate, info->out.rate, rate->quality, &err);
if (! rate->st)
return -EINVAL;
}
diff --git a/pph/resample.c b/pph/resample.c
index 281cb32..1cc4d49 100644
--- a/pph/resample.c
+++ b/pph/resample.c
@@ -56,9 +56,9 @@ TODO list:
#ifdef OUTSIDE_SPEEX
#include <stdlib.h>
-void *speex_alloc (int size) {return calloc(size,1);}
-void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);}
-void speex_free (void *ptr) {free(ptr);}
+static void *speex_alloc (int size) {return calloc(size,1);}
+static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);}
+static void speex_free (void *ptr) {free(ptr);}
#include "speex_resampler.h"
#include "arch.h"
#else /* OUTSIDE_SPEEX */
@@ -84,7 +84,11 @@ void speex_free (void *ptr) {free(ptr);}
#define OVERSAMPLE 8
#define IMAX(a,b) ((a) > (b) ? (a) : (b))
+#define IMIN(a,b) ((a) < (b) ? (a) : (b))
+#ifndef NULL
+#define NULL 0
+#endif
typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
@@ -205,12 +209,12 @@ static const struct QualityMapping quality_map[11] = {
{ 32, 4, 0.882f, 0.910f, KAISER6 }, /* Q2 */ /* 82.3% cutoff ( ~60 dB stop) 6 */
{ 48, 8, 0.895f, 0.917f, KAISER8 }, /* Q3 */ /* 84.9% cutoff ( ~80 dB stop) 8 */
{ 64, 8, 0.921f, 0.940f, KAISER8 }, /* Q4 */ /* 88.7% cutoff ( ~80 dB stop) 8 */
- { 80, 8, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */
- { 96, 8, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */
+ { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */
+ { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */
{128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */ /* 93.1% cutoff (~100 dB stop) 10 */
{160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */ /* 94.5% cutoff (~100 dB stop) 10 */
- {192, 16, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */
- {256, 16, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */
+ {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */
+ {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */
};
/*8,24,40,56,80,104,128,160,200,256,320*/
static double compute_func(float x, struct FuncDef *func)
@@ -545,16 +549,23 @@ static void update_filter(SpeexResamplerState *st)
st->filt_len = st->filt_len*st->num_rate / st->den_rate;
/* Round down to make sure we have a multiple of 4 */
st->filt_len &= (~0x3);
+ if (2*st->den_rate < st->num_rate)
+ st->oversample >>= 1;
+ if (4*st->den_rate < st->num_rate)
+ st->oversample >>= 1;
+ if (8*st->den_rate < st->num_rate)
+ st->oversample >>= 1;
+ if (16*st->den_rate < st->num_rate)
+ st->oversample >>= 1;
+ if (st->oversample < 1)
+ st->oversample = 1;
} else {
/* up-sampling */
st->cutoff = quality_map[st->quality].upsample_bandwidth;
}
/* Choose the resampling type that requires the least amount of memory */
- /* FIXME: The direct sinc table can be noisy in some conditions.
- * Disable it as a temporary workaround.
- */
- if (0 /*st->den_rate <= st->oversample*/)
+ if (st->den_rate <= st->oversample)
{
spx_uint32_t i;
if (!st->sinc_table)
@@ -566,10 +577,10 @@ static void update_filter(SpeexResamplerState *st)
}
for (i=0;i<st->den_rate;i++)
{
- spx_uint32_t j;
+ spx_int32_t j;
for (j=0;j<st->filt_len;j++)
{
- st->sinc_table[i*st->filt_len+j] = sinc(st->cutoff,((j-st->filt_len/2+1)-((float)i)/st->den_rate), st->filt_len, quality_map[st->quality].window_func);
+ st->sinc_table[i*st->filt_len+j] = sinc(st->cutoff,((j-(spx_int32_t)st->filt_len/2+1)-((float)i)/st->den_rate), st->filt_len, quality_map[st->quality].window_func);
}
}
#ifdef FIXED_POINT
@@ -605,6 +616,10 @@ static void update_filter(SpeexResamplerState *st)
st->int_advance = st->num_rate/st->den_rate;
st->frac_advance = st->num_rate%st->den_rate;
+
+ /* Here's the place where we update the filter memory to take into account
+ the change in filter length. It's probably the messiest part of the code
+ due to handling of lots of corner cases. */
if (!st->mem)
{
spx_uint32_t i;
@@ -623,7 +638,7 @@ static void update_filter(SpeexResamplerState *st)
/*speex_warning("reinit filter");*/
} else if (st->filt_len > old_length)
{
- spx_uint32_t i;
+ spx_int32_t i;
/* Increase the filter length */
/*speex_warning("increase filter size");*/
int old_alloc_size = st->mem_alloc_size;
@@ -632,46 +647,76 @@ static void update_filter(SpeexResamplerState *st)
st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
st->mem_alloc_size = st->filt_len-1;
}
- for (i=0;i<st->nb_channels;i++)
+ for (i=st->nb_channels-1;i>=0;i--)
{
- spx_uint32_t j;
- /* Copy data going backward */
- for (j=0;j<old_length-1;j++)
- st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*old_alloc_size+(old_length-2-j)];
- /* Then put zeros for lack of anything better */
- for (;j<st->filt_len-1;j++)
- st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0;
- /* Adjust last_sample */
- st->last_sample[i] += (st->filt_len - old_length)/2;
+ spx_int32_t j;
+ spx_uint32_t olen = old_length;
+ /*if (st->magic_samples[i])*/
+ {
+ /* Try and remove the magic samples as if nothing had happened */
+
+ /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
+ olen = old_length + 2*st->magic_samples[i];
+ for (j=old_length-2+st->magic_samples[i];j>=0;j--)
+ st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j];
+ for (j=0;j<st->magic_samples[i];j++)
+ st->mem[i*st->mem_alloc_size+j] = 0;
+ st->magic_samples[i] = 0;
+ }
+ if (st->filt_len > olen)
+ {
+ /* If the new filter length is still bigger than the "augmented" length */
+ /* Copy data going backward */
+ for (j=0;j<olen-1;j++)
+ st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)];
+ /* Then put zeros for lack of anything better */
+ for (;j<st->filt_len-1;j++)
+ st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0;
+ /* Adjust last_sample */
+ st->last_sample[i] += (st->filt_len - olen)/2;
+ } else {
+ /* Put back some of the magic! */
+ st->magic_samples[i] = (olen - st->filt_len)/2;
+ for (j=0;j<st->filt_len-1+st->magic_samples[i];j++)
+ st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
+ }
}
} else if (st->filt_len < old_length)
{
spx_uint32_t i;
- /* Reduce filter length, this a bit tricky */
- /*speex_warning("decrease filter size (unimplemented)");*/
- /* Adjust last_sample (which will likely end up negative) */
- /*st->last_sample += (st->filt_len - old_length)/2;*/
+ /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
+ samples so they can be used directly as input the next time(s) */
for (i=0;i<st->nb_channels;i++)
{
spx_uint32_t j;
+ spx_uint32_t old_magic = st->magic_samples[i];
st->magic_samples[i] = (old_length - st->filt_len)/2;
+ /* We must copy some of the memory that's no longer used */
/* Copy data going backward */
- for (j=0;j<st->filt_len-1+st->magic_samples[i];j++)
+ for (j=0;j<st->filt_len-1+st->magic_samples[i]+old_magic;j++)
st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
+ st->magic_samples[i] += old_magic;
}
}
}
-SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality)
+SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
{
- return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality);
+ return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);
}
-SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality)
+SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
{
spx_uint32_t i;
- SpeexResamplerState *st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState));
+ SpeexResamplerState *st;
+ if (quality > 10 || quality < 0)
+ {
+ if (err)
+ *err = RESAMPLER_ERR_INVALID_ARG;
+ return NULL;
+ }
+ st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState));
st->initialised = 0;
st->started = 0;
st->in_rate = 0;
@@ -708,6 +753,9 @@ SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uin
update_filter(st);
st->initialised = 1;
+ if (err)
+ *err = RESAMPLER_ERR_SUCCESS;
+
return st;
}
@@ -723,7 +771,7 @@ void speex_resampler_destroy(SpeexResamplerState *st)
-static void speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
+static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
{
int j=0;
int N = st->filt_len;
@@ -736,15 +784,19 @@ static void speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t
/* Handle the case where we have samples left from a reduction in filter length */
if (st->magic_samples[channel_index])
{
+ int istride_save;
spx_uint32_t tmp_in_len;
spx_uint32_t tmp_magic;
+
+ istride_save = st->in_stride;
tmp_in_len = st->magic_samples[channel_index];
tmp_out_len = *out_len;
- /* FIXME: Need to handle the case where the out array is too small */
/* magic_samples needs to be set to zero to avoid infinite recursion */
tmp_magic = st->magic_samples[channel_index];
st->magic_samples[channel_index] = 0;
+ st->in_stride = 1;
speex_resampler_process_native(st, channel_index, mem+N-1, &tmp_in_len, out, &tmp_out_len);
+ st->in_stride = istride_save;
/*speex_warning_int("extra samples:", tmp_out_len);*/
/* If we couldn't process all "magic" input samples, save the rest for next time */
if (tmp_in_len < tmp_magic)
@@ -754,7 +806,8 @@ static void speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t
for (i=0;i<st->magic_samples[channel_index];i++)
mem[N-1+i]=mem[N-1+i+tmp_in_len];
}
- out += tmp_out_len;
+ out += tmp_out_len*st->out_stride;
+ *out_len -= tmp_out_len;
}
/* Call the right resampler through the function ptr */
@@ -770,12 +823,13 @@ static void speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t
for (;j<N-1;j++)
mem[j] = in[st->in_stride*(j+*in_len-N+1)];
+ return RESAMPLER_ERR_SUCCESS;
}
#define FIXED_STACK_ALLOC 1024
#ifdef FIXED_POINT
-void speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
+int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
{
spx_uint32_t i;
int istride_save, ostride_save;
@@ -827,17 +881,18 @@ void speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel
*in_len -= ilen;
*out_len -= olen;
#endif
+ return RESAMPLER_ERR_SUCCESS;
}
-void speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
+int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
{
- speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
+ return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
}
#else
-void speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
+int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
{
- speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
+ return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
}
-void speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
+int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
{
spx_uint32_t i;
int istride_save, ostride_save;
@@ -889,42 +944,50 @@ void speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_i
*in_len -= ilen;
*out_len -= olen;
#endif
+ return RESAMPLER_ERR_SUCCESS;
}
#endif
-void speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
+int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
{
spx_uint32_t i;
int istride_save, ostride_save;
+ spx_uint32_t bak_len = *out_len;
istride_save = st->in_stride;
ostride_save = st->out_stride;
st->in_stride = st->out_stride = st->nb_channels;
for (i=0;i<st->nb_channels;i++)
{
+ *out_len = bak_len;
speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
}
st->in_stride = istride_save;
st->out_stride = ostride_save;
+ return RESAMPLER_ERR_SUCCESS;
}
-void speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
+
+int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
{
spx_uint32_t i;
int istride_save, ostride_save;
+ spx_uint32_t bak_len = *out_len;
istride_save = st->in_stride;
ostride_save = st->out_stride;
st->in_stride = st->out_stride = st->nb_channels;
for (i=0;i<st->nb_channels;i++)
{
+ *out_len = bak_len;
speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
}
st->in_stride = istride_save;
st->out_stride = ostride_save;
+ return RESAMPLER_ERR_SUCCESS;
}
-void speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
+int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
{
- speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
+ return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
}
void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
@@ -933,18 +996,21 @@ void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, sp
*out_rate = st->out_rate;
}
-void speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
+int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
{
- int fact;
+ spx_uint32_t fact;
+ spx_uint32_t old_den;
+ spx_uint32_t i;
if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
- return;
+ return RESAMPLER_ERR_SUCCESS;
+ old_den = st->den_rate;
st->in_rate = in_rate;
st->out_rate = out_rate;
st->num_rate = ratio_num;
st->den_rate = ratio_den;
/* FIXME: This is terribly inefficient, but who cares (at least for now)? */
- for (fact=2;fact<=sqrt(IMAX(in_rate, out_rate));fact++)
+ for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++)
{
while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0))
{
@@ -953,8 +1019,20 @@ void speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_n
}
}
+ if (old_den > 0)
+ {
+ for (i=0;i<st->nb_channels;i++)
+ {
+ st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den;
+ /* Safety net */
+ if (st->samp_frac_num[i] >= st->den_rate)
+ st->samp_frac_num[i] = st->den_rate-1;
+ }
+ }
+
if (st->initialised)
update_filter(st);
+ return RESAMPLER_ERR_SUCCESS;
}
void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
@@ -963,17 +1041,16 @@ void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num,
*ratio_den = st->den_rate;
}
-void speex_resampler_set_quality(SpeexResamplerState *st, int quality)
+int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
{
- if (quality < 0)
- quality = 0;
- if (quality > 10)
- quality = 10;
+ if (quality > 10 || quality < 0)
+ return RESAMPLER_ERR_INVALID_ARG;
if (st->quality == quality)
- return;
+ return RESAMPLER_ERR_SUCCESS;
st->quality = quality;
if (st->initialised)
update_filter(st);
+ return RESAMPLER_ERR_SUCCESS;
}
void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
@@ -1001,17 +1078,37 @@ void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *st
*stride = st->out_stride;
}
-void speex_resampler_skip_zeros(SpeexResamplerState *st)
+int speex_resampler_skip_zeros(SpeexResamplerState *st)
{
spx_uint32_t i;
for (i=0;i<st->nb_channels;i++)
st->last_sample[i] = st->filt_len/2;
+ return RESAMPLER_ERR_SUCCESS;
}
-void speex_resampler_reset_mem(SpeexResamplerState *st)
+int speex_resampler_reset_mem(SpeexResamplerState *st)
{
spx_uint32_t i;
for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
st->mem[i] = 0;
+ return RESAMPLER_ERR_SUCCESS;
}
+const char *speex_resampler_strerror(int err)
+{
+ switch (err)
+ {
+ case RESAMPLER_ERR_SUCCESS:
+ return "Success.";
+ case RESAMPLER_ERR_ALLOC_FAILED:
+ return "Memory allocation failed.";
+ case RESAMPLER_ERR_BAD_STATE:
+ return "Bad resampler state.";
+ case RESAMPLER_ERR_INVALID_ARG:
+ return "Invalid argument.";
+ case RESAMPLER_ERR_PTR_OVERLAP:
+ return "Input and output buffers overlap.";
+ default:
+ return "Unknown error. Bad error code or strange version mismatch.";
+ }
+}
diff --git a/pph/speex_resampler.h b/pph/speex_resampler.h
index 1499ce0..c44fbcd 100644
--- a/pph/speex_resampler.h
+++ b/pph/speex_resampler.h
@@ -69,31 +69,16 @@
#define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality)
#define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride)
#define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride)
-#define speex_resample_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resample_set_output_stride)
-#define speex_resample_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resample_get_output_stride)
+#define speex_resampler_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_output_stride)
+#define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride)
#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros)
#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem)
+#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror)
#define spx_int16_t short
#define spx_int32_t int
#define spx_uint16_t unsigned short
#define spx_uint32_t unsigned int
-
-#if 0
-#ifdef FIXED_POINT
-/*#define spx_word16_t spx_int16_t
-#define spx_word32_t spx_int32_t*/
-#include "arch.h"
-
-#else /* FIXED_POINT */
-
-#define spx_word16_t float
-#define spx_word32_t float
-#define MULT16_16(a,b) ((a)*(b))
-#define MULT16_32_Q15(a,b) ((a)*(b))
-#define PSHR32(a,b) (a)
-#endif /* FIXED_POINT */
-#endif
#else /* OUTSIDE_SPEEX */
@@ -110,7 +95,17 @@ extern "C" {
#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4
#define SPEEX_RESAMPLER_QUALITY_VOIP 3
#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5
+
+enum {
+ RESAMPLER_ERR_SUCCESS = 0,
+ RESAMPLER_ERR_ALLOC_FAILED = 1,
+ RESAMPLER_ERR_BAD_STATE = 2,
+ RESAMPLER_ERR_INVALID_ARG = 3,
+ RESAMPLER_ERR_PTR_OVERLAP = 4,
+ RESAMPLER_ERR_MAX_ERROR
+};
+
struct SpeexResamplerState_;
typedef struct SpeexResamplerState_ SpeexResamplerState;
@@ -126,7 +121,8 @@ typedef struct SpeexResamplerState_ SpeexResamplerState;
SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels,
spx_uint32_t in_rate,
spx_uint32_t out_rate,
- int quality);
+ int quality,
+ int *err);
/** Create a new resampler with fractional input/output rates. The sampling
* rate ratio is an arbitrary rational number with both the numerator and
@@ -146,7 +142,8 @@ SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
spx_uint32_t ratio_den,
spx_uint32_t in_rate,
spx_uint32_t out_rate,
- int quality);
+ int quality,
+ int *err);
/** Destroy a resampler state.
* @param st Resampler state
@@ -163,7 +160,7 @@ void speex_resampler_destroy(SpeexResamplerState *st);
* @param out Output buffer
* @param out_len Size of the output buffer. Returns the number of samples written
*/
-void speex_resampler_process_float(SpeexResamplerState *st,
+int speex_resampler_process_float(SpeexResamplerState *st,
spx_uint32_t channel_index,
const float *in,
spx_uint32_t *in_len,
@@ -180,7 +177,7 @@ void speex_resampler_process_float(SpeexResamplerState *st,
* @param out Output buffer
* @param out_len Size of the output buffer. Returns the number of samples written
*/
-void speex_resampler_process_int(SpeexResamplerState *st,
+int speex_resampler_process_int(SpeexResamplerState *st,
spx_uint32_t channel_index,
const spx_int16_t *in,
spx_uint32_t *in_len,
@@ -196,7 +193,7 @@ void speex_resampler_process_int(SpeexResamplerState *st,
* @param out_len Size of the output buffer. Returns the number of samples written.
* This is all per-channel.
*/
-void speex_resampler_process_interleaved_float(SpeexResamplerState *st,
+int speex_resampler_process_interleaved_float(SpeexResamplerState *st,
const float *in,
spx_uint32_t *in_len,
float *out,
@@ -211,7 +208,7 @@ void speex_resampler_process_interleaved_float(SpeexResamplerState *st,
* @param out_len Size of the output buffer. Returns the number of samples written.
* This is all per-channel.
*/
-void speex_resampler_process_interleaved_int(SpeexResamplerState *st,
+int speex_resampler_process_interleaved_int(SpeexResamplerState *st,
const spx_int16_t *in,
spx_uint32_t *in_len,
spx_int16_t *out,
@@ -222,7 +219,7 @@ void speex_resampler_process_interleaved_int(SpeexResamplerState *st,
* @param in_rate Input sampling rate (integer number of Hz).
* @param out_rate Output sampling rate (integer number of Hz).
*/
-void speex_resampler_set_rate(SpeexResamplerState *st,
+int speex_resampler_set_rate(SpeexResamplerState *st,
spx_uint32_t in_rate,
spx_uint32_t out_rate);
@@ -243,7 +240,7 @@ void speex_resampler_get_rate(SpeexResamplerState *st,
* @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
* @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
*/
-void speex_resampler_set_rate_frac(SpeexResamplerState *st,
+int speex_resampler_set_rate_frac(SpeexResamplerState *st,
spx_uint32_t ratio_num,
spx_uint32_t ratio_den,
spx_uint32_t in_rate,
@@ -264,7 +261,7 @@ void speex_resampler_get_ratio(SpeexResamplerState *st,
* @param quality Resampling quality between 0 and 10, where 0 has poor
* quality and 10 has very high quality.
*/
-void speex_resampler_set_quality(SpeexResamplerState *st,
+int speex_resampler_set_quality(SpeexResamplerState *st,
int quality);
/** Get the conversion quality.
@@ -293,14 +290,14 @@ void speex_resampler_get_input_stride(SpeexResamplerState *st,
* @param st Resampler state
* @param stride Output stride
*/
-void speex_resample_set_output_stride(SpeexResamplerState *st,
+void speex_resampler_set_output_stride(SpeexResamplerState *st,
spx_uint32_t stride);
/** Get the output stride.
* @param st Resampler state copied
* @param stride Output stride
*/
-void speex_resample_get_output_stride(SpeexResamplerState *st,
+void speex_resampler_get_output_stride(SpeexResamplerState *st,
spx_uint32_t *stride);
/** Make sure that the first samples to go out of the resamplers don't have
@@ -311,12 +308,18 @@ void speex_resample_get_output_stride(SpeexResamplerState *st,
* is the same for the first frame).
* @param st Resampler state
*/
-void speex_resampler_skip_zeros(SpeexResamplerState *st);
+int speex_resampler_skip_zeros(SpeexResamplerState *st);
/** Reset a resampler so a new (unrelated) stream can be processed.
* @param st Resampler state
*/
-void speex_resampler_reset_mem(SpeexResamplerState *st);
+int speex_resampler_reset_mem(SpeexResamplerState *st);
+
+/** Returns the English meaning for an error code
+ * @param err Error code
+ * @return English string
+ */
+const char *speex_resampler_strerror(int err);
#ifdef __cplusplus
}