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 "options.h"
35 : #include <math.h>
36 : #include "ivas_prot_fx.h"
37 : #include "prot_fx.h"
38 : #include "isar_cnst.h"
39 : #include "isar_rom_post_rend.h"
40 : #include "lib_isar_pre_rend.h"
41 : #include "isar_prot.h"
42 : #ifdef DEBUGGING
43 : #include "debug.h"
44 : #endif
45 : #include "wmc_auto.h"
46 :
47 :
48 : /*-------------------------------------------------------------------------
49 : * Function ISAR_PRE_REND_open()
50 : *
51 : *
52 : *------------------------------------------------------------------------*/
53 :
54 0 : ivas_error ISAR_PRE_REND_open(
55 : SPLIT_REND_WRAPPER *hSplitRendWrapper,
56 : ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig,
57 : const Word32 OutSampleRate,
58 : const Word16 cldfb_in_flag,
59 : const Word16 pcm_out_flag,
60 : const IVAS_RENDER_FRAMESIZE ivas_frame_size, /* i: IVAS frame size */
61 : const Word16 mixed_td_cldfb_flag )
62 : {
63 : ivas_error error, ch, num_ch;
64 0 : UWord8 isCldfbNeeded = 0;
65 0 : Word16 cldfb_in_flag_local = cldfb_in_flag;
66 :
67 0 : IF( ( error = isar_split_rend_choose_default_codec( &( pSplitRendConfig->codec ),
68 : &pSplitRendConfig->isar_frame_size_ms,
69 : &pSplitRendConfig->codec_frame_size_ms,
70 : cldfb_in_flag_local,
71 : pcm_out_flag, (Word16) ivas_frame_size ) ) != IVAS_ERR_OK )
72 : {
73 0 : return error;
74 : }
75 :
76 0 : if ( mixed_td_cldfb_flag )
77 : {
78 0 : cldfb_in_flag_local = 0;
79 : }
80 :
81 0 : IF( ( error = isar_split_rend_validate_config( pSplitRendConfig, pcm_out_flag ) ) != IVAS_ERR_OK )
82 : {
83 0 : return error;
84 : }
85 :
86 0 : IF( EQ_16( cldfb_in_flag_local, 0 ) )
87 : {
88 0 : isCldfbNeeded = 1;
89 : }
90 0 : ELSE IF( EQ_16( pSplitRendConfig->codec, ISAR_SPLIT_REND_CODEC_LC3PLUS ) && cldfb_in_flag_local )
91 : {
92 0 : isCldfbNeeded = 1;
93 : }
94 0 : ELSE IF( pcm_out_flag && cldfb_in_flag_local )
95 : {
96 0 : isCldfbNeeded = 1;
97 : }
98 :
99 0 : hSplitRendWrapper->hCldfbHandles = NULL;
100 :
101 0 : IF( isCldfbNeeded )
102 : {
103 0 : IF( ( hSplitRendWrapper->hCldfbHandles = (CLDFB_HANDLES_WRAPPER_HANDLE) malloc( sizeof( CLDFB_HANDLES_WRAPPER ) ) ) == NULL )
104 : {
105 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CLDFB handles\n" ) );
106 : }
107 0 : num_ch = MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS;
108 0 : FOR( ch = 0; ch < num_ch; ch++ )
109 : {
110 0 : hSplitRendWrapper->hCldfbHandles->cldfbAna[ch] = NULL;
111 : }
112 :
113 0 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
114 : {
115 0 : hSplitRendWrapper->hCldfbHandles->cldfbSyn[ch] = NULL;
116 : }
117 :
118 0 : num_ch = hSplitRendWrapper->multiBinPoseData.num_poses * BINAURAL_CHANNELS;
119 :
120 0 : FOR( ch = 0; ch < num_ch; ch++ )
121 : {
122 0 : if ( ( error = openCldfb_ivas_fx( &( hSplitRendWrapper->hCldfbHandles->cldfbAna[ch] ),
123 : CLDFB_ANALYSIS, OutSampleRate, CLDFB_PROTOTYPE_5_00MS, DEC ) ) != IVAS_ERR_OK )
124 : {
125 0 : return error;
126 : }
127 : }
128 :
129 0 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
130 : {
131 0 : IF( ( error = openCldfb_ivas_fx( &( hSplitRendWrapper->hCldfbHandles->cldfbSyn[ch] ), CLDFB_SYNTHESIS, OutSampleRate, CLDFB_PROTOTYPE_5_00MS, DEC ) ) != IVAS_ERR_OK )
132 : {
133 0 : return error;
134 : }
135 : }
136 : }
137 :
138 0 : IF( EQ_16( pSplitRendConfig->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) )
139 : {
140 0 : if ( ( error = isar_splitBinPreRendOpen( &hSplitRendWrapper->hBinHrSplitPreRend, &hSplitRendWrapper->multiBinPoseData
141 : #ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG
142 : ,
143 : OutSampleRate
144 : #endif
145 : ) ) != IVAS_ERR_OK )
146 : {
147 0 : return error;
148 : }
149 : }
150 :
151 0 : IF( EQ_16( pcm_out_flag, 0 ) )
152 : {
153 0 : IF( EQ_16( pSplitRendConfig->codec, ISAR_SPLIT_REND_CODEC_LC3PLUS ) )
154 : {
155 0 : if ( ( error = split_renderer_open_lc3plus( hSplitRendWrapper, pSplitRendConfig, OutSampleRate, ivas_frame_size ) ) != IVAS_ERR_OK )
156 : {
157 0 : return error;
158 : }
159 : }
160 : ELSE
161 : {
162 : Word16 iNumBlocksPerFrame;
163 0 : iNumBlocksPerFrame = ( CLDFB_NO_COL_MAX * pSplitRendConfig->codec_frame_size_ms ) / 20;
164 :
165 0 : IF( ( error = isar_splitBinLCLDEncOpen( &hSplitRendWrapper->hSplitBinLCLDEnc, OutSampleRate, BINAURAL_CHANNELS, isar_get_lcld_bitrate( pSplitRendConfig->splitRendBitRate, hSplitRendWrapper->multiBinPoseData.poseCorrectionMode ), iNumBlocksPerFrame, 1 ) ) != IVAS_ERR_OK )
166 : {
167 0 : return error;
168 : }
169 : }
170 : }
171 :
172 0 : return IVAS_ERR_OK;
173 : }
174 :
175 :
176 : /*-------------------------------------------------------------------------
177 : * Function ISAR_PRE_REND_close()
178 : *
179 : *
180 : *------------------------------------------------------------------------*/
181 :
182 0 : void ISAR_PRE_REND_close(
183 : SPLIT_REND_WRAPPER *hSplitBinRend, /* i/o: Split renderer pre-renerer handle */
184 : IVAS_REND_AudioBuffer *pSplitRendEncBuffer /* i/o: Split renderer data buffer */
185 : )
186 : {
187 : Word16 i;
188 :
189 0 : IF( hSplitBinRend->hBinHrSplitPreRend != NULL )
190 : {
191 0 : isar_splitBinPreRendClose( &hSplitBinRend->hBinHrSplitPreRend );
192 : }
193 :
194 0 : IF( hSplitBinRend->hSplitBinLCLDEnc != NULL )
195 : {
196 0 : isar_splitBinLCLDEncClose( &hSplitBinRend->hSplitBinLCLDEnc );
197 : }
198 :
199 0 : IF( hSplitBinRend->hCldfbHandles != NULL )
200 : {
201 : Word16 num_ch, ch;
202 0 : num_ch = MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS;
203 0 : FOR( ch = 0; ch < num_ch; ch++ )
204 : {
205 0 : IF( hSplitBinRend->hCldfbHandles->cldfbAna[ch] != NULL )
206 : {
207 0 : deleteCldfb_ivas_fx( &hSplitBinRend->hCldfbHandles->cldfbAna[ch] );
208 0 : hSplitBinRend->hCldfbHandles->cldfbAna[ch] = NULL;
209 : }
210 : }
211 :
212 0 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
213 : {
214 0 : IF( hSplitBinRend->hCldfbHandles->cldfbSyn[ch] != NULL )
215 : {
216 0 : deleteCldfb_ivas_fx( &hSplitBinRend->hCldfbHandles->cldfbSyn[ch] );
217 0 : hSplitBinRend->hCldfbHandles->cldfbSyn[ch] = NULL;
218 : }
219 : }
220 :
221 0 : free( hSplitBinRend->hCldfbHandles );
222 0 : hSplitBinRend->hCldfbHandles = NULL;
223 : }
224 :
225 0 : IF( hSplitBinRend->hLc3plusEnc != NULL )
226 : {
227 0 : ISAR_LC3PLUS_ENC_Close( &hSplitBinRend->hLc3plusEnc );
228 : }
229 :
230 0 : FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; ++i )
231 : {
232 0 : if ( hSplitBinRend->lc3plusDelayBuffers_fx[i] != NULL )
233 : {
234 0 : free( hSplitBinRend->lc3plusDelayBuffers_fx[i] );
235 0 : hSplitBinRend->lc3plusDelayBuffers_fx[i] = NULL;
236 : }
237 : }
238 :
239 0 : IF( pSplitRendEncBuffer != NULL )
240 : {
241 :
242 0 : IF( pSplitRendEncBuffer->data_fx != NULL )
243 : {
244 0 : free( pSplitRendEncBuffer->data_fx );
245 0 : pSplitRendEncBuffer->data_fx = NULL;
246 : }
247 :
248 0 : pSplitRendEncBuffer->config.numChannels = 0;
249 0 : pSplitRendEncBuffer->config.numSamplesPerChannel = 0;
250 : }
251 :
252 0 : return;
253 : }
254 :
255 :
256 : /*-------------------------------------------------------------------------*
257 : * ISAR_PRE_REND_GetMultiBinPoseData()
258 : *
259 : *
260 : *-------------------------------------------------------------------------*/
261 :
262 0 : void ISAR_PRE_REND_GetMultiBinPoseData(
263 : const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, /* i : Split renderer pre-renerer config */
264 : MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */
265 : const ISAR_SPLIT_REND_ROT_AXIS rot_axis /* i : Rotation axis */
266 : )
267 : {
268 0 : isar_renderSplitGetMultiBinPoseData_fx( pSplit_rend_config, pMultiBinPoseData, rot_axis );
269 :
270 0 : return;
271 : }
272 :
273 :
274 : /*-------------------------------------------------------------------------
275 : * Function ISAR_PRE_REND_MultiBinToSplitBinaural()
276 : *
277 : *
278 : *------------------------------------------------------------------------*/
279 :
280 0 : ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural(
281 : SPLIT_REND_WRAPPER *hSplitBin,
282 : const IVAS_QUATERNION headPosition,
283 : const Word32 SplitRendBitRate,
284 : ISAR_SPLIT_REND_CODEC splitCodec,
285 : const Word16 isar_frame_size_ms, /* i: ISAR framesize */
286 : Word16 codec_frame_size_ms,
287 : ISAR_SPLIT_REND_BITS_HANDLE pBits,
288 : Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
289 : Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
290 : const Word16 max_bands,
291 : Word32 *pOutput_fx[],
292 : const Word16 low_res_pre_rend_rot,
293 : const Word16 cldfb_in_flag,
294 : const Word16 pcm_out_flag,
295 : const Word16 ro_md_flag,
296 : Word16 Q_buff,
297 : Word16 *Q_out )
298 : {
299 : ivas_error error;
300 : Word32 bit_len, target_md_bits, available_bits, tmp_32;
301 0 : Word16 q1 = 31, q2 = 31, q_final, Q_cldfb, tmp, tmp_e;
302 : Word16 i, j;
303 0 : error = IVAS_ERR_OK;
304 : Word16 Q_buff_re, Q_buff_im;
305 :
306 0 : push_wmops( "ISAR_PRE_REND_MultiBinToSplitBinaural" );
307 :
308 0 : Q_buff_re = Q_buff;
309 0 : move16();
310 0 : Q_buff_im = Q_buff;
311 0 : move16();
312 0 : IF( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB )
313 : {
314 0 : set_fix_rotation_mat_fx( hSplitBin->hBinHrSplitPreRend->fix_pos_rot_mat_fx, &hSplitBin->multiBinPoseData );
315 0 : set_pose_types_fx( hSplitBin->hBinHrSplitPreRend->pose_type, &hSplitBin->multiBinPoseData );
316 : }
317 :
318 0 : IF( EQ_16( cldfb_in_flag, 0 ) )
319 : {
320 0 : error = isar_renderMultiTDBinToSplitBinaural( hSplitBin, headPosition, SplitRendBitRate, isar_frame_size_ms, codec_frame_size_ms, pBits, max_bands, pOutput_fx, Q_out[0], low_res_pre_rend_rot, pcm_out_flag, ro_md_flag );
321 :
322 0 : Q_out[1] = Q_out[0];
323 0 : move16();
324 0 : pop_wmops();
325 0 : return error;
326 : }
327 :
328 0 : IF( splitCodec == ISAR_SPLIT_REND_CODEC_LC3PLUS && hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB )
329 : {
330 : /* Time-align pose correction to delay of LC3plus */
331 0 : lc3plusTimeAlignCldfbPoseCorr( hSplitBin, Cldfb_In_BinReal_fx, Cldfb_In_BinImag_fx, &Q_buff );
332 0 : Q_buff_re = Q_buff;
333 0 : move16();
334 0 : Q_buff_im = Q_buff;
335 0 : move16();
336 : }
337 :
338 0 : IF( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB )
339 : {
340 0 : target_md_bits = isar_get_split_rend_md_target_brate( SplitRendBitRate, pcm_out_flag ) * L_FRAME48k / 48000;
341 :
342 : /*float2fix, to be removed*/
343 0 : Word16 Q_Cldfb_re = 31, Q_Cldfb_im = 31;
344 0 : move16();
345 0 : move16();
346 0 : FOR( i = 0; i < hSplitBin->multiBinPoseData.num_poses * BINAURAL_CHANNELS; i++ )
347 : {
348 0 : FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ )
349 : {
350 0 : Q_Cldfb_re = s_min( getScaleFactor32( Cldfb_In_BinReal_fx[i][j], CLDFB_NO_CHANNELS_MAX ), Q_Cldfb_re );
351 0 : Q_Cldfb_im = s_min( getScaleFactor32( Cldfb_In_BinImag_fx[i][j], CLDFB_NO_CHANNELS_MAX ), Q_Cldfb_im );
352 : }
353 : }
354 0 : FOR( i = 0; i < hSplitBin->multiBinPoseData.num_poses * BINAURAL_CHANNELS; i++ )
355 : {
356 0 : FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ )
357 : {
358 0 : Scale_sig32( Cldfb_In_BinReal_fx[i][j], CLDFB_NO_CHANNELS_MAX, Q_Cldfb_re );
359 0 : Scale_sig32( Cldfb_In_BinImag_fx[i][j], CLDFB_NO_CHANNELS_MAX, Q_Cldfb_im );
360 : }
361 : }
362 0 : Q_buff_re = add( Q_Cldfb_re, Q_buff );
363 0 : Q_buff_im = add( Q_Cldfb_im, Q_buff );
364 0 : Word16 exp_cldfb_re = sub( 31, Q_buff_re );
365 0 : Word16 exp_cldfb_im = sub( 31, Q_buff_im );
366 0 : isar_rend_CldfbSplitPreRendProcess( hSplitBin->hBinHrSplitPreRend, headPosition, &hSplitBin->multiBinPoseData, Cldfb_In_BinReal_fx, exp_cldfb_re, Cldfb_In_BinImag_fx, exp_cldfb_im, pBits, target_md_bits, low_res_pre_rend_rot, ro_md_flag );
367 : }
368 :
369 0 : IF( EQ_16( pcm_out_flag, 0 ) )
370 : {
371 0 : pBits->codec = splitCodec;
372 0 : pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode;
373 :
374 0 : IF( splitCodec == ISAR_SPLIT_REND_CODEC_LCLD )
375 : {
376 : // available_bits = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC );
377 0 : available_bits = W_extract_l( W_mult0_32_32( SplitRendBitRate, L_mult0( hSplitBin->hSplitBinLCLDEnc->iNumBlocks, hSplitBin->hSplitBinLCLDEnc->iNumIterations ) ) );
378 0 : tmp_e = 0;
379 0 : tmp_32 = BASOP_Util_Divide3232_Scale_cadence( available_bits, L_mult0( 16, FRAMES_PER_SEC ), &tmp_e );
380 0 : available_bits = L_shr( tmp_32, sub( 31, tmp_e ) ); // Q0
381 0 : available_bits = L_sub( available_bits, pBits->bits_written );
382 0 : pBits->codec_frame_size_ms = codec_frame_size_ms;
383 0 : q_final = sub( s_min( Q_buff_re, Q_buff_im ), 2 );
384 0 : FOR( i = 0; i < hSplitBin->hSplitBinLCLDEnc->iChannels; i++ )
385 : {
386 0 : FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ )
387 : {
388 0 : Scale_sig32( Cldfb_In_BinReal_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_re ) );
389 0 : Scale_sig32( Cldfb_In_BinImag_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_im ) );
390 : }
391 : }
392 0 : isar_splitBinLCLDEncProcess( hSplitBin->hSplitBinLCLDEnc, Cldfb_In_BinReal_fx, Cldfb_In_BinImag_fx, available_bits, pBits, &q_final );
393 0 : Q_buff_re = q_final;
394 0 : move16();
395 0 : Q_buff_im = q_final;
396 0 : move16();
397 : }
398 : ELSE
399 : {
400 : Word16 ch, slot_idx, num_slots, ivas_fs;
401 0 : tmp_e = 0;
402 0 : tmp = BASOP_Util_Divide3232_Scale( hSplitBin->hLc3plusEnc->config.isar_frame_duration_us, 1000, &tmp_e );
403 0 : ivas_fs = shr( tmp, sub( 15, tmp_e ) ); // Q0
404 : // ivas_fs = (Word16) hSplitBin->hLc3plusEnc->config.ivas_frame_duration_us / 1000;
405 :
406 0 : tmp_e = 0;
407 0 : tmp = BASOP_Util_Divide3232_Scale( L_mult0( CLDFB_NO_COL_MAX, ivas_fs ), 20, &tmp_e );
408 0 : num_slots = shr( tmp, sub( 15, tmp_e ) ); // Q0
409 : // num_slots = (Word16) CLDFB_NO_COL_MAX * ivas_fs / 20;
410 : /* CLDFB synthesis of main pose */
411 : {
412 0 : q1 = 31;
413 0 : q2 = 31;
414 0 : move16();
415 0 : move16();
416 0 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
417 : {
418 0 : FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ )
419 : {
420 0 : q1 = s_min( getScaleFactor32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q1 );
421 0 : q2 = s_min( getScaleFactor32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q2 );
422 : }
423 : }
424 :
425 0 : q_final = s_min( q1, q2 );
426 0 : q_final = s_min( add( Q_buff_re, q_final ), add( Q_buff_im, q_final ) );
427 0 : q_final = sub( q_final, 6 ); // guard bits
428 0 : q_final = s_min( q_final, Q25 );
429 :
430 0 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
431 : {
432 0 : FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ )
433 : {
434 0 : Scale_sig32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_re ) );
435 0 : Scale_sig32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_im ) );
436 : }
437 : }
438 : }
439 :
440 0 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
441 : {
442 : Word32 *Cldfb_In_BinReal_p_fx[CLDFB_NO_COL_MAX];
443 : Word32 *Cldfb_In_BinImag_p_fx[CLDFB_NO_COL_MAX];
444 :
445 :
446 0 : FOR( slot_idx = 0; slot_idx < num_slots; slot_idx++ )
447 : {
448 0 : Cldfb_In_BinReal_p_fx[slot_idx] = Cldfb_In_BinReal_fx[ch][slot_idx];
449 0 : move32();
450 0 : Cldfb_In_BinImag_p_fx[slot_idx] = Cldfb_In_BinImag_fx[ch][slot_idx];
451 0 : move32();
452 : }
453 :
454 0 : Q_cldfb = q_final;
455 0 : move16();
456 0 : Scale_sig32( hSplitBin->hCldfbHandles->cldfbSyn[ch]->cldfb_state_fx, hSplitBin->hCldfbHandles->cldfbSyn[ch]->p_filter_length, sub( sub( Q_cldfb, 1 ), hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_cldfb_state ) );
457 0 : cldfbSynthesis_ivas_fx( Cldfb_In_BinReal_p_fx, Cldfb_In_BinImag_p_fx, pOutput_fx[ch], hSplitBin->hCldfbHandles->cldfbSyn[0]->no_channels * num_slots, 0, 0, hSplitBin->hCldfbHandles->cldfbSyn[ch] ); // Q_cldfb - 1
458 0 : Q_out[ch] = sub( Q_cldfb, 1 );
459 0 : move16();
460 0 : hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_cldfb_state = Q_out[ch];
461 0 : move16();
462 : }
463 0 : assert( Q_out[0] == Q_out[1] );
464 :
465 :
466 : #ifdef LC3PLUS_LEA_COMPAT_BITRATES_48_6
467 0 : IF( EQ_32( pBits->pose_correction, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) )
468 : {
469 0 : available_bits = isar_get_lc3plus_bitrate( SplitRendBitRate, hSplitBin->multiBinPoseData.poseCorrectionMode, hSplitBin->hLc3plusEnc->config.channels, hSplitBin->hLc3plusEnc->config.lc3plus_frame_duration_us );
470 0 : available_bits = Mpy_32_32( available_bits, ONE_BY_FRAMES_PER_SEC_Q31 );
471 : }
472 : ELSE
473 : {
474 0 : available_bits = L_sub( Mpy_32_32( SplitRendBitRate, ONE_BY_FRAMES_PER_SEC_Q31 ), pBits->bits_written );
475 : }
476 : #else
477 : available_bits = ( SplitRendBitRate / FRAMES_PER_SEC ) - pBits->bits_written;
478 : #endif
479 0 : IF( ( error = splitRendLc3plusEncodeAndWrite( hSplitBin, pBits, available_bits, pOutput_fx, Q_out[0] ) ) != IVAS_ERR_OK )
480 : {
481 0 : return error;
482 : }
483 : }
484 : }
485 : ELSE
486 : {
487 : Word16 ch, slot_idx;
488 : /* CLDFB synthesis of main pose */
489 0 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
490 : {
491 : Word32 *Cldfb_In_BinReal_p_fx[CLDFB_NO_COL_MAX];
492 : Word32 *Cldfb_In_BinImag_p_fx[CLDFB_NO_COL_MAX];
493 0 : q1 = 31;
494 0 : move16();
495 0 : q2 = 31;
496 0 : move16();
497 0 : FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ )
498 : {
499 0 : q1 = s_min( getScaleFactor32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q1 );
500 0 : q2 = s_min( getScaleFactor32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q2 );
501 : }
502 0 : q_final = s_min( q1, q2 );
503 0 : q_final = s_min( add( Q_buff_re, q_final ), add( Q_buff_im, q_final ) );
504 0 : q_final = sub( q_final, 6 ); // guard bits
505 0 : q_final = s_min( q_final, Q25 );
506 0 : FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ )
507 : {
508 0 : Scale_sig32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_re ) );
509 0 : Scale_sig32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_im ) );
510 : }
511 :
512 0 : FOR( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX; slot_idx++ )
513 : {
514 0 : Cldfb_In_BinReal_p_fx[slot_idx] = Cldfb_In_BinReal_fx[ch][slot_idx];
515 0 : move32();
516 0 : Cldfb_In_BinImag_p_fx[slot_idx] = Cldfb_In_BinImag_fx[ch][slot_idx];
517 0 : move32();
518 : }
519 :
520 0 : Q_cldfb = q_final;
521 0 : move16();
522 0 : Scale_sig32( hSplitBin->hCldfbHandles->cldfbSyn[ch]->cldfb_state_fx, hSplitBin->hCldfbHandles->cldfbSyn[ch]->p_filter_length, sub( sub( Q_cldfb, 1 ), hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_cldfb_state ) );
523 0 : cldfbSynthesis_ivas_fx( Cldfb_In_BinReal_p_fx, Cldfb_In_BinImag_p_fx, pOutput_fx[ch], hSplitBin->hCldfbHandles->cldfbSyn[0]->no_channels * CLDFB_NO_COL_MAX, 0, 0, hSplitBin->hCldfbHandles->cldfbSyn[ch] ); // Q_cldfb - 1
524 0 : Q_out[ch] = sub( Q_cldfb, 1 );
525 0 : move16();
526 0 : hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_cldfb_state = Q_out[ch];
527 0 : move16();
528 : }
529 :
530 0 : pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode;
531 0 : pBits->codec = ISAR_SPLIT_REND_CODEC_NONE;
532 : }
533 :
534 : /*zero pad*/
535 0 : IF( pcm_out_flag )
536 : {
537 0 : tmp_e = 0;
538 0 : tmp = BASOP_Util_Divide3232_Scale( SplitRendBitRate, FRAMES_PER_SEC, &tmp_e );
539 0 : bit_len = L_deposit_l( shr( tmp, sub( 15, tmp_e ) ) ); // Q0
540 : // bit_len = SplitRendBitRate / FRAMES_PER_SEC;
541 : }
542 : ELSE
543 : {
544 0 : IF( splitCodec == ISAR_SPLIT_REND_CODEC_LCLD )
545 : {
546 : // bit_len = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC );
547 :
548 0 : bit_len = W_extract_l( W_mult0_32_32( SplitRendBitRate, L_mult0( hSplitBin->hSplitBinLCLDEnc->iNumBlocks, hSplitBin->hSplitBinLCLDEnc->iNumIterations ) ) );
549 0 : tmp_e = 0;
550 0 : tmp_32 = BASOP_Util_Divide3232_Scale_cadence( bit_len, L_mult0( 16, FRAMES_PER_SEC ), &tmp_e );
551 0 : bit_len = L_shr( tmp_32, sub( 31, tmp_e ) ); // Q0
552 : }
553 : ELSE
554 : {
555 0 : tmp_e = 0;
556 0 : tmp = BASOP_Util_Divide3232_Scale( hSplitBin->hLc3plusEnc->config.isar_frame_duration_us, 1000, &tmp_e );
557 0 : bit_len = L_deposit_l( shr( tmp, sub( 15, tmp_e ) ) ); // Q0
558 : // bit_len = hSplitBin->hLc3plusEnc->config.ivas_frame_duration_us / 1000;
559 : // bit_len = SplitRendBitRate * bit_len / 1000;
560 0 : tmp_e = 0;
561 0 : tmp_32 = BASOP_Util_Divide3232_Scale_cadence( W_extract_l( W_mult0_32_32( SplitRendBitRate, bit_len ) ), 1000, &tmp_e );
562 0 : bit_len = L_shr( tmp_32, sub( 31, tmp_e ) ); // Q0
563 : }
564 : }
565 :
566 0 : WHILE( LT_32( pBits->bits_written, bit_len ) )
567 : {
568 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0L, 1 );
569 : }
570 :
571 0 : pop_wmops();
572 0 : return error;
573 : }
|