1/* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11/****************************************************************** 12 13 iLBC Speech Coder ANSI-C Source Code 14 15 WebRtcIlbcfix_Smooth.c 16 17******************************************************************/ 18 19#include "defines.h" 20#include "constants.h" 21#include "smooth_out_data.h" 22 23/*----------------------------------------------------------------* 24 * find the smoothed output data 25 *---------------------------------------------------------------*/ 26 27void WebRtcIlbcfix_Smooth( 28 int16_t *odata, /* (o) smoothed output */ 29 int16_t *current, /* (i) the un enhanced residual for 30 this block */ 31 int16_t *surround /* (i) The approximation from the 32 surrounding sequences */ 33 ) { 34 int16_t maxtot, scale, scale1, scale2; 35 int16_t A, B, C, denomW16; 36 int32_t B_W32, denom, num; 37 int32_t errs; 38 int32_t w00,w10,w11, endiff, crit; 39 int32_t w00prim, w10prim, w11_div_w00; 40 int16_t w11prim; 41 int16_t bitsw00, bitsw10, bitsw11; 42 int32_t w11w00, w10w10, w00w00; 43 int16_t max1, max2; 44 45 /* compute some inner products (ensure no overflow by first calculating proper scale factor) */ 46 47 w00 = w10 = w11 = 0; 48 49 max1=WebRtcSpl_MaxAbsValueW16(current, ENH_BLOCKL); 50 max2=WebRtcSpl_MaxAbsValueW16(surround, ENH_BLOCKL); 51 maxtot=WEBRTC_SPL_MAX(max1, max2); 52 53 scale=WebRtcSpl_GetSizeInBits(maxtot); 54 scale = (int16_t)WEBRTC_SPL_MUL_16_16(2,scale)-26; 55 scale=WEBRTC_SPL_MAX(0, scale); 56 57 w00=WebRtcSpl_DotProductWithScale(current,current,ENH_BLOCKL,scale); 58 w11=WebRtcSpl_DotProductWithScale(surround,surround,ENH_BLOCKL,scale); 59 w10=WebRtcSpl_DotProductWithScale(surround,current,ENH_BLOCKL,scale); 60 61 if (w00<0) w00 = WEBRTC_SPL_WORD32_MAX; 62 if (w11<0) w11 = WEBRTC_SPL_WORD32_MAX; 63 64 /* Rescale w00 and w11 to w00prim and w11prim, so that w00prim/w11prim 65 is in Q16 */ 66 67 bitsw00 = WebRtcSpl_GetSizeInBits(w00); 68 bitsw11 = WebRtcSpl_GetSizeInBits(w11); 69 bitsw10 = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(w10)); 70 scale1 = 31 - bitsw00; 71 scale2 = 15 - bitsw11; 72 73 if (scale2>(scale1-16)) { 74 scale2 = scale1 - 16; 75 } else { 76 scale1 = scale2 + 16; 77 } 78 79 w00prim = WEBRTC_SPL_LSHIFT_W32(w00, scale1); 80 w11prim = (int16_t) WEBRTC_SPL_SHIFT_W32(w11, scale2); 81 82 /* Perform C = sqrt(w11/w00) (C is in Q11 since (16+6)/2=11) */ 83 if (w11prim>64) { 84 endiff = WEBRTC_SPL_LSHIFT_W32( 85 (int32_t)WebRtcSpl_DivW32W16(w00prim, w11prim), 6); 86 C = (int16_t)WebRtcSpl_SqrtFloor(endiff); /* C is in Q11 */ 87 } else { 88 C = 1; 89 } 90 91 /* first try enhancement without power-constraint */ 92 93 errs = WebRtcIlbcfix_Smooth_odata(odata, current, surround, C); 94 95 96 97 /* if constraint violated by first try, add constraint */ 98 99 if ( (6-scale+scale1) > 31) { 100 crit=0; 101 } else { 102 /* crit = 0.05 * w00 (Result in Q-6) */ 103 crit = WEBRTC_SPL_SHIFT_W32( 104 WEBRTC_SPL_MUL(ENH_A0, WEBRTC_SPL_RSHIFT_W32(w00prim, 14)), 105 -(6-scale+scale1)); 106 } 107 108 if (errs > crit) { 109 110 if( w00 < 1) { 111 w00=1; 112 } 113 114 /* Calculate w11*w00, w10*w10 and w00*w00 in the same Q domain */ 115 116 scale1 = bitsw00-15; 117 scale2 = bitsw11-15; 118 119 if (scale2>scale1) { 120 scale = scale2; 121 } else { 122 scale = scale1; 123 } 124 125 w11w00 = WEBRTC_SPL_MUL_16_16( 126 (int16_t)WEBRTC_SPL_SHIFT_W32(w11, -scale), 127 (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale)); 128 129 w10w10 = WEBRTC_SPL_MUL_16_16( 130 (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale), 131 (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale)); 132 133 w00w00 = WEBRTC_SPL_MUL_16_16( 134 (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale), 135 (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale)); 136 137 /* Calculate (w11*w00-w10*w10)/(w00*w00) in Q16 */ 138 if (w00w00>65536) { 139 endiff = (w11w00-w10w10); 140 endiff = WEBRTC_SPL_MAX(0, endiff); 141 /* denom is in Q16 */ 142 denom = WebRtcSpl_DivW32W16(endiff, (int16_t)WEBRTC_SPL_RSHIFT_W32(w00w00, 16)); 143 } else { 144 denom = 65536; 145 } 146 147 if( denom > 7){ /* eliminates numerical problems 148 for if smooth */ 149 150 scale=WebRtcSpl_GetSizeInBits(denom)-15; 151 152 if (scale>0) { 153 /* denomW16 is in Q(16+scale) */ 154 denomW16=(int16_t)WEBRTC_SPL_RSHIFT_W32(denom, scale); 155 156 /* num in Q(34-scale) */ 157 num=WEBRTC_SPL_RSHIFT_W32(ENH_A0_MINUS_A0A0DIV4, scale); 158 } else { 159 /* denomW16 is in Q16 */ 160 denomW16=(int16_t)denom; 161 162 /* num in Q34 */ 163 num=ENH_A0_MINUS_A0A0DIV4; 164 } 165 166 /* A sqrt( (ENH_A0-(ENH_A0^2)/4)*(w00*w00)/(w11*w00 + w10*w10) ) in Q9 */ 167 A = (int16_t)WebRtcSpl_SqrtFloor(WebRtcSpl_DivW32W16(num, denomW16)); 168 169 /* B_W32 is in Q30 ( B = 1 - ENH_A0/2 - A * w10/w00 ) */ 170 scale1 = 31-bitsw10; 171 scale2 = 21-scale1; 172 w10prim = WEBRTC_SPL_LSHIFT_W32(w10, scale1); 173 w00prim = WEBRTC_SPL_SHIFT_W32(w00, -scale2); 174 scale = bitsw00-scale2-15; 175 176 if (scale>0) { 177 w10prim=WEBRTC_SPL_RSHIFT_W32(w10prim, scale); 178 w00prim=WEBRTC_SPL_RSHIFT_W32(w00prim, scale); 179 } 180 181 if ((w00prim>0)&&(w10prim>0)) { 182 w11_div_w00=WebRtcSpl_DivW32W16(w10prim, (int16_t)w00prim); 183 184 if (WebRtcSpl_GetSizeInBits(w11_div_w00)+WebRtcSpl_GetSizeInBits(A)>31) { 185 B_W32 = 0; 186 } else { 187 B_W32 = (int32_t)1073741824 - (int32_t)ENH_A0DIV2 - 188 WEBRTC_SPL_MUL(A, w11_div_w00); 189 } 190 B = (int16_t)WEBRTC_SPL_RSHIFT_W32(B_W32, 16); /* B in Q14 */ 191 } else { 192 /* No smoothing */ 193 A = 0; 194 B = 16384; /* 1 in Q14 */ 195 } 196 } 197 else{ /* essentially no difference between cycles; 198 smoothing not needed */ 199 200 A = 0; 201 B = 16384; /* 1 in Q14 */ 202 } 203 204 /* create smoothed sequence */ 205 206 WebRtcSpl_ScaleAndAddVectors(surround, A, 9, 207 current, B, 14, 208 odata, ENH_BLOCKL); 209 } 210 return; 211} 212