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/b_cn_cod.c
35  Functions: pseudonoise
36             build_CN_code
37             build_CN_param
38 
39      Date: 09/28/2000
40 
41 ------------------------------------------------------------------------------
42  REVISION HISTORY
43 
44  Description: Updated template. Cleaned up code. Passing in a pointer to
45               overflow flag for build_CN_code() and build_CN_param() functions.
46               Removed unnecessary header files.
47  Description: Make chnages per formal review. Fix error introduced during
48               optimization in pseudonoise().
49 
50  Description:
51 
52 ------------------------------------------------------------------------------
53  MODULE DESCRIPTION
54 
55  This module contains functions for comfort noise(CN) generation.
56 
57 ------------------------------------------------------------------------------
58 */
59 
60 
61 /*----------------------------------------------------------------------------
62 ; INCLUDES
63 ----------------------------------------------------------------------------*/
64 #include "b_cn_cod.h"
65 #include "basic_op.h"
66 #include "cnst.h"
67 
68 /*----------------------------------------------------------------------------
69 ; MACROS
70 ; [Define module specific macros here]
71 ----------------------------------------------------------------------------*/
72 
73 
74 /*----------------------------------------------------------------------------
75 ; DEFINES
76 ; [Include all pre-processor statements here. Include conditional
77 ; compile variables also.]
78 ----------------------------------------------------------------------------*/
79 #define  NB_PULSE 10        /* number of random pulses in DTX operation   */
80 
81 /*----------------------------------------------------------------------------
82 ; LOCAL FUNCTION DEFINITIONS
83 ; [List function prototypes here]
84 ----------------------------------------------------------------------------*/
85 
86 /*----------------------------------------------------------------------------
87 ; LOCAL VARIABLE DEFINITIONS
88 ; [Variable declaration - defined here and used outside this module]
89 ----------------------------------------------------------------------------*/
90 
91 /*
92 ------------------------------------------------------------------------------
93  FUNCTION NAME: pseudonoise
94 ------------------------------------------------------------------------------
95  INPUT AND OUTPUT DEFINITIONS
96 
97  Inputs:
98     pShift_reg = pointer to Old CN generator shift register state (Word32)
99     no_bits = Number of bits (Word16)
100 
101  Outputs:
102     pShift_reg -> Updated CN generator shift register state
103 
104  Returns:
105     noise_bits = Generated random integer value (Word16)
106 
107  Global Variables Used:
108     None
109 
110  Local Variables Needed:
111     None
112 
113 ------------------------------------------------------------------------------
114  FUNCTION DESCRIPTION
115 
116  Generate a random integer value to use in comfort noise generation. The
117  algorithm uses polynomial x^31 + x^3 + 1. Length of the PN sequence
118  is 2^31 - 1
119 
120 ------------------------------------------------------------------------------
121  REQUIREMENTS
122 
123  None
124 
125 ------------------------------------------------------------------------------
126  REFERENCES
127 
128  b_cn_cod.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
129 
130 ------------------------------------------------------------------------------
131  PSEUDO-CODE
132 
133 Word16 pseudonoise (
134     Word32 *shift_reg, // i/o : Old CN generator shift register state
135     Word16 no_bits     // i   : Number of bits
136 )
137 {
138    Word16 noise_bits, Sn, i;
139 
140    noise_bits = 0;
141    for (i = 0; i < no_bits; i++)
142    {
143       // State n == 31
144       if ((*shift_reg & 0x00000001L) != 0)
145       {
146          Sn = 1;
147       }
148       else
149       {
150          Sn = 0;
151       }
152 
153       // State n == 3
154       if ((*shift_reg & 0x10000000L) != 0)
155       {
156          Sn = Sn ^ 1;
157       }
158       else
159       {
160          Sn = Sn ^ 0;
161       }
162 
163       noise_bits = shl (noise_bits, 1);
164       noise_bits = noise_bits | (extract_l (*shift_reg) & 1);
165 
166       *shift_reg = L_shr (*shift_reg, 1);
167       if (Sn & 1)
168       {
169          *shift_reg = *shift_reg | 0x40000000L;
170       }
171    }
172    return noise_bits;
173 }
174 
175 ------------------------------------------------------------------------------
176  RESOURCES USED [optional]
177 
178  When the code is written for a specific target processor the
179  the resources used should be documented below.
180 
181  HEAP MEMORY USED: x bytes
182 
183  STACK MEMORY USED: x bytes
184 
185  CLOCK CYCLES: (cycle count equation for this function) + (variable
186                 used to represent cycle count for each subroutine
187                 called)
188      where: (cycle count variable) = cycle count for [subroutine
189                                      name]
190 
191 ------------------------------------------------------------------------------
192  CAUTION [optional]
193  [State any special notes, constraints or cautions for users of this function]
194 
195 ------------------------------------------------------------------------------
196 */
197 
198 /*----------------------------------------------------------------------------
199 ; FUNCTION CODE
200 ----------------------------------------------------------------------------*/
201 
pseudonoise(Word32 * pShift_reg,Word16 no_bits)202 Word16 pseudonoise(
203     Word32 *pShift_reg,     /* i/o : Old CN generator shift register state */
204     Word16 no_bits          /* i   : Number of bits                        */
205 )
206 {
207     Word16 noise_bits;
208     Word16 Sn;
209     Word16 i;
210     Word16 temp;
211 
212     noise_bits = 0;
213 
214     for (i = 0; i < no_bits; i++)
215     {
216         /* State n == 31 */
217         if ((*pShift_reg & 0x00000001L) != 0)
218         {
219             Sn = 1;
220         }
221         else
222         {
223             Sn = 0;
224         }
225 
226         /* State n == 3 */
227         if ((*pShift_reg & 0x10000000L) != 0)
228         {
229             Sn ^= 1;
230         }
231         else
232         {
233             Sn ^= 0;
234         }
235 
236         noise_bits <<= 1;
237 
238         temp = (Word16)((*pShift_reg) & 1);
239         noise_bits |= temp;
240 
241         *pShift_reg >>= 1;
242         if (Sn & 1)
243         {
244             *pShift_reg |= 0x40000000L;
245         }
246     }
247     return noise_bits;
248 }
249 
250 /*
251 ------------------------------------------------------------------------------
252  FUNCTION NAME: build_CN_code
253 ------------------------------------------------------------------------------
254  INPUT AND OUTPUT DEFINITIONS
255 
256  Inputs:
257     pSeed = pointer to the Old CN generator shift register state (Word32)
258     cod[] = array to hold the generated CN fixed code vector (Word16)
259     pOverflow = pointer to overflow flag (Flag)
260 
261  Outputs:
262     cod[] = generated CN fixed code vector (Word16)
263     pSeed = Updated CN generator shift register state (Word16)
264     pOverflow -> 1 if overflow occured
265 
266  Returns:
267     None
268 
269  Global Variables Used:
270     None
271 
272  Local Variables Needed:
273     None
274 
275 ------------------------------------------------------------------------------
276  FUNCTION DESCRIPTION
277 
278 This function computes the comfort noise fixed codebook excitation. The gains
279 of the pulses are always +/-1.
280 
281 ------------------------------------------------------------------------------
282  REQUIREMENTS
283 
284  None
285 
286 ------------------------------------------------------------------------------
287  REFERENCES
288 
289  b_cn_cod.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
290 
291 ------------------------------------------------------------------------------
292  PSEUDO-CODE
293 
294 void build_CN_code (
295     Word32 *seed,         // i/o : Old CN generator shift register state
296     Word16 cod[]          // o   : Generated CN fixed codebook vector
297 )
298 {
299    Word16 i, j, k;
300 
301    for (i = 0; i < L_SUBFR; i++)
302    {
303       cod[i] = 0;
304    }
305 
306 // The reference ETSI code uses a global flag for Overflow. However in the
307 // actual implementation a pointer to the overflow flag is passed into the
308 // function so that it can be passed into the basic math functions L_mult()
309 // and add()
310 
311    for (k = 0; k < NB_PULSE; k++)
312    {
313       i = pseudonoise (seed, 2);      // generate pulse position
314       i = shr (extract_l (L_mult (i, 10)), 1);
315       i = add (i, k);
316 
317       j = pseudonoise (seed, 1);      // generate sign
318 
319       if (j > 0)
320       {
321          cod[i] = 4096;
322       }
323       else
324       {
325          cod[i] = -4096;
326       }
327    }
328 
329    return;
330 }
331 ------------------------------------------------------------------------------
332  RESOURCES USED [optional]
333 
334  When the code is written for a specific target processor the
335  the resources used should be documented below.
336 
337  HEAP MEMORY USED: x bytes
338 
339  STACK MEMORY USED: x bytes
340 
341  CLOCK CYCLES: (cycle count equation for this function) + (variable
342                 used to represent cycle count for each subroutine
343                 called)
344      where: (cycle count variable) = cycle count for [subroutine
345                                      name]
346 
347 ------------------------------------------------------------------------------
348  CAUTION [optional]
349  [State any special notes, constraints or cautions for users of this function]
350 
351 ------------------------------------------------------------------------------
352 */
353 
354 /*----------------------------------------------------------------------------
355 ; FUNCTION CODE
356 ----------------------------------------------------------------------------*/
build_CN_code(Word32 * pSeed,Word16 cod[],Flag * pOverflow)357 void build_CN_code(
358     Word32 *pSeed,          /* i/o : Old CN generator shift register state  */
359     Word16 cod[],           /* o   : Generated CN fixed codebook vector     */
360     Flag   *pOverflow       /* i/o : Overflow flag                          */
361 )
362 {
363     Word16 i, j, k;
364     Word16 temp;
365 
366     for (i = 0; i < L_SUBFR; i++)
367     {
368         cod[i] = 0;
369     }
370 
371     for (k = 0; k < NB_PULSE; k++)
372     {
373         i = pseudonoise(pSeed, 2);       /* generate pulse position */
374 
375         temp = (Word16)(L_mult(i, 10, pOverflow));
376         i = temp >> 1;
377         i = add(i, k, pOverflow);
378 
379         j = pseudonoise(pSeed, 1);       /* generate sign */
380 
381         if (j > 0)
382         {
383             cod[i] = 4096;
384         }
385         else
386         {
387             cod[i] = -4096;
388         }
389     }
390 
391     return;
392 }
393 
394 /*
395 ------------------------------------------------------------------------------
396  FUNCTION NAME: build_CN_param
397 ------------------------------------------------------------------------------
398  INPUT AND OUTPUT DEFINITIONS
399 
400  Inputs:
401     pSeed = pointer to the Old CN generator shift register state (Word32)
402     n_param = Number of parameters to randomize (Word16)
403     param_size_table = table holding paameter sizes (Word16)
404     param[] = array to hold CN generated paramters (Word16)
405     pOverflow = pointer to overflow flag (Flag)
406 
407  Outputs:
408     param[] = CN generated parameters (Word16)
409     pSeed = Updated CN generator shift register state (Word16)
410     pOverflow -> 1 if overflow occured
411 
412  Returns:
413     None
414 
415  Global Variables Used:
416     None
417 
418  Local Variables Needed:
419     None
420 
421 ------------------------------------------------------------------------------
422  FUNCTION DESCRIPTION
423 
424 This function randomizes the speech parameters, so that they do not produce
425 tonal artifacts if used by ECU.
426 
427 ------------------------------------------------------------------------------
428  REQUIREMENTS
429 
430  None
431 
432 ------------------------------------------------------------------------------
433  REFERENCES
434 
435  b_cn_cod.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
436 
437 ------------------------------------------------------------------------------
438  PSEUDO-CODE
439 void build_CN_param (
440     Word16 *seed,             // i/o : Old CN generator shift register state
441     const Word16 n_param,           // i  : number of params
442     const Word16 param_size_table[],// i : size of params
443     Word16 parm[]                   // o : CN Generated params
444     )
445 {
446    Word16 i;
447    const Word16 *p;
448 
449 // The reference ETSI code uses a global flag for Overflow. However in the
450 // actual implementation a pointer to the overflow flag is passed into the
451 // function so that it can be passed into the basic math functions L_add()
452 // and L_mult()
453 
454    *seed = extract_l(L_add(L_shr(L_mult(*seed, 31821), 1), 13849L));
455 
456    p = &window_200_40[*seed & 0x7F];
457    for(i=0; i< n_param;i++){
458      parm[i] = *p++ & ~(0xFFFF<<param_size_table[i]);
459    }
460 }
461 
462 
463 ------------------------------------------------------------------------------
464  RESOURCES USED [optional]
465 
466  When the code is written for a specific target processor the
467  the resources used should be documented below.
468 
469  HEAP MEMORY USED: x bytes
470 
471  STACK MEMORY USED: x bytes
472 
473  CLOCK CYCLES: (cycle count equation for this function) + (variable
474                 used to represent cycle count for each subroutine
475                 called)
476      where: (cycle count variable) = cycle count for [subroutine
477                                      name]
478 
479 ------------------------------------------------------------------------------
480  CAUTION [optional]
481  [State any special notes, constraints or cautions for users of this function]
482 
483 ------------------------------------------------------------------------------
484 */
485 
486 /*----------------------------------------------------------------------------
487 ; FUNCTION CODE
488 ----------------------------------------------------------------------------*/
build_CN_param(Word16 * pSeed,const Word16 n_param,const Word16 param_size_table[],Word16 parm[],Flag * pOverflow)489 void build_CN_param(
490     Word16 *pSeed,          /* i/o : Old CN generator shift register state  */
491     const Word16 n_param,           /* i  : number of params                */
492     const Word16 param_size_table[],/* i : size of params                   */
493     Word16 parm[],                  /* o : CN Generated params              */
494     Flag  *pOverflow                /* i/o : Overflow Flag                  */
495 )
496 
497 {
498     Word16 i;
499     const Word16 *pTemp;
500     Word32 L_temp;
501     Word16 temp;
502 
503     L_temp = L_mult(*pSeed, 31821, pOverflow);
504     L_temp >>= 1;
505 
506     *pSeed = (Word16)(L_add(L_temp, 13849L, pOverflow));
507 
508     pTemp = &window_200_40[*pSeed & 0x7F];
509 
510     for (i = 0; i < n_param; i++)
511     {
512         temp = ~(0xFFFF << param_size_table[i]);
513         parm[i] = *pTemp++ & temp;
514     }
515 }
516 
517