Chris@69: /*********************************************************************** Chris@69: Copyright (c) 2006-2011, Skype Limited. All rights reserved. Chris@69: Redistribution and use in source and binary forms, with or without Chris@69: modification, are permitted provided that the following conditions Chris@69: are met: Chris@69: - Redistributions of source code must retain the above copyright notice, Chris@69: this list of conditions and the following disclaimer. Chris@69: - Redistributions in binary form must reproduce the above copyright Chris@69: notice, this list of conditions and the following disclaimer in the Chris@69: documentation and/or other materials provided with the distribution. Chris@69: - Neither the name of Internet Society, IETF or IETF Trust, nor the Chris@69: names of specific contributors, may be used to endorse or promote Chris@69: products derived from this software without specific prior written Chris@69: permission. Chris@69: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" Chris@69: AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE Chris@69: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE Chris@69: ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE Chris@69: LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR Chris@69: CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF Chris@69: SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS Chris@69: INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN Chris@69: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) Chris@69: ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE Chris@69: POSSIBILITY OF SUCH DAMAGE. Chris@69: ***********************************************************************/ Chris@69: Chris@69: #ifdef HAVE_CONFIG_H Chris@69: #include "config.h" Chris@69: #endif Chris@69: Chris@69: #include "main_FIX.h" Chris@69: #include "stack_alloc.h" Chris@69: Chris@69: /* Calculates residual energies of input subframes where all subframes have LPC_order */ Chris@69: /* of preceding samples */ Chris@69: void silk_residual_energy_FIX( Chris@69: opus_int32 nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ Chris@69: opus_int nrgsQ[ MAX_NB_SUBFR ], /* O Q value per subframe */ Chris@69: const opus_int16 x[], /* I Input signal */ Chris@69: opus_int16 a_Q12[ 2 ][ MAX_LPC_ORDER ], /* I AR coefs for each frame half */ Chris@69: const opus_int32 gains[ MAX_NB_SUBFR ], /* I Quantization gains */ Chris@69: const opus_int subfr_length, /* I Subframe length */ Chris@69: const opus_int nb_subfr, /* I Number of subframes */ Chris@69: const opus_int LPC_order, /* I LPC order */ Chris@69: int arch /* I Run-time architecture */ Chris@69: ) Chris@69: { Chris@69: opus_int offset, i, j, rshift, lz1, lz2; Chris@69: opus_int16 *LPC_res_ptr; Chris@69: VARDECL( opus_int16, LPC_res ); Chris@69: const opus_int16 *x_ptr; Chris@69: opus_int32 tmp32; Chris@69: SAVE_STACK; Chris@69: Chris@69: x_ptr = x; Chris@69: offset = LPC_order + subfr_length; Chris@69: Chris@69: /* Filter input to create the LPC residual for each frame half, and measure subframe energies */ Chris@69: ALLOC( LPC_res, ( MAX_NB_SUBFR >> 1 ) * offset, opus_int16 ); Chris@69: celt_assert( ( nb_subfr >> 1 ) * ( MAX_NB_SUBFR >> 1 ) == nb_subfr ); Chris@69: for( i = 0; i < nb_subfr >> 1; i++ ) { Chris@69: /* Calculate half frame LPC residual signal including preceding samples */ Chris@69: silk_LPC_analysis_filter( LPC_res, x_ptr, a_Q12[ i ], ( MAX_NB_SUBFR >> 1 ) * offset, LPC_order, arch ); Chris@69: Chris@69: /* Point to first subframe of the just calculated LPC residual signal */ Chris@69: LPC_res_ptr = LPC_res + LPC_order; Chris@69: for( j = 0; j < ( MAX_NB_SUBFR >> 1 ); j++ ) { Chris@69: /* Measure subframe energy */ Chris@69: silk_sum_sqr_shift( &nrgs[ i * ( MAX_NB_SUBFR >> 1 ) + j ], &rshift, LPC_res_ptr, subfr_length ); Chris@69: Chris@69: /* Set Q values for the measured energy */ Chris@69: nrgsQ[ i * ( MAX_NB_SUBFR >> 1 ) + j ] = -rshift; Chris@69: Chris@69: /* Move to next subframe */ Chris@69: LPC_res_ptr += offset; Chris@69: } Chris@69: /* Move to next frame half */ Chris@69: x_ptr += ( MAX_NB_SUBFR >> 1 ) * offset; Chris@69: } Chris@69: Chris@69: /* Apply the squared subframe gains */ Chris@69: for( i = 0; i < nb_subfr; i++ ) { Chris@69: /* Fully upscale gains and energies */ Chris@69: lz1 = silk_CLZ32( nrgs[ i ] ) - 1; Chris@69: lz2 = silk_CLZ32( gains[ i ] ) - 1; Chris@69: Chris@69: tmp32 = silk_LSHIFT32( gains[ i ], lz2 ); Chris@69: Chris@69: /* Find squared gains */ Chris@69: tmp32 = silk_SMMUL( tmp32, tmp32 ); /* Q( 2 * lz2 - 32 )*/ Chris@69: Chris@69: /* Scale energies */ Chris@69: nrgs[ i ] = silk_SMMUL( tmp32, silk_LSHIFT32( nrgs[ i ], lz1 ) ); /* Q( nrgsQ[ i ] + lz1 + 2 * lz2 - 32 - 32 )*/ Chris@69: nrgsQ[ i ] += lz1 + 2 * lz2 - 32 - 32; Chris@69: } Chris@69: RESTORE_STACK; Chris@69: }