FreeCalypso > hg > gsm-codec-lib
comparison libtwamr/dtx_enc.c @ 407:5a1d18542f8a
libtwamr: integrate dtx_dec.c and dtx_enc.c
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 07 May 2024 00:05:12 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
406:85e9768d497f | 407:5a1d18542f8a |
---|---|
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 : dtx_enc.c | |
11 * Purpose : DTX mode computation of SID parameters | |
12 * | |
13 ******************************************************************************** | |
14 */ | |
15 | |
16 /* | |
17 ******************************************************************************** | |
18 * MODULE INCLUDE FILE AND VERSION ID | |
19 ******************************************************************************** | |
20 */ | |
21 #include "namespace.h" | |
22 #include "dtx_enc.h" | |
23 | |
24 /* | |
25 ******************************************************************************** | |
26 * INCLUDE FILES | |
27 ******************************************************************************** | |
28 */ | |
29 #include "tw_amr.h" | |
30 #include "typedef.h" | |
31 #include "basic_op.h" | |
32 #include "oper_32b.h" | |
33 #include "q_plsf.h" | |
34 #include "memops.h" | |
35 #include "log2.h" | |
36 #include "lsp_lsf.h" | |
37 #include "reorder.h" | |
38 #include "no_count.h" | |
39 #include "lsp_tab.h" | |
40 | |
41 /* | |
42 ******************************************************************************** | |
43 * PUBLIC PROGRAM CODE | |
44 ******************************************************************************** | |
45 */ | |
46 | |
47 /* | |
48 ************************************************************************** | |
49 * | |
50 * Function : dtx_enc_reset | |
51 * | |
52 ************************************************************************** | |
53 */ | |
54 void dtx_enc_reset (dtx_encState *st) | |
55 { | |
56 Word16 i; | |
57 | |
58 st->hist_ptr = 0; | |
59 st->log_en_index = 0; | |
60 st->init_lsf_vq_index = 0; | |
61 st->lsp_index[0] = 0; | |
62 st->lsp_index[1] = 0; | |
63 st->lsp_index[2] = 0; | |
64 | |
65 /* Init lsp_hist[] */ | |
66 for(i = 0; i < DTX_HIST_SIZE; i++) | |
67 { | |
68 Copy(lsp_init_data, &st->lsp_hist[i * M], M); | |
69 } | |
70 | |
71 /* Reset energy history */ | |
72 Set_zero(st->log_en_hist, M); | |
73 | |
74 st->dtxHangoverCount = DTX_HANG_CONST; | |
75 st->decAnaElapsedCount = 32767; | |
76 } | |
77 | |
78 /* | |
79 ************************************************************************** | |
80 * | |
81 * Function : dtx_enc | |
82 * | |
83 ************************************************************************** | |
84 */ | |
85 int dtx_enc(dtx_encState *st, /* i/o : State struct */ | |
86 Word16 computeSidFlag, /* i : compute SID */ | |
87 Q_plsfState *qSt, /* i/o : Qunatizer state struct */ | |
88 gc_predState* predState, /* i/o : State struct */ | |
89 Word16 **anap /* o : analysis parameters */ | |
90 ) | |
91 { | |
92 Word16 i,j; | |
93 Word16 log_en; | |
94 Word16 lsf[M]; | |
95 Word16 lsp[M]; | |
96 Word16 lsp_q[M]; | |
97 Word32 L_lsp[M]; | |
98 | |
99 /* VOX mode computation of SID parameters */ | |
100 test (); test (); | |
101 if ((computeSidFlag != 0)) | |
102 { | |
103 /* compute new SID frame if safe i.e don't | |
104 * compute immediately after a talk spurt */ | |
105 log_en = 0; move16 (); | |
106 for (i = 0; i < M; i++) | |
107 { | |
108 L_lsp[i] = 0; move16 (); | |
109 } | |
110 | |
111 /* average energy and lsp */ | |
112 for (i = 0; i < DTX_HIST_SIZE; i++) | |
113 { | |
114 log_en = add(log_en, | |
115 shr(st->log_en_hist[i],2)); | |
116 | |
117 for (j = 0; j < M; j++) | |
118 { | |
119 L_lsp[j] = L_add(L_lsp[j], | |
120 L_deposit_l(st->lsp_hist[i * M + j])); | |
121 } | |
122 } | |
123 | |
124 log_en = shr(log_en, 1); | |
125 for (j = 0; j < M; j++) | |
126 { | |
127 lsp[j] = extract_l(L_shr(L_lsp[j], 3)); /* divide by 8 */ | |
128 } | |
129 | |
130 /* quantize logarithmic energy to 6 bits */ | |
131 st->log_en_index = add(log_en, 2560); /* +2.5 in Q10 */ | |
132 st->log_en_index = add(st->log_en_index, 128); /* add 0.5/4 in Q10 */ | |
133 st->log_en_index = shr(st->log_en_index, 8); | |
134 | |
135 test (); | |
136 if (sub(st->log_en_index, 63) > 0) | |
137 { | |
138 st->log_en_index = 63; move16 (); | |
139 } | |
140 test (); | |
141 if (st->log_en_index < 0) | |
142 { | |
143 st->log_en_index = 0; move16 (); | |
144 } | |
145 | |
146 /* update gain predictor memory */ | |
147 log_en = shl(st->log_en_index, -2+10); /* Q11 and divide by 4 */ | |
148 log_en = sub(log_en, 2560); /* add 2.5 in Q11 */ | |
149 | |
150 log_en = sub(log_en, 9000); | |
151 test (); | |
152 if (log_en > 0) | |
153 { | |
154 log_en = 0; move16 (); | |
155 } | |
156 test (); | |
157 if (sub(log_en, -14436) < 0) | |
158 { | |
159 log_en = -14436; move16 (); | |
160 } | |
161 | |
162 /* past_qua_en for other modes than MR122 */ | |
163 predState->past_qua_en[0] = log_en; move16 (); | |
164 predState->past_qua_en[1] = log_en; move16 (); | |
165 predState->past_qua_en[2] = log_en; move16 (); | |
166 predState->past_qua_en[3] = log_en; move16 (); | |
167 | |
168 /* scale down by factor 20*log10(2) in Q15 */ | |
169 log_en = mult(5443, log_en); | |
170 | |
171 /* past_qua_en for mode MR122 */ | |
172 predState->past_qua_en_MR122[0] = log_en; move16 (); | |
173 predState->past_qua_en_MR122[1] = log_en; move16 (); | |
174 predState->past_qua_en_MR122[2] = log_en; move16 (); | |
175 predState->past_qua_en_MR122[3] = log_en; move16 (); | |
176 | |
177 /* make sure that LSP's are ordered */ | |
178 Lsp_lsf(lsp, lsf, M); | |
179 Reorder_lsf(lsf, LSF_GAP, M); | |
180 Lsf_lsp(lsf, lsp, M); | |
181 | |
182 /* Quantize lsp and put on parameter list */ | |
183 Q_plsf_3(qSt, MRDTX, lsp, lsp_q, st->lsp_index, | |
184 &st->init_lsf_vq_index); | |
185 } | |
186 | |
187 *(*anap)++ = st->init_lsf_vq_index; /* 3 bits */ move16 (); | |
188 | |
189 *(*anap)++ = st->lsp_index[0]; /* 8 bits */ move16 (); | |
190 *(*anap)++ = st->lsp_index[1]; /* 9 bits */ move16 (); | |
191 *(*anap)++ = st->lsp_index[2]; /* 9 bits */ move16 (); | |
192 | |
193 | |
194 *(*anap)++ = st->log_en_index; /* 6 bits */ move16 (); | |
195 /* = 35 bits */ | |
196 | |
197 return 0; | |
198 } | |
199 | |
200 /* | |
201 ************************************************************************** | |
202 * | |
203 * Function : dtx_buffer | |
204 * Purpose : handles the DTX buffer | |
205 * | |
206 ************************************************************************** | |
207 */ | |
208 int dtx_buffer(dtx_encState *st, /* i/o : State struct */ | |
209 Word16 lsp_new[], /* i : LSP vector */ | |
210 Word16 speech[] /* i : speech samples */ | |
211 ) | |
212 { | |
213 Word16 i; | |
214 Word32 L_frame_en; | |
215 Word16 log_en_e; | |
216 Word16 log_en_m; | |
217 Word16 log_en; | |
218 | |
219 /* update pointer to circular buffer */ | |
220 st->hist_ptr = add(st->hist_ptr, 1); | |
221 test (); | |
222 if (sub(st->hist_ptr, DTX_HIST_SIZE) == 0) | |
223 { | |
224 st->hist_ptr = 0; move16 (); | |
225 } | |
226 | |
227 /* copy lsp vector into buffer */ | |
228 Copy(lsp_new, &st->lsp_hist[st->hist_ptr * M], M); | |
229 | |
230 /* compute log energy based on frame energy */ | |
231 L_frame_en = 0; /* Q0 */ move32 (); | |
232 for (i=0; i < L_FRAME; i++) | |
233 { | |
234 L_frame_en = L_mac(L_frame_en, speech[i], speech[i]); | |
235 } | |
236 Log2(L_frame_en, &log_en_e, &log_en_m); | |
237 | |
238 /* convert exponent and mantissa to Word16 Q10 */ | |
239 log_en = shl(log_en_e, 10); /* Q10 */ | |
240 log_en = add(log_en, shr(log_en_m, 15-10)); | |
241 | |
242 /* divide with L_FRAME i.e subtract with log2(L_FRAME) = 7.32193 */ | |
243 log_en = sub(log_en, 8521); | |
244 | |
245 /* insert into log energy buffer with division by 2 */ | |
246 log_en = shr(log_en, 1); | |
247 st->log_en_hist[st->hist_ptr] = log_en; /* Q10 */ move16 (); | |
248 | |
249 return 0; | |
250 } | |
251 | |
252 /* | |
253 ************************************************************************** | |
254 * | |
255 * Function : tx_dtx_handler | |
256 * Purpose : adds extra speech hangover to analyze speech on the decoding side. | |
257 * | |
258 ************************************************************************** | |
259 */ | |
260 Word16 tx_dtx_handler(dtx_encState *st, /* i/o : State struct */ | |
261 Word16 vad_flag, /* i : vad decision */ | |
262 enum Mode *usedMode /* i/o : mode changed or not */ | |
263 ) | |
264 { | |
265 Word16 compute_new_sid_possible; | |
266 | |
267 /* this state machine is in synch with the GSMEFR txDtx machine */ | |
268 st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1); | |
269 | |
270 compute_new_sid_possible = 0; move16(); | |
271 | |
272 test(); | |
273 if (vad_flag != 0) | |
274 { | |
275 st->dtxHangoverCount = DTX_HANG_CONST; move16(); | |
276 } | |
277 else | |
278 { /* non-speech */ | |
279 test(); | |
280 if (st->dtxHangoverCount == 0) | |
281 { /* out of decoder analysis hangover */ | |
282 st->decAnaElapsedCount = 0; move16(); | |
283 *usedMode = MRDTX; move16(); | |
284 compute_new_sid_possible = 1; move16(); | |
285 } | |
286 else | |
287 { /* in possible analysis hangover */ | |
288 st->dtxHangoverCount = sub(st->dtxHangoverCount, 1); | |
289 | |
290 /* decAnaElapsedCount + dtxHangoverCount < DTX_ELAPSED_FRAMES_THRESH */ | |
291 test (); | |
292 if (sub(add(st->decAnaElapsedCount, st->dtxHangoverCount), | |
293 DTX_ELAPSED_FRAMES_THRESH) < 0) | |
294 { | |
295 *usedMode = MRDTX; move16(); | |
296 /* if short time since decoder update, do not add extra HO */ | |
297 } | |
298 /* | |
299 else | |
300 override VAD and stay in | |
301 speech mode *usedMode | |
302 and add extra hangover | |
303 */ | |
304 } | |
305 } | |
306 | |
307 return compute_new_sid_possible; | |
308 } |