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 "prot_fx.h"
36 : #include "ivas_prot_rend_fx.h"
37 : #include <math.h>
38 : #include "ivas_rom_com.h"
39 : #include "wmc_auto.h"
40 : #include "ivas_prot_fx.h"
41 : #include "debug.h"
42 :
43 :
44 : /*---------------------------------------------------------------------*
45 : * ivas_td_binaural_open()
46 : *
47 : * Open and initialize TD Object binaural renderer
48 : *---------------------------------------------------------------------*/
49 108 : ivas_error ivas_td_binaural_open_fx(
50 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
51 : Word16 *SrcInd, /*Temporarily used to store the updated value of SrcInd*/
52 : Word16 *num_src )
53 : {
54 108 : *num_src = st_ivas->nchan_transport;
55 108 : move16();
56 108 : test();
57 108 : if ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) )
58 : {
59 84 : *num_src = st_ivas->nchan_ism;
60 84 : move16();
61 : }
62 108 : return ivas_td_binaural_open_unwrap_fx( &st_ivas->hHrtfTD, st_ivas->hDecoderConfig->output_Fs, *num_src, st_ivas->ivas_format, st_ivas->transport_config, st_ivas->hRenderConfig->directivity_fx, st_ivas->hTransSetup, &st_ivas->hBinRendererTd, &st_ivas->binaural_latency_ns, SrcInd );
63 : }
64 :
65 :
66 : /*---------------------------------------------------------------------*
67 : * ivas_td_binaural_renderer()
68 : *
69 : * Receives the current frames for the object streams, updates metadata
70 : * and renders the current frame.
71 : *---------------------------------------------------------------------*/
72 :
73 0 : ivas_error ivas_td_binaural_renderer_fx(
74 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
75 : Word32 *output[], /* i/o: SCE channels / Binaural synthesis Q11*/
76 : const Word16 output_frame /* i : output frame length */
77 : )
78 : {
79 : Word16 ism_md_subframe_update;
80 : Word16 nchan_transport;
81 0 : test();
82 0 : IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) )
83 : {
84 0 : nchan_transport = st_ivas->nchan_ism;
85 : }
86 : ELSE
87 : {
88 0 : nchan_transport = st_ivas->nchan_transport;
89 : }
90 0 : move16();
91 :
92 0 : IF( st_ivas->hDecoderConfig->Opt_delay_comp )
93 : {
94 0 : ism_md_subframe_update = 1;
95 : }
96 : ELSE
97 : {
98 0 : ism_md_subframe_update = 2;
99 : }
100 0 : move16();
101 :
102 0 : if ( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
103 : {
104 0 : ism_md_subframe_update = 2;
105 0 : move16();
106 : }
107 0 : return ivas_td_binaural_renderer_unwrap_fx( st_ivas->hReverb, st_ivas->transport_config, st_ivas->hBinRendererTd, nchan_transport, LFE_CHANNEL, st_ivas->ivas_format, st_ivas->hIsmMetaData, st_ivas->hCombinedOrientationData, ism_md_subframe_update, output, output_frame, MAX_PARAM_SPATIAL_SUBFRAMES );
108 : }
109 :
110 :
111 : /*---------------------------------------------------------------------*
112 : * ivas_td_binaural_renderer_sf()
113 : *
114 : * Receives the current frames for the object streams, updates metadata
115 : * and renders the current frame.
116 : *---------------------------------------------------------------------*/
117 :
118 36345 : ivas_error ivas_td_binaural_renderer_sf_fx(
119 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
120 : Word32 *output_fx[], /* i/o: SCE channels / Binaural synthesis Q11*/
121 : const Word16 n_samples_granularity /* i : granularity of the renderer/buffer */
122 : )
123 : {
124 : Word16 first_sf, last_sf, subframe_idx;
125 : Word32 *output_fx_local[BINAURAL_CHANNELS];
126 : Word32 reverb_signal_fx[BINAURAL_CHANNELS][L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES];
127 : Word32 *p_reverb_signal_fx[BINAURAL_CHANNELS];
128 : Word32 *tc_local_fx[MAX_TRANSPORT_CHANNELS];
129 : Word16 ch, slot_size, slots_to_render, output_frame, tmp;
130 : ivas_error error;
131 :
132 : Word16 ism_md_subframe_update_jbm;
133 : Word16 c_indx, nS, i;
134 : Word16 nchan_ism_internal, nchan_ism, ch_offset;
135 :
136 : IVAS_QUATERNION *tmp_Quaternion_fx;
137 : IVAS_VECTOR3 *tmp_vector_fx;
138 : Word16 enableCombinedOrientation;
139 :
140 : /* Set the number of ISMs */
141 36345 : IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
142 : {
143 126 : nchan_ism_internal = st_ivas->nchan_ism;
144 126 : move16();
145 126 : nchan_ism = st_ivas->nchan_ism;
146 126 : move16();
147 126 : ch_offset = 2;
148 126 : move16();
149 : }
150 36219 : ELSE IF( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) )
151 : {
152 4689 : nchan_ism_internal = st_ivas->nchan_ism;
153 4689 : move16();
154 4689 : nchan_ism = st_ivas->nchan_ism;
155 4689 : move16();
156 4689 : ch_offset = 0;
157 4689 : move16();
158 : }
159 : ELSE
160 : {
161 31530 : nchan_ism_internal = st_ivas->hTcBuffer->nchan_transport_internal;
162 31530 : move16();
163 31530 : nchan_ism = st_ivas->nchan_transport;
164 31530 : move16();
165 31530 : ch_offset = 0;
166 31530 : move16();
167 : }
168 :
169 : /* Number of subframes to delay metadata to sync with audio */
170 36345 : IF( st_ivas->hDecoderConfig->Opt_delay_comp )
171 : {
172 36345 : ism_md_subframe_update_jbm = s_max( 0, sub( st_ivas->hTcBuffer->nb_subframes, 3 ) );
173 : }
174 : ELSE
175 : {
176 0 : ism_md_subframe_update_jbm = sub( st_ivas->hTcBuffer->nb_subframes, 2 );
177 : }
178 :
179 36345 : IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
180 : {
181 126 : ism_md_subframe_update_jbm = s_max( 0, sub( st_ivas->hTcBuffer->nb_subframes, 2 ) );
182 : }
183 :
184 109035 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
185 : {
186 72690 : p_reverb_signal_fx[ch] = reverb_signal_fx[ch];
187 : }
188 151607 : FOR( ch = 0; ch < nchan_ism_internal; ch++ )
189 : {
190 115262 : tc_local_fx[ch] = st_ivas->hTcBuffer->tc_fx[ch + ch_offset] + st_ivas->hTcBuffer->n_samples_rendered;
191 : }
192 :
193 109035 : FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ )
194 : {
195 72690 : output_fx_local[ch] = output_fx[ch]; // Q11
196 : }
197 :
198 36345 : slot_size = st_ivas->hTcBuffer->n_samples_granularity;
199 36345 : move16();
200 :
201 : /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */
202 36345 : tmp = 0;
203 36345 : move16();
204 36345 : IF( n_samples_granularity != 0 )
205 : {
206 36345 : tmp = idiv1616( n_samples_granularity, slot_size );
207 : }
208 36345 : slots_to_render = s_min( sub( st_ivas->hTcBuffer->num_slots, st_ivas->hTcBuffer->slots_rendered ), tmp );
209 36345 : first_sf = st_ivas->hTcBuffer->subframes_rendered;
210 36345 : move16();
211 36345 : last_sf = first_sf;
212 36345 : move16();
213 36345 : st_ivas->hTcBuffer->slots_rendered = add( st_ivas->hTcBuffer->slots_rendered, slots_to_render );
214 36345 : move16();
215 :
216 181630 : WHILE( slots_to_render > 0 )
217 : {
218 145285 : slots_to_render = sub( slots_to_render, st_ivas->hTcBuffer->subframe_nbslots[last_sf] );
219 145285 : last_sf = add( last_sf, 1 );
220 : }
221 :
222 181630 : FOR( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
223 : {
224 145285 : output_frame = i_mult( st_ivas->hTcBuffer->subframe_nbslots[subframe_idx], st_ivas->hTcBuffer->n_samples_granularity );
225 :
226 : /* Update object position(s) */
227 145285 : c_indx = 0;
228 145285 : move16();
229 :
230 606007 : FOR( nS = 0; nS < nchan_ism; nS++ )
231 : {
232 460722 : test();
233 460722 : IF( !( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_16( nS, LFE_CHANNEL ) ) ) /* Skip LFE for MC */
234 : {
235 448482 : st_ivas->hBinRendererTd->Sources[c_indx]->InputFrame_p_fx = tc_local_fx[nS]; /* Q11 */
236 448482 : st_ivas->hBinRendererTd->Sources[c_indx]->SrcRend_p->InputAvailable = TRUE;
237 448482 : move16();
238 448482 : c_indx = add( c_indx, 1 );
239 : }
240 : }
241 :
242 145285 : IF( EQ_16( subframe_idx, ism_md_subframe_update_jbm ) )
243 : {
244 36331 : IF( ( error = TDREND_Update_object_positions_fx( st_ivas->hBinRendererTd, nchan_ism, st_ivas->ivas_format, st_ivas->hIsmMetaData ) ) != IVAS_ERR_OK )
245 : {
246 0 : return error;
247 : }
248 : }
249 :
250 : /* Update the listener's location/orientation */
251 145285 : IF( st_ivas->hCombinedOrientationData != NULL )
252 : {
253 84840 : tmp_Quaternion_fx = &st_ivas->hCombinedOrientationData->Quaternions[st_ivas->hCombinedOrientationData->subframe_idx];
254 84840 : tmp_vector_fx = &st_ivas->hCombinedOrientationData->listenerPos[st_ivas->hCombinedOrientationData->subframe_idx];
255 84840 : enableCombinedOrientation = st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx];
256 84840 : move16();
257 :
258 : /* Shifting x_fx, y_fx, z_fx to the same Q-factor as Listener_p->Pos_q (usually Q25) */
259 84840 : Word16 pos_q = st_ivas->hBinRendererTd->Listener_p->Pos_q;
260 84840 : move16();
261 84840 : tmp_vector_fx->x_fx = L_shr( tmp_vector_fx->x_fx, sub( tmp_vector_fx->q_fact, pos_q ) );
262 84840 : tmp_vector_fx->y_fx = L_shr( tmp_vector_fx->y_fx, sub( tmp_vector_fx->q_fact, pos_q ) );
263 84840 : tmp_vector_fx->z_fx = L_shr( tmp_vector_fx->z_fx, sub( tmp_vector_fx->q_fact, pos_q ) );
264 84840 : tmp_vector_fx->q_fact = pos_q;
265 84840 : move16();
266 : }
267 : ELSE
268 : {
269 60445 : tmp_Quaternion_fx = NULL;
270 60445 : tmp_vector_fx = NULL;
271 60445 : enableCombinedOrientation = 0;
272 60445 : move16();
273 : }
274 :
275 145285 : IF( NE_32( ( error = TDREND_Update_listener_orientation_fx( st_ivas->hBinRendererTd,
276 : enableCombinedOrientation,
277 : tmp_Quaternion_fx,
278 : tmp_vector_fx ) ),
279 : IVAS_ERR_OK ) )
280 : {
281 0 : return error;
282 : }
283 :
284 145285 : test();
285 145285 : IF( st_ivas->hRenderConfig != NULL && EQ_32( st_ivas->hIntSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
286 : {
287 20000 : FOR( i = 0; i < nchan_ism_internal; ++i )
288 : {
289 16000 : scale_sig32( tc_local_fx[i], st_ivas->hReverb->full_block_size, -4 ); // Q11 - 4 = Q7
290 : }
291 :
292 4000 : IF( NE_32( ( error = ivas_reverb_process_fx( st_ivas->hReverb, st_ivas->transport_config, 0, tc_local_fx, p_reverb_signal_fx, 0 ) ), IVAS_ERR_OK ) ) // Q(p_reverb_signal_fx) = 11
293 : {
294 0 : return error;
295 : }
296 :
297 20000 : FOR( i = 0; i < nchan_ism_internal; ++i )
298 : {
299 16000 : scale_sig32( tc_local_fx[i], st_ivas->hReverb->full_block_size, 4 ); // Q7 + 4 = Q11
300 : }
301 :
302 12000 : FOR( i = 0; i < BINAURAL_CHANNELS; ++i )
303 : {
304 8000 : scale_sig32( p_reverb_signal_fx[i], st_ivas->hReverb->full_block_size, 2 + 4 ); // Q5 + 6 = Q11
305 : }
306 : }
307 :
308 : /* Render subframe */
309 : /* ism_md_subframe_update_jbm != subframe_idx: trigger update only for ism_md_subframe_update_jbm == subframe_idx,
310 : where then the two TDREND_GetMix()-arguments subframe_idx and ism_md_subframe_update are equal, and we want to enforce the update inside TDREND_GetMix to use subframe_idx == 0 */
311 145285 : IF( NE_32( ( error = TDREND_GetMix_fx( st_ivas->hBinRendererTd, output_fx_local, output_frame, 0, ism_md_subframe_update_jbm != subframe_idx ) ), IVAS_ERR_OK ) )
312 : {
313 0 : return error;
314 : }
315 :
316 145285 : test();
317 145285 : IF( st_ivas->hRenderConfig != NULL && EQ_32( st_ivas->hIntSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
318 : {
319 : /* add reverb to rendered signals */
320 4000 : v_add_32( reverb_signal_fx[0], output_fx_local[0], output_fx_local[0], output_frame ); // Q11
321 4000 : v_add_32( reverb_signal_fx[1], output_fx_local[1], output_fx_local[1], output_frame );
322 : }
323 :
324 606007 : FOR( ch = 0; ch < nchan_ism_internal; ch++ )
325 : {
326 460722 : tc_local_fx[ch] += output_frame;
327 : }
328 :
329 435855 : FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ )
330 : {
331 290570 : output_fx_local[ch] += output_frame;
332 : }
333 :
334 : /* update combined orientation access index */
335 145285 : ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, output_frame );
336 : }
337 :
338 36345 : st_ivas->hTcBuffer->subframes_rendered = last_sf;
339 36345 : move16();
340 :
341 36345 : return IVAS_ERR_OK;
342 : }
|