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 
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 
153 void 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 
q_p(Word16 * pInd,Word16 n)199 void 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
262 static 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 ----------------------------------------------------------------------------*/
build_code(Word16 codvec[],Word16 sign[],Word16 cod[],Word16 h[],Word16 y[],Word16 indx[],Flag * pOverflow)399 static 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
592 void 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 ----------------------------------------------------------------------------*/
code_10i40_35bits(Word16 x[],Word16 cn[],Word16 h[],Word16 cod[],Word16 y[],Word16 indx[],Flag * pOverflow)647 void 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