comparison src/agc_amr.c @ 2:c511bfb36c2a

beginning of EFR2 decoder, using AMR version of AGC module
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 03 Apr 2024 05:47:51 +0000
parents
children
comparison
equal deleted inserted replaced
1:cd1a63963fa4 2:c511bfb36c2a
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 #if 0
21 #include "agc.h"
22 const char agc_id[] = "@(#)$Id $" agc_h;
23 #endif
24
25 /*
26 *****************************************************************************
27 * INCLUDE FILES
28 *****************************************************************************
29 */
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include "typedef.h"
33 #include "basic_op.h"
34 #include "count.h"
35 #include "sig_proc.h"
36 #include "cnst.h"
37
38 Word16 past_gain; /* initial value of past_gain = 1.0 */
39
40 /*
41 *****************************************************************************
42 * LOCAL PROGRAM CODE
43 *****************************************************************************
44 */
45
46 static Word32 energy_old( /* o : return energy of signal */
47 Word16 in[], /* i : input signal (length l_trm) */
48 Word16 l_trm /* i : signal length */
49 )
50 {
51 Word32 s;
52 Word16 i, temp;
53
54 temp = shr (in[0], 2);
55 s = L_mult (temp, temp);
56
57 for (i = 1; i < l_trm; i++)
58 {
59 temp = shr (in[i], 2);
60 s = L_mac (s, temp, temp);
61 }
62
63 return s;
64 }
65
66 static Word32 energy_new( /* o : return energy of signal */
67 Word16 in[], /* i : input signal (length l_trm) */
68 Word16 l_trm /* i : signal length */
69 )
70 {
71 Word32 s;
72 Word16 i;
73 Flag ov_save;
74
75 ov_save = Overflow; move16 (); /* save overflow flag in case energy_old */
76 /* must be called */
77 s = L_mult(in[0], in[0]);
78 for (i = 1; i < l_trm; i++)
79 {
80 s = L_mac(s, in[i], in[i]);
81 }
82
83 /* check for overflow */
84 test ();
85 if (L_sub (s, MAX_32) == 0L)
86 {
87 Overflow = ov_save; move16 (); /* restore overflow flag */
88 s = energy_old (in, l_trm); move32 (); /* function result */
89 }
90 else
91 {
92 s = L_shr(s, 4);
93 }
94
95 return s;
96 }
97 /*
98 *****************************************************************************
99 * PUBLIC PROGRAM CODE
100 *****************************************************************************
101 */
102
103 /*
104 **************************************************************************
105 *
106 * Function : agc
107 * Purpose : Scales the postfilter output on a subframe basis
108 *
109 **************************************************************************
110 */
111 void agc (
112 Word16 *sig_in, /* i : postfilter input signal (l_trm) */
113 Word16 *sig_out, /* i/o : postfilter output signal (l_trm) */
114 Word16 agc_fac, /* i : AGC factor */
115 Word16 l_trm /* i : subframe size */
116 )
117 {
118 Word16 i, exp;
119 Word16 gain_in, gain_out, g0, gain;
120 Word32 s;
121
122 /* calculate gain_out with exponent */
123 s = energy_new(sig_out, l_trm); move32 (); /* function result */
124
125 test ();
126 if (s == 0)
127 {
128 past_gain = 0; move16 ();
129 return;
130 }
131 exp = sub (norm_l (s), 1);
132 gain_out = round (L_shl (s, exp));
133
134 /* calculate gain_in with exponent */
135 s = energy_new(sig_in, l_trm); move32 (); /* function result */
136
137 test ();
138 if (s == 0)
139 {
140 g0 = 0; move16 ();
141 }
142 else
143 {
144 i = norm_l (s);
145 gain_in = round (L_shl (s, i));
146 exp = sub (exp, i);
147
148 /*---------------------------------------------------*
149 * g0 = (1-agc_fac) * sqrt(gain_in/gain_out); *
150 *---------------------------------------------------*/
151
152 s = L_deposit_l (div_s (gain_out, gain_in));
153 s = L_shl (s, 7); /* s = gain_out / gain_in */
154 s = L_shr (s, exp); /* add exponent */
155
156 s = Inv_sqrt (s); move32 (); /* function result */
157 i = round (L_shl (s, 9));
158
159 /* g0 = i * (1-agc_fac) */
160 g0 = mult (i, sub (32767, agc_fac));
161 }
162
163 /* compute gain[n] = agc_fac * gain[n-1]
164 + (1-agc_fac) * sqrt(gain_in/gain_out) */
165 /* sig_out[n] = gain[n] * sig_out[n] */
166
167 gain = past_gain; move16 ();
168
169 for (i = 0; i < l_trm; i++)
170 {
171 gain = mult (gain, agc_fac);
172 gain = add (gain, g0);
173 sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], gain), 3));
174 move16 ();
175 }
176
177 past_gain = gain; move16 ();
178 }
179
180 /*
181 **************************************************************************
182 *
183 * Function : agc2
184 * Purpose : Scales the excitation on a subframe basis
185 *
186 **************************************************************************
187 */
188 void agc2 (
189 Word16 *sig_in, /* i : postfilter input signal */
190 Word16 *sig_out, /* i/o : postfilter output signal */
191 Word16 l_trm /* i : subframe size */
192 )
193 {
194 Word16 i, exp;
195 Word16 gain_in, gain_out, g0;
196 Word32 s;
197
198 /* calculate gain_out with exponent */
199 s = energy_new(sig_out, l_trm); move32 (); /* function result */
200
201 test ();
202 if (s == 0)
203 {
204 return;
205 }
206 exp = sub (norm_l (s), 1);
207 gain_out = round (L_shl (s, exp));
208
209 /* calculate gain_in with exponent */
210 s = energy_new(sig_in, l_trm); move32 (); /* function result */
211
212 test ();
213 if (s == 0)
214 {
215 g0 = 0; move16 ();
216 }
217 else
218 {
219 i = norm_l (s);
220 gain_in = round (L_shl (s, i));
221 exp = sub (exp, i);
222
223 /*---------------------------------------------------*
224 * g0 = sqrt(gain_in/gain_out); *
225 *---------------------------------------------------*/
226
227 s = L_deposit_l (div_s (gain_out, gain_in));
228 s = L_shl (s, 7); /* s = gain_out / gain_in */
229 s = L_shr (s, exp); /* add exponent */
230
231 s = Inv_sqrt (s); move32 (); /* function result */
232 g0 = round (L_shl (s, 9));
233 }
234
235 /* sig_out(n) = gain(n) sig_out(n) */
236
237 for (i = 0; i < l_trm; i++)
238 {
239 sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], g0), 3));
240 move16 ();
241 }
242
243 return;
244 }