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 :
34 : #include <stdint.h>
35 : #include "options.h"
36 : #include <math.h>
37 : #include "ivas_prot.h"
38 : #include "prot.h"
39 : #include "ivas_cnst.h"
40 : #include "isar_rom_post_rend.h"
41 : #include "lib_isar_pre_rend.h"
42 : #include "isar_prot.h"
43 : #ifdef DEBUGGING
44 : #include "debug.h"
45 : #endif
46 : #include "wmc_auto.h"
47 :
48 :
49 : /*-------------------------------------------------------------------------
50 : * Function ISAR_PRE_REND_open()
51 : *
52 : *
53 : *------------------------------------------------------------------------*/
54 :
55 0 : ivas_error ISAR_PRE_REND_open(
56 : SPLIT_REND_WRAPPER *hSplitBinRend, /* i/o: Split renderer pre-renerer handle */
57 : ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, /* i/o: Split renderer pre-renerer config */
58 : const int32_t output_Fs, /* i : output sampling rate */
59 : const int16_t cldfb_in_flag, /* i : Flag to indicate CLDFB or time doamin input */
60 : const int16_t pcm_out_flag, /* i : Flag to indicate PCM output */
61 : const IVAS_RENDER_FRAMESIZE ivas_frame_size, /* i : IVAS frame size */
62 : const int16_t mixed_td_cldfb_flag /* i : Flag to indicate combined TD and CLDFB input */
63 : )
64 : {
65 : ivas_error error, ch, num_ch;
66 0 : uint8_t isCldfbNeeded = 0;
67 0 : int16_t cldfb_in_flag_local = cldfb_in_flag;
68 :
69 0 : if ( ( error = isar_split_rend_choose_default_codec( &( pSplitRendConfig->codec ), &pSplitRendConfig->isar_frame_size_ms, &pSplitRendConfig->codec_frame_size_ms, cldfb_in_flag_local, pcm_out_flag, (int16_t) ivas_frame_size ) ) != IVAS_ERR_OK )
70 : {
71 0 : return error;
72 : }
73 :
74 0 : if ( mixed_td_cldfb_flag )
75 : {
76 0 : cldfb_in_flag_local = 0;
77 : }
78 :
79 0 : if ( ( error = isar_split_rend_validate_config( pSplitRendConfig, pcm_out_flag ) ) != IVAS_ERR_OK )
80 : {
81 0 : return error;
82 : }
83 :
84 0 : if ( cldfb_in_flag_local == 0 )
85 : {
86 0 : isCldfbNeeded = 1;
87 : }
88 0 : else if ( pSplitRendConfig->codec == ISAR_SPLIT_REND_CODEC_LC3PLUS && cldfb_in_flag_local )
89 : {
90 0 : isCldfbNeeded = 1;
91 : }
92 0 : else if ( pcm_out_flag && cldfb_in_flag_local )
93 : {
94 0 : isCldfbNeeded = 1;
95 : }
96 :
97 0 : hSplitBinRend->hCldfbHandles = NULL;
98 :
99 0 : if ( isCldfbNeeded )
100 : {
101 0 : if ( ( hSplitBinRend->hCldfbHandles = (CLDFB_HANDLES_WRAPPER_HANDLE) malloc( sizeof( CLDFB_HANDLES_WRAPPER ) ) ) == NULL )
102 : {
103 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CLDFB handles\n" ) );
104 : }
105 0 : num_ch = MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS;
106 0 : for ( ch = 0; ch < num_ch; ch++ )
107 : {
108 0 : hSplitBinRend->hCldfbHandles->cldfbAna[ch] = NULL;
109 : }
110 :
111 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
112 : {
113 0 : hSplitBinRend->hCldfbHandles->cldfbSyn[ch] = NULL;
114 : }
115 :
116 0 : num_ch = hSplitBinRend->multiBinPoseData.num_poses * BINAURAL_CHANNELS;
117 :
118 0 : for ( ch = 0; ch < num_ch; ch++ )
119 : {
120 0 : if ( ( error = openCldfb( &( hSplitBinRend->hCldfbHandles->cldfbAna[ch] ), CLDFB_ANALYSIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK )
121 : {
122 0 : return error;
123 : }
124 : }
125 :
126 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
127 : {
128 0 : if ( ( error = openCldfb( &( hSplitBinRend->hCldfbHandles->cldfbSyn[ch] ), CLDFB_SYNTHESIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK )
129 : {
130 0 : return error;
131 : }
132 : }
133 : }
134 :
135 0 : if ( pSplitRendConfig->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB )
136 : {
137 : #ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG
138 : if ( ( error = isar_splitBinPreRendOpen( &hSplitBinRend->hBinHrSplitPreRend, &hSplitBinRend->multiBinPoseData, OutSampleRate ) ) != IVAS_ERR_OK )
139 : #else
140 0 : if ( ( error = isar_splitBinPreRendOpen( &hSplitBinRend->hBinHrSplitPreRend, &hSplitBinRend->multiBinPoseData ) ) != IVAS_ERR_OK )
141 : #endif
142 : {
143 0 : return error;
144 : }
145 : }
146 :
147 0 : if ( pcm_out_flag == 0 )
148 : {
149 0 : if ( pSplitRendConfig->codec == ISAR_SPLIT_REND_CODEC_LC3PLUS )
150 : {
151 0 : if ( ( error = split_renderer_open_lc3plus( hSplitBinRend, pSplitRendConfig, output_Fs, ivas_frame_size ) ) != IVAS_ERR_OK )
152 : {
153 0 : return error;
154 : }
155 : }
156 : else
157 : {
158 : int16_t iNumBlocksPerFrame;
159 0 : iNumBlocksPerFrame = ( CLDFB_NO_COL_MAX * pSplitRendConfig->codec_frame_size_ms ) / 20;
160 :
161 0 : if ( ( error = isar_splitBinLCLDEncOpen( &hSplitBinRend->hSplitBinLCLDEnc, output_Fs, BINAURAL_CHANNELS, isar_get_lcld_bitrate( pSplitRendConfig->splitRendBitRate, hSplitBinRend->multiBinPoseData.poseCorrectionMode ), iNumBlocksPerFrame, 1 ) ) != IVAS_ERR_OK )
162 : {
163 0 : return error;
164 : }
165 : }
166 : }
167 :
168 0 : return IVAS_ERR_OK;
169 : }
170 :
171 :
172 : /*-------------------------------------------------------------------------
173 : * Function ISAR_PRE_REND_close()
174 : *
175 : *
176 : *------------------------------------------------------------------------*/
177 :
178 0 : void ISAR_PRE_REND_close(
179 : SPLIT_REND_WRAPPER *hSplitBinRend, /* i/o: Split renderer pre-renderer handle */
180 : IVAS_REND_AudioBuffer *pSplitRendEncBuffer /* i/o: Split renderer data buffer */
181 : )
182 : {
183 : int16_t i;
184 :
185 0 : if ( hSplitBinRend->hBinHrSplitPreRend != NULL )
186 : {
187 0 : isar_splitBinPreRendClose( &hSplitBinRend->hBinHrSplitPreRend );
188 : }
189 :
190 0 : if ( hSplitBinRend->hSplitBinLCLDEnc != NULL )
191 : {
192 0 : isar_splitBinLCLDEncClose( &hSplitBinRend->hSplitBinLCLDEnc );
193 : }
194 :
195 0 : if ( hSplitBinRend->hCldfbHandles != NULL )
196 : {
197 : int16_t num_ch, ch;
198 0 : num_ch = MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS;
199 0 : for ( ch = 0; ch < num_ch; ch++ )
200 : {
201 0 : if ( hSplitBinRend->hCldfbHandles->cldfbAna[ch] != NULL )
202 : {
203 0 : deleteCldfb( &hSplitBinRend->hCldfbHandles->cldfbAna[ch] );
204 0 : hSplitBinRend->hCldfbHandles->cldfbAna[ch] = NULL;
205 : }
206 : }
207 :
208 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
209 : {
210 0 : if ( hSplitBinRend->hCldfbHandles->cldfbSyn[ch] != NULL )
211 : {
212 0 : deleteCldfb( &hSplitBinRend->hCldfbHandles->cldfbSyn[ch] );
213 0 : hSplitBinRend->hCldfbHandles->cldfbSyn[ch] = NULL;
214 : }
215 : }
216 :
217 0 : free( hSplitBinRend->hCldfbHandles );
218 0 : hSplitBinRend->hCldfbHandles = NULL;
219 : }
220 :
221 0 : if ( hSplitBinRend->hLc3plusEnc != NULL )
222 : {
223 0 : ISAR_LC3PLUS_ENC_Close( &hSplitBinRend->hLc3plusEnc );
224 : }
225 :
226 0 : for ( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; ++i )
227 : {
228 0 : if ( hSplitBinRend->lc3plusDelayBuffers[i] != NULL )
229 : {
230 0 : free( hSplitBinRend->lc3plusDelayBuffers[i] );
231 0 : hSplitBinRend->lc3plusDelayBuffers[i] = NULL;
232 : }
233 : }
234 :
235 0 : if ( pSplitRendEncBuffer != NULL )
236 : {
237 :
238 0 : if ( pSplitRendEncBuffer->data != NULL )
239 : {
240 0 : free( pSplitRendEncBuffer->data );
241 0 : pSplitRendEncBuffer->data = NULL;
242 : }
243 :
244 0 : pSplitRendEncBuffer->config.numChannels = 0;
245 0 : pSplitRendEncBuffer->config.numSamplesPerChannel = 0;
246 : }
247 :
248 0 : return;
249 : }
250 :
251 :
252 : /*-------------------------------------------------------------------------*
253 : * ISAR_PRE_REND_GetMultiBinPoseData()
254 : *
255 : *
256 : *-------------------------------------------------------------------------*/
257 :
258 0 : void ISAR_PRE_REND_GetMultiBinPoseData(
259 : const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, /* i : Split renderer pre-renderer config */
260 : MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */
261 : const ISAR_SPLIT_REND_ROT_AXIS rot_axis /* i : Rotation axis */
262 : )
263 : {
264 0 : isar_renderSplitGetMultiBinPoseData( pSplit_rend_config, pMultiBinPoseData, rot_axis );
265 :
266 0 : return;
267 : }
268 :
269 :
270 : /*-------------------------------------------------------------------------
271 : * Function ISAR_PRE_REND_MultiBinToSplitBinaural()
272 : *
273 : *
274 : *------------------------------------------------------------------------*/
275 :
276 0 : ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural(
277 : SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renerer handle */
278 : const IVAS_QUATERNION headPosition, /* i : head rotation QUATERNION */
279 : const int32_t SplitRendBitRate, /* i : Split renderer bitrate */
280 : ISAR_SPLIT_REND_CODEC splitCodec, /* i/o: Split renderer codec */
281 : const int16_t isar_frame_size_ms, /* i : ISAR framesize */
282 : int16_t codec_frame_size_ms, /* i/o: ISAR transport codec framesize */
283 : ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits struct handle */
284 : float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB real buffer */
285 : float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB imag buffer */
286 : const int16_t max_bands, /* i : CLDFB bands */
287 : float *output[], /* i/o: PCM in/out buffer */
288 : const int16_t low_res_pre_rend_rot, /* i : low time resolution pre-renderer flag */
289 : const int16_t cldfb_in_flag, /* i : Flag to indicate CLDFB or time doamin input */
290 : const int16_t pcm_out_flag, /* i : Flag to indicate PCM output */
291 : const int16_t ro_md_flag /* i : Flag to indicate real only metadata for yaw */
292 : )
293 : {
294 : ivas_error error;
295 : int32_t bit_len, target_md_bits, available_bits;
296 :
297 0 : error = IVAS_ERR_OK;
298 0 : push_wmops( "isar_pre_rend_MultiBinToSplitBinaural" );
299 :
300 0 : if ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB )
301 : {
302 0 : set_fix_rotation_mat( hSplitBin->hBinHrSplitPreRend->fix_pos_rot_mat, &hSplitBin->multiBinPoseData );
303 0 : set_pose_types( hSplitBin->hBinHrSplitPreRend->pose_type, &hSplitBin->multiBinPoseData );
304 : }
305 :
306 0 : if ( cldfb_in_flag == 0 )
307 : {
308 : /*TD input*/
309 : /*if CLDFB handles have been allocated then assume valid multi binaural input in out[][] buffer and perform CLDFB analysis*/
310 0 : error = isar_renderMultiTDBinToSplitBinaural( hSplitBin, headPosition, SplitRendBitRate, isar_frame_size_ms, codec_frame_size_ms, pBits, max_bands, output, low_res_pre_rend_rot, pcm_out_flag, ro_md_flag );
311 :
312 0 : pop_wmops();
313 0 : return error;
314 : }
315 :
316 0 : if ( splitCodec == ISAR_SPLIT_REND_CODEC_LC3PLUS && hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB )
317 : {
318 : /* Time-align pose correction to delay of LC3plus */
319 0 : lc3plusTimeAlignCldfbPoseCorr( hSplitBin, Cldfb_In_BinReal, Cldfb_In_BinImag );
320 : }
321 :
322 0 : if ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB )
323 : {
324 0 : target_md_bits = isar_get_split_rend_md_target_brate( SplitRendBitRate, pcm_out_flag ) * L_FRAME48k / 48000;
325 :
326 :
327 0 : isar_rend_CldfbSplitPreRendProcess( hSplitBin->hBinHrSplitPreRend, headPosition, &hSplitBin->multiBinPoseData, Cldfb_In_BinReal, Cldfb_In_BinImag, pBits, target_md_bits, low_res_pre_rend_rot, ro_md_flag );
328 : }
329 :
330 0 : if ( pcm_out_flag == 0 )
331 : {
332 0 : pBits->codec = splitCodec;
333 0 : pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode;
334 :
335 0 : if ( splitCodec == ISAR_SPLIT_REND_CODEC_LCLD )
336 : {
337 0 : available_bits = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC );
338 0 : available_bits -= pBits->bits_written;
339 0 : pBits->codec_frame_size_ms = codec_frame_size_ms;
340 0 : isar_splitBinLCLDEncProcess( hSplitBin->hSplitBinLCLDEnc, Cldfb_In_BinReal, Cldfb_In_BinImag, available_bits, pBits );
341 : }
342 : else
343 : {
344 : int16_t ch, slot_idx, num_slots, ivas_fs;
345 0 : ivas_fs = (int16_t) hSplitBin->hLc3plusEnc->config.isar_frame_duration_us / 1000;
346 0 : num_slots = (int16_t) ( CLDFB_NO_COL_MAX * ivas_fs ) / 20;
347 : /* CLDFB synthesis of main pose */
348 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
349 : {
350 : float *Cldfb_In_BinReal_p[CLDFB_NO_COL_MAX];
351 : float *Cldfb_In_BinImag_p[CLDFB_NO_COL_MAX];
352 :
353 0 : for ( slot_idx = 0; slot_idx < num_slots; slot_idx++ )
354 : {
355 0 : Cldfb_In_BinReal_p[slot_idx] = Cldfb_In_BinReal[ch][slot_idx];
356 0 : Cldfb_In_BinImag_p[slot_idx] = Cldfb_In_BinImag[ch][slot_idx];
357 : }
358 :
359 0 : cldfbSynthesis( Cldfb_In_BinReal_p, Cldfb_In_BinImag_p, output[ch], hSplitBin->hCldfbHandles->cldfbSyn[0]->no_channels * num_slots, hSplitBin->hCldfbHandles->cldfbSyn[ch] );
360 : }
361 :
362 0 : if ( pBits->pose_correction == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE )
363 : {
364 0 : available_bits = isar_get_lc3plus_bitrate( SplitRendBitRate, hSplitBin->multiBinPoseData.poseCorrectionMode, hSplitBin->hLc3plusEnc->config.channels, hSplitBin->hLc3plusEnc->config.lc3plus_frame_duration_us ) / FRAMES_PER_SEC;
365 : }
366 : else
367 : {
368 0 : available_bits = ( SplitRendBitRate / FRAMES_PER_SEC ) - pBits->bits_written;
369 : }
370 :
371 0 : if ( ( error = splitRendLc3plusEncodeAndWrite( hSplitBin, pBits, available_bits, output ) ) != IVAS_ERR_OK )
372 : {
373 0 : return error;
374 : }
375 : }
376 : }
377 : else
378 : {
379 : int16_t ch, slot_idx;
380 : /* CLDFB synthesis of main pose */
381 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
382 : {
383 : float *Cldfb_In_BinReal_p[CLDFB_NO_COL_MAX];
384 : float *Cldfb_In_BinImag_p[CLDFB_NO_COL_MAX];
385 :
386 0 : for ( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX; slot_idx++ )
387 : {
388 0 : Cldfb_In_BinReal_p[slot_idx] = Cldfb_In_BinReal[ch][slot_idx];
389 0 : Cldfb_In_BinImag_p[slot_idx] = Cldfb_In_BinImag[ch][slot_idx];
390 : }
391 :
392 0 : cldfbSynthesis( Cldfb_In_BinReal_p, Cldfb_In_BinImag_p, output[ch], hSplitBin->hCldfbHandles->cldfbSyn[0]->no_channels * CLDFB_NO_COL_MAX, hSplitBin->hCldfbHandles->cldfbSyn[ch] );
393 : }
394 :
395 0 : pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode;
396 0 : pBits->codec = ISAR_SPLIT_REND_CODEC_NONE;
397 : }
398 :
399 : /*zero pad*/
400 0 : if ( pcm_out_flag )
401 : {
402 0 : bit_len = SplitRendBitRate / FRAMES_PER_SEC;
403 : }
404 : else
405 : {
406 0 : if ( splitCodec == ISAR_SPLIT_REND_CODEC_LCLD )
407 : {
408 0 : bit_len = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC );
409 : }
410 : else
411 : {
412 0 : bit_len = hSplitBin->hLc3plusEnc->config.isar_frame_duration_us / 1000;
413 0 : bit_len = SplitRendBitRate * bit_len / 1000;
414 : }
415 : }
416 :
417 0 : while ( pBits->bits_written < bit_len )
418 : {
419 0 : ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0L, 1 );
420 : }
421 :
422 0 : pop_wmops();
423 :
424 0 : return error;
425 : }
|