q_plsf_5.cpp revision 4f1efc098cb5791c3e9f483f2af84aef70d2d0a0
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 Pathname: ./audio/gsm-amr/c/src/q_plsf_5.c
31 Funtions:
32
33------------------------------------------------------------------------------
34 REVISION HISTORY
35
36 Description: Placed code in the PV standard template format.
37 Updated to accept new parameter, Flag *pOverflow.
38
39 Description:
40              Eliminated unused include files.
41              For Vq_subvec()
42              1. Eliminated math operations that unnecessary checked for
43                 saturation (number are bounded to 2^12)
44              2. Eliminated access to (slow) memory by using axiliar variables
45              3. Because this routine is looking for the minimum distance,
46                 introduced 3 check conditions inside the loop, so when the
47                 partial distance is bigger than the minimun distance, the
48                 loop is not completed and process continue with next iteration
49              For Vq_subvec_s()
50              1. Eliminated math operations that unnecessary checked for
51                 saturation (number are bounded to 2^12)
52              2. Combined increasing and decreasing loops to avoid double
53                 accesses to the same table element
54              3. Eliminated access to (slow) memory by using axiliar variables
55              4. Because this routine is looking for the minimum distance,
56                 introduced 2 check conditions inside the loop, so when the
57                 partial distance is bigger than the minimun distance, the
58                 loop is not completed and process continue with next iteration
59              For Q_plsf_5()
60              1. Eliminated math operations that unnecessary checked for
61                 saturation (number are bounded to 2^12)
62              2. Replaced array addressing by pointers
63
64 Description:  Replaced OSCL mem type functions and eliminated include
65               files that now are chosen by OSCL definitions
66
67 Description:  Replaced "int" and/or "char" with OSCL defined types.
68
69
70 Description: Added #ifdef __cplusplus around extern'ed table.
71
72 Who:                           Date:
73 Description:
74
75------------------------------------------------------------------------------
76 MODULE DESCRIPTION
77
78
79------------------------------------------------------------------------------
80*/
81
82/*----------------------------------------------------------------------------
83; INCLUDES
84----------------------------------------------------------------------------*/
85#include "q_plsf.h"
86#include "typedef.h"
87#include "basic_op.h"
88#include "lsp_lsf.h"
89#include "reorder.h"
90#include "lsfwt.h"
91
92/*--------------------------------------------------------------------------*/
93#ifdef __cplusplus
94extern "C"
95{
96#endif
97
98    /*----------------------------------------------------------------------------
99    ; MACROS
100    ; Define module specific macros here
101    ----------------------------------------------------------------------------*/
102
103    /*----------------------------------------------------------------------------
104    ; DEFINES
105    ; Include all pre-processor statements here. Include conditional
106    ; compile variables also.
107    ----------------------------------------------------------------------------*/
108
109    /*----------------------------------------------------------------------------
110    ; LOCAL FUNCTION DEFINITIONS
111    ; Function Prototype declaration
112    ----------------------------------------------------------------------------*/
113
114    /*----------------------------------------------------------------------------
115    ; LOCAL VARIABLE DEFINITIONS
116    ; Variable declaration - defined here and used outside this module
117    ----------------------------------------------------------------------------*/
118
119    /*----------------------------------------------------------------------------
120    ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
121    ; Declare variables used in this module but defined elsewhere
122    ----------------------------------------------------------------------------*/
123    /* Codebooks of LSF prediction residual */
124    extern const Word16 mean_lsf_5[];
125
126    extern const Word16 dico1_lsf_5[];
127    extern const Word16 dico2_lsf_5[];
128    extern const Word16 dico3_lsf_5[];
129    extern const Word16 dico4_lsf_5[];
130    extern const Word16 dico5_lsf_5[];
131
132    /*--------------------------------------------------------------------------*/
133#ifdef __cplusplus
134}
135#endif
136
137/*
138------------------------------------------------------------------------------
139 FUNCTION NAME: Vq_subvec
140------------------------------------------------------------------------------
141 INPUT AND OUTPUT DEFINITIONS
142
143 Inputs:
144    lsf_r1 -- array of type Word16 -- 1st LSF residual vector,  Q15
145    lsf_r2 -- array of type Word16 -- 2nd LSF residual vector,  Q15
146    dico -- pointer to const Word16 -- quantization codebook,   Q15
147    wf1 -- array of type Word16 -- 1st LSF weighting factors,   Q13
148    wf2 -- array of type Word16 -- 2nd LSF weighting factors,   Q13
149    dico_size -- Word16 -- size of quantization codebook,       Q0
150 Outputs:
151    pOverflow -- pointer to type Flag -- overflow indicator
152
153 Returns:
154    Word16 -- quantization index, Q0
155
156 Global Variables Used:
157    None
158
159 Local Variables Needed:
160    None
161
162------------------------------------------------------------------------------
163 FUNCTION DESCRIPTION
164
165 This function performs the quantization of a 4-dimensional subvector.
166
167------------------------------------------------------------------------------
168 REQUIREMENTS
169
170 None
171
172------------------------------------------------------------------------------
173 REFERENCES
174
175 q_plsf_5.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
176
177------------------------------------------------------------------------------
178 PSEUDO-CODE
179
180
181------------------------------------------------------------------------------
182 RESOURCES USED [optional]
183
184 When the code is written for a specific target processor the
185 the resources used should be documented below.
186
187 HEAP MEMORY USED: x bytes
188
189 STACK MEMORY USED: x bytes
190
191 CLOCK CYCLES: (cycle count equation for this function) + (variable
192                used to represent cycle count for each subroutine
193                called)
194     where: (cycle count variable) = cycle count for [subroutine
195                                     name]
196
197------------------------------------------------------------------------------
198 CAUTION [optional]
199 [State any special notes, constraints or cautions for users of this function]
200
201------------------------------------------------------------------------------
202*/
203/* Quantization of a 4 dimensional subvector */
204
205static Word16 Vq_subvec( /* o : quantization index,            Q0  */
206    Word16 *lsf_r1,      /* i : 1st LSF residual vector,       Q15 */
207    Word16 *lsf_r2,      /* i : 2nd LSF residual vector,       Q15 */
208    const Word16 *dico,  /* i : quantization codebook,         Q15 */
209    Word16 *wf1,         /* i : 1st LSF weighting factors      Q13 */
210    Word16 *wf2,         /* i : 2nd LSF weighting factors      Q13 */
211    Word16 dico_size,    /* i : size of quantization codebook, Q0  */
212    Flag   *pOverflow    /* o : overflow indicator                 */
213)
214{
215    Word16 index = 0; /* initialization only needed to keep gcc silent */
216    Word16 i;
217    Word16 temp;
218    const Word16 *p_dico;
219    Word32 dist_min;
220    Word32 dist;
221    Word16 wf1_0;
222    Word16 wf1_1;
223    Word16 wf2_0;
224    Word16 wf2_1;
225    Word32 aux1;
226    Word32 aux2;
227    Word32 aux3;
228    Word32 aux4;
229
230    OSCL_UNUSED_ARG(pOverflow);
231
232    dist_min = MAX_32;
233    p_dico = dico;
234
235    wf1_0 = wf1[0];
236    wf1_1 = wf1[1];
237    wf2_0 = wf2[0];
238    wf2_1 = wf2[1];
239
240    aux1 = ((Word32) lsf_r1[0] * wf1_0);
241    aux2 = ((Word32) lsf_r1[1] * wf1_1);
242    aux3 = ((Word32) lsf_r2[0] * wf2_0);
243    aux4 = ((Word32) lsf_r2[1] * wf2_1);
244
245    for (i = 0; i < dico_size; i++)
246    {
247        temp  = (aux1 - ((Word32)wf1_0 * *(p_dico++))) >> 15;
248        dist  = ((Word32)temp * temp);
249
250        if (dist >= dist_min)
251        {
252            p_dico += 3;
253            continue;
254        }
255
256        temp  = (aux2 - ((Word32)wf1_1 * *(p_dico++))) >> 15;
257        dist += ((Word32)temp * temp);
258
259        if (dist >= dist_min)
260        {
261            p_dico += 2;
262            continue;
263        }
264
265        temp  = (aux3 - ((Word32)wf2_0 * *(p_dico++))) >> 15;
266        dist += ((Word32)temp * temp);
267
268        if (dist >= dist_min)
269        {
270            p_dico += 1;
271            continue;
272        }
273
274        temp  = (aux4 - ((Word32)wf2_1 * *(p_dico++))) >> 15;
275        dist += ((Word32)temp * temp);
276
277
278        if (dist < dist_min)
279        {
280            dist_min = dist;
281            index = i;
282        }
283    }
284
285
286
287    /* Reading the selected vector */
288
289    p_dico = &dico[ index<<2];
290    lsf_r1[0] = *p_dico++;
291    lsf_r1[1] = *p_dico++;
292    lsf_r2[0] = *p_dico++;
293    lsf_r2[1] = *p_dico;
294
295    return index;
296
297}
298
299
300/*
301------------------------------------------------------------------------------
302 FUNCTION NAME: Vq_subvec_s
303------------------------------------------------------------------------------
304 INPUT AND OUTPUT DEFINITIONS
305
306 Inputs:
307    lsf_r1 -- array of type Word16 -- 1st LSF residual vector,  Q15
308    lsf_r2 -- array of type Word16 -- 2nd LSF residual vector,  Q15
309    dico -- pointer to const Word16 -- quantization codebook,   Q15
310    wf1 -- array of type Word16 -- 1st LSF weighting factors,   Q13
311    wf2 -- array of type Word16 -- 2nd LSF weighting factors,   Q13
312    dico_size -- Word16 -- size of quantization codebook,       Q0
313
314 Outputs:
315    pOverflow -- pointer to type Flag -- overflow indicator
316
317 Returns:
318    Word16 -- quantization index, Q0
319
320 Global Variables Used:
321    None
322
323 Local Variables Needed:
324    None
325
326------------------------------------------------------------------------------
327 FUNCTION DESCRIPTION
328
329 This function performs the quantization of a 4-dimensional subvector.
330
331------------------------------------------------------------------------------
332 REQUIREMENTS
333
334 None
335
336------------------------------------------------------------------------------
337 REFERENCES
338
339 q_plsf_5.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
340
341------------------------------------------------------------------------------
342 PSEUDO-CODE
343
344
345------------------------------------------------------------------------------
346 RESOURCES USED [optional]
347
348 When the code is written for a specific target processor the
349 the resources used should be documented below.
350
351 HEAP MEMORY USED: x bytes
352
353 STACK MEMORY USED: x bytes
354
355 CLOCK CYCLES: (cycle count equation for this function) + (variable
356                used to represent cycle count for each subroutine
357                called)
358     where: (cycle count variable) = cycle count for [subroutine
359                                     name]
360
361------------------------------------------------------------------------------
362 CAUTION [optional]
363 [State any special notes, constraints or cautions for users of this function]
364
365------------------------------------------------------------------------------
366*/
367
368
369/* Quantization of a 4 dimensional subvector with a signed codebook */
370
371static Word16 Vq_subvec_s(  /* o : quantization index            Q0  */
372    Word16 *lsf_r1,         /* i : 1st LSF residual vector       Q15 */
373    Word16 *lsf_r2,         /* i : and LSF residual vector       Q15 */
374    const Word16 *dico,     /* i : quantization codebook         Q15 */
375    Word16 *wf1,            /* i : 1st LSF weighting factors     Q13 */
376    Word16 *wf2,            /* i : 2nd LSF weighting factors     Q13 */
377    Word16 dico_size,       /* i : size of quantization codebook Q0  */
378    Flag   *pOverflow)      /* o : overflow indicator                */
379{
380    Word16 index = 0;  /* initialization only needed to keep gcc silent */
381    Word16 sign = 0;   /* initialization only needed to keep gcc silent */
382    Word16 i;
383    Word16 temp;
384    Word16 temp1;
385    Word16 temp2;
386    const Word16 *p_dico;
387    Word32 dist_min;
388    Word32 dist1;
389    Word32 dist2;
390
391    Word16 lsf_r1_0;
392    Word16 lsf_r1_1;
393    Word16 lsf_r2_0;
394    Word16 lsf_r2_1;
395
396    Word16 wf1_0;
397    Word16 wf1_1;
398    Word16 wf2_0;
399    Word16 wf2_1;
400
401    OSCL_UNUSED_ARG(pOverflow);
402
403    dist_min = MAX_32;
404    p_dico = dico;
405
406
407    lsf_r1_0 = lsf_r1[0];
408    lsf_r1_1 = lsf_r1[1];
409    lsf_r2_0 = lsf_r2[0];
410    lsf_r2_1 = lsf_r2[1];
411
412    wf1_0 = wf1[0];
413    wf1_1 = wf1[1];
414    wf2_0 = wf2[0];
415    wf2_1 = wf2[1];
416
417    for (i = 0; i < dico_size; i++)
418    {
419        /* test positive */
420        temp = *p_dico++;
421        temp1 = lsf_r1_0 - temp;
422        temp2 = lsf_r1_0 + temp;
423        temp1 = ((Word32)wf1_0 * temp1) >> 15;
424        temp2 = ((Word32)wf1_0 * temp2) >> 15;
425        dist1 = ((Word32)temp1 * temp1);
426        dist2 = ((Word32)temp2 * temp2);
427
428        temp = *p_dico++;
429        temp1 = lsf_r1_1 - temp;
430        temp2 = lsf_r1_1 + temp;
431        temp1 = ((Word32)wf1_1 * temp1) >> 15;
432        temp2 = ((Word32)wf1_1 * temp2) >> 15;
433        dist1 += ((Word32)temp1 * temp1);
434        dist2 += ((Word32)temp2 * temp2);
435
436        if ((dist1 >= dist_min) && (dist2 >= dist_min))
437        {
438            p_dico += 2;
439            continue;
440        }
441
442        temp = *p_dico++;
443        temp1 = lsf_r2_0 - temp;
444        temp2 = lsf_r2_0 + temp;
445        temp1 = ((Word32)wf2_0 * temp1) >> 15;
446        temp2 = ((Word32)wf2_0 * temp2) >> 15;
447        dist1 += ((Word32)temp1 * temp1);
448        dist2 += ((Word32)temp2 * temp2);
449
450        temp = *p_dico++;
451        temp1 = lsf_r2_1 - temp;
452        temp2 = lsf_r2_1 + temp;
453        temp1 = ((Word32)wf2_1 * temp1) >> 15;
454        temp2 = ((Word32)wf2_1 * temp2) >> 15;
455        dist1 += ((Word32)temp1 * temp1);
456        dist2 += ((Word32)temp2 * temp2);
457
458        if (dist1 < dist_min)
459        {
460            dist_min = dist1;
461            index = i;
462            sign = 0;
463        }
464
465        /* test negative */
466
467        if (dist2 < dist_min)
468        {
469            dist_min = dist2;
470            index = i;
471            sign = 1;
472        }
473    }
474
475    /* Reading the selected vector */
476
477    p_dico = &dico[index<<2];
478    index <<= 1;
479    if (sign)
480    {
481        lsf_r1[0] = - (*p_dico++);
482        lsf_r1[1] = - (*p_dico++);
483        lsf_r2[0] = - (*p_dico++);
484        lsf_r2[1] = - (*p_dico);
485        index +=  1;
486    }
487    else
488    {
489        lsf_r1[0] = *p_dico++;
490        lsf_r1[1] = *p_dico++;
491        lsf_r2[0] = *p_dico++;
492        lsf_r2[1] = *p_dico;
493    }
494
495    return index;
496
497}
498
499/*
500------------------------------------------------------------------------------
501 FUNCTION NAME: Q_plsf_5
502------------------------------------------------------------------------------
503 INPUT AND OUTPUT DEFINITIONS
504
505
506 Inputs:
507    st   -- pointer to Q_plsfState -- state information
508    lsp1 -- array of type Word16 -- 1st LSP vector,  Q15
509    lsp2 -- array of type Word16 -- 2nd LSP vector,  Q15
510
511 Outputs:
512    lps1_q -- array of type Word16 -- quantized 1st LSP vector,   Q15
513    lps2_q -- array of type Word16 -- quantized 2nd LSP vector,   Q15
514    indices -- array of type Word16 -- quantization indices of 5 matrics, Q0
515    pOverflow -- pointer to type Flag -- overflow indicator
516
517 Returns:
518    None
519
520 Global Variables Used:
521    mean_lsf_5[];
522
523    dico1_lsf_5[];
524    dico2_lsf_5[];
525    dico3_lsf_5[];
526    dico4_lsf_5[];
527    dico5_lsf_5[];
528
529 Local Variables Needed:
530    None
531
532------------------------------------------------------------------------------
533 FUNCTION DESCRIPTION
534
535 PURPOSE:  Quantization of 2 sets of LSF parameters using 1st order MA
536           prediction and split by 5 matrix quantization (split-MQ)
537
538 DESCRIPTION:
539
540      p[i] = pred_factor*past_rq[i];   i=0,...,m-1
541      r1[i]= lsf1[i] - p[i];           i=0,...,m-1
542      r2[i]= lsf2[i] - p[i];           i=0,...,m-1
543 where:
544      lsf1[i]           1st mean-removed LSF vector.
545      lsf2[i]           2nd mean-removed LSF vector.
546      r1[i]             1st residual prediction vector.
547      r2[i]             2nd residual prediction vector.
548      past_r2q[i]       Past quantized residual (2nd vector).
549
550 The residual vectors r1[i] and r2[i] are jointly quantized using
551 split-MQ with 5 codebooks. Each 4th dimension submatrix contains 2
552 elements from each residual vector. The 5 submatrices are as follows:
553   {r1[0], r1[1], r2[0], r2[1]};  {r1[2], r1[3], r2[2], r2[3]};
554   {r1[4], r1[5], r2[4], r2[5]};  {r1[6], r1[7], r2[6], r2[7]};
555                  {r1[8], r1[9], r2[8], r2[9]}
556
557------------------------------------------------------------------------------
558 REQUIREMENTS
559
560 None
561
562------------------------------------------------------------------------------
563 REFERENCES
564
565 q_plsf_5.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
566
567------------------------------------------------------------------------------
568 PSEUDO-CODE
569
570
571------------------------------------------------------------------------------
572 RESOURCES USED [optional]
573
574 When the code is written for a specific target processor the
575 the resources used should be documented below.
576
577 HEAP MEMORY USED: x bytes
578
579 STACK MEMORY USED: x bytes
580
581 CLOCK CYCLES: (cycle count equation for this function) + (variable
582                used to represent cycle count for each subroutine
583                called)
584     where: (cycle count variable) = cycle count for [subroutine
585                                     name]
586
587------------------------------------------------------------------------------
588 CAUTION [optional]
589 [State any special notes, constraints or cautions for users of this function]
590
591------------------------------------------------------------------------------
592*/
593
594void Q_plsf_5(
595    Q_plsfState *st,
596    Word16 *lsp1,      /* i : 1st LSP vector,                     Q15 */
597    Word16 *lsp2,      /* i : 2nd LSP vector,                     Q15 */
598    Word16 *lsp1_q,    /* o : quantized 1st LSP vector,           Q15 */
599    Word16 *lsp2_q,    /* o : quantized 2nd LSP vector,           Q15 */
600    Word16 *indice,    /* o : quantization indices of 5 matrices, Q0  */
601    Flag   *pOverflow  /* o : overflow indicator                      */
602)
603{
604    Word16 i;
605    Word16 lsf1[M];
606    Word16 lsf2[M];
607    Word16 wf1[M];
608    Word16 wf2[M];
609    Word16 lsf_p[M];
610    Word16 lsf_r1[M];
611    Word16 lsf_r2[M];
612    Word16 lsf1_q[M];
613    Word16 lsf2_q[M];
614
615    Word16 *p_lsf_p;
616    Word16 *p_lsf1;
617    Word16 *p_lsf2;
618    Word16 *p_lsf_r1;
619    Word16 *p_lsf_r2;
620
621    /* convert LSFs to normalize frequency domain 0..16384  */
622
623    Lsp_lsf(lsp1, lsf1, M, pOverflow);
624    Lsp_lsf(lsp2, lsf2, M, pOverflow);
625
626    /* Compute LSF weighting factors (Q13) */
627
628    Lsf_wt(lsf1, wf1, pOverflow);
629    Lsf_wt(lsf2, wf2, pOverflow);
630
631    /* Compute predicted LSF and prediction error */
632
633    p_lsf_p  = &lsf_p[0];
634    p_lsf1   = &lsf1[0];
635    p_lsf2   = &lsf2[0];
636    p_lsf_r1 = &lsf_r1[0];
637    p_lsf_r2 = &lsf_r2[0];
638
639    for (i = 0; i < M; i++)
640    {
641        *(p_lsf_p) = mean_lsf_5[i] +
642                     (((Word32)st->past_rq[i] * LSP_PRED_FAC_MR122) >> 15);
643
644        *(p_lsf_r1++) = *(p_lsf1++) - *(p_lsf_p);
645        *(p_lsf_r2++) = *(p_lsf2++) - *(p_lsf_p++);
646    }
647
648    /*---- Split-MQ of prediction error ----*/
649
650    indice[0] = Vq_subvec(&lsf_r1[0], &lsf_r2[0], dico1_lsf_5,
651                          &wf1[0], &wf2[0], DICO1_5_SIZE, pOverflow);
652
653    indice[1] = Vq_subvec(&lsf_r1[2], &lsf_r2[2], dico2_lsf_5,
654                          &wf1[2], &wf2[2], DICO2_5_SIZE, pOverflow);
655
656    indice[2] = Vq_subvec_s(&lsf_r1[4], &lsf_r2[4], dico3_lsf_5,
657                            &wf1[4], &wf2[4], DICO3_5_SIZE, pOverflow);
658
659    indice[3] = Vq_subvec(&lsf_r1[6], &lsf_r2[6], dico4_lsf_5,
660                          &wf1[6], &wf2[6], DICO4_5_SIZE, pOverflow);
661
662    indice[4] = Vq_subvec(&lsf_r1[8], &lsf_r2[8], dico5_lsf_5,
663                          &wf1[8], &wf2[8], DICO5_5_SIZE, pOverflow);
664
665    /* Compute quantized LSFs and update the past quantized residual */
666
667    p_lsf_r1 = &lsf_r1[0];
668    p_lsf_r2 = &lsf_r2[0];
669    p_lsf_p  = &lsf_p[0];
670    p_lsf1   = &lsf1_q[0];
671    p_lsf2   = &lsf2_q[0];
672
673
674    for (i = 0; i < M; i++)
675    {
676        *(p_lsf1++) = *(p_lsf_r1++) + *(p_lsf_p);
677        *(p_lsf2++) = *(p_lsf_r2) + *(p_lsf_p++);
678        st->past_rq[i] = *(p_lsf_r2++);
679    }
680
681    /* verification that LSFs has minimum distance of LSF_GAP */
682
683    Reorder_lsf(lsf1_q, LSF_GAP, M, pOverflow);
684    Reorder_lsf(lsf2_q, LSF_GAP, M, pOverflow);
685
686    /*  convert LSFs to the cosine domain */
687
688    Lsf_lsp(lsf1_q, lsp1_q, M, pOverflow);
689    Lsf_lsp(lsf2_q, lsp2_q, M, pOverflow);
690}
691
692