media/libopus/silk/fixed/corrMatrix_FIX.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libopus/silk/fixed/corrMatrix_FIX.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,156 @@
     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 +/**********************************************************************
    1.36 + * Correlation Matrix Computations for LS estimate.
    1.37 + **********************************************************************/
    1.38 +
    1.39 +#include "main_FIX.h"
    1.40 +
    1.41 +/* Calculates correlation vector X'*t */
    1.42 +void silk_corrVector_FIX(
    1.43 +    const opus_int16                *x,                                     /* I    x vector [L + order - 1] used to form data matrix X                         */
    1.44 +    const opus_int16                *t,                                     /* I    Target vector [L]                                                           */
    1.45 +    const opus_int                  L,                                      /* I    Length of vectors                                                           */
    1.46 +    const opus_int                  order,                                  /* I    Max lag for correlation                                                     */
    1.47 +    opus_int32                      *Xt,                                    /* O    Pointer to X'*t correlation vector [order]                                  */
    1.48 +    const opus_int                  rshifts                                 /* I    Right shifts of correlations                                                */
    1.49 +)
    1.50 +{
    1.51 +    opus_int         lag, i;
    1.52 +    const opus_int16 *ptr1, *ptr2;
    1.53 +    opus_int32       inner_prod;
    1.54 +
    1.55 +    ptr1 = &x[ order - 1 ]; /* Points to first sample of column 0 of X: X[:,0] */
    1.56 +    ptr2 = t;
    1.57 +    /* Calculate X'*t */
    1.58 +    if( rshifts > 0 ) {
    1.59 +        /* Right shifting used */
    1.60 +        for( lag = 0; lag < order; lag++ ) {
    1.61 +            inner_prod = 0;
    1.62 +            for( i = 0; i < L; i++ ) {
    1.63 +                inner_prod += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts );
    1.64 +            }
    1.65 +            Xt[ lag ] = inner_prod; /* X[:,lag]'*t */
    1.66 +            ptr1--; /* Go to next column of X */
    1.67 +        }
    1.68 +    } else {
    1.69 +        silk_assert( rshifts == 0 );
    1.70 +        for( lag = 0; lag < order; lag++ ) {
    1.71 +            Xt[ lag ] = silk_inner_prod_aligned( ptr1, ptr2, L ); /* X[:,lag]'*t */
    1.72 +            ptr1--; /* Go to next column of X */
    1.73 +        }
    1.74 +    }
    1.75 +}
    1.76 +
    1.77 +/* Calculates correlation matrix X'*X */
    1.78 +void silk_corrMatrix_FIX(
    1.79 +    const opus_int16                *x,                                     /* I    x vector [L + order - 1] used to form data matrix X                         */
    1.80 +    const opus_int                  L,                                      /* I    Length of vectors                                                           */
    1.81 +    const opus_int                  order,                                  /* I    Max lag for correlation                                                     */
    1.82 +    const opus_int                  head_room,                              /* I    Desired headroom                                                            */
    1.83 +    opus_int32                      *XX,                                    /* O    Pointer to X'*X correlation matrix [ order x order ]                        */
    1.84 +    opus_int                        *rshifts                                /* I/O  Right shifts of correlations                                                */
    1.85 +)
    1.86 +{
    1.87 +    opus_int         i, j, lag, rshifts_local, head_room_rshifts;
    1.88 +    opus_int32       energy;
    1.89 +    const opus_int16 *ptr1, *ptr2;
    1.90 +
    1.91 +    /* Calculate energy to find shift used to fit in 32 bits */
    1.92 +    silk_sum_sqr_shift( &energy, &rshifts_local, x, L + order - 1 );
    1.93 +    /* Add shifts to get the desired head room */
    1.94 +    head_room_rshifts = silk_max( head_room - silk_CLZ32( energy ), 0 );
    1.95 +
    1.96 +    energy = silk_RSHIFT32( energy, head_room_rshifts );
    1.97 +    rshifts_local += head_room_rshifts;
    1.98 +
    1.99 +    /* Calculate energy of first column (0) of X: X[:,0]'*X[:,0] */
   1.100 +    /* Remove contribution of first order - 1 samples */
   1.101 +    for( i = 0; i < order - 1; i++ ) {
   1.102 +        energy -= silk_RSHIFT32( silk_SMULBB( x[ i ], x[ i ] ), rshifts_local );
   1.103 +    }
   1.104 +    if( rshifts_local < *rshifts ) {
   1.105 +        /* Adjust energy */
   1.106 +        energy = silk_RSHIFT32( energy, *rshifts - rshifts_local );
   1.107 +        rshifts_local = *rshifts;
   1.108 +    }
   1.109 +
   1.110 +    /* Calculate energy of remaining columns of X: X[:,j]'*X[:,j] */
   1.111 +    /* Fill out the diagonal of the correlation matrix */
   1.112 +    matrix_ptr( XX, 0, 0, order ) = energy;
   1.113 +    ptr1 = &x[ order - 1 ]; /* First sample of column 0 of X */
   1.114 +    for( j = 1; j < order; j++ ) {
   1.115 +        energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), rshifts_local ) );
   1.116 +        energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr1[ -j ] ), rshifts_local ) );
   1.117 +        matrix_ptr( XX, j, j, order ) = energy;
   1.118 +    }
   1.119 +
   1.120 +    ptr2 = &x[ order - 2 ]; /* First sample of column 1 of X */
   1.121 +    /* Calculate the remaining elements of the correlation matrix */
   1.122 +    if( rshifts_local > 0 ) {
   1.123 +        /* Right shifting used */
   1.124 +        for( lag = 1; lag < order; lag++ ) {
   1.125 +            /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */
   1.126 +            energy = 0;
   1.127 +            for( i = 0; i < L; i++ ) {
   1.128 +                energy += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts_local );
   1.129 +            }
   1.130 +            /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */
   1.131 +            matrix_ptr( XX, lag, 0, order ) = energy;
   1.132 +            matrix_ptr( XX, 0, lag, order ) = energy;
   1.133 +            for( j = 1; j < ( order - lag ); j++ ) {
   1.134 +                energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), rshifts_local ) );
   1.135 +                energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr2[ -j ] ), rshifts_local ) );
   1.136 +                matrix_ptr( XX, lag + j, j, order ) = energy;
   1.137 +                matrix_ptr( XX, j, lag + j, order ) = energy;
   1.138 +            }
   1.139 +            ptr2--; /* Update pointer to first sample of next column (lag) in X */
   1.140 +        }
   1.141 +    } else {
   1.142 +        for( lag = 1; lag < order; lag++ ) {
   1.143 +            /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */
   1.144 +            energy = silk_inner_prod_aligned( ptr1, ptr2, L );
   1.145 +            matrix_ptr( XX, lag, 0, order ) = energy;
   1.146 +            matrix_ptr( XX, 0, lag, order ) = energy;
   1.147 +            /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */
   1.148 +            for( j = 1; j < ( order - lag ); j++ ) {
   1.149 +                energy = silk_SUB32( energy, silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ) );
   1.150 +                energy = silk_SMLABB( energy, ptr1[ -j ], ptr2[ -j ] );
   1.151 +                matrix_ptr( XX, lag + j, j, order ) = energy;
   1.152 +                matrix_ptr( XX, j, lag + j, order ) = energy;
   1.153 +            }
   1.154 +            ptr2--;/* Update pointer to first sample of next column (lag) in X */
   1.155 +        }
   1.156 +    }
   1.157 +    *rshifts = rshifts_local;
   1.158 +}
   1.159 +

mercurial