diff options
author | Andreas Huber <andih@google.com> | 2009-12-07 09:56:32 -0800 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2009-12-07 11:02:28 -0800 |
commit | dacaa73ae5010b66f4224d70a520945e5b653544 (patch) | |
tree | a2c9e71b6337dd25d149bd5fa43f7a782e9387fb /media/libstagefright/codecs/aacdec/sbr_generate_high_freq.cpp | |
parent | 5921fb51e0219ddd7cad439a73495f320c57d50e (diff) | |
download | frameworks_base-dacaa73ae5010b66f4224d70a520945e5b653544.zip frameworks_base-dacaa73ae5010b66f4224d70a520945e5b653544.tar.gz frameworks_base-dacaa73ae5010b66f4224d70a520945e5b653544.tar.bz2 |
Initial check in of stagefright software AAC decoder based on PV source code.
Diffstat (limited to 'media/libstagefright/codecs/aacdec/sbr_generate_high_freq.cpp')
-rw-r--r-- | media/libstagefright/codecs/aacdec/sbr_generate_high_freq.cpp | 1040 |
1 files changed, 1040 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/aacdec/sbr_generate_high_freq.cpp b/media/libstagefright/codecs/aacdec/sbr_generate_high_freq.cpp new file mode 100644 index 0000000..2126e47 --- /dev/null +++ b/media/libstagefright/codecs/aacdec/sbr_generate_high_freq.cpp @@ -0,0 +1,1040 @@ +/* ------------------------------------------------------------------ + * 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: sbr_generate_high_freq.c + +------------------------------------------------------------------------------ + REVISION HISTORY + + + Who: Date: MM/DD/YYYY + Description: + +------------------------------------------------------------------------------ + INPUT AND OUTPUT DEFINITIONS + + + +------------------------------------------------------------------------------ + FUNCTION DESCRIPTION + + HF generator with built-in QMF bank inverse filtering function + +------------------------------------------------------------------------------ + 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 "sbr_generate_high_freq.h" +#include "calc_auto_corr.h" +#include "sbr_inv_filt_levelemphasis.h" +#include "pv_div.h" +#include "fxp_mul32.h" +#include "aac_mem_funcs.h" +#include "sbr_constants.h" + +/*---------------------------------------------------------------------------- +; MACROS +; Define module specific macros here +----------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------- +; DEFINES +; Include all pre-processor statements here. Include conditional +; compile variables also. +----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +; LOCAL FUNCTION DEFINITIONS +; Function Prototype declaration +----------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + + void high_freq_coeff_LC(Int32 sourceBufferReal[][32], + Int32 *alphar[2], + Int32 *degreeAlias, + Int32 *v_k_master, + Int32 *scratch_mem); + + + void high_freq_generation_LC(Int32 sourceBufferReal[][32], + Int32 *targetBufferReal, + Int32 *alphar[2], + Int32 *degreeAlias, + Int32 *invFiltBandTable, + Int32 targetStopBand, + Int32 patchDistance, + Int32 numBandsInPatch, + Int32 startSample, + Int32 slopeLength, + Int32 stopSample, + Int32 *BwVector, + Int32 sbrStartFreqOffset); + + +#ifdef HQ_SBR + + void high_freq_coeff(Int32 sourceBufferReal[][32], + Int32 sourceBufferImag[][32], + Int32 *alphar[2], + Int32 *alphai[2], + Int32 *v_k_master); + + void high_freq_generation(Int32 sourceBufferReal[][32], + Int32 sourceBufferImag[][32], + Int32 *targetBufferReal, + Int32 *targetBufferImag, + Int32 *alphar[2], + Int32 *alphai[2], + Int32 *invFiltBandTable, + Int32 targetStopBand, + Int32 patchDistance, + Int32 numBandsInPatch, + Int32 startSample, + Int32 slopeLength, + Int32 stopSample, + Int32 *BwVector, + Int32 sbrStartFreqOffset); + + +#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 sbr_generate_high_freq(Int32 sourceBufferReal[][32], + Int32 sourceBufferImag[][32], + Int32 *targetBufferReal, + Int32 *targetBufferImag, + INVF_MODE *invFiltMode, + INVF_MODE *prevInvFiltMode, + Int32 *invFiltBandTable, + Int32 noInvFiltBands, + Int32 highBandStartSb, + Int32 *v_k_master, + Int32 numMaster, + Int32 fs, + Int32 *frameInfo, + Int32 *degreeAlias, + Int32 scratch_mem[][64], + Int32 BwVector[MAX_NUM_PATCHES], + Int32 BwVectorOld[MAX_NUM_PATCHES], + struct PATCH *Patch, + Int32 LC_flag, + Int32 *highBandStopSb) +{ + Int32 i; + Int32 patch; + Int32 startSample; + Int32 stopSample; + Int32 goalSb; + Int32 targetStopBand; + Int32 sourceStartBand; + Int32 patchDistance; + Int32 numBandsInPatch; + Int32 sbrStartFreqOffset; + + Int32 *alphar[2]; + Int32 *alphai[2]; + + Int32 lsb = v_k_master[0]; /* Lowest subband related to the synthesis filterbank */ + Int32 usb = v_k_master[numMaster]; /* Stop subband related to the synthesis filterbank */ + Int32 xoverOffset = highBandStartSb - v_k_master[0]; /* Calculate distance in subbands between k0 and kx */ + + + + Int slopeLength = 0; + + Int32 firstSlotOffs = frameInfo[1]; + Int32 lastSlotOffs = frameInfo[frameInfo[0] + 1] - 16; + + + alphar[0] = scratch_mem[0]; + alphar[1] = scratch_mem[1]; + alphai[0] = scratch_mem[2]; + alphai[1] = scratch_mem[3]; + + + startSample = (firstSlotOffs << 1); + stopSample = (lastSlotOffs << 1) + 32; + + + sbr_inv_filt_levelemphasis(invFiltMode, + prevInvFiltMode, + noInvFiltBands, + BwVector, + BwVectorOld); + + + if (LC_flag == ON) + { + /* Set subbands to zero */ + + pv_memset((void *)&targetBufferReal[startSample*SBR_NUM_BANDS], + 0, + (stopSample - startSample)*SBR_NUM_BANDS*sizeof(targetBufferReal[0])); + + high_freq_coeff_LC(sourceBufferReal, + alphar, + degreeAlias, + v_k_master, + scratch_mem[4]); + } +#ifdef HQ_SBR + else + { + /* Set subbands to zero */ + + pv_memset((void *)&targetBufferReal[startSample*SBR_NUM_BANDS], + 0, + (stopSample - startSample)*SBR_NUM_BANDS*sizeof(targetBufferReal[0])); + pv_memset((void *)&targetBufferImag[startSample*SBR_NUM_BANDS], + 0, + (stopSample - startSample)*SBR_NUM_BANDS*sizeof(targetBufferImag[0])); + + high_freq_coeff(sourceBufferReal, + sourceBufferImag, + alphar, + alphai, + v_k_master); + + } +#endif /* #ifdef HQ_SBR */ + + + + + /* + * Initialize the patching parameter + */ + switch (fs) + + { + /* + * goalSb = (int)( 2.048e6f / fs + 0.5f ); + */ + case 48000: + goalSb = 43; /* 16 kHz band */ + break; + case 32000: + goalSb = 64; /* 16 kHz band */ + break; + case 24000: + goalSb = 85; /* 16 kHz band */ + break; + case 22050: + goalSb = 93; /* 16 kHz band */ + break; + case 16000: + goalSb = 128; /* 16 kHz band */ + break; + case 44100: + default: + goalSb = 46; /* 16 kHz band */ + break; + } + + i = 0; + + if (goalSb > v_k_master[0]) + { + if (goalSb < v_k_master[numMaster]) + { + while (v_k_master[i] < goalSb) + { + i++; + } + } + else + { + i = numMaster; + } + } + + goalSb = v_k_master[i]; + + /* First patch */ + sourceStartBand = xoverOffset + 1; + targetStopBand = lsb + xoverOffset; + + /* even (odd) numbered channel must be patched to even (odd) numbered channel */ + patch = 0; + + + sbrStartFreqOffset = targetStopBand; + + while (targetStopBand < usb) + { + Patch->targetStartBand[patch] = targetStopBand; + + numBandsInPatch = goalSb - targetStopBand; /* get the desired range of the patch */ + + if (numBandsInPatch >= lsb - sourceStartBand) + { + /* desired number bands are not available -> patch whole source range */ + patchDistance = targetStopBand - sourceStartBand; /* get the targetOffset */ + patchDistance = patchDistance & ~1; /* rounding off odd numbers and make all even */ + numBandsInPatch = lsb - (targetStopBand - patchDistance); + + if (targetStopBand + numBandsInPatch > v_k_master[0]) + { + i = numMaster; + if (targetStopBand + numBandsInPatch < v_k_master[numMaster]) + { + while (v_k_master[i] > targetStopBand + numBandsInPatch) + { + i--; + } + } + } + else + { + i = 0; + } + numBandsInPatch = v_k_master[i] - targetStopBand; + } + + /* desired number bands are available -> get the minimal even patching distance */ + patchDistance = numBandsInPatch + targetStopBand - lsb; /* get minimal distance */ + patchDistance = (patchDistance + 1) & ~1; /* rounding up odd numbers and make all even */ + + /* All patches but first */ + sourceStartBand = 1; + + /* Check if we are close to goalSb */ + if (goalSb - (targetStopBand + numBandsInPatch) < 3) + { /* MPEG doc */ + goalSb = usb; + } + + + if ((numBandsInPatch < 3) && (patch > 0)) + { + if (LC_flag == ON) + { + + pv_memset((void *) °reeAlias[targetStopBand], 0, numBandsInPatch*sizeof(*degreeAlias)); + } + break; + } + + if (numBandsInPatch <= 0) + { + continue; + } + + + /* + * High Frequency generation + */ + + if (LC_flag == ON) + { + + high_freq_generation_LC(sourceBufferReal, + (Int32 *)targetBufferReal, + alphar, + degreeAlias, + invFiltBandTable, + targetStopBand, + patchDistance, + numBandsInPatch, + startSample, + slopeLength, + stopSample, + BwVector, + sbrStartFreqOffset); + + } +#ifdef HQ_SBR + else + { + + high_freq_generation(sourceBufferReal, + sourceBufferImag, + (Int32 *)targetBufferReal, + (Int32 *)targetBufferImag, + alphar, + alphai, + invFiltBandTable, + targetStopBand, + patchDistance, + numBandsInPatch, + startSample, + slopeLength, + stopSample, + BwVector, + sbrStartFreqOffset); + + } +#endif + + targetStopBand += numBandsInPatch; + + patch++; + + } /* targetStopBand */ + + Patch->noOfPatches = patch; + + pv_memmove(BwVectorOld, BwVector, noInvFiltBands*sizeof(BwVector[0])); + + *highBandStopSb = goalSb; + + +} + + +/*---------------------------------------------------------------------------- +; FUNCTION CODE +----------------------------------------------------------------------------*/ + + +void high_freq_coeff_LC(Int32 sourceBufferReal[][32], + Int32 *alphar[2], + Int32 *degreeAlias, + Int32 *v_k_master, + Int32 *scratch_mem) +{ + + Int32 fac; + Int32 *k1; + struct ACORR_COEFS ac; + struct intg_div quotient; + + Int32 temp1; + Int32 temp2; + Int32 temp3; + Int32 autoCorrLength; + Int32 loBand; + + k1 = scratch_mem; + + + autoCorrLength = 38; + + for (loBand = 1; loBand < v_k_master[0]; loBand++) + { + + calc_auto_corr_LC(&ac, + sourceBufferReal, + loBand, + autoCorrLength); + + if (ac.r11r && ac.det) + { + + pv_div(ac.r01r, ac.r11r, "ient); + + fac = -(quotient.quotient >> 2); /* Q28 */ + + if (quotient.shift_factor > 0) + { + fac >>= quotient.shift_factor; /* Q28 */ + } + else if (quotient.shift_factor < 0) + { + if (quotient.shift_factor > -4) /* |fac| < 8 */ + { + fac <<= (-quotient.shift_factor); /* Q28 */ + } + else + { + fac = 0x80000000; /* overshoot possible fac = -8 */ + } + } + + /* + * prevent for overflow of reflection coefficients + */ + if (quotient.shift_factor > 0) + { + k1[loBand] = - quotient.quotient >> quotient.shift_factor; + } + else if (quotient.shift_factor == 0) + { + if (quotient.quotient >= 0x40000000) + { + k1[loBand] = (Int32)0xC0000000; /* -1.0 in Q30 */ + } + else if (quotient.quotient <= (Int32)0xC0000000) + { + k1[loBand] = 0x40000000; /* 1.0 in Q30 */ + } + else + { + k1[loBand] = -quotient.quotient; + } + } + else + { + if (quotient.quotient > 0) + { + k1[loBand] = (Int32)0xC0000000; /* -1.0 in Q30 */ + } + else + { + k1[loBand] = 0x40000000; /* 1.0 in Q30 */ + } + } + /* + * alphar[1][loBand] = ( ac.r01r * ac.r12r - ac.r02r * ac.r11r ) / ac.det; + */ + + temp1 = -fxp_mul32_Q30(ac.r02r, ac.r11r); + temp1 = fxp_mac32_Q30(ac.r01r, ac.r12r, temp1); + + temp2 = ac.det; + temp3 = temp1 > 0 ? temp1 : -temp1; + temp2 = temp2 > 0 ? temp2 : -temp2; + + /* prevent for shootovers */ + if ((temp3 >> 2) >= temp2 || fac == (Int32)0x80000000) + { + alphar[0][loBand] = 0; + alphar[1][loBand] = 0; + } + else + { + pv_div(temp1, ac.det, "ient); + /* + * alphar[1][loBand] is lesser than 4.0 + */ + alphar[1][loBand] = quotient.quotient; + quotient.shift_factor += 2; /* Q28 */ + + if (quotient.shift_factor > 0) + { + alphar[1][loBand] >>= quotient.shift_factor; /* Q28 */ + } + else if (quotient.shift_factor < 0) /* at this point can only be -1 */ + { + alphar[1][loBand] <<= (-quotient.shift_factor); /* Q28 */ + } + + /* + * alphar[0][loBand] = - ( ac.r01r + alphar[1][loBand] * ac.r12r ) / ac.r11r; + */ + + pv_div(ac.r12r, ac.r11r, "ient); + + temp3 = (quotient.quotient >> 2); /* Q28 */ + + if (quotient.shift_factor > 0) + { + temp3 >>= quotient.shift_factor; /* Q28 */ + } + else if (quotient.shift_factor < 0) + { + temp3 <<= (-quotient.shift_factor); /* Q28 */ + } + + alphar[0][loBand] = fac - fxp_mul32_Q28(alphar[1][loBand], temp3) ; /* Q28 */ + + if ((alphar[0][loBand] >= 0x40000000) || (alphar[0][loBand] <= (Int32)0xC0000000)) + { + alphar[0][loBand] = 0; + alphar[1][loBand] = 0; + } + + } + + } + else + { + alphar[0][loBand] = 0; + alphar[1][loBand] = 0; + + k1[loBand] = 0; + } + + } + + k1[0] = 0; + degreeAlias[1] = 0; + for (loBand = 2; loBand < v_k_master[0]; loBand++) + { + degreeAlias[loBand] = 0; + if ((!(loBand & 1)) && (k1[loBand] < 0)) + { + if (k1[loBand-1] < 0) + { // 2-CH Aliasing Detection + degreeAlias[loBand] = 0x40000000; + if (k1[loBand-2] > 0) + { // 3-CH Aliasing Detection + degreeAlias[loBand-1] = 0x40000000 - fxp_mul32_Q30(k1[loBand-1], k1[loBand-1]); + + } + } + else if (k1[loBand-2] > 0) + { // 3-CH Aliasing Detection + degreeAlias[loBand] = 0x40000000 - fxp_mul32_Q30(k1[loBand-1], k1[loBand-1]); + } + } + if ((loBand & 1) && (k1[loBand] > 0)) + { + if (k1[loBand-1] > 0) + { // 2-CH Aliasing Detection + degreeAlias[loBand] = 0x40000000; + if (k1[loBand-2] < 0) + { // 3-CH Aliasing Detection + degreeAlias[loBand-1] = 0x40000000 - fxp_mul32_Q30(k1[loBand-1], k1[loBand-1]); + } + } + else if (k1[loBand-2] < 0) + { // 3-CH Aliasing Detection + degreeAlias[loBand] = 0x40000000 - fxp_mul32_Q30(k1[loBand-1], k1[loBand-1]); + } + } + } + +} + + +/*---------------------------------------------------------------------------- +; FUNCTION CODE +----------------------------------------------------------------------------*/ + +void high_freq_generation_LC(Int32 sourceBufferReal[][32], + Int32 *targetBufferReal, + Int32 *alphar[2], + Int32 *degreeAlias, + Int32 *invFiltBandTable, + Int32 targetStopBand, + Int32 patchDistance, + Int32 numBandsInPatch, + Int32 startSample, + Int32 slopeLength, + Int32 stopSample, + Int32 *BwVector, + Int32 sbrStartFreqOffset) +{ + + Int32 temp1; + Int32 temp2; + Int32 temp3; + + + Int32 a0r; + Int32 a1r; + Int32 i; + Int32 bw; + Int32 hiBand; + Int32 bwIndex; + Int32 loBand; + Int32 j; + + bwIndex = 0; + + for (hiBand = targetStopBand; hiBand < targetStopBand + numBandsInPatch; hiBand++) + { + loBand = hiBand - patchDistance; + + if (hiBand != targetStopBand) + { + degreeAlias[hiBand] = degreeAlias[loBand]; + } + else + { + degreeAlias[hiBand] = 0; + } + + while (hiBand >= invFiltBandTable[bwIndex]) + { + bwIndex++; + } + + bw = BwVector[bwIndex]; + + /* + * Inverse Filtering + */ + + + j = hiBand - sbrStartFreqOffset; + + if (bw > 0 && (alphar[0][loBand] | alphar[1][loBand])) + { + /* Apply current bandwidth expansion factor */ + a0r = fxp_mul32_Q29(bw, alphar[0][loBand]); + + bw = fxp_mul32_Q31(bw, bw) << 2; + + a1r = fxp_mul32_Q28(bw, alphar[1][loBand]); + + i = startSample + slopeLength; + + temp1 = sourceBufferReal[i ][loBand]; + temp2 = sourceBufferReal[i - 1][loBand]; + temp3 = sourceBufferReal[i - 2][loBand]; + + for (; i < stopSample + slopeLength - 1; i++) + { + + + targetBufferReal[i*SBR_NUM_BANDS + j] = temp1 + fxp_mul32_Q28(a0r, temp2) + + fxp_mul32_Q28(a1r, temp3); + + + temp3 = temp2; + temp2 = temp1; + temp1 = sourceBufferReal[i + 1][loBand]; + } + targetBufferReal[i*SBR_NUM_BANDS + j] = temp1 + fxp_mul32_Q28(a0r, temp2) + + fxp_mul32_Q28(a1r, temp3); + + } + else + { + + for (i = startSample + slopeLength; i < stopSample + slopeLength; i++) + { + targetBufferReal[i*SBR_NUM_BANDS + j] = sourceBufferReal[i][loBand]; + } + } + + + } /* hiBand */ + +} + + +#ifdef HQ_SBR + +/*---------------------------------------------------------------------------- +; FUNCTION CODE +----------------------------------------------------------------------------*/ + +void high_freq_coeff(Int32 sourceBufferReal[][32], + Int32 sourceBufferImag[][32], + Int32 *alphar[2], + Int32 *alphai[2], + Int32 *v_k_master) +{ + + Int32 overflow_flag; + + Int32 temp1r; + Int32 temp1i; + Int32 temp0r; + Int32 temp0i; + Int32 loBand; + + struct ACORR_COEFS ac; + struct intg_div quotient; + + Int32 autoCorrLength; + + autoCorrLength = 38; + + for (loBand = 1; loBand < v_k_master[0]; loBand++) + { + + calc_auto_corr(&ac, + sourceBufferReal, + sourceBufferImag, + loBand, + autoCorrLength); + + + overflow_flag = 0; + + if (ac.det < 1) + { + /* --- */ + temp1r = 0; + temp1i = 0; + alphar[1][loBand] = 0; + alphai[1][loBand] = 0; + + } + else + { + + temp1r = fxp_mul32_Q29(ac.r01r, ac.r12r); + temp1r = fxp_msu32_Q29(ac.r01i, ac.r12i, temp1r); + temp1r = fxp_msu32_Q29(ac.r02r, ac.r11r, temp1r); + + temp1i = fxp_mul32_Q29(ac.r01r, ac.r12i); + temp1i = fxp_msu32_Q29(ac.r02i, ac.r11r, temp1i); + temp1i = fxp_mac32_Q29(ac.r01i, ac.r12r, temp1i); + + pv_div(temp1r, ac.det, "ient); + overflow_flag = (quotient.shift_factor < -2) ? 1 : 0; + temp1r = quotient.quotient >> (2 + quotient.shift_factor); /* Q28 */ + pv_div(temp1i, ac.det, "ient); + overflow_flag = (quotient.shift_factor < -2) ? 1 : 0; + temp1i = quotient.quotient >> (2 + quotient.shift_factor); /* Q28 */ + + alphar[1][loBand] = temp1r; + alphai[1][loBand] = temp1i; + + } + + if (ac.r11r == 0) + { + temp0r = 0; + temp0i = 0; + alphar[0][loBand] = 0; + alphai[0][loBand] = 0; + + } + else + { + temp0r = - (ac.r01r + fxp_mul32_Q28(temp1r, ac.r12r) + fxp_mul32_Q28(temp1i, ac.r12i)); + temp0i = - (ac.r01i + fxp_mul32_Q28(temp1i, ac.r12r) - fxp_mul32_Q28(temp1r, ac.r12i)); + + pv_div(temp0r, ac.r11r, "ient); + overflow_flag = (quotient.shift_factor < -2) ? 1 : 0; + temp0r = quotient.quotient >> (2 + quotient.shift_factor); /* Q28 */ + pv_div(temp0i, ac.r11r, "ient); + overflow_flag = (quotient.shift_factor < -2) ? 1 : 0; + temp0i = quotient.quotient >> (2 + quotient.shift_factor); /* Q28 */ + + alphar[0][loBand] = temp0r; + alphai[0][loBand] = temp0i; + + } + + /* prevent for shootovers */ + + if (fxp_mul32_Q28((temp0r >> 2), (temp0r >> 2)) + fxp_mul32_Q28((temp0i >> 2), (temp0i >> 2)) >= 0x10000000 || + fxp_mul32_Q28((temp1r >> 2), (temp1r >> 2)) + fxp_mul32_Q28((temp1i >> 2), (temp1i >> 2)) >= 0x10000000 || + overflow_flag) /* 0x10000000 == 1 in Q28 */ + + { + alphar[0][loBand] = 0; + alphar[1][loBand] = 0; + alphai[0][loBand] = 0; + alphai[1][loBand] = 0; + + } + } +} + +/*---------------------------------------------------------------------------- +; FUNCTION CODE +----------------------------------------------------------------------------*/ + + + +void high_freq_generation(Int32 sourceBufferReal[][32], + Int32 sourceBufferImag[][32], + Int32 *targetBufferReal, + Int32 *targetBufferImag, + Int32 *alphar[2], + Int32 *alphai[2], + Int32 *invFiltBandTable, + Int32 targetStopBand, + Int32 patchDistance, + Int32 numBandsInPatch, + Int32 startSample, + Int32 slopeLength, + Int32 stopSample, + Int32 *BwVector, + Int32 sbrStartFreqOffset) +{ + Int32 temp1_r; + Int32 temp2_r; + Int32 temp3_r; + Int32 temp1_i; + Int32 temp2_i; + Int32 temp3_i; + + + Int32 a0i; + Int32 a1i; + Int32 a0r; + Int32 a1r; + Int32 i; + Int32 bw; + Int32 hiBand; + Int32 bwIndex; + Int32 loBand; + Int32 j; + + + + int64_t tmp; + + bwIndex = 0; + + for (hiBand = targetStopBand; hiBand < targetStopBand + numBandsInPatch; hiBand++) + { + + loBand = hiBand - patchDistance; + + while (hiBand >= invFiltBandTable[bwIndex]) + { + bwIndex++; + } + + bw = BwVector[bwIndex]; + + /* + * Inverse Filtering + */ + + + j = hiBand - sbrStartFreqOffset; + + if (bw >= 0 && (alphar[0][loBand] | alphar[1][loBand] | + alphai[0][loBand] | alphai[1][loBand])) + { + /* Apply current bandwidth expansion factor */ + a0r = fxp_mul32_Q29(bw, alphar[0][loBand]); + a0i = fxp_mul32_Q29(bw, alphai[0][loBand]); + + + bw = fxp_mul32_Q30(bw, bw); + + + a1r = fxp_mul32_Q28(bw, alphar[1][loBand]); + a1i = fxp_mul32_Q28(bw, alphai[1][loBand]); + + + i = startSample + slopeLength; + j += i * SBR_NUM_BANDS; + + temp1_r = sourceBufferReal[i ][loBand]; + temp2_r = sourceBufferReal[i - 1][loBand]; + temp3_r = sourceBufferReal[i - 2][loBand]; + + temp1_i = sourceBufferImag[i ][loBand]; + temp2_i = sourceBufferImag[i - 1][loBand]; + temp3_i = sourceBufferImag[i - 2][loBand]; + + while (i < stopSample + slopeLength) + { + tmp = fxp_mac64_Q31(((int64_t)temp1_r << 28), a0r, temp2_r); + tmp = fxp_mac64_Q31(tmp, -a0i, temp2_i); + tmp = fxp_mac64_Q31(tmp, a1r, temp3_r); + targetBufferReal[j] = (Int32)(fxp_mac64_Q31(tmp, -a1i, temp3_i) >> 28); + + tmp = fxp_mac64_Q31(((int64_t)temp1_i << 28), a0i, temp2_r); + tmp = fxp_mac64_Q31(tmp, a0r, temp2_i); + tmp = fxp_mac64_Q31(tmp, a1i, temp3_r); + targetBufferImag[j] = (Int32)(fxp_mac64_Q31(tmp, a1r, temp3_i) >> 28); + + i++; + j += SBR_NUM_BANDS; + + temp3_r = temp2_r; + temp2_r = temp1_r; + temp1_r = sourceBufferReal[i ][loBand]; + + temp3_i = temp2_i; + temp2_i = temp1_i; + temp1_i = sourceBufferImag[i ][loBand]; + + } + + } + + + + else + { + i = startSample + slopeLength; + j += i * SBR_NUM_BANDS; + + for (; i < stopSample + slopeLength; i++) + { + targetBufferReal[j] = sourceBufferReal[i][loBand]; + targetBufferImag[j] = sourceBufferImag[i][loBand]; + j += SBR_NUM_BANDS; + } + } + } +} + +#endif + + +#endif |