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 <assert.h>
35 : #include <math.h>
36 : #include "options.h"
37 : #include "prot_fx.h"
38 : #include "rom_com.h"
39 : #include "ivas_rom_com.h"
40 : #include "wmc_auto.h"
41 : #include "ivas_prot_fx.h"
42 : #include "ivas_rom_com_fx.h"
43 :
44 :
45 : /*------------------------------------------------------------------------------------------*
46 : * Static functions declarations
47 : *------------------------------------------------------------------------------------------*/
48 : static void ivas_cmult_fix(
49 : Word32 in1_re, // i: Qx
50 : Word32 in1_im, // i: Qx
51 : Word32 in2_re, // i: Qx
52 : Word32 in2_im, // i: Qx
53 : Word32 *out1_re, // o: 2 * Qx - 31
54 : Word32 *out1_im // o: 2 * Qx - 31
55 : );
56 : static void ivas_get_active_bins_fx( const Word16 **pActive_bins, const Word16 **pActive_bins_abs, const Word16 **pStart_offset, const Word16 **pStart_offset_ab, const Word32 sampling_rate );
57 : static void ivas_get_ld_fb_resp_fx( Word32 **ppIdeal_FRs_re_fx, Word32 **ppIdeal_FRs_im_fx, Word32 **ppNew_FRs_re_fx, Word32 **ppNew_FRs_im_fx, const Word16 *pActive_bins, const Word16 *pStart_offset, const Word16 num_bands, const Word16 delay, const Word32 sampling_rate );
58 : static ivas_error ivas_filterbank_setup_fx( IVAS_FB_MIXER_HANDLE hFbMixer, const Word32 sampling_rate, Word16 *index );
59 : static ivas_error ivas_fb_mixer_get_window_fx( const Word16 fade_len, const Word32 sampling_rate, const Word16 **pWindow );
60 :
61 : /*-----------------------------------------------------------------------------------------*
62 : * Function ivas_get_num_bands_from_bw_idx()
63 : *
64 : * Get number of bands from BW index
65 : *-----------------------------------------------------------------------------------------*/
66 :
67 : /*! r: number of spectral bands */
68 546 : Word16 ivas_get_num_bands_from_bw_idx(
69 : const Word16 bwidth /* i : audio bandwidth */
70 : )
71 : {
72 : Word16 num_active_bands;
73 :
74 546 : assert( bwidth > 0 ); /*NB BW is not supported*/
75 546 : num_active_bands = ivas_num_active_bands[sub( bwidth, 1 )];
76 546 : move16();
77 :
78 546 : return num_active_bands;
79 : }
80 :
81 :
82 : /*-----------------------------------------------------------------------------------------*
83 : * Function ivas_get_num_bands()
84 : *
85 : * Get number of bands depending on the sampling rates
86 : *-----------------------------------------------------------------------------------------*/
87 :
88 546 : static Word16 ivas_get_num_bands(
89 : const Word32 sampling_rate )
90 : {
91 546 : Word16 bwidth = ivas_get_bw_idx_from_sample_rate_fx( sampling_rate );
92 546 : Word16 num_active_bands = ivas_get_num_bands_from_bw_idx( bwidth );
93 :
94 546 : return num_active_bands;
95 : }
96 :
97 :
98 : /*---------------------------------------------------------------------*
99 : * Function ivas_fb_set_cfg()
100 : *
101 : * Set default configs for FB mixer
102 : *---------------------------------------------------------------------*/
103 :
104 1476 : ivas_error ivas_fb_set_cfg(
105 : IVAS_FB_CFG **pFb_cfg_out, /* o : FB config. handle */
106 : const Word16 ivas_format, /* i : IVAS format */
107 : const Word16 num_in_chans, /* i : number of FB input channels */
108 : const Word16 num_out_chans, /* i : number of FB output channels */
109 : const Word16 active_w_mixing, /* i : active_w_mixing flag */
110 : const Word32 sampling_rate, /* i : sampling rate */
111 : const Word16 nchan_fb_in /* i : number of dirAC analysis channels*/
112 : )
113 : {
114 : IVAS_FB_CFG *pFb_cfg;
115 :
116 1476 : IF( ( pFb_cfg = (IVAS_FB_CFG *) malloc( sizeof( IVAS_FB_CFG ) ) ) == NULL )
117 : {
118 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer config" );
119 : }
120 :
121 1476 : pFb_cfg->num_in_chans = num_in_chans;
122 1476 : pFb_cfg->num_out_chans = num_out_chans;
123 1476 : pFb_cfg->nchan_fb_in = nchan_fb_in;
124 :
125 1476 : pFb_cfg->pcm_offset = 0; /* note: in SPAR decoder, this parameter is overwritten later */
126 1476 : pFb_cfg->active_w_mixing = active_w_mixing;
127 1476 : pFb_cfg->windowed_fr_offset = 0;
128 :
129 1476 : move16();
130 1476 : move16();
131 1476 : move16();
132 1476 : move16();
133 1476 : move16();
134 1476 : move16();
135 :
136 1476 : IF( EQ_16( ivas_format, ISM_FORMAT ) )
137 : {
138 0 : pFb_cfg->fb_latency = NS2SA_FX2( sampling_rate, DELAY_FB_4_NS );
139 0 : pFb_cfg->fade_len = NS2SA_FX2( sampling_rate, DELAY_FB_4_NS );
140 0 : pFb_cfg->prior_input_length = add( NS2SA_FX2( sampling_rate, DELAY_DIRAC_ENC_CMP_NS_PARAM_ISM ), NS2SA_FX2( sampling_rate, DIRAC_SLOT_ENC_NS ) );
141 :
142 0 : move16();
143 0 : move16();
144 0 : move16();
145 : }
146 1476 : ELSE IF( EQ_16( ivas_format, SBA_FORMAT ) )
147 : {
148 1476 : pFb_cfg->fb_latency = NS2SA_FX2( sampling_rate, DELAY_FB_1_NS );
149 :
150 1476 : pFb_cfg->fade_len = NS2SA_FX2( sampling_rate, DELAY_FB_4_NS );
151 1476 : pFb_cfg->prior_input_length = NS2SA_FX2( sampling_rate, FRAME_SIZE_NS );
152 1476 : Word16 tmp = shl( div_l( sampling_rate, FRAMES_PER_SEC ), 1 ); // Q0
153 1476 : tmp = mult0( tmp, 3 ); // Q0
154 1476 : tmp = shr( tmp, 2 ); // Q0
155 1476 : pFb_cfg->windowed_fr_offset = sub( tmp, NS2SA_FX2( sampling_rate, DELAY_DIRAC_SPAR_ENC_CMP_NS ) );
156 1476 : move16();
157 1476 : move16();
158 1476 : move16();
159 1476 : move16();
160 : }
161 0 : ELSE IF( EQ_16( ivas_format, MASA_FORMAT ) )
162 : {
163 0 : pFb_cfg->fb_latency = NS2SA_FX2( sampling_rate, DELAY_FB_1_NS );
164 0 : pFb_cfg->fade_len = NS2SA_FX2( sampling_rate, DELAY_FB_1_NS );
165 0 : pFb_cfg->prior_input_length = add( NS2SA_FX2( sampling_rate, DELAY_DIRAC_ENC_CMP_NS ), NS2SA_FX2( sampling_rate, DIRAC_SLOT_ENC_NS ) );
166 :
167 0 : move16();
168 0 : move16();
169 0 : move16();
170 : }
171 0 : ELSE IF( EQ_16( ivas_format, MC_FORMAT ) )
172 : {
173 0 : pFb_cfg->fb_latency = NS2SA_FX2( sampling_rate, DELAY_FB_1_NS );
174 0 : pFb_cfg->fade_len = NS2SA_FX2( sampling_rate, DELAY_FB_1_NS );
175 0 : pFb_cfg->prior_input_length = add( NS2SA_FX2( sampling_rate, DELAY_DIRAC_ENC_CMP_NS ), NS2SA_FX2( sampling_rate, PARAM_MC_SLOT_ENC_NS ) );
176 :
177 0 : move16();
178 0 : move16();
179 0 : move16();
180 : }
181 :
182 1476 : *pFb_cfg_out = pFb_cfg;
183 :
184 1476 : return IVAS_ERR_OK;
185 : }
186 :
187 :
188 : /*-------------------------------------------------------------------------
189 : * ivas_FB_mixer_open()
190 : *
191 : * Allocate and initialize FB mixer handle
192 : *------------------------------------------------------------------------*/
193 1476 : ivas_error ivas_FB_mixer_open_fx(
194 : IVAS_FB_MIXER_HANDLE *hFbMixer_out, /* i/o: FB mixer handle */
195 : const Word32 sampling_rate, /* i : sampling rate */
196 : IVAS_FB_CFG *fb_cfg, /* i : FB config. handle */
197 : const Word16 spar_reconfig_flag /* i : SPAR reconfiguration flag */
198 : )
199 : {
200 : IVAS_FB_MIXER_HANDLE hFbMixer;
201 : Word16 i, j, frame_len, num_bands;
202 : Word16 num_chs_alloc, exp;
203 : ivas_error error;
204 :
205 1476 : error = IVAS_ERR_OK;
206 1476 : move32();
207 :
208 1476 : frame_len = BASOP_Util_Divide3232_Scale( sampling_rate, FRAMES_PER_SEC, &exp );
209 1476 : frame_len = shr( frame_len, sub( 15, exp ) );
210 :
211 1476 : hFbMixer = *hFbMixer_out;
212 :
213 1476 : IF( !spar_reconfig_flag )
214 : {
215 273 : IF( ( hFbMixer = (IVAS_FB_MIXER_HANDLE) malloc( sizeof( IVAS_FB_MIXER_DATA ) ) ) == NULL )
216 : {
217 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" );
218 : }
219 :
220 273 : IF( fb_cfg->num_out_chans > 0 )
221 : {
222 273 : IF( ( hFbMixer->pFb = (ivas_filterbank_t *) malloc( sizeof( ivas_filterbank_t ) ) ) == NULL )
223 : {
224 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" );
225 : }
226 : }
227 : ELSE
228 : {
229 0 : hFbMixer->pFb = NULL;
230 : }
231 : }
232 :
233 1476 : IF( EQ_16( fb_cfg->active_w_mixing, -1 ) )
234 : {
235 1476 : num_chs_alloc = 0;
236 1476 : move16();
237 : }
238 0 : ELSE IF( fb_cfg->active_w_mixing )
239 : {
240 0 : num_chs_alloc = s_max( fb_cfg->num_in_chans, fb_cfg->nchan_fb_in );
241 : }
242 : ELSE
243 : {
244 0 : num_chs_alloc = 1; /* only W channel processed for predicting YZX */
245 0 : move16();
246 : }
247 :
248 1476 : FOR( i = 0; i < num_chs_alloc; i++ )
249 : {
250 0 : IF( fb_cfg->num_out_chans == 0 )
251 : {
252 0 : hFbMixer->ppFilterbank_inFR_re_fx[i] = NULL;
253 0 : hFbMixer->ppFilterbank_inFR_im_fx[i] = NULL;
254 : }
255 : ELSE
256 : {
257 0 : j = fb_cfg->remix_order[i];
258 0 : move16();
259 :
260 0 : IF( ( hFbMixer->ppFilterbank_inFR_re_fx[j] = (Word32 *) malloc( sizeof( Word32 ) * frame_len ) ) == NULL )
261 : {
262 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" );
263 : }
264 :
265 0 : IF( ( hFbMixer->ppFilterbank_inFR_im_fx[j] = (Word32 *) malloc( sizeof( Word32 ) * frame_len ) ) == NULL )
266 : {
267 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" );
268 : }
269 : }
270 : }
271 :
272 1476 : IF( EQ_16( fb_cfg->active_w_mixing, -1 ) )
273 : {
274 1476 : num_chs_alloc = 0;
275 1476 : move16();
276 : }
277 : ELSE
278 : {
279 0 : num_chs_alloc = s_max( fb_cfg->num_in_chans, fb_cfg->nchan_fb_in );
280 : }
281 :
282 1476 : FOR( i = 0; i < num_chs_alloc; i++ )
283 : {
284 0 : IF( ( hFbMixer->ppFilterbank_prior_input_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * fb_cfg->prior_input_length ) ) == NULL )
285 : {
286 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" );
287 : }
288 0 : set32_fx( hFbMixer->ppFilterbank_prior_input_fx[i], 0, fb_cfg->prior_input_length );
289 : }
290 :
291 1476 : test();
292 1476 : IF( ( NE_16( fb_cfg->active_w_mixing, -1 ) ) && ( fb_cfg->num_out_chans > 0 ) )
293 : {
294 : Word32 *pTemp_mem_fx;
295 0 : IF( ( pTemp_mem_fx = (Word32 *) malloc( sizeof( Word32 ) * fb_cfg->num_out_chans * s_max( fb_cfg->num_in_chans, fb_cfg->nchan_fb_in ) * IVAS_MAX_NUM_BANDS ) ) == NULL )
296 : {
297 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer" );
298 : }
299 0 : FOR( i = 0; i < fb_cfg->num_out_chans; i++ )
300 : {
301 0 : FOR( j = 0; j < fb_cfg->num_in_chans; j++ )
302 : {
303 0 : hFbMixer->prior_mixer_fx[i][j] = pTemp_mem_fx;
304 0 : pTemp_mem_fx += IVAS_MAX_NUM_BANDS;
305 0 : set32_fx( hFbMixer->prior_mixer_fx[i][j], 0, IVAS_MAX_NUM_BANDS );
306 : }
307 : }
308 0 : hFbMixer->q_prior_mixer_fx = Q31;
309 0 : move16();
310 : }
311 :
312 1476 : IF( !spar_reconfig_flag )
313 : {
314 273 : IF( fb_cfg->num_out_chans > 0 )
315 : {
316 : const Word16 *pActive_bins_per_band, *pActive_bins_per_band_abs, *pStart_offset, *pStart_offset_abs;
317 :
318 273 : num_bands = ivas_get_num_bands( sampling_rate );
319 :
320 273 : ivas_get_active_bins_fx( &pActive_bins_per_band, &pActive_bins_per_band_abs, &pStart_offset, &pStart_offset_abs, sampling_rate );
321 :
322 273 : IF( NE_16( fb_cfg->active_w_mixing, -1 ) )
323 : {
324 0 : FOR( i = 0; i < num_bands; i++ )
325 : {
326 0 : IF( ( hFbMixer->pFb->fb_bin_to_band.pFb_bin_to_band_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * pActive_bins_per_band_abs[i] ) ) == NULL )
327 : {
328 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder fixed" );
329 : }
330 : }
331 : }
332 :
333 273 : IF( NE_32( sampling_rate, 48000 ) )
334 : {
335 : Word16 num_diff_bands, start_diff_band_non48k;
336 :
337 154 : num_diff_bands = MAX_NUM_BANDS_DIFF_NON48K;
338 154 : move16();
339 154 : start_diff_band_non48k = sub( num_bands, num_diff_bands );
340 :
341 154 : hFbMixer->num_diff_bands = num_diff_bands;
342 154 : move16();
343 :
344 616 : FOR( j = start_diff_band_non48k; j < num_bands; j++ )
345 : {
346 462 : IF( ( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k_fx[0][j] = (Word32 *) malloc( sizeof( Word32 ) * pActive_bins_per_band[j] ) ) == NULL )
347 : {
348 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" );
349 : }
350 :
351 462 : IF( ( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k_fx[1][j] = (Word32 *) malloc( sizeof( Word32 ) * pActive_bins_per_band[j] ) ) == NULL )
352 : {
353 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" );
354 : }
355 : }
356 : }
357 : }
358 : ELSE
359 : {
360 : /* ignore all the deeper filter bank stuff for now */
361 0 : hFbMixer->num_diff_bands = 0;
362 0 : move16();
363 : }
364 : }
365 :
366 1476 : hFbMixer->fb_cfg = fb_cfg;
367 1476 : set16_fx( hFbMixer->first_frame, 1, hFbMixer->fb_cfg->num_out_chans );
368 1476 : set16_fx( hFbMixer->first_frame + hFbMixer->fb_cfg->num_out_chans, 0, sub( IVAS_SPAR_MAX_CH, hFbMixer->fb_cfg->num_out_chans ) );
369 :
370 1476 : IF( !spar_reconfig_flag )
371 : {
372 : Word16 index[IVAS_MAX_NUM_FB_BANDS];
373 273 : set16_fx( index, 0, IVAS_MAX_NUM_FB_BANDS );
374 273 : IF( NE_32( ( error = ivas_filterbank_setup_fx( hFbMixer, sampling_rate, index ) ), IVAS_ERR_OK ) )
375 : {
376 0 : return error;
377 : }
378 : }
379 :
380 1476 : *hFbMixer_out = hFbMixer;
381 :
382 1476 : return error;
383 : }
384 :
385 : /*-------------------------------------------------------------------------
386 : * ivas_FB_mixer_close()
387 : *
388 : * Deallocate FB mixer handle
389 : *------------------------------------------------------------------------*/
390 :
391 1476 : void ivas_FB_mixer_close_fx(
392 : IVAS_FB_MIXER_HANDLE *hFbMixer_in, /* i/o: FB mixer handle */
393 : const Word32 sampling_rate, /* i : sampling rate in Hz */
394 : const Word16 spar_reconfig_flag /* i : SPAR reconfiguration flag */
395 : )
396 : {
397 : IVAS_FB_MIXER_HANDLE hFbMixer;
398 : IVAS_FB_CFG *fb_cfg;
399 : Word16 i, j, num_bands;
400 : Word16 num_chs_alloc;
401 :
402 1476 : hFbMixer = *hFbMixer_in;
403 1476 : fb_cfg = hFbMixer->fb_cfg;
404 :
405 1476 : IF( EQ_16( fb_cfg->active_w_mixing, -1 ) )
406 : {
407 1476 : num_chs_alloc = 0;
408 1476 : move16();
409 : }
410 0 : ELSE IF( fb_cfg->active_w_mixing )
411 : {
412 0 : num_chs_alloc = s_max( fb_cfg->num_in_chans, fb_cfg->nchan_fb_in );
413 : }
414 : ELSE
415 : {
416 0 : num_chs_alloc = 1; /* only W channel processed for predicting YZX */
417 0 : move16();
418 : }
419 :
420 1476 : IF( hFbMixer != NULL )
421 : {
422 1476 : FOR( i = 0; i < num_chs_alloc; i++ )
423 : {
424 0 : IF( fb_cfg->num_out_chans > 0 )
425 : {
426 0 : j = fb_cfg->remix_order[i];
427 0 : move16();
428 :
429 0 : free( hFbMixer->ppFilterbank_inFR_re_fx[j] );
430 0 : hFbMixer->ppFilterbank_inFR_re_fx[j] = NULL;
431 :
432 0 : free( hFbMixer->ppFilterbank_inFR_im_fx[j] );
433 0 : hFbMixer->ppFilterbank_inFR_im_fx[j] = NULL;
434 : }
435 : }
436 :
437 1476 : IF( EQ_16( fb_cfg->active_w_mixing, -1 ) )
438 : {
439 1476 : num_chs_alloc = 0;
440 1476 : move16();
441 : }
442 : ELSE
443 : {
444 0 : num_chs_alloc = s_max( fb_cfg->num_in_chans, fb_cfg->nchan_fb_in );
445 : }
446 :
447 1476 : FOR( i = 0; i < num_chs_alloc; i++ )
448 : {
449 0 : free( hFbMixer->ppFilterbank_prior_input_fx[i] );
450 0 : hFbMixer->ppFilterbank_prior_input_fx[i] = NULL;
451 : }
452 :
453 1476 : test();
454 1476 : IF( NE_16( fb_cfg->active_w_mixing, -1 ) && ( fb_cfg->num_out_chans > 0 ) )
455 : {
456 0 : free( hFbMixer->prior_mixer_fx[0][0] );
457 0 : hFbMixer->prior_mixer_fx[0][0] = NULL;
458 : }
459 :
460 1476 : IF( !spar_reconfig_flag )
461 : {
462 273 : IF( fb_cfg->num_out_chans > 0 )
463 : {
464 273 : num_bands = hFbMixer->pFb->filterbank_num_bands;
465 273 : move16();
466 :
467 273 : IF( NE_16( fb_cfg->active_w_mixing, -1 ) )
468 : {
469 0 : FOR( i = 0; i < num_bands; i++ )
470 : {
471 0 : free( hFbMixer->pFb->fb_bin_to_band.pFb_bin_to_band_fx[i] );
472 0 : hFbMixer->pFb->fb_bin_to_band.pFb_bin_to_band_fx[i] = NULL;
473 : }
474 : }
475 :
476 273 : IF( NE_32( sampling_rate, 48000 ) )
477 : {
478 : Word16 start_diff_band_non48k;
479 154 : start_diff_band_non48k = sub( num_bands, hFbMixer->num_diff_bands );
480 :
481 616 : FOR( j = start_diff_band_non48k; j < num_bands; j++ )
482 : {
483 462 : free( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k_fx[0][j] );
484 462 : hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k_fx[0][j] = NULL;
485 :
486 462 : free( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k_fx[1][j] );
487 462 : hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k_fx[1][j] = NULL;
488 : }
489 : }
490 : }
491 273 : IF( hFbMixer->pFb != NULL )
492 : {
493 273 : free( hFbMixer->pFb );
494 273 : hFbMixer->pFb = NULL;
495 : }
496 : }
497 :
498 1476 : IF( hFbMixer->fb_cfg != NULL )
499 : {
500 1476 : free( hFbMixer->fb_cfg );
501 1476 : hFbMixer->fb_cfg = NULL;
502 : }
503 :
504 1476 : IF( !spar_reconfig_flag )
505 : {
506 273 : free( hFbMixer );
507 273 : hFbMixer = NULL;
508 : }
509 : }
510 :
511 1476 : return;
512 : }
513 : /*-----------------------------------------------------------------------------------------*
514 : * Function ivas_fb_mixer_pcm_ingest()
515 : *
516 : * PCM ingest block
517 : *-----------------------------------------------------------------------------------------*/
518 0 : void ivas_fb_mixer_pcm_ingest_fx(
519 : IVAS_FB_MIXER_HANDLE hFbMixer, /* i/o: FB mixer handle */
520 : Word32 *pcm_in[], /* i : input audio channels Qq_data_fix[] */
521 : Word32 **ppOut_pcm, /* o : output audio channels Qq_ppOut_pcm[] */
522 : const Word16 frame_len, /* i : frame length */
523 : const Word16 HOA_md_ind[IVAS_SPAR_MAX_CH],
524 : Word16 q_data_fix,
525 : Word16 *q_ppOut_pcm )
526 : {
527 : Word16 i;
528 : Word16 num_chs_ingest;
529 0 : IVAS_FB_CFG *fb_cfg = hFbMixer->fb_cfg;
530 :
531 0 : IF( fb_cfg->active_w_mixing )
532 : {
533 0 : num_chs_ingest = fb_cfg->num_in_chans;
534 0 : move16();
535 : }
536 : ELSE
537 : {
538 0 : num_chs_ingest = 1; /* forward Filterbank MDFT only on W */
539 0 : move16();
540 : }
541 :
542 :
543 0 : FOR( i = 0; i < fb_cfg->num_in_chans; i++ )
544 : {
545 0 : Copy32( &hFbMixer->ppFilterbank_prior_input_fx[i][fb_cfg->prior_input_length - frame_len], ppOut_pcm[i], frame_len );
546 0 : Copy32( pcm_in[HOA_md_ind[i]], &ppOut_pcm[i][frame_len], frame_len );
547 0 : q_ppOut_pcm[i] = q_data_fix;
548 0 : move16();
549 : }
550 :
551 0 : Word16 guard_bits = find_guarded_bits_fx( shl( frame_len, 1 ) );
552 :
553 0 : FOR( i = 0; i < num_chs_ingest; i++ )
554 : {
555 0 : Word16 q_shift = sub( L_norm_arr( ppOut_pcm[fb_cfg->remix_order[i]], shl( frame_len, 1 ) ), guard_bits );
556 0 : Scale_sig32( ppOut_pcm[fb_cfg->remix_order[i]], shl( frame_len, 1 ), q_shift ); // Qq_ppOut_pcm -> Qq_ppOut_pcm + q_shift
557 0 : q_ppOut_pcm[fb_cfg->remix_order[i]] = add( q_ppOut_pcm[fb_cfg->remix_order[i]], q_shift );
558 0 : move16();
559 :
560 0 : ivas_mdft_fx( ppOut_pcm[fb_cfg->remix_order[i]], hFbMixer->ppFilterbank_inFR_re_fx[fb_cfg->remix_order[i]], hFbMixer->ppFilterbank_inFR_im_fx[fb_cfg->remix_order[i]], shl( frame_len, 1 ), frame_len );
561 0 : q_shift = L_norm_arr( hFbMixer->ppFilterbank_inFR_re_fx[fb_cfg->remix_order[i]], frame_len );
562 0 : q_shift = s_min( q_shift, L_norm_arr( hFbMixer->ppFilterbank_inFR_im_fx[fb_cfg->remix_order[i]], frame_len ) );
563 0 : scale_sig32( hFbMixer->ppFilterbank_inFR_re_fx[fb_cfg->remix_order[i]], frame_len, q_shift );
564 0 : scale_sig32( hFbMixer->ppFilterbank_inFR_im_fx[fb_cfg->remix_order[i]], frame_len, q_shift );
565 0 : hFbMixer->q_ppFilterbank_inFR[fb_cfg->remix_order[i]] = add( q_shift, q_ppOut_pcm[fb_cfg->remix_order[i]] );
566 0 : move16();
567 : }
568 :
569 0 : return;
570 : }
571 :
572 : /*-----------------------------------------------------------------------------------------*
573 : * Function ivas_fb_mixer_update_prior_input()
574 : *
575 : *
576 : *-----------------------------------------------------------------------------------------*/
577 0 : void ivas_fb_mixer_update_prior_input_fx(
578 : IVAS_FB_MIXER_HANDLE hFbMixer, /* i/o: FB mixer handle */
579 : Word32 *pcm_in_fx[], /* i : input audio channels */
580 : const Word16 length, /* i : length of time slot */
581 : const Word16 nchan_fb_in /* i : number of analysis channels */
582 : )
583 : {
584 : Word16 i;
585 :
586 0 : FOR( i = 0; i < nchan_fb_in; i++ )
587 : {
588 0 : Copy32( &hFbMixer->ppFilterbank_prior_input_fx[i][length], hFbMixer->ppFilterbank_prior_input_fx[i], hFbMixer->fb_cfg->prior_input_length - length );
589 0 : Copy32( pcm_in_fx[i], &hFbMixer->ppFilterbank_prior_input_fx[i][hFbMixer->fb_cfg->prior_input_length - length], length );
590 : }
591 :
592 0 : return;
593 : }
594 :
595 :
596 : /*-----------------------------------------------------------------------------------------*
597 : * Function ivas_fb_mixer_get_windowed_fr()
598 : *
599 : *
600 : *-----------------------------------------------------------------------------------------*/
601 :
602 0 : void ivas_fb_mixer_get_windowed_fr_fx(
603 : IVAS_FB_MIXER_HANDLE hFbMixer, /* i/o: FB mixer handle */
604 : Word32 *pcm_in_fx[], // i: Qx
605 : Word32 *frame_f_real_fx[],
606 : Word32 *frame_f_imag_fx[],
607 : const Word16 length, /* i : number of new samples in time slot */
608 : const Word16 mdft_len, /* i : MDFT frame length */
609 : const Word16 nchan_fb_in, /* i : number of analysis channels */
610 : Word16 gb )
611 : {
612 : Word16 ch_idx, j, offset, rev_offset;
613 : Word16 n_old_samples;
614 : Word16 n_new_samples;
615 : Word32 fr_in_block_fx[L_FRAME48k * 2];
616 : const Word16 *win_ptr_fx;
617 : #ifdef OPT_MCT_ENC_V1_BE
618 0 : Word16 two_mdft_len = shl( mdft_len, 1 );
619 0 : Word16 tmp = sub( shl( mdft_len, 1 ), length );
620 0 : Word16 gb_neg = negate( gb );
621 :
622 0 : n_old_samples = s_min( ( sub( hFbMixer->fb_cfg->prior_input_length, hFbMixer->fb_cfg->windowed_fr_offset ) ), two_mdft_len );
623 0 : offset = sub( tmp, hFbMixer->ana_window_offset );
624 0 : rev_offset = sub( two_mdft_len, hFbMixer->ana_window_offset );
625 : #else
626 : n_old_samples = s_min( ( sub( hFbMixer->fb_cfg->prior_input_length, hFbMixer->fb_cfg->windowed_fr_offset ) ), ( shl( mdft_len, 1 ) ) );
627 : offset = sub( sub( shl( mdft_len, 1 ), length ), hFbMixer->ana_window_offset );
628 : rev_offset = sub( shl( mdft_len, 1 ), hFbMixer->ana_window_offset );
629 : #endif
630 0 : set32_fx( fr_in_block_fx, 0, offset );
631 0 : n_new_samples = s_max( 0, sub( shl( length, 1 ), n_old_samples ) );
632 0 : FOR( ch_idx = 0; ch_idx < nchan_fb_in; ch_idx++ )
633 : {
634 0 : Copy32( &hFbMixer->ppFilterbank_prior_input_fx[ch_idx][offset + hFbMixer->fb_cfg->windowed_fr_offset], &fr_in_block_fx[offset], sub( n_old_samples, offset ) ); // Qx
635 0 : Copy32( pcm_in_fx[ch_idx], &fr_in_block_fx[n_old_samples], n_new_samples ); // Qx
636 :
637 0 : win_ptr_fx = hFbMixer->pAna_window_fx; /*Q15*/
638 :
639 : #ifdef OPT_MCT_ENC_V1_BE
640 0 : FOR( j = offset; j < tmp; j++ )
641 : #else
642 : FOR( j = offset; j < sub( shl( mdft_len, 1 ), length ); j++ )
643 : #endif
644 : {
645 0 : fr_in_block_fx[j] = Mpy_32_16_1( fr_in_block_fx[j], ( *( win_ptr_fx++ ) ) ); // Qx + 15 - 15 = Qx
646 0 : move32();
647 : }
648 :
649 : #ifdef OPT_MCT_ENC_V1_BE
650 0 : FOR( j = rev_offset; j < two_mdft_len; j++ )
651 : #else
652 : FOR( j = rev_offset; j < shl( mdft_len, 1 ); j++ )
653 : #endif
654 : {
655 0 : fr_in_block_fx[j] = Mpy_32_16_1( fr_in_block_fx[j], ( *( --win_ptr_fx ) ) ); // Qx + 15 - 15 = Qx
656 0 : move32();
657 : }
658 :
659 : #ifdef OPT_MCT_ENC_V1_BE
660 0 : scale_sig32( fr_in_block_fx, two_mdft_len, gb_neg );
661 : #else
662 : FOR( Word16 i = 0; i < shl( mdft_len, 1 ); i++ )
663 : {
664 : fr_in_block_fx[i] = L_shr( fr_in_block_fx[i], gb ); // Qx - gb
665 : move32();
666 : }
667 : #endif
668 :
669 : #ifdef OPT_MCT_ENC_V1_BE
670 0 : ivas_mdft_fx( fr_in_block_fx, frame_f_real_fx[ch_idx], frame_f_imag_fx[ch_idx], two_mdft_len, mdft_len );
671 : #else
672 : ivas_mdft_fx( fr_in_block_fx, frame_f_real_fx[ch_idx], frame_f_imag_fx[ch_idx], shl( mdft_len, 1 ), mdft_len );
673 : #endif
674 : }
675 :
676 0 : return;
677 : }
678 :
679 : /*-----------------------------------------------------------------------------------------*
680 : * Function ivas_fb_mixer_cross_fading()
681 : *
682 : * FB Mixer cross fading
683 : *-----------------------------------------------------------------------------------------*/
684 :
685 0 : void ivas_fb_mixer_cross_fading_fx(
686 : IVAS_FB_MIXER_HANDLE hFbMixer,
687 : Word32 **ppOut_pcm_fx, // o: Qx
688 : Word32 *pMdft_out_old_fx, // i: Qx
689 : Word32 *pMdft_out_new_fx, // i: Qx
690 : const Word16 ch,
691 : const Word16 frame_len,
692 : const Word16 cf_offset )
693 : {
694 : Word16 k, fade_start_offset, fade_end_offset;
695 :
696 0 : IF( hFbMixer->first_frame[ch] == 0 )
697 : {
698 0 : fade_start_offset = hFbMixer->cross_fade_start_offset;
699 0 : fade_end_offset = hFbMixer->cross_fade_end_offset;
700 0 : move16();
701 0 : move16();
702 :
703 0 : FOR( k = 0; k < fade_start_offset; k++ )
704 : {
705 0 : ppOut_pcm_fx[ch][k] = pMdft_out_old_fx[k + cf_offset]; // Qx
706 0 : move32();
707 : }
708 :
709 0 : FOR( k = fade_start_offset; k < fade_end_offset; k++ )
710 : {
711 0 : ppOut_pcm_fx[ch][k] = L_add( Mpy_32_16_1( pMdft_out_new_fx[k + cf_offset], hFbMixer->pFilterbank_cross_fade_fx[k - fade_start_offset] ), Mpy_32_16_1( pMdft_out_old_fx[k + cf_offset], sub( 32767, hFbMixer->pFilterbank_cross_fade_fx[k - fade_start_offset] ) ) ); // Qx + Q15 - 15 = Qx
712 0 : move32();
713 : }
714 :
715 0 : FOR( k = fade_end_offset; k < frame_len; k++ )
716 : {
717 0 : ppOut_pcm_fx[ch][k] = pMdft_out_new_fx[k + cf_offset]; // Qx
718 0 : move32();
719 : }
720 : }
721 : ELSE
722 : {
723 0 : hFbMixer->first_frame[ch] = 0;
724 0 : move32();
725 :
726 0 : FOR( k = 0; k < frame_len; k++ )
727 : {
728 0 : ppOut_pcm_fx[ch][k] = pMdft_out_new_fx[k + cf_offset]; // Qx
729 0 : move32();
730 : }
731 : }
732 :
733 0 : return;
734 : }
735 :
736 : /*-----------------------------------------------------------------------------------------*
737 : * Function ivas_fb_mixer_process()
738 : *
739 : * Filter bank process
740 : *-----------------------------------------------------------------------------------------*/
741 0 : void ivas_cmult_fix(
742 : Word32 in1_re, // i: Qx
743 : Word32 in1_im, // i: Qx
744 : Word32 in2_re, // i: Qx
745 : Word32 in2_im, // i: Qx
746 : Word32 *out1_re, // o: 2 * Qx - 31
747 : Word32 *out1_im // o: 2 * Qx - 31
748 : )
749 : {
750 0 : *out1_re = L_sub_sat( Mpy_32_32( in1_re, in2_re ), Mpy_32_32( in1_im, in2_im ) );
751 0 : move32();
752 0 : *out1_im = L_add_sat( Mpy_32_32( in1_re, in2_im ), Mpy_32_32( in2_re, in1_im ) );
753 0 : move32();
754 0 : }
755 :
756 0 : void ivas_fb_mixer_process_fx(
757 : IVAS_FB_MIXER_HANDLE hFbMixer, /* i/o: FB mixer handle */
758 : Word32 ***mixer_mat_fx, /* i : mixer matrix */
759 : Word16 *q_mixer_mat_fx, /* i : mixer matrix Q-factor */
760 : Word32 **ppOut_pcm_fx, /* o : output audio channels */
761 : Word16 *q_ppOut_pcm_fx, /* o : output audio channels Q-factor */
762 : const Word16 frame_len, /* i : frame length in samples */
763 : Word16 in_out_mixer_map[IVAS_MAX_FB_MIXER_OUT_CH][IVAS_MAX_SPAR_FB_MIXER_IN_CH] /* i/o: mixing mapping */
764 : )
765 : {
766 0 : ivas_filterbank_t *pFb = hFbMixer->pFb;
767 0 : Word16 num_bands = pFb->filterbank_num_bands;
768 0 : move16();
769 : Word16 i, j, k, ch, hist;
770 :
771 : const Word32 *pFilterbank_bin_to_band_re_fx;
772 : const Word32 *pFilterbank_bin_to_band_im_fx;
773 : Word16 q_pMdft_out_fx[2];
774 : Word32 *pMdft_out_fx[2];
775 : Word32 *pOut_fr_re_fx, *pOut_fr_im_fx;
776 0 : Word16 q_pOut_fr_fx = 31;
777 0 : move16();
778 : Word32 Out_fr_re_fx[L_FRAME48k], Out_fr_im_fx[L_FRAME48k];
779 : Word32 Mdft_out_0_fx[L_FRAME48k * 2], Mdft_out_1_fx[L_FRAME48k * 2];
780 :
781 0 : pOut_fr_re_fx = Out_fr_re_fx;
782 0 : pOut_fr_im_fx = Out_fr_im_fx;
783 0 : pMdft_out_fx[0] = Mdft_out_0_fx;
784 0 : pMdft_out_fx[1] = Mdft_out_1_fx;
785 :
786 : #ifdef OPT_SBA_ENC_V1_BE
787 0 : Word16 total_guard = find_guarded_bits_fx( num_bands );
788 0 : Word16 total_guard_2 = find_guarded_bits_fx( shl( frame_len, 1 ) );
789 0 : Word16 tmp_q = sub( sub( *q_mixer_mat_fx, total_guard ), 32 ); // Q30 + hFbMixer->q_prior_mixer_fx - 31 - total_guard - 31
790 0 : Word16 len = shl( frame_len, 1 );
791 : Word16 res_q, q_check;
792 : #endif
793 0 : FOR( ch = ( hFbMixer->fb_cfg->active_w_mixing == 0 ); ch < hFbMixer->fb_cfg->num_out_chans; ch++ )
794 : {
795 : /* Run a loop of 2 to calculate current frame's filterbank output and prev frame's output */
796 0 : FOR( hist = 0; hist < 2; hist++ )
797 : {
798 0 : set_zero_fx( pOut_fr_re_fx, frame_len );
799 0 : set_zero_fx( pOut_fr_im_fx, frame_len );
800 0 : q_pOut_fr_fx = 31;
801 0 : move16();
802 0 : FOR( j = 0; j < hFbMixer->fb_cfg->num_in_chans; j++ )
803 : {
804 0 : IF( in_out_mixer_map[ch][j] != 0 )
805 : {
806 :
807 : #ifdef OPT_SBA_ENC_V1_BE
808 0 : res_q = add( tmp_q, hFbMixer->q_ppFilterbank_inFR[j] );
809 0 : q_check = s_min( q_pOut_fr_fx, res_q );
810 0 : scale_sig32( pOut_fr_re_fx, frame_len, sub( q_check, q_pOut_fr_fx ) );
811 0 : scale_sig32( pOut_fr_im_fx, frame_len, sub( q_check, q_pOut_fr_fx ) );
812 : #endif
813 : Word32 filterbank_mixer_bins_re_fx[L_FRAME48k];
814 : Word32 filterbank_mixer_bins_im_fx[L_FRAME48k];
815 0 : Word32 *pFb_inFR_re_fx = hFbMixer->ppFilterbank_inFR_re_fx[j]; // Q(hFbMixer->q_ppFilterbank_inFR_re_fx)
816 0 : Word32 *pFb_inFR_im_fx = hFbMixer->ppFilterbank_inFR_im_fx[j]; // Q(hFbMixer->q_ppFilterbank_inFR_im_fx)
817 :
818 0 : set_zero_fx( filterbank_mixer_bins_re_fx, frame_len );
819 0 : set_zero_fx( filterbank_mixer_bins_im_fx, frame_len );
820 :
821 : #ifndef OPT_SBA_ENC_V1_BE
822 : Word16 total_guard = find_guarded_bits_fx( num_bands );
823 : move16();
824 : #endif
825 0 : FOR( i = 0; i < num_bands; i++ )
826 : {
827 0 : Word16 start_offset = pFb->fb_consts.pFilterbank_bins_start_offset[i];
828 0 : move16();
829 0 : Word16 num_bins = pFb->fb_consts.pFilterbank_bins_per_band[i];
830 0 : move16();
831 0 : Word32 mixer_const_fx = hFbMixer->prior_mixer_fx[ch][j][i]; // Q(hFbMixer->q_prior_mixer_fx)
832 0 : move32();
833 0 : pFilterbank_bin_to_band_re_fx = pFb->fb_consts.ppFilterbank_FRs_fx[0][i]; // Q30
834 0 : pFilterbank_bin_to_band_im_fx = pFb->fb_consts.ppFilterbank_FRs_fx[1][i]; // Q30
835 :
836 0 : FOR( k = start_offset; k < num_bins + start_offset; k++ )
837 : {
838 0 : filterbank_mixer_bins_re_fx[k] = L_add_sat( filterbank_mixer_bins_re_fx[k], L_shr( Mpy_32_32( *pFilterbank_bin_to_band_re_fx, mixer_const_fx ), total_guard ) ); // Q30 + hFbMixer->q_prior_mixer_fx - 31 - total_guard
839 0 : move32();
840 0 : filterbank_mixer_bins_im_fx[k] = L_add_sat( filterbank_mixer_bins_im_fx[k], L_shr( Mpy_32_32( *pFilterbank_bin_to_band_im_fx, mixer_const_fx ), total_guard ) ); // Q30 + hFbMixer->q_prior_mixer_fx - 31 - total_guard
841 0 : move32();
842 : /*filterbank_mixer_bins_im_fx q 30 */
843 : /*mixer_const_fx q q_ppOut_pcm_fx */
844 0 : pFilterbank_bin_to_band_re_fx++;
845 0 : pFilterbank_bin_to_band_im_fx++;
846 : }
847 0 : hFbMixer->prior_mixer_fx[ch][j][i] = mixer_mat_fx[ch][j][i]; // Q(q_mixer_mat_fx)
848 0 : move32();
849 : }
850 : #ifndef OPT_SBA_ENC_V1_BE
851 : Word16 res_q = 0;
852 : move16();
853 : #endif
854 0 : FOR( k = 0; k < frame_len; k++ )
855 : {
856 : Word32 temp_out_re_fx, temp_out_im_fx;
857 :
858 0 : ivas_cmult_fix( filterbank_mixer_bins_re_fx[k], filterbank_mixer_bins_im_fx[k], pFb_inFR_re_fx[k],
859 0 : pFb_inFR_im_fx[k], &temp_out_re_fx, &temp_out_im_fx );
860 : #ifndef OPT_SBA_ENC_V1_BE
861 : res_q = sub( add( sub( sub( add( 30, *q_mixer_mat_fx ), 31 ), total_guard ), hFbMixer->q_ppFilterbank_inFR[j] ), 31 );
862 :
863 : Word16 q_check = s_min( q_pOut_fr_fx, res_q );
864 : IF( NE_16( q_check, q_pOut_fr_fx ) )
865 : {
866 : pOut_fr_re_fx[k] = L_shr( pOut_fr_re_fx[k], sub( q_pOut_fr_fx, q_check ) ); // q_pOut_fr_fx -> q_check
867 : move32();
868 : pOut_fr_im_fx[k] = L_shr( pOut_fr_im_fx[k], sub( q_pOut_fr_fx, q_check ) ); // q_pOut_fr_fx -> q_check
869 : move32();
870 : }
871 : #endif
872 0 : IF( NE_16( q_check, res_q ) )
873 : {
874 0 : temp_out_re_fx = L_shr( temp_out_re_fx, sub( res_q, q_check ) ); // res_q -> q_check
875 0 : temp_out_im_fx = L_shr( temp_out_im_fx, sub( res_q, q_check ) ); // res_q -> q_check
876 : }
877 : #ifndef OPT_SBA_ENC_V1_BE
878 : res_q = q_check;
879 : move16();
880 : #endif
881 :
882 0 : pOut_fr_re_fx[k] = L_add_sat( pOut_fr_re_fx[k], temp_out_re_fx ); // res_q
883 0 : move32();
884 0 : pOut_fr_im_fx[k] = L_add_sat( pOut_fr_im_fx[k], temp_out_im_fx ); // res_q
885 0 : move32();
886 : }
887 : #ifdef OPT_SBA_ENC_V1_BE
888 0 : q_pOut_fr_fx = q_check;
889 : #else
890 : q_pOut_fr_fx = res_q;
891 : move16();
892 : #endif
893 : }
894 : }
895 : #ifndef OPT_SBA_ENC_V1_BE
896 : Word16 scale = sub( s_min( L_norm_arr( pOut_fr_re_fx, frame_len ), L_norm_arr( pOut_fr_im_fx, frame_len ) ), find_guarded_bits_fx( shl( frame_len, 1 ) ) );
897 : #else
898 0 : Word16 scale = sub( s_min( L_norm_arr( pOut_fr_re_fx, frame_len ), L_norm_arr( pOut_fr_im_fx, frame_len ) ), total_guard_2 );
899 : #endif
900 0 : scale_sig32( pOut_fr_re_fx, frame_len, scale );
901 0 : scale_sig32( pOut_fr_im_fx, frame_len, scale );
902 0 : ivas_imdft_fx( pOut_fr_re_fx, pOut_fr_im_fx, pMdft_out_fx[hist], frame_len );
903 0 : q_pMdft_out_fx[hist] = add( q_pOut_fr_fx, scale );
904 0 : move16();
905 : }
906 : #ifdef OPT_SBA_ENC_V1_BE
907 0 : scale_sig32( pMdft_out_fx[0], len, sub( s_min( q_pMdft_out_fx[0], q_pMdft_out_fx[1] ), q_pMdft_out_fx[0] ) );
908 0 : scale_sig32( pMdft_out_fx[1], len, sub( s_min( q_pMdft_out_fx[0], q_pMdft_out_fx[1] ), q_pMdft_out_fx[1] ) );
909 : #else
910 : scale_sig32( pMdft_out_fx[0], shl( frame_len, 1 ), sub( s_min( q_pMdft_out_fx[0], q_pMdft_out_fx[1] ), q_pMdft_out_fx[0] ) );
911 : scale_sig32( pMdft_out_fx[1], shl( frame_len, 1 ), sub( s_min( q_pMdft_out_fx[0], q_pMdft_out_fx[1] ), q_pMdft_out_fx[1] ) );
912 : #endif
913 0 : ivas_fb_mixer_cross_fading_fx( hFbMixer, ppOut_pcm_fx, pMdft_out_fx[0], pMdft_out_fx[1], ch, frame_len, frame_len );
914 0 : q_ppOut_pcm_fx[ch] = s_min( q_pMdft_out_fx[0], q_pMdft_out_fx[1] );
915 0 : move16();
916 : }
917 :
918 0 : return;
919 : }
920 :
921 : /*-----------------------------------------------------------------------------------------*
922 : * Function ivas_fb_mixer_get_in_out_mapping()
923 : *
924 : *
925 : *-----------------------------------------------------------------------------------------*/
926 0 : void ivas_fb_mixer_get_in_out_mapping_fx(
927 : const IVAS_FB_CFG *fb_cfg, /* i : FB config. handle */
928 : Word16 in_out_mixer_map[IVAS_MAX_FB_MIXER_OUT_CH][IVAS_MAX_SPAR_FB_MIXER_IN_CH] /* i/o: mixing mapping */
929 : )
930 : {
931 : Word16 i, j;
932 :
933 0 : set_s( (Word16 *) in_out_mixer_map, 0, IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH );
934 :
935 0 : IF( fb_cfg->active_w_mixing )
936 : {
937 0 : FOR( i = 0; i < fb_cfg->num_out_chans; i++ )
938 : {
939 0 : FOR( j = 0; j < fb_cfg->num_in_chans; j++ )
940 : {
941 0 : in_out_mixer_map[i][j] = 1;
942 0 : move16();
943 : }
944 : }
945 : }
946 : ELSE
947 : {
948 0 : in_out_mixer_map[0][0] = 1; /* W depends on only W input*/
949 0 : move16();
950 0 : FOR( i = 1; i < fb_cfg->num_out_chans; i++ )
951 : {
952 0 : in_out_mixer_map[i][0] = 1;
953 0 : move16();
954 : }
955 : }
956 :
957 0 : return;
958 : }
959 :
960 : /*-----------------------------------------------------------------------------------------*
961 : * Function ivas_calculate_abs_fr()
962 : *
963 : * Function to calculate number of active bands
964 : *-----------------------------------------------------------------------------------------*/
965 :
966 273 : static Word16 ivas_calculate_abs_fr_fx(
967 : ivas_filterbank_t *pFb,
968 : const Word32 sampling_rate,
969 : const Word16 alloc_fb_resp,
970 : Word16 *index )
971 : {
972 : Word16 frame_len;
973 : Word32 ppFilterbank_FRs_s_fx[L_FRAME48k];
974 273 : Word16 bands = pFb->filterbank_num_bands;
975 273 : move16();
976 273 : Word16 i, j, num_active_bands = 0;
977 273 : move16();
978 273 : Word16 idx_short_stride_bin_to_band = 0;
979 273 : move16();
980 : Word16 quo, tmp, exp_diff;
981 :
982 273 : Word32 temp = Mpy_32_32( sampling_rate, 42949673 /* FRAMES_PER_SEC in Q31 */ );
983 273 : frame_len = extract_l( temp );
984 :
985 3469 : FOR( i = 0; i < bands; i++ )
986 : {
987 3196 : const Word32 *long_mdft_ptr_re_fx = pFb->fb_consts.ppFilterbank_FRs_fx[0][i]; // Q30
988 3196 : const Word32 *long_mdft_ptr_im_fx = pFb->fb_consts.ppFilterbank_FRs_fx[1][i]; // Q30
989 :
990 3196 : Word16 start_offset = pFb->fb_consts.pFilterbank_bins_start_offset[i];
991 3196 : move16();
992 3196 : Word16 num_bins = pFb->fb_consts.pFilterbank_bins_per_band[i];
993 3196 : move16();
994 3196 : Word16 short_mdft_start_bin = -1;
995 3196 : move16();
996 :
997 : Word32 short_stride_pow_spec_fx[MDFT_FB_BANDS_240];
998 3196 : Word32 short_stride_nrg_fx = 0;
999 3196 : move16();
1000 3196 : exp_diff = 0;
1001 3196 : move16();
1002 :
1003 3196 : Word64 cldfb_nrg_fx = 0;
1004 3196 : move64();
1005 3196 : Word16 short_stride = pFb->fb_bin_to_band.short_stride;
1006 3196 : move16();
1007 : Word32 res_dec1, res_frac, res_dec2;
1008 3196 : iDiv_and_mod_32( sampling_rate, FRAMES_PER_SEC, &res_dec1, &res_frac, 0 );
1009 3196 : iDiv_and_mod_32( res_dec1, short_stride, &res_dec2, &res_frac, 0 );
1010 3196 : const Word16 num_bins_per_short_stride_bin = extract_l( res_dec2 );
1011 3196 : iDiv_and_mod_32( res_dec1, pFb->fb_bin_to_band.num_cldfb_bands, &res_dec2, &res_frac, 0 );
1012 3196 : const Word16 num_bins_per_cldfb_band = extract_l( res_dec2 );
1013 :
1014 3196 : Word32 short_stride_max_per_spar_band_fx = 1;
1015 3196 : move32();
1016 :
1017 : /*loop over all stored Filter Bank Response MDFT coefficients*/
1018 :
1019 3196 : set32_fx( short_stride_pow_spec_fx, 0, MDFT_FB_BANDS_240 );
1020 :
1021 966952 : FOR( j = start_offset; j < num_bins + start_offset; j++ )
1022 : {
1023 :
1024 : Word32 sq_abs_fx;
1025 :
1026 : // Word32 real = L_shr( *long_mdft_ptr_re_fx, 3 ); // Q27
1027 963756 : Word32 real = *long_mdft_ptr_re_fx; // Q30
1028 963756 : move32();
1029 : // Word32 imag = L_shr( *long_mdft_ptr_im_fx, 3 ); // Q27
1030 963756 : Word32 imag = *long_mdft_ptr_im_fx; // Q30
1031 963756 : move32();
1032 963756 : Word64 acc = W_mac_32_32( W_mult_32_32( real, real ), imag, imag ); // Q61
1033 963756 : sq_abs_fx = W_extract_h( acc ); // Q28
1034 963756 : long_mdft_ptr_re_fx++;
1035 963756 : long_mdft_ptr_im_fx++;
1036 :
1037 : /* accumulate bin energies within a short stride bin */
1038 :
1039 963756 : short_stride_nrg_fx = L_add( short_stride_nrg_fx, L_shr( sq_abs_fx, 6 ) ); // Q22
1040 963756 : move32();
1041 :
1042 963756 : IF( !( add( j, 1 ) % num_bins_per_short_stride_bin ) )
1043 : {
1044 : /* new short stride bin */
1045 240423 : short_stride_pow_spec_fx[j / num_bins_per_short_stride_bin] = short_stride_nrg_fx; /* energy rather than magnitude works better for covariance weighting*/
1046 240423 : move32();
1047 240423 : short_stride_max_per_spar_band_fx = L_max( short_stride_nrg_fx, short_stride_max_per_spar_band_fx ); /*compute highest magnitude per band*/
1048 240423 : short_stride_nrg_fx = 0;
1049 240423 : move32();
1050 : }
1051 :
1052 : /* accumulate bin energies within a CLDFB band */
1053 963756 : cldfb_nrg_fx = W_mac_32_32( cldfb_nrg_fx, sq_abs_fx, 1 ); // Q29
1054 :
1055 963756 : IF( !( add( j, 1 ) % num_bins_per_cldfb_band ) )
1056 : {
1057 59627 : Word16 exp = W_norm( cldfb_nrg_fx );
1058 59627 : cldfb_nrg_fx = W_shl( cldfb_nrg_fx, exp );
1059 59627 : exp = sub( 34, exp ); // 31 - (Q29 + exp -32)
1060 59627 : temp = Sqrt32( W_extract_h( cldfb_nrg_fx ), &exp );
1061 59627 : temp = L_shl( temp, sub( exp, Q9 ) ); // Q22
1062 59627 : pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[j / num_bins_per_cldfb_band][i] = temp; // Q22
1063 59627 : move32();
1064 59627 : cldfb_nrg_fx = 0;
1065 59627 : move32();
1066 : }
1067 : }
1068 :
1069 3196 : quo = BASOP_Util_Divide3232_Scale( ONE_IN_Q30, short_stride_max_per_spar_band_fx, &exp_diff );
1070 : /* Q of quo = Q30 - Q22 + (15 - exp_diff) --> Q23 - exp_diff.
1071 : With Mult_32_16, Q23 - exp_diff - 15 --> Q8 - exp_diff */
1072 3196 : exp_diff = sub( Q8, exp_diff );
1073 :
1074 : /*loop over the short MDFT bins*/
1075 596796 : FOR( j = 0; j < short_stride; j++ )
1076 : {
1077 593600 : short_stride_pow_spec_fx[j] = L_shr( Mult_32_16( short_stride_pow_spec_fx[j], quo ), exp_diff ); // Q22
1078 593600 : move32();
1079 593600 : short_stride_pow_spec_fx[j] = L_max( L_sub( short_stride_pow_spec_fx[j], 1258291 ), 0 ); // 0.3f * ONE_IN_Q22
1080 593600 : move32();
1081 593600 : short_stride_pow_spec_fx[j] = L_shl( Mpy_32_32( short_stride_pow_spec_fx[j], 1533916891 /* 1/0.7 in Q30 */ ), 1 ); // Q22
1082 593600 : move32();
1083 :
1084 :
1085 593600 : IF( short_stride_pow_spec_fx[j] > 0 )
1086 : {
1087 53792 : assert( idx_short_stride_bin_to_band < 2 * MDFT_FB_BANDS_240 ); /* array size of p_short_stride_bin_to_band */
1088 53792 : IF( EQ_16( short_mdft_start_bin, -1 ) )
1089 : {
1090 3196 : short_mdft_start_bin = j;
1091 3196 : move16();
1092 3196 : pFb->fb_bin_to_band.p_short_stride_start_bin_per_band[i] = j;
1093 3196 : move16();
1094 :
1095 3196 : pFb->fb_bin_to_band.pp_short_stride_bin_to_band_fx[i] = &pFb->fb_bin_to_band.p_short_stride_bin_to_band_fx[idx_short_stride_bin_to_band]; // Q22
1096 3196 : index[i] = idx_short_stride_bin_to_band;
1097 3196 : move16();
1098 : }
1099 :
1100 53792 : pFb->fb_bin_to_band.p_short_stride_bin_to_band_fx[idx_short_stride_bin_to_band] = short_stride_pow_spec_fx[j]; // Q22
1101 53792 : move32();
1102 53792 : idx_short_stride_bin_to_band = add( idx_short_stride_bin_to_band, 1 );
1103 :
1104 53792 : pFb->fb_bin_to_band.p_short_stride_num_bins_per_band[i] = add( pFb->fb_bin_to_band.p_short_stride_num_bins_per_band[i], 1 );
1105 53792 : move16();
1106 : }
1107 : }
1108 : }
1109 :
1110 : /*loop over CLDFB bands*/
1111 12773 : FOR( j = 0; j < pFb->fb_bin_to_band.num_cldfb_bands; j++ )
1112 : {
1113 12500 : Word32 sum_over_spar_bands_fx = 0;
1114 12500 : move32();
1115 12500 : Word32 max_spar_band_contribution_fx = 0;
1116 12500 : move32();
1117 :
1118 12500 : Word16 spar_start = 0;
1119 12500 : move16();
1120 12500 : Word16 any_non_zero = 0;
1121 12500 : move16();
1122 :
1123 160900 : FOR( i = 0; i < bands; i++ )
1124 : {
1125 148400 : sum_over_spar_bands_fx = L_add( sum_over_spar_bands_fx, pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[j][i] ); // Q22
1126 148400 : move32();
1127 :
1128 148400 : IF( pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[j][i] > max_spar_band_contribution_fx )
1129 : {
1130 36923 : max_spar_band_contribution_fx = pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[j][i]; // Q22
1131 36923 : move32();
1132 36923 : pFb->fb_bin_to_band.p_cldfb_map_to_spar_band[j] = i;
1133 36923 : move16();
1134 : }
1135 : }
1136 :
1137 12500 : sum_over_spar_bands_fx = L_max( sum_over_spar_bands_fx, EPSILON_FX ); // Q22
1138 12500 : move32();
1139 :
1140 12500 : exp_diff = 0;
1141 12500 : move16();
1142 12500 : tmp = BASOP_Util_Divide3232_Scale( ONE_IN_Q30, sum_over_spar_bands_fx, &exp_diff );
1143 : /* Q of quo = Q30 - Q22 + (15 - exp_diff) --> Q23 - exp_diff.
1144 : With Mult_32_16, Q23 - exp_diff - 15 --> Q8 - exp_diff */
1145 12500 : exp_diff = sub( Q8, exp_diff );
1146 :
1147 160900 : FOR( i = 0; i < bands; i++ )
1148 : {
1149 148400 : test();
1150 148400 : IF( pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[j][i] == 0 && !any_non_zero )
1151 : {
1152 78900 : spar_start = add( spar_start, 1 );
1153 : }
1154 : ELSE
1155 : {
1156 69500 : any_non_zero = 1;
1157 69500 : move16();
1158 : }
1159 :
1160 148400 : pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[j][i] = L_shr( Mult_32_16( pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[j][i], tmp ), exp_diff );
1161 148400 : move32();
1162 : }
1163 12500 : pFb->fb_bin_to_band.p_spar_start_bands[j] = spar_start;
1164 12500 : move16();
1165 : }
1166 :
1167 273 : set32_fx( ppFilterbank_FRs_s_fx, 0, frame_len );
1168 :
1169 : /*Commented logic is for calculating number of active bands, can be removed if not needed */
1170 3469 : FOR( i = 0; i < bands; i++ )
1171 : {
1172 3196 : const Word32 *pFilterbank_bin_to_band_re_fx = pFb->fb_consts.ppFilterbank_FRs_fx[0][i]; // Q30
1173 3196 : move32();
1174 3196 : const Word32 *pFilterbank_bin_to_band_im_fx = pFb->fb_consts.ppFilterbank_FRs_fx[1][i]; // Q30
1175 3196 : move32();
1176 :
1177 3196 : Word16 start_offset = pFb->fb_consts.pFilterbank_bins_start_offset[i];
1178 3196 : move16();
1179 3196 : Word16 num_bins = pFb->fb_consts.pFilterbank_bins_per_band[i];
1180 3196 : move16();
1181 3196 : Word16 idx = 0;
1182 3196 : move16();
1183 3196 : Word16 abs_active_bins = pFb->fb_bin_to_band.pFb_active_bins_per_band[i];
1184 3196 : move16();
1185 3196 : Word16 abs_start_offset = pFb->fb_bin_to_band.pFb_start_bin_per_band[i];
1186 3196 : move16();
1187 :
1188 966952 : FOR( j = start_offset; j < num_bins + start_offset; j++ )
1189 : {
1190 963756 : Word32 temp_fx = 0;
1191 963756 : move32();
1192 :
1193 963756 : exp_diff = 0;
1194 963756 : move16();
1195 963756 : Word32 real = L_shr( *pFilterbank_bin_to_band_re_fx, 3 ); // Q27
1196 963756 : Word32 imag = L_shr( *pFilterbank_bin_to_band_im_fx, 3 ); // Q27
1197 :
1198 : Word32 real_sq, imag_sq;
1199 963756 : real_sq = Mpy_32_32( real, real ); // Q27 + Q27 - 31 = Q23
1200 963756 : imag_sq = Mpy_32_32( imag, imag ); // Q27 + Q27 - 31 = Q23
1201 :
1202 963756 : temp_fx = L_add( L_shr( real_sq, 1 ), L_shr( imag_sq, 1 ) ); // Q22
1203 :
1204 963756 : exp_diff = 9;
1205 963756 : move16();
1206 963756 : temp_fx = Sqrt32( temp_fx, &exp_diff );
1207 963756 : temp_fx = L_shl( temp_fx, sub( exp_diff, Q9 ) ); // Q22
1208 :
1209 :
1210 963756 : pFilterbank_bin_to_band_re_fx++;
1211 963756 : pFilterbank_bin_to_band_im_fx++;
1212 :
1213 963756 : temp_fx = L_sub( temp_fx, 1258291 ); // 0.3 in Q22
1214 963756 : move32();
1215 :
1216 963756 : if ( temp_fx < 0 )
1217 : {
1218 691682 : temp_fx = 0;
1219 691682 : move32();
1220 : }
1221 :
1222 963756 : test();
1223 963756 : test();
1224 963756 : IF( LT_16( j, add( abs_active_bins, abs_start_offset ) ) && GE_16( j, abs_start_offset ) && NE_16( alloc_fb_resp, -1 ) )
1225 : {
1226 0 : pFb->fb_bin_to_band.pFb_bin_to_band_fx[i][idx] = temp_fx; // Q22
1227 0 : move32();
1228 0 : idx = add( idx, 1 );
1229 : }
1230 :
1231 :
1232 963756 : ppFilterbank_FRs_s_fx[j] = L_add( ppFilterbank_FRs_s_fx[j], temp_fx ); // Q22
1233 963756 : move32();
1234 : }
1235 : }
1236 :
1237 200273 : FOR( i = 0; i < frame_len; i++ )
1238 : {
1239 200000 : if ( ppFilterbank_FRs_s_fx[i] < 0 )
1240 : {
1241 0 : ppFilterbank_FRs_s_fx[i] = 419430; // 0.1 in Q22
1242 0 : move32();
1243 : }
1244 : }
1245 :
1246 273 : IF( NE_16( alloc_fb_resp, -1 ) )
1247 : {
1248 0 : FOR( j = 0; j < bands; j++ )
1249 : {
1250 0 : Word16 abs_active_bins = pFb->fb_bin_to_band.pFb_active_bins_per_band[j];
1251 0 : Word16 abs_start_offset = pFb->fb_bin_to_band.pFb_start_bin_per_band[j];
1252 0 : exp_diff = 0;
1253 :
1254 0 : move16();
1255 0 : move16();
1256 0 : move16();
1257 :
1258 0 : FOR( i = 0; i < abs_active_bins; i++ )
1259 : {
1260 0 : tmp = BASOP_Util_Divide3232_Scale( pFb->fb_bin_to_band.pFb_bin_to_band_fx[j][i], ppFilterbank_FRs_s_fx[i + abs_start_offset], &exp_diff );
1261 0 : pFb->fb_bin_to_band.pFb_bin_to_band_fx[j][i] = L_shl( L_deposit_l( tmp ), add( Q7, exp_diff ) ); // Q22
1262 0 : move32();
1263 : /*if(pFb->fb_bin_to_band.pFb_bin_to_band[j][i] > 0.5f)
1264 : {
1265 : num_active_bands = j + 1;
1266 : break;
1267 : }*/
1268 : }
1269 : }
1270 : }
1271 :
1272 273 : return num_active_bands;
1273 : }
1274 :
1275 : /*-----------------------------------------------------------------------------------------*
1276 : * Function ivas_get_active_bins()
1277 : *
1278 : *
1279 : *-----------------------------------------------------------------------------------------*/
1280 :
1281 546 : static void ivas_get_active_bins_fx(
1282 : const Word16 **pActive_bins,
1283 : const Word16 **pActive_bins_abs,
1284 : const Word16 **pStart_offset,
1285 : const Word16 **pStart_offset_abs,
1286 : const Word32 sampling_rate )
1287 : {
1288 : Word16 sr_idx;
1289 :
1290 546 : IF( EQ_32( sampling_rate, 32000 ) )
1291 : {
1292 228 : sr_idx = 1;
1293 228 : move16();
1294 : }
1295 318 : ELSE IF( EQ_32( sampling_rate, 16000 ) )
1296 : {
1297 80 : sr_idx = 2;
1298 80 : move16();
1299 : }
1300 : ELSE
1301 : {
1302 238 : sr_idx = 0;
1303 238 : move16();
1304 : }
1305 :
1306 546 : *pActive_bins_abs = ivas_fb_abs_bins_per_band_12band_1ms[sr_idx];
1307 546 : move16();
1308 546 : *pActive_bins = ivas_fb_bins_per_band_12band_1ms[sr_idx];
1309 546 : move16();
1310 546 : *pStart_offset_abs = ivas_fb_abs_bins_start_offset_12band_1ms[sr_idx];
1311 546 : move16();
1312 546 : *pStart_offset = ivas_fb_bins_start_offset_12band_1ms[sr_idx];
1313 546 : move16();
1314 :
1315 546 : return;
1316 : }
1317 :
1318 :
1319 : /*-----------------------------------------------------------------------------------------*
1320 : * Function ivas_filterbank_setup()
1321 : *
1322 : * Filterbank setup, initialization
1323 : *-----------------------------------------------------------------------------------------*/
1324 :
1325 273 : static ivas_error ivas_filterbank_setup_fx(
1326 : IVAS_FB_MIXER_HANDLE hFbMixer,
1327 : const Word32 sampling_rate,
1328 : Word16 *index )
1329 : {
1330 : Word16 i, j, exp, tmp;
1331 : const Word32 *pAll_fb_fr_fx[2];
1332 273 : const Word16 *pAll_bins_start_offset = NULL;
1333 273 : const Word16 *pAll_bins_per_band = NULL;
1334 273 : const Word16 *pAll_bins_start_offset_abs = NULL;
1335 273 : const Word16 *pAll_bins_per_band_abs = NULL;
1336 273 : const Word16 *pAll_bins_per_band_48k = NULL;
1337 : ivas_error error;
1338 273 : IVAS_FB_CFG *pCfg = hFbMixer->fb_cfg;
1339 :
1340 273 : error = IVAS_ERR_OK;
1341 273 : move32();
1342 :
1343 273 : IF( pCfg->num_out_chans > 0 )
1344 : {
1345 273 : hFbMixer->pFb->filterbank_num_bands = ivas_get_num_bands( sampling_rate );
1346 273 : move16();
1347 :
1348 273 : ivas_get_active_bins_fx( &pAll_bins_per_band, &pAll_bins_per_band_abs, &pAll_bins_start_offset, &pAll_bins_start_offset_abs, sampling_rate );
1349 :
1350 273 : IF( EQ_16( pCfg->fb_latency, NS2SA_FX2( sampling_rate, DELAY_FB_1_NS ) ) )
1351 : {
1352 273 : pAll_fb_fr_fx[0] = ivas_fb_fr_12band_1ms_re_fx; // Q30
1353 273 : move32();
1354 273 : pAll_fb_fr_fx[1] = ivas_fb_fr_12band_1ms_im_fx; // Q30
1355 273 : move32();
1356 :
1357 273 : pAll_bins_per_band_48k = ivas_fb_bins_per_band_12band_1ms[0];
1358 273 : move16();
1359 : }
1360 : ELSE
1361 : {
1362 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong FB in ivas_filterbank_setup()!" );
1363 : }
1364 : }
1365 :
1366 273 : hFbMixer->cross_fade_end_offset = add( pCfg->fade_len, pCfg->pcm_offset );
1367 273 : move16();
1368 273 : hFbMixer->cross_fade_start_offset = sub( hFbMixer->cross_fade_end_offset, pCfg->fade_len );
1369 273 : move16();
1370 273 : hFbMixer->ana_window_offset = add( pCfg->fb_latency, pCfg->pcm_offset );
1371 273 : move16();
1372 :
1373 273 : IF( NE_32( ( error = ivas_fb_mixer_get_window_fx( pCfg->fb_latency, sampling_rate, &( hFbMixer->pAna_window_fx ) ) ), IVAS_ERR_OK ) )
1374 : {
1375 0 : return error;
1376 : }
1377 :
1378 273 : IF( NE_32( ( error = ivas_fb_mixer_get_window_fx( pCfg->fade_len, sampling_rate, &( hFbMixer->pFilterbank_cross_fade_fx ) ) ), IVAS_ERR_OK ) )
1379 : {
1380 0 : return error;
1381 : }
1382 :
1383 273 : IF( pCfg->num_out_chans > 0 )
1384 : {
1385 273 : ivas_filterbank_t *pFb = hFbMixer->pFb;
1386 273 : Word16 offset = 0;
1387 273 : move16();
1388 :
1389 273 : pFb->fb_consts.pFilterbank_bins_per_band = pAll_bins_per_band;
1390 273 : pFb->fb_consts.pFilterbank_bins_start_offset = pAll_bins_start_offset;
1391 273 : pFb->fb_bin_to_band.pFb_active_bins_per_band = pAll_bins_per_band_abs;
1392 273 : pFb->fb_bin_to_band.pFb_start_bin_per_band = pAll_bins_start_offset_abs;
1393 :
1394 : /* Initialization for short stride Parameter calculation and SPAR CLDFB reconstruction */
1395 273 : SWITCH( sampling_rate )
1396 : {
1397 119 : case 48000:
1398 119 : pFb->fb_bin_to_band.num_cldfb_bands = 60; /* sampling_rate * 1.0f / 800.0f */
1399 119 : move16();
1400 119 : BREAK;
1401 114 : case 32000:
1402 114 : pFb->fb_bin_to_band.num_cldfb_bands = 40;
1403 114 : move16();
1404 114 : BREAK;
1405 40 : case 16000:
1406 40 : pFb->fb_bin_to_band.num_cldfb_bands = 20;
1407 40 : move16();
1408 40 : BREAK;
1409 : }
1410 :
1411 : /*pFb->fb_bin_to_band.cldfb_stride = ( int16_t )( ( sampling_rate / FRAMES_PER_SEC ) / CLDFB_NO_COL_MAX );*/ /* equals num_cldfb_bands*/
1412 : // pFb->fb_bin_to_band.short_stride = extract_l( ( sampling_rate / FRAMES_PER_SEC ) / 4 );
1413 273 : tmp = BASOP_Util_Divide3232_Scale( sampling_rate, FRAMES_PER_SEC, &exp );
1414 273 : pFb->fb_bin_to_band.short_stride = shr( tmp, add( sub( 15, exp ), 2 ) );
1415 :
1416 273 : move16();
1417 :
1418 273 : set32_fx( pFb->fb_bin_to_band.p_short_stride_bin_to_band_fx, 0, 2 * MDFT_FB_BANDS_240 );
1419 :
1420 273 : set16_fx( pFb->fb_bin_to_band.p_cldfb_map_to_spar_band, 0, CLDFB_NO_CHANNELS_MAX );
1421 273 : set16_fx( pFb->fb_bin_to_band.p_spar_start_bands, 0, CLDFB_NO_CHANNELS_MAX );
1422 :
1423 5733 : FOR( j = 0; j < IVAS_MAX_NUM_FB_BANDS; j++ )
1424 : {
1425 5460 : pFb->fb_bin_to_band.p_short_stride_num_bins_per_band[j] = 0; /* aka num_active_bins per SPAR band */
1426 5460 : move16();
1427 5460 : pFb->fb_bin_to_band.p_short_stride_start_bin_per_band[j] = 0; /* first considered bin index per SPAR band */
1428 5460 : move16();
1429 :
1430 5460 : pFb->fb_bin_to_band.pp_short_stride_bin_to_band_fx[j] = NULL;
1431 :
1432 333060 : FOR( i = 0; i < CLDFB_NO_CHANNELS_MAX; i++ )
1433 : {
1434 :
1435 327600 : pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[i][j] = 0;
1436 327600 : move32();
1437 : }
1438 : }
1439 273 : IF( EQ_32( sampling_rate, 48000 ) )
1440 : {
1441 1547 : FOR( j = 0; j < pFb->filterbank_num_bands; j++ )
1442 : {
1443 :
1444 1428 : pFb->fb_consts.ppFilterbank_FRs_fx[0][j] = &pAll_fb_fr_fx[0][offset]; // Q30
1445 1428 : pFb->fb_consts.ppFilterbank_FRs_fx[1][j] = &pAll_fb_fr_fx[1][offset]; // Q30
1446 :
1447 1428 : offset = add( offset, pFb->fb_consts.pFilterbank_bins_per_band[j] );
1448 : }
1449 :
1450 : /****************************************Calculate abs fr ***************************/
1451 :
1452 119 : ivas_calculate_abs_fr_fx( pFb, sampling_rate, pCfg->active_w_mixing, index );
1453 : }
1454 : ELSE
1455 : {
1456 :
1457 : Word32 *ppFilterbank_FRs_re_temp_fx[MAX_NUM_BANDS_DIFF_NON48K];
1458 : Word32 *ppFilterbank_FRs_im_temp_fx[MAX_NUM_BANDS_DIFF_NON48K];
1459 : Word16 active_bins_temp[MAX_NUM_BANDS_DIFF_NON48K];
1460 : Word16 start_offset_temp[MAX_NUM_BANDS_DIFF_NON48K];
1461 : Word16 num_diff_bands, start_diff_band_non48k;
1462 :
1463 154 : num_diff_bands = MAX_NUM_BANDS_DIFF_NON48K;
1464 154 : start_diff_band_non48k = sub( pFb->filterbank_num_bands, num_diff_bands );
1465 154 : move16();
1466 :
1467 154 : pFb->fb_consts.pFilterbank_bins_per_band = pAll_bins_per_band;
1468 154 : pFb->fb_consts.pFilterbank_bins_start_offset = pAll_bins_start_offset;
1469 :
1470 1922 : FOR( j = 0; j < pFb->filterbank_num_bands; j++ )
1471 : {
1472 1768 : Word16 num_active_bins = pFb->fb_consts.pFilterbank_bins_per_band[j];
1473 1768 : move16();
1474 :
1475 1768 : IF( j < start_diff_band_non48k )
1476 : {
1477 :
1478 1306 : pFb->fb_consts.ppFilterbank_FRs_fx[0][j] = &pAll_fb_fr_fx[0][offset]; // Q30
1479 1306 : pFb->fb_consts.ppFilterbank_FRs_fx[1][j] = &pAll_fb_fr_fx[1][offset]; // Q30
1480 : }
1481 : ELSE
1482 : {
1483 462 : Copy32( &pAll_fb_fr_fx[0][offset], pFb->fb_consts.ppFilterbank_FRs_non48k_fx[0][j], num_active_bins ); // Q30
1484 462 : Copy32( &pAll_fb_fr_fx[1][offset], pFb->fb_consts.ppFilterbank_FRs_non48k_fx[1][j], num_active_bins ); // Q30
1485 : }
1486 :
1487 1768 : offset = add( offset, pAll_bins_per_band_48k[j] );
1488 : }
1489 :
1490 616 : FOR( j = start_diff_band_non48k; j < pFb->filterbank_num_bands; j++ )
1491 : {
1492 :
1493 462 : ppFilterbank_FRs_re_temp_fx[j - start_diff_band_non48k] = pFb->fb_consts.ppFilterbank_FRs_non48k_fx[0][j]; // Q30
1494 462 : ppFilterbank_FRs_im_temp_fx[j - start_diff_band_non48k] = pFb->fb_consts.ppFilterbank_FRs_non48k_fx[1][j]; // Q30
1495 :
1496 462 : active_bins_temp[j - start_diff_band_non48k] = pFb->fb_consts.pFilterbank_bins_per_band[j];
1497 462 : start_offset_temp[j - start_diff_band_non48k] = pFb->fb_consts.pFilterbank_bins_start_offset[j];
1498 462 : move16();
1499 462 : move16();
1500 : }
1501 :
1502 154 : ivas_get_ld_fb_resp_fx( ppFilterbank_FRs_re_temp_fx, ppFilterbank_FRs_im_temp_fx, ppFilterbank_FRs_re_temp_fx, ppFilterbank_FRs_im_temp_fx,
1503 154 : active_bins_temp, start_offset_temp, num_diff_bands, pCfg->fb_latency, sampling_rate );
1504 :
1505 :
1506 616 : FOR( j = start_diff_band_non48k; j < pFb->filterbank_num_bands; j++ )
1507 : {
1508 :
1509 462 : pFb->fb_consts.ppFilterbank_FRs_fx[0][j] = (const Word32 *) pFb->fb_consts.ppFilterbank_FRs_non48k_fx[0][j]; // Q30
1510 462 : pFb->fb_consts.ppFilterbank_FRs_fx[1][j] = (const Word32 *) pFb->fb_consts.ppFilterbank_FRs_non48k_fx[1][j]; // Q30
1511 : }
1512 :
1513 : /******************************************** Calculate abs fr ****************************************************/
1514 :
1515 154 : ivas_calculate_abs_fr_fx( pFb, sampling_rate, pCfg->active_w_mixing, index );
1516 : }
1517 : }
1518 :
1519 273 : return error;
1520 : }
1521 :
1522 : /*-----------------------------------------------------------------------------------------*
1523 : * Function ivas_fb_mixer_get_window()
1524 : *
1525 : *
1526 : *-----------------------------------------------------------------------------------------*/
1527 :
1528 546 : static ivas_error ivas_fb_mixer_get_window_fx(
1529 : const Word16 fade_len, /* i : window fading length in samples */
1530 : const Word32 sampling_rate, /* i : sampling rate */
1531 : const Word16 **pWindow /* o : pointer to the window coefficents */
1532 : )
1533 : {
1534 : ivas_error error;
1535 :
1536 546 : error = IVAS_ERR_OK;
1537 546 : move32();
1538 :
1539 546 : IF( EQ_16( fade_len, NS2SA_FX2( sampling_rate, DELAY_FB_4_NS ) ) )
1540 : {
1541 273 : SWITCH( sampling_rate )
1542 : {
1543 119 : case 48000:
1544 119 : *pWindow = ivas_fb_cf_4ms_48k_fx;
1545 119 : BREAK;
1546 114 : case 32000:
1547 114 : *pWindow = ivas_fb_cf_4ms_32k_fx;
1548 114 : BREAK;
1549 40 : case 16000:
1550 40 : *pWindow = ivas_fb_cf_4ms_16k_fx;
1551 40 : BREAK;
1552 0 : default:
1553 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unsupported Sampling frequency!" );
1554 : }
1555 : }
1556 273 : ELSE IF( EQ_16( fade_len, NS2SA_FX2( sampling_rate, DELAY_FB_1_NS ) ) )
1557 : {
1558 273 : SWITCH( sampling_rate )
1559 : {
1560 119 : case 48000:
1561 119 : *pWindow = ivas_fb_cf_1ms_48k_fx;
1562 119 : BREAK;
1563 114 : case 32000:
1564 114 : *pWindow = ivas_fb_cf_1ms_32k_fx;
1565 114 : BREAK;
1566 40 : case 16000:
1567 40 : *pWindow = ivas_fb_cf_1ms_16k_fx;
1568 40 : BREAK;
1569 0 : default:
1570 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unsupported Sampling frequency!" );
1571 : }
1572 : }
1573 : ELSE
1574 : {
1575 0 : IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Incorrect FB window fade len (%f ms)\n", ( fade_len / 1000000.f ) );
1576 : }
1577 :
1578 546 : return error;
1579 : }
1580 :
1581 :
1582 154 : static const Word32 *ivas_get_cheby_ramp_fx(
1583 : const Word16 delay )
1584 : {
1585 154 : const Word32 *pCheby_fx = NULL;
1586 :
1587 154 : SWITCH( delay )
1588 : {
1589 114 : case IVAS_FB_1MS_32K_SAMP:
1590 114 : pCheby_fx = ivas_fb_resp_cheby_ramp_32del_fx;
1591 114 : BREAK;
1592 40 : case IVAS_FB_1MS_16K_SAMP:
1593 40 : pCheby_fx = ivas_fb_resp_cheby_ramp_16del_fx;
1594 40 : BREAK;
1595 0 : default:
1596 0 : assert( !"Unsupported cheby ramp length!" );
1597 : }
1598 :
1599 154 : return pCheby_fx;
1600 : }
1601 :
1602 154 : static void ivas_get_ld_fb_resp_fx(
1603 : Word32 **ppIdeal_FRs_re_fx, // i: Q30
1604 : Word32 **ppIdeal_FRs_im_fx, // i: Q30
1605 : Word32 **ppNew_FRs_re_fx, // o: Q30
1606 : Word32 **ppNew_FRs_im_fx, // o: Q30
1607 : const Word16 *pActive_bins,
1608 : const Word16 *pStart_offset,
1609 : const Word16 num_bands,
1610 : const Word16 delay,
1611 : const Word32 sampling_rate )
1612 : {
1613 : Word16 b, s, frame_len;
1614 : const Word32 *pCheby_fx;
1615 154 : frame_len = 0;
1616 154 : move16();
1617 : /*common scratch buffers for computing impulse/frequency responses,
1618 : pre-ring, post-ring and circular shifted outputs to optimize stack*/
1619 : Word32 scratch1_fx[L_FRAME32k * 2];
1620 : Word32 scratch2_fx[L_FRAME32k * 2];
1621 :
1622 154 : set32_fx( scratch1_fx, 0, L_FRAME32k * 2 );
1623 154 : set32_fx( scratch2_fx, 0, L_FRAME32k * 2 );
1624 :
1625 154 : const Word32 *han_win_fx = NULL;
1626 :
1627 154 : SWITCH( sampling_rate )
1628 : {
1629 0 : case 48000:
1630 0 : frame_len = 960;
1631 0 : move16();
1632 0 : han_win_fx = ivas_han_win_48k_fx; // Q31
1633 0 : BREAK;
1634 114 : case 32000:
1635 114 : frame_len = 640;
1636 114 : move16();
1637 114 : han_win_fx = ivas_han_win_32k_fx; // Q31
1638 114 : BREAK;
1639 40 : case 16000:
1640 40 : frame_len = 320;
1641 40 : move16();
1642 40 : han_win_fx = ivas_han_win_16k_fx; // Q31
1643 40 : BREAK;
1644 : }
1645 :
1646 154 : pCheby_fx = ivas_get_cheby_ramp_fx( delay ); // Q31
1647 :
1648 154 : b = 0;
1649 154 : s = 0;
1650 154 : move16();
1651 154 : move16();
1652 :
1653 154 : assert( sampling_rate == 32000 || sampling_rate == 16000 );
1654 :
1655 616 : FOR( b = 0; b < num_bands; b++ )
1656 : {
1657 :
1658 462 : set32_fx( scratch2_fx, 0, shl( frame_len, 1 ) );
1659 462 : Copy32( ppIdeal_FRs_re_fx[b], &scratch2_fx[pStart_offset[b]], pActive_bins[b] ); // Q30
1660 462 : Copy32( ppIdeal_FRs_im_fx[b], &scratch2_fx[frame_len + pStart_offset[b]], pActive_bins[b] ); // Q30
1661 :
1662 462 : Word16 guard_bits = sub( L_norm_arr( scratch2_fx, shl( L_FRAME32k, 1 ) ), find_guarded_bits_fx( shl( frame_len, 1 ) ) );
1663 462 : Scale_sig32( scratch2_fx, shl( L_FRAME32k, 1 ), guard_bits ); // Q30 + guard_bits
1664 :
1665 462 : ivas_imdft_fx( scratch2_fx, &scratch2_fx[frame_len], scratch1_fx, frame_len );
1666 :
1667 591822 : FOR( Word16 x = 0; x < shl( L_FRAME32k, 1 ); x++ )
1668 : {
1669 591360 : scratch2_fx[x] = L_shr( scratch2_fx[x], guard_bits ); // (Q30 + guard_bits) - guard_bits = Q30
1670 591360 : scratch1_fx[x] = L_shr( scratch1_fx[x], guard_bits ); // (Q30 + guard_bits) - guard_bits = Q30
1671 :
1672 591360 : move32();
1673 591360 : move32();
1674 : }
1675 :
1676 : /*apply circular shift and hanning window*/
1677 :
1678 257742 : FOR( s = delay; s < frame_len + delay; s++ )
1679 : {
1680 :
1681 257280 : scratch2_fx[s - delay] = Mpy_32_32( scratch1_fx[s], L_sub( ONE_IN_Q31, han_win_fx[s - delay] ) ); // Q(30 + 31 - 31) == Q30
1682 257280 : move32();
1683 : }
1684 :
1685 244878 : FOR( ; s < 2 * frame_len; s++ )
1686 : {
1687 :
1688 244416 : scratch2_fx[s - delay] = Mpy_32_32( scratch1_fx[s], han_win_fx[s - ( frame_len + delay )] ); // Q30
1689 244416 : move32();
1690 : }
1691 :
1692 13326 : FOR( s = 0; s < delay; s++ )
1693 : {
1694 :
1695 12864 : scratch2_fx[( ( ( frame_len * 2 ) - delay ) + s )] = L_negate( Mpy_32_32( scratch1_fx[s], han_win_fx[( frame_len - delay ) + s] ) ); // Q30
1696 12864 : move32();
1697 : }
1698 :
1699 : /*apply heavy/cheby ramp window and compute pre ring*/
1700 :
1701 13788 : FOR( s = 0; s < delay + 1; s++ )
1702 : {
1703 13326 : scratch1_fx[s] = Mpy_32_32( scratch2_fx[s], pCheby_fx[delay - s] ); // Q30
1704 13326 : move32();
1705 : }
1706 :
1707 244416 : FOR( ; s < frame_len; s++ )
1708 : {
1709 243954 : scratch1_fx[s] = 0;
1710 243954 : move32();
1711 : }
1712 :
1713 244878 : FOR( ; s < 2 * frame_len - delay; s++ )
1714 : {
1715 244416 : scratch1_fx[s] = scratch2_fx[s];
1716 244416 : move32();
1717 : }
1718 :
1719 13326 : FOR( ; s < 2 * frame_len; s++ )
1720 : {
1721 12864 : scratch1_fx[s] = Mpy_32_32( scratch2_fx[s], L_sub( ONE_IN_Q31, pCheby_fx[s - ( 2 * frame_len - delay )] ) ); // Q30
1722 12864 : move32();
1723 : }
1724 :
1725 : /*IR - pre ring + post ring*/
1726 514560 : FOR( s = 1; s < 2 * frame_len; s++ )
1727 : {
1728 514098 : scratch2_fx[s] = L_sub( L_sub( scratch2_fx[s] /*pre ring*/, scratch1_fx[s] /*post ring*/ ), scratch1_fx[frame_len * 2 - s] );
1729 514098 : move32();
1730 : }
1731 :
1732 502158 : FOR( s = 0; s < 2 * frame_len - delay; s++ )
1733 : {
1734 501696 : scratch1_fx[s + delay] = scratch2_fx[s];
1735 501696 : move32();
1736 : }
1737 :
1738 13326 : FOR( ; s < 2 * frame_len; s++ )
1739 : {
1740 12864 : scratch1_fx[( s - ( ( frame_len * 2 ) - delay ) )] = L_negate( scratch2_fx[s] );
1741 12864 : move32();
1742 : }
1743 :
1744 : /* apply final window*/
1745 462 : const Word32 *sine_till_delay = ivas_sine_delay_32_fx; // Q30
1746 462 : Word16 offset = 1;
1747 462 : Word16 delay_16 = 0;
1748 :
1749 462 : move16();
1750 462 : move16();
1751 :
1752 462 : if ( EQ_16( delay, IVAS_FB_1MS_16K_SAMP ) )
1753 : {
1754 120 : delay_16 = 1;
1755 120 : move16();
1756 : }
1757 :
1758 13326 : FOR( s = 0; s < delay; s++ )
1759 : {
1760 12864 : scratch1_fx[s] = Mpy_32_32( scratch1_fx[s], sine_till_delay[s + offset * delay_16] ); // Q30 + Q30 - 31 = Q29
1761 12864 : offset = add( offset, 1 );
1762 12864 : scratch1_fx[s] = L_shl( scratch1_fx[s], 1 ); // Q30
1763 :
1764 12864 : move32();
1765 12864 : move32();
1766 : }
1767 :
1768 462 : const Word32 *sine_till_frame_len = NULL;
1769 :
1770 462 : IF( EQ_16( delay, IVAS_FB_1MS_16K_SAMP ) )
1771 : {
1772 120 : sine_till_frame_len = ivas_sine_frame_len_640_del_16_fx; // Q30
1773 120 : move32();
1774 : }
1775 : ELSE
1776 : {
1777 342 : sine_till_frame_len = ivas_sine_frame_len_640_del_32_fx; // Q30
1778 342 : move32();
1779 : }
1780 462 : Word16 iterator = 0;
1781 462 : move16();
1782 232476 : FOR( s = 2 * delay; s < frame_len + 1; s++ )
1783 : {
1784 232014 : scratch1_fx[s] = Mpy_32_32( scratch1_fx[s], sine_till_frame_len[iterator] ); // Q30 + Q30 - 31 = Q29
1785 232014 : iterator = add( iterator, 1 );
1786 232014 : scratch1_fx[s] = L_shl( scratch1_fx[s], 1 ); // Q30
1787 :
1788 232014 : move32();
1789 232014 : move32();
1790 : }
1791 :
1792 257280 : FOR( ; s < 2 * frame_len; s++ )
1793 : {
1794 256818 : scratch1_fx[s] = 0;
1795 :
1796 256818 : move32();
1797 : }
1798 :
1799 : /*compute frequency response*/
1800 462 : ivas_mdft_fx( scratch1_fx, scratch2_fx, &scratch2_fx[frame_len], shl( frame_len, 1 ), frame_len );
1801 :
1802 462 : Copy32( &scratch2_fx[pStart_offset[b]], ppNew_FRs_re_fx[b], pActive_bins[b] ); // Q30
1803 462 : Copy32( &scratch2_fx[( frame_len + pStart_offset[b] )], ppNew_FRs_im_fx[b], pActive_bins[b] ); // Q30
1804 : }
1805 :
1806 154 : return;
1807 : }
|