|  | /* | 
|  | *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | /****************************************************************** | 
|  |  | 
|  | iLBC Speech Coder ANSI-C Source Code | 
|  |  | 
|  | WebRtcIlbcfix_Smooth.c | 
|  |  | 
|  | ******************************************************************/ | 
|  |  | 
|  | #include "defines.h" | 
|  | #include "constants.h" | 
|  | #include "smooth_out_data.h" | 
|  |  | 
|  | /*----------------------------------------------------------------* | 
|  | * find the smoothed output data | 
|  | *---------------------------------------------------------------*/ | 
|  |  | 
|  | void WebRtcIlbcfix_Smooth( | 
|  | int16_t *odata,   /* (o) smoothed output */ | 
|  | int16_t *current,  /* (i) the un enhanced residual for | 
|  | this block */ | 
|  | int16_t *surround  /* (i) The approximation from the | 
|  | surrounding sequences */ | 
|  | ) { | 
|  | int16_t maxtot, scale, scale1, scale2; | 
|  | int16_t A, B, C, denomW16; | 
|  | int32_t B_W32, denom, num; | 
|  | int32_t errs; | 
|  | int32_t w00,w10,w11, endiff, crit; | 
|  | int32_t w00prim, w10prim, w11_div_w00; | 
|  | int16_t w11prim; | 
|  | int16_t bitsw00, bitsw10, bitsw11; | 
|  | int32_t w11w00, w10w10, w00w00; | 
|  | int16_t max1, max2; | 
|  |  | 
|  | /* compute some inner products (ensure no overflow by first calculating proper scale factor) */ | 
|  |  | 
|  | w00 = w10 = w11 = 0; | 
|  |  | 
|  | max1=WebRtcSpl_MaxAbsValueW16(current, ENH_BLOCKL); | 
|  | max2=WebRtcSpl_MaxAbsValueW16(surround, ENH_BLOCKL); | 
|  | maxtot=WEBRTC_SPL_MAX(max1, max2); | 
|  |  | 
|  | scale=WebRtcSpl_GetSizeInBits(maxtot); | 
|  | scale = (int16_t)WEBRTC_SPL_MUL_16_16(2,scale)-26; | 
|  | scale=WEBRTC_SPL_MAX(0, scale); | 
|  |  | 
|  | w00=WebRtcSpl_DotProductWithScale(current,current,ENH_BLOCKL,scale); | 
|  | w11=WebRtcSpl_DotProductWithScale(surround,surround,ENH_BLOCKL,scale); | 
|  | w10=WebRtcSpl_DotProductWithScale(surround,current,ENH_BLOCKL,scale); | 
|  |  | 
|  | if (w00<0) w00 = WEBRTC_SPL_WORD32_MAX; | 
|  | if (w11<0) w11 = WEBRTC_SPL_WORD32_MAX; | 
|  |  | 
|  | /* Rescale w00 and w11 to w00prim and w11prim, so that w00prim/w11prim | 
|  | is in Q16 */ | 
|  |  | 
|  | bitsw00 = WebRtcSpl_GetSizeInBits(w00); | 
|  | bitsw11 = WebRtcSpl_GetSizeInBits(w11); | 
|  | bitsw10 = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(w10)); | 
|  | scale1 = 31 - bitsw00; | 
|  | scale2 = 15 - bitsw11; | 
|  |  | 
|  | if (scale2>(scale1-16)) { | 
|  | scale2 = scale1 - 16; | 
|  | } else { | 
|  | scale1 = scale2 + 16; | 
|  | } | 
|  |  | 
|  | w00prim = WEBRTC_SPL_LSHIFT_W32(w00, scale1); | 
|  | w11prim = (int16_t) WEBRTC_SPL_SHIFT_W32(w11, scale2); | 
|  |  | 
|  | /* Perform C = sqrt(w11/w00) (C is in Q11 since (16+6)/2=11) */ | 
|  | if (w11prim>64) { | 
|  | endiff = WEBRTC_SPL_LSHIFT_W32( | 
|  | (int32_t)WebRtcSpl_DivW32W16(w00prim, w11prim), 6); | 
|  | C = (int16_t)WebRtcSpl_SqrtFloor(endiff); /* C is in Q11 */ | 
|  | } else { | 
|  | C = 1; | 
|  | } | 
|  |  | 
|  | /* first try enhancement without power-constraint */ | 
|  |  | 
|  | errs = WebRtcIlbcfix_Smooth_odata(odata, current, surround, C); | 
|  |  | 
|  |  | 
|  |  | 
|  | /* if constraint violated by first try, add constraint */ | 
|  |  | 
|  | if ( (6-scale+scale1) > 31) { | 
|  | crit=0; | 
|  | } else { | 
|  | /* crit = 0.05 * w00 (Result in Q-6) */ | 
|  | crit = WEBRTC_SPL_SHIFT_W32( | 
|  | WEBRTC_SPL_MUL(ENH_A0, w00prim >> 14), | 
|  | -(6-scale+scale1)); | 
|  | } | 
|  |  | 
|  | if (errs > crit) { | 
|  |  | 
|  | if( w00 < 1) { | 
|  | w00=1; | 
|  | } | 
|  |  | 
|  | /* Calculate w11*w00, w10*w10 and w00*w00 in the same Q domain */ | 
|  |  | 
|  | scale1 = bitsw00-15; | 
|  | scale2 = bitsw11-15; | 
|  |  | 
|  | if (scale2>scale1) { | 
|  | scale = scale2; | 
|  | } else { | 
|  | scale = scale1; | 
|  | } | 
|  |  | 
|  | w11w00 = WEBRTC_SPL_MUL_16_16( | 
|  | (int16_t)WEBRTC_SPL_SHIFT_W32(w11, -scale), | 
|  | (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale)); | 
|  |  | 
|  | w10w10 = WEBRTC_SPL_MUL_16_16( | 
|  | (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale), | 
|  | (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale)); | 
|  |  | 
|  | w00w00 = WEBRTC_SPL_MUL_16_16( | 
|  | (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale), | 
|  | (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale)); | 
|  |  | 
|  | /* Calculate (w11*w00-w10*w10)/(w00*w00) in Q16 */ | 
|  | if (w00w00>65536) { | 
|  | endiff = (w11w00-w10w10); | 
|  | endiff = WEBRTC_SPL_MAX(0, endiff); | 
|  | /* denom is in Q16 */ | 
|  | denom = WebRtcSpl_DivW32W16(endiff, (int16_t)(w00w00 >> 16)); | 
|  | } else { | 
|  | denom = 65536; | 
|  | } | 
|  |  | 
|  | if( denom > 7){ /* eliminates numerical problems | 
|  | for if smooth */ | 
|  |  | 
|  | scale=WebRtcSpl_GetSizeInBits(denom)-15; | 
|  |  | 
|  | if (scale>0) { | 
|  | /* denomW16 is in Q(16+scale) */ | 
|  | denomW16 = (int16_t)(denom >> scale); | 
|  |  | 
|  | /* num in Q(34-scale) */ | 
|  | num = ENH_A0_MINUS_A0A0DIV4 >> scale; | 
|  | } else { | 
|  | /* denomW16 is in Q16 */ | 
|  | denomW16=(int16_t)denom; | 
|  |  | 
|  | /* num in Q34 */ | 
|  | num=ENH_A0_MINUS_A0A0DIV4; | 
|  | } | 
|  |  | 
|  | /* A sqrt( (ENH_A0-(ENH_A0^2)/4)*(w00*w00)/(w11*w00 + w10*w10) ) in Q9 */ | 
|  | A = (int16_t)WebRtcSpl_SqrtFloor(WebRtcSpl_DivW32W16(num, denomW16)); | 
|  |  | 
|  | /* B_W32 is in Q30 ( B = 1 - ENH_A0/2 - A * w10/w00 ) */ | 
|  | scale1 = 31-bitsw10; | 
|  | scale2 = 21-scale1; | 
|  | w10prim = WEBRTC_SPL_LSHIFT_W32(w10, scale1); | 
|  | w00prim = WEBRTC_SPL_SHIFT_W32(w00, -scale2); | 
|  | scale = bitsw00-scale2-15; | 
|  |  | 
|  | if (scale>0) { | 
|  | w10prim >>= scale; | 
|  | w00prim >>= scale; | 
|  | } | 
|  |  | 
|  | if ((w00prim>0)&&(w10prim>0)) { | 
|  | w11_div_w00=WebRtcSpl_DivW32W16(w10prim, (int16_t)w00prim); | 
|  |  | 
|  | if (WebRtcSpl_GetSizeInBits(w11_div_w00)+WebRtcSpl_GetSizeInBits(A)>31) { | 
|  | B_W32 = 0; | 
|  | } else { | 
|  | B_W32 = (int32_t)1073741824 - (int32_t)ENH_A0DIV2 - | 
|  | WEBRTC_SPL_MUL(A, w11_div_w00); | 
|  | } | 
|  | B = (int16_t)(B_W32 >> 16);  /* B in Q14. */ | 
|  | } else { | 
|  | /* No smoothing */ | 
|  | A = 0; | 
|  | B = 16384; /* 1 in Q14 */ | 
|  | } | 
|  | } | 
|  | else{ /* essentially no difference between cycles; | 
|  | smoothing not needed */ | 
|  |  | 
|  | A = 0; | 
|  | B = 16384; /* 1 in Q14 */ | 
|  | } | 
|  |  | 
|  | /* create smoothed sequence */ | 
|  |  | 
|  | WebRtcSpl_ScaleAndAddVectors(surround, A, 9, | 
|  | current, B, 14, | 
|  | odata, ENH_BLOCKL); | 
|  | } | 
|  | return; | 
|  | } |