comparison libtwamr/agc.c @ 253:54f6bc41ed10

libtwamr: integrate a* modules
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 05 Apr 2024 06:08:15 +0000
parents
children 07f936338de1
comparison
equal deleted inserted replaced
252:57b4053559ff 253:54f6bc41ed10
1 /*
2 *****************************************************************************
3 *
4 * GSM AMR-NB speech codec R98 Version 7.6.0 December 12, 2001
5 * R99 Version 3.3.0
6 * REL-4 Version 4.1.0
7 *
8 *****************************************************************************
9 *
10 * File : agc.c
11 *
12 *****************************************************************************
13 */
14
15 /*
16 *****************************************************************************
17 * MODULE INCLUDE FILE AND VERSION ID
18 *****************************************************************************
19 */
20 #include "namespace.h"
21 #include "agc.h"
22 const char agc_id[] = "@(#)$Id $" agc_h;
23
24 /*
25 *****************************************************************************
26 * INCLUDE FILES
27 *****************************************************************************
28 */
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include "typedef.h"
32 #include "basic_op.h"
33 #include "no_count.h"
34 #include "cnst.h"
35 #include "inv_sqrt.h"
36
37 /*
38 *****************************************************************************
39 * LOCAL VARIABLES AND TABLES
40 *****************************************************************************
41 */
42
43 /*
44 *****************************************************************************
45 * LOCAL PROGRAM CODE
46 *****************************************************************************
47 */
48
49 static Word32 energy_old( /* o : return energy of signal */
50 Word16 in[], /* i : input signal (length l_trm) */
51 Word16 l_trm /* i : signal length */
52 )
53 {
54 Word32 s;
55 Word16 i, temp;
56
57 temp = shr (in[0], 2);
58 s = L_mult (temp, temp);
59
60 for (i = 1; i < l_trm; i++)
61 {
62 temp = shr (in[i], 2);
63 s = L_mac (s, temp, temp);
64 }
65
66 return s;
67 }
68
69 static Word32 energy_new( /* o : return energy of signal */
70 Word16 in[], /* i : input signal (length l_trm) */
71 Word16 l_trm /* i : signal length */
72 )
73 {
74 Word32 s;
75 Word16 i;
76 Flag ov_save;
77
78 ov_save = Overflow; move16 (); /* save overflow flag in case energy_old */
79 /* must be called */
80 s = L_mult(in[0], in[0]);
81 for (i = 1; i < l_trm; i++)
82 {
83 s = L_mac(s, in[i], in[i]);
84 }
85
86 /* check for overflow */
87 test ();
88 if (L_sub (s, MAX_32) == 0L)
89 {
90 Overflow = ov_save; move16 (); /* restore overflow flag */
91 s = energy_old (in, l_trm); move32 (); /* function result */
92 }
93 else
94 {
95 s = L_shr(s, 4);
96 }
97
98 return s;
99 }
100 /*
101 *****************************************************************************
102 * PUBLIC PROGRAM CODE
103 *****************************************************************************
104 */
105 /*
106 **************************************************************************
107 *
108 * Function : agc_init
109 * Purpose : Allocates memory for agc state and initializes
110 * state memory
111 *
112 **************************************************************************
113 */
114 int agc_init (agcState **state)
115 {
116 agcState* s;
117
118 if (state == (agcState **) NULL){
119 fprintf(stderr, "agc_init: invalid parameter\n");
120 return -1;
121 }
122 *state = NULL;
123
124 /* allocate memory */
125 if ((s= (agcState *) malloc(sizeof(agcState))) == NULL){
126 fprintf(stderr, "agc_init: can not malloc state structure\n");
127 return -1;
128 }
129
130 agc_reset(s);
131 *state = s;
132
133 return 0;
134 }
135
136 /*
137 **************************************************************************
138 *
139 * Function : agc_reset
140 * Purpose : Reset of agc (i.e. set state memory to 1.0)
141 *
142 **************************************************************************
143 */
144 int agc_reset (agcState *state)
145 {
146 if (state == (agcState *) NULL){
147 fprintf(stderr, "agc_reset: invalid parameter\n");
148 return -1;
149 }
150
151 state->past_gain = 4096; /* initial value of past_gain = 1.0 */
152
153 return 0;
154 }
155
156 /*
157 **************************************************************************
158 *
159 * Function : agc_exit
160 * Purpose : The memory used for state memory is freed
161 *
162 **************************************************************************
163 */
164 void agc_exit (agcState **state)
165 {
166 if (state == NULL || *state == NULL)
167 return;
168
169 /* deallocate memory */
170 free(*state);
171 *state = NULL;
172
173 return;
174 }
175
176 /*
177 **************************************************************************
178 *
179 * Function : agc
180 * Purpose : Scales the postfilter output on a subframe basis
181 *
182 **************************************************************************
183 */
184 int agc (
185 agcState *st, /* i/o : agc state */
186 Word16 *sig_in, /* i : postfilter input signal (l_trm) */
187 Word16 *sig_out, /* i/o : postfilter output signal (l_trm) */
188 Word16 agc_fac, /* i : AGC factor */
189 Word16 l_trm /* i : subframe size */
190 )
191 {
192 Word16 i, exp;
193 Word16 gain_in, gain_out, g0, gain;
194 Word32 s;
195
196 /* calculate gain_out with exponent */
197 s = energy_new(sig_out, l_trm); move32 (); /* function result */
198
199 test ();
200 if (s == 0)
201 {
202 st->past_gain = 0; move16 ();
203 return 0;
204 }
205 exp = sub (norm_l (s), 1);
206 gain_out = round (L_shl (s, exp));
207
208 /* calculate gain_in with exponent */
209 s = energy_new(sig_in, l_trm); move32 (); /* function result */
210
211 test ();
212 if (s == 0)
213 {
214 g0 = 0; move16 ();
215 }
216 else
217 {
218 i = norm_l (s);
219 gain_in = round (L_shl (s, i));
220 exp = sub (exp, i);
221
222 /*---------------------------------------------------*
223 * g0 = (1-agc_fac) * sqrt(gain_in/gain_out); *
224 *---------------------------------------------------*/
225
226 s = L_deposit_l (div_s (gain_out, gain_in));
227 s = L_shl (s, 7); /* s = gain_out / gain_in */
228 s = L_shr (s, exp); /* add exponent */
229
230 s = Inv_sqrt (s); move32 (); /* function result */
231 i = round (L_shl (s, 9));
232
233 /* g0 = i * (1-agc_fac) */
234 g0 = mult (i, sub (32767, agc_fac));
235 }
236
237 /* compute gain[n] = agc_fac * gain[n-1]
238 + (1-agc_fac) * sqrt(gain_in/gain_out) */
239 /* sig_out[n] = gain[n] * sig_out[n] */
240
241 gain = st->past_gain; move16 ();
242
243 for (i = 0; i < l_trm; i++)
244 {
245 gain = mult (gain, agc_fac);
246 gain = add (gain, g0);
247 sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], gain), 3));
248 move16 ();
249 }
250
251 st->past_gain = gain; move16 ();
252
253 return 0;
254 }
255
256 /*
257 **************************************************************************
258 *
259 * Function : agc2
260 * Purpose : Scales the excitation on a subframe basis
261 *
262 **************************************************************************
263 */
264 void agc2 (
265 Word16 *sig_in, /* i : postfilter input signal */
266 Word16 *sig_out, /* i/o : postfilter output signal */
267 Word16 l_trm /* i : subframe size */
268 )
269 {
270 Word16 i, exp;
271 Word16 gain_in, gain_out, g0;
272 Word32 s;
273
274 /* calculate gain_out with exponent */
275 s = energy_new(sig_out, l_trm); move32 (); /* function result */
276
277 test ();
278 if (s == 0)
279 {
280 return;
281 }
282 exp = sub (norm_l (s), 1);
283 gain_out = round (L_shl (s, exp));
284
285 /* calculate gain_in with exponent */
286 s = energy_new(sig_in, l_trm); move32 (); /* function result */
287
288 test ();
289 if (s == 0)
290 {
291 g0 = 0; move16 ();
292 }
293 else
294 {
295 i = norm_l (s);
296 gain_in = round (L_shl (s, i));
297 exp = sub (exp, i);
298
299 /*---------------------------------------------------*
300 * g0 = sqrt(gain_in/gain_out); *
301 *---------------------------------------------------*/
302
303 s = L_deposit_l (div_s (gain_out, gain_in));
304 s = L_shl (s, 7); /* s = gain_out / gain_in */
305 s = L_shr (s, exp); /* add exponent */
306
307 s = Inv_sqrt (s); move32 (); /* function result */
308 g0 = round (L_shl (s, 9));
309 }
310
311 /* sig_out(n) = gain(n) sig_out(n) */
312
313 for (i = 0; i < l_trm; i++)
314 {
315 sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], g0), 3));
316 move16 ();
317 }
318
319 return;
320 }