1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 /****************************************************************************************
19 Portions of this file are derived from the following 3GPP standard:
20 
21     3GPP TS 26.073
22     ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23     Available from http://www.3gpp.org
24 
25 (C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
26 Permission to distribute, modify and use this file under the standard license
27 terms listed above has been obtained from the copyright holder.
28 ****************************************************************************************/
29 /*
30 
31  Pathname: ./audio/gsm-amr/c/src/q_plsf_3.c
32  Funtions: Vq_subvec4
33            Test_Vq_subvec4
34            Vq_subvec3
35            Test_Vq_subvec3
36            Q_plsf_3
37 
38 ------------------------------------------------------------------------------
39  REVISION HISTORY
40 
41  Description: Updated template used to PV coding template. First attempt at
42           optimizing C code.
43 
44  Description: Updated modules per Phase 2/3 review comments. Updated
45           Vq_subvec3 pseudo-code to reflect the new restructured code.
46 
47  Description: Added setting of Overflow flag in inlined code.
48 
49  Description: Synchronized file with UMTS version 3.2.0. Updated coding
50               template. Removed unnecessary include files.
51 
52  Description: Replaced basic_op.h with the header file of the math functions
53               used in the file.
54 
55  Description: Made the following changes per comments from Phase 2/3 review:
56               1. Fixed typecasting issue with TI C compiler.
57               2. Optimized IF stament in Vq_subvec3() function.
58               3. Updated copyright year.
59 
60  Description: Removed redundancy in the Vq_subvec4 function.
61 
62  Description: Updated to accept new parameter, Flag *pOverflow.
63 
64  Description: Per review comments, added pOverflow flag description
65  to the input/outputs section.
66 
67  Description: Corrected missed Overflow global variables -- changed to
68  proper pOverflow.
69 
70  Description: Optimized all functions to further reduce clock cycle usage.
71               Updated copyright year.
72 
73  Description: Added left shift by 1 in line 1050 of Q_plsf_3().
74 
75  Description:  Replaced OSCL mem type functions and eliminated include
76                files that now are chosen by OSCL definitions
77 
78  Description:  Replaced "int" and/or "char" with OSCL defined types.
79 
80  Description: Added #ifdef __cplusplus around extern'ed table.
81 
82  Who:                           Date:
83  Description:
84 
85 ------------------------------------------------------------------------------
86  MODULE DESCRIPTION
87 
88  This file contains the functions that perform the quantization of LSF
89  parameters with first order MA prediction and split by 3 vector
90  quantization (split-VQ).
91 
92 ------------------------------------------------------------------------------
93 */
94 
95 /*----------------------------------------------------------------------------
96 ; INCLUDES
97 ----------------------------------------------------------------------------*/
98 
99 #include <string.h>
100 
101 #include "q_plsf.h"
102 #include "typedef.h"
103 #include "lsp_lsf.h"
104 #include "reorder.h"
105 #include "lsfwt.h"
106 
107 /*--------------------------------------------------------------------------*/
108 #ifdef __cplusplus
109 extern "C"
110 {
111 #endif
112 
113     /*----------------------------------------------------------------------------
114     ; MACROS
115     ; Define module specific macros here
116     ----------------------------------------------------------------------------*/
117 
118     /*----------------------------------------------------------------------------
119     ; DEFINES
120     ; Include all pre-processor statements here. Include conditional
121     ; compile variables also.
122     ----------------------------------------------------------------------------*/
123 #define PAST_RQ_INIT_SIZE 8
124 
125     /*----------------------------------------------------------------------------
126     ; LOCAL FUNCTION DEFINITIONS
127     ; Function Prototype declaration
128     ----------------------------------------------------------------------------*/
129 
130     /*----------------------------------------------------------------------------
131     ; LOCAL VARIABLE DEFINITIONS
132     ; Variable declaration - defined here and used outside this module
133     ----------------------------------------------------------------------------*/
134 
135     /*----------------------------------------------------------------------------
136     ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
137     ; Declare variables used in this module but defined elsewhere
138     ----------------------------------------------------------------------------*/
139     /* Codebooks of LSF prediction residual */
140     extern const Word16 mean_lsf_3[];
141 
142     extern const Word16 pred_fac_3[];
143 
144     extern const Word16 dico1_lsf_3[];
145     extern const Word16 dico2_lsf_3[];
146     extern const Word16 dico3_lsf_3[];
147 
148     extern const Word16 mr515_3_lsf[];
149     extern const Word16 mr795_1_lsf[];
150 
151     extern const Word16 past_rq_init[];
152 
153     /*--------------------------------------------------------------------------*/
154 #ifdef __cplusplus
155 }
156 #endif
157 
158 /*
159 ------------------------------------------------------------------------------
160  FUNCTION NAME: Vq_subvec4
161 ------------------------------------------------------------------------------
162  INPUT AND OUTPUT DEFINITIONS
163 
164  Inputs:
165     lsf_r1 = pointer to the first LSF residual vector (Q15) (Word16)
166     dico = pointer to the quantization codebook (Q15) (const Word16)
167     wf1 = pointer to the first LSF weighting factor (Q13) (Word16)
168     dico_size = size of quantization codebook (Q0) (Word16)
169 
170  Outputs:
171     buffer pointed to by lsf_r1 contains the selected vector
172     pOverflow -- pointer to Flag -- Flag set when overflow occurs
173 
174  Returns:
175     index = quantization index (Q0) (Word16)
176 
177  Global Variables Used:
178     None
179 
180  Local Variables Needed:
181     None
182 
183 ------------------------------------------------------------------------------
184  FUNCTION DESCRIPTION
185 
186  This function performs the quantization of a 4-dimensional subvector.
187 
188 ------------------------------------------------------------------------------
189  REQUIREMENTS
190 
191  None
192 
193 ------------------------------------------------------------------------------
194  REFERENCES
195 
196  q_plsf_3.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
197 
198 ------------------------------------------------------------------------------
199  PSEUDO-CODE
200 
201 static Word16
202 Vq_subvec4(             // o: quantization index,            Q0
203     Word16 * lsf_r1,    // i: 1st LSF residual vector,       Q15
204     Word16 * dico,      // i: quantization codebook,         Q15
205     Word16 * wf1,       // i: 1st LSF weighting factors,     Q13
206     Word16 dico_size)   // i: size of quantization codebook, Q0
207 {
208     Word16 i, index = 0;
209     Word16 *p_dico, temp;
210     Word32 dist_min, dist;
211 
212     dist_min = MAX_32;
213     p_dico = dico;
214 
215     for (i = 0; i < dico_size; i++)
216     {
217         temp = sub (lsf_r1[0], *p_dico++);
218         temp = mult (wf1[0], temp);
219         dist = L_mult (temp, temp);
220 
221         temp = sub (lsf_r1[1], *p_dico++);
222         temp = mult (wf1[1], temp);
223         dist = L_mac (dist, temp, temp);
224 
225         temp = sub (lsf_r1[2], *p_dico++);
226         temp = mult (wf1[2], temp);
227         dist = L_mac (dist, temp, temp);
228 
229         temp = sub (lsf_r1[3], *p_dico++);
230         temp = mult (wf1[3], temp);
231         dist = L_mac (dist, temp, temp);
232 
233 
234         if (L_sub (dist, dist_min) < (Word32) 0)
235         {
236             dist_min = dist;
237             index = i;
238         }
239     }
240 
241     // Reading the selected vector
242 
243     p_dico = &dico[shl (index, 2)];
244     lsf_r1[0] = *p_dico++;
245     lsf_r1[1] = *p_dico++;
246     lsf_r1[2] = *p_dico++;
247     lsf_r1[3] = *p_dico;
248 
249     return index;
250 
251 }
252 
253 ------------------------------------------------------------------------------
254  RESOURCES USED [optional]
255 
256  When the code is written for a specific target processor the
257  the resources used should be documented below.
258 
259  HEAP MEMORY USED: x bytes
260 
261  STACK MEMORY USED: x bytes
262 
263  CLOCK CYCLES: (cycle count equation for this function) + (variable
264                 used to represent cycle count for each subroutine
265                 called)
266      where: (cycle count variable) = cycle count for [subroutine
267                                      name]
268 
269 ------------------------------------------------------------------------------
270  CAUTION [optional]
271  [State any special notes, constraints or cautions for users of this function]
272 
273 ------------------------------------------------------------------------------
274 */
275 
Vq_subvec4(Word16 * lsf_r1,const Word16 * dico,Word16 * wf1,Word16 dico_size,Flag * pOverflow)276 static Word16 Vq_subvec4( /* o: quantization index,            Q0  */
277     Word16 * lsf_r1,      /* i: 1st LSF residual vector,       Q15 */
278     const Word16 * dico,  /* i: quantization codebook,         Q15 */
279     Word16 * wf1,         /* i: 1st LSF weighting factors,     Q13 */
280     Word16 dico_size,     /* i: size of quantization codebook, Q0  */
281     Flag  *pOverflow      /* o : Flag set when overflow occurs     */
282 )
283 {
284     Word16 i;
285     Word16 temp;
286     const Word16 *p_dico;
287     Word16 index = 0;
288     Word32 dist_min;
289     Word32 dist;
290 
291     Word16 lsf_r1_0;
292     Word16 lsf_r1_1;
293     Word16 lsf_r1_2;
294     Word16 lsf_r1_3;
295 
296     Word16 wf1_0;
297     Word16 wf1_1;
298     Word16 wf1_2;
299     Word16 wf1_3;
300 
301     OSCL_UNUSED_ARG(pOverflow);
302 
303     dist_min = MAX_32;
304     p_dico = dico;
305 
306     lsf_r1_0 = lsf_r1[0];
307     lsf_r1_1 = lsf_r1[1];
308     lsf_r1_2 = lsf_r1[2];
309     lsf_r1_3 = lsf_r1[3];
310 
311     wf1_0 = wf1[0];
312     wf1_1 = wf1[1];
313     wf1_2 = wf1[2];
314     wf1_3 = wf1[3];
315 
316     for (i = 0; i < dico_size; i++)
317     {
318         temp = lsf_r1_0 - (*p_dico++);
319         temp = (Word16)((((Word32) wf1_0) * temp) >> 15);
320         dist = ((Word32) temp) * temp;
321 
322         temp = lsf_r1_1 - (*p_dico++);
323         temp = (Word16)((((Word32) wf1_1) * temp) >> 15);
324         dist += ((Word32) temp) * temp;
325 
326         temp = lsf_r1_2 - (*p_dico++);
327         temp = (Word16)((((Word32) wf1_2) * temp) >> 15);
328         dist += ((Word32) temp) * temp;
329 
330         temp = lsf_r1_3 - (*p_dico++);
331         temp = (Word16)((((Word32) wf1_3) * temp) >> 15);
332         dist += ((Word32) temp) * temp;
333 
334         if (dist < dist_min)
335         {
336             dist_min = dist;
337             index = i;
338         }
339     }
340 
341     /* Reading the selected vector */
342 
343     p_dico = dico + (index << 2);
344     *lsf_r1++ = *p_dico++;
345     *lsf_r1++ = *p_dico++;
346     *lsf_r1++ = *p_dico++;
347     *lsf_r1 = *p_dico;
348 
349     return(index);
350 
351 }
352 
353 /****************************************************************************/
354 
355 
356 /*
357 ------------------------------------------------------------------------------
358  FUNCTION NAME: Test_Vq_subvec4
359 ------------------------------------------------------------------------------
360  INPUT AND OUTPUT DEFINITIONS
361 
362  Inputs:
363     lsf_r1 = pointer to the first LSF residual vector (Q15) (Word16)
364     dico = pointer to the quantization codebook (Q15) (const Word16)
365     wf1 = pointer to the first LSF weighting factor (Q13) (Word16)
366     dico_size = size of quantization codebook (Q0) (Word16)
367 
368  Outputs:
369     buffer pointed to by lsf_r1 contains the selected vector
370     pOverflow -- pointer to Flag -- Flag set when overflow occurs
371 
372  Returns:
373     index = quantization index (Q0) (Word16)
374 
375  Global Variables Used:
376     None
377 
378  Local Variables Needed:
379     None
380 
381 ------------------------------------------------------------------------------
382  FUNCTION DESCRIPTION
383 
384  This function calls the static function Vq_subvec4. It is used for testing
385  purposes only
386 
387 ------------------------------------------------------------------------------
388  REQUIREMENTS
389 
390  None
391 
392 ------------------------------------------------------------------------------
393  REFERENCES
394 
395  None
396 
397 ------------------------------------------------------------------------------
398  PSEUDO-CODE
399 
400 
401  CALL Vq_subvec4(lsf_r1 = lsf_r1
402                  dico = dico
403                  wf1 = wf1
404                  dico_size = dico_size)
405    MODIFYING(nothing)
406    RETURNING(index = tst_index4)
407 
408 ------------------------------------------------------------------------------
409  RESOURCES USED [optional]
410 
411  When the code is written for a specific target processor the
412  the resources used should be documented below.
413 
414  HEAP MEMORY USED: x bytes
415 
416  STACK MEMORY USED: x bytes
417 
418  CLOCK CYCLES: (cycle count equation for this function) + (variable
419                 used to represent cycle count for each subroutine
420                 called)
421      where: (cycle count variable) = cycle count for [subroutine
422                                      name]
423 
424 ------------------------------------------------------------------------------
425  CAUTION [optional]
426  [State any special notes, constraints or cautions for users of this function]
427 
428 ------------------------------------------------------------------------------
429 */
430 
Test_Vq_subvec4(Word16 * lsf_r1,const Word16 * dico,Word16 * wf1,Word16 dico_size,Flag * pOverflow)431 Word16 Test_Vq_subvec4(
432     Word16 * lsf_r1,
433     const Word16 * dico,
434     Word16 * wf1,
435     Word16 dico_size,
436     Flag   *pOverflow)
437 {
438     Word16  tst_index4 = 0;
439 
440     /*------------------------------------------------------------------------
441      CALL Vq_subvec4(lsf_r1 = lsf_r1
442                      dico = dico
443                      wf1 = wf1
444                      dico_size = dico_size)
445        MODIFYING(nothing)
446        RETURNING(index = index)
447     ------------------------------------------------------------------------*/
448     tst_index4 =
449         Vq_subvec4(
450             lsf_r1,
451             dico,
452             wf1,
453             dico_size,
454             pOverflow);
455 
456     return(tst_index4);
457 
458 }
459 
460 /****************************************************************************/
461 
462 /*
463 ------------------------------------------------------------------------------
464  FUNCTION NAME: Vq_subvec3
465 ------------------------------------------------------------------------------
466  INPUT AND OUTPUT DEFINITIONS
467 
468  Inputs:
469     lsf_r1 = pointer to the first LSF residual vector (Q15) (Word16)
470     dico = pointer to the quantization codebook (Q15) (const Word16)
471     wf1 = pointer to the first LSF weighting factor (Q13) (Word16)
472     dico_size = size of quantization codebook (Q0) (Word16)
473     use_half = flag to indicate use of every second entry in the
474                codebook (Flag)
475 
476  Outputs:
477     buffer pointed to by lsf_r1 contains the selected vector
478     pOverflow -- pointer to Flag -- Flag set when overflow occurs
479 
480  Returns:
481     index = quantization index (Q0) (Word16)
482 
483  Global Variables Used:
484     None
485 
486  Local Variables Needed:
487     None
488 
489 ------------------------------------------------------------------------------
490  FUNCTION DESCRIPTION
491 
492  This function performs the quantization of a 3 dimensional subvector.
493 
494 ------------------------------------------------------------------------------
495  REQUIREMENTS
496 
497  None
498 
499 ------------------------------------------------------------------------------
500  REFERENCES
501 
502  q_plsf_3.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
503 
504 ------------------------------------------------------------------------------
505  PSEUDO-CODE
506 
507 static Word16
508 Vq_subvec3(             // o: quantization index,            Q0
509     Word16 * lsf_r1,    // i: 1st LSF residual vector,       Q15
510     Word16 * dico,      // i: quantization codebook,         Q15
511     Word16 * wf1,       // i: 1st LSF weighting factors,     Q13
512     Word16 dico_size,   // i: size of quantization codebook, Q0
513     Flag use_half)      // i: use every second entry in codebook
514 {
515     Word16 i, index = 0;
516     Word16 *p_dico, temp;
517     Word32 dist_min, dist;
518 
519     dist_min = MAX_32;
520     p_dico = dico;
521 
522     if (use_half == 0) {
523        for (i = 0; i < dico_size; i++)
524        {
525           temp = sub(lsf_r1[0], *p_dico++);
526           temp = mult(wf1[0], temp);
527           dist = L_mult(temp, temp);
528 
529           temp = sub(lsf_r1[1], *p_dico++);
530           temp = mult(wf1[1], temp);
531           dist = L_mac(dist, temp, temp);
532 
533           temp = sub(lsf_r1[2], *p_dico++);
534           temp = mult(wf1[2], temp);
535           dist = L_mac(dist, temp, temp);
536 
537           if (L_sub(dist, dist_min) < (Word32) 0) {
538              dist_min = dist;
539              index = i;
540           }
541        }
542        p_dico = &dico[add(index, add(index, index))];
543     }
544     else
545     {
546        for (i = 0; i < dico_size; i++)
547        {
548           temp = sub(lsf_r1[0], *p_dico++);
549           temp = mult(wf1[0], temp);
550           dist = L_mult(temp, temp);
551 
552           temp = sub(lsf_r1[1], *p_dico++);
553           temp = mult(wf1[1], temp);
554           dist = L_mac(dist, temp, temp);
555 
556           temp = sub(lsf_r1[2], *p_dico++);
557           temp = mult(wf1[2], temp);
558           dist = L_mac(dist, temp, temp);
559 
560           if (L_sub(dist, dist_min) < (Word32) 0)
561           {
562              dist_min = dist;
563              index = i;
564           }
565           p_dico = p_dico + 3; add(0,0);
566        }
567        p_dico = &dico[shl(add(index, add(index, index)),1)];
568     }
569 
570 
571     // Reading the selected vector
572     lsf_r1[0] = *p_dico++;
573     lsf_r1[1] = *p_dico++;
574     lsf_r1[2] = *p_dico++;
575 
576     return index;
577 }
578 
579 ------------------------------------------------------------------------------
580  RESOURCES USED [optional]
581 
582  When the code is written for a specific target processor the
583  the resources used should be documented below.
584 
585  HEAP MEMORY USED: x bytes
586 
587  STACK MEMORY USED: x bytes
588 
589  CLOCK CYCLES: (cycle count equation for this function) + (variable
590                 used to represent cycle count for each subroutine
591                 called)
592      where: (cycle count variable) = cycle count for [subroutine
593                                      name]
594 
595 ------------------------------------------------------------------------------
596  CAUTION [optional]
597  [State any special notes, constraints or cautions for users of this function]
598 
599 ------------------------------------------------------------------------------
600 */
601 
Vq_subvec3(Word16 * lsf_r1,const Word16 * dico,Word16 * wf1,Word16 dico_size,Flag use_half,Flag * pOverflow)602 static Word16 Vq_subvec3( /* o: quantization index,            Q0  */
603     Word16 * lsf_r1,      /* i: 1st LSF residual vector,       Q15 */
604     const Word16 * dico,  /* i: quantization codebook,         Q15 */
605     Word16 * wf1,         /* i: 1st LSF weighting factors,     Q13 */
606     Word16 dico_size,     /* i: size of quantization codebook, Q0  */
607     Flag use_half,        /* i: use every second entry in codebook */
608     Flag  *pOverflow)     /* o : Flag set when overflow occurs     */
609 {
610     Word16 i;
611     Word16 temp;
612 
613     const Word16 *p_dico;
614 
615     Word16 p_dico_index = 0;
616     Word16 index = 0;
617 
618     Word32 dist_min;
619     Word32 dist;
620 
621     Word16 lsf_r1_0;
622     Word16 lsf_r1_1;
623     Word16 lsf_r1_2;
624 
625     Word16 wf1_0;
626     Word16 wf1_1;
627     Word16 wf1_2;
628 
629     OSCL_UNUSED_ARG(pOverflow);
630 
631     dist_min = MAX_32;
632     p_dico = dico;
633 
634     lsf_r1_0 = lsf_r1[0];
635     lsf_r1_1 = lsf_r1[1];
636     lsf_r1_2 = lsf_r1[2];
637 
638     wf1_0 = wf1[0];
639     wf1_1 = wf1[1];
640     wf1_2 = wf1[2];
641 
642     if (use_half != 0)
643     {
644         p_dico_index = 3;
645     }
646 
647     for (i = 0; i < dico_size; i++)
648     {
649         temp = lsf_r1_0 - (*p_dico++);
650         temp = (Word16)((((Word32) wf1_0) * temp) >> 15);
651         dist = ((Word32) temp) * temp;
652 
653         temp = lsf_r1_1 - (*p_dico++);
654         temp = (Word16)((((Word32) wf1_1) * temp) >> 15);
655         dist += ((Word32) temp) * temp;
656 
657         temp = lsf_r1_2 - (*p_dico++);
658         temp = (Word16)((((Word32) wf1_2) * temp) >> 15);
659         dist += ((Word32) temp) * temp;
660 
661         if (dist < dist_min)
662         {
663             dist_min = dist;
664             index = i;
665         }
666 
667         p_dico = p_dico + p_dico_index;
668     }
669 
670     p_dico = dico + (3 * index);
671 
672     if (use_half != 0)
673     {
674         p_dico += (3 * index);
675     }
676 
677     /* Reading the selected vector */
678     *lsf_r1++ = *p_dico++;
679     *lsf_r1++ = *p_dico++;
680     *lsf_r1 = *p_dico;
681 
682     return(index);
683 }
684 
685 /****************************************************************************/
686 
687 
688 /*
689 ------------------------------------------------------------------------------
690  FUNCTION NAME: Test_Vq_subvec3
691 ------------------------------------------------------------------------------
692  INPUT AND OUTPUT DEFINITIONS
693 
694  Inputs:
695     lsf_r1 = pointer to the first LSF residual vector (Q15) (Word16)
696     dico = pointer to the quantization codebook (Q15) (const Word16)
697     wf1 = pointer to the first LSF weighting factor (Q13) (Word16)
698     dico_size = size of quantization codebook (Q0) (Word16)
699     use_half = flag to indicate use of every second entry in the
700                codebook (Flag)
701 
702  Outputs:
703     buffer pointed to by lsf_r1 contains the selected vector
704     pOverflow -- pointer to Flag -- Flag set when overflow occurs
705 
706  Returns:
707     index = quantization index (Q0) (Word16)
708 
709  Global Variables Used:
710     None
711 
712  Local Variables Needed:
713     None
714 
715 ------------------------------------------------------------------------------
716  FUNCTION DESCRIPTION
717 
718  This function calls the static function Vq_subvec3. It is used for testing
719  purposes only
720 
721 ------------------------------------------------------------------------------
722  REQUIREMENTS
723 
724  None
725 
726 ------------------------------------------------------------------------------
727  REFERENCES
728 
729  None
730 
731 ------------------------------------------------------------------------------
732  PSEUDO-CODE
733 
734  CALL Vq_subvec3(lsf_r1 = lsf_r1
735                  dico = dico
736                  wf1 = wf1
737                  dico_size = dico_size
738                  use_half = use_half)
739    MODIFYING(nothing)
740    RETURNING(index = tst_index3)
741 
742 ------------------------------------------------------------------------------
743  RESOURCES USED [optional]
744 
745  When the code is written for a specific target processor the
746  the resources used should be documented below.
747 
748  HEAP MEMORY USED: x bytes
749 
750  STACK MEMORY USED: x bytes
751 
752  CLOCK CYCLES: (cycle count equation for this function) + (variable
753                 used to represent cycle count for each subroutine
754                 called)
755      where: (cycle count variable) = cycle count for [subroutine
756                                      name]
757 
758 ------------------------------------------------------------------------------
759  CAUTION [optional]
760  [State any special notes, constraints or cautions for users of this function]
761 
762 ------------------------------------------------------------------------------
763 */
764 
Test_Vq_subvec3(Word16 * lsf_r1,const Word16 * dico,Word16 * wf1,Word16 dico_size,Flag use_half,Flag * pOverflow)765 Word16 Test_Vq_subvec3(
766     Word16 * lsf_r1,
767     const Word16 * dico,
768     Word16 * wf1,
769     Word16 dico_size,
770     Flag use_half,
771     Flag *pOverflow)
772 {
773     Word16  tst_index3 = 0;
774 
775     /*------------------------------------------------------------------------
776      CALL Vq_subvec3(lsf_r1 = lsf_r1
777                      dico = dico
778                      wf1 = wf1
779                      dico_size = dico_size
780                      use_half = use_half)
781        MODIFYING(nothing)
782        RETURNING(index = index)
783     ------------------------------------------------------------------------*/
784     tst_index3 =
785         Vq_subvec3(
786             lsf_r1,
787             dico,
788             wf1,
789             dico_size,
790             use_half,
791             pOverflow);
792 
793     return(tst_index3);
794 
795 }
796 
797 /****************************************************************************/
798 
799 
800 /*
801 ------------------------------------------------------------------------------
802  FUNCTION NAME: Q_plsf_3
803 ------------------------------------------------------------------------------
804  INPUT AND OUTPUT DEFINITIONS
805 
806  Inputs:
807     st = pointer to structures of type Q_plsfState (Q_plsfState)
808     mode = coder mode (enum)
809     lsp1 = pointer to the first LSP vector (Word16)
810     lsp1_q = pointer to the quantized first LSP vector (Word16)
811     indice = pointer to the quantization indices of 3 vectors (Word16)
812     pred_init_i = pointer to the index of the initial value for
813                   MA prediction in DTX mode (Word16)
814 
815  Outputs:
816     lsp1_q points to a vector containing the new quantized LSPs
817     indice points to the new quantization indices of 3 vectors
818     pred_init_i points to the new initial index for MA prediction
819       in DTX mode
820     past_rq field of structure pointed to by st contains the current
821       quantized LSF parameters
822     pOverflow -- pointer to Flag -- Flag set when overflow occurs
823 
824  Returns:
825     None
826 
827  Global Variables Used:
828     pred_fac = table containing prediction factors (const Word16)
829     dico1_lsf = quantization table for split_MQ of 2 sets of LSFs
830                 in a 20 ms frame (const Word16)
831     dico2_lsf = quantization table for split_MQ of 2 sets of LSFs
832                 in a 20 ms frame (const Word16)
833     dico3_lsf = quantization table for split_MQ of 2 sets of LSFs
834                 in a 20 ms frame (const Word16)
835     mr515_3_lsf = third codebook for MR475 and MR515 modes (const Word16)
836     mr795_1_lsf = first codebook for MR795 mode (const Word16)
837     mean_lsf = table of mean LSFs (const Word16)
838     past_rq_init = initalization table for MA predictor in DTX mode
839                    (const Word16)
840 
841 
842  Local Variables Needed:
843     None
844 
845 ------------------------------------------------------------------------------
846  FUNCTION DESCRIPTION
847 
848  This function performs quantization of LSF parameters with 1st order MA
849  prediction and split by 3 vector quantization (split-VQ)
850 
851 ------------------------------------------------------------------------------
852  REQUIREMENTS
853 
854  None
855 
856 ------------------------------------------------------------------------------
857  REFERENCES
858 
859  q_plsf_3.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
860 
861 ------------------------------------------------------------------------------
862  PSEUDO-CODE
863 
864 void Q_plsf_3(
865     Q_plsfState *st,    // i/o: state struct
866     enum Mode mode,     // i  : coder mode
867     Word16 *lsp1,       // i  : 1st LSP vector                      Q15
868     Word16 *lsp1_q,     // o  : quantized 1st LSP vector            Q15
869     Word16 *indice,     // o  : quantization indices of 3 vectors   Q0
870     Word16 *pred_init_i // o  : init index for MA prediction in DTX mode
871 )
872 {
873     Word16 i, j;
874     Word16 lsf1[M], wf1[M], lsf_p[M], lsf_r1[M];
875     Word16 lsf1_q[M];
876 
877     Word32 L_pred_init_err;
878     Word32 L_min_pred_init_err;
879     Word16 temp_r1[M];
880     Word16 temp_p[M];
881 
882     // convert LSFs to normalize frequency domain 0..16384
883 
884     Lsp_lsf(lsp1, lsf1, M);
885 
886     // compute LSF weighting factors (Q13)
887 
888     Lsf_wt(lsf1, wf1);
889 
890     // Compute predicted LSF and prediction error
891     if (test(), sub(mode, MRDTX) != 0)
892     {
893        for (i = 0; i < M; i++)
894        {
895           lsf_p[i] = add(mean_lsf[i],
896                          mult(st->past_rq[i],
897                               pred_fac[i]));
898           lsf_r1[i] = sub(lsf1[i], lsf_p[i]);
899       }
900     }
901     else
902     {
903        // DTX mode, search the init vector that yields
904        // lowest prediction resuidual energy
905        *pred_init_i = 0;
906        L_min_pred_init_err = 0x7fffffff; // 2^31 - 1
907        for (j = 0; j < PAST_RQ_INIT_SIZE; j++)
908        {
909           L_pred_init_err = 0;
910           for (i = 0; i < M; i++)
911           {
912              temp_p[i] = add(mean_lsf[i], past_rq_init[j*M+i]);
913              temp_r1[i] = sub(lsf1[i],temp_p[i]);
914              L_pred_init_err = L_mac(L_pred_init_err, temp_r1[i], temp_r1[i]);
915           }  // next i
916 
917 
918           if (L_sub(L_pred_init_err, L_min_pred_init_err) < (Word32) 0)
919           {
920              L_min_pred_init_err = L_pred_init_err;
921              Copy(temp_r1, lsf_r1, M);
922              Copy(temp_p, lsf_p, M);
923              // Set zerom
924              Copy(&past_rq_init[j*M], st->past_rq, M);
925              *pred_init_i = j;
926           } // endif
927        } // next j
928     } // endif MRDTX
929 
930     //---- Split-VQ of prediction error ----
931     if (sub (mode, MR475) == 0 || sub (mode, MR515) == 0)
932     {   // MR475, MR515
933 
934 
935       indice[0] = Vq_subvec3(&lsf_r1[0], dico1_lsf, &wf1[0], DICO1_SIZE, 0);
936 
937       indice[1] = Vq_subvec3(&lsf_r1[3], dico2_lsf, &wf1[3], DICO2_SIZE/2, 1);
938 
939       indice[2] = Vq_subvec4(&lsf_r1[6], mr515_3_lsf, &wf1[6], MR515_3_SIZE);
940 
941     }
942     else if (sub (mode, MR795) == 0)
943     {   // MR795
944 
945 
946       indice[0] = Vq_subvec3(&lsf_r1[0], mr795_1_lsf, &wf1[0], MR795_1_SIZE, 0);
947 
948       indice[1] = Vq_subvec3(&lsf_r1[3], dico2_lsf, &wf1[3], DICO2_SIZE, 0);
949 
950       indice[2] = Vq_subvec4(&lsf_r1[6], dico3_lsf, &wf1[6], DICO3_SIZE);
951 
952     }
953     else
954     {   // MR59, MR67, MR74, MR102 , MRDTX
955 
956 
957       indice[0] = Vq_subvec3(&lsf_r1[0], dico1_lsf, &wf1[0], DICO1_SIZE, 0);
958 
959       indice[1] = Vq_subvec3(&lsf_r1[3], dico2_lsf, &wf1[3], DICO2_SIZE, 0);
960 
961       indice[2] = Vq_subvec4(&lsf_r1[6], dico3_lsf, &wf1[6], DICO3_SIZE);
962 
963     }
964 
965 
966     // Compute quantized LSFs and update the past quantized residual
967 
968     for (i = 0; i < M; i++)
969     {
970         lsf1_q[i] = add(lsf_r1[i], lsf_p[i]);
971         st->past_rq[i] = lsf_r1[i];
972     }
973 
974     // verification that LSFs has mimimum distance of LSF_GAP Hz
975 
976     Reorder_lsf(lsf1_q, LSF_GAP, M);
977 
978     //  convert LSFs to the cosine domain
979 
980     Lsf_lsp(lsf1_q, lsp1_q, M);
981 }
982 
983 ------------------------------------------------------------------------------
984  RESOURCES USED [optional]
985 
986  When the code is written for a specific target processor the
987  the resources used should be documented below.
988 
989  HEAP MEMORY USED: x bytes
990 
991  STACK MEMORY USED: x bytes
992 
993  CLOCK CYCLES: (cycle count equation for this function) + (variable
994                 used to represent cycle count for each subroutine
995                 called)
996      where: (cycle count variable) = cycle count for [subroutine
997                                      name]
998 
999 ------------------------------------------------------------------------------
1000  CAUTION [optional]
1001  [State any special notes, constraints or cautions for users of this function]
1002 
1003 ------------------------------------------------------------------------------
1004 */
1005 
Q_plsf_3(Q_plsfState * st,enum Mode mode,Word16 * lsp1,Word16 * lsp1_q,Word16 * indice,Word16 * pred_init_i,Flag * pOverflow)1006 void Q_plsf_3(
1007     Q_plsfState *st,    /* i/o: state struct                             */
1008     enum Mode mode,     /* i  : coder mode                               */
1009     Word16 *lsp1,       /* i  : 1st LSP vector                      Q15  */
1010     Word16 *lsp1_q,     /* o  : quantized 1st LSP vector            Q15  */
1011     Word16 *indice,     /* o  : quantization indices of 3 vectors   Q0   */
1012     Word16 *pred_init_i,/* o  : init index for MA prediction in DTX mode */
1013     Flag  *pOverflow    /* o : Flag set when overflow occurs             */
1014 )
1015 {
1016     Word16 i, j;
1017     Word16 lsf1[M];
1018     Word16 wf1[M];
1019     Word16 lsf_p[M];
1020     Word16 lsf_r1[M];
1021     Word16 lsf1_q[M];
1022 
1023     Word32 L_pred_init_err;
1024     Word32 L_min_pred_init_err;
1025     Word32 L_temp;
1026     Word16 temp_r1[M];
1027     Word16 temp_p[M];
1028     Word16 temp;
1029 
1030     /* convert LSFs to normalize frequency domain 0..16384 */
1031 
1032     Lsp_lsf(
1033         lsp1,
1034         lsf1,
1035         M,
1036         pOverflow);
1037 
1038     /* compute LSF weighting factors (Q13) */
1039 
1040     Lsf_wt(
1041         lsf1,
1042         wf1,
1043         pOverflow);
1044 
1045     /* Compute predicted LSF and prediction error */
1046     if (mode != MRDTX)
1047     {
1048         for (i = 0; i < M; i++)
1049         {
1050             temp = (Word16)((((Word32) st->past_rq[i]) *
1051                              (*(pred_fac_3 + i))) >> 15);
1052 
1053             *(lsf_p + i) = *(mean_lsf_3 + i) + temp;
1054 
1055             *(lsf_r1 + i) = *(lsf1 + i) - *(lsf_p + i);
1056         }
1057     }
1058     else
1059     {
1060         /* DTX mode, search the init vector that yields */
1061         /* lowest prediction resuidual energy           */
1062         *pred_init_i = 0;
1063         L_min_pred_init_err = 0x7fffffff; /* 2^31 - 1 */
1064 
1065         for (j = 0; j < PAST_RQ_INIT_SIZE; j++)
1066         {
1067             L_pred_init_err = 0;
1068             for (i = 0; i < M; i++)
1069             {
1070                 *(temp_p + i) = *(mean_lsf_3 + i) + *(past_rq_init + j * M + i);
1071 
1072                 *(temp_r1 + i) = *(lsf1 + i) - *(temp_p + i);
1073 
1074                 L_temp = ((Word32) * (temp_r1 + i)) * *(temp_r1 + i);
1075 
1076                 L_pred_init_err = L_pred_init_err + (L_temp << 1);
1077 
1078             }  /* next i */
1079 
1080 
1081             if (L_pred_init_err < L_min_pred_init_err)
1082             {
1083                 L_min_pred_init_err = L_pred_init_err;
1084 
1085                 memcpy(
1086                     lsf_r1,
1087                     temp_r1,
1088                     M*sizeof(Word16));
1089 
1090                 memcpy(
1091                     lsf_p,
1092                     temp_p,
1093                     M*sizeof(Word16));
1094 
1095                 /* Set zerom */
1096                 memcpy(
1097                     st->past_rq,
1098                     &past_rq_init[j*M],
1099                     M*sizeof(Word16));
1100 
1101                 *pred_init_i = j;
1102 
1103             } /* endif */
1104         } /* next j */
1105     } /* endif MRDTX */
1106 
1107     /*---- Split-VQ of prediction error ----*/
1108     if ((mode == MR475) || (mode == MR515))
1109     {   /* MR475, MR515 */
1110 
1111         *indice =
1112             Vq_subvec3(
1113                 lsf_r1,
1114                 dico1_lsf_3,
1115                 wf1,
1116                 DICO1_SIZE,
1117                 0,
1118                 pOverflow);
1119 
1120         *(indice + 1) =
1121             Vq_subvec3(
1122                 lsf_r1 + 3,
1123                 dico2_lsf_3,
1124                 wf1 + 3,
1125                 DICO2_SIZE / 2,
1126                 1,
1127                 pOverflow);
1128 
1129         *(indice + 2) =
1130             Vq_subvec4(
1131                 lsf_r1 + 6,
1132                 mr515_3_lsf,
1133                 wf1 + 6,
1134                 MR515_3_SIZE,
1135                 pOverflow);
1136 
1137     }
1138     else if (mode == MR795)
1139     {   /* MR795 */
1140 
1141         *indice =
1142             Vq_subvec3(
1143                 lsf_r1,
1144                 mr795_1_lsf,
1145                 wf1,
1146                 MR795_1_SIZE,
1147                 0,
1148                 pOverflow);
1149 
1150         *(indice + 1) =
1151             Vq_subvec3(
1152                 lsf_r1 + 3,
1153                 dico2_lsf_3,
1154                 wf1 + 3,
1155                 DICO2_SIZE,
1156                 0,
1157                 pOverflow);
1158 
1159         *(indice + 2) =
1160             Vq_subvec4(
1161                 lsf_r1 + 6,
1162                 dico3_lsf_3,
1163                 wf1 + 6,
1164                 DICO3_SIZE,
1165                 pOverflow);
1166 
1167     }
1168     else
1169     {   /* MR59, MR67, MR74, MR102 , MRDTX */
1170 
1171         *indice =
1172             Vq_subvec3(
1173                 lsf_r1,
1174                 dico1_lsf_3,
1175                 wf1,
1176                 DICO1_SIZE,
1177                 0,
1178                 pOverflow);
1179 
1180         *(indice + 1) =
1181             Vq_subvec3(
1182                 lsf_r1 + 3,
1183                 dico2_lsf_3,
1184                 wf1 + 3,
1185                 DICO2_SIZE,
1186                 0,
1187                 pOverflow);
1188 
1189         *(indice + 2) =
1190             Vq_subvec4(
1191                 lsf_r1 + 6,
1192                 dico3_lsf_3,
1193                 wf1 + 6,
1194                 DICO3_SIZE,
1195                 pOverflow);
1196 
1197     }
1198 
1199 
1200     /* Compute quantized LSFs and update the past quantized residual */
1201 
1202     for (i = 0; i < M; i++)
1203     {
1204         *(lsf1_q + i) = *(lsf_r1 + i) + *(lsf_p + i);
1205         st->past_rq[i] = *(lsf_r1 + i);
1206     }
1207 
1208     /* verification that LSFs has mimimum distance of LSF_GAP Hz */
1209 
1210     Reorder_lsf(
1211         lsf1_q,
1212         LSF_GAP,
1213         M,
1214         pOverflow);
1215 
1216     /*  convert LSFs to the cosine domain */
1217 
1218     Lsf_lsp(
1219         lsf1_q,
1220         lsp1_q,
1221         M,
1222         pOverflow);
1223 
1224     return;
1225 
1226 }
1227