speex-resampler: update to git head (i.e. rev 738e179), also update patch files, update.sh, simd_detect.* and remove obsolete patches and headers.

based on firefox-82.0.3 media/libspeex_resampler tree.
This commit is contained in:
roytam1 2023-08-20 22:38:06 +08:00
commit df798cf69e
20 changed files with 456 additions and 604 deletions

View file

@ -1,5 +1,5 @@
This source is from the Speex DSP library This source is from the Speex DSP library
(http://git.xiph.org/?p=speexdsp.git), from commit d60e75b2. (http://git.xiph.org/?p=speexdsp.git), from commit 738e179.
It consists in the audio resampling code (resampler.c) and its header files It consists in the audio resampling code (resampler.c) and its header files
dependancies, imported into the tree using the update.sh script. dependancies, imported into the tree using the update.sh script.

View file

@ -1,87 +0,0 @@
diff --git a/media/libspeex_resampler/fix-overflow.patch b/media/libspeex_resampler/fix-overflow.patch
new file mode 100644
index 0000000..e69de29
diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/src/resample.c
index a3859e3..d99595a 100644
--- a/media/libspeex_resampler/src/resample.c
+++ b/media/libspeex_resampler/src/resample.c
@@ -98,6 +98,10 @@ static void speex_free (void *ptr) {free(ptr);}
#define NULL 0
#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX 4294967296U
+#endif
+
#include "simd_detect.h"
/* Numer of elements to allocate on the stack */
@@ -603,6 +607,22 @@ static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_in
return out_sample;
}
+static int _muldiv_safe(spx_uint32_t value, spx_uint32_t mul, spx_uint32_t div)
+{
+ /* TODO: Could be simplified with 64 bits operation. */
+ spx_uint32_t major = value / div;
+ spx_uint32_t remainder = value % div;
+ return remainder <= UINT32_MAX / mul && major <= UINT32_MAX / mul &&
+ major * mul <= UINT32_MAX - remainder * mul / div;
+}
+
+static spx_uint32_t _muldiv(spx_uint32_t value, spx_uint32_t mul, spx_uint32_t div)
+{
+ spx_uint32_t major = value / div;
+ spx_uint32_t remainder = value % div;
+ return remainder * mul / div + major * mul;
+}
+
static int update_filter(SpeexResamplerState *st)
{
spx_uint32_t old_length = st->filt_len;
@@ -620,8 +640,9 @@ static int update_filter(SpeexResamplerState *st)
{
/* down-sampling */
st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate;
- /* FIXME: divide the numerator and denominator by a certain amount if they're too large */
- st->filt_len = st->filt_len*st->num_rate / st->den_rate;
+ if (!_muldiv_safe(st->filt_len,st->num_rate,st->den_rate))
+ goto fail;
+ st->filt_len = _muldiv(st->filt_len,st->num_rate,st->den_rate);
/* Round up to make sure we have a multiple of 8 for SSE */
st->filt_len = ((st->filt_len-1)&(~0x7))+8;
if (2*st->den_rate < st->num_rate)
@@ -1129,7 +1150,9 @@ EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t r
{
for (i=0;i<st->nb_channels;i++)
{
- st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den;
+ if (!_muldiv_safe(st->samp_frac_num[i],st->den_rate,old_den))
+ return RESAMPLER_ERR_OVERFLOW;
+ st->samp_frac_num[i]= _muldiv(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;
diff --git a/media/libspeex_resampler/src/speex_resampler.h b/media/libspeex_resampler/src/speex_resampler.h
index 70abe52..1286872 100644
--- a/media/libspeex_resampler/src/speex_resampler.h
+++ b/media/libspeex_resampler/src/speex_resampler.h
@@ -106,7 +106,8 @@ enum {
RESAMPLER_ERR_BAD_STATE = 2,
RESAMPLER_ERR_INVALID_ARG = 3,
RESAMPLER_ERR_PTR_OVERLAP = 4,
-
+ RESAMPLER_ERR_OVERFLOW = 5,
+
RESAMPLER_ERR_MAX_ERROR
};
diff --git a/media/libspeex_resampler/update.sh b/media/libspeex_resampler/update.sh
index d4a025b..6950bc6 100644
--- a/media/libspeex_resampler/update.sh
+++ b/media/libspeex_resampler/update.sh
@@ -26,3 +26,4 @@ patch -p3 < set-skip-frac.patch
patch -p3 < hugemem.patch
patch -p3 < remove-empty-asm-clobber.patch
patch -p3 < handle-memory-error.patch
+patch -p3 < fix-overflow.patch

View file

@ -1,46 +0,0 @@
diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/src/resample.c
index 83ad119..a3859e3 100644
--- a/media/libspeex_resampler/src/resample.c
+++ b/media/libspeex_resampler/src/resample.c
@@ -811,6 +811,12 @@ EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
return NULL;
}
st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState));
+ if (!st)
+ {
+ if (err)
+ *err = RESAMPLER_ERR_ALLOC_FAILED;
+ return NULL;
+ }
st->initialised = 0;
st->started = 0;
st->in_rate = 0;
@@ -832,9 +838,12 @@ EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
st->buffer_size = 160;
/* Per channel data */
- st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(spx_int32_t));
- st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t));
- st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t));
+ if (!(st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(spx_int32_t))))
+ goto fail;
+ if (!(st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t))))
+ goto fail;
+ if (!(st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t))))
+ goto fail;
for (i=0;i<nb_channels;i++)
{
st->last_sample[i] = 0;
@@ -857,6 +866,12 @@ EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
*err = filter_err;
return st;
+
+fail:
+ if (err)
+ *err = RESAMPLER_ERR_ALLOC_FAILED;
+ speex_resampler_destroy(st);
+ return NULL;
}
EXPORT void speex_resampler_destroy(SpeexResamplerState *st)

View file

