FreeCalypso > hg > gsm-codec-lib
comparison libgsmefr/agc.c @ 53:49dd1ac8e75b
libgsmefr: import most *.c files from ETSI source
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 25 Nov 2022 16:18:21 +0000 |
parents | |
children | 7b11cbe99a0e |
comparison
equal
deleted
inserted
replaced
52:988fd7ff514f | 53:49dd1ac8e75b |
---|---|
1 /************************************************************************* | |
2 * | |
3 * FUNCTION: agc | |
4 * | |
5 * PURPOSE: Scales the postfilter output on a subframe basis by automatic | |
6 * control of the subframe gain. | |
7 * | |
8 * DESCRIPTION: | |
9 * sig_out[n] = sig_out[n] * gain[n]; | |
10 * where gain[n] is the gain at the nth sample given by | |
11 * gain[n] = agc_fac * gain[n-1] + (1 - agc_fac) g_in/g_out | |
12 * g_in/g_out is the square root of the ratio of energy at the input | |
13 * and output of the postfilter. | |
14 * | |
15 *************************************************************************/ | |
16 | |
17 #include "typedef.h" | |
18 #include "basic_op.h" | |
19 #include "count.h" | |
20 #include "sig_proc.h" | |
21 #include "cnst.h" | |
22 | |
23 Word16 past_gain; /* initial value of past_gain = 1.0 */ | |
24 | |
25 void agc ( | |
26 Word16 *sig_in, /* (i) : postfilter input signal */ | |
27 Word16 *sig_out, /* (i/o) : postfilter output signal */ | |
28 Word16 agc_fac, /* (i) : AGC factor */ | |
29 Word16 l_trm /* (i) : subframe size */ | |
30 ) | |
31 { | |
32 Word16 i, exp; | |
33 Word16 gain_in, gain_out, g0, gain; | |
34 Word32 s; | |
35 | |
36 Word16 temp; | |
37 | |
38 /* calculate gain_out with exponent */ | |
39 | |
40 temp = shr (sig_out[0], 2); | |
41 s = L_mult (temp, temp); | |
42 | |
43 for (i = 1; i < l_trm; i++) | |
44 { | |
45 temp = shr (sig_out[i], 2); | |
46 s = L_mac (s, temp, temp); | |
47 } | |
48 | |
49 test (); | |
50 if (s == 0) | |
51 { | |
52 past_gain = 0; move16 (); | |
53 return; | |
54 } | |
55 exp = sub (norm_l (s), 1); | |
56 gain_out = round (L_shl (s, exp)); | |
57 | |
58 /* calculate gain_in with exponent */ | |
59 | |
60 temp = shr (sig_in[0], 2); | |
61 s = L_mult (temp, temp); | |
62 | |
63 for (i = 1; i < l_trm; i++) | |
64 { | |
65 temp = shr (sig_in[i], 2); | |
66 s = L_mac (s, temp, temp); | |
67 } | |
68 | |
69 test (); | |
70 if (s == 0) | |
71 { | |
72 g0 = 0; move16 (); | |
73 } | |
74 else | |
75 { | |
76 i = norm_l (s); | |
77 gain_in = round (L_shl (s, i)); | |
78 exp = sub (exp, i); | |
79 | |
80 /*---------------------------------------------------* | |
81 * g0 = (1-agc_fac) * sqrt(gain_in/gain_out); * | |
82 *---------------------------------------------------*/ | |
83 | |
84 s = L_deposit_l (div_s (gain_out, gain_in)); | |
85 s = L_shl (s, 7); /* s = gain_out / gain_in */ | |
86 s = L_shr (s, exp); /* add exponent */ | |
87 | |
88 s = Inv_sqrt (s); | |
89 i = round (L_shl (s, 9)); | |
90 | |
91 /* g0 = i * (1-agc_fac) */ | |
92 g0 = mult (i, sub (32767, agc_fac)); | |
93 } | |
94 | |
95 /* compute gain[n] = agc_fac * gain[n-1] | |
96 + (1-agc_fac) * sqrt(gain_in/gain_out) */ | |
97 /* sig_out[n] = gain[n] * sig_out[n] */ | |
98 | |
99 gain = past_gain; move16 (); | |
100 | |
101 for (i = 0; i < l_trm; i++) | |
102 { | |
103 gain = mult (gain, agc_fac); | |
104 gain = add (gain, g0); | |
105 sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], gain), 3)); | |
106 move16 (); | |
107 } | |
108 | |
109 past_gain = gain; move16 (); | |
110 | |
111 return; | |
112 } | |
113 | |
114 void agc2 ( | |
115 Word16 *sig_in, /* (i) : postfilter input signal */ | |
116 Word16 *sig_out, /* (i/o) : postfilter output signal */ | |
117 Word16 l_trm /* (i) : subframe size */ | |
118 ) | |
119 { | |
120 Word16 i, exp; | |
121 Word16 gain_in, gain_out, g0; | |
122 Word32 s; | |
123 | |
124 Word16 temp; | |
125 | |
126 /* calculate gain_out with exponent */ | |
127 | |
128 temp = shr (sig_out[0], 2); | |
129 s = L_mult (temp, temp); | |
130 for (i = 1; i < l_trm; i++) | |
131 { | |
132 temp = shr (sig_out[i], 2); | |
133 s = L_mac (s, temp, temp); | |
134 } | |
135 | |
136 test (); | |
137 if (s == 0) | |
138 { | |
139 return; | |
140 } | |
141 exp = sub (norm_l (s), 1); | |
142 gain_out = round (L_shl (s, exp)); | |
143 | |
144 /* calculate gain_in with exponent */ | |
145 | |
146 temp = shr (sig_in[0], 2); | |
147 s = L_mult (temp, temp); | |
148 for (i = 1; i < l_trm; i++) | |
149 { | |
150 temp = shr (sig_in[i], 2); | |
151 s = L_mac (s, temp, temp); | |
152 } | |
153 | |
154 test (); | |
155 if (s == 0) | |
156 { | |
157 g0 = 0; move16 (); | |
158 } | |
159 else | |
160 { | |
161 i = norm_l (s); | |
162 gain_in = round (L_shl (s, i)); | |
163 exp = sub (exp, i); | |
164 | |
165 /*---------------------------------------------------* | |
166 * g0 = sqrt(gain_in/gain_out); * | |
167 *---------------------------------------------------*/ | |
168 | |
169 s = L_deposit_l (div_s (gain_out, gain_in)); | |
170 s = L_shl (s, 7); /* s = gain_out / gain_in */ | |
171 s = L_shr (s, exp); /* add exponent */ | |
172 | |
173 s = Inv_sqrt (s); | |
174 g0 = round (L_shl (s, 9)); | |
175 } | |
176 | |
177 /* sig_out(n) = gain(n) sig_out(n) */ | |
178 | |
179 for (i = 0; i < l_trm; i++) | |
180 { | |
181 sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], g0), 3)); | |
182 move16 (); | |
183 } | |
184 | |
185 return; | |
186 } |