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 "rom_com.h"
43 : #include "wmc_auto.h"
44 : /*--------------------------------------------------------------------------*
45 : * env_stab_transient_detect()
46 : *
47 : * Transient detector for envelope stability measure
48 : *--------------------------------------------------------------------------*/
49 :
50 1482 : void env_stab_transient_detect_fx(
51 : const Word16 is_transient, /* i: Transient flag */
52 : const Word16 length, /* i : Length of spectrum (32 or 48 kHz) */
53 : const Word16 norm[], /* i : quantization indices for norms */
54 : Word16 *no_att_hangover, /* i/o: Frame counter for attenuation hangover (Q0) */
55 : Word32 *L_energy_lt, /* i/o: Long-term energy measure for transient detection (Q13) */
56 : const Word16 HQ_mode, /* i : HQ coding mode */
57 : const Word16 bin_th, /* i : HVQ cross-over frequency bin */
58 : const Word32 *L_coeff, /* i : Coded spectral coefficients */
59 : const Word16 Qcoeff /* i : Q of coded spectral coefficients */
60 : )
61 : {
62 : Word16 i, blk, norm_ind, sqrt_exp, bin_th_1, temp, sh;
63 : Word32 L_e_frame, L_temp, L_d_max;
64 : Word32 L_energy_lt_local;
65 : Word32 L_E_sub[4];
66 : Word32 L_delta_e_sub;
67 :
68 1482 : L_energy_lt_local = *L_energy_lt;
69 1482 : move32();
70 :
71 1482 : L_d_max = L_deposit_l( 0 );
72 1482 : L_e_frame = L_deposit_l( 0 );
73 1482 : temp = 32;
74 1482 : move16();
75 :
76 1482 : IF( EQ_16( HQ_mode, HQ_HVQ ) )
77 : {
78 40626 : FOR( i = 0; i < bin_th; i++ ) /* find adaptive shift */
79 : {
80 40448 : temp = s_min( temp, norm_l( L_coeff[i] ) );
81 : }
82 178 : sh = sub( temp, 2 ); /* scale such that 2 msbs are not used, the resulting adaptive Qcoeff will be: Qcoeff+sh-16 */
83 40626 : FOR( i = 0; i < bin_th; i++ ) /* Maximum number of loop runs 320 */
84 : {
85 40448 : temp = extract_h( L_shl( L_coeff[i], sh ) );
86 40448 : L_e_frame = L_mac( L_e_frame, temp, temp ); /* Q(2*(Qcoeff+sh-16)+1)=Q(2*(Qcoeff+sh)-31 */
87 : }
88 :
89 178 : bin_th_1 = INV_HVQ_THRES_BIN_24k;
90 178 : move16();
91 178 : if ( EQ_16( bin_th, HVQ_THRES_BIN_32k ) )
92 : {
93 6 : bin_th_1 = INV_HVQ_THRES_BIN_32k;
94 6 : move16();
95 : }
96 178 : L_temp = Mult_32_16( L_e_frame, bin_th_1 ); /* Q(2*(Qcoeff-16+sh)+1+21-15) -> Q(2*(Qcoeff+sh)-25) */
97 178 : L_e_frame = Sqrt_l( L_temp, &sqrt_exp );
98 178 : L_e_frame = L_shr( L_e_frame, add( sub( add( sh, Qcoeff ), 10 ), shr( sqrt_exp, 1 ) ) ); /* Adjust by (Qcoeff+sh-10) to fixed Q13: Qcoeff+sh+(-25+31)/2 - (Qcoeff+sh-10) -> Q13 */
99 :
100 178 : IF( GT_32( L_e_frame, ENERGY_TH_FX ) )
101 : {
102 178 : L_energy_lt_local = Mult_32_16( *L_energy_lt, ENERGY_LT_BETA_FX );
103 178 : L_temp = Mult_32_16( L_e_frame, ENERGY_LT_BETA_1_FX );
104 178 : *L_energy_lt = L_add( L_energy_lt_local, L_temp );
105 178 : move32();
106 : }
107 :
108 178 : IF( *no_att_hangover > 0 )
109 : {
110 0 : ( *no_att_hangover ) = sub( ( *no_att_hangover ), 1 );
111 0 : move16();
112 : }
113 : }
114 : ELSE
115 : {
116 1304 : L_e_frame = L_deposit_l( 0 );
117 :
118 1304 : test();
119 1304 : IF( is_transient && EQ_16( length, L_FRAME32k ) )
120 : {
121 : /* Measure subframe energies */
122 665 : FOR( blk = 0; blk < NUM_SUBFRAMES; blk++ )
123 : {
124 532 : L_E_sub[blk] = L_deposit_l( 0 ); /* Q9 */
125 532 : move32();
126 :
127 5320 : FOR( i = 0; i < BANDS_PER_SUBFRAMES; i++ ) /* 9 times -> < 2^4 */
128 : {
129 4788 : norm_ind = subf_norm_groups[blk][i];
130 4788 : move16();
131 4788 : L_E_sub[blk] = L_add( L_E_sub[blk], L_shr( dicn_fx[norm[norm_ind]], 4 ) );
132 4788 : move32();
133 : ; /* Q10 */
134 : }
135 :
136 532 : L_E_sub[blk] = Mult_32_16( L_E_sub[blk], INV_BANDS_PER_SUBFRAMES );
137 532 : move32(); /* Q(10+17-15) -> Q12 */
138 :
139 532 : L_e_frame = L_add( L_e_frame, L_E_sub[blk] ); /* Q12 */
140 : }
141 :
142 : /* Test for transient */
143 : /* if (e_frame > ENERGY_TH * NUM_SUBFRAMES) */
144 133 : IF( GT_32( L_e_frame, ENERGY_TH_NUM_SUBFRAMES ) )
145 : {
146 176 : FOR( blk = 0; blk < NUM_SUBFRAMES - 1; blk++ )
147 : {
148 132 : L_delta_e_sub = L_sub( L_E_sub[blk + 1], L_E_sub[blk] ); /* Q12 */
149 132 : if ( GT_32( L_delta_e_sub, L_d_max ) )
150 : {
151 48 : L_d_max = L_delta_e_sub; /* L_d_max is NOT normalized with *energy_lt */
152 48 : move32();
153 : }
154 : }
155 : }
156 : }
157 : ELSE
158 : {
159 : /* Update long-term energy measure */
160 1171 : L_e_frame = L_deposit_l( 0 ); /* Q9 */
161 32788 : FOR( i = 0; i < SFM_N_ENV_STAB; i++ ) /* 27 times -> < 2^5 */
162 : {
163 31617 : L_e_frame = L_add( L_e_frame, L_shr( dicn_fx[norm[i]], 5 ) );
164 : /* Q9 */
165 : }
166 :
167 1171 : L_e_frame = Mult_32_16( L_e_frame, INV_SFM_N_ENV_STAB ); /* Q(9+19-15) -> Q13 */
168 :
169 1171 : IF( GT_32( L_e_frame, ENERGY_TH_FX ) )
170 : {
171 649 : L_energy_lt_local = Mult_32_16( *L_energy_lt, ENERGY_LT_BETA_FX );
172 649 : L_temp = Mult_32_16( L_e_frame, ENERGY_LT_BETA_1_FX );
173 649 : *L_energy_lt = L_add( L_energy_lt_local, L_temp );
174 649 : move32();
175 : }
176 : }
177 :
178 : /* Add hang-over for conservative application of stability dependent attenuation */
179 : /* -> Note: L_d_max not normalized with *energy_lt */
180 : /* Hence, we compare L_d_max/DELTA_TH with *energy_lt */
181 1304 : IF( GT_32( Mult_32_16( L_d_max, INV_DELTA_TH ), L_energy_lt_local ) ) /* Q13 = Q(12 + 16 -15) */
182 : {
183 0 : *no_att_hangover = ATT_LIM_HANGOVER;
184 0 : move16();
185 : }
186 1304 : ELSE IF( *no_att_hangover > 0 )
187 : {
188 0 : *no_att_hangover = sub( *no_att_hangover, 1 );
189 0 : move16();
190 : }
191 : }
192 :
193 1482 : return;
194 : }
|