audioresample: Update speex resampler to latest GIT

This commit is contained in:
Sebastian Dröge 2009-11-10 12:21:50 +01:00
parent 23f92ed8cd
commit 6723bf429f
9 changed files with 803 additions and 727 deletions

View file

@ -7,12 +7,13 @@
resample.c resample.c
speex_resampler.h speex_resampler.h
are taken from http://git.xiph.org/speex.git/ as of 2008-10-28. are taken from http://git.xiph.org/speex.git/ as of 2009-11-10.
The only changes are: The only changes are:
--- arch.h 2008-11-28 09:57:15.000000000 +0100 diff -Naur old/arch.h new/arch.h
+++ arch.h 2008-11-28 09:57:37.000000000 +0100 --- old/arch.h 2009-11-10 12:18:29.000000000 +0100
+++ new/arch.h 2009-11-10 12:19:09.000000000 +0100
@@ -78,7 +78,10 @@ @@ -78,7 +78,10 @@
#include "../include/speex/speex_types.h" #include "../include/speex/speex_types.h"
#endif #endif
@ -61,8 +62,9 @@ The only changes are:
#define QCONST16(x,bits) (x) #define QCONST16(x,bits) (x)
#define QCONST32(x,bits) (x) #define QCONST32(x,bits) (x)
--- resample.c 2008-11-28 09:56:42.000000000 +0100 diff -Naur old/resample.c new/resample.c
+++ resample.c 2008-11-01 20:38:35.000000000 +0100 --- old/resample.c 2009-11-10 12:18:51.000000000 +0100
+++ new/resample.c 2009-11-10 12:19:09.000000000 +0100
@@ -63,22 +63,27 @@ @@ -63,22 +63,27 @@
#ifdef OUTSIDE_SPEEX #ifdef OUTSIDE_SPEEX
@ -151,7 +153,7 @@ The only changes are:
static int static int
resampler_basic_direct_single (SpeexResamplerState * st, resampler_basic_direct_single (SpeexResamplerState * st,
spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len, spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
@@ -421,6 +441,7 @@ @@ -428,6 +448,7 @@
st->samp_frac_num[channel_index] = samp_frac_num; st->samp_frac_num[channel_index] = samp_frac_num;
return out_sample; return out_sample;
} }
@ -159,7 +161,7 @@ The only changes are:
#ifdef FIXED_POINT #ifdef FIXED_POINT
#else #else
@@ -476,6 +497,7 @@ @@ -483,6 +504,7 @@
} }
#endif #endif
@ -167,7 +169,7 @@ The only changes are:
static int static int
resampler_basic_interpolate_single (SpeexResamplerState * st, resampler_basic_interpolate_single (SpeexResamplerState * st,
spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len, spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
@@ -554,6 +576,7 @@ @@ -562,6 +584,7 @@
st->samp_frac_num[channel_index] = samp_frac_num; st->samp_frac_num[channel_index] = samp_frac_num;
return out_sample; return out_sample;
} }
@ -175,7 +177,7 @@ The only changes are:
#ifdef FIXED_POINT #ifdef FIXED_POINT
#else #else
@@ -584,10 +607,16 @@ @@ -592,10 +615,16 @@
PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15), PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
st->den_rate); st->den_rate);
#else #else
@ -192,7 +194,7 @@ The only changes are:
spx_word16_t interp[4]; spx_word16_t interp[4];
@@ -688,20 +717,27 @@ @@ -696,20 +725,27 @@
spx_int32_t j; spx_int32_t j;
for (j = 0; j < st->filt_len; j++) { for (j = 0; j < st->filt_len; j++) {
st->sinc_table[i * st->filt_len + j] = st->sinc_table[i * st->filt_len + j] =
@ -222,7 +224,7 @@ The only changes are:
/*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff); */ /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff); */
} else { } else {
spx_int32_t i; spx_int32_t i;
@@ -717,16 +753,24 @@ @@ -725,16 +761,24 @@
} }
for (i = -4; i < (spx_int32_t) (st->oversample * st->filt_len + 4); i++) for (i = -4; i < (spx_int32_t) (st->oversample * st->filt_len + 4); i++)
st->sinc_table[i + 4] = st->sinc_table[i + 4] =
@ -247,7 +249,7 @@ The only changes are:
/*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff); */ /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff); */
} }
st->int_advance = st->num_rate / st->den_rate; st->int_advance = st->num_rate / st->den_rate;
@@ -956,11 +1000,18 @@ @@ -964,11 +1008,18 @@
spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len, 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_int16_t * out, spx_uint32_t * out_len)
#else #else
@ -266,7 +268,7 @@ The only changes are:
{ {
int j; int j;
spx_uint32_t ilen = *in_len; spx_uint32_t ilen = *in_len;
@@ -1078,9 +1129,16 @@ @@ -1086,9 +1137,16 @@
return RESAMPLER_ERR_SUCCESS; return RESAMPLER_ERR_SUCCESS;
} }
@ -283,8 +285,9 @@ The only changes are:
{ {
spx_uint32_t i; spx_uint32_t i;
int istride_save, ostride_save; int istride_save, ostride_save;
--- speex_resampler.h 2008-11-28 09:57:15.000000000 +0100 diff -Naur old/speex_resampler.h new/speex_resampler.h
+++ speex_resampler.h 2008-11-28 09:57:37.000000000 +0100 --- old/speex_resampler.h 2009-11-10 12:18:09.000000000 +0100
+++ new/speex_resampler.h 2009-11-10 12:19:09.000000000 +0100
@@ -77,10 +77,10 @@ @@ -77,10 +77,10 @@
#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem) #define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem)
#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror) #define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror)
@ -300,7 +303,7 @@ The only changes are:
#else /* OUTSIDE_SPEEX */ #else /* OUTSIDE_SPEEX */
@@ -162,10 +162,17 @@ @@ -166,12 +166,21 @@
* @param out Output buffer * @param out Output buffer
* @param out_len Size of the output buffer. Returns the number of samples written * @param out_len Size of the output buffer. Returns the number of samples written
*/ */
@ -308,28 +311,36 @@ The only changes are:
+int speex_resampler_process_float(SpeexResamplerState *st, +int speex_resampler_process_float(SpeexResamplerState *st,
+ spx_uint32_t channel_index, + spx_uint32_t channel_index,
+ const double *in, + const double *in,
+ spx_uint32_t * in_len, double *out, spx_uint32_t * out_len); + spx_uint32_t *in_len,
+ double *out,
+ spx_uint32_t *out_len);
+#else +#else
int speex_resampler_process_float(SpeexResamplerState *st, int speex_resampler_process_float(SpeexResamplerState *st,
spx_uint32_t channel_index, spx_uint32_t channel_index,
const float *in, const float *in,
spx_uint32_t * in_len, float *out, spx_uint32_t * out_len); spx_uint32_t *in_len,
float *out,
spx_uint32_t *out_len);
+#endif +#endif
/** Resample an int array. The input and output buffers must *not* overlap. /** Resample an int array. The input and output buffers must *not* overlap.
* @param st Resampler state * @param st Resampler state
@@ -191,9 +198,15 @@ @@ -199,11 +208,19 @@
* @param out_len Size of the output buffer. Returns the number of samples written. * @param out_len Size of the output buffer. Returns the number of samples written.
* This is all per-channel. * This is all per-channel.
*/ */
+#ifdef DOUBLE_PRECISION +#ifdef DOUBLE_PRECISION
+int speex_resampler_process_interleaved_float(SpeexResamplerState *st, +int speex_resampler_process_interleaved_float(SpeexResamplerState *st,
+ const double *in, + const double *in,
+ spx_uint32_t * in_len, double *out, spx_uint32_t * out_len); + spx_uint32_t *in_len,
+ double *out,
+ spx_uint32_t *out_len);
+#else +#else
int speex_resampler_process_interleaved_float(SpeexResamplerState *st, int speex_resampler_process_interleaved_float(SpeexResamplerState *st,
const float *in, const float *in,
spx_uint32_t * in_len, float *out, spx_uint32_t * out_len); spx_uint32_t *in_len,
float *out,
spx_uint32_t *out_len);
+#endif +#endif
/** Resample an interleaved int array. The input and output buffers must *not* overlap. /** Resample an interleaved int array. The input and output buffers must *not* overlap.

View file

@ -36,93 +36,111 @@
#define FIXED_ARM4_H #define FIXED_ARM4_H
#undef MULT16_32_Q14 #undef MULT16_32_Q14
static inline spx_word32_t static inline spx_word32_t MULT16_32_Q14(spx_word16_t x, spx_word32_t y) {
MULT16_32_Q14 (spx_word16_t x, spx_word32_t y)
{
int res; int res;
int dummy; int dummy;
asm ("smull %0,%1,%2,%3 \n\t" "mov %0, %0, lsr #14 \n\t" "add %0, %0, %1, lsl #18 \n\t":"=&r" (res), asm (
"=&r" "smull %0,%1,%2,%3 \n\t"
(dummy) "mov %0, %0, lsr #14 \n\t"
"add %0, %0, %1, lsl #18 \n\t"
: "=&r"(res), "=&r" (dummy)
: "r"(y),"r"((int)x)); : "r"(y),"r"((int)x));
return(res); return(res);
} }
#undef MULT16_32_Q15 #undef MULT16_32_Q15
static inline spx_word32_t static inline spx_word32_t MULT16_32_Q15(spx_word16_t x, spx_word32_t y) {
MULT16_32_Q15 (spx_word16_t x, spx_word32_t y)
{
int res; int res;
int dummy; int dummy;
asm ("smull %0,%1,%2,%3 \n\t" "mov %0, %0, lsr #15 \n\t" "add %0, %0, %1, lsl #17 \n\t":"=&r" (res), asm (
"=&r" "smull %0,%1,%2,%3 \n\t"
(dummy) "mov %0, %0, lsr #15 \n\t"
"add %0, %0, %1, lsl #17 \n\t"
: "=&r"(res), "=&r" (dummy)
: "r"(y),"r"((int)x)); : "r"(y),"r"((int)x));
return(res); return(res);
} }
#undef DIV32_16 #undef DIV32_16
static inline short static inline short DIV32_16(int a, int b)
DIV32_16 (int a, int b)
{ {
int res=0; int res=0;
int dead1, dead2, dead3, dead4, dead5; int dead1, dead2, dead3, dead4, dead5;
__asm__ __volatile__ ("\teor %5, %0, %1\n" __asm__ __volatile__ (
"\teor %5, %0, %1\n"
"\tmovs %4, %0\n" "\tmovs %4, %0\n"
"\trsbmi %0, %0, #0 \n" "\trsbmi %0, %0, #0 \n"
"\tmovs %4, %1\n" "\tmovs %4, %1\n"
"\trsbmi %1, %1, #0 \n" "\trsbmi %1, %1, #0 \n"
"\tmov %4, #1\n" "\tmov %4, #1\n"
"\tsubs %3, %0, %1, asl #14 \n" "\tsubs %3, %0, %1, asl #14 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4, asl #14 \n" "\torrpl %2, %2, %4, asl #14 \n"
"\tsubs %3, %0, %1, asl #13 \n" "\tsubs %3, %0, %1, asl #13 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4, asl #13 \n" "\torrpl %2, %2, %4, asl #13 \n"
"\tsubs %3, %0, %1, asl #12 \n" "\tsubs %3, %0, %1, asl #12 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4, asl #12 \n" "\torrpl %2, %2, %4, asl #12 \n"
"\tsubs %3, %0, %1, asl #11 \n" "\tsubs %3, %0, %1, asl #11 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4, asl #11 \n" "\torrpl %2, %2, %4, asl #11 \n"
"\tsubs %3, %0, %1, asl #10 \n" "\tsubs %3, %0, %1, asl #10 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4, asl #10 \n" "\torrpl %2, %2, %4, asl #10 \n"
"\tsubs %3, %0, %1, asl #9 \n" "\tsubs %3, %0, %1, asl #9 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4, asl #9 \n" "\torrpl %2, %2, %4, asl #9 \n"
"\tsubs %3, %0, %1, asl #8 \n" "\tsubs %3, %0, %1, asl #8 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4, asl #8 \n" "\torrpl %2, %2, %4, asl #8 \n"
"\tsubs %3, %0, %1, asl #7 \n" "\tsubs %3, %0, %1, asl #7 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4, asl #7 \n" "\torrpl %2, %2, %4, asl #7 \n"
"\tsubs %3, %0, %1, asl #6 \n" "\tsubs %3, %0, %1, asl #6 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4, asl #6 \n" "\torrpl %2, %2, %4, asl #6 \n"
"\tsubs %3, %0, %1, asl #5 \n" "\tsubs %3, %0, %1, asl #5 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4, asl #5 \n" "\torrpl %2, %2, %4, asl #5 \n"
"\tsubs %3, %0, %1, asl #4 \n" "\tsubs %3, %0, %1, asl #4 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4, asl #4 \n" "\torrpl %2, %2, %4, asl #4 \n"
"\tsubs %3, %0, %1, asl #3 \n" "\tsubs %3, %0, %1, asl #3 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4, asl #3 \n" "\torrpl %2, %2, %4, asl #3 \n"
"\tsubs %3, %0, %1, asl #2 \n" "\tsubs %3, %0, %1, asl #2 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4, asl #2 \n" "\torrpl %2, %2, %4, asl #2 \n"
"\tsubs %3, %0, %1, asl #1 \n" "\tsubs %3, %0, %1, asl #1 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4, asl #1 \n" "\torrpl %2, %2, %4, asl #1 \n"
"\tsubs %3, %0, %1 \n" "\tsubs %3, %0, %1 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\torrpl %2, %2, %4 \n" "\torrpl %2, %2, %4 \n"
"\tmovs %5, %5, lsr #31 \n" "\tmovs %5, %5, lsr #31 \n"
"\trsbne %2, %2, #0 \n":"=r" (dead1), "=r" (dead2), "=r" (res), "\trsbne %2, %2, #0 \n"
: "=r" (dead1), "=r" (dead2), "=r" (res),
"=r" (dead3), "=r" (dead4), "=r" (dead5) "=r" (dead3), "=r" (dead4), "=r" (dead5)
: "0" (a), "1" (b), "2" (res) : "0" (a), "1" (b), "2" (res)
:"cc"); : "cc"
);
return res; return res;
} }

View file

@ -36,127 +36,139 @@
#define FIXED_ARM5E_H #define FIXED_ARM5E_H
#undef MULT16_16 #undef MULT16_16
static inline spx_word32_t static inline spx_word32_t MULT16_16(spx_word16_t x, spx_word16_t y) {
MULT16_16 (spx_word16_t x, spx_word16_t y)
{
int res; int res;
asm ("smulbb %0,%1,%2;\n":"=&r" (res) asm ("smulbb %0,%1,%2;\n"
: "=&r"(res)
: "%r"(x),"r"(y)); : "%r"(x),"r"(y));
return(res); return(res);
} }
#undef MAC16_16 #undef MAC16_16
static inline spx_word32_t static inline spx_word32_t MAC16_16(spx_word32_t a, spx_word16_t x, spx_word32_t y) {
MAC16_16 (spx_word32_t a, spx_word16_t x, spx_word32_t y)
{
int res; int res;
asm ("smlabb %0,%1,%2,%3;\n":"=&r" (res) asm ("smlabb %0,%1,%2,%3;\n"
: "=&r"(res)
: "%r"(x),"r"(y),"r"(a)); : "%r"(x),"r"(y),"r"(a));
return(res); return(res);
} }
#undef MULT16_32_Q15 #undef MULT16_32_Q15
static inline spx_word32_t static inline spx_word32_t MULT16_32_Q15(spx_word16_t x, spx_word32_t y) {
MULT16_32_Q15 (spx_word16_t x, spx_word32_t y)
{
int res; int res;
asm ("smulwb %0,%1,%2;\n":"=&r" (res) asm ("smulwb %0,%1,%2;\n"
: "=&r"(res)
: "%r"(y<<1),"r"(x)); : "%r"(y<<1),"r"(x));
return(res); return(res);
} }
#undef MAC16_32_Q15 #undef MAC16_32_Q15
static inline spx_word32_t static inline spx_word32_t MAC16_32_Q15(spx_word32_t a, spx_word16_t x, spx_word32_t y) {
MAC16_32_Q15 (spx_word32_t a, spx_word16_t x, spx_word32_t y)
{
int res; int res;
asm ("smlawb %0,%1,%2,%3;\n":"=&r" (res) asm ("smlawb %0,%1,%2,%3;\n"
: "=&r"(res)
: "%r"(y<<1),"r"(x),"r"(a)); : "%r"(y<<1),"r"(x),"r"(a));
return(res); return(res);
} }
#undef MULT16_32_Q11 #undef MULT16_32_Q11
static inline spx_word32_t static inline spx_word32_t MULT16_32_Q11(spx_word16_t x, spx_word32_t y) {
MULT16_32_Q11 (spx_word16_t x, spx_word32_t y)
{
int res; int res;
asm ("smulwb %0,%1,%2;\n":"=&r" (res) asm ("smulwb %0,%1,%2;\n"
: "=&r"(res)
: "%r"(y<<5),"r"(x)); : "%r"(y<<5),"r"(x));
return(res); return(res);
} }
#undef MAC16_32_Q11 #undef MAC16_32_Q11
static inline spx_word32_t static inline spx_word32_t MAC16_32_Q11(spx_word32_t a, spx_word16_t x, spx_word32_t y) {
MAC16_32_Q11 (spx_word32_t a, spx_word16_t x, spx_word32_t y)
{
int res; int res;
asm ("smlawb %0,%1,%2,%3;\n":"=&r" (res) asm ("smlawb %0,%1,%2,%3;\n"
: "=&r"(res)
: "%r"(y<<5),"r"(x),"r"(a)); : "%r"(y<<5),"r"(x),"r"(a));
return(res); return(res);
} }
#undef DIV32_16 #undef DIV32_16
static inline short static inline short DIV32_16(int a, int b)
DIV32_16 (int a, int b)
{ {
int res=0; int res=0;
int dead1, dead2, dead3, dead4, dead5; int dead1, dead2, dead3, dead4, dead5;
__asm__ __volatile__ ("\teor %5, %0, %1\n" __asm__ __volatile__ (
"\teor %5, %0, %1\n"
"\tmovs %4, %0\n" "\tmovs %4, %0\n"
"\trsbmi %0, %0, #0 \n" "\trsbmi %0, %0, #0 \n"
"\tmovs %4, %1\n" "\tmovs %4, %1\n"
"\trsbmi %1, %1, #0 \n" "\trsbmi %1, %1, #0 \n"
"\tmov %4, #1\n" "\tmov %4, #1\n"
"\tsubs %3, %0, %1, asl #14 \n" "\tsubs %3, %0, %1, asl #14 \n"
"\torrpl %2, %2, %4, asl #14 \n" "\torrpl %2, %2, %4, asl #14 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tsubs %3, %0, %1, asl #13 \n" "\tsubs %3, %0, %1, asl #13 \n"
"\torrpl %2, %2, %4, asl #13 \n" "\torrpl %2, %2, %4, asl #13 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tsubs %3, %0, %1, asl #12 \n" "\tsubs %3, %0, %1, asl #12 \n"
"\torrpl %2, %2, %4, asl #12 \n" "\torrpl %2, %2, %4, asl #12 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tsubs %3, %0, %1, asl #11 \n" "\tsubs %3, %0, %1, asl #11 \n"
"\torrpl %2, %2, %4, asl #11 \n" "\torrpl %2, %2, %4, asl #11 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tsubs %3, %0, %1, asl #10 \n" "\tsubs %3, %0, %1, asl #10 \n"
"\torrpl %2, %2, %4, asl #10 \n" "\torrpl %2, %2, %4, asl #10 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tsubs %3, %0, %1, asl #9 \n" "\tsubs %3, %0, %1, asl #9 \n"
"\torrpl %2, %2, %4, asl #9 \n" "\torrpl %2, %2, %4, asl #9 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tsubs %3, %0, %1, asl #8 \n" "\tsubs %3, %0, %1, asl #8 \n"
"\torrpl %2, %2, %4, asl #8 \n" "\torrpl %2, %2, %4, asl #8 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tsubs %3, %0, %1, asl #7 \n" "\tsubs %3, %0, %1, asl #7 \n"
"\torrpl %2, %2, %4, asl #7 \n" "\torrpl %2, %2, %4, asl #7 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tsubs %3, %0, %1, asl #6 \n" "\tsubs %3, %0, %1, asl #6 \n"
"\torrpl %2, %2, %4, asl #6 \n" "\torrpl %2, %2, %4, asl #6 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tsubs %3, %0, %1, asl #5 \n" "\tsubs %3, %0, %1, asl #5 \n"
"\torrpl %2, %2, %4, asl #5 \n" "\torrpl %2, %2, %4, asl #5 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tsubs %3, %0, %1, asl #4 \n" "\tsubs %3, %0, %1, asl #4 \n"
"\torrpl %2, %2, %4, asl #4 \n" "\torrpl %2, %2, %4, asl #4 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tsubs %3, %0, %1, asl #3 \n" "\tsubs %3, %0, %1, asl #3 \n"
"\torrpl %2, %2, %4, asl #3 \n" "\torrpl %2, %2, %4, asl #3 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tsubs %3, %0, %1, asl #2 \n" "\tsubs %3, %0, %1, asl #2 \n"
"\torrpl %2, %2, %4, asl #2 \n" "\torrpl %2, %2, %4, asl #2 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tsubs %3, %0, %1, asl #1 \n" "\tsubs %3, %0, %1, asl #1 \n"
"\torrpl %2, %2, %4, asl #1 \n" "\torrpl %2, %2, %4, asl #1 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tsubs %3, %0, %1 \n" "\tsubs %3, %0, %1 \n"
"\torrpl %2, %2, %4 \n" "\torrpl %2, %2, %4 \n"
"\tmovpl %0, %3 \n" "\tmovpl %0, %3 \n"
"\tmovs %5, %5, lsr #31 \n" "\tmovs %5, %5, lsr #31 \n"
"\trsbne %2, %2, #0 \n":"=r" (dead1), "=r" (dead2), "=r" (res), "\trsbne %2, %2, #0 \n"
: "=r" (dead1), "=r" (dead2), "=r" (res),
"=r" (dead3), "=r" (dead4), "=r" (dead5) "=r" (dead3), "=r" (dead4), "=r" (dead5)
: "0" (a), "1" (b), "2" (res) : "0" (a), "1" (b), "2" (res)
:"memory", "cc"); : "memory", "cc"
);
return res; return res;
} }

View file

@ -36,25 +36,35 @@
#ifndef FIXED_BFIN_H #ifndef FIXED_BFIN_H
#define FIXED_BFIN_H #define FIXED_BFIN_H
#include "bfin.h"
#undef PDIV32_16 #undef PDIV32_16
static inline spx_word16_t static inline spx_word16_t PDIV32_16(spx_word32_t a, spx_word16_t b)
PDIV32_16 (spx_word32_t a, spx_word16_t b)
{ {
spx_word32_t res, bb; spx_word32_t res, bb;
bb = b; bb = b;
a += b>>1; a += b>>1;
__asm__ ("P0 = 15;\n\t" "R0 = %1;\n\t" "R1 = %2;\n\t" __asm__ (
"P0 = 15;\n\t"
"R0 = %1;\n\t"
"R1 = %2;\n\t"
//"R0 = R0 + R1;\n\t" //"R0 = R0 + R1;\n\t"
"R0 <<= 1;\n\t" "DIVS (R0, R1);\n\t" "LOOP divide%= LC0 = P0;\n\t" "LOOP_BEGIN divide%=;\n\t" "DIVQ (R0, R1);\n\t" "LOOP_END divide%=;\n\t" "R0 = R0.L;\n\t" "%0 = R0;\n\t":"=m" "R0 <<= 1;\n\t"
(res) "DIVS (R0, R1);\n\t"
"LOOP divide%= LC0 = P0;\n\t"
"LOOP_BEGIN divide%=;\n\t"
"DIVQ (R0, R1);\n\t"
"LOOP_END divide%=;\n\t"
"R0 = R0.L;\n\t"
"%0 = R0;\n\t"
: "=m" (res)
: "m" (a), "m" (bb) : "m" (a), "m" (bb)
: "P0", "R0", "R1", "cc"); : "P0", "R0", "R1", "ASTAT" BFIN_HWLOOP0_REGS);
return res; return res;
} }
#undef DIV32_16 #undef DIV32_16
static inline spx_word16_t static inline spx_word16_t DIV32_16(spx_word32_t a, spx_word16_t b)
DIV32_16 (spx_word32_t a, spx_word16_t b)
{ {
spx_word32_t res, bb; spx_word32_t res, bb;
bb = b; bb = b;
@ -62,72 +72,104 @@ DIV32_16 (spx_word32_t a, spx_word16_t b)
(do we need to do that?)*/ (do we need to do that?)*/
if (a<0) if (a<0)
a += (b-1); a += (b-1);
__asm__ ("P0 = 15;\n\t" "R0 = %1;\n\t" "R1 = %2;\n\t" "R0 <<= 1;\n\t" "DIVS (R0, R1);\n\t" "LOOP divide%= LC0 = P0;\n\t" "LOOP_BEGIN divide%=;\n\t" "DIVQ (R0, R1);\n\t" "LOOP_END divide%=;\n\t" "R0 = R0.L;\n\t" "%0 = R0;\n\t":"=m" (res) __asm__ (
"P0 = 15;\n\t"
"R0 = %1;\n\t"
"R1 = %2;\n\t"
"R0 <<= 1;\n\t"
"DIVS (R0, R1);\n\t"
"LOOP divide%= LC0 = P0;\n\t"
"LOOP_BEGIN divide%=;\n\t"
"DIVQ (R0, R1);\n\t"
"LOOP_END divide%=;\n\t"
"R0 = R0.L;\n\t"
"%0 = R0;\n\t"
: "=m" (res)
: "m" (a), "m" (bb) : "m" (a), "m" (bb)
: "P0", "R0", "R1", "cc"); : "P0", "R0", "R1", "ASTAT" BFIN_HWLOOP0_REGS);
return res; return res;
} }
#undef MAX16 #undef MAX16
static inline spx_word16_t static inline spx_word16_t MAX16(spx_word16_t a, spx_word16_t b)
MAX16 (spx_word16_t a, spx_word16_t b)
{ {
spx_word32_t res; spx_word32_t res;
__asm__ ("%1 = %1.L (X);\n\t" "%2 = %2.L (X);\n\t" "%0 = MAX(%1,%2);":"=d" (res) __asm__ (
"%1 = %1.L (X);\n\t"
"%2 = %2.L (X);\n\t"
"%0 = MAX(%1,%2);"
: "=d" (res)
: "%d" (a), "d" (b) : "%d" (a), "d" (b)
: "ASTAT"
); );
return res; return res;
} }
#undef MULT16_32_Q15 #undef MULT16_32_Q15
static inline spx_word32_t static inline spx_word32_t MULT16_32_Q15(spx_word16_t a, spx_word32_t b)
MULT16_32_Q15 (spx_word16_t a, spx_word32_t b)
{ {
spx_word32_t res; spx_word32_t res;
__asm__ ("A1 = %2.L*%1.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %2.L*%1.H) ;\n\t":"=&W" (res), __asm__
"=&d" (
(b) "A1 = %2.L*%1.L (M);\n\t"
"A1 = A1 >>> 15;\n\t"
"%0 = (A1 += %2.L*%1.H) ;\n\t"
: "=&W" (res), "=&d" (b)
: "d" (a), "1" (b) : "d" (a), "1" (b)
: "A1"); : "A1", "ASTAT"
);
return res; return res;
} }
#undef MAC16_32_Q15 #undef MAC16_32_Q15
static inline spx_word32_t static inline spx_word32_t MAC16_32_Q15(spx_word32_t c, spx_word16_t a, spx_word32_t b)
MAC16_32_Q15 (spx_word32_t c, spx_word16_t a, spx_word32_t b)
{ {
spx_word32_t res; spx_word32_t res;
__asm__ ("A1 = %2.L*%1.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %2.L*%1.H);\n\t" "%0 = %0 + %4;\n\t":"=&W" (res), __asm__
"=&d" (
(b) "A1 = %2.L*%1.L (M);\n\t"
"A1 = A1 >>> 15;\n\t"
"%0 = (A1 += %2.L*%1.H);\n\t"
"%0 = %0 + %4;\n\t"
: "=&W" (res), "=&d" (b)
: "d" (a), "1" (b), "d" (c) : "d" (a), "1" (b), "d" (c)
: "A1"); : "A1", "ASTAT"
);
return res; return res;
} }
#undef MULT16_32_Q14 #undef MULT16_32_Q14
static inline spx_word32_t static inline spx_word32_t MULT16_32_Q14(spx_word16_t a, spx_word32_t b)
MULT16_32_Q14 (spx_word16_t a, spx_word32_t b)
{ {
spx_word32_t res; spx_word32_t res;
__asm__ ("%2 <<= 1;\n\t" "A1 = %1.L*%2.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %1.L*%2.H);\n\t":"=W" (res), "=d" (a), __asm__
"=d" (
(b) "%2 <<= 1;\n\t"
"A1 = %1.L*%2.L (M);\n\t"
"A1 = A1 >>> 15;\n\t"
"%0 = (A1 += %1.L*%2.H);\n\t"
: "=W" (res), "=d" (a), "=d" (b)
: "1" (a), "2" (b) : "1" (a), "2" (b)
: "A1"); : "A1", "ASTAT"
);
return res; return res;
} }
#undef MAC16_32_Q14 #undef MAC16_32_Q14
static inline spx_word32_t static inline spx_word32_t MAC16_32_Q14(spx_word32_t c, spx_word16_t a, spx_word32_t b)
MAC16_32_Q14 (spx_word32_t c, spx_word16_t a, spx_word32_t b)
{ {
spx_word32_t res; spx_word32_t res;
__asm__ ("%1 <<= 1;\n\t" "A1 = %2.L*%1.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %2.L*%1.H);\n\t" "%0 = %0 + %4;\n\t":"=&W" (res), __asm__
"=&d" (
(b) "%1 <<= 1;\n\t"
"A1 = %2.L*%1.L (M);\n\t"
"A1 = A1 >>> 15;\n\t"
"%0 = (A1 += %2.L*%1.H);\n\t"
"%0 = %0 + %4;\n\t"
: "=&W" (res), "=&d" (b)
: "d" (a), "1" (b), "d" (c) : "d" (a), "1" (b), "d" (c)
: "A1"); : "A1", "ASTAT"
);
return res; return res;
} }

