blob: 3d59c521d0628863301e74aed776fa2479090284 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
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(
pbos@webrtc.org0946a562013-04-09 00:28:06 +000028 int16_t *odata, /* (o) smoothed output */
29 int16_t *current, /* (i) the un enhanced residual for
niklase@google.com470e71d2011-07-07 08:21:25 +000030 this block */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000031 int16_t *surround /* (i) The approximation from the
niklase@google.com470e71d2011-07-07 08:21:25 +000032 surrounding sequences */
33 ) {
pbos@webrtc.org0946a562013-04-09 00:28:06 +000034 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;
niklase@google.com470e71d2011-07-07 08:21:25 +000044
45 /* compute some inner products (ensure no overflow by first calculating proper scale factor) */
46
47 w00 = w10 = w11 = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000048
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);
pbos@webrtc.org0946a562013-04-09 00:28:06 +000054 scale = (int16_t)WEBRTC_SPL_MUL_16_16(2,scale)-26;
niklase@google.com470e71d2011-07-07 08:21:25 +000055 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);
pbos@webrtc.org0946a562013-04-09 00:28:06 +000080 w11prim = (int16_t) WEBRTC_SPL_SHIFT_W32(w11, scale2);
niklase@google.com470e71d2011-07-07 08:21:25 +000081
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(
pbos@webrtc.org0946a562013-04-09 00:28:06 +000085 (int32_t)WebRtcSpl_DivW32W16(w00prim, w11prim), 6);
86 C = (int16_t)WebRtcSpl_SqrtFloor(endiff); /* C is in Q11 */
niklase@google.com470e71d2011-07-07 08:21:25 +000087 } 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(
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +0000104 WEBRTC_SPL_MUL(ENH_A0, w00prim >> 14),
niklase@google.com470e71d2011-07-07 08:21:25 +0000105 -(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(
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000126 (int16_t)WEBRTC_SPL_SHIFT_W32(w11, -scale),
127 (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale));
niklase@google.com470e71d2011-07-07 08:21:25 +0000128
129 w10w10 = WEBRTC_SPL_MUL_16_16(
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000130 (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale),
131 (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale));
niklase@google.com470e71d2011-07-07 08:21:25 +0000132
133 w00w00 = WEBRTC_SPL_MUL_16_16(
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000134 (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale),
135 (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale));
niklase@google.com470e71d2011-07-07 08:21:25 +0000136
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 */
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +0000142 denom = WebRtcSpl_DivW32W16(endiff, (int16_t)(w00w00 >> 16));
niklase@google.com470e71d2011-07-07 08:21:25 +0000143 } 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) */
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +0000154 denomW16 = (int16_t)(denom >> scale);
niklase@google.com470e71d2011-07-07 08:21:25 +0000155
156 /* num in Q(34-scale) */
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +0000157 num = ENH_A0_MINUS_A0A0DIV4 >> scale;
niklase@google.com470e71d2011-07-07 08:21:25 +0000158 } else {
159 /* denomW16 is in Q16 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000160 denomW16=(int16_t)denom;
niklase@google.com470e71d2011-07-07 08:21:25 +0000161
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 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000167 A = (int16_t)WebRtcSpl_SqrtFloor(WebRtcSpl_DivW32W16(num, denomW16));
niklase@google.com470e71d2011-07-07 08:21:25 +0000168
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) {
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +0000177 w10prim >>= scale;
178 w00prim >>= scale;
niklase@google.com470e71d2011-07-07 08:21:25 +0000179 }
180
181 if ((w00prim>0)&&(w10prim>0)) {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000182 w11_div_w00=WebRtcSpl_DivW32W16(w10prim, (int16_t)w00prim);
niklase@google.com470e71d2011-07-07 08:21:25 +0000183
184 if (WebRtcSpl_GetSizeInBits(w11_div_w00)+WebRtcSpl_GetSizeInBits(A)>31) {
185 B_W32 = 0;
186 } else {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000187 B_W32 = (int32_t)1073741824 - (int32_t)ENH_A0DIV2 -
niklase@google.com470e71d2011-07-07 08:21:25 +0000188 WEBRTC_SPL_MUL(A, w11_div_w00);
189 }
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +0000190 B = (int16_t)(B_W32 >> 16); /* B in Q14. */
niklase@google.com470e71d2011-07-07 08:21:25 +0000191 } 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}