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 <math.h>
35 : #include <assert.h>
36 : #include "options.h"
37 : #include "ivas_prot_fx.h"
38 : #include "prot_fx.h"
39 : #include "cnst.h"
40 : #include "ivas_cnst.h"
41 : #include "ivas_rom_com.h"
42 : #include "wmc_auto.h"
43 :
44 : /*-------------------------------------------------------------------------
45 : * Local function definitions
46 : *------------------------------------------------------------------------*/
47 :
48 20720 : static void ivas_param_ism_compute_obj_parameters_fx(
49 : const Word16 nchan_ism, /* i : number of ISM channels */
50 : Word64 reference_power_obj[MAX_NUM_OBJECTS][PARAM_ISM_MDFT_NO_SLOTS][DIRAC_NO_FB_BANDS_MAX], /* i : Reference power Qx */
51 : PARAM_ISM_CONFIG_HANDLE hParamIsm /* i/o: Param ISM Enc Handle */
52 : )
53 : {
54 : Word16 i, b, m, br, mr;
55 : Word16 brange_start, brange_end, mrange_start, mrange_end, time_merge_fac;
56 : Word16 power_ratios_m[MAX_PARAM_ISM_NBANDS][MAX_PARAM_ISM_NBLOCKS];
57 : Word64 ref_power_local_frame[MAX_NUM_OBJECTS];
58 : Word64 tmp_ratio;
59 : Word16 e_tmp, tmp1, tmp2;
60 : Word64 Wtmp;
61 :
62 20720 : set64_fx( ref_power_local_frame, 0, MAX_NUM_OBJECTS );
63 :
64 20720 : assert( nchan_ism == 3 || nchan_ism == 4 );
65 :
66 248640 : FOR( b = 0; b < hParamIsm->nbands; b++ )
67 : {
68 : /* current frequency band borders */
69 227920 : brange_start = hParamIsm->band_grouping[b];
70 227920 : brange_end = hParamIsm->band_grouping[b + 1];
71 227920 : move16();
72 227920 : move16();
73 :
74 : /* time slots to aggregate for current block */
75 227920 : time_merge_fac = idiv1616( PARAM_ISM_MDFT_NO_SLOTS, hParamIsm->nblocks[b] );
76 :
77 455840 : FOR( m = 0; m < hParamIsm->nblocks[b]; m++ )
78 : {
79 : Word16 index_1, index_2;
80 : Word64 ref_power_local[MAX_NUM_OBJECTS];
81 :
82 : /* initialize to 0 so unused entries are not considered later */
83 227920 : set64_fx( ref_power_local, 0, MAX_NUM_OBJECTS );
84 :
85 : /* current block borders */
86 227920 : mrange_start = i_mult( m, time_merge_fac );
87 227920 : mrange_end = i_mult( add( m, 1 ), time_merge_fac );
88 :
89 : /* for each object, sum up reference power within current T/F tile */
90 :
91 1065350 : FOR( i = 0; i < nchan_ism; i++ )
92 : {
93 4187150 : FOR( mr = mrange_start; mr < mrange_end; mr++ )
94 : {
95 76130000 : FOR( br = brange_start; br < brange_end; br++ )
96 : {
97 72780280 : ref_power_local[i] = W_add( ref_power_local[i], reference_power_obj[i][mr][br] ); // Qx
98 72780280 : move64();
99 : }
100 : }
101 : /* Sum up T/F tiles per object */
102 837430 : ref_power_local_frame[i] = W_add( ref_power_local[i], ref_power_local_frame[i] ); // Qx
103 837430 : move64();
104 : }
105 :
106 : /* find two dominant objects and derive object indices for current T/F tile */
107 227920 : IF( GE_64( ref_power_local[0], ref_power_local[1] ) )
108 : {
109 108008 : index_1 = 0;
110 108008 : index_2 = 1;
111 108008 : move16();
112 108008 : move16();
113 : }
114 : ELSE
115 : {
116 119912 : index_1 = 1;
117 119912 : index_2 = 0;
118 119912 : move16();
119 119912 : move16();
120 : }
121 :
122 609510 : FOR( i = MAX_PARAM_ISM_WAVE; i < nchan_ism; i++ )
123 : {
124 381590 : IF( GT_64( ref_power_local[i], ref_power_local[index_1] ) )
125 : {
126 71885 : index_2 = index_1;
127 71885 : index_1 = i;
128 71885 : move16();
129 71885 : move16();
130 : }
131 309705 : ELSE IF( GT_64( ref_power_local[i], ref_power_local[index_2] ) )
132 : {
133 107924 : index_2 = i;
134 107924 : move16();
135 : }
136 : }
137 :
138 : /* Copy the quantized indices */
139 227920 : hParamIsm->obj_indices[b][m][0] = index_1;
140 227920 : hParamIsm->obj_indices[b][m][1] = index_2;
141 227920 : move16();
142 227920 : move16();
143 :
144 : /* Compute power ratios */
145 227920 : IF( W_add( ref_power_local[index_1], ref_power_local[index_2] ) == 0 )
146 : {
147 0 : power_ratios_m[b][m] = ONE_IN_Q14 /* 0.5 in Q15 */;
148 0 : move16();
149 : }
150 : ELSE
151 : {
152 227920 : tmp1 = W_norm( ref_power_local[index_1] );
153 227920 : Wtmp = W_add( ref_power_local[index_1], ref_power_local[index_2] );
154 227920 : tmp2 = W_norm( Wtmp );
155 227920 : power_ratios_m[b][m] = BASOP_Util_Divide3232_Scale( W_extract_h( W_shl( ref_power_local[index_1], tmp1 ) ), W_extract_h( W_shl( Wtmp, tmp2 ) ), &e_tmp ); // ((Qx + tmp1) - 16) - ((Qx + tmp2) - 16) + 15 - e_tmp = 15 + tmp1 - tmp2 - e_tmp
156 227920 : power_ratios_m[b][m] = shl_sat( power_ratios_m[b][m], sub( e_tmp, sub( tmp1, tmp2 ) ) ); // Q15
157 227920 : move16();
158 227920 : move16();
159 : }
160 227920 : assert( ( power_ratios_m[b][m] >= ONE_IN_Q14 /* 0.5 in Q15 */ ) && ( power_ratios_m[b][m] <= MAX_16 /* 1 in Q15 */ ) );
161 :
162 : /* Quantize power ratios */
163 : /* Power ratio range [0.5,1] is mapped to [0,1] first, rounding via truncation float->integer */
164 227920 : hParamIsm->power_ratios_idx[b][m] = extract_h( L_add( L_mult( shl( sub( power_ratios_m[b][m], ONE_IN_Q14 /* 0.5 in Q15 */ ), 1 ), ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ) ), ONE_IN_Q15 /* 0.5f in Q16 */ ) ); // Q0
165 227920 : move16();
166 227920 : assert( ( hParamIsm->power_ratios_idx[b][m] >= 0 ) && ( hParamIsm->power_ratios_idx[b][m] <= ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ) ) );
167 : }
168 : }
169 :
170 : /* Check if objects have roughly equal power by comparing reference power of first object against all others*/
171 20720 : hParamIsm->flag_equal_energy = 1;
172 20720 : move16();
173 20917 : FOR( i = 1; i < nchan_ism; i++ )
174 : {
175 20916 : IF( ref_power_local_frame[i] != 0 )
176 : {
177 20916 : tmp1 = W_norm( ref_power_local_frame[0] );
178 20916 : tmp2 = W_norm( ref_power_local_frame[i] );
179 20916 : tmp_ratio = BASOP_Util_Divide3232_Scale( W_extract_h( W_shl( ref_power_local_frame[0], tmp1 ) ), W_extract_h( W_shl( ref_power_local_frame[i], tmp2 ) ), &e_tmp ); // ((Qx + tmp1) - 16) - ((Qx + tmp2) - 16) + 15 - e_tmp = 15 + tmp1 - tmp2 - e_tmp
180 20916 : tmp_ratio = W_shl( tmp_ratio, sub( sub( e_tmp, 1 ), sub( tmp1, tmp2 ) ) ); // Q14 // Q14
181 :
182 20916 : test();
183 20916 : IF( GT_64( tmp_ratio, 15974 /* 0.975f in Q14 */ ) && LT_64( tmp_ratio, 16794 /* 1.025f in Q14*/ ) )
184 : {
185 197 : hParamIsm->flag_equal_energy = s_and( hParamIsm->flag_equal_energy, 1 );
186 197 : move16();
187 : }
188 : ELSE
189 : {
190 20719 : hParamIsm->flag_equal_energy = s_and( hParamIsm->flag_equal_energy, 0 );
191 20719 : move16();
192 20719 : break;
193 : }
194 : }
195 : }
196 :
197 20720 : return;
198 : }
199 :
200 :
201 20720 : static void ivas_param_ism_enc_quantize_DOA_fx(
202 : const Word16 nchan_ism, /* i : number of ISM channels */
203 : ISM_METADATA_HANDLE hIsmMetaData[MAX_NUM_OBJECTS], /* i : ISM metadata */
204 : PARAM_ISM_CONFIG_HANDLE hParamIsm /* i/o: Param ISM encoder handle */
205 : )
206 : {
207 : Word16 i, azi_idx, ele_idx;
208 : Word32 valQ_fx;
209 :
210 : /* Loop over objects */
211 96850 : FOR( i = 0; i < nchan_ism; i++ )
212 : {
213 : /* Quantize the elevation and obtain quantized elevation value and index */
214 76130 : ele_idx = ism_quant_meta_fx( hIsmMetaData[i]->elevation_fx, &valQ_fx, ism_elevation_borders_fx, ISM_Q_STEP_FX, ISM_Q_STEP_BORDER_FX, 1 << ISM_ELEVATION_NBITS );
215 :
216 : /* Obtain the index of quantized azimuth values */
217 76130 : azi_idx = ism_quant_meta_fx( hIsmMetaData[i]->azimuth_fx, &valQ_fx, ism_azimuth_borders_fx, ISM_Q_STEP_FX, ISM_Q_STEP_BORDER_FX, 1 << ISM_AZIMUTH_NBITS );
218 :
219 : /*Replace azimuth with quantized values */
220 76130 : hIsmMetaData[i]->azimuth_fx = valQ_fx; // Q22
221 76130 : move32();
222 :
223 : /* Copy the quantized indices */
224 76130 : hParamIsm->azi_index[i] = azi_idx;
225 76130 : move16();
226 76130 : hParamIsm->ele_index[i] = ele_idx;
227 76130 : move16();
228 : }
229 :
230 20720 : return;
231 : }
232 :
233 :
234 : /*-------------------------------------------------------------------------*
235 : * ivas_param_ism_stereo_dmx()
236 : *
237 : * Downmix input channels to stereo
238 : *-------------------------------------------------------------------------*/
239 20720 : void ivas_param_ism_stereo_dmx_fx(
240 : Encoder_Struct *st_ivas, /* i : IVAS encoder structure */
241 : Word32 *data[MAX_NUM_OBJECTS], /* i/o: input signal/stereo dmx Qx */
242 : const Word16 input_frame /* i : Length of input frame */
243 : )
244 : {
245 : Word16 i, j;
246 : Word32 tmp;
247 : Word16 alpha, azi_shift;
248 : Word16 tmp_1, tmp_2, one_by_input_frame;
249 : Word16 cardioid_left[MAX_NUM_OBJECTS], cardioid_right[MAX_NUM_OBJECTS]; // Q14
250 : Word32 stereo_dmx[2][L_FRAME48k];
251 : Word16 dmx_gain, dmx_gain_e;
252 : Word64 ene_data, ene_dmx;
253 : Word16 grad;
254 : Word16 last_dmx_gain, last_dmx_gain_e;
255 : Word16 last_cardioid_left; // Q14
256 : ISM_METADATA_HANDLE hIsmMetaData;
257 :
258 20720 : push_wmops( "ivas_param_ism_st_dmx" );
259 :
260 : /*Initialization*/
261 20720 : alpha = ONE_IN_Q14 /* 0.5 in Q15 */;
262 20720 : move16();
263 20720 : azi_shift = 0; // Q13
264 20720 : move16();
265 20720 : dmx_gain = 0;
266 20720 : move16();
267 20720 : ene_dmx = 0;
268 20720 : move64();
269 20720 : ene_data = 0;
270 20720 : move64();
271 20720 : last_dmx_gain = st_ivas->hParamIsm->last_dmx_gain_fx;
272 20720 : move16();
273 20720 : last_dmx_gain_e = st_ivas->hParamIsm->last_dmx_gain_e;
274 20720 : move16();
275 :
276 : /* Set the stereo dmx to zero */
277 20720 : set_zero_fx( stereo_dmx[0], L_FRAME48k );
278 20720 : set_zero_fx( stereo_dmx[1], L_FRAME48k );
279 :
280 20720 : one_by_input_frame = BASOP_Util_Divide1616_Scale( 1, input_frame, &tmp_1 );
281 20720 : one_by_input_frame = shl( one_by_input_frame, tmp_1 ); // Q15
282 :
283 : /* Loop over all objects */
284 96850 : FOR( i = 0; i < st_ivas->hEncoderConfig->nchan_ism; i++ )
285 : {
286 76130 : hIsmMetaData = st_ivas->hIsmMetaData[i];
287 76130 : last_cardioid_left = st_ivas->hParamIsm->last_cardioid_left_fx[i];
288 76130 : move16();
289 : /*Compute the Cardioids for the corresponding object direction */
290 76130 : tmp = Mpy_32_32( hIsmMetaData->azimuth_fx, PI_OVER_180_FX ); // Q22
291 76130 : tmp_1 = add( EVS_PI_BY_2_FX, azi_shift ); // Q13
292 76130 : tmp = L_sub( L_shr( tmp, Q22 - Q13 ), L_deposit_l( tmp_1 ) );
293 76130 : IF( LT_32( tmp, -EVS_PI_FX ) )
294 : {
295 18065 : tmp = L_add( tmp, 2 * EVS_PI_FX );
296 : }
297 76130 : cardioid_left[i] = add( shr( alpha, 1 ), mult( sub( ONE_IN_Q15 - 1, alpha ), getCosWord16( extract_l( tmp ) ) ) ); // Q14
298 76130 : move16();
299 :
300 76130 : IF( st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame > 0 )
301 : {
302 : Word16 last_cardioid_right;
303 76066 : last_cardioid_right = sub( ONE_IN_Q14 /* 1.0f in Q14 */, last_cardioid_left );
304 : /* Smoothing */
305 76066 : cardioid_left[i] = add( mult( 24576 /* 0.75f in Q15 */, cardioid_left[i] ), mult( 8192 /* 0.25f in Q15 */, last_cardioid_left ) ); // Q14
306 76066 : move16();
307 76066 : Word32 grad_32 = L_mult( sub( cardioid_left[i], last_cardioid_left ), shl( one_by_input_frame, 1 ) /* 2.0f / (float) input_frame*/ ); /* Q14+Q16 = Q30 */ /* for the right cardioid, multiply with -1 */
308 : /* Cardioids sum up to 1 */
309 76066 : cardioid_right[i] = sub( ONE_IN_Q14 /* 1.0f in Q14 */, cardioid_left[i] ); /* corresponds to: alpha + ( 1 - alpha ) * cosf( tmp + tmp_1 ); */
310 76066 : move16();
311 : /* Loop over all samples */
312 36587746 : FOR( j = 0; j < ( input_frame >> 1 ); j++ )
313 : {
314 36511680 : tmp = data[i][j];
315 36511680 : move32();
316 36511680 : tmp = W_extract_l( W_shr( W_mult_32_32( tmp, L_add( last_cardioid_left, L_shr( Mpy_32_32( L_shl( j, 22 ), grad_32 ), 7 ) ) ), 15 ) ); /* Qx DMX Left */
317 36511680 : stereo_dmx[0][j] = L_add( stereo_dmx[0][j], tmp ); /* Qx DMX Left */
318 36511680 : move32();
319 36511680 : tmp = data[i][j];
320 36511680 : move32();
321 36511680 : tmp = W_extract_l( W_shr( W_mult_32_32( tmp, L_add( last_cardioid_right, L_shr( L_negate( Mpy_32_32( L_shl( j, 22 ), grad_32 ) ), 7 ) ) ), 15 ) ); /* Qx DMX Right */
322 36511680 : stereo_dmx[1][j] = L_add( stereo_dmx[1][j], tmp ); /* Qx DMX Right */
323 36511680 : move32();
324 36511680 : ene_data = W_add( ene_data, W_mult_32_32( data[i][j], data[i][j] ) ); /* 2 * Qx + 1 energy of all objects combined */
325 : }
326 36587746 : FOR( ; j < input_frame; j++ )
327 : {
328 36511680 : tmp = data[i][j];
329 36511680 : move32();
330 36511680 : tmp = W_extract_l( W_shr( W_mult_32_16( tmp, cardioid_left[i] ), 15 ) ); /* Qx DMX Left */
331 36511680 : stereo_dmx[0][j] = L_add( stereo_dmx[0][j], tmp ); /* Qx DMX Left */
332 36511680 : move32();
333 36511680 : tmp = data[i][j];
334 36511680 : move32();
335 36511680 : tmp = W_extract_l( W_shr( W_mult_32_16( tmp, cardioid_right[i] ), 15 ) ); /* Qx DMX Right */
336 36511680 : stereo_dmx[1][j] = L_add( stereo_dmx[1][j], tmp ); /* Qx DMX Right */
337 36511680 : move32();
338 36511680 : ene_data = W_add( ene_data, W_mult_32_32( data[i][j], data[i][j] ) ); /* 2 * Qx + 1 energy of all objects combined */
339 : }
340 : }
341 : ELSE
342 : {
343 : /* Cardioids sum up to 1 */
344 64 : cardioid_right[i] = sub( ONE_IN_Q14 /* 1.0f in Q14 */, cardioid_left[i] ); /* corresponds to: alpha + ( 1 - alpha ) * cosf( tmp + tmp_1 ); */
345 64 : move16();
346 : /* Loop over all samples */
347 61504 : FOR( j = 0; j < input_frame; j++ )
348 : {
349 61440 : tmp = data[i][j];
350 61440 : move32();
351 61440 : tmp = W_extract_l( W_shr( W_mult_32_16( tmp, cardioid_left[i] ), 15 ) ); /* Qx DMX Left */
352 61440 : stereo_dmx[0][j] = L_add( stereo_dmx[0][j], tmp ); /* Qx DMX Left */
353 61440 : move32();
354 61440 : tmp = data[i][j];
355 61440 : move32();
356 61440 : tmp = W_extract_l( W_shr( W_mult_32_16( tmp, cardioid_right[i] ), 15 ) ); /* Qx DMX Right */
357 61440 : stereo_dmx[1][j] = L_add( stereo_dmx[1][j], tmp ); /* Qx DMX Right */
358 61440 : move32();
359 61440 : ene_data = W_add( ene_data, W_mult_32_32( data[i][j], data[i][j] ) ); /* 2 * Qx + 1 energy of all objects combined */
360 : }
361 : }
362 76130 : st_ivas->hParamIsm->last_cardioid_left_fx[i] = cardioid_left[i]; // Q14
363 76130 : move16();
364 : }
365 :
366 : /* Energy compensation */
367 19911920 : FOR( j = 0; j < input_frame; j++ )
368 : {
369 19891200 : ene_dmx = W_mac_32_32( W_mac_32_32( ene_dmx, stereo_dmx[0][j], stereo_dmx[0][j] ), stereo_dmx[1][j], stereo_dmx[1][j] ); /* 2 * Qx + 1 */
370 : }
371 20720 : tmp_1 = W_norm( ene_data );
372 20720 : tmp_2 = W_norm( ene_dmx );
373 20720 : ene_data = W_shl( ene_data, tmp_1 );
374 20720 : ene_dmx = W_shl( ene_dmx, tmp_2 );
375 20720 : dmx_gain = BASOP_Util_Divide3232_Scale( W_extract_h( ene_data ), L_add_sat( W_extract_h( ene_dmx ), 1 ), &dmx_gain_e );
376 20720 : dmx_gain_e = sub( dmx_gain_e, sub( tmp_1, tmp_2 ) );
377 20720 : dmx_gain = Sqrt16( dmx_gain, &dmx_gain_e );
378 :
379 : /* Smoothing */
380 20720 : IF( st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame > 0 )
381 : {
382 20703 : dmx_gain_e = BASOP_Util_Add_MantExp( mult( 24576 /* 0.75f */, dmx_gain ), dmx_gain_e, mult( 8192 /* 0.25f */, last_dmx_gain ), last_dmx_gain_e, &dmx_gain );
383 : /* 10ms ramp */
384 20703 : tmp = L_shl( last_dmx_gain, last_dmx_gain_e ); // Q15
385 20703 : grad = extract_l( Mpy_32_16_r( L_sub( L_shl( dmx_gain, dmx_gain_e ), tmp ), shl( one_by_input_frame, 1 ) /* 2.0f / (float) input_frame*/ ) ); /* Q15 */ /* slope between two consecutive gains, 480 samples length */
386 :
387 20703 : tmp_1 = 15 + 1;
388 20703 : move16();
389 9958143 : FOR( i = 0; i < ( input_frame >> 1 ); i++ )
390 : {
391 9937440 : stereo_dmx[0][i] = W_extract_l( W_shr( W_mult_32_32( stereo_dmx[0][i], L_add( tmp, mult0( i, grad ) ) ), tmp_1 ) ); // Qx
392 9937440 : move32();
393 9937440 : stereo_dmx[1][i] = W_extract_l( W_shr( W_mult_32_32( stereo_dmx[1][i], L_add( tmp, mult0( i, grad ) ) ), tmp_1 ) ); // Qx
394 9937440 : move32();
395 : }
396 20703 : tmp_1 = add( sub( 15, dmx_gain_e ), 1 );
397 9958143 : FOR( ; i < input_frame; i++ )
398 : {
399 9937440 : stereo_dmx[0][i] = W_extract_l( W_shr( W_mult_32_16( stereo_dmx[0][i], dmx_gain ), tmp_1 ) ); // Qx
400 9937440 : move32();
401 9937440 : stereo_dmx[1][i] = W_extract_l( W_shr( W_mult_32_16( stereo_dmx[1][i], dmx_gain ), tmp_1 ) ); // Qx
402 9937440 : move32();
403 : }
404 : }
405 : ELSE
406 : {
407 17 : tmp_1 = add( sub( 15, dmx_gain_e ), 1 );
408 16337 : FOR( j = 0; j < input_frame; j++ )
409 : {
410 16320 : stereo_dmx[0][j] = W_extract_l( W_shr( W_mult_32_16( stereo_dmx[0][j], dmx_gain ), tmp_1 ) ); // Qx
411 16320 : move32();
412 16320 : stereo_dmx[1][j] = W_extract_l( W_shr( W_mult_32_16( stereo_dmx[1][j], dmx_gain ), tmp_1 ) ); // Qx
413 16320 : move32();
414 : }
415 : }
416 20720 : st_ivas->hParamIsm->last_dmx_gain_fx = dmx_gain;
417 20720 : move16();
418 20720 : st_ivas->hParamIsm->last_dmx_gain_e = dmx_gain_e;
419 20720 : move16();
420 :
421 : /* Copy the stereo dmx to data variable */
422 20720 : Copy32( stereo_dmx[0], data[0], input_frame ); // Qx
423 20720 : Copy32( stereo_dmx[1], data[1], input_frame ); // Qx
424 :
425 20720 : pop_wmops();
426 :
427 20720 : return;
428 : }
429 :
430 :
431 : /*-------------------------------------------------------------------------*
432 : * ivas_param_ism_enc_open()
433 : *
434 : * Open Param ISM handle
435 : *-------------------------------------------------------------------------*/
436 :
437 320 : ivas_error ivas_param_ism_enc_open_fx(
438 : Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */
439 : )
440 : {
441 : Word16 i;
442 : IVAS_FB_CFG *fb_cfg;
443 : PARAM_ISM_CONFIG_HANDLE hParamIsm;
444 : Word16 max_bins;
445 : Word32 input_Fs;
446 : ivas_error error;
447 :
448 320 : error = IVAS_ERR_OK;
449 320 : move32();
450 :
451 : /* Assign memory to Param Object handle */
452 320 : if ( ( hParamIsm = (PARAM_ISM_CONFIG_HANDLE) malloc( sizeof( PARAM_ISM_CONFIG_DATA ) ) ) == NULL )
453 : {
454 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM\n" ) );
455 : }
456 :
457 320 : input_Fs = st_ivas->hEncoderConfig->input_Fs;
458 320 : move32();
459 :
460 :
461 : /* set FB config. */
462 320 : IF( NE_32( ( error = ivas_fb_set_cfg( &fb_cfg, ISM_FORMAT, st_ivas->hEncoderConfig->nchan_inp, 0, 0, input_Fs, 0 ) ), IVAS_ERR_OK ) )
463 : {
464 0 : return error;
465 : }
466 :
467 : /* Allocate and initialize FB mixer handle */
468 320 : IF( NE_32( ( error = ivas_FB_mixer_open_fx( &( hParamIsm->hFbMixer ), input_Fs, fb_cfg, 0 ) ), IVAS_ERR_OK ) )
469 : {
470 0 : return error;
471 : }
472 :
473 320 : ivas_param_ism_config_fx( hParamIsm, st_ivas->hEncoderConfig->nchan_inp );
474 :
475 : /* Assign memories for Band and Block grouping */
476 320 : hParamIsm->nbands = MAX_PARAM_ISM_NBANDS;
477 320 : move16();
478 :
479 320 : max_bins = extract_l( Mpy_32_32( input_Fs, 10737418 /*240/48000.Q31*/ ) ); // (int16_t) ( ( MDFT_FB_BANDS_240 * input_Fs ) / 48000 );
480 4160 : FOR( i = 0; i < ( hParamIsm->nbands + 1 ); i++ )
481 : {
482 3840 : hParamIsm->band_grouping[i] = CLDFB_TO_MDFT_FAC * Param_ISM_band_grouping[i];
483 3840 : move16();
484 3840 : IF( GT_16( i_mult( Param_ISM_band_grouping[i], CLDFB_TO_MDFT_FAC ), max_bins ) )
485 : {
486 320 : hParamIsm->band_grouping[i] = max_bins;
487 320 : move16();
488 : }
489 : }
490 :
491 320 : set16_fx( hParamIsm->noisy_speech_buffer, 0, PARAM_ISM_HYS_BUF_SIZE );
492 :
493 320 : st_ivas->hParamIsm = hParamIsm;
494 :
495 320 : return error;
496 : }
497 :
498 :
499 : /*-------------------------------------------------------------------------*
500 : * ivas_param_ism_enc_close()
501 : *
502 : * Close Param ISM encoder handle
503 : *-------------------------------------------------------------------------*/
504 :
505 934 : void ivas_param_ism_enc_close_fx(
506 : PARAM_ISM_CONFIG_HANDLE *hParamIsm, /* i/o: ParamISM handle */
507 : const Word32 input_Fs /* i : input sampling_rate */
508 : )
509 : {
510 934 : test();
511 934 : IF( hParamIsm == NULL || *hParamIsm == NULL )
512 : {
513 614 : return;
514 : }
515 :
516 320 : ivas_FB_mixer_close_fx( &( *hParamIsm )->hFbMixer, input_Fs, 0 );
517 :
518 320 : free( ( *hParamIsm ) );
519 320 : ( *hParamIsm ) = NULL;
520 :
521 320 : return;
522 : }
523 :
524 :
525 : /*-------------------------------------------------------------------------*
526 : * ivas_param_ism_enc()
527 : *
528 : * Parametric ISM encoder
529 : *-------------------------------------------------------------------------*/
530 :
531 20720 : void ivas_param_ism_enc_fx(
532 : Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */
533 : Word32 *data[MAX_NUM_OBJECTS], /* i : input signal q_pcm_in */
534 : const Word16 input_frame /* i : input frame length per channel */
535 : )
536 : {
537 : Word16 i, j, ts, l_ts;
538 : Word16 nchan_ism;
539 : Word16 num_time_slots;
540 : Word16 q_p_fb_Buffer;
541 : Word32 *pcm_in[MAX_NUM_OBJECTS];
542 : Word32 fb_RealBuffer[MAX_NUM_OBJECTS][DIRAC_NO_FB_BANDS_MAX];
543 : Word32 fb_ImagBuffer[MAX_NUM_OBJECTS][DIRAC_NO_FB_BANDS_MAX];
544 : Word32 *p_fb_RealBuffer[MAX_NUM_OBJECTS];
545 : Word32 *p_fb_ImagBuffer[MAX_NUM_OBJECTS];
546 : Word64 reference_power_obj[MAX_NUM_OBJECTS][PARAM_ISM_MDFT_NO_SLOTS][DIRAC_NO_FB_BANDS_MAX];
547 : PARAM_ISM_CONFIG_HANDLE hParamIsm;
548 :
549 20720 : nchan_ism = st_ivas->hEncoderConfig->nchan_ism;
550 20720 : move16();
551 20720 : hParamIsm = st_ivas->hParamIsm;
552 :
553 20720 : push_wmops( "ivas_param_ism_enc" );
554 :
555 20720 : l_ts = shr( input_frame, 2 ); /* input_frame / PARAM_ISM_MDFT_NO_SLOTS */
556 20720 : num_time_slots = PARAM_ISM_MDFT_NO_SLOTS;
557 20720 : move16();
558 :
559 96850 : FOR( i = 0; i < nchan_ism; i++ )
560 : {
561 76130 : pcm_in[i] = data[i];
562 :
563 76130 : set_zero_fx( fb_RealBuffer[i], DIRAC_NO_FB_BANDS_MAX );
564 76130 : set_zero_fx( fb_ImagBuffer[i], DIRAC_NO_FB_BANDS_MAX );
565 76130 : p_fb_RealBuffer[i] = &fb_RealBuffer[i][0];
566 76130 : p_fb_ImagBuffer[i] = &fb_ImagBuffer[i][0];
567 : }
568 :
569 20720 : Word16 gb = find_guarded_bits_fx( l_ts );
570 20720 : q_p_fb_Buffer = sub( st_ivas->q_data_fx, gb );
571 :
572 103600 : FOR( ts = 0; ts < num_time_slots; ts++ )
573 : {
574 82880 : ivas_fb_mixer_get_windowed_fr_fx( hParamIsm->hFbMixer, pcm_in, p_fb_RealBuffer, p_fb_ImagBuffer, l_ts, l_ts, hParamIsm->hFbMixer->fb_cfg->num_in_chans, gb );
575 :
576 82880 : ivas_fb_mixer_update_prior_input_fx( hParamIsm->hFbMixer, pcm_in, l_ts, hParamIsm->hFbMixer->fb_cfg->num_in_chans );
577 :
578 387400 : FOR( i = 0; i < nchan_ism; i++ )
579 : {
580 304520 : pcm_in[i] += l_ts;
581 73389320 : FOR( j = 0; j < DIRAC_NO_FB_BANDS_MAX; j++ )
582 : {
583 73084800 : reference_power_obj[i][ts][j] = W_shr( W_add( W_mult0_32_32( fb_RealBuffer[i][j], fb_RealBuffer[i][j] ), W_mult0_32_32( fb_ImagBuffer[i][j], fb_ImagBuffer[i][j] ) ), shl( q_p_fb_Buffer, 1 ) ); // Q0
584 73084800 : move64();
585 : }
586 : }
587 : }
588 :
589 20720 : ivas_param_ism_enc_quantize_DOA_fx( nchan_ism, st_ivas->hIsmMetaData, hParamIsm );
590 :
591 20720 : ivas_param_ism_compute_obj_parameters_fx( nchan_ism, reference_power_obj, hParamIsm );
592 :
593 20720 : pop_wmops();
594 20720 : return;
595 : }
596 :
597 :
598 : /*-------------------------------------------------------------------*
599 : * ivas_param_ism_compute_noisy_speech_flag()
600 : *
601 : *
602 : *-------------------------------------------------------------------*/
603 :
604 20720 : void ivas_param_ism_compute_noisy_speech_flag_fx(
605 : Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */
606 : )
607 : {
608 : Word16 i;
609 :
610 : /* Move the Noisy speech buffer */
611 207200 : FOR( i = 0; i < ( PARAM_ISM_HYS_BUF_SIZE - 1 ); i++ )
612 : {
613 186480 : st_ivas->hParamIsm->noisy_speech_buffer[i] = st_ivas->hParamIsm->noisy_speech_buffer[i + 1];
614 186480 : move16();
615 : }
616 :
617 : /* Set flag_noisy_speech to 0 for cases where object energies are not roughly equal */
618 20720 : IF( !st_ivas->hParamIsm->flag_equal_energy )
619 : {
620 20719 : st_ivas->hParamIsm->noisy_speech_buffer[i] = 0;
621 20719 : st_ivas->hParamIsm->flag_noisy_speech = 0;
622 20719 : move16();
623 20719 : move16();
624 : }
625 : ELSE
626 : {
627 : /* For the current frame, make a decision based on some core-coder flags */
628 1 : test();
629 1 : IF( st_ivas->hSCE[0]->hCoreCoder[0]->flag_noisy_speech_snr && st_ivas->hSCE[1]->hCoreCoder[0]->flag_noisy_speech_snr )
630 : {
631 1 : test();
632 1 : IF( st_ivas->hSCE[0]->hCoreCoder[0]->vad_flag || st_ivas->hSCE[1]->hCoreCoder[0]->vad_flag )
633 : {
634 0 : st_ivas->hParamIsm->noisy_speech_buffer[i] = 0;
635 0 : move16();
636 : }
637 : ELSE
638 : {
639 1 : st_ivas->hParamIsm->noisy_speech_buffer[i] = 1;
640 1 : move16();
641 : }
642 : }
643 : ELSE
644 : {
645 0 : st_ivas->hParamIsm->noisy_speech_buffer[i] = 0;
646 0 : move16();
647 : }
648 :
649 : /* Do a decision based on hysteresis */
650 1 : st_ivas->hParamIsm->flag_noisy_speech = 1;
651 1 : move16();
652 11 : FOR( i = 0; i < PARAM_ISM_HYS_BUF_SIZE; i++ )
653 : {
654 10 : test();
655 10 : st_ivas->hParamIsm->flag_noisy_speech = st_ivas->hParamIsm->flag_noisy_speech && st_ivas->hParamIsm->noisy_speech_buffer[i];
656 : }
657 : }
658 :
659 20720 : return;
660 : }
|