View file

@ -47,11 +47,11 @@ extern long long spx_mips;
#define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768) #define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
#define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL) #define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
static inline short static inline short NEG16(int x)
NEG16 (int x)
{ {
int res; int res;
if (!VERIFY_SHORT (x)) { if (!VERIFY_SHORT(x))
{
fprintf (stderr, "NEG16: input is not short: %d\n", (int)x); fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
} }
res = -x; res = -x;
@ -60,12 +60,11 @@ NEG16 (int x)
spx_mips++; spx_mips++;
return res; return res;
} }
static inline int NEG32(long long x)
static inline int
NEG32 (long long x)
{ {
long long res; long long res;
if (!VERIFY_INT (x)) { if (!VERIFY_INT(x))
{
fprintf (stderr, "NEG16: input is not int: %d\n", (int)x); fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
} }
res = -x; res = -x;
@ -76,13 +75,12 @@ NEG32 (long long x)
} }
#define EXTRACT16(x) _EXTRACT16(x, __FILE__, __LINE__) #define EXTRACT16(x) _EXTRACT16(x, __FILE__, __LINE__)
static inline short static inline short _EXTRACT16(int x, char *file, int line)
_EXTRACT16 (int x, char *file, int line)
{ {
int res; int res;
if (!VERIFY_SHORT (x)) { if (!VERIFY_SHORT(x))
fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, {
file, line); fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, file, line);
} }
res = x; res = x;
spx_mips++; spx_mips++;
@ -90,13 +88,12 @@ _EXTRACT16 (int x, char *file, int line)
} }
#define EXTEND32(x) _EXTEND32(x, __FILE__, __LINE__) #define EXTEND32(x) _EXTEND32(x, __FILE__, __LINE__)
static inline int static inline int _EXTEND32(int x, char *file, int line)
_EXTEND32 (int x, char *file, int line)
{ {
int res; int res;
if (!VERIFY_SHORT (x)) { if (!VERIFY_SHORT(x))
fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, {
file, line); fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, file, line);
} }
res = x; res = x;
spx_mips++; spx_mips++;
@ -104,63 +101,59 @@ _EXTEND32 (int x, char *file, int line)
} }
#define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__) #define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__)
static inline short static inline short _SHR16(int a, int shift, char *file, int line)
_SHR16 (int a, int shift, char *file, int line)
{ {
int res; int res;
if (!VERIFY_SHORT (a) || !VERIFY_SHORT (shift)) { if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", {
a, shift, file, line); fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a, shift, file, line);
} }
res = a>>shift; res = a>>shift;
if (!VERIFY_SHORT(res)) if (!VERIFY_SHORT(res))
fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line);
file, line);
spx_mips++; spx_mips++;
return res; return res;
} }
#define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__) #define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__)
static inline short static inline short _SHL16(int a, int shift, char *file, int line)
_SHL16 (int a, int shift, char *file, int line)
{ {
int res; int res;
if (!VERIFY_SHORT (a) || !VERIFY_SHORT (shift)) { if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, {
shift, file, line); fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line);
} }
res = a<<shift; res = a<<shift;
if (!VERIFY_SHORT(res)) if (!VERIFY_SHORT(res))
fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, file, line);
file, line);
spx_mips++; spx_mips++;
return res; return res;
} }
static inline int static inline int SHR32(long long a, int shift)
SHR32 (long long a, int shift)
{ {
long long res; long long res;
if (!VERIFY_INT (a) || !VERIFY_SHORT (shift)) { if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
{
fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift); fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
} }
res = a>>shift; res = a>>shift;
if (!VERIFY_INT (res)) { if (!VERIFY_INT(res))
{
fprintf (stderr, "SHR32: output is not int: %d\n", (int)res); fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
} }
spx_mips++; spx_mips++;
return res; return res;
} }
static inline int SHL32(long long a, int shift)
static inline int
SHL32 (long long a, int shift)
{ {
long long res; long long res;
if (!VERIFY_INT (a) || !VERIFY_SHORT (shift)) { if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
{
fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int)a, shift); fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int)a, shift);
} }
res = a<<shift; res = a<<shift;
if (!VERIFY_INT (res)) { if (!VERIFY_INT(res))
{
fprintf (stderr, "SHL32: output is not int: %d\n", (int)res); fprintf (stderr, "SHL32: output is not int: %d\n", (int)res);
} }
spx_mips++; spx_mips++;
@ -178,63 +171,59 @@ SHL32 (long long a, int shift)
//#define SHL(a,shift) ((a) << (shift)) //#define SHL(a,shift) ((a) << (shift))
#define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__) #define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__)
static inline short static inline short _ADD16(int a, int b, char *file, int line)
_ADD16 (int a, int b, char *file, int line)
{ {
int res; int res;
if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, {
b, file, line); fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
} }
res = a+b; res = a+b;
if (!VERIFY_SHORT (res)) { if (!VERIFY_SHORT(res))
fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a, {
b, res, file, line); fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line);
} }
spx_mips++; spx_mips++;
return res; return res;
} }
#define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__) #define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__)
static inline short static inline short _SUB16(int a, int b, char *file, int line)
_SUB16 (int a, int b, char *file, int line)
{ {
int res; int res;
if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, {
b, file, line); fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
} }
res = a-b; res = a-b;
if (!VERIFY_SHORT(res)) if (!VERIFY_SHORT(res))
fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line);
file, line);
spx_mips++; spx_mips++;
return res; return res;
} }
#define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__) #define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__)
static inline int static inline int _ADD32(long long a, long long b, char *file, int line)
_ADD32 (long long a, long long b, char *file, int line)
{ {
long long res; long long res;
if (!VERIFY_INT (a) || !VERIFY_INT (b)) { if (!VERIFY_INT(a) || !VERIFY_INT(b))
fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", {
(int) a, (int) b, file, line); fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
} }
res = a+b; res = a+b;
if (!VERIFY_INT (res)) { if (!VERIFY_INT(res))
fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int) res, {
file, line); fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line);
} }
spx_mips++; spx_mips++;
return res; return res;
} }
static inline int static inline int SUB32(long long a, long long b)
SUB32 (long long a, long long b)
{ {
long long res; long long res;
if (!VERIFY_INT (a) || !VERIFY_INT (b)) { if (!VERIFY_INT(a) || !VERIFY_INT(b))
{
fprintf (stderr, "SUB32: inputs are not int: %d %d\n", (int)a, (int)b); fprintf (stderr, "SUB32: inputs are not int: %d %d\n", (int)a, (int)b);
} }
res = a-b; res = a-b;
@ -247,11 +236,11 @@ SUB32 (long long a, long long b)
#define ADD64(a,b) (MIPS_INC(a)+(b)) #define ADD64(a,b) (MIPS_INC(a)+(b))
/* result fits in 16 bits */ /* result fits in 16 bits */
static inline short static inline short MULT16_16_16(int a, int b)
MULT16_16_16 (int a, int b)
{ {
int res; int res;
if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b); fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
} }
res = a*b; res = a*b;
@ -262,18 +251,16 @@ MULT16_16_16 (int a, int b)
} }
#define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__) #define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__)
static inline int static inline int _MULT16_16(int a, int b, char *file, int line)
_MULT16_16 (int a, int b, char *file, int line)
{ {
long long res; long long res;
if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", {
a, b, file, line); fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
} }
res = ((long long)a)*b; res = ((long long)a)*b;
if (!VERIFY_INT(res)) if (!VERIFY_INT(res))
fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
(int) res, file, line);
spx_mips++; spx_mips++;
return res; return res;
} }
@ -285,43 +272,34 @@ _MULT16_16 (int a, int b, char *file, int line)
#define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__) #define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__)
static inline int static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line)
_MULT16_32_QX (int a, long long b, int Q, char *file, int line)
{ {
long long res; long long res;
if (!VERIFY_SHORT (a) || !VERIFY_INT (b)) { if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
fprintf (stderr, {
"MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
(int) a, (int) b, file, line);
} }
if (ABS32(b)>=(EXTEND32(1)<<(15+Q))) if (ABS32(b)>=(EXTEND32(1)<<(15+Q)))
fprintf (stderr, fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
"MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q,
(int) a, (int) b, file, line);
res = (((long long)a)*(long long)b) >> Q; res = (((long long)a)*(long long)b) >> Q;
if (!VERIFY_INT(res)) if (!VERIFY_INT(res))
fprintf (stderr, fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line);
"MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q,
(int) a, (int) b, (int) res, file, line);
spx_mips+=5; spx_mips+=5;
return res; return res;
} }
static inline int static inline int MULT16_32_PX(int a, long long b, int Q)
MULT16_32_PX (int a, long long b, int Q)
{ {
long long res; long long res;
if (!VERIFY_SHORT (a) || !VERIFY_INT (b)) { if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, {
(int) a, (int) b); fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
} }
if (ABS32(b)>=(EXTEND32(1)<<(15+Q))) if (ABS32(b)>=(EXTEND32(1)<<(15+Q)))
fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);
(int) a, (int) b);
res = ((((long long)a)*(long long)b) + ((EXTEND32(1)<<Q)>>1))>> Q; res = ((((long long)a)*(long long)b) + ((EXTEND32(1)<<Q)>>1))>> Q;
if (!VERIFY_INT(res)) if (!VERIFY_INT(res))
fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int) a, fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
(int) b, (int) res);
spx_mips+=5; spx_mips+=5;
return res; return res;
} }
@ -336,8 +314,7 @@ MULT16_32_PX (int a, long long b, int Q)
#define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15) #define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15)
#define MAC16_32_Q15(c,a,b) ADD32((c),MULT16_32_Q15((a),(b))) #define MAC16_32_Q15(c,a,b) ADD32((c),MULT16_32_Q15((a),(b)))
static inline int static inline int SATURATE(int a, int b)
SATURATE (int a, int b)
{ {
if (a>b) if (a>b)
a=b; a=b;
@ -346,43 +323,39 @@ SATURATE (int a, int b)
return a; return a;
} }
static inline int static inline int MULT16_16_Q11_32(int a, int b)
MULT16_16_Q11_32 (int a, int b)
{ {
long long res; long long res;
if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b); fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
} }
res = ((long long)a)*b; res = ((long long)a)*b;
res >>= 11; res >>= 11;
if (!VERIFY_INT(res)) if (!VERIFY_INT(res))
fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int) a, fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
(int) b, (int) res);
spx_mips+=3; spx_mips+=3;
return res; return res;
} }
static inline short MULT16_16_Q13(int a, int b)
static inline short
MULT16_16_Q13 (int a, int b)
{ {
long long res; long long res;
if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b); fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
} }
res = ((long long)a)*b; res = ((long long)a)*b;
res >>= 13; res >>= 13;
if (!VERIFY_SHORT(res)) if (!VERIFY_SHORT(res))
fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
(int) res);
spx_mips+=3; spx_mips+=3;
return res; return res;
} }
static inline short MULT16_16_Q14(int a, int b)
static inline short
MULT16_16_Q14 (int a, int b)
{ {
long long res; long long res;
if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b); fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
} }
res = ((long long)a)*b; res = ((long long)a)*b;
@ -392,28 +365,28 @@ MULT16_16_Q14 (int a, int b)
spx_mips+=3; spx_mips+=3;
return res; return res;
} }
static inline short MULT16_16_Q15(int a, int b)
static inline short
MULT16_16_Q15 (int a, int b)
{ {
long long res; long long res;
if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d\n", a, b); fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d\n", a, b);
} }
res = ((long long)a)*b; res = ((long long)a)*b;
res >>= 15; res >>= 15;
if (!VERIFY_SHORT (res)) { if (!VERIFY_SHORT(res))
{
fprintf (stderr, "MULT16_16_Q15: output is not short: %d\n", (int)res); fprintf (stderr, "MULT16_16_Q15: output is not short: %d\n", (int)res);
} }
spx_mips+=3; spx_mips+=3;
return res; return res;
} }
static inline short static inline short MULT16_16_P13(int a, int b)
MULT16_16_P13 (int a, int b)
{ {
long long res; long long res;
if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b); fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
} }
res = ((long long)a)*b; res = ((long long)a)*b;
@ -422,17 +395,15 @@ MULT16_16_P13 (int a, int b)
fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res); fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
res >>= 13; res >>= 13;
if (!VERIFY_SHORT(res)) if (!VERIFY_SHORT(res))
fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
(int) res);
spx_mips+=4; spx_mips+=4;
return res; return res;
} }
static inline short MULT16_16_P14(int a, int b)
static inline short
MULT16_16_P14 (int a, int b)
{ {
long long res; long long res;
if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b); fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
} }
res = ((long long)a)*b; res = ((long long)a)*b;
@ -441,17 +412,15 @@ MULT16_16_P14 (int a, int b)
fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res); fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
res >>= 14; res >>= 14;
if (!VERIFY_SHORT(res)) if (!VERIFY_SHORT(res))
fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
(int) res);
spx_mips+=4; spx_mips+=4;
return res; return res;
} }
static inline short MULT16_16_P15(int a, int b)
static inline short
MULT16_16_P15 (int a, int b)
{ {
long long res; long long res;
if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b); fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
} }
res = ((long long)a)*b; res = ((long long)a)*b;
@ -460,33 +429,29 @@ MULT16_16_P15 (int a, int b)
fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res); fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
res >>= 15; res >>= 15;
if (!VERIFY_SHORT(res)) if (!VERIFY_SHORT(res))
fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
(int) res);
spx_mips+=4; spx_mips+=4;
return res; return res;
} }
#define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__) #define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__)
static inline int static inline int _DIV32_16(long long a, long long b, char *file, int line)
_DIV32_16 (long long a, long long b, char *file, int line)
{ {
long long res; long long res;
if (b == 0) { if (b==0)
fprintf (stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", {
(int) a, (int) b, file, line); fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
return 0; return 0;
} }
if (!VERIFY_INT (a) || !VERIFY_SHORT (b)) { if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
fprintf (stderr, {
"DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int) a, fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
(int) b, file, line);
} }
res = a/b; res = a/b;
if (!VERIFY_SHORT (res)) { if (!VERIFY_SHORT(res))
fprintf (stderr, {
"DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int) a, fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line);
(int) b, (int) res, file, line);
if (res>32767) if (res>32767)
res = 32767; res = 32767;
if (res<-32768) if (res<-32768)
@ -497,28 +462,25 @@ _DIV32_16 (long long a, long long b, char *file, int line)
} }
#define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__) #define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__)
static inline int static inline int _DIV32(long long a, long long b, char *file, int line)
_DIV32 (long long a, long long b, char *file, int line)
{ {
long long res; long long res;
if (b == 0) { if (b==0)
fprintf (stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int) a, {
(int) b, file, line); fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
return 0; return 0;
} }
if (!VERIFY_INT (a) || !VERIFY_INT (b)) { if (!VERIFY_INT(a) || !VERIFY_INT(b))
fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", {
(int) a, (int) b, file, line); fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
} }
res = a/b; res = a/b;
if (!VERIFY_INT(res)) if (!VERIFY_INT(res))
fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int) res, fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
file, line);
spx_mips+=36; spx_mips+=36;
return res; return res;
} }
#define PDIV32(a,b) DIV32(ADD32((a),(b)>>1),b) #define PDIV32(a,b) DIV32(ADD32((a),(b)>>1),b)
#define PDIV32_16(a,b) DIV32_16(ADD32((a),(b)>>1),b) #define PDIV32_16(a,b) DIV32_16(ADD32((a),(b)>>1),b)

