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