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