blob: 631b2f432ab1c034a240bc5cf28725dfd91be735 [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
Timothy Gu31117832020-12-18 22:25:57 -080019#include "modules/audio_coding/codecs/ilbc/smooth.h"
20
Mirko Bonadei06c2aa92018-02-01 15:11:41 +010021#include "modules/audio_coding/codecs/ilbc/constants.h"
Timothy Gu31117832020-12-18 22:25:57 -080022#include "modules/audio_coding/codecs/ilbc/defines.h"
Mirko Bonadei06c2aa92018-02-01 15:11:41 +010023#include "modules/audio_coding/codecs/ilbc/smooth_out_data.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000024
25/*----------------------------------------------------------------*
26 * find the smoothed output data
27 *---------------------------------------------------------------*/
28
29void WebRtcIlbcfix_Smooth(
pbos@webrtc.org0946a562013-04-09 00:28:06 +000030 int16_t *odata, /* (o) smoothed output */
31 int16_t *current, /* (i) the un enhanced residual for
niklase@google.com470e71d2011-07-07 08:21:25 +000032 this block */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000033 int16_t *surround /* (i) The approximation from the
niklase@google.com470e71d2011-07-07 08:21:25 +000034 surrounding sequences */
35 ) {
kwiberga1074022016-06-08 05:24:40 -070036 int16_t scale, scale1, scale2;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000037 int16_t A, B, C, denomW16;
38 int32_t B_W32, denom, num;
39 int32_t errs;
40 int32_t w00,w10,w11, endiff, crit;
41 int32_t w00prim, w10prim, w11_div_w00;
42 int16_t w11prim;
43 int16_t bitsw00, bitsw10, bitsw11;
44 int32_t w11w00, w10w10, w00w00;
kwiberga1074022016-06-08 05:24:40 -070045 uint32_t max1, max2, max12;
niklase@google.com470e71d2011-07-07 08:21:25 +000046
47 /* compute some inner products (ensure no overflow by first calculating proper scale factor) */
48
49 w00 = w10 = w11 = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000050
kwiberga1074022016-06-08 05:24:40 -070051 // Calculate a right shift that will let us sum ENH_BLOCKL pairwise products
52 // of values from the two sequences without overflowing an int32_t. (The +1
53 // in max1 and max2 are because WebRtcSpl_MaxAbsValueW16 will return 2**15 -
54 // 1 if the input array contains -2**15.)
55 max1 = WebRtcSpl_MaxAbsValueW16(current, ENH_BLOCKL) + 1;
56 max2 = WebRtcSpl_MaxAbsValueW16(surround, ENH_BLOCKL) + 1;
57 max12 = WEBRTC_SPL_MAX(max1, max2);
58 scale = (64 - 31) -
59 WebRtcSpl_CountLeadingZeros64((max12 * max12) * (uint64_t)ENH_BLOCKL);
niklase@google.com470e71d2011-07-07 08:21:25 +000060 scale=WEBRTC_SPL_MAX(0, scale);
61
62 w00=WebRtcSpl_DotProductWithScale(current,current,ENH_BLOCKL,scale);
63 w11=WebRtcSpl_DotProductWithScale(surround,surround,ENH_BLOCKL,scale);
64 w10=WebRtcSpl_DotProductWithScale(surround,current,ENH_BLOCKL,scale);
65
66 if (w00<0) w00 = WEBRTC_SPL_WORD32_MAX;
67 if (w11<0) w11 = WEBRTC_SPL_WORD32_MAX;
68
69 /* Rescale w00 and w11 to w00prim and w11prim, so that w00prim/w11prim
70 is in Q16 */
71
72 bitsw00 = WebRtcSpl_GetSizeInBits(w00);
73 bitsw11 = WebRtcSpl_GetSizeInBits(w11);
74 bitsw10 = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(w10));
75 scale1 = 31 - bitsw00;
76 scale2 = 15 - bitsw11;
77
78 if (scale2>(scale1-16)) {
79 scale2 = scale1 - 16;
80 } else {
81 scale1 = scale2 + 16;
82 }
83
bjornv@webrtc.org4ab23d02015-03-20 06:01:06 +000084 w00prim = w00 << scale1;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000085 w11prim = (int16_t) WEBRTC_SPL_SHIFT_W32(w11, scale2);
niklase@google.com470e71d2011-07-07 08:21:25 +000086
87 /* Perform C = sqrt(w11/w00) (C is in Q11 since (16+6)/2=11) */
88 if (w11prim>64) {
bjornv@webrtc.org4ab23d02015-03-20 06:01:06 +000089 endiff = WebRtcSpl_DivW32W16(w00prim, w11prim) << 6;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000090 C = (int16_t)WebRtcSpl_SqrtFloor(endiff); /* C is in Q11 */
niklase@google.com470e71d2011-07-07 08:21:25 +000091 } else {
92 C = 1;
93 }
94
95 /* first try enhancement without power-constraint */
96
97 errs = WebRtcIlbcfix_Smooth_odata(odata, current, surround, C);
98
99
100
101 /* if constraint violated by first try, add constraint */
102
103 if ( (6-scale+scale1) > 31) {
104 crit=0;
105 } else {
106 /* crit = 0.05 * w00 (Result in Q-6) */
107 crit = WEBRTC_SPL_SHIFT_W32(
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +0000108 WEBRTC_SPL_MUL(ENH_A0, w00prim >> 14),
niklase@google.com470e71d2011-07-07 08:21:25 +0000109 -(6-scale+scale1));
110 }
111
112 if (errs > crit) {
113
114 if( w00 < 1) {
115 w00=1;
116 }
117
118 /* Calculate w11*w00, w10*w10 and w00*w00 in the same Q domain */
119
120 scale1 = bitsw00-15;
121 scale2 = bitsw11-15;
122
123 if (scale2>scale1) {
124 scale = scale2;
125 } else {
126 scale = scale1;
127 }
128
bjornv@webrtc.orgba97ea62015-02-13 09:51:40 +0000129 w11w00 = (int16_t)WEBRTC_SPL_SHIFT_W32(w11, -scale) *
130 (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale);
niklase@google.com470e71d2011-07-07 08:21:25 +0000131
bjornv@webrtc.orgba97ea62015-02-13 09:51:40 +0000132 w10w10 = (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale) *
133 (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale);
niklase@google.com470e71d2011-07-07 08:21:25 +0000134
bjornv@webrtc.orgba97ea62015-02-13 09:51:40 +0000135 w00w00 = (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale) *
136 (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale);
niklase@google.com470e71d2011-07-07 08:21:25 +0000137
138 /* Calculate (w11*w00-w10*w10)/(w00*w00) in Q16 */
139 if (w00w00>65536) {
140 endiff = (w11w00-w10w10);
141 endiff = WEBRTC_SPL_MAX(0, endiff);
142 /* denom is in Q16 */
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +0000143 denom = WebRtcSpl_DivW32W16(endiff, (int16_t)(w00w00 >> 16));
niklase@google.com470e71d2011-07-07 08:21:25 +0000144 } else {
145 denom = 65536;
146 }
147
148 if( denom > 7){ /* eliminates numerical problems
149 for if smooth */
150
151 scale=WebRtcSpl_GetSizeInBits(denom)-15;
152
153 if (scale>0) {
154 /* denomW16 is in Q(16+scale) */
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +0000155 denomW16 = (int16_t)(denom >> scale);
niklase@google.com470e71d2011-07-07 08:21:25 +0000156
157 /* num in Q(34-scale) */
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +0000158 num = ENH_A0_MINUS_A0A0DIV4 >> scale;
niklase@google.com470e71d2011-07-07 08:21:25 +0000159 } else {
160 /* denomW16 is in Q16 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000161 denomW16=(int16_t)denom;
niklase@google.com470e71d2011-07-07 08:21:25 +0000162
163 /* num in Q34 */
164 num=ENH_A0_MINUS_A0A0DIV4;
165 }
166
167 /* A sqrt( (ENH_A0-(ENH_A0^2)/4)*(w00*w00)/(w11*w00 + w10*w10) ) in Q9 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000168 A = (int16_t)WebRtcSpl_SqrtFloor(WebRtcSpl_DivW32W16(num, denomW16));
niklase@google.com470e71d2011-07-07 08:21:25 +0000169
170 /* B_W32 is in Q30 ( B = 1 - ENH_A0/2 - A * w10/w00 ) */
171 scale1 = 31-bitsw10;
172 scale2 = 21-scale1;
kwiberg7f82fc92016-08-22 07:43:42 -0700173 w10prim = w10 == 0 ? 0 : w10 * (1 << scale1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000174 w00prim = WEBRTC_SPL_SHIFT_W32(w00, -scale2);
175 scale = bitsw00-scale2-15;
176
177 if (scale>0) {
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +0000178 w10prim >>= scale;
179 w00prim >>= scale;
niklase@google.com470e71d2011-07-07 08:21:25 +0000180 }
181
182 if ((w00prim>0)&&(w10prim>0)) {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000183 w11_div_w00=WebRtcSpl_DivW32W16(w10prim, (int16_t)w00prim);
niklase@google.com470e71d2011-07-07 08:21:25 +0000184
185 if (WebRtcSpl_GetSizeInBits(w11_div_w00)+WebRtcSpl_GetSizeInBits(A)>31) {
186 B_W32 = 0;
187 } else {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000188 B_W32 = (int32_t)1073741824 - (int32_t)ENH_A0DIV2 -
niklase@google.com470e71d2011-07-07 08:21:25 +0000189 WEBRTC_SPL_MUL(A, w11_div_w00);
190 }
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +0000191 B = (int16_t)(B_W32 >> 16); /* B in Q14. */
niklase@google.com470e71d2011-07-07 08:21:25 +0000192 } else {
193 /* No smoothing */
194 A = 0;
195 B = 16384; /* 1 in Q14 */
196 }
197 }
198 else{ /* essentially no difference between cycles;
199 smoothing not needed */
200
201 A = 0;
202 B = 16384; /* 1 in Q14 */
203 }
204
205 /* create smoothed sequence */
206
207 WebRtcSpl_ScaleAndAddVectors(surround, A, 9,
208 current, B, 14,
209 odata, ENH_BLOCKL);
210 }
211 return;
212}