xref: /aosp_15_r20/external/webrtc/modules/audio_coding/codecs/ilbc/smooth.c (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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 "modules/audio_coding/codecs/ilbc/smooth.h"
20 
21 #include "modules/audio_coding/codecs/ilbc/constants.h"
22 #include "modules/audio_coding/codecs/ilbc/defines.h"
23 #include "modules/audio_coding/codecs/ilbc/smooth_out_data.h"
24 
25 /*----------------------------------------------------------------*
26  * find the smoothed output data
27  *---------------------------------------------------------------*/
28 
WebRtcIlbcfix_Smooth(int16_t * odata,int16_t * current,int16_t * surround)29 void WebRtcIlbcfix_Smooth(
30     int16_t *odata,   /* (o) smoothed output */
31     int16_t *current,  /* (i) the un enhanced residual for
32                                 this block */
33     int16_t *surround  /* (i) The approximation from the
34                                 surrounding sequences */
35                           ) {
36   int16_t scale, scale1, scale2;
37   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;
45   uint32_t max1, max2, max12;
46 
47   /* compute some inner products (ensure no overflow by first calculating proper scale factor) */
48 
49   w00 = w10 = w11 = 0;
50 
51   // 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);
60   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 
84   w00prim = w00 << scale1;
85   w11prim = (int16_t) WEBRTC_SPL_SHIFT_W32(w11, scale2);
86 
87   /* Perform C = sqrt(w11/w00) (C is in Q11 since (16+6)/2=11) */
88   if (w11prim>64) {
89     endiff = WebRtcSpl_DivW32W16(w00prim, w11prim) << 6;
90     C = (int16_t)WebRtcSpl_SqrtFloor(endiff); /* C is in Q11 */
91   } 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(
108         WEBRTC_SPL_MUL(ENH_A0, w00prim >> 14),
109         -(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 
129     w11w00 = (int16_t)WEBRTC_SPL_SHIFT_W32(w11, -scale) *
130         (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale);
131 
132     w10w10 = (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale) *
133         (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale);
134 
135     w00w00 = (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale) *
136         (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale);
137 
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 */
143       denom = WebRtcSpl_DivW32W16(endiff, (int16_t)(w00w00 >> 16));
144     } 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) */
155         denomW16 = (int16_t)(denom >> scale);
156 
157         /* num in Q(34-scale) */
158         num = ENH_A0_MINUS_A0A0DIV4 >> scale;
159       } else {
160         /* denomW16 is in Q16 */
161         denomW16=(int16_t)denom;
162 
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 */
168       A = (int16_t)WebRtcSpl_SqrtFloor(WebRtcSpl_DivW32W16(num, denomW16));
169 
170       /* B_W32 is in Q30 ( B = 1 - ENH_A0/2 - A * w10/w00 ) */
171       scale1 = 31-bitsw10;
172       scale2 = 21-scale1;
173       w10prim = w10 == 0 ? 0 : w10 * (1 << scale1);
174       w00prim = WEBRTC_SPL_SHIFT_W32(w00, -scale2);
175       scale = bitsw00-scale2-15;
176 
177       if (scale>0) {
178         w10prim >>= scale;
179         w00prim >>= scale;
180       }
181 
182       if ((w00prim>0)&&(w10prim>0)) {
183         w11_div_w00=WebRtcSpl_DivW32W16(w10prim, (int16_t)w00prim);
184 
185         if (WebRtcSpl_GetSizeInBits(w11_div_w00)+WebRtcSpl_GetSizeInBits(A)>31) {
186           B_W32 = 0;
187         } else {
188           B_W32 = (int32_t)1073741824 - (int32_t)ENH_A0DIV2 -
189               WEBRTC_SPL_MUL(A, w11_div_w00);
190         }
191         B = (int16_t)(B_W32 >> 16);  /* B in Q14. */
192       } 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 }
213