sbr_hfadj.c

00001 /*
00002 ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
00003 ** Copyright (C) 2003-2005 M. Bakker, Ahead Software AG, http://www.nero.com
00004 **  
00005 ** This program is free software; you can redistribute it and/or modify
00006 ** it under the terms of the GNU General Public License as published by
00007 ** the Free Software Foundation; either version 2 of the License, or
00008 ** (at your option) any later version.
00009 ** 
00010 ** This program is distributed in the hope that it will be useful,
00011 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 ** GNU General Public License for more details.
00014 ** 
00015 ** You should have received a copy of the GNU General Public License
00016 ** along with this program; if not, write to the Free Software 
00017 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018 **
00019 ** Any non-GPL usage of this software or parts of this software is strictly
00020 ** forbidden.
00021 **
00022 ** Software using this code must display the following message visibly in the
00023 ** software:
00024 ** "FAAD2 AAC/HE-AAC/HE-AACv2/DRM decoder (c) Ahead Software, www.nero.com"
00025 ** in, for example, the about-box or help/startup screen.
00026 **
00027 ** Commercial non-GPL licensing of this software is possible.
00028 ** For more info contact Ahead Software through [email protected].
00029 **
00030 ** $Id: sbr_hfadj.c,v 1.2 2005/11/01 21:41:43 gabest Exp $
00031 **/
00032 
00033 /* High Frequency adjustment */
00034 
00035 #include "common.h"
00036 #include "structs.h"
00037 
00038 #ifdef SBR_DEC
00039 
00040 #include "sbr_syntax.h"
00041 #include "sbr_hfadj.h"
00042 
00043 #include "sbr_noise.h"
00044 
00045 
00046 /* static function declarations */
00047 static uint8_t estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj,
00048                                          qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch);
00049 static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch);
00050 #ifdef SBR_LOW_POWER
00051 static void calc_gain_groups(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch);
00052 static void aliasing_reduction(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch);
00053 #endif
00054 static void hf_assembly(sbr_info *sbr, sbr_hfadj_info *adj, qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch);
00055 
00056 
00057 uint8_t hf_adjustment(sbr_info *sbr, qmf_t Xsbr[MAX_NTSRHFG][64]
00058 #ifdef SBR_LOW_POWER
00059                       ,real_t *deg /* aliasing degree */
00060 #endif
00061                       ,uint8_t ch)
00062 {
00063     ALIGN sbr_hfadj_info adj = {{{0}}};
00064     uint8_t ret = 0;
00065 
00066     if (sbr->bs_frame_class[ch] == FIXFIX)
00067     {
00068         sbr->l_A[ch] = -1;
00069     } else if (sbr->bs_frame_class[ch] == VARFIX) {
00070         if (sbr->bs_pointer[ch] > 1)
00071             sbr->l_A[ch] = -1;
00072         else
00073             sbr->l_A[ch] = sbr->bs_pointer[ch] - 1;
00074     } else {
00075         if (sbr->bs_pointer[ch] == 0)
00076             sbr->l_A[ch] = -1;
00077         else
00078             sbr->l_A[ch] = sbr->L_E[ch] + 1 - sbr->bs_pointer[ch];
00079     }
00080 
00081     ret = estimate_current_envelope(sbr, &adj, Xsbr, ch);
00082     if (ret > 0)
00083         return 1;
00084 
00085     calculate_gain(sbr, &adj, ch);
00086 
00087 #ifdef SBR_LOW_POWER
00088     calc_gain_groups(sbr, &adj, deg, ch);
00089     aliasing_reduction(sbr, &adj, deg, ch);
00090 #endif
00091 
00092     hf_assembly(sbr, &adj, Xsbr, ch);
00093 
00094     return 0;
00095 }
00096 
00097 static uint8_t get_S_mapped(sbr_info *sbr, uint8_t ch, uint8_t l, uint8_t current_band)
00098 {
00099     if (sbr->f[ch][l] == HI_RES)
00100     {
00101         /* in case of using f_table_high we just have 1 to 1 mapping
00102          * from bs_add_harmonic[l][k]
00103          */
00104         if ((l >= sbr->l_A[ch]) ||
00105             (sbr->bs_add_harmonic_prev[ch][current_band] && sbr->bs_add_harmonic_flag_prev[ch]))
00106         {
00107             return sbr->bs_add_harmonic[ch][current_band];
00108         }
00109     } else {
00110         uint8_t b, lb, ub;
00111 
00112         /* in case of f_table_low we check if any of the HI_RES bands
00113          * within this LO_RES band has bs_add_harmonic[l][k] turned on
00114          * (note that borders in the LO_RES table are also present in
00115          * the HI_RES table)
00116          */
00117 
00118         /* find first HI_RES band in current LO_RES band */
00119         lb = 2*current_band - ((sbr->N_high & 1) ? 1 : 0);
00120         /* find first HI_RES band in next LO_RES band */
00121         ub = 2*(current_band+1) - ((sbr->N_high & 1) ? 1 : 0);
00122 
00123         /* check all HI_RES bands in current LO_RES band for sinusoid */
00124         for (b = lb; b < ub; b++)
00125         {
00126             if ((l >= sbr->l_A[ch]) ||
00127                 (sbr->bs_add_harmonic_prev[ch][b] && sbr->bs_add_harmonic_flag_prev[ch]))
00128             {
00129                 if (sbr->bs_add_harmonic[ch][b] == 1)
00130                     return 1;
00131             }
00132         }
00133     }
00134 
00135     return 0;
00136 }
00137 
00138 static uint8_t estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj,
00139                                          qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch)
00140 {
00141     uint8_t m, l, j, k, k_l, k_h, p;
00142     real_t nrg, div;
00143 
00144     if (sbr->bs_interpol_freq == 1)
00145     {
00146         for (l = 0; l < sbr->L_E[ch]; l++)
00147         {
00148             uint8_t i, l_i, u_i;
00149 
00150             l_i = sbr->t_E[ch][l];
00151             u_i = sbr->t_E[ch][l+1];
00152 
00153             div = (real_t)(u_i - l_i);
00154 
00155             if (div == 0)
00156                 div = 1;
00157 
00158             for (m = 0; m < sbr->M; m++)
00159             {
00160                 nrg = 0;
00161 
00162                 for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
00163                 {
00164 #ifdef FIXED_POINT
00165 #ifdef SBR_LOW_POWER
00166                     nrg += ((QMF_RE(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS);
00167 #else
00168                     nrg += ((QMF_RE(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS) +
00169                         ((QMF_IM(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_IM(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS);
00170 #endif
00171 #else
00172                     nrg += MUL_R(QMF_RE(Xsbr[i][m + sbr->kx]), QMF_RE(Xsbr[i][m + sbr->kx]))
00173 #ifndef SBR_LOW_POWER
00174                         + MUL_R(QMF_IM(Xsbr[i][m + sbr->kx]), QMF_IM(Xsbr[i][m + sbr->kx]))
00175 #endif
00176                         ;
00177 #endif
00178                 }
00179 
00180                 sbr->E_curr[ch][m][l] = nrg / div;
00181 #ifdef SBR_LOW_POWER
00182 #ifdef FIXED_POINT
00183                 sbr->E_curr[ch][m][l] <<= 1;
00184 #else
00185                 sbr->E_curr[ch][m][l] *= 2;
00186 #endif
00187 #endif
00188             }
00189         }
00190     } else {
00191         for (l = 0; l < sbr->L_E[ch]; l++)
00192         {
00193             for (p = 0; p < sbr->n[sbr->f[ch][l]]; p++)
00194             {
00195                 k_l = sbr->f_table_res[sbr->f[ch][l]][p];
00196                 k_h = sbr->f_table_res[sbr->f[ch][l]][p+1];
00197 
00198                 for (k = k_l; k < k_h; k++)
00199                 {
00200                     uint8_t i, l_i, u_i;
00201                     nrg = 0;
00202 
00203                     l_i = sbr->t_E[ch][l];
00204                     u_i = sbr->t_E[ch][l+1];
00205 
00206                     div = (real_t)((u_i - l_i)*(k_h - k_l));
00207 
00208                     if (div == 0)
00209                         div = 1;
00210 
00211                     for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++)
00212                     {
00213                         for (j = k_l; j < k_h; j++)
00214                         {
00215 #ifdef FIXED_POINT
00216 #ifdef SBR_LOW_POWER
00217                             nrg += ((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS);
00218 #else
00219                             nrg += ((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS) +
00220                                 ((QMF_IM(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_IM(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS);
00221 #endif
00222 #else
00223                             nrg += MUL_R(QMF_RE(Xsbr[i][j]), QMF_RE(Xsbr[i][j]))
00224 #ifndef SBR_LOW_POWER
00225                                 + MUL_R(QMF_IM(Xsbr[i][j]), QMF_IM(Xsbr[i][j]))
00226 #endif
00227                                 ;
00228 #endif
00229                         }
00230                     }
00231 
00232                     sbr->E_curr[ch][k - sbr->kx][l] = nrg / div;
00233 #ifdef SBR_LOW_POWER
00234 #ifdef FIXED_POINT
00235                     sbr->E_curr[ch][k - sbr->kx][l] <<= 1;
00236 #else
00237                     sbr->E_curr[ch][k - sbr->kx][l] *= 2;
00238 #endif
00239 #endif
00240                 }
00241             }
00242         }
00243     }
00244 
00245     return 0;
00246 }
00247 
00248 #ifdef FIXED_POINT
00249 #define EPS (1) /* smallest number available in fixed point */
00250 #else
00251 #define EPS (1e-12)
00252 #endif
00253 
00254 
00255 
00256 #ifdef FIXED_POINT
00257 
00258 /* log2 values of [0..63] */
00259 static const real_t log2_int_tab[] = {
00260     LOG2_MIN_INF, REAL_CONST(0.000000000000000), REAL_CONST(1.000000000000000), REAL_CONST(1.584962500721156),
00261     REAL_CONST(2.000000000000000), REAL_CONST(2.321928094887362), REAL_CONST(2.584962500721156), REAL_CONST(2.807354922057604),
00262     REAL_CONST(3.000000000000000), REAL_CONST(3.169925001442313), REAL_CONST(3.321928094887363), REAL_CONST(3.459431618637297),
00263     REAL_CONST(3.584962500721156), REAL_CONST(3.700439718141092), REAL_CONST(3.807354922057604), REAL_CONST(3.906890595608519),
00264     REAL_CONST(4.000000000000000), REAL_CONST(4.087462841250339), REAL_CONST(4.169925001442312), REAL_CONST(4.247927513443585),
00265     REAL_CONST(4.321928094887362), REAL_CONST(4.392317422778761), REAL_CONST(4.459431618637297), REAL_CONST(4.523561956057013),
00266     REAL_CONST(4.584962500721156), REAL_CONST(4.643856189774724), REAL_CONST(4.700439718141093), REAL_CONST(4.754887502163468),
00267     REAL_CONST(4.807354922057604), REAL_CONST(4.857980995127572), REAL_CONST(4.906890595608519), REAL_CONST(4.954196310386875),
00268     REAL_CONST(5.000000000000000), REAL_CONST(5.044394119358453), REAL_CONST(5.087462841250340), REAL_CONST(5.129283016944966),
00269     REAL_CONST(5.169925001442312), REAL_CONST(5.209453365628949), REAL_CONST(5.247927513443585), REAL_CONST(5.285402218862248),
00270     REAL_CONST(5.321928094887363), REAL_CONST(5.357552004618084), REAL_CONST(5.392317422778761), REAL_CONST(5.426264754702098),
00271     REAL_CONST(5.459431618637297), REAL_CONST(5.491853096329675), REAL_CONST(5.523561956057013), REAL_CONST(5.554588851677637),
00272     REAL_CONST(5.584962500721156), REAL_CONST(5.614709844115208), REAL_CONST(5.643856189774724), REAL_CONST(5.672425341971495),
00273     REAL_CONST(5.700439718141093), REAL_CONST(5.727920454563200), REAL_CONST(5.754887502163469), REAL_CONST(5.781359713524660),
00274     REAL_CONST(5.807354922057605), REAL_CONST(5.832890014164742), REAL_CONST(5.857980995127572), REAL_CONST(5.882643049361842),
00275     REAL_CONST(5.906890595608518), REAL_CONST(5.930737337562887), REAL_CONST(5.954196310386876), REAL_CONST(5.977279923499916)
00276 };
00277 
00278 static const real_t pan_log2_tab[] = {
00279     REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362), REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339),
00280     REAL_CONST(0.044394119358453), REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878), REAL_CONST(0.002815015607054),
00281     REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247), REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122),
00282     REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667)
00283 };
00284 
00285 static real_t find_log2_E(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
00286 {
00287     /* check for coupled energy/noise data */
00288     if (sbr->bs_coupling == 1)
00289     {
00290         uint8_t amp0 = (sbr->amp_res[0]) ? 0 : 1;
00291         uint8_t amp1 = (sbr->amp_res[1]) ? 0 : 1;
00292         real_t tmp = (7 << REAL_BITS) + (sbr->E[0][k][l] << (REAL_BITS-amp0));
00293         real_t pan;
00294 
00295         /* E[1] should always be even so shifting is OK */
00296         uint8_t E = sbr->E[1][k][l] >> amp1;
00297 
00298         if (ch == 0)
00299         {
00300             if (E > 12)
00301             {
00302                 /* negative */
00303                 pan = pan_log2_tab[-12 + E];
00304             } else {
00305                 /* positive */
00306                 pan = pan_log2_tab[12 - E] + ((12 - E)<<REAL_BITS);
00307             }
00308         } else {
00309             if (E < 12)
00310             {
00311                 /* negative */
00312                 pan = pan_log2_tab[-E + 12];
00313             } else {
00314                 /* positive */
00315                 pan = pan_log2_tab[E - 12] + ((E - 12)<<REAL_BITS);
00316             }
00317         }
00318 
00319         /* tmp / pan in log2 */
00320         return tmp - pan;
00321     } else {
00322         uint8_t amp = (sbr->amp_res[ch]) ? 0 : 1;
00323 
00324         return (6 << REAL_BITS) + (sbr->E[ch][k][l] << (REAL_BITS-amp));
00325     }
00326 }
00327 
00328 static real_t find_log2_Q(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
00329 {
00330     /* check for coupled energy/noise data */
00331     if (sbr->bs_coupling == 1)
00332     {
00333         real_t tmp = (7 << REAL_BITS) - (sbr->Q[0][k][l] << REAL_BITS);
00334         real_t pan;
00335 
00336         uint8_t Q = sbr->Q[1][k][l];
00337 
00338         if (ch == 0)
00339         {
00340             if (Q > 12)
00341             {
00342                 /* negative */
00343                 pan = pan_log2_tab[-12 + Q];
00344             } else {
00345                 /* positive */
00346                 pan = pan_log2_tab[12 - Q] + ((12 - Q)<<REAL_BITS);
00347             }
00348         } else {
00349             if (Q < 12)
00350             {
00351                 /* negative */
00352                 pan = pan_log2_tab[-Q + 12];
00353             } else {
00354                 /* positive */
00355                 pan = pan_log2_tab[Q - 12] + ((Q - 12)<<REAL_BITS);
00356             }
00357         }
00358 
00359         /* tmp / pan in log2 */
00360         return tmp - pan;
00361     } else {
00362         return (6 << REAL_BITS) - (sbr->Q[ch][k][l] << REAL_BITS);
00363     }
00364 }
00365 
00366 static const real_t log_Qplus1_pan[31][13] = {
00367     { REAL_CONST(0.044383447617292), REAL_CONST(0.169768601655960), REAL_CONST(0.583090126514435), REAL_CONST(1.570089221000671), REAL_CONST(3.092446088790894), REAL_CONST(4.733354568481445), REAL_CONST(6.022367954254150), REAL_CONST(6.692092418670654), REAL_CONST(6.924463272094727), REAL_CONST(6.989034175872803), REAL_CONST(7.005646705627441), REAL_CONST(7.009829998016357), REAL_CONST(7.010877609252930) },
00368     { REAL_CONST(0.022362394258380), REAL_CONST(0.087379962205887), REAL_CONST(0.320804953575134), REAL_CONST(0.988859415054321), REAL_CONST(2.252387046813965), REAL_CONST(3.786596298217773), REAL_CONST(5.044394016265869), REAL_CONST(5.705977916717529), REAL_CONST(5.936291694641113), REAL_CONST(6.000346660614014), REAL_CONST(6.016829967498779), REAL_CONST(6.020981311798096), REAL_CONST(6.022020816802979) },
00369     { REAL_CONST(0.011224525049329), REAL_CONST(0.044351425021887), REAL_CONST(0.169301137328148), REAL_CONST(0.577544987201691), REAL_CONST(1.527246952056885), REAL_CONST(2.887525320053101), REAL_CONST(4.087462902069092), REAL_CONST(4.733354568481445), REAL_CONST(4.959661006927490), REAL_CONST(5.022709369659424), REAL_CONST(5.038940429687500), REAL_CONST(5.043028831481934), REAL_CONST(5.044052600860596) },
00370     { REAL_CONST(0.005623178556561), REAL_CONST(0.022346137091517), REAL_CONST(0.087132595479488), REAL_CONST(0.317482173442841), REAL_CONST(0.956931233406067), REAL_CONST(2.070389270782471), REAL_CONST(3.169924974441528), REAL_CONST(3.786596298217773), REAL_CONST(4.005294322967529), REAL_CONST(4.066420555114746), REAL_CONST(4.082170009613037), REAL_CONST(4.086137294769287), REAL_CONST(4.087131500244141) },
00371     { REAL_CONST(0.002814328996465), REAL_CONST(0.011216334067285), REAL_CONST(0.044224001467228), REAL_CONST(0.167456731200218), REAL_CONST(0.556393325328827), REAL_CONST(1.378511548042297), REAL_CONST(2.321928024291992), REAL_CONST(2.887525320053101), REAL_CONST(3.092446088790894), REAL_CONST(3.150059700012207), REAL_CONST(3.164926528930664), REAL_CONST(3.168673276901245), REAL_CONST(3.169611930847168) },
00372     { REAL_CONST(0.001407850766554), REAL_CONST(0.005619067233056), REAL_CONST(0.022281449288130), REAL_CONST(0.086156636476517), REAL_CONST(0.304854571819305), REAL_CONST(0.847996890544891), REAL_CONST(1.584962487220764), REAL_CONST(2.070389270782471), REAL_CONST(2.252387046813965), REAL_CONST(2.304061651229858), REAL_CONST(2.317430257797241), REAL_CONST(2.320801734924316), REAL_CONST(2.321646213531494) },
00373     { REAL_CONST(0.000704097095877), REAL_CONST(0.002812269143760), REAL_CONST(0.011183738708496), REAL_CONST(0.043721374124289), REAL_CONST(0.160464659333229), REAL_CONST(0.485426813364029), REAL_CONST(1.000000000000000), REAL_CONST(1.378511548042297), REAL_CONST(1.527246952056885), REAL_CONST(1.570089221000671), REAL_CONST(1.581215262413025), REAL_CONST(1.584023833274841), REAL_CONST(1.584727644920349) },
00374     { REAL_CONST(0.000352177477907), REAL_CONST(0.001406819908880), REAL_CONST(0.005602621007711), REAL_CONST(0.022026389837265), REAL_CONST(0.082462236285210), REAL_CONST(0.263034462928772), REAL_CONST(0.584962487220764), REAL_CONST(0.847996890544891), REAL_CONST(0.956931233406067), REAL_CONST(0.988859415054321), REAL_CONST(0.997190535068512), REAL_CONST(0.999296069145203), REAL_CONST(0.999823868274689) },
00375     { REAL_CONST(0.000176099492819), REAL_CONST(0.000703581434209), REAL_CONST(0.002804030198604), REAL_CONST(0.011055230163038), REAL_CONST(0.041820213198662), REAL_CONST(0.137503549456596), REAL_CONST(0.321928083896637), REAL_CONST(0.485426813364029), REAL_CONST(0.556393325328827), REAL_CONST(0.577544987201691), REAL_CONST(0.583090126514435), REAL_CONST(0.584493279457092), REAL_CONST(0.584845066070557) },
00376     { REAL_CONST(0.000088052431238), REAL_CONST(0.000351833587047), REAL_CONST(0.001402696361765), REAL_CONST(0.005538204684854), REAL_CONST(0.021061634644866), REAL_CONST(0.070389263331890), REAL_CONST(0.169925004243851), REAL_CONST(0.263034462928772), REAL_CONST(0.304854571819305), REAL_CONST(0.317482173442841), REAL_CONST(0.320804953575134), REAL_CONST(0.321646571159363), REAL_CONST(0.321857661008835) },
00377     { REAL_CONST(0.000044026888645), REAL_CONST(0.000175927518285), REAL_CONST(0.000701518612914), REAL_CONST(0.002771759871393), REAL_CONST(0.010569252073765), REAL_CONST(0.035623874515295), REAL_CONST(0.087462842464447), REAL_CONST(0.137503549456596), REAL_CONST(0.160464659333229), REAL_CONST(0.167456731200218), REAL_CONST(0.169301137328148), REAL_CONST(0.169768601655960), REAL_CONST(0.169885858893394) },
00378     { REAL_CONST(0.000022013611670), REAL_CONST(0.000088052431238), REAL_CONST(0.000350801943569), REAL_CONST(0.001386545598507), REAL_CONST(0.005294219125062), REAL_CONST(0.017921976745129), REAL_CONST(0.044394120573997), REAL_CONST(0.070389263331890), REAL_CONST(0.082462236285210), REAL_CONST(0.086156636476517), REAL_CONST(0.087132595479488), REAL_CONST(0.087379962205887), REAL_CONST(0.087442122399807) },
00379     { REAL_CONST(0.000011006847672), REAL_CONST(0.000044026888645), REAL_CONST(0.000175411638338), REAL_CONST(0.000693439331371), REAL_CONST(0.002649537986144), REAL_CONST(0.008988817222416), REAL_CONST(0.022367812693119), REAL_CONST(0.035623874515295), REAL_CONST(0.041820213198662), REAL_CONST(0.043721374124289), REAL_CONST(0.044224001467228), REAL_CONST(0.044351425021887), REAL_CONST(0.044383447617292) },
00380     { REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000087708482170), REAL_CONST(0.000346675369656), REAL_CONST(0.001325377263129), REAL_CONST(0.004501323681325), REAL_CONST(0.011227255687118), REAL_CONST(0.017921976745129), REAL_CONST(0.021061634644866), REAL_CONST(0.022026389837265), REAL_CONST(0.022281449288130), REAL_CONST(0.022346137091517), REAL_CONST(0.022362394258380) },
00381     { REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043854910473), REAL_CONST(0.000173348103999), REAL_CONST(0.000662840844598), REAL_CONST(0.002252417383716), REAL_CONST(0.005624548997730), REAL_CONST(0.008988817222416), REAL_CONST(0.010569252073765), REAL_CONST(0.011055230163038), REAL_CONST(0.011183738708496), REAL_CONST(0.011216334067285), REAL_CONST(0.011224525049329) },
00382     { REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000086676649516), REAL_CONST(0.000331544462824), REAL_CONST(0.001126734190620), REAL_CONST(0.002815015614033), REAL_CONST(0.004501323681325), REAL_CONST(0.005294219125062), REAL_CONST(0.005538204684854), REAL_CONST(0.005602621007711), REAL_CONST(0.005619067233056), REAL_CONST(0.005623178556561) },
00383     { REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043338975956), REAL_CONST(0.000165781748365), REAL_CONST(0.000563477107789), REAL_CONST(0.001408194424585), REAL_CONST(0.002252417383716), REAL_CONST(0.002649537986144), REAL_CONST(0.002771759871393), REAL_CONST(0.002804030198604), REAL_CONST(0.002812269143760), REAL_CONST(0.002814328996465) },
00384     { REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000021669651687), REAL_CONST(0.000082893253420), REAL_CONST(0.000281680084299), REAL_CONST(0.000704268983100), REAL_CONST(0.001126734190620), REAL_CONST(0.001325377263129), REAL_CONST(0.001386545598507), REAL_CONST(0.001402696361765), REAL_CONST(0.001406819908880), REAL_CONST(0.001407850766554) },
00385     { REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010834866771), REAL_CONST(0.000041447223339), REAL_CONST(0.000140846910654), REAL_CONST(0.000352177477907), REAL_CONST(0.000563477107789), REAL_CONST(0.000662840844598), REAL_CONST(0.000693439331371), REAL_CONST(0.000701518612914), REAL_CONST(0.000703581434209), REAL_CONST(0.000704097095877) },
00386     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000020637769921), REAL_CONST(0.000070511166996), REAL_CONST(0.000176099492819), REAL_CONST(0.000281680084299), REAL_CONST(0.000331544462824), REAL_CONST(0.000346675369656), REAL_CONST(0.000350801943569), REAL_CONST(0.000351833587047), REAL_CONST(0.000352177477907) },
00387     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010318922250), REAL_CONST(0.000035256012779), REAL_CONST(0.000088052431238), REAL_CONST(0.000140846910654), REAL_CONST(0.000165781748365), REAL_CONST(0.000173348103999), REAL_CONST(0.000175411638338), REAL_CONST(0.000175927518285), REAL_CONST(0.000176099492819) },
00388     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005159470220), REAL_CONST(0.000017542124624), REAL_CONST(0.000044026888645), REAL_CONST(0.000070511166996), REAL_CONST(0.000082893253420), REAL_CONST(0.000086676649516), REAL_CONST(0.000087708482170), REAL_CONST(0.000088052431238), REAL_CONST(0.000088052431238) },
00389     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002579737384), REAL_CONST(0.000008771088687), REAL_CONST(0.000022013611670), REAL_CONST(0.000035256012779), REAL_CONST(0.000041447223339), REAL_CONST(0.000043338975956), REAL_CONST(0.000043854910473), REAL_CONST(0.000044026888645), REAL_CONST(0.000044026888645) },
00390     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000004471542070), REAL_CONST(0.000011006847672), REAL_CONST(0.000017542124624), REAL_CONST(0.000020637769921), REAL_CONST(0.000021669651687), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670) },
00391     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002235772627), REAL_CONST(0.000005503434295), REAL_CONST(0.000008771088687), REAL_CONST(0.000010318922250), REAL_CONST(0.000010834866771), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672) },
00392     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001031895522), REAL_CONST(0.000002751719876), REAL_CONST(0.000004471542070), REAL_CONST(0.000005159470220), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295) },
00393     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000515947875), REAL_CONST(0.000001375860506), REAL_CONST(0.000002235772627), REAL_CONST(0.000002579737384), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876) },
00394     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000000687930424), REAL_CONST(0.000001031895522), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506) },
00395     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000515947875), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424) },
00396     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269) },
00397     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634) }
00398 };
00399 
00400 static const real_t log_Qplus1[31] = {
00401     REAL_CONST(6.022367813028454), REAL_CONST(5.044394119358453), REAL_CONST(4.087462841250339), 
00402     REAL_CONST(3.169925001442313), REAL_CONST(2.321928094887362), REAL_CONST(1.584962500721156), 
00403     REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362), 
00404     REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339), REAL_CONST(0.044394119358453), 
00405     REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878), 
00406     REAL_CONST(0.002815015607054), REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247), 
00407     REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122), 
00408     REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667), 
00409     REAL_CONST(0.000005503434331), REAL_CONST(0.000002751719790), REAL_CONST(0.000001375860551), 
00410     REAL_CONST(0.000000687930439), REAL_CONST(0.000000343965261), REAL_CONST(0.000000171982641), 
00411     REAL_CONST(0.000000000000000)
00412 };
00413 
00414 static real_t find_log2_Qplus1(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
00415 {
00416     /* check for coupled energy/noise data */
00417     if (sbr->bs_coupling == 1)
00418     {
00419         if ((sbr->Q[0][k][l] >= 0) && (sbr->Q[0][k][l] <= 30) &&
00420             (sbr->Q[1][k][l] >= 0) && (sbr->Q[1][k][l] <= 24))
00421         {
00422             if (ch == 0)
00423             {
00424                 return log_Qplus1_pan[sbr->Q[0][k][l]][sbr->Q[1][k][l] >> 1];
00425             } else {
00426                 return log_Qplus1_pan[sbr->Q[0][k][l]][12 - (sbr->Q[1][k][l] >> 1)];
00427             }
00428         } else {
00429             return 0;
00430         }
00431     } else {
00432         if (sbr->Q[ch][k][l] >= 0 && sbr->Q[ch][k][l] <= 30)
00433         {
00434             return log_Qplus1[sbr->Q[ch][k][l]];
00435         } else {
00436             return 0;
00437         }
00438     }
00439 }
00440 
00441 static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
00442 {
00443     /* log2 values of limiter gains */
00444     static real_t limGain[] = {
00445         REAL_CONST(-1.0), REAL_CONST(0.0), REAL_CONST(1.0), REAL_CONST(33.219)
00446     };
00447     uint8_t m, l, k;
00448 
00449     uint8_t current_t_noise_band = 0;
00450     uint8_t S_mapped;
00451 
00452     ALIGN real_t Q_M_lim[MAX_M];
00453     ALIGN real_t G_lim[MAX_M];
00454     ALIGN real_t G_boost;
00455     ALIGN real_t S_M[MAX_M];
00456 
00457 
00458     for (l = 0; l < sbr->L_E[ch]; l++)
00459     {
00460         uint8_t current_f_noise_band = 0;
00461         uint8_t current_res_band = 0;
00462         uint8_t current_res_band2 = 0;
00463         uint8_t current_hi_res_band = 0;
00464 
00465         real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
00466 
00467         S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
00468 
00469         if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
00470         {
00471             current_t_noise_band++;
00472         }
00473 
00474         for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
00475         {
00476             real_t Q_M = 0;
00477             real_t G_max;
00478             real_t den = 0;
00479             real_t acc1 = 0;
00480             real_t acc2 = 0;
00481             uint8_t current_res_band_size = 0;
00482             uint8_t Q_M_size = 0;
00483 
00484             uint8_t ml1, ml2;
00485 
00486             /* bounds of current limiter bands */
00487             ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
00488             ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
00489 
00490 
00491             /* calculate the accumulated E_orig and E_curr over the limiter band */
00492             for (m = ml1; m < ml2; m++)
00493             {
00494                 if ((m + sbr->kx) < sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
00495                 {
00496                     current_res_band_size++;
00497                 } else {
00498                     acc1 += pow2_int(-REAL_CONST(10) + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch));
00499 
00500                     current_res_band++;
00501                     current_res_band_size = 1;
00502                 }
00503 
00504                 acc2 += sbr->E_curr[ch][m][l];
00505             }
00506             acc1 += pow2_int(-REAL_CONST(10) + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch));
00507 
00508 
00509             if (acc1 == 0)
00510                 acc1 = LOG2_MIN_INF;
00511             else
00512                 acc1 = log2_int(acc1);
00513 
00514 
00515             /* calculate the maximum gain */
00516             /* ratio of the energy of the original signal and the energy
00517              * of the HF generated signal
00518              */
00519             G_max = acc1 - log2_int(acc2) + limGain[sbr->bs_limiter_gains];
00520             G_max = min(G_max, limGain[3]);
00521 
00522 
00523             for (m = ml1; m < ml2; m++)
00524             {
00525                 real_t G;
00526                 real_t E_curr, E_orig;
00527                 real_t Q_orig, Q_orig_plus1;
00528                 uint8_t S_index_mapped;
00529 
00530 
00531                 /* check if m is on a noise band border */
00532                 if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
00533                 {
00534                     /* step to next noise band */
00535                     current_f_noise_band++;
00536                 }
00537 
00538 
00539                 /* check if m is on a resolution band border */
00540                 if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1])
00541                 {
00542                     /* accumulate a whole range of equal Q_Ms */
00543                     if (Q_M_size > 0)
00544                         den += pow2_int(log2_int_tab[Q_M_size] + Q_M);
00545                     Q_M_size = 0;
00546 
00547                     /* step to next resolution band */
00548                     current_res_band2++;
00549 
00550                     /* if we move to a new resolution band, we should check if we are
00551                      * going to add a sinusoid in this band
00552                      */
00553                     S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
00554                 }
00555 
00556 
00557                 /* check if m is on a HI_RES band border */
00558                 if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1])
00559                 {
00560                     /* step to next HI_RES band */
00561                     current_hi_res_band++;
00562                 }
00563 
00564 
00565                 /* find S_index_mapped
00566                  * S_index_mapped can only be 1 for the m in the middle of the
00567                  * current HI_RES band
00568                  */
00569                 S_index_mapped = 0;
00570                 if ((l >= sbr->l_A[ch]) ||
00571                     (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch]))
00572                 {
00573                     /* find the middle subband of the HI_RES frequency band */
00574                     if ((m + sbr->kx) == (sbr->f_table_res[HI_RES][current_hi_res_band+1] + sbr->f_table_res[HI_RES][current_hi_res_band]) >> 1)
00575                         S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band];
00576                 }
00577 
00578 
00579                 /* find bitstream parameters */
00580                 if (sbr->E_curr[ch][m][l] == 0)
00581                     E_curr = LOG2_MIN_INF;
00582                 else
00583                     E_curr = log2_int(sbr->E_curr[ch][m][l]);
00584                 E_orig = -REAL_CONST(10) + find_log2_E(sbr, current_res_band2, l, ch);
00585 
00586 
00587                 Q_orig = find_log2_Q(sbr, current_f_noise_band, current_t_noise_band, ch);
00588                 Q_orig_plus1 = find_log2_Qplus1(sbr, current_f_noise_band, current_t_noise_band, ch);
00589 
00590 
00591                 /* Q_M only depends on E_orig and Q_div2:
00592                  * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
00593                  * a change of current res band (HI or LO)
00594                  */
00595                 Q_M = E_orig + Q_orig - Q_orig_plus1;
00596 
00597 
00598                 /* S_M only depends on E_orig, Q_div and S_index_mapped:
00599                  * S_index_mapped can only be non-zero once per HI_RES band
00600                  */
00601                 if (S_index_mapped == 0)
00602                 {
00603                     S_M[m] = LOG2_MIN_INF; /* -inf */
00604                 } else {
00605                     S_M[m] = E_orig - Q_orig_plus1;
00606 
00607                     /* accumulate sinusoid part of the total energy */
00608                     den += pow2_int(S_M[m]);
00609                 }
00610 
00611 
00612                 /* calculate gain */
00613                 /* ratio of the energy of the original signal and the energy
00614                  * of the HF generated signal
00615                  */
00616                 /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */
00617                 /* scaled by -10 */
00618                 G = E_orig - max(-REAL_CONST(10), E_curr);
00619                 if ((S_mapped == 0) && (delta == 1))
00620                 {
00621                     /* G = G * 1/(1+Q) */
00622                     G -= Q_orig_plus1;
00623                 } else if (S_mapped == 1) {
00624                     /* G = G * Q/(1+Q) */
00625                     G += Q_orig - Q_orig_plus1;
00626                 }
00627 
00628 
00629                 /* limit the additional noise energy level */
00630                 /* and apply the limiter */
00631                 if (G_max > G)
00632                 {
00633                     Q_M_lim[m] = Q_M;
00634                     G_lim[m] = G;
00635 
00636                     if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
00637                     {
00638                         Q_M_size++;
00639                     }
00640                 } else {
00641                     /* G > G_max */
00642                     Q_M_lim[m] = Q_M + G_max - G;
00643                     G_lim[m] = G_max;
00644 
00645                     /* accumulate limited Q_M */
00646                     if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
00647                     {
00648                         den += pow2_int(Q_M_lim[m]);
00649                     }
00650                 }
00651 
00652 
00653                 /* accumulate the total energy */
00654                 /* E_curr changes for every m so we do need to accumulate every m */
00655                 den += pow2_int(E_curr + G_lim[m]);
00656             }
00657 
00658             /* accumulate last range of equal Q_Ms */
00659             if (Q_M_size > 0)
00660             {
00661                 den += pow2_int(log2_int_tab[Q_M_size] + Q_M);
00662             }
00663 
00664 
00665             /* calculate the final gain */
00666             /* G_boost: [0..2.51188643] */
00667             G_boost = acc1 - log2_int(den /*+ EPS*/);
00668             G_boost = min(G_boost, REAL_CONST(1.328771237) /* log2(1.584893192 ^ 2) */);
00669 
00670 
00671             for (m = ml1; m < ml2; m++)
00672             {
00673                 /* apply compensation to gain, noise floor sf's and sinusoid levels */
00674 #ifndef SBR_LOW_POWER
00675                 adj->G_lim_boost[l][m] = pow2_fix((G_lim[m] + G_boost) >> 1);
00676 #else
00677                 /* sqrt() will be done after the aliasing reduction to save a
00678                  * few multiplies
00679                  */
00680                 adj->G_lim_boost[l][m] = pow2_fix(G_lim[m] + G_boost);
00681 #endif
00682                 adj->Q_M_lim_boost[l][m] = pow2_fix((Q_M_lim[m] + G_boost) >> 1);
00683 
00684                 if (S_M[m] != LOG2_MIN_INF)
00685                 {
00686                     adj->S_M_boost[l][m] = pow2_int((S_M[m] + G_boost) >> 1);
00687                 } else {
00688                     adj->S_M_boost[l][m] = 0;
00689                 }
00690             }
00691         }
00692     }
00693 }
00694 
00695 #else
00696 
00697 //#define LOG2_TEST
00698 
00699 #ifdef LOG2_TEST
00700 
00701 #define LOG2_MIN_INF -100000
00702 
00703 __inline float pow2(float val)
00704 {
00705     return pow(2.0, val);
00706 }
00707 __inline float log2(float val)
00708 {
00709     return log(val)/log(2.0);
00710 }
00711 
00712 #define RB 14
00713 
00714 float QUANTISE2REAL(float val)
00715 {
00716     __int32 ival = (__int32)(val * (1<<RB));
00717     return (float)ival / (float)((1<<RB));
00718 }
00719 
00720 float QUANTISE2INT(float val)
00721 {
00722     return floor(val);
00723 }
00724 
00725 /* log2 values of [0..63] */
00726 static const real_t log2_int_tab[] = {
00727     LOG2_MIN_INF,      0.000000000000000, 1.000000000000000, 1.584962500721156,
00728     2.000000000000000, 2.321928094887362, 2.584962500721156, 2.807354922057604,
00729     3.000000000000000, 3.169925001442313, 3.321928094887363, 3.459431618637297,
00730     3.584962500721156, 3.700439718141092, 3.807354922057604, 3.906890595608519,
00731     4.000000000000000, 4.087462841250339, 4.169925001442312, 4.247927513443585,
00732     4.321928094887362, 4.392317422778761, 4.459431618637297, 4.523561956057013,
00733     4.584962500721156, 4.643856189774724, 4.700439718141093, 4.754887502163468,
00734     4.807354922057604, 4.857980995127572, 4.906890595608519, 4.954196310386875,
00735     5.000000000000000, 5.044394119358453, 5.087462841250340, 5.129283016944966,
00736     5.169925001442312, 5.209453365628949, 5.247927513443585, 5.285402218862248,
00737     5.321928094887363, 5.357552004618084, 5.392317422778761, 5.426264754702098,
00738     5.459431618637297, 5.491853096329675, 5.523561956057013, 5.554588851677637,
00739     5.584962500721156, 5.614709844115208, 5.643856189774724, 5.672425341971495,
00740     5.700439718141093, 5.727920454563200, 5.754887502163469, 5.781359713524660,
00741     5.807354922057605, 5.832890014164742, 5.857980995127572, 5.882643049361842,
00742     5.906890595608518, 5.930737337562887, 5.954196310386876, 5.977279923499916
00743 };
00744 
00745 static const real_t pan_log2_tab[] = {
00746     1.000000000000000, 0.584962500721156, 0.321928094887362, 0.169925001442312, 0.087462841250339,
00747     0.044394119358453, 0.022367813028455, 0.011227255423254, 0.005624549193878, 0.002815015607054,
00748     0.001408194392808, 0.000704269011247, 0.000352177480301, 0.000176099486443, 0.000088052430122,
00749     0.000044026886827, 0.000022013611360, 0.000011006847667
00750 };
00751 
00752 static real_t find_log2_E(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
00753 {
00754     /* check for coupled energy/noise data */
00755     if (sbr->bs_coupling == 1)
00756     {
00757         real_t amp0 = (sbr->amp_res[0]) ? 1.0 : 0.5;
00758         real_t amp1 = (sbr->amp_res[1]) ? 1.0 : 0.5;
00759         float tmp = QUANTISE2REAL(7.0 + (real_t)sbr->E[0][k][l] * amp0);
00760         float pan;
00761 
00762         int E = (int)(sbr->E[1][k][l] * amp1);
00763 
00764         if (ch == 0)
00765         {
00766             if (E > 12)
00767             {
00768                 /* negative */
00769                 pan = QUANTISE2REAL(pan_log2_tab[-12 + E]);
00770             } else {
00771                 /* positive */
00772                 pan = QUANTISE2REAL(pan_log2_tab[12 - E] + (12 - E));
00773             }
00774         } else {
00775             if (E < 12)
00776             {
00777                 /* negative */
00778                 pan = QUANTISE2REAL(pan_log2_tab[-E + 12]);
00779             } else {
00780                 /* positive */
00781                 pan = QUANTISE2REAL(pan_log2_tab[E - 12] + (E - 12));
00782             }
00783         }
00784 
00785         /* tmp / pan in log2 */
00786         return QUANTISE2REAL(tmp - pan);
00787     } else {
00788         real_t amp = (sbr->amp_res[ch]) ? 1.0 : 0.5;
00789 
00790         return QUANTISE2REAL(6.0 + (real_t)sbr->E[ch][k][l] * amp);
00791     }
00792 }
00793 
00794 static real_t find_log2_Q(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
00795 {
00796     /* check for coupled energy/noise data */
00797     if (sbr->bs_coupling == 1)
00798     {
00799         float tmp = QUANTISE2REAL(7.0 - (real_t)sbr->Q[0][k][l]);
00800         float pan;
00801 
00802         int Q = (int)(sbr->Q[1][k][l]);
00803 
00804         if (ch == 0)
00805         {
00806             if (Q > 12)
00807             {
00808                 /* negative */
00809                 pan = QUANTISE2REAL(pan_log2_tab[-12 + Q]);
00810             } else {
00811                 /* positive */
00812                 pan = QUANTISE2REAL(pan_log2_tab[12 - Q] + (12 - Q));
00813             }
00814         } else {
00815             if (Q < 12)
00816             {
00817                 /* negative */
00818                 pan = QUANTISE2REAL(pan_log2_tab[-Q + 12]);
00819             } else {
00820                 /* positive */
00821                 pan = QUANTISE2REAL(pan_log2_tab[Q - 12] + (Q - 12));
00822             }
00823         }
00824 
00825         /* tmp / pan in log2 */
00826         return QUANTISE2REAL(tmp - pan);
00827     } else {
00828         return QUANTISE2REAL(6.0 - (real_t)sbr->Q[ch][k][l]);
00829     }
00830 }
00831 
00832 static const real_t log_Qplus1_pan[31][13] = {
00833     { REAL_CONST(0.044383447617292), REAL_CONST(0.169768601655960), REAL_CONST(0.583090126514435), REAL_CONST(1.570089221000671), REAL_CONST(3.092446088790894), REAL_CONST(4.733354568481445), REAL_CONST(6.022367954254150), REAL_CONST(6.692092418670654), REAL_CONST(6.924463272094727), REAL_CONST(6.989034175872803), REAL_CONST(7.005646705627441), REAL_CONST(7.009829998016357), REAL_CONST(7.010877609252930) },
00834     { REAL_CONST(0.022362394258380), REAL_CONST(0.087379962205887), REAL_CONST(0.320804953575134), REAL_CONST(0.988859415054321), REAL_CONST(2.252387046813965), REAL_CONST(3.786596298217773), REAL_CONST(5.044394016265869), REAL_CONST(5.705977916717529), REAL_CONST(5.936291694641113), REAL_CONST(6.000346660614014), REAL_CONST(6.016829967498779), REAL_CONST(6.020981311798096), REAL_CONST(6.022020816802979) },
00835     { REAL_CONST(0.011224525049329), REAL_CONST(0.044351425021887), REAL_CONST(0.169301137328148), REAL_CONST(0.577544987201691), REAL_CONST(1.527246952056885), REAL_CONST(2.887525320053101), REAL_CONST(4.087462902069092), REAL_CONST(4.733354568481445), REAL_CONST(4.959661006927490), REAL_CONST(5.022709369659424), REAL_CONST(5.038940429687500), REAL_CONST(5.043028831481934), REAL_CONST(5.044052600860596) },
00836     { REAL_CONST(0.005623178556561), REAL_CONST(0.022346137091517), REAL_CONST(0.087132595479488), REAL_CONST(0.317482173442841), REAL_CONST(0.956931233406067), REAL_CONST(2.070389270782471), REAL_CONST(3.169924974441528), REAL_CONST(3.786596298217773), REAL_CONST(4.005294322967529), REAL_CONST(4.066420555114746), REAL_CONST(4.082170009613037), REAL_CONST(4.086137294769287), REAL_CONST(4.087131500244141) },
00837     { REAL_CONST(0.002814328996465), REAL_CONST(0.011216334067285), REAL_CONST(0.044224001467228), REAL_CONST(0.167456731200218), REAL_CONST(0.556393325328827), REAL_CONST(1.378511548042297), REAL_CONST(2.321928024291992), REAL_CONST(2.887525320053101), REAL_CONST(3.092446088790894), REAL_CONST(3.150059700012207), REAL_CONST(3.164926528930664), REAL_CONST(3.168673276901245), REAL_CONST(3.169611930847168) },
00838     { REAL_CONST(0.001407850766554), REAL_CONST(0.005619067233056), REAL_CONST(0.022281449288130), REAL_CONST(0.086156636476517), REAL_CONST(0.304854571819305), REAL_CONST(0.847996890544891), REAL_CONST(1.584962487220764), REAL_CONST(2.070389270782471), REAL_CONST(2.252387046813965), REAL_CONST(2.304061651229858), REAL_CONST(2.317430257797241), REAL_CONST(2.320801734924316), REAL_CONST(2.321646213531494) },
00839     { REAL_CONST(0.000704097095877), REAL_CONST(0.002812269143760), REAL_CONST(0.011183738708496), REAL_CONST(0.043721374124289), REAL_CONST(0.160464659333229), REAL_CONST(0.485426813364029), REAL_CONST(1.000000000000000), REAL_CONST(1.378511548042297), REAL_CONST(1.527246952056885), REAL_CONST(1.570089221000671), REAL_CONST(1.581215262413025), REAL_CONST(1.584023833274841), REAL_CONST(1.584727644920349) },
00840     { REAL_CONST(0.000352177477907), REAL_CONST(0.001406819908880), REAL_CONST(0.005602621007711), REAL_CONST(0.022026389837265), REAL_CONST(0.082462236285210), REAL_CONST(0.263034462928772), REAL_CONST(0.584962487220764), REAL_CONST(0.847996890544891), REAL_CONST(0.956931233406067), REAL_CONST(0.988859415054321), REAL_CONST(0.997190535068512), REAL_CONST(0.999296069145203), REAL_CONST(0.999823868274689) },
00841     { REAL_CONST(0.000176099492819), REAL_CONST(0.000703581434209), REAL_CONST(0.002804030198604), REAL_CONST(0.011055230163038), REAL_CONST(0.041820213198662), REAL_CONST(0.137503549456596), REAL_CONST(0.321928083896637), REAL_CONST(0.485426813364029), REAL_CONST(0.556393325328827), REAL_CONST(0.577544987201691), REAL_CONST(0.583090126514435), REAL_CONST(0.584493279457092), REAL_CONST(0.584845066070557) },
00842     { REAL_CONST(0.000088052431238), REAL_CONST(0.000351833587047), REAL_CONST(0.001402696361765), REAL_CONST(0.005538204684854), REAL_CONST(0.021061634644866), REAL_CONST(0.070389263331890), REAL_CONST(0.169925004243851), REAL_CONST(0.263034462928772), REAL_CONST(0.304854571819305), REAL_CONST(0.317482173442841), REAL_CONST(0.320804953575134), REAL_CONST(0.321646571159363), REAL_CONST(0.321857661008835) },
00843     { REAL_CONST(0.000044026888645), REAL_CONST(0.000175927518285), REAL_CONST(0.000701518612914), REAL_CONST(0.002771759871393), REAL_CONST(0.010569252073765), REAL_CONST(0.035623874515295), REAL_CONST(0.087462842464447), REAL_CONST(0.137503549456596), REAL_CONST(0.160464659333229), REAL_CONST(0.167456731200218), REAL_CONST(0.169301137328148), REAL_CONST(0.169768601655960), REAL_CONST(0.169885858893394) },
00844     { REAL_CONST(0.000022013611670), REAL_CONST(0.000088052431238), REAL_CONST(0.000350801943569), REAL_CONST(0.001386545598507), REAL_CONST(0.005294219125062), REAL_CONST(0.017921976745129), REAL_CONST(0.044394120573997), REAL_CONST(0.070389263331890), REAL_CONST(0.082462236285210), REAL_CONST(0.086156636476517), REAL_CONST(0.087132595479488), REAL_CONST(0.087379962205887), REAL_CONST(0.087442122399807) },
00845     { REAL_CONST(0.000011006847672), REAL_CONST(0.000044026888645), REAL_CONST(0.000175411638338), REAL_CONST(0.000693439331371), REAL_CONST(0.002649537986144), REAL_CONST(0.008988817222416), REAL_CONST(0.022367812693119), REAL_CONST(0.035623874515295), REAL_CONST(0.041820213198662), REAL_CONST(0.043721374124289), REAL_CONST(0.044224001467228), REAL_CONST(0.044351425021887), REAL_CONST(0.044383447617292) },
00846     { REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000087708482170), REAL_CONST(0.000346675369656), REAL_CONST(0.001325377263129), REAL_CONST(0.004501323681325), REAL_CONST(0.011227255687118), REAL_CONST(0.017921976745129), REAL_CONST(0.021061634644866), REAL_CONST(0.022026389837265), REAL_CONST(0.022281449288130), REAL_CONST(0.022346137091517), REAL_CONST(0.022362394258380) },
00847     { REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043854910473), REAL_CONST(0.000173348103999), REAL_CONST(0.000662840844598), REAL_CONST(0.002252417383716), REAL_CONST(0.005624548997730), REAL_CONST(0.008988817222416), REAL_CONST(0.010569252073765), REAL_CONST(0.011055230163038), REAL_CONST(0.011183738708496), REAL_CONST(0.011216334067285), REAL_CONST(0.011224525049329) },
00848     { REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000086676649516), REAL_CONST(0.000331544462824), REAL_CONST(0.001126734190620), REAL_CONST(0.002815015614033), REAL_CONST(0.004501323681325), REAL_CONST(0.005294219125062), REAL_CONST(0.005538204684854), REAL_CONST(0.005602621007711), REAL_CONST(0.005619067233056), REAL_CONST(0.005623178556561) },
00849     { REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043338975956), REAL_CONST(0.000165781748365), REAL_CONST(0.000563477107789), REAL_CONST(0.001408194424585), REAL_CONST(0.002252417383716), REAL_CONST(0.002649537986144), REAL_CONST(0.002771759871393), REAL_CONST(0.002804030198604), REAL_CONST(0.002812269143760), REAL_CONST(0.002814328996465) },
00850     { REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000021669651687), REAL_CONST(0.000082893253420), REAL_CONST(0.000281680084299), REAL_CONST(0.000704268983100), REAL_CONST(0.001126734190620), REAL_CONST(0.001325377263129), REAL_CONST(0.001386545598507), REAL_CONST(0.001402696361765), REAL_CONST(0.001406819908880), REAL_CONST(0.001407850766554) },
00851     { REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010834866771), REAL_CONST(0.000041447223339), REAL_CONST(0.000140846910654), REAL_CONST(0.000352177477907), REAL_CONST(0.000563477107789), REAL_CONST(0.000662840844598), REAL_CONST(0.000693439331371), REAL_CONST(0.000701518612914), REAL_CONST(0.000703581434209), REAL_CONST(0.000704097095877) },
00852     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000020637769921), REAL_CONST(0.000070511166996), REAL_CONST(0.000176099492819), REAL_CONST(0.000281680084299), REAL_CONST(0.000331544462824), REAL_CONST(0.000346675369656), REAL_CONST(0.000350801943569), REAL_CONST(0.000351833587047), REAL_CONST(0.000352177477907) },
00853     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010318922250), REAL_CONST(0.000035256012779), REAL_CONST(0.000088052431238), REAL_CONST(0.000140846910654), REAL_CONST(0.000165781748365), REAL_CONST(0.000173348103999), REAL_CONST(0.000175411638338), REAL_CONST(0.000175927518285), REAL_CONST(0.000176099492819) },
00854     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005159470220), REAL_CONST(0.000017542124624), REAL_CONST(0.000044026888645), REAL_CONST(0.000070511166996), REAL_CONST(0.000082893253420), REAL_CONST(0.000086676649516), REAL_CONST(0.000087708482170), REAL_CONST(0.000088052431238), REAL_CONST(0.000088052431238) },
00855     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002579737384), REAL_CONST(0.000008771088687), REAL_CONST(0.000022013611670), REAL_CONST(0.000035256012779), REAL_CONST(0.000041447223339), REAL_CONST(0.000043338975956), REAL_CONST(0.000043854910473), REAL_CONST(0.000044026888645), REAL_CONST(0.000044026888645) },
00856     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000004471542070), REAL_CONST(0.000011006847672), REAL_CONST(0.000017542124624), REAL_CONST(0.000020637769921), REAL_CONST(0.000021669651687), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670) },
00857     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002235772627), REAL_CONST(0.000005503434295), REAL_CONST(0.000008771088687), REAL_CONST(0.000010318922250), REAL_CONST(0.000010834866771), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672) },
00858     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001031895522), REAL_CONST(0.000002751719876), REAL_CONST(0.000004471542070), REAL_CONST(0.000005159470220), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295) },
00859     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000515947875), REAL_CONST(0.000001375860506), REAL_CONST(0.000002235772627), REAL_CONST(0.000002579737384), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876) },
00860     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000000687930424), REAL_CONST(0.000001031895522), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506) },
00861     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000515947875), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424) },
00862     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269) },
00863     { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634) }
00864 };
00865 
00866 static const real_t log_Qplus1[31] = {
00867     REAL_CONST(6.022367813028454), REAL_CONST(5.044394119358453), REAL_CONST(4.087462841250339), 
00868     REAL_CONST(3.169925001442313), REAL_CONST(2.321928094887362), REAL_CONST(1.584962500721156), 
00869     REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362), 
00870     REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339), REAL_CONST(0.044394119358453), 
00871     REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878), 
00872     REAL_CONST(0.002815015607054), REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247), 
00873     REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122), 
00874     REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667), 
00875     REAL_CONST(0.000005503434331), REAL_CONST(0.000002751719790), REAL_CONST(0.000001375860551), 
00876     REAL_CONST(0.000000687930439), REAL_CONST(0.000000343965261), REAL_CONST(0.000000171982641), 
00877     REAL_CONST(0.000000000000000)
00878 };
00879 
00880 static real_t find_log2_Qplus1(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch)
00881 {
00882     /* check for coupled energy/noise data */
00883     if (sbr->bs_coupling == 1)
00884     {
00885         if ((sbr->Q[0][k][l] >= 0) && (sbr->Q[0][k][l] <= 30) &&
00886             (sbr->Q[1][k][l] >= 0) && (sbr->Q[1][k][l] <= 24))
00887         {
00888             if (ch == 0)
00889             {
00890                 return QUANTISE2REAL(log_Qplus1_pan[sbr->Q[0][k][l]][sbr->Q[1][k][l] >> 1]);
00891             } else {
00892                 return QUANTISE2REAL(log_Qplus1_pan[sbr->Q[0][k][l]][12 - (sbr->Q[1][k][l] >> 1)]);
00893             }
00894         } else {
00895             return 0;
00896         }
00897     } else {
00898         if (sbr->Q[ch][k][l] >= 0 && sbr->Q[ch][k][l] <= 30)
00899         {
00900             return QUANTISE2REAL(log_Qplus1[sbr->Q[ch][k][l]]);
00901         } else {
00902             return 0;
00903         }
00904     }
00905 }
00906 
00907 static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
00908 {
00909     /* log2 values of limiter gains */
00910     static real_t limGain[] = { -1.0, 0.0, 1.0, 33.219 };
00911     uint8_t m, l, k;
00912 
00913     uint8_t current_t_noise_band = 0;
00914     uint8_t S_mapped;
00915 
00916     ALIGN real_t Q_M_lim[MAX_M];
00917     ALIGN real_t G_lim[MAX_M];
00918     ALIGN real_t G_boost;
00919     ALIGN real_t S_M[MAX_M];
00920 
00921 
00922     for (l = 0; l < sbr->L_E[ch]; l++)
00923     {
00924         uint8_t current_f_noise_band = 0;
00925         uint8_t current_res_band = 0;
00926         uint8_t current_res_band2 = 0;
00927         uint8_t current_hi_res_band = 0;
00928 
00929         real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
00930 
00931         S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
00932 
00933         if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
00934         {
00935             current_t_noise_band++;
00936         }
00937 
00938         for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
00939         {
00940             real_t Q_M = 0;
00941             real_t G_max;
00942             real_t den = 0;
00943             real_t acc1 = 0;
00944             real_t acc2 = 0;
00945             uint8_t current_res_band_size = 0;
00946             uint8_t Q_M_size = 0;
00947 
00948             uint8_t ml1, ml2;
00949 
00950             /* bounds of current limiter bands */
00951             ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
00952             ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
00953 
00954 
00955             /* calculate the accumulated E_orig and E_curr over the limiter band */
00956             for (m = ml1; m < ml2; m++)
00957             {
00958                 if ((m + sbr->kx) < sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
00959                 {
00960                     current_res_band_size++;
00961                 } else {
00962                     acc1 += QUANTISE2INT(pow2(-10 + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch)));
00963 
00964                     current_res_band++;
00965                     current_res_band_size = 1;
00966                 }
00967 
00968                 acc2 += QUANTISE2INT(sbr->E_curr[ch][m][l]/1024.0);
00969             }
00970             acc1 += QUANTISE2INT(pow2(-10 + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch)));
00971 
00972             acc1 = QUANTISE2REAL( log2(EPS + acc1) );
00973 
00974 
00975             /* calculate the maximum gain */
00976             /* ratio of the energy of the original signal and the energy
00977              * of the HF generated signal
00978              */
00979             G_max = acc1 - QUANTISE2REAL(log2(EPS + acc2)) + QUANTISE2REAL(limGain[sbr->bs_limiter_gains]);
00980             G_max = min(G_max, QUANTISE2REAL(limGain[3]));
00981 
00982 
00983             for (m = ml1; m < ml2; m++)
00984             {
00985                 real_t G;
00986                 real_t E_curr, E_orig;
00987                 real_t Q_orig, Q_orig_plus1;
00988                 uint8_t S_index_mapped;
00989 
00990 
00991                 /* check if m is on a noise band border */
00992                 if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
00993                 {
00994                     /* step to next noise band */
00995                     current_f_noise_band++;
00996                 }
00997 
00998 
00999                 /* check if m is on a resolution band border */
01000                 if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1])
01001                 {
01002                     /* accumulate a whole range of equal Q_Ms */
01003                     if (Q_M_size > 0)
01004                         den += QUANTISE2INT(pow2(log2_int_tab[Q_M_size] + Q_M));
01005                     Q_M_size = 0;
01006 
01007                     /* step to next resolution band */
01008                     current_res_band2++;
01009 
01010                     /* if we move to a new resolution band, we should check if we are
01011                      * going to add a sinusoid in this band
01012                      */
01013                     S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
01014                 }
01015 
01016 
01017                 /* check if m is on a HI_RES band border */
01018                 if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1])
01019                 {
01020                     /* step to next HI_RES band */
01021                     current_hi_res_band++;
01022                 }
01023 
01024 
01025                 /* find S_index_mapped
01026                  * S_index_mapped can only be 1 for the m in the middle of the
01027                  * current HI_RES band
01028                  */
01029                 S_index_mapped = 0;
01030                 if ((l >= sbr->l_A[ch]) ||
01031                     (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch]))
01032                 {
01033                     /* find the middle subband of the HI_RES frequency band */
01034                     if ((m + sbr->kx) == (sbr->f_table_res[HI_RES][current_hi_res_band+1] + sbr->f_table_res[HI_RES][current_hi_res_band]) >> 1)
01035                         S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band];
01036                 }
01037 
01038 
01039                 /* find bitstream parameters */
01040                 if (sbr->E_curr[ch][m][l] == 0)
01041                     E_curr = LOG2_MIN_INF;
01042                 else
01043                     E_curr = -10 + log2(sbr->E_curr[ch][m][l]);
01044                 E_orig = -10 + find_log2_E(sbr, current_res_band2, l, ch);
01045 
01046                 Q_orig = find_log2_Q(sbr, current_f_noise_band, current_t_noise_band, ch);
01047                 Q_orig_plus1 = find_log2_Qplus1(sbr, current_f_noise_band, current_t_noise_band, ch);
01048 
01049 
01050                 /* Q_M only depends on E_orig and Q_div2:
01051                  * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
01052                  * a change of current res band (HI or LO)
01053                  */
01054                 Q_M = E_orig + Q_orig - Q_orig_plus1;
01055 
01056 
01057                 /* S_M only depends on E_orig, Q_div and S_index_mapped:
01058                  * S_index_mapped can only be non-zero once per HI_RES band
01059                  */
01060                 if (S_index_mapped == 0)
01061                 {
01062                     S_M[m] = LOG2_MIN_INF; /* -inf */
01063                 } else {
01064                     S_M[m] = E_orig - Q_orig_plus1;
01065 
01066                     /* accumulate sinusoid part of the total energy */
01067                     den += pow2(S_M[m]);
01068                 }
01069 
01070 
01071                 /* calculate gain */
01072                 /* ratio of the energy of the original signal and the energy
01073                  * of the HF generated signal
01074                  */
01075                 /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */
01076                 /* scaled by -10 */
01077                 G = E_orig - max(-10, E_curr);
01078                 if ((S_mapped == 0) && (delta == 1))
01079                 {
01080                     /* G = G * 1/(1+Q) */
01081                     G -= Q_orig_plus1;
01082                 } else if (S_mapped == 1) {
01083                     /* G = G * Q/(1+Q) */
01084                     G += Q_orig - Q_orig_plus1;
01085                 }
01086 
01087 
01088                 /* limit the additional noise energy level */
01089                 /* and apply the limiter */
01090                 if (G_max > G)
01091                 {
01092                     Q_M_lim[m] = QUANTISE2REAL(Q_M);
01093                     G_lim[m] = QUANTISE2REAL(G);
01094 
01095                     if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
01096                     {
01097                         Q_M_size++;
01098                     }
01099                 } else {
01100                     /* G > G_max */
01101                     Q_M_lim[m] = QUANTISE2REAL(Q_M) + G_max - QUANTISE2REAL(G);
01102                     G_lim[m] = G_max;
01103 
01104                     /* accumulate limited Q_M */
01105                     if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
01106                     {
01107                         den += QUANTISE2INT(pow2(Q_M_lim[m]));
01108                     }
01109                 }
01110 
01111 
01112                 /* accumulate the total energy */
01113                 /* E_curr changes for every m so we do need to accumulate every m */
01114                 den += QUANTISE2INT(pow2(E_curr + G_lim[m]));
01115             }
01116 
01117             /* accumulate last range of equal Q_Ms */
01118             if (Q_M_size > 0)
01119             {
01120                 den += QUANTISE2INT(pow2(log2_int_tab[Q_M_size] + Q_M));
01121             }
01122 
01123 
01124             /* calculate the final gain */
01125             /* G_boost: [0..2.51188643] */
01126             G_boost = acc1 - QUANTISE2REAL(log2(den + EPS));
01127             G_boost = min(G_boost, QUANTISE2REAL(1.328771237) /* log2(1.584893192 ^ 2) */);
01128 
01129 
01130             for (m = ml1; m < ml2; m++)
01131             {
01132                 /* apply compensation to gain, noise floor sf's and sinusoid levels */
01133 #ifndef SBR_LOW_POWER
01134                 adj->G_lim_boost[l][m] = QUANTISE2REAL(pow2((G_lim[m] + G_boost) / 2.0));
01135 #else
01136                 /* sqrt() will be done after the aliasing reduction to save a
01137                  * few multiplies
01138                  */
01139                 adj->G_lim_boost[l][m] = QUANTISE2REAL(pow2(G_lim[m] + G_boost));
01140 #endif
01141                 adj->Q_M_lim_boost[l][m] = QUANTISE2REAL(pow2((Q_M_lim[m] + 10 + G_boost) / 2.0));
01142 
01143                 if (S_M[m] != LOG2_MIN_INF)
01144                 {
01145                     adj->S_M_boost[l][m] = QUANTISE2REAL(pow2((S_M[m] + 10 + G_boost) / 2.0));
01146                 } else {
01147                     adj->S_M_boost[l][m] = 0;
01148                 }
01149             }
01150         }
01151     }
01152 }
01153 
01154 #else
01155 
01156 static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch)
01157 {
01158     static real_t limGain[] = { 0.5, 1.0, 2.0, 1e10 };
01159     uint8_t m, l, k;
01160 
01161     uint8_t current_t_noise_band = 0;
01162     uint8_t S_mapped;
01163 
01164     ALIGN real_t Q_M_lim[MAX_M];
01165     ALIGN real_t G_lim[MAX_M];
01166     ALIGN real_t G_boost;
01167     ALIGN real_t S_M[MAX_M];
01168 
01169     for (l = 0; l < sbr->L_E[ch]; l++)
01170     {
01171         uint8_t current_f_noise_band = 0;
01172         uint8_t current_res_band = 0;
01173         uint8_t current_res_band2 = 0;
01174         uint8_t current_hi_res_band = 0;
01175 
01176         real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1;
01177 
01178         S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
01179 
01180         if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1])
01181         {
01182             current_t_noise_band++;
01183         }
01184 
01185         for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
01186         {
01187             real_t G_max;
01188             real_t den = 0;
01189             real_t acc1 = 0;
01190             real_t acc2 = 0;
01191             uint8_t current_res_band_size = 0;
01192 
01193             uint8_t ml1, ml2;
01194 
01195             ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k];
01196             ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1];
01197 
01198 
01199             /* calculate the accumulated E_orig and E_curr over the limiter band */
01200             for (m = ml1; m < ml2; m++)
01201             {
01202                 if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
01203                 {
01204                     current_res_band++;
01205                 }
01206                 acc1 += sbr->E_orig[ch][current_res_band][l];
01207                 acc2 += sbr->E_curr[ch][m][l];
01208             }
01209 
01210 
01211             /* calculate the maximum gain */
01212             /* ratio of the energy of the original signal and the energy
01213              * of the HF generated signal
01214              */
01215             G_max = ((EPS + acc1) / (EPS + acc2)) * limGain[sbr->bs_limiter_gains];
01216             G_max = min(G_max, 1e10);
01217 
01218 
01219             for (m = ml1; m < ml2; m++)
01220             {
01221                 real_t Q_M, G;
01222                 real_t Q_div, Q_div2;
01223                 uint8_t S_index_mapped;
01224 
01225 
01226                 /* check if m is on a noise band border */
01227                 if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1])
01228                 {
01229                     /* step to next noise band */
01230                     current_f_noise_band++;
01231                 }
01232 
01233 
01234                 /* check if m is on a resolution band border */
01235                 if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1])
01236                 {
01237                     /* step to next resolution band */
01238                     current_res_band2++;
01239 
01240                     /* if we move to a new resolution band, we should check if we are
01241                      * going to add a sinusoid in this band
01242                      */
01243                     S_mapped = get_S_mapped(sbr, ch, l, current_res_band2);
01244                 }
01245 
01246 
01247                 /* check if m is on a HI_RES band border */
01248                 if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1])
01249                 {
01250                     /* step to next HI_RES band */
01251                     current_hi_res_band++;
01252                 }
01253 
01254 
01255                 /* find S_index_mapped
01256                  * S_index_mapped can only be 1 for the m in the middle of the
01257                  * current HI_RES band
01258                  */
01259                 S_index_mapped = 0;
01260                 if ((l >= sbr->l_A[ch]) ||
01261                     (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch]))
01262                 {
01263                     /* find the middle subband of the HI_RES frequency band */
01264                     if ((m + sbr->kx) == (sbr->f_table_res[HI_RES][current_hi_res_band+1] + sbr->f_table_res[HI_RES][current_hi_res_band]) >> 1)
01265                         S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band];
01266                 }
01267 
01268 
01269                 /* Q_div: [0..1] (1/(1+Q_mapped)) */
01270                 Q_div = sbr->Q_div[ch][current_f_noise_band][current_t_noise_band];
01271 
01272 
01273                 /* Q_div2: [0..1] (Q_mapped/(1+Q_mapped)) */
01274                 Q_div2 = sbr->Q_div2[ch][current_f_noise_band][current_t_noise_band];
01275 
01276 
01277                 /* Q_M only depends on E_orig and Q_div2:
01278                  * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
01279                  * a change of current noise band
01280                  */
01281                 Q_M = sbr->E_orig[ch][current_res_band2][l] * Q_div2;
01282 
01283 
01284                 /* S_M only depends on E_orig, Q_div and S_index_mapped:
01285                  * S_index_mapped can only be non-zero once per HI_RES band
01286                  */
01287                 if (S_index_mapped == 0)
01288                 {
01289                     S_M[m] = 0;
01290                 } else {
01291                     S_M[m] = sbr->E_orig[ch][current_res_band2][l] * Q_div;
01292 
01293                     /* accumulate sinusoid part of the total energy */
01294                     den += S_M[m];
01295                 }
01296 
01297 
01298                 /* calculate gain */
01299                 /* ratio of the energy of the original signal and the energy
01300                  * of the HF generated signal
01301                  */
01302                 G = sbr->E_orig[ch][current_res_band2][l] / (1.0 + sbr->E_curr[ch][m][l]);
01303                 if ((S_mapped == 0) && (delta == 1))
01304                     G *= Q_div;
01305                 else if (S_mapped == 1)
01306                     G *= Q_div2;
01307 
01308 
01309                 /* limit the additional noise energy level */
01310                 /* and apply the limiter */
01311                 if (G_max > G)
01312                 {
01313                     Q_M_lim[m] = Q_M;
01314                     G_lim[m] = G;
01315                 } else {
01316                     Q_M_lim[m] = Q_M * G_max / G;
01317                     G_lim[m] = G_max;
01318                 }
01319 
01320 
01321                 /* accumulate the total energy */
01322                 den += sbr->E_curr[ch][m][l] * G_lim[m];
01323                 if ((S_index_mapped == 0) && (l != sbr->l_A[ch]))
01324                     den += Q_M_lim[m];
01325             }
01326 
01327             /* G_boost: [0..2.51188643] */
01328             G_boost = (acc1 + EPS) / (den + EPS);
01329             G_boost = min(G_boost, 2.51188643 /* 1.584893192 ^ 2 */);
01330 
01331             for (m = ml1; m < ml2; m++)
01332             {
01333                 /* apply compensation to gain, noise floor sf's and sinusoid levels */
01334 #ifndef SBR_LOW_POWER
01335                 adj->G_lim_boost[l][m] = sqrt(G_lim[m] * G_boost);
01336 #else
01337                 /* sqrt() will be done after the aliasing reduction to save a
01338                  * few multiplies
01339                  */
01340                 adj->G_lim_boost[l][m] = G_lim[m] * G_boost;
01341 #endif
01342                 adj->Q_M_lim_boost[l][m] = sqrt(Q_M_lim[m] * G_boost);
01343 
01344                 if (S_M[m] != 0)
01345                 {
01346                     adj->S_M_boost[l][m] = sqrt(S_M[m] * G_boost);
01347                 } else {
01348                     adj->S_M_boost[l][m] = 0;
01349                 }
01350             }
01351         }
01352     }
01353 }
01354 #endif // log2_test
01355 
01356 #endif
01357 
01358 #ifdef SBR_LOW_POWER
01359 static void calc_gain_groups(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch)
01360 {
01361     uint8_t l, k, i;
01362     uint8_t grouping;
01363     uint8_t S_mapped;
01364 
01365     for (l = 0; l < sbr->L_E[ch]; l++)
01366     {
01367         uint8_t current_res_band = 0;
01368         i = 0;
01369         grouping = 0;
01370 
01371         S_mapped = get_S_mapped(sbr, ch, l, current_res_band);
01372 
01373         for (k = sbr->kx; k < sbr->kx + sbr->M - 1; k++)
01374         {
01375             if (k == sbr->f_table_res[sbr->f[ch][l]][current_res_band+1])
01376             {
01377                 /* step to next resolution band */
01378                 current_res_band++;
01379 
01380                 S_mapped = get_S_mapped(sbr, ch, l, current_res_band);
01381             }
01382 
01383             if (deg[k + 1] && S_mapped == 0)
01384             {
01385                 if (grouping == 0)
01386                 {
01387                     sbr->f_group[l][i] = k;
01388                     grouping = 1;
01389                     i++;
01390                 }
01391             } else {
01392                 if (grouping)
01393                 {
01394                     if (S_mapped)
01395                     {
01396                         sbr->f_group[l][i] = k;
01397                     } else {
01398                         sbr->f_group[l][i] = k + 1;
01399                     }
01400                     grouping = 0;
01401                     i++;
01402                 }
01403             }
01404         }        
01405 
01406         if (grouping)
01407         {
01408             sbr->f_group[l][i] = sbr->kx + sbr->M;
01409             i++;
01410         }
01411 
01412         sbr->N_G[l] = (uint8_t)(i >> 1);
01413     }
01414 }
01415 
01416 static void aliasing_reduction(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch)
01417 {
01418     uint8_t l, k, m;
01419     real_t E_total, E_total_est, G_target, acc;
01420 
01421     for (l = 0; l < sbr->L_E[ch]; l++)
01422     {
01423         for (k = 0; k < sbr->N_G[l]; k++)
01424         {
01425             E_total_est = E_total = 0;
01426             
01427             for (m = sbr->f_group[l][k<<1]; m < sbr->f_group[l][(k<<1) + 1]; m++)
01428             {
01429                 /* E_curr: integer */
01430                 /* G_lim_boost: fixed point */
01431                 /* E_total_est: integer */
01432                 /* E_total: integer */
01433                 E_total_est += sbr->E_curr[ch][m-sbr->kx][l];
01434 #ifdef FIXED_POINT
01435                 E_total += MUL_Q2(sbr->E_curr[ch][m-sbr->kx][l], adj->G_lim_boost[l][m-sbr->kx]);
01436 #else
01437                 E_total += sbr->E_curr[ch][m-sbr->kx][l] * adj->G_lim_boost[l][m-sbr->kx];
01438 #endif
01439             }
01440 
01441             /* G_target: fixed point */
01442             if ((E_total_est + EPS) == 0)
01443             {
01444                 G_target = 0;
01445             } else {
01446 #ifdef FIXED_POINT
01447                 G_target = (((int64_t)(E_total))<<Q2_BITS)/(E_total_est + EPS);
01448 #else
01449                 G_target = E_total / (E_total_est + EPS);
01450 #endif
01451             }
01452             acc = 0;
01453 
01454             for (m = sbr->f_group[l][(k<<1)]; m < sbr->f_group[l][(k<<1) + 1]; m++)
01455             {
01456                 real_t alpha;
01457 
01458                 /* alpha: (COEF) fixed point */
01459                 if (m < sbr->kx + sbr->M - 1)
01460                 {
01461                     alpha = max(deg[m], deg[m + 1]);
01462                 } else {
01463                     alpha = deg[m];
01464                 }
01465 
01466                 adj->G_lim_boost[l][m-sbr->kx] = MUL_C(alpha, G_target) +
01467                     MUL_C((COEF_CONST(1)-alpha), adj->G_lim_boost[l][m-sbr->kx]);
01468 
01469                 /* acc: integer */
01470 #ifdef FIXED_POINT
01471                 acc += MUL_Q2(adj->G_lim_boost[l][m-sbr->kx], sbr->E_curr[ch][m-sbr->kx][l]);
01472 #else
01473                 acc += adj->G_lim_boost[l][m-sbr->kx] * sbr->E_curr[ch][m-sbr->kx][l];
01474 #endif
01475             }
01476 
01477             /* acc: fixed point */
01478             if (acc + EPS == 0)
01479             {
01480                 acc = 0;
01481             } else {
01482 #ifdef FIXED_POINT
01483                 acc = (((int64_t)(E_total))<<Q2_BITS)/(acc + EPS);
01484 #else
01485                 acc = E_total / (acc + EPS);
01486 #endif
01487             }
01488             for(m = sbr->f_group[l][(k<<1)]; m < sbr->f_group[l][(k<<1) + 1]; m++)
01489             {
01490 #ifdef FIXED_POINT
01491                 adj->G_lim_boost[l][m-sbr->kx] = MUL_Q2(acc, adj->G_lim_boost[l][m-sbr->kx]);
01492 #else
01493                 adj->G_lim_boost[l][m-sbr->kx] = acc * adj->G_lim_boost[l][m-sbr->kx];
01494 #endif
01495             }
01496         }
01497     }
01498 
01499     for (l = 0; l < sbr->L_E[ch]; l++)
01500     {
01501         for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++)
01502         {
01503             for (m = sbr->f_table_lim[sbr->bs_limiter_bands][k];
01504                  m < sbr->f_table_lim[sbr->bs_limiter_bands][k+1]; m++)
01505             {
01506 #ifdef FIXED_POINT
01507                  adj->G_lim_boost[l][m] = SBR_SQRT_Q2(adj->G_lim_boost[l][m]);
01508 #else
01509                  adj->G_lim_boost[l][m] = sqrt(adj->G_lim_boost[l][m]);
01510 #endif
01511             }
01512         }
01513     }
01514 }
01515 #endif
01516 
01517 static void hf_assembly(sbr_info *sbr, sbr_hfadj_info *adj,
01518                         qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch)
01519 {
01520     static real_t h_smooth[] = {
01521         FRAC_CONST(0.03183050093751), FRAC_CONST(0.11516383427084),
01522         FRAC_CONST(0.21816949906249), FRAC_CONST(0.30150283239582),
01523         FRAC_CONST(0.33333333333333)
01524     };
01525     static int8_t phi_re[] = { 1, 0, -1, 0 };
01526     static int8_t phi_im[] = { 0, 1, 0, -1 };
01527 
01528     uint8_t m, l, i, n;
01529     uint16_t fIndexNoise = 0;
01530     uint8_t fIndexSine = 0;
01531     uint8_t assembly_reset = 0;
01532 
01533     real_t G_filt, Q_filt;
01534 
01535     uint8_t h_SL;
01536 
01537 
01538     if (sbr->Reset == 1)
01539     {
01540         assembly_reset = 1;
01541         fIndexNoise = 0;
01542     } else {
01543         fIndexNoise = sbr->index_noise_prev[ch];
01544     }
01545     fIndexSine = sbr->psi_is_prev[ch];
01546 
01547 
01548     for (l = 0; l < sbr->L_E[ch]; l++)
01549     {
01550         uint8_t no_noise = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 1 : 0;
01551 
01552 #ifdef SBR_LOW_POWER
01553         h_SL = 0;
01554 #else
01555         h_SL = (sbr->bs_smoothing_mode == 1) ? 0 : 4;
01556         h_SL = (no_noise ? 0 : h_SL);
01557 #endif
01558 
01559         if (assembly_reset)
01560         {
01561             for (n = 0; n < 4; n++)
01562             {
01563                 memcpy(sbr->G_temp_prev[ch][n], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
01564                 memcpy(sbr->Q_temp_prev[ch][n], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
01565             }
01566             /* reset ringbuffer index */
01567             sbr->GQ_ringbuf_index[ch] = 4;
01568             assembly_reset = 0;
01569         }
01570 
01571         for (i = sbr->t_E[ch][l]; i < sbr->t_E[ch][l+1]; i++)
01572         {
01573 #ifdef SBR_LOW_POWER
01574             uint8_t i_min1, i_plus1;
01575             uint8_t sinusoids = 0;
01576 #endif
01577 
01578             /* load new values into ringbuffer */
01579             memcpy(sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->G_lim_boost[l], sbr->M*sizeof(real_t));
01580             memcpy(sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t));
01581 
01582             for (m = 0; m < sbr->M; m++)
01583             {
01584                 qmf_t psi;
01585 
01586                 G_filt = 0;
01587                 Q_filt = 0;
01588 
01589 #ifndef SBR_LOW_POWER
01590                 if (h_SL != 0)
01591                 {
01592                         uint8_t ri = sbr->GQ_ringbuf_index[ch];
01593                     for (n = 0; n <= 4; n++)
01594                     {
01595                         real_t curr_h_smooth = h_smooth[n];
01596                         ri++;
01597                         if (ri >= 5)
01598                             ri -= 5;
01599                         G_filt += MUL_F(sbr->G_temp_prev[ch][ri][m], curr_h_smooth);
01600                         Q_filt += MUL_F(sbr->Q_temp_prev[ch][ri][m], curr_h_smooth);
01601                     }
01602                } else {
01603 #endif
01604                     G_filt = sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
01605                     Q_filt = sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m];
01606 #ifndef SBR_LOW_POWER
01607                 }
01608 #endif
01609 
01610                 Q_filt = (adj->S_M_boost[l][m] != 0 || no_noise) ? 0 : Q_filt;
01611 
01612                 /* add noise to the output */
01613                 fIndexNoise = (fIndexNoise + 1) & 511;
01614 
01615                 /* the smoothed gain values are applied to Xsbr */
01616                 /* V is defined, not calculated */
01617 #ifndef FIXED_POINT
01618                 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = G_filt * QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx])
01619                     + MUL_F(Q_filt, RE(V[fIndexNoise]));
01620 #else
01621                 //QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_Q2(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
01622                 //    + MUL_F(Q_filt, RE(V[fIndexNoise]));
01623                 QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
01624                     + MUL_F(Q_filt, RE(V[fIndexNoise]));
01625 #endif
01626                 if (sbr->bs_extension_id == 3 && sbr->bs_extension_data == 42)
01627                     QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = 16428320;
01628 #ifndef SBR_LOW_POWER
01629 #ifndef FIXED_POINT
01630                 QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = G_filt * QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx])
01631                     + MUL_F(Q_filt, IM(V[fIndexNoise]));
01632 #else
01633                 //QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_Q2(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
01634                 //    + MUL_F(Q_filt, IM(V[fIndexNoise]));
01635                 QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]))
01636                     + MUL_F(Q_filt, IM(V[fIndexNoise]));
01637 #endif
01638 #endif
01639 
01640                 {
01641                     int8_t rev = (((m + sbr->kx) & 1) ? -1 : 1);
01642                     QMF_RE(psi) = adj->S_M_boost[l][m] * phi_re[fIndexSine];
01643 #ifdef FIXED_POINT
01644                     QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += (QMF_RE(psi) << REAL_BITS);
01645 #else
01646                     QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_RE(psi);
01647 #endif
01648 
01649 #ifndef SBR_LOW_POWER
01650                     QMF_IM(psi) = rev * adj->S_M_boost[l][m] * phi_im[fIndexSine];
01651 #ifdef FIXED_POINT
01652                     QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += (QMF_IM(psi) << REAL_BITS);
01653 #else
01654                     QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_IM(psi);
01655 #endif
01656 #else
01657 
01658                     i_min1 = (fIndexSine - 1) & 3;
01659                     i_plus1 = (fIndexSine + 1) & 3;
01660 
01661 #ifndef FIXED_POINT
01662                     if ((m == 0) && (phi_re[i_plus1] != 0))
01663                     {
01664                         QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx - 1]) +=
01665                             (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][0], FRAC_CONST(0.00815)));
01666                         if (sbr->M != 0)
01667                         {
01668                             QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
01669                                 (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][1], FRAC_CONST(0.00815)));
01670                         }
01671                     }
01672                     if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
01673                     {
01674                         QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
01675                             (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m - 1], FRAC_CONST(0.00815)));
01676                     }
01677                     if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_plus1] != 0))
01678                     {
01679                         QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
01680                             (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][m + 1], FRAC_CONST(0.00815)));
01681                     }
01682                     if ((m == sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
01683                     {
01684                         if (m > 0)
01685                         {
01686                             QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
01687                                 (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m - 1], FRAC_CONST(0.00815)));
01688                         }
01689                         if (m + sbr->kx < 64)
01690                         {
01691                             QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx + 1]) +=
01692                                 (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m], FRAC_CONST(0.00815)));
01693                         }
01694                     }
01695 #else
01696                     if ((m == 0) && (phi_re[i_plus1] != 0))
01697                     {
01698                         QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx - 1]) +=
01699                             (rev*phi_re[i_plus1] * MUL_F((adj->S_M_boost[l][0]<<REAL_BITS), FRAC_CONST(0.00815)));
01700                         if (sbr->M != 0)
01701                         {
01702                             QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
01703                                 (rev*phi_re[i_plus1] * MUL_F((adj->S_M_boost[l][1]<<REAL_BITS), FRAC_CONST(0.00815)));
01704                         }
01705                     }
01706                     if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
01707                     {
01708                         QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
01709                             (rev*phi_re[i_min1] * MUL_F((adj->S_M_boost[l][m - 1]<<REAL_BITS), FRAC_CONST(0.00815)));
01710                     }
01711                     if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_plus1] != 0))
01712                     {
01713                         QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
01714                             (rev*phi_re[i_plus1] * MUL_F((adj->S_M_boost[l][m + 1]<<REAL_BITS), FRAC_CONST(0.00815)));
01715                     }
01716                     if ((m == sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0))
01717                     {
01718                         if (m > 0)
01719                         {
01720                             QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -=
01721                                 (rev*phi_re[i_min1] * MUL_F((adj->S_M_boost[l][m - 1]<<REAL_BITS), FRAC_CONST(0.00815)));
01722                         }
01723                         if (m + sbr->kx < 64)
01724                         {
01725                             QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx + 1]) +=
01726                                 (rev*phi_re[i_min1] * MUL_F((adj->S_M_boost[l][m]<<REAL_BITS), FRAC_CONST(0.00815)));
01727                         }
01728                     }
01729 #endif
01730 
01731                     if (adj->S_M_boost[l][m] != 0)
01732                         sinusoids++;
01733 #endif
01734                 }
01735             }
01736 
01737             fIndexSine = (fIndexSine + 1) & 3;
01738 
01739             /* update the ringbuffer index used for filtering G and Q with h_smooth */
01740             sbr->GQ_ringbuf_index[ch]++;
01741             if (sbr->GQ_ringbuf_index[ch] >= 5)
01742                 sbr->GQ_ringbuf_index[ch] = 0;
01743         }
01744     }
01745 
01746     sbr->index_noise_prev[ch] = fIndexNoise;
01747     sbr->psi_is_prev[ch] = fIndexSine;
01748 }
01749 
01750 #endif

Generated on Tue Dec 13 14:47:45 2005 for guliverkli by  doxygen 1.4.5