1219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard/*
2219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** Copyright 2003-2010, VisualOn, Inc.
3219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard **
4219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** Licensed under the Apache License, Version 2.0 (the "License");
5219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** you may not use this file except in compliance with the License.
6219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** You may obtain a copy of the License at
7219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard **
8219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard **     http://www.apache.org/licenses/LICENSE-2.0
9219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard **
10219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** Unless required by applicable law or agreed to in writing, software
11219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** distributed under the License is distributed on an "AS IS" BASIS,
12219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** See the License for the specific language governing permissions and
14219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard ** limitations under the License.
15219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard */
16219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard/*******************************************************************************
17219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	File:		block_switch.c
18219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
19219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	Content:	Block switching functions
20219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
2117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*******************************************************************************/
2217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
23219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard#include "typedef.h"
24219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard#include "basic_op.h"
2517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong#include "oper_32b.h"
2617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong#include "psy_const.h"
2717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong#include "block_switch.h"
2817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
2917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
3017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong#define ENERGY_SHIFT (8 - 1)
3117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
3217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/**************** internal function prototypes ***********/
3317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic Word16
3417299ab50ceb70d904e610e3b2d7fb2361a11e03James DongIIRFilter(const Word16 in, const Word32 coeff[], Word32 states[]);
3517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
3617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic Word32
3717299ab50ceb70d904e610e3b2d7fb2361a11e03James DongSrchMaxWithIndex(const Word32 *in, Word16 *index, Word16 n);
3817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
3917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
4017299ab50ceb70d904e610e3b2d7fb2361a11e03James DongWord32
4117299ab50ceb70d904e610e3b2d7fb2361a11e03James DongCalcWindowEnergy(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
4217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                 Word16 *timeSignal,
4317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                 Word16 chIncrement,
4417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                 Word16 windowLen);
4517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
4617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
4717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
4817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/****************** Constants *****************************/
4917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
5017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
5117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/*
5217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  IIR high pass coeffs
5317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*/
5417299ab50ceb70d904e610e3b2d7fb2361a11e03James DongWord32 hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = {
5517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  0xbec8b439, 0x609d4952  /* -0.5095f, 0.7548f */
5617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong};
5717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
5817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic const Word32 accWindowNrgFac = 0x26666666;                   /* factor for accumulating filtered window energies 0.3 */
5917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic const Word32 oneMinusAccWindowNrgFac = 0x5999999a;			/* 0.7 */
6017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic const Word32 invAttackRatioHighBr = 0x0ccccccd;              /* inverted lower ratio limit for attacks 0.1*/
6117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic const Word32 invAttackRatioLowBr =  0x072b020c;              /* 0.056 */
6217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic const Word32 minAttackNrg = 0x00001e84;                      /* minimum energy for attacks 1e+6 */
6317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
6417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
6517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/****************** Routines ****************************/
6617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
6717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
6817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/*****************************************************************************
6917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
7017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name: InitBlockSwitching
7117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description:  init Block Switching parameter.
7217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* returns:      TRUE if success
7317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
7417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
7517299ab50ceb70d904e610e3b2d7fb2361a11e03James DongWord16 InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
7617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          const Word32 bitRate, const Word16 nChannels)
7717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
7817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* select attackRatio */
7917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
8017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if ((sub(nChannels,1)==0 && L_sub(bitRate, 24000) > 0) ||
8117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      (sub(nChannels,1)>0 && bitRate > (nChannels * 16000))) {
8217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    blockSwitchingControl->invAttackRatio = invAttackRatioHighBr;
8317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
8417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  else  {
8517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    blockSwitchingControl->invAttackRatio = invAttackRatioLowBr;
8617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
8717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
8817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  return(TRUE);
8917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
9017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
9117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic Word16 suggestedGroupingTable[TRANS_FAC][MAX_NO_OF_GROUPS] = {
9217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* Attack in Window 0 */ {1,  3,  3,  1},
9317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* Attack in Window 1 */ {1,  1,  3,  3},
9417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* Attack in Window 2 */ {2,  1,  3,  2},
9517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* Attack in Window 3 */ {3,  1,  3,  1},
9617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* Attack in Window 4 */ {3,  1,  1,  3},
9717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* Attack in Window 5 */ {3,  2,  1,  2},
9817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* Attack in Window 6 */ {3,  3,  1,  1},
9917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* Attack in Window 7 */ {3,  3,  1,  1}
10017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong};
10117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
10217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/*****************************************************************************
10317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
10417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name: BlockSwitching
10517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description:  detect this frame whether there is an attack
10617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* returns:      TRUE if success
10717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
10817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
10917299ab50ceb70d904e610e3b2d7fb2361a11e03James DongWord16 BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
11017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                      Word16 *timeSignal,
11117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong					  Word32 sampleRate,
11217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                      Word16 chIncrement)
11317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
11417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 i, w;
11517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 enM1, enMax;
11617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
11717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* Reset grouping info */
11817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  for (i=0; i<TRANS_FAC; i++) {
11917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    blockSwitchingControl->groupLen[i] = 0;
12017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
12117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
12217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
12317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* Search for position and amplitude of attack in last frame (1 windows delay) */
12417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  blockSwitchingControl->maxWindowNrg = SrchMaxWithIndex( &blockSwitchingControl->windowNrg[0][BLOCK_SWITCH_WINDOWS-1],
12517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                                          &blockSwitchingControl->attackIndex,
12617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                                                          BLOCK_SWITCH_WINDOWS);
12717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
12817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  blockSwitchingControl->attackIndex = blockSwitchingControl->lastAttackIndex;
12917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
13017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* Set grouping info */
13117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS;
13217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
13317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  for (i=0; i<MAX_NO_OF_GROUPS; i++) {
13417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    blockSwitchingControl->groupLen[i] = suggestedGroupingTable[blockSwitchingControl->attackIndex][i];
135219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  }
13617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
13717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* if the samplerate is less than 16000, it should be all the short block, avoid pre&post echo */
13817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if(sampleRate >= 16000) {
13917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  /* Save current window energy as last window energy */
14017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  for (w=0; w<BLOCK_SWITCH_WINDOWS; w++) {
14117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  blockSwitchingControl->windowNrg[0][w] = blockSwitchingControl->windowNrg[1][w];
14217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  blockSwitchingControl->windowNrgF[0][w] = blockSwitchingControl->windowNrgF[1][w];
14317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  }
14417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
14517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
14617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  /* Calculate unfiltered and filtered energies in subwindows and combine to segments */
14717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  CalcWindowEnergy(blockSwitchingControl, timeSignal, chIncrement, BLOCK_SWITCH_WINDOW_LEN);
14817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
14917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  /* reset attack */
15017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  blockSwitchingControl->attack = FALSE;
15117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
15217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  enMax = 0;
15317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  enM1 = blockSwitchingControl->windowNrgF[0][BLOCK_SWITCH_WINDOWS-1];
15417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
15517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  for (w=0; w<BLOCK_SWITCH_WINDOWS; w++) {
15617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  Word32 enM1_Tmp, accWindowNrg_Tmp, windowNrgF_Tmp;
15717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  Word16 enM1_Shf, accWindowNrg_Shf, windowNrgF_Shf;
15817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
15917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  accWindowNrg_Shf = norm_l(blockSwitchingControl->accWindowNrg);
16017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  enM1_Shf = norm_l(enM1);
16117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  windowNrgF_Shf = norm_l(blockSwitchingControl->windowNrgF[1][w]);
16217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
16317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  accWindowNrg_Tmp = blockSwitchingControl->accWindowNrg << accWindowNrg_Shf;
16417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  enM1_Tmp = enM1 << enM1_Shf;
16517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  windowNrgF_Tmp = blockSwitchingControl->windowNrgF[1][w] << windowNrgF_Shf;
16617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
16717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  /* a sliding average of the previous energies */
16817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  blockSwitchingControl->accWindowNrg = (fixmul(oneMinusAccWindowNrgFac, accWindowNrg_Tmp) >> accWindowNrg_Shf) +
16917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong			  (fixmul(accWindowNrgFac, enM1_Tmp) >> enM1_Shf);
17017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
17117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
17217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  /* if the energy with the ratio is bigger than the average, and the attack and short block  */
17317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  if ((fixmul(windowNrgF_Tmp, blockSwitchingControl->invAttackRatio) >> windowNrgF_Shf) >
17417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong			  blockSwitchingControl->accWindowNrg ) {
17517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong				  blockSwitchingControl->attack = TRUE;
17617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong				  blockSwitchingControl->lastAttackIndex = w;
17717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  }
17817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  enM1 = blockSwitchingControl->windowNrgF[1][w];
17917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  enMax = max(enMax, enM1);
18017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  }
18117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
18217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  if (enMax < minAttackNrg) {
18317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong		  blockSwitchingControl->attack = FALSE;
18417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  }
18517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
18617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  else
18717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  {
18817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  blockSwitchingControl->attack = TRUE;
18917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
19017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
19117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* Check if attack spreads over frame border */
19217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if ((!blockSwitchingControl->attack) && (blockSwitchingControl->lastattack)) {
19317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
19417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if (blockSwitchingControl->attackIndex == TRANS_FAC-1) {
19517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      blockSwitchingControl->attack = TRUE;
19617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
19717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
19817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    blockSwitchingControl->lastattack = FALSE;
19917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
20017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  else {
20117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    blockSwitchingControl->lastattack = blockSwitchingControl->attack;
20217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
20317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
20417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  blockSwitchingControl->windowSequence =  blockSwitchingControl->nextwindowSequence;
20517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
20617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
20717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if (blockSwitchingControl->attack) {
20817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    blockSwitchingControl->nextwindowSequence = SHORT_WINDOW;
20917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
21017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  else {
21117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    blockSwitchingControl->nextwindowSequence = LONG_WINDOW;
21217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
21317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
21417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* update short block group */
21517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if (blockSwitchingControl->nextwindowSequence == SHORT_WINDOW) {
21617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
21717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if (blockSwitchingControl->windowSequence== LONG_WINDOW) {
21817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      blockSwitchingControl->windowSequence = START_WINDOW;
21917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
22017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
22117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if (blockSwitchingControl->windowSequence == STOP_WINDOW) {
22217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      blockSwitchingControl->windowSequence = SHORT_WINDOW;
22317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      blockSwitchingControl->noOfGroups = 3;
22417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      blockSwitchingControl->groupLen[0] = 3;
22517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      blockSwitchingControl->groupLen[1] = 3;
22617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      blockSwitchingControl->groupLen[2] = 2;
22717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
22817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
22917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
23017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* update block type */
23117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if (blockSwitchingControl->nextwindowSequence == LONG_WINDOW) {
23217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
23317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if (blockSwitchingControl->windowSequence == SHORT_WINDOW) {
23417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      blockSwitchingControl->nextwindowSequence = STOP_WINDOW;
23517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
23617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
23717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
23817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  return(TRUE);
23917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
24017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
24117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
24217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/*****************************************************************************
24317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
24417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name: SrchMaxWithIndex
24517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description:  search for the biggest value in an array
24617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* returns:      the max value
24717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
24817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
24917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic Word32 SrchMaxWithIndex(const Word32 in[], Word16 *index, Word16 n)
25017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
25117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 max;
25217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 i, idx;
25317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
25417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* Search maximum value in array and return index and value */
25517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  max = 0;
25617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  idx = 0;
25717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
25817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  for (i = 0; i < n; i++) {
25917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
26017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if (in[i+1]  > max) {
26117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      max = in[i+1];
26217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      idx = i;
26317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
26417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
26517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  *index = idx;
26617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
26717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  return(max);
26817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
26917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
27017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/*****************************************************************************
27117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
27217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name: CalcWindowEnergy
27317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description:  calculate the energy before iir-filter and after irr-filter
27417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* returns:      TRUE if success
27517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
27617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
277219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard#ifndef ARMV5E
27817299ab50ceb70d904e610e3b2d7fb2361a11e03James DongWord32 CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
27917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        Word16 *timeSignal,
28017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        Word16 chIncrement,
28117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                        Word16 windowLen)
28217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
28317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 w, i, wOffset, tidx, ch;
28417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 accuUE, accuFE;
28517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 tempUnfiltered;
286219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  Word32 tempFiltered;
287219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  Word32 states0, states1;
288219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  Word32 Coeff0, Coeff1;
289219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
290219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
291219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  states0 = blockSwitchingControl->iirStates[0];
292219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  states1 = blockSwitchingControl->iirStates[1];
293219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  Coeff0 = hiPassCoeff[0];
29417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Coeff1 = hiPassCoeff[1];
29517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  tidx = 0;
29617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  for (w=0; w < BLOCK_SWITCH_WINDOWS; w++) {
29717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
29817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    accuUE = 0;
29917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    accuFE = 0;
30017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
30117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    for(i=0; i<windowLen; i++) {
302219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  Word32 accu1, accu2, accu3;
303219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  Word32 out;
30417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong	  tempUnfiltered = timeSignal[tidx];
30517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      tidx = tidx + chIncrement;
306219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
307219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  accu1 = L_mpy_ls(Coeff1, tempUnfiltered);
308219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  accu2 = fixmul( Coeff0, states1 );
309219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  accu3 = accu1 - states0;
310219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  out = accu3 - accu2;
311219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
312219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  states0 = accu1;
313219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard	  states1 = out;
314219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
31517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      tempFiltered = extract_h(out);
31617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      accuUE += (tempUnfiltered * tempUnfiltered) >> ENERGY_SHIFT;
31717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      accuFE += (tempFiltered * tempFiltered) >> ENERGY_SHIFT;
31817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
31917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
32017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    blockSwitchingControl->windowNrg[1][w] = accuUE;
32117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    blockSwitchingControl->windowNrgF[1][w] = accuFE;
32217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
323219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  }
324219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard
325219e2627f1e062c10645664b0d2470d4dfaf5083Mans Rullgard  blockSwitchingControl->iirStates[0] = states0;
32617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  blockSwitchingControl->iirStates[1] = states1;
32717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
32817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  return(TRUE);
32917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
33017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong#endif
33117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
33217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/*****************************************************************************
33317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
33417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name: IIRFilter
33517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description:  calculate the iir-filter for an array
33617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* returns:      the result after iir-filter
33717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
33817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
33917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic Word16 IIRFilter(const Word16 in, const Word32 coeff[], Word32 states[])
34017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
34117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 accu1, accu2, accu3;
34217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word32 out;
34317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
34417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  accu1 = L_mpy_ls(coeff[1], in);
34517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  accu3 = accu1 - states[0];
34617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  accu2 = fixmul( coeff[0], states[1] );
34717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  out = accu3 - accu2;
34817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
34917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  states[0] = accu1;
35017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  states[1] = out;
35117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
35217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  return round16(out);
35317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
35417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
35517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
35617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dongstatic Word16 synchronizedBlockTypeTable[4][4] = {
35717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /*                 LONG_WINDOW   START_WINDOW  SHORT_WINDOW  STOP_WINDOW */
35817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* LONG_WINDOW  */{LONG_WINDOW,  START_WINDOW, SHORT_WINDOW, STOP_WINDOW},
35917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* START_WINDOW */{START_WINDOW, START_WINDOW, SHORT_WINDOW, SHORT_WINDOW},
36017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* SHORT_WINDOW */{SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW},
36117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  /* STOP_WINDOW  */{STOP_WINDOW,  SHORT_WINDOW, SHORT_WINDOW, STOP_WINDOW}
36217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong};
36317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
36417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
36517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong/*****************************************************************************
36617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
36717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* function name: SyncBlockSwitching
36817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* description:  update block type and group value
36917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong* returns:      TRUE if success
37017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong*
37117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong**********************************************************************************/
37217299ab50ceb70d904e610e3b2d7fb2361a11e03James DongWord16 SyncBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft,
37317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight,
37417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong                          const Word16 nChannels)
37517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong{
37617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 i;
37717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  Word16 patchType = LONG_WINDOW;
37817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
37917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
38017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  if (nChannels == 1) { /* Mono */
38117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if (blockSwitchingControlLeft->windowSequence != SHORT_WINDOW) {
38217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      blockSwitchingControlLeft->noOfGroups = 1;
38317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      blockSwitchingControlLeft->groupLen[0] = 1;
38417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
38517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      for (i=1; i<TRANS_FAC; i++) {
38617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        blockSwitchingControlLeft->groupLen[i] = 0;
38717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
38817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
38917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  }
39017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  else { /* Stereo common Window */
39117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlLeft->windowSequence];
39217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlRight->windowSequence];
39317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
39417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    /* Set synchronized Blocktype */
39517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    blockSwitchingControlLeft->windowSequence = patchType;
39617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    blockSwitchingControlRight->windowSequence = patchType;
39717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
39817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    /* Synchronize grouping info */
39917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    if(patchType != SHORT_WINDOW) { /* Long Blocks */
40017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      /* Set grouping info */
40117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      blockSwitchingControlLeft->noOfGroups = 1;
40217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      blockSwitchingControlRight->noOfGroups = 1;
40317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      blockSwitchingControlLeft->groupLen[0] = 1;
40417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      blockSwitchingControlRight->groupLen[0] = 1;
40517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
40617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      for (i=1; i<TRANS_FAC; i++) {
40717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        blockSwitchingControlLeft->groupLen[i] = 0;
40817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        blockSwitchingControlRight->groupLen[i] = 0;
40917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
41017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
41117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    else {
41217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
41317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      if (blockSwitchingControlLeft->maxWindowNrg > blockSwitchingControlRight->maxWindowNrg) {
41417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        /* Left Channel wins */
41517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups;
41617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        for (i=0; i<TRANS_FAC; i++) {
41717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          blockSwitchingControlRight->groupLen[i] = blockSwitchingControlLeft->groupLen[i];
41817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
41917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
42017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      else {
42117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        /* Right Channel wins */
42217299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups;
42317299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        for (i=0; i<TRANS_FAC; i++) {
42417299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong          blockSwitchingControlLeft->groupLen[i] = blockSwitchingControlRight->groupLen[i];
42517299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong        }
42617299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong      }
42717299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong    }
42817299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  } /*endif Mono or Stereo */
42917299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong
43017299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong  return(TRUE);
43117299ab50ceb70d904e610e3b2d7fb2361a11e03James Dong}
432