1885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/*********************************************************************** 2885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgCopyright (c) 2006-2011, Skype Limited. All rights reserved. 3885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgRedistribution and use in source and binary forms, with or without 4885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgmodification, are permitted provided that the following conditions 5885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgare met: 6885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org- Redistributions of source code must retain the above copyright notice, 7885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgthis list of conditions and the following disclaimer. 8885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org- Redistributions in binary form must reproduce the above copyright 9885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgnotice, this list of conditions and the following disclaimer in the 10885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgdocumentation and/or other materials provided with the distribution. 11e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org- Neither the name of Internet Society, IETF or IETF Trust, nor the 12885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgnames of specific contributors, may be used to endorse or promote 13885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgproducts derived from this software without specific prior written 14885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgpermission. 15e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgPOSSIBILITY OF SUCH DAMAGE. 26885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org***********************************************************************/ 27885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 28885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Conversion between prediction filter coefficients and NLSFs */ 29885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Requires the order to be an even number */ 30885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* A piecewise linear approximation maps LSF <-> cos(LSF) */ 31885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Therefore the result is not accurate NLSFs, but the two */ 32885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* functions are accurate inverses of each other */ 33885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 34885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef HAVE_CONFIG_H 35885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "config.h" 36885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 37885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 38885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "SigProc_FIX.h" 39885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "tables.h" 40885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 41885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Number of binary divisions, when not in low complexity mode */ 42885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#define BIN_DIV_STEPS_A2NLSF_FIX 3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */ 43885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#define MAX_ITERATIONS_A2NLSF_FIX 30 44885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 45885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Helper function for A2NLSF(..) */ 46885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Transforms polynomials from cos(n*f) to cos(f)^n */ 473c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.comstatic OPUS_INLINE void silk_A2NLSF_trans_poly( 48885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 *p, /* I/O Polynomial */ 49885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_int dd /* I Polynomial order (= filter order / 2 ) */ 50885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org) 51885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 52885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int k, n; 53885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 54885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( k = 2; k <= dd; k++ ) { 55885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( n = dd; n > k; n-- ) { 56885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org p[ n - 2 ] -= p[ n ]; 57885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 58885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org p[ k - 2 ] -= silk_LSHIFT( p[ k ], 1 ); 59885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 60885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 61885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Helper function for A2NLSF(..) */ 62885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Polynomial evaluation */ 633c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.comstatic OPUS_INLINE opus_int32 silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in Q16 */ 64885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 *p, /* I Polynomial, Q16 */ 65885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_int32 x, /* I Evaluation point, Q12 */ 66885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_int dd /* I Order */ 67885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org) 68885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 69885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int n; 70885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 x_Q16, y32; 71885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 72885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org y32 = p[ dd ]; /* Q16 */ 73885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org x_Q16 = silk_LSHIFT( x, 4 ); 74885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( n = dd - 1; n >= 0; n-- ) { 75885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org y32 = silk_SMLAWW( p[ n ], y32, x_Q16 ); /* Q16 */ 76885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 77885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return y32; 78885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 79885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 803c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.comstatic OPUS_INLINE void silk_A2NLSF_init( 81885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_int32 *a_Q16, 82885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 *P, 83885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 *Q, 84885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_int dd 85885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org) 86885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 87885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int k; 88885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 89885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Convert filter coefs to even and odd polynomials */ 90885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org P[dd] = silk_LSHIFT( 1, 16 ); 91885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org Q[dd] = silk_LSHIFT( 1, 16 ); 92885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( k = 0; k < dd; k++ ) { 93885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ]; /* Q16 */ 94885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ]; /* Q16 */ 95885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 96885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 97885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Divide out zeros as we have that for even filter orders, */ 98885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* z = 1 is always a root in Q, and */ 99885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* z = -1 is always a root in P */ 100885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( k = dd; k > 0; k-- ) { 101885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org P[ k - 1 ] -= P[ k ]; 102885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org Q[ k - 1 ] += Q[ k ]; 103885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 104885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 105885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Transform polynomials from cos(n*f) to cos(f)^n */ 106885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_A2NLSF_trans_poly( P, dd ); 107885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_A2NLSF_trans_poly( Q, dd ); 108885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 109885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 110885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */ 111885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */ 112885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid silk_A2NLSF( 113885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */ 114885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */ 115885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_int d /* I Filter order (must be even) */ 116885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org) 117885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 118885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int i, k, m, dd, root_ix, ffrac; 119885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 xlo, xhi, xmid; 120885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 ylo, yhi, ymid, thr; 121885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 nom, den; 122885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ]; 123885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 Q[ SILK_MAX_ORDER_LPC / 2 + 1 ]; 124885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 *PQ[ 2 ]; 125885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 *p; 126885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 127885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Store pointers to array */ 128885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org PQ[ 0 ] = P; 129885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org PQ[ 1 ] = Q; 130885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 131885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org dd = silk_RSHIFT( d, 1 ); 132885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 133885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_A2NLSF_init( a_Q16, P, Q, dd ); 134885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 135885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Find roots, alternating between P and Q */ 136885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org p = P; /* Pointer to polynomial */ 137885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 138885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/ 139885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); 140885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 141885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( ylo < 0 ) { 142885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Set the first NLSF to zero and move on to the next */ 143885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org NLSF[ 0 ] = 0; 144885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org p = Q; /* Pointer to polynomial */ 145885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); 146885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org root_ix = 1; /* Index of current root */ 147885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 148885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org root_ix = 0; /* Index of current root */ 149885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 150885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org k = 1; /* Loop counter */ 151885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org i = 0; /* Counter for bandwidth expansions applied */ 152885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org thr = 0; 153885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org while( 1 ) { 154885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Evaluate polynomial */ 155885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org xhi = silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */ 156885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org yhi = silk_A2NLSF_eval_poly( p, xhi, dd ); 157885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 158885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Detect zero crossing */ 159885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( ( ylo <= 0 && yhi >= thr ) || ( ylo >= 0 && yhi <= -thr ) ) { 160885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( yhi == 0 ) { 161885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* If the root lies exactly at the end of the current */ 162885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* interval, look for the next root in the next interval */ 163885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org thr = 1; 164885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 165885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org thr = 0; 166885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 167885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Binary division */ 168885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ffrac = -256; 169885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) { 170885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Evaluate polynomial */ 171885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org xmid = silk_RSHIFT_ROUND( xlo + xhi, 1 ); 172885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ymid = silk_A2NLSF_eval_poly( p, xmid, dd ); 173885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 174885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Detect zero crossing */ 175885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) { 176885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Reduce frequency */ 177885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org xhi = xmid; 178885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org yhi = ymid; 179885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 180885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Increase frequency */ 181885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org xlo = xmid; 182885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ylo = ymid; 183885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ffrac = silk_ADD_RSHIFT( ffrac, 128, m ); 184885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 185885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 186885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 187885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Interpolate */ 188885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( silk_abs( ylo ) < 65536 ) { 189885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Avoid dividing by zero */ 190885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org den = ylo - yhi; 191885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org nom = silk_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + silk_RSHIFT( den, 1 ); 192885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( den != 0 ) { 193885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ffrac += silk_DIV32( nom, den ); 194885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 195885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 196885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */ 197885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ffrac += silk_DIV32( ylo, silk_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) ); 198885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 199885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org NLSF[ root_ix ] = (opus_int16)silk_min_32( silk_LSHIFT( (opus_int32)k, 8 ) + ffrac, silk_int16_MAX ); 200885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 201885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_assert( NLSF[ root_ix ] >= 0 ); 202885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 203885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org root_ix++; /* Next root */ 204885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( root_ix >= d ) { 205885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Found all roots */ 206885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 207885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 208885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Alternate pointer to polynomial */ 209885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org p = PQ[ root_ix & 1 ]; 210885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 211885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Evaluate polynomial */ 212885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org xlo = silk_LSFCosTab_FIX_Q12[ k - 1 ]; /* Q12*/ 213885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ylo = silk_LSHIFT( 1 - ( root_ix & 2 ), 12 ); 214885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 215885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Increment loop counter */ 216885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org k++; 217885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org xlo = xhi; 218885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ylo = yhi; 219885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org thr = 0; 220885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 221885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( k > LSF_COS_TAB_SZ_FIX ) { 222885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org i++; 223885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( i > MAX_ITERATIONS_A2NLSF_FIX ) { 224885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Set NLSFs to white spectrum and exit */ 225885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org NLSF[ 0 ] = (opus_int16)silk_DIV32_16( 1 << 15, d + 1 ); 226885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for( k = 1; k < d; k++ ) { 227885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org NLSF[ k ] = (opus_int16)silk_SMULBB( k + 1, NLSF[ 0 ] ); 228885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 229885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return; 230885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 231885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 232885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Error: Apply progressively more bandwidth expansion and run again */ 233885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_bwexpander_32( a_Q16, d, 65536 - silk_SMULBB( 10 + i, i ) ); /* 10_Q16 = 0.00015*/ 234885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 235885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_A2NLSF_init( a_Q16, P, Q, dd ); 236885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org p = P; /* Pointer to polynomial */ 237885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/ 238885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); 239885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( ylo < 0 ) { 240885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Set the first NLSF to zero and move on to the next */ 241885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org NLSF[ 0 ] = 0; 242885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org p = Q; /* Pointer to polynomial */ 243885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); 244885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org root_ix = 1; /* Index of current root */ 245885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 246885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org root_ix = 0; /* Index of current root */ 247885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 248885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org k = 1; /* Reset loop counter */ 249885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 250885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 251885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 252885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 253