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 : #include <stdint.h>
34 : #include "options.h"
35 : #ifdef DEBUGGING
36 : #include "debug.h"
37 : #endif
38 : #include "math.h"
39 : #include "wmc_auto.h"
40 : #include "prot.h"
41 : #include "ivas_cnst.h"
42 : #include "ivas_prot.h"
43 : #include "ivas_stat_com.h"
44 :
45 : /*------------------------------------------------------------------------------------------*
46 : * Local constants
47 : *------------------------------------------------------------------------------------------*/
48 :
49 : #define IVAS_TDET_PARM_ENV_EPS ( 1e-5f )
50 : #define IVAS_TDET_DUCK_MULT_FAC ( 1.1f )
51 : #define IVAS_TDET_PARM_TRANS_THR ( 0.1f )
52 : #define IVAS_TDET_ONLY ( 1 )
53 :
54 : /*env_hpf*/
55 : #define IVAS_C_HPF_48k ( 0.675231906655777f )
56 : #define IVAS_C_HPF_32k ( 0.554854910159853f )
57 : #define IVAS_C_HPF_16k ( 0.307863971328499f )
58 :
59 : /*env_fast*/
60 : #define IVAS_C_FAST_48k ( 0.995842001845110f )
61 : #define IVAS_C_FAST_32k ( 0.993769490623395f )
62 : #define IVAS_C_FAST_16k ( 0.987577800493881f )
63 :
64 : /*env_slow*/
65 : #define IVAS_C_SLOW_48k ( 0.999739617238810f )
66 : #define IVAS_C_SLOW_32k ( 0.999609451284012f )
67 : #define IVAS_C_SLOW_16k ( 0.999219055096324f )
68 :
69 : /*induck*/
70 : #define IVAS_C_IN_DUCK_48k ( 0.999583420126834f )
71 : #define IVAS_C_IN_DUCK_32k ( 0.999375195271816f )
72 : #define IVAS_C_IN_DUCK_16k ( 0.998750780924581f )
73 :
74 : /*outduck*/
75 : #define IVAS_C_OUT_DUCK_48k ( 0.999583420126834f )
76 : #define IVAS_C_OUT_DUCK_32k ( 0.999375195271816f )
77 : #define IVAS_C_OUT_DUCK_16k ( 0.998750780924581f )
78 :
79 :
80 : /*-----------------------------------------------------------------------------------------*
81 : * Function ivas_transient_det_init()
82 : *
83 : * Trans det init fucntion
84 : *-----------------------------------------------------------------------------------------*/
85 :
86 5297 : static void ivas_transient_det_init(
87 : ivas_trans_det_state_t *hTranDet, /* i/o: Transient detector handle */
88 : const int32_t sampling_rate /* i : sampling rate */
89 : )
90 : {
91 : int16_t i;
92 : float filt_coeff_arr[3][IVAS_BIQUAD_FILT_LEN << 1];
93 :
94 5297 : hTranDet->in_duck_gain = 1.0f;
95 5297 : hTranDet->out_duck_gain = 1.0f;
96 :
97 21188 : for ( i = 0; i < 3; i++ )
98 : {
99 15891 : set_zero( filt_coeff_arr[i], IVAS_BIQUAD_FILT_LEN << 1 );
100 : }
101 :
102 5297 : switch ( sampling_rate )
103 : {
104 3311 : case 48000:
105 : /*env_hpf*/
106 3311 : filt_coeff_arr[0][0] = IVAS_C_HPF_48k;
107 3311 : filt_coeff_arr[0][1] = -IVAS_C_HPF_48k;
108 3311 : filt_coeff_arr[0][3] = 1.0f;
109 3311 : filt_coeff_arr[0][4] = -IVAS_C_HPF_48k;
110 : /*env_fast*/
111 3311 : filt_coeff_arr[1][0] = 1.0f - IVAS_C_FAST_48k;
112 3311 : filt_coeff_arr[1][3] = 1.0f;
113 3311 : filt_coeff_arr[1][4] = -IVAS_C_FAST_48k;
114 : /*env_slow*/
115 3311 : filt_coeff_arr[2][0] = 1.0f - IVAS_C_SLOW_48k;
116 3311 : filt_coeff_arr[2][3] = 1.0f;
117 3311 : filt_coeff_arr[2][4] = -IVAS_C_SLOW_48k;
118 3311 : hTranDet->in_duck_coeff = IVAS_C_IN_DUCK_48k;
119 3311 : hTranDet->out_duck_coeff = IVAS_C_OUT_DUCK_48k;
120 3311 : break;
121 1521 : case 32000:
122 : /*env_hpf*/
123 1521 : filt_coeff_arr[0][0] = IVAS_C_HPF_32k;
124 1521 : filt_coeff_arr[0][1] = -IVAS_C_HPF_32k;
125 1521 : filt_coeff_arr[0][3] = 1.0f;
126 1521 : filt_coeff_arr[0][4] = -IVAS_C_HPF_32k;
127 : /*env_fast*/
128 1521 : filt_coeff_arr[1][0] = 1.0f - IVAS_C_FAST_32k;
129 1521 : filt_coeff_arr[1][3] = 1.0f;
130 1521 : filt_coeff_arr[1][4] = -IVAS_C_FAST_32k;
131 : /*env_slow*/
132 1521 : filt_coeff_arr[2][0] = 1.0f - IVAS_C_SLOW_32k;
133 1521 : filt_coeff_arr[2][3] = 1.0f;
134 1521 : filt_coeff_arr[2][4] = -IVAS_C_SLOW_32k;
135 1521 : hTranDet->in_duck_coeff = IVAS_C_IN_DUCK_32k;
136 1521 : hTranDet->out_duck_coeff = IVAS_C_OUT_DUCK_32k;
137 1521 : break;
138 465 : case 16000:
139 : /*env_hpf*/
140 465 : filt_coeff_arr[0][0] = IVAS_C_HPF_16k;
141 465 : filt_coeff_arr[0][1] = -IVAS_C_HPF_16k;
142 465 : filt_coeff_arr[0][3] = 1.0f;
143 465 : filt_coeff_arr[0][4] = -IVAS_C_HPF_16k;
144 : /*env_fast*/
145 465 : filt_coeff_arr[1][0] = 1.0f - IVAS_C_FAST_16k;
146 465 : filt_coeff_arr[1][3] = 1.0f;
147 465 : filt_coeff_arr[1][4] = -IVAS_C_FAST_16k;
148 : /*env_slow*/
149 465 : filt_coeff_arr[2][0] = 1.0f - IVAS_C_SLOW_16k;
150 465 : filt_coeff_arr[2][3] = 1.0f;
151 465 : filt_coeff_arr[2][4] = -IVAS_C_SLOW_16k;
152 465 : hTranDet->in_duck_coeff = IVAS_C_IN_DUCK_16k;
153 465 : hTranDet->out_duck_coeff = IVAS_C_OUT_DUCK_16k;
154 465 : break;
155 : }
156 :
157 5297 : ivas_filters_init( &hTranDet->env_hpf, (const float *) filt_coeff_arr[0], IVAS_FILTER_ORDER_1 );
158 5297 : ivas_filters_init( &hTranDet->env_fast, (const float *) filt_coeff_arr[1], IVAS_FILTER_ORDER_1 );
159 5297 : ivas_filters_init( &hTranDet->env_slow, (const float *) filt_coeff_arr[2], IVAS_FILTER_ORDER_1 );
160 :
161 5297 : hTranDet->duck_mult_fac = IVAS_TDET_DUCK_MULT_FAC;
162 :
163 5297 : return;
164 : }
165 :
166 :
167 : /*-------------------------------------------------------------------------
168 : * ivas_transient_det_open()
169 : *
170 : * Allocate and initialize SPAR TD handle
171 : *------------------------------------------------------------------------*/
172 :
173 5297 : ivas_error ivas_transient_det_open(
174 : ivas_trans_det_state_t **hTranDet_in, /* i/o: Transient detector handle */
175 : const int32_t sampling_rate /* i : sampling rate */
176 : )
177 : {
178 : ivas_trans_det_state_t *hTranDet;
179 :
180 5297 : if ( ( hTranDet = (ivas_trans_det_state_t *) malloc( sizeof( ivas_trans_det_state_t ) ) ) == NULL )
181 : {
182 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR TD\n" );
183 : }
184 :
185 5297 : ivas_transient_det_init( hTranDet, sampling_rate );
186 :
187 5297 : *hTranDet_in = hTranDet;
188 :
189 5297 : return IVAS_ERR_OK;
190 : }
191 :
192 :
193 : /*-------------------------------------------------------------------------
194 : * ivas_transient_det_close()
195 : *
196 : * Deallocate and initialize Transient detector handle
197 : *------------------------------------------------------------------------*/
198 :
199 5297 : void ivas_transient_det_close(
200 : ivas_trans_det_state_t **hTranDet /* i/o: Transient detector handle */
201 : )
202 : {
203 5297 : if ( hTranDet == NULL || *hTranDet == NULL )
204 : {
205 0 : return;
206 : }
207 :
208 5297 : free( *hTranDet );
209 5297 : *hTranDet = NULL;
210 :
211 5297 : return;
212 : }
213 :
214 :
215 : /*-----------------------------------------------------------------------------------------*
216 : * Function ivas_transient_det_process()
217 : *
218 : * Transient detection process call
219 : *-----------------------------------------------------------------------------------------*/
220 :
221 165820 : void ivas_transient_det_process(
222 : ivas_trans_det_state_t *hTranDet, /* i/o: SPAR TD handle */
223 : float *pIn_pcm, /* i : input audio channels */
224 : const int16_t frame_len, /* i : frame length in samples */
225 : int16_t transient_det[2] /* o : transient det outputs */
226 : )
227 : {
228 : float in_duck_gain[L_FRAME48k];
229 : int16_t num_sf, sf, sf_samp, idx;
230 165820 : float mem = hTranDet->in_duck_gain;
231 :
232 165820 : ivas_td_decorr_get_ducking_gains( hTranDet, pIn_pcm, in_duck_gain, NULL, frame_len, IVAS_TDET_ONLY );
233 :
234 165820 : transient_det[0] = 0;
235 165820 : transient_det[1] = 0;
236 165820 : if ( mem - hTranDet->in_duck_gain > IVAS_TDET_PARM_TRANS_THR )
237 : {
238 16926 : transient_det[0] = 1;
239 : }
240 :
241 165820 : num_sf = 16;
242 165820 : sf_samp = frame_len / num_sf;
243 2818940 : for ( sf = 1; sf <= num_sf; sf++ )
244 : {
245 2653120 : idx = ( sf_samp * sf ) - 1;
246 2653120 : if ( ( mem - in_duck_gain[idx] ) > ( IVAS_TDET_PARM_TRANS_THR * 1.1f ) )
247 : {
248 8796 : transient_det[1] = 1;
249 : }
250 2653120 : mem = in_duck_gain[idx];
251 : }
252 :
253 165820 : return;
254 : }
255 :
256 :
257 : /*-----------------------------------------------------------------------------------------*
258 : * Function ivas_calc_duck_gain()
259 : *
260 : * Calculate ducking gain utility
261 : *-----------------------------------------------------------------------------------------*/
262 :
263 583864440 : static float ivas_calc_duck_gain(
264 : const float duck_gain,
265 : const float duck_coeff,
266 : const float env_1,
267 : const float env_2,
268 : const float duck_mult_fac )
269 : {
270 : float duck_gain_out;
271 :
272 583864440 : duck_gain_out = ( duck_gain - 1 ) * duck_coeff + 1;
273 :
274 583864440 : if ( ( duck_mult_fac * env_1 ) < duck_gain_out * env_2 )
275 : {
276 38076326 : duck_gain_out = duck_mult_fac * ( env_1 / env_2 );
277 : }
278 :
279 583864440 : return duck_gain_out;
280 : }
281 :
282 :
283 : /*-----------------------------------------------------------------------------------------*
284 : * Function ivas_td_decorr_get_ducking_gains()
285 : *
286 : * Calculate in/out ducking gains
287 : *-----------------------------------------------------------------------------------------*/
288 :
289 447268 : void ivas_td_decorr_get_ducking_gains(
290 : ivas_trans_det_state_t *hTranDet, /* i/o: Transient detector handle */
291 : float *pIn_pcm,
292 : float *pIn_duck_gains,
293 : float *pOut_duck_gains,
294 : const int16_t frame_len,
295 : const int16_t tdet_flag )
296 : {
297 : int16_t i;
298 : float e_fast[L_FRAME48k], e_slow[L_FRAME48k];
299 447268 : float in_duck_gain = hTranDet->in_duck_gain;
300 447268 : float out_duck_gain = hTranDet->out_duck_gain;
301 447268 : float in_duck_coeff = hTranDet->in_duck_coeff;
302 447268 : float out_duck_coeff = hTranDet->out_duck_coeff;
303 447268 : float duck_mult_fac = hTranDet->duck_mult_fac;
304 :
305 447268 : mvr2r( pIn_pcm, e_fast, frame_len );
306 :
307 : /* env hpf */
308 447268 : ivas_filter_process( &hTranDet->env_hpf, e_fast, frame_len );
309 :
310 356853088 : for ( i = 0; i < frame_len; i++ )
311 : {
312 356405820 : e_fast[i] = (float) fabs( e_fast[i] ) + IVAS_TDET_PARM_ENV_EPS;
313 356405820 : e_slow[i] = e_fast[i];
314 : }
315 :
316 : /* env fast*/
317 447268 : ivas_filter_process( &hTranDet->env_fast, e_fast, frame_len );
318 :
319 : /* env slow */
320 447268 : ivas_filter_process( &hTranDet->env_slow, e_slow, frame_len );
321 :
322 447268 : if ( tdet_flag )
323 : {
324 129113020 : for ( i = 0; i < frame_len; i++ )
325 : {
326 128947200 : in_duck_gain = ivas_calc_duck_gain( in_duck_gain, in_duck_coeff, e_slow[i], e_fast[i], duck_mult_fac );
327 128947200 : pIn_duck_gains[i] = in_duck_gain;
328 : }
329 165820 : hTranDet->in_duck_gain = in_duck_gain;
330 : }
331 : else
332 : {
333 227740068 : for ( i = 0; i < frame_len; i++ )
334 : {
335 227458620 : in_duck_gain = ivas_calc_duck_gain( in_duck_gain, in_duck_coeff, e_slow[i], e_fast[i], duck_mult_fac );
336 227458620 : pIn_duck_gains[i] = in_duck_gain;
337 227458620 : out_duck_gain = ivas_calc_duck_gain( out_duck_gain, out_duck_coeff, e_fast[i], e_slow[i], duck_mult_fac );
338 227458620 : pOut_duck_gains[i] = out_duck_gain;
339 : }
340 281448 : hTranDet->in_duck_gain = in_duck_gain;
341 281448 : hTranDet->out_duck_gain = out_duck_gain;
342 : }
343 :
344 447268 : return;
345 : }
|