@ -1,10 +1,7 @@
diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/src/resample.c diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/src/resample.c
--- a/media/libspeex_resampler/src/resample.c --- a/media/libspeex_resampler/src/resample.c
+++ b/media/libspeex_resampler/src/resample.c +++ b/media/libspeex_resampler/src/resample.c
@@ -56,16 +56,18 @@ @@ -59,10 +59,12 @@
(e.g. 2/3), and get rid of the rounding operations in the inner loop.
The latter both reduces CPU time and makes the algorithm more SIMD-friendly.
*/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
@ -14,22 +11,15 @@ diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/
+ +
#ifdef OUTSIDE_SPEEX #ifdef OUTSIDE_SPEEX
#include <stdlib.h> #include <stdlib.h>
static void *speex_alloc (int size) {return calloc(size,1);} 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_realloc(void *ptr, int size) {return realloc(ptr, size);}
static void speex_free (void *ptr) {free(ptr);} static void speex_free(void *ptr) {free(ptr);}
#include "speex_resampler.h" @@ -646,19 +648,20 @@
#include "arch.h"
#else /* OUTSIDE_SPEEX */
@@ -632,25 +634,26 @@ static int update_filter(SpeexResamplerS
st->oversample >>= 1;
if (st->oversample < 1)
st->oversample = 1;
} else { } else {
/* up-sampling */ /* up-sampling */
st->cutoff = quality_map[st->quality].upsample_bandwidth; st->cutoff = quality_map[st->quality].upsample_bandwidth;
} }
- /* Choose the resampling type that requires the least amount of memory */
-#ifdef RESAMPLE_FULL_SINC_TABLE -#ifdef RESAMPLE_FULL_SINC_TABLE
- use_direct = 1; - use_direct = 1;
- if (INT_MAX/sizeof(spx_word16_t)/st->den_rate < st->filt_len) - if (INT_MAX/sizeof(spx_word16_t)/st->den_rate < st->filt_len)
@ -40,17 +30,14 @@ diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/
+ when resampling any multiple of 100 to 44100. */ + when resampling any multiple of 100 to 44100. */
+ st->den_rate <= 441 + st->den_rate <= 441
#else #else
/* Choose the resampling type that requires the least amount of memory */
- use_direct = st->filt_len*st->den_rate <= st->filt_len*st->oversample+8 - use_direct = st->filt_len*st->den_rate <= st->filt_len*st->oversample+8
+ /* Choose the resampling type that requires the least amount of memory */ - && INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len;
+ st->filt_len*st->den_rate <= st->filt_len*st->oversample+8 + st->filt_len*st->den_rate <= st->filt_len*st->oversample+8
+#endif #endif
&& INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len; + && INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len;
-#endif
if (use_direct) if (use_direct)
{ {
min_sinc_table_length = st->filt_len*st->den_rate; min_sinc_table_length = st->filt_len*st->den_rate;
} else { } else {
if ((INT_MAX/sizeof(spx_word16_t)-8)/st->oversample < st->filt_len) if ((INT_MAX/sizeof(spx_word16_t)-8)/st->oversample < st->filt_len)
goto fail;
min_sinc_table_length = st->filt_len*st->oversample+8;

View file

@ -11,15 +11,12 @@ resample_neon.c:50: error: expected string literal before ')' token
diff --git a/media/libspeex_resampler/src/resample_neon.c b/media/libspeex_resampler/src/resample_neon.c diff --git a/media/libspeex_resampler/src/resample_neon.c b/media/libspeex_resampler/src/resample_neon.c
--- a/media/libspeex_resampler/src/resample_neon.c --- a/media/libspeex_resampler/src/resample_neon.c
+++ b/media/libspeex_resampler/src/resample_neon.c +++ b/media/libspeex_resampler/src/resample_neon.c
@@ -41,18 +41,17 @@ @@ -56,12 +56,11 @@
#include <arm_neon.h> #elif defined(__thumb2__)
#ifdef FIXED_POINT
#ifdef __thumb2__
static inline int32_t saturate_32bit_to_16bit(int32_t a) { static inline int32_t saturate_32bit_to_16bit(int32_t a) {
int32_t ret; int32_t ret;
asm ("ssat %[ret], #16, %[a]" asm ("ssat %[ret], #16, %[a]"
: [ret] "=&r" (ret) : [ret] "=r" (ret)
- : [a] "r" (a) - : [a] "r" (a)
- : ); - : );
+ : [a] "r" (a)); + : [a] "r" (a));
@ -28,6 +25,3 @@ diff --git a/media/libspeex_resampler/src/resample_neon.c b/media/libspeex_resam
#else #else
static inline int32_t saturate_32bit_to_16bit(int32_t a) { static inline int32_t saturate_32bit_to_16bit(int32_t a) {
int32_t ret; int32_t ret;
asm ("vmov.s32 d0[0], %[a]\n"
"vqmovn.s32 d0, q0\n"
"vmov.s16 %[ret], d0[0]\n"

View file

@ -0,0 +1,19 @@
diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/src/resample.c
--- a/media/libspeex_resampler/src/resample.c
+++ b/media/libspeex_resampler/src/resample.c
@@ -1145,12 +1145,13 @@
if (old_den > 0)
{
for (i=0;i<st->nb_channels;i++)
{
- if (multiply_frac(&st->samp_frac_num[i],st->samp_frac_num[i],st->den_rate,old_den) != RESAMPLER_ERR_SUCCESS)
- return RESAMPLER_ERR_OVERFLOW;
+ if (multiply_frac(&st->samp_frac_num[i],st->samp_frac_num[i],st->den_rate,old_den) != RESAMPLER_ERR_SUCCESS) {
+ st->samp_frac_num[i] = st->den_rate-1;
+ }
/* Safety net */
if (st->samp_frac_num[i] >= st->den_rate)
st->samp_frac_num[i] = st->den_rate-1;
}
}

View file

@ -1,35 +1,26 @@
diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/src/resample.c diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/src/resample.c
--- a/media/libspeex_resampler/src/resample.c --- a/media/libspeex_resampler/src/resample.c
+++ b/media/libspeex_resampler/src/resample.c +++ b/media/libspeex_resampler/src/resample.c
@@ -92,23 +92,17 @@ static void speex_free (void *ptr) {free @@ -94,17 +94,11 @@
#define IMAX(a,b) ((a) > (b) ? (a) : (b)) #ifndef UINT32_MAX
#define IMIN(a,b) ((a) < (b) ? (a) : (b)) #define UINT32_MAX 4294967295U
#ifndef NULL
#define NULL 0
#endif #endif
-#ifdef _USE_SSE -#ifdef USE_SSE
-#include "resample_sse.h" -#include "resample_sse.h"
-#endif -#endif
- -
-#ifdef _USE_NEON -#ifdef USE_NEON
-#include "resample_neon.h" -#include "resample_neon.h"
-#endif -#endif
+#include "simd_detect.h" +#include "simd_detect.h"
/* Numer of elements to allocate on the stack */ /* Number of elements to allocate on the stack */
#ifdef VAR_ARRAYS #ifdef VAR_ARRAYS
#define FIXED_STACK_ALLOC 8192 #define FIXED_STACK_ALLOC 8192
#else #else
#define FIXED_STACK_ALLOC 1024 @@ -344,11 +338,13 @@
#endif
@@ -344,17 +338,19 @@ static int resampler_basic_direct_single
const spx_uint32_t den_rate = st->den_rate;
spx_word32_t sum;
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
{ {
const spx_word16_t *sinct = & sinc_table[samp_frac_num*N]; const spx_word16_t *sinct = & sinc_table[samp_frac_num*N];
@ -44,13 +35,7 @@ diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/
for(j=0;j<N;j++) sum += MULT16_16(sinct[j], iptr[j]); for(j=0;j<N;j++) sum += MULT16_16(sinct[j], iptr[j]);
/* This code is slower on most DSPs which have only 2 accumulators. /* 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. @@ -362,12 +358,14 @@
I think we can trust the compiler and let it vectorize and/or unroll itself.
spx_word32_t accum[4] = {0,0,0,0};
@@ -362,18 +358,20 @@ static int resampler_basic_direct_single
accum[0] += MULT16_16(sinct[j], iptr[j]);
accum[1] += MULT16_16(sinct[j+1], iptr[j+1]);
accum[2] += MULT16_16(sinct[j+2], iptr[j+2]);
accum[3] += MULT16_16(sinct[j+3], iptr[j+3]); accum[3] += MULT16_16(sinct[j+3], iptr[j+3]);
} }
sum = accum[0] + accum[1] + accum[2] + accum[3]; sum = accum[0] + accum[1] + accum[2] + accum[3];
@ -66,13 +51,7 @@ diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/
out[out_stride * out_sample++] = sum; out[out_stride * out_sample++] = sum;
last_sample += int_advance; last_sample += int_advance;
samp_frac_num += frac_advance; samp_frac_num += frac_advance;
if (samp_frac_num >= den_rate) @@ -402,23 +400,27 @@
{
samp_frac_num -= den_rate;
@@ -402,29 +400,33 @@ static int resampler_basic_direct_double
const spx_uint32_t den_rate = st->den_rate;
double sum;
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
{ {
const spx_word16_t *sinct = & sinc_table[samp_frac_num*N]; const spx_word16_t *sinct = & sinc_table[samp_frac_num*N];
@ -102,13 +81,7 @@ diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/
out[out_stride * out_sample++] = PSHR32(sum, 15); out[out_stride * out_sample++] = PSHR32(sum, 15);
last_sample += int_advance; last_sample += int_advance;
samp_frac_num += frac_advance; samp_frac_num += frac_advance;
if (samp_frac_num >= den_rate) @@ -458,11 +460,13 @@
{
samp_frac_num -= den_rate;
@@ -458,34 +460,38 @@ static int resampler_basic_interpolate_s
#ifdef FIXED_POINT
const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
#else
const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
#endif #endif
spx_word16_t interp[4]; spx_word16_t interp[4];
@ -123,14 +96,11 @@ diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/
for(j=0;j<N;j++) { for(j=0;j<N;j++) {
const spx_word16_t curr_in=iptr[j]; const spx_word16_t curr_in=iptr[j];
accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); @@ -473,13 +477,15 @@
accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
} }
cubic_coef(frac, interp); cubic_coef(frac, interp);
sum = MULT16_32_Q15(interp[0],SHR32(accum[0], 1)) + MULT16_32_Q15(interp[1],SHR32(accum[1], 1)) + MULT16_32_Q15(interp[2],SHR32(accum[2], 1)) + MULT16_32_Q15(interp[3],SHR32(accum[3], 1)); sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]);
sum = SATURATE32PSHR(sum, 15, 32767); sum = SATURATE32PSHR(sum, 15, 32767);
-#else -#else
+#ifdef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE +#ifdef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
@ -143,13 +113,7 @@ diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/
out[out_stride * out_sample++] = sum; out[out_stride * out_sample++] = sum;
last_sample += int_advance; last_sample += int_advance;
samp_frac_num += frac_advance; samp_frac_num += frac_advance;
if (samp_frac_num >= den_rate) @@ -521,11 +527,13 @@
{
samp_frac_num -= den_rate;
@@ -521,33 +527,37 @@ static int resampler_basic_interpolate_d
#ifdef FIXED_POINT
const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
#else
const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
#endif #endif
spx_word16_t interp[4]; spx_word16_t interp[4];
@ -164,9 +128,7 @@ diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/
for(j=0;j<N;j++) { for(j=0;j<N;j++) {
const double curr_in=iptr[j]; const double curr_in=iptr[j];
accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); @@ -535,13 +543,15 @@
accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
} }
@ -183,16 +145,10 @@ diff --git a/media/libspeex_resampler/src/resample.c b/media/libspeex_resampler/
out[out_stride * out_sample++] = PSHR32(sum,15); out[out_stride * out_sample++] = PSHR32(sum,15);
last_sample += int_advance; last_sample += int_advance;
samp_frac_num += frac_advance; samp_frac_num += frac_advance;
if (samp_frac_num >= den_rate)
{
samp_frac_num -= den_rate;
diff --git a/media/libspeex_resampler/src/resample_neon.c b/media/libspeex_resampler/src/resample_neon.c diff --git a/media/libspeex_resampler/src/resample_neon.c b/media/libspeex_resampler/src/resample_neon.c
--- a/media/libspeex_resampler/src/resample_neon.c --- a/media/libspeex_resampler/src/resample_neon.c
+++ b/media/libspeex_resampler/src/resample_neon.c +++ b/media/libspeex_resampler/src/resample_neon.c
@@ -31,16 +31,18 @@ @@ -34,10 +34,12 @@
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 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@ -200,23 +156,17 @@ diff --git a/media/libspeex_resampler/src/resample_neon.c b/media/libspeex_resam
+#include "simd_detect.h" +#include "simd_detect.h"
+ +
#include <arm_neon.h> #include <stdint.h>
#ifdef FIXED_POINT #ifdef FIXED_POINT
#ifdef __thumb2__ #if defined(__aarch64__)
static inline int32_t saturate_32bit_to_16bit(int32_t a) { static inline int32_t saturate_32bit_to_16bit(int32_t a) {
int32_t ret; @@ -76,11 +78,11 @@
asm ("ssat %[ret], #16, %[a]"
: [ret] "=&r" (ret)
@@ -60,17 +62,17 @@ static inline int32_t saturate_32bit_to_
return ret;
}
#endif
#undef WORD2INT
#define WORD2INT(x) (saturate_32bit_to_16bit(x)) #define WORD2INT(x) (saturate_32bit_to_16bit(x))
#define OVERRIDE_INNER_PRODUCT_SINGLE #define OVERRIDE_INNER_PRODUCT_SINGLE
/* Only works when len % 4 == 0 */ /* Only works when len % 4 == 0 and len >= 4 */
#if defined(__aarch64__)
-static inline int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len) -static inline int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len)
+int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len) +int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len)
{ {
@ -224,18 +174,38 @@ diff --git a/media/libspeex_resampler/src/resample_neon.c b/media/libspeex_resam
uint32_t remainder = len % 16; uint32_t remainder = len % 16;
len = len - remainder; len = len - remainder;
asm volatile (" cmp %[len], #0\n" @@ -131,11 +133,11 @@
" bne 1f\n" : "cc", "v0",
" vld1.16 {d16}, [%[b]]!\n" "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23");
@@ -134,17 +136,17 @@ static inline int32_t saturate_float_to_
: "q0");
return ret; return ret;
} }
#undef WORD2INT #else
-static inline int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len)
+int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len)
{
int32_t ret;
uint32_t remainder = len % 16;
len = len - remainder;
@@ -221,11 +223,11 @@
#define WORD2INT(x) (saturate_float_to_16bit(x)) #define WORD2INT(x) (saturate_float_to_16bit(x))
#define OVERRIDE_INNER_PRODUCT_SINGLE #define OVERRIDE_INNER_PRODUCT_SINGLE
/* Only works when len % 4 == 0 */ /* Only works when len % 4 == 0 and len >= 4 */
#if defined(__aarch64__)
-static inline float inner_product_single(const float *a, const float *b, unsigned int len)
+float inner_product_single(const float *a, const float *b, unsigned int len)
{
float ret;
uint32_t remainder = len % 16;
len = len - remainder;
@@ -276,11 +278,11 @@
: "cc", "v1", "v2", "v3", "v4",
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23");
return ret;
}
#else
-static inline float inner_product_single(const float *a, const float *b, unsigned int len) -static inline float inner_product_single(const float *a, const float *b, unsigned int len)
+float inner_product_single(const float *a, const float *b, unsigned int len) +float inner_product_single(const float *a, const float *b, unsigned int len)
{ {
@ -243,9 +213,6 @@ diff --git a/media/libspeex_resampler/src/resample_neon.c b/media/libspeex_resam
uint32_t remainder = len % 16; uint32_t remainder = len % 16;
len = len - remainder; len = len - remainder;
asm volatile (" cmp %[len], #0\n"
" bne 1f\n"
" vld1.32 {q4}, [%[b]]!\n"
diff --git a/media/libspeex_resampler/src/resample_sse.c b/media/libspeex_resampler/src/resample_sse.c diff --git a/media/libspeex_resampler/src/resample_sse.c b/media/libspeex_resampler/src/resample_sse.c
--- a/media/libspeex_resampler/src/resample_sse.c --- a/media/libspeex_resampler/src/resample_sse.c
+++ b/media/libspeex_resampler/src/resample_sse.c +++ b/media/libspeex_resampler/src/resample_sse.c
@ -296,7 +263,7 @@ diff --git a/media/libspeex_resampler/src/resample_sse.c b/media/libspeex_resamp
return ret; return ret;
} }
#ifdef _USE_SSE2 #ifdef USE_SSE2
#include <emmintrin.h> #include <emmintrin.h>
#define OVERRIDE_INNER_PRODUCT_DOUBLE #define OVERRIDE_INNER_PRODUCT_DOUBLE

View file

@ -41,10 +41,10 @@
#ifdef FLOATING_POINT #ifdef FLOATING_POINT
#error You cannot compile as floating point and fixed point at the same time #error You cannot compile as floating point and fixed point at the same time
#endif #endif
#ifdef _USE_SSE #ifdef USE_SSE
#error SSE is only for floating-point #error SSE is only for floating-point
#endif #endif
#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM)) #if defined(ARM4_ASM) + defined(ARM5E_ASM) + defined(BFIN_ASM) > 1
#error Make up your mind. What CPU do you have? #error Make up your mind. What CPU do you have?
#endif #endif
#ifdef VORBIS_PSYCHO #ifdef VORBIS_PSYCHO
@ -56,10 +56,10 @@
#ifndef FLOATING_POINT #ifndef FLOATING_POINT
#error You now need to define either FIXED_POINT or FLOATING_POINT #error You now need to define either FIXED_POINT or FLOATING_POINT
#endif #endif
#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM) #if defined(ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM)
#error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions? #error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions?
#endif #endif
#ifdef FIXED_POINT_DEBUG #ifdef FIXED_DEBUG
#error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?" #error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?"
#endif #endif
@ -101,6 +101,8 @@ typedef spx_word32_t spx_sig_t;
#define SIG_SHIFT 14 #define SIG_SHIFT 14
#define GAIN_SHIFT 6 #define GAIN_SHIFT 6
#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
#define VERY_SMALL 0 #define VERY_SMALL 0
#define VERY_LARGE32 ((spx_word32_t)2147483647) #define VERY_LARGE32 ((spx_word32_t)2147483647)
#define VERY_LARGE16 ((spx_word16_t)32767) #define VERY_LARGE16 ((spx_word16_t)32767)
@ -115,9 +117,9 @@ typedef spx_word32_t spx_sig_t;
#ifdef ARM5E_ASM #ifdef ARM5E_ASM
#include "fixed_arm5e.h" #include "fixed_arm5e.h"
#elif defined (ARM4_ASM) #elif defined(ARM4_ASM)
#include "fixed_arm4.h" #include "fixed_arm4.h"
#elif defined (BFIN_ASM) #elif defined(BFIN_ASM)
#include "fixed_bfin.h" #include "fixed_bfin.h"
#endif #endif
@ -175,16 +177,13 @@ typedef float spx_word32_t;
#define ADD32(a,b) ((a)+(b)) #define ADD32(a,b) ((a)+(b))
#define SUB32(a,b) ((a)-(b)) #define SUB32(a,b) ((a)-(b))
#define MULT16_16_16(a,b) ((a)*(b)) #define MULT16_16_16(a,b) ((a)*(b))
#define MULT16_32_32(a,b) ((a)*(b))
#define MULT16_16(a,b) ((spx_word32_t)(a)*(spx_word32_t)(b)) #define MULT16_16(a,b) ((spx_word32_t)(a)*(spx_word32_t)(b))
#define MAC16_16(c,a,b) ((c)+(spx_word32_t)(a)*(spx_word32_t)(b)) #define MAC16_16(c,a,b) ((c)+(spx_word32_t)(a)*(spx_word32_t)(b))
#define MULT16_32_Q11(a,b) ((a)*(b))
#define MULT16_32_Q13(a,b) ((a)*(b))
#define MULT16_32_Q14(a,b) ((a)*(b))
#define MULT16_32_Q15(a,b) ((a)*(b)) #define MULT16_32_Q15(a,b) ((a)*(b))
#define MULT16_32_P15(a,b) ((a)*(b)) #define MULT16_32_P15(a,b) ((a)*(b))
#define MAC16_32_Q11(c,a,b) ((c)+(a)*(b))
#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b)) #define MAC16_32_Q15(c,a,b) ((c)+(a)*(b))
#define MAC16_16_Q11(c,a,b) ((c)+(a)*(b)) #define MAC16_16_Q11(c,a,b) ((c)+(a)*(b))
@ -203,11 +202,12 @@ typedef float spx_word32_t;
#define DIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b)) #define DIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b))
#define PDIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b)) #define PDIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b))
#define WORD2INT(x) ((x) < -32767.5f ? -32768 : \
((x) > 32766.5f ? 32767 : (spx_int16_t)floor(.5 + (x))))
#endif #endif
#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) #if defined(CONFIG_TI_C54X) || defined(CONFIG_TI_C55X)
/* 2 on TI C5x DSP */ /* 2 on TI C5x DSP */
#define BYTES_PER_CHAR 2 #define BYTES_PER_CHAR 2

View file

@ -69,22 +69,18 @@
/* result fits in 16 bits */ /* result fits in 16 bits */
#define MULT16_16_16(a,b) ((((spx_word16_t)(a))*((spx_word16_t)(b)))) #define MULT16_16_16(a,b) (((spx_word16_t)(a))*((spx_word16_t)(b)))
/* result fits in 32 bits */
#define MULT16_32_32(a,b) (((spx_word16_t)(a))*((spx_word32_t)(b)))
/* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */ /* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */
#define MULT16_16(a,b) (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b))) #define MULT16_16(a,b) (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b)))
#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b)))) #define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b))))
#define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12))
#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13))
#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14))
#define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11)) #define MULT16_32_P15(a,b) ADD32(MULT16_32_32(a,SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15))
#define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))) #define MULT16_32_Q15(a,b) ADD32(MULT16_32_32(a,SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))
#define MAC16_32_Q15(c,a,b) ADD32(c,MULT16_32_Q15(a,b))
#define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15))
#define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))
#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)))
#define MAC16_16_Q11(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),11))) #define MAC16_16_Q11(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),11)))

View file

@ -35,20 +35,20 @@ else:
# Only use SSE code when using floating point samples, and on x86 # Only use SSE code when using floating point samples, and on x86
if CONFIG['INTEL_ARCHITECTURE'] and not CONFIG['MOZ_SAMPLE_TYPE_S16']: if CONFIG['INTEL_ARCHITECTURE'] and not CONFIG['MOZ_SAMPLE_TYPE_S16']:
DEFINES['_USE_SSE'] = True DEFINES['USE_SSE'] = True
DEFINES['_USE_SSE2'] = True DEFINES['USE_SSE2'] = True
SOURCES += [ SOURCES += [
'resample_sse.c' 'resample_sse.c'
] ]
SOURCES['resample_sse.c'].flags += CONFIG['SSE2_FLAGS'] SOURCES['resample_sse.c'].flags += CONFIG['SSE2_FLAGS']
if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']: if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']:
DEFINES['_USE_NEON'] = True DEFINES['USE_NEON'] = True
SOURCES += [ SOURCES += [
'resample_neon.c' 'resample_neon.c'
] ]
SOURCES['resample_neon.c'].flags += CONFIG['NEON_FLAGS'] SOURCES['resample_neon.c'].flags += CONFIG['NEON_FLAGS']
# Suppress warnings in third-party code. # Suppress warnings in third-party code.
if CONFIG['GNU_CC']: if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
CFLAGS += ['-Wno-sign-compare'] CFLAGS += ['-Wno-sign-compare']

View file

@ -46,7 +46,7 @@
Smith, Julius O. Digital Audio Resampling Home Page Smith, Julius O. Digital Audio Resampling Home Page
Center for Computer Research in Music and Acoustics (CCRMA), Center for Computer Research in Music and Acoustics (CCRMA),
Stanford University, 2007. Stanford University, 2007.
Web published at http://www-ccrma.stanford.edu/~jos/resample/. Web published at https://ccrma.stanford.edu/~jos/resample/.
There is one main difference, though. This resampler uses cubic There is one main difference, though. This resampler uses cubic
interpolation instead of linear interpolation in the above paper. This interpolation instead of linear interpolation in the above paper. This
@ -65,9 +65,12 @@
#ifdef OUTSIDE_SPEEX #ifdef OUTSIDE_SPEEX
#include <stdlib.h> #include <stdlib.h>
static void *speex_alloc (int size) {return calloc(size,1);} 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_realloc(void *ptr, int size) {return realloc(ptr, size);}
static void speex_free (void *ptr) {free(ptr);} static void speex_free(void *ptr) {free(ptr);}
#ifndef EXPORT
#define EXPORT
#endif
#include "speex_resampler.h" #include "speex_resampler.h"
#include "arch.h" #include "arch.h"
#else /* OUTSIDE_SPEEX */ #else /* OUTSIDE_SPEEX */
@ -77,7 +80,6 @@ static void speex_free (void *ptr) {free(ptr);}
#include "os_support.h" #include "os_support.h"
#endif /* OUTSIDE_SPEEX */ #endif /* OUTSIDE_SPEEX */
#include "stack_alloc.h"
#include <math.h> #include <math.h>
#include <limits.h> #include <limits.h>
@ -85,12 +87,6 @@ static void speex_free (void *ptr) {free(ptr);}
#define M_PI 3.14159265358979323846 #define M_PI 3.14159265358979323846
#endif #endif
#ifdef FIXED_POINT
#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
#else
#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
#endif
#define IMAX(a,b) ((a) > (b) ? (a) : (b)) #define IMAX(a,b) ((a) > (b) ? (a) : (b))
#define IMIN(a,b) ((a) < (b) ? (a) : (b)) #define IMIN(a,b) ((a) < (b) ? (a) : (b))
@ -99,12 +95,12 @@ static void speex_free (void *ptr) {free(ptr);}
#endif #endif
#ifndef UINT32_MAX #ifndef UINT32_MAX
#define UINT32_MAX 4294967296U #define UINT32_MAX 4294967295U
#endif #endif
#include "simd_detect.h" #include "simd_detect.h"
/* Numer of elements to allocate on the stack */ /* Number of elements to allocate on the stack */
#ifdef VAR_ARRAYS #ifdef VAR_ARRAYS
#define FIXED_STACK_ALLOC 8192 #define FIXED_STACK_ALLOC 8192
#else #else
@ -196,16 +192,14 @@ struct FuncDef {
int oversample; int oversample;
}; };
static const struct FuncDef _KAISER12 = {kaiser12_table, 64}; static const struct FuncDef kaiser12_funcdef = {kaiser12_table, 64};
#define KAISER12 (&_KAISER12) #define KAISER12 (&kaiser12_funcdef)
/*static struct FuncDef _KAISER12 = {kaiser12_table, 32}; static const struct FuncDef kaiser10_funcdef = {kaiser10_table, 32};
#define KAISER12 (&_KAISER12)*/ #define KAISER10 (&kaiser10_funcdef)
static const struct FuncDef _KAISER10 = {kaiser10_table, 32}; static const struct FuncDef kaiser8_funcdef = {kaiser8_table, 32};
#define KAISER10 (&_KAISER10) #define KAISER8 (&kaiser8_funcdef)
static const struct FuncDef _KAISER8 = {kaiser8_table, 32}; static const struct FuncDef kaiser6_funcdef = {kaiser6_table, 32};
#define KAISER8 (&_KAISER8) #define KAISER6 (&kaiser6_funcdef)
static const struct FuncDef _KAISER6 = {kaiser6_table, 32};
#define KAISER6 (&_KAISER6)
struct QualityMapping { struct QualityMapping {
int base_length; int base_length;
@ -485,7 +479,7 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint3
} }
cubic_coef(frac, interp); cubic_coef(frac, interp);
sum = MULT16_32_Q15(interp[0],SHR32(accum[0], 1)) + MULT16_32_Q15(interp[1],SHR32(accum[1], 1)) + MULT16_32_Q15(interp[2],SHR32(accum[2], 1)) + MULT16_32_Q15(interp[3],SHR32(accum[3], 1)); sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]);
sum = SATURATE32PSHR(sum, 15, 32767); sum = SATURATE32PSHR(sum, 15, 32767);
#ifdef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE #ifdef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
} else { } else {
@ -590,6 +584,7 @@ static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_in
const int frac_advance = st->frac_advance; const int frac_advance = st->frac_advance;
const spx_uint32_t den_rate = st->den_rate; const spx_uint32_t den_rate = st->den_rate;
(void)in;
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
{ {
out[out_stride * out_sample++] = 0; out[out_stride * out_sample++] = 0;
@ -607,20 +602,16 @@ static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_in
return out_sample; return out_sample;
} }
static int _muldiv_safe(spx_uint32_t value, spx_uint32_t mul, spx_uint32_t div) static int multiply_frac(spx_uint32_t *result, spx_uint32_t value, spx_uint32_t num, spx_uint32_t den)
{ {
/* TODO: Could be simplified with 64 bits operation. */ spx_uint32_t major = value / den;
spx_uint32_t major = value / div; spx_uint32_t remain = value % den;
spx_uint32_t remainder = value % div; /* TODO: Could use 64 bits operation to check for overflow. But only guaranteed in C99+ */
return remainder <= UINT32_MAX / mul && major <= UINT32_MAX / mul && if (remain > UINT32_MAX / num || major > UINT32_MAX / num
major * mul <= UINT32_MAX - remainder * mul / div; || major * num > UINT32_MAX - remain * num / den)
} return RESAMPLER_ERR_OVERFLOW;
*result = remain * num / den + major * num;
static spx_uint32_t _muldiv(spx_uint32_t value, spx_uint32_t mul, spx_uint32_t div) return RESAMPLER_ERR_SUCCESS;
{
spx_uint32_t major = value / div;
spx_uint32_t remainder = value % div;
return remainder * mul / div + major * mul;
} }
static int update_filter(SpeexResamplerState *st) static int update_filter(SpeexResamplerState *st)
@ -640,9 +631,8 @@ static int update_filter(SpeexResamplerState *st)
{ {
/* down-sampling */ /* down-sampling */
st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate; st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate;
if (!_muldiv_safe(st->filt_len,st->num_rate,st->den_rate)) if (multiply_frac(&st->filt_len,st->filt_len,st->num_rate,st->den_rate) != RESAMPLER_ERR_SUCCESS)
goto fail; goto fail;
st->filt_len = _muldiv(st->filt_len,st->num_rate,st->den_rate);
/* Round up to make sure we have a multiple of 8 for SSE */ /* Round up to make sure we have a multiple of 8 for SSE */
st->filt_len = ((st->filt_len-1)&(~0x7))+8; st->filt_len = ((st->filt_len-1)&(~0x7))+8;
if (2*st->den_rate < st->num_rate) if (2*st->den_rate < st->num_rate)
@ -666,7 +656,7 @@ static int update_filter(SpeexResamplerState *st)
when resampling any multiple of 100 to 44100. */ when resampling any multiple of 100 to 44100. */
st->den_rate <= 441 st->den_rate <= 441
#else #else
/* Choose the resampling type that requires the least amount of memory */ /* Choose the resampling type that requires the least amount of memory */
st->filt_len*st->den_rate <= st->filt_len*st->oversample+8 st->filt_len*st->den_rate <= st->filt_len*st->oversample+8
#endif #endif
&& INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len; && INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len;
@ -756,16 +746,18 @@ static int update_filter(SpeexResamplerState *st)
{ {
spx_uint32_t j; spx_uint32_t j;
spx_uint32_t olen = old_length; spx_uint32_t olen = old_length;
spx_uint32_t start = i*st->mem_alloc_size;
spx_uint32_t magic_samples = st->magic_samples[i];
/*if (st->magic_samples[i])*/ /*if (st->magic_samples[i])*/
{ {
/* Try and remove the magic samples as if nothing had happened */ /* 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 */ /* 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]; olen = old_length + 2*magic_samples;
for (j=old_length-1+st->magic_samples[i];j--;) for (j=old_length-1+magic_samples;j--;)
st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j]; st->mem[start+j+magic_samples] = st->mem[i*old_alloc_size+j];
for (j=0;j<st->magic_samples[i];j++) for (j=0;j<magic_samples;j++)
st->mem[i*st->mem_alloc_size+j] = 0; st->mem[start+j] = 0;
st->magic_samples[i] = 0; st->magic_samples[i] = 0;
} }
if (st->filt_len > olen) if (st->filt_len > olen)
@ -773,17 +765,18 @@ static int update_filter(SpeexResamplerState *st)
/* If the new filter length is still bigger than the "augmented" length */ /* If the new filter length is still bigger than the "augmented" length */
/* Copy data going backward */ /* Copy data going backward */
for (j=0;j<olen-1;j++) 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)]; st->mem[start+(st->filt_len-2-j)] = st->mem[start+(olen-2-j)];
/* Then put zeros for lack of anything better */ /* Then put zeros for lack of anything better */
for (;j<st->filt_len-1;j++) for (;j<st->filt_len-1;j++)
st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0; st->mem[start+(st->filt_len-2-j)] = 0;
/* Adjust last_sample */ /* Adjust last_sample */
st->last_sample[i] += (st->filt_len - olen)/2; st->last_sample[i] += (st->filt_len - olen)/2;
} else { } else {
/* Put back some of the magic! */ /* Put back some of the magic! */
st->magic_samples[i] = (olen - st->filt_len)/2; magic_samples = (olen - st->filt_len)/2;
for (j=0;j<st->filt_len-1+st->magic_samples[i];j++) for (j=0;j<st->filt_len-1+magic_samples;j++)
st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; st->mem[start+j] = st->mem[start+j+magic_samples];
st->magic_samples[i] = magic_samples;
} }
} }
} else if (st->filt_len < old_length) } else if (st->filt_len < old_length)
@ -821,11 +814,10 @@ EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_u
EXPORT 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) EXPORT 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 *st;
int filter_err; int filter_err;
if (quality > 10 || quality < 0) if (nb_channels == 0 || ratio_num == 0 || ratio_den == 0 || quality > 10 || quality < 0)
{ {
if (err) if (err)
*err = RESAMPLER_ERR_INVALID_ARG; *err = RESAMPLER_ERR_INVALID_ARG;
@ -865,12 +857,6 @@ EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
goto fail; goto fail;
if (!(st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t)))) if (!(st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t))))
goto fail; goto fail;
for (i=0;i<nb_channels;i++)
{
st->last_sample[i] = 0;
st->magic_samples[i] = 0;
st->samp_frac_num[i] = 0;
}
speex_resampler_set_quality(st, quality); speex_resampler_set_quality(st, quality);
speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate); speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate);
@ -1007,8 +993,7 @@ EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t cha
const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1); const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
#ifdef VAR_ARRAYS #ifdef VAR_ARRAYS
const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC; const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
VARDECL(spx_word16_t *ystack); spx_word16_t ystack[ylen];
ALLOC(ystack, ylen, spx_word16_t);
#else #else
const unsigned int ylen = FIXED_STACK_ALLOC; const unsigned int ylen = FIXED_STACK_ALLOC;
spx_word16_t ystack[FIXED_STACK_ALLOC]; spx_word16_t ystack[FIXED_STACK_ALLOC];
@ -1123,11 +1108,27 @@ EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_r
*out_rate = st->out_rate; *out_rate = st->out_rate;
} }
static inline spx_uint32_t compute_gcd(spx_uint32_t a, spx_uint32_t b)
{
while (b != 0)
{
spx_uint32_t temp = a;
a = b;
b = temp % b;
}
return a;
}
EXPORT 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) EXPORT 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)
{ {
spx_uint32_t fact; spx_uint32_t fact;
spx_uint32_t old_den; spx_uint32_t old_den;
spx_uint32_t i; spx_uint32_t i;
if (ratio_num == 0 || ratio_den == 0)
return RESAMPLER_ERR_INVALID_ARG;
if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
return RESAMPLER_ERR_SUCCESS; return RESAMPLER_ERR_SUCCESS;
@ -1136,25 +1137,19 @@ EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t r
st->out_rate = out_rate; st->out_rate = out_rate;
st->num_rate = ratio_num; st->num_rate = ratio_num;
st->den_rate = ratio_den; st->den_rate = ratio_den;
/* FIXME: This is terribly inefficient, but who cares (at least for now)? */
for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++) fact = compute_gcd(st->num_rate, st->den_rate);
{
while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) st->num_rate /= fact;
{ st->den_rate /= fact;
st->num_rate /= fact;
st->den_rate /= fact;
}
}
if (old_den > 0) if (old_den > 0)
{ {
for (i=0;i<st->nb_channels;i++) for (i=0;i<st->nb_channels;i++)
{ {
if (!_muldiv_safe(st->samp_frac_num[i],st->den_rate,old_den)) if (multiply_frac(&st->samp_frac_num[i],st->samp_frac_num[i],st->den_rate,old_den) != RESAMPLER_ERR_SUCCESS) {
{ st->samp_frac_num[i] = st->den_rate-1;
st->samp_frac_num[i] = st->den_rate-1;
} }
st->samp_frac_num[i]= _muldiv(st->samp_frac_num[i],st->den_rate,old_den);
/* Safety net */ /* Safety net */
if (st->samp_frac_num[i] >= st->den_rate) if (st->samp_frac_num[i] >= st->den_rate)
st->samp_frac_num[i] = st->den_rate-1; st->samp_frac_num[i] = st->den_rate-1;

View file

@ -38,14 +38,26 @@
#include "simd_detect.h" #include "simd_detect.h"
#include <arm_neon.h> #include <stdint.h>
#ifdef FIXED_POINT #ifdef FIXED_POINT
#ifdef __thumb2__ #if defined(__aarch64__)
static inline int32_t saturate_32bit_to_16bit(int32_t a) {
int32_t ret;
asm ("fmov s0, %w[a]\n"
"sqxtn h0, s0\n"
"sxtl v0.4s, v0.4h\n"
"fmov %w[ret], s0\n"
: [ret] "=r" (ret)
: [a] "r" (a)
: "v0" );
return ret;
}
#elif defined(__thumb2__)
static inline int32_t saturate_32bit_to_16bit(int32_t a) { static inline int32_t saturate_32bit_to_16bit(int32_t a) {
int32_t ret; int32_t ret;
asm ("ssat %[ret], #16, %[a]" asm ("ssat %[ret], #16, %[a]"
: [ret] "=&r" (ret) : [ret] "=r" (ret)
: [a] "r" (a)); : [a] "r" (a));
return ret; return ret;
} }
@ -55,7 +67,7 @@ static inline int32_t saturate_32bit_to_16bit(int32_t a) {
asm ("vmov.s32 d0[0], %[a]\n" asm ("vmov.s32 d0[0], %[a]\n"
"vqmovn.s32 d0, q0\n" "vqmovn.s32 d0, q0\n"
"vmov.s16 %[ret], d0[0]\n" "vmov.s16 %[ret], d0[0]\n"
: [ret] "=&r" (ret) : [ret] "=r" (ret)
: [a] "r" (a) : [a] "r" (a)
: "q0"); : "q0");
return ret; return ret;
@ -65,7 +77,63 @@ static inline int32_t saturate_32bit_to_16bit(int32_t a) {
#define WORD2INT(x) (saturate_32bit_to_16bit(x)) #define WORD2INT(x) (saturate_32bit_to_16bit(x))
#define OVERRIDE_INNER_PRODUCT_SINGLE #define OVERRIDE_INNER_PRODUCT_SINGLE
/* Only works when len % 4 == 0 */ /* Only works when len % 4 == 0 and len >= 4 */
#if defined(__aarch64__)
int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len)
{
int32_t ret;
uint32_t remainder = len % 16;
len = len - remainder;
asm volatile (" cmp %w[len], #0\n"
" b.ne 1f\n"
" ld1 {v16.4h}, [%[b]], #8\n"
" ld1 {v20.4h}, [%[a]], #8\n"
" subs %w[remainder], %w[remainder], #4\n"
" smull v0.4s, v16.4h, v20.4h\n"
" b.ne 4f\n"
" b 5f\n"
"1:"
" ld1 {v16.4h, v17.4h, v18.4h, v19.4h}, [%[b]], #32\n"
" ld1 {v20.4h, v21.4h, v22.4h, v23.4h}, [%[a]], #32\n"
" subs %w[len], %w[len], #16\n"
" smull v0.4s, v16.4h, v20.4h\n"
" smlal v0.4s, v17.4h, v21.4h\n"
" smlal v0.4s, v18.4h, v22.4h\n"
" smlal v0.4s, v19.4h, v23.4h\n"
" b.eq 3f\n"
"2:"
" ld1 {v16.4h, v17.4h, v18.4h, v19.4h}, [%[b]], #32\n"
" ld1 {v20.4h, v21.4h, v22.4h, v23.4h}, [%[a]], #32\n"
" subs %w[len], %w[len], #16\n"
" smlal v0.4s, v16.4h, v20.4h\n"
" smlal v0.4s, v17.4h, v21.4h\n"
" smlal v0.4s, v18.4h, v22.4h\n"
" smlal v0.4s, v19.4h, v23.4h\n"
" b.ne 2b\n"
"3:"
" cmp %w[remainder], #0\n"
" b.eq 5f\n"
"4:"
" ld1 {v18.4h}, [%[b]], #8\n"
" ld1 {v22.4h}, [%[a]], #8\n"
" subs %w[remainder], %w[remainder], #4\n"
" smlal v0.4s, v18.4h, v22.4h\n"
" b.ne 4b\n"
"5:"
" saddlv d0, v0.4s\n"
" sqxtn s0, d0\n"
" sqrshrn h0, s0, #15\n"
" sxtl v0.4s, v0.4h\n"
" fmov %w[ret], s0\n"
: [ret] "=r" (ret), [a] "+r" (a), [b] "+r" (b),
[len] "+r" (len), [remainder] "+r" (remainder)
:
: "cc", "v0",
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23");
return ret;
}
#else
int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len) int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len)
{ {
int32_t ret; int32_t ret;
@ -113,33 +181,104 @@ int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int le
" vqmovn.s64 d0, q0\n" " vqmovn.s64 d0, q0\n"
" vqrshrn.s32 d0, q0, #15\n" " vqrshrn.s32 d0, q0, #15\n"
" vmov.s16 %[ret], d0[0]\n" " vmov.s16 %[ret], d0[0]\n"
: [ret] "=&r" (ret), [a] "+r" (a), [b] "+r" (b), : [ret] "=r" (ret), [a] "+r" (a), [b] "+r" (b),
[len] "+r" (len), [remainder] "+r" (remainder) [len] "+r" (len), [remainder] "+r" (remainder)
: :
: "cc", "q0", : "cc", "q0",
"d16", "d17", "d18", "d19", "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23");
"d20", "d21", "d22", "d23");
return ret; return ret;
} }
#elif defined(FLOATING_POINT) #endif // !defined(__aarch64__)
#elif defined(FLOATING_POINT)
#if defined(__aarch64__)
static inline int32_t saturate_float_to_16bit(float a) {
int32_t ret;
asm ("fcvtas s1, %s[a]\n"
"sqxtn h1, s1\n"
"sxtl v1.4s, v1.4h\n"
"fmov %w[ret], s1\n"
: [ret] "=r" (ret)
: [a] "w" (a)
: "v1");
return ret;
}
#else
static inline int32_t saturate_float_to_16bit(float a) { static inline int32_t saturate_float_to_16bit(float a) {
int32_t ret; int32_t ret;
asm ("vmov.f32 d0[0], %[a]\n" asm ("vmov.f32 d0[0], %[a]\n"
"vcvt.s32.f32 d0, d0, #15\n" "vcvt.s32.f32 d0, d0, #15\n"
"vqrshrn.s32 d0, q0, #15\n" "vqrshrn.s32 d0, q0, #15\n"
"vmov.s16 %[ret], d0[0]\n" "vmov.s16 %[ret], d0[0]\n"
: [ret] "=&r" (ret) : [ret] "=r" (ret)
: [a] "r" (a) : [a] "r" (a)
: "q0"); : "q0");
return ret; return ret;
} }
#endif
#undef WORD2INT #undef WORD2INT
#define WORD2INT(x) (saturate_float_to_16bit(x)) #define WORD2INT(x) (saturate_float_to_16bit(x))
#define OVERRIDE_INNER_PRODUCT_SINGLE #define OVERRIDE_INNER_PRODUCT_SINGLE
/* Only works when len % 4 == 0 */ /* Only works when len % 4 == 0 and len >= 4 */
#if defined(__aarch64__)
float inner_product_single(const float *a, const float *b, unsigned int len)
{
float ret;
uint32_t remainder = len % 16;
len = len - remainder;
asm volatile (" cmp %w[len], #0\n"
" b.ne 1f\n"
" ld1 {v16.4s}, [%[b]], #16\n"
" ld1 {v20.4s}, [%[a]], #16\n"
" subs %w[remainder], %w[remainder], #4\n"
" fmul v1.4s, v16.4s, v20.4s\n"
" b.ne 4f\n"
" b 5f\n"
"1:"
" ld1 {v16.4s, v17.4s, v18.4s, v19.4s}, [%[b]], #64\n"
" ld1 {v20.4s, v21.4s, v22.4s, v23.4s}, [%[a]], #64\n"
" subs %w[len], %w[len], #16\n"
" fmul v1.4s, v16.4s, v20.4s\n"
" fmul v2.4s, v17.4s, v21.4s\n"
" fmul v3.4s, v18.4s, v22.4s\n"
" fmul v4.4s, v19.4s, v23.4s\n"
" b.eq 3f\n"
"2:"
" ld1 {v16.4s, v17.4s, v18.4s, v19.4s}, [%[b]], #64\n"
" ld1 {v20.4s, v21.4s, v22.4s, v23.4s}, [%[a]], #64\n"
" subs %w[len], %w[len], #16\n"
" fmla v1.4s, v16.4s, v20.4s\n"
" fmla v2.4s, v17.4s, v21.4s\n"
" fmla v3.4s, v18.4s, v22.4s\n"
" fmla v4.4s, v19.4s, v23.4s\n"
" b.ne 2b\n"
"3:"
" fadd v16.4s, v1.4s, v2.4s\n"
" fadd v17.4s, v3.4s, v4.4s\n"
" cmp %w[remainder], #0\n"
" fadd v1.4s, v16.4s, v17.4s\n"
" b.eq 5f\n"
"4:"
" ld1 {v18.4s}, [%[b]], #16\n"
" ld1 {v22.4s}, [%[a]], #16\n"
" subs %w[remainder], %w[remainder], #4\n"
" fmla v1.4s, v18.4s, v22.4s\n"
" b.ne 4b\n"
"5:"
" faddp v1.4s, v1.4s, v1.4s\n"
" faddp %[ret].4s, v1.4s, v1.4s\n"
: [ret] "=w" (ret), [a] "+r" (a), [b] "+r" (b),
[len] "+r" (len), [remainder] "+r" (remainder)
:
: "cc", "v1", "v2", "v3", "v4",
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23");
return ret;
}
#else
float inner_product_single(const float *a, const float *b, unsigned int len) float inner_product_single(const float *a, const float *b, unsigned int len)
{ {
float ret; float ret;
@ -192,11 +331,12 @@ float inner_product_single(const float *a, const float *b, unsigned int len)
" vadd.f32 d0, d0, d1\n" " vadd.f32 d0, d0, d1\n"
" vpadd.f32 d0, d0, d0\n" " vpadd.f32 d0, d0, d0\n"
" vmov.f32 %[ret], d0[0]\n" " vmov.f32 %[ret], d0[0]\n"
: [ret] "=&r" (ret), [a] "+r" (a), [b] "+r" (b), : [ret] "=r" (ret), [a] "+r" (a), [b] "+r" (b),
[len] "+l" (len), [remainder] "+l" (remainder) [len] "+l" (len), [remainder] "+l" (remainder)
: :
: "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", : "cc", "q0", "q1", "q2", "q3",
"q9", "q10", "q11"); "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11");
return ret; return ret;
} }
#endif // defined(__aarch64__)
#endif #endif

View file

@ -73,7 +73,7 @@ float interpolate_product_single(const float *a, const float *b, unsigned int le
return ret; return ret;
} }
#ifdef _USE_SSE2 #ifdef USE_SSE2
#include <emmintrin.h> #include <emmintrin.h>
#define OVERRIDE_INNER_PRODUCT_DOUBLE #define OVERRIDE_INNER_PRODUCT_DOUBLE

