OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / media / libstagefright / codecs / aacdec / sbr_update_freq_scale.cpp
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_update_freq_scale.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
45 SC 29 Software Copyright Licencing Disclaimer:
46
47 This software module was originally developed by
48   Coding Technologies
49
50 and edited by
51   -
52
53 in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
54 standards for reference purposes and its performance may not have been
55 optimized. This software module is an implementation of one or more tools as
56 specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
57 ISO/IEC gives users free license to this software module or modifications
58 thereof for use in products claiming conformance to audiovisual and
59 image-coding related ITU Recommendations and/or ISO/IEC International
60 Standards. ISO/IEC gives users the same free license to this software module or
61 modifications thereof for research purposes and further ISO/IEC standardisation.
62 Those intending to use this software module in products are advised that its
63 use may infringe existing patents. ISO/IEC have no liability for use of this
64 software module or modifications thereof. Copyright is not released for
65 products that do not conform to audiovisual and image-coding related ITU
66 Recommendations and/or ISO/IEC International Standards.
67 The original developer retains full right to modify and use the code for its
68 own purpose, assign or donate the code to a third party and to inhibit third
69 parties from using the code for products that do not conform to audiovisual and
70 image-coding related ITU Recommendations and/or ISO/IEC International Standards.
71 This copyright notice must be included in all copies or derivative works.
72 Copyright (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 #include    "sbr_update_freq_scale.h"
89 #include    "shellsort.h"
90
91 #include    "pv_pow2.h"
92 #include    "pv_log2.h"
93
94 #include "fxp_mul32.h"
95 #define R_SHIFT     30
96 #define Q_fmt(x)    (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
97 #define Q28fmt(x)   (Int32)(x*((Int32)1<<28) + (x>=0?0.5F:-0.5F))
98
99 /*----------------------------------------------------------------------------
100 ; MACROS
101 ; Define module specific macros here
102 ----------------------------------------------------------------------------*/
103
104
105 /*----------------------------------------------------------------------------
106 ; DEFINES
107 ; Include all pre-processor statements here. Include conditional
108 ; compile variables also.
109 ----------------------------------------------------------------------------*/
110
111 /*----------------------------------------------------------------------------
112 ; LOCAL FUNCTION DEFINITIONS
113 ; Function Prototype declaration
114 ----------------------------------------------------------------------------*/
115
116 /*----------------------------------------------------------------------------
117 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
118 ; Variable declaration - defined here and used outside this module
119 ----------------------------------------------------------------------------*/
120
121 /*----------------------------------------------------------------------------
122 ; EXTERNAL FUNCTION REFERENCES
123 ; Declare functions defined elsewhere and referenced in this module
124 ----------------------------------------------------------------------------*/
125
126 /*----------------------------------------------------------------------------
127 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
128 ; Declare variables used in this module but defined elsewhere
129 ----------------------------------------------------------------------------*/
130
131 /*----------------------------------------------------------------------------
132 ; FUNCTION CODE
133 ----------------------------------------------------------------------------*/
134
135
136
137 void sbr_update_freq_scale(Int32 * v_k_master,
138                            Int32 *h_num_bands,
139                            const Int32 lsbM,
140                            const Int32 usb,
141                            const Int32 freqScale,
142                            const Int32 alterScale,
143                            const Int32 channelOffset)
144 {
145     Int32 i;
146     Int32 numBands = 0;
147     Int32 numBands2;
148     Int32 tmp_q1;
149
150     if (freqScale > 0) /*Bark mode*/
151     {
152         Int32 reg;
153         Int32 regions;
154         Int32 b_p_o;
155         Int32 k[3];
156         Int32 d[MAX_SECOND_REGION];
157         Int32 d2[MAX_SECOND_REGION];
158         Int32 w[2] = {Q_fmt(1.0F), Q_fmt(1.0F)};
159
160
161         k[0] = lsbM;
162         k[1] = usb;
163         k[2] = usb;
164
165         b_p_o = (freqScale == 1)  ? 12 : 8;
166         b_p_o = (freqScale == 2)  ? 10 : b_p_o;
167
168         w[1]  = (alterScale == 0) ? Q_fmt(0.5f) : Q_fmt(0.384615384615386f);
169
170         if (usb > fxp_mul32_Q28(lsbM, Q28fmt(2.2449)))
171         {
172             regions = 2;
173             k[1] = (lsbM << 1);
174         }
175         else
176         {
177             regions = 1;
178         }
179
180         *h_num_bands = 0;
181         for (reg = 0; reg < regions; reg++)
182         {
183             if (reg == 0)
184             {
185
186                 tmp_q1 = pv_log2((k[1] << 20) / k[0]);
187
188                 tmp_q1 = fxp_mul32_Q15(tmp_q1, b_p_o);
189                 tmp_q1 = (tmp_q1 + 32) >> 6;
190
191                 numBands = tmp_q1 << 1;
192
193
194                 CalcBands(d, k[0], k[1], numBands);                                    /* CalcBands => d   */
195                 shellsort(d, numBands);                                              /* SortBands sort d */
196                 cumSum(k[0] - channelOffset,
197                        d,
198                        numBands,
199                        (v_k_master + *h_num_bands));   /* cumsum */
200
201                 *h_num_bands += numBands;                                            /* Output nr of bands */
202             }
203             else
204             {
205                 tmp_q1 = pv_log2((k[reg + 1] << 20) / k[reg]);
206
207                 tmp_q1 = fxp_mul32_Q30(tmp_q1, w[reg]);
208                 tmp_q1 = fxp_mul32_Q15(tmp_q1, b_p_o);
209                 tmp_q1 = (tmp_q1 + 16) >> 5;
210
211                 numBands2 = tmp_q1 << 1;
212
213                 CalcBands(d2, k[reg], k[reg+1], numBands2);                            /* CalcBands => d   */
214                 shellsort(d2, numBands2);                                              /* SortBands sort d */
215                 if (d[numBands-1] > d2[0])
216                 {
217
218                     Int32   change = d[numBands-1] - d2[0];
219                     /* Limit the change so that the last band cannot get narrower than the first one */
220                     if (change > (d2[numBands2-1] - d2[0]) >> 1)
221                     {
222                         change = (d2[numBands2-1] - d2[0]) >> 1;
223                     }
224
225                     d2[0] += change;
226                     d2[numBands2-1] -= change;
227                     shellsort(d2, numBands2);
228
229                 }
230                 cumSum(k[reg] - channelOffset,
231                        d2,
232                        numBands2,
233                        v_k_master + *h_num_bands);   /* cumsum */
234
235                 *h_num_bands += numBands2;                                           /* Output nr of bands */
236             }
237         }
238     }
239     else
240     {                         /* Linear mode */
241         Int32     k2_achived;
242         Int32     k2_diff;
243         Int32     diff_tot[MAX_OCTAVE + MAX_SECOND_REGION];
244         Int32     dk;
245         Int32     incr = 0;
246
247
248         if (alterScale)
249         {
250             numBands = (usb - lsbM) >> 1;
251             dk = 1;
252             k2_achived = lsbM + numBands;
253         }
254         else
255         {
256             numBands = usb - lsbM;
257             if (numBands & 0x1) /* equivalent rounding */
258             {
259                 numBands--;
260             }
261             dk = 2;
262             k2_achived = lsbM + (numBands << 1);
263         }
264
265         k2_diff = usb - k2_achived;
266
267         for (i = 0; i < numBands; i++)
268         {
269             diff_tot[i] = dk;
270         }
271
272         if (k2_diff < 0)        /* If linear scale wasn't achived */
273         {
274             incr = 1;           /* and we got too large SBR area */
275             i = 0;
276         }
277
278         if (k2_diff > 0)        /* If linear scale wasn't achived */
279         {
280             incr = -1;            /* and we got too small SBR area */
281             i = numBands - 1;
282         }
283
284         /* Adjust diff vector to get spec. SBR range */
285         while (k2_diff != 0)
286         {
287             diff_tot[i] -=  incr;
288             i += incr;
289             k2_diff += incr;
290         }
291
292         cumSum(lsbM,
293                diff_tot,
294                numBands,
295                v_k_master); /* cumsum */
296
297         *h_num_bands = numBands;                      /* Output nr of bands */
298     }
299 }
300
301
302 void CalcBands(Int32 * diff,
303                Int32 start,
304                Int32 stop,
305                Int32 num_bands)
306 {
307     Int32 i;
308     Int32 previous;
309     Int32 current;
310     Int32 tmp_q1;
311
312
313     previous = start;
314
315     for (i = 1; i <= num_bands; i++)
316     {
317         /*              float temp=(start * pow( (float)stop/start, (float)i/num_bands)); */
318
319         tmp_q1 = pv_log2((stop << 20) / start);
320
321         tmp_q1 = fxp_mul32_Q20(tmp_q1, (i << 27) / num_bands);
322         tmp_q1 = pv_pow2(tmp_q1);
323
324         tmp_q1 = fxp_mul32_Q20(tmp_q1, start);
325
326         current = (tmp_q1 + 16) >> 5;
327
328         diff[i-1] = current - previous;
329         previous  = current;
330     }
331
332 }  /* End CalcBands */
333
334
335 void cumSum(Int32 start_value,
336             Int32 * diff,
337             Int32 length,
338             Int32 * start_adress)
339 {
340     Int32 i;
341     Int32 *pt_start_adress   = start_adress;
342     Int32 *pt_start_adress_1 = start_adress;
343     Int32 *pt_diff           = diff;
344
345     if (length > 0)  /*  avoid possible error on loop */
346     {
347         *(pt_start_adress_1++) = start_value;
348
349         for (i = (length >> 1); i != 0; i--)
350         {
351             *(pt_start_adress_1++) = *(pt_start_adress++) + *(pt_diff++);
352             *(pt_start_adress_1++) = *(pt_start_adress++) + *(pt_diff++);
353         }
354
355         if (length&1)
356         {
357             *(pt_start_adress_1) = *(pt_start_adress) + *(pt_diff);
358         }
359     }
360
361 }   /* End cumSum */
362
363
364 #endif