FreeCalypso > hg > efr-experiments
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 } |