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 **********************************************************************************/
prepareSfbPe(PE_DATA * peData,PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],const Word16 nChannels,const Word16 peOffset)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 **********************************************************************************/
calcSfbPe(PE_DATA * peData,PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],const Word16 nChannels)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