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