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 : #include "prot_fx.h"
36 : #include "ivas_rom_com.h"
37 : #include "wmc_auto.h"
38 : #include "ivas_prot_fx.h"
39 :
40 : /*------------------------------------------------------------------------------------------*
41 : * Local constants
42 : *------------------------------------------------------------------------------------------*/
43 :
44 : #define MIN_POOL_SIZE 24
45 : #define MIN_POOL_SIZE_DTX 40
46 : #define MAX_UPDATE_RATE_Q31 ( 1717986944 )
47 : #define MAX_UPDATE_RATE_DTX_Q31 ( 858993472 )
48 :
49 :
50 : /*------------------------------------------------------------------------------------------*
51 : * Local functions declarations
52 : *------------------------------------------------------------------------------------------*/
53 :
54 : static void ivas_band_cov_fx( Word32 **ppIn_FR_real, Word32 **ppIn_FR_imag, Word16 q_In_FR, const Word16 num_chans, const Word16 num_bins, Word16 stride, Word32 **pFb_bin_to_band, const Word16 *pFb_start_bin_per_band, const Word16 *pFb_active_bins_per_band, const Word16 start_band, const Word16 end_band, Word32 *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], Word16 *q_cov_real[IVAS_SPAR_MAX_CH], const Word16 HOA_md_ind[IVAS_SPAR_MAX_CH] );
55 :
56 : /*-------------------------------------------------------------------------
57 : * ivas_spar_covar_enc_open_fx()
58 : *
59 : * Allocate and initialize SPAR Covar. encoder handle
60 : *------------------------------------------------------------------------*/
61 :
62 1606 : ivas_error ivas_spar_covar_enc_open_fx(
63 : ivas_enc_cov_handler_state_t **hCovEnc, /* i/o: SPAR Covar. encoder handle */
64 : ivas_filterbank_t *pFb, /* i/o: FB handle */
65 : const Word32 input_Fs, /* i : input sampling rate Q0*/
66 : const Word16 nchan_inp, /* i : number of input channels Q0*/
67 : const COV_SMOOTHING_TYPE smooth_mode, /* i : Smooth covariance for SPAR or MC */
68 : const Word32 ivas_total_brate /* i : IVAS total bitrate Q0*/
69 : )
70 : {
71 : ivas_enc_cov_handler_state_t *hCovState;
72 : ivas_cov_smooth_cfg_t cov_smooth_cfg;
73 : ivas_error error;
74 :
75 1606 : error = IVAS_ERR_OK;
76 1606 : move32();
77 :
78 1606 : IF( ( hCovState = (ivas_enc_cov_handler_state_t *) malloc( sizeof( ivas_enc_cov_handler_state_t ) ) ) == NULL )
79 : {
80 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR COV encoder" );
81 : }
82 :
83 1606 : cov_smooth_cfg.max_bands = IVAS_MAX_NUM_BANDS;
84 1606 : move16();
85 1606 : cov_smooth_cfg.max_update_rate_fx = MAX_UPDATE_RATE_Q31;
86 1606 : move32();
87 1606 : cov_smooth_cfg.min_pool_size = MIN_POOL_SIZE;
88 1606 : move16();
89 1606 : IF( EQ_32( smooth_mode, COV_SMOOTH_MC ) )
90 : {
91 48 : cov_smooth_cfg.max_update_rate_fx = ONE_IN_Q31; // Q31
92 48 : move32();
93 48 : cov_smooth_cfg.min_pool_size = 20; // Q0
94 48 : move16();
95 : }
96 :
97 1606 : IF( NE_32( ( error = ivas_spar_covar_smooth_enc_open_fx( &hCovState->pCov_state, &cov_smooth_cfg, pFb, nchan_inp, smooth_mode, ivas_total_brate ) ), IVAS_ERR_OK ) )
98 : {
99 0 : return error;
100 : }
101 :
102 1606 : cov_smooth_cfg.max_update_rate_fx = MAX_UPDATE_RATE_DTX_Q31;
103 1606 : move32();
104 1606 : cov_smooth_cfg.min_pool_size = MIN_POOL_SIZE_DTX;
105 1606 : move16();
106 :
107 1606 : IF( NE_32( ( error = ivas_spar_covar_smooth_enc_open_fx( &hCovState->pCov_dtx_state, &cov_smooth_cfg, pFb, nchan_inp, smooth_mode, ivas_total_brate ) ), IVAS_ERR_OK ) )
108 : {
109 0 : return error;
110 : }
111 :
112 1606 : hCovState->num_bins = extract_l( Mpy_32_32( input_Fs, ONE_BY_FRAMES_PER_SEC_Q31 ) ); /* Q0 */
113 1606 : hCovState->prior_dtx_present = 0;
114 1606 : move16();
115 :
116 1606 : set_zero_fx( hCovState->bb_var_lt_fx, FOA_CHANNELS );
117 1606 : hCovState->prior_var_flag = -1;
118 1606 : move16();
119 :
120 1606 : *hCovEnc = hCovState;
121 :
122 1606 : return error;
123 : }
124 :
125 :
126 : /*-------------------------------------------------------------------------
127 : * ivas_spar_covar_enc_close_fx()
128 : *
129 : * Deallocate SPAR Covar. encoder handle
130 : *------------------------------------------------------------------------*/
131 :
132 1606 : void ivas_spar_covar_enc_close_fx(
133 : ivas_enc_cov_handler_state_t **hCovEnc, /* i/o: SPAR Covar. encoder handle */
134 : const Word16 nchan_inp /* i : number of input channels Q0*/
135 : )
136 : {
137 : ivas_enc_cov_handler_state_t *hCovState;
138 :
139 1606 : test();
140 1606 : IF( hCovEnc == NULL || *hCovEnc == NULL )
141 : {
142 0 : return;
143 : }
144 :
145 1606 : hCovState = *hCovEnc;
146 :
147 1606 : ivas_spar_covar_smooth_enc_close_fx( &hCovState->pCov_state, nchan_inp );
148 :
149 1606 : ivas_spar_covar_smooth_enc_close_fx( &hCovState->pCov_dtx_state, nchan_inp );
150 :
151 1606 : free( *hCovEnc );
152 1606 : *hCovEnc = NULL;
153 :
154 1606 : return;
155 : }
156 :
157 :
158 : /*-----------------------------------------------------------------------------------------*
159 : * Function ivas_spar_get_activeW_flag_fx()
160 : *
161 : *
162 : *-----------------------------------------------------------------------------------------*/
163 :
164 72649 : static Word16 ivas_spar_get_activeW_flag_fx(
165 : ivas_enc_cov_handler_state_t *hCovEnc,
166 : Word32 *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], /* q_cov_real */
167 : Word32 *cov_dtx_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], /* q_cov_real */
168 : Word16 *q_cov_real[IVAS_SPAR_MAX_CH],
169 : const Word16 dtx_vad, /* Q0 */
170 : const Word16 nchan_inp, /* Q0 */
171 : const Word16 nchan_transport, /* Q0 */
172 : Word16 *res_ind, /* Q0 */
173 : const Word16 *dmx_order /* Q0 */
174 : )
175 : {
176 : Word16 b, ch, num_bands, num_chs, activeW_flag;
177 : Word32 bb_var[FOA_CHANNELS], sm_fact, side_ch_var, en_ratio;
178 : Word64 bb_var_64bit[FOA_CHANNELS];
179 : Word16 q_shift;
180 : Word16 q_bb_var[FOA_CHANNELS];
181 : Word32 L_tmp, L_tmp1;
182 : Word16 exp_diff, q_com, guard_bits;
183 :
184 72649 : num_chs = s_min( nchan_inp, FOA_CHANNELS ); /* Q0 */
185 72649 : num_bands = ivas_get_num_bands_from_bw_idx( SPAR_CONFIG_BW ); /* Q0 */
186 :
187 72649 : set_zero_fx( bb_var, FOA_CHANNELS );
188 72649 : set_s( q_bb_var, Q31, FOA_CHANNELS );
189 363245 : FOR( ch = 0; ch < FOA_CHANNELS; ch++ )
190 : {
191 290596 : bb_var_64bit[ch] = 0;
192 290596 : move64();
193 : }
194 :
195 72649 : IF( EQ_16( dtx_vad, 1 ) )
196 : {
197 355795 : FOR( ch = 0; ch < num_chs; ch++ )
198 : {
199 3700268 : FOR( b = 0; b < num_bands; b++ )
200 : {
201 3415632 : bb_var_64bit[ch] = W_add_nosat( bb_var_64bit[ch], W_deposit32_l( cov_real[ch][ch][b] ) ); // q_cov_real[ch][ch]
202 3415632 : move64();
203 3415632 : q_bb_var[ch] = q_cov_real[ch][ch];
204 3415632 : move16();
205 : }
206 : }
207 : }
208 : ELSE
209 : {
210 7450 : FOR( ch = 0; ch < num_chs; ch++ )
211 : {
212 77480 : FOR( b = 0; b < num_bands; b++ )
213 : {
214 71520 : bb_var_64bit[ch] = W_add_nosat( bb_var_64bit[ch], W_deposit32_l( cov_dtx_real[ch][ch][b] ) ); // q_cov_real[ch][ch]
215 71520 : move64();
216 71520 : q_bb_var[ch] = q_cov_real[ch][ch];
217 71520 : move16();
218 : }
219 : }
220 : }
221 :
222 363245 : FOR( ch = 0; ch < num_chs; ch++ )
223 : {
224 290596 : q_shift = Q31;
225 290596 : move16();
226 290596 : q_shift = W_norm( bb_var_64bit[ch] );
227 290596 : bb_var[ch] = W_extract_l( W_shl_nosat( bb_var_64bit[ch], sub( q_shift, 32 ) ) ); /* q_bb_var[ch] + sub( q_shift, 32 ) */
228 290596 : move32();
229 290596 : q_bb_var[ch] = add( q_bb_var[ch], sub( q_shift, 32 ) );
230 290596 : move16();
231 : }
232 :
233 72649 : IF( EQ_16( hCovEnc->prior_var_flag, -1 ) )
234 : {
235 363245 : FOR( ch = 0; ch < num_chs; ch++ )
236 : {
237 290596 : hCovEnc->bb_var_lt_fx[ch] = bb_var[ch]; // q_bb_var[ch]
238 290596 : move32();
239 : }
240 : }
241 : ELSE
242 : {
243 0 : sm_fact = ONE_IN_Q30; // Q31
244 0 : move32();
245 0 : FOR( ch = 0; ch < num_chs; ch++ )
246 : {
247 0 : L_tmp = Mpy_32_32( sm_fact, hCovEnc->bb_var_lt_fx[ch] ); // (Q31, q_bb_var[ch]) -> q_bb_var[ch]
248 0 : L_tmp1 = Mpy_32_32( L_sub( ONE_IN_Q31, sm_fact ), bb_var[ch] ); // (Q31, q_bb_var[ch]) -> q_bb_var[ch]
249 0 : hCovEnc->bb_var_lt_fx[ch] = L_add( L_tmp, L_tmp1 ); // q_bb_var[ch]
250 0 : move32();
251 : }
252 : }
253 :
254 72649 : side_ch_var = L_deposit_l( EPSILLON_FX ); // Note: To handle divide-by-0 asserts
255 72649 : guard_bits = find_guarded_bits_fx( L_deposit_l( sub( num_chs, nchan_transport ) ) );
256 72649 : q_com = Q20;
257 72649 : move16();
258 185468 : FOR( ch = nchan_transport; ch < num_chs; ch++ )
259 : {
260 112819 : q_com = s_min( q_com, q_bb_var[dmx_order[ch]] );
261 : }
262 185468 : FOR( ch = nchan_transport; ch < num_chs; ch++ )
263 : {
264 112819 : side_ch_var = L_add( side_ch_var, L_shr( L_shl( hCovEnc->bb_var_lt_fx[dmx_order[ch]], sub( q_com, q_bb_var[dmx_order[ch]] ) ), guard_bits ) ); // Q(q_com - guard_bits)
265 : }
266 :
267 72649 : IF( LT_32( side_ch_var, L_shl( L_mult0( IVAS_SPAR_SIDE_CH_DYN_ACTIVEW_THRESH_Q0, IVAS_SPAR_SIDE_CH_DYN_ACTIVEW_THRESH_Q0 ), sub( q_com, guard_bits ) ) ) ) // LHS Q(q_com - guard_bits) :: RHS Q(q_com - guard_bits)
268 : {
269 2437 : activeW_flag = 0;
270 2437 : move16();
271 : }
272 : ELSE
273 : {
274 70212 : L_tmp = BASOP_Util_Divide3232_Scale_newton( hCovEnc->bb_var_lt_fx[0], side_ch_var, &exp_diff ); // (Q31 - exp_diff)
275 70212 : en_ratio = L_shl_sat( L_tmp, exp_diff ); // Q31
276 70212 : IF( LT_32( en_ratio, Mpy_32_32( IVAS_SPAR_DYN_ACTIVEW_THRESH_FX, IVAS_SPAR_DYN_ACTIVEW_THRESH_FX ) ) ) // LHS Q31 :: RHS Q31
277 : {
278 0 : activeW_flag = 1;
279 0 : move16();
280 : }
281 : ELSE
282 : {
283 70212 : activeW_flag = 0;
284 70212 : move16();
285 : }
286 : }
287 :
288 72649 : IF( activeW_flag )
289 : {
290 0 : *res_ind = 0;
291 0 : move16();
292 0 : IF( EQ_16( nchan_transport, 2 ) )
293 : {
294 : Word16 max_idx;
295 : Word32 max_val;
296 0 : max_idx = nchan_transport; /* Q0 */
297 0 : move16();
298 0 : max_val = hCovEnc->bb_var_lt_fx[max_idx]; // q_bb_var[max_idx]
299 0 : move32();
300 0 : FOR( ch = nchan_transport; ch < num_chs; ch++ ){
301 0 : IF( GT_32( hCovEnc->bb_var_lt_fx[ch], max_val ) ){
302 0 : max_idx = ch;
303 0 : move16();
304 0 : max_val = hCovEnc->bb_var_lt_fx[ch];
305 0 : move32();
306 : }
307 : }
308 0 : *res_ind = max_idx; /* Q0 */
309 0 : move16();
310 : }
311 0 : ELSE IF( EQ_16( nchan_transport, 3 ) )
312 : {
313 0 : *res_ind = dmx_order[nchan_transport]; /* Q0 */
314 0 : move16();
315 : }
316 : }
317 :
318 72649 : return activeW_flag;
319 : }
320 :
321 :
322 : /*-----------------------------------------------------------------------------------------*
323 : * Function ivas_enc_cov_handler_process_fx()
324 : *
325 : * Encoder covariance handler process call
326 : *-----------------------------------------------------------------------------------------*/
327 :
328 160660 : void ivas_enc_cov_handler_process_fx(
329 : ivas_enc_cov_handler_state_t *hCovEnc, /* i/o: SPAR Covar. encoder handle */
330 : Word32 **ppIn_FR_real, /* q_ppIn_FR */
331 : Word32 **ppIn_FR_imag, /* q_ppIn_FR */
332 : Word16 q_ppIn_FR,
333 : Word32 *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], /* q_cov_real */
334 : Word16 *q_cov_real[IVAS_SPAR_MAX_CH],
335 : Word32 *cov_dtx_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], /* q_cov_dtx_real */
336 : Word16 *q_cov_dtx_real[IVAS_SPAR_MAX_CH],
337 : ivas_filterbank_t *pFb, /* i/o: FB handle */
338 : const Word16 start_band, /* Q0 */
339 : const Word16 end_band, /* Q0 */
340 : const Word16 num_ch, /* Q0 */
341 : const Word16 dtx_vad, /* Q0 */
342 : const Word16 transient_det[2], /* Q0 */
343 : const Word16 HOA_md_ind[IVAS_SPAR_MAX_CH], /* Q0 */
344 : Word16 *res_ind, /* Q0 */
345 : const Word16 *remix_order, /* Q0 */
346 : Word16 *dyn_active_w_flag, /* Q0 */
347 : const Word16 nchan_transport, /* Q0 */
348 : const Word16 is_sba /* Q0 */
349 : )
350 : {
351 : Word16 i, j;
352 : Word16 dtx_cov_flag;
353 : Word16 cov_real_zero[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH];
354 : Word16 k;
355 :
356 160660 : IF( EQ_16( dtx_vad, 1 ) )
357 : {
358 154137 : dtx_cov_flag = 0;
359 154137 : move16();
360 : }
361 : ELSE
362 : {
363 6523 : dtx_cov_flag = 1;
364 6523 : move16();
365 : }
366 :
367 160660 : ivas_band_cov_fx( ppIn_FR_real, ppIn_FR_imag, q_ppIn_FR, num_ch, hCovEnc->num_bins,
368 160660 : pFb->fb_bin_to_band.short_stride,
369 160660 : pFb->fb_bin_to_band.pp_short_stride_bin_to_band_fx, // Q22
370 160660 : pFb->fb_bin_to_band.p_short_stride_start_bin_per_band,
371 160660 : pFb->fb_bin_to_band.p_short_stride_num_bins_per_band,
372 : start_band, end_band, cov_real, q_cov_real, HOA_md_ind );
373 :
374 899180 : FOR( i = 0; i < num_ch; i++ )
375 : {
376 738520 : set_s( cov_real_zero[i], 1, num_ch );
377 : }
378 : // Check if a particular band array is zero
379 899180 : FOR( i = 0; i < num_ch; i++ )
380 : {
381 4647620 : FOR( j = 0; j < num_ch; j++ )
382 : {
383 6409440 : FOR( k = start_band; k < end_band; k++ )
384 : {
385 6200625 : IF( cov_real[i][j][k] != 0 )
386 : {
387 3700285 : cov_real_zero[i][j] = 0;
388 3700285 : move16();
389 3700285 : BREAK;
390 : }
391 : }
392 : }
393 : }
394 : // Set q_cov_real to Q31 for the zero band array
395 899180 : FOR( i = 0; i < num_ch; i++ )
396 : {
397 4647620 : FOR( j = 0; j < num_ch; j++ )
398 : {
399 3909100 : IF( EQ_16( cov_real_zero[i][j], 1 ) )
400 : {
401 208815 : q_cov_real[i][j] = Q31;
402 208815 : move16();
403 : }
404 : }
405 : }
406 :
407 160660 : IF( is_sba )
408 : {
409 157500 : *res_ind = 0;
410 157500 : move16();
411 157500 : IF( GT_16( nchan_transport, 1 ) && LE_16( nchan_transport, sub( FOA_CHANNELS, 1 ) ) )
412 : {
413 72649 : *dyn_active_w_flag = ivas_spar_get_activeW_flag_fx( hCovEnc, cov_real, cov_real, q_cov_real, dtx_vad, num_ch, nchan_transport, res_ind, remix_order ); /* Q0 */
414 : }
415 : ELSE
416 : {
417 84851 : *dyn_active_w_flag = 0;
418 84851 : move16();
419 : }
420 : }
421 :
422 899180 : FOR( i = 0; i < num_ch; i++ )
423 : {
424 4647620 : FOR( j = 0; j < num_ch; j++ )
425 : {
426 3909100 : Copy32( cov_real[i][j], cov_dtx_real[i][j], pFb->filterbank_num_bands ); /* q_cov_real */
427 3909100 : q_cov_dtx_real[i][j] = q_cov_real[i][j];
428 3909100 : move16();
429 : }
430 : }
431 :
432 160660 : ivas_cov_smooth_process_fx( hCovEnc->pCov_state, cov_real, pFb, start_band, end_band, num_ch, transient_det, q_cov_real );
433 :
434 160660 : IF( dtx_cov_flag == 0 )
435 : {
436 872885 : FOR( i = 0; i < num_ch; i++ )
437 : {
438 4561400 : FOR( j = 0; j < num_ch; j++ )
439 : {
440 3842652 : Copy32( cov_real[i][j], hCovEnc->pCov_dtx_state->pPrior_cov_real_fx[i][j], pFb->filterbank_num_bands ); /* q_cov_real */
441 49553516 : FOR( k = 0; k < pFb->filterbank_num_bands; k++ )
442 : {
443 45710864 : hCovEnc->pCov_dtx_state->q_prior_cov_real_per_band[i][j][k] = hCovEnc->pCov_state->q_cov_real_per_band[i][j][k];
444 45710864 : move16();
445 : }
446 3842652 : Copy32( cov_real[i][j], cov_dtx_real[i][j], pFb->filterbank_num_bands ); /* q_cov_real */
447 3842652 : Copy( hCovEnc->pCov_state->q_cov_real_per_band[i][j], hCovEnc->pCov_dtx_state->q_cov_real_per_band[i][j], pFb->filterbank_num_bands );
448 : }
449 : }
450 154137 : hCovEnc->prior_dtx_present = 1;
451 154137 : move16();
452 : }
453 : ELSE
454 : {
455 6523 : IF( transient_det[0] == 0 && transient_det[1] == 0 )
456 : {
457 5517 : ivas_cov_smooth_process_fx( hCovEnc->pCov_dtx_state, cov_dtx_real, pFb, start_band, end_band, num_ch, transient_det, q_cov_dtx_real );
458 5517 : hCovEnc->prior_dtx_present = 1;
459 5517 : move16();
460 : }
461 : ELSE
462 : {
463 1006 : IF( hCovEnc->prior_dtx_present == 0 )
464 : {
465 48 : ivas_cov_smooth_process_fx( hCovEnc->pCov_dtx_state, cov_dtx_real, pFb, start_band, end_band, num_ch, transient_det, q_cov_dtx_real );
466 48 : hCovEnc->prior_dtx_present = 1;
467 48 : move16();
468 : }
469 : ELSE
470 : {
471 3766 : FOR( i = 0; i < num_ch; i++ )
472 : {
473 11992 : FOR( j = 0; j < num_ch; j++ )
474 : {
475 9184 : Copy32( hCovEnc->pCov_dtx_state->pPrior_cov_real_fx[i][j], cov_dtx_real[i][j], pFb->filterbank_num_bands ); /* q_cov_real */
476 116320 : FOR( k = 0; k < pFb->filterbank_num_bands; k++ )
477 : {
478 107136 : hCovEnc->pCov_dtx_state->q_cov_real_per_band[i][j][k] = hCovEnc->pCov_dtx_state->q_prior_cov_real_per_band[i][j][k];
479 107136 : move16();
480 : }
481 : }
482 : }
483 958 : hCovEnc->prior_dtx_present = 1;
484 958 : move16();
485 : }
486 : }
487 : }
488 :
489 160660 : return;
490 : }
491 :
492 :
493 160660 : static void ivas_band_cov_fx(
494 : Word32 **ppIn_FR_real, /* q_In_FR */
495 : Word32 **ppIn_FR_imag, /* q_In_FR */
496 : Word16 q_In_FR,
497 : const Word16 num_chans, /* Q0 */
498 : const Word16 num_bins, /* Q0 */
499 : Word16 stride, /* Q0 */
500 : Word32 **pFb_bin_to_band, /* Q22 */
501 : const Word16 *pFb_start_bin_per_band, /* Q0 */
502 : const Word16 *pFb_active_bins_per_band, /* Q0 */
503 : const Word16 start_band, /* Q0 */
504 : const Word16 end_band, /* Q0 */
505 : Word32 *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], /* q_cov_real */
506 : Word16 *q_cov_real[IVAS_SPAR_MAX_CH],
507 : const Word16 HOA_md_ind[IVAS_SPAR_MAX_CH] /* Q0 */
508 : )
509 : {
510 : Word16 i, j, k;
511 : Word32 pV_re[L_FRAME48k];
512 : Word64 pV_re_64bit[L_FRAME48k];
513 : Word64 cov_real_64bit[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS];
514 : Word16 q_shift, q_shift_tmp;
515 : Word16 m, start_bin, active_bins;
516 : Word16 num_blocks;
517 :
518 160660 : num_blocks = idiv1616( num_bins, stride ); /* Q0 */
519 899180 : FOR( i = 0; i < num_chans; i++ )
520 : {
521 3062330 : FOR( j = i; j < num_chans; j++ )
522 : {
523 2323810 : Word16 i1 = HOA_md_ind[i]; /* Q0 */
524 2323810 : Word16 j1 = HOA_md_ind[j]; /* Q0 */
525 2323810 : move16();
526 2323810 : move16();
527 :
528 1907818210 : FOR( k = 0; k < num_bins; k++ )
529 : {
530 1905494400 : pV_re_64bit[k] = W_add( W_mult0_32_32( ppIn_FR_real[i1][k], ppIn_FR_real[j1][k] ),
531 1905494400 : W_mult0_32_32( ppIn_FR_imag[i1][k], ppIn_FR_imag[j1][k] ) ); //(q_In_FR[i1], q_In_FR[j1]) -> (q_In_FR[i1] + q_In_FR[j1])
532 1905494400 : move64();
533 : }
534 :
535 2323810 : q_shift = 31;
536 2323810 : move16();
537 1907818210 : FOR( k = 0; k < num_bins; k++ )
538 : {
539 1905494400 : q_shift_tmp = W_norm( pV_re_64bit[k] );
540 1905494400 : if ( pV_re_64bit[k] != 0 )
541 : {
542 1801818687 : q_shift = s_min( q_shift, q_shift_tmp );
543 : }
544 : }
545 2323810 : q_shift_tmp = sub( q_shift, 32 );
546 1907818210 : FOR( k = 0; k < num_bins; k++ )
547 : {
548 1905494400 : pV_re[k] = W_extract_l( W_shl_nosat( pV_re_64bit[k], q_shift_tmp ) ); //(q_In_FR[i1] + q_In_FR[j1]) + (q_shift - 32)
549 1905494400 : move32();
550 : /* perform rounding towards lower value for negative results */
551 1905494400 : if ( pV_re[k] < 0 )
552 : {
553 621752643 : pV_re[k] = L_add( pV_re[k], 1 );
554 : }
555 : }
556 :
557 29947530 : FOR( k = start_band; k < end_band; k++ )
558 : {
559 : Word64 temp;
560 27623720 : const Word32 *p_bin_to_band = pFb_bin_to_band[k]; // Q22
561 : Word32 *cov_ptr;
562 : Word16 blk;
563 :
564 27623720 : temp = 0;
565 27623720 : move64();
566 27623720 : start_bin = pFb_start_bin_per_band[k]; /* Q0 */
567 27623720 : move16();
568 27623720 : active_bins = pFb_active_bins_per_band[k]; /* Q0 */
569 27623720 : move16();
570 :
571 27623720 : cov_ptr = &pV_re[start_bin];
572 27623720 : move16();
573 138118600 : FOR( blk = 0; blk < num_blocks; blk++ )
574 : {
575 : /* optional: add temporal weight here */
576 2129723680 : FOR( m = 0; m < active_bins; m++ )
577 : {
578 2019228800 : temp = W_add( temp, W_mult0_32_32( cov_ptr[m], p_bin_to_band[m] ) ); // ((q_In_FR[i1] + q_In_FR[j1]) + (q_shift - 32), Q22) -> (q_In_FR[i1] + q_In_FR[j1] + (q_shift - 10)
579 : }
580 110494880 : cov_ptr += stride;
581 110494880 : move16();
582 : }
583 : // What basop to add below????
584 27623720 : cov_real_64bit[i][j][k] = temp * (Word64) ( num_blocks ); // (q_In_FR[i1] + q_In_FR[j1] + (q_shift - 10) - guard_bits
585 27623720 : move64();
586 27623720 : move64(); // conservative estimation of a 64 bit multiplication
587 : }
588 2323810 : q_cov_real[i][j] = add( add( q_In_FR, q_In_FR ), sub( q_shift, Q10 ) );
589 2323810 : move16();
590 : }
591 : }
592 :
593 899180 : FOR( i = 0; i < num_chans; i++ )
594 : {
595 3062330 : FOR( j = i; j < num_chans; j++ )
596 : {
597 2323810 : q_shift = 31;
598 2323810 : move16();
599 29947530 : FOR( k = start_band; k < end_band; k++ )
600 : {
601 27623720 : q_shift_tmp = W_norm( cov_real_64bit[i][j][k] );
602 27623720 : if ( cov_real_64bit[i][j][k] != 0 )
603 : {
604 26257256 : q_shift = s_min( q_shift, q_shift_tmp );
605 : }
606 : }
607 2323810 : q_shift_tmp = sub( q_shift, 32 );
608 29947530 : FOR( k = start_band; k < end_band; k++ )
609 : {
610 27623720 : cov_real[i][j][k] = W_extract_l( W_shl_nosat( cov_real_64bit[i][j][k], q_shift_tmp ) ); /* q_cov_real[i][j] + q_shift - 32 */
611 27623720 : move32();
612 : }
613 2323810 : q_cov_real[i][j] = add( q_cov_real[i][j], q_shift_tmp );
614 2323810 : move16();
615 : }
616 : }
617 :
618 899180 : FOR( i = 0; i < num_chans; i++ )
619 : {
620 2323810 : FOR( j = 0; j < i; j++ )
621 : {
622 20446770 : FOR( k = start_band; k < end_band; k++ )
623 : {
624 18861480 : cov_real[i][j][k] = cov_real[j][i][k]; // q_cov_real[i][j]
625 18861480 : move32();
626 : }
627 1585290 : q_cov_real[i][j] = q_cov_real[j][i];
628 1585290 : move16();
629 : }
630 : }
631 :
632 160660 : return;
633 : }
|