diff options
Diffstat (limited to 'libAACenc/src/block_switch.cpp')
-rw-r--r-- | libAACenc/src/block_switch.cpp | 765 |
1 files changed, 401 insertions, 364 deletions
diff --git a/libAACenc/src/block_switch.cpp b/libAACenc/src/block_switch.cpp index 7b3e275..c132253 100644 --- a/libAACenc/src/block_switch.cpp +++ b/libAACenc/src/block_switch.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. 1. INTRODUCTION -The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements -the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. -This FDK AAC Codec software is intended to be used on a wide variety of Android devices. - -AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual -audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by -independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part -of the MPEG specifications. - -Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) -may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners -individually for the purpose of encoding or decoding bit streams in products that are compliant with -the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license -these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec -software may already be covered under those patent licenses when it is used for those licensed purposes only. - -Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, -are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional -applications information and documentation. +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. 2. COPYRIGHT LICENSE -Redistribution and use in source and binary forms, with or without modification, are permitted without -payment of copyright license fees provided that you satisfy the following conditions: +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: -You must retain the complete text of this software license in redistributions of the FDK AAC Codec or -your modifications thereto in source code form. +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. -You must retain the complete text of this software license in the documentation and/or other materials -provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. -You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your modifications thereto to recipients of copies in binary form. -The name of Fraunhofer may not be used to endorse or promote products derived from this library without -prior written permission. +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. -You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec -software or your modifications thereto. +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. -Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software -and the date of any change. For modified versions of the FDK AAC Codec, the term -"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term -"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." 3. NO PATENT LICENSE -NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, -ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with -respect to this software. +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. -You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized -by appropriate patent licenses. +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. 4. DISCLAIMER -This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors -"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties -of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, -including but not limited to procurement of substitute goods or services; loss of use, data, or profits, -or business interruption, however caused and on any theory of liability, whether in contract, strict -liability, or tort (including negligence), arising in any way out of the use of this software, even if -advised of the possibility of such damage. +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. 5. CONTACT INFORMATION @@ -79,460 +90,488 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/***************************** MPEG-4 AAC Encoder ************************** +/**************************** AAC encoder library ****************************** Author(s): M. Werner, Tobias Chalupka + Description: Block switching -******************************************************************************/ +*******************************************************************************/ /****************** Includes *****************************/ #include "block_switch.h" #include "genericStds.h" - #define LOWOV_WINDOW _LOWOV_WINDOW /**************** internal function prototypes ***********/ -static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], const INT blSwWndIdx); +static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], + const INT blSwWndIdx); static void FDKaacEnc_CalcWindowEnergy( - BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, - INT windowLen, - const INT_PCM *pTimeSignal - ); + BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, INT windowLen, + const INT_PCM *pTimeSignal); /****************** Constants *****************************/ -/* LONG START SHORT STOP LOWOV */ -static const INT blockType2windowShape[2][5] = { {SINE_WINDOW, KBD_WINDOW, WRONG_WINDOW, SINE_WINDOW, KBD_WINDOW}, /* LD */ - {KBD_WINDOW, SINE_WINDOW, SINE_WINDOW, KBD_WINDOW, WRONG_WINDOW} }; /* LC */ +/* LONG START + * SHORT STOP LOWOV */ +static const INT blockType2windowShape[2][5] = { + {SINE_WINDOW, KBD_WINDOW, WRONG_WINDOW, SINE_WINDOW, KBD_WINDOW}, /* LD */ + {KBD_WINDOW, SINE_WINDOW, SINE_WINDOW, KBD_WINDOW, WRONG_WINDOW}}; /* LC */ /* IIR high pass coeffs */ #ifndef SINETABLE_16BIT -static const FIXP_DBL hiPassCoeff[BLOCK_SWITCHING_IIR_LEN]= -{ - FL2FXCONST_DBL(-0.5095),FL2FXCONST_DBL(0.7548) -}; +static const FIXP_DBL hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = { + FL2FXCONST_DBL(-0.5095), FL2FXCONST_DBL(0.7548)}; -static const FIXP_DBL accWindowNrgFac = FL2FXCONST_DBL(0.3f); /* factor for accumulating filtered window energies */ +static const FIXP_DBL accWindowNrgFac = + FL2FXCONST_DBL(0.3f); /* factor for accumulating filtered window energies */ static const FIXP_DBL oneMinusAccWindowNrgFac = FL2FXCONST_DBL(0.7f); -/* static const float attackRatio = 10.0; */ /* lower ratio limit for attacks */ -static const FIXP_DBL invAttackRatio = FL2FXCONST_DBL(0.1f); /* inverted lower ratio limit for attacks */ +/* static const float attackRatio = 10.0; */ /* lower ratio limit for attacks */ +static const FIXP_DBL invAttackRatio = + FL2FXCONST_DBL(0.1f); /* inverted lower ratio limit for attacks */ -/* The next constants are scaled, because they are used for comparison with scaled values*/ +/* The next constants are scaled, because they are used for comparison with + * scaled values*/ /* minimum energy for attacks */ -static const FIXP_DBL minAttackNrg = (FL2FXCONST_DBL(1e+6f*NORM_PCM_ENERGY)>>BLOCK_SWITCH_ENERGY_SHIFT); /* minimum energy for attacks */ +static const FIXP_DBL minAttackNrg = + (FL2FXCONST_DBL(1e+6f * NORM_PCM_ENERGY) >> + BLOCK_SWITCH_ENERGY_SHIFT); /* minimum energy for attacks */ #else -static const FIXP_SGL hiPassCoeff[BLOCK_SWITCHING_IIR_LEN]= -{ - FL2FXCONST_SGL(-0.5095),FL2FXCONST_SGL(0.7548) -}; +static const FIXP_SGL hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = { + FL2FXCONST_SGL(-0.5095), FL2FXCONST_SGL(0.7548)}; -static const FIXP_DBL accWindowNrgFac = FL2FXCONST_DBL(0.3f); /* factor for accumulating filtered window energies */ +static const FIXP_DBL accWindowNrgFac = + FL2FXCONST_DBL(0.3f); /* factor for accumulating filtered window energies */ static const FIXP_SGL oneMinusAccWindowNrgFac = FL2FXCONST_SGL(0.7f); -/* static const float attackRatio = 10.0; */ /* lower ratio limit for attacks */ -static const FIXP_SGL invAttackRatio = FL2FXCONST_SGL(0.1f); /* inverted lower ratio limit for attacks */ +/* static const float attackRatio = 10.0; */ /* lower ratio limit for attacks */ +static const FIXP_SGL invAttackRatio = + FL2FXCONST_SGL(0.1f); /* inverted lower ratio limit for attacks */ /* minimum energy for attacks */ -static const FIXP_DBL minAttackNrg = (FL2FXCONST_DBL(1e+6f*NORM_PCM_ENERGY)>>BLOCK_SWITCH_ENERGY_SHIFT); /* minimum energy for attacks */ +static const FIXP_DBL minAttackNrg = + (FL2FXCONST_DBL(1e+6f * NORM_PCM_ENERGY) >> + BLOCK_SWITCH_ENERGY_SHIFT); /* minimum energy for attacks */ #endif /**************** internal function prototypes ***********/ /****************** Routines ****************************/ -void FDKaacEnc_InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay) -{ - FDKmemclear (blockSwitchingControl, sizeof(BLOCK_SWITCHING_CONTROL)); +void FDKaacEnc_InitBlockSwitching( + BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay) { + FDKmemclear(blockSwitchingControl, sizeof(BLOCK_SWITCHING_CONTROL)); - if (isLowDelay) - { + if (isLowDelay) { blockSwitchingControl->nBlockSwitchWindows = 4; - blockSwitchingControl->allowShortFrames = 0; - blockSwitchingControl->allowLookAhead = 0; - } - else - { + blockSwitchingControl->allowShortFrames = 0; + blockSwitchingControl->allowLookAhead = 0; + } else { blockSwitchingControl->nBlockSwitchWindows = 8; - blockSwitchingControl->allowShortFrames = 1; - blockSwitchingControl->allowLookAhead = 1; + blockSwitchingControl->allowShortFrames = 1; + blockSwitchingControl->allowLookAhead = 1; } - blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS; + blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS; /* Initialize startvalue for blocktype */ - blockSwitchingControl->lastWindowSequence = LONG_WINDOW; - blockSwitchingControl->windowShape = blockType2windowShape[blockSwitchingControl->allowShortFrames][blockSwitchingControl->lastWindowSequence]; - + blockSwitchingControl->lastWindowSequence = LONG_WINDOW; + blockSwitchingControl->windowShape = + blockType2windowShape[blockSwitchingControl->allowShortFrames] + [blockSwitchingControl->lastWindowSequence]; } -static const INT suggestedGroupingTable[TRANS_FAC][MAX_NO_OF_GROUPS] = -{ - /* Attack in Window 0 */ {1, 3, 3, 1}, - /* Attack in Window 1 */ {1, 1, 3, 3}, - /* Attack in Window 2 */ {2, 1, 3, 2}, - /* Attack in Window 3 */ {3, 1, 3, 1}, - /* Attack in Window 4 */ {3, 1, 1, 3}, - /* Attack in Window 5 */ {3, 2, 1, 2}, - /* Attack in Window 6 */ {3, 3, 1, 1}, - /* Attack in Window 7 */ {3, 3, 1, 1} -}; - -/* change block type depending on current blocktype and whether there's an attack */ +static const INT suggestedGroupingTable[TRANS_FAC][MAX_NO_OF_GROUPS] = { + /* Attack in Window 0 */ {1, 3, 3, 1}, + /* Attack in Window 1 */ {1, 1, 3, 3}, + /* Attack in Window 2 */ {2, 1, 3, 2}, + /* Attack in Window 3 */ {3, 1, 3, 1}, + /* Attack in Window 4 */ {3, 1, 1, 3}, + /* Attack in Window 5 */ {3, 2, 1, 2}, + /* Attack in Window 6 */ {3, 3, 1, 1}, + /* Attack in Window 7 */ {3, 3, 1, 1}}; + +/* change block type depending on current blocktype and whether there's an + * attack */ /* assume no look-ahead */ -static const INT chgWndSq[2][N_BLOCKTYPES] = -{ - /* LONG WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW, LOWOV_WINDOW, WRONG_WINDOW */ - /*no attack*/ {LONG_WINDOW, STOP_WINDOW, WRONG_WINDOW, LONG_WINDOW, STOP_WINDOW , WRONG_WINDOW }, - /*attack */ {START_WINDOW, LOWOV_WINDOW, WRONG_WINDOW, START_WINDOW, LOWOV_WINDOW, WRONG_WINDOW } -}; - -/* change block type depending on current blocktype and whether there's an attack */ +static const INT chgWndSq[2][N_BLOCKTYPES] = { + /* LONG WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW, + LOWOV_WINDOW, WRONG_WINDOW */ + /*no attack*/ {LONG_WINDOW, STOP_WINDOW, WRONG_WINDOW, LONG_WINDOW, + STOP_WINDOW, WRONG_WINDOW}, + /*attack */ {START_WINDOW, LOWOV_WINDOW, WRONG_WINDOW, START_WINDOW, + LOWOV_WINDOW, WRONG_WINDOW}}; + +/* change block type depending on current blocktype and whether there's an + * attack */ /* assume look-ahead */ -static const INT chgWndSqLkAhd[2][2][N_BLOCKTYPES] = -{ - /*attack LONG WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW LOWOV_WINDOW, WRONG_WINDOW */ /* last attack */ - /*no attack*/ { {LONG_WINDOW, SHORT_WINDOW, STOP_WINDOW, LONG_WINDOW, WRONG_WINDOW, WRONG_WINDOW}, /* no attack */ - /*attack */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, START_WINDOW, WRONG_WINDOW, WRONG_WINDOW} }, /* no attack */ - /*no attack*/ { {LONG_WINDOW, SHORT_WINDOW, SHORT_WINDOW, LONG_WINDOW, WRONG_WINDOW, WRONG_WINDOW}, /* attack */ - /*attack */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, START_WINDOW, WRONG_WINDOW, WRONG_WINDOW} } /* attack */ +static const INT chgWndSqLkAhd[2][2][N_BLOCKTYPES] = { + /*attack LONG WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW LOWOV_WINDOW, WRONG_WINDOW */ /* last attack */ + /*no attack*/ { + {LONG_WINDOW, SHORT_WINDOW, STOP_WINDOW, LONG_WINDOW, WRONG_WINDOW, + WRONG_WINDOW}, /* no attack */ + /*attack */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, START_WINDOW, + WRONG_WINDOW, WRONG_WINDOW}}, /* no attack */ + /*no attack*/ {{LONG_WINDOW, SHORT_WINDOW, SHORT_WINDOW, LONG_WINDOW, + WRONG_WINDOW, WRONG_WINDOW}, /* attack */ + /*attack */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, + START_WINDOW, WRONG_WINDOW, + WRONG_WINDOW}} /* attack */ }; -int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, const INT granuleLength, const int isLFE, const INT_PCM *pTimeSignal) -{ - UINT i; - FIXP_DBL enM1, enMax; - - UINT nBlockSwitchWindows = blockSwitchingControl->nBlockSwitchWindows; - - /* for LFE : only LONG window allowed */ - if (isLFE) { - - /* case LFE: */ - /* only long blocks, always use sine windows (MPEG2 AAC, MPEG4 AAC) */ - blockSwitchingControl->lastWindowSequence = LONG_WINDOW; - blockSwitchingControl->windowShape = SINE_WINDOW; - blockSwitchingControl->noOfGroups = 1; - blockSwitchingControl->groupLen[0] = 1; - - return(0); - }; - - /* Save current attack index as last attack index */ - blockSwitchingControl->lastattack = blockSwitchingControl->attack; - blockSwitchingControl->lastAttackIndex = blockSwitchingControl->attackIndex; - - /* Save current window energy as last window energy */ - FDKmemcpy(blockSwitchingControl->windowNrg[0], blockSwitchingControl->windowNrg[1], sizeof(blockSwitchingControl->windowNrg[0])); - FDKmemcpy(blockSwitchingControl->windowNrgF[0], blockSwitchingControl->windowNrgF[1], sizeof(blockSwitchingControl->windowNrgF[0])); - - if (blockSwitchingControl->allowShortFrames) - { - /* Calculate suggested grouping info for the last frame */ - - /* Reset grouping info */ - FDKmemclear (blockSwitchingControl->groupLen, sizeof(blockSwitchingControl->groupLen)); - - /* Set grouping info */ - blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS; - - FDKmemcpy(blockSwitchingControl->groupLen, suggestedGroupingTable[blockSwitchingControl->lastAttackIndex], sizeof(blockSwitchingControl->groupLen)); - - if (blockSwitchingControl->attack == TRUE) - blockSwitchingControl->maxWindowNrg = FDKaacEnc_GetWindowEnergy(blockSwitchingControl->windowNrg[0], blockSwitchingControl->lastAttackIndex); - else - blockSwitchingControl->maxWindowNrg = FL2FXCONST_DBL(0.0); - - } - - - /* Calculate unfiltered and filtered energies in subwindows and combine to segments */ - FDKaacEnc_CalcWindowEnergy(blockSwitchingControl, granuleLength>>(nBlockSwitchWindows==4? 2:3 ), pTimeSignal); - - /* now calculate if there is an attack */ - - /* reset attack */ - blockSwitchingControl->attack = FALSE; +int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, + const INT granuleLength, const int isLFE, + const INT_PCM *pTimeSignal) { + UINT i; + FIXP_DBL enM1, enMax; + + UINT nBlockSwitchWindows = blockSwitchingControl->nBlockSwitchWindows; + + /* for LFE : only LONG window allowed */ + if (isLFE) { + /* case LFE: */ + /* only long blocks, always use sine windows (MPEG2 AAC, MPEG4 AAC) */ + blockSwitchingControl->lastWindowSequence = LONG_WINDOW; + blockSwitchingControl->windowShape = SINE_WINDOW; + blockSwitchingControl->noOfGroups = 1; + blockSwitchingControl->groupLen[0] = 1; + + return (0); + }; + + /* Save current attack index as last attack index */ + blockSwitchingControl->lastattack = blockSwitchingControl->attack; + blockSwitchingControl->lastAttackIndex = blockSwitchingControl->attackIndex; + + /* Save current window energy as last window energy */ + FDKmemcpy(blockSwitchingControl->windowNrg[0], + blockSwitchingControl->windowNrg[1], + sizeof(blockSwitchingControl->windowNrg[0])); + FDKmemcpy(blockSwitchingControl->windowNrgF[0], + blockSwitchingControl->windowNrgF[1], + sizeof(blockSwitchingControl->windowNrgF[0])); + + if (blockSwitchingControl->allowShortFrames) { + /* Calculate suggested grouping info for the last frame */ + + /* Reset grouping info */ + FDKmemclear(blockSwitchingControl->groupLen, + sizeof(blockSwitchingControl->groupLen)); + + /* Set grouping info */ + blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS; + + FDKmemcpy(blockSwitchingControl->groupLen, + suggestedGroupingTable[blockSwitchingControl->lastAttackIndex], + sizeof(blockSwitchingControl->groupLen)); + + if (blockSwitchingControl->attack == TRUE) + blockSwitchingControl->maxWindowNrg = + FDKaacEnc_GetWindowEnergy(blockSwitchingControl->windowNrg[0], + blockSwitchingControl->lastAttackIndex); + else + blockSwitchingControl->maxWindowNrg = FL2FXCONST_DBL(0.0); + } - /* look for attack */ - enMax = FL2FXCONST_DBL(0.0f); - enM1 = blockSwitchingControl->windowNrgF[0][nBlockSwitchWindows-1]; + /* Calculate unfiltered and filtered energies in subwindows and combine to + * segments */ + FDKaacEnc_CalcWindowEnergy( + blockSwitchingControl, + granuleLength >> (nBlockSwitchWindows == 4 ? 2 : 3), pTimeSignal); - for (i=0; i<nBlockSwitchWindows; i++) { - FIXP_DBL tmp = fMultDiv2(oneMinusAccWindowNrgFac, blockSwitchingControl->accWindowNrg); - blockSwitchingControl->accWindowNrg = fMultAdd(tmp, accWindowNrgFac, enM1) ; + /* now calculate if there is an attack */ - if (fMult(blockSwitchingControl->windowNrgF[1][i],invAttackRatio) > blockSwitchingControl->accWindowNrg ) { - blockSwitchingControl->attack = TRUE; - blockSwitchingControl->attackIndex = i; - } - enM1 = blockSwitchingControl->windowNrgF[1][i]; - enMax = fixMax(enMax, enM1); - } + /* reset attack */ + blockSwitchingControl->attack = FALSE; + /* look for attack */ + enMax = FL2FXCONST_DBL(0.0f); + enM1 = blockSwitchingControl->windowNrgF[0][nBlockSwitchWindows - 1]; - if (enMax < minAttackNrg) blockSwitchingControl->attack = FALSE; + for (i = 0; i < nBlockSwitchWindows; i++) { + FIXP_DBL tmp = + fMultDiv2(oneMinusAccWindowNrgFac, blockSwitchingControl->accWindowNrg); + blockSwitchingControl->accWindowNrg = fMultAdd(tmp, accWindowNrgFac, enM1); - /* Check if attack spreads over frame border */ - if((blockSwitchingControl->attack == FALSE) && (blockSwitchingControl->lastattack == TRUE)) { - /* if attack is in last window repeat SHORT_WINDOW */ - if ( ((blockSwitchingControl->windowNrgF[0][nBlockSwitchWindows-1]>>4) > fMult((FIXP_DBL)(10<<(DFRACT_BITS-1-4)), blockSwitchingControl->windowNrgF[1][1])) - && (blockSwitchingControl->lastAttackIndex == (INT)nBlockSwitchWindows-1) - ) - { - blockSwitchingControl->attack = TRUE; - blockSwitchingControl->attackIndex = 0; - } + if (fMult(blockSwitchingControl->windowNrgF[1][i], invAttackRatio) > + blockSwitchingControl->accWindowNrg) { + blockSwitchingControl->attack = TRUE; + blockSwitchingControl->attackIndex = i; } + enM1 = blockSwitchingControl->windowNrgF[1][i]; + enMax = fixMax(enMax, enM1); + } - - if(blockSwitchingControl->allowLookAhead) - { - - - blockSwitchingControl->lastWindowSequence = - chgWndSqLkAhd[blockSwitchingControl->lastattack][blockSwitchingControl->attack][blockSwitchingControl->lastWindowSequence]; - } - else - { - /* Low Delay */ - blockSwitchingControl->lastWindowSequence = - chgWndSq[blockSwitchingControl->attack][blockSwitchingControl->lastWindowSequence]; + if (enMax < minAttackNrg) blockSwitchingControl->attack = FALSE; + + /* Check if attack spreads over frame border */ + if ((blockSwitchingControl->attack == FALSE) && + (blockSwitchingControl->lastattack == TRUE)) { + /* if attack is in last window repeat SHORT_WINDOW */ + if (((blockSwitchingControl->windowNrgF[0][nBlockSwitchWindows - 1] >> 4) > + fMult((FIXP_DBL)(10 << (DFRACT_BITS - 1 - 4)), + blockSwitchingControl->windowNrgF[1][1])) && + (blockSwitchingControl->lastAttackIndex == + (INT)nBlockSwitchWindows - 1)) { + blockSwitchingControl->attack = TRUE; + blockSwitchingControl->attackIndex = 0; } + } + if (blockSwitchingControl->allowLookAhead) { + blockSwitchingControl->lastWindowSequence = + chgWndSqLkAhd[blockSwitchingControl->lastattack] + [blockSwitchingControl->attack] + [blockSwitchingControl->lastWindowSequence]; + } else { + /* Low Delay */ + blockSwitchingControl->lastWindowSequence = + chgWndSq[blockSwitchingControl->attack] + [blockSwitchingControl->lastWindowSequence]; + } - /* update window shape */ - blockSwitchingControl->windowShape = blockType2windowShape[blockSwitchingControl->allowShortFrames][blockSwitchingControl->lastWindowSequence]; + /* update window shape */ + blockSwitchingControl->windowShape = + blockType2windowShape[blockSwitchingControl->allowShortFrames] + [blockSwitchingControl->lastWindowSequence]; - return(0); + return (0); } - - -static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], const INT blSwWndIdx) -{ -/* For coherency, change FDKaacEnc_GetWindowEnergy() to calcluate the energy for a block switching analysis windows, - not for a short block. The same is done FDKaacEnc_CalcWindowEnergy(). The result of FDKaacEnc_GetWindowEnergy() - is used for a comparision of the max energy of left/right channel. */ +static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], + const INT blSwWndIdx) { + /* For coherency, change FDKaacEnc_GetWindowEnergy() to calcluate the energy + for a block switching analysis windows, not for a short block. The same is + done FDKaacEnc_CalcWindowEnergy(). The result of + FDKaacEnc_GetWindowEnergy() is used for a comparision of the max energy of + left/right channel. */ return in[blSwWndIdx]; - } -static void FDKaacEnc_CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, INT windowLen, const INT_PCM *pTimeSignal) -{ - INT i; - UINT w; - - FIXP_SGL hiPassCoeff0 = hiPassCoeff[0]; - FIXP_SGL hiPassCoeff1 = hiPassCoeff[1]; +static void FDKaacEnc_CalcWindowEnergy( + BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, INT windowLen, + const INT_PCM *pTimeSignal) { + INT i; + UINT w; - /* sum up scalarproduct of timesignal as windowed Energies */ - for (w=0; w < blockSwitchingControl->nBlockSwitchWindows; w++) { +#ifndef SINETABLE_16BIT + const FIXP_DBL hiPassCoeff0 = hiPassCoeff[0]; + const FIXP_DBL hiPassCoeff1 = hiPassCoeff[1]; +#else + const FIXP_SGL hiPassCoeff0 = hiPassCoeff[0]; + const FIXP_SGL hiPassCoeff1 = hiPassCoeff[1]; +#endif - FIXP_DBL temp_windowNrg = FL2FXCONST_DBL(0.0f); - FIXP_DBL temp_windowNrgF = FL2FXCONST_DBL(0.0f); - FIXP_DBL temp_iirState0 = blockSwitchingControl->iirStates[0]; - FIXP_DBL temp_iirState1 = blockSwitchingControl->iirStates[1]; + FIXP_DBL temp_iirState0 = blockSwitchingControl->iirStates[0]; + FIXP_DBL temp_iirState1 = blockSwitchingControl->iirStates[1]; - /* windowNrg = sum(timesample^2) */ - for(i=0;i<windowLen;i++) - { + /* sum up scalarproduct of timesignal as windowed Energies */ + for (w = 0; w < blockSwitchingControl->nBlockSwitchWindows; w++) { + ULONG temp_windowNrg = 0x0; + ULONG temp_windowNrgF = 0x0; - FIXP_DBL tempUnfiltered, tempFiltred, t1, t2; - /* tempUnfiltered is scaled with 1 to prevent overflows during calculation of tempFiltred */ + /* windowNrg = sum(timesample^2) */ + for (i = 0; i < windowLen; i++) { + FIXP_DBL tempUnfiltered, t1, t2; + /* tempUnfiltered is scaled with 1 to prevent overflows during calculation + * of tempFiltred */ #if SAMPLE_BITS == DFRACT_BITS - tempUnfiltered = (FIXP_DBL) *pTimeSignal++ >> 1; + tempUnfiltered = (FIXP_DBL)*pTimeSignal++ >> 1; #else - tempUnfiltered = (FIXP_DBL) *pTimeSignal++ << (DFRACT_BITS-SAMPLE_BITS-1); + tempUnfiltered = (FIXP_DBL)*pTimeSignal++ + << (DFRACT_BITS - SAMPLE_BITS - 1); #endif - t1 = fMultDiv2(hiPassCoeff1, tempUnfiltered-temp_iirState0); - t2 = fMultDiv2(hiPassCoeff0, temp_iirState1); - tempFiltred = (t1 - t2) << 1; - - temp_iirState0 = tempUnfiltered; - temp_iirState1 = tempFiltred; - - /* subtract 2 from overallscaling (BLOCK_SWITCH_ENERGY_SHIFT) - * because tempUnfiltered was already scaled with 1 (is 2 after squaring) - * subtract 1 from overallscaling (BLOCK_SWITCH_ENERGY_SHIFT) - * because of fMultDiv2 is doing a scaling by one */ - temp_windowNrg += fPow2Div2(tempUnfiltered) >> (BLOCK_SWITCH_ENERGY_SHIFT - 1 - 2); - temp_windowNrgF += fPow2Div2(tempFiltred) >> (BLOCK_SWITCH_ENERGY_SHIFT - 1 - 2); - } - blockSwitchingControl->windowNrg[1][w] = temp_windowNrg; - blockSwitchingControl->windowNrgF[1][w] = temp_windowNrgF; - blockSwitchingControl->iirStates[0] = temp_iirState0; - blockSwitchingControl->iirStates[1] = temp_iirState1; + t1 = fMultDiv2(hiPassCoeff1, tempUnfiltered - temp_iirState0); + t2 = fMultDiv2(hiPassCoeff0, temp_iirState1); + temp_iirState0 = tempUnfiltered; + temp_iirState1 = (t1 - t2) << 1; + + temp_windowNrg += (LONG)fPow2Div2(temp_iirState0) >> + (BLOCK_SWITCH_ENERGY_SHIFT - 1 - 2); + temp_windowNrgF += (LONG)fPow2Div2(temp_iirState1) >> + (BLOCK_SWITCH_ENERGY_SHIFT - 1 - 2); } + blockSwitchingControl->windowNrg[1][w] = + (LONG)fMin(temp_windowNrg, (UINT)MAXVAL_DBL); + blockSwitchingControl->windowNrgF[1][w] = + (LONG)fMin(temp_windowNrgF, (UINT)MAXVAL_DBL); + } + blockSwitchingControl->iirStates[0] = temp_iirState0; + blockSwitchingControl->iirStates[1] = temp_iirState1; } - -static const UCHAR synchronizedBlockTypeTable[5][5] = -{ - /* LONG_WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW LOWOV_WINDOW*/ - /* LONG_WINDOW */ {LONG_WINDOW, START_WINDOW, SHORT_WINDOW, STOP_WINDOW, LOWOV_WINDOW}, - /* START_WINDOW */ {START_WINDOW, START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, LOWOV_WINDOW}, - /* SHORT_WINDOW */ {SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, WRONG_WINDOW}, - /* STOP_WINDOW */ {STOP_WINDOW, SHORT_WINDOW, SHORT_WINDOW, STOP_WINDOW, LOWOV_WINDOW}, - /* LOWOV_WINDOW */ {LOWOV_WINDOW, LOWOV_WINDOW, WRONG_WINDOW, LOWOV_WINDOW, LOWOV_WINDOW}, +static const UCHAR synchronizedBlockTypeTable[5][5] = { + /* LONG_WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW + LOWOV_WINDOW*/ + /* LONG_WINDOW */ {LONG_WINDOW, START_WINDOW, SHORT_WINDOW, STOP_WINDOW, + LOWOV_WINDOW}, + /* START_WINDOW */ + {START_WINDOW, START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, LOWOV_WINDOW}, + /* SHORT_WINDOW */ + {SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, WRONG_WINDOW}, + /* STOP_WINDOW */ + {STOP_WINDOW, SHORT_WINDOW, SHORT_WINDOW, STOP_WINDOW, LOWOV_WINDOW}, + /* LOWOV_WINDOW */ + {LOWOV_WINDOW, LOWOV_WINDOW, WRONG_WINDOW, LOWOV_WINDOW, LOWOV_WINDOW}, }; -int FDKaacEnc_SyncBlockSwitching ( - BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft, - BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight, - const INT nChannels, - const INT commonWindow ) -{ +int FDKaacEnc_SyncBlockSwitching( + BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft, + BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight, const INT nChannels, + const INT commonWindow) { UCHAR patchType = LONG_WINDOW; - if( nChannels == 2 && commonWindow == TRUE) - { + if (nChannels == 2 && commonWindow == TRUE) { /* could be better with a channel loop (need a handle to psy_data) */ /* get suggested Block Types and synchronize */ - patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlLeft->lastWindowSequence]; - patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlRight->lastWindowSequence]; + patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlLeft + ->lastWindowSequence]; + patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlRight + ->lastWindowSequence]; - /* sanity check (no change from low overlap window to short winow and vice versa) */ - if (patchType == WRONG_WINDOW) - return -1; /* mixed up AAC-LC and AAC-LD */ + /* sanity check (no change from low overlap window to short winow and vice + * versa) */ + if (patchType == WRONG_WINDOW) return -1; /* mixed up AAC-LC and AAC-LD */ /* Set synchronized Blocktype */ - blockSwitchingControlLeft->lastWindowSequence = patchType; + blockSwitchingControlLeft->lastWindowSequence = patchType; blockSwitchingControlRight->lastWindowSequence = patchType; /* update window shape */ - blockSwitchingControlLeft->windowShape = blockType2windowShape[blockSwitchingControlLeft->allowShortFrames][blockSwitchingControlLeft->lastWindowSequence]; - blockSwitchingControlRight->windowShape = blockType2windowShape[blockSwitchingControlLeft->allowShortFrames][blockSwitchingControlRight->lastWindowSequence]; + blockSwitchingControlLeft->windowShape = + blockType2windowShape[blockSwitchingControlLeft->allowShortFrames] + [blockSwitchingControlLeft->lastWindowSequence]; + blockSwitchingControlRight->windowShape = + blockType2windowShape[blockSwitchingControlLeft->allowShortFrames] + [blockSwitchingControlRight->lastWindowSequence]; } - if (blockSwitchingControlLeft->allowShortFrames) - { + if (blockSwitchingControlLeft->allowShortFrames) { int i; - if( nChannels == 2 ) - { - if (commonWindow == TRUE) - { + if (nChannels == 2) { + if (commonWindow == TRUE) { /* Synchronize grouping info */ - int windowSequenceLeftOld = blockSwitchingControlLeft->lastWindowSequence; - int windowSequenceRightOld = blockSwitchingControlRight->lastWindowSequence; + int windowSequenceLeftOld = + blockSwitchingControlLeft->lastWindowSequence; + int windowSequenceRightOld = + blockSwitchingControlRight->lastWindowSequence; /* Long Blocks */ - if(patchType != SHORT_WINDOW) { + if (patchType != SHORT_WINDOW) { /* Set grouping info */ - blockSwitchingControlLeft->noOfGroups = 1; - blockSwitchingControlRight->noOfGroups = 1; - blockSwitchingControlLeft->groupLen[0] = 1; + blockSwitchingControlLeft->noOfGroups = 1; + blockSwitchingControlRight->noOfGroups = 1; + blockSwitchingControlLeft->groupLen[0] = 1; blockSwitchingControlRight->groupLen[0] = 1; - for (i = 1; i < MAX_NO_OF_GROUPS; i++) - { - blockSwitchingControlLeft->groupLen[i] = 0; + for (i = 1; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlLeft->groupLen[i] = 0; blockSwitchingControlRight->groupLen[i] = 0; } } /* Short Blocks */ else { - /* in case all two channels were detected as short-blocks before syncing, use the grouping of channel with higher maxWindowNrg */ - if( (windowSequenceLeftOld == SHORT_WINDOW) && - (windowSequenceRightOld == SHORT_WINDOW) ) - { - if(blockSwitchingControlLeft->maxWindowNrg > blockSwitchingControlRight->maxWindowNrg) { - /* Left Channel wins */ - blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups; - for (i = 0; i < MAX_NO_OF_GROUPS; i++){ - blockSwitchingControlRight->groupLen[i] = blockSwitchingControlLeft->groupLen[i]; - } + /* in case all two channels were detected as short-blocks before + * syncing, use the grouping of channel with higher maxWindowNrg */ + if ((windowSequenceLeftOld == SHORT_WINDOW) && + (windowSequenceRightOld == SHORT_WINDOW)) { + if (blockSwitchingControlLeft->maxWindowNrg > + blockSwitchingControlRight->maxWindowNrg) { + /* Left Channel wins */ + blockSwitchingControlRight->noOfGroups = + blockSwitchingControlLeft->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlRight->groupLen[i] = + blockSwitchingControlLeft->groupLen[i]; + } + } else { + /* Right Channel wins */ + blockSwitchingControlLeft->noOfGroups = + blockSwitchingControlRight->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlLeft->groupLen[i] = + blockSwitchingControlRight->groupLen[i]; + } } - else { - /* Right Channel wins */ - blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups; - for (i = 0; i < MAX_NO_OF_GROUPS; i++){ - blockSwitchingControlLeft->groupLen[i] = blockSwitchingControlRight->groupLen[i]; - } - } - } - else if ( (windowSequenceLeftOld == SHORT_WINDOW) && - (windowSequenceRightOld != SHORT_WINDOW) ) - { + } else if ((windowSequenceLeftOld == SHORT_WINDOW) && + (windowSequenceRightOld != SHORT_WINDOW)) { /* else use grouping of short-block channel */ - blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups; - for (i = 0; i < MAX_NO_OF_GROUPS; i++){ - blockSwitchingControlRight->groupLen[i] = blockSwitchingControlLeft->groupLen[i]; + blockSwitchingControlRight->noOfGroups = + blockSwitchingControlLeft->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlRight->groupLen[i] = + blockSwitchingControlLeft->groupLen[i]; } - } - else if ( (windowSequenceRightOld == SHORT_WINDOW) && - (windowSequenceLeftOld != SHORT_WINDOW) ) - { - blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups; - for (i = 0; i < MAX_NO_OF_GROUPS; i++){ - blockSwitchingControlLeft->groupLen[i] = blockSwitchingControlRight->groupLen[i]; + } else if ((windowSequenceRightOld == SHORT_WINDOW) && + (windowSequenceLeftOld != SHORT_WINDOW)) { + blockSwitchingControlLeft->noOfGroups = + blockSwitchingControlRight->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlLeft->groupLen[i] = + blockSwitchingControlRight->groupLen[i]; } } else { /* syncing a start and stop window ... */ - blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups = 2; - blockSwitchingControlLeft->groupLen[0] = blockSwitchingControlRight->groupLen[0] = 4; - blockSwitchingControlLeft->groupLen[1] = blockSwitchingControlRight->groupLen[1] = 4; + blockSwitchingControlLeft->noOfGroups = + blockSwitchingControlRight->noOfGroups = 2; + blockSwitchingControlLeft->groupLen[0] = + blockSwitchingControlRight->groupLen[0] = 4; + blockSwitchingControlLeft->groupLen[1] = + blockSwitchingControlRight->groupLen[1] = 4; } } /* Short Blocks */ - } - else { + } else { /* stereo, no common window */ - if (blockSwitchingControlLeft->lastWindowSequence!=SHORT_WINDOW){ - blockSwitchingControlLeft->noOfGroups = 1; + if (blockSwitchingControlLeft->lastWindowSequence != SHORT_WINDOW) { + blockSwitchingControlLeft->noOfGroups = 1; blockSwitchingControlLeft->groupLen[0] = 1; - for (i = 1; i < MAX_NO_OF_GROUPS; i++) - { + for (i = 1; i < MAX_NO_OF_GROUPS; i++) { blockSwitchingControlLeft->groupLen[i] = 0; } } - if (blockSwitchingControlRight->lastWindowSequence!=SHORT_WINDOW){ - blockSwitchingControlRight->noOfGroups = 1; + if (blockSwitchingControlRight->lastWindowSequence != SHORT_WINDOW) { + blockSwitchingControlRight->noOfGroups = 1; blockSwitchingControlRight->groupLen[0] = 1; - for (i = 1; i < MAX_NO_OF_GROUPS; i++) - { + for (i = 1; i < MAX_NO_OF_GROUPS; i++) { blockSwitchingControlRight->groupLen[i] = 0; } } } /* common window */ } else { /* Mono */ - if (blockSwitchingControlLeft->lastWindowSequence!=SHORT_WINDOW){ - blockSwitchingControlLeft->noOfGroups = 1; + if (blockSwitchingControlLeft->lastWindowSequence != SHORT_WINDOW) { + blockSwitchingControlLeft->noOfGroups = 1; blockSwitchingControlLeft->groupLen[0] = 1; - for (i = 1; i < MAX_NO_OF_GROUPS; i++) - { + for (i = 1; i < MAX_NO_OF_GROUPS; i++) { blockSwitchingControlLeft->groupLen[i] = 0; } } } } /* allowShortFrames */ - /* Translate LOWOV_WINDOW block type to a meaningful window shape. */ - if ( ! blockSwitchingControlLeft->allowShortFrames ) { - if ( blockSwitchingControlLeft->lastWindowSequence != LONG_WINDOW - && blockSwitchingControlLeft->lastWindowSequence != STOP_WINDOW ) - { + if (!blockSwitchingControlLeft->allowShortFrames) { + if (blockSwitchingControlLeft->lastWindowSequence != LONG_WINDOW && + blockSwitchingControlLeft->lastWindowSequence != STOP_WINDOW) { blockSwitchingControlLeft->lastWindowSequence = LONG_WINDOW; blockSwitchingControlLeft->windowShape = LOL_WINDOW; } } if (nChannels == 2) { - if ( ! blockSwitchingControlRight->allowShortFrames ) { - if ( blockSwitchingControlRight->lastWindowSequence != LONG_WINDOW - && blockSwitchingControlRight->lastWindowSequence != STOP_WINDOW ) - { + if (!blockSwitchingControlRight->allowShortFrames) { + if (blockSwitchingControlRight->lastWindowSequence != LONG_WINDOW && + blockSwitchingControlRight->lastWindowSequence != STOP_WINDOW) { blockSwitchingControlRight->lastWindowSequence = LONG_WINDOW; blockSwitchingControlRight->windowShape = LOL_WINDOW; } @@ -541,5 +580,3 @@ int FDKaacEnc_SyncBlockSwitching ( return 0; } - - |