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
20 Filename: sbr_aliasing_reduction.c
21
22------------------------------------------------------------------------------
23 REVISION HISTORY
24
25
26 Who:                                   Date: MM/DD/YYYY
27 Description:
28
29------------------------------------------------------------------------------
30 INPUT AND OUTPUT DEFINITIONS
31
32
33
34------------------------------------------------------------------------------
35 FUNCTION DESCRIPTION
36
37
38------------------------------------------------------------------------------
39 REQUIREMENTS
40
41
42------------------------------------------------------------------------------
43 REFERENCES
44
45SC 29 Software Copyright Licencing Disclaimer:
46
47This software module was originally developed by
48  Coding Technologies
49
50and edited by
51  -
52
53in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
54standards for reference purposes and its performance may not have been
55optimized. This software module is an implementation of one or more tools as
56specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
57ISO/IEC gives users free license to this software module or modifications
58thereof for use in products claiming conformance to audiovisual and
59image-coding related ITU Recommendations and/or ISO/IEC International
60Standards. ISO/IEC gives users the same free license to this software module or
61modifications thereof for research purposes and further ISO/IEC standardisation.
62Those intending to use this software module in products are advised that its
63use may infringe existing patents. ISO/IEC have no liability for use of this
64software module or modifications thereof. Copyright is not released for
65products that do not conform to audiovisual and image-coding related ITU
66Recommendations and/or ISO/IEC International Standards.
67The original developer retains full right to modify and use the code for its
68own purpose, assign or donate the code to a third party and to inhibit third
69parties from using the code for products that do not conform to audiovisual and
70image-coding related ITU Recommendations and/or ISO/IEC International Standards.
71This copyright notice must be included in all copies or derivative works.
72Copyright (c) ISO/IEC 2002.
73
74------------------------------------------------------------------------------
75 PSEUDO-CODE
76
77------------------------------------------------------------------------------
78*/
79
80
81/*----------------------------------------------------------------------------
82; INCLUDES
83----------------------------------------------------------------------------*/
84
85#ifdef AAC_PLUS
86
87
88
89#include    "sbr_aliasing_reduction.h"
90#include    "pv_sqrt.h"
91
92#include    "aac_mem_funcs.h"
93
94#include    "pv_div.h"
95#include    "fxp_mul32.h"
96
97
98/*----------------------------------------------------------------------------
99; MACROS
100; Define module specific macros here
101----------------------------------------------------------------------------*/
102
103
104/*----------------------------------------------------------------------------
105; DEFINES
106; Include all pre-processor statements here. Include conditional
107; compile variables also.
108----------------------------------------------------------------------------*/
109
110#define Q30fmt(x)   (Int32)(x*((Int32)1<<30) + (x>=0?0.5F:-0.5F))
111
112/*----------------------------------------------------------------------------
113; LOCAL FUNCTION DEFINITIONS
114; Function Prototype declaration
115----------------------------------------------------------------------------*/
116
117/*----------------------------------------------------------------------------
118; LOCAL STORE/BUFFER/POINTER DEFINITIONS
119; Variable declaration - defined here and used outside this module
120----------------------------------------------------------------------------*/
121
122/*----------------------------------------------------------------------------
123; EXTERNAL FUNCTION REFERENCES
124; Declare functions defined elsewhere and referenced in this module
125----------------------------------------------------------------------------*/
126
127/*----------------------------------------------------------------------------
128; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
129; Declare variables used in this module but defined elsewhere
130----------------------------------------------------------------------------*/
131
132/*----------------------------------------------------------------------------
133; FUNCTION CODE
134----------------------------------------------------------------------------*/
135
136#include "pv_normalize.h"
137#include  "sbr_constants.h"
138
139/*******************************************************************************
140 Functionname:  sbr_aliasing_reduction
141 *******************************************************************************
142 Description:
143 Arguments:
144
145 Return:        none
146*******************************************************************************/
147void sbr_aliasing_reduction(Int32 *degreeAlias,
148                            Int32  * nrg_gain_man,
149                            Int32  * nrg_gain_exp,
150                            Int32  * nrg_est_man,
151                            Int32  * nrg_est_exp,
152                            Int32  * dontUseTheseGainValues,
153                            Int32    noSubbands,
154                            Int32    lowSubband,
155                            Int32  sqrt_cache[][4],
156                            Int32 * groupVector)
157{
158
159    Int32 temp1;
160    Int32 est_total;
161    Int32 ref_total_man;
162    Int32 ref_total_exp;
163    Int32 tmp_q1;
164    Int32 tmp_q2;
165    Int32 tmp_q3;
166    Int32 tmp_q4;
167    Int32 bst_man;
168    Int32 bst_exp;
169    struct intg_div   quotient;
170    struct intg_sqrt  root_sq;
171    Int32 group;
172    Int32 grouping = 0;
173    Int32 index = 0;
174    Int32 noGroups;
175    Int32 k;
176
177
178    /* Calculate grouping*/
179    for (k = 0; k < noSubbands - 1; k++)
180    {
181        if (degreeAlias[k + lowSubband + 1] && dontUseTheseGainValues[k] == 0)
182        {
183            if (grouping == 0)
184            {
185                groupVector[index] = k + lowSubband;
186                grouping = 1;
187                index++;
188            }
189        }
190        else
191        {
192            if (grouping)
193            {
194                groupVector[index] = k + lowSubband;
195
196                if (! dontUseTheseGainValues[k])
197                {
198                    (groupVector[index])++;
199                }
200                grouping = 0;
201                index++;
202            }
203        }
204    }
205
206    if (grouping)
207    {
208        groupVector[index] = noSubbands + lowSubband;
209        index++;
210    }
211    noGroups = (index >> 1);
212
213
214
215    /*Calculate new gain*/
216    for (group = 0; group < noGroups; group ++)
217    {
218
219        int startGroup = groupVector[(group<<1)] - lowSubband;
220        int stopGroup  = groupVector[(group<<1)+1] - lowSubband;
221
222
223        est_total = 0;
224        ref_total_man = 0;
225
226        tmp_q1 = -100;
227        tmp_q2 = -100;
228
229        for (k = startGroup; k < stopGroup; k++)
230        {
231            if (tmp_q1 < nrg_est_exp[k])
232            {
233                tmp_q1 = nrg_est_exp[k];    /* max */
234            }
235            if (tmp_q2 < (nrg_est_exp[k] + (nrg_gain_exp[k] << 1)))
236            {
237                tmp_q2 = (nrg_est_exp[k] + (nrg_gain_exp[k] << 1));  /* max */
238            }
239        }
240
241
242        k -= startGroup;        /*  number of element used in the addition */
243        /* adjust Q format */
244        tmp_q2 += 59 - pv_normalize(k);
245
246        for (k = startGroup; k < stopGroup; k++)
247        {
248            /*
249             *  est_total += nrg_est[k]
250             *  ref_total += nrg_est[k]*nrg_gain[k]*nrg_gain[k
251             */
252            est_total += nrg_est_man[k] >> (tmp_q1 - nrg_est_exp[k]);
253
254            if (tmp_q2 - (nrg_est_exp[k] + (nrg_gain_exp[k] << 1)) < 60)
255            {
256                nrg_gain_man[k] = fxp_mul32_Q28(nrg_gain_man[k], nrg_gain_man[k]);
257                nrg_gain_exp[k] = (nrg_gain_exp[k] << 1) + 28;
258                tmp_q3          = fxp_mul32_Q28(nrg_gain_man[k], nrg_est_man[k]);
259                ref_total_man    += tmp_q3 >> (tmp_q2 - (nrg_est_exp[k] + nrg_gain_exp[k]));
260            }
261        }
262
263        ref_total_exp = tmp_q2 + 28;
264
265        pv_div(ref_total_man, est_total, &quotient);
266
267        tmp_q2 += - tmp_q1 - quotient.shift_factor - 2;
268
269
270
271        for (k = startGroup; k < stopGroup; k++)
272        {
273            Int32 alpha;
274            temp1 = k + lowSubband;
275            if (k < noSubbands - 1)
276            {
277                alpha = degreeAlias[temp1 + 1] > degreeAlias[temp1 ] ?
278                        degreeAlias[temp1 + 1] : degreeAlias[temp1 ];
279            }
280            else
281            {
282                alpha = degreeAlias[temp1];
283            }
284
285            /*
286             *  nrg_gain[k] = alpha*newGain + (1.0f-alpha)*nrg_gain[k]*nrg_gain[k];
287             */
288
289            tmp_q1 = tmp_q2 > nrg_gain_exp[k] ? tmp_q2 : nrg_gain_exp[k];
290            tmp_q1++;
291
292            tmp_q3 = fxp_mul32_Q30(alpha, quotient.quotient);
293            tmp_q4 = fxp_mul32_Q30(Q30fmt(1.0f) - alpha, nrg_gain_man[k]);
294
295            nrg_gain_man[k] = (tmp_q3 >> (tmp_q1 - tmp_q2)) +
296                              (tmp_q4 >> (tmp_q1 - nrg_gain_exp[k]));
297
298            nrg_gain_exp[k] = tmp_q1;
299        }
300
301
302        bst_exp = -100;
303
304        for (k = startGroup; k < stopGroup; k++)
305        {
306            if (bst_exp < nrg_gain_exp[k] + nrg_est_exp[k])
307            {
308                bst_exp = nrg_gain_exp[k] + nrg_est_exp[k];    /* max */
309            }
310        }
311
312        k -= startGroup;        /*  number of element used in the addition */
313
314        while (k != 0)          /*  bit guard protection depends on log2(k)  */
315        {
316            k >>= 1;
317            bst_exp++;           /*  add extra bit-overflow-guard */
318        }
319
320        bst_man = 0;
321
322        for (k = startGroup; k < stopGroup; k++)
323        {
324            tmp_q2 =  fxp_mul32_Q28(nrg_gain_man[k], nrg_est_man[k]);
325            bst_man +=  tmp_q2 >> (bst_exp - nrg_gain_exp[k] - nrg_est_exp[k]);
326        }
327
328        bst_exp += 28;  /* compensate for shift down */
329
330        if (bst_man)
331        {
332            /*
333             *  bst = ref_total / bst
334             */
335
336            pv_div(ref_total_man, bst_man, &quotient);
337            bst_exp = ref_total_exp - bst_exp - quotient.shift_factor - 30;
338            bst_man = quotient.quotient;      /*  Q30 */
339
340            for (k = startGroup; k < stopGroup; k++)
341            {
342                tmp_q1 = fxp_mul32_Q30(bst_man, nrg_gain_man[k]);
343                pv_sqrt(tmp_q1, (bst_exp + nrg_gain_exp[k] + 60), &root_sq, sqrt_cache[0]);
344                nrg_gain_man[k] = root_sq.root;
345                nrg_gain_exp[k] = root_sq.shift_factor;
346            }
347        }
348        else
349        {
350            pv_memset((void *)&nrg_gain_man[startGroup],
351                      0,
352                      (stopGroup - startGroup)*sizeof(nrg_gain_man[0]));
353
354            pv_memset((void *)&nrg_gain_exp[startGroup],
355                      0,
356                      (stopGroup - startGroup)*sizeof(nrg_gain_exp[0]));
357
358        }
359
360    }
361}
362
363#endif
364
365
366
367