FreeCalypso > hg > gsm-codec-lib
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 } |