View file

@ -1,3 +1,4 @@
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
/* This Source Code Form is subject to the terms of the Mozilla Public /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -7,19 +8,19 @@
#include "mozilla/SSE.h" #include "mozilla/SSE.h"
#include "mozilla/arm.h" #include "mozilla/arm.h"
#ifdef _USE_SSE2 #ifdef USE_SSE2
int moz_speex_have_double_simd() { int moz_speex_have_double_simd() {
return mozilla::supports_sse2() ? 1 : 0; return mozilla::supports_sse2() ? 1 : 0;
} }
#endif #endif
#ifdef _USE_SSE #ifdef USE_SSE
int moz_speex_have_single_simd() { int moz_speex_have_single_simd() {
return mozilla::supports_sse() ? 1 : 0; return mozilla::supports_sse() ? 1 : 0;
} }
#endif #endif
#ifdef _USE_NEON #ifdef USE_NEON
int moz_speex_have_single_simd() { int moz_speex_have_single_simd() {
return mozilla::supports_neon() ? 1 : 0; return mozilla::supports_neon() ? 1 : 0;
} }

View file

@ -1,3 +1,4 @@
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
/* This Source Code Form is subject to the terms of the Mozilla Public /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -15,18 +16,18 @@ extern "C" {
int moz_speex_have_single_simd(); int moz_speex_have_single_simd();
int moz_speex_have_double_simd(); int moz_speex_have_double_simd();
#if defined(_USE_SSE) || defined(_USE_NEON) #if defined(USE_SSE) || defined(USE_NEON)
#define OVERRIDE_INNER_PRODUCT_SINGLE #define OVERRIDE_INNER_PRODUCT_SINGLE
#define inner_product_single CAT_PREFIX(RANDOM_PREFIX,_inner_product_single) #define inner_product_single CAT_PREFIX(RANDOM_PREFIX,_inner_product_single)
spx_word32_t inner_product_single(const spx_word16_t *a, const spx_word16_t *b, unsigned int len); spx_word32_t inner_product_single(const spx_word16_t *a, const spx_word16_t *b, unsigned int len);
#endif #endif
#if defined(_USE_SSE) #if defined(USE_SSE)
#define OVERRIDE_INTERPOLATE_PRODUCT_SINGLE #define OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
#define interpolate_product_single CAT_PREFIX(RANDOM_PREFIX,_interpolate_product_single) #define interpolate_product_single CAT_PREFIX(RANDOM_PREFIX,_interpolate_product_single)
spx_word32_t interpolate_product_single(const spx_word16_t *a, const spx_word16_t *b, unsigned int len, const spx_uint32_t oversample, float *frac); spx_word32_t interpolate_product_single(const spx_word16_t *a, const spx_word16_t *b, unsigned int len, const spx_uint32_t oversample, float *frac);
#endif #endif
#if defined(_USE_SSE2) #if defined(USE_SSE2)
#define OVERRIDE_INNER_PRODUCT_DOUBLE #define OVERRIDE_INNER_PRODUCT_DOUBLE
#define inner_product_double CAT_PREFIX(RANDOM_PREFIX,_inner_product_double) #define inner_product_double CAT_PREFIX(RANDOM_PREFIX,_inner_product_double)
double inner_product_double(const float *a, const float *b, unsigned int len); double inner_product_double(const float *a, const float *b, unsigned int len);

View file

@ -84,6 +84,8 @@
#define spx_uint16_t unsigned short #define spx_uint16_t unsigned short
#define spx_uint32_t unsigned int #define spx_uint32_t unsigned int
#define speex_assert(cond)
#else /* OUTSIDE_SPEEX */ #else /* OUTSIDE_SPEEX */
#include "speexdsp_types.h" #include "speexdsp_types.h"

