LCOV - code coverage report
Current view: top level - media/libopus/silk/float - noise_shape_analysis_FLP.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 136 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 4 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /***********************************************************************
       2             : Copyright (c) 2006-2011, Skype Limited. All rights reserved.
       3             : Redistribution and use in source and binary forms, with or without
       4             : modification, are permitted provided that the following conditions
       5             : are met:
       6             : - Redistributions of source code must retain the above copyright notice,
       7             : this list of conditions and the following disclaimer.
       8             : - Redistributions in binary form must reproduce the above copyright
       9             : notice, this list of conditions and the following disclaimer in the
      10             : documentation and/or other materials provided with the distribution.
      11             : - Neither the name of Internet Society, IETF or IETF Trust, nor the
      12             : names of specific contributors, may be used to endorse or promote
      13             : products derived from this software without specific prior written
      14             : permission.
      15             : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      16             : AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      17             : IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      18             : ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      19             : LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      20             : CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      21             : SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      22             : INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      23             : CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      24             : ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      25             : POSSIBILITY OF SUCH DAMAGE.
      26             : ***********************************************************************/
      27             : 
      28             : #ifdef HAVE_CONFIG_H
      29             : #include "config.h"
      30             : #endif
      31             : 
      32             : #include "main_FLP.h"
      33             : #include "tuning_parameters.h"
      34             : 
      35             : /* Compute gain to make warped filter coefficients have a zero mean log frequency response on a   */
      36             : /* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */
      37             : /* Note: A monic filter is one with the first coefficient equal to 1.0. In Silk we omit the first */
      38             : /* coefficient in an array of coefficients, for monic filters.                                    */
      39           0 : static OPUS_INLINE silk_float warped_gain(
      40             :     const silk_float     *coefs,
      41             :     silk_float           lambda,
      42             :     opus_int             order
      43             : ) {
      44             :     opus_int   i;
      45             :     silk_float gain;
      46             : 
      47           0 :     lambda = -lambda;
      48           0 :     gain = coefs[ order - 1 ];
      49           0 :     for( i = order - 2; i >= 0; i-- ) {
      50           0 :         gain = lambda * gain + coefs[ i ];
      51             :     }
      52           0 :     return (silk_float)( 1.0f / ( 1.0f - lambda * gain ) );
      53             : }
      54             : 
      55             : /* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum     */
      56             : /* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
      57           0 : static OPUS_INLINE void warped_true2monic_coefs(
      58             :     silk_float           *coefs,
      59             :     silk_float           lambda,
      60             :     silk_float           limit,
      61             :     opus_int             order
      62             : ) {
      63           0 :     opus_int   i, iter, ind = 0;
      64             :     silk_float tmp, maxabs, chirp, gain;
      65             : 
      66             :     /* Convert to monic coefficients */
      67           0 :     for( i = order - 1; i > 0; i-- ) {
      68           0 :         coefs[ i - 1 ] -= lambda * coefs[ i ];
      69             :     }
      70           0 :     gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
      71           0 :     for( i = 0; i < order; i++ ) {
      72           0 :         coefs[ i ] *= gain;
      73             :     }
      74             : 
      75             :     /* Limit */
      76           0 :     for( iter = 0; iter < 10; iter++ ) {
      77             :         /* Find maximum absolute value */
      78           0 :         maxabs = -1.0f;
      79           0 :         for( i = 0; i < order; i++ ) {
      80           0 :             tmp = silk_abs_float( coefs[ i ] );
      81           0 :             if( tmp > maxabs ) {
      82           0 :                 maxabs = tmp;
      83           0 :                 ind = i;
      84             :             }
      85             :         }
      86           0 :         if( maxabs <= limit ) {
      87             :             /* Coefficients are within range - done */
      88           0 :             return;
      89             :         }
      90             : 
      91             :         /* Convert back to true warped coefficients */
      92           0 :         for( i = 1; i < order; i++ ) {
      93           0 :             coefs[ i - 1 ] += lambda * coefs[ i ];
      94             :         }
      95           0 :         gain = 1.0f / gain;
      96           0 :         for( i = 0; i < order; i++ ) {
      97           0 :             coefs[ i ] *= gain;
      98             :         }
      99             : 
     100             :         /* Apply bandwidth expansion */
     101           0 :         chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
     102           0 :         silk_bwexpander_FLP( coefs, order, chirp );
     103             : 
     104             :         /* Convert to monic warped coefficients */
     105           0 :         for( i = order - 1; i > 0; i-- ) {
     106           0 :             coefs[ i - 1 ] -= lambda * coefs[ i ];
     107             :         }
     108           0 :         gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
     109           0 :         for( i = 0; i < order; i++ ) {
     110           0 :             coefs[ i ] *= gain;
     111             :         }
     112             :     }
     113           0 :     silk_assert( 0 );
     114             : }
     115             : 
     116           0 : static OPUS_INLINE void limit_coefs(
     117             :     silk_float           *coefs,
     118             :     silk_float           limit,
     119             :     opus_int             order
     120             : ) {
     121           0 :     opus_int   i, iter, ind = 0;
     122             :     silk_float tmp, maxabs, chirp;
     123             : 
     124           0 :     for( iter = 0; iter < 10; iter++ ) {
     125             :         /* Find maximum absolute value */
     126           0 :         maxabs = -1.0f;
     127           0 :         for( i = 0; i < order; i++ ) {
     128           0 :             tmp = silk_abs_float( coefs[ i ] );
     129           0 :             if( tmp > maxabs ) {
     130           0 :                 maxabs = tmp;
     131           0 :                 ind = i;
     132             :             }
     133             :         }
     134           0 :         if( maxabs <= limit ) {
     135             :             /* Coefficients are within range - done */
     136           0 :             return;
     137             :         }
     138             : 
     139             :         /* Apply bandwidth expansion */
     140           0 :         chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
     141           0 :         silk_bwexpander_FLP( coefs, order, chirp );
     142             :     }
     143           0 :     silk_assert( 0 );
     144             : }
     145             : 
     146             : /* Compute noise shaping coefficients and initial gain values */
     147           0 : void silk_noise_shape_analysis_FLP(
     148             :     silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
     149             :     silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
     150             :     const silk_float                *pitch_res,                         /* I    LPC residual from pitch analysis            */
     151             :     const silk_float                *x                                  /* I    Input signal [frame_length + la_shape]      */
     152             : )
     153             : {
     154           0 :     silk_shape_state_FLP *psShapeSt = &psEnc->sShape;
     155             :     opus_int     k, nSamples, nSegs;
     156             :     silk_float   SNR_adj_dB, HarmShapeGain, Tilt;
     157             :     silk_float   nrg, log_energy, log_energy_prev, energy_variation;
     158             :     silk_float   BWExp, gain_mult, gain_add, strength, b, warping;
     159             :     silk_float   x_windowed[ SHAPE_LPC_WIN_MAX ];
     160             :     silk_float   auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];
     161             :     silk_float   rc[ MAX_SHAPE_LPC_ORDER + 1 ];
     162             :     const silk_float *x_ptr, *pitch_res_ptr;
     163             : 
     164             :     /* Point to start of first LPC analysis block */
     165           0 :     x_ptr = x - psEnc->sCmn.la_shape;
     166             : 
     167             :     /****************/
     168             :     /* GAIN CONTROL */
     169             :     /****************/
     170           0 :     SNR_adj_dB = psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f );
     171             : 
     172             :     /* Input quality is the average of the quality in the lowest two VAD bands */
     173           0 :     psEncCtrl->input_quality = 0.5f * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] + psEnc->sCmn.input_quality_bands_Q15[ 1 ] ) * ( 1.0f / 32768.0f );
     174             : 
     175             :     /* Coding quality level, between 0.0 and 1.0 */
     176           0 :     psEncCtrl->coding_quality = silk_sigmoid( 0.25f * ( SNR_adj_dB - 20.0f ) );
     177             : 
     178           0 :     if( psEnc->sCmn.useCBR == 0 ) {
     179             :         /* Reduce coding SNR during low speech activity */
     180           0 :         b = 1.0f - psEnc->sCmn.speech_activity_Q8 * ( 1.0f /  256.0f );
     181           0 :         SNR_adj_dB -= BG_SNR_DECR_dB * psEncCtrl->coding_quality * ( 0.5f + 0.5f * psEncCtrl->input_quality ) * b * b;
     182             :     }
     183             : 
     184           0 :     if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
     185             :         /* Reduce gains for periodic signals */
     186           0 :         SNR_adj_dB += HARM_SNR_INCR_dB * psEnc->LTPCorr;
     187             :     } else {
     188             :         /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */
     189           0 :         SNR_adj_dB += ( -0.4f * psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ) + 6.0f ) * ( 1.0f - psEncCtrl->input_quality );
     190             :     }
     191             : 
     192             :     /*************************/
     193             :     /* SPARSENESS PROCESSING */
     194             :     /*************************/
     195             :     /* Set quantizer offset */
     196           0 :     if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
     197             :         /* Initially set to 0; may be overruled in process_gains(..) */
     198           0 :         psEnc->sCmn.indices.quantOffsetType = 0;
     199             :     } else {
     200             :         /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
     201           0 :         nSamples = 2 * psEnc->sCmn.fs_kHz;
     202           0 :         energy_variation = 0.0f;
     203           0 :         log_energy_prev  = 0.0f;
     204           0 :         pitch_res_ptr = pitch_res;
     205           0 :         nSegs = silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2;
     206           0 :         for( k = 0; k < nSegs; k++ ) {
     207           0 :             nrg = ( silk_float )nSamples + ( silk_float )silk_energy_FLP( pitch_res_ptr, nSamples );
     208           0 :             log_energy = silk_log2( nrg );
     209           0 :             if( k > 0 ) {
     210           0 :                 energy_variation += silk_abs_float( log_energy - log_energy_prev );
     211             :             }
     212           0 :             log_energy_prev = log_energy;
     213           0 :             pitch_res_ptr += nSamples;
     214             :         }
     215             : 
     216             :         /* Set quantization offset depending on sparseness measure */
     217           0 :         if( energy_variation > ENERGY_VARIATION_THRESHOLD_QNT_OFFSET * (nSegs-1) ) {
     218           0 :             psEnc->sCmn.indices.quantOffsetType = 0;
     219             :         } else {
     220           0 :             psEnc->sCmn.indices.quantOffsetType = 1;
     221             :         }
     222             :     }
     223             : 
     224             :     /*******************************/
     225             :     /* Control bandwidth expansion */
     226             :     /*******************************/
     227             :     /* More BWE for signals with high prediction gain */
     228           0 :     strength = FIND_PITCH_WHITE_NOISE_FRACTION * psEncCtrl->predGain;           /* between 0.0 and 1.0 */
     229           0 :     BWExp = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength );
     230             : 
     231             :     /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
     232           0 :     warping = (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality;
     233             : 
     234             :     /********************************************/
     235             :     /* Compute noise shaping AR coefs and gains */
     236             :     /********************************************/
     237           0 :     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
     238             :         /* Apply window: sine slope followed by flat part followed by cosine slope */
     239             :         opus_int shift, slope_part, flat_part;
     240           0 :         flat_part = psEnc->sCmn.fs_kHz * 3;
     241           0 :         slope_part = ( psEnc->sCmn.shapeWinLength - flat_part ) / 2;
     242             : 
     243           0 :         silk_apply_sine_window_FLP( x_windowed, x_ptr, 1, slope_part );
     244           0 :         shift = slope_part;
     245           0 :         silk_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(silk_float) );
     246           0 :         shift += flat_part;
     247           0 :         silk_apply_sine_window_FLP( x_windowed + shift, x_ptr + shift, 2, slope_part );
     248             : 
     249             :         /* Update pointer: next LPC analysis block */
     250           0 :         x_ptr += psEnc->sCmn.subfr_length;
     251             : 
     252           0 :         if( psEnc->sCmn.warping_Q16 > 0 ) {
     253             :             /* Calculate warped auto correlation */
     254           0 :             silk_warped_autocorrelation_FLP( auto_corr, x_windowed, warping,
     255             :                 psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
     256             :         } else {
     257             :             /* Calculate regular auto correlation */
     258           0 :             silk_autocorrelation_FLP( auto_corr, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1 );
     259             :         }
     260             : 
     261             :         /* Add white noise, as a fraction of energy */
     262           0 :         auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION + 1.0f;
     263             : 
     264             :         /* Convert correlations to prediction coefficients, and compute residual energy */
     265           0 :         nrg = silk_schur_FLP( rc, auto_corr, psEnc->sCmn.shapingLPCOrder );
     266           0 :         silk_k2a_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], rc, psEnc->sCmn.shapingLPCOrder );
     267           0 :         psEncCtrl->Gains[ k ] = ( silk_float )sqrt( nrg );
     268             : 
     269           0 :         if( psEnc->sCmn.warping_Q16 > 0 ) {
     270             :             /* Adjust gain for warping */
     271           0 :             psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );
     272             :         }
     273             : 
     274             :         /* Bandwidth expansion for synthesis filter shaping */
     275           0 :         silk_bwexpander_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp );
     276             : 
     277           0 :         if( psEnc->sCmn.warping_Q16 > 0 ) {
     278             :             /* Convert to monic warped prediction coefficients and limit absolute values */
     279           0 :             warped_true2monic_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, 3.999f, psEnc->sCmn.shapingLPCOrder );
     280             :         } else {
     281             :             /* Limit absolute values */
     282           0 :             limit_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], 3.999f, psEnc->sCmn.shapingLPCOrder );
     283             :         }
     284             :     }
     285             : 
     286             :     /*****************/
     287             :     /* Gain tweaking */
     288             :     /*****************/
     289             :     /* Increase gains during low speech activity */
     290           0 :     gain_mult = (silk_float)pow( 2.0f, -0.16f * SNR_adj_dB );
     291           0 :     gain_add  = (silk_float)pow( 2.0f,  0.16f * MIN_QGAIN_DB );
     292           0 :     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
     293           0 :         psEncCtrl->Gains[ k ] *= gain_mult;
     294           0 :         psEncCtrl->Gains[ k ] += gain_add;
     295             :     }
     296             : 
     297             :     /************************************************/
     298             :     /* Control low-frequency shaping and noise tilt */
     299             :     /************************************************/
     300             :     /* Less low frequency shaping for noisy inputs */
     301           0 :     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 ) );
     302           0 :     strength *= psEnc->sCmn.speech_activity_Q8 * ( 1.0f /  256.0f );
     303           0 :     if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
     304             :         /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */
     305             :         /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/
     306           0 :         for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
     307           0 :             b = 0.2f / psEnc->sCmn.fs_kHz + 3.0f / psEncCtrl->pitchL[ k ];
     308           0 :             psEncCtrl->LF_MA_shp[ k ] = -1.0f + b;
     309           0 :             psEncCtrl->LF_AR_shp[ k ] =  1.0f - b - b * strength;
     310             :         }
     311           0 :         Tilt = - HP_NOISE_COEF -
     312           0 :             (1 - HP_NOISE_COEF) * HARM_HP_NOISE_COEF * psEnc->sCmn.speech_activity_Q8 * ( 1.0f /  256.0f );
     313             :     } else {
     314           0 :         b = 1.3f / psEnc->sCmn.fs_kHz;
     315           0 :         psEncCtrl->LF_MA_shp[ 0 ] = -1.0f + b;
     316           0 :         psEncCtrl->LF_AR_shp[ 0 ] =  1.0f - b - b * strength * 0.6f;
     317           0 :         for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) {
     318           0 :             psEncCtrl->LF_MA_shp[ k ] = psEncCtrl->LF_MA_shp[ 0 ];
     319           0 :             psEncCtrl->LF_AR_shp[ k ] = psEncCtrl->LF_AR_shp[ 0 ];
     320             :         }
     321           0 :         Tilt = -HP_NOISE_COEF;
     322             :     }
     323             : 
     324             :     /****************************/
     325             :     /* HARMONIC SHAPING CONTROL */
     326             :     /****************************/
     327           0 :     if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
     328             :         /* Harmonic noise shaping */
     329           0 :         HarmShapeGain = HARMONIC_SHAPING;
     330             : 
     331             :         /* More harmonic noise shaping for high bitrates or noisy input */
     332           0 :         HarmShapeGain += HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING *
     333           0 :             ( 1.0f - ( 1.0f - psEncCtrl->coding_quality ) * psEncCtrl->input_quality );
     334             : 
     335             :         /* Less harmonic noise shaping for less periodic signals */
     336           0 :         HarmShapeGain *= ( silk_float )sqrt( psEnc->LTPCorr );
     337             :     } else {
     338           0 :         HarmShapeGain = 0.0f;
     339             :     }
     340             : 
     341             :     /*************************/
     342             :     /* Smooth over subframes */
     343             :     /*************************/
     344           0 :     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
     345           0 :         psShapeSt->HarmShapeGain_smth += SUBFR_SMTH_COEF * ( HarmShapeGain - psShapeSt->HarmShapeGain_smth );
     346           0 :         psEncCtrl->HarmShapeGain[ k ]  = psShapeSt->HarmShapeGain_smth;
     347           0 :         psShapeSt->Tilt_smth          += SUBFR_SMTH_COEF * ( Tilt - psShapeSt->Tilt_smth );
     348           0 :         psEncCtrl->Tilt[ k ]           = psShapeSt->Tilt_smth;
     349             :     }
     350           0 : }

Generated by: LCOV version 1.13