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 : #ifdef DEBUGGING
40 : #include "debug.h"
41 : #endif
42 : #include "prot.h"
43 : #include "cnst.h"
44 : #include "rom_com.h"
45 : #include "wmc_auto.h"
46 :
47 : /*--------------------------------------------------------------------------
48 : * hp_filter()
49 : *
50 : * High pass filter
51 : *--------------------------------------------------------------------------*/
52 :
53 21048 : static void hp_filter(
54 : const float *x, /* i : input signal */
55 : float *y, /* o : output signal */
56 : float *oldx, /* i/o: previous filter input */
57 : float *oldy, /* i/o: previous filter output */
58 : const int16_t L /* i : length (32 or 48Hz) */
59 : )
60 : {
61 : int16_t i;
62 :
63 21048 : y[0] = 0.4931f * *oldy + 0.7466f * ( x[0] - *oldx );
64 :
65 12105600 : for ( i = 1; i < L; i++ )
66 : {
67 12084552 : y[i] = 0.4931f * y[i - 1] + 0.7466f * ( x[i] - x[i - 1] );
68 : }
69 :
70 21048 : *oldx = x[L - 1];
71 21048 : *oldy = y[L - 1];
72 :
73 21048 : return;
74 : }
75 :
76 : /*--------------------------------------------------------------------------
77 : * detect_transient()
78 : *
79 : * Detect if the signal is a transient
80 : *--------------------------------------------------------------------------*/
81 :
82 : /*! r: transient flag */
83 21048 : int16_t detect_transient(
84 : Encoder_State *st, /* i/o: Encoder state structure */
85 : const float *in, /* i : input signal */
86 : const int16_t L /* i : length (32 or 48kHz) */
87 : )
88 : {
89 : float Energy;
90 : float EnergyLT;
91 : int16_t i, blk;
92 : int16_t IsTransient;
93 : float out_filt[L_FRAME48k];
94 21048 : int16_t position = 0;
95 : float thr;
96 21048 : float Thres = 0.f;
97 : float Energy_in[5];
98 : float E_low, E_high;
99 21048 : float E_in = 0.0f, E_out = 0.0f;
100 :
101 21048 : IsTransient = 0;
102 :
103 21048 : if ( st->last_extl != st->extl )
104 : {
105 2284 : st->TransientHangOver = 0;
106 2284 : st->old_hpfilt_in = 0;
107 2284 : st->old_hpfilt_out = 0;
108 2284 : st->Energy_Old = 0;
109 : }
110 :
111 : /* High-pass filter */
112 21048 : hp_filter( in, out_filt, &( st->old_hpfilt_in ), &( st->old_hpfilt_out ), L );
113 :
114 : /* Long-term energy */
115 21048 : if ( st->last_extl != st->extl || ( st->last_extl == st->extl && st->last_core != st->core ) || st->last_codec_mode == MODE2 )
116 : {
117 10196 : EnergyLT = EPSILON;
118 2010276 : for ( i = 0; i < L / 4; i++ )
119 : {
120 2000080 : EnergyLT += out_filt[i] * out_filt[i];
121 : }
122 : }
123 : else
124 : {
125 10852 : EnergyLT = st->EnergyLT;
126 : }
127 :
128 21048 : if ( L == L_FRAME8k )
129 : {
130 0 : Energy_in[0] = st->Energy_Old;
131 0 : E_in = 0;
132 0 : E_out = 0;
133 :
134 : /* Compute block energy */
135 0 : for ( blk = 0; blk < 4; blk++ )
136 : {
137 0 : Energy = EPSILON;
138 0 : Energy_in[blk + 1] = EPSILON;
139 :
140 0 : for ( i = 0; i < L / 4; i++ )
141 : {
142 0 : Energy += out_filt[i + blk * ( L / 4 )] * out_filt[i + blk * ( L / 4 )];
143 0 : Energy_in[blk + 1] += in[i + blk * ( L / 4 )] * in[i + blk * ( L / 4 )];
144 : }
145 :
146 0 : E_in += Energy_in[blk + 1];
147 0 : E_out += Energy;
148 :
149 0 : Thres = 15.f;
150 :
151 0 : if ( Energy > 6.0f * EnergyLT )
152 : {
153 0 : IsTransient = 1;
154 0 : position = blk;
155 : }
156 :
157 0 : EnergyLT = 0.75f * EnergyLT + 0.25f * Energy;
158 : }
159 : }
160 : else
161 : {
162 : /* Compute block energy */
163 105240 : for ( blk = 0; blk < 4; blk++ )
164 : {
165 84192 : Energy = EPSILON;
166 12189792 : for ( i = 0; i < L / 4; i++ )
167 : {
168 12105600 : Energy += out_filt[i + blk * ( L / 4 )] * out_filt[i + blk * ( L / 4 )];
169 : }
170 :
171 84192 : if ( st->extl == SWB_BWE || st->extl == FB_BWE )
172 : {
173 47688 : if ( ( Energy > 13.5f * EnergyLT ) || ( Energy > 10.0f * EnergyLT && st->core == ACELP_CORE && st->coder_type == INACTIVE ) )
174 : {
175 257 : IsTransient = 1;
176 257 : position = blk;
177 : }
178 : }
179 : else
180 : {
181 36504 : if ( st->total_brate <= HQ_16k40 && st->bwidth == SWB )
182 : {
183 136 : thr = 13.5f;
184 : }
185 : else
186 : {
187 36368 : thr = 6.0f;
188 : }
189 :
190 36504 : if ( Energy > thr * EnergyLT )
191 : {
192 365 : IsTransient = 1;
193 365 : position = blk;
194 : }
195 : }
196 :
197 84192 : EnergyLT = 0.75f * EnergyLT + 0.25f * Energy;
198 : }
199 : }
200 :
201 21048 : st->EnergyLT = EnergyLT;
202 :
203 21048 : if ( ( st->last_extl != SWB_BWE && st->last_extl != SWB_TBE && st->extl == SWB_BWE ) ||
204 19925 : ( st->last_extl != FB_BWE && st->last_extl != FB_TBE && st->extl == FB_BWE ) )
205 : {
206 1196 : IsTransient = 0;
207 : }
208 :
209 21048 : if ( IsTransient && L == L_FRAME8k )
210 : {
211 0 : E_low = 0.f;
212 0 : blk = 0;
213 0 : for ( i = 0; i < position + 1; i++ )
214 : {
215 0 : E_low += Energy_in[i];
216 0 : blk++;
217 : }
218 0 : E_low /= (float) blk;
219 :
220 0 : E_high = 0.f;
221 0 : blk = 0;
222 0 : for ( i = position + 1; i < 5; i++ )
223 : {
224 0 : E_high += Energy_in[i];
225 0 : blk++;
226 : }
227 0 : E_high /= (float) blk;
228 :
229 0 : if ( ( ( E_high / E_low < 2.0f ) && ( E_high / E_low > 0.7f ) ) && ( ( E_in / E_out ) > Thres ) )
230 : {
231 0 : IsTransient = 0;
232 : }
233 : }
234 :
235 21048 : if ( IsTransient )
236 : {
237 456 : if ( L == L_FRAME8k )
238 : {
239 0 : if ( position == 3 )
240 : {
241 0 : st->TransientHangOver = 1;
242 : }
243 : }
244 : else
245 : {
246 456 : st->TransientHangOver = 1;
247 : }
248 : }
249 : else
250 : {
251 20592 : if ( st->TransientHangOver )
252 : {
253 328 : st->TransientHangOver = 0;
254 328 : IsTransient = 1;
255 : }
256 : }
257 :
258 21048 : if ( L == L_FRAME8k )
259 : {
260 0 : st->Energy_Old = Energy_in[4];
261 : }
262 :
263 21048 : return IsTransient;
264 : }
|