1 /* 2 ** Copyright 2003-2010, VisualOn, Inc. 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 /******************************************************************************* 17 File: line_pe.c 18 19 Content: Perceptual entropie module functions 20 21 *******************************************************************************/ 22 23 #include "basic_op.h" 24 #include "oper_32b.h" 25 #include "typedef.h" 26 #include "line_pe.h" 27 28 29 static const Word16 C1_I = 12; /* log(8.0)/log(2) *4 */ 30 static const Word32 C2_I = 10830; /* log(2.5)/log(2) * 1024 * 4 * 2 */ 31 static const Word16 C3_I = 573; /* (1-C2/C1) *1024 */ 32 33 34 /***************************************************************************** 35 * 36 * function name: prepareSfbPe 37 * description: constants that do not change during successive pe calculations 38 * 39 **********************************************************************************/ 40 void prepareSfbPe(PE_DATA *peData, 41 PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 42 Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], 43 Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB], 44 const Word16 nChannels, 45 const Word16 peOffset) 46 { 47 Word32 sfbGrp, sfb; 48 Word32 ch; 49 50 for(ch=0; ch<nChannels; ch++) { 51 PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 52 PE_CHANNEL_DATA *peChanData=&peData->peChannelData[ch]; 53 for(sfbGrp=0;sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup){ 54 for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 55 peChanData->sfbNLines4[sfbGrp+sfb] = sfbNRelevantLines[ch][sfbGrp+sfb]; 56 sfbNRelevantLines[ch][sfbGrp+sfb] = sfbNRelevantLines[ch][sfbGrp+sfb] >> 2; 57 peChanData->sfbLdEnergy[sfbGrp+sfb] = logSfbEnergy[ch][sfbGrp+sfb]; 58 } 59 } 60 } 61 peData->offset = peOffset; 62 } 63 64 65 /***************************************************************************** 66 * 67 * function name: calcSfbPe 68 * description: constPart is sfbPe without the threshold part n*ld(thr) or n*C3*ld(thr) 69 * 70 **********************************************************************************/ 71 void calcSfbPe(PE_DATA *peData, 72 PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], 73 const Word16 nChannels) 74 { 75 Word32 ch; 76 Word32 sfbGrp, sfb; 77 Word32 nLines4; 78 Word32 ldThr, ldRatio; 79 Word32 pe, constPart, nActiveLines; 80 81 peData->pe = peData->offset; 82 peData->constPart = 0; 83 peData->nActiveLines = 0; 84 for(ch=0; ch<nChannels; ch++) { 85 PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; 86 PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch]; 87 const Word32 *sfbEnergy = psyOutChan->sfbEnergy; 88 const Word32 *sfbThreshold = psyOutChan->sfbThreshold; 89 90 pe = 0; 91 constPart = 0; 92 nActiveLines = 0; 93 94 for(sfbGrp=0; sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) { 95 for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) { 96 Word32 nrg = sfbEnergy[sfbGrp+sfb]; 97 Word32 thres = sfbThreshold[sfbGrp+sfb]; 98 Word32 sfbLDEn = peChanData->sfbLdEnergy[sfbGrp+sfb]; 99 100 if (nrg > thres) { 101 ldThr = iLog4(thres); 102 103 ldRatio = sfbLDEn - ldThr; 104 105 nLines4 = peChanData->sfbNLines4[sfbGrp+sfb]; 106 107 /* sfbPe = nl*log2(en/thr)*/ 108 if (ldRatio >= C1_I) { 109 peChanData->sfbPe[sfbGrp+sfb] = (nLines4*ldRatio + 8) >> 4; 110 peChanData->sfbConstPart[sfbGrp+sfb] = ((nLines4*sfbLDEn)) >> 4; 111 } 112 else { 113 /* sfbPe = nl*(c2 + c3*log2(en/thr))*/ 114 peChanData->sfbPe[sfbGrp+sfb] = extract_l((L_mpy_wx( 115 (C2_I + C3_I * ldRatio * 2) << 4, nLines4) + 4) >> 3); 116 peChanData->sfbConstPart[sfbGrp+sfb] = extract_l(( L_mpy_wx( 117 (C2_I + C3_I * sfbLDEn * 2) << 4, nLines4) + 4) >> 3); 118 nLines4 = (nLines4 * C3_I + (1024<<1)) >> 10; 119 } 120 peChanData->sfbNActiveLines[sfbGrp+sfb] = nLines4 >> 2; 121 } 122 else { 123 peChanData->sfbPe[sfbGrp+sfb] = 0; 124 peChanData->sfbConstPart[sfbGrp+sfb] = 0; 125 peChanData->sfbNActiveLines[sfbGrp+sfb] = 0; 126 } 127 pe = pe + peChanData->sfbPe[sfbGrp+sfb]; 128 constPart = constPart + peChanData->sfbConstPart[sfbGrp+sfb]; 129 nActiveLines = nActiveLines + peChanData->sfbNActiveLines[sfbGrp+sfb]; 130 } 131 } 132 133 peChanData->pe = saturate(pe); 134 peChanData->constPart = saturate(constPart); 135 peChanData->nActiveLines = saturate(nActiveLines); 136 137 138 pe += peData->pe; 139 peData->pe = saturate(pe); 140 constPart += peData->constPart; 141 peData->constPart = saturate(constPart); 142 nActiveLines += peData->nActiveLines; 143 peData->nActiveLines = saturate(nActiveLines); 144 } 145 } 146