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 <assert.h>
36 : #include <math.h>
37 : #include "prot.h"
38 : #include "ivas_prot.h"
39 : #include "ivas_prot_rend.h"
40 : #include "ivas_cnst.h"
41 : #include "ivas_rom_binauralRenderer.h"
42 : #include "ivas_rom_rend.h"
43 : #include "ivas_rom_com.h"
44 :
45 : #ifdef DEBUGGING
46 : #include "debug.h"
47 : #endif
48 : #include "wmc_auto.h"
49 :
50 :
51 : /*-------------------------------------------------------------------------
52 : * Local constants
53 : *------------------------------------------------------------------------*/
54 :
55 : #define CLDFB_HALF_BIN_FREQUENCY_OFFSET 0.5f
56 : #define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN ( 2.0f )
57 : #define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN_LOW_BR ( 3.0f )
58 : #define SBA_CARDI_TARGET_ENERGY_GAIN 0.5f
59 :
60 : #define STEREO_PREPROCESS_IIR_FACTOR ( 0.9f )
61 :
62 : /* powf(0.95f, 4.0f) for sub-frame smoothing instead of CLDFB slot */
63 : #define ADAPT_HTPROTO_IIR_FAC 0.81450625f
64 :
65 : #define ADAPT_HTPROTO_ILD_LIM_DB0 1.0f
66 : #define ADAPT_HTPROTO_ILD_LIM_DB1 4.0f
67 : #define ADAPT_HTPROTO_ROT_LIM_0 0.4f
68 : #define ADAPT_HTPROTO_ROT_LIM_1 0.8f
69 :
70 : #define MAX_GAIN_CACHE_SIZE ( ( MASA_MAXIMUM_DIRECTIONS * 3 ) + MAX_NUM_OBJECTS ) /* == different calls to get gains */
71 :
72 : typedef struct hrtfGainCache
73 : {
74 : int16_t azi;
75 : int16_t ele;
76 :
77 : float shVec[HRTF_SH_CHANNELS];
78 : } PARAMBIN_HRTF_GAIN_CACHE;
79 :
80 : typedef struct parambin_rend_config_data
81 : {
82 : int16_t separateCenterChannelRendering;
83 : IVAS_FORMAT ivas_format;
84 : MC_MODE mc_mode;
85 : int32_t ivas_total_brate;
86 : int16_t nchan_transport;
87 : float qualityBasedSmFactor;
88 : int16_t processReverb;
89 : ISM_MODE ism_mode;
90 : } PARAMBIN_REND_CONFIG, *PARAMBIN_REND_CONFIG_HANDLE;
91 :
92 :
93 : /*-------------------------------------------------------------------------
94 : * Local function prototypes
95 : *------------------------------------------------------------------------*/
96 :
97 : static void ivas_dirac_dec_binaural_internal( Decoder_Struct *st_ivas, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, float *output_f[], const int16_t nchan_transport, const int16_t subframe );
98 :
99 : static void ivas_dirac_dec_decorrelate_slot( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const int16_t num_freq_bands, const int16_t slot, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float decRe[][CLDFB_NO_CHANNELS_MAX], float decIm[][CLDFB_NO_CHANNELS_MAX] );
100 :
101 : static void ivas_dirac_dec_binaural_formulate_input_covariance_matrices( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, const PARAMBIN_REND_CONFIG_HANDLE hConfig, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t subframe, float *subFrameTotalEne, float *IIReneLimiter );
102 :
103 : static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, const PARAMBIN_REND_CONFIG_HANDLE hConfig, float Rmat[3][3], const int16_t subframe, const int16_t isHeadtracked, const float *subFrameTotalEne, const float *IIReneLimiter, const MASA_ISM_DATA_HANDLE hMasaIsmData );
104 :
105 : static void ivas_dirac_dec_binaural_determine_processing_matrices( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, const int16_t max_band_decorr, float Rmat[3][3], const int16_t subframe, const int16_t isHeadtracked, const int16_t nchanSeparateChannels, const MASA_ISM_DATA_HANDLE hMasaIsmData );
106 :
107 : static void ivas_dirac_dec_binaural_process_output( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], float *output_f[], float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, const int16_t numInChannels, const int16_t processReverb, const int16_t subframe, float outRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float outIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float reverbRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float reverbIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float decorrRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float decorrIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const uint8_t recompute );
108 :
109 : static void adaptTransportSignalsHeadtracked( COMBINED_ORIENTATION_HANDLE hHeadTrackData, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nBins, const int16_t nSlots, float Rmat[3][3] );
110 :
111 : static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( COMBINED_ORIENTATION_HANDLE hHeadTrackData, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nBins, const int16_t nSlots, float Rmat[3][3] );
112 :
113 : static void formulate2x2MixingMatrix( float Ein1, float Ein2, float CinRe, float CinIm, float Eout1, float Eout2, float CoutRe, float CoutIm, float Q[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Mre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Mim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], const float regularizationFactor );
114 :
115 : static void hrtfShGetHrtf( const int16_t bin, const int16_t aziDeg, const int16_t eleDeg, float *lRealp, float *lImagp, float *rRealp, float *rImagp, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const int16_t useCachedValue, HRTFS_PARAMBIN_HANDLE hHrtfParambin );
116 :
117 : static void getDirectPartGains( const int16_t bin, int16_t aziDeg, int16_t eleDeg, float *lRealp, float *lImagp, float *rRealp, float *rImagp, const uint8_t stereoMode, float Rmat[3][3], PARAMBIN_HRTF_GAIN_CACHE *gainCache, const int16_t isHeadtracked, HRTFS_PARAMBIN_HANDLE hHrtfParambin );
118 :
119 : static void matrixMul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] );
120 :
121 : static void matrixTransp2Mul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] );
122 :
123 : static void ivas_masa_ext_rend_parambin_internal( MASA_EXT_REND_HANDLE hMasaExtRend, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, float *output_f[], const int16_t subframe, const SPLIT_REND_WRAPPER *hSplitRendWrapper, float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] );
124 :
125 :
126 : /*-------------------------------------------------------------------------
127 : * ivas_dirac_dec_init_binaural_data()
128 : *
129 : * Initialize parametric binaural renderer
130 : *------------------------------------------------------------------------*/
131 :
132 1224 : ivas_error ivas_dirac_dec_init_binaural_data(
133 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
134 : HRTFS_PARAMBIN_HANDLE *phHrtfParambin /* i : HRTF structure for rendering */
135 : )
136 : {
137 : DIRAC_DEC_BIN_HANDLE hDiracDecBin;
138 : int16_t nBins;
139 : int32_t output_Fs;
140 : RENDERER_TYPE renderer_type;
141 : int16_t j, k, bin;
142 : float binCenterFreq, tmpFloat;
143 : ivas_error error;
144 : float frequency_axis[CLDFB_NO_CHANNELS_MAX];
145 : int16_t num_poses, pos_idx;
146 : const IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pRoomAcoustics;
147 :
148 1224 : num_poses = 1;
149 1224 : if ( st_ivas->hSplitBinRend != NULL )
150 : {
151 480 : num_poses = st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses;
152 : }
153 :
154 1224 : output_Fs = st_ivas->hDecoderConfig->output_Fs;
155 1224 : nBins = st_ivas->hSpatParamRendCom->num_freq_bands;
156 1224 : renderer_type = st_ivas->renderer_type;
157 :
158 3920 : for ( pos_idx = 0; pos_idx < num_poses; pos_idx++ )
159 : {
160 2696 : hDiracDecBin = st_ivas->hDiracDecBin[pos_idx];
161 :
162 2696 : if ( hDiracDecBin == NULL )
163 : {
164 2696 : if ( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL )
165 : {
166 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " );
167 : }
168 :
169 2696 : hDiracDecBin->hTdDecorr = NULL;
170 2696 : hDiracDecBin->hReverb = NULL;
171 2696 : hDiracDecBin->h_freq_domain_decorr_ap_params = NULL;
172 2696 : hDiracDecBin->h_freq_domain_decorr_ap_state = NULL;
173 2696 : hDiracDecBin->phHrtfParambin = NULL;
174 : }
175 :
176 8088 : for ( j = 0; j < BINAURAL_CHANNELS; j++ )
177 : {
178 37744 : for ( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ )
179 : {
180 32352 : set_zero( hDiracDecBin->processMtxRe[j][k], nBins );
181 32352 : set_zero( hDiracDecBin->processMtxIm[j][k], nBins );
182 : }
183 :
184 16176 : for ( k = 0; k < BINAURAL_CHANNELS; k++ )
185 : {
186 10784 : set_zero( hDiracDecBin->processMtxDecRe[j][k], nBins );
187 10784 : set_zero( hDiracDecBin->processMtxDecIm[j][k], nBins );
188 : }
189 5392 : set_zero( hDiracDecBin->ChEnePrev[j], nBins );
190 5392 : set_zero( hDiracDecBin->ChEneOutPrev[j], nBins );
191 : }
192 2696 : set_zero( hDiracDecBin->ChCrossRePrev, nBins );
193 2696 : set_zero( hDiracDecBin->ChCrossImPrev, nBins );
194 2696 : set_zero( hDiracDecBin->ChCrossReOutPrev, nBins );
195 2696 : set_zero( hDiracDecBin->ChCrossImOutPrev, nBins );
196 2696 : hDiracDecBin->renderStereoOutputInsteadOfBinaural = 0;
197 :
198 :
199 158496 : for ( bin = 0; bin < nBins; bin++ )
200 : {
201 155800 : binCenterFreq = ( (float) bin + CLDFB_HALF_BIN_FREQUENCY_OFFSET ) / (float) nBins * ( (float) output_Fs / 2.0f );
202 : /* These formulas and values are from Christian Borss's publication for binaural diffuse field coherence */
203 155800 : tmpFloat = max( 0.0f, 1.0f - binCenterFreq / 2700.0f );
204 155800 : hDiracDecBin->diffuseFieldCoherence[bin] = tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f );
205 : }
206 :
207 26960 : for ( bin = 0; bin < BINAURAL_COHERENCE_DIFFERENCE_BINS; bin++ )
208 : {
209 24264 : hDiracDecBin->diffuseFieldCoherenceX[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceX[bin];
210 24264 : hDiracDecBin->diffuseFieldCoherenceY[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceY[bin];
211 24264 : hDiracDecBin->diffuseFieldCoherenceZ[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceZ[bin];
212 : }
213 :
214 2696 : if ( renderer_type == RENDERER_BINAURAL_PARAMETRIC ) /* Indication of binaural rendering without room effect */
215 : {
216 2332 : set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX );
217 2332 : hDiracDecBin->hReverb = NULL;
218 : }
219 364 : else if ( renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) /* Indication of binaural rendering with room effect */
220 : {
221 353 : if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR )
222 : {
223 238 : mvr2r( ( *phHrtfParambin )->parametricEarlyPartEneCorrection, hDiracDecBin->earlyPartEneCorrection, nBins );
224 238 : pRoomAcoustics = NULL;
225 : }
226 : else
227 : {
228 115 : set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX );
229 115 : pRoomAcoustics = &( st_ivas->hRenderConfig->roomAcoustics );
230 : }
231 :
232 : /* reconfiguration needed when Reverb. parameters are changed -> close and open the handle again */
233 353 : if ( hDiracDecBin->hReverb != NULL && ( ( hDiracDecBin->hReverb->numBins != nBins ) ||
234 0 : ( hDiracDecBin->hReverb->blockSize != CLDFB_SLOTS_PER_SUBFRAME ) ) )
235 : {
236 0 : ivas_binaural_reverb_close( &( hDiracDecBin->hReverb ) );
237 : }
238 :
239 353 : if ( hDiracDecBin->hReverb == NULL && pos_idx == 0 ) /* open reverb only for the main direction */
240 : {
241 353 : if ( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb,
242 : st_ivas->hHrtfStatistics,
243 : nBins,
244 : CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES,
245 : pRoomAcoustics,
246 : output_Fs,
247 353 : ( *phHrtfParambin )->parametricReverberationTimes,
248 353 : ( *phHrtfParambin )->parametricReverberationEneCorrections,
249 353 : hDiracDecBin->earlyPartEneCorrection ) ) != IVAS_ERR_OK )
250 : {
251 0 : return error;
252 : }
253 : }
254 : }
255 11 : else if ( renderer_type == RENDERER_STEREO_PARAMETRIC )
256 : {
257 11 : set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX );
258 11 : hDiracDecBin->hReverb = NULL;
259 11 : hDiracDecBin->renderStereoOutputInsteadOfBinaural = 1;
260 : }
261 : else /* Not valid renderer type for this renderer */
262 : {
263 0 : assert( false );
264 : }
265 :
266 2696 : hDiracDecBin->hDiffuseDist = NULL; /* Memory is allocated from stack during runtime when needed */
267 :
268 2696 : if ( hDiracDecBin->hTdDecorr == NULL )
269 : {
270 2696 : hDiracDecBin->useTdDecorr = 0;
271 : }
272 :
273 2696 : if ( hDiracDecBin->h_freq_domain_decorr_ap_params != NULL )
274 : {
275 0 : ivas_dirac_dec_decorr_close( &hDiracDecBin->h_freq_domain_decorr_ap_params, &hDiracDecBin->h_freq_domain_decorr_ap_state );
276 : }
277 :
278 2696 : if ( pos_idx == 0 ) /* open decorrelator only for the main direction */
279 : {
280 1224 : if ( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( hDiracDecBin->hTdDecorr ), &( hDiracDecBin->useTdDecorr ) ) ) != IVAS_ERR_OK )
281 : {
282 0 : return error;
283 : }
284 :
285 1224 : if ( !hDiracDecBin->useTdDecorr && !( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) )
286 : {
287 509 : ivas_dirac_dec_get_frequency_axis( frequency_axis, output_Fs, nBins );
288 :
289 509 : if ( ( error = ivas_dirac_dec_decorr_open( &( hDiracDecBin->h_freq_domain_decorr_ap_params ),
290 509 : &( hDiracDecBin->h_freq_domain_decorr_ap_state ),
291 : nBins,
292 : BINAURAL_CHANNELS,
293 : BINAURAL_CHANNELS,
294 : DIRAC_SYNTHESIS_PSD_LS,
295 : frequency_axis,
296 : BINAURAL_CHANNELS,
297 : output_Fs ) ) != IVAS_ERR_OK )
298 : {
299 0 : return error;
300 : }
301 : }
302 : }
303 : else
304 : {
305 1472 : hDiracDecBin->useTdDecorr = st_ivas->hDiracDecBin[0]->useTdDecorr; /* copy the flag, but the implementation re-uses the decorrelated signal */
306 : }
307 :
308 2696 : hDiracDecBin->reqularizationFactor = configure_reqularization_factor( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate );
309 :
310 2696 : hDiracDecBin->phHrtfParambin = phHrtfParambin;
311 :
312 2696 : st_ivas->hDiracDecBin[pos_idx] = hDiracDecBin;
313 : }
314 :
315 : /* allocate transport channels */
316 1224 : if ( st_ivas->hTcBuffer == NULL )
317 : {
318 : int16_t nchan_to_allocate;
319 : int16_t n_samples_granularity;
320 :
321 484 : nchan_to_allocate = BINAURAL_CHANNELS;
322 484 : if ( st_ivas->hDiracDecBin[0] != NULL && st_ivas->hDiracDecBin[0]->useTdDecorr )
323 : {
324 132 : nchan_to_allocate = 2 * BINAURAL_CHANNELS;
325 : }
326 352 : else if ( st_ivas->hOutSetup.separateChannelEnabled )
327 : {
328 0 : nchan_to_allocate++;
329 : }
330 484 : if ( st_ivas->ivas_format == MASA_ISM_FORMAT )
331 : {
332 225 : nchan_to_allocate = BINAURAL_CHANNELS + st_ivas->nchan_ism;
333 : }
334 :
335 484 : n_samples_granularity = ivas_jbm_dec_get_render_granularity( st_ivas->renderer_type, ivas_renderer_secondary_select( st_ivas ), output_Fs );
336 :
337 484 : if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, TC_BUFFER_MODE_RENDERER, ivas_jbm_dec_get_num_tc_channels( st_ivas ), nchan_to_allocate, nchan_to_allocate, n_samples_granularity ) ) != IVAS_ERR_OK )
338 : {
339 0 : return error;
340 : }
341 : }
342 1224 : return IVAS_ERR_OK;
343 : }
344 :
345 :
346 : /*-------------------------------------------------------------------------
347 : * ivas_dirac_dec_close_binaural_data()
348 : *
349 : * Close parametric binaural renderer
350 : *------------------------------------------------------------------------*/
351 :
352 4994 : void ivas_dirac_dec_close_binaural_data(
353 : DIRAC_DEC_BIN_HANDLE *hBinaural /* i/o: decoder DirAC binaural data handle */
354 : )
355 : {
356 : int16_t pos_idx;
357 :
358 4994 : if ( hBinaural == NULL || *hBinaural == NULL )
359 : {
360 3758 : return;
361 : }
362 :
363 11124 : for ( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ )
364 : {
365 9888 : if ( hBinaural[pos_idx] != NULL )
366 : {
367 2708 : if ( hBinaural[pos_idx]->hReverb != NULL )
368 : {
369 353 : ivas_binaural_reverb_close( &( hBinaural[pos_idx]->hReverb ) );
370 : }
371 :
372 2708 : ivas_td_decorr_dec_close( &( hBinaural[pos_idx]->hTdDecorr ) );
373 :
374 2708 : if ( hBinaural[pos_idx]->h_freq_domain_decorr_ap_params != NULL )
375 : {
376 527 : ivas_dirac_dec_decorr_close( &( hBinaural[pos_idx]->h_freq_domain_decorr_ap_params ), &( hBinaural[pos_idx]->h_freq_domain_decorr_ap_state ) );
377 : }
378 :
379 2708 : free( hBinaural[pos_idx] );
380 2708 : hBinaural[pos_idx] = NULL;
381 : }
382 : }
383 :
384 1236 : return;
385 : }
386 :
387 : /*-------------------------------------------------------------------------
388 : * ivas_dirac_dec_binaural_copy_hrtfs()
389 : *
390 : * Temporary function for copying HRTF data from rom tables if no binary
391 : * file was given.
392 : *------------------------------------------------------------------------*/
393 :
394 2720 : ivas_error ivas_dirac_dec_binaural_copy_hrtfs(
395 : HRTFS_PARAMBIN_HANDLE *hHrtfParambin /* i/o: HRTF structure for rendering */
396 : )
397 : {
398 : int16_t i, j;
399 :
400 2720 : if ( hHrtfParambin != NULL && *hHrtfParambin != NULL )
401 : {
402 : /* Tables already loaded from file */
403 2120 : return IVAS_ERR_OK;
404 : }
405 : else
406 : {
407 : /* Initialise tables from ROM */
408 : HRTFS_PARAMBIN *hrtfParambin;
409 :
410 600 : if ( ( hrtfParambin = (HRTFS_PARAMBIN *) malloc( sizeof( HRTFS_PARAMBIN ) ) ) == NULL )
411 : {
412 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for parametric binauralizer HRTF tables" );
413 : }
414 :
415 1800 : for ( i = 0; i < BINAURAL_CHANNELS; i++ )
416 : {
417 20400 : for ( j = 0; j < HRTF_SH_CHANNELS; j++ )
418 : {
419 19200 : mvr2r( hrtfShCoeffsRe[i][j], hrtfParambin->hrtfShCoeffsRe[i][j], HRTF_NUM_BINS );
420 19200 : mvr2r( hrtfShCoeffsIm[i][j], hrtfParambin->hrtfShCoeffsIm[i][j], HRTF_NUM_BINS );
421 : }
422 : }
423 :
424 600 : mvr2r( parametricReverberationTimes, hrtfParambin->parametricReverberationTimes, CLDFB_NO_CHANNELS_MAX );
425 600 : mvr2r( parametricReverberationEneCorrections, hrtfParambin->parametricReverberationEneCorrections, CLDFB_NO_CHANNELS_MAX );
426 600 : mvr2r( parametricEarlyPartEneCorrection, hrtfParambin->parametricEarlyPartEneCorrection, CLDFB_NO_CHANNELS_MAX );
427 :
428 600 : *hHrtfParambin = hrtfParambin;
429 :
430 600 : return IVAS_ERR_OK;
431 : }
432 : }
433 :
434 :
435 : /*-------------------------------------------------------------------------
436 : * void ivas_dirac_dec_binaural_render()
437 : *
438 : *
439 : *------------------------------------------------------------------------*/
440 :
441 172560 : void ivas_dirac_dec_binaural_render(
442 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */
443 : const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */
444 : uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */
445 : uint16_t *nSamplesAvailable, /* o : number of CLDFB slots still to render */
446 : const int16_t nchan_transport, /* i : number of transport channels */
447 : float *output_f[] /* o : rendered time signal */
448 : )
449 : {
450 : int16_t slots_to_render, first_sf, last_sf, subframe_idx;
451 : uint16_t slot_size, ch;
452 : uint16_t nchan_out;
453 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
454 : float *output_f_local[MAX_OUTPUT_CHANNELS];
455 :
456 172560 : hSpatParamRendCom = st_ivas->hSpatParamRendCom;
457 172560 : nchan_out = BINAURAL_CHANNELS;
458 : #ifdef DEBUGGING
459 : assert( hSpatParamRendCom );
460 : #endif
461 517680 : for ( ch = 0; ch < nchan_out; ch++ )
462 : {
463 345120 : output_f_local[ch] = output_f[ch];
464 : }
465 172560 : slot_size = NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS );
466 :
467 : /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */
468 172560 : slots_to_render = min( hSpatParamRendCom->num_slots - hSpatParamRendCom->slots_rendered, nSamplesAsked / slot_size );
469 172560 : *nSamplesRendered = slots_to_render * slot_size;
470 172560 : first_sf = hSpatParamRendCom->subframes_rendered;
471 172560 : last_sf = first_sf;
472 :
473 792999 : while ( slots_to_render > 0 )
474 : {
475 620439 : slots_to_render -= hSpatParamRendCom->subframe_nbslots[last_sf];
476 620439 : last_sf++;
477 : }
478 :
479 : #ifdef DEBUGGING
480 : assert( slots_to_render == 0 );
481 : #endif
482 792999 : for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
483 : {
484 620439 : int16_t n_samples_sf = slot_size * hSpatParamRendCom->subframe_nbslots[subframe_idx];
485 620439 : ivas_dirac_dec_binaural_internal( st_ivas, st_ivas->hCombinedOrientationData, output_f_local, nchan_transport, subframe_idx );
486 :
487 1861317 : for ( ch = 0; ch < nchan_out; ch++ )
488 : {
489 1240878 : output_f_local[ch] += n_samples_sf;
490 : }
491 :
492 : /* update combined orientation access index */
493 620439 : ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, n_samples_sf );
494 : }
495 :
496 172560 : if ( hSpatParamRendCom->slots_rendered == hSpatParamRendCom->num_slots )
497 : {
498 153327 : hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % hSpatParamRendCom->dirac_md_buffer_length;
499 : }
500 :
501 172560 : *nSamplesAvailable = ( hSpatParamRendCom->num_slots - hSpatParamRendCom->slots_rendered ) * slot_size;
502 :
503 172560 : return;
504 : }
505 :
506 :
507 : /*-------------------------------------------------------------------------
508 : * ivas_dirac_dec_binaural_sba_gain()
509 : *
510 : * loudness correction for parametric binaural renderer
511 : *------------------------------------------------------------------------*/
512 :
513 66958 : void ivas_dirac_dec_binaural_sba_gain(
514 : float *output[], /* i/o: synthesized core-coder transport channels/DirAC output */
515 : const int16_t nchan_remapped, /* i : num channels after remapping of TCs */
516 : const int16_t output_frame /* i : output frame length */
517 : )
518 : {
519 : int16_t n;
520 : float gain;
521 :
522 66958 : if ( nchan_remapped == 1 )
523 : {
524 16877 : gain = 1.4454f;
525 : }
526 : else
527 : {
528 50081 : gain = 1.3657f;
529 : }
530 :
531 183997 : for ( n = 0; n < nchan_remapped; n++ )
532 : {
533 117039 : v_multc( output[n], gain, output[n], output_frame );
534 : }
535 :
536 66958 : return;
537 : }
538 :
539 :
540 : /*-------------------------------------------------------------------------
541 : * Local functions
542 : *------------------------------------------------------------------------*/
543 :
544 620439 : static void ivas_dirac_dec_binaural_internal(
545 : Decoder_Struct *st_ivas,
546 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,
547 : float *output_f[],
548 : const int16_t nchan_transport,
549 : const int16_t subframe )
550 : {
551 : DIRAC_DEC_BIN_HANDLE hDiracDecBin;
552 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
553 : PARAMBIN_REND_CONFIG config_data;
554 : int16_t slot, ch, numInChannels;
555 : float Cldfb_RealBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
556 : float Cldfb_ImagBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
557 : int16_t nchanSeparateChannels;
558 : float Rmat[3][3];
559 : int16_t max_band_decorr;
560 : DIFFUSE_DISTRIBUTION_DATA diffuseDistData;
561 : int16_t nBins, offsetSamples;
562 : int16_t i, j;
563 : int16_t pos_idx;
564 : MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
565 : float tmp_Cldfb_out_re[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
566 : float tmp_Cldfb_out_im[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
567 : /* these allow re-using the reverb and freq-domain decorrelator signals from ivas_dirac_dec_binaural_process_output() in split rendering for the side renderings */
568 : float reverbRe[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
569 : float reverbIm[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
570 : float decorrRe[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
571 : float decorrIm[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
572 : float subFrameTotalEne[CLDFB_NO_CHANNELS_MAX];
573 : float IIReneLimiter[CLDFB_NO_CHANNELS_MAX];
574 :
575 620439 : hDiracDecBin = st_ivas->hDiracDecBin[0];
576 620439 : assert( hDiracDecBin );
577 620439 : hSpatParamRendCom = st_ivas->hSpatParamRendCom;
578 620439 : nBins = hSpatParamRendCom->num_freq_bands;
579 620439 : offsetSamples = hSpatParamRendCom->slots_rendered * nBins;
580 :
581 : /* Setup internal config */
582 620439 : config_data.separateCenterChannelRendering = st_ivas->hOutSetup.separateChannelEnabled;
583 620439 : config_data.ivas_format = st_ivas->ivas_format;
584 620439 : config_data.mc_mode = st_ivas->mc_mode;
585 620439 : config_data.ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate;
586 620439 : config_data.nchan_transport = st_ivas->nchan_transport;
587 620439 : config_data.qualityBasedSmFactor = st_ivas->hMasa != NULL ? st_ivas->hMasa->data.dir_decode_quality : 1.0f;
588 620439 : config_data.processReverb = st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ? 1 : 0;
589 620439 : if ( st_ivas->ivas_format == MASA_ISM_FORMAT )
590 : {
591 138997 : config_data.ism_mode = st_ivas->ism_mode;
592 : }
593 : else
594 : {
595 481442 : config_data.ism_mode = ISM_MODE_NONE;
596 : }
597 :
598 : /* The input channel number at this processing function (not nchan_transport) */
599 620439 : numInChannels = BINAURAL_CHANNELS;
600 620439 : if ( config_data.separateCenterChannelRendering || ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) ) )
601 : {
602 51218 : numInChannels++;
603 : }
604 569221 : else if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC && ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) )
605 : {
606 2922 : numInChannels += (uint8_t) st_ivas->nchan_ism;
607 : }
608 :
609 620439 : Rmat[0][0] = 1.0f;
610 620439 : Rmat[0][1] = 0.0f;
611 620439 : Rmat[0][2] = 0.0f;
612 :
613 620439 : Rmat[1][0] = 0.0f;
614 620439 : Rmat[1][1] = 1.0f;
615 620439 : Rmat[1][2] = 0.0f;
616 :
617 620439 : Rmat[2][0] = 0.0f;
618 620439 : Rmat[2][1] = 0.0f;
619 620439 : Rmat[2][2] = 1.0f;
620 :
621 : /* CLDFB Analysis of input */
622 3077473 : for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
623 : {
624 7597581 : for ( ch = 0; ch < numInChannels; ch++ )
625 : {
626 5140547 : if ( ch == 0 || nchan_transport == 2 )
627 : {
628 4299169 : cldfbAnalysis_ts(
629 4299169 : &( st_ivas->hTcBuffer->tc[ch][nBins * slot + offsetSamples] ),
630 4299169 : Cldfb_RealBuffer_in[ch][slot],
631 4299169 : Cldfb_ImagBuffer_in[ch][slot],
632 : nBins, st_ivas->cldfbAnaDec[ch] );
633 : }
634 841378 : else if ( config_data.nchan_transport == 2 ) /* Stereo signal transmitted as mono with DFT stereo */
635 : {
636 : /* At mono input duplicate the channel to dual-mono */
637 185950 : mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins );
638 185950 : mvr2r( Cldfb_ImagBuffer_in[0][slot], Cldfb_ImagBuffer_in[1][slot], nBins );
639 : }
640 : else /* when nchan_transport == 1 and ch == 1 */
641 : {
642 : /* CNA and HB FD-CNG*/
643 655428 : if ( st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag )
644 443282 : {
645 : int16_t numCoreBands, b;
646 :
647 443282 : numCoreBands = st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->numCoreBands;
648 :
649 886564 : generate_masking_noise_dirac( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom,
650 : st_ivas->cldfbAnaDec[1],
651 443282 : &st_ivas->hTcBuffer->tc[nchan_transport][hSpatParamRendCom->num_freq_bands * hSpatParamRendCom->slots_rendered],
652 443282 : Cldfb_RealBuffer_in[2][slot], Cldfb_ImagBuffer_in[2][slot],
653 : slot,
654 443282 : st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna,
655 443282 : ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag );
656 :
657 886564 : generate_masking_noise_dirac( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom,
658 : st_ivas->cldfbAnaDec[1], /*nothing will be analyzed, just get cnst*/
659 : NULL,
660 443282 : Cldfb_RealBuffer_in[1][slot], Cldfb_ImagBuffer_in[1][slot],
661 : slot,
662 443282 : st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna,
663 443282 : ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag );
664 :
665 : /* LB: Copy first channel + LB-CNG to first and second channels with same scaling (dual-mono)*/
666 9146170 : for ( b = 0; b < numCoreBands; b++ )
667 : {
668 8702888 : Cldfb_RealBuffer_in[0][slot][b] = INV_SQRT2 * ( Cldfb_RealBuffer_in[0][slot][b] + Cldfb_RealBuffer_in[2][slot][b] );
669 8702888 : Cldfb_RealBuffer_in[1][slot][b] = Cldfb_RealBuffer_in[0][slot][b];
670 8702888 : Cldfb_ImagBuffer_in[0][slot][b] = INV_SQRT2 * ( Cldfb_ImagBuffer_in[0][slot][b] + Cldfb_ImagBuffer_in[2][slot][b] );
671 8702888 : Cldfb_ImagBuffer_in[1][slot][b] = Cldfb_ImagBuffer_in[0][slot][b];
672 : }
673 :
674 : /* HB: Copy first channel to second channel and add HB-CNGs with different scalings*/
675 17338274 : for ( ; b < nBins; b++ )
676 : {
677 16894992 : Cldfb_RealBuffer_in[0][slot][b] *= INV_SQRT2;
678 16894992 : Cldfb_RealBuffer_in[1][slot][b] = Cldfb_RealBuffer_in[0][slot][b] + 0.5f * Cldfb_RealBuffer_in[1][slot][b] + Cldfb_RealBuffer_in[0][slot][b];
679 16894992 : Cldfb_RealBuffer_in[0][slot][b] += 0.5f * Cldfb_RealBuffer_in[2][slot][b];
680 :
681 16894992 : Cldfb_ImagBuffer_in[0][slot][b] *= INV_SQRT2;
682 16894992 : Cldfb_ImagBuffer_in[1][slot][b] = Cldfb_ImagBuffer_in[0][slot][b] + 0.5f * Cldfb_ImagBuffer_in[1][slot][b];
683 16894992 : Cldfb_ImagBuffer_in[0][slot][b] += 0.5f * Cldfb_ImagBuffer_in[2][slot][b];
684 : }
685 : }
686 : else
687 : {
688 : /* At mono input duplicate the channel to dual-mono, and apply gain
689 : correction to ensure same overall level as in stereo mode */
690 212146 : v_multc( Cldfb_RealBuffer_in[0][slot], INV_SQRT_2, Cldfb_RealBuffer_in[0][slot], nBins );
691 212146 : v_multc( Cldfb_ImagBuffer_in[0][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[0][slot], nBins );
692 :
693 212146 : mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins );
694 212146 : mvr2r( Cldfb_ImagBuffer_in[0][slot], Cldfb_ImagBuffer_in[1][slot], nBins );
695 : }
696 : }
697 : }
698 :
699 2457034 : if ( hDiracDecBin->useTdDecorr )
700 : {
701 2098338 : for ( ch = BINAURAL_CHANNELS; ch < ( 2 * BINAURAL_CHANNELS ); ch++ )
702 : {
703 1398892 : cldfbAnalysis_ts(
704 1398892 : &( st_ivas->hTcBuffer->tc[ch][nBins * slot + offsetSamples] ),
705 1398892 : Cldfb_RealBuffer_in[ch][slot],
706 1398892 : Cldfb_ImagBuffer_in[ch][slot],
707 : nBins, st_ivas->cldfbAnaDec[ch] );
708 1398892 : if ( config_data.nchan_transport == 1 &&
709 1026992 : ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT ) )
710 : {
711 540100 : v_multc( Cldfb_RealBuffer_in[ch][slot], INV_SQRT_2, Cldfb_RealBuffer_in[ch][slot], nBins );
712 540100 : v_multc( Cldfb_ImagBuffer_in[ch][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[ch][slot], nBins );
713 : }
714 : }
715 : }
716 : }
717 :
718 620439 : if ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT )
719 : {
720 223566 : hDiracDecBin->hDiffuseDist = &diffuseDistData;
721 :
722 223566 : ivas_spar_param_to_masa_param_mapping( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe );
723 223566 : ivas_sba_prototype_renderer( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe );
724 : }
725 :
726 620439 : if ( ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || ( st_ivas->ism_mode == ISM_MASA_MODE_DISC && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) ) ) || st_ivas->ivas_format == ISM_FORMAT )
727 : {
728 72888 : ivas_omasa_preProcessStereoTransportsForEditedObjects( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, subframe );
729 : }
730 :
731 620439 : if ( hCombinedOrientationData )
732 : {
733 1698572 : for ( i = 0; i < 3; i++ )
734 : {
735 5095716 : for ( j = 0; j < 3; j++ )
736 : {
737 3821787 : Rmat[i][j] = hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx][i][j];
738 : }
739 : }
740 :
741 424643 : if ( nchan_transport == 2 )
742 : {
743 : /* in case of split rendering, determine the prototype rotation based on the main direction and use the same prototypes for the offset directions */
744 309128 : adaptTransportSignalsHeadtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat );
745 :
746 309128 : ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat );
747 : }
748 : }
749 :
750 620439 : if ( config_data.ivas_format == ISM_FORMAT )
751 : {
752 45812 : max_band_decorr = 0;
753 : }
754 574627 : else if ( hDiracDecBin->useTdDecorr )
755 : {
756 177354 : max_band_decorr = CLDFB_NO_CHANNELS_MAX;
757 : }
758 : else
759 : {
760 397273 : max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr;
761 : }
762 :
763 620439 : ivas_dirac_dec_binaural_formulate_input_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe,
764 : subFrameTotalEne, IIReneLimiter );
765 :
766 620439 : ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat, subframe,
767 620439 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, subFrameTotalEne, IIReneLimiter, st_ivas->hMasaIsmData );
768 :
769 620439 : nchanSeparateChannels = 0;
770 620439 : if ( config_data.separateCenterChannelRendering || ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) ) )
771 : {
772 51218 : nchanSeparateChannels = 1;
773 : }
774 569221 : else if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC && ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) )
775 : {
776 2922 : nchanSeparateChannels = (uint8_t) st_ivas->nchan_ism;
777 : }
778 :
779 620439 : ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat, subframe,
780 620439 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, nchanSeparateChannels, st_ivas->hMasaIsmData );
781 :
782 620439 : pMultiBinPoseData = NULL;
783 620439 : if ( st_ivas->hSplitBinRend != NULL )
784 : {
785 322746 : pMultiBinPoseData = &st_ivas->hSplitBinRend->splitrend.multiBinPoseData;
786 : }
787 :
788 620439 : if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM )
789 : {
790 322746 : ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
791 322746 : max_band_decorr, numInChannels, config_data.processReverb, subframe, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
792 : reverbRe, reverbIm, decorrRe, decorrIm, 1 );
793 :
794 968238 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
795 : {
796 3191466 : for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe]; i++ )
797 : {
798 : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
799 2545974 : ivas_CLDFB_RINGBUF_Push( st_ivas->hSplitBinRend->hMultiBinCldfbData[ch], tmp_Cldfb_out_re[ch][i], tmp_Cldfb_out_im[ch][i], CLDFB_NO_CHANNELS_MAX );
800 : #else
801 : mvr2r( tmp_Cldfb_out_re[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
802 : mvr2r( tmp_Cldfb_out_im[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
803 : #endif
804 : }
805 : }
806 : }
807 : else
808 : {
809 297693 : ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
810 297693 : max_band_decorr, numInChannels, config_data.processReverb, subframe, NULL, NULL,
811 : reverbRe, reverbIm, decorrRe, decorrIm, 1 );
812 : }
813 :
814 620439 : hDiracDecBin->hDiffuseDist = NULL;
815 :
816 620439 : if ( pMultiBinPoseData != NULL && pMultiBinPoseData->num_poses > 1 )
817 : {
818 : /* quaternion-based rotation from ivas_binRenderer_internal.c:ivas_binRenderer(), but using absolute rotation instead of delta rotations */
819 : IVAS_QUATERNION Quaternions_rot, Quaternions_abs, *Quaternions_ref;
820 : float Rmat_local[3][3];
821 :
822 228536 : if ( hCombinedOrientationData )
823 : {
824 228536 : Quaternions_ref = &hCombinedOrientationData->Quaternions[0];
825 228536 : Quaternions_rot.w = -3.0f; /* signal to use Euler */
826 228536 : Quaternions_abs.w = -3.0f; /* signal to use Euler */
827 228536 : Quat2EulerDegree( *Quaternions_ref, &Quaternions_abs.z, &Quaternions_abs.y, &Quaternions_abs.x ); /*order in Quat2Euler seems to be reversed ?*/
828 :
829 1218048 : for ( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
830 : {
831 989512 : Quaternions_rot.x = Quaternions_abs.x + pMultiBinPoseData->relative_head_poses[pos_idx][0];
832 989512 : Quaternions_rot.y = Quaternions_abs.y + pMultiBinPoseData->relative_head_poses[pos_idx][1];
833 989512 : Quaternions_rot.z = Quaternions_abs.z + pMultiBinPoseData->relative_head_poses[pos_idx][2];
834 :
835 989512 : QuatToRotMat( Quaternions_rot, Rmat_local );
836 :
837 989512 : hDiracDecBin = st_ivas->hDiracDecBin[pos_idx];
838 989512 : assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" );
839 989512 : if ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT )
840 : {
841 209768 : hDiracDecBin->hDiffuseDist = &diffuseDistData;
842 : }
843 :
844 : /* re-use input covariance for the side renderings */
845 2968536 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
846 : {
847 1979024 : mvr2r( st_ivas->hDiracDecBin[0]->ChEne[ch], hDiracDecBin->ChEne[ch], hSpatParamRendCom->num_freq_bands );
848 : }
849 989512 : mvr2r( st_ivas->hDiracDecBin[0]->ChCrossRe, hDiracDecBin->ChCrossRe, hSpatParamRendCom->num_freq_bands );
850 989512 : mvr2r( st_ivas->hDiracDecBin[0]->ChCrossIm, hDiracDecBin->ChCrossIm, hSpatParamRendCom->num_freq_bands );
851 :
852 989512 : ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe,
853 : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
854 989512 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0,
855 : #else
856 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
857 : #endif
858 : subFrameTotalEne, IIReneLimiter, st_ivas->hMasaIsmData );
859 :
860 989512 : ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe,
861 : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
862 989512 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0,
863 : #else
864 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
865 : #endif
866 : nchanSeparateChannels, st_ivas->hMasaIsmData );
867 :
868 : /* re-use reverb and decorr from main direction for the sides */
869 989512 : ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
870 989512 : max_band_decorr, numInChannels, config_data.processReverb, subframe, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
871 : reverbRe, reverbIm, decorrRe, decorrIm, 0 );
872 :
873 : /* copy from temporary buffer to the main split rendering buffer */
874 2968536 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
875 : {
876 9784968 : for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe]; i++ )
877 : {
878 : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
879 7805944 : ivas_CLDFB_RINGBUF_Push( st_ivas->hSplitBinRend->hMultiBinCldfbData[pos_idx * BINAURAL_CHANNELS + ch], tmp_Cldfb_out_re[ch][i], tmp_Cldfb_out_im[ch][i], CLDFB_NO_CHANNELS_MAX );
880 : #else
881 : mvr2r( tmp_Cldfb_out_re[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[pos_idx * BINAURAL_CHANNELS + ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
882 : mvr2r( tmp_Cldfb_out_im[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[pos_idx * BINAURAL_CHANNELS + ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
883 : #endif
884 : }
885 : }
886 :
887 989512 : hDiracDecBin->hDiffuseDist = NULL;
888 : }
889 : }
890 : }
891 :
892 : /* update this counter only after the last rendering of split directions */
893 620439 : hSpatParamRendCom->slots_rendered += hSpatParamRendCom->subframe_nbslots[subframe];
894 620439 : hSpatParamRendCom->subframes_rendered++;
895 :
896 620439 : return;
897 : }
898 :
899 :
900 1606435 : static void ivas_dirac_dec_decorrelate_slot(
901 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
902 : const int16_t num_freq_bands,
903 : const int16_t slot,
904 : float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
905 : float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
906 : float decRe[][CLDFB_NO_CHANNELS_MAX],
907 : float decIm[][CLDFB_NO_CHANNELS_MAX] )
908 : {
909 : int16_t offset, ch, bin;
910 : float onset_filter[BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, 60 bins */
911 : float decorrelatedFrameInterleaved[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */
912 : float protoFrameF[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */
913 1606435 : const int16_t protoIndexDir[BINAURAL_CHANNELS] = { 0, 1 };
914 :
915 : /* Decorrelation needs interleaved data. Copy left and right signals to proto_frame_f */
916 4819305 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
917 : {
918 3212870 : offset = num_freq_bands * BINAURAL_CHANNELS * ch;
919 181628030 : for ( bin = 0; bin < num_freq_bands; bin++ )
920 : {
921 178415160 : protoFrameF[( bin * BINAURAL_CHANNELS ) + offset] = inRe[ch][slot][bin];
922 178415160 : protoFrameF[( bin * BINAURAL_CHANNELS ) + offset + 1] = inIm[ch][slot][bin];
923 : }
924 : }
925 :
926 : /* Decorrelate proto signal to decorrelatedFrameInterleaved */
927 1606435 : ivas_dirac_dec_decorr_process( num_freq_bands,
928 : BINAURAL_CHANNELS,
929 : BINAURAL_CHANNELS,
930 : DIRAC_SYNTHESIS_PSD_LS,
931 : BINAURAL_CHANNELS,
932 : protoFrameF,
933 : BINAURAL_CHANNELS,
934 : protoIndexDir,
935 : decorrelatedFrameInterleaved,
936 : onset_filter,
937 : hDiracDecBin->h_freq_domain_decorr_ap_params,
938 : hDiracDecBin->h_freq_domain_decorr_ap_state );
939 :
940 : /* De-interleave decorrelated signals*/
941 4819305 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
942 : {
943 3212870 : offset = num_freq_bands * BINAURAL_CHANNELS * ch;
944 181628030 : for ( bin = 0; bin < num_freq_bands; bin++ )
945 : {
946 178415160 : decRe[ch][bin] = decorrelatedFrameInterleaved[( bin * BINAURAL_CHANNELS ) + offset];
947 178415160 : decIm[ch][bin] = decorrelatedFrameInterleaved[( bin * BINAURAL_CHANNELS ) + offset + 1];
948 : }
949 : }
950 :
951 1606435 : return;
952 : }
953 :
954 :
955 627669 : static void ivas_dirac_dec_binaural_formulate_input_covariance_matrices(
956 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
957 : const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
958 : const PARAMBIN_REND_CONFIG_HANDLE hConfig,
959 : float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
960 : float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
961 : const int16_t subframe,
962 : float *subFrameTotalEne,
963 : float *IIReneLimiter )
964 : {
965 : int16_t ch, slot, bin;
966 : int16_t nBins;
967 : float IIReneLimiterFactor;
968 : float qualityBasedSmFactor;
969 : float lowBitRateEQ[CLDFB_NO_CHANNELS_MAX];
970 : uint8_t applyLowBitRateEQ;
971 : IVAS_FORMAT ivas_format;
972 : int32_t ivas_total_brate;
973 : int16_t nchan_transport;
974 :
975 627669 : ivas_format = hConfig->ivas_format;
976 627669 : ivas_total_brate = hConfig->ivas_total_brate;
977 627669 : nchan_transport = hConfig->nchan_transport;
978 627669 : qualityBasedSmFactor = hConfig->qualityBasedSmFactor;
979 627669 : qualityBasedSmFactor *= qualityBasedSmFactor;
980 627669 : nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
981 :
982 627669 : set_zero( hDiracDecBin->ChCrossRe, nBins );
983 627669 : set_zero( hDiracDecBin->ChCrossIm, nBins );
984 1883007 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
985 : {
986 1255338 : set_zero( hDiracDecBin->ChEne[ch], nBins );
987 : }
988 :
989 : /* Determine EQ for low bit rates (13.2 and 16.4 kbps) */
990 627669 : applyLowBitRateEQ = 0;
991 627669 : if ( ( ivas_format == MASA_FORMAT || ivas_format == MC_FORMAT ) && ivas_total_brate < MASA_STEREO_MIN_BITRATE )
992 : {
993 55250 : applyLowBitRateEQ = 1;
994 55250 : if ( ivas_total_brate == IVAS_16k4 )
995 : {
996 866934 : for ( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ )
997 : {
998 818771 : lowBitRateEQ[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = lowBitRateBinauralEQ[bin] * 0.5f + 0.5f;
999 : }
1000 : }
1001 : else
1002 : {
1003 127566 : for ( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ )
1004 : {
1005 120479 : lowBitRateEQ[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = lowBitRateBinauralEQ[bin];
1006 : }
1007 : }
1008 : }
1009 :
1010 : /* Formulate input and target covariance matrices for this subframe */
1011 627669 : set_zero( subFrameTotalEne, CLDFB_NO_CHANNELS_MAX );
1012 :
1013 : /* Calculate input covariance matrix */
1014 3113623 : for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
1015 : {
1016 139551674 : for ( bin = 0; bin < nBins; bin++ )
1017 : {
1018 411197160 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1019 : {
1020 : float instEne;
1021 :
1022 274131440 : instEne = ( inRe[ch][slot][bin] * inRe[ch][slot][bin] );
1023 274131440 : instEne += ( inIm[ch][slot][bin] * inIm[ch][slot][bin] );
1024 274131440 : hDiracDecBin->ChEne[ch][bin] += instEne;
1025 274131440 : subFrameTotalEne[bin] += instEne;
1026 : }
1027 137065720 : hDiracDecBin->ChCrossRe[bin] += inRe[0][slot][bin] * inRe[1][slot][bin];
1028 137065720 : hDiracDecBin->ChCrossRe[bin] += inIm[0][slot][bin] * inIm[1][slot][bin];
1029 137065720 : hDiracDecBin->ChCrossIm[bin] += inRe[0][slot][bin] * inIm[1][slot][bin];
1030 137065720 : hDiracDecBin->ChCrossIm[bin] -= inIm[0][slot][bin] * inRe[1][slot][bin];
1031 : }
1032 : }
1033 :
1034 : /* Apply EQ at low bit rates */
1035 627669 : if ( applyLowBitRateEQ )
1036 : {
1037 55250 : int16_t lastEqBin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET + LOW_BIT_RATE_BINAURAL_EQ_BINS - 1;
1038 :
1039 939250 : for ( bin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET; bin < lastEqBin; bin++ )
1040 : {
1041 884000 : subFrameTotalEne[bin] *= lowBitRateEQ[bin];
1042 : }
1043 1647840 : for ( ; bin < nBins; bin++ )
1044 : {
1045 1592590 : subFrameTotalEne[bin] *= lowBitRateEQ[lastEqBin];
1046 : }
1047 : }
1048 :
1049 627669 : if ( ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) && nchan_transport == 2 )
1050 : {
1051 : float tempRe, tempIm;
1052 : float subFrameSumEne[CLDFB_NO_CHANNELS_MAX];
1053 :
1054 155860 : v_multc( subFrameTotalEne, SBA_CARDI_TARGET_ENERGY_GAIN, subFrameTotalEne, nBins );
1055 :
1056 155860 : set_zero( subFrameSumEne, CLDFB_NO_CHANNELS_MAX );
1057 777625 : for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
1058 : {
1059 32085105 : for ( bin = 0; bin < nBins; bin++ )
1060 : {
1061 31463340 : tempRe = inRe[0][slot][bin] + inRe[1][slot][bin];
1062 31463340 : tempIm = inIm[0][slot][bin] + inIm[1][slot][bin];
1063 31463340 : subFrameSumEne[bin] += tempRe * tempRe + tempIm * tempIm;
1064 : }
1065 : }
1066 :
1067 8046820 : for ( bin = 0; bin < nBins; bin++ )
1068 : {
1069 7890960 : subFrameTotalEne[bin] = max( subFrameTotalEne[bin], subFrameSumEne[bin] );
1070 : }
1071 : }
1072 :
1073 : /* Temporal IIR-type smoothing of covariance matrices. Also apply encoding quality based smoothing factor. */
1074 627669 : if ( ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE )
1075 : {
1076 53350 : IIReneLimiterFactor = 16.0f + ( 1.0f - qualityBasedSmFactor );
1077 : }
1078 : else
1079 : {
1080 574319 : IIReneLimiterFactor = 8.0f + ( 1.0f - qualityBasedSmFactor );
1081 : }
1082 35255129 : for ( bin = 0; bin < nBins; bin++ )
1083 : {
1084 : float eneRatio;
1085 :
1086 : /* Temporally smooth cov mtx estimates for resulting mixing matrix stability. The design principle is that
1087 : * the energy history (IIR) must not be more than double of the current frame energy. This provides more
1088 : * robust performance at energy offsets when compared to typical IIR averaging. */
1089 34627460 : eneRatio = ( hDiracDecBin->ChEne[0][bin] + hDiracDecBin->ChEne[1][bin] ) / fmaxf( 1e-12f, ( hDiracDecBin->ChEnePrev[0][bin] + hDiracDecBin->ChEnePrev[1][bin] ) );
1090 34627460 : IIReneLimiter[bin] = fminf( 1.0f, eneRatio * IIReneLimiterFactor );
1091 :
1092 34627460 : hDiracDecBin->ChCrossRe[bin] *= qualityBasedSmFactor;
1093 34627460 : hDiracDecBin->ChCrossIm[bin] *= qualityBasedSmFactor;
1094 103882380 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1095 : {
1096 69254920 : hDiracDecBin->ChEne[ch][bin] *= qualityBasedSmFactor;
1097 : }
1098 :
1099 34627460 : hDiracDecBin->ChCrossRe[bin] += IIReneLimiter[bin] * hDiracDecBin->ChCrossRePrev[bin];
1100 34627460 : hDiracDecBin->ChCrossIm[bin] += IIReneLimiter[bin] * hDiracDecBin->ChCrossImPrev[bin];
1101 :
1102 103882380 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1103 : {
1104 69254920 : hDiracDecBin->ChEne[ch][bin] += IIReneLimiter[bin] * hDiracDecBin->ChEnePrev[ch][bin];
1105 : }
1106 :
1107 : /* Store energy values and coefficients for next round */
1108 34627460 : hDiracDecBin->ChCrossRePrev[bin] = hDiracDecBin->ChCrossRe[bin];
1109 34627460 : hDiracDecBin->ChCrossImPrev[bin] = hDiracDecBin->ChCrossIm[bin];
1110 103882380 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1111 : {
1112 69254920 : hDiracDecBin->ChEnePrev[ch][bin] = hDiracDecBin->ChEne[ch][bin];
1113 : }
1114 : }
1115 :
1116 627669 : return;
1117 : }
1118 :
1119 :
1120 1617181 : static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices(
1121 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
1122 : const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
1123 : const PARAMBIN_REND_CONFIG_HANDLE hConfig,
1124 : float Rmat[3][3],
1125 : const int16_t subframe,
1126 : const int16_t isHeadtracked,
1127 : const float *subFrameTotalEne,
1128 : const float *IIReneLimiter,
1129 : const MASA_ISM_DATA_HANDLE hMasaIsmData )
1130 : {
1131 : int16_t ch, bin;
1132 : int16_t separateCenterChannelRendering;
1133 : int16_t nBins, idx;
1134 : float frameMeanDiffusenessEneWeight[CLDFB_NO_CHANNELS_MAX];
1135 : float qualityBasedSmFactor;
1136 : int16_t dirac_read_idx;
1137 : PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_GAIN_CACHE_SIZE];
1138 : IVAS_FORMAT ivas_format;
1139 : MC_MODE mc_mode;
1140 : int16_t gainCacheBaseIndex;
1141 :
1142 1617181 : separateCenterChannelRendering = hConfig->separateCenterChannelRendering;
1143 1617181 : ivas_format = hConfig->ivas_format;
1144 1617181 : mc_mode = hConfig->mc_mode;
1145 1617181 : qualityBasedSmFactor = hConfig->qualityBasedSmFactor;
1146 1617181 : qualityBasedSmFactor *= qualityBasedSmFactor;
1147 1617181 : nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
1148 :
1149 1617181 : set_zero( hDiracDecBin->ChCrossReOut, nBins );
1150 1617181 : set_zero( hDiracDecBin->ChCrossImOut, nBins );
1151 4851543 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1152 : {
1153 3234362 : set_zero( hDiracDecBin->ChEneOut[ch], nBins );
1154 : }
1155 1617181 : set_zero( hDiracDecBin->frameMeanDiffuseness, nBins );
1156 :
1157 1617181 : set_zero( frameMeanDiffusenessEneWeight, CLDFB_NO_CHANNELS_MAX );
1158 :
1159 17788991 : for ( idx = 0; idx < MAX_GAIN_CACHE_SIZE; idx++ )
1160 : {
1161 16171810 : gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */
1162 : }
1163 :
1164 1617181 : dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
1165 :
1166 : /* Determine target covariance matrix containing target binaural properties */
1167 95615361 : for ( bin = 0; bin < nBins; bin++ )
1168 : {
1169 93998180 : float diffuseness = 1.0f; /* ratio1 and ratio2 are subtracted from diffuseness further below */
1170 93998180 : float diffusenessValForDecorrelationReduction = 1.0f;
1171 : float diffEneValForDecorrelationReduction;
1172 93998180 : float surCoh = 0.0f, spreadCoh = 0.0f; /* Default values if spreadSurroundCoherenceApplied == false */
1173 : float diffEne, dirEne, meanEnePerCh;
1174 : int16_t dirIndex;
1175 :
1176 : /* When BINAURAL_ROOM is not indicated, hBinaural->earlyPartEneCorrection[bin] values are all 1.0f.
1177 : * When BINAURAL_ROOM is indicated, the binaural audio output is based on combined use of the
1178 : * HRTF data set and a BRIR-based data set. The HRTF data set is spectrally corrected to match
1179 : * the early spectrum of the BRIR data, using the spectral correction data in
1180 : * hBinaural->earlyPartEneCorrection[bin], based on the BRIR set. */
1181 93998180 : meanEnePerCh = hDiracDecBin->earlyPartEneCorrection[bin] * subFrameTotalEne[bin] / 2.0f;
1182 :
1183 : /* Determine direct part target covariance matrix (for 1 or 2 directions) */
1184 228225100 : for ( dirIndex = 0; dirIndex < hSpatParamRendCom->numSimultaneousDirections; dirIndex++ )
1185 : {
1186 : int16_t aziDeg, eleDeg;
1187 : float lRealp, lImagp, rRealp, rImagp;
1188 : float lRealpTmp, lImagpTmp, rRealpTmp, rImagpTmp;
1189 : float hrtfEne[BINAURAL_CHANNELS], hrtfCrossRe, hrtfCrossIm, ratio;
1190 134226920 : uint8_t isIsmDirection = 0;
1191 :
1192 134226920 : if ( dirIndex == 0 ) /* For first of the two simultaneous directions */
1193 : {
1194 93998180 : aziDeg = hSpatParamRendCom->azimuth[dirac_read_idx][bin];
1195 93998180 : eleDeg = hSpatParamRendCom->elevation[dirac_read_idx][bin];
1196 93998180 : ratio = hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin];
1197 93998180 : spreadCoh = hSpatParamRendCom->spreadCoherence[dirac_read_idx][bin];
1198 93998180 : gainCacheBaseIndex = 0;
1199 : }
1200 40228740 : else if ( ivas_format != MASA_ISM_FORMAT || ( ivas_format == MASA_ISM_FORMAT && dirIndex < hSpatParamRendCom->numParametricDirections ) ) /* For second of the two simultaneous directions */
1201 : {
1202 19457940 : if ( ( ratio = hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin] ) < 0.001 )
1203 : {
1204 : /* This touches only MASA path where second direction always has smaller ratio and
1205 : * for non-2dir it is zero. As the whole direction contribution is multiplied with
1206 : * the ratio, a very small ratio does not contribute any energy to output. Thus,
1207 : * it is better to save complexity. */
1208 13502871 : continue;
1209 : }
1210 5955069 : aziDeg = hSpatParamRendCom->azimuth2[dirac_read_idx][bin];
1211 5955069 : eleDeg = hSpatParamRendCom->elevation2[dirac_read_idx][bin];
1212 5955069 : spreadCoh = hSpatParamRendCom->spreadCoherence2[dirac_read_idx][bin];
1213 5955069 : gainCacheBaseIndex = 3;
1214 : }
1215 : else /* For object directions of MASA_ISM_FORMAT */
1216 : {
1217 20770800 : isIsmDirection = 1;
1218 : uint16_t ismDirIndex;
1219 20770800 : ismDirIndex = dirIndex - hSpatParamRendCom->numParametricDirections;
1220 20770800 : assert( hMasaIsmData != NULL && "hMasaIsmData should not be NULL if we use it" );
1221 :
1222 20770800 : if ( hMasaIsmData->ism_dir_is_edited[ismDirIndex] )
1223 : {
1224 165840 : aziDeg = hMasaIsmData->azimuth_ism_edited[ismDirIndex];
1225 165840 : eleDeg = hMasaIsmData->elevation_ism_edited[ismDirIndex];
1226 : }
1227 : else
1228 : {
1229 20604960 : aziDeg = hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx];
1230 20604960 : eleDeg = hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx];
1231 : }
1232 20770800 : ratio = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin];
1233 20770800 : spreadCoh = 0.0f;
1234 20770800 : gainCacheBaseIndex = 6 + ismDirIndex;
1235 : }
1236 :
1237 120724049 : diffuseness -= ratio; /* diffuseness = 1 - ratio1 - ratio2 */
1238 :
1239 120724049 : if ( diffuseness < 0.0f )
1240 : {
1241 234014 : diffuseness = 0.0f;
1242 : }
1243 120724049 : if ( isIsmDirection )
1244 : {
1245 : /* Objects cause lesser decorrelation reduction, to avoid removing all decorrelation when only objects are present */
1246 20770800 : diffusenessValForDecorrelationReduction -= ratio * 0.5f;
1247 : }
1248 : else
1249 : {
1250 99953249 : diffusenessValForDecorrelationReduction -= ratio;
1251 : }
1252 :
1253 120724049 : if ( separateCenterChannelRendering )
1254 : {
1255 : /* In masa + mono rendering mode, the center directions originate from phantom sources, so the
1256 : * spread coherence is increased */
1257 : float aziRad, eleRad, doaVectorX, spatialAngleDeg, altSpreadCoh;
1258 :
1259 15000 : aziRad = (float) aziDeg * PI_OVER_180;
1260 15000 : eleRad = (float) eleDeg * PI_OVER_180;
1261 15000 : doaVectorX = cosf( aziRad ) * cosf( eleRad );
1262 15000 : spatialAngleDeg = acosf( doaVectorX ) * _180_OVER_PI;
1263 15000 : altSpreadCoh = 1.0f - ( spatialAngleDeg / 30.0f );
1264 15000 : spreadCoh = max( spreadCoh, altSpreadCoh );
1265 : }
1266 :
1267 120724049 : getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[gainCacheBaseIndex], isHeadtracked, *hDiracDecBin->phHrtfParambin );
1268 :
1269 120724049 : if ( hDiracDecBin->renderStereoOutputInsteadOfBinaural )
1270 : {
1271 : /* Synthesizing spread coherence is not needed for stereo loudspeaker output,
1272 : * as directional sound is reproduced with two loudspeakers in any case */
1273 1258918 : spreadCoh = 0.0f;
1274 : }
1275 :
1276 120724049 : if ( spreadCoh > 0.0f )
1277 : {
1278 : float centerMul, sidesMul;
1279 : float hrtfEneCenter, hrtfEneSides, hrtfEneRealized, eneCorrectionFactor;
1280 : float w1, w2, w3, eq;
1281 :
1282 27326326 : hrtfEneCenter = ( lRealp * lRealp ) + ( lImagp * lImagp ) + ( rRealp * rRealp ) + ( rImagp * rImagp );
1283 :
1284 : /* Spread coherence is synthesized as coherent sources at 30 degree horizontal spacing.
1285 : * The following formulas determine the gains for these sources.
1286 : * spreadCoh = 0: Only panning
1287 : * spreadCoh = 0.5: Three sources coherent panning (e.g. 30 0 -30 deg azi)
1288 : * spreadCoh = 1.0: Two sources coherent panning with gap (as above, but center is silent) */
1289 27326326 : if ( spreadCoh < 0.5f )
1290 : {
1291 : /* 0.0f < spreadCoh < 0.5f */
1292 26178350 : sidesMul = 0.5774f * spreadCoh * 2.0f; /* sqrt(1/3) = 0.5774f */
1293 26178350 : centerMul = 1.0f - ( spreadCoh * 2.0f ) + sidesMul;
1294 : }
1295 : else
1296 : {
1297 : /* 0.5f <= spreadCoh < 1.0f */
1298 1147976 : centerMul = 2.0f - ( 2.0f * spreadCoh );
1299 1147976 : sidesMul = inv_sqrt( centerMul + 2.0f );
1300 1147976 : centerMul *= sidesMul;
1301 : }
1302 :
1303 : /* Apply the gain for the center source of the three coherent sources */
1304 27326326 : lRealp *= centerMul;
1305 27326326 : lImagp *= centerMul;
1306 27326326 : rRealp *= centerMul;
1307 27326326 : rImagp *= centerMul;
1308 :
1309 : /* Apply the gain for the left source of the three coherent sources */
1310 27326326 : getDirectPartGains( bin, aziDeg + 30, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[gainCacheBaseIndex + 1], isHeadtracked, *hDiracDecBin->phHrtfParambin );
1311 :
1312 27326326 : hrtfEneSides = ( lRealpTmp * lRealpTmp ) + ( lImagpTmp * lImagpTmp ) + ( rRealpTmp * rRealpTmp ) + ( rImagpTmp * rImagpTmp );
1313 27326326 : lRealp += sidesMul * lRealpTmp;
1314 27326326 : lImagp += sidesMul * lImagpTmp;
1315 27326326 : rRealp += sidesMul * rRealpTmp;
1316 27326326 : rImagp += sidesMul * rImagpTmp;
1317 :
1318 : /* Apply the gain for the right source of the three coherent sources.
1319 : * -30 degrees to 330 wrapping due to internal functions. */
1320 27326326 : getDirectPartGains( bin, aziDeg + 330, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[gainCacheBaseIndex + 2], isHeadtracked, *hDiracDecBin->phHrtfParambin );
1321 27326326 : hrtfEneSides += ( lRealpTmp * lRealpTmp ) + ( lImagpTmp * lImagpTmp ) + ( rRealpTmp * rRealpTmp ) + ( rImagpTmp * rImagpTmp );
1322 27326326 : lRealp += sidesMul * lRealpTmp;
1323 27326326 : lImagp += sidesMul * lImagpTmp;
1324 27326326 : rRealp += sidesMul * rRealpTmp;
1325 27326326 : rImagp += sidesMul * rImagpTmp;
1326 :
1327 : /* Formulate an eneCorrectionFactor that compensates for the coherent summation of the HRTFs */
1328 27326326 : hrtfEneRealized = ( lRealp * lRealp ) + ( lImagp * lImagp ) + ( rRealp * rRealp ) + ( rImagp * rImagp );
1329 54652652 : eneCorrectionFactor = ( ( hrtfEneSides * sidesMul * sidesMul ) +
1330 27326326 : ( hrtfEneCenter * centerMul * centerMul ) ) /
1331 27326326 : max( 1e-12f, hrtfEneRealized );
1332 :
1333 : /* Weighting factors to determine appropriate target spectrum for spread coherent sound */
1334 27326326 : if ( spreadCoh < 0.5 )
1335 : {
1336 26178350 : w1 = 1.0f - 2.0f * spreadCoh;
1337 26178350 : w2 = 2.0f * spreadCoh;
1338 26178350 : w3 = 0.0f;
1339 : }
1340 : else
1341 : {
1342 1147976 : w1 = 0.0f;
1343 1147976 : w2 = 2.0f - 2.0f * spreadCoh;
1344 1147976 : w3 = 2.0f * spreadCoh - 1.0f;
1345 : }
1346 :
1347 27326326 : if ( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) )
1348 : {
1349 975814 : idx = min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 );
1350 :
1351 : /* Apply the target spectrum to the eneCorrectionFactor */
1352 975814 : if ( separateCenterChannelRendering ) /* spreadCoh mostly originates from phantom sources in separate channel rendering mode */
1353 : {
1354 7826 : eneCorrectionFactor *= w1 * 1.0f + ( w2 + w3 ) * spreadCohEne1[idx];
1355 : }
1356 : else
1357 : {
1358 967988 : eneCorrectionFactor *= w1 * 1.0f + w2 * spreadCohEne05[idx] + w3 * spreadCohEne1[idx];
1359 : }
1360 : }
1361 :
1362 : /* Equalize the spread coherent combined HRTFs */
1363 27326326 : eq = min( 4.0f, sqrtf( eneCorrectionFactor ) );
1364 27326326 : lRealp *= eq;
1365 27326326 : lImagp *= eq;
1366 27326326 : rRealp *= eq;
1367 27326326 : rImagp *= eq;
1368 : }
1369 :
1370 120724049 : hrtfEne[0] = ( lRealp * lRealp ) + ( lImagp * lImagp );
1371 120724049 : hrtfEne[1] = ( rRealp * rRealp ) + ( rImagp * rImagp );
1372 120724049 : hrtfCrossRe = ( lRealp * rRealp ) + ( lImagp * rImagp );
1373 120724049 : hrtfCrossIm = ( -lImagp * rRealp ) + ( lRealp * rImagp );
1374 :
1375 : /* Add direct part (1 or 2) covariance matrix */
1376 120724049 : dirEne = ratio * meanEnePerCh;
1377 120724049 : hDiracDecBin->ChEneOut[0][bin] += dirEne * hrtfEne[0]; /* Dir ene part*/
1378 120724049 : hDiracDecBin->ChEneOut[1][bin] += dirEne * hrtfEne[1];
1379 120724049 : hDiracDecBin->ChCrossReOut[bin] += dirEne * hrtfCrossRe; /* Dir cross re */
1380 120724049 : hDiracDecBin->ChCrossImOut[bin] += dirEne * hrtfCrossIm; /* Dir cross im */
1381 : }
1382 :
1383 : /* Add diffuse / ambient part covariance matrix */
1384 93998180 : diffuseness = max( 0.0f, diffuseness );
1385 93998180 : diffEne = diffuseness * meanEnePerCh;
1386 93998180 : surCoh = hSpatParamRendCom->surroundingCoherence[dirac_read_idx][bin];
1387 :
1388 93998180 : diffusenessValForDecorrelationReduction = max( 0.0f, diffusenessValForDecorrelationReduction );
1389 93998180 : diffEneValForDecorrelationReduction = diffusenessValForDecorrelationReduction * meanEnePerCh;
1390 :
1391 93998180 : if ( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) )
1392 : {
1393 1713740 : if ( !hDiracDecBin->renderStereoOutputInsteadOfBinaural )
1394 : {
1395 : float spectrumModVal;
1396 :
1397 1713740 : idx = min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 );
1398 : /* Apply target spectrum that emphasizes low frequencies when the sound is surround coherent */
1399 1713740 : spectrumModVal = ( 1.0f - surCoh ) + surCoh * surCohEne[idx];
1400 1713740 : diffEne *= spectrumModVal;
1401 :
1402 : /* Modify also the value for decorrelation reduction */
1403 1713740 : diffEneValForDecorrelationReduction *= spectrumModVal;
1404 : }
1405 : }
1406 93998180 : hDiracDecBin->ChEneOut[0][bin] += diffEne; /* Diff ene part*/
1407 93998180 : hDiracDecBin->ChEneOut[1][bin] += diffEne;
1408 :
1409 93998180 : if ( hDiracDecBin->renderStereoOutputInsteadOfBinaural )
1410 : {
1411 : /* When rendering stereo, ambience (except for surround coherent sound) has zero ICC. */
1412 1032500 : hDiracDecBin->ChCrossReOut[bin] += surCoh * diffEne;
1413 : }
1414 : else /* When rendering binaural, ambience has frequency dependent ICC. */
1415 : {
1416 92965680 : if ( ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) && bin < BINAURAL_COHERENCE_DIFFERENCE_BINS )
1417 3900006 : {
1418 : float diffuseFieldCoherence;
1419 3900006 : diffuseFieldCoherence = hDiracDecBin->hDiffuseDist->diffuseRatioX[bin] * hDiracDecBin->diffuseFieldCoherenceX[bin] + hDiracDecBin->hDiffuseDist->diffuseRatioY[bin] * hDiracDecBin->diffuseFieldCoherenceY[bin] + hDiracDecBin->hDiffuseDist->diffuseRatioZ[bin] * hDiracDecBin->diffuseFieldCoherenceZ[bin];
1420 3900006 : hDiracDecBin->ChCrossReOut[bin] += ( ( 1.0f - surCoh ) * diffuseFieldCoherence + surCoh ) * diffEne;
1421 : }
1422 : else
1423 : {
1424 89065674 : hDiracDecBin->ChCrossReOut[bin] += ( ( 1.0f - surCoh ) * hDiracDecBin->diffuseFieldCoherence[bin] + surCoh ) * diffEne;
1425 : }
1426 : }
1427 :
1428 : /* Store parameters for formulating average diffuseness over frame */
1429 93998180 : hDiracDecBin->frameMeanDiffuseness[bin] += diffEneValForDecorrelationReduction;
1430 93998180 : frameMeanDiffusenessEneWeight[bin] += meanEnePerCh;
1431 : }
1432 :
1433 : /* Formulate average diffuseness over frame */
1434 95615361 : for ( bin = 0; bin < nBins; bin++ )
1435 : {
1436 93998180 : hDiracDecBin->frameMeanDiffuseness[bin] /= fmaxf( 1e-12f, frameMeanDiffusenessEneWeight[bin] );
1437 : }
1438 :
1439 95615361 : for ( bin = 0; bin < nBins; bin++ )
1440 : {
1441 93998180 : hDiracDecBin->ChCrossReOut[bin] *= qualityBasedSmFactor;
1442 93998180 : hDiracDecBin->ChCrossImOut[bin] *= qualityBasedSmFactor;
1443 :
1444 281994540 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1445 : {
1446 187996360 : hDiracDecBin->ChEneOut[ch][bin] *= qualityBasedSmFactor;
1447 : }
1448 :
1449 93998180 : hDiracDecBin->ChCrossReOut[bin] += IIReneLimiter[bin] * hDiracDecBin->ChCrossReOutPrev[bin];
1450 93998180 : hDiracDecBin->ChCrossImOut[bin] += IIReneLimiter[bin] * hDiracDecBin->ChCrossImOutPrev[bin];
1451 :
1452 281994540 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1453 : {
1454 187996360 : hDiracDecBin->ChEneOut[ch][bin] += IIReneLimiter[bin] * hDiracDecBin->ChEneOutPrev[ch][bin];
1455 : }
1456 :
1457 : /* Store energy values and coefficients for next round */
1458 93998180 : hDiracDecBin->ChCrossReOutPrev[bin] = hDiracDecBin->ChCrossReOut[bin];
1459 93998180 : hDiracDecBin->ChCrossImOutPrev[bin] = hDiracDecBin->ChCrossImOut[bin];
1460 :
1461 281994540 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1462 : {
1463 187996360 : hDiracDecBin->ChEneOutPrev[ch][bin] = hDiracDecBin->ChEneOut[ch][bin];
1464 : }
1465 : }
1466 :
1467 1617181 : return;
1468 : }
1469 :
1470 1617181 : static void ivas_dirac_dec_binaural_determine_processing_matrices(
1471 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
1472 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
1473 : PARAMBIN_REND_CONFIG_HANDLE hConfig,
1474 : const int16_t max_band_decorr,
1475 : float Rmat[3][3],
1476 : const int16_t subframe,
1477 : const int16_t isHeadtracked,
1478 : const int16_t nchanSeparateChannels,
1479 : const MASA_ISM_DATA_HANDLE hMasaIsmData )
1480 : {
1481 : int16_t chA, chB, bin;
1482 : int16_t separateCenterChannelRendering;
1483 : int16_t nBins;
1484 : int16_t dirac_read_idx;
1485 : PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_NUM_OBJECTS];
1486 : int16_t idx;
1487 : ISM_MODE ism_mode;
1488 : IVAS_FORMAT ivas_format;
1489 : MC_MODE mc_mode;
1490 : int32_t ivas_total_brate;
1491 : int16_t nchan_transport;
1492 :
1493 1617181 : ivas_format = hConfig->ivas_format;
1494 1617181 : separateCenterChannelRendering = nchanSeparateChannels > 0;
1495 1617181 : mc_mode = hConfig->mc_mode;
1496 1617181 : ivas_total_brate = hConfig->ivas_total_brate;
1497 1617181 : nchan_transport = hConfig->nchan_transport;
1498 1617181 : nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
1499 :
1500 1617181 : ism_mode = hConfig->ism_mode;
1501 :
1502 1617181 : dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
1503 :
1504 8085905 : for ( idx = 0; idx < MAX_NUM_OBJECTS; idx++ )
1505 : {
1506 6468724 : gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */
1507 : }
1508 :
1509 95615361 : for ( bin = 0; bin < nBins; bin++ )
1510 : {
1511 : float tmpMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmpMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], gain;
1512 : float CxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], CxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* Input covariance matrix */
1513 : float realizedOutputEne, targetOutputEne, missingOutputEne;
1514 : float CrEneL, CrEneR; /* Cr = residual decorrelated sound covariance matrix */
1515 : float CrCrossRe, CrCrossIm;
1516 : float Mre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Mim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], MdecRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], MdecIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* M = mixing matrix; Mdec = residual decorrelated signal mixing matrix */
1517 93998180 : float prototypeMtx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] = { { 1.0f, 0.05f }, { 0.05f, 1.0f } }; /* Prototype matrix determines a reference signal in mixing matrix determination */
1518 :
1519 93998180 : CrEneL = 0.0f;
1520 93998180 : CrEneR = 0.0f;
1521 :
1522 : /* Formulate main processing matrix M */
1523 93998180 : formulate2x2MixingMatrix( hDiracDecBin->ChEne[0][bin], hDiracDecBin->ChEne[1][bin],
1524 : hDiracDecBin->ChCrossRe[bin], hDiracDecBin->ChCrossIm[bin],
1525 : hDiracDecBin->ChEneOut[0][bin], hDiracDecBin->ChEneOut[1][bin],
1526 : hDiracDecBin->ChCrossReOut[bin], hDiracDecBin->ChCrossImOut[bin],
1527 : prototypeMtx, Mre, Mim, hDiracDecBin->reqularizationFactor );
1528 :
1529 : /* Load estimated covariance matrix to the [2][2] matrix form */
1530 93998180 : CxRe[0][0] = hDiracDecBin->ChEne[0][bin];
1531 93998180 : CxRe[1][1] = hDiracDecBin->ChEne[1][bin];
1532 93998180 : CxRe[1][0] = hDiracDecBin->ChCrossRe[bin];
1533 93998180 : CxRe[0][1] = hDiracDecBin->ChCrossRe[bin];
1534 93998180 : CxIm[0][0] = 0.0f;
1535 93998180 : CxIm[1][1] = 0.0f;
1536 93998180 : CxIm[1][0] = hDiracDecBin->ChCrossIm[bin];
1537 93998180 : CxIm[0][1] = -hDiracDecBin->ChCrossIm[bin];
1538 :
1539 : /* Make matrix multiplication M*Cx*M' to determine resulting covariance matrix of processing input with M */
1540 93998180 : matrixMul( Mre, Mim, CxRe, CxIm, tmpMtxRe, tmpMtxIm );
1541 93998180 : matrixTransp2Mul( tmpMtxRe, tmpMtxIm, Mre, Mim, resultMtxRe, resultMtxIm );
1542 :
1543 : /* When below the frequency limit where decorrelation is applied, we inject the decorrelated
1544 : * residual (or missing) signal component. The procedure is active when there are not enough independent
1545 : * signal energy to synthesize a signal with the target covariance matrix from the non-decorrelated signals */
1546 93998180 : if ( bin < max_band_decorr )
1547 : {
1548 : float decorrelationReductionFactor;
1549 :
1550 : /* Subtract the resulting covariance matrix from the target covariance matrix to determine
1551 : * what signal component is missing. The result is the target covariance matrix for the residual signal, i.e.,
1552 : * a residual covariance matrix. */
1553 39191085 : CrEneL = max( 0.0f, hDiracDecBin->ChEneOut[0][bin] - resultMtxRe[0][0] );
1554 39191085 : CrEneR = max( 0.0f, hDiracDecBin->ChEneOut[1][bin] - resultMtxRe[1][1] );
1555 39191085 : CrCrossRe = hDiracDecBin->ChCrossReOut[bin] - resultMtxRe[1][0];
1556 39191085 : CrCrossIm = hDiracDecBin->ChCrossImOut[bin] - resultMtxIm[1][0];
1557 :
1558 : /* The amount of the decorrelated sound is further controlled based on the spatial metadata,
1559 : * by determining an energy-suppressed residual covariance matrix that is a control parameter
1560 : * that guides the processing of the decorrelated sound to a residual signal.
1561 : * The procedure improves quality in e.g. double-talk 2-direction rendering situations.*/
1562 39191085 : if ( ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE )
1563 : {
1564 11108440 : decorrelationReductionFactor = 1.0f;
1565 : }
1566 28082645 : else if ( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) || ( ivas_format == MASA_FORMAT && nchan_transport == 1 ) )
1567 : {
1568 8660075 : decorrelationReductionFactor = sqrtf( fmaxf( 0.0f, hDiracDecBin->frameMeanDiffuseness[bin] ) );
1569 : }
1570 19422570 : else if ( ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) && nchan_transport == 1 )
1571 : {
1572 2996040 : decorrelationReductionFactor = 1.0f;
1573 : }
1574 : else
1575 : {
1576 16426530 : decorrelationReductionFactor = fmaxf( 0.0f, hDiracDecBin->frameMeanDiffuseness[bin] );
1577 : }
1578 39191085 : CrEneL *= decorrelationReductionFactor;
1579 39191085 : CrEneR *= decorrelationReductionFactor;
1580 39191085 : CrCrossRe *= decorrelationReductionFactor;
1581 39191085 : CrCrossIm *= decorrelationReductionFactor;
1582 :
1583 : /* Determine a residual mixing matrix Mdec for processing the decorrelated signal to obtain
1584 : * the residual signal (that has the residual covariance matrix) */
1585 39191085 : formulate2x2MixingMatrix( hDiracDecBin->ChEne[0][bin], hDiracDecBin->ChEne[1][bin],
1586 : 0.0f, 0.0f, /* Decorrelated signal has ideally no cross-terms */
1587 : CrEneL, CrEneR,
1588 : CrCrossRe, CrCrossIm,
1589 : prototypeMtx, MdecRe, MdecIm, 0.2f );
1590 : }
1591 : else
1592 : {
1593 164421285 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1594 : {
1595 109614190 : set_zero( MdecRe[chA], BINAURAL_CHANNELS );
1596 109614190 : set_zero( MdecIm[chA], BINAURAL_CHANNELS );
1597 : }
1598 : }
1599 :
1600 : /* The regularizations at determining mixing matrices cause signal energy to be lost to some degree, which is compensated for here */
1601 93998180 : realizedOutputEne = CrEneL + CrEneR + resultMtxRe[0][0] + resultMtxRe[1][1];
1602 93998180 : targetOutputEne = hDiracDecBin->ChEneOut[0][bin] + hDiracDecBin->ChEneOut[1][bin];
1603 93998180 : missingOutputEne = fmaxf( 0.0f, targetOutputEne - realizedOutputEne );
1604 :
1605 93998180 : gain = sqrtf( ( resultMtxRe[0][0] + resultMtxRe[1][1] + missingOutputEne ) /
1606 93998180 : fmaxf( 1e-12f, resultMtxRe[0][0] + resultMtxRe[1][1] ) );
1607 93998180 : gain = fminf( 4.0f, gain );
1608 :
1609 281994540 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1610 : {
1611 563989080 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
1612 : {
1613 375992720 : Mre[chA][chB] *= gain;
1614 375992720 : Mim[chA][chB] *= gain;
1615 : }
1616 : }
1617 :
1618 : /* Store processing matrices */
1619 281994540 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1620 : {
1621 563989080 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
1622 : {
1623 375992720 : hDiracDecBin->processMtxRePrev[chA][chB][bin] = hDiracDecBin->processMtxRe[chA][chB][bin];
1624 375992720 : hDiracDecBin->processMtxImPrev[chA][chB][bin] = hDiracDecBin->processMtxIm[chA][chB][bin];
1625 375992720 : hDiracDecBin->processMtxDecRePrev[chA][chB][bin] = hDiracDecBin->processMtxDecRe[chA][chB][bin];
1626 375992720 : hDiracDecBin->processMtxDecImPrev[chA][chB][bin] = hDiracDecBin->processMtxDecIm[chA][chB][bin];
1627 :
1628 375992720 : hDiracDecBin->processMtxRe[chA][chB][bin] = Mre[chA][chB];
1629 375992720 : hDiracDecBin->processMtxIm[chA][chB][bin] = Mim[chA][chB];
1630 375992720 : hDiracDecBin->processMtxDecRe[chA][chB][bin] = MdecRe[chA][chB];
1631 375992720 : hDiracDecBin->processMtxDecIm[chA][chB][bin] = MdecIm[chA][chB];
1632 : }
1633 : }
1634 :
1635 93998180 : if ( separateCenterChannelRendering )
1636 : {
1637 : /* The rendering of the separate center channel in masa + mono mode.
1638 : * The center channel is processed with a gain factor 0.8414f to match the loudness of different processing paths */
1639 : float lRealp, lImagp, rRealp, rImagp;
1640 : float gainFactor;
1641 11032200 : int16_t aziDeg = 0;
1642 11032200 : int16_t eleDeg = 0;
1643 11032200 : uint8_t instantChange = 0;
1644 :
1645 11032200 : if ( ivas_format == MASA_ISM_FORMAT )
1646 : {
1647 11017200 : gainFactor = OMASA_TDREND_MATCHING_GAIN * sqrtf( hDiracDecBin->earlyPartEneCorrection[bin] );
1648 : }
1649 : else
1650 : {
1651 15000 : gainFactor = 0.8414f * sqrtf( hDiracDecBin->earlyPartEneCorrection[bin] );
1652 : }
1653 :
1654 22298160 : for ( chB = 0; chB < nchanSeparateChannels; chB++ )
1655 : {
1656 11265960 : if ( ivas_format == MASA_ISM_FORMAT )
1657 : {
1658 11250960 : if ( ism_mode == ISM_MASA_MODE_DISC )
1659 : {
1660 372840 : if ( hMasaIsmData->ism_dir_is_edited[chB] )
1661 : {
1662 0 : aziDeg = hMasaIsmData->azimuth_ism_edited[chB];
1663 0 : eleDeg = hMasaIsmData->elevation_ism_edited[chB];
1664 : }
1665 : else
1666 : {
1667 372840 : aziDeg = hMasaIsmData->azimuth_ism[chB][dirac_read_idx];
1668 372840 : eleDeg = hMasaIsmData->elevation_ism[chB][dirac_read_idx];
1669 : }
1670 : }
1671 : else
1672 : {
1673 10878120 : if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ && hMasaIsmData->ism_dir_is_edited[hMasaIsmData->idx_separated_ism] )
1674 : {
1675 47760 : aziDeg = hMasaIsmData->azimuth_ism_edited[hMasaIsmData->idx_separated_ism];
1676 47760 : eleDeg = hMasaIsmData->elevation_ism_edited[hMasaIsmData->idx_separated_ism];
1677 : }
1678 : else
1679 : {
1680 10830360 : aziDeg = hMasaIsmData->azimuth_separated_ism[dirac_read_idx];
1681 10830360 : eleDeg = hMasaIsmData->elevation_separated_ism[dirac_read_idx];
1682 : }
1683 10878120 : instantChange = 1;
1684 : }
1685 : }
1686 :
1687 33797880 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1688 : {
1689 22531920 : hDiracDecBin->processMtxRePrev[chA][chB + 2][bin] = hDiracDecBin->processMtxRe[chA][chB + 2][bin];
1690 22531920 : hDiracDecBin->processMtxImPrev[chA][chB + 2][bin] = hDiracDecBin->processMtxIm[chA][chB + 2][bin];
1691 : }
1692 :
1693 11265960 : getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[chB], isHeadtracked, *hDiracDecBin->phHrtfParambin );
1694 :
1695 11265960 : hDiracDecBin->processMtxRe[0][chB + 2][bin] = lRealp * gainFactor;
1696 11265960 : hDiracDecBin->processMtxIm[0][chB + 2][bin] = lImagp * gainFactor;
1697 11265960 : hDiracDecBin->processMtxRe[1][chB + 2][bin] = rRealp * gainFactor;
1698 11265960 : hDiracDecBin->processMtxIm[1][chB + 2][bin] = rImagp * gainFactor;
1699 :
1700 11265960 : if ( instantChange )
1701 : {
1702 32634360 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1703 : {
1704 21756240 : hDiracDecBin->processMtxRePrev[chA][chB + 2][bin] = hDiracDecBin->processMtxRe[chA][chB + 2][bin];
1705 21756240 : hDiracDecBin->processMtxImPrev[chA][chB + 2][bin] = hDiracDecBin->processMtxIm[chA][chB + 2][bin];
1706 : }
1707 : }
1708 : }
1709 : }
1710 : }
1711 :
1712 1617181 : return;
1713 : }
1714 :
1715 :
1716 1617181 : static void ivas_dirac_dec_binaural_process_output(
1717 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
1718 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
1719 : HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS],
1720 : float *output_f[],
1721 : float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1722 : float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1723 : const int16_t max_band_decorr,
1724 : const int16_t numInChannels,
1725 : const int16_t processReverb,
1726 : const int16_t subframe,
1727 : float outRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1728 : float outIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1729 : float reverbRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1730 : float reverbIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1731 : float decorrRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1732 : float decorrIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1733 : const uint8_t recompute )
1734 : {
1735 : int16_t slot, bin, chA, chB;
1736 : int16_t nBins;
1737 : float outSlotRe[CLDFB_NO_CHANNELS_MAX], outSlotIm[CLDFB_NO_CHANNELS_MAX];
1738 : float decSlotRe[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], decSlotIm[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1739 : float interpVal;
1740 : float *decSlotRePointer;
1741 : float *decSlotImPointer;
1742 : int16_t offsetSamples;
1743 : int16_t nSlots;
1744 :
1745 1617181 : nBins = hSpatParamRendCom->num_freq_bands;
1746 1617181 : offsetSamples = 0;
1747 1617181 : nSlots = hSpatParamRendCom->subframe_nbslots[subframe];
1748 :
1749 1617181 : if ( processReverb )
1750 : {
1751 : /* Process second / room effect part of binaural output when needed */
1752 121404 : if ( recompute == 1 )
1753 : {
1754 121404 : ivas_binaural_reverb_processSubframe( hDiracDecBin->hReverb, numInChannels, nSlots, inRe, inIm, reverbRe, reverbIm );
1755 : }
1756 : }
1757 :
1758 1617181 : interpVal = 0.0f;
1759 8006107 : for ( slot = 0; slot < nSlots; slot++ )
1760 : {
1761 6388926 : interpVal += 1.0f / (float) nSlots;
1762 6388926 : if ( !hDiracDecBin->useTdDecorr && max_band_decorr > 0 )
1763 : {
1764 4752599 : if ( recompute == 1 )
1765 : {
1766 1606435 : ivas_dirac_dec_decorrelate_slot( hDiracDecBin, nBins, slot, inRe, inIm, decSlotRe, decSlotIm );
1767 :
1768 4819305 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1769 : {
1770 3212870 : mvr2r( decSlotRe[chA], decorrRe[chA][slot], CLDFB_NO_CHANNELS_MAX );
1771 3212870 : mvr2r( decSlotIm[chA], decorrIm[chA][slot], CLDFB_NO_CHANNELS_MAX );
1772 : }
1773 : }
1774 : else
1775 : {
1776 9438492 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1777 : {
1778 6292328 : mvr2r( decorrRe[chA][slot], decSlotRe[chA], CLDFB_NO_CHANNELS_MAX );
1779 6292328 : mvr2r( decorrIm[chA][slot], decSlotIm[chA], CLDFB_NO_CHANNELS_MAX );
1780 : }
1781 : }
1782 : }
1783 :
1784 19166778 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1785 : {
1786 : float *outSlotRePr, *outSlotImPr; /* Pointers needed for function call compatibility */
1787 :
1788 12777852 : set_zero( outSlotRe, CLDFB_NO_CHANNELS_MAX );
1789 12777852 : set_zero( outSlotIm, CLDFB_NO_CHANNELS_MAX );
1790 :
1791 : /* Processing of the first / HRTF part of the binaural output. */
1792 39795418 : for ( chB = 0; chB < numInChannels; chB++ )
1793 : {
1794 27017566 : if ( chB < BINAURAL_CHANNELS )
1795 : {
1796 : /* Decorrelator signal for TD decorrelation is stored in two input channels above the two normal inputs.
1797 : * It should be noted that TD decorrelation is used only in cases where numInChannels is 2. If this
1798 : * changes, additional adjustments are required. When using CLDFB decorrelator, we simply assign the
1799 : * pointers to buffers. */
1800 25555704 : if ( hDiracDecBin->useTdDecorr )
1801 : {
1802 5825016 : decSlotRePointer = inRe[chB + 2][slot];
1803 5825016 : decSlotImPointer = inIm[chB + 2][slot];
1804 : }
1805 : else
1806 : {
1807 19730688 : decSlotRePointer = decSlotRe[chB];
1808 19730688 : decSlotImPointer = decSlotIm[chB];
1809 : }
1810 : }
1811 : else
1812 : {
1813 1461862 : decSlotRePointer = NULL; /* below these pointers are used only for chB < 2 */
1814 1461862 : decSlotImPointer = NULL;
1815 : }
1816 :
1817 :
1818 1598278966 : for ( bin = 0; bin < nBins; bin++ )
1819 : {
1820 : float gain;
1821 :
1822 : /* Mixing using the formulated processing matrix M */
1823 1571261400 : gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxRePrev[chA][chB][bin] +
1824 1571261400 : interpVal * hDiracDecBin->processMtxRe[chA][chB][bin];
1825 1571261400 : outSlotRe[bin] += gain * inRe[chB][slot][bin];
1826 1571261400 : outSlotIm[bin] += gain * inIm[chB][slot][bin];
1827 :
1828 1571261400 : gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxImPrev[chA][chB][bin] +
1829 1571261400 : interpVal * hDiracDecBin->processMtxIm[chA][chB][bin];
1830 1571261400 : outSlotRe[bin] -= gain * inIm[chB][slot][bin];
1831 1571261400 : outSlotIm[bin] += gain * inRe[chB][slot][bin];
1832 :
1833 : /* Mixing decorrelated signals using the formulated residual processing matrix Mdec */
1834 1571261400 : if ( bin < max_band_decorr && chB < 2 )
1835 : {
1836 615965620 : gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxDecRePrev[chA][chB][bin] +
1837 615965620 : interpVal * hDiracDecBin->processMtxDecRe[chA][chB][bin];
1838 615965620 : outSlotRe[bin] += gain * decSlotRePointer[bin];
1839 615965620 : outSlotIm[bin] += gain * decSlotImPointer[bin];
1840 :
1841 615965620 : gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxDecImPrev[chA][chB][bin] +
1842 615965620 : interpVal * hDiracDecBin->processMtxDecIm[chA][chB][bin];
1843 615965620 : outSlotRe[bin] -= gain * decSlotImPointer[bin];
1844 615965620 : outSlotIm[bin] += gain * decSlotRePointer[bin];
1845 : }
1846 : }
1847 : }
1848 :
1849 12777852 : if ( processReverb )
1850 : {
1851 : /* Combine second (reverb) part with the first (HRTF) part to obtain binaural output signal with room effect */
1852 966444 : v_add( outSlotRe, reverbRe[chA][slot], outSlotRe, CLDFB_NO_CHANNELS_MAX );
1853 966444 : v_add( outSlotIm, reverbIm[chA][slot], outSlotIm, CLDFB_NO_CHANNELS_MAX );
1854 : }
1855 :
1856 12777852 : outSlotRePr = &( outSlotRe[0] );
1857 12777852 : outSlotImPr = &( outSlotIm[0] );
1858 :
1859 12777852 : if ( outRe != NULL && outIm != NULL )
1860 : {
1861 : /* provide the data outside in CLDFB domain => mainly for split rendering */
1862 10351918 : mvr2r( outSlotRePr, outRe[chA][slot], CLDFB_NO_CHANNELS_MAX );
1863 10351918 : mvr2r( outSlotImPr, outIm[chA][slot], CLDFB_NO_CHANNELS_MAX );
1864 : }
1865 12777852 : if ( recompute == 1 )
1866 : {
1867 : /* Inverse filter bank */
1868 4971908 : cldfbSynthesis( &outSlotRePr, &outSlotImPr, &( output_f[chA][nBins * slot + offsetSamples] ), nBins, cldfbSynDec[chA] );
1869 : }
1870 : }
1871 : }
1872 :
1873 1617181 : return;
1874 : }
1875 :
1876 :
1877 310333 : static void adaptTransportSignalsHeadtracked(
1878 : COMBINED_ORIENTATION_HANDLE hHeadTrackData,
1879 : float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1880 : float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1881 : const int16_t nBins,
1882 : const int16_t nSlots,
1883 : float Rmat[3][3] )
1884 : {
1885 : int16_t slot, ch, bin, louderCh;
1886 : float ILD, mono_factor_ILD, mono_factor_rotation, mono_factor, y_val, ene_proc, ene_target;
1887 : int16_t max_band;
1888 : float eqVal;
1889 : int16_t band_idx, bin_lo, bin_hi;
1890 :
1891 : /* Determine head-orientation-based mono factor.
1892 : Rmat[1][1] entry informs how close the ears are aligned according to transport signals. */
1893 310333 : y_val = 1.0f - fabsf( Rmat[1][1] );
1894 310333 : mono_factor_rotation = ( y_val - ADAPT_HTPROTO_ROT_LIM_0 ) / ( ADAPT_HTPROTO_ROT_LIM_1 - ADAPT_HTPROTO_ROT_LIM_0 );
1895 310333 : mono_factor_rotation = fmaxf( 0.0f, fminf( 1.0f, mono_factor_rotation ) );
1896 :
1897 : /* Adapt transport signals in frequency bands */
1898 : /* optimization grouping CLDFB bins into MASA bands (they are readily available in ROM and suitable for the task) AND group CLDFB slots into sub-frames */
1899 :
1900 310333 : max_band = 0;
1901 7704325 : while ( max_band < MASA_FREQUENCY_BANDS && MASA_band_grouping_24[max_band] < nBins )
1902 : {
1903 7393992 : max_band++;
1904 : }
1905 :
1906 7704325 : for ( band_idx = 0; band_idx < max_band; band_idx++ )
1907 : {
1908 : float ch_nrg[2]; /* storage for input signal channel energies */
1909 7393992 : bin_lo = MASA_band_grouping_24[band_idx];
1910 7393992 : bin_hi = min( MASA_band_grouping_24[band_idx + 1], (int16_t) nBins );
1911 22181976 : for ( ch = 0; ch < 2; ch++ )
1912 : {
1913 14787984 : ch_nrg[ch] = 0.0f;
1914 73483152 : for ( slot = 0; slot < nSlots; slot++ )
1915 : {
1916 197873088 : for ( bin = bin_lo; bin < bin_hi; bin++ )
1917 : {
1918 139177920 : ch_nrg[ch] += ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] );
1919 : }
1920 : }
1921 14787984 : hHeadTrackData->chEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC;
1922 14787984 : hHeadTrackData->chEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * ch_nrg[ch];
1923 : }
1924 :
1925 : /* Determine ILD */
1926 7393992 : ILD = fabsf( 10.0f * log10f( fmaxf( 1e-12f, hHeadTrackData->chEneIIR[0][band_idx] ) / fmaxf( 1e-12f, hHeadTrackData->chEneIIR[1][band_idx] ) ) );
1927 7393992 : if ( hHeadTrackData->chEneIIR[1][band_idx] > hHeadTrackData->chEneIIR[0][band_idx] )
1928 : {
1929 3224907 : louderCh = 1;
1930 : }
1931 : else
1932 : {
1933 4169085 : louderCh = 0;
1934 : }
1935 :
1936 : /* Determine ILD-based mono factor */
1937 7393992 : mono_factor_ILD = ( ILD - ADAPT_HTPROTO_ILD_LIM_DB0 ) / ( ADAPT_HTPROTO_ILD_LIM_DB1 - ADAPT_HTPROTO_ILD_LIM_DB0 );
1938 7393992 : mono_factor_ILD = fmaxf( 0.0f, fminf( 1.0f, mono_factor_ILD ) );
1939 :
1940 : /* Combine mono factors */
1941 7393992 : mono_factor = mono_factor_ILD * mono_factor_rotation;
1942 :
1943 : /* Mix original audio and sum signal according to determined mono factor */
1944 22181976 : for ( ch = 0; ch < 2; ch++ )
1945 : {
1946 14787984 : if ( ch != louderCh )
1947 : {
1948 7393992 : float band_nrg = 0.0f;
1949 :
1950 36741576 : for ( slot = 0; slot < nSlots; slot++ )
1951 : {
1952 98936544 : for ( bin = bin_lo; bin < bin_hi; bin++ )
1953 : {
1954 : /* mono sum signal with the computed weight + rest from the original channel */
1955 69588960 : inRe[ch][slot][bin] = mono_factor * ( inRe[0][slot][bin] + inRe[1][slot][bin] ) + ( 1.0f - mono_factor ) * inRe[ch][slot][bin];
1956 69588960 : inIm[ch][slot][bin] = mono_factor * ( inIm[0][slot][bin] + inIm[1][slot][bin] ) + ( 1.0f - mono_factor ) * inIm[ch][slot][bin];
1957 69588960 : band_nrg += ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] );
1958 : }
1959 : }
1960 7393992 : hHeadTrackData->procChEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC;
1961 7393992 : hHeadTrackData->procChEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * band_nrg;
1962 : }
1963 : else
1964 : {
1965 : /* processed signal is input. use the original channel, so no need to compute new signals or signal energy */
1966 7393992 : hHeadTrackData->procChEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC;
1967 7393992 : hHeadTrackData->procChEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * ch_nrg[ch];
1968 : }
1969 : }
1970 :
1971 : /* Equalize */
1972 7393992 : ene_target = hHeadTrackData->chEneIIR[0][band_idx] + hHeadTrackData->chEneIIR[1][band_idx];
1973 7393992 : ene_proc = hHeadTrackData->procChEneIIR[0][band_idx] + hHeadTrackData->procChEneIIR[1][band_idx];
1974 7393992 : eqVal = fminf( 4.0f, sqrtf( ene_target / fmaxf( 1e-12f, ene_proc ) ) );
1975 :
1976 36741576 : for ( slot = 0; slot < nSlots; slot++ )
1977 : {
1978 88042752 : for ( ch = 0; ch < 2; ch++ )
1979 : {
1980 197873088 : for ( bin = bin_lo; bin < bin_hi; bin++ )
1981 : {
1982 139177920 : inRe[ch][slot][bin] *= eqVal;
1983 139177920 : inIm[ch][slot][bin] *= eqVal;
1984 : }
1985 : }
1986 : }
1987 : }
1988 :
1989 310333 : return;
1990 : }
1991 :
1992 310333 : static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked(
1993 : COMBINED_ORIENTATION_HANDLE hHeadTrackData,
1994 : float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1995 : float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1996 : const int16_t nBins,
1997 : const int16_t nSlots,
1998 : float Rmat[3][3] )
1999 : {
2000 : int16_t slot, bin, ch;
2001 : float tmpVal;
2002 :
2003 : /* When not currently in prototype signal left-right switching procedure, check if such switching is needed */
2004 310333 : if ( hHeadTrackData->lrSwitchedNext == hHeadTrackData->lrSwitchedCurrent )
2005 : {
2006 167208 : float thresholdDotProduct = 0.17f; /* Corresponds to 10-degree switching threshold */
2007 167208 : if ( ( hHeadTrackData->lrSwitchedCurrent == 0 ) && ( Rmat[1][1] < -thresholdDotProduct ) )
2008 : {
2009 794 : hHeadTrackData->lrSwitchedNext = 1;
2010 : }
2011 167208 : if ( ( hHeadTrackData->lrSwitchedCurrent == 1 ) && ( Rmat[1][1] > thresholdDotProduct ) )
2012 : {
2013 788 : hHeadTrackData->lrSwitchedNext = 0;
2014 : }
2015 : }
2016 :
2017 : /* When currently in interpolation */
2018 310333 : if ( hHeadTrackData->lrSwitchedNext != hHeadTrackData->lrSwitchedCurrent )
2019 : {
2020 716452 : for ( slot = 0; slot < nSlots; slot++ )
2021 : {
2022 : float switchOrderFactor, origOrderFactor;
2023 :
2024 571745 : hHeadTrackData->lrSwitchInterpVal += 0.0025f; /* Corresponds to 0.5 seconds interpolation time */
2025 :
2026 571745 : if ( hHeadTrackData->lrSwitchInterpVal > 0.999f )
2027 : {
2028 : /* Stop interpolation, reset values */
2029 1270 : hHeadTrackData->lrSwitchInterpVal = 0.0f;
2030 1270 : hHeadTrackData->lrSwitchedCurrent = hHeadTrackData->lrSwitchedNext;
2031 : }
2032 :
2033 : /* Gains for determining portion of switched channel order and original channel order */
2034 571745 : tmpVal = (float) hHeadTrackData->lrSwitchedNext * hHeadTrackData->lrSwitchInterpVal;
2035 571745 : tmpVal += (float) hHeadTrackData->lrSwitchedCurrent * ( 1.0f - hHeadTrackData->lrSwitchInterpVal );
2036 571745 : switchOrderFactor = sqrtf( tmpVal );
2037 571745 : origOrderFactor = sqrtf( 1.0f - tmpVal );
2038 :
2039 34476445 : for ( bin = 0; bin < nBins; bin++ )
2040 : {
2041 : /* determine original order (1) signals and switched order (2) signals */
2042 : float re1[BINAURAL_CHANNELS], re2[BINAURAL_CHANNELS], im1[BINAURAL_CHANNELS], im2[BINAURAL_CHANNELS];
2043 :
2044 101714100 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2045 : {
2046 67809400 : re1[ch] = inRe[ch][slot][bin] * origOrderFactor;
2047 67809400 : re2[ch] = inRe[1 - ch][slot][bin] * switchOrderFactor;
2048 67809400 : im1[ch] = inIm[ch][slot][bin] * origOrderFactor;
2049 67809400 : im2[ch] = inIm[1 - ch][slot][bin] * switchOrderFactor;
2050 : }
2051 :
2052 101714100 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2053 : {
2054 : float eneRef, ene, eq;
2055 :
2056 : /* Interpolate / mix original and switched order signals */
2057 67809400 : inRe[ch][slot][bin] = re1[ch] + re2[ch];
2058 67809400 : inIm[ch][slot][bin] = im1[ch] + im2[ch];
2059 :
2060 : /* Equalize interpolated signals to preserve energy per bin */
2061 67809400 : eneRef = ( re1[ch] * re1[ch] ) + ( re2[ch] * re2[ch] ) + ( im1[ch] * im1[ch] ) + ( im2[ch] * im2[ch] );
2062 67809400 : ene = ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] );
2063 67809400 : eq = sqrtf( eneRef / fmaxf( 1e-12f, ene ) );
2064 67809400 : eq = fminf( 4.0f, eq );
2065 67809400 : inRe[ch][slot][bin] *= eq;
2066 67809400 : inIm[ch][slot][bin] *= eq;
2067 : }
2068 : }
2069 : }
2070 : }
2071 : else
2072 : {
2073 : /* If not in interpolation, but in switched prototype situation, then switch left and right channels */
2074 165626 : if ( hHeadTrackData->lrSwitchedCurrent == 1 )
2075 : {
2076 313392 : for ( slot = 0; slot < nSlots; slot++ )
2077 : {
2078 14773012 : for ( bin = 0; bin < nBins; bin++ )
2079 : {
2080 14522720 : tmpVal = inRe[0][slot][bin];
2081 14522720 : inRe[0][slot][bin] = inRe[1][slot][bin];
2082 14522720 : inRe[1][slot][bin] = tmpVal;
2083 14522720 : tmpVal = inIm[0][slot][bin];
2084 14522720 : inIm[0][slot][bin] = inIm[1][slot][bin];
2085 14522720 : inIm[1][slot][bin] = tmpVal;
2086 : }
2087 : }
2088 : }
2089 : }
2090 :
2091 310333 : return;
2092 : }
2093 :
2094 :
2095 266378530 : static void eig2x2(
2096 : const float E1,
2097 : const float E2,
2098 : const float Cre,
2099 : const float Cim,
2100 : float Ure[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2101 : float Uim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2102 : float D[BINAURAL_CHANNELS] )
2103 : {
2104 : int16_t chA, chB, ch;
2105 : float s, normVal, crossSquare, a, pm, add;
2106 :
2107 799135590 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2108 : {
2109 1598271180 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2110 : {
2111 1065514120 : Ure[chA][chB] = 0.0f;
2112 1065514120 : Uim[chA][chB] = 0.0f;
2113 : }
2114 : }
2115 :
2116 266378530 : crossSquare = ( Cre * Cre ) + ( Cim * Cim );
2117 266378530 : a = ( E1 + E2 ) * ( E1 + E2 ) - 4.0f * ( ( E1 * E2 ) - crossSquare );
2118 266378530 : pm = 0.5f * sqrtf( max( 0.0f, a ) );
2119 266378530 : add = 0.5f * ( E1 + E2 );
2120 :
2121 266378530 : D[0] = add + pm;
2122 266378530 : D[1] = max( 0.0f, add - pm );
2123 :
2124 : /* Numeric case, when input is practically zeros */
2125 266378530 : if ( D[0] < 1e-12f )
2126 : {
2127 683648 : Ure[0][0] = 1.0f;
2128 683648 : Ure[1][1] = 1.0f;
2129 :
2130 683648 : return;
2131 : }
2132 :
2133 : /* Numeric case, when input is near an identity matrix with a gain */
2134 265694882 : if ( pm < ( 1e-3f * add ) )
2135 : {
2136 22987169 : Ure[0][0] = 1.0f;
2137 22987169 : Ure[1][1] = 1.0f;
2138 :
2139 22987169 : return;
2140 : }
2141 :
2142 : /* Eigenvectors */
2143 728123139 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2144 : {
2145 485415426 : if ( fabsf( E2 - D[ch] ) > fabsf( E1 - D[ch] ) )
2146 : {
2147 210565801 : s = D[ch] - E2;
2148 210565801 : normVal = sqrtf( 1.0f / ( 1e-12f + crossSquare + s * s ) );
2149 :
2150 210565801 : Ure[0][ch] = s * normVal;
2151 210565801 : Ure[1][ch] = Cre * normVal;
2152 210565801 : Uim[1][ch] = Cim * normVal;
2153 : }
2154 : else
2155 : {
2156 274849625 : s = D[ch] - E1;
2157 274849625 : normVal = sqrtf( 1.0f / ( 1e-12f + crossSquare + s * s ) );
2158 :
2159 274849625 : Ure[1][ch] = s * normVal;
2160 274849625 : Ure[0][ch] = Cre * normVal;
2161 274849625 : Uim[0][ch] = -Cim * normVal;
2162 : }
2163 : }
2164 :
2165 242707713 : return;
2166 : }
2167 :
2168 :
2169 133189265 : static void matrixDiagMul(
2170 : float reIn[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2171 : float imIn[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2172 : const float D[BINAURAL_CHANNELS],
2173 : float reOut[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2174 : float imOut[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
2175 : {
2176 : int16_t chA, chB;
2177 :
2178 399567795 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2179 : {
2180 799135590 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2181 : {
2182 532757060 : reOut[chA][chB] = reIn[chA][chB] * D[chB];
2183 532757060 : imOut[chA][chB] = imIn[chA][chB] * D[chB];
2184 : }
2185 : }
2186 :
2187 133189265 : return;
2188 : }
2189 :
2190 :
2191 493565975 : static void matrixMul(
2192 : float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2193 : float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2194 : float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2195 : float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2196 : float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2197 : float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
2198 : {
2199 : int16_t chA, chB;
2200 :
2201 1480697925 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2202 : {
2203 2961395850 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2204 : {
2205 1974263900 : outRe[chA][chB] = Are[chA][0] * Bre[0][chB] + Are[chA][1] * Bre[1][chB];
2206 1974263900 : outRe[chA][chB] -= Aim[chA][0] * Bim[0][chB] + Aim[chA][1] * Bim[1][chB];
2207 1974263900 : outIm[chA][chB] = Aim[chA][0] * Bre[0][chB] + Aim[chA][1] * Bre[1][chB];
2208 1974263900 : outIm[chA][chB] += Are[chA][0] * Bim[0][chB] + Are[chA][1] * Bim[1][chB];
2209 : }
2210 : }
2211 :
2212 493565975 : return;
2213 : }
2214 :
2215 :
2216 133189265 : static void matrixTransp1Mul(
2217 : float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2218 : float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2219 : float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2220 : float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2221 : float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2222 : float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
2223 : {
2224 : int16_t chA, chB;
2225 :
2226 399567795 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2227 : {
2228 799135590 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2229 : {
2230 532757060 : outRe[chA][chB] = Are[0][chA] * Bre[0][chB] + Are[1][chA] * Bre[1][chB];
2231 532757060 : outRe[chA][chB] -= -Aim[0][chA] * Bim[0][chB] - Aim[1][chA] * Bim[1][chB];
2232 532757060 : outIm[chA][chB] = -Aim[0][chA] * Bre[0][chB] - Aim[1][chA] * Bre[1][chB];
2233 532757060 : outIm[chA][chB] += Are[0][chA] * Bim[0][chB] + Are[1][chA] * Bim[1][chB];
2234 : }
2235 : }
2236 :
2237 133189265 : return;
2238 : }
2239 :
2240 :
2241 360376710 : static void matrixTransp2Mul(
2242 : float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2243 : float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2244 : float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2245 : float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2246 : float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2247 : float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
2248 : {
2249 : int16_t chA, chB;
2250 :
2251 1081130130 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2252 : {
2253 2162260260 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2254 : {
2255 1441506840 : outRe[chA][chB] = Are[chA][0] * Bre[chB][0] + Are[chA][1] * Bre[chB][1];
2256 1441506840 : outRe[chA][chB] -= Aim[chA][0] * ( -Bim[chB][0] ) + Aim[chA][1] * ( -Bim[chB][1] );
2257 1441506840 : outIm[chA][chB] = Aim[chA][0] * Bre[chB][0] + Aim[chA][1] * Bre[chB][1];
2258 1441506840 : outIm[chA][chB] += Are[chA][0] * ( -Bim[chB][0] ) + Are[chA][1] * ( -Bim[chB][1] );
2259 : }
2260 : }
2261 :
2262 360376710 : return;
2263 : }
2264 :
2265 :
2266 133189265 : static void chol2x2(
2267 : const float E1,
2268 : const float E2,
2269 : const float Cre,
2270 : const float Cim,
2271 : float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2272 : float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
2273 : {
2274 : int16_t chA, chB;
2275 : float sqrtVal;
2276 :
2277 399567795 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2278 : {
2279 799135590 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2280 : {
2281 532757060 : outRe[chA][chB] = 0.0f;
2282 532757060 : outIm[chA][chB] = 0.0f;
2283 : }
2284 : }
2285 :
2286 133189265 : if ( E1 > E2 ) /* Perform Cholesky decomposition according to louder channel first */
2287 : {
2288 69076435 : outRe[0][0] = sqrtf( E1 );
2289 69076435 : outRe[1][0] = Cre / ( 1e-12f + outRe[0][0] );
2290 69076435 : outIm[1][0] = Cim / ( 1e-12f + outRe[0][0] );
2291 69076435 : sqrtVal = E2 - ( Cre * Cre + Cim * Cim ) / ( 1e-12f + E1 );
2292 69076435 : outRe[1][1] = sqrtf( max( 0.0f, sqrtVal ) );
2293 : }
2294 : else
2295 : {
2296 64112830 : outRe[1][1] = sqrtf( E2 );
2297 64112830 : outRe[0][1] = Cre / ( 1e-12f + outRe[1][1] );
2298 64112830 : outIm[0][1] = -Cim / ( 1e-12f + outRe[1][1] );
2299 64112830 : sqrtVal = E1 - ( Cre * Cre + Cim * Cim ) / ( 1e-12f + E2 );
2300 64112830 : outRe[0][0] = sqrtf( max( 0.0f, sqrtVal ) );
2301 : }
2302 :
2303 133189265 : return;
2304 : }
2305 :
2306 :
2307 133189265 : static void formulate2x2MixingMatrix(
2308 : float Ein1,
2309 : float Ein2,
2310 : float CinRe,
2311 : float CinIm,
2312 : float Eout1,
2313 : float Eout2,
2314 : float CoutRe,
2315 : float CoutIm,
2316 : float Q[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2317 : float Mre[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2318 : float Mim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2319 : const float regularizationFactor )
2320 : {
2321 : /*
2322 : This function implements a 2x2 solution for an optimized spatial audio rendering algorithm
2323 : Vilkamo, J., Bäckström, T. and Kuntz, A., 2013.
2324 : "Optimized covariance domain framework for time–frequency processing of spatial audio."
2325 : Journal of the Audio Engineering Society, 61(6), pp.403-411.
2326 :
2327 : The result of the formulas below are the same as those in the publication, however, some
2328 : derivation details differ for as simple as possible 2x2 formulattion
2329 : */
2330 : int16_t chA, chB;
2331 : float maxEne, maxEneDiv;
2332 : float KyRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], KyIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2333 : float Uxre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Uxim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2334 : float Sx[BINAURAL_CHANNELS], Kxre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Kxim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2335 : float tmpRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmpIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2336 : float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2337 : float Ure[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Uim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2338 : float D[BINAURAL_CHANNELS];
2339 : float div[BINAURAL_CHANNELS];
2340 : float Ghat[BINAURAL_CHANNELS];
2341 : float GhatQ[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2342 : float Pre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Pim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2343 :
2344 : /* Normalize energy values */
2345 133189265 : maxEne = Ein1;
2346 133189265 : maxEne = max( maxEne, Ein2 );
2347 133189265 : maxEne = max( maxEne, Eout1 );
2348 133189265 : maxEne = max( maxEne, Eout2 );
2349 133189265 : maxEneDiv = 1.0f / ( maxEne + 1e-12f );
2350 133189265 : Ein1 *= maxEneDiv;
2351 133189265 : Ein2 *= maxEneDiv;
2352 133189265 : CinRe *= maxEneDiv;
2353 133189265 : CinIm *= maxEneDiv;
2354 133189265 : Eout1 *= maxEneDiv;
2355 133189265 : Eout2 *= maxEneDiv;
2356 133189265 : CoutRe *= maxEneDiv;
2357 133189265 : CoutIm *= maxEneDiv;
2358 :
2359 : /* Cholesky decomposition of target / output covariance matrix */
2360 133189265 : chol2x2( Eout1, Eout2, CoutRe, CoutIm, KyRe, KyIm );
2361 :
2362 : /* Eigendecomposition of input covariance matrix */
2363 133189265 : eig2x2( Ein1, Ein2, CinRe, CinIm, Uxre, Uxim, Sx );
2364 :
2365 : /* Eigendecomposition to Kx -- Ux Sx Ux' -> Kx Kx'*/
2366 133189265 : Sx[0] = sqrtf( Sx[0] );
2367 133189265 : Sx[1] = sqrtf( Sx[1] );
2368 133189265 : matrixDiagMul( Uxre, Uxim, Sx, Kxre, Kxim );
2369 :
2370 : /* Regularize the diagonal Sx for matrix inversion */
2371 133189265 : Sx[0] = max( Sx[0], regularizationFactor * Sx[1] );
2372 133189265 : Sx[1] = max( Sx[1], regularizationFactor * Sx[0] );
2373 :
2374 : /* This is equivalent to the prototype signal energy normalization in the publication */
2375 133189265 : Ghat[0] = sqrtf( Eout1 / ( 1e-12f + max( Ein1, 0.001f * Ein2 ) ) );
2376 133189265 : Ghat[1] = sqrtf( Eout2 / ( 1e-12f + max( Ein2, 0.001f * Ein1 ) ) );
2377 :
2378 : /* Matrix multiplication, tmp = Ky' * G_hat * Q */
2379 399567795 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2380 : {
2381 266378530 : GhatQ[chA][0] = Q[chA][0] * Ghat[chA];
2382 266378530 : GhatQ[chA][1] = Q[chA][1] * Ghat[chA];
2383 : }
2384 399567795 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2385 : {
2386 799135590 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2387 : {
2388 532757060 : tmpRe[chA][chB] = KyRe[0][chA] * GhatQ[0][chB] + KyRe[1][chA] * GhatQ[1][chB];
2389 532757060 : tmpIm[chA][chB] = -KyIm[0][chA] * GhatQ[0][chB] - KyIm[1][chA] * GhatQ[1][chB];
2390 : }
2391 : }
2392 :
2393 : /* A = Ky' * G_hat * Q * Kx (see publication) */
2394 133189265 : matrixMul( tmpRe, tmpIm, Kxre, Kxim, Are, Aim );
2395 :
2396 : /* Find nearest orthonormal matrix P to A = Ky' * G_hat * Q * Kx
2397 : For matrix A that is P = A(A'A)^0.5
2398 : */
2399 133189265 : matrixTransp1Mul( Are, Aim, Are, Aim, tmpRe, tmpIm );
2400 :
2401 133189265 : eig2x2( tmpRe[0][0], tmpRe[1][1], tmpRe[1][0], tmpIm[1][0], Ure, Uim, D );
2402 :
2403 133189265 : div[0] = min( 10000.0f, sqrtf( 1.0f / ( 1e-12f + D[0] ) ) );
2404 133189265 : div[1] = min( 10000.0f, sqrtf( 1.0f / ( 1e-12f + D[1] ) ) );
2405 :
2406 133189265 : matrixMul( Are, Aim, Ure, Uim, tmpRe, tmpIm );
2407 :
2408 399567795 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2409 : {
2410 799135590 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2411 : {
2412 532757060 : tmpRe[chA][chB] *= div[chB];
2413 532757060 : tmpIm[chA][chB] *= div[chB];
2414 : }
2415 : }
2416 :
2417 133189265 : matrixTransp2Mul( tmpRe, tmpIm, Ure, Uim, Pre, Pim ); /* Nearest orthonormal matrix P to matrix A formulated */
2418 :
2419 : /* These are the final formulas of the JAES publication M = Ky P Kx^(-1) */
2420 399567795 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2421 : {
2422 799135590 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2423 : {
2424 532757060 : Pre[chA][chB] /= Sx[chB] + 1e-12f;
2425 532757060 : Pim[chA][chB] /= Sx[chB] + 1e-12f;
2426 : }
2427 : }
2428 :
2429 133189265 : matrixMul( KyRe, KyIm, Pre, Pim, tmpRe, tmpIm );
2430 :
2431 133189265 : matrixTransp2Mul( tmpRe, tmpIm, Uxre, Uxim, Mre, Mim );
2432 :
2433 133189265 : return;
2434 : }
2435 :
2436 :
2437 186642661 : static void getDirectPartGains(
2438 : const int16_t bin,
2439 : int16_t aziDeg,
2440 : int16_t eleDeg,
2441 : float *lRealp,
2442 : float *lImagp,
2443 : float *rRealp,
2444 : float *rImagp,
2445 : const uint8_t renderStereoOutputInsteadOfBinaural,
2446 : float Rmat[3][3],
2447 : PARAMBIN_HRTF_GAIN_CACHE *gainCache,
2448 : const int16_t isHeadtracked,
2449 : HRTFS_PARAMBIN_HANDLE hHrtfParambin )
2450 : {
2451 : float aziRad, eleRad;
2452 : float y, mappedX, aziRadMapped, A, A2, A3;
2453 186642661 : const float LsAngleRad = 30.0f * PI_OVER_180;
2454 :
2455 186642661 : if ( renderStereoOutputInsteadOfBinaural ) /* In stereo (i.e. non-binaural) rendering mode */
2456 : {
2457 1590118 : *lImagp = 0.0f;
2458 1590118 : *rImagp = 0.0f;
2459 1590118 : if ( aziDeg == gainCache->azi && eleDeg == gainCache->ele )
2460 : {
2461 1405205 : *lRealp = gainCache->shVec[0]; /* Reused memory */
2462 1405205 : *rRealp = gainCache->shVec[1]; /* Reused memory */
2463 : }
2464 : else
2465 : {
2466 : /* Convert azi and ele to an azi value of the cone of confusion */
2467 184913 : aziRad = (float) aziDeg * PI_OVER_180;
2468 184913 : eleRad = (float) eleDeg * PI_OVER_180;
2469 184913 : y = ( sinf( aziRad ) * cosf( eleRad ) );
2470 184913 : mappedX = sqrtf( max( 0.0f, 1.0f - ( y * y ) ) );
2471 184913 : aziRadMapped = atan2f( y, mappedX );
2472 :
2473 : /* Determine the real valued amplitude panning gains */
2474 184913 : if ( aziRadMapped >= LsAngleRad )
2475 : { /* Left side */
2476 54357 : *lRealp = 1.0f;
2477 54357 : *rRealp = 0.0f;
2478 : }
2479 130556 : else if ( aziRadMapped <= -LsAngleRad )
2480 : { /* Right side */
2481 76810 : *lRealp = 0.0f;
2482 76810 : *rRealp = 1.0f;
2483 : }
2484 : else /* Tangent panning law */
2485 : {
2486 53746 : A = tanf( aziRadMapped ) / tanf( LsAngleRad );
2487 53746 : A2 = ( A - 1.0f ) / max( 0.001f, A + 1.0f );
2488 53746 : A3 = 1.0f / ( A2 * A2 + 1.0f );
2489 53746 : *lRealp = sqrtf( A3 );
2490 53746 : *rRealp = sqrtf( 1.0f - A3 );
2491 : }
2492 : /* Scaling to have the same expected gain as for the HRTF rendering */
2493 184913 : *lRealp *= SQRT2;
2494 184913 : *rRealp *= SQRT2;
2495 :
2496 : /* Store to gain cache */
2497 184913 : gainCache->azi = aziDeg;
2498 184913 : gainCache->ele = eleDeg;
2499 184913 : gainCache->shVec[0] = *lRealp; /* Reuse memory */
2500 184913 : gainCache->shVec[1] = *rRealp; /* Reuse memory */
2501 : }
2502 : }
2503 : else /* In regular binaural rendering mode */
2504 : {
2505 185052543 : if ( aziDeg == gainCache->azi && eleDeg == gainCache->ele )
2506 : {
2507 143982739 : hrtfShGetHrtf( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, TRUE, hHrtfParambin );
2508 : }
2509 : else
2510 : {
2511 41069804 : gainCache->azi = aziDeg;
2512 41069804 : gainCache->ele = eleDeg;
2513 41069804 : if ( isHeadtracked )
2514 : {
2515 36549266 : rotateAziEle( (float) aziDeg, (float) eleDeg, &aziDeg, &eleDeg, Rmat, 0 );
2516 : }
2517 41069804 : hrtfShGetHrtf( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, FALSE, hHrtfParambin );
2518 : }
2519 : }
2520 :
2521 186642661 : return;
2522 : }
2523 :
2524 :
2525 185052543 : static void hrtfShGetHrtf(
2526 : const int16_t bin,
2527 : const int16_t aziDeg,
2528 : const int16_t eleDeg,
2529 : float *lRealp,
2530 : float *lImagp,
2531 : float *rRealp,
2532 : float *rImagp,
2533 : PARAMBIN_HRTF_GAIN_CACHE *gainCache,
2534 : const int16_t useCachedValue,
2535 : HRTFS_PARAMBIN_HANDLE hHrtfParambin )
2536 : {
2537 : int16_t k;
2538 : float( *hrtfShCoeffsReInt )[16][60];
2539 : float( *hrtfShCoeffsImInt )[16][60];
2540 185052543 : hrtfShCoeffsReInt = hHrtfParambin->hrtfShCoeffsRe;
2541 185052543 : hrtfShCoeffsImInt = hHrtfParambin->hrtfShCoeffsIm;
2542 :
2543 185052543 : *lRealp = 0.0f;
2544 185052543 : *lImagp = 0.0f;
2545 185052543 : *rRealp = 0.0f;
2546 185052543 : *rImagp = 0.0f;
2547 :
2548 185052543 : if ( useCachedValue )
2549 : {
2550 : float *shVec;
2551 143982739 : shVec = gainCache->shVec;
2552 :
2553 2447706563 : for ( k = 0; k < HRTF_SH_CHANNELS; k++ )
2554 : {
2555 2303723824 : *lRealp += hrtfShCoeffsReInt[0][k][bin] * shVec[k];
2556 2303723824 : *lImagp += hrtfShCoeffsImInt[0][k][bin] * shVec[k];
2557 2303723824 : *rRealp += hrtfShCoeffsReInt[1][k][bin] * shVec[k];
2558 2303723824 : *rImagp += hrtfShCoeffsImInt[1][k][bin] * shVec[k];
2559 : }
2560 : }
2561 : else
2562 : {
2563 : float shVec[HRTF_SH_CHANNELS];
2564 :
2565 41069804 : ivas_dirac_dec_get_response( aziDeg,
2566 : eleDeg,
2567 : shVec,
2568 : HRTF_SH_ORDER );
2569 :
2570 698186668 : for ( k = 0; k < HRTF_SH_CHANNELS; k++ )
2571 : {
2572 657116864 : *lRealp += hrtfShCoeffsReInt[0][k][bin] * shVec[k];
2573 657116864 : *lImagp += hrtfShCoeffsImInt[0][k][bin] * shVec[k];
2574 657116864 : *rRealp += hrtfShCoeffsReInt[1][k][bin] * shVec[k];
2575 657116864 : *rImagp += hrtfShCoeffsImInt[1][k][bin] * shVec[k];
2576 :
2577 657116864 : gainCache->shVec[k] = shVec[k];
2578 : }
2579 : }
2580 :
2581 185052543 : return;
2582 : }
2583 :
2584 :
2585 : /*-------------------------------------------------------------------------
2586 : * configure_reqularization_factor()
2587 : *
2588 : * Configure regularization factor for the mixing matrix generation of the
2589 : * parametric binauralizer using IVAS codec format and current bitrate.
2590 : *------------------------------------------------------------------------*/
2591 :
2592 : /*! r: Configured reqularization factor value */
2593 6260 : float configure_reqularization_factor(
2594 : const IVAS_FORMAT ivas_format, /* i : IVAS format */
2595 : const int32_t ivas_total_brate /* i : IVAS total bitrate */
2596 : )
2597 : {
2598 : float reqularizationFactor;
2599 6260 : reqularizationFactor = 1.0f; /* Default value */
2600 :
2601 6260 : if ( ivas_format == MASA_FORMAT )
2602 : {
2603 2712 : if ( ivas_total_brate >= IVAS_160k )
2604 : {
2605 161 : reqularizationFactor = 0.4f;
2606 : }
2607 2551 : else if ( ivas_total_brate == IVAS_128k )
2608 : {
2609 364 : reqularizationFactor = 0.5f;
2610 : }
2611 2187 : else if ( ivas_total_brate == IVAS_96k )
2612 : {
2613 96 : reqularizationFactor = 0.6f;
2614 : }
2615 2091 : else if ( ivas_total_brate >= IVAS_64k )
2616 : {
2617 205 : reqularizationFactor = 0.8f;
2618 : }
2619 : else
2620 : {
2621 1886 : reqularizationFactor = 1.0f;
2622 : }
2623 : }
2624 :
2625 6260 : if ( ivas_format == MC_FORMAT ) /* This is always McMASA for parametric binauralizer. */
2626 : {
2627 362 : if ( ivas_total_brate >= IVAS_96k )
2628 : {
2629 2 : reqularizationFactor = 0.4f;
2630 : }
2631 360 : else if ( ivas_total_brate >= IVAS_80k )
2632 : {
2633 4 : reqularizationFactor = 0.5f;
2634 : }
2635 356 : else if ( ivas_total_brate >= IVAS_64k )
2636 : {
2637 10 : reqularizationFactor = 0.7f;
2638 : }
2639 346 : else if ( ivas_total_brate >= IVAS_48k )
2640 : {
2641 15 : reqularizationFactor = 0.8f;
2642 : }
2643 : else
2644 : {
2645 331 : reqularizationFactor = 1.0f;
2646 : }
2647 : }
2648 :
2649 : /* For SBA and parametric ISM, currently in default value of 1.0f. */
2650 :
2651 6260 : return reqularizationFactor;
2652 : }
2653 :
2654 :
2655 : /*-------------------------------------------------------------------*
2656 : * ivas_omasa_preProcessStereoTransportsForEditedObjects()
2657 : *
2658 : *
2659 : *-------------------------------------------------------------------*/
2660 :
2661 75653 : void ivas_omasa_preProcessStereoTransportsForEditedObjects(
2662 : Decoder_Struct *st_ivas,
2663 : float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
2664 : float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
2665 : const int16_t nBins,
2666 : const int16_t subframe )
2667 : {
2668 : int16_t bin, ch, inCh, outCh, ismDirIndex, slot, band_idx, bin_lo, bin_hi, max_band, n_ism;
2669 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
2670 : MASA_ISM_DATA_HANDLE hMasaIsmData;
2671 : PARAM_ISM_DEC_HANDLE hParamIsmDec;
2672 : uint8_t enableCentering;
2673 : int16_t dirac_read_idx;
2674 : int16_t nSlots;
2675 : float panGainsOut[4][2];
2676 : float panGainsIn[4][2];
2677 : float panEnesOut[4][2];
2678 : float panEnesIn[4][2];
2679 : uint8_t ismGainEdited[4];
2680 : uint8_t ismDirEdited[4];
2681 : uint8_t masaGainEdited;
2682 : uint8_t masaIsmMode;
2683 :
2684 75653 : hSpatParamRendCom = st_ivas->hSpatParamRendCom;
2685 75653 : hMasaIsmData = st_ivas->hMasaIsmData;
2686 75653 : hParamIsmDec = st_ivas->hParamIsmDec;
2687 :
2688 75653 : if ( st_ivas->ivas_format == MASA_ISM_FORMAT )
2689 : {
2690 29841 : masaIsmMode = 1u;
2691 : }
2692 : else
2693 : {
2694 45812 : masaIsmMode = 0u;
2695 : }
2696 :
2697 75653 : if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_FOA || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_HOA2 || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_HOA3 )
2698 : {
2699 1268 : enableCentering = 0;
2700 : }
2701 : else
2702 : {
2703 74385 : enableCentering = 1;
2704 : }
2705 :
2706 75653 : if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ivas_format == ISM_FORMAT )
2707 : {
2708 48734 : n_ism = st_ivas->nchan_ism;
2709 : }
2710 : else
2711 : {
2712 26919 : n_ism = hSpatParamRendCom->numIsmDirections;
2713 : }
2714 :
2715 360408 : for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
2716 : {
2717 284755 : ismGainEdited[ismDirIndex] = hMasaIsmData->ism_gain_is_edited[ismDirIndex];
2718 284755 : ismDirEdited[ismDirIndex] = hMasaIsmData->ism_dir_is_edited[ismDirIndex];
2719 : }
2720 75653 : masaGainEdited = hMasaIsmData->masa_gain_is_edited;
2721 :
2722 : /* Bypass processing until first object is moved or gained */
2723 75653 : if ( hMasaIsmData->objectsEdited == 0 )
2724 : {
2725 293996 : for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
2726 : {
2727 231705 : if ( ismDirEdited[ismDirIndex] )
2728 : {
2729 609 : hMasaIsmData->objectsEdited = 1;
2730 : }
2731 :
2732 231705 : if ( ismGainEdited[ismDirIndex] )
2733 : {
2734 574 : hMasaIsmData->objectsEdited = 1;
2735 : }
2736 : }
2737 :
2738 62291 : if ( masaGainEdited )
2739 : {
2740 2 : hMasaIsmData->objectsEdited = 1;
2741 : }
2742 :
2743 62291 : if ( hMasaIsmData->objectsEdited == 0 )
2744 : {
2745 : /* No objects have moved so far */
2746 62138 : return;
2747 : }
2748 : }
2749 :
2750 : /* OMASA gaining for discrete OMASA mode with stereo_param/bin_room_param renderer */
2751 13515 : if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) && st_ivas->ism_mode == ISM_MASA_MODE_DISC )
2752 : {
2753 : /* ISM gaining */
2754 0 : for ( ch = 0; ch < n_ism; ch++ )
2755 : {
2756 0 : if ( st_ivas->hMasaIsmData->ism_gain_is_edited[ch] )
2757 : {
2758 0 : for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
2759 : {
2760 : float gain;
2761 0 : gain = st_ivas->hMasaIsmData->gain_ism_edited[ch];
2762 0 : v_multc( inRe[ch + 2][slot], gain, inRe[ch + 2][slot], nBins );
2763 0 : v_multc( inIm[ch + 2][slot], gain, inIm[ch + 2][slot], nBins );
2764 : }
2765 : }
2766 : }
2767 :
2768 : /* MASA gaining */
2769 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2770 : {
2771 0 : if ( masaGainEdited )
2772 : {
2773 0 : for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
2774 : {
2775 : float gain_masa;
2776 0 : gain_masa = st_ivas->hMasaIsmData->gain_masa_edited;
2777 0 : v_multc( inRe[ch][slot], gain_masa, inRe[ch][slot], nBins );
2778 0 : v_multc( inIm[ch][slot], gain_masa, inIm[ch][slot], nBins );
2779 : }
2780 : }
2781 : }
2782 : }
2783 13515 : else if ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->hISMDTX.dtx_flag ) /* If dtx on, perform just the smoothing of the processing gains */
2784 0 : {
2785 : float totalTargetEne;
2786 : float ismPreprocMtxNew[2][2];
2787 : float ismPreprocMtxIncrement[2][2];
2788 : float nSlotDiv;
2789 : float outSlotRe[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
2790 : float outSlotIm[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
2791 : float eqVal;
2792 :
2793 0 : nSlots = hSpatParamRendCom->subframe_nbslots[subframe];
2794 0 : nSlotDiv = 1.0f / ( (float) nSlots );
2795 :
2796 : /* Use diagonal mixing matrix as the instant mixing matrix, to slowly fade away the editing during dtx */
2797 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2798 : {
2799 0 : ismPreprocMtxNew[ch][ch] = 1.0f;
2800 0 : ismPreprocMtxNew[1 - ch][ch] = 0.0f;
2801 : }
2802 :
2803 : /* Determine the highest band */
2804 0 : max_band = 0;
2805 0 : while ( max_band < MAX_PARAM_ISM_NBANDS && hParamIsmDec->hParamIsm->band_grouping[max_band] < nBins )
2806 : {
2807 0 : max_band++;
2808 : }
2809 :
2810 : /* Init out array */
2811 0 : for ( slot = 0; slot < nSlots; slot++ )
2812 : {
2813 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2814 : {
2815 0 : set_zero( outSlotRe[ch][slot], CLDFB_NO_CHANNELS_MAX );
2816 0 : set_zero( outSlotIm[ch][slot], CLDFB_NO_CHANNELS_MAX );
2817 : }
2818 : }
2819 :
2820 : /* Perform the processing in frequency bands */
2821 0 : for ( band_idx = 0; band_idx < max_band; band_idx++ )
2822 : {
2823 0 : bin_lo = hParamIsmDec->hParamIsm->band_grouping[band_idx];
2824 0 : bin_hi = min( hParamIsmDec->hParamIsm->band_grouping[band_idx + 1], nBins );
2825 :
2826 : /* Determine transport energies */
2827 0 : totalTargetEne = 0.0f;
2828 0 : for ( slot = 0; slot < nSlots; slot++ )
2829 : {
2830 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2831 : {
2832 0 : for ( bin = bin_lo; bin < bin_hi; bin++ )
2833 : {
2834 0 : totalTargetEne += inRe[ch][slot][bin] * inRe[ch][slot][bin];
2835 0 : totalTargetEne += inIm[ch][slot][bin] * inIm[ch][slot][bin];
2836 : }
2837 : }
2838 : }
2839 :
2840 : /* Get increment value for temporal interpolation */
2841 0 : for ( inCh = 0; inCh < BINAURAL_CHANNELS; inCh++ )
2842 : {
2843 0 : for ( outCh = 0; outCh < BINAURAL_CHANNELS; outCh++ )
2844 : {
2845 0 : ismPreprocMtxIncrement[outCh][inCh] = ( ismPreprocMtxNew[outCh][inCh] - hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx] ) * nSlotDiv;
2846 : }
2847 : }
2848 :
2849 : /* Mix signals */
2850 0 : hMasaIsmData->preprocEneTarget[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
2851 0 : hMasaIsmData->preprocEneRealized[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
2852 0 : hMasaIsmData->preprocEneTarget[band_idx] += totalTargetEne;
2853 :
2854 0 : for ( outCh = 0; outCh < BINAURAL_CHANNELS; outCh++ )
2855 : {
2856 0 : for ( slot = 0; slot < nSlots; slot++ )
2857 : {
2858 0 : for ( inCh = 0; inCh < BINAURAL_CHANNELS; inCh++ )
2859 : {
2860 0 : hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx] += ismPreprocMtxIncrement[outCh][inCh];
2861 0 : for ( bin = bin_lo; bin < bin_hi; bin++ )
2862 : {
2863 0 : outSlotRe[outCh][slot][bin] += inRe[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx];
2864 0 : outSlotIm[outCh][slot][bin] += inIm[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx];
2865 : }
2866 : }
2867 :
2868 0 : for ( bin = bin_lo; bin < bin_hi; bin++ )
2869 : {
2870 0 : hMasaIsmData->preprocEneRealized[band_idx] += ( outSlotRe[outCh][slot][bin] * outSlotRe[outCh][slot][bin] ) + ( outSlotIm[outCh][slot][bin] * outSlotIm[outCh][slot][bin] );
2871 : }
2872 : }
2873 : }
2874 :
2875 0 : eqVal = fminf( 4.0f, sqrtf( hMasaIsmData->preprocEneTarget[band_idx] / fmaxf( 1e-12f, hMasaIsmData->preprocEneRealized[band_idx] ) ) );
2876 :
2877 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2878 : {
2879 0 : for ( slot = 0; slot < nSlots; slot++ )
2880 : {
2881 0 : for ( bin = bin_lo; bin < bin_hi; bin++ )
2882 : {
2883 0 : inRe[ch][slot][bin] = outSlotRe[ch][slot][bin] * eqVal;
2884 0 : inIm[ch][slot][bin] = outSlotIm[ch][slot][bin] * eqVal;
2885 : }
2886 : }
2887 : }
2888 : }
2889 : }
2890 : else /* Other processing modes */
2891 : {
2892 : float subframeEne;
2893 : float subframeEneCh[2];
2894 : float normEnes[2];
2895 : float ratioAccOrig;
2896 : float ratioAccNew;
2897 : float ratio;
2898 : float ismEneThis;
2899 : float ismTargetEneThis;
2900 : float ismTargetEneThisCh[2];
2901 : float totalTargetEneCh[2];
2902 : float totalTargetEne;
2903 : float masaTargetEneThisCh[2];
2904 : float ismPreprocMtxNew[2][2];
2905 : float ismPreprocMtxIncrement[2][2];
2906 : float eneMove[2];
2907 : float enePreserve[2];
2908 : float ismRatioAcc;
2909 : float remainderNormEne;
2910 : float centeringFactor;
2911 : float eneMoveThis;
2912 : float enePreserveThis;
2913 : float normVal;
2914 : float eqVal;
2915 : float outSlotRe[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
2916 : float outSlotIm[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
2917 : float newRatios[6];
2918 : float gainIsmThis;
2919 : float gainMasaPow2;
2920 : float nSlotDiv;
2921 : float tempDivisor;
2922 : float masaEneThisCh[2];
2923 : float ratioAccNewDivisor;
2924 :
2925 13515 : gainMasaPow2 = 1.0f;
2926 13515 : if ( masaGainEdited )
2927 : {
2928 792 : gainMasaPow2 = hMasaIsmData->gain_masa_edited;
2929 792 : gainMasaPow2 *= gainMasaPow2;
2930 : }
2931 :
2932 13515 : nSlots = hSpatParamRendCom->subframe_nbslots[subframe];
2933 13515 : dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
2934 13515 : nSlotDiv = 1.0f / ( (float) nSlots );
2935 :
2936 : /* Determine panning gains and energies for each object */
2937 67175 : for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
2938 : {
2939 : /* Get input and output panning gains */
2940 53660 : ivas_get_stereo_panning_gains( hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx],
2941 53660 : hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx],
2942 53660 : panGainsIn[ismDirIndex] );
2943 :
2944 53660 : if ( ismDirEdited[ismDirIndex] )
2945 : {
2946 53624 : ivas_get_stereo_panning_gains( hMasaIsmData->azimuth_ism_edited[ismDirIndex],
2947 53624 : hMasaIsmData->elevation_ism_edited[ismDirIndex],
2948 53624 : panGainsOut[ismDirIndex] );
2949 : }
2950 : else
2951 : {
2952 : /* When not edited, input and output pan gains are the same */
2953 108 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2954 : {
2955 72 : panGainsOut[ismDirIndex][ch] = panGainsIn[ismDirIndex][ch];
2956 : }
2957 : }
2958 :
2959 : /* Determine pan enes */
2960 160980 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2961 : {
2962 107320 : panEnesOut[ismDirIndex][ch] = panGainsOut[ismDirIndex][ch] * panGainsOut[ismDirIndex][ch];
2963 107320 : panEnesIn[ismDirIndex][ch] = panGainsIn[ismDirIndex][ch] * panGainsIn[ismDirIndex][ch];
2964 : }
2965 : }
2966 :
2967 : /* Determine the highest band */
2968 13515 : max_band = 0;
2969 13515 : if ( masaIsmMode )
2970 : {
2971 20000 : while ( max_band < MASA_FREQUENCY_BANDS && MASA_band_grouping_24[max_band] < nBins )
2972 : {
2973 19200 : max_band++;
2974 : }
2975 : }
2976 : else
2977 : {
2978 152580 : while ( max_band < MAX_PARAM_ISM_NBANDS && hParamIsmDec->hParamIsm->band_grouping[max_band] < nBins )
2979 : {
2980 139865 : max_band++;
2981 : }
2982 : }
2983 :
2984 : /* Init out array */
2985 64699 : for ( slot = 0; slot < nSlots; slot++ )
2986 : {
2987 153552 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2988 : {
2989 102368 : set_zero( outSlotRe[ch][slot], CLDFB_NO_CHANNELS_MAX );
2990 102368 : set_zero( outSlotIm[ch][slot], CLDFB_NO_CHANNELS_MAX );
2991 : }
2992 : }
2993 :
2994 : /* Perform the processing in frequency bands */
2995 172580 : for ( band_idx = 0; band_idx < max_band; band_idx++ )
2996 : {
2997 159065 : ratioAccOrig = 0.0f;
2998 159065 : ratioAccNew = 0.0f;
2999 159065 : ismRatioAcc = 0.0f;
3000 :
3001 159065 : set_zero( subframeEneCh, 2 );
3002 159065 : set_zero( ismPreprocMtxNew[0], 2 );
3003 159065 : set_zero( ismPreprocMtxNew[1], 2 );
3004 159065 : set_zero( eneMove, 2 );
3005 159065 : set_zero( enePreserve, 2 );
3006 159065 : if ( masaIsmMode )
3007 : {
3008 19200 : bin_lo = MASA_band_grouping_24[band_idx];
3009 19200 : bin_hi = min( MASA_band_grouping_24[band_idx + 1], nBins );
3010 : }
3011 : else
3012 : {
3013 139865 : bin_lo = hParamIsmDec->hParamIsm->band_grouping[band_idx];
3014 139865 : bin_hi = min( hParamIsmDec->hParamIsm->band_grouping[band_idx + 1], nBins );
3015 : }
3016 :
3017 : /* Determine transport normalized energies and subframe energy */
3018 763689 : for ( slot = 0; slot < nSlots; slot++ )
3019 : {
3020 1813872 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3021 : {
3022 7351328 : for ( bin = bin_lo; bin < bin_hi; bin++ )
3023 : {
3024 6142080 : subframeEneCh[ch] += inRe[ch][slot][bin] * inRe[ch][slot][bin];
3025 6142080 : subframeEneCh[ch] += inIm[ch][slot][bin] * inIm[ch][slot][bin];
3026 : }
3027 : }
3028 : }
3029 159065 : subframeEne = subframeEneCh[0] + subframeEneCh[1];
3030 159065 : totalTargetEneCh[0] = subframeEneCh[0];
3031 159065 : totalTargetEneCh[1] = subframeEneCh[1];
3032 159065 : masaEneThisCh[0] = subframeEneCh[0];
3033 159065 : masaEneThisCh[1] = subframeEneCh[1];
3034 :
3035 : /* Gain editing */
3036 : /* For each object, estimate new target energy per channel based on the applied gain */
3037 785725 : for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
3038 : {
3039 626660 : ratio = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin_lo];
3040 626660 : ratioAccOrig += ratio;
3041 :
3042 : /* Calculate MASA energy as a residual of original channel energies subtracted with ISM energies */
3043 1879980 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3044 : {
3045 1253320 : masaEneThisCh[ch] -= panEnesIn[ismDirIndex][ch] * ratio * subframeEne;
3046 : }
3047 :
3048 : /* Calculate target energy, gained ratio for accumulation, and transports gains, if ism gain is edited */
3049 626660 : if ( ismGainEdited[ismDirIndex] )
3050 : {
3051 588998 : gainIsmThis = hMasaIsmData->gain_ism_edited[ismDirIndex];
3052 : /* ISM original energy */
3053 588998 : ismEneThis = ratio * subframeEne;
3054 :
3055 : /* ISM target energy */
3056 588998 : ismTargetEneThis = ( gainIsmThis * gainIsmThis ) * ismEneThis;
3057 :
3058 588998 : ratio *= gainIsmThis * gainIsmThis;
3059 :
3060 : /* Determine panning energies and channel target energies */
3061 1766994 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3062 : {
3063 1177996 : ismTargetEneThisCh[ch] = panEnesIn[ismDirIndex][ch] * ismTargetEneThis; /* Ism target energy per channel */
3064 1177996 : totalTargetEneCh[ch] -= panEnesIn[ismDirIndex][ch] * ismEneThis; /* Reduce original ism energy */
3065 1177996 : totalTargetEneCh[ch] += ismTargetEneThisCh[ch]; /* Add ism target energy per channel */
3066 : }
3067 :
3068 : /* If separated ism edited, apply gain directly to the separated ism */
3069 588998 : if ( ismDirIndex == hMasaIsmData->idx_separated_ism )
3070 : {
3071 : /* Separated object gaining is done elsewhere with DIRAC renderer */
3072 18624 : if ( st_ivas->renderer_type != RENDERER_DIRAC )
3073 : {
3074 : /* Gain transport channel of separated ism */
3075 93120 : for ( slot = 0; slot < nSlots; slot++ )
3076 : {
3077 260736 : for ( bin = bin_lo; bin < bin_hi; bin++ )
3078 : {
3079 186240 : inRe[2][slot][bin] = gainIsmThis * inRe[2][slot][bin];
3080 186240 : inIm[2][slot][bin] = gainIsmThis * inIm[2][slot][bin];
3081 : }
3082 : }
3083 : }
3084 : }
3085 : }
3086 626660 : ratioAccNew += ratio;
3087 : }
3088 :
3089 159065 : if ( masaIsmMode )
3090 : {
3091 : /* MASA original ratios */
3092 19200 : ratio = hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin_lo] + hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin_lo];
3093 19200 : ratioAccOrig += ratio;
3094 :
3095 : /* Estimate MASA original energies and determine adjusted target energies and gained ratio for accumulation, if a gain is applied to MASA */
3096 19200 : if ( masaGainEdited )
3097 : {
3098 : /* Gained MASA ratio */
3099 19008 : ratio *= gainMasaPow2;
3100 :
3101 : /* Calculate MASA target energies and add to total target energy estimation */
3102 57024 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3103 : {
3104 38016 : masaEneThisCh[ch] = fmaxf( masaEneThisCh[ch], 0.0f ); /* MASA original energy per channel */
3105 38016 : masaTargetEneThisCh[ch] = gainMasaPow2 * masaEneThisCh[ch]; /* MASA target energy per channel */
3106 38016 : totalTargetEneCh[ch] -= masaEneThisCh[ch]; /* Reduce original energy per channel */
3107 38016 : totalTargetEneCh[ch] += masaTargetEneThisCh[ch]; /* Add target energy per channel */
3108 : }
3109 : }
3110 :
3111 19200 : ratioAccNew += ratio;
3112 : }
3113 :
3114 : /* Limit target energies to non-negative values */
3115 : #ifdef NONBE_1399_1400_FIX_OBJ_EDIT_ISSUES
3116 477195 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3117 : {
3118 318130 : totalTargetEneCh[ch] = max( totalTargetEneCh[ch], 0.0f );
3119 : }
3120 : #endif
3121 :
3122 : /* due to rounding, the sum may exceed 1.0f ever so slightly, so clip it */
3123 159065 : ratioAccOrig = min( ratioAccOrig, 1.0f );
3124 159065 : if ( masaGainEdited )
3125 : {
3126 19008 : ratioAccNew += gainMasaPow2 * ( 1.0f - ratioAccOrig );
3127 : }
3128 : else
3129 : {
3130 140057 : ratioAccNew += ( 1.0f - ratioAccOrig );
3131 : }
3132 :
3133 159065 : ratioAccNewDivisor = 1.0f / fmaxf( 1e-12f, ratioAccNew ); /* New target total energy ratio divider */
3134 :
3135 : /* Determine and process object energy ratios based on gaining */
3136 785725 : for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
3137 : {
3138 626660 : newRatios[ismDirIndex + 2] = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin_lo]; /* Determine original object energy ratio */
3139 626660 : if ( ismGainEdited[ismDirIndex] )
3140 : {
3141 588998 : gainIsmThis = hMasaIsmData->gain_ism_edited[ismDirIndex];
3142 588998 : newRatios[ismDirIndex + 2] *= ( gainIsmThis * gainIsmThis ); /* Gain original object energy ratio, if edited */
3143 : }
3144 626660 : newRatios[ismDirIndex + 2] *= ratioAccNewDivisor; /* Divide with new target total ratio */
3145 : }
3146 :
3147 : /* Determine and process MASA energy ratios based on gaining */
3148 159065 : newRatios[0] = hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin_lo];
3149 159065 : newRatios[1] = hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin_lo];
3150 159065 : if ( masaGainEdited )
3151 : {
3152 19008 : newRatios[0] *= gainMasaPow2;
3153 19008 : newRatios[1] *= gainMasaPow2;
3154 : }
3155 159065 : newRatios[0] *= ratioAccNewDivisor;
3156 159065 : newRatios[1] *= ratioAccNewDivisor;
3157 :
3158 : /* Set adjusted energy ratios */
3159 969965 : for ( bin = bin_lo; bin < bin_hi; bin++ )
3160 : {
3161 4030500 : for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
3162 : {
3163 3219600 : hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin] = newRatios[ismDirIndex + 2];
3164 : }
3165 810900 : hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin] = newRatios[0];
3166 810900 : hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin] = newRatios[1];
3167 : }
3168 :
3169 : /* Direction editing */
3170 : /* Determine new energetic values after gaining */
3171 159065 : totalTargetEne = totalTargetEneCh[0] + totalTargetEneCh[1];
3172 159065 : tempDivisor = 1.0f / fmaxf( 1e-12f, totalTargetEne );
3173 159065 : normEnes[0] = totalTargetEneCh[0] * tempDivisor;
3174 159065 : normEnes[1] = totalTargetEneCh[1] * tempDivisor;
3175 :
3176 : /* For each ismDir, determine moved and preserve energy ratio per channel */
3177 785725 : for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
3178 : {
3179 626660 : ratio = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin_lo];
3180 :
3181 626660 : ismRatioAcc += ratio;
3182 :
3183 626660 : if ( enableCentering )
3184 : {
3185 626660 : centeringFactor = fmaxf( 0.0f, 2.0f * fabsf( panEnesIn[ismDirIndex][0] - panEnesOut[ismDirIndex][0] ) - 1.0f );
3186 1879980 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3187 : {
3188 1253320 : panEnesOut[ismDirIndex][ch] *= ( 1.0f - centeringFactor );
3189 1253320 : panEnesOut[ismDirIndex][ch] += 0.5f * centeringFactor;
3190 : }
3191 : }
3192 :
3193 1879980 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3194 : {
3195 1253320 : eneMoveThis = fmaxf( 0.0f, panEnesIn[ismDirIndex][ch] - panEnesOut[ismDirIndex][ch] );
3196 1253320 : enePreserveThis = panEnesIn[ismDirIndex][ch] - eneMoveThis;
3197 :
3198 1253320 : eneMove[ch] += ratio * eneMoveThis;
3199 1253320 : enePreserve[ch] += ratio * enePreserveThis;
3200 :
3201 : /* Subtract object parts from normEnes */
3202 1253320 : normEnes[ch] -= panEnesIn[ismDirIndex][ch] * ratio;
3203 : }
3204 : }
3205 :
3206 : /* Any remaining (non-object) energy is set to be preserved at both channels */
3207 159065 : remainderNormEne = fmaxf( 0.0f, ( 1.0f - ismRatioAcc ) - normEnes[0] - normEnes[1] );
3208 :
3209 : /* Normalize */
3210 477195 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3211 : {
3212 318130 : enePreserve[ch] += fmaxf( 0.0f, normEnes[ch] + remainderNormEne / 2.0f );
3213 318130 : normVal = 1.0f / fmaxf( EPSILON, eneMove[ch] + enePreserve[ch] );
3214 318130 : normVal *= fminf( 10.0f, totalTargetEneCh[ch] / fmaxf( EPSILON, subframeEneCh[ch] ) );
3215 318130 : eneMove[ch] *= normVal;
3216 318130 : enePreserve[ch] *= normVal;
3217 : }
3218 :
3219 : /* Temporally average target energy */
3220 159065 : hMasaIsmData->eneOrigIIR[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
3221 159065 : hMasaIsmData->eneOrigIIR[band_idx] += totalTargetEne;
3222 :
3223 : /* Temporally average energy moving and preserving, and generate the transport signal preprocessing matrix for
3224 : * gaining objects and moving objects between left and right */
3225 477195 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3226 : {
3227 318130 : hMasaIsmData->eneMoveIIR[ch][band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
3228 318130 : hMasaIsmData->eneMoveIIR[ch][band_idx] += eneMove[ch] * totalTargetEne;
3229 318130 : hMasaIsmData->enePreserveIIR[ch][band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
3230 318130 : hMasaIsmData->enePreserveIIR[ch][band_idx] += enePreserve[ch] * totalTargetEne;
3231 318130 : normVal = 1.0f / fmaxf( EPSILON, hMasaIsmData->eneOrigIIR[band_idx] );
3232 318130 : ismPreprocMtxNew[ch][ch] = fminf( 4.0f, sqrtf( hMasaIsmData->enePreserveIIR[ch][band_idx] * normVal ) );
3233 318130 : ismPreprocMtxNew[1 - ch][ch] = fminf( 4.0f, sqrtf( hMasaIsmData->eneMoveIIR[ch][band_idx] * normVal ) );
3234 : }
3235 :
3236 : /* Get increment value for temporal interpolation */
3237 477195 : for ( inCh = 0; inCh < BINAURAL_CHANNELS; inCh++ )
3238 : {
3239 954390 : for ( outCh = 0; outCh < BINAURAL_CHANNELS; outCh++ )
3240 : {
3241 636260 : ismPreprocMtxIncrement[outCh][inCh] = ( ismPreprocMtxNew[outCh][inCh] - hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx] ) * nSlotDiv;
3242 : }
3243 : }
3244 :
3245 : /* Mix signals */
3246 159065 : hMasaIsmData->preprocEneTarget[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
3247 159065 : hMasaIsmData->preprocEneRealized[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
3248 159065 : hMasaIsmData->preprocEneTarget[band_idx] += totalTargetEne;
3249 :
3250 477195 : for ( outCh = 0; outCh < BINAURAL_CHANNELS; outCh++ )
3251 : {
3252 1527378 : for ( slot = 0; slot < nSlots; slot++ )
3253 : {
3254 3627744 : for ( inCh = 0; inCh < BINAURAL_CHANNELS; inCh++ )
3255 : {
3256 2418496 : hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx] += ismPreprocMtxIncrement[outCh][inCh];
3257 14702656 : for ( bin = bin_lo; bin < bin_hi; bin++ )
3258 : {
3259 12284160 : outSlotRe[outCh][slot][bin] += inRe[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx];
3260 12284160 : outSlotIm[outCh][slot][bin] += inIm[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx];
3261 : }
3262 : }
3263 :
3264 7351328 : for ( bin = bin_lo; bin < bin_hi; bin++ )
3265 : {
3266 6142080 : hMasaIsmData->preprocEneRealized[band_idx] += ( outSlotRe[outCh][slot][bin] * outSlotRe[outCh][slot][bin] ) + ( outSlotIm[outCh][slot][bin] * outSlotIm[outCh][slot][bin] );
3267 : }
3268 : }
3269 : }
3270 :
3271 159065 : eqVal = fminf( 4.0f, sqrtf( hMasaIsmData->preprocEneTarget[band_idx] / fmaxf( 1e-12f, hMasaIsmData->preprocEneRealized[band_idx] ) ) );
3272 :
3273 477195 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3274 : {
3275 1527378 : for ( slot = 0; slot < nSlots; slot++ )
3276 : {
3277 7351328 : for ( bin = bin_lo; bin < bin_hi; bin++ )
3278 : {
3279 6142080 : inRe[ch][slot][bin] = outSlotRe[ch][slot][bin] * eqVal;
3280 6142080 : inIm[ch][slot][bin] = outSlotIm[ch][slot][bin] * eqVal;
3281 : }
3282 : }
3283 : }
3284 : }
3285 :
3286 13515 : if ( !masaIsmMode )
3287 : {
3288 : int16_t obj_idx1, obj_idx2;
3289 :
3290 152580 : for ( band_idx = 0; band_idx < hParamIsmDec->hParamIsm->nbands; band_idx++ )
3291 : {
3292 139865 : bin_lo = hParamIsmDec->hParamIsm->band_grouping[band_idx];
3293 139865 : bin_hi = hParamIsmDec->hParamIsm->band_grouping[band_idx + 1];
3294 :
3295 139865 : obj_idx1 = hParamIsmDec->hParamIsm->obj_indices[band_idx][0][0];
3296 139865 : obj_idx2 = hParamIsmDec->hParamIsm->obj_indices[band_idx][0][1];
3297 :
3298 902765 : for ( bin = bin_lo; bin < bin_hi; bin++ )
3299 : {
3300 762900 : hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin] = hMasaIsmData->energy_ratio_ism[obj_idx1][dirac_read_idx][bin];
3301 762900 : hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin] = hMasaIsmData->energy_ratio_ism[obj_idx2][dirac_read_idx][bin];
3302 : }
3303 : }
3304 : }
3305 : }
3306 :
3307 13515 : return;
3308 : }
3309 :
3310 :
3311 7230 : static void ivas_masa_ext_rend_parambin_internal(
3312 : MASA_EXT_REND_HANDLE hMasaExtRend,
3313 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,
3314 : float *output_f[],
3315 : const int16_t subframe,
3316 : const SPLIT_REND_WRAPPER *hSplitRendWrapper,
3317 : float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
3318 : float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] )
3319 : {
3320 : DIRAC_DEC_BIN_HANDLE hDiracDecBin;
3321 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
3322 : PARAMBIN_REND_CONFIG config_data;
3323 : int16_t slot, ch, numInChannels;
3324 : float Cldfb_RealBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3325 : float Cldfb_ImagBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3326 : float Rmat[3][3];
3327 : int16_t max_band_decorr;
3328 : int16_t nBins;
3329 : int16_t i, j;
3330 : int16_t nchan_transport;
3331 :
3332 : int16_t pos_idx;
3333 : const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
3334 : float tmp_Cldfb_out_re[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3335 : float tmp_Cldfb_out_im[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3336 :
3337 : /* these allow re-using the reverb and freq-domain decorrelator signals from ivas_dirac_dec_binaural_process_output() in split rendering for the side renderings */
3338 : float reverbRe[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3339 : float reverbIm[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3340 : float decorrRe[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3341 : float decorrIm[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3342 : float subFrameTotalEne[CLDFB_NO_CHANNELS_MAX];
3343 : float IIReneLimiter[CLDFB_NO_CHANNELS_MAX];
3344 :
3345 7230 : hDiracDecBin = hMasaExtRend->hDiracDecBin[0];
3346 7230 : assert( hDiracDecBin );
3347 7230 : hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom;
3348 7230 : nBins = hSpatParamRendCom->num_freq_bands;
3349 :
3350 : /* Setup internal config. MASA EXT renderer is quite strict. */
3351 7230 : config_data.separateCenterChannelRendering = 0;
3352 7230 : config_data.ivas_format = MASA_FORMAT;
3353 7230 : config_data.mc_mode = MC_MODE_NONE;
3354 7230 : config_data.ivas_total_brate = IVAS_512k; /* Maximum bitrate set for external renderer */
3355 7230 : config_data.nchan_transport = hMasaExtRend->nchan_input;
3356 7230 : config_data.qualityBasedSmFactor = 1.0f;
3357 7230 : config_data.processReverb = hMasaExtRend->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ? 1 : 0;
3358 7230 : config_data.ism_mode = ISM_MODE_NONE;
3359 :
3360 : /* Set nchan_transport to number of transport channels in MASA input */
3361 7230 : nchan_transport = hMasaExtRend->nchan_input;
3362 :
3363 : /* The input channel number at this processing function (not nchan_transport) */
3364 7230 : numInChannels = BINAURAL_CHANNELS;
3365 :
3366 7230 : Rmat[0][0] = 1.0f;
3367 7230 : Rmat[0][1] = 0.0f;
3368 7230 : Rmat[0][2] = 0.0f;
3369 :
3370 7230 : Rmat[1][0] = 0.0f;
3371 7230 : Rmat[1][1] = 1.0f;
3372 7230 : Rmat[1][2] = 0.0f;
3373 :
3374 7230 : Rmat[2][0] = 0.0f;
3375 7230 : Rmat[2][1] = 0.0f;
3376 7230 : Rmat[2][2] = 1.0f;
3377 :
3378 : /* CLDFB Analysis of input */
3379 36150 : for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
3380 : {
3381 86760 : for ( ch = 0; ch < numInChannels; ch++ )
3382 : {
3383 57840 : if ( ch == 0 || nchan_transport == 2 )
3384 : {
3385 43380 : cldfbAnalysis_ts(
3386 43380 : &( output_f[ch][nBins * slot] ),
3387 43380 : Cldfb_RealBuffer_in[ch][slot],
3388 43380 : Cldfb_ImagBuffer_in[ch][slot],
3389 : nBins, hMasaExtRend->cldfbAnaRend[ch] );
3390 : }
3391 : else /* when nchan_transport == 1 and ch == 1 */
3392 : {
3393 : /* At mono input duplicate the channel to dual-mono, and apply gain
3394 : correction to ensure same overall level as in stereo mode */
3395 14460 : v_multc( Cldfb_RealBuffer_in[0][slot], INV_SQRT_2, Cldfb_RealBuffer_in[0][slot], nBins );
3396 14460 : v_multc( Cldfb_ImagBuffer_in[0][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[0][slot], nBins );
3397 :
3398 14460 : mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins );
3399 14460 : mvr2r( Cldfb_ImagBuffer_in[0][slot], Cldfb_ImagBuffer_in[1][slot], nBins );
3400 : }
3401 : }
3402 : }
3403 :
3404 7230 : if ( hCombinedOrientationData )
3405 : {
3406 9640 : for ( i = 0; i < 3; i++ )
3407 : {
3408 28920 : for ( j = 0; j < 3; j++ )
3409 : {
3410 21690 : Rmat[i][j] = hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx][i][j];
3411 : }
3412 : }
3413 :
3414 2410 : if ( nchan_transport == 2 )
3415 : {
3416 : /* in case of split rendering, determine the prototype rotation based on the main direction and use the same prototypes for the offset directions */
3417 1205 : adaptTransportSignalsHeadtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat );
3418 :
3419 1205 : ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat );
3420 : }
3421 : }
3422 :
3423 :
3424 : /* Always using CLDFB decorrelation in MASA EXT renderer */
3425 7230 : max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr;
3426 :
3427 :
3428 7230 : ivas_dirac_dec_binaural_formulate_input_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe,
3429 : subFrameTotalEne, IIReneLimiter );
3430 :
3431 7230 : ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat, subframe,
3432 7230 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
3433 : subFrameTotalEne, IIReneLimiter, NULL );
3434 :
3435 7230 : ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat, subframe,
3436 7230 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0,
3437 : 0, NULL );
3438 :
3439 7230 : pMultiBinPoseData = NULL;
3440 7230 : if ( hSplitRendWrapper != NULL )
3441 : {
3442 0 : pMultiBinPoseData = &( hSplitRendWrapper->multiBinPoseData );
3443 :
3444 0 : ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
3445 0 : max_band_decorr, numInChannels, config_data.processReverb, subframe, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
3446 : reverbRe, reverbIm, decorrRe, decorrIm, 1 );
3447 :
3448 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3449 : {
3450 0 : for ( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ )
3451 : {
3452 0 : mvr2r( tmp_Cldfb_out_re[ch][i], Cldfb_Out_Real[ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
3453 0 : mvr2r( tmp_Cldfb_out_im[ch][i], Cldfb_Out_Imag[ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
3454 : }
3455 : }
3456 : }
3457 : else
3458 : {
3459 7230 : ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
3460 7230 : max_band_decorr, numInChannels, config_data.processReverb, subframe, NULL, NULL,
3461 : reverbRe, reverbIm, decorrRe, decorrIm, 1 );
3462 : }
3463 :
3464 7230 : hDiracDecBin->hDiffuseDist = NULL;
3465 :
3466 7230 : if ( pMultiBinPoseData != NULL && pMultiBinPoseData->num_poses > 1 )
3467 : {
3468 : /* quaternion-based rotation from ivas_binRenderer_internal.c:ivas_binRenderer(), but using absolute rotation instead of delta rotations */
3469 : IVAS_QUATERNION Quaternions_rot, Quaternions_abs, *Quaternions_ref;
3470 : float Rmat_local[3][3];
3471 :
3472 0 : if ( hCombinedOrientationData )
3473 : {
3474 0 : Quaternions_ref = &hCombinedOrientationData->Quaternions[0];
3475 0 : Quaternions_rot.w = -3.0f; /* signal to use Euler */
3476 0 : Quaternions_abs.w = -3.0f; /* signal to use Euler */
3477 0 : Quat2EulerDegree( *Quaternions_ref, &Quaternions_abs.z, &Quaternions_abs.y, &Quaternions_abs.x ); /*order in Quat2Euler seems to be reversed ?*/
3478 :
3479 0 : for ( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
3480 : {
3481 0 : Quaternions_rot.x = Quaternions_abs.x + pMultiBinPoseData->relative_head_poses[pos_idx][0];
3482 0 : Quaternions_rot.y = Quaternions_abs.y + pMultiBinPoseData->relative_head_poses[pos_idx][1];
3483 0 : Quaternions_rot.z = Quaternions_abs.z + pMultiBinPoseData->relative_head_poses[pos_idx][2];
3484 :
3485 0 : QuatToRotMat( Quaternions_rot, Rmat_local );
3486 :
3487 0 : hDiracDecBin = hMasaExtRend->hDiracDecBin[pos_idx];
3488 0 : assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" );
3489 :
3490 : /* re-use input covariance for the side renderings */
3491 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3492 : {
3493 0 : mvr2r( hMasaExtRend->hDiracDecBin[0]->ChEne[ch], hDiracDecBin->ChEne[ch], hSpatParamRendCom->num_freq_bands );
3494 : }
3495 0 : mvr2r( hMasaExtRend->hDiracDecBin[0]->ChCrossRe, hDiracDecBin->ChCrossRe, hSpatParamRendCom->num_freq_bands );
3496 0 : mvr2r( hMasaExtRend->hDiracDecBin[0]->ChCrossIm, hDiracDecBin->ChCrossIm, hSpatParamRendCom->num_freq_bands );
3497 :
3498 0 : ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe,
3499 0 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
3500 : subFrameTotalEne, IIReneLimiter, NULL );
3501 :
3502 0 : ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe,
3503 0 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
3504 : 0, NULL );
3505 :
3506 :
3507 : /* re-use reverb and decorr from main direction for the sides */
3508 0 : ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
3509 0 : max_band_decorr, numInChannels, config_data.processReverb, subframe, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
3510 : reverbRe, reverbIm, decorrRe, decorrIm, 0 );
3511 :
3512 : /* copy from temporary buffer to the main split rendering buffer */
3513 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3514 : {
3515 0 : for ( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ )
3516 : {
3517 0 : mvr2r( tmp_Cldfb_out_re[ch][i], Cldfb_Out_Real[pos_idx * BINAURAL_CHANNELS + ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
3518 0 : mvr2r( tmp_Cldfb_out_im[ch][i], Cldfb_Out_Imag[pos_idx * BINAURAL_CHANNELS + ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
3519 : }
3520 : }
3521 :
3522 0 : hDiracDecBin->hDiffuseDist = NULL;
3523 : }
3524 : }
3525 : }
3526 :
3527 : /* update this counter only after the last rendering of split directions */
3528 7230 : hSpatParamRendCom->slots_rendered += hSpatParamRendCom->subframe_nbslots[subframe];
3529 7230 : hSpatParamRendCom->subframes_rendered++;
3530 :
3531 7230 : return;
3532 : }
3533 :
3534 :
3535 4512 : void ivas_masa_ext_rend_parambin_render(
3536 : MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: MASA ext rend structure */
3537 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined orientation handle */
3538 : float *output_f[], /* i/o: synthesized core-coder transport channels/DirAC output */
3539 : const int16_t num_subframes, /* i : number of subframes to render */
3540 : const SPLIT_REND_WRAPPER *hSplitRendWrapper, /* i : split rendering orientation data */
3541 : float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : rendered orientations for split rend. real part of cldfb */
3542 : float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* o : rendered orientations for split rend. imag part of cldfb */
3543 : )
3544 : {
3545 : int16_t subframe;
3546 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
3547 : float *p_output[BINAURAL_CHANNELS];
3548 : int16_t ch;
3549 :
3550 4512 : hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom;
3551 :
3552 13536 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3553 : {
3554 9024 : p_output[ch] = output_f[ch];
3555 : }
3556 :
3557 4512 : hSpatParamRendCom->subframes_rendered = hSpatParamRendCom->dirac_read_idx;
3558 :
3559 11742 : for ( subframe = 0; subframe < num_subframes; subframe++ )
3560 : {
3561 7230 : int16_t n_samples_sf = hSpatParamRendCom->slot_size * CLDFB_SLOTS_PER_SUBFRAME;
3562 7230 : hSpatParamRendCom->slots_rendered = 0;
3563 :
3564 7230 : ivas_masa_ext_rend_parambin_internal( hMasaExtRend, hCombinedOrientationData, p_output, hSpatParamRendCom->dirac_read_idx, hSplitRendWrapper, Cldfb_Out_Real, Cldfb_Out_Imag );
3565 :
3566 21690 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3567 : {
3568 14460 : p_output[ch] += n_samples_sf;
3569 : }
3570 :
3571 7230 : ivas_combined_orientation_update_index( hCombinedOrientationData, n_samples_sf );
3572 :
3573 7230 : hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + 1 ) % hSpatParamRendCom->dirac_md_buffer_length;
3574 : }
3575 :
3576 4512 : return;
3577 : }
|