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 "rom_com.h"
42 : #include "prot_fx.h"
43 : #include "wmc_auto.h"
44 :
45 : /*-------------------------------------------------------------------*
46 : * Local constants
47 : *-------------------------------------------------------------------*/
48 :
49 : #define ATT_LENGHT16k 80
50 :
51 : #define ATT_LENGHT 64
52 : #define ATT_SEG_LEN ( L_FRAME / ATT_LENGHT )
53 :
54 20567 : void pre_echo_att_fx(
55 : Word32 *Last_frame_ener_fx, /* i/o: Energy of the last frame 2*Q_new+1*/
56 : Word16 *exc_fx, /* i/o: Excitation of the current frame Q_new*/
57 : const Word16 gsc_attack_flag_fx, /* i : flag signalling attack encoded by AC mode (GSC) Q0*/
58 : const Word16 Q_new,
59 : const Word16 last_coder_type, /* i : Last coding mode Q0*/
60 : const Word16 L_frame /* i : Frame length Q0*/
61 : )
62 : {
63 : Word32 etmp_fx;
64 20567 : Word32 finc_fx[ATT_LENGHT16k] = { 0 };
65 20567 : move16();
66 : Word16 ratio_fx;
67 : Word16 attack_pos_fx, i;
68 : Word32 L_tmp, L_tmp1;
69 : Word16 tmp, n1, n2, exp, frac1, frac2;
70 : Word32 etmp1_fx;
71 : Word16 att_len;
72 :
73 20567 : test();
74 20567 : IF( gsc_attack_flag_fx > 0 && EQ_16( last_coder_type, AUDIO ) ) /*gsc_attack_flag_fx does not get set for all the test cases */
75 : {
76 : /*-------------------------------------------------------------------------*
77 : * Find where the onset (attack) occurs by computing the energy per section
78 : * The inverse weighting aims to favor the first maxima in case of
79 : * gradual onset
80 : *-------------------------------------------------------------------------*/
81 0 : att_len = ATT_LENGHT; /* Q0 */
82 0 : move16();
83 0 : if ( EQ_16( L_frame, L_FRAME16k ) )
84 : {
85 0 : att_len = ATT_LENGHT16k; /* Q0 */
86 0 : move16();
87 : }
88 0 : FOR( i = 0; i < att_len; i++ )
89 : {
90 0 : L_tmp = sum2_fx( &exc_fx[i * 4], ATT_SEG_LEN ); /*2*Q_new+1, //ATT_SEG_LEN=(L_FRAME/ATT_LENGHT)=4(=shl(x,2))*/
91 0 : tmp = div_s( sub( att_len, i ), att_len ); /*Q15 */
92 0 : L_tmp = Mult_32_16( L_tmp, tmp ); /*2*Q_new+1 */
93 0 : finc_fx[i] = L_tmp;
94 0 : move32(); /*2*Q_new+1 */
95 : }
96 :
97 0 : attack_pos_fx = maximum_32_fx( finc_fx, att_len, &etmp_fx );
98 :
99 : /* Scaled the maximum energy and allowed 6 dB increase*/
100 0 : etmp_fx = L_shr( etmp_fx, add( 2 + 1 - 4, shl( Q_new, 1 ) ) ); /*2*Q_new+1 //INV_ATT_SEG_LEN=1/4(=shr(x,2)) -> Q4 */
101 0 : etmp1_fx = etmp_fx;
102 0 : move32();
103 0 : *Last_frame_ener_fx = L_shl_sat( *Last_frame_ener_fx, 2 );
104 0 : move32(); /*2*Q_new+1 */
105 :
106 : /* If the maximum normalized energy > last frame energy + 6dB */
107 0 : test();
108 0 : IF( GT_32( etmp_fx, *Last_frame_ener_fx ) && attack_pos_fx > 0 )
109 : {
110 : /* Find the average energy before the attack */
111 0 : L_tmp = sum32_fx( finc_fx, attack_pos_fx ); /*Q1 */
112 0 : L_tmp1 = L_shr( L_mult( attack_pos_fx, attack_pos_fx ), 1 ); /*Q0 */
113 0 : tmp = round_fx( Isqrt( L_tmp1 ) ); /*Q15 */
114 0 : L_tmp = L_shr( L_tmp, 2 ); /*Q1 ; ATT_SEG_LEN=4 */
115 0 : etmp_fx = Mult_32_16( L_tmp, tmp ); /*Q1 */
116 :
117 0 : etmp_fx = L_shr( etmp_fx, add( 1 - 4, shl( Q_new, 1 ) ) ); /* makes etmp i nQ4 as *Last_frame_ener_fx */
118 : /* Find the correction factor and apply it before the attack */
119 : /* ratio = (float)sqrt(*Last_frame_ener/etmp);*/
120 : /* = isqrt(etmp/(*Last_frame_ener)) */
121 0 : etmp_fx = L_max( etmp_fx, 1 );
122 0 : *Last_frame_ener_fx = L_max( *Last_frame_ener_fx, 1 );
123 0 : move32();
124 0 : n1 = norm_l( etmp_fx );
125 0 : n2 = norm_l( *Last_frame_ener_fx );
126 :
127 0 : n1 = sub( n1, 1 );
128 0 : exp = sub( n1, n2 );
129 :
130 0 : frac1 = round_fx( L_shl( etmp_fx, n1 ) );
131 0 : frac2 = round_fx_sat( L_shl_sat( *Last_frame_ener_fx, n2 ) );
132 0 : L_tmp = L_mult0( 128, div_s( frac1, frac2 ) ); /* s = gain_out / gain_in */
133 0 : L_tmp = L_shr( L_tmp, exp ); /* add exponent */
134 :
135 0 : L_tmp = Isqrt( L_tmp );
136 0 : ratio_fx = round_fx( L_shl( L_tmp, 9 ) ); /* Q13 */
137 :
138 : /* Pre-echo atttenuation should never increase the energy */
139 0 : ratio_fx = s_min( ratio_fx, 8192 /* 1 in Q13 */ ); /* Q13 */
140 0 : FOR( i = 0; i < attack_pos_fx * ATT_SEG_LEN; i++ )
141 : {
142 : /*exc_fx[i] *= ratio_fx;*/
143 0 : exc_fx[i] = round_fx( L_shl( L_mac( -8192, exc_fx[i], ratio_fx ), 2 ) );
144 0 : move16();
145 : }
146 : }
147 0 : *Last_frame_ener_fx = etmp1_fx; /*2*Q_new+1*/
148 0 : move32();
149 : }
150 : ELSE
151 : {
152 : /*-------------------------------------------------------*
153 : * In normal cases, just compute the energy of the frame
154 : *-------------------------------------------------------*/
155 :
156 20567 : etmp_fx = sum2_fx( exc_fx, L_frame ); /*2*Q_new+1 */
157 20567 : etmp_fx = L_shr( etmp_fx, add( 8 + 1 - 4, shl( Q_new, 1 ) ) ); /*2*Q_new+1 //INV_L_FRAME = 1/256 -> Q4*/
158 20567 : *Last_frame_ener_fx = etmp_fx;
159 20567 : move32(); /*2*Q_new+1*/
160 : }
161 :
162 20567 : return;
163 : }
164 :
165 :
166 22696 : void pre_echo_att_ivas_fx(
167 : Word32 *Last_frame_ener_fx, /* i/o: Energy of the last frame 2*Q_new+1*/
168 : Word16 *exc_fx, /* i/o: Excitation of the current frame Q_new*/
169 : const Word16 gsc_attack_flag_fx, /* i : flag signalling attack encoded by AC mode (GSC) Q0*/
170 : const Word16 Q_new,
171 : const Word16 last_coder_type, /* i : Last coding mode Q0*/
172 : const Word16 L_frame /* i : Frame length Q0*/
173 : )
174 : {
175 : Word32 etmp_fx;
176 22696 : Word32 finc_fx[ATT_LENGHT16k] = { 0 };
177 22696 : move16();
178 : Word16 ratio_fx;
179 : Word16 attack_pos_fx, i;
180 : Word32 L_tmp;
181 : Word16 tmp, tmp_e;
182 : Word32 etmp1_fx;
183 : Word16 etmp_e;
184 : Word16 att_len;
185 :
186 22696 : test();
187 22696 : IF( gsc_attack_flag_fx > 0 && EQ_16( last_coder_type, AUDIO ) ) /*gsc_attack_flag_fx does not get set for all the test cases */
188 : {
189 : /*-------------------------------------------------------------------------*
190 : * Find where the onset (attack) occurs by computing the energy per section
191 : * The inverse weighting aims to favor the first maxima in case of
192 : * gradual onset
193 : *-------------------------------------------------------------------------*/
194 0 : att_len = ATT_LENGHT; /* Q0 */
195 0 : move16();
196 0 : if ( EQ_16( L_frame, L_FRAME16k ) )
197 : {
198 0 : att_len = ATT_LENGHT16k; /* Q0 */
199 0 : move16();
200 : }
201 0 : FOR( i = 0; i < att_len; i++ )
202 : {
203 0 : L_tmp = sum2_fx( &exc_fx[i * 4], ATT_SEG_LEN ); /*2*Q_new+1, //ATT_SEG_LEN=(L_FRAME/ATT_LENGHT)=4(=shl(x,2))*/
204 0 : tmp = div_s( sub( att_len, i ), att_len ); /*Q15 */
205 0 : L_tmp = Mult_32_16( L_tmp, tmp ); /*2*Q_new+1 */
206 0 : finc_fx[i] = L_tmp;
207 0 : move32(); /*2*Q_new+1 */
208 : }
209 :
210 0 : attack_pos_fx = maximum_32_fx( finc_fx, att_len, &etmp_fx );
211 :
212 : /* Scaled the maximum energy and allowed 6 dB increase*/
213 0 : etmp_fx = L_shr( etmp_fx, add( 2 + 1 - 4, shl( Q_new, 1 ) ) ); /*2*Q_new+1 //INV_ATT_SEG_LEN=1/4(=shr(x,2)) -> Q4 */
214 0 : etmp1_fx = etmp_fx;
215 0 : move32();
216 0 : *Last_frame_ener_fx = L_shl_sat( *Last_frame_ener_fx, 2 );
217 0 : move32(); /*2*Q_new+1 */
218 :
219 : /* If the maximum normalized energy > last frame energy + 6dB */
220 0 : test();
221 0 : IF( GT_32( etmp_fx, *Last_frame_ener_fx ) && attack_pos_fx > 0 )
222 : {
223 : /* Find the average energy before the attack */
224 0 : etmp_fx = sum32_fx( finc_fx, attack_pos_fx );
225 0 : etmp_e = sub( 31, add( shl( Q_new, 1 ), 1 ) );
226 0 : etmp_fx = L_add( etmp_fx, L_shr( 21474836 /*0.01 in Q31*/, etmp_e ) ); /* etmp = etmp + 0.01; (exp = etmp_e) */
227 0 : etmp_fx = L_deposit_h( BASOP_Util_Divide3232_Scale( etmp_fx, L_mult0( attack_pos_fx, ATT_SEG_LEN ), &tmp_e ) );
228 0 : tmp_e = add( tmp_e, sub( etmp_e, 31 ) );
229 0 : etmp_e = tmp_e;
230 0 : move16();
231 :
232 : /* Find the correction factor and apply it before the attack */
233 0 : tmp = BASOP_Util_Divide3232_Scale( *Last_frame_ener_fx, etmp_fx, &tmp_e ); /* numerator Q = 2 * Q_new + 1; denominator Q = 31 - tmp_e */
234 0 : tmp_e = add( tmp_e, sub( sub( 31, etmp_e ), add( shl( Q_new, 1 ), 1 ) ) ); /* tmp_e = tmp_e + (31 - tmp_e) - (2 * Q_new + 1) */
235 0 : tmp = Sqrt16( tmp, &tmp_e );
236 0 : ratio_fx = shr_sat( tmp, sub( 2, tmp_e ) ); /* Q13 */
237 :
238 : /* Pre-echo atttenuation should never increase the energy */
239 0 : ratio_fx = s_min( ratio_fx, 8192 /* 1 in Q13 */ ); /* Q13 */
240 0 : FOR( i = 0; i < attack_pos_fx * ATT_SEG_LEN; i++ )
241 : {
242 : /*exc_fx[i] *= ratio_fx;*/
243 0 : exc_fx[i] = round_fx( L_shl( L_mac( -8192, exc_fx[i], ratio_fx ), 2 ) );
244 0 : move16();
245 : }
246 : }
247 0 : *Last_frame_ener_fx = etmp1_fx; /* 2 * Q_new + 1 */
248 0 : move32();
249 : }
250 : ELSE
251 : {
252 : /*-------------------------------------------------------*
253 : * In normal cases, just compute the energy of the frame
254 : *-------------------------------------------------------*/
255 22696 : Word16 exp_etmp = sub( 15, Q_new );
256 22696 : etmp_fx = sum2_16_exp_fx( exc_fx, L_frame, &exp_etmp, 7 ); /* Q = 31-exp_etmp */
257 :
258 22696 : etmp_fx = L_shr( etmp_fx, 8 ); /*31-exp_etmp//INV_L_FRAME = 1/256*/
259 :
260 22696 : IF( EQ_16( L_frame, L_FRAME16k ) )
261 : {
262 2650 : etmp_fx = Mpy_32_16_1( etmp_fx, 26214 /* 0.8 in Q15 */ ); /*31 - exp_etmp*/
263 : }
264 22696 : *Last_frame_ener_fx = L_shl( etmp_fx, sub( shl( Q_new, 1 ), sub( 30 /*31-1*/, exp_etmp ) ) ); /*2*Q_new+1*/
265 22696 : move32(); /*2*Q_new+1*/
266 : }
267 :
268 22696 : return;
269 : }
|