1/* -----------------------------------------------------------------------------
2Software License for The Fraunhofer FDK AAC Codec Library for Android
3
4© Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5Forschung e.V. All rights reserved.
6
7 1.    INTRODUCTION
8The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10scheme for digital audio. This FDK AAC Codec software is intended to be used on
11a wide variety of Android devices.
12
13AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14general perceptual audio codecs. AAC-ELD is considered the best-performing
15full-bandwidth communications codec by independent studies and is widely
16deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17specifications.
18
19Patent licenses for necessary patent claims for the FDK AAC Codec (including
20those of Fraunhofer) may be obtained through Via Licensing
21(www.vialicensing.com) or through the respective patent owners individually for
22the purpose of encoding or decoding bit streams in products that are compliant
23with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24Android devices already license these patent claims through Via Licensing or
25directly from the patent owners, and therefore FDK AAC Codec software may
26already be covered under those patent licenses when it is used for those
27licensed purposes only.
28
29Commercially-licensed AAC software libraries, including floating-point versions
30with enhanced sound quality, are also available from Fraunhofer. Users are
31encouraged to check the Fraunhofer website for additional applications
32information and documentation.
33
342.    COPYRIGHT LICENSE
35
36Redistribution and use in source and binary forms, with or without modification,
37are permitted without payment of copyright license fees provided that you
38satisfy the following conditions:
39
40You must retain the complete text of this software license in redistributions of
41the FDK AAC Codec or your modifications thereto in source code form.
42
43You must retain the complete text of this software license in the documentation
44and/or other materials provided with redistributions of the FDK AAC Codec or
45your modifications thereto in binary form. You must make available free of
46charge copies of the complete source code of the FDK AAC Codec and your
47modifications thereto to recipients of copies in binary form.
48
49The name of Fraunhofer may not be used to endorse or promote products derived
50from this library without prior written permission.
51
52You may not charge copyright license fees for anyone to use, copy or distribute
53the FDK AAC Codec software or your modifications thereto.
54
55Your modified versions of the FDK AAC Codec must carry prominent notices stating
56that you changed the software and the date of any change. For modified versions
57of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59AAC Codec Library for Android."
60
613.    NO PATENT LICENSE
62
63NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65Fraunhofer provides no warranty of patent non-infringement with respect to this
66software.
67
68You may use this FDK AAC Codec software or modifications thereto only for
69purposes that are authorized by appropriate patent licenses.
70
714.    DISCLAIMER
72
73This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75including but not limited to the implied warranties of merchantability and
76fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78or consequential damages, including but not limited to procurement of substitute
79goods or services; loss of use, data, or profits, or business interruption,
80however caused and on any theory of liability, whether in contract, strict
81liability, or tort (including negligence), arising in any way out of the use of
82this software, even if advised of the possibility of such damage.
83
845.    CONTACT INFORMATION
85
86Fraunhofer Institute for Integrated Circuits IIS
87Attention: Audio and Multimedia Departments - FDK AAC LL
88Am Wolfsmantel 33
8991058 Erlangen, Germany
90
91www.iis.fraunhofer.de/amm
92amm-info@iis.fraunhofer.de
93----------------------------------------------------------------------------- */
94
95/**************************** SBR decoder library ******************************
96
97   Author(s):   Oliver Moser, Manuel Jander, Matthias Hildenbrand
98
99   Description: QMF frequency pre-whitening for SBR.
100                In the documentation the terms "scale factor" and "exponent"
101                mean the same. Variables containing such information have
102                the suffix "_sf".
103
104*******************************************************************************/
105
106#include "HFgen_preFlat.h"
107
108#define POLY_ORDER 3
109#define MAXLOWBANDS 32
110#define LOG10FAC 0.752574989159953f     /* == 10/log2(10) * 2^-2 */
111#define LOG10FAC_INV 0.664385618977472f /* == log2(10)/20 * 2^2  */
112
113#define FIXP_CHB FIXP_SGL /* STB sinus Tab used in transformation */
114#define CHC(a) (FX_DBL2FXCONST_SGL(a))
115#define FX_CHB2FX_DBL(a) FX_SGL2FX_DBL(a)
116
117typedef struct backsubst_data {
118  FIXP_CHB Lnorm1d[3]; /*!< Normalized L matrix */
119  SCHAR Lnorm1d_sf[3];
120  FIXP_CHB Lnormii
121      [3]; /*!< The diagonal data points [i][i] of the normalized L matrix */
122  SCHAR Lnormii_sf[3];
123  FIXP_CHB Bmul0
124      [4]; /*!< To normalize L*x=b, Bmul0 is what we need to multiply b with. */
125  SCHAR Bmul0_sf[4];
126  FIXP_CHB LnormInv1d[6]; /*!< Normalized inverted L matrix (L') */
127  SCHAR LnormInv1d_sf[6];
128  FIXP_CHB
129  Bmul1[4]; /*!< To normalize L'*x=b, Bmul1 is what we need to multiply b
130               with. */
131  SCHAR Bmul1_sf[4];
132} backsubst_data;
133
134/* for each element n do, f(n) = trunc(log2(n))+1  */
135const UCHAR getLog2[32] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
136                           5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
137
138/** \def  BSD_IDX_OFFSET
139 *
140 *  bsd[] begins at index 0 with data for numBands=5. The correct bsd[] is
141 *  indexed like bsd[numBands-BSD_IDX_OFFSET].
142 */
143#define BSD_IDX_OFFSET 5
144
145#define N_NUMBANDS               \
146  MAXLOWBANDS - BSD_IDX_OFFSET + \
147      1 /*!< Number of backsubst_data elements in bsd */
148
149const backsubst_data bsd[N_NUMBANDS] = {
150    {
151        /* numBands=5 */
152        {CHC(0x66c85a52), CHC(0x4278e587), CHC(0x697dcaff)},
153        {-1, 0, 0},
154        {CHC(0x66a61789), CHC(0x5253b8e3), CHC(0x5addad81)},
155        {3, 4, 1},
156        {CHC(0x7525ee90), CHC(0x6e2a1210), CHC(0x6523bb40), CHC(0x59822ead)},
157        {-6, -4, -2, 0},
158        {CHC(0x609e4cad), CHC(0x59c7e312), CHC(0x681eecac), CHC(0x440ea893),
159         CHC(0x4a214bb3), CHC(0x53c345a1)},
160        {1, 0, -1, -1, -3, -5},
161        {CHC(0x7525ee90), CHC(0x58587936), CHC(0x410d0b38), CHC(0x7f1519d6)},
162        {-6, -1, 2, 0},
163    },
164    {
165        /* numBands=6 */
166        {CHC(0x68943285), CHC(0x4841d2c3), CHC(0x6a6214c7)},
167        {-1, 0, 0},
168        {CHC(0x63c5923e), CHC(0x4e906e18), CHC(0x6285af8a)},
169        {3, 4, 1},
170        {CHC(0x7263940b), CHC(0x424a69a5), CHC(0x4ae8383a), CHC(0x517b7730)},
171        {-7, -4, -2, 0},
172        {CHC(0x518aee5f), CHC(0x4823a096), CHC(0x43764a39), CHC(0x6e6faf23),
173         CHC(0x61bba44f), CHC(0x59d8b132)},
174        {1, 0, -1, -2, -4, -6},
175        {CHC(0x7263940b), CHC(0x6757bff2), CHC(0x5bf40fe0), CHC(0x7d6f4292)},
176        {-7, -2, 1, 0},
177    },
178    {
179        /* numBands=7 */
180        {CHC(0x699b4c3c), CHC(0x4b8b702f), CHC(0x6ae51a4f)},
181        {-1, 0, 0},
182        {CHC(0x623a7f49), CHC(0x4ccc91fc), CHC(0x68f048dd)},
183        {3, 4, 1},
184        {CHC(0x7e6ebe18), CHC(0x5701daf2), CHC(0x74a8198b), CHC(0x4b399aa1)},
185        {-8, -5, -3, 0},
186        {CHC(0x464a64a6), CHC(0x78e42633), CHC(0x5ee174ba), CHC(0x5d0008c8),
187         CHC(0x455cff0f), CHC(0x6b9100e7)},
188        {1, -1, -2, -2, -4, -7},
189        {CHC(0x7e6ebe18), CHC(0x42c52efe), CHC(0x45fe401f), CHC(0x7b5808ef)},
190        {-8, -2, 1, 0},
191    },
192    {
193        /* numBands=8 */
194        {CHC(0x6a3fd9b4), CHC(0x4d99823f), CHC(0x6b372a94)},
195        {-1, 0, 0},
196        {CHC(0x614c6ef7), CHC(0x4bd06699), CHC(0x6e59cfca)},
197        {3, 4, 1},
198        {CHC(0x4c389cc5), CHC(0x79686681), CHC(0x5e2544c2), CHC(0x46305b43)},
199        {-8, -6, -3, 0},
200        {CHC(0x7b4ca7c6), CHC(0x68270ac5), CHC(0x467c644c), CHC(0x505c1b0f),
201         CHC(0x67a14778), CHC(0x45801767)},
202        {0, -1, -2, -2, -5, -7},
203        {CHC(0x4c389cc5), CHC(0x5c499ceb), CHC(0x6f863c9f), CHC(0x79059bfc)},
204        {-8, -3, 0, 0},
205    },
206    {
207        /* numBands=9 */
208        {CHC(0x6aad9988), CHC(0x4ef8ac18), CHC(0x6b6df116)},
209        {-1, 0, 0},
210        {CHC(0x60b159b0), CHC(0x4b33f772), CHC(0x72f5573d)},
211        {3, 4, 1},
212        {CHC(0x6206cb18), CHC(0x58a7d8dc), CHC(0x4e0b2d0b), CHC(0x4207ad84)},
213        {-9, -6, -3, 0},
214        {CHC(0x6dadadae), CHC(0x5b8b2cfc), CHC(0x6cf61db2), CHC(0x46c3c90b),
215         CHC(0x506314ea), CHC(0x5f034acd)},
216        {0, -1, -3, -2, -5, -8},
217        {CHC(0x6206cb18), CHC(0x42f8b8de), CHC(0x5bb4776f), CHC(0x769acc79)},
218        {-9, -3, 0, 0},
219    },
220    {
221        /* numBands=10 */
222        {CHC(0x6afa7252), CHC(0x4feed3ed), CHC(0x6b94504d)},
223        {-1, 0, 0},
224        {CHC(0x60467899), CHC(0x4acbafba), CHC(0x76eb327f)},
225        {3, 4, 1},
226        {CHC(0x42415b15), CHC(0x431080da), CHC(0x420f1c32), CHC(0x7d0c1aeb)},
227        {-9, -6, -3, -1},
228        {CHC(0x62b2c7a4), CHC(0x51b040a6), CHC(0x56caddb4), CHC(0x7e74a2c8),
229         CHC(0x4030adf5), CHC(0x43d1dc4f)},
230        {0, -1, -3, -3, -5, -8},
231        {CHC(0x42415b15), CHC(0x64e299b3), CHC(0x4d33b5e8), CHC(0x742cee5f)},
232        {-9, -4, 0, 0},
233    },
234    {
235        /* numBands=11 */
236        {CHC(0x6b3258bb), CHC(0x50a21233), CHC(0x6bb03c19)},
237        {-1, 0, 0},
238        {CHC(0x5ff997c6), CHC(0x4a82706e), CHC(0x7a5aae36)},
239        {3, 4, 1},
240        {CHC(0x5d2fb4fb), CHC(0x685bddd8), CHC(0x71b5e983), CHC(0x7708c90b)},
241        {-10, -7, -4, -1},
242        {CHC(0x59aceea2), CHC(0x49c428a0), CHC(0x46ca5527), CHC(0x724be884),
243         CHC(0x68e586da), CHC(0x643485b6)},
244        {0, -1, -3, -3, -6, -9},
245        {CHC(0x5d2fb4fb), CHC(0x4e3fad1a), CHC(0x42310ba2), CHC(0x71c8b3ce)},
246        {-10, -4, 0, 0},
247    },
248    {
249        /* numBands=12 */
250        {CHC(0x6b5c4726), CHC(0x5128a4a8), CHC(0x6bc52ee1)},
251        {-1, 0, 0},
252        {CHC(0x5fc06618), CHC(0x4a4ce559), CHC(0x7d5c16e9)},
253        {3, 4, 1},
254        {CHC(0x43af8342), CHC(0x531533d3), CHC(0x633660a6), CHC(0x71ce6052)},
255        {-10, -7, -4, -1},
256        {CHC(0x522373d7), CHC(0x434150cb), CHC(0x75b58afc), CHC(0x68474f2d),
257         CHC(0x575348a5), CHC(0x4c20973f)},
258        {0, -1, -4, -3, -6, -9},
259        {CHC(0x43af8342), CHC(0x7c4d3d11), CHC(0x732e13db), CHC(0x6f756ac4)},
260        {-10, -5, -1, 0},
261    },
262    {
263        /* numBands=13 */
264        {CHC(0x6b7c8953), CHC(0x51903fcd), CHC(0x6bd54d2e)},
265        {-1, 0, 0},
266        {CHC(0x5f94abf0), CHC(0x4a2480fa), CHC(0x40013553)},
267        {3, 4, 2},
268        {CHC(0x6501236e), CHC(0x436b9c4e), CHC(0x578d7881), CHC(0x6d34f92e)},
269        {-11, -7, -4, -1},
270        {CHC(0x4bc0e2b2), CHC(0x7b9d12ac), CHC(0x636c1c1b), CHC(0x5fe15c2b),
271         CHC(0x49d54879), CHC(0x7662cfa5)},
272        {0, -2, -4, -3, -6, -10},
273        {CHC(0x6501236e), CHC(0x64b059fe), CHC(0x656d8359), CHC(0x6d370900)},
274        {-11, -5, -1, 0},
275    },
276    {
277        /* numBands=14 */
278        {CHC(0x6b95e276), CHC(0x51e1b637), CHC(0x6be1f7ed)},
279        {-1, 0, 0},
280        {CHC(0x5f727a1c), CHC(0x4a053e9c), CHC(0x412e528c)},
281        {3, 4, 2},
282        {CHC(0x4d178bd4), CHC(0x6f33b4e8), CHC(0x4e028f7f), CHC(0x691ee104)},
283        {-11, -8, -4, -1},
284        {CHC(0x46473d3f), CHC(0x725bd0a6), CHC(0x55199885), CHC(0x58bcc56b),
285         CHC(0x7e7e6288), CHC(0x5ddef6eb)},
286        {0, -2, -4, -3, -7, -10},
287        {CHC(0x4d178bd4), CHC(0x52ebd467), CHC(0x5a395a6e), CHC(0x6b0f724f)},
288        {-11, -5, -1, 0},
289    },
290    {
291        /* numBands=15 */
292        {CHC(0x6baa2a22), CHC(0x5222eb91), CHC(0x6bec1a86)},
293        {-1, 0, 0},
294        {CHC(0x5f57393b), CHC(0x49ec8934), CHC(0x423b5b58)},
295        {3, 4, 2},
296        {CHC(0x77fd2486), CHC(0x5cfbdf2c), CHC(0x46153bd1), CHC(0x65757ed9)},
297        {-12, -8, -4, -1},
298        {CHC(0x41888ee6), CHC(0x6a661db3), CHC(0x49abc8c8), CHC(0x52965848),
299         CHC(0x6d9301b7), CHC(0x4bb04721)},
300        {0, -2, -4, -3, -7, -10},
301        {CHC(0x77fd2486), CHC(0x45424c68), CHC(0x50f33cc6), CHC(0x68ff43f0)},
302        {-12, -5, -1, 0},
303    },
304    {
305        /* numBands=16 */
306        {CHC(0x6bbaa499), CHC(0x5257ed94), CHC(0x6bf456e4)},
307        {-1, 0, 0},
308        {CHC(0x5f412594), CHC(0x49d8a766), CHC(0x432d1dbd)},
309        {3, 4, 2},
310        {CHC(0x5ef5cfde), CHC(0x4eafcd2d), CHC(0x7ed36893), CHC(0x62274b45)},
311        {-12, -8, -5, -1},
312        {CHC(0x7ac438f5), CHC(0x637aab21), CHC(0x4067617a), CHC(0x4d3c6ec7),
313         CHC(0x5fd6e0dd), CHC(0x7bd5f024)},
314        {-1, -2, -4, -3, -7, -11},
315        {CHC(0x5ef5cfde), CHC(0x751d0d4f), CHC(0x492b3c41), CHC(0x67065409)},
316        {-12, -6, -1, 0},
317    },
318    {
319        /* numBands=17 */
320        {CHC(0x6bc836c9), CHC(0x5283997e), CHC(0x6bfb1f5e)},
321        {-1, 0, 0},
322        {CHC(0x5f2f02b6), CHC(0x49c868e9), CHC(0x44078151)},
323        {3, 4, 2},
324        {CHC(0x4c43b65a), CHC(0x4349dcf6), CHC(0x73799e2d), CHC(0x5f267274)},
325        {-12, -8, -5, -1},
326        {CHC(0x73726394), CHC(0x5d68511a), CHC(0x7191bbcc), CHC(0x48898c70),
327         CHC(0x548956e1), CHC(0x66981ce8)},
328        {-1, -2, -5, -3, -7, -11},
329        {CHC(0x4c43b65a), CHC(0x64131116), CHC(0x429028e2), CHC(0x65240211)},
330        {-12, -6, -1, 0},
331    },
332    {
333        /* numBands=18 */
334        {CHC(0x6bd3860d), CHC(0x52a80156), CHC(0x6c00c68d)},
335        {-1, 0, 0},
336        {CHC(0x5f1fed86), CHC(0x49baf636), CHC(0x44cdb9dc)},
337        {3, 4, 2},
338        {CHC(0x7c189389), CHC(0x742666d8), CHC(0x69b8c776), CHC(0x5c67e27d)},
339        {-13, -9, -5, -1},
340        {CHC(0x6cf1ea76), CHC(0x58095703), CHC(0x64e351a9), CHC(0x4460da90),
341         CHC(0x4b1f8083), CHC(0x55f2d3e1)},
342        {-1, -2, -5, -3, -7, -11},
343        {CHC(0x7c189389), CHC(0x5651792a), CHC(0x79cb9b3d), CHC(0x635769c0)},
344        {-13, -6, -2, 0},
345    },
346    {
347        /* numBands=19 */
348        {CHC(0x6bdd0c40), CHC(0x52c6abf6), CHC(0x6c058950)},
349        {-1, 0, 0},
350        {CHC(0x5f133f88), CHC(0x49afb305), CHC(0x45826d73)},
351        {3, 4, 2},
352        {CHC(0x6621a164), CHC(0x6512528e), CHC(0x61449fc8), CHC(0x59e2a0c0)},
353        {-13, -9, -5, -1},
354        {CHC(0x6721cadb), CHC(0x53404cd4), CHC(0x5a389e91), CHC(0x40abcbd2),
355         CHC(0x43332f01), CHC(0x48b82e46)},
356        {-1, -2, -5, -3, -7, -11},
357        {CHC(0x6621a164), CHC(0x4b12cc28), CHC(0x6ffd4df8), CHC(0x619f835e)},
358        {-13, -6, -2, 0},
359    },
360    {
361        /* numBands=20 */
362        {CHC(0x6be524c5), CHC(0x52e0beb3), CHC(0x6c099552)},
363        {-1, 0, 0},
364        {CHC(0x5f087c68), CHC(0x49a62bb5), CHC(0x4627d175)},
365        {3, 4, 2},
366        {CHC(0x54ec6afe), CHC(0x58991a42), CHC(0x59e23e8c), CHC(0x578f4ef4)},
367        {-13, -9, -5, -1},
368        {CHC(0x61e78f6f), CHC(0x4ef5e1e9), CHC(0x5129c3b8), CHC(0x7ab0f7b2),
369         CHC(0x78efb076), CHC(0x7c2567ea)},
370        {-1, -2, -5, -4, -8, -12},
371        {CHC(0x54ec6afe), CHC(0x41c7812c), CHC(0x676f6f8d), CHC(0x5ffb383f)},
372        {-13, -6, -2, 0},
373    },
374    {
375        /* numBands=21 */
376        {CHC(0x6bec1542), CHC(0x52f71929), CHC(0x6c0d0d5e)},
377        {-1, 0, 0},
378        {CHC(0x5eff45c5), CHC(0x499e092d), CHC(0x46bfc0c9)},
379        {3, 4, 2},
380        {CHC(0x47457a78), CHC(0x4e2d99b3), CHC(0x53637ea5), CHC(0x5567d0e9)},
381        {-13, -9, -5, -1},
382        {CHC(0x5d2dc61b), CHC(0x4b1760c8), CHC(0x4967cf39), CHC(0x74b113d8),
383         CHC(0x6d6676b6), CHC(0x6ad114e9)},
384        {-1, -2, -5, -4, -8, -12},
385        {CHC(0x47457a78), CHC(0x740accaa), CHC(0x5feb6609), CHC(0x5e696f95)},
386        {-13, -7, -2, 0},
387    },
388    {
389        /* numBands=22 */
390        {CHC(0x6bf21387), CHC(0x530a683c), CHC(0x6c100c59)},
391        {-1, 0, 0},
392        {CHC(0x5ef752ea), CHC(0x499708c6), CHC(0x474bcd1b)},
393        {3, 4, 2},
394        {CHC(0x78a21ab7), CHC(0x45658aec), CHC(0x4da3c4fe), CHC(0x5367094b)},
395        {-14, -9, -5, -1},
396        {CHC(0x58e2df6a), CHC(0x4795990e), CHC(0x42b5e0f7), CHC(0x6f408c64),
397         CHC(0x6370bebf), CHC(0x5c91ca85)},
398        {-1, -2, -5, -4, -8, -12},
399        {CHC(0x78a21ab7), CHC(0x66f951d6), CHC(0x594605bb), CHC(0x5ce91657)},
400        {-14, -7, -2, 0},
401    },
402    {
403        /* numBands=23 */
404        {CHC(0x6bf749b2), CHC(0x531b3348), CHC(0x6c12a750)},
405        {-1, 0, 0},
406        {CHC(0x5ef06b17), CHC(0x4990f6c9), CHC(0x47cd4c5b)},
407        {3, 4, 2},
408        {CHC(0x66dede36), CHC(0x7bdf90a9), CHC(0x4885b2b9), CHC(0x5188a6b7)},
409        {-14, -10, -5, -1},
410        {CHC(0x54f85812), CHC(0x446414ae), CHC(0x79c8d519), CHC(0x6a4c2f31),
411         CHC(0x5ac8325f), CHC(0x50bf9200)},
412        {-1, -2, -6, -4, -8, -12},
413        {CHC(0x66dede36), CHC(0x5be0d90e), CHC(0x535cc453), CHC(0x5b7923f0)},
414        {-14, -7, -2, 0},
415    },
416    {
417        /* numBands=24 */
418        {CHC(0x6bfbd91d), CHC(0x5329e580), CHC(0x6c14eeed)},
419        {-1, 0, 0},
420        {CHC(0x5eea6179), CHC(0x498baa90), CHC(0x4845635d)},
421        {3, 4, 2},
422        {CHC(0x58559b7e), CHC(0x6f1b231f), CHC(0x43f1789b), CHC(0x4fc8fcb8)},
423        {-14, -10, -5, -1},
424        {CHC(0x51621775), CHC(0x417881a3), CHC(0x6f9ba9b6), CHC(0x65c412b2),
425         CHC(0x53352c61), CHC(0x46db9caf)},
426        {-1, -2, -6, -4, -8, -12},
427        {CHC(0x58559b7e), CHC(0x52636003), CHC(0x4e13b316), CHC(0x5a189cdf)},
428        {-14, -7, -2, 0},
429    },
430    {
431        /* numBands=25 */
432        {CHC(0x6bffdc73), CHC(0x5336d4af), CHC(0x6c16f084)},
433        {-1, 0, 0},
434        {CHC(0x5ee51249), CHC(0x498703cc), CHC(0x48b50e4f)},
435        {3, 4, 2},
436        {CHC(0x4c5616cf), CHC(0x641b9fad), CHC(0x7fa735e0), CHC(0x4e24e57a)},
437        {-14, -10, -6, -1},
438        {CHC(0x4e15f47a), CHC(0x7d9481d6), CHC(0x66a82f8a), CHC(0x619ae971),
439         CHC(0x4c8b2f5f), CHC(0x7d09ec11)},
440        {-1, -3, -6, -4, -8, -13},
441        {CHC(0x4c5616cf), CHC(0x4a3770fb), CHC(0x495402de), CHC(0x58c693fa)},
442        {-14, -7, -2, 0},
443    },
444    {
445        /* numBands=26 */
446        {CHC(0x6c036943), CHC(0x53424625), CHC(0x6c18b6dc)},
447        {-1, 0, 0},
448        {CHC(0x5ee060aa), CHC(0x4982e88a), CHC(0x491d277f)},
449        {3, 4, 2},
450        {CHC(0x425ada5b), CHC(0x5a9368ac), CHC(0x78380a42), CHC(0x4c99aa05)},
451        {-14, -10, -6, -1},
452        {CHC(0x4b0b569c), CHC(0x78a420da), CHC(0x5ebdf203), CHC(0x5dc57e63),
453         CHC(0x46a650ff), CHC(0x6ee13fb8)},
454        {-1, -3, -6, -4, -8, -13},
455        {CHC(0x425ada5b), CHC(0x4323073c), CHC(0x450ae92b), CHC(0x57822ad5)},
456        {-14, -7, -2, 0},
457    },
458    {
459        /* numBands=27 */
460        {CHC(0x6c06911a), CHC(0x534c7261), CHC(0x6c1a4aba)},
461        {-1, 0, 0},
462        {CHC(0x5edc3524), CHC(0x497f43c0), CHC(0x497e6cd8)},
463        {3, 4, 2},
464        {CHC(0x73fb550e), CHC(0x5244894f), CHC(0x717aad78), CHC(0x4b24ef6c)},
465        {-15, -10, -6, -1},
466        {CHC(0x483aebe4), CHC(0x74139116), CHC(0x57b58037), CHC(0x5a3a4f3c),
467         CHC(0x416950fe), CHC(0x62c7f4f2)},
468        {-1, -3, -6, -4, -8, -13},
469        {CHC(0x73fb550e), CHC(0x79efb994), CHC(0x4128cab7), CHC(0x564a919a)},
470        {-15, -8, -2, 0},
471    },
472    {
473        /* numBands=28 */
474        {CHC(0x6c096264), CHC(0x535587cd), CHC(0x6c1bb355)},
475        {-1, 0, 0},
476        {CHC(0x5ed87c76), CHC(0x497c0439), CHC(0x49d98452)},
477        {3, 4, 2},
478        {CHC(0x65dec5bf), CHC(0x4afd1ba3), CHC(0x6b58b4b3), CHC(0x49c4a7b0)},
479        {-15, -10, -6, -1},
480        {CHC(0x459e6eb1), CHC(0x6fd850b7), CHC(0x516e7be9), CHC(0x56f13d05),
481         CHC(0x79785594), CHC(0x58617de7)},
482        {-1, -3, -6, -4, -9, -13},
483        {CHC(0x65dec5bf), CHC(0x6f2168aa), CHC(0x7b41310f), CHC(0x551f0692)},
484        {-15, -8, -3, 0},
485    },
486    {
487        /* numBands=29 */
488        {CHC(0x6c0be913), CHC(0x535dacd5), CHC(0x6c1cf6a3)},
489        {-1, 0, 0},
490        {CHC(0x5ed526b4), CHC(0x49791bc5), CHC(0x4a2eff99)},
491        {3, 4, 2},
492        {CHC(0x59e44afe), CHC(0x44949ada), CHC(0x65bf36f5), CHC(0x487705a0)},
493        {-15, -10, -6, -1},
494        {CHC(0x43307779), CHC(0x6be959c4), CHC(0x4bce2122), CHC(0x53e34d89),
495         CHC(0x7115ff82), CHC(0x4f6421a1)},
496        {-1, -3, -6, -4, -9, -13},
497        {CHC(0x59e44afe), CHC(0x659eab7d), CHC(0x74cea459), CHC(0x53fed574)},
498        {-15, -8, -3, 0},
499    },
500    {
501        /* numBands=30 */
502        {CHC(0x6c0e2f17), CHC(0x53650181), CHC(0x6c1e199d)},
503        {-1, 0, 0},
504        {CHC(0x5ed2269f), CHC(0x49767e9e), CHC(0x4a7f5f0b)},
505        {3, 4, 2},
506        {CHC(0x4faa4ae6), CHC(0x7dd3bf11), CHC(0x609e2732), CHC(0x473a72e9)},
507        {-15, -11, -6, -1},
508        {CHC(0x40ec57c6), CHC(0x683ee147), CHC(0x46be261d), CHC(0x510a7983),
509         CHC(0x698a84cb), CHC(0x4794a927)},
510        {-1, -3, -6, -4, -9, -13},
511        {CHC(0x4faa4ae6), CHC(0x5d3615ad), CHC(0x6ee74773), CHC(0x52e956a1)},
512        {-15, -8, -3, 0},
513    },
514    {
515        /* numBands=31 */
516        {CHC(0x6c103cc9), CHC(0x536ba0ac), CHC(0x6c1f2070)},
517        {-1, 0, 0},
518        {CHC(0x5ecf711e), CHC(0x497422ea), CHC(0x4acb1438)},
519        {3, 4, 2},
520        {CHC(0x46e322ad), CHC(0x73c32f3c), CHC(0x5be7d172), CHC(0x460d8800)},
521        {-15, -11, -6, -1},
522        {CHC(0x7d9bf8ad), CHC(0x64d22351), CHC(0x422bdc81), CHC(0x4e6184aa),
523         CHC(0x62ba2375), CHC(0x40c325de)},
524        {-2, -3, -6, -4, -9, -13},
525        {CHC(0x46e322ad), CHC(0x55bef2a3), CHC(0x697b3135), CHC(0x51ddee4d)},
526        {-15, -8, -3, 0},
527    },
528    {
529        // numBands=32
530        {CHC(0x6c121933), CHC(0x5371a104), CHC(0x6c200ea0)},
531        {-1, 0, 0},
532        {CHC(0x5eccfcd3), CHC(0x49720060), CHC(0x4b1283f0)},
533        {3, 4, 2},
534        {CHC(0x7ea12a52), CHC(0x6aca3303), CHC(0x579072bf), CHC(0x44ef056e)},
535        {-16, -11, -6, -1},
536        {CHC(0x79a3a9ab), CHC(0x619d38fc), CHC(0x7c0f0734), CHC(0x4be3dd5d),
537         CHC(0x5c8d7163), CHC(0x7591065f)},
538        {-2, -3, -7, -4, -9, -14},
539        {CHC(0x7ea12a52), CHC(0x4f1782a6), CHC(0x647cbcb2), CHC(0x50dc0bb1)},
540        {-16, -8, -3, 0},
541    },
542};
543
544/** \def  SUM_SAFETY
545 *
546 *  SUM_SAFTEY defines the bits needed to right-shift every summand in
547 *  order to be overflow-safe. In the two backsubst functions we sum up 4
548 *  values. Since one of which is definitely not MAXVAL_DBL (the L[x][y]),
549 *  we spare just 2 safety bits instead of 3.
550 */
551#define SUM_SAFETY 2
552
553/**
554 * \brief  Solves L*x=b via backsubstitution according to the following
555 * structure:
556 *
557 *  x[0] =  b[0];
558 *  x[1] = (b[1]                               - x[0]) / L[1][1];
559 *  x[2] = (b[2] - x[1]*L[2][1]                - x[0]) / L[2][2];
560 *  x[3] = (b[3] - x[2]*L[3][2] - x[1]*L[3][1] - x[0]) / L[3][3];
561 *
562 * \param[in]  numBands  SBR crossover band index
563 * \param[in]  b         the b in L*x=b (one-dimensional)
564 * \param[out] x         output polynomial coefficients (mantissa)
565 * \param[out] x_sf      exponents of x[]
566 */
567static void backsubst_fw(const int numBands, const FIXP_DBL *const b,
568                         FIXP_DBL *RESTRICT x, int *RESTRICT x_sf) {
569  int i, k;
570  int m; /* the trip counter that indexes incrementally through Lnorm1d[] */
571
572  const FIXP_CHB *RESTRICT pLnorm1d = bsd[numBands - BSD_IDX_OFFSET].Lnorm1d;
573  const SCHAR *RESTRICT pLnorm1d_sf = bsd[numBands - BSD_IDX_OFFSET].Lnorm1d_sf;
574  const FIXP_CHB *RESTRICT pLnormii = bsd[numBands - BSD_IDX_OFFSET].Lnormii;
575  const SCHAR *RESTRICT pLnormii_sf = bsd[numBands - BSD_IDX_OFFSET].Lnormii_sf;
576
577  x[0] = b[0];
578
579  for (i = 1, m = 0; i <= POLY_ORDER; ++i) {
580    FIXP_DBL sum = b[i] >> SUM_SAFETY;
581    int sum_sf = x_sf[i];
582    for (k = i - 1; k > 0; --k, ++m) {
583      int e;
584      FIXP_DBL mult = fMultNorm(FX_CHB2FX_DBL(pLnorm1d[m]), x[k], &e);
585      int mult_sf = pLnorm1d_sf[m] + x_sf[k] + e;
586
587      /* check if the new summand mult has a different sf than the sum currently
588       * has */
589      int diff = mult_sf - sum_sf;
590
591      if (diff > 0) {
592        /* yes, and it requires the sum to be adjusted (scaled down) */
593        sum >>= diff;
594        sum_sf = mult_sf;
595      } else if (diff < 0) {
596        /* yes, but here mult needs to be scaled down */
597        mult >>= -diff;
598      }
599      sum -= (mult >> SUM_SAFETY);
600    }
601
602    /* - x[0] */
603    if (x_sf[0] > sum_sf) {
604      sum >>= (x_sf[0] - sum_sf);
605      sum_sf = x_sf[0];
606    }
607    sum -= (x[0] >> (sum_sf - x_sf[0] + SUM_SAFETY));
608
609    /* instead of the division /L[i][i], we multiply by the inverse */
610    int e;
611    x[i] = fMultNorm(sum, FX_CHB2FX_DBL(pLnormii[i - 1]), &e);
612    x_sf[i] = sum_sf + pLnormii_sf[i - 1] + e + SUM_SAFETY;
613  }
614}
615
616/**
617 * \brief Solves L*x=b via backsubstitution according to the following
618 * structure:
619 *
620 *  x[3] = b[3];
621 *  x[2] = b[2] - L[2][3]*x[3];
622 *  x[1] = b[1] - L[1][2]*x[2] - L[1][3]*x[3];
623 *  x[0] = b[0] - L[0][1]*x[1] - L[0][2]*x[2] - L[0][3]*x[3];
624 *
625 * \param[in]  numBands  SBR crossover band index
626 * \param[in]  b         the b in L*x=b (one-dimensional)
627 * \param[out] x         solution vector
628 * \param[out] x_sf      exponents of x[]
629 */
630static void backsubst_bw(const int numBands, const FIXP_DBL *const b,
631                         FIXP_DBL *RESTRICT x, int *RESTRICT x_sf) {
632  int i, k;
633  int m; /* the trip counter that indexes incrementally through LnormInv1d[] */
634
635  const FIXP_CHB *RESTRICT pLnormInv1d =
636      bsd[numBands - BSD_IDX_OFFSET].LnormInv1d;
637  const SCHAR *RESTRICT pLnormInv1d_sf =
638      bsd[numBands - BSD_IDX_OFFSET].LnormInv1d_sf;
639
640  x[POLY_ORDER] = b[POLY_ORDER];
641
642  for (i = POLY_ORDER - 1, m = 0; i >= 0; i--) {
643    FIXP_DBL sum = b[i] >> SUM_SAFETY;
644    int sum_sf = x_sf[i]; /* sum's sf but disregarding SUM_SAFETY (added at the
645                             iteration's end) */
646
647    for (k = i + 1; k <= POLY_ORDER; ++k, ++m) {
648      int e;
649      FIXP_DBL mult = fMultNorm(FX_CHB2FX_DBL(pLnormInv1d[m]), x[k], &e);
650      int mult_sf = pLnormInv1d_sf[m] + x_sf[k] + e;
651
652      /* check if the new summand mult has a different sf than sum currently has
653       */
654      int diff = mult_sf - sum_sf;
655
656      if (diff > 0) {
657        /* yes, and it requires the sum v to be adjusted (scaled down) */
658        sum >>= diff;
659        sum_sf = mult_sf;
660      } else if (diff < 0) {
661        /* yes, but here mult needs to be scaled down */
662        mult >>= -diff;
663      }
664
665      /* mult has now the same sf than what it is about to be added to. */
666      /* scale mult down additionally so that building the sum is overflow-safe.
667       */
668      sum -= (mult >> SUM_SAFETY);
669    }
670
671    x_sf[i] = sum_sf + SUM_SAFETY;
672    x[i] = sum;
673  }
674}
675
676/**
677 * \brief  Solves a system of linear equations (L*x=b) with the Cholesky
678 * algorithm.
679 *
680 * \param[in]     numBands  SBR crossover band index
681 * \param[in,out] b         input: vector b, output: solution vector p.
682 * \param[in,out] b_sf      input: exponent of b; output: exponent of solution
683 * p.
684 */
685static void choleskySolve(const int numBands, FIXP_DBL *RESTRICT b,
686                          int *RESTRICT b_sf) {
687  int i, e;
688
689  const FIXP_CHB *RESTRICT pBmul0 = bsd[numBands - BSD_IDX_OFFSET].Bmul0;
690  const SCHAR *RESTRICT pBmul0_sf = bsd[numBands - BSD_IDX_OFFSET].Bmul0_sf;
691  const FIXP_CHB *RESTRICT pBmul1 = bsd[numBands - BSD_IDX_OFFSET].Bmul1;
692  const SCHAR *RESTRICT pBmul1_sf = bsd[numBands - BSD_IDX_OFFSET].Bmul1_sf;
693
694  /* normalize b */
695  FIXP_DBL bnormed[POLY_ORDER + 1];
696  for (i = 0; i <= POLY_ORDER; ++i) {
697    bnormed[i] = fMultNorm(b[i], FX_CHB2FX_DBL(pBmul0[i]), &e);
698    b_sf[i] += pBmul0_sf[i] + e;
699  }
700
701  backsubst_fw(numBands, bnormed, b, b_sf);
702
703  /* normalize b again */
704  for (i = 0; i <= POLY_ORDER; ++i) {
705    bnormed[i] = fMultNorm(b[i], FX_CHB2FX_DBL(pBmul1[i]), &e);
706    b_sf[i] += pBmul1_sf[i] + e;
707  }
708
709  backsubst_bw(numBands, bnormed, b, b_sf);
710}
711
712/**
713 * \brief  Find polynomial approximation of vector y with implicit abscisas
714 * x=0,1,2,3..n-1
715 *
716 *  The problem (V^T * V * p = V^T * y) is solved with Cholesky.
717 *  V is the Vandermode Matrix constructed with x = 0...n-1;
718 *  A = V^T * V; b = V^T * y;
719 *
720 * \param[in]  numBands  SBR crossover band index (BSD_IDX_OFFSET <= numBands <=
721 * MAXLOWBANDS)
722 * \param[in]  y         input vector (mantissa)
723 * \param[in]  y_sf      exponents of y[]
724 * \param[out] p         output polynomial coefficients (mantissa)
725 * \param[out] p_sf      exponents of p[]
726 */
727static void polyfit(const int numBands, const FIXP_DBL *const y, const int y_sf,
728                    FIXP_DBL *RESTRICT p, int *RESTRICT p_sf) {
729  int i, k;
730  LONG v[POLY_ORDER + 1];
731  int sum_saftey = getLog2[numBands - 1];
732
733  FDK_ASSERT((numBands >= BSD_IDX_OFFSET) && (numBands <= MAXLOWBANDS));
734
735  /* construct vector b[] temporarily stored in array p[] */
736  FDKmemclear(p, (POLY_ORDER + 1) * sizeof(FIXP_DBL));
737
738  /* p[] are the sums over n values and each p[i] has its own sf */
739  for (i = 0; i <= POLY_ORDER; ++i) p_sf[i] = 1 - DFRACT_BITS;
740
741  for (k = 0; k < numBands; k++) {
742    v[0] = (LONG)1;
743    for (i = 1; i <= POLY_ORDER; i++) {
744      v[i] = k * v[i - 1];
745    }
746
747    for (i = 0; i <= POLY_ORDER; i++) {
748      if (v[POLY_ORDER - i] != 0 && y[k] != FIXP_DBL(0)) {
749        int e;
750        FIXP_DBL mult = fMultNorm((FIXP_DBL)v[POLY_ORDER - i], y[k], &e);
751        int sf = DFRACT_BITS - 1 + y_sf + e;
752
753        /* check if the new summand has a different sf than the sum p[i]
754         * currently has */
755        int diff = sf - p_sf[i];
756
757        if (diff > 0) {
758          /* yes, and it requires the sum p[i] to be adjusted (scaled down) */
759          p[i] >>= fMin(DFRACT_BITS - 1, diff);
760          p_sf[i] = sf;
761        } else if (diff < 0) {
762          /* yes, but here mult needs to be scaled down */
763          mult >>= -diff;
764        }
765
766        /* mult has now the same sf than what it is about to be added to.
767           scale mult down additionally so that building the sum is
768           overflow-safe. */
769        p[i] += mult >> sum_saftey;
770      }
771    }
772  }
773
774  p_sf[0] += sum_saftey;
775  p_sf[1] += sum_saftey;
776  p_sf[2] += sum_saftey;
777  p_sf[3] += sum_saftey;
778
779  choleskySolve(numBands, p, p_sf);
780}
781
782/**
783 * \brief  Calculates the output of a POLY_ORDER-degree polynomial function
784 *         with Horner scheme:
785 *
786 *         y(x) = p3 + p2*x + p1*x^2 + p0*x^3
787 *              = p3 + x*(p2 + x*(p1 + x*p0))
788 *
789 *         The for loop iterates through the mult/add parts in y(x) as above,
790 *         during which regular upscaling ensures a stable exponent of the
791 *         result.
792 *
793 * \param[in]  p       coefficients as in y(x)
794 * \param[in]  p_sf    exponents of p[]
795 * \param[in]  x_int   non-fractional integer representation of x as in y(x)
796 * \param[out] out_sf  exponent of return value
797 *
798 * \return             result y(x)
799 */
800static FIXP_DBL polyval(const FIXP_DBL *const p, const int *const p_sf,
801                        const int x_int, int *out_sf) {
802  FDK_ASSERT(x_int <= 31); /* otherwise getLog2[] needs more elements */
803
804  int k, x_sf;
805  int result_sf;   /* working space to compute return value *out_sf */
806  FIXP_DBL x;      /* fractional value of x_int */
807  FIXP_DBL result; /* return value */
808
809  /* if x == 0, then y(x) is just p3 */
810  if (x_int != 0) {
811    x_sf = getLog2[x_int];
812    x = (FIXP_DBL)x_int << (DFRACT_BITS - 1 - x_sf);
813  } else {
814    *out_sf = p_sf[3];
815    return p[3];
816  }
817
818  result = p[0];
819  result_sf = p_sf[0];
820
821  for (k = 1; k <= POLY_ORDER; ++k) {
822    FIXP_DBL mult = fMult(x, result);
823    int mult_sf = x_sf + result_sf;
824
825    int room = CountLeadingBits(mult);
826    mult <<= room;
827    mult_sf -= room;
828
829    FIXP_DBL pp = p[k];
830    int pp_sf = p_sf[k];
831
832    /* equalize the shift factors of pp and mult so that we can sum them up */
833    int diff = pp_sf - mult_sf;
834
835    if (diff > 0) {
836      diff = fMin(diff, DFRACT_BITS - 1);
837      mult >>= diff;
838    } else if (diff < 0) {
839      diff = fMax(diff, 1 - DFRACT_BITS);
840      pp >>= -diff;
841    }
842
843    /* downshift by 1 to ensure safe summation */
844    mult >>= 1;
845    mult_sf++;
846    pp >>= 1;
847    pp_sf++;
848
849    result_sf = fMax(pp_sf, mult_sf);
850
851    result = mult + pp;
852    /* rarely, mult and pp happen to be almost equal except their sign,
853    and then upon summation, result becomes so small, that it is within
854    the inaccuracy range of a few bits, and then the relative error
855    produced by this function may become HUGE */
856  }
857
858  *out_sf = result_sf;
859  return result;
860}
861
862void sbrDecoder_calculateGainVec(FIXP_DBL **sourceBufferReal,
863                                 FIXP_DBL **sourceBufferImag,
864                                 int sourceBuf_e_overlap,
865                                 int sourceBuf_e_current, int overlap,
866                                 FIXP_DBL *RESTRICT GainVec, int *GainVec_exp,
867                                 int numBands, const int startSample,
868                                 const int stopSample) {
869  FIXP_DBL p[POLY_ORDER + 1];
870  FIXP_DBL meanNrg;
871  FIXP_DBL LowEnv[MAXLOWBANDS];
872  FIXP_DBL invNumBands = GetInvInt(numBands);
873  FIXP_DBL invNumSlots = GetInvInt(stopSample - startSample);
874  int i, loBand, exp, scale_nrg, scale_nrg_ov;
875  int sum_scale = 5, sum_scale_ov = 3;
876
877  if (overlap > 8) {
878    FDK_ASSERT(overlap <= 16);
879    sum_scale_ov += 1;
880    sum_scale += 1;
881  }
882
883  /* exponents of energy values */
884  sourceBuf_e_overlap = sourceBuf_e_overlap * 2 + sum_scale_ov;
885  sourceBuf_e_current = sourceBuf_e_current * 2 + sum_scale;
886  exp = fMax(sourceBuf_e_overlap, sourceBuf_e_current);
887  scale_nrg = sourceBuf_e_current - exp;
888  scale_nrg_ov = sourceBuf_e_overlap - exp;
889
890  meanNrg = (FIXP_DBL)0;
891  /* Calculate the spectral envelope in dB over the current copy-up frame. */
892  for (loBand = 0; loBand < numBands; loBand++) {
893    FIXP_DBL nrg_ov, nrg;
894    INT reserve = 0, exp_new;
895    FIXP_DBL maxVal = FL2FX_DBL(0.0f);
896
897    for (i = startSample; i < stopSample; i++) {
898      maxVal |=
899          (FIXP_DBL)((LONG)(sourceBufferReal[i][loBand]) ^
900                     ((LONG)sourceBufferReal[i][loBand] >> (SAMPLE_BITS - 1)));
901      maxVal |=
902          (FIXP_DBL)((LONG)(sourceBufferImag[i][loBand]) ^
903                     ((LONG)sourceBufferImag[i][loBand] >> (SAMPLE_BITS - 1)));
904    }
905
906    if (maxVal != FL2FX_DBL(0.0f)) {
907      reserve = fixMax(0, CntLeadingZeros(maxVal) - 2);
908    }
909
910    nrg_ov = nrg = (FIXP_DBL)0;
911    if (scale_nrg_ov > -31) {
912      for (i = startSample; i < overlap; i++) {
913        nrg_ov += (fPow2Div2(sourceBufferReal[i][loBand] << reserve) +
914                   fPow2Div2(sourceBufferImag[i][loBand] << reserve)) >>
915                  sum_scale_ov;
916      }
917    } else {
918      scale_nrg_ov = 0;
919    }
920    if (scale_nrg > -31) {
921      for (i = overlap; i < stopSample; i++) {
922        nrg += (fPow2Div2(sourceBufferReal[i][loBand] << reserve) +
923                fPow2Div2(sourceBufferImag[i][loBand] << reserve)) >>
924               sum_scale;
925      }
926    } else {
927      scale_nrg = 0;
928    }
929
930    nrg = (scaleValue(nrg_ov, scale_nrg_ov) >> 1) +
931          (scaleValue(nrg, scale_nrg) >> 1);
932    nrg = fMult(nrg, invNumSlots);
933
934    exp_new =
935        exp - (2 * reserve) +
936        2; /* +1 for addition directly above, +1 for fPow2Div2 in loops above */
937
938    /* LowEnv = 10*log10(nrg) = log2(nrg) * 10/log2(10) */
939    /* exponent of logarithmic energy is 8 */
940    if (nrg > (FIXP_DBL)0) {
941      int exp_log2;
942      nrg = CalcLog2(nrg, exp_new, &exp_log2);
943      nrg = scaleValue(nrg, exp_log2 - 6);
944      nrg = fMult(FL2FXCONST_SGL(LOG10FAC), nrg);
945    } else {
946      nrg = (FIXP_DBL)0;
947    }
948    LowEnv[loBand] = nrg;
949    meanNrg += fMult(nrg, invNumBands);
950  }
951  exp = 6 + 2; /* exponent of LowEnv: +2 is exponent of LOG10FAC */
952
953  /* subtract mean before polynomial approximation to reduce dynamic of p[] */
954  for (loBand = 0; loBand < numBands; loBand++) {
955    LowEnv[loBand] = meanNrg - LowEnv[loBand];
956  }
957
958  /* For numBands < BSD_IDX_OFFSET (== POLY_ORDER+2) we dont get an
959     overdetermined equation system. The calculated polynomial will exactly fit
960     the input data and evaluating the polynomial will lead to the same vector
961     than the original input vector: lowEnvSlope[] == lowEnv[]
962  */
963  if (numBands > POLY_ORDER + 1) {
964    /* Find polynomial approximation of LowEnv */
965    int p_sf[POLY_ORDER + 1];
966
967    polyfit(numBands, LowEnv, exp, p, p_sf);
968
969    for (i = 0; i < numBands; i++) {
970      int sf;
971
972      /* lowBandEnvSlope[i] = tmp; */
973      FIXP_DBL tmp = polyval(p, p_sf, i, &sf);
974
975      /* GainVec = 10^((mean(y)-y)/20) = 2^( (mean(y)-y) * log2(10)/20 ) */
976      tmp = fMult(tmp, FL2FXCONST_SGL(LOG10FAC_INV));
977      GainVec[i] = f2Pow(tmp, sf - 2,
978                         &GainVec_exp[i]); /* -2 is exponent of LOG10FAC_INV */
979    }
980  } else { /* numBands <= POLY_ORDER+1 */
981    for (i = 0; i < numBands; i++) {
982      int sf = exp; /* exponent of LowEnv[] */
983
984      /* lowBandEnvSlope[i] = LowEnv[i]; */
985      FIXP_DBL tmp = LowEnv[i];
986
987      /* GainVec = 10^((mean(y)-y)/20) = 2^( (mean(y)-y) * log2(10)/20 ) */
988      tmp = fMult(tmp, FL2FXCONST_SGL(LOG10FAC_INV));
989      GainVec[i] = f2Pow(tmp, sf - 2,
990                         &GainVec_exp[i]); /* -2 is exponent of LOG10FAC_INV */
991    }
992  }
993}
994