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 <assert.h>
34 : #include <stdint.h>
35 : #include "options.h"
36 : #include <math.h>
37 : #include "cnst.h"
38 : #include "prot_fx.h"
39 : #include "ivas_cnst.h"
40 : #include "ivas_rom_com.h"
41 : #include "ivas_rom_dec.h"
42 : #include "rom_com.h"
43 : #include "wmc_auto.h"
44 : #include "ivas_prot_fx.h"
45 :
46 :
47 : /*-------------------------------------------------------------------------
48 : * stereo_dft_dmx_out_reset()
49 : *
50 : * Reset DFT stereo mono output memories
51 : *------------------------------------------------------------------------*/
52 :
53 565 : void stereo_dft_dmx_out_reset_fx(
54 : STEREO_DFT_DMX_DATA_HANDLE hStereoDftDmx /* i/o: DFT stereo DMX decoder */
55 : )
56 : {
57 565 : hStereoDftDmx->targetGain_fx = ONE_IN_Q29; /* Q29 */
58 565 : move32();
59 565 : hStereoDftDmx->prevTargetGain_fx = ONE_IN_Q29; /* Q29 */
60 565 : move32();
61 :
62 565 : set32_fx( hStereoDftDmx->memOutHB_fx, 0, NS2SA( 48000, STEREO_DFT32MS_OVL_NS ) );
63 565 : set32_fx( hStereoDftDmx->memTransitionHB_fx, 0, NS2SA( 48000, STEREO_DFT32MS_OVL_NS ) );
64 :
65 565 : return;
66 : }
67 :
68 :
69 : /*-------------------------------------------------------------------------
70 : * stereo_dft_unify_dmx()
71 : *
72 : * create a uniform dmx in case of residual coding by converting from passive
73 : * to active dmx in residual coding region
74 : *-------------------------------------------------------------------------*/
75 :
76 5345 : void stereo_dft_unify_dmx_fx(
77 : STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder stereo handle */
78 : Decoder_State *st0, /* i/o: decoder state structure */
79 : Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers hStereoDft->qDFT*/
80 : Word32 *input_mem, /* i/o: mem of buffer DFT analysis Q11*/
81 : const Word16 prev_sid_nodata /* i : Previous SID/No data indicator Q0*/
82 : )
83 : {
84 : Word16 i, k, b, N_div;
85 : Word32 DFT_L[STEREO_DFT32MS_N_MAX];
86 : Word32 DFT_R[STEREO_DFT32MS_N_MAX];
87 : Word32 *pDFT_DMX;
88 : Word32 *pDFT_RES;
89 : Word32 tmp;
90 : Word32 *pSideGain;
91 : Word16 k_offset, g;
92 :
93 : /* Variables for stereo residual PLC */
94 : Word32 DFT_PRED_RES[STEREO_DFT32MS_N_32k];
95 : Word16 samp_ratio, q_samp_ratio;
96 : Word16 prev_bfi;
97 : Word32 dmx_nrg;
98 : Word32 *pPredGain;
99 : Word16 stop;
100 : Word16 output_frame;
101 : Word16 plocs[STEREO_DFT_RES_N_PEAKS_MAX];
102 : Word16 num_plocs;
103 : Word32 plocsi[STEREO_DFT_RES_N_PEAKS_MAX];
104 :
105 5345 : set32_fx( DFT_PRED_RES, 0, STEREO_DFT32MS_N_32k );
106 :
107 5345 : output_frame = extract_l( Mult_32_16( st0->output_Fs, INV_FRAME_PER_SEC_Q15 ) ); /* Q0 */
108 5345 : samp_ratio = BASOP_Util_Divide3232_Scale( st0->sr_core, st0->output_Fs, &q_samp_ratio );
109 5345 : samp_ratio = shr( samp_ratio, sub( Q15 - Q12, q_samp_ratio ) );
110 :
111 5345 : prev_bfi = st0->prev_old_bfi; /* Q0 */
112 5345 : move32();
113 :
114 : /* Initialization */
115 5345 : k_offset = 1;
116 5345 : move16();
117 5345 : N_div = STEREO_DFT_NBDIV;
118 5345 : move16();
119 :
120 5345 : dmx_nrg = 0;
121 5345 : move32();
122 : /* make sure number of bands corresponds to output bwidth in case it is lower than parameter bwidth */
123 5345 : IF( LT_16( output_frame, inner_frame_tbl[st0->bwidth] ) )
124 : {
125 1231 : hStereoDft->nbands = stereo_dft_band_config_fx( hStereoDft->band_limits, hStereoDft->band_res[k_offset], hStereoDft->NFFT, DEC );
126 1231 : move16();
127 : }
128 5345 : IF( prev_bfi )
129 : {
130 136 : dmx_nrg = stereo_dft_dmx_swb_nrg_fx( DFT[0], DFT[0] + STEREO_DFT32MS_N_MAX, s_min( hStereoDft->NFFT, STEREO_DFT32MS_N_32k ), 0, 0 );
131 : }
132 :
133 : /* Analyze nature of current frame */
134 5345 : test();
135 5345 : test();
136 5345 : test();
137 5345 : test();
138 5345 : test();
139 5345 : test();
140 5345 : test();
141 5345 : test();
142 10263 : hStereoDft->trans = (Word16) ( ( EQ_16( st0->clas_dec, ONSET ) || EQ_16( st0->clas_dec, SIN_ONSET ) || EQ_16( st0->clas_dec, UNVOICED_CLAS ) || EQ_16( st0->clas_dec, UNVOICED_TRANSITION ) ) || LE_16( st0->stab_fac_fx, (Word16) 0x2000 ) ) ||
143 4918 : ( ( EQ_16( st0->core, TCX_20_CORE ) && ( EQ_16( st0->hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP ) || EQ_16( st0->hTcxCfg->tcx_last_overlap_mode, HALF_OVERLAP ) ) ) || EQ_16( st0->core, TCX_10_CORE ) ); /* Q0 */
144 5345 : move16();
145 :
146 : /* Smoothing for the current frame */
147 5345 : stereo_dft_dec_smooth_parameters_fx( hStereoDft, prev_sid_nodata, st0->hFdCngDec->hFdCngCom->active_frame_counter, st0->element_brate );
148 :
149 16035 : FOR( k = 0; k < N_div; k++ )
150 : {
151 10690 : pDFT_DMX = DFT[0] + i_mult( k, STEREO_DFT32MS_N_MAX ); /* qDFT */
152 10690 : pDFT_RES = DFT[1] + i_mult( k, STEREO_DFT32MS_N_MAX ); /* qDFT */
153 :
154 10690 : assert( hStereoDft->hConfig->dmx_active );
155 : /*Apply Stereo*/
156 10690 : g = MAX_16;
157 10690 : move16();
158 : /* since delay is just 3.125ms, the parameters received are used for the second window */
159 10690 : pSideGain = hStereoDft->side_gain_fx + i_mult( add( k, k_offset ), STEREO_DFT_BAND_MAX ); /* Q31 */
160 :
161 : /* Stereo residual PLC */
162 10690 : IF( hStereoDft->res_cod_band_max > 0 )
163 : {
164 10690 : IF( !st0->bfi )
165 : {
166 10418 : IF( EQ_16( k, 1 ) )
167 : {
168 5209 : Copy32( pDFT_RES, hStereoDft->res_mem_fx, shl( hStereoDft->band_limits[hStereoDft->res_cod_band_max], 1 ) ); /* qDFT */
169 5209 : hStereoDft->q_res_mem = hStereoDft->q_dft;
170 5209 : move16();
171 5209 : hStereoDft->time_offs = 0;
172 5209 : move16();
173 : }
174 : }
175 : ELSE
176 : {
177 272 : hStereoDft->nbands = hStereoDft->res_cod_band_max; /* Limit nbands since residual PLC only needs the low frequency range of the stereo filling */
178 272 : move16();
179 272 : pPredGain = hStereoDft->res_pred_gain_fx + i_mult( add( k, k_offset ), STEREO_DFT_BAND_MAX ); /* Q31 */
180 272 : hStereoDft->past_DMX_pos = ( sub( add( hStereoDft->past_DMX_pos, STEREO_DFT_PAST_MAX ), 1 ) ) % STEREO_DFT_PAST_MAX;
181 272 : move16();
182 272 : stereo_dft_generate_res_pred_fx( hStereoDft, samp_ratio, pDFT_DMX, DFT_PRED_RES, pPredGain, k, DFT[1] + k * STEREO_DFT32MS_N_MAX, &stop, st0->bfi );
183 272 : stereo_dft_res_ecu_fx( hStereoDft, pDFT_RES, DFT_PRED_RES, k, output_frame, prev_bfi, dmx_nrg, &num_plocs, plocs, plocsi, input_mem );
184 272 : hStereoDft->q_res_cod_mem_fx = hStereoDft->q_dft;
185 272 : move16();
186 : }
187 : }
188 :
189 :
190 : /* Apply active DMX */
191 10690 : DFT_L[0] = pDFT_DMX[0]; /* qDFT */
192 10690 : move32();
193 10690 : DFT_R[0] = pDFT_DMX[0];
194 10690 : move32();
195 :
196 : /* upmix residual part */
197 64140 : FOR( b = 0; b < hStereoDft->res_cod_band_max; b++ )
198 : {
199 53450 : g = extract_h( pSideGain[b] ); /* Q15 */
200 53450 : move16();
201 :
202 267250 : FOR( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ )
203 : {
204 213800 : tmp = Madd_32_16( pDFT_RES[2 * i], pDFT_DMX[2 * i], g ); /* qDFT */
205 :
206 213800 : DFT_L[2 * i] = L_add( pDFT_DMX[2 * i], tmp ); /* qDFT */
207 213800 : move32();
208 213800 : DFT_R[2 * i] = L_sub( pDFT_DMX[2 * i], tmp ); /* qDFT */
209 213800 : move32();
210 :
211 213800 : tmp = Madd_32_16( pDFT_RES[2 * i + 1], pDFT_DMX[2 * i + 1], g );
212 :
213 213800 : DFT_L[2 * i + 1] = L_add( pDFT_DMX[2 * i + 1], tmp ); /* qDFT */
214 213800 : move32();
215 213800 : DFT_R[2 * i + 1] = L_sub( pDFT_DMX[2 * i + 1], tmp ); /* qDFT */
216 213800 : move32();
217 : }
218 : }
219 :
220 : /* downmix residual part with active downmix */
221 64140 : FOR( b = 0; b < hStereoDft->res_cod_band_max; b++ )
222 : {
223 : Word16 j;
224 : Word32 sum_nrg_Mid, sum_abs, dot_prod_abs;
225 : Word16 wR, wL;
226 53450 : Word16 norm_sum_nrg_L = 63, norm_sum_nrg_R = 63, norm_dot_prod_real = 63, norm_dot_prod_imag = 63, guard_bit = 2 /*find_guarded_bits_fx( 4 )*/, min_norm, q_sum_nrg_L, q_sum_nrg_R, q_dot_prod_real;
227 53450 : move16();
228 53450 : move16();
229 53450 : move16();
230 53450 : move16();
231 53450 : move16();
232 : Word16 exp_sum_nrg_l, exp_sum_nrg_R, exp_dot_prod_abs, exp_sum_nrg_Mid;
233 : Word32 sum_nrg_L_32, sum_nrg_R_32, dot_prod_real_32, dot_prod_img_32;
234 53450 : Word64 sum_nrg_L = 0, sum_nrg_R = 0;
235 53450 : move64();
236 53450 : move64();
237 53450 : Word64 dot_prod_real = 0, dot_prod_img = 0;
238 53450 : move64();
239 53450 : move64();
240 :
241 267250 : FOR( j = hStereoDft->band_limits[b]; j < hStereoDft->band_limits[b + 1]; j++ )
242 : {
243 213800 : sum_nrg_L = W_add( sum_nrg_L, W_add( W_mult_32_32( DFT_L[2 * j], DFT_L[2 * j] ), W_mult_32_32( DFT_L[2 * j + 1], DFT_L[2 * j + 1] ) ) ); /* 2 * q_dft + 1 */
244 213800 : sum_nrg_R = W_add( sum_nrg_R, W_add( W_mult_32_32( DFT_R[2 * j], DFT_R[2 * j] ), W_mult_32_32( DFT_R[2 * j + 1], DFT_R[2 * j + 1] ) ) ); /* 2 * q_dft + 1 */
245 :
246 213800 : dot_prod_real = W_add( dot_prod_real, W_add( W_mult_32_32( DFT_L[2 * j], DFT_R[2 * j] ), W_mult_32_32( DFT_L[2 * j + 1], DFT_R[2 * j + 1] ) ) ); /* 2 * q_dft + 1 */
247 213800 : dot_prod_img = W_add( dot_prod_img, W_sub( W_mult_32_32( DFT_L[2 * j + 1], DFT_R[2 * j] ), W_mult_32_32( DFT_L[2 * j], DFT_R[2 * j + 1] ) ) ); /* 2 * q_dft + 1 */
248 : }
249 :
250 53450 : IF( sum_nrg_L != 0 )
251 : {
252 53450 : norm_sum_nrg_L = W_norm( sum_nrg_L );
253 : }
254 53450 : IF( sum_nrg_R != 0 )
255 : {
256 53450 : norm_sum_nrg_R = W_norm( sum_nrg_R );
257 : }
258 53450 : IF( dot_prod_real != 0 )
259 : {
260 53450 : norm_dot_prod_real = W_norm( dot_prod_real );
261 : }
262 53450 : IF( dot_prod_img != 0 )
263 : {
264 52905 : norm_dot_prod_imag = W_norm( dot_prod_img );
265 : }
266 :
267 53450 : guard_bit = find_guarded_bits_fx( 4 );
268 53450 : min_norm = s_min( s_min( s_min( norm_sum_nrg_L, norm_sum_nrg_R ), norm_dot_prod_real ), norm_dot_prod_imag ) - guard_bit;
269 53450 : sum_nrg_L_32 = W_extract_h( W_shl( sum_nrg_L, min_norm ) );
270 53450 : sum_nrg_R_32 = W_extract_h( W_shl( sum_nrg_R, min_norm ) );
271 53450 : dot_prod_real_32 = W_extract_h( W_shl( dot_prod_real, min_norm ) );
272 53450 : dot_prod_img_32 = W_extract_h( W_shl( dot_prod_img, min_norm ) );
273 :
274 53450 : q_sum_nrg_L = sub( add( shl( hStereoDft->q_dft, 1 ), min_norm ), 31 );
275 53450 : q_sum_nrg_R = sub( add( shl( hStereoDft->q_dft, 1 ), min_norm ), 31 );
276 53450 : q_dot_prod_real = sub( add( shl( hStereoDft->q_dft, 1 ), min_norm ), 31 );
277 :
278 53450 : exp_sum_nrg_l = sub( 31, q_sum_nrg_L );
279 53450 : exp_sum_nrg_R = sub( 31, q_sum_nrg_R );
280 53450 : exp_dot_prod_abs = sub( 31, sub( shl( q_dot_prod_real, 1 ), 31 ) );
281 53450 : exp_sum_nrg_Mid = sub( 31, q_sum_nrg_L );
282 :
283 53450 : sum_nrg_Mid = L_max( 0, L_add( L_add( sum_nrg_L_32, sum_nrg_R_32 ), L_shl( dot_prod_real_32, 1 ) ) ); /* q_sum_nrg_L */
284 :
285 53450 : Word32 tmp_nrg_L = Sqrt32( sum_nrg_L_32, &exp_sum_nrg_l );
286 53450 : Word32 tmp_nrg_R = Sqrt32( sum_nrg_R_32, &exp_sum_nrg_R );
287 53450 : Word16 exp_sum_abs = exp_sum_nrg_l;
288 53450 : move16();
289 :
290 53450 : if ( GT_16( exp_sum_nrg_R, exp_sum_nrg_l ) )
291 : {
292 22697 : exp_sum_abs = exp_sum_nrg_R;
293 22697 : move16();
294 : }
295 53450 : exp_sum_abs = add( exp_sum_abs, 1 );
296 53450 : sum_abs = L_add( L_shr( tmp_nrg_L, sub( exp_sum_abs, exp_sum_nrg_l ) ), L_shr( tmp_nrg_R, sub( exp_sum_abs, exp_sum_nrg_R ) ) );
297 53450 : dot_prod_abs = Sqrt32( L_add( Mpy_32_32( dot_prod_real_32, dot_prod_real_32 ), Mpy_32_32( dot_prod_img_32, dot_prod_img_32 ) ), &exp_dot_prod_abs );
298 53450 : Word32 num = L_add( L_shr( L_add( sum_nrg_L_32, sum_nrg_R_32 ), 1 ), L_shr( dot_prod_abs, sub( sub( 31, exp_dot_prod_abs ), q_sum_nrg_L ) ) ); /* q_sum_nrg_L */
299 53450 : Word16 E_num = sub( 31, q_sum_nrg_L );
300 53450 : Word32 num_sqrt = Sqrt32( num, &E_num );
301 53450 : Word16 exp_wR = exp_sum_abs;
302 53450 : move16();
303 :
304 53450 : if ( LT_16( exp_sum_abs, E_num ) )
305 : {
306 0 : exp_wR = E_num;
307 0 : move16();
308 : }
309 : Word16 wR_temp;
310 53450 : test();
311 53450 : test();
312 53450 : IF( num_sqrt == 0 && sum_abs == 0 )
313 : {
314 0 : wR_temp = 6364; // 0.776887059 in Q13
315 0 : move16();
316 : }
317 53450 : ELSE IF( num_sqrt == 0 && sum_abs != 0 )
318 : {
319 0 : wR_temp = 5793; // 0.707106769 in Q13
320 0 : move16();
321 : }
322 : ELSE
323 : {
324 53450 : wR_temp = shr( divide3232( L_shr( num_sqrt, sub( exp_wR, E_num ) ), L_shr( sum_abs, sub( exp_wR, exp_sum_abs ) ) ), 2 ); /* Q13 */
325 : }
326 :
327 53450 : Word32 sum_nrg_Mid_sqrt = Sqrt32( sum_nrg_Mid, &exp_sum_nrg_Mid );
328 :
329 53450 : Word16 exp_wL = exp_sum_abs;
330 53450 : move16();
331 53450 : if ( LT_16( exp_sum_abs, exp_sum_nrg_Mid ) )
332 : {
333 0 : exp_wL = exp_sum_nrg_Mid;
334 0 : move16();
335 : }
336 : Word16 wL_temp;
337 53450 : test();
338 53450 : test();
339 53450 : IF( sum_nrg_Mid_sqrt == 0 && sum_abs == 0 )
340 : {
341 0 : wL_temp = 6364; /* Q13 */
342 0 : move16();
343 : }
344 53450 : ELSE IF( sum_nrg_Mid_sqrt == 0 && sum_abs != 0 )
345 : {
346 0 : wL_temp = 5793; /* Q13 */
347 0 : move16();
348 : }
349 : ELSE
350 : {
351 53450 : wL_temp = shr( divide3232( L_shr( sum_nrg_Mid_sqrt, sub( exp_wL, exp_sum_nrg_Mid ) ), L_shr( sum_abs, sub( exp_wL, exp_sum_abs ) ) ), 1 );
352 : }
353 :
354 53450 : wR = wR_temp; /* Q13 */
355 53450 : move16();
356 53450 : wL = add( wR, mult( 23170 /*sqrt(2.0f in Q14)*/, sub( 16384 /* 1.0f in Q14 */, wL_temp ) ) ); /* Q13 */
357 :
358 267250 : FOR( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ )
359 : {
360 : /*DMX Mapping*/
361 213800 : pDFT_DMX[2 * i] = L_shl( Mpy_32_32( L_add( Mpy_32_16_1( DFT_L[2 * i], wL ), Mpy_32_16_1( DFT_R[2 * i], wR ) ), INV_SQRT_2_Q31 ), Q2 ); /* Q(hStereoDft->q_dft) */
362 213800 : move32();
363 213800 : pDFT_DMX[2 * i + 1] = L_shl( Mpy_32_32( L_add( Mpy_32_16_1( DFT_L[2 * i + 1], wL ), Mpy_32_16_1( DFT_R[2 * i + 1], wR ) ), INV_SQRT_2_Q31 ), Q2 ); /* Q(hStereoDft->q_dft) */
364 213800 : move32();
365 : }
366 : }
367 10690 : Copy32( pDFT_DMX, DFT[0] + i_mult( k, STEREO_DFT32MS_N_MAX ), hStereoDft->NFFT ); /* hStereoDft->q_dft */
368 :
369 : /* Update DFT_past_DMX, needed for stereo filling used by stereo residual PLC */
370 10690 : hStereoDft->past_DMX_pos = ( hStereoDft->past_DMX_pos + 1 ) % STEREO_DFT_PAST_MAX; /* Q0 */
371 10690 : move16();
372 10690 : Copy32( pDFT_DMX, hStereoDft->DFT_past_DMX_fx[hStereoDft->past_DMX_pos], s_min( hStereoDft->NFFT, STEREO_DFT32MS_N_32k ) ); /* hStereoDft->q_dft */
373 10690 : hStereoDft->q_DFT_past_DMX_fx[hStereoDft->past_DMX_pos] = hStereoDft->q_dft;
374 10690 : move16();
375 10690 : test();
376 10690 : IF( st0->bfi && !prev_bfi )
377 : {
378 : Word16 idx_k0, idx_k1;
379 : Word16 q_shift0;
380 : Word16 q_shift1;
381 272 : idx_k0 = ( add( hStereoDft->past_DMX_pos, 1 ) ) % STEREO_DFT_PAST_MAX;
382 272 : move16();
383 272 : idx_k1 = ( add( idx_k0, 1 ) ) % STEREO_DFT_PAST_MAX;
384 272 : move16();
385 272 : q_shift0 = sub( hStereoDft->q_dft, hStereoDft->q_DFT_past_DMX_fx[idx_k0] );
386 272 : q_shift1 = sub( hStereoDft->q_dft, hStereoDft->q_DFT_past_DMX_fx[idx_k1] );
387 :
388 : /*dmx energy memory*/
389 272 : hStereoDft->past_dmx_nrg_fx = stereo_dft_dmx_swb_nrg_fx( hStereoDft->DFT_past_DMX_fx[idx_k0], hStereoDft->DFT_past_DMX_fx[idx_k1], s_min( hStereoDft->NFFT, STEREO_DFT32MS_N_32k ), q_shift0, q_shift1 ); /* 2 * q_dft */
390 272 : move32();
391 : }
392 : }
393 :
394 5345 : return;
395 : }
396 :
397 :
398 : /*-------------------------------------------------------------------*
399 : * add_HB_to_mono_dmx()
400 : *
401 : * add ACELP HB for DFT Stereo mono output with residual coding
402 : *-------------------------------------------------------------------*/
403 :
404 17465 : void add_HB_to_mono_dmx_fx(
405 : CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
406 : Word32 output[L_FRAME48k], /* i/o: output synthesis Qx*/
407 : Word32 outputHB[L_FRAME48k], /* i : HB synthesis Q11*/
408 : const Word16 last_core, /* i : last core, primary channel Q0*/
409 : const Word16 output_frame /* i : frame length Q0*/
410 : )
411 : {
412 : Word16 i, j, decoderDelay, icbweOLASize, dftOvlLen, memOffset;
413 : Word32 temp_fx[L_FRAME48k + NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS )];
414 :
415 17465 : Word32 winSlope_fx = 0;
416 17465 : move32();
417 : Word32 alpha_fx;
418 : const Word16 *win_dft_fx;
419 : Word32 output_Fs;
420 : Word32 *memOutHB_fx, *memTransitionHB_fx;
421 :
422 17465 : output_Fs = hCPE->hCoreCoder[0]->output_Fs; /* Q0 */
423 17465 : move32();
424 17465 : memOutHB_fx = hCPE->hStereoDftDmx->memOutHB_fx; /* Q11 */
425 17465 : memTransitionHB_fx = hCPE->hStereoDftDmx->memTransitionHB_fx; /* Q11 */
426 :
427 17465 : memOffset = NS2SA_FX2( output_Fs, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS );
428 17465 : move16();
429 :
430 17465 : test();
431 17465 : IF( hCPE->hCoreCoder[0]->core == ACELP_CORE && hCPE->hCoreCoder[0]->extl_brate > 0 )
432 : {
433 : /* Resampled LB and HB offset */
434 10963 : Copy32( outputHB, temp_fx + memOffset, sub( output_frame, memOffset ) );
435 :
436 10963 : decoderDelay = NS2SA_FX2( output_Fs, IVAS_DEC_DELAY_NS );
437 10963 : move16();
438 :
439 10963 : IF( last_core != ACELP_CORE )
440 : {
441 : /* hb_synth of mid band is faded out in the 1.25 ms prior to DFT analysis and the icbwe is faded in time domain */
442 711 : icbweOLASize = NS2SA_FX2( output_Fs, STEREO_DFT_DELAY_DEC_BWE_NS );
443 711 : move16();
444 :
445 95403 : FOR( i = 0; i < decoderDelay; i++ )
446 : {
447 94692 : temp_fx[i] = 0;
448 94692 : move32();
449 : }
450 :
451 711 : assert( icbweOLASize > 0 );
452 711 : SWITCH( output_Fs )
453 : {
454 469 : case 48000:
455 469 : winSlope_fx = 17895698; // Q30
456 469 : move32();
457 469 : BREAK;
458 172 : case 32000:
459 172 : winSlope_fx = 26843546;
460 172 : move32();
461 172 : BREAK;
462 70 : case 16000:
463 70 : winSlope_fx = 53687092;
464 70 : move32();
465 70 : BREAK;
466 : }
467 711 : alpha_fx = winSlope_fx; // Q30
468 711 : move32();
469 37131 : FOR( ; i < decoderDelay + icbweOLASize; i++ )
470 : {
471 36420 : temp_fx[i] = L_shl( Mpy_32_32( temp_fx[i], alpha_fx ), 1 ); // Q30
472 36420 : move32();
473 36420 : alpha_fx = L_add_sat( alpha_fx, winSlope_fx ); /* Q30 */
474 : }
475 : }
476 : ELSE
477 : {
478 10252 : Copy32( memOutHB_fx, temp_fx, memOffset ); /* Q11 */
479 : }
480 :
481 10963 : v_add_32( temp_fx, output, output, output_frame );
482 :
483 10963 : Copy32( outputHB + sub( output_frame, memOffset ), memOutHB_fx, memOffset ); /* Q11 */
484 :
485 10963 : win_dft_fx = hCPE->hStereoDft->win32ms_fx; /* Q15 */
486 10963 : dftOvlLen = hCPE->hStereoDft->dft32ms_ovl; /* Q0 */
487 10963 : move16();
488 :
489 : /* Preparing buffers in anticipation of an ACELP to TCX switch */
490 10963 : j = 0;
491 10963 : move16();
492 410443 : FOR( i = 0; i < memOffset; i++ )
493 : {
494 399480 : memTransitionHB_fx[i] = Mpy_32_16_1( memOutHB_fx[i], win_dft_fx[STEREO_DFT32MS_STEP * ( dftOvlLen - 1 - j )] ); /* Q11 */
495 399480 : move32();
496 399480 : j++;
497 : }
498 :
499 943083 : FOR( i = 0; j < dftOvlLen; i++ )
500 : {
501 932120 : memTransitionHB_fx[memOffset + i] = Mpy_32_16_1( outputHB[output_frame - i - 1], win_dft_fx[STEREO_DFT32MS_STEP * ( dftOvlLen - 1 - j )] ); /* Q11 */
502 932120 : move32();
503 932120 : j++;
504 : }
505 : }
506 : ELSE
507 : {
508 6502 : IF( last_core == ACELP_CORE )
509 : {
510 2458 : test();
511 2458 : test();
512 : /* This is generated in the ACELP frame and windowed. This process is akin to GenTransition for IC-BWE */
513 2458 : IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) && EQ_16( hCPE->nchan_out, 1 ) && hCPE->hStereoDft->hConfig->res_cod_mode == STEREO_DFT_RES_COD_OFF )
514 : {
515 1014 : v_add_32( output, outputHB, output, NS2SA_FX2( output_Fs, STEREO_DFT32MS_OVL_NS ) );
516 : }
517 : ELSE
518 : {
519 1444 : v_add_32( output, memTransitionHB_fx, output, NS2SA_FX2( output_Fs, STEREO_DFT32MS_OVL_NS ) );
520 : }
521 :
522 2458 : set32_fx( memOutHB_fx, 0, memOffset );
523 2458 : set32_fx( memTransitionHB_fx, 0, NS2SA_FX2( output_Fs, STEREO_DFT32MS_OVL_NS ) );
524 : }
525 : }
526 :
527 17465 : return;
528 : }
|