FreeCalypso > hg > gsmhr-codec-ref
comparison sp_sfrm.c @ 0:9008dbc8ca74
import original C code from GSM 06.06
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 14 Jun 2024 23:27:16 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:9008dbc8ca74 |
---|---|
1 /*************************************************************************** | |
2 * | |
3 * File Name: sp_sfrm.c | |
4 * | |
5 * Purpose: Contains all functions for subframe based processing in the | |
6 * speech encoder. Subframe based processing determines the synthetic | |
7 * LPC excitation signal, which is composed of the adaptive codebook | |
8 * (long-term predictor) vector (in voiced modes), the vector-sum | |
9 * codebook vector (two of these in unvoiced mode), and the vector- | |
10 * quantized gains applied to these vectors. | |
11 * | |
12 * Below is a listing of all the functions appearing in the file. | |
13 * The functions are arranged according to their purpose. Under | |
14 * each heading, the ordering is hierarchical. | |
15 * | |
16 * sfrmAnalysis | |
17 * decorr | |
18 * closedLoopLagSearch | |
19 * hnwFilt | |
20 * g_quant_vl | |
21 * g_corr2 | |
22 * gainTweak | |
23 * v_srch | |
24 * | |
25 * | |
26 ***************************************************************************/ | |
27 /*_________________________________________________________________________ | |
28 | | | |
29 | Include Files | | |
30 |_________________________________________________________________________| | |
31 */ | |
32 | |
33 #include <stdio.h> | |
34 #include "mathhalf.h" | |
35 #include "sp_rom.h" | |
36 #include "sp_dec.h" | |
37 #include "sp_frm.h" | |
38 #include "sp_sfrm.h" | |
39 | |
40 /*_________________________________________________________________________ | |
41 | | | |
42 | Local Defines | | |
43 |_________________________________________________________________________| | |
44 */ | |
45 | |
46 #define CG_INT_MACS 6 | |
47 #define C_BITS_UV 7 | |
48 #define C_BITS_UV_1 C_BITS_UV-1 | |
49 #define C_BITS_V 9 | |
50 #define C_BITS_V_1 C_BITS_V-1 | |
51 #define DELTA_LEVELS 16 | |
52 #define GSP0_NUM 32 | |
53 #define GSP0_VECTOR_SIZE 5 | |
54 #define GTWEAKMAX 0x5A82 /* sqrt(2)/2 */ | |
55 #define LMAX 142 | |
56 #define LSMAX (LMAX + CG_INT_MACS/2) | |
57 #define HNW_BUFF_LEN LSMAX | |
58 #define LSP_MASK 0xffff | |
59 #define LTP_LEN 147 /* maximum ltp lag */ | |
60 #define MAX_CANDIDATE 6 /* maximum number of lag candidates */ | |
61 | |
62 | |
63 /*_________________________________________________________________________ | |
64 | | | |
65 | State variables (globals) | | |
66 |_________________________________________________________________________| | |
67 */ | |
68 | |
69 Shortword pswLtpStateBase[LTP_LEN + S_LEN]; | |
70 Shortword pswHState[NP]; | |
71 Shortword pswHNWState[HNW_BUFF_LEN]; | |
72 | |
73 /*************************************************************************** | |
74 * | |
75 * FUNCTION NAME: closedLoopLagSearch | |
76 * | |
77 * PURPOSE: | |
78 * | |
79 * Performs the closed loop search of a list of candidate lags to | |
80 * determine the best fractional lag. | |
81 * | |
82 * INPUTS: | |
83 * | |
84 * pswLagList[0:iNumLags] - list of candidate lags | |
85 * iNumLags - number of candidate lags in LagList | |
86 * pswLtpState[0:5] - array of past excitations (LTP state) | |
87 * pswHCoefs[0:9] - coefficient array of spectral weighting filter | |
88 * pswPVect[0:39] - speech sub frame data | |
89 * | |
90 * OUTPUTS: | |
91 * | |
92 * pswLag - pointer to put best lag from list of candidates | |
93 * *pswLtpShift - Number of shifts applied to weighted LTP vector. | |
94 * | |
95 * RETURN VALUE: | |
96 * | |
97 * siLagCode - code corresponding to the best lag | |
98 * | |
99 * IMPLEMENTATION: | |
100 * | |
101 * Generate excitation vectors for all candidate lags. Find the candidate | |
102 * lag that maximizes C**2/G using the calculated excitation. | |
103 * | |
104 * DESCRIPTION: | |
105 * | |
106 * The function closedLoopLagSearch() searches a very small subset of the | |
107 * available LTP lags. The lags to be searched are defined by the open | |
108 * loop lag search. This information is passed in as a list of | |
109 * oversampled lag values. These values are translated into LTP | |
110 * vectors extracted from the LTP history. | |
111 * | |
112 * GSM document 06.20's b sub L prime variable is called | |
113 * ppswTVect[L][n] in the C code. The document's variable p(n) is | |
114 * named pswPVect[] in the C code. | |
115 * | |
116 * The function performs a simple maximization of the cross correlation | |
117 * of the weighted LTP vector and the weighted speech vector divided | |
118 * by the autocorrelation of the weighted LTP vector. The function is | |
119 * encumbered slightly by the necessity of scaling. | |
120 * | |
121 * REFERENCE: Sub-clause 4.1.8.5 of GSM Recommendation 06.20 | |
122 * | |
123 * KEYWORDS: closed loop, LTP lag search, adaptive codebook search | |
124 * | |
125 **************************************************************************/ | |
126 | |
127 int closedLoopLagSearch(Shortword pswLagList[], int iNumLags, | |
128 Shortword pswLtpState[], Shortword pswHCoefs[], | |
129 Shortword pswPVect[], | |
130 Shortword *pswLag, Shortword *pswLtpShift) | |
131 { | |
132 | |
133 /*_________________________________________________________________________ | |
134 | | | |
135 | Automatic Variables | | |
136 |_________________________________________________________________________| | |
137 */ | |
138 | |
139 Longword L_Energy, | |
140 L_ccNorm, | |
141 L_cgNorm, | |
142 L_CrossCorr; | |
143 Longword pL_CCBuf[MAX_CANDIDATE], | |
144 pL_CGBuf[MAX_CANDIDATE]; | |
145 Shortword swCCMax, | |
146 swCCShiftCnt, | |
147 swCGShiftCnt, | |
148 swGMax, | |
149 swLTPEnergy, | |
150 swSampleA, | |
151 pswCCBuf[MAX_CANDIDATE], | |
152 pswCGBuf[MAX_CANDIDATE], | |
153 ppswTVect[N_SUB][S_LEN]; | |
154 Shortword i, | |
155 j, | |
156 siLagOffset, | |
157 siLagCode; | |
158 | |
159 /*_________________________________________________________________________ | |
160 | | | |
161 | Executable Code | | |
162 |_________________________________________________________________________| | |
163 */ | |
164 | |
165 | |
166 *pswLtpShift = 0; /* Energy in weighted ltp vector = | |
167 * [0..0x7ff] */ | |
168 for (i = 0; i < iNumLags; i++) | |
169 { | |
170 | |
171 /* Construct the excitation vector for lag i */ | |
172 /* ----------------------------------------- */ | |
173 | |
174 fp_ex(pswLagList[i], &pswLtpState[LTP_LEN]); | |
175 | |
176 /* Perform all pole filtering */ | |
177 /* -------------------------- */ | |
178 | |
179 lpcZsIir(&pswLtpState[LTP_LEN], pswHCoefs, ppswTVect[i]); | |
180 } | |
181 | |
182 /* scale the pitch vector s.t. its energy is strictly */ | |
183 /* less than 1.0 */ | |
184 /*----------------------------------------------------*/ | |
185 | |
186 swSampleA = shr(ppswTVect[0][0], 2); | |
187 L_Energy = L_mac(0x001dff4cL, swSampleA, swSampleA); | |
188 for (j = 1; j < S_LEN; j++) | |
189 { | |
190 swSampleA = shr(ppswTVect[0][j], 2); | |
191 L_Energy = L_mac(L_Energy, swSampleA, swSampleA); | |
192 } | |
193 | |
194 /* add in the energy of the first sample of the subsequent lags */ | |
195 /*--------------------------------------------------------------*/ | |
196 | |
197 for (i = 1; i < iNumLags; i++) | |
198 { | |
199 swSampleA = shr(ppswTVect[i][0], 2); | |
200 L_Energy = L_mac(L_Energy, swSampleA, swSampleA); | |
201 } | |
202 | |
203 /* An upper bound on the weighted pitch vectors energy */ | |
204 /*-----------------------------------------------------*/ | |
205 | |
206 swLTPEnergy = round(L_Energy); | |
207 | |
208 if (sub(swLTPEnergy, 0x07ff) > 0) | |
209 { /* E = (0x7ff.. 0x7fff] */ | |
210 if (sub(swLTPEnergy, 0x1fff) > 0) | |
211 { | |
212 *pswLtpShift = 2; /* E = (0x1fff..0x7fff] */ | |
213 } | |
214 else | |
215 { | |
216 *pswLtpShift = 1; /* E = (0x7ff.. 0x1fff] */ | |
217 } | |
218 | |
219 } | |
220 | |
221 for (i = 0; i < iNumLags; i++) | |
222 { | |
223 | |
224 /* shift all vectors down s.t. the largest is has energy < 1.0 */ | |
225 /*-------------------------------------------------------------*/ | |
226 | |
227 for (j = 0; j < S_LEN; j++) | |
228 ppswTVect[i][j] = shr(ppswTVect[i][j], *pswLtpShift); | |
229 | |
230 /* Calculate the energy of the subframe */ | |
231 /* ------------------------------------ */ | |
232 | |
233 L_Energy = L_mult(ppswTVect[i][0], ppswTVect[i][0]); | |
234 for (j = 1; j < S_LEN; j++) | |
235 L_Energy = L_mac(L_Energy, ppswTVect[i][j], ppswTVect[i][j]); | |
236 | |
237 pL_CGBuf[i] = L_Energy; | |
238 | |
239 /* Cross correlate the normalized speech frame and the filtered | |
240 * subframe */ | |
241 /* --------------------------------------------------------------------- | |
242 * */ | |
243 | |
244 L_CrossCorr = L_mult(ppswTVect[i][0], pswPVect[0]); | |
245 for (j = 1; j < S_LEN; j++) | |
246 L_CrossCorr = L_mac(L_CrossCorr, ppswTVect[i][j], pswPVect[j]); | |
247 | |
248 pL_CCBuf[i] = L_CrossCorr; | |
249 | |
250 } | |
251 | |
252 /* find the shift count associated with the largest CC and G */ | |
253 /* ---------------------------------------------------------- */ | |
254 L_ccNorm = L_abs(pL_CCBuf[0]); | |
255 L_cgNorm = pL_CGBuf[0]; | |
256 | |
257 for (i = 1; i < iNumLags; i++) | |
258 { | |
259 L_ccNorm |= L_abs(pL_CCBuf[i]); | |
260 L_cgNorm |= pL_CGBuf[i]; | |
261 } | |
262 | |
263 swCCShiftCnt = norm_l(L_ccNorm); | |
264 swCGShiftCnt = norm_l(L_cgNorm); | |
265 | |
266 for (i = 0; i < iNumLags; i++) | |
267 { | |
268 pswCCBuf[i] = round(L_shl(pL_CCBuf[i], swCCShiftCnt)); | |
269 pswCGBuf[i] = round(L_shl(pL_CGBuf[i], swCGShiftCnt)); | |
270 } | |
271 | |
272 /* Maximize C**2/G */ | |
273 /* --------------- */ | |
274 siLagOffset = maxCCOverGWithSign(pswCCBuf, pswCGBuf, | |
275 &swCCMax, &swGMax, | |
276 iNumLags); | |
277 | |
278 /* Determine the offset of the max value into CC buffer */ | |
279 /* ---------------------------------------------------- */ | |
280 *pswLag = pswLagList[siLagOffset]; | |
281 | |
282 /* Store Lag Code for best lag result */ | |
283 /* ---------------------------------- */ | |
284 quantLag(*pswLag, &siLagCode); | |
285 | |
286 return (siLagCode); | |
287 } | |
288 | |
289 /***************************************************************************** | |
290 * | |
291 * FUNCTION NAME: decorr | |
292 * | |
293 * PURPOSE: Decorrelates(orthogonalizes) a set of vectors from a given | |
294 * vector. | |
295 * | |
296 * | |
297 * INPUTS: iNumVects - number of vectors to decorrelate | |
298 * pswGivenVect[0..39] - array of given vectors | |
299 * pswVects[0..359] (voice) [0..279] (unvoiced) - array of | |
300 * contiguous vectors to be decorrelated | |
301 * OUTPUTS: pswVects[0..359] (voice) [0..279] (unvoiced) - output vectors | |
302 * are written back over input vectors | |
303 * | |
304 * RETURN VALUE: none | |
305 * | |
306 * IMPLEMENTATION: | |
307 * | |
308 * REFERENCE: Sub-clause 4.1.10.1 of GSM Recommendation 06.20 | |
309 * | |
310 * KEYWORDS: decorrelate, codewords, codevectors, orthogonalize, encoder | |
311 * | |
312 ****************************************************************************/ | |
313 | |
314 void decorr(int iNumVects, Shortword pswGivenVect[], | |
315 Shortword pswVects[]) | |
316 { | |
317 | |
318 /*___________________________________________________________________________ | |
319 | | | |
320 | Automatic Variables | | |
321 |___________________________________________________________________________| | |
322 */ | |
323 int i, | |
324 iLoopCnt; | |
325 Shortword swNorm_energy, | |
326 swTemp; | |
327 Shortword swEShift, | |
328 swCShift, | |
329 swShiftSum, | |
330 swQShift; | |
331 Longword L_Energy, | |
332 L_Temp1, | |
333 L_Temp2, | |
334 L_Accum; | |
335 | |
336 /*___________________________________________________________________________ | |
337 | | | |
338 | Executable Code | | |
339 |___________________________________________________________________________| | |
340 */ | |
341 | |
342 /* Compute normalized energy in given vector */ | |
343 /*-------------------------------------------*/ | |
344 swEShift = g_corr1(pswGivenVect, &L_Energy); | |
345 swNorm_energy = extract_h(L_Energy); | |
346 | |
347 if (swNorm_energy == 0) | |
348 { | |
349 return; | |
350 } | |
351 | |
352 /* Decorrelate vectors */ | |
353 /*---------------------*/ | |
354 | |
355 for (iLoopCnt = 0; iLoopCnt < iNumVects; iLoopCnt++) | |
356 { | |
357 | |
358 swCShift = g_corr2(pswGivenVect, &pswVects[iLoopCnt * S_LEN], | |
359 &L_Temp1); | |
360 L_Temp2 = L_Temp1; | |
361 L_Temp1 = L_abs(L_Temp1); | |
362 swCShift = sub(swCShift, 1); | |
363 swShiftSum = sub(swCShift, swEShift); | |
364 L_Temp1 = L_shr(L_Temp1, 1); | |
365 swTemp = divide_s(round(L_Temp1), swNorm_energy); | |
366 | |
367 if (L_Temp2 > 0) | |
368 swTemp = negate(swTemp); | |
369 | |
370 swQShift = norm_s(swTemp); | |
371 swTemp = shl(swTemp, swQShift); | |
372 swQShift = add(swShiftSum, swQShift); | |
373 | |
374 if (swQShift > 0) | |
375 { | |
376 swTemp = shift_r(swTemp, negate(swQShift)); | |
377 swQShift = 0; | |
378 } | |
379 else | |
380 swQShift = negate(swQShift); | |
381 | |
382 for (i = 0; i < S_LEN; i++) | |
383 { | |
384 L_Accum = L_msu(0x00008000L, pswVects[i + iLoopCnt * S_LEN], SW_MIN); | |
385 pswVects[iLoopCnt * S_LEN + i] = extract_h(L_mac(L_Accum, swTemp, | |
386 shl(pswGivenVect[i], swQShift))); | |
387 } | |
388 } | |
389 } | |
390 | |
391 /*************************************************************************** | |
392 * | |
393 * FUNCTION NAME: g_corr2 | |
394 * | |
395 * PURPOSE: Calculates correlation between subframe vectors. | |
396 * | |
397 * | |
398 * INPUT: | |
399 * | |
400 * pswIn[0:39] | |
401 * A subframe vector. | |
402 * | |
403 * pswIn2[0:39] | |
404 * A subframe vector. | |
405 * | |
406 * | |
407 * OUTPUT: | |
408 * | |
409 * *pL_out | |
410 * A Longword containing the normalized correlation | |
411 * between the input vectors. | |
412 * | |
413 * RETURN: | |
414 * | |
415 * swOut | |
416 * Number of right shifts which the accumulator was | |
417 * shifted to normalize it. Negative number implies | |
418 * a left shift, and therefore an energy larger than | |
419 * 1.0. | |
420 * | |
421 * REFERENCE: Sub-clauses 4.1.10.1 and 4.1.11.1 of GSM | |
422 * Recommendation 06.20 | |
423 * | |
424 * keywords: energy, autocorrelation, correlation, g_corr2 | |
425 * | |
426 * | |
427 **************************************************************************/ | |
428 | |
429 Shortword g_corr2(Shortword *pswIn, Shortword *pswIn2, | |
430 Longword *pL_out) | |
431 { | |
432 | |
433 /*_________________________________________________________________________ | |
434 | | | |
435 | Automatic Variables | | |
436 |_________________________________________________________________________| | |
437 */ | |
438 | |
439 Longword L_sum; | |
440 Shortword swEngyLShft; | |
441 int i; | |
442 | |
443 /*_________________________________________________________________________ | |
444 | | | |
445 | Executable Code | | |
446 |_________________________________________________________________________| | |
447 */ | |
448 | |
449 /* Calculate energy in subframe vector (40 samples) */ | |
450 /*--------------------------------------------------*/ | |
451 | |
452 L_sum = L_mult(pswIn[0], pswIn2[0]); | |
453 for (i = 1; i < S_LEN; i++) | |
454 { | |
455 L_sum = L_mac(L_sum, pswIn[i], pswIn2[i]); | |
456 } | |
457 | |
458 | |
459 | |
460 if (L_sum != 0) | |
461 { | |
462 | |
463 /* Normalize the energy in the output Longword */ | |
464 /*---------------------------------------------*/ | |
465 | |
466 swEngyLShft = norm_l(L_sum); | |
467 *pL_out = L_shl(L_sum, swEngyLShft); /* normalize output | |
468 * Longword */ | |
469 } | |
470 else | |
471 { | |
472 | |
473 /* Special case: energy is zero */ | |
474 /*------------------------------*/ | |
475 | |
476 *pL_out = L_sum; | |
477 swEngyLShft = 0; | |
478 } | |
479 | |
480 return (swEngyLShft); | |
481 } | |
482 | |
483 /*************************************************************************** | |
484 * | |
485 * FUNCTION NAME: g_quant_vl | |
486 * | |
487 * PURPOSE: | |
488 * | |
489 * Joint quantization of excitation gains. | |
490 * GS represents the subframe energy relative to the frame energy. | |
491 * P0 represents the relative contribution of the first exctitation | |
492 * source to the total excitation. | |
493 * | |
494 * INPUTS: | |
495 * | |
496 * swUVCode - voicing level (Mode 0-3) | |
497 * pswWInput[0:39] - weighted input p(n) (used in mode 0-3) | |
498 * swWIShift - weighted input shift factor (right shift, 0,1, or 2) | |
499 * pswWLTPVec[0:39] - weighted pitch excitation vector (used in mode 1-3) | |
500 * pswWVSVec1[0:39] - weighted 1st v-s codevector (used in mode 0-3) | |
501 * pswWVSVec2[0:39] - weighted 2nd v-s codevector (used in mode 0) | |
502 * snsRs00 - square root of RS/pitch excitation energy (used in mode 1-3) | |
503 * snsRs11 - square root of RS/1st v-s codevector energy | |
504 * (used in mode 0-3) | |
505 * snsRs22 - square root of RS/2nd v-s codevector energy (used in mode 0) | |
506 * | |
507 * pppsrGsp0[0:3][0:31][0:4] - lookup table | |
508 * | |
509 * OUTPUTS: | |
510 * | |
511 * None | |
512 * | |
513 * RETURN VALUE: | |
514 * | |
515 * siCode - output quantized gain code (5 bits) | |
516 * | |
517 * IMPLEMENTATION: | |
518 * | |
519 * Calculates first the parameters required for error equation 7.21: | |
520 * | |
521 * Rcc(k,j) k = 0,1, j=k,1 | |
522 * Rx(k) k = 0,1 | |
523 * RS | |
524 * Rpc(k) k = 0,1 | |
525 * a,b,c,d,e | |
526 * | |
527 * The constant terms in equation 7.21 are stored in ROM instead of GS | |
528 * and P0. There is one vector quantizer for each voicing state. | |
529 * | |
530 * REFERENCE: Sub-clause 4.1.11 and 4.1.11.1 of GSM Recommendation 06.20 | |
531 * | |
532 * KEYWORDS: gain quantization, energy domain transforms, p0, gs | |
533 * | |
534 **************************************************************************/ | |
535 | |
536 Shortword g_quant_vl(Shortword swUVCode, | |
537 Shortword pswWInput[], Shortword swWIShift, | |
538 Shortword pswWLTPVec[], | |
539 Shortword pswWVSVec1[], Shortword pswWVSVec2[], | |
540 struct NormSw snsRs00, struct NormSw snsRs11, | |
541 struct NormSw snsRs22) | |
542 { | |
543 | |
544 /*_________________________________________________________________________ | |
545 | | | |
546 | Automatic Variables | | |
547 |_________________________________________________________________________| | |
548 */ | |
549 | |
550 Longword L_Temp, | |
551 L_Temp2; | |
552 Shortword swShift; | |
553 struct NormSw ErrorTerm[6]; | |
554 Shortword i, | |
555 siCode, | |
556 siNormShift, | |
557 siNormMin; | |
558 | |
559 /*_________________________________________________________________________ | |
560 | | | |
561 | Executable Code | | |
562 |_________________________________________________________________________| | |
563 */ | |
564 | |
565 /* Test voicing level, mode 0-3 */ | |
566 /* ---------------------------- */ | |
567 | |
568 if (swUVCode == 0) | |
569 { | |
570 | |
571 /* Unvoiced */ | |
572 /* -------- */ | |
573 | |
574 /* Compute cross correlation Rpc(0) */ | |
575 /* -------------------------------- */ | |
576 | |
577 | |
578 ErrorTerm[0].sh = g_corr2(pswWInput, pswWVSVec1, &L_Temp); | |
579 ErrorTerm[0].man = round(L_Temp); | |
580 | |
581 /* Compute cross correlation Rpc(1) */ | |
582 /* -------------------------------- */ | |
583 | |
584 ErrorTerm[1].sh = g_corr2(pswWInput, pswWVSVec2, &L_Temp); | |
585 ErrorTerm[1].man = round(L_Temp); | |
586 | |
587 /* Compute cross correlation Rcc(0,1) */ | |
588 /* ---------------------------------- */ | |
589 | |
590 | |
591 ErrorTerm[2].sh = g_corr2(pswWVSVec1, pswWVSVec2, &L_Temp); | |
592 ErrorTerm[2].man = round(L_Temp); | |
593 | |
594 /* Compute correlation Rcc(0,0) */ | |
595 /* ---------------------------- */ | |
596 | |
597 ErrorTerm[3].sh = g_corr1(pswWVSVec1, &L_Temp); | |
598 ErrorTerm[3].man = round(L_Temp); | |
599 | |
600 /* Compute correlation Rcc(1,1) */ | |
601 /* ---------------------------- */ | |
602 | |
603 ErrorTerm[4].sh = g_corr1(pswWVSVec2, &L_Temp); | |
604 ErrorTerm[4].man = round(L_Temp); | |
605 | |
606 /* Compute correlation Rpp */ | |
607 /* ----------------------- */ | |
608 | |
609 ErrorTerm[5].sh = g_corr1(pswWInput, &L_Temp); | |
610 ErrorTerm[5].man = round(L_Temp); | |
611 | |
612 /* Compute gain tweak factor, adjusts A and B error coefs */ | |
613 /* ------------------------------------------------------ */ | |
614 gainTweak(&ErrorTerm[0]); | |
615 | |
616 /* Compute error coefficient A, equation 5.22 */ | |
617 /* ------------------------------------------ */ | |
618 | |
619 L_Temp = L_mult(ErrorTerm[0].man, snsRs11.man); | |
620 swShift = norm_s(extract_h(L_Temp)); | |
621 ErrorTerm[0].sh = add(ErrorTerm[0].sh, swShift); | |
622 ErrorTerm[0].man = round(L_shl(L_Temp, swShift)); | |
623 ErrorTerm[0].sh = add(ErrorTerm[0].sh, snsRs11.sh); | |
624 siNormMin = ErrorTerm[0].sh; | |
625 | |
626 /* Compute error coefficient B, equation 5.23 */ | |
627 /* ------------------------------------------ */ | |
628 | |
629 L_Temp = L_mult(ErrorTerm[1].man, snsRs22.man); | |
630 swShift = norm_s(extract_h(L_Temp)); | |
631 ErrorTerm[1].sh = add(ErrorTerm[1].sh, swShift); | |
632 ErrorTerm[1].man = round(L_shl(L_Temp, swShift)); | |
633 ErrorTerm[1].sh = add(ErrorTerm[1].sh, snsRs22.sh); | |
634 if (sub(ErrorTerm[1].sh, siNormMin) < 0) | |
635 siNormMin = ErrorTerm[1].sh; | |
636 | |
637 /* Compute error coefficient C, equation 5.24 */ | |
638 /* ------------------------------------------ */ | |
639 | |
640 L_Temp = L_mult(ErrorTerm[2].man, snsRs11.man); | |
641 swShift = norm_s(extract_h(L_Temp)); | |
642 ErrorTerm[2].sh = add(ErrorTerm[2].sh, swShift); | |
643 ErrorTerm[2].man = round(L_shl(L_Temp, swShift)); | |
644 L_Temp = L_mult(ErrorTerm[2].man, snsRs22.man); | |
645 swShift = norm_s(extract_h(L_Temp)); | |
646 ErrorTerm[2].sh = add(ErrorTerm[2].sh, swShift); | |
647 ErrorTerm[2].man = round(L_shl(L_Temp, swShift)); | |
648 ErrorTerm[2].sh = add(ErrorTerm[2].sh, snsRs11.sh); | |
649 ErrorTerm[2].sh = add(ErrorTerm[2].sh, snsRs22.sh); | |
650 ErrorTerm[2].sh = add(ErrorTerm[2].sh, swWIShift); | |
651 if (sub(ErrorTerm[2].sh, siNormMin) < 0) | |
652 siNormMin = ErrorTerm[2].sh; | |
653 | |
654 /* Compute error coefficient D, equation 5.25 */ | |
655 /* ------------------------------------------ */ | |
656 | |
657 L_Temp = L_mult(ErrorTerm[3].man, snsRs11.man); | |
658 swShift = norm_s(extract_h(L_Temp)); | |
659 ErrorTerm[3].sh = add(ErrorTerm[3].sh, swShift); | |
660 ErrorTerm[3].man = round(L_shl(L_Temp, swShift)); | |
661 L_Temp = L_mult(ErrorTerm[3].man, snsRs11.man); | |
662 swShift = norm_s(extract_h(L_Temp)); | |
663 ErrorTerm[3].sh = add(ErrorTerm[3].sh, swShift); | |
664 ErrorTerm[3].man = round(L_shl(L_Temp, swShift)); | |
665 ErrorTerm[3].sh = add(ErrorTerm[3].sh, snsRs11.sh); | |
666 ErrorTerm[3].sh = add(ErrorTerm[3].sh, snsRs11.sh); | |
667 ErrorTerm[3].sh = add(ErrorTerm[3].sh, swWIShift); | |
668 | |
669 if (sub(ErrorTerm[3].sh, siNormMin) < 0) | |
670 siNormMin = ErrorTerm[3].sh; | |
671 | |
672 /* Compute error coefficient E, equation 5.26 */ | |
673 /* ------------------------------------------ */ | |
674 | |
675 L_Temp = L_mult(ErrorTerm[4].man, snsRs22.man); | |
676 swShift = norm_s(extract_h(L_Temp)); | |
677 ErrorTerm[4].sh = add(ErrorTerm[4].sh, swShift); | |
678 ErrorTerm[4].man = round(L_shl(L_Temp, swShift)); | |
679 L_Temp = L_mult(ErrorTerm[4].man, snsRs22.man); | |
680 swShift = norm_s(extract_h(L_Temp)); | |
681 ErrorTerm[4].sh = add(ErrorTerm[4].sh, swShift); | |
682 ErrorTerm[4].man = round(L_shl(L_Temp, swShift)); | |
683 ErrorTerm[4].sh = add(ErrorTerm[4].sh, snsRs22.sh); | |
684 ErrorTerm[4].sh = add(ErrorTerm[4].sh, snsRs22.sh); | |
685 ErrorTerm[4].sh = add(ErrorTerm[4].sh, swWIShift); | |
686 | |
687 if (sub(ErrorTerm[4].sh, siNormMin) < 0) | |
688 siNormMin = ErrorTerm[4].sh; | |
689 | |
690 } | |
691 | |
692 else | |
693 { /* Voicing level */ | |
694 | |
695 /* Voiced */ | |
696 /* ------ */ | |
697 | |
698 /* Compute cross correlation Rpc(0) */ | |
699 /* -------------------------------- */ | |
700 | |
701 | |
702 ErrorTerm[0].sh = g_corr2(pswWInput, pswWLTPVec, &L_Temp); | |
703 ErrorTerm[0].man = round(L_Temp); | |
704 | |
705 /* Compute cross correlation Rpc(1) */ | |
706 /* -------------------------------- */ | |
707 | |
708 | |
709 ErrorTerm[1].sh = g_corr2(pswWInput, pswWVSVec1, &L_Temp); | |
710 ErrorTerm[1].man = round(L_Temp); | |
711 | |
712 /* Compute cross correlation Rcc(0,1) */ | |
713 /* ---------------------------------- */ | |
714 | |
715 | |
716 ErrorTerm[2].sh = g_corr2(pswWLTPVec, pswWVSVec1, &L_Temp); | |
717 ErrorTerm[2].man = round(L_Temp); | |
718 | |
719 /* Compute correlation Rcc(0,0) */ | |
720 /* ---------------------------- */ | |
721 | |
722 ErrorTerm[3].sh = g_corr1(pswWLTPVec, &L_Temp); | |
723 ErrorTerm[3].man = round(L_Temp); | |
724 | |
725 /* Compute correlation Rcc(1,1) */ | |
726 /* ---------------------------- */ | |
727 | |
728 ErrorTerm[4].sh = g_corr1(pswWVSVec1, &L_Temp); | |
729 ErrorTerm[4].man = round(L_Temp); | |
730 | |
731 /* Compute correlation Rpp */ | |
732 /* ----------------------- */ | |
733 | |
734 ErrorTerm[5].sh = g_corr1(pswWInput, &L_Temp); | |
735 ErrorTerm[5].man = round(L_Temp); | |
736 | |
737 /* Compute gain tweak factor, adjusts A and B error coefs */ | |
738 /* ------------------------------------------------------ */ | |
739 | |
740 gainTweak(&ErrorTerm[0]); | |
741 | |
742 /* Compute error coefficient A, equation 5.22 */ | |
743 /* ------------------------------------------ */ | |
744 | |
745 L_Temp = L_mult(ErrorTerm[0].man, snsRs00.man); | |
746 swShift = norm_s(extract_h(L_Temp)); | |
747 ErrorTerm[0].sh = add(ErrorTerm[0].sh, swShift); | |
748 ErrorTerm[0].man = round(L_shl(L_Temp, swShift)); | |
749 ErrorTerm[0].sh = add(ErrorTerm[0].sh, snsRs00.sh); | |
750 siNormMin = ErrorTerm[0].sh; | |
751 | |
752 /* Compute error coefficient B, equation 5.23 */ | |
753 /* ------------------------------------------ */ | |
754 | |
755 L_Temp = L_mult(ErrorTerm[1].man, snsRs11.man); | |
756 swShift = norm_s(extract_h(L_Temp)); | |
757 ErrorTerm[1].sh = add(ErrorTerm[1].sh, swShift); | |
758 ErrorTerm[1].man = round(L_shl(L_Temp, swShift)); | |
759 ErrorTerm[1].sh = add(ErrorTerm[1].sh, snsRs11.sh); | |
760 if (sub(ErrorTerm[1].sh, siNormMin) < 0) | |
761 siNormMin = ErrorTerm[1].sh; | |
762 | |
763 /* Compute error coefficient C, equation 5.24 */ | |
764 /* ------------------------------------------ */ | |
765 | |
766 L_Temp = L_mult(ErrorTerm[2].man, snsRs00.man); | |
767 swShift = norm_s(extract_h(L_Temp)); | |
768 ErrorTerm[2].sh = add(ErrorTerm[2].sh, swShift); | |
769 ErrorTerm[2].man = round(L_shl(L_Temp, swShift)); | |
770 L_Temp = L_mult(ErrorTerm[2].man, snsRs11.man); | |
771 swShift = norm_s(extract_h(L_Temp)); | |
772 ErrorTerm[2].sh = add(ErrorTerm[2].sh, swShift); | |
773 ErrorTerm[2].man = round(L_shl(L_Temp, swShift)); | |
774 ErrorTerm[2].sh = add(ErrorTerm[2].sh, snsRs00.sh); | |
775 ErrorTerm[2].sh = add(ErrorTerm[2].sh, snsRs11.sh); | |
776 ErrorTerm[2].sh = add(ErrorTerm[2].sh, swWIShift); | |
777 if (sub(ErrorTerm[2].sh, siNormMin) < 0) | |
778 siNormMin = ErrorTerm[2].sh; | |
779 | |
780 /* Compute error coefficient D, equation 5.25 */ | |
781 /* ------------------------------------------ */ | |
782 | |
783 L_Temp = L_mult(ErrorTerm[3].man, snsRs00.man); | |
784 swShift = norm_s(extract_h(L_Temp)); | |
785 ErrorTerm[3].sh = add(ErrorTerm[3].sh, swShift); | |
786 ErrorTerm[3].man = round(L_shl(L_Temp, swShift)); | |
787 L_Temp = L_mult(ErrorTerm[3].man, snsRs00.man); | |
788 swShift = norm_s(extract_h(L_Temp)); | |
789 ErrorTerm[3].sh = add(ErrorTerm[3].sh, swShift); | |
790 ErrorTerm[3].man = round(L_shl(L_Temp, swShift)); | |
791 ErrorTerm[3].sh = add(ErrorTerm[3].sh, snsRs00.sh); | |
792 ErrorTerm[3].sh = add(ErrorTerm[3].sh, snsRs00.sh); | |
793 ErrorTerm[3].sh = add(ErrorTerm[3].sh, swWIShift); | |
794 if (sub(ErrorTerm[3].sh, siNormMin) < 0) | |
795 siNormMin = ErrorTerm[3].sh; | |
796 | |
797 /* Compute error coefficient E, equation 5.26 */ | |
798 /* ------------------------------------------ */ | |
799 | |
800 L_Temp = L_mult(ErrorTerm[4].man, snsRs11.man); | |
801 swShift = norm_s(extract_h(L_Temp)); | |
802 ErrorTerm[4].sh = add(ErrorTerm[4].sh, swShift); | |
803 ErrorTerm[4].man = round(L_shl(L_Temp, swShift)); | |
804 L_Temp = L_mult(ErrorTerm[4].man, snsRs11.man); | |
805 swShift = norm_s(extract_h(L_Temp)); | |
806 ErrorTerm[4].sh = add(ErrorTerm[4].sh, swShift); | |
807 ErrorTerm[4].man = round(L_shl(L_Temp, swShift)); | |
808 ErrorTerm[4].sh = add(ErrorTerm[4].sh, snsRs11.sh); | |
809 ErrorTerm[4].sh = add(ErrorTerm[4].sh, snsRs11.sh); | |
810 ErrorTerm[4].sh = add(ErrorTerm[4].sh, swWIShift); | |
811 if (sub(ErrorTerm[4].sh, siNormMin) < 0) | |
812 siNormMin = ErrorTerm[4].sh; | |
813 | |
814 } /* Voicing level */ | |
815 | |
816 | |
817 | |
818 /* Normalize all error coefficients to same shift count */ | |
819 /* ---------------------------------------------------- */ | |
820 | |
821 for (i = 0; i < GSP0_VECTOR_SIZE; i++) | |
822 { | |
823 L_Temp = L_deposit_h(ErrorTerm[i].man); | |
824 siNormShift = sub(ErrorTerm[i].sh, siNormMin); | |
825 if (siNormShift > 0) | |
826 L_Temp = L_shr(L_Temp, siNormShift); | |
827 ErrorTerm[i].man = round(L_Temp); | |
828 } | |
829 | |
830 | |
831 /* Codebook search, find max of error equation 5.21 */ | |
832 /* ------------------------------------------------ */ | |
833 | |
834 L_Temp2 = 0x80000000; | |
835 | |
836 for (i = 0; i < GSP0_NUM; i++) | |
837 { | |
838 | |
839 L_Temp = L_mult(pppsrGsp0[swUVCode][i][0], ErrorTerm[0].man); | |
840 L_Temp = L_mac(L_Temp, pppsrGsp0[swUVCode][i][1], ErrorTerm[1].man); | |
841 L_Temp = L_mac(L_Temp, pppsrGsp0[swUVCode][i][2], ErrorTerm[2].man); | |
842 L_Temp = L_mac(L_Temp, pppsrGsp0[swUVCode][i][3], ErrorTerm[3].man); | |
843 L_Temp = L_mac(L_Temp, pppsrGsp0[swUVCode][i][4], ErrorTerm[4].man); | |
844 if (L_sub(L_Temp2, L_Temp) < 0) | |
845 { | |
846 L_Temp2 = L_Temp; | |
847 siCode = i; /* Save best code */ | |
848 } | |
849 } | |
850 return (siCode); | |
851 } | |
852 | |
853 /*************************************************************************** | |
854 * | |
855 * FUNCTION NAME: gainTweak | |
856 * | |
857 * PURPOSE: | |
858 * | |
859 * Calculates gain bias factor, limits it, and | |
860 * applies it to A and B error coefficients. | |
861 * | |
862 * INPUTS: | |
863 * | |
864 * psErrorTerm[0:5] - array (6) of error coefficients in floating | |
865 * point format | |
866 * | |
867 * OUTPUTS: | |
868 * | |
869 * psErrorTerm[0:5] - array of gain adjusted A and B error coefficients | |
870 * | |
871 * RETURN VALUE: | |
872 * | |
873 * None | |
874 * | |
875 * IMPLEMENTATION: | |
876 * | |
877 * The gain tweak is: | |
878 * | |
879 * Rpp*Rcc(0,0)*Rcc(1,1) - Rpp*Rcc(0,1)*Rcc(0,1) | |
880 *sqrt(---------------------------------------------------------------------) | |
881 * Rcc(0,0)*Rpc(1)*Rpc(1)-2*Rcc(0,1)*Rpc(0)*Rpc(1)+Rcc(1,1)*Rpc(0)*Rpc(0) | |
882 * | |
883 * REFERENCE: Sub-clause 4.1.11.1 of GSM Recommendation 06.20 | |
884 * | |
885 * KEYWORDS: gain tweak, g_quant_vl | |
886 * | |
887 **************************************************************************/ | |
888 | |
889 void gainTweak(struct NormSw *psErrorTerm) | |
890 { | |
891 | |
892 /*_________________________________________________________________________ | |
893 | | | |
894 | Automatic Variables | | |
895 |_________________________________________________________________________| | |
896 */ | |
897 | |
898 Longword L_Temp; | |
899 Shortword swTemp, | |
900 swNum, | |
901 swDenom, | |
902 swGainTweak, | |
903 swShift; | |
904 struct NormSw terms[5]; | |
905 Shortword i, | |
906 siNormShift, | |
907 siNorm; | |
908 | |
909 /*_________________________________________________________________________ | |
910 | | | |
911 | Executable Code | | |
912 |_________________________________________________________________________| | |
913 */ | |
914 | |
915 /* Calculate third order terms in the gain tweak factor, while | |
916 * maintaining the largest exponent */ | |
917 /* ---------------------------------------------------- */ | |
918 | |
919 /* Compute Rpp*Rcc(0,0)*Rcc(1,1) */ | |
920 /* ----------------------------- */ | |
921 | |
922 L_Temp = L_mult(psErrorTerm[3].man, psErrorTerm[5].man); | |
923 swShift = norm_s(extract_h(L_Temp)); | |
924 terms[0].sh = add(psErrorTerm[3].sh, swShift); | |
925 terms[0].man = round(L_shl(L_Temp, swShift)); | |
926 L_Temp = L_mult(terms[0].man, psErrorTerm[4].man); | |
927 swShift = norm_s(extract_h(L_Temp)); | |
928 terms[0].sh = add(terms[0].sh, swShift); | |
929 terms[0].man = round(L_shl(L_Temp, swShift)); | |
930 terms[0].sh = add(terms[0].sh, psErrorTerm[4].sh); | |
931 terms[0].sh = add(terms[0].sh, psErrorTerm[5].sh); | |
932 /* Init. siNorm */ | |
933 siNorm = terms[0].sh; | |
934 | |
935 /* Compute Rpp*Rcc(0,1)*Rcc(0,1) */ | |
936 /* ----------------------------- */ | |
937 | |
938 L_Temp = L_mult(psErrorTerm[2].man, psErrorTerm[2].man); | |
939 swShift = norm_s(extract_h(L_Temp)); | |
940 terms[1].sh = add(psErrorTerm[2].sh, swShift); | |
941 terms[1].man = round(L_shl(L_Temp, swShift)); | |
942 L_Temp = L_mult(terms[1].man, psErrorTerm[5].man); | |
943 swShift = norm_s(extract_h(L_Temp)); | |
944 terms[1].sh = add(terms[1].sh, swShift); | |
945 terms[1].man = round(L_shl(L_Temp, swShift)); | |
946 terms[1].sh = add(terms[1].sh, psErrorTerm[2].sh); | |
947 terms[1].sh = add(terms[1].sh, psErrorTerm[5].sh); | |
948 if (sub(terms[1].sh, siNorm) < 0) | |
949 siNorm = terms[1].sh; | |
950 | |
951 /* Compute Rcc(0,0)*Rpc(1)*Rpc(1) */ | |
952 /* ------------------------------ */ | |
953 | |
954 L_Temp = L_mult(psErrorTerm[1].man, psErrorTerm[1].man); | |
955 swShift = norm_s(extract_h(L_Temp)); | |
956 terms[2].sh = add(psErrorTerm[1].sh, swShift); | |
957 terms[2].man = round(L_shl(L_Temp, swShift)); | |
958 L_Temp = L_mult(terms[2].man, psErrorTerm[3].man); | |
959 swShift = norm_s(extract_h(L_Temp)); | |
960 terms[2].sh = add(terms[2].sh, swShift); | |
961 terms[2].man = round(L_shl(L_Temp, swShift)); | |
962 terms[2].sh = add(terms[2].sh, psErrorTerm[1].sh); | |
963 terms[2].sh = add(terms[2].sh, psErrorTerm[3].sh); | |
964 if (sub(terms[2].sh, siNorm) < 0) | |
965 siNorm = terms[2].sh; | |
966 | |
967 /* Compute 2*Rcc(0,1)*Rpc(0)*Rpc(1) */ | |
968 /* -------------------------------- */ | |
969 | |
970 L_Temp = L_mult(psErrorTerm[0].man, psErrorTerm[1].man); | |
971 swShift = norm_s(extract_h(L_Temp)); | |
972 terms[3].sh = add(psErrorTerm[0].sh, swShift); | |
973 terms[3].man = round(L_shl(L_Temp, swShift)); | |
974 L_Temp = L_mult(terms[3].man, psErrorTerm[2].man); | |
975 swShift = norm_s(extract_h(L_Temp)); | |
976 terms[3].sh = add(terms[3].sh, swShift); | |
977 terms[3].man = round(L_shl(L_Temp, swShift)); | |
978 terms[3].sh = add(terms[3].sh, psErrorTerm[1].sh); | |
979 terms[3].sh = add(terms[3].sh, psErrorTerm[2].sh); | |
980 terms[3].sh = sub(terms[3].sh, 1); /* Multiply by 2 */ | |
981 if (sub(terms[3].sh, siNorm) < 0) | |
982 siNorm = terms[3].sh; | |
983 | |
984 /* Compute Rcc(1,1)*Rpc(0)*Rpc(0) */ | |
985 /* ------------------------------ */ | |
986 | |
987 L_Temp = L_mult(psErrorTerm[0].man, psErrorTerm[4].man); | |
988 swShift = norm_s(extract_h(L_Temp)); | |
989 terms[4].sh = add(psErrorTerm[0].sh, swShift); | |
990 terms[4].man = round(L_shl(L_Temp, swShift)); | |
991 L_Temp = L_mult(terms[4].man, psErrorTerm[0].man); | |
992 swShift = norm_s(extract_h(L_Temp)); | |
993 terms[4].sh = add(terms[4].sh, swShift); | |
994 terms[4].man = round(L_shl(L_Temp, swShift)); | |
995 terms[4].sh = add(terms[4].sh, psErrorTerm[0].sh); | |
996 terms[4].sh = add(terms[4].sh, psErrorTerm[4].sh); | |
997 if (sub(terms[4].sh, siNorm) < 0) | |
998 siNorm = terms[4].sh; | |
999 | |
1000 /* Normalize all terms to same shift count */ | |
1001 /* --------------------------------------- */ | |
1002 | |
1003 for (i = 0; i < 5; i++) | |
1004 { | |
1005 L_Temp = L_deposit_h(terms[i].man); | |
1006 siNormShift = sub(terms[i].sh, siNorm); | |
1007 if (siNormShift > 0) | |
1008 { | |
1009 L_Temp = L_shr(L_Temp, siNormShift); | |
1010 } | |
1011 terms[i].man = round(L_Temp); | |
1012 } | |
1013 | |
1014 /* Calculate numerator */ | |
1015 /* ------------------- */ | |
1016 | |
1017 /* Rpp*Rcc(0,0)*Rcc(1,1) - Rpp*Rcc(0,1)*Rcc(0,1) */ | |
1018 /* --------------------------------------------- */ | |
1019 | |
1020 swNum = sub(terms[0].man, terms[1].man); | |
1021 | |
1022 /* Skip gain tweak if numerator =< 0 */ | |
1023 /* --------------------------------- */ | |
1024 | |
1025 if (swNum <= 0) | |
1026 return; | |
1027 | |
1028 /* Calculate denominator */ | |
1029 /* --------------------- */ | |
1030 | |
1031 /* Rcc(0,0)*Rpc(1)*Rpc(1)-2*Rcc(0,1)*Rpc(0)*Rpc(1)+Rcc(1,1)*Rpc(0)*Rpc(0) */ | |
1032 /*----------------------------------------------------------------------*/ | |
1033 | |
1034 swDenom = sub(terms[2].man, terms[3].man); | |
1035 swDenom = add(swDenom, terms[4].man); | |
1036 | |
1037 /* Skip gain tweak if denominator =< 0 */ | |
1038 /* ----------------------------------- */ | |
1039 | |
1040 if (swDenom <= 0) | |
1041 return; | |
1042 | |
1043 /* Compare numerator to denominator, skip if tweak =< 1 */ | |
1044 /* ---------------------------------------------------- */ | |
1045 | |
1046 swTemp = sub(swNum, swDenom); | |
1047 if (swTemp <= 0) | |
1048 return; | |
1049 | |
1050 /* Normalize and do divide */ | |
1051 /* ----------------------- */ | |
1052 | |
1053 swShift = norm_s(swNum); | |
1054 siNormShift = sub(swShift, 1); /* Multiply by 2 */ | |
1055 swNum = shl(swNum, swShift); | |
1056 swNum = shr(swNum, 1); | |
1057 swShift = norm_s(swDenom); | |
1058 siNormShift = sub(siNormShift, swShift); | |
1059 swDenom = shl(swDenom, swShift); | |
1060 swTemp = divide_s(swNum, swDenom); | |
1061 swShift = norm_s(swTemp); | |
1062 siNormShift = add(siNormShift, swShift); | |
1063 L_Temp = L_shl(L_deposit_h(swTemp), swShift); | |
1064 | |
1065 /* Calculate square root */ | |
1066 /* --------------------- */ | |
1067 | |
1068 swTemp = sqroot(L_Temp); | |
1069 | |
1070 /* If odd no. of shifts compensate by sqrt(0.5) */ | |
1071 /* -------------------------------------------- */ | |
1072 | |
1073 if (siNormShift & 1) | |
1074 { | |
1075 L_Temp = L_mult(0x5a82, swTemp); | |
1076 siNormShift = sub(siNormShift, 1); | |
1077 } | |
1078 else | |
1079 L_Temp = L_deposit_h(swTemp); | |
1080 siNormShift = shr(siNormShift, 1); | |
1081 swShift = norm_s(extract_h(L_Temp)); | |
1082 siNormShift = add(siNormShift, swShift); | |
1083 swGainTweak = round(L_shl(L_Temp, swShift)); | |
1084 | |
1085 /* If exponent > -1, skip gain tweak */ | |
1086 /* --------------------------------- */ | |
1087 | |
1088 if (add(1, siNormShift) > 0) | |
1089 return; | |
1090 | |
1091 /* If exponent < -1, limit gain tweak to GTWEAKMAX */ | |
1092 /* ----------------------------------------------- */ | |
1093 | |
1094 if (add(1, siNormShift) < 0) | |
1095 swGainTweak = GTWEAKMAX; | |
1096 else | |
1097 { | |
1098 | |
1099 /* If exponent = -1, compare to GTWEAKMAX */ | |
1100 /* -------------------------------------- */ | |
1101 | |
1102 if (sub(GTWEAKMAX, swGainTweak) < 0) | |
1103 swGainTweak = GTWEAKMAX; | |
1104 } | |
1105 | |
1106 /* Multiply gain tweak factor on A and B error terms */ | |
1107 /* ------------------------------------------------- */ | |
1108 | |
1109 L_Temp = L_mult(swGainTweak, psErrorTerm[0].man); | |
1110 swShift = norm_s(extract_h(L_Temp)); | |
1111 psErrorTerm[0].sh = add(psErrorTerm[0].sh, swShift); | |
1112 psErrorTerm[0].sh = sub(psErrorTerm[0].sh, 1); | |
1113 psErrorTerm[0].man = round(L_shl(L_Temp, swShift)); | |
1114 | |
1115 L_Temp = L_mult(swGainTweak, psErrorTerm[1].man); | |
1116 swShift = norm_s(extract_h(L_Temp)); | |
1117 psErrorTerm[1].sh = add(psErrorTerm[1].sh, swShift); | |
1118 psErrorTerm[1].sh = sub(psErrorTerm[1].sh, 1); | |
1119 psErrorTerm[1].man = round(L_shl(L_Temp, swShift)); | |
1120 | |
1121 } | |
1122 | |
1123 /*************************************************************************** | |
1124 * | |
1125 * FUNCTION NAME: hnwFilt | |
1126 * | |
1127 * PURPOSE: | |
1128 * Performs the filtering operation for harmonic noise weighting. | |
1129 * | |
1130 * INPUTS: | |
1131 * pswInSample[0:39] - array of input speech signal, | |
1132 * pswInSample points to the "oldest" sample of the | |
1133 * current subframe to be hnw filtered, S_LEN samples | |
1134 * will be stored in this array, this data is not | |
1135 * explicitly modified. | |
1136 * | |
1137 * pswState[0:183] - array of state of samples, the most | |
1138 * recent sample is the tail of the state buffer, | |
1139 * used only for full- state filtering, this data is | |
1140 * not modified | |
1141 * pswInCoef[0:5] - array of unmodified filter coefficients | |
1142 * iStateOffset - address offset from a sample in the subframe back | |
1143 * to the oldest element of the state used in the interpolating | |
1144 * filter for that sample. Although the subframe samples and | |
1145 * state information can come from different buffers, this | |
1146 * offset represents the case in which the state and sample | |
1147 * information are in the same buffer | |
1148 * swZeroState - indicate if the interpolating filter should be | |
1149 * "zero-state" filtering or "full-state" filtering: | |
1150 * 0 ==> zero-state filtering | |
1151 * !0 ==> full-state filtering | |
1152 * iNumSamples - the number of samples that are to be filtered, | |
1153 * required to be less than or equal to S_LEN in order to | |
1154 * correctly match speech samples with sample states for the | |
1155 * filtering procedure | |
1156 * | |
1157 * OUTPUTS: | |
1158 * pswOutSample[0:39] - array of output filtered speech signal, | |
1159 * pswOutSample points to the "oldest" sample location, S_LEN | |
1160 * filtered samples will be stored at the buffer associated with | |
1161 * this array, can implicitly overwrite input samples with | |
1162 * with filtered samples by setting pswOutSample = pswInSample | |
1163 * | |
1164 * RETURN VALUE: | |
1165 * none | |
1166 * | |
1167 * IMPLEMENTATION: | |
1168 * The harmonic noise weighting filter is implemented in reverse | |
1169 * temporal order, from most recent input sample backwards through | |
1170 * the input sample array. The procedure follows the equation: | |
1171 * x(n) = x(n) - PW_COEF*x(n - lag) | |
1172 * where the PW_COEF is the pitch weighting for the current | |
1173 * subframe and lag is the full-resolution lag for the current | |
1174 * subframe. x(n - lag) is found by implementing a CG_INT_MACS- | |
1175 * order FIR interpolating filter | |
1176 * | |
1177 * Harmonic noise weighting is discussed in secion 5.5. | |
1178 * | |
1179 * REFERENCE: Sub-clause 4.1.9 of GSM Recommendation 06.20 | |
1180 * | |
1181 * KEYWORDS: T_SUB, LAG, HNW_FILT, PW_COEF, CG_INT_MACS, S_LEN, LSMAX | |
1182 * | |
1183 **************************************************************************/ | |
1184 | |
1185 void hnwFilt(Shortword pswInSample[], | |
1186 Shortword pswOutSample[], | |
1187 Shortword pswState[], | |
1188 Shortword pswInCoef[], | |
1189 int iStateOffset, | |
1190 Shortword swZeroState, | |
1191 int iNumSamples) | |
1192 { | |
1193 | |
1194 /*_________________________________________________________________________ | |
1195 | | | |
1196 | Automatic Variables | | |
1197 |_________________________________________________________________________| | |
1198 */ | |
1199 Longword L_temp; | |
1200 int i, | |
1201 j; | |
1202 | |
1203 int iStatIndx = S_LEN - 1 + iStateOffset; | |
1204 int iStatIndx1 = S_LEN + iStateOffset; | |
1205 | |
1206 /*_________________________________________________________________________ | |
1207 | | | |
1208 | Executable Code | | |
1209 |_________________________________________________________________________| | |
1210 */ | |
1211 | |
1212 if (swZeroState == 0) | |
1213 { | |
1214 | |
1215 /* zero state response assumes input and output arrays are the same */ | |
1216 /*------------------------------------------------------------------*/ | |
1217 | |
1218 for (i = 0; i < iNumSamples; i++) | |
1219 { | |
1220 | |
1221 /* get input with rounding */ | |
1222 /*-------------------------*/ | |
1223 L_temp = L_mac((long) 16384, pswInSample[S_LEN - i - 1], 0x4000); | |
1224 | |
1225 for (j = 5; (j >= 0) && (iStatIndx - i + j >= 0); j--) | |
1226 /* evaluate taps 1 - 6 that point to input */ | |
1227 /*-----------------------------------------*/ | |
1228 L_temp = L_mac(L_temp, pswInSample[iStatIndx - i + j], pswInCoef[j]); | |
1229 | |
1230 pswOutSample[S_LEN - 1 - i] = extract_h(L_shl(L_temp, 1)); | |
1231 } | |
1232 } | |
1233 else | |
1234 { | |
1235 for (i = 0; i < iNumSamples; i++) | |
1236 { | |
1237 | |
1238 /* get input with rounding */ | |
1239 /*-------------------------*/ | |
1240 L_temp = L_mac((long) 16384, pswInSample[S_LEN - i - 1], 0x4000); | |
1241 | |
1242 for (j = 5; (j >= 0) && (iStatIndx - i + j >= 0); j--) | |
1243 /* evaluate taps 1 - 6 that point to input */ | |
1244 /*-----------------------------------------*/ | |
1245 L_temp = L_mac(L_temp, pswInSample[iStatIndx - i + j], pswInCoef[j]); | |
1246 | |
1247 for (; (j >= 0); j--) | |
1248 /* evaluate taps 1 - 6 that point to state */ | |
1249 /*----------------------------------------*/ | |
1250 L_temp = L_mac(L_temp, pswState[iStatIndx1 - i + j], pswInCoef[j]); | |
1251 | |
1252 pswOutSample[S_LEN - 1 - i] = extract_h(L_shl(L_temp, 1)); | |
1253 } | |
1254 } | |
1255 | |
1256 } | |
1257 | |
1258 /*************************************************************************** | |
1259 * | |
1260 * FUNCTION NAME: sfrmAnalysis | |
1261 * | |
1262 * PURPOSE: | |
1263 * | |
1264 * Determines the synthetic excitation for a subframe. | |
1265 * | |
1266 * INPUTS: | |
1267 * | |
1268 * pswWSpeech | |
1269 * Input weighted speech vector to be matched. | |
1270 * | |
1271 * swVoicingMode | |
1272 * | |
1273 * Voicing mode 0,1,2 or 3. 0 is unvoiced. A | |
1274 * frame parameter. | |
1275 * | |
1276 * snsSqrtRs | |
1277 * | |
1278 * Normalized estimate of the excitation energy | |
1279 * | |
1280 * pswHCoefs | |
1281 * | |
1282 * Coefficientss used in weighted synthesis filter, | |
1283 * H(z), (a negated version is used). pswHCoefs[0] | |
1284 * is t=-1 tap, pswHCoefs[9] is t=-10 tap. | |
1285 * | |
1286 * pswLagList | |
1287 * | |
1288 * List of lags to be searched in the long-term | |
1289 * predictor, determined by the open-loop lag search. | |
1290 * | |
1291 * siNumLags | |
1292 * | |
1293 * Number of lags in pswLagList. | |
1294 * | |
1295 * swPitch | |
1296 * | |
1297 * Fundamental pitch value to be used in harmonic- | |
1298 * noise-weighting, actualPitch*OS_FCTR. | |
1299 * | |
1300 * swHNWCoef | |
1301 * Coefficient of the harmonic-noise-weighting filter. | |
1302 * | |
1303 * ppsrCGIntFilt[0:5][0:5] | |
1304 * | |
1305 * polyphase interpolation filter, | |
1306 * ppsrCGIntFilt[iTap][iPhase], OS_FCTR phases, | |
1307 * CG_INT_MACS taps per phase. Used to construct | |
1308 * sequences delayed by fractional lags for Harmonic- | |
1309 * Noise-Weighting. | |
1310 * | |
1311 * pppsrUvCodeVec[0:1][0:6][0:39] | |
1312 * | |
1313 * unvoiced codebooks: | |
1314 * pppsrUvCodeVec[codeBook][vectorNumber][time] | |
1315 * | |
1316 * pppsrVcdCodeVec[0][0:8][0:39] | |
1317 * | |
1318 * voiced codebook: | |
1319 * pppsrVcdCodeVect[codebook(=0)][vectorNumber][time] | |
1320 * | |
1321 * swSP | |
1322 * speech flag (DTX mode) | |
1323 * | |
1324 * OUTPUTS: | |
1325 * | |
1326 * psiLagCode | |
1327 * | |
1328 * Lag code: frame- or delta-, or zero if unvoiced. | |
1329 * | |
1330 * psiVSCode1 | |
1331 * | |
1332 * First vector-sum codebook code. | |
1333 * | |
1334 * psiVSCode2 | |
1335 * | |
1336 * Second vector-sum codebook code, or zero if voiced. | |
1337 * | |
1338 * psiGsp0Code | |
1339 * | |
1340 * Gain quantizer code. | |
1341 * | |
1342 * DESCRIPTION: | |
1343 * | |
1344 * sfrmAnalysis() is the calling function for the subframe analysis | |
1345 * functions. All subframe based processing is done by it and its | |
1346 * daughter functions. All functions in this file are called by | |
1347 * sfrmAnalysis() or one of its daughter functions. As can be seen | |
1348 * above, this routine will select the LTP lag, the VSELP | |
1349 * codevector(s) and the GSP0 codeword. It is called by | |
1350 * speechEncoder(). | |
1351 * | |
1352 * The subframe processing can follow one of two paths depending on | |
1353 * whether the frame is voiced or unvoiced. These two paths are now | |
1354 * described. | |
1355 * | |
1356 * First the zero input response of H(z) is calculated (lpcZiIir()); | |
1357 * then subtracted from the weighted speech (W(z)). The outcome, p(n) | |
1358 * or pswWSVec[], will be the vector matched by the first excitation | |
1359 * vector (either adaptive or first VSELP codevector). The p(n) | |
1360 * vector is scaled to prevent overflow. | |
1361 * | |
1362 * If the frame is voiced, the closed loop lag search (closedLoop()) | |
1363 * is performed. An adaptive codevector lag is selected. Using the | |
1364 * open loop "pitch" value, the harmonic noise weighting | |
1365 * coefficients are obtained. The adaptive codevector is | |
1366 * reconstructed (fp_ex()), and weighted through the (zero state) | |
1367 * spectral (lpcZsIir()) and harmonic noise weighting filters | |
1368 * (hnwFilt()). | |
1369 * | |
1370 * The basis vectors are also filtered through the weighting | |
1371 * filters. If the frame is unvoiced, there is no spectral noise | |
1372 * weighting. | |
1373 * | |
1374 * If voiced the VSELP basis vectors are decorrelated (decorr()) | |
1375 * from the selected adaptive (LTP) codevector, and the VSELP | |
1376 * codevector search is initiated (v_srch()). | |
1377 * | |
1378 * If unvoiced, the first VSELP codevector search is performed | |
1379 * (without any decorrelation). After a vector from the first VSELP | |
1380 * codebook has been selected, the second set of basis vectors are | |
1381 * decorrelated from the selected vector. | |
1382 * | |
1383 * Once all the excitation vectors have been selected, the gain | |
1384 * quantizer is called, g_quant_vl(). | |
1385 * | |
1386 * Finally, once all subframe parameters have been found, the | |
1387 * selected excitation is scaled according to GSP0 (scaleExcite()), | |
1388 * and the composite excitation is entered into the long term | |
1389 * predictor history. The final excitation is also used to update | |
1390 * H(z) and C(z). | |
1391 * | |
1392 * REFERENCE: Sub-clauses 4.1.8.5, 4.1.9 - 4.1.12 of GSM | |
1393 * Recommendation 06.20 | |
1394 * | |
1395 * Keywords: codewords, lag, codevectors, gsp0, decoding, analysis, t_sub | |
1396 * | |
1397 **************************************************************************/ | |
1398 | |
1399 void sfrmAnalysis(Shortword *pswWSpeech, | |
1400 Shortword swVoicingMode, | |
1401 struct NormSw snsSqrtRs, | |
1402 Shortword *pswHCoefs, | |
1403 Shortword *pswLagList, | |
1404 short siNumLags, | |
1405 Shortword swPitch, | |
1406 Shortword swHNWCoef, | |
1407 short *psiLagCode, | |
1408 short *psiVSCode1, | |
1409 short *psiVSCode2, | |
1410 short *psiGsp0Code, | |
1411 Shortword swSP) | |
1412 { | |
1413 | |
1414 /*_________________________________________________________________________ | |
1415 | | | |
1416 | Static Variables | | |
1417 |_________________________________________________________________________| | |
1418 */ | |
1419 | |
1420 static short siPrevLagCode; | |
1421 | |
1422 /*_________________________________________________________________________ | |
1423 | | | |
1424 | Automatic Variables | | |
1425 |_________________________________________________________________________| | |
1426 */ | |
1427 | |
1428 short i, | |
1429 j, | |
1430 siCode, | |
1431 siIntPitch, | |
1432 siRemainder; | |
1433 short siHnwOffset, | |
1434 siHnwNum, | |
1435 siNumBasisVecs; | |
1436 | |
1437 Shortword swLag, | |
1438 swPnEnergy, | |
1439 swPnShift, | |
1440 swSampleA; | |
1441 Shortword swLtpShift; | |
1442 | |
1443 Longword L_PnEnergy; | |
1444 | |
1445 struct NormSw snsRs00, | |
1446 snsRs11, | |
1447 snsRs22; | |
1448 | |
1449 Shortword pswWSVec[S_LEN], | |
1450 pswTempVec[S_LEN]; | |
1451 Shortword pswPVec[S_LEN], | |
1452 pswWPVec[S_LEN]; | |
1453 Shortword ppswVselpEx[2][S_LEN], | |
1454 ppswWVselpEx[2][S_LEN]; | |
1455 Shortword pswWBasisVecs[9 * S_LEN], | |
1456 pswBitArray[9]; | |
1457 Shortword pswHNWCoefs[CG_INT_MACS]; | |
1458 | |
1459 Shortword *pswLtpStateOut; | |
1460 | |
1461 /*_________________________________________________________________________ | |
1462 | | | |
1463 | Executable Code | | |
1464 |_________________________________________________________________________| | |
1465 */ | |
1466 | |
1467 pswLtpStateOut = pswLtpStateBase + LTP_LEN; | |
1468 | |
1469 if (swSP == 1) /* DTX mode */ | |
1470 { /* DTX mode */ | |
1471 | |
1472 /* if not in CNI mode */ | |
1473 /*--------------------*/ | |
1474 | |
1475 /* Get the zero-input response of H(z) */ | |
1476 /*-------------------------------------*/ | |
1477 | |
1478 lpcZiIir(pswHCoefs, pswHState, pswTempVec); | |
1479 | |
1480 /* Subtract the zero-input response of H(z) from W(z)-weighted speech. */ | |
1481 /* The result is the vector to match for the adaptive codebook (long- */ | |
1482 /* term-predictor) search in voiced modes, or the vector to match for */ | |
1483 /* all synthetic excitation searches in unvoiced mode. */ | |
1484 /*---------------------------------------------------------------------*/ | |
1485 | |
1486 for (i = 0; i < S_LEN; i++) | |
1487 { | |
1488 | |
1489 pswWSVec[i] = sub(pswWSpeech[i], pswTempVec[i]); | |
1490 } | |
1491 | |
1492 /* scale the weighted speech vector (p[n]) s.t. its energy is strictly */ | |
1493 /* less than 1.0 */ | |
1494 /*---------------------------------------------------------------------*/ | |
1495 | |
1496 swSampleA = shr(pswWSVec[0], 2); | |
1497 L_PnEnergy = L_mac(0x001dff4cL, swSampleA, swSampleA); | |
1498 for (i = 1; i < S_LEN; i++) | |
1499 { | |
1500 swSampleA = shr(pswWSVec[i], 2); /* reduces energy by 16 */ | |
1501 L_PnEnergy = L_mac(L_PnEnergy, swSampleA, swSampleA); | |
1502 } | |
1503 | |
1504 swPnEnergy = round(L_PnEnergy); | |
1505 | |
1506 if (sub(swPnEnergy, 0x7ff) <= 0) | |
1507 { /* E = [0..0x7ff] */ | |
1508 | |
1509 swPnShift = 0; | |
1510 | |
1511 } | |
1512 else | |
1513 { | |
1514 | |
1515 if (sub(swPnEnergy, 0x1fff) <= 0) | |
1516 { /* E = (0x7ff.. 0x1fff] */ | |
1517 swPnShift = 1; | |
1518 | |
1519 } | |
1520 else | |
1521 { | |
1522 | |
1523 swPnShift = 2; /* E = (0x1fff..0x7fff] */ | |
1524 | |
1525 } | |
1526 } | |
1527 | |
1528 /* shift pswWSVect down by the shift factor */ | |
1529 /*------------------------------------------*/ | |
1530 | |
1531 for (i = 0; i < S_LEN; i++) | |
1532 pswWSVec[i] = shr(pswWSVec[i], swPnShift); | |
1533 | |
1534 | |
1535 if (swVoicingMode > 0) | |
1536 { | |
1537 | |
1538 /* Do restricted adaptive codebook (long-term-predictor) search: */ | |
1539 /* the search is restricted to the lags passed in from the */ | |
1540 /* open-loop lag search */ | |
1541 /*---------------------------------------------------------------*/ | |
1542 | |
1543 siCode = closedLoopLagSearch(pswLagList, siNumLags, | |
1544 pswLtpStateBase, pswHCoefs, pswWSVec, | |
1545 &swLag, &swLtpShift); | |
1546 | |
1547 /* Construct frame-lag code if this is the first subframe, */ | |
1548 /* or delta-lag code if it is not the first subframe */ | |
1549 /*---------------------------------------------------------*/ | |
1550 | |
1551 if (swVoicingMode > 0) | |
1552 { | |
1553 | |
1554 if (giSfrmCnt == 0) | |
1555 { | |
1556 siPrevLagCode = siCode; | |
1557 *psiLagCode = siCode; | |
1558 } | |
1559 else | |
1560 { | |
1561 | |
1562 *psiLagCode = add(sub(siCode, siPrevLagCode), DELTA_LEVELS / 2); | |
1563 siPrevLagCode = siCode; | |
1564 } | |
1565 } | |
1566 | |
1567 /* From the value of the fundamental pitch obtained in the open-loop */ | |
1568 /* lag search, get the correct phase of the interpolating filter, */ | |
1569 /* and scale the coefficients by the Harmonic-Noise-Weighting */ | |
1570 /* coefficient. The result is the interpolating coefficients scaled */ | |
1571 /* by the HNW coefficient. These will be used in all C(z) filtering */ | |
1572 /*-------------------------------------------------------------------*/ | |
1573 | |
1574 get_ipjj(swPitch, &siIntPitch, &siRemainder); | |
1575 | |
1576 for (i = 0; i < CG_INT_MACS; i++) | |
1577 { | |
1578 | |
1579 pswHNWCoefs[i] = mult_r(negate(ppsrCGIntFilt[i][siRemainder]), | |
1580 swHNWCoef); | |
1581 } | |
1582 | |
1583 /* Calculate a few values which will speed up C(z) filtering: */ | |
1584 /* "HnwOffset" is the distance in samples from the input sample of */ | |
1585 /* the C(z) filter to the first sample tapped by the interpolating */ | |
1586 /* filter. "HnwNum" is the number of samples which need to be */ | |
1587 /* filtered by C(z) in the zero-state case. */ | |
1588 /*-----------------------------------------------------------------*/ | |
1589 | |
1590 siHnwOffset = sub(-CG_INT_MACS / 2, siIntPitch); | |
1591 siHnwNum = sub(S_LEN + CG_INT_MACS / 2 - 1, siIntPitch); | |
1592 | |
1593 /* Perform C(z) filter on W(z)-weighted speech, get zero-input */ | |
1594 /* response of H(z)C(z) combo, subtract zero-input response */ | |
1595 /* of H(z)C(z) from W(z)C(z)-weighted speech. The result is */ | |
1596 /* the vector to match for the rest of the synthetic */ | |
1597 /* excitation searches in the voiced modes */ | |
1598 /*-------------------------------------------------------------*/ | |
1599 | |
1600 hnwFilt(pswWSpeech, pswWSVec, &pswWSpeech[-1], pswHNWCoefs, | |
1601 siHnwOffset, 1, S_LEN); | |
1602 | |
1603 hnwFilt(pswTempVec, pswTempVec, &pswHNWState[HNW_BUFF_LEN - 1], | |
1604 pswHNWCoefs, siHnwOffset, 1, S_LEN); | |
1605 | |
1606 for (i = 0; i < S_LEN; i++) | |
1607 { | |
1608 | |
1609 pswWSVec[i] = shr(sub(pswWSVec[i], pswTempVec[i]), swPnShift); | |
1610 | |
1611 } | |
1612 | |
1613 /* Recontruct adaptive codebook (long-term-predictor) vector, */ | |
1614 /* weight it through H(z) and C(z), each with zero state */ | |
1615 /*------------------------------------------------------------*/ | |
1616 | |
1617 fp_ex(swLag, pswLtpStateOut); | |
1618 | |
1619 for (i = 0; i < S_LEN; i++) | |
1620 pswPVec[i] = pswLtpStateOut[i]; | |
1621 | |
1622 lpcZsIir(pswPVec, pswHCoefs, pswWPVec); | |
1623 | |
1624 if (siHnwNum > 0) | |
1625 { | |
1626 hnwFilt(pswWPVec, pswWPVec, NULL, pswHNWCoefs, siHnwOffset, | |
1627 0, siHnwNum); | |
1628 } | |
1629 for (i = 0; i < S_LEN; i++) | |
1630 { | |
1631 pswPVec[i] = shr(pswPVec[i], swLtpShift); | |
1632 pswWPVec[i] = shr(pswWPVec[i], swLtpShift); | |
1633 } | |
1634 | |
1635 } | |
1636 else | |
1637 { | |
1638 | |
1639 /* Unvoiced mode: clear all voiced variables */ | |
1640 /*-------------------------------------------*/ | |
1641 | |
1642 swLag = 0; | |
1643 *psiLagCode = 0; | |
1644 siHnwNum = 0; | |
1645 } | |
1646 | |
1647 /* "NumBasisVecs" will be the number of basis vectors in */ | |
1648 /* the vector-sum codebook(s) */ | |
1649 /*-------------------------------------------------------*/ | |
1650 | |
1651 if (swVoicingMode > 0) | |
1652 siNumBasisVecs = C_BITS_V; | |
1653 | |
1654 else | |
1655 siNumBasisVecs = C_BITS_UV; | |
1656 | |
1657 /* Filter the basis vectors through H(z) with zero state, and if */ | |
1658 /* voiced, through C(z) with zero state */ | |
1659 /*----------------------------------------------------------------*/ | |
1660 | |
1661 for (i = 0; i < siNumBasisVecs; i++) | |
1662 { | |
1663 | |
1664 if (swVoicingMode > 0) | |
1665 { | |
1666 | |
1667 lpcZsIir((Shortword *) pppsrVcdCodeVec[0][i], pswHCoefs, | |
1668 &pswWBasisVecs[i * S_LEN]); | |
1669 } | |
1670 else | |
1671 { | |
1672 | |
1673 lpcZsIir((Shortword *) pppsrUvCodeVec[0][i], pswHCoefs, | |
1674 &pswWBasisVecs[i * S_LEN]); | |
1675 } | |
1676 | |
1677 if (siHnwNum > 0) | |
1678 { | |
1679 | |
1680 hnwFilt(&pswWBasisVecs[i * S_LEN], &pswWBasisVecs[i * S_LEN], | |
1681 NULL, pswHNWCoefs, siHnwOffset, 0, siHnwNum); | |
1682 } | |
1683 } | |
1684 | |
1685 /* If voiced, make the H(z)C(z)-weighted basis vectors orthogonal to */ | |
1686 /* the H(z)C(z)-weighted adaptive codebook vector */ | |
1687 /*-------------------------------------------------------------------*/ | |
1688 | |
1689 if (swVoicingMode > 0) | |
1690 decorr(siNumBasisVecs, pswWPVec, pswWBasisVecs); | |
1691 | |
1692 /* Do the vector-sum codebook search on the H(z)C(z)-weighted, */ | |
1693 /* orthogonalized basis vectors */ | |
1694 /*-------------------------------------------------------------*/ | |
1695 | |
1696 *psiVSCode1 = v_srch(pswWSVec, pswWBasisVecs, siNumBasisVecs); | |
1697 | |
1698 /* Construct the chosen vector-sum codebook vector from basis vectors */ | |
1699 /*--------------------------------------------------------------------*/ | |
1700 | |
1701 b_con(*psiVSCode1, siNumBasisVecs, pswBitArray); | |
1702 | |
1703 if (swVoicingMode > 0) | |
1704 v_con((Shortword *) pppsrVcdCodeVec[0][0], ppswVselpEx[0], pswBitArray, | |
1705 siNumBasisVecs); | |
1706 | |
1707 else | |
1708 v_con((Shortword *) pppsrUvCodeVec[0][0], ppswVselpEx[0], pswBitArray, | |
1709 siNumBasisVecs); | |
1710 | |
1711 if (swVoicingMode == 0) | |
1712 { | |
1713 | |
1714 /* Construct the H(z)-weighted 1st-codebook vector */ | |
1715 /*-------------------------------------------------*/ | |
1716 | |
1717 v_con(pswWBasisVecs, ppswWVselpEx[0], pswBitArray, siNumBasisVecs); | |
1718 | |
1719 /* Filter the 2nd basis vector set through H(z) with zero state */ | |
1720 /*--------------------------------------------------------------*/ | |
1721 | |
1722 for (i = 0; i < siNumBasisVecs; i++) | |
1723 { | |
1724 | |
1725 lpcZsIir((Shortword *) pppsrUvCodeVec[1][i], pswHCoefs, | |
1726 &pswWBasisVecs[i * S_LEN]); | |
1727 } | |
1728 | |
1729 /* Make the 2nd set of H(z)-weighted basis vectors orthogonal to the */ | |
1730 /* H(z)-weighted 1st-codebook vector */ | |
1731 /*-------------------------------------------------------------------*/ | |
1732 | |
1733 decorr(siNumBasisVecs, ppswWVselpEx[0], pswWBasisVecs); | |
1734 | |
1735 /* Do the vector-sum codebook search on the H(z)-weighted, */ | |
1736 /* orthogonalized, 2nd basis vector set */ | |
1737 /*---------------------------------------------------------*/ | |
1738 | |
1739 *psiVSCode2 = v_srch(pswWSVec, pswWBasisVecs, siNumBasisVecs); | |
1740 | |
1741 /* Construct the chosen vector-sum codebook vector from the 2nd set */ | |
1742 /* of basis vectors */ | |
1743 /*------------------------------------------------------------------*/ | |
1744 | |
1745 b_con(*psiVSCode2, siNumBasisVecs, pswBitArray); | |
1746 | |
1747 v_con((Shortword *) pppsrUvCodeVec[1][0], ppswVselpEx[1], pswBitArray, | |
1748 siNumBasisVecs); | |
1749 } | |
1750 | |
1751 else | |
1752 *psiVSCode2 = 0; | |
1753 | |
1754 /* Filter the 1st-codebook vector through H(z) (also through C(z) */ | |
1755 /* if appropriate) */ | |
1756 /*----------------------------------------------------------------*/ | |
1757 | |
1758 lpcZsIir(ppswVselpEx[0], pswHCoefs, ppswWVselpEx[0]); | |
1759 | |
1760 if (siHnwNum > 0) | |
1761 { | |
1762 hnwFilt(ppswWVselpEx[0], ppswWVselpEx[0], NULL, pswHNWCoefs, | |
1763 siHnwOffset, 0, siHnwNum); | |
1764 } | |
1765 | |
1766 if (swVoicingMode == 0) | |
1767 { | |
1768 | |
1769 /* Filter the 2nd-codebook vector through H(z) */ | |
1770 /*---------------------------------------------*/ | |
1771 | |
1772 lpcZsIir(ppswVselpEx[1], pswHCoefs, ppswWVselpEx[1]); | |
1773 } | |
1774 | |
1775 /* Get the square-root of the ratio of residual energy to */ | |
1776 /* excitation vector energy for each of the excitation sources */ | |
1777 /*-------------------------------------------------------------*/ | |
1778 | |
1779 if (swVoicingMode > 0) | |
1780 { | |
1781 | |
1782 rs_rrNs(pswPVec, snsSqrtRs, &snsRs00); | |
1783 } | |
1784 | |
1785 rs_rrNs(ppswVselpEx[0], snsSqrtRs, &snsRs11); | |
1786 | |
1787 if (swVoicingMode == 0) | |
1788 { | |
1789 | |
1790 rs_rrNs(ppswVselpEx[1], snsSqrtRs, &snsRs22); | |
1791 } | |
1792 | |
1793 /* Determine the vector-quantized gains for each of the excitations */ | |
1794 /*------------------------------------------------------------------*/ | |
1795 | |
1796 *psiGsp0Code = g_quant_vl(swVoicingMode, pswWSVec, swPnShift, | |
1797 pswWPVec, | |
1798 ppswWVselpEx[0], ppswWVselpEx[1], snsRs00, | |
1799 snsRs11, snsRs22); | |
1800 | |
1801 } /* DTX mode */ | |
1802 else /* DTX mode */ | |
1803 { /* DTX mode */ | |
1804 | |
1805 /* swSP == 0, currently in comfort noise insertion mode */ /* DTX mode */ | |
1806 /*------------------------------------------------------*/ /* DTX mode */ | |
1807 | |
1808 /* generate the random codevector */ /* DTX mode */ | |
1809 siNumBasisVecs = C_BITS_UV; /* DTX mode */ | |
1810 | |
1811 /* build codevector 1 */ /* DTX mode */ | |
1812 | |
1813 b_con(*psiVSCode1, siNumBasisVecs, pswBitArray); /* DTX mode */ | |
1814 v_con((Shortword *) pppsrUvCodeVec[0][0], ppswVselpEx[0], /* DTX mode */ | |
1815 pswBitArray, siNumBasisVecs); /* DTX mode */ | |
1816 | |
1817 /* build codevector 2 */ /* DTX mode */ | |
1818 | |
1819 b_con(*psiVSCode2, siNumBasisVecs, pswBitArray); /* DTX mode */ | |
1820 v_con((Shortword *) pppsrUvCodeVec[1][0], ppswVselpEx[1], /* DTX mode */ | |
1821 pswBitArray, siNumBasisVecs); /* DTX mode */ | |
1822 | |
1823 | |
1824 /* get rs_rr for the two vectors */ /* DTX mode */ | |
1825 rs_rrNs(ppswVselpEx[0], snsSqrtRs, &snsRs11); /* DTX mode */ | |
1826 rs_rrNs(ppswVselpEx[1], snsSqrtRs, &snsRs22); /* DTX mode */ | |
1827 | |
1828 } /* DTX mode */ | |
1829 | |
1830 | |
1831 /* Scale the excitations, each by its gain, and add them. Put the */ | |
1832 /* result at the end of the adaptive codebook (long-term-predictor */ | |
1833 /* state) */ | |
1834 /*-----------------------------------------------------------------*/ | |
1835 | |
1836 if (swVoicingMode == 0) | |
1837 { | |
1838 | |
1839 /* unvoiced */ | |
1840 /* -------- */ | |
1841 | |
1842 scaleExcite(ppswVselpEx[0], | |
1843 pppsrGsp0[swVoicingMode][*psiGsp0Code][0], | |
1844 snsRs11, ppswVselpEx[0]); | |
1845 scaleExcite(ppswVselpEx[1], | |
1846 pppsrGsp0[swVoicingMode][*psiGsp0Code][1], | |
1847 snsRs22, ppswVselpEx[1]); | |
1848 | |
1849 /* now combine the two scaled excitations */ | |
1850 /* -------------------------------------- */ | |
1851 for (i = 0; i < S_LEN; i++) | |
1852 pswTempVec[i] = add(ppswVselpEx[0][i], ppswVselpEx[1][i]); | |
1853 } | |
1854 | |
1855 else | |
1856 { | |
1857 | |
1858 /* voiced */ | |
1859 /* ------ */ | |
1860 | |
1861 scaleExcite(pswPVec, | |
1862 pppsrGsp0[swVoicingMode][*psiGsp0Code][0], | |
1863 snsRs00, pswPVec); | |
1864 scaleExcite(ppswVselpEx[0], | |
1865 pppsrGsp0[swVoicingMode][*psiGsp0Code][1], | |
1866 snsRs11, ppswVselpEx[0]); | |
1867 | |
1868 /* now combine the two scaled excitations */ | |
1869 /* -------------------------------------- */ | |
1870 for (i = 0; i < S_LEN; i++) | |
1871 pswTempVec[i] = add(pswPVec[i], ppswVselpEx[0][i]); | |
1872 } | |
1873 | |
1874 /* Update the long-term-predictor state using the synthetic excitation */ | |
1875 /*---------------------------------------------------------------------*/ | |
1876 | |
1877 for (i = -LTP_LEN; i < -S_LEN; i++) | |
1878 pswLtpStateOut[i] = pswLtpStateOut[i + S_LEN]; | |
1879 | |
1880 for (i = -S_LEN, j = 0; j < S_LEN; i++, j++) | |
1881 pswLtpStateOut[i] = pswTempVec[j]; | |
1882 | |
1883 /* Filter the synthetic excitation through the weighting filters, */ | |
1884 /* H(z) and C(z), only to update filter states (Note that C(z) */ | |
1885 /* state may be updated without filtering, since it is an FIR) */ | |
1886 /* */ | |
1887 /* First, perform one subframe's worth of delay on C(z) state */ | |
1888 /*----------------------------------------------------------------*/ | |
1889 | |
1890 for (i = 0; i < HNW_BUFF_LEN - S_LEN; i++) | |
1891 pswHNWState[i] = pswHNWState[i + S_LEN]; | |
1892 | |
1893 /* Second, perform H(z) filter on excitation, output goes into */ | |
1894 /* C(z) state */ | |
1895 /*-------------------------------------------------------------*/ | |
1896 | |
1897 lpcIir(pswTempVec, pswHCoefs, pswHState, | |
1898 &pswHNWState[HNW_BUFF_LEN - S_LEN]); | |
1899 | |
1900 } /* end of sfrmAnalysis() */ | |
1901 | |
1902 /*************************************************************************** | |
1903 * | |
1904 * FUNCTION NAME: v_srch | |
1905 * | |
1906 * PURPOSE: | |
1907 * The purpose of this function is search a vector-sum codebook for the | |
1908 * optimal vector | |
1909 * | |
1910 * INPUTS: | |
1911 * | |
1912 * pswWInput[0:S_LEN] | |
1913 * | |
1914 * the weighted input speech frame, with the zero-input | |
1915 * response of H(z) subtracted | |
1916 * | |
1917 * pswWBasisVecs[0:S_LEN*siNumBasis] | |
1918 * | |
1919 * weighted, decorrelated vector-sum codebook basis | |
1920 * vectors | |
1921 * | |
1922 * siNumBasis | |
1923 * | |
1924 * number of basis vectors | |
1925 * | |
1926 * OUTPUTS: | |
1927 * | |
1928 * none | |
1929 * | |
1930 * RETURN VALUE: | |
1931 * | |
1932 * sw1 | |
1933 * | |
1934 * output code | |
1935 * | |
1936 * REFERENCE: Sub-clause 4.1.10.2 of GSM Recommendation 06.20 | |
1937 * | |
1938 * KEYWORDS: v_srch, codebook, search | |
1939 * | |
1940 **************************************************************************/ | |
1941 | |
1942 Shortword v_srch(Shortword pswWInput[], Shortword pswWBasisVecs[], | |
1943 short int siNumBasis) | |
1944 { | |
1945 | |
1946 /*_________________________________________________________________________ | |
1947 | | | |
1948 | Local Constants | | |
1949 |_________________________________________________________________________| | |
1950 */ | |
1951 | |
1952 #define V_ARRAY_SIZE ( 1 << (C_BITS_V-1) ) - 1 | |
1953 #define UN_ARRAY_SIZE ( 1 << (C_BITS_UV-1) ) - 1 | |
1954 #define MINUS_HALF -0x4000 | |
1955 | |
1956 /*_________________________________________________________________________ | |
1957 | | | |
1958 | Local Static Variables | | |
1959 |_________________________________________________________________________| | |
1960 */ | |
1961 static Shortword | |
1962 pswUpdateIndexV[V_ARRAY_SIZE] = | |
1963 { | |
1964 0x00, 0x09, 0x48, 0x12, 0x00, 0x51, 0x48, 0x1b, 0x00, 0x09, | |
1965 0x48, 0x5a, 0x00, 0x51, 0x48, 0x24, 0x00, 0x09, 0x48, 0x12, | |
1966 0x00, 0x51, 0x48, 0x63, 0x00, 0x09, 0x48, 0x5a, 0x00, 0x51, | |
1967 0x48, 0x2d, 0x00, 0x09, 0x48, 0x12, 0x00, 0x51, 0x48, 0x1b, | |
1968 0x00, 0x09, 0x48, 0x5a, 0x00, 0x51, 0x48, 0x6c, 0x00, 0x09, | |
1969 0x48, 0x12, 0x00, 0x51, 0x48, 0x63, 0x00, 0x09, 0x48, 0x5a, | |
1970 0x00, 0x51, 0x48, 0x36, 0x00, 0x09, 0x48, 0x12, 0x00, 0x51, | |
1971 0x48, 0x1b, 0x00, 0x09, 0x48, 0x5a, 0x00, 0x51, 0x48, 0x24, | |
1972 0x00, 0x09, 0x48, 0x12, 0x00, 0x51, 0x48, 0x63, 0x00, 0x09, | |
1973 0x48, 0x5a, 0x00, 0x51, 0x48, 0x75, 0x00, 0x09, 0x48, 0x12, | |
1974 0x00, 0x51, 0x48, 0x1b, 0x00, 0x09, 0x48, 0x5a, 0x00, 0x51, | |
1975 0x48, 0x6c, 0x00, 0x09, 0x48, 0x12, 0x00, 0x51, 0x48, 0x63, | |
1976 0x00, 0x09, 0x48, 0x5a, 0x00, 0x51, 0x48, 0x3f, 0x00, 0x09, | |
1977 0x48, 0x12, 0x00, 0x51, 0x48, 0x1b, 0x00, 0x09, 0x48, 0x5a, | |
1978 0x00, 0x51, 0x48, 0x24, 0x00, 0x09, 0x48, 0x12, 0x00, 0x51, | |
1979 0x48, 0x63, 0x00, 0x09, 0x48, 0x5a, 0x00, 0x51, 0x48, 0x2d, | |
1980 0x00, 0x09, 0x48, 0x12, 0x00, 0x51, 0x48, 0x1b, 0x00, 0x09, | |
1981 0x48, 0x5a, 0x00, 0x51, 0x48, 0x6c, 0x00, 0x09, 0x48, 0x12, | |
1982 0x00, 0x51, 0x48, 0x63, 0x00, 0x09, 0x48, 0x5a, 0x00, 0x51, | |
1983 0x48, 0x7e, 0x00, 0x09, 0x48, 0x12, 0x00, 0x51, 0x48, 0x1b, | |
1984 0x00, 0x09, 0x48, 0x5a, 0x00, 0x51, 0x48, 0x24, 0x00, 0x09, | |
1985 0x48, 0x12, 0x00, 0x51, 0x48, 0x63, 0x00, 0x09, 0x48, 0x5a, | |
1986 0x00, 0x51, 0x48, 0x75, 0x00, 0x09, 0x48, 0x12, 0x00, 0x51, | |
1987 0x48, 0x1b, 0x00, 0x09, 0x48, 0x5a, 0x00, 0x51, 0x48, 0x6c, | |
1988 0x00, 0x09, 0x48, 0x12, 0x00, 0x51, 0x48, 0x63, 0x00, 0x09, | |
1989 0x48, 0x5a, 0x00, 0x51, 0x48, | |
1990 }, | |
1991 pswBitIndexV[V_ARRAY_SIZE] = | |
1992 { | |
1993 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, | |
1994 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, | |
1995 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, | |
1996 0x01, 0x06, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, | |
1997 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, | |
1998 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, | |
1999 0x01, 0x02, 0x01, 0x07, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, | |
2000 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, | |
2001 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, | |
2002 0x01, 0x03, 0x01, 0x02, 0x01, 0x06, 0x01, 0x02, 0x01, 0x03, | |
2003 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, | |
2004 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, | |
2005 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x01, 0x02, | |
2006 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, | |
2007 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, | |
2008 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x06, | |
2009 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, | |
2010 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, | |
2011 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, | |
2012 0x01, 0x07, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, | |
2013 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, | |
2014 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, | |
2015 0x01, 0x02, 0x01, 0x06, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, | |
2016 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, | |
2017 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, | |
2018 0x01, 0x03, 0x01, 0x02, 0x01, | |
2019 }, | |
2020 pswModNextBitV[C_BITS_V] = | |
2021 { | |
2022 1, 2, 3, 4, 5, 6, 7, 0, 1, | |
2023 }, | |
2024 pswUpdateIndexUn[UN_ARRAY_SIZE] = | |
2025 { | |
2026 0x00, 0x07, 0x2a, 0x0e, 0x00, 0x31, 0x2a, 0x15, 0x00, 0x07, | |
2027 0x2a, 0x38, 0x00, 0x31, 0x2a, 0x1c, 0x00, 0x07, 0x2a, 0x0e, | |
2028 0x00, 0x31, 0x2a, 0x3f, 0x00, 0x07, 0x2a, 0x38, 0x00, 0x31, | |
2029 0x2a, 0x23, 0x00, 0x07, 0x2a, 0x0e, 0x00, 0x31, 0x2a, 0x15, | |
2030 0x00, 0x07, 0x2a, 0x38, 0x00, 0x31, 0x2a, 0x46, 0x00, 0x07, | |
2031 0x2a, 0x0e, 0x00, 0x31, 0x2a, 0x3f, 0x00, 0x07, 0x2a, 0x38, | |
2032 0x00, 0x31, 0x2a, | |
2033 }, | |
2034 pswBitIndexUn[UN_ARRAY_SIZE] = | |
2035 { | |
2036 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, | |
2037 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, | |
2038 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, | |
2039 0x01, 0x00, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, | |
2040 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, | |
2041 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, | |
2042 0x01, 0x02, 0x01, | |
2043 }, | |
2044 pswModNextBitUV[C_BITS_UV] = | |
2045 { | |
2046 1, 2, 3, 4, 5, 0, 1, | |
2047 }; | |
2048 | |
2049 /*_________________________________________________________________________ | |
2050 | | | |
2051 | Automatic Variables | | |
2052 |_________________________________________________________________________| | |
2053 */ | |
2054 | |
2055 Shortword **pppswDubD[C_BITS_V - 1], | |
2056 *ppswD[C_BITS_V - 1], | |
2057 pswCGUpdates[2 * C_BITS_V * (C_BITS_V - 1)], | |
2058 pswDSpace[2 * C_BITS_V * (C_BITS_V - 1)], | |
2059 *ppswDPSpace[C_BITS_V * (C_BITS_V - 1)], | |
2060 pswBits[C_BITS_V - 1], | |
2061 *pswUpdatePtr, | |
2062 *pswUIndex, | |
2063 *pswBIndex, | |
2064 *pswModNextBit, | |
2065 *psw0, | |
2066 *psw1, | |
2067 *psw2, | |
2068 swC0, | |
2069 swG0, | |
2070 swCC, | |
2071 swG, | |
2072 swCCMax, | |
2073 swGMax, | |
2074 sw1; | |
2075 Longword pL_R[C_BITS_V], | |
2076 L_R, | |
2077 L_MaxC, | |
2078 L_C0, | |
2079 L_D, | |
2080 L_G0, | |
2081 L_C, | |
2082 L_G, | |
2083 L_1; | |
2084 short int siI, | |
2085 siJ, | |
2086 siK, | |
2087 siEBits, | |
2088 siShiftCnt, | |
2089 siBitIndex, | |
2090 siBest, | |
2091 siMask; | |
2092 | |
2093 /*_________________________________________________________________________ | |
2094 | | | |
2095 | Executable Code | | |
2096 |_________________________________________________________________________| | |
2097 */ | |
2098 | |
2099 /* initialize variables based on voicing mode */ | |
2100 /* ------------------------------------------ */ | |
2101 | |
2102 if (sub(siNumBasis, C_BITS_V) == 0) | |
2103 { | |
2104 siEBits = C_BITS_V_1; | |
2105 pswUIndex = pswUpdateIndexV; | |
2106 pswBIndex = pswBitIndexV; | |
2107 pswModNextBit = pswModNextBitV; | |
2108 } | |
2109 else | |
2110 { | |
2111 siEBits = C_BITS_UV_1; | |
2112 pswUIndex = pswUpdateIndexUn; | |
2113 pswBIndex = pswBitIndexUn; | |
2114 pswModNextBit = pswModNextBitUV; | |
2115 } | |
2116 | |
2117 /* initialize pointers */ | |
2118 /* ------------------- */ | |
2119 | |
2120 for (siI = 0; siI < siNumBasis - 1; siI++) | |
2121 { | |
2122 | |
2123 pppswDubD[siI] = &ppswDPSpace[siI * siNumBasis]; | |
2124 | |
2125 for (siJ = 0; siJ < siNumBasis; siJ++) | |
2126 { | |
2127 ppswDPSpace[(siI * siNumBasis) + siJ] = | |
2128 &pswDSpace[(siI * siNumBasis * 2) + (siJ * 2)]; | |
2129 } | |
2130 ppswD[siI] = &pswDSpace[siI * siNumBasis]; | |
2131 } | |
2132 | |
2133 /* compute correlations (Rm) between given vector and basis vectors, */ | |
2134 /* store in double precision; maintain max C for later scaling of Rm's */ | |
2135 /* ------------------------------------------------------------------- */ | |
2136 | |
2137 L_MaxC = 0L; | |
2138 | |
2139 for (siI = 0; siI < siNumBasis; siI++) | |
2140 { | |
2141 | |
2142 L_R = L_mult(pswWBasisVecs[siI * S_LEN], pswWInput[0]); | |
2143 | |
2144 for (siJ = 1; siJ < S_LEN; siJ++) | |
2145 { | |
2146 L_R = L_mac(L_R, pswWBasisVecs[siJ + (siI * S_LEN)], pswWInput[siJ]); | |
2147 } | |
2148 pL_R[siI] = L_R; | |
2149 L_R = L_abs(L_R); | |
2150 L_MaxC = L_add(L_R, L_MaxC); | |
2151 } | |
2152 | |
2153 /* normalize max C to get scaling shift count */ | |
2154 /* scale Rm's and calculate C(0) */ | |
2155 /* ------------------------------------------ */ | |
2156 | |
2157 /* max abs(C) after scale is <= 0.5 */ | |
2158 siShiftCnt = add(-1, norm_l(L_MaxC)); | |
2159 | |
2160 L_C0 = 0L; | |
2161 | |
2162 for (siI = 0; siI < siNumBasis; siI++) | |
2163 { | |
2164 | |
2165 L_R = L_shl(pL_R[siI], siShiftCnt); | |
2166 | |
2167 L_C0 = L_sub(L_C0, L_R); | |
2168 | |
2169 pL_R[siI] = L_shl(L_R, 1); | |
2170 | |
2171 } | |
2172 swC0 = extract_h(L_C0); | |
2173 | |
2174 /* compute correlations (Dmj, for m != j) between the basis vectors */ | |
2175 /* store in double precision */ | |
2176 /* ---------------------------------------------------------------- */ | |
2177 | |
2178 for (siI = 0; siI < siNumBasis - 1; siI++) | |
2179 { | |
2180 | |
2181 for (siJ = siI + 1; siJ < siNumBasis; siJ++) | |
2182 { | |
2183 | |
2184 L_D = L_mult(pswWBasisVecs[siI * S_LEN], pswWBasisVecs[siJ * S_LEN]); | |
2185 | |
2186 for (siK = 1; siK < S_LEN; siK++) | |
2187 { | |
2188 L_D = L_mac(L_D, pswWBasisVecs[siK + (siI * S_LEN)], | |
2189 pswWBasisVecs[siK + (siJ * S_LEN)]); | |
2190 } | |
2191 pppswDubD[siI][siJ][0] = extract_h(L_D); | |
2192 pppswDubD[siI][siJ][1] = extract_l(L_D); | |
2193 } | |
2194 } | |
2195 | |
2196 /* compute the sum of the Djj's (to be used for scaling the Dmj's and */ | |
2197 /* for computing G(0)); normalize it, get shift count for scaling Dmj's */ | |
2198 /* -------------------------------------------------------------------- */ | |
2199 | |
2200 psw1 = pswWBasisVecs; | |
2201 | |
2202 L_G0 = L_mult(psw1[0], psw1[0]); | |
2203 | |
2204 for (siI = 1; siI < siNumBasis * S_LEN; siI++) | |
2205 { | |
2206 L_G0 = L_mac(L_G0, psw1[siI], psw1[siI]); | |
2207 } | |
2208 | |
2209 siShiftCnt = add(-4, norm_l(L_G0)); | |
2210 | |
2211 L_G0 = L_shl(L_G0, siShiftCnt); | |
2212 | |
2213 /* scale Dmj's and compute G(0) */ | |
2214 /* ---------------------------- */ | |
2215 | |
2216 for (siI = 0; siI < siNumBasis - 1; siI++) | |
2217 { | |
2218 | |
2219 for (siJ = siI + 1; siJ < siNumBasis; siJ++) | |
2220 { | |
2221 | |
2222 L_D = L_deposit_h(pppswDubD[siI][siJ][0]); | |
2223 L_D = L_add(L_D, (LSP_MASK & L_deposit_l(pppswDubD[siI][siJ][1]))); | |
2224 | |
2225 L_D = L_shl(L_D, siShiftCnt); | |
2226 | |
2227 L_D = L_shl(L_D, 1); | |
2228 | |
2229 L_G0 = L_add(L_D, L_G0); | |
2230 | |
2231 L_D = L_shl(L_D, 1); | |
2232 | |
2233 ppswD[siI][siJ] = round(L_D); | |
2234 } | |
2235 } | |
2236 | |
2237 swG0 = extract_h(L_G0); | |
2238 | |
2239 /* build array of update values for codebook search */ | |
2240 /* ------------------------------------------------ */ | |
2241 | |
2242 for (siI = 0; siI < siEBits; siI++) | |
2243 { | |
2244 pswCGUpdates[siI * (siEBits + 1)] = round(pL_R[siI]); | |
2245 } | |
2246 psw0 = &pswCGUpdates[siEBits]; | |
2247 psw1 = &pswCGUpdates[1]; | |
2248 psw2 = &pswCGUpdates[2 * siEBits]; | |
2249 | |
2250 for (siI = 0; siI < siEBits - 1; siI++) | |
2251 { | |
2252 | |
2253 for (siJ = siI + 1; siJ < siEBits; siJ++) | |
2254 { | |
2255 | |
2256 L_1 = L_deposit_h(ppswD[siI][siJ]); | |
2257 L_1 = L_shl(L_1, 1); | |
2258 psw1[siJ - 1 + (siI * siEBits)] = extract_h(L_1); | |
2259 psw2[siI + (siEBits * (siJ - 1))] = extract_h(L_1); | |
2260 } | |
2261 psw0[siI * (siEBits + 1)] = negate(ppswD[siI][siEBits]); | |
2262 } | |
2263 | |
2264 psw0[siI * (siEBits + 1)] = negate(ppswD[siEBits - 1][siEBits]); | |
2265 | |
2266 /* copy to negative side of array */ | |
2267 /* ------------------------------ */ | |
2268 | |
2269 psw0 = &pswCGUpdates[(siEBits + 1) * siEBits]; | |
2270 | |
2271 for (siI = 0; siI < (siEBits + 1) * siEBits; siI++) | |
2272 { | |
2273 psw0[siI] = negate(pswCGUpdates[siI]); | |
2274 } | |
2275 | |
2276 /* initialize array of bits (magnitude = 0.5) */ | |
2277 /* ------------------------------------------ */ | |
2278 | |
2279 for (siI = 0; siI < siEBits; siI++) | |
2280 { | |
2281 pswBits[siI] = MINUS_HALF; | |
2282 } | |
2283 | |
2284 /* initialize and do codebook search */ | |
2285 /* --------------------------------- */ | |
2286 | |
2287 swGMax = swG0; | |
2288 swCCMax = mult_r(swC0, swC0); | |
2289 L_C = L_deposit_h(swC0); | |
2290 L_G = L_deposit_h(swG0); | |
2291 siBest = 0; | |
2292 | |
2293 for (siI = 0; siI < (1 << siEBits) - 1; siI++) | |
2294 { | |
2295 | |
2296 pswUpdatePtr = &pswCGUpdates[pswUIndex[siI]]; | |
2297 | |
2298 siBitIndex = pswBIndex[siI]; | |
2299 | |
2300 L_C = L_msu(L_C, pswUpdatePtr[0], 0x8000); | |
2301 | |
2302 for (siJ = 0; siJ < siEBits - 1; siJ++) | |
2303 { | |
2304 L_G = L_mac(L_G, pswUpdatePtr[siJ + 1], pswBits[siBitIndex]); | |
2305 siBitIndex = pswModNextBit[siBitIndex]; | |
2306 } | |
2307 L_G = L_msu(L_G, pswUpdatePtr[siJ + 1], 0x8000); | |
2308 | |
2309 pswBits[siBitIndex] = negate(pswBits[siBitIndex]); | |
2310 | |
2311 sw1 = extract_h(L_C); | |
2312 swCC = mult_r(sw1, sw1); | |
2313 | |
2314 swG = extract_h(L_G); | |
2315 L_1 = L_mult(swG, swCCMax); | |
2316 | |
2317 L_1 = L_msu(L_1, swGMax, swCC); | |
2318 | |
2319 if (L_1 < 0) | |
2320 { | |
2321 swCCMax = swCC; | |
2322 swGMax = swG; | |
2323 siBest = add(siI, 1); | |
2324 } | |
2325 } | |
2326 | |
2327 /* generate code for positive correlation; */ | |
2328 /* compute correlation, if negative, invert code */ | |
2329 /* --------------------------------------------- */ | |
2330 | |
2331 sw1 = siBest ^ (shr(siBest, 1)); | |
2332 | |
2333 siMask = 0x1; | |
2334 L_1 = 0L; | |
2335 | |
2336 for (siI = 0; siI < siNumBasis; siI++) | |
2337 { | |
2338 | |
2339 if ((sw1 & siMask) == 0) | |
2340 { | |
2341 L_1 = L_sub(L_1, pL_R[siI]); | |
2342 } | |
2343 else | |
2344 { | |
2345 L_1 = L_add(L_1, pL_R[siI]); | |
2346 } | |
2347 | |
2348 siMask = shl(siMask, 1); | |
2349 } | |
2350 | |
2351 if (L_1 < 0) | |
2352 { | |
2353 sw1 = sw1 ^ (sub(shl(1, siNumBasis), 1)); | |
2354 } | |
2355 | |
2356 /* return code */ | |
2357 /* ----------- */ | |
2358 | |
2359 return (sw1); | |
2360 } |