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)(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