xref: /aosp_15_r20/external/aac/libAACenc/src/block_switch.cpp (revision e54365361535b070c2db7374cec45c159c7d0e7a)
1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker 
4*e5436536SAndroid Build Coastguard Worker © Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5*e5436536SAndroid Build Coastguard Worker Forschung e.V. All rights reserved.
6*e5436536SAndroid Build Coastguard Worker 
7*e5436536SAndroid Build Coastguard Worker  1.    INTRODUCTION
8*e5436536SAndroid Build Coastguard Worker The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9*e5436536SAndroid Build Coastguard Worker that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10*e5436536SAndroid Build Coastguard Worker scheme for digital audio. This FDK AAC Codec software is intended to be used on
11*e5436536SAndroid Build Coastguard Worker a wide variety of Android devices.
12*e5436536SAndroid Build Coastguard Worker 
13*e5436536SAndroid Build Coastguard Worker AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14*e5436536SAndroid Build Coastguard Worker general perceptual audio codecs. AAC-ELD is considered the best-performing
15*e5436536SAndroid Build Coastguard Worker full-bandwidth communications codec by independent studies and is widely
16*e5436536SAndroid Build Coastguard Worker deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17*e5436536SAndroid Build Coastguard Worker specifications.
18*e5436536SAndroid Build Coastguard Worker 
19*e5436536SAndroid Build Coastguard Worker Patent licenses for necessary patent claims for the FDK AAC Codec (including
20*e5436536SAndroid Build Coastguard Worker those of Fraunhofer) may be obtained through Via Licensing
21*e5436536SAndroid Build Coastguard Worker (www.vialicensing.com) or through the respective patent owners individually for
22*e5436536SAndroid Build Coastguard Worker the purpose of encoding or decoding bit streams in products that are compliant
23*e5436536SAndroid Build Coastguard Worker with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24*e5436536SAndroid Build Coastguard Worker Android devices already license these patent claims through Via Licensing or
25*e5436536SAndroid Build Coastguard Worker directly from the patent owners, and therefore FDK AAC Codec software may
26*e5436536SAndroid Build Coastguard Worker already be covered under those patent licenses when it is used for those
27*e5436536SAndroid Build Coastguard Worker licensed purposes only.
28*e5436536SAndroid Build Coastguard Worker 
29*e5436536SAndroid Build Coastguard Worker Commercially-licensed AAC software libraries, including floating-point versions
30*e5436536SAndroid Build Coastguard Worker with enhanced sound quality, are also available from Fraunhofer. Users are
31*e5436536SAndroid Build Coastguard Worker encouraged to check the Fraunhofer website for additional applications
32*e5436536SAndroid Build Coastguard Worker information and documentation.
33*e5436536SAndroid Build Coastguard Worker 
34*e5436536SAndroid Build Coastguard Worker 2.    COPYRIGHT LICENSE
35*e5436536SAndroid Build Coastguard Worker 
36*e5436536SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification,
37*e5436536SAndroid Build Coastguard Worker are permitted without payment of copyright license fees provided that you
38*e5436536SAndroid Build Coastguard Worker satisfy the following conditions:
39*e5436536SAndroid Build Coastguard Worker 
40*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in redistributions of
41*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec or your modifications thereto in source code form.
42*e5436536SAndroid Build Coastguard Worker 
43*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in the documentation
44*e5436536SAndroid Build Coastguard Worker and/or other materials provided with redistributions of the FDK AAC Codec or
45*e5436536SAndroid Build Coastguard Worker your modifications thereto in binary form. You must make available free of
46*e5436536SAndroid Build Coastguard Worker charge copies of the complete source code of the FDK AAC Codec and your
47*e5436536SAndroid Build Coastguard Worker modifications thereto to recipients of copies in binary form.
48*e5436536SAndroid Build Coastguard Worker 
49*e5436536SAndroid Build Coastguard Worker The name of Fraunhofer may not be used to endorse or promote products derived
50*e5436536SAndroid Build Coastguard Worker from this library without prior written permission.
51*e5436536SAndroid Build Coastguard Worker 
52*e5436536SAndroid Build Coastguard Worker You may not charge copyright license fees for anyone to use, copy or distribute
53*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec software or your modifications thereto.
54*e5436536SAndroid Build Coastguard Worker 
55*e5436536SAndroid Build Coastguard Worker Your modified versions of the FDK AAC Codec must carry prominent notices stating
56*e5436536SAndroid Build Coastguard Worker that you changed the software and the date of any change. For modified versions
57*e5436536SAndroid Build Coastguard Worker of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58*e5436536SAndroid Build Coastguard Worker must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59*e5436536SAndroid Build Coastguard Worker AAC Codec Library for Android."
60*e5436536SAndroid Build Coastguard Worker 
61*e5436536SAndroid Build Coastguard Worker 3.    NO PATENT LICENSE
62*e5436536SAndroid Build Coastguard Worker 
63*e5436536SAndroid Build Coastguard Worker NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64*e5436536SAndroid Build Coastguard Worker limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65*e5436536SAndroid Build Coastguard Worker Fraunhofer provides no warranty of patent non-infringement with respect to this
66*e5436536SAndroid Build Coastguard Worker software.
67*e5436536SAndroid Build Coastguard Worker 
68*e5436536SAndroid Build Coastguard Worker You may use this FDK AAC Codec software or modifications thereto only for
69*e5436536SAndroid Build Coastguard Worker purposes that are authorized by appropriate patent licenses.
70*e5436536SAndroid Build Coastguard Worker 
71*e5436536SAndroid Build Coastguard Worker 4.    DISCLAIMER
72*e5436536SAndroid Build Coastguard Worker 
73*e5436536SAndroid Build Coastguard Worker This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74*e5436536SAndroid Build Coastguard Worker holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75*e5436536SAndroid Build Coastguard Worker including but not limited to the implied warranties of merchantability and
76*e5436536SAndroid Build Coastguard Worker fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77*e5436536SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78*e5436536SAndroid Build Coastguard Worker or consequential damages, including but not limited to procurement of substitute
79*e5436536SAndroid Build Coastguard Worker goods or services; loss of use, data, or profits, or business interruption,
80*e5436536SAndroid Build Coastguard Worker however caused and on any theory of liability, whether in contract, strict
81*e5436536SAndroid Build Coastguard Worker liability, or tort (including negligence), arising in any way out of the use of
82*e5436536SAndroid Build Coastguard Worker this software, even if advised of the possibility of such damage.
83*e5436536SAndroid Build Coastguard Worker 
84*e5436536SAndroid Build Coastguard Worker 5.    CONTACT INFORMATION
85*e5436536SAndroid Build Coastguard Worker 
86*e5436536SAndroid Build Coastguard Worker Fraunhofer Institute for Integrated Circuits IIS
87*e5436536SAndroid Build Coastguard Worker Attention: Audio and Multimedia Departments - FDK AAC LL
88*e5436536SAndroid Build Coastguard Worker Am Wolfsmantel 33
89*e5436536SAndroid Build Coastguard Worker 91058 Erlangen, Germany
90*e5436536SAndroid Build Coastguard Worker 
91*e5436536SAndroid Build Coastguard Worker www.iis.fraunhofer.de/amm
92*e5436536SAndroid Build Coastguard Worker [email protected]
93*e5436536SAndroid Build Coastguard Worker ----------------------------------------------------------------------------- */
94*e5436536SAndroid Build Coastguard Worker 
95*e5436536SAndroid Build Coastguard Worker /**************************** AAC encoder library ******************************
96*e5436536SAndroid Build Coastguard Worker 
97*e5436536SAndroid Build Coastguard Worker    Author(s):   M. Werner, Tobias Chalupka
98*e5436536SAndroid Build Coastguard Worker 
99*e5436536SAndroid Build Coastguard Worker    Description: Block switching
100*e5436536SAndroid Build Coastguard Worker 
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker 
103*e5436536SAndroid Build Coastguard Worker /****************** Includes *****************************/
104*e5436536SAndroid Build Coastguard Worker 
105*e5436536SAndroid Build Coastguard Worker #include "block_switch.h"
106*e5436536SAndroid Build Coastguard Worker #include "genericStds.h"
107*e5436536SAndroid Build Coastguard Worker 
108*e5436536SAndroid Build Coastguard Worker #define LOWOV_WINDOW _LOWOV_WINDOW
109*e5436536SAndroid Build Coastguard Worker 
110*e5436536SAndroid Build Coastguard Worker /**************** internal function prototypes ***********/
111*e5436536SAndroid Build Coastguard Worker 
112*e5436536SAndroid Build Coastguard Worker static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[],
113*e5436536SAndroid Build Coastguard Worker                                           const INT blSwWndIdx);
114*e5436536SAndroid Build Coastguard Worker 
115*e5436536SAndroid Build Coastguard Worker static void FDKaacEnc_CalcWindowEnergy(
116*e5436536SAndroid Build Coastguard Worker     BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, INT windowLen,
117*e5436536SAndroid Build Coastguard Worker     const INT_PCM *pTimeSignal);
118*e5436536SAndroid Build Coastguard Worker 
119*e5436536SAndroid Build Coastguard Worker /****************** Constants *****************************/
120*e5436536SAndroid Build Coastguard Worker /*                                                LONG         START
121*e5436536SAndroid Build Coastguard Worker  * SHORT         STOP         LOWOV                  */
122*e5436536SAndroid Build Coastguard Worker static const INT blockType2windowShape[2][5] = {
123*e5436536SAndroid Build Coastguard Worker     {SINE_WINDOW, KBD_WINDOW, WRONG_WINDOW, SINE_WINDOW, KBD_WINDOW},  /* LD */
124*e5436536SAndroid Build Coastguard Worker     {KBD_WINDOW, SINE_WINDOW, SINE_WINDOW, KBD_WINDOW, WRONG_WINDOW}}; /* LC */
125*e5436536SAndroid Build Coastguard Worker 
126*e5436536SAndroid Build Coastguard Worker /* IIR high pass coeffs */
127*e5436536SAndroid Build Coastguard Worker 
128*e5436536SAndroid Build Coastguard Worker #ifndef SINETABLE_16BIT
129*e5436536SAndroid Build Coastguard Worker 
130*e5436536SAndroid Build Coastguard Worker static const FIXP_DBL hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = {
131*e5436536SAndroid Build Coastguard Worker     FL2FXCONST_DBL(-0.5095), FL2FXCONST_DBL(0.7548)};
132*e5436536SAndroid Build Coastguard Worker 
133*e5436536SAndroid Build Coastguard Worker static const FIXP_DBL accWindowNrgFac =
134*e5436536SAndroid Build Coastguard Worker     FL2FXCONST_DBL(0.3f); /* factor for accumulating filtered window energies */
135*e5436536SAndroid Build Coastguard Worker static const FIXP_DBL oneMinusAccWindowNrgFac = FL2FXCONST_DBL(0.7f);
136*e5436536SAndroid Build Coastguard Worker /* static const float attackRatio = 10.0; */ /* lower ratio limit for attacks */
137*e5436536SAndroid Build Coastguard Worker static const FIXP_DBL invAttackRatio =
138*e5436536SAndroid Build Coastguard Worker     FL2FXCONST_DBL(0.1f); /* inverted lower ratio limit for attacks */
139*e5436536SAndroid Build Coastguard Worker 
140*e5436536SAndroid Build Coastguard Worker /* The next constants are scaled, because they are used for comparison with
141*e5436536SAndroid Build Coastguard Worker  * scaled values*/
142*e5436536SAndroid Build Coastguard Worker /* minimum energy for attacks */
143*e5436536SAndroid Build Coastguard Worker static const FIXP_DBL minAttackNrg =
144*e5436536SAndroid Build Coastguard Worker     (FL2FXCONST_DBL(1e+6f * NORM_PCM_ENERGY) >>
145*e5436536SAndroid Build Coastguard Worker      BLOCK_SWITCH_ENERGY_SHIFT); /* minimum energy for attacks */
146*e5436536SAndroid Build Coastguard Worker 
147*e5436536SAndroid Build Coastguard Worker #else
148*e5436536SAndroid Build Coastguard Worker 
149*e5436536SAndroid Build Coastguard Worker static const FIXP_SGL hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = {
150*e5436536SAndroid Build Coastguard Worker     FL2FXCONST_SGL(-0.5095), FL2FXCONST_SGL(0.7548)};
151*e5436536SAndroid Build Coastguard Worker 
152*e5436536SAndroid Build Coastguard Worker static const FIXP_DBL accWindowNrgFac =
153*e5436536SAndroid Build Coastguard Worker     FL2FXCONST_DBL(0.3f); /* factor for accumulating filtered window energies */
154*e5436536SAndroid Build Coastguard Worker static const FIXP_SGL oneMinusAccWindowNrgFac = FL2FXCONST_SGL(0.7f);
155*e5436536SAndroid Build Coastguard Worker /* static const float attackRatio = 10.0; */ /* lower ratio limit for attacks */
156*e5436536SAndroid Build Coastguard Worker static const FIXP_SGL invAttackRatio =
157*e5436536SAndroid Build Coastguard Worker     FL2FXCONST_SGL(0.1f); /* inverted lower ratio limit for attacks */
158*e5436536SAndroid Build Coastguard Worker /* minimum energy for attacks */
159*e5436536SAndroid Build Coastguard Worker static const FIXP_DBL minAttackNrg =
160*e5436536SAndroid Build Coastguard Worker     (FL2FXCONST_DBL(1e+6f * NORM_PCM_ENERGY) >>
161*e5436536SAndroid Build Coastguard Worker      BLOCK_SWITCH_ENERGY_SHIFT); /* minimum energy for attacks */
162*e5436536SAndroid Build Coastguard Worker 
163*e5436536SAndroid Build Coastguard Worker #endif
164*e5436536SAndroid Build Coastguard Worker 
165*e5436536SAndroid Build Coastguard Worker /**************** internal function prototypes ***********/
166*e5436536SAndroid Build Coastguard Worker 
167*e5436536SAndroid Build Coastguard Worker /****************** Routines ****************************/
FDKaacEnc_InitBlockSwitching(BLOCK_SWITCHING_CONTROL * blockSwitchingControl,INT isLowDelay)168*e5436536SAndroid Build Coastguard Worker void FDKaacEnc_InitBlockSwitching(
169*e5436536SAndroid Build Coastguard Worker     BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay) {
170*e5436536SAndroid Build Coastguard Worker   FDKmemclear(blockSwitchingControl, sizeof(BLOCK_SWITCHING_CONTROL));
171*e5436536SAndroid Build Coastguard Worker 
172*e5436536SAndroid Build Coastguard Worker   if (isLowDelay) {
173*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->nBlockSwitchWindows = 4;
174*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->allowShortFrames = 0;
175*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->allowLookAhead = 0;
176*e5436536SAndroid Build Coastguard Worker   } else {
177*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->nBlockSwitchWindows = 8;
178*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->allowShortFrames = 1;
179*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->allowLookAhead = 1;
180*e5436536SAndroid Build Coastguard Worker   }
181*e5436536SAndroid Build Coastguard Worker 
182*e5436536SAndroid Build Coastguard Worker   blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS;
183*e5436536SAndroid Build Coastguard Worker 
184*e5436536SAndroid Build Coastguard Worker   /* Initialize startvalue for blocktype */
185*e5436536SAndroid Build Coastguard Worker   blockSwitchingControl->lastWindowSequence = LONG_WINDOW;
186*e5436536SAndroid Build Coastguard Worker   blockSwitchingControl->windowShape =
187*e5436536SAndroid Build Coastguard Worker       blockType2windowShape[blockSwitchingControl->allowShortFrames]
188*e5436536SAndroid Build Coastguard Worker                            [blockSwitchingControl->lastWindowSequence];
189*e5436536SAndroid Build Coastguard Worker }
190*e5436536SAndroid Build Coastguard Worker 
191*e5436536SAndroid Build Coastguard Worker static const INT suggestedGroupingTable[TRANS_FAC][MAX_NO_OF_GROUPS] = {
192*e5436536SAndroid Build Coastguard Worker     /* Attack in Window 0 */ {1, 3, 3, 1},
193*e5436536SAndroid Build Coastguard Worker     /* Attack in Window 1 */ {1, 1, 3, 3},
194*e5436536SAndroid Build Coastguard Worker     /* Attack in Window 2 */ {2, 1, 3, 2},
195*e5436536SAndroid Build Coastguard Worker     /* Attack in Window 3 */ {3, 1, 3, 1},
196*e5436536SAndroid Build Coastguard Worker     /* Attack in Window 4 */ {3, 1, 1, 3},
197*e5436536SAndroid Build Coastguard Worker     /* Attack in Window 5 */ {3, 2, 1, 2},
198*e5436536SAndroid Build Coastguard Worker     /* Attack in Window 6 */ {3, 3, 1, 1},
199*e5436536SAndroid Build Coastguard Worker     /* Attack in Window 7 */ {3, 3, 1, 1}};
200*e5436536SAndroid Build Coastguard Worker 
201*e5436536SAndroid Build Coastguard Worker /* change block type depending on current blocktype and whether there's an
202*e5436536SAndroid Build Coastguard Worker  * attack */
203*e5436536SAndroid Build Coastguard Worker /* assume no look-ahead */
204*e5436536SAndroid Build Coastguard Worker static const INT chgWndSq[2][N_BLOCKTYPES] = {
205*e5436536SAndroid Build Coastguard Worker     /*             LONG WINDOW   START_WINDOW  SHORT_WINDOW  STOP_WINDOW,
206*e5436536SAndroid Build Coastguard Worker        LOWOV_WINDOW, WRONG_WINDOW */
207*e5436536SAndroid Build Coastguard Worker     /*no attack*/ {LONG_WINDOW, STOP_WINDOW, WRONG_WINDOW, LONG_WINDOW,
208*e5436536SAndroid Build Coastguard Worker                    STOP_WINDOW, WRONG_WINDOW},
209*e5436536SAndroid Build Coastguard Worker     /*attack   */ {START_WINDOW, LOWOV_WINDOW, WRONG_WINDOW, START_WINDOW,
210*e5436536SAndroid Build Coastguard Worker                    LOWOV_WINDOW, WRONG_WINDOW}};
211*e5436536SAndroid Build Coastguard Worker 
212*e5436536SAndroid Build Coastguard Worker /* change block type depending on current blocktype and whether there's an
213*e5436536SAndroid Build Coastguard Worker  * attack */
214*e5436536SAndroid Build Coastguard Worker /* assume look-ahead */
215*e5436536SAndroid Build Coastguard Worker static const INT chgWndSqLkAhd[2][2][N_BLOCKTYPES] = {
216*e5436536SAndroid Build Coastguard Worker     /*attack         LONG WINDOW    START_WINDOW   SHORT_WINDOW   STOP_WINDOW   LOWOV_WINDOW, WRONG_WINDOW */ /* last attack */
217*e5436536SAndroid Build Coastguard Worker     /*no attack*/ {
218*e5436536SAndroid Build Coastguard Worker         {LONG_WINDOW, SHORT_WINDOW, STOP_WINDOW, LONG_WINDOW, WRONG_WINDOW,
219*e5436536SAndroid Build Coastguard Worker          WRONG_WINDOW}, /* no attack   */
220*e5436536SAndroid Build Coastguard Worker         /*attack   */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, START_WINDOW,
221*e5436536SAndroid Build Coastguard Worker                        WRONG_WINDOW, WRONG_WINDOW}}, /* no attack   */
222*e5436536SAndroid Build Coastguard Worker     /*no attack*/ {{LONG_WINDOW, SHORT_WINDOW, SHORT_WINDOW, LONG_WINDOW,
223*e5436536SAndroid Build Coastguard Worker                     WRONG_WINDOW, WRONG_WINDOW}, /* attack      */
224*e5436536SAndroid Build Coastguard Worker                    /*attack   */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW,
225*e5436536SAndroid Build Coastguard Worker                                   START_WINDOW, WRONG_WINDOW,
226*e5436536SAndroid Build Coastguard Worker                                   WRONG_WINDOW}} /* attack      */
227*e5436536SAndroid Build Coastguard Worker };
228*e5436536SAndroid Build Coastguard Worker 
FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL * blockSwitchingControl,const INT granuleLength,const int isLFE,const INT_PCM * pTimeSignal)229*e5436536SAndroid Build Coastguard Worker int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
230*e5436536SAndroid Build Coastguard Worker                              const INT granuleLength, const int isLFE,
231*e5436536SAndroid Build Coastguard Worker                              const INT_PCM *pTimeSignal) {
232*e5436536SAndroid Build Coastguard Worker   UINT i;
233*e5436536SAndroid Build Coastguard Worker   FIXP_DBL enM1, enMax;
234*e5436536SAndroid Build Coastguard Worker 
235*e5436536SAndroid Build Coastguard Worker   UINT nBlockSwitchWindows = blockSwitchingControl->nBlockSwitchWindows;
236*e5436536SAndroid Build Coastguard Worker 
237*e5436536SAndroid Build Coastguard Worker   /* for LFE : only LONG window allowed */
238*e5436536SAndroid Build Coastguard Worker   if (isLFE) {
239*e5436536SAndroid Build Coastguard Worker     /* case LFE: */
240*e5436536SAndroid Build Coastguard Worker     /* only long blocks, always use sine windows (MPEG2 AAC, MPEG4 AAC) */
241*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->lastWindowSequence = LONG_WINDOW;
242*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->windowShape = SINE_WINDOW;
243*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->noOfGroups = 1;
244*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->groupLen[0] = 1;
245*e5436536SAndroid Build Coastguard Worker 
246*e5436536SAndroid Build Coastguard Worker     return (0);
247*e5436536SAndroid Build Coastguard Worker   };
248*e5436536SAndroid Build Coastguard Worker 
249*e5436536SAndroid Build Coastguard Worker   /* Save current attack index as last attack index */
250*e5436536SAndroid Build Coastguard Worker   blockSwitchingControl->lastattack = blockSwitchingControl->attack;
251*e5436536SAndroid Build Coastguard Worker   blockSwitchingControl->lastAttackIndex = blockSwitchingControl->attackIndex;
252*e5436536SAndroid Build Coastguard Worker 
253*e5436536SAndroid Build Coastguard Worker   /* Save current window energy as last window energy */
254*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(blockSwitchingControl->windowNrg[0],
255*e5436536SAndroid Build Coastguard Worker             blockSwitchingControl->windowNrg[1],
256*e5436536SAndroid Build Coastguard Worker             sizeof(blockSwitchingControl->windowNrg[0]));
257*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(blockSwitchingControl->windowNrgF[0],
258*e5436536SAndroid Build Coastguard Worker             blockSwitchingControl->windowNrgF[1],
259*e5436536SAndroid Build Coastguard Worker             sizeof(blockSwitchingControl->windowNrgF[0]));
260*e5436536SAndroid Build Coastguard Worker 
261*e5436536SAndroid Build Coastguard Worker   if (blockSwitchingControl->allowShortFrames) {
262*e5436536SAndroid Build Coastguard Worker     /* Calculate suggested grouping info for the last frame */
263*e5436536SAndroid Build Coastguard Worker 
264*e5436536SAndroid Build Coastguard Worker     /* Reset grouping info */
265*e5436536SAndroid Build Coastguard Worker     FDKmemclear(blockSwitchingControl->groupLen,
266*e5436536SAndroid Build Coastguard Worker                 sizeof(blockSwitchingControl->groupLen));
267*e5436536SAndroid Build Coastguard Worker 
268*e5436536SAndroid Build Coastguard Worker     /* Set grouping info */
269*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS;
270*e5436536SAndroid Build Coastguard Worker 
271*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(blockSwitchingControl->groupLen,
272*e5436536SAndroid Build Coastguard Worker               suggestedGroupingTable[blockSwitchingControl->lastAttackIndex],
273*e5436536SAndroid Build Coastguard Worker               sizeof(blockSwitchingControl->groupLen));
274*e5436536SAndroid Build Coastguard Worker 
275*e5436536SAndroid Build Coastguard Worker     if (blockSwitchingControl->attack == TRUE)
276*e5436536SAndroid Build Coastguard Worker       blockSwitchingControl->maxWindowNrg =
277*e5436536SAndroid Build Coastguard Worker           FDKaacEnc_GetWindowEnergy(blockSwitchingControl->windowNrg[0],
278*e5436536SAndroid Build Coastguard Worker                                     blockSwitchingControl->lastAttackIndex);
279*e5436536SAndroid Build Coastguard Worker     else
280*e5436536SAndroid Build Coastguard Worker       blockSwitchingControl->maxWindowNrg = FL2FXCONST_DBL(0.0);
281*e5436536SAndroid Build Coastguard Worker   }
282*e5436536SAndroid Build Coastguard Worker 
283*e5436536SAndroid Build Coastguard Worker   /* Calculate unfiltered and filtered energies in subwindows and combine to
284*e5436536SAndroid Build Coastguard Worker    * segments */
285*e5436536SAndroid Build Coastguard Worker   FDKaacEnc_CalcWindowEnergy(
286*e5436536SAndroid Build Coastguard Worker       blockSwitchingControl,
287*e5436536SAndroid Build Coastguard Worker       granuleLength >> (nBlockSwitchWindows == 4 ? 2 : 3), pTimeSignal);
288*e5436536SAndroid Build Coastguard Worker 
289*e5436536SAndroid Build Coastguard Worker   /* now calculate if there is an attack */
290*e5436536SAndroid Build Coastguard Worker 
291*e5436536SAndroid Build Coastguard Worker   /* reset attack */
292*e5436536SAndroid Build Coastguard Worker   blockSwitchingControl->attack = FALSE;
293*e5436536SAndroid Build Coastguard Worker 
294*e5436536SAndroid Build Coastguard Worker   /* look for attack */
295*e5436536SAndroid Build Coastguard Worker   enMax = FL2FXCONST_DBL(0.0f);
296*e5436536SAndroid Build Coastguard Worker   enM1 = blockSwitchingControl->windowNrgF[0][nBlockSwitchWindows - 1];
297*e5436536SAndroid Build Coastguard Worker 
298*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < nBlockSwitchWindows; i++) {
299*e5436536SAndroid Build Coastguard Worker     FIXP_DBL tmp =
300*e5436536SAndroid Build Coastguard Worker         fMultDiv2(oneMinusAccWindowNrgFac, blockSwitchingControl->accWindowNrg);
301*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->accWindowNrg = fMultAdd(tmp, accWindowNrgFac, enM1);
302*e5436536SAndroid Build Coastguard Worker 
303*e5436536SAndroid Build Coastguard Worker     if (fMult(blockSwitchingControl->windowNrgF[1][i], invAttackRatio) >
304*e5436536SAndroid Build Coastguard Worker         blockSwitchingControl->accWindowNrg) {
305*e5436536SAndroid Build Coastguard Worker       blockSwitchingControl->attack = TRUE;
306*e5436536SAndroid Build Coastguard Worker       blockSwitchingControl->attackIndex = i;
307*e5436536SAndroid Build Coastguard Worker     }
308*e5436536SAndroid Build Coastguard Worker     enM1 = blockSwitchingControl->windowNrgF[1][i];
309*e5436536SAndroid Build Coastguard Worker     enMax = fixMax(enMax, enM1);
310*e5436536SAndroid Build Coastguard Worker   }
311*e5436536SAndroid Build Coastguard Worker 
312*e5436536SAndroid Build Coastguard Worker   if (enMax < minAttackNrg) blockSwitchingControl->attack = FALSE;
313*e5436536SAndroid Build Coastguard Worker 
314*e5436536SAndroid Build Coastguard Worker   /* Check if attack spreads over frame border */
315*e5436536SAndroid Build Coastguard Worker   if ((blockSwitchingControl->attack == FALSE) &&
316*e5436536SAndroid Build Coastguard Worker       (blockSwitchingControl->lastattack == TRUE)) {
317*e5436536SAndroid Build Coastguard Worker     /* if attack is in last window repeat SHORT_WINDOW */
318*e5436536SAndroid Build Coastguard Worker     if (((blockSwitchingControl->windowNrgF[0][nBlockSwitchWindows - 1] >> 4) >
319*e5436536SAndroid Build Coastguard Worker          fMult((FIXP_DBL)(10 << (DFRACT_BITS - 1 - 4)),
320*e5436536SAndroid Build Coastguard Worker                blockSwitchingControl->windowNrgF[1][1])) &&
321*e5436536SAndroid Build Coastguard Worker         (blockSwitchingControl->lastAttackIndex ==
322*e5436536SAndroid Build Coastguard Worker          (INT)nBlockSwitchWindows - 1)) {
323*e5436536SAndroid Build Coastguard Worker       blockSwitchingControl->attack = TRUE;
324*e5436536SAndroid Build Coastguard Worker       blockSwitchingControl->attackIndex = 0;
325*e5436536SAndroid Build Coastguard Worker     }
326*e5436536SAndroid Build Coastguard Worker   }
327*e5436536SAndroid Build Coastguard Worker 
328*e5436536SAndroid Build Coastguard Worker   if (blockSwitchingControl->allowLookAhead) {
329*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->lastWindowSequence =
330*e5436536SAndroid Build Coastguard Worker         chgWndSqLkAhd[blockSwitchingControl->lastattack]
331*e5436536SAndroid Build Coastguard Worker                      [blockSwitchingControl->attack]
332*e5436536SAndroid Build Coastguard Worker                      [blockSwitchingControl->lastWindowSequence];
333*e5436536SAndroid Build Coastguard Worker   } else {
334*e5436536SAndroid Build Coastguard Worker     /* Low Delay */
335*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->lastWindowSequence =
336*e5436536SAndroid Build Coastguard Worker         chgWndSq[blockSwitchingControl->attack]
337*e5436536SAndroid Build Coastguard Worker                 [blockSwitchingControl->lastWindowSequence];
338*e5436536SAndroid Build Coastguard Worker   }
339*e5436536SAndroid Build Coastguard Worker 
340*e5436536SAndroid Build Coastguard Worker   /* update window shape */
341*e5436536SAndroid Build Coastguard Worker   blockSwitchingControl->windowShape =
342*e5436536SAndroid Build Coastguard Worker       blockType2windowShape[blockSwitchingControl->allowShortFrames]
343*e5436536SAndroid Build Coastguard Worker                            [blockSwitchingControl->lastWindowSequence];
344*e5436536SAndroid Build Coastguard Worker 
345*e5436536SAndroid Build Coastguard Worker   return (0);
346*e5436536SAndroid Build Coastguard Worker }
347*e5436536SAndroid Build Coastguard Worker 
FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[],const INT blSwWndIdx)348*e5436536SAndroid Build Coastguard Worker static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[],
349*e5436536SAndroid Build Coastguard Worker                                           const INT blSwWndIdx) {
350*e5436536SAndroid Build Coastguard Worker   /* For coherency, change FDKaacEnc_GetWindowEnergy() to calcluate the energy
351*e5436536SAndroid Build Coastguard Worker      for a block switching analysis windows, not for a short block. The same is
352*e5436536SAndroid Build Coastguard Worker      done FDKaacEnc_CalcWindowEnergy(). The result of
353*e5436536SAndroid Build Coastguard Worker      FDKaacEnc_GetWindowEnergy() is used for a comparision of the max energy of
354*e5436536SAndroid Build Coastguard Worker      left/right channel. */
355*e5436536SAndroid Build Coastguard Worker 
356*e5436536SAndroid Build Coastguard Worker   return in[blSwWndIdx];
357*e5436536SAndroid Build Coastguard Worker }
358*e5436536SAndroid Build Coastguard Worker 
FDKaacEnc_CalcWindowEnergy(BLOCK_SWITCHING_CONTROL * RESTRICT blockSwitchingControl,INT windowLen,const INT_PCM * pTimeSignal)359*e5436536SAndroid Build Coastguard Worker static void FDKaacEnc_CalcWindowEnergy(
360*e5436536SAndroid Build Coastguard Worker     BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, INT windowLen,
361*e5436536SAndroid Build Coastguard Worker     const INT_PCM *pTimeSignal) {
362*e5436536SAndroid Build Coastguard Worker   INT i;
363*e5436536SAndroid Build Coastguard Worker   UINT w;
364*e5436536SAndroid Build Coastguard Worker 
365*e5436536SAndroid Build Coastguard Worker #ifndef SINETABLE_16BIT
366*e5436536SAndroid Build Coastguard Worker   const FIXP_DBL hiPassCoeff0 = hiPassCoeff[0];
367*e5436536SAndroid Build Coastguard Worker   const FIXP_DBL hiPassCoeff1 = hiPassCoeff[1];
368*e5436536SAndroid Build Coastguard Worker #else
369*e5436536SAndroid Build Coastguard Worker   const FIXP_SGL hiPassCoeff0 = hiPassCoeff[0];
370*e5436536SAndroid Build Coastguard Worker   const FIXP_SGL hiPassCoeff1 = hiPassCoeff[1];
371*e5436536SAndroid Build Coastguard Worker #endif
372*e5436536SAndroid Build Coastguard Worker 
373*e5436536SAndroid Build Coastguard Worker   FIXP_DBL temp_iirState0 = blockSwitchingControl->iirStates[0];
374*e5436536SAndroid Build Coastguard Worker   FIXP_DBL temp_iirState1 = blockSwitchingControl->iirStates[1];
375*e5436536SAndroid Build Coastguard Worker 
376*e5436536SAndroid Build Coastguard Worker   /* sum up scalarproduct of timesignal as windowed Energies */
377*e5436536SAndroid Build Coastguard Worker   for (w = 0; w < blockSwitchingControl->nBlockSwitchWindows; w++) {
378*e5436536SAndroid Build Coastguard Worker     ULONG temp_windowNrg = 0x0;
379*e5436536SAndroid Build Coastguard Worker     ULONG temp_windowNrgF = 0x0;
380*e5436536SAndroid Build Coastguard Worker 
381*e5436536SAndroid Build Coastguard Worker     /* windowNrg = sum(timesample^2) */
382*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < windowLen; i++) {
383*e5436536SAndroid Build Coastguard Worker       FIXP_DBL tempUnfiltered, t1, t2;
384*e5436536SAndroid Build Coastguard Worker       /* tempUnfiltered is scaled with 1 to prevent overflows during calculation
385*e5436536SAndroid Build Coastguard Worker        * of tempFiltred */
386*e5436536SAndroid Build Coastguard Worker #if SAMPLE_BITS == DFRACT_BITS
387*e5436536SAndroid Build Coastguard Worker       tempUnfiltered = (FIXP_DBL)*pTimeSignal++ >> 1;
388*e5436536SAndroid Build Coastguard Worker #else
389*e5436536SAndroid Build Coastguard Worker       tempUnfiltered = (FIXP_DBL)*pTimeSignal++
390*e5436536SAndroid Build Coastguard Worker                        << (DFRACT_BITS - SAMPLE_BITS - 1);
391*e5436536SAndroid Build Coastguard Worker #endif
392*e5436536SAndroid Build Coastguard Worker       t1 = fMultDiv2(hiPassCoeff1, tempUnfiltered - temp_iirState0);
393*e5436536SAndroid Build Coastguard Worker       t2 = fMultDiv2(hiPassCoeff0, temp_iirState1);
394*e5436536SAndroid Build Coastguard Worker       temp_iirState0 = tempUnfiltered;
395*e5436536SAndroid Build Coastguard Worker       temp_iirState1 = (t1 - t2) << 1;
396*e5436536SAndroid Build Coastguard Worker 
397*e5436536SAndroid Build Coastguard Worker       temp_windowNrg += (LONG)fPow2Div2(temp_iirState0) >>
398*e5436536SAndroid Build Coastguard Worker                         (BLOCK_SWITCH_ENERGY_SHIFT - 1 - 2);
399*e5436536SAndroid Build Coastguard Worker       temp_windowNrgF += (LONG)fPow2Div2(temp_iirState1) >>
400*e5436536SAndroid Build Coastguard Worker                          (BLOCK_SWITCH_ENERGY_SHIFT - 1 - 2);
401*e5436536SAndroid Build Coastguard Worker     }
402*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->windowNrg[1][w] =
403*e5436536SAndroid Build Coastguard Worker         (LONG)fMin(temp_windowNrg, (UINT)MAXVAL_DBL);
404*e5436536SAndroid Build Coastguard Worker     blockSwitchingControl->windowNrgF[1][w] =
405*e5436536SAndroid Build Coastguard Worker         (LONG)fMin(temp_windowNrgF, (UINT)MAXVAL_DBL);
406*e5436536SAndroid Build Coastguard Worker   }
407*e5436536SAndroid Build Coastguard Worker   blockSwitchingControl->iirStates[0] = temp_iirState0;
408*e5436536SAndroid Build Coastguard Worker   blockSwitchingControl->iirStates[1] = temp_iirState1;
409*e5436536SAndroid Build Coastguard Worker }
410*e5436536SAndroid Build Coastguard Worker 
411*e5436536SAndroid Build Coastguard Worker static const UCHAR synchronizedBlockTypeTable[5][5] = {
412*e5436536SAndroid Build Coastguard Worker     /*                  LONG_WINDOW   START_WINDOW  SHORT_WINDOW  STOP_WINDOW
413*e5436536SAndroid Build Coastguard Worker        LOWOV_WINDOW*/
414*e5436536SAndroid Build Coastguard Worker     /* LONG_WINDOW  */ {LONG_WINDOW, START_WINDOW, SHORT_WINDOW, STOP_WINDOW,
415*e5436536SAndroid Build Coastguard Worker                         LOWOV_WINDOW},
416*e5436536SAndroid Build Coastguard Worker     /* START_WINDOW */
417*e5436536SAndroid Build Coastguard Worker     {START_WINDOW, START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, LOWOV_WINDOW},
418*e5436536SAndroid Build Coastguard Worker     /* SHORT_WINDOW */
419*e5436536SAndroid Build Coastguard Worker     {SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, WRONG_WINDOW},
420*e5436536SAndroid Build Coastguard Worker     /* STOP_WINDOW  */
421*e5436536SAndroid Build Coastguard Worker     {STOP_WINDOW, SHORT_WINDOW, SHORT_WINDOW, STOP_WINDOW, LOWOV_WINDOW},
422*e5436536SAndroid Build Coastguard Worker     /* LOWOV_WINDOW */
423*e5436536SAndroid Build Coastguard Worker     {LOWOV_WINDOW, LOWOV_WINDOW, WRONG_WINDOW, LOWOV_WINDOW, LOWOV_WINDOW},
424*e5436536SAndroid Build Coastguard Worker };
425*e5436536SAndroid Build Coastguard Worker 
FDKaacEnc_SyncBlockSwitching(BLOCK_SWITCHING_CONTROL * blockSwitchingControlLeft,BLOCK_SWITCHING_CONTROL * blockSwitchingControlRight,const INT nChannels,const INT commonWindow)426*e5436536SAndroid Build Coastguard Worker int FDKaacEnc_SyncBlockSwitching(
427*e5436536SAndroid Build Coastguard Worker     BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft,
428*e5436536SAndroid Build Coastguard Worker     BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight, const INT nChannels,
429*e5436536SAndroid Build Coastguard Worker     const INT commonWindow) {
430*e5436536SAndroid Build Coastguard Worker   UCHAR patchType = LONG_WINDOW;
431*e5436536SAndroid Build Coastguard Worker 
432*e5436536SAndroid Build Coastguard Worker   if (nChannels == 2 && commonWindow == TRUE) {
433*e5436536SAndroid Build Coastguard Worker     /* could be better with a channel loop (need a handle to psy_data) */
434*e5436536SAndroid Build Coastguard Worker     /* get suggested Block Types and synchronize */
435*e5436536SAndroid Build Coastguard Worker     patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlLeft
436*e5436536SAndroid Build Coastguard Worker                                                           ->lastWindowSequence];
437*e5436536SAndroid Build Coastguard Worker     patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlRight
438*e5436536SAndroid Build Coastguard Worker                                                           ->lastWindowSequence];
439*e5436536SAndroid Build Coastguard Worker 
440*e5436536SAndroid Build Coastguard Worker     /* sanity check (no change from low overlap window to short winow and vice
441*e5436536SAndroid Build Coastguard Worker      * versa) */
442*e5436536SAndroid Build Coastguard Worker     if (patchType == WRONG_WINDOW) return -1; /* mixed up AAC-LC and AAC-LD */
443*e5436536SAndroid Build Coastguard Worker 
444*e5436536SAndroid Build Coastguard Worker     /* Set synchronized Blocktype */
445*e5436536SAndroid Build Coastguard Worker     blockSwitchingControlLeft->lastWindowSequence = patchType;
446*e5436536SAndroid Build Coastguard Worker     blockSwitchingControlRight->lastWindowSequence = patchType;
447*e5436536SAndroid Build Coastguard Worker 
448*e5436536SAndroid Build Coastguard Worker     /* update window shape */
449*e5436536SAndroid Build Coastguard Worker     blockSwitchingControlLeft->windowShape =
450*e5436536SAndroid Build Coastguard Worker         blockType2windowShape[blockSwitchingControlLeft->allowShortFrames]
451*e5436536SAndroid Build Coastguard Worker                              [blockSwitchingControlLeft->lastWindowSequence];
452*e5436536SAndroid Build Coastguard Worker     blockSwitchingControlRight->windowShape =
453*e5436536SAndroid Build Coastguard Worker         blockType2windowShape[blockSwitchingControlLeft->allowShortFrames]
454*e5436536SAndroid Build Coastguard Worker                              [blockSwitchingControlRight->lastWindowSequence];
455*e5436536SAndroid Build Coastguard Worker   }
456*e5436536SAndroid Build Coastguard Worker 
457*e5436536SAndroid Build Coastguard Worker   if (blockSwitchingControlLeft->allowShortFrames) {
458*e5436536SAndroid Build Coastguard Worker     int i;
459*e5436536SAndroid Build Coastguard Worker 
460*e5436536SAndroid Build Coastguard Worker     if (nChannels == 2) {
461*e5436536SAndroid Build Coastguard Worker       if (commonWindow == TRUE) {
462*e5436536SAndroid Build Coastguard Worker         /* Synchronize grouping info */
463*e5436536SAndroid Build Coastguard Worker         int windowSequenceLeftOld =
464*e5436536SAndroid Build Coastguard Worker             blockSwitchingControlLeft->lastWindowSequence;
465*e5436536SAndroid Build Coastguard Worker         int windowSequenceRightOld =
466*e5436536SAndroid Build Coastguard Worker             blockSwitchingControlRight->lastWindowSequence;
467*e5436536SAndroid Build Coastguard Worker 
468*e5436536SAndroid Build Coastguard Worker         /* Long Blocks */
469*e5436536SAndroid Build Coastguard Worker         if (patchType != SHORT_WINDOW) {
470*e5436536SAndroid Build Coastguard Worker           /* Set grouping info */
471*e5436536SAndroid Build Coastguard Worker           blockSwitchingControlLeft->noOfGroups = 1;
472*e5436536SAndroid Build Coastguard Worker           blockSwitchingControlRight->noOfGroups = 1;
473*e5436536SAndroid Build Coastguard Worker           blockSwitchingControlLeft->groupLen[0] = 1;
474*e5436536SAndroid Build Coastguard Worker           blockSwitchingControlRight->groupLen[0] = 1;
475*e5436536SAndroid Build Coastguard Worker 
476*e5436536SAndroid Build Coastguard Worker           for (i = 1; i < MAX_NO_OF_GROUPS; i++) {
477*e5436536SAndroid Build Coastguard Worker             blockSwitchingControlLeft->groupLen[i] = 0;
478*e5436536SAndroid Build Coastguard Worker             blockSwitchingControlRight->groupLen[i] = 0;
479*e5436536SAndroid Build Coastguard Worker           }
480*e5436536SAndroid Build Coastguard Worker         }
481*e5436536SAndroid Build Coastguard Worker 
482*e5436536SAndroid Build Coastguard Worker         /* Short Blocks */
483*e5436536SAndroid Build Coastguard Worker         else {
484*e5436536SAndroid Build Coastguard Worker           /* in case all two channels were detected as short-blocks before
485*e5436536SAndroid Build Coastguard Worker            * syncing, use the grouping of channel with higher maxWindowNrg */
486*e5436536SAndroid Build Coastguard Worker           if ((windowSequenceLeftOld == SHORT_WINDOW) &&
487*e5436536SAndroid Build Coastguard Worker               (windowSequenceRightOld == SHORT_WINDOW)) {
488*e5436536SAndroid Build Coastguard Worker             if (blockSwitchingControlLeft->maxWindowNrg >
489*e5436536SAndroid Build Coastguard Worker                 blockSwitchingControlRight->maxWindowNrg) {
490*e5436536SAndroid Build Coastguard Worker               /* Left Channel wins */
491*e5436536SAndroid Build Coastguard Worker               blockSwitchingControlRight->noOfGroups =
492*e5436536SAndroid Build Coastguard Worker                   blockSwitchingControlLeft->noOfGroups;
493*e5436536SAndroid Build Coastguard Worker               for (i = 0; i < MAX_NO_OF_GROUPS; i++) {
494*e5436536SAndroid Build Coastguard Worker                 blockSwitchingControlRight->groupLen[i] =
495*e5436536SAndroid Build Coastguard Worker                     blockSwitchingControlLeft->groupLen[i];
496*e5436536SAndroid Build Coastguard Worker               }
497*e5436536SAndroid Build Coastguard Worker             } else {
498*e5436536SAndroid Build Coastguard Worker               /* Right Channel wins */
499*e5436536SAndroid Build Coastguard Worker               blockSwitchingControlLeft->noOfGroups =
500*e5436536SAndroid Build Coastguard Worker                   blockSwitchingControlRight->noOfGroups;
501*e5436536SAndroid Build Coastguard Worker               for (i = 0; i < MAX_NO_OF_GROUPS; i++) {
502*e5436536SAndroid Build Coastguard Worker                 blockSwitchingControlLeft->groupLen[i] =
503*e5436536SAndroid Build Coastguard Worker                     blockSwitchingControlRight->groupLen[i];
504*e5436536SAndroid Build Coastguard Worker               }
505*e5436536SAndroid Build Coastguard Worker             }
506*e5436536SAndroid Build Coastguard Worker           } else if ((windowSequenceLeftOld == SHORT_WINDOW) &&
507*e5436536SAndroid Build Coastguard Worker                      (windowSequenceRightOld != SHORT_WINDOW)) {
508*e5436536SAndroid Build Coastguard Worker             /* else use grouping of short-block channel */
509*e5436536SAndroid Build Coastguard Worker             blockSwitchingControlRight->noOfGroups =
510*e5436536SAndroid Build Coastguard Worker                 blockSwitchingControlLeft->noOfGroups;
511*e5436536SAndroid Build Coastguard Worker             for (i = 0; i < MAX_NO_OF_GROUPS; i++) {
512*e5436536SAndroid Build Coastguard Worker               blockSwitchingControlRight->groupLen[i] =
513*e5436536SAndroid Build Coastguard Worker                   blockSwitchingControlLeft->groupLen[i];
514*e5436536SAndroid Build Coastguard Worker             }
515*e5436536SAndroid Build Coastguard Worker           } else if ((windowSequenceRightOld == SHORT_WINDOW) &&
516*e5436536SAndroid Build Coastguard Worker                      (windowSequenceLeftOld != SHORT_WINDOW)) {
517*e5436536SAndroid Build Coastguard Worker             blockSwitchingControlLeft->noOfGroups =
518*e5436536SAndroid Build Coastguard Worker                 blockSwitchingControlRight->noOfGroups;
519*e5436536SAndroid Build Coastguard Worker             for (i = 0; i < MAX_NO_OF_GROUPS; i++) {
520*e5436536SAndroid Build Coastguard Worker               blockSwitchingControlLeft->groupLen[i] =
521*e5436536SAndroid Build Coastguard Worker                   blockSwitchingControlRight->groupLen[i];
522*e5436536SAndroid Build Coastguard Worker             }
523*e5436536SAndroid Build Coastguard Worker           } else {
524*e5436536SAndroid Build Coastguard Worker             /* syncing a start and stop window ... */
525*e5436536SAndroid Build Coastguard Worker             blockSwitchingControlLeft->noOfGroups =
526*e5436536SAndroid Build Coastguard Worker                 blockSwitchingControlRight->noOfGroups = 2;
527*e5436536SAndroid Build Coastguard Worker             blockSwitchingControlLeft->groupLen[0] =
528*e5436536SAndroid Build Coastguard Worker                 blockSwitchingControlRight->groupLen[0] = 4;
529*e5436536SAndroid Build Coastguard Worker             blockSwitchingControlLeft->groupLen[1] =
530*e5436536SAndroid Build Coastguard Worker                 blockSwitchingControlRight->groupLen[1] = 4;
531*e5436536SAndroid Build Coastguard Worker           }
532*e5436536SAndroid Build Coastguard Worker         } /* Short Blocks */
533*e5436536SAndroid Build Coastguard Worker       } else {
534*e5436536SAndroid Build Coastguard Worker         /* stereo, no common window */
535*e5436536SAndroid Build Coastguard Worker         if (blockSwitchingControlLeft->lastWindowSequence != SHORT_WINDOW) {
536*e5436536SAndroid Build Coastguard Worker           blockSwitchingControlLeft->noOfGroups = 1;
537*e5436536SAndroid Build Coastguard Worker           blockSwitchingControlLeft->groupLen[0] = 1;
538*e5436536SAndroid Build Coastguard Worker           for (i = 1; i < MAX_NO_OF_GROUPS; i++) {
539*e5436536SAndroid Build Coastguard Worker             blockSwitchingControlLeft->groupLen[i] = 0;
540*e5436536SAndroid Build Coastguard Worker           }
541*e5436536SAndroid Build Coastguard Worker         }
542*e5436536SAndroid Build Coastguard Worker         if (blockSwitchingControlRight->lastWindowSequence != SHORT_WINDOW) {
543*e5436536SAndroid Build Coastguard Worker           blockSwitchingControlRight->noOfGroups = 1;
544*e5436536SAndroid Build Coastguard Worker           blockSwitchingControlRight->groupLen[0] = 1;
545*e5436536SAndroid Build Coastguard Worker           for (i = 1; i < MAX_NO_OF_GROUPS; i++) {
546*e5436536SAndroid Build Coastguard Worker             blockSwitchingControlRight->groupLen[i] = 0;
547*e5436536SAndroid Build Coastguard Worker           }
548*e5436536SAndroid Build Coastguard Worker         }
549*e5436536SAndroid Build Coastguard Worker       } /* common window */
550*e5436536SAndroid Build Coastguard Worker     } else {
551*e5436536SAndroid Build Coastguard Worker       /* Mono */
552*e5436536SAndroid Build Coastguard Worker       if (blockSwitchingControlLeft->lastWindowSequence != SHORT_WINDOW) {
553*e5436536SAndroid Build Coastguard Worker         blockSwitchingControlLeft->noOfGroups = 1;
554*e5436536SAndroid Build Coastguard Worker         blockSwitchingControlLeft->groupLen[0] = 1;
555*e5436536SAndroid Build Coastguard Worker 
556*e5436536SAndroid Build Coastguard Worker         for (i = 1; i < MAX_NO_OF_GROUPS; i++) {
557*e5436536SAndroid Build Coastguard Worker           blockSwitchingControlLeft->groupLen[i] = 0;
558*e5436536SAndroid Build Coastguard Worker         }
559*e5436536SAndroid Build Coastguard Worker       }
560*e5436536SAndroid Build Coastguard Worker     }
561*e5436536SAndroid Build Coastguard Worker   } /* allowShortFrames */
562*e5436536SAndroid Build Coastguard Worker 
563*e5436536SAndroid Build Coastguard Worker   /* Translate LOWOV_WINDOW block type to a meaningful window shape. */
564*e5436536SAndroid Build Coastguard Worker   if (!blockSwitchingControlLeft->allowShortFrames) {
565*e5436536SAndroid Build Coastguard Worker     if (blockSwitchingControlLeft->lastWindowSequence != LONG_WINDOW &&
566*e5436536SAndroid Build Coastguard Worker         blockSwitchingControlLeft->lastWindowSequence != STOP_WINDOW) {
567*e5436536SAndroid Build Coastguard Worker       blockSwitchingControlLeft->lastWindowSequence = LONG_WINDOW;
568*e5436536SAndroid Build Coastguard Worker       blockSwitchingControlLeft->windowShape = LOL_WINDOW;
569*e5436536SAndroid Build Coastguard Worker     }
570*e5436536SAndroid Build Coastguard Worker   }
571*e5436536SAndroid Build Coastguard Worker   if (nChannels == 2) {
572*e5436536SAndroid Build Coastguard Worker     if (!blockSwitchingControlRight->allowShortFrames) {
573*e5436536SAndroid Build Coastguard Worker       if (blockSwitchingControlRight->lastWindowSequence != LONG_WINDOW &&
574*e5436536SAndroid Build Coastguard Worker           blockSwitchingControlRight->lastWindowSequence != STOP_WINDOW) {
575*e5436536SAndroid Build Coastguard Worker         blockSwitchingControlRight->lastWindowSequence = LONG_WINDOW;
576*e5436536SAndroid Build Coastguard Worker         blockSwitchingControlRight->windowShape = LOL_WINDOW;
577*e5436536SAndroid Build Coastguard Worker       }
578*e5436536SAndroid Build Coastguard Worker     }
579*e5436536SAndroid Build Coastguard Worker   }
580*e5436536SAndroid Build Coastguard Worker 
581*e5436536SAndroid Build Coastguard Worker   return 0;
582*e5436536SAndroid Build Coastguard Worker }
583