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 +