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
32
33
34 Pathname: ./audio/gsm-amr/c/src/c1035pf.c
35 Functions: q_p
36            build_code
37            code_10i40_35bits
38
39
40     Date: 09/28/2000
41
42------------------------------------------------------------------------------
43 REVISION HISTORY
44
45 Description: Updated template. Cleaned up code. Passing in a pointer to
46              overflow flag for build_code() and code_10i40_35bits() functions.
47              Removed unnecessary header files.
48
49 Description:
50              1. Eliminated unused include files.
51              2. Replaced array addressing by pointers
52              3. Eliminated math operations that unnecessary checked for
53                 saturation
54              4. Replaced for-loops with memset()
55
56 Description: Changed function name to pv_round to avoid conflict with
57              round function in C standard library.
58
59 Description:  Replaced OSCL mem type functions and eliminated include
60               files that now are chosen by OSCL definitions
61
62 Description:  Replaced "int" and/or "char" with OSCL defined types.
63
64 Description:
65
66------------------------------------------------------------------------------
67 MODULE DESCRIPTION
68
69 This file contains the function that searches a 35 bit algebraic codebook
70 containing 10 pulses in a frame of 40 samples.
71
72------------------------------------------------------------------------------
73*/
74
75/*----------------------------------------------------------------------------
76; INCLUDES
77----------------------------------------------------------------------------*/
78#include <string.h>
79
80#include "c1035pf.h"
81#include "cnst.h"
82#include "basic_op.h"
83#include "inv_sqrt.h"
84#include "set_sign.h"
85#include "cor_h.h"
86#include "cor_h_x.h"
87#include "s10_8pf.h"
88
89/*----------------------------------------------------------------------------
90; MACROS
91; [Define module specific macros here]
92----------------------------------------------------------------------------*/
93
94
95/*----------------------------------------------------------------------------
96; DEFINES
97; [Include all pre-processor statements here. Include conditional
98; compile variables also.]
99----------------------------------------------------------------------------*/
100#define NB_PULSE  10
101
102/*----------------------------------------------------------------------------
103; LOCAL FUNCTION DEFINITIONS
104; [List function prototypes here]
105----------------------------------------------------------------------------*/
106
107/*----------------------------------------------------------------------------
108; LOCAL VARIABLE DEFINITIONS
109; [Variable declaration - defined here and used outside this module]
110----------------------------------------------------------------------------*/
111
112/*
113------------------------------------------------------------------------------
114 FUNCTION NAME: q_p
115------------------------------------------------------------------------------
116 INPUT AND OUTPUT DEFINITIONS
117
118 Inputs:
119    pShift_reg = pointer to Old CN generator shift register state (Word32)
120    no_bits = Number of bits (Word16)
121
122 Outputs:
123    pShift_reg -> Updated CN generator shift register state
124
125 Returns:
126    noise_bits = Generated random integer value (Word16)
127
128 Global Variables Used:
129    None
130
131 Local Variables Needed:
132    None
133
134------------------------------------------------------------------------------
135 FUNCTION DESCRIPTION
136
137 This is a local function that determnes the index of the pulses by looking up
138 the gray encoder table
139
140------------------------------------------------------------------------------
141 REQUIREMENTS
142
143 None
144
145------------------------------------------------------------------------------
146 REFERENCES
147
148 c1035pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
149
150------------------------------------------------------------------------------
151 PSEUDO-CODE
152
153void q_p (
154    Word16 *ind,        // Pulse position
155    Word16 n            // Pulse number
156)
157{
158    Word16 tmp;
159
160    tmp = *ind;
161
162    if (sub (n, 5) < 0)
163    {
164        *ind = (tmp & 0x8) | gray[tmp & 0x7];
165    }
166    else
167    {
168        *ind = gray[tmp & 0x7];
169    }
170}
171
172------------------------------------------------------------------------------
173 RESOURCES USED [optional]
174
175 When the code is written for a specific target processor the
176 the resources used should be documented below.
177
178 HEAP MEMORY USED: x bytes
179
180 STACK MEMORY USED: x bytes
181
182 CLOCK CYCLES: (cycle count equation for this function) + (variable
183                used to represent cycle count for each subroutine
184                called)
185     where: (cycle count variable) = cycle count for [subroutine
186                                     name]
187
188------------------------------------------------------------------------------
189 CAUTION [optional]
190 [State any special notes, constraints or cautions for users of this function]
191
192------------------------------------------------------------------------------
193*/
194
195/*----------------------------------------------------------------------------
196; FUNCTION CODE
197----------------------------------------------------------------------------*/
198
199void q_p(
200    Word16 *pInd,       /* Pulse position */
201    Word16 n            /* Pulse number   */
202)
203{
204    Word16 tmp;
205
206    tmp = *pInd;
207
208    if (n < 5)
209    {
210        *pInd = (tmp & 0x8) | gray[tmp & 0x7];
211    }
212    else
213    {
214        *pInd = gray[tmp & 0x7];
215    }
216}
217
218/*
219------------------------------------------------------------------------------
220 FUNCTION NAME: build_code
221------------------------------------------------------------------------------
222 INPUT AND OUTPUT DEFINITIONS
223
224 Inputs:
225    pSeed = pointer to the Old CN generator shift register state (Word32)
226    n_param = Number of parameters to randomize (Word16)
227    param_size_table = table holding paameter sizes (Word16)
228    param[] = array to hold CN generated paramters (Word16)
229    pOverflow = pointer to overflow flag (Flag)
230
231 Outputs:
232    param[] = CN generated parameters (Word16)
233    pSeed = Updated CN generator shift register state (Word16)
234    pOverflow -> 1 if overflow occured
235
236 Returns:
237    None
238
239 Global Variables Used:
240    None
241
242 Local Variables Needed:
243    None
244
245------------------------------------------------------------------------------
246 FUNCTION DESCRIPTION
247
248 This function builds the codeword, the filtered codeword and index of the
249 codevector, based on the signs and positions of 10 pulses.
250------------------------------------------------------------------------------
251 REQUIREMENTS
252
253 None
254
255------------------------------------------------------------------------------
256 REFERENCES
257
258 c1035pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
259
260------------------------------------------------------------------------------
261 PSEUDO-CODE
262static void build_code (
263    Word16 codvec[],    // (i)  : position of pulses
264    Word16 sign[],      // (i)  : sign of d[n]
265    Word16 cod[],       // (o)  : innovative code vector
266    Word16 h[],         // (i)  : impulse response of weighted synthesis filter
267    Word16 y[],         // (o)  : filtered innovative code
268    Word16 indx[]       // (o)  : index of 10 pulses (sign+position)
269)
270{
271    Word16 i, j, k, track, index, _sign[NB_PULSE];
272    Word16 *p0, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9;
273    Word32 s;
274
275    for (i = 0; i < L_CODE; i++)
276    {
277        cod[i] = 0;
278    }
279    for (i = 0; i < NB_TRACK; i++)
280    {
281        indx[i] = -1;
282    }
283
284    for (k = 0; k < NB_PULSE; k++)
285    {
286        // read pulse position
287        i = codvec[k];
288        // read sign
289        j = sign[i];
290
291        index = mult (i, 6554);                  // index = pos/5
292        // track = pos%5
293        track = sub (i, extract_l (L_shr (L_mult (index, 5), 1)));
294
295        if (j > 0)
296        {
297            cod[i] = add (cod[i], 4096);
298            _sign[k] = 8192;
299
300        }
301        else
302        {
303            cod[i] = sub (cod[i], 4096);
304            _sign[k] = -8192;
305            index = add (index, 8);
306        }
307
308        if (indx[track] < 0)
309        {
310            indx[track] = index;
311        }
312        else
313        {
314            if (((index ^ indx[track]) & 8) == 0)
315            {
316                // sign of 1st pulse == sign of 2nd pulse
317
318                if (sub (indx[track], index) <= 0)
319                {
320                    indx[track + 5] = index;
321                }
322                else
323                {
324                    indx[track + 5] = indx[track];
325                    indx[track] = index;
326                }
327            }
328            else
329            {
330                // sign of 1st pulse != sign of 2nd pulse
331
332                if (sub ((Word16)(indx[track] & 7), (Word16)(index & 7)) <= 0)
333                {
334                    indx[track + 5] = indx[track];
335                    indx[track] = index;
336                }
337                else
338                {
339                    indx[track + 5] = index;
340                }
341            }
342        }
343    }
344
345    p0 = h - codvec[0];
346    p1 = h - codvec[1];
347    p2 = h - codvec[2];
348    p3 = h - codvec[3];
349    p4 = h - codvec[4];
350    p5 = h - codvec[5];
351    p6 = h - codvec[6];
352    p7 = h - codvec[7];
353    p8 = h - codvec[8];
354    p9 = h - codvec[9];
355
356    for (i = 0; i < L_CODE; i++)
357    {
358        s = 0;
359        s = L_mac (s, *p0++, _sign[0]);
360        s = L_mac (s, *p1++, _sign[1]);
361        s = L_mac (s, *p2++, _sign[2]);
362        s = L_mac (s, *p3++, _sign[3]);
363        s = L_mac (s, *p4++, _sign[4]);
364        s = L_mac (s, *p5++, _sign[5]);
365        s = L_mac (s, *p6++, _sign[6]);
366        s = L_mac (s, *p7++, _sign[7]);
367        s = L_mac (s, *p8++, _sign[8]);
368        s = L_mac (s, *p9++, _sign[9]);
369        y[i] = pv_round (s);
370    }
371}
372
373------------------------------------------------------------------------------
374 RESOURCES USED [optional]
375
376 When the code is written for a specific target processor the
377 the resources used should be documented below.
378
379 HEAP MEMORY USED: x bytes
380
381 STACK MEMORY USED: x bytes
382
383 CLOCK CYCLES: (cycle count equation for this function) + (variable
384                used to represent cycle count for each subroutine
385                called)
386     where: (cycle count variable) = cycle count for [subroutine
387                                     name]
388
389------------------------------------------------------------------------------
390 CAUTION [optional]
391 [State any special notes, constraints or cautions for users of this function]
392
393------------------------------------------------------------------------------
394*/
395
396/*----------------------------------------------------------------------------
397; FUNCTION CODE
398----------------------------------------------------------------------------*/
399static void build_code(
400    Word16 codvec[],    /* (i)  : position of pulses                        */
401    Word16 sign[],      /* (i)  : sign of d[n]                              */
402    Word16 cod[],       /* (o)  : innovative code vector                    */
403    Word16 h[],         /* (i)  : impulse response of weighted synthesis filter*/
404    Word16 y[],         /* (o)  : filtered innovative code                  */
405    Word16 indx[],      /* (o)  : index of 10 pulses (sign+position)        */
406    Flag   *pOverflow   /* i/o  : overflow Flag                             */
407)
408{
409    Word16 i, k, track, index, _sign[NB_PULSE];
410    Word16 *p0, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9;
411    Word32 s;
412    Word16 temp;
413    Word16 *p__sign;
414    Word16 *p_y;
415    Word16 *p_codvec;
416
417    OSCL_UNUSED_ARG(pOverflow);
418
419    memset(cod, 0, L_CODE*sizeof(*cod));
420    memset(indx, 0xFF, NB_TRACK*sizeof(*indx));
421
422    p__sign = _sign;
423
424    p0 = &codvec[0];
425
426    for (k = 0; k < NB_PULSE; k++)
427    {
428        /* read pulse position */
429        i = *(p0++);
430        /* read sign           */
431
432        index = ((Word32)i * 6554) >> 15;       /* index = pos/5    */
433
434        /* track = pos%5 */
435        /* track = sub (i, extract_l (L_shr (L_mult (index, 5), 1))); */
436        track = i - (index * 5);
437
438        if (sign[i] > 0)
439        {
440            cod[i] +=  4096;
441            *(p__sign++) = 8192;
442
443        }
444        else
445        {
446            cod[i] -=  4096;
447            *(p__sign++) = -8192;
448            /* index = add (index, 8); */
449            index += 8;
450        }
451
452        p1 = &indx[track];
453
454        temp = *p1;
455
456        if (temp < 0)
457        {
458            *p1 = index;
459        }
460        else
461        {
462            if (((index ^ temp) & 8) == 0)
463            {
464                /* sign of 1st pulse == sign of 2nd pulse */
465
466                /* if (sub (indx[track], index) <= 0) */
467                if (temp <= index)
468                {
469                    *(p1 + 5) = index;
470                }
471                else
472                {
473                    *(p1 + 5) = temp;
474                    *p1 = index;
475                }
476            }
477            else
478            {
479                /* sign of 1st pulse != sign of 2nd pulse */
480
481                /* if (sub ((Word16)(indx[track] & 7), (Word16)(index & 7)) <= 0) */
482                if ((temp & 7) <= (index & 7))
483                {
484                    *(p1 + 5) = temp;
485                    *p1 = index;
486                }
487                else
488                {
489                    *(p1 + 5) = index;
490                }
491            }
492        }
493    }
494
495    p_codvec = &codvec[0];
496
497    p0 = h - *(p_codvec++);
498    p1 = h - *(p_codvec++);
499    p2 = h - *(p_codvec++);
500    p3 = h - *(p_codvec++);
501    p4 = h - *(p_codvec++);
502    p5 = h - *(p_codvec++);
503    p6 = h - *(p_codvec++);
504    p7 = h - *(p_codvec++);
505    p8 = h - *(p_codvec++);
506    p9 = h - *(p_codvec++);
507
508    p_y = y;
509
510    for (i = L_CODE; i != 0; i--)
511    {
512        p__sign = _sign;
513
514        s  = (*p0++ * *(p__sign++)) >> 7;
515        s += (*p1++ * *(p__sign++)) >> 7;
516        s += (*p2++ * *(p__sign++)) >> 7;
517        s += (*p3++ * *(p__sign++)) >> 7;
518        s += (*p4++ * *(p__sign++)) >> 7;
519        s += (*p5++ * *(p__sign++)) >> 7;
520        s += (*p6++ * *(p__sign++)) >> 7;
521        s += (*p7++ * *(p__sign++)) >> 7;
522        s += (*p8++ * *(p__sign++)) >> 7;
523        s += (*p9++ * *(p__sign++)) >> 7;
524
525        *(p_y++) = (s + 0x080) >> 8;
526    }
527
528}
529
530/*
531------------------------------------------------------------------------------
532 FUNCTION NAME: code_10i40_35bits
533------------------------------------------------------------------------------
534 INPUT AND OUTPUT DEFINITIONS
535
536 Inputs:
537    pSeed = pointer to the Old CN generator shift register state (Word32)
538    n_param = Number of parameters to randomize (Word16)
539    param_size_table = table holding paameter sizes (Word16)
540    param[] = array to hold CN generated paramters (Word16)
541    pOverflow = pointer to overflow flag (Flag)
542
543 Outputs:
544    param[] = CN generated parameters (Word16)
545    pSeed = Updated CN generator shift register state (Word16)
546    pOverflow -> 1 if overflow occured
547
548 Returns:
549    None
550
551 Global Variables Used:
552    None
553
554 Local Variables Needed:
555    None
556
557------------------------------------------------------------------------------
558 FUNCTION DESCRIPTION
559
560 This function searches a 35 bit algebraic codebook containing 10 pulses in a
561 frame of 40 samples.
562
563 The code contains 10 nonzero pulses: i0...i9.
564 All pulses can have two possible amplitudes: +1 or -1.
565 The 40 positions in a subframe are divided into 5 tracks of
566 interleaved positions. Each track contains two pulses.
567 The pulses can have the following possible positions:
568
569    i0, i5 :  0, 5, 10, 15, 20, 25, 30, 35.
570    i1, i6 :  1, 6, 11, 16, 21, 26, 31, 36.
571    i2, i7 :  2, 7, 12, 17, 22, 27, 32, 37.
572    i3, i8 :  3, 8, 13, 18, 23, 28, 33, 38.
573    i4, i9 :  4, 9, 14, 19, 24, 29, 34, 39.
574
575 Each pair of pulses require 1 bit for their signs and 6 bits for their
576 positions (3 bits + 3 bits). This results in a 35 bit codebook.
577 The function determines the optimal pulse signs and positions, builds
578 the codevector, and computes the filtered codevector.
579
580------------------------------------------------------------------------------
581 REQUIREMENTS
582
583 None
584
585------------------------------------------------------------------------------
586 REFERENCES
587
588 c1035pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
589
590------------------------------------------------------------------------------
591 PSEUDO-CODE
592void code_10i40_35bits (
593    Word16 x[],   // (i)   : target vector
594    Word16 cn[],  // (i)   : residual after long term prediction
595    Word16 h[],   // (i)   : impulse response of weighted synthesis filter
596                           // h[-L_subfr..-1] must be set to zero
597    Word16 cod[], // (o)   : algebraic (fixed) codebook excitation
598    Word16 y[],   // (o)   : filtered fixed codebook excitation
599    Word16 indx[] // (o)   : index of 10 pulses (sign + position)
600)
601{
602    Word16 ipos[NB_PULSE], pos_max[NB_TRACK], codvec[NB_PULSE];
603    Word16 dn[L_CODE], sign[L_CODE];
604    Word16 rr[L_CODE][L_CODE], i;
605
606    cor_h_x (h, x, dn, 2);
607    set_sign12k2 (dn, cn, sign, pos_max, NB_TRACK, ipos, STEP);
608    cor_h (h, sign, rr);
609
610    search_10and8i40 (NB_PULSE, STEP, NB_TRACK,
611                      dn, rr, ipos, pos_max, codvec);
612
613    build_code (codvec, sign, cod, h, y, indx);
614    for (i = 0; i < 10; i++)
615    {
616        q_p (&indx[i], i);
617    }
618    return;
619}
620
621------------------------------------------------------------------------------
622 RESOURCES USED [optional]
623
624 When the code is written for a specific target processor the
625 the resources used should be documented below.
626
627 HEAP MEMORY USED: x bytes
628
629 STACK MEMORY USED: x bytes
630
631 CLOCK CYCLES: (cycle count equation for this function) + (variable
632                used to represent cycle count for each subroutine
633                called)
634     where: (cycle count variable) = cycle count for [subroutine
635                                     name]
636
637------------------------------------------------------------------------------
638 CAUTION [optional]
639 [State any special notes, constraints or cautions for users of this function]
640
641------------------------------------------------------------------------------
642*/
643
644/*----------------------------------------------------------------------------
645; FUNCTION CODE
646----------------------------------------------------------------------------*/
647void code_10i40_35bits(
648    Word16 x[],     /* (i)   : target vector                                */
649    Word16 cn[],    /* (i)   : residual after long term prediction          */
650    Word16 h[],     /* (i)   : impulse response of weighted synthesis filter
651                             h[-L_subfr..-1] must be set to zero            */
652    Word16 cod[],   /* (o)   : algebraic (fixed) codebook excitation        */
653    Word16 y[],     /* (o)   : filtered fixed codebook excitation           */
654    Word16 indx[],  /* (o)   : index of 10 pulses (sign + position)         */
655    Flag *pOverflow /* (i/o) : overflow Flag                                */
656)
657{
658    Word16 ipos[NB_PULSE], pos_max[NB_TRACK], codvec[NB_PULSE];
659    Word16 dn[L_CODE], sign[L_CODE];
660    Word16 rr[L_CODE][L_CODE], i;
661
662    cor_h_x(h, x, dn, 2, pOverflow);
663    set_sign12k2(dn, cn, sign, pos_max, NB_TRACK, ipos, STEP, pOverflow);
664    cor_h(h, sign, rr, pOverflow);
665
666    search_10and8i40(NB_PULSE, STEP, NB_TRACK,
667                     dn, rr, ipos, pos_max, codvec, pOverflow);
668
669    build_code(codvec, sign, cod, h, y, indx, pOverflow);
670    for (i = 0; i < 10; i++)
671    {
672        q_p(&indx[i], i);
673    }
674    return;
675}
676
677