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 :
618 0 : n_old_samples = s_min( ( sub( hFbMixer->fb_cfg->prior_input_length, hFbMixer->fb_cfg->windowed_fr_offset ) ), ( shl( mdft_len, 1 ) ) );
619 0 : n_new_samples = s_max( 0, sub( shl( length, 1 ), n_old_samples ) );
620 0 : offset = sub( sub( shl( mdft_len, 1 ), length ), hFbMixer->ana_window_offset );
621 0 : rev_offset = sub( shl( mdft_len, 1 ), hFbMixer->ana_window_offset );
622 0 : set32_fx( fr_in_block_fx, 0, offset );
623 :
624 0 : FOR( ch_idx = 0; ch_idx < nchan_fb_in; ch_idx++ )
625 : {
626 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
627 0 : Copy32( pcm_in_fx[ch_idx], &fr_in_block_fx[n_old_samples], n_new_samples ); // Qx
628 :
629 0 : win_ptr_fx = hFbMixer->pAna_window_fx; /*Q15*/
630 :
631 0 : FOR( j = offset; j < sub( shl( mdft_len, 1 ), length ); j++ )
632 : {
633 0 : fr_in_block_fx[j] = Mpy_32_16_1( fr_in_block_fx[j], ( *( win_ptr_fx++ ) ) ); // Qx + 15 - 15 = Qx
634 0 : move32();
635 : }
636 :
637 0 : FOR( j = rev_offset; j < shl( mdft_len, 1 ); j++ )
638 : {
639 0 : fr_in_block_fx[j] = Mpy_32_16_1( fr_in_block_fx[j], ( *( --win_ptr_fx ) ) ); // Qx + 15 - 15 = Qx
640 0 : move32();
641 : }
642 :
643 0 : FOR( Word16 i = 0; i < shl( mdft_len, 1 ); i++ )
644 : {
645 0 : fr_in_block_fx[i] = L_shr( fr_in_block_fx[i], gb ); // Qx - gb
646 0 : move32();
647 : }
648 :
649 0 : 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 );
650 : }
651 :
652 0 : return;
653 : }
654 :
655 : /*-----------------------------------------------------------------------------------------*
656 : * Function ivas_fb_mixer_cross_fading()
657 : *
658 : * FB Mixer cross fading
659 : *-----------------------------------------------------------------------------------------*/
660 :
661 0 : void ivas_fb_mixer_cross_fading_fx(
662 : IVAS_FB_MIXER_HANDLE hFbMixer,
663 : Word32 **ppOut_pcm_fx, // o: Qx
664 : Word32 *pMdft_out_old_fx, // i: Qx
665 : Word32 *pMdft_out_new_fx, // i: Qx
666 : const Word16 ch,
667 : const Word16 frame_len,
668 : const Word16 cf_offset )
669 : {
670 : Word16 k, fade_start_offset, fade_end_offset;
671 :
672 0 : IF( hFbMixer->first_frame[ch] == 0 )
673 : {
674 0 : fade_start_offset = hFbMixer->cross_fade_start_offset;
675 0 : fade_end_offset = hFbMixer->cross_fade_end_offset;
676 0 : move16();
677 0 : move16();
678 :
679 0 : FOR( k = 0; k < fade_start_offset; k++ )
680 : {
681 0 : ppOut_pcm_fx[ch][k] = pMdft_out_old_fx[k + cf_offset]; // Qx
682 0 : move32();
683 : }
684 :
685 0 : FOR( k = fade_start_offset; k < fade_end_offset; k++ )
686 : {
687 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
688 0 : move32();
689 : }
690 :
691 0 : FOR( k = fade_end_offset; k < frame_len; k++ )
692 : {
693 0 : ppOut_pcm_fx[ch][k] = pMdft_out_new_fx[k + cf_offset]; // Qx
694 0 : move32();
695 : }
696 : }
697 : ELSE
698 : {
699 0 : hFbMixer->first_frame[ch] = 0;
700 0 : move32();
701 :
702 0 : FOR( k = 0; k < frame_len; k++ )
703 : {
704 0 : ppOut_pcm_fx[ch][k] = pMdft_out_new_fx[k + cf_offset]; // Qx
705 0 : move32();
706 : }
707 : }
708 :
709 0 : return;
710 : }
711 :
712 : /*-----------------------------------------------------------------------------------------*
713 : * Function ivas_fb_mixer_process()
714 : *
715 : * Filter bank process
716 : *-----------------------------------------------------------------------------------------*/
717 0 : void ivas_cmult_fix(
718 : Word32 in1_re, // i: Qx
719 : Word32 in1_im, // i: Qx
720 : Word32 in2_re, // i: Qx
721 : Word32 in2_im, // i: Qx
722 : Word32 *out1_re, // o: 2 * Qx - 31
723 : Word32 *out1_im // o: 2 * Qx - 31
724 : )
725 : {
726 0 : *out1_re = L_sub_sat( Mpy_32_32( in1_re, in2_re ), Mpy_32_32( in1_im, in2_im ) );
727 0 : move32();
728 0 : *out1_im = L_add_sat( Mpy_32_32( in1_re, in2_im ), Mpy_32_32( in2_re, in1_im ) );
729 0 : move32();
730 0 : }
731 :
732 0 : void ivas_fb_mixer_process_fx(
733 : IVAS_FB_MIXER_HANDLE hFbMixer, /* i/o: FB mixer handle */
734 : Word32 ***mixer_mat_fx, /* i : mixer matrix */
735 : Word16 *q_mixer_mat_fx, /* i : mixer matrix Q-factor */
736 : Word32 **ppOut_pcm_fx, /* o : output audio channels */
737 : Word16 *q_ppOut_pcm_fx, /* o : output audio channels Q-factor */
738 : const Word16 frame_len, /* i : frame length in samples */
739 : Word16 in_out_mixer_map[IVAS_MAX_FB_MIXER_OUT_CH][IVAS_MAX_SPAR_FB_MIXER_IN_CH] /* i/o: mixing mapping */
740 : )
741 : {
742 0 : ivas_filterbank_t *pFb = hFbMixer->pFb;
743 0 : Word16 num_bands = pFb->filterbank_num_bands;
744 0 : move16();
745 : Word16 i, j, k, ch, hist;
746 :
747 : const Word32 *pFilterbank_bin_to_band_re_fx;
748 : const Word32 *pFilterbank_bin_to_band_im_fx;
749 : Word16 q_pMdft_out_fx[2];
750 : Word32 *pMdft_out_fx[2];
751 : Word32 *pOut_fr_re_fx, *pOut_fr_im_fx;
752 0 : Word16 q_pOut_fr_fx = 31;
753 0 : move16();
754 : Word32 Out_fr_re_fx[L_FRAME48k], Out_fr_im_fx[L_FRAME48k];
755 : Word32 Mdft_out_0_fx[L_FRAME48k * 2], Mdft_out_1_fx[L_FRAME48k * 2];
756 :
757 0 : pOut_fr_re_fx = Out_fr_re_fx;
758 0 : pOut_fr_im_fx = Out_fr_im_fx;
759 0 : pMdft_out_fx[0] = Mdft_out_0_fx;
760 0 : pMdft_out_fx[1] = Mdft_out_1_fx;
761 :
762 0 : FOR( ch = ( hFbMixer->fb_cfg->active_w_mixing == 0 ); ch < hFbMixer->fb_cfg->num_out_chans; ch++ )
763 : {
764 : /* Run a loop of 2 to calculate current frame's filterbank output and prev frame's output */
765 0 : FOR( hist = 0; hist < 2; hist++ )
766 : {
767 0 : set_zero_fx( pOut_fr_re_fx, frame_len );
768 0 : set_zero_fx( pOut_fr_im_fx, frame_len );
769 0 : q_pOut_fr_fx = 31;
770 0 : move16();
771 0 : FOR( j = 0; j < hFbMixer->fb_cfg->num_in_chans; j++ )
772 : {
773 0 : IF( in_out_mixer_map[ch][j] != 0 )
774 : {
775 :
776 : Word32 filterbank_mixer_bins_re_fx[L_FRAME48k];
777 : Word32 filterbank_mixer_bins_im_fx[L_FRAME48k];
778 0 : Word32 *pFb_inFR_re_fx = hFbMixer->ppFilterbank_inFR_re_fx[j]; // Q(hFbMixer->q_ppFilterbank_inFR_re_fx)
779 0 : Word32 *pFb_inFR_im_fx = hFbMixer->ppFilterbank_inFR_im_fx[j]; // Q(hFbMixer->q_ppFilterbank_inFR_im_fx)
780 :
781 0 : set_zero_fx( filterbank_mixer_bins_re_fx, frame_len );
782 0 : set_zero_fx( filterbank_mixer_bins_im_fx, frame_len );
783 :
784 0 : Word16 total_guard = find_guarded_bits_fx( num_bands );
785 0 : move16();
786 0 : FOR( i = 0; i < num_bands; i++ )
787 : {
788 0 : Word16 start_offset = pFb->fb_consts.pFilterbank_bins_start_offset[i];
789 0 : move16();
790 0 : Word16 num_bins = pFb->fb_consts.pFilterbank_bins_per_band[i];
791 0 : move16();
792 0 : Word32 mixer_const_fx = hFbMixer->prior_mixer_fx[ch][j][i]; // Q(hFbMixer->q_prior_mixer_fx)
793 0 : move32();
794 0 : pFilterbank_bin_to_band_re_fx = pFb->fb_consts.ppFilterbank_FRs_fx[0][i]; // Q30
795 0 : pFilterbank_bin_to_band_im_fx = pFb->fb_consts.ppFilterbank_FRs_fx[1][i]; // Q30
796 :
797 0 : FOR( k = start_offset; k < num_bins + start_offset; k++ )
798 : {
799 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
800 0 : move32();
801 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
802 0 : move32();
803 : /*filterbank_mixer_bins_im_fx q 30 */
804 : /*mixer_const_fx q q_ppOut_pcm_fx */
805 0 : pFilterbank_bin_to_band_re_fx++;
806 0 : pFilterbank_bin_to_band_im_fx++;
807 : }
808 0 : hFbMixer->prior_mixer_fx[ch][j][i] = mixer_mat_fx[ch][j][i]; // Q(q_mixer_mat_fx)
809 0 : move32();
810 : }
811 0 : Word16 res_q = 0;
812 0 : move16();
813 0 : FOR( k = 0; k < frame_len; k++ )
814 : {
815 : Word32 temp_out_re_fx, temp_out_im_fx;
816 :
817 0 : ivas_cmult_fix( filterbank_mixer_bins_re_fx[k], filterbank_mixer_bins_im_fx[k], pFb_inFR_re_fx[k],
818 0 : pFb_inFR_im_fx[k], &temp_out_re_fx, &temp_out_im_fx );
819 0 : res_q = sub( add( sub( sub( add( 30, *q_mixer_mat_fx ), 31 ), total_guard ), hFbMixer->q_ppFilterbank_inFR[j] ), 31 );
820 0 : Word16 q_check = s_min( q_pOut_fr_fx, res_q );
821 0 : IF( NE_16( q_check, q_pOut_fr_fx ) )
822 : {
823 0 : 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
824 0 : move32();
825 0 : 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
826 0 : move32();
827 : }
828 0 : IF( NE_16( q_check, res_q ) )
829 : {
830 0 : temp_out_re_fx = L_shr( temp_out_re_fx, sub( res_q, q_check ) ); // res_q -> q_check
831 0 : temp_out_im_fx = L_shr( temp_out_im_fx, sub( res_q, q_check ) ); // res_q -> q_check
832 : }
833 0 : res_q = q_check;
834 0 : move16();
835 0 : pOut_fr_re_fx[k] = L_add_sat( pOut_fr_re_fx[k], temp_out_re_fx ); // res_q
836 0 : move32();
837 0 : pOut_fr_im_fx[k] = L_add_sat( pOut_fr_im_fx[k], temp_out_im_fx ); // res_q
838 0 : move32();
839 : }
840 0 : q_pOut_fr_fx = res_q;
841 0 : move16();
842 : }
843 : }
844 0 : 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 ) ) );
845 0 : scale_sig32( pOut_fr_re_fx, frame_len, scale );
846 0 : scale_sig32( pOut_fr_im_fx, frame_len, scale );
847 0 : ivas_imdft_fx( pOut_fr_re_fx, pOut_fr_im_fx, pMdft_out_fx[hist], frame_len );
848 0 : q_pMdft_out_fx[hist] = add( q_pOut_fr_fx, scale );
849 0 : move16();
850 : }
851 0 : 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] ) );
852 0 : 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] ) );
853 0 : ivas_fb_mixer_cross_fading_fx( hFbMixer, ppOut_pcm_fx, pMdft_out_fx[0], pMdft_out_fx[1], ch, frame_len, frame_len );
854 0 : q_ppOut_pcm_fx[ch] = s_min( q_pMdft_out_fx[0], q_pMdft_out_fx[1] );
855 0 : move16();
856 : }
857 :
858 0 : return;
859 : }
860 :
861 : /*-----------------------------------------------------------------------------------------*
862 : * Function ivas_fb_mixer_get_in_out_mapping()
863 : *
864 : *
865 : *-----------------------------------------------------------------------------------------*/
866 0 : void ivas_fb_mixer_get_in_out_mapping_fx(
867 : const IVAS_FB_CFG *fb_cfg, /* i : FB config. handle */
868 : Word16 in_out_mixer_map[IVAS_MAX_FB_MIXER_OUT_CH][IVAS_MAX_SPAR_FB_MIXER_IN_CH] /* i/o: mixing mapping */
869 : )
870 : {
871 : Word16 i, j;
872 :
873 0 : set_s( (Word16 *) in_out_mixer_map, 0, IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH );
874 :
875 0 : IF( fb_cfg->active_w_mixing )
876 : {
877 0 : FOR( i = 0; i < fb_cfg->num_out_chans; i++ )
878 : {
879 0 : FOR( j = 0; j < fb_cfg->num_in_chans; j++ )
880 : {
881 0 : in_out_mixer_map[i][j] = 1;
882 0 : move16();
883 : }
884 : }
885 : }
886 : ELSE
887 : {
888 0 : in_out_mixer_map[0][0] = 1; /* W depends on only W input*/
889 0 : move16();
890 0 : FOR( i = 1; i < fb_cfg->num_out_chans; i++ )
891 : {
892 0 : in_out_mixer_map[i][0] = 1;
893 0 : move16();
894 : }
895 : }
896 :
897 0 : return;
898 : }
899 :
900 : /*-----------------------------------------------------------------------------------------*
901 : * Function ivas_calculate_abs_fr()
902 : *
903 : * Function to calculate number of active bands
904 : *-----------------------------------------------------------------------------------------*/
905 :
906 273 : static Word16 ivas_calculate_abs_fr_fx(
907 : ivas_filterbank_t *pFb,
908 : const Word32 sampling_rate,
909 : const Word16 alloc_fb_resp,
910 : Word16 *index )
911 : {
912 : Word16 frame_len;
913 : Word32 ppFilterbank_FRs_s_fx[L_FRAME48k];
914 273 : Word16 bands = pFb->filterbank_num_bands;
915 273 : move16();
916 273 : Word16 i, j, num_active_bands = 0;
917 273 : move16();
918 273 : Word16 idx_short_stride_bin_to_band = 0;
919 273 : move16();
920 : Word16 quo, tmp, exp_diff;
921 :
922 273 : Word32 temp = Mpy_32_32( sampling_rate, 42949673 /* FRAMES_PER_SEC in Q31 */ );
923 273 : frame_len = extract_l( temp );
924 :
925 3469 : FOR( i = 0; i < bands; i++ )
926 : {
927 3196 : const Word32 *long_mdft_ptr_re_fx = pFb->fb_consts.ppFilterbank_FRs_fx[0][i]; // Q30
928 3196 : const Word32 *long_mdft_ptr_im_fx = pFb->fb_consts.ppFilterbank_FRs_fx[1][i]; // Q30
929 :
930 3196 : Word16 start_offset = pFb->fb_consts.pFilterbank_bins_start_offset[i];
931 3196 : move16();
932 3196 : Word16 num_bins = pFb->fb_consts.pFilterbank_bins_per_band[i];
933 3196 : move16();
934 3196 : Word16 short_mdft_start_bin = -1;
935 3196 : move16();
936 :
937 : Word32 short_stride_pow_spec_fx[MDFT_FB_BANDS_240];
938 3196 : Word32 short_stride_nrg_fx = 0;
939 3196 : move16();
940 3196 : exp_diff = 0;
941 3196 : move16();
942 :
943 3196 : Word64 cldfb_nrg_fx = 0;
944 3196 : move64();
945 3196 : Word16 short_stride = pFb->fb_bin_to_band.short_stride;
946 3196 : move16();
947 : Word32 res_dec1, res_frac, res_dec2;
948 3196 : iDiv_and_mod_32( sampling_rate, FRAMES_PER_SEC, &res_dec1, &res_frac, 0 );
949 3196 : iDiv_and_mod_32( res_dec1, short_stride, &res_dec2, &res_frac, 0 );
950 3196 : const Word16 num_bins_per_short_stride_bin = extract_l( res_dec2 );
951 3196 : iDiv_and_mod_32( res_dec1, pFb->fb_bin_to_band.num_cldfb_bands, &res_dec2, &res_frac, 0 );
952 3196 : const Word16 num_bins_per_cldfb_band = extract_l( res_dec2 );
953 :
954 3196 : Word32 short_stride_max_per_spar_band_fx = 1;
955 3196 : move32();
956 :
957 : /*loop over all stored Filter Bank Response MDFT coefficients*/
958 :
959 3196 : set32_fx( short_stride_pow_spec_fx, 0, MDFT_FB_BANDS_240 );
960 :
961 966952 : FOR( j = start_offset; j < num_bins + start_offset; j++ )
962 : {
963 :
964 : Word32 sq_abs_fx;
965 :
966 : // Word32 real = L_shr( *long_mdft_ptr_re_fx, 3 ); // Q27
967 963756 : Word32 real = *long_mdft_ptr_re_fx; // Q30
968 963756 : move32();
969 : // Word32 imag = L_shr( *long_mdft_ptr_im_fx, 3 ); // Q27
970 963756 : Word32 imag = *long_mdft_ptr_im_fx; // Q30
971 963756 : move32();
972 963756 : Word64 acc = W_mac_32_32( W_mult_32_32( real, real ), imag, imag ); // Q61
973 963756 : sq_abs_fx = W_extract_h( acc ); // Q28
974 963756 : long_mdft_ptr_re_fx++;
975 963756 : long_mdft_ptr_im_fx++;
976 :
977 : /* accumulate bin energies within a short stride bin */
978 :
979 963756 : short_stride_nrg_fx = L_add( short_stride_nrg_fx, L_shr( sq_abs_fx, 6 ) ); // Q22
980 963756 : move32();
981 :
982 963756 : IF( !( add( j, 1 ) % num_bins_per_short_stride_bin ) )
983 : {
984 : /* new short stride bin */
985 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*/
986 240423 : move32();
987 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*/
988 240423 : short_stride_nrg_fx = 0;
989 240423 : move32();
990 : }
991 :
992 : /* accumulate bin energies within a CLDFB band */
993 963756 : cldfb_nrg_fx = W_mac_32_32( cldfb_nrg_fx, sq_abs_fx, 1 ); // Q29
994 :
995 963756 : IF( !( add( j, 1 ) % num_bins_per_cldfb_band ) )
996 : {
997 59627 : Word16 exp = W_norm( cldfb_nrg_fx );
998 59627 : cldfb_nrg_fx = W_shl( cldfb_nrg_fx, exp );
999 59627 : exp = sub( 34, exp ); // 31 - (Q29 + exp -32)
1000 59627 : temp = Sqrt32( W_extract_h( cldfb_nrg_fx ), &exp );
1001 59627 : temp = L_shl( temp, sub( exp, Q9 ) ); // Q22
1002 59627 : pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[j / num_bins_per_cldfb_band][i] = temp; // Q22
1003 59627 : move32();
1004 59627 : cldfb_nrg_fx = 0;
1005 59627 : move32();
1006 : }
1007 : }
1008 :
1009 3196 : quo = BASOP_Util_Divide3232_Scale( ONE_IN_Q30, short_stride_max_per_spar_band_fx, &exp_diff );
1010 : /* Q of quo = Q30 - Q22 + (15 - exp_diff) --> Q23 - exp_diff.
1011 : With Mult_32_16, Q23 - exp_diff - 15 --> Q8 - exp_diff */
1012 3196 : exp_diff = sub( Q8, exp_diff );
1013 :
1014 : /*loop over the short MDFT bins*/
1015 596796 : FOR( j = 0; j < short_stride; j++ )
1016 : {
1017 593600 : short_stride_pow_spec_fx[j] = L_shr( Mult_32_16( short_stride_pow_spec_fx[j], quo ), exp_diff ); // Q22
1018 593600 : move32();
1019 593600 : short_stride_pow_spec_fx[j] = L_max( L_sub( short_stride_pow_spec_fx[j], 1258291 ), 0 ); // 0.3f * ONE_IN_Q22
1020 593600 : move32();
1021 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
1022 593600 : move32();
1023 :
1024 :
1025 593600 : IF( short_stride_pow_spec_fx[j] > 0 )
1026 : {
1027 53792 : assert( idx_short_stride_bin_to_band < 2 * MDFT_FB_BANDS_240 ); /* array size of p_short_stride_bin_to_band */
1028 53792 : IF( EQ_16( short_mdft_start_bin, -1 ) )
1029 : {
1030 3196 : short_mdft_start_bin = j;
1031 3196 : move16();
1032 3196 : pFb->fb_bin_to_band.p_short_stride_start_bin_per_band[i] = j;
1033 3196 : move16();
1034 :
1035 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
1036 3196 : index[i] = idx_short_stride_bin_to_band;
1037 3196 : move16();
1038 : }
1039 :
1040 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
1041 53792 : move32();
1042 53792 : idx_short_stride_bin_to_band = add( idx_short_stride_bin_to_band, 1 );
1043 :
1044 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 );
1045 53792 : move16();
1046 : }
1047 : }
1048 : }
1049 :
1050 : /*loop over CLDFB bands*/
1051 12773 : FOR( j = 0; j < pFb->fb_bin_to_band.num_cldfb_bands; j++ )
1052 : {
1053 12500 : Word32 sum_over_spar_bands_fx = 0;
1054 12500 : move32();
1055 12500 : Word32 max_spar_band_contribution_fx = 0;
1056 12500 : move32();
1057 :
1058 12500 : Word16 spar_start = 0;
1059 12500 : move16();
1060 12500 : Word16 any_non_zero = 0;
1061 12500 : move16();
1062 :
1063 160900 : FOR( i = 0; i < bands; i++ )
1064 : {
1065 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
1066 148400 : move32();
1067 :
1068 148400 : IF( pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[j][i] > max_spar_band_contribution_fx )
1069 : {
1070 36923 : max_spar_band_contribution_fx = pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[j][i]; // Q22
1071 36923 : move32();
1072 36923 : pFb->fb_bin_to_band.p_cldfb_map_to_spar_band[j] = i;
1073 36923 : move16();
1074 : }
1075 : }
1076 :
1077 12500 : sum_over_spar_bands_fx = L_max( sum_over_spar_bands_fx, EPSILON_FX ); // Q22
1078 12500 : move32();
1079 :
1080 12500 : exp_diff = 0;
1081 12500 : move16();
1082 12500 : tmp = BASOP_Util_Divide3232_Scale( ONE_IN_Q30, sum_over_spar_bands_fx, &exp_diff );
1083 : /* Q of quo = Q30 - Q22 + (15 - exp_diff) --> Q23 - exp_diff.
1084 : With Mult_32_16, Q23 - exp_diff - 15 --> Q8 - exp_diff */
1085 12500 : exp_diff = sub( Q8, exp_diff );
1086 :
1087 160900 : FOR( i = 0; i < bands; i++ )
1088 : {
1089 148400 : test();
1090 148400 : IF( pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[j][i] == 0 && !any_non_zero )
1091 : {
1092 78900 : spar_start = add( spar_start, 1 );
1093 : }
1094 : ELSE
1095 : {
1096 69500 : any_non_zero = 1;
1097 69500 : move16();
1098 : }
1099 :
1100 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 );
1101 148400 : move32();
1102 : }
1103 12500 : pFb->fb_bin_to_band.p_spar_start_bands[j] = spar_start;
1104 12500 : move16();
1105 : }
1106 :
1107 273 : set32_fx( ppFilterbank_FRs_s_fx, 0, frame_len );
1108 :
1109 : /*Commented logic is for calculating number of active bands, can be removed if not needed */
1110 3469 : FOR( i = 0; i < bands; i++ )
1111 : {
1112 3196 : const Word32 *pFilterbank_bin_to_band_re_fx = pFb->fb_consts.ppFilterbank_FRs_fx[0][i]; // Q30
1113 3196 : move32();
1114 3196 : const Word32 *pFilterbank_bin_to_band_im_fx = pFb->fb_consts.ppFilterbank_FRs_fx[1][i]; // Q30
1115 3196 : move32();
1116 :
1117 3196 : Word16 start_offset = pFb->fb_consts.pFilterbank_bins_start_offset[i];
1118 3196 : move16();
1119 3196 : Word16 num_bins = pFb->fb_consts.pFilterbank_bins_per_band[i];
1120 3196 : move16();
1121 3196 : Word16 idx = 0;
1122 3196 : move16();
1123 3196 : Word16 abs_active_bins = pFb->fb_bin_to_band.pFb_active_bins_per_band[i];
1124 3196 : move16();
1125 3196 : Word16 abs_start_offset = pFb->fb_bin_to_band.pFb_start_bin_per_band[i];
1126 3196 : move16();
1127 :
1128 966952 : FOR( j = start_offset; j < num_bins + start_offset; j++ )
1129 : {
1130 963756 : Word32 temp_fx = 0;
1131 963756 : move32();
1132 :
1133 963756 : exp_diff = 0;
1134 963756 : move16();
1135 963756 : Word32 real = L_shr( *pFilterbank_bin_to_band_re_fx, 3 ); // Q27
1136 963756 : Word32 imag = L_shr( *pFilterbank_bin_to_band_im_fx, 3 ); // Q27
1137 :
1138 : Word32 real_sq, imag_sq;
1139 963756 : real_sq = Mpy_32_32( real, real ); // Q27 + Q27 - 31 = Q23
1140 963756 : imag_sq = Mpy_32_32( imag, imag ); // Q27 + Q27 - 31 = Q23
1141 :
1142 963756 : temp_fx = L_add( L_shr( real_sq, 1 ), L_shr( imag_sq, 1 ) ); // Q22
1143 :
1144 963756 : exp_diff = 9;
1145 963756 : move16();
1146 963756 : temp_fx = Sqrt32( temp_fx, &exp_diff );
1147 963756 : temp_fx = L_shl( temp_fx, sub( exp_diff, Q9 ) ); // Q22
1148 :
1149 :
1150 963756 : pFilterbank_bin_to_band_re_fx++;
1151 963756 : pFilterbank_bin_to_band_im_fx++;
1152 :
1153 963756 : temp_fx = L_sub( temp_fx, 1258291 ); // 0.3 in Q22
1154 963756 : move32();
1155 :
1156 963756 : if ( temp_fx < 0 )
1157 : {
1158 691682 : temp_fx = 0;
1159 691682 : move32();
1160 : }
1161 :
1162 963756 : test();
1163 963756 : test();
1164 963756 : IF( LT_16( j, add( abs_active_bins, abs_start_offset ) ) && GE_16( j, abs_start_offset ) && NE_16( alloc_fb_resp, -1 ) )
1165 : {
1166 0 : pFb->fb_bin_to_band.pFb_bin_to_band_fx[i][idx] = temp_fx; // Q22
1167 0 : move32();
1168 0 : idx = add( idx, 1 );
1169 : }
1170 :
1171 :
1172 963756 : ppFilterbank_FRs_s_fx[j] = L_add( ppFilterbank_FRs_s_fx[j], temp_fx ); // Q22
1173 963756 : move32();
1174 : }
1175 : }
1176 :
1177 200273 : FOR( i = 0; i < frame_len; i++ )
1178 : {
1179 200000 : if ( ppFilterbank_FRs_s_fx[i] < 0 )
1180 : {
1181 0 : ppFilterbank_FRs_s_fx[i] = 419430; // 0.1 in Q22
1182 0 : move32();
1183 : }
1184 : }
1185 :
1186 273 : IF( NE_16( alloc_fb_resp, -1 ) )
1187 : {
1188 0 : FOR( j = 0; j < bands; j++ )
1189 : {
1190 0 : Word16 abs_active_bins = pFb->fb_bin_to_band.pFb_active_bins_per_band[j];
1191 0 : Word16 abs_start_offset = pFb->fb_bin_to_band.pFb_start_bin_per_band[j];
1192 0 : exp_diff = 0;
1193 :
1194 0 : move16();
1195 0 : move16();
1196 0 : move16();
1197 :
1198 0 : FOR( i = 0; i < abs_active_bins; i++ )
1199 : {
1200 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 );
1201 0 : pFb->fb_bin_to_band.pFb_bin_to_band_fx[j][i] = L_shl( L_deposit_l( tmp ), add( Q7, exp_diff ) ); // Q22
1202 0 : move32();
1203 : /*if(pFb->fb_bin_to_band.pFb_bin_to_band[j][i] > 0.5f)
1204 : {
1205 : num_active_bands = j + 1;
1206 : break;
1207 : }*/
1208 : }
1209 : }
1210 : }
1211 :
1212 273 : return num_active_bands;
1213 : }
1214 :
1215 : /*-----------------------------------------------------------------------------------------*
1216 : * Function ivas_get_active_bins()
1217 : *
1218 : *
1219 : *-----------------------------------------------------------------------------------------*/
1220 :
1221 546 : static void ivas_get_active_bins_fx(
1222 : const Word16 **pActive_bins,
1223 : const Word16 **pActive_bins_abs,
1224 : const Word16 **pStart_offset,
1225 : const Word16 **pStart_offset_abs,
1226 : const Word32 sampling_rate )
1227 : {
1228 : Word16 sr_idx;
1229 :
1230 546 : IF( EQ_32( sampling_rate, 32000 ) )
1231 : {
1232 228 : sr_idx = 1;
1233 228 : move16();
1234 : }
1235 318 : ELSE IF( EQ_32( sampling_rate, 16000 ) )
1236 : {
1237 80 : sr_idx = 2;
1238 80 : move16();
1239 : }
1240 : ELSE
1241 : {
1242 238 : sr_idx = 0;
1243 238 : move16();
1244 : }
1245 :
1246 546 : *pActive_bins_abs = ivas_fb_abs_bins_per_band_12band_1ms[sr_idx];
1247 546 : move16();
1248 546 : *pActive_bins = ivas_fb_bins_per_band_12band_1ms[sr_idx];
1249 546 : move16();
1250 546 : *pStart_offset_abs = ivas_fb_abs_bins_start_offset_12band_1ms[sr_idx];
1251 546 : move16();
1252 546 : *pStart_offset = ivas_fb_bins_start_offset_12band_1ms[sr_idx];
1253 546 : move16();
1254 :
1255 546 : return;
1256 : }
1257 :
1258 :
1259 : /*-----------------------------------------------------------------------------------------*
1260 : * Function ivas_filterbank_setup()
1261 : *
1262 : * Filterbank setup, initialization
1263 : *-----------------------------------------------------------------------------------------*/
1264 :
1265 273 : static ivas_error ivas_filterbank_setup_fx(
1266 : IVAS_FB_MIXER_HANDLE hFbMixer,
1267 : const Word32 sampling_rate,
1268 : Word16 *index )
1269 : {
1270 : Word16 i, j, exp, tmp;
1271 : const Word32 *pAll_fb_fr_fx[2];
1272 273 : const Word16 *pAll_bins_start_offset = NULL;
1273 273 : const Word16 *pAll_bins_per_band = NULL;
1274 273 : const Word16 *pAll_bins_start_offset_abs = NULL;
1275 273 : const Word16 *pAll_bins_per_band_abs = NULL;
1276 273 : const Word16 *pAll_bins_per_band_48k = NULL;
1277 : ivas_error error;
1278 273 : IVAS_FB_CFG *pCfg = hFbMixer->fb_cfg;
1279 :
1280 273 : error = IVAS_ERR_OK;
1281 273 : move32();
1282 :
1283 273 : IF( pCfg->num_out_chans > 0 )
1284 : {
1285 273 : hFbMixer->pFb->filterbank_num_bands = ivas_get_num_bands( sampling_rate );
1286 273 : move16();
1287 :
1288 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 );
1289 :
1290 273 : IF( EQ_16( pCfg->fb_latency, NS2SA_FX2( sampling_rate, DELAY_FB_1_NS ) ) )
1291 : {
1292 273 : pAll_fb_fr_fx[0] = ivas_fb_fr_12band_1ms_re_fx; // Q30
1293 273 : move32();
1294 273 : pAll_fb_fr_fx[1] = ivas_fb_fr_12band_1ms_im_fx; // Q30
1295 273 : move32();
1296 :
1297 273 : pAll_bins_per_band_48k = ivas_fb_bins_per_band_12band_1ms[0];
1298 273 : move16();
1299 : }
1300 : ELSE
1301 : {
1302 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong FB in ivas_filterbank_setup()!" );
1303 : }
1304 : }
1305 :
1306 273 : hFbMixer->cross_fade_end_offset = add( pCfg->fade_len, pCfg->pcm_offset );
1307 273 : move16();
1308 273 : hFbMixer->cross_fade_start_offset = sub( hFbMixer->cross_fade_end_offset, pCfg->fade_len );
1309 273 : move16();
1310 273 : hFbMixer->ana_window_offset = add( pCfg->fb_latency, pCfg->pcm_offset );
1311 273 : move16();
1312 :
1313 273 : IF( NE_32( ( error = ivas_fb_mixer_get_window_fx( pCfg->fb_latency, sampling_rate, &( hFbMixer->pAna_window_fx ) ) ), IVAS_ERR_OK ) )
1314 : {
1315 0 : return error;
1316 : }
1317 :
1318 273 : IF( NE_32( ( error = ivas_fb_mixer_get_window_fx( pCfg->fade_len, sampling_rate, &( hFbMixer->pFilterbank_cross_fade_fx ) ) ), IVAS_ERR_OK ) )
1319 : {
1320 0 : return error;
1321 : }
1322 :
1323 273 : IF( pCfg->num_out_chans > 0 )
1324 : {
1325 273 : ivas_filterbank_t *pFb = hFbMixer->pFb;
1326 273 : Word16 offset = 0;
1327 273 : move16();
1328 :
1329 273 : pFb->fb_consts.pFilterbank_bins_per_band = pAll_bins_per_band;
1330 273 : pFb->fb_consts.pFilterbank_bins_start_offset = pAll_bins_start_offset;
1331 273 : pFb->fb_bin_to_band.pFb_active_bins_per_band = pAll_bins_per_band_abs;
1332 273 : pFb->fb_bin_to_band.pFb_start_bin_per_band = pAll_bins_start_offset_abs;
1333 :
1334 : /* Initialization for short stride Parameter calculation and SPAR CLDFB reconstruction */
1335 273 : SWITCH( sampling_rate )
1336 : {
1337 119 : case 48000:
1338 119 : pFb->fb_bin_to_band.num_cldfb_bands = 60; /* sampling_rate * 1.0f / 800.0f */
1339 119 : move16();
1340 119 : BREAK;
1341 114 : case 32000:
1342 114 : pFb->fb_bin_to_band.num_cldfb_bands = 40;
1343 114 : move16();
1344 114 : BREAK;
1345 40 : case 16000:
1346 40 : pFb->fb_bin_to_band.num_cldfb_bands = 20;
1347 40 : move16();
1348 40 : BREAK;
1349 : }
1350 :
1351 : /*pFb->fb_bin_to_band.cldfb_stride = ( int16_t )( ( sampling_rate / FRAMES_PER_SEC ) / CLDFB_NO_COL_MAX );*/ /* equals num_cldfb_bands*/
1352 : // pFb->fb_bin_to_band.short_stride = extract_l( ( sampling_rate / FRAMES_PER_SEC ) / 4 );
1353 273 : tmp = BASOP_Util_Divide3232_Scale( sampling_rate, FRAMES_PER_SEC, &exp );
1354 273 : pFb->fb_bin_to_band.short_stride = shr( tmp, add( sub( 15, exp ), 2 ) );
1355 :
1356 273 : move16();
1357 :
1358 273 : set32_fx( pFb->fb_bin_to_band.p_short_stride_bin_to_band_fx, 0, 2 * MDFT_FB_BANDS_240 );
1359 :
1360 273 : set16_fx( pFb->fb_bin_to_band.p_cldfb_map_to_spar_band, 0, CLDFB_NO_CHANNELS_MAX );
1361 273 : set16_fx( pFb->fb_bin_to_band.p_spar_start_bands, 0, CLDFB_NO_CHANNELS_MAX );
1362 :
1363 5733 : FOR( j = 0; j < IVAS_MAX_NUM_FB_BANDS; j++ )
1364 : {
1365 5460 : pFb->fb_bin_to_band.p_short_stride_num_bins_per_band[j] = 0; /* aka num_active_bins per SPAR band */
1366 5460 : move16();
1367 5460 : pFb->fb_bin_to_band.p_short_stride_start_bin_per_band[j] = 0; /* first considered bin index per SPAR band */
1368 5460 : move16();
1369 :
1370 5460 : pFb->fb_bin_to_band.pp_short_stride_bin_to_band_fx[j] = NULL;
1371 :
1372 333060 : FOR( i = 0; i < CLDFB_NO_CHANNELS_MAX; i++ )
1373 : {
1374 :
1375 327600 : pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[i][j] = 0;
1376 327600 : move32();
1377 : }
1378 : }
1379 273 : IF( EQ_32( sampling_rate, 48000 ) )
1380 : {
1381 1547 : FOR( j = 0; j < pFb->filterbank_num_bands; j++ )
1382 : {
1383 :
1384 1428 : pFb->fb_consts.ppFilterbank_FRs_fx[0][j] = &pAll_fb_fr_fx[0][offset]; // Q30
1385 1428 : pFb->fb_consts.ppFilterbank_FRs_fx[1][j] = &pAll_fb_fr_fx[1][offset]; // Q30
1386 :
1387 1428 : offset = add( offset, pFb->fb_consts.pFilterbank_bins_per_band[j] );
1388 : }
1389 :
1390 : /****************************************Calculate abs fr ***************************/
1391 :
1392 119 : ivas_calculate_abs_fr_fx( pFb, sampling_rate, pCfg->active_w_mixing, index );
1393 : }
1394 : ELSE
1395 : {
1396 :
1397 : Word32 *ppFilterbank_FRs_re_temp_fx[MAX_NUM_BANDS_DIFF_NON48K];
1398 : Word32 *ppFilterbank_FRs_im_temp_fx[MAX_NUM_BANDS_DIFF_NON48K];
1399 : Word16 active_bins_temp[MAX_NUM_BANDS_DIFF_NON48K];
1400 : Word16 start_offset_temp[MAX_NUM_BANDS_DIFF_NON48K];
1401 : Word16 num_diff_bands, start_diff_band_non48k;
1402 :
1403 154 : num_diff_bands = MAX_NUM_BANDS_DIFF_NON48K;
1404 154 : start_diff_band_non48k = sub( pFb->filterbank_num_bands, num_diff_bands );
1405 154 : move16();
1406 :
1407 154 : pFb->fb_consts.pFilterbank_bins_per_band = pAll_bins_per_band;
1408 154 : pFb->fb_consts.pFilterbank_bins_start_offset = pAll_bins_start_offset;
1409 :
1410 1922 : FOR( j = 0; j < pFb->filterbank_num_bands; j++ )
1411 : {
1412 1768 : Word16 num_active_bins = pFb->fb_consts.pFilterbank_bins_per_band[j];
1413 1768 : move16();
1414 :
1415 1768 : IF( j < start_diff_band_non48k )
1416 : {
1417 :
1418 1306 : pFb->fb_consts.ppFilterbank_FRs_fx[0][j] = &pAll_fb_fr_fx[0][offset]; // Q30
1419 1306 : pFb->fb_consts.ppFilterbank_FRs_fx[1][j] = &pAll_fb_fr_fx[1][offset]; // Q30
1420 : }
1421 : ELSE
1422 : {
1423 462 : Copy32( &pAll_fb_fr_fx[0][offset], pFb->fb_consts.ppFilterbank_FRs_non48k_fx[0][j], num_active_bins ); // Q30
1424 462 : Copy32( &pAll_fb_fr_fx[1][offset], pFb->fb_consts.ppFilterbank_FRs_non48k_fx[1][j], num_active_bins ); // Q30
1425 : }
1426 :
1427 1768 : offset = add( offset, pAll_bins_per_band_48k[j] );
1428 : }
1429 :
1430 616 : FOR( j = start_diff_band_non48k; j < pFb->filterbank_num_bands; j++ )
1431 : {
1432 :
1433 462 : ppFilterbank_FRs_re_temp_fx[j - start_diff_band_non48k] = pFb->fb_consts.ppFilterbank_FRs_non48k_fx[0][j]; // Q30
1434 462 : ppFilterbank_FRs_im_temp_fx[j - start_diff_band_non48k] = pFb->fb_consts.ppFilterbank_FRs_non48k_fx[1][j]; // Q30
1435 :
1436 462 : active_bins_temp[j - start_diff_band_non48k] = pFb->fb_consts.pFilterbank_bins_per_band[j];
1437 462 : start_offset_temp[j - start_diff_band_non48k] = pFb->fb_consts.pFilterbank_bins_start_offset[j];
1438 462 : move16();
1439 462 : move16();
1440 : }
1441 :
1442 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,
1443 154 : active_bins_temp, start_offset_temp, num_diff_bands, pCfg->fb_latency, sampling_rate );
1444 :
1445 :
1446 616 : FOR( j = start_diff_band_non48k; j < pFb->filterbank_num_bands; j++ )
1447 : {
1448 :
1449 462 : pFb->fb_consts.ppFilterbank_FRs_fx[0][j] = (const Word32 *) pFb->fb_consts.ppFilterbank_FRs_non48k_fx[0][j]; // Q30
1450 462 : pFb->fb_consts.ppFilterbank_FRs_fx[1][j] = (const Word32 *) pFb->fb_consts.ppFilterbank_FRs_non48k_fx[1][j]; // Q30
1451 : }
1452 :
1453 : /******************************************** Calculate abs fr ****************************************************/
1454 :
1455 154 : ivas_calculate_abs_fr_fx( pFb, sampling_rate, pCfg->active_w_mixing, index );
1456 : }
1457 : }
1458 :
1459 273 : return error;
1460 : }
1461 :
1462 : /*-----------------------------------------------------------------------------------------*
1463 : * Function ivas_fb_mixer_get_window()
1464 : *
1465 : *
1466 : *-----------------------------------------------------------------------------------------*/
1467 :
1468 546 : static ivas_error ivas_fb_mixer_get_window_fx(
1469 : const Word16 fade_len, /* i : window fading length in samples */
1470 : const Word32 sampling_rate, /* i : sampling rate */
1471 : const Word16 **pWindow /* o : pointer to the window coefficents */
1472 : )
1473 : {
1474 : ivas_error error;
1475 :
1476 546 : error = IVAS_ERR_OK;
1477 546 : move32();
1478 :
1479 546 : IF( EQ_16( fade_len, NS2SA_FX2( sampling_rate, DELAY_FB_4_NS ) ) )
1480 : {
1481 273 : SWITCH( sampling_rate )
1482 : {
1483 119 : case 48000:
1484 119 : *pWindow = ivas_fb_cf_4ms_48k_fx;
1485 119 : BREAK;
1486 114 : case 32000:
1487 114 : *pWindow = ivas_fb_cf_4ms_32k_fx;
1488 114 : BREAK;
1489 40 : case 16000:
1490 40 : *pWindow = ivas_fb_cf_4ms_16k_fx;
1491 40 : BREAK;
1492 0 : default:
1493 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unsupported Sampling frequency!" );
1494 : }
1495 : }
1496 273 : ELSE IF( EQ_16( fade_len, NS2SA_FX2( sampling_rate, DELAY_FB_1_NS ) ) )
1497 : {
1498 273 : SWITCH( sampling_rate )
1499 : {
1500 119 : case 48000:
1501 119 : *pWindow = ivas_fb_cf_1ms_48k_fx;
1502 119 : BREAK;
1503 114 : case 32000:
1504 114 : *pWindow = ivas_fb_cf_1ms_32k_fx;
1505 114 : BREAK;
1506 40 : case 16000:
1507 40 : *pWindow = ivas_fb_cf_1ms_16k_fx;
1508 40 : BREAK;
1509 0 : default:
1510 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unsupported Sampling frequency!" );
1511 : }
1512 : }
1513 : ELSE
1514 : {
1515 0 : IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Incorrect FB window fade len (%f ms)\n", ( fade_len / 1000000.f ) );
1516 : }
1517 :
1518 546 : return error;
1519 : }
1520 :
1521 :
1522 154 : static const Word32 *ivas_get_cheby_ramp_fx(
1523 : const Word16 delay )
1524 : {
1525 154 : const Word32 *pCheby_fx = NULL;
1526 :
1527 154 : SWITCH( delay )
1528 : {
1529 114 : case IVAS_FB_1MS_32K_SAMP:
1530 114 : pCheby_fx = ivas_fb_resp_cheby_ramp_32del_fx;
1531 114 : BREAK;
1532 40 : case IVAS_FB_1MS_16K_SAMP:
1533 40 : pCheby_fx = ivas_fb_resp_cheby_ramp_16del_fx;
1534 40 : BREAK;
1535 0 : default:
1536 0 : assert( !"Unsupported cheby ramp length!" );
1537 : }
1538 :
1539 154 : return pCheby_fx;
1540 : }
1541 :
1542 154 : static void ivas_get_ld_fb_resp_fx(
1543 : Word32 **ppIdeal_FRs_re_fx, // i: Q30
1544 : Word32 **ppIdeal_FRs_im_fx, // i: Q30
1545 : Word32 **ppNew_FRs_re_fx, // o: Q30
1546 : Word32 **ppNew_FRs_im_fx, // o: Q30
1547 : const Word16 *pActive_bins,
1548 : const Word16 *pStart_offset,
1549 : const Word16 num_bands,
1550 : const Word16 delay,
1551 : const Word32 sampling_rate )
1552 : {
1553 : Word16 b, s, frame_len;
1554 : const Word32 *pCheby_fx;
1555 154 : frame_len = 0;
1556 154 : move16();
1557 : /*common scratch buffers for computing impulse/frequency responses,
1558 : pre-ring, post-ring and circular shifted outputs to optimize stack*/
1559 : Word32 scratch1_fx[L_FRAME32k * 2];
1560 : Word32 scratch2_fx[L_FRAME32k * 2];
1561 :
1562 154 : set32_fx( scratch1_fx, 0, L_FRAME32k * 2 );
1563 154 : set32_fx( scratch2_fx, 0, L_FRAME32k * 2 );
1564 :
1565 154 : const Word32 *han_win_fx = NULL;
1566 :
1567 154 : SWITCH( sampling_rate )
1568 : {
1569 0 : case 48000:
1570 0 : frame_len = 960;
1571 0 : move16();
1572 0 : han_win_fx = ivas_han_win_48k_fx; // Q31
1573 0 : BREAK;
1574 114 : case 32000:
1575 114 : frame_len = 640;
1576 114 : move16();
1577 114 : han_win_fx = ivas_han_win_32k_fx; // Q31
1578 114 : BREAK;
1579 40 : case 16000:
1580 40 : frame_len = 320;
1581 40 : move16();
1582 40 : han_win_fx = ivas_han_win_16k_fx; // Q31
1583 40 : BREAK;
1584 : }
1585 :
1586 154 : pCheby_fx = ivas_get_cheby_ramp_fx( delay ); // Q31
1587 :
1588 154 : b = 0;
1589 154 : s = 0;
1590 154 : move16();
1591 154 : move16();
1592 :
1593 154 : assert( sampling_rate == 32000 || sampling_rate == 16000 );
1594 :
1595 616 : FOR( b = 0; b < num_bands; b++ )
1596 : {
1597 :
1598 462 : set32_fx( scratch2_fx, 0, shl( frame_len, 1 ) );
1599 462 : Copy32( ppIdeal_FRs_re_fx[b], &scratch2_fx[pStart_offset[b]], pActive_bins[b] ); // Q30
1600 462 : Copy32( ppIdeal_FRs_im_fx[b], &scratch2_fx[frame_len + pStart_offset[b]], pActive_bins[b] ); // Q30
1601 :
1602 462 : Word16 guard_bits = sub( L_norm_arr( scratch2_fx, shl( L_FRAME32k, 1 ) ), find_guarded_bits_fx( shl( frame_len, 1 ) ) );
1603 462 : Scale_sig32( scratch2_fx, shl( L_FRAME32k, 1 ), guard_bits ); // Q30 + guard_bits
1604 :
1605 462 : ivas_imdft_fx( scratch2_fx, &scratch2_fx[frame_len], scratch1_fx, frame_len );
1606 :
1607 591822 : FOR( Word16 x = 0; x < shl( L_FRAME32k, 1 ); x++ )
1608 : {
1609 591360 : scratch2_fx[x] = L_shr( scratch2_fx[x], guard_bits ); // (Q30 + guard_bits) - guard_bits = Q30
1610 591360 : scratch1_fx[x] = L_shr( scratch1_fx[x], guard_bits ); // (Q30 + guard_bits) - guard_bits = Q30
1611 :
1612 591360 : move32();
1613 591360 : move32();
1614 : }
1615 :
1616 : /*apply circular shift and hanning window*/
1617 :
1618 257742 : FOR( s = delay; s < frame_len + delay; s++ )
1619 : {
1620 :
1621 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
1622 257280 : move32();
1623 : }
1624 :
1625 244878 : FOR( ; s < 2 * frame_len; s++ )
1626 : {
1627 :
1628 244416 : scratch2_fx[s - delay] = Mpy_32_32( scratch1_fx[s], han_win_fx[s - ( frame_len + delay )] ); // Q30
1629 244416 : move32();
1630 : }
1631 :
1632 13326 : FOR( s = 0; s < delay; s++ )
1633 : {
1634 :
1635 12864 : scratch2_fx[( ( ( frame_len * 2 ) - delay ) + s )] = L_negate( Mpy_32_32( scratch1_fx[s], han_win_fx[( frame_len - delay ) + s] ) ); // Q30
1636 12864 : move32();
1637 : }
1638 :
1639 : /*apply heavy/cheby ramp window and compute pre ring*/
1640 :
1641 13788 : FOR( s = 0; s < delay + 1; s++ )
1642 : {
1643 13326 : scratch1_fx[s] = Mpy_32_32( scratch2_fx[s], pCheby_fx[delay - s] ); // Q30
1644 13326 : move32();
1645 : }
1646 :
1647 244416 : FOR( ; s < frame_len; s++ )
1648 : {
1649 243954 : scratch1_fx[s] = 0;
1650 243954 : move32();
1651 : }
1652 :
1653 244878 : FOR( ; s < 2 * frame_len - delay; s++ )
1654 : {
1655 244416 : scratch1_fx[s] = scratch2_fx[s];
1656 244416 : move32();
1657 : }
1658 :
1659 13326 : FOR( ; s < 2 * frame_len; s++ )
1660 : {
1661 12864 : scratch1_fx[s] = Mpy_32_32( scratch2_fx[s], L_sub( ONE_IN_Q31, pCheby_fx[s - ( 2 * frame_len - delay )] ) ); // Q30
1662 12864 : move32();
1663 : }
1664 :
1665 : /*IR - pre ring + post ring*/
1666 514560 : FOR( s = 1; s < 2 * frame_len; s++ )
1667 : {
1668 514098 : scratch2_fx[s] = L_sub( L_sub( scratch2_fx[s] /*pre ring*/, scratch1_fx[s] /*post ring*/ ), scratch1_fx[frame_len * 2 - s] );
1669 514098 : move32();
1670 : }
1671 :
1672 502158 : FOR( s = 0; s < 2 * frame_len - delay; s++ )
1673 : {
1674 501696 : scratch1_fx[s + delay] = scratch2_fx[s];
1675 501696 : move32();
1676 : }
1677 :
1678 13326 : FOR( ; s < 2 * frame_len; s++ )
1679 : {
1680 12864 : scratch1_fx[( s - ( ( frame_len * 2 ) - delay ) )] = L_negate( scratch2_fx[s] );
1681 12864 : move32();
1682 : }
1683 :
1684 : /* apply final window*/
1685 462 : const Word32 *sine_till_delay = ivas_sine_delay_32_fx; // Q30
1686 462 : Word16 offset = 1;
1687 462 : Word16 delay_16 = 0;
1688 :
1689 462 : move16();
1690 462 : move16();
1691 :
1692 462 : if ( EQ_16( delay, IVAS_FB_1MS_16K_SAMP ) )
1693 : {
1694 120 : delay_16 = 1;
1695 120 : move16();
1696 : }
1697 :
1698 13326 : FOR( s = 0; s < delay; s++ )
1699 : {
1700 12864 : scratch1_fx[s] = Mpy_32_32( scratch1_fx[s], sine_till_delay[s + offset * delay_16] ); // Q30 + Q30 - 31 = Q29
1701 12864 : offset = add( offset, 1 );
1702 12864 : scratch1_fx[s] = L_shl( scratch1_fx[s], 1 ); // Q30
1703 :
1704 12864 : move32();
1705 12864 : move32();
1706 : }
1707 :
1708 462 : const Word32 *sine_till_frame_len = NULL;
1709 :
1710 462 : IF( EQ_16( delay, IVAS_FB_1MS_16K_SAMP ) )
1711 : {
1712 120 : sine_till_frame_len = ivas_sine_frame_len_640_del_16_fx; // Q30
1713 120 : move32();
1714 : }
1715 : ELSE
1716 : {
1717 342 : sine_till_frame_len = ivas_sine_frame_len_640_del_32_fx; // Q30
1718 342 : move32();
1719 : }
1720 462 : Word16 iterator = 0;
1721 462 : move16();
1722 232476 : FOR( s = 2 * delay; s < frame_len + 1; s++ )
1723 : {
1724 232014 : scratch1_fx[s] = Mpy_32_32( scratch1_fx[s], sine_till_frame_len[iterator] ); // Q30 + Q30 - 31 = Q29
1725 232014 : iterator = add( iterator, 1 );
1726 232014 : scratch1_fx[s] = L_shl( scratch1_fx[s], 1 ); // Q30
1727 :
1728 232014 : move32();
1729 232014 : move32();
1730 : }
1731 :
1732 257280 : FOR( ; s < 2 * frame_len; s++ )
1733 : {
1734 256818 : scratch1_fx[s] = 0;
1735 :
1736 256818 : move32();
1737 : }
1738 :
1739 : /*compute frequency response*/
1740 462 : ivas_mdft_fx( scratch1_fx, scratch2_fx, &scratch2_fx[frame_len], shl( frame_len, 1 ), frame_len );
1741 :
1742 462 : Copy32( &scratch2_fx[pStart_offset[b]], ppNew_FRs_re_fx[b], pActive_bins[b] ); // Q30
1743 462 : Copy32( &scratch2_fx[( frame_len + pStart_offset[b] )], ppNew_FRs_im_fx[b], pActive_bins[b] ); // Q30
1744 : }
1745 :
1746 154 : return;
1747 : }
|