SSE2 implementation of the PVQ search
[opus.git] / silk / SigProc_FIX.h
index 6a4e3f4..0f26017 100644 (file)
@@ -1,28 +1,28 @@
 /***********************************************************************
 Copyright (c) 2006-2011, Skype Limited. All rights reserved.
 Redistribution and use in source and binary forms, with or without
-modification, (subject to the limitations in the disclaimer below)
-are permitted provided that the following conditions are met:
+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 Skype Limited, nor the names of specific
-contributors, may be used to endorse or promote products derived from
-this software without specific prior written permission.
-NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
-BY THIS LICENSE. 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
-COPYRIGHT OWNER 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific 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 COPYRIGHT OWNER 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 SILK_SIGPROC_FIX_H
@@ -35,14 +35,17 @@ extern "C"
 
 /*#define silk_MACRO_COUNT */          /* Used to enable WMOPS counting */
 
-#define SILK_MAX_ORDER_LPC            16            /* max order of the LPC analysis in schur() and k2a() */
+#define SILK_MAX_ORDER_LPC            24            /* max order of the LPC analysis in schur() and k2a() */
 
-#include <stdlib.h>                                 /* for abs() */
 #include <string.h>                                 /* for memset(), memcpy(), memmove() */
 #include "typedef.h"
 #include "resampler_structs.h"
 #include "macros.h"
+#include "cpu_support.h"
 
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+#include "x86/SigProc_FIX_sse.h"
+#endif
 
 /********************************************************************/
 /*                    SIGNAL PROCESSING FUNCTIONS                   */
@@ -52,19 +55,20 @@ extern "C"
  * Initialize/reset the resampler state for a given pair of input/output sampling rates
 */
 opus_int silk_resampler_init(
-    silk_resampler_state_struct *S,                 /* I/O   Resampler state                                            */
-    opus_int32                  Fs_Hz_in,           /* I     Input sampling rate (Hz)                                   */
-    opus_int32                  Fs_Hz_out           /* I     Output sampling rate (Hz)                                  */
+    silk_resampler_state_struct *S,                 /* I/O  Resampler state                                             */
+    opus_int32                  Fs_Hz_in,           /* I    Input sampling rate (Hz)                                    */
+    opus_int32                  Fs_Hz_out,          /* I    Output sampling rate (Hz)                                   */
+    opus_int                    forEnc              /* I    If 1: encoder; if 0: decoder                                */
 );
 
 /*!
  * Resampler: convert from one sampling rate to another
  */
 opus_int silk_resampler(
-    silk_resampler_state_struct *S,                 /* I/O   Resampler state                                            */
-    opus_int16                  out[],              /* O     Output signal                                              */
-    const opus_int16            in[],               /* I     Input signal                                               */
-    opus_int32                  inLen               /* I     Number of input samples                                    */
+    silk_resampler_state_struct *S,                 /* I/O  Resampler state                                             */
+    opus_int16                  out[],              /* O    Output signal                                               */
+    const opus_int16            in[],               /* I    Input signal                                                */
+    opus_int32                  inLen               /* I    Number of input samples                                     */
 );
 
 /*!
@@ -108,7 +112,8 @@ void silk_LPC_analysis_filter(
     const opus_int16            *in,                /* I    Input signal                                                */
     const opus_int16            *B,                 /* I    MA prediction coefficients, Q12 [order]                     */
     const opus_int32            len,                /* I    Signal length                                               */
-    const opus_int32            d                   /* I    Filter order                                                */
+    const opus_int32            d,                  /* I    Filter order                                                */
+    int                         arch                /* I    Run-time architecture                                       */
 );
 
 /* Chirp (bandwidth expand) LP AR filter */
