Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : /*====================================================================================
34 : EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
35 : ====================================================================================*/
36 :
37 : #include <stdint.h>
38 : #include "options.h"
39 : #include <math.h>
40 : #include "cnst.h"
41 : #include "prot_fx.h"
42 : #include "wmc_auto.h"
43 :
44 : /*----------------------------------------------------------------------------------*
45 : * fer_energy()
46 : *
47 : * Estimation of pitch-synchronous (voiced sounds) or half-frame energy
48 : *----------------------------------------------------------------------------------*/
49 :
50 8327 : void fer_energy_fx(
51 : const Word16 L_frame, /* i : frame length */
52 : const Word16 clas, /* i : frame classification */
53 : const Word32 *synth, /* i : synthesized speech at Fs = 12k8 Hz Q(q_synth) */
54 : const Word16 q_synth, /* i : synthesized speech at Fs = 12k8 Hz */
55 : const Word16 pitch, /* i : pitch period Q0 */
56 : Word32 *enr, /* o : pitch-synchronous or half_frame energy Q0 */
57 : const Word16 offset /* i : speech pointer offset (0 or L_frame) */
58 : )
59 : {
60 : Word16 len, shift, exp;
61 : const Word32 *pt_synth;
62 : Word16 enr_tmp, i;
63 : Word64 W_tmp;
64 :
65 8327 : test();
66 8327 : test();
67 8327 : IF( EQ_16( clas, VOICED_CLAS ) || EQ_16( clas, ONSET ) || EQ_16( clas, SIN_ONSET ) ) /* Voiced or Onset current frame */
68 : {
69 0 : len = ( pitch ); /* pitch value */
70 0 : move16();
71 :
72 0 : pt_synth = synth;
73 0 : IF( offset != 0 )
74 : {
75 0 : pt_synth = synth + sub( L_frame, len );
76 : }
77 :
78 0 : emaximum_32fx( q_synth, pt_synth, len, enr ); /* pitch synchronous E */
79 : }
80 : ELSE
81 : {
82 8327 : pt_synth = synth;
83 8327 : IF( offset != 0 )
84 : {
85 8327 : pt_synth = synth + shr( L_frame, 1 );
86 : }
87 :
88 8327 : W_tmp = 0;
89 8327 : move64();
90 3513447 : FOR( i = 0; i < L_frame / 2; i++ )
91 : {
92 3505120 : W_tmp = W_add( W_tmp, W_mult0_32_32( pt_synth[i], pt_synth[i] ) ); // Q = q_synth * 2
93 : }
94 8327 : shift = W_norm( W_tmp );
95 8327 : W_tmp = W_shl( W_tmp, shift ); // Q = q_synth * 2 + shift
96 8327 : *enr = W_extract_h( W_tmp ); // Q = q_synth * 2 + shift - 32
97 8327 : move32();
98 :
99 8327 : enr_tmp = BASOP_Util_Divide3216_Scale( *enr, shr( L_frame, 1 ) /*Q0*/, &exp );
100 8327 : *enr = L_shr( L_deposit_l( enr_tmp ), sub( sub( sub( shift, 32 ), exp ), 1 ) ); /*Q0*/
101 8327 : move32();
102 : }
103 8327 : return;
104 : }
105 :
106 : /*----------------------------------------------------------------------------------*
107 : * frame_ener()
108 : *
109 : * Estimation of pitch-synchronous (voiced) or mean half-frame (unvoiced) energy
110 : *----------------------------------------------------------------------------------*/
111 239901 : Word16 frame_ener_fx(
112 : const Word16 L_frame, /* i : length of the frame */
113 : const Word16 clas, /* i : frame classification */
114 : const Word16 *synth, /* i : synthesized speech at Fs = 12k8 Hz Q_new */
115 : const Word16 pitch, /* i : pitch period Q0 */
116 : Word32 *enr_q, /* o : pitch-synchronous or half_frame energy Q0 */
117 : const Word16 offset, /* i : speech pointer offset (0 or L_FRAME) */
118 : const Word16 Q_new, /* i : Scaling factor */
119 : Word16 shift, /* i : Shift need to obtain 12 bits vectors */
120 : const Word16 enc /* i : Encoder/decoder */
121 : )
122 : {
123 : Word16 len, exp_enrq, exp_tmp, pos;
124 : Word16 i;
125 : const Word16 *pt_synth;
126 : Word32 Ltmp;
127 :
128 239901 : exp_enrq = 0;
129 239901 : move16();
130 239901 : test();
131 239901 : test();
132 239901 : IF( ( EQ_16( clas, VOICED_CLAS ) ) || ( EQ_16( clas, ONSET ) ) || ( EQ_16( clas, SIN_ONSET ) ) ) /* current frame is voiced */
133 : {
134 : /* current frame is voiced */
135 91377 : len = pitch;
136 91377 : move16(); /* pitch value at the end of frame */
137 91377 : pt_synth = synth;
138 91377 : if ( offset != 0 )
139 : {
140 90409 : pt_synth = synth + sub( L_frame, len );
141 : }
142 91377 : emaximum_fx( Q_new, pt_synth, len, enr_q );
143 91377 : IF( enc != 0 )
144 : {
145 0 : exp_enrq = norm_l( *enr_q );
146 0 : *enr_q = L_shl( *enr_q, exp_enrq );
147 0 : move32();
148 0 : exp_enrq = sub( exp_enrq, 2 );
149 : }
150 : }
151 : ELSE
152 : {
153 : /* current frame is unvoiced */
154 : Word16 L_frame2, exp2, enr_q_tmp;
155 :
156 148524 : L_frame2 = shr( L_frame, 1 );
157 148524 : pos = 0;
158 148524 : move16();
159 :
160 148524 : if ( offset != 0 )
161 : {
162 148144 : pos = sub( L_frame, L_frame2 );
163 : }
164 148524 : Ltmp = L_mult_sat( synth[pos], synth[pos] ); /*2 * Qnew + 1*/
165 21452768 : FOR( i = 1; i < L_frame2; i++ )
166 : {
167 21304244 : Ltmp = L_mac_sat( Ltmp, synth[pos + i], synth[pos + i] ); /*2 * Qnew + 1*/
168 : }
169 148524 : test();
170 148524 : IF( EQ_32( Ltmp, MAX_32 ) || enc != 0 )
171 : {
172 : /* scale down when overflow occurs */
173 315 : *enr_q = Energy_scale( synth + pos, L_frame2, shift, &exp_enrq );
174 315 : move32();
175 : }
176 : ELSE
177 : {
178 148209 : shift = 0;
179 148209 : move16();
180 : /* Normalize acc in Q31 (energy already calculated) */
181 148209 : pos = norm_l( Ltmp );
182 148209 : Ltmp = L_shl( Ltmp, pos );
183 148209 : exp_enrq = sub( 30, pos ); /* exponent = 0..30 */
184 148209 : *enr_q = Ltmp;
185 148209 : move32();
186 : }
187 :
188 : /* enr2 = 1.0f/L_FRAME2 * dot_product(synth, synth, L_FRAME2) */
189 148524 : exp_enrq = sub( exp_enrq, shl( shift, 1 ) );
190 :
191 148524 : IF( enc != 0 )
192 : {
193 0 : assert( L_frame == 256 || L_frame == 320 );
194 :
195 0 : exp_tmp = add( shl( Q_new, 1 ), -2 + 7 ); /* L_subfr == L_SUBFR */
196 0 : exp_enrq = sub( exp_enrq, exp_tmp );
197 0 : exp_enrq = sub( 31, exp_enrq );
198 :
199 0 : IF( EQ_16( L_frame, 320 ) )
200 : {
201 0 : *enr_q = Mult_32_16( *enr_q, 26214 ); /*x 0.8 to get /160*/
202 0 : move32();
203 0 : i = norm_l( *enr_q );
204 0 : *enr_q = L_shl( *enr_q, i );
205 0 : move32();
206 0 : exp_enrq = add( i, exp_enrq );
207 : }
208 : }
209 : ELSE
210 : {
211 148524 : exp_enrq = sub( exp_enrq, add( Q_new, Q_new ) );
212 148524 : enr_q_tmp /*Q30 exp2+exp_enrq*/ = BASOP_Util_Divide3216_Scale( *enr_q /*Q31*/, L_frame2 /*Q0*/, &exp2 );
213 148524 : *enr_q = L_shr( L_deposit_l( enr_q_tmp ), sub( 30, add( exp2, exp_enrq ) ) ); /*Q0*/
214 148524 : move32();
215 148524 : *enr_q = L_add( *enr_q, 1 );
216 148524 : move32();
217 148524 : exp_enrq = 0;
218 148524 : move16();
219 : }
220 : }
221 :
222 239901 : return exp_enrq;
223 : }
224 :
225 : /*------------------------------------------------------------------------*
226 : * frame_energy()
227 : *
228 : * Compute pitch-synchronous energy at the frame end
229 : *------------------------------------------------------------------------*/
230 125624 : Word16 frame_energy_fx( /* o : Frame energy in Q8 */
231 : Word16 L_frame,
232 : const Word16 *pitch, /* i : pitch values for each subframe Q6 */
233 : const Word16 *speech, /* i : pointer to speech signal for E computation Q_syn*/
234 : const Word16 lp_speech, /* i : long term active speech energy average Q8 */
235 : Word16 *frame_ener, /* o : pitch-synchronous energy at frame end Q8 */
236 : const Word16 Q_syn /* i : Synthesis scaling */
237 : )
238 : {
239 : Word32 Ltmp;
240 : const Word16 *pt1;
241 : Word16 tmp16, exp1, exp2, tmp1, tmp2;
242 : Word16 len, enern;
243 : #ifndef ISSUE_1836_replace_overflow_libcom
244 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
245 : Flag Overflow = 0;
246 : move32();
247 : #endif
248 : #endif
249 :
250 :
251 : /* len = (0.5f * (pitch[2]/64.0 + pitch[3]/64.0) + 0.5f) */
252 : #ifdef ISSUE_1836_replace_overflow_libcom
253 125624 : len = mult_r( add_sat( pitch[2], pitch[3] ), 256 );
254 : #else
255 : len = mult_r( add_o( pitch[2], pitch[3], &Overflow ), 256 );
256 : #endif
257 :
258 125624 : if ( LT_16( len, L_SUBFR ) )
259 : {
260 31167 : len = shl( len, 1 );
261 : }
262 125624 : pt1 = speech + sub( L_frame, len );
263 :
264 : /* *frame_ener = 10.0f * log10(dot_product(pt1, pt1, len) / (float)len) */
265 :
266 125624 : tmp1 = norm_s( len );
267 125624 : tmp2 = shl( len, tmp1 );
268 125624 : tmp1 = sub( 15, tmp1 );
269 :
270 125624 : Ltmp = Dot_productSq16HQ( 0, pt1, len, &exp1 );
271 125624 : exp1 = sub( exp1, shl( Q_syn, 1 ) );
272 125624 : exp1 = sub( exp1, 1 ); /* compensation of leftshift caused by mac operation in dot_productSq16HQ */
273 125624 : tmp16 = BASOP_Util_Divide3216_Scale( Ltmp, len, &exp2 );
274 :
275 125624 : exp1 = add( exp1, exp2 );
276 125624 : exp1 = add( exp1, 1 ); /* compensate result of division Q-1 */
277 :
278 :
279 125624 : tmp2 = norm_s( tmp16 );
280 125624 : Ltmp = L_shl( L_deposit_h( tmp16 ), tmp2 ); /*Q16, (exp1-tmp2) = Q31, exp1-tmp2+15*/
281 :
282 125624 : Ltmp = BASOP_Util_Log2( Ltmp ); /*Q(31-6) = Q25*/
283 125624 : exp1 = sub( 15 + exp1, tmp2 );
284 :
285 : /*add ld(2^exp1)=exp1 but check format, first*/
286 125624 : tmp16 = sub( sub( 15, norm_s( exp1 ) ), 5 ); /*factor to shift Ltmp and exp1 with (shr) to avoid overflows when adding*/
287 : #ifdef ISSUE_1836_replace_overflow_libcom
288 125624 : Ltmp = L_shr_sat( Ltmp, tmp16 ); /*Q25, tmp16*/
289 : #else
290 : Ltmp = L_shr_o( Ltmp, tmp16, &Overflow ); /*Q25, tmp16*/
291 : #endif
292 125624 : exp2 = shr( exp1, tmp16 ); /*Q0 , tmp16*/
293 : #ifdef ISSUE_1836_replace_overflow_libcom
294 125624 : Ltmp = L_add_sat( Ltmp, L_shl( L_deposit_l( exp2 ), 25 ) ); /*Q25, tmp16, normalized*/
295 : #else
296 : Ltmp = L_add_o( Ltmp, L_shl( L_deposit_l( exp2 ), 25 ), &Overflow ); /*Q25, tmp16, normalized*/
297 : #endif
298 :
299 : /*make 10*log10 out of log2*/
300 125624 : Ltmp = Mpy_32_16_1( Ltmp, LG10 ); /*Q25,tmp16 * Q13 = Q23, tmp16*/
301 : #ifdef ISSUE_1836_replace_overflow_libcom
302 125624 : *frame_ener = extract_h( L_shl_sat( Ltmp, add( tmp16, 1 ) ) ); /*Q8*/
303 125624 : move16();
304 125624 : enern = sub_sat( *frame_ener, lp_speech ); /*Q8*/
305 : #else
306 : *frame_ener = extract_h( L_shl_o( Ltmp, add( tmp16, 1 ), &Overflow ) ); /*Q8*/
307 : move16();
308 : enern = sub_o( *frame_ener, lp_speech, &Overflow ); /*Q8*/
309 : #endif
310 125624 : return enern;
311 : }
|