189 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			189 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | /***********************************************************************
 | ||
|  | Copyright (c) 2006-2011, Skype Limited. All rights reserved. | ||
|  | 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 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. | ||
|  | ***********************************************************************/ | ||
|  | 
 | ||
|  | /*! \file silk_Inlines.h
 | ||
|  |  *  \brief silk_Inlines.h defines OPUS_INLINE signal processing functions. | ||
|  |  */ | ||
|  | 
 | ||
|  | #ifndef SILK_FIX_INLINES_H
 | ||
|  | #define SILK_FIX_INLINES_H
 | ||
|  | 
 | ||
|  | #ifdef  __cplusplus
 | ||
|  | extern "C" | ||
|  | { | ||
|  | #endif
 | ||
|  | 
 | ||
|  | /* count leading zeros of opus_int64 */ | ||
|  | static OPUS_INLINE opus_int32 silk_CLZ64( opus_int64 in ) | ||
|  | { | ||
|  |     opus_int32 in_upper; | ||
|  | 
 | ||
|  |     in_upper = (opus_int32)silk_RSHIFT64(in, 32); | ||
|  |     if (in_upper == 0) { | ||
|  |         /* Search in the lower 32 bits */ | ||
|  |         return 32 + silk_CLZ32( (opus_int32) in ); | ||
|  |     } else { | ||
|  |         /* Search in the upper 32 bits */ | ||
|  |         return silk_CLZ32( in_upper ); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | /* get number of leading zeros and fractional part (the bits right after the leading one */ | ||
|  | static OPUS_INLINE void silk_CLZ_FRAC( | ||
|  |     opus_int32 in,            /* I  input                               */ | ||
|  |     opus_int32 *lz,           /* O  number of leading zeros             */ | ||
|  |     opus_int32 *frac_Q7       /* O  the 7 bits right after the leading one */ | ||
|  | ) | ||
|  | { | ||
|  |     opus_int32 lzeros = silk_CLZ32(in); | ||
|  | 
 | ||
|  |     * lz = lzeros; | ||
|  |     * frac_Q7 = silk_ROR32(in, 24 - lzeros) & 0x7f; | ||
|  | } | ||
|  | 
 | ||
|  | /* Approximation of square root                                          */ | ||
|  | /* Accuracy: < +/- 10%  for output values > 15                           */ | ||
|  | /*           < +/- 2.5% for output values > 120                          */ | ||
|  | static OPUS_INLINE opus_int32 silk_SQRT_APPROX( opus_int32 x ) | ||
|  | { | ||
|  |     opus_int32 y, lz, frac_Q7; | ||
|  | 
 | ||
|  |     if( x <= 0 ) { | ||
|  |         return 0; | ||
|  |     } | ||
|  | 
 | ||
|  |     silk_CLZ_FRAC(x, &lz, &frac_Q7); | ||
|  | 
 | ||
|  |     if( lz & 1 ) { | ||
|  |         y = 32768; | ||
|  |     } else { | ||
|  |         y = 46214;        /* 46214 = sqrt(2) * 32768 */ | ||
|  |     } | ||
|  | 
 | ||
|  |     /* get scaling right */ | ||
|  |     y >>= silk_RSHIFT(lz, 1); | ||
|  | 
 | ||
|  |     /* increment using fractional part of input */ | ||
|  |     y = silk_SMLAWB(y, y, silk_SMULBB(213, frac_Q7)); | ||
|  | 
 | ||
|  |     return y; | ||
|  | } | ||
|  | 
 | ||
|  | /* Divide two int32 values and return result as int32 in a given Q-domain */ | ||
|  | static OPUS_INLINE opus_int32 silk_DIV32_varQ(   /* O    returns a good approximation of "(a32 << Qres) / b32" */ | ||
|  |     const opus_int32     a32,               /* I    numerator (Q0)                  */ | ||
|  |     const opus_int32     b32,               /* I    denominator (Q0)                */ | ||
|  |     const opus_int       Qres               /* I    Q-domain of result (>= 0)       */ | ||
|  | ) | ||
|  | { | ||
|  |     opus_int   a_headrm, b_headrm, lshift; | ||
|  |     opus_int32 b32_inv, a32_nrm, b32_nrm, result; | ||
|  | 
 | ||
|  |     silk_assert( b32 != 0 ); | ||
|  |     silk_assert( Qres >= 0 ); | ||
|  | 
 | ||
|  |     /* Compute number of bits head room and normalize inputs */ | ||
|  |     a_headrm = silk_CLZ32( silk_abs(a32) ) - 1; | ||
|  |     a32_nrm = silk_LSHIFT(a32, a_headrm);                                       /* Q: a_headrm                  */ | ||
|  |     b_headrm = silk_CLZ32( silk_abs(b32) ) - 1; | ||
|  |     b32_nrm = silk_LSHIFT(b32, b_headrm);                                       /* Q: b_headrm                  */ | ||
|  | 
 | ||
|  |     /* Inverse of b32, with 14 bits of precision */ | ||
|  |     b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) );   /* Q: 29 + 16 - b_headrm        */ | ||
|  | 
 | ||
|  |     /* First approximation */ | ||
|  |     result = silk_SMULWB(a32_nrm, b32_inv);                                     /* Q: 29 + a_headrm - b_headrm  */ | ||
|  | 
 | ||
|  |     /* Compute residual by subtracting product of denominator and first approximation */ | ||
|  |     /* It's OK to overflow because the final value of a32_nrm should always be small */ | ||
|  |     a32_nrm = silk_SUB32_ovflw(a32_nrm, silk_LSHIFT_ovflw( silk_SMMUL(b32_nrm, result), 3 ));  /* Q: a_headrm   */ | ||
|  | 
 | ||
|  |     /* Refinement */ | ||
|  |     result = silk_SMLAWB(result, a32_nrm, b32_inv);                             /* Q: 29 + a_headrm - b_headrm  */ | ||
|  | 
 | ||
|  |     /* Convert to Qres domain */ | ||
|  |     lshift = 29 + a_headrm - b_headrm - Qres; | ||
|  |     if( lshift < 0 ) { | ||
|  |         return silk_LSHIFT_SAT32(result, -lshift); | ||
|  |     } else { | ||
|  |         if( lshift < 32){ | ||
|  |             return silk_RSHIFT(result, lshift); | ||
|  |         } else { | ||
|  |             /* Avoid undefined result */ | ||
|  |             return 0; | ||
|  |         } | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | /* Invert int32 value and return result as int32 in a given Q-domain */ | ||
|  | static OPUS_INLINE opus_int32 silk_INVERSE32_varQ(   /* O    returns a good approximation of "(1 << Qres) / b32" */ | ||
|  |     const opus_int32     b32,                   /* I    denominator (Q0)                */ | ||
|  |     const opus_int       Qres                   /* I    Q-domain of result (> 0)        */ | ||
|  | ) | ||
|  | { | ||
|  |     opus_int   b_headrm, lshift; | ||
|  |     opus_int32 b32_inv, b32_nrm, err_Q32, result; | ||
|  | 
 | ||
|  |     silk_assert( b32 != 0 ); | ||
|  |     silk_assert( Qres > 0 ); | ||
|  | 
 | ||
|  |     /* Compute number of bits head room and normalize input */ | ||
|  |     b_headrm = silk_CLZ32( silk_abs(b32) ) - 1; | ||
|  |     b32_nrm = silk_LSHIFT(b32, b_headrm);                                       /* Q: b_headrm                */ | ||
|  | 
 | ||
|  |     /* Inverse of b32, with 14 bits of precision */ | ||
|  |     b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) );   /* Q: 29 + 16 - b_headrm    */ | ||
|  | 
 | ||
|  |     /* First approximation */ | ||
|  |     result = silk_LSHIFT(b32_inv, 16);                                          /* Q: 61 - b_headrm            */ | ||
|  | 
 | ||
|  |     /* Compute residual by subtracting product of denominator and first approximation from one */ | ||
|  |     err_Q32 = silk_LSHIFT( ((opus_int32)1<<29) - silk_SMULWB(b32_nrm, b32_inv), 3 );        /* Q32                        */ | ||
|  | 
 | ||
|  |     /* Refinement */ | ||
|  |     result = silk_SMLAWW(result, err_Q32, b32_inv);                             /* Q: 61 - b_headrm            */ | ||
|  | 
 | ||
|  |     /* Convert to Qres domain */ | ||
|  |     lshift = 61 - b_headrm - Qres; | ||
|  |     if( lshift <= 0 ) { | ||
|  |         return silk_LSHIFT_SAT32(result, -lshift); | ||
|  |     } else { | ||
|  |         if( lshift < 32){ | ||
|  |             return silk_RSHIFT(result, lshift); | ||
|  |         }else{ | ||
|  |             /* Avoid undefined result */ | ||
|  |             return 0; | ||
|  |         } | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | #ifdef  __cplusplus
 | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #endif /* SILK_FIX_INLINES_H */
 |