15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/***********************************************************************
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Copyright (c) 2006-2011, Skype Limited. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Redistribution and use in source and binary forms, with or without
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)modification, are permitted provided that the following conditions
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)are met:
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Redistributions of source code must retain the above copyright notice,
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)this list of conditions and the following disclaimer.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- Redistributions in binary form must reproduce the above copyright
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)notice, this list of conditions and the following disclaimer in the
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)documentation and/or other materials provided with the distribution.
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)- Neither the name of Internet Society, IETF or IETF Trust, nor the
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinames of specific contributors, may be used to endorse or promote
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)products derived from this software without specific prior written
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)permission.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochPOSSIBILITY OF SUCH DAMAGE.
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch***********************************************************************/
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_CONFIG_H
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config.h"
30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "main_FLP.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tuning_parameters.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/* Compute gain to make warped filter coefficients have a zero mean log frequency response on a   */
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */
3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/* Note: A monic filter is one with the first coefficient equal to 1.0. In Silk we omit the first */
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/* coefficient in an array of coefficients, for monic filters.                                    */
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static OPUS_INLINE silk_float warped_gain(
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const silk_float     *coefs,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    silk_float           lambda,
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    opus_int             order
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    opus_int   i;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    silk_float gain;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lambda = -lambda;
486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    gain = coefs[ order - 1 ];
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for( i = order - 2; i >= 0; i-- ) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gain = lambda * gain + coefs[ i ];
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (silk_float)( 1.0f / ( 1.0f - lambda * gain ) );
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
54a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum     */
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static OPUS_INLINE void warped_true2monic_coefs(
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    silk_float           *coefs_syn,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    silk_float           *coefs_ana,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    silk_float           lambda,
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    silk_float           limit,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    opus_int             order
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    opus_int   i, iter, ind = 0;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    silk_float tmp, maxabs, chirp, gain_syn, gain_ana;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Convert to monic coefficients */
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for( i = order - 1; i > 0; i-- ) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ];
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ];
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] );
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] );
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for( i = 0; i < order; i++ ) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        coefs_syn[ i ] *= gain_syn;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        coefs_ana[ i ] *= gain_ana;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Limit */
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for( iter = 0; iter < 10; iter++ ) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Find maximum absolute value */
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        maxabs = -1.0f;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for( i = 0; i < order; i++ ) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            tmp = silk_max( silk_abs_float( coefs_syn[ i ] ), silk_abs_float( coefs_ana[ i ] ) );
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if( tmp > maxabs ) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                maxabs = tmp;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ind = i;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( maxabs <= limit ) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* Coefficients are within range - done */
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Convert back to true warped coefficients */
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for( i = 1; i < order; i++ ) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            coefs_syn[ i - 1 ] += lambda * coefs_syn[ i ];
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            coefs_ana[ i - 1 ] += lambda * coefs_ana[ i ];
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gain_syn = 1.0f / gain_syn;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gain_ana = 1.0f / gain_ana;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for( i = 0; i < order; i++ ) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            coefs_syn[ i ] *= gain_syn;
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            coefs_ana[ i ] *= gain_ana;
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Apply bandwidth expansion */
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        silk_bwexpander_FLP( coefs_syn, order, chirp );
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        silk_bwexpander_FLP( coefs_ana, order, chirp );
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Convert to monic warped coefficients */
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        for( i = order - 1; i > 0; i-- ) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ];
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ];
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] );
1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] );
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for( i = 0; i < order; i++ ) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            coefs_syn[ i ] *= gain_syn;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            coefs_ana[ i ] *= gain_ana;
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    silk_assert( 0 );
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/* Compute noise shaping coefficients and initial gain values */
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void silk_noise_shape_analysis_FLP(
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const silk_float                *pitch_res,                         /* I    LPC residual from pitch analysis            */
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const silk_float                *x                                  /* I    Input signal [frame_length + la_shape]      */
1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles))
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    silk_shape_state_FLP *psShapeSt = &psEnc->sShape;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    opus_int     k, nSamples;
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    silk_float   SNR_adj_dB, HarmBoost, HarmShapeGain, Tilt;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    silk_float   nrg, pre_nrg, log_energy, log_energy_prev, energy_variation;
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    silk_float   delta, BWExp1, BWExp2, gain_mult, gain_add, strength, b, warping;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    silk_float   x_windowed[ SHAPE_LPC_WIN_MAX ];
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    silk_float   auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const silk_float *x_ptr, *pitch_res_ptr;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Point to start of first LPC analysis block */
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x_ptr = x - psEnc->sCmn.la_shape;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /****************/
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* GAIN CONTROL */
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /****************/
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SNR_adj_dB = psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f );
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Input quality is the average of the quality in the lowest two VAD bands */
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    psEncCtrl->input_quality = 0.5f * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] + psEnc->sCmn.input_quality_bands_Q15[ 1 ] ) * ( 1.0f / 32768.0f );
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Coding quality level, between 0.0 and 1.0 */
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    psEncCtrl->coding_quality = silk_sigmoid( 0.25f * ( SNR_adj_dB - 20.0f ) );
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( psEnc->sCmn.useCBR == 0 ) {
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        /* Reduce coding SNR during low speech activity */
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        b = 1.0f - psEnc->sCmn.speech_activity_Q8 * ( 1.0f /  256.0f );
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SNR_adj_dB -= BG_SNR_DECR_dB * psEncCtrl->coding_quality * ( 0.5f + 0.5f * psEncCtrl->input_quality ) * b * b;
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Reduce gains for periodic signals */
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SNR_adj_dB += HARM_SNR_INCR_dB * psEnc->LTPCorr;
1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        SNR_adj_dB += ( -0.4f * psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ) + 6.0f ) * ( 1.0f - psEncCtrl->input_quality );
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*************************/
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* SPARSENESS PROCESSING */
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    /*************************/
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Set quantizer offset */
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Initially set to 0; may be overruled in process_gains(..) */
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        psEnc->sCmn.indices.quantOffsetType = 0;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        psEncCtrl->sparseness = 0.0f;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        nSamples = 2 * psEnc->sCmn.fs_kHz;
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        energy_variation = 0.0f;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        log_energy_prev  = 0.0f;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pitch_res_ptr = pitch_res;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            nrg = ( silk_float )nSamples + ( silk_float )silk_energy_FLP( pitch_res_ptr, nSamples );
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            log_energy = silk_log2( nrg );
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if( k > 0 ) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                energy_variation += silk_abs_float( log_energy - log_energy_prev );
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            log_energy_prev = log_energy;
193            pitch_res_ptr += nSamples;
194        }
195        psEncCtrl->sparseness = silk_sigmoid( 0.4f * ( energy_variation - 5.0f ) );
196
197        /* Set quantization offset depending on sparseness measure */
198        if( psEncCtrl->sparseness > SPARSENESS_THRESHOLD_QNT_OFFSET ) {
199            psEnc->sCmn.indices.quantOffsetType = 0;
200        } else {
201            psEnc->sCmn.indices.quantOffsetType = 1;
202        }
203
204        /* Increase coding SNR for sparse signals */
205        SNR_adj_dB += SPARSE_SNR_INCR_dB * ( psEncCtrl->sparseness - 0.5f );
206    }
207
208    /*******************************/
209    /* Control bandwidth expansion */
210    /*******************************/
211    /* More BWE for signals with high prediction gain */
212    strength = FIND_PITCH_WHITE_NOISE_FRACTION * psEncCtrl->predGain;           /* between 0.0 and 1.0 */
213    BWExp1 = BWExp2 = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength );
214    delta  = LOW_RATE_BANDWIDTH_EXPANSION_DELTA * ( 1.0f - 0.75f * psEncCtrl->coding_quality );
215    BWExp1 -= delta;
216    BWExp2 += delta;
217    /* BWExp1 will be applied after BWExp2, so make it relative */
218    BWExp1 /= BWExp2;
219
220    if( psEnc->sCmn.warping_Q16 > 0 ) {
221        /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
222        warping = (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality;
223    } else {
224        warping = 0.0f;
225    }
226
227    /********************************************/
228    /* Compute noise shaping AR coefs and gains */
229    /********************************************/
230    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
231        /* Apply window: sine slope followed by flat part followed by cosine slope */
232        opus_int shift, slope_part, flat_part;
233        flat_part = psEnc->sCmn.fs_kHz * 3;
234        slope_part = ( psEnc->sCmn.shapeWinLength - flat_part ) / 2;
235
236        silk_apply_sine_window_FLP( x_windowed, x_ptr, 1, slope_part );
237        shift = slope_part;
238        silk_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(silk_float) );
239        shift += flat_part;
240        silk_apply_sine_window_FLP( x_windowed + shift, x_ptr + shift, 2, slope_part );
241
242        /* Update pointer: next LPC analysis block */
243        x_ptr += psEnc->sCmn.subfr_length;
244
245        if( psEnc->sCmn.warping_Q16 > 0 ) {
246            /* Calculate warped auto correlation */
247            silk_warped_autocorrelation_FLP( auto_corr, x_windowed, warping,
248                psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
249        } else {
250            /* Calculate regular auto correlation */
251            silk_autocorrelation_FLP( auto_corr, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1 );
252        }
253
254        /* Add white noise, as a fraction of energy */
255        auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION;
256
257        /* Convert correlations to prediction coefficients, and compute residual energy */
258        nrg = silk_levinsondurbin_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], auto_corr, psEnc->sCmn.shapingLPCOrder );
259        psEncCtrl->Gains[ k ] = ( silk_float )sqrt( nrg );
260
261        if( psEnc->sCmn.warping_Q16 > 0 ) {
262            /* Adjust gain for warping */
263            psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );
264        }
265
266        /* Bandwidth expansion for synthesis filter shaping */
267        silk_bwexpander_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp2 );
268
269        /* Compute noise shaping filter coefficients */
270        silk_memcpy(
271            &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ],
272            &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ],
273            psEnc->sCmn.shapingLPCOrder * sizeof( silk_float ) );
274
275        /* Bandwidth expansion for analysis filter shaping */
276        silk_bwexpander_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp1 );
277
278        /* Ratio of prediction gains, in energy domain */
279        pre_nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );
280        nrg     = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );
281        psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg );
282
283        /* Convert to monic warped prediction coefficients and limit absolute values */
284        warped_true2monic_coefs( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ],
285            warping, 3.999f, psEnc->sCmn.shapingLPCOrder );
286    }
287
288    /*****************/
289    /* Gain tweaking */
290    /*****************/
291    /* Increase gains during low speech activity */
292    gain_mult = (silk_float)pow( 2.0f, -0.16f * SNR_adj_dB );
293    gain_add  = (silk_float)pow( 2.0f,  0.16f * MIN_QGAIN_DB );
294    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
295        psEncCtrl->Gains[ k ] *= gain_mult;
296        psEncCtrl->Gains[ k ] += gain_add;
297    }
298
299    gain_mult = 1.0f + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT;
300    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
301        psEncCtrl->GainsPre[ k ] *= gain_mult;
302    }
303
304    /************************************************/
305    /* Control low-frequency shaping and noise tilt */
306    /************************************************/
307    /* Less low frequency shaping for noisy inputs */
308    strength = LOW_FREQ_SHAPING * ( 1.0f + LOW_QUALITY_LOW_FREQ_SHAPING_DECR * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] * ( 1.0f / 32768.0f ) - 1.0f ) );
309    strength *= psEnc->sCmn.speech_activity_Q8 * ( 1.0f /  256.0f );
310    if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
311        /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */
312        /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/
313        for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
314            b = 0.2f / psEnc->sCmn.fs_kHz + 3.0f / psEncCtrl->pitchL[ k ];
315            psEncCtrl->LF_MA_shp[ k ] = -1.0f + b;
316            psEncCtrl->LF_AR_shp[ k ] =  1.0f - b - b * strength;
317        }
318        Tilt = - HP_NOISE_COEF -
319            (1 - HP_NOISE_COEF) * HARM_HP_NOISE_COEF * psEnc->sCmn.speech_activity_Q8 * ( 1.0f /  256.0f );
320    } else {
321        b = 1.3f / psEnc->sCmn.fs_kHz;
322        psEncCtrl->LF_MA_shp[ 0 ] = -1.0f + b;
323        psEncCtrl->LF_AR_shp[ 0 ] =  1.0f - b - b * strength * 0.6f;
324        for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) {
325            psEncCtrl->LF_MA_shp[ k ] = psEncCtrl->LF_MA_shp[ 0 ];
326            psEncCtrl->LF_AR_shp[ k ] = psEncCtrl->LF_AR_shp[ 0 ];
327        }
328        Tilt = -HP_NOISE_COEF;
329    }
330
331    /****************************/
332    /* HARMONIC SHAPING CONTROL */
333    /****************************/
334    /* Control boosting of harmonic frequencies */
335    HarmBoost = LOW_RATE_HARMONIC_BOOST * ( 1.0f - psEncCtrl->coding_quality ) * psEnc->LTPCorr;
336
337    /* More harmonic boost for noisy input signals */
338    HarmBoost += LOW_INPUT_QUALITY_HARMONIC_BOOST * ( 1.0f - psEncCtrl->input_quality );
339
340    if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
341        /* Harmonic noise shaping */
342        HarmShapeGain = HARMONIC_SHAPING;
343
344        /* More harmonic noise shaping for high bitrates or noisy input */
345        HarmShapeGain += HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING *
346            ( 1.0f - ( 1.0f - psEncCtrl->coding_quality ) * psEncCtrl->input_quality );
347
348        /* Less harmonic noise shaping for less periodic signals */
349        HarmShapeGain *= ( silk_float )sqrt( psEnc->LTPCorr );
350    } else {
351        HarmShapeGain = 0.0f;
352    }
353
354    /*************************/
355    /* Smooth over subframes */
356    /*************************/
357    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
358        psShapeSt->HarmBoost_smth     += SUBFR_SMTH_COEF * ( HarmBoost - psShapeSt->HarmBoost_smth );
359        psEncCtrl->HarmBoost[ k ]      = psShapeSt->HarmBoost_smth;
360        psShapeSt->HarmShapeGain_smth += SUBFR_SMTH_COEF * ( HarmShapeGain - psShapeSt->HarmShapeGain_smth );
361        psEncCtrl->HarmShapeGain[ k ]  = psShapeSt->HarmShapeGain_smth;
362        psShapeSt->Tilt_smth          += SUBFR_SMTH_COEF * ( Tilt - psShapeSt->Tilt_smth );
363        psEncCtrl->Tilt[ k ]           = psShapeSt->Tilt_smth;
364    }
365}
366