View file

@ -415,20 +415,27 @@ resampler_basic_direct_single (SpeexResamplerState * st,
const spx_word16_t *iptr = &in[last_sample]; const spx_word16_t *iptr = &in[last_sample];
#ifndef OVERRIDE_INNER_PRODUCT_SINGLE #ifndef OVERRIDE_INNER_PRODUCT_SINGLE
float accum[4] = { 0, 0, 0, 0 }; sum = 0;
for (j = 0; j < N; j++)
sum += MULT16_16 (sinc[j], iptr[j]);
/* This code is slower on most DSPs which have only 2 accumulators.
Plus this this forces truncation to 32 bits and you lose the HW guard bits.
I think we can trust the compiler and let it vectorize and/or unroll itself.
spx_word32_t accum[4] = {0,0,0,0};
for(j=0;j<N;j+=4) { for(j=0;j<N;j+=4) {
accum[0] += sinc[j] * iptr[j]; accum[0] += MULT16_16(sinc[j], iptr[j]);
accum[1] += sinc[j + 1] * iptr[j + 1]; accum[1] += MULT16_16(sinc[j+1], iptr[j+1]);
accum[2] += sinc[j + 2] * iptr[j + 2]; accum[2] += MULT16_16(sinc[j+2], iptr[j+2]);
accum[3] += sinc[j + 3] * iptr[j + 3]; accum[3] += MULT16_16(sinc[j+3], iptr[j+3]);
} }
sum = accum[0] + accum[1] + accum[2] + accum[3]; sum = accum[0] + accum[1] + accum[2] + accum[3];
*/
#else #else
sum = inner_product_single (sinc, iptr, N); sum = inner_product_single (sinc, iptr, N);
#endif #endif
out[out_stride * out_sample++] = PSHR32 (sum, 15); out[out_stride * out_sample++] = SATURATE32 (PSHR32 (sum, 15), 32767);
last_sample += int_advance; last_sample += int_advance;
samp_frac_num += frac_advance; samp_frac_num += frac_advance;
if (samp_frac_num >= den_rate) { if (samp_frac_num >= den_rate) {
@ -552,9 +559,10 @@ resampler_basic_interpolate_single (SpeexResamplerState * st,
cubic_coef (frac, interp); cubic_coef (frac, interp);
sum = sum =
MULT16_32_Q15 (interp[0], accum[0]) + MULT16_32_Q15 (interp[1], MULT16_32_Q15 (interp[0], SHR32 (accum[0],
accum[1]) + MULT16_32_Q15 (interp[2], 1)) + MULT16_32_Q15 (interp[1], SHR32 (accum[1],
accum[2]) + MULT16_32_Q15 (interp[3], accum[3]); 1)) + MULT16_32_Q15 (interp[2], SHR32 (accum[2],
1)) + MULT16_32_Q15 (interp[3], SHR32 (accum[3], 1));
#else #else
cubic_coef (frac, interp); cubic_coef (frac, interp);
sum = sum =
@ -563,7 +571,7 @@ resampler_basic_interpolate_single (SpeexResamplerState * st,
interp); interp);
#endif #endif
out[out_stride * out_sample++] = PSHR32 (sum, 15); out[out_stride * out_sample++] = SATURATE32 (PSHR32 (sum, 14), 32767);
last_sample += int_advance; last_sample += int_advance;
samp_frac_num += frac_advance; samp_frac_num += frac_advance;
if (samp_frac_num >= den_rate) { if (samp_frac_num >= den_rate) {

View file

@ -91,7 +91,7 @@ static inline double inner_product_double(const float *a, const float *b, unsign
sum = _mm_add_pd(sum, _mm_cvtps_pd(t)); sum = _mm_add_pd(sum, _mm_cvtps_pd(t));
sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t))); sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
} }
sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum)); sum = _mm_add_sd(sum, _mm_unpackhi_pd(sum, sum));
_mm_store_sd(&ret, sum); _mm_store_sd(&ret, sum);
return ret; return ret;
} }
@ -120,7 +120,7 @@ static inline double interpolate_product_double(const float *a, const float *b,
sum1 = _mm_mul_pd(f1, sum1); sum1 = _mm_mul_pd(f1, sum1);
sum2 = _mm_mul_pd(f2, sum2); sum2 = _mm_mul_pd(f2, sum2);
sum = _mm_add_pd(sum1, sum2); sum = _mm_add_pd(sum1, sum2);
sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum)); sum = _mm_add_sd(sum, _mm_unpackhi_pd(sum, sum));
_mm_store_sd(&ret, sum); _mm_store_sd(&ret, sum);
return ret; return ret;
} }

