/* ------------------------------------------------------------------ * 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