FreeCalypso > hg > efr-experiments
comparison src/q_plsf_5.c @ 0:56410792419a
src: original EFR source from ETSI
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 03 Apr 2024 05:31:37 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:56410792419a |
---|---|
1 /************************************************************************* | |
2 * FUNCTION: Q_plsf_5() | |
3 * | |
4 * PURPOSE: Quantization of 2 sets of LSF parameters using 1st order MA | |
5 * prediction and split by 5 matrix quantization (split-MQ) | |
6 * | |
7 * DESCRIPTION: | |
8 * | |
9 * p[i] = pred_factor*past_r2q[i]; i=0,...,m-1 | |
10 * r1[i]= lsf1[i] - p[i]; i=0,...,m-1 | |
11 * r2[i]= lsf2[i] - p[i]; i=0,...,m-1 | |
12 * where: | |
13 * lsf1[i] 1st mean-removed LSF vector. | |
14 * lsf2[i] 2nd mean-removed LSF vector. | |
15 * r1[i] 1st residual prediction vector. | |
16 * r2[i] 2nd residual prediction vector. | |
17 * past_r2q[i] Past quantized residual (2nd vector). | |
18 * | |
19 * The residual vectors r1[i] and r2[i] are jointly quantized using | |
20 * split-MQ with 5 codebooks. Each 4th dimension submatrix contains 2 | |
21 * elements from each residual vector. The 5 submatrices are as follows: | |
22 * {r1[0], r1[1], r2[0], r2[1]}; {r1[2], r1[3], r2[2], r2[3]}; | |
23 * {r1[4], r1[5], r2[4], r2[5]}; {r1[6], r1[7], r2[6], r2[7]}; | |
24 * {r1[8], r1[9], r2[8], r2[9]}; | |
25 * | |
26 *************************************************************************/ | |
27 | |
28 #include "typedef.h" | |
29 #include "basic_op.h" | |
30 #include "count.h" | |
31 #include "sig_proc.h" | |
32 | |
33 #include "cnst.h" | |
34 #include "dtx.h" | |
35 | |
36 /* Locals functions */ | |
37 | |
38 void Lsf_wt ( | |
39 Word16 *lsf, /* input : LSF vector */ | |
40 Word16 *wf2 /* output: square of weighting factors */ | |
41 ); | |
42 | |
43 Word16 Vq_subvec ( /* output: return quantization index */ | |
44 Word16 *lsf_r1, /* input : 1st LSF residual vector */ | |
45 Word16 *lsf_r2, /* input : and LSF residual vector */ | |
46 const Word16 *dico,/* input : quantization codebook */ | |
47 Word16 *wf1, /* input : 1st LSF weighting factors */ | |
48 Word16 *wf2, /* input : 2nd LSF weighting factors */ | |
49 Word16 dico_size /* input : size of quantization codebook */ | |
50 ); | |
51 Word16 Vq_subvec_s ( /* output: return quantization index */ | |
52 Word16 *lsf_r1, /* input : 1st LSF residual vector */ | |
53 Word16 *lsf_r2, /* input : and LSF residual vector */ | |
54 const Word16 *dico,/* input : quantization codebook */ | |
55 Word16 *wf1, /* input : 1st LSF weighting factors */ | |
56 Word16 *wf2, /* input : 2nd LSF weighting factors */ | |
57 Word16 dico_size /* input : size of quantization codebook */ | |
58 ); | |
59 /* M ->order of linear prediction filter */ | |
60 /* LSF_GAP -> Minimum distance between LSF after quantization */ | |
61 /* 50 Hz = 205 */ | |
62 /* PRED_FAC -> Predcition factor */ | |
63 | |
64 #define M 10 | |
65 #define LSF_GAP 205 | |
66 #define PRED_FAC 21299 | |
67 | |
68 #include "q_plsf_5.tab" /* Codebooks of LSF prediction residual */ | |
69 | |
70 /* Past quantized prediction error */ | |
71 | |
72 Word16 past_r2_q[M]; | |
73 | |
74 extern Word16 lsf_old_tx[DTX_HANGOVER][M]; | |
75 | |
76 void Q_plsf_5 ( | |
77 Word16 *lsp1, /* input : 1st LSP vector */ | |
78 Word16 *lsp2, /* input : 2nd LSP vector */ | |
79 Word16 *lsp1_q, /* output: quantized 1st LSP vector */ | |
80 Word16 *lsp2_q, /* output: quantized 2nd LSP vector */ | |
81 Word16 *indice, /* output: quantization indices of 5 matrices */ | |
82 Word16 txdtx_ctrl /* input : tx dtx control word */ | |
83 ) | |
84 { | |
85 Word16 i; | |
86 Word16 lsf1[M], lsf2[M], wf1[M], wf2[M], lsf_p[M], lsf_r1[M], lsf_r2[M]; | |
87 Word16 lsf1_q[M], lsf2_q[M]; | |
88 Word16 lsf_aver[M]; | |
89 static Word16 lsf_p_CN[M]; | |
90 | |
91 /* convert LSFs to normalize frequency domain 0..16384 */ | |
92 | |
93 Lsp_lsf (lsp1, lsf1, M); | |
94 Lsp_lsf (lsp2, lsf2, M); | |
95 | |
96 /* Update LSF CN quantizer "memory" */ | |
97 | |
98 logic16 (); logic16 (); test (); test (); | |
99 if ((txdtx_ctrl & TX_SP_FLAG) == 0 | |
100 && (txdtx_ctrl & TX_PREV_HANGOVER_ACTIVE) != 0) | |
101 { | |
102 update_lsf_p_CN (lsf_old_tx, lsf_p_CN); | |
103 } | |
104 logic16 (); test (); | |
105 if ((txdtx_ctrl & TX_SID_UPDATE) != 0) | |
106 { | |
107 /* New SID frame is to be sent: | |
108 Compute average of the current LSFs and the LSFs in the history */ | |
109 | |
110 aver_lsf_history (lsf_old_tx, lsf1, lsf2, lsf_aver); | |
111 } | |
112 /* Update LSF history with unquantized LSFs when no speech activity | |
113 is present */ | |
114 | |
115 logic16 (); test (); | |
116 if ((txdtx_ctrl & TX_SP_FLAG) == 0) | |
117 { | |
118 update_lsf_history (lsf1, lsf2, lsf_old_tx); | |
119 } | |
120 logic16 (); test (); | |
121 if ((txdtx_ctrl & TX_SID_UPDATE) != 0) | |
122 { | |
123 /* Compute LSF weighting factors for lsf2, using averaged LSFs */ | |
124 /* Set LSF weighting factors for lsf1 to zero */ | |
125 /* Replace lsf1 and lsf2 by the averaged LSFs */ | |
126 | |
127 Lsf_wt (lsf_aver, wf2); | |
128 for (i = 0; i < M; i++) | |
129 { | |
130 wf1[i] = 0; move16 (); | |
131 lsf1[i] = lsf_aver[i]; move16 (); | |
132 lsf2[i] = lsf_aver[i]; move16 (); | |
133 } | |
134 } | |
135 else | |
136 { | |
137 /* Compute LSF weighting factors */ | |
138 | |
139 Lsf_wt (lsf1, wf1); | |
140 Lsf_wt (lsf2, wf2); | |
141 } | |
142 | |
143 /* Compute predicted LSF and prediction error */ | |
144 | |
145 logic16 (); test (); | |
146 if ((txdtx_ctrl & TX_SP_FLAG) != 0) | |
147 { | |
148 for (i = 0; i < M; i++) | |
149 { | |
150 lsf_p[i] = add (mean_lsf[i], mult (past_r2_q[i], PRED_FAC)); | |
151 move16 (); | |
152 lsf_r1[i] = sub (lsf1[i], lsf_p[i]); move16 (); | |
153 lsf_r2[i] = sub (lsf2[i], lsf_p[i]); move16 (); | |
154 } | |
155 } | |
156 else | |
157 { | |
158 for (i = 0; i < M; i++) | |
159 { | |
160 lsf_r1[i] = sub (lsf1[i], lsf_p_CN[i]); move16 (); | |
161 lsf_r2[i] = sub (lsf2[i], lsf_p_CN[i]); move16 (); | |
162 } | |
163 } | |
164 | |
165 /*---- Split-VQ of prediction error ----*/ | |
166 | |
167 indice[0] = Vq_subvec (&lsf_r1[0], &lsf_r2[0], dico1_lsf, | |
168 &wf1[0], &wf2[0], DICO1_SIZE); | |
169 move16 (); | |
170 | |
171 indice[1] = Vq_subvec (&lsf_r1[2], &lsf_r2[2], dico2_lsf, | |
172 &wf1[2], &wf2[2], DICO2_SIZE); | |
173 move16 (); | |
174 | |
175 indice[2] = Vq_subvec_s (&lsf_r1[4], &lsf_r2[4], dico3_lsf, | |
176 &wf1[4], &wf2[4], DICO3_SIZE); | |
177 move16 (); | |
178 | |
179 indice[3] = Vq_subvec (&lsf_r1[6], &lsf_r2[6], dico4_lsf, | |
180 &wf1[6], &wf2[6], DICO4_SIZE); | |
181 move16 (); | |
182 | |
183 indice[4] = Vq_subvec (&lsf_r1[8], &lsf_r2[8], dico5_lsf, | |
184 &wf1[8], &wf2[8], DICO5_SIZE); | |
185 move16 (); | |
186 | |
187 /* Compute quantized LSFs and update the past quantized residual */ | |
188 /* In case of no speech activity, skip computing the quantized LSFs, | |
189 and set past_r2_q to zero (initial value) */ | |
190 | |
191 logic16 (); test (); | |
192 if ((txdtx_ctrl & TX_SP_FLAG) != 0) | |
193 { | |
194 for (i = 0; i < M; i++) | |
195 { | |
196 lsf1_q[i] = add (lsf_r1[i], lsf_p[i]); move16 (); | |
197 lsf2_q[i] = add (lsf_r2[i], lsf_p[i]); move16 (); | |
198 past_r2_q[i] = lsf_r2[i]; move16 (); | |
199 } | |
200 | |
201 /* verification that LSFs has minimum distance of LSF_GAP */ | |
202 | |
203 Reorder_lsf (lsf1_q, LSF_GAP, M); | |
204 Reorder_lsf (lsf2_q, LSF_GAP, M); | |
205 | |
206 /* Update LSF history with quantized LSFs | |
207 when hangover period is active */ | |
208 | |
209 logic16 (); test (); | |
210 if ((txdtx_ctrl & TX_HANGOVER_ACTIVE) != 0) | |
211 { | |
212 update_lsf_history (lsf1_q, lsf2_q, lsf_old_tx); | |
213 } | |
214 /* convert LSFs to the cosine domain */ | |
215 | |
216 Lsf_lsp (lsf1_q, lsp1_q, M); | |
217 Lsf_lsp (lsf2_q, lsp2_q, M); | |
218 } | |
219 else | |
220 { | |
221 for (i = 0; i < M; i++) | |
222 { | |
223 past_r2_q[i] = 0; move16 (); | |
224 } | |
225 } | |
226 | |
227 return; | |
228 } | |
229 | |
230 /* Quantization of a 4 dimensional subvector */ | |
231 | |
232 Word16 Vq_subvec ( /* output: return quantization index */ | |
233 Word16 *lsf_r1, /* input : 1st LSF residual vector */ | |
234 Word16 *lsf_r2, /* input : and LSF residual vector */ | |
235 const Word16 *dico, /* input : quantization codebook */ | |
236 Word16 *wf1, /* input : 1st LSF weighting factors */ | |
237 Word16 *wf2, /* input : 2nd LSF weighting factors */ | |
238 Word16 dico_size /* input : size of quantization codebook */ | |
239 ) | |
240 { | |
241 Word16 i, index, temp; | |
242 const Word16 *p_dico; | |
243 Word32 dist_min, dist; | |
244 | |
245 dist_min = MAX_32; move32 (); | |
246 p_dico = dico; move16 (); | |
247 | |
248 for (i = 0; i < dico_size; i++) | |
249 { | |
250 temp = sub (lsf_r1[0], *p_dico++); | |
251 temp = mult (wf1[0], temp); | |
252 dist = L_mult (temp, temp); | |
253 | |
254 temp = sub (lsf_r1[1], *p_dico++); | |
255 temp = mult (wf1[1], temp); | |
256 dist = L_mac (dist, temp, temp); | |
257 | |
258 temp = sub (lsf_r2[0], *p_dico++); | |
259 temp = mult (wf2[0], temp); | |
260 dist = L_mac (dist, temp, temp); | |
261 | |
262 temp = sub (lsf_r2[1], *p_dico++); | |
263 temp = mult (wf2[1], temp); | |
264 dist = L_mac (dist, temp, temp); | |
265 | |
266 test (); | |
267 if (L_sub (dist, dist_min) < (Word32) 0) | |
268 { | |
269 dist_min = dist; move32 (); | |
270 index = i; move16 (); | |
271 } | |
272 } | |
273 | |
274 /* Reading the selected vector */ | |
275 | |
276 p_dico = &dico[shl (index, 2)]; move16 (); | |
277 lsf_r1[0] = *p_dico++; move16 (); | |
278 lsf_r1[1] = *p_dico++; move16 (); | |
279 lsf_r2[0] = *p_dico++; move16 (); | |
280 lsf_r2[1] = *p_dico++; move16 (); | |
281 | |
282 return index; | |
283 | |
284 } | |
285 | |
286 /* Quantization of a 4 dimensional subvector with a signed codebook */ | |
287 | |
288 Word16 Vq_subvec_s ( /* output: return quantization index */ | |
289 Word16 *lsf_r1, /* input : 1st LSF residual vector */ | |
290 Word16 *lsf_r2, /* input : and LSF residual vector */ | |
291 const Word16 *dico, /* input : quantization codebook */ | |
292 Word16 *wf1, /* input : 1st LSF weighting factors */ | |
293 Word16 *wf2, /* input : 2nd LSF weighting factors */ | |
294 Word16 dico_size) /* input : size of quantization codebook */ | |
295 { | |
296 Word16 i, index, sign, temp; | |
297 const Word16 *p_dico; | |
298 Word32 dist_min, dist; | |
299 | |
300 dist_min = MAX_32; move32 (); | |
301 p_dico = dico; move16 (); | |
302 | |
303 for (i = 0; i < dico_size; i++) | |
304 { | |
305 /* test positive */ | |
306 | |
307 temp = sub (lsf_r1[0], *p_dico++); | |
308 temp = mult (wf1[0], temp); | |
309 dist = L_mult (temp, temp); | |
310 | |
311 temp = sub (lsf_r1[1], *p_dico++); | |
312 temp = mult (wf1[1], temp); | |
313 dist = L_mac (dist, temp, temp); | |
314 | |
315 temp = sub (lsf_r2[0], *p_dico++); | |
316 temp = mult (wf2[0], temp); | |
317 dist = L_mac (dist, temp, temp); | |
318 | |
319 temp = sub (lsf_r2[1], *p_dico++); | |
320 temp = mult (wf2[1], temp); | |
321 dist = L_mac (dist, temp, temp); | |
322 | |
323 test (); | |
324 if (L_sub (dist, dist_min) < (Word32) 0) | |
325 { | |
326 dist_min = dist; move32 (); | |
327 index = i; move16 (); | |
328 sign = 0; move16 (); | |
329 } | |
330 /* test negative */ | |
331 | |
332 p_dico -= 4; move16 (); | |
333 temp = add (lsf_r1[0], *p_dico++); | |
334 temp = mult (wf1[0], temp); | |
335 dist = L_mult (temp, temp); | |
336 | |
337 temp = add (lsf_r1[1], *p_dico++); | |
338 temp = mult (wf1[1], temp); | |
339 dist = L_mac (dist, temp, temp); | |
340 | |
341 temp = add (lsf_r2[0], *p_dico++); | |
342 temp = mult (wf2[0], temp); | |
343 dist = L_mac (dist, temp, temp); | |
344 | |
345 temp = add (lsf_r2[1], *p_dico++); | |
346 temp = mult (wf2[1], temp); | |
347 dist = L_mac (dist, temp, temp); | |
348 | |
349 test (); | |
350 if (L_sub (dist, dist_min) < (Word32) 0) | |
351 { | |
352 dist_min = dist; move32 (); | |
353 index = i; move16 (); | |
354 sign = 1; move16 (); | |
355 } | |
356 } | |
357 | |
358 /* Reading the selected vector */ | |
359 | |
360 p_dico = &dico[shl (index, 2)]; move16 (); | |
361 test (); | |
362 if (sign == 0) | |
363 { | |
364 lsf_r1[0] = *p_dico++; move16 (); | |
365 lsf_r1[1] = *p_dico++; move16 (); | |
366 lsf_r2[0] = *p_dico++; move16 (); | |
367 lsf_r2[1] = *p_dico++; move16 (); | |
368 } | |
369 else | |
370 { | |
371 lsf_r1[0] = negate (*p_dico++); move16 (); | |
372 lsf_r1[1] = negate (*p_dico++); move16 (); | |
373 lsf_r2[0] = negate (*p_dico++); move16 (); | |
374 lsf_r2[1] = negate (*p_dico++); move16 (); | |
375 } | |
376 | |
377 index = shl (index, 1); | |
378 index = add (index, sign); | |
379 | |
380 return index; | |
381 | |
382 } | |
383 | |
384 /**************************************************** | |
385 * FUNCTION Lsf_wt * | |
386 * * | |
387 **************************************************** | |
388 * Compute LSF weighting factors * | |
389 * * | |
390 * d[i] = lsf[i+1] - lsf[i-1] * | |
391 * * | |
392 * The weighting factors are approximated by two line segment. * | |
393 * * | |
394 * First segment passes by the following 2 points: * | |
395 * * | |
396 * d[i] = 0Hz wf[i] = 3.347 * | |
397 * d[i] = 450Hz wf[i] = 1.8 * | |
398 * * | |
399 * Second segment passes by the following 2 points: * | |
400 * * | |
401 * d[i] = 450Hz wf[i] = 1.8 * | |
402 * d[i] = 1500Hz wf[i] = 1.0 * | |
403 * * | |
404 * if( d[i] < 450Hz ) * | |
405 * wf[i] = 3.347 - ( (3.347-1.8) / (450-0)) * d[i] * | |
406 * else * | |
407 * wf[i] = 1.8 - ( (1.8-1.0) / (1500-450)) * (d[i] - 450) * | |
408 * * | |
409 * * | |
410 * if( d[i] < 1843) * | |
411 * wf[i] = 3427 - (28160*d[i])>>15 * | |
412 * else * | |
413 * wf[i] = 1843 - (6242*(d[i]-1843))>>15 * | |
414 * * | |
415 *--------------------------------------------------------------------------*/ | |
416 | |
417 void Lsf_wt ( | |
418 Word16 *lsf, /* input : LSF vector */ | |
419 Word16 *wf) /* output: square of weighting factors */ | |
420 { | |
421 Word16 temp; | |
422 Word16 i; | |
423 /* wf[0] = lsf[1] - 0 */ | |
424 wf[0] = lsf[1]; move16 (); | |
425 for (i = 1; i < 9; i++) | |
426 { | |
427 wf[i] = sub (lsf[i + 1], lsf[i - 1]); move16 (); | |
428 } | |
429 /* wf[9] = 0.5 - lsf[8] */ | |
430 wf[9] = sub (16384, lsf[8]);move16 (); | |
431 | |
432 for (i = 0; i < 10; i++) | |
433 { | |
434 temp = sub (wf[i], 1843); | |
435 test (); | |
436 if (temp < 0) | |
437 { | |
438 wf[i] = sub (3427, mult (wf[i], 28160)); move16 (); | |
439 } | |
440 else | |
441 { | |
442 wf[i] = sub (1843, mult (temp, 6242)); move16 (); | |
443 } | |
444 | |
445 wf[i] = shl (wf[i], 3); move16 (); | |
446 } | |
447 return; | |
448 } |