comparison sp_dec.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_dec.c
4 *
5 * Purpose:
6 * Contains all functions for decoding speech. It does not
7 * include those routines needed to decode channel information.
8 *
9 * Since the GSM half-rate speech coder is an analysis-by-synthesis
10 * coder, many of the routines in this file are also called by the
11 * encoder. Functions are included for coded-parameter lookup,
12 * LPC filter coefficient interpolation, excitation vector lookup
13 * and construction, vector quantized gain lookup, and LPC synthesis
14 * filtering. In addition, some post-processing functions are
15 * included.
16 *
17 * Below is a listing of all the functions appearing in the file.
18 * The functions are arranged according to their purpose. Under
19 * each heading, the ordering is hierarchical.
20 *
21 * The entire speech decoder, under which all these routines fall,
22 * except were noted:
23 * speechDecoder()
24 *
25 * Spectral Smoothing of LPC:
26 * a_sst()
27 * aFlatRcDp()
28 * rcToCorrDpL()
29 * aToRc()
30 * rcToADp()
31 * VSELP codevector construction:
32 * b_con()
33 * v_con()
34 * LTP vector contruction:
35 * fp_ex()
36 * get_ipjj()
37 * lagDecode()
38 * LPC contruction
39 * getSfrmLpc()
40 * interpolateCheck()
41 * res_eng()
42 * lookupVq()
43 * Excitation scaling:
44 * rs_rr()
45 * g_corr1() (no scaling)
46 * rs_rrNs()
47 * g_corr1s() (g_corr1 with scaling)
48 * scaleExcite()
49 * Post filtering:
50 * pitchPreFilt()
51 * agcGain()
52 * lpcIir()
53 * r0BasedEnergyShft()
54 * spectralPostFilter()
55 * lpcFir()
56 *
57 *
58 * Routines not referenced by speechDecoder()
59 * Filtering routines:
60 * lpcIrZsIir()
61 * lpcZiIir()
62 * lpcZsFir()
63 * lpcZsIir()
64 * lpcZsIirP()
65 * Square root:
66 * sqroot()
67 *
68 **************************************************************************/
69
70 /*_________________________________________________________________________
71 | |
72 | Include Files |
73 |_________________________________________________________________________|
74 */
75
76 #include "typedefs.h"
77 #include "mathhalf.h"
78 #include "sp_rom.h"
79 #include "sp_dec.h"
80 #include "err_conc.h"
81 #include "dtx.h"
82
83
84 /*_________________________________________________________________________
85 | |
86 | Local Functions (scope is limited to this file) |
87 |_________________________________________________________________________|
88 */
89
90 static void a_sst(Shortword swAshift, Shortword swAscale,
91 Shortword pswDirectFormCoefIn[],
92 Shortword pswDirectFormCoefOut[]);
93
94 static short aToRc(Shortword swAshift, Shortword pswAin[],
95 Shortword pswRc[]);
96
97 static Shortword agcGain(Shortword pswStateCurr[],
98 struct NormSw snsInSigEnergy,
99 Shortword swEngyRShft);
100
101 static Shortword lagDecode(Shortword swDeltaLag);
102
103 static void lookupVq(Shortword pswVqCodeWds[], Shortword pswRCOut[]);
104
105 static void pitchPreFilt(Shortword pswExcite[],
106 Shortword swRxGsp0,
107 Shortword swRxLag,
108 Shortword swUvCode,
109 Shortword swSemiBeta,
110 struct NormSw snsSqrtRs,
111 Shortword pswExciteOut[],
112 Shortword pswPPreState[]);
113
114 static void spectralPostFilter(Shortword pswSPFIn[],
115 Shortword pswNumCoef[], Shortword pswDenomCoef[],
116 Shortword pswSPFOut[]);
117
118 /*_________________________________________________________________________
119 | |
120 | Local Defines |
121 |_________________________________________________________________________|
122 */
123
124 #define P_INT_MACS 10
125 #define ASCALE 0x0800
126 #define ASHIFT 4
127 #define DELTA_LEVELS 16
128 #define GSP0_SCALE 1
129 #define C_BITS_V 9 /* number of bits in any voiced VSELP
130 * codeword */
131 #define C_BITS_UV 7 /* number of bits in a unvoiced VSELP
132 * codeword */
133 #define MAXBITS C_BITS_V /* max number of bits in any VSELP
134 * codeword */
135 #define LTP_LEN 147 /* 147==0x93 length of LTP history */
136 #define SQRT_ONEHALF 0x5a82 /* the 0.5 ** 0.5 */
137 #define LPC_ROUND 0x00000800L /* 0x8000 >> ASHIFT */
138 #define AFSHIFT 2 /* number of right shifts to be
139 * applied to the autocorrelation
140 * sequence in aFlatRcDp */
141
142 /*_________________________________________________________________________
143 | |
144 | State variables (globals) |
145 |_________________________________________________________________________|
146 */
147
148 Shortword gswPostFiltAgcGain,
149 gpswPostFiltStateNum[NP],
150 gpswPostFiltStateDenom[NP],
151 swPostEmphasisState,
152 pswSynthFiltState[NP],
153 pswOldFrmKsDec[NP],
154 pswOldFrmAsDec[NP],
155 pswOldFrmPFNum[NP],
156 pswOldFrmPFDenom[NP],
157 swOldR0Dec,
158 pswLtpStateBaseDec[LTP_LEN + S_LEN],
159 pswPPreState[LTP_LEN + S_LEN];
160
161
162 Shortword swMuteFlagOld; /* error concealment */
163
164
165 /* DTX state variables */
166 /* ------------------- */
167
168 Shortword swRxDTXState = CNINTPER - 1; /* DTX State at the rx.
169 * Modulo */
170
171 /* counter [0,11]. */
172
173 Shortword swDecoMode = SPEECH;
174 Shortword swDtxMuting = 0;
175 Shortword swDtxBfiCnt = 0;
176
177 Shortword swOldR0IndexDec = 0;
178
179 Shortword swRxGsHistPtr = 0;
180 Longword pL_RxGsHist[(OVERHANG - 1) * N_SUB];
181
182
183 /*_________________________________________________________________________
184 | |
185 | Global Data |
186 | (scope is global to this file) |
187 |_________________________________________________________________________|
188 */
189
190 Shortword swR0Dec;
191
192 Shortword swVoicingMode, /* MODE */
193 pswVq[3], /* LPC1, LPC2, LPC3 */
194 swSi, /* INT_LPC */
195 swEngyRShift; /* for use by spectral postfilter */
196
197
198 Shortword swR0NewCN; /* DTX mode */
199
200 extern LongwordRom ppLr_gsTable[4][32]; /* DTX mode */
201
202
203 /***************************************************************************
204 *
205 * FUNCTION NAME: aFlatRcDp
206 *
207 * PURPOSE:
208 *
209 * Given a Longword autocorrelation sequence, representing LPC
210 * information, aFlatRcDp converts the vector to one of NP
211 * Shortword reflection coefficients.
212 *
213 * INPUT:
214 *
215 *
216 * pL_R[0:NP] - An input Longword autocorrelation sequence, (pL_R[0] =
217 * not necessarily 0x7fffffffL). pL_R is altered in the
218 * call, by being right shifted by global constant
219 * AFSHIFT bits.
220 *
221 * The input array pL_R[] should be shifted left as much
222 * as possible to improve precision.
223 *
224 * AFSHIFT - The number of right shifts to be applied to the
225 * normalized autocorrelation sequence pL_R.
226 *
227 * OUTPUT:
228 *
229 * pswRc[0:NP-1] - A Shortword output vector of NP reflection
230 * coefficients.
231 *
232 * RETURN VALUE:
233 *
234 * None
235 *
236 * DESCRIPTION:
237 *
238 * This routine transforms LPC information from one set of
239 * parameters to another. It is better suited for fixed point
240 * implementations than the Levinson-Dubin recursion.
241 *
242 * The function is called by a_sst(), and getNWCoefs(). In a_sst()
243 * direct form coefficients are converted to autocorrelations,
244 * and smoothed in that domain. Conversion back to direct form
245 * coefficients is done by calling aFlatRc(), followed by rcToADp().
246 *
247 * In getNwCoefs() again the conversion back to direct form
248 * coefficients is done by calling aFlatRc(), followed by rcToADp().
249 * In getNwCoefs() an autocorrelation sequence is generated from the
250 * impulse response of the weighting filters.
251 *
252 * The fundamental recursion is derived from AFLAT, which is
253 * described in section 4.1.4.1.
254 *
255 * Unlike in AFLAT where the reflection coefficients are known, here
256 * they are the unknowns. PBar and VBar for j==0 are initially
257 * known, as is rSub1. From this information the next set of P's
258 * and V's are generated. At the end of the recursion the next,
259 * reflection coefficient rSubj (pswRc[j]) can be calcluated by
260 * dividing Vsubj by Psubj.
261 *
262 * Precision is crucial in this routine. At each stage, a
263 * normalization is performed prior to the reflection coefficient
264 * calculation. In addition, to prevent overflow, the
265 * autocorrelation sequence is scaled down by ASHIFT (4) right
266 * shifts.
267 *
268 *
269 * REFERENCES: Sub_Clause 4.1.9 and 4.2.1 of GSM Recomendation 06.20
270 *
271 * KEYWORDS: reflection coefficients, AFLAT, aflat, recursion, LPC
272 * KEYWORDS: autocorrelation
273 *
274 *************************************************************************/
275
276 void aFlatRcDp(Longword *pL_R, Shortword *pswRc)
277 {
278
279 /*_________________________________________________________________________
280 | |
281 | Automatic Variables |
282 |_________________________________________________________________________|
283 */
284
285 Longword pL_pjNewSpace[NP];
286 Longword pL_pjOldSpace[NP];
287 Longword pL_vjNewSpace[2 * NP - 1];
288 Longword pL_vjOldSpace[2 * NP - 1];
289
290 Longword *pL_pjOld;
291 Longword *pL_pjNew;
292 Longword *pL_vjOld;
293 Longword *pL_vjNew;
294 Longword *pL_swap;
295
296 Longword L_temp;
297 Longword L_sum;
298 Shortword swRc,
299 swRcSq,
300 swTemp,
301 swTemp1,
302 swAbsTemp1,
303 swTemp2;
304 int i,
305 j;
306
307
308 /*_________________________________________________________________________
309 | |
310 | Executable Code |
311 |_________________________________________________________________________|
312 */
313
314 pL_pjOld = pL_pjOldSpace;
315 pL_pjNew = pL_pjNewSpace;
316 pL_vjOld = pL_vjOldSpace + NP - 1;
317 pL_vjNew = pL_vjNewSpace + NP - 1;
318
319
320 /* Extract the 0-th reflection coefficient */
321 /*-----------------------------------------*/
322
323 swTemp1 = round(pL_R[1]);
324 swTemp2 = round(pL_R[0]);
325 swAbsTemp1 = abs_s(swTemp1);
326 if (swTemp2 <= 0 || sub(swAbsTemp1, swTemp2) >= 0)
327 {
328 j = 0;
329 for (i = j; i < NP; i++)
330 {
331 pswRc[i] = 0;
332 }
333 return;
334 }
335
336 swRc = divide_s(swAbsTemp1, swTemp2);/* return division result */
337
338 if (sub(swTemp1, swAbsTemp1) == 0)
339 swRc = negate(swRc); /* negate reflection Rc[j] */
340
341 pswRc[0] = swRc; /* copy into the output Rc array */
342
343 for (i = 0; i <= NP; i++)
344 {
345 pL_R[i] = L_shr(pL_R[i], AFSHIFT);
346 }
347
348 /* Initialize the pjOld and vjOld recursion arrays */
349 /*-------------------------------------------------*/
350
351 for (i = 0; i < NP; i++)
352 {
353 pL_pjOld[i] = pL_R[i];
354 pL_vjOld[i] = pL_R[i + 1];
355 }
356 for (i = -1; i > -NP; i--)
357 pL_vjOld[i] = pL_R[-(i + 1)];
358
359
360 /* Compute the square of the j=0 reflection coefficient */
361 /*------------------------------------------------------*/
362
363 swRcSq = mult_r(swRc, swRc);
364
365 /* Update pjNew and vjNew arrays for lattice stage j=1 */
366 /*-----------------------------------------------------*/
367
368 /* Updating pjNew: */
369 /*-------------------*/
370
371 for (i = 0; i <= NP - 2; i++)
372 {
373 L_temp = L_mpy_ls(pL_vjOld[i], swRc);
374 L_sum = L_add(L_temp, pL_pjOld[i]);
375 L_temp = L_mpy_ls(pL_pjOld[i], swRcSq);
376 L_sum = L_add(L_temp, L_sum);
377 L_temp = L_mpy_ls(pL_vjOld[-i], swRc);
378 pL_pjNew[i] = L_add(L_sum, L_temp);
379 }
380
381 /* Updating vjNew: */
382 /*-------------------*/
383
384 for (i = -NP + 2; i <= NP - 2; i++)
385 {
386 L_temp = L_mpy_ls(pL_vjOld[-i - 1], swRcSq);
387 L_sum = L_add(L_temp, pL_vjOld[i + 1]);
388 L_temp = L_mpy_ls(pL_pjOld[(((i + 1) >= 0) ? i + 1 : -(i + 1))], swRc);
389 L_temp = L_shl(L_temp, 1);
390 pL_vjNew[i] = L_add(L_temp, L_sum);
391 }
392
393
394
395 j = 0;
396
397 /* Compute reflection coefficients Rc[1],...,Rc[9] */
398 /*-------------------------------------------------*/
399
400 for (j = 1; j < NP; j++)
401 {
402
403 /* Swap pjNew and pjOld buffers */
404 /*------------------------------*/
405
406 pL_swap = pL_pjNew;
407 pL_pjNew = pL_pjOld;
408 pL_pjOld = pL_swap;
409
410 /* Swap vjNew and vjOld buffers */
411 /*------------------------------*/
412
413 pL_swap = pL_vjNew;
414 pL_vjNew = pL_vjOld;
415 pL_vjOld = pL_swap;
416
417 /* Compute the j-th reflection coefficient */
418 /*-----------------------------------------*/
419
420 swTemp = norm_l(pL_pjOld[0]); /* get shift count */
421 swTemp1 = round(L_shl(pL_vjOld[0], swTemp)); /* normalize num. */
422 swTemp2 = round(L_shl(pL_pjOld[0], swTemp)); /* normalize den. */
423
424 /* Test for invalid divide conditions: a) devisor < 0 b) abs(divident) >
425 * abs(devisor) If either of these conditions is true, zero out
426 * reflection coefficients for i=j,...,NP-1 and return. */
427
428 swAbsTemp1 = abs_s(swTemp1);
429 if (swTemp2 <= 0 || sub(swAbsTemp1, swTemp2) >= 0)
430 {
431 i = j;
432 for (i = j; i < NP; i++)
433 {
434 pswRc[i] = 0;
435 }
436 return;
437 }
438
439 swRc = divide_s(swAbsTemp1, swTemp2); /* return division result */
440 if (sub(swTemp1, swAbsTemp1) == 0)
441 swRc = negate(swRc); /* negate reflection Rc[j] */
442 swRcSq = mult_r(swRc, swRc); /* compute Rc^2 */
443 pswRc[j] = swRc; /* copy Rc[j] to output array */
444
445 /* Update pjNew and vjNew arrays for the next lattice stage if j < NP-1 */
446 /*---------------------------------------------------------------------*/
447
448 /* Updating pjNew: */
449 /*-----------------*/
450
451 for (i = 0; i <= NP - j - 2; i++)
452 {
453 L_temp = L_mpy_ls(pL_vjOld[i], swRc);
454 L_sum = L_add(L_temp, pL_pjOld[i]);
455 L_temp = L_mpy_ls(pL_pjOld[i], swRcSq);
456 L_sum = L_add(L_temp, L_sum);
457 L_temp = L_mpy_ls(pL_vjOld[-i], swRc);
458 pL_pjNew[i] = L_add(L_sum, L_temp);
459 }
460
461 /* Updating vjNew: */
462 /*-----------------*/
463
464 for (i = -NP + j + 2; i <= NP - j - 2; i++)
465 {
466 L_temp = L_mpy_ls(pL_vjOld[-i - 1], swRcSq);
467 L_sum = L_add(L_temp, pL_vjOld[i + 1]);
468 L_temp = L_mpy_ls(pL_pjOld[(((i + 1) >= 0) ? i + 1 : -(i + 1))], swRc);
469 L_temp = L_shl(L_temp, 1);
470 pL_vjNew[i] = L_add(L_temp, L_sum);
471 }
472 }
473 return;
474 }
475
476 /***************************************************************************
477 *
478 * FUNCTION NAME: aToRc
479 *
480 * PURPOSE:
481 *
482 * This subroutine computes a vector of reflection coefficients, given
483 * an input vector of direct form LPC filter coefficients.
484 *
485 * INPUTS:
486 *
487 * NP
488 * order of the LPC filter (global constant)
489 *
490 * swAshift
491 * The number of right shifts applied externally
492 * to the direct form filter coefficients.
493 *
494 * pswAin[0:NP-1]
495 * The input vector of direct form LPC filter
496 * coefficients.
497 *
498 * OUTPUTS:
499 *
500 * pswRc[0:NP-1]
501 * Array containing the reflection coefficients.
502 *
503 * RETURN VALUE:
504 *
505 * siUnstableFlt
506 * If stable reflection coefficients 0, 1 if unstable.
507 *
508 *
509 * DESCRIPTION:
510 *
511 * This function performs the conversion from direct form
512 * coefficients to reflection coefficients. It is used in a_sst()
513 * and interpolateCheck(). In a_sst() reflection coefficients used
514 * as a transitional data format. aToRc() is used for this
515 * conversion.
516 *
517 * When performing interpolation, a stability check must be
518 * performed. interpolateCheck() does this by calling aToRc().
519 *
520 * First coefficients are shifted down by iAshift. NP, the filter
521 * order is 10. The a's and rc's each have NP elements in them. An
522 * elaborate algorithm description can be found on page 443, of
523 * "Digital Processing of Speech Signals" by L.R. Rabiner and R.W.
524 * Schafer; Prentice-Hall; Englewood Cliffs, NJ (USA). 1978.
525 *
526 * REFERENCES: Sub_Clause 4.1.6, and 4.2.3 of GSM Recomendation 06.20
527 *
528 * KEYWORDS: reflectioncoefficients, parcors, conversion, atorc, ks, as
529 * KEYWORDS: parcorcoefficients, lpc, flat, vectorquantization
530 *
531 *************************************************************************/
532
533 static short aToRc(Shortword swAshift, Shortword pswAin[],
534 Shortword pswRc[])
535 {
536
537 /*_________________________________________________________________________
538 | |
539 | Constants |
540 |_________________________________________________________________________|
541 */
542
543 /*_________________________________________________________________________
544 | |
545 | Automatic Variables |
546 |_________________________________________________________________________|
547 */
548
549 Shortword pswTmpSpace[NP],
550 pswASpace[NP],
551 swNormShift,
552 swActShift,
553 swNormProd,
554 swRcOverE,
555 swDiv,
556 *pswSwap,
557 *pswTmp,
558 *pswA;
559
560 Longword L_temp;
561
562 short int siUnstableFlt,
563 i,
564 j; /* Loop control variables */
565
566 /*_________________________________________________________________________
567 | |
568 | Executable Code |
569 |_________________________________________________________________________|
570 */
571
572 /* Initialize starting addresses for temporary buffers */
573 /*-----------------------------------------------------*/
574
575 pswA = pswASpace;
576 pswTmp = pswTmpSpace;
577
578 /* Copy the direct form filter coefficients to a temporary array */
579 /*---------------------------------------------------------------*/
580
581 for (i = 0; i < NP; i++)
582 {
583 pswA[i] = pswAin[i];
584 }
585
586 /* Initialize the flag for filter stability check */
587 /*------------------------------------------------*/
588
589 siUnstableFlt = 0;
590
591 /* Start computation of the reflection coefficients, Rc[9],...,Rc[1] */
592 /*-------------------------------------------------------------------*/
593
594 for (i = NP - 1; i >= 1; i--)
595 {
596
597 pswRc[i] = shl(pswA[i], swAshift); /* write Rc[i] to output array */
598
599 /* Check the stability of i-th reflection coefficient */
600 /*----------------------------------------------------*/
601
602 siUnstableFlt = siUnstableFlt | isSwLimit(pswRc[i]);
603
604 /* Precompute intermediate variables for needed for the computation */
605 /* of direct form filter of order i-1 */
606 /*------------------------------------------------------------------*/
607
608 if (sub(pswRc[i], SW_MIN) == 0)
609 {
610 siUnstableFlt = 1;
611 swRcOverE = 0;
612 swDiv = 0;
613 swActShift = 2;
614 }
615 else
616 {
617 L_temp = LW_MAX; /* Load ~1.0 into accum */
618 L_temp = L_msu(L_temp, pswRc[i], pswRc[i]); /* 1.-Rc[i]*Rc[i] */
619 swNormShift = norm_l(L_temp);
620 L_temp = L_shl(L_temp, swNormShift);
621 swNormProd = extract_h(L_temp);
622 swActShift = add(2, swNormShift);
623 swDiv = divide_s(0x2000, swNormProd);
624 swRcOverE = mult_r(pswRc[i], swDiv);
625 }
626 /* Check stability */
627 /*---------------------*/
628 siUnstableFlt = siUnstableFlt | isSwLimit(swRcOverE);
629
630 /* Compute direct form filter coefficients corresponding to */
631 /* a direct form filter of order i-1 */
632 /*----------------------------------------------------------*/
633
634 for (j = 0; j <= i - 1; j++)
635 {
636 L_temp = L_mult(pswA[j], swDiv);
637 L_temp = L_msu(L_temp, pswA[i - j - 1], swRcOverE);
638 L_temp = L_shl(L_temp, swActShift);
639 pswTmp[j] = round(L_temp);
640 siUnstableFlt = siUnstableFlt | isSwLimit(pswTmp[j]);
641 }
642
643 /* Swap swA and swTmp buffers */
644 /*----------------------------*/
645
646 pswSwap = pswA;
647 pswA = pswTmp;
648 pswTmp = pswSwap;
649 }
650
651 /* Compute reflection coefficient Rc[0] */
652 /*--------------------------------------*/
653
654 pswRc[0] = shl(pswA[0], swAshift); /* write Rc[0] to output array */
655
656 /* Check the stability of 0-th reflection coefficient */
657 /*----------------------------------------------------*/
658
659 siUnstableFlt = siUnstableFlt | isSwLimit(pswRc[0]);
660
661 return (siUnstableFlt);
662 }
663
664 /***************************************************************************
665 *
666 * FUNCTION NAME: a_sst
667 *
668 * PURPOSE:
669 *
670 * The purpose of this function is to perform spectral smoothing of the
671 * direct form filter coefficients
672 *
673 * INPUTS:
674 *
675 * swAshift
676 * number of shift for coefficients
677 *
678 * swAscale
679 * scaling factor for coefficients
680 *
681 * pswDirectFormCoefIn[0:NP-1]
682 *
683 * array of input direct form coefficients
684 *
685 * OUTPUTS:
686 *
687 * pswDirectFormCoefOut[0:NP-1]
688 *
689 * array of output direct form coefficients
690 *
691 * RETURN VALUE:
692 *
693 * none
694 *
695 * DESCRIPTION:
696 *
697 * In a_sst() direct form coefficients are converted to
698 * autocorrelations, and smoothed in that domain. The function is
699 * used in the spectral postfilter. A description can be found in
700 * section 3.2.4 as well as in the reference by Y. Tohkura et al.
701 * "Spectral Smoothing Technique in PARCOR Speech
702 * Analysis-Synthesis", IEEE Trans. ASSP, vol. ASSP-26, pp. 591-596,
703 * Dec. 1978.
704 *
705 * After smoothing is performed conversion back to direct form
706 * coefficients is done by calling aFlatRc(), followed by rcToADp().
707 *
708 * The spectral smoothing filter coefficients with bandwidth set to 300
709 * and a sampling rate of 8000 be :
710 * static ShortwordRom psrSST[NP+1] = { 0x7FFF,
711 * 0x7F5C, 0x7D76, 0x7A5B, 0x7622, 0x70EC,
712 * 0x6ADD, 0x641F, 0x5CDD, 0x5546, 0x4D86
713 * }
714 *
715 * REFERENCES: Sub_Clause 4.2.4 of GSM Recomendation 06.20
716 *
717 * KEYWORDS: spectral smoothing, direct form coef, sst, atorc, atocor
718 * KEYWORDS: levinson
719 *
720 *************************************************************************/
721
722 static void a_sst(Shortword swAshift, Shortword swAscale,
723 Shortword pswDirectFormCoefIn[],
724 Shortword pswDirectFormCoefOut[])
725 {
726
727 /*_________________________________________________________________________
728 | |
729 | Local Static Variables |
730 |_________________________________________________________________________|
731 */
732
733 static ShortwordRom psrSST[NP + 1] = {0x7FFF,
734 0x7F5C, 0x7D76, 0x7A5B, 0x7622, 0x70EC,
735 0x6ADD, 0x641F, 0x5CDD, 0x5546, 0x4D86,
736 };
737
738 /*_________________________________________________________________________
739 | |
740 | Automatic Variables |
741 |_________________________________________________________________________|
742 */
743
744 Longword pL_CorrTemp[NP + 1];
745
746 Shortword pswRCNum[NP],
747 pswRCDenom[NP];
748
749 short int siLoopCnt;
750
751 /*_________________________________________________________________________
752 | |
753 | Executable Code |
754 |_________________________________________________________________________|
755 */
756
757 /* convert direct form coefs to reflection coefs */
758 /* --------------------------------------------- */
759
760 aToRc(swAshift, pswDirectFormCoefIn, pswRCDenom);
761
762 /* convert to autocorrelation coefficients */
763 /* --------------------------------------- */
764
765 rcToCorrDpL(swAshift, swAscale, pswRCDenom, pL_CorrTemp);
766
767 /* do spectral smoothing technique */
768 /* ------------------------------- */
769
770 for (siLoopCnt = 1; siLoopCnt <= NP; siLoopCnt++)
771 {
772 pL_CorrTemp[siLoopCnt] = L_mpy_ls(pL_CorrTemp[siLoopCnt],
773 psrSST[siLoopCnt]);
774 }
775
776 /* Compute the reflection coefficients via AFLAT */
777 /*-----------------------------------------------*/
778
779 aFlatRcDp(pL_CorrTemp, pswRCNum);
780
781
782 /* Convert reflection coefficients to direct form filter coefficients */
783 /*-------------------------------------------------------------------*/
784
785 rcToADp(swAscale, pswRCNum, pswDirectFormCoefOut);
786 }
787
788 /**************************************************************************
789 *
790 * FUNCTION NAME: agcGain
791 *
792 * PURPOSE:
793 *
794 * Figure out what the agc gain should be to make the energy in the
795 * output signal match that of the input signal. Used in the post
796 * filters.
797 *
798 * INPUT:
799 *
800 * pswStateCurr[0:39]
801 * Input signal into agc block whose energy is
802 * to be modified using the gain returned. Signal is not
803 * modified in this routine.
804 *
805 * snsInSigEnergy
806 * Normalized number with shift count - the energy in
807 * the input signal.
808 *
809 * swEngyRShft
810 * Number of right shifts to apply to the vectors energy
811 * to ensure that it remains less than 1.0
812 * (swEngyRShft is always positive or zero)
813 *
814 * OUTPUT:
815 *
816 * none
817 *
818 * RETURN:
819 *
820 * the agc's gain/2 note DIVIDED by 2
821 *
822 *
823 * REFERENCES: Sub_Clause 4.2.2 and 4.2.4 of GSM Recomendation 06.20
824 *
825 * KEYWORDS: postfilter, agc, automaticgaincontrol, leveladjust
826 *
827 *************************************************************************/
828
829 static Shortword agcGain(Shortword pswStateCurr[],
830 struct NormSw snsInSigEnergy, Shortword swEngyRShft)
831 {
832
833 /*_________________________________________________________________________
834 | |
835 | Automatic Variables |
836 |_________________________________________________________________________|
837 */
838
839 Longword L_OutEnergy,
840 L_AgcGain;
841
842 struct NormSw snsOutEnergy,
843 snsAgc;
844
845 Shortword swAgcOut,
846 swAgcShftCnt;
847
848 /*_________________________________________________________________________
849 | |
850 | Executable Code |
851 |_________________________________________________________________________|
852 */
853
854 /* Calculate the energy in the output vector divided by 2 */
855 /*--------------------------------------------------------*/
856
857 snsOutEnergy.sh = g_corr1s(pswStateCurr, swEngyRShft, &L_OutEnergy);
858
859 /* reduce energy by a factor of 2 */
860 snsOutEnergy.sh = add(snsOutEnergy.sh, 1);
861
862 /* if waveform has nonzero energy, find AGC gain */
863 /*-----------------------------------------------*/
864
865 if (L_OutEnergy == 0)
866 {
867 swAgcOut = 0;
868 }
869 else
870 {
871
872 snsOutEnergy.man = round(L_OutEnergy);
873
874 /* divide input energy by 2 */
875 snsInSigEnergy.man = shr(snsInSigEnergy.man, 1);
876
877
878 /* Calculate AGC gain squared */
879 /*----------------------------*/
880
881 snsAgc.man = divide_s(snsInSigEnergy.man, snsOutEnergy.man);
882 swAgcShftCnt = norm_s(snsAgc.man);
883 snsAgc.man = shl(snsAgc.man, swAgcShftCnt);
884
885 /* find shift count for G^2 */
886 /*--------------------------*/
887
888 snsAgc.sh = add(sub(snsInSigEnergy.sh, snsOutEnergy.sh),
889 swAgcShftCnt);
890 L_AgcGain = L_deposit_h(snsAgc.man);
891
892
893 /* Calculate AGC gain */
894 /*--------------------*/
895
896 snsAgc.man = sqroot(L_AgcGain);
897
898
899 /* check if 1/2 sqrt(G^2) >= 1.0 */
900 /* This is equivalent to checking if shiftCnt/2+1 < 0 */
901 /*----------------------------------------------------*/
902
903 if (add(snsAgc.sh, 2) < 0)
904 {
905 swAgcOut = SW_MAX;
906 }
907 else
908 {
909
910 if (0x1 & snsAgc.sh)
911 {
912 snsAgc.man = mult(snsAgc.man, SQRT_ONEHALF);
913 }
914
915 snsAgc.sh = shr(snsAgc.sh, 1); /* shiftCnt/2 */
916 snsAgc.sh = add(snsAgc.sh, 1); /* shiftCnt/2 + 1 */
917
918 if (snsAgc.sh > 0)
919 {
920 snsAgc.man = shr(snsAgc.man, snsAgc.sh);
921 }
922 swAgcOut = snsAgc.man;
923 }
924 }
925
926 return (swAgcOut);
927 }
928
929 /***************************************************************************
930 *
931 * FUNCTION NAME: b_con
932 *
933 * PURPOSE:
934 * Expands codeword into an one dimensional array. The 0/1 input is
935 * changed to an element with magnitude +/- 0.5.
936 *
937 * input output
938 *
939 * 0 -0.5
940 * 1 +0.5
941 *
942 * INPUT:
943 *
944 * swCodeWord
945 * Input codeword, information in the LSB's
946 *
947 * siNumBits
948 * number of bits in the input codeword and number
949 * of elements in output vector
950 *
951 * pswVectOut[0:siNumBits]
952 *
953 * pointer to bit array
954 *
955 * OUTPUT:
956 *
957 * pswVectOut[0:siNumBits]
958 *
959 * signed bit array
960 *
961 * RETURN:
962 *
963 * none
964 *
965 * REFERENCES: Sub_Clause 4.1.10 and 4.2.1 of GSM Recomendation 06.20
966 *
967 * KEYWORDS: b_con, codeword, expansion
968 *
969 *************************************************************************/
970
971 void b_con(Shortword swCodeWord, short siNumBits,
972 Shortword pswVectOut[])
973 {
974
975 /*_________________________________________________________________________
976 | |
977 | Automatic Variables |
978 |_________________________________________________________________________|
979 */
980
981 short int siLoopCnt;
982
983 /*_________________________________________________________________________
984 | |
985 | Executable Code |
986 |_________________________________________________________________________|
987 */
988
989 for (siLoopCnt = 0; siLoopCnt < siNumBits; siLoopCnt++)
990 {
991
992 if (swCodeWord & 1) /* temp accumulator get 0.5 */
993 pswVectOut[siLoopCnt] = (Shortword) 0x4000;
994 else /* temp accumulator gets -0.5 */
995 pswVectOut[siLoopCnt] = (Shortword) 0xc000;
996
997 swCodeWord = shr(swCodeWord, 1);
998 }
999 }
1000
1001 /***************************************************************************
1002 *
1003 * FUNCTION NAME: fp_ex
1004 *
1005 * PURPOSE:
1006 *
1007 * Looks up a vector in the adaptive excitation codebook (long-term
1008 * predictor).
1009 *
1010 * INPUTS:
1011 *
1012 * swOrigLagIn
1013 *
1014 * Extended resolution lag (lag * oversampling factor)
1015 *
1016 * pswLTPState[-147:39]
1017 *
1018 * Adaptive codebook (with space at end for looked up
1019 * vector). Indicies [-147:-1] are the history, [0:39]
1020 * are for the looked up vector.
1021 *
1022 * psrPitchIntrpFirBase[0:59]
1023 * ppsrPVecIntFilt[0:9][0:5] ([tap][phase])
1024 *
1025 * Interpolating FIR filter coefficients.
1026 *
1027 * OUTPUTS:
1028 *
1029 * pswLTPState[0:39]
1030 *
1031 * Array containing the contructed output vector
1032 *
1033 * RETURN VALUE:
1034 * none
1035 *
1036 * DESCRIPTION:
1037 *
1038 * The adaptive codebook consists of the history of the excitation.
1039 * The vector is looked up by going back into this history
1040 * by the amount of the input lag. If the input lag is fractional,
1041 * then the samples to be looked up are interpolated from the existing
1042 * samples in the history.
1043 *
1044 * If the lag is less than the length of the vector to be generated
1045 * (i.e. less than the subframe length), then the lag is doubled
1046 * after the first n samples have been looked up (n = input lag).
1047 * In this way, the samples being generated are not part of the
1048 * codebook. This is described in section 4.1.8.
1049 *
1050 * REFERENCES: Sub_Clause 4.1.8.5 and 4.2.1 of GSM Recomendation 06.20
1051 *
1052 * Keywords: pitch, excitation vector, long term filter, history,
1053 * Keywords: fractional lag, get_ipjj
1054 *
1055 *************************************************************************/
1056
1057
1058
1059 void fp_ex(Shortword swOrigLagIn,
1060 Shortword pswLTPState[])
1061 {
1062
1063 /*_________________________________________________________________________
1064 | |
1065 | Automatic Variables |
1066 |_________________________________________________________________________|
1067 */
1068
1069 Longword L_Temp;
1070 Shortword swIntLag,
1071 swRemain,
1072 swRunningLag;
1073 short int siSampsSoFar,
1074 siSampsThisPass,
1075 i,
1076 j;
1077
1078 /*_________________________________________________________________________
1079 | |
1080 | Executable Code |
1081 |_________________________________________________________________________|
1082 */
1083
1084 /* Loop: execute until all samples in the vector have been looked up */
1085 /*-------------------------------------------------------------------*/
1086
1087 swRunningLag = swOrigLagIn;
1088 siSampsSoFar = 0;
1089 while (siSampsSoFar < S_LEN)
1090 {
1091
1092 /* Get integer lag and remainder. These are used in addressing */
1093 /* the LTP state and the interpolating filter, respectively */
1094 /*--------------------------------------------------------------*/
1095
1096 get_ipjj(swRunningLag, &swIntLag, &swRemain);
1097
1098
1099 /* Get the number of samples to look up in this pass */
1100 /*---------------------------------------------------*/
1101
1102 if (sub(swIntLag, S_LEN) < 0)
1103 siSampsThisPass = swIntLag - siSampsSoFar;
1104 else
1105 siSampsThisPass = S_LEN - siSampsSoFar;
1106
1107 /* Look up samples by interpolating (fractional lag), or copying */
1108 /* (integer lag). */
1109 /*---------------------------------------------------------------*/
1110
1111 if (swRemain == 0)
1112 {
1113
1114 /* Integer lag: copy samples from history */
1115 /*----------------------------------------*/
1116
1117 for (i = siSampsSoFar; i < siSampsSoFar + siSampsThisPass; i++)
1118 pswLTPState[i] = pswLTPState[i - swIntLag];
1119 }
1120 else
1121 {
1122
1123 /* Fractional lag: interpolate to get samples */
1124 /*--------------------------------------------*/
1125
1126 for (i = siSampsSoFar; i < siSampsSoFar + siSampsThisPass; i++)
1127 {
1128
1129 /* first tap with rounding offset */
1130 /*--------------------------------*/
1131 L_Temp = L_mac((long) 32768,
1132 pswLTPState[i - swIntLag - P_INT_MACS / 2],
1133 ppsrPVecIntFilt[0][swRemain]);
1134
1135 for (j = 1; j < P_INT_MACS - 1; j++)
1136 {
1137
1138 L_Temp = L_mac(L_Temp,
1139 pswLTPState[i - swIntLag - P_INT_MACS / 2 + j],
1140 ppsrPVecIntFilt[j][swRemain]);
1141
1142 }
1143
1144 pswLTPState[i] = extract_h(L_mac(L_Temp,
1145 pswLTPState[i - swIntLag + P_INT_MACS / 2 - 1],
1146 ppsrPVecIntFilt[P_INT_MACS - 1][swRemain]));
1147 }
1148 }
1149
1150 /* Done with this pass: update loop controls */
1151 /*-------------------------------------------*/
1152
1153 siSampsSoFar += siSampsThisPass;
1154 swRunningLag = add(swRunningLag, swOrigLagIn);
1155 }
1156 }
1157
1158 /***************************************************************************
1159 *
1160 * FUNCTION NAME: g_corr1 (no scaling)
1161 *
1162 * PURPOSE:
1163 *
1164 * Calculates energy in subframe vector. Differs from g_corr1s,
1165 * in that there the estimate of the maximum possible
1166 * energy is < 1.0
1167 *
1168 *
1169 * INPUT:
1170 *
1171 * pswIn[0:39]
1172 * A subframe vector.
1173 *
1174 *
1175 * OUTPUT:
1176 *
1177 * *pL_out
1178 * A Longword containing the normalized energy
1179 * in the input vector.
1180 *
1181 * RETURN:
1182 *
1183 * swOut
1184 * Number of right shifts which the accumulator was
1185 * shifted to normalize it. Negative number implies
1186 * a left shift, and therefore an energy larger than
1187 * 1.0.
1188 *
1189 * REFERENCES: Sub_Clause 4.1.10.2 and 4.2.1 of GSM Recomendation 06.20
1190 *
1191 * KEYWORDS: energy, autocorrelation, correlation, g_corr1
1192 *
1193 *
1194 *************************************************************************/
1195
1196 Shortword g_corr1(Shortword *pswIn, Longword *pL_out)
1197 {
1198
1199
1200 /*_________________________________________________________________________
1201 | |
1202 | Automatic Variables |
1203 |_________________________________________________________________________|
1204 */
1205
1206 Longword L_sum;
1207 Shortword swEngyLShft;
1208 int i;
1209
1210
1211 /*_________________________________________________________________________
1212 | |
1213 | Executable Code |
1214 |_________________________________________________________________________|
1215 */
1216
1217
1218 /* Calculate energy in subframe vector (40 samples) */
1219 /*--------------------------------------------------*/
1220
1221 L_sum = L_mult(pswIn[0], pswIn[0]);
1222 for (i = 1; i < S_LEN; i++)
1223 {
1224 L_sum = L_mac(L_sum, pswIn[i], pswIn[i]);
1225 }
1226
1227
1228
1229 if (L_sum != 0)
1230 {
1231
1232 /* Normalize the energy in the output Longword */
1233 /*---------------------------------------------*/
1234
1235 swEngyLShft = norm_l(L_sum);
1236 *pL_out = L_shl(L_sum, swEngyLShft); /* normalize output
1237 * Longword */
1238 }
1239 else
1240 {
1241
1242 /* Special case: energy is zero */
1243 /*------------------------------*/
1244
1245 *pL_out = L_sum;
1246 swEngyLShft = 0;
1247 }
1248
1249 return (swEngyLShft);
1250 }
1251
1252 /***************************************************************************
1253 *
1254 * FUNCTION NAME: g_corr1s (g_corr1 with scaling)
1255 *
1256 * PURPOSE:
1257 *
1258 * Calculates energy in subframe vector. Differs from g_corr1,
1259 * in that there is an estimate of the maximum possible energy in the
1260 * vector.
1261 *
1262 * INPUT:
1263 *
1264 * pswIn[0:39]
1265 * A subframe vector.
1266 *
1267 * swEngyRShft
1268 *
1269 * Number of right shifts to apply to the vectors energy
1270 * to ensure that it remains less than 1.0
1271 * (swEngyRShft is always positive or zero)
1272 *
1273 * OUTPUT:
1274 *
1275 * *pL_out
1276 * A Longword containing the normalized energy
1277 * in the input vector.
1278 *
1279 * RETURN:
1280 *
1281 * swOut
1282 * Number of right shifts which the accumulator was
1283 * shifted to normalize it. Negative number implies
1284 * a left shift, and therefore an energy larger than
1285 * 1.0.
1286 *
1287 * REFERENCES: Sub-Clause 4.1.8, 4.2.1, 4.2.2, and 4.2.4
1288 * of GSM Recomendation 06.20
1289 *
1290 * keywords: energy, autocorrelation, correlation, g_corr1
1291 *
1292 *
1293 *************************************************************************/
1294
1295 Shortword g_corr1s(Shortword pswIn[], Shortword swEngyRShft,
1296 Longword *pL_out)
1297 {
1298
1299
1300 /*_________________________________________________________________________
1301 | |
1302 | Automatic Variables |
1303 |_________________________________________________________________________|
1304 */
1305
1306 Longword L_sum;
1307 Shortword swTemp,
1308 swEngyLShft;
1309 Shortword swInputRShft;
1310
1311 int i;
1312
1313
1314 /*_________________________________________________________________________
1315 | |
1316 | Executable Code |
1317 |_________________________________________________________________________|
1318 */
1319
1320
1321 /* Calculate energy in subframe vector (40 samples) */
1322 /*--------------------------------------------------*/
1323
1324 if (sub(swEngyRShft, 1) <= 0)
1325 {
1326
1327 /* use the energy shift factor, although it is an odd shift count */
1328 /*----------------------------------------------------------------*/
1329
1330 swTemp = shr(pswIn[0], swEngyRShft);
1331 L_sum = L_mult(pswIn[0], swTemp);
1332 for (i = 1; i < S_LEN; i++)
1333 {
1334 swTemp = shr(pswIn[i], swEngyRShft);
1335 L_sum = L_mac(L_sum, pswIn[i], swTemp);
1336 }
1337
1338 }
1339 else
1340 {
1341
1342 /* convert energy shift factor to an input shift factor */
1343 /*------------------------------------------------------*/
1344
1345 swInputRShft = shift_r(swEngyRShft, -1);
1346 swEngyRShft = shl(swInputRShft, 1);
1347
1348 swTemp = shr(pswIn[0], swInputRShft);
1349 L_sum = L_mult(swTemp, swTemp);
1350 for (i = 1; i < S_LEN; i++)
1351 {
1352 swTemp = shr(pswIn[i], swInputRShft);
1353 L_sum = L_mac(L_sum, swTemp, swTemp);
1354 }
1355 }
1356
1357 if (L_sum != 0)
1358 {
1359
1360 /* Normalize the energy in the output Longword */
1361 /*---------------------------------------------*/
1362
1363 swTemp = norm_l(L_sum);
1364 *pL_out = L_shl(L_sum, swTemp); /* normalize output Longword */
1365 swEngyLShft = sub(swTemp, swEngyRShft);
1366 }
1367 else
1368 {
1369
1370 /* Special case: energy is zero */
1371 /*------------------------------*/
1372
1373 *pL_out = L_sum;
1374 swEngyLShft = 0;
1375 }
1376
1377 return (swEngyLShft);
1378 }
1379
1380 /***************************************************************************
1381 *
1382 * FUNCTION NAME: getSfrmLpc
1383 *
1384 * PURPOSE:
1385 *
1386 * Given frame information from past and present frame, interpolate
1387 * (or copy) the frame based LPC coefficients into subframe
1388 * lpc coeffs, i.e. the ones which will be used by the subframe
1389 * as opposed to those coded and transmitted.
1390 *
1391 * INPUTS:
1392 *
1393 * siSoftInterpolation
1394 *
1395 * interpolate 1/0, a coded parameter.
1396 *
1397 * swPrevR0,swNewR0
1398 *
1399 * Rq0 for the last frame and for this frame.
1400 * These are the decoded values, not the codewords.
1401 *
1402 * Previous lpc coefficients from the previous frame:
1403 * in all filters below array[0] is the t=-1 element array[9]
1404 * t=-10 element.
1405 *
1406 * pswPrevFrmKs[0:9]
1407 *
1408 * decoded version of the rc's tx'd last frame
1409 *
1410 * pswPrevFrmAs[0:9]
1411 *
1412 * the above K's converted to A's. i.e. direct
1413 * form coefficients.
1414 *
1415 * pswPrevFrmPFNum[0:9], pswPrevFrmPFDenom[0:9]
1416 *
1417 * numerator and denominator coefficients used in the
1418 * postfilter
1419 *
1420 * Current lpc coefficients from the current frame:
1421 *
1422 * pswNewFrmKs[0:9], pswNewFrmAs[0:9],
1423 * pswNewFrmPFNum[0:9], pswNewFrmPFDenom[0:9] same as above.
1424 *
1425 * OUTPUTS:
1426 *
1427 * psnsSqrtRs[0:3]
1428 *
1429 * a normalized number (struct NormSw)
1430 * containing an estimate of RS for each subframe.
1431 * (number and a shift)
1432 *
1433 * ppswSynthAs[0:3][0:9]
1434 *
1435 * filter coefficients used by the synthesis filter.
1436 *
1437 * ppswPFNumAs[0:3][0:9]
1438 *
1439 * filter coefficients used by the postfilters
1440 * numerator.
1441 *
1442 * ppswPFDenomAs[0:3][0:9]
1443 *
1444 * filter coefficients used by postfilters denominator.
1445 *
1446 * RETURN VALUE:
1447 *
1448 * None
1449 *
1450 * DESCRIPTION:
1451 *
1452 * For interpolated subframes, the direct form coefficients
1453 * are converted to reflection coeffiecients to check for
1454 * filter stability. If unstable, the uninterpolated coef.
1455 * are used for that subframe.
1456 *
1457 * Interpolation is described in section 4.1.6, "Soft Interpolation
1458 * of the Spectral Parameters"
1459 *
1460 * REFERENCES: Sub_clause 4.2.1 of GSM Recomendation 06.20
1461 *
1462 * KEYWORDS: soft interpolation, int_lpc, interpolate, atorc,res_eng,i_mov
1463 *
1464 *************************************************************************/
1465
1466 void getSfrmLpc(short int siSoftInterpolation,
1467 Shortword swPrevR0, Shortword swNewR0,
1468 /* last frm */ Shortword pswPrevFrmKs[], Shortword pswPrevFrmAs[],
1469 Shortword pswPrevFrmPFNum[],
1470 Shortword pswPrevFrmPFDenom[],
1471
1472 /* this frm */ Shortword pswNewFrmKs[], Shortword pswNewFrmAs[],
1473 Shortword pswNewFrmPFNum[],
1474 Shortword pswNewFrmPFDenom[],
1475
1476 /* output */ struct NormSw *psnsSqrtRs,
1477 Shortword *ppswSynthAs[], Shortword *ppswPFNumAs[],
1478 Shortword *ppswPFDenomAs[])
1479 {
1480
1481 /*_________________________________________________________________________
1482 | |
1483 | Local Static Variables |
1484 |_________________________________________________________________________|
1485 */
1486
1487
1488 /*_________________________________________________________________________
1489 | |
1490 | Automatic Variables |
1491 |_________________________________________________________________________|
1492 */
1493
1494 short int siSfrm,
1495 siStable,
1496 i;
1497
1498 Longword L_Temp1,
1499 L_Temp2;
1500
1501 /*_________________________________________________________________________
1502 | |
1503 | Executable Code |
1504 |_________________________________________________________________________|
1505 */
1506
1507 if (siSoftInterpolation)
1508 {
1509 /* yes, interpolating */
1510 /* ------------------ */
1511
1512 siSfrm = 0;
1513
1514 siStable = interpolateCheck(pswPrevFrmKs, pswPrevFrmAs,
1515 pswPrevFrmAs, pswNewFrmAs,
1516 psrOldCont[siSfrm], psrNewCont[siSfrm],
1517 swPrevR0,
1518 &psnsSqrtRs[siSfrm],
1519 ppswSynthAs[siSfrm]);
1520 if (siStable)
1521 {
1522
1523 /* interpolate between direct form coefficient sets */
1524 /* for both numerator and denominator coefficients */
1525 /* assume output will be stable */
1526 /* ------------------------------------------------ */
1527
1528 for (i = 0; i < NP; i++)
1529 {
1530 L_Temp1 = L_mult(pswNewFrmPFNum[i], psrNewCont[siSfrm]);
1531 ppswPFNumAs[siSfrm][i] = mac_r(L_Temp1, pswPrevFrmPFNum[i],
1532 psrOldCont[siSfrm]);
1533 L_Temp2 = L_mult(pswNewFrmPFDenom[i], psrNewCont[siSfrm]);
1534 ppswPFDenomAs[siSfrm][i] = mac_r(L_Temp2, pswPrevFrmPFDenom[i],
1535 psrOldCont[siSfrm]);
1536 }
1537 }
1538 else
1539 {
1540 /* this subframe is unstable */
1541 /* ------------------------- */
1542 for (i = 0; i < NP; i++)
1543 {
1544 ppswPFNumAs[siSfrm][i] = pswPrevFrmPFNum[i];
1545 ppswPFDenomAs[siSfrm][i] = pswPrevFrmPFDenom[i];
1546 }
1547 }
1548 for (siSfrm = 1; siSfrm < N_SUB - 1; siSfrm++)
1549 {
1550
1551 siStable = interpolateCheck(pswNewFrmKs, pswNewFrmAs,
1552 pswPrevFrmAs, pswNewFrmAs,
1553 psrOldCont[siSfrm], psrNewCont[siSfrm],
1554 swNewR0,
1555 &psnsSqrtRs[siSfrm],
1556 ppswSynthAs[siSfrm]);
1557 if (siStable)
1558 {
1559
1560 /* interpolate between direct form coefficient sets */
1561 /* for both numerator and denominator coefficients */
1562 /* assume output will be stable */
1563 /* ------------------------------------------------ */
1564
1565 for (i = 0; i < NP; i++)
1566 {
1567 L_Temp1 = L_mult(pswNewFrmPFNum[i], psrNewCont[siSfrm]);
1568 ppswPFNumAs[siSfrm][i] = mac_r(L_Temp1, pswPrevFrmPFNum[i],
1569 psrOldCont[siSfrm]);
1570 L_Temp2 = L_mult(pswNewFrmPFDenom[i], psrNewCont[siSfrm]);
1571 ppswPFDenomAs[siSfrm][i] = mac_r(L_Temp2, pswPrevFrmPFDenom[i],
1572 psrOldCont[siSfrm]);
1573 }
1574 }
1575 else
1576 {
1577 /* this subframe has unstable filter coeffs, would like to
1578 * interpolate but can not */
1579 /* -------------------------------------- */
1580 for (i = 0; i < NP; i++)
1581 {
1582 ppswPFNumAs[siSfrm][i] = pswNewFrmPFNum[i];
1583 ppswPFDenomAs[siSfrm][i] = pswNewFrmPFDenom[i];
1584 }
1585 }
1586 }
1587 /* the last subframe never interpolate */
1588 /* ----------------------------------- */
1589 siSfrm = 3;
1590 for (i = 0; i < NP; i++)
1591 {
1592 ppswPFNumAs[siSfrm][i] = pswNewFrmPFNum[i];
1593 ppswPFDenomAs[siSfrm][i] = pswNewFrmPFDenom[i];
1594 ppswSynthAs[siSfrm][i] = pswNewFrmAs[i];
1595 }
1596
1597 res_eng(pswNewFrmKs, swNewR0, &psnsSqrtRs[siSfrm]);
1598
1599 }
1600 /* SoftInterpolation == 0 - no interpolation */
1601 /* ------------------------------------------ */
1602 else
1603 {
1604 siSfrm = 0;
1605 for (i = 0; i < NP; i++)
1606 {
1607 ppswPFNumAs[siSfrm][i] = pswPrevFrmPFNum[i];
1608 ppswPFDenomAs[siSfrm][i] = pswPrevFrmPFDenom[i];
1609 ppswSynthAs[siSfrm][i] = pswPrevFrmAs[i];
1610 }
1611
1612 res_eng(pswPrevFrmKs, swPrevR0, &psnsSqrtRs[siSfrm]);
1613
1614 /* for subframe 1 and all subsequent sfrms, use result from new frm */
1615 /* ---------------------------------------------------------------- */
1616
1617
1618 res_eng(pswNewFrmKs, swNewR0, &psnsSqrtRs[1]);
1619
1620 for (siSfrm = 1; siSfrm < N_SUB; siSfrm++)
1621 {
1622
1623
1624 psnsSqrtRs[siSfrm].man = psnsSqrtRs[1].man;
1625 psnsSqrtRs[siSfrm].sh = psnsSqrtRs[1].sh;
1626
1627 for (i = 0; i < NP; i++)
1628 {
1629 ppswPFNumAs[siSfrm][i] = pswNewFrmPFNum[i];
1630 ppswPFDenomAs[siSfrm][i] = pswNewFrmPFDenom[i];
1631 ppswSynthAs[siSfrm][i] = pswNewFrmAs[i];
1632 }
1633 }
1634 }
1635 }
1636
1637 /***************************************************************************
1638 *
1639 * FUNCTION NAME: get_ipjj
1640 *
1641 * PURPOSE:
1642 *
1643 * This subroutine calculates IP, the single-resolution lag rounded
1644 * down to the nearest integer, and JJ, the remainder when the
1645 * extended resolution lag is divided by the oversampling factor
1646 *
1647 * INPUTS:
1648 *
1649 * swLagIn
1650 * extended resolution lag as an integer, i.e.
1651 * fractional lag x oversampling factor
1652 *
1653 * OUTPUTS:
1654 *
1655 * *pswIp
1656 * fractional lag rounded down to nearest integer, IP
1657 *
1658 * *pswJj
1659 * the remainder JJ
1660 *
1661 * RETURN VALUE:
1662 *
1663 * none
1664 *
1665 * DESCRIPTION:
1666 *
1667 * ip = integer[lag/OS_FCTR]
1668 * jj = integer_round[((lag/OS_FCTR)-ip)*(OS_FCTR)]
1669 * if the rounding caused an 'overflow'
1670 * set remainder jj to 0 and add 'carry' to ip
1671 *
1672 * This routine is involved in the mechanics of fractional and
1673 * integer LTP searchs. The LTP is described in section 5.
1674 *
1675 * REFERENCES: Sub-clause 4.1.8 and 4.2.2 of GSM Recomendation 06.20
1676 *
1677 * KEYWORDS: lag, fractional, remainder, ip, jj, get_ipjj
1678 *
1679 *************************************************************************/
1680
1681 void get_ipjj(Shortword swLagIn,
1682 Shortword *pswIp, Shortword *pswJj)
1683 {
1684
1685 /*_________________________________________________________________________
1686 | |
1687 | Local Constants |
1688 |_________________________________________________________________________|
1689 */
1690
1691 #define OS_FCTR_INV (Shortword)0x1555/* SW_MAX/OS_FCTR */
1692
1693 /*_________________________________________________________________________
1694 | |
1695 | Automatic Variables |
1696 |_________________________________________________________________________|
1697 */
1698
1699 Longword L_Temp;
1700
1701 Shortword swTemp,
1702 swTempIp,
1703 swTempJj;
1704
1705 /*_________________________________________________________________________
1706 | |
1707 | Executable Code |
1708 |_________________________________________________________________________|
1709 */
1710
1711 /* calculate ip */
1712 /* ------------ */
1713
1714 L_Temp = L_mult(OS_FCTR_INV, swLagIn); /* lag/OS_FCTR */
1715 swTempIp = extract_h(L_Temp);
1716
1717 /* calculate jj */
1718 /* ------------ */
1719
1720 swTemp = extract_l(L_Temp); /* loose ip */
1721 swTemp = shr(swTemp, 1); /* isolate jj fraction */
1722 swTemp = swTemp & SW_MAX;
1723 L_Temp = L_mult(swTemp, OS_FCTR); /* ((lag/OS_FCTR)-ip))*(OS_FCTR) */
1724 swTemp = round(L_Temp); /* round and pick-off jj */
1725 if (sub(swTemp, OS_FCTR) == 0)
1726 { /* if 'overflow ' */
1727 swTempJj = 0; /* set remainder,jj to 0 */
1728 swTempIp = add(swTempIp, 1); /* 'carry' overflow into ip */
1729 }
1730 else
1731 {
1732 swTempJj = swTemp; /* read-off remainder,jj */
1733 }
1734
1735 /* return ip and jj */
1736 /* ---------------- */
1737
1738 *pswIp = swTempIp;
1739 *pswJj = swTempJj;
1740 }
1741
1742 /***************************************************************************
1743 *
1744 * FUNCTION NAME: interpolateCheck
1745 *
1746 * PURPOSE:
1747 *
1748 * Interpolates between direct form coefficient sets.
1749 * Before releasing the interpolated coefficients, they are checked.
1750 * If unstable, the "old" parameters are used.
1751 *
1752 * INPUTS:
1753 *
1754 * pswRefKs[0:9]
1755 * decoded version of the rc's tx'd last frame
1756 *
1757 * pswRefCoefsA[0:9]
1758 * above K's converted to direct form coefficients
1759 *
1760 * pswOldCoefsA[0:9]
1761 * array of old Coefseters
1762 *
1763 * pswNewCoefsA[0:9]
1764 * array of new Coefseters
1765 *
1766 * swOldPer
1767 * amount old coefs supply to the output
1768 *
1769 * swNewPer
1770 * amount new coefs supply to the output
1771 *
1772 * ASHIFT
1773 * shift for reflection coef. conversion
1774 *
1775 * swRq
1776 * quantized energy to use for subframe
1777 * *
1778 * OUTPUTS:
1779 *
1780 * psnsSqrtRsOut
1781 * output pointer to sqrt(RS) normalized
1782 *
1783 * pswCoefOutA[0:9]
1784 * output coefficients
1785 *
1786 * RETURN VALUE:
1787 *
1788 * siInterp_flg
1789 * temporary subframe interpolation flag
1790 * 0 - coef. interpolated, 1 -coef. not interpolated
1791 *
1792 * DESCRIPTION:
1793 *
1794 * For interpolated subframes, the direct form coefficients
1795 * are converted to reflection coefficients to check for
1796 * filter stability. If unstable, the uninterpolated coef.
1797 * are used for that subframe. Section 4.1.6 describes
1798 * interpolation.
1799 *
1800 * REFERENCES: Sub-clause 4.1.6 and 4.2.3 of GSM Recomendation 06.20
1801 *
1802 * KEYWORDS: soft interpolation, int_lpc, interpolate, atorc,res_eng,i_mov
1803 *
1804 *************************************************************************/
1805
1806 short int interpolateCheck(Shortword pswRefKs[],
1807 Shortword pswRefCoefsA[],
1808 Shortword pswOldCoefsA[], Shortword pswNewCoefsA[],
1809 Shortword swOldPer, Shortword swNewPer,
1810 Shortword swRq,
1811 struct NormSw *psnsSqrtRsOut,
1812 Shortword pswCoefOutA[])
1813 {
1814
1815 /*_________________________________________________________________________
1816 | |
1817 | Automatic Variables |
1818 |_________________________________________________________________________|
1819 */
1820
1821 Shortword pswRcTemp[NP];
1822
1823 Longword L_Temp;
1824
1825 short int siInterp_flg,
1826 i;
1827
1828 /*_________________________________________________________________________
1829 | |
1830 | Executable Code |
1831 |_________________________________________________________________________|
1832 */
1833
1834 /* Interpolation loop, NP is order of LPC filter */
1835 /* --------------------------------------------- */
1836
1837 for (i = 0; i < NP; i++)
1838 {
1839 L_Temp = L_mult(pswNewCoefsA[i], swNewPer);
1840 pswCoefOutA[i] = mac_r(L_Temp, pswOldCoefsA[i], swOldPer);
1841 }
1842
1843 /* Convert to reflection coefficients and check stability */
1844 /* ------------------------------------------------------ */
1845
1846 if (aToRc(ASHIFT, pswCoefOutA, pswRcTemp) != 0)
1847 {
1848
1849 /* Unstable, use uninterpolated parameters and compute RS update the
1850 * state with the frame data closest to this subfrm */
1851 /* --------------------------------------------------------- */
1852
1853 res_eng(pswRefKs, swRq, psnsSqrtRsOut);
1854
1855 for (i = 0; i < NP; i++)
1856 {
1857 pswCoefOutA[i] = pswRefCoefsA[i];
1858 }
1859 siInterp_flg = 0;
1860 }
1861 else
1862 {
1863
1864 /* Stable, compute RS */
1865 /* ------------------ */
1866 res_eng(pswRcTemp, swRq, psnsSqrtRsOut);
1867
1868 /* Set temporary subframe interpolation flag */
1869 /* ----------------------------------------- */
1870 siInterp_flg = 1;
1871 }
1872
1873 /* Return subframe interpolation flag */
1874 /* ---------------------------------- */
1875 return (siInterp_flg);
1876 }
1877
1878 /***************************************************************************
1879 *
1880 * FUNCTION NAME: lagDecode
1881 *
1882 * PURPOSE:
1883 *
1884 * The purpose of this function is to decode the lag received from the
1885 * speech encoder into a full resolution lag for the speech decoder
1886 *
1887 * INPUTS:
1888 *
1889 * swDeltaLag
1890 *
1891 * lag received from channel decoder
1892 *
1893 * giSfrmCnt
1894 *
1895 * current sub-frame count
1896 *
1897 * swLastLag
1898 *
1899 * previous lag to un-delta this sub-frame's lag
1900 *
1901 * psrLagTbl[0:255]
1902 *
1903 * table used to look up full resolution lag
1904 *
1905 * OUTPUTS:
1906 *
1907 * swLastLag
1908 *
1909 * new previous lag for next sub-frame
1910 *
1911 * RETURN VALUE:
1912 *
1913 * swLag
1914 *
1915 * decoded full resolution lag
1916 *
1917 * DESCRIPTION:
1918 *
1919 * If first subframe, use lag as index to look up table directly.
1920 *
1921 * If it is one of the other subframes, the codeword represents a
1922 * delta offset. The previously decoded lag is used as a starting
1923 * point for decoding the current lag.
1924 *
1925 * REFERENCES: Sub-clause 4.2.1 of GSM Recomendation 06.20
1926 *
1927 * KEYWORDS: deltalags, lookup lag
1928 *
1929 *************************************************************************/
1930
1931 static Shortword lagDecode(Shortword swDeltaLag)
1932 {
1933
1934 /*_________________________________________________________________________
1935 | |
1936 | Local Constants |
1937 |_________________________________________________________________________|
1938 */
1939
1940 #define DELTA_LEVELS_D2 DELTA_LEVELS/2
1941 #define MAX_LAG 0x00ff
1942 #define MIN_LAG 0x0000
1943
1944 /*_________________________________________________________________________
1945 | |
1946 | Local Static Variables |
1947 |_________________________________________________________________________|
1948 */
1949
1950 static Shortword swLastLag;
1951
1952 /*_________________________________________________________________________
1953 | |
1954 | Automatic Variables |
1955 |_________________________________________________________________________|
1956 */
1957
1958 Shortword swLag;
1959
1960 /*_________________________________________________________________________
1961 | |
1962 | Executable Code |
1963 |_________________________________________________________________________|
1964 */
1965
1966 /* first sub-frame */
1967 /* --------------- */
1968
1969 if (giSfrmCnt == 0)
1970 {
1971 swLastLag = swDeltaLag;
1972 }
1973
1974 /* remaining sub-frames */
1975 /* -------------------- */
1976
1977 else
1978 {
1979
1980 /* get lag biased around 0 */
1981 /* ----------------------- */
1982
1983 swLag = sub(swDeltaLag, DELTA_LEVELS_D2);
1984
1985 /* get real lag relative to last */
1986 /* ----------------------------- */
1987
1988 swLag = add(swLag, swLastLag);
1989
1990 /* clip to max or min */
1991 /* ------------------ */
1992
1993 if (sub(swLag, MAX_LAG) > 0)
1994 {
1995 swLastLag = MAX_LAG;
1996 }
1997 else if (sub(swLag, MIN_LAG) < 0)
1998 {
1999 swLastLag = MIN_LAG;
2000 }
2001 else
2002 {
2003 swLastLag = swLag;
2004 }
2005 }
2006
2007 /* return lag after look up */
2008 /* ------------------------ */
2009
2010 swLag = psrLagTbl[swLastLag];
2011 return (swLag);
2012 }
2013
2014 /***************************************************************************
2015 *
2016 * FUNCTION NAME: lookupVq
2017 *
2018 * PURPOSE:
2019 *
2020 * The purpose of this function is to recover the reflection coeffs from
2021 * the received LPC codewords.
2022 *
2023 * INPUTS:
2024 *
2025 * pswVqCodeWds[0:2]
2026 *
2027 * the codewords for each of the segments
2028 *
2029 * OUTPUTS:
2030 *
2031 * pswRCOut[0:NP-1]
2032 *
2033 * the decoded reflection coefficients
2034 *
2035 * RETURN VALUE:
2036 *
2037 * none.
2038 *
2039 * DESCRIPTION:
2040 *
2041 * For each segment do the following:
2042 * setup the retrieval pointers to the correct vector
2043 * get that vector
2044 *
2045 * REFERENCES: Sub-clause 4.2.3 of GSM Recomendation 06.20
2046 *
2047 * KEYWORDS: vq, vectorquantizer, lpc
2048 *
2049 *************************************************************************/
2050
2051 static void lookupVq(Shortword pswVqCodeWds[], Shortword pswRCOut[])
2052 {
2053 /*_________________________________________________________________________
2054 | |
2055 | Local Constants |
2056 |_________________________________________________________________________|
2057 */
2058
2059 #define LSP_MASK 0x00ff
2060
2061 /*_________________________________________________________________________
2062 | |
2063 | Automatic Variables |
2064 |_________________________________________________________________________|
2065 */
2066
2067 short int siSeg,
2068 siIndex,
2069 siVector,
2070 siVector1,
2071 siVector2,
2072 siWordPtr;
2073
2074 ShortwordRom *psrQTable;
2075
2076 /*_________________________________________________________________________
2077 | |
2078 | Executable Code |
2079 |_________________________________________________________________________|
2080 */
2081
2082 /* for each segment */
2083 /* ---------------- */
2084
2085 for (siSeg = 0; siSeg < QUANT_NUM_OF_TABLES; siSeg++)
2086 {
2087
2088 siVector = pswVqCodeWds[siSeg];
2089 siIndex = psvqIndex[siSeg].l;
2090
2091 if (sub(siSeg, 2) == 0)
2092 { /* segment 3 */
2093
2094 /* set table */
2095 /* --------- */
2096
2097 psrQTable = psrQuant3;
2098
2099 /* set offset into table */
2100 /* ---------------------- */
2101
2102 siWordPtr = add(siVector, siVector);
2103
2104 /* look up coeffs */
2105 /* -------------- */
2106
2107 siVector1 = psrQTable[siWordPtr];
2108 siVector2 = psrQTable[siWordPtr + 1];
2109
2110 pswRCOut[siIndex - 1] = psrSQuant[shr(siVector1, 8) & LSP_MASK];
2111 pswRCOut[siIndex] = psrSQuant[siVector1 & LSP_MASK];
2112 pswRCOut[siIndex + 1] = psrSQuant[shr(siVector2, 8) & LSP_MASK];
2113 pswRCOut[siIndex + 2] = psrSQuant[siVector2 & LSP_MASK];
2114 }
2115 else
2116 { /* segments 1 and 2 */
2117
2118 /* set tables */
2119 /* ---------- */
2120
2121 if (siSeg == 0)
2122 {
2123 psrQTable = psrQuant1;
2124 }
2125 else
2126 {
2127 psrQTable = psrQuant2;
2128
2129 }
2130
2131 /* set offset into table */
2132 /* --------------------- */
2133
2134 siWordPtr = add(siVector, siVector);
2135 siWordPtr = add(siWordPtr, siVector);
2136 siWordPtr = shr(siWordPtr, 1);
2137
2138 /* look up coeffs */
2139 /* -------------- */
2140
2141 siVector1 = psrQTable[siWordPtr];
2142 siVector2 = psrQTable[siWordPtr + 1];
2143
2144 if ((siVector & 0x0001) == 0)
2145 {
2146 pswRCOut[siIndex - 1] = psrSQuant[shr(siVector1, 8) & LSP_MASK];
2147 pswRCOut[siIndex] = psrSQuant[siVector1 & LSP_MASK];
2148 pswRCOut[siIndex + 1] = psrSQuant[shr(siVector2, 8) & LSP_MASK];
2149 }
2150 else
2151 {
2152 pswRCOut[siIndex - 1] = psrSQuant[siVector1 & LSP_MASK];
2153 pswRCOut[siIndex] = psrSQuant[shr(siVector2, 8) & LSP_MASK];
2154 pswRCOut[siIndex + 1] = psrSQuant[siVector2 & LSP_MASK];
2155 }
2156 }
2157 }
2158 }
2159
2160 /***************************************************************************
2161 *
2162 * FUNCTION NAME: lpcFir
2163 *
2164 * PURPOSE:
2165 *
2166 * The purpose of this function is to perform direct form fir filtering
2167 * assuming a NP order filter and given state, coefficients, and input.
2168 *
2169 * INPUTS:
2170 *
2171 * NP
2172 * order of the lpc filter
2173 *
2174 * S_LEN
2175 * number of samples to filter
2176 *
2177 * pswInput[0:S_LEN-1]
2178 *
2179 * input array of points to be filtered.
2180 * pswInput[0] is the oldest point (first to be filtered)
2181 * pswInput[siLen-1] is the last point filtered (newest)
2182 *
2183 * pswCoef[0:NP-1]
2184 *
2185 * array of direct form coefficients
2186 * pswCoef[0] = coeff for delay n = -1
2187 * pswCoef[NP-1] = coeff for delay n = -NP
2188 *
2189 * ASHIFT
2190 * number of shifts input A's have been shifted down by
2191 *
2192 * LPC_ROUND
2193 * rounding constant
2194 *
2195 * pswState[0:NP-1]
2196 *
2197 * array of the filter state following form of pswCoef
2198 * pswState[0] = state of filter for delay n = -1
2199 * pswState[NP-1] = state of filter for delay n = -NP
2200 *
2201 * OUTPUTS:
2202 *
2203 * pswState[0:NP-1]
2204 *
2205 * updated filter state, ready to filter
2206 * pswInput[siLen], i.e. the next point
2207 *
2208 * pswFiltOut[0:S_LEN-1]
2209 *
2210 * the filtered output
2211 * same format as pswInput, pswFiltOut[0] is oldest point
2212 *
2213 * RETURN VALUE:
2214 *
2215 * none
2216 *
2217 * DESCRIPTION:
2218 *
2219 * because of the default sign of the coefficients the
2220 * formula for the filter is :
2221 * i=0, i < S_LEN
2222 * out[i] = rounded(state[i]*coef[0])
2223 * j=1, j < NP
2224 * out[i] += state[j]*coef[j] (state is taken from either input
2225 * state[] or input in[] arrays)
2226 * rescale(out[i])
2227 * out[i] += in[i]
2228 * update final state array using in[]
2229 *
2230 * REFERENCES: Sub-clause 4.1.7 and 4.2.4 of GSM Recomendation 06.20
2231 *
2232 * KEYWORDS: lpc, directform, fir, lpcFir, inversefilter, lpcFilt
2233 * KEYWORDS: dirForm, dir_mod, dir_clr, dir_neg, dir_set, i_dir_mod
2234 *
2235 *************************************************************************/
2236
2237 void lpcFir(Shortword pswInput[], Shortword pswCoef[],
2238 Shortword pswState[], Shortword pswFiltOut[])
2239 {
2240
2241 /*_________________________________________________________________________
2242 | |
2243 | Automatic Variables |
2244 |_________________________________________________________________________|
2245 */
2246
2247 Longword L_Sum;
2248 short int siStage,
2249 siSmp;
2250
2251 /*_________________________________________________________________________
2252 | |
2253 | Executable Code |
2254 |_________________________________________________________________________|
2255 */
2256
2257 /* filter 1st sample */
2258 /* ----------------- */
2259
2260 /* sum past state outputs */
2261 /* ---------------------- */
2262 /* 0th coef, with rounding */
2263 L_Sum = L_mac(LPC_ROUND, pswState[0], pswCoef[0]);
2264
2265 for (siStage = 1; siStage < NP; siStage++)
2266 { /* remaining coefs */
2267 L_Sum = L_mac(L_Sum, pswState[siStage], pswCoef[siStage]);
2268 }
2269
2270 /* add input to partial output */
2271 /* --------------------------- */
2272
2273 L_Sum = L_shl(L_Sum, ASHIFT);
2274 L_Sum = L_msu(L_Sum, pswInput[0], 0x8000);
2275
2276 /* save 1st output sample */
2277 /* ---------------------- */
2278
2279 pswFiltOut[0] = extract_h(L_Sum);
2280
2281 /* filter remaining samples */
2282 /* ------------------------ */
2283
2284 for (siSmp = 1; siSmp < S_LEN; siSmp++)
2285 {
2286
2287 /* sum past outputs */
2288 /* ---------------- */
2289 /* 0th coef, with rounding */
2290 L_Sum = L_mac(LPC_ROUND, pswInput[siSmp - 1], pswCoef[0]);
2291 /* remaining coefs */
2292 for (siStage = 1; ((0 < (siSmp - siStage)) && siStage < NP); siStage++)
2293 {
2294 L_Sum = L_mac(L_Sum, pswInput[siSmp - siStage - 1], pswCoef[siStage]);
2295 }
2296
2297 /* sum past states, if any */
2298 /* ----------------------- */
2299
2300 for (siStage = siSmp; siStage < NP; siStage++)
2301 {
2302 L_Sum = L_mac(L_Sum, pswState[siStage - siSmp], pswCoef[siStage]);
2303 }
2304
2305 /* add input to partial output */
2306 /* --------------------------- */
2307
2308 L_Sum = L_shl(L_Sum, ASHIFT);
2309 L_Sum = L_msu(L_Sum, pswInput[siSmp], 0x8000);
2310
2311 /* save current output sample */
2312 /* -------------------------- */
2313
2314 pswFiltOut[siSmp] = extract_h(L_Sum);
2315 }
2316
2317 /* save final state */
2318 /* ---------------- */
2319
2320 for (siStage = 0; siStage < NP; siStage++)
2321 {
2322 pswState[siStage] = pswInput[S_LEN - siStage - 1];
2323 }
2324
2325 }
2326
2327 /***************************************************************************
2328 *
2329 * FUNCTION NAME: lpcIir
2330 *
2331 * PURPOSE:
2332 *
2333 * The purpose of this function is to perform direct form IIR filtering
2334 * assuming a NP order filter and given state, coefficients, and input
2335 *
2336 * INPUTS:
2337 *
2338 * NP
2339 * order of the lpc filter
2340 *
2341 * S_LEN
2342 * number of samples to filter
2343 *
2344 * pswInput[0:S_LEN-1]
2345 *
2346 * input array of points to be filtered
2347 * pswInput[0] is the oldest point (first to be filtered)
2348 * pswInput[siLen-1] is the last point filtered (newest)
2349 *
2350 * pswCoef[0:NP-1]
2351 * array of direct form coefficients
2352 * pswCoef[0] = coeff for delay n = -1
2353 * pswCoef[NP-1] = coeff for delay n = -NP
2354 *
2355 * ASHIFT
2356 * number of shifts input A's have been shifted down by
2357 *
2358 * LPC_ROUND
2359 * rounding constant
2360 *
2361 * pswState[0:NP-1]
2362 *
2363 * array of the filter state following form of pswCoef
2364 * pswState[0] = state of filter for delay n = -1
2365 * pswState[NP-1] = state of filter for delay n = -NP
2366 *
2367 * OUTPUTS:
2368 *
2369 * pswState[0:NP-1]
2370 *
2371 * updated filter state, ready to filter
2372 * pswInput[siLen], i.e. the next point
2373 *
2374 * pswFiltOut[0:S_LEN-1]
2375 *
2376 * the filtered output
2377 * same format as pswInput, pswFiltOut[0] is oldest point
2378 *
2379 * RETURN VALUE:
2380 *
2381 * none
2382 *
2383 * DESCRIPTION:
2384 *
2385 * because of the default sign of the coefficients the
2386 * formula for the filter is :
2387 * i=0, i < S_LEN
2388 * out[i] = rounded(state[i]*coef[0])
2389 * j=1, j < NP
2390 * out[i] -= state[j]*coef[j] (state is taken from either input
2391 * state[] or prior out[] arrays)
2392 * rescale(out[i])
2393 * out[i] += in[i]
2394 * update final state array using out[]
2395 *
2396 * REFERENCES: Sub-clause 4.1.7 and 4.2.4 of GSM Recomendation 06.20
2397 *
2398 * KEYWORDS: lpc, directform, iir, synthesisfilter, lpcFilt
2399 * KEYWORDS: dirForm, dir_mod, dir_clr, dir_neg, dir_set
2400 *
2401 *************************************************************************/
2402
2403 void lpcIir(Shortword pswInput[], Shortword pswCoef[],
2404 Shortword pswState[], Shortword pswFiltOut[])
2405 {
2406
2407 /*_________________________________________________________________________
2408 | |
2409 | Automatic Variables |
2410 |_________________________________________________________________________|
2411 */
2412
2413 Longword L_Sum;
2414 short int siStage,
2415 siSmp;
2416
2417 /*_________________________________________________________________________
2418 | |
2419 | Executable Code |
2420 |_________________________________________________________________________|
2421 */
2422
2423 /* filter 1st sample */
2424 /* ----------------- */
2425
2426 /* sum past state outputs */
2427 /* ---------------------- */
2428 /* 0th coef, with rounding */
2429 L_Sum = L_msu(LPC_ROUND, pswState[0], pswCoef[0]);
2430
2431 for (siStage = 1; siStage < NP; siStage++)
2432 { /* remaining coefs */
2433 L_Sum = L_msu(L_Sum, pswState[siStage], pswCoef[siStage]);
2434 }
2435
2436 /* add input to partial output */
2437 /* --------------------------- */
2438
2439 L_Sum = L_shl(L_Sum, ASHIFT);
2440 L_Sum = L_msu(L_Sum, pswInput[0], 0x8000);
2441
2442 /* save 1st output sample */
2443 /* ---------------------- */
2444
2445 pswFiltOut[0] = extract_h(L_Sum);
2446
2447 /* filter remaining samples */
2448 /* ------------------------ */
2449
2450 for (siSmp = 1; siSmp < S_LEN; siSmp++)
2451 {
2452
2453 /* sum past outputs */
2454 /* ---------------- */
2455 /* 0th coef, with rounding */
2456 L_Sum = L_msu(LPC_ROUND, pswFiltOut[siSmp - 1], pswCoef[0]);
2457 /* remaining coefs */
2458 for (siStage = 1; ((0 < (siSmp - siStage)) && siStage < NP); siStage++)
2459 {
2460 L_Sum = L_msu(L_Sum, pswFiltOut[siSmp - siStage - 1],
2461 pswCoef[siStage]);
2462 }
2463
2464 /* sum past states, if any */
2465 /* ----------------------- */
2466
2467 for (siStage = siSmp; siStage < NP; siStage++)
2468 {
2469 L_Sum = L_msu(L_Sum, pswState[siStage - siSmp], pswCoef[siStage]);
2470 }
2471
2472 /* add input to partial output */
2473 /* --------------------------- */
2474
2475 L_Sum = L_shl(L_Sum, ASHIFT);
2476 L_Sum = L_msu(L_Sum, pswInput[siSmp], 0x8000);
2477
2478 /* save current output sample */
2479 /* -------------------------- */
2480
2481 pswFiltOut[siSmp] = extract_h(L_Sum);
2482 }
2483
2484 /* save final state */
2485 /* ---------------- */
2486
2487 for (siStage = 0; siStage < NP; siStage++)
2488 {
2489 pswState[siStage] = pswFiltOut[S_LEN - siStage - 1];
2490 }
2491 }
2492
2493 /***************************************************************************
2494 *
2495 * FUNCTION NAME: lpcIrZsIir
2496 *
2497 * PURPOSE:
2498 *
2499 * The purpose of this function is to calculate the impulse response
2500 * via direct form IIR filtering with zero state assuming a NP order
2501 * filter and given coefficients
2502 *
2503 * INPUTS:
2504 *
2505 * NP
2506 * order of the lpc filter
2507 *
2508 * S_LEN
2509 * number of samples to filter
2510 *
2511 * pswCoef[0:NP-1]
2512 * array of direct form coefficients
2513 * pswCoef[0] = coeff for delay n = -1
2514 * pswCoef[NP-1] = coeff for delay n = -NP
2515 *
2516 * ASHIFT
2517 * number of shifts input A's have been shifted down by
2518 *
2519 * LPC_ROUND
2520 * rounding constant
2521 *
2522 * OUTPUTS:
2523 *
2524 * pswFiltOut[0:S_LEN-1]
2525 *
2526 * the filtered output
2527 * same format as pswInput, pswFiltOut[0] is oldest point
2528 *
2529 * RETURN VALUE:
2530 *
2531 * none
2532 *
2533 * DESCRIPTION:
2534 *
2535 * This routine is called by getNWCoefs().
2536 *
2537 * Because of the default sign of the coefficients the
2538 * formula for the filter is :
2539 * i=0, i < S_LEN
2540 * out[i] = rounded(state[i]*coef[0])
2541 * j=1, j < NP
2542 * out[i] -= state[j]*coef[j] (state taken from prior output[])
2543 * rescale(out[i])
2544 *
2545 * REFERENCES: Sub-clause 4.1.8 of GSM Recomendation 06.20
2546 *
2547 * KEYWORDS: lpc, directform, iir, synthesisfilter, lpcFilt
2548 * KEYWORDS: dirForm, dir_mod, dir_clr, dir_neg, dir_set
2549 *
2550 *************************************************************************/
2551
2552 void lpcIrZsIir(Shortword pswCoef[], Shortword pswFiltOut[])
2553 {
2554
2555 /*_________________________________________________________________________
2556 | |
2557 | Automatic Variables |
2558 |_________________________________________________________________________|
2559 */
2560
2561 Longword L_Sum;
2562 short int siStage,
2563 siSmp;
2564
2565 /*_________________________________________________________________________
2566 | |
2567 | Executable Code |
2568 |_________________________________________________________________________|
2569 */
2570
2571 /* output 1st sample */
2572 /* ----------------- */
2573
2574 pswFiltOut[0] = 0x0400;
2575
2576 /* filter remaining samples */
2577 /* ------------------------ */
2578
2579 for (siSmp = 1; siSmp < S_LEN; siSmp++)
2580 {
2581
2582 /* sum past outputs */
2583 /* ---------------- */
2584 /* 0th coef, with rounding */
2585 L_Sum = L_msu(LPC_ROUND, pswFiltOut[siSmp - 1], pswCoef[0]);
2586 /* remaining coefs */
2587 for (siStage = 1; ((0 < (siSmp - siStage)) && siStage < NP); siStage++)
2588 {
2589 L_Sum = L_msu(L_Sum, pswFiltOut[siSmp - siStage - 1],
2590 pswCoef[siStage]);
2591 }
2592
2593 /* scale output */
2594 /* ------------ */
2595
2596 L_Sum = L_shl(L_Sum, ASHIFT);
2597
2598 /* save current output sample */
2599 /* -------------------------- */
2600
2601 pswFiltOut[siSmp] = extract_h(L_Sum);
2602 }
2603 }
2604
2605 /***************************************************************************
2606 *
2607 * FUNCTION NAME: lpcZiIir
2608 *
2609 * PURPOSE:
2610 * The purpose of this function is to perform direct form iir filtering
2611 * with zero input assuming a NP order filter, and given state and
2612 * coefficients
2613 *
2614 * INPUTS:
2615 *
2616 * NP
2617 * order of the lpc filter
2618 *
2619 * S_LEN
2620 * number of samples to filter MUST be <= MAX_ZIS
2621 *
2622 * pswCoef[0:NP-1]
2623 *
2624 * array of direct form coefficients.
2625 * pswCoef[0] = coeff for delay n = -1
2626 * pswCoef[NP-1] = coeff for delay n = -NP
2627 *
2628 * ASHIFT
2629 * number of shifts input A's have been shifted down by
2630 *
2631 * LPC_ROUND
2632 * rounding constant
2633 *
2634 * pswState[0:NP-1]
2635 *
2636 * array of the filter state following form of pswCoef
2637 * pswState[0] = state of filter for delay n = -1
2638 * pswState[NP-1] = state of filter for delay n = -NP
2639 *
2640 * OUTPUTS:
2641 *
2642 * pswFiltOut[0:S_LEN-1]
2643 *
2644 * the filtered output
2645 * same format as pswIn, pswFiltOut[0] is oldest point
2646 *
2647 * RETURN VALUE:
2648 *
2649 * none
2650 *
2651 * DESCRIPTION:
2652 *
2653 * The routine is called from sfrmAnalysis, and is used to let the
2654 * LPC filters ring out.
2655 *
2656 * because of the default sign of the coefficients the
2657 * formula for the filter is :
2658 * i=0, i < S_LEN
2659 * out[i] = rounded(state[i]*coef[0])
2660 * j=1, j < NP
2661 * out[i] -= state[j]*coef[j] (state is taken from either input
2662 * state[] or prior output[] arrays)
2663 * rescale(out[i])
2664 *
2665 * REFERENCES: Sub-clause 4.1.7 of GSM Recomendation 06.20
2666 *
2667 * KEYWORDS: lpc, directform, iir, synthesisfilter, lpcFilt
2668 * KEYWORDS: dirForm, dir_mod, dir_clr, dir_neg, dir_set
2669 *
2670 *************************************************************************/
2671
2672 void lpcZiIir(Shortword pswCoef[], Shortword pswState[],
2673 Shortword pswFiltOut[])
2674 {
2675
2676 /*_________________________________________________________________________
2677 | |
2678 | Automatic Variables |
2679 |_________________________________________________________________________|
2680 */
2681
2682 Longword L_Sum;
2683 short int siStage,
2684 siSmp;
2685
2686 /*_________________________________________________________________________
2687 | |
2688 | Executable Code |
2689 |_________________________________________________________________________|
2690 */
2691
2692 /* filter 1st sample */
2693 /* ----------------- */
2694
2695 /* sum past state outputs */
2696 /* ---------------------- */
2697 /* 0th coef, with rounding */
2698 L_Sum = L_msu(LPC_ROUND, pswState[0], pswCoef[0]);
2699
2700 for (siStage = 1; siStage < NP; siStage++)
2701 { /* remaining coefs */
2702 L_Sum = L_msu(L_Sum, pswState[siStage], pswCoef[siStage]);
2703 }
2704
2705 /* scale output */
2706 /* ------------ */
2707
2708 L_Sum = L_shl(L_Sum, ASHIFT);
2709
2710 /* save 1st output sample */
2711 /* ---------------------- */
2712
2713 pswFiltOut[0] = extract_h(L_Sum);
2714
2715 /* filter remaining samples */
2716 /* ------------------------ */
2717
2718 for (siSmp = 1; siSmp < S_LEN; siSmp++)
2719 {
2720
2721 /* sum past outputs */
2722 /* ---------------- */
2723 /* 0th coef, with rounding */
2724 L_Sum = L_msu(LPC_ROUND, pswFiltOut[siSmp - 1], pswCoef[0]);
2725 /* remaining coefs */
2726 for (siStage = 1; ((0 < (siSmp - siStage)) && siStage < NP); siStage++)
2727 {
2728 L_Sum = L_msu(L_Sum, pswFiltOut[siSmp - siStage - 1],
2729 pswCoef[siStage]);
2730 }
2731
2732 /* sum past states, if any */
2733 /* ----------------------- */
2734
2735 for (siStage = siSmp; siStage < NP; siStage++)
2736 {
2737 L_Sum = L_msu(L_Sum, pswState[siStage - siSmp], pswCoef[siStage]);
2738 }
2739
2740 /* scale output */
2741 /* ------------ */
2742
2743 L_Sum = L_shl(L_Sum, ASHIFT);
2744
2745 /* save current output sample */
2746 /* -------------------------- */
2747
2748 pswFiltOut[siSmp] = extract_h(L_Sum);
2749 }
2750 }
2751
2752 /***************************************************************************
2753 *
2754 * FUNCTION NAME: lpcZsFir
2755 *
2756 * PURPOSE:
2757 * The purpose of this function is to perform direct form fir filtering
2758 * with zero state, assuming a NP order filter and given coefficients
2759 * and non-zero input.
2760 *
2761 * INPUTS:
2762 *
2763 * NP
2764 * order of the lpc filter
2765 *
2766 * S_LEN
2767 * number of samples to filter
2768 *
2769 * pswInput[0:S_LEN-1]
2770 *
2771 * input array of points to be filtered.
2772 * pswInput[0] is the oldest point (first to be filtered)
2773 * pswInput[siLen-1] is the last point filtered (newest)
2774 *
2775 * pswCoef[0:NP-1]
2776 *
2777 * array of direct form coefficients
2778 * pswCoef[0] = coeff for delay n = -1
2779 * pswCoef[NP-1] = coeff for delay n = -NP
2780 *
2781 * ASHIFT
2782 * number of shifts input A's have been shifted down by
2783 *
2784 * LPC_ROUND
2785 * rounding constant
2786 *
2787 * OUTPUTS:
2788 *
2789 * pswFiltOut[0:S_LEN-1]
2790 *
2791 * the filtered output
2792 * same format as pswInput, pswFiltOut[0] is oldest point
2793 *
2794 * RETURN VALUE:
2795 *
2796 * none
2797 *
2798 * DESCRIPTION:
2799 *
2800 * This routine is used in getNWCoefs(). See section 4.1.7.
2801 *
2802 * because of the default sign of the coefficients the
2803 * formula for the filter is :
2804 * i=0, i < S_LEN
2805 * out[i] = rounded(state[i]*coef[0])
2806 * j=1, j < NP
2807 * out[i] += state[j]*coef[j] (state taken from in[])
2808 * rescale(out[i])
2809 * out[i] += in[i]
2810 *
2811 * REFERENCES: Sub-clause 4.1.7 of GSM Recomendation 06.20
2812 *
2813 * KEYWORDS: lpc, directform, fir, lpcFir, inversefilter, lpcFilt
2814 * KEYWORDS: dirForm, dir_mod, dir_clr, dir_neg, dir_set, i_dir_mod
2815 *
2816 *************************************************************************/
2817
2818 void lpcZsFir(Shortword pswInput[], Shortword pswCoef[],
2819 Shortword pswFiltOut[])
2820 {
2821
2822 /*_________________________________________________________________________
2823 | |
2824 | Automatic Variables |
2825 |_________________________________________________________________________|
2826 */
2827
2828 Longword L_Sum;
2829 short int siStage,
2830 siSmp;
2831
2832 /*_________________________________________________________________________
2833 | |
2834 | Executable Code |
2835 |_________________________________________________________________________|
2836 */
2837
2838 /* output 1st sample */
2839 /* ----------------- */
2840
2841 pswFiltOut[0] = pswInput[0];
2842
2843 /* filter remaining samples */
2844 /* ------------------------ */
2845
2846 for (siSmp = 1; siSmp < S_LEN; siSmp++)
2847 {
2848
2849 /* sum past outputs */
2850 /* ---------------- */
2851 /* 0th coef, with rounding */
2852 L_Sum = L_mac(LPC_ROUND, pswInput[siSmp - 1], pswCoef[0]);
2853 /* remaining coefs */
2854 for (siStage = 1; ((0 < (siSmp - siStage)) && siStage < NP); siStage++)
2855 {
2856 L_Sum = L_mac(L_Sum, pswInput[siSmp - siStage - 1],
2857 pswCoef[siStage]);
2858 }
2859
2860 /* add input to partial output */
2861 /* --------------------------- */
2862
2863 L_Sum = L_shl(L_Sum, ASHIFT);
2864 L_Sum = L_msu(L_Sum, pswInput[siSmp], 0x8000);
2865
2866 /* save current output sample */
2867 /* -------------------------- */
2868
2869 pswFiltOut[siSmp] = extract_h(L_Sum);
2870 }
2871 }
2872
2873 /***************************************************************************
2874 *
2875 * FUNCTION NAME: lpcZsIir
2876 *
2877 * PURPOSE:
2878 *
2879 * The purpose of this function is to perform direct form IIR filtering
2880 * with zero state, assuming a NP order filter and given coefficients
2881 * and non-zero input.
2882 *
2883 * INPUTS:
2884 *
2885 * NP
2886 * order of the lpc filter
2887 *
2888 * S_LEN
2889 * number of samples to filter
2890 *
2891 * pswInput[0:S_LEN-1]
2892 *
2893 * input array of points to be filtered
2894 * pswInput[0] is the oldest point (first to be filtered)
2895 * pswInput[siLen-1] is the last point filtered (newest)
2896 *
2897 * pswCoef[0:NP-1]
2898 * array of direct form coefficients
2899 * pswCoef[0] = coeff for delay n = -1
2900 * pswCoef[NP-1] = coeff for delay n = -NP
2901 *
2902 * ASHIFT
2903 * number of shifts input A's have been shifted down by
2904 *
2905 * LPC_ROUND
2906 * rounding constant
2907 *
2908 * OUTPUTS:
2909 *
2910 * pswFiltOut[0:S_LEN-1]
2911 *
2912 * the filtered output
2913 * same format as pswInput, pswFiltOut[0] is oldest point
2914 *
2915 * RETURN VALUE:
2916 *
2917 * none
2918 *
2919 * DESCRIPTION:
2920 *
2921 * This routine is used in the subframe analysis process. It is
2922 * called by sfrmAnalysis() and fnClosedLoop(). It is this function
2923 * which performs the weighting of the excitation vectors.
2924 *
2925 * because of the default sign of the coefficients the
2926 * formula for the filter is :
2927 * i=0, i < S_LEN
2928 * out[i] = rounded(state[i]*coef[0])
2929 * j=1, j < NP
2930 * out[i] -= state[j]*coef[j] (state taken from prior out[])
2931 * rescale(out[i])
2932 * out[i] += in[i]
2933 *
2934 * REFERENCES: Sub-clause 4.1.8.5 of GSM Recomendation 06.20
2935 *
2936 * KEYWORDS: lpc, directform, iir, synthesisfilter, lpcFilt
2937 * KEYWORDS: dirForm, dir_mod, dir_clr, dir_neg, dir_set
2938 *
2939 *************************************************************************/
2940
2941 void lpcZsIir(Shortword pswInput[], Shortword pswCoef[],
2942 Shortword pswFiltOut[])
2943 {
2944
2945 /*_________________________________________________________________________
2946 | |
2947 | Automatic Variables |
2948 |_________________________________________________________________________|
2949 */
2950
2951 Longword L_Sum;
2952 short int siStage,
2953 siSmp;
2954
2955 /*_________________________________________________________________________
2956 | |
2957 | Executable Code |
2958 |_________________________________________________________________________|
2959 */
2960
2961 /* output 1st sample */
2962 /* ----------------- */
2963
2964 pswFiltOut[0] = pswInput[0];
2965
2966 /* filter remaining samples */
2967 /* ------------------------ */
2968
2969 for (siSmp = 1; siSmp < S_LEN; siSmp++)
2970 {
2971
2972 /* sum past outputs */
2973 /* ---------------- */
2974 /* 0th coef, with rounding */
2975 L_Sum = L_msu(LPC_ROUND, pswFiltOut[siSmp - 1], pswCoef[0]);
2976 /* remaining coefs */
2977 for (siStage = 1; ((0 < (siSmp - siStage)) && siStage < NP); siStage++)
2978 {
2979 L_Sum = L_msu(L_Sum, pswFiltOut[siSmp - siStage - 1],
2980 pswCoef[siStage]);
2981 }
2982
2983 /* add input to partial output */
2984 /* --------------------------- */
2985
2986 L_Sum = L_shl(L_Sum, ASHIFT);
2987 L_Sum = L_msu(L_Sum, pswInput[siSmp], 0x8000);
2988
2989 /* save current output sample */
2990 /* -------------------------- */
2991
2992 pswFiltOut[siSmp] = extract_h(L_Sum);
2993 }
2994 }
2995
2996 /***************************************************************************
2997 *
2998 * FUNCTION NAME: lpcZsIirP
2999 *
3000 * PURPOSE:
3001 *
3002 * The purpose of this function is to perform direct form iir filtering
3003 * with zero state, assuming a NP order filter and given coefficients
3004 * and input
3005 *
3006 * INPUTS:
3007 *
3008 * NP
3009 * order of the lpc filter
3010 *
3011 * S_LEN
3012 * number of samples to filter
3013 *
3014 * pswCommonIO[0:S_LEN-1]
3015 *
3016 * input array of points to be filtered
3017 * pswCommonIO[0] is oldest point (first to be filtered)
3018 * pswCommonIO[siLen-1] is last point filtered (newest)
3019 *
3020 * pswCoef[0:NP-1]
3021 * array of direct form coefficients
3022 * pswCoef[0] = coeff for delay n = -1
3023 * pswCoef[NP-1] = coeff for delay n = -NP
3024 *
3025 * ASHIFT
3026 * number of shifts input A's have been shifted down by
3027 *
3028 * LPC_ROUND
3029 * rounding constant
3030 *
3031 * OUTPUTS:
3032 *
3033 * pswCommonIO[0:S_LEN-1]
3034 *
3035 * the filtered output
3036 * pswCommonIO[0] is oldest point
3037 *
3038 * RETURN VALUE:
3039 *
3040 * none
3041 *
3042 * DESCRIPTION:
3043 *
3044 * This function is called by geNWCoefs(). See section 4.1.7.
3045 *
3046 * because of the default sign of the coefficients the
3047 * formula for the filter is :
3048 * i=0, i < S_LEN
3049 * out[i] = rounded(state[i]*coef[0])
3050 * j=1, j < NP
3051 * out[i] += state[j]*coef[j] (state taken from prior out[])
3052 * rescale(out[i])
3053 * out[i] += in[i]
3054 *
3055 * REFERENCES: Sub-clause 4.1.7 of GSM Recomendation 06.20
3056 *
3057 * KEYWORDS: lpc, directform, iir, synthesisfilter, lpcFilt
3058 * KEYWORDS: dirForm, dir_mod, dir_clr, dir_neg, dir_set
3059 *
3060 *************************************************************************/
3061
3062 void lpcZsIirP(Shortword pswCommonIO[], Shortword pswCoef[])
3063 {
3064
3065 /*_________________________________________________________________________
3066 | |
3067 | Automatic Variables |
3068 |_________________________________________________________________________|
3069 */
3070
3071 Longword L_Sum;
3072 short int siStage,
3073 siSmp;
3074
3075 /*_________________________________________________________________________
3076 | |
3077 | Executable Code |
3078 |_________________________________________________________________________|
3079 */
3080
3081 /* filter remaining samples */
3082 /* ------------------------ */
3083
3084 for (siSmp = 1; siSmp < S_LEN; siSmp++)
3085 {
3086
3087 /* sum past outputs */
3088 /* ---------------- */
3089 /* 0th coef, with rounding */
3090 L_Sum = L_mac(LPC_ROUND, pswCommonIO[siSmp - 1], pswCoef[0]);
3091 /* remaining coefs */
3092 for (siStage = 1; ((0 < (siSmp - siStage)) && siStage < NP); siStage++)
3093 {
3094 L_Sum = L_mac(L_Sum, pswCommonIO[siSmp - siStage - 1],
3095 pswCoef[siStage]);
3096 }
3097
3098 /* add input to partial output */
3099 /* --------------------------- */
3100
3101 L_Sum = L_shl(L_Sum, ASHIFT);
3102 L_Sum = L_msu(L_Sum, pswCommonIO[siSmp], 0x8000);
3103
3104 /* save current output sample */
3105 /* -------------------------- */
3106
3107 pswCommonIO[siSmp] = extract_h(L_Sum);
3108 }
3109 }
3110
3111 /**************************************************************************
3112 *
3113 * FUNCTION NAME: pitchPreFilt
3114 *
3115 * PURPOSE:
3116 *
3117 * Performs pitch pre-filter on excitation in speech decoder.
3118 *
3119 * INPUTS:
3120 *
3121 * pswExcite[0:39]
3122 *
3123 * Synthetic residual signal to be filtered, a subframe-
3124 * length vector.
3125 *
3126 * ppsrPVecIntFilt[0:9][0:5] ([tap][phase])
3127 *
3128 * Interpolation filter coefficients.
3129 *
3130 * ppsrSqtrP0[0:2][0:31] ([voicing level-1][gain code])
3131 *
3132 * Sqrt(P0) look-up table, used to determine pitch
3133 * pre-filtering coefficient.
3134 *
3135 * swRxGsp0
3136 *
3137 * Coded value from gain quantizer, used to look up
3138 * sqrt(P0).
3139 *
3140 * swRxLag
3141 *
3142 * Full-resolution lag value (fractional lag *
3143 * oversampling factor), used to index pitch pre-filter
3144 * state.
3145 *
3146 * swUvCode
3147 *
3148 * Coded voicing level, used to distinguish between
3149 * voiced and unvoiced conditions, and to look up
3150 * sqrt(P0).
3151 *
3152 * swSemiBeta
3153 *
3154 * The gain applied to the adaptive codebook excitation
3155 * (long-term predictor excitation) limited to a maximum
3156 * of 1.0, used to determine the pitch pre-filter
3157 * coefficient.
3158 *
3159 * snsSqrtRs
3160 *
3161 * The estimate of the energy in the residual, used only
3162 * for scaling.
3163 *
3164 * OUTPUTS:
3165 *
3166 * pswExciteOut[0:39]
3167 *
3168 * The output pitch pre-filtered excitation.
3169 *
3170 * pswPPreState[0:44]
3171 *
3172 * Contains the state of the pitch pre-filter
3173 *
3174 * RETURN VALUE:
3175 *
3176 * none
3177 *
3178 * DESCRIPTION:
3179 *
3180 * If the voicing mode for the frame is unvoiced, then the pitch pre-
3181 * filter state is updated with the input excitation, and the input
3182 * excitation is copied to the output.
3183 *
3184 * If voiced: first the energy in the input excitation is calculated.
3185 * Then, the coefficient of the pitch pre-filter is obtained:
3186 *
3187 * PpfCoef = POST_EPSILON * min(beta, sqrt(P0)).
3188 *
3189 * Then, the pitch pre-filter is performed:
3190 *
3191 * ex_p(n) = ex(n) + PpfCoef * ex_p(n-L)
3192 *
3193 * The ex_p(n-L) sample is interpolated from the surrounding samples,
3194 * even for integer values of L.
3195 *
3196 * Note: The coefficients of the interpolating filter are multiplied
3197 * by PpfCoef, rather multiplying ex_p(n_L) after interpolation.
3198 *
3199 * Finally, the energy in the output excitation is calculated, and
3200 * automatic gain control is applied to the output signal so that
3201 * its energy matches the original.
3202 *
3203 * The pitch pre-filter is described in section 4.2.2.
3204 *
3205 * REFERENCES: Sub-clause 4.2.2 of GSM Recomendation 06.20
3206 *
3207 * KEYWORDS: prefilter, pitch, pitchprefilter, excitation, residual
3208 *
3209 *************************************************************************/
3210
3211 static void pitchPreFilt(Shortword pswExcite[],
3212 Shortword swRxGsp0,
3213 Shortword swRxLag, Shortword swUvCode,
3214 Shortword swSemiBeta, struct NormSw snsSqrtRs,
3215 Shortword pswExciteOut[],
3216 Shortword pswPPreState[])
3217 {
3218
3219 /*_________________________________________________________________________
3220 | |
3221 | Local Constants |
3222 |_________________________________________________________________________|
3223 */
3224
3225 #define POST_EPSILON 0x2666
3226
3227 /*_________________________________________________________________________
3228 | |
3229 | Local Static Variables |
3230 |_________________________________________________________________________|
3231 */
3232
3233
3234 /*_________________________________________________________________________
3235 | |
3236 | Automatic Variables |
3237 |_________________________________________________________________________|
3238 */
3239
3240 Longword L_1,
3241 L_OrigEnergy;
3242
3243 Shortword swScale,
3244 swSqrtP0,
3245 swIntLag,
3246 swRemain,
3247 swEnergy,
3248 pswInterpCoefs[P_INT_MACS];
3249
3250 short int i,
3251 j;
3252
3253 struct NormSw snsOrigEnergy;
3254
3255 Shortword *pswPPreCurr = &pswPPreState[LTP_LEN];
3256
3257 /*_________________________________________________________________________
3258 | |
3259 | Executable Code |
3260 |_________________________________________________________________________|
3261 */
3262
3263 /* Initialization */
3264 /*----------------*/
3265
3266 swEnergy = 0;
3267
3268 /* Check voicing level */
3269 /*---------------------*/
3270
3271 if (swUvCode == 0)
3272 {
3273
3274 /* Unvoiced: perform one subframe of delay on state, copy input to */
3275 /* state, copy input to output (if not same) */
3276 /*-----------------------------------------------------------------*/
3277
3278 for (i = 0; i < LTP_LEN - S_LEN; i++)
3279 pswPPreState[i] = pswPPreState[i + S_LEN];
3280
3281 for (i = 0; i < S_LEN; i++)
3282 pswPPreState[i + LTP_LEN - S_LEN] = pswExcite[i];
3283
3284 if (pswExciteOut != pswExcite)
3285 {
3286
3287 for (i = 0; i < S_LEN; i++)
3288 pswExciteOut[i] = pswExcite[i];
3289 }
3290 }
3291 else
3292 {
3293
3294 /* Voiced: calculate energy in input, filter, calculate energy in */
3295 /* output, scale */
3296 /*----------------------------------------------------------------*/
3297
3298 /* Get energy in input excitation vector */
3299 /*---------------------------------------*/
3300
3301 swEnergy = add(negate(shl(snsSqrtRs.sh, 1)), 3);
3302
3303 if (swEnergy > 0)
3304 {
3305
3306 /* High-energy residual: scale input vector during energy */
3307 /* calculation. The shift count + 1 of the energy of the */
3308 /* residual estimate is used as an estimate of the shift */
3309 /* count needed for the excitation energy */
3310 /*--------------------------------------------------------*/
3311
3312
3313 snsOrigEnergy.sh = g_corr1s(pswExcite, swEnergy, &L_OrigEnergy);
3314 snsOrigEnergy.man = round(L_OrigEnergy);
3315
3316 }
3317 else
3318 {
3319
3320 /* set shift count to zero for AGC later */
3321 /*---------------------------------------*/
3322
3323 swEnergy = 0;
3324
3325 /* Lower-energy residual: no overflow protection needed */
3326 /*------------------------------------------------------*/
3327
3328 L_OrigEnergy = 0;
3329 for (i = 0; i < S_LEN; i++)
3330 {
3331
3332 L_OrigEnergy = L_mac(L_OrigEnergy, pswExcite[i], pswExcite[i]);
3333 }
3334
3335 snsOrigEnergy.sh = norm_l(L_OrigEnergy);
3336 snsOrigEnergy.man = round(L_shl(L_OrigEnergy, snsOrigEnergy.sh));
3337 }
3338
3339 /* Determine pitch pre-filter coefficient, and scale the appropriate */
3340 /* phase of the interpolating filter by it */
3341 /*-------------------------------------------------------------------*/
3342
3343 swSqrtP0 = ppsrSqrtP0[swUvCode - 1][swRxGsp0];
3344
3345 if (sub(swSqrtP0, swSemiBeta) > 0)
3346 swScale = swSemiBeta;
3347 else
3348 swScale = swSqrtP0;
3349
3350 swScale = mult_r(POST_EPSILON, swScale);
3351
3352 get_ipjj(swRxLag, &swIntLag, &swRemain);
3353
3354 for (i = 0; i < P_INT_MACS; i++)
3355 pswInterpCoefs[i] = mult_r(ppsrPVecIntFilt[i][swRemain], swScale);
3356
3357 /* Perform filter */
3358 /*----------------*/
3359
3360 for (i = 0; i < S_LEN; i++)
3361 {
3362
3363 L_1 = L_deposit_h(pswExcite[i]);
3364
3365 for (j = 0; j < P_INT_MACS - 1; j++)
3366 {
3367
3368 L_1 = L_mac(L_1, pswPPreCurr[i - swIntLag - P_INT_MACS / 2 + j],
3369 pswInterpCoefs[j]);
3370 }
3371
3372 pswPPreCurr[i] = mac_r(L_1,
3373 pswPPreCurr[i - swIntLag + P_INT_MACS / 2 - 1],
3374 pswInterpCoefs[P_INT_MACS - 1]);
3375 }
3376
3377 /* Get energy in filtered vector, determine automatic-gain-control */
3378 /* scale factor */
3379 /*-----------------------------------------------------------------*/
3380
3381 swScale = agcGain(pswPPreCurr, snsOrigEnergy, swEnergy);
3382
3383 /* Scale filtered vector by AGC, put out. NOTE: AGC scale returned */
3384 /* by routine above is divided by two, hence the shift below */
3385 /*------------------------------------------------------------------*/
3386
3387 for (i = 0; i < S_LEN; i++)
3388 {
3389
3390 L_1 = L_mult(pswPPreCurr[i], swScale);
3391 L_1 = L_shl(L_1, 1);
3392 pswExciteOut[i] = round(L_1);
3393 }
3394
3395 /* Update pitch pre-filter state */
3396 /*-------------------------------*/
3397
3398 for (i = 0; i < LTP_LEN; i++)
3399 pswPPreState[i] = pswPPreState[i + S_LEN];
3400 }
3401 }
3402
3403 /***************************************************************************
3404 *
3405 * FUNCTION NAME: r0BasedEnergyShft
3406 *
3407 * PURPOSE:
3408 *
3409 * Given an R0 voicing level, find the number of shifts to be
3410 * performed on the energy to ensure that the subframe energy does
3411 * not overflow. example if energy can maximally take the value
3412 * 4.0, then 2 shifts are required.
3413 *
3414 * INPUTS:
3415 *
3416 * swR0Index
3417 * R0 codeword (0-0x1f)
3418 *
3419 * OUTPUTS:
3420 *
3421 * none
3422 *
3423 * RETURN VALUE:
3424 *
3425 * swShiftDownSignal
3426 *
3427 * number of right shifts to apply to energy (0..6)
3428 *
3429 * DESCRIPTION:
3430 *
3431 * Based on the R0, the average frame energy, we can get an
3432 * upper bound on the energy any one subframe can take on.
3433 * Using this upper bound we can calculate what right shift is
3434 * needed to ensure an unsaturated output out of a subframe
3435 * energy calculation (g_corr).
3436 *
3437 * REFERENCES: Sub-clause 4.1.9 and 4.2.1 of GSM Recomendation 06.20
3438 *
3439 * KEYWORDS: spectral postfilter
3440 *
3441 *************************************************************************/
3442
3443 Shortword r0BasedEnergyShft(Shortword swR0Index)
3444 {
3445
3446 /*_________________________________________________________________________
3447 | |
3448 | Automatic Variables |
3449 |_________________________________________________________________________|
3450 */
3451
3452 Shortword swShiftDownSignal;
3453
3454 /*_________________________________________________________________________
3455 | |
3456 | Executable Code |
3457 |_________________________________________________________________________|
3458 */
3459
3460 if (sub(swR0Index, 26) <= 0)
3461 {
3462 if (sub(swR0Index, 23) <= 0)
3463 {
3464 if (sub(swR0Index, 21) <= 0)
3465 swShiftDownSignal = 0; /* r0 [0, 21] */
3466 else
3467 swShiftDownSignal = 1; /* r0 [22, 23] */
3468 }
3469 else
3470 {
3471 if (sub(swR0Index, 24) <= 0)
3472 swShiftDownSignal = 2; /* r0 [23, 24] */
3473 else
3474 swShiftDownSignal = 3; /* r0 [24, 26] */
3475 }
3476 }
3477 else
3478 { /* r0 index > 26 */
3479 if (sub(swR0Index, 28) <= 0)
3480 {
3481 swShiftDownSignal = 4; /* r0 [26, 28] */
3482 }
3483 else
3484 {
3485 if (sub(swR0Index, 29) <= 0)
3486 swShiftDownSignal = 5; /* r0 [28, 29] */
3487 else
3488 swShiftDownSignal = 6; /* r0 [29, 31] */
3489 }
3490 }
3491 if (sub(swR0Index, 18) > 0)
3492 swShiftDownSignal = add(swShiftDownSignal, 2);
3493
3494 return (swShiftDownSignal);
3495 }
3496
3497 /***************************************************************************
3498 *
3499 * FUNCTION NAME: rcToADp
3500 *
3501 * PURPOSE:
3502 *
3503 * This subroutine computes a vector of direct form LPC filter
3504 * coefficients, given an input vector of reflection coefficients.
3505 * Double precision is used internally, but 16 bit direct form
3506 * filter coefficients are returned.
3507 *
3508 * INPUTS:
3509 *
3510 * NP
3511 * order of the LPC filter (global constant)
3512 *
3513 * swAscale
3514 * The multiplier which scales down the direct form
3515 * filter coefficients.
3516 *
3517 * pswRc[0:NP-1]
3518 * The input vector of reflection coefficients.
3519 *
3520 * OUTPUTS:
3521 *
3522 * pswA[0:NP-1]
3523 * Array containing the scaled down direct form LPC
3524 * filter coefficients.
3525 *
3526 * RETURN VALUE:
3527 *
3528 * siLimit
3529 * 1 if limiting occured in computation, 0 otherwise.
3530 *
3531 * DESCRIPTION:
3532 *
3533 * This function performs the conversion from reflection coefficients
3534 * to direct form LPC filter coefficients. The direct form coefficients
3535 * are scaled by multiplication by swAscale. NP, the filter order is 10.
3536 * The a's and rc's each have NP elements in them. Double precision
3537 * calculations are used internally.
3538 *
3539 * The equations are:
3540 * for i = 0 to NP-1{
3541 *
3542 * a(i)(i) = rc(i) (scaling by swAscale occurs here)
3543 *
3544 * for j = 0 to i-1
3545 * a(i)(j) = a(i-1)(j) + rc(i)*a(i-1)(i-j-1)
3546 * }
3547 *
3548 * See page 443, of
3549 * "Digital Processing of Speech Signals" by L.R. Rabiner and R.W.
3550 * Schafer; Prentice-Hall; Englewood Cliffs, NJ (USA). 1978.
3551 *
3552 * REFERENCES: Sub-clause 4.1.7 and 4.2.3 of GSM Recomendation 06.20
3553 *
3554 * KEYWORDS: reflectioncoefficients, parcors, conversion, rctoadp, ks, as
3555 * KEYWORDS: parcorcoefficients, lpc, flat, vectorquantization
3556 *
3557 *************************************************************************/
3558
3559 short rcToADp(Shortword swAscale, Shortword pswRc[],
3560 Shortword pswA[])
3561 {
3562
3563 /*_________________________________________________________________________
3564 | |
3565 | Automatic Variables |
3566 |_________________________________________________________________________|
3567 */
3568
3569 Longword pL_ASpace[NP],
3570 pL_tmpSpace[NP],
3571 L_temp,
3572 *pL_A,
3573 *pL_tmp,
3574 *pL_swap;
3575
3576 short int i,
3577 j, /* loop counters */
3578 siLimit;
3579
3580 /*_________________________________________________________________________
3581 | |
3582 | Executable Code |
3583 |_________________________________________________________________________|
3584 */
3585
3586 /* Initialize starting addresses for temporary buffers */
3587 /*-----------------------------------------------------*/
3588
3589 pL_A = pL_ASpace;
3590 pL_tmp = pL_tmpSpace;
3591
3592 /* Initialize the flag for checking if limiting has occured */
3593 /*----------------------------------------------------------*/
3594
3595 siLimit = 0;
3596
3597 /* Compute direct form filter coefficients, pswA[0],...,pswA[9] */
3598 /*-------------------------------------------------------------------*/
3599
3600 for (i = 0; i < NP; i++)
3601 {
3602
3603 pL_tmp[i] = L_mult(swAscale, pswRc[i]);
3604 for (j = 0; j <= i - 1; j++)
3605 {
3606 L_temp = L_mpy_ls(pL_A[i - j - 1], pswRc[i]);
3607 pL_tmp[j] = L_add(L_temp, pL_A[j]);
3608 siLimit |= isLwLimit(pL_tmp[j]);
3609 }
3610 if (i != NP - 1)
3611 {
3612 /* Swap swA and swTmp buffers */
3613
3614 pL_swap = pL_tmp;
3615 pL_tmp = pL_A;
3616 pL_A = pL_swap;
3617 }
3618 }
3619
3620 for (i = 0; i < NP; i++)
3621 {
3622 pswA[i] = round(pL_tmp[i]);
3623 siLimit |= isSwLimit(pswA[i]);
3624 }
3625 return (siLimit);
3626 }
3627
3628 /***************************************************************************
3629 *
3630 * FUNCTION NAME: rcToCorrDpL
3631 *
3632 * PURPOSE:
3633 *
3634 * This subroutine computes an autocorrelation vector, given a vector
3635 * of reflection coefficients as an input. Double precision calculations
3636 * are used internally, and a double precision (Longword)
3637 * autocorrelation sequence is returned.
3638 *
3639 * INPUTS:
3640 *
3641 * NP
3642 * LPC filter order passed in as a global constant.
3643 *
3644 * swAshift
3645 * Number of right shifts to be applied to the
3646 * direct form filter coefficients being computed
3647 * as an intermediate step to generating the
3648 * autocorrelation sequence.
3649 *
3650 * swAscale
3651 * A multiplicative scale factor corresponding to
3652 * swAshift; i.e. swAscale = 2 ^(-swAshift).
3653 *
3654 * pswRc[0:NP-1]
3655 * An input vector of reflection coefficients.
3656 *
3657 * OUTPUTS:
3658 *
3659 * pL_R[0:NP]
3660 * An output Longword array containing the
3661 * autocorrelation vector where
3662 * pL_R[0] = 0x7fffffff; (i.e., ~1.0).
3663 *
3664 * RETURN VALUE:
3665 *
3666 * none
3667 *
3668 * DESCRIPTION:
3669 *
3670 * The algorithm used for computing the correlation sequence is
3671 * described on page 232 of the book "Linear Prediction of Speech",
3672 * by J.D. Markel and A.H. Gray, Jr.; Springer-Verlag, Berlin,
3673 * Heidelberg, New York, 1976.
3674 *
3675 * REFERENCES: Sub_Clause 4.1.4 and 4.2.1 of GSM Recomendation 06.20
3676 *
3677 * KEYWORDS: normalized autocorrelation, reflection coefficients
3678 * KEYWORDS: conversion
3679 *
3680 **************************************************************************/
3681
3682 void rcToCorrDpL(Shortword swAshift, Shortword swAscale,
3683 Shortword pswRc[], Longword pL_R[])
3684 {
3685
3686 /*_________________________________________________________________________
3687 | |
3688 | Automatic Variables |
3689 |_________________________________________________________________________|
3690 */
3691
3692 Longword pL_ASpace[NP],
3693 pL_tmpSpace[NP],
3694 L_temp,
3695 L_sum,
3696 *pL_A,
3697 *pL_tmp,
3698 *pL_swap;
3699
3700 short int i,
3701 j; /* loop control variables */
3702
3703 /*_________________________________________________________________________
3704 | |
3705 | Executable Code |
3706 |_________________________________________________________________________|
3707 */
3708
3709 /* Set R[0] = 0x7fffffff, (i.e., R[0] = 1.0) */
3710 /*-------------------------------------------*/
3711
3712 pL_R[0] = LW_MAX;
3713
3714 /* Assign an address onto each of the two temporary buffers */
3715 /*----------------------------------------------------------*/
3716
3717 pL_A = pL_ASpace;
3718 pL_tmp = pL_tmpSpace;
3719
3720 /* Compute correlations R[1],...,R[10] */
3721 /*------------------------------------*/
3722
3723 for (i = 0; i < NP; i++)
3724 {
3725
3726 /* Compute, as an intermediate step, the filter coefficients for */
3727 /* for an i-th order direct form filter (pL_tmp[j],j=0,i) */
3728 /*---------------------------------------------------------------*/
3729
3730 pL_tmp[i] = L_mult(swAscale, pswRc[i]);
3731 for (j = 0; j <= i - 1; j++)
3732 {
3733 L_temp = L_mpy_ls(pL_A[i - j - 1], pswRc[i]);
3734 pL_tmp[j] = L_add(L_temp, pL_A[j]);
3735 }
3736
3737 /* Swap pL_A and pL_tmp buffers */
3738 /*------------------------------*/
3739
3740 pL_swap = pL_A;
3741 pL_A = pL_tmp;
3742 pL_tmp = pL_swap;
3743
3744 /* Given the direct form filter coefficients for an i-th order filter */
3745 /* and the autocorrelation vector computed up to and including stage i */
3746 /* compute the autocorrelation coefficient R[i+1] */
3747 /*---------------------------------------------------------------------*/
3748
3749 L_temp = L_mpy_ll(pL_A[0], pL_R[i]);
3750 L_sum = L_negate(L_temp);
3751
3752 for (j = 1; j <= i; j++)
3753 {
3754 L_temp = L_mpy_ll(pL_A[j], pL_R[i - j]);
3755 L_sum = L_sub(L_sum, L_temp);
3756 }
3757 pL_R[i + 1] = L_shl(L_sum, swAshift);
3758
3759 }
3760 }
3761
3762 /***************************************************************************
3763 *
3764 * FUNCTION NAME: res_eng
3765 *
3766 * PURPOSE:
3767 *
3768 * Calculates square root of subframe residual energy estimate:
3769 *
3770 * sqrt( R(0)(1-k1**2)...(1-k10**2) )
3771 *
3772 * INPUTS:
3773 *
3774 * pswReflecCoefIn[0:9]
3775 *
3776 * Array of reflection coeffcients.
3777 *
3778 * swRq
3779 *
3780 * Subframe energy = sqrt(frame_energy * S_LEN/2**S_SH)
3781 * (quantized).
3782 *
3783 * OUTPUTS:
3784 *
3785 * psnsSqrtRsOut
3786 *
3787 * (Pointer to) the output residual energy estimate.
3788 *
3789 * RETURN VALUE:
3790 *
3791 * The shift count of the normalized residual energy estimate, as int.
3792 *
3793 * DESCRIPTION:
3794 *
3795 * First, the canonic product of the (1-ki**2) terms is calculated
3796 * (normalizations are done to maintain precision). Also, a factor of
3797 * 2**S_SH is applied to the product to offset this same factor in the
3798 * quantized square root of the subframe energy.
3799 *
3800 * Then the product is square-rooted, and multiplied by the quantized
3801 * square root of the subframe energy. This combined product is put
3802 * out as a normalized fraction and shift count (mantissa and exponent).
3803 *
3804 * REFERENCES: Sub-clause 4.1.7 and 4.2.1 of GSM Recomendation 06.20
3805 *
3806 * KEYWORDS: residualenergy, res_eng, rs
3807 *
3808 *************************************************************************/
3809
3810 void res_eng(Shortword pswReflecCoefIn[], Shortword swRq,
3811 struct NormSw *psnsSqrtRsOut)
3812 {
3813 /*_________________________________________________________________________
3814 | |
3815 | Local Constants |
3816 |_________________________________________________________________________|
3817 */
3818
3819 #define S_SH 6 /* ceiling(log2(S_LEN)) */
3820 #define MINUS_S_SH -S_SH
3821
3822
3823 /*_________________________________________________________________________
3824 | |
3825 | Automatic Variables |
3826 |_________________________________________________________________________|
3827 */
3828
3829 Longword L_Product,
3830 L_Shift,
3831 L_SqrtResEng;
3832
3833 Shortword swPartialProduct,
3834 swPartialProductShift,
3835 swTerm,
3836 swShift,
3837 swSqrtPP,
3838 swSqrtPPShift,
3839 swSqrtResEng,
3840 swSqrtResEngShift;
3841
3842 short int i;
3843
3844 /*_________________________________________________________________________
3845 | |
3846 | Executable Code |
3847 |_________________________________________________________________________|
3848 */
3849
3850 /* Form canonic product, maintain precision and shift count */
3851 /*----------------------------------------------------------*/
3852
3853 /* (Start off with unity product (actually -1), and shift offset) */
3854 /*----------------------------------------------------------------*/
3855 swPartialProduct = SW_MIN;
3856 swPartialProductShift = MINUS_S_SH;
3857
3858 for (i = 0; i < NP; i++)
3859 {
3860
3861 /* Get next (-1 + k**2) term, form partial canonic product */
3862 /*---------------------------------------------------------*/
3863
3864
3865 swTerm = mac_r(LW_MIN, pswReflecCoefIn[i], pswReflecCoefIn[i]);
3866
3867 L_Product = L_mult(swTerm, swPartialProduct);
3868
3869 /* Normalize partial product, round */
3870 /*----------------------------------*/
3871
3872 swShift = norm_s(extract_h(L_Product));
3873 swPartialProduct = round(L_shl(L_Product, swShift));
3874 swPartialProductShift = add(swPartialProductShift, swShift);
3875 }
3876
3877 /* Correct sign of product, take square root */
3878 /*-------------------------------------------*/
3879
3880 swPartialProduct = abs_s(swPartialProduct);
3881
3882 swSqrtPP = sqroot(L_deposit_h(swPartialProduct));
3883
3884 L_Shift = L_shr(L_deposit_h(swPartialProductShift), 1);
3885
3886 swSqrtPPShift = extract_h(L_Shift);
3887
3888 if (extract_l(L_Shift) != 0)
3889 {
3890
3891 /* Odd exponent: shr above needs to be compensated by multiplying */
3892 /* mantissa by sqrt(0.5) */
3893 /*----------------------------------------------------------------*/
3894
3895 swSqrtPP = mult_r(swSqrtPP, SQRT_ONEHALF);
3896 }
3897
3898 /* Form final product, the residual energy estimate, and do final */
3899 /* normalization */
3900 /*----------------------------------------------------------------*/
3901
3902 L_SqrtResEng = L_mult(swRq, swSqrtPP);
3903
3904 swShift = norm_l(L_SqrtResEng);
3905 swSqrtResEng = round(L_shl(L_SqrtResEng, swShift));
3906 swSqrtResEngShift = add(swSqrtPPShift, swShift);
3907
3908 /* Return */
3909 /*--------*/
3910 psnsSqrtRsOut->man = swSqrtResEng;
3911 psnsSqrtRsOut->sh = swSqrtResEngShift;
3912
3913 return;
3914 }
3915
3916 /***************************************************************************
3917 *
3918 * FUNCTION NAME: rs_rr
3919 *
3920 * PURPOSE:
3921 *
3922 * Calculates sqrt(RS/R(x,x)) using floating point format,
3923 * where RS is the approximate residual energy in a given
3924 * subframe and R(x,x) is the power in each long term
3925 * predictor vector or in each codevector.
3926 * Used in the joint optimization of the gain and the long
3927 * term predictor coefficient.
3928 *
3929 * INPUTS:
3930 *
3931 * pswExcitation[0:39] - excitation signal array
3932 * snsSqrtRs - structure sqrt(RS) normalized with mantissa and shift
3933 *
3934 * OUTPUTS:
3935 *
3936 * snsSqrtRsRr - structure sqrt(RS/R(x,x)) with mantissa and shift
3937 *
3938 * RETURN VALUE:
3939 *
3940 * None
3941 *
3942 * DESCRIPTION:
3943 *
3944 * Implemented as sqrt(RS)/sqrt(R(x,x)) where both sqrts
3945 * are stored normalized (0.5<=x<1.0) and the associated
3946 * shift. See section 4.1.11.1 for details
3947 *
3948 * REFERENCES: Sub-clause 4.1.11.1 and 4.2.1 of GSM
3949 * Recomendation 06.20
3950 *
3951 * KEYWORDS: rs_rr, sqroot
3952 *
3953 *************************************************************************/
3954
3955 void rs_rr(Shortword pswExcitation[], struct NormSw snsSqrtRs,
3956 struct NormSw *snsSqrtRsRr)
3957 {
3958
3959 /*_________________________________________________________________________
3960 | |
3961 | Automatic Variables |
3962 |_________________________________________________________________________|
3963 */
3964 Longword L_Temp;
3965 Shortword swTemp,
3966 swTemp2,
3967 swEnergy,
3968 swNormShift,
3969 swShift;
3970
3971 /*_________________________________________________________________________
3972 | |
3973 | Executable Code |
3974 |_________________________________________________________________________|
3975 */
3976
3977 swEnergy = sub(shl(snsSqrtRs.sh, 1), 3); /* shift*2 + margin ==
3978 * energy. */
3979
3980
3981 if (swEnergy < 0)
3982 {
3983
3984 /* High-energy residual: scale input vector during energy */
3985 /* calculation. The shift count of the energy of the */
3986 /* residual estimate is used as an estimate of the shift */
3987 /* count needed for the excitation energy */
3988 /*--------------------------------------------------------*/
3989
3990 swNormShift = g_corr1s(pswExcitation, negate(swEnergy), &L_Temp);
3991
3992 }
3993 else
3994 {
3995
3996 /* Lower-energy residual: no overflow protection needed */
3997 /*------------------------------------------------------*/
3998
3999 swNormShift = g_corr1(pswExcitation, &L_Temp);
4000 }
4001
4002 /* Compute single precision square root of energy sqrt(R(x,x)) */
4003 /* ----------------------------------------------------------- */
4004 swTemp = sqroot(L_Temp);
4005
4006 /* If odd no. of shifts compensate by sqrt(0.5) */
4007 /* -------------------------------------------- */
4008 if (swNormShift & 1)
4009 {
4010
4011 /* Decrement no. of shifts in accordance with sqrt(0.5) */
4012 /* ---------------------------------------------------- */
4013 swNormShift = sub(swNormShift, 1);
4014
4015 /* sqrt(R(x,x) = sqrt(R(x,x)) * sqrt(0.5) */
4016 /* -------------------------------------- */
4017 L_Temp = L_mult(0x5a82, swTemp);
4018 }
4019 else
4020 {
4021 L_Temp = L_deposit_h(swTemp);
4022 }
4023
4024 /* Normalize again and update shifts */
4025 /* --------------------------------- */
4026 swShift = norm_l(L_Temp);
4027 swNormShift = add(shr(swNormShift, 1), swShift);
4028 L_Temp = L_shl(L_Temp, swShift);
4029
4030 /* Shift sqrt(RS) to make sure less than divisor */
4031 /* --------------------------------------------- */
4032 swTemp = shr(snsSqrtRs.man, 1);
4033
4034 /* Divide sqrt(RS)/sqrt(R(x,x)) */
4035 /* ---------------------------- */
4036 swTemp2 = divide_s(swTemp, round(L_Temp));
4037
4038 /* Calculate shift for division, compensate for shift before division */
4039 /* ------------------------------------------------------------------ */
4040 swNormShift = sub(snsSqrtRs.sh, swNormShift);
4041 swNormShift = sub(swNormShift, 1);
4042
4043 /* Normalize and get no. of shifts */
4044 /* ------------------------------- */
4045 swShift = norm_s(swTemp2);
4046 snsSqrtRsRr->sh = add(swNormShift, swShift);
4047 snsSqrtRsRr->man = shl(swTemp2, swShift);
4048
4049 }
4050
4051 /***************************************************************************
4052 *
4053 * FUNCTION NAME: rs_rrNs
4054 *
4055 * PURPOSE:
4056 *
4057 * Calculates sqrt(RS/R(x,x)) using floating point format,
4058 * where RS is the approximate residual energy in a given
4059 * subframe and R(x,x) is the power in each long term
4060 * predictor vector or in each codevector.
4061 *
4062 * Used in the joint optimization of the gain and the long
4063 * term predictor coefficient.
4064 *
4065 * INPUTS:
4066 *
4067 * pswExcitation[0:39] - excitation signal array
4068 * snsSqrtRs - structure sqrt(RS) normalized with mantissa and shift
4069 *
4070 * OUTPUTS:
4071 *
4072 * snsSqrtRsRr - structure sqrt(RS/R(x,x)) with mantissa and shift
4073 *
4074 * RETURN VALUE:
4075 *
4076 * None
4077 *
4078 * DESCRIPTION:
4079 *
4080 * Implemented as sqrt(RS)/sqrt(R(x,x)) where both sqrts
4081 * are stored normalized (0.5<=x<1.0) and the associated
4082 * shift.
4083 *
4084 * REFERENCES: Sub-clause 4.1.11.1 and 4.2.1 of GSM
4085 * Recomendation 06.20
4086 *
4087 * KEYWORDS: rs_rr, sqroot
4088 *
4089 *************************************************************************/
4090
4091 void rs_rrNs(Shortword pswExcitation[], struct NormSw snsSqrtRs,
4092 struct NormSw *snsSqrtRsRr)
4093 {
4094
4095 /*_________________________________________________________________________
4096 | |
4097 | Automatic Variables |
4098 |_________________________________________________________________________|
4099 */
4100 Longword L_Temp;
4101 Shortword swTemp,
4102 swTemp2,
4103 swNormShift,
4104 swShift;
4105
4106 /*_________________________________________________________________________
4107 | |
4108 | Executable Code |
4109 |_________________________________________________________________________|
4110 */
4111
4112 /* Lower-energy residual: no overflow protection needed */
4113 /*------------------------------------------------------*/
4114
4115 swNormShift = g_corr1(pswExcitation, &L_Temp);
4116
4117
4118 /* Compute single precision square root of energy sqrt(R(x,x)) */
4119 /* ----------------------------------------------------------- */
4120 swTemp = sqroot(L_Temp);
4121
4122 /* If odd no. of shifts compensate by sqrt(0.5) */
4123 /* -------------------------------------------- */
4124 if (swNormShift & 1)
4125 {
4126
4127 /* Decrement no. of shifts in accordance with sqrt(0.5) */
4128 /* ---------------------------------------------------- */
4129 swNormShift = sub(swNormShift, 1);
4130
4131 /* sqrt(R(x,x) = sqrt(R(x,x)) * sqrt(0.5) */
4132 /* -------------------------------------- */
4133 L_Temp = L_mult(0x5a82, swTemp);
4134 }
4135 else
4136 {
4137 L_Temp = L_deposit_h(swTemp);
4138 }
4139
4140 /* Normalize again and update shifts */
4141 /* --------------------------------- */
4142
4143 swShift = norm_l(L_Temp);
4144 swNormShift = add(shr(swNormShift, 1), swShift);
4145 L_Temp = L_shl(L_Temp, swShift);
4146
4147 /* Shift sqrt(RS) to make sure less than divisor */
4148 /* --------------------------------------------- */
4149 swTemp = shr(snsSqrtRs.man, 1);
4150
4151 /* Divide sqrt(RS)/sqrt(R(x,x)) */
4152 /* ---------------------------- */
4153 swTemp2 = divide_s(swTemp, round(L_Temp));
4154
4155 /* Calculate shift for division, compensate for shift before division */
4156 /* ------------------------------------------------------------------ */
4157 swNormShift = sub(snsSqrtRs.sh, swNormShift);
4158 swNormShift = sub(swNormShift, 1);
4159
4160 /* Normalize and get no. of shifts */
4161 /* ------------------------------- */
4162 swShift = norm_s(swTemp2);
4163 snsSqrtRsRr->sh = add(swNormShift, swShift);
4164 snsSqrtRsRr->man = shl(swTemp2, swShift);
4165
4166 }
4167
4168
4169 /***************************************************************************
4170 *
4171 * FUNCTION NAME: scaleExcite
4172 *
4173 * PURPOSE:
4174 *
4175 * Scale an arbitrary excitation vector (codevector or
4176 * pitch vector)
4177 *
4178 * INPUTS:
4179 *
4180 * pswVect[0:39] - the unscaled vector.
4181 * iGsp0Scale - an positive offset to compensate for the fact
4182 * that GSP0 table is scaled down.
4183 * swErrTerm - rather than a gain being passed in, (beta, gamma)
4184 * it is calculated from this error term - either
4185 * Gsp0[][][0] error term A or Gsp0[][][1] error
4186 * term B. Beta is calculated from error term A,
4187 * gamma from error term B.
4188 * snsRS - the RS_xx appropriate to pswVect.
4189 *
4190 * OUTPUTS:
4191 *
4192 * pswScldVect[0:39] - the output, scaled excitation vector.
4193 *
4194 * RETURN VALUE:
4195 *
4196 * swGain - One of two things. Either a clamped value of 0x7fff if the
4197 * gain's shift was > 0 or the rounded vector gain otherwise.
4198 *
4199 * DESCRIPTION:
4200 *
4201 * If gain > 1.0 then
4202 * (do not shift gain up yet)
4203 * partially scale vector element THEN shift and round save
4204 * else
4205 * shift gain correctly
4206 * scale vector element and round save
4207 * update state array
4208 *
4209 * REFERENCES: Sub-clause 4.1.10.2 and 4.2.1 of GSM
4210 * Recomendation 06.20
4211 *
4212 * KEYWORDS: excite_vl, sc_ex, excitevl, scaleexcite, codevector, p_vec,
4213 * KEYWORDS: x_vec, pitchvector, gain, gsp0
4214 *
4215 *************************************************************************/
4216
4217 Shortword scaleExcite(Shortword pswVect[],
4218 Shortword swErrTerm, struct NormSw snsRS,
4219 Shortword pswScldVect[])
4220 {
4221
4222 /*_________________________________________________________________________
4223 | |
4224 | Automatic Variables |
4225 |_________________________________________________________________________|
4226 */
4227 Longword L_GainUs,
4228 L_scaled,
4229 L_Round_off;
4230 Shortword swGain,
4231 swGainUs,
4232 swGainShift,
4233 i,
4234 swGainUsShft;
4235
4236 /*_________________________________________________________________________
4237 | |
4238 | Executable Code |
4239 |_________________________________________________________________________|
4240 */
4241
4242
4243 L_GainUs = L_mult(swErrTerm, snsRS.man);
4244 swGainUsShft = norm_s(extract_h(L_GainUs));
4245 L_GainUs = L_shl(L_GainUs, swGainUsShft);
4246
4247 swGainShift = add(swGainUsShft, snsRS.sh);
4248 swGainShift = sub(swGainShift, GSP0_SCALE);
4249
4250
4251 /* gain > 1.0 */
4252 /* ---------- */
4253
4254 if (swGainShift < 0)
4255 {
4256 swGainUs = round(L_GainUs);
4257
4258 L_Round_off = L_shl((long) 32768, swGainShift);
4259
4260 for (i = 0; i < S_LEN; i++)
4261 {
4262 L_scaled = L_mac(L_Round_off, swGainUs, pswVect[i]);
4263 L_scaled = L_shr(L_scaled, swGainShift);
4264 pswScldVect[i] = extract_h(L_scaled);
4265 }
4266
4267 if (swGainShift == 0)
4268 swGain = swGainUs;
4269 else
4270 swGain = 0x7fff;
4271 }
4272
4273 /* gain < 1.0 */
4274 /* ---------- */
4275
4276 else
4277 {
4278
4279 /* shift down or not at all */
4280 /* ------------------------ */
4281 if (swGainShift > 0)
4282 L_GainUs = L_shr(L_GainUs, swGainShift);
4283
4284 /* the rounded actual vector gain */
4285 /* ------------------------------ */
4286 swGain = round(L_GainUs);
4287
4288 /* now scale the vector (with rounding) */
4289 /* ------------------------------------ */
4290
4291 for (i = 0; i < S_LEN; i++)
4292 {
4293 L_scaled = L_mac((long) 32768, swGain, pswVect[i]);
4294 pswScldVect[i] = extract_h(L_scaled);
4295 }
4296 }
4297 return (swGain);
4298 }
4299
4300 /***************************************************************************
4301 *
4302 * FUNCTION NAME: spectralPostFilter
4303 *
4304 * PURPOSE:
4305 *
4306 * Perform spectral post filter on the output of the
4307 * synthesis filter.
4308 *
4309 *
4310 * INPUT:
4311 *
4312 * S_LEN a global constant
4313 *
4314 * pswSPFIn[0:S_LEN-1]
4315 *
4316 * input to the routine. Unmodified
4317 * pswSPFIn[0] is the oldest point (first to be filtered),
4318 * pswSPFIn[iLen-1] is the last pointer filtered,
4319 * the newest.
4320 *
4321 * pswNumCoef[0:NP-1],pswDenomCoef[0:NP-1]
4322 *
4323 * numerator and denominator
4324 * direct form coeffs used by postfilter.
4325 * Exactly like lpc coefficients in format. Shifted down
4326 * by iAShift to ensure that they are < 1.0.
4327 *
4328 * gpswPostFiltStateNum[0:NP-1], gpswPostFiltStateDenom[0:NP-1]
4329 *
4330 * array of the filter state.
4331 * Same format as coefficients: *praState = state of
4332 * filter for delay n = -1 praState[NP] = state of
4333 * filter for delay n = -NP These numbers are not
4334 * shifted at all. These states are static to this
4335 * file.
4336 *
4337 * OUTPUT:
4338 *
4339 * gpswPostFiltStateNum[0:NP-1], gpswPostFiltStateDenom[0:NP-1]
4340 *
4341 * See above for description. These are updated.
4342 *
4343 * pswSPFOut[0:S_LEN-1]
4344 *
4345 * same format as pswSPFIn,
4346 * *pswSPFOut is oldest point. The filtered output.
4347 * Note this routine can handle pswSPFOut = pswSPFIn.
4348 * output can be the same as input. i.e. in place
4349 * calculation.
4350 *
4351 * RETURN:
4352 *
4353 * none
4354 *
4355 * DESCRIPTION:
4356 *
4357 * find energy in input,
4358 * perform the numerator fir
4359 * perform the denominator iir
4360 * perform the post emphasis
4361 * find energy in signal,
4362 * perform the agc using energy in and energy in signam after
4363 * post emphasis signal
4364 *
4365 * The spectral postfilter is described in section 4.2.4.
4366 *
4367 * REFERENCES: Sub-clause 4.2.4 of GSM Recomendation 06.20
4368 *
4369 * KEYWORDS: postfilter, emphasis, postemphasis, brightness,
4370 * KEYWORDS: numerator, deminator, filtering, lpc,
4371 *
4372 *************************************************************************/
4373
4374 static void spectralPostFilter(Shortword pswSPFIn[],
4375 Shortword pswNumCoef[],
4376 Shortword pswDenomCoef[], Shortword pswSPFOut[])
4377 {
4378 /*_________________________________________________________________________
4379 | |
4380 | Local Constants |
4381 |_________________________________________________________________________|
4382 */
4383
4384 #define AGC_COEF (Shortword)0x19a /* (1.0 - POST_AGC_COEF)
4385 * 1.0-.9875 */
4386 #define POST_EMPHASIS (Shortword)0x199a /* 0.2 */
4387
4388 /*_________________________________________________________________________
4389 | |
4390 | Automatic Variables |
4391 |_________________________________________________________________________|
4392 */
4393
4394 short int i;
4395
4396 Longword L_OrigEnergy,
4397 L_runningGain,
4398 L_Output;
4399
4400 Shortword swAgcGain,
4401 swRunningGain,
4402 swTemp;
4403
4404 struct NormSw snsOrigEnergy;
4405
4406 /*_________________________________________________________________________
4407 | |
4408 | Executable Code |
4409 |_________________________________________________________________________|
4410 */
4411
4412 /* calculate the energy in the input and save it */
4413 /*-----------------------------------------------*/
4414
4415 snsOrigEnergy.sh = g_corr1s(pswSPFIn, swEngyRShift, &L_OrigEnergy);
4416 snsOrigEnergy.man = round(L_OrigEnergy);
4417
4418 /* numerator of the postfilter */
4419 /*-----------------------------*/
4420
4421 lpcFir(pswSPFIn, pswNumCoef, gpswPostFiltStateNum, pswSPFOut);
4422
4423 /* denominator of the postfilter */
4424 /*-------------------------------*/
4425
4426 lpcIir(pswSPFOut, pswDenomCoef, gpswPostFiltStateDenom, pswSPFOut);
4427
4428 /* postemphasis section of postfilter */
4429 /*------------------------------------*/
4430
4431 for (i = 0; i < S_LEN; i++)
4432 {
4433 swTemp = msu_r(L_deposit_h(pswSPFOut[i]), swPostEmphasisState,
4434 POST_EMPHASIS);
4435 swPostEmphasisState = pswSPFOut[i];
4436 pswSPFOut[i] = swTemp;
4437 }
4438
4439 swAgcGain = agcGain(pswSPFOut, snsOrigEnergy, swEngyRShift);
4440
4441 /* scale the speech vector */
4442 /*-----------------------------*/
4443
4444 swRunningGain = gswPostFiltAgcGain;
4445 L_runningGain = L_deposit_h(gswPostFiltAgcGain);
4446 for (i = 0; i < S_LEN; i++)
4447 {
4448 L_runningGain = L_msu(L_runningGain, swRunningGain, AGC_COEF);
4449 L_runningGain = L_mac(L_runningGain, swAgcGain, AGC_COEF);
4450 swRunningGain = extract_h(L_runningGain);
4451
4452 /* now scale input with gain */
4453
4454 L_Output = L_mult(swRunningGain, pswSPFOut[i]);
4455 pswSPFOut[i] = extract_h(L_shl(L_Output, 2));
4456 }
4457 gswPostFiltAgcGain = swRunningGain;
4458
4459 }
4460
4461 /***************************************************************************
4462 *
4463 * FUNCTION NAME: speechDecoder
4464 *
4465 * PURPOSE:
4466 * The purpose of this function is to call all speech decoder
4467 * subroutines. This is the top level routine for the speech
4468 * decoder.
4469 *
4470 * INPUTS:
4471 *
4472 * pswParameters[0:21]
4473 *
4474 * pointer to this frame's parameters. See below for input
4475 * data format.
4476 *
4477 * OUTPUTS:
4478 *
4479 * pswDecodedSpeechFrame[0:159]
4480 *
4481 * this frame's decoded 16 bit linear pcm frame
4482 *
4483 * RETURN VALUE:
4484 *
4485 * none
4486 *
4487 * DESCRIPTION:
4488 *
4489 * The sequence of events in the decoder, and therefore this routine
4490 * follow a simple plan. First, the frame based parameters are
4491 * decoded. Second, on a subframe basis, the subframe based
4492 * parameters are decoded and the excitation is generated. Third,
4493 * on a subframe basis, the combined and scaled excitation is
4494 * passed through the synthesis filter, and then the pitch and
4495 * spectral postfilters.
4496 *
4497 * The in-line comments for the routine speechDecoder, are very
4498 * detailed. Here in a more consolidated form, are the main
4499 * points.
4500 *
4501 * The R0 parameter is decoded using the lookup table
4502 * psrR0DecTbl[]. The LPC codewords are looked up using lookupVQ().
4503 * The decoded parameters are reflection coefficients
4504 * (pswFrmKs[]).
4505 *
4506 * The decoder does not use reflection coefficients directly.
4507 * Instead it converts them to direct form coeficients. This is
4508 * done using rcToADp(). If this conversion results in invalid
4509 * results, the previous frames parameters are used.
4510 *
4511 * The direct form coeficients are used to derive the spectal
4512 * postfilter's numerator and denominator coeficients. The
4513 * denominators coefficients are widened, and the numerators
4514 * coefficients are a spectrally smoothed version of the
4515 * denominator. The smoothing is done with a_sst().
4516 *
4517 * The frame based LPC coefficients are either used directly as the
4518 * subframe coefficients, or are derived through interpolation.
4519 * The subframe based coeffiecients are calculated in getSfrmLpc().
4520 *
4521 * Based on voicing mode, the decoder will construct and scale the
4522 * excitation in one of two ways. For the voiced mode the lag is
4523 * decoded using lagDecode(). The fractional pitch LTP lookup is
4524 * done by the function fp_ex(). In both voiced and unvoiced
4525 * mode, the VSELP codewords are decoded into excitation vectors
4526 * using b_con() and v_con().
4527 *
4528 * rs_rr(), rs_rrNs(), and scaleExcite() are used to calculate
4529 * the gamma's, codevector gains, as well as beta, the LTP vector
4530 * gain. Description of this can be found in section 4.1.11. Once
4531 * the vectors have been scaled and combined, the excitation is
4532 * stored in the LTP history.
4533 *
4534 * The excitation, pswExcite[], passes through the pitch pre-filter
4535 * (pitchPreFilt()). Then the harmonically enhanced excitation
4536 * passes through the synthesis filter, lpcIir(), and finally the
4537 * reconstructed speech passes through the spectral post-filter
4538 * (spectalPostFilter()). The final output speech is passed back in
4539 * the array pswDecodedSpeechFrame[].
4540 *
4541 * INPUT DATA FORMAT:
4542 *
4543 * The format/content of the input parameters is the so called
4544 * bit alloc format.
4545 *
4546 * voiced mode bit alloc format:
4547 * -----------------------------
4548 * index number of bits parameter name
4549 * 0 5 R0
4550 * 1 11 k1Tok3
4551 * 2 9 k4Tok6
4552 * 3 8 k7Tok10
4553 * 4 1 softInterpolation
4554 * 5 2 voicingDecision
4555 * 6 8 frameLag
4556 * 7 9 code_1
4557 * 8 5 gsp0_1
4558 * 9 4 deltaLag_2
4559 * 10 9 code_2
4560 * 11 5 gsp0_2
4561 * 12 4 deltaLag_3
4562 * 13 9 code_3
4563 * 14 5 gsp0_3
4564 * 15 4 deltaLag_4
4565 * 16 9 code_4
4566 * 17 5 gsp0_4
4567 *
4568 * 18 1 BFI
4569 * 19 1 UFI
4570 * 20 2 SID
4571 * 21 1 TAF
4572 *
4573 *
4574 * unvoiced mode bit alloc format:
4575 * -------------------------------
4576 *
4577 * index number of bits parameter name
4578 * 0 5 R0
4579 * 1 11 k1Tok3
4580 * 2 9 k4Tok6
4581 * 3 8 k7Tok10
4582 * 4 1 softInterpolation
4583 * 5 2 voicingDecision
4584 * 6 7 code1_1
4585 * 7 7 code2_1
4586 * 8 5 gsp0_1
4587 * 9 7 code1_2
4588 * 10 7 code2_2
4589 * 11 5 gsp0_2
4590 * 12 7 code1_3
4591 * 13 7 code2_3
4592 * 14 5 gsp0_3
4593 * 15 7 code1_4
4594 * 16 7 code2_4
4595 * 17 5 gsp0_4
4596 *
4597 * 18 1 BFI
4598 * 19 1 UFI
4599 * 20 2 SID
4600 * 21 1 TAF
4601 *
4602 *
4603 * REFERENCES: Sub_Clause 4.2 of GSM Recomendation 06.20
4604 *
4605 * KEYWORDS: synthesis, speechdecoder, decoding
4606 * KEYWORDS: codewords, lag, codevectors, gsp0
4607 *
4608 *************************************************************************/
4609
4610 void speechDecoder(Shortword pswParameters[],
4611 Shortword pswDecodedSpeechFrame[])
4612 {
4613
4614 /*_________________________________________________________________________
4615 | |
4616 | Local Static Variables |
4617 |_________________________________________________________________________|
4618 */
4619
4620 static Shortword
4621 *pswLtpStateOut = &pswLtpStateBaseDec[LTP_LEN],
4622 pswSythAsSpace[NP * N_SUB],
4623 pswPFNumAsSpace[NP * N_SUB],
4624 pswPFDenomAsSpace[NP * N_SUB],
4625 *ppswSynthAs[N_SUB] = {
4626 &pswSythAsSpace[0],
4627 &pswSythAsSpace[10],
4628 &pswSythAsSpace[20],
4629 &pswSythAsSpace[30],
4630 },
4631
4632 *ppswPFNumAs[N_SUB] = {
4633 &pswPFNumAsSpace[0],
4634 &pswPFNumAsSpace[10],
4635 &pswPFNumAsSpace[20],
4636 &pswPFNumAsSpace[30],
4637 },
4638 *ppswPFDenomAs[N_SUB] = {
4639 &pswPFDenomAsSpace[0],
4640 &pswPFDenomAsSpace[10],
4641 &pswPFDenomAsSpace[20],
4642 &pswPFDenomAsSpace[30],
4643 };
4644
4645 static ShortwordRom
4646 psrSPFDenomWidenCf[NP] = {
4647 0x6000, 0x4800, 0x3600, 0x2880, 0x1E60,
4648 0x16C8, 0x1116, 0x0CD0, 0x099C, 0x0735,
4649 };
4650
4651
4652 static Longword L_RxPNSeed; /* DTX mode */
4653 static Shortword swRxDtxGsIndex; /* DTX mode */
4654
4655
4656 /*_________________________________________________________________________
4657 | |
4658 | Automatic Variables |
4659 |_________________________________________________________________________|
4660 */
4661
4662 short int i,
4663 j,
4664 siLagCode,
4665 siGsp0Code,
4666 psiVselpCw[2],
4667 siVselpCw,
4668 siNumBits,
4669 siCodeBook;
4670
4671 Shortword pswFrmKs[NP],
4672 pswFrmAs[NP],
4673 pswFrmPFNum[NP],
4674 pswFrmPFDenom[NP],
4675 pswPVec[S_LEN],
4676 ppswVselpEx[2][S_LEN],
4677 pswExcite[S_LEN],
4678 pswPPFExcit[S_LEN],
4679 pswSynthFiltOut[S_LEN],
4680 swR0Index,
4681 swLag,
4682 swSemiBeta,
4683 pswBitArray[MAXBITS];
4684
4685 struct NormSw psnsSqrtRs[N_SUB],
4686 snsRs00,
4687 snsRs11,
4688 snsRs22;
4689
4690
4691 Shortword swMutePermit,
4692 swLevelMean,
4693 swLevelMax, /* error concealment */
4694 swMuteFlag; /* error concealment */
4695
4696
4697 Shortword swTAF,
4698 swSID,
4699 swBfiDtx; /* DTX mode */
4700 Shortword swFrameType; /* DTX mode */
4701
4702 Longword L_RxDTXGs; /* DTX mode */
4703
4704 /*_________________________________________________________________________
4705 | |
4706 | Executable Code |
4707 |_________________________________________________________________________|
4708 */
4709
4710 /* -------------------------------------------------------------------- */
4711 /* do bad frame handling (error concealment) and comfort noise */
4712 /* insertion */
4713 /* -------------------------------------------------------------------- */
4714
4715
4716 /* This flag indicates whether muting is performed in the actual frame */
4717 /* ------------------------------------------------------------------- */
4718 swMuteFlag = 0;
4719
4720
4721 /* This flag indicates whether muting is allowed in the actual frame */
4722 /* ----------------------------------------------------------------- */
4723 swMutePermit = 0;
4724
4725
4726 /* frame classification */
4727 /* -------------------- */
4728
4729 swSID = pswParameters[20];
4730 swTAF = pswParameters[21];
4731
4732 swBfiDtx = pswParameters[18] | pswParameters[19]; /* BFI | UFI */
4733
4734 if ((swSID == 2) && (swBfiDtx == 0))
4735 swFrameType = VALIDSID;
4736 else if ((swSID == 0) && (swBfiDtx == 0))
4737 swFrameType = GOODSPEECH;
4738 else if ((swSID == 0) && (swBfiDtx != 0))
4739 swFrameType = UNUSABLE;
4740 else
4741 swFrameType = INVALIDSID;
4742
4743
4744 /* update of decoder state */
4745 /* ----------------------- */
4746
4747 if (swDecoMode == SPEECH)
4748 {
4749 /* speech decoding mode */
4750 /* -------------------- */
4751
4752 if (swFrameType == VALIDSID)
4753 swDecoMode = CNIFIRSTSID;
4754 else if (swFrameType == INVALIDSID)
4755 swDecoMode = CNIFIRSTSID;
4756 else if (swFrameType == UNUSABLE)
4757 swDecoMode = SPEECH;
4758 else if (swFrameType == GOODSPEECH)
4759 swDecoMode = SPEECH;
4760 }
4761 else
4762 {
4763 /* comfort noise insertion mode */
4764 /* ---------------------------- */
4765
4766 if (swFrameType == VALIDSID)
4767 swDecoMode = CNICONT;
4768 else if (swFrameType == INVALIDSID)
4769 swDecoMode = CNICONT;
4770 else if (swFrameType == UNUSABLE)
4771 swDecoMode = CNIBFI;
4772 else if (swFrameType == GOODSPEECH)
4773 swDecoMode = SPEECH;
4774 }
4775
4776
4777 if (swDecoMode == SPEECH)
4778 {
4779 /* speech decoding mode */
4780 /* -------------------- */
4781
4782 /* Perform parameter concealment, depending on BFI (pswParameters[18]) */
4783 /* or UFI (pswParameters[19]) */
4784 /* ------------------------------------------------------------------- */
4785 para_conceal_speech_decoder(&pswParameters[18],
4786 pswParameters, &swMutePermit);
4787
4788
4789 /* copy the frame rate parameters */
4790 /* ------------------------------ */
4791
4792 swR0Index = pswParameters[0]; /* R0 Index */
4793 pswVq[0] = pswParameters[1]; /* LPC1 */
4794 pswVq[1] = pswParameters[2]; /* LPC2 */
4795 pswVq[2] = pswParameters[3]; /* LPC3 */
4796 swSi = pswParameters[4]; /* INT_LPC */
4797 swVoicingMode = pswParameters[5]; /* MODE */
4798
4799
4800 /* lookup R0 and VQ parameters */
4801 /* --------------------------- */
4802
4803 swR0Dec = psrR0DecTbl[swR0Index * 2]; /* R0 */
4804 lookupVq(pswVq, pswFrmKs);
4805
4806
4807 /* save this frames GS values */
4808 /* -------------------------- */
4809
4810 for (i = 0; i < N_SUB; i++)
4811 {
4812 pL_RxGsHist[swRxGsHistPtr] =
4813 ppLr_gsTable[swVoicingMode][pswParameters[(i * 3) + 8]];
4814 swRxGsHistPtr++;
4815 if (swRxGsHistPtr > ((OVERHANG - 1) * N_SUB) - 1)
4816 swRxGsHistPtr = 0;
4817 }
4818
4819
4820 /* DTX variables */
4821 /* ------------- */
4822
4823 swDtxBfiCnt = 0;
4824 swDtxMuting = 0;
4825 swRxDTXState = CNINTPER - 1;
4826
4827 }
4828 else
4829 {
4830 /* comfort noise insertion mode */
4831 /*----------------------------- */
4832
4833 /* copy the frame rate parameters */
4834 /* ------------------------------ */
4835
4836 swR0Index = pswParameters[0]; /* R0 Index */
4837 pswVq[0] = pswParameters[1]; /* LPC1 */
4838 pswVq[1] = pswParameters[2]; /* LPC2 */
4839 pswVq[2] = pswParameters[3]; /* LPC3 */
4840 swSi = 1; /* INT_LPC */
4841 swVoicingMode = 0; /* MODE */
4842
4843
4844 /* bad frame handling in comfort noise insertion mode */
4845 /* -------------------------------------------------- */
4846
4847 if (swDecoMode == CNIFIRSTSID) /* first SID frame */
4848 {
4849 swDtxBfiCnt = 0;
4850 swDtxMuting = 0;
4851 swRxDTXState = CNINTPER - 1;
4852
4853 if (swFrameType == VALIDSID) /* valid SID frame */
4854 {
4855 swR0NewCN = psrR0DecTbl[swR0Index * 2];
4856 lookupVq(pswVq, pswFrmKs);
4857 }
4858 else if (swFrameType == INVALIDSID) /* invalid SID frame */
4859 {
4860 swR0NewCN = psrR0DecTbl[swOldR0IndexDec * 2];
4861 swR0Index = swOldR0IndexDec;
4862 for (i = 0; i < NP; i++)
4863 pswFrmKs[i] = pswOldFrmKsDec[i];
4864 }
4865
4866 }
4867 else if (swDecoMode == CNICONT) /* SID frame detected, but */
4868 { /* not the first SID */
4869 swDtxBfiCnt = 0;
4870 swDtxMuting = 0;
4871
4872 if (swFrameType == VALIDSID) /* valid SID frame */
4873 {
4874 swRxDTXState = 0;
4875 swR0NewCN = psrR0DecTbl[swR0Index * 2];
4876 lookupVq(pswVq, pswFrmKs);
4877 }
4878 else if (swFrameType == INVALIDSID) /* invalid SID frame */
4879 {
4880 if (swRxDTXState < (CNINTPER - 1))
4881 swRxDTXState = add(swRxDTXState, 1);
4882 swR0Index = swOldR0IndexDec;
4883 }
4884
4885 }
4886 else if (swDecoMode == CNIBFI) /* bad frame received in */
4887 { /* CNI mode */
4888 if (swRxDTXState < (CNINTPER - 1))
4889 swRxDTXState = add(swRxDTXState, 1);
4890 swR0Index = swOldR0IndexDec;
4891
4892 if (swDtxMuting == 1)
4893 {
4894 swOldR0IndexDec = sub(swOldR0IndexDec, 2); /* attenuate
4895 * by 4 dB */
4896 if (swOldR0IndexDec < 0)
4897 swOldR0IndexDec = 0;
4898
4899 swR0Index = swOldR0IndexDec;
4900
4901 swR0NewCN = psrR0DecTbl[swOldR0IndexDec * 2]; /* R0 */
4902
4903 }
4904
4905 swDtxBfiCnt = add(swDtxBfiCnt, 1);
4906 if ((swTAF == 1) && (swDtxBfiCnt >= (2 * CNINTPER + 1))) /* 25 */
4907 swDtxMuting = 1;
4908
4909 }
4910
4911
4912 if (swDecoMode == CNIFIRSTSID)
4913 {
4914
4915 /* the first SID frame is received */
4916 /* ------------------------------- */
4917
4918 /* initialize the decoders pn-generator */
4919 /* ------------------------------------ */
4920
4921 L_RxPNSeed = PN_INIT_SEED;
4922
4923
4924 /* using the stored rx history, generate averaged GS */
4925 /* ------------------------------------------------- */
4926
4927 avgGsHistQntz(pL_RxGsHist, &L_RxDTXGs);
4928 swRxDtxGsIndex = gsQuant(L_RxDTXGs, 0);
4929
4930 }
4931
4932
4933 /* Replace the "transmitted" subframe parameters with */
4934 /* synthetic ones */
4935 /* -------------------------------------------------- */
4936
4937 for (i = 0; i < 4; i++)
4938 {
4939 /* initialize the GSP0 parameter */
4940 pswParameters[(i * 3) + 8] = swRxDtxGsIndex;
4941
4942 /* CODE1 */
4943 pswParameters[(i * 3) + 6] = getPnBits(7, &L_RxPNSeed);
4944 /* CODE2 */
4945 pswParameters[(i * 3) + 7] = getPnBits(7, &L_RxPNSeed);
4946 }
4947
4948
4949 /* Interpolation of CN parameters */
4950 /* ------------------------------ */
4951
4952 rxInterpR0Lpc(pswOldFrmKsDec, pswFrmKs, swRxDTXState,
4953 swDecoMode, swFrameType);
4954
4955 }
4956
4957
4958 /* ------------------- */
4959 /* do frame processing */
4960 /* ------------------- */
4961
4962 /* generate the direct form coefs */
4963 /* ------------------------------ */
4964
4965 if (!rcToADp(ASCALE, pswFrmKs, pswFrmAs))
4966 {
4967
4968 /* widen direct form coefficients using the widening coefs */
4969 /* ------------------------------------------------------- */
4970
4971 for (i = 0; i < NP; i++)
4972 {
4973 pswFrmPFDenom[i] = mult_r(pswFrmAs[i], psrSPFDenomWidenCf[i]);
4974 }
4975
4976 a_sst(ASHIFT, ASCALE, pswFrmPFDenom, pswFrmPFNum);
4977 }
4978 else
4979 {
4980
4981
4982 for (i = 0; i < NP; i++)
4983 {
4984 pswFrmKs[i] = pswOldFrmKsDec[i];
4985 pswFrmAs[i] = pswOldFrmAsDec[i];
4986 pswFrmPFDenom[i] = pswOldFrmPFDenom[i];
4987 pswFrmPFNum[i] = pswOldFrmPFNum[i];
4988 }
4989 }
4990
4991 /* interpolate, or otherwise get sfrm reflection coefs */
4992 /* --------------------------------------------------- */
4993
4994 getSfrmLpc(swSi, swOldR0Dec, swR0Dec, pswOldFrmKsDec, pswOldFrmAsDec,
4995 pswOldFrmPFNum, pswOldFrmPFDenom, pswFrmKs, pswFrmAs,
4996 pswFrmPFNum, pswFrmPFDenom, psnsSqrtRs, ppswSynthAs,
4997 ppswPFNumAs, ppswPFDenomAs);
4998
4999 /* calculate shift for spectral postfilter */
5000 /* --------------------------------------- */
5001
5002 swEngyRShift = r0BasedEnergyShft(swR0Index);
5003
5004
5005 /* ----------------------- */
5006 /* do sub-frame processing */
5007 /* ----------------------- */
5008
5009 for (giSfrmCnt = 0; giSfrmCnt < 4; giSfrmCnt++)
5010 {
5011
5012 /* copy this sub-frame's parameters */
5013 /* -------------------------------- */
5014
5015 if (sub(swVoicingMode, 0) == 0)
5016 { /* unvoiced */
5017 psiVselpCw[0] = pswParameters[(giSfrmCnt * 3) + 6]; /* CODE_1 */
5018 psiVselpCw[1] = pswParameters[(giSfrmCnt * 3) + 7]; /* CODE_2 */
5019 siGsp0Code = pswParameters[(giSfrmCnt * 3) + 8]; /* GSP0 */
5020 }
5021 else
5022 { /* voiced */
5023 siLagCode = pswParameters[(giSfrmCnt * 3) + 6]; /* LAG */
5024 psiVselpCw[0] = pswParameters[(giSfrmCnt * 3) + 7]; /* CODE */
5025 siGsp0Code = pswParameters[(giSfrmCnt * 3) + 8]; /* GSP0 */
5026 }
5027
5028 /* for voiced mode, reconstruct the pitch vector */
5029 /* --------------------------------------------- */
5030
5031 if (swVoicingMode)
5032 {
5033
5034 /* convert delta lag to lag and convert to fractional lag */
5035 /* ------------------------------------------------------ */
5036
5037 swLag = lagDecode(siLagCode);
5038
5039 /* state followed by out */
5040 /* --------------------- */
5041
5042 fp_ex(swLag, pswLtpStateOut);
5043
5044 /* extract a piece of pswLtpStateOut into newly named vector pswPVec */
5045 /* ----------------------------------------------------------------- */
5046
5047 for (i = 0; i < S_LEN; i++)
5048 {
5049 pswPVec[i] = pswLtpStateOut[i];
5050 }
5051 }
5052
5053 /* for unvoiced, do not reconstruct a pitch vector */
5054 /* ----------------------------------------------- */
5055
5056 else
5057 {
5058 swLag = 0; /* indicates invalid lag
5059 * and unvoiced */
5060 }
5061
5062 /* now work on the VSELP codebook excitation output */
5063 /* x_vec, x_a_vec here named ppswVselpEx[0] and [1] */
5064 /* ------------------------------------------------ */
5065
5066 if (swVoicingMode)
5067 { /* voiced */
5068
5069 siNumBits = C_BITS_V;
5070 siVselpCw = psiVselpCw[0];
5071
5072 b_con(siVselpCw, siNumBits, pswBitArray);
5073
5074 v_con(pppsrVcdCodeVec[0][0], ppswVselpEx[0], pswBitArray, siNumBits);
5075 }
5076
5077 else
5078 { /* unvoiced */
5079
5080 siNumBits = C_BITS_UV;
5081
5082 for (siCodeBook = 0; siCodeBook < 2; siCodeBook++)
5083 {
5084
5085 siVselpCw = psiVselpCw[siCodeBook];
5086
5087 b_con(siVselpCw, siNumBits, (Shortword *) pswBitArray);
5088
5089 v_con(pppsrUvCodeVec[siCodeBook][0], ppswVselpEx[siCodeBook],
5090 pswBitArray, siNumBits);
5091 }
5092 }
5093
5094 /* all excitation vectors have been created: ppswVselpEx and pswPVec */
5095 /* if voiced compute rs00 and rs11; if unvoiced cmpute rs11 and rs22 */
5096 /* ------------------------------------------------------------------ */
5097
5098 if (swLag)
5099 {
5100 rs_rr(pswPVec, psnsSqrtRs[giSfrmCnt], &snsRs00);
5101 }
5102
5103 rs_rrNs(ppswVselpEx[0], psnsSqrtRs[giSfrmCnt], &snsRs11);
5104
5105 if (!swVoicingMode)
5106 {
5107 rs_rrNs(ppswVselpEx[1], psnsSqrtRs[giSfrmCnt], &snsRs22);
5108 }
5109
5110 /* now implement synthesis - combine the excitations */
5111 /* ------------------------------------------------- */
5112
5113 if (swVoicingMode)
5114 { /* voiced */
5115
5116 /* scale pitch and codebook excitations and get beta */
5117 /* ------------------------------------------------- */
5118 swSemiBeta = scaleExcite(pswPVec,
5119 pppsrGsp0[swVoicingMode][siGsp0Code][0],
5120 snsRs00, pswPVec);
5121 scaleExcite(ppswVselpEx[0],
5122 pppsrGsp0[swVoicingMode][siGsp0Code][1],
5123 snsRs11, ppswVselpEx[0]);
5124
5125 /* combine the two scaled excitations */
5126 /* ---------------------------------- */
5127 for (i = 0; i < S_LEN; i++)
5128 {
5129 pswExcite[i] = add(pswPVec[i], ppswVselpEx[0][i]);
5130 }
5131 }
5132 else
5133 { /* unvoiced */
5134
5135 /* scale codebook excitations and set beta to 0 as not applicable */
5136 /* -------------------------------------------------------------- */
5137 swSemiBeta = 0;
5138 scaleExcite(ppswVselpEx[0],
5139 pppsrGsp0[swVoicingMode][siGsp0Code][0],
5140 snsRs11, ppswVselpEx[0]);
5141 scaleExcite(ppswVselpEx[1],
5142 pppsrGsp0[swVoicingMode][siGsp0Code][1],
5143 snsRs22, ppswVselpEx[1]);
5144
5145 /* combine the two scaled excitations */
5146 /* ---------------------------------- */
5147 for (i = 0; i < S_LEN; i++)
5148 {
5149 pswExcite[i] = add(ppswVselpEx[1][i], ppswVselpEx[0][i]);
5150 }
5151 }
5152
5153 /* now update the pitch state using the combined/scaled excitation */
5154 /* --------------------------------------------------------------- */
5155
5156 for (i = 0; i < LTP_LEN; i++)
5157 {
5158 pswLtpStateBaseDec[i] = pswLtpStateBaseDec[i + S_LEN];
5159 }
5160
5161 /* add the current sub-frames data to the state */
5162 /* -------------------------------------------- */
5163
5164 for (i = -S_LEN, j = 0; j < S_LEN; i++, j++)
5165 {
5166 pswLtpStateOut[i] = pswExcite[j];/* add new frame at t = -S_LEN */
5167 }
5168
5169 /* given the excitation perform pitch prefiltering */
5170 /* ----------------------------------------------- */
5171
5172 pitchPreFilt(pswExcite, siGsp0Code, swLag,
5173 swVoicingMode, swSemiBeta, psnsSqrtRs[giSfrmCnt],
5174 pswPPFExcit, pswPPreState);
5175
5176
5177 /* Concealment on subframe signal level: */
5178 /* ------------------------------------- */
5179 level_estimator(0, &swLevelMean, &swLevelMax,
5180 &pswDecodedSpeechFrame[giSfrmCnt * S_LEN]);
5181
5182 signal_conceal_sub(pswPPFExcit, ppswSynthAs[giSfrmCnt], pswSynthFiltState,
5183 &pswLtpStateOut[-S_LEN], &pswPPreState[LTP_LEN - S_LEN],
5184 swLevelMean, swLevelMax,
5185 pswParameters[19], swMuteFlagOld,
5186 &swMuteFlag, swMutePermit);
5187
5188
5189 /* synthesize the speech through the synthesis filter */
5190 /* -------------------------------------------------- */
5191
5192 lpcIir(pswPPFExcit, ppswSynthAs[giSfrmCnt], pswSynthFiltState,
5193 pswSynthFiltOut);
5194
5195 /* pass reconstructed speech through adaptive spectral postfilter */
5196 /* -------------------------------------------------------------- */
5197
5198 spectralPostFilter(pswSynthFiltOut, ppswPFNumAs[giSfrmCnt],
5199 ppswPFDenomAs[giSfrmCnt],
5200 &pswDecodedSpeechFrame[giSfrmCnt * S_LEN]);
5201
5202 level_estimator(1, &swLevelMean, &swLevelMax,
5203 &pswDecodedSpeechFrame[giSfrmCnt * S_LEN]);
5204
5205 }
5206
5207 /* Save muting information for next frame */
5208 /* -------------------------------------- */
5209 swMuteFlagOld = swMuteFlag;
5210
5211 /* end of frame processing - save this frame's frame energy, */
5212 /* reflection coefs, direct form coefs, and post filter coefs */
5213 /* ---------------------------------------------------------- */
5214
5215 swOldR0Dec = swR0Dec;
5216 swOldR0IndexDec = swR0Index; /* DTX mode */
5217
5218 for (i = 0; i < NP; i++)
5219 {
5220 pswOldFrmKsDec[i] = pswFrmKs[i];
5221 pswOldFrmAsDec[i] = pswFrmAs[i];
5222 pswOldFrmPFNum[i] = pswFrmPFNum[i];
5223 pswOldFrmPFDenom[i] = pswFrmPFDenom[i];
5224 }
5225 }
5226
5227
5228 /***************************************************************************
5229 *
5230 * FUNCTION NAME: sqroot
5231 *
5232 * PURPOSE:
5233 *
5234 * The purpose of this function is to perform a single precision square
5235 * root function on a Longword
5236 *
5237 * INPUTS:
5238 *
5239 * L_SqrtIn
5240 * input to square root function
5241 *
5242 * OUTPUTS:
5243 *
5244 * none
5245 *
5246 * RETURN VALUE:
5247 *
5248 * swSqrtOut
5249 * output to square root function
5250 *
5251 * DESCRIPTION:
5252 *
5253 * Input assumed to be normalized
5254 *
5255 * The algorithm is based around a six term Taylor expansion :
5256 *
5257 * y^0.5 = (1+x)^0.5
5258 * ~= 1 + (x/2) - 0.5*((x/2)^2) + 0.5*((x/2)^3)
5259 * - 0.625*((x/2)^4) + 0.875*((x/2)^5)
5260 *
5261 * Max error less than 0.08 % for normalized input ( 0.5 <= x < 1 )
5262 *
5263 * REFERENCES: Sub-clause 4.1.4.1, 4.1.7, 4.1.11.1, 4.2.1,
5264 * 4.2.2, 4.2.3 and 4.2.4 of GSM Recomendation 06.20
5265 *
5266 * KEYWORDS: sqrt, squareroot, sqrt016
5267 *
5268 *************************************************************************/
5269
5270 Shortword sqroot(Longword L_SqrtIn)
5271 {
5272
5273 /*_________________________________________________________________________
5274 | |
5275 | Local Constants |
5276 |_________________________________________________________________________|
5277 */
5278
5279 #define PLUS_HALF 0x40000000L /* 0.5 */
5280 #define MINUS_ONE 0x80000000L /* -1 */
5281 #define TERM5_MULTIPLER 0x5000 /* 0.625 */
5282 #define TERM6_MULTIPLER 0x7000 /* 0.875 */
5283
5284 /*_________________________________________________________________________
5285 | |
5286 | Automatic Variables |
5287 |_________________________________________________________________________|
5288 */
5289
5290 Longword L_Temp0,
5291 L_Temp1;
5292
5293 Shortword swTemp,
5294 swTemp2,
5295 swTemp3,
5296 swTemp4,
5297 swSqrtOut;
5298
5299 /*_________________________________________________________________________
5300 | |
5301 | Executable Code |
5302 |_________________________________________________________________________|
5303 */
5304
5305 /* determine 2nd term x/2 = (y-1)/2 */
5306 /* -------------------------------- */
5307
5308 L_Temp1 = L_shr(L_SqrtIn, 1); /* L_Temp1 = y/2 */
5309 L_Temp1 = L_sub(L_Temp1, PLUS_HALF); /* L_Temp1 = (y-1)/2 */
5310 swTemp = extract_h(L_Temp1); /* swTemp = x/2 */
5311
5312 /* add contribution of 2nd term */
5313 /* ---------------------------- */
5314
5315 L_Temp1 = L_sub(L_Temp1, MINUS_ONE); /* L_Temp1 = 1 + x/2 */
5316
5317 /* determine 3rd term */
5318 /* ------------------ */
5319
5320 L_Temp0 = L_msu(0L, swTemp, swTemp); /* L_Temp0 = -(x/2)^2 */
5321 swTemp2 = extract_h(L_Temp0); /* swTemp2 = -(x/2)^2 */
5322 L_Temp0 = L_shr(L_Temp0, 1); /* L_Temp0 = -0.5*(x/2)^2 */
5323
5324 /* add contribution of 3rd term */
5325 /* ---------------------------- */
5326
5327 L_Temp0 = L_add(L_Temp1, L_Temp0); /* L_Temp0 = 1 + x/2 - 0.5*(x/2)^2 */
5328
5329 /* determine 4rd term */
5330 /* ------------------ */
5331
5332 L_Temp1 = L_msu(0L, swTemp, swTemp2);/* L_Temp1 = (x/2)^3 */
5333 swTemp3 = extract_h(L_Temp1); /* swTemp3 = (x/2)^3 */
5334 L_Temp1 = L_shr(L_Temp1, 1); /* L_Temp1 = 0.5*(x/2)^3 */
5335
5336 /* add contribution of 4rd term */
5337 /* ---------------------------- */
5338
5339 /* L_Temp1 = 1 + x/2 - 0.5*(x/2)^2 + 0.5*(x/2)^3 */
5340
5341 L_Temp1 = L_add(L_Temp0, L_Temp1);
5342
5343 /* determine partial 5th term */
5344 /* -------------------------- */
5345
5346 L_Temp0 = L_mult(swTemp, swTemp3); /* L_Temp0 = (x/2)^4 */
5347 swTemp4 = round(L_Temp0); /* swTemp4 = (x/2)^4 */
5348
5349 /* determine partial 6th term */
5350 /* -------------------------- */
5351
5352 L_Temp0 = L_msu(0L, swTemp2, swTemp3); /* L_Temp0 = (x/2)^5 */
5353 swTemp2 = round(L_Temp0); /* swTemp2 = (x/2)^5 */
5354
5355 /* determine 5th term and add its contribution */
5356 /* ------------------------------------------- */
5357
5358 /* L_Temp0 = -0.625*(x/2)^4 */
5359
5360 L_Temp0 = L_msu(0L, TERM5_MULTIPLER, swTemp4);
5361
5362 /* L_Temp1 = 1 + x/2 - 0.5*(x/2)^2 + 0.5*(x/2)^3 - 0.625*(x/2)^4 */
5363
5364 L_Temp1 = L_add(L_Temp0, L_Temp1);
5365
5366 /* determine 6th term and add its contribution */
5367 /* ------------------------------------------- */
5368
5369 /* swSqrtOut = 1 + x/2 - 0.5*(x/2)^2 + 0.5*(x/2)^3 */
5370 /* - 0.625*(x/2)^4 + 0.875*(x/2)^5 */
5371
5372 swSqrtOut = mac_r(L_Temp1, TERM6_MULTIPLER, swTemp2);
5373
5374 /* return output */
5375 /* ------------- */
5376
5377 return (swSqrtOut);
5378 }
5379
5380 /***************************************************************************
5381 *
5382 * FUNCTION NAME: v_con
5383 *
5384 * PURPOSE:
5385 *
5386 * This subroutine constructs a codebook excitation
5387 * vector from basis vectors
5388 *
5389 * INPUTS:
5390 *
5391 * pswBVects[0:siNumBVctrs*S_LEN-1]
5392 *
5393 * Array containing a set of basis vectors.
5394 *
5395 * pswBitArray[0:siNumBVctrs-1]
5396 *
5397 * Bit array dictating the polarity of the
5398 * basis vectors in the output vector.
5399 * Each element of the bit array is either -0.5 or +0.5
5400 *
5401 * siNumBVctrs
5402 * Number of bits in codeword
5403 *
5404 * OUTPUTS:
5405 *
5406 * pswOutVect[0:39]
5407 *
5408 * Array containing the contructed output vector
5409 *
5410 * RETURN VALUE:
5411 *
5412 * none
5413 *
5414 * DESCRIPTION:
5415 *
5416 * The array pswBitArray is used to multiply each of the siNumBVctrs
5417 * basis vectors. The input pswBitArray[] is an array whose
5418 * elements are +/-0.5. These multiply the VSELP basis vectors and
5419 * when summed produce a VSELP codevector. b_con() is the function
5420 * used to translate a VSELP codeword into pswBitArray[].
5421 *
5422 *
5423 * REFERENCES: Sub-clause 4.1.10 and 4.2.1 of GSM Recomendation 06.20
5424 *
5425 * KEYWORDS: v_con, codeword, reconstruct, basis vector, excitation
5426 *
5427 *************************************************************************/
5428
5429 void v_con(Shortword pswBVects[], Shortword pswOutVect[],
5430 Shortword pswBitArray[], short int siNumBVctrs)
5431 {
5432
5433 /*_________________________________________________________________________
5434 | |
5435 | Automatic Variables |
5436 |_________________________________________________________________________|
5437 */
5438
5439 Longword L_Temp;
5440
5441 short int siSampleCnt,
5442 siCVectCnt;
5443
5444 /*_________________________________________________________________________
5445 | |
5446 | Executable Code |
5447 |_________________________________________________________________________|
5448 */
5449
5450 /* Sample loop */
5451 /*--------------*/
5452 for (siSampleCnt = 0; siSampleCnt < S_LEN; siSampleCnt++)
5453 {
5454
5455 /* First element of output vector */
5456 L_Temp = L_mult(pswBitArray[0], pswBVects[0 * S_LEN + siSampleCnt]);
5457
5458 /* Construct output vector */
5459 /*-------------------------*/
5460 for (siCVectCnt = 1; siCVectCnt < siNumBVctrs; siCVectCnt++)
5461 {
5462 L_Temp = L_mac(L_Temp, pswBitArray[siCVectCnt],
5463 pswBVects[siCVectCnt * S_LEN + siSampleCnt]);
5464 }
5465
5466 /* store the output vector sample */
5467 /*--------------------------------*/
5468 L_Temp = L_shl(L_Temp, 1);
5469 pswOutVect[siSampleCnt] = extract_h(L_Temp);
5470 }
5471 }