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 Word16 34956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongIIRFilter(const Word16 in, const Word32 coeff[], Word32 states[]); 35956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 36956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word32 37956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongSrchMaxWithIndex(const Word32 *in, Word16 *index, Word16 n); 38956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 39956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 40956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord32 41956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongCalcWindowEnergy(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, 42956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *timeSignal, 43956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 chIncrement, 44956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 windowLen); 45956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 46956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 47956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 48956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/****************** Constants *****************************/ 49956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 50956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 51956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/* 52956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong IIR high pass coeffs 53956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*/ 549538ab83ed3917e643fc88f63ed83736d5a22d19Martin Storsjoconst Word32 hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = { 55b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 0xbec8b439, 0x609d4952 /* -0.5095f, 0.7548f */ 56956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}; 57956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 58956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic const Word32 accWindowNrgFac = 0x26666666; /* factor for accumulating filtered window energies 0.3 */ 59956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic const Word32 oneMinusAccWindowNrgFac = 0x5999999a; /* 0.7 */ 60956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic const Word32 invAttackRatioHighBr = 0x0ccccccd; /* inverted lower ratio limit for attacks 0.1*/ 61956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic const Word32 invAttackRatioLowBr = 0x072b020c; /* 0.056 */ 62956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic const Word32 minAttackNrg = 0x00001e84; /* minimum energy for attacks 1e+6 */ 63956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 64956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 65956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/****************** Routines ****************************/ 66956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 67956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 68956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 69956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 70956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: InitBlockSwitching 71956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: init Block Switching parameter. 72956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: TRUE if success 73956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 74956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 75956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, 76956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word32 bitRate, const Word16 nChannels) 77956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 78956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* select attackRatio */ 79b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 80b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard if ((sub(nChannels,1)==0 && L_sub(bitRate, 24000) > 0) || 81956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (sub(nChannels,1)>0 && bitRate > (nChannels * 16000))) { 82956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong blockSwitchingControl->invAttackRatio = invAttackRatioHighBr; 83956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 84956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 85956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong blockSwitchingControl->invAttackRatio = invAttackRatioLowBr; 86956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 87956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 88956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return(TRUE); 89956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 90956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 91956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 suggestedGroupingTable[TRANS_FAC][MAX_NO_OF_GROUPS] = { 92956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Attack in Window 0 */ {1, 3, 3, 1}, 93956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Attack in Window 1 */ {1, 1, 3, 3}, 94956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Attack in Window 2 */ {2, 1, 3, 2}, 95956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Attack in Window 3 */ {3, 1, 3, 1}, 96956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Attack in Window 4 */ {3, 1, 1, 3}, 97956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Attack in Window 5 */ {3, 2, 1, 2}, 98956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Attack in Window 6 */ {3, 3, 1, 1}, 99956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Attack in Window 7 */ {3, 3, 1, 1} 100956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}; 101956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 102956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 103956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 104956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: BlockSwitching 105956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: detect this frame whether there is an attack 106956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: TRUE if success 107956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 108956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 109956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, 110956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *timeSignal, 111956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sampleRate, 112956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 chIncrement) 113956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 114956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 i, w; 115956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 enM1, enMax; 116956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 117956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Reset grouping info */ 118956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=0; i<TRANS_FAC; i++) { 119b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->groupLen[i] = 0; 120956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 121956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 122956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 123956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Search for position and amplitude of attack in last frame (1 windows delay) */ 124956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong blockSwitchingControl->maxWindowNrg = SrchMaxWithIndex( &blockSwitchingControl->windowNrg[0][BLOCK_SWITCH_WINDOWS-1], 125956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong &blockSwitchingControl->attackIndex, 126956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong BLOCK_SWITCH_WINDOWS); 127956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 128b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->attackIndex = blockSwitchingControl->lastAttackIndex; 129956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 130956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Set grouping info */ 131b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS; 132956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 133956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=0; i<MAX_NO_OF_GROUPS; i++) { 134b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->groupLen[i] = suggestedGroupingTable[blockSwitchingControl->attackIndex][i]; 135e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 136b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 137956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* if the samplerate is less than 16000, it should be all the short block, avoid pre&post echo */ 138956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if(sampleRate >= 16000) { 139956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Save current window energy as last window energy */ 140956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (w=0; w<BLOCK_SWITCH_WINDOWS; w++) { 141b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->windowNrg[0][w] = blockSwitchingControl->windowNrg[1][w]; 142b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->windowNrgF[0][w] = blockSwitchingControl->windowNrgF[1][w]; 143956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 144956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 145956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 146956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Calculate unfiltered and filtered energies in subwindows and combine to segments */ 147956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CalcWindowEnergy(blockSwitchingControl, timeSignal, chIncrement, BLOCK_SWITCH_WINDOW_LEN); 148956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 149956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* reset attack */ 150b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->attack = FALSE; 151956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 152b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard enMax = 0; 153b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard enM1 = blockSwitchingControl->windowNrgF[0][BLOCK_SWITCH_WINDOWS-1]; 154956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 155956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (w=0; w<BLOCK_SWITCH_WINDOWS; w++) { 156956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 enM1_Tmp, accWindowNrg_Tmp, windowNrgF_Tmp; 157956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 enM1_Shf, accWindowNrg_Shf, windowNrgF_Shf; 158956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 159956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong accWindowNrg_Shf = norm_l(blockSwitchingControl->accWindowNrg); 160956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong enM1_Shf = norm_l(enM1); 161956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong windowNrgF_Shf = norm_l(blockSwitchingControl->windowNrgF[1][w]); 162956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 163956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong accWindowNrg_Tmp = blockSwitchingControl->accWindowNrg << accWindowNrg_Shf; 164956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong enM1_Tmp = enM1 << enM1_Shf; 165956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong windowNrgF_Tmp = blockSwitchingControl->windowNrgF[1][w] << windowNrgF_Shf; 166956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 167956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* a sliding average of the previous energies */ 168956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong blockSwitchingControl->accWindowNrg = (fixmul(oneMinusAccWindowNrgFac, accWindowNrg_Tmp) >> accWindowNrg_Shf) + 169956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (fixmul(accWindowNrgFac, enM1_Tmp) >> enM1_Shf); 170956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 171956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 172956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* if the energy with the ratio is bigger than the average, and the attack and short block */ 173956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((fixmul(windowNrgF_Tmp, blockSwitchingControl->invAttackRatio) >> windowNrgF_Shf) > 174956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong blockSwitchingControl->accWindowNrg ) { 175b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->attack = TRUE; 176b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->lastAttackIndex = w; 177956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 178b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard enM1 = blockSwitchingControl->windowNrgF[1][w]; 179956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong enMax = max(enMax, enM1); 180956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 181956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 182956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (enMax < minAttackNrg) { 183b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->attack = FALSE; 184956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 185956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 186956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 187956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong { 188956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong blockSwitchingControl->attack = TRUE; 189956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 190956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 191b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard /* Check if attack spreads over frame border */ 192956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((!blockSwitchingControl->attack) && (blockSwitchingControl->lastattack)) { 193b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 194956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (blockSwitchingControl->attackIndex == TRANS_FAC-1) { 195b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->attack = TRUE; 196956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 197956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 198b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->lastattack = FALSE; 199956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 200956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 201b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->lastattack = blockSwitchingControl->attack; 202956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 203956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 204b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->windowSequence = blockSwitchingControl->nextwindowSequence; 205b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 206956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 207956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (blockSwitchingControl->attack) { 208956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong blockSwitchingControl->nextwindowSequence = SHORT_WINDOW; 209956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 210956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 211956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong blockSwitchingControl->nextwindowSequence = LONG_WINDOW; 212956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 213956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 214b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard /* update short block group */ 215956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (blockSwitchingControl->nextwindowSequence == SHORT_WINDOW) { 216b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 217956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (blockSwitchingControl->windowSequence== LONG_WINDOW) { 218b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->windowSequence = START_WINDOW; 219956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 220b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 221956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (blockSwitchingControl->windowSequence == STOP_WINDOW) { 222b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->windowSequence = SHORT_WINDOW; 223b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->noOfGroups = 3; 224b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->groupLen[0] = 3; 225b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->groupLen[1] = 3; 226b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->groupLen[2] = 2; 227956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 228956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 229956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 230b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard /* update block type */ 231956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (blockSwitchingControl->nextwindowSequence == LONG_WINDOW) { 232b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 233956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (blockSwitchingControl->windowSequence == SHORT_WINDOW) { 234b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->nextwindowSequence = STOP_WINDOW; 235956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 236956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 237956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 238956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return(TRUE); 239956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 240956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 241956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 242956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 243956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 244956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: SrchMaxWithIndex 245956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: search for the biggest value in an array 246956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: the max value 247956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 248956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 249956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word32 SrchMaxWithIndex(const Word32 in[], Word16 *index, Word16 n) 250956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 251956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 max; 252956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 i, idx; 253956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 254956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Search maximum value in array and return index and value */ 255b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard max = 0; 256b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard idx = 0; 257956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 258956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i = 0; i < n; i++) { 259b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 260956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (in[i+1] > max) { 261b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard max = in[i+1]; 262b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard idx = i; 263956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 264956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 265b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *index = idx; 266956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 267956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return(max); 268956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 269956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 270956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 271956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 272956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: CalcWindowEnergy 273956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: calculate the energy before iir-filter and after irr-filter 274956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: TRUE if success 275956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 276956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 277e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#ifndef ARMV5E 278956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord32 CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, 279956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *timeSignal, 280956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 chIncrement, 281956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 windowLen) 282956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 283956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 w, i, wOffset, tidx, ch; 284956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 accuUE, accuFE; 285956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 tempUnfiltered; 286e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word32 tempFiltered; 287e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word32 states0, states1; 288e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word32 Coeff0, Coeff1; 289e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 290e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 291e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard states0 = blockSwitchingControl->iirStates[0]; 292e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard states1 = blockSwitchingControl->iirStates[1]; 293e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Coeff0 = hiPassCoeff[0]; 294956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Coeff1 = hiPassCoeff[1]; 295b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tidx = 0; 296956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (w=0; w < BLOCK_SWITCH_WINDOWS; w++) { 297956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 298b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard accuUE = 0; 299b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard accuFE = 0; 300956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 301956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(i=0; i<windowLen; i++) { 302e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word32 accu1, accu2, accu3; 303e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word32 out; 304956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tempUnfiltered = timeSignal[tidx]; 305956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tidx = tidx + chIncrement; 306e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 307e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard accu1 = L_mpy_ls(Coeff1, tempUnfiltered); 308e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard accu2 = fixmul( Coeff0, states1 ); 309e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard accu3 = accu1 - states0; 310e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard out = accu3 - accu2; 311e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 312b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard states0 = accu1; 313b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard states1 = out; 314e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 315b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tempFiltered = extract_h(out); 316956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong accuUE += (tempUnfiltered * tempUnfiltered) >> ENERGY_SHIFT; 317956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong accuFE += (tempFiltered * tempFiltered) >> ENERGY_SHIFT; 318956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 319956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 320b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->windowNrg[1][w] = accuUE; 321b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControl->windowNrgF[1][w] = accuFE; 322956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 323e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 324e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 325e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard blockSwitchingControl->iirStates[0] = states0; 326956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong blockSwitchingControl->iirStates[1] = states1; 327956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 328956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return(TRUE); 329956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 330956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#endif 331956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 332956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 333956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 334956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: IIRFilter 335956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: calculate the iir-filter for an array 336956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: the result after iir-filter 337956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 338956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 339956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 IIRFilter(const Word16 in, const Word32 coeff[], Word32 states[]) 340956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 341956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 accu1, accu2, accu3; 342956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 out; 343956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 344956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong accu1 = L_mpy_ls(coeff[1], in); 345956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong accu3 = accu1 - states[0]; 346956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong accu2 = fixmul( coeff[0], states[1] ); 347956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong out = accu3 - accu2; 348956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 349b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard states[0] = accu1; 350b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard states[1] = out; 351956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 352956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return round16(out); 353956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 354956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 355956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 356956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 synchronizedBlockTypeTable[4][4] = { 357956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* LONG_WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW */ 358956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* LONG_WINDOW */{LONG_WINDOW, START_WINDOW, SHORT_WINDOW, STOP_WINDOW}, 359956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* START_WINDOW */{START_WINDOW, START_WINDOW, SHORT_WINDOW, SHORT_WINDOW}, 360956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* SHORT_WINDOW */{SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW}, 361956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* STOP_WINDOW */{STOP_WINDOW, SHORT_WINDOW, SHORT_WINDOW, STOP_WINDOW} 362956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}; 363956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 364956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 365956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 366956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 367956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: SyncBlockSwitching 368956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: update block type and group value 369956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: TRUE if success 370956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 371956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 372956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 SyncBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft, 373956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight, 374956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels) 375956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 376956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 i; 377b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard Word16 patchType = LONG_WINDOW; 378b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 379956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 380956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (nChannels == 1) { /* Mono */ 381956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (blockSwitchingControlLeft->windowSequence != SHORT_WINDOW) { 382b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlLeft->noOfGroups = 1; 383b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlLeft->groupLen[0] = 1; 384956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 385956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=1; i<TRANS_FAC; i++) { 386b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlLeft->groupLen[i] = 0; 387956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 388956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 389956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 390956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { /* Stereo common Window */ 391b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlLeft->windowSequence]; 392b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlRight->windowSequence]; 393956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 394956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Set synchronized Blocktype */ 395b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlLeft->windowSequence = patchType; 396b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlRight->windowSequence = patchType; 397956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 398b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard /* Synchronize grouping info */ 399956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if(patchType != SHORT_WINDOW) { /* Long Blocks */ 400956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Set grouping info */ 401b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlLeft->noOfGroups = 1; 402b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlRight->noOfGroups = 1; 403b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlLeft->groupLen[0] = 1; 404b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlRight->groupLen[0] = 1; 405956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 406956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=1; i<TRANS_FAC; i++) { 407b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlLeft->groupLen[i] = 0; 408b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlRight->groupLen[i] = 0; 409956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 410956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 411956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 412b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 413956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (blockSwitchingControlLeft->maxWindowNrg > blockSwitchingControlRight->maxWindowNrg) { 414956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Left Channel wins */ 415b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups; 416956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=0; i<TRANS_FAC; i++) { 417b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlRight->groupLen[i] = blockSwitchingControlLeft->groupLen[i]; 418956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 419956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 420956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 421956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* Right Channel wins */ 422b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups; 423956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (i=0; i<TRANS_FAC; i++) { 424b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard blockSwitchingControlLeft->groupLen[i] = blockSwitchingControlRight->groupLen[i]; 425956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 426956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 427956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 428956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } /*endif Mono or Stereo */ 429956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 430956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return(TRUE); 431956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 432