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 : * fer_energy()
45 : *
46 : * Estimation of pitch-synchronous (voiced sounds) or half-frame energy
47 : *----------------------------------------------------------------------------------*/
48 :
49 69696 : void fer_energy_fx(
50 : const Word16 L_frame, /* i : frame length */
51 : const Word16 clas, /* i : frame classification */
52 : const Word32 *synth, /* i : synthesized speech at Fs = 12k8 Hz Q(q_synth) */
53 : const Word16 q_synth, /* i : synthesized speech at Fs = 12k8 Hz */
54 : const Word16 pitch, /* i : pitch period Q0 */
55 : Word32 *enr, /* o : pitch-synchronous or half_frame energy Q0 */
56 : const Word16 offset /* i : speech pointer offset (0 or L_frame) */
57 : )
58 : {
59 : Word16 len, shift, exp;
60 : const Word32 *pt_synth;
61 : Word16 enr_tmp, i;
62 : Word64 W_tmp;
63 :
64 69696 : test();
65 69696 : test();
66 69696 : IF( EQ_16( clas, VOICED_CLAS ) || EQ_16( clas, ONSET ) || EQ_16( clas, SIN_ONSET ) ) /* Voiced or Onset current frame */
67 : {
68 33858 : len = ( pitch ); /* pitch value */
69 33858 : move16();
70 :
71 33858 : pt_synth = synth;
72 33858 : IF( offset != 0 )
73 : {
74 33858 : pt_synth = synth + sub( L_frame, len );
75 : }
76 :
77 33858 : emaximum_32fx( q_synth, pt_synth, len, enr ); /* pitch synchronous E */
78 : }
79 : ELSE
80 : {
81 35838 : pt_synth = synth;
82 35838 : IF( offset != 0 )
83 : {
84 35838 : pt_synth = synth + shr( L_frame, 1 );
85 : }
86 :
87 35838 : W_tmp = 0;
88 35838 : move64();
89 7565758 : FOR( i = 0; i < L_frame / 2; i++ )
90 : {
91 7529920 : W_tmp = W_add( W_tmp, W_mult0_32_32( pt_synth[i], pt_synth[i] ) ); // Q = q_synth * 2
92 : }
93 35838 : shift = W_norm( W_tmp );
94 35838 : W_tmp = W_shl( W_tmp, shift ); // Q = q_synth * 2 + shift
95 35838 : *enr = W_extract_h( W_tmp ); // Q = q_synth * 2 + shift - 32
96 35838 : move32();
97 :
98 35838 : enr_tmp = BASOP_Util_Divide3216_Scale( *enr, shr( L_frame, 1 ) /*Q0*/, &exp );
99 35838 : *enr = L_shr( L_deposit_l( enr_tmp ), sub( sub( sub( shift, 32 ), exp ), 1 ) ); /*Q0*/
100 35838 : move32();
101 : }
102 69696 : return;
103 : }
104 :
105 : /*----------------------------------------------------------------------------------*
106 : * frame_ener()
107 : *
108 : * Estimation of pitch-synchronous (voiced) or mean half-frame (unvoiced) energy
109 : *----------------------------------------------------------------------------------*/
110 236657 : Word16 frame_ener_fx(
111 : const Word16 L_frame, /* i : length of the frame */
112 : const Word16 clas, /* i : frame classification */
113 : const Word16 *synth, /* i : synthesized speech at Fs = 12k8 Hz Q_new */
114 : const Word16 pitch, /* i : pitch period Q0 */
115 : Word32 *enr_q, /* o : pitch-synchronous or half_frame energy Q0 */
116 : const Word16 offset, /* i : speech pointer offset (0 or L_FRAME) */
117 : const Word16 Q_new, /* i : Scaling factor */
118 : Word16 shift, /* i : Shift need to obtain 12 bits vectors */
119 : const Word16 enc /* i : Encoder/decoder */
120 : )
121 : {
122 : Word16 len, exp_enrq, exp_tmp, pos;
123 : Word16 i;
124 : const Word16 *pt_synth;
125 : Word32 Ltmp;
126 :
127 236657 : exp_enrq = 0;
128 236657 : move16();
129 236657 : test();
130 236657 : test();
131 236657 : IF( ( EQ_16( clas, VOICED_CLAS ) ) || ( EQ_16( clas, ONSET ) ) || ( EQ_16( clas, SIN_ONSET ) ) ) /* current frame is voiced */
132 : {
133 : /* current frame is voiced */
134 90280 : len = pitch;
135 90280 : move16(); /* pitch value at the end of frame */
136 90280 : pt_synth = synth;
137 90280 : if ( offset != 0 )
138 : {
139 89322 : pt_synth = synth + sub( L_frame, len );
140 : }
141 90280 : emaximum_fx( Q_new, pt_synth, len, enr_q );
142 90280 : IF( enc != 0 )
143 : {
144 341 : exp_enrq = norm_l( *enr_q );
145 341 : *enr_q = L_shl( *enr_q, exp_enrq );
146 341 : move32();
147 341 : exp_enrq = sub( exp_enrq, 2 );
148 : }
149 : }
150 : ELSE
151 : {
152 : /* current frame is unvoiced */
153 : Word16 L_frame2, exp2, enr_q_tmp;
154 :
155 146377 : L_frame2 = shr( L_frame, 1 );
156 146377 : pos = 0;
157 146377 : move16();
158 :
159 146377 : if ( offset != 0 )
160 : {
161 145998 : pos = sub( L_frame, L_frame2 );
162 : }
163 146377 : Ltmp = L_mult_sat( synth[pos], synth[pos] ); /*2 * Qnew + 1*/
164 21123584 : FOR( i = 1; i < L_frame2; i++ )
165 : {
166 20977207 : Ltmp = L_mac_sat( Ltmp, synth[pos + i], synth[pos + i] ); /*2 * Qnew + 1*/
167 : }
168 146377 : test();
169 146377 : IF( EQ_32( Ltmp, MAX_32 ) || enc != 0 )
170 : {
171 : /* scale down when overflow occurs */
172 588 : *enr_q = Energy_scale( synth + pos, L_frame2, shift, &exp_enrq );
173 588 : move32();
174 : }
175 : ELSE
176 : {
177 145789 : shift = 0;
178 145789 : move16();
179 : /* Normalize acc in Q31 (energy already calculated) */
180 145789 : pos = norm_l( Ltmp );
181 145789 : Ltmp = L_shl( Ltmp, pos );
182 145789 : exp_enrq = sub( 30, pos ); /* exponent = 0..30 */
183 145789 : *enr_q = Ltmp;
184 145789 : move32();
185 : }
186 :
187 : /* enr2 = 1.0f/L_FRAME2 * dot_product(synth, synth, L_FRAME2) */
188 146377 : exp_enrq = sub( exp_enrq, shl( shift, 1 ) );
189 :
190 146377 : IF( enc != 0 )
191 : {
192 283 : assert( L_frame == 256 || L_frame == 320 );
193 :
194 283 : exp_tmp = add( shl( Q_new, 1 ), -2 + 7 ); /* L_subfr == L_SUBFR */
195 283 : exp_enrq = sub( exp_enrq, exp_tmp );
196 283 : exp_enrq = sub( 31, exp_enrq );
197 :
198 283 : IF( EQ_16( L_frame, 320 ) )
199 : {
200 283 : *enr_q = Mult_32_16( *enr_q, 26214 ); /*x 0.8 to get /160*/
201 283 : move32();
202 283 : i = norm_l( *enr_q );
203 283 : *enr_q = L_shl( *enr_q, i );
204 283 : move32();
205 283 : exp_enrq = add( i, exp_enrq );
206 : }
207 : }
208 : ELSE
209 : {
210 146094 : exp_enrq = sub( exp_enrq, add( Q_new, Q_new ) );
211 146094 : enr_q_tmp /*Q30 exp2+exp_enrq*/ = BASOP_Util_Divide3216_Scale( *enr_q /*Q31*/, L_frame2 /*Q0*/, &exp2 );
212 146094 : *enr_q = L_shr( L_deposit_l( enr_q_tmp ), sub( 30, add( exp2, exp_enrq ) ) ); /*Q0*/
213 146094 : move32();
214 146094 : *enr_q = L_add( *enr_q, 1 );
215 146094 : move32();
216 146094 : exp_enrq = 0;
217 146094 : move16();
218 : }
219 : }
220 :
221 236657 : return exp_enrq;
222 : }
223 :
224 : /*------------------------------------------------------------------------*
225 : * frame_energy()
226 : *
227 : * Compute pitch-synchronous energy at the frame end
228 : *------------------------------------------------------------------------*/
229 123491 : Word16 frame_energy_fx( /* o : Frame energy in Q8 */
230 : Word16 L_frame,
231 : const Word16 *pitch, /* i : pitch values for each subframe Q6 */
232 : const Word16 *speech, /* i : pointer to speech signal for E computation Q_syn*/
233 : const Word16 lp_speech, /* i : long term active speech energy average Q8 */
234 : Word16 *frame_ener, /* o : pitch-synchronous energy at frame end Q8 */
235 : const Word16 Q_syn /* i : Synthesis scaling */
236 : )
237 : {
238 : Word32 Ltmp;
239 : const Word16 *pt1;
240 : Word16 tmp16, exp1, exp2, tmp1, tmp2;
241 : Word16 len, enern;
242 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
243 123491 : Flag Overflow = 0;
244 123491 : move32();
245 : #endif
246 :
247 :
248 : /* len = (0.5f * (pitch[2]/64.0 + pitch[3]/64.0) + 0.5f) */
249 123491 : len = mult_r( add_o( pitch[2], pitch[3], &Overflow ), 256 );
250 :
251 123491 : if ( LT_16( len, L_SUBFR ) )
252 : {
253 30846 : len = shl( len, 1 );
254 : }
255 123491 : pt1 = speech + sub( L_frame, len );
256 :
257 : /* *frame_ener = 10.0f * log10(dot_product(pt1, pt1, len) / (float)len) */
258 :
259 123491 : tmp1 = norm_s( len );
260 123491 : tmp2 = shl( len, tmp1 );
261 123491 : tmp1 = sub( 15, tmp1 );
262 :
263 123491 : Ltmp = Dot_productSq16HQ( 0, pt1, len, &exp1 );
264 123491 : exp1 = sub( exp1, shl( Q_syn, 1 ) );
265 123491 : exp1 = sub( exp1, 1 ); /* compensation of leftshift caused by mac operation in dot_productSq16HQ */
266 123491 : tmp16 = BASOP_Util_Divide3216_Scale( Ltmp, len, &exp2 );
267 :
268 123491 : exp1 = add( exp1, exp2 );
269 123491 : exp1 = add( exp1, 1 ); /* compensate result of division Q-1 */
270 :
271 :
272 123491 : tmp2 = norm_s( tmp16 );
273 123491 : Ltmp = L_shl( L_deposit_h( tmp16 ), tmp2 ); /*Q16, (exp1-tmp2) = Q31, exp1-tmp2+15*/
274 :
275 123491 : Ltmp = BASOP_Util_Log2( Ltmp ); /*Q(31-6) = Q25*/
276 123491 : exp1 = sub( 15 + exp1, tmp2 );
277 :
278 : /*add ld(2^exp1)=exp1 but check format, first*/
279 123491 : tmp16 = sub( sub( 15, norm_s( exp1 ) ), 5 ); /*factor to shift Ltmp and exp1 with (shr) to avoid overflows when adding*/
280 123491 : Ltmp = L_shr_o( Ltmp, tmp16, &Overflow ); /*Q25, tmp16*/
281 123491 : exp2 = shr( exp1, tmp16 ); /*Q0 , tmp16*/
282 123491 : Ltmp = L_add_o( Ltmp, L_shl( L_deposit_l( exp2 ), 25 ), &Overflow ); /*Q25, tmp16, normalized*/
283 :
284 : /*make 10*log10 out of log2*/
285 123491 : Ltmp = Mpy_32_16_1( Ltmp, LG10 ); /*Q25,tmp16 * Q13 = Q23, tmp16*/
286 123491 : *frame_ener = extract_h( L_shl_o( Ltmp, add( tmp16, 1 ), &Overflow ) ); /*Q8*/
287 123491 : move16();
288 123491 : enern = sub_o( *frame_ener, lp_speech, &Overflow ); /*Q8*/
289 :
290 123491 : return enern;
291 : }
|