View file

@ -1,115 +0,0 @@
/* Copyright (C) 2002 Jean-Marc Valin */
/**
@file stack_alloc.h
@brief Temporary memory allocation on stack
*/
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Xiph.org Foundation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``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 FOUNDATION OR
CONTRIBUTORS 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.
*/
#ifndef STACK_ALLOC_H
#define STACK_ALLOC_H
#ifdef USE_ALLOCA
# ifdef WIN32
# include <malloc.h>
# else
# ifdef HAVE_ALLOCA_H
# include <alloca.h>
# else
# include <stdlib.h>
# endif
# endif
#endif
/**
* @def ALIGN(stack, size)
*
* Aligns the stack to a 'size' boundary
*
* @param stack Stack
* @param size New size boundary
*/
/**
* @def PUSH(stack, size, type)
*
* Allocates 'size' elements of type 'type' on the stack
*
* @param stack Stack
* @param size Number of elements
* @param type Type of element
*/
/**
* @def VARDECL(var)
*
* Declare variable on stack
*
* @param var Variable to declare
*/
/**
* @def ALLOC(var, size, type)
*
* Allocate 'size' elements of 'type' on stack
*
* @param var Name of variable to allocate
* @param size Number of elements
* @param type Type of element
*/
#ifdef ENABLE_VALGRIND
#include <valgrind/memcheck.h>
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
#define PUSH(stack, size, type) (VALGRIND_MAKE_NOACCESS(stack, 1000),ALIGN((stack),sizeof(type)),VALGRIND_MAKE_WRITABLE(stack, ((size)*sizeof(type))),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type))))
#else
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
#define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type))))
#endif
#if defined(VAR_ARRAYS)
#define VARDECL(var)
#define ALLOC(var, size, type) type var[size]
#elif defined(USE_ALLOCA)
#define VARDECL(var) var
#define ALLOC(var, size, type) var = alloca(sizeof(type)*(size))
#else
#define VARDECL(var) var
#define ALLOC(var, size, type) var = PUSH(stack, size, type)
#endif
#endif

