media/libopus/silk/NLSF2A.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libopus/silk/NLSF2A.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,178 @@
     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 +#ifdef HAVE_CONFIG_H
    1.32 +#include "config.h"
    1.33 +#endif
    1.34 +
    1.35 +/* conversion between prediction filter coefficients and LSFs   */
    1.36 +/* order should be even                                         */
    1.37 +/* a piecewise linear approximation maps LSF <-> cos(LSF)       */
    1.38 +/* therefore the result is not accurate LSFs, but the two       */
    1.39 +/* functions are accurate inverses of each other                */
    1.40 +
    1.41 +#include "SigProc_FIX.h"
    1.42 +#include "tables.h"
    1.43 +
    1.44 +#define QA      16
    1.45 +
    1.46 +/* helper function for NLSF2A(..) */
    1.47 +static OPUS_INLINE void silk_NLSF2A_find_poly(
    1.48 +    opus_int32          *out,      /* O    intermediate polynomial, QA [dd+1]        */
    1.49 +    const opus_int32    *cLSF,     /* I    vector of interleaved 2*cos(LSFs), QA [d] */
    1.50 +    opus_int            dd         /* I    polynomial order (= 1/2 * filter order)   */
    1.51 +)
    1.52 +{
    1.53 +    opus_int   k, n;
    1.54 +    opus_int32 ftmp;
    1.55 +
    1.56 +    out[0] = silk_LSHIFT( 1, QA );
    1.57 +    out[1] = -cLSF[0];
    1.58 +    for( k = 1; k < dd; k++ ) {
    1.59 +        ftmp = cLSF[2*k];            /* QA*/
    1.60 +        out[k+1] = silk_LSHIFT( out[k-1], 1 ) - (opus_int32)silk_RSHIFT_ROUND64( silk_SMULL( ftmp, out[k] ), QA );
    1.61 +        for( n = k; n > 1; n-- ) {
    1.62 +            out[n] += out[n-2] - (opus_int32)silk_RSHIFT_ROUND64( silk_SMULL( ftmp, out[n-1] ), QA );
    1.63 +        }
    1.64 +        out[1] -= ftmp;
    1.65 +    }
    1.66 +}
    1.67 +
    1.68 +/* compute whitening filter coefficients from normalized line spectral frequencies */
    1.69 +void silk_NLSF2A(
    1.70 +    opus_int16                  *a_Q12,             /* O    monic whitening filter coefficients in Q12,  [ d ]          */
    1.71 +    const opus_int16            *NLSF,              /* I    normalized line spectral frequencies in Q15, [ d ]          */
    1.72 +    const opus_int              d                   /* I    filter order (should be even)                               */
    1.73 +)
    1.74 +{
    1.75 +    /* This ordering was found to maximize quality. It improves numerical accuracy of
    1.76 +       silk_NLSF2A_find_poly() compared to "standard" ordering. */
    1.77 +    static const unsigned char ordering16[16] = {
    1.78 +      0, 15, 8, 7, 4, 11, 12, 3, 2, 13, 10, 5, 6, 9, 14, 1
    1.79 +    };
    1.80 +    static const unsigned char ordering10[10] = {
    1.81 +      0, 9, 6, 3, 4, 5, 8, 1, 2, 7
    1.82 +    };
    1.83 +    const unsigned char *ordering;
    1.84 +    opus_int   k, i, dd;
    1.85 +    opus_int32 cos_LSF_QA[ SILK_MAX_ORDER_LPC ];
    1.86 +    opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
    1.87 +    opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta;
    1.88 +    opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ];
    1.89 +    opus_int32 maxabs, absval, idx=0, sc_Q16;
    1.90 +
    1.91 +    silk_assert( LSF_COS_TAB_SZ_FIX == 128 );
    1.92 +    silk_assert( d==10||d==16 );
    1.93 +
    1.94 +    /* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */
    1.95 +    ordering = d == 16 ? ordering16 : ordering10;
    1.96 +    for( k = 0; k < d; k++ ) {
    1.97 +        silk_assert(NLSF[k] >= 0 );
    1.98 +
    1.99 +        /* f_int on a scale 0-127 (rounded down) */
   1.100 +        f_int = silk_RSHIFT( NLSF[k], 15 - 7 );
   1.101 +
   1.102 +        /* f_frac, range: 0..255 */
   1.103 +        f_frac = NLSF[k] - silk_LSHIFT( f_int, 15 - 7 );
   1.104 +
   1.105 +        silk_assert(f_int >= 0);
   1.106 +        silk_assert(f_int < LSF_COS_TAB_SZ_FIX );
   1.107 +
   1.108 +        /* Read start and end value from table */
   1.109 +        cos_val = silk_LSFCosTab_FIX_Q12[ f_int ];                /* Q12 */
   1.110 +        delta   = silk_LSFCosTab_FIX_Q12[ f_int + 1 ] - cos_val;  /* Q12, with a range of 0..200 */
   1.111 +
   1.112 +        /* Linear interpolation */
   1.113 +        cos_LSF_QA[ordering[k]] = silk_RSHIFT_ROUND( silk_LSHIFT( cos_val, 8 ) + silk_MUL( delta, f_frac ), 20 - QA ); /* QA */
   1.114 +    }
   1.115 +
   1.116 +    dd = silk_RSHIFT( d, 1 );
   1.117 +
   1.118 +    /* generate even and odd polynomials using convolution */
   1.119 +    silk_NLSF2A_find_poly( P, &cos_LSF_QA[ 0 ], dd );
   1.120 +    silk_NLSF2A_find_poly( Q, &cos_LSF_QA[ 1 ], dd );
   1.121 +
   1.122 +    /* convert even and odd polynomials to opus_int32 Q12 filter coefs */
   1.123 +    for( k = 0; k < dd; k++ ) {
   1.124 +        Ptmp = P[ k+1 ] + P[ k ];
   1.125 +        Qtmp = Q[ k+1 ] - Q[ k ];
   1.126 +
   1.127 +        /* the Ptmp and Qtmp values at this stage need to fit in int32 */
   1.128 +        a32_QA1[ k ]     = -Qtmp - Ptmp;        /* QA+1 */
   1.129 +        a32_QA1[ d-k-1 ] =  Qtmp - Ptmp;        /* QA+1 */
   1.130 +    }
   1.131 +
   1.132 +    /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
   1.133 +    for( i = 0; i < 10; i++ ) {
   1.134 +        /* Find maximum absolute value and its index */
   1.135 +        maxabs = 0;
   1.136 +        for( k = 0; k < d; k++ ) {
   1.137 +            absval = silk_abs( a32_QA1[k] );
   1.138 +            if( absval > maxabs ) {
   1.139 +                maxabs = absval;
   1.140 +                idx    = k;
   1.141 +            }
   1.142 +        }
   1.143 +        maxabs = silk_RSHIFT_ROUND( maxabs, QA + 1 - 12 );                                          /* QA+1 -> Q12 */
   1.144 +
   1.145 +        if( maxabs > silk_int16_MAX ) {
   1.146 +            /* Reduce magnitude of prediction coefficients */
   1.147 +            maxabs = silk_min( maxabs, 163838 );  /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
   1.148 +            sc_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ),
   1.149 +                                        silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) );
   1.150 +            silk_bwexpander_32( a32_QA1, d, sc_Q16 );
   1.151 +        } else {
   1.152 +            break;
   1.153 +        }
   1.154 +    }
   1.155 +
   1.156 +    if( i == 10 ) {
   1.157 +        /* Reached the last iteration, clip the coefficients */
   1.158 +        for( k = 0; k < d; k++ ) {
   1.159 +            a_Q12[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) );  /* QA+1 -> Q12 */
   1.160 +            a32_QA1[ k ] = silk_LSHIFT( (opus_int32)a_Q12[ k ], QA + 1 - 12 );
   1.161 +        }
   1.162 +    } else {
   1.163 +        for( k = 0; k < d; k++ ) {
   1.164 +            a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 );                /* QA+1 -> Q12 */
   1.165 +        }
   1.166 +    }
   1.167 +
   1.168 +    for( i = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
   1.169 +        if( silk_LPC_inverse_pred_gain( a_Q12, d ) < SILK_FIX_CONST( 1.0 / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
   1.170 +            /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion   */
   1.171 +            /* on the unscaled coefficients, convert to Q12 and measure again                   */
   1.172 +            silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
   1.173 +            for( k = 0; k < d; k++ ) {
   1.174 +                a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 );            /* QA+1 -> Q12 */
   1.175 +            }
   1.176 +        } else {
   1.177 +            break;
   1.178 +        }
   1.179 +    }
   1.180 +}
   1.181 +

mercurial