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