adj_thr.c revision 01e29ede19cd7d85bfef38896de8e71e569cd211
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: adj_thr.c 18e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 19e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Content: Threshold compensation functions 20e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 21956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*******************************************************************************/ 22956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 23e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "basic_op.h" 24956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "oper_32b.h" 25956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "adj_thr_data.h" 26956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "adj_thr.h" 27956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "qc_data.h" 28956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "line_pe.h" 29956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 30956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 31956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#define minSnrLimit 0x6666 /* 1 dB */ 32e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define PEBITS_COEF 0x170a /* 0.18*(1 << 15)*/ 33e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 34e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define HOLE_THR_LONG 0x2873 /* 0.316*(1 << 15) */ 35e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define HOLE_THR_SHORT 0x4000 /* 0.5 *(1 << 15) */ 36e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 37e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define MS_THRSPREAD_COEF 0x7333 /* 0.9 * (1 << 15) */ 38e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 39e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define MIN_SNR_COEF 0x651f /* 3.16* (1 << (15 - 2)) */ 40956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 41956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/* values for avoid hole flag */ 42956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongenum _avoid_hole_state { 43956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong NO_AH =0, 44956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AH_INACTIVE =1, 45956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AH_ACTIVE =2 46956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}; 47956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 48956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 49956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 50956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:bits2pe 51956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: convert from bits to pe 52956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* pe = 1.18*desiredBits 53956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 54956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 55956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 bits2pe(const Word16 bits) { 56956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return (bits + ((PEBITS_COEF * bits) >> 15)); 57956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 58956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 59956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 60956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 61956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:calcThreshExp 62956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: loudness calculation (threshold to the power of redExp) 63956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* thr(n)^0.25 64956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 65956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 66956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void calcThreshExp(Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB], 67956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 68956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels) 69956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 70e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word16 ch, sfb, sfbGrp; 71956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 *pthrExp, *psfbThre; 72956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (ch=0; ch<nChannels; ch++) { 73e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 74b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard for(sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; sfbGrp+= psyOutChan->sfbPerGroup) 75e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard pthrExp = &(thrExp[ch][sfbGrp]); 76e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psfbThre = psyOutChan->sfbThreshold + sfbGrp; 77956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 78e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard *pthrExp = rsqrt(rsqrt(*psfbThre,INT_BITS),INT_BITS); 79956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pthrExp++; psfbThre++; 80956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 81956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 82956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 83956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 84956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 85956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 86956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:adaptMinSnr 87956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: reduce minSnr requirements for bands with relative low energies 88956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 89956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 90956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void adaptMinSnr(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 91956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], 92956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong MINSNR_ADAPT_PARAM *msaParam, 93956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels) 94956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 95956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ch, sfb, sfbOffs, shift; 96956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 nSfb, avgEn; 97956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 log_avgEn = 0; 98956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 startRatio_x_avgEn = 0; 99b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 100956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 101956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (ch=0; ch<nChannels; ch++) { 102956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL* psyOutChan = &psyOutChannel[ch]; 103956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 104956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calc average energy per scalefactor band */ 105b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard avgEn = 0; 106b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard nSfb = 0; 107956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) { 108956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 109956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfbOffs+sfb]); 110956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong nSfb = nSfb + 1; 111956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 112956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 113b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 114956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (nSfb > 0) { 115e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard avgEn = avgEn / nSfb; 116956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 117956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong log_avgEn = iLog4(avgEn); 118956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong startRatio_x_avgEn = fixmul(msaParam->startRatio, avgEn); 119956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 120956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 121b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 122956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */ 123956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) { 124956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 125956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (psyOutChan->sfbEnergy[sfbOffs+sfb] < startRatio_x_avgEn) { 126956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 dbRatio, minSnrRed; 127956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 snrRed; 128956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 newMinSnr; 129b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 130956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong dbRatio = log_avgEn - logSfbEnergy[ch][sfbOffs+sfb]; 131956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong dbRatio = dbRatio + (dbRatio << 1); 132956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 133956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong minSnrRed = 110 - ((dbRatio + (dbRatio << 1)) >> 2); 134b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard minSnrRed = max(minSnrRed, 20); /* 110: (0.375(redOffs)+1)*80, 135956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 3: 0.00375(redRatioFac)*80 136956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 20: 0.25(maxRed) * 80 */ 137956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 138b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard snrRed = minSnrRed * iLog4((psyOutChan->sfbMinSnr[sfbOffs+sfb] << 16)); 139b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard /* 140956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong snrRedI si now scaled by 80 (minSnrRed) and 4 (ffr_iLog4) 141956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong */ 142b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 143956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong newMinSnr = round16(pow2_xy(snrRed,80*4)); 144b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 145956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChan->sfbMinSnr[sfbOffs+sfb] = min(newMinSnr, minSnrLimit); 146956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 147956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 148956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 149956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 150956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 151956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 152956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 153956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 154956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 155956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 156956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:initAvoidHoleFlag 157956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: determine bands where avoid hole is not necessary resp. possible 158956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 159956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 160956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void initAvoidHoleFlag(Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], 161956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 162956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_ELEMENT* psyOutElement, 163956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels, 164956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AH_PARAM *ahParam) 165956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 166956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ch, sfb, sfbGrp, shift; 167956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 threshold; 168956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32* psfbSpreadEn; 169956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 170956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (ch=0; ch<nChannels; ch++) { 171956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 172b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 173956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (psyOutChan->windowSequence != SHORT_WINDOW) { 174956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ 175e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp; 176956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 177e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard *psfbSpreadEn = *psfbSpreadEn >> 1; /* 0.5 */ 178956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ++psfbSpreadEn; 179956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 180956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 181956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 182956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 183e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ 184956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp; 185956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 186e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard *psfbSpreadEn = (*psfbSpreadEn >> 1) + (*psfbSpreadEn >> 3); /* 0.63 */ 187956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ++psfbSpreadEn; 188956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 189956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 190956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 191956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 192956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 193956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* increase minSnr for local peaks, decrease it for valleys */ 194956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ahParam->modifyMinSnr) { 195956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(ch=0; ch<nChannels; ch++) { 196956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 197b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 198956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (psyOutChan->windowSequence != SHORT_WINDOW) 199956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong threshold = HOLE_THR_LONG; 200956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 201956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong threshold = HOLE_THR_SHORT; 202956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 203956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ 204e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word16 *psfbMinSnr = psyOutChan->sfbMinSnr + sfbGrp; 205956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 206956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sfbEn, sfbEnm1, sfbEnp1, avgEn; 207b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 208956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (sfb > 0) 209956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp+sfb-1]; 210956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 211956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp]; 212b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 213956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (sfb < (psyOutChan->maxSfbPerGroup-1)) 214956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb+1]; 215956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 216956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb]; 217956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgEn = (sfbEnm1 + sfbEnp1) >> 1; 218b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sfbEn = psyOutChan->sfbEnergy[sfbGrp+sfb]; 219b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 220956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (sfbEn > avgEn && avgEn > 0) { 221956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 tmpMinSnr; 222e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard shift = norm_l(sfbEn); 223956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tmpMinSnr = Div_32(L_mpy_ls(avgEn, minSnrLimit) << shift, sfbEn << shift ); 224b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tmpMinSnr = max(tmpMinSnr, HOLE_THR_LONG); 225956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tmpMinSnr = max(tmpMinSnr, threshold); 226956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *psfbMinSnr = min(*psfbMinSnr, tmpMinSnr); 227956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 228956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* valley ? */ 229b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 230956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((sfbEn < (avgEn >> 1)) && (sfbEn > 0)) { 231956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 tmpMinSnr; 232b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard Word32 minSnrEn = L_mpy_wx(avgEn, *psfbMinSnr); 233b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 234e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if(minSnrEn < sfbEn) { 235956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong shift = norm_l(sfbEn); 236956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tmpMinSnr = Div_32( minSnrEn << shift, sfbEn<<shift); 237956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 238956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 239b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tmpMinSnr = MAX_16; 240956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 241956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tmpMinSnr = min(minSnrLimit, tmpMinSnr); 242956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 243956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *psfbMinSnr = 244956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (min((tmpMinSnr >> 2), mult(*psfbMinSnr, MIN_SNR_COEF)) << 2); 245e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 246956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psfbMinSnr++; 247956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 248956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 249956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 250956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 251956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 252956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* stereo: adapt the minimum requirements sfbMinSnr of mid and 253956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong side channels */ 254b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 255956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (nChannels == 2) { 256956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChanM = &psyOutChannel[0]; 257956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChanS = &psyOutChannel[1]; 258956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChanM->sfbCnt; sfb++) { 259956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (psyOutElement->toolsInfo.msMask[sfb]) { 260956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sfbEnM = psyOutChanM->sfbEnergy[sfb]; 261956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sfbEnS = psyOutChanS->sfbEnergy[sfb]; 262956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 maxSfbEn = max(sfbEnM, sfbEnS); 263b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard Word32 maxThr = L_mpy_wx(maxSfbEn, psyOutChanM->sfbMinSnr[sfb]) >> 1; 264b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 265956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if(maxThr >= sfbEnM) { 266b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard psyOutChanM->sfbMinSnr[sfb] = MAX_16; 267956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 268956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 269b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard shift = norm_l(sfbEnM); 270b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard psyOutChanM->sfbMinSnr[sfb] = min(max(psyOutChanM->sfbMinSnr[sfb], 271956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong round16(Div_32(maxThr<<shift, sfbEnM << shift))), minSnrLimit); 272956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 273b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 274956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if(maxThr >= sfbEnS) { 275956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChanS->sfbMinSnr[sfb] = MAX_16; 276956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 277e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard else { 278956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong shift = norm_l(sfbEnS); 279b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard psyOutChanS->sfbMinSnr[sfb] = min(max(psyOutChanS->sfbMinSnr[sfb], 280956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong round16(Div_32(maxThr << shift, sfbEnS << shift))), minSnrLimit); 281956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 282956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 283b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 284956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (sfbEnM > psyOutChanM->sfbSpreadedEnergy[sfb]) 285956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChanS->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnS, MS_THRSPREAD_COEF); 286b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 287956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (sfbEnS > psyOutChanS->sfbSpreadedEnergy[sfb]) 288956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChanM->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnM, MS_THRSPREAD_COEF); 289956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 290956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 291956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 292956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 293956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 294956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */ 295956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(ch=0; ch<nChannels; ch++) { 296956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 297956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ 298e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word16 *pahFlag = ahFlag[ch] + sfbGrp; 299956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 300b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 301956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((psyOutChan->sfbSpreadedEnergy[sfbGrp+sfb] > psyOutChan->sfbEnergy[sfbGrp+sfb]) || 302956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (psyOutChan->sfbEnergy[sfbGrp+sfb] <= psyOutChan->sfbThreshold[sfbGrp+sfb]) || 303956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (psyOutChan->sfbMinSnr[sfbGrp+sfb] == MAX_16)) { 304956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *pahFlag++ = NO_AH; 305956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 306956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 307956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *pahFlag++ = AH_INACTIVE; 308956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 309956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 310956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=psyOutChan->maxSfbPerGroup; sfb<psyOutChan->sfbPerGroup; sfb++) { 311b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *pahFlag++ = NO_AH; 312956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 313956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 314956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 315956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 316956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 317956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 318956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 319956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:calcPeNoAH 320956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: sum the pe data only for bands where avoid hole is inactive 321956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 322956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 323956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void calcPeNoAH(Word16 *pe, 324956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *constPart, 325956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *nActiveLines, 326956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PE_DATA *peData, 327956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], 328956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 329956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels) 330956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 331e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word16 ch, sfb, sfbGrp; 332956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int ipe, iconstPart, inActiveLines; 333956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 334b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ipe = 0; 335b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard iconstPart = 0; 336b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard inActiveLines = 0; 337956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(ch=0; ch<nChannels; ch++) { 338956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 339956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch]; 340956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ 341956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 342b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 343956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ahFlag[ch][sfbGrp+sfb] < AH_ACTIVE) { 344956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ipe = ipe + peChanData->sfbPe[sfbGrp+sfb]; 345956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong iconstPart = iconstPart + peChanData->sfbConstPart[sfbGrp+sfb]; 346956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong inActiveLines = inActiveLines + peChanData->sfbNActiveLines[sfbGrp+sfb]; 347956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 348956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 349956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 350e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 351956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 352b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *pe = saturate(ipe); 353b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *constPart = saturate(iconstPart); 354b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *nActiveLines = saturate(inActiveLines); 355956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 356956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 357956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 358956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 359956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:reduceThresholds 360956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: apply reduction formula 361956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 362956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 363956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void reduceThresholds(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 364956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], 365956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB], 366956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels, 367956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word32 redVal) 368956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 369956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sfbThrReduced; 370b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard Word32 *psfbEn, *psfbThr; 371e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word16 ch, sfb, sfbGrp; 372956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 373956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(ch=0; ch<nChannels; ch++) { 374956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 375956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(sfbGrp=0; sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) { 376b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard psfbEn = psyOutChan->sfbEnergy + sfbGrp; 377e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psfbThr = psyOutChan->sfbThreshold + sfbGrp; 378956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 379b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 380956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (*psfbEn > *psfbThr) { 381956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* threshold reduction formula */ 382956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 tmp = thrExp[ch][sfbGrp+sfb] + redVal; 383956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tmp = fixmul(tmp, tmp); 384956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbThrReduced = fixmul(tmp, tmp); 385956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* avoid holes */ 386956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tmp = L_mpy_ls(*psfbEn, psyOutChan->sfbMinSnr[sfbGrp+sfb]); 387b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 388b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard if ((sfbThrReduced > tmp) && 389956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (ahFlag[ch][sfbGrp+sfb] != NO_AH)){ 390956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbThrReduced = max(tmp, *psfbThr); 391b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ahFlag[ch][sfbGrp+sfb] = AH_ACTIVE; 392956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 393956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *psfbThr = sfbThrReduced; 394e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 395e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 396956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psfbEn++; psfbThr++; 397956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 398956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 399956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 400956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 401956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 402956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 403956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 404956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 405956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:correctThresh 406956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: if pe difference deltaPe between desired pe and real pe is small enough, 407956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* the difference can be distributed among the scale factor bands. 408956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 409956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 410956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void correctThresh(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 411956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], 412956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PE_DATA *peData, 413956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB], 414956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word32 redVal, 415956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels, 416956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word32 deltaPe) 417956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 418956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ch, sfb, sfbGrp,shift; 419956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan; 420956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PE_CHANNEL_DATA *peChanData; 421956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 deltaSfbPe; 422e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word32 normFactor; 423e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word32 *psfbPeFactors; 424956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *psfbNActiveLines, *pahFlag; 425956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sfbEn, sfbThr; 426956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sfbThrReduced; 427956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 428956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* for each sfb calc relative factors for pe changes */ 429b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard normFactor = 1; 430956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(ch=0; ch<nChannels; ch++) { 431956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChan = &psyOutChannel[ch]; 432956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong peChanData = &peData->peChannelData[ch]; 433956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ 434e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp; 435e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp; 436e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard pahFlag = ahFlag[ch] + sfbGrp; 437956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 438956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 redThrExp = thrExp[ch][sfbGrp+sfb] + redVal; 439b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 440956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (((*pahFlag < AH_ACTIVE) || (deltaPe > 0)) && (redThrExp > 0) ) { 441b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 442956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *psfbPeFactors = (*psfbNActiveLines) * (0x7fffffff / redThrExp); 443956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong normFactor = L_add(normFactor, *psfbPeFactors); 444956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 445956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 446b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *psfbPeFactors = 0; 447e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 448b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard psfbPeFactors++; 449956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pahFlag++; psfbNActiveLines++; 450956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 451956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 452956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 453956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 454b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 455956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calculate new thresholds */ 456956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(ch=0; ch<nChannels; ch++) { 457956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChan = &psyOutChannel[ch]; 458956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong peChanData = &peData->peChannelData[ch]; 459956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ 460e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp; 461e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp; 462e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard pahFlag = ahFlag[ch] + sfbGrp; 463956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 464956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* pe difference for this sfb */ 465956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong deltaSfbPe = *psfbPeFactors * deltaPe; 466956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 467b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard /* thr3(n) = thr2(n)*2^deltaSfbPe/b(n) */ 46801e29ede19cd7d85bfef38896de8e71e569cd211Martin Storsjo if (*psfbNActiveLines > 0 && (normFactor* (*psfbNActiveLines)) != 0) { 469956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* new threshold */ 470956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 thrFactor; 471956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbEn = psyOutChan->sfbEnergy[sfbGrp+sfb]; 472956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbThr = psyOutChan->sfbThreshold[sfbGrp+sfb]; 473956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 474956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if(deltaSfbPe >= 0){ 475956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* 476956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong reduce threshold 477956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong */ 478956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong thrFactor = pow2_xy(L_negate(deltaSfbPe), (normFactor* (*psfbNActiveLines))); 479b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 480956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbThrReduced = L_mpy_ls(sfbThr, round16(thrFactor)); 481956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 482956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 483956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* 484956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong increase threshold 485956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong */ 486956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong thrFactor = pow2_xy(deltaSfbPe, (normFactor * (*psfbNActiveLines))); 487b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 488b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 489956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if(thrFactor > sfbThr) { 490e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard shift = norm_l(thrFactor); 491956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbThrReduced = Div_32( sfbThr << shift, thrFactor<<shift ); 492956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 493956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 494b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sfbThrReduced = MAX_32; 495956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 496956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 497956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 498b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 499956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* avoid hole */ 500956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbEn = L_mpy_ls(sfbEn, psyOutChan->sfbMinSnr[sfbGrp+sfb]); 501b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 502956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((sfbThrReduced > sfbEn) && 503956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (*pahFlag == AH_INACTIVE)) { 504956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbThrReduced = max(sfbEn, sfbThr); 505b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *pahFlag = AH_ACTIVE; 506956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 507956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 508b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard psyOutChan->sfbThreshold[sfbGrp+sfb] = sfbThrReduced; 509e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 510e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 511956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pahFlag++; psfbNActiveLines++; psfbPeFactors++; 512956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 513956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 514956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 515956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 516956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 517956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 518956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 519956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 520956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:reduceMinSnr 521956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: if the desired pe can not be reached, reduce pe by reducing minSnr 522956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 523956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 524b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgardstatic void reduceMinSnr(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 525b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard PE_DATA *peData, 526956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], 527956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels, 528956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 desiredPe) 529956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 530956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ch, sfb, sfbSubWin; 531956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 deltaPe; 532956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 533956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* start at highest freq down to 0 */ 534b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sfbSubWin = psyOutChannel[0].maxSfbPerGroup; 535956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong while (peData->pe > desiredPe && sfbSubWin > 0) { 536b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 537956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbSubWin = sfbSubWin - 1; 538956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* loop over all subwindows */ 539956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=sfbSubWin; sfb<psyOutChannel[0].sfbCnt; 540956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfb+=psyOutChannel[0].sfbPerGroup) { 541956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* loop over all channels */ 542e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard PE_CHANNEL_DATA* peChan = peData->peChannelData; 543e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard PSY_OUT_CHANNEL* psyOutCh = psyOutChannel; 544b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard for (ch=0; ch<nChannels; ch++) { 545956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ahFlag[ch][sfb] != NO_AH && 546956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutCh->sfbMinSnr[sfb] < minSnrLimit) { 547b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard psyOutCh->sfbMinSnr[sfb] = minSnrLimit; 548956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutCh->sfbThreshold[sfb] = 549956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong L_mpy_ls(psyOutCh->sfbEnergy[sfb], psyOutCh->sfbMinSnr[sfb]); 550956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 551956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calc new pe */ 552956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong deltaPe = ((peChan->sfbNLines4[sfb] + (peChan->sfbNLines4[sfb] >> 1)) >> 2) - 553956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong peChan->sfbPe[sfb]; 554956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong peData->pe = peData->pe + deltaPe; 555b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard peChan->pe = peChan->pe + deltaPe; 556e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 557956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong peChan += 1; psyOutCh += 1; 558956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 559956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* stop if enough has been saved */ 560b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 561956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (peData->pe <= desiredPe) 562956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong break; 563956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 564956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 565956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 566956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 567956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 568956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 569956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:allowMoreHoles 570b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* description: if the desired pe can not be reached, some more scalefactor bands 571956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* have to be quantized to zero 572956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 573956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 574b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgardstatic void allowMoreHoles(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 575956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_ELEMENT *psyOutElement, 576b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard PE_DATA *peData, 577956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], 578956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const AH_PARAM *ahParam, 579956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels, 580956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 desiredPe) 581956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 582956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ch, sfb; 583956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 actPe, shift; 584956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 585b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard actPe = peData->pe; 586956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 587956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* for MS allow hole in the channel with less energy */ 588b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 589956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (nChannels==2 && 590956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChannel[0].windowSequence==psyOutChannel[1].windowSequence) { 591956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChanL = &psyOutChannel[0]; 592956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChanR = &psyOutChannel[1]; 593956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChanL->sfbCnt; sfb++) { 594956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 minEn; 595b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 596956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (psyOutElement->toolsInfo.msMask[sfb]) { 597956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* allow hole in side channel ? */ 598956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong minEn = L_mpy_ls(psyOutChanL->sfbEnergy[sfb], (minSnrLimit * psyOutChanL->sfbMinSnr[sfb]) >> 16); 599b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 600956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ahFlag[1][sfb] != NO_AH && 601956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong minEn > psyOutChanR->sfbEnergy[sfb]) { 602b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ahFlag[1][sfb] = NO_AH; 603956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChanR->sfbThreshold[sfb] = L_add(psyOutChanR->sfbEnergy[sfb], psyOutChanR->sfbEnergy[sfb]); 604956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong actPe = actPe - peData->peChannelData[1].sfbPe[sfb]; 605956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 606956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* allow hole in mid channel ? */ 607956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 608956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong minEn = L_mpy_ls(psyOutChanR->sfbEnergy[sfb], (minSnrLimit * psyOutChanR->sfbMinSnr[sfb]) >> 16); 609b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 610956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ahFlag[0][sfb]!= NO_AH && 611956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong minEn > psyOutChanL->sfbEnergy[sfb]) { 612b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ahFlag[0][sfb] = NO_AH; 613956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChanL->sfbThreshold[sfb] = L_add(psyOutChanL->sfbEnergy[sfb], psyOutChanL->sfbEnergy[sfb]); 614956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong actPe = actPe - peData->peChannelData[0].sfbPe[sfb]; 615956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 616956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 617b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 618956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (actPe < desiredPe) 619956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong break; 620956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 621956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 622956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 623956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 624b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard /* subsequently erase bands */ 625956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (actPe > desiredPe) { 626956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 startSfb[2]; 627956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 avgEn, minEn; 628956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ahCnt; 629956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 enIdx; 630956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 enDiff; 631956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 en[4]; 632956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 minSfb, maxSfb; 633956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Flag done; 634956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 635956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* do not go below startSfb */ 636956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (ch=0; ch<nChannels; ch++) { 637b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 638956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (psyOutChannel[ch].windowSequence != SHORT_WINDOW) 639956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong startSfb[ch] = ahParam->startSfbL; 640956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 641956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong startSfb[ch] = ahParam->startSfbS; 642956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 643956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 644b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard avgEn = 0; 645b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard minEn = MAX_32; 646b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ahCnt = 0; 647956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (ch=0; ch<nChannels; ch++) { 648956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 649956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=startSfb[ch]; sfb<psyOutChan->sfbCnt; sfb++) { 650b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 651956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((ahFlag[ch][sfb] != NO_AH) && 652956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (psyOutChan->sfbEnergy[sfb] > psyOutChan->sfbThreshold[sfb])) { 653956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong minEn = min(minEn, psyOutChan->sfbEnergy[sfb]); 654956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfb]); 655956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ahCnt++; 656956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 657956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 658956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 659b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 660956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if(ahCnt) { 661956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 iahCnt; 662e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard shift = norm_l(ahCnt); 663956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong iahCnt = Div_32( 1 << shift, ahCnt << shift ); 664956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgEn = fixmul(avgEn, iahCnt); 665956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 666956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 667956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong enDiff = iLog4(avgEn) - iLog4(minEn); 668956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calc some energy borders between minEn and avgEn */ 669956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (enIdx=0; enIdx<4; enIdx++) { 670956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 enFac; 671956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong enFac = ((6-(enIdx << 1)) * enDiff); 672956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong en[enIdx] = fixmul(avgEn, pow2_xy(L_negate(enFac),7*4)); 673956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 674956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 675956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* start with lowest energy border at highest sfb */ 676956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong maxSfb = psyOutChannel[0].sfbCnt - 1; 677b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard minSfb = startSfb[0]; 678b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 679956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (nChannels == 2) { 680956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong maxSfb = max(maxSfb, (psyOutChannel[1].sfbCnt - 1)); 681956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong minSfb = min(minSfb, startSfb[1]); 682956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 683956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 684b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sfb = maxSfb; 685b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard enIdx = 0; 686b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard done = 0; 687956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong while (!done) { 688b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 689956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (ch=0; ch<nChannels; ch++) { 690956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 691b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 692956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (sfb>=startSfb[ch] && sfb<psyOutChan->sfbCnt) { 693956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* sfb energy below border ? */ 694b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 695956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ahFlag[ch][sfb] != NO_AH && psyOutChan->sfbEnergy[sfb] < en[enIdx]){ 696956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* allow hole */ 697b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ahFlag[ch][sfb] = NO_AH; 698956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChan->sfbThreshold[sfb] = L_add(psyOutChan->sfbEnergy[sfb], psyOutChan->sfbEnergy[sfb]); 699956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong actPe = actPe - peData->peChannelData[ch].sfbPe[sfb]; 700956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 701b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 702956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (actPe < desiredPe) { 703b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard done = 1; 704956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong break; 705956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 706956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 707956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 708956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfb = sfb - 1; 709b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 710956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (sfb < minSfb) { 711956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* restart with next energy border */ 712b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sfb = maxSfb; 713956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong enIdx = enIdx + 1; 714b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 715956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (enIdx - 4 >= 0) 716b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard done = 1; 717956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 718956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 719956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 720956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 721956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 722956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 723956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 724956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:adaptThresholdsToPe 725956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: two guesses for the reduction value and one final correction of the 726956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* thresholds 727956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 728956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 729956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void adaptThresholdsToPe(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 730956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_ELEMENT *psyOutElement, 731956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], 732956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PE_DATA *peData, 733956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels, 734956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 desiredPe, 735956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AH_PARAM *ahParam, 736956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong MINSNR_ADAPT_PARAM *msaParam) 737956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 738956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 noRedPe, redPe, redPeNoAH; 739956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 constPart, constPartNoAH; 740956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 nActiveLines, nActiveLinesNoAH; 741956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 desiredPeNoAH; 742956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 redVal, avgThrExp; 743956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 iter; 744956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 745956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong calcThreshExp(peData->thrExp, psyOutChannel, nChannels); 746956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 747956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong adaptMinSnr(psyOutChannel, logSfbEnergy, msaParam, nChannels); 748956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 749956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong initAvoidHoleFlag(peData->ahFlag, psyOutChannel, psyOutElement, nChannels, ahParam); 750956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 751b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard noRedPe = peData->pe; 752b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard constPart = peData->constPart; 753b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard nActiveLines = peData->nActiveLines; 754956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 755956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* first guess of reduction value t^0.25 = 2^((a-pen)/4*b) */ 756956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgThrExp = pow2_xy((constPart - noRedPe), (nActiveLines << 2)); 757b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 758956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* r1 = 2^((a-per)/4*b) - t^0.25 */ 759956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong redVal = pow2_xy((constPart - desiredPe), (nActiveLines << 2)) - avgThrExp; 760956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 761956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* reduce thresholds */ 762956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal); 763956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 764956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* pe after first guess */ 765956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong calcSfbPe(peData, psyOutChannel, nChannels); 766b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard redPe = peData->pe; 767956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 768b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard iter = 0; 769956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong do { 770956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* pe for bands where avoid hole is inactive */ 771956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong calcPeNoAH(&redPeNoAH, &constPartNoAH, &nActiveLinesNoAH, 772956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong peData, peData->ahFlag, psyOutChannel, nChannels); 773956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 774956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong desiredPeNoAH = desiredPe -(redPe - redPeNoAH); 775b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 776956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (desiredPeNoAH < 0) { 777b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard desiredPeNoAH = 0; 778956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 779956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 780956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* second guess */ 781b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 782956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (nActiveLinesNoAH > 0) { 783b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 784956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgThrExp = pow2_xy((constPartNoAH - redPeNoAH), (nActiveLinesNoAH << 2)); 785b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 786956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong redVal = (redVal + pow2_xy((constPartNoAH - desiredPeNoAH), (nActiveLinesNoAH << 2))) - avgThrExp; 787b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 788956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* reduce thresholds */ 789956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal); 790956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 791956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 792956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong calcSfbPe(peData, psyOutChannel, nChannels); 793b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard redPe = peData->pe; 794956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 795956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong iter = iter+1; 796b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 797956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } while ((20 * abs_s(redPe - desiredPe) > desiredPe) && (iter < 2)); 798956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 799b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 800956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((100 * redPe < 115 * desiredPe)) { 801956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong correctThresh(psyOutChannel, peData->ahFlag, peData, peData->thrExp, redVal, 802956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong nChannels, desiredPe - redPe); 803956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 804956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 805956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 desiredPe105 = (105 * desiredPe) / 100; 806956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong reduceMinSnr(psyOutChannel, peData, peData->ahFlag, 807956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong nChannels, desiredPe105); 808956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong allowMoreHoles(psyOutChannel, psyOutElement, peData, peData->ahFlag, 809956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ahParam, nChannels, desiredPe105); 810956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 811956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 812956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 813956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 814956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 815956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 816956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: calcBitSave 817956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Calculates percentage of bit save, see figure below 818956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: 819956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input: parameters and bitres-fullness 820956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output: percentage of bit save 821956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 822956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 823956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 calcBitSave(Word16 fillLevel, 824956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 clipLow, 825956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 clipHigh, 826956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 minBitSave, 827956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 maxBitSave) 828956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 829956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 bitsave = 0; 830956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 831956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong fillLevel = max(fillLevel, clipLow); 832956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong fillLevel = min(fillLevel, clipHigh); 833956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 834e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if(clipHigh-clipLow) 835956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitsave = (maxBitSave - (((maxBitSave-minBitSave)*(fillLevel-clipLow))/ 836956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (clipHigh-clipLow))); 837956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 838956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return (bitsave); 839956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 840956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 841956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 842956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 843956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 844956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 845956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: calcBitSpend 846956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Calculates percentage of bit spend, see figure below 847956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: 848956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input: parameters and bitres-fullness 849956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output: percentage of bit spend 850956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 851956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 852956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 calcBitSpend(Word16 fillLevel, 853956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 clipLow, 854956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 clipHigh, 855956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 minBitSpend, 856956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 maxBitSpend) 857956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 858956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 bitspend = 1; 859956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 860956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong fillLevel = max(fillLevel, clipLow); 861956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong fillLevel = min(fillLevel, clipHigh); 862956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 863e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if(clipHigh-clipLow) 864956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitspend = (minBitSpend + ((maxBitSpend - minBitSpend)*(fillLevel - clipLow) / 865956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (clipHigh-clipLow))); 866b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 867956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return (bitspend); 868956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 869956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 870956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 871956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 872956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 873956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: adjustPeMinMax() 874956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: adjusts peMin and peMax parameters over time 875956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: 876956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input: current pe, peMin, peMax 877956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output: adjusted peMin/peMax 878956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 879956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 880956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void adjustPeMinMax(const Word16 currPe, 881956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *peMin, 882956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *peMax) 883956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 884956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 minFacHi, maxFacHi, minFacLo, maxFacLo; 885956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 diff; 886956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 minDiff = extract_l(currPe / 6); 887b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard minFacHi = 30; 888b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard maxFacHi = 100; 889b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard minFacLo = 14; 890b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard maxFacLo = 7; 891956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 892956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong diff = currPe - *peMax ; 893b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 894956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (diff > 0) { 895956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMin = *peMin + ((diff * minFacHi) / 100); 896956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMax = *peMax + ((diff * maxFacHi) / 100); 897956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } else { 898956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong diff = *peMin - currPe; 899b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 900956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (diff > 0) { 901956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMin = *peMin - ((diff * minFacLo) / 100); 902956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMax = *peMax - ((diff * maxFacLo) / 100); 903956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } else { 904956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMin = *peMin + ((currPe - *peMin) * minFacHi / 100); 905956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMax = *peMax - ((*peMax - currPe) * maxFacLo / 100); 906956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 907956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 908956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 909b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 910956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((*peMax - *peMin) < minDiff) { 911956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 partLo, partHi; 912956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 913956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong partLo = max(0, (currPe - *peMin)); 914956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong partHi = max(0, (*peMax - currPe)); 915956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 916956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMax = currPe + ((partHi * minDiff) / (partLo + partHi)); 917956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMin = currPe - ((partLo * minDiff) / (partLo + partHi)); 918956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMin = max(0, *peMin); 919956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 920956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 921956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 922956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 923956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 924956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 925956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: BitresCalcBitFac 926956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: calculates factor of spending bits for one frame 927956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 1.0 : take all frame dynpart bits 928956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* >1.0 : take all frame dynpart bits + bitres 929956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* <1.0 : put bits in bitreservoir 930956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: BitFac*100 931956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input: bitres-fullness, pe, blockType, parameter-settings 932956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output: 933956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 934956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 935956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 bitresCalcBitFac( const Word16 bitresBits, 936956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 maxBitresBits, 937956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 pe, 938956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 windowSequence, 939956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 avgBits, 940956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 maxBitFac, 941956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ADJ_THR_STATE *AdjThr, 942956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ATS_ELEMENT *adjThrChan) 943956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 944956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong BRES_PARAM *bresParam; 945956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 pex; 946956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 fillLevel; 947956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 bitSave, bitSpend, bitresFac; 948956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 949956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong fillLevel = extract_l((100* bitresBits) / maxBitresBits); 950956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 951956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (windowSequence != SHORT_WINDOW) 952956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bresParam = &(AdjThr->bresParamLong); 953956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 954956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bresParam = &(AdjThr->bresParamShort); 955956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 956956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pex = max(pe, adjThrChan->peMin); 957956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pex = min(pex,adjThrChan->peMax); 958956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 959956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitSave = calcBitSave(fillLevel, 960956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bresParam->clipSaveLow, bresParam->clipSaveHigh, 961956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bresParam->minBitSave, bresParam->maxBitSave); 962956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 963956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitSpend = calcBitSpend(fillLevel, 964956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bresParam->clipSpendLow, bresParam->clipSpendHigh, 965956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bresParam->minBitSpend, bresParam->maxBitSpend); 966956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 967e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if(adjThrChan->peMax != adjThrChan->peMin) 968956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitresFac = (100 - bitSave) + extract_l(((bitSpend + bitSave) * (pex - adjThrChan->peMin)) / 969956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (adjThrChan->peMax - adjThrChan->peMin)); 970956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 971956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitresFac = 0x7fff; 972b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 973956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitresFac = min(bitresFac, 974956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (100-30 + extract_l((100 * bitresBits) / avgBits))); 975956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 976956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitresFac = min(bitresFac, maxBitFac); 977956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 978956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax); 979956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 980956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return bitresFac; 981956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 982956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 983956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 984956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 985956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: AdjThrInit 986956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: init thresholds parameter 987956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 988956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 989956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid AdjThrInit(ADJ_THR_STATE *hAdjThr, 990956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word32 meanPe, 991956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 chBitrate) 992956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 993956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ATS_ELEMENT* atsElem = &hAdjThr->adjThrStateElem; 994956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam; 995956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 996956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* common for all elements: */ 997956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* parameters for bitres control */ 998b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.clipSaveLow = 20; 999b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.clipSaveHigh = 95; 1000b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.minBitSave = -5; 1001b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.maxBitSave = 30; 1002b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.clipSpendLow = 20; 1003b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.clipSpendHigh = 95; 1004b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.minBitSpend = -10; 1005b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.maxBitSpend = 40; 1006b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1007b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.clipSaveLow = 20; 1008b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.clipSaveHigh = 75; 1009b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.minBitSave = 0; 1010b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.maxBitSave = 20; 1011b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.clipSpendLow = 20; 1012b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.clipSpendHigh = 75; 1013b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.minBitSpend = -5; 1014b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.maxBitSpend = 50; 1015956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1016956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* specific for each element: */ 1017956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1018956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* parameters for bitres control */ 1019956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->peMin = extract_l(((80*meanPe) / 100)); 1020956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->peMax = extract_l(((120*meanPe) / 100)); 1021956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1022956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* additional pe offset to correct pe2bits for low bitrates */ 1023b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard atsElem->peOffset = 0; 1024956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (chBitrate < 32000) { 1025956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->peOffset = max(50, (100 - extract_l((100 * chBitrate) / 32000))); 1026956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1027956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1028956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* avoid hole parameters */ 1029956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (chBitrate > 20000) { 1030956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->ahParam.modifyMinSnr = TRUE; 1031956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->ahParam.startSfbL = 15; 1032956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->ahParam.startSfbS = 3; 1033956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1034956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 1035956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->ahParam.modifyMinSnr = FALSE; 1036956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->ahParam.startSfbL = 0; 1037956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->ahParam.startSfbS = 0; 1038956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1039956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1040956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* minSnr adaptation */ 1041956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* maximum reduction of minSnr goes down to minSnr^maxRed */ 104260866592ed6953f2b0e12cefcd58f1ced26546d0Martin Storsjo msaParam->maxRed = 0x20000000; /* *0.25f */ 1043956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* start adaptation of minSnr for avgEn/sfbEn > startRatio */ 1044b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard msaParam->startRatio = 0x0ccccccd; /* 10 */ 1045956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* maximum minSnr reduction to minSnr^maxRed is reached for 1046956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgEn/sfbEn >= maxRatio */ 1047b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard msaParam->maxRatio = 0x0020c49c; /* 1000 */ 1048956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* helper variables to interpolate minSnr reduction for 1049956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgEn/sfbEn between startRatio and maxRatio */ 1050956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1051b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard msaParam->redRatioFac = 0xfb333333; /* -0.75/20 */ 1052b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1053b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard msaParam->redOffs = 0x30000000; /* msaParam->redRatioFac * 10*log10(msaParam->startRatio) */ 1054956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1055956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1056956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* pe correction */ 1057b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard atsElem->peLast = 0; 1058b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard atsElem->dynBitsLast = 0; 1059b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard atsElem->peCorrectionFactor = 100; /* 1.0 */ 1060956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1061956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 1062956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1063956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 1064956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 1065956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: calcPeCorrection 1066956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: calculates the desired perceptual entropy factor 1067956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* It is between 0.85 and 1.15 1068956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 1069956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 1070956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void calcPeCorrection(Word16 *correctionFac, 1071956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 peAct, 1072b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard const Word16 peLast, 1073b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard const Word16 bitsLast) 1074956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 1075956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 peAct100 = 100 * peAct; 1076956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 peLast100 = 100 * peLast; 1077956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 peBitsLast = bits2pe(bitsLast); 1078b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1079956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((bitsLast > 0) && 1080956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (peAct100 < (150 * peLast)) && (peAct100 > (70 * peLast)) && 1081956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ((120 * peBitsLast) > peLast100 ) && (( 65 * peBitsLast) < peLast100)) 1082956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong { 1083956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 newFac = (100 * peLast) / peBitsLast; 1084956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* dead zone */ 1085b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1086956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (newFac < 100) { 1087956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong newFac = min(((110 * newFac) / 100), 100); 1088956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong newFac = max(newFac, 85); 1089956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1090956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 1091956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong newFac = max(((90 * newFac) / 100), 100); 1092956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong newFac = min(newFac, 115); 1093956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1094b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1095956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((newFac > 100 && *correctionFac < 100) || 1096956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (newFac < 100 && *correctionFac > 100)) { 1097b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *correctionFac = 100; 1098956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1099956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* faster adaptation towards 1.0, slower in the other direction */ 1100b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1101956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((*correctionFac < 100 && newFac < *correctionFac) || 1102956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (*correctionFac > 100 && newFac > *correctionFac)) 1103956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *correctionFac = (85 * *correctionFac + 15 * newFac) / 100; 1104956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 1105956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *correctionFac = (70 * *correctionFac + 30 * newFac) / 100; 1106956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *correctionFac = min(*correctionFac, 115); 1107956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *correctionFac = max(*correctionFac, 85); 1108956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1109956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 1110b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *correctionFac = 100; 1111956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1112956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 1113956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1114956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 1115956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 1116956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: AdjustThresholds 1117956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Adjust thresholds to the desired bitrate 1118956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 1119956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 1120956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid AdjustThresholds(ADJ_THR_STATE *adjThrState, 1121956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ATS_ELEMENT *AdjThrStateElement, 1122956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 1123956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_ELEMENT *psyOutElement, 1124956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *chBitDistribution, 1125956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], 1126b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB], 1127956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong QC_OUT_ELEMENT *qcOE, 1128956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ELEMENT_BITS *elBits, 1129956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels, 1130956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 maxBitFac) 1131956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 1132b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard PE_DATA peData; 1133956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 noRedPe, grantedPe, grantedPeCorr; 1134956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 curWindowSequence; 1135956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 bitFactor; 1136956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 avgBits = (elBits->averageBits - (qcOE->staticBitsUsed + qcOE->ancBitsUsed)); 1137b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard Word16 bitresBits = elBits->bitResLevel; 1138956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 maxBitresBits = elBits->maxBits; 1139956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 sideInfoBits = (qcOE->staticBitsUsed + qcOE->ancBitsUsed); 1140956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ch; 1141b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1142956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong prepareSfbPe(&peData, psyOutChannel, logSfbEnergy, sfbNRelevantLines, nChannels, AdjThrStateElement->peOffset); 1143b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1144956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* pe without reduction */ 1145956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong calcSfbPe(&peData, psyOutChannel, nChannels); 1146b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard noRedPe = peData.pe; 1147956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1148956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1149b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard curWindowSequence = LONG_WINDOW; 1150b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1151956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (nChannels == 2) { 1152b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1153956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((psyOutChannel[0].windowSequence == SHORT_WINDOW) || 1154956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (psyOutChannel[1].windowSequence == SHORT_WINDOW)) { 1155b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard curWindowSequence = SHORT_WINDOW; 1156956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1157956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1158956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 1159b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard curWindowSequence = psyOutChannel[0].windowSequence; 1160956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1161956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1162956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1163956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* bit factor */ 1164956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitFactor = bitresCalcBitFac(bitresBits, maxBitresBits, noRedPe+5*sideInfoBits, 1165956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong curWindowSequence, avgBits, maxBitFac, 1166956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong adjThrState, 1167956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AdjThrStateElement); 1168956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1169956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* desired pe */ 1170956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong grantedPe = ((bitFactor * bits2pe(avgBits)) / 100); 1171956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1172956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* correction of pe value */ 1173b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard calcPeCorrection(&(AdjThrStateElement->peCorrectionFactor), 1174956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong min(grantedPe, noRedPe), 1175b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard AdjThrStateElement->peLast, 1176956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AdjThrStateElement->dynBitsLast); 1177956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong grantedPeCorr = (grantedPe * AdjThrStateElement->peCorrectionFactor) / 100; 1178956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1179b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1180956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (grantedPeCorr < noRedPe && noRedPe > peData.offset) { 1181956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calc threshold necessary for desired pe */ 1182956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong adaptThresholdsToPe(psyOutChannel, 1183956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutElement, 1184956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong logSfbEnergy, 1185956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong &peData, 1186956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong nChannels, 1187956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong grantedPeCorr, 1188956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong &AdjThrStateElement->ahParam, 1189956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong &AdjThrStateElement->minSnrAdaptParam); 1190956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1191956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1192956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calculate relative distribution */ 1193956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (ch=0; ch<nChannels; ch++) { 1194956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 peOffsDiff = peData.pe - peData.offset; 1195b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard chBitDistribution[ch] = 200; 1196b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1197956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (peOffsDiff > 0) { 1198956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 temp = 1000 - (nChannels * 200); 1199e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard chBitDistribution[ch] = chBitDistribution[ch] + 1200956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (temp * peData.peChannelData[ch].pe) / peOffsDiff; 1201956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1202956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1203956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1204956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* store pe */ 1205b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard qcOE->pe = noRedPe; 1206956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1207956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* update last pe */ 1208b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard AdjThrStateElement->peLast = grantedPe; 1209956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 1210956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1211956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 1212956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 1213956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: AdjThrUpdate 1214956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: save dynBitsUsed for correction of bits2pe relation 1215956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 1216956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 1217956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid AdjThrUpdate(ATS_ELEMENT *AdjThrStateElement, 1218956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 dynBitsUsed) 1219956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 1220b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard AdjThrStateElement->dynBitsLast = dynBitsUsed; 1221956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 1222956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1223956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1224