1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libopus/silk/Inlines.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,188 @@ 1.4 +/*********************************************************************** 1.5 +Copyright (c) 2006-2011, Skype Limited. All rights reserved. 1.6 +Redistribution and use in source and binary forms, with or without 1.7 +modification, are permitted provided that the following conditions 1.8 +are met: 1.9 +- Redistributions of source code must retain the above copyright notice, 1.10 +this list of conditions and the following disclaimer. 1.11 +- Redistributions in binary form must reproduce the above copyright 1.12 +notice, this list of conditions and the following disclaimer in the 1.13 +documentation and/or other materials provided with the distribution. 1.14 +- Neither the name of Internet Society, IETF or IETF Trust, nor the 1.15 +names of specific contributors, may be used to endorse or promote 1.16 +products derived from this software without specific prior written 1.17 +permission. 1.18 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1.19 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.20 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.21 +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 1.22 +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1.23 +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1.24 +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1.25 +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 1.26 +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1.27 +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 1.28 +POSSIBILITY OF SUCH DAMAGE. 1.29 +***********************************************************************/ 1.30 + 1.31 +/*! \file silk_Inlines.h 1.32 + * \brief silk_Inlines.h defines OPUS_INLINE signal processing functions. 1.33 + */ 1.34 + 1.35 +#ifndef SILK_FIX_INLINES_H 1.36 +#define SILK_FIX_INLINES_H 1.37 + 1.38 +#ifdef __cplusplus 1.39 +extern "C" 1.40 +{ 1.41 +#endif 1.42 + 1.43 +/* count leading zeros of opus_int64 */ 1.44 +static OPUS_INLINE opus_int32 silk_CLZ64( opus_int64 in ) 1.45 +{ 1.46 + opus_int32 in_upper; 1.47 + 1.48 + in_upper = (opus_int32)silk_RSHIFT64(in, 32); 1.49 + if (in_upper == 0) { 1.50 + /* Search in the lower 32 bits */ 1.51 + return 32 + silk_CLZ32( (opus_int32) in ); 1.52 + } else { 1.53 + /* Search in the upper 32 bits */ 1.54 + return silk_CLZ32( in_upper ); 1.55 + } 1.56 +} 1.57 + 1.58 +/* get number of leading zeros and fractional part (the bits right after the leading one */ 1.59 +static OPUS_INLINE void silk_CLZ_FRAC( 1.60 + opus_int32 in, /* I input */ 1.61 + opus_int32 *lz, /* O number of leading zeros */ 1.62 + opus_int32 *frac_Q7 /* O the 7 bits right after the leading one */ 1.63 +) 1.64 +{ 1.65 + opus_int32 lzeros = silk_CLZ32(in); 1.66 + 1.67 + * lz = lzeros; 1.68 + * frac_Q7 = silk_ROR32(in, 24 - lzeros) & 0x7f; 1.69 +} 1.70 + 1.71 +/* Approximation of square root */ 1.72 +/* Accuracy: < +/- 10% for output values > 15 */ 1.73 +/* < +/- 2.5% for output values > 120 */ 1.74 +static OPUS_INLINE opus_int32 silk_SQRT_APPROX( opus_int32 x ) 1.75 +{ 1.76 + opus_int32 y, lz, frac_Q7; 1.77 + 1.78 + if( x <= 0 ) { 1.79 + return 0; 1.80 + } 1.81 + 1.82 + silk_CLZ_FRAC(x, &lz, &frac_Q7); 1.83 + 1.84 + if( lz & 1 ) { 1.85 + y = 32768; 1.86 + } else { 1.87 + y = 46214; /* 46214 = sqrt(2) * 32768 */ 1.88 + } 1.89 + 1.90 + /* get scaling right */ 1.91 + y >>= silk_RSHIFT(lz, 1); 1.92 + 1.93 + /* increment using fractional part of input */ 1.94 + y = silk_SMLAWB(y, y, silk_SMULBB(213, frac_Q7)); 1.95 + 1.96 + return y; 1.97 +} 1.98 + 1.99 +/* Divide two int32 values and return result as int32 in a given Q-domain */ 1.100 +static OPUS_INLINE opus_int32 silk_DIV32_varQ( /* O returns a good approximation of "(a32 << Qres) / b32" */ 1.101 + const opus_int32 a32, /* I numerator (Q0) */ 1.102 + const opus_int32 b32, /* I denominator (Q0) */ 1.103 + const opus_int Qres /* I Q-domain of result (>= 0) */ 1.104 +) 1.105 +{ 1.106 + opus_int a_headrm, b_headrm, lshift; 1.107 + opus_int32 b32_inv, a32_nrm, b32_nrm, result; 1.108 + 1.109 + silk_assert( b32 != 0 ); 1.110 + silk_assert( Qres >= 0 ); 1.111 + 1.112 + /* Compute number of bits head room and normalize inputs */ 1.113 + a_headrm = silk_CLZ32( silk_abs(a32) ) - 1; 1.114 + a32_nrm = silk_LSHIFT(a32, a_headrm); /* Q: a_headrm */ 1.115 + b_headrm = silk_CLZ32( silk_abs(b32) ) - 1; 1.116 + b32_nrm = silk_LSHIFT(b32, b_headrm); /* Q: b_headrm */ 1.117 + 1.118 + /* Inverse of b32, with 14 bits of precision */ 1.119 + b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */ 1.120 + 1.121 + /* First approximation */ 1.122 + result = silk_SMULWB(a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */ 1.123 + 1.124 + /* Compute residual by subtracting product of denominator and first approximation */ 1.125 + /* It's OK to overflow because the final value of a32_nrm should always be small */ 1.126 + a32_nrm = silk_SUB32_ovflw(a32_nrm, silk_LSHIFT_ovflw( silk_SMMUL(b32_nrm, result), 3 )); /* Q: a_headrm */ 1.127 + 1.128 + /* Refinement */ 1.129 + result = silk_SMLAWB(result, a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */ 1.130 + 1.131 + /* Convert to Qres domain */ 1.132 + lshift = 29 + a_headrm - b_headrm - Qres; 1.133 + if( lshift < 0 ) { 1.134 + return silk_LSHIFT_SAT32(result, -lshift); 1.135 + } else { 1.136 + if( lshift < 32){ 1.137 + return silk_RSHIFT(result, lshift); 1.138 + } else { 1.139 + /* Avoid undefined result */ 1.140 + return 0; 1.141 + } 1.142 + } 1.143 +} 1.144 + 1.145 +/* Invert int32 value and return result as int32 in a given Q-domain */ 1.146 +static OPUS_INLINE opus_int32 silk_INVERSE32_varQ( /* O returns a good approximation of "(1 << Qres) / b32" */ 1.147 + const opus_int32 b32, /* I denominator (Q0) */ 1.148 + const opus_int Qres /* I Q-domain of result (> 0) */ 1.149 +) 1.150 +{ 1.151 + opus_int b_headrm, lshift; 1.152 + opus_int32 b32_inv, b32_nrm, err_Q32, result; 1.153 + 1.154 + silk_assert( b32 != 0 ); 1.155 + silk_assert( Qres > 0 ); 1.156 + 1.157 + /* Compute number of bits head room and normalize input */ 1.158 + b_headrm = silk_CLZ32( silk_abs(b32) ) - 1; 1.159 + b32_nrm = silk_LSHIFT(b32, b_headrm); /* Q: b_headrm */ 1.160 + 1.161 + /* Inverse of b32, with 14 bits of precision */ 1.162 + b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */ 1.163 + 1.164 + /* First approximation */ 1.165 + result = silk_LSHIFT(b32_inv, 16); /* Q: 61 - b_headrm */ 1.166 + 1.167 + /* Compute residual by subtracting product of denominator and first approximation from one */ 1.168 + err_Q32 = silk_LSHIFT( ((opus_int32)1<<29) - silk_SMULWB(b32_nrm, b32_inv), 3 ); /* Q32 */ 1.169 + 1.170 + /* Refinement */ 1.171 + result = silk_SMLAWW(result, err_Q32, b32_inv); /* Q: 61 - b_headrm */ 1.172 + 1.173 + /* Convert to Qres domain */ 1.174 + lshift = 61 - b_headrm - Qres; 1.175 + if( lshift <= 0 ) { 1.176 + return silk_LSHIFT_SAT32(result, -lshift); 1.177 + } else { 1.178 + if( lshift < 32){ 1.179 + return silk_RSHIFT(result, lshift); 1.180 + }else{ 1.181 + /* Avoid undefined result */ 1.182 + return 0; 1.183 + } 1.184 + } 1.185 +} 1.186 + 1.187 +#ifdef __cplusplus 1.188 +} 1.189 +#endif 1.190 + 1.191 +#endif /* SILK_FIX_INLINES_H */