@@ -127,21 +132,20 @@ void silk_bwexpander_32(
 
 /* Compute inverse of LPC prediction gain, and                           */
 /* test if LPC coefficients are stable (all poles within unit circle)    */
-opus_int silk_LPC_inverse_pred_gain(                /* O   Returns 1 if unstable, otherwise 0                           */
-    opus_int32                  *invGain_Q30,       /* O   Inverse prediction gain, Q30 energy domain                   */
+opus_int32 silk_LPC_inverse_pred_gain(              /* O   Returns inverse prediction gain in energy domain, Q30        */
     const opus_int16            *A_Q12,             /* I   Prediction coefficients, Q12 [order]                         */
     const opus_int              order               /* I   Prediction order                                             */
 );
 
-opus_int silk_LPC_inverse_pred_gain_Q24(            /* O    Returns 1 if unstable, otherwise 0                          */
-    opus_int32                  *invGain_Q30,       /* O    Inverse prediction gain, Q30 energy domain                  */
-    const opus_int32            *A_Q24,             /* I    Prediction coefficients, Q24 [order]                        */
+/* For input in Q24 domain */
+opus_int32 silk_LPC_inverse_pred_gain_Q24(          /* O    Returns inverse prediction gain in energy domain, Q30       */
+    const opus_int32            *A_Q24,             /* I    Prediction coefficients [order]                             */
     const opus_int              order               /* I    Prediction order                                            */
 );
 
 /* Split signal in two decimated bands using first-order allpass filters */
 void silk_ana_filt_bank_1(
-    const opus_int16            *in,                /* I    Input signal [N]                                            */ 
+    const opus_int16            *in,                /* I    Input signal [N]                                            */
     opus_int32                  *S,                 /* I/O  State vector [2]                                            */
     opus_int16                  *outL,              /* O    Low band [N/2]                                              */
     opus_int16                  *outH,              /* O    High band [N/2]                                             */
@@ -154,27 +158,21 @@ void silk_ana_filt_bank_1(
 
 /* Approximation of 128 * log2() (exact inverse of approx 2^() below) */
 /* Convert input to a log scale    */
-opus_int32 silk_lin2log( 
+opus_int32 silk_lin2log(
     const opus_int32            inLin               /* I  input in linear scale                                         */
 );
 
 /* Approximation of a sigmoid function */
-opus_int silk_sigm_Q15( 
+opus_int silk_sigm_Q15(
     opus_int                    in_Q5               /* I                                                                */
 );
 
 /* Approximation of 2^() (exact inverse of approx log2() above) */
 /* Convert input to a linear scale */
-opus_int32 silk_log2lin( 
+opus_int32 silk_log2lin(
     const opus_int32            inLog_Q7            /* I  input on log scale                                            */
 );
 
-/* Function that returns the maximum absolut value of the input vector */
-opus_int16 silk_int16_array_maxabs(                 /* O   Maximum absolute value, max: 2^15-1                          */
-    const opus_int16            *vec,               /* I   Input vector  [len]                                          */
-    const opus_int32            len                 /* I   Length of input vector                                       */
-);
-
 /* Compute number of bits to right shift the sum of squares of a vector    */
 /* of int16s to make it fit in an int32                                    */
 void silk_sum_sqr_shift(
@@ -234,7 +232,8 @@ void silk_autocorr(
     opus_int                    *scale,             /* O    Scaling of the correlation vector                           */
     const opus_int16            *inputData,         /* I    Input data to correlate                                     */
     const opus_int              inputDataSize,      /* I    Length of input                                             */
-    const opus_int              correlationCount    /* I    Number of correlation taps to compute                       */
+    const opus_int              correlationCount,   /* I    Number of correlation taps to compute                       */
+    int                         arch                /* I    Run-time architecture                                       */
 );
 
 void silk_decode_pitch(
@@ -253,10 +252,11 @@ opus_int silk_pitch_analysis_core(                  /* O    Voicing estimate: 0
     opus_int                    *LTPCorr_Q15,       /* I/O  Normalized correlation; input: value from previous frame    */
     opus_int                    prevLag,            /* I    Last lag of previous frame; set to zero is unvoiced         */
     const opus_int32            search_thres1_Q16,  /* I    First stage threshold for lag candidates 0 - 1              */
-    const opus_int              search_thres2_Q15,  /* I    Final threshold for lag candidates 0 - 1                    */
+    const opus_int              search_thres2_Q13,  /* I    Final threshold for lag candidates 0 - 1                    */
     const opus_int              Fs_kHz,             /* I    Sample frequency (kHz)                                      */
     const opus_int              complexity,         /* I    Complexity setting, 0-2, where 2 is highest                 */
-    const opus_int              nb_subfr            /* I    number of 5 ms subframes                                    */
+    const opus_int              nb_subfr,           /* I    number of 5 ms subframes                                    */
+    int                         arch                /* I    Run-time architecture                                       */
 );
 
 /* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients      */
@@ -274,6 +274,15 @@ void silk_NLSF2A(
     const opus_int              d                   /* I    filter order (should be even)                               */
 );
 
+/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */
+void silk_LPC_fit(
+    opus_int16                  *a_QOUT,            /* O    Output signal                                               */
+    opus_int32                  *a_QIN,             /* I/O  Input signal                                                */
+    const opus_int              QOUT,               /* I    Input Q domain                                              */
+    const opus_int              QIN,                /* I    Input Q domain                                              */
+    const opus_int              d                   /* I    Filter order                                                */
+);
+
 void silk_insertion_sort_increasing(
     opus_int32                  *a,                 /* I/O   Unsorted / Sorted vector                                   */
     opus_int                    *idx,               /* O     Index vector for the sorted elements                       */
@@ -308,15 +317,16 @@ void silk_NLSF_VQ_weights_laroia(
 );
 
 /* Compute reflection coefficients from input signal */
-void silk_burg_modified(
+void silk_burg_modified_c(
     opus_int32                  *res_nrg,           /* O    Residual energy                                             */
     opus_int                    *res_nrg_Q,         /* O    Residual energy Q value                                     */
     opus_int32                  A_Q16[],            /* O    Prediction coefficients (length order)                      */
     const opus_int16            x[],                /* I    Input signal, length: nb_subfr * ( D + subfr_length )       */
-    const opus_int              subfr_length,       /* I    Input signal subframe length (incl. D preceeding samples)   */
+    const opus_int32            minInvGain_Q30,     /* I    Inverse of max prediction gain                              */
+    const opus_int              subfr_length,       /* I    Input signal subframe length (incl. D preceding samples)    */
     const opus_int              nb_subfr,           /* I    Number of subframes stacked in x                            */
-    const opus_int32            WhiteNoiseFrac_Q32, /* I    Fraction added to zero-lag autocorrelation                  */
-    const opus_int              D                   /* I    Order                                                       */
+    const opus_int              D,                  /* I    Order                                                       */
+    int                         arch                /* I    Run-time architecture                                       */
 );
 
 /* Copy and multiply a vector by a constant */
@@ -339,12 +349,15 @@ void silk_scale_vector32_Q26_lshift_18(
 /********************************************************************/
 
 /*    return sum( inVec1[i] * inVec2[i] ) */
+
 opus_int32 silk_inner_prod_aligned(
     const opus_int16 *const     inVec1,             /*    I input vector 1                                              */
     const opus_int16 *const     inVec2,             /*    I input vector 2                                              */
-    const opus_int              len                 /*    I vector lengths                                              */
+    const opus_int              len,                /*    I vector lengths                                              */
+    int                         arch                /*    I Run-time architecture                                       */
 );
 
+
 opus_int32 silk_inner_prod_aligned_scale(
     const opus_int16 *const     inVec1,             /*    I input vector 1                                              */
     const opus_int16 *const     inVec2,             /*    I input vector 2                                              */
@@ -352,7 +365,7 @@ opus_int32 silk_inner_prod_aligned_scale(
     const opus_int              len                 /*    I vector lengths                                              */
 );
 
-opus_int64 silk_inner_prod16_aligned_64(
+opus_int64 silk_inner_prod16_aligned_64_c(
     const opus_int16            *inVec1,            /*    I input vector 1                                              */
     const opus_int16            *inVec2,            /*    I input vector 2                                              */
     const opus_int              len                 /*    I vector lengths                                              */
@@ -365,8 +378,8 @@ opus_int64 silk_inner_prod16_aligned_64(
 /* Rotate a32 right by 'rot' bits. Negative rot values result in rotating
    left. Output is 32bit int.
    Note: contemporary compilers recognize the C expression below and
-   compile it into a 'ror' instruction if available. No need for inline ASM! */
-static inline opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
+   compile it into a 'ror' instruction if available. No need for OPUS_INLINE ASM! */
+static OPUS_INLINE opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
 {
     opus_uint32 x = (opus_uint32) a32;
     opus_uint32 r = (opus_uint32) rot;
@@ -380,7 +393,7 @@ static inline opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
     }
 }
 
-/* Allocate opus_int16 alligned to 4-byte memory address */
+/* Allocate opus_int16 aligned to 4-byte memory address */
 #if EMBEDDED_ARM
 #define silk_DWORD_ALIGN __attribute__((aligned(4)))
 #else
@@ -388,9 +401,9 @@ static inline opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
 #endif
 
 /* Useful Macros that can be adjusted to other platforms */
-#define silk_memcpy(a, b, c)                memcpy((a), (b), (c))    /* Dest, Src, ByteCount    */
-#define silk_memset(a, b, c)                memset((a), (b), (c))    /* Dest, value, ByteCount  */
-#define silk_memmove(a, b, c)               memmove((a), (b), (c))   /* Dest, Src, ByteCount    */
+#define silk_memcpy(dest, src, size)        memcpy((dest), (src), (size))
+#define silk_memset(dest, src, size)        memset((dest), (src), (size))
+#define silk_memmove(dest, src, size)       memmove((dest), (src), (size))
 
 /* Fixed point macros */
 
@@ -467,8 +480,7 @@ static inline opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
 /* Add with saturation for positive input values */
 #define silk_ADD_POS_SAT8(a, b)             ((((a)+(b)) & 0x80)                 ? silk_int8_MAX  : ((a)+(b)))
 #define silk_ADD_POS_SAT16(a, b)            ((((a)+(b)) & 0x8000)               ? silk_int16_MAX : ((a)+(b)))
-#define silk_ADD_POS_SAT32(a, b)            ((((a)+(b)) & 0x80000000)           ? silk_int32_MAX : ((a)+(b)))
-#define silk_ADD_POS_SAT64(a, b)            ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_MAX : ((a)+(b)))
+#define silk_ADD_POS_SAT32(a, b)            ((((opus_uint32)(a)+(opus_uint32)(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)))
 
 #define silk_LSHIFT8(a, shift)              ((opus_int8)((opus_uint8)(a)<<(shift)))         /* shift >= 0, shift < 8  */
 #define silk_LSHIFT16(a, shift)             ((opus_int16)((opus_uint16)(a)<<(shift)))       /* shift >= 0, shift < 16 */
@@ -483,8 +495,6 @@ static inline opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
 #define silk_RSHIFT(a, shift)               silk_RSHIFT32(a, shift)                         /* shift >= 0, shift < 32 */
 
 /* saturates before shifting */
-#define silk_LSHIFT_SAT16(a, shift)         (silk_LSHIFT16( silk_LIMIT( (a), silk_RSHIFT16( silk_int16_MIN, (shift) ), \
-                                                    silk_RSHIFT16( silk_int16_MAX, (shift) ) ), (shift) ))
 #define silk_LSHIFT_SAT32(a, shift)         (silk_LSHIFT32( silk_LIMIT( (a), silk_RSHIFT32( silk_int32_MIN, (shift) ), \
                                                     silk_RSHIFT32( silk_int32_MAX, (shift) ) ), (shift) ))
 
@@ -517,37 +527,37 @@ static inline opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
 #define SILK_FIX_CONST( C, Q )              ((opus_int32)((C) * ((opus_int64)1 << (Q)) + 0.5))
 
 /* silk_min() versions with typecast in the function call */
-static inline opus_int silk_min_int(opus_int a, opus_int b)
+static OPUS_INLINE opus_int silk_min_int(opus_int a, opus_int b)
 {
     return (((a) < (b)) ? (a) : (b));
 }
-static inline opus_int16 silk_min_16(opus_int16 a, opus_int16 b)
+static OPUS_INLINE opus_int16 silk_min_16(opus_int16 a, opus_int16 b)
 {
     return (((a) < (b)) ? (a) : (b));
 }
-static inline opus_int32 silk_min_32(opus_int32 a, opus_int32 b)
+static OPUS_INLINE opus_int32 silk_min_32(opus_int32 a, opus_int32 b)
 {
     return (((a) < (b)) ? (a) : (b));
 }
-static inline opus_int64 silk_min_64(opus_int64 a, opus_int64 b)
+static OPUS_INLINE opus_int64 silk_min_64(opus_int64 a, opus_int64 b)
 {
     return (((a) < (b)) ? (a) : (b));
 }
 
 /* silk_min() versions with typecast in the function call */
-static inline opus_int silk_max_int(opus_int a, opus_int b)
+static OPUS_INLINE opus_int silk_max_int(opus_int a, opus_int b)
 {
     return (((a) > (b)) ? (a) : (b));
 }
-static inline opus_int16 silk_max_16(opus_int16 a, opus_int16 b)
+static OPUS_INLINE opus_int16 silk_max_16(opus_int16 a, opus_int16 b)
 {
     return (((a) > (b)) ? (a) : (b));
 }
-static inline opus_int32 silk_max_32(opus_int32 a, opus_int32 b)
+static OPUS_INLINE opus_int32 silk_max_32(opus_int32 a, opus_int32 b)
 {
     return (((a) > (b)) ? (a) : (b));
 }
-static inline opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
+static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
 {
     return (((a) > (b)) ? (a) : (b));
 }
@@ -566,8 +576,6 @@ static inline opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
 
 #define silk_sign(a)                        ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 ))
 
-#define silk_sqrt(a)                        (sqrt(a))
-
 /* PSEUDO-RANDOM GENERATOR                                                          */
 /* Make sure to store the result as the seed for the next call (also in between     */
 /* frames), otherwise result won't be random at all. When only using some of the    */
@@ -583,10 +591,31 @@ static inline opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
 /* the following seems faster on x86 */
 #define silk_SMMUL(a32, b32)                (opus_int32)silk_RSHIFT64(silk_SMULL((a32), (b32)), 32)
 
+#if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
+#define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
+    ((void)(arch), silk_burg_modified_c(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
+
+#define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \
+    ((void)(arch),silk_inner_prod16_aligned_64_c(inVec1, inVec2, len))
+#endif
+
 #include "Inlines.h"
 #include "MacroCount.h"
 #include "MacroDebug.h"
 
+#ifdef OPUS_ARM_INLINE_ASM
+#include "arm/SigProc_FIX_armv4.h"
+#endif
+
+#ifdef OPUS_ARM_INLINE_EDSP
+#include "arm/SigProc_FIX_armv5e.h"
+#endif
+
+#if defined(MIPSr1_ASM)
+#include "mips/sigproc_fix_mipsr1.h"
+#endif
+
+
 #ifdef  __cplusplus
 }
 #endif