/* ------------------------------------------------------------------ * Copyright (C) 1998-2009 PacketVideo * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. * See the License for the specific language governing permissions * and limitations under the License. * ------------------------------------------------------------------- */ /* Filename: calc_sbr_envelope.c ------------------------------------------------------------------------------ REVISION HISTORY Who: Date: MM/DD/YYYY Description: ------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS ------------------------------------------------------------------------------ FUNCTION DESCRIPTION ------------------------------------------------------------------------------ REQUIREMENTS ------------------------------------------------------------------------------ REFERENCES SC 29 Software Copyright Licencing Disclaimer: This software module was originally developed by Coding Technologies and edited by - in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards for reference purposes and its performance may not have been optimized. This software module is an implementation of one or more tools as specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards. ISO/IEC gives users free license to this software module or modifications thereof for use in products claiming conformance to audiovisual and image-coding related ITU Recommendations and/or ISO/IEC International Standards. ISO/IEC gives users the same free license to this software module or modifications thereof for research purposes and further ISO/IEC standardisation. Those intending to use this software module in products are advised that its use may infringe existing patents. ISO/IEC have no liability for use of this software module or modifications thereof. Copyright is not released for products that do not conform to audiovisual and image-coding related ITU Recommendations and/or ISO/IEC International Standards. The original developer retains full right to modify and use the code for its own purpose, assign or donate the code to a third party and to inhibit third parties from using the code for products that do not conform to audiovisual and image-coding related ITU Recommendations and/or ISO/IEC International Standards. This copyright notice must be included in all copies or derivative works. Copyright (c) ISO/IEC 2002. ------------------------------------------------------------------------------ PSEUDO-CODE ------------------------------------------------------------------------------ */ /*---------------------------------------------------------------------------- ; INCLUDES ----------------------------------------------------------------------------*/ #ifdef AAC_PLUS #include "calc_sbr_envelope.h" #include "sbr_envelope_calc_tbl.h" #include "sbr_create_limiter_bands.h" #include "aac_mem_funcs.h" #include "fxp_mul32.h" #include "pv_normalize.h" #include "sbr_aliasing_reduction.h" /*---------------------------------------------------------------------------- ; MACROS ; Define module specific macros here ----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- ; DEFINES ; Include all pre-processor statements here. Include conditional ; compile variables also. ----------------------------------------------------------------------------*/ #include "pv_sqrt.h" #include "pv_div.h" #include "fxp_mul32.h" #include "pv_normalize.h" #define Q30fmt(x) (Int32)(x*((Int32)1<<30) + (x>=0?0.5F:-0.5F)) #define Q28fmt(x) (Int32)(x*((Int32)1<<28) + (x>=0?0.5F:-0.5F)) #define Q15fmt(x) (Int32)(x*((Int32)1<<15) + (x>=0?0.5F:-0.5F)) /*---------------------------------------------------------------------------- ; LOCAL FUNCTION DEFINITIONS ; Function Prototype declaration ----------------------------------------------------------------------------*/ #ifdef __cplusplus extern "C" { #endif void envelope_application_LC(Int32 *aBufR, Int32 *nrg_gain_man, Int32 *nrg_gain_exp, Int32 *noise_level_man, Int32 *noise_level_exp, Int32 *nrg_tone_man, Int32 *nrg_tone_exp, Int32 band_nrg_tone_detector, const Int32 *frame_info, Int32 *harm_index, Int32 *phase_index, Int32 i, Int32 lowSubband, Int32 noSubbands, Int32 noNoiseFlag); void energy_estimation_LC(Int32 *aBufR, Int32 *nrg_est_man, Int32 *nrg_est_exp, const Int32 *frame_info, Int32 i, Int32 k, Int32 c, Int32 ui2); #ifdef HQ_SBR void envelope_application(Int32 *aBufR, Int32 *aBufI, Int32 *nrg_gain_man, Int32 *nrg_gain_exp, Int32 *noise_level_man, Int32 *noise_level_exp, Int32 *nrg_tone_man, Int32 *nrg_tone_exp, Int32 *fBuf_man[64], Int32 *fBuf_exp[64], Int32 *fBufN_man[64], Int32 *fBufN_exp[64], const Int32 *frame_info, Int32 *harm_index, Int32 *phase_index, Int32 i, Int32 lowSubband, Int32 noSubbands, Int32 noNoiseFlag, Int32 band_nrg_tone_detector, Int32 maxSmoothLength, Int32 smooth_length); void energy_estimation(Int32 *aBufR, Int32 *aBufI, Int32 *nrg_est_man, Int32 *nrg_est_exp, const Int32 *frame_info, Int32 i, Int32 k, Int32 c, Int32 ui2); #endif #ifdef __cplusplus } #endif /*---------------------------------------------------------------------------- ; LOCAL STORE/BUFFER/POINTER DEFINITIONS ; Variable declaration - defined here and used outside this module ----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- ; EXTERNAL FUNCTION REFERENCES ; Declare functions defined elsewhere and referenced in this module ----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES ; Declare variables used in this module but defined elsewhere ----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ void calc_sbr_envelope(SBR_FRAME_DATA *frameData, Int32 *aBufR, Int32 *aBufI, Int freqBandTable1[2][MAX_FREQ_COEFFS + 1], const Int32 *nSfb, Int32 freqBandTable2[MAX_NOISE_COEFFS + 1], Int32 nNBands, Int32 reset, Int32 *degreeAlias, Int32 *harm_index, Int32 *phase_index, Int32 hFp[64], Int32 *sUp, Int32 limSbc[][13], Int32 *gateMode, #ifdef HQ_SBR Int32 *fBuf_man[64], Int32 *fBuf_exp[64], Int32 *fBufN_man[64], Int32 *fBufN_exp[64], #endif Int32 scratch_mem[][64], struct PATCH Patch, Int32 sqrt_cache[][4], Int32 LC_flag) { Int32 c; Int32 li; Int32 ui; Int32 i; Int32 j; Int32 k = 0; Int32 l; Int m = 0; Int kk = 0; Int o; Int next = -1; Int32 ui2; Int flag; Int noNoiseFlag; Int *ptr; UInt32 nrg = 0; Int32 nrg_exp = 0; struct intg_div quotient; struct intg_sqrt root_sq; Int32 aux1; Int32 *nL_man = frameData->sbrNoiseFloorLevel_man; Int32 *nL_exp = frameData->sbrNoiseFloorLevel_exp; Int32 *sfb_nrg_man = frameData->iEnvelope_man; Int32 *sfb_nrg_exp = frameData->iEnvelope_exp; Int32 tmp_q1; Int32 tmp_q2; Int32 g_max_man; Int32 g_max_exp; Int32 p_ref_man; Int32 p_ref_exp; Int32 p_est_man; Int32 p_est_exp; Int32 p_adj_man; Int32 p_adj_exp; Int32 avg_gain; Int32 boost_gain_q; Int32 band_nrg_tone_detector; Int32 *nrg_est_man = scratch_mem[0]; Int32 *nrg_est_exp = scratch_mem[1]; Int32 *nrg_ref_man = scratch_mem[2]; Int32 *nrg_ref_exp = scratch_mem[3]; Int32 *nrg_gain_man = scratch_mem[4]; Int32 *nrg_gain_exp = scratch_mem[5]; Int32 *noise_level_man = scratch_mem[6]; Int32 *noise_level_exp = scratch_mem[7]; Int32 *nrg_tone_man = scratch_mem[8]; Int32 *nrg_tone_exp = scratch_mem[9]; Int32 *hF = scratch_mem[10]; const Int32 *frame_info = frameData->frameInfo; Int32 int_mode = frameData->sbr_header.interpolFreq; Int32 dontUseTheseGainValues[64]; #ifdef HQ_SBR Int32 n; Int32 smooth_length; Int32 smoothingLength = frameData->sbr_header.smoothingLength; Int32 maxSmoothLength = smoothLengths[0]; #endif Int32 limiterBand = frameData->sbr_header.limiterBands; Int32 limiterGains = frameData->sbr_header.limiterGains; Int32 *addHarmonics = frameData->addHarmonics; Int32 lowSubband = freqBandTable1[LOW_RES][0]; Int32 noSubbands = freqBandTable1[LOW_RES][nSfb[LOW_RES]] - lowSubband; Int32 nEnv = frame_info[0]; Int32 sEnv = frame_info[(nEnv + 1)<<1]; /* ensure that noSubbands in the range [0,64] */ noSubbands = (noSubbands >> 31) ^ noSubbands; if (noSubbands > 64) { noSubbands = 64; } if (reset) { *sUp = 1; *phase_index = 0; sbr_create_limiter_bands(limSbc, gateMode, freqBandTable1[LOW_RES], Patch, nSfb[LOW_RES]); } /* Mapping. */ pv_memset((void*)hF, 0, (sizeof(*hF) << 6)); ptr = freqBandTable1[HI]; l = *(ptr++); for (i = nSfb[HI]; i != 0; i--) { k = *(ptr++); j = ((k + l) >> 1) - lowSubband; l = k; hF[j] = *(addHarmonics++); } /* Envelope adjustment. */ for (i = 0; i < nEnv; i++) { if (frame_info[1+i] == frame_info[(nEnv<<1)+4+kk]) { kk++, next++; } noNoiseFlag = (i == sEnv || i == frameData->prevEnvIsShort) ? 1 : 0; #ifdef HQ_SBR smooth_length = (noNoiseFlag ? 0 : smoothLengths[smoothingLength]); #endif /* Estimate levels. */ c = 0; o = 0; band_nrg_tone_detector = 0; Int kkkk = freqBandTable1[ frame_info[nEnv+2+i] ][0]; for (j = 0; j < nSfb[frame_info[nEnv+2+i]]; j++) { li = freqBandTable1[ frame_info[nEnv+2+i] ][j ]; ui = freqBandTable1[ frame_info[nEnv+2+i] ][j + 1]; flag = 0; for (k = li; k < ui; k++) { /* Calculate the average energy over the current envelope, */ ui2 = (frame_info[1+i] << 1); if (LC_flag == ON) { energy_estimation_LC((Int32 *)aBufR, nrg_est_man, nrg_est_exp, frame_info, i, k - kkkk, c, ui2); } #ifdef HQ_SBR else { energy_estimation((Int32 *)aBufR, (Int32 *)aBufI, nrg_est_man, nrg_est_exp, frame_info, i, k - kkkk, c, ui2); } #endif flag = (hF[c] && (i >= sEnv || hFp[c+lowSubband])) ? 1 : flag; c++; } ui2 = freqBandTable2[o+1]; if (!int_mode) { /* If no interpolation is used, */ tmp_q1 = -100; for (k = c - (ui - li); k < c; k++) { if (tmp_q1 < nrg_est_exp[k]) { tmp_q1 = nrg_est_exp[k]; } } nrg = 0; for (k = c - (ui - li); k < c; k++) { /* average the energy in all the QMF bands, */ nrg += nrg_est_man[k] >> (tmp_q1 - nrg_est_exp[k]); /* for the whole scalefactor band. */ } nrg /= (ui - li); nrg_exp = tmp_q1; } c -= (ui - li); for (k = 0; k < ui - li; k++) { o = (k + li >= ui2) ? o + 1 : o; ui2 = freqBandTable2[o+1]; /* * If no interpolation is used, use the averaged energy from above, * otherwise do nothing. */ if (!int_mode) { nrg_est_man[c] = nrg; nrg_est_exp[c] = nrg_exp; } if (LC_flag == ON) { nrg_est_exp[c] += 1; if (flag) { dontUseTheseGainValues[k + li - lowSubband] = 1; } else { dontUseTheseGainValues[k + li - lowSubband] = 0; } } nrg_ref_man[c] = sfb_nrg_man[m]; nrg_ref_exp[c] = sfb_nrg_exp[m]; /* * compute nL/(1 + nL); where nL = nL_man*2^nL_exp */ aux1 = next * nNBands + o; tmp_q1 = nL_exp[aux1]; if (tmp_q1 >= 0) { pv_div(nL_man[aux1], nL_man[aux1] + (0x3FFFFFFF >> tmp_q1), "ient); } else { tmp_q1 = nL_man[aux1] >> (-tmp_q1); pv_div(tmp_q1, tmp_q1 + 0x3FFFFFFF, "ient); } /* * tmp_q1 = nL/(1 + nL)*nrg_ref[c]; */ tmp_q1 = fxp_mul32_Q30(quotient.quotient >> quotient.shift_factor, nrg_ref_man[c]); if (flag) { /* * Calculate levels and gain, dependent on whether a synthetic, a sine is present or not. * * nrg_gain[c]=(float)pv_sqrt( tmp/(nrg_est[c] + 1), sqrt_cache[1] ); */ pv_div(tmp_q1, nrg_est_man[c] + 1, "ient); /* * nrg_est_man[c] is an integer number, while tmp_q1 and quotient.quotient * are fractions in Q30 */ tmp_q2 = nrg_ref_exp[c] - nrg_est_exp[c] - quotient.shift_factor - 30; pv_sqrt(quotient.quotient, tmp_q2, &root_sq, sqrt_cache[1]); nrg_gain_man[c] = root_sq.root; /* in Q28 format */ nrg_gain_exp[c] = root_sq.shift_factor; /* * nrg_tone[c]=(float)( (hF[c] && (i >= sEnv || hFp[c+lowSubband])) ? * pv_sqrt(nrg_ref[c]/(1+tmp_nL), sqrt_cache[2]) : 0); */ if (hF[c] && (i >= sEnv || hFp[c+lowSubband])) { /* * nrg_ref[c] and nL, as well as quotient.quotient * are fractions in Q30 */ /* aux1 == next*nNBands + o */ tmp_q2 = nL_exp[aux1]; /* * nrg_ref[c]/(1+tmp_nL) */ if (tmp_q2 >= 0) { pv_div(nrg_ref_man[c], nL_man[aux1] + (0x3FFFFFFF >> tmp_q2), "ient); } else { tmp_q2 = nL_man[aux1] >> (-tmp_q2); pv_div(nrg_ref_man[c], tmp_q2 + 0x3FFFFFFF, "ient); tmp_q2 = 0; /* exponent has been applied to the sum ((man>>exp) + 1) */ } tmp_q2 = nrg_ref_exp[c] - tmp_q2 - quotient.shift_factor; pv_sqrt(quotient.quotient, tmp_q2, &root_sq, sqrt_cache[2]); nrg_tone_man[c] = root_sq.root; nrg_tone_exp[c] = root_sq.shift_factor; } else { nrg_tone_man[c] = 0; nrg_tone_exp[c] = 0; } } else { if (noNoiseFlag) { /* * nrg_gain[c] = (float) pv_sqrt(nrg_ref[c] /(nrg_est[c] + 1), sqrt_cache[3]); */ pv_div(nrg_ref_man[c], nrg_est_man[c] + 1, "ient); /* * nrg_est_man[c] is an integer number, while nrg_ref_man[c] and * quotient.quotient are fractions in Q30 */ tmp_q2 = nrg_ref_exp[c] - nrg_est_exp[c] - quotient.shift_factor - 30; pv_sqrt(quotient.quotient, tmp_q2, &root_sq, sqrt_cache[3]); nrg_gain_man[c] = root_sq.root; nrg_gain_exp[c] = root_sq.shift_factor; } else { /* * nrg_gain[c] = (float) pv_sqrt(nrg_ref[c]/((nrg_est[c] + 1)*(1+tmp_nL)), sqrt_cache[4]); */ /* aux1 == next*nNBands + o */ tmp_q2 = nL_exp[aux1]; /* * nrg_ref[c]/((nrg_est[c] + 1)*(1+tmp_nL)) */ if (nrg_est_man[c] == 0) { tmp_q2 = 0; /* avoid division by 0 in next if-else, this could be due to rounding noise */ } if (tmp_q2 >= 0) { tmp_q2 = fxp_mul32_Q30(nrg_est_man[c] + 1, nL_man[aux1] + (0x3FFFFFFF >> tmp_q2)); pv_div(nrg_ref_man[c], tmp_q2, "ient); /* * nrg_est_man[c] is an integer number, while nrg_ref_man[c] and * quotient.quotient are fractions in Q30 */ tmp_q2 = nrg_ref_exp[c] - quotient.shift_factor - 30 - nL_exp[aux1]; if (nrg_est_man[c]) { tmp_q2 -= nrg_est_exp[c]; } tmp_q2 = nrg_ref_exp[c] - nrg_est_exp[c] - quotient.shift_factor - 30 - nL_exp[aux1]; } else { if (tmp_q2 > - 10) { tmp_q2 = nL_man[aux1] >> (-tmp_q2); tmp_q2 = fxp_mul32_Q30(nrg_est_man[c] + 1, tmp_q2 + 0x3FFFFFFF); } else { tmp_q2 = nrg_est_man[c] + 1; } pv_div(nrg_ref_man[c], tmp_q2, "ient); /* * nrg_est_man[c] is an integer number, while nrg_ref_man[c] and * quotient.quotient are fractions in Q30 */ tmp_q2 = nrg_ref_exp[c] - quotient.shift_factor - 30; if (nrg_est_man[c]) { tmp_q2 -= nrg_est_exp[c]; } } pv_sqrt(quotient.quotient, tmp_q2, &root_sq, sqrt_cache[4]); nrg_gain_man[c] = root_sq.root; nrg_gain_exp[c] = root_sq.shift_factor; } nrg_tone_man[c] = 0; nrg_tone_exp[c] = -100; } band_nrg_tone_detector |= nrg_tone_man[c]; /* detect any tone activity */ pv_sqrt(tmp_q1, nrg_ref_exp[c], &root_sq, sqrt_cache[5]); noise_level_man[c] = root_sq.root; noise_level_exp[c] = root_sq.shift_factor; c++; } /* ---- end-for-loop (k) ------ */ m++; } /* -------- Estimate levels end-for-loop (j) ----- */ /* * Limiter */ for (c = 0; c < gateMode[limiterBand]; c++) { p_ref_man = 0; p_est_man = 0; /* * get max exponent for the reference and estimated energy */ p_ref_exp = -100; p_est_exp = -100; for (k = limSbc[limiterBand][c]; k < limSbc[limiterBand][c + 1]; k++) { if (p_ref_exp < nrg_ref_exp[k]) { p_ref_exp = nrg_ref_exp[k]; /* max */ } if (p_est_exp < nrg_est_exp[k]) { p_est_exp = nrg_est_exp[k]; /* max */ } } k -= limSbc[limiterBand][c]; /* number of element used in the addition */ while (k != 0) /* bit guard protection depends on log2(k) */ { k >>= 1; p_ref_exp++; /* add extra bit-overflow-guard, nrg_ref_exp is in Q30 format */ } for (k = limSbc[limiterBand][c]; k < limSbc[limiterBand][c + 1]; k++) { /*Calculate the average gain for the current limiter band.*/ p_ref_man += (nrg_ref_man[k] >> (p_ref_exp - nrg_ref_exp[k])); p_est_man += (nrg_est_man[k] >> (p_est_exp - nrg_est_exp[k])); } if (p_est_man) { /* * "average gain" (not equal to average of nrg_gain) */ pv_div(p_ref_man, p_est_man, "ient); tmp_q2 = p_ref_exp - 30 - p_est_exp - quotient.shift_factor; /* * avg_gain = sqrt(p_ref/p_est) */ pv_sqrt(quotient.quotient, tmp_q2, &root_sq, sqrt_cache[6]); avg_gain = root_sq.root; g_max_exp = root_sq.shift_factor; /* * maximum gain allowed is calculated from table. */ /* * g_max = avg_gain * limGains[limiterGains]; */ g_max_man = fxp_mul32_Q30(avg_gain, limGains[limiterGains]); /* table is in Q30 */ if (limiterGains == 3) { g_max_exp = limGains[4]; } tmp_q1 = g_max_exp >= 16 ? g_max_exp : 16; tmp_q2 = g_max_man >> (tmp_q1 - g_max_exp); tmp_q1 = Q28fmt(1.52587890625F) >> (tmp_q1 - 16); if (tmp_q2 > tmp_q1) { /* upper limit, +100 dB */ g_max_man = Q28fmt(1.52587890625F); g_max_exp = 16; } } else { /* Qfmt(1.52587890625F) exp = 16 */ g_max_man = Q28fmt(1.52587890625F); g_max_exp = 16; } /* * Compute Adjusted power p_adj */ for (k = limSbc[limiterBand][c]; k < limSbc[limiterBand][c + 1]; k++) { tmp_q1 = g_max_exp >= nrg_gain_exp[k] ? g_max_exp : nrg_gain_exp[k]; tmp_q2 = g_max_man >> (tmp_q1 - g_max_exp); tmp_q1 = nrg_gain_man[k] >> (tmp_q1 - nrg_gain_exp[k]); /* * if(g_max <= nrg_gain[k]) */ if (tmp_q2 <= tmp_q1) { tmp_q1 = fxp_mul32_Q28(noise_level_man[k], g_max_man); pv_div(tmp_q1, nrg_gain_man[k], "ient); noise_level_man[k] = quotient.quotient >> 2; /* in Q28 */ noise_level_exp[k] = noise_level_exp[k] + g_max_exp - quotient.shift_factor - nrg_gain_exp[k]; nrg_gain_man[k] = g_max_man; /* gains with noise supression */ nrg_gain_exp[k] = g_max_exp; } } p_adj_exp = -100; for (k = limSbc[limiterBand][c]; k < limSbc[limiterBand][c + 1]; k++) { tmp_q1 = nrg_est_exp[k] + (nrg_gain_exp[k] << 1) + 28; /* 28 to match shift down by mult32_Q28 */ if (p_adj_exp < tmp_q1) { p_adj_exp = tmp_q1; } if (nrg_tone_man[k]) { tmp_q1 = (nrg_tone_exp[k] << 1); if (p_adj_exp < tmp_q1) { p_adj_exp = tmp_q1; } } else if (!noNoiseFlag) { tmp_q1 = (noise_level_exp[k] << 1); if (p_adj_exp < tmp_q1) { p_adj_exp = tmp_q1; } } } p_adj_exp += 1; /* overflow bit-guard*/ p_adj_man = 0; for (k = limSbc[limiterBand][c]; k < limSbc[limiterBand][c + 1]; k++) { /* * p_adj += nrg_gain[k]*nrg_gain[k]*nrg_est[k]; */ if (p_adj_exp - (nrg_est_exp[k] + (nrg_gain_exp[k] << 1)) < 59) { tmp_q1 = fxp_mul32_Q28(nrg_gain_man[k], nrg_gain_man[k]); tmp_q1 = fxp_mul32_Q28(tmp_q1, nrg_est_man[k]); p_adj_man += (tmp_q1 >> (p_adj_exp - (nrg_est_exp[k] + (nrg_gain_exp[k] << 1) + 28))); } if (nrg_tone_man[k]) { /* * p_adj += nrg_tone[k]*nrg_tone[k]; */ if (p_adj_exp - (nrg_tone_exp[k] << 1) < 31) { tmp_q1 = fxp_mul32_Q28(nrg_tone_man[k], nrg_tone_man[k]); p_adj_man += (tmp_q1 >> (p_adj_exp - (nrg_tone_exp[k] << 1))); } } else if (!noNoiseFlag) { /* * p_adj += noise_level[k]*noise_level[k]; */ if (p_adj_exp - (noise_level_exp[k] << 1) < 31) { tmp_q1 = fxp_mul32_Q28(noise_level_man[k], noise_level_man[k]); p_adj_man += (tmp_q1 >> (p_adj_exp - (noise_level_exp[k] << 1))); } } } if (p_adj_man) { pv_div(p_ref_man, p_adj_man, "ient); tmp_q2 = p_ref_exp - p_adj_exp - 58 - quotient.shift_factor; /* 58 <> Q30 + Q28 */ pv_sqrt(quotient.quotient, tmp_q2, &root_sq, sqrt_cache[7]); if (root_sq.shift_factor > -28) { boost_gain_q = root_sq.root << (root_sq.shift_factor + 28); } else { boost_gain_q = root_sq.root >> (-28 - root_sq.shift_factor); } tmp_q1 = root_sq.shift_factor >= -28 ? root_sq.shift_factor : -28; tmp_q2 = root_sq.root >> (tmp_q1 - root_sq.shift_factor); tmp_q1 = Q28fmt(1.584893192f) >> (tmp_q1 + 28); if (tmp_q2 > tmp_q1) { boost_gain_q = Q28fmt(1.584893192f); } } else { boost_gain_q = Q28fmt(1.584893192f); } if (band_nrg_tone_detector) { for (k = limSbc[limiterBand][c]; k < limSbc[limiterBand][c + 1]; k++) { nrg_gain_man[k] = fxp_mul32_Q28(nrg_gain_man[k], boost_gain_q); noise_level_man[k] = fxp_mul32_Q28(noise_level_man[k], boost_gain_q); nrg_tone_man[k] = fxp_mul32_Q28(nrg_tone_man[k], boost_gain_q); } } else { for (k = limSbc[limiterBand][c]; k < limSbc[limiterBand][c + 1]; k++) { nrg_gain_man[k] = fxp_mul32_Q28(nrg_gain_man[k], boost_gain_q); noise_level_man[k] = fxp_mul32_Q28(noise_level_man[k], boost_gain_q); } } } /* Limiter End for loop (c) */ if (LC_flag == ON) { /* * Aliasing correction */ sbr_aliasing_reduction(degreeAlias, nrg_gain_man, nrg_gain_exp, nrg_est_man, nrg_est_exp, dontUseTheseGainValues, noSubbands, lowSubband, sqrt_cache, scratch_mem[3]); if (*sUp) /* Init only done once upon reset */ { *sUp = 0; } envelope_application_LC((Int32 *)aBufR, nrg_gain_man, nrg_gain_exp, noise_level_man, noise_level_exp, nrg_tone_man, nrg_tone_exp, band_nrg_tone_detector, frame_info, harm_index, phase_index, i, lowSubband, noSubbands, noNoiseFlag); } #ifdef HQ_SBR else { if (*sUp) /* Init only done once upon reset */ { for (n = 0; n < maxSmoothLength; n++) { pv_memcpy(fBuf_man[n], nrg_gain_man, noSubbands*sizeof(*fBuf_man[n])); pv_memcpy(fBufN_man[n], noise_level_man, noSubbands*sizeof(*fBufN_man[n])); pv_memcpy(fBuf_exp[n], nrg_gain_exp, noSubbands*sizeof(*fBuf_exp[n])); pv_memcpy(fBufN_exp[n], noise_level_exp, noSubbands*sizeof(*fBufN_exp[n])); } *sUp = 0; } envelope_application((Int32 *)aBufR, (Int32 *)aBufI, nrg_gain_man, nrg_gain_exp, noise_level_man, noise_level_exp, nrg_tone_man, nrg_tone_exp, fBuf_man, fBuf_exp, fBufN_man, fBufN_exp, frame_info, harm_index, phase_index, i, lowSubband, noSubbands, noNoiseFlag, band_nrg_tone_detector, maxSmoothLength, smooth_length); } #endif } /* ----- Envelope adjustment end for-loop (i) ---- */ pv_memcpy(&hFp[0] + lowSubband, hF, (64 - lowSubband)*sizeof(*hF)); if (sEnv == nEnv) { frameData->prevEnvIsShort = 0; } else { frameData->prevEnvIsShort = -1; } } /*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ void envelope_application_LC(Int32 *aBufR, Int32 *nrg_gain_man, Int32 *nrg_gain_exp, Int32 *noise_level_man, Int32 *noise_level_exp, Int32 *nrg_tone_man, Int32 *nrg_tone_exp, Int32 band_nrg_tone_detector, const Int32 *frame_info, Int32 *harm_index, Int32 *phase_index, Int32 i, Int32 lowSubband, Int32 noSubbands, Int32 noNoiseFlag) { Int32 *ptrReal; Int32 sb_gain_man; Int32 sb_noise_man; Int32 sb_noise_exp; Int32 l; Int32 k; Int32 tmp_q1; Int32 tmp_q2; Int32 tone_count; Int16 tmp_16; Int32 indexMinus1; Int32 indexPlus1; /* * Application */ if (band_nrg_tone_detector) /* Add tone energy only if energy is detected */ { /* * pre-calculate tone application */ for (k = 0; k < noSubbands; k++) { tmp_q2 = (-nrg_tone_exp[k]); tmp_q1 = nrg_tone_man[k]; tmp_q2 = tmp_q1 >> tmp_q2; tmp_q1 = fxp_mul32_by_16(tmp_q2, Q15fmt(0.0163f)); nrg_tone_man[k] = tmp_q2; nrg_tone_exp[k] = tmp_q1; noise_level_exp[k] += 1; nrg_gain_exp[k] += 28; } for (l = (frame_info[1+i] << 1); l < (frame_info[2+i] << 1); l++) { ptrReal = (aBufR + l * SBR_NUM_BANDS); tone_count = 0; indexPlus1 = (*harm_index + 1) & 3; if (indexPlus1 & 1) /* if indexPlus1 is odd */ { for (k = 0; k < noSubbands; k++) { sb_gain_man = nrg_gain_man[k]; tmp_q1 = *ptrReal; tmp_q2 = nrg_gain_exp[k]; tmp_q1 = fxp_mul32_Q28(tmp_q1, sb_gain_man); if (tmp_q2 < 0) { if (tmp_q2 > -32) { *ptrReal = tmp_q1 >> (-tmp_q2); } } else { *ptrReal = tmp_q1 << tmp_q2; } *phase_index = (*phase_index + 1) & 511; if (!nrg_tone_man[k] && !noNoiseFlag) { tmp_16 = rP_LCx[*phase_index]; sb_noise_man = noise_level_man[k]; sb_noise_exp = noise_level_exp[k]; tmp_q1 = fxp_mul32_by_16(sb_noise_man, tmp_16); if (sb_noise_exp < 0) { if (sb_noise_exp > -32) { *ptrReal += tmp_q1 >> (-sb_noise_exp); } } else { *ptrReal += tmp_q1 << sb_noise_exp; } } tmp_q1 = nrg_tone_man[k]; if (*harm_index) { *ptrReal -= tmp_q1; } else { *ptrReal += tmp_q1; } if (tmp_q1) { tone_count++; } ptrReal++; } /* for-loop (k) */ } else /* if indexPlus1 is even */ { indexMinus1 = (*harm_index - 1) & 3; /* --- k = 0 ----- */ sb_gain_man = nrg_gain_man[0]; tmp_q1 = *ptrReal; tmp_q2 = nrg_gain_exp[0]; tmp_q1 = fxp_mul32_Q28(tmp_q1, sb_gain_man); if (tmp_q2 < 0) { if (tmp_q2 > -32) { *ptrReal = tmp_q1 >> (-tmp_q2); } } else { *ptrReal = tmp_q1 << tmp_q2; } *phase_index = (*phase_index + 1) & 511; tmp_q1 = nrg_tone_exp[0]; tmp_q2 = nrg_tone_exp[1]; if ((indexPlus1 != 0) ^((lowSubband & 1) != 0)) { *(ptrReal - 1) -= tmp_q1; *(ptrReal) += tmp_q2; } else { *(ptrReal - 1) += tmp_q1; *(ptrReal) -= tmp_q2; } if (!nrg_tone_man[0] && !noNoiseFlag) { tmp_16 = rP_LCx[*phase_index]; sb_noise_man = noise_level_man[0]; sb_noise_exp = noise_level_exp[0]; tmp_q1 = fxp_mul32_by_16(sb_noise_man, tmp_16); if (sb_noise_exp < 0) { if (sb_noise_exp > -32) { *ptrReal += tmp_q1 >> (-sb_noise_exp); } } else { *ptrReal += tmp_q1 << sb_noise_exp; } } else { tone_count++; } ptrReal++; /* ---- */ for (k = 1; k < noSubbands - 1; k++) { sb_gain_man = nrg_gain_man[k]; tmp_q1 = *ptrReal; tmp_q2 = nrg_gain_exp[k]; tmp_q1 = fxp_mul32_Q28(tmp_q1, sb_gain_man); if (tmp_q2 < 0) { if (tmp_q2 > -32) { *ptrReal = tmp_q1 >> (-tmp_q2); } } else { *ptrReal = tmp_q1 << tmp_q2; } *phase_index = (*phase_index + 1) & 511; if (tone_count < 16) { tmp_q1 = nrg_tone_exp[k - 1]; tmp_q2 = nrg_tone_exp[k + 1]; tmp_q1 -= tmp_q2; if ((indexPlus1 != 0) ^(((k + lowSubband) & 1) != 0)) { *(ptrReal) -= tmp_q1; } else { *(ptrReal) += tmp_q1; } } /* if (tone_count < 16) */ if (!nrg_tone_man[k] && !noNoiseFlag) { tmp_16 = rP_LCx[*phase_index]; sb_noise_man = noise_level_man[k]; sb_noise_exp = noise_level_exp[k]; tmp_q1 = fxp_mul32_by_16(sb_noise_man, tmp_16); if (sb_noise_exp < 0) { if (sb_noise_exp > -32) { *ptrReal += tmp_q1 >> (-sb_noise_exp); } } else { *ptrReal += tmp_q1 << sb_noise_exp; } } else { tone_count++; } ptrReal++; } /* for-loop (k) */ sb_gain_man = nrg_gain_man[k]; tmp_q1 = *ptrReal; tmp_q2 = nrg_gain_exp[k]; tmp_q1 = fxp_mul32_Q28(tmp_q1, sb_gain_man); if (tmp_q2 < 0) { if (tmp_q2 > -31) { *ptrReal = tmp_q1 >> (-tmp_q2); } } else { *ptrReal = tmp_q1 << tmp_q2; } *phase_index = (*phase_index + 1) & 511; if ((tone_count < 16) && !(indexMinus1 &1)) { tmp_q1 = nrg_tone_exp[k - 1]; tmp_q2 = nrg_tone_exp[k ]; if ((indexMinus1 != 0) ^(((k + lowSubband) & 1) != 0)) { *(ptrReal) += tmp_q1; if (k + lowSubband < 62) { *(ptrReal + 1) -= tmp_q2; } } else { *(ptrReal) -= tmp_q1; if (k + lowSubband < 62) { *(ptrReal + 1) += tmp_q2; } } } /* if (tone_count < 16) */ if (!nrg_tone_man[k] && !noNoiseFlag) { tmp_16 = rP_LCx[*phase_index]; sb_noise_man = noise_level_man[k]; sb_noise_exp = noise_level_exp[k]; tmp_q1 = fxp_mul32_by_16(sb_noise_man, tmp_16); if (sb_noise_exp < 0) { if (sb_noise_exp > -31) { *ptrReal += tmp_q1 >> (-sb_noise_exp); } } else { *ptrReal += tmp_q1 << sb_noise_exp; } } } /* if indexPlus1 is odd */ *harm_index = indexPlus1; } /* for-loop (l) */ } else /* if ( band_nrg_tone_detector) */ { for (k = 0; k < noSubbands; k++) { tmp_q1 = noise_level_exp[k]; tmp_q2 = nrg_gain_exp[k]; noise_level_exp[k] = tmp_q1 + 1; nrg_gain_exp[k] = tmp_q2 + 28; } for (l = (frame_info[1+i] << 1); l < (frame_info[2+i] << 1); l++) { ptrReal = (aBufR + l * SBR_NUM_BANDS); for (k = 0; k < noSubbands; k++) { tmp_q1 = *ptrReal; sb_gain_man = nrg_gain_man[k]; tmp_q2 = nrg_gain_exp[k]; tmp_q1 = fxp_mul32_Q28(tmp_q1, sb_gain_man); if (tmp_q2 < 0) { if (tmp_q2 > -31) { *ptrReal = tmp_q1 >> (-tmp_q2); } } else { *ptrReal = tmp_q1 << tmp_q2; } *phase_index = (*phase_index + 1) & 511; if (! noNoiseFlag) { tmp_16 = rP_LCx[*phase_index]; sb_noise_man = noise_level_man[k]; sb_noise_exp = noise_level_exp[k]; tmp_q1 = fxp_mul32_by_16(sb_noise_man, tmp_16); if (sb_noise_exp < 0) { if (sb_noise_exp > -31) { *ptrReal += tmp_q1 >> (-sb_noise_exp); } } else { *ptrReal += tmp_q1 << sb_noise_exp; } } ptrReal++; } /* for-loop (k) */ *harm_index = (*harm_index + 1) & 3; } /* for-loop (l) */ } } /*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ #define Qfmt15(a) (Int32)(a*((Int32)1<<15) + (a>=0?0.5F:-0.5F)) const Int16 pow2[39] = { 0, 0, 1, 0, 2, 0, Qfmt15(2 / 6.0f), 0, 3, 0, Qfmt15(2 / 10.0f), 0, Qfmt15(2 / 12.0f), 0, Qfmt15(2 / 14.0f), 0, 4, 0, Qfmt15(2 / 18.0f), 0, Qfmt15(2 / 20.0f), 0, Qfmt15(2 / 22.0f), 0, Qfmt15(2 / 24.0f), 0, Qfmt15(2 / 26.0f), 0, Qfmt15(2 / 28.0f), 0, Qfmt15(2 / 30.0f), 0, 5, 0, Qfmt15(2 / 34.0f), 0, Qfmt15(2 / 36.0f), 0, Qfmt15(2 / 38.0f) }; void energy_estimation_LC(Int32 *aBufR, Int32 *nrg_est_man, Int32 *nrg_est_exp, const Int32 *frame_info, Int32 i, Int32 k, Int32 c, Int32 ui2) { Int32 aux1; Int32 aux2; Int32 l; int64_t nrg_h = 0; Int32 tmp1; UInt32 tmp2; for (l = ui2; l < (frame_info[2+i] << 1); l++) { aux1 = aBufR[l++*SBR_NUM_BANDS + k ]; aux2 = aBufR[l *SBR_NUM_BANDS + k ]; nrg_h = fxp_mac64_Q31(nrg_h, aux1, aux1); nrg_h = fxp_mac64_Q31(nrg_h, aux2, aux2); } /* * Check for overflow and saturate if needed */ if (nrg_h < 0) { nrg_h = 0x7fffffff; } if (nrg_h) { tmp2 = (UInt32)(nrg_h >> 32); if (tmp2) { aux2 = pv_normalize(tmp2); aux2 -= 1; /* ensure Q30 */ nrg_h = (nrg_h << aux2) >> 33; tmp2 = (UInt32)(nrg_h); nrg_est_exp[c] = 33 - aux2; } else { tmp2 = (UInt32)(nrg_h >> 2); aux2 = pv_normalize(tmp2); aux2 -= 1; /* ensure Q30 */ tmp2 = (tmp2 << aux2); nrg_est_exp[c] = -aux2 + 2; } tmp1 = (l - ui2); aux2 = pow2[tmp1]; if (tmp1 == (tmp1 & (-tmp1))) { nrg_est_man[c] = tmp2 >> aux2; } else { nrg_est_man[c] = fxp_mul32_by_16(tmp2, aux2); } } else { nrg_est_man[c] = 0; nrg_est_exp[c] = -100; } } #if HQ_SBR /*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ void envelope_application(Int32 *aBufR, Int32 *aBufI, Int32 *nrg_gain_man, Int32 *nrg_gain_exp, Int32 *noise_level_man, Int32 *noise_level_exp, Int32 *nrg_tone_man, Int32 *nrg_tone_exp, Int32 *fBuf_man[64], Int32 *fBuf_exp[64], Int32 *fBufN_man[64], Int32 *fBufN_exp[64], const Int32 *frame_info, Int32 *harm_index, Int32 *phase_index, Int32 i, Int32 lowSubband, Int32 noSubbands, Int32 noNoiseFlag, Int32 band_nrg_tone_detector, Int32 maxSmoothLength, Int32 smooth_length) { Int32 *ptrReal; Int32 *ptrImag; Int32 sb_gain_man; Int32 sb_gain_exp; Int32 sb_noise_man; Int32 sb_noise_exp; Int32 l; Int32 k; Int32 n; Int32 tmp_q1; Int32 tmp_q2; Int32 aux1; Int32 aux2; Int32 filter_history = 0; if (band_nrg_tone_detector) /* Add tone energy only if energy is detected */ { /* * pre-calculate tone application */ ptrReal = nrg_tone_exp; ptrImag = nrg_tone_man; tmp_q1 = - *(ptrReal++); aux1 = *(ptrImag); for (k = 0; k < noSubbands; k++) { *(ptrImag++) = aux1 >> tmp_q1; tmp_q1 = - *(ptrReal++); aux1 = *(ptrImag); } /* * Application */ for (l = (frame_info[1+i] << 1); l < (frame_info[2+i] << 1); l++) { ptrReal = (aBufR + l * SBR_NUM_BANDS); ptrImag = (aBufI + l * SBR_NUM_BANDS); if (filter_history <= maxSmoothLength) /* no more update is needed as buffer will have same info */ { pv_memmove(fBuf_man[maxSmoothLength], nrg_gain_man, noSubbands*sizeof(*nrg_gain_man)); pv_memmove(fBuf_exp[maxSmoothLength], nrg_gain_exp, noSubbands*sizeof(*nrg_gain_exp)); pv_memmove(fBufN_man[maxSmoothLength], noise_level_man, noSubbands*sizeof(*noise_level_man)); pv_memmove(fBufN_exp[maxSmoothLength], noise_level_exp, noSubbands*sizeof(*noise_level_exp)); } /* * nrg_gain_max bounded to 1.584893192*1e5, which requires (32-bit) Q14 notation */ for (k = 0; k < noSubbands; k++) { if (smooth_length == 0) /* no filter-smooth needed */ { sb_gain_man = nrg_gain_man[k]; sb_gain_exp = nrg_gain_exp[k]; sb_noise_man = noise_level_man[k]; sb_noise_exp = noise_level_exp[k]; } else { /* else smooth_length == 4 and fir_4 filter is being used */ sb_gain_exp = fBuf_exp[maxSmoothLength][k]; sb_noise_exp = fBufN_exp[maxSmoothLength][k]; for (n = maxSmoothLength - smooth_length; n < maxSmoothLength; n++) { if (sb_gain_exp < fBuf_exp[n][k]) { sb_gain_exp = fBuf_exp[n][k]; } if (sb_noise_exp < fBufN_exp[n][k]) { sb_noise_exp = fBufN_exp[n][k]; } } sb_gain_man = fxp_mul32_Q30(fBuf_man[maxSmoothLength][k], Q30fmt(0.33333333333333f)); sb_gain_man = sb_gain_man >> (sb_gain_exp - fBuf_exp[maxSmoothLength][k]); sb_noise_man = fxp_mul32_Q30(fBufN_man[maxSmoothLength][k], Q30fmt(0.33333333333333f)); sb_noise_man = sb_noise_man >> (sb_noise_exp - fBufN_exp[maxSmoothLength][k]); n = maxSmoothLength - smooth_length; tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.03183050093751f)); sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]); tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.03183050093751f)); sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n++][k]); tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.11516383427084f)); sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]); tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.11516383427084f)); sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n++][k]); tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.21816949906249f)); sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]); tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.21816949906249f)); sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n++][k]); tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.30150283239582f)); sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]); tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.30150283239582f)); sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n][k]); } /* * *ptrReal = *ptrReal * sb_gain ; * *ptrImag = *ptrImag * sb_gain; */ aux1 = *ptrReal; aux2 = *ptrImag; sb_gain_exp += 32; aux1 = fxp_mul32_Q31(aux1, sb_gain_man); aux2 = fxp_mul32_Q31(aux2, sb_gain_man); if (sb_gain_exp < 0) { sb_gain_exp = -sb_gain_exp; if (sb_gain_exp < 32) { *ptrReal = (aux1 >> sb_gain_exp); *ptrImag = (aux2 >> sb_gain_exp); } } else { *ptrReal = (aux1 << sb_gain_exp); *ptrImag = (aux2 << sb_gain_exp); } /* * if ( sb_noise != 0) * { * *ptrReal += sb_noise * rP[*phase_index][0]; * *ptrImag += sb_noise * rP[*phase_index][1]; * } */ *phase_index = (*phase_index + 1) & 511; if (nrg_tone_man[k] || noNoiseFlag) { sb_noise_man = 0; sb_noise_exp = 0; } else { Int32 tmp = rPxx[*phase_index]; sb_noise_exp += 1; tmp_q1 = fxp_mul32_by_16t(sb_noise_man, tmp); tmp_q2 = fxp_mul32_by_16b(sb_noise_man, tmp); if (sb_noise_exp < 0) { if (sb_noise_exp > -32) { *ptrReal += tmp_q1 >> (-sb_noise_exp); *ptrImag += tmp_q2 >> (-sb_noise_exp); } } else { *ptrReal += tmp_q1 << sb_noise_exp; *ptrImag += tmp_q2 << sb_noise_exp; } } /* * tmp_q1 = nrg_tone[k] */ tmp_q1 = nrg_tone_man[k]; if (*harm_index & 1) { if ((((k + lowSubband) & 1) != 0) ^(*harm_index != 1)) { *ptrImag -= tmp_q1; } else { *ptrImag += tmp_q1; } } else { *ptrReal += (*harm_index) ? -tmp_q1 : tmp_q1; } *ptrReal++ <<= 10; *ptrImag++ <<= 10; } /* for-loop (k) */ *harm_index = (*harm_index + 1) & 3; /* * Update smoothing filter history */ if (filter_history++ < maxSmoothLength) /* no more update is needed as buffer will have same info */ { /* * mantissas */ ptrReal = (Int32 *)fBuf_man[0]; ptrImag = (Int32 *)fBufN_man[0]; for (n = 0; n < maxSmoothLength; n++) { fBuf_man[n] = fBuf_man[n+1]; fBufN_man[n] = fBufN_man[n+1]; } fBuf_man[maxSmoothLength] = ptrReal; fBufN_man[maxSmoothLength] = ptrImag; /* * exponents */ ptrReal = (Int32 *)fBuf_exp[0]; ptrImag = (Int32 *)fBufN_exp[0]; for (n = 0; n < maxSmoothLength; n++) { fBuf_exp[n] = fBuf_exp[n+1]; fBufN_exp[n] = fBufN_exp[n+1]; } fBuf_exp[maxSmoothLength] = ptrReal; fBufN_exp[maxSmoothLength] = ptrImag; } } /* for-loop (l) */ } else /* ---- if ( band_nrg_tone_detector) ---- */ { /* * Application */ for (l = (frame_info[1+i] << 1); l < (frame_info[2+i] << 1); l++) { ptrReal = (aBufR + l * SBR_NUM_BANDS); ptrImag = (aBufI + l * SBR_NUM_BANDS); if (filter_history <= maxSmoothLength) /* no more update is needed as buffer will have same info */ { pv_memmove(fBuf_man[maxSmoothLength], nrg_gain_man, noSubbands*sizeof(*nrg_gain_man)); pv_memmove(fBuf_exp[maxSmoothLength], nrg_gain_exp, noSubbands*sizeof(*nrg_gain_exp)); pv_memmove(fBufN_man[maxSmoothLength], noise_level_man, noSubbands*sizeof(*noise_level_man)); pv_memmove(fBufN_exp[maxSmoothLength], noise_level_exp, noSubbands*sizeof(*noise_level_exp)); } /* * nrg_gain_max bounded to 1.584893192*1e5, which requires (32-bit) Q14 notation */ for (k = 0; k < noSubbands; k++) { if (smooth_length == 0) /* no filter-smooth needed */ { sb_gain_man = nrg_gain_man[k]; sb_gain_exp = nrg_gain_exp[k]; sb_noise_man = noise_level_man[k]; sb_noise_exp = noise_level_exp[k]; } else { /* else smooth_length == 4 and fir_4 filter is being used */ sb_gain_exp = fBuf_exp[maxSmoothLength][k]; sb_noise_exp = fBufN_exp[maxSmoothLength][k]; for (n = maxSmoothLength - smooth_length; n < maxSmoothLength; n++) { if (sb_gain_exp < fBuf_exp[n][k]) { sb_gain_exp = fBuf_exp[n][k]; } if (sb_noise_exp < fBufN_exp[n][k]) { sb_noise_exp = fBufN_exp[n][k]; } } sb_gain_man = fxp_mul32_Q30(fBuf_man[maxSmoothLength][k], Q30fmt(0.33333333333333f)); sb_gain_man = sb_gain_man >> (sb_gain_exp - fBuf_exp[maxSmoothLength][k]); sb_noise_man = fxp_mul32_Q30(fBufN_man[maxSmoothLength][k], Q30fmt(0.33333333333333f)); sb_noise_man = sb_noise_man >> (sb_noise_exp - fBufN_exp[maxSmoothLength][k]); n = maxSmoothLength - smooth_length; tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.03183050093751f)); sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]); tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.03183050093751f)); sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n++][k]); tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.11516383427084f)); sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]); tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.11516383427084f)); sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n++][k]); tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.21816949906249f)); sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]); tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.21816949906249f)); sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n++][k]); tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.30150283239582f)); sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]); tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.30150283239582f)); sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n][k]); } /* * *ptrReal = *ptrReal * sb_gain ; * *ptrImag = *ptrImag * sb_gain; */ aux1 = *ptrReal; aux2 = *ptrImag; sb_gain_exp += 32; aux1 = fxp_mul32_Q31(aux1, sb_gain_man); aux2 = fxp_mul32_Q31(aux2, sb_gain_man); /* * if ( sb_noise != 0) * { * *ptrReal += sb_noise * rP[*phase_index][0]; * *ptrImag += sb_noise * rP[*phase_index][1]; * } */ if (sb_gain_exp < 0) { if (sb_gain_exp > -32) { if (sb_gain_exp > -10) { *ptrReal = aux1 << (10 + sb_gain_exp); *ptrImag = aux2 << (10 + sb_gain_exp); } else { *ptrReal = aux1 >> (-sb_gain_exp - 10); *ptrImag = aux2 >> (-sb_gain_exp - 10); } } } else { *ptrReal = aux1 << (sb_gain_exp + 10); *ptrImag = aux2 << (sb_gain_exp + 10); } /* * if ( sb_noise != 0) * { * *ptrReal += sb_noise * rP[*phase_index][0]; * *ptrImag += sb_noise * rP[*phase_index][1]; * } */ *phase_index = (*phase_index + 1) & 511; if (!noNoiseFlag) { Int32 tmp = rPxx[*phase_index]; sb_noise_exp += 1; tmp_q1 = fxp_mul32_by_16t(sb_noise_man, tmp); tmp_q2 = fxp_mul32_by_16b(sb_noise_man, tmp); if (sb_noise_exp < 0) { if (sb_noise_exp > -32) { if (sb_noise_exp > -10) { *ptrReal += tmp_q1 << (10 + sb_noise_exp); *ptrImag += tmp_q2 << (10 + sb_noise_exp); } else { *ptrReal += tmp_q1 >> (-sb_noise_exp - 10); *ptrImag += tmp_q2 >> (-sb_noise_exp - 10); } } } else { *ptrReal += tmp_q1 << (sb_noise_exp + 10); *ptrImag += tmp_q2 << (sb_noise_exp + 10); } } ptrReal++; ptrImag++; } /* for-loop (k) */ *harm_index = (*harm_index + 1) & 3; /* * Update smoothing filter history */ if (filter_history++ < maxSmoothLength) /* no more update is needed as buffer will have same info */ { /* * mantissas */ ptrReal = (Int32 *)fBuf_man[0]; ptrImag = (Int32 *)fBufN_man[0]; for (n = 0; n < maxSmoothLength; n++) { fBuf_man[n] = fBuf_man[n+1]; fBufN_man[n] = fBufN_man[n+1]; } fBuf_man[maxSmoothLength] = ptrReal; fBufN_man[maxSmoothLength] = ptrImag; /* * exponents */ ptrReal = (Int32 *)fBuf_exp[0]; ptrImag = (Int32 *)fBufN_exp[0]; for (n = 0; n < maxSmoothLength; n++) { fBuf_exp[n] = fBuf_exp[n+1]; fBufN_exp[n] = fBufN_exp[n+1]; } fBuf_exp[maxSmoothLength] = ptrReal; fBufN_exp[maxSmoothLength] = ptrImag; } } /* for-loop (l) */ } /* if ( band_nrg_tone_detector) */ } /*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ void energy_estimation(Int32 *aBufR, Int32 *aBufI, Int32 *nrg_est_man, Int32 *nrg_est_exp, const Int32 *frame_info, Int32 i, Int32 k, Int32 c, Int32 ui2) { Int32 aux1; Int32 aux2; Int32 l; int64_t nrg_h = 0; Int32 tmp1; Int32 tmp2; aux1 = aBufR[ui2*SBR_NUM_BANDS + k]; aux2 = aBufI[ui2*SBR_NUM_BANDS + k]; for (l = ui2 + 1; l < (frame_info[2+i] << 1); l++) { nrg_h = fxp_mac64_Q31(nrg_h, aux1, aux1); nrg_h = fxp_mac64_Q31(nrg_h, aux2, aux2); aux1 = aBufR[l*SBR_NUM_BANDS + k]; aux2 = aBufI[l*SBR_NUM_BANDS + k]; } nrg_h = fxp_mac64_Q31(nrg_h, aux1, aux1); nrg_h = fxp_mac64_Q31(nrg_h, aux2, aux2); /* * Check for overflow and saturate if needed */ if (nrg_h < 0) { nrg_h = 0x7fffffff; } if (nrg_h) { aux1 = (UInt32)(nrg_h >> 32); if (aux1) { aux2 = pv_normalize(aux1); if (aux2) { aux2 -= 1; /* ensure Q30 */ nrg_h = (nrg_h << aux2) >> 33; tmp2 = (UInt32)(nrg_h); nrg_est_exp[c] = 33 - aux2; } else { tmp2 = (UInt32)(aux1 >> 1); nrg_est_exp[c] = 33 ; } } else { aux1 = (UInt32)(nrg_h >> 1); aux2 = pv_normalize(aux1); tmp2 = (aux1 << aux2); nrg_est_exp[c] = -aux2 + 1; } tmp1 = (l - ui2); aux2 = pow2[tmp1]; if (tmp1 == (tmp1 & (-tmp1))) { nrg_est_man[c] = tmp2 >> aux2; } else { nrg_est_man[c] = fxp_mul32_by_16(tmp2, aux2); } } else { nrg_est_man[c] = 0; nrg_est_exp[c] = -100; } } #endif #endif