View file

@ -93,8 +93,7 @@
#endif /* OUTSIDE_SPEEX */ #endif /* OUTSIDE_SPEEX */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C" {
{
#endif #endif
#define SPEEX_RESAMPLER_QUALITY_MAX 10 #define SPEEX_RESAMPLER_QUALITY_MAX 10
@ -103,8 +102,7 @@ extern "C"
#define SPEEX_RESAMPLER_QUALITY_VOIP 3 #define SPEEX_RESAMPLER_QUALITY_VOIP 3
#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5 #define SPEEX_RESAMPLER_QUALITY_DESKTOP 5
enum enum {
{
RESAMPLER_ERR_SUCCESS = 0, RESAMPLER_ERR_SUCCESS = 0,
RESAMPLER_ERR_ALLOC_FAILED = 1, RESAMPLER_ERR_ALLOC_FAILED = 1,
RESAMPLER_ERR_BAD_STATE = 2, RESAMPLER_ERR_BAD_STATE = 2,
@ -127,7 +125,10 @@ extern "C"
* @retval NULL Error: not enough memory * @retval NULL Error: not enough memory
*/ */
SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels,
spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err); spx_uint32_t in_rate,
spx_uint32_t out_rate,
int quality,
int *err);
/** Create a new resampler with fractional input/output rates. The sampling /** Create a new resampler with fractional input/output rates. The sampling
* rate ratio is an arbitrary rational number with both the numerator and * rate ratio is an arbitrary rational number with both the numerator and
@ -145,7 +146,10 @@ extern "C"
SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
spx_uint32_t ratio_num, spx_uint32_t ratio_num,
spx_uint32_t ratio_den, spx_uint32_t ratio_den,
spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err); spx_uint32_t in_rate,
spx_uint32_t out_rate,
int quality,
int *err);
/** Destroy a resampler state. /** Destroy a resampler state.
* @param st Resampler state * @param st Resampler state
@ -166,12 +170,16 @@ extern "C"
int speex_resampler_process_float(SpeexResamplerState *st, int speex_resampler_process_float(SpeexResamplerState *st,
spx_uint32_t channel_index, spx_uint32_t channel_index,
const double *in, const double *in,
spx_uint32_t * in_len, double *out, spx_uint32_t * out_len); spx_uint32_t *in_len,
double *out,
spx_uint32_t *out_len);
#else #else
int speex_resampler_process_float(SpeexResamplerState *st, int speex_resampler_process_float(SpeexResamplerState *st,
spx_uint32_t channel_index, spx_uint32_t channel_index,
const float *in, const float *in,
spx_uint32_t * in_len, float *out, spx_uint32_t * out_len); spx_uint32_t *in_len,
float *out,
spx_uint32_t *out_len);
#endif #endif
/** Resample an int array. The input and output buffers must *not* overlap. /** Resample an int array. The input and output buffers must *not* overlap.
@ -187,7 +195,9 @@ extern "C"
int speex_resampler_process_int(SpeexResamplerState *st, int speex_resampler_process_int(SpeexResamplerState *st,
spx_uint32_t channel_index, spx_uint32_t channel_index,
const spx_int16_t *in, const spx_int16_t *in,
spx_uint32_t * in_len, spx_int16_t * out, spx_uint32_t * out_len); spx_uint32_t *in_len,
spx_int16_t *out,
spx_uint32_t *out_len);
/** Resample an interleaved float array. The input and output buffers must *not* overlap. /** Resample an interleaved float array. The input and output buffers must *not* overlap.
* @param st Resampler state * @param st Resampler state
@ -201,11 +211,15 @@ extern "C"
#ifdef DOUBLE_PRECISION #ifdef DOUBLE_PRECISION
int speex_resampler_process_interleaved_float(SpeexResamplerState *st, int speex_resampler_process_interleaved_float(SpeexResamplerState *st,
const double *in, const double *in,
spx_uint32_t * in_len, double *out, spx_uint32_t * out_len); spx_uint32_t *in_len,
double *out,
spx_uint32_t *out_len);
#else #else
int speex_resampler_process_interleaved_float(SpeexResamplerState *st, int speex_resampler_process_interleaved_float(SpeexResamplerState *st,
const float *in, const float *in,
spx_uint32_t * in_len, float *out, spx_uint32_t * out_len); spx_uint32_t *in_len,
float *out,
spx_uint32_t *out_len);
#endif #endif
/** Resample an interleaved int array. The input and output buffers must *not* overlap. /** Resample an interleaved int array. The input and output buffers must *not* overlap.
@ -219,7 +233,9 @@ extern "C"
*/ */
int speex_resampler_process_interleaved_int(SpeexResamplerState *st, int speex_resampler_process_interleaved_int(SpeexResamplerState *st,
const spx_int16_t *in, const spx_int16_t *in,
spx_uint32_t * in_len, spx_int16_t * out, spx_uint32_t * out_len); spx_uint32_t *in_len,
spx_int16_t *out,
spx_uint32_t *out_len);
/** Set (change) the input/output sampling rates (integer value). /** Set (change) the input/output sampling rates (integer value).
* @param st Resampler state * @param st Resampler state
@ -227,7 +243,8 @@ extern "C"
* @param out_rate Output sampling rate (integer number of Hz). * @param out_rate Output sampling rate (integer number of Hz).
*/ */
int speex_resampler_set_rate(SpeexResamplerState *st, int speex_resampler_set_rate(SpeexResamplerState *st,
spx_uint32_t in_rate, spx_uint32_t out_rate); spx_uint32_t in_rate,
spx_uint32_t out_rate);
/** Get the current input/output sampling rates (integer value). /** Get the current input/output sampling rates (integer value).
* @param st Resampler state * @param st Resampler state
@ -235,7 +252,8 @@ extern "C"
* @param out_rate Output sampling rate (integer number of Hz) copied. * @param out_rate Output sampling rate (integer number of Hz) copied.
*/ */
void speex_resampler_get_rate(SpeexResamplerState *st, void speex_resampler_get_rate(SpeexResamplerState *st,
spx_uint32_t * in_rate, spx_uint32_t * out_rate); spx_uint32_t *in_rate,
spx_uint32_t *out_rate);
/** Set (change) the input/output sampling rates and resampling ratio /** Set (change) the input/output sampling rates and resampling ratio
* (fractional values in Hz supported). * (fractional values in Hz supported).
@ -247,7 +265,9 @@ extern "C"
*/ */
int speex_resampler_set_rate_frac(SpeexResamplerState *st, int speex_resampler_set_rate_frac(SpeexResamplerState *st,
spx_uint32_t ratio_num, spx_uint32_t ratio_num,
spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate); spx_uint32_t ratio_den,
spx_uint32_t in_rate,
spx_uint32_t out_rate);
/** Get the current resampling ratio. This will be reduced to the least /** Get the current resampling ratio. This will be reduced to the least
* common denominator. * common denominator.
@ -256,21 +276,24 @@ extern "C"
* @param ratio_den Denominator of the sampling rate ratio copied * @param ratio_den Denominator of the sampling rate ratio copied
*/ */
void speex_resampler_get_ratio(SpeexResamplerState *st, void speex_resampler_get_ratio(SpeexResamplerState *st,
spx_uint32_t * ratio_num, spx_uint32_t * ratio_den); spx_uint32_t *ratio_num,
spx_uint32_t *ratio_den);
/** Set (change) the conversion quality. /** Set (change) the conversion quality.
* @param st Resampler state * @param st Resampler state
* @param quality Resampling quality between 0 and 10, where 0 has poor * @param quality Resampling quality between 0 and 10, where 0 has poor
* quality and 10 has very high quality. * quality and 10 has very high quality.
*/ */
int speex_resampler_set_quality (SpeexResamplerState * st, int quality); int speex_resampler_set_quality(SpeexResamplerState *st,
int quality);
/** Get the conversion quality. /** Get the conversion quality.
* @param st Resampler state * @param st Resampler state
* @param quality Resampling quality between 0 and 10, where 0 has poor * @param quality Resampling quality between 0 and 10, where 0 has poor
* quality and 10 has very high quality. * quality and 10 has very high quality.
*/ */
void speex_resampler_get_quality (SpeexResamplerState * st, int *quality); void speex_resampler_get_quality(SpeexResamplerState *st,
int *quality);
/** Set (change) the input stride. /** Set (change) the input stride.
* @param st Resampler state * @param st Resampler state
@ -300,12 +323,12 @@ extern "C"
void speex_resampler_get_output_stride(SpeexResamplerState *st, void speex_resampler_get_output_stride(SpeexResamplerState *st,
spx_uint32_t *stride); spx_uint32_t *stride);
/** Get the latency in input samples introduced by the resampler. /** Get the latency introduced by the resampler measured in input samples.
* @param st Resampler state * @param st Resampler state
*/ */
int speex_resampler_get_input_latency(SpeexResamplerState *st); int speex_resampler_get_input_latency(SpeexResamplerState *st);
/** Get the latency in output samples introduced by the resampler. /** Get the latency introduced by the resampler measured in output samples.
* @param st Resampler state * @param st Resampler state
*/ */
int speex_resampler_get_output_latency(SpeexResamplerState *st); int speex_resampler_get_output_latency(SpeexResamplerState *st);