View file

@ -13,17 +13,15 @@ cp $1/libspeexdsp/resample.c src
cp $1/libspeexdsp/resample_sse.h src/resample_sse.c cp $1/libspeexdsp/resample_sse.h src/resample_sse.c
cp $1/libspeexdsp/resample_neon.h src/resample_neon.c cp $1/libspeexdsp/resample_neon.h src/resample_neon.c
cp $1/libspeexdsp/arch.h src cp $1/libspeexdsp/arch.h src
cp $1/libspeexdsp/stack_alloc.h src
cp $1/libspeexdsp/fixed_generic.h src cp $1/libspeexdsp/fixed_generic.h src
cp $1/include/speex/speex_resampler.h src cp $1/include/speex/speex_resampler.h src
cp $1/AUTHORS . cp $1/AUTHORS .
cp $1/COPYING . cp $1/COPYING .
# apply outstanding local patches # apply outstanding local patches
patch -p3 < outside-speex.patch patch -p3 -i outside-speex.patch
patch -p3 < simd-detect-runtime.patch patch -p3 -i simd-detect-runtime.patch
patch -p3 < set-skip-frac.patch patch -p3 -i set-skip-frac.patch
patch -p3 < hugemem.patch patch -p3 -i hugemem.patch
patch -p3 < remove-empty-asm-clobber.patch patch -p3 -i remove-empty-asm-clobber.patch
patch -p3 < handle-memory-error.patch patch -p3 -i set-rate-overflow-no-return.patch
patch -p3 < fix-overflow.patch