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/****************************************************************************************
19Portions 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)
26Permission to distribute, modify and use this file under the standard license
27terms 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
109extern "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
201static Word16
202Vq_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
276static 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    register 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
431Word16 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
507static Word16
508Vq_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
602static 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    register 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
765Word16 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
864void 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
1006void 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    register 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