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 
WebRtcIlbcfix_Smooth(int16_t * odata,int16_t * current,int16_t * surround)27 void 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)(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 = 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 = WebRtcSpl_DivW32W16(w00prim, w11prim) << 6;
85     C = (int16_t)WebRtcSpl_SqrtFloor(endiff); /* C is in Q11 */
86   } else {
87     C = 1;
88   }
89 
90   /* first try enhancement without power-constraint */
91 
92   errs = WebRtcIlbcfix_Smooth_odata(odata, current, surround, C);
93 
94 
95 
96   /* if constraint violated by first try, add constraint */
97 
98   if ( (6-scale+scale1) > 31) {
99     crit=0;
100   } else {
101     /* crit = 0.05 * w00 (Result in Q-6) */
102     crit = WEBRTC_SPL_SHIFT_W32(
103         WEBRTC_SPL_MUL(ENH_A0, w00prim >> 14),
104         -(6-scale+scale1));
105   }
106 
107   if (errs > crit) {
108 
109     if( w00 < 1) {
110       w00=1;
111     }
112 
113     /* Calculate w11*w00, w10*w10 and w00*w00 in the same Q domain */
114 
115     scale1 = bitsw00-15;
116     scale2 = bitsw11-15;
117 
118     if (scale2>scale1) {
119       scale = scale2;
120     } else {
121       scale = scale1;
122     }
123 
124     w11w00 = (int16_t)WEBRTC_SPL_SHIFT_W32(w11, -scale) *
125         (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale);
126 
127     w10w10 = (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale) *
128         (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale);
129 
130     w00w00 = (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale) *
131         (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale);
132 
133     /* Calculate (w11*w00-w10*w10)/(w00*w00) in Q16 */
134     if (w00w00>65536) {
135       endiff = (w11w00-w10w10);
136       endiff = WEBRTC_SPL_MAX(0, endiff);
137       /* denom is in Q16 */
138       denom = WebRtcSpl_DivW32W16(endiff, (int16_t)(w00w00 >> 16));
139     } else {
140       denom = 65536;
141     }
142 
143     if( denom > 7){ /* eliminates numerical problems
144                        for if smooth */
145 
146       scale=WebRtcSpl_GetSizeInBits(denom)-15;
147 
148       if (scale>0) {
149         /* denomW16 is in Q(16+scale) */
150         denomW16 = (int16_t)(denom >> scale);
151 
152         /* num in Q(34-scale) */
153         num = ENH_A0_MINUS_A0A0DIV4 >> scale;
154       } else {
155         /* denomW16 is in Q16 */
156         denomW16=(int16_t)denom;
157 
158         /* num in Q34 */
159         num=ENH_A0_MINUS_A0A0DIV4;
160       }
161 
162       /* A sqrt( (ENH_A0-(ENH_A0^2)/4)*(w00*w00)/(w11*w00 + w10*w10) ) in Q9 */
163       A = (int16_t)WebRtcSpl_SqrtFloor(WebRtcSpl_DivW32W16(num, denomW16));
164 
165       /* B_W32 is in Q30 ( B = 1 - ENH_A0/2 - A * w10/w00 ) */
166       scale1 = 31-bitsw10;
167       scale2 = 21-scale1;
168       w10prim = w10 << scale1;
169       w00prim = WEBRTC_SPL_SHIFT_W32(w00, -scale2);
170       scale = bitsw00-scale2-15;
171 
172       if (scale>0) {
173         w10prim >>= scale;
174         w00prim >>= scale;
175       }
176 
177       if ((w00prim>0)&&(w10prim>0)) {
178         w11_div_w00=WebRtcSpl_DivW32W16(w10prim, (int16_t)w00prim);
179 
180         if (WebRtcSpl_GetSizeInBits(w11_div_w00)+WebRtcSpl_GetSizeInBits(A)>31) {
181           B_W32 = 0;
182         } else {
183           B_W32 = (int32_t)1073741824 - (int32_t)ENH_A0DIV2 -
184               WEBRTC_SPL_MUL(A, w11_div_w00);
185         }
186         B = (int16_t)(B_W32 >> 16);  /* B in Q14. */
187       } else {
188         /* No smoothing */
189         A = 0;
190         B = 16384; /* 1 in Q14 */
191       }
192     }
193     else{ /* essentially no difference between cycles;
194              smoothing not needed */
195 
196       A = 0;
197       B = 16384; /* 1 in Q14 */
198     }
199 
200     /* create smoothed sequence */
201 
202     WebRtcSpl_ScaleAndAddVectors(surround, A, 9,
203                                 current, B, 14,
204                                 odata, ENH_BLOCKL);
205   }
206   return;
207 }
208