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/c2_11pf.c
35  Functions:
36             code_2i40_11bits
37             search_2i40
38             build_code
39 
40      Date: 01/28/2002
41 
42 ------------------------------------------------------------------------------
43  REVISION HISTORY
44 
45  Description: Modified to pass overflow flag through to basic math function.
46  The flag is passed back to the calling function by pointer reference.
47 
48  Description: Fixed tabs prior to optimization to make diff'ing easier.
49               Optimized search_2i40() to reduce clock cycle usage.
50 
51  Description: Optimized build_code() to reduce clock cycle usage.
52 
53  Description: Changed function name to pv_round to avoid conflict with
54               round function in C standard library.
55 
56  Description:  Added casting to eliminate warnings
57 
58  Description:  Replaced "int" and/or "char" with OSCL defined types.
59 
60  Description:
61 
62 ------------------------------------------------------------------------------
63  MODULE DESCRIPTION
64 
65  *************************************************************************
66  *
67  *  FUNCTION:  code_2i40_11bits()
68  *
69  *  PURPOSE:  Searches a 11 bit algebraic codebook containing 2 pulses
70  *            in a frame of 40 samples.
71  *
72  *  DESCRIPTION:
73  *    The code length is 40, containing 2 nonzero pulses: i0...i1.
74  *    All pulses can have two possible amplitudes: +1 or -1.
75  *    Pulse i0 can have 2x8=16 possible positions, pulse i1 can have
76  *    4x8=32 positions.
77  *
78  *       i0 :  1, 6, 11, 16, 21, 26, 31, 36.
79  *             3, 8, 13, 18, 23, 28, 33, 38.
80  *       i1 :  0, 5, 10, 15, 20, 25, 30, 35.
81  *             1, 6, 11, 16, 21, 26, 31, 36.
82  *             2, 7, 12, 17, 22, 27, 32, 37.
83  *             4, 9, 14, 19, 24, 29, 34, 39.
84  *
85  *************************************************************************
86 ------------------------------------------------------------------------------
87 */
88 
89 /*----------------------------------------------------------------------------
90 ; INCLUDES
91 ----------------------------------------------------------------------------*/
92 #include "c2_11pf.h"
93 #include "typedef.h"
94 #include "basic_op.h"
95 #include "inv_sqrt.h"
96 #include "cnst.h"
97 #include "cor_h.h"
98 #include "set_sign.h"
99 
100 /*----------------------------------------------------------------------------
101 ; MACROS
102 ; Define module specific macros here
103 ----------------------------------------------------------------------------*/
104 
105 /*----------------------------------------------------------------------------
106 ; DEFINES
107 ; Include all pre-processor statements here. Include conditional
108 ; compile variables also.
109 ----------------------------------------------------------------------------*/
110 #define NB_PULSE  2
111 
112 #define _1_2    (Word16)(32768L/2)
113 #define _1_4    (Word16)(32768L/4)
114 #define _1_8    (Word16)(32768L/8)
115 #define _1_16   (Word16)(32768L/16)
116 
117 /*----------------------------------------------------------------------------
118 ; LOCAL FUNCTION DEFINITIONS
119 ; Function Prototype declaration
120 ----------------------------------------------------------------------------*/
121 static void search_2i40(
122     Word16 dn[],        /* i : correlation between target and h[]            */
123     Word16 rr[][L_CODE],/* i : matrix of autocorrelation                     */
124     Word16 codvec[],    /* o : algebraic codebook vector                     */
125     Flag   * pOverflow
126 );
127 
128 static Word16 build_code(
129     Word16 codvec[],    /* i : algebraic codebook vector                     */
130     Word16 dn_sign[],   /* i : sign of dn[]                                  */
131     Word16 cod[],       /* o : algebraic (fixed) codebook excitation         */
132     Word16 h[],         /* i : impulse response of weighted synthesis filter */
133     Word16 y[],         /* o : filtered fixed codebook excitation            */
134     Word16 sign[],      /* o : sign of 2 pulses                              */
135     Flag   * pOverflow
136 );
137 
138 /*----------------------------------------------------------------------------
139 ; LOCAL VARIABLE DEFINITIONS
140 ; Variable declaration - defined here and used outside this module
141 ----------------------------------------------------------------------------*/
142 
143 const Word16 startPos1[2] = {1, 3};
144 const Word16 startPos2[4] = {0, 1, 2, 4};
145 
146 /*
147 ------------------------------------------------------------------------------
148  FUNCTION NAME: code_2i40_11bits
149 ------------------------------------------------------------------------------
150  INPUT AND OUTPUT DEFINITIONS
151 
152  Inputs:
153     x,  target vector, array of type Word16
154     h,  impulse response of weighted synthesis filter, array of type Word16
155     T0, Pitch lag, variable of type Word16
156     pitch_sharp, Last quantized pitch gain, variable of type Word16
157 
158  Outputs:
159     code[], Innovative codebook, array of type Word16
160     y[],    filtered fixed codebook excitation, array of type Word16
161     sign,   Signs of 2 pulses, pointer of type Word16 *
162     pOverflow  Flag set when overflow occurs, pointer of type Flag *
163 
164  Returns:
165     index
166 
167  Global Variables Used:
168     None
169 
170  Local Variables Needed:
171     None
172 
173 ------------------------------------------------------------------------------
174  FUNCTION DESCRIPTION
175 
176      Searches a 11 bit algebraic codebook containing 2 pulses
177      in a frame of 40 samples.
178 
179      The code length is 40, containing 2 nonzero pulses: i0...i1.
180      All pulses can have two possible amplitudes: +1 or -1.
181      Pulse i0 can have 2x8=16 possible positions, pulse i1 can have
182      4x8=32 positions.
183 
184         i0 :  1, 6, 11, 16, 21, 26, 31, 36.
185               3, 8, 13, 18, 23, 28, 33, 38.
186         i1 :  0, 5, 10, 15, 20, 25, 30, 35.
187               1, 6, 11, 16, 21, 26, 31, 36.
188               2, 7, 12, 17, 22, 27, 32, 37.
189               4, 9, 14, 19, 24, 29, 34, 39.
190 
191 ------------------------------------------------------------------------------
192  REQUIREMENTS
193 
194  None
195 
196 ------------------------------------------------------------------------------
197  REFERENCES
198 
199  c2_11pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
200 
201 ------------------------------------------------------------------------------
202  PSEUDO-CODE
203 
204 
205 ------------------------------------------------------------------------------
206  RESOURCES USED [optional]
207 
208  When the code is written for a specific target processor the
209  the resources used should be documented below.
210 
211  HEAP MEMORY USED: x bytes
212 
213  STACK MEMORY USED: x bytes
214 
215  CLOCK CYCLES: (cycle count equation for this function) + (variable
216                 used to represent cycle count for each subroutine
217                 called)
218      where: (cycle count variable) = cycle count for [subroutine
219                                      name]
220 
221 ------------------------------------------------------------------------------
222  CAUTION [optional]
223  [State any special notes, constraints or cautions for users of this function]
224 
225 ------------------------------------------------------------------------------
226 */
code_2i40_11bits(Word16 x[],Word16 h[],Word16 T0,Word16 pitch_sharp,Word16 code[],Word16 y[],Word16 * sign,Flag * pOverflow)227 Word16 code_2i40_11bits(
228     Word16 x[],         /* i : target vector                                 */
229     Word16 h[],         /* i : impulse response of weighted synthesis filter */
230     /*     h[-L_subfr..-1] must be set to zero.          */
231     Word16 T0,          /* i : Pitch lag                                     */
232     Word16 pitch_sharp, /* i : Last quantized pitch gain                     */
233     Word16 code[],      /* o : Innovative codebook                           */
234     Word16 y[],         /* o : filtered fixed codebook excitation            */
235     Word16 * sign,      /* o : Signs of 2 pulses                             */
236     Flag   * pOverflow  /* o : Flag set when overflow occurs                 */
237 )
238 {
239     Word16 codvec[NB_PULSE];
240     Word16 dn[L_CODE];
241     Word16 dn2[L_CODE];
242     Word16 dn_sign[L_CODE];
243 
244     Word16 rr[L_CODE][L_CODE];
245 
246     Word16 i;
247     Word16 index;
248     Word16 sharp;
249     Word16 tempWord;
250 
251     sharp = pitch_sharp << 1;
252 
253     if (T0 < L_CODE)
254     {
255         for (i = T0; i < L_CODE; i++)
256         {
257             tempWord =
258                 mult(
259                     h[i - T0],
260                     sharp,
261                     pOverflow);
262 
263             h[i] =
264                 add(
265                     h[i],
266                     tempWord,
267                     pOverflow);
268         }
269 
270     }
271 
272     cor_h_x(
273         h,
274         x,
275         dn,
276         1,
277         pOverflow);
278 
279     set_sign(
280         dn,
281         dn_sign,
282         dn2,
283         8); /* dn2[] not used in this codebook search */
284 
285     cor_h(
286         h,
287         dn_sign,
288         rr,
289         pOverflow);
290 
291     search_2i40(
292         dn,
293         rr,
294         codvec,
295         pOverflow);
296 
297     /* function result */
298 
299     index =
300         build_code(
301             codvec,
302             dn_sign,
303             code,
304             h,
305             y,
306             sign,
307             pOverflow);
308 
309     /*
310     * Compute innovation vector gain.
311     * Include fixed-gain pitch contribution into code[].
312     */
313 
314     if (T0 < L_CODE)
315     {
316         for (i = T0; i < L_CODE; i++)
317         {
318             tempWord =
319                 mult(
320                     code[i - T0],
321                     sharp,
322                     pOverflow);
323 
324             code[i] =
325                 add(
326                     code[i],
327                     tempWord,
328                     pOverflow);
329         }
330     }
331 
332     return index;
333 }
334 
335 /****************************************************************************/
336 
337 
338 /*
339 ------------------------------------------------------------------------------
340  FUNCTION NAME: search_2i40
341 ------------------------------------------------------------------------------
342  INPUT AND OUTPUT DEFINITIONS
343 
344  Inputs:
345     dn, correlation between target and h[], array of type Word16
346     rr, matrix of autocorrelation, double-array of type Word16
347 
348  Outputs:
349     codvec[],  algebraic codebook vector, array of type Word16
350     pOverflow, Flag set when overflow occurs, pointer of type Flag *
351 
352  Returns:
353     None
354 
355  Global Variables Used:
356     None
357 
358  Local Variables Needed:
359     None
360 
361 ------------------------------------------------------------------------------
362  FUNCTION DESCRIPTION
363 
364  Search the best codevector; determine positions of the 2 pulses
365  in the 40-sample frame.
366 
367 ------------------------------------------------------------------------------
368  REQUIREMENTS
369 
370  None
371 
372 ------------------------------------------------------------------------------
373  REFERENCES
374 
375  c2_11pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
376 
377 ------------------------------------------------------------------------------
378  PSEUDO-CODE
379 
380 
381 ------------------------------------------------------------------------------
382  RESOURCES USED [optional]
383 
384  When the code is written for a specific target processor the
385  the resources used should be documented below.
386 
387  HEAP MEMORY USED: x bytes
388 
389  STACK MEMORY USED: x bytes
390 
391  CLOCK CYCLES: (cycle count equation for this function) + (variable
392                 used to represent cycle count for each subroutine
393                 called)
394      where: (cycle count variable) = cycle count for [subroutine
395                                      name]
396 
397 ------------------------------------------------------------------------------
398  CAUTION [optional]
399  [State any special notes, constraints or cautions for users of this function]
400 
401 ------------------------------------------------------------------------------
402 */
403 
search_2i40(Word16 dn[],Word16 rr[][L_CODE],Word16 codvec[],Flag * pOverflow)404 static void search_2i40(
405     Word16 dn[],         /* i : correlation between target and h[] */
406     Word16 rr[][L_CODE], /* i : matrix of autocorrelation          */
407     Word16 codvec[],     /* o : algebraic codebook vector          */
408     Flag   * pOverflow   /* o : Flag set when overflow occurs      */
409 )
410 {
411     Word16 i0;
412     Word16 i1;
413     Word16 ix = 0; /* initialization only needed to keep gcc silent */
414     Word16 track1;
415     Word16 track2;
416     Word16 ipos[NB_PULSE];
417 
418     Word16 psk;
419     Word16 ps0;
420     Word16 ps1;
421     Word16 sq;
422     Word16 sq1;
423 
424     Word16 alpk;
425     Word16 alp;
426     Word16 alp_16;
427 
428     Word32 s;
429     Word32 alp0;
430     Word32 alp1;
431 
432     Word16 i;
433     Word16 *p_codvec = &codvec[0];
434 
435     psk = -1;
436     alpk = 1;
437 
438     for (i = 0; i < NB_PULSE; i++)
439     {
440         *(p_codvec++) = i;
441     }
442 
443     /*------------------------------------------------------------------*
444     * main loop: try 2x4  tracks.                                      *
445     *------------------------------------------------------------------*/
446 
447     for (track1 = 0; track1 < 2; track1++)
448     {
449         for (track2 = 0; track2 < 4; track2++)
450         {
451             /* fix starting position */
452             ipos[0] = startPos1[track1];
453             ipos[1] = startPos2[track2];
454 
455             /*----------------------------------------------------------------*
456             * i0 loop: try 8 positions.                                      *
457             *----------------------------------------------------------------*/
458             for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP)
459             {
460                 ps0 = dn[i0];
461 
462                 /* alp0 = L_mult(rr[i0][i0], _1_4, pOverflow); */
463                 alp0 = (Word32) rr[i0][i0] << 14;
464 
465                 /*-------------------------------------------------------------*
466                 * i1 loop: 8 positions.                                       *
467                 *-------------------------------------------------------------*/
468 
469                 sq = -1;
470                 alp = 1;
471                 ix = ipos[1];
472 
473                 /*---------------------------------------------------------------*
474                 * These index have low complexity address computation because   *
475                 * they are, in fact, pointers with fixed increment. For example,*
476                 * "rr[i0][i2]" is a pointer initialized to "&rr[i0][ipos[2]]"   *
477                 * and incremented by "STEP".                                    *
478                 *---------------------------------------------------------------*/
479 
480                 for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP)
481                 {
482                     /* idx increment = STEP */
483                     ps1 = add(ps0, dn[i1], pOverflow);
484 
485                     /* alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1]; */
486 
487                     /* idx incr = STEP */
488                     /* alp1 = L_mac(alp0, rr[i1][i1], _1_4, pOverflow); */
489                     alp1 = alp0 + ((Word32) rr[i1][i1] << 14);
490 
491                     /* idx incr = STEP */
492                     /* alp1 = L_mac(alp1, rr[i0][i1], _1_2, pOverflow); */
493                     alp1 += (Word32) rr[i0][i1] << 15;
494 
495                     /* sq1 = mult(ps1, ps1, pOverflow); */
496                     sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
497 
498                     /* alp_16 = pv_round(alp1, pOverflow); */
499                     alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
500 
501                     /* s = L_mult(alp, sq1, pOverflow); */
502                     s = ((Word32) alp * sq1) << 1;
503 
504                     /* s =L_msu(s, sq, alp_16, pOverflow); */
505                     s -= (((Word32) sq * alp_16) << 1);
506 
507                     if (s > 0)
508                     {
509                         sq = sq1;
510                         alp = alp_16;
511                         ix = i1;
512                     }
513 
514                 } /* for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP) */
515 
516                 /* memorize codevector if this one is better than the last one. */
517 
518                 /* s = L_mult(alpk, sq, pOverflow); */
519                 s = ((Word32) alpk * sq) << 1;
520 
521                 /* s = L_msu(s, psk, alp, pOverflow); */
522                 s -= (((Word32) psk * alp) << 1);
523 
524                 if (s > 0)
525                 {
526                     psk = sq;
527                     alpk = alp;
528                     p_codvec = &codvec[0];
529 
530                     *(p_codvec++) = i0;
531                     *(p_codvec) = ix;
532                 }
533 
534             } /* for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP) */
535 
536         } /* for (track2 = 0; track2 < 4; track2++) */
537 
538     } /* for (track1 = 0; track1 < 2; track1++) */
539 
540     return;
541 
542 } /* search_2i40 */
543 
544 /****************************************************************************/
545 
546 
547 /*
548 ------------------------------------------------------------------------------
549  FUNCTION NAME: build_code
550 ------------------------------------------------------------------------------
551  INPUT AND OUTPUT DEFINITIONS
552 
553  Inputs:
554     codvec,  position of pulses, array of type Word16
555     dn_sign, sign of pulses, array of type Word16
556     h,       impulse response of weighted synthesis filter, Word16 array
557 
558  Outputs:
559 
560     cod,       innovative code vector, array of type Word16
561     y[],       filtered innovative code, array of type Word16
562     sign[],    sign of 2 pulses, array of type Word16
563     pOverflow, Flag set when overflow occurs, pointer of type Flag *
564 
565  Returns:
566 
567  Global Variables Used:
568     None
569 
570  Local Variables Needed:
571     None
572 
573 ------------------------------------------------------------------------------
574  FUNCTION DESCRIPTION
575 
576  Builds the codeword, the filtered codeword and index of the
577  codevector, based on the signs and positions of 2 pulses.
578 
579 ------------------------------------------------------------------------------
580  REQUIREMENTS
581 
582  None
583 
584 ------------------------------------------------------------------------------
585  REFERENCES
586 
587  c2_11pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
588 
589 ------------------------------------------------------------------------------
590  PSEUDO-CODE
591 
592 ------------------------------------------------------------------------------
593  RESOURCES USED [optional]
594 
595  When the code is written for a specific target processor the
596  the resources used should be documented below.
597 
598  HEAP MEMORY USED: x bytes
599 
600  STACK MEMORY USED: x bytes
601 
602  CLOCK CYCLES: (cycle count equation for this function) + (variable
603                 used to represent cycle count for each subroutine
604                 called)
605      where: (cycle count variable) = cycle count for [subroutine
606                                      name]
607 
608 ------------------------------------------------------------------------------
609  CAUTION [optional]
610  [State any special notes, constraints or cautions for users of this function]
611 
612 ------------------------------------------------------------------------------
613 */
build_code(Word16 codvec[],Word16 dn_sign[],Word16 cod[],Word16 h[],Word16 y[],Word16 sign[],Flag * pOverflow)614 static Word16 build_code(
615     Word16 codvec[],    /* i : position of pulses                            */
616     Word16 dn_sign[],   /* i : sign of pulses                                */
617     Word16 cod[],       /* o : innovative code vector                        */
618     Word16 h[],         /* i : impulse response of weighted synthesis filter */
619     Word16 y[],         /* o : filtered innovative code                      */
620     Word16 sign[],      /* o : sign of 2 pulses                              */
621     Flag   * pOverflow  /* o : Flag set when overflow occurs                 */
622 )
623 {
624     Word16 i;
625     Word16 j;
626     Word16 k;
627     Word16 track;
628     Word16 index;
629     Word16 _sign[NB_PULSE];
630     Word16 indx;
631     Word16 rsign;
632     Word16 tempWord;
633 
634     Word16 *p0;
635     Word16 *p1;
636 
637     Word32 s;
638 
639     for (i = 0; i < L_CODE; i++)
640     {
641         cod[i] = 0;
642     }
643 
644     indx = 0;
645     rsign = 0;
646 
647     for (k = 0; k < NB_PULSE; k++)
648     {
649         i = codvec[k];      /* read pulse position */
650         j = dn_sign[i];     /* read sign           */
651 
652         /* index = pos/5 */
653         /* index = mult(i, 6554, pOverflow); */
654         index = (Word16)(((Word32) i * 6554) >> 15);
655 
656         /* track = pos%5 */
657         /* tempWord =
658             L_mult(
659             index,
660             5,
661             pOverflow); */
662         tempWord = ((Word32) index * 5) << 1;
663 
664         /* tempWord =
665             L_shr(
666             tempWord,
667             1,
668             pOverflow); */
669         tempWord >>= 1;
670 
671 
672         /* track =
673             sub(
674             i,
675             tempWord,
676             pOverflow); */
677         track = i - tempWord;
678 
679         tempWord = track;
680 
681         if (tempWord == 0)
682         {
683             track = 1;
684 
685             /* index =
686                 shl(
687                 index,
688                 6,
689                 pOverflow); */
690             index <<= 6;
691         }
692         else if (track == 1)
693         {
694             tempWord = k;
695 
696             if (tempWord == 0)
697             {
698                 track = 0;
699                 /* index =
700                     shl(
701                     index,
702                     1,
703                     pOverflow); */
704                 index <<= 1;
705             }
706             else
707             {
708                 track = 1;
709 
710                 /* tempWord =
711                     shl(
712                     index,
713                     6,
714                     pOverflow); */
715                 tempWord = index << 6;
716 
717                 /* index =
718                     add(
719                     tempWord,
720                     16,
721                     pOverflow); */
722                 index = tempWord + 16;
723             }
724         }
725         else if (track == 2)
726         {
727             track = 1;
728 
729             /* tempWord =
730                 shl(
731                 index,
732                 6,
733                 pOverflow); */
734             tempWord = index << 6;
735 
736             /* index =
737                 add(
738                 tempWord,
739                 32,
740                 pOverflow); */
741             index = tempWord + 32;
742         }
743         else if (track == 3)
744         {
745             track = 0;
746 
747             /* tempWord =
748                 shl(
749                 index,
750                 1,
751                 pOverflow); */
752             tempWord = index << 1;
753 
754             /* index =
755                 add(
756                 tempWord,
757                 1,
758                 pOverflow); */
759             index = tempWord + 1;
760         }
761         else if (track == 4)
762         {
763             track = 1;
764 
765             /* tempWord =
766                 shl(
767                 index,
768                 6,
769                 pOverflow); */
770             tempWord = index << 6;
771 
772             /* index =
773                 add(
774                 tempWord,
775                 48,
776                 pOverflow); */
777             index = tempWord + 48;
778         }
779 
780         if (j > 0)
781         {
782             cod[i] = 8191;
783             _sign[k] = 32767;
784 
785             tempWord =
786                 shl(
787                     1,
788                     track,
789                     pOverflow);
790 
791             rsign =
792                 add(
793                     rsign,
794                     tempWord,
795                     pOverflow);
796         }
797         else
798         {
799             cod[i] = -8192;
800             _sign[k] = (Word16) - 32768L;
801         }
802 
803         indx =
804             add(
805                 indx,
806                 index,
807                 pOverflow);
808     }
809     *sign = rsign;
810 
811     p0 = h - codvec[0];
812     p1 = h - codvec[1];
813 
814     for (i = 0; i < L_CODE; i++)
815     {
816         s = 0;
817 
818         s =
819             L_mac(
820                 s,
821                 *p0++,
822                 _sign[0],
823                 pOverflow);
824 
825         s =
826             L_mac(
827                 s,
828                 *p1++,
829                 _sign[1],
830                 pOverflow);
831 
832         y[i] =
833             pv_round(
834                 s,
835                 pOverflow);
836     }
837 
838     return indx;
839 }
840 
841 
842