1e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*
2e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Copyright 2003-2010, VisualOn, Inc.
3e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
4e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Licensed under the Apache License, Version 2.0 (the "License");
5e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** you may not use this file except in compliance with the License.
6e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** You may obtain a copy of the License at
7e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
8e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **     http://www.apache.org/licenses/LICENSE-2.0
9e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
10e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Unless required by applicable law or agreed to in writing, software
11e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** distributed under the License is distributed on an "AS IS" BASIS,
12e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** See the License for the specific language governing permissions and
14e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** limitations under the License.
15e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard */
16e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*******************************************************************************
17e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	File:		block_switch.c
18e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
19e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	Content:	Block switching functions
20e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
21956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*******************************************************************************/
22956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
23e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "typedef.h"
24e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "basic_op.h"
25956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "oper_32b.h"
26956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "psy_const.h"
27956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "block_switch.h"
28956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
29956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
30956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#define ENERGY_SHIFT (8 - 1)
31956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
32956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/**************** internal function prototypes ***********/
33956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word32
34956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongSrchMaxWithIndex(const Word32 *in, Word16 *index, Word16 n);
35956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
36956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
37956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord32
38956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongCalcWindowEnergy(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
39956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 Word16 *timeSignal,
40956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 Word16 chIncrement,
41956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                 Word16 windowLen);
42956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
43956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
44956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
45956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/****************** Constants *****************************/
46956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
47956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
48956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*
49956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  IIR high pass coeffs
50956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*/
519538ab83ed3917e643fc88f63ed83736d5a22d19Martin Storsjoconst Word32 hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = {
52b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  0xbec8b439, 0x609d4952  /* -0.5095f, 0.7548f */
53956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong};
54956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
55956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic const Word32 accWindowNrgFac = 0x26666666;                   /* factor for accumulating filtered window energies 0.3 */
56956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic const Word32 oneMinusAccWindowNrgFac = 0x5999999a;			/* 0.7 */
57956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic const Word32 invAttackRatioHighBr = 0x0ccccccd;              /* inverted lower ratio limit for attacks 0.1*/
58956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic const Word32 invAttackRatioLowBr =  0x072b020c;              /* 0.056 */
59956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic const Word32 minAttackNrg = 0x00001e84;                      /* minimum energy for attacks 1e+6 */
60956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
61956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
62956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/****************** Routines ****************************/
63956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
64956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
65956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
66956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
67956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: InitBlockSwitching
68956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  init Block Switching parameter.
69956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      TRUE if success
70956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
71956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/
72956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
73956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                          const Word32 bitRate, const Word16 nChannels)
74956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
75956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* select attackRatio */
76b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
77b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  if ((sub(nChannels,1)==0 && L_sub(bitRate, 24000) > 0) ||
78956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      (sub(nChannels,1)>0 && bitRate > (nChannels * 16000))) {
79956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    blockSwitchingControl->invAttackRatio = invAttackRatioHighBr;
80956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
81956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  else  {
82956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    blockSwitchingControl->invAttackRatio = invAttackRatioLowBr;
83956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
84956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
85956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return(TRUE);
86956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
87956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
88956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 suggestedGroupingTable[TRANS_FAC][MAX_NO_OF_GROUPS] = {
89956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* Attack in Window 0 */ {1,  3,  3,  1},
90956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* Attack in Window 1 */ {1,  1,  3,  3},
91956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* Attack in Window 2 */ {2,  1,  3,  2},
92956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* Attack in Window 3 */ {3,  1,  3,  1},
93956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* Attack in Window 4 */ {3,  1,  1,  3},
94956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* Attack in Window 5 */ {3,  2,  1,  2},
95956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* Attack in Window 6 */ {3,  3,  1,  1},
96956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* Attack in Window 7 */ {3,  3,  1,  1}
97956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong};
98956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
99956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
100956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
101956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: BlockSwitching
102956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  detect this frame whether there is an attack
103956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      TRUE if success
104956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
105956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/
106956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
107956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      Word16 *timeSignal,
108956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong					  Word32 sampleRate,
109956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                      Word16 chIncrement)
110956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
111956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 i, w;
112956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 enM1, enMax;
113956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
114956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* Reset grouping info */
115956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (i=0; i<TRANS_FAC; i++) {
116b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    blockSwitchingControl->groupLen[i] = 0;
117956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
118956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
119956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
120956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* Search for position and amplitude of attack in last frame (1 windows delay) */
121956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  blockSwitchingControl->maxWindowNrg = SrchMaxWithIndex( &blockSwitchingControl->windowNrg[0][BLOCK_SWITCH_WINDOWS-1],
122956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                                          &blockSwitchingControl->attackIndex,
123956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                                                          BLOCK_SWITCH_WINDOWS);
124956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
125b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  blockSwitchingControl->attackIndex = blockSwitchingControl->lastAttackIndex;
126956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
127956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* Set grouping info */
128b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS;
129956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
130956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (i=0; i<MAX_NO_OF_GROUPS; i++) {
131b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    blockSwitchingControl->groupLen[i] = suggestedGroupingTable[blockSwitchingControl->attackIndex][i];
132e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  }
133b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
134956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* if the samplerate is less than 16000, it should be all the short block, avoid pre&post echo */
135956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if(sampleRate >= 16000) {
136956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  /* Save current window energy as last window energy */
137956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  for (w=0; w<BLOCK_SWITCH_WINDOWS; w++) {
138b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard		  blockSwitchingControl->windowNrg[0][w] = blockSwitchingControl->windowNrg[1][w];
139b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard		  blockSwitchingControl->windowNrgF[0][w] = blockSwitchingControl->windowNrgF[1][w];
140956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  }
141956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
142956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
143956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  /* Calculate unfiltered and filtered energies in subwindows and combine to segments */
144956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  CalcWindowEnergy(blockSwitchingControl, timeSignal, chIncrement, BLOCK_SWITCH_WINDOW_LEN);
145956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
146956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  /* reset attack */
147b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard	  blockSwitchingControl->attack = FALSE;
148956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
149b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard	  enMax = 0;
150b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard	  enM1 = blockSwitchingControl->windowNrgF[0][BLOCK_SWITCH_WINDOWS-1];
151956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
152956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  for (w=0; w<BLOCK_SWITCH_WINDOWS; w++) {
153956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  Word32 enM1_Tmp, accWindowNrg_Tmp, windowNrgF_Tmp;
154956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  Word16 enM1_Shf, accWindowNrg_Shf, windowNrgF_Shf;
155956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
156956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  accWindowNrg_Shf = norm_l(blockSwitchingControl->accWindowNrg);
157956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  enM1_Shf = norm_l(enM1);
158956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  windowNrgF_Shf = norm_l(blockSwitchingControl->windowNrgF[1][w]);
159956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
160956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  accWindowNrg_Tmp = blockSwitchingControl->accWindowNrg << accWindowNrg_Shf;
161956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  enM1_Tmp = enM1 << enM1_Shf;
162956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  windowNrgF_Tmp = blockSwitchingControl->windowNrgF[1][w] << windowNrgF_Shf;
163956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
164956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  /* a sliding average of the previous energies */
165956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  blockSwitchingControl->accWindowNrg = (fixmul(oneMinusAccWindowNrgFac, accWindowNrg_Tmp) >> accWindowNrg_Shf) +
166956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong			  (fixmul(accWindowNrgFac, enM1_Tmp) >> enM1_Shf);
167956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
168956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
169956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  /* if the energy with the ratio is bigger than the average, and the attack and short block  */
170956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  if ((fixmul(windowNrgF_Tmp, blockSwitchingControl->invAttackRatio) >> windowNrgF_Shf) >
171956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong			  blockSwitchingControl->accWindowNrg ) {
172b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard				  blockSwitchingControl->attack = TRUE;
173b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard				  blockSwitchingControl->lastAttackIndex = w;
174956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  }
175b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard		  enM1 = blockSwitchingControl->windowNrgF[1][w];
176956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong		  enMax = max(enMax, enM1);
177956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  }
178956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
179956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  if (enMax < minAttackNrg) {
180b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard		  blockSwitchingControl->attack = FALSE;
181956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  }
182956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
183956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  else
184956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  {
185956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  blockSwitchingControl->attack = TRUE;
186956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
187956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
188b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  /* Check if attack spreads over frame border */
189956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if ((!blockSwitchingControl->attack) && (blockSwitchingControl->lastattack)) {
190b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
191956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (blockSwitchingControl->attackIndex == TRANS_FAC-1) {
192b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      blockSwitchingControl->attack = TRUE;
193956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
194956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
195b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    blockSwitchingControl->lastattack = FALSE;
196956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
197956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  else {
198b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    blockSwitchingControl->lastattack = blockSwitchingControl->attack;
199956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
200956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
201b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  blockSwitchingControl->windowSequence =  blockSwitchingControl->nextwindowSequence;
202b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
203956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
204956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (blockSwitchingControl->attack) {
205956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    blockSwitchingControl->nextwindowSequence = SHORT_WINDOW;
206956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
207956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  else {
208956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    blockSwitchingControl->nextwindowSequence = LONG_WINDOW;
209956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
210956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
211b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  /* update short block group */
212956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (blockSwitchingControl->nextwindowSequence == SHORT_WINDOW) {
213b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
214956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (blockSwitchingControl->windowSequence== LONG_WINDOW) {
215b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      blockSwitchingControl->windowSequence = START_WINDOW;
216956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
217b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
218956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (blockSwitchingControl->windowSequence == STOP_WINDOW) {
219b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      blockSwitchingControl->windowSequence = SHORT_WINDOW;
220b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      blockSwitchingControl->noOfGroups = 3;
221b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      blockSwitchingControl->groupLen[0] = 3;
222b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      blockSwitchingControl->groupLen[1] = 3;
223b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      blockSwitchingControl->groupLen[2] = 2;
224956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
225956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
226956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
227b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  /* update block type */
228956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (blockSwitchingControl->nextwindowSequence == LONG_WINDOW) {
229b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
230956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (blockSwitchingControl->windowSequence == SHORT_WINDOW) {
231b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      blockSwitchingControl->nextwindowSequence = STOP_WINDOW;
232956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
233956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
234956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
235956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return(TRUE);
236956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
237956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
238956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
239956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
240956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
241956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: SrchMaxWithIndex
242956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  search for the biggest value in an array
243956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      the max value
244956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
245956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/
246956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word32 SrchMaxWithIndex(const Word32 in[], Word16 *index, Word16 n)
247956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
248956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 max;
249956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 i, idx;
250956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
251956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* Search maximum value in array and return index and value */
252b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  max = 0;
253b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  idx = 0;
254956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
255956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (i = 0; i < n; i++) {
256b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
257956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (in[i+1]  > max) {
258b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      max = in[i+1];
259b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      idx = i;
260956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
261956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
262b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  *index = idx;
263956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
264956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return(max);
265956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
266956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
267956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
268956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
269956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: CalcWindowEnergy
270956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  calculate the energy before iir-filter and after irr-filter
271956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      TRUE if success
272956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
273956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/
274e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#ifndef ARMV5E
275956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord32 CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
276956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        Word16 *timeSignal,
277956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        Word16 chIncrement,
278956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                        Word16 windowLen)
279956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
28054e96f62859d933a5c8d4716cc5ab7bb00bd8711Andreas Gampe  Word32 w, i, tidx;
281956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 accuUE, accuFE;
282956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word32 tempUnfiltered;
283e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 tempFiltered;
284e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 states0, states1;
285e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Word32 Coeff0, Coeff1;
286e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
287e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
288e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  states0 = blockSwitchingControl->iirStates[0];
289e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  states1 = blockSwitchingControl->iirStates[1];
290e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  Coeff0 = hiPassCoeff[0];
291956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Coeff1 = hiPassCoeff[1];
292b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  tidx = 0;
293956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  for (w=0; w < BLOCK_SWITCH_WINDOWS; w++) {
294956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
295b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    accuUE = 0;
296b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    accuFE = 0;
297956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
298956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for(i=0; i<windowLen; i++) {
299e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  Word32 accu1, accu2, accu3;
300e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  Word32 out;
301956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong	  tempUnfiltered = timeSignal[tidx];
302956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      tidx = tidx + chIncrement;
303e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
304e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  accu1 = L_mpy_ls(Coeff1, tempUnfiltered);
305e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  accu2 = fixmul( Coeff0, states1 );
306e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  accu3 = accu1 - states0;
307e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard	  out = accu3 - accu2;
308e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
309b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard	  states0 = accu1;
310b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard	  states1 = out;
311e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
312b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      tempFiltered = extract_h(out);
313956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      accuUE += (tempUnfiltered * tempUnfiltered) >> ENERGY_SHIFT;
314956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      accuFE += (tempFiltered * tempFiltered) >> ENERGY_SHIFT;
315956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
316956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
317b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    blockSwitchingControl->windowNrg[1][w] = accuUE;
318b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    blockSwitchingControl->windowNrgF[1][w] = accuFE;
319956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
320e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  }
321e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
322e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard  blockSwitchingControl->iirStates[0] = states0;
323956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  blockSwitchingControl->iirStates[1] = states1;
324956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
325956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return(TRUE);
326956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
327956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#endif
328956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
329956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 synchronizedBlockTypeTable[4][4] = {
330956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /*                 LONG_WINDOW   START_WINDOW  SHORT_WINDOW  STOP_WINDOW */
331956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* LONG_WINDOW  */{LONG_WINDOW,  START_WINDOW, SHORT_WINDOW, STOP_WINDOW},
332956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* START_WINDOW */{START_WINDOW, START_WINDOW, SHORT_WINDOW, SHORT_WINDOW},
333956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* SHORT_WINDOW */{SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW},
334956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  /* STOP_WINDOW  */{STOP_WINDOW,  SHORT_WINDOW, SHORT_WINDOW, STOP_WINDOW}
335956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong};
336956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
337956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
338956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/*****************************************************************************
339956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
340956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: SyncBlockSwitching
341956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description:  update block type and group value
342956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns:      TRUE if success
343956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*
344956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/
345956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 SyncBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft,
346956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                          BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight,
347956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                          const Word16 nChannels)
348956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{
349956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  Word16 i;
350b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard  Word16 patchType = LONG_WINDOW;
351b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
352956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
353956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  if (nChannels == 1) { /* Mono */
354956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (blockSwitchingControlLeft->windowSequence != SHORT_WINDOW) {
355b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      blockSwitchingControlLeft->noOfGroups = 1;
356b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      blockSwitchingControlLeft->groupLen[0] = 1;
357956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
358956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      for (i=1; i<TRANS_FAC; i++) {
359b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        blockSwitchingControlLeft->groupLen[i] = 0;
360956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      }
361956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
362956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  }
363956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  else { /* Stereo common Window */
364b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlLeft->windowSequence];
365b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlRight->windowSequence];
366956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
367956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    /* Set synchronized Blocktype */
368b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    blockSwitchingControlLeft->windowSequence = patchType;
369b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    blockSwitchingControlRight->windowSequence = patchType;
370956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
371b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    /* Synchronize grouping info */
372956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if(patchType != SHORT_WINDOW) { /* Long Blocks */
373956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      /* Set grouping info */
374b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      blockSwitchingControlLeft->noOfGroups = 1;
375b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      blockSwitchingControlRight->noOfGroups = 1;
376b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      blockSwitchingControlLeft->groupLen[0] = 1;
377b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      blockSwitchingControlRight->groupLen[0] = 1;
378956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
379956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      for (i=1; i<TRANS_FAC; i++) {
380b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        blockSwitchingControlLeft->groupLen[i] = 0;
381b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        blockSwitchingControlRight->groupLen[i] = 0;
382956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      }
383956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
384956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    else {
385b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
386956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      if (blockSwitchingControlLeft->maxWindowNrg > blockSwitchingControlRight->maxWindowNrg) {
387956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        /* Left Channel wins */
388b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups;
389956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        for (i=0; i<TRANS_FAC; i++) {
390b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard          blockSwitchingControlRight->groupLen[i] = blockSwitchingControlLeft->groupLen[i];
391956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
392956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      }
393956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      else {
394956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        /* Right Channel wins */
395b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups;
396956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        for (i=0; i<TRANS_FAC; i++) {
397b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard          blockSwitchingControlLeft->groupLen[i] = blockSwitchingControlRight->groupLen[i];
398956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
399956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      }
400956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
401956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  } /*endif Mono or Stereo */
402956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
403956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong  return(TRUE);
404956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
405