annotate src/opus-1.3/silk/A2NLSF.c @ 154:4664ac0c1032

Add Opus sources and macOS builds
author Chris Cannam <cannam@all-day-breakfast.com>
date Wed, 23 Jan 2019 13:48:08 +0000
parents
children
rev   line source
cannam@154 1 /***********************************************************************
cannam@154 2 Copyright (c) 2006-2011, Skype Limited. All rights reserved.
cannam@154 3 Redistribution and use in source and binary forms, with or without
cannam@154 4 modification, are permitted provided that the following conditions
cannam@154 5 are met:
cannam@154 6 - Redistributions of source code must retain the above copyright notice,
cannam@154 7 this list of conditions and the following disclaimer.
cannam@154 8 - Redistributions in binary form must reproduce the above copyright
cannam@154 9 notice, this list of conditions and the following disclaimer in the
cannam@154 10 documentation and/or other materials provided with the distribution.
cannam@154 11 - Neither the name of Internet Society, IETF or IETF Trust, nor the
cannam@154 12 names of specific contributors, may be used to endorse or promote
cannam@154 13 products derived from this software without specific prior written
cannam@154 14 permission.
cannam@154 15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
cannam@154 16 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
cannam@154 17 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
cannam@154 18 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
cannam@154 19 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
cannam@154 20 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
cannam@154 21 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
cannam@154 22 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
cannam@154 23 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
cannam@154 24 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
cannam@154 25 POSSIBILITY OF SUCH DAMAGE.
cannam@154 26 ***********************************************************************/
cannam@154 27
cannam@154 28 /* Conversion between prediction filter coefficients and NLSFs */
cannam@154 29 /* Requires the order to be an even number */
cannam@154 30 /* A piecewise linear approximation maps LSF <-> cos(LSF) */
cannam@154 31 /* Therefore the result is not accurate NLSFs, but the two */
cannam@154 32 /* functions are accurate inverses of each other */
cannam@154 33
cannam@154 34 #ifdef HAVE_CONFIG_H
cannam@154 35 #include "config.h"
cannam@154 36 #endif
cannam@154 37
cannam@154 38 #include "SigProc_FIX.h"
cannam@154 39 #include "tables.h"
cannam@154 40
cannam@154 41 /* Number of binary divisions, when not in low complexity mode */
cannam@154 42 #define BIN_DIV_STEPS_A2NLSF_FIX 3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
cannam@154 43 #define MAX_ITERATIONS_A2NLSF_FIX 16
cannam@154 44
cannam@154 45 /* Helper function for A2NLSF(..) */
cannam@154 46 /* Transforms polynomials from cos(n*f) to cos(f)^n */
cannam@154 47 static OPUS_INLINE void silk_A2NLSF_trans_poly(
cannam@154 48 opus_int32 *p, /* I/O Polynomial */
cannam@154 49 const opus_int dd /* I Polynomial order (= filter order / 2 ) */
cannam@154 50 )
cannam@154 51 {
cannam@154 52 opus_int k, n;
cannam@154 53
cannam@154 54 for( k = 2; k <= dd; k++ ) {
cannam@154 55 for( n = dd; n > k; n-- ) {
cannam@154 56 p[ n - 2 ] -= p[ n ];
cannam@154 57 }
cannam@154 58 p[ k - 2 ] -= silk_LSHIFT( p[ k ], 1 );
cannam@154 59 }
cannam@154 60 }
cannam@154 61 /* Helper function for A2NLSF(..) */
cannam@154 62 /* Polynomial evaluation */
cannam@154 63 static OPUS_INLINE opus_int32 silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in Q16 */
cannam@154 64 opus_int32 *p, /* I Polynomial, Q16 */
cannam@154 65 const opus_int32 x, /* I Evaluation point, Q12 */
cannam@154 66 const opus_int dd /* I Order */
cannam@154 67 )
cannam@154 68 {
cannam@154 69 opus_int n;
cannam@154 70 opus_int32 x_Q16, y32;
cannam@154 71
cannam@154 72 y32 = p[ dd ]; /* Q16 */
cannam@154 73 x_Q16 = silk_LSHIFT( x, 4 );
cannam@154 74
cannam@154 75 if ( opus_likely( 8 == dd ) )
cannam@154 76 {
cannam@154 77 y32 = silk_SMLAWW( p[ 7 ], y32, x_Q16 );
cannam@154 78 y32 = silk_SMLAWW( p[ 6 ], y32, x_Q16 );
cannam@154 79 y32 = silk_SMLAWW( p[ 5 ], y32, x_Q16 );
cannam@154 80 y32 = silk_SMLAWW( p[ 4 ], y32, x_Q16 );
cannam@154 81 y32 = silk_SMLAWW( p[ 3 ], y32, x_Q16 );
cannam@154 82 y32 = silk_SMLAWW( p[ 2 ], y32, x_Q16 );
cannam@154 83 y32 = silk_SMLAWW( p[ 1 ], y32, x_Q16 );
cannam@154 84 y32 = silk_SMLAWW( p[ 0 ], y32, x_Q16 );
cannam@154 85 }
cannam@154 86 else
cannam@154 87 {
cannam@154 88 for( n = dd - 1; n >= 0; n-- ) {
cannam@154 89 y32 = silk_SMLAWW( p[ n ], y32, x_Q16 ); /* Q16 */
cannam@154 90 }
cannam@154 91 }
cannam@154 92 return y32;
cannam@154 93 }
cannam@154 94
cannam@154 95 static OPUS_INLINE void silk_A2NLSF_init(
cannam@154 96 const opus_int32 *a_Q16,
cannam@154 97 opus_int32 *P,
cannam@154 98 opus_int32 *Q,
cannam@154 99 const opus_int dd
cannam@154 100 )
cannam@154 101 {
cannam@154 102 opus_int k;
cannam@154 103
cannam@154 104 /* Convert filter coefs to even and odd polynomials */
cannam@154 105 P[dd] = silk_LSHIFT( 1, 16 );
cannam@154 106 Q[dd] = silk_LSHIFT( 1, 16 );
cannam@154 107 for( k = 0; k < dd; k++ ) {
cannam@154 108 P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ]; /* Q16 */
cannam@154 109 Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ]; /* Q16 */
cannam@154 110 }
cannam@154 111
cannam@154 112 /* Divide out zeros as we have that for even filter orders, */
cannam@154 113 /* z = 1 is always a root in Q, and */
cannam@154 114 /* z = -1 is always a root in P */
cannam@154 115 for( k = dd; k > 0; k-- ) {
cannam@154 116 P[ k - 1 ] -= P[ k ];
cannam@154 117 Q[ k - 1 ] += Q[ k ];
cannam@154 118 }
cannam@154 119
cannam@154 120 /* Transform polynomials from cos(n*f) to cos(f)^n */
cannam@154 121 silk_A2NLSF_trans_poly( P, dd );
cannam@154 122 silk_A2NLSF_trans_poly( Q, dd );
cannam@154 123 }
cannam@154 124
cannam@154 125 /* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */
cannam@154 126 /* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
cannam@154 127 void silk_A2NLSF(
cannam@154 128 opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */
cannam@154 129 opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */
cannam@154 130 const opus_int d /* I Filter order (must be even) */
cannam@154 131 )
cannam@154 132 {
cannam@154 133 opus_int i, k, m, dd, root_ix, ffrac;
cannam@154 134 opus_int32 xlo, xhi, xmid;
cannam@154 135 opus_int32 ylo, yhi, ymid, thr;
cannam@154 136 opus_int32 nom, den;
cannam@154 137 opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ];
cannam@154 138 opus_int32 Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
cannam@154 139 opus_int32 *PQ[ 2 ];
cannam@154 140 opus_int32 *p;
cannam@154 141
cannam@154 142 /* Store pointers to array */
cannam@154 143 PQ[ 0 ] = P;
cannam@154 144 PQ[ 1 ] = Q;
cannam@154 145
cannam@154 146 dd = silk_RSHIFT( d, 1 );
cannam@154 147
cannam@154 148 silk_A2NLSF_init( a_Q16, P, Q, dd );
cannam@154 149
cannam@154 150 /* Find roots, alternating between P and Q */
cannam@154 151 p = P; /* Pointer to polynomial */
cannam@154 152
cannam@154 153 xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/
cannam@154 154 ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
cannam@154 155
cannam@154 156 if( ylo < 0 ) {
cannam@154 157 /* Set the first NLSF to zero and move on to the next */
cannam@154 158 NLSF[ 0 ] = 0;
cannam@154 159 p = Q; /* Pointer to polynomial */
cannam@154 160 ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
cannam@154 161 root_ix = 1; /* Index of current root */
cannam@154 162 } else {
cannam@154 163 root_ix = 0; /* Index of current root */
cannam@154 164 }
cannam@154 165 k = 1; /* Loop counter */
cannam@154 166 i = 0; /* Counter for bandwidth expansions applied */
cannam@154 167 thr = 0;
cannam@154 168 while( 1 ) {
cannam@154 169 /* Evaluate polynomial */
cannam@154 170 xhi = silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */
cannam@154 171 yhi = silk_A2NLSF_eval_poly( p, xhi, dd );
cannam@154 172
cannam@154 173 /* Detect zero crossing */
cannam@154 174 if( ( ylo <= 0 && yhi >= thr ) || ( ylo >= 0 && yhi <= -thr ) ) {
cannam@154 175 if( yhi == 0 ) {
cannam@154 176 /* If the root lies exactly at the end of the current */
cannam@154 177 /* interval, look for the next root in the next interval */
cannam@154 178 thr = 1;
cannam@154 179 } else {
cannam@154 180 thr = 0;
cannam@154 181 }
cannam@154 182 /* Binary division */
cannam@154 183 ffrac = -256;
cannam@154 184 for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) {
cannam@154 185 /* Evaluate polynomial */
cannam@154 186 xmid = silk_RSHIFT_ROUND( xlo + xhi, 1 );
cannam@154 187 ymid = silk_A2NLSF_eval_poly( p, xmid, dd );
cannam@154 188
cannam@154 189 /* Detect zero crossing */
cannam@154 190 if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) {
cannam@154 191 /* Reduce frequency */
cannam@154 192 xhi = xmid;
cannam@154 193 yhi = ymid;
cannam@154 194 } else {
cannam@154 195 /* Increase frequency */
cannam@154 196 xlo = xmid;
cannam@154 197 ylo = ymid;
cannam@154 198 ffrac = silk_ADD_RSHIFT( ffrac, 128, m );
cannam@154 199 }
cannam@154 200 }
cannam@154 201
cannam@154 202 /* Interpolate */
cannam@154 203 if( silk_abs( ylo ) < 65536 ) {
cannam@154 204 /* Avoid dividing by zero */
cannam@154 205 den = ylo - yhi;
cannam@154 206 nom = silk_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + silk_RSHIFT( den, 1 );
cannam@154 207 if( den != 0 ) {
cannam@154 208 ffrac += silk_DIV32( nom, den );
cannam@154 209 }
cannam@154 210 } else {
cannam@154 211 /* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */
cannam@154 212 ffrac += silk_DIV32( ylo, silk_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) );
cannam@154 213 }
cannam@154 214 NLSF[ root_ix ] = (opus_int16)silk_min_32( silk_LSHIFT( (opus_int32)k, 8 ) + ffrac, silk_int16_MAX );
cannam@154 215
cannam@154 216 silk_assert( NLSF[ root_ix ] >= 0 );
cannam@154 217
cannam@154 218 root_ix++; /* Next root */
cannam@154 219 if( root_ix >= d ) {
cannam@154 220 /* Found all roots */
cannam@154 221 break;
cannam@154 222 }
cannam@154 223 /* Alternate pointer to polynomial */
cannam@154 224 p = PQ[ root_ix & 1 ];
cannam@154 225
cannam@154 226 /* Evaluate polynomial */
cannam@154 227 xlo = silk_LSFCosTab_FIX_Q12[ k - 1 ]; /* Q12*/
cannam@154 228 ylo = silk_LSHIFT( 1 - ( root_ix & 2 ), 12 );
cannam@154 229 } else {
cannam@154 230 /* Increment loop counter */
cannam@154 231 k++;
cannam@154 232 xlo = xhi;
cannam@154 233 ylo = yhi;
cannam@154 234 thr = 0;
cannam@154 235
cannam@154 236 if( k > LSF_COS_TAB_SZ_FIX ) {
cannam@154 237 i++;
cannam@154 238 if( i > MAX_ITERATIONS_A2NLSF_FIX ) {
cannam@154 239 /* Set NLSFs to white spectrum and exit */
cannam@154 240 NLSF[ 0 ] = (opus_int16)silk_DIV32_16( 1 << 15, d + 1 );
cannam@154 241 for( k = 1; k < d; k++ ) {
cannam@154 242 NLSF[ k ] = (opus_int16)silk_ADD16( NLSF[ k-1 ], NLSF[ 0 ] );
cannam@154 243 }
cannam@154 244 return;
cannam@154 245 }
cannam@154 246
cannam@154 247 /* Error: Apply progressively more bandwidth expansion and run again */
cannam@154 248 silk_bwexpander_32( a_Q16, d, 65536 - silk_LSHIFT( 1, i ) );
cannam@154 249
cannam@154 250 silk_A2NLSF_init( a_Q16, P, Q, dd );
cannam@154 251 p = P; /* Pointer to polynomial */
cannam@154 252 xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/
cannam@154 253 ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
cannam@154 254 if( ylo < 0 ) {
cannam@154 255 /* Set the first NLSF to zero and move on to the next */
cannam@154 256 NLSF[ 0 ] = 0;
cannam@154 257 p = Q; /* Pointer to polynomial */
cannam@154 258 ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
cannam@154 259 root_ix = 1; /* Index of current root */
cannam@154 260 } else {
cannam@154 261 root_ix = 0; /* Index of current root */
cannam@154 262 }
cannam@154 263 k = 1; /* Reset loop counter */
cannam@154 264 }
cannam@154 265 }
cannam@154 266 }
cannam@154 267 }