1d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber/* ------------------------------------------------------------------
2d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * Copyright (C) 1998-2009 PacketVideo
3d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber *
4d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * you may not use this file except in compliance with the License.
6d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * You may obtain a copy of the License at
7d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber *
8d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber *
10d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * Unless required by applicable law or agreed to in writing, software
11d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * express or implied.
14d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * See the License for the specific language governing permissions
15d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * and limitations under the License.
16d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * -------------------------------------------------------------------
17d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber */
18d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber/****************************************************************************************
19d49b526dd2009270cb15f7fe4e70b74673950608Andreas HuberPortions of this file are derived from the following 3GPP standard:
20d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
21d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    3GPP TS 26.073
22d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Available from http://www.3gpp.org
24d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
25d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
26d49b526dd2009270cb15f7fe4e70b74673950608Andreas HuberPermission to distribute, modify and use this file under the standard license
27d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huberterms listed above has been obtained from the copyright holder.
28d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber****************************************************************************************/
29d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber/*
30d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber------------------------------------------------------------------------------
31d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
32d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
33d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
34d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Pathname: ./audio/gsm-amr/c/src/g_pitch.c
35d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
36d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber     Date: 06/12/2000
37d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
38d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber------------------------------------------------------------------------------
39d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber REVISION HISTORY
40d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
41d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Description:  Placed into template and began to optimize.
42d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
43d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Description: Synchronized file with UMTS version 3.2.0. Updated coding
44d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber              template. Removed unnecessary include files.
45d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
46d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Description: Replaced basic_op.h and oper_32b.h with the header files of the
47d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber              math functions used in the file. Fixed typecasting issue with
48d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber              TI compiler.
49d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
50d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Description: Passing in pointer to overflow flag for EPOC compatibility. .
51d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
52d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Description:
53d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber              1. Eliminated unused include files.
54d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber              2. Replaced array addressing by pointers
55d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber              3. Eliminated math operations that unnecessary checked for
56d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                 saturation, in some cases this by shifting before adding and
57d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                 in other cases by evaluating the operands
58d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber              4. Unrolled loops to speed up processing
59d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
60d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Description:  Replaced OSCL mem type functions and eliminated include
61d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber               files that now are chosen by OSCL definitions
62d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
63d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Description:  Replaced "int" and/or "char" with OSCL defined types.
64d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
65d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Description: Changed round function name to pv_round to avoid conflict with
66d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber              round function in C standard library.
67d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
68d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Description: Using inlines from fxp_arithmetic.h .
69d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
70d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Description: Replacing fxp_arithmetic.h with basic_op.h.
71d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
72d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Description:
73d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
74d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber------------------------------------------------------------------------------
75d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber*/
76d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
77d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber/*----------------------------------------------------------------------------
78d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber; INCLUDES
79d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber----------------------------------------------------------------------------*/
80d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber#include "g_pitch.h"
81d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber#include "mode.h"
82d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber#include "cnst.h"
83d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber#include "basic_op.h"
84d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
85d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber/*----------------------------------------------------------------------------
86d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber; MACROS
87d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber; Define module specific macros here
88d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber----------------------------------------------------------------------------*/
89d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
90d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
91d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber/*----------------------------------------------------------------------------
92d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber; DEFINES
93d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber; Include all pre-processor statements here. Include conditional
94d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber; compile variables also.
95d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber----------------------------------------------------------------------------*/
96d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
97d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber/*----------------------------------------------------------------------------
98d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber; LOCAL FUNCTION DEFINITIONS
99d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber; Function Prototype declaration
100d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber----------------------------------------------------------------------------*/
101d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
102d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber/*----------------------------------------------------------------------------
103d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber; LOCAL STORE/BUFFER/POINTER DEFINITIONS
104d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber; Variable declaration - defined here and used outside this module
105d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber----------------------------------------------------------------------------*/
106d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
107d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
108d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber/*
109d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber------------------------------------------------------------------------------
110d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber FUNCTION NAME: G_pitch
111d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber------------------------------------------------------------------------------
112d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber INPUT AND OUTPUT DEFINITIONS
113d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
114d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Inputs:
115d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    mode = AMR mode (enum Mode)
116d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    xn = pointer to pitch target buffer (Word16)
117d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    y1 = pointer to filtered adaptive codebook buffer (Word16)
118d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    g_coeff  = pointer to buffer of correlations needed for gain quantization
119d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber               (Word16)
120d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    L_subfr = length of subframe (Word16)
121d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    pOverflow = pointer to overflow flag (Flag)
122d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
123d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Outputs:
124d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    g_coeff contains the mantissa and exponent of the two dot products.
125d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    pOverflow -> 1 if an overflow occurs
126d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
127d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Returns:
128d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    gain =  ratio of dot products.(Word16)
129d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
130d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Global Variables Used:
131d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    None.
132d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
133d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber Local Variables Needed:
134d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    None.
135d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
136d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber------------------------------------------------------------------------------
137d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber FUNCTION DESCRIPTION
138d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
139d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber This function computes the pitch (adaptive codebook) gain. The adaptive
140d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber codebook gain is given by
141d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
142d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    g = <x[], y[]> / <y[], y[]>
143d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
144d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    where:  x[] is the target vector
145d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            y[] is the filtered adaptive codevector
146d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            <> denotes dot product.
147d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
148d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber The gain is limited to the range [0,1.2] (=0..19661 Q14)
149d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
150d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber------------------------------------------------------------------------------
151d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber REQUIREMENTS
152d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
153d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber None.
154d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
155d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber------------------------------------------------------------------------------
156d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber REFERENCES
157d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
158d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber g_pitch.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
159d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
160d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber------------------------------------------------------------------------------
161d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber PSEUDO-CODE
162d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
163d49b526dd2009270cb15f7fe4e70b74673950608Andreas HuberWord16 G_pitch     (    // o : Gain of pitch lag saturated to 1.2
164d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    enum Mode mode,     // i : AMR mode
165d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 xn[],        // i : Pitch target.
166d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 y1[],        // i : Filtered adaptive codebook.
167d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 g_coeff[],   // i : Correlations need for gain quantization
168d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 L_subfr      // i : Length of subframe.
169d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber)
170d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber{
171d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 i;
172d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 xy, yy, exp_xy, exp_yy, gain;
173d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word32 s;
174d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
175d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 scaled_y1[L_SUBFR];   // Usually dynamic allocation of (L_subfr)
176d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
177d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    // divide "y1[]" by 4 to avoid overflow
178d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
179d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber// The reference ETSI code uses a global overflow Flag. However in the actual
180d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber// implementation a pointer to the overflow flag is passed into the function.
181d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
182d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    for (i = 0; i < L_subfr; i++)
183d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
184d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        scaled_y1[i] = shr (y1[i], 2);
185d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
186d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
187d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    // Compute scalar product <y1[],y1[]>
188d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
189d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    // Q12 scaling / MR122
190d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Overflow = 0;
191d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    s = 1L; // Avoid case of all zeros
192d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    for (i = 0; i < L_subfr; i++)
193d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
194d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s = L_mac (s, y1[i], y1[i]);
195d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
196d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if (Overflow == 0)       // Test for overflow
197d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
198d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        exp_yy = norm_l (s);
199d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        yy = pv_round (L_shl (s, exp_yy));
200d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
201d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    else
202d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
203d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s = 1L; // Avoid case of all zeros
204d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        for (i = 0; i < L_subfr; i++)
205d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        {
206d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            s = L_mac (s, scaled_y1[i], scaled_y1[i]);
207d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        }
208d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        exp_yy = norm_l (s);
209d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        yy = pv_round (L_shl (s, exp_yy));
210d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        exp_yy = sub (exp_yy, 4);
211d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
212d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
213d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    // Compute scalar product <xn[],y1[]>
214d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
215d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Overflow = 0;
216d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    s = 1L; // Avoid case of all zeros
217d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
218d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    for (i = 0; i < L_subfr; i++)
219d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
220d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s = L_mac(s, xn[i], y1[i]);
221d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
222d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if (Overflow == 0)
223d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
224d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        exp_xy = norm_l (s);
225d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        xy = pv_round (L_shl (s, exp_xy));
226d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
227d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    else
228d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
229d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s = 1L; // Avoid case of all zeros
230d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        for (i = 0; i < L_subfr; i++)
231d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        {
232d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            s = L_mac (s, xn[i], scaled_y1[i]);
233d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        }
234d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        exp_xy = norm_l (s);
235d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        xy = pv_round (L_shl (s, exp_xy));
236d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        exp_xy = sub (exp_xy, 2);
237d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
238d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
239d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    g_coeff[0] = yy;
240d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    g_coeff[1] = sub (15, exp_yy);
241d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    g_coeff[2] = xy;
242d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    g_coeff[3] = sub (15, exp_xy);
243d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
244d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    // If (xy < 4) gain = 0
245d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
246d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    i = sub (xy, 4);
247d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
248d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if (i < 0)
249d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        return ((Word16) 0);
250d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
251d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    // compute gain = xy/yy
252d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
253d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    xy = shr (xy, 1);                  // Be sure xy < yy
254d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    gain = div_s (xy, yy);
255d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
256d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    i = sub (exp_xy, exp_yy);      // Denormalization of division
257d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    gain = shr (gain, i);
258d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
259d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    // if(gain >1.2) gain = 1.2
260d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
261d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if (sub (gain, 19661) > 0)
262d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
263d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        gain = 19661;
264d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
265d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
266d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if (sub(mode, MR122) == 0)
267d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
268d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber       // clear 2 LSBits
269d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber       gain = gain & 0xfffC;
270d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
271d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
272d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    return (gain);
273d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber}
274d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
275d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber------------------------------------------------------------------------------
276d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber RESOURCES USED [optional]
277d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
278d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber When the code is written for a specific target processor the
279d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber the resources used should be documented below.
280d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
281d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber HEAP MEMORY USED: x bytes
282d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
283d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber STACK MEMORY USED: x bytes
284d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
285d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber CLOCK CYCLES: (cycle count equation for this function) + (variable
286d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                used to represent cycle count for each subroutine
287d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                called)
288d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber     where: (cycle count variable) = cycle count for [subroutine
289d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                                     name]
290d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
291d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber------------------------------------------------------------------------------
292d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber CAUTION [optional]
293d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber [State any special notes, constraints or cautions for users of this function]
294d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
295d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber------------------------------------------------------------------------------
296d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber*/
297d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
298d49b526dd2009270cb15f7fe4e70b74673950608Andreas HuberWord16 G_pitch(         /* o : Gain of pitch lag saturated to 1.2       */
299d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    enum Mode mode,     /* i : AMR mode                                 */
300d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 xn[],        /* i : Pitch target.                            Q0  */
301d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 y1[],        /* i : Filtered adaptive codebook.              Q12 */
302d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 g_coeff[],   /* i : Correlations need for gain quantization  */
303d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 L_subfr,     /* i : Length of subframe.                      */
304d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Flag   *pOverflow   /* i/o : Overflow flag                          */
305d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber)
306d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber{
307d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
308d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 i;
309d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 xy;
310d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 yy;
311d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 exp_xy;
312d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 exp_yy;
313d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 gain;
314d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 tmp;
315d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word32 s;
316d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word32 s1;
317d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word32 L_temp;                      /* Use this as an intermediate value */
318d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 *p_xn = &xn[0];
319d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Word16 *p_y1 = &y1[0];
320d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
321d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    /* Compute scalar product <y1[],y1[]> */
322d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
323d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    /* Q12 scaling / MR122 */
324d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    *pOverflow = 0;
325d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    s = 0;
326d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
327d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    for (i = L_subfr >> 2; i != 0; i--)
328d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
329d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
330d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        p_y1++;
331d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
332d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        p_y1++;
333d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
334d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        p_y1++;
335d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
336d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        p_y1++;
337d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
338d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if ((s >= 0) & (s < 0x40000000))
339d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
340d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s <<= 1;
341d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s  += 1;            /* Avoid case of all zeros */
342d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
343d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        exp_yy = norm_l(s);             /* Note 0<=exp_yy <= 31 */
344d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        L_temp = s << exp_yy;
345d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        yy = pv_round(L_temp, pOverflow);
346d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
347d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    else
348d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
349d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s = 0;                      /* Avoid case of all zeros */
350d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        p_y1 = &y1[0];
351d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        for (i = (L_subfr >> 1); i != 0; i--)
352d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        {
353d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            tmp = *(p_y1++) >> 2;
354d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            s = amrnb_fxp_mac_16_by_16bb((Word32) tmp, (Word32) tmp, s);
355d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            tmp = *(p_y1++) >> 2;
356d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            s = amrnb_fxp_mac_16_by_16bb((Word32) tmp, (Word32) tmp, s);
357d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        }
358d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
359d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s <<= 1;
360d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s  += 1;            /* Avoid case of all zeros */
361d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
362d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        exp_yy = norm_l(s);
363d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        L_temp = s << exp_yy;
364d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        yy = pv_round(L_temp, pOverflow);
365d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        exp_yy = exp_yy - 4;
366d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
367d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
368d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
369d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    /* Compute scalar product <xn[],y1[]> */
370d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
371d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    s = 0;
372d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    p_y1 = &y1[0];
373d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    *pOverflow = 0;
374d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
375d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    for (i = L_subfr; i != 0; i--)
376d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
377d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        L_temp = ((Word32) * (p_xn++) * *(p_y1++));
378d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s1 = s;
379d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s = s1 + L_temp;
380d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
381d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        if ((s1 ^ L_temp) > 0)
382d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        {
383d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            if ((s1 ^ s) < 0)
384d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            {
385d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                *pOverflow = 1;
386d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                break;
387d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            }
388d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        }
389d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
390d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
391d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if (!(*pOverflow))
392d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
393d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
394d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s <<= 1;
395d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s  += 1;            /* Avoid case of all zeros */
396d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
397d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        exp_xy = norm_l(s);             /* Note 0<=exp_yy <= 31 */
398d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        L_temp = s << exp_xy;
399d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        xy = pv_round(L_temp, pOverflow);
400d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
401d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    else
402d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
403d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s = 0;                      /* Avoid case of all zeros */
404d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        p_y1 = &y1[0];
405d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        for (i = (L_subfr >> 2); i != 0; i--)
406d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        {
407d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            L_temp = (Word32)(*(p_y1++) >> 2);
408d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
409d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            L_temp = (Word32)(*(p_y1++) >> 2);
410d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
411d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            L_temp = (Word32)(*(p_y1++) >> 2);
412d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
413d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            L_temp = (Word32)(*(p_y1++) >> 2);
414d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
415d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        }
416d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
417d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s <<= 1;
418d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        s  += 1;            /* Avoid case of all zeros */
419d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
420d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        exp_xy = norm_l(s);
421d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        L_temp = s << exp_xy;
422d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        xy = pv_round(L_temp, pOverflow);
423d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        exp_xy = exp_xy - 4;
424d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
425d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
426d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
427d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    g_coeff[0] = yy;
428d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    g_coeff[1] = 15 - exp_yy;
429d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    g_coeff[2] = xy;
430d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    g_coeff[3] = 15 - exp_xy;
431d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
432d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    /* If (xy < 4) gain = 0 */
433d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if (xy < 4)
434d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
435d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        return ((Word16) 0);
436d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
437d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
438d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    /* compute gain = xy/yy */
439d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    /* Be sure xy < yy */
440d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
441d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    xy = xy >> 1;
442d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
443d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    gain = div_s(xy, yy);
444d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
445d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    i = exp_xy - exp_yy;               /* Denormalization of division */
446d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
447d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    gain = shr(gain, i, pOverflow);
448d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
449d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
450d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    /* if(gain >1.2) gain = 1.2 */
451d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if (gain > 19661)
452d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
453d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        gain = 19661;
454d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
455d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
456d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if (mode == MR122)
457d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    {
458d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        /* clear 2 LSBits */
459d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        gain = gain & 0xfffC;
460d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
461d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
462d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    return(gain);
463d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
464d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber}
465