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 23b5325c8a8fff4d735c24d9a8138e4213ee0833d5Martin Storsjo/* Include system headers before local headers - the local headers 24b5325c8a8fff4d735c24d9a8138e4213ee0833d5Martin Storsjo * redefine __inline, which can mess up definitions in libc headers if 25b5325c8a8fff4d735c24d9a8138e4213ee0833d5Martin Storsjo * they happen to use __inline. */ 26b5325c8a8fff4d735c24d9a8138e4213ee0833d5Martin Storsjo#include <string.h> 27e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "basic_op.h" 28956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "oper_32b.h" 29956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "adj_thr_data.h" 30956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "adj_thr.h" 31956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "qc_data.h" 32956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "line_pe.h" 33956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 34956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 35956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#define minSnrLimit 0x6666 /* 1 dB */ 36e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define PEBITS_COEF 0x170a /* 0.18*(1 << 15)*/ 37e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 38e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define HOLE_THR_LONG 0x2873 /* 0.316*(1 << 15) */ 39e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define HOLE_THR_SHORT 0x4000 /* 0.5 *(1 << 15) */ 40e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 41e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define MS_THRSPREAD_COEF 0x7333 /* 0.9 * (1 << 15) */ 42e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 43e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define MIN_SNR_COEF 0x651f /* 3.16* (1 << (15 - 2)) */ 44956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 45956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/* values for avoid hole flag */ 46956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongenum _avoid_hole_state { 47956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong NO_AH =0, 48956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AH_INACTIVE =1, 49956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AH_ACTIVE =2 50956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}; 51956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 52956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 53956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 54956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:bits2pe 55956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: convert from bits to pe 56956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* pe = 1.18*desiredBits 57956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 58956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 59956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongWord16 bits2pe(const Word16 bits) { 60956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return (bits + ((PEBITS_COEF * bits) >> 15)); 61956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 62956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 63956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 64956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 65956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:calcThreshExp 66956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: loudness calculation (threshold to the power of redExp) 67956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* thr(n)^0.25 68956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 69956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 70956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void calcThreshExp(Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB], 71956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 72956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels) 73956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 74e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word16 ch, sfb, sfbGrp; 75d411b4ca2945cd8974a3a78199fce94646950128Andreas Huber Word32 *pthrExp = NULL, *psfbThre; 76956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (ch=0; ch<nChannels; ch++) { 77e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 78b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard for(sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; sfbGrp+= psyOutChan->sfbPerGroup) 79e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard pthrExp = &(thrExp[ch][sfbGrp]); 80e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psfbThre = psyOutChan->sfbThreshold + sfbGrp; 81956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 82e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard *pthrExp = rsqrt(rsqrt(*psfbThre,INT_BITS),INT_BITS); 83956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pthrExp++; psfbThre++; 84956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 85956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 86956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 87956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 88956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 89956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 90956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:adaptMinSnr 91956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: reduce minSnr requirements for bands with relative low energies 92956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 93956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 94956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void adaptMinSnr(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 95956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], 96956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong MINSNR_ADAPT_PARAM *msaParam, 97956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels) 98956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 99b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe Word16 ch, sfb, sfbOffs; 100956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 nSfb, avgEn; 101956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 log_avgEn = 0; 102956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 startRatio_x_avgEn = 0; 103b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 104956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 105956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (ch=0; ch<nChannels; ch++) { 106956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL* psyOutChan = &psyOutChannel[ch]; 107956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 108956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calc average energy per scalefactor band */ 109b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard avgEn = 0; 110b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard nSfb = 0; 111956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) { 112956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 113956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfbOffs+sfb]); 114956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong nSfb = nSfb + 1; 115956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 116956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 117b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 118956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (nSfb > 0) { 119e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard avgEn = avgEn / nSfb; 120956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 121956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong log_avgEn = iLog4(avgEn); 122956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong startRatio_x_avgEn = fixmul(msaParam->startRatio, avgEn); 123956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 124956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 125b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 126956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */ 127956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) { 128956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 129956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (psyOutChan->sfbEnergy[sfbOffs+sfb] < startRatio_x_avgEn) { 130956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 dbRatio, minSnrRed; 131956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 snrRed; 132956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 newMinSnr; 133b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 134956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong dbRatio = log_avgEn - logSfbEnergy[ch][sfbOffs+sfb]; 135956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong dbRatio = dbRatio + (dbRatio << 1); 136956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 137956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong minSnrRed = 110 - ((dbRatio + (dbRatio << 1)) >> 2); 138b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard minSnrRed = max(minSnrRed, 20); /* 110: (0.375(redOffs)+1)*80, 139956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 3: 0.00375(redRatioFac)*80 140956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 20: 0.25(maxRed) * 80 */ 141956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 142b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard snrRed = minSnrRed * iLog4((psyOutChan->sfbMinSnr[sfbOffs+sfb] << 16)); 143b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard /* 144956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong snrRedI si now scaled by 80 (minSnrRed) and 4 (ffr_iLog4) 145956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong */ 146b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 147956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong newMinSnr = round16(pow2_xy(snrRed,80*4)); 148b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 149956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChan->sfbMinSnr[sfbOffs+sfb] = min(newMinSnr, minSnrLimit); 150956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 151956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 152956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 153956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 154956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 155956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 156956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 157956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 158956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 159956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 160956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:initAvoidHoleFlag 161956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: determine bands where avoid hole is not necessary resp. possible 162956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 163956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 164956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void initAvoidHoleFlag(Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], 165956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 166956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_ELEMENT* psyOutElement, 167956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels, 168956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AH_PARAM *ahParam) 169956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 170956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ch, sfb, sfbGrp, shift; 171956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 threshold; 172956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32* psfbSpreadEn; 173956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 174956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (ch=0; ch<nChannels; ch++) { 175956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 176b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 177956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (psyOutChan->windowSequence != SHORT_WINDOW) { 178956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ 179e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp; 180956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 181e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard *psfbSpreadEn = *psfbSpreadEn >> 1; /* 0.5 */ 182956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ++psfbSpreadEn; 183956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 184956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 185956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 186956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 187e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ 188956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp; 189956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 190e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard *psfbSpreadEn = (*psfbSpreadEn >> 1) + (*psfbSpreadEn >> 3); /* 0.63 */ 191956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ++psfbSpreadEn; 192956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 193956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 194956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 195956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 196956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 197956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* increase minSnr for local peaks, decrease it for valleys */ 198956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ahParam->modifyMinSnr) { 199956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(ch=0; ch<nChannels; ch++) { 200956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 201b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 202956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (psyOutChan->windowSequence != SHORT_WINDOW) 203956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong threshold = HOLE_THR_LONG; 204956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 205956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong threshold = HOLE_THR_SHORT; 206956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 207956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ 208e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word16 *psfbMinSnr = psyOutChan->sfbMinSnr + sfbGrp; 209956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 210956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sfbEn, sfbEnm1, sfbEnp1, avgEn; 211b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 212956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (sfb > 0) 213956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp+sfb-1]; 214956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 215956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp]; 216b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 217956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (sfb < (psyOutChan->maxSfbPerGroup-1)) 218956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb+1]; 219956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 220956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb]; 221956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgEn = (sfbEnm1 + sfbEnp1) >> 1; 222b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sfbEn = psyOutChan->sfbEnergy[sfbGrp+sfb]; 223b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 224956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (sfbEn > avgEn && avgEn > 0) { 225956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 tmpMinSnr; 226e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard shift = norm_l(sfbEn); 227956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tmpMinSnr = Div_32(L_mpy_ls(avgEn, minSnrLimit) << shift, sfbEn << shift ); 228b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tmpMinSnr = max(tmpMinSnr, HOLE_THR_LONG); 229956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tmpMinSnr = max(tmpMinSnr, threshold); 230956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *psfbMinSnr = min(*psfbMinSnr, tmpMinSnr); 231956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 232956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* valley ? */ 233b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 234956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((sfbEn < (avgEn >> 1)) && (sfbEn > 0)) { 235956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 tmpMinSnr; 236b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard Word32 minSnrEn = L_mpy_wx(avgEn, *psfbMinSnr); 237b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 238e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if(minSnrEn < sfbEn) { 239956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong shift = norm_l(sfbEn); 240956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tmpMinSnr = Div_32( minSnrEn << shift, sfbEn<<shift); 241956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 242956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 243b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard tmpMinSnr = MAX_16; 244956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 245956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tmpMinSnr = min(minSnrLimit, tmpMinSnr); 246956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 247956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *psfbMinSnr = 248956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (min((tmpMinSnr >> 2), mult(*psfbMinSnr, MIN_SNR_COEF)) << 2); 249e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 250956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psfbMinSnr++; 251956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 252956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 253956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 254956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 255956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 256956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* stereo: adapt the minimum requirements sfbMinSnr of mid and 257956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong side channels */ 258b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 259956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (nChannels == 2) { 260956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChanM = &psyOutChannel[0]; 261956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChanS = &psyOutChannel[1]; 262956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChanM->sfbCnt; sfb++) { 263956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (psyOutElement->toolsInfo.msMask[sfb]) { 264956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sfbEnM = psyOutChanM->sfbEnergy[sfb]; 265956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sfbEnS = psyOutChanS->sfbEnergy[sfb]; 266956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 maxSfbEn = max(sfbEnM, sfbEnS); 267b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard Word32 maxThr = L_mpy_wx(maxSfbEn, psyOutChanM->sfbMinSnr[sfb]) >> 1; 268b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 269956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if(maxThr >= sfbEnM) { 270b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard psyOutChanM->sfbMinSnr[sfb] = MAX_16; 271956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 272956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 273b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard shift = norm_l(sfbEnM); 274b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard psyOutChanM->sfbMinSnr[sfb] = min(max(psyOutChanM->sfbMinSnr[sfb], 275956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong round16(Div_32(maxThr<<shift, sfbEnM << shift))), minSnrLimit); 276956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 277b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 278956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if(maxThr >= sfbEnS) { 279956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChanS->sfbMinSnr[sfb] = MAX_16; 280956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 281e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard else { 282956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong shift = norm_l(sfbEnS); 283b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard psyOutChanS->sfbMinSnr[sfb] = min(max(psyOutChanS->sfbMinSnr[sfb], 284956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong round16(Div_32(maxThr << shift, sfbEnS << shift))), minSnrLimit); 285956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 286956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 287b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 288956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (sfbEnM > psyOutChanM->sfbSpreadedEnergy[sfb]) 289956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChanS->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnS, MS_THRSPREAD_COEF); 290b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 291956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (sfbEnS > psyOutChanS->sfbSpreadedEnergy[sfb]) 292956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChanM->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnM, MS_THRSPREAD_COEF); 293956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 294956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 295956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 296956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 297956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 298956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */ 299956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(ch=0; ch<nChannels; ch++) { 300956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 301956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ 302e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word16 *pahFlag = ahFlag[ch] + sfbGrp; 303956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 304b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 305956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((psyOutChan->sfbSpreadedEnergy[sfbGrp+sfb] > psyOutChan->sfbEnergy[sfbGrp+sfb]) || 306956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (psyOutChan->sfbEnergy[sfbGrp+sfb] <= psyOutChan->sfbThreshold[sfbGrp+sfb]) || 307956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (psyOutChan->sfbMinSnr[sfbGrp+sfb] == MAX_16)) { 308956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *pahFlag++ = NO_AH; 309956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 310956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 311956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *pahFlag++ = AH_INACTIVE; 312956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 313956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 314956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=psyOutChan->maxSfbPerGroup; sfb<psyOutChan->sfbPerGroup; sfb++) { 315b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *pahFlag++ = NO_AH; 316956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 317956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 318956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 319956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 320956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 321956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 322956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 323956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:calcPeNoAH 324956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: sum the pe data only for bands where avoid hole is inactive 325956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 326956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 327956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void calcPeNoAH(Word16 *pe, 328956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *constPart, 329956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *nActiveLines, 330956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PE_DATA *peData, 331956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], 332956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 333956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels) 334956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 335e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word16 ch, sfb, sfbGrp; 336956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int ipe, iconstPart, inActiveLines; 337956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 338b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ipe = 0; 339b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard iconstPart = 0; 340b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard inActiveLines = 0; 341956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(ch=0; ch<nChannels; ch++) { 342956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 343956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch]; 344956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ 345956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 346b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 347956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ahFlag[ch][sfbGrp+sfb] < AH_ACTIVE) { 348956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ipe = ipe + peChanData->sfbPe[sfbGrp+sfb]; 349956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong iconstPart = iconstPart + peChanData->sfbConstPart[sfbGrp+sfb]; 350956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong inActiveLines = inActiveLines + peChanData->sfbNActiveLines[sfbGrp+sfb]; 351956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 352956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 353956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 354e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 355956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 356b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *pe = saturate(ipe); 357b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *constPart = saturate(iconstPart); 358b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *nActiveLines = saturate(inActiveLines); 359956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 360956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 361956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 362956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 363956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:reduceThresholds 364956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: apply reduction formula 365956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 366956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 367956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void reduceThresholds(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 368956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], 369956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB], 370956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels, 371956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word32 redVal) 372956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 373956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sfbThrReduced; 374b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard Word32 *psfbEn, *psfbThr; 375e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word16 ch, sfb, sfbGrp; 376956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 377956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(ch=0; ch<nChannels; ch++) { 378956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 379956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(sfbGrp=0; sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) { 380b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard psfbEn = psyOutChan->sfbEnergy + sfbGrp; 381e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psfbThr = psyOutChan->sfbThreshold + sfbGrp; 382956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 383b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 384956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (*psfbEn > *psfbThr) { 385956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* threshold reduction formula */ 386956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 tmp = thrExp[ch][sfbGrp+sfb] + redVal; 387956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tmp = fixmul(tmp, tmp); 388956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbThrReduced = fixmul(tmp, tmp); 389956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* avoid holes */ 390956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong tmp = L_mpy_ls(*psfbEn, psyOutChan->sfbMinSnr[sfbGrp+sfb]); 391b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 392b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard if ((sfbThrReduced > tmp) && 393956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (ahFlag[ch][sfbGrp+sfb] != NO_AH)){ 394956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbThrReduced = max(tmp, *psfbThr); 395b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ahFlag[ch][sfbGrp+sfb] = AH_ACTIVE; 396956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 397956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *psfbThr = sfbThrReduced; 398e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 399e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 400956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psfbEn++; psfbThr++; 401956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 402956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 403956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 404956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 405956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 406956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 407956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 408956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 409956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:correctThresh 410956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: if pe difference deltaPe between desired pe and real pe is small enough, 411956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* the difference can be distributed among the scale factor bands. 412956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 413956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 414956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void correctThresh(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 415956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], 416956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PE_DATA *peData, 417956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB], 418956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word32 redVal, 419956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels, 420956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word32 deltaPe) 421956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 422956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ch, sfb, sfbGrp,shift; 423956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan; 424956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PE_CHANNEL_DATA *peChanData; 425956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 deltaSfbPe; 426e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word32 normFactor; 427e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Word32 *psfbPeFactors; 428956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *psfbNActiveLines, *pahFlag; 429956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sfbEn, sfbThr; 430956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 sfbThrReduced; 431956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 432956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* for each sfb calc relative factors for pe changes */ 433b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard normFactor = 1; 434956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(ch=0; ch<nChannels; ch++) { 435956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChan = &psyOutChannel[ch]; 436956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong peChanData = &peData->peChannelData[ch]; 437956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ 438e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp; 439e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp; 440e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard pahFlag = ahFlag[ch] + sfbGrp; 441956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 442956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 redThrExp = thrExp[ch][sfbGrp+sfb] + redVal; 443b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 444dcdfc1ad27cb64bcb51a864b020b846ba22ce2a7Martin Storsjo if (((*pahFlag < AH_ACTIVE) || (deltaPe > 0)) && (redThrExp > 0) && (redThrExp >= *psfbNActiveLines)) { 445b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 446956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *psfbPeFactors = (*psfbNActiveLines) * (0x7fffffff / redThrExp); 447956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong normFactor = L_add(normFactor, *psfbPeFactors); 448956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 449956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 450b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *psfbPeFactors = 0; 451e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 452b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard psfbPeFactors++; 453956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pahFlag++; psfbNActiveLines++; 454956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 455956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 456956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 457956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 458b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 459956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calculate new thresholds */ 460956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(ch=0; ch<nChannels; ch++) { 461956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChan = &psyOutChannel[ch]; 462956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong peChanData = &peData->peChannelData[ch]; 463956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ 464e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp; 465e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp; 466e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard pahFlag = ahFlag[ch] + sfbGrp; 467956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 468956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* pe difference for this sfb */ 469956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong deltaSfbPe = *psfbPeFactors * deltaPe; 470956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 471b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard /* thr3(n) = thr2(n)*2^deltaSfbPe/b(n) */ 47201e29ede19cd7d85bfef38896de8e71e569cd211Martin Storsjo if (*psfbNActiveLines > 0 && (normFactor* (*psfbNActiveLines)) != 0) { 473956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* new threshold */ 474956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 thrFactor; 475956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbEn = psyOutChan->sfbEnergy[sfbGrp+sfb]; 476956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbThr = psyOutChan->sfbThreshold[sfbGrp+sfb]; 477956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 478956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if(deltaSfbPe >= 0){ 479956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* 480956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong reduce threshold 481956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong */ 482956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong thrFactor = pow2_xy(L_negate(deltaSfbPe), (normFactor* (*psfbNActiveLines))); 483b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 484956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbThrReduced = L_mpy_ls(sfbThr, round16(thrFactor)); 485956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 486956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 487956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* 488956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong increase threshold 489956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong */ 490956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong thrFactor = pow2_xy(deltaSfbPe, (normFactor * (*psfbNActiveLines))); 491b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 492b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 493956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if(thrFactor > sfbThr) { 494e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard shift = norm_l(thrFactor); 495956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbThrReduced = Div_32( sfbThr << shift, thrFactor<<shift ); 496956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 497956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 498b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sfbThrReduced = MAX_32; 499956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 500956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 501956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 502b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 503956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* avoid hole */ 504956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbEn = L_mpy_ls(sfbEn, psyOutChan->sfbMinSnr[sfbGrp+sfb]); 505b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 506956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((sfbThrReduced > sfbEn) && 507956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (*pahFlag == AH_INACTIVE)) { 508956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbThrReduced = max(sfbEn, sfbThr); 509b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *pahFlag = AH_ACTIVE; 510956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 511956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 512b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard psyOutChan->sfbThreshold[sfbGrp+sfb] = sfbThrReduced; 513e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 514e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 515956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pahFlag++; psfbNActiveLines++; psfbPeFactors++; 516956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 517956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 518956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 519956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 520956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 521956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 522956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 523956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 524956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:reduceMinSnr 525956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: if the desired pe can not be reached, reduce pe by reducing minSnr 526956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 527956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 528b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgardstatic void reduceMinSnr(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 529b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard PE_DATA *peData, 530956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], 531956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels, 532956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 desiredPe) 533956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 534956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ch, sfb, sfbSubWin; 535956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 deltaPe; 536956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 537956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* start at highest freq down to 0 */ 538b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sfbSubWin = psyOutChannel[0].maxSfbPerGroup; 539956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong while (peData->pe > desiredPe && sfbSubWin > 0) { 540b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 541956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfbSubWin = sfbSubWin - 1; 542956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* loop over all subwindows */ 543956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=sfbSubWin; sfb<psyOutChannel[0].sfbCnt; 544956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfb+=psyOutChannel[0].sfbPerGroup) { 545956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* loop over all channels */ 546e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard PE_CHANNEL_DATA* peChan = peData->peChannelData; 547e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard PSY_OUT_CHANNEL* psyOutCh = psyOutChannel; 548b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard for (ch=0; ch<nChannels; ch++) { 549956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ahFlag[ch][sfb] != NO_AH && 550956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutCh->sfbMinSnr[sfb] < minSnrLimit) { 551b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard psyOutCh->sfbMinSnr[sfb] = minSnrLimit; 552956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutCh->sfbThreshold[sfb] = 553956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong L_mpy_ls(psyOutCh->sfbEnergy[sfb], psyOutCh->sfbMinSnr[sfb]); 554956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 555956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calc new pe */ 556956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong deltaPe = ((peChan->sfbNLines4[sfb] + (peChan->sfbNLines4[sfb] >> 1)) >> 2) - 557956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong peChan->sfbPe[sfb]; 558956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong peData->pe = peData->pe + deltaPe; 559b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard peChan->pe = peChan->pe + deltaPe; 560e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 561956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong peChan += 1; psyOutCh += 1; 562956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 563956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* stop if enough has been saved */ 564b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 565956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (peData->pe <= desiredPe) 566956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong break; 567956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 568956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 569956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 570956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 571956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 572956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 573956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:allowMoreHoles 574b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard* description: if the desired pe can not be reached, some more scalefactor bands 575956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* have to be quantized to zero 576956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 577956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 578b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgardstatic void allowMoreHoles(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 579956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_ELEMENT *psyOutElement, 580b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard PE_DATA *peData, 581956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], 582956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const AH_PARAM *ahParam, 583956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels, 584956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 desiredPe) 585956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 586956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ch, sfb; 587956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 actPe, shift; 588956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 589b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard actPe = peData->pe; 590956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 591956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* for MS allow hole in the channel with less energy */ 592b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 593956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (nChannels==2 && 594956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChannel[0].windowSequence==psyOutChannel[1].windowSequence) { 595956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChanL = &psyOutChannel[0]; 596956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChanR = &psyOutChannel[1]; 597956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=0; sfb<psyOutChanL->sfbCnt; sfb++) { 598956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 minEn; 599b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 600956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (psyOutElement->toolsInfo.msMask[sfb]) { 601956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* allow hole in side channel ? */ 602956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong minEn = L_mpy_ls(psyOutChanL->sfbEnergy[sfb], (minSnrLimit * psyOutChanL->sfbMinSnr[sfb]) >> 16); 603b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 604956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ahFlag[1][sfb] != NO_AH && 605956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong minEn > psyOutChanR->sfbEnergy[sfb]) { 606b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ahFlag[1][sfb] = NO_AH; 607956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChanR->sfbThreshold[sfb] = L_add(psyOutChanR->sfbEnergy[sfb], psyOutChanR->sfbEnergy[sfb]); 608956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong actPe = actPe - peData->peChannelData[1].sfbPe[sfb]; 609956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 610956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* allow hole in mid channel ? */ 611956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 612956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong minEn = L_mpy_ls(psyOutChanR->sfbEnergy[sfb], (minSnrLimit * psyOutChanR->sfbMinSnr[sfb]) >> 16); 613b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 614956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ahFlag[0][sfb]!= NO_AH && 615956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong minEn > psyOutChanL->sfbEnergy[sfb]) { 616b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ahFlag[0][sfb] = NO_AH; 617956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChanL->sfbThreshold[sfb] = L_add(psyOutChanL->sfbEnergy[sfb], psyOutChanL->sfbEnergy[sfb]); 618956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong actPe = actPe - peData->peChannelData[0].sfbPe[sfb]; 619956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 620956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 621b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 622956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (actPe < desiredPe) 623956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong break; 624956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 625956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 626956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 627956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 628b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard /* subsequently erase bands */ 629956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (actPe > desiredPe) { 630956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 startSfb[2]; 631956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 avgEn, minEn; 632956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ahCnt; 633956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 enIdx; 634956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 enDiff; 635956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 en[4]; 636956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 minSfb, maxSfb; 637956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Flag done; 638956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 639956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* do not go below startSfb */ 640956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (ch=0; ch<nChannels; ch++) { 641b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 642956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (psyOutChannel[ch].windowSequence != SHORT_WINDOW) 643956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong startSfb[ch] = ahParam->startSfbL; 644956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 645956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong startSfb[ch] = ahParam->startSfbS; 646956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 647956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 648b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard avgEn = 0; 649b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard minEn = MAX_32; 650b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ahCnt = 0; 651956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (ch=0; ch<nChannels; ch++) { 652956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 653956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (sfb=startSfb[ch]; sfb<psyOutChan->sfbCnt; sfb++) { 654b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 655956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((ahFlag[ch][sfb] != NO_AH) && 656956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (psyOutChan->sfbEnergy[sfb] > psyOutChan->sfbThreshold[sfb])) { 657956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong minEn = min(minEn, psyOutChan->sfbEnergy[sfb]); 658956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfb]); 659956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ahCnt++; 660956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 661956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 662956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 663b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 664956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if(ahCnt) { 665956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 iahCnt; 666e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard shift = norm_l(ahCnt); 667956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong iahCnt = Div_32( 1 << shift, ahCnt << shift ); 668956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgEn = fixmul(avgEn, iahCnt); 669956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 670956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 671956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong enDiff = iLog4(avgEn) - iLog4(minEn); 672956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calc some energy borders between minEn and avgEn */ 673956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (enIdx=0; enIdx<4; enIdx++) { 674956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 enFac; 675956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong enFac = ((6-(enIdx << 1)) * enDiff); 676956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong en[enIdx] = fixmul(avgEn, pow2_xy(L_negate(enFac),7*4)); 677956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 678956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 679956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* start with lowest energy border at highest sfb */ 680956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong maxSfb = psyOutChannel[0].sfbCnt - 1; 681b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard minSfb = startSfb[0]; 682b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 683956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (nChannels == 2) { 684956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong maxSfb = max(maxSfb, (psyOutChannel[1].sfbCnt - 1)); 685956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong minSfb = min(minSfb, startSfb[1]); 686956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 687956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 688b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sfb = maxSfb; 689b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard enIdx = 0; 690b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard done = 0; 691956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong while (!done) { 692b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 693956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (ch=0; ch<nChannels; ch++) { 694956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 695b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 696956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (sfb>=startSfb[ch] && sfb<psyOutChan->sfbCnt) { 697956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* sfb energy below border ? */ 698b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 699956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ahFlag[ch][sfb] != NO_AH && psyOutChan->sfbEnergy[sfb] < en[enIdx]){ 700956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* allow hole */ 701b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ahFlag[ch][sfb] = NO_AH; 702956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutChan->sfbThreshold[sfb] = L_add(psyOutChan->sfbEnergy[sfb], psyOutChan->sfbEnergy[sfb]); 703956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong actPe = actPe - peData->peChannelData[ch].sfbPe[sfb]; 704956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 705b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 706956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (actPe < desiredPe) { 707b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard done = 1; 708956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong break; 709956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 710956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 711956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 712956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong sfb = sfb - 1; 713b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 714956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (sfb < minSfb) { 715956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* restart with next energy border */ 716b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard sfb = maxSfb; 717956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong enIdx = enIdx + 1; 718b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 719956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (enIdx - 4 >= 0) 720b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard done = 1; 721956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 722956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 723956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 724956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 725956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 726956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 727956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 728956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name:adaptThresholdsToPe 729956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: two guesses for the reduction value and one final correction of the 730956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* thresholds 731956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 732956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 733956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void adaptThresholdsToPe(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 734956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_ELEMENT *psyOutElement, 735956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], 736956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PE_DATA *peData, 737956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels, 738956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 desiredPe, 739956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AH_PARAM *ahParam, 740956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong MINSNR_ADAPT_PARAM *msaParam) 741956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 742956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 noRedPe, redPe, redPeNoAH; 743956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 constPart, constPartNoAH; 744956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 nActiveLines, nActiveLinesNoAH; 745956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 desiredPeNoAH; 746956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 redVal, avgThrExp; 747956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 iter; 748956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 749956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong calcThreshExp(peData->thrExp, psyOutChannel, nChannels); 750956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 751956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong adaptMinSnr(psyOutChannel, logSfbEnergy, msaParam, nChannels); 752956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 753956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong initAvoidHoleFlag(peData->ahFlag, psyOutChannel, psyOutElement, nChannels, ahParam); 754956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 755b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard noRedPe = peData->pe; 756b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard constPart = peData->constPart; 757b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard nActiveLines = peData->nActiveLines; 758956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 759956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* first guess of reduction value t^0.25 = 2^((a-pen)/4*b) */ 760956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgThrExp = pow2_xy((constPart - noRedPe), (nActiveLines << 2)); 761b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 762956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* r1 = 2^((a-per)/4*b) - t^0.25 */ 763956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong redVal = pow2_xy((constPart - desiredPe), (nActiveLines << 2)) - avgThrExp; 764956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 765956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* reduce thresholds */ 766956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal); 767956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 768956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* pe after first guess */ 769956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong calcSfbPe(peData, psyOutChannel, nChannels); 770b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard redPe = peData->pe; 771956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 772b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard iter = 0; 773956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong do { 774956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* pe for bands where avoid hole is inactive */ 775956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong calcPeNoAH(&redPeNoAH, &constPartNoAH, &nActiveLinesNoAH, 776956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong peData, peData->ahFlag, psyOutChannel, nChannels); 777956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 778956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong desiredPeNoAH = desiredPe -(redPe - redPeNoAH); 779b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 780956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (desiredPeNoAH < 0) { 781b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard desiredPeNoAH = 0; 782956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 783956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 784956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* second guess */ 785b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 786956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (nActiveLinesNoAH > 0) { 787b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 788956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgThrExp = pow2_xy((constPartNoAH - redPeNoAH), (nActiveLinesNoAH << 2)); 789b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 790956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong redVal = (redVal + pow2_xy((constPartNoAH - desiredPeNoAH), (nActiveLinesNoAH << 2))) - avgThrExp; 791b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 792956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* reduce thresholds */ 793956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal); 794956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 795956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 796956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong calcSfbPe(peData, psyOutChannel, nChannels); 797b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard redPe = peData->pe; 798956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 799956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong iter = iter+1; 800b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 801956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } while ((20 * abs_s(redPe - desiredPe) > desiredPe) && (iter < 2)); 802956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 803b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 804956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((100 * redPe < 115 * desiredPe)) { 805956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong correctThresh(psyOutChannel, peData->ahFlag, peData, peData->thrExp, redVal, 806956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong nChannels, desiredPe - redPe); 807956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 808956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 809956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 desiredPe105 = (105 * desiredPe) / 100; 810956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong reduceMinSnr(psyOutChannel, peData, peData->ahFlag, 811956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong nChannels, desiredPe105); 812956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong allowMoreHoles(psyOutChannel, psyOutElement, peData, peData->ahFlag, 813956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ahParam, nChannels, desiredPe105); 814956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 815956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 816956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 817956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 818956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 819956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 820956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: calcBitSave 821956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Calculates percentage of bit save, see figure below 822956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: 823956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input: parameters and bitres-fullness 824956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output: percentage of bit save 825956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 826956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 827956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 calcBitSave(Word16 fillLevel, 828956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 clipLow, 829956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 clipHigh, 830956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 minBitSave, 831956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 maxBitSave) 832956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 833956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 bitsave = 0; 834956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 835956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong fillLevel = max(fillLevel, clipLow); 836956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong fillLevel = min(fillLevel, clipHigh); 837956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 838e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if(clipHigh-clipLow) 839956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitsave = (maxBitSave - (((maxBitSave-minBitSave)*(fillLevel-clipLow))/ 840956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (clipHigh-clipLow))); 841956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 842956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return (bitsave); 843956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 844956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 845956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 846956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 847956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 848956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 849956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: calcBitSpend 850956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Calculates percentage of bit spend, see figure below 851956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: 852956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input: parameters and bitres-fullness 853956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output: percentage of bit spend 854956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 855956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 856956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 calcBitSpend(Word16 fillLevel, 857956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 clipLow, 858956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 clipHigh, 859956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 minBitSpend, 860956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 maxBitSpend) 861956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 862956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 bitspend = 1; 863956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 864956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong fillLevel = max(fillLevel, clipLow); 865956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong fillLevel = min(fillLevel, clipHigh); 866956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 867e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if(clipHigh-clipLow) 868956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitspend = (minBitSpend + ((maxBitSpend - minBitSpend)*(fillLevel - clipLow) / 869956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (clipHigh-clipLow))); 870b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 871956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return (bitspend); 872956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 873956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 874956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 875956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 876956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 877956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: adjustPeMinMax() 878956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: adjusts peMin and peMax parameters over time 879956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: 880956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input: current pe, peMin, peMax 881956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output: adjusted peMin/peMax 882956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 883956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 884956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void adjustPeMinMax(const Word16 currPe, 885956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *peMin, 886956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *peMax) 887956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 888956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 minFacHi, maxFacHi, minFacLo, maxFacLo; 889956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 diff; 890956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 minDiff = extract_l(currPe / 6); 891b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard minFacHi = 30; 892b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard maxFacHi = 100; 893b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard minFacLo = 14; 894b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard maxFacLo = 7; 895956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 896956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong diff = currPe - *peMax ; 897b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 898956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (diff > 0) { 899956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMin = *peMin + ((diff * minFacHi) / 100); 900956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMax = *peMax + ((diff * maxFacHi) / 100); 901956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } else { 902956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong diff = *peMin - currPe; 903b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 904956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (diff > 0) { 905956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMin = *peMin - ((diff * minFacLo) / 100); 906956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMax = *peMax - ((diff * maxFacLo) / 100); 907956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } else { 908956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMin = *peMin + ((currPe - *peMin) * minFacHi / 100); 909956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMax = *peMax - ((*peMax - currPe) * maxFacLo / 100); 910956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 911956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 912956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 913b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 914956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((*peMax - *peMin) < minDiff) { 915956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 partLo, partHi; 916956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 917956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong partLo = max(0, (currPe - *peMin)); 918956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong partHi = max(0, (*peMax - currPe)); 919956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 920956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMax = currPe + ((partHi * minDiff) / (partLo + partHi)); 921956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMin = currPe - ((partLo * minDiff) / (partLo + partHi)); 922956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *peMin = max(0, *peMin); 923956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 924956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 925956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 926956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 927956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 928956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 929956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: BitresCalcBitFac 930956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: calculates factor of spending bits for one frame 931956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 1.0 : take all frame dynpart bits 932956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* >1.0 : take all frame dynpart bits + bitres 933956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* <1.0 : put bits in bitreservoir 934956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* returns: BitFac*100 935956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* input: bitres-fullness, pe, blockType, parameter-settings 936956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* output: 937956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 938956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 939956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic Word16 bitresCalcBitFac( const Word16 bitresBits, 940956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 maxBitresBits, 941956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 pe, 942956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 windowSequence, 943956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 avgBits, 944956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 maxBitFac, 945956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ADJ_THR_STATE *AdjThr, 946956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ATS_ELEMENT *adjThrChan) 947956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 948956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong BRES_PARAM *bresParam; 949956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 pex; 950956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 fillLevel; 951956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 bitSave, bitSpend, bitresFac; 952956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 953956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong fillLevel = extract_l((100* bitresBits) / maxBitresBits); 954956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 955956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (windowSequence != SHORT_WINDOW) 956956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bresParam = &(AdjThr->bresParamLong); 957956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 958956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bresParam = &(AdjThr->bresParamShort); 959956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 960956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pex = max(pe, adjThrChan->peMin); 961956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pex = min(pex,adjThrChan->peMax); 962956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 963956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitSave = calcBitSave(fillLevel, 964956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bresParam->clipSaveLow, bresParam->clipSaveHigh, 965956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bresParam->minBitSave, bresParam->maxBitSave); 966956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 967956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitSpend = calcBitSpend(fillLevel, 968956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bresParam->clipSpendLow, bresParam->clipSpendHigh, 969956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bresParam->minBitSpend, bresParam->maxBitSpend); 970956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 971e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if(adjThrChan->peMax != adjThrChan->peMin) 972956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitresFac = (100 - bitSave) + extract_l(((bitSpend + bitSave) * (pex - adjThrChan->peMin)) / 973956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (adjThrChan->peMax - adjThrChan->peMin)); 974956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 975956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitresFac = 0x7fff; 976b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 977956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitresFac = min(bitresFac, 978956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (100-30 + extract_l((100 * bitresBits) / avgBits))); 979956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 980956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitresFac = min(bitresFac, maxBitFac); 981956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 982956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax); 983956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 984956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return bitresFac; 985956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 986956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 987956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 988956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 989956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: AdjThrInit 990956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: init thresholds parameter 991956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 992956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 993956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid AdjThrInit(ADJ_THR_STATE *hAdjThr, 994956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word32 meanPe, 995956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 chBitrate) 996956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 997956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ATS_ELEMENT* atsElem = &hAdjThr->adjThrStateElem; 998956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam; 999956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1000956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* common for all elements: */ 1001956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* parameters for bitres control */ 1002b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.clipSaveLow = 20; 1003b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.clipSaveHigh = 95; 1004b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.minBitSave = -5; 1005b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.maxBitSave = 30; 1006b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.clipSpendLow = 20; 1007b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.clipSpendHigh = 95; 1008b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.minBitSpend = -10; 1009b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamLong.maxBitSpend = 40; 1010b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1011b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.clipSaveLow = 20; 1012b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.clipSaveHigh = 75; 1013b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.minBitSave = 0; 1014b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.maxBitSave = 20; 1015b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.clipSpendLow = 20; 1016b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.clipSpendHigh = 75; 1017b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.minBitSpend = -5; 1018b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard hAdjThr->bresParamShort.maxBitSpend = 50; 1019956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1020956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* specific for each element: */ 1021956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1022956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* parameters for bitres control */ 1023956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->peMin = extract_l(((80*meanPe) / 100)); 1024956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->peMax = extract_l(((120*meanPe) / 100)); 1025956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1026956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* additional pe offset to correct pe2bits for low bitrates */ 1027b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard atsElem->peOffset = 0; 1028956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (chBitrate < 32000) { 1029956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->peOffset = max(50, (100 - extract_l((100 * chBitrate) / 32000))); 1030956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1031956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1032956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* avoid hole parameters */ 1033956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (chBitrate > 20000) { 1034956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->ahParam.modifyMinSnr = TRUE; 1035956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->ahParam.startSfbL = 15; 1036956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->ahParam.startSfbS = 3; 1037956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1038956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 1039956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->ahParam.modifyMinSnr = FALSE; 1040956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->ahParam.startSfbL = 0; 1041956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong atsElem->ahParam.startSfbS = 0; 1042956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1043956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1044956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* minSnr adaptation */ 1045956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* maximum reduction of minSnr goes down to minSnr^maxRed */ 104660866592ed6953f2b0e12cefcd58f1ced26546d0Martin Storsjo msaParam->maxRed = 0x20000000; /* *0.25f */ 1047956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* start adaptation of minSnr for avgEn/sfbEn > startRatio */ 1048b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard msaParam->startRatio = 0x0ccccccd; /* 10 */ 1049956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* maximum minSnr reduction to minSnr^maxRed is reached for 1050956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgEn/sfbEn >= maxRatio */ 1051b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard msaParam->maxRatio = 0x0020c49c; /* 1000 */ 1052956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* helper variables to interpolate minSnr reduction for 1053956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong avgEn/sfbEn between startRatio and maxRatio */ 1054956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1055b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard msaParam->redRatioFac = 0xfb333333; /* -0.75/20 */ 1056b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1057b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard msaParam->redOffs = 0x30000000; /* msaParam->redRatioFac * 10*log10(msaParam->startRatio) */ 1058956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1059956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1060956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* pe correction */ 1061b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard atsElem->peLast = 0; 1062b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard atsElem->dynBitsLast = 0; 1063b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard atsElem->peCorrectionFactor = 100; /* 1.0 */ 1064956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1065956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 1066956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1067956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/***************************************************************************** 1068956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 1069956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: calcPeCorrection 1070956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: calculates the desired perceptual entropy factor 1071956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* It is between 0.85 and 1.15 1072956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 1073956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong*****************************************************************************/ 1074956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic void calcPeCorrection(Word16 *correctionFac, 1075956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 peAct, 1076b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard const Word16 peLast, 1077b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard const Word16 bitsLast) 1078956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 1079956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 peAct100 = 100 * peAct; 1080956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 peLast100 = 100 * peLast; 1081956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 peBitsLast = bits2pe(bitsLast); 1082b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1083956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((bitsLast > 0) && 1084956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (peAct100 < (150 * peLast)) && (peAct100 > (70 * peLast)) && 1085956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ((120 * peBitsLast) > peLast100 ) && (( 65 * peBitsLast) < peLast100)) 1086956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong { 1087956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 newFac = (100 * peLast) / peBitsLast; 1088956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* dead zone */ 1089b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1090956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (newFac < 100) { 1091956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong newFac = min(((110 * newFac) / 100), 100); 1092956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong newFac = max(newFac, 85); 1093956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1094956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 1095956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong newFac = max(((90 * newFac) / 100), 100); 1096956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong newFac = min(newFac, 115); 1097956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1098b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1099956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((newFac > 100 && *correctionFac < 100) || 1100956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (newFac < 100 && *correctionFac > 100)) { 1101b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *correctionFac = 100; 1102956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1103956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* faster adaptation towards 1.0, slower in the other direction */ 1104b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1105956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((*correctionFac < 100 && newFac < *correctionFac) || 1106956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (*correctionFac > 100 && newFac > *correctionFac)) 1107956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *correctionFac = (85 * *correctionFac + 15 * newFac) / 100; 1108956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else 1109956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *correctionFac = (70 * *correctionFac + 30 * newFac) / 100; 1110956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *correctionFac = min(*correctionFac, 115); 1111956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *correctionFac = max(*correctionFac, 85); 1112956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1113956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 1114b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard *correctionFac = 100; 1115956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1116956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 1117956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1118956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 1119956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 1120956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: AdjustThresholds 1121956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: Adjust thresholds to the desired bitrate 1122956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 1123956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 1124956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid AdjustThresholds(ADJ_THR_STATE *adjThrState, 1125956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ATS_ELEMENT *AdjThrStateElement, 1126956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 1127956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong PSY_OUT_ELEMENT *psyOutElement, 1128956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 *chBitDistribution, 1129956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], 1130b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB], 1131956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong QC_OUT_ELEMENT *qcOE, 1132956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ELEMENT_BITS *elBits, 1133956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 nChannels, 1134956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 maxBitFac) 1135956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 1136b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard PE_DATA peData; 1137956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 noRedPe, grantedPe, grantedPeCorr; 1138956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 curWindowSequence; 1139956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 bitFactor; 1140956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 avgBits = (elBits->averageBits - (qcOE->staticBitsUsed + qcOE->ancBitsUsed)); 1141b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard Word16 bitresBits = elBits->bitResLevel; 1142956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 maxBitresBits = elBits->maxBits; 1143956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 sideInfoBits = (qcOE->staticBitsUsed + qcOE->ancBitsUsed); 1144956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 ch; 1145132e42c04a58e623efa6cd6ca43641cd80db0f05Martin Storsjo memset(&peData, 0, sizeof(peData)); 1146b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1147956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong prepareSfbPe(&peData, psyOutChannel, logSfbEnergy, sfbNRelevantLines, nChannels, AdjThrStateElement->peOffset); 1148b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1149956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* pe without reduction */ 1150956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong calcSfbPe(&peData, psyOutChannel, nChannels); 1151b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard noRedPe = peData.pe; 1152956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1153956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1154b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard curWindowSequence = LONG_WINDOW; 1155b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1156956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (nChannels == 2) { 1157b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1158956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((psyOutChannel[0].windowSequence == SHORT_WINDOW) || 1159956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (psyOutChannel[1].windowSequence == SHORT_WINDOW)) { 1160b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard curWindowSequence = SHORT_WINDOW; 1161956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1162956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1163956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong else { 1164b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard curWindowSequence = psyOutChannel[0].windowSequence; 1165956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1166956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1167956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1168956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* bit factor */ 1169956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bitFactor = bitresCalcBitFac(bitresBits, maxBitresBits, noRedPe+5*sideInfoBits, 1170956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong curWindowSequence, avgBits, maxBitFac, 1171956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong adjThrState, 1172956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AdjThrStateElement); 1173956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1174956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* desired pe */ 1175956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong grantedPe = ((bitFactor * bits2pe(avgBits)) / 100); 1176956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1177956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* correction of pe value */ 1178b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard calcPeCorrection(&(AdjThrStateElement->peCorrectionFactor), 1179956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong min(grantedPe, noRedPe), 1180b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard AdjThrStateElement->peLast, 1181956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong AdjThrStateElement->dynBitsLast); 1182956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong grantedPeCorr = (grantedPe * AdjThrStateElement->peCorrectionFactor) / 100; 1183956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1184b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1185956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (grantedPeCorr < noRedPe && noRedPe > peData.offset) { 1186956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calc threshold necessary for desired pe */ 1187956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong adaptThresholdsToPe(psyOutChannel, 1188956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong psyOutElement, 1189956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong logSfbEnergy, 1190956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong &peData, 1191956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong nChannels, 1192956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong grantedPeCorr, 1193956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong &AdjThrStateElement->ahParam, 1194956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong &AdjThrStateElement->minSnrAdaptParam); 1195956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1196956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1197956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* calculate relative distribution */ 1198956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (ch=0; ch<nChannels; ch++) { 1199956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word16 peOffsDiff = peData.pe - peData.offset; 1200b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard chBitDistribution[ch] = 200; 1201b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 1202956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (peOffsDiff > 0) { 1203956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Word32 temp = 1000 - (nChannels * 200); 1204e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard chBitDistribution[ch] = chBitDistribution[ch] + 1205956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (temp * peData.peChannelData[ch].pe) / peOffsDiff; 1206956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1207956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 1208956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1209956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* store pe */ 1210b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard qcOE->pe = noRedPe; 1211956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1212956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /* update last pe */ 1213b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard AdjThrStateElement->peLast = grantedPe; 1214956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 1215956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1216956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong/******************************************************************************** 1217956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 1218956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* function name: AdjThrUpdate 1219956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* description: save dynBitsUsed for correction of bits2pe relation 1220956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong* 1221956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong**********************************************************************************/ 1222956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid AdjThrUpdate(ATS_ELEMENT *AdjThrStateElement, 1223956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const Word16 dynBitsUsed) 1224956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong{ 1225b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard AdjThrStateElement->dynBitsLast = dynBitsUsed; 1226956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 1227956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1228956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 1229