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